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
This commit is contained in:
parent
9c3ad5ba93
commit
c46697b9cb
@ -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 *);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user