svn commit: r340674 - head/sys/compat/linux

Tijl Coosemans tijl at FreeBSD.org
Tue Nov 20 14:18:58 UTC 2018


Author: tijl
Date: Tue Nov 20 14:18:57 2018
New Revision: 340674
URL: https://svnweb.freebsd.org/changeset/base/340674

Log:
  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
  MFC after:	2 days
  X-MFC-With:	r340631

Modified:
  head/sys/compat/linux/linux_socket.c

Modified: head/sys/compat/linux/linux_socket.c
==============================================================================
--- head/sys/compat/linux/linux_socket.c	Tue Nov 20 11:23:33 2018	(r340673)
+++ head/sys/compat/linux/linux_socket.c	Tue Nov 20 14:18:57 2018	(r340674)
@@ -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-head mailing list