aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Carpenter <dan.carpenter@oracle.com>2013-10-02 17:27:20 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-11-04 07:31:00 -0500
commit2e8d97ab1f1236d08a8576d5c4b25d3180ff01f6 (patch)
tree33a15e9fb81f001a8e2c9075837dbea6249ceca4
parentb24b4a82fc96f74d848275c8f1b33df66cbef061 (diff)
net: heap overflow in __audit_sockaddr()
[ Upstream commit 1661bf364ae9c506bc8795fef70d1532931be1e8 ] 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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--net/compat.c2
-rw-r--r--net/socket.c24
2 files changed, 22 insertions, 4 deletions
diff --git a/net/compat.c b/net/compat.c
index f0a1ba6c8086..89032580bd1d 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -71,6 +71,8 @@ int get_compat_msghdr(struct msghdr *kmsg, struct compat_msghdr __user *umsg)
71 __get_user(kmsg->msg_controllen, &umsg->msg_controllen) || 71 __get_user(kmsg->msg_controllen, &umsg->msg_controllen) ||
72 __get_user(kmsg->msg_flags, &umsg->msg_flags)) 72 __get_user(kmsg->msg_flags, &umsg->msg_flags))
73 return -EFAULT; 73 return -EFAULT;
74 if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
75 return -EINVAL;
74 kmsg->msg_name = compat_ptr(tmp1); 76 kmsg->msg_name = compat_ptr(tmp1);
75 kmsg->msg_iov = compat_ptr(tmp2); 77 kmsg->msg_iov = compat_ptr(tmp2);
76 kmsg->msg_control = compat_ptr(tmp3); 78 kmsg->msg_control = compat_ptr(tmp3);
diff --git a/net/socket.c b/net/socket.c
index 4ca1526db756..9c467b2afc84 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1956,6 +1956,16 @@ struct used_address {
1956 unsigned int name_len; 1956 unsigned int name_len;
1957}; 1957};
1958 1958
1959static int copy_msghdr_from_user(struct msghdr *kmsg,
1960 struct msghdr __user *umsg)
1961{
1962 if (copy_from_user(kmsg, umsg, sizeof(struct msghdr)))
1963 return -EFAULT;
1964 if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
1965 return -EINVAL;
1966 return 0;
1967}
1968
1959static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg, 1969static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
1960 struct msghdr *msg_sys, unsigned int flags, 1970 struct msghdr *msg_sys, unsigned int flags,
1961 struct used_address *used_address) 1971 struct used_address *used_address)
@@ -1974,8 +1984,11 @@ static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
1974 if (MSG_CMSG_COMPAT & flags) { 1984 if (MSG_CMSG_COMPAT & flags) {
1975 if (get_compat_msghdr(msg_sys, msg_compat)) 1985 if (get_compat_msghdr(msg_sys, msg_compat))
1976 return -EFAULT; 1986 return -EFAULT;
1977 } else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr))) 1987 } else {
1978 return -EFAULT; 1988 err = copy_msghdr_from_user(msg_sys, msg);
1989 if (err)
1990 return err;
1991 }
1979 1992
1980 if (msg_sys->msg_iovlen > UIO_FASTIOV) { 1993 if (msg_sys->msg_iovlen > UIO_FASTIOV) {
1981 err = -EMSGSIZE; 1994 err = -EMSGSIZE;
@@ -2183,8 +2196,11 @@ static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
2183 if (MSG_CMSG_COMPAT & flags) { 2196 if (MSG_CMSG_COMPAT & flags) {
2184 if (get_compat_msghdr(msg_sys, msg_compat)) 2197 if (get_compat_msghdr(msg_sys, msg_compat))
2185 return -EFAULT; 2198 return -EFAULT;
2186 } else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr))) 2199 } else {
2187 return -EFAULT; 2200 err = copy_msghdr_from_user(msg_sys, msg);
2201 if (err)
2202 return err;
2203 }
2188 2204
2189 if (msg_sys->msg_iovlen > UIO_FASTIOV) { 2205 if (msg_sys->msg_iovlen > UIO_FASTIOV) {
2190 err = -EMSGSIZE; 2206 err = -EMSGSIZE;