git: 7d0f8cd93bce - main - pf: ensure that we won't enter an endless loop
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 10 Oct 2024 12:37:15 UTC
The branch main has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=7d0f8cd93bce786728a1fff8b2e2184c8e48f3b2 commit 7d0f8cd93bce786728a1fff8b2e2184c8e48f3b2 Author: Kristof Provost <kp@FreeBSD.org> AuthorDate: 2024-09-26 15:53:53 +0000 Commit: Kristof Provost <kp@FreeBSD.org> CommitDate: 2024-10-10 12:10:39 +0000 pf: ensure that we won't enter an endless loop ensure that we won't enter an endless loop while iterating over an address pool. problem found and solution tested by claudio. ok claudio, henning, "reads fine" to zinke Obtained from: OpenBSD, mikeb <mikeb@openbsd.org>, e4fc4bddb9 Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D46927 --- sys/netpfil/pf/pf_table.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/sys/netpfil/pf/pf_table.c b/sys/netpfil/pf/pf_table.c index 690cb6d9ab90..77bd466ec2b3 100644 --- a/sys/netpfil/pf/pf_table.c +++ b/sys/netpfil/pf/pf_table.c @@ -2245,7 +2245,7 @@ pfr_pool_get(struct pfr_ktable *kt, int *pidx, struct pf_addr *counter, struct pf_addr addr, cur, mask, umask_addr; union sockaddr_union uaddr, umask; struct pfr_kentry *ke, *ke2 = NULL; - int idx = -1, use_counter = 0; + int startidx, idx = -1, loop = 0, use_counter = 0; MPASS(pidx != NULL); MPASS(counter != NULL); @@ -2272,18 +2272,29 @@ pfr_pool_get(struct pfr_ktable *kt, int *pidx, struct pf_addr *counter, use_counter = 1; if (idx < 0) idx = 0; + startidx = idx; _next_block: - ke = pfr_kentry_byidx(kt, idx, af); - if (ke == NULL) { + if (loop && startidx == idx) { pfr_kstate_counter_add(&kt->pfrkt_nomatch, 1); return (1); } + + ke = pfr_kentry_byidx(kt, idx, af); + if (ke == NULL) { + /* we don't have this idx, try looping */ + if (loop || (ke = pfr_kentry_byidx(kt, 0, af)) == NULL) { + pfr_kstate_counter_add(&kt->pfrkt_nomatch, 1); + return (1); + } + idx = 0; + loop++; + } pfr_prepare_network(&umask, af, ke->pfrke_net); pfr_sockaddr_to_pf_addr(&ke->pfrke_sa, &cur); pfr_sockaddr_to_pf_addr(&umask, &mask); - if (use_counter) { + if (use_counter && !PF_AZERO(counter, af)) { /* is supplied address within block? */ if (!PF_MATCHA(0, &cur, &mask, counter, af)) { /* no, go to next block in table */