io_uring: allow tcp ancillary data for __sys_recvmsg_sock()
For TCP tx zero-copy, the kernel notifies the process of completions by queuing completion notifications on the socket error queue. This patch allows reading these notifications via recvmsg to support TCP tx zero-copy. Ancillary data was originally disallowed due to privilege escalation via io_uring's offloading of sendmsg() onto a kernel thread with kernel credentials (https://crbug.com/project-zero/1975). So, we must ensure that the socket type is one where the ancillary data types that are delivered on recvmsg are plain data (no file descriptors or values that are translated based on the identity of the calling process). This was tested by using io_uring to call recvmsg on the MSG_ERRQUEUE with tx zero-copy enabled. Before this patch, we received -EINVALID from this specific code path. After this patch, we could read tcp tx zero-copy completion notifications from the MSG_ERRQUEUE. Signed-off-by: Soheil Hassas Yeganeh <soheil@google.com> Signed-off-by: Arjun Roy <arjunroy@google.com> Acked-by: Eric Dumazet <edumazet@google.com> Reviewed-by: Jann Horn <jannh@google.com> Reviewed-by: Jens Axboe <axboe@kernel.dk> Signed-off-by: Luke Hsiao <lukehsiao@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
37a319b5f9
commit
583bbf0624
|
@ -41,6 +41,8 @@ struct net;
|
|||
#define SOCK_PASSCRED 3
|
||||
#define SOCK_PASSSEC 4
|
||||
|
||||
#define PROTO_CMSG_DATA_ONLY 0x0001
|
||||
|
||||
#ifndef ARCH_HAS_SOCKET_TYPES
|
||||
/**
|
||||
* enum sock_type - Socket types
|
||||
|
@ -135,6 +137,7 @@ typedef int (*sk_read_actor_t)(read_descriptor_t *, struct sk_buff *,
|
|||
|
||||
struct proto_ops {
|
||||
int family;
|
||||
unsigned int flags;
|
||||
struct module *owner;
|
||||
int (*release) (struct socket *sock);
|
||||
int (*bind) (struct socket *sock,
|
||||
|
|
|
@ -1017,6 +1017,7 @@ static int inet_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned lon
|
|||
|
||||
const struct proto_ops inet_stream_ops = {
|
||||
.family = PF_INET,
|
||||
.flags = PROTO_CMSG_DATA_ONLY,
|
||||
.owner = THIS_MODULE,
|
||||
.release = inet_release,
|
||||
.bind = inet_bind,
|
||||
|
|
|
@ -661,6 +661,7 @@ int inet6_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
|
|||
|
||||
const struct proto_ops inet6_stream_ops = {
|
||||
.family = PF_INET6,
|
||||
.flags = PROTO_CMSG_DATA_ONLY,
|
||||
.owner = THIS_MODULE,
|
||||
.release = inet6_release,
|
||||
.bind = inet6_bind,
|
||||
|
|
|
@ -2628,9 +2628,11 @@ long __sys_recvmsg_sock(struct socket *sock, struct msghdr *msg,
|
|||
struct user_msghdr __user *umsg,
|
||||
struct sockaddr __user *uaddr, unsigned int flags)
|
||||
{
|
||||
/* disallow ancillary data requests from this path */
|
||||
if (msg->msg_control || msg->msg_controllen)
|
||||
return -EINVAL;
|
||||
if (msg->msg_control || msg->msg_controllen) {
|
||||
/* disallow ancillary data reqs unless cmsg is plain data */
|
||||
if (!(sock->ops->flags & PROTO_CMSG_DATA_ONLY))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return ____sys_recvmsg(sock, msg, umsg, uaddr, flags, 0);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue