svn commit: r340762 - releng/12.0/sys/compat/linux

Tijl Coosemans tijl at FreeBSD.org
Thu Nov 22 13:12:18 UTC 2018


Author: tijl
Date: Thu Nov 22 13:12:17 2018
New Revision: 340762
URL: https://svnweb.freebsd.org/changeset/base/340762

Log:
  MFS r340757:
  
  Fix another user address dereference in linux_sendmsg syscall.
  
  This was hidden behind the LINUX_CMSG_NXTHDR macro which dereferences its
  second argument.  Stop using the macro as well as LINUX_CMSG_FIRSTHDR.  Use
  the size field of the kernel copy of the control message header to obtain
  the next control message.
  
  PR:		217901
  Approved by:	re (marius)

Modified:
  releng/12.0/sys/compat/linux/linux_socket.c
Directory Properties:
  releng/12.0/   (props changed)

Modified: releng/12.0/sys/compat/linux/linux_socket.c
==============================================================================
--- releng/12.0/sys/compat/linux/linux_socket.c	Thu Nov 22 13:09:42 2018	(r340761)
+++ releng/12.0/sys/compat/linux/linux_socket.c	Thu Nov 22 13:12:17 2018	(r340762)
@@ -1096,6 +1096,7 @@ linux_sendmsg_common(struct thread *td, l_int s, struc
 	sa_family_t sa_family;
 	void *data;
 	l_size_t len;
+	l_size_t clen;
 	int error;
 
 	error = copyin(msghdr, &linux_msg, sizeof(linux_msg));
@@ -1127,7 +1128,7 @@ linux_sendmsg_common(struct thread *td, l_int s, struc
 
 	control = NULL;
 
-	if ((ptr_cmsg = LINUX_CMSG_FIRSTHDR(&linux_msg)) != NULL) {
+	if (linux_msg.msg_controllen >= sizeof(struct l_cmsghdr)) {
 		error = kern_getsockname(td, s, &sa, &datalen);
 		if (error != 0)
 			goto bad;
@@ -1140,6 +1141,8 @@ linux_sendmsg_common(struct thread *td, l_int s, struc
 		data = mtod(control, void *);
 		datalen = 0;
 
+		ptr_cmsg = PTRIN(linux_msg.msg_control);
+		clen = linux_msg.msg_controllen;
 		do {
 			error = copyin(ptr_cmsg, &linux_cmsg,
 			    sizeof(struct l_cmsghdr));
@@ -1147,7 +1150,8 @@ linux_sendmsg_common(struct thread *td, l_int s, struc
 				goto bad;
 
 			error = EINVAL;
-			if (linux_cmsg.cmsg_len < sizeof(struct l_cmsghdr))
+			if (linux_cmsg.cmsg_len < sizeof(struct l_cmsghdr) ||
+			    linux_cmsg.cmsg_len > clen)
 				goto bad;
 
 			if (datalen + CMSG_HDRSZ > MCLBYTES)
@@ -1199,7 +1203,14 @@ linux_sendmsg_common(struct thread *td, l_int s, struc
 			cmsg->cmsg_len = CMSG_LEN(len);
 			data = (char *)data + CMSG_SPACE(len);
 			datalen += CMSG_SPACE(len);
-		} while ((ptr_cmsg = LINUX_CMSG_NXTHDR(&linux_msg, ptr_cmsg)));
+
+			if (clen <= LINUX_CMSG_ALIGN(linux_cmsg.cmsg_len))
+				break;
+
+			clen -= LINUX_CMSG_ALIGN(linux_cmsg.cmsg_len);
+			ptr_cmsg = (struct l_cmsghdr *)((char *)ptr_cmsg +
+			    LINUX_CMSG_ALIGN(linux_cmsg.cmsg_len));
+		} while(clen >= sizeof(struct l_cmsghdr));
 
 		control->m_len = datalen;
 		if (datalen == 0) {


More information about the svn-src-all mailing list