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,