mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-01 18:55:12 +00:00
net: socket: Fix the wrong returns for recvmsg and sendmsg
Based on08adb7dabd
upstream. We found that after v3.10.73, recvmsg might return -EFAULT while -EINVAL was expected. We tested it through the recvmsg01 testcase come from LTP testsuit. It set msg->msg_namelen to -1 and the recvmsg syscall returned errno 14, which is unexpected (errno 22 is expected): recvmsg01 4 TFAIL : invalid socket length ; returned -1 (expected -1), errno 14 (expected 22) Linux mainline has no this bug for commit08adb7dab
fixes it accidentally. However, it is too large and complex to be backported to LTS 3.10. Commit281c9c36
(net: compat: Update get_compat_msghdr() to match copy_msghdr_from_user() behaviour) made get_compat_msghdr() return error if msg_sys->msg_namelen was negative, which changed the behaviors of recvmsg and sendmsg syscall in a lib32 system: Before commit281c9c36
, get_compat_msghdr() wouldn't fail and it would return -EINVAL in move_addr_to_user() or somewhere if msg_sys->msg_namelen was invalid and then syscall returned -EINVAL, which is correct. And now, when msg_sys->msg_namelen is negative, get_compat_msghdr() will fail and wants to return -EINVAL, however, the outer syscall will return -EFAULT directly, which is unexpected. This patch gets the return value of get_compat_msghdr() as well as copy_msghdr_from_user(), then returns this expected value if get_compat_msghdr() fails. Fixes:281c9c36
(net: compat: Update get_compat_msghdr() to match copy_msghdr_from_user() behaviour) Signed-off-by: Junling Zheng <zhengjunling@huawei.com> Signed-off-by: Hanbing Xu <xuhanbing@huawei.com> Cc: Li Zefan <lizefan@huawei.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: David Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Willy Tarreau <w@1wt.eu>
This commit is contained in:
parent
cb162b71b1
commit
a8226a6384
26
net/socket.c
26
net/socket.c
@ -1903,15 +1903,12 @@ SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned, flags)
|
||||
int fput_needed;
|
||||
|
||||
err = -EFAULT;
|
||||
if (MSG_CMSG_COMPAT & flags) {
|
||||
if (get_compat_msghdr(&msg_sys, msg_compat))
|
||||
return -EFAULT;
|
||||
}
|
||||
else {
|
||||
if (MSG_CMSG_COMPAT & flags)
|
||||
err = get_compat_msghdr(&msg_sys, msg_compat);
|
||||
else
|
||||
err = copy_msghdr_from_user(&msg_sys, msg);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
sock = sockfd_lookup_light(fd, &err, &fput_needed);
|
||||
if (!sock)
|
||||
@ -2016,15 +2013,12 @@ SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg,
|
||||
struct sockaddr __user *uaddr;
|
||||
int __user *uaddr_len;
|
||||
|
||||
if (MSG_CMSG_COMPAT & flags) {
|
||||
if (get_compat_msghdr(&msg_sys, msg_compat))
|
||||
return -EFAULT;
|
||||
}
|
||||
else {
|
||||
if (MSG_CMSG_COMPAT & flags)
|
||||
err = get_compat_msghdr(&msg_sys, msg_compat);
|
||||
else
|
||||
err = copy_msghdr_from_user(&msg_sys, msg);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
sock = sockfd_lookup_light(fd, &err, &fput_needed);
|
||||
if (!sock)
|
||||
|
Loading…
Reference in New Issue
Block a user