git: 7b673a2c73d0 - main - freebsd32: Make sendmsg match native ABI for unpadded final control message

From: Jessica Clarke <jrtc27_at_FreeBSD.org>
Date: Thu, 15 Sep 2022 16:17:03 UTC
The branch main has been updated by jrtc27:

URL: https://cgit.FreeBSD.org/src/commit/?id=7b673a2c73d0577e2c006aeb110295a522b98135

commit 7b673a2c73d0577e2c006aeb110295a522b98135
Author:     Jessica Clarke <jrtc27@FreeBSD.org>
AuthorDate: 2022-09-15 16:16:22 +0000
Commit:     Jessica Clarke <jrtc27@FreeBSD.org>
CommitDate: 2022-09-15 16:16:22 +0000

    freebsd32: Make sendmsg match native ABI for unpadded final control message
    
    The API says that CMSG_SPACE should be used for msg_controllen, but in
    practice the native ABI allows you to only use CMSG_LEN for the final
    (typically only) control message, and real-world software does this,
    including Wayland. For freebsd32, this is in practice mostly harmless,
    since control messages are generally used to carry file descriptors,
    which are already 4 bytes in size and thus no padding is needed, but
    they can carry other quantities that may not result in an aligned
    length. This was discovered after CheriBSD's freebsd64 equivalent was
    updated to match the freebsd32 implementation, as that uses 8 byte
    alignment which does break the file descriptor use case, and thus
    Wayland.
    
    This used to be addressed by aligning buflen before the first iteration,
    but that allowed unwanted invalid inputs and was lost in 1b1428dcc82b,
    with no safer equivalent put in its place.
    
    Reviewed by:    brooks, kib, markj
    Obtained from:  CheriBSD
    Fixes:          1b1428dcc82b ("Fix a TOCTOU vulnerability in freebsd32_copyin_control().")
    MFC after:      1 week
    Differential Revision:  https://reviews.freebsd.org/D36554
---
 sys/compat/freebsd32/freebsd32_misc.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
index b4c212ecd38d..a52b33a72f8a 100644
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -1556,15 +1556,19 @@ freebsd32_copyin_control(struct mbuf **mp, caddr_t buf, u_int buflen)
 			break;
 		}
 		cm = (struct cmsghdr *)in1;
-		if (cm->cmsg_len < FREEBSD32_ALIGN(sizeof(*cm))) {
+		if (cm->cmsg_len < FREEBSD32_ALIGN(sizeof(*cm)) ||
+		    cm->cmsg_len > buflen) {
 			error = EINVAL;
 			break;
 		}
 		msglen = FREEBSD32_ALIGN(cm->cmsg_len);
-		if (msglen > buflen || msglen < cm->cmsg_len) {
+		if (msglen < cm->cmsg_len) {
 			error = EINVAL;
 			break;
 		}
+		/* The native ABI permits the final padding to be omitted. */
+		if (msglen > buflen)
+			msglen = buflen;
 		buflen -= msglen;
 
 		in1 = (char *)in1 + msglen;