aboutsummaryrefslogtreecommitdiffstats
path: root/net/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/socket.c')
-rw-r--r--net/socket.c92
1 files changed, 56 insertions, 36 deletions
diff --git a/net/socket.c b/net/socket.c
index 66c4a8cf6db9..1ba57d888981 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -90,6 +90,7 @@
90#include <asm/unistd.h> 90#include <asm/unistd.h>
91 91
92#include <net/compat.h> 92#include <net/compat.h>
93#include <net/wext.h>
93 94
94#include <net/sock.h> 95#include <net/sock.h>
95#include <linux/netfilter.h> 96#include <linux/netfilter.h>
@@ -179,9 +180,9 @@ static DEFINE_PER_CPU(int, sockets_in_use) = 0;
179 * invalid addresses -EFAULT is returned. On a success 0 is returned. 180 * invalid addresses -EFAULT is returned. On a success 0 is returned.
180 */ 181 */
181 182
182int move_addr_to_kernel(void __user *uaddr, int ulen, void *kaddr) 183int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr *kaddr)
183{ 184{
184 if (ulen < 0 || ulen > MAX_SOCK_ADDR) 185 if (ulen < 0 || ulen > sizeof(struct sockaddr_storage))
185 return -EINVAL; 186 return -EINVAL;
186 if (ulen == 0) 187 if (ulen == 0)
187 return 0; 188 return 0;
@@ -207,7 +208,7 @@ int move_addr_to_kernel(void __user *uaddr, int ulen, void *kaddr)
207 * specified. Zero is returned for a success. 208 * specified. Zero is returned for a success.
208 */ 209 */
209 210
210int move_addr_to_user(void *kaddr, int klen, void __user *uaddr, 211int move_addr_to_user(struct sockaddr *kaddr, int klen, void __user *uaddr,
211 int __user *ulen) 212 int __user *ulen)
212{ 213{
213 int err; 214 int err;
@@ -218,7 +219,7 @@ int move_addr_to_user(void *kaddr, int klen, void __user *uaddr,
218 return err; 219 return err;
219 if (len > klen) 220 if (len > klen)
220 len = klen; 221 len = klen;
221 if (len < 0 || len > MAX_SOCK_ADDR) 222 if (len < 0 || len > sizeof(struct sockaddr_storage))
222 return -EINVAL; 223 return -EINVAL;
223 if (len) { 224 if (len) {
224 if (audit_sockaddr(klen, kaddr)) 225 if (audit_sockaddr(klen, kaddr))
@@ -1341,20 +1342,20 @@ out_fd:
1341asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen) 1342asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)
1342{ 1343{
1343 struct socket *sock; 1344 struct socket *sock;
1344 char address[MAX_SOCK_ADDR]; 1345 struct sockaddr_storage address;
1345 int err, fput_needed; 1346 int err, fput_needed;
1346 1347
1347 sock = sockfd_lookup_light(fd, &err, &fput_needed); 1348 sock = sockfd_lookup_light(fd, &err, &fput_needed);
1348 if (sock) { 1349 if (sock) {
1349 err = move_addr_to_kernel(umyaddr, addrlen, address); 1350 err = move_addr_to_kernel(umyaddr, addrlen, (struct sockaddr *)&address);
1350 if (err >= 0) { 1351 if (err >= 0) {
1351 err = security_socket_bind(sock, 1352 err = security_socket_bind(sock,
1352 (struct sockaddr *)address, 1353 (struct sockaddr *)&address,
1353 addrlen); 1354 addrlen);
1354 if (!err) 1355 if (!err)
1355 err = sock->ops->bind(sock, 1356 err = sock->ops->bind(sock,
1356 (struct sockaddr *) 1357 (struct sockaddr *)
1357 address, addrlen); 1358 &address, addrlen);
1358 } 1359 }
1359 fput_light(sock->file, fput_needed); 1360 fput_light(sock->file, fput_needed);
1360 } 1361 }
@@ -1406,7 +1407,7 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,
1406 struct socket *sock, *newsock; 1407 struct socket *sock, *newsock;
1407 struct file *newfile; 1408 struct file *newfile;
1408 int err, len, newfd, fput_needed; 1409 int err, len, newfd, fput_needed;
1409 char address[MAX_SOCK_ADDR]; 1410 struct sockaddr_storage address;
1410 1411
1411 sock = sockfd_lookup_light(fd, &err, &fput_needed); 1412 sock = sockfd_lookup_light(fd, &err, &fput_needed);
1412 if (!sock) 1413 if (!sock)
@@ -1445,13 +1446,13 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,
1445 goto out_fd; 1446 goto out_fd;
1446 1447
1447 if (upeer_sockaddr) { 1448 if (upeer_sockaddr) {
1448 if (newsock->ops->getname(newsock, (struct sockaddr *)address, 1449 if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
1449 &len, 2) < 0) { 1450 &len, 2) < 0) {
1450 err = -ECONNABORTED; 1451 err = -ECONNABORTED;
1451 goto out_fd; 1452 goto out_fd;
1452 } 1453 }
1453 err = move_addr_to_user(address, len, upeer_sockaddr, 1454 err = move_addr_to_user((struct sockaddr *)&address,
1454 upeer_addrlen); 1455 len, upeer_sockaddr, upeer_addrlen);
1455 if (err < 0) 1456 if (err < 0)
1456 goto out_fd; 1457 goto out_fd;
1457 } 1458 }
@@ -1494,22 +1495,22 @@ asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr,
1494 int addrlen) 1495 int addrlen)
1495{ 1496{
1496 struct socket *sock; 1497 struct socket *sock;
1497 char address[MAX_SOCK_ADDR]; 1498 struct sockaddr_storage address;
1498 int err, fput_needed; 1499 int err, fput_needed;
1499 1500
1500 sock = sockfd_lookup_light(fd, &err, &fput_needed); 1501 sock = sockfd_lookup_light(fd, &err, &fput_needed);
1501 if (!sock) 1502 if (!sock)
1502 goto out; 1503 goto out;
1503 err = move_addr_to_kernel(uservaddr, addrlen, address); 1504 err = move_addr_to_kernel(uservaddr, addrlen, (struct sockaddr *)&address);
1504 if (err < 0) 1505 if (err < 0)
1505 goto out_put; 1506 goto out_put;
1506 1507
1507 err = 1508 err =
1508 security_socket_connect(sock, (struct sockaddr *)address, addrlen); 1509 security_socket_connect(sock, (struct sockaddr *)&address, addrlen);
1509 if (err) 1510 if (err)
1510 goto out_put; 1511 goto out_put;
1511 1512
1512 err = sock->ops->connect(sock, (struct sockaddr *)address, addrlen, 1513 err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,
1513 sock->file->f_flags); 1514 sock->file->f_flags);
1514out_put: 1515out_put:
1515 fput_light(sock->file, fput_needed); 1516 fput_light(sock->file, fput_needed);
@@ -1526,7 +1527,7 @@ asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr,
1526 int __user *usockaddr_len) 1527 int __user *usockaddr_len)
1527{ 1528{
1528 struct socket *sock; 1529 struct socket *sock;
1529 char address[MAX_SOCK_ADDR]; 1530 struct sockaddr_storage address;
1530 int len, err, fput_needed; 1531 int len, err, fput_needed;
1531 1532
1532 sock = sockfd_lookup_light(fd, &err, &fput_needed); 1533 sock = sockfd_lookup_light(fd, &err, &fput_needed);
@@ -1537,10 +1538,10 @@ asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr,
1537 if (err) 1538 if (err)
1538 goto out_put; 1539 goto out_put;
1539 1540
1540 err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 0); 1541 err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0);
1541 if (err) 1542 if (err)
1542 goto out_put; 1543 goto out_put;
1543 err = move_addr_to_user(address, len, usockaddr, usockaddr_len); 1544 err = move_addr_to_user((struct sockaddr *)&address, len, usockaddr, usockaddr_len);
1544 1545
1545out_put: 1546out_put:
1546 fput_light(sock->file, fput_needed); 1547 fput_light(sock->file, fput_needed);
@@ -1557,7 +1558,7 @@ asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr,
1557 int __user *usockaddr_len) 1558 int __user *usockaddr_len)
1558{ 1559{
1559 struct socket *sock; 1560 struct socket *sock;
1560 char address[MAX_SOCK_ADDR]; 1561 struct sockaddr_storage address;
1561 int len, err, fput_needed; 1562 int len, err, fput_needed;
1562 1563
1563 sock = sockfd_lookup_light(fd, &err, &fput_needed); 1564 sock = sockfd_lookup_light(fd, &err, &fput_needed);
@@ -1569,10 +1570,10 @@ asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr,
1569 } 1570 }
1570 1571
1571 err = 1572 err =
1572 sock->ops->getname(sock, (struct sockaddr *)address, &len, 1573 sock->ops->getname(sock, (struct sockaddr *)&address, &len,
1573 1); 1574 1);
1574 if (!err) 1575 if (!err)
1575 err = move_addr_to_user(address, len, usockaddr, 1576 err = move_addr_to_user((struct sockaddr *)&address, len, usockaddr,
1576 usockaddr_len); 1577 usockaddr_len);
1577 fput_light(sock->file, fput_needed); 1578 fput_light(sock->file, fput_needed);
1578 } 1579 }
@@ -1590,7 +1591,7 @@ asmlinkage long sys_sendto(int fd, void __user *buff, size_t len,
1590 int addr_len) 1591 int addr_len)
1591{ 1592{
1592 struct socket *sock; 1593 struct socket *sock;
1593 char address[MAX_SOCK_ADDR]; 1594 struct sockaddr_storage address;
1594 int err; 1595 int err;
1595 struct msghdr msg; 1596 struct msghdr msg;
1596 struct iovec iov; 1597 struct iovec iov;
@@ -1609,10 +1610,10 @@ asmlinkage long sys_sendto(int fd, void __user *buff, size_t len,
1609 msg.msg_controllen = 0; 1610 msg.msg_controllen = 0;
1610 msg.msg_namelen = 0; 1611 msg.msg_namelen = 0;
1611 if (addr) { 1612 if (addr) {
1612 err = move_addr_to_kernel(addr, addr_len, address); 1613 err = move_addr_to_kernel(addr, addr_len, (struct sockaddr *)&address);
1613 if (err < 0) 1614 if (err < 0)
1614 goto out_put; 1615 goto out_put;
1615 msg.msg_name = address; 1616 msg.msg_name = (struct sockaddr *)&address;
1616 msg.msg_namelen = addr_len; 1617 msg.msg_namelen = addr_len;
1617 } 1618 }
1618 if (sock->file->f_flags & O_NONBLOCK) 1619 if (sock->file->f_flags & O_NONBLOCK)
@@ -1648,7 +1649,7 @@ asmlinkage long sys_recvfrom(int fd, void __user *ubuf, size_t size,
1648 struct socket *sock; 1649 struct socket *sock;
1649 struct iovec iov; 1650 struct iovec iov;
1650 struct msghdr msg; 1651 struct msghdr msg;
1651 char address[MAX_SOCK_ADDR]; 1652 struct sockaddr_storage address;
1652 int err, err2; 1653 int err, err2;
1653 int fput_needed; 1654 int fput_needed;
1654 1655
@@ -1662,14 +1663,15 @@ asmlinkage long sys_recvfrom(int fd, void __user *ubuf, size_t size,
1662 msg.msg_iov = &iov; 1663 msg.msg_iov = &iov;
1663 iov.iov_len = size; 1664 iov.iov_len = size;
1664 iov.iov_base = ubuf; 1665 iov.iov_base = ubuf;
1665 msg.msg_name = address; 1666 msg.msg_name = (struct sockaddr *)&address;
1666 msg.msg_namelen = MAX_SOCK_ADDR; 1667 msg.msg_namelen = sizeof(address);
1667 if (sock->file->f_flags & O_NONBLOCK) 1668 if (sock->file->f_flags & O_NONBLOCK)
1668 flags |= MSG_DONTWAIT; 1669 flags |= MSG_DONTWAIT;
1669 err = sock_recvmsg(sock, &msg, size, flags); 1670 err = sock_recvmsg(sock, &msg, size, flags);
1670 1671
1671 if (err >= 0 && addr != NULL) { 1672 if (err >= 0 && addr != NULL) {
1672 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);
1673 if (err2 < 0) 1675 if (err2 < 0)
1674 err = err2; 1676 err = err2;
1675 } 1677 }
@@ -1789,7 +1791,7 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
1789 struct compat_msghdr __user *msg_compat = 1791 struct compat_msghdr __user *msg_compat =
1790 (struct compat_msghdr __user *)msg; 1792 (struct compat_msghdr __user *)msg;
1791 struct socket *sock; 1793 struct socket *sock;
1792 char address[MAX_SOCK_ADDR]; 1794 struct sockaddr_storage address;
1793 struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; 1795 struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
1794 unsigned char ctl[sizeof(struct cmsghdr) + 20] 1796 unsigned char ctl[sizeof(struct cmsghdr) + 20]
1795 __attribute__ ((aligned(sizeof(__kernel_size_t)))); 1797 __attribute__ ((aligned(sizeof(__kernel_size_t))));
@@ -1827,9 +1829,13 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
1827 1829
1828 /* This will also move the address data into kernel space */ 1830 /* This will also move the address data into kernel space */
1829 if (MSG_CMSG_COMPAT & flags) { 1831 if (MSG_CMSG_COMPAT & flags) {
1830 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);
1831 } else 1835 } else
1832 err = verify_iovec(&msg_sys, iov, address, VERIFY_READ); 1836 err = verify_iovec(&msg_sys, iov,
1837 (struct sockaddr *)&address,
1838 VERIFY_READ);
1833 if (err < 0) 1839 if (err < 0)
1834 goto out_freeiov; 1840 goto out_freeiov;
1835 total_len = err; 1841 total_len = err;
@@ -1900,7 +1906,7 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg,
1900 int fput_needed; 1906 int fput_needed;
1901 1907
1902 /* kernel mode address */ 1908 /* kernel mode address */
1903 char addr[MAX_SOCK_ADDR]; 1909 struct sockaddr_storage addr;
1904 1910
1905 /* user mode address pointers */ 1911 /* user mode address pointers */
1906 struct sockaddr __user *uaddr; 1912 struct sockaddr __user *uaddr;
@@ -1938,9 +1944,13 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg,
1938 uaddr = (__force void __user *)msg_sys.msg_name; 1944 uaddr = (__force void __user *)msg_sys.msg_name;
1939 uaddr_len = COMPAT_NAMELEN(msg); 1945 uaddr_len = COMPAT_NAMELEN(msg);
1940 if (MSG_CMSG_COMPAT & flags) { 1946 if (MSG_CMSG_COMPAT & flags) {
1941 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);
1942 } else 1950 } else
1943 err = verify_iovec(&msg_sys, iov, addr, VERIFY_WRITE); 1951 err = verify_iovec(&msg_sys, iov,
1952 (struct sockaddr *)&addr,
1953 VERIFY_WRITE);
1944 if (err < 0) 1954 if (err < 0)
1945 goto out_freeiov; 1955 goto out_freeiov;
1946 total_len = err; 1956 total_len = err;
@@ -1956,7 +1966,8 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg,
1956 len = err; 1966 len = err;
1957 1967
1958 if (uaddr != NULL) { 1968 if (uaddr != NULL) {
1959 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,
1960 uaddr_len); 1971 uaddr_len);
1961 if (err < 0) 1972 if (err < 0)
1962 goto out_freeiov; 1973 goto out_freeiov;
@@ -2210,10 +2221,19 @@ static long compat_sock_ioctl(struct file *file, unsigned cmd,
2210{ 2221{
2211 struct socket *sock = file->private_data; 2222 struct socket *sock = file->private_data;
2212 int ret = -ENOIOCTLCMD; 2223 int ret = -ENOIOCTLCMD;
2224 struct sock *sk;
2225 struct net *net;
2226
2227 sk = sock->sk;
2228 net = sock_net(sk);
2213 2229
2214 if (sock->ops->compat_ioctl) 2230 if (sock->ops->compat_ioctl)
2215 ret = sock->ops->compat_ioctl(sock, cmd, arg); 2231 ret = sock->ops->compat_ioctl(sock, cmd, arg);
2216 2232
2233 if (ret == -ENOIOCTLCMD &&
2234 (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST))
2235 ret = compat_wext_handle_ioctl(net, cmd, arg);
2236
2217 return ret; 2237 return ret;
2218} 2238}
2219#endif 2239#endif