| From f1fe8bb11aa2772335c3e66da2bbdbaba36285ae Mon Sep 17 00:00:00 2001 |
| From: Dan Carpenter <dan.carpenter@oracle.com> |
| Date: Wed, 27 Nov 2013 15:40:21 +0300 |
| Subject: net: clamp ->msg_namelen instead of returning an error |
| |
| From: Dan Carpenter <dan.carpenter@oracle.com> |
| |
| [ Upstream commit db31c55a6fb245fdbb752a2ca4aefec89afabb06 ] |
| |
| If kmsg->msg_namelen > sizeof(struct sockaddr_storage) then in the |
| original code that would lead to memory corruption in the kernel if you |
| had audit configured. If you didn't have audit configured it was |
| harmless. |
| |
| There are some programs such as beta versions of Ruby which use too |
| large of a buffer and returning an error code breaks them. We should |
| clamp the ->msg_namelen value instead. |
| |
| Fixes: 1661bf364ae9 ("net: heap overflow in __audit_sockaddr()") |
| Reported-by: Eric Wong <normalperson@yhbt.net> |
| Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> |
| Tested-by: Eric Wong <normalperson@yhbt.net> |
| Acked-by: Eric Dumazet <edumazet@google.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/compat.c | 2 +- |
| net/socket.c | 2 +- |
| 2 files changed, 2 insertions(+), 2 deletions(-) |
| |
| --- a/net/compat.c |
| +++ b/net/compat.c |
| @@ -72,7 +72,7 @@ int get_compat_msghdr(struct msghdr *kms |
| __get_user(kmsg->msg_flags, &umsg->msg_flags)) |
| return -EFAULT; |
| if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) |
| - return -EINVAL; |
| + kmsg->msg_namelen = sizeof(struct sockaddr_storage); |
| kmsg->msg_name = compat_ptr(tmp1); |
| kmsg->msg_iov = compat_ptr(tmp2); |
| kmsg->msg_control = compat_ptr(tmp3); |
| --- a/net/socket.c |
| +++ b/net/socket.c |
| @@ -1965,7 +1965,7 @@ static int copy_msghdr_from_user(struct |
| if (copy_from_user(kmsg, umsg, sizeof(struct msghdr))) |
| return -EFAULT; |
| if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) |
| - return -EINVAL; |
| + kmsg->msg_namelen = sizeof(struct sockaddr_storage); |
| return 0; |
| } |
| |