diff options
| author | Andi Kleen <ak@linux.intel.com> | 2008-07-21 18:16:54 -0400 |
|---|---|---|
| committer | Andi Kleen <ak@linux.intel.com> | 2008-07-21 18:16:54 -0400 |
| commit | 8294fafdafc602ed11f401c44628fab8558c5cf5 (patch) | |
| tree | c8d0371cfd05226b56d52bfde9c69f8caca4501d /net/socket.c | |
| parent | 725c3a2d70f958adee807c178178819a50f68a56 (diff) | |
| parent | bf20e740a4bcc686de02e2fd1c1810a58872f46e (diff) | |
Merge branch 'for-upstream/acpi-test' of git://repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6 into release-2.6.27
Diffstat (limited to 'net/socket.c')
| -rw-r--r-- | net/socket.c | 92 |
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 | ||
| 182 | 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) |
| 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 | ||
| 210 | 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, |
| 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: | |||
| 1341 | 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) |
| 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); |
| 1514 | out_put: | 1515 | out_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 | ||
| 1545 | out_put: | 1546 | out_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 |
