aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/socket.h6
-rw-r--r--include/net/compat.h2
-rw-r--r--net/compat.c2
-rw-r--r--net/core/iovec.c2
-rw-r--r--net/socket.c82
5 files changed, 52 insertions, 42 deletions
diff --git a/include/linux/socket.h b/include/linux/socket.h
index bd2b30a74e76..950af631e7fb 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -306,10 +306,10 @@ extern int csum_partial_copy_fromiovecend(unsigned char *kdata,
306 int offset, 306 int offset,
307 unsigned int len, __wsum *csump); 307 unsigned int len, __wsum *csump);
308 308
309extern int verify_iovec(struct msghdr *m, struct iovec *iov, char *address, int mode); 309extern int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode);
310extern int memcpy_toiovec(struct iovec *v, unsigned char *kdata, int len); 310extern int memcpy_toiovec(struct iovec *v, unsigned char *kdata, int len);
311extern int move_addr_to_user(void *kaddr, int klen, void __user *uaddr, int __user *ulen); 311extern int move_addr_to_user(struct sockaddr *kaddr, int klen, void __user *uaddr, int __user *ulen);
312extern int move_addr_to_kernel(void __user *uaddr, int ulen, void *kaddr); 312extern int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr *kaddr);
313extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data); 313extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data);
314 314
315#endif 315#endif
diff --git a/include/net/compat.h b/include/net/compat.h
index 164cb682e220..5bbf8bf9efea 100644
--- a/include/net/compat.h
+++ b/include/net/compat.h
@@ -32,7 +32,7 @@ extern int compat_sock_get_timestampns(struct sock *, struct timespec __user *);
32#endif /* defined(CONFIG_COMPAT) */ 32#endif /* defined(CONFIG_COMPAT) */
33 33
34extern int get_compat_msghdr(struct msghdr *, struct compat_msghdr __user *); 34extern int get_compat_msghdr(struct msghdr *, struct compat_msghdr __user *);
35extern int verify_compat_iovec(struct msghdr *, struct iovec *, char *, int); 35extern int verify_compat_iovec(struct msghdr *, struct iovec *, struct sockaddr *, int);
36extern asmlinkage long compat_sys_sendmsg(int,struct compat_msghdr __user *,unsigned); 36extern asmlinkage long compat_sys_sendmsg(int,struct compat_msghdr __user *,unsigned);
37extern asmlinkage long compat_sys_recvmsg(int,struct compat_msghdr __user *,unsigned); 37extern asmlinkage long compat_sys_recvmsg(int,struct compat_msghdr __user *,unsigned);
38extern asmlinkage long compat_sys_getsockopt(int, int, int, char __user *, int __user *); 38extern asmlinkage long compat_sys_getsockopt(int, int, int, char __user *, int __user *);
diff --git a/net/compat.c b/net/compat.c
index c823f6f290cb..6e1b03b51933 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -75,7 +75,7 @@ int get_compat_msghdr(struct msghdr *kmsg, struct compat_msghdr __user *umsg)
75 75
76/* I've named the args so it is easy to tell whose space the pointers are in. */ 76/* I've named the args so it is easy to tell whose space the pointers are in. */
77int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov, 77int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov,
78 char *kern_address, int mode) 78 struct sockaddr *kern_address, int mode)
79{ 79{
80 int tot_len; 80 int tot_len;
81 81
diff --git a/net/core/iovec.c b/net/core/iovec.c
index 755c37fdaee7..4c9c0121c9da 100644
--- a/net/core/iovec.c
+++ b/net/core/iovec.c
@@ -36,7 +36,7 @@
36 * in any case. 36 * in any case.
37 */ 37 */
38 38
39int verify_iovec(struct msghdr *m, struct iovec *iov, char *address, int mode) 39int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode)
40{ 40{
41 int size, err, ct; 41 int size, err, ct;
42 42
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
183int move_addr_to_kernel(void __user *uaddr, int ulen, void *kaddr) 183int 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
211int move_addr_to_user(void *kaddr, int klen, void __user *uaddr, 211int 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:
1342asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen) 1342asmlinkage 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);
1515out_put: 1515out_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
1546out_put: 1546out_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;