aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrooks Davis <brooks@FreeBSD.org>2022-08-24 17:34:39 +0000
committerBrooks Davis <brooks@FreeBSD.org>2022-08-24 17:34:39 +0000
commitc46697b9cb97a14f61ac0a58758aab081b9e48c5 (patch)
treeaa4153cd8e6479c200e6a417cb6a019d02374364
parent9c3ad5ba932b5ed8d176a498155925cef69f7d62 (diff)
downloadsrc-c46697b9cb97a14f61ac0a58758aab081b9e48c5.tar.gz
src-c46697b9cb97a14f61ac0a58758aab081b9e48c5.zip
freebsd32_sendmsg: fix control message ABI
When a freebsd32 caller uses all or most allowed space for control messages (MCLBYTES == 2K) then the message may no longer fit when the messages are padded for 64-bit alignment. Historically we've just shrugged and said there is no ABI guarantee. We ran into this on CheriBSD where a capsicumized 64-bit nm would fail when called with more than 64 files. Fix this by not gratutiously capping size of mbuf data we'll allocate to MCLBYTES and let m_get2 allocate up to MJUMPAGESIZE (4K or larger). Instead of hard-coding a length check, let m_get2 do it and check for a NULL return. Reviewed by: markj, jhb, emaste Sponsored by: DARPA, AFRL Differential Revision: https://reviews.freebsd.org/D36322
-rw-r--r--sys/compat/freebsd32/freebsd32_misc.c21
1 files changed, 11 insertions, 10 deletions
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
index d1c44a4f9952..b4c212ecd38d 100644
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -1535,6 +1535,7 @@ freebsd32_copyin_control(struct mbuf **mp, caddr_t buf, u_int buflen)
u_int msglen, outlen;
int error;
+ /* Enforce the size limit of the native implementation. */
if (buflen > MCLBYTES)
return (EINVAL);
@@ -1570,20 +1571,20 @@ freebsd32_copyin_control(struct mbuf **mp, caddr_t buf, u_int buflen)
outlen += CMSG_ALIGN(sizeof(*cm)) +
CMSG_ALIGN(msglen - FREEBSD32_ALIGN(sizeof(*cm)));
}
- if (error == 0 && outlen > MCLBYTES) {
- /*
- * XXXMJ This implies that the upper limit on 32-bit aligned
- * control messages is less than MCLBYTES, and so we are not
- * perfectly compatible. However, there is no platform
- * guarantee that mbuf clusters larger than MCLBYTES can be
- * allocated.
- */
- error = EINVAL;
- }
if (error != 0)
goto out;
+ /*
+ * Allocate up to MJUMPAGESIZE space for the re-aligned and
+ * re-padded control messages. This allows a full MCLBYTES of
+ * 32-bit sized and aligned messages to fit and avoids an ABI
+ * mismatch with the native implementation.
+ */
m = m_get2(outlen, M_WAITOK, MT_CONTROL, 0);
+ if (m == NULL) {
+ error = EINVAL;
+ goto out;
+ }
m->m_len = outlen;
md = mtod(m, void *);