The branch main has been updated by kp:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=c3cc26afc9226d808389bca8e939f408415b72ad

commit c3cc26afc9226d808389bca8e939f408415b72ad
Author:     Kristof Provost <k...@freebsd.org>
AuthorDate: 2025-07-09 14:48:06 +0000
Commit:     Kristof Provost <k...@freebsd.org>
CommitDate: 2025-07-18 07:33:29 +0000

    pf: stricter af checks for af-to rules
    
    An af-to pf rule must have an address family naf to use after
    translation.  Make stricter sanity checks in pf ioctl to avoid later
    crashes during packet processing.
    Reported-by: syzbot+0ef9190e7d0195496...@syzkaller.appspotmail.com
    OK sashan@
    
    Obtained from:  OpenBSD, bluhm <bl...@openbsd.org>, 035d4f5430
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
---
 sys/netpfil/pf/pf_ioctl.c | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
index 3caa0d2e3b11..937619977fd9 100644
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -2041,6 +2041,34 @@ pf_ioctl_getrules(struct pfioc_rule *pr)
        return (0);
 }
 
+static int
+pf_rule_checkaf(struct pf_krule *r)
+{
+       switch (r->af) {
+       case 0:
+               if (r->rule_flag & PFRULE_AFTO)
+                       return (EPFNOSUPPORT);
+               break;
+       case AF_INET:
+               if ((r->rule_flag & PFRULE_AFTO) && r->naf != AF_INET6)
+                       return (EPFNOSUPPORT);
+               break;
+#ifdef INET6
+       case AF_INET6:
+               if ((r->rule_flag & PFRULE_AFTO) && r->naf != AF_INET)
+                       return (EPFNOSUPPORT);
+               break;
+#endif /* INET6 */
+       default:
+               return (EPFNOSUPPORT);
+       }
+
+       if ((r->rule_flag & PFRULE_AFTO) == 0 && r->naf != 0)
+               return (EPFNOSUPPORT);
+
+       return (0);
+}
+
 static int
 pf_validate_range(uint8_t op, uint16_t port[2])
 {
@@ -2073,6 +2101,8 @@ pf_ioctl_addrule(struct pf_krule *rule, uint32_t ticket,
 
 #define        ERROUT(x)       ERROUT_FUNCTION(errout, x)
 
+       if ((error = pf_rule_checkaf(rule)))
+               ERROUT(error);
        if (pf_validate_range(rule->src.port_op, rule->src.port))
                ERROUT(EINVAL);
        if (pf_validate_range(rule->dst.port_op, rule->dst.port))
@@ -3741,6 +3771,10 @@ DIOCGETRULENV_error:
                                break;
                        }
 
+                       if ((error = pf_rule_checkaf(newrule))) {
+                               pf_krule_free(newrule);
+                               break;
+                       }
                        if (newrule->ifname[0])
                                kif = pf_kkif_create(M_WAITOK);
                        pf_counter_u64_init(&newrule->evaluations, M_WAITOK);

Reply via email to