Blame view

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
126
127
128
  /*
   *	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...
129
  static const struct file_operations socket_file_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
130
131
132
133
134
135
  	.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...
136
137
138
  #ifdef CONFIG_COMPAT
  	.compat_ioctl = compat_sock_ioctl,
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
140
141
142
  	.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...
143
144
  	.sendpage =	sock_sendpage,
  	.splice_write = generic_splice_sendpage,
9c55e01c0   Jens Axboe   [TCP]: Splice rec...
145
  	.splice_read =	sock_splice_read,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146
147
148
149
150
  };
  
  /*
   *	The protocol list. Each protocol is registered in here.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151
  static DEFINE_SPINLOCK(net_family_lock);
f0fd27d42   Stephen Hemminger   [NET]: sock_regis...
152
  static const struct net_proto_family *net_families[NPROTO] __read_mostly;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
155
156
157
158
159
160
  /*
   *	Statistics counters of the socket lists
   */
  
  static DEFINE_PER_CPU(int, sockets_in_use) = 0;
  
  /*
89bddce58   Stephen Hemminger   [NET] socket: cod...
161
162
163
   * 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
164
   */
89bddce58   Stephen Hemminger   [NET] socket: cod...
165
  #define MAX_SOCK_ADDR	128		/* 108 for Unix domain -
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
166
167
  					   16 for IP, 16 for IPX,
  					   24 for IPv6,
89bddce58   Stephen Hemminger   [NET] socket: cod...
168
  					   about 80 for AX.25
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
169
170
  					   must be at least one bigger than
  					   the AF_UNIX size (see net/unix/af_unix.c
89bddce58   Stephen Hemminger   [NET] socket: cod...
171
  					   :unix_mkname()).
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
  					 */
89bddce58   Stephen Hemminger   [NET] socket: cod...
173

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174
175
176
177
178
179
180
181
182
183
  /**
   *	move_addr_to_kernel	-	copy a socket address into kernel space
   *	@uaddr: Address in user space
   *	@kaddr: Address in kernel space
   *	@ulen: Length in user space
   *
   *	The address is copied into kernel space. If the provided address is
   *	too long an error code of -EINVAL is returned. If the copy gives
   *	invalid addresses -EFAULT is returned. On a success 0 is returned.
   */
230b18392   YOSHIFUJI Hideaki   net: Use standard...
184
  int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr *kaddr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185
  {
230b18392   YOSHIFUJI Hideaki   net: Use standard...
186
  	if (ulen < 0 || ulen > sizeof(struct sockaddr_storage))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
  		return -EINVAL;
89bddce58   Stephen Hemminger   [NET] socket: cod...
188
  	if (ulen == 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189
  		return 0;
89bddce58   Stephen Hemminger   [NET] socket: cod...
190
  	if (copy_from_user(kaddr, uaddr, ulen))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
191
  		return -EFAULT;
3ec3b2fba   David Woodhouse   AUDIT: Capture sy...
192
  	return audit_sockaddr(ulen, kaddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
  }
  
  /**
   *	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...
211

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

e94b17660   Christoph Lameter   [PATCH] slab: rem...
242
  	ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
244
245
  	if (!ei)
  		return NULL;
  	init_waitqueue_head(&ei->socket.wait);
89bddce58   Stephen Hemminger   [NET] socket: cod...
246

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
248
249
250
251
252
  	ei->socket.fasync_list = NULL;
  	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
253
254
255
256
257
258
259
260
261
  
  	return &ei->vfs_inode;
  }
  
  static void sock_destroy_inode(struct inode *inode)
  {
  	kmem_cache_free(sock_inode_cachep,
  			container_of(inode, struct socket_alloc, vfs_inode));
  }
51cc50685   Alexey Dobriyan   SL*B: drop kmem c...
262
  static void init_once(void *foo)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263
  {
89bddce58   Stephen Hemminger   [NET] socket: cod...
264
  	struct socket_alloc *ei = (struct socket_alloc *)foo;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
270
271
  static int init_inodecache(void)
  {
  	sock_inode_cachep = kmem_cache_create("sock_inode_cache",
89bddce58   Stephen Hemminger   [NET] socket: cod...
272
273
274
275
276
  					      sizeof(struct socket_alloc),
  					      0,
  					      (SLAB_HWCACHE_ALIGN |
  					       SLAB_RECLAIM_ACCOUNT |
  					       SLAB_MEM_SPREAD),
20c2df83d   Paul Mundt   mm: Remove slab d...
277
  					      init_once);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
278
279
280
281
  	if (sock_inode_cachep == NULL)
  		return -ENOMEM;
  	return 0;
  }
b87221de6   Alexey Dobriyan   const: mark remai...
282
  static const struct super_operations sockfs_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283
284
285
286
  	.alloc_inode =	sock_alloc_inode,
  	.destroy_inode =sock_destroy_inode,
  	.statfs =	simple_statfs,
  };
454e2398b   David Howells   [PATCH] VFS: Perm...
287
  static int sockfs_get_sb(struct file_system_type *fs_type,
89bddce58   Stephen Hemminger   [NET] socket: cod...
288
289
  			 int flags, const char *dev_name, void *data,
  			 struct vfsmount *mnt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
290
  {
454e2398b   David Howells   [PATCH] VFS: Perm...
291
292
  	return get_sb_pseudo(fs_type, "socket:", &sockfs_ops, SOCKFS_MAGIC,
  			     mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293
  }
ba89966c1   Eric Dumazet   [NET]: use __read...
294
  static struct vfsmount *sock_mnt __read_mostly;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295
296
297
298
299
300
  
  static struct file_system_type sock_fs_type = {
  	.name =		"sockfs",
  	.get_sb =	sockfs_get_sb,
  	.kill_sb =	kill_anon_super,
  };
89bddce58   Stephen Hemminger   [NET] socket: cod...
301

c23fbb6bc   Eric Dumazet   VFS: delay the de...
302
303
304
305
306
307
308
309
  /*
   * 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...
310
  static const struct dentry_operations sockfs_dentry_operations = {
c23fbb6bc   Eric Dumazet   VFS: delay the de...
311
  	.d_dname  = sockfs_dname,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
312
313
314
315
316
  };
  
  /*
   *	Obtains the first available file descriptor and sets it up for use.
   *
39d8c1b6f   David S. Miller   [NET]: Do not los...
317
318
   *	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
319
320
321
322
323
324
325
326
327
328
329
   *	and file struct implicitly stored in sock->file.
   *	Note that another thread may close file descriptor before we return
   *	from this function. We use the fact that now we do not refer
   *	to socket after mapping. If one day we will need it, this
   *	function will increment ref. count on file by 1.
   *
   *	In any case returned fd MAY BE not valid!
   *	This race condition is unavoidable
   *	with shared fd spaces, we cannot solve it inside kernel,
   *	but we take care of internal coherence yet.
   */
7cbe66b6b   Al Viro   merge sock_alloc_...
330
  static int sock_alloc_file(struct socket *sock, struct file **f, int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
331
  {
7cbe66b6b   Al Viro   merge sock_alloc_...
332
  	struct qstr name = { .name = "" };
2c48b9c45   Al Viro   switch alloc_file...
333
  	struct path path;
7cbe66b6b   Al Viro   merge sock_alloc_...
334
  	struct file *file;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335
  	int fd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
336

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

2c48b9c45   Al Viro   switch alloc_file...
341
342
  	path.dentry = d_alloc(sock_mnt->mnt_sb->s_root, &name);
  	if (unlikely(!path.dentry)) {
7cbe66b6b   Al Viro   merge sock_alloc_...
343
  		put_unused_fd(fd);
39d8c1b6f   David S. Miller   [NET]: Do not los...
344
  		return -ENOMEM;
7cbe66b6b   Al Viro   merge sock_alloc_...
345
  	}
2c48b9c45   Al Viro   switch alloc_file...
346
  	path.mnt = mntget(sock_mnt);
39d8c1b6f   David S. Miller   [NET]: Do not los...
347

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

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

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

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
378
379
  	return fd;
  }
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
380
381
  static struct socket *sock_from_file(struct file *file, int *err)
  {
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
382
383
  	if (file->f_op == &socket_file_ops)
  		return file->private_data;	/* set in sock_map_fd */
23bb80d21   Eric Dumazet   [NET]: cleanup so...
384
385
  	*err = -ENOTSOCK;
  	return NULL;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
386
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
  /**
   *	sockfd_lookup	- 	Go from a file number to its socket slot
   *	@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
403
  	struct socket *sock;
89bddce58   Stephen Hemminger   [NET] socket: cod...
404
405
  	file = fget(fd);
  	if (!file) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
406
407
408
  		*err = -EBADF;
  		return NULL;
  	}
89bddce58   Stephen Hemminger   [NET] socket: cod...
409

6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
410
411
  	sock = sock_from_file(file, err);
  	if (!sock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
412
  		fput(file);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
413
414
  	return sock;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
415

6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
416
417
418
419
  static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
  {
  	struct file *file;
  	struct socket *sock;
3672558c6   Hua Zhong   [NET]: sockfd_loo...
420
  	*err = -EBADF;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
421
422
423
424
425
426
  	file = fget_light(fd, fput_needed);
  	if (file) {
  		sock = sock_from_file(file, err);
  		if (sock)
  			return sock;
  		fput_light(file, *fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
427
  	}
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
428
  	return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
429
430
431
432
  }
  
  /**
   *	sock_alloc	-	allocate a socket
89bddce58   Stephen Hemminger   [NET] socket: cod...
433
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
434
435
436
437
438
439
440
   *	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...
441
442
  	struct inode *inode;
  	struct socket *sock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
443
444
445
446
447
448
  
  	inode = new_inode(sock_mnt->mnt_sb);
  	if (!inode)
  		return NULL;
  
  	sock = SOCKET_I(inode);
29a020d35   Eric Dumazet   [PATCH] net: kmem...
449
  	kmemcheck_annotate_bitfield(sock, type);
89bddce58   Stephen Hemminger   [NET] socket: cod...
450
  	inode->i_mode = S_IFSOCK | S_IRWXUGO;
8192b0c48   David Howells   CRED: Wrap task c...
451
452
  	inode->i_uid = current_fsuid();
  	inode->i_gid = current_fsgid();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
453

4e69489a0   Eric Dumazet   socket: use percp...
454
  	percpu_add(sockets_in_use, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
455
456
457
458
459
460
461
462
  	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...
463

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
464
465
466
467
  static int sock_no_open(struct inode *irrelevant, struct file *dontcare)
  {
  	return -ENXIO;
  }
4b6f5d20b   Arjan van de Ven   [PATCH] Make most...
468
  const struct file_operations bad_sock_fops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
469
470
471
472
473
474
475
476
477
478
  	.owner = THIS_MODULE,
  	.open = sock_no_open,
  };
  
  /**
   *	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...
479
   *	an inode not a file.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
480
   */
89bddce58   Stephen Hemminger   [NET] socket: cod...
481

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
482
483
484
485
486
487
488
489
490
491
492
493
494
  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);
  	}
  
  	if (sock->fasync_list)
  		printk(KERN_ERR "sock_release: fasync list not empty!
  ");
4e69489a0   Eric Dumazet   socket: use percp...
495
  	percpu_sub(sockets_in_use, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
496
497
498
499
  	if (!sock->file) {
  		iput(SOCK_INODE(sock));
  		return;
  	}
89bddce58   Stephen Hemminger   [NET] socket: cod...
500
  	sock->file = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
501
  }
20d494735   Patrick Ohly   net: socket infra...
502
503
504
505
506
507
508
509
510
511
512
  int sock_tx_timestamp(struct msghdr *msg, struct sock *sk,
  		      union skb_shared_tx *shtx)
  {
  	shtx->flags = 0;
  	if (sock_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE))
  		shtx->hardware = 1;
  	if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE))
  		shtx->software = 1;
  	return 0;
  }
  EXPORT_SYMBOL(sock_tx_timestamp);
89bddce58   Stephen Hemminger   [NET] socket: cod...
513
  static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
  				 struct msghdr *msg, size_t size)
  {
  	struct sock_iocb *si = kiocb_to_siocb(iocb);
  	int err;
  
  	si->sock = sock;
  	si->scm = NULL;
  	si->msg = msg;
  	si->size = size;
  
  	err = security_socket_sendmsg(sock, msg, size);
  	if (err)
  		return err;
  
  	return sock->ops->sendmsg(iocb, sock, msg, size);
  }
  
  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;
  }
  
  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...
556
  	msg->msg_iov = (struct iovec *)vec;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
557
558
559
560
561
  	msg->msg_iovlen = num;
  	result = sock_sendmsg(sock, msg, size);
  	set_fs(oldfs);
  	return result;
  }
20d494735   Patrick Ohly   net: socket infra...
562
563
564
565
566
567
568
569
570
  static int ktime2ts(ktime_t kt, struct timespec *ts)
  {
  	if (kt.tv64) {
  		*ts = ktime_to_timespec(kt);
  		return 1;
  	} else {
  		return 0;
  	}
  }
92f37fd2e   Eric Dumazet   [NET]: Adding SO_...
571
572
573
574
575
576
  /*
   * 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...
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
  	int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
  	struct timespec ts[3];
  	int empty = 1;
  	struct skb_shared_hwtstamps *shhwtstamps =
  		skb_hwtstamps(skb);
  
  	/* Race occurred between timestamp enabling and packet
  	   receiving.  Fill in the current time for now. */
  	if (need_software_tstamp && skb->tstamp.tv64 == 0)
  		__net_timestamp(skb);
  
  	if (need_software_tstamp) {
  		if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
  			struct timeval tv;
  			skb_get_timestamp(skb, &tv);
  			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP,
  				 sizeof(tv), &tv);
  		} else {
  			struct timespec ts;
  			skb_get_timestampns(skb, &ts);
  			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS,
  				 sizeof(ts), &ts);
  		}
  	}
  
  
  	memset(ts, 0, sizeof(ts));
  	if (skb->tstamp.tv64 &&
  	    sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE)) {
  		skb_get_timestampns(skb, ts + 0);
  		empty = 0;
  	}
  	if (shhwtstamps) {
  		if (sock_flag(sk, SOCK_TIMESTAMPING_SYS_HARDWARE) &&
  		    ktime2ts(shhwtstamps->syststamp, ts + 1))
  			empty = 0;
  		if (sock_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE) &&
  		    ktime2ts(shhwtstamps->hwtstamp, ts + 2))
  			empty = 0;
92f37fd2e   Eric Dumazet   [NET]: Adding SO_...
616
  	}
20d494735   Patrick Ohly   net: socket infra...
617
618
619
  	if (!empty)
  		put_cmsg(msg, SOL_SOCKET,
  			 SCM_TIMESTAMPING, sizeof(ts), &ts);
92f37fd2e   Eric Dumazet   [NET]: Adding SO_...
620
  }
7c81fd8bf   Arnaldo Carvalho de Melo   [SOCKET]: Export ...
621
  EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
3b885787e   Neil Horman   net: Generalize s...
622
623
624
625
626
627
628
629
630
631
632
633
634
635
  inline void sock_recv_drops(struct msghdr *msg, struct sock *sk, struct sk_buff *skb)
  {
  	if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && skb->dropcount)
  		put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL,
  			sizeof(__u32), &skb->dropcount);
  }
  
  void sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
  	struct sk_buff *skb)
  {
  	sock_recv_timestamp(msg, sk, skb);
  	sock_recv_drops(msg, sk, skb);
  }
  EXPORT_SYMBOL_GPL(sock_recv_ts_and_drops);
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
636
637
  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
638
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
639
640
641
642
643
644
645
  	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
646
647
  	return sock->ops->recvmsg(iocb, sock, msg, size, flags);
  }
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
648
649
650
651
652
653
654
  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...
655
  int sock_recvmsg(struct socket *sock, struct msghdr *msg,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
656
657
658
659
660
  		 size_t size, int flags)
  {
  	struct kiocb iocb;
  	struct sock_iocb siocb;
  	int ret;
89bddce58   Stephen Hemminger   [NET] socket: cod...
661
  	init_sync_kiocb(&iocb, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
662
663
664
665
666
667
  	iocb.private = &siocb;
  	ret = __sock_recvmsg(&iocb, sock, msg, size, flags);
  	if (-EIOCBQUEUED == ret)
  		ret = wait_on_sync_kiocb(&iocb);
  	return ret;
  }
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
668
669
670
671
672
673
674
675
676
677
678
679
680
681
  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;
  }
89bddce58   Stephen Hemminger   [NET] socket: cod...
682
683
  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
684
685
686
687
688
689
690
691
692
  {
  	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...
693
  	msg->msg_iov = (struct iovec *)vec, msg->msg_iovlen = num;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
694
695
696
697
698
699
700
701
702
  	result = sock_recvmsg(sock, msg, size, flags);
  	set_fs(oldfs);
  	return result;
  }
  
  static void sock_aio_dtor(struct kiocb *iocb)
  {
  	kfree(iocb->private);
  }
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
703
704
  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
705
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
706
707
  	struct socket *sock;
  	int flags;
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
708
709
710
711
712
  	sock = file->private_data;
  
  	flags = !(file->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT;
  	if (more)
  		flags |= MSG_MORE;
e69495838   Linus Torvalds   Make sock_sendpag...
713
  	return kernel_sendpage(sock, page, offset, size, flags);
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
714
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
715

9c55e01c0   Jens Axboe   [TCP]: Splice rec...
716
717
718
719
720
  static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
  			        struct pipe_inode_info *pipe, size_t len,
  				unsigned int flags)
  {
  	struct socket *sock = file->private_data;
997b37da1   Rémi Denis-Courmont   [NET]: Make sure ...
721
722
  	if (unlikely(!sock->ops->splice_read))
  		return -EINVAL;
9c55e01c0   Jens Axboe   [TCP]: Splice rec...
723
724
  	return sock->ops->splice_read(sock, ppos, pipe, len, flags);
  }
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
725
  static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
89bddce58   Stephen Hemminger   [NET] socket: cod...
726
  					 struct sock_iocb *siocb)
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
727
728
729
730
731
  {
  	if (!is_sync_kiocb(iocb)) {
  		siocb = kmalloc(sizeof(*siocb), GFP_KERNEL);
  		if (!siocb)
  			return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
732
733
  		iocb->ki_dtor = sock_aio_dtor;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
734

ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
735
  	siocb->kiocb = iocb;
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
736
737
  	iocb->private = siocb;
  	return siocb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
738
  }
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
739
  static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb,
027445c37   Badari Pulavarty   [PATCH] Vectorize...
740
741
  		struct file *file, const struct iovec *iov,
  		unsigned long nr_segs)
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
742
743
744
745
  {
  	struct socket *sock = file->private_data;
  	size_t size = 0;
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
746

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

ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
750
751
752
753
  	msg->msg_name = NULL;
  	msg->msg_namelen = 0;
  	msg->msg_control = NULL;
  	msg->msg_controllen = 0;
89bddce58   Stephen Hemminger   [NET] socket: cod...
754
  	msg->msg_iov = (struct iovec *)iov;
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
755
756
757
758
759
  	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...
760
761
  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...
762
763
  {
  	struct sock_iocb siocb, *x;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
764
765
  	if (pos != 0)
  		return -ESPIPE;
027445c37   Badari Pulavarty   [PATCH] Vectorize...
766
767
  
  	if (iocb->ki_left == 0)	/* Match SYS5 behaviour */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
768
  		return 0;
027445c37   Badari Pulavarty   [PATCH] Vectorize...
769
770
  
  	x = alloc_sock_iocb(iocb, &siocb);
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
771
772
  	if (!x)
  		return -ENOMEM;
027445c37   Badari Pulavarty   [PATCH] Vectorize...
773
  	return do_sock_read(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
774
  }
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
775
  static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb,
027445c37   Badari Pulavarty   [PATCH] Vectorize...
776
777
  			struct file *file, const struct iovec *iov,
  			unsigned long nr_segs)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
778
  {
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
779
780
781
  	struct socket *sock = file->private_data;
  	size_t size = 0;
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
782

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

ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
786
787
788
789
  	msg->msg_name = NULL;
  	msg->msg_namelen = 0;
  	msg->msg_control = NULL;
  	msg->msg_controllen = 0;
89bddce58   Stephen Hemminger   [NET] socket: cod...
790
  	msg->msg_iov = (struct iovec *)iov;
ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
791
792
793
794
  	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
795

ce1d4d3e8   Christoph Hellwig   [NET]: restructur...
796
  	return __sock_sendmsg(iocb, sock, msg, size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
797
  }
027445c37   Badari Pulavarty   [PATCH] Vectorize...
798
799
  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...
800
801
  {
  	struct sock_iocb siocb, *x;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
802

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

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

027445c37   Badari Pulavarty   [PATCH] Vectorize...
810
  	return do_sock_write(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
811
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
812
813
814
815
  /*
   * Atomic setting of ioctl hooks to avoid race
   * with module unload.
   */
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
816
  static DEFINE_MUTEX(br_ioctl_mutex);
881d966b4   Eric W. Biederman   [NET]: Make the d...
817
  static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg) = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
818

881d966b4   Eric W. Biederman   [NET]: Make the d...
819
  void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
820
  {
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
821
  	mutex_lock(&br_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
822
  	br_ioctl_hook = hook;
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
823
  	mutex_unlock(&br_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
824
  }
89bddce58   Stephen Hemminger   [NET] socket: cod...
825

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
826
  EXPORT_SYMBOL(brioctl_set);
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
827
  static DEFINE_MUTEX(vlan_ioctl_mutex);
881d966b4   Eric W. Biederman   [NET]: Make the d...
828
  static int (*vlan_ioctl_hook) (struct net *, void __user *arg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
829

881d966b4   Eric W. Biederman   [NET]: Make the d...
830
  void vlan_ioctl_set(int (*hook) (struct net *, void __user *))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
831
  {
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
832
  	mutex_lock(&vlan_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
833
  	vlan_ioctl_hook = hook;
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
834
  	mutex_unlock(&vlan_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
835
  }
89bddce58   Stephen Hemminger   [NET] socket: cod...
836

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
837
  EXPORT_SYMBOL(vlan_ioctl_set);
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
838
  static DEFINE_MUTEX(dlci_ioctl_mutex);
89bddce58   Stephen Hemminger   [NET] socket: cod...
839
  static int (*dlci_ioctl_hook) (unsigned int, void __user *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
840

89bddce58   Stephen Hemminger   [NET] socket: cod...
841
  void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
842
  {
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
843
  	mutex_lock(&dlci_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
844
  	dlci_ioctl_hook = hook;
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
845
  	mutex_unlock(&dlci_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
846
  }
89bddce58   Stephen Hemminger   [NET] socket: cod...
847

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
848
  EXPORT_SYMBOL(dlci_ioctl_set);
6b96018b2   Arnd Bergmann   compat: move sock...
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
  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
866
867
868
869
870
871
872
873
  /*
   *	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...
874
  	struct sock *sk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
875
876
  	void __user *argp = (void __user *)arg;
  	int pid, err;
881d966b4   Eric W. Biederman   [NET]: Make the d...
877
  	struct net *net;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
878

b69aee04f   Eric Dumazet   [NET]: Use file->...
879
  	sock = file->private_data;
881d966b4   Eric W. Biederman   [NET]: Make the d...
880
  	sk = sock->sk;
3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
881
  	net = sock_net(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
882
  	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
881d966b4   Eric W. Biederman   [NET]: Make the d...
883
  		err = dev_ioctl(net, cmd, argp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
884
  	} else
3d23e349d   Johannes Berg   wext: refactor
885
  #ifdef CONFIG_WEXT_CORE
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
886
  	if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
881d966b4   Eric W. Biederman   [NET]: Make the d...
887
  		err = dev_ioctl(net, cmd, argp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
888
  	} else
3d23e349d   Johannes Berg   wext: refactor
889
  #endif
89bddce58   Stephen Hemminger   [NET] socket: cod...
890
  		switch (cmd) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
891
892
893
894
895
896
897
898
899
  		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...
900
  			err = put_user(f_getown(sock->file),
89bddce58   Stephen Hemminger   [NET] socket: cod...
901
  				       (int __user *)argp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
902
903
904
905
906
907
908
909
  			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: ...
910
  			mutex_lock(&br_ioctl_mutex);
89bddce58   Stephen Hemminger   [NET] socket: cod...
911
  			if (br_ioctl_hook)
881d966b4   Eric W. Biederman   [NET]: Make the d...
912
  				err = br_ioctl_hook(net, cmd, argp);
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
913
  			mutex_unlock(&br_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
914
915
916
917
918
919
  			break;
  		case SIOCGIFVLAN:
  		case SIOCSIFVLAN:
  			err = -ENOPKG;
  			if (!vlan_ioctl_hook)
  				request_module("8021q");
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
920
  			mutex_lock(&vlan_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
921
  			if (vlan_ioctl_hook)
881d966b4   Eric W. Biederman   [NET]: Make the d...
922
  				err = vlan_ioctl_hook(net, argp);
4a3e2f711   Arjan van de Ven   [NET] sem2mutex: ...
923
  			mutex_unlock(&vlan_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
924
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
925
926
927
928
929
  		case SIOCADDDLCI:
  		case SIOCDELDLCI:
  			err = -ENOPKG;
  			if (!dlci_ioctl_hook)
  				request_module("dlci");
7512cbf6e   Pavel Emelyanov   [DLCI]: Fix tiny ...
930
931
  			mutex_lock(&dlci_ioctl_mutex);
  			if (dlci_ioctl_hook)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
932
  				err = dlci_ioctl_hook(cmd, argp);
7512cbf6e   Pavel Emelyanov   [DLCI]: Fix tiny ...
933
  			mutex_unlock(&dlci_ioctl_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
934
935
  			break;
  		default:
6b96018b2   Arnd Bergmann   compat: move sock...
936
  			err = sock_do_ioctl(net, sock, cmd, arg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
937
  			break;
89bddce58   Stephen Hemminger   [NET] socket: cod...
938
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
939
940
941
942
943
944
945
  	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...
946

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
947
948
949
950
951
952
953
954
955
  	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
956
  	sock->type = type;
7420ed23a   Venkat Yekkirala   [NetLabel]: SELin...
957
958
959
  	err = security_socket_post_create(sock, family, type, protocol, 1);
  	if (err)
  		goto out_release;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
960
961
962
  out:
  	*res = sock;
  	return err;
7420ed23a   Venkat Yekkirala   [NetLabel]: SELin...
963
964
965
966
  out_release:
  	sock_release(sock);
  	sock = NULL;
  	goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
967
968
969
  }
  
  /* No kernel lock held - perfect */
89bddce58   Stephen Hemminger   [NET] socket: cod...
970
  static unsigned int sock_poll(struct file *file, poll_table *wait)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
971
972
973
974
  {
  	struct socket *sock;
  
  	/*
89bddce58   Stephen Hemminger   [NET] socket: cod...
975
  	 *      We can't return errors to poll, so it's either yes or no.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
976
  	 */
b69aee04f   Eric Dumazet   [NET]: Use file->...
977
  	sock = file->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
978
979
  	return sock->ops->poll(file, sock, wait);
  }
89bddce58   Stephen Hemminger   [NET] socket: cod...
980
  static int sock_mmap(struct file *file, struct vm_area_struct *vma)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
981
  {
b69aee04f   Eric Dumazet   [NET]: Use file->...
982
  	struct socket *sock = file->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
983
984
985
  
  	return sock->ops->mmap(file, sock, vma);
  }
20380731b   Arnaldo Carvalho de Melo   [NET]: Fix sparse...
986
  static int sock_close(struct inode *inode, struct file *filp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
987
988
  {
  	/*
89bddce58   Stephen Hemminger   [NET] socket: cod...
989
990
  	 *      It was possible the inode is NULL we were
  	 *      closing an unfinished socket.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
991
  	 */
89bddce58   Stephen Hemminger   [NET] socket: cod...
992
  	if (!inode) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
993
994
995
996
  		printk(KERN_DEBUG "sock_close: NULL inode
  ");
  		return 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
  	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)
   *	   or under socket lock.
   *	3. fasync_list can be used from softirq context, so that
   *	   modification under socket lock have to be enhanced with
   *	   write_lock_bh(&sk->sk_callback_lock).
   *							--ANK (990710)
   */
  
  static int sock_fasync(int fd, struct file *filp, int on)
  {
89bddce58   Stephen Hemminger   [NET] socket: cod...
1018
  	struct fasync_struct *fa, *fna = NULL, **prev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1019
1020
  	struct socket *sock;
  	struct sock *sk;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1021
  	if (on) {
8b3a70058   Kris Katterjohn   [NET]: Remove mor...
1022
  		fna = kmalloc(sizeof(struct fasync_struct), GFP_KERNEL);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1023
  		if (fna == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1024
1025
  			return -ENOMEM;
  	}
b69aee04f   Eric Dumazet   [NET]: Use file->...
1026
  	sock = filp->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1027

89bddce58   Stephen Hemminger   [NET] socket: cod...
1028
1029
  	sk = sock->sk;
  	if (sk == NULL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1030
1031
1032
1033
1034
  		kfree(fna);
  		return -EINVAL;
  	}
  
  	lock_sock(sk);
76398425b   Jonathan Corbet   Move FASYNC bit h...
1035
1036
1037
1038
1039
1040
  	spin_lock(&filp->f_lock);
  	if (on)
  		filp->f_flags |= FASYNC;
  	else
  		filp->f_flags &= ~FASYNC;
  	spin_unlock(&filp->f_lock);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1041
  	prev = &(sock->fasync_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1042

89bddce58   Stephen Hemminger   [NET] socket: cod...
1043
1044
  	for (fa = *prev; fa != NULL; prev = &fa->fa_next, fa = *prev)
  		if (fa->fa_file == filp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1045
  			break;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1046
1047
  	if (on) {
  		if (fa != NULL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1048
  			write_lock_bh(&sk->sk_callback_lock);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1049
  			fa->fa_fd = fd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1050
1051
1052
1053
1054
  			write_unlock_bh(&sk->sk_callback_lock);
  
  			kfree(fna);
  			goto out;
  		}
89bddce58   Stephen Hemminger   [NET] socket: cod...
1055
1056
1057
1058
  		fna->fa_file = filp;
  		fna->fa_fd = fd;
  		fna->magic = FASYNC_MAGIC;
  		fna->fa_next = sock->fasync_list;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1059
  		write_lock_bh(&sk->sk_callback_lock);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1060
  		sock->fasync_list = fna;
bcdce7195   Eric Dumazet   net: speedup sk_w...
1061
  		sock_set_flag(sk, SOCK_FASYNC);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1062
  		write_unlock_bh(&sk->sk_callback_lock);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1063
1064
  	} else {
  		if (fa != NULL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1065
  			write_lock_bh(&sk->sk_callback_lock);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1066
  			*prev = fa->fa_next;
bcdce7195   Eric Dumazet   net: speedup sk_w...
1067
1068
  			if (!sock->fasync_list)
  				sock_reset_flag(sk, SOCK_FASYNC);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
  			write_unlock_bh(&sk->sk_callback_lock);
  			kfree(fa);
  		}
  	}
  
  out:
  	release_sock(sock->sk);
  	return 0;
  }
  
  /* This function may be called only under socket lock or callback_lock */
  
  int sock_wake_async(struct socket *sock, int how, int band)
  {
  	if (!sock || !sock->fasync_list)
  		return -1;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1085
  	switch (how) {
8d8ad9d7c   Pavel Emelyanov   [NET]: Name magic...
1086
  	case SOCK_WAKE_WAITD:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1087
1088
1089
  		if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
  			break;
  		goto call_kill;
8d8ad9d7c   Pavel Emelyanov   [NET]: Name magic...
1090
  	case SOCK_WAKE_SPACE:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1091
1092
1093
  		if (!test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags))
  			break;
  		/* fall through */
8d8ad9d7c   Pavel Emelyanov   [NET]: Name magic...
1094
  	case SOCK_WAKE_IO:
89bddce58   Stephen Hemminger   [NET] socket: cod...
1095
  call_kill:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1096
1097
  		__kill_fasync(sock->fasync_list, SIGIO, band);
  		break;
8d8ad9d7c   Pavel Emelyanov   [NET]: Name magic...
1098
  	case SOCK_WAKE_URG:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1099
1100
1101
1102
  		__kill_fasync(sock->fasync_list, SIGURG, band);
  	}
  	return 0;
  }
1b8d7ae42   Eric W. Biederman   [NET]: Make socke...
1103
  static int __sock_create(struct net *net, int family, int type, int protocol,
89bddce58   Stephen Hemminger   [NET] socket: cod...
1104
  			 struct socket **res, int kern)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1105
1106
1107
  {
  	int err;
  	struct socket *sock;
55737fda0   Stephen Hemminger   [NET]: socket fam...
1108
  	const struct net_proto_family *pf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1109
1110
  
  	/*
89bddce58   Stephen Hemminger   [NET] socket: cod...
1111
  	 *      Check protocol is in range
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
  	 */
  	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...
1124
  		static int warned;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1125
1126
  		if (!warned) {
  			warned = 1;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1127
1128
1129
  			printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)
  ",
  			       current->comm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1130
1131
1132
1133
1134
1135
1136
  		}
  		family = PF_PACKET;
  	}
  
  	err = security_socket_create(family, type, protocol, kern);
  	if (err)
  		return err;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1137

55737fda0   Stephen Hemminger   [NET]: socket fam...
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
  	/*
  	 *	Allocate the socket and allow the family to set things up. if
  	 *	the protocol is 0, the family is instructed to select an appropriate
  	 *	default.
  	 */
  	sock = sock_alloc();
  	if (!sock) {
  		if (net_ratelimit())
  			printk(KERN_WARNING "socket: no more sockets
  ");
  		return -ENFILE;	/* Not exactly a match, but its the
  				   closest posix thing */
  	}
  
  	sock->type = type;
95a5afca4   Johannes Berg   net: Remove CONFI...
1153
  #ifdef CONFIG_MODULES
89bddce58   Stephen Hemminger   [NET] socket: cod...
1154
1155
1156
  	/* 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
1157
1158
1159
  	 * requested real, full-featured networking support upon configuration.
  	 * Otherwise module support will break!
  	 */
55737fda0   Stephen Hemminger   [NET]: socket fam...
1160
  	if (net_families[family] == NULL)
89bddce58   Stephen Hemminger   [NET] socket: cod...
1161
  		request_module("net-pf-%d", family);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1162
  #endif
55737fda0   Stephen Hemminger   [NET]: socket fam...
1163
1164
1165
1166
1167
  	rcu_read_lock();
  	pf = rcu_dereference(net_families[family]);
  	err = -EAFNOSUPPORT;
  	if (!pf)
  		goto out_release;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1168
1169
1170
1171
1172
  
  	/*
  	 * 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...
1173
  	if (!try_module_get(pf->owner))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1174
  		goto out_release;
55737fda0   Stephen Hemminger   [NET]: socket fam...
1175
1176
  	/* Now protected by module ref count */
  	rcu_read_unlock();
3f378b684   Eric Paris   net: pass kern to...
1177
  	err = pf->create(net, sock, protocol, kern);
55737fda0   Stephen Hemminger   [NET]: socket fam...
1178
  	if (err < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1179
  		goto out_module_put;
a79af59ef   Frank Filz   [NET]: Fix module...
1180

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1181
1182
1183
1184
  	/*
  	 * 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...
1185
1186
  	if (!try_module_get(sock->ops->owner))
  		goto out_module_busy;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1187
1188
1189
1190
  	/*
  	 * Now that we're done with the ->create function, the [loadable]
  	 * module can have its refcnt decremented
  	 */
55737fda0   Stephen Hemminger   [NET]: socket fam...
1191
  	module_put(pf->owner);
7420ed23a   Venkat Yekkirala   [NetLabel]: SELin...
1192
1193
  	err = security_socket_post_create(sock, family, type, protocol, kern);
  	if (err)
3b1855255   Herbert Xu   [NET]: Fix unbala...
1194
  		goto out_sock_release;
55737fda0   Stephen Hemminger   [NET]: socket fam...
1195
  	*res = sock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1196

55737fda0   Stephen Hemminger   [NET]: socket fam...
1197
1198
1199
1200
  	return 0;
  
  out_module_busy:
  	err = -EAFNOSUPPORT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1201
  out_module_put:
55737fda0   Stephen Hemminger   [NET]: socket fam...
1202
1203
1204
  	sock->ops = NULL;
  	module_put(pf->owner);
  out_sock_release:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1205
  	sock_release(sock);
55737fda0   Stephen Hemminger   [NET]: socket fam...
1206
1207
1208
1209
1210
  	return err;
  
  out_release:
  	rcu_read_unlock();
  	goto out_sock_release;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1211
1212
1213
1214
  }
  
  int sock_create(int family, int type, int protocol, struct socket **res)
  {
1b8d7ae42   Eric W. Biederman   [NET]: Make socke...
1215
  	return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1216
1217
1218
1219
  }
  
  int sock_create_kern(int family, int type, int protocol, struct socket **res)
  {
1b8d7ae42   Eric W. Biederman   [NET]: Make socke...
1220
  	return __sock_create(&init_net, family, type, protocol, res, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1221
  }
3e0fa65f8   Heiko Carstens   [CVE-2009-0029] S...
1222
  SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1223
1224
1225
  {
  	int retval;
  	struct socket *sock;
a677a039b   Ulrich Drepper   flag parameters: ...
1226
  	int flags;
e38b36f32   Ulrich Drepper   flag parameters: ...
1227
1228
1229
1230
1231
  	/* 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: ...
1232
  	flags = type & ~SOCK_TYPE_MASK;
77d272005   Ulrich Drepper   flag parameters: ...
1233
  	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
a677a039b   Ulrich Drepper   flag parameters: ...
1234
1235
  		return -EINVAL;
  	type &= SOCK_TYPE_MASK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1236

aaca0bdca   Ulrich Drepper   flag parameters: ...
1237
1238
  	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
  		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1239
1240
1241
  	retval = sock_create(family, type, protocol, &sock);
  	if (retval < 0)
  		goto out;
77d272005   Ulrich Drepper   flag parameters: ...
1242
  	retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
  	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...
1258
1259
  SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
  		int __user *, usockvec)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1260
1261
1262
  {
  	struct socket *sock1, *sock2;
  	int fd1, fd2, err;
db3495099   Al Viro   [PATCH] AUDIT_FD_...
1263
  	struct file *newfile1, *newfile2;
a677a039b   Ulrich Drepper   flag parameters: ...
1264
1265
1266
  	int flags;
  
  	flags = type & ~SOCK_TYPE_MASK;
77d272005   Ulrich Drepper   flag parameters: ...
1267
  	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
a677a039b   Ulrich Drepper   flag parameters: ...
1268
1269
  		return -EINVAL;
  	type &= SOCK_TYPE_MASK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1270

aaca0bdca   Ulrich Drepper   flag parameters: ...
1271
1272
  	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
  		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
  	/*
  	 * 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...
1287
  	if (err < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1288
  		goto out_release_both;
7cbe66b6b   Al Viro   merge sock_alloc_...
1289
  	fd1 = sock_alloc_file(sock1, &newfile1, flags);
bf3c23d17   David S. Miller   [NET]: Fix error ...
1290
1291
  	if (unlikely(fd1 < 0)) {
  		err = fd1;
db3495099   Al Viro   [PATCH] AUDIT_FD_...
1292
  		goto out_release_both;
bf3c23d17   David S. Miller   [NET]: Fix error ...
1293
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1294

7cbe66b6b   Al Viro   merge sock_alloc_...
1295
  	fd2 = sock_alloc_file(sock2, &newfile2, flags);
198de4d7a   Al Viro   reorder alloc_fd/...
1296
1297
1298
1299
1300
1301
  	if (unlikely(fd2 < 0)) {
  		err = fd2;
  		fput(newfile1);
  		put_unused_fd(fd1);
  		sock_release(sock2);
  		goto out;
db3495099   Al Viro   [PATCH] AUDIT_FD_...
1302
  	}
157cf649a   Al Viro   sanitize audit_fd...
1303
  	audit_fd_pair(fd1, fd2);
db3495099   Al Viro   [PATCH] AUDIT_FD_...
1304
1305
  	fd_install(fd1, newfile1);
  	fd_install(fd2, newfile2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1306
1307
1308
  	/* fd1 and fd2 may be already another descriptors.
  	 * Not kernel problem.
  	 */
89bddce58   Stephen Hemminger   [NET] socket: cod...
1309
  	err = put_user(fd1, &usockvec[0]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1310
1311
1312
1313
1314
1315
1316
1317
  	if (!err)
  		err = put_user(fd2, &usockvec[1]);
  	if (!err)
  		return 0;
  
  	sys_close(fd2);
  	sys_close(fd1);
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1318
  out_release_both:
89bddce58   Stephen Hemminger   [NET] socket: cod...
1319
  	sock_release(sock2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1320
  out_release_1:
89bddce58   Stephen Hemminger   [NET] socket: cod...
1321
  	sock_release(sock1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1322
1323
1324
  out:
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1325
1326
1327
1328
1329
1330
1331
  /*
   *	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...
1332
  SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1333
1334
  {
  	struct socket *sock;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1335
  	struct sockaddr_storage address;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1336
  	int err, fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1337

89bddce58   Stephen Hemminger   [NET] socket: cod...
1338
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
e71a4783a   Stephen Hemminger   [NET] core: white...
1339
  	if (sock) {
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1340
  		err = move_addr_to_kernel(umyaddr, addrlen, (struct sockaddr *)&address);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1341
1342
  		if (err >= 0) {
  			err = security_socket_bind(sock,
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1343
  						   (struct sockaddr *)&address,
89bddce58   Stephen Hemminger   [NET] socket: cod...
1344
  						   addrlen);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1345
1346
  			if (!err)
  				err = sock->ops->bind(sock,
89bddce58   Stephen Hemminger   [NET] socket: cod...
1347
  						      (struct sockaddr *)
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1348
  						      &address, addrlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1349
  		}
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1350
  		fput_light(sock->file, fput_needed);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1351
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1352
1353
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1354
1355
1356
1357
1358
  /*
   *	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...
1359
  SYSCALL_DEFINE2(listen, int, fd, int, backlog)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1360
1361
  {
  	struct socket *sock;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1362
  	int err, fput_needed;
b8e1f9b5c   Pavel Emelyanov   [NET] sysctl: mak...
1363
  	int somaxconn;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1364
1365
1366
  
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
  	if (sock) {
8efa6e93c   Pavel Emelyanov   [NETNS]: Introduc...
1367
  		somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
b8e1f9b5c   Pavel Emelyanov   [NET] sysctl: mak...
1368
1369
  		if ((unsigned)backlog > somaxconn)
  			backlog = somaxconn;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1370
1371
  
  		err = security_socket_listen(sock, backlog);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1372
1373
  		if (!err)
  			err = sock->ops->listen(sock, backlog);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1374

6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1375
  		fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1376
1377
1378
  	}
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
  /*
   *	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...
1390
1391
  SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
  		int __user *, upeer_addrlen, int, flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1392
1393
  {
  	struct socket *sock, *newsock;
39d8c1b6f   David S. Miller   [NET]: Do not los...
1394
  	struct file *newfile;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1395
  	int err, len, newfd, fput_needed;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1396
  	struct sockaddr_storage address;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1397

77d272005   Ulrich Drepper   flag parameters: ...
1398
  	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
aaca0bdca   Ulrich Drepper   flag parameters: ...
1399
1400
1401
1402
  		return -EINVAL;
  
  	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
  		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1403
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1404
1405
1406
1407
  	if (!sock)
  		goto out;
  
  	err = -ENFILE;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1408
  	if (!(newsock = sock_alloc()))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1409
1410
1411
1412
  		goto out_put;
  
  	newsock->type = sock->type;
  	newsock->ops = sock->ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1413
1414
1415
1416
1417
  	/*
  	 * We don't need try_module_get here, as the listening socket (sock)
  	 * has the protocol module (sock->ops->owner) held.
  	 */
  	__module_get(newsock->ops->owner);
7cbe66b6b   Al Viro   merge sock_alloc_...
1418
  	newfd = sock_alloc_file(newsock, &newfile, flags);
39d8c1b6f   David S. Miller   [NET]: Do not los...
1419
1420
  	if (unlikely(newfd < 0)) {
  		err = newfd;
9a1875e60   David S. Miller   [NET]: Fully fix ...
1421
1422
  		sock_release(newsock);
  		goto out_put;
39d8c1b6f   David S. Miller   [NET]: Do not los...
1423
  	}
a79af59ef   Frank Filz   [NET]: Fix module...
1424
1425
  	err = security_socket_accept(sock, newsock);
  	if (err)
39d8c1b6f   David S. Miller   [NET]: Do not los...
1426
  		goto out_fd;
a79af59ef   Frank Filz   [NET]: Fix module...
1427

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1428
1429
  	err = sock->ops->accept(sock, newsock, sock->file->f_flags);
  	if (err < 0)
39d8c1b6f   David S. Miller   [NET]: Do not los...
1430
  		goto out_fd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1431
1432
  
  	if (upeer_sockaddr) {
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1433
  		if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
89bddce58   Stephen Hemminger   [NET] socket: cod...
1434
  					  &len, 2) < 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1435
  			err = -ECONNABORTED;
39d8c1b6f   David S. Miller   [NET]: Do not los...
1436
  			goto out_fd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1437
  		}
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1438
1439
  		err = move_addr_to_user((struct sockaddr *)&address,
  					len, upeer_sockaddr, upeer_addrlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1440
  		if (err < 0)
39d8c1b6f   David S. Miller   [NET]: Do not los...
1441
  			goto out_fd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1442
1443
1444
  	}
  
  	/* File flags are not inherited via accept() unlike another OSes. */
39d8c1b6f   David S. Miller   [NET]: Do not los...
1445
1446
  	fd_install(newfd, newfile);
  	err = newfd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1447

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1448
  out_put:
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1449
  	fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1450
1451
  out:
  	return err;
39d8c1b6f   David S. Miller   [NET]: Do not los...
1452
  out_fd:
9606a2163   David S. Miller   [NET]: Fix dentry...
1453
  	fput(newfile);
39d8c1b6f   David S. Miller   [NET]: Do not los...
1454
  	put_unused_fd(newfd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1455
1456
  	goto out_put;
  }
20f37034f   Heiko Carstens   [CVE-2009-0029] S...
1457
1458
  SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,
  		int __user *, upeer_addrlen)
aaca0bdca   Ulrich Drepper   flag parameters: ...
1459
  {
de11defeb   Ulrich Drepper   reintroduce accept4
1460
  	return sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0);
aaca0bdca   Ulrich Drepper   flag parameters: ...
1461
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
  /*
   *	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...
1473
1474
  SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
  		int, addrlen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1475
1476
  {
  	struct socket *sock;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1477
  	struct sockaddr_storage address;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1478
  	int err, fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1479

6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1480
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1481
1482
  	if (!sock)
  		goto out;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1483
  	err = move_addr_to_kernel(uservaddr, addrlen, (struct sockaddr *)&address);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1484
1485
  	if (err < 0)
  		goto out_put;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1486
  	err =
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1487
  	    security_socket_connect(sock, (struct sockaddr *)&address, addrlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1488
1489
  	if (err)
  		goto out_put;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1490
  	err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1491
1492
  				 sock->file->f_flags);
  out_put:
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1493
  	fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1494
1495
1496
1497
1498
1499
1500
1501
  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...
1502
1503
  SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
  		int __user *, usockaddr_len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1504
1505
  {
  	struct socket *sock;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1506
  	struct sockaddr_storage address;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1507
  	int len, err, fput_needed;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1508

6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1509
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1510
1511
1512
1513
1514
1515
  	if (!sock)
  		goto out;
  
  	err = security_socket_getsockname(sock);
  	if (err)
  		goto out_put;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1516
  	err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1517
1518
  	if (err)
  		goto out_put;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1519
  	err = move_addr_to_user((struct sockaddr *)&address, len, usockaddr, usockaddr_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1520
1521
  
  out_put:
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1522
  	fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1523
1524
1525
1526
1527
1528
1529
1530
  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...
1531
1532
  SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
  		int __user *, usockaddr_len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1533
1534
  {
  	struct socket *sock;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1535
  	struct sockaddr_storage address;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1536
  	int len, err, fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1537

89bddce58   Stephen Hemminger   [NET] socket: cod...
1538
1539
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
  	if (sock != NULL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1540
1541
  		err = security_socket_getpeername(sock);
  		if (err) {
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1542
  			fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1543
1544
  			return err;
  		}
89bddce58   Stephen Hemminger   [NET] socket: cod...
1545
  		err =
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1546
  		    sock->ops->getname(sock, (struct sockaddr *)&address, &len,
89bddce58   Stephen Hemminger   [NET] socket: cod...
1547
  				       1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1548
  		if (!err)
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1549
  			err = move_addr_to_user((struct sockaddr *)&address, len, usockaddr,
89bddce58   Stephen Hemminger   [NET] socket: cod...
1550
  						usockaddr_len);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1551
  		fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1552
1553
1554
1555
1556
1557
1558
1559
1560
  	}
  	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...
1561
1562
1563
  SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
  		unsigned, flags, struct sockaddr __user *, addr,
  		int, addr_len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1564
1565
  {
  	struct socket *sock;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1566
  	struct sockaddr_storage address;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1567
1568
1569
  	int err;
  	struct msghdr msg;
  	struct iovec iov;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1570
  	int fput_needed;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1571

de0fa95c1   Pavel Emelyanov   [NET]: Use sockfd...
1572
1573
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
  	if (!sock)
4387ff75f   David S. Miller   [NET]: Fix net/so...
1574
  		goto out;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1575

89bddce58   Stephen Hemminger   [NET] socket: cod...
1576
1577
1578
1579
1580
1581
1582
1583
  	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...
1584
  	if (addr) {
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1585
  		err = move_addr_to_kernel(addr, addr_len, (struct sockaddr *)&address);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1586
1587
  		if (err < 0)
  			goto out_put;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1588
  		msg.msg_name = (struct sockaddr *)&address;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1589
  		msg.msg_namelen = addr_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1590
1591
1592
1593
1594
  	}
  	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...
1595
  out_put:
de0fa95c1   Pavel Emelyanov   [NET]: Use sockfd...
1596
  	fput_light(sock->file, fput_needed);
4387ff75f   David S. Miller   [NET]: Fix net/so...
1597
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1598
1599
1600
1601
  	return err;
  }
  
  /*
89bddce58   Stephen Hemminger   [NET] socket: cod...
1602
   *	Send a datagram down a socket.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1603
   */
3e0fa65f8   Heiko Carstens   [CVE-2009-0029] S...
1604
1605
  SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len,
  		unsigned, flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1606
1607
1608
1609
1610
  {
  	return sys_sendto(fd, buff, len, flags, NULL, 0);
  }
  
  /*
89bddce58   Stephen Hemminger   [NET] socket: cod...
1611
   *	Receive a frame from the socket and optionally record the address of the
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1612
1613
1614
   *	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...
1615
1616
1617
  SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
  		unsigned, flags, struct sockaddr __user *, addr,
  		int __user *, addr_len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1618
1619
1620
1621
  {
  	struct socket *sock;
  	struct iovec iov;
  	struct msghdr msg;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1622
  	struct sockaddr_storage address;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1623
  	int err, err2;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1624
  	int fput_needed;
de0fa95c1   Pavel Emelyanov   [NET]: Use sockfd...
1625
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1626
  	if (!sock)
de0fa95c1   Pavel Emelyanov   [NET]: Use sockfd...
1627
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1628

89bddce58   Stephen Hemminger   [NET] socket: cod...
1629
1630
1631
1632
1633
1634
  	msg.msg_control = NULL;
  	msg.msg_controllen = 0;
  	msg.msg_iovlen = 1;
  	msg.msg_iov = &iov;
  	iov.iov_len = size;
  	iov.iov_base = ubuf;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1635
1636
  	msg.msg_name = (struct sockaddr *)&address;
  	msg.msg_namelen = sizeof(address);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1637
1638
  	if (sock->file->f_flags & O_NONBLOCK)
  		flags |= MSG_DONTWAIT;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1639
  	err = sock_recvmsg(sock, &msg, size, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1640

89bddce58   Stephen Hemminger   [NET] socket: cod...
1641
  	if (err >= 0 && addr != NULL) {
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1642
1643
  		err2 = move_addr_to_user((struct sockaddr *)&address,
  					 msg.msg_namelen, addr, addr_len);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1644
1645
  		if (err2 < 0)
  			err = err2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1646
  	}
de0fa95c1   Pavel Emelyanov   [NET]: Use sockfd...
1647
1648
  
  	fput_light(sock->file, fput_needed);
4387ff75f   David S. Miller   [NET]: Fix net/so...
1649
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1650
1651
1652
1653
  	return err;
  }
  
  /*
89bddce58   Stephen Hemminger   [NET] socket: cod...
1654
   *	Receive a datagram from a socket.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1655
   */
89bddce58   Stephen Hemminger   [NET] socket: cod...
1656
1657
  asmlinkage long sys_recv(int fd, void __user *ubuf, size_t size,
  			 unsigned flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1658
1659
1660
1661
1662
1663
1664
1665
  {
  	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...
1666
1667
  SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
  		char __user *, optval, int, optlen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1668
  {
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1669
  	int err, fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1670
1671
1672
1673
  	struct socket *sock;
  
  	if (optlen < 0)
  		return -EINVAL;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1674
1675
1676
1677
  
  	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...
1678
1679
  		if (err)
  			goto out_put;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1680
1681
  
  		if (level == SOL_SOCKET)
89bddce58   Stephen Hemminger   [NET] socket: cod...
1682
1683
1684
  			err =
  			    sock_setsockopt(sock, level, optname, optval,
  					    optlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1685
  		else
89bddce58   Stephen Hemminger   [NET] socket: cod...
1686
1687
1688
  			err =
  			    sock->ops->setsockopt(sock, level, optname, optval,
  						  optlen);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1689
1690
  out_put:
  		fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1691
1692
1693
1694
1695
1696
1697
1698
  	}
  	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...
1699
1700
  SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
  		char __user *, optval, int __user *, optlen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1701
  {
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1702
  	int err, fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1703
  	struct socket *sock;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1704
1705
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
  	if (sock != NULL) {
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1706
1707
1708
  		err = security_socket_getsockopt(sock, level, optname);
  		if (err)
  			goto out_put;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1709
1710
  
  		if (level == SOL_SOCKET)
89bddce58   Stephen Hemminger   [NET] socket: cod...
1711
1712
1713
  			err =
  			    sock_getsockopt(sock, level, optname, optval,
  					    optlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1714
  		else
89bddce58   Stephen Hemminger   [NET] socket: cod...
1715
1716
1717
  			err =
  			    sock->ops->getsockopt(sock, level, optname, optval,
  						  optlen);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1718
1719
  out_put:
  		fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1720
1721
1722
  	}
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1723
1724
1725
  /*
   *	Shutdown a socket.
   */
754fe8d29   Heiko Carstens   [CVE-2009-0029] S...
1726
  SYSCALL_DEFINE2(shutdown, int, fd, int, how)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1727
  {
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1728
  	int err, fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1729
  	struct socket *sock;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1730
1731
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
  	if (sock != NULL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1732
  		err = security_socket_shutdown(sock, how);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1733
1734
1735
  		if (!err)
  			err = sock->ops->shutdown(sock, how);
  		fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1736
1737
1738
  	}
  	return err;
  }
89bddce58   Stephen Hemminger   [NET] socket: cod...
1739
  /* A couple of helpful macros for getting the address of the 32/64 bit
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1740
1741
1742
1743
1744
   * 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)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1745
1746
1747
  /*
   *	BSD sendmsg interface
   */
3e0fa65f8   Heiko Carstens   [CVE-2009-0029] S...
1748
  SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned, flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1749
  {
89bddce58   Stephen Hemminger   [NET] socket: cod...
1750
1751
  	struct compat_msghdr __user *msg_compat =
  	    (struct compat_msghdr __user *)msg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1752
  	struct socket *sock;
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1753
  	struct sockaddr_storage address;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1754
  	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
b9d717a7b   Alex Williamson   [NET]: Make sure ...
1755
  	unsigned char ctl[sizeof(struct cmsghdr) + 20]
89bddce58   Stephen Hemminger   [NET] socket: cod...
1756
1757
  	    __attribute__ ((aligned(sizeof(__kernel_size_t))));
  	/* 20 is size of ipv6_pktinfo */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1758
1759
1760
  	unsigned char *ctl_buf = ctl;
  	struct msghdr msg_sys;
  	int err, ctl_len, iov_size, total_len;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1761
  	int fput_needed;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1762

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1763
1764
1765
1766
  	err = -EFAULT;
  	if (MSG_CMSG_COMPAT & flags) {
  		if (get_compat_msghdr(&msg_sys, msg_compat))
  			return -EFAULT;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1767
1768
  	}
  	else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1769
  		return -EFAULT;
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1770
  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1771
  	if (!sock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1772
1773
1774
1775
1776
1777
  		goto out;
  
  	/* do not move before msg_sys is valid */
  	err = -EMSGSIZE;
  	if (msg_sys.msg_iovlen > UIO_MAXIOV)
  		goto out_put;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1778
  	/* Check whether to allocate the iovec area */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
  	err = -ENOMEM;
  	iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);
  	if (msg_sys.msg_iovlen > UIO_FASTIOV) {
  		iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
  		if (!iov)
  			goto out_put;
  	}
  
  	/* This will also move the address data into kernel space */
  	if (MSG_CMSG_COMPAT & flags) {
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1789
1790
1791
  		err = verify_compat_iovec(&msg_sys, iov,
  					  (struct sockaddr *)&address,
  					  VERIFY_READ);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1792
  	} else
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1793
1794
1795
  		err = verify_iovec(&msg_sys, iov,
  				   (struct sockaddr *)&address,
  				   VERIFY_READ);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1796
  	if (err < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1797
1798
1799
1800
1801
1802
1803
  		goto out_freeiov;
  	total_len = err;
  
  	err = -ENOBUFS;
  
  	if (msg_sys.msg_controllen > INT_MAX)
  		goto out_freeiov;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1804
  	ctl_len = msg_sys.msg_controllen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1805
  	if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
89bddce58   Stephen Hemminger   [NET] socket: cod...
1806
1807
1808
  		err =
  		    cmsghdr_from_user_compat_to_kern(&msg_sys, sock->sk, ctl,
  						     sizeof(ctl));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1809
1810
1811
  		if (err)
  			goto out_freeiov;
  		ctl_buf = msg_sys.msg_control;
8920e8f94   Al Viro   [PATCH] Fix 32bit...
1812
  		ctl_len = msg_sys.msg_controllen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1813
  	} else if (ctl_len) {
89bddce58   Stephen Hemminger   [NET] socket: cod...
1814
  		if (ctl_len > sizeof(ctl)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1815
  			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1816
  			if (ctl_buf == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1817
1818
1819
1820
1821
1822
1823
1824
  				goto out_freeiov;
  		}
  		err = -EFAULT;
  		/*
  		 * Careful! Before this, msg_sys.msg_control contains a user pointer.
  		 * Afterwards, it will be a kernel pointer. Thus the compiler-assisted
  		 * checking falls down on this.
  		 */
89bddce58   Stephen Hemminger   [NET] socket: cod...
1825
1826
  		if (copy_from_user(ctl_buf, (void __user *)msg_sys.msg_control,
  				   ctl_len))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
  			goto out_freectl;
  		msg_sys.msg_control = ctl_buf;
  	}
  	msg_sys.msg_flags = flags;
  
  	if (sock->file->f_flags & O_NONBLOCK)
  		msg_sys.msg_flags |= MSG_DONTWAIT;
  	err = sock_sendmsg(sock, &msg_sys, total_len);
  
  out_freectl:
89bddce58   Stephen Hemminger   [NET] socket: cod...
1837
  	if (ctl_buf != ctl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1838
1839
1840
1841
1842
  		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
  out_freeiov:
  	if (iov != iovstack)
  		sock_kfree_s(sock->sk, iov, iov_size);
  out_put:
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1843
  	fput_light(sock->file, fput_needed);
89bddce58   Stephen Hemminger   [NET] socket: cod...
1844
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1845
1846
  	return err;
  }
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
1847
1848
  static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
  			 struct msghdr *msg_sys, unsigned flags, int nosec)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1849
  {
89bddce58   Stephen Hemminger   [NET] socket: cod...
1850
1851
  	struct compat_msghdr __user *msg_compat =
  	    (struct compat_msghdr __user *)msg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1852
  	struct iovec iovstack[UIO_FASTIOV];
89bddce58   Stephen Hemminger   [NET] socket: cod...
1853
  	struct iovec *iov = iovstack;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1854
1855
1856
1857
  	unsigned long cmsg_ptr;
  	int err, iov_size, total_len, len;
  
  	/* kernel mode address */
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1858
  	struct sockaddr_storage addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1859
1860
1861
1862
  
  	/* user mode address pointers */
  	struct sockaddr __user *uaddr;
  	int __user *uaddr_len;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1863

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1864
  	if (MSG_CMSG_COMPAT & flags) {
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
1865
  		if (get_compat_msghdr(msg_sys, msg_compat))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1866
  			return -EFAULT;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1867
  	}
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
1868
  	else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr)))
89bddce58   Stephen Hemminger   [NET] socket: cod...
1869
  		return -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1870

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1871
  	err = -EMSGSIZE;
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
1872
1873
  	if (msg_sys->msg_iovlen > UIO_MAXIOV)
  		goto out;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1874
1875
  
  	/* Check whether to allocate the iovec area */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1876
  	err = -ENOMEM;
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
1877
1878
  	iov_size = msg_sys->msg_iovlen * sizeof(struct iovec);
  	if (msg_sys->msg_iovlen > UIO_FASTIOV) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1879
1880
  		iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
  		if (!iov)
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
1881
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1882
1883
1884
  	}
  
  	/*
89bddce58   Stephen Hemminger   [NET] socket: cod...
1885
1886
  	 *      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
1887
  	 */
89bddce58   Stephen Hemminger   [NET] socket: cod...
1888

a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
1889
  	uaddr = (__force void __user *)msg_sys->msg_name;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1890
1891
  	uaddr_len = COMPAT_NAMELEN(msg);
  	if (MSG_CMSG_COMPAT & flags) {
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
1892
  		err = verify_compat_iovec(msg_sys, iov,
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1893
1894
  					  (struct sockaddr *)&addr,
  					  VERIFY_WRITE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1895
  	} else
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
1896
  		err = verify_iovec(msg_sys, iov,
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1897
1898
  				   (struct sockaddr *)&addr,
  				   VERIFY_WRITE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1899
1900
  	if (err < 0)
  		goto out_freeiov;
89bddce58   Stephen Hemminger   [NET] socket: cod...
1901
  	total_len = err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1902

a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
1903
1904
  	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...
1905

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1906
1907
  	if (sock->file->f_flags & O_NONBLOCK)
  		flags |= MSG_DONTWAIT;
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
1908
1909
  	err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys,
  							  total_len, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1910
1911
1912
1913
1914
  	if (err < 0)
  		goto out_freeiov;
  	len = err;
  
  	if (uaddr != NULL) {
230b18392   YOSHIFUJI Hideaki   net: Use standard...
1915
  		err = move_addr_to_user((struct sockaddr *)&addr,
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
1916
  					msg_sys->msg_namelen, uaddr,
89bddce58   Stephen Hemminger   [NET] socket: cod...
1917
  					uaddr_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1918
1919
1920
  		if (err < 0)
  			goto out_freeiov;
  	}
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
1921
  	err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
37f7f421c   David S. Miller   [NET]: Do not lea...
1922
  			 COMPAT_FLAGS(msg));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1923
1924
1925
  	if (err)
  		goto out_freeiov;
  	if (MSG_CMSG_COMPAT & flags)
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
1926
  		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1927
1928
  				 &msg_compat->msg_controllen);
  	else
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
1929
  		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1930
1931
1932
1933
1934
1935
1936
1937
  				 &msg->msg_controllen);
  	if (err)
  		goto out_freeiov;
  	err = len;
  
  out_freeiov:
  	if (iov != iovstack)
  		sock_kfree_s(sock->sk, iov, iov_size);
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
  out:
  	return err;
  }
  
  /*
   *	BSD recvmsg interface
   */
  
  SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg,
  		unsigned int, flags)
  {
  	int fput_needed, err;
  	struct msghdr msg_sys;
  	struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed);
  
  	if (!sock)
  		goto out;
  
  	err = __sys_recvmsg(sock, msg, &msg_sys, flags, 0);
6cb153cab   Benjamin LaHaise   [NET]: use fget_l...
1957
  	fput_light(sock->file, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1958
1959
1960
  out:
  	return err;
  }
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
  /*
   *     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...
1971
  	struct compat_mmsghdr __user *compat_entry;
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
  	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...
1991
  	compat_entry = (struct compat_mmsghdr __user *)mmsg;
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
1992
1993
1994
1995
1996
  
  	while (datagrams < vlen) {
  		/*
  		 * No need to ask LSM for more than the first datagram.
  		 */
d7256d0eb   Jean-Mickael Guerin   net: compat_mmsgh...
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
  		if (MSG_CMSG_COMPAT & flags) {
  			err = __sys_recvmsg(sock, (struct msghdr __user *)compat_entry,
  					    &msg_sys, flags, datagrams);
  			if (err < 0)
  				break;
  			err = __put_user(err, &compat_entry->msg_len);
  			++compat_entry;
  		} else {
  			err = __sys_recvmsg(sock, (struct msghdr __user *)entry,
  					    &msg_sys, flags, datagrams);
  			if (err < 0)
  				break;
  			err = put_user(err, &entry->msg_len);
  			++entry;
  		}
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2012
2013
  		if (err)
  			break;
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
  		++datagrams;
  
  		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
2036

a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
  	if (err == 0)
  		return datagrams;
  
  	if (datagrams != 0) {
  		/*
  		 * We may return less entries than requested (vlen) if the
  		 * sock is non block and there aren't enough datagrams...
  		 */
  		if (err != -EAGAIN) {
  			/*
  			 * ... or  if recvmsg returns an error after we
  			 * received some datagrams, where we record the
  			 * error to return on the next call or if the
  			 * app asks about it using getsockopt(SO_ERROR).
  			 */
  			sock->sk->sk_err = -err;
  		}
  
  		return datagrams;
  	}
  
  	return err;
  }
  
  SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
  		unsigned int, vlen, unsigned int, flags,
  		struct timespec __user *, timeout)
  {
  	int datagrams;
  	struct timespec timeout_sys;
  
  	if (!timeout)
  		return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL);
  
  	if (copy_from_user(&timeout_sys, timeout, sizeof(timeout_sys)))
  		return -EFAULT;
  
  	datagrams = __sys_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys);
  
  	if (datagrams > 0 &&
  	    copy_to_user(timeout, &timeout_sys, sizeof(timeout_sys)))
  		datagrams = -EFAULT;
  
  	return datagrams;
  }
  
  #ifdef __ARCH_WANT_SYS_SOCKETCALL
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2084
2085
  /* Argument list sizes for sys_socketcall */
  #define AL(x) ((x) * sizeof(unsigned long))
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2086
  static const unsigned char nargs[20] = {
89bddce58   Stephen Hemminger   [NET] socket: cod...
2087
2088
  	AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
  	AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
aaca0bdca   Ulrich Drepper   flag parameters: ...
2089
  	AL(6),AL(2),AL(5),AL(5),AL(3),AL(3),
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2090
  	AL(4),AL(5)
89bddce58   Stephen Hemminger   [NET] socket: cod...
2091
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2092
2093
2094
  #undef AL
  
  /*
89bddce58   Stephen Hemminger   [NET] socket: cod...
2095
   *	System call vectors.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2096
2097
2098
   *
   *	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...
2099
   *  it is set by the callees.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2100
   */
3e0fa65f8   Heiko Carstens   [CVE-2009-0029] S...
2101
  SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2102
2103
  {
  	unsigned long a[6];
89bddce58   Stephen Hemminger   [NET] socket: cod...
2104
  	unsigned long a0, a1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2105
  	int err;
47379052b   Arjan van de Ven   net: Add explicit...
2106
  	unsigned int len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2107

a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2108
  	if (call < 1 || call > SYS_RECVMMSG)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2109
  		return -EINVAL;
47379052b   Arjan van de Ven   net: Add explicit...
2110
2111
2112
  	len = nargs[call];
  	if (len > sizeof(a))
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2113
  	/* copy_from_user should be SMP safe. */
47379052b   Arjan van de Ven   net: Add explicit...
2114
  	if (copy_from_user(a, args, len))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2115
  		return -EFAULT;
3ec3b2fba   David Woodhouse   AUDIT: Capture sy...
2116

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

89bddce58   Stephen Hemminger   [NET] socket: cod...
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
  	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
2136
2137
  		err = sys_accept4(a0, (struct sockaddr __user *)a1,
  				  (int __user *)a[2], 0);
89bddce58   Stephen Hemminger   [NET] socket: cod...
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
  		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;
  	case SYS_RECVMSG:
  		err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]);
  		break;
a2e272554   Arnaldo Carvalho de Melo   net: Introduce re...
2184
2185
2186
2187
  	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
2188
2189
2190
  	case SYS_ACCEPT4:
  		err = sys_accept4(a0, (struct sockaddr __user *)a1,
  				  (int __user *)a[2], a[3]);
aaca0bdca   Ulrich Drepper   flag parameters: ...
2191
  		break;
89bddce58   Stephen Hemminger   [NET] socket: cod...
2192
2193
2194
  	default:
  		err = -EINVAL;
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2195
2196
2197
  	}
  	return err;
  }
89bddce58   Stephen Hemminger   [NET] socket: cod...
2198
  #endif				/* __ARCH_WANT_SYS_SOCKETCALL */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2199

55737fda0   Stephen Hemminger   [NET]: socket fam...
2200
2201
2202
2203
  /**
   *	sock_register - add a socket protocol handler
   *	@ops: description of protocol
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2204
2205
   *	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...
2206
2207
   *	socket interface. The value ops->family coresponds to the
   *	socket system call protocol family.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2208
   */
f0fd27d42   Stephen Hemminger   [NET]: sock_regis...
2209
  int sock_register(const struct net_proto_family *ops)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2210
2211
2212
2213
  {
  	int err;
  
  	if (ops->family >= NPROTO) {
89bddce58   Stephen Hemminger   [NET] socket: cod...
2214
2215
2216
  		printk(KERN_CRIT "protocol %d >= NPROTO(%d)
  ", ops->family,
  		       NPROTO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2217
2218
  		return -ENOBUFS;
  	}
55737fda0   Stephen Hemminger   [NET]: socket fam...
2219
2220
2221
2222
2223
  
  	spin_lock(&net_family_lock);
  	if (net_families[ops->family])
  		err = -EEXIST;
  	else {
89bddce58   Stephen Hemminger   [NET] socket: cod...
2224
  		net_families[ops->family] = ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2225
2226
  		err = 0;
  	}
55737fda0   Stephen Hemminger   [NET]: socket fam...
2227
  	spin_unlock(&net_family_lock);
89bddce58   Stephen Hemminger   [NET] socket: cod...
2228
2229
  	printk(KERN_INFO "NET: Registered protocol family %d
  ", ops->family);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2230
2231
  	return err;
  }
55737fda0   Stephen Hemminger   [NET]: socket fam...
2232
2233
2234
2235
  /**
   *	sock_unregister - remove a protocol handler
   *	@family: protocol family to remove
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2236
2237
   *	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...
2238
2239
2240
2241
2242
2243
   *	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
2244
   */
f0fd27d42   Stephen Hemminger   [NET]: sock_regis...
2245
  void sock_unregister(int family)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2246
  {
f0fd27d42   Stephen Hemminger   [NET]: sock_regis...
2247
  	BUG_ON(family < 0 || family >= NPROTO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2248

55737fda0   Stephen Hemminger   [NET]: socket fam...
2249
  	spin_lock(&net_family_lock);
89bddce58   Stephen Hemminger   [NET] socket: cod...
2250
  	net_families[family] = NULL;
55737fda0   Stephen Hemminger   [NET]: socket fam...
2251
2252
2253
  	spin_unlock(&net_family_lock);
  
  	synchronize_rcu();
89bddce58   Stephen Hemminger   [NET] socket: cod...
2254
2255
  	printk(KERN_INFO "NET: Unregistered protocol family %d
  ", family);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2256
  }
77d76ea31   Andi Kleen   [NET]: Small clea...
2257
  static int __init sock_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2258
2259
  {
  	/*
89bddce58   Stephen Hemminger   [NET] socket: cod...
2260
  	 *      Initialize sock SLAB cache.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2261
  	 */
89bddce58   Stephen Hemminger   [NET] socket: cod...
2262

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2263
  	sk_init();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2264
  	/*
89bddce58   Stephen Hemminger   [NET] socket: cod...
2265
  	 *      Initialize skbuff SLAB cache
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2266
2267
  	 */
  	skb_init();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2268
2269
  
  	/*
89bddce58   Stephen Hemminger   [NET] socket: cod...
2270
  	 *      Initialize the protocols module.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2271
2272
2273
2274
2275
  	 */
  
  	init_inodecache();
  	register_filesystem(&sock_fs_type);
  	sock_mnt = kern_mount(&sock_fs_type);
77d76ea31   Andi Kleen   [NET]: Small clea...
2276
2277
  
  	/* The real protocol initialization is performed in later initcalls.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2278
2279
2280
2281
2282
  	 */
  
  #ifdef CONFIG_NETFILTER
  	netfilter_init();
  #endif
cbeb321a6   David S. Miller   [NET]: Fix sock_i...
2283
2284
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2285
  }
77d76ea31   Andi Kleen   [NET]: Small clea...
2286
  core_initcall(sock_init);	/* early initcall */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2287
2288
2289
2290
2291
  #ifdef CONFIG_PROC_FS
  void socket_seq_show(struct seq_file *seq)
  {
  	int cpu;
  	int counter = 0;
6f9120422   KAMEZAWA Hiroyuki   [PATCH] for_each_...
2292
  	for_each_possible_cpu(cpu)
89bddce58   Stephen Hemminger   [NET] socket: cod...
2293
  	    counter += per_cpu(sockets_in_use, cpu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2294
2295
2296
2297
2298
2299
2300
2301
  
  	/* 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...
2302
  #endif				/* CONFIG_PROC_FS */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2303

89bbfc95d   Shaun Pereira   [NET]: allow 32 b...
2304
  #ifdef CONFIG_COMPAT
6b96018b2   Arnd Bergmann   compat: move sock...
2305
2306
  static int do_siocgstamp(struct net *net, struct socket *sock,
  			 unsigned int cmd, struct compat_timeval __user *up)
7a229387d   Arnd Bergmann   net: copy socket ...
2307
  {
7a229387d   Arnd Bergmann   net: copy socket ...
2308
2309
2310
2311
2312
  	mm_segment_t old_fs = get_fs();
  	struct timeval ktv;
  	int err;
  
  	set_fs(KERNEL_DS);
6b96018b2   Arnd Bergmann   compat: move sock...
2313
  	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv);
7a229387d   Arnd Bergmann   net: copy socket ...
2314
2315
2316
2317
2318
2319
2320
  	set_fs(old_fs);
  	if (!err) {
  		err = put_user(ktv.tv_sec, &up->tv_sec);
  		err |= __put_user(ktv.tv_usec, &up->tv_usec);
  	}
  	return err;
  }
6b96018b2   Arnd Bergmann   compat: move sock...
2321
2322
  static int do_siocgstampns(struct net *net, struct socket *sock,
  			 unsigned int cmd, struct compat_timespec __user *up)
7a229387d   Arnd Bergmann   net: copy socket ...
2323
  {
7a229387d   Arnd Bergmann   net: copy socket ...
2324
2325
2326
2327
2328
  	mm_segment_t old_fs = get_fs();
  	struct timespec kts;
  	int err;
  
  	set_fs(KERNEL_DS);
6b96018b2   Arnd Bergmann   compat: move sock...
2329
  	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts);
7a229387d   Arnd Bergmann   net: copy socket ...
2330
2331
2332
2333
2334
2335
2336
  	set_fs(old_fs);
  	if (!err) {
  		err = put_user(kts.tv_sec, &up->tv_sec);
  		err |= __put_user(kts.tv_nsec, &up->tv_nsec);
  	}
  	return err;
  }
6b96018b2   Arnd Bergmann   compat: move sock...
2337
  static int dev_ifname32(struct net *net, struct compat_ifreq __user *uifr32)
7a229387d   Arnd Bergmann   net: copy socket ...
2338
2339
2340
2341
2342
  {
  	struct ifreq __user *uifr;
  	int err;
  
  	uifr = compat_alloc_user_space(sizeof(struct ifreq));
6b96018b2   Arnd Bergmann   compat: move sock...
2343
  	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
7a229387d   Arnd Bergmann   net: copy socket ...
2344
  		return -EFAULT;
6b96018b2   Arnd Bergmann   compat: move sock...
2345
  	err = dev_ioctl(net, SIOCGIFNAME, uifr);
7a229387d   Arnd Bergmann   net: copy socket ...
2346
2347
  	if (err)
  		return err;
6b96018b2   Arnd Bergmann   compat: move sock...
2348
  	if (copy_in_user(uifr32, uifr, sizeof(struct compat_ifreq)))
7a229387d   Arnd Bergmann   net: copy socket ...
2349
2350
2351
2352
  		return -EFAULT;
  
  	return 0;
  }
6b96018b2   Arnd Bergmann   compat: move sock...
2353
  static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32)
7a229387d   Arnd Bergmann   net: copy socket ...
2354
  {
6b96018b2   Arnd Bergmann   compat: move sock...
2355
  	struct compat_ifconf ifc32;
7a229387d   Arnd Bergmann   net: copy socket ...
2356
2357
  	struct ifconf ifc;
  	struct ifconf __user *uifc;
6b96018b2   Arnd Bergmann   compat: move sock...
2358
  	struct compat_ifreq __user *ifr32;
7a229387d   Arnd Bergmann   net: copy socket ...
2359
2360
2361
  	struct ifreq __user *ifr;
  	unsigned int i, j;
  	int err;
6b96018b2   Arnd Bergmann   compat: move sock...
2362
  	if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf)))
7a229387d   Arnd Bergmann   net: copy socket ...
2363
2364
2365
2366
2367
2368
2369
2370
  		return -EFAULT;
  
  	if (ifc32.ifcbuf == 0) {
  		ifc32.ifc_len = 0;
  		ifc.ifc_len = 0;
  		ifc.ifc_req = NULL;
  		uifc = compat_alloc_user_space(sizeof(struct ifconf));
  	} else {
6b96018b2   Arnd Bergmann   compat: move sock...
2371
  		size_t len =((ifc32.ifc_len / sizeof (struct compat_ifreq)) + 1) *
7a229387d   Arnd Bergmann   net: copy socket ...
2372
2373
2374
2375
2376
  			sizeof (struct ifreq);
  		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);
6b96018b2   Arnd Bergmann   compat: move sock...
2377
2378
  		for (i = 0; i < ifc32.ifc_len; i += sizeof (struct compat_ifreq)) {
  			if (copy_in_user(ifr, ifr32, sizeof(struct compat_ifreq)))
7a229387d   Arnd Bergmann   net: copy socket ...
2379
2380
2381
2382
2383
2384
2385
  				return -EFAULT;
  			ifr++;
  			ifr32++;
  		}
  	}
  	if (copy_to_user(uifc, &ifc, sizeof(struct ifconf)))
  		return -EFAULT;
6b96018b2   Arnd Bergmann   compat: move sock...
2386
  	err = dev_ioctl(net, SIOCGIFCONF, uifc);
7a229387d   Arnd Bergmann   net: copy socket ...
2387
2388
2389
2390
2391
2392
2393
2394
2395
  	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;
6b96018b2   Arnd Bergmann   compat: move sock...
2396
2397
2398
               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 ...
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
  			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...
2409
  		i = ((i / sizeof(struct ifreq)) * sizeof(struct compat_ifreq));
7a229387d   Arnd Bergmann   net: copy socket ...
2410
2411
2412
2413
  		ifc32.ifc_len = i;
  	} else {
  		ifc32.ifc_len = i;
  	}
6b96018b2   Arnd Bergmann   compat: move sock...
2414
  	if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf)))
7a229387d   Arnd Bergmann   net: copy socket ...
2415
2416
2417
2418
  		return -EFAULT;
  
  	return 0;
  }
6b96018b2   Arnd Bergmann   compat: move sock...
2419
  static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
7a229387d   Arnd Bergmann   net: copy socket ...
2420
2421
  {
  	struct ifreq __user *ifr;
7a229387d   Arnd Bergmann   net: copy socket ...
2422
2423
2424
2425
  	u32 data;
  	void __user *datap;
  
  	ifr = compat_alloc_user_space(sizeof(*ifr));
7a229387d   Arnd Bergmann   net: copy socket ...
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
  
  	if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
  		return -EFAULT;
  
  	if (get_user(data, &ifr32->ifr_ifru.ifru_data))
  		return -EFAULT;
  
  	datap = compat_ptr(data);
  	if (put_user(datap, &ifr->ifr_ifru.ifru_data))
  		return -EFAULT;
6b96018b2   Arnd Bergmann   compat: move sock...
2436
  	return dev_ioctl(net, SIOCETHTOOL, ifr);
7a229387d   Arnd Bergmann   net: copy socket ...
2437
  }
7a50a240c   Arnd Bergmann   net/compat_ioctl:...
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
  static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32)
  {
  	void __user *uptr;
  	compat_uptr_t uptr32;
  	struct ifreq __user *uifr;
  
  	uifr = compat_alloc_user_space(sizeof (*uifr));
  	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...
2458
2459
  static int bond_ioctl(struct net *net, unsigned int cmd,
  			 struct compat_ifreq __user *ifr32)
7a229387d   Arnd Bergmann   net: copy socket ...
2460
2461
2462
  {
  	struct ifreq kifr;
  	struct ifreq __user *uifr;
7a229387d   Arnd Bergmann   net: copy socket ...
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
  	mm_segment_t old_fs;
  	int err;
  	u32 data;
  	void __user *datap;
  
  	switch (cmd) {
  	case SIOCBONDENSLAVE:
  	case SIOCBONDRELEASE:
  	case SIOCBONDSETHWADDR:
  	case SIOCBONDCHANGEACTIVE:
6b96018b2   Arnd Bergmann   compat: move sock...
2473
  		if (copy_from_user(&kifr, ifr32, sizeof(struct compat_ifreq)))
7a229387d   Arnd Bergmann   net: copy socket ...
2474
2475
2476
2477
  			return -EFAULT;
  
  		old_fs = get_fs();
  		set_fs (KERNEL_DS);
6b96018b2   Arnd Bergmann   compat: move sock...
2478
  		err = dev_ioctl(net, cmd, &kifr);
7a229387d   Arnd Bergmann   net: copy socket ...
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
  		set_fs (old_fs);
  
  		return err;
  	case SIOCBONDSLAVEINFOQUERY:
  	case SIOCBONDINFOQUERY:
  		uifr = compat_alloc_user_space(sizeof(*uifr));
  		if (copy_in_user(&uifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
  			return -EFAULT;
  
  		if (get_user(data, &ifr32->ifr_ifru.ifru_data))
  			return -EFAULT;
  
  		datap = compat_ptr(data);
  		if (put_user(datap, &uifr->ifr_ifru.ifru_data))
  			return -EFAULT;
6b96018b2   Arnd Bergmann   compat: move sock...
2494
  		return dev_ioctl(net, cmd, uifr);
7a229387d   Arnd Bergmann   net: copy socket ...
2495
2496
2497
2498
  	default:
  		return -EINVAL;
  	};
  }
6b96018b2   Arnd Bergmann   compat: move sock...
2499
2500
  static int siocdevprivate_ioctl(struct net *net, unsigned int cmd,
  				 struct compat_ifreq __user *u_ifreq32)
7a229387d   Arnd Bergmann   net: copy socket ...
2501
2502
  {
  	struct ifreq __user *u_ifreq64;
7a229387d   Arnd Bergmann   net: copy socket ...
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
  	char tmp_buf[IFNAMSIZ];
  	void __user *data64;
  	u32 data32;
  
  	if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]),
  			   IFNAMSIZ))
  		return -EFAULT;
  	if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data))
  		return -EFAULT;
  	data64 = compat_ptr(data32);
  
  	u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
  
  	/* Don't check these user accesses, just let that get trapped
  	 * in the ioctl handler instead.
  	 */
  	if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0],
  			 IFNAMSIZ))
  		return -EFAULT;
  	if (__put_user(data64, &u_ifreq64->ifr_ifru.ifru_data))
  		return -EFAULT;
6b96018b2   Arnd Bergmann   compat: move sock...
2524
  	return dev_ioctl(net, cmd, u_ifreq64);
7a229387d   Arnd Bergmann   net: copy socket ...
2525
  }
6b96018b2   Arnd Bergmann   compat: move sock...
2526
2527
  static int dev_ifsioc(struct net *net, struct socket *sock,
  			 unsigned int cmd, struct compat_ifreq __user *uifr32)
7a229387d   Arnd Bergmann   net: copy socket ...
2528
  {
a2116ed22   Arnd Bergmann   net/compat: fix d...
2529
  	struct ifreq __user *uifr;
7a229387d   Arnd Bergmann   net: copy socket ...
2530
  	int err;
a2116ed22   Arnd Bergmann   net/compat: fix d...
2531
2532
2533
2534
2535
  	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 ...
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
  	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...
2548
  		case SIOCGIFPFLAGS:
7a229387d   Arnd Bergmann   net: copy socket ...
2549
  		case SIOCGIFTXQLEN:
fab2532ba   Arnd Bergmann   net, compat_ioctl...
2550
2551
  		case SIOCGMIIPHY:
  		case SIOCGMIIREG:
a2116ed22   Arnd Bergmann   net/compat: fix d...
2552
  			if (copy_in_user(uifr32, uifr, sizeof(*uifr32)))
7a229387d   Arnd Bergmann   net: copy socket ...
2553
2554
2555
2556
2557
2558
  				err = -EFAULT;
  			break;
  		}
  	}
  	return err;
  }
a2116ed22   Arnd Bergmann   net/compat: fix d...
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
  static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
  			struct compat_ifreq __user *uifr32)
  {
  	struct ifreq ifr;
  	struct compat_ifmap __user *uifmap32;
  	mm_segment_t old_fs;
  	int err;
  
  	uifmap32 = &uifr32->ifr_ifru.ifru_map;
  	err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name));
  	err |= __get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
  	err |= __get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
  	err |= __get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
  	err |= __get_user(ifr.ifr_map.irq, &uifmap32->irq);
  	err |= __get_user(ifr.ifr_map.dma, &uifmap32->dma);
  	err |= __get_user(ifr.ifr_map.port, &uifmap32->port);
  	if (err)
  		return -EFAULT;
  
  	old_fs = get_fs();
  	set_fs (KERNEL_DS);
  	err = dev_ioctl(net, cmd, (void __user *)&ifr);
  	set_fs (old_fs);
  
  	if (cmd == SIOCGIFMAP && !err) {
  		err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name));
  		err |= __put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
  		err |= __put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
  		err |= __put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
  		err |= __put_user(ifr.ifr_map.irq, &uifmap32->irq);
  		err |= __put_user(ifr.ifr_map.dma, &uifmap32->dma);
  		err |= __put_user(ifr.ifr_map.port, &uifmap32->port);
  		if (err)
  			err = -EFAULT;
  	}
  	return err;
  }
  
  static int compat_siocshwtstamp(struct net *net, struct compat_ifreq __user *uifr32)
  {
  	void __user *uptr;
  	compat_uptr_t uptr32;
  	struct ifreq __user *uifr;
  
  	uifr = compat_alloc_user_space(sizeof (*uifr));
  	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
  		return -EFAULT;
  
  	if (get_user(uptr32, &uifr32->ifr_data))
  		return -EFAULT;
  
  	uptr = compat_ptr(uptr32);
  
  	if (put_user(uptr, &uifr->ifr_data))
  		return -EFAULT;
  
  	return dev_ioctl(net, SIOCSHWTSTAMP, uifr);
  }
7a229387d   Arnd Bergmann   net: copy socket ...
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
  struct rtentry32 {
  	u32   		rt_pad1;
  	struct sockaddr rt_dst;         /* target address               */
  	struct sockaddr rt_gateway;     /* gateway addr (RTF_GATEWAY)   */
  	struct sockaddr rt_genmask;     /* target network mask (IP)     */
  	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! */
  	/* char * */ u32 rt_dev;        /* forcing the device at add    */
  	u32   		rt_mtu;         /* per route MTU/Window         */
  	u32   		rt_window;      /* Window clamping              */
  	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...
2647
2648
  static int routing_ioctl(struct net *net, struct socket *sock,
  			 unsigned int cmd, void __user *argp)
7a229387d   Arnd Bergmann   net: copy socket ...
2649
2650
2651
2652
2653
2654
2655
2656
  {
  	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...
2657
2658
  	if (sock && sock->sk && sock->sk->sk_family == AF_INET6) { /* ipv6 */
  		struct in6_rtmsg32 __user *ur6 = argp;
7a229387d   Arnd Bergmann   net: copy socket ...
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
  		ret = copy_from_user (&r6.rtmsg_dst, &(ur6->rtmsg_dst),
  			3 * sizeof(struct in6_addr));
  		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));
  
  		r = (void *) &r6;
  	} else { /* ipv4 */
6b96018b2   Arnd Bergmann   compat: move sock...
2671
  		struct rtentry32 __user *ur4 = argp;
7a229387d   Arnd Bergmann   net: copy socket ...
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
  		ret = copy_from_user (&r4.rt_dst, &(ur4->rt_dst),
  					3 * sizeof(struct sockaddr));
  		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));
  		if (rtdev) {
  			ret |= copy_from_user (devname, compat_ptr(rtdev), 15);
  			r4.rt_dev = devname; devname[15] = 0;
  		} else
  			r4.rt_dev = NULL;
  
  		r = (void *) &r4;
  	}
  
  	if (ret) {
  		ret = -EFAULT;
  		goto out;
  	}
  
  	set_fs (KERNEL_DS);
6b96018b2   Arnd Bergmann   compat: move sock...
2695
  	ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r);
7a229387d   Arnd Bergmann   net: copy socket ...
2696
2697
2698
  	set_fs (old_fs);
  
  out:
7a229387d   Arnd Bergmann   net: copy socket ...
2699
2700
2701
2702
2703
2704
2705
  	return ret;
  }
  
  /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE
   * for some operations; this forces use of the newer bridge-utils that
   * use compatiable ioctls
   */
6b96018b2   Arnd Bergmann   compat: move sock...
2706
  static int old_bridge_ioctl(compat_ulong_t __user *argp)
7a229387d   Arnd Bergmann   net: copy socket ...
2707
  {
6b96018b2   Arnd Bergmann   compat: move sock...
2708
  	compat_ulong_t tmp;
7a229387d   Arnd Bergmann   net: copy socket ...
2709

6b96018b2   Arnd Bergmann   compat: move sock...
2710
  	if (get_user(tmp, argp))
7a229387d   Arnd Bergmann   net: copy socket ...
2711
2712
2713
2714
2715
  		return -EFAULT;
  	if (tmp == BRCTL_GET_VERSION)
  		return BRCTL_VERSION + 1;
  	return -EINVAL;
  }
6b96018b2   Arnd Bergmann   compat: move sock...
2716
2717
2718
2719
2720
2721
  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 ...
2722

6b96018b2   Arnd Bergmann   compat: move sock...
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
  	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
  		return siocdevprivate_ioctl(net, cmd, argp);
  
  	switch (cmd) {
  	case SIOCSIFBR:
  	case SIOCGIFBR:
  		return old_bridge_ioctl(argp);
  	case SIOCGIFNAME:
  		return dev_ifname32(net, argp);
  	case SIOCGIFCONF:
  		return dev_ifconf(net, argp);
  	case SIOCETHTOOL:
  		return ethtool_ioctl(net, argp);
7a50a240c   Arnd Bergmann   net/compat_ioctl:...
2736
2737
  	case SIOCWANDEV:
  		return compat_siocwandev(net, argp);
a2116ed22   Arnd Bergmann   net/compat: fix d...
2738
2739
2740
  	case SIOCGIFMAP:
  	case SIOCSIFMAP:
  		return compat_sioc_ifmap(net, cmd, argp);
6b96018b2   Arnd Bergmann   compat: move sock...
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
  	case SIOCBONDENSLAVE:
  	case SIOCBONDRELEASE:
  	case SIOCBONDSETHWADDR:
  	case SIOCBONDSLAVEINFOQUERY:
  	case SIOCBONDINFOQUERY:
  	case SIOCBONDCHANGEACTIVE:
  		return bond_ioctl(net, cmd, argp);
  	case SIOCADDRT:
  	case SIOCDELRT:
  		return routing_ioctl(net, sock, cmd, argp);
  	case SIOCGSTAMP:
  		return do_siocgstamp(net, sock, cmd, argp);
  	case SIOCGSTAMPNS:
  		return do_siocgstampns(net, sock, cmd, argp);
a2116ed22   Arnd Bergmann   net/compat: fix d...
2755
2756
  	case SIOCSHWTSTAMP:
  		return compat_siocshwtstamp(net, argp);
6b96018b2   Arnd Bergmann   compat: move sock...
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
  
  	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...
2783
2784
2785
  	case SIOCGIFADDR:
  	case SIOCSIFADDR:
  	case SIOCSIFHWBROADCAST:
6b96018b2   Arnd Bergmann   compat: move sock...
2786
  	case SIOCDIFADDR:
6b96018b2   Arnd Bergmann   compat: move sock...
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
  	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...
2799
2800
2801
2802
  	case SIOCSIFNAME:
  	case SIOCGMIIPHY:
  	case SIOCGMIIREG:
  	case SIOCSMIIREG:
6b96018b2   Arnd Bergmann   compat: move sock...
2803
  		return dev_ifsioc(net, sock, cmd, argp);
9177efd39   Arnd Bergmann   net, compat_ioctl...
2804

6b96018b2   Arnd Bergmann   compat: move sock...
2805
2806
2807
  	case SIOCSARP:
  	case SIOCGARP:
  	case SIOCDARP:
6b96018b2   Arnd Bergmann   compat: move sock...
2808
  	case SIOCATMARK:
9177efd39   Arnd Bergmann   net, compat_ioctl...
2809
2810
2811
2812
2813
2814
2815
2816
  		return sock_do_ioctl(net, sock, cmd, arg);
  	}
  
  	/* Prevent warning from compat_sys_ioctl, these always
  	 * result in -EINVAL in the native case anyway. */
  	switch (cmd) {
  	case SIOCRTMSG:
  	case SIOCGIFCOUNT:
6b96018b2   Arnd Bergmann   compat: move sock...
2817
2818
2819
  	case SIOCSRARP:
  	case SIOCGRARP:
  	case SIOCDRARP:
9177efd39   Arnd Bergmann   net, compat_ioctl...
2820
2821
2822
2823
  	case SIOCSIFLINK:
  	case SIOCGIFSLAVE:
  	case SIOCSIFSLAVE:
  		return -EINVAL;
6b96018b2   Arnd Bergmann   compat: move sock...
2824
2825
2826
2827
  	}
  
  	return -ENOIOCTLCMD;
  }
7a229387d   Arnd Bergmann   net: copy socket ...
2828

89bbfc95d   Shaun Pereira   [NET]: allow 32 b...
2829
  static long compat_sock_ioctl(struct file *file, unsigned cmd,
89bddce58   Stephen Hemminger   [NET] socket: cod...
2830
  			      unsigned long arg)
89bbfc95d   Shaun Pereira   [NET]: allow 32 b...
2831
2832
2833
  {
  	struct socket *sock = file->private_data;
  	int ret = -ENOIOCTLCMD;
87de87d5e   David S. Miller   wext: Dispatch an...
2834
2835
2836
2837
2838
  	struct sock *sk;
  	struct net *net;
  
  	sk = sock->sk;
  	net = sock_net(sk);
89bbfc95d   Shaun Pereira   [NET]: allow 32 b...
2839
2840
2841
  
  	if (sock->ops->compat_ioctl)
  		ret = sock->ops->compat_ioctl(sock, cmd, arg);
87de87d5e   David S. Miller   wext: Dispatch an...
2842
2843
2844
  	if (ret == -ENOIOCTLCMD &&
  	    (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST))
  		ret = compat_wext_handle_ioctl(net, cmd, arg);
6b96018b2   Arnd Bergmann   compat: move sock...
2845
2846
  	if (ret == -ENOIOCTLCMD)
  		ret = compat_sock_ioctl_trans(file, sock, cmd, arg);
89bbfc95d   Shaun Pereira   [NET]: allow 32 b...
2847
2848
2849
  	return ret;
  }
  #endif
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
  int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
  {
  	return sock->ops->bind(sock, addr, addrlen);
  }
  
  int kernel_listen(struct socket *sock, int backlog)
  {
  	return sock->ops->listen(sock, backlog);
  }
  
  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...
2873
  		*newsock = NULL;
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
2874
2875
2876
2877
  		goto done;
  	}
  
  	(*newsock)->ops = sock->ops;
1b08534e5   Wei Yongjun   net: Fix module r...
2878
  	__module_get((*newsock)->ops->owner);
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
2879
2880
2881
2882
2883
2884
  
  done:
  	return err;
  }
  
  int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
4768fbcbc   YOSHIFUJI Hideaki   [NET]: Fix whites...
2885
  		   int flags)
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
  {
  	return sock->ops->connect(sock, addr, addrlen, flags);
  }
  
  int kernel_getsockname(struct socket *sock, struct sockaddr *addr,
  			 int *addrlen)
  {
  	return sock->ops->getname(sock, addr, addrlen, 0);
  }
  
  int kernel_getpeername(struct socket *sock, struct sockaddr *addr,
  			 int *addrlen)
  {
  	return sock->ops->getname(sock, addr, addrlen, 1);
  }
  
  int kernel_getsockopt(struct socket *sock, int level, int optname,
  			char *optval, int *optlen)
  {
  	mm_segment_t oldfs = get_fs();
  	int err;
  
  	set_fs(KERNEL_DS);
  	if (level == SOL_SOCKET)
  		err = sock_getsockopt(sock, level, optname, optval, optlen);
  	else
  		err = sock->ops->getsockopt(sock, level, optname, optval,
  					    optlen);
  	set_fs(oldfs);
  	return err;
  }
  
  int kernel_setsockopt(struct socket *sock, int level, int optname,
b7058842c   David S. Miller   net: Make setsock...
2919
  			char *optval, unsigned int optlen)
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
  {
  	mm_segment_t oldfs = get_fs();
  	int err;
  
  	set_fs(KERNEL_DS);
  	if (level == SOL_SOCKET)
  		err = sock_setsockopt(sock, level, optname, optval, optlen);
  	else
  		err = sock->ops->setsockopt(sock, level, optname, optval,
  					    optlen);
  	set_fs(oldfs);
  	return err;
  }
  
  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);
  }
  
  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;
  }
91cf45f02   Trond Myklebust   [NET]: Add the he...
2954
2955
2956
2957
  int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
  {
  	return sock->ops->shutdown(sock, how);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
  EXPORT_SYMBOL(sock_create);
  EXPORT_SYMBOL(sock_create_kern);
  EXPORT_SYMBOL(sock_create_lite);
  EXPORT_SYMBOL(sock_map_fd);
  EXPORT_SYMBOL(sock_recvmsg);
  EXPORT_SYMBOL(sock_register);
  EXPORT_SYMBOL(sock_release);
  EXPORT_SYMBOL(sock_sendmsg);
  EXPORT_SYMBOL(sock_unregister);
  EXPORT_SYMBOL(sock_wake_async);
  EXPORT_SYMBOL(sockfd_lookup);
  EXPORT_SYMBOL(kernel_sendmsg);
  EXPORT_SYMBOL(kernel_recvmsg);
ac5a488ef   Sridhar Samudrala   [NET]: Round out ...
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
  EXPORT_SYMBOL(kernel_bind);
  EXPORT_SYMBOL(kernel_listen);
  EXPORT_SYMBOL(kernel_accept);
  EXPORT_SYMBOL(kernel_connect);
  EXPORT_SYMBOL(kernel_getsockname);
  EXPORT_SYMBOL(kernel_getpeername);
  EXPORT_SYMBOL(kernel_getsockopt);
  EXPORT_SYMBOL(kernel_setsockopt);
  EXPORT_SYMBOL(kernel_sendpage);
  EXPORT_SYMBOL(kernel_sock_ioctl);
91cf45f02   Trond Myklebust   [NET]: Add the he...
2981
  EXPORT_SYMBOL(kernel_sock_shutdown);