diff options
Diffstat (limited to 'net/socket.c')
| -rw-r--r-- | net/socket.c | 24 |
1 files changed, 14 insertions, 10 deletions
diff --git a/net/socket.c b/net/socket.c index c226aceee65b..e83c416708af 100644 --- a/net/socket.c +++ b/net/socket.c | |||
| @@ -221,12 +221,13 @@ static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen, | |||
| 221 | int err; | 221 | int err; |
| 222 | int len; | 222 | int len; |
| 223 | 223 | ||
| 224 | BUG_ON(klen > sizeof(struct sockaddr_storage)); | ||
| 224 | err = get_user(len, ulen); | 225 | err = get_user(len, ulen); |
| 225 | if (err) | 226 | if (err) |
| 226 | return err; | 227 | return err; |
| 227 | if (len > klen) | 228 | if (len > klen) |
| 228 | len = klen; | 229 | len = klen; |
| 229 | if (len < 0 || len > sizeof(struct sockaddr_storage)) | 230 | if (len < 0) |
| 230 | return -EINVAL; | 231 | return -EINVAL; |
| 231 | if (len) { | 232 | if (len) { |
| 232 | if (audit_sockaddr(klen, kaddr)) | 233 | if (audit_sockaddr(klen, kaddr)) |
| @@ -1840,8 +1841,10 @@ SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size, | |||
| 1840 | msg.msg_iov = &iov; | 1841 | msg.msg_iov = &iov; |
| 1841 | iov.iov_len = size; | 1842 | iov.iov_len = size; |
| 1842 | iov.iov_base = ubuf; | 1843 | iov.iov_base = ubuf; |
| 1843 | msg.msg_name = (struct sockaddr *)&address; | 1844 | /* Save some cycles and don't copy the address if not needed */ |
| 1844 | msg.msg_namelen = sizeof(address); | 1845 | msg.msg_name = addr ? (struct sockaddr *)&address : NULL; |
| 1846 | /* We assume all kernel code knows the size of sockaddr_storage */ | ||
| 1847 | msg.msg_namelen = 0; | ||
| 1845 | if (sock->file->f_flags & O_NONBLOCK) | 1848 | if (sock->file->f_flags & O_NONBLOCK) |
| 1846 | flags |= MSG_DONTWAIT; | 1849 | flags |= MSG_DONTWAIT; |
| 1847 | err = sock_recvmsg(sock, &msg, size, flags); | 1850 | err = sock_recvmsg(sock, &msg, size, flags); |
| @@ -1970,7 +1973,7 @@ static int copy_msghdr_from_user(struct msghdr *kmsg, | |||
| 1970 | if (copy_from_user(kmsg, umsg, sizeof(struct msghdr))) | 1973 | if (copy_from_user(kmsg, umsg, sizeof(struct msghdr))) |
| 1971 | return -EFAULT; | 1974 | return -EFAULT; |
| 1972 | if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) | 1975 | if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) |
| 1973 | return -EINVAL; | 1976 | kmsg->msg_namelen = sizeof(struct sockaddr_storage); |
| 1974 | return 0; | 1977 | return 0; |
| 1975 | } | 1978 | } |
| 1976 | 1979 | ||
| @@ -2221,16 +2224,14 @@ static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg, | |||
| 2221 | goto out; | 2224 | goto out; |
| 2222 | } | 2225 | } |
| 2223 | 2226 | ||
| 2224 | /* | 2227 | /* Save the user-mode address (verify_iovec will change the |
| 2225 | * Save the user-mode address (verify_iovec will change the | 2228 | * kernel msghdr to use the kernel address space) |
| 2226 | * kernel msghdr to use the kernel address space) | ||
| 2227 | */ | 2229 | */ |
| 2228 | |||
| 2229 | uaddr = (__force void __user *)msg_sys->msg_name; | 2230 | uaddr = (__force void __user *)msg_sys->msg_name; |
| 2230 | uaddr_len = COMPAT_NAMELEN(msg); | 2231 | uaddr_len = COMPAT_NAMELEN(msg); |
| 2231 | if (MSG_CMSG_COMPAT & flags) { | 2232 | if (MSG_CMSG_COMPAT & flags) |
| 2232 | err = verify_compat_iovec(msg_sys, iov, &addr, VERIFY_WRITE); | 2233 | err = verify_compat_iovec(msg_sys, iov, &addr, VERIFY_WRITE); |
| 2233 | } else | 2234 | else |
| 2234 | err = verify_iovec(msg_sys, iov, &addr, VERIFY_WRITE); | 2235 | err = verify_iovec(msg_sys, iov, &addr, VERIFY_WRITE); |
| 2235 | if (err < 0) | 2236 | if (err < 0) |
| 2236 | goto out_freeiov; | 2237 | goto out_freeiov; |
| @@ -2239,6 +2240,9 @@ static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg, | |||
| 2239 | cmsg_ptr = (unsigned long)msg_sys->msg_control; | 2240 | cmsg_ptr = (unsigned long)msg_sys->msg_control; |
| 2240 | msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT); | 2241 | msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT); |
| 2241 | 2242 | ||
| 2243 | /* We assume all kernel code knows the size of sockaddr_storage */ | ||
| 2244 | msg_sys->msg_namelen = 0; | ||
| 2245 | |||
| 2242 | if (sock->file->f_flags & O_NONBLOCK) | 2246 | if (sock->file->f_flags & O_NONBLOCK) |
| 2243 | flags |= MSG_DONTWAIT; | 2247 | flags |= MSG_DONTWAIT; |
| 2244 | err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys, | 2248 | err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys, |
