Skip to content

Commit 86a7e0b

Browse files
jrifedavem330
authored andcommitted
net: prevent rewrite of msg_name in sock_sendmsg()
Callers of sock_sendmsg(), and similarly kernel_sendmsg(), in kernel space may observe their value of msg_name change in cases where BPF sendmsg hooks rewrite the send address. This has been confirmed to break NFS mounts running in UDP mode and has the potential to break other systems. This patch: 1) Creates a new function called __sock_sendmsg() with same logic as the old sock_sendmsg() function. 2) Replaces calls to sock_sendmsg() made by __sys_sendto() and __sys_sendmsg() with __sock_sendmsg() to avoid an unnecessary copy, as these system calls are already protected. 3) Modifies sock_sendmsg() so that it makes a copy of msg_name if present before passing it down the stack to insulate callers from changes to the send address. Link: https://lore.kernel.org/netdev/20230912013332.2048422-1-jrife@google.com/ Fixes: 1cedee1 ("bpf: Hooks for sys_sendmsg") Cc: stable@vger.kernel.org Reviewed-by: Willem de Bruijn <willemb@google.com> Signed-off-by: Jordan Rife <jrife@google.com> Reviewed-by: Simon Horman <horms@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 26297b4 commit 86a7e0b

File tree

1 file changed

+23
-6
lines changed

1 file changed

+23
-6
lines changed

net/socket.c

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,14 @@ static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg)
737737
return ret;
738738
}
739739

740+
static int __sock_sendmsg(struct socket *sock, struct msghdr *msg)
741+
{
742+
int err = security_socket_sendmsg(sock, msg,
743+
msg_data_left(msg));
744+
745+
return err ?: sock_sendmsg_nosec(sock, msg);
746+
}
747+
740748
/**
741749
* sock_sendmsg - send a message through @sock
742750
* @sock: socket
@@ -747,10 +755,19 @@ static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg)
747755
*/
748756
int sock_sendmsg(struct socket *sock, struct msghdr *msg)
749757
{
750-
int err = security_socket_sendmsg(sock, msg,
751-
msg_data_left(msg));
758+
struct sockaddr_storage *save_addr = (struct sockaddr_storage *)msg->msg_name;
759+
struct sockaddr_storage address;
760+
int ret;
752761

753-
return err ?: sock_sendmsg_nosec(sock, msg);
762+
if (msg->msg_name) {
763+
memcpy(&address, msg->msg_name, msg->msg_namelen);
764+
msg->msg_name = &address;
765+
}
766+
767+
ret = __sock_sendmsg(sock, msg);
768+
msg->msg_name = save_addr;
769+
770+
return ret;
754771
}
755772
EXPORT_SYMBOL(sock_sendmsg);
756773

@@ -1138,7 +1155,7 @@ static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from)
11381155
if (sock->type == SOCK_SEQPACKET)
11391156
msg.msg_flags |= MSG_EOR;
11401157

1141-
res = sock_sendmsg(sock, &msg);
1158+
res = __sock_sendmsg(sock, &msg);
11421159
*from = msg.msg_iter;
11431160
return res;
11441161
}
@@ -2174,7 +2191,7 @@ int __sys_sendto(int fd, void __user *buff, size_t len, unsigned int flags,
21742191
if (sock->file->f_flags & O_NONBLOCK)
21752192
flags |= MSG_DONTWAIT;
21762193
msg.msg_flags = flags;
2177-
err = sock_sendmsg(sock, &msg);
2194+
err = __sock_sendmsg(sock, &msg);
21782195

21792196
out_put:
21802197
fput_light(sock->file, fput_needed);
@@ -2538,7 +2555,7 @@ static int ____sys_sendmsg(struct socket *sock, struct msghdr *msg_sys,
25382555
err = sock_sendmsg_nosec(sock, msg_sys);
25392556
goto out_freectl;
25402557
}
2541-
err = sock_sendmsg(sock, msg_sys);
2558+
err = __sock_sendmsg(sock, msg_sys);
25422559
/*
25432560
* If this is sendmmsg() and sending to current destination address was
25442561
* successful, remember it.

0 commit comments

Comments
 (0)