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,