aboutsummaryrefslogtreecommitdiffstats
path: root/net/socket.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2014-11-10 20:23:13 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2014-11-19 16:23:49 -0500
commit08adb7dabd4874cc5666b4490653b26534702ce0 (patch)
tree8848933c57ef03c59e52ace937103c91c4e32607 /net/socket.c
parent0844932009e1656726c6e9c369e694017b129378 (diff)
fold verify_iovec() into copy_msghdr_from_user()
... and do the same on the compat side of things. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'net/socket.c')
-rw-r--r--net/socket.c93
1 files changed, 53 insertions, 40 deletions
diff --git a/net/socket.c b/net/socket.c
index 59020f0b583b..ee3ee39eefa5 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1988,16 +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 user_msghdr __user *umsg) 1992 struct user_msghdr __user *umsg,
1993 struct sockaddr __user **save_addr,
1994 struct iovec **iov)
1993{ 1995{
1994 /* We are relying on the (currently) identical layouts. Once 1996 struct sockaddr __user *uaddr;
1995 * the kernel-side changes, this place will need to be updated 1997 struct iovec __user *uiov;
1996 */ 1998 ssize_t err;
1997 if (copy_from_user(kmsg, umsg, sizeof(struct msghdr))) 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))
1998 return -EFAULT; 2008 return -EFAULT;
1999 2009
2000 if (kmsg->msg_name == NULL) 2010 if (!uaddr)
2001 kmsg->msg_namelen = 0; 2011 kmsg->msg_namelen = 0;
2002 2012
2003 if (kmsg->msg_namelen < 0) 2013 if (kmsg->msg_namelen < 0)
@@ -2005,7 +2015,31 @@ static int copy_msghdr_from_user(struct msghdr *kmsg,
2005 2015
2006 if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) 2016 if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
2007 kmsg->msg_namelen = sizeof(struct sockaddr_storage); 2017 kmsg->msg_namelen = sizeof(struct sockaddr_storage);
2008 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;
2009} 2043}
2010 2044
2011static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg, 2045static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
@@ -2020,26 +2054,17 @@ static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
2020 __attribute__ ((aligned(sizeof(__kernel_size_t)))); 2054 __attribute__ ((aligned(sizeof(__kernel_size_t))));
2021 /* 20 is size of ipv6_pktinfo */ 2055 /* 20 is size of ipv6_pktinfo */
2022 unsigned char *ctl_buf = ctl; 2056 unsigned char *ctl_buf = ctl;
2023 int err, ctl_len, total_len; 2057 int ctl_len, total_len;
2058 ssize_t err;
2024 2059
2025 err = -EFAULT; 2060 msg_sys->msg_name = &address;
2026 if (MSG_CMSG_COMPAT & flags) {
2027 if (get_compat_msghdr(msg_sys, msg_compat))
2028 return -EFAULT;
2029 } else {
2030 err = copy_msghdr_from_user(msg_sys, msg);
2031 if (err)
2032 return err;
2033 }
2034 2061
2035 /* This will also move the address data into kernel space */
2036 if (MSG_CMSG_COMPAT & flags) 2062 if (MSG_CMSG_COMPAT & flags)
2037 err = verify_compat_iovec(msg_sys, iovstack, &address, WRITE); 2063 err = get_compat_msghdr(msg_sys, msg_compat, NULL, &iov);
2038 else 2064 else
2039 err = verify_iovec(msg_sys, iovstack, &address, WRITE); 2065 err = copy_msghdr_from_user(msg_sys, msg, NULL, &iov);
2040 if (err < 0) 2066 if (err < 0)
2041 goto out_freeiov; 2067 goto out_freeiov;
2042 iov = msg_sys->msg_iov;
2043 total_len = err; 2068 total_len = err;
2044 2069
2045 err = -ENOBUFS; 2070 err = -ENOBUFS;
@@ -2215,36 +2240,24 @@ static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg,
2215 struct iovec iovstack[UIO_FASTIOV]; 2240 struct iovec iovstack[UIO_FASTIOV];
2216 struct iovec *iov = iovstack; 2241 struct iovec *iov = iovstack;
2217 unsigned long cmsg_ptr; 2242 unsigned long cmsg_ptr;
2218 int err, total_len, len; 2243 int total_len, len;
2244 ssize_t err;
2219 2245
2220 /* kernel mode address */ 2246 /* kernel mode address */
2221 struct sockaddr_storage addr; 2247 struct sockaddr_storage addr;
2222 2248
2223 /* user mode address pointers */ 2249 /* user mode address pointers */
2224 struct sockaddr __user *uaddr; 2250 struct sockaddr __user *uaddr;
2225 int __user *uaddr_len; 2251 int __user *uaddr_len = COMPAT_NAMELEN(msg);
2226 2252
2227 if (MSG_CMSG_COMPAT & flags) { 2253 msg_sys->msg_name = &addr;
2228 if (get_compat_msghdr(msg_sys, msg_compat))
2229 return -EFAULT;
2230 } else {
2231 err = copy_msghdr_from_user(msg_sys, msg);
2232 if (err)
2233 return err;
2234 }
2235 2254
2236 /* Save the user-mode address (verify_iovec will change the
2237 * kernel msghdr to use the kernel address space)
2238 */
2239 uaddr = (__force void __user *)msg_sys->msg_name;
2240 uaddr_len = COMPAT_NAMELEN(msg);
2241 if (MSG_CMSG_COMPAT & flags) 2255 if (MSG_CMSG_COMPAT & flags)
2242 err = verify_compat_iovec(msg_sys, iovstack, &addr, READ); 2256 err = get_compat_msghdr(msg_sys, msg_compat, &uaddr, &iov);
2243 else 2257 else
2244 err = verify_iovec(msg_sys, iovstack, &addr, READ); 2258 err = copy_msghdr_from_user(msg_sys, msg, &uaddr, &iov);
2245 if (err < 0) 2259 if (err < 0)
2246 goto out_freeiov; 2260 goto out_freeiov;
2247 iov = msg_sys->msg_iov;
2248 total_len = err; 2261 total_len = err;
2249 2262
2250 cmsg_ptr = (unsigned long)msg_sys->msg_control; 2263 cmsg_ptr = (unsigned long)msg_sys->msg_control;