pf: hardcoded AF_INET in pfr_pool_get breaks IPv6 tables

Renaud Allard <[email protected]>
Newsgroups gmane.os.openbsd.bugs
Message-ID <[email protected]>
pfr_pool_get() in sys/net/pf_table.c hardcodes AF_INET at the
_next_entry label (line 2773) where it should use the af parameter:

	pfr_prepare_network(&mask, AF_INET, ke2->pfrke_net);

For IPv6, this fills the wrong struct member (sin.sin_addr instead
of sin6.sin6_addr), producing an all-zeros mask.  The nested block
skip fails: the pool wraps instead of advancing.  When pfrke_net
is > 32 the shift count goes negative (UB).  Every other call to
pfr_prepare_network in the file uses the correct af.

Tested on OpenBSD 7.9-beta amd64 with a /126 table containing a
nested /128, nat-to round-robin, 8 connections.  Stock kernel
never reaches the 4th address.  Patched kernel uses all four.

Index: sys/net/pf_table.c
===================================================================
--- sys/net/pf_table.c
+++ sys/net/pf_table.c
@@ -2770,7 +2770,7 @@ pfr_pool_get(struct pf_pool *rpool, stru
 		}
 _next_entry:
 		/* we need to increase the counter past the nested block */
-		pfr_prepare_network(&mask, AF_INET, ke2->pfrke_net);
+		pfr_prepare_network(&mask, af, ke2->pfrke_net);
 		pf_poolmask(addr, addr, SUNION2PF(&mask, af), &pfr_ffaddr, af);
 		pf_addr_inc(addr, af);
 		if (!pf_match_addr(0, *raddr, *rmask, addr, af)) {
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.