Hello,

Petr Hoffmann discovered glitch in 'pfctl -a "*" -sr' command when it is
recursively dumping rulesets from PF kernel module. The ruleset in kernel
got created by screw-it.sh shell script:

    #!/bin/sh

    pfctl -d
    echo 'anchor "../bar/*"\nanchor "bar/*"' |pfctl -a foo -f -
    echo pass | pfctl -f - -a foo/bar
    echo 'anchor "foo"\nanchor "bar" ' | pfctl -f -

Now if we use 'pfctl -a "*" -sr' we get output as follows:

    # pfctl -a "*" -sr
    anchor "foo" all {
      anchor "../bar/*" all {
    pfctl: DIOCGETRULES: Invalid argument
      }
      anchor "bar/*" all {
        pass all flags S/SA
      }
    }
    anchor "bar" all {
    }

The problem comes from pfctl_show_rules(), which is going to descend
to "../bar/" anchor at line 845:

 828                 case PFCTL_SHOW_RULES:
 829                         if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL))
 830                                 labels = 1;
 839                         if (pr.anchor_call[0] &&
 ...
 840                             (((p = strrchr(pr.anchor_call, '/')) ?
 841                             p[1] == '_' : pr.anchor_call[0] == '_') ||
 842                             opts & PF_OPT_RECURSE)) {
 843                                 printf(" {\n");
 844                                 pfctl_print_rule_counters(&pr.rule, opts);
 845                                 pfctl_show_rules(dev, npath, opts, format,
 846                                     pr.anchor_call, depth + 1,
 847                                     pr.rule.anchor_wildcard, -1);
 848                                 INDENT(depth, !(opts & PF_OPT_VERBOSE));
 849                                 printf("}\n");

The simplest fix here is not to allow pfctl_show_rules() to descend
to anchor specified by relative path.

patched pfctl gives output as follows:

    # ./pfctl -a "*" -sr 
    anchor "foo" all {
      anchor "../bar/*" all
      anchor "bar/*" all {
        pass all flags S/SA
      }
    }
    anchor "bar" all {
    }

OK?

thanks a lot
regards
sasha

--------8<---------------8<---------------8<------------------8<--------
diff -r d0c6296079db src/sbin/pfctl/pfctl.c
--- a/src/sbin/pfctl/pfctl.c    Mon May 30 20:12:24 2016 +0200
+++ b/src/sbin/pfctl/pfctl.c    Mon May 30 20:41:11 2016 +0200
@@ -835,11 +835,14 @@
                         * If this is an 'unnamed' brace notation anchor OR
                         * the user has explicitly requested recursion,
                         * print it recursively.
+                        *
+                        * Note: we don't descend to relative anchors.
                         */
                                if (pr.anchor_call[0] &&
                            (((p = strrchr(pr.anchor_call, '/')) ?
                            p[1] == '_' : pr.anchor_call[0] == '_') ||
-                           opts & PF_OPT_RECURSE)) {
+                           ((opts & PF_OPT_RECURSE) &&
+                           (strncmp(pr.anchor_call, "../", 3) != 0)))) {
                                printf(" {\n");
                                pfctl_print_rule_counters(&pr.rule, opts);
                                pfctl_show_rules(dev, npath, opts, format,

Reply via email to