git: c3cc26afc922 - main - pf: stricter af checks for af-to rules
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 18 Jul 2025 09:53:06 UTC
The branch main has been updated by kp:
URL: https://cgit.FreeBSD.org/src/commit/?id=c3cc26afc9226d808389bca8e939f408415b72ad
commit c3cc26afc9226d808389bca8e939f408415b72ad
Author: Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2025-07-09 14:48:06 +0000
Commit: Kristof Provost <kp@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+0ef9190e7d0195496d0d@syzkaller.appspotmail.com
OK sashan@
Obtained from: OpenBSD, bluhm <bluhm@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);