On Fri, Nov 24, 2017 at 02:58:48PM +0100, Alexandr Nedvedicky wrote:
> this diff is part of the 'big patch' [1] to pfctl I've sent while back. The
> pfctl fails to handle nested 'load anchor' statements properly, when ruleset
> is
> being loaded to non-root anchor (e.g. pfctl -a regress ...), see [1] to find
> more details about the issue.
>
> Also I'm piggy backing yet another fix to 'name vs. path'. the bug occurs on
> parse.y, where we handle 'load anchor'. I've just spotted this problem, when
> I was hunting down the problem with '-a'.
>
> OK?
OK bluhm@
> --------8<---------------8<---------------8<------------------8<--------
> diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
> index e1dcfbc382f..1016c909ccc 100644
> --- a/sbin/pfctl/parse.y
> +++ b/sbin/pfctl/parse.y
> @@ -939,7 +939,7 @@ anchorrule : ANCHOR anchorname dir quick interface
> af proto fromto
> loadrule : LOAD ANCHOR string FROM string {
> struct loadanchors *loadanchor;
>
> - if (strlen(pf->anchor->name) + 1 +
> + if (strlen(pf->anchor->path) + 1 +
> strlen($3) >= PATH_MAX) {
> yyerror("anchorname %s too long, max %u\n",
> $3, PATH_MAX - 1);
> @@ -954,7 +954,7 @@ loadrule : LOAD ANCHOR string FROM string {
> err(1, "loadrule: malloc");
> if (pf->anchor->name[0])
> snprintf(loadanchor->anchorname, PATH_MAX,
> - "%s/%s", pf->anchor->name, $3);
> + "%s/%s", pf->anchor->path, $3);
> else
> strlcpy(loadanchor->anchorname, $3, PATH_MAX);
> if ((loadanchor->filename = strdup($5)) == NULL)
> diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
> index d6cfc132c0e..044e8767bae 100644
> --- a/sbin/pfctl/pfctl.c
> +++ b/sbin/pfctl/pfctl.c
> @@ -1658,20 +1658,21 @@ pfctl_rules(int dev, char *filename, int opts, int
> optimize,
> free(path);
> path = NULL;
>
> - /* process "load anchor" directives that might have used queues */
> - if (!anchorname[0]) {
> + if (trans == NULL) {
> + /*
> + * process "load anchor" directives that might have used queues
> + */
> if (pfctl_load_anchors(dev, &pf, t) == -1)
> ERRX("load anchors");
> pfctl_clear_queues(&qspecs);
> pfctl_clear_queues(&rootqs);
> - }
>
> - if (trans == NULL && (opts & PF_OPT_NOACTION) == 0) {
> - if (!anchorname[0])
> - if (pfctl_load_options(&pf))
> + if ((opts & PF_OPT_NOACTION) == 0) {
> + if (!anchorname[0] && pfctl_load_options(&pf))
> goto _error;
> - if (pfctl_trans(dev, t, DIOCXCOMMIT, osize))
> - ERR("DIOCXCOMMIT");
> + if (pfctl_trans(dev, t, DIOCXCOMMIT, osize))
> + ERR("DIOCXCOMMIT");
> + }
> }
> return (0);
>