aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@amacapital.net>2013-06-05 15:38:26 -0400
committerDavid S. Miller <davem@davemloft.net>2013-06-06 14:52:14 -0400
commita7526eb5d06b0084ef12d7b168d008fcf516caab (patch)
treec79242698fadf78c23bbb9f50a7a8b9a74a40284
parent4d3797d7e1861ac1af150a6189315786c5e1c820 (diff)
net: Unbreak compat_sys_{send,recv}msg
I broke them in this commit: commit 1be374a0518a288147c6a7398792583200a67261 Author: Andy Lutomirski <luto@amacapital.net> Date: Wed May 22 14:07:44 2013 -0700 net: Block MSG_CMSG_COMPAT in send(m)msg and recv(m)msg This patch adds __sys_sendmsg and __sys_sendmsg as common helpers that accept MSG_CMSG_COMPAT and blocks MSG_CMSG_COMPAT at the syscall entrypoints. It also reverts some unnecessary checks in sys_socketcall. Apparently I was suffering from underscore blindness the first time around. Signed-off-by: Andy Lutomirski <luto@amacapital.net> Tested-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/socket.h3
-rw-r--r--net/compat.c13
-rw-r--r--net/socket.c72
3 files changed, 47 insertions, 41 deletions
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 33bf2dfab19d..b10ce4b341ea 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -320,6 +320,9 @@ extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data);
320 320
321struct timespec; 321struct timespec;
322 322
323/* The __sys_...msg variants allow MSG_CMSG_COMPAT */
324extern long __sys_recvmsg(int fd, struct msghdr __user *msg, unsigned flags);
325extern long __sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags);
323extern int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, 326extern int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
324 unsigned int flags, struct timespec *timeout); 327 unsigned int flags, struct timespec *timeout);
325extern int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, 328extern int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg,
diff --git a/net/compat.c b/net/compat.c
index 79ae88485001..f0a1ba6c8086 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -734,19 +734,25 @@ static unsigned char nas[21] = {
734 734
735asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags) 735asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags)
736{ 736{
737 return sys_sendmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); 737 if (flags & MSG_CMSG_COMPAT)
738 return -EINVAL;
739 return __sys_sendmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
738} 740}
739 741
740asmlinkage long compat_sys_sendmmsg(int fd, struct compat_mmsghdr __user *mmsg, 742asmlinkage long compat_sys_sendmmsg(int fd, struct compat_mmsghdr __user *mmsg,
741 unsigned int vlen, unsigned int flags) 743 unsigned int vlen, unsigned int flags)
742{ 744{
745 if (flags & MSG_CMSG_COMPAT)
746 return -EINVAL;
743 return __sys_sendmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, 747 return __sys_sendmmsg(fd, (struct mmsghdr __user *)mmsg, vlen,
744 flags | MSG_CMSG_COMPAT); 748 flags | MSG_CMSG_COMPAT);
745} 749}
746 750
747asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags) 751asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags)
748{ 752{
749 return sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); 753 if (flags & MSG_CMSG_COMPAT)
754 return -EINVAL;
755 return __sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
750} 756}
751 757
752asmlinkage long compat_sys_recv(int fd, void __user *buf, size_t len, unsigned int flags) 758asmlinkage long compat_sys_recv(int fd, void __user *buf, size_t len, unsigned int flags)
@@ -768,6 +774,9 @@ asmlinkage long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg,
768 int datagrams; 774 int datagrams;
769 struct timespec ktspec; 775 struct timespec ktspec;
770 776
777 if (flags & MSG_CMSG_COMPAT)
778 return -EINVAL;
779
771 if (COMPAT_USE_64BIT_TIME) 780 if (COMPAT_USE_64BIT_TIME)
772 return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, 781 return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen,
773 flags | MSG_CMSG_COMPAT, 782 flags | MSG_CMSG_COMPAT,
diff --git a/net/socket.c b/net/socket.c
index 9ff6366fee13..4ca1526db756 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1956,7 +1956,7 @@ struct used_address {
1956 unsigned int name_len; 1956 unsigned int name_len;
1957}; 1957};
1958 1958
1959static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg, 1959static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
1960 struct msghdr *msg_sys, unsigned int flags, 1960 struct msghdr *msg_sys, unsigned int flags,
1961 struct used_address *used_address) 1961 struct used_address *used_address)
1962{ 1962{
@@ -2071,26 +2071,30 @@ out:
2071 * BSD sendmsg interface 2071 * BSD sendmsg interface
2072 */ 2072 */
2073 2073
2074SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned int, flags) 2074long __sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
2075{ 2075{
2076 int fput_needed, err; 2076 int fput_needed, err;
2077 struct msghdr msg_sys; 2077 struct msghdr msg_sys;
2078 struct socket *sock; 2078 struct socket *sock;
2079 2079
2080 if (flags & MSG_CMSG_COMPAT)
2081 return -EINVAL;
2082
2083 sock = sockfd_lookup_light(fd, &err, &fput_needed); 2080 sock = sockfd_lookup_light(fd, &err, &fput_needed);
2084 if (!sock) 2081 if (!sock)
2085 goto out; 2082 goto out;
2086 2083
2087 err = __sys_sendmsg(sock, msg, &msg_sys, flags, NULL); 2084 err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL);
2088 2085
2089 fput_light(sock->file, fput_needed); 2086 fput_light(sock->file, fput_needed);
2090out: 2087out:
2091 return err; 2088 return err;
2092} 2089}
2093 2090
2091SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned int, flags)
2092{
2093 if (flags & MSG_CMSG_COMPAT)
2094 return -EINVAL;
2095 return __sys_sendmsg(fd, msg, flags);
2096}
2097
2094/* 2098/*
2095 * Linux sendmmsg interface 2099 * Linux sendmmsg interface
2096 */ 2100 */
@@ -2121,15 +2125,16 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2121 2125
2122 while (datagrams < vlen) { 2126 while (datagrams < vlen) {
2123 if (MSG_CMSG_COMPAT & flags) { 2127 if (MSG_CMSG_COMPAT & flags) {
2124 err = __sys_sendmsg(sock, (struct msghdr __user *)compat_entry, 2128 err = ___sys_sendmsg(sock, (struct msghdr __user *)compat_entry,
2125 &msg_sys, flags, &used_address); 2129 &msg_sys, flags, &used_address);
2126 if (err < 0) 2130 if (err < 0)
2127 break; 2131 break;
2128 err = __put_user(err, &compat_entry->msg_len); 2132 err = __put_user(err, &compat_entry->msg_len);
2129 ++compat_entry; 2133 ++compat_entry;
2130 } else { 2134 } else {
2131 err = __sys_sendmsg(sock, (struct msghdr __user *)entry, 2135 err = ___sys_sendmsg(sock,
2132 &msg_sys, flags, &used_address); 2136 (struct msghdr __user *)entry,
2137 &msg_sys, flags, &used_address);
2133 if (err < 0) 2138 if (err < 0)
2134 break; 2139 break;
2135 err = put_user(err, &entry->msg_len); 2140 err = put_user(err, &entry->msg_len);
@@ -2158,7 +2163,7 @@ SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
2158 return __sys_sendmmsg(fd, mmsg, vlen, flags); 2163 return __sys_sendmmsg(fd, mmsg, vlen, flags);
2159} 2164}
2160 2165
2161static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg, 2166static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
2162 struct msghdr *msg_sys, unsigned int flags, int nosec) 2167 struct msghdr *msg_sys, unsigned int flags, int nosec)
2163{ 2168{
2164 struct compat_msghdr __user *msg_compat = 2169 struct compat_msghdr __user *msg_compat =
@@ -2250,27 +2255,31 @@ out:
2250 * BSD recvmsg interface 2255 * BSD recvmsg interface
2251 */ 2256 */
2252 2257
2253SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg, 2258long __sys_recvmsg(int fd, struct msghdr __user *msg, unsigned flags)
2254 unsigned int, flags)
2255{ 2259{
2256 int fput_needed, err; 2260 int fput_needed, err;
2257 struct msghdr msg_sys; 2261 struct msghdr msg_sys;
2258 struct socket *sock; 2262 struct socket *sock;
2259 2263
2260 if (flags & MSG_CMSG_COMPAT)
2261 return -EINVAL;
2262
2263 sock = sockfd_lookup_light(fd, &err, &fput_needed); 2264 sock = sockfd_lookup_light(fd, &err, &fput_needed);
2264 if (!sock) 2265 if (!sock)
2265 goto out; 2266 goto out;
2266 2267
2267 err = __sys_recvmsg(sock, msg, &msg_sys, flags, 0); 2268 err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0);
2268 2269
2269 fput_light(sock->file, fput_needed); 2270 fput_light(sock->file, fput_needed);
2270out: 2271out:
2271 return err; 2272 return err;
2272} 2273}
2273 2274
2275SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg,
2276 unsigned int, flags)
2277{
2278 if (flags & MSG_CMSG_COMPAT)
2279 return -EINVAL;
2280 return __sys_recvmsg(fd, msg, flags);
2281}
2282
2274/* 2283/*
2275 * Linux recvmmsg interface 2284 * Linux recvmmsg interface
2276 */ 2285 */
@@ -2308,17 +2317,18 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2308 * No need to ask LSM for more than the first datagram. 2317 * No need to ask LSM for more than the first datagram.
2309 */ 2318 */
2310 if (MSG_CMSG_COMPAT & flags) { 2319 if (MSG_CMSG_COMPAT & flags) {
2311 err = __sys_recvmsg(sock, (struct msghdr __user *)compat_entry, 2320 err = ___sys_recvmsg(sock, (struct msghdr __user *)compat_entry,
2312 &msg_sys, flags & ~MSG_WAITFORONE, 2321 &msg_sys, flags & ~MSG_WAITFORONE,
2313 datagrams); 2322 datagrams);
2314 if (err < 0) 2323 if (err < 0)
2315 break; 2324 break;
2316 err = __put_user(err, &compat_entry->msg_len); 2325 err = __put_user(err, &compat_entry->msg_len);
2317 ++compat_entry; 2326 ++compat_entry;
2318 } else { 2327 } else {
2319 err = __sys_recvmsg(sock, (struct msghdr __user *)entry, 2328 err = ___sys_recvmsg(sock,
2320 &msg_sys, flags & ~MSG_WAITFORONE, 2329 (struct msghdr __user *)entry,
2321 datagrams); 2330 &msg_sys, flags & ~MSG_WAITFORONE,
2331 datagrams);
2322 if (err < 0) 2332 if (err < 0)
2323 break; 2333 break;
2324 err = put_user(err, &entry->msg_len); 2334 err = put_user(err, &entry->msg_len);
@@ -2505,31 +2515,15 @@ SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
2505 (int __user *)a[4]); 2515 (int __user *)a[4]);
2506 break; 2516 break;
2507 case SYS_SENDMSG: 2517 case SYS_SENDMSG:
2508 if (a[2] & MSG_CMSG_COMPAT) {
2509 err = -EINVAL;
2510 break;
2511 }
2512 err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]); 2518 err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]);
2513 break; 2519 break;
2514 case SYS_SENDMMSG: 2520 case SYS_SENDMMSG:
2515 if (a[3] & MSG_CMSG_COMPAT) {
2516 err = -EINVAL;
2517 break;
2518 }
2519 err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]); 2521 err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]);
2520 break; 2522 break;
2521 case SYS_RECVMSG: 2523 case SYS_RECVMSG:
2522 if (a[2] & MSG_CMSG_COMPAT) {
2523 err = -EINVAL;
2524 break;
2525 }
2526 err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]); 2524 err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]);
2527 break; 2525 break;
2528 case SYS_RECVMMSG: 2526 case SYS_RECVMMSG:
2529 if (a[3] & MSG_CMSG_COMPAT) {
2530 err = -EINVAL;
2531 break;
2532 }
2533 err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3], 2527 err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3],
2534 (struct timespec __user *)a[4]); 2528 (struct timespec __user *)a[4]);
2535 break; 2529 break;