diff options
Diffstat (limited to 'net/socket.c')
-rw-r--r-- | net/socket.c | 61 |
1 files changed, 42 insertions, 19 deletions
diff --git a/net/socket.c b/net/socket.c index 6b94633ca61d..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,22 +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 = sockfd_lookup_light(fd, &err, &fput_needed); | 2078 | struct socket *sock; |
2079 | 2079 | ||
2080 | sock = sockfd_lookup_light(fd, &err, &fput_needed); | ||
2080 | if (!sock) | 2081 | if (!sock) |
2081 | goto out; | 2082 | goto out; |
2082 | 2083 | ||
2083 | err = __sys_sendmsg(sock, msg, &msg_sys, flags, NULL); | 2084 | err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL); |
2084 | 2085 | ||
2085 | fput_light(sock->file, fput_needed); | 2086 | fput_light(sock->file, fput_needed); |
2086 | out: | 2087 | out: |
2087 | return err; | 2088 | return err; |
2088 | } | 2089 | } |
2089 | 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 | |||
2090 | /* | 2098 | /* |
2091 | * Linux sendmmsg interface | 2099 | * Linux sendmmsg interface |
2092 | */ | 2100 | */ |
@@ -2117,15 +2125,16 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, | |||
2117 | 2125 | ||
2118 | while (datagrams < vlen) { | 2126 | while (datagrams < vlen) { |
2119 | if (MSG_CMSG_COMPAT & flags) { | 2127 | if (MSG_CMSG_COMPAT & flags) { |
2120 | err = __sys_sendmsg(sock, (struct msghdr __user *)compat_entry, | 2128 | err = ___sys_sendmsg(sock, (struct msghdr __user *)compat_entry, |
2121 | &msg_sys, flags, &used_address); | 2129 | &msg_sys, flags, &used_address); |
2122 | if (err < 0) | 2130 | if (err < 0) |
2123 | break; | 2131 | break; |
2124 | err = __put_user(err, &compat_entry->msg_len); | 2132 | err = __put_user(err, &compat_entry->msg_len); |
2125 | ++compat_entry; | 2133 | ++compat_entry; |
2126 | } else { | 2134 | } else { |
2127 | err = __sys_sendmsg(sock, (struct msghdr __user *)entry, | 2135 | err = ___sys_sendmsg(sock, |
2128 | &msg_sys, flags, &used_address); | 2136 | (struct msghdr __user *)entry, |
2137 | &msg_sys, flags, &used_address); | ||
2129 | if (err < 0) | 2138 | if (err < 0) |
2130 | break; | 2139 | break; |
2131 | err = put_user(err, &entry->msg_len); | 2140 | err = put_user(err, &entry->msg_len); |
@@ -2149,10 +2158,12 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, | |||
2149 | SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg, | 2158 | SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg, |
2150 | unsigned int, vlen, unsigned int, flags) | 2159 | unsigned int, vlen, unsigned int, flags) |
2151 | { | 2160 | { |
2161 | if (flags & MSG_CMSG_COMPAT) | ||
2162 | return -EINVAL; | ||
2152 | return __sys_sendmmsg(fd, mmsg, vlen, flags); | 2163 | return __sys_sendmmsg(fd, mmsg, vlen, flags); |
2153 | } | 2164 | } |
2154 | 2165 | ||
2155 | static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg, | 2166 | static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg, |
2156 | struct msghdr *msg_sys, unsigned int flags, int nosec) | 2167 | struct msghdr *msg_sys, unsigned int flags, int nosec) |
2157 | { | 2168 | { |
2158 | struct compat_msghdr __user *msg_compat = | 2169 | struct compat_msghdr __user *msg_compat = |
@@ -2244,23 +2255,31 @@ out: | |||
2244 | * BSD recvmsg interface | 2255 | * BSD recvmsg interface |
2245 | */ | 2256 | */ |
2246 | 2257 | ||
2247 | SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg, | 2258 | long __sys_recvmsg(int fd, struct msghdr __user *msg, unsigned flags) |
2248 | unsigned int, flags) | ||
2249 | { | 2259 | { |
2250 | int fput_needed, err; | 2260 | int fput_needed, err; |
2251 | struct msghdr msg_sys; | 2261 | struct msghdr msg_sys; |
2252 | struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed); | 2262 | struct socket *sock; |
2253 | 2263 | ||
2264 | sock = sockfd_lookup_light(fd, &err, &fput_needed); | ||
2254 | if (!sock) | 2265 | if (!sock) |
2255 | goto out; | 2266 | goto out; |
2256 | 2267 | ||
2257 | err = __sys_recvmsg(sock, msg, &msg_sys, flags, 0); | 2268 | err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0); |
2258 | 2269 | ||
2259 | fput_light(sock->file, fput_needed); | 2270 | fput_light(sock->file, fput_needed); |
2260 | out: | 2271 | out: |
2261 | return err; | 2272 | return err; |
2262 | } | 2273 | } |
2263 | 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 | |||
2264 | /* | 2283 | /* |
2265 | * Linux recvmmsg interface | 2284 | * Linux recvmmsg interface |
2266 | */ | 2285 | */ |
@@ -2298,17 +2317,18 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, | |||
2298 | * No need to ask LSM for more than the first datagram. | 2317 | * No need to ask LSM for more than the first datagram. |
2299 | */ | 2318 | */ |
2300 | if (MSG_CMSG_COMPAT & flags) { | 2319 | if (MSG_CMSG_COMPAT & flags) { |
2301 | err = __sys_recvmsg(sock, (struct msghdr __user *)compat_entry, | 2320 | err = ___sys_recvmsg(sock, (struct msghdr __user *)compat_entry, |
2302 | &msg_sys, flags & ~MSG_WAITFORONE, | 2321 | &msg_sys, flags & ~MSG_WAITFORONE, |
2303 | datagrams); | 2322 | datagrams); |
2304 | if (err < 0) | 2323 | if (err < 0) |
2305 | break; | 2324 | break; |
2306 | err = __put_user(err, &compat_entry->msg_len); | 2325 | err = __put_user(err, &compat_entry->msg_len); |
2307 | ++compat_entry; | 2326 | ++compat_entry; |
2308 | } else { | 2327 | } else { |
2309 | err = __sys_recvmsg(sock, (struct msghdr __user *)entry, | 2328 | err = ___sys_recvmsg(sock, |
2310 | &msg_sys, flags & ~MSG_WAITFORONE, | 2329 | (struct msghdr __user *)entry, |
2311 | datagrams); | 2330 | &msg_sys, flags & ~MSG_WAITFORONE, |
2331 | datagrams); | ||
2312 | if (err < 0) | 2332 | if (err < 0) |
2313 | break; | 2333 | break; |
2314 | err = put_user(err, &entry->msg_len); | 2334 | err = put_user(err, &entry->msg_len); |
@@ -2375,6 +2395,9 @@ SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg, | |||
2375 | int datagrams; | 2395 | int datagrams; |
2376 | struct timespec timeout_sys; | 2396 | struct timespec timeout_sys; |
2377 | 2397 | ||
2398 | if (flags & MSG_CMSG_COMPAT) | ||
2399 | return -EINVAL; | ||
2400 | |||
2378 | if (!timeout) | 2401 | if (!timeout) |
2379 | return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL); | 2402 | return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL); |
2380 | 2403 | ||