xref: /openbmc/linux/net/socket.c (revision 894dc24c)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * NET		An implementation of the SOCKET network access protocol.
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Version:	@(#)socket.c	1.1.93	18/02/95
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * Authors:	Orest Zborowski, <obz@Kodak.COM>
702c30a84SJesper Juhl  *		Ross Biro
81da177e4SLinus Torvalds  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
91da177e4SLinus Torvalds  *
101da177e4SLinus Torvalds  * Fixes:
111da177e4SLinus Torvalds  *		Anonymous	:	NOTSOCK/BADF cleanup. Error fix in
121da177e4SLinus Torvalds  *					shutdown()
131da177e4SLinus Torvalds  *		Alan Cox	:	verify_area() fixes
141da177e4SLinus Torvalds  *		Alan Cox	:	Removed DDI
151da177e4SLinus Torvalds  *		Jonathan Kamens	:	SOCK_DGRAM reconnect bug
161da177e4SLinus Torvalds  *		Alan Cox	:	Moved a load of checks to the very
171da177e4SLinus Torvalds  *					top level.
181da177e4SLinus Torvalds  *		Alan Cox	:	Move address structures to/from user
191da177e4SLinus Torvalds  *					mode above the protocol layers.
201da177e4SLinus Torvalds  *		Rob Janssen	:	Allow 0 length sends.
211da177e4SLinus Torvalds  *		Alan Cox	:	Asynchronous I/O support (cribbed from the
221da177e4SLinus Torvalds  *					tty drivers).
231da177e4SLinus Torvalds  *		Niibe Yutaka	:	Asynchronous I/O for writes (4.4BSD style)
241da177e4SLinus Torvalds  *		Jeff Uphoff	:	Made max number of sockets command-line
251da177e4SLinus Torvalds  *					configurable.
261da177e4SLinus Torvalds  *		Matti Aarnio	:	Made the number of sockets dynamic,
271da177e4SLinus Torvalds  *					to be allocated when needed, and mr.
281da177e4SLinus Torvalds  *					Uphoff's max is used as max to be
291da177e4SLinus Torvalds  *					allowed to allocate.
301da177e4SLinus Torvalds  *		Linus		:	Argh. removed all the socket allocation
311da177e4SLinus Torvalds  *					altogether: it's in the inode now.
321da177e4SLinus Torvalds  *		Alan Cox	:	Made sock_alloc()/sock_release() public
331da177e4SLinus Torvalds  *					for NetROM and future kernel nfsd type
341da177e4SLinus Torvalds  *					stuff.
351da177e4SLinus Torvalds  *		Alan Cox	:	sendmsg/recvmsg basics.
361da177e4SLinus Torvalds  *		Tom Dyas	:	Export net symbols.
371da177e4SLinus Torvalds  *		Marcin Dalecki	:	Fixed problems with CONFIG_NET="n".
381da177e4SLinus Torvalds  *		Alan Cox	:	Added thread locking to sys_* calls
391da177e4SLinus Torvalds  *					for sockets. May have errors at the
401da177e4SLinus Torvalds  *					moment.
411da177e4SLinus Torvalds  *		Kevin Buhr	:	Fixed the dumb errors in the above.
421da177e4SLinus Torvalds  *		Andi Kleen	:	Some small cleanups, optimizations,
431da177e4SLinus Torvalds  *					and fixed a copy_from_user() bug.
441da177e4SLinus Torvalds  *		Tigran Aivazian	:	sys_send(args) calls sys_sendto(args, NULL, 0)
451da177e4SLinus Torvalds  *		Tigran Aivazian	:	Made listen(2) backlog sanity checks
461da177e4SLinus Torvalds  *					protocol-independent
471da177e4SLinus Torvalds  *
481da177e4SLinus Torvalds  *
491da177e4SLinus Torvalds  *		This program is free software; you can redistribute it and/or
501da177e4SLinus Torvalds  *		modify it under the terms of the GNU General Public License
511da177e4SLinus Torvalds  *		as published by the Free Software Foundation; either version
521da177e4SLinus Torvalds  *		2 of the License, or (at your option) any later version.
531da177e4SLinus Torvalds  *
541da177e4SLinus Torvalds  *
551da177e4SLinus Torvalds  *	This module is effectively the top level interface to the BSD socket
561da177e4SLinus Torvalds  *	paradigm.
571da177e4SLinus Torvalds  *
581da177e4SLinus Torvalds  *	Based upon Swansea University Computer Society NET3.039
591da177e4SLinus Torvalds  */
601da177e4SLinus Torvalds 
611da177e4SLinus Torvalds #include <linux/mm.h>
621da177e4SLinus Torvalds #include <linux/socket.h>
631da177e4SLinus Torvalds #include <linux/file.h>
641da177e4SLinus Torvalds #include <linux/net.h>
651da177e4SLinus Torvalds #include <linux/interrupt.h>
66aaca0bdcSUlrich Drepper #include <linux/thread_info.h>
6755737fdaSStephen Hemminger #include <linux/rcupdate.h>
681da177e4SLinus Torvalds #include <linux/netdevice.h>
691da177e4SLinus Torvalds #include <linux/proc_fs.h>
701da177e4SLinus Torvalds #include <linux/seq_file.h>
714a3e2f71SArjan van de Ven #include <linux/mutex.h>
721da177e4SLinus Torvalds #include <linux/wanrouter.h>
731da177e4SLinus Torvalds #include <linux/if_bridge.h>
7420380731SArnaldo Carvalho de Melo #include <linux/if_frad.h>
7520380731SArnaldo Carvalho de Melo #include <linux/if_vlan.h>
761da177e4SLinus Torvalds #include <linux/init.h>
771da177e4SLinus Torvalds #include <linux/poll.h>
781da177e4SLinus Torvalds #include <linux/cache.h>
791da177e4SLinus Torvalds #include <linux/module.h>
801da177e4SLinus Torvalds #include <linux/highmem.h>
811da177e4SLinus Torvalds #include <linux/mount.h>
821da177e4SLinus Torvalds #include <linux/security.h>
831da177e4SLinus Torvalds #include <linux/syscalls.h>
841da177e4SLinus Torvalds #include <linux/compat.h>
851da177e4SLinus Torvalds #include <linux/kmod.h>
863ec3b2fbSDavid Woodhouse #include <linux/audit.h>
87d86b5e0eSAdrian Bunk #include <linux/wireless.h>
881b8d7ae4SEric W. Biederman #include <linux/nsproxy.h>
891fd7317dSNick Black #include <linux/magic.h>
905a0e3ad6STejun Heo #include <linux/slab.h>
911da177e4SLinus Torvalds 
921da177e4SLinus Torvalds #include <asm/uaccess.h>
931da177e4SLinus Torvalds #include <asm/unistd.h>
941da177e4SLinus Torvalds 
951da177e4SLinus Torvalds #include <net/compat.h>
9687de87d5SDavid S. Miller #include <net/wext.h>
97f8451725SHerbert Xu #include <net/cls_cgroup.h>
981da177e4SLinus Torvalds 
991da177e4SLinus Torvalds #include <net/sock.h>
1001da177e4SLinus Torvalds #include <linux/netfilter.h>
1011da177e4SLinus Torvalds 
1026b96018bSArnd Bergmann #include <linux/if_tun.h>
1036b96018bSArnd Bergmann #include <linux/ipv6_route.h>
1046b96018bSArnd Bergmann #include <linux/route.h>
1056b96018bSArnd Bergmann #include <linux/sockios.h>
1066b96018bSArnd Bergmann #include <linux/atalk.h>
1076b96018bSArnd Bergmann 
1081da177e4SLinus Torvalds static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
109027445c3SBadari Pulavarty static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
110027445c3SBadari Pulavarty 			 unsigned long nr_segs, loff_t pos);
111027445c3SBadari Pulavarty static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
112027445c3SBadari Pulavarty 			  unsigned long nr_segs, loff_t pos);
1131da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma);
1141da177e4SLinus Torvalds 
1151da177e4SLinus Torvalds static int sock_close(struct inode *inode, struct file *file);
1161da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file,
1171da177e4SLinus Torvalds 			      struct poll_table_struct *wait);
11889bddce5SStephen Hemminger static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
11989bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
12089bbfc95SShaun Pereira static long compat_sock_ioctl(struct file *file,
12189bbfc95SShaun Pereira 			      unsigned int cmd, unsigned long arg);
12289bbfc95SShaun Pereira #endif
1231da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on);
1241da177e4SLinus Torvalds static ssize_t sock_sendpage(struct file *file, struct page *page,
1251da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more);
1269c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
1279c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
1289c55e01cSJens Axboe 				unsigned int flags);
1291da177e4SLinus Torvalds 
1301da177e4SLinus Torvalds /*
1311da177e4SLinus Torvalds  *	Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
1321da177e4SLinus Torvalds  *	in the operation structures but are done directly via the socketcall() multiplexor.
1331da177e4SLinus Torvalds  */
1341da177e4SLinus Torvalds 
135da7071d7SArjan van de Ven static const struct file_operations socket_file_ops = {
1361da177e4SLinus Torvalds 	.owner =	THIS_MODULE,
1371da177e4SLinus Torvalds 	.llseek =	no_llseek,
1381da177e4SLinus Torvalds 	.aio_read =	sock_aio_read,
1391da177e4SLinus Torvalds 	.aio_write =	sock_aio_write,
1401da177e4SLinus Torvalds 	.poll =		sock_poll,
1411da177e4SLinus Torvalds 	.unlocked_ioctl = sock_ioctl,
14289bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
14389bbfc95SShaun Pereira 	.compat_ioctl = compat_sock_ioctl,
14489bbfc95SShaun Pereira #endif
1451da177e4SLinus Torvalds 	.mmap =		sock_mmap,
1461da177e4SLinus Torvalds 	.open =		sock_no_open,	/* special open code to disallow open via /proc */
1471da177e4SLinus Torvalds 	.release =	sock_close,
1481da177e4SLinus Torvalds 	.fasync =	sock_fasync,
1495274f052SJens Axboe 	.sendpage =	sock_sendpage,
1505274f052SJens Axboe 	.splice_write = generic_splice_sendpage,
1519c55e01cSJens Axboe 	.splice_read =	sock_splice_read,
1521da177e4SLinus Torvalds };
1531da177e4SLinus Torvalds 
1541da177e4SLinus Torvalds /*
1551da177e4SLinus Torvalds  *	The protocol list. Each protocol is registered in here.
1561da177e4SLinus Torvalds  */
1571da177e4SLinus Torvalds 
1581da177e4SLinus Torvalds static DEFINE_SPINLOCK(net_family_lock);
159190683a9SEric Dumazet static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly;
1601da177e4SLinus Torvalds 
1611da177e4SLinus Torvalds /*
1621da177e4SLinus Torvalds  *	Statistics counters of the socket lists
1631da177e4SLinus Torvalds  */
1641da177e4SLinus Torvalds 
165c6d409cfSEric Dumazet static DEFINE_PER_CPU(int, sockets_in_use);
1661da177e4SLinus Torvalds 
1671da177e4SLinus Torvalds /*
16889bddce5SStephen Hemminger  * Support routines.
16989bddce5SStephen Hemminger  * Move socket addresses back and forth across the kernel/user
1701da177e4SLinus Torvalds  * divide and look after the messy bits.
1711da177e4SLinus Torvalds  */
1721da177e4SLinus Torvalds 
1731da177e4SLinus Torvalds /**
1741da177e4SLinus Torvalds  *	move_addr_to_kernel	-	copy a socket address into kernel space
1751da177e4SLinus Torvalds  *	@uaddr: Address in user space
1761da177e4SLinus Torvalds  *	@kaddr: Address in kernel space
1771da177e4SLinus Torvalds  *	@ulen: Length in user space
1781da177e4SLinus Torvalds  *
1791da177e4SLinus Torvalds  *	The address is copied into kernel space. If the provided address is
1801da177e4SLinus Torvalds  *	too long an error code of -EINVAL is returned. If the copy gives
1811da177e4SLinus Torvalds  *	invalid addresses -EFAULT is returned. On a success 0 is returned.
1821da177e4SLinus Torvalds  */
1831da177e4SLinus Torvalds 
184230b1839SYOSHIFUJI Hideaki int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr *kaddr)
1851da177e4SLinus Torvalds {
186230b1839SYOSHIFUJI Hideaki 	if (ulen < 0 || ulen > sizeof(struct sockaddr_storage))
1871da177e4SLinus Torvalds 		return -EINVAL;
1881da177e4SLinus Torvalds 	if (ulen == 0)
1891da177e4SLinus Torvalds 		return 0;
1901da177e4SLinus Torvalds 	if (copy_from_user(kaddr, uaddr, ulen))
1911da177e4SLinus Torvalds 		return -EFAULT;
1923ec3b2fbSDavid Woodhouse 	return audit_sockaddr(ulen, kaddr);
1931da177e4SLinus Torvalds }
1941da177e4SLinus Torvalds 
1951da177e4SLinus Torvalds /**
1961da177e4SLinus Torvalds  *	move_addr_to_user	-	copy an address to user space
1971da177e4SLinus Torvalds  *	@kaddr: kernel space address
1981da177e4SLinus Torvalds  *	@klen: length of address in kernel
1991da177e4SLinus Torvalds  *	@uaddr: user space address
2001da177e4SLinus Torvalds  *	@ulen: pointer to user length field
2011da177e4SLinus Torvalds  *
2021da177e4SLinus Torvalds  *	The value pointed to by ulen on entry is the buffer length available.
2031da177e4SLinus Torvalds  *	This is overwritten with the buffer space used. -EINVAL is returned
2041da177e4SLinus Torvalds  *	if an overlong buffer is specified or a negative buffer size. -EFAULT
2051da177e4SLinus Torvalds  *	is returned if either the buffer or the length field are not
2061da177e4SLinus Torvalds  *	accessible.
2071da177e4SLinus Torvalds  *	After copying the data up to the limit the user specifies, the true
2081da177e4SLinus Torvalds  *	length of the data is written over the length limit the user
2091da177e4SLinus Torvalds  *	specified. Zero is returned for a success.
2101da177e4SLinus Torvalds  */
2111da177e4SLinus Torvalds 
21211165f14Sstephen hemminger static int move_addr_to_user(struct sockaddr *kaddr, int klen,
21311165f14Sstephen hemminger 			     void __user *uaddr, int __user *ulen)
2141da177e4SLinus Torvalds {
2151da177e4SLinus Torvalds 	int err;
2161da177e4SLinus Torvalds 	int len;
2171da177e4SLinus Torvalds 
21889bddce5SStephen Hemminger 	err = get_user(len, ulen);
21989bddce5SStephen Hemminger 	if (err)
2201da177e4SLinus Torvalds 		return err;
2211da177e4SLinus Torvalds 	if (len > klen)
2221da177e4SLinus Torvalds 		len = klen;
223230b1839SYOSHIFUJI Hideaki 	if (len < 0 || len > sizeof(struct sockaddr_storage))
2241da177e4SLinus Torvalds 		return -EINVAL;
22589bddce5SStephen Hemminger 	if (len) {
226d6fe3945SSteve Grubb 		if (audit_sockaddr(klen, kaddr))
227d6fe3945SSteve Grubb 			return -ENOMEM;
2281da177e4SLinus Torvalds 		if (copy_to_user(uaddr, kaddr, len))
2291da177e4SLinus Torvalds 			return -EFAULT;
2301da177e4SLinus Torvalds 	}
2311da177e4SLinus Torvalds 	/*
2321da177e4SLinus Torvalds 	 *      "fromlen shall refer to the value before truncation.."
2331da177e4SLinus Torvalds 	 *                      1003.1g
2341da177e4SLinus Torvalds 	 */
2351da177e4SLinus Torvalds 	return __put_user(klen, ulen);
2361da177e4SLinus Torvalds }
2371da177e4SLinus Torvalds 
238e18b890bSChristoph Lameter static struct kmem_cache *sock_inode_cachep __read_mostly;
2391da177e4SLinus Torvalds 
2401da177e4SLinus Torvalds static struct inode *sock_alloc_inode(struct super_block *sb)
2411da177e4SLinus Torvalds {
2421da177e4SLinus Torvalds 	struct socket_alloc *ei;
243eaefd110SEric Dumazet 	struct socket_wq *wq;
24489bddce5SStephen Hemminger 
245e94b1766SChristoph Lameter 	ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL);
2461da177e4SLinus Torvalds 	if (!ei)
2471da177e4SLinus Torvalds 		return NULL;
248eaefd110SEric Dumazet 	wq = kmalloc(sizeof(*wq), GFP_KERNEL);
249eaefd110SEric Dumazet 	if (!wq) {
25043815482SEric Dumazet 		kmem_cache_free(sock_inode_cachep, ei);
25143815482SEric Dumazet 		return NULL;
25243815482SEric Dumazet 	}
253eaefd110SEric Dumazet 	init_waitqueue_head(&wq->wait);
254eaefd110SEric Dumazet 	wq->fasync_list = NULL;
255eaefd110SEric Dumazet 	RCU_INIT_POINTER(ei->socket.wq, wq);
2561da177e4SLinus Torvalds 
2571da177e4SLinus Torvalds 	ei->socket.state = SS_UNCONNECTED;
2581da177e4SLinus Torvalds 	ei->socket.flags = 0;
2591da177e4SLinus Torvalds 	ei->socket.ops = NULL;
2601da177e4SLinus Torvalds 	ei->socket.sk = NULL;
2611da177e4SLinus Torvalds 	ei->socket.file = NULL;
2621da177e4SLinus Torvalds 
2631da177e4SLinus Torvalds 	return &ei->vfs_inode;
2641da177e4SLinus Torvalds }
2651da177e4SLinus Torvalds 
2661da177e4SLinus Torvalds static void sock_destroy_inode(struct inode *inode)
2671da177e4SLinus Torvalds {
26843815482SEric Dumazet 	struct socket_alloc *ei;
269eaefd110SEric Dumazet 	struct socket_wq *wq;
27043815482SEric Dumazet 
27143815482SEric Dumazet 	ei = container_of(inode, struct socket_alloc, vfs_inode);
272eaefd110SEric Dumazet 	wq = rcu_dereference_protected(ei->socket.wq, 1);
27361845220SLai Jiangshan 	kfree_rcu(wq, rcu);
27443815482SEric Dumazet 	kmem_cache_free(sock_inode_cachep, ei);
2751da177e4SLinus Torvalds }
2761da177e4SLinus Torvalds 
27751cc5068SAlexey Dobriyan static void init_once(void *foo)
2781da177e4SLinus Torvalds {
2791da177e4SLinus Torvalds 	struct socket_alloc *ei = (struct socket_alloc *)foo;
2801da177e4SLinus Torvalds 
2811da177e4SLinus Torvalds 	inode_init_once(&ei->vfs_inode);
2821da177e4SLinus Torvalds }
2831da177e4SLinus Torvalds 
2841da177e4SLinus Torvalds static int init_inodecache(void)
2851da177e4SLinus Torvalds {
2861da177e4SLinus Torvalds 	sock_inode_cachep = kmem_cache_create("sock_inode_cache",
2871da177e4SLinus Torvalds 					      sizeof(struct socket_alloc),
28889bddce5SStephen Hemminger 					      0,
28989bddce5SStephen Hemminger 					      (SLAB_HWCACHE_ALIGN |
29089bddce5SStephen Hemminger 					       SLAB_RECLAIM_ACCOUNT |
291fffb60f9SPaul Jackson 					       SLAB_MEM_SPREAD),
29220c2df83SPaul Mundt 					      init_once);
2931da177e4SLinus Torvalds 	if (sock_inode_cachep == NULL)
2941da177e4SLinus Torvalds 		return -ENOMEM;
2951da177e4SLinus Torvalds 	return 0;
2961da177e4SLinus Torvalds }
2971da177e4SLinus Torvalds 
298b87221deSAlexey Dobriyan static const struct super_operations sockfs_ops = {
2991da177e4SLinus Torvalds 	.alloc_inode	= sock_alloc_inode,
3001da177e4SLinus Torvalds 	.destroy_inode	= sock_destroy_inode,
3011da177e4SLinus Torvalds 	.statfs		= simple_statfs,
3021da177e4SLinus Torvalds };
3031da177e4SLinus Torvalds 
304c23fbb6bSEric Dumazet /*
305c23fbb6bSEric Dumazet  * sockfs_dname() is called from d_path().
306c23fbb6bSEric Dumazet  */
307c23fbb6bSEric Dumazet static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen)
308c23fbb6bSEric Dumazet {
309c23fbb6bSEric Dumazet 	return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]",
310c23fbb6bSEric Dumazet 				dentry->d_inode->i_ino);
311c23fbb6bSEric Dumazet }
312c23fbb6bSEric Dumazet 
3133ba13d17SAl Viro static const struct dentry_operations sockfs_dentry_operations = {
314c23fbb6bSEric Dumazet 	.d_dname  = sockfs_dname,
3151da177e4SLinus Torvalds };
3161da177e4SLinus Torvalds 
317c74a1cbbSAl Viro static struct dentry *sockfs_mount(struct file_system_type *fs_type,
318c74a1cbbSAl Viro 			 int flags, const char *dev_name, void *data)
319c74a1cbbSAl Viro {
320c74a1cbbSAl Viro 	return mount_pseudo(fs_type, "socket:", &sockfs_ops,
321c74a1cbbSAl Viro 		&sockfs_dentry_operations, SOCKFS_MAGIC);
322c74a1cbbSAl Viro }
323c74a1cbbSAl Viro 
324c74a1cbbSAl Viro static struct vfsmount *sock_mnt __read_mostly;
325c74a1cbbSAl Viro 
326c74a1cbbSAl Viro static struct file_system_type sock_fs_type = {
327c74a1cbbSAl Viro 	.name =		"sockfs",
328c74a1cbbSAl Viro 	.mount =	sockfs_mount,
329c74a1cbbSAl Viro 	.kill_sb =	kill_anon_super,
330c74a1cbbSAl Viro };
331c74a1cbbSAl Viro 
3321da177e4SLinus Torvalds /*
3331da177e4SLinus Torvalds  *	Obtains the first available file descriptor and sets it up for use.
3341da177e4SLinus Torvalds  *
33539d8c1b6SDavid S. Miller  *	These functions create file structures and maps them to fd space
33639d8c1b6SDavid S. Miller  *	of the current process. On success it returns file descriptor
3371da177e4SLinus Torvalds  *	and file struct implicitly stored in sock->file.
3381da177e4SLinus Torvalds  *	Note that another thread may close file descriptor before we return
3391da177e4SLinus Torvalds  *	from this function. We use the fact that now we do not refer
3401da177e4SLinus Torvalds  *	to socket after mapping. If one day we will need it, this
3411da177e4SLinus Torvalds  *	function will increment ref. count on file by 1.
3421da177e4SLinus Torvalds  *
3431da177e4SLinus Torvalds  *	In any case returned fd MAY BE not valid!
3441da177e4SLinus Torvalds  *	This race condition is unavoidable
3451da177e4SLinus Torvalds  *	with shared fd spaces, we cannot solve it inside kernel,
3461da177e4SLinus Torvalds  *	but we take care of internal coherence yet.
3471da177e4SLinus Torvalds  */
3481da177e4SLinus Torvalds 
3497cbe66b6SAl Viro static int sock_alloc_file(struct socket *sock, struct file **f, int flags)
3501da177e4SLinus Torvalds {
3517cbe66b6SAl Viro 	struct qstr name = { .name = "" };
3522c48b9c4SAl Viro 	struct path path;
3537cbe66b6SAl Viro 	struct file *file;
3541da177e4SLinus Torvalds 	int fd;
3551da177e4SLinus Torvalds 
356a677a039SUlrich Drepper 	fd = get_unused_fd_flags(flags);
3577cbe66b6SAl Viro 	if (unlikely(fd < 0))
3587cbe66b6SAl Viro 		return fd;
3591da177e4SLinus Torvalds 
3604b936885SNick Piggin 	path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name);
3612c48b9c4SAl Viro 	if (unlikely(!path.dentry)) {
3627cbe66b6SAl Viro 		put_unused_fd(fd);
36339d8c1b6SDavid S. Miller 		return -ENOMEM;
3647cbe66b6SAl Viro 	}
3652c48b9c4SAl Viro 	path.mnt = mntget(sock_mnt);
36639d8c1b6SDavid S. Miller 
3672c48b9c4SAl Viro 	d_instantiate(path.dentry, SOCK_INODE(sock));
368cc3808f8SAl Viro 	SOCK_INODE(sock)->i_fop = &socket_file_ops;
369cc3808f8SAl Viro 
3702c48b9c4SAl Viro 	file = alloc_file(&path, FMODE_READ | FMODE_WRITE,
371cc3808f8SAl Viro 		  &socket_file_ops);
372cc3808f8SAl Viro 	if (unlikely(!file)) {
373cc3808f8SAl Viro 		/* drop dentry, keep inode */
3747de9c6eeSAl Viro 		ihold(path.dentry->d_inode);
3752c48b9c4SAl Viro 		path_put(&path);
376cc3808f8SAl Viro 		put_unused_fd(fd);
377cc3808f8SAl Viro 		return -ENFILE;
378cc3808f8SAl Viro 	}
3791da177e4SLinus Torvalds 
3801da177e4SLinus Torvalds 	sock->file = file;
38177d27200SUlrich Drepper 	file->f_flags = O_RDWR | (flags & O_NONBLOCK);
3821da177e4SLinus Torvalds 	file->f_pos = 0;
38307dc3f07SBenjamin LaHaise 	file->private_data = sock;
38439d8c1b6SDavid S. Miller 
3857cbe66b6SAl Viro 	*f = file;
3867cbe66b6SAl Viro 	return fd;
3871da177e4SLinus Torvalds }
3881da177e4SLinus Torvalds 
389a677a039SUlrich Drepper int sock_map_fd(struct socket *sock, int flags)
39039d8c1b6SDavid S. Miller {
39139d8c1b6SDavid S. Miller 	struct file *newfile;
3927cbe66b6SAl Viro 	int fd = sock_alloc_file(sock, &newfile, flags);
39339d8c1b6SDavid S. Miller 
3947cbe66b6SAl Viro 	if (likely(fd >= 0))
39539d8c1b6SDavid S. Miller 		fd_install(fd, newfile);
3967cbe66b6SAl Viro 
3971da177e4SLinus Torvalds 	return fd;
3981da177e4SLinus Torvalds }
399c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_map_fd);
4001da177e4SLinus Torvalds 
4016cb153caSBenjamin LaHaise static struct socket *sock_from_file(struct file *file, int *err)
4026cb153caSBenjamin LaHaise {
4036cb153caSBenjamin LaHaise 	if (file->f_op == &socket_file_ops)
4046cb153caSBenjamin LaHaise 		return file->private_data;	/* set in sock_map_fd */
4056cb153caSBenjamin LaHaise 
4066cb153caSBenjamin LaHaise 	*err = -ENOTSOCK;
4076cb153caSBenjamin LaHaise 	return NULL;
4086cb153caSBenjamin LaHaise }
4096cb153caSBenjamin LaHaise 
4101da177e4SLinus Torvalds /**
4111da177e4SLinus Torvalds  *	sockfd_lookup - Go from a file number to its socket slot
4121da177e4SLinus Torvalds  *	@fd: file handle
4131da177e4SLinus Torvalds  *	@err: pointer to an error code return
4141da177e4SLinus Torvalds  *
4151da177e4SLinus Torvalds  *	The file handle passed in is locked and the socket it is bound
4161da177e4SLinus Torvalds  *	too is returned. If an error occurs the err pointer is overwritten
4171da177e4SLinus Torvalds  *	with a negative errno code and NULL is returned. The function checks
4181da177e4SLinus Torvalds  *	for both invalid handles and passing a handle which is not a socket.
4191da177e4SLinus Torvalds  *
4201da177e4SLinus Torvalds  *	On a success the socket object pointer is returned.
4211da177e4SLinus Torvalds  */
4221da177e4SLinus Torvalds 
4231da177e4SLinus Torvalds struct socket *sockfd_lookup(int fd, int *err)
4241da177e4SLinus Torvalds {
4251da177e4SLinus Torvalds 	struct file *file;
4261da177e4SLinus Torvalds 	struct socket *sock;
4271da177e4SLinus Torvalds 
42889bddce5SStephen Hemminger 	file = fget(fd);
42989bddce5SStephen Hemminger 	if (!file) {
4301da177e4SLinus Torvalds 		*err = -EBADF;
4311da177e4SLinus Torvalds 		return NULL;
4321da177e4SLinus Torvalds 	}
43389bddce5SStephen Hemminger 
4346cb153caSBenjamin LaHaise 	sock = sock_from_file(file, err);
4356cb153caSBenjamin LaHaise 	if (!sock)
4361da177e4SLinus Torvalds 		fput(file);
4376cb153caSBenjamin LaHaise 	return sock;
4381da177e4SLinus Torvalds }
439c6d409cfSEric Dumazet EXPORT_SYMBOL(sockfd_lookup);
4401da177e4SLinus Torvalds 
4416cb153caSBenjamin LaHaise static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
4426cb153caSBenjamin LaHaise {
4436cb153caSBenjamin LaHaise 	struct file *file;
4446cb153caSBenjamin LaHaise 	struct socket *sock;
4456cb153caSBenjamin LaHaise 
4463672558cSHua Zhong 	*err = -EBADF;
4476cb153caSBenjamin LaHaise 	file = fget_light(fd, fput_needed);
4486cb153caSBenjamin LaHaise 	if (file) {
4496cb153caSBenjamin LaHaise 		sock = sock_from_file(file, err);
4506cb153caSBenjamin LaHaise 		if (sock)
4511da177e4SLinus Torvalds 			return sock;
4526cb153caSBenjamin LaHaise 		fput_light(file, *fput_needed);
4536cb153caSBenjamin LaHaise 	}
4546cb153caSBenjamin LaHaise 	return NULL;
4551da177e4SLinus Torvalds }
4561da177e4SLinus Torvalds 
4571da177e4SLinus Torvalds /**
4581da177e4SLinus Torvalds  *	sock_alloc	-	allocate a socket
4591da177e4SLinus Torvalds  *
4601da177e4SLinus Torvalds  *	Allocate a new inode and socket object. The two are bound together
4611da177e4SLinus Torvalds  *	and initialised. The socket is then returned. If we are out of inodes
4621da177e4SLinus Torvalds  *	NULL is returned.
4631da177e4SLinus Torvalds  */
4641da177e4SLinus Torvalds 
4651da177e4SLinus Torvalds static struct socket *sock_alloc(void)
4661da177e4SLinus Torvalds {
4671da177e4SLinus Torvalds 	struct inode *inode;
4681da177e4SLinus Torvalds 	struct socket *sock;
4691da177e4SLinus Torvalds 
4701da177e4SLinus Torvalds 	inode = new_inode(sock_mnt->mnt_sb);
4711da177e4SLinus Torvalds 	if (!inode)
4721da177e4SLinus Torvalds 		return NULL;
4731da177e4SLinus Torvalds 
4741da177e4SLinus Torvalds 	sock = SOCKET_I(inode);
4751da177e4SLinus Torvalds 
47629a020d3SEric Dumazet 	kmemcheck_annotate_bitfield(sock, type);
47785fe4025SChristoph Hellwig 	inode->i_ino = get_next_ino();
4781da177e4SLinus Torvalds 	inode->i_mode = S_IFSOCK | S_IRWXUGO;
4798192b0c4SDavid Howells 	inode->i_uid = current_fsuid();
4808192b0c4SDavid Howells 	inode->i_gid = current_fsgid();
4811da177e4SLinus Torvalds 
4824e69489aSEric Dumazet 	percpu_add(sockets_in_use, 1);
4831da177e4SLinus Torvalds 	return sock;
4841da177e4SLinus Torvalds }
4851da177e4SLinus Torvalds 
4861da177e4SLinus Torvalds /*
4871da177e4SLinus Torvalds  *	In theory you can't get an open on this inode, but /proc provides
4881da177e4SLinus Torvalds  *	a back door. Remember to keep it shut otherwise you'll let the
4891da177e4SLinus Torvalds  *	creepy crawlies in.
4901da177e4SLinus Torvalds  */
4911da177e4SLinus Torvalds 
4921da177e4SLinus Torvalds static int sock_no_open(struct inode *irrelevant, struct file *dontcare)
4931da177e4SLinus Torvalds {
4941da177e4SLinus Torvalds 	return -ENXIO;
4951da177e4SLinus Torvalds }
4961da177e4SLinus Torvalds 
4974b6f5d20SArjan van de Ven const struct file_operations bad_sock_fops = {
4981da177e4SLinus Torvalds 	.owner = THIS_MODULE,
4991da177e4SLinus Torvalds 	.open = sock_no_open,
5006038f373SArnd Bergmann 	.llseek = noop_llseek,
5011da177e4SLinus Torvalds };
5021da177e4SLinus Torvalds 
5031da177e4SLinus Torvalds /**
5041da177e4SLinus Torvalds  *	sock_release	-	close a socket
5051da177e4SLinus Torvalds  *	@sock: socket to close
5061da177e4SLinus Torvalds  *
5071da177e4SLinus Torvalds  *	The socket is released from the protocol stack if it has a release
5081da177e4SLinus Torvalds  *	callback, and the inode is then released if the socket is bound to
5091da177e4SLinus Torvalds  *	an inode not a file.
5101da177e4SLinus Torvalds  */
5111da177e4SLinus Torvalds 
5121da177e4SLinus Torvalds void sock_release(struct socket *sock)
5131da177e4SLinus Torvalds {
5141da177e4SLinus Torvalds 	if (sock->ops) {
5151da177e4SLinus Torvalds 		struct module *owner = sock->ops->owner;
5161da177e4SLinus Torvalds 
5171da177e4SLinus Torvalds 		sock->ops->release(sock);
5181da177e4SLinus Torvalds 		sock->ops = NULL;
5191da177e4SLinus Torvalds 		module_put(owner);
5201da177e4SLinus Torvalds 	}
5211da177e4SLinus Torvalds 
522eaefd110SEric Dumazet 	if (rcu_dereference_protected(sock->wq, 1)->fasync_list)
5231da177e4SLinus Torvalds 		printk(KERN_ERR "sock_release: fasync list not empty!\n");
5241da177e4SLinus Torvalds 
5254e69489aSEric Dumazet 	percpu_sub(sockets_in_use, 1);
5261da177e4SLinus Torvalds 	if (!sock->file) {
5271da177e4SLinus Torvalds 		iput(SOCK_INODE(sock));
5281da177e4SLinus Torvalds 		return;
5291da177e4SLinus Torvalds 	}
5301da177e4SLinus Torvalds 	sock->file = NULL;
5311da177e4SLinus Torvalds }
532c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_release);
5331da177e4SLinus Torvalds 
5342244d07bSOliver Hartkopp int sock_tx_timestamp(struct sock *sk, __u8 *tx_flags)
53520d49473SPatrick Ohly {
5362244d07bSOliver Hartkopp 	*tx_flags = 0;
53720d49473SPatrick Ohly 	if (sock_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE))
5382244d07bSOliver Hartkopp 		*tx_flags |= SKBTX_HW_TSTAMP;
53920d49473SPatrick Ohly 	if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE))
5402244d07bSOliver Hartkopp 		*tx_flags |= SKBTX_SW_TSTAMP;
54120d49473SPatrick Ohly 	return 0;
54220d49473SPatrick Ohly }
54320d49473SPatrick Ohly EXPORT_SYMBOL(sock_tx_timestamp);
54420d49473SPatrick Ohly 
545228e548eSAnton Blanchard static inline int __sock_sendmsg_nosec(struct kiocb *iocb, struct socket *sock,
5461da177e4SLinus Torvalds 				       struct msghdr *msg, size_t size)
5471da177e4SLinus Torvalds {
5481da177e4SLinus Torvalds 	struct sock_iocb *si = kiocb_to_siocb(iocb);
5491da177e4SLinus Torvalds 
550f8451725SHerbert Xu 	sock_update_classid(sock->sk);
551f8451725SHerbert Xu 
5521da177e4SLinus Torvalds 	si->sock = sock;
5531da177e4SLinus Torvalds 	si->scm = NULL;
5541da177e4SLinus Torvalds 	si->msg = msg;
5551da177e4SLinus Torvalds 	si->size = size;
5561da177e4SLinus Torvalds 
5571da177e4SLinus Torvalds 	return sock->ops->sendmsg(iocb, sock, msg, size);
5581da177e4SLinus Torvalds }
5591da177e4SLinus Torvalds 
560228e548eSAnton Blanchard static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock,
561228e548eSAnton Blanchard 				 struct msghdr *msg, size_t size)
562228e548eSAnton Blanchard {
563228e548eSAnton Blanchard 	int err = security_socket_sendmsg(sock, msg, size);
564228e548eSAnton Blanchard 
565228e548eSAnton Blanchard 	return err ?: __sock_sendmsg_nosec(iocb, sock, msg, size);
566228e548eSAnton Blanchard }
567228e548eSAnton Blanchard 
5681da177e4SLinus Torvalds int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
5691da177e4SLinus Torvalds {
5701da177e4SLinus Torvalds 	struct kiocb iocb;
5711da177e4SLinus Torvalds 	struct sock_iocb siocb;
5721da177e4SLinus Torvalds 	int ret;
5731da177e4SLinus Torvalds 
5741da177e4SLinus Torvalds 	init_sync_kiocb(&iocb, NULL);
5751da177e4SLinus Torvalds 	iocb.private = &siocb;
5761da177e4SLinus Torvalds 	ret = __sock_sendmsg(&iocb, sock, msg, size);
5771da177e4SLinus Torvalds 	if (-EIOCBQUEUED == ret)
5781da177e4SLinus Torvalds 		ret = wait_on_sync_kiocb(&iocb);
5791da177e4SLinus Torvalds 	return ret;
5801da177e4SLinus Torvalds }
581c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_sendmsg);
5821da177e4SLinus Torvalds 
583894dc24cSEric Dumazet static int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg, size_t size)
584228e548eSAnton Blanchard {
585228e548eSAnton Blanchard 	struct kiocb iocb;
586228e548eSAnton Blanchard 	struct sock_iocb siocb;
587228e548eSAnton Blanchard 	int ret;
588228e548eSAnton Blanchard 
589228e548eSAnton Blanchard 	init_sync_kiocb(&iocb, NULL);
590228e548eSAnton Blanchard 	iocb.private = &siocb;
591228e548eSAnton Blanchard 	ret = __sock_sendmsg_nosec(&iocb, sock, msg, size);
592228e548eSAnton Blanchard 	if (-EIOCBQUEUED == ret)
593228e548eSAnton Blanchard 		ret = wait_on_sync_kiocb(&iocb);
594228e548eSAnton Blanchard 	return ret;
595228e548eSAnton Blanchard }
596228e548eSAnton Blanchard 
5971da177e4SLinus Torvalds int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
5981da177e4SLinus Torvalds 		   struct kvec *vec, size_t num, size_t size)
5991da177e4SLinus Torvalds {
6001da177e4SLinus Torvalds 	mm_segment_t oldfs = get_fs();
6011da177e4SLinus Torvalds 	int result;
6021da177e4SLinus Torvalds 
6031da177e4SLinus Torvalds 	set_fs(KERNEL_DS);
6041da177e4SLinus Torvalds 	/*
6051da177e4SLinus Torvalds 	 * the following is safe, since for compiler definitions of kvec and
6061da177e4SLinus Torvalds 	 * iovec are identical, yielding the same in-core layout and alignment
6071da177e4SLinus Torvalds 	 */
60889bddce5SStephen Hemminger 	msg->msg_iov = (struct iovec *)vec;
6091da177e4SLinus Torvalds 	msg->msg_iovlen = num;
6101da177e4SLinus Torvalds 	result = sock_sendmsg(sock, msg, size);
6111da177e4SLinus Torvalds 	set_fs(oldfs);
6121da177e4SLinus Torvalds 	return result;
6131da177e4SLinus Torvalds }
614c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendmsg);
6151da177e4SLinus Torvalds 
61620d49473SPatrick Ohly static int ktime2ts(ktime_t kt, struct timespec *ts)
61720d49473SPatrick Ohly {
61820d49473SPatrick Ohly 	if (kt.tv64) {
61920d49473SPatrick Ohly 		*ts = ktime_to_timespec(kt);
62020d49473SPatrick Ohly 		return 1;
62120d49473SPatrick Ohly 	} else {
62220d49473SPatrick Ohly 		return 0;
62320d49473SPatrick Ohly 	}
62420d49473SPatrick Ohly }
62520d49473SPatrick Ohly 
62692f37fd2SEric Dumazet /*
62792f37fd2SEric Dumazet  * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
62892f37fd2SEric Dumazet  */
62992f37fd2SEric Dumazet void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
63092f37fd2SEric Dumazet 	struct sk_buff *skb)
63192f37fd2SEric Dumazet {
63220d49473SPatrick Ohly 	int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
63320d49473SPatrick Ohly 	struct timespec ts[3];
63420d49473SPatrick Ohly 	int empty = 1;
63520d49473SPatrick Ohly 	struct skb_shared_hwtstamps *shhwtstamps =
63620d49473SPatrick Ohly 		skb_hwtstamps(skb);
63792f37fd2SEric Dumazet 
63820d49473SPatrick Ohly 	/* Race occurred between timestamp enabling and packet
63920d49473SPatrick Ohly 	   receiving.  Fill in the current time for now. */
64020d49473SPatrick Ohly 	if (need_software_tstamp && skb->tstamp.tv64 == 0)
64120d49473SPatrick Ohly 		__net_timestamp(skb);
64220d49473SPatrick Ohly 
64320d49473SPatrick Ohly 	if (need_software_tstamp) {
64492f37fd2SEric Dumazet 		if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
64592f37fd2SEric Dumazet 			struct timeval tv;
64620d49473SPatrick Ohly 			skb_get_timestamp(skb, &tv);
64720d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP,
64820d49473SPatrick Ohly 				 sizeof(tv), &tv);
64992f37fd2SEric Dumazet 		} else {
650842509b8SHagen Paul Pfeifer 			skb_get_timestampns(skb, &ts[0]);
65120d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS,
652842509b8SHagen Paul Pfeifer 				 sizeof(ts[0]), &ts[0]);
65392f37fd2SEric Dumazet 		}
65492f37fd2SEric Dumazet 	}
65592f37fd2SEric Dumazet 
65620d49473SPatrick Ohly 
65720d49473SPatrick Ohly 	memset(ts, 0, sizeof(ts));
65820d49473SPatrick Ohly 	if (skb->tstamp.tv64 &&
65920d49473SPatrick Ohly 	    sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE)) {
66020d49473SPatrick Ohly 		skb_get_timestampns(skb, ts + 0);
66120d49473SPatrick Ohly 		empty = 0;
66220d49473SPatrick Ohly 	}
66320d49473SPatrick Ohly 	if (shhwtstamps) {
66420d49473SPatrick Ohly 		if (sock_flag(sk, SOCK_TIMESTAMPING_SYS_HARDWARE) &&
66520d49473SPatrick Ohly 		    ktime2ts(shhwtstamps->syststamp, ts + 1))
66620d49473SPatrick Ohly 			empty = 0;
66720d49473SPatrick Ohly 		if (sock_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE) &&
66820d49473SPatrick Ohly 		    ktime2ts(shhwtstamps->hwtstamp, ts + 2))
66920d49473SPatrick Ohly 			empty = 0;
67020d49473SPatrick Ohly 	}
67120d49473SPatrick Ohly 	if (!empty)
67220d49473SPatrick Ohly 		put_cmsg(msg, SOL_SOCKET,
67320d49473SPatrick Ohly 			 SCM_TIMESTAMPING, sizeof(ts), &ts);
67420d49473SPatrick Ohly }
6757c81fd8bSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
6767c81fd8bSArnaldo Carvalho de Melo 
67711165f14Sstephen hemminger static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk,
67811165f14Sstephen hemminger 				   struct sk_buff *skb)
6793b885787SNeil Horman {
6803b885787SNeil Horman 	if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && skb->dropcount)
6813b885787SNeil Horman 		put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL,
6823b885787SNeil Horman 			sizeof(__u32), &skb->dropcount);
6833b885787SNeil Horman }
6843b885787SNeil Horman 
685767dd033SEric Dumazet void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
6863b885787SNeil Horman 	struct sk_buff *skb)
6873b885787SNeil Horman {
6883b885787SNeil Horman 	sock_recv_timestamp(msg, sk, skb);
6893b885787SNeil Horman 	sock_recv_drops(msg, sk, skb);
6903b885787SNeil Horman }
691767dd033SEric Dumazet EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops);
6923b885787SNeil Horman 
693a2e27255SArnaldo Carvalho de Melo static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock,
6941da177e4SLinus Torvalds 				       struct msghdr *msg, size_t size, int flags)
6951da177e4SLinus Torvalds {
6961da177e4SLinus Torvalds 	struct sock_iocb *si = kiocb_to_siocb(iocb);
6971da177e4SLinus Torvalds 
698f8451725SHerbert Xu 	sock_update_classid(sock->sk);
699f8451725SHerbert Xu 
7001da177e4SLinus Torvalds 	si->sock = sock;
7011da177e4SLinus Torvalds 	si->scm = NULL;
7021da177e4SLinus Torvalds 	si->msg = msg;
7031da177e4SLinus Torvalds 	si->size = size;
7041da177e4SLinus Torvalds 	si->flags = flags;
7051da177e4SLinus Torvalds 
7061da177e4SLinus Torvalds 	return sock->ops->recvmsg(iocb, sock, msg, size, flags);
7071da177e4SLinus Torvalds }
7081da177e4SLinus Torvalds 
709a2e27255SArnaldo Carvalho de Melo static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock,
710a2e27255SArnaldo Carvalho de Melo 				 struct msghdr *msg, size_t size, int flags)
711a2e27255SArnaldo Carvalho de Melo {
712a2e27255SArnaldo Carvalho de Melo 	int err = security_socket_recvmsg(sock, msg, size, flags);
713a2e27255SArnaldo Carvalho de Melo 
714a2e27255SArnaldo Carvalho de Melo 	return err ?: __sock_recvmsg_nosec(iocb, sock, msg, size, flags);
715a2e27255SArnaldo Carvalho de Melo }
716a2e27255SArnaldo Carvalho de Melo 
7171da177e4SLinus Torvalds int sock_recvmsg(struct socket *sock, struct msghdr *msg,
7181da177e4SLinus Torvalds 		 size_t size, int flags)
7191da177e4SLinus Torvalds {
7201da177e4SLinus Torvalds 	struct kiocb iocb;
7211da177e4SLinus Torvalds 	struct sock_iocb siocb;
7221da177e4SLinus Torvalds 	int ret;
7231da177e4SLinus Torvalds 
7241da177e4SLinus Torvalds 	init_sync_kiocb(&iocb, NULL);
7251da177e4SLinus Torvalds 	iocb.private = &siocb;
7261da177e4SLinus Torvalds 	ret = __sock_recvmsg(&iocb, sock, msg, size, flags);
7271da177e4SLinus Torvalds 	if (-EIOCBQUEUED == ret)
7281da177e4SLinus Torvalds 		ret = wait_on_sync_kiocb(&iocb);
7291da177e4SLinus Torvalds 	return ret;
7301da177e4SLinus Torvalds }
731c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_recvmsg);
7321da177e4SLinus Torvalds 
733a2e27255SArnaldo Carvalho de Melo static int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
734a2e27255SArnaldo Carvalho de Melo 			      size_t size, int flags)
735a2e27255SArnaldo Carvalho de Melo {
736a2e27255SArnaldo Carvalho de Melo 	struct kiocb iocb;
737a2e27255SArnaldo Carvalho de Melo 	struct sock_iocb siocb;
738a2e27255SArnaldo Carvalho de Melo 	int ret;
739a2e27255SArnaldo Carvalho de Melo 
740a2e27255SArnaldo Carvalho de Melo 	init_sync_kiocb(&iocb, NULL);
741a2e27255SArnaldo Carvalho de Melo 	iocb.private = &siocb;
742a2e27255SArnaldo Carvalho de Melo 	ret = __sock_recvmsg_nosec(&iocb, sock, msg, size, flags);
743a2e27255SArnaldo Carvalho de Melo 	if (-EIOCBQUEUED == ret)
744a2e27255SArnaldo Carvalho de Melo 		ret = wait_on_sync_kiocb(&iocb);
745a2e27255SArnaldo Carvalho de Melo 	return ret;
746a2e27255SArnaldo Carvalho de Melo }
747a2e27255SArnaldo Carvalho de Melo 
748c1249c0aSMartin Lucina /**
749c1249c0aSMartin Lucina  * kernel_recvmsg - Receive a message from a socket (kernel space)
750c1249c0aSMartin Lucina  * @sock:       The socket to receive the message from
751c1249c0aSMartin Lucina  * @msg:        Received message
752c1249c0aSMartin Lucina  * @vec:        Input s/g array for message data
753c1249c0aSMartin Lucina  * @num:        Size of input s/g array
754c1249c0aSMartin Lucina  * @size:       Number of bytes to read
755c1249c0aSMartin Lucina  * @flags:      Message flags (MSG_DONTWAIT, etc...)
756c1249c0aSMartin Lucina  *
757c1249c0aSMartin Lucina  * On return the msg structure contains the scatter/gather array passed in the
758c1249c0aSMartin Lucina  * vec argument. The array is modified so that it consists of the unfilled
759c1249c0aSMartin Lucina  * portion of the original array.
760c1249c0aSMartin Lucina  *
761c1249c0aSMartin Lucina  * The returned value is the total number of bytes received, or an error.
762c1249c0aSMartin Lucina  */
7631da177e4SLinus Torvalds int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
76489bddce5SStephen Hemminger 		   struct kvec *vec, size_t num, size_t size, int flags)
7651da177e4SLinus Torvalds {
7661da177e4SLinus Torvalds 	mm_segment_t oldfs = get_fs();
7671da177e4SLinus Torvalds 	int result;
7681da177e4SLinus Torvalds 
7691da177e4SLinus Torvalds 	set_fs(KERNEL_DS);
7701da177e4SLinus Torvalds 	/*
7711da177e4SLinus Torvalds 	 * the following is safe, since for compiler definitions of kvec and
7721da177e4SLinus Torvalds 	 * iovec are identical, yielding the same in-core layout and alignment
7731da177e4SLinus Torvalds 	 */
77489bddce5SStephen Hemminger 	msg->msg_iov = (struct iovec *)vec, msg->msg_iovlen = num;
7751da177e4SLinus Torvalds 	result = sock_recvmsg(sock, msg, size, flags);
7761da177e4SLinus Torvalds 	set_fs(oldfs);
7771da177e4SLinus Torvalds 	return result;
7781da177e4SLinus Torvalds }
779c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_recvmsg);
7801da177e4SLinus Torvalds 
7811da177e4SLinus Torvalds static void sock_aio_dtor(struct kiocb *iocb)
7821da177e4SLinus Torvalds {
7831da177e4SLinus Torvalds 	kfree(iocb->private);
7841da177e4SLinus Torvalds }
7851da177e4SLinus Torvalds 
78620380731SArnaldo Carvalho de Melo static ssize_t sock_sendpage(struct file *file, struct page *page,
7871da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more)
7881da177e4SLinus Torvalds {
7891da177e4SLinus Torvalds 	struct socket *sock;
7901da177e4SLinus Torvalds 	int flags;
7911da177e4SLinus Torvalds 
792b69aee04SEric Dumazet 	sock = file->private_data;
7931da177e4SLinus Torvalds 
7941da177e4SLinus Torvalds 	flags = !(file->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT;
7951da177e4SLinus Torvalds 	if (more)
7961da177e4SLinus Torvalds 		flags |= MSG_MORE;
7971da177e4SLinus Torvalds 
798e6949583SLinus Torvalds 	return kernel_sendpage(sock, page, offset, size, flags);
7991da177e4SLinus Torvalds }
8001da177e4SLinus Torvalds 
8019c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
8029c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
8039c55e01cSJens Axboe 				unsigned int flags)
8049c55e01cSJens Axboe {
8059c55e01cSJens Axboe 	struct socket *sock = file->private_data;
8069c55e01cSJens Axboe 
807997b37daSRémi Denis-Courmont 	if (unlikely(!sock->ops->splice_read))
808997b37daSRémi Denis-Courmont 		return -EINVAL;
809997b37daSRémi Denis-Courmont 
810f8451725SHerbert Xu 	sock_update_classid(sock->sk);
811f8451725SHerbert Xu 
8129c55e01cSJens Axboe 	return sock->ops->splice_read(sock, ppos, pipe, len, flags);
8139c55e01cSJens Axboe }
8149c55e01cSJens Axboe 
815ce1d4d3eSChristoph Hellwig static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
81689bddce5SStephen Hemminger 					 struct sock_iocb *siocb)
817ce1d4d3eSChristoph Hellwig {
818ce1d4d3eSChristoph Hellwig 	if (!is_sync_kiocb(iocb)) {
819ce1d4d3eSChristoph Hellwig 		siocb = kmalloc(sizeof(*siocb), GFP_KERNEL);
820ce1d4d3eSChristoph Hellwig 		if (!siocb)
821ce1d4d3eSChristoph Hellwig 			return NULL;
822ce1d4d3eSChristoph Hellwig 		iocb->ki_dtor = sock_aio_dtor;
823ce1d4d3eSChristoph Hellwig 	}
824ce1d4d3eSChristoph Hellwig 
825ce1d4d3eSChristoph Hellwig 	siocb->kiocb = iocb;
826ce1d4d3eSChristoph Hellwig 	iocb->private = siocb;
827ce1d4d3eSChristoph Hellwig 	return siocb;
828ce1d4d3eSChristoph Hellwig }
829ce1d4d3eSChristoph Hellwig 
830ce1d4d3eSChristoph Hellwig static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb,
831027445c3SBadari Pulavarty 		struct file *file, const struct iovec *iov,
83289bddce5SStephen Hemminger 		unsigned long nr_segs)
833ce1d4d3eSChristoph Hellwig {
834ce1d4d3eSChristoph Hellwig 	struct socket *sock = file->private_data;
835ce1d4d3eSChristoph Hellwig 	size_t size = 0;
836ce1d4d3eSChristoph Hellwig 	int i;
837ce1d4d3eSChristoph Hellwig 
838ce1d4d3eSChristoph Hellwig 	for (i = 0; i < nr_segs; i++)
839ce1d4d3eSChristoph Hellwig 		size += iov[i].iov_len;
840ce1d4d3eSChristoph Hellwig 
841ce1d4d3eSChristoph Hellwig 	msg->msg_name = NULL;
842ce1d4d3eSChristoph Hellwig 	msg->msg_namelen = 0;
843ce1d4d3eSChristoph Hellwig 	msg->msg_control = NULL;
844ce1d4d3eSChristoph Hellwig 	msg->msg_controllen = 0;
845ce1d4d3eSChristoph Hellwig 	msg->msg_iov = (struct iovec *)iov;
846ce1d4d3eSChristoph Hellwig 	msg->msg_iovlen = nr_segs;
847ce1d4d3eSChristoph Hellwig 	msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
848ce1d4d3eSChristoph Hellwig 
849ce1d4d3eSChristoph Hellwig 	return __sock_recvmsg(iocb, sock, msg, size, msg->msg_flags);
850ce1d4d3eSChristoph Hellwig }
851ce1d4d3eSChristoph Hellwig 
852027445c3SBadari Pulavarty static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
853027445c3SBadari Pulavarty 				unsigned long nr_segs, loff_t pos)
854ce1d4d3eSChristoph Hellwig {
855ce1d4d3eSChristoph Hellwig 	struct sock_iocb siocb, *x;
856ce1d4d3eSChristoph Hellwig 
857ce1d4d3eSChristoph Hellwig 	if (pos != 0)
858ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
859027445c3SBadari Pulavarty 
860027445c3SBadari Pulavarty 	if (iocb->ki_left == 0)	/* Match SYS5 behaviour */
861ce1d4d3eSChristoph Hellwig 		return 0;
862ce1d4d3eSChristoph Hellwig 
863027445c3SBadari Pulavarty 
864027445c3SBadari Pulavarty 	x = alloc_sock_iocb(iocb, &siocb);
865ce1d4d3eSChristoph Hellwig 	if (!x)
866ce1d4d3eSChristoph Hellwig 		return -ENOMEM;
867027445c3SBadari Pulavarty 	return do_sock_read(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
868ce1d4d3eSChristoph Hellwig }
869ce1d4d3eSChristoph Hellwig 
870ce1d4d3eSChristoph Hellwig static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb,
871027445c3SBadari Pulavarty 			struct file *file, const struct iovec *iov,
87289bddce5SStephen Hemminger 			unsigned long nr_segs)
873ce1d4d3eSChristoph Hellwig {
874ce1d4d3eSChristoph Hellwig 	struct socket *sock = file->private_data;
875ce1d4d3eSChristoph Hellwig 	size_t size = 0;
876ce1d4d3eSChristoph Hellwig 	int i;
877ce1d4d3eSChristoph Hellwig 
878ce1d4d3eSChristoph Hellwig 	for (i = 0; i < nr_segs; i++)
879ce1d4d3eSChristoph Hellwig 		size += iov[i].iov_len;
880ce1d4d3eSChristoph Hellwig 
881ce1d4d3eSChristoph Hellwig 	msg->msg_name = NULL;
882ce1d4d3eSChristoph Hellwig 	msg->msg_namelen = 0;
883ce1d4d3eSChristoph Hellwig 	msg->msg_control = NULL;
884ce1d4d3eSChristoph Hellwig 	msg->msg_controllen = 0;
885ce1d4d3eSChristoph Hellwig 	msg->msg_iov = (struct iovec *)iov;
886ce1d4d3eSChristoph Hellwig 	msg->msg_iovlen = nr_segs;
887ce1d4d3eSChristoph Hellwig 	msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
888ce1d4d3eSChristoph Hellwig 	if (sock->type == SOCK_SEQPACKET)
889ce1d4d3eSChristoph Hellwig 		msg->msg_flags |= MSG_EOR;
890ce1d4d3eSChristoph Hellwig 
891ce1d4d3eSChristoph Hellwig 	return __sock_sendmsg(iocb, sock, msg, size);
892ce1d4d3eSChristoph Hellwig }
893ce1d4d3eSChristoph Hellwig 
894027445c3SBadari Pulavarty static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
895027445c3SBadari Pulavarty 			  unsigned long nr_segs, loff_t pos)
8961da177e4SLinus Torvalds {
897ce1d4d3eSChristoph Hellwig 	struct sock_iocb siocb, *x;
8981da177e4SLinus Torvalds 
899ce1d4d3eSChristoph Hellwig 	if (pos != 0)
900ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
901027445c3SBadari Pulavarty 
902027445c3SBadari Pulavarty 	x = alloc_sock_iocb(iocb, &siocb);
903ce1d4d3eSChristoph Hellwig 	if (!x)
904ce1d4d3eSChristoph Hellwig 		return -ENOMEM;
905ce1d4d3eSChristoph Hellwig 
906027445c3SBadari Pulavarty 	return do_sock_write(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
9071da177e4SLinus Torvalds }
9081da177e4SLinus Torvalds 
9091da177e4SLinus Torvalds /*
9101da177e4SLinus Torvalds  * Atomic setting of ioctl hooks to avoid race
9111da177e4SLinus Torvalds  * with module unload.
9121da177e4SLinus Torvalds  */
9131da177e4SLinus Torvalds 
9144a3e2f71SArjan van de Ven static DEFINE_MUTEX(br_ioctl_mutex);
915c6d409cfSEric Dumazet static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg);
9161da177e4SLinus Torvalds 
917881d966bSEric W. Biederman void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *))
9181da177e4SLinus Torvalds {
9194a3e2f71SArjan van de Ven 	mutex_lock(&br_ioctl_mutex);
9201da177e4SLinus Torvalds 	br_ioctl_hook = hook;
9214a3e2f71SArjan van de Ven 	mutex_unlock(&br_ioctl_mutex);
9221da177e4SLinus Torvalds }
9231da177e4SLinus Torvalds EXPORT_SYMBOL(brioctl_set);
9241da177e4SLinus Torvalds 
9254a3e2f71SArjan van de Ven static DEFINE_MUTEX(vlan_ioctl_mutex);
926881d966bSEric W. Biederman static int (*vlan_ioctl_hook) (struct net *, void __user *arg);
9271da177e4SLinus Torvalds 
928881d966bSEric W. Biederman void vlan_ioctl_set(int (*hook) (struct net *, void __user *))
9291da177e4SLinus Torvalds {
9304a3e2f71SArjan van de Ven 	mutex_lock(&vlan_ioctl_mutex);
9311da177e4SLinus Torvalds 	vlan_ioctl_hook = hook;
9324a3e2f71SArjan van de Ven 	mutex_unlock(&vlan_ioctl_mutex);
9331da177e4SLinus Torvalds }
9341da177e4SLinus Torvalds EXPORT_SYMBOL(vlan_ioctl_set);
9351da177e4SLinus Torvalds 
9364a3e2f71SArjan van de Ven static DEFINE_MUTEX(dlci_ioctl_mutex);
9371da177e4SLinus Torvalds static int (*dlci_ioctl_hook) (unsigned int, void __user *);
9381da177e4SLinus Torvalds 
9391da177e4SLinus Torvalds void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
9401da177e4SLinus Torvalds {
9414a3e2f71SArjan van de Ven 	mutex_lock(&dlci_ioctl_mutex);
9421da177e4SLinus Torvalds 	dlci_ioctl_hook = hook;
9434a3e2f71SArjan van de Ven 	mutex_unlock(&dlci_ioctl_mutex);
9441da177e4SLinus Torvalds }
9451da177e4SLinus Torvalds EXPORT_SYMBOL(dlci_ioctl_set);
9461da177e4SLinus Torvalds 
9476b96018bSArnd Bergmann static long sock_do_ioctl(struct net *net, struct socket *sock,
9486b96018bSArnd Bergmann 				 unsigned int cmd, unsigned long arg)
9496b96018bSArnd Bergmann {
9506b96018bSArnd Bergmann 	int err;
9516b96018bSArnd Bergmann 	void __user *argp = (void __user *)arg;
9526b96018bSArnd Bergmann 
9536b96018bSArnd Bergmann 	err = sock->ops->ioctl(sock, cmd, arg);
9546b96018bSArnd Bergmann 
9556b96018bSArnd Bergmann 	/*
9566b96018bSArnd Bergmann 	 * If this ioctl is unknown try to hand it down
9576b96018bSArnd Bergmann 	 * to the NIC driver.
9586b96018bSArnd Bergmann 	 */
9596b96018bSArnd Bergmann 	if (err == -ENOIOCTLCMD)
9606b96018bSArnd Bergmann 		err = dev_ioctl(net, cmd, argp);
9616b96018bSArnd Bergmann 
9626b96018bSArnd Bergmann 	return err;
9636b96018bSArnd Bergmann }
9646b96018bSArnd Bergmann 
9651da177e4SLinus Torvalds /*
9661da177e4SLinus Torvalds  *	With an ioctl, arg may well be a user mode pointer, but we don't know
9671da177e4SLinus Torvalds  *	what to do with it - that's up to the protocol still.
9681da177e4SLinus Torvalds  */
9691da177e4SLinus Torvalds 
9701da177e4SLinus Torvalds static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
9711da177e4SLinus Torvalds {
9721da177e4SLinus Torvalds 	struct socket *sock;
973881d966bSEric W. Biederman 	struct sock *sk;
9741da177e4SLinus Torvalds 	void __user *argp = (void __user *)arg;
9751da177e4SLinus Torvalds 	int pid, err;
976881d966bSEric W. Biederman 	struct net *net;
9771da177e4SLinus Torvalds 
978b69aee04SEric Dumazet 	sock = file->private_data;
979881d966bSEric W. Biederman 	sk = sock->sk;
9803b1e0a65SYOSHIFUJI Hideaki 	net = sock_net(sk);
9811da177e4SLinus Torvalds 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
982881d966bSEric W. Biederman 		err = dev_ioctl(net, cmd, argp);
9831da177e4SLinus Torvalds 	} else
9843d23e349SJohannes Berg #ifdef CONFIG_WEXT_CORE
9851da177e4SLinus Torvalds 	if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
986881d966bSEric W. Biederman 		err = dev_ioctl(net, cmd, argp);
9871da177e4SLinus Torvalds 	} else
9883d23e349SJohannes Berg #endif
9891da177e4SLinus Torvalds 		switch (cmd) {
9901da177e4SLinus Torvalds 		case FIOSETOWN:
9911da177e4SLinus Torvalds 		case SIOCSPGRP:
9921da177e4SLinus Torvalds 			err = -EFAULT;
9931da177e4SLinus Torvalds 			if (get_user(pid, (int __user *)argp))
9941da177e4SLinus Torvalds 				break;
9951da177e4SLinus Torvalds 			err = f_setown(sock->file, pid, 1);
9961da177e4SLinus Torvalds 			break;
9971da177e4SLinus Torvalds 		case FIOGETOWN:
9981da177e4SLinus Torvalds 		case SIOCGPGRP:
999609d7fa9SEric W. Biederman 			err = put_user(f_getown(sock->file),
100089bddce5SStephen Hemminger 				       (int __user *)argp);
10011da177e4SLinus Torvalds 			break;
10021da177e4SLinus Torvalds 		case SIOCGIFBR:
10031da177e4SLinus Torvalds 		case SIOCSIFBR:
10041da177e4SLinus Torvalds 		case SIOCBRADDBR:
10051da177e4SLinus Torvalds 		case SIOCBRDELBR:
10061da177e4SLinus Torvalds 			err = -ENOPKG;
10071da177e4SLinus Torvalds 			if (!br_ioctl_hook)
10081da177e4SLinus Torvalds 				request_module("bridge");
10091da177e4SLinus Torvalds 
10104a3e2f71SArjan van de Ven 			mutex_lock(&br_ioctl_mutex);
10111da177e4SLinus Torvalds 			if (br_ioctl_hook)
1012881d966bSEric W. Biederman 				err = br_ioctl_hook(net, cmd, argp);
10134a3e2f71SArjan van de Ven 			mutex_unlock(&br_ioctl_mutex);
10141da177e4SLinus Torvalds 			break;
10151da177e4SLinus Torvalds 		case SIOCGIFVLAN:
10161da177e4SLinus Torvalds 		case SIOCSIFVLAN:
10171da177e4SLinus Torvalds 			err = -ENOPKG;
10181da177e4SLinus Torvalds 			if (!vlan_ioctl_hook)
10191da177e4SLinus Torvalds 				request_module("8021q");
10201da177e4SLinus Torvalds 
10214a3e2f71SArjan van de Ven 			mutex_lock(&vlan_ioctl_mutex);
10221da177e4SLinus Torvalds 			if (vlan_ioctl_hook)
1023881d966bSEric W. Biederman 				err = vlan_ioctl_hook(net, argp);
10244a3e2f71SArjan van de Ven 			mutex_unlock(&vlan_ioctl_mutex);
10251da177e4SLinus Torvalds 			break;
10261da177e4SLinus Torvalds 		case SIOCADDDLCI:
10271da177e4SLinus Torvalds 		case SIOCDELDLCI:
10281da177e4SLinus Torvalds 			err = -ENOPKG;
10291da177e4SLinus Torvalds 			if (!dlci_ioctl_hook)
10301da177e4SLinus Torvalds 				request_module("dlci");
10311da177e4SLinus Torvalds 
10324a3e2f71SArjan van de Ven 			mutex_lock(&dlci_ioctl_mutex);
10337512cbf6SPavel Emelyanov 			if (dlci_ioctl_hook)
10341da177e4SLinus Torvalds 				err = dlci_ioctl_hook(cmd, argp);
10354a3e2f71SArjan van de Ven 			mutex_unlock(&dlci_ioctl_mutex);
10361da177e4SLinus Torvalds 			break;
10371da177e4SLinus Torvalds 		default:
10386b96018bSArnd Bergmann 			err = sock_do_ioctl(net, sock, cmd, arg);
10391da177e4SLinus Torvalds 			break;
10401da177e4SLinus Torvalds 		}
10411da177e4SLinus Torvalds 	return err;
10421da177e4SLinus Torvalds }
10431da177e4SLinus Torvalds 
10441da177e4SLinus Torvalds int sock_create_lite(int family, int type, int protocol, struct socket **res)
10451da177e4SLinus Torvalds {
10461da177e4SLinus Torvalds 	int err;
10471da177e4SLinus Torvalds 	struct socket *sock = NULL;
10481da177e4SLinus Torvalds 
10491da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, 1);
10501da177e4SLinus Torvalds 	if (err)
10511da177e4SLinus Torvalds 		goto out;
10521da177e4SLinus Torvalds 
10531da177e4SLinus Torvalds 	sock = sock_alloc();
10541da177e4SLinus Torvalds 	if (!sock) {
10551da177e4SLinus Torvalds 		err = -ENOMEM;
10561da177e4SLinus Torvalds 		goto out;
10571da177e4SLinus Torvalds 	}
10581da177e4SLinus Torvalds 
10591da177e4SLinus Torvalds 	sock->type = type;
10607420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, 1);
10617420ed23SVenkat Yekkirala 	if (err)
10627420ed23SVenkat Yekkirala 		goto out_release;
10637420ed23SVenkat Yekkirala 
10641da177e4SLinus Torvalds out:
10651da177e4SLinus Torvalds 	*res = sock;
10661da177e4SLinus Torvalds 	return err;
10677420ed23SVenkat Yekkirala out_release:
10687420ed23SVenkat Yekkirala 	sock_release(sock);
10697420ed23SVenkat Yekkirala 	sock = NULL;
10707420ed23SVenkat Yekkirala 	goto out;
10711da177e4SLinus Torvalds }
1072c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_lite);
10731da177e4SLinus Torvalds 
10741da177e4SLinus Torvalds /* No kernel lock held - perfect */
10751da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file, poll_table *wait)
10761da177e4SLinus Torvalds {
10771da177e4SLinus Torvalds 	struct socket *sock;
10781da177e4SLinus Torvalds 
10791da177e4SLinus Torvalds 	/*
10801da177e4SLinus Torvalds 	 *      We can't return errors to poll, so it's either yes or no.
10811da177e4SLinus Torvalds 	 */
1082b69aee04SEric Dumazet 	sock = file->private_data;
10831da177e4SLinus Torvalds 	return sock->ops->poll(file, sock, wait);
10841da177e4SLinus Torvalds }
10851da177e4SLinus Torvalds 
10861da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma)
10871da177e4SLinus Torvalds {
1088b69aee04SEric Dumazet 	struct socket *sock = file->private_data;
10891da177e4SLinus Torvalds 
10901da177e4SLinus Torvalds 	return sock->ops->mmap(file, sock, vma);
10911da177e4SLinus Torvalds }
10921da177e4SLinus Torvalds 
109320380731SArnaldo Carvalho de Melo static int sock_close(struct inode *inode, struct file *filp)
10941da177e4SLinus Torvalds {
10951da177e4SLinus Torvalds 	/*
10961da177e4SLinus Torvalds 	 *      It was possible the inode is NULL we were
10971da177e4SLinus Torvalds 	 *      closing an unfinished socket.
10981da177e4SLinus Torvalds 	 */
10991da177e4SLinus Torvalds 
110089bddce5SStephen Hemminger 	if (!inode) {
11011da177e4SLinus Torvalds 		printk(KERN_DEBUG "sock_close: NULL inode\n");
11021da177e4SLinus Torvalds 		return 0;
11031da177e4SLinus Torvalds 	}
11041da177e4SLinus Torvalds 	sock_release(SOCKET_I(inode));
11051da177e4SLinus Torvalds 	return 0;
11061da177e4SLinus Torvalds }
11071da177e4SLinus Torvalds 
11081da177e4SLinus Torvalds /*
11091da177e4SLinus Torvalds  *	Update the socket async list
11101da177e4SLinus Torvalds  *
11111da177e4SLinus Torvalds  *	Fasync_list locking strategy.
11121da177e4SLinus Torvalds  *
11131da177e4SLinus Torvalds  *	1. fasync_list is modified only under process context socket lock
11141da177e4SLinus Torvalds  *	   i.e. under semaphore.
11151da177e4SLinus Torvalds  *	2. fasync_list is used under read_lock(&sk->sk_callback_lock)
1116989a2979SEric Dumazet  *	   or under socket lock
11171da177e4SLinus Torvalds  */
11181da177e4SLinus Torvalds 
11191da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on)
11201da177e4SLinus Torvalds {
1121989a2979SEric Dumazet 	struct socket *sock = filp->private_data;
1122989a2979SEric Dumazet 	struct sock *sk = sock->sk;
1123eaefd110SEric Dumazet 	struct socket_wq *wq;
11241da177e4SLinus Torvalds 
1125989a2979SEric Dumazet 	if (sk == NULL)
11261da177e4SLinus Torvalds 		return -EINVAL;
11271da177e4SLinus Torvalds 
11281da177e4SLinus Torvalds 	lock_sock(sk);
1129eaefd110SEric Dumazet 	wq = rcu_dereference_protected(sock->wq, sock_owned_by_user(sk));
1130eaefd110SEric Dumazet 	fasync_helper(fd, filp, on, &wq->fasync_list);
11311da177e4SLinus Torvalds 
1132eaefd110SEric Dumazet 	if (!wq->fasync_list)
1133bcdce719SEric Dumazet 		sock_reset_flag(sk, SOCK_FASYNC);
1134989a2979SEric Dumazet 	else
1135989a2979SEric Dumazet 		sock_set_flag(sk, SOCK_FASYNC);
11361da177e4SLinus Torvalds 
1137989a2979SEric Dumazet 	release_sock(sk);
11381da177e4SLinus Torvalds 	return 0;
11391da177e4SLinus Torvalds }
11401da177e4SLinus Torvalds 
114143815482SEric Dumazet /* This function may be called only under socket lock or callback_lock or rcu_lock */
11421da177e4SLinus Torvalds 
11431da177e4SLinus Torvalds int sock_wake_async(struct socket *sock, int how, int band)
11441da177e4SLinus Torvalds {
114543815482SEric Dumazet 	struct socket_wq *wq;
114643815482SEric Dumazet 
114743815482SEric Dumazet 	if (!sock)
11481da177e4SLinus Torvalds 		return -1;
114943815482SEric Dumazet 	rcu_read_lock();
115043815482SEric Dumazet 	wq = rcu_dereference(sock->wq);
115143815482SEric Dumazet 	if (!wq || !wq->fasync_list) {
115243815482SEric Dumazet 		rcu_read_unlock();
115343815482SEric Dumazet 		return -1;
115443815482SEric Dumazet 	}
115589bddce5SStephen Hemminger 	switch (how) {
11568d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_WAITD:
11571da177e4SLinus Torvalds 		if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
11581da177e4SLinus Torvalds 			break;
11591da177e4SLinus Torvalds 		goto call_kill;
11608d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_SPACE:
11611da177e4SLinus Torvalds 		if (!test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags))
11621da177e4SLinus Torvalds 			break;
11631da177e4SLinus Torvalds 		/* fall through */
11648d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_IO:
11651da177e4SLinus Torvalds call_kill:
116643815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGIO, band);
11671da177e4SLinus Torvalds 		break;
11688d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_URG:
116943815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGURG, band);
11701da177e4SLinus Torvalds 	}
117143815482SEric Dumazet 	rcu_read_unlock();
11721da177e4SLinus Torvalds 	return 0;
11731da177e4SLinus Torvalds }
1174c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_wake_async);
11751da177e4SLinus Torvalds 
1176721db93aSPavel Emelyanov int __sock_create(struct net *net, int family, int type, int protocol,
117789bddce5SStephen Hemminger 			 struct socket **res, int kern)
11781da177e4SLinus Torvalds {
11791da177e4SLinus Torvalds 	int err;
11801da177e4SLinus Torvalds 	struct socket *sock;
118155737fdaSStephen Hemminger 	const struct net_proto_family *pf;
11821da177e4SLinus Torvalds 
11831da177e4SLinus Torvalds 	/*
11841da177e4SLinus Torvalds 	 *      Check protocol is in range
11851da177e4SLinus Torvalds 	 */
11861da177e4SLinus Torvalds 	if (family < 0 || family >= NPROTO)
11871da177e4SLinus Torvalds 		return -EAFNOSUPPORT;
11881da177e4SLinus Torvalds 	if (type < 0 || type >= SOCK_MAX)
11891da177e4SLinus Torvalds 		return -EINVAL;
11901da177e4SLinus Torvalds 
11911da177e4SLinus Torvalds 	/* Compatibility.
11921da177e4SLinus Torvalds 
11931da177e4SLinus Torvalds 	   This uglymoron is moved from INET layer to here to avoid
11941da177e4SLinus Torvalds 	   deadlock in module load.
11951da177e4SLinus Torvalds 	 */
11961da177e4SLinus Torvalds 	if (family == PF_INET && type == SOCK_PACKET) {
11971da177e4SLinus Torvalds 		static int warned;
11981da177e4SLinus Torvalds 		if (!warned) {
11991da177e4SLinus Torvalds 			warned = 1;
120089bddce5SStephen Hemminger 			printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)\n",
120189bddce5SStephen Hemminger 			       current->comm);
12021da177e4SLinus Torvalds 		}
12031da177e4SLinus Torvalds 		family = PF_PACKET;
12041da177e4SLinus Torvalds 	}
12051da177e4SLinus Torvalds 
12061da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, kern);
12071da177e4SLinus Torvalds 	if (err)
12081da177e4SLinus Torvalds 		return err;
12091da177e4SLinus Torvalds 
121055737fdaSStephen Hemminger 	/*
121155737fdaSStephen Hemminger 	 *	Allocate the socket and allow the family to set things up. if
121255737fdaSStephen Hemminger 	 *	the protocol is 0, the family is instructed to select an appropriate
121355737fdaSStephen Hemminger 	 *	default.
121455737fdaSStephen Hemminger 	 */
121555737fdaSStephen Hemminger 	sock = sock_alloc();
121655737fdaSStephen Hemminger 	if (!sock) {
121755737fdaSStephen Hemminger 		if (net_ratelimit())
121855737fdaSStephen Hemminger 			printk(KERN_WARNING "socket: no more sockets\n");
121955737fdaSStephen Hemminger 		return -ENFILE;	/* Not exactly a match, but its the
122055737fdaSStephen Hemminger 				   closest posix thing */
122155737fdaSStephen Hemminger 	}
122255737fdaSStephen Hemminger 
122355737fdaSStephen Hemminger 	sock->type = type;
122455737fdaSStephen Hemminger 
122595a5afcaSJohannes Berg #ifdef CONFIG_MODULES
12261da177e4SLinus Torvalds 	/* Attempt to load a protocol module if the find failed.
12271da177e4SLinus Torvalds 	 *
12281da177e4SLinus Torvalds 	 * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
12291da177e4SLinus Torvalds 	 * requested real, full-featured networking support upon configuration.
12301da177e4SLinus Torvalds 	 * Otherwise module support will break!
12311da177e4SLinus Torvalds 	 */
1232190683a9SEric Dumazet 	if (rcu_access_pointer(net_families[family]) == NULL)
12331da177e4SLinus Torvalds 		request_module("net-pf-%d", family);
12341da177e4SLinus Torvalds #endif
12351da177e4SLinus Torvalds 
123655737fdaSStephen Hemminger 	rcu_read_lock();
123755737fdaSStephen Hemminger 	pf = rcu_dereference(net_families[family]);
12381da177e4SLinus Torvalds 	err = -EAFNOSUPPORT;
123955737fdaSStephen Hemminger 	if (!pf)
124055737fdaSStephen Hemminger 		goto out_release;
12411da177e4SLinus Torvalds 
12421da177e4SLinus Torvalds 	/*
12431da177e4SLinus Torvalds 	 * We will call the ->create function, that possibly is in a loadable
12441da177e4SLinus Torvalds 	 * module, so we have to bump that loadable module refcnt first.
12451da177e4SLinus Torvalds 	 */
124655737fdaSStephen Hemminger 	if (!try_module_get(pf->owner))
12471da177e4SLinus Torvalds 		goto out_release;
12481da177e4SLinus Torvalds 
124955737fdaSStephen Hemminger 	/* Now protected by module ref count */
125055737fdaSStephen Hemminger 	rcu_read_unlock();
125155737fdaSStephen Hemminger 
12523f378b68SEric Paris 	err = pf->create(net, sock, protocol, kern);
125355737fdaSStephen Hemminger 	if (err < 0)
12541da177e4SLinus Torvalds 		goto out_module_put;
1255a79af59eSFrank Filz 
12561da177e4SLinus Torvalds 	/*
12571da177e4SLinus Torvalds 	 * Now to bump the refcnt of the [loadable] module that owns this
12581da177e4SLinus Torvalds 	 * socket at sock_release time we decrement its refcnt.
12591da177e4SLinus Torvalds 	 */
126055737fdaSStephen Hemminger 	if (!try_module_get(sock->ops->owner))
126155737fdaSStephen Hemminger 		goto out_module_busy;
126255737fdaSStephen Hemminger 
12631da177e4SLinus Torvalds 	/*
12641da177e4SLinus Torvalds 	 * Now that we're done with the ->create function, the [loadable]
12651da177e4SLinus Torvalds 	 * module can have its refcnt decremented
12661da177e4SLinus Torvalds 	 */
126755737fdaSStephen Hemminger 	module_put(pf->owner);
12687420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, kern);
12697420ed23SVenkat Yekkirala 	if (err)
12703b185525SHerbert Xu 		goto out_sock_release;
127155737fdaSStephen Hemminger 	*res = sock;
12721da177e4SLinus Torvalds 
127355737fdaSStephen Hemminger 	return 0;
127455737fdaSStephen Hemminger 
127555737fdaSStephen Hemminger out_module_busy:
127655737fdaSStephen Hemminger 	err = -EAFNOSUPPORT;
12771da177e4SLinus Torvalds out_module_put:
127855737fdaSStephen Hemminger 	sock->ops = NULL;
127955737fdaSStephen Hemminger 	module_put(pf->owner);
128055737fdaSStephen Hemminger out_sock_release:
12811da177e4SLinus Torvalds 	sock_release(sock);
128255737fdaSStephen Hemminger 	return err;
128355737fdaSStephen Hemminger 
128455737fdaSStephen Hemminger out_release:
128555737fdaSStephen Hemminger 	rcu_read_unlock();
128655737fdaSStephen Hemminger 	goto out_sock_release;
12871da177e4SLinus Torvalds }
1288721db93aSPavel Emelyanov EXPORT_SYMBOL(__sock_create);
12891da177e4SLinus Torvalds 
12901da177e4SLinus Torvalds int sock_create(int family, int type, int protocol, struct socket **res)
12911da177e4SLinus Torvalds {
12921b8d7ae4SEric W. Biederman 	return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
12931da177e4SLinus Torvalds }
1294c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create);
12951da177e4SLinus Torvalds 
12961da177e4SLinus Torvalds int sock_create_kern(int family, int type, int protocol, struct socket **res)
12971da177e4SLinus Torvalds {
12981b8d7ae4SEric W. Biederman 	return __sock_create(&init_net, family, type, protocol, res, 1);
12991da177e4SLinus Torvalds }
1300c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_kern);
13011da177e4SLinus Torvalds 
13023e0fa65fSHeiko Carstens SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
13031da177e4SLinus Torvalds {
13041da177e4SLinus Torvalds 	int retval;
13051da177e4SLinus Torvalds 	struct socket *sock;
1306a677a039SUlrich Drepper 	int flags;
1307a677a039SUlrich Drepper 
1308e38b36f3SUlrich Drepper 	/* Check the SOCK_* constants for consistency.  */
1309e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
1310e38b36f3SUlrich Drepper 	BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
1311e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);
1312e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);
1313e38b36f3SUlrich Drepper 
1314a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
131577d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1316a677a039SUlrich Drepper 		return -EINVAL;
1317a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
13181da177e4SLinus Torvalds 
1319aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1320aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1321aaca0bdcSUlrich Drepper 
13221da177e4SLinus Torvalds 	retval = sock_create(family, type, protocol, &sock);
13231da177e4SLinus Torvalds 	if (retval < 0)
13241da177e4SLinus Torvalds 		goto out;
13251da177e4SLinus Torvalds 
132677d27200SUlrich Drepper 	retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
13271da177e4SLinus Torvalds 	if (retval < 0)
13281da177e4SLinus Torvalds 		goto out_release;
13291da177e4SLinus Torvalds 
13301da177e4SLinus Torvalds out:
13311da177e4SLinus Torvalds 	/* It may be already another descriptor 8) Not kernel problem. */
13321da177e4SLinus Torvalds 	return retval;
13331da177e4SLinus Torvalds 
13341da177e4SLinus Torvalds out_release:
13351da177e4SLinus Torvalds 	sock_release(sock);
13361da177e4SLinus Torvalds 	return retval;
13371da177e4SLinus Torvalds }
13381da177e4SLinus Torvalds 
13391da177e4SLinus Torvalds /*
13401da177e4SLinus Torvalds  *	Create a pair of connected sockets.
13411da177e4SLinus Torvalds  */
13421da177e4SLinus Torvalds 
13433e0fa65fSHeiko Carstens SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
13443e0fa65fSHeiko Carstens 		int __user *, usockvec)
13451da177e4SLinus Torvalds {
13461da177e4SLinus Torvalds 	struct socket *sock1, *sock2;
13471da177e4SLinus Torvalds 	int fd1, fd2, err;
1348db349509SAl Viro 	struct file *newfile1, *newfile2;
1349a677a039SUlrich Drepper 	int flags;
1350a677a039SUlrich Drepper 
1351a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
135277d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1353a677a039SUlrich Drepper 		return -EINVAL;
1354a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
13551da177e4SLinus Torvalds 
1356aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1357aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1358aaca0bdcSUlrich Drepper 
13591da177e4SLinus Torvalds 	/*
13601da177e4SLinus Torvalds 	 * Obtain the first socket and check if the underlying protocol
13611da177e4SLinus Torvalds 	 * supports the socketpair call.
13621da177e4SLinus Torvalds 	 */
13631da177e4SLinus Torvalds 
13641da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock1);
13651da177e4SLinus Torvalds 	if (err < 0)
13661da177e4SLinus Torvalds 		goto out;
13671da177e4SLinus Torvalds 
13681da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock2);
13691da177e4SLinus Torvalds 	if (err < 0)
13701da177e4SLinus Torvalds 		goto out_release_1;
13711da177e4SLinus Torvalds 
13721da177e4SLinus Torvalds 	err = sock1->ops->socketpair(sock1, sock2);
13731da177e4SLinus Torvalds 	if (err < 0)
13741da177e4SLinus Torvalds 		goto out_release_both;
13751da177e4SLinus Torvalds 
13767cbe66b6SAl Viro 	fd1 = sock_alloc_file(sock1, &newfile1, flags);
1377bf3c23d1SDavid S. Miller 	if (unlikely(fd1 < 0)) {
1378bf3c23d1SDavid S. Miller 		err = fd1;
13791da177e4SLinus Torvalds 		goto out_release_both;
1380bf3c23d1SDavid S. Miller 	}
13811da177e4SLinus Torvalds 
13827cbe66b6SAl Viro 	fd2 = sock_alloc_file(sock2, &newfile2, flags);
1383198de4d7SAl Viro 	if (unlikely(fd2 < 0)) {
1384198de4d7SAl Viro 		err = fd2;
1385198de4d7SAl Viro 		fput(newfile1);
1386198de4d7SAl Viro 		put_unused_fd(fd1);
1387198de4d7SAl Viro 		sock_release(sock2);
1388198de4d7SAl Viro 		goto out;
1389db349509SAl Viro 	}
1390db349509SAl Viro 
1391157cf649SAl Viro 	audit_fd_pair(fd1, fd2);
1392db349509SAl Viro 	fd_install(fd1, newfile1);
1393db349509SAl Viro 	fd_install(fd2, newfile2);
13941da177e4SLinus Torvalds 	/* fd1 and fd2 may be already another descriptors.
13951da177e4SLinus Torvalds 	 * Not kernel problem.
13961da177e4SLinus Torvalds 	 */
13971da177e4SLinus Torvalds 
13981da177e4SLinus Torvalds 	err = put_user(fd1, &usockvec[0]);
13991da177e4SLinus Torvalds 	if (!err)
14001da177e4SLinus Torvalds 		err = put_user(fd2, &usockvec[1]);
14011da177e4SLinus Torvalds 	if (!err)
14021da177e4SLinus Torvalds 		return 0;
14031da177e4SLinus Torvalds 
14041da177e4SLinus Torvalds 	sys_close(fd2);
14051da177e4SLinus Torvalds 	sys_close(fd1);
14061da177e4SLinus Torvalds 	return err;
14071da177e4SLinus Torvalds 
14081da177e4SLinus Torvalds out_release_both:
14091da177e4SLinus Torvalds 	sock_release(sock2);
14101da177e4SLinus Torvalds out_release_1:
14111da177e4SLinus Torvalds 	sock_release(sock1);
14121da177e4SLinus Torvalds out:
14131da177e4SLinus Torvalds 	return err;
14141da177e4SLinus Torvalds }
14151da177e4SLinus Torvalds 
14161da177e4SLinus Torvalds /*
14171da177e4SLinus Torvalds  *	Bind a name to a socket. Nothing much to do here since it's
14181da177e4SLinus Torvalds  *	the protocol's responsibility to handle the local address.
14191da177e4SLinus Torvalds  *
14201da177e4SLinus Torvalds  *	We move the socket address to kernel space before we call
14211da177e4SLinus Torvalds  *	the protocol layer (having also checked the address is ok).
14221da177e4SLinus Torvalds  */
14231da177e4SLinus Torvalds 
142420f37034SHeiko Carstens SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
14251da177e4SLinus Torvalds {
14261da177e4SLinus Torvalds 	struct socket *sock;
1427230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
14286cb153caSBenjamin LaHaise 	int err, fput_needed;
14291da177e4SLinus Torvalds 
143089bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
143189bddce5SStephen Hemminger 	if (sock) {
1432230b1839SYOSHIFUJI Hideaki 		err = move_addr_to_kernel(umyaddr, addrlen, (struct sockaddr *)&address);
143389bddce5SStephen Hemminger 		if (err >= 0) {
143489bddce5SStephen Hemminger 			err = security_socket_bind(sock,
1435230b1839SYOSHIFUJI Hideaki 						   (struct sockaddr *)&address,
143689bddce5SStephen Hemminger 						   addrlen);
14376cb153caSBenjamin LaHaise 			if (!err)
14386cb153caSBenjamin LaHaise 				err = sock->ops->bind(sock,
143989bddce5SStephen Hemminger 						      (struct sockaddr *)
1440230b1839SYOSHIFUJI Hideaki 						      &address, addrlen);
14411da177e4SLinus Torvalds 		}
14426cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
14431da177e4SLinus Torvalds 	}
14441da177e4SLinus Torvalds 	return err;
14451da177e4SLinus Torvalds }
14461da177e4SLinus Torvalds 
14471da177e4SLinus Torvalds /*
14481da177e4SLinus Torvalds  *	Perform a listen. Basically, we allow the protocol to do anything
14491da177e4SLinus Torvalds  *	necessary for a listen, and if that works, we mark the socket as
14501da177e4SLinus Torvalds  *	ready for listening.
14511da177e4SLinus Torvalds  */
14521da177e4SLinus Torvalds 
14533e0fa65fSHeiko Carstens SYSCALL_DEFINE2(listen, int, fd, int, backlog)
14541da177e4SLinus Torvalds {
14551da177e4SLinus Torvalds 	struct socket *sock;
14566cb153caSBenjamin LaHaise 	int err, fput_needed;
1457b8e1f9b5SPavel Emelyanov 	int somaxconn;
14581da177e4SLinus Torvalds 
145989bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
146089bddce5SStephen Hemminger 	if (sock) {
14618efa6e93SPavel Emelyanov 		somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
1462b8e1f9b5SPavel Emelyanov 		if ((unsigned)backlog > somaxconn)
1463b8e1f9b5SPavel Emelyanov 			backlog = somaxconn;
14641da177e4SLinus Torvalds 
14651da177e4SLinus Torvalds 		err = security_socket_listen(sock, backlog);
14666cb153caSBenjamin LaHaise 		if (!err)
14671da177e4SLinus Torvalds 			err = sock->ops->listen(sock, backlog);
14686cb153caSBenjamin LaHaise 
14696cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
14701da177e4SLinus Torvalds 	}
14711da177e4SLinus Torvalds 	return err;
14721da177e4SLinus Torvalds }
14731da177e4SLinus Torvalds 
14741da177e4SLinus Torvalds /*
14751da177e4SLinus Torvalds  *	For accept, we attempt to create a new socket, set up the link
14761da177e4SLinus Torvalds  *	with the client, wake up the client, then return the new
14771da177e4SLinus Torvalds  *	connected fd. We collect the address of the connector in kernel
14781da177e4SLinus Torvalds  *	space and move it to user at the very end. This is unclean because
14791da177e4SLinus Torvalds  *	we open the socket then return an error.
14801da177e4SLinus Torvalds  *
14811da177e4SLinus Torvalds  *	1003.1g adds the ability to recvmsg() to query connection pending
14821da177e4SLinus Torvalds  *	status to recvmsg. We need to add that support in a way thats
14831da177e4SLinus Torvalds  *	clean when we restucture accept also.
14841da177e4SLinus Torvalds  */
14851da177e4SLinus Torvalds 
148620f37034SHeiko Carstens SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
148720f37034SHeiko Carstens 		int __user *, upeer_addrlen, int, flags)
14881da177e4SLinus Torvalds {
14891da177e4SLinus Torvalds 	struct socket *sock, *newsock;
149039d8c1b6SDavid S. Miller 	struct file *newfile;
14916cb153caSBenjamin LaHaise 	int err, len, newfd, fput_needed;
1492230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
14931da177e4SLinus Torvalds 
149477d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1495aaca0bdcSUlrich Drepper 		return -EINVAL;
1496aaca0bdcSUlrich Drepper 
1497aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1498aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1499aaca0bdcSUlrich Drepper 
15006cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
15011da177e4SLinus Torvalds 	if (!sock)
15021da177e4SLinus Torvalds 		goto out;
15031da177e4SLinus Torvalds 
15041da177e4SLinus Torvalds 	err = -ENFILE;
1505c6d409cfSEric Dumazet 	newsock = sock_alloc();
1506c6d409cfSEric Dumazet 	if (!newsock)
15071da177e4SLinus Torvalds 		goto out_put;
15081da177e4SLinus Torvalds 
15091da177e4SLinus Torvalds 	newsock->type = sock->type;
15101da177e4SLinus Torvalds 	newsock->ops = sock->ops;
15111da177e4SLinus Torvalds 
15121da177e4SLinus Torvalds 	/*
15131da177e4SLinus Torvalds 	 * We don't need try_module_get here, as the listening socket (sock)
15141da177e4SLinus Torvalds 	 * has the protocol module (sock->ops->owner) held.
15151da177e4SLinus Torvalds 	 */
15161da177e4SLinus Torvalds 	__module_get(newsock->ops->owner);
15171da177e4SLinus Torvalds 
15187cbe66b6SAl Viro 	newfd = sock_alloc_file(newsock, &newfile, flags);
151939d8c1b6SDavid S. Miller 	if (unlikely(newfd < 0)) {
152039d8c1b6SDavid S. Miller 		err = newfd;
15219a1875e6SDavid S. Miller 		sock_release(newsock);
15229a1875e6SDavid S. Miller 		goto out_put;
152339d8c1b6SDavid S. Miller 	}
152439d8c1b6SDavid S. Miller 
1525a79af59eSFrank Filz 	err = security_socket_accept(sock, newsock);
1526a79af59eSFrank Filz 	if (err)
152739d8c1b6SDavid S. Miller 		goto out_fd;
1528a79af59eSFrank Filz 
15291da177e4SLinus Torvalds 	err = sock->ops->accept(sock, newsock, sock->file->f_flags);
15301da177e4SLinus Torvalds 	if (err < 0)
153139d8c1b6SDavid S. Miller 		goto out_fd;
15321da177e4SLinus Torvalds 
15331da177e4SLinus Torvalds 	if (upeer_sockaddr) {
1534230b1839SYOSHIFUJI Hideaki 		if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
153589bddce5SStephen Hemminger 					  &len, 2) < 0) {
15361da177e4SLinus Torvalds 			err = -ECONNABORTED;
153739d8c1b6SDavid S. Miller 			goto out_fd;
15381da177e4SLinus Torvalds 		}
1539230b1839SYOSHIFUJI Hideaki 		err = move_addr_to_user((struct sockaddr *)&address,
1540230b1839SYOSHIFUJI Hideaki 					len, upeer_sockaddr, upeer_addrlen);
15411da177e4SLinus Torvalds 		if (err < 0)
154239d8c1b6SDavid S. Miller 			goto out_fd;
15431da177e4SLinus Torvalds 	}
15441da177e4SLinus Torvalds 
15451da177e4SLinus Torvalds 	/* File flags are not inherited via accept() unlike another OSes. */
15461da177e4SLinus Torvalds 
154739d8c1b6SDavid S. Miller 	fd_install(newfd, newfile);
154839d8c1b6SDavid S. Miller 	err = newfd;
15491da177e4SLinus Torvalds 
15501da177e4SLinus Torvalds out_put:
15516cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
15521da177e4SLinus Torvalds out:
15531da177e4SLinus Torvalds 	return err;
155439d8c1b6SDavid S. Miller out_fd:
15559606a216SDavid S. Miller 	fput(newfile);
155639d8c1b6SDavid S. Miller 	put_unused_fd(newfd);
15571da177e4SLinus Torvalds 	goto out_put;
15581da177e4SLinus Torvalds }
15591da177e4SLinus Torvalds 
156020f37034SHeiko Carstens SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,
156120f37034SHeiko Carstens 		int __user *, upeer_addrlen)
1562aaca0bdcSUlrich Drepper {
1563de11defeSUlrich Drepper 	return sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0);
1564aaca0bdcSUlrich Drepper }
1565aaca0bdcSUlrich Drepper 
15661da177e4SLinus Torvalds /*
15671da177e4SLinus Torvalds  *	Attempt to connect to a socket with the server address.  The address
15681da177e4SLinus Torvalds  *	is in user space so we verify it is OK and move it to kernel space.
15691da177e4SLinus Torvalds  *
15701da177e4SLinus Torvalds  *	For 1003.1g we need to add clean support for a bind to AF_UNSPEC to
15711da177e4SLinus Torvalds  *	break bindings
15721da177e4SLinus Torvalds  *
15731da177e4SLinus Torvalds  *	NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and
15741da177e4SLinus Torvalds  *	other SEQPACKET protocols that take time to connect() as it doesn't
15751da177e4SLinus Torvalds  *	include the -EINPROGRESS status for such sockets.
15761da177e4SLinus Torvalds  */
15771da177e4SLinus Torvalds 
157820f37034SHeiko Carstens SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
157920f37034SHeiko Carstens 		int, addrlen)
15801da177e4SLinus Torvalds {
15811da177e4SLinus Torvalds 	struct socket *sock;
1582230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
15836cb153caSBenjamin LaHaise 	int err, fput_needed;
15841da177e4SLinus Torvalds 
15856cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
15861da177e4SLinus Torvalds 	if (!sock)
15871da177e4SLinus Torvalds 		goto out;
1588230b1839SYOSHIFUJI Hideaki 	err = move_addr_to_kernel(uservaddr, addrlen, (struct sockaddr *)&address);
15891da177e4SLinus Torvalds 	if (err < 0)
15901da177e4SLinus Torvalds 		goto out_put;
15911da177e4SLinus Torvalds 
159289bddce5SStephen Hemminger 	err =
1593230b1839SYOSHIFUJI Hideaki 	    security_socket_connect(sock, (struct sockaddr *)&address, addrlen);
15941da177e4SLinus Torvalds 	if (err)
15951da177e4SLinus Torvalds 		goto out_put;
15961da177e4SLinus Torvalds 
1597230b1839SYOSHIFUJI Hideaki 	err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,
15981da177e4SLinus Torvalds 				 sock->file->f_flags);
15991da177e4SLinus Torvalds out_put:
16006cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
16011da177e4SLinus Torvalds out:
16021da177e4SLinus Torvalds 	return err;
16031da177e4SLinus Torvalds }
16041da177e4SLinus Torvalds 
16051da177e4SLinus Torvalds /*
16061da177e4SLinus Torvalds  *	Get the local address ('name') of a socket object. Move the obtained
16071da177e4SLinus Torvalds  *	name to user space.
16081da177e4SLinus Torvalds  */
16091da177e4SLinus Torvalds 
161020f37034SHeiko Carstens SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
161120f37034SHeiko Carstens 		int __user *, usockaddr_len)
16121da177e4SLinus Torvalds {
16131da177e4SLinus Torvalds 	struct socket *sock;
1614230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16156cb153caSBenjamin LaHaise 	int len, err, fput_needed;
16161da177e4SLinus Torvalds 
16176cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
16181da177e4SLinus Torvalds 	if (!sock)
16191da177e4SLinus Torvalds 		goto out;
16201da177e4SLinus Torvalds 
16211da177e4SLinus Torvalds 	err = security_socket_getsockname(sock);
16221da177e4SLinus Torvalds 	if (err)
16231da177e4SLinus Torvalds 		goto out_put;
16241da177e4SLinus Torvalds 
1625230b1839SYOSHIFUJI Hideaki 	err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0);
16261da177e4SLinus Torvalds 	if (err)
16271da177e4SLinus Torvalds 		goto out_put;
1628230b1839SYOSHIFUJI Hideaki 	err = move_addr_to_user((struct sockaddr *)&address, len, usockaddr, usockaddr_len);
16291da177e4SLinus Torvalds 
16301da177e4SLinus Torvalds out_put:
16316cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
16321da177e4SLinus Torvalds out:
16331da177e4SLinus Torvalds 	return err;
16341da177e4SLinus Torvalds }
16351da177e4SLinus Torvalds 
16361da177e4SLinus Torvalds /*
16371da177e4SLinus Torvalds  *	Get the remote address ('name') of a socket object. Move the obtained
16381da177e4SLinus Torvalds  *	name to user space.
16391da177e4SLinus Torvalds  */
16401da177e4SLinus Torvalds 
164120f37034SHeiko Carstens SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
164220f37034SHeiko Carstens 		int __user *, usockaddr_len)
16431da177e4SLinus Torvalds {
16441da177e4SLinus Torvalds 	struct socket *sock;
1645230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16466cb153caSBenjamin LaHaise 	int len, err, fput_needed;
16471da177e4SLinus Torvalds 
164889bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
164989bddce5SStephen Hemminger 	if (sock != NULL) {
16501da177e4SLinus Torvalds 		err = security_socket_getpeername(sock);
16511da177e4SLinus Torvalds 		if (err) {
16526cb153caSBenjamin LaHaise 			fput_light(sock->file, fput_needed);
16531da177e4SLinus Torvalds 			return err;
16541da177e4SLinus Torvalds 		}
16551da177e4SLinus Torvalds 
165689bddce5SStephen Hemminger 		err =
1657230b1839SYOSHIFUJI Hideaki 		    sock->ops->getname(sock, (struct sockaddr *)&address, &len,
165889bddce5SStephen Hemminger 				       1);
16591da177e4SLinus Torvalds 		if (!err)
1660230b1839SYOSHIFUJI Hideaki 			err = move_addr_to_user((struct sockaddr *)&address, len, usockaddr,
166189bddce5SStephen Hemminger 						usockaddr_len);
16626cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
16631da177e4SLinus Torvalds 	}
16641da177e4SLinus Torvalds 	return err;
16651da177e4SLinus Torvalds }
16661da177e4SLinus Torvalds 
16671da177e4SLinus Torvalds /*
16681da177e4SLinus Torvalds  *	Send a datagram to a given address. We move the address into kernel
16691da177e4SLinus Torvalds  *	space and check the user space data area is readable before invoking
16701da177e4SLinus Torvalds  *	the protocol.
16711da177e4SLinus Torvalds  */
16721da177e4SLinus Torvalds 
16733e0fa65fSHeiko Carstens SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
16743e0fa65fSHeiko Carstens 		unsigned, flags, struct sockaddr __user *, addr,
16753e0fa65fSHeiko Carstens 		int, addr_len)
16761da177e4SLinus Torvalds {
16771da177e4SLinus Torvalds 	struct socket *sock;
1678230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16791da177e4SLinus Torvalds 	int err;
16801da177e4SLinus Torvalds 	struct msghdr msg;
16811da177e4SLinus Torvalds 	struct iovec iov;
16826cb153caSBenjamin LaHaise 	int fput_needed;
16831da177e4SLinus Torvalds 
1684253eacc0SLinus Torvalds 	if (len > INT_MAX)
1685253eacc0SLinus Torvalds 		len = INT_MAX;
1686de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1687de0fa95cSPavel Emelyanov 	if (!sock)
16884387ff75SDavid S. Miller 		goto out;
16896cb153caSBenjamin LaHaise 
16901da177e4SLinus Torvalds 	iov.iov_base = buff;
16911da177e4SLinus Torvalds 	iov.iov_len = len;
16921da177e4SLinus Torvalds 	msg.msg_name = NULL;
16931da177e4SLinus Torvalds 	msg.msg_iov = &iov;
16941da177e4SLinus Torvalds 	msg.msg_iovlen = 1;
16951da177e4SLinus Torvalds 	msg.msg_control = NULL;
16961da177e4SLinus Torvalds 	msg.msg_controllen = 0;
16971da177e4SLinus Torvalds 	msg.msg_namelen = 0;
16986cb153caSBenjamin LaHaise 	if (addr) {
1699230b1839SYOSHIFUJI Hideaki 		err = move_addr_to_kernel(addr, addr_len, (struct sockaddr *)&address);
17001da177e4SLinus Torvalds 		if (err < 0)
17011da177e4SLinus Torvalds 			goto out_put;
1702230b1839SYOSHIFUJI Hideaki 		msg.msg_name = (struct sockaddr *)&address;
17031da177e4SLinus Torvalds 		msg.msg_namelen = addr_len;
17041da177e4SLinus Torvalds 	}
17051da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
17061da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
17071da177e4SLinus Torvalds 	msg.msg_flags = flags;
17081da177e4SLinus Torvalds 	err = sock_sendmsg(sock, &msg, len);
17091da177e4SLinus Torvalds 
17101da177e4SLinus Torvalds out_put:
1711de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
17124387ff75SDavid S. Miller out:
17131da177e4SLinus Torvalds 	return err;
17141da177e4SLinus Torvalds }
17151da177e4SLinus Torvalds 
17161da177e4SLinus Torvalds /*
17171da177e4SLinus Torvalds  *	Send a datagram down a socket.
17181da177e4SLinus Torvalds  */
17191da177e4SLinus Torvalds 
17203e0fa65fSHeiko Carstens SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len,
17213e0fa65fSHeiko Carstens 		unsigned, flags)
17221da177e4SLinus Torvalds {
17231da177e4SLinus Torvalds 	return sys_sendto(fd, buff, len, flags, NULL, 0);
17241da177e4SLinus Torvalds }
17251da177e4SLinus Torvalds 
17261da177e4SLinus Torvalds /*
17271da177e4SLinus Torvalds  *	Receive a frame from the socket and optionally record the address of the
17281da177e4SLinus Torvalds  *	sender. We verify the buffers are writable and if needed move the
17291da177e4SLinus Torvalds  *	sender address from kernel to user space.
17301da177e4SLinus Torvalds  */
17311da177e4SLinus Torvalds 
17323e0fa65fSHeiko Carstens SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
17333e0fa65fSHeiko Carstens 		unsigned, flags, struct sockaddr __user *, addr,
17343e0fa65fSHeiko Carstens 		int __user *, addr_len)
17351da177e4SLinus Torvalds {
17361da177e4SLinus Torvalds 	struct socket *sock;
17371da177e4SLinus Torvalds 	struct iovec iov;
17381da177e4SLinus Torvalds 	struct msghdr msg;
1739230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
17401da177e4SLinus Torvalds 	int err, err2;
17416cb153caSBenjamin LaHaise 	int fput_needed;
17421da177e4SLinus Torvalds 
1743253eacc0SLinus Torvalds 	if (size > INT_MAX)
1744253eacc0SLinus Torvalds 		size = INT_MAX;
1745de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
17461da177e4SLinus Torvalds 	if (!sock)
1747de0fa95cSPavel Emelyanov 		goto out;
17481da177e4SLinus Torvalds 
17491da177e4SLinus Torvalds 	msg.msg_control = NULL;
17501da177e4SLinus Torvalds 	msg.msg_controllen = 0;
17511da177e4SLinus Torvalds 	msg.msg_iovlen = 1;
17521da177e4SLinus Torvalds 	msg.msg_iov = &iov;
17531da177e4SLinus Torvalds 	iov.iov_len = size;
17541da177e4SLinus Torvalds 	iov.iov_base = ubuf;
1755230b1839SYOSHIFUJI Hideaki 	msg.msg_name = (struct sockaddr *)&address;
1756230b1839SYOSHIFUJI Hideaki 	msg.msg_namelen = sizeof(address);
17571da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
17581da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
17591da177e4SLinus Torvalds 	err = sock_recvmsg(sock, &msg, size, flags);
17601da177e4SLinus Torvalds 
176189bddce5SStephen Hemminger 	if (err >= 0 && addr != NULL) {
1762230b1839SYOSHIFUJI Hideaki 		err2 = move_addr_to_user((struct sockaddr *)&address,
1763230b1839SYOSHIFUJI Hideaki 					 msg.msg_namelen, addr, addr_len);
17641da177e4SLinus Torvalds 		if (err2 < 0)
17651da177e4SLinus Torvalds 			err = err2;
17661da177e4SLinus Torvalds 	}
1767de0fa95cSPavel Emelyanov 
1768de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
17694387ff75SDavid S. Miller out:
17701da177e4SLinus Torvalds 	return err;
17711da177e4SLinus Torvalds }
17721da177e4SLinus Torvalds 
17731da177e4SLinus Torvalds /*
17741da177e4SLinus Torvalds  *	Receive a datagram from a socket.
17751da177e4SLinus Torvalds  */
17761da177e4SLinus Torvalds 
177789bddce5SStephen Hemminger asmlinkage long sys_recv(int fd, void __user *ubuf, size_t size,
177889bddce5SStephen Hemminger 			 unsigned flags)
17791da177e4SLinus Torvalds {
17801da177e4SLinus Torvalds 	return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL);
17811da177e4SLinus Torvalds }
17821da177e4SLinus Torvalds 
17831da177e4SLinus Torvalds /*
17841da177e4SLinus Torvalds  *	Set a socket option. Because we don't know the option lengths we have
17851da177e4SLinus Torvalds  *	to pass the user mode parameter for the protocols to sort out.
17861da177e4SLinus Torvalds  */
17871da177e4SLinus Torvalds 
178820f37034SHeiko Carstens SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
178920f37034SHeiko Carstens 		char __user *, optval, int, optlen)
17901da177e4SLinus Torvalds {
17916cb153caSBenjamin LaHaise 	int err, fput_needed;
17921da177e4SLinus Torvalds 	struct socket *sock;
17931da177e4SLinus Torvalds 
17941da177e4SLinus Torvalds 	if (optlen < 0)
17951da177e4SLinus Torvalds 		return -EINVAL;
17961da177e4SLinus Torvalds 
179789bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
179889bddce5SStephen Hemminger 	if (sock != NULL) {
17991da177e4SLinus Torvalds 		err = security_socket_setsockopt(sock, level, optname);
18006cb153caSBenjamin LaHaise 		if (err)
18016cb153caSBenjamin LaHaise 			goto out_put;
18021da177e4SLinus Torvalds 
18031da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
180489bddce5SStephen Hemminger 			err =
180589bddce5SStephen Hemminger 			    sock_setsockopt(sock, level, optname, optval,
180689bddce5SStephen Hemminger 					    optlen);
18071da177e4SLinus Torvalds 		else
180889bddce5SStephen Hemminger 			err =
180989bddce5SStephen Hemminger 			    sock->ops->setsockopt(sock, level, optname, optval,
181089bddce5SStephen Hemminger 						  optlen);
18116cb153caSBenjamin LaHaise out_put:
18126cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
18131da177e4SLinus Torvalds 	}
18141da177e4SLinus Torvalds 	return err;
18151da177e4SLinus Torvalds }
18161da177e4SLinus Torvalds 
18171da177e4SLinus Torvalds /*
18181da177e4SLinus Torvalds  *	Get a socket option. Because we don't know the option lengths we have
18191da177e4SLinus Torvalds  *	to pass a user mode parameter for the protocols to sort out.
18201da177e4SLinus Torvalds  */
18211da177e4SLinus Torvalds 
182220f37034SHeiko Carstens SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
182320f37034SHeiko Carstens 		char __user *, optval, int __user *, optlen)
18241da177e4SLinus Torvalds {
18256cb153caSBenjamin LaHaise 	int err, fput_needed;
18261da177e4SLinus Torvalds 	struct socket *sock;
18271da177e4SLinus Torvalds 
182889bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
182989bddce5SStephen Hemminger 	if (sock != NULL) {
18306cb153caSBenjamin LaHaise 		err = security_socket_getsockopt(sock, level, optname);
18316cb153caSBenjamin LaHaise 		if (err)
18326cb153caSBenjamin LaHaise 			goto out_put;
18331da177e4SLinus Torvalds 
18341da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
183589bddce5SStephen Hemminger 			err =
183689bddce5SStephen Hemminger 			    sock_getsockopt(sock, level, optname, optval,
183789bddce5SStephen Hemminger 					    optlen);
18381da177e4SLinus Torvalds 		else
183989bddce5SStephen Hemminger 			err =
184089bddce5SStephen Hemminger 			    sock->ops->getsockopt(sock, level, optname, optval,
184189bddce5SStephen Hemminger 						  optlen);
18426cb153caSBenjamin LaHaise out_put:
18436cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
18441da177e4SLinus Torvalds 	}
18451da177e4SLinus Torvalds 	return err;
18461da177e4SLinus Torvalds }
18471da177e4SLinus Torvalds 
18481da177e4SLinus Torvalds /*
18491da177e4SLinus Torvalds  *	Shutdown a socket.
18501da177e4SLinus Torvalds  */
18511da177e4SLinus Torvalds 
1852754fe8d2SHeiko Carstens SYSCALL_DEFINE2(shutdown, int, fd, int, how)
18531da177e4SLinus Torvalds {
18546cb153caSBenjamin LaHaise 	int err, fput_needed;
18551da177e4SLinus Torvalds 	struct socket *sock;
18561da177e4SLinus Torvalds 
185789bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
185889bddce5SStephen Hemminger 	if (sock != NULL) {
18591da177e4SLinus Torvalds 		err = security_socket_shutdown(sock, how);
18606cb153caSBenjamin LaHaise 		if (!err)
18611da177e4SLinus Torvalds 			err = sock->ops->shutdown(sock, how);
18626cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
18631da177e4SLinus Torvalds 	}
18641da177e4SLinus Torvalds 	return err;
18651da177e4SLinus Torvalds }
18661da177e4SLinus Torvalds 
18671da177e4SLinus Torvalds /* A couple of helpful macros for getting the address of the 32/64 bit
18681da177e4SLinus Torvalds  * fields which are the same type (int / unsigned) on our platforms.
18691da177e4SLinus Torvalds  */
18701da177e4SLinus Torvalds #define COMPAT_MSG(msg, member)	((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member)
18711da177e4SLinus Torvalds #define COMPAT_NAMELEN(msg)	COMPAT_MSG(msg, msg_namelen)
18721da177e4SLinus Torvalds #define COMPAT_FLAGS(msg)	COMPAT_MSG(msg, msg_flags)
18731da177e4SLinus Torvalds 
1874228e548eSAnton Blanchard static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
1875228e548eSAnton Blanchard 			 struct msghdr *msg_sys, unsigned flags, int nosec)
18761da177e4SLinus Torvalds {
187789bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
187889bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
1879230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
18801da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
1881b9d717a7SAlex Williamson 	unsigned char ctl[sizeof(struct cmsghdr) + 20]
1882b9d717a7SAlex Williamson 	    __attribute__ ((aligned(sizeof(__kernel_size_t))));
1883b9d717a7SAlex Williamson 	/* 20 is size of ipv6_pktinfo */
18841da177e4SLinus Torvalds 	unsigned char *ctl_buf = ctl;
18851da177e4SLinus Torvalds 	int err, ctl_len, iov_size, total_len;
18861da177e4SLinus Torvalds 
18871da177e4SLinus Torvalds 	err = -EFAULT;
18881da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
1889228e548eSAnton Blanchard 		if (get_compat_msghdr(msg_sys, msg_compat))
18901da177e4SLinus Torvalds 			return -EFAULT;
1891228e548eSAnton Blanchard 	} else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr)))
18921da177e4SLinus Torvalds 		return -EFAULT;
18931da177e4SLinus Torvalds 
18941da177e4SLinus Torvalds 	/* do not move before msg_sys is valid */
18951da177e4SLinus Torvalds 	err = -EMSGSIZE;
1896228e548eSAnton Blanchard 	if (msg_sys->msg_iovlen > UIO_MAXIOV)
1897228e548eSAnton Blanchard 		goto out;
18981da177e4SLinus Torvalds 
18991da177e4SLinus Torvalds 	/* Check whether to allocate the iovec area */
19001da177e4SLinus Torvalds 	err = -ENOMEM;
1901228e548eSAnton Blanchard 	iov_size = msg_sys->msg_iovlen * sizeof(struct iovec);
1902228e548eSAnton Blanchard 	if (msg_sys->msg_iovlen > UIO_FASTIOV) {
19031da177e4SLinus Torvalds 		iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
19041da177e4SLinus Torvalds 		if (!iov)
1905228e548eSAnton Blanchard 			goto out;
19061da177e4SLinus Torvalds 	}
19071da177e4SLinus Torvalds 
19081da177e4SLinus Torvalds 	/* This will also move the address data into kernel space */
19091da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
1910228e548eSAnton Blanchard 		err = verify_compat_iovec(msg_sys, iov,
1911230b1839SYOSHIFUJI Hideaki 					  (struct sockaddr *)&address,
1912230b1839SYOSHIFUJI Hideaki 					  VERIFY_READ);
19131da177e4SLinus Torvalds 	} else
1914228e548eSAnton Blanchard 		err = verify_iovec(msg_sys, iov,
1915230b1839SYOSHIFUJI Hideaki 				   (struct sockaddr *)&address,
1916230b1839SYOSHIFUJI Hideaki 				   VERIFY_READ);
19171da177e4SLinus Torvalds 	if (err < 0)
19181da177e4SLinus Torvalds 		goto out_freeiov;
19191da177e4SLinus Torvalds 	total_len = err;
19201da177e4SLinus Torvalds 
19211da177e4SLinus Torvalds 	err = -ENOBUFS;
19221da177e4SLinus Torvalds 
1923228e548eSAnton Blanchard 	if (msg_sys->msg_controllen > INT_MAX)
19241da177e4SLinus Torvalds 		goto out_freeiov;
1925228e548eSAnton Blanchard 	ctl_len = msg_sys->msg_controllen;
19261da177e4SLinus Torvalds 	if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
192789bddce5SStephen Hemminger 		err =
1928228e548eSAnton Blanchard 		    cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl,
192989bddce5SStephen Hemminger 						     sizeof(ctl));
19301da177e4SLinus Torvalds 		if (err)
19311da177e4SLinus Torvalds 			goto out_freeiov;
1932228e548eSAnton Blanchard 		ctl_buf = msg_sys->msg_control;
1933228e548eSAnton Blanchard 		ctl_len = msg_sys->msg_controllen;
19341da177e4SLinus Torvalds 	} else if (ctl_len) {
193589bddce5SStephen Hemminger 		if (ctl_len > sizeof(ctl)) {
19361da177e4SLinus Torvalds 			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
19371da177e4SLinus Torvalds 			if (ctl_buf == NULL)
19381da177e4SLinus Torvalds 				goto out_freeiov;
19391da177e4SLinus Torvalds 		}
19401da177e4SLinus Torvalds 		err = -EFAULT;
19411da177e4SLinus Torvalds 		/*
1942228e548eSAnton Blanchard 		 * Careful! Before this, msg_sys->msg_control contains a user pointer.
19431da177e4SLinus Torvalds 		 * Afterwards, it will be a kernel pointer. Thus the compiler-assisted
19441da177e4SLinus Torvalds 		 * checking falls down on this.
19451da177e4SLinus Torvalds 		 */
1946fb8621bbSNamhyung Kim 		if (copy_from_user(ctl_buf,
1947228e548eSAnton Blanchard 				   (void __user __force *)msg_sys->msg_control,
194889bddce5SStephen Hemminger 				   ctl_len))
19491da177e4SLinus Torvalds 			goto out_freectl;
1950228e548eSAnton Blanchard 		msg_sys->msg_control = ctl_buf;
19511da177e4SLinus Torvalds 	}
1952228e548eSAnton Blanchard 	msg_sys->msg_flags = flags;
19531da177e4SLinus Torvalds 
19541da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
1955228e548eSAnton Blanchard 		msg_sys->msg_flags |= MSG_DONTWAIT;
1956228e548eSAnton Blanchard 	err = (nosec ? sock_sendmsg_nosec : sock_sendmsg)(sock, msg_sys,
1957228e548eSAnton Blanchard 							  total_len);
19581da177e4SLinus Torvalds 
19591da177e4SLinus Torvalds out_freectl:
19601da177e4SLinus Torvalds 	if (ctl_buf != ctl)
19611da177e4SLinus Torvalds 		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
19621da177e4SLinus Torvalds out_freeiov:
19631da177e4SLinus Torvalds 	if (iov != iovstack)
19641da177e4SLinus Torvalds 		sock_kfree_s(sock->sk, iov, iov_size);
1965228e548eSAnton Blanchard out:
1966228e548eSAnton Blanchard 	return err;
1967228e548eSAnton Blanchard }
1968228e548eSAnton Blanchard 
1969228e548eSAnton Blanchard /*
1970228e548eSAnton Blanchard  *	BSD sendmsg interface
1971228e548eSAnton Blanchard  */
1972228e548eSAnton Blanchard 
1973228e548eSAnton Blanchard SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned, flags)
1974228e548eSAnton Blanchard {
1975228e548eSAnton Blanchard 	int fput_needed, err;
1976228e548eSAnton Blanchard 	struct msghdr msg_sys;
1977228e548eSAnton Blanchard 	struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed);
1978228e548eSAnton Blanchard 
1979228e548eSAnton Blanchard 	if (!sock)
1980228e548eSAnton Blanchard 		goto out;
1981228e548eSAnton Blanchard 
1982228e548eSAnton Blanchard 	err = __sys_sendmsg(sock, msg, &msg_sys, flags, 0);
1983228e548eSAnton Blanchard 
19846cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
19851da177e4SLinus Torvalds out:
19861da177e4SLinus Torvalds 	return err;
19871da177e4SLinus Torvalds }
19881da177e4SLinus Torvalds 
1989228e548eSAnton Blanchard /*
1990228e548eSAnton Blanchard  *	Linux sendmmsg interface
1991228e548eSAnton Blanchard  */
1992228e548eSAnton Blanchard 
1993228e548eSAnton Blanchard int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
1994228e548eSAnton Blanchard 		   unsigned int flags)
1995228e548eSAnton Blanchard {
1996228e548eSAnton Blanchard 	int fput_needed, err, datagrams;
1997228e548eSAnton Blanchard 	struct socket *sock;
1998228e548eSAnton Blanchard 	struct mmsghdr __user *entry;
1999228e548eSAnton Blanchard 	struct compat_mmsghdr __user *compat_entry;
2000228e548eSAnton Blanchard 	struct msghdr msg_sys;
2001228e548eSAnton Blanchard 
2002228e548eSAnton Blanchard 	datagrams = 0;
2003228e548eSAnton Blanchard 
2004228e548eSAnton Blanchard 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2005228e548eSAnton Blanchard 	if (!sock)
2006228e548eSAnton Blanchard 		return err;
2007228e548eSAnton Blanchard 
2008228e548eSAnton Blanchard 	err = sock_error(sock->sk);
2009228e548eSAnton Blanchard 	if (err)
2010228e548eSAnton Blanchard 		goto out_put;
2011228e548eSAnton Blanchard 
2012228e548eSAnton Blanchard 	entry = mmsg;
2013228e548eSAnton Blanchard 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2014228e548eSAnton Blanchard 
2015228e548eSAnton Blanchard 	while (datagrams < vlen) {
2016228e548eSAnton Blanchard 		/*
2017228e548eSAnton Blanchard 		 * No need to ask LSM for more than the first datagram.
2018228e548eSAnton Blanchard 		 */
2019228e548eSAnton Blanchard 		if (MSG_CMSG_COMPAT & flags) {
2020228e548eSAnton Blanchard 			err = __sys_sendmsg(sock, (struct msghdr __user *)compat_entry,
2021228e548eSAnton Blanchard 					    &msg_sys, flags, datagrams);
2022228e548eSAnton Blanchard 			if (err < 0)
2023228e548eSAnton Blanchard 				break;
2024228e548eSAnton Blanchard 			err = __put_user(err, &compat_entry->msg_len);
2025228e548eSAnton Blanchard 			++compat_entry;
2026228e548eSAnton Blanchard 		} else {
2027228e548eSAnton Blanchard 			err = __sys_sendmsg(sock, (struct msghdr __user *)entry,
2028228e548eSAnton Blanchard 					    &msg_sys, flags, datagrams);
2029228e548eSAnton Blanchard 			if (err < 0)
2030228e548eSAnton Blanchard 				break;
2031228e548eSAnton Blanchard 			err = put_user(err, &entry->msg_len);
2032228e548eSAnton Blanchard 			++entry;
2033228e548eSAnton Blanchard 		}
2034228e548eSAnton Blanchard 
2035228e548eSAnton Blanchard 		if (err)
2036228e548eSAnton Blanchard 			break;
2037228e548eSAnton Blanchard 		++datagrams;
2038228e548eSAnton Blanchard 	}
2039228e548eSAnton Blanchard 
2040228e548eSAnton Blanchard out_put:
2041228e548eSAnton Blanchard 	fput_light(sock->file, fput_needed);
2042228e548eSAnton Blanchard 
2043228e548eSAnton Blanchard 	if (err == 0)
2044228e548eSAnton Blanchard 		return datagrams;
2045228e548eSAnton Blanchard 
2046228e548eSAnton Blanchard 	if (datagrams != 0) {
2047228e548eSAnton Blanchard 		/*
2048228e548eSAnton Blanchard 		 * We may send less entries than requested (vlen) if the
2049228e548eSAnton Blanchard 		 * sock is non blocking...
2050228e548eSAnton Blanchard 		 */
2051228e548eSAnton Blanchard 		if (err != -EAGAIN) {
2052228e548eSAnton Blanchard 			/*
2053228e548eSAnton Blanchard 			 * ... or if sendmsg returns an error after we
2054228e548eSAnton Blanchard 			 * send some datagrams, where we record the
2055228e548eSAnton Blanchard 			 * error to return on the next call or if the
2056228e548eSAnton Blanchard 			 * app asks about it using getsockopt(SO_ERROR).
2057228e548eSAnton Blanchard 			 */
2058228e548eSAnton Blanchard 			sock->sk->sk_err = -err;
2059228e548eSAnton Blanchard 		}
2060228e548eSAnton Blanchard 
2061228e548eSAnton Blanchard 		return datagrams;
2062228e548eSAnton Blanchard 	}
2063228e548eSAnton Blanchard 
2064228e548eSAnton Blanchard 	return err;
2065228e548eSAnton Blanchard }
2066228e548eSAnton Blanchard 
2067228e548eSAnton Blanchard SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
2068228e548eSAnton Blanchard 		unsigned int, vlen, unsigned int, flags)
2069228e548eSAnton Blanchard {
2070228e548eSAnton Blanchard 	return __sys_sendmmsg(fd, mmsg, vlen, flags);
2071228e548eSAnton Blanchard }
2072228e548eSAnton Blanchard 
2073a2e27255SArnaldo Carvalho de Melo static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
2074a2e27255SArnaldo Carvalho de Melo 			 struct msghdr *msg_sys, unsigned flags, int nosec)
20751da177e4SLinus Torvalds {
207689bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
207789bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
20781da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV];
20791da177e4SLinus Torvalds 	struct iovec *iov = iovstack;
20801da177e4SLinus Torvalds 	unsigned long cmsg_ptr;
20811da177e4SLinus Torvalds 	int err, iov_size, total_len, len;
20821da177e4SLinus Torvalds 
20831da177e4SLinus Torvalds 	/* kernel mode address */
2084230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage addr;
20851da177e4SLinus Torvalds 
20861da177e4SLinus Torvalds 	/* user mode address pointers */
20871da177e4SLinus Torvalds 	struct sockaddr __user *uaddr;
20881da177e4SLinus Torvalds 	int __user *uaddr_len;
20891da177e4SLinus Torvalds 
20901da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
2091a2e27255SArnaldo Carvalho de Melo 		if (get_compat_msghdr(msg_sys, msg_compat))
20921da177e4SLinus Torvalds 			return -EFAULT;
2093c6d409cfSEric Dumazet 	} else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr)))
20941da177e4SLinus Torvalds 		return -EFAULT;
20951da177e4SLinus Torvalds 
20961da177e4SLinus Torvalds 	err = -EMSGSIZE;
2097a2e27255SArnaldo Carvalho de Melo 	if (msg_sys->msg_iovlen > UIO_MAXIOV)
2098a2e27255SArnaldo Carvalho de Melo 		goto out;
20991da177e4SLinus Torvalds 
21001da177e4SLinus Torvalds 	/* Check whether to allocate the iovec area */
21011da177e4SLinus Torvalds 	err = -ENOMEM;
2102a2e27255SArnaldo Carvalho de Melo 	iov_size = msg_sys->msg_iovlen * sizeof(struct iovec);
2103a2e27255SArnaldo Carvalho de Melo 	if (msg_sys->msg_iovlen > UIO_FASTIOV) {
21041da177e4SLinus Torvalds 		iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
21051da177e4SLinus Torvalds 		if (!iov)
2106a2e27255SArnaldo Carvalho de Melo 			goto out;
21071da177e4SLinus Torvalds 	}
21081da177e4SLinus Torvalds 
21091da177e4SLinus Torvalds 	/*
21101da177e4SLinus Torvalds 	 *      Save the user-mode address (verify_iovec will change the
21111da177e4SLinus Torvalds 	 *      kernel msghdr to use the kernel address space)
21121da177e4SLinus Torvalds 	 */
21131da177e4SLinus Torvalds 
2114a2e27255SArnaldo Carvalho de Melo 	uaddr = (__force void __user *)msg_sys->msg_name;
21151da177e4SLinus Torvalds 	uaddr_len = COMPAT_NAMELEN(msg);
21161da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
2117a2e27255SArnaldo Carvalho de Melo 		err = verify_compat_iovec(msg_sys, iov,
2118230b1839SYOSHIFUJI Hideaki 					  (struct sockaddr *)&addr,
2119230b1839SYOSHIFUJI Hideaki 					  VERIFY_WRITE);
21201da177e4SLinus Torvalds 	} else
2121a2e27255SArnaldo Carvalho de Melo 		err = verify_iovec(msg_sys, iov,
2122230b1839SYOSHIFUJI Hideaki 				   (struct sockaddr *)&addr,
2123230b1839SYOSHIFUJI Hideaki 				   VERIFY_WRITE);
21241da177e4SLinus Torvalds 	if (err < 0)
21251da177e4SLinus Torvalds 		goto out_freeiov;
21261da177e4SLinus Torvalds 	total_len = err;
21271da177e4SLinus Torvalds 
2128a2e27255SArnaldo Carvalho de Melo 	cmsg_ptr = (unsigned long)msg_sys->msg_control;
2129a2e27255SArnaldo Carvalho de Melo 	msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
21301da177e4SLinus Torvalds 
21311da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
21321da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
2133a2e27255SArnaldo Carvalho de Melo 	err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys,
2134a2e27255SArnaldo Carvalho de Melo 							  total_len, flags);
21351da177e4SLinus Torvalds 	if (err < 0)
21361da177e4SLinus Torvalds 		goto out_freeiov;
21371da177e4SLinus Torvalds 	len = err;
21381da177e4SLinus Torvalds 
21391da177e4SLinus Torvalds 	if (uaddr != NULL) {
2140230b1839SYOSHIFUJI Hideaki 		err = move_addr_to_user((struct sockaddr *)&addr,
2141a2e27255SArnaldo Carvalho de Melo 					msg_sys->msg_namelen, uaddr,
214289bddce5SStephen Hemminger 					uaddr_len);
21431da177e4SLinus Torvalds 		if (err < 0)
21441da177e4SLinus Torvalds 			goto out_freeiov;
21451da177e4SLinus Torvalds 	}
2146a2e27255SArnaldo Carvalho de Melo 	err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
214737f7f421SDavid S. Miller 			 COMPAT_FLAGS(msg));
21481da177e4SLinus Torvalds 	if (err)
21491da177e4SLinus Torvalds 		goto out_freeiov;
21501da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags)
2151a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
21521da177e4SLinus Torvalds 				 &msg_compat->msg_controllen);
21531da177e4SLinus Torvalds 	else
2154a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
21551da177e4SLinus Torvalds 				 &msg->msg_controllen);
21561da177e4SLinus Torvalds 	if (err)
21571da177e4SLinus Torvalds 		goto out_freeiov;
21581da177e4SLinus Torvalds 	err = len;
21591da177e4SLinus Torvalds 
21601da177e4SLinus Torvalds out_freeiov:
21611da177e4SLinus Torvalds 	if (iov != iovstack)
21621da177e4SLinus Torvalds 		sock_kfree_s(sock->sk, iov, iov_size);
2163a2e27255SArnaldo Carvalho de Melo out:
2164a2e27255SArnaldo Carvalho de Melo 	return err;
2165a2e27255SArnaldo Carvalho de Melo }
2166a2e27255SArnaldo Carvalho de Melo 
2167a2e27255SArnaldo Carvalho de Melo /*
2168a2e27255SArnaldo Carvalho de Melo  *	BSD recvmsg interface
2169a2e27255SArnaldo Carvalho de Melo  */
2170a2e27255SArnaldo Carvalho de Melo 
2171a2e27255SArnaldo Carvalho de Melo SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg,
2172a2e27255SArnaldo Carvalho de Melo 		unsigned int, flags)
2173a2e27255SArnaldo Carvalho de Melo {
2174a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err;
2175a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
2176a2e27255SArnaldo Carvalho de Melo 	struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed);
2177a2e27255SArnaldo Carvalho de Melo 
2178a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2179a2e27255SArnaldo Carvalho de Melo 		goto out;
2180a2e27255SArnaldo Carvalho de Melo 
2181a2e27255SArnaldo Carvalho de Melo 	err = __sys_recvmsg(sock, msg, &msg_sys, flags, 0);
2182a2e27255SArnaldo Carvalho de Melo 
21836cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
21841da177e4SLinus Torvalds out:
21851da177e4SLinus Torvalds 	return err;
21861da177e4SLinus Torvalds }
21871da177e4SLinus Torvalds 
2188a2e27255SArnaldo Carvalho de Melo /*
2189a2e27255SArnaldo Carvalho de Melo  *     Linux recvmmsg interface
2190a2e27255SArnaldo Carvalho de Melo  */
21911da177e4SLinus Torvalds 
2192a2e27255SArnaldo Carvalho de Melo int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2193a2e27255SArnaldo Carvalho de Melo 		   unsigned int flags, struct timespec *timeout)
2194a2e27255SArnaldo Carvalho de Melo {
2195a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err, datagrams;
2196a2e27255SArnaldo Carvalho de Melo 	struct socket *sock;
2197a2e27255SArnaldo Carvalho de Melo 	struct mmsghdr __user *entry;
2198d7256d0eSJean-Mickael Guerin 	struct compat_mmsghdr __user *compat_entry;
2199a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
2200a2e27255SArnaldo Carvalho de Melo 	struct timespec end_time;
2201a2e27255SArnaldo Carvalho de Melo 
2202a2e27255SArnaldo Carvalho de Melo 	if (timeout &&
2203a2e27255SArnaldo Carvalho de Melo 	    poll_select_set_timeout(&end_time, timeout->tv_sec,
2204a2e27255SArnaldo Carvalho de Melo 				    timeout->tv_nsec))
2205a2e27255SArnaldo Carvalho de Melo 		return -EINVAL;
2206a2e27255SArnaldo Carvalho de Melo 
2207a2e27255SArnaldo Carvalho de Melo 	datagrams = 0;
2208a2e27255SArnaldo Carvalho de Melo 
2209a2e27255SArnaldo Carvalho de Melo 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2210a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2211a2e27255SArnaldo Carvalho de Melo 		return err;
2212a2e27255SArnaldo Carvalho de Melo 
2213a2e27255SArnaldo Carvalho de Melo 	err = sock_error(sock->sk);
2214a2e27255SArnaldo Carvalho de Melo 	if (err)
2215a2e27255SArnaldo Carvalho de Melo 		goto out_put;
2216a2e27255SArnaldo Carvalho de Melo 
2217a2e27255SArnaldo Carvalho de Melo 	entry = mmsg;
2218d7256d0eSJean-Mickael Guerin 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2219a2e27255SArnaldo Carvalho de Melo 
2220a2e27255SArnaldo Carvalho de Melo 	while (datagrams < vlen) {
2221a2e27255SArnaldo Carvalho de Melo 		/*
2222a2e27255SArnaldo Carvalho de Melo 		 * No need to ask LSM for more than the first datagram.
2223a2e27255SArnaldo Carvalho de Melo 		 */
2224d7256d0eSJean-Mickael Guerin 		if (MSG_CMSG_COMPAT & flags) {
2225d7256d0eSJean-Mickael Guerin 			err = __sys_recvmsg(sock, (struct msghdr __user *)compat_entry,
2226b9eb8b87SAnton Blanchard 					    &msg_sys, flags & ~MSG_WAITFORONE,
2227b9eb8b87SAnton Blanchard 					    datagrams);
2228d7256d0eSJean-Mickael Guerin 			if (err < 0)
2229d7256d0eSJean-Mickael Guerin 				break;
2230d7256d0eSJean-Mickael Guerin 			err = __put_user(err, &compat_entry->msg_len);
2231d7256d0eSJean-Mickael Guerin 			++compat_entry;
2232d7256d0eSJean-Mickael Guerin 		} else {
2233a2e27255SArnaldo Carvalho de Melo 			err = __sys_recvmsg(sock, (struct msghdr __user *)entry,
2234b9eb8b87SAnton Blanchard 					    &msg_sys, flags & ~MSG_WAITFORONE,
2235b9eb8b87SAnton Blanchard 					    datagrams);
2236a2e27255SArnaldo Carvalho de Melo 			if (err < 0)
2237a2e27255SArnaldo Carvalho de Melo 				break;
2238a2e27255SArnaldo Carvalho de Melo 			err = put_user(err, &entry->msg_len);
2239d7256d0eSJean-Mickael Guerin 			++entry;
2240d7256d0eSJean-Mickael Guerin 		}
2241d7256d0eSJean-Mickael Guerin 
2242a2e27255SArnaldo Carvalho de Melo 		if (err)
2243a2e27255SArnaldo Carvalho de Melo 			break;
2244a2e27255SArnaldo Carvalho de Melo 		++datagrams;
2245a2e27255SArnaldo Carvalho de Melo 
224671c5c159SBrandon L Black 		/* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
224771c5c159SBrandon L Black 		if (flags & MSG_WAITFORONE)
224871c5c159SBrandon L Black 			flags |= MSG_DONTWAIT;
224971c5c159SBrandon L Black 
2250a2e27255SArnaldo Carvalho de Melo 		if (timeout) {
2251a2e27255SArnaldo Carvalho de Melo 			ktime_get_ts(timeout);
2252a2e27255SArnaldo Carvalho de Melo 			*timeout = timespec_sub(end_time, *timeout);
2253a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_sec < 0) {
2254a2e27255SArnaldo Carvalho de Melo 				timeout->tv_sec = timeout->tv_nsec = 0;
2255a2e27255SArnaldo Carvalho de Melo 				break;
2256a2e27255SArnaldo Carvalho de Melo 			}
2257a2e27255SArnaldo Carvalho de Melo 
2258a2e27255SArnaldo Carvalho de Melo 			/* Timeout, return less than vlen datagrams */
2259a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_nsec == 0 && timeout->tv_sec == 0)
2260a2e27255SArnaldo Carvalho de Melo 				break;
2261a2e27255SArnaldo Carvalho de Melo 		}
2262a2e27255SArnaldo Carvalho de Melo 
2263a2e27255SArnaldo Carvalho de Melo 		/* Out of band data, return right away */
2264a2e27255SArnaldo Carvalho de Melo 		if (msg_sys.msg_flags & MSG_OOB)
2265a2e27255SArnaldo Carvalho de Melo 			break;
2266a2e27255SArnaldo Carvalho de Melo 	}
2267a2e27255SArnaldo Carvalho de Melo 
2268a2e27255SArnaldo Carvalho de Melo out_put:
2269a2e27255SArnaldo Carvalho de Melo 	fput_light(sock->file, fput_needed);
2270a2e27255SArnaldo Carvalho de Melo 
2271a2e27255SArnaldo Carvalho de Melo 	if (err == 0)
2272a2e27255SArnaldo Carvalho de Melo 		return datagrams;
2273a2e27255SArnaldo Carvalho de Melo 
2274a2e27255SArnaldo Carvalho de Melo 	if (datagrams != 0) {
2275a2e27255SArnaldo Carvalho de Melo 		/*
2276a2e27255SArnaldo Carvalho de Melo 		 * We may return less entries than requested (vlen) if the
2277a2e27255SArnaldo Carvalho de Melo 		 * sock is non block and there aren't enough datagrams...
2278a2e27255SArnaldo Carvalho de Melo 		 */
2279a2e27255SArnaldo Carvalho de Melo 		if (err != -EAGAIN) {
2280a2e27255SArnaldo Carvalho de Melo 			/*
2281a2e27255SArnaldo Carvalho de Melo 			 * ... or  if recvmsg returns an error after we
2282a2e27255SArnaldo Carvalho de Melo 			 * received some datagrams, where we record the
2283a2e27255SArnaldo Carvalho de Melo 			 * error to return on the next call or if the
2284a2e27255SArnaldo Carvalho de Melo 			 * app asks about it using getsockopt(SO_ERROR).
2285a2e27255SArnaldo Carvalho de Melo 			 */
2286a2e27255SArnaldo Carvalho de Melo 			sock->sk->sk_err = -err;
2287a2e27255SArnaldo Carvalho de Melo 		}
2288a2e27255SArnaldo Carvalho de Melo 
2289a2e27255SArnaldo Carvalho de Melo 		return datagrams;
2290a2e27255SArnaldo Carvalho de Melo 	}
2291a2e27255SArnaldo Carvalho de Melo 
2292a2e27255SArnaldo Carvalho de Melo 	return err;
2293a2e27255SArnaldo Carvalho de Melo }
2294a2e27255SArnaldo Carvalho de Melo 
2295a2e27255SArnaldo Carvalho de Melo SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
2296a2e27255SArnaldo Carvalho de Melo 		unsigned int, vlen, unsigned int, flags,
2297a2e27255SArnaldo Carvalho de Melo 		struct timespec __user *, timeout)
2298a2e27255SArnaldo Carvalho de Melo {
2299a2e27255SArnaldo Carvalho de Melo 	int datagrams;
2300a2e27255SArnaldo Carvalho de Melo 	struct timespec timeout_sys;
2301a2e27255SArnaldo Carvalho de Melo 
2302a2e27255SArnaldo Carvalho de Melo 	if (!timeout)
2303a2e27255SArnaldo Carvalho de Melo 		return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL);
2304a2e27255SArnaldo Carvalho de Melo 
2305a2e27255SArnaldo Carvalho de Melo 	if (copy_from_user(&timeout_sys, timeout, sizeof(timeout_sys)))
2306a2e27255SArnaldo Carvalho de Melo 		return -EFAULT;
2307a2e27255SArnaldo Carvalho de Melo 
2308a2e27255SArnaldo Carvalho de Melo 	datagrams = __sys_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys);
2309a2e27255SArnaldo Carvalho de Melo 
2310a2e27255SArnaldo Carvalho de Melo 	if (datagrams > 0 &&
2311a2e27255SArnaldo Carvalho de Melo 	    copy_to_user(timeout, &timeout_sys, sizeof(timeout_sys)))
2312a2e27255SArnaldo Carvalho de Melo 		datagrams = -EFAULT;
2313a2e27255SArnaldo Carvalho de Melo 
2314a2e27255SArnaldo Carvalho de Melo 	return datagrams;
2315a2e27255SArnaldo Carvalho de Melo }
2316a2e27255SArnaldo Carvalho de Melo 
2317a2e27255SArnaldo Carvalho de Melo #ifdef __ARCH_WANT_SYS_SOCKETCALL
23181da177e4SLinus Torvalds /* Argument list sizes for sys_socketcall */
23191da177e4SLinus Torvalds #define AL(x) ((x) * sizeof(unsigned long))
2320228e548eSAnton Blanchard static const unsigned char nargs[21] = {
232189bddce5SStephen Hemminger 	AL(0), AL(3), AL(3), AL(3), AL(2), AL(3),
23221da177e4SLinus Torvalds 	AL(3), AL(3), AL(4), AL(4), AL(4), AL(6),
2323aaca0bdcSUlrich Drepper 	AL(6), AL(2), AL(5), AL(5), AL(3), AL(3),
2324228e548eSAnton Blanchard 	AL(4), AL(5), AL(4)
232589bddce5SStephen Hemminger };
232689bddce5SStephen Hemminger 
23271da177e4SLinus Torvalds #undef AL
23281da177e4SLinus Torvalds 
23291da177e4SLinus Torvalds /*
23301da177e4SLinus Torvalds  *	System call vectors.
23311da177e4SLinus Torvalds  *
23321da177e4SLinus Torvalds  *	Argument checking cleaned up. Saved 20% in size.
23331da177e4SLinus Torvalds  *  This function doesn't need to set the kernel lock because
23341da177e4SLinus Torvalds  *  it is set by the callees.
23351da177e4SLinus Torvalds  */
23361da177e4SLinus Torvalds 
23373e0fa65fSHeiko Carstens SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
23381da177e4SLinus Torvalds {
23391da177e4SLinus Torvalds 	unsigned long a[6];
23401da177e4SLinus Torvalds 	unsigned long a0, a1;
23411da177e4SLinus Torvalds 	int err;
234247379052SArjan van de Ven 	unsigned int len;
23431da177e4SLinus Torvalds 
2344228e548eSAnton Blanchard 	if (call < 1 || call > SYS_SENDMMSG)
23451da177e4SLinus Torvalds 		return -EINVAL;
23461da177e4SLinus Torvalds 
234747379052SArjan van de Ven 	len = nargs[call];
234847379052SArjan van de Ven 	if (len > sizeof(a))
234947379052SArjan van de Ven 		return -EINVAL;
235047379052SArjan van de Ven 
23511da177e4SLinus Torvalds 	/* copy_from_user should be SMP safe. */
235247379052SArjan van de Ven 	if (copy_from_user(a, args, len))
23531da177e4SLinus Torvalds 		return -EFAULT;
23541da177e4SLinus Torvalds 
2355f3298dc4SAl Viro 	audit_socketcall(nargs[call] / sizeof(unsigned long), a);
23563ec3b2fbSDavid Woodhouse 
23571da177e4SLinus Torvalds 	a0 = a[0];
23581da177e4SLinus Torvalds 	a1 = a[1];
23591da177e4SLinus Torvalds 
236089bddce5SStephen Hemminger 	switch (call) {
23611da177e4SLinus Torvalds 	case SYS_SOCKET:
23621da177e4SLinus Torvalds 		err = sys_socket(a0, a1, a[2]);
23631da177e4SLinus Torvalds 		break;
23641da177e4SLinus Torvalds 	case SYS_BIND:
23651da177e4SLinus Torvalds 		err = sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
23661da177e4SLinus Torvalds 		break;
23671da177e4SLinus Torvalds 	case SYS_CONNECT:
23681da177e4SLinus Torvalds 		err = sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
23691da177e4SLinus Torvalds 		break;
23701da177e4SLinus Torvalds 	case SYS_LISTEN:
23711da177e4SLinus Torvalds 		err = sys_listen(a0, a1);
23721da177e4SLinus Torvalds 		break;
23731da177e4SLinus Torvalds 	case SYS_ACCEPT:
2374de11defeSUlrich Drepper 		err = sys_accept4(a0, (struct sockaddr __user *)a1,
2375aaca0bdcSUlrich Drepper 				  (int __user *)a[2], 0);
23761da177e4SLinus Torvalds 		break;
23771da177e4SLinus Torvalds 	case SYS_GETSOCKNAME:
237889bddce5SStephen Hemminger 		err =
237989bddce5SStephen Hemminger 		    sys_getsockname(a0, (struct sockaddr __user *)a1,
238089bddce5SStephen Hemminger 				    (int __user *)a[2]);
23811da177e4SLinus Torvalds 		break;
23821da177e4SLinus Torvalds 	case SYS_GETPEERNAME:
238389bddce5SStephen Hemminger 		err =
238489bddce5SStephen Hemminger 		    sys_getpeername(a0, (struct sockaddr __user *)a1,
238589bddce5SStephen Hemminger 				    (int __user *)a[2]);
23861da177e4SLinus Torvalds 		break;
23871da177e4SLinus Torvalds 	case SYS_SOCKETPAIR:
23881da177e4SLinus Torvalds 		err = sys_socketpair(a0, a1, a[2], (int __user *)a[3]);
23891da177e4SLinus Torvalds 		break;
23901da177e4SLinus Torvalds 	case SYS_SEND:
23911da177e4SLinus Torvalds 		err = sys_send(a0, (void __user *)a1, a[2], a[3]);
23921da177e4SLinus Torvalds 		break;
23931da177e4SLinus Torvalds 	case SYS_SENDTO:
23941da177e4SLinus Torvalds 		err = sys_sendto(a0, (void __user *)a1, a[2], a[3],
23951da177e4SLinus Torvalds 				 (struct sockaddr __user *)a[4], a[5]);
23961da177e4SLinus Torvalds 		break;
23971da177e4SLinus Torvalds 	case SYS_RECV:
23981da177e4SLinus Torvalds 		err = sys_recv(a0, (void __user *)a1, a[2], a[3]);
23991da177e4SLinus Torvalds 		break;
24001da177e4SLinus Torvalds 	case SYS_RECVFROM:
24011da177e4SLinus Torvalds 		err = sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
240289bddce5SStephen Hemminger 				   (struct sockaddr __user *)a[4],
240389bddce5SStephen Hemminger 				   (int __user *)a[5]);
24041da177e4SLinus Torvalds 		break;
24051da177e4SLinus Torvalds 	case SYS_SHUTDOWN:
24061da177e4SLinus Torvalds 		err = sys_shutdown(a0, a1);
24071da177e4SLinus Torvalds 		break;
24081da177e4SLinus Torvalds 	case SYS_SETSOCKOPT:
24091da177e4SLinus Torvalds 		err = sys_setsockopt(a0, a1, a[2], (char __user *)a[3], a[4]);
24101da177e4SLinus Torvalds 		break;
24111da177e4SLinus Torvalds 	case SYS_GETSOCKOPT:
241289bddce5SStephen Hemminger 		err =
241389bddce5SStephen Hemminger 		    sys_getsockopt(a0, a1, a[2], (char __user *)a[3],
241489bddce5SStephen Hemminger 				   (int __user *)a[4]);
24151da177e4SLinus Torvalds 		break;
24161da177e4SLinus Torvalds 	case SYS_SENDMSG:
24171da177e4SLinus Torvalds 		err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]);
24181da177e4SLinus Torvalds 		break;
2419228e548eSAnton Blanchard 	case SYS_SENDMMSG:
2420228e548eSAnton Blanchard 		err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]);
2421228e548eSAnton Blanchard 		break;
24221da177e4SLinus Torvalds 	case SYS_RECVMSG:
24231da177e4SLinus Torvalds 		err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]);
24241da177e4SLinus Torvalds 		break;
2425a2e27255SArnaldo Carvalho de Melo 	case SYS_RECVMMSG:
2426a2e27255SArnaldo Carvalho de Melo 		err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3],
2427a2e27255SArnaldo Carvalho de Melo 				   (struct timespec __user *)a[4]);
2428a2e27255SArnaldo Carvalho de Melo 		break;
2429de11defeSUlrich Drepper 	case SYS_ACCEPT4:
2430de11defeSUlrich Drepper 		err = sys_accept4(a0, (struct sockaddr __user *)a1,
2431de11defeSUlrich Drepper 				  (int __user *)a[2], a[3]);
2432aaca0bdcSUlrich Drepper 		break;
24331da177e4SLinus Torvalds 	default:
24341da177e4SLinus Torvalds 		err = -EINVAL;
24351da177e4SLinus Torvalds 		break;
24361da177e4SLinus Torvalds 	}
24371da177e4SLinus Torvalds 	return err;
24381da177e4SLinus Torvalds }
24391da177e4SLinus Torvalds 
24401da177e4SLinus Torvalds #endif				/* __ARCH_WANT_SYS_SOCKETCALL */
24411da177e4SLinus Torvalds 
244255737fdaSStephen Hemminger /**
244355737fdaSStephen Hemminger  *	sock_register - add a socket protocol handler
244455737fdaSStephen Hemminger  *	@ops: description of protocol
244555737fdaSStephen Hemminger  *
24461da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
24471da177e4SLinus Torvalds  *	advertise its address family, and have it linked into the
244855737fdaSStephen Hemminger  *	socket interface. The value ops->family coresponds to the
244955737fdaSStephen Hemminger  *	socket system call protocol family.
24501da177e4SLinus Torvalds  */
2451f0fd27d4SStephen Hemminger int sock_register(const struct net_proto_family *ops)
24521da177e4SLinus Torvalds {
24531da177e4SLinus Torvalds 	int err;
24541da177e4SLinus Torvalds 
24551da177e4SLinus Torvalds 	if (ops->family >= NPROTO) {
245689bddce5SStephen Hemminger 		printk(KERN_CRIT "protocol %d >= NPROTO(%d)\n", ops->family,
245789bddce5SStephen Hemminger 		       NPROTO);
24581da177e4SLinus Torvalds 		return -ENOBUFS;
24591da177e4SLinus Torvalds 	}
246055737fdaSStephen Hemminger 
246155737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2462190683a9SEric Dumazet 	if (rcu_dereference_protected(net_families[ops->family],
2463190683a9SEric Dumazet 				      lockdep_is_held(&net_family_lock)))
24641da177e4SLinus Torvalds 		err = -EEXIST;
246555737fdaSStephen Hemminger 	else {
2466190683a9SEric Dumazet 		rcu_assign_pointer(net_families[ops->family], ops);
24671da177e4SLinus Torvalds 		err = 0;
24681da177e4SLinus Torvalds 	}
246955737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
247055737fdaSStephen Hemminger 
247189bddce5SStephen Hemminger 	printk(KERN_INFO "NET: Registered protocol family %d\n", ops->family);
24721da177e4SLinus Torvalds 	return err;
24731da177e4SLinus Torvalds }
2474c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_register);
24751da177e4SLinus Torvalds 
247655737fdaSStephen Hemminger /**
247755737fdaSStephen Hemminger  *	sock_unregister - remove a protocol handler
247855737fdaSStephen Hemminger  *	@family: protocol family to remove
247955737fdaSStephen Hemminger  *
24801da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
24811da177e4SLinus Torvalds  *	remove its address family, and have it unlinked from the
248255737fdaSStephen Hemminger  *	new socket creation.
248355737fdaSStephen Hemminger  *
248455737fdaSStephen Hemminger  *	If protocol handler is a module, then it can use module reference
248555737fdaSStephen Hemminger  *	counts to protect against new references. If protocol handler is not
248655737fdaSStephen Hemminger  *	a module then it needs to provide its own protection in
248755737fdaSStephen Hemminger  *	the ops->create routine.
24881da177e4SLinus Torvalds  */
2489f0fd27d4SStephen Hemminger void sock_unregister(int family)
24901da177e4SLinus Torvalds {
2491f0fd27d4SStephen Hemminger 	BUG_ON(family < 0 || family >= NPROTO);
24921da177e4SLinus Torvalds 
249355737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2494190683a9SEric Dumazet 	rcu_assign_pointer(net_families[family], NULL);
249555737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
249655737fdaSStephen Hemminger 
249755737fdaSStephen Hemminger 	synchronize_rcu();
249855737fdaSStephen Hemminger 
249989bddce5SStephen Hemminger 	printk(KERN_INFO "NET: Unregistered protocol family %d\n", family);
25001da177e4SLinus Torvalds }
2501c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_unregister);
25021da177e4SLinus Torvalds 
250377d76ea3SAndi Kleen static int __init sock_init(void)
25041da177e4SLinus Torvalds {
2505b3e19d92SNick Piggin 	int err;
2506b3e19d92SNick Piggin 
25071da177e4SLinus Torvalds 	/*
25081da177e4SLinus Torvalds 	 *      Initialize sock SLAB cache.
25091da177e4SLinus Torvalds 	 */
25101da177e4SLinus Torvalds 
25111da177e4SLinus Torvalds 	sk_init();
25121da177e4SLinus Torvalds 
25131da177e4SLinus Torvalds 	/*
25141da177e4SLinus Torvalds 	 *      Initialize skbuff SLAB cache
25151da177e4SLinus Torvalds 	 */
25161da177e4SLinus Torvalds 	skb_init();
25171da177e4SLinus Torvalds 
25181da177e4SLinus Torvalds 	/*
25191da177e4SLinus Torvalds 	 *      Initialize the protocols module.
25201da177e4SLinus Torvalds 	 */
25211da177e4SLinus Torvalds 
25221da177e4SLinus Torvalds 	init_inodecache();
2523b3e19d92SNick Piggin 
2524b3e19d92SNick Piggin 	err = register_filesystem(&sock_fs_type);
2525b3e19d92SNick Piggin 	if (err)
2526b3e19d92SNick Piggin 		goto out_fs;
25271da177e4SLinus Torvalds 	sock_mnt = kern_mount(&sock_fs_type);
2528b3e19d92SNick Piggin 	if (IS_ERR(sock_mnt)) {
2529b3e19d92SNick Piggin 		err = PTR_ERR(sock_mnt);
2530b3e19d92SNick Piggin 		goto out_mount;
2531b3e19d92SNick Piggin 	}
253277d76ea3SAndi Kleen 
253377d76ea3SAndi Kleen 	/* The real protocol initialization is performed in later initcalls.
25341da177e4SLinus Torvalds 	 */
25351da177e4SLinus Torvalds 
25361da177e4SLinus Torvalds #ifdef CONFIG_NETFILTER
25371da177e4SLinus Torvalds 	netfilter_init();
25381da177e4SLinus Torvalds #endif
2539cbeb321aSDavid S. Miller 
2540c1f19b51SRichard Cochran #ifdef CONFIG_NETWORK_PHY_TIMESTAMPING
2541c1f19b51SRichard Cochran 	skb_timestamping_init();
2542c1f19b51SRichard Cochran #endif
2543c1f19b51SRichard Cochran 
2544b3e19d92SNick Piggin out:
2545b3e19d92SNick Piggin 	return err;
2546b3e19d92SNick Piggin 
2547b3e19d92SNick Piggin out_mount:
2548b3e19d92SNick Piggin 	unregister_filesystem(&sock_fs_type);
2549b3e19d92SNick Piggin out_fs:
2550b3e19d92SNick Piggin 	goto out;
25511da177e4SLinus Torvalds }
25521da177e4SLinus Torvalds 
255377d76ea3SAndi Kleen core_initcall(sock_init);	/* early initcall */
255477d76ea3SAndi Kleen 
25551da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS
25561da177e4SLinus Torvalds void socket_seq_show(struct seq_file *seq)
25571da177e4SLinus Torvalds {
25581da177e4SLinus Torvalds 	int cpu;
25591da177e4SLinus Torvalds 	int counter = 0;
25601da177e4SLinus Torvalds 
25616f912042SKAMEZAWA Hiroyuki 	for_each_possible_cpu(cpu)
25621da177e4SLinus Torvalds 	    counter += per_cpu(sockets_in_use, cpu);
25631da177e4SLinus Torvalds 
25641da177e4SLinus Torvalds 	/* It can be negative, by the way. 8) */
25651da177e4SLinus Torvalds 	if (counter < 0)
25661da177e4SLinus Torvalds 		counter = 0;
25671da177e4SLinus Torvalds 
25681da177e4SLinus Torvalds 	seq_printf(seq, "sockets: used %d\n", counter);
25691da177e4SLinus Torvalds }
25701da177e4SLinus Torvalds #endif				/* CONFIG_PROC_FS */
25711da177e4SLinus Torvalds 
257289bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
25736b96018bSArnd Bergmann static int do_siocgstamp(struct net *net, struct socket *sock,
25746b96018bSArnd Bergmann 			 unsigned int cmd, struct compat_timeval __user *up)
25757a229387SArnd Bergmann {
25767a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
25777a229387SArnd Bergmann 	struct timeval ktv;
25787a229387SArnd Bergmann 	int err;
25797a229387SArnd Bergmann 
25807a229387SArnd Bergmann 	set_fs(KERNEL_DS);
25816b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv);
25827a229387SArnd Bergmann 	set_fs(old_fs);
25837a229387SArnd Bergmann 	if (!err) {
25847a229387SArnd Bergmann 		err = put_user(ktv.tv_sec, &up->tv_sec);
25857a229387SArnd Bergmann 		err |= __put_user(ktv.tv_usec, &up->tv_usec);
25867a229387SArnd Bergmann 	}
25877a229387SArnd Bergmann 	return err;
25887a229387SArnd Bergmann }
25897a229387SArnd Bergmann 
25906b96018bSArnd Bergmann static int do_siocgstampns(struct net *net, struct socket *sock,
25916b96018bSArnd Bergmann 			 unsigned int cmd, struct compat_timespec __user *up)
25927a229387SArnd Bergmann {
25937a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
25947a229387SArnd Bergmann 	struct timespec kts;
25957a229387SArnd Bergmann 	int err;
25967a229387SArnd Bergmann 
25977a229387SArnd Bergmann 	set_fs(KERNEL_DS);
25986b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts);
25997a229387SArnd Bergmann 	set_fs(old_fs);
26007a229387SArnd Bergmann 	if (!err) {
26017a229387SArnd Bergmann 		err = put_user(kts.tv_sec, &up->tv_sec);
26027a229387SArnd Bergmann 		err |= __put_user(kts.tv_nsec, &up->tv_nsec);
26037a229387SArnd Bergmann 	}
26047a229387SArnd Bergmann 	return err;
26057a229387SArnd Bergmann }
26067a229387SArnd Bergmann 
26076b96018bSArnd Bergmann static int dev_ifname32(struct net *net, struct compat_ifreq __user *uifr32)
26087a229387SArnd Bergmann {
26097a229387SArnd Bergmann 	struct ifreq __user *uifr;
26107a229387SArnd Bergmann 	int err;
26117a229387SArnd Bergmann 
26127a229387SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(struct ifreq));
26136b96018bSArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
26147a229387SArnd Bergmann 		return -EFAULT;
26157a229387SArnd Bergmann 
26166b96018bSArnd Bergmann 	err = dev_ioctl(net, SIOCGIFNAME, uifr);
26177a229387SArnd Bergmann 	if (err)
26187a229387SArnd Bergmann 		return err;
26197a229387SArnd Bergmann 
26206b96018bSArnd Bergmann 	if (copy_in_user(uifr32, uifr, sizeof(struct compat_ifreq)))
26217a229387SArnd Bergmann 		return -EFAULT;
26227a229387SArnd Bergmann 
26237a229387SArnd Bergmann 	return 0;
26247a229387SArnd Bergmann }
26257a229387SArnd Bergmann 
26266b96018bSArnd Bergmann static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32)
26277a229387SArnd Bergmann {
26286b96018bSArnd Bergmann 	struct compat_ifconf ifc32;
26297a229387SArnd Bergmann 	struct ifconf ifc;
26307a229387SArnd Bergmann 	struct ifconf __user *uifc;
26316b96018bSArnd Bergmann 	struct compat_ifreq __user *ifr32;
26327a229387SArnd Bergmann 	struct ifreq __user *ifr;
26337a229387SArnd Bergmann 	unsigned int i, j;
26347a229387SArnd Bergmann 	int err;
26357a229387SArnd Bergmann 
26366b96018bSArnd Bergmann 	if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf)))
26377a229387SArnd Bergmann 		return -EFAULT;
26387a229387SArnd Bergmann 
26397a229387SArnd Bergmann 	if (ifc32.ifcbuf == 0) {
26407a229387SArnd Bergmann 		ifc32.ifc_len = 0;
26417a229387SArnd Bergmann 		ifc.ifc_len = 0;
26427a229387SArnd Bergmann 		ifc.ifc_req = NULL;
26437a229387SArnd Bergmann 		uifc = compat_alloc_user_space(sizeof(struct ifconf));
26447a229387SArnd Bergmann 	} else {
26456b96018bSArnd Bergmann 		size_t len = ((ifc32.ifc_len / sizeof(struct compat_ifreq)) + 1) *
26467a229387SArnd Bergmann 			sizeof(struct ifreq);
26477a229387SArnd Bergmann 		uifc = compat_alloc_user_space(sizeof(struct ifconf) + len);
26487a229387SArnd Bergmann 		ifc.ifc_len = len;
26497a229387SArnd Bergmann 		ifr = ifc.ifc_req = (void __user *)(uifc + 1);
26507a229387SArnd Bergmann 		ifr32 = compat_ptr(ifc32.ifcbuf);
26516b96018bSArnd Bergmann 		for (i = 0; i < ifc32.ifc_len; i += sizeof(struct compat_ifreq)) {
26526b96018bSArnd Bergmann 			if (copy_in_user(ifr, ifr32, sizeof(struct compat_ifreq)))
26537a229387SArnd Bergmann 				return -EFAULT;
26547a229387SArnd Bergmann 			ifr++;
26557a229387SArnd Bergmann 			ifr32++;
26567a229387SArnd Bergmann 		}
26577a229387SArnd Bergmann 	}
26587a229387SArnd Bergmann 	if (copy_to_user(uifc, &ifc, sizeof(struct ifconf)))
26597a229387SArnd Bergmann 		return -EFAULT;
26607a229387SArnd Bergmann 
26616b96018bSArnd Bergmann 	err = dev_ioctl(net, SIOCGIFCONF, uifc);
26627a229387SArnd Bergmann 	if (err)
26637a229387SArnd Bergmann 		return err;
26647a229387SArnd Bergmann 
26657a229387SArnd Bergmann 	if (copy_from_user(&ifc, uifc, sizeof(struct ifconf)))
26667a229387SArnd Bergmann 		return -EFAULT;
26677a229387SArnd Bergmann 
26687a229387SArnd Bergmann 	ifr = ifc.ifc_req;
26697a229387SArnd Bergmann 	ifr32 = compat_ptr(ifc32.ifcbuf);
26707a229387SArnd Bergmann 	for (i = 0, j = 0;
26716b96018bSArnd Bergmann 	     i + sizeof(struct compat_ifreq) <= ifc32.ifc_len && j < ifc.ifc_len;
26726b96018bSArnd Bergmann 	     i += sizeof(struct compat_ifreq), j += sizeof(struct ifreq)) {
26736b96018bSArnd Bergmann 		if (copy_in_user(ifr32, ifr, sizeof(struct compat_ifreq)))
26747a229387SArnd Bergmann 			return -EFAULT;
26757a229387SArnd Bergmann 		ifr32++;
26767a229387SArnd Bergmann 		ifr++;
26777a229387SArnd Bergmann 	}
26787a229387SArnd Bergmann 
26797a229387SArnd Bergmann 	if (ifc32.ifcbuf == 0) {
26807a229387SArnd Bergmann 		/* Translate from 64-bit structure multiple to
26817a229387SArnd Bergmann 		 * a 32-bit one.
26827a229387SArnd Bergmann 		 */
26837a229387SArnd Bergmann 		i = ifc.ifc_len;
26846b96018bSArnd Bergmann 		i = ((i / sizeof(struct ifreq)) * sizeof(struct compat_ifreq));
26857a229387SArnd Bergmann 		ifc32.ifc_len = i;
26867a229387SArnd Bergmann 	} else {
26877a229387SArnd Bergmann 		ifc32.ifc_len = i;
26887a229387SArnd Bergmann 	}
26896b96018bSArnd Bergmann 	if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf)))
26907a229387SArnd Bergmann 		return -EFAULT;
26917a229387SArnd Bergmann 
26927a229387SArnd Bergmann 	return 0;
26937a229387SArnd Bergmann }
26947a229387SArnd Bergmann 
26956b96018bSArnd Bergmann static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
26967a229387SArnd Bergmann {
26973a7da39dSBen Hutchings 	struct compat_ethtool_rxnfc __user *compat_rxnfc;
26983a7da39dSBen Hutchings 	bool convert_in = false, convert_out = false;
26993a7da39dSBen Hutchings 	size_t buf_size = ALIGN(sizeof(struct ifreq), 8);
27003a7da39dSBen Hutchings 	struct ethtool_rxnfc __user *rxnfc;
27017a229387SArnd Bergmann 	struct ifreq __user *ifr;
27023a7da39dSBen Hutchings 	u32 rule_cnt = 0, actual_rule_cnt;
27033a7da39dSBen Hutchings 	u32 ethcmd;
27047a229387SArnd Bergmann 	u32 data;
27053a7da39dSBen Hutchings 	int ret;
27067a229387SArnd Bergmann 
27077a229387SArnd Bergmann 	if (get_user(data, &ifr32->ifr_ifru.ifru_data))
27087a229387SArnd Bergmann 		return -EFAULT;
27097a229387SArnd Bergmann 
27103a7da39dSBen Hutchings 	compat_rxnfc = compat_ptr(data);
27113a7da39dSBen Hutchings 
27123a7da39dSBen Hutchings 	if (get_user(ethcmd, &compat_rxnfc->cmd))
27137a229387SArnd Bergmann 		return -EFAULT;
27147a229387SArnd Bergmann 
27153a7da39dSBen Hutchings 	/* Most ethtool structures are defined without padding.
27163a7da39dSBen Hutchings 	 * Unfortunately struct ethtool_rxnfc is an exception.
27173a7da39dSBen Hutchings 	 */
27183a7da39dSBen Hutchings 	switch (ethcmd) {
27193a7da39dSBen Hutchings 	default:
27203a7da39dSBen Hutchings 		break;
27213a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLALL:
27223a7da39dSBen Hutchings 		/* Buffer size is variable */
27233a7da39dSBen Hutchings 		if (get_user(rule_cnt, &compat_rxnfc->rule_cnt))
27243a7da39dSBen Hutchings 			return -EFAULT;
27253a7da39dSBen Hutchings 		if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32))
27263a7da39dSBen Hutchings 			return -ENOMEM;
27273a7da39dSBen Hutchings 		buf_size += rule_cnt * sizeof(u32);
27283a7da39dSBen Hutchings 		/* fall through */
27293a7da39dSBen Hutchings 	case ETHTOOL_GRXRINGS:
27303a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLCNT:
27313a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRULE:
27323a7da39dSBen Hutchings 		convert_out = true;
27333a7da39dSBen Hutchings 		/* fall through */
27343a7da39dSBen Hutchings 	case ETHTOOL_SRXCLSRLDEL:
27353a7da39dSBen Hutchings 	case ETHTOOL_SRXCLSRLINS:
27363a7da39dSBen Hutchings 		buf_size += sizeof(struct ethtool_rxnfc);
27373a7da39dSBen Hutchings 		convert_in = true;
27383a7da39dSBen Hutchings 		break;
27393a7da39dSBen Hutchings 	}
27403a7da39dSBen Hutchings 
27413a7da39dSBen Hutchings 	ifr = compat_alloc_user_space(buf_size);
27423a7da39dSBen Hutchings 	rxnfc = (void *)ifr + ALIGN(sizeof(struct ifreq), 8);
27433a7da39dSBen Hutchings 
27443a7da39dSBen Hutchings 	if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
27453a7da39dSBen Hutchings 		return -EFAULT;
27463a7da39dSBen Hutchings 
27473a7da39dSBen Hutchings 	if (put_user(convert_in ? rxnfc : compat_ptr(data),
27483a7da39dSBen Hutchings 		     &ifr->ifr_ifru.ifru_data))
27493a7da39dSBen Hutchings 		return -EFAULT;
27503a7da39dSBen Hutchings 
27513a7da39dSBen Hutchings 	if (convert_in) {
2752127fe533SAlexander Duyck 		/* We expect there to be holes between fs.m_ext and
27533a7da39dSBen Hutchings 		 * fs.ring_cookie and at the end of fs, but nowhere else.
27543a7da39dSBen Hutchings 		 */
2755127fe533SAlexander Duyck 		BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_ext) +
2756127fe533SAlexander Duyck 			     sizeof(compat_rxnfc->fs.m_ext) !=
2757127fe533SAlexander Duyck 			     offsetof(struct ethtool_rxnfc, fs.m_ext) +
2758127fe533SAlexander Duyck 			     sizeof(rxnfc->fs.m_ext));
27593a7da39dSBen Hutchings 		BUILD_BUG_ON(
27603a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.location) -
27613a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) !=
27623a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.location) -
27633a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.ring_cookie));
27643a7da39dSBen Hutchings 
27653a7da39dSBen Hutchings 		if (copy_in_user(rxnfc, compat_rxnfc,
2766127fe533SAlexander Duyck 				 (void *)(&rxnfc->fs.m_ext + 1) -
27673a7da39dSBen Hutchings 				 (void *)rxnfc) ||
27683a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->fs.ring_cookie,
27693a7da39dSBen Hutchings 				 &compat_rxnfc->fs.ring_cookie,
27703a7da39dSBen Hutchings 				 (void *)(&rxnfc->fs.location + 1) -
27713a7da39dSBen Hutchings 				 (void *)&rxnfc->fs.ring_cookie) ||
27723a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt,
27733a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
27743a7da39dSBen Hutchings 			return -EFAULT;
27753a7da39dSBen Hutchings 	}
27763a7da39dSBen Hutchings 
27773a7da39dSBen Hutchings 	ret = dev_ioctl(net, SIOCETHTOOL, ifr);
27783a7da39dSBen Hutchings 	if (ret)
27793a7da39dSBen Hutchings 		return ret;
27803a7da39dSBen Hutchings 
27813a7da39dSBen Hutchings 	if (convert_out) {
27823a7da39dSBen Hutchings 		if (copy_in_user(compat_rxnfc, rxnfc,
2783127fe533SAlexander Duyck 				 (const void *)(&rxnfc->fs.m_ext + 1) -
27843a7da39dSBen Hutchings 				 (const void *)rxnfc) ||
27853a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->fs.ring_cookie,
27863a7da39dSBen Hutchings 				 &rxnfc->fs.ring_cookie,
27873a7da39dSBen Hutchings 				 (const void *)(&rxnfc->fs.location + 1) -
27883a7da39dSBen Hutchings 				 (const void *)&rxnfc->fs.ring_cookie) ||
27893a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt,
27903a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
27913a7da39dSBen Hutchings 			return -EFAULT;
27923a7da39dSBen Hutchings 
27933a7da39dSBen Hutchings 		if (ethcmd == ETHTOOL_GRXCLSRLALL) {
27943a7da39dSBen Hutchings 			/* As an optimisation, we only copy the actual
27953a7da39dSBen Hutchings 			 * number of rules that the underlying
27963a7da39dSBen Hutchings 			 * function returned.  Since Mallory might
27973a7da39dSBen Hutchings 			 * change the rule count in user memory, we
27983a7da39dSBen Hutchings 			 * check that it is less than the rule count
27993a7da39dSBen Hutchings 			 * originally given (as the user buffer size),
28003a7da39dSBen Hutchings 			 * which has been range-checked.
28013a7da39dSBen Hutchings 			 */
28023a7da39dSBen Hutchings 			if (get_user(actual_rule_cnt, &rxnfc->rule_cnt))
28033a7da39dSBen Hutchings 				return -EFAULT;
28043a7da39dSBen Hutchings 			if (actual_rule_cnt < rule_cnt)
28053a7da39dSBen Hutchings 				rule_cnt = actual_rule_cnt;
28063a7da39dSBen Hutchings 			if (copy_in_user(&compat_rxnfc->rule_locs[0],
28073a7da39dSBen Hutchings 					 &rxnfc->rule_locs[0],
28083a7da39dSBen Hutchings 					 rule_cnt * sizeof(u32)))
28093a7da39dSBen Hutchings 				return -EFAULT;
28103a7da39dSBen Hutchings 		}
28113a7da39dSBen Hutchings 	}
28123a7da39dSBen Hutchings 
28133a7da39dSBen Hutchings 	return 0;
28147a229387SArnd Bergmann }
28157a229387SArnd Bergmann 
28167a50a240SArnd Bergmann static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32)
28177a50a240SArnd Bergmann {
28187a50a240SArnd Bergmann 	void __user *uptr;
28197a50a240SArnd Bergmann 	compat_uptr_t uptr32;
28207a50a240SArnd Bergmann 	struct ifreq __user *uifr;
28217a50a240SArnd Bergmann 
28227a50a240SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
28237a50a240SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
28247a50a240SArnd Bergmann 		return -EFAULT;
28257a50a240SArnd Bergmann 
28267a50a240SArnd Bergmann 	if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu))
28277a50a240SArnd Bergmann 		return -EFAULT;
28287a50a240SArnd Bergmann 
28297a50a240SArnd Bergmann 	uptr = compat_ptr(uptr32);
28307a50a240SArnd Bergmann 
28317a50a240SArnd Bergmann 	if (put_user(uptr, &uifr->ifr_settings.ifs_ifsu.raw_hdlc))
28327a50a240SArnd Bergmann 		return -EFAULT;
28337a50a240SArnd Bergmann 
28347a50a240SArnd Bergmann 	return dev_ioctl(net, SIOCWANDEV, uifr);
28357a50a240SArnd Bergmann }
28367a50a240SArnd Bergmann 
28376b96018bSArnd Bergmann static int bond_ioctl(struct net *net, unsigned int cmd,
28386b96018bSArnd Bergmann 			 struct compat_ifreq __user *ifr32)
28397a229387SArnd Bergmann {
28407a229387SArnd Bergmann 	struct ifreq kifr;
28417a229387SArnd Bergmann 	struct ifreq __user *uifr;
28427a229387SArnd Bergmann 	mm_segment_t old_fs;
28437a229387SArnd Bergmann 	int err;
28447a229387SArnd Bergmann 	u32 data;
28457a229387SArnd Bergmann 	void __user *datap;
28467a229387SArnd Bergmann 
28477a229387SArnd Bergmann 	switch (cmd) {
28487a229387SArnd Bergmann 	case SIOCBONDENSLAVE:
28497a229387SArnd Bergmann 	case SIOCBONDRELEASE:
28507a229387SArnd Bergmann 	case SIOCBONDSETHWADDR:
28517a229387SArnd Bergmann 	case SIOCBONDCHANGEACTIVE:
28526b96018bSArnd Bergmann 		if (copy_from_user(&kifr, ifr32, sizeof(struct compat_ifreq)))
28537a229387SArnd Bergmann 			return -EFAULT;
28547a229387SArnd Bergmann 
28557a229387SArnd Bergmann 		old_fs = get_fs();
28567a229387SArnd Bergmann 		set_fs(KERNEL_DS);
2857c3f52ae6Sstephen hemminger 		err = dev_ioctl(net, cmd,
2858c3f52ae6Sstephen hemminger 				(struct ifreq __user __force *) &kifr);
28597a229387SArnd Bergmann 		set_fs(old_fs);
28607a229387SArnd Bergmann 
28617a229387SArnd Bergmann 		return err;
28627a229387SArnd Bergmann 	case SIOCBONDSLAVEINFOQUERY:
28637a229387SArnd Bergmann 	case SIOCBONDINFOQUERY:
28647a229387SArnd Bergmann 		uifr = compat_alloc_user_space(sizeof(*uifr));
28657a229387SArnd Bergmann 		if (copy_in_user(&uifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
28667a229387SArnd Bergmann 			return -EFAULT;
28677a229387SArnd Bergmann 
28687a229387SArnd Bergmann 		if (get_user(data, &ifr32->ifr_ifru.ifru_data))
28697a229387SArnd Bergmann 			return -EFAULT;
28707a229387SArnd Bergmann 
28717a229387SArnd Bergmann 		datap = compat_ptr(data);
28727a229387SArnd Bergmann 		if (put_user(datap, &uifr->ifr_ifru.ifru_data))
28737a229387SArnd Bergmann 			return -EFAULT;
28747a229387SArnd Bergmann 
28756b96018bSArnd Bergmann 		return dev_ioctl(net, cmd, uifr);
28767a229387SArnd Bergmann 	default:
28777a229387SArnd Bergmann 		return -EINVAL;
2878ccbd6a5aSJoe Perches 	}
28797a229387SArnd Bergmann }
28807a229387SArnd Bergmann 
28816b96018bSArnd Bergmann static int siocdevprivate_ioctl(struct net *net, unsigned int cmd,
28826b96018bSArnd Bergmann 				 struct compat_ifreq __user *u_ifreq32)
28837a229387SArnd Bergmann {
28847a229387SArnd Bergmann 	struct ifreq __user *u_ifreq64;
28857a229387SArnd Bergmann 	char tmp_buf[IFNAMSIZ];
28867a229387SArnd Bergmann 	void __user *data64;
28877a229387SArnd Bergmann 	u32 data32;
28887a229387SArnd Bergmann 
28897a229387SArnd Bergmann 	if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]),
28907a229387SArnd Bergmann 			   IFNAMSIZ))
28917a229387SArnd Bergmann 		return -EFAULT;
28927a229387SArnd Bergmann 	if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data))
28937a229387SArnd Bergmann 		return -EFAULT;
28947a229387SArnd Bergmann 	data64 = compat_ptr(data32);
28957a229387SArnd Bergmann 
28967a229387SArnd Bergmann 	u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
28977a229387SArnd Bergmann 
28987a229387SArnd Bergmann 	/* Don't check these user accesses, just let that get trapped
28997a229387SArnd Bergmann 	 * in the ioctl handler instead.
29007a229387SArnd Bergmann 	 */
29017a229387SArnd Bergmann 	if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0],
29027a229387SArnd Bergmann 			 IFNAMSIZ))
29037a229387SArnd Bergmann 		return -EFAULT;
29047a229387SArnd Bergmann 	if (__put_user(data64, &u_ifreq64->ifr_ifru.ifru_data))
29057a229387SArnd Bergmann 		return -EFAULT;
29067a229387SArnd Bergmann 
29076b96018bSArnd Bergmann 	return dev_ioctl(net, cmd, u_ifreq64);
29087a229387SArnd Bergmann }
29097a229387SArnd Bergmann 
29106b96018bSArnd Bergmann static int dev_ifsioc(struct net *net, struct socket *sock,
29116b96018bSArnd Bergmann 			 unsigned int cmd, struct compat_ifreq __user *uifr32)
29127a229387SArnd Bergmann {
2913a2116ed2SArnd Bergmann 	struct ifreq __user *uifr;
29147a229387SArnd Bergmann 	int err;
29157a229387SArnd Bergmann 
2916a2116ed2SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
2917a2116ed2SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(*uifr32)))
29187a229387SArnd Bergmann 		return -EFAULT;
2919a2116ed2SArnd Bergmann 
2920a2116ed2SArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr);
2921a2116ed2SArnd Bergmann 
29227a229387SArnd Bergmann 	if (!err) {
29237a229387SArnd Bergmann 		switch (cmd) {
29247a229387SArnd Bergmann 		case SIOCGIFFLAGS:
29257a229387SArnd Bergmann 		case SIOCGIFMETRIC:
29267a229387SArnd Bergmann 		case SIOCGIFMTU:
29277a229387SArnd Bergmann 		case SIOCGIFMEM:
29287a229387SArnd Bergmann 		case SIOCGIFHWADDR:
29297a229387SArnd Bergmann 		case SIOCGIFINDEX:
29307a229387SArnd Bergmann 		case SIOCGIFADDR:
29317a229387SArnd Bergmann 		case SIOCGIFBRDADDR:
29327a229387SArnd Bergmann 		case SIOCGIFDSTADDR:
29337a229387SArnd Bergmann 		case SIOCGIFNETMASK:
2934fab2532bSArnd Bergmann 		case SIOCGIFPFLAGS:
29357a229387SArnd Bergmann 		case SIOCGIFTXQLEN:
2936fab2532bSArnd Bergmann 		case SIOCGMIIPHY:
2937fab2532bSArnd Bergmann 		case SIOCGMIIREG:
2938a2116ed2SArnd Bergmann 			if (copy_in_user(uifr32, uifr, sizeof(*uifr32)))
2939a2116ed2SArnd Bergmann 				err = -EFAULT;
29407a229387SArnd Bergmann 			break;
2941a2116ed2SArnd Bergmann 		}
2942a2116ed2SArnd Bergmann 	}
2943a2116ed2SArnd Bergmann 	return err;
2944a2116ed2SArnd Bergmann }
2945a2116ed2SArnd Bergmann 
2946a2116ed2SArnd Bergmann static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
2947a2116ed2SArnd Bergmann 			struct compat_ifreq __user *uifr32)
2948a2116ed2SArnd Bergmann {
2949a2116ed2SArnd Bergmann 	struct ifreq ifr;
2950a2116ed2SArnd Bergmann 	struct compat_ifmap __user *uifmap32;
2951a2116ed2SArnd Bergmann 	mm_segment_t old_fs;
2952a2116ed2SArnd Bergmann 	int err;
2953a2116ed2SArnd Bergmann 
2954a2116ed2SArnd Bergmann 	uifmap32 = &uifr32->ifr_ifru.ifru_map;
2955a2116ed2SArnd Bergmann 	err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name));
2956a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
2957a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
2958a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
2959a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.irq, &uifmap32->irq);
2960a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.dma, &uifmap32->dma);
2961a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.port, &uifmap32->port);
2962a2116ed2SArnd Bergmann 	if (err)
2963a2116ed2SArnd Bergmann 		return -EFAULT;
2964a2116ed2SArnd Bergmann 
2965a2116ed2SArnd Bergmann 	old_fs = get_fs();
2966a2116ed2SArnd Bergmann 	set_fs(KERNEL_DS);
2967c3f52ae6Sstephen hemminger 	err = dev_ioctl(net, cmd, (void  __user __force *)&ifr);
2968a2116ed2SArnd Bergmann 	set_fs(old_fs);
2969a2116ed2SArnd Bergmann 
2970a2116ed2SArnd Bergmann 	if (cmd == SIOCGIFMAP && !err) {
29717a229387SArnd Bergmann 		err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name));
29727a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
29737a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
29747a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
29757a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.irq, &uifmap32->irq);
29767a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.dma, &uifmap32->dma);
29777a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.port, &uifmap32->port);
29787a229387SArnd Bergmann 		if (err)
29797a229387SArnd Bergmann 			err = -EFAULT;
29807a229387SArnd Bergmann 	}
29817a229387SArnd Bergmann 	return err;
29827a229387SArnd Bergmann }
29837a229387SArnd Bergmann 
2984a2116ed2SArnd Bergmann static int compat_siocshwtstamp(struct net *net, struct compat_ifreq __user *uifr32)
2985a2116ed2SArnd Bergmann {
2986a2116ed2SArnd Bergmann 	void __user *uptr;
2987a2116ed2SArnd Bergmann 	compat_uptr_t uptr32;
2988a2116ed2SArnd Bergmann 	struct ifreq __user *uifr;
2989a2116ed2SArnd Bergmann 
2990a2116ed2SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
2991a2116ed2SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
2992a2116ed2SArnd Bergmann 		return -EFAULT;
2993a2116ed2SArnd Bergmann 
2994a2116ed2SArnd Bergmann 	if (get_user(uptr32, &uifr32->ifr_data))
2995a2116ed2SArnd Bergmann 		return -EFAULT;
2996a2116ed2SArnd Bergmann 
2997a2116ed2SArnd Bergmann 	uptr = compat_ptr(uptr32);
2998a2116ed2SArnd Bergmann 
2999a2116ed2SArnd Bergmann 	if (put_user(uptr, &uifr->ifr_data))
3000a2116ed2SArnd Bergmann 		return -EFAULT;
3001a2116ed2SArnd Bergmann 
3002a2116ed2SArnd Bergmann 	return dev_ioctl(net, SIOCSHWTSTAMP, uifr);
3003a2116ed2SArnd Bergmann }
3004a2116ed2SArnd Bergmann 
30057a229387SArnd Bergmann struct rtentry32 {
30067a229387SArnd Bergmann 	u32		rt_pad1;
30077a229387SArnd Bergmann 	struct sockaddr rt_dst;         /* target address               */
30087a229387SArnd Bergmann 	struct sockaddr rt_gateway;     /* gateway addr (RTF_GATEWAY)   */
30097a229387SArnd Bergmann 	struct sockaddr rt_genmask;     /* target network mask (IP)     */
30107a229387SArnd Bergmann 	unsigned short	rt_flags;
30117a229387SArnd Bergmann 	short		rt_pad2;
30127a229387SArnd Bergmann 	u32		rt_pad3;
30137a229387SArnd Bergmann 	unsigned char	rt_tos;
30147a229387SArnd Bergmann 	unsigned char	rt_class;
30157a229387SArnd Bergmann 	short		rt_pad4;
30167a229387SArnd Bergmann 	short		rt_metric;      /* +1 for binary compatibility! */
30177a229387SArnd Bergmann 	/* char * */ u32 rt_dev;        /* forcing the device at add    */
30187a229387SArnd Bergmann 	u32		rt_mtu;         /* per route MTU/Window         */
30197a229387SArnd Bergmann 	u32		rt_window;      /* Window clamping              */
30207a229387SArnd Bergmann 	unsigned short  rt_irtt;        /* Initial RTT                  */
30217a229387SArnd Bergmann };
30227a229387SArnd Bergmann 
30237a229387SArnd Bergmann struct in6_rtmsg32 {
30247a229387SArnd Bergmann 	struct in6_addr		rtmsg_dst;
30257a229387SArnd Bergmann 	struct in6_addr		rtmsg_src;
30267a229387SArnd Bergmann 	struct in6_addr		rtmsg_gateway;
30277a229387SArnd Bergmann 	u32			rtmsg_type;
30287a229387SArnd Bergmann 	u16			rtmsg_dst_len;
30297a229387SArnd Bergmann 	u16			rtmsg_src_len;
30307a229387SArnd Bergmann 	u32			rtmsg_metric;
30317a229387SArnd Bergmann 	u32			rtmsg_info;
30327a229387SArnd Bergmann 	u32			rtmsg_flags;
30337a229387SArnd Bergmann 	s32			rtmsg_ifindex;
30347a229387SArnd Bergmann };
30357a229387SArnd Bergmann 
30366b96018bSArnd Bergmann static int routing_ioctl(struct net *net, struct socket *sock,
30376b96018bSArnd Bergmann 			 unsigned int cmd, void __user *argp)
30387a229387SArnd Bergmann {
30397a229387SArnd Bergmann 	int ret;
30407a229387SArnd Bergmann 	void *r = NULL;
30417a229387SArnd Bergmann 	struct in6_rtmsg r6;
30427a229387SArnd Bergmann 	struct rtentry r4;
30437a229387SArnd Bergmann 	char devname[16];
30447a229387SArnd Bergmann 	u32 rtdev;
30457a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
30467a229387SArnd Bergmann 
30476b96018bSArnd Bergmann 	if (sock && sock->sk && sock->sk->sk_family == AF_INET6) { /* ipv6 */
30486b96018bSArnd Bergmann 		struct in6_rtmsg32 __user *ur6 = argp;
30497a229387SArnd Bergmann 		ret = copy_from_user(&r6.rtmsg_dst, &(ur6->rtmsg_dst),
30507a229387SArnd Bergmann 			3 * sizeof(struct in6_addr));
30517a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_type, &(ur6->rtmsg_type));
30527a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len));
30537a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_src_len, &(ur6->rtmsg_src_len));
30547a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_metric, &(ur6->rtmsg_metric));
30557a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_info, &(ur6->rtmsg_info));
30567a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_flags, &(ur6->rtmsg_flags));
30577a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex));
30587a229387SArnd Bergmann 
30597a229387SArnd Bergmann 		r = (void *) &r6;
30607a229387SArnd Bergmann 	} else { /* ipv4 */
30616b96018bSArnd Bergmann 		struct rtentry32 __user *ur4 = argp;
30627a229387SArnd Bergmann 		ret = copy_from_user(&r4.rt_dst, &(ur4->rt_dst),
30637a229387SArnd Bergmann 					3 * sizeof(struct sockaddr));
30647a229387SArnd Bergmann 		ret |= __get_user(r4.rt_flags, &(ur4->rt_flags));
30657a229387SArnd Bergmann 		ret |= __get_user(r4.rt_metric, &(ur4->rt_metric));
30667a229387SArnd Bergmann 		ret |= __get_user(r4.rt_mtu, &(ur4->rt_mtu));
30677a229387SArnd Bergmann 		ret |= __get_user(r4.rt_window, &(ur4->rt_window));
30687a229387SArnd Bergmann 		ret |= __get_user(r4.rt_irtt, &(ur4->rt_irtt));
30697a229387SArnd Bergmann 		ret |= __get_user(rtdev, &(ur4->rt_dev));
30707a229387SArnd Bergmann 		if (rtdev) {
30717a229387SArnd Bergmann 			ret |= copy_from_user(devname, compat_ptr(rtdev), 15);
3072c3f52ae6Sstephen hemminger 			r4.rt_dev = (char __user __force *)devname;
3073c3f52ae6Sstephen hemminger 			devname[15] = 0;
30747a229387SArnd Bergmann 		} else
30757a229387SArnd Bergmann 			r4.rt_dev = NULL;
30767a229387SArnd Bergmann 
30777a229387SArnd Bergmann 		r = (void *) &r4;
30787a229387SArnd Bergmann 	}
30797a229387SArnd Bergmann 
30807a229387SArnd Bergmann 	if (ret) {
30817a229387SArnd Bergmann 		ret = -EFAULT;
30827a229387SArnd Bergmann 		goto out;
30837a229387SArnd Bergmann 	}
30847a229387SArnd Bergmann 
30857a229387SArnd Bergmann 	set_fs(KERNEL_DS);
30866b96018bSArnd Bergmann 	ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r);
30877a229387SArnd Bergmann 	set_fs(old_fs);
30887a229387SArnd Bergmann 
30897a229387SArnd Bergmann out:
30907a229387SArnd Bergmann 	return ret;
30917a229387SArnd Bergmann }
30927a229387SArnd Bergmann 
30937a229387SArnd Bergmann /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE
30947a229387SArnd Bergmann  * for some operations; this forces use of the newer bridge-utils that
309525985edcSLucas De Marchi  * use compatible ioctls
30967a229387SArnd Bergmann  */
30976b96018bSArnd Bergmann static int old_bridge_ioctl(compat_ulong_t __user *argp)
30987a229387SArnd Bergmann {
30996b96018bSArnd Bergmann 	compat_ulong_t tmp;
31007a229387SArnd Bergmann 
31016b96018bSArnd Bergmann 	if (get_user(tmp, argp))
31027a229387SArnd Bergmann 		return -EFAULT;
31037a229387SArnd Bergmann 	if (tmp == BRCTL_GET_VERSION)
31047a229387SArnd Bergmann 		return BRCTL_VERSION + 1;
31057a229387SArnd Bergmann 	return -EINVAL;
31067a229387SArnd Bergmann }
31077a229387SArnd Bergmann 
31086b96018bSArnd Bergmann static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
31096b96018bSArnd Bergmann 			 unsigned int cmd, unsigned long arg)
31106b96018bSArnd Bergmann {
31116b96018bSArnd Bergmann 	void __user *argp = compat_ptr(arg);
31126b96018bSArnd Bergmann 	struct sock *sk = sock->sk;
31136b96018bSArnd Bergmann 	struct net *net = sock_net(sk);
31147a229387SArnd Bergmann 
31156b96018bSArnd Bergmann 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
31166b96018bSArnd Bergmann 		return siocdevprivate_ioctl(net, cmd, argp);
31177a229387SArnd Bergmann 
31186b96018bSArnd Bergmann 	switch (cmd) {
31196b96018bSArnd Bergmann 	case SIOCSIFBR:
31206b96018bSArnd Bergmann 	case SIOCGIFBR:
31216b96018bSArnd Bergmann 		return old_bridge_ioctl(argp);
31226b96018bSArnd Bergmann 	case SIOCGIFNAME:
31236b96018bSArnd Bergmann 		return dev_ifname32(net, argp);
31246b96018bSArnd Bergmann 	case SIOCGIFCONF:
31256b96018bSArnd Bergmann 		return dev_ifconf(net, argp);
31266b96018bSArnd Bergmann 	case SIOCETHTOOL:
31276b96018bSArnd Bergmann 		return ethtool_ioctl(net, argp);
31287a50a240SArnd Bergmann 	case SIOCWANDEV:
31297a50a240SArnd Bergmann 		return compat_siocwandev(net, argp);
3130a2116ed2SArnd Bergmann 	case SIOCGIFMAP:
3131a2116ed2SArnd Bergmann 	case SIOCSIFMAP:
3132a2116ed2SArnd Bergmann 		return compat_sioc_ifmap(net, cmd, argp);
31336b96018bSArnd Bergmann 	case SIOCBONDENSLAVE:
31346b96018bSArnd Bergmann 	case SIOCBONDRELEASE:
31356b96018bSArnd Bergmann 	case SIOCBONDSETHWADDR:
31366b96018bSArnd Bergmann 	case SIOCBONDSLAVEINFOQUERY:
31376b96018bSArnd Bergmann 	case SIOCBONDINFOQUERY:
31386b96018bSArnd Bergmann 	case SIOCBONDCHANGEACTIVE:
31396b96018bSArnd Bergmann 		return bond_ioctl(net, cmd, argp);
31406b96018bSArnd Bergmann 	case SIOCADDRT:
31416b96018bSArnd Bergmann 	case SIOCDELRT:
31426b96018bSArnd Bergmann 		return routing_ioctl(net, sock, cmd, argp);
31436b96018bSArnd Bergmann 	case SIOCGSTAMP:
31446b96018bSArnd Bergmann 		return do_siocgstamp(net, sock, cmd, argp);
31456b96018bSArnd Bergmann 	case SIOCGSTAMPNS:
31466b96018bSArnd Bergmann 		return do_siocgstampns(net, sock, cmd, argp);
3147a2116ed2SArnd Bergmann 	case SIOCSHWTSTAMP:
3148a2116ed2SArnd Bergmann 		return compat_siocshwtstamp(net, argp);
31497a229387SArnd Bergmann 
31506b96018bSArnd Bergmann 	case FIOSETOWN:
31516b96018bSArnd Bergmann 	case SIOCSPGRP:
31526b96018bSArnd Bergmann 	case FIOGETOWN:
31536b96018bSArnd Bergmann 	case SIOCGPGRP:
31546b96018bSArnd Bergmann 	case SIOCBRADDBR:
31556b96018bSArnd Bergmann 	case SIOCBRDELBR:
31566b96018bSArnd Bergmann 	case SIOCGIFVLAN:
31576b96018bSArnd Bergmann 	case SIOCSIFVLAN:
31586b96018bSArnd Bergmann 	case SIOCADDDLCI:
31596b96018bSArnd Bergmann 	case SIOCDELDLCI:
31606b96018bSArnd Bergmann 		return sock_ioctl(file, cmd, arg);
31616b96018bSArnd Bergmann 
31626b96018bSArnd Bergmann 	case SIOCGIFFLAGS:
31636b96018bSArnd Bergmann 	case SIOCSIFFLAGS:
31646b96018bSArnd Bergmann 	case SIOCGIFMETRIC:
31656b96018bSArnd Bergmann 	case SIOCSIFMETRIC:
31666b96018bSArnd Bergmann 	case SIOCGIFMTU:
31676b96018bSArnd Bergmann 	case SIOCSIFMTU:
31686b96018bSArnd Bergmann 	case SIOCGIFMEM:
31696b96018bSArnd Bergmann 	case SIOCSIFMEM:
31706b96018bSArnd Bergmann 	case SIOCGIFHWADDR:
31716b96018bSArnd Bergmann 	case SIOCSIFHWADDR:
31726b96018bSArnd Bergmann 	case SIOCADDMULTI:
31736b96018bSArnd Bergmann 	case SIOCDELMULTI:
31746b96018bSArnd Bergmann 	case SIOCGIFINDEX:
31756b96018bSArnd Bergmann 	case SIOCGIFADDR:
31766b96018bSArnd Bergmann 	case SIOCSIFADDR:
31776b96018bSArnd Bergmann 	case SIOCSIFHWBROADCAST:
31786b96018bSArnd Bergmann 	case SIOCDIFADDR:
31796b96018bSArnd Bergmann 	case SIOCGIFBRDADDR:
31806b96018bSArnd Bergmann 	case SIOCSIFBRDADDR:
31816b96018bSArnd Bergmann 	case SIOCGIFDSTADDR:
31826b96018bSArnd Bergmann 	case SIOCSIFDSTADDR:
31836b96018bSArnd Bergmann 	case SIOCGIFNETMASK:
31846b96018bSArnd Bergmann 	case SIOCSIFNETMASK:
31856b96018bSArnd Bergmann 	case SIOCSIFPFLAGS:
31866b96018bSArnd Bergmann 	case SIOCGIFPFLAGS:
31876b96018bSArnd Bergmann 	case SIOCGIFTXQLEN:
31886b96018bSArnd Bergmann 	case SIOCSIFTXQLEN:
31896b96018bSArnd Bergmann 	case SIOCBRADDIF:
31906b96018bSArnd Bergmann 	case SIOCBRDELIF:
31919177efd3SArnd Bergmann 	case SIOCSIFNAME:
31929177efd3SArnd Bergmann 	case SIOCGMIIPHY:
31939177efd3SArnd Bergmann 	case SIOCGMIIREG:
31949177efd3SArnd Bergmann 	case SIOCSMIIREG:
31956b96018bSArnd Bergmann 		return dev_ifsioc(net, sock, cmd, argp);
31969177efd3SArnd Bergmann 
31976b96018bSArnd Bergmann 	case SIOCSARP:
31986b96018bSArnd Bergmann 	case SIOCGARP:
31996b96018bSArnd Bergmann 	case SIOCDARP:
32006b96018bSArnd Bergmann 	case SIOCATMARK:
32019177efd3SArnd Bergmann 		return sock_do_ioctl(net, sock, cmd, arg);
32029177efd3SArnd Bergmann 	}
32039177efd3SArnd Bergmann 
32049177efd3SArnd Bergmann 	/* Prevent warning from compat_sys_ioctl, these always
32059177efd3SArnd Bergmann 	 * result in -EINVAL in the native case anyway. */
32069177efd3SArnd Bergmann 	switch (cmd) {
32079177efd3SArnd Bergmann 	case SIOCRTMSG:
32089177efd3SArnd Bergmann 	case SIOCGIFCOUNT:
32096b96018bSArnd Bergmann 	case SIOCSRARP:
32106b96018bSArnd Bergmann 	case SIOCGRARP:
32116b96018bSArnd Bergmann 	case SIOCDRARP:
32129177efd3SArnd Bergmann 	case SIOCSIFLINK:
32139177efd3SArnd Bergmann 	case SIOCGIFSLAVE:
32149177efd3SArnd Bergmann 	case SIOCSIFSLAVE:
32159177efd3SArnd Bergmann 		return -EINVAL;
32166b96018bSArnd Bergmann 	}
32176b96018bSArnd Bergmann 
32186b96018bSArnd Bergmann 	return -ENOIOCTLCMD;
32196b96018bSArnd Bergmann }
32207a229387SArnd Bergmann 
322189bbfc95SShaun Pereira static long compat_sock_ioctl(struct file *file, unsigned cmd,
322289bbfc95SShaun Pereira 			      unsigned long arg)
322389bbfc95SShaun Pereira {
322489bbfc95SShaun Pereira 	struct socket *sock = file->private_data;
322589bbfc95SShaun Pereira 	int ret = -ENOIOCTLCMD;
322687de87d5SDavid S. Miller 	struct sock *sk;
322787de87d5SDavid S. Miller 	struct net *net;
322887de87d5SDavid S. Miller 
322987de87d5SDavid S. Miller 	sk = sock->sk;
323087de87d5SDavid S. Miller 	net = sock_net(sk);
323189bbfc95SShaun Pereira 
323289bbfc95SShaun Pereira 	if (sock->ops->compat_ioctl)
323389bbfc95SShaun Pereira 		ret = sock->ops->compat_ioctl(sock, cmd, arg);
323489bbfc95SShaun Pereira 
323587de87d5SDavid S. Miller 	if (ret == -ENOIOCTLCMD &&
323687de87d5SDavid S. Miller 	    (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST))
323787de87d5SDavid S. Miller 		ret = compat_wext_handle_ioctl(net, cmd, arg);
323887de87d5SDavid S. Miller 
32396b96018bSArnd Bergmann 	if (ret == -ENOIOCTLCMD)
32406b96018bSArnd Bergmann 		ret = compat_sock_ioctl_trans(file, sock, cmd, arg);
32416b96018bSArnd Bergmann 
324289bbfc95SShaun Pereira 	return ret;
324389bbfc95SShaun Pereira }
324489bbfc95SShaun Pereira #endif
324589bbfc95SShaun Pereira 
3246ac5a488eSSridhar Samudrala int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
3247ac5a488eSSridhar Samudrala {
3248ac5a488eSSridhar Samudrala 	return sock->ops->bind(sock, addr, addrlen);
3249ac5a488eSSridhar Samudrala }
3250c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_bind);
3251ac5a488eSSridhar Samudrala 
3252ac5a488eSSridhar Samudrala int kernel_listen(struct socket *sock, int backlog)
3253ac5a488eSSridhar Samudrala {
3254ac5a488eSSridhar Samudrala 	return sock->ops->listen(sock, backlog);
3255ac5a488eSSridhar Samudrala }
3256c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_listen);
3257ac5a488eSSridhar Samudrala 
3258ac5a488eSSridhar Samudrala int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
3259ac5a488eSSridhar Samudrala {
3260ac5a488eSSridhar Samudrala 	struct sock *sk = sock->sk;
3261ac5a488eSSridhar Samudrala 	int err;
3262ac5a488eSSridhar Samudrala 
3263ac5a488eSSridhar Samudrala 	err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
3264ac5a488eSSridhar Samudrala 			       newsock);
3265ac5a488eSSridhar Samudrala 	if (err < 0)
3266ac5a488eSSridhar Samudrala 		goto done;
3267ac5a488eSSridhar Samudrala 
3268ac5a488eSSridhar Samudrala 	err = sock->ops->accept(sock, *newsock, flags);
3269ac5a488eSSridhar Samudrala 	if (err < 0) {
3270ac5a488eSSridhar Samudrala 		sock_release(*newsock);
3271fa8705b0STony Battersby 		*newsock = NULL;
3272ac5a488eSSridhar Samudrala 		goto done;
3273ac5a488eSSridhar Samudrala 	}
3274ac5a488eSSridhar Samudrala 
3275ac5a488eSSridhar Samudrala 	(*newsock)->ops = sock->ops;
32761b08534eSWei Yongjun 	__module_get((*newsock)->ops->owner);
3277ac5a488eSSridhar Samudrala 
3278ac5a488eSSridhar Samudrala done:
3279ac5a488eSSridhar Samudrala 	return err;
3280ac5a488eSSridhar Samudrala }
3281c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_accept);
3282ac5a488eSSridhar Samudrala 
3283ac5a488eSSridhar Samudrala int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
3284ac5a488eSSridhar Samudrala 		   int flags)
3285ac5a488eSSridhar Samudrala {
3286ac5a488eSSridhar Samudrala 	return sock->ops->connect(sock, addr, addrlen, flags);
3287ac5a488eSSridhar Samudrala }
3288c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_connect);
3289ac5a488eSSridhar Samudrala 
3290ac5a488eSSridhar Samudrala int kernel_getsockname(struct socket *sock, struct sockaddr *addr,
3291ac5a488eSSridhar Samudrala 			 int *addrlen)
3292ac5a488eSSridhar Samudrala {
3293ac5a488eSSridhar Samudrala 	return sock->ops->getname(sock, addr, addrlen, 0);
3294ac5a488eSSridhar Samudrala }
3295c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockname);
3296ac5a488eSSridhar Samudrala 
3297ac5a488eSSridhar Samudrala int kernel_getpeername(struct socket *sock, struct sockaddr *addr,
3298ac5a488eSSridhar Samudrala 			 int *addrlen)
3299ac5a488eSSridhar Samudrala {
3300ac5a488eSSridhar Samudrala 	return sock->ops->getname(sock, addr, addrlen, 1);
3301ac5a488eSSridhar Samudrala }
3302c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getpeername);
3303ac5a488eSSridhar Samudrala 
3304ac5a488eSSridhar Samudrala int kernel_getsockopt(struct socket *sock, int level, int optname,
3305ac5a488eSSridhar Samudrala 			char *optval, int *optlen)
3306ac5a488eSSridhar Samudrala {
3307ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3308fb8621bbSNamhyung Kim 	char __user *uoptval;
3309fb8621bbSNamhyung Kim 	int __user *uoptlen;
3310ac5a488eSSridhar Samudrala 	int err;
3311ac5a488eSSridhar Samudrala 
3312fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3313fb8621bbSNamhyung Kim 	uoptlen = (int __user __force *) optlen;
3314fb8621bbSNamhyung Kim 
3315ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3316ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3317fb8621bbSNamhyung Kim 		err = sock_getsockopt(sock, level, optname, uoptval, uoptlen);
3318ac5a488eSSridhar Samudrala 	else
3319fb8621bbSNamhyung Kim 		err = sock->ops->getsockopt(sock, level, optname, uoptval,
3320fb8621bbSNamhyung Kim 					    uoptlen);
3321ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3322ac5a488eSSridhar Samudrala 	return err;
3323ac5a488eSSridhar Samudrala }
3324c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockopt);
3325ac5a488eSSridhar Samudrala 
3326ac5a488eSSridhar Samudrala int kernel_setsockopt(struct socket *sock, int level, int optname,
3327b7058842SDavid S. Miller 			char *optval, unsigned int optlen)
3328ac5a488eSSridhar Samudrala {
3329ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3330fb8621bbSNamhyung Kim 	char __user *uoptval;
3331ac5a488eSSridhar Samudrala 	int err;
3332ac5a488eSSridhar Samudrala 
3333fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3334fb8621bbSNamhyung Kim 
3335ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3336ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3337fb8621bbSNamhyung Kim 		err = sock_setsockopt(sock, level, optname, uoptval, optlen);
3338ac5a488eSSridhar Samudrala 	else
3339fb8621bbSNamhyung Kim 		err = sock->ops->setsockopt(sock, level, optname, uoptval,
3340ac5a488eSSridhar Samudrala 					    optlen);
3341ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3342ac5a488eSSridhar Samudrala 	return err;
3343ac5a488eSSridhar Samudrala }
3344c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_setsockopt);
3345ac5a488eSSridhar Samudrala 
3346ac5a488eSSridhar Samudrala int kernel_sendpage(struct socket *sock, struct page *page, int offset,
3347ac5a488eSSridhar Samudrala 		    size_t size, int flags)
3348ac5a488eSSridhar Samudrala {
3349f8451725SHerbert Xu 	sock_update_classid(sock->sk);
3350f8451725SHerbert Xu 
3351ac5a488eSSridhar Samudrala 	if (sock->ops->sendpage)
3352ac5a488eSSridhar Samudrala 		return sock->ops->sendpage(sock, page, offset, size, flags);
3353ac5a488eSSridhar Samudrala 
3354ac5a488eSSridhar Samudrala 	return sock_no_sendpage(sock, page, offset, size, flags);
3355ac5a488eSSridhar Samudrala }
3356c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendpage);
3357ac5a488eSSridhar Samudrala 
3358ac5a488eSSridhar Samudrala int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg)
3359ac5a488eSSridhar Samudrala {
3360ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3361ac5a488eSSridhar Samudrala 	int err;
3362ac5a488eSSridhar Samudrala 
3363ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3364ac5a488eSSridhar Samudrala 	err = sock->ops->ioctl(sock, cmd, arg);
3365ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3366ac5a488eSSridhar Samudrala 
3367ac5a488eSSridhar Samudrala 	return err;
3368ac5a488eSSridhar Samudrala }
3369c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sock_ioctl);
3370ac5a488eSSridhar Samudrala 
337191cf45f0STrond Myklebust int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
337291cf45f0STrond Myklebust {
337391cf45f0STrond Myklebust 	return sock->ops->shutdown(sock, how);
337491cf45f0STrond Myklebust }
337591cf45f0STrond Myklebust EXPORT_SYMBOL(kernel_sock_shutdown);
3376