aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-11-21 12:17:35 -0500
committerDavid S. Miller <davem@davemloft.net>2014-11-21 12:17:35 -0500
commit675a53bd689c217bbe2736c09a57e10f95c686a7 (patch)
tree9f4f3c1f4fac484e6994f88ea383d8af93be2bfd
parentabd40774132b8dd474ee0ac1532df1af843ada59 (diff)
parent232365f660b0016dcf618723707f91f4a95013db (diff)
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
-rw-r--r--arch/arm/kernel/sys_oabi-compat.c4
-rw-r--r--include/linux/socket.h17
-rw-r--r--include/linux/syscalls.h6
-rw-r--r--include/net/compat.h5
-rw-r--r--include/net/sock.h23
-rw-r--r--net/compat.c83
-rw-r--r--net/core/iovec.c47
-rw-r--r--net/socket.c140
8 files changed, 114 insertions, 211 deletions
diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c
index e90a3148f385..b83f3b7737fb 100644
--- a/arch/arm/kernel/sys_oabi-compat.c
+++ b/arch/arm/kernel/sys_oabi-compat.c
@@ -400,7 +400,7 @@ asmlinkage long sys_oabi_sendto(int fd, void __user *buff,
400 return sys_sendto(fd, buff, len, flags, addr, addrlen); 400 return sys_sendto(fd, buff, len, flags, addr, addrlen);
401} 401}
402 402
403asmlinkage long sys_oabi_sendmsg(int fd, struct msghdr __user *msg, unsigned flags) 403asmlinkage long sys_oabi_sendmsg(int fd, struct user_msghdr __user *msg, unsigned flags)
404{ 404{
405 struct sockaddr __user *addr; 405 struct sockaddr __user *addr;
406 int msg_namelen; 406 int msg_namelen;
@@ -446,7 +446,7 @@ asmlinkage long sys_oabi_socketcall(int call, unsigned long __user *args)
446 break; 446 break;
447 case SYS_SENDMSG: 447 case SYS_SENDMSG:
448 if (copy_from_user(a, args, 3 * sizeof(long)) == 0) 448 if (copy_from_user(a, args, 3 * sizeof(long)) == 0)
449 r = sys_oabi_sendmsg(a[0], (struct msghdr __user *)a[1], a[2]); 449 r = sys_oabi_sendmsg(a[0], (struct user_msghdr __user *)a[1], a[2]);
450 break; 450 break;
451 default: 451 default:
452 r = sys_socketcall(call, args); 452 r = sys_socketcall(call, args);
diff --git a/include/linux/socket.h b/include/linux/socket.h
index bb9b83640070..de5222832be4 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -53,10 +53,20 @@ struct msghdr {
53 __kernel_size_t msg_controllen; /* ancillary data buffer length */ 53 __kernel_size_t msg_controllen; /* ancillary data buffer length */
54 unsigned int msg_flags; /* flags on received message */ 54 unsigned int msg_flags; /* flags on received message */
55}; 55};
56
57struct user_msghdr {
58 void __user *msg_name; /* ptr to socket address structure */
59 int msg_namelen; /* size of socket address structure */
60 struct iovec __user *msg_iov; /* scatter/gather array */
61 __kernel_size_t msg_iovlen; /* # elements in msg_iov */
62 void __user *msg_control; /* ancillary data */
63 __kernel_size_t msg_controllen; /* ancillary data buffer length */
64 unsigned int msg_flags; /* flags on received message */
65};
56 66
57/* For recvmmsg/sendmmsg */ 67/* For recvmmsg/sendmmsg */
58struct mmsghdr { 68struct mmsghdr {
59 struct msghdr msg_hdr; 69 struct user_msghdr msg_hdr;
60 unsigned int msg_len; 70 unsigned int msg_len;
61}; 71};
62 72
@@ -312,15 +322,14 @@ extern int csum_partial_copy_fromiovecend(unsigned char *kdata,
312extern unsigned long iov_pages(const struct iovec *iov, int offset, 322extern unsigned long iov_pages(const struct iovec *iov, int offset,
313 unsigned long nr_segs); 323 unsigned long nr_segs);
314 324
315extern int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *address, int mode);
316extern int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr); 325extern int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr);
317extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data); 326extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data);
318 327
319struct timespec; 328struct timespec;
320 329
321/* The __sys_...msg variants allow MSG_CMSG_COMPAT */ 330/* The __sys_...msg variants allow MSG_CMSG_COMPAT */
322extern long __sys_recvmsg(int fd, struct msghdr __user *msg, unsigned flags); 331extern long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned flags);
323extern long __sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags); 332extern long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned flags);
324extern int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, 333extern int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
325 unsigned int flags, struct timespec *timeout); 334 unsigned int flags, struct timespec *timeout);
326extern int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, 335extern int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg,
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index bda9b81357cc..c9afdc7a7f84 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -25,7 +25,7 @@ struct linux_dirent64;
25struct list_head; 25struct list_head;
26struct mmap_arg_struct; 26struct mmap_arg_struct;
27struct msgbuf; 27struct msgbuf;
28struct msghdr; 28struct user_msghdr;
29struct mmsghdr; 29struct mmsghdr;
30struct msqid_ds; 30struct msqid_ds;
31struct new_utsname; 31struct new_utsname;
@@ -601,13 +601,13 @@ asmlinkage long sys_getpeername(int, struct sockaddr __user *, int __user *);
601asmlinkage long sys_send(int, void __user *, size_t, unsigned); 601asmlinkage long sys_send(int, void __user *, size_t, unsigned);
602asmlinkage long sys_sendto(int, void __user *, size_t, unsigned, 602asmlinkage long sys_sendto(int, void __user *, size_t, unsigned,
603 struct sockaddr __user *, int); 603 struct sockaddr __user *, int);
604asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags); 604asmlinkage long sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned flags);
605asmlinkage long sys_sendmmsg(int fd, struct mmsghdr __user *msg, 605asmlinkage long sys_sendmmsg(int fd, struct mmsghdr __user *msg,
606 unsigned int vlen, unsigned flags); 606 unsigned int vlen, unsigned flags);
607asmlinkage long sys_recv(int, void __user *, size_t, unsigned); 607asmlinkage long sys_recv(int, void __user *, size_t, unsigned);
608asmlinkage long sys_recvfrom(int, void __user *, size_t, unsigned, 608asmlinkage long sys_recvfrom(int, void __user *, size_t, unsigned,
609 struct sockaddr __user *, int __user *); 609 struct sockaddr __user *, int __user *);
610asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned flags); 610asmlinkage long sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned flags);
611asmlinkage long sys_recvmmsg(int fd, struct mmsghdr __user *msg, 611asmlinkage long sys_recvmmsg(int fd, struct mmsghdr __user *msg,
612 unsigned int vlen, unsigned flags, 612 unsigned int vlen, unsigned flags,
613 struct timespec __user *timeout); 613 struct timespec __user *timeout);
diff --git a/include/net/compat.h b/include/net/compat.h
index 3b603b199c01..42a9c8431177 100644
--- a/include/net/compat.h
+++ b/include/net/compat.h
@@ -40,9 +40,8 @@ int compat_sock_get_timestampns(struct sock *, struct timespec __user *);
40#define compat_mmsghdr mmsghdr 40#define compat_mmsghdr mmsghdr
41#endif /* defined(CONFIG_COMPAT) */ 41#endif /* defined(CONFIG_COMPAT) */
42 42
43int get_compat_msghdr(struct msghdr *, struct compat_msghdr __user *); 43ssize_t get_compat_msghdr(struct msghdr *, struct compat_msghdr __user *,
44int verify_compat_iovec(struct msghdr *, struct iovec *, 44 struct sockaddr __user **, struct iovec **);
45 struct sockaddr_storage *, int);
46asmlinkage long compat_sys_sendmsg(int, struct compat_msghdr __user *, 45asmlinkage long compat_sys_sendmsg(int, struct compat_msghdr __user *,
47 unsigned int); 46 unsigned int);
48asmlinkage long compat_sys_sendmmsg(int, struct compat_mmsghdr __user *, 47asmlinkage long compat_sys_sendmmsg(int, struct compat_mmsghdr __user *,
diff --git a/include/net/sock.h b/include/net/sock.h
index 83a669f83bae..df9b89bce8ff 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1884,29 +1884,6 @@ static inline int skb_copy_to_page_nocache(struct sock *sk, char __user *from,
1884 return 0; 1884 return 0;
1885} 1885}
1886 1886
1887static inline int skb_copy_to_page(struct sock *sk, char __user *from,
1888 struct sk_buff *skb, struct page *page,
1889 int off, int copy)
1890{
1891 if (skb->ip_summed == CHECKSUM_NONE) {
1892 int err = 0;
1893 __wsum csum = csum_and_copy_from_user(from,
1894 page_address(page) + off,
1895 copy, 0, &err);
1896 if (err)
1897 return err;
1898 skb->csum = csum_block_add(skb->csum, csum, skb->len);
1899 } else if (copy_from_user(page_address(page) + off, from, copy))
1900 return -EFAULT;
1901
1902 skb->len += copy;
1903 skb->data_len += copy;
1904 skb->truesize += copy;
1905 sk->sk_wmem_queued += copy;
1906 sk_mem_charge(sk, copy);
1907 return 0;
1908}
1909
1910/** 1887/**
1911 * sk_wmem_alloc_get - returns write allocations 1888 * sk_wmem_alloc_get - returns write allocations
1912 * @sk: socket 1889 * @sk: socket
diff --git a/net/compat.c b/net/compat.c
index bc8aeefddf3f..062f157d2a6b 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -31,41 +31,18 @@
31#include <asm/uaccess.h> 31#include <asm/uaccess.h>
32#include <net/compat.h> 32#include <net/compat.h>
33 33
34static inline int iov_from_user_compat_to_kern(struct iovec *kiov, 34ssize_t get_compat_msghdr(struct msghdr *kmsg,
35 struct compat_iovec __user *uiov32, 35 struct compat_msghdr __user *umsg,
36 int niov) 36 struct sockaddr __user **save_addr,
37 struct iovec **iov)
37{ 38{
38 int tot_len = 0; 39 compat_uptr_t uaddr, uiov, tmp3;
39 40 ssize_t err;
40 while (niov > 0) {
41 compat_uptr_t buf;
42 compat_size_t len;
43
44 if (get_user(len, &uiov32->iov_len) ||
45 get_user(buf, &uiov32->iov_base))
46 return -EFAULT;
47
48 if (len > INT_MAX - tot_len)
49 len = INT_MAX - tot_len;
50
51 tot_len += len;
52 kiov->iov_base = compat_ptr(buf);
53 kiov->iov_len = (__kernel_size_t) len;
54 uiov32++;
55 kiov++;
56 niov--;
57 }
58 return tot_len;
59}
60
61int get_compat_msghdr(struct msghdr *kmsg, struct compat_msghdr __user *umsg)
62{
63 compat_uptr_t tmp1, tmp2, tmp3;
64 41
65 if (!access_ok(VERIFY_READ, umsg, sizeof(*umsg)) || 42 if (!access_ok(VERIFY_READ, umsg, sizeof(*umsg)) ||
66 __get_user(tmp1, &umsg->msg_name) || 43 __get_user(uaddr, &umsg->msg_name) ||
67 __get_user(kmsg->msg_namelen, &umsg->msg_namelen) || 44 __get_user(kmsg->msg_namelen, &umsg->msg_namelen) ||
68 __get_user(tmp2, &umsg->msg_iov) || 45 __get_user(uiov, &umsg->msg_iov) ||
69 __get_user(kmsg->msg_iovlen, &umsg->msg_iovlen) || 46 __get_user(kmsg->msg_iovlen, &umsg->msg_iovlen) ||
70 __get_user(tmp3, &umsg->msg_control) || 47 __get_user(tmp3, &umsg->msg_control) ||
71 __get_user(kmsg->msg_controllen, &umsg->msg_controllen) || 48 __get_user(kmsg->msg_controllen, &umsg->msg_controllen) ||
@@ -73,39 +50,33 @@ int get_compat_msghdr(struct msghdr *kmsg, struct compat_msghdr __user *umsg)
73 return -EFAULT; 50 return -EFAULT;
74 if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) 51 if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
75 kmsg->msg_namelen = sizeof(struct sockaddr_storage); 52 kmsg->msg_namelen = sizeof(struct sockaddr_storage);
76 kmsg->msg_name = compat_ptr(tmp1);
77 kmsg->msg_iov = compat_ptr(tmp2);
78 kmsg->msg_control = compat_ptr(tmp3); 53 kmsg->msg_control = compat_ptr(tmp3);
79 return 0;
80}
81 54
82/* I've named the args so it is easy to tell whose space the pointers are in. */ 55 if (save_addr)
83int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov, 56 *save_addr = compat_ptr(uaddr);
84 struct sockaddr_storage *kern_address, int mode)
85{
86 int tot_len;
87 57
88 if (kern_msg->msg_name && kern_msg->msg_namelen) { 58 if (uaddr && kmsg->msg_namelen) {
89 if (mode == VERIFY_READ) { 59 if (!save_addr) {
90 int err = move_addr_to_kernel(kern_msg->msg_name, 60 err = move_addr_to_kernel(compat_ptr(uaddr),
91 kern_msg->msg_namelen, 61 kmsg->msg_namelen,
92 kern_address); 62 kmsg->msg_name);
93 if (err < 0) 63 if (err < 0)
94 return err; 64 return err;
95 } 65 }
96 kern_msg->msg_name = kern_address;
97 } else { 66 } else {
98 kern_msg->msg_name = NULL; 67 kmsg->msg_name = NULL;
99 kern_msg->msg_namelen = 0; 68 kmsg->msg_namelen = 0;
100 } 69 }
101 70
102 tot_len = iov_from_user_compat_to_kern(kern_iov, 71 if (kmsg->msg_iovlen > UIO_MAXIOV)
103 (struct compat_iovec __user *)kern_msg->msg_iov, 72 return -EMSGSIZE;
104 kern_msg->msg_iovlen);
105 if (tot_len >= 0)
106 kern_msg->msg_iov = kern_iov;
107 73
108 return tot_len; 74 err = compat_rw_copy_check_uvector(save_addr ? READ : WRITE,
75 compat_ptr(uiov), kmsg->msg_iovlen,
76 UIO_FASTIOV, *iov, iov);
77 if (err >= 0)
78 kmsg->msg_iov = *iov;
79 return err;
109} 80}
110 81
111/* Bleech... */ 82/* Bleech... */
@@ -740,7 +711,7 @@ COMPAT_SYSCALL_DEFINE3(sendmsg, int, fd, struct compat_msghdr __user *, msg, uns
740{ 711{
741 if (flags & MSG_CMSG_COMPAT) 712 if (flags & MSG_CMSG_COMPAT)
742 return -EINVAL; 713 return -EINVAL;
743 return __sys_sendmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); 714 return __sys_sendmsg(fd, (struct user_msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
744} 715}
745 716
746COMPAT_SYSCALL_DEFINE4(sendmmsg, int, fd, struct compat_mmsghdr __user *, mmsg, 717COMPAT_SYSCALL_DEFINE4(sendmmsg, int, fd, struct compat_mmsghdr __user *, mmsg,
@@ -756,7 +727,7 @@ COMPAT_SYSCALL_DEFINE3(recvmsg, int, fd, struct compat_msghdr __user *, msg, uns
756{ 727{
757 if (flags & MSG_CMSG_COMPAT) 728 if (flags & MSG_CMSG_COMPAT)
758 return -EINVAL; 729 return -EINVAL;
759 return __sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); 730 return __sys_recvmsg(fd, (struct user_msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
760} 731}
761 732
762COMPAT_SYSCALL_DEFINE4(recv, int, fd, void __user *, buf, compat_size_t, len, unsigned int, flags) 733COMPAT_SYSCALL_DEFINE4(recv, int, fd, void __user *, buf, compat_size_t, len, unsigned int, flags)
diff --git a/net/core/iovec.c b/net/core/iovec.c
index e1ec45ab1e63..dcbe98b3726a 100644
--- a/net/core/iovec.c
+++ b/net/core/iovec.c
@@ -28,53 +28,6 @@
28#include <net/sock.h> 28#include <net/sock.h>
29 29
30/* 30/*
31 * Verify iovec. The caller must ensure that the iovec is big enough
32 * to hold the message iovec.
33 *
34 * Save time not doing access_ok. copy_*_user will make this work
35 * in any case.
36 */
37
38int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *address, int mode)
39{
40 int size, ct, err;
41
42 if (m->msg_name && m->msg_namelen) {
43 if (mode == VERIFY_READ) {
44 void __user *namep;
45 namep = (void __user __force *) m->msg_name;
46 err = move_addr_to_kernel(namep, m->msg_namelen,
47 address);
48 if (err < 0)
49 return err;
50 }
51 m->msg_name = address;
52 } else {
53 m->msg_name = NULL;
54 m->msg_namelen = 0;
55 }
56
57 size = m->msg_iovlen * sizeof(struct iovec);
58 if (copy_from_user(iov, (void __user __force *) m->msg_iov, size))
59 return -EFAULT;
60
61 m->msg_iov = iov;
62 err = 0;
63
64 for (ct = 0; ct < m->msg_iovlen; ct++) {
65 size_t len = iov[ct].iov_len;
66
67 if (len > INT_MAX - err) {
68 len = INT_MAX - err;
69 iov[ct].iov_len = len;
70 }
71 err += len;
72 }
73
74 return err;
75}
76
77/*
78 * And now for the all-in-one: copy and checksum from a user iovec 31 * And now for the all-in-one: copy and checksum from a user iovec
79 * directly to a datagram 32 * directly to a datagram
80 * Calls to csum_partial but the last must be in 32 bit chunks 33 * Calls to csum_partial but the last must be in 32 bit chunks
diff --git a/net/socket.c b/net/socket.c
index fe20c319a0bb..ee3ee39eefa5 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1988,13 +1988,26 @@ struct used_address {
1988 unsigned int name_len; 1988 unsigned int name_len;
1989}; 1989};
1990 1990
1991static int copy_msghdr_from_user(struct msghdr *kmsg, 1991static ssize_t copy_msghdr_from_user(struct msghdr *kmsg,
1992 struct msghdr __user *umsg) 1992 struct user_msghdr __user *umsg,
1993 struct sockaddr __user **save_addr,
1994 struct iovec **iov)
1993{ 1995{
1994 if (copy_from_user(kmsg, umsg, sizeof(struct msghdr))) 1996 struct sockaddr __user *uaddr;
1997 struct iovec __user *uiov;
1998 ssize_t err;
1999
2000 if (!access_ok(VERIFY_READ, umsg, sizeof(*umsg)) ||
2001 __get_user(uaddr, &umsg->msg_name) ||
2002 __get_user(kmsg->msg_namelen, &umsg->msg_namelen) ||
2003 __get_user(uiov, &umsg->msg_iov) ||
2004 __get_user(kmsg->msg_iovlen, &umsg->msg_iovlen) ||
2005 __get_user(kmsg->msg_control, &umsg->msg_control) ||
2006 __get_user(kmsg->msg_controllen, &umsg->msg_controllen) ||
2007 __get_user(kmsg->msg_flags, &umsg->msg_flags))
1995 return -EFAULT; 2008 return -EFAULT;
1996 2009
1997 if (kmsg->msg_name == NULL) 2010 if (!uaddr)
1998 kmsg->msg_namelen = 0; 2011 kmsg->msg_namelen = 0;
1999 2012
2000 if (kmsg->msg_namelen < 0) 2013 if (kmsg->msg_namelen < 0)
@@ -2002,10 +2015,34 @@ static int copy_msghdr_from_user(struct msghdr *kmsg,
2002 2015
2003 if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) 2016 if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
2004 kmsg->msg_namelen = sizeof(struct sockaddr_storage); 2017 kmsg->msg_namelen = sizeof(struct sockaddr_storage);
2005 return 0; 2018
2019 if (save_addr)
2020 *save_addr = uaddr;
2021
2022 if (uaddr && kmsg->msg_namelen) {
2023 if (!save_addr) {
2024 err = move_addr_to_kernel(uaddr, kmsg->msg_namelen,
2025 kmsg->msg_name);
2026 if (err < 0)
2027 return err;
2028 }
2029 } else {
2030 kmsg->msg_name = NULL;
2031 kmsg->msg_namelen = 0;
2032 }
2033
2034 if (kmsg->msg_iovlen > UIO_MAXIOV)
2035 return -EMSGSIZE;
2036
2037 err = rw_copy_check_uvector(save_addr ? READ : WRITE,
2038 uiov, kmsg->msg_iovlen,
2039 UIO_FASTIOV, *iov, iov);
2040 if (err >= 0)
2041 kmsg->msg_iov = *iov;
2042 return err;
2006} 2043}
2007 2044
2008static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg, 2045static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
2009 struct msghdr *msg_sys, unsigned int flags, 2046 struct msghdr *msg_sys, unsigned int flags,
2010 struct used_address *used_address) 2047 struct used_address *used_address)
2011{ 2048{
@@ -2017,34 +2054,15 @@ static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
2017 __attribute__ ((aligned(sizeof(__kernel_size_t)))); 2054 __attribute__ ((aligned(sizeof(__kernel_size_t))));
2018 /* 20 is size of ipv6_pktinfo */ 2055 /* 20 is size of ipv6_pktinfo */
2019 unsigned char *ctl_buf = ctl; 2056 unsigned char *ctl_buf = ctl;
2020 int err, ctl_len, total_len; 2057 int ctl_len, total_len;
2021 2058 ssize_t err;
2022 err = -EFAULT;
2023 if (MSG_CMSG_COMPAT & flags) {
2024 if (get_compat_msghdr(msg_sys, msg_compat))
2025 return -EFAULT;
2026 } else {
2027 err = copy_msghdr_from_user(msg_sys, msg);
2028 if (err)
2029 return err;
2030 }
2031 2059
2032 if (msg_sys->msg_iovlen > UIO_FASTIOV) { 2060 msg_sys->msg_name = &address;
2033 err = -EMSGSIZE;
2034 if (msg_sys->msg_iovlen > UIO_MAXIOV)
2035 goto out;
2036 err = -ENOMEM;
2037 iov = kmalloc(msg_sys->msg_iovlen * sizeof(struct iovec),
2038 GFP_KERNEL);
2039 if (!iov)
2040 goto out;
2041 }
2042 2061
2043 /* This will also move the address data into kernel space */ 2062 if (MSG_CMSG_COMPAT & flags)
2044 if (MSG_CMSG_COMPAT & flags) { 2063 err = get_compat_msghdr(msg_sys, msg_compat, NULL, &iov);
2045 err = verify_compat_iovec(msg_sys, iov, &address, VERIFY_READ); 2064 else
2046 } else 2065 err = copy_msghdr_from_user(msg_sys, msg, NULL, &iov);
2047 err = verify_iovec(msg_sys, iov, &address, VERIFY_READ);
2048 if (err < 0) 2066 if (err < 0)
2049 goto out_freeiov; 2067 goto out_freeiov;
2050 total_len = err; 2068 total_len = err;
@@ -2115,7 +2133,6 @@ out_freectl:
2115out_freeiov: 2133out_freeiov:
2116 if (iov != iovstack) 2134 if (iov != iovstack)
2117 kfree(iov); 2135 kfree(iov);
2118out:
2119 return err; 2136 return err;
2120} 2137}
2121 2138
@@ -2123,7 +2140,7 @@ out:
2123 * BSD sendmsg interface 2140 * BSD sendmsg interface
2124 */ 2141 */
2125 2142
2126long __sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags) 2143long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned flags)
2127{ 2144{
2128 int fput_needed, err; 2145 int fput_needed, err;
2129 struct msghdr msg_sys; 2146 struct msghdr msg_sys;
@@ -2140,7 +2157,7 @@ out:
2140 return err; 2157 return err;
2141} 2158}
2142 2159
2143SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned int, flags) 2160SYSCALL_DEFINE3(sendmsg, int, fd, struct user_msghdr __user *, msg, unsigned int, flags)
2144{ 2161{
2145 if (flags & MSG_CMSG_COMPAT) 2162 if (flags & MSG_CMSG_COMPAT)
2146 return -EINVAL; 2163 return -EINVAL;
@@ -2177,7 +2194,7 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2177 2194
2178 while (datagrams < vlen) { 2195 while (datagrams < vlen) {
2179 if (MSG_CMSG_COMPAT & flags) { 2196 if (MSG_CMSG_COMPAT & flags) {
2180 err = ___sys_sendmsg(sock, (struct msghdr __user *)compat_entry, 2197 err = ___sys_sendmsg(sock, (struct user_msghdr __user *)compat_entry,
2181 &msg_sys, flags, &used_address); 2198 &msg_sys, flags, &used_address);
2182 if (err < 0) 2199 if (err < 0)
2183 break; 2200 break;
@@ -2185,7 +2202,7 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2185 ++compat_entry; 2202 ++compat_entry;
2186 } else { 2203 } else {
2187 err = ___sys_sendmsg(sock, 2204 err = ___sys_sendmsg(sock,
2188 (struct msghdr __user *)entry, 2205 (struct user_msghdr __user *)entry,
2189 &msg_sys, flags, &used_address); 2206 &msg_sys, flags, &used_address);
2190 if (err < 0) 2207 if (err < 0)
2191 break; 2208 break;
@@ -2215,7 +2232,7 @@ SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
2215 return __sys_sendmmsg(fd, mmsg, vlen, flags); 2232 return __sys_sendmmsg(fd, mmsg, vlen, flags);
2216} 2233}
2217 2234
2218static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg, 2235static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg,
2219 struct msghdr *msg_sys, unsigned int flags, int nosec) 2236 struct msghdr *msg_sys, unsigned int flags, int nosec)
2220{ 2237{
2221 struct compat_msghdr __user *msg_compat = 2238 struct compat_msghdr __user *msg_compat =
@@ -2223,44 +2240,22 @@ static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
2223 struct iovec iovstack[UIO_FASTIOV]; 2240 struct iovec iovstack[UIO_FASTIOV];
2224 struct iovec *iov = iovstack; 2241 struct iovec *iov = iovstack;
2225 unsigned long cmsg_ptr; 2242 unsigned long cmsg_ptr;
2226 int err, total_len, len; 2243 int total_len, len;
2244 ssize_t err;
2227 2245
2228 /* kernel mode address */ 2246 /* kernel mode address */
2229 struct sockaddr_storage addr; 2247 struct sockaddr_storage addr;
2230 2248
2231 /* user mode address pointers */ 2249 /* user mode address pointers */
2232 struct sockaddr __user *uaddr; 2250 struct sockaddr __user *uaddr;
2233 int __user *uaddr_len; 2251 int __user *uaddr_len = COMPAT_NAMELEN(msg);
2234 2252
2235 if (MSG_CMSG_COMPAT & flags) { 2253 msg_sys->msg_name = &addr;
2236 if (get_compat_msghdr(msg_sys, msg_compat))
2237 return -EFAULT;
2238 } else {
2239 err = copy_msghdr_from_user(msg_sys, msg);
2240 if (err)
2241 return err;
2242 }
2243
2244 if (msg_sys->msg_iovlen > UIO_FASTIOV) {
2245 err = -EMSGSIZE;
2246 if (msg_sys->msg_iovlen > UIO_MAXIOV)
2247 goto out;
2248 err = -ENOMEM;
2249 iov = kmalloc(msg_sys->msg_iovlen * sizeof(struct iovec),
2250 GFP_KERNEL);
2251 if (!iov)
2252 goto out;
2253 }
2254 2254
2255 /* Save the user-mode address (verify_iovec will change the
2256 * kernel msghdr to use the kernel address space)
2257 */
2258 uaddr = (__force void __user *)msg_sys->msg_name;
2259 uaddr_len = COMPAT_NAMELEN(msg);
2260 if (MSG_CMSG_COMPAT & flags) 2255 if (MSG_CMSG_COMPAT & flags)
2261 err = verify_compat_iovec(msg_sys, iov, &addr, VERIFY_WRITE); 2256 err = get_compat_msghdr(msg_sys, msg_compat, &uaddr, &iov);
2262 else 2257 else
2263 err = verify_iovec(msg_sys, iov, &addr, VERIFY_WRITE); 2258 err = copy_msghdr_from_user(msg_sys, msg, &uaddr, &iov);
2264 if (err < 0) 2259 if (err < 0)
2265 goto out_freeiov; 2260 goto out_freeiov;
2266 total_len = err; 2261 total_len = err;
@@ -2303,7 +2298,6 @@ static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
2303out_freeiov: 2298out_freeiov:
2304 if (iov != iovstack) 2299 if (iov != iovstack)
2305 kfree(iov); 2300 kfree(iov);
2306out:
2307 return err; 2301 return err;
2308} 2302}
2309 2303
@@ -2311,7 +2305,7 @@ out:
2311 * BSD recvmsg interface 2305 * BSD recvmsg interface
2312 */ 2306 */
2313 2307
2314long __sys_recvmsg(int fd, struct msghdr __user *msg, unsigned flags) 2308long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned flags)
2315{ 2309{
2316 int fput_needed, err; 2310 int fput_needed, err;
2317 struct msghdr msg_sys; 2311 struct msghdr msg_sys;
@@ -2328,7 +2322,7 @@ out:
2328 return err; 2322 return err;
2329} 2323}
2330 2324
2331SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg, 2325SYSCALL_DEFINE3(recvmsg, int, fd, struct user_msghdr __user *, msg,
2332 unsigned int, flags) 2326 unsigned int, flags)
2333{ 2327{
2334 if (flags & MSG_CMSG_COMPAT) 2328 if (flags & MSG_CMSG_COMPAT)
@@ -2373,7 +2367,7 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2373 * No need to ask LSM for more than the first datagram. 2367 * No need to ask LSM for more than the first datagram.
2374 */ 2368 */
2375 if (MSG_CMSG_COMPAT & flags) { 2369 if (MSG_CMSG_COMPAT & flags) {
2376 err = ___sys_recvmsg(sock, (struct msghdr __user *)compat_entry, 2370 err = ___sys_recvmsg(sock, (struct user_msghdr __user *)compat_entry,
2377 &msg_sys, flags & ~MSG_WAITFORONE, 2371 &msg_sys, flags & ~MSG_WAITFORONE,
2378 datagrams); 2372 datagrams);
2379 if (err < 0) 2373 if (err < 0)
@@ -2382,7 +2376,7 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2382 ++compat_entry; 2376 ++compat_entry;
2383 } else { 2377 } else {
2384 err = ___sys_recvmsg(sock, 2378 err = ___sys_recvmsg(sock,
2385 (struct msghdr __user *)entry, 2379 (struct user_msghdr __user *)entry,
2386 &msg_sys, flags & ~MSG_WAITFORONE, 2380 &msg_sys, flags & ~MSG_WAITFORONE,
2387 datagrams); 2381 datagrams);
2388 if (err < 0) 2382 if (err < 0)
@@ -2571,13 +2565,13 @@ SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
2571 (int __user *)a[4]); 2565 (int __user *)a[4]);
2572 break; 2566 break;
2573 case SYS_SENDMSG: 2567 case SYS_SENDMSG:
2574 err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]); 2568 err = sys_sendmsg(a0, (struct user_msghdr __user *)a1, a[2]);
2575 break; 2569 break;
2576 case SYS_SENDMMSG: 2570 case SYS_SENDMMSG:
2577 err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]); 2571 err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]);
2578 break; 2572 break;
2579 case SYS_RECVMSG: 2573 case SYS_RECVMSG:
2580 err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]); 2574 err = sys_recvmsg(a0, (struct user_msghdr __user *)a1, a[2]);
2581 break; 2575 break;
2582 case SYS_RECVMMSG: 2576 case SYS_RECVMMSG:
2583 err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3], 2577 err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3],