Blame view

net/socket.c 83.6 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
  #include <linux/if_bridge.h>
20380731b   Arnaldo Carvalho de Melo   [NET]: Fix sparse...
72
73
  #include <linux/if_frad.h>
  #include <linux/if_vlan.h>
408eccce3   Daniel Borkmann   net: ptp: move PT...
74
  #include <linux/ptp_classify.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>
600e17792   Masatake YAMATO   net: Providing pr...
90
  #include <linux/xattr.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
92
93
94
95
  
  #include <asm/uaccess.h>
  #include <asm/unistd.h>
  
  #include <net/compat.h>
87de87d5e   David S. Miller   wext: Dispatch an...
96
  #include <net/wext.h>
f84517253   Herbert Xu   cls_cgroup: Store...
97
  #include <net/cls_cgroup.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
99
100
  
  #include <net/sock.h>
  #include <linux/netfilter.h>
6b96018b2   Arnd Bergmann   compat: move sock...
101
102
103
  #include <linux/if_tun.h>
  #include <linux/ipv6_route.h>
  #include <linux/route.h>
6b96018b2   Arnd Bergmann   compat: move sock...
104
105
  #include <linux/sockios.h>
  #include <linux/atalk.h>
076bb0c82   Eliezer Tamir   net: rename inclu...
106
  #include <net/busy_poll.h>
f24b9be59   Willem de Bruijn   net-timestamp: ex...
107
  #include <linux/errqueue.h>
060212928   Eliezer Tamir   net: add low late...
108

e0d1095ae   Cong Wang   net: rename CONFI...
109
  #ifdef CONFIG_NET_RX_BUSY_POLL
64b0dc517   Eliezer Tamir   net: rename busy ...
110
111
  unsigned int sysctl_net_busy_read __read_mostly;
  unsigned int sysctl_net_busy_poll __read_mostly;
060212928   Eliezer Tamir   net: add low late...
112
  #endif
6b96018b2   Arnd Bergmann   compat: move sock...
113

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114
  static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
027445c37   Badari Pulavarty   [PATCH] Vectorize...
115
116
117
118
  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...
119
  static int sock_mmap(struct file *file, struct vm_area_struct *vma);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
121
122
123
  
  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...
124
  static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
89bbfc95d   Shaun Pereira   [NET]: allow 32 b...
125
126
  #ifdef CONFIG_COMPAT
  static long compat_sock_ioctl(struct file *file,
89bddce58   Stephen Hemminger   [NET] socket: cod...
127
  			      unsigned int cmd, unsigned long arg);
89bbfc95d   Shaun Pereira   [NET]: allow 32 b...
128
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129
  static int sock_fasync(int fd, struct file *filp, int on);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
130
131
  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...
132
  static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
133
  				struct pipe_inode_info *pipe, size_t len,
9c55e01c0   Jens Axboe   [TCP]: Splice rec...
134
  				unsigned int flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
135

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
137
138
139
  /*
   *	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...
140
  static const struct file_operations socket_file_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
142
143
144
145
146
  	.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...
147
148
149
  #ifdef CONFIG_COMPAT
  	.compat_ioctl = compat_sock_ioctl,
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
150
151
152
153
  	.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...
154
155
  	.sendpage =	sock_sendpage,
  	.splice_write = generic_splice_sendpage,
9c55e01c0   Jens Axboe   [TCP]: Splice rec...
156
  	.splice_read =	sock_splice_read,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
157
158
159
160
161
  };
  
  /*
   *	The protocol list. Each protocol is registered in here.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162
  static DEFINE_SPINLOCK(net_family_lock);
190683a9d   Eric Dumazet   net: net_families...
163
  static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165
166
167
  /*
   *	Statistics counters of the socket lists
   */
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
168
  static DEFINE_PER_CPU(int, sockets_in_use);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
169
170
  
  /*
89bddce58   Stephen Hemminger   [NET] socket: cod...
171
172
173
   * 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
174
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175
176
177
178
179
180
181
182
183
184
  /**
   *	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.
   */
43db362d3   Maciej Żenczykowski   net: get rid of s...
185
  int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
  {
230b18392   YOSHIFUJI Hideaki   net: Use standard...
187
  	if (ulen < 0 || ulen > sizeof(struct sockaddr_storage))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188
  		return -EINVAL;
89bddce58   Stephen Hemminger   [NET] socket: cod...
189
  	if (ulen == 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
  		return 0;
89bddce58   Stephen Hemminger   [NET] socket: cod...
191
  	if (copy_from_user(kaddr, uaddr, ulen))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
  		return -EFAULT;
3ec3b2fba   David Woodhouse   AUDIT: Capture sy...
193
  	return audit_sockaddr(ulen, kaddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
  }
  
  /**
   *	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...
212

43db362d3   Maciej Żenczykowski   net: get rid of s...
213
  static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen,
11165f145   stephen hemminger   socket: localize ...
214
  			     void __user *uaddr, int __user *ulen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215
216
217
  {
  	int err;
  	int len;
68c6beb37   Hannes Frederic Sowa   net: add BUG_ON i...
218
  	BUG_ON(klen > sizeof(struct sockaddr_storage));
89bddce58   Stephen Hemminger   [NET] socket: cod...
219
220
  	err = get_user(len, ulen);
  	if (err)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
  		return err;
89bddce58   Stephen Hemminger   [NET] socket: cod...
222
223
  	if (len > klen)
  		len = klen;
68c6beb37   Hannes Frederic Sowa   net: add BUG_ON i...
224
  	if (len < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
  		return -EINVAL;
89bddce58   Stephen Hemminger   [NET] socket: cod...
226
  	if (len) {
d6fe3945b   Steve Grubb   [PATCH] sockaddr ...
227
228
  		if (audit_sockaddr(klen, kaddr))
  			return -ENOMEM;
89bddce58   Stephen Hemminger   [NET] socket: cod...
229
  		if (copy_to_user(uaddr, kaddr, len))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
231
232
  			return -EFAULT;
  	}
  	/*
89bddce58   Stephen Hemminger   [NET] socket: cod...
233
234
  	 *      "fromlen shall refer to the value before truncation.."
  	 *                      1003.1g
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
235
236
237
  	 */
  	return __put_user(klen, ulen);
  }
e18b890bb   Christoph Lameter   [PATCH] slab: rem...
238
  static struct kmem_cache *sock_inode_cachep __read_mostly;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
239
240
241
242
  
  static struct inode *sock_alloc_inode(struct super_block *sb)
  {
  	struct socket_alloc *ei;
eaefd1105   Eric Dumazet   net: add __rcu an...
243
  	struct socket_wq *wq;
89bddce58   Stephen Hemminger   [NET] socket: cod...
244

e94b17660   Christoph Lameter   [PATCH] slab: rem...
245
  	ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
246
247
  	if (!ei)
  		return NULL;
eaefd1105   Eric Dumazet   net: add __rcu an...
248
249
  	wq = kmalloc(sizeof(*wq), GFP_KERNEL);
  	if (!wq) {
438154823   Eric Dumazet   net: sock_def_rea...
250
251
252
  		kmem_cache_free(sock_inode_cachep, ei);
  		return NULL;
  	}
eaefd1105   Eric Dumazet   net: add __rcu an...
253
254
255
  	init_waitqueue_head(&wq->wait);
  	wq->fasync_list = NULL;
  	RCU_INIT_POINTER(ei->socket.wq, wq);
89bddce58   Stephen Hemminger   [NET] socket: cod...
256

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
257
258
259
260
261
  	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
262
263
264
265
266
267
  
  	return &ei->vfs_inode;
  }
  
  static void sock_destroy_inode(struct inode *inode)
  {
438154823   Eric Dumazet   net: sock_def_rea...
268
  	struct socket_alloc *ei;
eaefd1105   Eric Dumazet   net: add __rcu an...
269
  	struct socket_wq *wq;
438154823   Eric Dumazet   net: sock_def_rea...
270
271
  
  	ei = container_of(inode, struct socket_alloc, vfs_inode);
eaefd1105   Eric Dumazet   net: add __rcu an...
272
  	wq = rcu_dereference_protected(ei->socket.wq, 1);
618452202   Lai Jiangshan   net,rcu: convert ...
273
  	kfree_rcu(wq, rcu);
438154823   Eric Dumazet   net: sock_def_rea...
274
  	kmem_cache_free(sock_inode_cachep, ei);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
275
  }
51cc50685   Alexey Dobriyan   SL*B: drop kmem c...
276
  static void init_once(void *foo)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
277
  {
89bddce58   Stephen Hemminger   [NET] socket: cod...
278
  	struct socket_alloc *ei = (struct socket_alloc *)foo;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283
284
285
  static int init_inodecache(void)
  {
  	sock_inode_cachep = kmem_cache_create("sock_inode_cache",
89bddce58   Stephen Hemminger   [NET] socket: cod...
286
287
288
289
290
  					      sizeof(struct socket_alloc),
  					      0,
  					      (SLAB_HWCACHE_ALIGN |
  					       SLAB_RECLAIM_ACCOUNT |
  					       SLAB_MEM_SPREAD),
20c2df83d   Paul Mundt   mm: Remove slab d...
291
  					      init_once);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
292
293
294
295
  	if (sock_inode_cachep == NULL)
  		return -ENOMEM;
  	return 0;
  }
b87221de6   Alexey Dobriyan   const: mark remai...
296
  static const struct super_operations sockfs_ops = {
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
297
298
299
  	.alloc_inode	= sock_alloc_inode,
  	.destroy_inode	= sock_destroy_inode,
  	.statfs		= simple_statfs,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
300
  };
c23fbb6bc   Eric Dumazet   VFS: delay the de...
301
302
303
304
305
306
307
308
  /*
   * 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...
309
  static const struct dentry_operations sockfs_dentry_operations = {
c23fbb6bc   Eric Dumazet   VFS: delay the de...
310
  	.d_dname  = sockfs_dname,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
311
  };
c74a1cbb3   Al Viro   pass default dent...
312
313
314
315
316
317
318
319
320
321
322
323
324
325
  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
326
327
328
  /*
   *	Obtains the first available file descriptor and sets it up for use.
   *
39d8c1b6f   David S. Miller   [NET]: Do not los...
329
330
   *	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
331
332
333
334
335
336
337
338
339
340
341
   *	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.
   */
aab174f0d   Linus Torvalds   Merge branch 'for...
342
  struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
343
  {
7cbe66b6b   Al Viro   merge sock_alloc_...
344
  	struct qstr name = { .name = "" };
2c48b9c45   Al Viro   switch alloc_file...
345
  	struct path path;
7cbe66b6b   Al Viro   merge sock_alloc_...
346
  	struct file *file;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
347

600e17792   Masatake YAMATO   net: Providing pr...
348
349
350
351
352
353
354
  	if (dname) {
  		name.name = dname;
  		name.len = strlen(name.name);
  	} else if (sock->sk) {
  		name.name = sock->sk->sk_prot_creator->name;
  		name.len = strlen(name.name);
  	}
4b936885a   Nick Piggin   fs: improve scala...
355
  	path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name);
284076305   Al Viro   take descriptor h...
356
357
  	if (unlikely(!path.dentry))
  		return ERR_PTR(-ENOMEM);
2c48b9c45   Al Viro   switch alloc_file...
358
  	path.mnt = mntget(sock_mnt);
39d8c1b6f   David S. Miller   [NET]: Do not los...
359

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

2c48b9c45   Al Viro   switch alloc_file...
363
  	file = alloc_file(&path, FMODE_READ | FMODE_WRITE,
ce8d2cdf3   Dave Hansen   r/o bind mounts: ...
364
  		  &socket_file_ops);
39b652527   Anatol Pomozov   fs: Preserve erro...
365
  	if (unlikely(IS_ERR(file))) {
cc3808f8c   Al Viro   switch sock_alloc...
366
  		/* drop dentry, keep inode */
7de9c6ee3   Al Viro   new helper: ihold()
367
  		ihold(path.dentry->d_inode);
2c48b9c45   Al Viro   switch alloc_file...
368
  		path_put(&path);
39b652527   Anatol Pomozov   fs: Preserve erro...
369
  		return file;
cc3808f8c   Al Viro   switch sock_alloc...
370
371
372
  	}
  
  	sock->file = file;
77d272005   Ulrich Drepper   flag parameters: ...
373
  	file->f_flags = O_RDWR | (flags & O_NONBLOCK);
39d8c1b6f   David S. Miller   [NET]: Do not los...
374
  	file->private_data = sock;
284076305   Al Viro   take descriptor h...
375
  	return file;
39d8c1b6f   David S. Miller   [NET]: Do not los...
376
  }
56b31d1c9   Al Viro   unexport sock_map...
377
  EXPORT_SYMBOL(sock_alloc_file);
39d8c1b6f   David S. Miller   [NET]: Do not los...
378

56b31d1c9   Al Viro   unexport sock_map...
379
  static int sock_map_fd(struct socket *sock, int flags)
39d8c1b6f   David S. Miller   [NET]: Do not los...
380
381
  {
  	struct file *newfile;
284076305   Al Viro   take descriptor h...
382
383
384
  	int fd = get_unused_fd_flags(flags);
  	if (unlikely(fd < 0))
  		return fd;
39d8c1b6f   David S. Miller   [NET]: Do not los...
385

aab174f0d   Linus Torvalds   Merge branch 'for...
386
  	newfile = sock_alloc_file(sock, flags, NULL);
284076305   Al Viro   take descriptor h...
387
  	if (likely(!IS_ERR(newfile))) {
39d8c1b6f   David S. Miller   [NET]: Do not los...
388
  		fd_install(fd, newfile);
284076305   Al Viro   take descriptor h...
389
390
  		return fd;
  	}
7cbe66b6b   Al Viro   merge sock_alloc_...
391

284076305   Al Viro   take descriptor h...
392
393
  	put_unused_fd(fd);
  	return PTR_ERR(newfile);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
394
  }
406a3c638   John Fastabend   net: netprio_cgro...
395
  struct socket *sock_from_file(struct file *file, int *err)
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
396
  {
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
397
398
  	if (file->f_op == &socket_file_ops)
  		return file->private_data;	/* set in sock_map_fd */
23bb80d21   Eric Dumazet   [NET]: cleanup so...
399
400
  	*err = -ENOTSOCK;
  	return NULL;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
401
  }
406a3c638   John Fastabend   net: netprio_cgro...
402
  EXPORT_SYMBOL(sock_from_file);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
403

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
404
  /**
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
405
   *	sockfd_lookup - Go from a file number to its socket slot
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
406
407
408
409
410
411
412
413
414
415
416
417
418
419
   *	@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
420
  	struct socket *sock;
89bddce58   Stephen Hemminger   [NET] socket: cod...
421
422
  	file = fget(fd);
  	if (!file) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
423
424
425
  		*err = -EBADF;
  		return NULL;
  	}
89bddce58   Stephen Hemminger   [NET] socket: cod...
426

6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
427
428
  	sock = sock_from_file(file, err);
  	if (!sock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
429
  		fput(file);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
430
431
  	return sock;
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
432
  EXPORT_SYMBOL(sockfd_lookup);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
433

6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
434
435
  static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
  {
00e188ef6   Al Viro   sockfd_lookup_lig...
436
  	struct fd f = fdget(fd);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
437
  	struct socket *sock;
3672558c6   Hua Zhong   [NET]: sockfd_loo...
438
  	*err = -EBADF;
00e188ef6   Al Viro   sockfd_lookup_lig...
439
440
441
442
  	if (f.file) {
  		sock = sock_from_file(f.file, err);
  		if (likely(sock)) {
  			*fput_needed = f.flags;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
443
  			return sock;
00e188ef6   Al Viro   sockfd_lookup_lig...
444
445
  		}
  		fdput(f);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
446
  	}
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
447
  	return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
448
  }
600e17792   Masatake YAMATO   net: Providing pr...
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
  #define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname"
  #define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX)
  #define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1)
  static ssize_t sockfs_getxattr(struct dentry *dentry,
  			       const char *name, void *value, size_t size)
  {
  	const char *proto_name;
  	size_t proto_size;
  	int error;
  
  	error = -ENODATA;
  	if (!strncmp(name, XATTR_NAME_SOCKPROTONAME, XATTR_NAME_SOCKPROTONAME_LEN)) {
  		proto_name = dentry->d_name.name;
  		proto_size = strlen(proto_name);
  
  		if (value) {
  			error = -ERANGE;
  			if (proto_size + 1 > size)
  				goto out;
  
  			strncpy(value, proto_name, proto_size + 1);
  		}
  		error = proto_size + 1;
  	}
  
  out:
  	return error;
  }
  
  static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer,
  				size_t size)
  {
  	ssize_t len;
  	ssize_t used = 0;
  
  	len = security_inode_listsecurity(dentry->d_inode, buffer, size);
  	if (len < 0)
  		return len;
  	used += len;
  	if (buffer) {
  		if (size < used)
  			return -ERANGE;
  		buffer += len;
  	}
  
  	len = (XATTR_NAME_SOCKPROTONAME_LEN + 1);
  	used += len;
  	if (buffer) {
  		if (size < used)
  			return -ERANGE;
  		memcpy(buffer, XATTR_NAME_SOCKPROTONAME, len);
  		buffer += len;
  	}
  
  	return used;
  }
  
  static const struct inode_operations sockfs_inode_ops = {
  	.getxattr = sockfs_getxattr,
  	.listxattr = sockfs_listxattr,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
510
511
  /**
   *	sock_alloc	-	allocate a socket
89bddce58   Stephen Hemminger   [NET] socket: cod...
512
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
513
514
515
516
517
518
519
   *	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...
520
521
  	struct inode *inode;
  	struct socket *sock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
522

a209dfc7b   Eric Dumazet   vfs: dont chain p...
523
  	inode = new_inode_pseudo(sock_mnt->mnt_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
524
525
526
527
  	if (!inode)
  		return NULL;
  
  	sock = SOCKET_I(inode);
29a020d35   Eric Dumazet   [PATCH] net: kmem...
528
  	kmemcheck_annotate_bitfield(sock, type);
85fe4025c   Christoph Hellwig   fs: do not assign...
529
  	inode->i_ino = get_next_ino();
89bddce58   Stephen Hemminger   [NET] socket: cod...
530
  	inode->i_mode = S_IFSOCK | S_IRWXUGO;
8192b0c48   David Howells   CRED: Wrap task c...
531
532
  	inode->i_uid = current_fsuid();
  	inode->i_gid = current_fsgid();
600e17792   Masatake YAMATO   net: Providing pr...
533
  	inode->i_op = &sockfs_inode_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
534

19e8d69c5   Alex Shi   net: replace perc...
535
  	this_cpu_add(sockets_in_use, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
536
537
538
539
540
541
542
543
  	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...
544

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
545
546
547
548
  static int sock_no_open(struct inode *irrelevant, struct file *dontcare)
  {
  	return -ENXIO;
  }
4b6f5d20b   Arjan van de Ven   [PATCH] Make most...
549
  const struct file_operations bad_sock_fops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
550
551
  	.owner = THIS_MODULE,
  	.open = sock_no_open,
6038f373a   Arnd Bergmann   llseek: automatic...
552
  	.llseek = noop_llseek,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
553
554
555
556
557
558
559
560
  };
  
  /**
   *	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...
561
   *	an inode not a file.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
562
   */
89bddce58   Stephen Hemminger   [NET] socket: cod...
563

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
564
565
566
567
568
569
570
571
572
  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...
573
  	if (rcu_dereference_protected(sock->wq, 1)->fasync_list)
3410f22ea   Yang Yingliang   socket: replace s...
574
575
  		pr_err("%s: fasync list not empty!
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
576

b09e786bd   Mikulas Patocka   tun: fix a crash ...
577
578
  	if (test_bit(SOCK_EXTERNALLY_ALLOCATED, &sock->flags))
  		return;
19e8d69c5   Alex Shi   net: replace perc...
579
  	this_cpu_sub(sockets_in_use, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
581
582
583
  	if (!sock->file) {
  		iput(SOCK_INODE(sock));
  		return;
  	}
89bddce58   Stephen Hemminger   [NET] socket: cod...
584
  	sock->file = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
585
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
586
  EXPORT_SYMBOL(sock_release);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
587

140c55d4b   Eric Dumazet   net-timestamp: so...
588
  void sock_tx_timestamp(const struct sock *sk, __u8 *tx_flags)
20d494735   Patrick Ohly   net: socket infra...
589
  {
140c55d4b   Eric Dumazet   net-timestamp: so...
590
  	u8 flags = *tx_flags;
b9f40e21e   Willem de Bruijn   net-timestamp: mo...
591
  	if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_HARDWARE)
140c55d4b   Eric Dumazet   net-timestamp: so...
592
  		flags |= SKBTX_HW_TSTAMP;
b9f40e21e   Willem de Bruijn   net-timestamp: mo...
593
  	if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_SOFTWARE)
140c55d4b   Eric Dumazet   net-timestamp: so...
594
  		flags |= SKBTX_SW_TSTAMP;
e7fd28853   Willem de Bruijn   net-timestamp: SC...
595
  	if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_SCHED)
140c55d4b   Eric Dumazet   net-timestamp: so...
596
  		flags |= SKBTX_SCHED_TSTAMP;
e1c8a607b   Willem de Bruijn   net-timestamp: AC...
597
  	if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_ACK)
140c55d4b   Eric Dumazet   net-timestamp: so...
598
  		flags |= SKBTX_ACK_TSTAMP;
e7fd28853   Willem de Bruijn   net-timestamp: SC...
599

6e3e939f3   Johannes Berg   net: add wireless...
600
  	if (sock_flag(sk, SOCK_WIFI_STATUS))
140c55d4b   Eric Dumazet   net-timestamp: so...
601
602
603
  		flags |= SKBTX_WIFI_STATUS;
  
  	*tx_flags = flags;
20d494735   Patrick Ohly   net: socket infra...
604
605
  }
  EXPORT_SYMBOL(sock_tx_timestamp);
228e548e6   Anton Blanchard   net: Add sendmmsg...
606
607
  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
608
609
  {
  	struct sock_iocb *si = kiocb_to_siocb(iocb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
610
611
612
613
614
  
  	si->sock = sock;
  	si->scm = NULL;
  	si->msg = msg;
  	si->size = size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
615
616
  	return sock->ops->sendmsg(iocb, sock, msg, size);
  }
228e548e6   Anton Blanchard   net: Add sendmmsg...
617
618
619
620
621
622
623
  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
624
625
626
627
628
629
630
631
632
633
634
635
636
  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...
637
  EXPORT_SYMBOL(sock_sendmsg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
638

894dc24ce   Eric Dumazet   net: sock_sendmsg...
639
  static int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg, size_t size)
228e548e6   Anton Blanchard   net: Add sendmmsg...
640
641
642
643
644
645
646
647
648
649
650
651
  {
  	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
652
653
654
655
656
657
658
659
660
661
662
  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...
663
  	msg->msg_iov = (struct iovec *)vec;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
664
665
666
667
668
  	msg->msg_iovlen = num;
  	result = sock_sendmsg(sock, msg, size);
  	set_fs(oldfs);
  	return result;
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
669
  EXPORT_SYMBOL(kernel_sendmsg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
670

92f37fd2e   Eric Dumazet   [NET]: Adding SO_...
671
672
673
674
675
676
  /*
   * 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...
677
  	int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
f24b9be59   Willem de Bruijn   net-timestamp: ex...
678
  	struct scm_timestamping tss;
20d494735   Patrick Ohly   net: socket infra...
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
  	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 {
f24b9be59   Willem de Bruijn   net-timestamp: ex...
695
696
  			struct timespec ts;
  			skb_get_timestampns(skb, &ts);
20d494735   Patrick Ohly   net: socket infra...
697
  			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS,
f24b9be59   Willem de Bruijn   net-timestamp: ex...
698
  				 sizeof(ts), &ts);
20d494735   Patrick Ohly   net: socket infra...
699
700
  		}
  	}
f24b9be59   Willem de Bruijn   net-timestamp: ex...
701
  	memset(&tss, 0, sizeof(tss));
b9f40e21e   Willem de Bruijn   net-timestamp: mo...
702
  	if ((sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE ||
f24b9be59   Willem de Bruijn   net-timestamp: ex...
703
704
  	     skb_shinfo(skb)->tx_flags & SKBTX_ANY_SW_TSTAMP) &&
  	    ktime_to_timespec_cond(skb->tstamp, tss.ts + 0))
20d494735   Patrick Ohly   net: socket infra...
705
  		empty = 0;
4d276eb6a   Willem de Bruijn   net: remove depre...
706
  	if (shhwtstamps &&
b9f40e21e   Willem de Bruijn   net-timestamp: mo...
707
  	    (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
f24b9be59   Willem de Bruijn   net-timestamp: ex...
708
  	    ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2))
4d276eb6a   Willem de Bruijn   net: remove depre...
709
  		empty = 0;
20d494735   Patrick Ohly   net: socket infra...
710
711
  	if (!empty)
  		put_cmsg(msg, SOL_SOCKET,
f24b9be59   Willem de Bruijn   net-timestamp: ex...
712
  			 SCM_TIMESTAMPING, sizeof(tss), &tss);
92f37fd2e   Eric Dumazet   [NET]: Adding SO_...
713
  }
7c81fd8bf   Arnaldo Carvalho de Melo   [SOCKET]: Export ...
714
  EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
6e3e939f3   Johannes Berg   net: add wireless...
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
  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 ...
730
731
  static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk,
  				   struct sk_buff *skb)
3b885787e   Neil Horman   net: Generalize s...
732
733
734
735
736
  {
  	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...
737
  void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
3b885787e   Neil Horman   net: Generalize s...
738
739
740
741
742
  	struct sk_buff *skb)
  {
  	sock_recv_timestamp(msg, sk, skb);
  	sock_recv_drops(msg, sk, skb);
  }
767dd0336   Eric Dumazet   net: speedup sock...
743
  EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops);
3b885787e   Neil Horman   net: Generalize s...
744

a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
745
746
  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
747
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
748
749
750
751
752
753
754
  	struct sock_iocb *si = kiocb_to_siocb(iocb);
  
  	si->sock = sock;
  	si->scm = NULL;
  	si->msg = msg;
  	si->size = size;
  	si->flags = flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
755
756
  	return sock->ops->recvmsg(iocb, sock, msg, size, flags);
  }
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
757
758
759
760
761
762
763
  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...
764
  int sock_recvmsg(struct socket *sock, struct msghdr *msg,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
765
766
767
768
769
  		 size_t size, int flags)
  {
  	struct kiocb iocb;
  	struct sock_iocb siocb;
  	int ret;
89bddce58   Stephen Hemminger   [NET] socket: cod...
770
  	init_sync_kiocb(&iocb, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
771
772
773
774
775
776
  	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...
777
  EXPORT_SYMBOL(sock_recvmsg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
778

a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
779
780
781
782
783
784
785
786
787
788
789
790
791
792
  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...
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
  /**
   * 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...
808
809
  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
810
811
812
813
814
815
816
817
818
  {
  	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...
819
  	msg->msg_iov = (struct iovec *)vec, msg->msg_iovlen = num;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
820
821
822
823
  	result = sock_recvmsg(sock, msg, size, flags);
  	set_fs(oldfs);
  	return result;
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
824
  EXPORT_SYMBOL(kernel_recvmsg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
825

ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
826
827
  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
828
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
829
830
  	struct socket *sock;
  	int flags;
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
831
  	sock = file->private_data;
35f9c09fe   Eric Dumazet   tcp: tcp_sendpage...
832
833
834
  	flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
  	/* more is a combination of MSG_MORE and MSG_SENDPAGE_NOTLAST */
  	flags |= more;
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
835

e69495838   Linus Torvalds   Make sock_sendpag...
836
  	return kernel_sendpage(sock, page, offset, size, flags);
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
837
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
838

9c55e01c0   Jens Axboe   [TCP]: Splice rec...
839
  static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
840
  				struct pipe_inode_info *pipe, size_t len,
9c55e01c0   Jens Axboe   [TCP]: Splice rec...
841
842
843
  				unsigned int flags)
  {
  	struct socket *sock = file->private_data;
997b37da1   Rémi Denis-Courmont   [NET]: Make sure ...
844
845
  	if (unlikely(!sock->ops->splice_read))
  		return -EINVAL;
9c55e01c0   Jens Axboe   [TCP]: Splice rec...
846
847
  	return sock->ops->splice_read(sock, ppos, pipe, len, flags);
  }
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
848
  static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
89bddce58   Stephen Hemminger   [NET] socket: cod...
849
  					 struct sock_iocb *siocb)
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
850
  {
d29c445b6   Kent Overstreet   aio: Kill ki_dtor
851
852
  	if (!is_sync_kiocb(iocb))
  		BUG();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
853

ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
854
  	siocb->kiocb = iocb;
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
855
856
  	iocb->private = siocb;
  	return siocb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
857
  }
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
858
  static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb,
027445c37   Badari Pulavarty   [PATCH] Vectorize...
859
860
  		struct file *file, const struct iovec *iov,
  		unsigned long nr_segs)
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
861
862
863
864
  {
  	struct socket *sock = file->private_data;
  	size_t size = 0;
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
865

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

ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
869
870
871
872
  	msg->msg_name = NULL;
  	msg->msg_namelen = 0;
  	msg->msg_control = NULL;
  	msg->msg_controllen = 0;
89bddce58   Stephen Hemminger   [NET] socket: cod...
873
  	msg->msg_iov = (struct iovec *)iov;
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
874
875
876
877
878
  	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...
879
880
  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...
881
882
  {
  	struct sock_iocb siocb, *x;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
883
884
  	if (pos != 0)
  		return -ESPIPE;
027445c37   Badari Pulavarty   [PATCH] Vectorize...
885

73a7075e3   Kent Overstreet   aio: Kill aio_rw_...
886
  	if (iocb->ki_nbytes == 0)	/* Match SYS5 behaviour */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
887
  		return 0;
027445c37   Badari Pulavarty   [PATCH] Vectorize...
888
889
  
  	x = alloc_sock_iocb(iocb, &siocb);
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
890
891
  	if (!x)
  		return -ENOMEM;
027445c37   Badari Pulavarty   [PATCH] Vectorize...
892
  	return do_sock_read(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
893
  }
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
894
  static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb,
027445c37   Badari Pulavarty   [PATCH] Vectorize...
895
896
  			struct file *file, const struct iovec *iov,
  			unsigned long nr_segs)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
897
  {
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
898
899
900
  	struct socket *sock = file->private_data;
  	size_t size = 0;
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
901

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

ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
905
906
907
908
  	msg->msg_name = NULL;
  	msg->msg_namelen = 0;
  	msg->msg_control = NULL;
  	msg->msg_controllen = 0;
89bddce58   Stephen Hemminger   [NET] socket: cod...
909
  	msg->msg_iov = (struct iovec *)iov;
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
910
911
912
913
  	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
914

ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
915
  	return __sock_sendmsg(iocb, sock, msg, size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
916
  }
027445c37   Badari Pulavarty   [PATCH] Vectorize...
917
918
  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...
919
920
  {
  	struct sock_iocb siocb, *x;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
921

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

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

027445c37   Badari Pulavarty   [PATCH] Vectorize...
929
  	return do_sock_write(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
930
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
931
932
933
934
  /*
   * Atomic setting of ioctl hooks to avoid race
   * with module unload.
   */
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
935
  static DEFINE_MUTEX(br_ioctl_mutex);
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
936
  static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
937

881d966b4   Eric W. Biederman   [NET]: Make the d...
938
  void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
939
  {
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
940
  	mutex_lock(&br_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
941
  	br_ioctl_hook = hook;
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
942
  	mutex_unlock(&br_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
943
944
  }
  EXPORT_SYMBOL(brioctl_set);
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
945
  static DEFINE_MUTEX(vlan_ioctl_mutex);
881d966b4   Eric W. Biederman   [NET]: Make the d...
946
  static int (*vlan_ioctl_hook) (struct net *, void __user *arg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
947

881d966b4   Eric W. Biederman   [NET]: Make the d...
948
  void vlan_ioctl_set(int (*hook) (struct net *, void __user *))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
949
  {
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
950
  	mutex_lock(&vlan_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
951
  	vlan_ioctl_hook = hook;
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
952
  	mutex_unlock(&vlan_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
953
954
  }
  EXPORT_SYMBOL(vlan_ioctl_set);
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
955
  static DEFINE_MUTEX(dlci_ioctl_mutex);
89bddce58   Stephen Hemminger   [NET] socket: cod...
956
  static int (*dlci_ioctl_hook) (unsigned int, void __user *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
957

89bddce58   Stephen Hemminger   [NET] socket: cod...
958
  void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
959
  {
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
960
  	mutex_lock(&dlci_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
961
  	dlci_ioctl_hook = hook;
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
962
  	mutex_unlock(&dlci_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
963
964
  }
  EXPORT_SYMBOL(dlci_ioctl_set);
6b96018b2   Arnd Bergmann   compat: move sock...
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
  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
982
983
984
985
986
987
988
989
  /*
   *	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...
990
  	struct sock *sk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
991
992
  	void __user *argp = (void __user *)arg;
  	int pid, err;
881d966b4   Eric W. Biederman   [NET]: Make the d...
993
  	struct net *net;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
994

b69aee04f   Eric Dumazet   [NET]: Use file->...
995
  	sock = file->private_data;
881d966b4   Eric W. Biederman   [NET]: Make the d...
996
  	sk = sock->sk;
3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
997
  	net = sock_net(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
998
  	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
881d966b4   Eric W. Biederman   [NET]: Make the d...
999
  		err = dev_ioctl(net, cmd, argp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1000
  	} else
3d23e349d   Johannes Berg   wext: refactor
1001
  #ifdef CONFIG_WEXT_CORE
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1002
  	if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
881d966b4   Eric W. Biederman   [NET]: Make the d...
1003
  		err = dev_ioctl(net, cmd, argp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1004
  	} else
3d23e349d   Johannes Berg   wext: refactor
1005
  #endif
89bddce58   Stephen Hemminger   [NET] socket: cod...
1006
  		switch (cmd) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1007
1008
1009
1010
1011
1012
1013
1014
1015
  		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...
1016
  			err = put_user(f_getown(sock->file),
89bddce58   Stephen Hemminger   [NET] socket: cod...
1017
  				       (int __user *)argp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1018
1019
1020
1021
1022
1023
1024
1025
  			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: ...
1026
  			mutex_lock(&br_ioctl_mutex);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1027
  			if (br_ioctl_hook)
881d966b4   Eric W. Biederman   [NET]: Make the d...
1028
  				err = br_ioctl_hook(net, cmd, argp);
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
1029
  			mutex_unlock(&br_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1030
1031
1032
1033
1034
1035
  			break;
  		case SIOCGIFVLAN:
  		case SIOCSIFVLAN:
  			err = -ENOPKG;
  			if (!vlan_ioctl_hook)
  				request_module("8021q");
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
1036
  			mutex_lock(&vlan_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1037
  			if (vlan_ioctl_hook)
881d966b4   Eric W. Biederman   [NET]: Make the d...
1038
  				err = vlan_ioctl_hook(net, argp);
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
1039
  			mutex_unlock(&vlan_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1040
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1041
1042
1043
1044
1045
  		case SIOCADDDLCI:
  		case SIOCDELDLCI:
  			err = -ENOPKG;
  			if (!dlci_ioctl_hook)
  				request_module("dlci");
7512cbf6e   Pavel Emelyanov   [DLCI]: Fix tiny ...
1046
1047
  			mutex_lock(&dlci_ioctl_mutex);
  			if (dlci_ioctl_hook)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1048
  				err = dlci_ioctl_hook(cmd, argp);
7512cbf6e   Pavel Emelyanov   [DLCI]: Fix tiny ...
1049
  			mutex_unlock(&dlci_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1050
1051
  			break;
  		default:
6b96018b2   Arnd Bergmann   compat: move sock...
1052
  			err = sock_do_ioctl(net, sock, cmd, arg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1053
  			break;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1054
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1055
1056
1057
1058
1059
1060
1061
  	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...
1062

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1063
1064
1065
1066
1067
1068
1069
1070
1071
  	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
1072
  	sock->type = type;
7420ed23a   Venkat Yekkirala   [NetLabel]: SELin...
1073
1074
1075
  	err = security_socket_post_create(sock, family, type, protocol, 1);
  	if (err)
  		goto out_release;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1076
1077
1078
  out:
  	*res = sock;
  	return err;
7420ed23a   Venkat Yekkirala   [NetLabel]: SELin...
1079
1080
1081
1082
  out_release:
  	sock_release(sock);
  	sock = NULL;
  	goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1083
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
1084
  EXPORT_SYMBOL(sock_create_lite);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1085
1086
  
  /* No kernel lock held - perfect */
89bddce58   Stephen Hemminger   [NET] socket: cod...
1087
  static unsigned int sock_poll(struct file *file, poll_table *wait)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1088
  {
cbf55001b   Eliezer Tamir   net: rename low l...
1089
  	unsigned int busy_flag = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1090
1091
1092
  	struct socket *sock;
  
  	/*
89bddce58   Stephen Hemminger   [NET] socket: cod...
1093
  	 *      We can't return errors to poll, so it's either yes or no.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1094
  	 */
b69aee04f   Eric Dumazet   [NET]: Use file->...
1095
  	sock = file->private_data;
2d48d67fa   Eliezer Tamir   net: poll/select ...
1096

cbf55001b   Eliezer Tamir   net: rename low l...
1097
  	if (sk_can_busy_loop(sock->sk)) {
2d48d67fa   Eliezer Tamir   net: poll/select ...
1098
  		/* this socket can poll_ll so tell the system call */
cbf55001b   Eliezer Tamir   net: rename low l...
1099
  		busy_flag = POLL_BUSY_LOOP;
2d48d67fa   Eliezer Tamir   net: poll/select ...
1100
1101
  
  		/* once, only if requested by syscall */
cbf55001b   Eliezer Tamir   net: rename low l...
1102
1103
  		if (wait && (wait->_key & POLL_BUSY_LOOP))
  			sk_busy_loop(sock->sk, 1);
2d48d67fa   Eliezer Tamir   net: poll/select ...
1104
  	}
cbf55001b   Eliezer Tamir   net: rename low l...
1105
  	return busy_flag | sock->ops->poll(file, sock, wait);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1106
  }
89bddce58   Stephen Hemminger   [NET] socket: cod...
1107
  static int sock_mmap(struct file *file, struct vm_area_struct *vma)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1108
  {
b69aee04f   Eric Dumazet   [NET]: Use file->...
1109
  	struct socket *sock = file->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1110
1111
1112
  
  	return sock->ops->mmap(file, sock, vma);
  }
20380731b   Arnaldo Carvalho de Melo   [NET]: Fix sparse...
1113
  static int sock_close(struct inode *inode, struct file *filp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1114
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
  	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...
1127
   *	   or under socket lock
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1128
1129
1130
1131
   */
  
  static int sock_fasync(int fd, struct file *filp, int on)
  {
989a29792   Eric Dumazet   fasync: RCU and f...
1132
1133
  	struct socket *sock = filp->private_data;
  	struct sock *sk = sock->sk;
eaefd1105   Eric Dumazet   net: add __rcu an...
1134
  	struct socket_wq *wq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1135

989a29792   Eric Dumazet   fasync: RCU and f...
1136
  	if (sk == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1137
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1138
1139
  
  	lock_sock(sk);
eaefd1105   Eric Dumazet   net: add __rcu an...
1140
1141
  	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
1142

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

989a29792   Eric Dumazet   fasync: RCU and f...
1148
  	release_sock(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1149
1150
  	return 0;
  }
438154823   Eric Dumazet   net: sock_def_rea...
1151
  /* This function may be called only under socket lock or callback_lock or rcu_lock */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1152
1153
1154
  
  int sock_wake_async(struct socket *sock, int how, int band)
  {
438154823   Eric Dumazet   net: sock_def_rea...
1155
1156
1157
1158
1159
1160
1161
1162
  	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
1163
  		return -1;
438154823   Eric Dumazet   net: sock_def_rea...
1164
  	}
89bddce58   Stephen Hemminger   [NET] socket: cod...
1165
  	switch (how) {
8d8ad9d7c   Pavel Emelyanov   [NET]: Name magic...
1166
  	case SOCK_WAKE_WAITD:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1167
1168
1169
  		if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
  			break;
  		goto call_kill;
8d8ad9d7c   Pavel Emelyanov   [NET]: Name magic...
1170
  	case SOCK_WAKE_SPACE:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1171
1172
1173
  		if (!test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags))
  			break;
  		/* fall through */
8d8ad9d7c   Pavel Emelyanov   [NET]: Name magic...
1174
  	case SOCK_WAKE_IO:
89bddce58   Stephen Hemminger   [NET] socket: cod...
1175
  call_kill:
438154823   Eric Dumazet   net: sock_def_rea...
1176
  		kill_fasync(&wq->fasync_list, SIGIO, band);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1177
  		break;
8d8ad9d7c   Pavel Emelyanov   [NET]: Name magic...
1178
  	case SOCK_WAKE_URG:
438154823   Eric Dumazet   net: sock_def_rea...
1179
  		kill_fasync(&wq->fasync_list, SIGURG, band);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1180
  	}
438154823   Eric Dumazet   net: sock_def_rea...
1181
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1182
1183
  	return 0;
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
1184
  EXPORT_SYMBOL(sock_wake_async);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1185

721db93a5   Pavel Emelyanov   net: Export __soc...
1186
  int __sock_create(struct net *net, int family, int type, int protocol,
89bddce58   Stephen Hemminger   [NET] socket: cod...
1187
  			 struct socket **res, int kern)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1188
1189
1190
  {
  	int err;
  	struct socket *sock;
55737fda0   Stephen Hemminger   [NET]: socket fam...
1191
  	const struct net_proto_family *pf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1192
1193
  
  	/*
89bddce58   Stephen Hemminger   [NET] socket: cod...
1194
  	 *      Check protocol is in range
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
  	 */
  	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...
1207
  		static int warned;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1208
1209
  		if (!warned) {
  			warned = 1;
3410f22ea   Yang Yingliang   socket: replace s...
1210
1211
1212
  			pr_info("%s uses obsolete (PF_INET,SOCK_PACKET)
  ",
  				current->comm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1213
1214
1215
1216
1217
1218
1219
  		}
  		family = PF_PACKET;
  	}
  
  	err = security_socket_create(family, type, protocol, kern);
  	if (err)
  		return err;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1220

55737fda0   Stephen Hemminger   [NET]: socket fam...
1221
1222
1223
1224
1225
1226
1227
  	/*
  	 *	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) {
e87cc4728   Joe Perches   net: Convert net_...
1228
1229
  		net_warn_ratelimited("socket: no more sockets
  ");
55737fda0   Stephen Hemminger   [NET]: socket fam...
1230
1231
1232
1233
1234
  		return -ENFILE;	/* Not exactly a match, but its the
  				   closest posix thing */
  	}
  
  	sock->type = type;
95a5afca4   Johannes Berg   net: Remove CONFI...
1235
  #ifdef CONFIG_MODULES
89bddce58   Stephen Hemminger   [NET] socket: cod...
1236
1237
1238
  	/* 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
1239
1240
1241
  	 * requested real, full-featured networking support upon configuration.
  	 * Otherwise module support will break!
  	 */
190683a9d   Eric Dumazet   net: net_families...
1242
  	if (rcu_access_pointer(net_families[family]) == NULL)
89bddce58   Stephen Hemminger   [NET] socket: cod...
1243
  		request_module("net-pf-%d", family);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1244
  #endif
55737fda0   Stephen Hemminger   [NET]: socket fam...
1245
1246
1247
1248
1249
  	rcu_read_lock();
  	pf = rcu_dereference(net_families[family]);
  	err = -EAFNOSUPPORT;
  	if (!pf)
  		goto out_release;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1250
1251
1252
1253
1254
  
  	/*
  	 * 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...
1255
  	if (!try_module_get(pf->owner))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1256
  		goto out_release;
55737fda0   Stephen Hemminger   [NET]: socket fam...
1257
1258
  	/* Now protected by module ref count */
  	rcu_read_unlock();
3f378b684   Eric Paris   net: pass kern to...
1259
  	err = pf->create(net, sock, protocol, kern);
55737fda0   Stephen Hemminger   [NET]: socket fam...
1260
  	if (err < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1261
  		goto out_module_put;
a79af59ef   Frank Filz   [NET]: Fix module...
1262

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1263
1264
1265
1266
  	/*
  	 * 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...
1267
1268
  	if (!try_module_get(sock->ops->owner))
  		goto out_module_busy;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1269
1270
1271
1272
  	/*
  	 * Now that we're done with the ->create function, the [loadable]
  	 * module can have its refcnt decremented
  	 */
55737fda0   Stephen Hemminger   [NET]: socket fam...
1273
  	module_put(pf->owner);
7420ed23a   Venkat Yekkirala   [NetLabel]: SELin...
1274
1275
  	err = security_socket_post_create(sock, family, type, protocol, kern);
  	if (err)
3b1855255   Herbert Xu   [NET]: Fix unbala...
1276
  		goto out_sock_release;
55737fda0   Stephen Hemminger   [NET]: socket fam...
1277
  	*res = sock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1278

55737fda0   Stephen Hemminger   [NET]: socket fam...
1279
1280
1281
1282
  	return 0;
  
  out_module_busy:
  	err = -EAFNOSUPPORT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1283
  out_module_put:
55737fda0   Stephen Hemminger   [NET]: socket fam...
1284
1285
1286
  	sock->ops = NULL;
  	module_put(pf->owner);
  out_sock_release:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1287
  	sock_release(sock);
55737fda0   Stephen Hemminger   [NET]: socket fam...
1288
1289
1290
1291
1292
  	return err;
  
  out_release:
  	rcu_read_unlock();
  	goto out_sock_release;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1293
  }
721db93a5   Pavel Emelyanov   net: Export __soc...
1294
  EXPORT_SYMBOL(__sock_create);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1295
1296
1297
  
  int sock_create(int family, int type, int protocol, struct socket **res)
  {
1b8d7ae42   Eric W. Biederman   [NET]: Make socke...
1298
  	return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1299
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
1300
  EXPORT_SYMBOL(sock_create);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1301
1302
1303
  
  int sock_create_kern(int family, int type, int protocol, struct socket **res)
  {
1b8d7ae42   Eric W. Biederman   [NET]: Make socke...
1304
  	return __sock_create(&init_net, family, type, protocol, res, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1305
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
1306
  EXPORT_SYMBOL(sock_create_kern);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1307

3e0fa65f8   Heiko Carstens   [CVE-2009-0029] S...
1308
  SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1309
1310
1311
  {
  	int retval;
  	struct socket *sock;
a677a039b   Ulrich Drepper   flag parameters: ...
1312
  	int flags;
e38b36f32   Ulrich Drepper   flag parameters: ...
1313
1314
1315
1316
1317
  	/* 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: ...
1318
  	flags = type & ~SOCK_TYPE_MASK;
77d272005   Ulrich Drepper   flag parameters: ...
1319
  	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
a677a039b   Ulrich Drepper   flag parameters: ...
1320
1321
  		return -EINVAL;
  	type &= SOCK_TYPE_MASK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1322

aaca0bdca   Ulrich Drepper   flag parameters: ...
1323
1324
  	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
  		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1325
1326
1327
  	retval = sock_create(family, type, protocol, &sock);
  	if (retval < 0)
  		goto out;
77d272005   Ulrich Drepper   flag parameters: ...
1328
  	retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
  	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...
1344
1345
  SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
  		int __user *, usockvec)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1346
1347
1348
  {
  	struct socket *sock1, *sock2;
  	int fd1, fd2, err;
db3495099   Al Viro   [PATCH] AUDIT_FD_...
1349
  	struct file *newfile1, *newfile2;
a677a039b   Ulrich Drepper   flag parameters: ...
1350
1351
1352
  	int flags;
  
  	flags = type & ~SOCK_TYPE_MASK;
77d272005   Ulrich Drepper   flag parameters: ...
1353
  	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
a677a039b   Ulrich Drepper   flag parameters: ...
1354
1355
  		return -EINVAL;
  	type &= SOCK_TYPE_MASK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1356

aaca0bdca   Ulrich Drepper   flag parameters: ...
1357
1358
  	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
  		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
  	/*
  	 * 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...
1373
  	if (err < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1374
  		goto out_release_both;
284076305   Al Viro   take descriptor h...
1375
  	fd1 = get_unused_fd_flags(flags);
bf3c23d17   David S. Miller   [NET]: Fix error ...
1376
1377
  	if (unlikely(fd1 < 0)) {
  		err = fd1;
db3495099   Al Viro   [PATCH] AUDIT_FD_...
1378
  		goto out_release_both;
bf3c23d17   David S. Miller   [NET]: Fix error ...
1379
  	}
d73aa2867   Yann Droneaud   net: handle error...
1380

284076305   Al Viro   take descriptor h...
1381
  	fd2 = get_unused_fd_flags(flags);
198de4d7a   Al Viro   reorder alloc_fd/...
1382
1383
  	if (unlikely(fd2 < 0)) {
  		err = fd2;
d73aa2867   Yann Droneaud   net: handle error...
1384
  		goto out_put_unused_1;
284076305   Al Viro   take descriptor h...
1385
  	}
aab174f0d   Linus Torvalds   Merge branch 'for...
1386
  	newfile1 = sock_alloc_file(sock1, flags, NULL);
284076305   Al Viro   take descriptor h...
1387
1388
  	if (unlikely(IS_ERR(newfile1))) {
  		err = PTR_ERR(newfile1);
d73aa2867   Yann Droneaud   net: handle error...
1389
  		goto out_put_unused_both;
284076305   Al Viro   take descriptor h...
1390
  	}
aab174f0d   Linus Torvalds   Merge branch 'for...
1391
  	newfile2 = sock_alloc_file(sock2, flags, NULL);
284076305   Al Viro   take descriptor h...
1392
1393
  	if (IS_ERR(newfile2)) {
  		err = PTR_ERR(newfile2);
d73aa2867   Yann Droneaud   net: handle error...
1394
  		goto out_fput_1;
db3495099   Al Viro   [PATCH] AUDIT_FD_...
1395
  	}
d73aa2867   Yann Droneaud   net: handle error...
1396
1397
1398
1399
1400
1401
1402
  	err = put_user(fd1, &usockvec[0]);
  	if (err)
  		goto out_fput_both;
  
  	err = put_user(fd2, &usockvec[1]);
  	if (err)
  		goto out_fput_both;
157cf649a   Al Viro   sanitize audit_fd...
1403
  	audit_fd_pair(fd1, fd2);
d73aa2867   Yann Droneaud   net: handle error...
1404

db3495099   Al Viro   [PATCH] AUDIT_FD_...
1405
1406
  	fd_install(fd1, newfile1);
  	fd_install(fd2, newfile2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1407
1408
1409
  	/* fd1 and fd2 may be already another descriptors.
  	 * Not kernel problem.
  	 */
d73aa2867   Yann Droneaud   net: handle error...
1410
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1411

d73aa2867   Yann Droneaud   net: handle error...
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
  out_fput_both:
  	fput(newfile2);
  	fput(newfile1);
  	put_unused_fd(fd2);
  	put_unused_fd(fd1);
  	goto out;
  
  out_fput_1:
  	fput(newfile1);
  	put_unused_fd(fd2);
  	put_unused_fd(fd1);
  	sock_release(sock2);
  	goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1425

d73aa2867   Yann Droneaud   net: handle error...
1426
1427
1428
1429
  out_put_unused_both:
  	put_unused_fd(fd2);
  out_put_unused_1:
  	put_unused_fd(fd1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1430
  out_release_both:
89bddce58   Stephen Hemminger   [NET] socket: cod...
1431
  	sock_release(sock2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1432
  out_release_1:
89bddce58   Stephen Hemminger   [NET] socket: cod...
1433
  	sock_release(sock1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1434
1435
1436
  out:
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1437
1438
1439
1440
1441
1442
1443
  /*
   *	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...
1444
  SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1445
1446
  {
  	struct socket *sock;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1447
  	struct sockaddr_storage address;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1448
  	int err, fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1449

89bddce58   Stephen Hemminger   [NET] socket: cod...
1450
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
e71a4783a   Stephen Hemminger   [NET] core: white...
1451
  	if (sock) {
43db362d3   Maciej Żenczykowski   net: get rid of s...
1452
  		err = move_addr_to_kernel(umyaddr, addrlen, &address);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1453
1454
  		if (err >= 0) {
  			err = security_socket_bind(sock,
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1455
  						   (struct sockaddr *)&address,
89bddce58   Stephen Hemminger   [NET] socket: cod...
1456
  						   addrlen);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1457
1458
  			if (!err)
  				err = sock->ops->bind(sock,
89bddce58   Stephen Hemminger   [NET] socket: cod...
1459
  						      (struct sockaddr *)
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1460
  						      &address, addrlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1461
  		}
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1462
  		fput_light(sock->file, fput_needed);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1463
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1464
1465
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1466
1467
1468
1469
1470
  /*
   *	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...
1471
  SYSCALL_DEFINE2(listen, int, fd, int, backlog)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1472
1473
  {
  	struct socket *sock;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1474
  	int err, fput_needed;
b8e1f9b5c   Pavel Emelyanov   [NET] sysctl: mak...
1475
  	int somaxconn;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1476
1477
1478
  
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
  	if (sock) {
8efa6e93c   Pavel Emelyanov   [NETNS]: Introduc...
1479
  		somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
95c961747   Eric Dumazet   net: cleanup unsi...
1480
  		if ((unsigned int)backlog > somaxconn)
b8e1f9b5c   Pavel Emelyanov   [NET] sysctl: mak...
1481
  			backlog = somaxconn;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1482
1483
  
  		err = security_socket_listen(sock, backlog);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1484
1485
  		if (!err)
  			err = sock->ops->listen(sock, backlog);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1486

6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1487
  		fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1488
1489
1490
  	}
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
  /*
   *	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...
1502
1503
  SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
  		int __user *, upeer_addrlen, int, flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1504
1505
  {
  	struct socket *sock, *newsock;
39d8c1b6f   David S. Miller   [NET]: Do not los...
1506
  	struct file *newfile;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1507
  	int err, len, newfd, fput_needed;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1508
  	struct sockaddr_storage address;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1509

77d272005   Ulrich Drepper   flag parameters: ...
1510
  	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
aaca0bdca   Ulrich Drepper   flag parameters: ...
1511
1512
1513
1514
  		return -EINVAL;
  
  	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
  		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1515
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1516
1517
1518
1519
  	if (!sock)
  		goto out;
  
  	err = -ENFILE;
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
1520
1521
  	newsock = sock_alloc();
  	if (!newsock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1522
1523
1524
1525
  		goto out_put;
  
  	newsock->type = sock->type;
  	newsock->ops = sock->ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1526
1527
1528
1529
1530
  	/*
  	 * 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);
284076305   Al Viro   take descriptor h...
1531
  	newfd = get_unused_fd_flags(flags);
39d8c1b6f   David S. Miller   [NET]: Do not los...
1532
1533
  	if (unlikely(newfd < 0)) {
  		err = newfd;
9a1875e60   David S. Miller   [NET]: Fully fix ...
1534
1535
  		sock_release(newsock);
  		goto out_put;
39d8c1b6f   David S. Miller   [NET]: Do not los...
1536
  	}
aab174f0d   Linus Torvalds   Merge branch 'for...
1537
  	newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name);
284076305   Al Viro   take descriptor h...
1538
1539
1540
1541
1542
1543
  	if (unlikely(IS_ERR(newfile))) {
  		err = PTR_ERR(newfile);
  		put_unused_fd(newfd);
  		sock_release(newsock);
  		goto out_put;
  	}
39d8c1b6f   David S. Miller   [NET]: Do not los...
1544

a79af59ef   Frank Filz   [NET]: Fix module...
1545
1546
  	err = security_socket_accept(sock, newsock);
  	if (err)
39d8c1b6f   David S. Miller   [NET]: Do not los...
1547
  		goto out_fd;
a79af59ef   Frank Filz   [NET]: Fix module...
1548

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1549
1550
  	err = sock->ops->accept(sock, newsock, sock->file->f_flags);
  	if (err < 0)
39d8c1b6f   David S. Miller   [NET]: Do not los...
1551
  		goto out_fd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1552
1553
  
  	if (upeer_sockaddr) {
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1554
  		if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
89bddce58   Stephen Hemminger   [NET] socket: cod...
1555
  					  &len, 2) < 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1556
  			err = -ECONNABORTED;
39d8c1b6f   David S. Miller   [NET]: Do not los...
1557
  			goto out_fd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1558
  		}
43db362d3   Maciej Żenczykowski   net: get rid of s...
1559
  		err = move_addr_to_user(&address,
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1560
  					len, upeer_sockaddr, upeer_addrlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1561
  		if (err < 0)
39d8c1b6f   David S. Miller   [NET]: Do not los...
1562
  			goto out_fd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1563
1564
1565
  	}
  
  	/* File flags are not inherited via accept() unlike another OSes. */
39d8c1b6f   David S. Miller   [NET]: Do not los...
1566
1567
  	fd_install(newfd, newfile);
  	err = newfd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1568

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1569
  out_put:
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1570
  	fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1571
1572
  out:
  	return err;
39d8c1b6f   David S. Miller   [NET]: Do not los...
1573
  out_fd:
9606a2163   David S. Miller   [NET]: Fix dentry...
1574
  	fput(newfile);
39d8c1b6f   David S. Miller   [NET]: Do not los...
1575
  	put_unused_fd(newfd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1576
1577
  	goto out_put;
  }
20f37034f   Heiko Carstens   [CVE-2009-0029] S...
1578
1579
  SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,
  		int __user *, upeer_addrlen)
aaca0bdca   Ulrich Drepper   flag parameters: ...
1580
  {
de11defeb   Ulrich Drepper   reintroduce accept4
1581
  	return sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0);
aaca0bdca   Ulrich Drepper   flag parameters: ...
1582
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
  /*
   *	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...
1594
1595
  SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
  		int, addrlen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1596
1597
  {
  	struct socket *sock;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1598
  	struct sockaddr_storage address;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1599
  	int err, fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1600

6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1601
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1602
1603
  	if (!sock)
  		goto out;
43db362d3   Maciej Żenczykowski   net: get rid of s...
1604
  	err = move_addr_to_kernel(uservaddr, addrlen, &address);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1605
1606
  	if (err < 0)
  		goto out_put;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1607
  	err =
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1608
  	    security_socket_connect(sock, (struct sockaddr *)&address, addrlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1609
1610
  	if (err)
  		goto out_put;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1611
  	err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1612
1613
  				 sock->file->f_flags);
  out_put:
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1614
  	fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1615
1616
1617
1618
1619
1620
1621
1622
  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...
1623
1624
  SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
  		int __user *, usockaddr_len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1625
1626
  {
  	struct socket *sock;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1627
  	struct sockaddr_storage address;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1628
  	int len, err, fput_needed;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1629

6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1630
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1631
1632
1633
1634
1635
1636
  	if (!sock)
  		goto out;
  
  	err = security_socket_getsockname(sock);
  	if (err)
  		goto out_put;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1637
  	err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1638
1639
  	if (err)
  		goto out_put;
43db362d3   Maciej Żenczykowski   net: get rid of s...
1640
  	err = move_addr_to_user(&address, len, usockaddr, usockaddr_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1641
1642
  
  out_put:
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1643
  	fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1644
1645
1646
1647
1648
1649
1650
1651
  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...
1652
1653
  SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
  		int __user *, usockaddr_len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1654
1655
  {
  	struct socket *sock;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1656
  	struct sockaddr_storage address;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1657
  	int len, err, fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1658

89bddce58   Stephen Hemminger   [NET] socket: cod...
1659
1660
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
  	if (sock != NULL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1661
1662
  		err = security_socket_getpeername(sock);
  		if (err) {
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1663
  			fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1664
1665
  			return err;
  		}
89bddce58   Stephen Hemminger   [NET] socket: cod...
1666
  		err =
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1667
  		    sock->ops->getname(sock, (struct sockaddr *)&address, &len,
89bddce58   Stephen Hemminger   [NET] socket: cod...
1668
  				       1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1669
  		if (!err)
43db362d3   Maciej Żenczykowski   net: get rid of s...
1670
  			err = move_addr_to_user(&address, len, usockaddr,
89bddce58   Stephen Hemminger   [NET] socket: cod...
1671
  						usockaddr_len);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1672
  		fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1673
1674
1675
1676
1677
1678
1679
1680
1681
  	}
  	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...
1682
  SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
95c961747   Eric Dumazet   net: cleanup unsi...
1683
  		unsigned int, flags, struct sockaddr __user *, addr,
3e0fa65f8   Heiko Carstens   [CVE-2009-0029] S...
1684
  		int, addr_len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1685
1686
  {
  	struct socket *sock;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1687
  	struct sockaddr_storage address;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1688
1689
1690
  	int err;
  	struct msghdr msg;
  	struct iovec iov;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1691
  	int fput_needed;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1692

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

89bddce58   Stephen Hemminger   [NET] socket: cod...
1699
1700
1701
1702
1703
1704
1705
1706
  	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...
1707
  	if (addr) {
43db362d3   Maciej Żenczykowski   net: get rid of s...
1708
  		err = move_addr_to_kernel(addr, addr_len, &address);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1709
1710
  		if (err < 0)
  			goto out_put;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1711
  		msg.msg_name = (struct sockaddr *)&address;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1712
  		msg.msg_namelen = addr_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1713
1714
1715
1716
1717
  	}
  	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...
1718
  out_put:
de0fa95c1   Pavel Emelyanov   [NET]: Use sockfd...
1719
  	fput_light(sock->file, fput_needed);
4387ff75f   David S. Miller   [NET]: Fix net/so...
1720
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1721
1722
1723
1724
  	return err;
  }
  
  /*
89bddce58   Stephen Hemminger   [NET] socket: cod...
1725
   *	Send a datagram down a socket.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1726
   */
3e0fa65f8   Heiko Carstens   [CVE-2009-0029] S...
1727
  SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len,
95c961747   Eric Dumazet   net: cleanup unsi...
1728
  		unsigned int, flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1729
1730
1731
1732
1733
  {
  	return sys_sendto(fd, buff, len, flags, NULL, 0);
  }
  
  /*
89bddce58   Stephen Hemminger   [NET] socket: cod...
1734
   *	Receive a frame from the socket and optionally record the address of the
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1735
1736
1737
   *	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...
1738
  SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
95c961747   Eric Dumazet   net: cleanup unsi...
1739
  		unsigned int, flags, struct sockaddr __user *, addr,
3e0fa65f8   Heiko Carstens   [CVE-2009-0029] S...
1740
  		int __user *, addr_len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1741
1742
1743
1744
  {
  	struct socket *sock;
  	struct iovec iov;
  	struct msghdr msg;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1745
  	struct sockaddr_storage address;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1746
  	int err, err2;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1747
  	int fput_needed;
253eacc07   Linus Torvalds   net: Truncate rec...
1748
1749
  	if (size > INT_MAX)
  		size = INT_MAX;
de0fa95c1   Pavel Emelyanov   [NET]: Use sockfd...
1750
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1751
  	if (!sock)
de0fa95c1   Pavel Emelyanov   [NET]: Use sockfd...
1752
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1753

89bddce58   Stephen Hemminger   [NET] socket: cod...
1754
1755
1756
1757
1758
1759
  	msg.msg_control = NULL;
  	msg.msg_controllen = 0;
  	msg.msg_iovlen = 1;
  	msg.msg_iov = &iov;
  	iov.iov_len = size;
  	iov.iov_base = ubuf;
f3d334260   Hannes Frederic Sowa   net: rework recvm...
1760
1761
1762
1763
  	/* Save some cycles and don't copy the address if not needed */
  	msg.msg_name = addr ? (struct sockaddr *)&address : NULL;
  	/* We assume all kernel code knows the size of sockaddr_storage */
  	msg.msg_namelen = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1764
1765
  	if (sock->file->f_flags & O_NONBLOCK)
  		flags |= MSG_DONTWAIT;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1766
  	err = sock_recvmsg(sock, &msg, size, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1767

89bddce58   Stephen Hemminger   [NET] socket: cod...
1768
  	if (err >= 0 && addr != NULL) {
43db362d3   Maciej Żenczykowski   net: get rid of s...
1769
  		err2 = move_addr_to_user(&address,
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1770
  					 msg.msg_namelen, addr, addr_len);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1771
1772
  		if (err2 < 0)
  			err = err2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1773
  	}
de0fa95c1   Pavel Emelyanov   [NET]: Use sockfd...
1774
1775
  
  	fput_light(sock->file, fput_needed);
4387ff75f   David S. Miller   [NET]: Fix net/so...
1776
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1777
1778
1779
1780
  	return err;
  }
  
  /*
89bddce58   Stephen Hemminger   [NET] socket: cod...
1781
   *	Receive a datagram from a socket.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1782
   */
b7c0ddf5f   Jan Glauber   net: use SYSCALL_...
1783
1784
  SYSCALL_DEFINE4(recv, int, fd, void __user *, ubuf, size_t, size,
  		unsigned int, flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1785
1786
1787
1788
1789
1790
1791
1792
  {
  	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...
1793
1794
  SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
  		char __user *, optval, int, optlen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1795
  {
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1796
  	int err, fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1797
1798
1799
1800
  	struct socket *sock;
  
  	if (optlen < 0)
  		return -EINVAL;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1801
1802
1803
1804
  
  	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...
1805
1806
  		if (err)
  			goto out_put;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1807
1808
  
  		if (level == SOL_SOCKET)
89bddce58   Stephen Hemminger   [NET] socket: cod...
1809
1810
1811
  			err =
  			    sock_setsockopt(sock, level, optname, optval,
  					    optlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1812
  		else
89bddce58   Stephen Hemminger   [NET] socket: cod...
1813
1814
1815
  			err =
  			    sock->ops->setsockopt(sock, level, optname, optval,
  						  optlen);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1816
1817
  out_put:
  		fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1818
1819
1820
1821
1822
1823
1824
1825
  	}
  	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...
1826
1827
  SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
  		char __user *, optval, int __user *, optlen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1828
  {
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1829
  	int err, fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1830
  	struct socket *sock;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1831
1832
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
  	if (sock != NULL) {
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1833
1834
1835
  		err = security_socket_getsockopt(sock, level, optname);
  		if (err)
  			goto out_put;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1836
1837
  
  		if (level == SOL_SOCKET)
89bddce58   Stephen Hemminger   [NET] socket: cod...
1838
1839
1840
  			err =
  			    sock_getsockopt(sock, level, optname, optval,
  					    optlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1841
  		else
89bddce58   Stephen Hemminger   [NET] socket: cod...
1842
1843
1844
  			err =
  			    sock->ops->getsockopt(sock, level, optname, optval,
  						  optlen);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1845
1846
  out_put:
  		fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1847
1848
1849
  	}
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1850
1851
1852
  /*
   *	Shutdown a socket.
   */
754fe8d29   Heiko Carstens   [CVE-2009-0029] S...
1853
  SYSCALL_DEFINE2(shutdown, int, fd, int, how)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1854
  {
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1855
  	int err, fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1856
  	struct socket *sock;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1857
1858
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
  	if (sock != NULL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1859
  		err = security_socket_shutdown(sock, how);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1860
1861
1862
  		if (!err)
  			err = sock->ops->shutdown(sock, how);
  		fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1863
1864
1865
  	}
  	return err;
  }
89bddce58   Stephen Hemminger   [NET] socket: cod...
1866
  /* A couple of helpful macros for getting the address of the 32/64 bit
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1867
1868
1869
1870
1871
   * 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...
1872
1873
1874
1875
  struct used_address {
  	struct sockaddr_storage name;
  	unsigned int name_len;
  };
1661bf364   Dan Carpenter   net: heap overflo...
1876
1877
1878
1879
1880
  static int copy_msghdr_from_user(struct msghdr *kmsg,
  				 struct msghdr __user *umsg)
  {
  	if (copy_from_user(kmsg, umsg, sizeof(struct msghdr)))
  		return -EFAULT;
dbb490b96   Matthew Leach   net: socket: erro...
1881
1882
1883
  
  	if (kmsg->msg_namelen < 0)
  		return -EINVAL;
1661bf364   Dan Carpenter   net: heap overflo...
1884
  	if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
db31c55a6   Dan Carpenter   net: clamp ->msg_...
1885
  		kmsg->msg_namelen = sizeof(struct sockaddr_storage);
1661bf364   Dan Carpenter   net: heap overflo...
1886
1887
  	return 0;
  }
a7526eb5d   Andy Lutomirski   net: Unbreak comp...
1888
  static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
95c961747   Eric Dumazet   net: cleanup unsi...
1889
  			 struct msghdr *msg_sys, unsigned int flags,
c71d8ebe7   Tetsuo Handa   net: Fix security...
1890
  			 struct used_address *used_address)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1891
  {
89bddce58   Stephen Hemminger   [NET] socket: cod...
1892
1893
  	struct compat_msghdr __user *msg_compat =
  	    (struct compat_msghdr __user *)msg;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1894
  	struct sockaddr_storage address;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1895
  	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
b9d717a7b   Alex Williamson   [NET]: Make sure ...
1896
  	unsigned char ctl[sizeof(struct cmsghdr) + 20]
89bddce58   Stephen Hemminger   [NET] socket: cod...
1897
1898
  	    __attribute__ ((aligned(sizeof(__kernel_size_t))));
  	/* 20 is size of ipv6_pktinfo */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1899
  	unsigned char *ctl_buf = ctl;
a74e91061   Eric Dumazet   net: change big i...
1900
  	int err, ctl_len, total_len;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1901

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1902
1903
  	err = -EFAULT;
  	if (MSG_CMSG_COMPAT & flags) {
228e548e6   Anton Blanchard   net: Add sendmmsg...
1904
  		if (get_compat_msghdr(msg_sys, msg_compat))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1905
  			return -EFAULT;
1661bf364   Dan Carpenter   net: heap overflo...
1906
1907
1908
1909
1910
  	} else {
  		err = copy_msghdr_from_user(msg_sys, msg);
  		if (err)
  			return err;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1911

228e548e6   Anton Blanchard   net: Add sendmmsg...
1912
  	if (msg_sys->msg_iovlen > UIO_FASTIOV) {
a74e91061   Eric Dumazet   net: change big i...
1913
1914
1915
1916
1917
1918
  		err = -EMSGSIZE;
  		if (msg_sys->msg_iovlen > UIO_MAXIOV)
  			goto out;
  		err = -ENOMEM;
  		iov = kmalloc(msg_sys->msg_iovlen * sizeof(struct iovec),
  			      GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1919
  		if (!iov)
228e548e6   Anton Blanchard   net: Add sendmmsg...
1920
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1921
1922
1923
1924
  	}
  
  	/* This will also move the address data into kernel space */
  	if (MSG_CMSG_COMPAT & flags) {
43db362d3   Maciej Żenczykowski   net: get rid of s...
1925
  		err = verify_compat_iovec(msg_sys, iov, &address, VERIFY_READ);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1926
  	} else
43db362d3   Maciej Żenczykowski   net: get rid of s...
1927
  		err = verify_iovec(msg_sys, iov, &address, VERIFY_READ);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1928
  	if (err < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1929
1930
1931
1932
  		goto out_freeiov;
  	total_len = err;
  
  	err = -ENOBUFS;
228e548e6   Anton Blanchard   net: Add sendmmsg...
1933
  	if (msg_sys->msg_controllen > INT_MAX)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1934
  		goto out_freeiov;
228e548e6   Anton Blanchard   net: Add sendmmsg...
1935
  	ctl_len = msg_sys->msg_controllen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1936
  	if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
89bddce58   Stephen Hemminger   [NET] socket: cod...
1937
  		err =
228e548e6   Anton Blanchard   net: Add sendmmsg...
1938
  		    cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl,
89bddce58   Stephen Hemminger   [NET] socket: cod...
1939
  						     sizeof(ctl));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1940
1941
  		if (err)
  			goto out_freeiov;
228e548e6   Anton Blanchard   net: Add sendmmsg...
1942
1943
  		ctl_buf = msg_sys->msg_control;
  		ctl_len = msg_sys->msg_controllen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1944
  	} else if (ctl_len) {
89bddce58   Stephen Hemminger   [NET] socket: cod...
1945
  		if (ctl_len > sizeof(ctl)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1946
  			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1947
  			if (ctl_buf == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1948
1949
1950
1951
  				goto out_freeiov;
  		}
  		err = -EFAULT;
  		/*
228e548e6   Anton Blanchard   net: Add sendmmsg...
1952
  		 * Careful! Before this, msg_sys->msg_control contains a user pointer.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1953
1954
1955
  		 * Afterwards, it will be a kernel pointer. Thus the compiler-assisted
  		 * checking falls down on this.
  		 */
fb8621bb6   Namhyung Kim   net: remove addre...
1956
  		if (copy_from_user(ctl_buf,
228e548e6   Anton Blanchard   net: Add sendmmsg...
1957
  				   (void __user __force *)msg_sys->msg_control,
89bddce58   Stephen Hemminger   [NET] socket: cod...
1958
  				   ctl_len))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1959
  			goto out_freectl;
228e548e6   Anton Blanchard   net: Add sendmmsg...
1960
  		msg_sys->msg_control = ctl_buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1961
  	}
228e548e6   Anton Blanchard   net: Add sendmmsg...
1962
  	msg_sys->msg_flags = flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1963
1964
  
  	if (sock->file->f_flags & O_NONBLOCK)
228e548e6   Anton Blanchard   net: Add sendmmsg...
1965
  		msg_sys->msg_flags |= MSG_DONTWAIT;
c71d8ebe7   Tetsuo Handa   net: Fix security...
1966
1967
1968
1969
1970
1971
  	/*
  	 * 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:...
1972
1973
1974
  	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...
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
  		    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:...
1986
1987
1988
  		if (msg_sys->msg_name)
  			memcpy(&used_address->name, msg_sys->msg_name,
  			       used_address->name_len);
c71d8ebe7   Tetsuo Handa   net: Fix security...
1989
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1990
1991
  
  out_freectl:
89bddce58   Stephen Hemminger   [NET] socket: cod...
1992
  	if (ctl_buf != ctl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1993
1994
1995
  		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
  out_freeiov:
  	if (iov != iovstack)
a74e91061   Eric Dumazet   net: change big i...
1996
  		kfree(iov);
228e548e6   Anton Blanchard   net: Add sendmmsg...
1997
1998
1999
2000
2001
2002
2003
  out:
  	return err;
  }
  
  /*
   *	BSD sendmsg interface
   */
a7526eb5d   Andy Lutomirski   net: Unbreak comp...
2004
  long __sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
228e548e6   Anton Blanchard   net: Add sendmmsg...
2005
2006
2007
  {
  	int fput_needed, err;
  	struct msghdr msg_sys;
1be374a05   Andy Lutomirski   net: Block MSG_CM...
2008
  	struct socket *sock;
1be374a05   Andy Lutomirski   net: Block MSG_CM...
2009
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
228e548e6   Anton Blanchard   net: Add sendmmsg...
2010
2011
  	if (!sock)
  		goto out;
a7526eb5d   Andy Lutomirski   net: Unbreak comp...
2012
  	err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL);
228e548e6   Anton Blanchard   net: Add sendmmsg...
2013

6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
2014
  	fput_light(sock->file, fput_needed);
89bddce58   Stephen Hemminger   [NET] socket: cod...
2015
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2016
2017
  	return err;
  }
a7526eb5d   Andy Lutomirski   net: Unbreak comp...
2018
2019
2020
2021
2022
2023
  SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned int, flags)
  {
  	if (flags & MSG_CMSG_COMPAT)
  		return -EINVAL;
  	return __sys_sendmsg(fd, msg, flags);
  }
228e548e6   Anton Blanchard   net: Add sendmmsg...
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
  /*
   *	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...
2036
  	struct used_address used_address;
228e548e6   Anton Blanchard   net: Add sendmmsg...
2037

98382f419   Anton Blanchard   net: Cap number o...
2038
2039
  	if (vlen > UIO_MAXIOV)
  		vlen = UIO_MAXIOV;
228e548e6   Anton Blanchard   net: Add sendmmsg...
2040
2041
2042
2043
2044
2045
  
  	datagrams = 0;
  
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
  	if (!sock)
  		return err;
c71d8ebe7   Tetsuo Handa   net: Fix security...
2046
  	used_address.name_len = UINT_MAX;
228e548e6   Anton Blanchard   net: Add sendmmsg...
2047
2048
  	entry = mmsg;
  	compat_entry = (struct compat_mmsghdr __user *)mmsg;
728ffb86f   Anton Blanchard   net: sendmmsg sho...
2049
  	err = 0;
228e548e6   Anton Blanchard   net: Add sendmmsg...
2050
2051
  
  	while (datagrams < vlen) {
228e548e6   Anton Blanchard   net: Add sendmmsg...
2052
  		if (MSG_CMSG_COMPAT & flags) {
a7526eb5d   Andy Lutomirski   net: Unbreak comp...
2053
2054
  			err = ___sys_sendmsg(sock, (struct msghdr __user *)compat_entry,
  					     &msg_sys, flags, &used_address);
228e548e6   Anton Blanchard   net: Add sendmmsg...
2055
2056
2057
2058
2059
  			if (err < 0)
  				break;
  			err = __put_user(err, &compat_entry->msg_len);
  			++compat_entry;
  		} else {
a7526eb5d   Andy Lutomirski   net: Unbreak comp...
2060
2061
2062
  			err = ___sys_sendmsg(sock,
  					     (struct msghdr __user *)entry,
  					     &msg_sys, flags, &used_address);
228e548e6   Anton Blanchard   net: Add sendmmsg...
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
  			if (err < 0)
  				break;
  			err = put_user(err, &entry->msg_len);
  			++entry;
  		}
  
  		if (err)
  			break;
  		++datagrams;
  	}
228e548e6   Anton Blanchard   net: Add sendmmsg...
2073
  	fput_light(sock->file, fput_needed);
728ffb86f   Anton Blanchard   net: sendmmsg sho...
2074
2075
  	/* We only return an error if no datagrams were able to be sent */
  	if (datagrams != 0)
228e548e6   Anton Blanchard   net: Add sendmmsg...
2076
  		return datagrams;
228e548e6   Anton Blanchard   net: Add sendmmsg...
2077
2078
2079
2080
2081
2082
  	return err;
  }
  
  SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
  		unsigned int, vlen, unsigned int, flags)
  {
1be374a05   Andy Lutomirski   net: Block MSG_CM...
2083
2084
  	if (flags & MSG_CMSG_COMPAT)
  		return -EINVAL;
228e548e6   Anton Blanchard   net: Add sendmmsg...
2085
2086
  	return __sys_sendmmsg(fd, mmsg, vlen, flags);
  }
a7526eb5d   Andy Lutomirski   net: Unbreak comp...
2087
  static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
95c961747   Eric Dumazet   net: cleanup unsi...
2088
  			 struct msghdr *msg_sys, unsigned int flags, int nosec)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2089
  {
89bddce58   Stephen Hemminger   [NET] socket: cod...
2090
2091
  	struct compat_msghdr __user *msg_compat =
  	    (struct compat_msghdr __user *)msg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2092
  	struct iovec iovstack[UIO_FASTIOV];
89bddce58   Stephen Hemminger   [NET] socket: cod...
2093
  	struct iovec *iov = iovstack;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2094
  	unsigned long cmsg_ptr;
a74e91061   Eric Dumazet   net: change big i...
2095
  	int err, total_len, len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2096
2097
  
  	/* kernel mode address */
230b18392   YOSHIFUJI Hideaki   net: Use standard...
2098
  	struct sockaddr_storage addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2099
2100
2101
2102
  
  	/* user mode address pointers */
  	struct sockaddr __user *uaddr;
  	int __user *uaddr_len;
89bddce58   Stephen Hemminger   [NET] socket: cod...
2103

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2104
  	if (MSG_CMSG_COMPAT & flags) {
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2105
  		if (get_compat_msghdr(msg_sys, msg_compat))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2106
  			return -EFAULT;
1661bf364   Dan Carpenter   net: heap overflo...
2107
2108
2109
2110
2111
  	} else {
  		err = copy_msghdr_from_user(msg_sys, msg);
  		if (err)
  			return err;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2112

a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2113
  	if (msg_sys->msg_iovlen > UIO_FASTIOV) {
a74e91061   Eric Dumazet   net: change big i...
2114
2115
2116
2117
2118
2119
  		err = -EMSGSIZE;
  		if (msg_sys->msg_iovlen > UIO_MAXIOV)
  			goto out;
  		err = -ENOMEM;
  		iov = kmalloc(msg_sys->msg_iovlen * sizeof(struct iovec),
  			      GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2120
  		if (!iov)
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2121
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2122
  	}
f3d334260   Hannes Frederic Sowa   net: rework recvm...
2123
2124
  	/* 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
2125
  	 */
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2126
  	uaddr = (__force void __user *)msg_sys->msg_name;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2127
  	uaddr_len = COMPAT_NAMELEN(msg);
f3d334260   Hannes Frederic Sowa   net: rework recvm...
2128
  	if (MSG_CMSG_COMPAT & flags)
43db362d3   Maciej Żenczykowski   net: get rid of s...
2129
  		err = verify_compat_iovec(msg_sys, iov, &addr, VERIFY_WRITE);
f3d334260   Hannes Frederic Sowa   net: rework recvm...
2130
  	else
43db362d3   Maciej Żenczykowski   net: get rid of s...
2131
  		err = verify_iovec(msg_sys, iov, &addr, VERIFY_WRITE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2132
2133
  	if (err < 0)
  		goto out_freeiov;
89bddce58   Stephen Hemminger   [NET] socket: cod...
2134
  	total_len = err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2135

a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2136
2137
  	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...
2138

f3d334260   Hannes Frederic Sowa   net: rework recvm...
2139
2140
  	/* We assume all kernel code knows the size of sockaddr_storage */
  	msg_sys->msg_namelen = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2141
2142
  	if (sock->file->f_flags & O_NONBLOCK)
  		flags |= MSG_DONTWAIT;
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2143
2144
  	err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys,
  							  total_len, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2145
2146
2147
2148
2149
  	if (err < 0)
  		goto out_freeiov;
  	len = err;
  
  	if (uaddr != NULL) {
43db362d3   Maciej Żenczykowski   net: get rid of s...
2150
  		err = move_addr_to_user(&addr,
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2151
  					msg_sys->msg_namelen, uaddr,
89bddce58   Stephen Hemminger   [NET] socket: cod...
2152
  					uaddr_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2153
2154
2155
  		if (err < 0)
  			goto out_freeiov;
  	}
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2156
  	err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
37f7f421c   David S. Miller   [NET]: Do not lea...
2157
  			 COMPAT_FLAGS(msg));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2158
2159
2160
  	if (err)
  		goto out_freeiov;
  	if (MSG_CMSG_COMPAT & flags)
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2161
  		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2162
2163
  				 &msg_compat->msg_controllen);
  	else
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2164
  		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2165
2166
2167
2168
2169
2170
2171
  				 &msg->msg_controllen);
  	if (err)
  		goto out_freeiov;
  	err = len;
  
  out_freeiov:
  	if (iov != iovstack)
a74e91061   Eric Dumazet   net: change big i...
2172
  		kfree(iov);
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2173
2174
2175
2176
2177
2178
2179
  out:
  	return err;
  }
  
  /*
   *	BSD recvmsg interface
   */
a7526eb5d   Andy Lutomirski   net: Unbreak comp...
2180
  long __sys_recvmsg(int fd, struct msghdr __user *msg, unsigned flags)
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2181
2182
2183
  {
  	int fput_needed, err;
  	struct msghdr msg_sys;
1be374a05   Andy Lutomirski   net: Block MSG_CM...
2184
  	struct socket *sock;
1be374a05   Andy Lutomirski   net: Block MSG_CM...
2185
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2186
2187
  	if (!sock)
  		goto out;
a7526eb5d   Andy Lutomirski   net: Unbreak comp...
2188
  	err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0);
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2189

6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
2190
  	fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2191
2192
2193
  out:
  	return err;
  }
a7526eb5d   Andy Lutomirski   net: Unbreak comp...
2194
2195
2196
2197
2198
2199
2200
  SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg,
  		unsigned int, flags)
  {
  	if (flags & MSG_CMSG_COMPAT)
  		return -EINVAL;
  	return __sys_recvmsg(fd, msg, flags);
  }
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
  /*
   *     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...
2211
  	struct compat_mmsghdr __user *compat_entry;
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
  	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...
2231
  	compat_entry = (struct compat_mmsghdr __user *)mmsg;
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2232
2233
2234
2235
2236
  
  	while (datagrams < vlen) {
  		/*
  		 * No need to ask LSM for more than the first datagram.
  		 */
d7256d0eb   Jean-Mickael Guerin   net: compat_mmsgh...
2237
  		if (MSG_CMSG_COMPAT & flags) {
a7526eb5d   Andy Lutomirski   net: Unbreak comp...
2238
2239
2240
  			err = ___sys_recvmsg(sock, (struct msghdr __user *)compat_entry,
  					     &msg_sys, flags & ~MSG_WAITFORONE,
  					     datagrams);
d7256d0eb   Jean-Mickael Guerin   net: compat_mmsgh...
2241
2242
2243
2244
2245
  			if (err < 0)
  				break;
  			err = __put_user(err, &compat_entry->msg_len);
  			++compat_entry;
  		} else {
a7526eb5d   Andy Lutomirski   net: Unbreak comp...
2246
2247
2248
2249
  			err = ___sys_recvmsg(sock,
  					     (struct msghdr __user *)entry,
  					     &msg_sys, flags & ~MSG_WAITFORONE,
  					     datagrams);
d7256d0eb   Jean-Mickael Guerin   net: compat_mmsgh...
2250
2251
2252
2253
2254
  			if (err < 0)
  				break;
  			err = put_user(err, &entry->msg_len);
  			++entry;
  		}
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2255
2256
  		if (err)
  			break;
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2257
  		++datagrams;
71c5c1595   Brandon L Black   net: Add MSG_WAIT...
2258
2259
2260
  		/* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
  		if (flags & MSG_WAITFORONE)
  			flags |= MSG_DONTWAIT;
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
  		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
2281

a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
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
  	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;
1be374a05   Andy Lutomirski   net: Block MSG_CM...
2312
2313
  	if (flags & MSG_CMSG_COMPAT)
  		return -EINVAL;
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
  	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
2330
2331
  /* Argument list sizes for sys_socketcall */
  #define AL(x) ((x) * sizeof(unsigned long))
228e548e6   Anton Blanchard   net: Add sendmmsg...
2332
  static const unsigned char nargs[21] = {
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
2333
2334
2335
  	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...
2336
  	AL(4), AL(5), AL(4)
89bddce58   Stephen Hemminger   [NET] socket: cod...
2337
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2338
2339
2340
  #undef AL
  
  /*
89bddce58   Stephen Hemminger   [NET] socket: cod...
2341
   *	System call vectors.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2342
2343
2344
   *
   *	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...
2345
   *  it is set by the callees.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2346
   */
3e0fa65f8   Heiko Carstens   [CVE-2009-0029] S...
2347
  SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2348
  {
2950fa9d3   Chen Gang   kernel: audit: be...
2349
  	unsigned long a[AUDITSC_ARGS];
89bddce58   Stephen Hemminger   [NET] socket: cod...
2350
  	unsigned long a0, a1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2351
  	int err;
47379052b   Arjan van de Ven   net: Add explicit...
2352
  	unsigned int len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2353

228e548e6   Anton Blanchard   net: Add sendmmsg...
2354
  	if (call < 1 || call > SYS_SENDMMSG)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2355
  		return -EINVAL;
47379052b   Arjan van de Ven   net: Add explicit...
2356
2357
2358
  	len = nargs[call];
  	if (len > sizeof(a))
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2359
  	/* copy_from_user should be SMP safe. */
47379052b   Arjan van de Ven   net: Add explicit...
2360
  	if (copy_from_user(a, args, len))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2361
  		return -EFAULT;
3ec3b2fba   David Woodhouse   AUDIT: Capture sy...
2362

2950fa9d3   Chen Gang   kernel: audit: be...
2363
2364
2365
  	err = audit_socketcall(nargs[call] / sizeof(unsigned long), a);
  	if (err)
  		return err;
3ec3b2fba   David Woodhouse   AUDIT: Capture sy...
2366

89bddce58   Stephen Hemminger   [NET] socket: cod...
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
  	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
2384
2385
  		err = sys_accept4(a0, (struct sockaddr __user *)a1,
  				  (int __user *)a[2], 0);
89bddce58   Stephen Hemminger   [NET] socket: cod...
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
  		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...
2429
2430
2431
  	case SYS_SENDMMSG:
  		err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]);
  		break;
89bddce58   Stephen Hemminger   [NET] socket: cod...
2432
2433
2434
  	case SYS_RECVMSG:
  		err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]);
  		break;
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2435
2436
2437
2438
  	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
2439
2440
2441
  	case SYS_ACCEPT4:
  		err = sys_accept4(a0, (struct sockaddr __user *)a1,
  				  (int __user *)a[2], a[3]);
aaca0bdca   Ulrich Drepper   flag parameters: ...
2442
  		break;
89bddce58   Stephen Hemminger   [NET] socket: cod...
2443
2444
2445
  	default:
  		err = -EINVAL;
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2446
2447
2448
  	}
  	return err;
  }
89bddce58   Stephen Hemminger   [NET] socket: cod...
2449
  #endif				/* __ARCH_WANT_SYS_SOCKETCALL */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2450

55737fda0   Stephen Hemminger   [NET]: socket fam...
2451
2452
2453
2454
  /**
   *	sock_register - add a socket protocol handler
   *	@ops: description of protocol
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2455
2456
   *	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...
2457
2458
   *	socket interface. The value ops->family coresponds to the
   *	socket system call protocol family.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2459
   */
f0fd27d42   Stephen Hemminger   [NET]: sock_regis...
2460
  int sock_register(const struct net_proto_family *ops)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2461
2462
2463
2464
  {
  	int err;
  
  	if (ops->family >= NPROTO) {
3410f22ea   Yang Yingliang   socket: replace s...
2465
2466
  		pr_crit("protocol %d >= NPROTO(%d)
  ", ops->family, NPROTO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2467
2468
  		return -ENOBUFS;
  	}
55737fda0   Stephen Hemminger   [NET]: socket fam...
2469
2470
  
  	spin_lock(&net_family_lock);
190683a9d   Eric Dumazet   net: net_families...
2471
2472
  	if (rcu_dereference_protected(net_families[ops->family],
  				      lockdep_is_held(&net_family_lock)))
55737fda0   Stephen Hemminger   [NET]: socket fam...
2473
2474
  		err = -EEXIST;
  	else {
cf778b00e   Eric Dumazet   net: reintroduce ...
2475
  		rcu_assign_pointer(net_families[ops->family], ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2476
2477
  		err = 0;
  	}
55737fda0   Stephen Hemminger   [NET]: socket fam...
2478
  	spin_unlock(&net_family_lock);
3410f22ea   Yang Yingliang   socket: replace s...
2479
2480
  	pr_info("NET: Registered protocol family %d
  ", ops->family);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2481
2482
  	return err;
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
2483
  EXPORT_SYMBOL(sock_register);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2484

55737fda0   Stephen Hemminger   [NET]: socket fam...
2485
2486
2487
2488
  /**
   *	sock_unregister - remove a protocol handler
   *	@family: protocol family to remove
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2489
2490
   *	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...
2491
2492
2493
2494
2495
2496
   *	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
2497
   */
f0fd27d42   Stephen Hemminger   [NET]: sock_regis...
2498
  void sock_unregister(int family)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2499
  {
f0fd27d42   Stephen Hemminger   [NET]: sock_regis...
2500
  	BUG_ON(family < 0 || family >= NPROTO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2501

55737fda0   Stephen Hemminger   [NET]: socket fam...
2502
  	spin_lock(&net_family_lock);
a9b3cd7f3   Stephen Hemminger   rcu: convert uses...
2503
  	RCU_INIT_POINTER(net_families[family], NULL);
55737fda0   Stephen Hemminger   [NET]: socket fam...
2504
2505
2506
  	spin_unlock(&net_family_lock);
  
  	synchronize_rcu();
3410f22ea   Yang Yingliang   socket: replace s...
2507
2508
  	pr_info("NET: Unregistered protocol family %d
  ", family);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2509
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
2510
  EXPORT_SYMBOL(sock_unregister);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2511

77d76ea31   Andi Kleen   [NET]: Small clea...
2512
  static int __init sock_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2513
  {
b3e19d924   Nick Piggin   fs: scale mntget/...
2514
  	int err;
2ca794e5e   Eric W. Biederman   net sysctl: Initi...
2515
2516
2517
2518
2519
2520
  	/*
  	 *      Initialize the network sysctl infrastructure.
  	 */
  	err = net_sysctl_init();
  	if (err)
  		goto out;
b3e19d924   Nick Piggin   fs: scale mntget/...
2521

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2522
  	/*
89bddce58   Stephen Hemminger   [NET] socket: cod...
2523
  	 *      Initialize skbuff SLAB cache
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2524
2525
  	 */
  	skb_init();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2526
2527
  
  	/*
89bddce58   Stephen Hemminger   [NET] socket: cod...
2528
  	 *      Initialize the protocols module.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2529
2530
2531
  	 */
  
  	init_inodecache();
b3e19d924   Nick Piggin   fs: scale mntget/...
2532
2533
2534
2535
  
  	err = register_filesystem(&sock_fs_type);
  	if (err)
  		goto out_fs;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2536
  	sock_mnt = kern_mount(&sock_fs_type);
b3e19d924   Nick Piggin   fs: scale mntget/...
2537
2538
2539
2540
  	if (IS_ERR(sock_mnt)) {
  		err = PTR_ERR(sock_mnt);
  		goto out_mount;
  	}
77d76ea31   Andi Kleen   [NET]: Small clea...
2541
2542
  
  	/* The real protocol initialization is performed in later initcalls.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2543
2544
2545
  	 */
  
  #ifdef CONFIG_NETFILTER
6d11cfdba   Pablo Neira Ayuso   netfilter: don't ...
2546
2547
2548
  	err = netfilter_init();
  	if (err)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2549
  #endif
cbeb321a6   David S. Miller   [NET]: Fix sock_i...
2550

408eccce3   Daniel Borkmann   net: ptp: move PT...
2551
  	ptp_classifier_init();
c1f19b51d   Richard Cochran   net: support time...
2552

b3e19d924   Nick Piggin   fs: scale mntget/...
2553
2554
2555
2556
2557
2558
2559
  out:
  	return err;
  
  out_mount:
  	unregister_filesystem(&sock_fs_type);
  out_fs:
  	goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2560
  }
77d76ea31   Andi Kleen   [NET]: Small clea...
2561
  core_initcall(sock_init);	/* early initcall */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2562
2563
2564
2565
2566
  #ifdef CONFIG_PROC_FS
  void socket_seq_show(struct seq_file *seq)
  {
  	int cpu;
  	int counter = 0;
6f9120422   KAMEZAWA Hiroyuki   [PATCH] for_each_...
2567
  	for_each_possible_cpu(cpu)
89bddce58   Stephen Hemminger   [NET] socket: cod...
2568
  	    counter += per_cpu(sockets_in_use, cpu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2569
2570
2571
2572
2573
2574
2575
2576
  
  	/* 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...
2577
  #endif				/* CONFIG_PROC_FS */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2578

89bbfc95d   Shaun Pereira   [NET]: allow 32 b...
2579
  #ifdef CONFIG_COMPAT
6b96018b2   Arnd Bergmann   compat: move sock...
2580
  static int do_siocgstamp(struct net *net, struct socket *sock,
644595f89   H. Peter Anvin   compat: Handle CO...
2581
  			 unsigned int cmd, void __user *up)
7a229387d   Arnd Bergmann   net: copy socket ...
2582
  {
7a229387d   Arnd Bergmann   net: copy socket ...
2583
2584
2585
2586
2587
  	mm_segment_t old_fs = get_fs();
  	struct timeval ktv;
  	int err;
  
  	set_fs(KERNEL_DS);
6b96018b2   Arnd Bergmann   compat: move sock...
2588
  	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv);
7a229387d   Arnd Bergmann   net: copy socket ...
2589
  	set_fs(old_fs);
644595f89   H. Peter Anvin   compat: Handle CO...
2590
  	if (!err)
ed6fe9d61   Mikulas Patocka   Fix order of argu...
2591
  		err = compat_put_timeval(&ktv, up);
644595f89   H. Peter Anvin   compat: Handle CO...
2592

7a229387d   Arnd Bergmann   net: copy socket ...
2593
2594
  	return err;
  }
6b96018b2   Arnd Bergmann   compat: move sock...
2595
  static int do_siocgstampns(struct net *net, struct socket *sock,
644595f89   H. Peter Anvin   compat: Handle CO...
2596
  			   unsigned int cmd, void __user *up)
7a229387d   Arnd Bergmann   net: copy socket ...
2597
  {
7a229387d   Arnd Bergmann   net: copy socket ...
2598
2599
2600
2601
2602
  	mm_segment_t old_fs = get_fs();
  	struct timespec kts;
  	int err;
  
  	set_fs(KERNEL_DS);
6b96018b2   Arnd Bergmann   compat: move sock...
2603
  	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts);
7a229387d   Arnd Bergmann   net: copy socket ...
2604
  	set_fs(old_fs);
644595f89   H. Peter Anvin   compat: Handle CO...
2605
  	if (!err)
ed6fe9d61   Mikulas Patocka   Fix order of argu...
2606
  		err = compat_put_timespec(&kts, up);
644595f89   H. Peter Anvin   compat: Handle CO...
2607

7a229387d   Arnd Bergmann   net: copy socket ...
2608
2609
  	return err;
  }
6b96018b2   Arnd Bergmann   compat: move sock...
2610
  static int dev_ifname32(struct net *net, struct compat_ifreq __user *uifr32)
7a229387d   Arnd Bergmann   net: copy socket ...
2611
2612
2613
2614
2615
  {
  	struct ifreq __user *uifr;
  	int err;
  
  	uifr = compat_alloc_user_space(sizeof(struct ifreq));
6b96018b2   Arnd Bergmann   compat: move sock...
2616
  	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
7a229387d   Arnd Bergmann   net: copy socket ...
2617
  		return -EFAULT;
6b96018b2   Arnd Bergmann   compat: move sock...
2618
  	err = dev_ioctl(net, SIOCGIFNAME, uifr);
7a229387d   Arnd Bergmann   net: copy socket ...
2619
2620
  	if (err)
  		return err;
6b96018b2   Arnd Bergmann   compat: move sock...
2621
  	if (copy_in_user(uifr32, uifr, sizeof(struct compat_ifreq)))
7a229387d   Arnd Bergmann   net: copy socket ...
2622
2623
2624
2625
  		return -EFAULT;
  
  	return 0;
  }
6b96018b2   Arnd Bergmann   compat: move sock...
2626
  static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32)
7a229387d   Arnd Bergmann   net: copy socket ...
2627
  {
6b96018b2   Arnd Bergmann   compat: move sock...
2628
  	struct compat_ifconf ifc32;
7a229387d   Arnd Bergmann   net: copy socket ...
2629
2630
  	struct ifconf ifc;
  	struct ifconf __user *uifc;
6b96018b2   Arnd Bergmann   compat: move sock...
2631
  	struct compat_ifreq __user *ifr32;
7a229387d   Arnd Bergmann   net: copy socket ...
2632
2633
2634
  	struct ifreq __user *ifr;
  	unsigned int i, j;
  	int err;
6b96018b2   Arnd Bergmann   compat: move sock...
2635
  	if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf)))
7a229387d   Arnd Bergmann   net: copy socket ...
2636
  		return -EFAULT;
43da5f2e0   Mathias Krause   net: fix info lea...
2637
  	memset(&ifc, 0, sizeof(ifc));
7a229387d   Arnd Bergmann   net: copy socket ...
2638
2639
2640
2641
2642
2643
  	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...
2644
2645
  		size_t len = ((ifc32.ifc_len / sizeof(struct compat_ifreq)) + 1) *
  			sizeof(struct ifreq);
7a229387d   Arnd Bergmann   net: copy socket ...
2646
2647
2648
2649
  		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...
2650
  		for (i = 0; i < ifc32.ifc_len; i += sizeof(struct compat_ifreq)) {
6b96018b2   Arnd Bergmann   compat: move sock...
2651
  			if (copy_in_user(ifr, ifr32, sizeof(struct compat_ifreq)))
7a229387d   Arnd Bergmann   net: copy socket ...
2652
2653
2654
2655
2656
2657
2658
  				return -EFAULT;
  			ifr++;
  			ifr32++;
  		}
  	}
  	if (copy_to_user(uifc, &ifc, sizeof(struct ifconf)))
  		return -EFAULT;
6b96018b2   Arnd Bergmann   compat: move sock...
2659
  	err = dev_ioctl(net, SIOCGIFCONF, uifc);
7a229387d   Arnd Bergmann   net: copy socket ...
2660
2661
2662
2663
2664
2665
2666
2667
2668
  	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...
2669
2670
2671
  	     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 ...
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
  			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...
2682
  		i = ((i / sizeof(struct ifreq)) * sizeof(struct compat_ifreq));
7a229387d   Arnd Bergmann   net: copy socket ...
2683
2684
2685
2686
  		ifc32.ifc_len = i;
  	} else {
  		ifc32.ifc_len = i;
  	}
6b96018b2   Arnd Bergmann   compat: move sock...
2687
  	if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf)))
7a229387d   Arnd Bergmann   net: copy socket ...
2688
2689
2690
2691
  		return -EFAULT;
  
  	return 0;
  }
6b96018b2   Arnd Bergmann   compat: move sock...
2692
  static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
7a229387d   Arnd Bergmann   net: copy socket ...
2693
  {
3a7da39d1   Ben Hutchings   ethtool: Compat h...
2694
2695
2696
2697
  	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 ...
2698
  	struct ifreq __user *ifr;
3a7da39d1   Ben Hutchings   ethtool: Compat h...
2699
2700
  	u32 rule_cnt = 0, actual_rule_cnt;
  	u32 ethcmd;
7a229387d   Arnd Bergmann   net: copy socket ...
2701
  	u32 data;
3a7da39d1   Ben Hutchings   ethtool: Compat h...
2702
  	int ret;
7a229387d   Arnd Bergmann   net: copy socket ...
2703

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

3a7da39d1   Ben Hutchings   ethtool: Compat h...
2707
2708
2709
  	compat_rxnfc = compat_ptr(data);
  
  	if (get_user(ethcmd, &compat_rxnfc->cmd))
7a229387d   Arnd Bergmann   net: copy socket ...
2710
  		return -EFAULT;
3a7da39d1   Ben Hutchings   ethtool: Compat h...
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
  	/* 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...
2728
  	case ETHTOOL_SRXCLSRLINS:
3a7da39d1   Ben Hutchings   ethtool: Compat h...
2729
2730
2731
  		convert_out = true;
  		/* fall through */
  	case ETHTOOL_SRXCLSRLDEL:
3a7da39d1   Ben Hutchings   ethtool: Compat h...
2732
2733
2734
2735
2736
2737
  		buf_size += sizeof(struct ethtool_rxnfc);
  		convert_in = true;
  		break;
  	}
  
  	ifr = compat_alloc_user_space(buf_size);
954b12445   Stephen Hemminger   ethtool: fix spar...
2738
  	rxnfc = (void __user *)ifr + ALIGN(sizeof(struct ifreq), 8);
3a7da39d1   Ben Hutchings   ethtool: Compat h...
2739
2740
  
  	if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
7a229387d   Arnd Bergmann   net: copy socket ...
2741
  		return -EFAULT;
3a7da39d1   Ben Hutchings   ethtool: Compat h...
2742
2743
  	if (put_user(convert_in ? rxnfc : compat_ptr(data),
  		     &ifr->ifr_ifru.ifru_data))
7a229387d   Arnd Bergmann   net: copy socket ...
2744
  		return -EFAULT;
3a7da39d1   Ben Hutchings   ethtool: Compat h...
2745
  	if (convert_in) {
127fe533a   Alexander Duyck   v3 ethtool: add n...
2746
  		/* We expect there to be holes between fs.m_ext and
3a7da39d1   Ben Hutchings   ethtool: Compat h...
2747
2748
  		 * fs.ring_cookie and at the end of fs, but nowhere else.
  		 */
127fe533a   Alexander Duyck   v3 ethtool: add n...
2749
2750
2751
2752
  		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...
2753
2754
2755
2756
2757
2758
2759
  		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,
954b12445   Stephen Hemminger   ethtool: fix spar...
2760
2761
  				 (void __user *)(&rxnfc->fs.m_ext + 1) -
  				 (void __user *)rxnfc) ||
3a7da39d1   Ben Hutchings   ethtool: Compat h...
2762
2763
  		    copy_in_user(&rxnfc->fs.ring_cookie,
  				 &compat_rxnfc->fs.ring_cookie,
954b12445   Stephen Hemminger   ethtool: fix spar...
2764
2765
  				 (void __user *)(&rxnfc->fs.location + 1) -
  				 (void __user *)&rxnfc->fs.ring_cookie) ||
3a7da39d1   Ben Hutchings   ethtool: Compat h...
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
  		    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,
954b12445   Stephen Hemminger   ethtool: fix spar...
2777
2778
  				 (const void __user *)(&rxnfc->fs.m_ext + 1) -
  				 (const void __user *)rxnfc) ||
3a7da39d1   Ben Hutchings   ethtool: Compat h...
2779
2780
  		    copy_in_user(&compat_rxnfc->fs.ring_cookie,
  				 &rxnfc->fs.ring_cookie,
954b12445   Stephen Hemminger   ethtool: fix spar...
2781
2782
  				 (const void __user *)(&rxnfc->fs.location + 1) -
  				 (const void __user *)&rxnfc->fs.ring_cookie) ||
3a7da39d1   Ben Hutchings   ethtool: Compat h...
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
  		    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 ...
2808
  }
7a50a240c   Arnd Bergmann   net/compat_ioctl:...
2809
2810
2811
2812
2813
  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...
2814
  	uifr = compat_alloc_user_space(sizeof(*uifr));
7a50a240c   Arnd Bergmann   net/compat_ioctl:...
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
  	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...
2828
2829
  static int bond_ioctl(struct net *net, unsigned int cmd,
  			 struct compat_ifreq __user *ifr32)
7a229387d   Arnd Bergmann   net: copy socket ...
2830
2831
  {
  	struct ifreq kifr;
7a229387d   Arnd Bergmann   net: copy socket ...
2832
2833
  	mm_segment_t old_fs;
  	int err;
7a229387d   Arnd Bergmann   net: copy socket ...
2834
2835
2836
2837
2838
2839
  
  	switch (cmd) {
  	case SIOCBONDENSLAVE:
  	case SIOCBONDRELEASE:
  	case SIOCBONDSETHWADDR:
  	case SIOCBONDCHANGEACTIVE:
6b96018b2   Arnd Bergmann   compat: move sock...
2840
  		if (copy_from_user(&kifr, ifr32, sizeof(struct compat_ifreq)))
7a229387d   Arnd Bergmann   net: copy socket ...
2841
2842
2843
  			return -EFAULT;
  
  		old_fs = get_fs();
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
2844
  		set_fs(KERNEL_DS);
c3f52ae6a   stephen hemminger   socket: suppress ...
2845
2846
  		err = dev_ioctl(net, cmd,
  				(struct ifreq __user __force *) &kifr);
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
2847
  		set_fs(old_fs);
7a229387d   Arnd Bergmann   net: copy socket ...
2848
2849
  
  		return err;
7a229387d   Arnd Bergmann   net: copy socket ...
2850
  	default:
07d106d0a   Linus Torvalds   vfs: fix up ENOIO...
2851
  		return -ENOIOCTLCMD;
ccbd6a5a4   Joe Perches   net: Remove unnec...
2852
  	}
7a229387d   Arnd Bergmann   net: copy socket ...
2853
  }
590d4693f   Ben Hutchings   net/compat: Merge...
2854
2855
  /* Handle ioctls that use ifreq::ifr_data and just need struct ifreq converted */
  static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd,
6b96018b2   Arnd Bergmann   compat: move sock...
2856
  				 struct compat_ifreq __user *u_ifreq32)
7a229387d   Arnd Bergmann   net: copy socket ...
2857
2858
  {
  	struct ifreq __user *u_ifreq64;
7a229387d   Arnd Bergmann   net: copy socket ...
2859
2860
2861
2862
2863
2864
2865
  	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;
417c3522b   Ben Hutchings   net/compat: Fix m...
2866
  	if (get_user(data32, &u_ifreq32->ifr_ifru.ifru_data))
7a229387d   Arnd Bergmann   net: copy socket ...
2867
2868
2869
2870
  		return -EFAULT;
  	data64 = compat_ptr(data32);
  
  	u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
7a229387d   Arnd Bergmann   net: copy socket ...
2871
2872
2873
  	if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0],
  			 IFNAMSIZ))
  		return -EFAULT;
417c3522b   Ben Hutchings   net/compat: Fix m...
2874
  	if (put_user(data64, &u_ifreq64->ifr_ifru.ifru_data))
7a229387d   Arnd Bergmann   net: copy socket ...
2875
  		return -EFAULT;
6b96018b2   Arnd Bergmann   compat: move sock...
2876
  	return dev_ioctl(net, cmd, u_ifreq64);
7a229387d   Arnd Bergmann   net: copy socket ...
2877
  }
6b96018b2   Arnd Bergmann   compat: move sock...
2878
2879
  static int dev_ifsioc(struct net *net, struct socket *sock,
  			 unsigned int cmd, struct compat_ifreq __user *uifr32)
7a229387d   Arnd Bergmann   net: copy socket ...
2880
  {
a2116ed22   Arnd Bergmann   net/compat: fix d...
2881
  	struct ifreq __user *uifr;
7a229387d   Arnd Bergmann   net: copy socket ...
2882
  	int err;
a2116ed22   Arnd Bergmann   net/compat: fix d...
2883
2884
2885
2886
2887
  	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 ...
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
  	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...
2900
  		case SIOCGIFPFLAGS:
7a229387d   Arnd Bergmann   net: copy socket ...
2901
  		case SIOCGIFTXQLEN:
fab2532ba   Arnd Bergmann   net, compat_ioctl...
2902
2903
  		case SIOCGMIIPHY:
  		case SIOCGMIIREG:
a2116ed22   Arnd Bergmann   net/compat: fix d...
2904
  			if (copy_in_user(uifr32, uifr, sizeof(*uifr32)))
7a229387d   Arnd Bergmann   net: copy socket ...
2905
2906
2907
2908
2909
2910
  				err = -EFAULT;
  			break;
  		}
  	}
  	return err;
  }
a2116ed22   Arnd Bergmann   net/compat: fix d...
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
  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));
3ddc5b46a   Mathieu Desnoyers   kernel-wide: fix ...
2921
2922
2923
2924
2925
2926
  	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);
a2116ed22   Arnd Bergmann   net/compat: fix d...
2927
2928
2929
2930
  	if (err)
  		return -EFAULT;
  
  	old_fs = get_fs();
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
2931
  	set_fs(KERNEL_DS);
c3f52ae6a   stephen hemminger   socket: suppress ...
2932
  	err = dev_ioctl(net, cmd, (void  __user __force *)&ifr);
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
2933
  	set_fs(old_fs);
a2116ed22   Arnd Bergmann   net/compat: fix d...
2934
2935
2936
  
  	if (cmd == SIOCGIFMAP && !err) {
  		err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name));
3ddc5b46a   Mathieu Desnoyers   kernel-wide: fix ...
2937
2938
2939
2940
2941
2942
  		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);
a2116ed22   Arnd Bergmann   net/compat: fix d...
2943
2944
2945
2946
2947
  		if (err)
  			err = -EFAULT;
  	}
  	return err;
  }
7a229387d   Arnd Bergmann   net: copy socket ...
2948
  struct rtentry32 {
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
2949
  	u32		rt_pad1;
7a229387d   Arnd Bergmann   net: copy socket ...
2950
2951
2952
  	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...
2953
2954
2955
2956
2957
2958
2959
  	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 ...
2960
  	/* char * */ u32 rt_dev;        /* forcing the device at add    */
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
2961
2962
  	u32		rt_mtu;         /* per route MTU/Window         */
  	u32		rt_window;      /* Window clamping              */
7a229387d   Arnd Bergmann   net: copy socket ...
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
  	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...
2978
2979
  static int routing_ioctl(struct net *net, struct socket *sock,
  			 unsigned int cmd, void __user *argp)
7a229387d   Arnd Bergmann   net: copy socket ...
2980
2981
2982
2983
2984
2985
2986
2987
  {
  	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...
2988
2989
  	if (sock && sock->sk && sock->sk->sk_family == AF_INET6) { /* ipv6 */
  		struct in6_rtmsg32 __user *ur6 = argp;
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
2990
  		ret = copy_from_user(&r6.rtmsg_dst, &(ur6->rtmsg_dst),
7a229387d   Arnd Bergmann   net: copy socket ...
2991
  			3 * sizeof(struct in6_addr));
3ddc5b46a   Mathieu Desnoyers   kernel-wide: fix ...
2992
2993
2994
2995
2996
2997
2998
  		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 ...
2999
3000
3001
  
  		r = (void *) &r6;
  	} else { /* ipv4 */
6b96018b2   Arnd Bergmann   compat: move sock...
3002
  		struct rtentry32 __user *ur4 = argp;
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
3003
  		ret = copy_from_user(&r4.rt_dst, &(ur4->rt_dst),
7a229387d   Arnd Bergmann   net: copy socket ...
3004
  					3 * sizeof(struct sockaddr));
3ddc5b46a   Mathieu Desnoyers   kernel-wide: fix ...
3005
3006
3007
3008
3009
3010
  		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 ...
3011
  		if (rtdev) {
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
3012
  			ret |= copy_from_user(devname, compat_ptr(rtdev), 15);
c3f52ae6a   stephen hemminger   socket: suppress ...
3013
3014
  			r4.rt_dev = (char __user __force *)devname;
  			devname[15] = 0;
7a229387d   Arnd Bergmann   net: copy socket ...
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
  		} else
  			r4.rt_dev = NULL;
  
  		r = (void *) &r4;
  	}
  
  	if (ret) {
  		ret = -EFAULT;
  		goto out;
  	}
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
3025
  	set_fs(KERNEL_DS);
6b96018b2   Arnd Bergmann   compat: move sock...
3026
  	ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r);
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
3027
  	set_fs(old_fs);
7a229387d   Arnd Bergmann   net: copy socket ...
3028
3029
  
  out:
7a229387d   Arnd Bergmann   net: copy socket ...
3030
3031
3032
3033
3034
  	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...
3035
   * use compatible ioctls
7a229387d   Arnd Bergmann   net: copy socket ...
3036
   */
6b96018b2   Arnd Bergmann   compat: move sock...
3037
  static int old_bridge_ioctl(compat_ulong_t __user *argp)
7a229387d   Arnd Bergmann   net: copy socket ...
3038
  {
6b96018b2   Arnd Bergmann   compat: move sock...
3039
  	compat_ulong_t tmp;
7a229387d   Arnd Bergmann   net: copy socket ...
3040

6b96018b2   Arnd Bergmann   compat: move sock...
3041
  	if (get_user(tmp, argp))
7a229387d   Arnd Bergmann   net: copy socket ...
3042
3043
3044
3045
3046
  		return -EFAULT;
  	if (tmp == BRCTL_GET_VERSION)
  		return BRCTL_VERSION + 1;
  	return -EINVAL;
  }
6b96018b2   Arnd Bergmann   compat: move sock...
3047
3048
3049
3050
3051
3052
  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 ...
3053

6b96018b2   Arnd Bergmann   compat: move sock...
3054
  	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
590d4693f   Ben Hutchings   net/compat: Merge...
3055
  		return compat_ifr_data_ioctl(net, cmd, argp);
6b96018b2   Arnd Bergmann   compat: move sock...
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
  
  	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:...
3067
3068
  	case SIOCWANDEV:
  		return compat_siocwandev(net, argp);
a2116ed22   Arnd Bergmann   net/compat: fix d...
3069
3070
3071
  	case SIOCGIFMAP:
  	case SIOCSIFMAP:
  		return compat_sioc_ifmap(net, cmd, argp);
6b96018b2   Arnd Bergmann   compat: move sock...
3072
3073
3074
  	case SIOCBONDENSLAVE:
  	case SIOCBONDRELEASE:
  	case SIOCBONDSETHWADDR:
6b96018b2   Arnd Bergmann   compat: move sock...
3075
3076
3077
3078
3079
3080
3081
3082
3083
  	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);
590d4693f   Ben Hutchings   net/compat: Merge...
3084
3085
  	case SIOCBONDSLAVEINFOQUERY:
  	case SIOCBONDINFOQUERY:
a2116ed22   Arnd Bergmann   net/compat: fix d...
3086
  	case SIOCSHWTSTAMP:
fd468c74b   Ben Hutchings   net_tstamp: Add S...
3087
  	case SIOCGHWTSTAMP:
590d4693f   Ben Hutchings   net/compat: Merge...
3088
  		return compat_ifr_data_ioctl(net, cmd, argp);
6b96018b2   Arnd Bergmann   compat: move sock...
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
  
  	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...
3115
3116
3117
  	case SIOCGIFADDR:
  	case SIOCSIFADDR:
  	case SIOCSIFHWBROADCAST:
6b96018b2   Arnd Bergmann   compat: move sock...
3118
  	case SIOCDIFADDR:
6b96018b2   Arnd Bergmann   compat: move sock...
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
  	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...
3131
3132
3133
3134
  	case SIOCSIFNAME:
  	case SIOCGMIIPHY:
  	case SIOCGMIIREG:
  	case SIOCSMIIREG:
6b96018b2   Arnd Bergmann   compat: move sock...
3135
  		return dev_ifsioc(net, sock, cmd, argp);
9177efd39   Arnd Bergmann   net, compat_ioctl...
3136

6b96018b2   Arnd Bergmann   compat: move sock...
3137
3138
3139
  	case SIOCSARP:
  	case SIOCGARP:
  	case SIOCDARP:
6b96018b2   Arnd Bergmann   compat: move sock...
3140
  	case SIOCATMARK:
9177efd39   Arnd Bergmann   net, compat_ioctl...
3141
3142
  		return sock_do_ioctl(net, sock, cmd, arg);
  	}
6b96018b2   Arnd Bergmann   compat: move sock...
3143
3144
  	return -ENOIOCTLCMD;
  }
7a229387d   Arnd Bergmann   net: copy socket ...
3145

95c961747   Eric Dumazet   net: cleanup unsi...
3146
  static long compat_sock_ioctl(struct file *file, unsigned int cmd,
89bddce58   Stephen Hemminger   [NET] socket: cod...
3147
  			      unsigned long arg)
89bbfc95d   Shaun Pereira   [NET]: allow 32 b...
3148
3149
3150
  {
  	struct socket *sock = file->private_data;
  	int ret = -ENOIOCTLCMD;
87de87d5e   David S. Miller   wext: Dispatch an...
3151
3152
3153
3154
3155
  	struct sock *sk;
  	struct net *net;
  
  	sk = sock->sk;
  	net = sock_net(sk);
89bbfc95d   Shaun Pereira   [NET]: allow 32 b...
3156
3157
3158
  
  	if (sock->ops->compat_ioctl)
  		ret = sock->ops->compat_ioctl(sock, cmd, arg);
87de87d5e   David S. Miller   wext: Dispatch an...
3159
3160
3161
  	if (ret == -ENOIOCTLCMD &&
  	    (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST))
  		ret = compat_wext_handle_ioctl(net, cmd, arg);
6b96018b2   Arnd Bergmann   compat: move sock...
3162
3163
  	if (ret == -ENOIOCTLCMD)
  		ret = compat_sock_ioctl_trans(file, sock, cmd, arg);
89bbfc95d   Shaun Pereira   [NET]: allow 32 b...
3164
3165
3166
  	return ret;
  }
  #endif
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3167
3168
3169
3170
  int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
  {
  	return sock->ops->bind(sock, addr, addrlen);
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
3171
  EXPORT_SYMBOL(kernel_bind);
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3172
3173
3174
3175
3176
  
  int kernel_listen(struct socket *sock, int backlog)
  {
  	return sock->ops->listen(sock, backlog);
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
3177
  EXPORT_SYMBOL(kernel_listen);
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
  
  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...
3192
  		*newsock = NULL;
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3193
3194
3195
3196
  		goto done;
  	}
  
  	(*newsock)->ops = sock->ops;
1b08534e5   Wei Yongjun   net: Fix module r...
3197
  	__module_get((*newsock)->ops->owner);
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3198
3199
3200
3201
  
  done:
  	return err;
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
3202
  EXPORT_SYMBOL(kernel_accept);
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3203
3204
  
  int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
4768fbcbc   YOSHIFUJI Hideaki   [NET]: Fix whites...
3205
  		   int flags)
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3206
3207
3208
  {
  	return sock->ops->connect(sock, addr, addrlen, flags);
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
3209
  EXPORT_SYMBOL(kernel_connect);
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3210
3211
3212
3213
3214
3215
  
  int kernel_getsockname(struct socket *sock, struct sockaddr *addr,
  			 int *addrlen)
  {
  	return sock->ops->getname(sock, addr, addrlen, 0);
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
3216
  EXPORT_SYMBOL(kernel_getsockname);
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3217
3218
3219
3220
3221
3222
  
  int kernel_getpeername(struct socket *sock, struct sockaddr *addr,
  			 int *addrlen)
  {
  	return sock->ops->getname(sock, addr, addrlen, 1);
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
3223
  EXPORT_SYMBOL(kernel_getpeername);
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3224
3225
3226
3227
3228
  
  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...
3229
3230
  	char __user *uoptval;
  	int __user *uoptlen;
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3231
  	int err;
fb8621bb6   Namhyung Kim   net: remove addre...
3232
3233
  	uoptval = (char __user __force *) optval;
  	uoptlen = (int __user __force *) optlen;
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3234
3235
  	set_fs(KERNEL_DS);
  	if (level == SOL_SOCKET)
fb8621bb6   Namhyung Kim   net: remove addre...
3236
  		err = sock_getsockopt(sock, level, optname, uoptval, uoptlen);
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3237
  	else
fb8621bb6   Namhyung Kim   net: remove addre...
3238
3239
  		err = sock->ops->getsockopt(sock, level, optname, uoptval,
  					    uoptlen);
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3240
3241
3242
  	set_fs(oldfs);
  	return err;
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
3243
  EXPORT_SYMBOL(kernel_getsockopt);
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3244
3245
  
  int kernel_setsockopt(struct socket *sock, int level, int optname,
b7058842c   David S. Miller   net: Make setsock...
3246
  			char *optval, unsigned int optlen)
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3247
3248
  {
  	mm_segment_t oldfs = get_fs();
fb8621bb6   Namhyung Kim   net: remove addre...
3249
  	char __user *uoptval;
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3250
  	int err;
fb8621bb6   Namhyung Kim   net: remove addre...
3251
  	uoptval = (char __user __force *) optval;
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3252
3253
  	set_fs(KERNEL_DS);
  	if (level == SOL_SOCKET)
fb8621bb6   Namhyung Kim   net: remove addre...
3254
  		err = sock_setsockopt(sock, level, optname, uoptval, optlen);
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3255
  	else
fb8621bb6   Namhyung Kim   net: remove addre...
3256
  		err = sock->ops->setsockopt(sock, level, optname, uoptval,
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3257
3258
3259
3260
  					    optlen);
  	set_fs(oldfs);
  	return err;
  }
c6d409cfd   Eric Dumazet   From abbffa2aa9bd...
3261
  EXPORT_SYMBOL(kernel_setsockopt);
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3262
3263
3264
3265
3266
3267
3268
3269
3270
  
  int kernel_sendpage(struct socket *sock, struct page *page, int offset,
  		    size_t size, int flags)
  {
  	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...
3271
  EXPORT_SYMBOL(kernel_sendpage);
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
  
  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...
3284
  EXPORT_SYMBOL(kernel_sock_ioctl);
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
3285

91cf45f02   Trond Myklebust   [NET]: Add the he...
3286
3287
3288
3289
  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...
3290
  EXPORT_SYMBOL(kernel_sock_shutdown);