Date: Fri, 9 Jul 2021 09:16:11 GMT From: Kristof Provost <kp@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: 3fc12ae04204 - main - pf: bound DIOCGETSTATESV2 memory use Message-ID: <202107090916.1699GBCF028658@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch main has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=3fc12ae042040192aa43984106a75663aaa9e0f5 commit 3fc12ae042040192aa43984106a75663aaa9e0f5 Author: Kristof Provost <kp@FreeBSD.org> AuthorDate: 2021-07-08 13:01:19 +0000 Commit: Kristof Provost <kp@FreeBSD.org> CommitDate: 2021-07-09 08:30:02 +0000 pf: bound DIOCGETSTATESV2 memory use Rather than allocating however much memory userspace asks for we only allocate enough for a handful of states, and copy to userspace for each completed row. We start out with enough space for 16 states (per row), but grow that as required. In most configurations we expect at most a handful of states per row (more than that would have other negative effects on packet processing performance). Reviewed by: mjg MFC after: 1 week Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D31111 --- sys/netpfil/pf/pf_ioctl.c | 48 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c index e4017f48a8ca..e0f7216ce5fc 100644 --- a/sys/netpfil/pf/pf_ioctl.c +++ b/sys/netpfil/pf/pf_ioctl.c @@ -2878,6 +2878,8 @@ DIOCGETSTATES_full: struct pf_kstate *s; struct pf_state_export *pstore, *p; int i, nr; + size_t slice_count = 16, count; + void *out; if (ps->ps_req_version > PF_STATE_VERSION) { error = ENOTSUP; @@ -2890,38 +2892,60 @@ DIOCGETSTATES_full: break; } - p = pstore = malloc(ps->ps_len, M_TEMP, M_WAITOK | M_ZERO); + out = ps->ps_states; + pstore = mallocarray(slice_count, + sizeof(struct pf_state_export), M_TEMP, M_WAITOK | M_ZERO); nr = 0; for (i = 0; i <= pf_hashmask; i++) { struct pf_idhash *ih = &V_pf_idhash[i]; +DIOCGETSTATESV2_retry: + p = pstore; + if (LIST_EMPTY(&ih->states)) continue; PF_HASHROW_LOCK(ih); + count = 0; + LIST_FOREACH(s, &ih->states, entry) { + if (s->timeout == PFTM_UNLINKED) + continue; + count++; + } + + if (count > slice_count) { + PF_HASHROW_UNLOCK(ih); + free(pstore, M_TEMP); + slice_count = count * 2; + pstore = mallocarray(slice_count, + sizeof(struct pf_state_export), M_TEMP, + M_WAITOK | M_ZERO); + goto DIOCGETSTATESV2_retry; + } + + if ((nr+count) * sizeof(*p) > ps->ps_len) { + PF_HASHROW_UNLOCK(ih); + goto DIOCGETSTATESV2_full; + } + LIST_FOREACH(s, &ih->states, entry) { if (s->timeout == PFTM_UNLINKED) continue; - if ((nr+1) * sizeof(*p) > ps->ps_len) { - PF_HASHROW_UNLOCK(ih); - goto DIOCGETSTATESV2_full; - } pf_state_export(p, s); p++; nr++; } PF_HASHROW_UNLOCK(ih); + error = copyout(pstore, out, + sizeof(struct pf_state_export) * count); + if (error) + break; + out = ps->ps_states + nr; } DIOCGETSTATESV2_full: - error = copyout(pstore, ps->ps_states, - sizeof(struct pf_state_export) * nr); - if (error) { - free(pstore, M_TEMP); - break; - } - ps->ps_len = sizeof(struct pf_state_export) * nr; + ps->ps_len = nr * sizeof(struct pf_state_export); free(pstore, M_TEMP); break;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202107090916.1699GBCF028658>