aboutsummaryrefslogtreecommitdiffstats
path: root/net/socket.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2014-04-06 14:03:05 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2014-11-19 16:22:59 -0500
commit666547ff591cebdedc4679bf6b1b3f3383a8dea3 (patch)
tree59a5eadc4a3a1ca74ca7e6f36cb55f9808602368 /net/socket.c
parentdaaf427c6ab392bedcd018e326b2ffa1e1110cd6 (diff)
separate kernel- and userland-side msghdr
Kernel-side struct msghdr is (currently) using the same layout as userland one, but it's not a one-to-one copy - even without considering 32bit compat issues, we have msg_iov, msg_name and msg_control copied to kernel[1]. It's fairly localized, so we get away with a few functions where that knowledge is needed (and we could shrink that set even more). Pretty much everything deals with the kernel-side variant and the few places that want userland one just use a bunch of force-casts to paper over the differences. The thing is, kernel-side definition of struct msghdr is *not* exposed in include/uapi - libc doesn't see it, etc. So we can add struct user_msghdr, with proper annotations and let the few places that ever deal with those beasts use it for userland pointers. Saner typechecking aside, that will allow to change the layout of kernel-side msghdr - e.g. replace msg_iov/msg_iovlen there with struct iov_iter, getting rid of the need to modify the iovec as we copy data to/from it, etc. We could introduce kernel_msghdr instead, but that would create much more noise - the absolute majority of the instances would need to have the type switched to kernel_msghdr and definition of struct msghdr in include/linux/socket.h is not going to be seen by userland anyway. This commit just introduces user_msghdr and switches the few places that are dealing with userland-side msghdr to it. [1] actually, it's even trickier than that - we copy msg_control for sendmsg, but keep the userland address on recvmsg. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'net/socket.c')
-rw-r--r--net/socket.c29
1 files changed, 16 insertions, 13 deletions
diff --git a/net/socket.c b/net/socket.c
index fe20c319a0bb..0ae8147e3acc 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1989,8 +1989,11 @@ struct used_address {
1989}; 1989};
1990 1990
1991static int copy_msghdr_from_user(struct msghdr *kmsg, 1991static int copy_msghdr_from_user(struct msghdr *kmsg,
1992 struct msghdr __user *umsg) 1992 struct user_msghdr __user *umsg)
1993{ 1993{
1994 /* We are relying on the (currently) identical layouts. Once
1995 * the kernel-side changes, this place will need to be updated
1996 */
1994 if (copy_from_user(kmsg, umsg, sizeof(struct msghdr))) 1997 if (copy_from_user(kmsg, umsg, sizeof(struct msghdr)))
1995 return -EFAULT; 1998 return -EFAULT;
1996 1999
@@ -2005,7 +2008,7 @@ static int copy_msghdr_from_user(struct msghdr *kmsg,
2005 return 0; 2008 return 0;
2006} 2009}
2007 2010
2008static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg, 2011static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
2009 struct msghdr *msg_sys, unsigned int flags, 2012 struct msghdr *msg_sys, unsigned int flags,
2010 struct used_address *used_address) 2013 struct used_address *used_address)
2011{ 2014{
@@ -2123,7 +2126,7 @@ out:
2123 * BSD sendmsg interface 2126 * BSD sendmsg interface
2124 */ 2127 */
2125 2128
2126long __sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags) 2129long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned flags)
2127{ 2130{
2128 int fput_needed, err; 2131 int fput_needed, err;
2129 struct msghdr msg_sys; 2132 struct msghdr msg_sys;
@@ -2140,7 +2143,7 @@ out:
2140 return err; 2143 return err;
2141} 2144}
2142 2145
2143SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned int, flags) 2146SYSCALL_DEFINE3(sendmsg, int, fd, struct user_msghdr __user *, msg, unsigned int, flags)
2144{ 2147{
2145 if (flags & MSG_CMSG_COMPAT) 2148 if (flags & MSG_CMSG_COMPAT)
2146 return -EINVAL; 2149 return -EINVAL;
@@ -2177,7 +2180,7 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2177 2180
2178 while (datagrams < vlen) { 2181 while (datagrams < vlen) {
2179 if (MSG_CMSG_COMPAT & flags) { 2182 if (MSG_CMSG_COMPAT & flags) {
2180 err = ___sys_sendmsg(sock, (struct msghdr __user *)compat_entry, 2183 err = ___sys_sendmsg(sock, (struct user_msghdr __user *)compat_entry,
2181 &msg_sys, flags, &used_address); 2184 &msg_sys, flags, &used_address);
2182 if (err < 0) 2185 if (err < 0)
2183 break; 2186 break;
@@ -2185,7 +2188,7 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2185 ++compat_entry; 2188 ++compat_entry;
2186 } else { 2189 } else {
2187 err = ___sys_sendmsg(sock, 2190 err = ___sys_sendmsg(sock,
2188 (struct msghdr __user *)entry, 2191 (struct user_msghdr __user *)entry,
2189 &msg_sys, flags, &used_address); 2192 &msg_sys, flags, &used_address);
2190 if (err < 0) 2193 if (err < 0)
2191 break; 2194 break;
@@ -2215,7 +2218,7 @@ SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
2215 return __sys_sendmmsg(fd, mmsg, vlen, flags); 2218 return __sys_sendmmsg(fd, mmsg, vlen, flags);
2216} 2219}
2217 2220
2218static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg, 2221static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg,
2219 struct msghdr *msg_sys, unsigned int flags, int nosec) 2222 struct msghdr *msg_sys, unsigned int flags, int nosec)
2220{ 2223{
2221 struct compat_msghdr __user *msg_compat = 2224 struct compat_msghdr __user *msg_compat =
@@ -2311,7 +2314,7 @@ out:
2311 * BSD recvmsg interface 2314 * BSD recvmsg interface
2312 */ 2315 */
2313 2316
2314long __sys_recvmsg(int fd, struct msghdr __user *msg, unsigned flags) 2317long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned flags)
2315{ 2318{
2316 int fput_needed, err; 2319 int fput_needed, err;
2317 struct msghdr msg_sys; 2320 struct msghdr msg_sys;
@@ -2328,7 +2331,7 @@ out:
2328 return err; 2331 return err;
2329} 2332}
2330 2333
2331SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg, 2334SYSCALL_DEFINE3(recvmsg, int, fd, struct user_msghdr __user *, msg,
2332 unsigned int, flags) 2335 unsigned int, flags)
2333{ 2336{
2334 if (flags & MSG_CMSG_COMPAT) 2337 if (flags & MSG_CMSG_COMPAT)
@@ -2373,7 +2376,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. 2376 * No need to ask LSM for more than the first datagram.
2374 */ 2377 */
2375 if (MSG_CMSG_COMPAT & flags) { 2378 if (MSG_CMSG_COMPAT & flags) {
2376 err = ___sys_recvmsg(sock, (struct msghdr __user *)compat_entry, 2379 err = ___sys_recvmsg(sock, (struct user_msghdr __user *)compat_entry,
2377 &msg_sys, flags & ~MSG_WAITFORONE, 2380 &msg_sys, flags & ~MSG_WAITFORONE,
2378 datagrams); 2381 datagrams);
2379 if (err < 0) 2382 if (err < 0)
@@ -2382,7 +2385,7 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2382 ++compat_entry; 2385 ++compat_entry;
2383 } else { 2386 } else {
2384 err = ___sys_recvmsg(sock, 2387 err = ___sys_recvmsg(sock,
2385 (struct msghdr __user *)entry, 2388 (struct user_msghdr __user *)entry,
2386 &msg_sys, flags & ~MSG_WAITFORONE, 2389 &msg_sys, flags & ~MSG_WAITFORONE,
2387 datagrams); 2390 datagrams);
2388 if (err < 0) 2391 if (err < 0)
@@ -2571,13 +2574,13 @@ SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
2571 (int __user *)a[4]); 2574 (int __user *)a[4]);
2572 break; 2575 break;
2573 case SYS_SENDMSG: 2576 case SYS_SENDMSG:
2574 err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]); 2577 err = sys_sendmsg(a0, (struct user_msghdr __user *)a1, a[2]);
2575 break; 2578 break;
2576 case SYS_SENDMMSG: 2579 case SYS_SENDMMSG:
2577 err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]); 2580 err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]);
2578 break; 2581 break;
2579 case SYS_RECVMSG: 2582 case SYS_RECVMSG:
2580 err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]); 2583 err = sys_recvmsg(a0, (struct user_msghdr __user *)a1, a[2]);
2581 break; 2584 break;
2582 case SYS_RECVMMSG: 2585 case SYS_RECVMMSG:
2583 err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3], 2586 err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3],