Blame view

net/compat.c 22.5 KB
457c89965   Thomas Gleixner   treewide: Add SPD...
1
  // SPDX-License-Identifier: GPL-2.0-only
4768fbcbc   YOSHIFUJI Hideaki   [NET]: Fix whites...
2
  /*
1da177e4c   Linus Torvalds   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   YOSHIFUJI Hideaki   [NET]: Fix whites...
12
   * Copyright (C) 2000,2001	Andi Kleen, SuSE Labs
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
14
15
   */
  
  #include <linux/kernel.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
16
  #include <linux/gfp.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
  #include <linux/fs.h>
1da177e4c   Linus Torvalds   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   Linus Torvalds   Linux-2.6.12-rc2
25
  #include <linux/security.h>
62bc306e2   Richard Guy Briggs   audit: log 32-bit...
26
  #include <linux/audit.h>
bc3b2d7fb   Paul Gortmaker   net: Add export.h...
27
  #include <linux/export.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
29
30
  
  #include <net/scm.h>
  #include <net/sock.h>
dae502954   David L Stevens   ipv4/ipv6 compat:...
31
32
  #include <net/ip.h>
  #include <net/ipv6.h>
7c0f6ba68   Linus Torvalds   Replace <asm/uacc...
33
  #include <linux/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
  #include <net/compat.h>
da1842849   Al Viro   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   Linus Torvalds   Linux-2.6.12-rc2
39
  {
5da028a8a   Al Viro   get_compat_msghdr...
40
  	struct compat_msghdr msg;
08adb7dab   Al Viro   fold verify_iovec...
41
  	ssize_t err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42

5da028a8a   Al Viro   get_compat_msghdr...
43
  	if (copy_from_user(&msg, umsg, sizeof(*umsg)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
  		return -EFAULT;
91edd096e   Catalin Marinas   net: compat: Upda...
45

5da028a8a   Al Viro   get_compat_msghdr...
46
47
48
49
  	kmsg->msg_flags = msg.msg_flags;
  	kmsg->msg_namelen = msg.msg_namelen;
  
  	if (!msg.msg_name)
91edd096e   Catalin Marinas   net: compat: Upda...
50
51
52
53
  		kmsg->msg_namelen = 0;
  
  	if (kmsg->msg_namelen < 0)
  		return -EINVAL;
1661bf364   Dan Carpenter   net: heap overflo...
54
  	if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
db31c55a6   Dan Carpenter   net: clamp ->msg_...
55
  		kmsg->msg_namelen = sizeof(struct sockaddr_storage);
5da028a8a   Al Viro   get_compat_msghdr...
56
57
58
  
  	kmsg->msg_control = compat_ptr(msg.msg_control);
  	kmsg->msg_controllen = msg.msg_controllen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59

08adb7dab   Al Viro   fold verify_iovec...
60
  	if (save_addr)
5da028a8a   Al Viro   get_compat_msghdr...
61
  		*save_addr = compat_ptr(msg.msg_name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62

5da028a8a   Al Viro   get_compat_msghdr...
63
  	if (msg.msg_name && kmsg->msg_namelen) {
08adb7dab   Al Viro   fold verify_iovec...
64
  		if (!save_addr) {
5da028a8a   Al Viro   get_compat_msghdr...
65
  			err = move_addr_to_kernel(compat_ptr(msg.msg_name),
08adb7dab   Al Viro   fold verify_iovec...
66
67
  						  kmsg->msg_namelen,
  						  kmsg->msg_name);
e71a4783a   Stephen Hemminger   [NET] core: white...
68
  			if (err < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
70
  				return err;
  		}
40eea803c   Andrey Ryabinin   net: sendmsg: fix...
71
  	} else {
08adb7dab   Al Viro   fold verify_iovec...
72
73
  		kmsg->msg_name = NULL;
  		kmsg->msg_namelen = 0;
40eea803c   Andrey Ryabinin   net: sendmsg: fix...
74
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75

5da028a8a   Al Viro   get_compat_msghdr...
76
  	if (msg.msg_iovlen > UIO_MAXIOV)
084493200   Al Viro   {compat_,}verify_...
77
  		return -EMSGSIZE;
0345f9313   tadeusz.struk@intel.com   net: socket: add ...
78
  	kmsg->msg_iocb = NULL;
87e5e6dab   Jens Axboe   uio: make import_...
79
  	err = compat_import_iovec(save_addr ? READ : WRITE,
5da028a8a   Al Viro   get_compat_msghdr...
80
  				   compat_ptr(msg.msg_iov), msg.msg_iovlen,
da1842849   Al Viro   net: switch impor...
81
  				   UIO_FASTIOV, iov, &kmsg->msg_iter);
87e5e6dab   Jens Axboe   uio: make import_...
82
  	return err < 0 ? err : 0;
1da177e4c   Linus Torvalds   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   yuan linyu   scm: remove use C...
89
  	((void __user *)((char __user *)(cmsg) + sizeof(struct compat_cmsghdr)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
  #define CMSG_COMPAT_SPACE(len)				\
1ff8cebf4   yuan linyu   scm: remove use C...
91
  	(sizeof(struct compat_cmsghdr) + CMSG_COMPAT_ALIGN(len))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
  #define CMSG_COMPAT_LEN(len)				\
1ff8cebf4   yuan linyu   scm: remove use C...
93
  	(sizeof(struct compat_cmsghdr) + (len))
1da177e4c   Linus Torvalds   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   Al Viro   [PATCH] Fix 32bit...
120
  int cmsghdr_from_user_compat_to_kern(struct msghdr *kmsg, struct sock *sk,
1da177e4c   Linus Torvalds   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   Al Viro   [PATCH] Fix 32bit...
127
  	int err = -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128

ac4340fc3   David S. Miller   net: Assert at bu...
129
130
  	BUILD_BUG_ON(sizeof(struct compat_cmsghdr) !=
  		     CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr)));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
132
133
  	kcmlen = 0;
  	kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
  	ucmsg = CMSG_COMPAT_FIRSTHDR(kmsg);
e71a4783a   Stephen Hemminger   [NET] core: white...
134
135
  	while (ucmsg != NULL) {
  		if (get_user(ucmlen, &ucmsg->cmsg_len))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
137
138
139
140
  			return -EFAULT;
  
  		/* Catch bogons. */
  		if (!CMSG_COMPAT_OK(ucmlen, ucmsg, kmsg))
  			return -EINVAL;
1ff8cebf4   yuan linyu   scm: remove use C...
141
  		tmp = ((ucmlen - sizeof(*ucmsg)) + sizeof(struct cmsghdr));
8920e8f94   Al Viro   [PATCH] Fix 32bit...
142
  		tmp = CMSG_ALIGN(tmp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143
144
145
  		kcmlen += tmp;
  		ucmsg = cmsg_compat_nxthdr(kmsg, ucmsg, ucmlen);
  	}
e71a4783a   Stephen Hemminger   [NET] core: white...
146
  	if (kcmlen == 0)
1da177e4c   Linus Torvalds   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   Al Viro   [PATCH] Fix 32bit...
154
155
156
  	if (kcmlen > stackbuf_size)
  		kcmsg_base = kcmsg = sock_kmalloc(sk, kcmlen, GFP_KERNEL);
  	if (kcmsg == NULL)
1da177e4c   Linus Torvalds   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   Stephen Hemminger   [NET] core: white...
162
  	while (ucmsg != NULL) {
8920e8f94   Al Viro   [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   yuan linyu   scm: remove use C...
167
  		tmp = ((ucmlen - sizeof(*ucmsg)) + sizeof(struct cmsghdr));
8920e8f94   Al Viro   [PATCH] Fix 32bit...
168
169
  		if ((char *)kcmsg_base + kcmlen - (char *)kcmsg < CMSG_ALIGN(tmp))
  			goto Einval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
  		kcmsg->cmsg_len = tmp;
8920e8f94   Al Viro   [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   yuan linyu   scm: remove use C...
176
  				   (ucmlen - sizeof(*ucmsg))))
8920e8f94   Al Viro   [PATCH] Fix 32bit...
177
  			goto Efault;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178
179
  
  		/* Advance. */
8920e8f94   Al Viro   [PATCH] Fix 32bit...
180
  		kcmsg = (struct cmsghdr *)((char *)kcmsg + tmp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
181
182
  		ucmsg = cmsg_compat_nxthdr(kmsg, ucmsg, ucmlen);
  	}
c2a64bb9f   Meng Xu   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   Linus Torvalds   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   Al Viro   [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   Linus Torvalds   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   Linus Torvalds   Linux-2.6.12-rc2
203
204
  	struct compat_cmsghdr __user *cm = (struct compat_cmsghdr __user *) kmsg->msg_control;
  	struct compat_cmsghdr cmhdr;
13c6ee2a9   Deepa Dinamani   socket: Use old_t...
205
206
  	struct old_timeval32 ctv;
  	struct old_timespec32 cts[3];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
207
  	int cmlen;
e71a4783a   Stephen Hemminger   [NET] core: white...
208
  	if (cm == NULL || kmsg->msg_controllen < sizeof(*cm)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209
210
211
  		kmsg->msg_flags |= MSG_CTRUNC;
  		return 0; /* XXX: return error? check spec. */
  	}
ee4fa23c4   H. J. Lu   compat: Use COMPA...
212
  	if (!COMPAT_USE_64BIT_TIME) {
7f1bc6e95   Deepa Dinamani   sockopt: Rename S...
213
  		if (level == SOL_SOCKET && type == SO_TIMESTAMP_OLD) {
13c6ee2a9   Deepa Dinamani   socket: Use old_t...
214
  			struct __kernel_old_timeval *tv = (struct __kernel_old_timeval *)data;
ee4fa23c4   H. J. Lu   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   Deepa Dinamani   sockopt: Rename S...
221
222
  		    (type == SO_TIMESTAMPNS_OLD || type == SO_TIMESTAMPING_OLD)) {
  			int count = type == SO_TIMESTAMPNS_OLD ? 1 : 3;
ee4fa23c4   H. J. Lu   compat: Use COMPA...
223
224
225
226
227
228
229
230
  			int i;
  			struct timespec *ts = (struct timespec *)data;
  			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   Patrick Ohly   net: socket infra...
231
  		}
4768fbcbc   YOSHIFUJI Hideaki   [NET]: Fix whites...
232
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
233
  	cmlen = CMSG_COMPAT_LEN(len);
e71a4783a   Stephen Hemminger   [NET] core: white...
234
  	if (kmsg->msg_controllen < cmlen) {
1da177e4c   Linus Torvalds   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   Stephen Hemminger   [NET] core: white...
241
  	if (copy_to_user(cm, &cmhdr, sizeof cmhdr))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
242
  		return -EFAULT;
e71a4783a   Stephen Hemminger   [NET] core: white...
243
  	if (copy_to_user(CMSG_COMPAT_DATA(cm), data, cmlen - sizeof(struct compat_cmsghdr)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
244
245
  		return -EFAULT;
  	cmlen = CMSG_COMPAT_SPACE(len);
1ac70e7ad   Wei Yongjun   [NET]: Fix functi...
246
247
  	if (kmsg->msg_controllen < cmlen)
  		cmlen = kmsg->msg_controllen;
1da177e4c   Linus Torvalds   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   Ulrich Drepper   O_CLOEXEC for SCM...
270
271
  		err = get_unused_fd_flags(MSG_CMSG_CLOEXEC & kmsg->msg_flags
  					  ? O_CLOEXEC : 0);
1da177e4c   Linus Torvalds   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   Al Viro   make get_file() r...
281
  		fd_install(new_fd, get_file(fp[i]));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
282
283
284
285
  	}
  
  	if (i > 0) {
  		int cmlen = CMSG_COMPAT_LEN(i * sizeof(int));
effee6a00   Miklos Szeredi   [NET]: File descr...
286
  		err = put_user(SOL_SOCKET, &cm->cmsg_level);
1da177e4c   Linus Torvalds   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   Willem de Bruijn   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   Linus Torvalds   Linux-2.6.12-rc2
308
309
  {
  	struct compat_sock_fprog __user *fprog32 = (struct compat_sock_fprog __user *)optval;
4768fbcbc   YOSHIFUJI Hideaki   [NET]: Fix whites...
310
  	struct sock_fprog __user *kfprog = compat_alloc_user_space(sizeof(struct sock_fprog));
f8f8a727e   Al Viro   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   Willem de Bruijn   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   Linus Torvalds   Linux-2.6.12-rc2
333
  		return -EFAULT;
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
334
  	return sock_setsockopt(sock, level, optname, (char __user *)kfprog,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335
336
  			      sizeof(struct sock_fprog));
  }
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
337
  static int compat_sock_setsockopt(struct socket *sock, int level, int optname,
b7058842c   David S. Miller   net: Make setsock...
338
  				char __user *optval, unsigned int optlen)
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
339
  {
195759884   Helge Deller   soreuseport: add ...
340
341
  	if (optname == SO_ATTACH_FILTER ||
  	    optname == SO_ATTACH_REUSEPORT_CBPF)
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
342
343
  		return do_set_attach_filter(sock, level, optname,
  					    optval, optlen);
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
344
345
  	return sock_setsockopt(sock, level, optname, optval, optlen);
  }
73ee3eafd   Dominik Brodowski   net: socket: add ...
346
347
  static int __compat_sys_setsockopt(int fd, int level, int optname,
  				   char __user *optval, unsigned int optlen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
348
  {
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
349
  	int err;
52baf9878   Jann Horn   net: socket: add ...
350
  	struct socket *sock;
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
351

52baf9878   Jann Horn   net: socket: add ...
352
353
354
355
  	if (optlen > INT_MAX)
  		return -EINVAL;
  
  	sock = sockfd_lookup(fd, &err);
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
356
357
  	if (sock) {
  		err = security_socket_setsockopt(sock, level, optname);
3fdadf7d2   Dmitry Mishin   [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   Linus Torvalds   Linux-2.6.12-rc2
375
  }
73ee3eafd   Dominik Brodowski   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   Dominik Brodowski   net: socket: add ...
381
382
383
  static int __compat_sys_getsockopt(int fd, int level, int optname,
  				   char __user *optval,
  				   int __user *optlen)
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
384
385
  {
  	int err;
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
386
  	struct socket *sock = sockfd_lookup(fd, &err);
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
387

c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
388
389
  	if (sock) {
  		err = security_socket_getsockopt(sock, level, optname);
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
390
391
392
393
394
395
  		if (err) {
  			sockfd_put(sock);
  			return err;
  		}
  
  		if (level == SOL_SOCKET)
fe0c72f3d   Arnd Bergmann   socket: move comp...
396
  			err = sock_getsockopt(sock, level,
3fdadf7d2   Dmitry Mishin   [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   David L Stevens   ipv4/ipv6 compat:...
408

8770cf4a5   Dominik Brodowski   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   David L Stevens   ipv4/ipv6 compat:...
414
415
416
  struct compat_group_req {
  	__u32				 gr_interface;
  	struct __kernel_sockaddr_storage gr_group
e099b2d9d   Ameen Ali   net: __aligned(si...
417
  		__aligned(4);
bc10502db   Eric Dumazet   net: use __packed...
418
  } __packed;
dae502954   David L Stevens   ipv4/ipv6 compat:...
419
420
421
422
  
  struct compat_group_source_req {
  	__u32				 gsr_interface;
  	struct __kernel_sockaddr_storage gsr_group
e099b2d9d   Ameen Ali   net: __aligned(si...
423
  		__aligned(4);
dae502954   David L Stevens   ipv4/ipv6 compat:...
424
  	struct __kernel_sockaddr_storage gsr_source
e099b2d9d   Ameen Ali   net: __aligned(si...
425
  		__aligned(4);
bc10502db   Eric Dumazet   net: use __packed...
426
  } __packed;
dae502954   David L Stevens   ipv4/ipv6 compat:...
427
428
429
430
  
  struct compat_group_filter {
  	__u32				 gf_interface;
  	struct __kernel_sockaddr_storage gf_group
e099b2d9d   Ameen Ali   net: __aligned(si...
431
  		__aligned(4);
dae502954   David L Stevens   ipv4/ipv6 compat:...
432
433
434
  	__u32				 gf_fmode;
  	__u32				 gf_numsrc;
  	struct __kernel_sockaddr_storage gf_slist[1]
e099b2d9d   Ameen Ali   net: __aligned(si...
435
  		__aligned(4);
bc10502db   Eric Dumazet   net: use __packed...
436
  } __packed;
dae502954   David L Stevens   ipv4/ipv6 compat:...
437

be666e0a1   David L Stevens   net: Several clea...
438
439
  #define __COMPAT_GF0_SIZE (sizeof(struct compat_group_filter) - \
  			sizeof(struct __kernel_sockaddr_storage))
dae502954   David L Stevens   ipv4/ipv6 compat:...
440
441
  
  int compat_mc_setsockopt(struct sock *sock, int level, int optname,
b7058842c   David S. Miller   net: Make setsock...
442
  	char __user *optval, unsigned int optlen,
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
443
  	int (*setsockopt)(struct sock *, int, int, char __user *, unsigned int))
dae502954   David L Stevens   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   Ben Dooks   net: fixup addres...
452
  		struct compat_group_req __user *gr32 = (void __user *)optval;
dae502954   David L Stevens   ipv4/ipv6 compat:...
453
454
455
  		struct group_req __user *kgr =
  			compat_alloc_user_space(sizeof(struct group_req));
  		u32 interface;
96d4f267e   Linus Torvalds   Remove 'type' arg...
456
457
  		if (!access_ok(gr32, sizeof(*gr32)) ||
  		    !access_ok(kgr, sizeof(struct group_req)) ||
dae502954   David L Stevens   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   Ben Dooks   net: fixup addres...
472
  		struct compat_group_source_req __user *gsr32 = (void __user *)optval;
be666e0a1   David L Stevens   net: Several clea...
473
  		struct group_source_req __user *kgsr = compat_alloc_user_space(
dae502954   David L Stevens   ipv4/ipv6 compat:...
474
475
  			sizeof(struct group_source_req));
  		u32 interface;
96d4f267e   Linus Torvalds   Remove 'type' arg...
476
477
  		if (!access_ok(gsr32, sizeof(*gsr32)) ||
  		    !access_ok(kgsr,
dae502954   David L Stevens   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   Ben Dooks   net: fixup addres...
492
  		struct compat_group_filter __user *gf32 = (void __user *)optval;
be666e0a1   David L Stevens   net: Several clea...
493
  		struct group_filter __user *kgf;
dae502954   David L Stevens   ipv4/ipv6 compat:...
494
  		u32 interface, fmode, numsrc;
96d4f267e   Linus Torvalds   Remove 'type' arg...
495
  		if (!access_ok(gf32, __COMPAT_GF0_SIZE) ||
dae502954   David L Stevens   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   Linus Torvalds   Remove 'type' arg...
505
  		if (!access_ok(kgf, koptlen) ||
dae502954   David L Stevens   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   David L Stevens   net: Several clea...
511
  		    (numsrc && copy_in_user(kgf->gf_slist, gf32->gf_slist,
dae502954   David L Stevens   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   David L Stevens   ipv4/ipv6 compat:...
523
  EXPORT_SYMBOL(compat_mc_setsockopt);
42908c69f   David L Stevens   net: Add compat s...
524
525
  int compat_mc_getsockopt(struct sock *sock, int level, int optname,
  	char __user *optval, int __user *optlen,
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
526
  	int (*getsockopt)(struct sock *, int, int, char __user *, int __user *))
42908c69f   David L Stevens   net: Add compat s...
527
  {
46d841105   Ben Dooks   net: fixup addres...
528
  	struct compat_group_filter __user *gf32 = (void __user *)optval;
42908c69f   David L Stevens   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   Linus Torvalds   Remove 'type' arg...
538
  	if (!access_ok(optlen, sizeof(*optlen)) ||
42908c69f   David L Stevens   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   Linus Torvalds   Remove 'type' arg...
547
  	if (!access_ok(koptlen, sizeof(*koptlen)) ||
42908c69f   David L Stevens   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   Linus Torvalds   Remove 'type' arg...
553
  	if (!access_ok(gf32, __COMPAT_GF0_SIZE) ||
42908c69f   David L Stevens   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   Eric Dumazet   From abbffa2aa9bd...
560
  	    copy_in_user(&kgf->gf_group, &gf32->gf_group, sizeof(kgf->gf_group)))
42908c69f   David L Stevens   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   Linus Torvalds   Remove 'type' arg...
566
  	if (!access_ok(koptlen, sizeof(*koptlen)) ||
42908c69f   David L Stevens   net: Add compat s...
567
568
569
570
  	    __get_user(klen, koptlen))
  		return -EFAULT;
  
  	ulen = klen - (sizeof(*kgf)-sizeof(*gf32));
96d4f267e   Linus Torvalds   Remove 'type' arg...
571
  	if (!access_ok(optlen, sizeof(*optlen)) ||
42908c69f   David L Stevens   net: Add compat s...
572
573
  	    __put_user(ulen, optlen))
  		return -EFAULT;
96d4f267e   Linus Torvalds   Remove 'type' arg...
574
575
  	if (!access_ok(kgf, klen) ||
  	    !access_ok(gf32, ulen) ||
42908c69f   David L Stevens   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   Eric Dumazet   From abbffa2aa9bd...
590
  		if (copy_in_user(gf32->gf_slist, kgf->gf_slist, copylen))
42908c69f   David L Stevens   net: Add compat s...
591
592
593
594
  			return -EFAULT;
  	}
  	return err;
  }
42908c69f   David L Stevens   net: Add compat s...
595
  EXPORT_SYMBOL(compat_mc_getsockopt);
dae502954   David L Stevens   ipv4/ipv6 compat:...
596

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
597
598
  /* Argument list sizes for compat_sys_socketcall */
  #define AL(x) ((x) * sizeof(u32))
228e548e6   Anton Blanchard   net: Add sendmmsg...
599
  static unsigned char nas[21] = {
c6d409cfd   Eric Dumazet   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   Anton Blanchard   net: Add sendmmsg...
603
  	AL(4), AL(5), AL(4)
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
604
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
605
  #undef AL
6df354653   Dominik Brodowski   net: socket: add ...
606
607
608
  static inline long __compat_sys_sendmsg(int fd,
  					struct compat_msghdr __user *msg,
  					unsigned int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
609
  {
e1834a329   Dominik Brodowski   net: socket: move...
610
611
  	return __sys_sendmsg(fd, (struct user_msghdr __user *)msg,
  			     flags | MSG_CMSG_COMPAT, false);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
612
  }
6df354653   Dominik Brodowski   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   Anton Blanchard   net: Add sendmmsg...
622
623
  {
  	return __sys_sendmmsg(fd, (struct mmsghdr __user *)mmsg, vlen,
e1834a329   Dominik Brodowski   net: socket: move...
624
  			      flags | MSG_CMSG_COMPAT, false);
228e548e6   Anton Blanchard   net: Add sendmmsg...
625
  }
6df354653   Dominik Brodowski   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   Linus Torvalds   Linux-2.6.12-rc2
635
  {
e1834a329   Dominik Brodowski   net: socket: move...
636
637
  	return __sys_recvmsg(fd, (struct user_msghdr __user *)msg,
  			     flags | MSG_CMSG_COMPAT, false);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
638
  }
6df354653   Dominik Brodowski   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   Dominik Brodowski   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   Heiko Carstens   net/compat: conve...
652
  COMPAT_SYSCALL_DEFINE4(recv, int, fd, void __user *, buf, compat_size_t, len, unsigned int, flags)
1dacc76d0   Johannes Berg   net/compat/wext: ...
653
  {
fd4e82f5b   Dominik Brodowski   net: socket: add ...
654
  	return __compat_sys_recvfrom(fd, buf, len, flags, NULL, NULL);
1dacc76d0   Johannes Berg   net/compat/wext: ...
655
  }
3a49a0f71   Heiko Carstens   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   Johannes Berg   net/compat/wext: ...
659
  {
fd4e82f5b   Dominik Brodowski   net: socket: add ...
660
  	return __compat_sys_recvfrom(fd, buf, len, flags, addr, addrlen);
1dacc76d0   Johannes Berg   net/compat/wext: ...
661
  }
e11d4284e   Arnd Bergmann   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   Arnaldo Carvalho de Melo   net: Introduce re...
665
  {
e11d4284e   Arnd Bergmann   y2038: socket: Ad...
666
667
  	return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen,
  			      flags | MSG_CMSG_COMPAT, timeout, NULL);
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
668
  }
e11d4284e   Arnd Bergmann   y2038: socket: Ad...
669
  #ifdef CONFIG_COMPAT_32BIT_TIME
8dabe7245   Arnd Bergmann   y2038: syscalls: ...
670
  COMPAT_SYSCALL_DEFINE5(recvmmsg_time32, int, fd, struct compat_mmsghdr __user *, mmsg,
157b334aa   Dominik Brodowski   net: socket: add ...
671
  		       unsigned int, vlen, unsigned int, flags,
9afc5eee6   Arnd Bergmann   y2038: globally r...
672
  		       struct old_timespec32 __user *, timeout)
157b334aa   Dominik Brodowski   net: socket: add ...
673
  {
e11d4284e   Arnd Bergmann   y2038: socket: Ad...
674
675
  	return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen,
  			      flags | MSG_CMSG_COMPAT, NULL, timeout);
157b334aa   Dominik Brodowski   net: socket: add ...
676
  }
e11d4284e   Arnd Bergmann   y2038: socket: Ad...
677
  #endif
157b334aa   Dominik Brodowski   net: socket: add ...
678

361d93c46   Heiko Carstens   net/compat: conve...
679
  COMPAT_SYSCALL_DEFINE2(socketcall, int, call, u32 __user *, args)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
680
  {
62bc306e2   Richard Guy Briggs   audit: log 32-bit...
681
682
  	u32 a[AUDITSC_ARGS];
  	unsigned int len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
683
  	u32 a0, a1;
62bc306e2   Richard Guy Briggs   audit: log 32-bit...
684
  	int ret;
4768fbcbc   YOSHIFUJI Hideaki   [NET]: Fix whites...
685

228e548e6   Anton Blanchard   net: Add sendmmsg...
686
  	if (call < SYS_SOCKET || call > SYS_SENDMMSG)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
687
  		return -EINVAL;
62bc306e2   Richard Guy Briggs   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   Linus Torvalds   Linux-2.6.12-rc2
693
  		return -EFAULT;
62bc306e2   Richard Guy Briggs   audit: log 32-bit...
694
695
696
697
  
  	ret = audit_socketcall_compat(len / sizeof(a[0]), a);
  	if (ret)
  		return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
698
699
  	a0 = a[0];
  	a1 = a[1];
4768fbcbc   YOSHIFUJI Hideaki   [NET]: Fix whites...
700

e71a4783a   Stephen Hemminger   [NET] core: white...
701
  	switch (call) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
702
  	case SYS_SOCKET:
9d6a15c3f   Dominik Brodowski   net: socket: add ...
703
  		ret = __sys_socket(a0, a1, a[2]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
704
705
  		break;
  	case SYS_BIND:
a87d35d87   Dominik Brodowski   net: socket: add ...
706
  		ret = __sys_bind(a0, compat_ptr(a1), a[2]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
707
708
  		break;
  	case SYS_CONNECT:
1387c2c2f   Dominik Brodowski   net: socket: add ...
709
  		ret = __sys_connect(a0, compat_ptr(a1), a[2]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
710
711
  		break;
  	case SYS_LISTEN:
25e290eed   Dominik Brodowski   net: socket: add ...
712
  		ret = __sys_listen(a0, a1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
713
714
  		break;
  	case SYS_ACCEPT:
4541e8056   Dominik Brodowski   net: socket: add ...
715
  		ret = __sys_accept4(a0, compat_ptr(a1), compat_ptr(a[2]), 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
716
717
  		break;
  	case SYS_GETSOCKNAME:
8882a107b   Dominik Brodowski   net: socket: add ...
718
  		ret = __sys_getsockname(a0, compat_ptr(a1), compat_ptr(a[2]));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
719
720
  		break;
  	case SYS_GETPEERNAME:
b21c8f838   Dominik Brodowski   net: socket: add ...
721
  		ret = __sys_getpeername(a0, compat_ptr(a1), compat_ptr(a[2]));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
722
723
  		break;
  	case SYS_SOCKETPAIR:
6debc8d83   Dominik Brodowski   net: socket: add ...
724
  		ret = __sys_socketpair(a0, a1, a[2], compat_ptr(a[3]));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
725
726
  		break;
  	case SYS_SEND:
f3bf896b1   Dominik Brodowski   net: socket: repl...
727
  		ret = __sys_sendto(a0, compat_ptr(a1), a[2], a[3], NULL, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
728
729
  		break;
  	case SYS_SENDTO:
211b634b7   Dominik Brodowski   net: socket: add ...
730
731
  		ret = __sys_sendto(a0, compat_ptr(a1), a[2], a[3],
  				   compat_ptr(a[4]), a[5]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
732
733
  		break;
  	case SYS_RECV:
fd4e82f5b   Dominik Brodowski   net: socket: add ...
734
735
  		ret = __compat_sys_recvfrom(a0, compat_ptr(a1), a[2], a[3],
  					    NULL, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
736
737
  		break;
  	case SYS_RECVFROM:
fd4e82f5b   Dominik Brodowski   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   Linus Torvalds   Linux-2.6.12-rc2
741
742
  		break;
  	case SYS_SHUTDOWN:
005a1aeac   Dominik Brodowski   net: socket: add ...
743
  		ret = __sys_shutdown(a0, a1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
744
745
  		break;
  	case SYS_SETSOCKOPT:
73ee3eafd   Dominik Brodowski   net: socket: add ...
746
747
  		ret = __compat_sys_setsockopt(a0, a1, a[2],
  					      compat_ptr(a[3]), a[4]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
748
749
  		break;
  	case SYS_GETSOCKOPT:
8770cf4a5   Dominik Brodowski   net: socket: add ...
750
751
752
  		ret = __compat_sys_getsockopt(a0, a1, a[2],
  					      compat_ptr(a[3]),
  					      compat_ptr(a[4]));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
753
754
  		break;
  	case SYS_SENDMSG:
6df354653   Dominik Brodowski   net: socket: add ...
755
  		ret = __compat_sys_sendmsg(a0, compat_ptr(a1), a[2]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
756
  		break;
228e548e6   Anton Blanchard   net: Add sendmmsg...
757
  	case SYS_SENDMMSG:
6df354653   Dominik Brodowski   net: socket: add ...
758
  		ret = __compat_sys_sendmmsg(a0, compat_ptr(a1), a[2], a[3]);
228e548e6   Anton Blanchard   net: Add sendmmsg...
759
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
760
  	case SYS_RECVMSG:
6df354653   Dominik Brodowski   net: socket: add ...
761
  		ret = __compat_sys_recvmsg(a0, compat_ptr(a1), a[2]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
762
  		break;
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
763
  	case SYS_RECVMMSG:
e11d4284e   Arnd Bergmann   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   Arnaldo Carvalho de Melo   net: Introduce re...
767
  		break;
de11defeb   Ulrich Drepper   reintroduce accept4
768
  	case SYS_ACCEPT4:
4541e8056   Dominik Brodowski   net: socket: add ...
769
  		ret = __sys_accept4(a0, compat_ptr(a1), compat_ptr(a[2]), a[3]);
aaca0bdca   Ulrich Drepper   flag parameters: ...
770
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
771
772
773
774
775
776
  	default:
  		ret = -EINVAL;
  		break;
  	}
  	return ret;
  }