git: fea1a98ead91 - main - freebsd32: Fix a double copyin in sendmsg() and recvmsg()

Mark Johnston markj at FreeBSD.org
Sun Sep 19 17:55:14 UTC 2021


The branch main has been updated by markj:

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

commit fea1a98ead918b39280b586773a923e76194400b
Author:     Mark Johnston <markj at FreeBSD.org>
AuthorDate: 2021-09-19 17:45:09 +0000
Commit:     Mark Johnston <markj at FreeBSD.org>
CommitDate: 2021-09-19 17:54:16 +0000

    freebsd32: Fix a double copyin in sendmsg() and recvmsg()
    
    freebsd32_sendmsg() and freebsd32_recvmsg() both copyin the message
    header twice, once directly and once in freebsd32_copyinmsghdr().  The
    iovec length from the former is used when copying in msg_iov, but the
    rest of the kernel uses the iovec length from the latter.  When
    kern_sendit() and kern_recvit() iterate over the iovec to compute the
    residual for I/O, they can therefore end up walking past the end of the
    copied in iovec, either resulting in a system call error, userspace
    memory corruption from uiomove() with invalid iovecs, or a kernel page
    fault if the copied-in iovec is followed by an unmapped KVA region.
    
    Reported by:    syzbot+7cc64cd0c49605acd421 at syzkaller.appspotmail.com
    Reviewed by:    kib, emaste
    MFC after:      1 week
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D32010
---
 sys/compat/freebsd32/freebsd32_misc.c | 14 +++-----------
 1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
index be942f9fafd3..08941ebc5be9 100644
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -1414,19 +1414,15 @@ int
 freebsd32_recvmsg(struct thread *td, struct freebsd32_recvmsg_args *uap)
 {
 	struct msghdr msg;
-	struct msghdr32 m32;
 	struct iovec *uiov, *iov;
 	struct mbuf *control = NULL;
 	struct mbuf **controlp;
-
 	int error;
-	error = copyin(uap->msg, &m32, sizeof(m32));
-	if (error)
-		return (error);
+
 	error = freebsd32_copyinmsghdr(uap->msg, &msg);
 	if (error)
 		return (error);
-	error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov,
+	error = freebsd32_copyiniov((void *)msg.msg_iov, msg.msg_iovlen, &iov,
 	    EMSGSIZE);
 	if (error)
 		return (error);
@@ -1559,19 +1555,15 @@ int
 freebsd32_sendmsg(struct thread *td, struct freebsd32_sendmsg_args *uap)
 {
 	struct msghdr msg;
-	struct msghdr32 m32;
 	struct iovec *iov;
 	struct mbuf *control = NULL;
 	struct sockaddr *to = NULL;
 	int error;
 
-	error = copyin(uap->msg, &m32, sizeof(m32));
-	if (error)
-		return (error);
 	error = freebsd32_copyinmsghdr(uap->msg, &msg);
 	if (error)
 		return (error);
-	error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov,
+	error = freebsd32_copyiniov((void *)msg.msg_iov, msg.msg_iovlen, &iov,
 	    EMSGSIZE);
 	if (error)
 		return (error);


More information about the dev-commits-src-all mailing list