The branch main has been updated by glebius: URL: https://cgit.FreeBSD.org/src/commit/?id=845896655815eaf339953e2aa48d79ca4539874b
commit 845896655815eaf339953e2aa48d79ca4539874b Author: Gleb Smirnoff <[email protected]> AuthorDate: 2025-12-03 23:16:33 +0000 Commit: Gleb Smirnoff <[email protected]> CommitDate: 2025-12-03 23:19:45 +0000 bpf: calculate net.bpf.stats buffer size dynamically This removed the global counter, that was updated in a racy manner. Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D53868 --- sys/net/bpf.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/sys/net/bpf.c b/sys/net/bpf.c index f5302059d5eb..aff0d3c761ad 100644 --- a/sys/net/bpf.c +++ b/sys/net/bpf.c @@ -178,7 +178,6 @@ struct bpf_dltlist32 { CK_LIST_HEAD(bpf_iflist, bpf_if); static struct bpf_iflist bpf_iflist = CK_LIST_HEAD_INITIALIZER(); static struct sx bpf_sx; /* bpf global lock */ -static int bpf_bpfd_cnt; static void bpfif_ref(struct bpf_if *); static void bpfif_rele(struct bpf_if *); @@ -760,7 +759,6 @@ bpf_attachd(struct bpf_d *d, struct bpf_if *bp) bpf_wakeup(d); BPFD_UNLOCK(d); - bpf_bpfd_cnt++; CTR3(KTR_NET, "%s: bpf_attach called by pid %d, adding to %s list", __func__, d->bd_pid, d->bd_writer ? "writer" : "active"); @@ -864,7 +862,6 @@ bpf_detachd(struct bpf_d *d, bool detached_ifp) bpf_wakeup(d); } BPFD_UNLOCK(d); - bpf_bpfd_cnt--; /* Call event handler iff d is attached */ if (error == 0) @@ -3044,7 +3041,8 @@ bpf_stats_sysctl(SYSCTL_HANDLER_ARGS) { static const struct xbpf_d zerostats; struct xbpf_d *xbdbuf, *xbd, tempstats; - int index, error; + u_int bpfd_cnt, index; + int error; struct bpf_if *bp; struct bpf_d *bd; @@ -3074,25 +3072,33 @@ bpf_stats_sysctl(SYSCTL_HANDLER_ARGS) bpf_zero_counters(); return (0); } - if (req->oldptr == NULL) - return (SYSCTL_OUT(req, 0, bpf_bpfd_cnt * sizeof(*xbd))); - if (bpf_bpfd_cnt == 0) - return (SYSCTL_OUT(req, 0, 0)); - xbdbuf = malloc(req->oldlen, M_BPF, M_WAITOK); + bpfd_cnt = 0; BPF_LOCK(); - if (req->oldlen < (bpf_bpfd_cnt * sizeof(*xbd))) { + CK_LIST_FOREACH(bp, &bpf_iflist, bif_next) { + CK_LIST_FOREACH(bd, &bp->bif_wlist, bd_next) + bpfd_cnt++; + CK_LIST_FOREACH(bd, &bp->bif_dlist, bd_next) + bpfd_cnt++; + } + if (bpfd_cnt == 0 || req->oldptr == NULL) { + BPF_UNLOCK(); + return (SYSCTL_OUT(req, 0, bpfd_cnt * sizeof(*xbd))); + } + if (req->oldlen < bpfd_cnt * sizeof(*xbd)) { BPF_UNLOCK(); - free(xbdbuf, M_BPF); return (ENOMEM); } + xbdbuf = malloc(bpfd_cnt * sizeof(*xbd), M_BPF, M_WAITOK); index = 0; CK_LIST_FOREACH(bp, &bpf_iflist, bif_next) { /* Send writers-only first */ CK_LIST_FOREACH(bd, &bp->bif_wlist, bd_next) { + MPASS(index <= bpfd_cnt); xbd = &xbdbuf[index++]; bpfstats_fill_xbpf(xbd, bd); } CK_LIST_FOREACH(bd, &bp->bif_dlist, bd_next) { + MPASS(index <= bpfd_cnt); xbd = &xbdbuf[index++]; bpfstats_fill_xbpf(xbd, bd); }
