diff options
Diffstat (limited to 'net/socket.c')
-rw-r--r-- | net/socket.c | 22 |
1 files changed, 13 insertions, 9 deletions
diff --git a/net/socket.c b/net/socket.c index c226aceee65b..0b18693f2be6 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); |
@@ -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, |