git: a373ea07650b - main - pf: fix pf_map_addr() not to cause dividing by 0

From: Kristof Provost <kp_at_FreeBSD.org>
Date: Mon, 03 Mar 2025 16:08:29 UTC
The branch main has been updated by kp:

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

commit a373ea07650b13f4d398d1341c932082bdb05d3a
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2025-02-28 14:58:15 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2025-03-03 16:07:16 +0000

    pf: fix pf_map_addr() not to cause dividing by 0
    
    This fixes problem when using table or dynamic interface addresses for
    source-hash. Also avoid calling arc4random_uniform() with upper_bound == 0.
    
    ok mikeb
    
    Obtained from:  OpenBSD, yasuoka <yasuoka@openbsd.org>, c30ec822b8
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
---
 sys/netpfil/pf/pf_lb.c | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/sys/netpfil/pf/pf_lb.c b/sys/netpfil/pf/pf_lb.c
index cb1d7af258f3..ea9fbc46af63 100644
--- a/sys/netpfil/pf/pf_lb.c
+++ b/sys/netpfil/pf/pf_lb.c
@@ -518,7 +518,10 @@ pf_map_addr(sa_family_t af, struct pf_krule *r, struct pf_addr *saddr,
 	case PF_POOL_RANDOM:
 		if (rpool->cur->addr.type == PF_ADDR_TABLE) {
 			cnt = rpool->cur->addr.p.tbl->pfrkt_cnt;
-			rpool->tblidx = (int)arc4random_uniform(cnt);
+			if (cnt == 0)
+				rpool->tblidx = 0;
+			else
+				rpool->tblidx = (int)arc4random_uniform(cnt);
 			memset(&rpool->counter, 0, sizeof(rpool->counter));
 			if (pfr_pool_get(rpool->cur->addr.p.tbl,
 			    &rpool->tblidx, &rpool->counter, af, NULL)) {
@@ -528,7 +531,10 @@ pf_map_addr(sa_family_t af, struct pf_krule *r, struct pf_addr *saddr,
 			PF_ACPY(naddr, &rpool->counter, af);
 		} else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
 			cnt = rpool->cur->addr.p.dyn->pfid_kt->pfrkt_cnt;
-			rpool->tblidx = (int)arc4random_uniform(cnt);
+			if (cnt == 0)
+				rpool->tblidx = 0;
+			else
+				rpool->tblidx = (int)arc4random_uniform(cnt);
 			memset(&rpool->counter, 0, sizeof(rpool->counter));
 			if (pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt,
 			    &rpool->tblidx, &rpool->counter, af,
@@ -583,7 +589,10 @@ pf_map_addr(sa_family_t af, struct pf_krule *r, struct pf_addr *saddr,
 		    pf_hash(saddr, (struct pf_addr *)&hash, &rpool->key, af);
 		if (rpool->cur->addr.type == PF_ADDR_TABLE) {
 			cnt = rpool->cur->addr.p.tbl->pfrkt_cnt;
-			rpool->tblidx = (int)(hashidx % cnt);
+			if (cnt == 0)
+				rpool->tblidx = 0;
+			else
+				rpool->tblidx = (int)(hashidx % cnt);
 			memset(&rpool->counter, 0, sizeof(rpool->counter));
 			if (pfr_pool_get(rpool->cur->addr.p.tbl,
 			    &rpool->tblidx, &rpool->counter, af, NULL)) {
@@ -593,7 +602,10 @@ pf_map_addr(sa_family_t af, struct pf_krule *r, struct pf_addr *saddr,
 			PF_ACPY(naddr, &rpool->counter, af);
 		} else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
 			cnt = rpool->cur->addr.p.dyn->pfid_kt->pfrkt_cnt;
-			rpool->tblidx = (int)(hashidx % cnt);
+			if (cnt == 0)
+				rpool->tblidx = 0;
+			else
+				rpool->tblidx = (int)(hashidx % cnt);
 			memset(&rpool->counter, 0, sizeof(rpool->counter));
 			if (pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt,
 			    &rpool->tblidx, &rpool->counter, af,