git: f13da24715a7 - main - net/bpf: Fix writing of buffer bigger than PAGESIZE
Kristof Provost
kp at FreeBSD.org
Fri Jul 2 09:18:44 UTC 2021
On 23 Jun 2021, at 22:35, Gleb Smirnoff wrote:
> Warner, Kristof,
>
> On Wed, Jun 23, 2021 at 04:41:01PM +0000, Warner Losh wrote:
> W> net/bpf: Fix writing of buffer bigger than PAGESIZE
> W>
> W> When allocating the mbuf we used m_get2 which fails
> W> if len is superior to MJUMPAGESIZE, if its the case,
> W> use m_getjcl instead.
> W>
> W> Reviewed by: kp@
> W> PR: 205164
> W> Pull Request: https://github.com/freebsd/freebsd-src/pull/131
>
> m_get2() used to provide jumbo mbufs in the past, see
> 3112ae76449ae0931d207603f14b083627bd731d.
>
> IMHO, makes sense to create m_get3() and use it in bpf. What do you
> think?
>
Do you mean, create an m_get3() like this (untested):
diff --git a/sys/kern/kern_mbuf.c b/sys/kern/kern_mbuf.c
index a46c576bad90..202a1c1a5b41 100644
--- a/sys/kern/kern_mbuf.c
+++ b/sys/kern/kern_mbuf.c
@@ -1370,6 +1370,51 @@ m_get2(int size, int how, short type, int flags)
return (m);
}
+/*
+ * m_get3() allocates minimum mbuf that would fit "size" argument.
+ * Unlike m_get2() is can allocate clusters up to MJUM16BYTES.
+ */
+struct mbuf *
+m_get3(int size, int how, short type, int flags)
+{
+ struct mb_args args;
+ struct mbuf *m, *n;
+ uma_zone_t zone;
+
+ args.flags = flags;
+ args.type = type;
+
+ if (size <= MHLEN || (size <= MLEN && (flags & M_PKTHDR) == 0))
+ return (uma_zalloc_arg(zone_mbuf, &args, how));
+ if (size <= MCLBYTES)
+ return (uma_zalloc_arg(zone_pack, &args, how));
+
+ if (size > MJUM16BYTES)
+ return (NULL);
+
+ m = uma_zalloc_arg(zone_mbuf, &args, how);
+ if (m == NULL)
+ return (NULL);
+
+#if MJUMPAGESIZE != MCLBYTES
+ if (size <= MJUMPAGESIZE)
+ zone = zone_jumbop;
+ else
+#endif
+ if (size <= MJUM9BYTES)
+ zone = zone_jumbo9;
+ else
+ zone = zone_jumbo16;
+
+ n = uma_zalloc_arg(zone_jumbop, m, how);
+ if (n == NULL) {
+ uma_zfree(zone_mbuf, m);
+ return (NULL);
+ }
+
+ return (m);
+}
+
/*
* m_getjcl() returns an mbuf with a cluster of the specified size
attached.
* For size it takes MCLBYTES, MJUMPAGESIZE, MJUM9BYTES, MJUM16BYTES.
diff --git a/sys/net/bpf.c b/sys/net/bpf.c
index ec05dd6d337b..ef7285241fdf 100644
--- a/sys/net/bpf.c
+++ b/sys/net/bpf.c
@@ -641,15 +641,7 @@ bpf_movein(struct uio *uio, int linktype, struct
ifnet *ifp, struct mbuf **mp,
if (len < hlen || len - hlen > ifp->if_mtu)
return (EMSGSIZE);
- /* Allocate a mbuf for our write, since m_get2 fails if len >= to
MJUMPAGESIZE, use m_getjcl for bigger buffers */
- if (len < MJUMPAGESIZE)
- m = m_get2(len, M_WAITOK, MT_DATA, M_PKTHDR);
- else if (len <= MJUM9BYTES)
- m = m_getjcl(M_WAITOK, MT_DATA, M_PKTHDR, MJUM9BYTES);
- else if (len <= MJUM16BYTES)
- m = m_getjcl(M_WAITOK, MT_DATA, M_PKTHDR, MJUM16BYTES);
- else
- m = NULL;
+ m = m_get3(len, M_WAITOK, MT_DATA, M_PKTHDR);
if (m == NULL)
return (EIO);
m->m_pkthdr.len = m->m_len = len;
diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h
index e37b872c74fe..b9211aaedc3c 100644
--- a/sys/sys/mbuf.h
+++ b/sys/sys/mbuf.h
@@ -828,6 +828,7 @@ u_int m_fixhdr(struct mbuf *);
struct mbuf *m_fragment(struct mbuf *, int, int);
void m_freem(struct mbuf *);
struct mbuf *m_get2(int, int, short, int);
+struct mbuf *m_get3(int, int, short, int);
struct mbuf *m_getjcl(int, short, int, int);
struct mbuf *m_getm2(struct mbuf *, int, int, short, int);
struct mbuf *m_getptr(struct mbuf *, int, int *);
—
Kristof
More information about the dev-commits-src-all
mailing list