diff options
author | Andy Lutomirski <luto@amacapital.net> | 2013-06-05 15:38:26 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-06-06 14:52:14 -0400 |
commit | a7526eb5d06b0084ef12d7b168d008fcf516caab (patch) | |
tree | c79242698fadf78c23bbb9f50a7a8b9a74a40284 | |
parent | 4d3797d7e1861ac1af150a6189315786c5e1c820 (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.h | 3 | ||||
-rw-r--r-- | net/compat.c | 13 | ||||
-rw-r--r-- | net/socket.c | 72 |
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 | ||
321 | struct timespec; | 321 | struct timespec; |
322 | 322 | ||
323 | /* The __sys_...msg variants allow MSG_CMSG_COMPAT */ | ||
324 | extern long __sys_recvmsg(int fd, struct msghdr __user *msg, unsigned flags); | ||
325 | extern long __sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags); | ||
323 | extern int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, | 326 | extern 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); |
325 | extern int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, | 328 | extern 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 | ||
735 | asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags) | 735 | asmlinkage 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 | ||
740 | asmlinkage long compat_sys_sendmmsg(int fd, struct compat_mmsghdr __user *mmsg, | 742 | asmlinkage 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 | ||
747 | asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags) | 751 | asmlinkage 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 | ||
752 | asmlinkage long compat_sys_recv(int fd, void __user *buf, size_t len, unsigned int flags) | 758 | asmlinkage 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 | ||
1959 | static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg, | 1959 | static 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 | ||
2074 | SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned int, flags) | 2074 | long __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); |
2090 | out: | 2087 | out: |
2091 | return err; | 2088 | return err; |
2092 | } | 2089 | } |
2093 | 2090 | ||
2091 | SYSCALL_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 | ||
2161 | static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg, | 2166 | static 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 | ||
2253 | SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg, | 2258 | long __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); |
2270 | out: | 2271 | out: |
2271 | return err; | 2272 | return err; |
2272 | } | 2273 | } |
2273 | 2274 | ||
2275 | SYSCALL_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; |