netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCHSET 0/2] Disallow ancillary data from __sys_{recv,send}msg_file()
@ 2019-11-26  1:31 Jens Axboe
  2019-11-26  1:31 ` [PATCH 1/2] net: separate out the msghdr copy from ___sys_{send,recv}msg() Jens Axboe
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Jens Axboe @ 2019-11-26  1:31 UTC (permalink / raw)
  To: netdev; +Cc: davem

io_uring currently uses __sys_sendmsg_file() and __sys_recvmsg_file() to
handle sendmsg and recvmsg operations. This generally works fine, but we
don't want to allow cmsg type operations, just "normal" data transfers.

This small patchset first splits the msghdr copy from the two main
helpers in net/socket.c, then changes __sys_sendmsg_file() and
__sys_recvmsg_file() to use those helpers. With patch 2, we also add a
check to explicitly check for msghdr->msg_control and
msghdr->msg_controllen and return -EINVAL if they are set.

 net/socket.c | 184 ++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 132 insertions(+), 52 deletions(-)

-- 
Jens Axboe



^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/2] net: separate out the msghdr copy from ___sys_{send,recv}msg()
  2019-11-26  1:31 [PATCHSET 0/2] Disallow ancillary data from __sys_{recv,send}msg_file() Jens Axboe
@ 2019-11-26  1:31 ` Jens Axboe
  2019-11-26  1:31 ` [PATCH 2/2] net: disallow ancillary data for __sys_{send,recv}msg_file() Jens Axboe
  2019-11-26 22:00 ` [PATCHSET 0/2] Disallow ancillary data from __sys_{recv,send}msg_file() David Miller
  2 siblings, 0 replies; 5+ messages in thread
From: Jens Axboe @ 2019-11-26  1:31 UTC (permalink / raw)
  To: netdev; +Cc: davem, Jens Axboe

This is in preparation for enabling the io_uring helpers for sendmsg
and recvmsg to first copy the header for validation before continuing
with the operation.

There should be no functional changes in this patch.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
---
 net/socket.c | 141 ++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 95 insertions(+), 46 deletions(-)

diff --git a/net/socket.c b/net/socket.c
index 96e44b55d3d3..da729df8f03d 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -2263,15 +2263,10 @@ static int copy_msghdr_from_user(struct msghdr *kmsg,
 	return err < 0 ? err : 0;
 }
 
-static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
-			 struct msghdr *msg_sys, unsigned int flags,
-			 struct used_address *used_address,
-			 unsigned int allowed_msghdr_flags)
+static int ____sys_sendmsg(struct socket *sock, struct msghdr *msg_sys,
+			   unsigned int flags, struct used_address *used_address,
+			   unsigned int allowed_msghdr_flags)
 {
-	struct compat_msghdr __user *msg_compat =
-	    (struct compat_msghdr __user *)msg;
-	struct sockaddr_storage address;
-	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
 	unsigned char ctl[sizeof(struct cmsghdr) + 20]
 				__aligned(sizeof(__kernel_size_t));
 	/* 20 is size of ipv6_pktinfo */
@@ -2279,19 +2274,10 @@ static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
 	int ctl_len;
 	ssize_t err;
 
-	msg_sys->msg_name = &address;
-
-	if (MSG_CMSG_COMPAT & flags)
-		err = get_compat_msghdr(msg_sys, msg_compat, NULL, &iov);
-	else
-		err = copy_msghdr_from_user(msg_sys, msg, NULL, &iov);
-	if (err < 0)
-		return err;
-
 	err = -ENOBUFS;
 
 	if (msg_sys->msg_controllen > INT_MAX)
-		goto out_freeiov;
+		goto out;
 	flags |= (msg_sys->msg_flags & allowed_msghdr_flags);
 	ctl_len = msg_sys->msg_controllen;
 	if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
@@ -2299,7 +2285,7 @@ static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
 		    cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl,
 						     sizeof(ctl));
 		if (err)
-			goto out_freeiov;
+			goto out;
 		ctl_buf = msg_sys->msg_control;
 		ctl_len = msg_sys->msg_controllen;
 	} else if (ctl_len) {
@@ -2308,7 +2294,7 @@ static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
 		if (ctl_len > sizeof(ctl)) {
 			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
 			if (ctl_buf == NULL)
-				goto out_freeiov;
+				goto out;
 		}
 		err = -EFAULT;
 		/*
@@ -2354,7 +2340,47 @@ static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
 out_freectl:
 	if (ctl_buf != ctl)
 		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
-out_freeiov:
+out:
+	return err;
+}
+
+static int sendmsg_copy_msghdr(struct msghdr *msg,
+			       struct user_msghdr __user *umsg, unsigned flags,
+			       struct iovec **iov)
+{
+	int err;
+
+	if (flags & MSG_CMSG_COMPAT) {
+		struct compat_msghdr __user *msg_compat;
+
+		msg_compat = (struct compat_msghdr __user *) umsg;
+		err = get_compat_msghdr(msg, msg_compat, NULL, iov);
+	} else {
+		err = copy_msghdr_from_user(msg, umsg, NULL, iov);
+	}
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
+			 struct msghdr *msg_sys, unsigned int flags,
+			 struct used_address *used_address,
+			 unsigned int allowed_msghdr_flags)
+{
+	struct sockaddr_storage address;
+	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
+	ssize_t err;
+
+	msg_sys->msg_name = &address;
+
+	err = sendmsg_copy_msghdr(msg_sys, msg, flags, &iov);
+	if (err < 0)
+		return err;
+
+	err = ____sys_sendmsg(sock, msg_sys, flags, used_address,
+				allowed_msghdr_flags);
 	kfree(iov);
 	return err;
 }
@@ -2473,33 +2499,41 @@ SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
 	return __sys_sendmmsg(fd, mmsg, vlen, flags, true);
 }
 
-static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg,
-			 struct msghdr *msg_sys, unsigned int flags, int nosec)
+static int recvmsg_copy_msghdr(struct msghdr *msg,
+			       struct user_msghdr __user *umsg, unsigned flags,
+			       struct sockaddr __user **uaddr,
+			       struct iovec **iov)
 {
-	struct compat_msghdr __user *msg_compat =
-	    (struct compat_msghdr __user *)msg;
-	struct iovec iovstack[UIO_FASTIOV];
-	struct iovec *iov = iovstack;
-	unsigned long cmsg_ptr;
-	int len;
 	ssize_t err;
 
-	/* kernel mode address */
-	struct sockaddr_storage addr;
-
-	/* user mode address pointers */
-	struct sockaddr __user *uaddr;
-	int __user *uaddr_len = COMPAT_NAMELEN(msg);
-
-	msg_sys->msg_name = &addr;
+	if (MSG_CMSG_COMPAT & flags) {
+		struct compat_msghdr __user *msg_compat;
 
-	if (MSG_CMSG_COMPAT & flags)
-		err = get_compat_msghdr(msg_sys, msg_compat, &uaddr, &iov);
-	else
-		err = copy_msghdr_from_user(msg_sys, msg, &uaddr, &iov);
+		msg_compat = (struct compat_msghdr __user *) umsg;
+		err = get_compat_msghdr(msg, msg_compat, uaddr, iov);
+	} else {
+		err = copy_msghdr_from_user(msg, umsg, uaddr, iov);
+	}
 	if (err < 0)
 		return err;
 
+	return 0;
+}
+
+static int ____sys_recvmsg(struct socket *sock, struct msghdr *msg_sys,
+			   struct user_msghdr __user *msg,
+			   struct sockaddr __user *uaddr,
+			   unsigned int flags, int nosec)
+{
+	struct compat_msghdr __user *msg_compat =
+					(struct compat_msghdr __user *) msg;
+	int __user *uaddr_len = COMPAT_NAMELEN(msg);
+	struct sockaddr_storage addr;
+	unsigned long cmsg_ptr;
+	int len;
+	ssize_t err;
+
+	msg_sys->msg_name = &addr;
 	cmsg_ptr = (unsigned long)msg_sys->msg_control;
 	msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
 
@@ -2510,7 +2544,7 @@ static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg,
 		flags |= MSG_DONTWAIT;
 	err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys, flags);
 	if (err < 0)
-		goto out_freeiov;
+		goto out;
 	len = err;
 
 	if (uaddr != NULL) {
@@ -2518,12 +2552,12 @@ static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg,
 					msg_sys->msg_namelen, uaddr,
 					uaddr_len);
 		if (err < 0)
-			goto out_freeiov;
+			goto out;
 	}
 	err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
 			 COMPAT_FLAGS(msg));
 	if (err)
-		goto out_freeiov;
+		goto out;
 	if (MSG_CMSG_COMPAT & flags)
 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
 				 &msg_compat->msg_controllen);
@@ -2531,10 +2565,25 @@ static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg,
 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
 				 &msg->msg_controllen);
 	if (err)
-		goto out_freeiov;
+		goto out;
 	err = len;
+out:
+	return err;
+}
+
+static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg,
+			 struct msghdr *msg_sys, unsigned int flags, int nosec)
+{
+	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
+	/* user mode address pointers */
+	struct sockaddr __user *uaddr;
+	ssize_t err;
+
+	err = recvmsg_copy_msghdr(msg_sys, msg, flags, &uaddr, &iov);
+	if (err < 0)
+		return err;
 
-out_freeiov:
+	err = ____sys_recvmsg(sock, msg_sys, msg, uaddr, flags, nosec);
 	kfree(iov);
 	return err;
 }
-- 
2.24.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/2] net: disallow ancillary data for __sys_{send,recv}msg_file()
  2019-11-26  1:31 [PATCHSET 0/2] Disallow ancillary data from __sys_{recv,send}msg_file() Jens Axboe
  2019-11-26  1:31 ` [PATCH 1/2] net: separate out the msghdr copy from ___sys_{send,recv}msg() Jens Axboe
@ 2019-11-26  1:31 ` Jens Axboe
  2019-11-26 22:00 ` [PATCHSET 0/2] Disallow ancillary data from __sys_{recv,send}msg_file() David Miller
  2 siblings, 0 replies; 5+ messages in thread
From: Jens Axboe @ 2019-11-26  1:31 UTC (permalink / raw)
  To: netdev; +Cc: davem, Jens Axboe

Only io_uring uses (and added) these, and we want to disallow the
use of sendmsg/recvmsg for anything but regular data transfers.
Use the newly added prep helper to split the msghdr copy out from
the core function, to check for msg_control and msg_controllen
settings. If either is set, we return -EINVAL.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
---
 net/socket.c | 43 +++++++++++++++++++++++++++++++++++++------
 1 file changed, 37 insertions(+), 6 deletions(-)

diff --git a/net/socket.c b/net/socket.c
index da729df8f03d..2d6083b881ab 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -2388,12 +2388,27 @@ static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
 /*
  *	BSD sendmsg interface
  */
-long __sys_sendmsg_sock(struct socket *sock, struct user_msghdr __user *msg,
+long __sys_sendmsg_sock(struct socket *sock, struct user_msghdr __user *umsg,
 			unsigned int flags)
 {
-	struct msghdr msg_sys;
+	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
+	struct sockaddr_storage address;
+	struct msghdr msg = { .msg_name = &address };
+	ssize_t err;
+
+	err = sendmsg_copy_msghdr(&msg, umsg, flags, &iov);
+	if (err)
+		return err;
+	/* disallow ancillary data requests from this path */
+	if (msg.msg_control || msg.msg_controllen) {
+		err = -EINVAL;
+		goto out;
+	}
 
-	return ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL, 0);
+	err = ____sys_sendmsg(sock, &msg, flags, NULL, 0);
+out:
+	kfree(iov);
+	return err;
 }
 
 long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned int flags,
@@ -2592,12 +2607,28 @@ static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg,
  *	BSD recvmsg interface
  */
 
-long __sys_recvmsg_sock(struct socket *sock, struct user_msghdr __user *msg,
+long __sys_recvmsg_sock(struct socket *sock, struct user_msghdr __user *umsg,
 			unsigned int flags)
 {
-	struct msghdr msg_sys;
+	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
+	struct sockaddr_storage address;
+	struct msghdr msg = { .msg_name = &address };
+	struct sockaddr __user *uaddr;
+	ssize_t err;
 
-	return ___sys_recvmsg(sock, msg, &msg_sys, flags, 0);
+	err = recvmsg_copy_msghdr(&msg, umsg, flags, &uaddr, &iov);
+	if (err)
+		return err;
+	/* disallow ancillary data requests from this path */
+	if (msg.msg_control || msg.msg_controllen) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	err = ____sys_recvmsg(sock, &msg, umsg, uaddr, flags, 0);
+out:
+	kfree(iov);
+	return err;
 }
 
 long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned int flags,
-- 
2.24.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCHSET 0/2] Disallow ancillary data from __sys_{recv,send}msg_file()
  2019-11-26  1:31 [PATCHSET 0/2] Disallow ancillary data from __sys_{recv,send}msg_file() Jens Axboe
  2019-11-26  1:31 ` [PATCH 1/2] net: separate out the msghdr copy from ___sys_{send,recv}msg() Jens Axboe
  2019-11-26  1:31 ` [PATCH 2/2] net: disallow ancillary data for __sys_{send,recv}msg_file() Jens Axboe
@ 2019-11-26 22:00 ` David Miller
  2019-11-26 22:04   ` Jens Axboe
  2 siblings, 1 reply; 5+ messages in thread
From: David Miller @ 2019-11-26 22:00 UTC (permalink / raw)
  To: axboe; +Cc: netdev

From: Jens Axboe <axboe@kernel.dk>
Date: Mon, 25 Nov 2019 18:31:43 -0700

> io_uring currently uses __sys_sendmsg_file() and __sys_recvmsg_file() to
> handle sendmsg and recvmsg operations. This generally works fine, but we
> don't want to allow cmsg type operations, just "normal" data transfers.
> 
> This small patchset first splits the msghdr copy from the two main
> helpers in net/socket.c, then changes __sys_sendmsg_file() and
> __sys_recvmsg_file() to use those helpers. With patch 2, we also add a
> check to explicitly check for msghdr->msg_control and
> msghdr->msg_controllen and return -EINVAL if they are set.

For the series:

Acked-by: David S. Miller <davem@davemloft.net>

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCHSET 0/2] Disallow ancillary data from __sys_{recv,send}msg_file()
  2019-11-26 22:00 ` [PATCHSET 0/2] Disallow ancillary data from __sys_{recv,send}msg_file() David Miller
@ 2019-11-26 22:04   ` Jens Axboe
  0 siblings, 0 replies; 5+ messages in thread
From: Jens Axboe @ 2019-11-26 22:04 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

On 11/26/19 3:00 PM, David Miller wrote:
> From: Jens Axboe <axboe@kernel.dk>
> Date: Mon, 25 Nov 2019 18:31:43 -0700
> 
>> io_uring currently uses __sys_sendmsg_file() and __sys_recvmsg_file() to
>> handle sendmsg and recvmsg operations. This generally works fine, but we
>> don't want to allow cmsg type operations, just "normal" data transfers.
>>
>> This small patchset first splits the msghdr copy from the two main
>> helpers in net/socket.c, then changes __sys_sendmsg_file() and
>> __sys_recvmsg_file() to use those helpers. With patch 2, we also add a
>> check to explicitly check for msghdr->msg_control and
>> msghdr->msg_controllen and return -EINVAL if they are set.
> 
> For the series:
> 
> Acked-by: David S. Miller <davem@davemloft.net>

Thanks David, added to the series.

-- 
Jens Axboe


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2019-11-26 22:04 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-26  1:31 [PATCHSET 0/2] Disallow ancillary data from __sys_{recv,send}msg_file() Jens Axboe
2019-11-26  1:31 ` [PATCH 1/2] net: separate out the msghdr copy from ___sys_{send,recv}msg() Jens Axboe
2019-11-26  1:31 ` [PATCH 2/2] net: disallow ancillary data for __sys_{send,recv}msg_file() Jens Axboe
2019-11-26 22:00 ` [PATCHSET 0/2] Disallow ancillary data from __sys_{recv,send}msg_file() David Miller
2019-11-26 22:04   ` Jens Axboe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).