From d4a3062c59847166e91c434e29ec53c06f09dec4 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Fri, 29 Nov 2019 14:54:08 -0500 Subject: [PATCH] fixes for 5.3 Signed-off-by: Sasha Levin --- ...orkers-should-inherit-the-user-creds.patch | 133 ++++++++++ ...illary-data-for-__sys_-send-recv-msg.patch | 92 +++++++ ...-the-msghdr-copy-from-___sys_-send-r.patch | 250 ++++++++++++++++++ queue-5.3/series | 3 + 4 files changed, 478 insertions(+) create mode 100644 queue-5.3/io_uring-async-workers-should-inherit-the-user-creds.patch create mode 100644 queue-5.3/net-disallow-ancillary-data-for-__sys_-send-recv-msg.patch create mode 100644 queue-5.3/net-separate-out-the-msghdr-copy-from-___sys_-send-r.patch create mode 100644 queue-5.3/series diff --git a/queue-5.3/io_uring-async-workers-should-inherit-the-user-creds.patch b/queue-5.3/io_uring-async-workers-should-inherit-the-user-creds.patch new file mode 100644 index 00000000000..bb5da4939dc --- /dev/null +++ b/queue-5.3/io_uring-async-workers-should-inherit-the-user-creds.patch @@ -0,0 +1,133 @@ +From e106d9fcc66411426c16ea3c3579e49cf2819b3c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Nov 2019 08:52:30 -0700 +Subject: io_uring: async workers should inherit the user creds + +From: Jens Axboe + +[ Upstream commit 181e448d8709e517c9c7b523fcd209f24eb38ca7 ] + +If we don't inherit the original task creds, then we can confuse users +like fuse that pass creds in the request header. See link below on +identical aio issue. + +Link: https://lore.kernel.org/linux-fsdevel/26f0d78e-99ca-2f1b-78b9-433088053a61@scylladb.com/T/#u +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + fs/io_uring.c | 23 ++++++++++++++++++++++- + 1 file changed, 22 insertions(+), 1 deletion(-) + +diff --git a/fs/io_uring.c b/fs/io_uring.c +index 56c23dee98117..f563a581b924c 100644 +--- a/fs/io_uring.c ++++ b/fs/io_uring.c +@@ -260,6 +260,8 @@ struct io_ring_ctx { + + struct user_struct *user; + ++ struct cred *creds; ++ + struct completion ctx_done; + + struct { +@@ -1633,8 +1635,11 @@ static void io_poll_complete_work(struct work_struct *work) + struct io_poll_iocb *poll = &req->poll; + struct poll_table_struct pt = { ._key = poll->events }; + struct io_ring_ctx *ctx = req->ctx; ++ const struct cred *old_cred; + __poll_t mask = 0; + ++ old_cred = override_creds(ctx->creds); ++ + if (!READ_ONCE(poll->canceled)) + mask = vfs_poll(poll->file, &pt) & poll->events; + +@@ -1649,7 +1654,7 @@ static void io_poll_complete_work(struct work_struct *work) + if (!mask && !READ_ONCE(poll->canceled)) { + add_wait_queue(poll->head, &poll->wait); + spin_unlock_irq(&ctx->completion_lock); +- return; ++ goto out; + } + list_del_init(&req->list); + io_poll_complete(ctx, req, mask); +@@ -1657,6 +1662,8 @@ static void io_poll_complete_work(struct work_struct *work) + + io_cqring_ev_posted(ctx); + io_put_req(req); ++out: ++ revert_creds(old_cred); + } + + static int io_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync, +@@ -1906,10 +1913,12 @@ static void io_sq_wq_submit_work(struct work_struct *work) + struct io_ring_ctx *ctx = req->ctx; + struct mm_struct *cur_mm = NULL; + struct async_list *async_list; ++ const struct cred *old_cred; + LIST_HEAD(req_list); + mm_segment_t old_fs; + int ret; + ++ old_cred = override_creds(ctx->creds); + async_list = io_async_list_from_sqe(ctx, req->submit.sqe); + restart: + do { +@@ -2017,6 +2026,7 @@ static void io_sq_wq_submit_work(struct work_struct *work) + unuse_mm(cur_mm); + mmput(cur_mm); + } ++ revert_creds(old_cred); + } + + /* +@@ -2354,6 +2364,7 @@ static int io_sq_thread(void *data) + { + struct io_ring_ctx *ctx = data; + struct mm_struct *cur_mm = NULL; ++ const struct cred *old_cred; + mm_segment_t old_fs; + DEFINE_WAIT(wait); + unsigned inflight; +@@ -2363,6 +2374,7 @@ static int io_sq_thread(void *data) + + old_fs = get_fs(); + set_fs(USER_DS); ++ old_cred = override_creds(ctx->creds); + + timeout = inflight = 0; + while (!kthread_should_park()) { +@@ -2473,6 +2485,7 @@ static int io_sq_thread(void *data) + unuse_mm(cur_mm); + mmput(cur_mm); + } ++ revert_creds(old_cred); + + kthread_parkme(); + +@@ -3142,6 +3155,8 @@ static void io_ring_ctx_free(struct io_ring_ctx *ctx) + io_unaccount_mem(ctx->user, + ring_pages(ctx->sq_entries, ctx->cq_entries)); + free_uid(ctx->user); ++ if (ctx->creds) ++ put_cred(ctx->creds); + kfree(ctx); + } + +@@ -3419,6 +3434,12 @@ static int io_uring_create(unsigned entries, struct io_uring_params *p) + ctx->account_mem = account_mem; + ctx->user = user; + ++ ctx->creds = prepare_creds(); ++ if (!ctx->creds) { ++ ret = -ENOMEM; ++ goto err; ++ } ++ + ret = io_allocate_scq_urings(ctx, p); + if (ret) + goto err; +-- +2.20.1 + diff --git a/queue-5.3/net-disallow-ancillary-data-for-__sys_-send-recv-msg.patch b/queue-5.3/net-disallow-ancillary-data-for-__sys_-send-recv-msg.patch new file mode 100644 index 00000000000..840de340705 --- /dev/null +++ b/queue-5.3/net-disallow-ancillary-data-for-__sys_-send-recv-msg.patch @@ -0,0 +1,92 @@ +From cfda91f3a3100b6668a4baacd087572e90d081c0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Nov 2019 17:04:13 -0700 +Subject: net: disallow ancillary data for __sys_{send,recv}msg_file() + +From: Jens Axboe + +[ Upstream commit d69e07793f891524c6bbf1e75b9ae69db4450953 ] + +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. + +Acked-by: David S. Miller +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + net/socket.c | 43 +++++++++++++++++++++++++++++++++++++------ + 1 file changed, 37 insertions(+), 6 deletions(-) + +diff --git a/net/socket.c b/net/socket.c +index fbe08d7df7732..d7a106028f0e0 100644 +--- a/net/socket.c ++++ b/net/socket.c +@@ -2357,12 +2357,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, +@@ -2561,12 +2576,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.20.1 + diff --git a/queue-5.3/net-separate-out-the-msghdr-copy-from-___sys_-send-r.patch b/queue-5.3/net-separate-out-the-msghdr-copy-from-___sys_-send-r.patch new file mode 100644 index 00000000000..db3b4f84846 --- /dev/null +++ b/queue-5.3/net-separate-out-the-msghdr-copy-from-___sys_-send-r.patch @@ -0,0 +1,250 @@ +From 17ae4d73b94236ef718b81a247b362b508d7d0f5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Nov 2019 14:27:34 -0700 +Subject: net: separate out the msghdr copy from ___sys_{send,recv}msg() + +From: Jens Axboe + +[ Upstream commit 4257c8ca13b084550574b8c9a667d9c90ff746eb ] + +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. + +Acked-by: David S. Miller +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + net/socket.c | 141 ++++++++++++++++++++++++++++++++++----------------- + 1 file changed, 95 insertions(+), 46 deletions(-) + +diff --git a/net/socket.c b/net/socket.c +index 6a9ab7a8b1d2c..fbe08d7df7732 100644 +--- a/net/socket.c ++++ b/net/socket.c +@@ -2232,15 +2232,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 */ +@@ -2248,19 +2243,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) { +@@ -2268,7 +2254,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) { +@@ -2277,7 +2263,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; + /* +@@ -2323,7 +2309,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; + } +@@ -2442,33 +2468,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); + +@@ -2479,7 +2513,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) { +@@ -2487,12 +2521,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); +@@ -2500,10 +2534,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.20.1 + diff --git a/queue-5.3/series b/queue-5.3/series new file mode 100644 index 00000000000..701544c872e --- /dev/null +++ b/queue-5.3/series @@ -0,0 +1,3 @@ +io_uring-async-workers-should-inherit-the-user-creds.patch +net-separate-out-the-msghdr-copy-from-___sys_-send-r.patch +net-disallow-ancillary-data-for-__sys_-send-recv-msg.patch -- 2.47.3