diff options
author | Dan Carpenter <dan.carpenter@oracle.com> | 2013-10-02 17:27:20 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-10-03 16:05:14 -0400 |
commit | 1661bf364ae9c506bc8795fef70d1532931be1e8 (patch) | |
tree | 2ce62724a9931016cbbdb1bb94bc140012524c71 /net/socket.c | |
parent | 196896d4bb297e3ff24e62b2bfc22bbed7a28431 (diff) |
net: heap overflow in __audit_sockaddr()
We need to cap ->msg_namelen or it leads to a buffer overflow when we
to the memcpy() in __audit_sockaddr(). It requires CAP_AUDIT_CONTROL to
exploit this bug.
The call tree is:
___sys_recvmsg()
move_addr_to_user()
audit_sockaddr()
__audit_sockaddr()
Reported-by: Jüri Aedla <juri.aedla@gmail.com>
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/socket.c')
-rw-r--r-- | net/socket.c | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/net/socket.c b/net/socket.c index ebed4b68f768..c226aceee65b 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -1964,6 +1964,16 @@ struct used_address { | |||
1964 | unsigned int name_len; | 1964 | unsigned int name_len; |
1965 | }; | 1965 | }; |
1966 | 1966 | ||
1967 | static int copy_msghdr_from_user(struct msghdr *kmsg, | ||
1968 | struct msghdr __user *umsg) | ||
1969 | { | ||
1970 | if (copy_from_user(kmsg, umsg, sizeof(struct msghdr))) | ||
1971 | return -EFAULT; | ||
1972 | if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) | ||
1973 | return -EINVAL; | ||
1974 | return 0; | ||
1975 | } | ||
1976 | |||
1967 | static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg, | 1977 | static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg, |
1968 | struct msghdr *msg_sys, unsigned int flags, | 1978 | struct msghdr *msg_sys, unsigned int flags, |
1969 | struct used_address *used_address) | 1979 | struct used_address *used_address) |
@@ -1982,8 +1992,11 @@ static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg, | |||
1982 | if (MSG_CMSG_COMPAT & flags) { | 1992 | if (MSG_CMSG_COMPAT & flags) { |
1983 | if (get_compat_msghdr(msg_sys, msg_compat)) | 1993 | if (get_compat_msghdr(msg_sys, msg_compat)) |
1984 | return -EFAULT; | 1994 | return -EFAULT; |
1985 | } else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr))) | 1995 | } else { |
1986 | return -EFAULT; | 1996 | err = copy_msghdr_from_user(msg_sys, msg); |
1997 | if (err) | ||
1998 | return err; | ||
1999 | } | ||
1987 | 2000 | ||
1988 | if (msg_sys->msg_iovlen > UIO_FASTIOV) { | 2001 | if (msg_sys->msg_iovlen > UIO_FASTIOV) { |
1989 | err = -EMSGSIZE; | 2002 | err = -EMSGSIZE; |
@@ -2191,8 +2204,11 @@ static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg, | |||
2191 | if (MSG_CMSG_COMPAT & flags) { | 2204 | if (MSG_CMSG_COMPAT & flags) { |
2192 | if (get_compat_msghdr(msg_sys, msg_compat)) | 2205 | if (get_compat_msghdr(msg_sys, msg_compat)) |
2193 | return -EFAULT; | 2206 | return -EFAULT; |
2194 | } else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr))) | 2207 | } else { |
2195 | return -EFAULT; | 2208 | err = copy_msghdr_from_user(msg_sys, msg); |
2209 | if (err) | ||
2210 | return err; | ||
2211 | } | ||
2196 | 2212 | ||
2197 | if (msg_sys->msg_iovlen > UIO_FASTIOV) { | 2213 | if (msg_sys->msg_iovlen > UIO_FASTIOV) { |
2198 | err = -EMSGSIZE; | 2214 | err = -EMSGSIZE; |