diff options
Diffstat (limited to 'net/socket.c')
-rw-r--r-- | net/socket.c | 82 |
1 files changed, 46 insertions, 36 deletions
diff --git a/net/socket.c b/net/socket.c index 81fe82513046..1ba57d888981 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -180,9 +180,9 @@ static DEFINE_PER_CPU(int, sockets_in_use) = 0; | |||
180 | * invalid addresses -EFAULT is returned. On a success 0 is returned. | 180 | * invalid addresses -EFAULT is returned. On a success 0 is returned. |
181 | */ | 181 | */ |
182 | 182 | ||
183 | int move_addr_to_kernel(void __user *uaddr, int ulen, void *kaddr) | 183 | int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr *kaddr) |
184 | { | 184 | { |
185 | if (ulen < 0 || ulen > MAX_SOCK_ADDR) | 185 | if (ulen < 0 || ulen > sizeof(struct sockaddr_storage)) |
186 | return -EINVAL; | 186 | return -EINVAL; |
187 | if (ulen == 0) | 187 | if (ulen == 0) |
188 | return 0; | 188 | return 0; |
@@ -208,7 +208,7 @@ int move_addr_to_kernel(void __user *uaddr, int ulen, void *kaddr) | |||
208 | * specified. Zero is returned for a success. | 208 | * specified. Zero is returned for a success. |
209 | */ | 209 | */ |
210 | 210 | ||
211 | int move_addr_to_user(void *kaddr, int klen, void __user *uaddr, | 211 | int move_addr_to_user(struct sockaddr *kaddr, int klen, void __user *uaddr, |
212 | int __user *ulen) | 212 | int __user *ulen) |
213 | { | 213 | { |
214 | int err; | 214 | int err; |
@@ -219,7 +219,7 @@ int move_addr_to_user(void *kaddr, int klen, void __user *uaddr, | |||
219 | return err; | 219 | return err; |
220 | if (len > klen) | 220 | if (len > klen) |
221 | len = klen; | 221 | len = klen; |
222 | if (len < 0 || len > MAX_SOCK_ADDR) | 222 | if (len < 0 || len > sizeof(struct sockaddr_storage)) |
223 | return -EINVAL; | 223 | return -EINVAL; |
224 | if (len) { | 224 | if (len) { |
225 | if (audit_sockaddr(klen, kaddr)) | 225 | if (audit_sockaddr(klen, kaddr)) |
@@ -1342,20 +1342,20 @@ out_fd: | |||
1342 | asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen) | 1342 | asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen) |
1343 | { | 1343 | { |
1344 | struct socket *sock; | 1344 | struct socket *sock; |
1345 | char address[MAX_SOCK_ADDR]; | 1345 | struct sockaddr_storage address; |
1346 | int err, fput_needed; | 1346 | int err, fput_needed; |
1347 | 1347 | ||
1348 | sock = sockfd_lookup_light(fd, &err, &fput_needed); | 1348 | sock = sockfd_lookup_light(fd, &err, &fput_needed); |
1349 | if (sock) { | 1349 | if (sock) { |
1350 | err = move_addr_to_kernel(umyaddr, addrlen, address); | 1350 | err = move_addr_to_kernel(umyaddr, addrlen, (struct sockaddr *)&address); |
1351 | if (err >= 0) { | 1351 | if (err >= 0) { |
1352 | err = security_socket_bind(sock, | 1352 | err = security_socket_bind(sock, |
1353 | (struct sockaddr *)address, | 1353 | (struct sockaddr *)&address, |
1354 | addrlen); | 1354 | addrlen); |
1355 | if (!err) | 1355 | if (!err) |
1356 | err = sock->ops->bind(sock, | 1356 | err = sock->ops->bind(sock, |
1357 | (struct sockaddr *) | 1357 | (struct sockaddr *) |
1358 | address, addrlen); | 1358 | &address, addrlen); |
1359 | } | 1359 | } |
1360 | fput_light(sock->file, fput_needed); | 1360 | fput_light(sock->file, fput_needed); |
1361 | } | 1361 | } |
@@ -1407,7 +1407,7 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, | |||
1407 | struct socket *sock, *newsock; | 1407 | struct socket *sock, *newsock; |
1408 | struct file *newfile; | 1408 | struct file *newfile; |
1409 | int err, len, newfd, fput_needed; | 1409 | int err, len, newfd, fput_needed; |
1410 | char address[MAX_SOCK_ADDR]; | 1410 | struct sockaddr_storage address; |
1411 | 1411 | ||
1412 | sock = sockfd_lookup_light(fd, &err, &fput_needed); | 1412 | sock = sockfd_lookup_light(fd, &err, &fput_needed); |
1413 | if (!sock) | 1413 | if (!sock) |
@@ -1446,13 +1446,13 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, | |||
1446 | goto out_fd; | 1446 | goto out_fd; |
1447 | 1447 | ||
1448 | if (upeer_sockaddr) { | 1448 | if (upeer_sockaddr) { |
1449 | if (newsock->ops->getname(newsock, (struct sockaddr *)address, | 1449 | if (newsock->ops->getname(newsock, (struct sockaddr *)&address, |
1450 | &len, 2) < 0) { | 1450 | &len, 2) < 0) { |
1451 | err = -ECONNABORTED; | 1451 | err = -ECONNABORTED; |
1452 | goto out_fd; | 1452 | goto out_fd; |
1453 | } | 1453 | } |
1454 | err = move_addr_to_user(address, len, upeer_sockaddr, | 1454 | err = move_addr_to_user((struct sockaddr *)&address, |
1455 | upeer_addrlen); | 1455 | len, upeer_sockaddr, upeer_addrlen); |
1456 | if (err < 0) | 1456 | if (err < 0) |
1457 | goto out_fd; | 1457 | goto out_fd; |
1458 | } | 1458 | } |
@@ -1495,22 +1495,22 @@ asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, | |||
1495 | int addrlen) | 1495 | int addrlen) |
1496 | { | 1496 | { |
1497 | struct socket *sock; | 1497 | struct socket *sock; |
1498 | char address[MAX_SOCK_ADDR]; | 1498 | struct sockaddr_storage address; |
1499 | int err, fput_needed; | 1499 | int err, fput_needed; |
1500 | 1500 | ||
1501 | sock = sockfd_lookup_light(fd, &err, &fput_needed); | 1501 | sock = sockfd_lookup_light(fd, &err, &fput_needed); |
1502 | if (!sock) | 1502 | if (!sock) |
1503 | goto out; | 1503 | goto out; |
1504 | err = move_addr_to_kernel(uservaddr, addrlen, address); | 1504 | err = move_addr_to_kernel(uservaddr, addrlen, (struct sockaddr *)&address); |
1505 | if (err < 0) | 1505 | if (err < 0) |
1506 | goto out_put; | 1506 | goto out_put; |
1507 | 1507 | ||
1508 | err = | 1508 | err = |
1509 | security_socket_connect(sock, (struct sockaddr *)address, addrlen); | 1509 | security_socket_connect(sock, (struct sockaddr *)&address, addrlen); |
1510 | if (err) | 1510 | if (err) |
1511 | goto out_put; | 1511 | goto out_put; |
1512 | 1512 | ||
1513 | err = sock->ops->connect(sock, (struct sockaddr *)address, addrlen, | 1513 | err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen, |
1514 | sock->file->f_flags); | 1514 | sock->file->f_flags); |
1515 | out_put: | 1515 | out_put: |
1516 | fput_light(sock->file, fput_needed); | 1516 | fput_light(sock->file, fput_needed); |
@@ -1527,7 +1527,7 @@ asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr, | |||
1527 | int __user *usockaddr_len) | 1527 | int __user *usockaddr_len) |
1528 | { | 1528 | { |
1529 | struct socket *sock; | 1529 | struct socket *sock; |
1530 | char address[MAX_SOCK_ADDR]; | 1530 | struct sockaddr_storage address; |
1531 | int len, err, fput_needed; | 1531 | int len, err, fput_needed; |
1532 | 1532 | ||
1533 | sock = sockfd_lookup_light(fd, &err, &fput_needed); | 1533 | sock = sockfd_lookup_light(fd, &err, &fput_needed); |
@@ -1538,10 +1538,10 @@ asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr, | |||
1538 | if (err) | 1538 | if (err) |
1539 | goto out_put; | 1539 | goto out_put; |
1540 | 1540 | ||
1541 | err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 0); | 1541 | err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0); |
1542 | if (err) | 1542 | if (err) |
1543 | goto out_put; | 1543 | goto out_put; |
1544 | err = move_addr_to_user(address, len, usockaddr, usockaddr_len); | 1544 | err = move_addr_to_user((struct sockaddr *)&address, len, usockaddr, usockaddr_len); |
1545 | 1545 | ||
1546 | out_put: | 1546 | out_put: |
1547 | fput_light(sock->file, fput_needed); | 1547 | fput_light(sock->file, fput_needed); |
@@ -1558,7 +1558,7 @@ asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr, | |||
1558 | int __user *usockaddr_len) | 1558 | int __user *usockaddr_len) |
1559 | { | 1559 | { |
1560 | struct socket *sock; | 1560 | struct socket *sock; |
1561 | char address[MAX_SOCK_ADDR]; | 1561 | struct sockaddr_storage address; |
1562 | int len, err, fput_needed; | 1562 | int len, err, fput_needed; |
1563 | 1563 | ||
1564 | sock = sockfd_lookup_light(fd, &err, &fput_needed); | 1564 | sock = sockfd_lookup_light(fd, &err, &fput_needed); |
@@ -1570,10 +1570,10 @@ asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr, | |||
1570 | } | 1570 | } |
1571 | 1571 | ||
1572 | err = | 1572 | err = |
1573 | sock->ops->getname(sock, (struct sockaddr *)address, &len, | 1573 | sock->ops->getname(sock, (struct sockaddr *)&address, &len, |
1574 | 1); | 1574 | 1); |
1575 | if (!err) | 1575 | if (!err) |
1576 | err = move_addr_to_user(address, len, usockaddr, | 1576 | err = move_addr_to_user((struct sockaddr *)&address, len, usockaddr, |
1577 | usockaddr_len); | 1577 | usockaddr_len); |
1578 | fput_light(sock->file, fput_needed); | 1578 | fput_light(sock->file, fput_needed); |
1579 | } | 1579 | } |
@@ -1591,7 +1591,7 @@ asmlinkage long sys_sendto(int fd, void __user *buff, size_t len, | |||
1591 | int addr_len) | 1591 | int addr_len) |
1592 | { | 1592 | { |
1593 | struct socket *sock; | 1593 | struct socket *sock; |
1594 | char address[MAX_SOCK_ADDR]; | 1594 | struct sockaddr_storage address; |
1595 | int err; | 1595 | int err; |
1596 | struct msghdr msg; | 1596 | struct msghdr msg; |
1597 | struct iovec iov; | 1597 | struct iovec iov; |
@@ -1610,10 +1610,10 @@ asmlinkage long sys_sendto(int fd, void __user *buff, size_t len, | |||
1610 | msg.msg_controllen = 0; | 1610 | msg.msg_controllen = 0; |
1611 | msg.msg_namelen = 0; | 1611 | msg.msg_namelen = 0; |
1612 | if (addr) { | 1612 | if (addr) { |
1613 | err = move_addr_to_kernel(addr, addr_len, address); | 1613 | err = move_addr_to_kernel(addr, addr_len, (struct sockaddr *)&address); |
1614 | if (err < 0) | 1614 | if (err < 0) |
1615 | goto out_put; | 1615 | goto out_put; |
1616 | msg.msg_name = address; | 1616 | msg.msg_name = (struct sockaddr *)&address; |
1617 | msg.msg_namelen = addr_len; | 1617 | msg.msg_namelen = addr_len; |
1618 | } | 1618 | } |
1619 | if (sock->file->f_flags & O_NONBLOCK) | 1619 | if (sock->file->f_flags & O_NONBLOCK) |
@@ -1649,7 +1649,7 @@ asmlinkage long sys_recvfrom(int fd, void __user *ubuf, size_t size, | |||
1649 | struct socket *sock; | 1649 | struct socket *sock; |
1650 | struct iovec iov; | 1650 | struct iovec iov; |
1651 | struct msghdr msg; | 1651 | struct msghdr msg; |
1652 | char address[MAX_SOCK_ADDR]; | 1652 | struct sockaddr_storage address; |
1653 | int err, err2; | 1653 | int err, err2; |
1654 | int fput_needed; | 1654 | int fput_needed; |
1655 | 1655 | ||
@@ -1663,14 +1663,15 @@ asmlinkage long sys_recvfrom(int fd, void __user *ubuf, size_t size, | |||
1663 | msg.msg_iov = &iov; | 1663 | msg.msg_iov = &iov; |
1664 | iov.iov_len = size; | 1664 | iov.iov_len = size; |
1665 | iov.iov_base = ubuf; | 1665 | iov.iov_base = ubuf; |
1666 | msg.msg_name = address; | 1666 | msg.msg_name = (struct sockaddr *)&address; |
1667 | msg.msg_namelen = MAX_SOCK_ADDR; | 1667 | msg.msg_namelen = sizeof(address); |
1668 | if (sock->file->f_flags & O_NONBLOCK) | 1668 | if (sock->file->f_flags & O_NONBLOCK) |
1669 | flags |= MSG_DONTWAIT; | 1669 | flags |= MSG_DONTWAIT; |
1670 | err = sock_recvmsg(sock, &msg, size, flags); | 1670 | err = sock_recvmsg(sock, &msg, size, flags); |
1671 | 1671 | ||
1672 | if (err >= 0 && addr != NULL) { | 1672 | if (err >= 0 && addr != NULL) { |
1673 | err2 = move_addr_to_user(address, msg.msg_namelen, addr, addr_len); | 1673 | err2 = move_addr_to_user((struct sockaddr *)&address, |
1674 | msg.msg_namelen, addr, addr_len); | ||
1674 | if (err2 < 0) | 1675 | if (err2 < 0) |
1675 | err = err2; | 1676 | err = err2; |
1676 | } | 1677 | } |
@@ -1790,7 +1791,7 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags) | |||
1790 | struct compat_msghdr __user *msg_compat = | 1791 | struct compat_msghdr __user *msg_compat = |
1791 | (struct compat_msghdr __user *)msg; | 1792 | (struct compat_msghdr __user *)msg; |
1792 | struct socket *sock; | 1793 | struct socket *sock; |
1793 | char address[MAX_SOCK_ADDR]; | 1794 | struct sockaddr_storage address; |
1794 | struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; | 1795 | struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; |
1795 | unsigned char ctl[sizeof(struct cmsghdr) + 20] | 1796 | unsigned char ctl[sizeof(struct cmsghdr) + 20] |
1796 | __attribute__ ((aligned(sizeof(__kernel_size_t)))); | 1797 | __attribute__ ((aligned(sizeof(__kernel_size_t)))); |
@@ -1828,9 +1829,13 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags) | |||
1828 | 1829 | ||
1829 | /* This will also move the address data into kernel space */ | 1830 | /* This will also move the address data into kernel space */ |
1830 | if (MSG_CMSG_COMPAT & flags) { | 1831 | if (MSG_CMSG_COMPAT & flags) { |
1831 | err = verify_compat_iovec(&msg_sys, iov, address, VERIFY_READ); | 1832 | err = verify_compat_iovec(&msg_sys, iov, |
1833 | (struct sockaddr *)&address, | ||
1834 | VERIFY_READ); | ||
1832 | } else | 1835 | } else |
1833 | err = verify_iovec(&msg_sys, iov, address, VERIFY_READ); | 1836 | err = verify_iovec(&msg_sys, iov, |
1837 | (struct sockaddr *)&address, | ||
1838 | VERIFY_READ); | ||
1834 | if (err < 0) | 1839 | if (err < 0) |
1835 | goto out_freeiov; | 1840 | goto out_freeiov; |
1836 | total_len = err; | 1841 | total_len = err; |
@@ -1901,7 +1906,7 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, | |||
1901 | int fput_needed; | 1906 | int fput_needed; |
1902 | 1907 | ||
1903 | /* kernel mode address */ | 1908 | /* kernel mode address */ |
1904 | char addr[MAX_SOCK_ADDR]; | 1909 | struct sockaddr_storage addr; |
1905 | 1910 | ||
1906 | /* user mode address pointers */ | 1911 | /* user mode address pointers */ |
1907 | struct sockaddr __user *uaddr; | 1912 | struct sockaddr __user *uaddr; |
@@ -1939,9 +1944,13 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, | |||
1939 | uaddr = (__force void __user *)msg_sys.msg_name; | 1944 | uaddr = (__force void __user *)msg_sys.msg_name; |
1940 | uaddr_len = COMPAT_NAMELEN(msg); | 1945 | uaddr_len = COMPAT_NAMELEN(msg); |
1941 | if (MSG_CMSG_COMPAT & flags) { | 1946 | if (MSG_CMSG_COMPAT & flags) { |
1942 | err = verify_compat_iovec(&msg_sys, iov, addr, VERIFY_WRITE); | 1947 | err = verify_compat_iovec(&msg_sys, iov, |
1948 | (struct sockaddr *)&addr, | ||
1949 | VERIFY_WRITE); | ||
1943 | } else | 1950 | } else |
1944 | err = verify_iovec(&msg_sys, iov, addr, VERIFY_WRITE); | 1951 | err = verify_iovec(&msg_sys, iov, |
1952 | (struct sockaddr *)&addr, | ||
1953 | VERIFY_WRITE); | ||
1945 | if (err < 0) | 1954 | if (err < 0) |
1946 | goto out_freeiov; | 1955 | goto out_freeiov; |
1947 | total_len = err; | 1956 | total_len = err; |
@@ -1957,7 +1966,8 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, | |||
1957 | len = err; | 1966 | len = err; |
1958 | 1967 | ||
1959 | if (uaddr != NULL) { | 1968 | if (uaddr != NULL) { |
1960 | err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, | 1969 | err = move_addr_to_user((struct sockaddr *)&addr, |
1970 | msg_sys.msg_namelen, uaddr, | ||
1961 | uaddr_len); | 1971 | uaddr_len); |
1962 | if (err < 0) | 1972 | if (err < 0) |
1963 | goto out_freeiov; | 1973 | goto out_freeiov; |