My earlier commit [1.1169 of pf.c (2023/01/05)] makes pf(4) to report wrong
authorsashan <sashan@openbsd.org>
Fri, 21 Jun 2024 12:51:29 +0000 (12:51 +0000)
committersashan <sashan@openbsd.org>
Fri, 21 Jun 2024 12:51:29 +0000 (12:51 +0000)
rule and anchor number when packet matches rule found and anchor depth 2
and more.  The issue has been noticed and reported by Giannis Kapetanakis
(billias _at_ edu.physics.uoc.gr), who also co-developed and tested
the final fix presented in this commit.

To fix the issue pf(4) must also remember the anchor where matching rule
belongs while rules are traversed to find a match for given packet.
The information on anchor is now kept in anchor stack frame.w

OK sthen@

sys/net/pf.c
sys/net/pfvar_priv.h

index 47ec92d..2a46228 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pf.c,v 1.1198 2024/06/20 19:25:42 bluhm Exp $ */
+/*     $OpenBSD: pf.c,v 1.1199 2024/06/21 12:51:29 sashan Exp $ */
 
 /*
  * Copyright (c) 2001 Daniel Hartmeier
@@ -3666,8 +3666,8 @@ pf_anchor_stack_top(void)
 }
 
 int
-pf_anchor_stack_push(struct pf_ruleset *rs, struct pf_rule *r,
-    struct pf_anchor *child, int jump_target)
+pf_anchor_stack_push(struct pf_ruleset *rs, struct pf_rule *anchor,
+    struct pf_rule *r, struct pf_anchor *child, int jump_target)
 {
        struct pf_anchor_stackframe *stack;
        struct pf_anchor_stackframe *top_sf = pf_anchor_stack_top();
@@ -3677,6 +3677,7 @@ pf_anchor_stack_push(struct pf_ruleset *rs, struct pf_rule *r,
                return (-1);
 
        top_sf->sf_rs = rs;
+       top_sf->sf_anchor = anchor;
        top_sf->sf_r = r;
        top_sf->sf_child = child;
        top_sf->sf_jump_target = jump_target;
@@ -3693,8 +3694,8 @@ pf_anchor_stack_push(struct pf_ruleset *rs, struct pf_rule *r,
 }
 
 int
-pf_anchor_stack_pop(struct pf_ruleset **rs, struct pf_rule **r,
-    struct pf_anchor **child, int *jump_target)
+pf_anchor_stack_pop(struct pf_ruleset **rs, struct pf_rule **anchor,
+    struct pf_rule **r, struct pf_anchor **child, int *jump_target)
 {
        struct pf_anchor_stackframe *top_sf = pf_anchor_stack_top();
        struct pf_anchor_stackframe *stack;
@@ -3710,6 +3711,7 @@ pf_anchor_stack_pop(struct pf_ruleset **rs, struct pf_rule **r,
                            __func__);
 
                *rs = top_sf->sf_rs;
+               *anchor = top_sf->sf_anchor;
                *r = top_sf->sf_r;
                *child = top_sf->sf_child;
                *jump_target = top_sf->sf_jump_target;
@@ -4306,25 +4308,27 @@ enter_ruleset:
                        if (r->quick)
                                return (PF_TEST_QUICK);
                } else {
-                       ctx->a = r;
                        ctx->aruleset = &r->anchor->ruleset;
                        if (r->anchor_wildcard) {
                                RB_FOREACH(child, pf_anchor_node,
                                    &r->anchor->children) {
-                                       if (pf_anchor_stack_push(ruleset, r,
-                                           child, PF_NEXT_CHILD) != 0)
+                                       if (pf_anchor_stack_push(ruleset,
+                                           ctx->a, r, child,
+                                           PF_NEXT_CHILD) != 0)
                                                return (PF_TEST_FAIL);
 
+                                       ctx->a = r;
                                        ruleset = &child->ruleset;
                                        goto enter_ruleset;
 next_child:
                                        continue;       /* with RB_FOREACH() */
                                }
                        } else {
-                               if (pf_anchor_stack_push(ruleset, r, child,
-                                   PF_NEXT_RULE) != 0)
+                               if (pf_anchor_stack_push(ruleset, ctx->a,
+                                   r, child, PF_NEXT_RULE) != 0)
                                        return (PF_TEST_FAIL);
 
+                               ctx->a = r;
                                ruleset = &r->anchor->ruleset;
                                child = NULL;
                                goto enter_ruleset;
@@ -4335,7 +4339,9 @@ next_rule:
                r = TAILQ_NEXT(r, entries);
        }
 
-       if (pf_anchor_stack_pop(&ruleset, &r, &child, &target) == 0) {
+       if (pf_anchor_stack_pop(&ruleset, &ctx->a, &r, &child,
+           &target) == 0) {
+
                /* stop if any rule matched within quick anchors. */
                if (r->quick == PF_TEST_QUICK && *ctx->am == r)
                        return (PF_TEST_QUICK);
index 7a420bf..d059357 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pfvar_priv.h,v 1.36 2024/04/22 13:30:22 bluhm Exp $   */
+/*     $OpenBSD: pfvar_priv.h,v 1.37 2024/06/21 12:51:29 sashan Exp $  */
 
 /*
  * Copyright (c) 2001 Daniel Hartmeier
@@ -321,6 +321,7 @@ struct pf_pdesc {
 
 struct pf_anchor_stackframe {
        struct pf_ruleset       *sf_rs;
+       struct pf_rule          *sf_anchor;
        union {
                struct pf_rule                  *u_r;
                struct pf_anchor_stackframe     *u_stack_top;