net: use put_user() for msghdr results written back to user space

____sys_recvmsg() writes msg_flags and msg_controllen back with
__put_user(), and the compat sendmmsg()/recvmmsg() loops write msg_len
the same way.  None of these has an access_ok() of its own: they rely on
the earlier copy_from_user() of the message header having checked the
range.  For the compat msg_len that is not even true, since msg_len
lives after the compat_msghdr that was copied.  It is only safe because
compat pointers are 32-bit.  The native mmsg paths already use
put_user().

Use put_user() everywhere.  On x86 that adds a couple of instructions to
check the address, on a path that has to enable and disable user access
for each write anyway.

This is part of getting rid of __get_user() and __put_user() entirely.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Linus Torvalds 2026-10-19 19:23:33 -10:00
parent 94905fcbd9
commit 4e60e85129

View File

@ -2850,7 +2850,7 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
&msg_sys, flags, &used_address, MSG_EOR);
if (err < 0)
break;
err = __put_user(err, &compat_entry->msg_len);
err = put_user(err, &compat_entry->msg_len);
++compat_entry;
} else {
err = ___sys_sendmsg(sock,
@ -2943,16 +2943,16 @@ static int ____sys_recvmsg(struct socket *sock, struct msghdr *msg_sys,
if (err < 0)
goto out;
}
err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
COMPAT_FLAGS(msg));
err = put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
COMPAT_FLAGS(msg));
if (err)
goto out;
if (MSG_CMSG_COMPAT & flags)
err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
&msg_compat->msg_controllen);
err = put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
&msg_compat->msg_controllen);
else
err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
&msg->msg_controllen);
err = put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
&msg->msg_controllen);
if (err)
goto out;
err = len;
@ -3064,7 +3064,7 @@ static int do_recvmmsg(int fd, struct mmsghdr __user *mmsg,
datagrams);
if (err < 0)
break;
err = __put_user(err, &compat_entry->msg_len);
err = put_user(err, &compat_entry->msg_len);
++compat_entry;
} else {
err = ___sys_recvmsg(sock,