Blame view
net/compat.c
22.5 KB
457c89965 treewide: Add SPD... |
1 |
// SPDX-License-Identifier: GPL-2.0-only |
4768fbcbc [NET]: Fix whites... |
2 |
/* |
1da177e4c Linux-2.6.12-rc2 |
3 4 5 6 7 8 9 10 11 |
* 32bit Socket syscall emulation. Based on arch/sparc64/kernel/sys_sparc32.c. * * Copyright (C) 2000 VA Linux Co * Copyright (C) 2000 Don Dugger <n0ano@valinux.com> * Copyright (C) 1999 Arun Sharma <arun.sharma@intel.com> * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 2000 Hewlett-Packard Co. * Copyright (C) 2000 David Mosberger-Tang <davidm@hpl.hp.com> |
4768fbcbc [NET]: Fix whites... |
12 |
* Copyright (C) 2000,2001 Andi Kleen, SuSE Labs |
1da177e4c Linux-2.6.12-rc2 |
13 14 15 |
*/ #include <linux/kernel.h> |
5a0e3ad6a include cleanup: ... |
16 |
#include <linux/gfp.h> |
1da177e4c Linux-2.6.12-rc2 |
17 |
#include <linux/fs.h> |
1da177e4c Linux-2.6.12-rc2 |
18 19 20 21 22 23 24 |
#include <linux/types.h> #include <linux/file.h> #include <linux/icmpv6.h> #include <linux/socket.h> #include <linux/syscalls.h> #include <linux/filter.h> #include <linux/compat.h> |
1da177e4c Linux-2.6.12-rc2 |
25 |
#include <linux/security.h> |
62bc306e2 audit: log 32-bit... |
26 |
#include <linux/audit.h> |
bc3b2d7fb net: Add export.h... |
27 |
#include <linux/export.h> |
1da177e4c Linux-2.6.12-rc2 |
28 29 30 |
#include <net/scm.h> #include <net/sock.h> |
dae502954 ipv4/ipv6 compat:... |
31 32 |
#include <net/ip.h> #include <net/ipv6.h> |
7c0f6ba68 Replace <asm/uacc... |
33 |
#include <linux/uaccess.h> |
1da177e4c Linux-2.6.12-rc2 |
34 |
#include <net/compat.h> |
da1842849 net: switch impor... |
35 36 37 38 |
int get_compat_msghdr(struct msghdr *kmsg, struct compat_msghdr __user *umsg, struct sockaddr __user **save_addr, struct iovec **iov) |
1da177e4c Linux-2.6.12-rc2 |
39 |
{ |
5da028a8a get_compat_msghdr... |
40 |
struct compat_msghdr msg; |
08adb7dab fold verify_iovec... |
41 |
ssize_t err; |
1da177e4c Linux-2.6.12-rc2 |
42 |
|
5da028a8a get_compat_msghdr... |
43 |
if (copy_from_user(&msg, umsg, sizeof(*umsg))) |
1da177e4c Linux-2.6.12-rc2 |
44 |
return -EFAULT; |
91edd096e net: compat: Upda... |
45 |
|
5da028a8a get_compat_msghdr... |
46 47 48 49 |
kmsg->msg_flags = msg.msg_flags; kmsg->msg_namelen = msg.msg_namelen; if (!msg.msg_name) |
91edd096e net: compat: Upda... |
50 51 52 53 |
kmsg->msg_namelen = 0; if (kmsg->msg_namelen < 0) return -EINVAL; |
1661bf364 net: heap overflo... |
54 |
if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) |
db31c55a6 net: clamp ->msg_... |
55 |
kmsg->msg_namelen = sizeof(struct sockaddr_storage); |
5da028a8a get_compat_msghdr... |
56 57 58 |
kmsg->msg_control = compat_ptr(msg.msg_control); kmsg->msg_controllen = msg.msg_controllen; |
1da177e4c Linux-2.6.12-rc2 |
59 |
|
08adb7dab fold verify_iovec... |
60 |
if (save_addr) |
5da028a8a get_compat_msghdr... |
61 |
*save_addr = compat_ptr(msg.msg_name); |
1da177e4c Linux-2.6.12-rc2 |
62 |
|
5da028a8a get_compat_msghdr... |
63 |
if (msg.msg_name && kmsg->msg_namelen) { |
08adb7dab fold verify_iovec... |
64 |
if (!save_addr) { |
5da028a8a get_compat_msghdr... |
65 |
err = move_addr_to_kernel(compat_ptr(msg.msg_name), |
08adb7dab fold verify_iovec... |
66 67 |
kmsg->msg_namelen, kmsg->msg_name); |
e71a4783a [NET] core: white... |
68 |
if (err < 0) |
1da177e4c Linux-2.6.12-rc2 |
69 70 |
return err; } |
40eea803c net: sendmsg: fix... |
71 |
} else { |
08adb7dab fold verify_iovec... |
72 73 |
kmsg->msg_name = NULL; kmsg->msg_namelen = 0; |
40eea803c net: sendmsg: fix... |
74 |
} |
1da177e4c Linux-2.6.12-rc2 |
75 |
|
5da028a8a get_compat_msghdr... |
76 |
if (msg.msg_iovlen > UIO_MAXIOV) |
084493200 {compat_,}verify_... |
77 |
return -EMSGSIZE; |
0345f9313 net: socket: add ... |
78 |
kmsg->msg_iocb = NULL; |
87e5e6dab uio: make import_... |
79 |
err = compat_import_iovec(save_addr ? READ : WRITE, |
5da028a8a get_compat_msghdr... |
80 |
compat_ptr(msg.msg_iov), msg.msg_iovlen, |
da1842849 net: switch impor... |
81 |
UIO_FASTIOV, iov, &kmsg->msg_iter); |
87e5e6dab uio: make import_... |
82 |
return err < 0 ? err : 0; |
1da177e4c Linux-2.6.12-rc2 |
83 84 85 86 87 88 |
} /* Bleech... */ #define CMSG_COMPAT_ALIGN(len) ALIGN((len), sizeof(s32)) #define CMSG_COMPAT_DATA(cmsg) \ |
1ff8cebf4 scm: remove use C... |
89 |
((void __user *)((char __user *)(cmsg) + sizeof(struct compat_cmsghdr))) |
1da177e4c Linux-2.6.12-rc2 |
90 |
#define CMSG_COMPAT_SPACE(len) \ |
1ff8cebf4 scm: remove use C... |
91 |
(sizeof(struct compat_cmsghdr) + CMSG_COMPAT_ALIGN(len)) |
1da177e4c Linux-2.6.12-rc2 |
92 |
#define CMSG_COMPAT_LEN(len) \ |
1ff8cebf4 scm: remove use C... |
93 |
(sizeof(struct compat_cmsghdr) + (len)) |
1da177e4c Linux-2.6.12-rc2 |
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
#define CMSG_COMPAT_FIRSTHDR(msg) \ (((msg)->msg_controllen) >= sizeof(struct compat_cmsghdr) ? \ (struct compat_cmsghdr __user *)((msg)->msg_control) : \ (struct compat_cmsghdr __user *)NULL) #define CMSG_COMPAT_OK(ucmlen, ucmsg, mhdr) \ ((ucmlen) >= sizeof(struct compat_cmsghdr) && \ (ucmlen) <= (unsigned long) \ ((mhdr)->msg_controllen - \ ((char *)(ucmsg) - (char *)(mhdr)->msg_control))) static inline struct compat_cmsghdr __user *cmsg_compat_nxthdr(struct msghdr *msg, struct compat_cmsghdr __user *cmsg, int cmsg_len) { char __user *ptr = (char __user *)cmsg + CMSG_COMPAT_ALIGN(cmsg_len); if ((unsigned long)(ptr + 1 - (char __user *)msg->msg_control) > msg->msg_controllen) return NULL; return (struct compat_cmsghdr __user *)ptr; } /* There is a lot of hair here because the alignment rules (and * thus placement) of cmsg headers and length are different for * 32-bit apps. -DaveM */ |
8920e8f94 [PATCH] Fix 32bit... |
120 |
int cmsghdr_from_user_compat_to_kern(struct msghdr *kmsg, struct sock *sk, |
1da177e4c Linux-2.6.12-rc2 |
121 122 123 124 125 126 |
unsigned char *stackbuf, int stackbuf_size) { struct compat_cmsghdr __user *ucmsg; struct cmsghdr *kcmsg, *kcmsg_base; compat_size_t ucmlen; __kernel_size_t kcmlen, tmp; |
8920e8f94 [PATCH] Fix 32bit... |
127 |
int err = -EFAULT; |
1da177e4c Linux-2.6.12-rc2 |
128 |
|
ac4340fc3 net: Assert at bu... |
129 130 |
BUILD_BUG_ON(sizeof(struct compat_cmsghdr) != CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr))); |
1da177e4c Linux-2.6.12-rc2 |
131 132 133 |
kcmlen = 0; kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf; ucmsg = CMSG_COMPAT_FIRSTHDR(kmsg); |
e71a4783a [NET] core: white... |
134 135 |
while (ucmsg != NULL) { if (get_user(ucmlen, &ucmsg->cmsg_len)) |
1da177e4c Linux-2.6.12-rc2 |
136 137 138 139 140 |
return -EFAULT; /* Catch bogons. */ if (!CMSG_COMPAT_OK(ucmlen, ucmsg, kmsg)) return -EINVAL; |
1ff8cebf4 scm: remove use C... |
141 |
tmp = ((ucmlen - sizeof(*ucmsg)) + sizeof(struct cmsghdr)); |
8920e8f94 [PATCH] Fix 32bit... |
142 |
tmp = CMSG_ALIGN(tmp); |
1da177e4c Linux-2.6.12-rc2 |
143 144 145 |
kcmlen += tmp; ucmsg = cmsg_compat_nxthdr(kmsg, ucmsg, ucmlen); } |
e71a4783a [NET] core: white... |
146 |
if (kcmlen == 0) |
1da177e4c Linux-2.6.12-rc2 |
147 148 149 150 151 152 153 |
return -EINVAL; /* The kcmlen holds the 64-bit version of the control length. * It may not be modified as we do not stick it into the kmsg * until we have successfully copied over all of the data * from the user. */ |
8920e8f94 [PATCH] Fix 32bit... |
154 155 156 |
if (kcmlen > stackbuf_size) kcmsg_base = kcmsg = sock_kmalloc(sk, kcmlen, GFP_KERNEL); if (kcmsg == NULL) |
1da177e4c Linux-2.6.12-rc2 |
157 158 159 160 161 |
return -ENOBUFS; /* Now copy them over neatly. */ memset(kcmsg, 0, kcmlen); ucmsg = CMSG_COMPAT_FIRSTHDR(kmsg); |
e71a4783a [NET] core: white... |
162 |
while (ucmsg != NULL) { |
8920e8f94 [PATCH] Fix 32bit... |
163 164 165 166 |
if (__get_user(ucmlen, &ucmsg->cmsg_len)) goto Efault; if (!CMSG_COMPAT_OK(ucmlen, ucmsg, kmsg)) goto Einval; |
1ff8cebf4 scm: remove use C... |
167 |
tmp = ((ucmlen - sizeof(*ucmsg)) + sizeof(struct cmsghdr)); |
8920e8f94 [PATCH] Fix 32bit... |
168 169 |
if ((char *)kcmsg_base + kcmlen - (char *)kcmsg < CMSG_ALIGN(tmp)) goto Einval; |
1da177e4c Linux-2.6.12-rc2 |
170 |
kcmsg->cmsg_len = tmp; |
8920e8f94 [PATCH] Fix 32bit... |
171 172 173 174 175 |
tmp = CMSG_ALIGN(tmp); if (__get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level) || __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type) || copy_from_user(CMSG_DATA(kcmsg), CMSG_COMPAT_DATA(ucmsg), |
1ff8cebf4 scm: remove use C... |
176 |
(ucmlen - sizeof(*ucmsg)))) |
8920e8f94 [PATCH] Fix 32bit... |
177 |
goto Efault; |
1da177e4c Linux-2.6.12-rc2 |
178 179 |
/* Advance. */ |
8920e8f94 [PATCH] Fix 32bit... |
180 |
kcmsg = (struct cmsghdr *)((char *)kcmsg + tmp); |
1da177e4c Linux-2.6.12-rc2 |
181 182 |
ucmsg = cmsg_compat_nxthdr(kmsg, ucmsg, ucmlen); } |
c2a64bb9f net: compat: asse... |
183 184 185 186 187 188 |
/* * check the length of messages copied in is the same as the * what we get from the first loop */ if ((char *)kcmsg - (char *)kcmsg_base != kcmlen) goto Einval; |
1da177e4c Linux-2.6.12-rc2 |
189 190 191 192 |
/* Ok, looks like we made it. Hook it up and return success. */ kmsg->msg_control = kcmsg_base; kmsg->msg_controllen = kcmlen; return 0; |
8920e8f94 [PATCH] Fix 32bit... |
193 194 195 196 197 198 |
Einval: err = -EINVAL; Efault: if (kcmsg_base != (struct cmsghdr *)stackbuf) sock_kfree_s(sk, kcmsg_base, kcmlen); return err; |
1da177e4c Linux-2.6.12-rc2 |
199 200 201 202 |
} int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *data) { |
1da177e4c Linux-2.6.12-rc2 |
203 204 |
struct compat_cmsghdr __user *cm = (struct compat_cmsghdr __user *) kmsg->msg_control; struct compat_cmsghdr cmhdr; |
13c6ee2a9 socket: Use old_t... |
205 206 |
struct old_timeval32 ctv; struct old_timespec32 cts[3]; |
1da177e4c Linux-2.6.12-rc2 |
207 |
int cmlen; |
e71a4783a [NET] core: white... |
208 |
if (cm == NULL || kmsg->msg_controllen < sizeof(*cm)) { |
1da177e4c Linux-2.6.12-rc2 |
209 210 211 |
kmsg->msg_flags |= MSG_CTRUNC; return 0; /* XXX: return error? check spec. */ } |
ee4fa23c4 compat: Use COMPA... |
212 |
if (!COMPAT_USE_64BIT_TIME) { |
7f1bc6e95 sockopt: Rename S... |
213 |
if (level == SOL_SOCKET && type == SO_TIMESTAMP_OLD) { |
13c6ee2a9 socket: Use old_t... |
214 |
struct __kernel_old_timeval *tv = (struct __kernel_old_timeval *)data; |
ee4fa23c4 compat: Use COMPA... |
215 216 217 218 219 220 |
ctv.tv_sec = tv->tv_sec; ctv.tv_usec = tv->tv_usec; data = &ctv; len = sizeof(ctv); } if (level == SOL_SOCKET && |
7f1bc6e95 sockopt: Rename S... |
221 222 |
(type == SO_TIMESTAMPNS_OLD || type == SO_TIMESTAMPING_OLD)) { int count = type == SO_TIMESTAMPNS_OLD ? 1 : 3; |
ee4fa23c4 compat: Use COMPA... |
223 |
int i; |
df1b4ba9d y2038: socket: us... |
224 |
struct __kernel_old_timespec *ts = data; |
ee4fa23c4 compat: Use COMPA... |
225 226 227 228 229 230 |
for (i = 0; i < count; i++) { cts[i].tv_sec = ts[i].tv_sec; cts[i].tv_nsec = ts[i].tv_nsec; } data = &cts; len = sizeof(cts[0]) * count; |
20d494735 net: socket infra... |
231 |
} |
4768fbcbc [NET]: Fix whites... |
232 |
} |
1da177e4c Linux-2.6.12-rc2 |
233 |
cmlen = CMSG_COMPAT_LEN(len); |
e71a4783a [NET] core: white... |
234 |
if (kmsg->msg_controllen < cmlen) { |
1da177e4c Linux-2.6.12-rc2 |
235 236 237 238 239 240 |
kmsg->msg_flags |= MSG_CTRUNC; cmlen = kmsg->msg_controllen; } cmhdr.cmsg_level = level; cmhdr.cmsg_type = type; cmhdr.cmsg_len = cmlen; |
e71a4783a [NET] core: white... |
241 |
if (copy_to_user(cm, &cmhdr, sizeof cmhdr)) |
1da177e4c Linux-2.6.12-rc2 |
242 |
return -EFAULT; |
e71a4783a [NET] core: white... |
243 |
if (copy_to_user(CMSG_COMPAT_DATA(cm), data, cmlen - sizeof(struct compat_cmsghdr))) |
1da177e4c Linux-2.6.12-rc2 |
244 245 |
return -EFAULT; cmlen = CMSG_COMPAT_SPACE(len); |
1ac70e7ad [NET]: Fix functi... |
246 247 |
if (kmsg->msg_controllen < cmlen) cmlen = kmsg->msg_controllen; |
1da177e4c Linux-2.6.12-rc2 |
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 |
kmsg->msg_control += cmlen; kmsg->msg_controllen -= cmlen; return 0; } void scm_detach_fds_compat(struct msghdr *kmsg, struct scm_cookie *scm) { struct compat_cmsghdr __user *cm = (struct compat_cmsghdr __user *) kmsg->msg_control; int fdmax = (kmsg->msg_controllen - sizeof(struct compat_cmsghdr)) / sizeof(int); int fdnum = scm->fp->count; struct file **fp = scm->fp->fp; int __user *cmfptr; int err = 0, i; if (fdnum < fdmax) fdmax = fdnum; for (i = 0, cmfptr = (int __user *) CMSG_COMPAT_DATA(cm); i < fdmax; i++, cmfptr++) { int new_fd; err = security_file_receive(fp[i]); if (err) break; |
4a19542e5 O_CLOEXEC for SCM... |
270 271 |
err = get_unused_fd_flags(MSG_CMSG_CLOEXEC & kmsg->msg_flags ? O_CLOEXEC : 0); |
1da177e4c Linux-2.6.12-rc2 |
272 273 274 275 276 277 278 279 280 |
if (err < 0) break; new_fd = err; err = put_user(new_fd, cmfptr); if (err) { put_unused_fd(new_fd); break; } /* Bump the usage count and install the file. */ |
cb0942b81 make get_file() r... |
281 |
fd_install(new_fd, get_file(fp[i])); |
1da177e4c Linux-2.6.12-rc2 |
282 283 284 285 |
} if (i > 0) { int cmlen = CMSG_COMPAT_LEN(i * sizeof(int)); |
effee6a00 [NET]: File descr... |
286 |
err = put_user(SOL_SOCKET, &cm->cmsg_level); |
1da177e4c Linux-2.6.12-rc2 |
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 |
if (!err) err = put_user(SCM_RIGHTS, &cm->cmsg_type); if (!err) err = put_user(cmlen, &cm->cmsg_len); if (!err) { cmlen = CMSG_COMPAT_SPACE(i * sizeof(int)); kmsg->msg_control += cmlen; kmsg->msg_controllen -= cmlen; } } if (i < fdnum) kmsg->msg_flags |= MSG_CTRUNC; /* * All of the files that fit in the message have had their * usage counts incremented, so we just free the list. */ __scm_destroy(scm); } |
719c44d34 packet: compat su... |
306 307 |
/* allocate a 64-bit sock_fprog on the user stack for duration of syscall. */ struct sock_fprog __user *get_compat_bpf_fprog(char __user *optval) |
1da177e4c Linux-2.6.12-rc2 |
308 309 |
{ struct compat_sock_fprog __user *fprog32 = (struct compat_sock_fprog __user *)optval; |
4768fbcbc [NET]: Fix whites... |
310 |
struct sock_fprog __user *kfprog = compat_alloc_user_space(sizeof(struct sock_fprog)); |
f8f8a727e get_compat_bpf_fp... |
311 312 313 314 315 316 317 318 319 |
struct compat_sock_fprog f32; struct sock_fprog f; if (copy_from_user(&f32, fprog32, sizeof(*fprog32))) return NULL; memset(&f, 0, sizeof(f)); f.len = f32.len; f.filter = compat_ptr(f32.filter); if (copy_to_user(kfprog, &f, sizeof(struct sock_fprog))) |
719c44d34 packet: compat su... |
320 321 322 323 324 325 326 327 328 329 330 331 332 |
return NULL; return kfprog; } EXPORT_SYMBOL_GPL(get_compat_bpf_fprog); static int do_set_attach_filter(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen) { struct sock_fprog __user *kfprog; kfprog = get_compat_bpf_fprog(optval); if (!kfprog) |
1da177e4c Linux-2.6.12-rc2 |
333 |
return -EFAULT; |
3fdadf7d2 [NET]: {get|set}s... |
334 |
return sock_setsockopt(sock, level, optname, (char __user *)kfprog, |
1da177e4c Linux-2.6.12-rc2 |
335 336 |
sizeof(struct sock_fprog)); } |
3fdadf7d2 [NET]: {get|set}s... |
337 |
static int compat_sock_setsockopt(struct socket *sock, int level, int optname, |
b7058842c net: Make setsock... |
338 |
char __user *optval, unsigned int optlen) |
3fdadf7d2 [NET]: {get|set}s... |
339 |
{ |
195759884 soreuseport: add ... |
340 341 |
if (optname == SO_ATTACH_FILTER || optname == SO_ATTACH_REUSEPORT_CBPF) |
3fdadf7d2 [NET]: {get|set}s... |
342 343 |
return do_set_attach_filter(sock, level, optname, optval, optlen); |
3fdadf7d2 [NET]: {get|set}s... |
344 345 |
return sock_setsockopt(sock, level, optname, optval, optlen); } |
73ee3eafd net: socket: add ... |
346 347 |
static int __compat_sys_setsockopt(int fd, int level, int optname, char __user *optval, unsigned int optlen) |
1da177e4c Linux-2.6.12-rc2 |
348 |
{ |
3fdadf7d2 [NET]: {get|set}s... |
349 |
int err; |
52baf9878 net: socket: add ... |
350 |
struct socket *sock; |
3fdadf7d2 [NET]: {get|set}s... |
351 |
|
52baf9878 net: socket: add ... |
352 353 354 355 |
if (optlen > INT_MAX) return -EINVAL; sock = sockfd_lookup(fd, &err); |
c6d409cfd From abbffa2aa9bd... |
356 357 |
if (sock) { err = security_socket_setsockopt(sock, level, optname); |
3fdadf7d2 [NET]: {get|set}s... |
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 |
if (err) { sockfd_put(sock); return err; } if (level == SOL_SOCKET) err = compat_sock_setsockopt(sock, level, optname, optval, optlen); else if (sock->ops->compat_setsockopt) err = sock->ops->compat_setsockopt(sock, level, optname, optval, optlen); else err = sock->ops->setsockopt(sock, level, optname, optval, optlen); sockfd_put(sock); } return err; |
1da177e4c Linux-2.6.12-rc2 |
375 |
} |
73ee3eafd net: socket: add ... |
376 377 378 379 380 |
COMPAT_SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname, char __user *, optval, unsigned int, optlen) { return __compat_sys_setsockopt(fd, level, optname, optval, optlen); } |
8770cf4a5 net: socket: add ... |
381 382 383 |
static int __compat_sys_getsockopt(int fd, int level, int optname, char __user *optval, int __user *optlen) |
3fdadf7d2 [NET]: {get|set}s... |
384 385 |
{ int err; |
c6d409cfd From abbffa2aa9bd... |
386 |
struct socket *sock = sockfd_lookup(fd, &err); |
3fdadf7d2 [NET]: {get|set}s... |
387 |
|
c6d409cfd From abbffa2aa9bd... |
388 389 |
if (sock) { err = security_socket_getsockopt(sock, level, optname); |
3fdadf7d2 [NET]: {get|set}s... |
390 391 392 393 394 395 |
if (err) { sockfd_put(sock); return err; } if (level == SOL_SOCKET) |
fe0c72f3d socket: move comp... |
396 |
err = sock_getsockopt(sock, level, |
3fdadf7d2 [NET]: {get|set}s... |
397 398 399 400 401 402 403 404 405 406 407 |
optname, optval, optlen); else if (sock->ops->compat_getsockopt) err = sock->ops->compat_getsockopt(sock, level, optname, optval, optlen); else err = sock->ops->getsockopt(sock, level, optname, optval, optlen); sockfd_put(sock); } return err; } |
dae502954 ipv4/ipv6 compat:... |
408 |
|
8770cf4a5 net: socket: add ... |
409 410 411 412 413 |
COMPAT_SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname, char __user *, optval, int __user *, optlen) { return __compat_sys_getsockopt(fd, level, optname, optval, optlen); } |
dae502954 ipv4/ipv6 compat:... |
414 415 416 |
struct compat_group_req { __u32 gr_interface; struct __kernel_sockaddr_storage gr_group |
e099b2d9d net: __aligned(si... |
417 |
__aligned(4); |
bc10502db net: use __packed... |
418 |
} __packed; |
dae502954 ipv4/ipv6 compat:... |
419 420 421 422 |
struct compat_group_source_req { __u32 gsr_interface; struct __kernel_sockaddr_storage gsr_group |
e099b2d9d net: __aligned(si... |
423 |
__aligned(4); |
dae502954 ipv4/ipv6 compat:... |
424 |
struct __kernel_sockaddr_storage gsr_source |
e099b2d9d net: __aligned(si... |
425 |
__aligned(4); |
bc10502db net: use __packed... |
426 |
} __packed; |
dae502954 ipv4/ipv6 compat:... |
427 428 429 430 |
struct compat_group_filter { __u32 gf_interface; struct __kernel_sockaddr_storage gf_group |
e099b2d9d net: __aligned(si... |
431 |
__aligned(4); |
dae502954 ipv4/ipv6 compat:... |
432 433 434 |
__u32 gf_fmode; __u32 gf_numsrc; struct __kernel_sockaddr_storage gf_slist[1] |
e099b2d9d net: __aligned(si... |
435 |
__aligned(4); |
bc10502db net: use __packed... |
436 |
} __packed; |
dae502954 ipv4/ipv6 compat:... |
437 |
|
be666e0a1 net: Several clea... |
438 439 |
#define __COMPAT_GF0_SIZE (sizeof(struct compat_group_filter) - \ sizeof(struct __kernel_sockaddr_storage)) |
dae502954 ipv4/ipv6 compat:... |
440 441 |
int compat_mc_setsockopt(struct sock *sock, int level, int optname, |
b7058842c net: Make setsock... |
442 |
char __user *optval, unsigned int optlen, |
c6d409cfd From abbffa2aa9bd... |
443 |
int (*setsockopt)(struct sock *, int, int, char __user *, unsigned int)) |
dae502954 ipv4/ipv6 compat:... |
444 445 446 447 448 449 450 451 |
{ char __user *koptval = optval; int koptlen = optlen; switch (optname) { case MCAST_JOIN_GROUP: case MCAST_LEAVE_GROUP: { |
46d841105 net: fixup addres... |
452 |
struct compat_group_req __user *gr32 = (void __user *)optval; |
dae502954 ipv4/ipv6 compat:... |
453 454 455 |
struct group_req __user *kgr = compat_alloc_user_space(sizeof(struct group_req)); u32 interface; |
96d4f267e Remove 'type' arg... |
456 457 |
if (!access_ok(gr32, sizeof(*gr32)) || !access_ok(kgr, sizeof(struct group_req)) || |
dae502954 ipv4/ipv6 compat:... |
458 459 460 461 462 463 464 465 466 467 468 469 470 471 |
__get_user(interface, &gr32->gr_interface) || __put_user(interface, &kgr->gr_interface) || copy_in_user(&kgr->gr_group, &gr32->gr_group, sizeof(kgr->gr_group))) return -EFAULT; koptval = (char __user *)kgr; koptlen = sizeof(struct group_req); break; } case MCAST_JOIN_SOURCE_GROUP: case MCAST_LEAVE_SOURCE_GROUP: case MCAST_BLOCK_SOURCE: case MCAST_UNBLOCK_SOURCE: { |
46d841105 net: fixup addres... |
472 |
struct compat_group_source_req __user *gsr32 = (void __user *)optval; |
be666e0a1 net: Several clea... |
473 |
struct group_source_req __user *kgsr = compat_alloc_user_space( |
dae502954 ipv4/ipv6 compat:... |
474 475 |
sizeof(struct group_source_req)); u32 interface; |
96d4f267e Remove 'type' arg... |
476 477 |
if (!access_ok(gsr32, sizeof(*gsr32)) || !access_ok(kgsr, |
dae502954 ipv4/ipv6 compat:... |
478 479 480 481 482 483 484 485 486 487 488 489 490 491 |
sizeof(struct group_source_req)) || __get_user(interface, &gsr32->gsr_interface) || __put_user(interface, &kgsr->gsr_interface) || copy_in_user(&kgsr->gsr_group, &gsr32->gsr_group, sizeof(kgsr->gsr_group)) || copy_in_user(&kgsr->gsr_source, &gsr32->gsr_source, sizeof(kgsr->gsr_source))) return -EFAULT; koptval = (char __user *)kgsr; koptlen = sizeof(struct group_source_req); break; } case MCAST_MSFILTER: { |
46d841105 net: fixup addres... |
492 |
struct compat_group_filter __user *gf32 = (void __user *)optval; |
be666e0a1 net: Several clea... |
493 |
struct group_filter __user *kgf; |
dae502954 ipv4/ipv6 compat:... |
494 |
u32 interface, fmode, numsrc; |
96d4f267e Remove 'type' arg... |
495 |
if (!access_ok(gf32, __COMPAT_GF0_SIZE) || |
dae502954 ipv4/ipv6 compat:... |
496 497 498 499 500 501 502 503 504 |
__get_user(interface, &gf32->gf_interface) || __get_user(fmode, &gf32->gf_fmode) || __get_user(numsrc, &gf32->gf_numsrc)) return -EFAULT; koptlen = optlen + sizeof(struct group_filter) - sizeof(struct compat_group_filter); if (koptlen < GROUP_FILTER_SIZE(numsrc)) return -EINVAL; kgf = compat_alloc_user_space(koptlen); |
96d4f267e Remove 'type' arg... |
505 |
if (!access_ok(kgf, koptlen) || |
dae502954 ipv4/ipv6 compat:... |
506 507 508 509 510 |
__put_user(interface, &kgf->gf_interface) || __put_user(fmode, &kgf->gf_fmode) || __put_user(numsrc, &kgf->gf_numsrc) || copy_in_user(&kgf->gf_group, &gf32->gf_group, sizeof(kgf->gf_group)) || |
be666e0a1 net: Several clea... |
511 |
(numsrc && copy_in_user(kgf->gf_slist, gf32->gf_slist, |
dae502954 ipv4/ipv6 compat:... |
512 513 514 515 516 517 518 519 520 521 522 |
numsrc * sizeof(kgf->gf_slist[0])))) return -EFAULT; koptval = (char __user *)kgf; break; } default: break; } return setsockopt(sock, level, optname, koptval, koptlen); } |
dae502954 ipv4/ipv6 compat:... |
523 |
EXPORT_SYMBOL(compat_mc_setsockopt); |
42908c69f net: Add compat s... |
524 525 |
int compat_mc_getsockopt(struct sock *sock, int level, int optname, char __user *optval, int __user *optlen, |
c6d409cfd From abbffa2aa9bd... |
526 |
int (*getsockopt)(struct sock *, int, int, char __user *, int __user *)) |
42908c69f net: Add compat s... |
527 |
{ |
46d841105 net: fixup addres... |
528 |
struct compat_group_filter __user *gf32 = (void __user *)optval; |
42908c69f net: Add compat s... |
529 530 531 532 533 534 535 536 537 |
struct group_filter __user *kgf; int __user *koptlen; u32 interface, fmode, numsrc; int klen, ulen, err; if (optname != MCAST_MSFILTER) return getsockopt(sock, level, optname, optval, optlen); koptlen = compat_alloc_user_space(sizeof(*koptlen)); |
96d4f267e Remove 'type' arg... |
538 |
if (!access_ok(optlen, sizeof(*optlen)) || |
42908c69f net: Add compat s... |
539 540 541 542 543 544 545 546 |
__get_user(ulen, optlen)) return -EFAULT; /* adjust len for pad */ klen = ulen + sizeof(*kgf) - sizeof(*gf32); if (klen < GROUP_FILTER_SIZE(0)) return -EINVAL; |
96d4f267e Remove 'type' arg... |
547 |
if (!access_ok(koptlen, sizeof(*koptlen)) || |
42908c69f net: Add compat s... |
548 549 550 551 552 |
__put_user(klen, koptlen)) return -EFAULT; /* have to allow space for previous compat_alloc_user_space, too */ kgf = compat_alloc_user_space(klen+sizeof(*optlen)); |
96d4f267e Remove 'type' arg... |
553 |
if (!access_ok(gf32, __COMPAT_GF0_SIZE) || |
42908c69f net: Add compat s... |
554 555 556 557 558 559 |
__get_user(interface, &gf32->gf_interface) || __get_user(fmode, &gf32->gf_fmode) || __get_user(numsrc, &gf32->gf_numsrc) || __put_user(interface, &kgf->gf_interface) || __put_user(fmode, &kgf->gf_fmode) || __put_user(numsrc, &kgf->gf_numsrc) || |
c6d409cfd From abbffa2aa9bd... |
560 |
copy_in_user(&kgf->gf_group, &gf32->gf_group, sizeof(kgf->gf_group))) |
42908c69f net: Add compat s... |
561 562 563 564 565 |
return -EFAULT; err = getsockopt(sock, level, optname, (char __user *)kgf, koptlen); if (err) return err; |
96d4f267e Remove 'type' arg... |
566 |
if (!access_ok(koptlen, sizeof(*koptlen)) || |
42908c69f net: Add compat s... |
567 568 569 570 |
__get_user(klen, koptlen)) return -EFAULT; ulen = klen - (sizeof(*kgf)-sizeof(*gf32)); |
96d4f267e Remove 'type' arg... |
571 |
if (!access_ok(optlen, sizeof(*optlen)) || |
42908c69f net: Add compat s... |
572 573 |
__put_user(ulen, optlen)) return -EFAULT; |
96d4f267e Remove 'type' arg... |
574 575 |
if (!access_ok(kgf, klen) || !access_ok(gf32, ulen) || |
42908c69f net: Add compat s... |
576 577 578 579 580 581 582 583 584 585 586 587 588 589 |
__get_user(interface, &kgf->gf_interface) || __get_user(fmode, &kgf->gf_fmode) || __get_user(numsrc, &kgf->gf_numsrc) || __put_user(interface, &gf32->gf_interface) || __put_user(fmode, &gf32->gf_fmode) || __put_user(numsrc, &gf32->gf_numsrc)) return -EFAULT; if (numsrc) { int copylen; klen -= GROUP_FILTER_SIZE(0); copylen = numsrc * sizeof(gf32->gf_slist[0]); if (copylen > klen) copylen = klen; |
c6d409cfd From abbffa2aa9bd... |
590 |
if (copy_in_user(gf32->gf_slist, kgf->gf_slist, copylen)) |
42908c69f net: Add compat s... |
591 592 593 594 |
return -EFAULT; } return err; } |
42908c69f net: Add compat s... |
595 |
EXPORT_SYMBOL(compat_mc_getsockopt); |
dae502954 ipv4/ipv6 compat:... |
596 |
|
1da177e4c Linux-2.6.12-rc2 |
597 598 |
/* Argument list sizes for compat_sys_socketcall */ #define AL(x) ((x) * sizeof(u32)) |
228e548e6 net: Add sendmmsg... |
599 |
static unsigned char nas[21] = { |
c6d409cfd From abbffa2aa9bd... |
600 601 602 |
AL(0), AL(3), AL(3), AL(3), AL(2), AL(3), AL(3), AL(3), AL(4), AL(4), AL(4), AL(6), AL(6), AL(2), AL(5), AL(5), AL(3), AL(3), |
228e548e6 net: Add sendmmsg... |
603 |
AL(4), AL(5), AL(4) |
c6d409cfd From abbffa2aa9bd... |
604 |
}; |
1da177e4c Linux-2.6.12-rc2 |
605 |
#undef AL |
6df354653 net: socket: add ... |
606 607 608 |
static inline long __compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags) |
1da177e4c Linux-2.6.12-rc2 |
609 |
{ |
e1834a329 net: socket: move... |
610 611 |
return __sys_sendmsg(fd, (struct user_msghdr __user *)msg, flags | MSG_CMSG_COMPAT, false); |
1da177e4c Linux-2.6.12-rc2 |
612 |
} |
6df354653 net: socket: add ... |
613 614 615 616 617 618 619 620 621 |
COMPAT_SYSCALL_DEFINE3(sendmsg, int, fd, struct compat_msghdr __user *, msg, unsigned int, flags) { return __compat_sys_sendmsg(fd, msg, flags); } static inline long __compat_sys_sendmmsg(int fd, struct compat_mmsghdr __user *mmsg, unsigned int vlen, unsigned int flags) |
228e548e6 net: Add sendmmsg... |
622 623 |
{ return __sys_sendmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, |
e1834a329 net: socket: move... |
624 |
flags | MSG_CMSG_COMPAT, false); |
228e548e6 net: Add sendmmsg... |
625 |
} |
6df354653 net: socket: add ... |
626 627 628 629 630 631 632 633 634 |
COMPAT_SYSCALL_DEFINE4(sendmmsg, int, fd, struct compat_mmsghdr __user *, mmsg, unsigned int, vlen, unsigned int, flags) { return __compat_sys_sendmmsg(fd, mmsg, vlen, flags); } static inline long __compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags) |
1da177e4c Linux-2.6.12-rc2 |
635 |
{ |
e1834a329 net: socket: move... |
636 637 |
return __sys_recvmsg(fd, (struct user_msghdr __user *)msg, flags | MSG_CMSG_COMPAT, false); |
1da177e4c Linux-2.6.12-rc2 |
638 |
} |
6df354653 net: socket: add ... |
639 640 641 642 643 |
COMPAT_SYSCALL_DEFINE3(recvmsg, int, fd, struct compat_msghdr __user *, msg, unsigned int, flags) { return __compat_sys_recvmsg(fd, msg, flags); } |
fd4e82f5b net: socket: add ... |
644 645 646 647 648 649 650 651 |
static inline long __compat_sys_recvfrom(int fd, void __user *buf, compat_size_t len, unsigned int flags, struct sockaddr __user *addr, int __user *addrlen) { return __sys_recvfrom(fd, buf, len, flags | MSG_CMSG_COMPAT, addr, addrlen); } |
3a49a0f71 net/compat: conve... |
652 |
COMPAT_SYSCALL_DEFINE4(recv, int, fd, void __user *, buf, compat_size_t, len, unsigned int, flags) |
1dacc76d0 net/compat/wext: ... |
653 |
{ |
fd4e82f5b net: socket: add ... |
654 |
return __compat_sys_recvfrom(fd, buf, len, flags, NULL, NULL); |
1dacc76d0 net/compat/wext: ... |
655 |
} |
3a49a0f71 net/compat: conve... |
656 657 658 |
COMPAT_SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, buf, compat_size_t, len, unsigned int, flags, struct sockaddr __user *, addr, int __user *, addrlen) |
1dacc76d0 net/compat/wext: ... |
659 |
{ |
fd4e82f5b net: socket: add ... |
660 |
return __compat_sys_recvfrom(fd, buf, len, flags, addr, addrlen); |
1dacc76d0 net/compat/wext: ... |
661 |
} |
e11d4284e y2038: socket: Ad... |
662 663 664 |
COMPAT_SYSCALL_DEFINE5(recvmmsg_time64, int, fd, struct compat_mmsghdr __user *, mmsg, unsigned int, vlen, unsigned int, flags, struct __kernel_timespec __user *, timeout) |
a2e272554 net: Introduce re... |
665 |
{ |
e11d4284e y2038: socket: Ad... |
666 667 |
return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, flags | MSG_CMSG_COMPAT, timeout, NULL); |
a2e272554 net: Introduce re... |
668 |
} |
e11d4284e y2038: socket: Ad... |
669 |
#ifdef CONFIG_COMPAT_32BIT_TIME |
8dabe7245 y2038: syscalls: ... |
670 |
COMPAT_SYSCALL_DEFINE5(recvmmsg_time32, int, fd, struct compat_mmsghdr __user *, mmsg, |
157b334aa net: socket: add ... |
671 |
unsigned int, vlen, unsigned int, flags, |
9afc5eee6 y2038: globally r... |
672 |
struct old_timespec32 __user *, timeout) |
157b334aa net: socket: add ... |
673 |
{ |
e11d4284e y2038: socket: Ad... |
674 675 |
return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, flags | MSG_CMSG_COMPAT, NULL, timeout); |
157b334aa net: socket: add ... |
676 |
} |
e11d4284e y2038: socket: Ad... |
677 |
#endif |
157b334aa net: socket: add ... |
678 |
|
361d93c46 net/compat: conve... |
679 |
COMPAT_SYSCALL_DEFINE2(socketcall, int, call, u32 __user *, args) |
1da177e4c Linux-2.6.12-rc2 |
680 |
{ |
62bc306e2 audit: log 32-bit... |
681 682 |
u32 a[AUDITSC_ARGS]; unsigned int len; |
1da177e4c Linux-2.6.12-rc2 |
683 |
u32 a0, a1; |
62bc306e2 audit: log 32-bit... |
684 |
int ret; |
4768fbcbc [NET]: Fix whites... |
685 |
|
228e548e6 net: Add sendmmsg... |
686 |
if (call < SYS_SOCKET || call > SYS_SENDMMSG) |
1da177e4c Linux-2.6.12-rc2 |
687 |
return -EINVAL; |
62bc306e2 audit: log 32-bit... |
688 689 690 691 692 |
len = nas[call]; if (len > sizeof(a)) return -EINVAL; if (copy_from_user(a, args, len)) |
1da177e4c Linux-2.6.12-rc2 |
693 |
return -EFAULT; |
62bc306e2 audit: log 32-bit... |
694 695 696 697 |
ret = audit_socketcall_compat(len / sizeof(a[0]), a); if (ret) return ret; |
1da177e4c Linux-2.6.12-rc2 |
698 699 |
a0 = a[0]; a1 = a[1]; |
4768fbcbc [NET]: Fix whites... |
700 |
|
e71a4783a [NET] core: white... |
701 |
switch (call) { |
1da177e4c Linux-2.6.12-rc2 |
702 |
case SYS_SOCKET: |
9d6a15c3f net: socket: add ... |
703 |
ret = __sys_socket(a0, a1, a[2]); |
1da177e4c Linux-2.6.12-rc2 |
704 705 |
break; case SYS_BIND: |
a87d35d87 net: socket: add ... |
706 |
ret = __sys_bind(a0, compat_ptr(a1), a[2]); |
1da177e4c Linux-2.6.12-rc2 |
707 708 |
break; case SYS_CONNECT: |
1387c2c2f net: socket: add ... |
709 |
ret = __sys_connect(a0, compat_ptr(a1), a[2]); |
1da177e4c Linux-2.6.12-rc2 |
710 711 |
break; case SYS_LISTEN: |
25e290eed net: socket: add ... |
712 |
ret = __sys_listen(a0, a1); |
1da177e4c Linux-2.6.12-rc2 |
713 714 |
break; case SYS_ACCEPT: |
4541e8056 net: socket: add ... |
715 |
ret = __sys_accept4(a0, compat_ptr(a1), compat_ptr(a[2]), 0); |
1da177e4c Linux-2.6.12-rc2 |
716 717 |
break; case SYS_GETSOCKNAME: |
8882a107b net: socket: add ... |
718 |
ret = __sys_getsockname(a0, compat_ptr(a1), compat_ptr(a[2])); |
1da177e4c Linux-2.6.12-rc2 |
719 720 |
break; case SYS_GETPEERNAME: |
b21c8f838 net: socket: add ... |
721 |
ret = __sys_getpeername(a0, compat_ptr(a1), compat_ptr(a[2])); |
1da177e4c Linux-2.6.12-rc2 |
722 723 |
break; case SYS_SOCKETPAIR: |
6debc8d83 net: socket: add ... |
724 |
ret = __sys_socketpair(a0, a1, a[2], compat_ptr(a[3])); |
1da177e4c Linux-2.6.12-rc2 |
725 726 |
break; case SYS_SEND: |
f3bf896b1 net: socket: repl... |
727 |
ret = __sys_sendto(a0, compat_ptr(a1), a[2], a[3], NULL, 0); |
1da177e4c Linux-2.6.12-rc2 |
728 729 |
break; case SYS_SENDTO: |
211b634b7 net: socket: add ... |
730 731 |
ret = __sys_sendto(a0, compat_ptr(a1), a[2], a[3], compat_ptr(a[4]), a[5]); |
1da177e4c Linux-2.6.12-rc2 |
732 733 |
break; case SYS_RECV: |
fd4e82f5b net: socket: add ... |
734 735 |
ret = __compat_sys_recvfrom(a0, compat_ptr(a1), a[2], a[3], NULL, NULL); |
1da177e4c Linux-2.6.12-rc2 |
736 737 |
break; case SYS_RECVFROM: |
fd4e82f5b net: socket: add ... |
738 739 740 |
ret = __compat_sys_recvfrom(a0, compat_ptr(a1), a[2], a[3], compat_ptr(a[4]), compat_ptr(a[5])); |
1da177e4c Linux-2.6.12-rc2 |
741 742 |
break; case SYS_SHUTDOWN: |
005a1aeac net: socket: add ... |
743 |
ret = __sys_shutdown(a0, a1); |
1da177e4c Linux-2.6.12-rc2 |
744 745 |
break; case SYS_SETSOCKOPT: |
73ee3eafd net: socket: add ... |
746 747 |
ret = __compat_sys_setsockopt(a0, a1, a[2], compat_ptr(a[3]), a[4]); |
1da177e4c Linux-2.6.12-rc2 |
748 749 |
break; case SYS_GETSOCKOPT: |
8770cf4a5 net: socket: add ... |
750 751 752 |
ret = __compat_sys_getsockopt(a0, a1, a[2], compat_ptr(a[3]), compat_ptr(a[4])); |
1da177e4c Linux-2.6.12-rc2 |
753 754 |
break; case SYS_SENDMSG: |
6df354653 net: socket: add ... |
755 |
ret = __compat_sys_sendmsg(a0, compat_ptr(a1), a[2]); |
1da177e4c Linux-2.6.12-rc2 |
756 |
break; |
228e548e6 net: Add sendmmsg... |
757 |
case SYS_SENDMMSG: |
6df354653 net: socket: add ... |
758 |
ret = __compat_sys_sendmmsg(a0, compat_ptr(a1), a[2], a[3]); |
228e548e6 net: Add sendmmsg... |
759 |
break; |
1da177e4c Linux-2.6.12-rc2 |
760 |
case SYS_RECVMSG: |
6df354653 net: socket: add ... |
761 |
ret = __compat_sys_recvmsg(a0, compat_ptr(a1), a[2]); |
1da177e4c Linux-2.6.12-rc2 |
762 |
break; |
a2e272554 net: Introduce re... |
763 |
case SYS_RECVMMSG: |
e11d4284e y2038: socket: Ad... |
764 765 766 |
ret = __sys_recvmmsg(a0, compat_ptr(a1), a[2], a[3] | MSG_CMSG_COMPAT, NULL, compat_ptr(a[4])); |
a2e272554 net: Introduce re... |
767 |
break; |
de11defeb reintroduce accept4 |
768 |
case SYS_ACCEPT4: |
4541e8056 net: socket: add ... |
769 |
ret = __sys_accept4(a0, compat_ptr(a1), compat_ptr(a[2]), a[3]); |
aaca0bdca flag parameters: ... |
770 |
break; |
1da177e4c Linux-2.6.12-rc2 |
771 772 773 774 775 776 |
default: ret = -EINVAL; break; } return ret; } |