Blame view

net/socket.c 81.8 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
  /*
   * NET		An implementation of the SOCKET network access protocol.
   *
   * Version:	@(#)socket.c	1.1.93	18/02/95
   *
   * Authors:	Orest Zborowski, <obz@Kodak.COM>
02c30a84e   Jesper Juhl   [PATCH] update Ro...
7
   *		Ross Biro
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
   *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
   *
   * Fixes:
   *		Anonymous	:	NOTSOCK/BADF cleanup. Error fix in
   *					shutdown()
   *		Alan Cox	:	verify_area() fixes
   *		Alan Cox	:	Removed DDI
   *		Jonathan Kamens	:	SOCK_DGRAM reconnect bug
   *		Alan Cox	:	Moved a load of checks to the very
   *					top level.
   *		Alan Cox	:	Move address structures to/from user
   *					mode above the protocol layers.
   *		Rob Janssen	:	Allow 0 length sends.
   *		Alan Cox	:	Asynchronous I/O support (cribbed from the
   *					tty drivers).
   *		Niibe Yutaka	:	Asynchronous I/O for writes (4.4BSD style)
   *		Jeff Uphoff	:	Made max number of sockets command-line
   *					configurable.
   *		Matti Aarnio	:	Made the number of sockets dynamic,
   *					to be allocated when needed, and mr.
   *					Uphoff's max is used as max to be
   *					allowed to allocate.
   *		Linus		:	Argh. removed all the socket allocation
   *					altogether: it's in the inode now.
   *		Alan Cox	:	Made sock_alloc()/sock_release() public
   *					for NetROM and future kernel nfsd type
   *					stuff.
   *		Alan Cox	:	sendmsg/recvmsg basics.
   *		Tom Dyas	:	Export net symbols.
   *		Marcin Dalecki	:	Fixed problems with CONFIG_NET="n".
   *		Alan Cox	:	Added thread locking to sys_* calls
   *					for sockets. May have errors at the
   *					moment.
   *		Kevin Buhr	:	Fixed the dumb errors in the above.
   *		Andi Kleen	:	Some small cleanups, optimizations,
   *					and fixed a copy_from_user() bug.
   *		Tigran Aivazian	:	sys_send(args) calls sys_sendto(args, NULL, 0)
89bddce58   Stephen Hemminger   [NET] socket: cod...
45
   *		Tigran Aivazian	:	Made listen(2) backlog sanity checks
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
47
48
49
50
51
52
53
54
55
   *					protocol-independent
   *
   *
   *		This program is free software; you can redistribute it and/or
   *		modify it under the terms of the GNU General Public License
   *		as published by the Free Software Foundation; either version
   *		2 of the License, or (at your option) any later version.
   *
   *
   *	This module is effectively the top level interface to the BSD socket
89bddce58   Stephen Hemminger   [NET] socket: cod...
56
   *	paradigm.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57
58
59
   *
   *	Based upon Swansea University Computer Society NET3.039
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
  #include <linux/mm.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
61
62
63
64
  #include <linux/socket.h>
  #include <linux/file.h>
  #include <linux/net.h>
  #include <linux/interrupt.h>
aaca0bdca   Ulrich Drepper   flag parameters: ...
65
  #include <linux/thread_info.h>
55737fda0   Stephen Hemminger   [NET]: socket fam...
66
  #include <linux/rcupdate.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
68
69
  #include <linux/netdevice.h>
  #include <linux/proc_fs.h>
  #include <linux/seq_file.h>
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
70
  #include <linux/mutex.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
72
  #include <linux/wanrouter.h>
  #include <linux/if_bridge.h>
20380731b   Arnaldo Carvalho de Melo   [NET]: Fix sparse...
73
74
  #include <linux/if_frad.h>
  #include <linux/if_vlan.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75
76
77
78
79
  #include <linux/init.h>
  #include <linux/poll.h>
  #include <linux/cache.h>
  #include <linux/module.h>
  #include <linux/highmem.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80
81
82
83
84
  #include <linux/mount.h>
  #include <linux/security.h>
  #include <linux/syscalls.h>
  #include <linux/compat.h>
  #include <linux/kmod.h>
3ec3b2fba   David Woodhouse   AUDIT: Capture sy...
85
  #include <linux/audit.h>
d86b5e0e6   Adrian Bunk   [PATCH] net/: fix...
86
  #include <linux/wireless.h>
1b8d7ae42   Eric W. Biederman   [NET]: Make socke...
87
  #include <linux/nsproxy.h>
1fd7317d0   Nick Black   Move magic number...
88
  #include <linux/magic.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
89
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
91
92
93
94
  
  #include <asm/uaccess.h>
  #include <asm/unistd.h>
  
  #include <net/compat.h>
87de87d5e   David S. Miller   wext: Dispatch an...
95
  #include <net/wext.h>
f84517253   Herbert Xu   cls_cgroup: Store...
96
  #include <net/cls_cgroup.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
98
99
  
  #include <net/sock.h>
  #include <linux/netfilter.h>
6b96018b2   Arnd Bergmann   compat: move sock...
100
101
102
  #include <linux/if_tun.h>
  #include <linux/ipv6_route.h>
  #include <linux/route.h>
6b96018b2   Arnd Bergmann   compat: move sock...
103
104
  #include <linux/sockios.h>
  #include <linux/atalk.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
  static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
027445c37   Badari Pulavarty   [PATCH] Vectorize...
106
107
108
109
  static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
  			 unsigned long nr_segs, loff_t pos);
  static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
  			  unsigned long nr_segs, loff_t pos);
89bddce58   Stephen Hemminger   [NET] socket: cod...
110
  static int sock_mmap(struct file *file, struct vm_area_struct *vma);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
112
113
114
  
  static int sock_close(struct inode *inode, struct file *file);
  static unsigned int sock_poll(struct file *file,
  			      struct poll_table_struct *wait);
89bddce58   Stephen Hemminger   [NET] socket: cod...
115
  static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
89bbfc95d   Shaun Pereira   [NET]: allow 32 b...
116
117
  #ifdef CONFIG_COMPAT
  static long compat_sock_ioctl(struct file *file,
89bddce58   Stephen Hemminger   [NET] socket: cod...
118
  			      unsigned int cmd, unsigned long arg);
89bbfc95d   Shaun Pereira   [NET]: allow 32 b...
119
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
  static int sock_fasync(int fd, struct file *filp, int on);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
122
  static ssize_t sock_sendpage(struct file *file, struct page *page,
  			     int offset, size_t size, loff_t *ppos, int more);
9c55e01c0   Jens Axboe   [TCP]: Splice rec...
123
  static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
124
  				struct pipe_inode_info *pipe, size_t len,
9c55e01c0   Jens Axboe   [TCP]: Splice rec...
125
  				unsigned int flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
127
128
129
130
  /*
   *	Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
   *	in the operation structures but are done directly via the socketcall() multiplexor.
   */
da7071d7e   Arjan van de Ven   [PATCH] mark stru...
131
  static const struct file_operations socket_file_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
133
134
135
136
137
  	.owner =	THIS_MODULE,
  	.llseek =	no_llseek,
  	.aio_read =	sock_aio_read,
  	.aio_write =	sock_aio_write,
  	.poll =		sock_poll,
  	.unlocked_ioctl = sock_ioctl,
89bbfc95d   Shaun Pereira   [NET]: allow 32 b...
138
139
140
  #ifdef CONFIG_COMPAT
  	.compat_ioctl = compat_sock_ioctl,
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
142
143
144
  	.mmap =		sock_mmap,
  	.open =		sock_no_open,	/* special open code to disallow open via /proc */
  	.release =	sock_close,
  	.fasync =	sock_fasync,
5274f052e   Jens Axboe   [PATCH] Introduce...
145
146
  	.sendpage =	sock_sendpage,
  	.splice_write = generic_splice_sendpage,
9c55e01c0   Jens Axboe   [TCP]: Splice rec...
147
  	.splice_read =	sock_splice_read,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148
149
150
151
152
  };
  
  /*
   *	The protocol list. Each protocol is registered in here.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
  static DEFINE_SPINLOCK(net_family_lock);
190683a9d   Eric Dumazet   net: net_families...
154
  static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
155

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
156
157
158
  /*
   *	Statistics counters of the socket lists
   */
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
159
  static DEFINE_PER_CPU(int, sockets_in_use);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160
161
  
  /*
89bddce58   Stephen Hemminger   [NET] socket: cod...
162
163
164
   * Support routines.
   * Move socket addresses back and forth across the kernel/user
   * divide and look after the messy bits.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
166
167
168
169
170
171
172
173
174
175
  /**
   *	move_addr_to_kernel	-	copy a socket address into kernel space
   *	@uaddr: Address in user space
   *	@kaddr: Address in kernel space
   *	@ulen: Length in user space
   *
   *	The address is copied into kernel space. If the provided address is
   *	too long an error code of -EINVAL is returned. If the copy gives
   *	invalid addresses -EFAULT is returned. On a success 0 is returned.
   */
230b18392   YOSHIFUJI Hideaki   net: Use standard...
176
  int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr *kaddr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177
  {
230b18392   YOSHIFUJI Hideaki   net: Use standard...
178
  	if (ulen < 0 || ulen > sizeof(struct sockaddr_storage))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
  		return -EINVAL;
89bddce58   Stephen Hemminger   [NET] socket: cod...
180
  	if (ulen == 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
181
  		return 0;
89bddce58   Stephen Hemminger   [NET] socket: cod...
182
  	if (copy_from_user(kaddr, uaddr, ulen))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
  		return -EFAULT;
3ec3b2fba   David Woodhouse   AUDIT: Capture sy...
184
  	return audit_sockaddr(ulen, kaddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
  }
  
  /**
   *	move_addr_to_user	-	copy an address to user space
   *	@kaddr: kernel space address
   *	@klen: length of address in kernel
   *	@uaddr: user space address
   *	@ulen: pointer to user length field
   *
   *	The value pointed to by ulen on entry is the buffer length available.
   *	This is overwritten with the buffer space used. -EINVAL is returned
   *	if an overlong buffer is specified or a negative buffer size. -EFAULT
   *	is returned if either the buffer or the length field are not
   *	accessible.
   *	After copying the data up to the limit the user specifies, the true
   *	length of the data is written over the length limit the user
   *	specified. Zero is returned for a success.
   */
89bddce58   Stephen Hemminger   [NET] socket: cod...
203

11165f145   stephen hemminger   socket: localize ...
204
205
  static int move_addr_to_user(struct sockaddr *kaddr, int klen,
  			     void __user *uaddr, int __user *ulen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206
207
208
  {
  	int err;
  	int len;
89bddce58   Stephen Hemminger   [NET] socket: cod...
209
210
  	err = get_user(len, ulen);
  	if (err)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211
  		return err;
89bddce58   Stephen Hemminger   [NET] socket: cod...
212
213
  	if (len > klen)
  		len = klen;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
214
  	if (len < 0 || len > sizeof(struct sockaddr_storage))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215
  		return -EINVAL;
89bddce58   Stephen Hemminger   [NET] socket: cod...
216
  	if (len) {
d6fe3945b   Steve Grubb   [PATCH] sockaddr ...
217
218
  		if (audit_sockaddr(klen, kaddr))
  			return -ENOMEM;
89bddce58   Stephen Hemminger   [NET] socket: cod...
219
  		if (copy_to_user(uaddr, kaddr, len))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
220
221
222
  			return -EFAULT;
  	}
  	/*
89bddce58   Stephen Hemminger   [NET] socket: cod...
223
224
  	 *      "fromlen shall refer to the value before truncation.."
  	 *                      1003.1g
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
226
227
  	 */
  	return __put_user(klen, ulen);
  }
e18b890bb   Christoph Lameter   [PATCH] slab: rem...
228
  static struct kmem_cache *sock_inode_cachep __read_mostly;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
229
230
231
232
  
  static struct inode *sock_alloc_inode(struct super_block *sb)
  {
  	struct socket_alloc *ei;
eaefd1105   Eric Dumazet   net: add __rcu an...
233
  	struct socket_wq *wq;
89bddce58   Stephen Hemminger   [NET] socket: cod...
234

e94b17660   Christoph Lameter   [PATCH] slab: rem...
235
  	ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236
237
  	if (!ei)
  		return NULL;
eaefd1105   Eric Dumazet   net: add __rcu an...
238
239
  	wq = kmalloc(sizeof(*wq), GFP_KERNEL);
  	if (!wq) {
438154823   Eric Dumazet   net: sock_def_rea...
240
241
242
  		kmem_cache_free(sock_inode_cachep, ei);
  		return NULL;
  	}
eaefd1105   Eric Dumazet   net: add __rcu an...
243
244
245
  	init_waitqueue_head(&wq->wait);
  	wq->fasync_list = NULL;
  	RCU_INIT_POINTER(ei->socket.wq, wq);
89bddce58   Stephen Hemminger   [NET] socket: cod...
246

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
248
249
250
251
  	ei->socket.state = SS_UNCONNECTED;
  	ei->socket.flags = 0;
  	ei->socket.ops = NULL;
  	ei->socket.sk = NULL;
  	ei->socket.file = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
252
253
254
255
256
257
  
  	return &ei->vfs_inode;
  }
  
  static void sock_destroy_inode(struct inode *inode)
  {
438154823   Eric Dumazet   net: sock_def_rea...
258
  	struct socket_alloc *ei;
eaefd1105   Eric Dumazet   net: add __rcu an...
259
  	struct socket_wq *wq;
438154823   Eric Dumazet   net: sock_def_rea...
260
261
  
  	ei = container_of(inode, struct socket_alloc, vfs_inode);
eaefd1105   Eric Dumazet   net: add __rcu an...
262
  	wq = rcu_dereference_protected(ei->socket.wq, 1);
618452202   Lai Jiangshan   net,rcu: convert ...
263
  	kfree_rcu(wq, rcu);
438154823   Eric Dumazet   net: sock_def_rea...
264
  	kmem_cache_free(sock_inode_cachep, ei);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
  }
51cc50685   Alexey Dobriyan   SL*B: drop kmem c...
266
  static void init_once(void *foo)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267
  {
89bddce58   Stephen Hemminger   [NET] socket: cod...
268
  	struct socket_alloc *ei = (struct socket_alloc *)foo;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269

a35afb830   Christoph Lameter   Remove SLAB_CTOR_...
270
  	inode_init_once(&ei->vfs_inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
271
  }
89bddce58   Stephen Hemminger   [NET] socket: cod...
272

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273
274
275
  static int init_inodecache(void)
  {
  	sock_inode_cachep = kmem_cache_create("sock_inode_cache",
89bddce58   Stephen Hemminger   [NET] socket: cod...
276
277
278
279
280
  					      sizeof(struct socket_alloc),
  					      0,
  					      (SLAB_HWCACHE_ALIGN |
  					       SLAB_RECLAIM_ACCOUNT |
  					       SLAB_MEM_SPREAD),
20c2df83d   Paul Mundt   mm: Remove slab d...
281
  					      init_once);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
282
283
284
285
  	if (sock_inode_cachep == NULL)
  		return -ENOMEM;
  	return 0;
  }
b87221de6   Alexey Dobriyan   const: mark remai...
286
  static const struct super_operations sockfs_ops = {
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
287
288
289
  	.alloc_inode	= sock_alloc_inode,
  	.destroy_inode	= sock_destroy_inode,
  	.statfs		= simple_statfs,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
290
  };
c23fbb6bc   Eric Dumazet   VFS: delay the de...
291
292
293
294
295
296
297
298
  /*
   * sockfs_dname() is called from d_path().
   */
  static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen)
  {
  	return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]",
  				dentry->d_inode->i_ino);
  }
3ba13d179   Al Viro   constify dentry_o...
299
  static const struct dentry_operations sockfs_dentry_operations = {
c23fbb6bc   Eric Dumazet   VFS: delay the de...
300
  	.d_dname  = sockfs_dname,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
301
  };
c74a1cbb3   Al Viro   pass default dent...
302
303
304
305
306
307
308
309
310
311
312
313
314
315
  static struct dentry *sockfs_mount(struct file_system_type *fs_type,
  			 int flags, const char *dev_name, void *data)
  {
  	return mount_pseudo(fs_type, "socket:", &sockfs_ops,
  		&sockfs_dentry_operations, SOCKFS_MAGIC);
  }
  
  static struct vfsmount *sock_mnt __read_mostly;
  
  static struct file_system_type sock_fs_type = {
  	.name =		"sockfs",
  	.mount =	sockfs_mount,
  	.kill_sb =	kill_anon_super,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
316
317
318
  /*
   *	Obtains the first available file descriptor and sets it up for use.
   *
39d8c1b6f   David S. Miller   [NET]: Do not los...
319
320
   *	These functions create file structures and maps them to fd space
   *	of the current process. On success it returns file descriptor
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
321
322
323
324
325
326
327
328
329
330
331
   *	and file struct implicitly stored in sock->file.
   *	Note that another thread may close file descriptor before we return
   *	from this function. We use the fact that now we do not refer
   *	to socket after mapping. If one day we will need it, this
   *	function will increment ref. count on file by 1.
   *
   *	In any case returned fd MAY BE not valid!
   *	This race condition is unavoidable
   *	with shared fd spaces, we cannot solve it inside kernel,
   *	but we take care of internal coherence yet.
   */
7cbe66b6b   Al Viro   merge sock_alloc_...
332
  static int sock_alloc_file(struct socket *sock, struct file **f, int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
333
  {
7cbe66b6b   Al Viro   merge sock_alloc_...
334
  	struct qstr name = { .name = "" };
2c48b9c45   Al Viro   switch alloc_file...
335
  	struct path path;
7cbe66b6b   Al Viro   merge sock_alloc_...
336
  	struct file *file;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337
  	int fd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
338

a677a039b   Ulrich Drepper   flag parameters: ...
339
  	fd = get_unused_fd_flags(flags);
7cbe66b6b   Al Viro   merge sock_alloc_...
340
341
  	if (unlikely(fd < 0))
  		return fd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
342

4b936885a   Nick Piggin   fs: improve scala...
343
  	path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name);
2c48b9c45   Al Viro   switch alloc_file...
344
  	if (unlikely(!path.dentry)) {
7cbe66b6b   Al Viro   merge sock_alloc_...
345
  		put_unused_fd(fd);
39d8c1b6f   David S. Miller   [NET]: Do not los...
346
  		return -ENOMEM;
7cbe66b6b   Al Viro   merge sock_alloc_...
347
  	}
2c48b9c45   Al Viro   switch alloc_file...
348
  	path.mnt = mntget(sock_mnt);
39d8c1b6f   David S. Miller   [NET]: Do not los...
349

2c48b9c45   Al Viro   switch alloc_file...
350
  	d_instantiate(path.dentry, SOCK_INODE(sock));
cc3808f8c   Al Viro   switch sock_alloc...
351
  	SOCK_INODE(sock)->i_fop = &socket_file_ops;
39d8c1b6f   David S. Miller   [NET]: Do not los...
352

2c48b9c45   Al Viro   switch alloc_file...
353
  	file = alloc_file(&path, FMODE_READ | FMODE_WRITE,
ce8d2cdf3   Dave Hansen   r/o bind mounts: ...
354
  		  &socket_file_ops);
cc3808f8c   Al Viro   switch sock_alloc...
355
356
  	if (unlikely(!file)) {
  		/* drop dentry, keep inode */
7de9c6ee3   Al Viro   new helper: ihold()
357
  		ihold(path.dentry->d_inode);
2c48b9c45   Al Viro   switch alloc_file...
358
  		path_put(&path);
cc3808f8c   Al Viro   switch sock_alloc...
359
360
361
362
363
  		put_unused_fd(fd);
  		return -ENFILE;
  	}
  
  	sock->file = file;
77d272005   Ulrich Drepper   flag parameters: ...
364
  	file->f_flags = O_RDWR | (flags & O_NONBLOCK);
39d8c1b6f   David S. Miller   [NET]: Do not los...
365
366
  	file->f_pos = 0;
  	file->private_data = sock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
367

7cbe66b6b   Al Viro   merge sock_alloc_...
368
369
  	*f = file;
  	return fd;
39d8c1b6f   David S. Miller   [NET]: Do not los...
370
  }
a677a039b   Ulrich Drepper   flag parameters: ...
371
  int sock_map_fd(struct socket *sock, int flags)
39d8c1b6f   David S. Miller   [NET]: Do not los...
372
373
  {
  	struct file *newfile;
7cbe66b6b   Al Viro   merge sock_alloc_...
374
  	int fd = sock_alloc_file(sock, &newfile, flags);
39d8c1b6f   David S. Miller   [NET]: Do not los...
375

7cbe66b6b   Al Viro   merge sock_alloc_...
376
  	if (likely(fd >= 0))
39d8c1b6f   David S. Miller   [NET]: Do not los...
377
  		fd_install(fd, newfile);
7cbe66b6b   Al Viro   merge sock_alloc_...
378

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
379
380
  	return fd;
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
381
  EXPORT_SYMBOL(sock_map_fd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
382

6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
383
384
  static struct socket *sock_from_file(struct file *file, int *err)
  {
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
385
386
  	if (file->f_op == &socket_file_ops)
  		return file->private_data;	/* set in sock_map_fd */
23bb80d21   Eric Dumazet   [NET]: cleanup so...
387
388
  	*err = -ENOTSOCK;
  	return NULL;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
389
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
390
  /**
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
391
   *	sockfd_lookup - Go from a file number to its socket slot
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
392
393
394
395
396
397
398
399
400
401
402
403
404
405
   *	@fd: file handle
   *	@err: pointer to an error code return
   *
   *	The file handle passed in is locked and the socket it is bound
   *	too is returned. If an error occurs the err pointer is overwritten
   *	with a negative errno code and NULL is returned. The function checks
   *	for both invalid handles and passing a handle which is not a socket.
   *
   *	On a success the socket object pointer is returned.
   */
  
  struct socket *sockfd_lookup(int fd, int *err)
  {
  	struct file *file;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
406
  	struct socket *sock;
89bddce58   Stephen Hemminger   [NET] socket: cod...
407
408
  	file = fget(fd);
  	if (!file) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
409
410
411
  		*err = -EBADF;
  		return NULL;
  	}
89bddce58   Stephen Hemminger   [NET] socket: cod...
412

6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
413
414
  	sock = sock_from_file(file, err);
  	if (!sock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
415
  		fput(file);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
416
417
  	return sock;
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
418
  EXPORT_SYMBOL(sockfd_lookup);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
419

6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
420
421
422
423
  static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
  {
  	struct file *file;
  	struct socket *sock;
3672558c6   Hua Zhong   [NET]: sockfd_loo...
424
  	*err = -EBADF;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
425
426
427
428
429
430
  	file = fget_light(fd, fput_needed);
  	if (file) {
  		sock = sock_from_file(file, err);
  		if (sock)
  			return sock;
  		fput_light(file, *fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
431
  	}
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
432
  	return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
433
434
435
436
  }
  
  /**
   *	sock_alloc	-	allocate a socket
89bddce58   Stephen Hemminger   [NET] socket: cod...
437
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
438
439
440
441
442
443
444
   *	Allocate a new inode and socket object. The two are bound together
   *	and initialised. The socket is then returned. If we are out of inodes
   *	NULL is returned.
   */
  
  static struct socket *sock_alloc(void)
  {
89bddce58   Stephen Hemminger   [NET] socket: cod...
445
446
  	struct inode *inode;
  	struct socket *sock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
447

a209dfc7b   Eric Dumazet   vfs: dont chain p...
448
  	inode = new_inode_pseudo(sock_mnt->mnt_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
449
450
451
452
  	if (!inode)
  		return NULL;
  
  	sock = SOCKET_I(inode);
29a020d35   Eric Dumazet   [PATCH] net: kmem...
453
  	kmemcheck_annotate_bitfield(sock, type);
85fe4025c   Christoph Hellwig   fs: do not assign...
454
  	inode->i_ino = get_next_ino();
89bddce58   Stephen Hemminger   [NET] socket: cod...
455
  	inode->i_mode = S_IFSOCK | S_IRWXUGO;
8192b0c48   David Howells   CRED: Wrap task c...
456
457
  	inode->i_uid = current_fsuid();
  	inode->i_gid = current_fsgid();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
458

4e69489a0   Eric Dumazet   socket: use percp...
459
  	percpu_add(sockets_in_use, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
460
461
462
463
464
465
466
467
  	return sock;
  }
  
  /*
   *	In theory you can't get an open on this inode, but /proc provides
   *	a back door. Remember to keep it shut otherwise you'll let the
   *	creepy crawlies in.
   */
89bddce58   Stephen Hemminger   [NET] socket: cod...
468

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
469
470
471
472
  static int sock_no_open(struct inode *irrelevant, struct file *dontcare)
  {
  	return -ENXIO;
  }
4b6f5d20b   Arjan van de Ven   [PATCH] Make most...
473
  const struct file_operations bad_sock_fops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
475
  	.owner = THIS_MODULE,
  	.open = sock_no_open,
6038f373a   Arnd Bergmann   llseek: automatic...
476
  	.llseek = noop_llseek,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
477
478
479
480
481
482
483
484
  };
  
  /**
   *	sock_release	-	close a socket
   *	@sock: socket to close
   *
   *	The socket is released from the protocol stack if it has a release
   *	callback, and the inode is then released if the socket is bound to
89bddce58   Stephen Hemminger   [NET] socket: cod...
485
   *	an inode not a file.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
486
   */
89bddce58   Stephen Hemminger   [NET] socket: cod...
487

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
488
489
490
491
492
493
494
495
496
  void sock_release(struct socket *sock)
  {
  	if (sock->ops) {
  		struct module *owner = sock->ops->owner;
  
  		sock->ops->release(sock);
  		sock->ops = NULL;
  		module_put(owner);
  	}
eaefd1105   Eric Dumazet   net: add __rcu an...
497
  	if (rcu_dereference_protected(sock->wq, 1)->fasync_list)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
498
499
  		printk(KERN_ERR "sock_release: fasync list not empty!
  ");
4e69489a0   Eric Dumazet   socket: use percp...
500
  	percpu_sub(sockets_in_use, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
501
502
503
504
  	if (!sock->file) {
  		iput(SOCK_INODE(sock));
  		return;
  	}
89bddce58   Stephen Hemminger   [NET] socket: cod...
505
  	sock->file = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
506
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
507
  EXPORT_SYMBOL(sock_release);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
508

2244d07bf   Oliver Hartkopp   net: simplify fla...
509
  int sock_tx_timestamp(struct sock *sk, __u8 *tx_flags)
20d494735   Patrick Ohly   net: socket infra...
510
  {
2244d07bf   Oliver Hartkopp   net: simplify fla...
511
  	*tx_flags = 0;
20d494735   Patrick Ohly   net: socket infra...
512
  	if (sock_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE))
2244d07bf   Oliver Hartkopp   net: simplify fla...
513
  		*tx_flags |= SKBTX_HW_TSTAMP;
20d494735   Patrick Ohly   net: socket infra...
514
  	if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE))
2244d07bf   Oliver Hartkopp   net: simplify fla...
515
  		*tx_flags |= SKBTX_SW_TSTAMP;
6e3e939f3   Johannes Berg   net: add wireless...
516
517
  	if (sock_flag(sk, SOCK_WIFI_STATUS))
  		*tx_flags |= SKBTX_WIFI_STATUS;
20d494735   Patrick Ohly   net: socket infra...
518
519
520
  	return 0;
  }
  EXPORT_SYMBOL(sock_tx_timestamp);
228e548e6   Anton Blanchard   net: Add sendmmsg...
521
522
  static inline int __sock_sendmsg_nosec(struct kiocb *iocb, struct socket *sock,
  				       struct msghdr *msg, size_t size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
523
524
  {
  	struct sock_iocb *si = kiocb_to_siocb(iocb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
525

f84517253   Herbert Xu   cls_cgroup: Store...
526
  	sock_update_classid(sock->sk);
5bc1421e3   Neil Horman   net: add network ...
527
  	sock_update_netprioidx(sock->sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
528
529
530
531
  	si->sock = sock;
  	si->scm = NULL;
  	si->msg = msg;
  	si->size = size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
532
533
  	return sock->ops->sendmsg(iocb, sock, msg, size);
  }
228e548e6   Anton Blanchard   net: Add sendmmsg...
534
535
536
537
538
539
540
  static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock,
  				 struct msghdr *msg, size_t size)
  {
  	int err = security_socket_sendmsg(sock, msg, size);
  
  	return err ?: __sock_sendmsg_nosec(iocb, sock, msg, size);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
541
542
543
544
545
546
547
548
549
550
551
552
553
  int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
  {
  	struct kiocb iocb;
  	struct sock_iocb siocb;
  	int ret;
  
  	init_sync_kiocb(&iocb, NULL);
  	iocb.private = &siocb;
  	ret = __sock_sendmsg(&iocb, sock, msg, size);
  	if (-EIOCBQUEUED == ret)
  		ret = wait_on_sync_kiocb(&iocb);
  	return ret;
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
554
  EXPORT_SYMBOL(sock_sendmsg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
555

894dc24ce   Eric Dumazet   net: sock_sendmsg...
556
  static int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg, size_t size)
228e548e6   Anton Blanchard   net: Add sendmmsg...
557
558
559
560
561
562
563
564
565
566
567
568
  {
  	struct kiocb iocb;
  	struct sock_iocb siocb;
  	int ret;
  
  	init_sync_kiocb(&iocb, NULL);
  	iocb.private = &siocb;
  	ret = __sock_sendmsg_nosec(&iocb, sock, msg, size);
  	if (-EIOCBQUEUED == ret)
  		ret = wait_on_sync_kiocb(&iocb);
  	return ret;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
569
570
571
572
573
574
575
576
577
578
579
  int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
  		   struct kvec *vec, size_t num, size_t size)
  {
  	mm_segment_t oldfs = get_fs();
  	int result;
  
  	set_fs(KERNEL_DS);
  	/*
  	 * the following is safe, since for compiler definitions of kvec and
  	 * iovec are identical, yielding the same in-core layout and alignment
  	 */
89bddce58   Stephen Hemminger   [NET] socket: cod...
580
  	msg->msg_iov = (struct iovec *)vec;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
581
582
583
584
585
  	msg->msg_iovlen = num;
  	result = sock_sendmsg(sock, msg, size);
  	set_fs(oldfs);
  	return result;
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
586
  EXPORT_SYMBOL(kernel_sendmsg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
587

20d494735   Patrick Ohly   net: socket infra...
588
589
590
591
592
593
594
595
596
  static int ktime2ts(ktime_t kt, struct timespec *ts)
  {
  	if (kt.tv64) {
  		*ts = ktime_to_timespec(kt);
  		return 1;
  	} else {
  		return 0;
  	}
  }
92f37fd2e   Eric Dumazet   [NET]: Adding SO_...
597
598
599
600
601
602
  /*
   * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
   */
  void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
  	struct sk_buff *skb)
  {
20d494735   Patrick Ohly   net: socket infra...
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
  	int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
  	struct timespec ts[3];
  	int empty = 1;
  	struct skb_shared_hwtstamps *shhwtstamps =
  		skb_hwtstamps(skb);
  
  	/* Race occurred between timestamp enabling and packet
  	   receiving.  Fill in the current time for now. */
  	if (need_software_tstamp && skb->tstamp.tv64 == 0)
  		__net_timestamp(skb);
  
  	if (need_software_tstamp) {
  		if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
  			struct timeval tv;
  			skb_get_timestamp(skb, &tv);
  			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP,
  				 sizeof(tv), &tv);
  		} else {
842509b85   Hagen Paul Pfeifer   socket: remove du...
621
  			skb_get_timestampns(skb, &ts[0]);
20d494735   Patrick Ohly   net: socket infra...
622
  			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS,
842509b85   Hagen Paul Pfeifer   socket: remove du...
623
  				 sizeof(ts[0]), &ts[0]);
20d494735   Patrick Ohly   net: socket infra...
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
  		}
  	}
  
  
  	memset(ts, 0, sizeof(ts));
  	if (skb->tstamp.tv64 &&
  	    sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE)) {
  		skb_get_timestampns(skb, ts + 0);
  		empty = 0;
  	}
  	if (shhwtstamps) {
  		if (sock_flag(sk, SOCK_TIMESTAMPING_SYS_HARDWARE) &&
  		    ktime2ts(shhwtstamps->syststamp, ts + 1))
  			empty = 0;
  		if (sock_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE) &&
  		    ktime2ts(shhwtstamps->hwtstamp, ts + 2))
  			empty = 0;
92f37fd2e   Eric Dumazet   [NET]: Adding SO_...
641
  	}
20d494735   Patrick Ohly   net: socket infra...
642
643
644
  	if (!empty)
  		put_cmsg(msg, SOL_SOCKET,
  			 SCM_TIMESTAMPING, sizeof(ts), &ts);
92f37fd2e   Eric Dumazet   [NET]: Adding SO_...
645
  }
7c81fd8bf   Arnaldo Carvalho de Melo   [SOCKET]: Export ...
646
  EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
6e3e939f3   Johannes Berg   net: add wireless...
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
  void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
  	struct sk_buff *skb)
  {
  	int ack;
  
  	if (!sock_flag(sk, SOCK_WIFI_STATUS))
  		return;
  	if (!skb->wifi_acked_valid)
  		return;
  
  	ack = skb->wifi_acked;
  
  	put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack);
  }
  EXPORT_SYMBOL_GPL(__sock_recv_wifi_status);
11165f145   stephen hemminger   socket: localize ...
662
663
  static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk,
  				   struct sk_buff *skb)
3b885787e   Neil Horman   net: Generalize s...
664
665
666
667
668
  {
  	if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && skb->dropcount)
  		put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL,
  			sizeof(__u32), &skb->dropcount);
  }
767dd0336   Eric Dumazet   net: speedup sock...
669
  void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
3b885787e   Neil Horman   net: Generalize s...
670
671
672
673
674
  	struct sk_buff *skb)
  {
  	sock_recv_timestamp(msg, sk, skb);
  	sock_recv_drops(msg, sk, skb);
  }
767dd0336   Eric Dumazet   net: speedup sock...
675
  EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops);
3b885787e   Neil Horman   net: Generalize s...
676

a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
677
678
  static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock,
  				       struct msghdr *msg, size_t size, int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
679
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
680
  	struct sock_iocb *si = kiocb_to_siocb(iocb);
f84517253   Herbert Xu   cls_cgroup: Store...
681
  	sock_update_classid(sock->sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
682
683
684
685
686
  	si->sock = sock;
  	si->scm = NULL;
  	si->msg = msg;
  	si->size = size;
  	si->flags = flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
687
688
  	return sock->ops->recvmsg(iocb, sock, msg, size, flags);
  }
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
689
690
691
692
693
694
695
  static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock,
  				 struct msghdr *msg, size_t size, int flags)
  {
  	int err = security_socket_recvmsg(sock, msg, size, flags);
  
  	return err ?: __sock_recvmsg_nosec(iocb, sock, msg, size, flags);
  }
89bddce58   Stephen Hemminger   [NET] socket: cod...
696
  int sock_recvmsg(struct socket *sock, struct msghdr *msg,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
697
698
699
700
701
  		 size_t size, int flags)
  {
  	struct kiocb iocb;
  	struct sock_iocb siocb;
  	int ret;
89bddce58   Stephen Hemminger   [NET] socket: cod...
702
  	init_sync_kiocb(&iocb, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
703
704
705
706
707
708
  	iocb.private = &siocb;
  	ret = __sock_recvmsg(&iocb, sock, msg, size, flags);
  	if (-EIOCBQUEUED == ret)
  		ret = wait_on_sync_kiocb(&iocb);
  	return ret;
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
709
  EXPORT_SYMBOL(sock_recvmsg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
710

a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
711
712
713
714
715
716
717
718
719
720
721
722
723
724
  static int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
  			      size_t size, int flags)
  {
  	struct kiocb iocb;
  	struct sock_iocb siocb;
  	int ret;
  
  	init_sync_kiocb(&iocb, NULL);
  	iocb.private = &siocb;
  	ret = __sock_recvmsg_nosec(&iocb, sock, msg, size, flags);
  	if (-EIOCBQUEUED == ret)
  		ret = wait_on_sync_kiocb(&iocb);
  	return ret;
  }
c1249c0aa   Martin Lucina   net: Document the...
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
  /**
   * kernel_recvmsg - Receive a message from a socket (kernel space)
   * @sock:       The socket to receive the message from
   * @msg:        Received message
   * @vec:        Input s/g array for message data
   * @num:        Size of input s/g array
   * @size:       Number of bytes to read
   * @flags:      Message flags (MSG_DONTWAIT, etc...)
   *
   * On return the msg structure contains the scatter/gather array passed in the
   * vec argument. The array is modified so that it consists of the unfilled
   * portion of the original array.
   *
   * The returned value is the total number of bytes received, or an error.
   */
89bddce58   Stephen Hemminger   [NET] socket: cod...
740
741
  int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
  		   struct kvec *vec, size_t num, size_t size, int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
742
743
744
745
746
747
748
749
750
  {
  	mm_segment_t oldfs = get_fs();
  	int result;
  
  	set_fs(KERNEL_DS);
  	/*
  	 * the following is safe, since for compiler definitions of kvec and
  	 * iovec are identical, yielding the same in-core layout and alignment
  	 */
89bddce58   Stephen Hemminger   [NET] socket: cod...
751
  	msg->msg_iov = (struct iovec *)vec, msg->msg_iovlen = num;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
752
753
754
755
  	result = sock_recvmsg(sock, msg, size, flags);
  	set_fs(oldfs);
  	return result;
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
756
  EXPORT_SYMBOL(kernel_recvmsg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
757
758
759
760
761
  
  static void sock_aio_dtor(struct kiocb *iocb)
  {
  	kfree(iocb->private);
  }
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
762
763
  static ssize_t sock_sendpage(struct file *file, struct page *page,
  			     int offset, size_t size, loff_t *ppos, int more)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
764
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
765
766
  	struct socket *sock;
  	int flags;
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
767
768
769
770
771
  	sock = file->private_data;
  
  	flags = !(file->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT;
  	if (more)
  		flags |= MSG_MORE;
e69495838   Linus Torvalds   Make sock_sendpag...
772
  	return kernel_sendpage(sock, page, offset, size, flags);
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
773
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
774

9c55e01c0   Jens Axboe   [TCP]: Splice rec...
775
  static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
776
  				struct pipe_inode_info *pipe, size_t len,
9c55e01c0   Jens Axboe   [TCP]: Splice rec...
777
778
779
  				unsigned int flags)
  {
  	struct socket *sock = file->private_data;
997b37da1   Rémi Denis-Courmont   [NET]: Make sure ...
780
781
  	if (unlikely(!sock->ops->splice_read))
  		return -EINVAL;
f84517253   Herbert Xu   cls_cgroup: Store...
782
  	sock_update_classid(sock->sk);
9c55e01c0   Jens Axboe   [TCP]: Splice rec...
783
784
  	return sock->ops->splice_read(sock, ppos, pipe, len, flags);
  }
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
785
  static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
89bddce58   Stephen Hemminger   [NET] socket: cod...
786
  					 struct sock_iocb *siocb)
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
787
788
789
790
791
  {
  	if (!is_sync_kiocb(iocb)) {
  		siocb = kmalloc(sizeof(*siocb), GFP_KERNEL);
  		if (!siocb)
  			return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
792
793
  		iocb->ki_dtor = sock_aio_dtor;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
794

ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
795
  	siocb->kiocb = iocb;
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
796
797
  	iocb->private = siocb;
  	return siocb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
798
  }
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
799
  static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb,
027445c37   Badari Pulavarty   [PATCH] Vectorize...
800
801
  		struct file *file, const struct iovec *iov,
  		unsigned long nr_segs)
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
802
803
804
805
  {
  	struct socket *sock = file->private_data;
  	size_t size = 0;
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
806

89bddce58   Stephen Hemminger   [NET] socket: cod...
807
808
  	for (i = 0; i < nr_segs; i++)
  		size += iov[i].iov_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
809

ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
810
811
812
813
  	msg->msg_name = NULL;
  	msg->msg_namelen = 0;
  	msg->msg_control = NULL;
  	msg->msg_controllen = 0;
89bddce58   Stephen Hemminger   [NET] socket: cod...
814
  	msg->msg_iov = (struct iovec *)iov;
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
815
816
817
818
819
  	msg->msg_iovlen = nr_segs;
  	msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
  
  	return __sock_recvmsg(iocb, sock, msg, size, msg->msg_flags);
  }
027445c37   Badari Pulavarty   [PATCH] Vectorize...
820
821
  static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
  				unsigned long nr_segs, loff_t pos)
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
822
823
  {
  	struct sock_iocb siocb, *x;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
824
825
  	if (pos != 0)
  		return -ESPIPE;
027445c37   Badari Pulavarty   [PATCH] Vectorize...
826
827
  
  	if (iocb->ki_left == 0)	/* Match SYS5 behaviour */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
828
  		return 0;
027445c37   Badari Pulavarty   [PATCH] Vectorize...
829
830
  
  	x = alloc_sock_iocb(iocb, &siocb);
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
831
832
  	if (!x)
  		return -ENOMEM;
027445c37   Badari Pulavarty   [PATCH] Vectorize...
833
  	return do_sock_read(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
834
  }
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
835
  static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb,
027445c37   Badari Pulavarty   [PATCH] Vectorize...
836
837
  			struct file *file, const struct iovec *iov,
  			unsigned long nr_segs)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
838
  {
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
839
840
841
  	struct socket *sock = file->private_data;
  	size_t size = 0;
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
842

89bddce58   Stephen Hemminger   [NET] socket: cod...
843
844
  	for (i = 0; i < nr_segs; i++)
  		size += iov[i].iov_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
845

ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
846
847
848
849
  	msg->msg_name = NULL;
  	msg->msg_namelen = 0;
  	msg->msg_control = NULL;
  	msg->msg_controllen = 0;
89bddce58   Stephen Hemminger   [NET] socket: cod...
850
  	msg->msg_iov = (struct iovec *)iov;
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
851
852
853
854
  	msg->msg_iovlen = nr_segs;
  	msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
  	if (sock->type == SOCK_SEQPACKET)
  		msg->msg_flags |= MSG_EOR;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
855

ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
856
  	return __sock_sendmsg(iocb, sock, msg, size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
857
  }
027445c37   Badari Pulavarty   [PATCH] Vectorize...
858
859
  static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
  			  unsigned long nr_segs, loff_t pos)
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
860
861
  {
  	struct sock_iocb siocb, *x;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
862

ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
863
864
  	if (pos != 0)
  		return -ESPIPE;
027445c37   Badari Pulavarty   [PATCH] Vectorize...
865

027445c37   Badari Pulavarty   [PATCH] Vectorize...
866
  	x = alloc_sock_iocb(iocb, &siocb);
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
867
868
  	if (!x)
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
869

027445c37   Badari Pulavarty   [PATCH] Vectorize...
870
  	return do_sock_write(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
871
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
872
873
874
875
  /*
   * Atomic setting of ioctl hooks to avoid race
   * with module unload.
   */
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
876
  static DEFINE_MUTEX(br_ioctl_mutex);
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
877
  static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
878

881d966b4   Eric W. Biederman   [NET]: Make the d...
879
  void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
880
  {
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
881
  	mutex_lock(&br_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
882
  	br_ioctl_hook = hook;
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
883
  	mutex_unlock(&br_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
884
885
  }
  EXPORT_SYMBOL(brioctl_set);
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
886
  static DEFINE_MUTEX(vlan_ioctl_mutex);
881d966b4   Eric W. Biederman   [NET]: Make the d...
887
  static int (*vlan_ioctl_hook) (struct net *, void __user *arg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
888

881d966b4   Eric W. Biederman   [NET]: Make the d...
889
  void vlan_ioctl_set(int (*hook) (struct net *, void __user *))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
890
  {
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
891
  	mutex_lock(&vlan_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
892
  	vlan_ioctl_hook = hook;
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
893
  	mutex_unlock(&vlan_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
894
895
  }
  EXPORT_SYMBOL(vlan_ioctl_set);
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
896
  static DEFINE_MUTEX(dlci_ioctl_mutex);
89bddce58   Stephen Hemminger   [NET] socket: cod...
897
  static int (*dlci_ioctl_hook) (unsigned int, void __user *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
898

89bddce58   Stephen Hemminger   [NET] socket: cod...
899
  void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
900
  {
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
901
  	mutex_lock(&dlci_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
902
  	dlci_ioctl_hook = hook;
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
903
  	mutex_unlock(&dlci_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
904
905
  }
  EXPORT_SYMBOL(dlci_ioctl_set);
6b96018b2   Arnd Bergmann   compat: move sock...
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
  static long sock_do_ioctl(struct net *net, struct socket *sock,
  				 unsigned int cmd, unsigned long arg)
  {
  	int err;
  	void __user *argp = (void __user *)arg;
  
  	err = sock->ops->ioctl(sock, cmd, arg);
  
  	/*
  	 * If this ioctl is unknown try to hand it down
  	 * to the NIC driver.
  	 */
  	if (err == -ENOIOCTLCMD)
  		err = dev_ioctl(net, cmd, argp);
  
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
923
924
925
926
927
928
929
930
  /*
   *	With an ioctl, arg may well be a user mode pointer, but we don't know
   *	what to do with it - that's up to the protocol still.
   */
  
  static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
  {
  	struct socket *sock;
881d966b4   Eric W. Biederman   [NET]: Make the d...
931
  	struct sock *sk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
932
933
  	void __user *argp = (void __user *)arg;
  	int pid, err;
881d966b4   Eric W. Biederman   [NET]: Make the d...
934
  	struct net *net;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
935

b69aee04f   Eric Dumazet   [NET]: Use file->...
936
  	sock = file->private_data;
881d966b4   Eric W. Biederman   [NET]: Make the d...
937
  	sk = sock->sk;
3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
938
  	net = sock_net(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
939
  	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
881d966b4   Eric W. Biederman   [NET]: Make the d...
940
  		err = dev_ioctl(net, cmd, argp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
941
  	} else
3d23e349d   Johannes Berg   wext: refactor
942
  #ifdef CONFIG_WEXT_CORE
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
943
  	if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
881d966b4   Eric W. Biederman   [NET]: Make the d...
944
  		err = dev_ioctl(net, cmd, argp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
945
  	} else
3d23e349d   Johannes Berg   wext: refactor
946
  #endif
89bddce58   Stephen Hemminger   [NET] socket: cod...
947
  		switch (cmd) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
948
949
950
951
952
953
954
955
956
  		case FIOSETOWN:
  		case SIOCSPGRP:
  			err = -EFAULT;
  			if (get_user(pid, (int __user *)argp))
  				break;
  			err = f_setown(sock->file, pid, 1);
  			break;
  		case FIOGETOWN:
  		case SIOCGPGRP:
609d7fa95   Eric W. Biederman   [PATCH] file: mod...
957
  			err = put_user(f_getown(sock->file),
89bddce58   Stephen Hemminger   [NET] socket: cod...
958
  				       (int __user *)argp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
959
960
961
962
963
964
965
966
  			break;
  		case SIOCGIFBR:
  		case SIOCSIFBR:
  		case SIOCBRADDBR:
  		case SIOCBRDELBR:
  			err = -ENOPKG;
  			if (!br_ioctl_hook)
  				request_module("bridge");
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
967
  			mutex_lock(&br_ioctl_mutex);
89bddce58   Stephen Hemminger   [NET] socket: cod...
968
  			if (br_ioctl_hook)
881d966b4   Eric W. Biederman   [NET]: Make the d...
969
  				err = br_ioctl_hook(net, cmd, argp);
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
970
  			mutex_unlock(&br_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
971
972
973
974
975
976
  			break;
  		case SIOCGIFVLAN:
  		case SIOCSIFVLAN:
  			err = -ENOPKG;
  			if (!vlan_ioctl_hook)
  				request_module("8021q");
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
977
  			mutex_lock(&vlan_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
978
  			if (vlan_ioctl_hook)
881d966b4   Eric W. Biederman   [NET]: Make the d...
979
  				err = vlan_ioctl_hook(net, argp);
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
980
  			mutex_unlock(&vlan_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
981
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
982
983
984
985
986
  		case SIOCADDDLCI:
  		case SIOCDELDLCI:
  			err = -ENOPKG;
  			if (!dlci_ioctl_hook)
  				request_module("dlci");
7512cbf6e   Pavel Emelyanov   [DLCI]: Fix tiny ...
987
988
  			mutex_lock(&dlci_ioctl_mutex);
  			if (dlci_ioctl_hook)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
989
  				err = dlci_ioctl_hook(cmd, argp);
7512cbf6e   Pavel Emelyanov   [DLCI]: Fix tiny ...
990
  			mutex_unlock(&dlci_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
991
992
  			break;
  		default:
6b96018b2   Arnd Bergmann   compat: move sock...
993
  			err = sock_do_ioctl(net, sock, cmd, arg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
994
  			break;
89bddce58   Stephen Hemminger   [NET] socket: cod...
995
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
996
997
998
999
1000
1001
1002
  	return err;
  }
  
  int sock_create_lite(int family, int type, int protocol, struct socket **res)
  {
  	int err;
  	struct socket *sock = NULL;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1003

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1004
1005
1006
1007
1008
1009
1010
1011
1012
  	err = security_socket_create(family, type, protocol, 1);
  	if (err)
  		goto out;
  
  	sock = sock_alloc();
  	if (!sock) {
  		err = -ENOMEM;
  		goto out;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1013
  	sock->type = type;
7420ed23a   Venkat Yekkirala   [NetLabel]: SELin...
1014
1015
1016
  	err = security_socket_post_create(sock, family, type, protocol, 1);
  	if (err)
  		goto out_release;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1017
1018
1019
  out:
  	*res = sock;
  	return err;
7420ed23a   Venkat Yekkirala   [NetLabel]: SELin...
1020
1021
1022
1023
  out_release:
  	sock_release(sock);
  	sock = NULL;
  	goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1024
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
1025
  EXPORT_SYMBOL(sock_create_lite);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1026
1027
  
  /* No kernel lock held - perfect */
89bddce58   Stephen Hemminger   [NET] socket: cod...
1028
  static unsigned int sock_poll(struct file *file, poll_table *wait)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1029
1030
1031
1032
  {
  	struct socket *sock;
  
  	/*
89bddce58   Stephen Hemminger   [NET] socket: cod...
1033
  	 *      We can't return errors to poll, so it's either yes or no.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1034
  	 */
b69aee04f   Eric Dumazet   [NET]: Use file->...
1035
  	sock = file->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1036
1037
  	return sock->ops->poll(file, sock, wait);
  }
89bddce58   Stephen Hemminger   [NET] socket: cod...
1038
  static int sock_mmap(struct file *file, struct vm_area_struct *vma)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1039
  {
b69aee04f   Eric Dumazet   [NET]: Use file->...
1040
  	struct socket *sock = file->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1041
1042
1043
  
  	return sock->ops->mmap(file, sock, vma);
  }
20380731b   Arnaldo Carvalho de Melo   [NET]: Fix sparse...
1044
  static int sock_close(struct inode *inode, struct file *filp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1045
1046
  {
  	/*
89bddce58   Stephen Hemminger   [NET] socket: cod...
1047
1048
  	 *      It was possible the inode is NULL we were
  	 *      closing an unfinished socket.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1049
  	 */
89bddce58   Stephen Hemminger   [NET] socket: cod...
1050
  	if (!inode) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1051
1052
1053
1054
  		printk(KERN_DEBUG "sock_close: NULL inode
  ");
  		return 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
  	sock_release(SOCKET_I(inode));
  	return 0;
  }
  
  /*
   *	Update the socket async list
   *
   *	Fasync_list locking strategy.
   *
   *	1. fasync_list is modified only under process context socket lock
   *	   i.e. under semaphore.
   *	2. fasync_list is used under read_lock(&sk->sk_callback_lock)
989a29792   Eric Dumazet   fasync: RCU and f...
1067
   *	   or under socket lock
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1068
1069
1070
1071
   */
  
  static int sock_fasync(int fd, struct file *filp, int on)
  {
989a29792   Eric Dumazet   fasync: RCU and f...
1072
1073
  	struct socket *sock = filp->private_data;
  	struct sock *sk = sock->sk;
eaefd1105   Eric Dumazet   net: add __rcu an...
1074
  	struct socket_wq *wq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1075

989a29792   Eric Dumazet   fasync: RCU and f...
1076
  	if (sk == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1077
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1078
1079
  
  	lock_sock(sk);
eaefd1105   Eric Dumazet   net: add __rcu an...
1080
1081
  	wq = rcu_dereference_protected(sock->wq, sock_owned_by_user(sk));
  	fasync_helper(fd, filp, on, &wq->fasync_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1082

eaefd1105   Eric Dumazet   net: add __rcu an...
1083
  	if (!wq->fasync_list)
989a29792   Eric Dumazet   fasync: RCU and f...
1084
1085
  		sock_reset_flag(sk, SOCK_FASYNC);
  	else
bcdce7195   Eric Dumazet   net: speedup sk_w...
1086
  		sock_set_flag(sk, SOCK_FASYNC);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1087

989a29792   Eric Dumazet   fasync: RCU and f...
1088
  	release_sock(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1089
1090
  	return 0;
  }
438154823   Eric Dumazet   net: sock_def_rea...
1091
  /* This function may be called only under socket lock or callback_lock or rcu_lock */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1092
1093
1094
  
  int sock_wake_async(struct socket *sock, int how, int band)
  {
438154823   Eric Dumazet   net: sock_def_rea...
1095
1096
1097
1098
1099
1100
1101
1102
  	struct socket_wq *wq;
  
  	if (!sock)
  		return -1;
  	rcu_read_lock();
  	wq = rcu_dereference(sock->wq);
  	if (!wq || !wq->fasync_list) {
  		rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1103
  		return -1;
438154823   Eric Dumazet   net: sock_def_rea...
1104
  	}
89bddce58   Stephen Hemminger   [NET] socket: cod...
1105
  	switch (how) {
8d8ad9d7c   Pavel Emelyanov   [NET]: Name magic...
1106
  	case SOCK_WAKE_WAITD:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1107
1108
1109
  		if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
  			break;
  		goto call_kill;
8d8ad9d7c   Pavel Emelyanov   [NET]: Name magic...
1110
  	case SOCK_WAKE_SPACE:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1111
1112
1113
  		if (!test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags))
  			break;
  		/* fall through */
8d8ad9d7c   Pavel Emelyanov   [NET]: Name magic...
1114
  	case SOCK_WAKE_IO:
89bddce58   Stephen Hemminger   [NET] socket: cod...
1115
  call_kill:
438154823   Eric Dumazet   net: sock_def_rea...
1116
  		kill_fasync(&wq->fasync_list, SIGIO, band);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1117
  		break;
8d8ad9d7c   Pavel Emelyanov   [NET]: Name magic...
1118
  	case SOCK_WAKE_URG:
438154823   Eric Dumazet   net: sock_def_rea...
1119
  		kill_fasync(&wq->fasync_list, SIGURG, band);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1120
  	}
438154823   Eric Dumazet   net: sock_def_rea...
1121
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1122
1123
  	return 0;
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
1124
  EXPORT_SYMBOL(sock_wake_async);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1125

721db93a5   Pavel Emelyanov   net: Export __soc...
1126
  int __sock_create(struct net *net, int family, int type, int protocol,
89bddce58   Stephen Hemminger   [NET] socket: cod...
1127
  			 struct socket **res, int kern)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1128
1129
1130
  {
  	int err;
  	struct socket *sock;
55737fda0   Stephen Hemminger   [NET]: socket fam...
1131
  	const struct net_proto_family *pf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1132
1133
  
  	/*
89bddce58   Stephen Hemminger   [NET] socket: cod...
1134
  	 *      Check protocol is in range
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
  	 */
  	if (family < 0 || family >= NPROTO)
  		return -EAFNOSUPPORT;
  	if (type < 0 || type >= SOCK_MAX)
  		return -EINVAL;
  
  	/* Compatibility.
  
  	   This uglymoron is moved from INET layer to here to avoid
  	   deadlock in module load.
  	 */
  	if (family == PF_INET && type == SOCK_PACKET) {
89bddce58   Stephen Hemminger   [NET] socket: cod...
1147
  		static int warned;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1148
1149
  		if (!warned) {
  			warned = 1;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1150
1151
1152
  			printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)
  ",
  			       current->comm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1153
1154
1155
1156
1157
1158
1159
  		}
  		family = PF_PACKET;
  	}
  
  	err = security_socket_create(family, type, protocol, kern);
  	if (err)
  		return err;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1160

55737fda0   Stephen Hemminger   [NET]: socket fam...
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
  	/*
  	 *	Allocate the socket and allow the family to set things up. if
  	 *	the protocol is 0, the family is instructed to select an appropriate
  	 *	default.
  	 */
  	sock = sock_alloc();
  	if (!sock) {
  		if (net_ratelimit())
  			printk(KERN_WARNING "socket: no more sockets
  ");
  		return -ENFILE;	/* Not exactly a match, but its the
  				   closest posix thing */
  	}
  
  	sock->type = type;
95a5afca4   Johannes Berg   net: Remove CONFI...
1176
  #ifdef CONFIG_MODULES
89bddce58   Stephen Hemminger   [NET] socket: cod...
1177
1178
1179
  	/* Attempt to load a protocol module if the find failed.
  	 *
  	 * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1180
1181
1182
  	 * requested real, full-featured networking support upon configuration.
  	 * Otherwise module support will break!
  	 */
190683a9d   Eric Dumazet   net: net_families...
1183
  	if (rcu_access_pointer(net_families[family]) == NULL)
89bddce58   Stephen Hemminger   [NET] socket: cod...
1184
  		request_module("net-pf-%d", family);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1185
  #endif
55737fda0   Stephen Hemminger   [NET]: socket fam...
1186
1187
1188
1189
1190
  	rcu_read_lock();
  	pf = rcu_dereference(net_families[family]);
  	err = -EAFNOSUPPORT;
  	if (!pf)
  		goto out_release;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1191
1192
1193
1194
1195
  
  	/*
  	 * We will call the ->create function, that possibly is in a loadable
  	 * module, so we have to bump that loadable module refcnt first.
  	 */
55737fda0   Stephen Hemminger   [NET]: socket fam...
1196
  	if (!try_module_get(pf->owner))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1197
  		goto out_release;
55737fda0   Stephen Hemminger   [NET]: socket fam...
1198
1199
  	/* Now protected by module ref count */
  	rcu_read_unlock();
3f378b684   Eric Paris   net: pass kern to...
1200
  	err = pf->create(net, sock, protocol, kern);
55737fda0   Stephen Hemminger   [NET]: socket fam...
1201
  	if (err < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1202
  		goto out_module_put;
a79af59ef   Frank Filz   [NET]: Fix module...
1203

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1204
1205
1206
1207
  	/*
  	 * Now to bump the refcnt of the [loadable] module that owns this
  	 * socket at sock_release time we decrement its refcnt.
  	 */
55737fda0   Stephen Hemminger   [NET]: socket fam...
1208
1209
  	if (!try_module_get(sock->ops->owner))
  		goto out_module_busy;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1210
1211
1212
1213
  	/*
  	 * Now that we're done with the ->create function, the [loadable]
  	 * module can have its refcnt decremented
  	 */
55737fda0   Stephen Hemminger   [NET]: socket fam...
1214
  	module_put(pf->owner);
7420ed23a   Venkat Yekkirala   [NetLabel]: SELin...
1215
1216
  	err = security_socket_post_create(sock, family, type, protocol, kern);
  	if (err)
3b1855255   Herbert Xu   [NET]: Fix unbala...
1217
  		goto out_sock_release;
55737fda0   Stephen Hemminger   [NET]: socket fam...
1218
  	*res = sock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1219

55737fda0   Stephen Hemminger   [NET]: socket fam...
1220
1221
1222
1223
  	return 0;
  
  out_module_busy:
  	err = -EAFNOSUPPORT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1224
  out_module_put:
55737fda0   Stephen Hemminger   [NET]: socket fam...
1225
1226
1227
  	sock->ops = NULL;
  	module_put(pf->owner);
  out_sock_release:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1228
  	sock_release(sock);
55737fda0   Stephen Hemminger   [NET]: socket fam...
1229
1230
1231
1232
1233
  	return err;
  
  out_release:
  	rcu_read_unlock();
  	goto out_sock_release;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1234
  }
721db93a5   Pavel Emelyanov   net: Export __soc...
1235
  EXPORT_SYMBOL(__sock_create);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1236
1237
1238
  
  int sock_create(int family, int type, int protocol, struct socket **res)
  {
1b8d7ae42   Eric W. Biederman   [NET]: Make socke...
1239
  	return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1240
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
1241
  EXPORT_SYMBOL(sock_create);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1242
1243
1244
  
  int sock_create_kern(int family, int type, int protocol, struct socket **res)
  {
1b8d7ae42   Eric W. Biederman   [NET]: Make socke...
1245
  	return __sock_create(&init_net, family, type, protocol, res, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1246
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
1247
  EXPORT_SYMBOL(sock_create_kern);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1248

3e0fa65f8   Heiko Carstens   [CVE-2009-0029] S...
1249
  SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1250
1251
1252
  {
  	int retval;
  	struct socket *sock;
a677a039b   Ulrich Drepper   flag parameters: ...
1253
  	int flags;
e38b36f32   Ulrich Drepper   flag parameters: ...
1254
1255
1256
1257
1258
  	/* Check the SOCK_* constants for consistency.  */
  	BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
  	BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
  	BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);
  	BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);
a677a039b   Ulrich Drepper   flag parameters: ...
1259
  	flags = type & ~SOCK_TYPE_MASK;
77d272005   Ulrich Drepper   flag parameters: ...
1260
  	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
a677a039b   Ulrich Drepper   flag parameters: ...
1261
1262
  		return -EINVAL;
  	type &= SOCK_TYPE_MASK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1263

aaca0bdca   Ulrich Drepper   flag parameters: ...
1264
1265
  	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
  		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1266
1267
1268
  	retval = sock_create(family, type, protocol, &sock);
  	if (retval < 0)
  		goto out;
77d272005   Ulrich Drepper   flag parameters: ...
1269
  	retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
  	if (retval < 0)
  		goto out_release;
  
  out:
  	/* It may be already another descriptor 8) Not kernel problem. */
  	return retval;
  
  out_release:
  	sock_release(sock);
  	return retval;
  }
  
  /*
   *	Create a pair of connected sockets.
   */
3e0fa65f8   Heiko Carstens   [CVE-2009-0029] S...
1285
1286
  SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
  		int __user *, usockvec)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1287
1288
1289
  {
  	struct socket *sock1, *sock2;
  	int fd1, fd2, err;
db3495099   Al Viro   [PATCH] AUDIT_FD_...
1290
  	struct file *newfile1, *newfile2;
a677a039b   Ulrich Drepper   flag parameters: ...
1291
1292
1293
  	int flags;
  
  	flags = type & ~SOCK_TYPE_MASK;
77d272005   Ulrich Drepper   flag parameters: ...
1294
  	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
a677a039b   Ulrich Drepper   flag parameters: ...
1295
1296
  		return -EINVAL;
  	type &= SOCK_TYPE_MASK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1297

aaca0bdca   Ulrich Drepper   flag parameters: ...
1298
1299
  	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
  		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
  	/*
  	 * Obtain the first socket and check if the underlying protocol
  	 * supports the socketpair call.
  	 */
  
  	err = sock_create(family, type, protocol, &sock1);
  	if (err < 0)
  		goto out;
  
  	err = sock_create(family, type, protocol, &sock2);
  	if (err < 0)
  		goto out_release_1;
  
  	err = sock1->ops->socketpair(sock1, sock2);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1314
  	if (err < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1315
  		goto out_release_both;
7cbe66b6b   Al Viro   merge sock_alloc_...
1316
  	fd1 = sock_alloc_file(sock1, &newfile1, flags);
bf3c23d17   David S. Miller   [NET]: Fix error ...
1317
1318
  	if (unlikely(fd1 < 0)) {
  		err = fd1;
db3495099   Al Viro   [PATCH] AUDIT_FD_...
1319
  		goto out_release_both;
bf3c23d17   David S. Miller   [NET]: Fix error ...
1320
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1321

7cbe66b6b   Al Viro   merge sock_alloc_...
1322
  	fd2 = sock_alloc_file(sock2, &newfile2, flags);
198de4d7a   Al Viro   reorder alloc_fd/...
1323
1324
1325
1326
1327
1328
  	if (unlikely(fd2 < 0)) {
  		err = fd2;
  		fput(newfile1);
  		put_unused_fd(fd1);
  		sock_release(sock2);
  		goto out;
db3495099   Al Viro   [PATCH] AUDIT_FD_...
1329
  	}
157cf649a   Al Viro   sanitize audit_fd...
1330
  	audit_fd_pair(fd1, fd2);
db3495099   Al Viro   [PATCH] AUDIT_FD_...
1331
1332
  	fd_install(fd1, newfile1);
  	fd_install(fd2, newfile2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1333
1334
1335
  	/* fd1 and fd2 may be already another descriptors.
  	 * Not kernel problem.
  	 */
89bddce58   Stephen Hemminger   [NET] socket: cod...
1336
  	err = put_user(fd1, &usockvec[0]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1337
1338
1339
1340
1341
1342
1343
1344
  	if (!err)
  		err = put_user(fd2, &usockvec[1]);
  	if (!err)
  		return 0;
  
  	sys_close(fd2);
  	sys_close(fd1);
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1345
  out_release_both:
89bddce58   Stephen Hemminger   [NET] socket: cod...
1346
  	sock_release(sock2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1347
  out_release_1:
89bddce58   Stephen Hemminger   [NET] socket: cod...
1348
  	sock_release(sock1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1349
1350
1351
  out:
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1352
1353
1354
1355
1356
1357
1358
  /*
   *	Bind a name to a socket. Nothing much to do here since it's
   *	the protocol's responsibility to handle the local address.
   *
   *	We move the socket address to kernel space before we call
   *	the protocol layer (having also checked the address is ok).
   */
20f37034f   Heiko Carstens   [CVE-2009-0029] S...
1359
  SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1360
1361
  {
  	struct socket *sock;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1362
  	struct sockaddr_storage address;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1363
  	int err, fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1364

89bddce58   Stephen Hemminger   [NET] socket: cod...
1365
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
e71a4783a   Stephen Hemminger   [NET] core: white...
1366
  	if (sock) {
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1367
  		err = move_addr_to_kernel(umyaddr, addrlen, (struct sockaddr *)&address);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1368
1369
  		if (err >= 0) {
  			err = security_socket_bind(sock,
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1370
  						   (struct sockaddr *)&address,
89bddce58   Stephen Hemminger   [NET] socket: cod...
1371
  						   addrlen);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1372
1373
  			if (!err)
  				err = sock->ops->bind(sock,
89bddce58   Stephen Hemminger   [NET] socket: cod...
1374
  						      (struct sockaddr *)
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1375
  						      &address, addrlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1376
  		}
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1377
  		fput_light(sock->file, fput_needed);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1378
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1379
1380
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1381
1382
1383
1384
1385
  /*
   *	Perform a listen. Basically, we allow the protocol to do anything
   *	necessary for a listen, and if that works, we mark the socket as
   *	ready for listening.
   */
3e0fa65f8   Heiko Carstens   [CVE-2009-0029] S...
1386
  SYSCALL_DEFINE2(listen, int, fd, int, backlog)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1387
1388
  {
  	struct socket *sock;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1389
  	int err, fput_needed;
b8e1f9b5c   Pavel Emelyanov   [NET] sysctl: mak...
1390
  	int somaxconn;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1391
1392
1393
  
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
  	if (sock) {
8efa6e93c   Pavel Emelyanov   [NETNS]: Introduc...
1394
  		somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
b8e1f9b5c   Pavel Emelyanov   [NET] sysctl: mak...
1395
1396
  		if ((unsigned)backlog > somaxconn)
  			backlog = somaxconn;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1397
1398
  
  		err = security_socket_listen(sock, backlog);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1399
1400
  		if (!err)
  			err = sock->ops->listen(sock, backlog);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1401

6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1402
  		fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1403
1404
1405
  	}
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
  /*
   *	For accept, we attempt to create a new socket, set up the link
   *	with the client, wake up the client, then return the new
   *	connected fd. We collect the address of the connector in kernel
   *	space and move it to user at the very end. This is unclean because
   *	we open the socket then return an error.
   *
   *	1003.1g adds the ability to recvmsg() to query connection pending
   *	status to recvmsg. We need to add that support in a way thats
   *	clean when we restucture accept also.
   */
20f37034f   Heiko Carstens   [CVE-2009-0029] S...
1417
1418
  SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
  		int __user *, upeer_addrlen, int, flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1419
1420
  {
  	struct socket *sock, *newsock;
39d8c1b6f   David S. Miller   [NET]: Do not los...
1421
  	struct file *newfile;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1422
  	int err, len, newfd, fput_needed;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1423
  	struct sockaddr_storage address;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1424

77d272005   Ulrich Drepper   flag parameters: ...
1425
  	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
aaca0bdca   Ulrich Drepper   flag parameters: ...
1426
1427
1428
1429
  		return -EINVAL;
  
  	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
  		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1430
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1431
1432
1433
1434
  	if (!sock)
  		goto out;
  
  	err = -ENFILE;
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
1435
1436
  	newsock = sock_alloc();
  	if (!newsock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1437
1438
1439
1440
  		goto out_put;
  
  	newsock->type = sock->type;
  	newsock->ops = sock->ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1441
1442
1443
1444
1445
  	/*
  	 * We don't need try_module_get here, as the listening socket (sock)
  	 * has the protocol module (sock->ops->owner) held.
  	 */
  	__module_get(newsock->ops->owner);
7cbe66b6b   Al Viro   merge sock_alloc_...
1446
  	newfd = sock_alloc_file(newsock, &newfile, flags);
39d8c1b6f   David S. Miller   [NET]: Do not los...
1447
1448
  	if (unlikely(newfd < 0)) {
  		err = newfd;
9a1875e60   David S. Miller   [NET]: Fully fix ...
1449
1450
  		sock_release(newsock);
  		goto out_put;
39d8c1b6f   David S. Miller   [NET]: Do not los...
1451
  	}
a79af59ef   Frank Filz   [NET]: Fix module...
1452
1453
  	err = security_socket_accept(sock, newsock);
  	if (err)
39d8c1b6f   David S. Miller   [NET]: Do not los...
1454
  		goto out_fd;
a79af59ef   Frank Filz   [NET]: Fix module...
1455

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1456
1457
  	err = sock->ops->accept(sock, newsock, sock->file->f_flags);
  	if (err < 0)
39d8c1b6f   David S. Miller   [NET]: Do not los...
1458
  		goto out_fd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1459
1460
  
  	if (upeer_sockaddr) {
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1461
  		if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
89bddce58   Stephen Hemminger   [NET] socket: cod...
1462
  					  &len, 2) < 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1463
  			err = -ECONNABORTED;
39d8c1b6f   David S. Miller   [NET]: Do not los...
1464
  			goto out_fd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1465
  		}
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1466
1467
  		err = move_addr_to_user((struct sockaddr *)&address,
  					len, upeer_sockaddr, upeer_addrlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1468
  		if (err < 0)
39d8c1b6f   David S. Miller   [NET]: Do not los...
1469
  			goto out_fd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1470
1471
1472
  	}
  
  	/* File flags are not inherited via accept() unlike another OSes. */
39d8c1b6f   David S. Miller   [NET]: Do not los...
1473
1474
  	fd_install(newfd, newfile);
  	err = newfd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1475

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1476
  out_put:
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1477
  	fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1478
1479
  out:
  	return err;
39d8c1b6f   David S. Miller   [NET]: Do not los...
1480
  out_fd:
9606a2163   David S. Miller   [NET]: Fix dentry...
1481
  	fput(newfile);
39d8c1b6f   David S. Miller   [NET]: Do not los...
1482
  	put_unused_fd(newfd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1483
1484
  	goto out_put;
  }
20f37034f   Heiko Carstens   [CVE-2009-0029] S...
1485
1486
  SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,
  		int __user *, upeer_addrlen)
aaca0bdca   Ulrich Drepper   flag parameters: ...
1487
  {
de11defeb   Ulrich Drepper   reintroduce accept4
1488
  	return sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0);
aaca0bdca   Ulrich Drepper   flag parameters: ...
1489
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
  /*
   *	Attempt to connect to a socket with the server address.  The address
   *	is in user space so we verify it is OK and move it to kernel space.
   *
   *	For 1003.1g we need to add clean support for a bind to AF_UNSPEC to
   *	break bindings
   *
   *	NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and
   *	other SEQPACKET protocols that take time to connect() as it doesn't
   *	include the -EINPROGRESS status for such sockets.
   */
20f37034f   Heiko Carstens   [CVE-2009-0029] S...
1501
1502
  SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
  		int, addrlen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1503
1504
  {
  	struct socket *sock;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1505
  	struct sockaddr_storage address;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1506
  	int err, fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1507

6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1508
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1509
1510
  	if (!sock)
  		goto out;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1511
  	err = move_addr_to_kernel(uservaddr, addrlen, (struct sockaddr *)&address);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1512
1513
  	if (err < 0)
  		goto out_put;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1514
  	err =
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1515
  	    security_socket_connect(sock, (struct sockaddr *)&address, addrlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1516
1517
  	if (err)
  		goto out_put;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1518
  	err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1519
1520
  				 sock->file->f_flags);
  out_put:
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1521
  	fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1522
1523
1524
1525
1526
1527
1528
1529
  out:
  	return err;
  }
  
  /*
   *	Get the local address ('name') of a socket object. Move the obtained
   *	name to user space.
   */
20f37034f   Heiko Carstens   [CVE-2009-0029] S...
1530
1531
  SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
  		int __user *, usockaddr_len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1532
1533
  {
  	struct socket *sock;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1534
  	struct sockaddr_storage address;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1535
  	int len, err, fput_needed;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1536

6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1537
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1538
1539
1540
1541
1542
1543
  	if (!sock)
  		goto out;
  
  	err = security_socket_getsockname(sock);
  	if (err)
  		goto out_put;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1544
  	err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1545
1546
  	if (err)
  		goto out_put;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1547
  	err = move_addr_to_user((struct sockaddr *)&address, len, usockaddr, usockaddr_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1548
1549
  
  out_put:
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1550
  	fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1551
1552
1553
1554
1555
1556
1557
1558
  out:
  	return err;
  }
  
  /*
   *	Get the remote address ('name') of a socket object. Move the obtained
   *	name to user space.
   */
20f37034f   Heiko Carstens   [CVE-2009-0029] S...
1559
1560
  SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
  		int __user *, usockaddr_len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1561
1562
  {
  	struct socket *sock;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1563
  	struct sockaddr_storage address;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1564
  	int len, err, fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1565

89bddce58   Stephen Hemminger   [NET] socket: cod...
1566
1567
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
  	if (sock != NULL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1568
1569
  		err = security_socket_getpeername(sock);
  		if (err) {
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1570
  			fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1571
1572
  			return err;
  		}
89bddce58   Stephen Hemminger   [NET] socket: cod...
1573
  		err =
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1574
  		    sock->ops->getname(sock, (struct sockaddr *)&address, &len,
89bddce58   Stephen Hemminger   [NET] socket: cod...
1575
  				       1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1576
  		if (!err)
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1577
  			err = move_addr_to_user((struct sockaddr *)&address, len, usockaddr,
89bddce58   Stephen Hemminger   [NET] socket: cod...
1578
  						usockaddr_len);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1579
  		fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1580
1581
1582
1583
1584
1585
1586
1587
1588
  	}
  	return err;
  }
  
  /*
   *	Send a datagram to a given address. We move the address into kernel
   *	space and check the user space data area is readable before invoking
   *	the protocol.
   */
3e0fa65f8   Heiko Carstens   [CVE-2009-0029] S...
1589
1590
1591
  SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
  		unsigned, flags, struct sockaddr __user *, addr,
  		int, addr_len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1592
1593
  {
  	struct socket *sock;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1594
  	struct sockaddr_storage address;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1595
1596
1597
  	int err;
  	struct msghdr msg;
  	struct iovec iov;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1598
  	int fput_needed;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1599

253eacc07   Linus Torvalds   net: Truncate rec...
1600
1601
  	if (len > INT_MAX)
  		len = INT_MAX;
de0fa95c1   Pavel Emelyanov   [NET]: Use sockfd...
1602
1603
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
  	if (!sock)
4387ff75f   David S. Miller   [NET]: Fix net/so...
1604
  		goto out;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1605

89bddce58   Stephen Hemminger   [NET] socket: cod...
1606
1607
1608
1609
1610
1611
1612
1613
  	iov.iov_base = buff;
  	iov.iov_len = len;
  	msg.msg_name = NULL;
  	msg.msg_iov = &iov;
  	msg.msg_iovlen = 1;
  	msg.msg_control = NULL;
  	msg.msg_controllen = 0;
  	msg.msg_namelen = 0;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1614
  	if (addr) {
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1615
  		err = move_addr_to_kernel(addr, addr_len, (struct sockaddr *)&address);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1616
1617
  		if (err < 0)
  			goto out_put;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1618
  		msg.msg_name = (struct sockaddr *)&address;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1619
  		msg.msg_namelen = addr_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1620
1621
1622
1623
1624
  	}
  	if (sock->file->f_flags & O_NONBLOCK)
  		flags |= MSG_DONTWAIT;
  	msg.msg_flags = flags;
  	err = sock_sendmsg(sock, &msg, len);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1625
  out_put:
de0fa95c1   Pavel Emelyanov   [NET]: Use sockfd...
1626
  	fput_light(sock->file, fput_needed);
4387ff75f   David S. Miller   [NET]: Fix net/so...
1627
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1628
1629
1630
1631
  	return err;
  }
  
  /*
89bddce58   Stephen Hemminger   [NET] socket: cod...
1632
   *	Send a datagram down a socket.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1633
   */
3e0fa65f8   Heiko Carstens   [CVE-2009-0029] S...
1634
1635
  SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len,
  		unsigned, flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1636
1637
1638
1639
1640
  {
  	return sys_sendto(fd, buff, len, flags, NULL, 0);
  }
  
  /*
89bddce58   Stephen Hemminger   [NET] socket: cod...
1641
   *	Receive a frame from the socket and optionally record the address of the
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1642
1643
1644
   *	sender. We verify the buffers are writable and if needed move the
   *	sender address from kernel to user space.
   */
3e0fa65f8   Heiko Carstens   [CVE-2009-0029] S...
1645
1646
1647
  SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
  		unsigned, flags, struct sockaddr __user *, addr,
  		int __user *, addr_len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1648
1649
1650
1651
  {
  	struct socket *sock;
  	struct iovec iov;
  	struct msghdr msg;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1652
  	struct sockaddr_storage address;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1653
  	int err, err2;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1654
  	int fput_needed;
253eacc07   Linus Torvalds   net: Truncate rec...
1655
1656
  	if (size > INT_MAX)
  		size = INT_MAX;
de0fa95c1   Pavel Emelyanov   [NET]: Use sockfd...
1657
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1658
  	if (!sock)
de0fa95c1   Pavel Emelyanov   [NET]: Use sockfd...
1659
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1660

89bddce58   Stephen Hemminger   [NET] socket: cod...
1661
1662
1663
1664
1665
1666
  	msg.msg_control = NULL;
  	msg.msg_controllen = 0;
  	msg.msg_iovlen = 1;
  	msg.msg_iov = &iov;
  	iov.iov_len = size;
  	iov.iov_base = ubuf;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1667
1668
  	msg.msg_name = (struct sockaddr *)&address;
  	msg.msg_namelen = sizeof(address);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1669
1670
  	if (sock->file->f_flags & O_NONBLOCK)
  		flags |= MSG_DONTWAIT;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1671
  	err = sock_recvmsg(sock, &msg, size, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1672

89bddce58   Stephen Hemminger   [NET] socket: cod...
1673
  	if (err >= 0 && addr != NULL) {
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1674
1675
  		err2 = move_addr_to_user((struct sockaddr *)&address,
  					 msg.msg_namelen, addr, addr_len);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1676
1677
  		if (err2 < 0)
  			err = err2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1678
  	}
de0fa95c1   Pavel Emelyanov   [NET]: Use sockfd...
1679
1680
  
  	fput_light(sock->file, fput_needed);
4387ff75f   David S. Miller   [NET]: Fix net/so...
1681
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1682
1683
1684
1685
  	return err;
  }
  
  /*
89bddce58   Stephen Hemminger   [NET] socket: cod...
1686
   *	Receive a datagram from a socket.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1687
   */
89bddce58   Stephen Hemminger   [NET] socket: cod...
1688
1689
  asmlinkage long sys_recv(int fd, void __user *ubuf, size_t size,
  			 unsigned flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1690
1691
1692
1693
1694
1695
1696
1697
  {
  	return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL);
  }
  
  /*
   *	Set a socket option. Because we don't know the option lengths we have
   *	to pass the user mode parameter for the protocols to sort out.
   */
20f37034f   Heiko Carstens   [CVE-2009-0029] S...
1698
1699
  SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
  		char __user *, optval, int, optlen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1700
  {
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1701
  	int err, fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1702
1703
1704
1705
  	struct socket *sock;
  
  	if (optlen < 0)
  		return -EINVAL;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1706
1707
1708
1709
  
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
  	if (sock != NULL) {
  		err = security_socket_setsockopt(sock, level, optname);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1710
1711
  		if (err)
  			goto out_put;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1712
1713
  
  		if (level == SOL_SOCKET)
89bddce58   Stephen Hemminger   [NET] socket: cod...
1714
1715
1716
  			err =
  			    sock_setsockopt(sock, level, optname, optval,
  					    optlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1717
  		else
89bddce58   Stephen Hemminger   [NET] socket: cod...
1718
1719
1720
  			err =
  			    sock->ops->setsockopt(sock, level, optname, optval,
  						  optlen);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1721
1722
  out_put:
  		fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1723
1724
1725
1726
1727
1728
1729
1730
  	}
  	return err;
  }
  
  /*
   *	Get a socket option. Because we don't know the option lengths we have
   *	to pass a user mode parameter for the protocols to sort out.
   */
20f37034f   Heiko Carstens   [CVE-2009-0029] S...
1731
1732
  SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
  		char __user *, optval, int __user *, optlen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1733
  {
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1734
  	int err, fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1735
  	struct socket *sock;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1736
1737
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
  	if (sock != NULL) {
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1738
1739
1740
  		err = security_socket_getsockopt(sock, level, optname);
  		if (err)
  			goto out_put;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1741
1742
  
  		if (level == SOL_SOCKET)
89bddce58   Stephen Hemminger   [NET] socket: cod...
1743
1744
1745
  			err =
  			    sock_getsockopt(sock, level, optname, optval,
  					    optlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1746
  		else
89bddce58   Stephen Hemminger   [NET] socket: cod...
1747
1748
1749
  			err =
  			    sock->ops->getsockopt(sock, level, optname, optval,
  						  optlen);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1750
1751
  out_put:
  		fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1752
1753
1754
  	}
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1755
1756
1757
  /*
   *	Shutdown a socket.
   */
754fe8d29   Heiko Carstens   [CVE-2009-0029] S...
1758
  SYSCALL_DEFINE2(shutdown, int, fd, int, how)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1759
  {
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1760
  	int err, fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1761
  	struct socket *sock;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1762
1763
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
  	if (sock != NULL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1764
  		err = security_socket_shutdown(sock, how);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1765
1766
1767
  		if (!err)
  			err = sock->ops->shutdown(sock, how);
  		fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1768
1769
1770
  	}
  	return err;
  }
89bddce58   Stephen Hemminger   [NET] socket: cod...
1771
  /* A couple of helpful macros for getting the address of the 32/64 bit
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1772
1773
1774
1775
1776
   * fields which are the same type (int / unsigned) on our platforms.
   */
  #define COMPAT_MSG(msg, member)	((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member)
  #define COMPAT_NAMELEN(msg)	COMPAT_MSG(msg, msg_namelen)
  #define COMPAT_FLAGS(msg)	COMPAT_MSG(msg, msg_flags)
c71d8ebe7   Tetsuo Handa   net: Fix security...
1777
1778
1779
1780
  struct used_address {
  	struct sockaddr_storage name;
  	unsigned int name_len;
  };
228e548e6   Anton Blanchard   net: Add sendmmsg...
1781
  static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
c71d8ebe7   Tetsuo Handa   net: Fix security...
1782
1783
  			 struct msghdr *msg_sys, unsigned flags,
  			 struct used_address *used_address)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1784
  {
89bddce58   Stephen Hemminger   [NET] socket: cod...
1785
1786
  	struct compat_msghdr __user *msg_compat =
  	    (struct compat_msghdr __user *)msg;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1787
  	struct sockaddr_storage address;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1788
  	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
b9d717a7b   Alex Williamson   [NET]: Make sure ...
1789
  	unsigned char ctl[sizeof(struct cmsghdr) + 20]
89bddce58   Stephen Hemminger   [NET] socket: cod...
1790
1791
  	    __attribute__ ((aligned(sizeof(__kernel_size_t))));
  	/* 20 is size of ipv6_pktinfo */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1792
  	unsigned char *ctl_buf = ctl;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1793
  	int err, ctl_len, iov_size, total_len;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1794

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1795
1796
  	err = -EFAULT;
  	if (MSG_CMSG_COMPAT & flags) {
228e548e6   Anton Blanchard   net: Add sendmmsg...
1797
  		if (get_compat_msghdr(msg_sys, msg_compat))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1798
  			return -EFAULT;
228e548e6   Anton Blanchard   net: Add sendmmsg...
1799
  	} else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1800
  		return -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1801
1802
  	/* do not move before msg_sys is valid */
  	err = -EMSGSIZE;
228e548e6   Anton Blanchard   net: Add sendmmsg...
1803
1804
  	if (msg_sys->msg_iovlen > UIO_MAXIOV)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1805

89bddce58   Stephen Hemminger   [NET] socket: cod...
1806
  	/* Check whether to allocate the iovec area */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1807
  	err = -ENOMEM;
228e548e6   Anton Blanchard   net: Add sendmmsg...
1808
1809
  	iov_size = msg_sys->msg_iovlen * sizeof(struct iovec);
  	if (msg_sys->msg_iovlen > UIO_FASTIOV) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1810
1811
  		iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
  		if (!iov)
228e548e6   Anton Blanchard   net: Add sendmmsg...
1812
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1813
1814
1815
1816
  	}
  
  	/* This will also move the address data into kernel space */
  	if (MSG_CMSG_COMPAT & flags) {
228e548e6   Anton Blanchard   net: Add sendmmsg...
1817
  		err = verify_compat_iovec(msg_sys, iov,
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1818
1819
  					  (struct sockaddr *)&address,
  					  VERIFY_READ);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1820
  	} else
228e548e6   Anton Blanchard   net: Add sendmmsg...
1821
  		err = verify_iovec(msg_sys, iov,
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1822
1823
  				   (struct sockaddr *)&address,
  				   VERIFY_READ);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1824
  	if (err < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1825
1826
1827
1828
  		goto out_freeiov;
  	total_len = err;
  
  	err = -ENOBUFS;
228e548e6   Anton Blanchard   net: Add sendmmsg...
1829
  	if (msg_sys->msg_controllen > INT_MAX)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1830
  		goto out_freeiov;
228e548e6   Anton Blanchard   net: Add sendmmsg...
1831
  	ctl_len = msg_sys->msg_controllen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1832
  	if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
89bddce58   Stephen Hemminger   [NET] socket: cod...
1833
  		err =
228e548e6   Anton Blanchard   net: Add sendmmsg...
1834
  		    cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl,
89bddce58   Stephen Hemminger   [NET] socket: cod...
1835
  						     sizeof(ctl));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1836
1837
  		if (err)
  			goto out_freeiov;
228e548e6   Anton Blanchard   net: Add sendmmsg...
1838
1839
  		ctl_buf = msg_sys->msg_control;
  		ctl_len = msg_sys->msg_controllen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1840
  	} else if (ctl_len) {
89bddce58   Stephen Hemminger   [NET] socket: cod...
1841
  		if (ctl_len > sizeof(ctl)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1842
  			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1843
  			if (ctl_buf == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1844
1845
1846
1847
  				goto out_freeiov;
  		}
  		err = -EFAULT;
  		/*
228e548e6   Anton Blanchard   net: Add sendmmsg...
1848
  		 * Careful! Before this, msg_sys->msg_control contains a user pointer.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1849
1850
1851
  		 * Afterwards, it will be a kernel pointer. Thus the compiler-assisted
  		 * checking falls down on this.
  		 */
fb8621bb6   Namhyung Kim   net: remove addre...
1852
  		if (copy_from_user(ctl_buf,
228e548e6   Anton Blanchard   net: Add sendmmsg...
1853
  				   (void __user __force *)msg_sys->msg_control,
89bddce58   Stephen Hemminger   [NET] socket: cod...
1854
  				   ctl_len))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1855
  			goto out_freectl;
228e548e6   Anton Blanchard   net: Add sendmmsg...
1856
  		msg_sys->msg_control = ctl_buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1857
  	}
228e548e6   Anton Blanchard   net: Add sendmmsg...
1858
  	msg_sys->msg_flags = flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1859
1860
  
  	if (sock->file->f_flags & O_NONBLOCK)
228e548e6   Anton Blanchard   net: Add sendmmsg...
1861
  		msg_sys->msg_flags |= MSG_DONTWAIT;
c71d8ebe7   Tetsuo Handa   net: Fix security...
1862
1863
1864
1865
1866
1867
  	/*
  	 * If this is sendmmsg() and current destination address is same as
  	 * previously succeeded address, omit asking LSM's decision.
  	 * used_address->name_len is initialized to UINT_MAX so that the first
  	 * destination address never matches.
  	 */
bc909d9dd   Mathieu Desnoyers   sendmmsg/sendmsg:...
1868
1869
1870
  	if (used_address && msg_sys->msg_name &&
  	    used_address->name_len == msg_sys->msg_namelen &&
  	    !memcmp(&used_address->name, msg_sys->msg_name,
c71d8ebe7   Tetsuo Handa   net: Fix security...
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
  		    used_address->name_len)) {
  		err = sock_sendmsg_nosec(sock, msg_sys, total_len);
  		goto out_freectl;
  	}
  	err = sock_sendmsg(sock, msg_sys, total_len);
  	/*
  	 * If this is sendmmsg() and sending to current destination address was
  	 * successful, remember it.
  	 */
  	if (used_address && err >= 0) {
  		used_address->name_len = msg_sys->msg_namelen;
bc909d9dd   Mathieu Desnoyers   sendmmsg/sendmsg:...
1882
1883
1884
  		if (msg_sys->msg_name)
  			memcpy(&used_address->name, msg_sys->msg_name,
  			       used_address->name_len);
c71d8ebe7   Tetsuo Handa   net: Fix security...
1885
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1886
1887
  
  out_freectl:
89bddce58   Stephen Hemminger   [NET] socket: cod...
1888
  	if (ctl_buf != ctl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1889
1890
1891
1892
  		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
  out_freeiov:
  	if (iov != iovstack)
  		sock_kfree_s(sock->sk, iov, iov_size);
228e548e6   Anton Blanchard   net: Add sendmmsg...
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
  out:
  	return err;
  }
  
  /*
   *	BSD sendmsg interface
   */
  
  SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned, flags)
  {
  	int fput_needed, err;
  	struct msghdr msg_sys;
  	struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed);
  
  	if (!sock)
  		goto out;
c71d8ebe7   Tetsuo Handa   net: Fix security...
1909
  	err = __sys_sendmsg(sock, msg, &msg_sys, flags, NULL);
228e548e6   Anton Blanchard   net: Add sendmmsg...
1910

6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1911
  	fput_light(sock->file, fput_needed);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1912
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1913
1914
  	return err;
  }
228e548e6   Anton Blanchard   net: Add sendmmsg...
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
  /*
   *	Linux sendmmsg interface
   */
  
  int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
  		   unsigned int flags)
  {
  	int fput_needed, err, datagrams;
  	struct socket *sock;
  	struct mmsghdr __user *entry;
  	struct compat_mmsghdr __user *compat_entry;
  	struct msghdr msg_sys;
c71d8ebe7   Tetsuo Handa   net: Fix security...
1927
  	struct used_address used_address;
228e548e6   Anton Blanchard   net: Add sendmmsg...
1928

98382f419   Anton Blanchard   net: Cap number o...
1929
1930
  	if (vlen > UIO_MAXIOV)
  		vlen = UIO_MAXIOV;
228e548e6   Anton Blanchard   net: Add sendmmsg...
1931
1932
1933
1934
1935
1936
  
  	datagrams = 0;
  
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
  	if (!sock)
  		return err;
c71d8ebe7   Tetsuo Handa   net: Fix security...
1937
  	used_address.name_len = UINT_MAX;
228e548e6   Anton Blanchard   net: Add sendmmsg...
1938
1939
  	entry = mmsg;
  	compat_entry = (struct compat_mmsghdr __user *)mmsg;
728ffb86f   Anton Blanchard   net: sendmmsg sho...
1940
  	err = 0;
228e548e6   Anton Blanchard   net: Add sendmmsg...
1941
1942
  
  	while (datagrams < vlen) {
228e548e6   Anton Blanchard   net: Add sendmmsg...
1943
1944
  		if (MSG_CMSG_COMPAT & flags) {
  			err = __sys_sendmsg(sock, (struct msghdr __user *)compat_entry,
c71d8ebe7   Tetsuo Handa   net: Fix security...
1945
  					    &msg_sys, flags, &used_address);
228e548e6   Anton Blanchard   net: Add sendmmsg...
1946
1947
1948
1949
1950
1951
  			if (err < 0)
  				break;
  			err = __put_user(err, &compat_entry->msg_len);
  			++compat_entry;
  		} else {
  			err = __sys_sendmsg(sock, (struct msghdr __user *)entry,
c71d8ebe7   Tetsuo Handa   net: Fix security...
1952
  					    &msg_sys, flags, &used_address);
228e548e6   Anton Blanchard   net: Add sendmmsg...
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
  			if (err < 0)
  				break;
  			err = put_user(err, &entry->msg_len);
  			++entry;
  		}
  
  		if (err)
  			break;
  		++datagrams;
  	}
228e548e6   Anton Blanchard   net: Add sendmmsg...
1963
  	fput_light(sock->file, fput_needed);
728ffb86f   Anton Blanchard   net: sendmmsg sho...
1964
1965
  	/* We only return an error if no datagrams were able to be sent */
  	if (datagrams != 0)
228e548e6   Anton Blanchard   net: Add sendmmsg...
1966
  		return datagrams;
228e548e6   Anton Blanchard   net: Add sendmmsg...
1967
1968
1969
1970
1971
1972
1973
1974
  	return err;
  }
  
  SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
  		unsigned int, vlen, unsigned int, flags)
  {
  	return __sys_sendmmsg(fd, mmsg, vlen, flags);
  }
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
1975
1976
  static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
  			 struct msghdr *msg_sys, unsigned flags, int nosec)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1977
  {
89bddce58   Stephen Hemminger   [NET] socket: cod...
1978
1979
  	struct compat_msghdr __user *msg_compat =
  	    (struct compat_msghdr __user *)msg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1980
  	struct iovec iovstack[UIO_FASTIOV];
89bddce58   Stephen Hemminger   [NET] socket: cod...
1981
  	struct iovec *iov = iovstack;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1982
1983
1984
1985
  	unsigned long cmsg_ptr;
  	int err, iov_size, total_len, len;
  
  	/* kernel mode address */
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1986
  	struct sockaddr_storage addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1987
1988
1989
1990
  
  	/* user mode address pointers */
  	struct sockaddr __user *uaddr;
  	int __user *uaddr_len;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1991

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1992
  	if (MSG_CMSG_COMPAT & flags) {
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
1993
  		if (get_compat_msghdr(msg_sys, msg_compat))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1994
  			return -EFAULT;
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
1995
  	} else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr)))
89bddce58   Stephen Hemminger   [NET] socket: cod...
1996
  		return -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1997

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1998
  	err = -EMSGSIZE;
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
1999
2000
  	if (msg_sys->msg_iovlen > UIO_MAXIOV)
  		goto out;
89bddce58   Stephen Hemminger   [NET] socket: cod...
2001
2002
  
  	/* Check whether to allocate the iovec area */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2003
  	err = -ENOMEM;
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2004
2005
  	iov_size = msg_sys->msg_iovlen * sizeof(struct iovec);
  	if (msg_sys->msg_iovlen > UIO_FASTIOV) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2006
2007
  		iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
  		if (!iov)
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2008
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2009
2010
2011
  	}
  
  	/*
89bddce58   Stephen Hemminger   [NET] socket: cod...
2012
2013
  	 *      Save the user-mode address (verify_iovec will change the
  	 *      kernel msghdr to use the kernel address space)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2014
  	 */
89bddce58   Stephen Hemminger   [NET] socket: cod...
2015

a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2016
  	uaddr = (__force void __user *)msg_sys->msg_name;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2017
2018
  	uaddr_len = COMPAT_NAMELEN(msg);
  	if (MSG_CMSG_COMPAT & flags) {
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2019
  		err = verify_compat_iovec(msg_sys, iov,
230b18392   YOSHIFUJI Hideaki   net: Use standard...
2020
2021
  					  (struct sockaddr *)&addr,
  					  VERIFY_WRITE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2022
  	} else
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2023
  		err = verify_iovec(msg_sys, iov,
230b18392   YOSHIFUJI Hideaki   net: Use standard...
2024
2025
  				   (struct sockaddr *)&addr,
  				   VERIFY_WRITE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2026
2027
  	if (err < 0)
  		goto out_freeiov;
89bddce58   Stephen Hemminger   [NET] socket: cod...
2028
  	total_len = err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2029

a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2030
2031
  	cmsg_ptr = (unsigned long)msg_sys->msg_control;
  	msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
89bddce58   Stephen Hemminger   [NET] socket: cod...
2032

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2033
2034
  	if (sock->file->f_flags & O_NONBLOCK)
  		flags |= MSG_DONTWAIT;
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2035
2036
  	err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys,
  							  total_len, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2037
2038
2039
2040
2041
  	if (err < 0)
  		goto out_freeiov;
  	len = err;
  
  	if (uaddr != NULL) {
230b18392   YOSHIFUJI Hideaki   net: Use standard...
2042
  		err = move_addr_to_user((struct sockaddr *)&addr,
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2043
  					msg_sys->msg_namelen, uaddr,
89bddce58   Stephen Hemminger   [NET] socket: cod...
2044
  					uaddr_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2045
2046
2047
  		if (err < 0)
  			goto out_freeiov;
  	}
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2048
  	err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
37f7f421c   David S. Miller   [NET]: Do not lea...
2049
  			 COMPAT_FLAGS(msg));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2050
2051
2052
  	if (err)
  		goto out_freeiov;
  	if (MSG_CMSG_COMPAT & flags)
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2053
  		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2054
2055
  				 &msg_compat->msg_controllen);
  	else
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2056
  		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2057
2058
2059
2060
2061
2062
2063
2064
  				 &msg->msg_controllen);
  	if (err)
  		goto out_freeiov;
  	err = len;
  
  out_freeiov:
  	if (iov != iovstack)
  		sock_kfree_s(sock->sk, iov, iov_size);
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
  out:
  	return err;
  }
  
  /*
   *	BSD recvmsg interface
   */
  
  SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg,
  		unsigned int, flags)
  {
  	int fput_needed, err;
  	struct msghdr msg_sys;
  	struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed);
  
  	if (!sock)
  		goto out;
  
  	err = __sys_recvmsg(sock, msg, &msg_sys, flags, 0);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
2084
  	fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2085
2086
2087
  out:
  	return err;
  }
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
  /*
   *     Linux recvmmsg interface
   */
  
  int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
  		   unsigned int flags, struct timespec *timeout)
  {
  	int fput_needed, err, datagrams;
  	struct socket *sock;
  	struct mmsghdr __user *entry;
d7256d0eb   Jean-Mickael Guerin   net: compat_mmsgh...
2098
  	struct compat_mmsghdr __user *compat_entry;
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
  	struct msghdr msg_sys;
  	struct timespec end_time;
  
  	if (timeout &&
  	    poll_select_set_timeout(&end_time, timeout->tv_sec,
  				    timeout->tv_nsec))
  		return -EINVAL;
  
  	datagrams = 0;
  
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
  	if (!sock)
  		return err;
  
  	err = sock_error(sock->sk);
  	if (err)
  		goto out_put;
  
  	entry = mmsg;
d7256d0eb   Jean-Mickael Guerin   net: compat_mmsgh...
2118
  	compat_entry = (struct compat_mmsghdr __user *)mmsg;
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2119
2120
2121
2122
2123
  
  	while (datagrams < vlen) {
  		/*
  		 * No need to ask LSM for more than the first datagram.
  		 */
d7256d0eb   Jean-Mickael Guerin   net: compat_mmsgh...
2124
2125
  		if (MSG_CMSG_COMPAT & flags) {
  			err = __sys_recvmsg(sock, (struct msghdr __user *)compat_entry,
b9eb8b875   Anton Blanchard   net: recvmmsg: St...
2126
2127
  					    &msg_sys, flags & ~MSG_WAITFORONE,
  					    datagrams);
d7256d0eb   Jean-Mickael Guerin   net: compat_mmsgh...
2128
2129
2130
2131
2132
2133
  			if (err < 0)
  				break;
  			err = __put_user(err, &compat_entry->msg_len);
  			++compat_entry;
  		} else {
  			err = __sys_recvmsg(sock, (struct msghdr __user *)entry,
b9eb8b875   Anton Blanchard   net: recvmmsg: St...
2134
2135
  					    &msg_sys, flags & ~MSG_WAITFORONE,
  					    datagrams);
d7256d0eb   Jean-Mickael Guerin   net: compat_mmsgh...
2136
2137
2138
2139
2140
  			if (err < 0)
  				break;
  			err = put_user(err, &entry->msg_len);
  			++entry;
  		}
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2141
2142
  		if (err)
  			break;
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2143
  		++datagrams;
71c5c1595   Brandon L Black   net: Add MSG_WAIT...
2144
2145
2146
  		/* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
  		if (flags & MSG_WAITFORONE)
  			flags |= MSG_DONTWAIT;
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
  		if (timeout) {
  			ktime_get_ts(timeout);
  			*timeout = timespec_sub(end_time, *timeout);
  			if (timeout->tv_sec < 0) {
  				timeout->tv_sec = timeout->tv_nsec = 0;
  				break;
  			}
  
  			/* Timeout, return less than vlen datagrams */
  			if (timeout->tv_nsec == 0 && timeout->tv_sec == 0)
  				break;
  		}
  
  		/* Out of band data, return right away */
  		if (msg_sys.msg_flags & MSG_OOB)
  			break;
  	}
  
  out_put:
  	fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2167

a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
  	if (err == 0)
  		return datagrams;
  
  	if (datagrams != 0) {
  		/*
  		 * We may return less entries than requested (vlen) if the
  		 * sock is non block and there aren't enough datagrams...
  		 */
  		if (err != -EAGAIN) {
  			/*
  			 * ... or  if recvmsg returns an error after we
  			 * received some datagrams, where we record the
  			 * error to return on the next call or if the
  			 * app asks about it using getsockopt(SO_ERROR).
  			 */
  			sock->sk->sk_err = -err;
  		}
  
  		return datagrams;
  	}
  
  	return err;
  }
  
  SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
  		unsigned int, vlen, unsigned int, flags,
  		struct timespec __user *, timeout)
  {
  	int datagrams;
  	struct timespec timeout_sys;
  
  	if (!timeout)
  		return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL);
  
  	if (copy_from_user(&timeout_sys, timeout, sizeof(timeout_sys)))
  		return -EFAULT;
  
  	datagrams = __sys_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys);
  
  	if (datagrams > 0 &&
  	    copy_to_user(timeout, &timeout_sys, sizeof(timeout_sys)))
  		datagrams = -EFAULT;
  
  	return datagrams;
  }
  
  #ifdef __ARCH_WANT_SYS_SOCKETCALL
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2215
2216
  /* Argument list sizes for sys_socketcall */
  #define AL(x) ((x) * sizeof(unsigned long))
228e548e6   Anton Blanchard   net: Add sendmmsg...
2217
  static const unsigned char nargs[21] = {
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
2218
2219
2220
  	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...
2221
  	AL(4), AL(5), AL(4)
89bddce58   Stephen Hemminger   [NET] socket: cod...
2222
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2223
2224
2225
  #undef AL
  
  /*
89bddce58   Stephen Hemminger   [NET] socket: cod...
2226
   *	System call vectors.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2227
2228
2229
   *
   *	Argument checking cleaned up. Saved 20% in size.
   *  This function doesn't need to set the kernel lock because
89bddce58   Stephen Hemminger   [NET] socket: cod...
2230
   *  it is set by the callees.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2231
   */
3e0fa65f8   Heiko Carstens   [CVE-2009-0029] S...
2232
  SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2233
2234
  {
  	unsigned long a[6];
89bddce58   Stephen Hemminger   [NET] socket: cod...
2235
  	unsigned long a0, a1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2236
  	int err;
47379052b   Arjan van de Ven   net: Add explicit...
2237
  	unsigned int len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2238

228e548e6   Anton Blanchard   net: Add sendmmsg...
2239
  	if (call < 1 || call > SYS_SENDMMSG)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2240
  		return -EINVAL;
47379052b   Arjan van de Ven   net: Add explicit...
2241
2242
2243
  	len = nargs[call];
  	if (len > sizeof(a))
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2244
  	/* copy_from_user should be SMP safe. */
47379052b   Arjan van de Ven   net: Add explicit...
2245
  	if (copy_from_user(a, args, len))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2246
  		return -EFAULT;
3ec3b2fba   David Woodhouse   AUDIT: Capture sy...
2247

f3298dc4f   Al Viro   sanitize audit_so...
2248
  	audit_socketcall(nargs[call] / sizeof(unsigned long), a);
3ec3b2fba   David Woodhouse   AUDIT: Capture sy...
2249

89bddce58   Stephen Hemminger   [NET] socket: cod...
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
  	a0 = a[0];
  	a1 = a[1];
  
  	switch (call) {
  	case SYS_SOCKET:
  		err = sys_socket(a0, a1, a[2]);
  		break;
  	case SYS_BIND:
  		err = sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
  		break;
  	case SYS_CONNECT:
  		err = sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
  		break;
  	case SYS_LISTEN:
  		err = sys_listen(a0, a1);
  		break;
  	case SYS_ACCEPT:
de11defeb   Ulrich Drepper   reintroduce accept4
2267
2268
  		err = sys_accept4(a0, (struct sockaddr __user *)a1,
  				  (int __user *)a[2], 0);
89bddce58   Stephen Hemminger   [NET] socket: cod...
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
  		break;
  	case SYS_GETSOCKNAME:
  		err =
  		    sys_getsockname(a0, (struct sockaddr __user *)a1,
  				    (int __user *)a[2]);
  		break;
  	case SYS_GETPEERNAME:
  		err =
  		    sys_getpeername(a0, (struct sockaddr __user *)a1,
  				    (int __user *)a[2]);
  		break;
  	case SYS_SOCKETPAIR:
  		err = sys_socketpair(a0, a1, a[2], (int __user *)a[3]);
  		break;
  	case SYS_SEND:
  		err = sys_send(a0, (void __user *)a1, a[2], a[3]);
  		break;
  	case SYS_SENDTO:
  		err = sys_sendto(a0, (void __user *)a1, a[2], a[3],
  				 (struct sockaddr __user *)a[4], a[5]);
  		break;
  	case SYS_RECV:
  		err = sys_recv(a0, (void __user *)a1, a[2], a[3]);
  		break;
  	case SYS_RECVFROM:
  		err = sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
  				   (struct sockaddr __user *)a[4],
  				   (int __user *)a[5]);
  		break;
  	case SYS_SHUTDOWN:
  		err = sys_shutdown(a0, a1);
  		break;
  	case SYS_SETSOCKOPT:
  		err = sys_setsockopt(a0, a1, a[2], (char __user *)a[3], a[4]);
  		break;
  	case SYS_GETSOCKOPT:
  		err =
  		    sys_getsockopt(a0, a1, a[2], (char __user *)a[3],
  				   (int __user *)a[4]);
  		break;
  	case SYS_SENDMSG:
  		err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]);
  		break;
228e548e6   Anton Blanchard   net: Add sendmmsg...
2312
2313
2314
  	case SYS_SENDMMSG:
  		err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]);
  		break;
89bddce58   Stephen Hemminger   [NET] socket: cod...
2315
2316
2317
  	case SYS_RECVMSG:
  		err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]);
  		break;
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2318
2319
2320
2321
  	case SYS_RECVMMSG:
  		err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3],
  				   (struct timespec __user *)a[4]);
  		break;
de11defeb   Ulrich Drepper   reintroduce accept4
2322
2323
2324
  	case SYS_ACCEPT4:
  		err = sys_accept4(a0, (struct sockaddr __user *)a1,
  				  (int __user *)a[2], a[3]);
aaca0bdca   Ulrich Drepper   flag parameters: ...
2325
  		break;
89bddce58   Stephen Hemminger   [NET] socket: cod...
2326
2327
2328
  	default:
  		err = -EINVAL;
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2329
2330
2331
  	}
  	return err;
  }
89bddce58   Stephen Hemminger   [NET] socket: cod...
2332
  #endif				/* __ARCH_WANT_SYS_SOCKETCALL */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2333

55737fda0   Stephen Hemminger   [NET]: socket fam...
2334
2335
2336
2337
  /**
   *	sock_register - add a socket protocol handler
   *	@ops: description of protocol
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2338
2339
   *	This function is called by a protocol handler that wants to
   *	advertise its address family, and have it linked into the
55737fda0   Stephen Hemminger   [NET]: socket fam...
2340
2341
   *	socket interface. The value ops->family coresponds to the
   *	socket system call protocol family.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2342
   */
f0fd27d42   Stephen Hemminger   [NET]: sock_regis...
2343
  int sock_register(const struct net_proto_family *ops)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2344
2345
2346
2347
  {
  	int err;
  
  	if (ops->family >= NPROTO) {
89bddce58   Stephen Hemminger   [NET] socket: cod...
2348
2349
2350
  		printk(KERN_CRIT "protocol %d >= NPROTO(%d)
  ", ops->family,
  		       NPROTO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2351
2352
  		return -ENOBUFS;
  	}
55737fda0   Stephen Hemminger   [NET]: socket fam...
2353
2354
  
  	spin_lock(&net_family_lock);
190683a9d   Eric Dumazet   net: net_families...
2355
2356
  	if (rcu_dereference_protected(net_families[ops->family],
  				      lockdep_is_held(&net_family_lock)))
55737fda0   Stephen Hemminger   [NET]: socket fam...
2357
2358
  		err = -EEXIST;
  	else {
cf778b00e   Eric Dumazet   net: reintroduce ...
2359
  		rcu_assign_pointer(net_families[ops->family], ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2360
2361
  		err = 0;
  	}
55737fda0   Stephen Hemminger   [NET]: socket fam...
2362
  	spin_unlock(&net_family_lock);
89bddce58   Stephen Hemminger   [NET] socket: cod...
2363
2364
  	printk(KERN_INFO "NET: Registered protocol family %d
  ", ops->family);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2365
2366
  	return err;
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
2367
  EXPORT_SYMBOL(sock_register);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2368

55737fda0   Stephen Hemminger   [NET]: socket fam...
2369
2370
2371
2372
  /**
   *	sock_unregister - remove a protocol handler
   *	@family: protocol family to remove
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2373
2374
   *	This function is called by a protocol handler that wants to
   *	remove its address family, and have it unlinked from the
55737fda0   Stephen Hemminger   [NET]: socket fam...
2375
2376
2377
2378
2379
2380
   *	new socket creation.
   *
   *	If protocol handler is a module, then it can use module reference
   *	counts to protect against new references. If protocol handler is not
   *	a module then it needs to provide its own protection in
   *	the ops->create routine.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2381
   */
f0fd27d42   Stephen Hemminger   [NET]: sock_regis...
2382
  void sock_unregister(int family)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2383
  {
f0fd27d42   Stephen Hemminger   [NET]: sock_regis...
2384
  	BUG_ON(family < 0 || family >= NPROTO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2385

55737fda0   Stephen Hemminger   [NET]: socket fam...
2386
  	spin_lock(&net_family_lock);
a9b3cd7f3   Stephen Hemminger   rcu: convert uses...
2387
  	RCU_INIT_POINTER(net_families[family], NULL);
55737fda0   Stephen Hemminger   [NET]: socket fam...
2388
2389
2390
  	spin_unlock(&net_family_lock);
  
  	synchronize_rcu();
89bddce58   Stephen Hemminger   [NET] socket: cod...
2391
2392
  	printk(KERN_INFO "NET: Unregistered protocol family %d
  ", family);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2393
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
2394
  EXPORT_SYMBOL(sock_unregister);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2395

77d76ea31   Andi Kleen   [NET]: Small clea...
2396
  static int __init sock_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2397
  {
b3e19d924   Nick Piggin   fs: scale mntget/...
2398
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2399
  	/*
89bddce58   Stephen Hemminger   [NET] socket: cod...
2400
  	 *      Initialize sock SLAB cache.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2401
  	 */
89bddce58   Stephen Hemminger   [NET] socket: cod...
2402

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2403
  	sk_init();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2404
  	/*
89bddce58   Stephen Hemminger   [NET] socket: cod...
2405
  	 *      Initialize skbuff SLAB cache
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2406
2407
  	 */
  	skb_init();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2408
2409
  
  	/*
89bddce58   Stephen Hemminger   [NET] socket: cod...
2410
  	 *      Initialize the protocols module.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2411
2412
2413
  	 */
  
  	init_inodecache();
b3e19d924   Nick Piggin   fs: scale mntget/...
2414
2415
2416
2417
  
  	err = register_filesystem(&sock_fs_type);
  	if (err)
  		goto out_fs;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2418
  	sock_mnt = kern_mount(&sock_fs_type);
b3e19d924   Nick Piggin   fs: scale mntget/...
2419
2420
2421
2422
  	if (IS_ERR(sock_mnt)) {
  		err = PTR_ERR(sock_mnt);
  		goto out_mount;
  	}
77d76ea31   Andi Kleen   [NET]: Small clea...
2423
2424
  
  	/* The real protocol initialization is performed in later initcalls.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2425
2426
2427
2428
2429
  	 */
  
  #ifdef CONFIG_NETFILTER
  	netfilter_init();
  #endif
cbeb321a6   David S. Miller   [NET]: Fix sock_i...
2430

c1f19b51d   Richard Cochran   net: support time...
2431
2432
2433
  #ifdef CONFIG_NETWORK_PHY_TIMESTAMPING
  	skb_timestamping_init();
  #endif
b3e19d924   Nick Piggin   fs: scale mntget/...
2434
2435
2436
2437
2438
2439
2440
  out:
  	return err;
  
  out_mount:
  	unregister_filesystem(&sock_fs_type);
  out_fs:
  	goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2441
  }
77d76ea31   Andi Kleen   [NET]: Small clea...
2442
  core_initcall(sock_init);	/* early initcall */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2443
2444
2445
2446
2447
  #ifdef CONFIG_PROC_FS
  void socket_seq_show(struct seq_file *seq)
  {
  	int cpu;
  	int counter = 0;
6f9120422   KAMEZAWA Hiroyuki   [PATCH] for_each_...
2448
  	for_each_possible_cpu(cpu)
89bddce58   Stephen Hemminger   [NET] socket: cod...
2449
  	    counter += per_cpu(sockets_in_use, cpu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2450
2451
2452
2453
2454
2455
2456
2457
  
  	/* It can be negative, by the way. 8) */
  	if (counter < 0)
  		counter = 0;
  
  	seq_printf(seq, "sockets: used %d
  ", counter);
  }
89bddce58   Stephen Hemminger   [NET] socket: cod...
2458
  #endif				/* CONFIG_PROC_FS */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2459

89bbfc95d   Shaun Pereira   [NET]: allow 32 b...
2460
  #ifdef CONFIG_COMPAT
6b96018b2   Arnd Bergmann   compat: move sock...
2461
2462
  static int do_siocgstamp(struct net *net, struct socket *sock,
  			 unsigned int cmd, struct compat_timeval __user *up)
7a229387d   Arnd Bergmann   net: copy socket ...
2463
  {
7a229387d   Arnd Bergmann   net: copy socket ...
2464
2465
2466
2467
2468
  	mm_segment_t old_fs = get_fs();
  	struct timeval ktv;
  	int err;
  
  	set_fs(KERNEL_DS);
6b96018b2   Arnd Bergmann   compat: move sock...
2469
  	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv);
7a229387d   Arnd Bergmann   net: copy socket ...
2470
2471
2472
2473
2474
2475
2476
  	set_fs(old_fs);
  	if (!err) {
  		err = put_user(ktv.tv_sec, &up->tv_sec);
  		err |= __put_user(ktv.tv_usec, &up->tv_usec);
  	}
  	return err;
  }
6b96018b2   Arnd Bergmann   compat: move sock...
2477
2478
  static int do_siocgstampns(struct net *net, struct socket *sock,
  			 unsigned int cmd, struct compat_timespec __user *up)
7a229387d   Arnd Bergmann   net: copy socket ...
2479
  {
7a229387d   Arnd Bergmann   net: copy socket ...
2480
2481
2482
2483
2484
  	mm_segment_t old_fs = get_fs();
  	struct timespec kts;
  	int err;
  
  	set_fs(KERNEL_DS);
6b96018b2   Arnd Bergmann   compat: move sock...
2485
  	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts);
7a229387d   Arnd Bergmann   net: copy socket ...
2486
2487
2488
2489
2490
2491
2492
  	set_fs(old_fs);
  	if (!err) {
  		err = put_user(kts.tv_sec, &up->tv_sec);
  		err |= __put_user(kts.tv_nsec, &up->tv_nsec);
  	}
  	return err;
  }
6b96018b2   Arnd Bergmann   compat: move sock...
2493
  static int dev_ifname32(struct net *net, struct compat_ifreq __user *uifr32)
7a229387d   Arnd Bergmann   net: copy socket ...
2494
2495
2496
2497
2498
  {
  	struct ifreq __user *uifr;
  	int err;
  
  	uifr = compat_alloc_user_space(sizeof(struct ifreq));
6b96018b2   Arnd Bergmann   compat: move sock...
2499
  	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
7a229387d   Arnd Bergmann   net: copy socket ...
2500
  		return -EFAULT;
6b96018b2   Arnd Bergmann   compat: move sock...
2501
  	err = dev_ioctl(net, SIOCGIFNAME, uifr);
7a229387d   Arnd Bergmann   net: copy socket ...
2502
2503
  	if (err)
  		return err;
6b96018b2   Arnd Bergmann   compat: move sock...
2504
  	if (copy_in_user(uifr32, uifr, sizeof(struct compat_ifreq)))
7a229387d   Arnd Bergmann   net: copy socket ...
2505
2506
2507
2508
  		return -EFAULT;
  
  	return 0;
  }
6b96018b2   Arnd Bergmann   compat: move sock...
2509
  static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32)
7a229387d   Arnd Bergmann   net: copy socket ...
2510
  {
6b96018b2   Arnd Bergmann   compat: move sock...
2511
  	struct compat_ifconf ifc32;
7a229387d   Arnd Bergmann   net: copy socket ...
2512
2513
  	struct ifconf ifc;
  	struct ifconf __user *uifc;
6b96018b2   Arnd Bergmann   compat: move sock...
2514
  	struct compat_ifreq __user *ifr32;
7a229387d   Arnd Bergmann   net: copy socket ...
2515
2516
2517
  	struct ifreq __user *ifr;
  	unsigned int i, j;
  	int err;
6b96018b2   Arnd Bergmann   compat: move sock...
2518
  	if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf)))
7a229387d   Arnd Bergmann   net: copy socket ...
2519
2520
2521
2522
2523
2524
2525
2526
  		return -EFAULT;
  
  	if (ifc32.ifcbuf == 0) {
  		ifc32.ifc_len = 0;
  		ifc.ifc_len = 0;
  		ifc.ifc_req = NULL;
  		uifc = compat_alloc_user_space(sizeof(struct ifconf));
  	} else {
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
2527
2528
  		size_t len = ((ifc32.ifc_len / sizeof(struct compat_ifreq)) + 1) *
  			sizeof(struct ifreq);
7a229387d   Arnd Bergmann   net: copy socket ...
2529
2530
2531
2532
  		uifc = compat_alloc_user_space(sizeof(struct ifconf) + len);
  		ifc.ifc_len = len;
  		ifr = ifc.ifc_req = (void __user *)(uifc + 1);
  		ifr32 = compat_ptr(ifc32.ifcbuf);
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
2533
  		for (i = 0; i < ifc32.ifc_len; i += sizeof(struct compat_ifreq)) {
6b96018b2   Arnd Bergmann   compat: move sock...
2534
  			if (copy_in_user(ifr, ifr32, sizeof(struct compat_ifreq)))
7a229387d   Arnd Bergmann   net: copy socket ...
2535
2536
2537
2538
2539
2540
2541
  				return -EFAULT;
  			ifr++;
  			ifr32++;
  		}
  	}
  	if (copy_to_user(uifc, &ifc, sizeof(struct ifconf)))
  		return -EFAULT;
6b96018b2   Arnd Bergmann   compat: move sock...
2542
  	err = dev_ioctl(net, SIOCGIFCONF, uifc);
7a229387d   Arnd Bergmann   net: copy socket ...
2543
2544
2545
2546
2547
2548
2549
2550
2551
  	if (err)
  		return err;
  
  	if (copy_from_user(&ifc, uifc, sizeof(struct ifconf)))
  		return -EFAULT;
  
  	ifr = ifc.ifc_req;
  	ifr32 = compat_ptr(ifc32.ifcbuf);
  	for (i = 0, j = 0;
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
2552
2553
2554
  	     i + sizeof(struct compat_ifreq) <= ifc32.ifc_len && j < ifc.ifc_len;
  	     i += sizeof(struct compat_ifreq), j += sizeof(struct ifreq)) {
  		if (copy_in_user(ifr32, ifr, sizeof(struct compat_ifreq)))
7a229387d   Arnd Bergmann   net: copy socket ...
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
  			return -EFAULT;
  		ifr32++;
  		ifr++;
  	}
  
  	if (ifc32.ifcbuf == 0) {
  		/* Translate from 64-bit structure multiple to
  		 * a 32-bit one.
  		 */
  		i = ifc.ifc_len;
6b96018b2   Arnd Bergmann   compat: move sock...
2565
  		i = ((i / sizeof(struct ifreq)) * sizeof(struct compat_ifreq));
7a229387d   Arnd Bergmann   net: copy socket ...
2566
2567
2568
2569
  		ifc32.ifc_len = i;
  	} else {
  		ifc32.ifc_len = i;
  	}
6b96018b2   Arnd Bergmann   compat: move sock...
2570
  	if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf)))
7a229387d   Arnd Bergmann   net: copy socket ...
2571
2572
2573
2574
  		return -EFAULT;
  
  	return 0;
  }
6b96018b2   Arnd Bergmann   compat: move sock...
2575
  static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
7a229387d   Arnd Bergmann   net: copy socket ...
2576
  {
3a7da39d1   Ben Hutchings   ethtool: Compat h...
2577
2578
2579
2580
  	struct compat_ethtool_rxnfc __user *compat_rxnfc;
  	bool convert_in = false, convert_out = false;
  	size_t buf_size = ALIGN(sizeof(struct ifreq), 8);
  	struct ethtool_rxnfc __user *rxnfc;
7a229387d   Arnd Bergmann   net: copy socket ...
2581
  	struct ifreq __user *ifr;
3a7da39d1   Ben Hutchings   ethtool: Compat h...
2582
2583
  	u32 rule_cnt = 0, actual_rule_cnt;
  	u32 ethcmd;
7a229387d   Arnd Bergmann   net: copy socket ...
2584
  	u32 data;
3a7da39d1   Ben Hutchings   ethtool: Compat h...
2585
  	int ret;
7a229387d   Arnd Bergmann   net: copy socket ...
2586

3a7da39d1   Ben Hutchings   ethtool: Compat h...
2587
2588
  	if (get_user(data, &ifr32->ifr_ifru.ifru_data))
  		return -EFAULT;
7a229387d   Arnd Bergmann   net: copy socket ...
2589

3a7da39d1   Ben Hutchings   ethtool: Compat h...
2590
2591
2592
  	compat_rxnfc = compat_ptr(data);
  
  	if (get_user(ethcmd, &compat_rxnfc->cmd))
7a229387d   Arnd Bergmann   net: copy socket ...
2593
  		return -EFAULT;
3a7da39d1   Ben Hutchings   ethtool: Compat h...
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
  	/* Most ethtool structures are defined without padding.
  	 * Unfortunately struct ethtool_rxnfc is an exception.
  	 */
  	switch (ethcmd) {
  	default:
  		break;
  	case ETHTOOL_GRXCLSRLALL:
  		/* Buffer size is variable */
  		if (get_user(rule_cnt, &compat_rxnfc->rule_cnt))
  			return -EFAULT;
  		if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32))
  			return -ENOMEM;
  		buf_size += rule_cnt * sizeof(u32);
  		/* fall through */
  	case ETHTOOL_GRXRINGS:
  	case ETHTOOL_GRXCLSRLCNT:
  	case ETHTOOL_GRXCLSRULE:
55664f324   Ben Hutchings   ethtool: Allow dr...
2611
  	case ETHTOOL_SRXCLSRLINS:
3a7da39d1   Ben Hutchings   ethtool: Compat h...
2612
2613
2614
  		convert_out = true;
  		/* fall through */
  	case ETHTOOL_SRXCLSRLDEL:
3a7da39d1   Ben Hutchings   ethtool: Compat h...
2615
2616
2617
2618
2619
2620
2621
2622
2623
  		buf_size += sizeof(struct ethtool_rxnfc);
  		convert_in = true;
  		break;
  	}
  
  	ifr = compat_alloc_user_space(buf_size);
  	rxnfc = (void *)ifr + ALIGN(sizeof(struct ifreq), 8);
  
  	if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
7a229387d   Arnd Bergmann   net: copy socket ...
2624
  		return -EFAULT;
3a7da39d1   Ben Hutchings   ethtool: Compat h...
2625
2626
  	if (put_user(convert_in ? rxnfc : compat_ptr(data),
  		     &ifr->ifr_ifru.ifru_data))
7a229387d   Arnd Bergmann   net: copy socket ...
2627
  		return -EFAULT;
3a7da39d1   Ben Hutchings   ethtool: Compat h...
2628
  	if (convert_in) {
127fe533a   Alexander Duyck   v3 ethtool: add n...
2629
  		/* We expect there to be holes between fs.m_ext and
3a7da39d1   Ben Hutchings   ethtool: Compat h...
2630
2631
  		 * fs.ring_cookie and at the end of fs, but nowhere else.
  		 */
127fe533a   Alexander Duyck   v3 ethtool: add n...
2632
2633
2634
2635
  		BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_ext) +
  			     sizeof(compat_rxnfc->fs.m_ext) !=
  			     offsetof(struct ethtool_rxnfc, fs.m_ext) +
  			     sizeof(rxnfc->fs.m_ext));
3a7da39d1   Ben Hutchings   ethtool: Compat h...
2636
2637
2638
2639
2640
2641
2642
  		BUILD_BUG_ON(
  			offsetof(struct compat_ethtool_rxnfc, fs.location) -
  			offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) !=
  			offsetof(struct ethtool_rxnfc, fs.location) -
  			offsetof(struct ethtool_rxnfc, fs.ring_cookie));
  
  		if (copy_in_user(rxnfc, compat_rxnfc,
127fe533a   Alexander Duyck   v3 ethtool: add n...
2643
  				 (void *)(&rxnfc->fs.m_ext + 1) -
3a7da39d1   Ben Hutchings   ethtool: Compat h...
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
  				 (void *)rxnfc) ||
  		    copy_in_user(&rxnfc->fs.ring_cookie,
  				 &compat_rxnfc->fs.ring_cookie,
  				 (void *)(&rxnfc->fs.location + 1) -
  				 (void *)&rxnfc->fs.ring_cookie) ||
  		    copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt,
  				 sizeof(rxnfc->rule_cnt)))
  			return -EFAULT;
  	}
  
  	ret = dev_ioctl(net, SIOCETHTOOL, ifr);
  	if (ret)
  		return ret;
  
  	if (convert_out) {
  		if (copy_in_user(compat_rxnfc, rxnfc,
127fe533a   Alexander Duyck   v3 ethtool: add n...
2660
  				 (const void *)(&rxnfc->fs.m_ext + 1) -
3a7da39d1   Ben Hutchings   ethtool: Compat h...
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
  				 (const void *)rxnfc) ||
  		    copy_in_user(&compat_rxnfc->fs.ring_cookie,
  				 &rxnfc->fs.ring_cookie,
  				 (const void *)(&rxnfc->fs.location + 1) -
  				 (const void *)&rxnfc->fs.ring_cookie) ||
  		    copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt,
  				 sizeof(rxnfc->rule_cnt)))
  			return -EFAULT;
  
  		if (ethcmd == ETHTOOL_GRXCLSRLALL) {
  			/* As an optimisation, we only copy the actual
  			 * number of rules that the underlying
  			 * function returned.  Since Mallory might
  			 * change the rule count in user memory, we
  			 * check that it is less than the rule count
  			 * originally given (as the user buffer size),
  			 * which has been range-checked.
  			 */
  			if (get_user(actual_rule_cnt, &rxnfc->rule_cnt))
  				return -EFAULT;
  			if (actual_rule_cnt < rule_cnt)
  				rule_cnt = actual_rule_cnt;
  			if (copy_in_user(&compat_rxnfc->rule_locs[0],
  					 &rxnfc->rule_locs[0],
  					 rule_cnt * sizeof(u32)))
  				return -EFAULT;
  		}
  	}
  
  	return 0;
7a229387d   Arnd Bergmann   net: copy socket ...
2691
  }
7a50a240c   Arnd Bergmann   net/compat_ioctl:...
2692
2693
2694
2695
2696
  static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32)
  {
  	void __user *uptr;
  	compat_uptr_t uptr32;
  	struct ifreq __user *uifr;
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
2697
  	uifr = compat_alloc_user_space(sizeof(*uifr));
7a50a240c   Arnd Bergmann   net/compat_ioctl:...
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
  	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
  		return -EFAULT;
  
  	if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu))
  		return -EFAULT;
  
  	uptr = compat_ptr(uptr32);
  
  	if (put_user(uptr, &uifr->ifr_settings.ifs_ifsu.raw_hdlc))
  		return -EFAULT;
  
  	return dev_ioctl(net, SIOCWANDEV, uifr);
  }
6b96018b2   Arnd Bergmann   compat: move sock...
2711
2712
  static int bond_ioctl(struct net *net, unsigned int cmd,
  			 struct compat_ifreq __user *ifr32)
7a229387d   Arnd Bergmann   net: copy socket ...
2713
2714
2715
  {
  	struct ifreq kifr;
  	struct ifreq __user *uifr;
7a229387d   Arnd Bergmann   net: copy socket ...
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
  	mm_segment_t old_fs;
  	int err;
  	u32 data;
  	void __user *datap;
  
  	switch (cmd) {
  	case SIOCBONDENSLAVE:
  	case SIOCBONDRELEASE:
  	case SIOCBONDSETHWADDR:
  	case SIOCBONDCHANGEACTIVE:
6b96018b2   Arnd Bergmann   compat: move sock...
2726
  		if (copy_from_user(&kifr, ifr32, sizeof(struct compat_ifreq)))
7a229387d   Arnd Bergmann   net: copy socket ...
2727
2728
2729
  			return -EFAULT;
  
  		old_fs = get_fs();
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
2730
  		set_fs(KERNEL_DS);
c3f52ae6a   stephen hemminger   socket: suppress ...
2731
2732
  		err = dev_ioctl(net, cmd,
  				(struct ifreq __user __force *) &kifr);
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
2733
  		set_fs(old_fs);
7a229387d   Arnd Bergmann   net: copy socket ...
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
  
  		return err;
  	case SIOCBONDSLAVEINFOQUERY:
  	case SIOCBONDINFOQUERY:
  		uifr = compat_alloc_user_space(sizeof(*uifr));
  		if (copy_in_user(&uifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
  			return -EFAULT;
  
  		if (get_user(data, &ifr32->ifr_ifru.ifru_data))
  			return -EFAULT;
  
  		datap = compat_ptr(data);
  		if (put_user(datap, &uifr->ifr_ifru.ifru_data))
  			return -EFAULT;
6b96018b2   Arnd Bergmann   compat: move sock...
2748
  		return dev_ioctl(net, cmd, uifr);
7a229387d   Arnd Bergmann   net: copy socket ...
2749
  	default:
07d106d0a   Linus Torvalds   vfs: fix up ENOIO...
2750
  		return -ENOIOCTLCMD;
ccbd6a5a4   Joe Perches   net: Remove unnec...
2751
  	}
7a229387d   Arnd Bergmann   net: copy socket ...
2752
  }
6b96018b2   Arnd Bergmann   compat: move sock...
2753
2754
  static int siocdevprivate_ioctl(struct net *net, unsigned int cmd,
  				 struct compat_ifreq __user *u_ifreq32)
7a229387d   Arnd Bergmann   net: copy socket ...
2755
2756
  {
  	struct ifreq __user *u_ifreq64;
7a229387d   Arnd Bergmann   net: copy socket ...
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
  	char tmp_buf[IFNAMSIZ];
  	void __user *data64;
  	u32 data32;
  
  	if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]),
  			   IFNAMSIZ))
  		return -EFAULT;
  	if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data))
  		return -EFAULT;
  	data64 = compat_ptr(data32);
  
  	u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
  
  	/* Don't check these user accesses, just let that get trapped
  	 * in the ioctl handler instead.
  	 */
  	if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0],
  			 IFNAMSIZ))
  		return -EFAULT;
  	if (__put_user(data64, &u_ifreq64->ifr_ifru.ifru_data))
  		return -EFAULT;
6b96018b2   Arnd Bergmann   compat: move sock...
2778
  	return dev_ioctl(net, cmd, u_ifreq64);
7a229387d   Arnd Bergmann   net: copy socket ...
2779
  }
6b96018b2   Arnd Bergmann   compat: move sock...
2780
2781
  static int dev_ifsioc(struct net *net, struct socket *sock,
  			 unsigned int cmd, struct compat_ifreq __user *uifr32)
7a229387d   Arnd Bergmann   net: copy socket ...
2782
  {
a2116ed22   Arnd Bergmann   net/compat: fix d...
2783
  	struct ifreq __user *uifr;
7a229387d   Arnd Bergmann   net: copy socket ...
2784
  	int err;
a2116ed22   Arnd Bergmann   net/compat: fix d...
2785
2786
2787
2788
2789
  	uifr = compat_alloc_user_space(sizeof(*uifr));
  	if (copy_in_user(uifr, uifr32, sizeof(*uifr32)))
  		return -EFAULT;
  
  	err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr);
7a229387d   Arnd Bergmann   net: copy socket ...
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
  	if (!err) {
  		switch (cmd) {
  		case SIOCGIFFLAGS:
  		case SIOCGIFMETRIC:
  		case SIOCGIFMTU:
  		case SIOCGIFMEM:
  		case SIOCGIFHWADDR:
  		case SIOCGIFINDEX:
  		case SIOCGIFADDR:
  		case SIOCGIFBRDADDR:
  		case SIOCGIFDSTADDR:
  		case SIOCGIFNETMASK:
fab2532ba   Arnd Bergmann   net, compat_ioctl...
2802
  		case SIOCGIFPFLAGS:
7a229387d   Arnd Bergmann   net: copy socket ...
2803
  		case SIOCGIFTXQLEN:
fab2532ba   Arnd Bergmann   net, compat_ioctl...
2804
2805
  		case SIOCGMIIPHY:
  		case SIOCGMIIREG:
a2116ed22   Arnd Bergmann   net/compat: fix d...
2806
  			if (copy_in_user(uifr32, uifr, sizeof(*uifr32)))
7a229387d   Arnd Bergmann   net: copy socket ...
2807
2808
2809
2810
2811
2812
  				err = -EFAULT;
  			break;
  		}
  	}
  	return err;
  }
a2116ed22   Arnd Bergmann   net/compat: fix d...
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
  static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
  			struct compat_ifreq __user *uifr32)
  {
  	struct ifreq ifr;
  	struct compat_ifmap __user *uifmap32;
  	mm_segment_t old_fs;
  	int err;
  
  	uifmap32 = &uifr32->ifr_ifru.ifru_map;
  	err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name));
  	err |= __get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
  	err |= __get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
  	err |= __get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
  	err |= __get_user(ifr.ifr_map.irq, &uifmap32->irq);
  	err |= __get_user(ifr.ifr_map.dma, &uifmap32->dma);
  	err |= __get_user(ifr.ifr_map.port, &uifmap32->port);
  	if (err)
  		return -EFAULT;
  
  	old_fs = get_fs();
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
2833
  	set_fs(KERNEL_DS);
c3f52ae6a   stephen hemminger   socket: suppress ...
2834
  	err = dev_ioctl(net, cmd, (void  __user __force *)&ifr);
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
2835
  	set_fs(old_fs);
a2116ed22   Arnd Bergmann   net/compat: fix d...
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
  
  	if (cmd == SIOCGIFMAP && !err) {
  		err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name));
  		err |= __put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
  		err |= __put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
  		err |= __put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
  		err |= __put_user(ifr.ifr_map.irq, &uifmap32->irq);
  		err |= __put_user(ifr.ifr_map.dma, &uifmap32->dma);
  		err |= __put_user(ifr.ifr_map.port, &uifmap32->port);
  		if (err)
  			err = -EFAULT;
  	}
  	return err;
  }
  
  static int compat_siocshwtstamp(struct net *net, struct compat_ifreq __user *uifr32)
  {
  	void __user *uptr;
  	compat_uptr_t uptr32;
  	struct ifreq __user *uifr;
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
2856
  	uifr = compat_alloc_user_space(sizeof(*uifr));
a2116ed22   Arnd Bergmann   net/compat: fix d...
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
  	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
  		return -EFAULT;
  
  	if (get_user(uptr32, &uifr32->ifr_data))
  		return -EFAULT;
  
  	uptr = compat_ptr(uptr32);
  
  	if (put_user(uptr, &uifr->ifr_data))
  		return -EFAULT;
  
  	return dev_ioctl(net, SIOCSHWTSTAMP, uifr);
  }
7a229387d   Arnd Bergmann   net: copy socket ...
2870
  struct rtentry32 {
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
2871
  	u32		rt_pad1;
7a229387d   Arnd Bergmann   net: copy socket ...
2872
2873
2874
  	struct sockaddr rt_dst;         /* target address               */
  	struct sockaddr rt_gateway;     /* gateway addr (RTF_GATEWAY)   */
  	struct sockaddr rt_genmask;     /* target network mask (IP)     */
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
2875
2876
2877
2878
2879
2880
2881
  	unsigned short	rt_flags;
  	short		rt_pad2;
  	u32		rt_pad3;
  	unsigned char	rt_tos;
  	unsigned char	rt_class;
  	short		rt_pad4;
  	short		rt_metric;      /* +1 for binary compatibility! */
7a229387d   Arnd Bergmann   net: copy socket ...
2882
  	/* char * */ u32 rt_dev;        /* forcing the device at add    */
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
2883
2884
  	u32		rt_mtu;         /* per route MTU/Window         */
  	u32		rt_window;      /* Window clamping              */
7a229387d   Arnd Bergmann   net: copy socket ...
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
  	unsigned short  rt_irtt;        /* Initial RTT                  */
  };
  
  struct in6_rtmsg32 {
  	struct in6_addr		rtmsg_dst;
  	struct in6_addr		rtmsg_src;
  	struct in6_addr		rtmsg_gateway;
  	u32			rtmsg_type;
  	u16			rtmsg_dst_len;
  	u16			rtmsg_src_len;
  	u32			rtmsg_metric;
  	u32			rtmsg_info;
  	u32			rtmsg_flags;
  	s32			rtmsg_ifindex;
  };
6b96018b2   Arnd Bergmann   compat: move sock...
2900
2901
  static int routing_ioctl(struct net *net, struct socket *sock,
  			 unsigned int cmd, void __user *argp)
7a229387d   Arnd Bergmann   net: copy socket ...
2902
2903
2904
2905
2906
2907
2908
2909
  {
  	int ret;
  	void *r = NULL;
  	struct in6_rtmsg r6;
  	struct rtentry r4;
  	char devname[16];
  	u32 rtdev;
  	mm_segment_t old_fs = get_fs();
6b96018b2   Arnd Bergmann   compat: move sock...
2910
2911
  	if (sock && sock->sk && sock->sk->sk_family == AF_INET6) { /* ipv6 */
  		struct in6_rtmsg32 __user *ur6 = argp;
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
2912
  		ret = copy_from_user(&r6.rtmsg_dst, &(ur6->rtmsg_dst),
7a229387d   Arnd Bergmann   net: copy socket ...
2913
  			3 * sizeof(struct in6_addr));
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
2914
2915
2916
2917
2918
2919
2920
  		ret |= __get_user(r6.rtmsg_type, &(ur6->rtmsg_type));
  		ret |= __get_user(r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len));
  		ret |= __get_user(r6.rtmsg_src_len, &(ur6->rtmsg_src_len));
  		ret |= __get_user(r6.rtmsg_metric, &(ur6->rtmsg_metric));
  		ret |= __get_user(r6.rtmsg_info, &(ur6->rtmsg_info));
  		ret |= __get_user(r6.rtmsg_flags, &(ur6->rtmsg_flags));
  		ret |= __get_user(r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex));
7a229387d   Arnd Bergmann   net: copy socket ...
2921
2922
2923
  
  		r = (void *) &r6;
  	} else { /* ipv4 */
6b96018b2   Arnd Bergmann   compat: move sock...
2924
  		struct rtentry32 __user *ur4 = argp;
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
2925
  		ret = copy_from_user(&r4.rt_dst, &(ur4->rt_dst),
7a229387d   Arnd Bergmann   net: copy socket ...
2926
  					3 * sizeof(struct sockaddr));
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
2927
2928
2929
2930
2931
2932
  		ret |= __get_user(r4.rt_flags, &(ur4->rt_flags));
  		ret |= __get_user(r4.rt_metric, &(ur4->rt_metric));
  		ret |= __get_user(r4.rt_mtu, &(ur4->rt_mtu));
  		ret |= __get_user(r4.rt_window, &(ur4->rt_window));
  		ret |= __get_user(r4.rt_irtt, &(ur4->rt_irtt));
  		ret |= __get_user(rtdev, &(ur4->rt_dev));
7a229387d   Arnd Bergmann   net: copy socket ...
2933
  		if (rtdev) {
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
2934
  			ret |= copy_from_user(devname, compat_ptr(rtdev), 15);
c3f52ae6a   stephen hemminger   socket: suppress ...
2935
2936
  			r4.rt_dev = (char __user __force *)devname;
  			devname[15] = 0;
7a229387d   Arnd Bergmann   net: copy socket ...
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
  		} else
  			r4.rt_dev = NULL;
  
  		r = (void *) &r4;
  	}
  
  	if (ret) {
  		ret = -EFAULT;
  		goto out;
  	}
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
2947
  	set_fs(KERNEL_DS);
6b96018b2   Arnd Bergmann   compat: move sock...
2948
  	ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r);
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
2949
  	set_fs(old_fs);
7a229387d   Arnd Bergmann   net: copy socket ...
2950
2951
  
  out:
7a229387d   Arnd Bergmann   net: copy socket ...
2952
2953
2954
2955
2956
  	return ret;
  }
  
  /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE
   * for some operations; this forces use of the newer bridge-utils that
25985edce   Lucas De Marchi   Fix common misspe...
2957
   * use compatible ioctls
7a229387d   Arnd Bergmann   net: copy socket ...
2958
   */
6b96018b2   Arnd Bergmann   compat: move sock...
2959
  static int old_bridge_ioctl(compat_ulong_t __user *argp)
7a229387d   Arnd Bergmann   net: copy socket ...
2960
  {
6b96018b2   Arnd Bergmann   compat: move sock...
2961
  	compat_ulong_t tmp;
7a229387d   Arnd Bergmann   net: copy socket ...
2962

6b96018b2   Arnd Bergmann   compat: move sock...
2963
  	if (get_user(tmp, argp))
7a229387d   Arnd Bergmann   net: copy socket ...
2964
2965
2966
2967
2968
  		return -EFAULT;
  	if (tmp == BRCTL_GET_VERSION)
  		return BRCTL_VERSION + 1;
  	return -EINVAL;
  }
6b96018b2   Arnd Bergmann   compat: move sock...
2969
2970
2971
2972
2973
2974
  static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
  			 unsigned int cmd, unsigned long arg)
  {
  	void __user *argp = compat_ptr(arg);
  	struct sock *sk = sock->sk;
  	struct net *net = sock_net(sk);
7a229387d   Arnd Bergmann   net: copy socket ...
2975

6b96018b2   Arnd Bergmann   compat: move sock...
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
  	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
  		return siocdevprivate_ioctl(net, cmd, argp);
  
  	switch (cmd) {
  	case SIOCSIFBR:
  	case SIOCGIFBR:
  		return old_bridge_ioctl(argp);
  	case SIOCGIFNAME:
  		return dev_ifname32(net, argp);
  	case SIOCGIFCONF:
  		return dev_ifconf(net, argp);
  	case SIOCETHTOOL:
  		return ethtool_ioctl(net, argp);
7a50a240c   Arnd Bergmann   net/compat_ioctl:...
2989
2990
  	case SIOCWANDEV:
  		return compat_siocwandev(net, argp);
a2116ed22   Arnd Bergmann   net/compat: fix d...
2991
2992
2993
  	case SIOCGIFMAP:
  	case SIOCSIFMAP:
  		return compat_sioc_ifmap(net, cmd, argp);
6b96018b2   Arnd Bergmann   compat: move sock...
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
  	case SIOCBONDENSLAVE:
  	case SIOCBONDRELEASE:
  	case SIOCBONDSETHWADDR:
  	case SIOCBONDSLAVEINFOQUERY:
  	case SIOCBONDINFOQUERY:
  	case SIOCBONDCHANGEACTIVE:
  		return bond_ioctl(net, cmd, argp);
  	case SIOCADDRT:
  	case SIOCDELRT:
  		return routing_ioctl(net, sock, cmd, argp);
  	case SIOCGSTAMP:
  		return do_siocgstamp(net, sock, cmd, argp);
  	case SIOCGSTAMPNS:
  		return do_siocgstampns(net, sock, cmd, argp);
a2116ed22   Arnd Bergmann   net/compat: fix d...
3008
3009
  	case SIOCSHWTSTAMP:
  		return compat_siocshwtstamp(net, argp);
6b96018b2   Arnd Bergmann   compat: move sock...
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
  
  	case FIOSETOWN:
  	case SIOCSPGRP:
  	case FIOGETOWN:
  	case SIOCGPGRP:
  	case SIOCBRADDBR:
  	case SIOCBRDELBR:
  	case SIOCGIFVLAN:
  	case SIOCSIFVLAN:
  	case SIOCADDDLCI:
  	case SIOCDELDLCI:
  		return sock_ioctl(file, cmd, arg);
  
  	case SIOCGIFFLAGS:
  	case SIOCSIFFLAGS:
  	case SIOCGIFMETRIC:
  	case SIOCSIFMETRIC:
  	case SIOCGIFMTU:
  	case SIOCSIFMTU:
  	case SIOCGIFMEM:
  	case SIOCSIFMEM:
  	case SIOCGIFHWADDR:
  	case SIOCSIFHWADDR:
  	case SIOCADDMULTI:
  	case SIOCDELMULTI:
  	case SIOCGIFINDEX:
6b96018b2   Arnd Bergmann   compat: move sock...
3036
3037
3038
  	case SIOCGIFADDR:
  	case SIOCSIFADDR:
  	case SIOCSIFHWBROADCAST:
6b96018b2   Arnd Bergmann   compat: move sock...
3039
  	case SIOCDIFADDR:
6b96018b2   Arnd Bergmann   compat: move sock...
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
  	case SIOCGIFBRDADDR:
  	case SIOCSIFBRDADDR:
  	case SIOCGIFDSTADDR:
  	case SIOCSIFDSTADDR:
  	case SIOCGIFNETMASK:
  	case SIOCSIFNETMASK:
  	case SIOCSIFPFLAGS:
  	case SIOCGIFPFLAGS:
  	case SIOCGIFTXQLEN:
  	case SIOCSIFTXQLEN:
  	case SIOCBRADDIF:
  	case SIOCBRDELIF:
9177efd39   Arnd Bergmann   net, compat_ioctl...
3052
3053
3054
3055
  	case SIOCSIFNAME:
  	case SIOCGMIIPHY:
  	case SIOCGMIIREG:
  	case SIOCSMIIREG:
6b96018b2   Arnd Bergmann   compat: move sock...
3056
  		return dev_ifsioc(net, sock, cmd, argp);
9177efd39   Arnd Bergmann   net, compat_ioctl...
3057

6b96018b2   Arnd Bergmann   compat: move sock...
3058
3059
3060
  	case SIOCSARP:
  	case SIOCGARP:
  	case SIOCDARP:
6b96018b2   Arnd Bergmann   compat: move sock...
3061
  	case SIOCATMARK:
9177efd39   Arnd Bergmann   net, compat_ioctl...
3062
3063
  		return sock_do_ioctl(net, sock, cmd, arg);
  	}
6b96018b2   Arnd Bergmann   compat: move sock...
3064
3065
  	return -ENOIOCTLCMD;
  }
7a229387d   Arnd Bergmann   net: copy socket ...
3066

89bbfc95d   Shaun Pereira   [NET]: allow 32 b...
3067
  static long compat_sock_ioctl(struct file *file, unsigned cmd,
89bddce58   Stephen Hemminger   [NET] socket: cod...
3068
  			      unsigned long arg)
89bbfc95d   Shaun Pereira   [NET]: allow 32 b...
3069
3070
3071
  {
  	struct socket *sock = file->private_data;
  	int ret = -ENOIOCTLCMD;
87de87d5e   David S. Miller   wext: Dispatch an...
3072
3073
3074
3075
3076
  	struct sock *sk;
  	struct net *net;
  
  	sk = sock->sk;
  	net = sock_net(sk);
89bbfc95d   Shaun Pereira   [NET]: allow 32 b...
3077
3078
3079
  
  	if (sock->ops->compat_ioctl)
  		ret = sock->ops->compat_ioctl(sock, cmd, arg);
87de87d5e   David S. Miller   wext: Dispatch an...
3080
3081
3082
  	if (ret == -ENOIOCTLCMD &&
  	    (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST))
  		ret = compat_wext_handle_ioctl(net, cmd, arg);
6b96018b2   Arnd Bergmann   compat: move sock...
3083
3084
  	if (ret == -ENOIOCTLCMD)
  		ret = compat_sock_ioctl_trans(file, sock, cmd, arg);
89bbfc95d   Shaun Pereira   [NET]: allow 32 b...
3085
3086
3087
  	return ret;
  }
  #endif
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3088
3089
3090
3091
  int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
  {
  	return sock->ops->bind(sock, addr, addrlen);
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
3092
  EXPORT_SYMBOL(kernel_bind);
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3093
3094
3095
3096
3097
  
  int kernel_listen(struct socket *sock, int backlog)
  {
  	return sock->ops->listen(sock, backlog);
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
3098
  EXPORT_SYMBOL(kernel_listen);
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
  
  int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
  {
  	struct sock *sk = sock->sk;
  	int err;
  
  	err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
  			       newsock);
  	if (err < 0)
  		goto done;
  
  	err = sock->ops->accept(sock, *newsock, flags);
  	if (err < 0) {
  		sock_release(*newsock);
fa8705b00   Tony Battersby   [NET]: sanitize k...
3113
  		*newsock = NULL;
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3114
3115
3116
3117
  		goto done;
  	}
  
  	(*newsock)->ops = sock->ops;
1b08534e5   Wei Yongjun   net: Fix module r...
3118
  	__module_get((*newsock)->ops->owner);
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3119
3120
3121
3122
  
  done:
  	return err;
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
3123
  EXPORT_SYMBOL(kernel_accept);
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3124
3125
  
  int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
4768fbcbc   YOSHIFUJI Hideaki   [NET]: Fix whites...
3126
  		   int flags)
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3127
3128
3129
  {
  	return sock->ops->connect(sock, addr, addrlen, flags);
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
3130
  EXPORT_SYMBOL(kernel_connect);
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3131
3132
3133
3134
3135
3136
  
  int kernel_getsockname(struct socket *sock, struct sockaddr *addr,
  			 int *addrlen)
  {
  	return sock->ops->getname(sock, addr, addrlen, 0);
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
3137
  EXPORT_SYMBOL(kernel_getsockname);
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3138
3139
3140
3141
3142
3143
  
  int kernel_getpeername(struct socket *sock, struct sockaddr *addr,
  			 int *addrlen)
  {
  	return sock->ops->getname(sock, addr, addrlen, 1);
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
3144
  EXPORT_SYMBOL(kernel_getpeername);
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3145
3146
3147
3148
3149
  
  int kernel_getsockopt(struct socket *sock, int level, int optname,
  			char *optval, int *optlen)
  {
  	mm_segment_t oldfs = get_fs();
fb8621bb6   Namhyung Kim   net: remove addre...
3150
3151
  	char __user *uoptval;
  	int __user *uoptlen;
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3152
  	int err;
fb8621bb6   Namhyung Kim   net: remove addre...
3153
3154
  	uoptval = (char __user __force *) optval;
  	uoptlen = (int __user __force *) optlen;
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3155
3156
  	set_fs(KERNEL_DS);
  	if (level == SOL_SOCKET)
fb8621bb6   Namhyung Kim   net: remove addre...
3157
  		err = sock_getsockopt(sock, level, optname, uoptval, uoptlen);
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3158
  	else
fb8621bb6   Namhyung Kim   net: remove addre...
3159
3160
  		err = sock->ops->getsockopt(sock, level, optname, uoptval,
  					    uoptlen);
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3161
3162
3163
  	set_fs(oldfs);
  	return err;
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
3164
  EXPORT_SYMBOL(kernel_getsockopt);
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3165
3166
  
  int kernel_setsockopt(struct socket *sock, int level, int optname,
b7058842c   David S. Miller   net: Make setsock...
3167
  			char *optval, unsigned int optlen)
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3168
3169
  {
  	mm_segment_t oldfs = get_fs();
fb8621bb6   Namhyung Kim   net: remove addre...
3170
  	char __user *uoptval;
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3171
  	int err;
fb8621bb6   Namhyung Kim   net: remove addre...
3172
  	uoptval = (char __user __force *) optval;
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3173
3174
  	set_fs(KERNEL_DS);
  	if (level == SOL_SOCKET)
fb8621bb6   Namhyung Kim   net: remove addre...
3175
  		err = sock_setsockopt(sock, level, optname, uoptval, optlen);
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3176
  	else
fb8621bb6   Namhyung Kim   net: remove addre...
3177
  		err = sock->ops->setsockopt(sock, level, optname, uoptval,
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3178
3179
3180
3181
  					    optlen);
  	set_fs(oldfs);
  	return err;
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
3182
  EXPORT_SYMBOL(kernel_setsockopt);
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3183
3184
3185
3186
  
  int kernel_sendpage(struct socket *sock, struct page *page, int offset,
  		    size_t size, int flags)
  {
f84517253   Herbert Xu   cls_cgroup: Store...
3187
  	sock_update_classid(sock->sk);
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3188
3189
3190
3191
3192
  	if (sock->ops->sendpage)
  		return sock->ops->sendpage(sock, page, offset, size, flags);
  
  	return sock_no_sendpage(sock, page, offset, size, flags);
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
3193
  EXPORT_SYMBOL(kernel_sendpage);
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
  
  int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg)
  {
  	mm_segment_t oldfs = get_fs();
  	int err;
  
  	set_fs(KERNEL_DS);
  	err = sock->ops->ioctl(sock, cmd, arg);
  	set_fs(oldfs);
  
  	return err;
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
3206
  EXPORT_SYMBOL(kernel_sock_ioctl);
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3207

91cf45f02   Trond Myklebust   [NET]: Add the he...
3208
3209
3210
3211
  int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
  {
  	return sock->ops->shutdown(sock, how);
  }
91cf45f02   Trond Myklebust   [NET]: Add the he...
3212
  EXPORT_SYMBOL(kernel_sock_shutdown);