xref: /openbmc/linux/net/socket.c (revision 56b31d1c)
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 
18443db362dSMaciej Żenczykowski int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *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 
21243db362dSMaciej Żenczykowski static int move_addr_to_user(struct sockaddr_storage *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 
34956b31d1cSAl Viro struct file *sock_alloc_file(struct socket *sock, int flags)
3501da177e4SLinus Torvalds {
3517cbe66b6SAl Viro 	struct qstr name = { .name = "" };
3522c48b9c4SAl Viro 	struct path path;
3537cbe66b6SAl Viro 	struct file *file;
3541da177e4SLinus Torvalds 
3554b936885SNick Piggin 	path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name);
35628407630SAl Viro 	if (unlikely(!path.dentry))
35728407630SAl Viro 		return ERR_PTR(-ENOMEM);
3582c48b9c4SAl Viro 	path.mnt = mntget(sock_mnt);
35939d8c1b6SDavid S. Miller 
3602c48b9c4SAl Viro 	d_instantiate(path.dentry, SOCK_INODE(sock));
361cc3808f8SAl Viro 	SOCK_INODE(sock)->i_fop = &socket_file_ops;
362cc3808f8SAl Viro 
3632c48b9c4SAl Viro 	file = alloc_file(&path, FMODE_READ | FMODE_WRITE,
364cc3808f8SAl Viro 		  &socket_file_ops);
365cc3808f8SAl Viro 	if (unlikely(!file)) {
366cc3808f8SAl Viro 		/* drop dentry, keep inode */
3677de9c6eeSAl Viro 		ihold(path.dentry->d_inode);
3682c48b9c4SAl Viro 		path_put(&path);
36928407630SAl Viro 		return ERR_PTR(-ENFILE);
370cc3808f8SAl Viro 	}
3711da177e4SLinus Torvalds 
3721da177e4SLinus Torvalds 	sock->file = file;
37377d27200SUlrich Drepper 	file->f_flags = O_RDWR | (flags & O_NONBLOCK);
3741da177e4SLinus Torvalds 	file->f_pos = 0;
37507dc3f07SBenjamin LaHaise 	file->private_data = sock;
37628407630SAl Viro 	return file;
3771da177e4SLinus Torvalds }
37856b31d1cSAl Viro EXPORT_SYMBOL(sock_alloc_file);
3791da177e4SLinus Torvalds 
38056b31d1cSAl Viro static int sock_map_fd(struct socket *sock, int flags)
38139d8c1b6SDavid S. Miller {
38239d8c1b6SDavid S. Miller 	struct file *newfile;
38328407630SAl Viro 	int fd = get_unused_fd_flags(flags);
38428407630SAl Viro 	if (unlikely(fd < 0))
3851da177e4SLinus Torvalds 		return fd;
38628407630SAl Viro 
38728407630SAl Viro 	newfile = sock_alloc_file(sock, flags);
38828407630SAl Viro 	if (likely(!IS_ERR(newfile))) {
38928407630SAl Viro 		fd_install(fd, newfile);
39028407630SAl Viro 		return fd;
39128407630SAl Viro 	}
39228407630SAl Viro 
39328407630SAl Viro 	put_unused_fd(fd);
39428407630SAl Viro 	return PTR_ERR(newfile);
3951da177e4SLinus Torvalds }
3961da177e4SLinus Torvalds 
397406a3c63SJohn Fastabend struct socket *sock_from_file(struct file *file, int *err)
3986cb153caSBenjamin LaHaise {
3996cb153caSBenjamin LaHaise 	if (file->f_op == &socket_file_ops)
4006cb153caSBenjamin LaHaise 		return file->private_data;	/* set in sock_map_fd */
4016cb153caSBenjamin LaHaise 
4026cb153caSBenjamin LaHaise 	*err = -ENOTSOCK;
4036cb153caSBenjamin LaHaise 	return NULL;
4046cb153caSBenjamin LaHaise }
405406a3c63SJohn Fastabend EXPORT_SYMBOL(sock_from_file);
4066cb153caSBenjamin LaHaise 
4071da177e4SLinus Torvalds /**
4081da177e4SLinus Torvalds  *	sockfd_lookup - Go from a file number to its socket slot
4091da177e4SLinus Torvalds  *	@fd: file handle
4101da177e4SLinus Torvalds  *	@err: pointer to an error code return
4111da177e4SLinus Torvalds  *
4121da177e4SLinus Torvalds  *	The file handle passed in is locked and the socket it is bound
4131da177e4SLinus Torvalds  *	too is returned. If an error occurs the err pointer is overwritten
4141da177e4SLinus Torvalds  *	with a negative errno code and NULL is returned. The function checks
4151da177e4SLinus Torvalds  *	for both invalid handles and passing a handle which is not a socket.
4161da177e4SLinus Torvalds  *
4171da177e4SLinus Torvalds  *	On a success the socket object pointer is returned.
4181da177e4SLinus Torvalds  */
4191da177e4SLinus Torvalds 
4201da177e4SLinus Torvalds struct socket *sockfd_lookup(int fd, int *err)
4211da177e4SLinus Torvalds {
4221da177e4SLinus Torvalds 	struct file *file;
4231da177e4SLinus Torvalds 	struct socket *sock;
4241da177e4SLinus Torvalds 
42589bddce5SStephen Hemminger 	file = fget(fd);
42689bddce5SStephen Hemminger 	if (!file) {
4271da177e4SLinus Torvalds 		*err = -EBADF;
4281da177e4SLinus Torvalds 		return NULL;
4291da177e4SLinus Torvalds 	}
43089bddce5SStephen Hemminger 
4316cb153caSBenjamin LaHaise 	sock = sock_from_file(file, err);
4326cb153caSBenjamin LaHaise 	if (!sock)
4331da177e4SLinus Torvalds 		fput(file);
4346cb153caSBenjamin LaHaise 	return sock;
4351da177e4SLinus Torvalds }
436c6d409cfSEric Dumazet EXPORT_SYMBOL(sockfd_lookup);
4371da177e4SLinus Torvalds 
4386cb153caSBenjamin LaHaise static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
4396cb153caSBenjamin LaHaise {
4406cb153caSBenjamin LaHaise 	struct file *file;
4416cb153caSBenjamin LaHaise 	struct socket *sock;
4426cb153caSBenjamin LaHaise 
4433672558cSHua Zhong 	*err = -EBADF;
4446cb153caSBenjamin LaHaise 	file = fget_light(fd, fput_needed);
4456cb153caSBenjamin LaHaise 	if (file) {
4466cb153caSBenjamin LaHaise 		sock = sock_from_file(file, err);
4476cb153caSBenjamin LaHaise 		if (sock)
4481da177e4SLinus Torvalds 			return sock;
4496cb153caSBenjamin LaHaise 		fput_light(file, *fput_needed);
4506cb153caSBenjamin LaHaise 	}
4516cb153caSBenjamin LaHaise 	return NULL;
4521da177e4SLinus Torvalds }
4531da177e4SLinus Torvalds 
4541da177e4SLinus Torvalds /**
4551da177e4SLinus Torvalds  *	sock_alloc	-	allocate a socket
4561da177e4SLinus Torvalds  *
4571da177e4SLinus Torvalds  *	Allocate a new inode and socket object. The two are bound together
4581da177e4SLinus Torvalds  *	and initialised. The socket is then returned. If we are out of inodes
4591da177e4SLinus Torvalds  *	NULL is returned.
4601da177e4SLinus Torvalds  */
4611da177e4SLinus Torvalds 
4621da177e4SLinus Torvalds static struct socket *sock_alloc(void)
4631da177e4SLinus Torvalds {
4641da177e4SLinus Torvalds 	struct inode *inode;
4651da177e4SLinus Torvalds 	struct socket *sock;
4661da177e4SLinus Torvalds 
467a209dfc7SEric Dumazet 	inode = new_inode_pseudo(sock_mnt->mnt_sb);
4681da177e4SLinus Torvalds 	if (!inode)
4691da177e4SLinus Torvalds 		return NULL;
4701da177e4SLinus Torvalds 
4711da177e4SLinus Torvalds 	sock = SOCKET_I(inode);
4721da177e4SLinus Torvalds 
47329a020d3SEric Dumazet 	kmemcheck_annotate_bitfield(sock, type);
47485fe4025SChristoph Hellwig 	inode->i_ino = get_next_ino();
4751da177e4SLinus Torvalds 	inode->i_mode = S_IFSOCK | S_IRWXUGO;
4768192b0c4SDavid Howells 	inode->i_uid = current_fsuid();
4778192b0c4SDavid Howells 	inode->i_gid = current_fsgid();
4781da177e4SLinus Torvalds 
47919e8d69cSAlex Shi 	this_cpu_add(sockets_in_use, 1);
4801da177e4SLinus Torvalds 	return sock;
4811da177e4SLinus Torvalds }
4821da177e4SLinus Torvalds 
4831da177e4SLinus Torvalds /*
4841da177e4SLinus Torvalds  *	In theory you can't get an open on this inode, but /proc provides
4851da177e4SLinus Torvalds  *	a back door. Remember to keep it shut otherwise you'll let the
4861da177e4SLinus Torvalds  *	creepy crawlies in.
4871da177e4SLinus Torvalds  */
4881da177e4SLinus Torvalds 
4891da177e4SLinus Torvalds static int sock_no_open(struct inode *irrelevant, struct file *dontcare)
4901da177e4SLinus Torvalds {
4911da177e4SLinus Torvalds 	return -ENXIO;
4921da177e4SLinus Torvalds }
4931da177e4SLinus Torvalds 
4944b6f5d20SArjan van de Ven const struct file_operations bad_sock_fops = {
4951da177e4SLinus Torvalds 	.owner = THIS_MODULE,
4961da177e4SLinus Torvalds 	.open = sock_no_open,
4976038f373SArnd Bergmann 	.llseek = noop_llseek,
4981da177e4SLinus Torvalds };
4991da177e4SLinus Torvalds 
5001da177e4SLinus Torvalds /**
5011da177e4SLinus Torvalds  *	sock_release	-	close a socket
5021da177e4SLinus Torvalds  *	@sock: socket to close
5031da177e4SLinus Torvalds  *
5041da177e4SLinus Torvalds  *	The socket is released from the protocol stack if it has a release
5051da177e4SLinus Torvalds  *	callback, and the inode is then released if the socket is bound to
5061da177e4SLinus Torvalds  *	an inode not a file.
5071da177e4SLinus Torvalds  */
5081da177e4SLinus Torvalds 
5091da177e4SLinus Torvalds void sock_release(struct socket *sock)
5101da177e4SLinus Torvalds {
5111da177e4SLinus Torvalds 	if (sock->ops) {
5121da177e4SLinus Torvalds 		struct module *owner = sock->ops->owner;
5131da177e4SLinus Torvalds 
5141da177e4SLinus Torvalds 		sock->ops->release(sock);
5151da177e4SLinus Torvalds 		sock->ops = NULL;
5161da177e4SLinus Torvalds 		module_put(owner);
5171da177e4SLinus Torvalds 	}
5181da177e4SLinus Torvalds 
519eaefd110SEric Dumazet 	if (rcu_dereference_protected(sock->wq, 1)->fasync_list)
5201da177e4SLinus Torvalds 		printk(KERN_ERR "sock_release: fasync list not empty!\n");
5211da177e4SLinus Torvalds 
522b09e786bSMikulas Patocka 	if (test_bit(SOCK_EXTERNALLY_ALLOCATED, &sock->flags))
523b09e786bSMikulas Patocka 		return;
524b09e786bSMikulas Patocka 
52519e8d69cSAlex Shi 	this_cpu_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;
5416e3e939fSJohannes Berg 	if (sock_flag(sk, SOCK_WIFI_STATUS))
5426e3e939fSJohannes Berg 		*tx_flags |= SKBTX_WIFI_STATUS;
54320d49473SPatrick Ohly 	return 0;
54420d49473SPatrick Ohly }
54520d49473SPatrick Ohly EXPORT_SYMBOL(sock_tx_timestamp);
54620d49473SPatrick Ohly 
547228e548eSAnton Blanchard static inline int __sock_sendmsg_nosec(struct kiocb *iocb, struct socket *sock,
5481da177e4SLinus Torvalds 				       struct msghdr *msg, size_t size)
5491da177e4SLinus Torvalds {
5501da177e4SLinus Torvalds 	struct sock_iocb *si = kiocb_to_siocb(iocb);
5511da177e4SLinus Torvalds 
552f8451725SHerbert Xu 	sock_update_classid(sock->sk);
553f8451725SHerbert Xu 
5541da177e4SLinus Torvalds 	si->sock = sock;
5551da177e4SLinus Torvalds 	si->scm = NULL;
5561da177e4SLinus Torvalds 	si->msg = msg;
5571da177e4SLinus Torvalds 	si->size = size;
5581da177e4SLinus Torvalds 
5591da177e4SLinus Torvalds 	return sock->ops->sendmsg(iocb, sock, msg, size);
5601da177e4SLinus Torvalds }
5611da177e4SLinus Torvalds 
562228e548eSAnton Blanchard static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock,
563228e548eSAnton Blanchard 				 struct msghdr *msg, size_t size)
564228e548eSAnton Blanchard {
565228e548eSAnton Blanchard 	int err = security_socket_sendmsg(sock, msg, size);
566228e548eSAnton Blanchard 
567228e548eSAnton Blanchard 	return err ?: __sock_sendmsg_nosec(iocb, sock, msg, size);
568228e548eSAnton Blanchard }
569228e548eSAnton Blanchard 
5701da177e4SLinus Torvalds int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
5711da177e4SLinus Torvalds {
5721da177e4SLinus Torvalds 	struct kiocb iocb;
5731da177e4SLinus Torvalds 	struct sock_iocb siocb;
5741da177e4SLinus Torvalds 	int ret;
5751da177e4SLinus Torvalds 
5761da177e4SLinus Torvalds 	init_sync_kiocb(&iocb, NULL);
5771da177e4SLinus Torvalds 	iocb.private = &siocb;
5781da177e4SLinus Torvalds 	ret = __sock_sendmsg(&iocb, sock, msg, size);
5791da177e4SLinus Torvalds 	if (-EIOCBQUEUED == ret)
5801da177e4SLinus Torvalds 		ret = wait_on_sync_kiocb(&iocb);
5811da177e4SLinus Torvalds 	return ret;
5821da177e4SLinus Torvalds }
583c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_sendmsg);
5841da177e4SLinus Torvalds 
585894dc24cSEric Dumazet static int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg, size_t size)
586228e548eSAnton Blanchard {
587228e548eSAnton Blanchard 	struct kiocb iocb;
588228e548eSAnton Blanchard 	struct sock_iocb siocb;
589228e548eSAnton Blanchard 	int ret;
590228e548eSAnton Blanchard 
591228e548eSAnton Blanchard 	init_sync_kiocb(&iocb, NULL);
592228e548eSAnton Blanchard 	iocb.private = &siocb;
593228e548eSAnton Blanchard 	ret = __sock_sendmsg_nosec(&iocb, sock, msg, size);
594228e548eSAnton Blanchard 	if (-EIOCBQUEUED == ret)
595228e548eSAnton Blanchard 		ret = wait_on_sync_kiocb(&iocb);
596228e548eSAnton Blanchard 	return ret;
597228e548eSAnton Blanchard }
598228e548eSAnton Blanchard 
5991da177e4SLinus Torvalds int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
6001da177e4SLinus Torvalds 		   struct kvec *vec, size_t num, size_t size)
6011da177e4SLinus Torvalds {
6021da177e4SLinus Torvalds 	mm_segment_t oldfs = get_fs();
6031da177e4SLinus Torvalds 	int result;
6041da177e4SLinus Torvalds 
6051da177e4SLinus Torvalds 	set_fs(KERNEL_DS);
6061da177e4SLinus Torvalds 	/*
6071da177e4SLinus Torvalds 	 * the following is safe, since for compiler definitions of kvec and
6081da177e4SLinus Torvalds 	 * iovec are identical, yielding the same in-core layout and alignment
6091da177e4SLinus Torvalds 	 */
61089bddce5SStephen Hemminger 	msg->msg_iov = (struct iovec *)vec;
6111da177e4SLinus Torvalds 	msg->msg_iovlen = num;
6121da177e4SLinus Torvalds 	result = sock_sendmsg(sock, msg, size);
6131da177e4SLinus Torvalds 	set_fs(oldfs);
6141da177e4SLinus Torvalds 	return result;
6151da177e4SLinus Torvalds }
616c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendmsg);
6171da177e4SLinus Torvalds 
61820d49473SPatrick Ohly static int ktime2ts(ktime_t kt, struct timespec *ts)
61920d49473SPatrick Ohly {
62020d49473SPatrick Ohly 	if (kt.tv64) {
62120d49473SPatrick Ohly 		*ts = ktime_to_timespec(kt);
62220d49473SPatrick Ohly 		return 1;
62320d49473SPatrick Ohly 	} else {
62420d49473SPatrick Ohly 		return 0;
62520d49473SPatrick Ohly 	}
62620d49473SPatrick Ohly }
62720d49473SPatrick Ohly 
62892f37fd2SEric Dumazet /*
62992f37fd2SEric Dumazet  * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
63092f37fd2SEric Dumazet  */
63192f37fd2SEric Dumazet void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
63292f37fd2SEric Dumazet 	struct sk_buff *skb)
63392f37fd2SEric Dumazet {
63420d49473SPatrick Ohly 	int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
63520d49473SPatrick Ohly 	struct timespec ts[3];
63620d49473SPatrick Ohly 	int empty = 1;
63720d49473SPatrick Ohly 	struct skb_shared_hwtstamps *shhwtstamps =
63820d49473SPatrick Ohly 		skb_hwtstamps(skb);
63992f37fd2SEric Dumazet 
64020d49473SPatrick Ohly 	/* Race occurred between timestamp enabling and packet
64120d49473SPatrick Ohly 	   receiving.  Fill in the current time for now. */
64220d49473SPatrick Ohly 	if (need_software_tstamp && skb->tstamp.tv64 == 0)
64320d49473SPatrick Ohly 		__net_timestamp(skb);
64420d49473SPatrick Ohly 
64520d49473SPatrick Ohly 	if (need_software_tstamp) {
64692f37fd2SEric Dumazet 		if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
64792f37fd2SEric Dumazet 			struct timeval tv;
64820d49473SPatrick Ohly 			skb_get_timestamp(skb, &tv);
64920d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP,
65020d49473SPatrick Ohly 				 sizeof(tv), &tv);
65192f37fd2SEric Dumazet 		} else {
652842509b8SHagen Paul Pfeifer 			skb_get_timestampns(skb, &ts[0]);
65320d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS,
654842509b8SHagen Paul Pfeifer 				 sizeof(ts[0]), &ts[0]);
65592f37fd2SEric Dumazet 		}
65692f37fd2SEric Dumazet 	}
65792f37fd2SEric Dumazet 
65820d49473SPatrick Ohly 
65920d49473SPatrick Ohly 	memset(ts, 0, sizeof(ts));
66020d49473SPatrick Ohly 	if (skb->tstamp.tv64 &&
66120d49473SPatrick Ohly 	    sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE)) {
66220d49473SPatrick Ohly 		skb_get_timestampns(skb, ts + 0);
66320d49473SPatrick Ohly 		empty = 0;
66420d49473SPatrick Ohly 	}
66520d49473SPatrick Ohly 	if (shhwtstamps) {
66620d49473SPatrick Ohly 		if (sock_flag(sk, SOCK_TIMESTAMPING_SYS_HARDWARE) &&
66720d49473SPatrick Ohly 		    ktime2ts(shhwtstamps->syststamp, ts + 1))
66820d49473SPatrick Ohly 			empty = 0;
66920d49473SPatrick Ohly 		if (sock_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE) &&
67020d49473SPatrick Ohly 		    ktime2ts(shhwtstamps->hwtstamp, ts + 2))
67120d49473SPatrick Ohly 			empty = 0;
67220d49473SPatrick Ohly 	}
67320d49473SPatrick Ohly 	if (!empty)
67420d49473SPatrick Ohly 		put_cmsg(msg, SOL_SOCKET,
67520d49473SPatrick Ohly 			 SCM_TIMESTAMPING, sizeof(ts), &ts);
67620d49473SPatrick Ohly }
6777c81fd8bSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
6787c81fd8bSArnaldo Carvalho de Melo 
6796e3e939fSJohannes Berg void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
6806e3e939fSJohannes Berg 	struct sk_buff *skb)
6816e3e939fSJohannes Berg {
6826e3e939fSJohannes Berg 	int ack;
6836e3e939fSJohannes Berg 
6846e3e939fSJohannes Berg 	if (!sock_flag(sk, SOCK_WIFI_STATUS))
6856e3e939fSJohannes Berg 		return;
6866e3e939fSJohannes Berg 	if (!skb->wifi_acked_valid)
6876e3e939fSJohannes Berg 		return;
6886e3e939fSJohannes Berg 
6896e3e939fSJohannes Berg 	ack = skb->wifi_acked;
6906e3e939fSJohannes Berg 
6916e3e939fSJohannes Berg 	put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack);
6926e3e939fSJohannes Berg }
6936e3e939fSJohannes Berg EXPORT_SYMBOL_GPL(__sock_recv_wifi_status);
6946e3e939fSJohannes Berg 
69511165f14Sstephen hemminger static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk,
69611165f14Sstephen hemminger 				   struct sk_buff *skb)
6973b885787SNeil Horman {
6983b885787SNeil Horman 	if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && skb->dropcount)
6993b885787SNeil Horman 		put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL,
7003b885787SNeil Horman 			sizeof(__u32), &skb->dropcount);
7013b885787SNeil Horman }
7023b885787SNeil Horman 
703767dd033SEric Dumazet void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
7043b885787SNeil Horman 	struct sk_buff *skb)
7053b885787SNeil Horman {
7063b885787SNeil Horman 	sock_recv_timestamp(msg, sk, skb);
7073b885787SNeil Horman 	sock_recv_drops(msg, sk, skb);
7083b885787SNeil Horman }
709767dd033SEric Dumazet EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops);
7103b885787SNeil Horman 
711a2e27255SArnaldo Carvalho de Melo static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock,
7121da177e4SLinus Torvalds 				       struct msghdr *msg, size_t size, int flags)
7131da177e4SLinus Torvalds {
7141da177e4SLinus Torvalds 	struct sock_iocb *si = kiocb_to_siocb(iocb);
7151da177e4SLinus Torvalds 
716f8451725SHerbert Xu 	sock_update_classid(sock->sk);
717f8451725SHerbert Xu 
7181da177e4SLinus Torvalds 	si->sock = sock;
7191da177e4SLinus Torvalds 	si->scm = NULL;
7201da177e4SLinus Torvalds 	si->msg = msg;
7211da177e4SLinus Torvalds 	si->size = size;
7221da177e4SLinus Torvalds 	si->flags = flags;
7231da177e4SLinus Torvalds 
7241da177e4SLinus Torvalds 	return sock->ops->recvmsg(iocb, sock, msg, size, flags);
7251da177e4SLinus Torvalds }
7261da177e4SLinus Torvalds 
727a2e27255SArnaldo Carvalho de Melo static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock,
728a2e27255SArnaldo Carvalho de Melo 				 struct msghdr *msg, size_t size, int flags)
729a2e27255SArnaldo Carvalho de Melo {
730a2e27255SArnaldo Carvalho de Melo 	int err = security_socket_recvmsg(sock, msg, size, flags);
731a2e27255SArnaldo Carvalho de Melo 
732a2e27255SArnaldo Carvalho de Melo 	return err ?: __sock_recvmsg_nosec(iocb, sock, msg, size, flags);
733a2e27255SArnaldo Carvalho de Melo }
734a2e27255SArnaldo Carvalho de Melo 
7351da177e4SLinus Torvalds int sock_recvmsg(struct socket *sock, struct msghdr *msg,
7361da177e4SLinus Torvalds 		 size_t size, int flags)
7371da177e4SLinus Torvalds {
7381da177e4SLinus Torvalds 	struct kiocb iocb;
7391da177e4SLinus Torvalds 	struct sock_iocb siocb;
7401da177e4SLinus Torvalds 	int ret;
7411da177e4SLinus Torvalds 
7421da177e4SLinus Torvalds 	init_sync_kiocb(&iocb, NULL);
7431da177e4SLinus Torvalds 	iocb.private = &siocb;
7441da177e4SLinus Torvalds 	ret = __sock_recvmsg(&iocb, sock, msg, size, flags);
7451da177e4SLinus Torvalds 	if (-EIOCBQUEUED == ret)
7461da177e4SLinus Torvalds 		ret = wait_on_sync_kiocb(&iocb);
7471da177e4SLinus Torvalds 	return ret;
7481da177e4SLinus Torvalds }
749c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_recvmsg);
7501da177e4SLinus Torvalds 
751a2e27255SArnaldo Carvalho de Melo static int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
752a2e27255SArnaldo Carvalho de Melo 			      size_t size, int flags)
753a2e27255SArnaldo Carvalho de Melo {
754a2e27255SArnaldo Carvalho de Melo 	struct kiocb iocb;
755a2e27255SArnaldo Carvalho de Melo 	struct sock_iocb siocb;
756a2e27255SArnaldo Carvalho de Melo 	int ret;
757a2e27255SArnaldo Carvalho de Melo 
758a2e27255SArnaldo Carvalho de Melo 	init_sync_kiocb(&iocb, NULL);
759a2e27255SArnaldo Carvalho de Melo 	iocb.private = &siocb;
760a2e27255SArnaldo Carvalho de Melo 	ret = __sock_recvmsg_nosec(&iocb, sock, msg, size, flags);
761a2e27255SArnaldo Carvalho de Melo 	if (-EIOCBQUEUED == ret)
762a2e27255SArnaldo Carvalho de Melo 		ret = wait_on_sync_kiocb(&iocb);
763a2e27255SArnaldo Carvalho de Melo 	return ret;
764a2e27255SArnaldo Carvalho de Melo }
765a2e27255SArnaldo Carvalho de Melo 
766c1249c0aSMartin Lucina /**
767c1249c0aSMartin Lucina  * kernel_recvmsg - Receive a message from a socket (kernel space)
768c1249c0aSMartin Lucina  * @sock:       The socket to receive the message from
769c1249c0aSMartin Lucina  * @msg:        Received message
770c1249c0aSMartin Lucina  * @vec:        Input s/g array for message data
771c1249c0aSMartin Lucina  * @num:        Size of input s/g array
772c1249c0aSMartin Lucina  * @size:       Number of bytes to read
773c1249c0aSMartin Lucina  * @flags:      Message flags (MSG_DONTWAIT, etc...)
774c1249c0aSMartin Lucina  *
775c1249c0aSMartin Lucina  * On return the msg structure contains the scatter/gather array passed in the
776c1249c0aSMartin Lucina  * vec argument. The array is modified so that it consists of the unfilled
777c1249c0aSMartin Lucina  * portion of the original array.
778c1249c0aSMartin Lucina  *
779c1249c0aSMartin Lucina  * The returned value is the total number of bytes received, or an error.
780c1249c0aSMartin Lucina  */
7811da177e4SLinus Torvalds int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
78289bddce5SStephen Hemminger 		   struct kvec *vec, size_t num, size_t size, int flags)
7831da177e4SLinus Torvalds {
7841da177e4SLinus Torvalds 	mm_segment_t oldfs = get_fs();
7851da177e4SLinus Torvalds 	int result;
7861da177e4SLinus Torvalds 
7871da177e4SLinus Torvalds 	set_fs(KERNEL_DS);
7881da177e4SLinus Torvalds 	/*
7891da177e4SLinus Torvalds 	 * the following is safe, since for compiler definitions of kvec and
7901da177e4SLinus Torvalds 	 * iovec are identical, yielding the same in-core layout and alignment
7911da177e4SLinus Torvalds 	 */
79289bddce5SStephen Hemminger 	msg->msg_iov = (struct iovec *)vec, msg->msg_iovlen = num;
7931da177e4SLinus Torvalds 	result = sock_recvmsg(sock, msg, size, flags);
7941da177e4SLinus Torvalds 	set_fs(oldfs);
7951da177e4SLinus Torvalds 	return result;
7961da177e4SLinus Torvalds }
797c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_recvmsg);
7981da177e4SLinus Torvalds 
7991da177e4SLinus Torvalds static void sock_aio_dtor(struct kiocb *iocb)
8001da177e4SLinus Torvalds {
8011da177e4SLinus Torvalds 	kfree(iocb->private);
8021da177e4SLinus Torvalds }
8031da177e4SLinus Torvalds 
80420380731SArnaldo Carvalho de Melo static ssize_t sock_sendpage(struct file *file, struct page *page,
8051da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more)
8061da177e4SLinus Torvalds {
8071da177e4SLinus Torvalds 	struct socket *sock;
8081da177e4SLinus Torvalds 	int flags;
8091da177e4SLinus Torvalds 
810b69aee04SEric Dumazet 	sock = file->private_data;
8111da177e4SLinus Torvalds 
81235f9c09fSEric Dumazet 	flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
81335f9c09fSEric Dumazet 	/* more is a combination of MSG_MORE and MSG_SENDPAGE_NOTLAST */
81435f9c09fSEric Dumazet 	flags |= more;
8151da177e4SLinus Torvalds 
816e6949583SLinus Torvalds 	return kernel_sendpage(sock, page, offset, size, flags);
8171da177e4SLinus Torvalds }
8181da177e4SLinus Torvalds 
8199c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
8209c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
8219c55e01cSJens Axboe 				unsigned int flags)
8229c55e01cSJens Axboe {
8239c55e01cSJens Axboe 	struct socket *sock = file->private_data;
8249c55e01cSJens Axboe 
825997b37daSRémi Denis-Courmont 	if (unlikely(!sock->ops->splice_read))
826997b37daSRémi Denis-Courmont 		return -EINVAL;
827997b37daSRémi Denis-Courmont 
828f8451725SHerbert Xu 	sock_update_classid(sock->sk);
829f8451725SHerbert Xu 
8309c55e01cSJens Axboe 	return sock->ops->splice_read(sock, ppos, pipe, len, flags);
8319c55e01cSJens Axboe }
8329c55e01cSJens Axboe 
833ce1d4d3eSChristoph Hellwig static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
83489bddce5SStephen Hemminger 					 struct sock_iocb *siocb)
835ce1d4d3eSChristoph Hellwig {
836ce1d4d3eSChristoph Hellwig 	if (!is_sync_kiocb(iocb)) {
837ce1d4d3eSChristoph Hellwig 		siocb = kmalloc(sizeof(*siocb), GFP_KERNEL);
838ce1d4d3eSChristoph Hellwig 		if (!siocb)
839ce1d4d3eSChristoph Hellwig 			return NULL;
840ce1d4d3eSChristoph Hellwig 		iocb->ki_dtor = sock_aio_dtor;
841ce1d4d3eSChristoph Hellwig 	}
842ce1d4d3eSChristoph Hellwig 
843ce1d4d3eSChristoph Hellwig 	siocb->kiocb = iocb;
844ce1d4d3eSChristoph Hellwig 	iocb->private = siocb;
845ce1d4d3eSChristoph Hellwig 	return siocb;
846ce1d4d3eSChristoph Hellwig }
847ce1d4d3eSChristoph Hellwig 
848ce1d4d3eSChristoph Hellwig static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb,
849027445c3SBadari Pulavarty 		struct file *file, const struct iovec *iov,
85089bddce5SStephen Hemminger 		unsigned long nr_segs)
851ce1d4d3eSChristoph Hellwig {
852ce1d4d3eSChristoph Hellwig 	struct socket *sock = file->private_data;
853ce1d4d3eSChristoph Hellwig 	size_t size = 0;
854ce1d4d3eSChristoph Hellwig 	int i;
855ce1d4d3eSChristoph Hellwig 
856ce1d4d3eSChristoph Hellwig 	for (i = 0; i < nr_segs; i++)
857ce1d4d3eSChristoph Hellwig 		size += iov[i].iov_len;
858ce1d4d3eSChristoph Hellwig 
859ce1d4d3eSChristoph Hellwig 	msg->msg_name = NULL;
860ce1d4d3eSChristoph Hellwig 	msg->msg_namelen = 0;
861ce1d4d3eSChristoph Hellwig 	msg->msg_control = NULL;
862ce1d4d3eSChristoph Hellwig 	msg->msg_controllen = 0;
863ce1d4d3eSChristoph Hellwig 	msg->msg_iov = (struct iovec *)iov;
864ce1d4d3eSChristoph Hellwig 	msg->msg_iovlen = nr_segs;
865ce1d4d3eSChristoph Hellwig 	msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
866ce1d4d3eSChristoph Hellwig 
867ce1d4d3eSChristoph Hellwig 	return __sock_recvmsg(iocb, sock, msg, size, msg->msg_flags);
868ce1d4d3eSChristoph Hellwig }
869ce1d4d3eSChristoph Hellwig 
870027445c3SBadari Pulavarty static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
871027445c3SBadari Pulavarty 				unsigned long nr_segs, loff_t pos)
872ce1d4d3eSChristoph Hellwig {
873ce1d4d3eSChristoph Hellwig 	struct sock_iocb siocb, *x;
874ce1d4d3eSChristoph Hellwig 
875ce1d4d3eSChristoph Hellwig 	if (pos != 0)
876ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
877027445c3SBadari Pulavarty 
878027445c3SBadari Pulavarty 	if (iocb->ki_left == 0)	/* Match SYS5 behaviour */
879ce1d4d3eSChristoph Hellwig 		return 0;
880ce1d4d3eSChristoph Hellwig 
881027445c3SBadari Pulavarty 
882027445c3SBadari Pulavarty 	x = alloc_sock_iocb(iocb, &siocb);
883ce1d4d3eSChristoph Hellwig 	if (!x)
884ce1d4d3eSChristoph Hellwig 		return -ENOMEM;
885027445c3SBadari Pulavarty 	return do_sock_read(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
886ce1d4d3eSChristoph Hellwig }
887ce1d4d3eSChristoph Hellwig 
888ce1d4d3eSChristoph Hellwig static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb,
889027445c3SBadari Pulavarty 			struct file *file, const struct iovec *iov,
89089bddce5SStephen Hemminger 			unsigned long nr_segs)
891ce1d4d3eSChristoph Hellwig {
892ce1d4d3eSChristoph Hellwig 	struct socket *sock = file->private_data;
893ce1d4d3eSChristoph Hellwig 	size_t size = 0;
894ce1d4d3eSChristoph Hellwig 	int i;
895ce1d4d3eSChristoph Hellwig 
896ce1d4d3eSChristoph Hellwig 	for (i = 0; i < nr_segs; i++)
897ce1d4d3eSChristoph Hellwig 		size += iov[i].iov_len;
898ce1d4d3eSChristoph Hellwig 
899ce1d4d3eSChristoph Hellwig 	msg->msg_name = NULL;
900ce1d4d3eSChristoph Hellwig 	msg->msg_namelen = 0;
901ce1d4d3eSChristoph Hellwig 	msg->msg_control = NULL;
902ce1d4d3eSChristoph Hellwig 	msg->msg_controllen = 0;
903ce1d4d3eSChristoph Hellwig 	msg->msg_iov = (struct iovec *)iov;
904ce1d4d3eSChristoph Hellwig 	msg->msg_iovlen = nr_segs;
905ce1d4d3eSChristoph Hellwig 	msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
906ce1d4d3eSChristoph Hellwig 	if (sock->type == SOCK_SEQPACKET)
907ce1d4d3eSChristoph Hellwig 		msg->msg_flags |= MSG_EOR;
908ce1d4d3eSChristoph Hellwig 
909ce1d4d3eSChristoph Hellwig 	return __sock_sendmsg(iocb, sock, msg, size);
910ce1d4d3eSChristoph Hellwig }
911ce1d4d3eSChristoph Hellwig 
912027445c3SBadari Pulavarty static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
913027445c3SBadari Pulavarty 			  unsigned long nr_segs, loff_t pos)
9141da177e4SLinus Torvalds {
915ce1d4d3eSChristoph Hellwig 	struct sock_iocb siocb, *x;
9161da177e4SLinus Torvalds 
917ce1d4d3eSChristoph Hellwig 	if (pos != 0)
918ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
919027445c3SBadari Pulavarty 
920027445c3SBadari Pulavarty 	x = alloc_sock_iocb(iocb, &siocb);
921ce1d4d3eSChristoph Hellwig 	if (!x)
922ce1d4d3eSChristoph Hellwig 		return -ENOMEM;
923ce1d4d3eSChristoph Hellwig 
924027445c3SBadari Pulavarty 	return do_sock_write(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
9251da177e4SLinus Torvalds }
9261da177e4SLinus Torvalds 
9271da177e4SLinus Torvalds /*
9281da177e4SLinus Torvalds  * Atomic setting of ioctl hooks to avoid race
9291da177e4SLinus Torvalds  * with module unload.
9301da177e4SLinus Torvalds  */
9311da177e4SLinus Torvalds 
9324a3e2f71SArjan van de Ven static DEFINE_MUTEX(br_ioctl_mutex);
933c6d409cfSEric Dumazet static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg);
9341da177e4SLinus Torvalds 
935881d966bSEric W. Biederman void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *))
9361da177e4SLinus Torvalds {
9374a3e2f71SArjan van de Ven 	mutex_lock(&br_ioctl_mutex);
9381da177e4SLinus Torvalds 	br_ioctl_hook = hook;
9394a3e2f71SArjan van de Ven 	mutex_unlock(&br_ioctl_mutex);
9401da177e4SLinus Torvalds }
9411da177e4SLinus Torvalds EXPORT_SYMBOL(brioctl_set);
9421da177e4SLinus Torvalds 
9434a3e2f71SArjan van de Ven static DEFINE_MUTEX(vlan_ioctl_mutex);
944881d966bSEric W. Biederman static int (*vlan_ioctl_hook) (struct net *, void __user *arg);
9451da177e4SLinus Torvalds 
946881d966bSEric W. Biederman void vlan_ioctl_set(int (*hook) (struct net *, void __user *))
9471da177e4SLinus Torvalds {
9484a3e2f71SArjan van de Ven 	mutex_lock(&vlan_ioctl_mutex);
9491da177e4SLinus Torvalds 	vlan_ioctl_hook = hook;
9504a3e2f71SArjan van de Ven 	mutex_unlock(&vlan_ioctl_mutex);
9511da177e4SLinus Torvalds }
9521da177e4SLinus Torvalds EXPORT_SYMBOL(vlan_ioctl_set);
9531da177e4SLinus Torvalds 
9544a3e2f71SArjan van de Ven static DEFINE_MUTEX(dlci_ioctl_mutex);
9551da177e4SLinus Torvalds static int (*dlci_ioctl_hook) (unsigned int, void __user *);
9561da177e4SLinus Torvalds 
9571da177e4SLinus Torvalds void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
9581da177e4SLinus Torvalds {
9594a3e2f71SArjan van de Ven 	mutex_lock(&dlci_ioctl_mutex);
9601da177e4SLinus Torvalds 	dlci_ioctl_hook = hook;
9614a3e2f71SArjan van de Ven 	mutex_unlock(&dlci_ioctl_mutex);
9621da177e4SLinus Torvalds }
9631da177e4SLinus Torvalds EXPORT_SYMBOL(dlci_ioctl_set);
9641da177e4SLinus Torvalds 
9656b96018bSArnd Bergmann static long sock_do_ioctl(struct net *net, struct socket *sock,
9666b96018bSArnd Bergmann 				 unsigned int cmd, unsigned long arg)
9676b96018bSArnd Bergmann {
9686b96018bSArnd Bergmann 	int err;
9696b96018bSArnd Bergmann 	void __user *argp = (void __user *)arg;
9706b96018bSArnd Bergmann 
9716b96018bSArnd Bergmann 	err = sock->ops->ioctl(sock, cmd, arg);
9726b96018bSArnd Bergmann 
9736b96018bSArnd Bergmann 	/*
9746b96018bSArnd Bergmann 	 * If this ioctl is unknown try to hand it down
9756b96018bSArnd Bergmann 	 * to the NIC driver.
9766b96018bSArnd Bergmann 	 */
9776b96018bSArnd Bergmann 	if (err == -ENOIOCTLCMD)
9786b96018bSArnd Bergmann 		err = dev_ioctl(net, cmd, argp);
9796b96018bSArnd Bergmann 
9806b96018bSArnd Bergmann 	return err;
9816b96018bSArnd Bergmann }
9826b96018bSArnd Bergmann 
9831da177e4SLinus Torvalds /*
9841da177e4SLinus Torvalds  *	With an ioctl, arg may well be a user mode pointer, but we don't know
9851da177e4SLinus Torvalds  *	what to do with it - that's up to the protocol still.
9861da177e4SLinus Torvalds  */
9871da177e4SLinus Torvalds 
9881da177e4SLinus Torvalds static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
9891da177e4SLinus Torvalds {
9901da177e4SLinus Torvalds 	struct socket *sock;
991881d966bSEric W. Biederman 	struct sock *sk;
9921da177e4SLinus Torvalds 	void __user *argp = (void __user *)arg;
9931da177e4SLinus Torvalds 	int pid, err;
994881d966bSEric W. Biederman 	struct net *net;
9951da177e4SLinus Torvalds 
996b69aee04SEric Dumazet 	sock = file->private_data;
997881d966bSEric W. Biederman 	sk = sock->sk;
9983b1e0a65SYOSHIFUJI Hideaki 	net = sock_net(sk);
9991da177e4SLinus Torvalds 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
1000881d966bSEric W. Biederman 		err = dev_ioctl(net, cmd, argp);
10011da177e4SLinus Torvalds 	} else
10023d23e349SJohannes Berg #ifdef CONFIG_WEXT_CORE
10031da177e4SLinus Torvalds 	if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
1004881d966bSEric W. Biederman 		err = dev_ioctl(net, cmd, argp);
10051da177e4SLinus Torvalds 	} else
10063d23e349SJohannes Berg #endif
10071da177e4SLinus Torvalds 		switch (cmd) {
10081da177e4SLinus Torvalds 		case FIOSETOWN:
10091da177e4SLinus Torvalds 		case SIOCSPGRP:
10101da177e4SLinus Torvalds 			err = -EFAULT;
10111da177e4SLinus Torvalds 			if (get_user(pid, (int __user *)argp))
10121da177e4SLinus Torvalds 				break;
10131da177e4SLinus Torvalds 			err = f_setown(sock->file, pid, 1);
10141da177e4SLinus Torvalds 			break;
10151da177e4SLinus Torvalds 		case FIOGETOWN:
10161da177e4SLinus Torvalds 		case SIOCGPGRP:
1017609d7fa9SEric W. Biederman 			err = put_user(f_getown(sock->file),
101889bddce5SStephen Hemminger 				       (int __user *)argp);
10191da177e4SLinus Torvalds 			break;
10201da177e4SLinus Torvalds 		case SIOCGIFBR:
10211da177e4SLinus Torvalds 		case SIOCSIFBR:
10221da177e4SLinus Torvalds 		case SIOCBRADDBR:
10231da177e4SLinus Torvalds 		case SIOCBRDELBR:
10241da177e4SLinus Torvalds 			err = -ENOPKG;
10251da177e4SLinus Torvalds 			if (!br_ioctl_hook)
10261da177e4SLinus Torvalds 				request_module("bridge");
10271da177e4SLinus Torvalds 
10284a3e2f71SArjan van de Ven 			mutex_lock(&br_ioctl_mutex);
10291da177e4SLinus Torvalds 			if (br_ioctl_hook)
1030881d966bSEric W. Biederman 				err = br_ioctl_hook(net, cmd, argp);
10314a3e2f71SArjan van de Ven 			mutex_unlock(&br_ioctl_mutex);
10321da177e4SLinus Torvalds 			break;
10331da177e4SLinus Torvalds 		case SIOCGIFVLAN:
10341da177e4SLinus Torvalds 		case SIOCSIFVLAN:
10351da177e4SLinus Torvalds 			err = -ENOPKG;
10361da177e4SLinus Torvalds 			if (!vlan_ioctl_hook)
10371da177e4SLinus Torvalds 				request_module("8021q");
10381da177e4SLinus Torvalds 
10394a3e2f71SArjan van de Ven 			mutex_lock(&vlan_ioctl_mutex);
10401da177e4SLinus Torvalds 			if (vlan_ioctl_hook)
1041881d966bSEric W. Biederman 				err = vlan_ioctl_hook(net, argp);
10424a3e2f71SArjan van de Ven 			mutex_unlock(&vlan_ioctl_mutex);
10431da177e4SLinus Torvalds 			break;
10441da177e4SLinus Torvalds 		case SIOCADDDLCI:
10451da177e4SLinus Torvalds 		case SIOCDELDLCI:
10461da177e4SLinus Torvalds 			err = -ENOPKG;
10471da177e4SLinus Torvalds 			if (!dlci_ioctl_hook)
10481da177e4SLinus Torvalds 				request_module("dlci");
10491da177e4SLinus Torvalds 
10504a3e2f71SArjan van de Ven 			mutex_lock(&dlci_ioctl_mutex);
10517512cbf6SPavel Emelyanov 			if (dlci_ioctl_hook)
10521da177e4SLinus Torvalds 				err = dlci_ioctl_hook(cmd, argp);
10534a3e2f71SArjan van de Ven 			mutex_unlock(&dlci_ioctl_mutex);
10541da177e4SLinus Torvalds 			break;
10551da177e4SLinus Torvalds 		default:
10566b96018bSArnd Bergmann 			err = sock_do_ioctl(net, sock, cmd, arg);
10571da177e4SLinus Torvalds 			break;
10581da177e4SLinus Torvalds 		}
10591da177e4SLinus Torvalds 	return err;
10601da177e4SLinus Torvalds }
10611da177e4SLinus Torvalds 
10621da177e4SLinus Torvalds int sock_create_lite(int family, int type, int protocol, struct socket **res)
10631da177e4SLinus Torvalds {
10641da177e4SLinus Torvalds 	int err;
10651da177e4SLinus Torvalds 	struct socket *sock = NULL;
10661da177e4SLinus Torvalds 
10671da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, 1);
10681da177e4SLinus Torvalds 	if (err)
10691da177e4SLinus Torvalds 		goto out;
10701da177e4SLinus Torvalds 
10711da177e4SLinus Torvalds 	sock = sock_alloc();
10721da177e4SLinus Torvalds 	if (!sock) {
10731da177e4SLinus Torvalds 		err = -ENOMEM;
10741da177e4SLinus Torvalds 		goto out;
10751da177e4SLinus Torvalds 	}
10761da177e4SLinus Torvalds 
10771da177e4SLinus Torvalds 	sock->type = type;
10787420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, 1);
10797420ed23SVenkat Yekkirala 	if (err)
10807420ed23SVenkat Yekkirala 		goto out_release;
10817420ed23SVenkat Yekkirala 
10821da177e4SLinus Torvalds out:
10831da177e4SLinus Torvalds 	*res = sock;
10841da177e4SLinus Torvalds 	return err;
10857420ed23SVenkat Yekkirala out_release:
10867420ed23SVenkat Yekkirala 	sock_release(sock);
10877420ed23SVenkat Yekkirala 	sock = NULL;
10887420ed23SVenkat Yekkirala 	goto out;
10891da177e4SLinus Torvalds }
1090c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_lite);
10911da177e4SLinus Torvalds 
10921da177e4SLinus Torvalds /* No kernel lock held - perfect */
10931da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file, poll_table *wait)
10941da177e4SLinus Torvalds {
10951da177e4SLinus Torvalds 	struct socket *sock;
10961da177e4SLinus Torvalds 
10971da177e4SLinus Torvalds 	/*
10981da177e4SLinus Torvalds 	 *      We can't return errors to poll, so it's either yes or no.
10991da177e4SLinus Torvalds 	 */
1100b69aee04SEric Dumazet 	sock = file->private_data;
11011da177e4SLinus Torvalds 	return sock->ops->poll(file, sock, wait);
11021da177e4SLinus Torvalds }
11031da177e4SLinus Torvalds 
11041da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma)
11051da177e4SLinus Torvalds {
1106b69aee04SEric Dumazet 	struct socket *sock = file->private_data;
11071da177e4SLinus Torvalds 
11081da177e4SLinus Torvalds 	return sock->ops->mmap(file, sock, vma);
11091da177e4SLinus Torvalds }
11101da177e4SLinus Torvalds 
111120380731SArnaldo Carvalho de Melo static int sock_close(struct inode *inode, struct file *filp)
11121da177e4SLinus Torvalds {
11131da177e4SLinus Torvalds 	/*
11141da177e4SLinus Torvalds 	 *      It was possible the inode is NULL we were
11151da177e4SLinus Torvalds 	 *      closing an unfinished socket.
11161da177e4SLinus Torvalds 	 */
11171da177e4SLinus Torvalds 
111889bddce5SStephen Hemminger 	if (!inode) {
11191da177e4SLinus Torvalds 		printk(KERN_DEBUG "sock_close: NULL inode\n");
11201da177e4SLinus Torvalds 		return 0;
11211da177e4SLinus Torvalds 	}
11221da177e4SLinus Torvalds 	sock_release(SOCKET_I(inode));
11231da177e4SLinus Torvalds 	return 0;
11241da177e4SLinus Torvalds }
11251da177e4SLinus Torvalds 
11261da177e4SLinus Torvalds /*
11271da177e4SLinus Torvalds  *	Update the socket async list
11281da177e4SLinus Torvalds  *
11291da177e4SLinus Torvalds  *	Fasync_list locking strategy.
11301da177e4SLinus Torvalds  *
11311da177e4SLinus Torvalds  *	1. fasync_list is modified only under process context socket lock
11321da177e4SLinus Torvalds  *	   i.e. under semaphore.
11331da177e4SLinus Torvalds  *	2. fasync_list is used under read_lock(&sk->sk_callback_lock)
1134989a2979SEric Dumazet  *	   or under socket lock
11351da177e4SLinus Torvalds  */
11361da177e4SLinus Torvalds 
11371da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on)
11381da177e4SLinus Torvalds {
1139989a2979SEric Dumazet 	struct socket *sock = filp->private_data;
1140989a2979SEric Dumazet 	struct sock *sk = sock->sk;
1141eaefd110SEric Dumazet 	struct socket_wq *wq;
11421da177e4SLinus Torvalds 
1143989a2979SEric Dumazet 	if (sk == NULL)
11441da177e4SLinus Torvalds 		return -EINVAL;
11451da177e4SLinus Torvalds 
11461da177e4SLinus Torvalds 	lock_sock(sk);
1147eaefd110SEric Dumazet 	wq = rcu_dereference_protected(sock->wq, sock_owned_by_user(sk));
1148eaefd110SEric Dumazet 	fasync_helper(fd, filp, on, &wq->fasync_list);
11491da177e4SLinus Torvalds 
1150eaefd110SEric Dumazet 	if (!wq->fasync_list)
1151bcdce719SEric Dumazet 		sock_reset_flag(sk, SOCK_FASYNC);
1152989a2979SEric Dumazet 	else
1153989a2979SEric Dumazet 		sock_set_flag(sk, SOCK_FASYNC);
11541da177e4SLinus Torvalds 
1155989a2979SEric Dumazet 	release_sock(sk);
11561da177e4SLinus Torvalds 	return 0;
11571da177e4SLinus Torvalds }
11581da177e4SLinus Torvalds 
115943815482SEric Dumazet /* This function may be called only under socket lock or callback_lock or rcu_lock */
11601da177e4SLinus Torvalds 
11611da177e4SLinus Torvalds int sock_wake_async(struct socket *sock, int how, int band)
11621da177e4SLinus Torvalds {
116343815482SEric Dumazet 	struct socket_wq *wq;
116443815482SEric Dumazet 
116543815482SEric Dumazet 	if (!sock)
11661da177e4SLinus Torvalds 		return -1;
116743815482SEric Dumazet 	rcu_read_lock();
116843815482SEric Dumazet 	wq = rcu_dereference(sock->wq);
116943815482SEric Dumazet 	if (!wq || !wq->fasync_list) {
117043815482SEric Dumazet 		rcu_read_unlock();
117143815482SEric Dumazet 		return -1;
117243815482SEric Dumazet 	}
117389bddce5SStephen Hemminger 	switch (how) {
11748d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_WAITD:
11751da177e4SLinus Torvalds 		if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
11761da177e4SLinus Torvalds 			break;
11771da177e4SLinus Torvalds 		goto call_kill;
11788d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_SPACE:
11791da177e4SLinus Torvalds 		if (!test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags))
11801da177e4SLinus Torvalds 			break;
11811da177e4SLinus Torvalds 		/* fall through */
11828d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_IO:
11831da177e4SLinus Torvalds call_kill:
118443815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGIO, band);
11851da177e4SLinus Torvalds 		break;
11868d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_URG:
118743815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGURG, band);
11881da177e4SLinus Torvalds 	}
118943815482SEric Dumazet 	rcu_read_unlock();
11901da177e4SLinus Torvalds 	return 0;
11911da177e4SLinus Torvalds }
1192c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_wake_async);
11931da177e4SLinus Torvalds 
1194721db93aSPavel Emelyanov int __sock_create(struct net *net, int family, int type, int protocol,
119589bddce5SStephen Hemminger 			 struct socket **res, int kern)
11961da177e4SLinus Torvalds {
11971da177e4SLinus Torvalds 	int err;
11981da177e4SLinus Torvalds 	struct socket *sock;
119955737fdaSStephen Hemminger 	const struct net_proto_family *pf;
12001da177e4SLinus Torvalds 
12011da177e4SLinus Torvalds 	/*
12021da177e4SLinus Torvalds 	 *      Check protocol is in range
12031da177e4SLinus Torvalds 	 */
12041da177e4SLinus Torvalds 	if (family < 0 || family >= NPROTO)
12051da177e4SLinus Torvalds 		return -EAFNOSUPPORT;
12061da177e4SLinus Torvalds 	if (type < 0 || type >= SOCK_MAX)
12071da177e4SLinus Torvalds 		return -EINVAL;
12081da177e4SLinus Torvalds 
12091da177e4SLinus Torvalds 	/* Compatibility.
12101da177e4SLinus Torvalds 
12111da177e4SLinus Torvalds 	   This uglymoron is moved from INET layer to here to avoid
12121da177e4SLinus Torvalds 	   deadlock in module load.
12131da177e4SLinus Torvalds 	 */
12141da177e4SLinus Torvalds 	if (family == PF_INET && type == SOCK_PACKET) {
12151da177e4SLinus Torvalds 		static int warned;
12161da177e4SLinus Torvalds 		if (!warned) {
12171da177e4SLinus Torvalds 			warned = 1;
121889bddce5SStephen Hemminger 			printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)\n",
121989bddce5SStephen Hemminger 			       current->comm);
12201da177e4SLinus Torvalds 		}
12211da177e4SLinus Torvalds 		family = PF_PACKET;
12221da177e4SLinus Torvalds 	}
12231da177e4SLinus Torvalds 
12241da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, kern);
12251da177e4SLinus Torvalds 	if (err)
12261da177e4SLinus Torvalds 		return err;
12271da177e4SLinus Torvalds 
122855737fdaSStephen Hemminger 	/*
122955737fdaSStephen Hemminger 	 *	Allocate the socket and allow the family to set things up. if
123055737fdaSStephen Hemminger 	 *	the protocol is 0, the family is instructed to select an appropriate
123155737fdaSStephen Hemminger 	 *	default.
123255737fdaSStephen Hemminger 	 */
123355737fdaSStephen Hemminger 	sock = sock_alloc();
123455737fdaSStephen Hemminger 	if (!sock) {
1235e87cc472SJoe Perches 		net_warn_ratelimited("socket: no more sockets\n");
123655737fdaSStephen Hemminger 		return -ENFILE;	/* Not exactly a match, but its the
123755737fdaSStephen Hemminger 				   closest posix thing */
123855737fdaSStephen Hemminger 	}
123955737fdaSStephen Hemminger 
124055737fdaSStephen Hemminger 	sock->type = type;
124155737fdaSStephen Hemminger 
124295a5afcaSJohannes Berg #ifdef CONFIG_MODULES
12431da177e4SLinus Torvalds 	/* Attempt to load a protocol module if the find failed.
12441da177e4SLinus Torvalds 	 *
12451da177e4SLinus Torvalds 	 * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
12461da177e4SLinus Torvalds 	 * requested real, full-featured networking support upon configuration.
12471da177e4SLinus Torvalds 	 * Otherwise module support will break!
12481da177e4SLinus Torvalds 	 */
1249190683a9SEric Dumazet 	if (rcu_access_pointer(net_families[family]) == NULL)
12501da177e4SLinus Torvalds 		request_module("net-pf-%d", family);
12511da177e4SLinus Torvalds #endif
12521da177e4SLinus Torvalds 
125355737fdaSStephen Hemminger 	rcu_read_lock();
125455737fdaSStephen Hemminger 	pf = rcu_dereference(net_families[family]);
12551da177e4SLinus Torvalds 	err = -EAFNOSUPPORT;
125655737fdaSStephen Hemminger 	if (!pf)
125755737fdaSStephen Hemminger 		goto out_release;
12581da177e4SLinus Torvalds 
12591da177e4SLinus Torvalds 	/*
12601da177e4SLinus Torvalds 	 * We will call the ->create function, that possibly is in a loadable
12611da177e4SLinus Torvalds 	 * module, so we have to bump that loadable module refcnt first.
12621da177e4SLinus Torvalds 	 */
126355737fdaSStephen Hemminger 	if (!try_module_get(pf->owner))
12641da177e4SLinus Torvalds 		goto out_release;
12651da177e4SLinus Torvalds 
126655737fdaSStephen Hemminger 	/* Now protected by module ref count */
126755737fdaSStephen Hemminger 	rcu_read_unlock();
126855737fdaSStephen Hemminger 
12693f378b68SEric Paris 	err = pf->create(net, sock, protocol, kern);
127055737fdaSStephen Hemminger 	if (err < 0)
12711da177e4SLinus Torvalds 		goto out_module_put;
1272a79af59eSFrank Filz 
12731da177e4SLinus Torvalds 	/*
12741da177e4SLinus Torvalds 	 * Now to bump the refcnt of the [loadable] module that owns this
12751da177e4SLinus Torvalds 	 * socket at sock_release time we decrement its refcnt.
12761da177e4SLinus Torvalds 	 */
127755737fdaSStephen Hemminger 	if (!try_module_get(sock->ops->owner))
127855737fdaSStephen Hemminger 		goto out_module_busy;
127955737fdaSStephen Hemminger 
12801da177e4SLinus Torvalds 	/*
12811da177e4SLinus Torvalds 	 * Now that we're done with the ->create function, the [loadable]
12821da177e4SLinus Torvalds 	 * module can have its refcnt decremented
12831da177e4SLinus Torvalds 	 */
128455737fdaSStephen Hemminger 	module_put(pf->owner);
12857420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, kern);
12867420ed23SVenkat Yekkirala 	if (err)
12873b185525SHerbert Xu 		goto out_sock_release;
128855737fdaSStephen Hemminger 	*res = sock;
12891da177e4SLinus Torvalds 
129055737fdaSStephen Hemminger 	return 0;
129155737fdaSStephen Hemminger 
129255737fdaSStephen Hemminger out_module_busy:
129355737fdaSStephen Hemminger 	err = -EAFNOSUPPORT;
12941da177e4SLinus Torvalds out_module_put:
129555737fdaSStephen Hemminger 	sock->ops = NULL;
129655737fdaSStephen Hemminger 	module_put(pf->owner);
129755737fdaSStephen Hemminger out_sock_release:
12981da177e4SLinus Torvalds 	sock_release(sock);
129955737fdaSStephen Hemminger 	return err;
130055737fdaSStephen Hemminger 
130155737fdaSStephen Hemminger out_release:
130255737fdaSStephen Hemminger 	rcu_read_unlock();
130355737fdaSStephen Hemminger 	goto out_sock_release;
13041da177e4SLinus Torvalds }
1305721db93aSPavel Emelyanov EXPORT_SYMBOL(__sock_create);
13061da177e4SLinus Torvalds 
13071da177e4SLinus Torvalds int sock_create(int family, int type, int protocol, struct socket **res)
13081da177e4SLinus Torvalds {
13091b8d7ae4SEric W. Biederman 	return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
13101da177e4SLinus Torvalds }
1311c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create);
13121da177e4SLinus Torvalds 
13131da177e4SLinus Torvalds int sock_create_kern(int family, int type, int protocol, struct socket **res)
13141da177e4SLinus Torvalds {
13151b8d7ae4SEric W. Biederman 	return __sock_create(&init_net, family, type, protocol, res, 1);
13161da177e4SLinus Torvalds }
1317c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_kern);
13181da177e4SLinus Torvalds 
13193e0fa65fSHeiko Carstens SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
13201da177e4SLinus Torvalds {
13211da177e4SLinus Torvalds 	int retval;
13221da177e4SLinus Torvalds 	struct socket *sock;
1323a677a039SUlrich Drepper 	int flags;
1324a677a039SUlrich Drepper 
1325e38b36f3SUlrich Drepper 	/* Check the SOCK_* constants for consistency.  */
1326e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
1327e38b36f3SUlrich Drepper 	BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
1328e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);
1329e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);
1330e38b36f3SUlrich Drepper 
1331a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
133277d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1333a677a039SUlrich Drepper 		return -EINVAL;
1334a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
13351da177e4SLinus Torvalds 
1336aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1337aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1338aaca0bdcSUlrich Drepper 
13391da177e4SLinus Torvalds 	retval = sock_create(family, type, protocol, &sock);
13401da177e4SLinus Torvalds 	if (retval < 0)
13411da177e4SLinus Torvalds 		goto out;
13421da177e4SLinus Torvalds 
134377d27200SUlrich Drepper 	retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
13441da177e4SLinus Torvalds 	if (retval < 0)
13451da177e4SLinus Torvalds 		goto out_release;
13461da177e4SLinus Torvalds 
13471da177e4SLinus Torvalds out:
13481da177e4SLinus Torvalds 	/* It may be already another descriptor 8) Not kernel problem. */
13491da177e4SLinus Torvalds 	return retval;
13501da177e4SLinus Torvalds 
13511da177e4SLinus Torvalds out_release:
13521da177e4SLinus Torvalds 	sock_release(sock);
13531da177e4SLinus Torvalds 	return retval;
13541da177e4SLinus Torvalds }
13551da177e4SLinus Torvalds 
13561da177e4SLinus Torvalds /*
13571da177e4SLinus Torvalds  *	Create a pair of connected sockets.
13581da177e4SLinus Torvalds  */
13591da177e4SLinus Torvalds 
13603e0fa65fSHeiko Carstens SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
13613e0fa65fSHeiko Carstens 		int __user *, usockvec)
13621da177e4SLinus Torvalds {
13631da177e4SLinus Torvalds 	struct socket *sock1, *sock2;
13641da177e4SLinus Torvalds 	int fd1, fd2, err;
1365db349509SAl Viro 	struct file *newfile1, *newfile2;
1366a677a039SUlrich Drepper 	int flags;
1367a677a039SUlrich Drepper 
1368a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
136977d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1370a677a039SUlrich Drepper 		return -EINVAL;
1371a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
13721da177e4SLinus Torvalds 
1373aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1374aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1375aaca0bdcSUlrich Drepper 
13761da177e4SLinus Torvalds 	/*
13771da177e4SLinus Torvalds 	 * Obtain the first socket and check if the underlying protocol
13781da177e4SLinus Torvalds 	 * supports the socketpair call.
13791da177e4SLinus Torvalds 	 */
13801da177e4SLinus Torvalds 
13811da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock1);
13821da177e4SLinus Torvalds 	if (err < 0)
13831da177e4SLinus Torvalds 		goto out;
13841da177e4SLinus Torvalds 
13851da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock2);
13861da177e4SLinus Torvalds 	if (err < 0)
13871da177e4SLinus Torvalds 		goto out_release_1;
13881da177e4SLinus Torvalds 
13891da177e4SLinus Torvalds 	err = sock1->ops->socketpair(sock1, sock2);
13901da177e4SLinus Torvalds 	if (err < 0)
13911da177e4SLinus Torvalds 		goto out_release_both;
13921da177e4SLinus Torvalds 
139328407630SAl Viro 	fd1 = get_unused_fd_flags(flags);
1394bf3c23d1SDavid S. Miller 	if (unlikely(fd1 < 0)) {
1395bf3c23d1SDavid S. Miller 		err = fd1;
13961da177e4SLinus Torvalds 		goto out_release_both;
1397bf3c23d1SDavid S. Miller 	}
139828407630SAl Viro 	fd2 = get_unused_fd_flags(flags);
1399198de4d7SAl Viro 	if (unlikely(fd2 < 0)) {
1400198de4d7SAl Viro 		err = fd2;
140128407630SAl Viro 		put_unused_fd(fd1);
140228407630SAl Viro 		goto out_release_both;
140328407630SAl Viro 	}
140428407630SAl Viro 
140528407630SAl Viro 	newfile1 = sock_alloc_file(sock1, flags);
140628407630SAl Viro 	if (unlikely(IS_ERR(newfile1))) {
140728407630SAl Viro 		err = PTR_ERR(newfile1);
140828407630SAl Viro 		put_unused_fd(fd1);
140928407630SAl Viro 		put_unused_fd(fd2);
141028407630SAl Viro 		goto out_release_both;
141128407630SAl Viro 	}
141228407630SAl Viro 
141328407630SAl Viro 	newfile2 = sock_alloc_file(sock2, flags);
141428407630SAl Viro 	if (IS_ERR(newfile2)) {
141528407630SAl Viro 		err = PTR_ERR(newfile2);
1416198de4d7SAl Viro 		fput(newfile1);
1417198de4d7SAl Viro 		put_unused_fd(fd1);
141828407630SAl Viro 		put_unused_fd(fd2);
1419198de4d7SAl Viro 		sock_release(sock2);
1420198de4d7SAl Viro 		goto out;
1421db349509SAl Viro 	}
1422db349509SAl Viro 
1423157cf649SAl Viro 	audit_fd_pair(fd1, fd2);
1424db349509SAl Viro 	fd_install(fd1, newfile1);
1425db349509SAl Viro 	fd_install(fd2, newfile2);
14261da177e4SLinus Torvalds 	/* fd1 and fd2 may be already another descriptors.
14271da177e4SLinus Torvalds 	 * Not kernel problem.
14281da177e4SLinus Torvalds 	 */
14291da177e4SLinus Torvalds 
14301da177e4SLinus Torvalds 	err = put_user(fd1, &usockvec[0]);
14311da177e4SLinus Torvalds 	if (!err)
14321da177e4SLinus Torvalds 		err = put_user(fd2, &usockvec[1]);
14331da177e4SLinus Torvalds 	if (!err)
14341da177e4SLinus Torvalds 		return 0;
14351da177e4SLinus Torvalds 
14361da177e4SLinus Torvalds 	sys_close(fd2);
14371da177e4SLinus Torvalds 	sys_close(fd1);
14381da177e4SLinus Torvalds 	return err;
14391da177e4SLinus Torvalds 
14401da177e4SLinus Torvalds out_release_both:
14411da177e4SLinus Torvalds 	sock_release(sock2);
14421da177e4SLinus Torvalds out_release_1:
14431da177e4SLinus Torvalds 	sock_release(sock1);
14441da177e4SLinus Torvalds out:
14451da177e4SLinus Torvalds 	return err;
14461da177e4SLinus Torvalds }
14471da177e4SLinus Torvalds 
14481da177e4SLinus Torvalds /*
14491da177e4SLinus Torvalds  *	Bind a name to a socket. Nothing much to do here since it's
14501da177e4SLinus Torvalds  *	the protocol's responsibility to handle the local address.
14511da177e4SLinus Torvalds  *
14521da177e4SLinus Torvalds  *	We move the socket address to kernel space before we call
14531da177e4SLinus Torvalds  *	the protocol layer (having also checked the address is ok).
14541da177e4SLinus Torvalds  */
14551da177e4SLinus Torvalds 
145620f37034SHeiko Carstens SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
14571da177e4SLinus Torvalds {
14581da177e4SLinus Torvalds 	struct socket *sock;
1459230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
14606cb153caSBenjamin LaHaise 	int err, fput_needed;
14611da177e4SLinus Torvalds 
146289bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
146389bddce5SStephen Hemminger 	if (sock) {
146443db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(umyaddr, addrlen, &address);
146589bddce5SStephen Hemminger 		if (err >= 0) {
146689bddce5SStephen Hemminger 			err = security_socket_bind(sock,
1467230b1839SYOSHIFUJI Hideaki 						   (struct sockaddr *)&address,
146889bddce5SStephen Hemminger 						   addrlen);
14696cb153caSBenjamin LaHaise 			if (!err)
14706cb153caSBenjamin LaHaise 				err = sock->ops->bind(sock,
147189bddce5SStephen Hemminger 						      (struct sockaddr *)
1472230b1839SYOSHIFUJI Hideaki 						      &address, addrlen);
14731da177e4SLinus Torvalds 		}
14746cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
14751da177e4SLinus Torvalds 	}
14761da177e4SLinus Torvalds 	return err;
14771da177e4SLinus Torvalds }
14781da177e4SLinus Torvalds 
14791da177e4SLinus Torvalds /*
14801da177e4SLinus Torvalds  *	Perform a listen. Basically, we allow the protocol to do anything
14811da177e4SLinus Torvalds  *	necessary for a listen, and if that works, we mark the socket as
14821da177e4SLinus Torvalds  *	ready for listening.
14831da177e4SLinus Torvalds  */
14841da177e4SLinus Torvalds 
14853e0fa65fSHeiko Carstens SYSCALL_DEFINE2(listen, int, fd, int, backlog)
14861da177e4SLinus Torvalds {
14871da177e4SLinus Torvalds 	struct socket *sock;
14886cb153caSBenjamin LaHaise 	int err, fput_needed;
1489b8e1f9b5SPavel Emelyanov 	int somaxconn;
14901da177e4SLinus Torvalds 
149189bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
149289bddce5SStephen Hemminger 	if (sock) {
14938efa6e93SPavel Emelyanov 		somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
149495c96174SEric Dumazet 		if ((unsigned int)backlog > somaxconn)
1495b8e1f9b5SPavel Emelyanov 			backlog = somaxconn;
14961da177e4SLinus Torvalds 
14971da177e4SLinus Torvalds 		err = security_socket_listen(sock, backlog);
14986cb153caSBenjamin LaHaise 		if (!err)
14991da177e4SLinus Torvalds 			err = sock->ops->listen(sock, backlog);
15006cb153caSBenjamin LaHaise 
15016cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
15021da177e4SLinus Torvalds 	}
15031da177e4SLinus Torvalds 	return err;
15041da177e4SLinus Torvalds }
15051da177e4SLinus Torvalds 
15061da177e4SLinus Torvalds /*
15071da177e4SLinus Torvalds  *	For accept, we attempt to create a new socket, set up the link
15081da177e4SLinus Torvalds  *	with the client, wake up the client, then return the new
15091da177e4SLinus Torvalds  *	connected fd. We collect the address of the connector in kernel
15101da177e4SLinus Torvalds  *	space and move it to user at the very end. This is unclean because
15111da177e4SLinus Torvalds  *	we open the socket then return an error.
15121da177e4SLinus Torvalds  *
15131da177e4SLinus Torvalds  *	1003.1g adds the ability to recvmsg() to query connection pending
15141da177e4SLinus Torvalds  *	status to recvmsg. We need to add that support in a way thats
15151da177e4SLinus Torvalds  *	clean when we restucture accept also.
15161da177e4SLinus Torvalds  */
15171da177e4SLinus Torvalds 
151820f37034SHeiko Carstens SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
151920f37034SHeiko Carstens 		int __user *, upeer_addrlen, int, flags)
15201da177e4SLinus Torvalds {
15211da177e4SLinus Torvalds 	struct socket *sock, *newsock;
152239d8c1b6SDavid S. Miller 	struct file *newfile;
15236cb153caSBenjamin LaHaise 	int err, len, newfd, fput_needed;
1524230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
15251da177e4SLinus Torvalds 
152677d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1527aaca0bdcSUlrich Drepper 		return -EINVAL;
1528aaca0bdcSUlrich Drepper 
1529aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1530aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1531aaca0bdcSUlrich Drepper 
15326cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
15331da177e4SLinus Torvalds 	if (!sock)
15341da177e4SLinus Torvalds 		goto out;
15351da177e4SLinus Torvalds 
15361da177e4SLinus Torvalds 	err = -ENFILE;
1537c6d409cfSEric Dumazet 	newsock = sock_alloc();
1538c6d409cfSEric Dumazet 	if (!newsock)
15391da177e4SLinus Torvalds 		goto out_put;
15401da177e4SLinus Torvalds 
15411da177e4SLinus Torvalds 	newsock->type = sock->type;
15421da177e4SLinus Torvalds 	newsock->ops = sock->ops;
15431da177e4SLinus Torvalds 
15441da177e4SLinus Torvalds 	/*
15451da177e4SLinus Torvalds 	 * We don't need try_module_get here, as the listening socket (sock)
15461da177e4SLinus Torvalds 	 * has the protocol module (sock->ops->owner) held.
15471da177e4SLinus Torvalds 	 */
15481da177e4SLinus Torvalds 	__module_get(newsock->ops->owner);
15491da177e4SLinus Torvalds 
155028407630SAl Viro 	newfd = get_unused_fd_flags(flags);
155139d8c1b6SDavid S. Miller 	if (unlikely(newfd < 0)) {
155239d8c1b6SDavid S. Miller 		err = newfd;
15539a1875e6SDavid S. Miller 		sock_release(newsock);
15549a1875e6SDavid S. Miller 		goto out_put;
155539d8c1b6SDavid S. Miller 	}
155628407630SAl Viro 	newfile = sock_alloc_file(newsock, flags);
155728407630SAl Viro 	if (unlikely(IS_ERR(newfile))) {
155828407630SAl Viro 		err = PTR_ERR(newfile);
155928407630SAl Viro 		put_unused_fd(newfd);
156028407630SAl Viro 		sock_release(newsock);
156128407630SAl Viro 		goto out_put;
156228407630SAl Viro 	}
156339d8c1b6SDavid S. Miller 
1564a79af59eSFrank Filz 	err = security_socket_accept(sock, newsock);
1565a79af59eSFrank Filz 	if (err)
156639d8c1b6SDavid S. Miller 		goto out_fd;
1567a79af59eSFrank Filz 
15681da177e4SLinus Torvalds 	err = sock->ops->accept(sock, newsock, sock->file->f_flags);
15691da177e4SLinus Torvalds 	if (err < 0)
157039d8c1b6SDavid S. Miller 		goto out_fd;
15711da177e4SLinus Torvalds 
15721da177e4SLinus Torvalds 	if (upeer_sockaddr) {
1573230b1839SYOSHIFUJI Hideaki 		if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
157489bddce5SStephen Hemminger 					  &len, 2) < 0) {
15751da177e4SLinus Torvalds 			err = -ECONNABORTED;
157639d8c1b6SDavid S. Miller 			goto out_fd;
15771da177e4SLinus Torvalds 		}
157843db362dSMaciej Żenczykowski 		err = move_addr_to_user(&address,
1579230b1839SYOSHIFUJI Hideaki 					len, upeer_sockaddr, upeer_addrlen);
15801da177e4SLinus Torvalds 		if (err < 0)
158139d8c1b6SDavid S. Miller 			goto out_fd;
15821da177e4SLinus Torvalds 	}
15831da177e4SLinus Torvalds 
15841da177e4SLinus Torvalds 	/* File flags are not inherited via accept() unlike another OSes. */
15851da177e4SLinus Torvalds 
158639d8c1b6SDavid S. Miller 	fd_install(newfd, newfile);
158739d8c1b6SDavid S. Miller 	err = newfd;
15881da177e4SLinus Torvalds 
15891da177e4SLinus Torvalds out_put:
15906cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
15911da177e4SLinus Torvalds out:
15921da177e4SLinus Torvalds 	return err;
159339d8c1b6SDavid S. Miller out_fd:
15949606a216SDavid S. Miller 	fput(newfile);
159539d8c1b6SDavid S. Miller 	put_unused_fd(newfd);
15961da177e4SLinus Torvalds 	goto out_put;
15971da177e4SLinus Torvalds }
15981da177e4SLinus Torvalds 
159920f37034SHeiko Carstens SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,
160020f37034SHeiko Carstens 		int __user *, upeer_addrlen)
1601aaca0bdcSUlrich Drepper {
1602de11defeSUlrich Drepper 	return sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0);
1603aaca0bdcSUlrich Drepper }
1604aaca0bdcSUlrich Drepper 
16051da177e4SLinus Torvalds /*
16061da177e4SLinus Torvalds  *	Attempt to connect to a socket with the server address.  The address
16071da177e4SLinus Torvalds  *	is in user space so we verify it is OK and move it to kernel space.
16081da177e4SLinus Torvalds  *
16091da177e4SLinus Torvalds  *	For 1003.1g we need to add clean support for a bind to AF_UNSPEC to
16101da177e4SLinus Torvalds  *	break bindings
16111da177e4SLinus Torvalds  *
16121da177e4SLinus Torvalds  *	NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and
16131da177e4SLinus Torvalds  *	other SEQPACKET protocols that take time to connect() as it doesn't
16141da177e4SLinus Torvalds  *	include the -EINPROGRESS status for such sockets.
16151da177e4SLinus Torvalds  */
16161da177e4SLinus Torvalds 
161720f37034SHeiko Carstens SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
161820f37034SHeiko Carstens 		int, addrlen)
16191da177e4SLinus Torvalds {
16201da177e4SLinus Torvalds 	struct socket *sock;
1621230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16226cb153caSBenjamin LaHaise 	int err, fput_needed;
16231da177e4SLinus Torvalds 
16246cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
16251da177e4SLinus Torvalds 	if (!sock)
16261da177e4SLinus Torvalds 		goto out;
162743db362dSMaciej Żenczykowski 	err = move_addr_to_kernel(uservaddr, addrlen, &address);
16281da177e4SLinus Torvalds 	if (err < 0)
16291da177e4SLinus Torvalds 		goto out_put;
16301da177e4SLinus Torvalds 
163189bddce5SStephen Hemminger 	err =
1632230b1839SYOSHIFUJI Hideaki 	    security_socket_connect(sock, (struct sockaddr *)&address, addrlen);
16331da177e4SLinus Torvalds 	if (err)
16341da177e4SLinus Torvalds 		goto out_put;
16351da177e4SLinus Torvalds 
1636230b1839SYOSHIFUJI Hideaki 	err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,
16371da177e4SLinus Torvalds 				 sock->file->f_flags);
16381da177e4SLinus Torvalds out_put:
16396cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
16401da177e4SLinus Torvalds out:
16411da177e4SLinus Torvalds 	return err;
16421da177e4SLinus Torvalds }
16431da177e4SLinus Torvalds 
16441da177e4SLinus Torvalds /*
16451da177e4SLinus Torvalds  *	Get the local address ('name') of a socket object. Move the obtained
16461da177e4SLinus Torvalds  *	name to user space.
16471da177e4SLinus Torvalds  */
16481da177e4SLinus Torvalds 
164920f37034SHeiko Carstens SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
165020f37034SHeiko Carstens 		int __user *, usockaddr_len)
16511da177e4SLinus Torvalds {
16521da177e4SLinus Torvalds 	struct socket *sock;
1653230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16546cb153caSBenjamin LaHaise 	int len, err, fput_needed;
16551da177e4SLinus Torvalds 
16566cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
16571da177e4SLinus Torvalds 	if (!sock)
16581da177e4SLinus Torvalds 		goto out;
16591da177e4SLinus Torvalds 
16601da177e4SLinus Torvalds 	err = security_socket_getsockname(sock);
16611da177e4SLinus Torvalds 	if (err)
16621da177e4SLinus Torvalds 		goto out_put;
16631da177e4SLinus Torvalds 
1664230b1839SYOSHIFUJI Hideaki 	err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0);
16651da177e4SLinus Torvalds 	if (err)
16661da177e4SLinus Torvalds 		goto out_put;
166743db362dSMaciej Żenczykowski 	err = move_addr_to_user(&address, len, usockaddr, usockaddr_len);
16681da177e4SLinus Torvalds 
16691da177e4SLinus Torvalds out_put:
16706cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
16711da177e4SLinus Torvalds out:
16721da177e4SLinus Torvalds 	return err;
16731da177e4SLinus Torvalds }
16741da177e4SLinus Torvalds 
16751da177e4SLinus Torvalds /*
16761da177e4SLinus Torvalds  *	Get the remote address ('name') of a socket object. Move the obtained
16771da177e4SLinus Torvalds  *	name to user space.
16781da177e4SLinus Torvalds  */
16791da177e4SLinus Torvalds 
168020f37034SHeiko Carstens SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
168120f37034SHeiko Carstens 		int __user *, usockaddr_len)
16821da177e4SLinus Torvalds {
16831da177e4SLinus Torvalds 	struct socket *sock;
1684230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16856cb153caSBenjamin LaHaise 	int len, err, fput_needed;
16861da177e4SLinus Torvalds 
168789bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
168889bddce5SStephen Hemminger 	if (sock != NULL) {
16891da177e4SLinus Torvalds 		err = security_socket_getpeername(sock);
16901da177e4SLinus Torvalds 		if (err) {
16916cb153caSBenjamin LaHaise 			fput_light(sock->file, fput_needed);
16921da177e4SLinus Torvalds 			return err;
16931da177e4SLinus Torvalds 		}
16941da177e4SLinus Torvalds 
169589bddce5SStephen Hemminger 		err =
1696230b1839SYOSHIFUJI Hideaki 		    sock->ops->getname(sock, (struct sockaddr *)&address, &len,
169789bddce5SStephen Hemminger 				       1);
16981da177e4SLinus Torvalds 		if (!err)
169943db362dSMaciej Żenczykowski 			err = move_addr_to_user(&address, len, usockaddr,
170089bddce5SStephen Hemminger 						usockaddr_len);
17016cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
17021da177e4SLinus Torvalds 	}
17031da177e4SLinus Torvalds 	return err;
17041da177e4SLinus Torvalds }
17051da177e4SLinus Torvalds 
17061da177e4SLinus Torvalds /*
17071da177e4SLinus Torvalds  *	Send a datagram to a given address. We move the address into kernel
17081da177e4SLinus Torvalds  *	space and check the user space data area is readable before invoking
17091da177e4SLinus Torvalds  *	the protocol.
17101da177e4SLinus Torvalds  */
17111da177e4SLinus Torvalds 
17123e0fa65fSHeiko Carstens SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
171395c96174SEric Dumazet 		unsigned int, flags, struct sockaddr __user *, addr,
17143e0fa65fSHeiko Carstens 		int, addr_len)
17151da177e4SLinus Torvalds {
17161da177e4SLinus Torvalds 	struct socket *sock;
1717230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
17181da177e4SLinus Torvalds 	int err;
17191da177e4SLinus Torvalds 	struct msghdr msg;
17201da177e4SLinus Torvalds 	struct iovec iov;
17216cb153caSBenjamin LaHaise 	int fput_needed;
17221da177e4SLinus Torvalds 
1723253eacc0SLinus Torvalds 	if (len > INT_MAX)
1724253eacc0SLinus Torvalds 		len = INT_MAX;
1725de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1726de0fa95cSPavel Emelyanov 	if (!sock)
17274387ff75SDavid S. Miller 		goto out;
17286cb153caSBenjamin LaHaise 
17291da177e4SLinus Torvalds 	iov.iov_base = buff;
17301da177e4SLinus Torvalds 	iov.iov_len = len;
17311da177e4SLinus Torvalds 	msg.msg_name = NULL;
17321da177e4SLinus Torvalds 	msg.msg_iov = &iov;
17331da177e4SLinus Torvalds 	msg.msg_iovlen = 1;
17341da177e4SLinus Torvalds 	msg.msg_control = NULL;
17351da177e4SLinus Torvalds 	msg.msg_controllen = 0;
17361da177e4SLinus Torvalds 	msg.msg_namelen = 0;
17376cb153caSBenjamin LaHaise 	if (addr) {
173843db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(addr, addr_len, &address);
17391da177e4SLinus Torvalds 		if (err < 0)
17401da177e4SLinus Torvalds 			goto out_put;
1741230b1839SYOSHIFUJI Hideaki 		msg.msg_name = (struct sockaddr *)&address;
17421da177e4SLinus Torvalds 		msg.msg_namelen = addr_len;
17431da177e4SLinus Torvalds 	}
17441da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
17451da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
17461da177e4SLinus Torvalds 	msg.msg_flags = flags;
17471da177e4SLinus Torvalds 	err = sock_sendmsg(sock, &msg, len);
17481da177e4SLinus Torvalds 
17491da177e4SLinus Torvalds out_put:
1750de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
17514387ff75SDavid S. Miller out:
17521da177e4SLinus Torvalds 	return err;
17531da177e4SLinus Torvalds }
17541da177e4SLinus Torvalds 
17551da177e4SLinus Torvalds /*
17561da177e4SLinus Torvalds  *	Send a datagram down a socket.
17571da177e4SLinus Torvalds  */
17581da177e4SLinus Torvalds 
17593e0fa65fSHeiko Carstens SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len,
176095c96174SEric Dumazet 		unsigned int, flags)
17611da177e4SLinus Torvalds {
17621da177e4SLinus Torvalds 	return sys_sendto(fd, buff, len, flags, NULL, 0);
17631da177e4SLinus Torvalds }
17641da177e4SLinus Torvalds 
17651da177e4SLinus Torvalds /*
17661da177e4SLinus Torvalds  *	Receive a frame from the socket and optionally record the address of the
17671da177e4SLinus Torvalds  *	sender. We verify the buffers are writable and if needed move the
17681da177e4SLinus Torvalds  *	sender address from kernel to user space.
17691da177e4SLinus Torvalds  */
17701da177e4SLinus Torvalds 
17713e0fa65fSHeiko Carstens SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
177295c96174SEric Dumazet 		unsigned int, flags, struct sockaddr __user *, addr,
17733e0fa65fSHeiko Carstens 		int __user *, addr_len)
17741da177e4SLinus Torvalds {
17751da177e4SLinus Torvalds 	struct socket *sock;
17761da177e4SLinus Torvalds 	struct iovec iov;
17771da177e4SLinus Torvalds 	struct msghdr msg;
1778230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
17791da177e4SLinus Torvalds 	int err, err2;
17806cb153caSBenjamin LaHaise 	int fput_needed;
17811da177e4SLinus Torvalds 
1782253eacc0SLinus Torvalds 	if (size > INT_MAX)
1783253eacc0SLinus Torvalds 		size = INT_MAX;
1784de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
17851da177e4SLinus Torvalds 	if (!sock)
1786de0fa95cSPavel Emelyanov 		goto out;
17871da177e4SLinus Torvalds 
17881da177e4SLinus Torvalds 	msg.msg_control = NULL;
17891da177e4SLinus Torvalds 	msg.msg_controllen = 0;
17901da177e4SLinus Torvalds 	msg.msg_iovlen = 1;
17911da177e4SLinus Torvalds 	msg.msg_iov = &iov;
17921da177e4SLinus Torvalds 	iov.iov_len = size;
17931da177e4SLinus Torvalds 	iov.iov_base = ubuf;
1794230b1839SYOSHIFUJI Hideaki 	msg.msg_name = (struct sockaddr *)&address;
1795230b1839SYOSHIFUJI Hideaki 	msg.msg_namelen = sizeof(address);
17961da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
17971da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
17981da177e4SLinus Torvalds 	err = sock_recvmsg(sock, &msg, size, flags);
17991da177e4SLinus Torvalds 
180089bddce5SStephen Hemminger 	if (err >= 0 && addr != NULL) {
180143db362dSMaciej Żenczykowski 		err2 = move_addr_to_user(&address,
1802230b1839SYOSHIFUJI Hideaki 					 msg.msg_namelen, addr, addr_len);
18031da177e4SLinus Torvalds 		if (err2 < 0)
18041da177e4SLinus Torvalds 			err = err2;
18051da177e4SLinus Torvalds 	}
1806de0fa95cSPavel Emelyanov 
1807de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
18084387ff75SDavid S. Miller out:
18091da177e4SLinus Torvalds 	return err;
18101da177e4SLinus Torvalds }
18111da177e4SLinus Torvalds 
18121da177e4SLinus Torvalds /*
18131da177e4SLinus Torvalds  *	Receive a datagram from a socket.
18141da177e4SLinus Torvalds  */
18151da177e4SLinus Torvalds 
181689bddce5SStephen Hemminger asmlinkage long sys_recv(int fd, void __user *ubuf, size_t size,
181795c96174SEric Dumazet 			 unsigned int flags)
18181da177e4SLinus Torvalds {
18191da177e4SLinus Torvalds 	return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL);
18201da177e4SLinus Torvalds }
18211da177e4SLinus Torvalds 
18221da177e4SLinus Torvalds /*
18231da177e4SLinus Torvalds  *	Set a socket option. Because we don't know the option lengths we have
18241da177e4SLinus Torvalds  *	to pass the user mode parameter for the protocols to sort out.
18251da177e4SLinus Torvalds  */
18261da177e4SLinus Torvalds 
182720f37034SHeiko Carstens SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
182820f37034SHeiko Carstens 		char __user *, optval, int, optlen)
18291da177e4SLinus Torvalds {
18306cb153caSBenjamin LaHaise 	int err, fput_needed;
18311da177e4SLinus Torvalds 	struct socket *sock;
18321da177e4SLinus Torvalds 
18331da177e4SLinus Torvalds 	if (optlen < 0)
18341da177e4SLinus Torvalds 		return -EINVAL;
18351da177e4SLinus Torvalds 
183689bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
183789bddce5SStephen Hemminger 	if (sock != NULL) {
18381da177e4SLinus Torvalds 		err = security_socket_setsockopt(sock, level, optname);
18396cb153caSBenjamin LaHaise 		if (err)
18406cb153caSBenjamin LaHaise 			goto out_put;
18411da177e4SLinus Torvalds 
18421da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
184389bddce5SStephen Hemminger 			err =
184489bddce5SStephen Hemminger 			    sock_setsockopt(sock, level, optname, optval,
184589bddce5SStephen Hemminger 					    optlen);
18461da177e4SLinus Torvalds 		else
184789bddce5SStephen Hemminger 			err =
184889bddce5SStephen Hemminger 			    sock->ops->setsockopt(sock, level, optname, optval,
184989bddce5SStephen Hemminger 						  optlen);
18506cb153caSBenjamin LaHaise out_put:
18516cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
18521da177e4SLinus Torvalds 	}
18531da177e4SLinus Torvalds 	return err;
18541da177e4SLinus Torvalds }
18551da177e4SLinus Torvalds 
18561da177e4SLinus Torvalds /*
18571da177e4SLinus Torvalds  *	Get a socket option. Because we don't know the option lengths we have
18581da177e4SLinus Torvalds  *	to pass a user mode parameter for the protocols to sort out.
18591da177e4SLinus Torvalds  */
18601da177e4SLinus Torvalds 
186120f37034SHeiko Carstens SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
186220f37034SHeiko Carstens 		char __user *, optval, int __user *, optlen)
18631da177e4SLinus Torvalds {
18646cb153caSBenjamin LaHaise 	int err, fput_needed;
18651da177e4SLinus Torvalds 	struct socket *sock;
18661da177e4SLinus Torvalds 
186789bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
186889bddce5SStephen Hemminger 	if (sock != NULL) {
18696cb153caSBenjamin LaHaise 		err = security_socket_getsockopt(sock, level, optname);
18706cb153caSBenjamin LaHaise 		if (err)
18716cb153caSBenjamin LaHaise 			goto out_put;
18721da177e4SLinus Torvalds 
18731da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
187489bddce5SStephen Hemminger 			err =
187589bddce5SStephen Hemminger 			    sock_getsockopt(sock, level, optname, optval,
187689bddce5SStephen Hemminger 					    optlen);
18771da177e4SLinus Torvalds 		else
187889bddce5SStephen Hemminger 			err =
187989bddce5SStephen Hemminger 			    sock->ops->getsockopt(sock, level, optname, optval,
188089bddce5SStephen Hemminger 						  optlen);
18816cb153caSBenjamin LaHaise out_put:
18826cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
18831da177e4SLinus Torvalds 	}
18841da177e4SLinus Torvalds 	return err;
18851da177e4SLinus Torvalds }
18861da177e4SLinus Torvalds 
18871da177e4SLinus Torvalds /*
18881da177e4SLinus Torvalds  *	Shutdown a socket.
18891da177e4SLinus Torvalds  */
18901da177e4SLinus Torvalds 
1891754fe8d2SHeiko Carstens SYSCALL_DEFINE2(shutdown, int, fd, int, how)
18921da177e4SLinus Torvalds {
18936cb153caSBenjamin LaHaise 	int err, fput_needed;
18941da177e4SLinus Torvalds 	struct socket *sock;
18951da177e4SLinus Torvalds 
189689bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
189789bddce5SStephen Hemminger 	if (sock != NULL) {
18981da177e4SLinus Torvalds 		err = security_socket_shutdown(sock, how);
18996cb153caSBenjamin LaHaise 		if (!err)
19001da177e4SLinus Torvalds 			err = sock->ops->shutdown(sock, how);
19016cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
19021da177e4SLinus Torvalds 	}
19031da177e4SLinus Torvalds 	return err;
19041da177e4SLinus Torvalds }
19051da177e4SLinus Torvalds 
19061da177e4SLinus Torvalds /* A couple of helpful macros for getting the address of the 32/64 bit
19071da177e4SLinus Torvalds  * fields which are the same type (int / unsigned) on our platforms.
19081da177e4SLinus Torvalds  */
19091da177e4SLinus Torvalds #define COMPAT_MSG(msg, member)	((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member)
19101da177e4SLinus Torvalds #define COMPAT_NAMELEN(msg)	COMPAT_MSG(msg, msg_namelen)
19111da177e4SLinus Torvalds #define COMPAT_FLAGS(msg)	COMPAT_MSG(msg, msg_flags)
19121da177e4SLinus Torvalds 
1913c71d8ebeSTetsuo Handa struct used_address {
1914c71d8ebeSTetsuo Handa 	struct sockaddr_storage name;
1915c71d8ebeSTetsuo Handa 	unsigned int name_len;
1916c71d8ebeSTetsuo Handa };
1917c71d8ebeSTetsuo Handa 
1918228e548eSAnton Blanchard static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
191995c96174SEric Dumazet 			 struct msghdr *msg_sys, unsigned int flags,
1920c71d8ebeSTetsuo Handa 			 struct used_address *used_address)
19211da177e4SLinus Torvalds {
192289bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
192389bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
1924230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
19251da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
1926b9d717a7SAlex Williamson 	unsigned char ctl[sizeof(struct cmsghdr) + 20]
1927b9d717a7SAlex Williamson 	    __attribute__ ((aligned(sizeof(__kernel_size_t))));
1928b9d717a7SAlex Williamson 	/* 20 is size of ipv6_pktinfo */
19291da177e4SLinus Torvalds 	unsigned char *ctl_buf = ctl;
1930a74e9106SEric Dumazet 	int err, ctl_len, total_len;
19311da177e4SLinus Torvalds 
19321da177e4SLinus Torvalds 	err = -EFAULT;
19331da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
1934228e548eSAnton Blanchard 		if (get_compat_msghdr(msg_sys, msg_compat))
19351da177e4SLinus Torvalds 			return -EFAULT;
1936228e548eSAnton Blanchard 	} else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr)))
19371da177e4SLinus Torvalds 		return -EFAULT;
19381da177e4SLinus Torvalds 
1939a74e9106SEric Dumazet 	if (msg_sys->msg_iovlen > UIO_FASTIOV) {
19401da177e4SLinus Torvalds 		err = -EMSGSIZE;
1941228e548eSAnton Blanchard 		if (msg_sys->msg_iovlen > UIO_MAXIOV)
1942228e548eSAnton Blanchard 			goto out;
19431da177e4SLinus Torvalds 		err = -ENOMEM;
1944a74e9106SEric Dumazet 		iov = kmalloc(msg_sys->msg_iovlen * sizeof(struct iovec),
1945a74e9106SEric Dumazet 			      GFP_KERNEL);
19461da177e4SLinus Torvalds 		if (!iov)
1947228e548eSAnton Blanchard 			goto out;
19481da177e4SLinus Torvalds 	}
19491da177e4SLinus Torvalds 
19501da177e4SLinus Torvalds 	/* This will also move the address data into kernel space */
19511da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
195243db362dSMaciej Żenczykowski 		err = verify_compat_iovec(msg_sys, iov, &address, VERIFY_READ);
19531da177e4SLinus Torvalds 	} else
195443db362dSMaciej Żenczykowski 		err = verify_iovec(msg_sys, iov, &address, VERIFY_READ);
19551da177e4SLinus Torvalds 	if (err < 0)
19561da177e4SLinus Torvalds 		goto out_freeiov;
19571da177e4SLinus Torvalds 	total_len = err;
19581da177e4SLinus Torvalds 
19591da177e4SLinus Torvalds 	err = -ENOBUFS;
19601da177e4SLinus Torvalds 
1961228e548eSAnton Blanchard 	if (msg_sys->msg_controllen > INT_MAX)
19621da177e4SLinus Torvalds 		goto out_freeiov;
1963228e548eSAnton Blanchard 	ctl_len = msg_sys->msg_controllen;
19641da177e4SLinus Torvalds 	if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
196589bddce5SStephen Hemminger 		err =
1966228e548eSAnton Blanchard 		    cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl,
196789bddce5SStephen Hemminger 						     sizeof(ctl));
19681da177e4SLinus Torvalds 		if (err)
19691da177e4SLinus Torvalds 			goto out_freeiov;
1970228e548eSAnton Blanchard 		ctl_buf = msg_sys->msg_control;
1971228e548eSAnton Blanchard 		ctl_len = msg_sys->msg_controllen;
19721da177e4SLinus Torvalds 	} else if (ctl_len) {
197389bddce5SStephen Hemminger 		if (ctl_len > sizeof(ctl)) {
19741da177e4SLinus Torvalds 			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
19751da177e4SLinus Torvalds 			if (ctl_buf == NULL)
19761da177e4SLinus Torvalds 				goto out_freeiov;
19771da177e4SLinus Torvalds 		}
19781da177e4SLinus Torvalds 		err = -EFAULT;
19791da177e4SLinus Torvalds 		/*
1980228e548eSAnton Blanchard 		 * Careful! Before this, msg_sys->msg_control contains a user pointer.
19811da177e4SLinus Torvalds 		 * Afterwards, it will be a kernel pointer. Thus the compiler-assisted
19821da177e4SLinus Torvalds 		 * checking falls down on this.
19831da177e4SLinus Torvalds 		 */
1984fb8621bbSNamhyung Kim 		if (copy_from_user(ctl_buf,
1985228e548eSAnton Blanchard 				   (void __user __force *)msg_sys->msg_control,
198689bddce5SStephen Hemminger 				   ctl_len))
19871da177e4SLinus Torvalds 			goto out_freectl;
1988228e548eSAnton Blanchard 		msg_sys->msg_control = ctl_buf;
19891da177e4SLinus Torvalds 	}
1990228e548eSAnton Blanchard 	msg_sys->msg_flags = flags;
19911da177e4SLinus Torvalds 
19921da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
1993228e548eSAnton Blanchard 		msg_sys->msg_flags |= MSG_DONTWAIT;
1994c71d8ebeSTetsuo Handa 	/*
1995c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and current destination address is same as
1996c71d8ebeSTetsuo Handa 	 * previously succeeded address, omit asking LSM's decision.
1997c71d8ebeSTetsuo Handa 	 * used_address->name_len is initialized to UINT_MAX so that the first
1998c71d8ebeSTetsuo Handa 	 * destination address never matches.
1999c71d8ebeSTetsuo Handa 	 */
2000bc909d9dSMathieu Desnoyers 	if (used_address && msg_sys->msg_name &&
2001bc909d9dSMathieu Desnoyers 	    used_address->name_len == msg_sys->msg_namelen &&
2002bc909d9dSMathieu Desnoyers 	    !memcmp(&used_address->name, msg_sys->msg_name,
2003c71d8ebeSTetsuo Handa 		    used_address->name_len)) {
2004c71d8ebeSTetsuo Handa 		err = sock_sendmsg_nosec(sock, msg_sys, total_len);
2005c71d8ebeSTetsuo Handa 		goto out_freectl;
2006c71d8ebeSTetsuo Handa 	}
2007c71d8ebeSTetsuo Handa 	err = sock_sendmsg(sock, msg_sys, total_len);
2008c71d8ebeSTetsuo Handa 	/*
2009c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and sending to current destination address was
2010c71d8ebeSTetsuo Handa 	 * successful, remember it.
2011c71d8ebeSTetsuo Handa 	 */
2012c71d8ebeSTetsuo Handa 	if (used_address && err >= 0) {
2013c71d8ebeSTetsuo Handa 		used_address->name_len = msg_sys->msg_namelen;
2014bc909d9dSMathieu Desnoyers 		if (msg_sys->msg_name)
2015bc909d9dSMathieu Desnoyers 			memcpy(&used_address->name, msg_sys->msg_name,
2016c71d8ebeSTetsuo Handa 			       used_address->name_len);
2017c71d8ebeSTetsuo Handa 	}
20181da177e4SLinus Torvalds 
20191da177e4SLinus Torvalds out_freectl:
20201da177e4SLinus Torvalds 	if (ctl_buf != ctl)
20211da177e4SLinus Torvalds 		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
20221da177e4SLinus Torvalds out_freeiov:
20231da177e4SLinus Torvalds 	if (iov != iovstack)
2024a74e9106SEric Dumazet 		kfree(iov);
2025228e548eSAnton Blanchard out:
2026228e548eSAnton Blanchard 	return err;
2027228e548eSAnton Blanchard }
2028228e548eSAnton Blanchard 
2029228e548eSAnton Blanchard /*
2030228e548eSAnton Blanchard  *	BSD sendmsg interface
2031228e548eSAnton Blanchard  */
2032228e548eSAnton Blanchard 
203395c96174SEric Dumazet SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned int, flags)
2034228e548eSAnton Blanchard {
2035228e548eSAnton Blanchard 	int fput_needed, err;
2036228e548eSAnton Blanchard 	struct msghdr msg_sys;
2037228e548eSAnton Blanchard 	struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed);
2038228e548eSAnton Blanchard 
2039228e548eSAnton Blanchard 	if (!sock)
2040228e548eSAnton Blanchard 		goto out;
2041228e548eSAnton Blanchard 
2042c71d8ebeSTetsuo Handa 	err = __sys_sendmsg(sock, msg, &msg_sys, flags, NULL);
2043228e548eSAnton Blanchard 
20446cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
20451da177e4SLinus Torvalds out:
20461da177e4SLinus Torvalds 	return err;
20471da177e4SLinus Torvalds }
20481da177e4SLinus Torvalds 
2049228e548eSAnton Blanchard /*
2050228e548eSAnton Blanchard  *	Linux sendmmsg interface
2051228e548eSAnton Blanchard  */
2052228e548eSAnton Blanchard 
2053228e548eSAnton Blanchard int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2054228e548eSAnton Blanchard 		   unsigned int flags)
2055228e548eSAnton Blanchard {
2056228e548eSAnton Blanchard 	int fput_needed, err, datagrams;
2057228e548eSAnton Blanchard 	struct socket *sock;
2058228e548eSAnton Blanchard 	struct mmsghdr __user *entry;
2059228e548eSAnton Blanchard 	struct compat_mmsghdr __user *compat_entry;
2060228e548eSAnton Blanchard 	struct msghdr msg_sys;
2061c71d8ebeSTetsuo Handa 	struct used_address used_address;
2062228e548eSAnton Blanchard 
206398382f41SAnton Blanchard 	if (vlen > UIO_MAXIOV)
206498382f41SAnton Blanchard 		vlen = UIO_MAXIOV;
2065228e548eSAnton Blanchard 
2066228e548eSAnton Blanchard 	datagrams = 0;
2067228e548eSAnton Blanchard 
2068228e548eSAnton Blanchard 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2069228e548eSAnton Blanchard 	if (!sock)
2070228e548eSAnton Blanchard 		return err;
2071228e548eSAnton Blanchard 
2072c71d8ebeSTetsuo Handa 	used_address.name_len = UINT_MAX;
2073228e548eSAnton Blanchard 	entry = mmsg;
2074228e548eSAnton Blanchard 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2075728ffb86SAnton Blanchard 	err = 0;
2076228e548eSAnton Blanchard 
2077228e548eSAnton Blanchard 	while (datagrams < vlen) {
2078228e548eSAnton Blanchard 		if (MSG_CMSG_COMPAT & flags) {
2079228e548eSAnton Blanchard 			err = __sys_sendmsg(sock, (struct msghdr __user *)compat_entry,
2080c71d8ebeSTetsuo Handa 					    &msg_sys, flags, &used_address);
2081228e548eSAnton Blanchard 			if (err < 0)
2082228e548eSAnton Blanchard 				break;
2083228e548eSAnton Blanchard 			err = __put_user(err, &compat_entry->msg_len);
2084228e548eSAnton Blanchard 			++compat_entry;
2085228e548eSAnton Blanchard 		} else {
2086228e548eSAnton Blanchard 			err = __sys_sendmsg(sock, (struct msghdr __user *)entry,
2087c71d8ebeSTetsuo Handa 					    &msg_sys, flags, &used_address);
2088228e548eSAnton Blanchard 			if (err < 0)
2089228e548eSAnton Blanchard 				break;
2090228e548eSAnton Blanchard 			err = put_user(err, &entry->msg_len);
2091228e548eSAnton Blanchard 			++entry;
2092228e548eSAnton Blanchard 		}
2093228e548eSAnton Blanchard 
2094228e548eSAnton Blanchard 		if (err)
2095228e548eSAnton Blanchard 			break;
2096228e548eSAnton Blanchard 		++datagrams;
2097228e548eSAnton Blanchard 	}
2098228e548eSAnton Blanchard 
2099228e548eSAnton Blanchard 	fput_light(sock->file, fput_needed);
2100228e548eSAnton Blanchard 
2101728ffb86SAnton Blanchard 	/* We only return an error if no datagrams were able to be sent */
2102728ffb86SAnton Blanchard 	if (datagrams != 0)
2103228e548eSAnton Blanchard 		return datagrams;
2104228e548eSAnton Blanchard 
2105228e548eSAnton Blanchard 	return err;
2106228e548eSAnton Blanchard }
2107228e548eSAnton Blanchard 
2108228e548eSAnton Blanchard SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
2109228e548eSAnton Blanchard 		unsigned int, vlen, unsigned int, flags)
2110228e548eSAnton Blanchard {
2111228e548eSAnton Blanchard 	return __sys_sendmmsg(fd, mmsg, vlen, flags);
2112228e548eSAnton Blanchard }
2113228e548eSAnton Blanchard 
2114a2e27255SArnaldo Carvalho de Melo static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
211595c96174SEric Dumazet 			 struct msghdr *msg_sys, unsigned int flags, int nosec)
21161da177e4SLinus Torvalds {
211789bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
211889bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
21191da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV];
21201da177e4SLinus Torvalds 	struct iovec *iov = iovstack;
21211da177e4SLinus Torvalds 	unsigned long cmsg_ptr;
2122a74e9106SEric Dumazet 	int err, total_len, len;
21231da177e4SLinus Torvalds 
21241da177e4SLinus Torvalds 	/* kernel mode address */
2125230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage addr;
21261da177e4SLinus Torvalds 
21271da177e4SLinus Torvalds 	/* user mode address pointers */
21281da177e4SLinus Torvalds 	struct sockaddr __user *uaddr;
21291da177e4SLinus Torvalds 	int __user *uaddr_len;
21301da177e4SLinus Torvalds 
21311da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
2132a2e27255SArnaldo Carvalho de Melo 		if (get_compat_msghdr(msg_sys, msg_compat))
21331da177e4SLinus Torvalds 			return -EFAULT;
2134c6d409cfSEric Dumazet 	} else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr)))
21351da177e4SLinus Torvalds 		return -EFAULT;
21361da177e4SLinus Torvalds 
2137a74e9106SEric Dumazet 	if (msg_sys->msg_iovlen > UIO_FASTIOV) {
21381da177e4SLinus Torvalds 		err = -EMSGSIZE;
2139a2e27255SArnaldo Carvalho de Melo 		if (msg_sys->msg_iovlen > UIO_MAXIOV)
2140a2e27255SArnaldo Carvalho de Melo 			goto out;
21411da177e4SLinus Torvalds 		err = -ENOMEM;
2142a74e9106SEric Dumazet 		iov = kmalloc(msg_sys->msg_iovlen * sizeof(struct iovec),
2143a74e9106SEric Dumazet 			      GFP_KERNEL);
21441da177e4SLinus Torvalds 		if (!iov)
2145a2e27255SArnaldo Carvalho de Melo 			goto out;
21461da177e4SLinus Torvalds 	}
21471da177e4SLinus Torvalds 
21481da177e4SLinus Torvalds 	/*
21491da177e4SLinus Torvalds 	 *      Save the user-mode address (verify_iovec will change the
21501da177e4SLinus Torvalds 	 *      kernel msghdr to use the kernel address space)
21511da177e4SLinus Torvalds 	 */
21521da177e4SLinus Torvalds 
2153a2e27255SArnaldo Carvalho de Melo 	uaddr = (__force void __user *)msg_sys->msg_name;
21541da177e4SLinus Torvalds 	uaddr_len = COMPAT_NAMELEN(msg);
21551da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
215643db362dSMaciej Żenczykowski 		err = verify_compat_iovec(msg_sys, iov, &addr, VERIFY_WRITE);
21571da177e4SLinus Torvalds 	} else
215843db362dSMaciej Żenczykowski 		err = verify_iovec(msg_sys, iov, &addr, VERIFY_WRITE);
21591da177e4SLinus Torvalds 	if (err < 0)
21601da177e4SLinus Torvalds 		goto out_freeiov;
21611da177e4SLinus Torvalds 	total_len = err;
21621da177e4SLinus Torvalds 
2163a2e27255SArnaldo Carvalho de Melo 	cmsg_ptr = (unsigned long)msg_sys->msg_control;
2164a2e27255SArnaldo Carvalho de Melo 	msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
21651da177e4SLinus Torvalds 
21661da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
21671da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
2168a2e27255SArnaldo Carvalho de Melo 	err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys,
2169a2e27255SArnaldo Carvalho de Melo 							  total_len, flags);
21701da177e4SLinus Torvalds 	if (err < 0)
21711da177e4SLinus Torvalds 		goto out_freeiov;
21721da177e4SLinus Torvalds 	len = err;
21731da177e4SLinus Torvalds 
21741da177e4SLinus Torvalds 	if (uaddr != NULL) {
217543db362dSMaciej Żenczykowski 		err = move_addr_to_user(&addr,
2176a2e27255SArnaldo Carvalho de Melo 					msg_sys->msg_namelen, uaddr,
217789bddce5SStephen Hemminger 					uaddr_len);
21781da177e4SLinus Torvalds 		if (err < 0)
21791da177e4SLinus Torvalds 			goto out_freeiov;
21801da177e4SLinus Torvalds 	}
2181a2e27255SArnaldo Carvalho de Melo 	err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
218237f7f421SDavid S. Miller 			 COMPAT_FLAGS(msg));
21831da177e4SLinus Torvalds 	if (err)
21841da177e4SLinus Torvalds 		goto out_freeiov;
21851da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags)
2186a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
21871da177e4SLinus Torvalds 				 &msg_compat->msg_controllen);
21881da177e4SLinus Torvalds 	else
2189a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
21901da177e4SLinus Torvalds 				 &msg->msg_controllen);
21911da177e4SLinus Torvalds 	if (err)
21921da177e4SLinus Torvalds 		goto out_freeiov;
21931da177e4SLinus Torvalds 	err = len;
21941da177e4SLinus Torvalds 
21951da177e4SLinus Torvalds out_freeiov:
21961da177e4SLinus Torvalds 	if (iov != iovstack)
2197a74e9106SEric Dumazet 		kfree(iov);
2198a2e27255SArnaldo Carvalho de Melo out:
2199a2e27255SArnaldo Carvalho de Melo 	return err;
2200a2e27255SArnaldo Carvalho de Melo }
2201a2e27255SArnaldo Carvalho de Melo 
2202a2e27255SArnaldo Carvalho de Melo /*
2203a2e27255SArnaldo Carvalho de Melo  *	BSD recvmsg interface
2204a2e27255SArnaldo Carvalho de Melo  */
2205a2e27255SArnaldo Carvalho de Melo 
2206a2e27255SArnaldo Carvalho de Melo SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg,
2207a2e27255SArnaldo Carvalho de Melo 		unsigned int, flags)
2208a2e27255SArnaldo Carvalho de Melo {
2209a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err;
2210a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
2211a2e27255SArnaldo Carvalho de Melo 	struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed);
2212a2e27255SArnaldo Carvalho de Melo 
2213a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2214a2e27255SArnaldo Carvalho de Melo 		goto out;
2215a2e27255SArnaldo Carvalho de Melo 
2216a2e27255SArnaldo Carvalho de Melo 	err = __sys_recvmsg(sock, msg, &msg_sys, flags, 0);
2217a2e27255SArnaldo Carvalho de Melo 
22186cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
22191da177e4SLinus Torvalds out:
22201da177e4SLinus Torvalds 	return err;
22211da177e4SLinus Torvalds }
22221da177e4SLinus Torvalds 
2223a2e27255SArnaldo Carvalho de Melo /*
2224a2e27255SArnaldo Carvalho de Melo  *     Linux recvmmsg interface
2225a2e27255SArnaldo Carvalho de Melo  */
22261da177e4SLinus Torvalds 
2227a2e27255SArnaldo Carvalho de Melo int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2228a2e27255SArnaldo Carvalho de Melo 		   unsigned int flags, struct timespec *timeout)
2229a2e27255SArnaldo Carvalho de Melo {
2230a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err, datagrams;
2231a2e27255SArnaldo Carvalho de Melo 	struct socket *sock;
2232a2e27255SArnaldo Carvalho de Melo 	struct mmsghdr __user *entry;
2233d7256d0eSJean-Mickael Guerin 	struct compat_mmsghdr __user *compat_entry;
2234a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
2235a2e27255SArnaldo Carvalho de Melo 	struct timespec end_time;
2236a2e27255SArnaldo Carvalho de Melo 
2237a2e27255SArnaldo Carvalho de Melo 	if (timeout &&
2238a2e27255SArnaldo Carvalho de Melo 	    poll_select_set_timeout(&end_time, timeout->tv_sec,
2239a2e27255SArnaldo Carvalho de Melo 				    timeout->tv_nsec))
2240a2e27255SArnaldo Carvalho de Melo 		return -EINVAL;
2241a2e27255SArnaldo Carvalho de Melo 
2242a2e27255SArnaldo Carvalho de Melo 	datagrams = 0;
2243a2e27255SArnaldo Carvalho de Melo 
2244a2e27255SArnaldo Carvalho de Melo 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2245a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2246a2e27255SArnaldo Carvalho de Melo 		return err;
2247a2e27255SArnaldo Carvalho de Melo 
2248a2e27255SArnaldo Carvalho de Melo 	err = sock_error(sock->sk);
2249a2e27255SArnaldo Carvalho de Melo 	if (err)
2250a2e27255SArnaldo Carvalho de Melo 		goto out_put;
2251a2e27255SArnaldo Carvalho de Melo 
2252a2e27255SArnaldo Carvalho de Melo 	entry = mmsg;
2253d7256d0eSJean-Mickael Guerin 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2254a2e27255SArnaldo Carvalho de Melo 
2255a2e27255SArnaldo Carvalho de Melo 	while (datagrams < vlen) {
2256a2e27255SArnaldo Carvalho de Melo 		/*
2257a2e27255SArnaldo Carvalho de Melo 		 * No need to ask LSM for more than the first datagram.
2258a2e27255SArnaldo Carvalho de Melo 		 */
2259d7256d0eSJean-Mickael Guerin 		if (MSG_CMSG_COMPAT & flags) {
2260d7256d0eSJean-Mickael Guerin 			err = __sys_recvmsg(sock, (struct msghdr __user *)compat_entry,
2261b9eb8b87SAnton Blanchard 					    &msg_sys, flags & ~MSG_WAITFORONE,
2262b9eb8b87SAnton Blanchard 					    datagrams);
2263d7256d0eSJean-Mickael Guerin 			if (err < 0)
2264d7256d0eSJean-Mickael Guerin 				break;
2265d7256d0eSJean-Mickael Guerin 			err = __put_user(err, &compat_entry->msg_len);
2266d7256d0eSJean-Mickael Guerin 			++compat_entry;
2267d7256d0eSJean-Mickael Guerin 		} else {
2268a2e27255SArnaldo Carvalho de Melo 			err = __sys_recvmsg(sock, (struct msghdr __user *)entry,
2269b9eb8b87SAnton Blanchard 					    &msg_sys, flags & ~MSG_WAITFORONE,
2270b9eb8b87SAnton Blanchard 					    datagrams);
2271a2e27255SArnaldo Carvalho de Melo 			if (err < 0)
2272a2e27255SArnaldo Carvalho de Melo 				break;
2273a2e27255SArnaldo Carvalho de Melo 			err = put_user(err, &entry->msg_len);
2274d7256d0eSJean-Mickael Guerin 			++entry;
2275d7256d0eSJean-Mickael Guerin 		}
2276d7256d0eSJean-Mickael Guerin 
2277a2e27255SArnaldo Carvalho de Melo 		if (err)
2278a2e27255SArnaldo Carvalho de Melo 			break;
2279a2e27255SArnaldo Carvalho de Melo 		++datagrams;
2280a2e27255SArnaldo Carvalho de Melo 
228171c5c159SBrandon L Black 		/* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
228271c5c159SBrandon L Black 		if (flags & MSG_WAITFORONE)
228371c5c159SBrandon L Black 			flags |= MSG_DONTWAIT;
228471c5c159SBrandon L Black 
2285a2e27255SArnaldo Carvalho de Melo 		if (timeout) {
2286a2e27255SArnaldo Carvalho de Melo 			ktime_get_ts(timeout);
2287a2e27255SArnaldo Carvalho de Melo 			*timeout = timespec_sub(end_time, *timeout);
2288a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_sec < 0) {
2289a2e27255SArnaldo Carvalho de Melo 				timeout->tv_sec = timeout->tv_nsec = 0;
2290a2e27255SArnaldo Carvalho de Melo 				break;
2291a2e27255SArnaldo Carvalho de Melo 			}
2292a2e27255SArnaldo Carvalho de Melo 
2293a2e27255SArnaldo Carvalho de Melo 			/* Timeout, return less than vlen datagrams */
2294a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_nsec == 0 && timeout->tv_sec == 0)
2295a2e27255SArnaldo Carvalho de Melo 				break;
2296a2e27255SArnaldo Carvalho de Melo 		}
2297a2e27255SArnaldo Carvalho de Melo 
2298a2e27255SArnaldo Carvalho de Melo 		/* Out of band data, return right away */
2299a2e27255SArnaldo Carvalho de Melo 		if (msg_sys.msg_flags & MSG_OOB)
2300a2e27255SArnaldo Carvalho de Melo 			break;
2301a2e27255SArnaldo Carvalho de Melo 	}
2302a2e27255SArnaldo Carvalho de Melo 
2303a2e27255SArnaldo Carvalho de Melo out_put:
2304a2e27255SArnaldo Carvalho de Melo 	fput_light(sock->file, fput_needed);
2305a2e27255SArnaldo Carvalho de Melo 
2306a2e27255SArnaldo Carvalho de Melo 	if (err == 0)
2307a2e27255SArnaldo Carvalho de Melo 		return datagrams;
2308a2e27255SArnaldo Carvalho de Melo 
2309a2e27255SArnaldo Carvalho de Melo 	if (datagrams != 0) {
2310a2e27255SArnaldo Carvalho de Melo 		/*
2311a2e27255SArnaldo Carvalho de Melo 		 * We may return less entries than requested (vlen) if the
2312a2e27255SArnaldo Carvalho de Melo 		 * sock is non block and there aren't enough datagrams...
2313a2e27255SArnaldo Carvalho de Melo 		 */
2314a2e27255SArnaldo Carvalho de Melo 		if (err != -EAGAIN) {
2315a2e27255SArnaldo Carvalho de Melo 			/*
2316a2e27255SArnaldo Carvalho de Melo 			 * ... or  if recvmsg returns an error after we
2317a2e27255SArnaldo Carvalho de Melo 			 * received some datagrams, where we record the
2318a2e27255SArnaldo Carvalho de Melo 			 * error to return on the next call or if the
2319a2e27255SArnaldo Carvalho de Melo 			 * app asks about it using getsockopt(SO_ERROR).
2320a2e27255SArnaldo Carvalho de Melo 			 */
2321a2e27255SArnaldo Carvalho de Melo 			sock->sk->sk_err = -err;
2322a2e27255SArnaldo Carvalho de Melo 		}
2323a2e27255SArnaldo Carvalho de Melo 
2324a2e27255SArnaldo Carvalho de Melo 		return datagrams;
2325a2e27255SArnaldo Carvalho de Melo 	}
2326a2e27255SArnaldo Carvalho de Melo 
2327a2e27255SArnaldo Carvalho de Melo 	return err;
2328a2e27255SArnaldo Carvalho de Melo }
2329a2e27255SArnaldo Carvalho de Melo 
2330a2e27255SArnaldo Carvalho de Melo SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
2331a2e27255SArnaldo Carvalho de Melo 		unsigned int, vlen, unsigned int, flags,
2332a2e27255SArnaldo Carvalho de Melo 		struct timespec __user *, timeout)
2333a2e27255SArnaldo Carvalho de Melo {
2334a2e27255SArnaldo Carvalho de Melo 	int datagrams;
2335a2e27255SArnaldo Carvalho de Melo 	struct timespec timeout_sys;
2336a2e27255SArnaldo Carvalho de Melo 
2337a2e27255SArnaldo Carvalho de Melo 	if (!timeout)
2338a2e27255SArnaldo Carvalho de Melo 		return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL);
2339a2e27255SArnaldo Carvalho de Melo 
2340a2e27255SArnaldo Carvalho de Melo 	if (copy_from_user(&timeout_sys, timeout, sizeof(timeout_sys)))
2341a2e27255SArnaldo Carvalho de Melo 		return -EFAULT;
2342a2e27255SArnaldo Carvalho de Melo 
2343a2e27255SArnaldo Carvalho de Melo 	datagrams = __sys_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys);
2344a2e27255SArnaldo Carvalho de Melo 
2345a2e27255SArnaldo Carvalho de Melo 	if (datagrams > 0 &&
2346a2e27255SArnaldo Carvalho de Melo 	    copy_to_user(timeout, &timeout_sys, sizeof(timeout_sys)))
2347a2e27255SArnaldo Carvalho de Melo 		datagrams = -EFAULT;
2348a2e27255SArnaldo Carvalho de Melo 
2349a2e27255SArnaldo Carvalho de Melo 	return datagrams;
2350a2e27255SArnaldo Carvalho de Melo }
2351a2e27255SArnaldo Carvalho de Melo 
2352a2e27255SArnaldo Carvalho de Melo #ifdef __ARCH_WANT_SYS_SOCKETCALL
23531da177e4SLinus Torvalds /* Argument list sizes for sys_socketcall */
23541da177e4SLinus Torvalds #define AL(x) ((x) * sizeof(unsigned long))
2355228e548eSAnton Blanchard static const unsigned char nargs[21] = {
235689bddce5SStephen Hemminger 	AL(0), AL(3), AL(3), AL(3), AL(2), AL(3),
23571da177e4SLinus Torvalds 	AL(3), AL(3), AL(4), AL(4), AL(4), AL(6),
2358aaca0bdcSUlrich Drepper 	AL(6), AL(2), AL(5), AL(5), AL(3), AL(3),
2359228e548eSAnton Blanchard 	AL(4), AL(5), AL(4)
236089bddce5SStephen Hemminger };
236189bddce5SStephen Hemminger 
23621da177e4SLinus Torvalds #undef AL
23631da177e4SLinus Torvalds 
23641da177e4SLinus Torvalds /*
23651da177e4SLinus Torvalds  *	System call vectors.
23661da177e4SLinus Torvalds  *
23671da177e4SLinus Torvalds  *	Argument checking cleaned up. Saved 20% in size.
23681da177e4SLinus Torvalds  *  This function doesn't need to set the kernel lock because
23691da177e4SLinus Torvalds  *  it is set by the callees.
23701da177e4SLinus Torvalds  */
23711da177e4SLinus Torvalds 
23723e0fa65fSHeiko Carstens SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
23731da177e4SLinus Torvalds {
23741da177e4SLinus Torvalds 	unsigned long a[6];
23751da177e4SLinus Torvalds 	unsigned long a0, a1;
23761da177e4SLinus Torvalds 	int err;
237747379052SArjan van de Ven 	unsigned int len;
23781da177e4SLinus Torvalds 
2379228e548eSAnton Blanchard 	if (call < 1 || call > SYS_SENDMMSG)
23801da177e4SLinus Torvalds 		return -EINVAL;
23811da177e4SLinus Torvalds 
238247379052SArjan van de Ven 	len = nargs[call];
238347379052SArjan van de Ven 	if (len > sizeof(a))
238447379052SArjan van de Ven 		return -EINVAL;
238547379052SArjan van de Ven 
23861da177e4SLinus Torvalds 	/* copy_from_user should be SMP safe. */
238747379052SArjan van de Ven 	if (copy_from_user(a, args, len))
23881da177e4SLinus Torvalds 		return -EFAULT;
23891da177e4SLinus Torvalds 
2390f3298dc4SAl Viro 	audit_socketcall(nargs[call] / sizeof(unsigned long), a);
23913ec3b2fbSDavid Woodhouse 
23921da177e4SLinus Torvalds 	a0 = a[0];
23931da177e4SLinus Torvalds 	a1 = a[1];
23941da177e4SLinus Torvalds 
239589bddce5SStephen Hemminger 	switch (call) {
23961da177e4SLinus Torvalds 	case SYS_SOCKET:
23971da177e4SLinus Torvalds 		err = sys_socket(a0, a1, a[2]);
23981da177e4SLinus Torvalds 		break;
23991da177e4SLinus Torvalds 	case SYS_BIND:
24001da177e4SLinus Torvalds 		err = sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
24011da177e4SLinus Torvalds 		break;
24021da177e4SLinus Torvalds 	case SYS_CONNECT:
24031da177e4SLinus Torvalds 		err = sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
24041da177e4SLinus Torvalds 		break;
24051da177e4SLinus Torvalds 	case SYS_LISTEN:
24061da177e4SLinus Torvalds 		err = sys_listen(a0, a1);
24071da177e4SLinus Torvalds 		break;
24081da177e4SLinus Torvalds 	case SYS_ACCEPT:
2409de11defeSUlrich Drepper 		err = sys_accept4(a0, (struct sockaddr __user *)a1,
2410aaca0bdcSUlrich Drepper 				  (int __user *)a[2], 0);
24111da177e4SLinus Torvalds 		break;
24121da177e4SLinus Torvalds 	case SYS_GETSOCKNAME:
241389bddce5SStephen Hemminger 		err =
241489bddce5SStephen Hemminger 		    sys_getsockname(a0, (struct sockaddr __user *)a1,
241589bddce5SStephen Hemminger 				    (int __user *)a[2]);
24161da177e4SLinus Torvalds 		break;
24171da177e4SLinus Torvalds 	case SYS_GETPEERNAME:
241889bddce5SStephen Hemminger 		err =
241989bddce5SStephen Hemminger 		    sys_getpeername(a0, (struct sockaddr __user *)a1,
242089bddce5SStephen Hemminger 				    (int __user *)a[2]);
24211da177e4SLinus Torvalds 		break;
24221da177e4SLinus Torvalds 	case SYS_SOCKETPAIR:
24231da177e4SLinus Torvalds 		err = sys_socketpair(a0, a1, a[2], (int __user *)a[3]);
24241da177e4SLinus Torvalds 		break;
24251da177e4SLinus Torvalds 	case SYS_SEND:
24261da177e4SLinus Torvalds 		err = sys_send(a0, (void __user *)a1, a[2], a[3]);
24271da177e4SLinus Torvalds 		break;
24281da177e4SLinus Torvalds 	case SYS_SENDTO:
24291da177e4SLinus Torvalds 		err = sys_sendto(a0, (void __user *)a1, a[2], a[3],
24301da177e4SLinus Torvalds 				 (struct sockaddr __user *)a[4], a[5]);
24311da177e4SLinus Torvalds 		break;
24321da177e4SLinus Torvalds 	case SYS_RECV:
24331da177e4SLinus Torvalds 		err = sys_recv(a0, (void __user *)a1, a[2], a[3]);
24341da177e4SLinus Torvalds 		break;
24351da177e4SLinus Torvalds 	case SYS_RECVFROM:
24361da177e4SLinus Torvalds 		err = sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
243789bddce5SStephen Hemminger 				   (struct sockaddr __user *)a[4],
243889bddce5SStephen Hemminger 				   (int __user *)a[5]);
24391da177e4SLinus Torvalds 		break;
24401da177e4SLinus Torvalds 	case SYS_SHUTDOWN:
24411da177e4SLinus Torvalds 		err = sys_shutdown(a0, a1);
24421da177e4SLinus Torvalds 		break;
24431da177e4SLinus Torvalds 	case SYS_SETSOCKOPT:
24441da177e4SLinus Torvalds 		err = sys_setsockopt(a0, a1, a[2], (char __user *)a[3], a[4]);
24451da177e4SLinus Torvalds 		break;
24461da177e4SLinus Torvalds 	case SYS_GETSOCKOPT:
244789bddce5SStephen Hemminger 		err =
244889bddce5SStephen Hemminger 		    sys_getsockopt(a0, a1, a[2], (char __user *)a[3],
244989bddce5SStephen Hemminger 				   (int __user *)a[4]);
24501da177e4SLinus Torvalds 		break;
24511da177e4SLinus Torvalds 	case SYS_SENDMSG:
24521da177e4SLinus Torvalds 		err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]);
24531da177e4SLinus Torvalds 		break;
2454228e548eSAnton Blanchard 	case SYS_SENDMMSG:
2455228e548eSAnton Blanchard 		err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]);
2456228e548eSAnton Blanchard 		break;
24571da177e4SLinus Torvalds 	case SYS_RECVMSG:
24581da177e4SLinus Torvalds 		err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]);
24591da177e4SLinus Torvalds 		break;
2460a2e27255SArnaldo Carvalho de Melo 	case SYS_RECVMMSG:
2461a2e27255SArnaldo Carvalho de Melo 		err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3],
2462a2e27255SArnaldo Carvalho de Melo 				   (struct timespec __user *)a[4]);
2463a2e27255SArnaldo Carvalho de Melo 		break;
2464de11defeSUlrich Drepper 	case SYS_ACCEPT4:
2465de11defeSUlrich Drepper 		err = sys_accept4(a0, (struct sockaddr __user *)a1,
2466de11defeSUlrich Drepper 				  (int __user *)a[2], a[3]);
2467aaca0bdcSUlrich Drepper 		break;
24681da177e4SLinus Torvalds 	default:
24691da177e4SLinus Torvalds 		err = -EINVAL;
24701da177e4SLinus Torvalds 		break;
24711da177e4SLinus Torvalds 	}
24721da177e4SLinus Torvalds 	return err;
24731da177e4SLinus Torvalds }
24741da177e4SLinus Torvalds 
24751da177e4SLinus Torvalds #endif				/* __ARCH_WANT_SYS_SOCKETCALL */
24761da177e4SLinus Torvalds 
247755737fdaSStephen Hemminger /**
247855737fdaSStephen Hemminger  *	sock_register - add a socket protocol handler
247955737fdaSStephen Hemminger  *	@ops: description of protocol
248055737fdaSStephen Hemminger  *
24811da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
24821da177e4SLinus Torvalds  *	advertise its address family, and have it linked into the
248355737fdaSStephen Hemminger  *	socket interface. The value ops->family coresponds to the
248455737fdaSStephen Hemminger  *	socket system call protocol family.
24851da177e4SLinus Torvalds  */
2486f0fd27d4SStephen Hemminger int sock_register(const struct net_proto_family *ops)
24871da177e4SLinus Torvalds {
24881da177e4SLinus Torvalds 	int err;
24891da177e4SLinus Torvalds 
24901da177e4SLinus Torvalds 	if (ops->family >= NPROTO) {
249189bddce5SStephen Hemminger 		printk(KERN_CRIT "protocol %d >= NPROTO(%d)\n", ops->family,
249289bddce5SStephen Hemminger 		       NPROTO);
24931da177e4SLinus Torvalds 		return -ENOBUFS;
24941da177e4SLinus Torvalds 	}
249555737fdaSStephen Hemminger 
249655737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2497190683a9SEric Dumazet 	if (rcu_dereference_protected(net_families[ops->family],
2498190683a9SEric Dumazet 				      lockdep_is_held(&net_family_lock)))
24991da177e4SLinus Torvalds 		err = -EEXIST;
250055737fdaSStephen Hemminger 	else {
2501cf778b00SEric Dumazet 		rcu_assign_pointer(net_families[ops->family], ops);
25021da177e4SLinus Torvalds 		err = 0;
25031da177e4SLinus Torvalds 	}
250455737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
250555737fdaSStephen Hemminger 
250689bddce5SStephen Hemminger 	printk(KERN_INFO "NET: Registered protocol family %d\n", ops->family);
25071da177e4SLinus Torvalds 	return err;
25081da177e4SLinus Torvalds }
2509c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_register);
25101da177e4SLinus Torvalds 
251155737fdaSStephen Hemminger /**
251255737fdaSStephen Hemminger  *	sock_unregister - remove a protocol handler
251355737fdaSStephen Hemminger  *	@family: protocol family to remove
251455737fdaSStephen Hemminger  *
25151da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
25161da177e4SLinus Torvalds  *	remove its address family, and have it unlinked from the
251755737fdaSStephen Hemminger  *	new socket creation.
251855737fdaSStephen Hemminger  *
251955737fdaSStephen Hemminger  *	If protocol handler is a module, then it can use module reference
252055737fdaSStephen Hemminger  *	counts to protect against new references. If protocol handler is not
252155737fdaSStephen Hemminger  *	a module then it needs to provide its own protection in
252255737fdaSStephen Hemminger  *	the ops->create routine.
25231da177e4SLinus Torvalds  */
2524f0fd27d4SStephen Hemminger void sock_unregister(int family)
25251da177e4SLinus Torvalds {
2526f0fd27d4SStephen Hemminger 	BUG_ON(family < 0 || family >= NPROTO);
25271da177e4SLinus Torvalds 
252855737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2529a9b3cd7fSStephen Hemminger 	RCU_INIT_POINTER(net_families[family], NULL);
253055737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
253155737fdaSStephen Hemminger 
253255737fdaSStephen Hemminger 	synchronize_rcu();
253355737fdaSStephen Hemminger 
253489bddce5SStephen Hemminger 	printk(KERN_INFO "NET: Unregistered protocol family %d\n", family);
25351da177e4SLinus Torvalds }
2536c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_unregister);
25371da177e4SLinus Torvalds 
253877d76ea3SAndi Kleen static int __init sock_init(void)
25391da177e4SLinus Torvalds {
2540b3e19d92SNick Piggin 	int err;
25412ca794e5SEric W. Biederman 	/*
25422ca794e5SEric W. Biederman 	 *      Initialize the network sysctl infrastructure.
25432ca794e5SEric W. Biederman 	 */
25442ca794e5SEric W. Biederman 	err = net_sysctl_init();
25452ca794e5SEric W. Biederman 	if (err)
25462ca794e5SEric W. Biederman 		goto out;
2547b3e19d92SNick Piggin 
25481da177e4SLinus Torvalds 	/*
25491da177e4SLinus Torvalds 	 *      Initialize sock SLAB cache.
25501da177e4SLinus Torvalds 	 */
25511da177e4SLinus Torvalds 
25521da177e4SLinus Torvalds 	sk_init();
25531da177e4SLinus Torvalds 
25541da177e4SLinus Torvalds 	/*
25551da177e4SLinus Torvalds 	 *      Initialize skbuff SLAB cache
25561da177e4SLinus Torvalds 	 */
25571da177e4SLinus Torvalds 	skb_init();
25581da177e4SLinus Torvalds 
25591da177e4SLinus Torvalds 	/*
25601da177e4SLinus Torvalds 	 *      Initialize the protocols module.
25611da177e4SLinus Torvalds 	 */
25621da177e4SLinus Torvalds 
25631da177e4SLinus Torvalds 	init_inodecache();
2564b3e19d92SNick Piggin 
2565b3e19d92SNick Piggin 	err = register_filesystem(&sock_fs_type);
2566b3e19d92SNick Piggin 	if (err)
2567b3e19d92SNick Piggin 		goto out_fs;
25681da177e4SLinus Torvalds 	sock_mnt = kern_mount(&sock_fs_type);
2569b3e19d92SNick Piggin 	if (IS_ERR(sock_mnt)) {
2570b3e19d92SNick Piggin 		err = PTR_ERR(sock_mnt);
2571b3e19d92SNick Piggin 		goto out_mount;
2572b3e19d92SNick Piggin 	}
257377d76ea3SAndi Kleen 
257477d76ea3SAndi Kleen 	/* The real protocol initialization is performed in later initcalls.
25751da177e4SLinus Torvalds 	 */
25761da177e4SLinus Torvalds 
25771da177e4SLinus Torvalds #ifdef CONFIG_NETFILTER
25781da177e4SLinus Torvalds 	netfilter_init();
25791da177e4SLinus Torvalds #endif
2580cbeb321aSDavid S. Miller 
2581c1f19b51SRichard Cochran #ifdef CONFIG_NETWORK_PHY_TIMESTAMPING
2582c1f19b51SRichard Cochran 	skb_timestamping_init();
2583c1f19b51SRichard Cochran #endif
2584c1f19b51SRichard Cochran 
2585b3e19d92SNick Piggin out:
2586b3e19d92SNick Piggin 	return err;
2587b3e19d92SNick Piggin 
2588b3e19d92SNick Piggin out_mount:
2589b3e19d92SNick Piggin 	unregister_filesystem(&sock_fs_type);
2590b3e19d92SNick Piggin out_fs:
2591b3e19d92SNick Piggin 	goto out;
25921da177e4SLinus Torvalds }
25931da177e4SLinus Torvalds 
259477d76ea3SAndi Kleen core_initcall(sock_init);	/* early initcall */
259577d76ea3SAndi Kleen 
25961da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS
25971da177e4SLinus Torvalds void socket_seq_show(struct seq_file *seq)
25981da177e4SLinus Torvalds {
25991da177e4SLinus Torvalds 	int cpu;
26001da177e4SLinus Torvalds 	int counter = 0;
26011da177e4SLinus Torvalds 
26026f912042SKAMEZAWA Hiroyuki 	for_each_possible_cpu(cpu)
26031da177e4SLinus Torvalds 	    counter += per_cpu(sockets_in_use, cpu);
26041da177e4SLinus Torvalds 
26051da177e4SLinus Torvalds 	/* It can be negative, by the way. 8) */
26061da177e4SLinus Torvalds 	if (counter < 0)
26071da177e4SLinus Torvalds 		counter = 0;
26081da177e4SLinus Torvalds 
26091da177e4SLinus Torvalds 	seq_printf(seq, "sockets: used %d\n", counter);
26101da177e4SLinus Torvalds }
26111da177e4SLinus Torvalds #endif				/* CONFIG_PROC_FS */
26121da177e4SLinus Torvalds 
261389bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
26146b96018bSArnd Bergmann static int do_siocgstamp(struct net *net, struct socket *sock,
2615644595f8SH. Peter Anvin 			 unsigned int cmd, void __user *up)
26167a229387SArnd Bergmann {
26177a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
26187a229387SArnd Bergmann 	struct timeval ktv;
26197a229387SArnd Bergmann 	int err;
26207a229387SArnd Bergmann 
26217a229387SArnd Bergmann 	set_fs(KERNEL_DS);
26226b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv);
26237a229387SArnd Bergmann 	set_fs(old_fs);
2624644595f8SH. Peter Anvin 	if (!err)
2625ed6fe9d6SMikulas Patocka 		err = compat_put_timeval(&ktv, up);
2626644595f8SH. Peter Anvin 
26277a229387SArnd Bergmann 	return err;
26287a229387SArnd Bergmann }
26297a229387SArnd Bergmann 
26306b96018bSArnd Bergmann static int do_siocgstampns(struct net *net, struct socket *sock,
2631644595f8SH. Peter Anvin 			   unsigned int cmd, void __user *up)
26327a229387SArnd Bergmann {
26337a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
26347a229387SArnd Bergmann 	struct timespec kts;
26357a229387SArnd Bergmann 	int err;
26367a229387SArnd Bergmann 
26377a229387SArnd Bergmann 	set_fs(KERNEL_DS);
26386b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts);
26397a229387SArnd Bergmann 	set_fs(old_fs);
2640644595f8SH. Peter Anvin 	if (!err)
2641ed6fe9d6SMikulas Patocka 		err = compat_put_timespec(&kts, up);
2642644595f8SH. Peter Anvin 
26437a229387SArnd Bergmann 	return err;
26447a229387SArnd Bergmann }
26457a229387SArnd Bergmann 
26466b96018bSArnd Bergmann static int dev_ifname32(struct net *net, struct compat_ifreq __user *uifr32)
26477a229387SArnd Bergmann {
26487a229387SArnd Bergmann 	struct ifreq __user *uifr;
26497a229387SArnd Bergmann 	int err;
26507a229387SArnd Bergmann 
26517a229387SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(struct ifreq));
26526b96018bSArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
26537a229387SArnd Bergmann 		return -EFAULT;
26547a229387SArnd Bergmann 
26556b96018bSArnd Bergmann 	err = dev_ioctl(net, SIOCGIFNAME, uifr);
26567a229387SArnd Bergmann 	if (err)
26577a229387SArnd Bergmann 		return err;
26587a229387SArnd Bergmann 
26596b96018bSArnd Bergmann 	if (copy_in_user(uifr32, uifr, sizeof(struct compat_ifreq)))
26607a229387SArnd Bergmann 		return -EFAULT;
26617a229387SArnd Bergmann 
26627a229387SArnd Bergmann 	return 0;
26637a229387SArnd Bergmann }
26647a229387SArnd Bergmann 
26656b96018bSArnd Bergmann static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32)
26667a229387SArnd Bergmann {
26676b96018bSArnd Bergmann 	struct compat_ifconf ifc32;
26687a229387SArnd Bergmann 	struct ifconf ifc;
26697a229387SArnd Bergmann 	struct ifconf __user *uifc;
26706b96018bSArnd Bergmann 	struct compat_ifreq __user *ifr32;
26717a229387SArnd Bergmann 	struct ifreq __user *ifr;
26727a229387SArnd Bergmann 	unsigned int i, j;
26737a229387SArnd Bergmann 	int err;
26747a229387SArnd Bergmann 
26756b96018bSArnd Bergmann 	if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf)))
26767a229387SArnd Bergmann 		return -EFAULT;
26777a229387SArnd Bergmann 
267843da5f2eSMathias Krause 	memset(&ifc, 0, sizeof(ifc));
26797a229387SArnd Bergmann 	if (ifc32.ifcbuf == 0) {
26807a229387SArnd Bergmann 		ifc32.ifc_len = 0;
26817a229387SArnd Bergmann 		ifc.ifc_len = 0;
26827a229387SArnd Bergmann 		ifc.ifc_req = NULL;
26837a229387SArnd Bergmann 		uifc = compat_alloc_user_space(sizeof(struct ifconf));
26847a229387SArnd Bergmann 	} else {
26856b96018bSArnd Bergmann 		size_t len = ((ifc32.ifc_len / sizeof(struct compat_ifreq)) + 1) *
26867a229387SArnd Bergmann 			sizeof(struct ifreq);
26877a229387SArnd Bergmann 		uifc = compat_alloc_user_space(sizeof(struct ifconf) + len);
26887a229387SArnd Bergmann 		ifc.ifc_len = len;
26897a229387SArnd Bergmann 		ifr = ifc.ifc_req = (void __user *)(uifc + 1);
26907a229387SArnd Bergmann 		ifr32 = compat_ptr(ifc32.ifcbuf);
26916b96018bSArnd Bergmann 		for (i = 0; i < ifc32.ifc_len; i += sizeof(struct compat_ifreq)) {
26926b96018bSArnd Bergmann 			if (copy_in_user(ifr, ifr32, sizeof(struct compat_ifreq)))
26937a229387SArnd Bergmann 				return -EFAULT;
26947a229387SArnd Bergmann 			ifr++;
26957a229387SArnd Bergmann 			ifr32++;
26967a229387SArnd Bergmann 		}
26977a229387SArnd Bergmann 	}
26987a229387SArnd Bergmann 	if (copy_to_user(uifc, &ifc, sizeof(struct ifconf)))
26997a229387SArnd Bergmann 		return -EFAULT;
27007a229387SArnd Bergmann 
27016b96018bSArnd Bergmann 	err = dev_ioctl(net, SIOCGIFCONF, uifc);
27027a229387SArnd Bergmann 	if (err)
27037a229387SArnd Bergmann 		return err;
27047a229387SArnd Bergmann 
27057a229387SArnd Bergmann 	if (copy_from_user(&ifc, uifc, sizeof(struct ifconf)))
27067a229387SArnd Bergmann 		return -EFAULT;
27077a229387SArnd Bergmann 
27087a229387SArnd Bergmann 	ifr = ifc.ifc_req;
27097a229387SArnd Bergmann 	ifr32 = compat_ptr(ifc32.ifcbuf);
27107a229387SArnd Bergmann 	for (i = 0, j = 0;
27116b96018bSArnd Bergmann 	     i + sizeof(struct compat_ifreq) <= ifc32.ifc_len && j < ifc.ifc_len;
27126b96018bSArnd Bergmann 	     i += sizeof(struct compat_ifreq), j += sizeof(struct ifreq)) {
27136b96018bSArnd Bergmann 		if (copy_in_user(ifr32, ifr, sizeof(struct compat_ifreq)))
27147a229387SArnd Bergmann 			return -EFAULT;
27157a229387SArnd Bergmann 		ifr32++;
27167a229387SArnd Bergmann 		ifr++;
27177a229387SArnd Bergmann 	}
27187a229387SArnd Bergmann 
27197a229387SArnd Bergmann 	if (ifc32.ifcbuf == 0) {
27207a229387SArnd Bergmann 		/* Translate from 64-bit structure multiple to
27217a229387SArnd Bergmann 		 * a 32-bit one.
27227a229387SArnd Bergmann 		 */
27237a229387SArnd Bergmann 		i = ifc.ifc_len;
27246b96018bSArnd Bergmann 		i = ((i / sizeof(struct ifreq)) * sizeof(struct compat_ifreq));
27257a229387SArnd Bergmann 		ifc32.ifc_len = i;
27267a229387SArnd Bergmann 	} else {
27277a229387SArnd Bergmann 		ifc32.ifc_len = i;
27287a229387SArnd Bergmann 	}
27296b96018bSArnd Bergmann 	if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf)))
27307a229387SArnd Bergmann 		return -EFAULT;
27317a229387SArnd Bergmann 
27327a229387SArnd Bergmann 	return 0;
27337a229387SArnd Bergmann }
27347a229387SArnd Bergmann 
27356b96018bSArnd Bergmann static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
27367a229387SArnd Bergmann {
27373a7da39dSBen Hutchings 	struct compat_ethtool_rxnfc __user *compat_rxnfc;
27383a7da39dSBen Hutchings 	bool convert_in = false, convert_out = false;
27393a7da39dSBen Hutchings 	size_t buf_size = ALIGN(sizeof(struct ifreq), 8);
27403a7da39dSBen Hutchings 	struct ethtool_rxnfc __user *rxnfc;
27417a229387SArnd Bergmann 	struct ifreq __user *ifr;
27423a7da39dSBen Hutchings 	u32 rule_cnt = 0, actual_rule_cnt;
27433a7da39dSBen Hutchings 	u32 ethcmd;
27447a229387SArnd Bergmann 	u32 data;
27453a7da39dSBen Hutchings 	int ret;
27467a229387SArnd Bergmann 
27477a229387SArnd Bergmann 	if (get_user(data, &ifr32->ifr_ifru.ifru_data))
27487a229387SArnd Bergmann 		return -EFAULT;
27497a229387SArnd Bergmann 
27503a7da39dSBen Hutchings 	compat_rxnfc = compat_ptr(data);
27513a7da39dSBen Hutchings 
27523a7da39dSBen Hutchings 	if (get_user(ethcmd, &compat_rxnfc->cmd))
27537a229387SArnd Bergmann 		return -EFAULT;
27547a229387SArnd Bergmann 
27553a7da39dSBen Hutchings 	/* Most ethtool structures are defined without padding.
27563a7da39dSBen Hutchings 	 * Unfortunately struct ethtool_rxnfc is an exception.
27573a7da39dSBen Hutchings 	 */
27583a7da39dSBen Hutchings 	switch (ethcmd) {
27593a7da39dSBen Hutchings 	default:
27603a7da39dSBen Hutchings 		break;
27613a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLALL:
27623a7da39dSBen Hutchings 		/* Buffer size is variable */
27633a7da39dSBen Hutchings 		if (get_user(rule_cnt, &compat_rxnfc->rule_cnt))
27643a7da39dSBen Hutchings 			return -EFAULT;
27653a7da39dSBen Hutchings 		if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32))
27663a7da39dSBen Hutchings 			return -ENOMEM;
27673a7da39dSBen Hutchings 		buf_size += rule_cnt * sizeof(u32);
27683a7da39dSBen Hutchings 		/* fall through */
27693a7da39dSBen Hutchings 	case ETHTOOL_GRXRINGS:
27703a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLCNT:
27713a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRULE:
277255664f32SBen Hutchings 	case ETHTOOL_SRXCLSRLINS:
27733a7da39dSBen Hutchings 		convert_out = true;
27743a7da39dSBen Hutchings 		/* fall through */
27753a7da39dSBen Hutchings 	case ETHTOOL_SRXCLSRLDEL:
27763a7da39dSBen Hutchings 		buf_size += sizeof(struct ethtool_rxnfc);
27773a7da39dSBen Hutchings 		convert_in = true;
27783a7da39dSBen Hutchings 		break;
27793a7da39dSBen Hutchings 	}
27803a7da39dSBen Hutchings 
27813a7da39dSBen Hutchings 	ifr = compat_alloc_user_space(buf_size);
27823a7da39dSBen Hutchings 	rxnfc = (void *)ifr + ALIGN(sizeof(struct ifreq), 8);
27833a7da39dSBen Hutchings 
27843a7da39dSBen Hutchings 	if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
27853a7da39dSBen Hutchings 		return -EFAULT;
27863a7da39dSBen Hutchings 
27873a7da39dSBen Hutchings 	if (put_user(convert_in ? rxnfc : compat_ptr(data),
27883a7da39dSBen Hutchings 		     &ifr->ifr_ifru.ifru_data))
27893a7da39dSBen Hutchings 		return -EFAULT;
27903a7da39dSBen Hutchings 
27913a7da39dSBen Hutchings 	if (convert_in) {
2792127fe533SAlexander Duyck 		/* We expect there to be holes between fs.m_ext and
27933a7da39dSBen Hutchings 		 * fs.ring_cookie and at the end of fs, but nowhere else.
27943a7da39dSBen Hutchings 		 */
2795127fe533SAlexander Duyck 		BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_ext) +
2796127fe533SAlexander Duyck 			     sizeof(compat_rxnfc->fs.m_ext) !=
2797127fe533SAlexander Duyck 			     offsetof(struct ethtool_rxnfc, fs.m_ext) +
2798127fe533SAlexander Duyck 			     sizeof(rxnfc->fs.m_ext));
27993a7da39dSBen Hutchings 		BUILD_BUG_ON(
28003a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.location) -
28013a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) !=
28023a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.location) -
28033a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.ring_cookie));
28043a7da39dSBen Hutchings 
28053a7da39dSBen Hutchings 		if (copy_in_user(rxnfc, compat_rxnfc,
2806127fe533SAlexander Duyck 				 (void *)(&rxnfc->fs.m_ext + 1) -
28073a7da39dSBen Hutchings 				 (void *)rxnfc) ||
28083a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->fs.ring_cookie,
28093a7da39dSBen Hutchings 				 &compat_rxnfc->fs.ring_cookie,
28103a7da39dSBen Hutchings 				 (void *)(&rxnfc->fs.location + 1) -
28113a7da39dSBen Hutchings 				 (void *)&rxnfc->fs.ring_cookie) ||
28123a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt,
28133a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
28143a7da39dSBen Hutchings 			return -EFAULT;
28153a7da39dSBen Hutchings 	}
28163a7da39dSBen Hutchings 
28173a7da39dSBen Hutchings 	ret = dev_ioctl(net, SIOCETHTOOL, ifr);
28183a7da39dSBen Hutchings 	if (ret)
28193a7da39dSBen Hutchings 		return ret;
28203a7da39dSBen Hutchings 
28213a7da39dSBen Hutchings 	if (convert_out) {
28223a7da39dSBen Hutchings 		if (copy_in_user(compat_rxnfc, rxnfc,
2823127fe533SAlexander Duyck 				 (const void *)(&rxnfc->fs.m_ext + 1) -
28243a7da39dSBen Hutchings 				 (const void *)rxnfc) ||
28253a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->fs.ring_cookie,
28263a7da39dSBen Hutchings 				 &rxnfc->fs.ring_cookie,
28273a7da39dSBen Hutchings 				 (const void *)(&rxnfc->fs.location + 1) -
28283a7da39dSBen Hutchings 				 (const void *)&rxnfc->fs.ring_cookie) ||
28293a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt,
28303a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
28313a7da39dSBen Hutchings 			return -EFAULT;
28323a7da39dSBen Hutchings 
28333a7da39dSBen Hutchings 		if (ethcmd == ETHTOOL_GRXCLSRLALL) {
28343a7da39dSBen Hutchings 			/* As an optimisation, we only copy the actual
28353a7da39dSBen Hutchings 			 * number of rules that the underlying
28363a7da39dSBen Hutchings 			 * function returned.  Since Mallory might
28373a7da39dSBen Hutchings 			 * change the rule count in user memory, we
28383a7da39dSBen Hutchings 			 * check that it is less than the rule count
28393a7da39dSBen Hutchings 			 * originally given (as the user buffer size),
28403a7da39dSBen Hutchings 			 * which has been range-checked.
28413a7da39dSBen Hutchings 			 */
28423a7da39dSBen Hutchings 			if (get_user(actual_rule_cnt, &rxnfc->rule_cnt))
28433a7da39dSBen Hutchings 				return -EFAULT;
28443a7da39dSBen Hutchings 			if (actual_rule_cnt < rule_cnt)
28453a7da39dSBen Hutchings 				rule_cnt = actual_rule_cnt;
28463a7da39dSBen Hutchings 			if (copy_in_user(&compat_rxnfc->rule_locs[0],
28473a7da39dSBen Hutchings 					 &rxnfc->rule_locs[0],
28483a7da39dSBen Hutchings 					 rule_cnt * sizeof(u32)))
28493a7da39dSBen Hutchings 				return -EFAULT;
28503a7da39dSBen Hutchings 		}
28513a7da39dSBen Hutchings 	}
28523a7da39dSBen Hutchings 
28533a7da39dSBen Hutchings 	return 0;
28547a229387SArnd Bergmann }
28557a229387SArnd Bergmann 
28567a50a240SArnd Bergmann static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32)
28577a50a240SArnd Bergmann {
28587a50a240SArnd Bergmann 	void __user *uptr;
28597a50a240SArnd Bergmann 	compat_uptr_t uptr32;
28607a50a240SArnd Bergmann 	struct ifreq __user *uifr;
28617a50a240SArnd Bergmann 
28627a50a240SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
28637a50a240SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
28647a50a240SArnd Bergmann 		return -EFAULT;
28657a50a240SArnd Bergmann 
28667a50a240SArnd Bergmann 	if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu))
28677a50a240SArnd Bergmann 		return -EFAULT;
28687a50a240SArnd Bergmann 
28697a50a240SArnd Bergmann 	uptr = compat_ptr(uptr32);
28707a50a240SArnd Bergmann 
28717a50a240SArnd Bergmann 	if (put_user(uptr, &uifr->ifr_settings.ifs_ifsu.raw_hdlc))
28727a50a240SArnd Bergmann 		return -EFAULT;
28737a50a240SArnd Bergmann 
28747a50a240SArnd Bergmann 	return dev_ioctl(net, SIOCWANDEV, uifr);
28757a50a240SArnd Bergmann }
28767a50a240SArnd Bergmann 
28776b96018bSArnd Bergmann static int bond_ioctl(struct net *net, unsigned int cmd,
28786b96018bSArnd Bergmann 			 struct compat_ifreq __user *ifr32)
28797a229387SArnd Bergmann {
28807a229387SArnd Bergmann 	struct ifreq kifr;
28817a229387SArnd Bergmann 	struct ifreq __user *uifr;
28827a229387SArnd Bergmann 	mm_segment_t old_fs;
28837a229387SArnd Bergmann 	int err;
28847a229387SArnd Bergmann 	u32 data;
28857a229387SArnd Bergmann 	void __user *datap;
28867a229387SArnd Bergmann 
28877a229387SArnd Bergmann 	switch (cmd) {
28887a229387SArnd Bergmann 	case SIOCBONDENSLAVE:
28897a229387SArnd Bergmann 	case SIOCBONDRELEASE:
28907a229387SArnd Bergmann 	case SIOCBONDSETHWADDR:
28917a229387SArnd Bergmann 	case SIOCBONDCHANGEACTIVE:
28926b96018bSArnd Bergmann 		if (copy_from_user(&kifr, ifr32, sizeof(struct compat_ifreq)))
28937a229387SArnd Bergmann 			return -EFAULT;
28947a229387SArnd Bergmann 
28957a229387SArnd Bergmann 		old_fs = get_fs();
28967a229387SArnd Bergmann 		set_fs(KERNEL_DS);
2897c3f52ae6Sstephen hemminger 		err = dev_ioctl(net, cmd,
2898c3f52ae6Sstephen hemminger 				(struct ifreq __user __force *) &kifr);
28997a229387SArnd Bergmann 		set_fs(old_fs);
29007a229387SArnd Bergmann 
29017a229387SArnd Bergmann 		return err;
29027a229387SArnd Bergmann 	case SIOCBONDSLAVEINFOQUERY:
29037a229387SArnd Bergmann 	case SIOCBONDINFOQUERY:
29047a229387SArnd Bergmann 		uifr = compat_alloc_user_space(sizeof(*uifr));
29057a229387SArnd Bergmann 		if (copy_in_user(&uifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
29067a229387SArnd Bergmann 			return -EFAULT;
29077a229387SArnd Bergmann 
29087a229387SArnd Bergmann 		if (get_user(data, &ifr32->ifr_ifru.ifru_data))
29097a229387SArnd Bergmann 			return -EFAULT;
29107a229387SArnd Bergmann 
29117a229387SArnd Bergmann 		datap = compat_ptr(data);
29127a229387SArnd Bergmann 		if (put_user(datap, &uifr->ifr_ifru.ifru_data))
29137a229387SArnd Bergmann 			return -EFAULT;
29147a229387SArnd Bergmann 
29156b96018bSArnd Bergmann 		return dev_ioctl(net, cmd, uifr);
29167a229387SArnd Bergmann 	default:
291707d106d0SLinus Torvalds 		return -ENOIOCTLCMD;
2918ccbd6a5aSJoe Perches 	}
29197a229387SArnd Bergmann }
29207a229387SArnd Bergmann 
29216b96018bSArnd Bergmann static int siocdevprivate_ioctl(struct net *net, unsigned int cmd,
29226b96018bSArnd Bergmann 				 struct compat_ifreq __user *u_ifreq32)
29237a229387SArnd Bergmann {
29247a229387SArnd Bergmann 	struct ifreq __user *u_ifreq64;
29257a229387SArnd Bergmann 	char tmp_buf[IFNAMSIZ];
29267a229387SArnd Bergmann 	void __user *data64;
29277a229387SArnd Bergmann 	u32 data32;
29287a229387SArnd Bergmann 
29297a229387SArnd Bergmann 	if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]),
29307a229387SArnd Bergmann 			   IFNAMSIZ))
29317a229387SArnd Bergmann 		return -EFAULT;
29327a229387SArnd Bergmann 	if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data))
29337a229387SArnd Bergmann 		return -EFAULT;
29347a229387SArnd Bergmann 	data64 = compat_ptr(data32);
29357a229387SArnd Bergmann 
29367a229387SArnd Bergmann 	u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
29377a229387SArnd Bergmann 
29387a229387SArnd Bergmann 	/* Don't check these user accesses, just let that get trapped
29397a229387SArnd Bergmann 	 * in the ioctl handler instead.
29407a229387SArnd Bergmann 	 */
29417a229387SArnd Bergmann 	if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0],
29427a229387SArnd Bergmann 			 IFNAMSIZ))
29437a229387SArnd Bergmann 		return -EFAULT;
29447a229387SArnd Bergmann 	if (__put_user(data64, &u_ifreq64->ifr_ifru.ifru_data))
29457a229387SArnd Bergmann 		return -EFAULT;
29467a229387SArnd Bergmann 
29476b96018bSArnd Bergmann 	return dev_ioctl(net, cmd, u_ifreq64);
29487a229387SArnd Bergmann }
29497a229387SArnd Bergmann 
29506b96018bSArnd Bergmann static int dev_ifsioc(struct net *net, struct socket *sock,
29516b96018bSArnd Bergmann 			 unsigned int cmd, struct compat_ifreq __user *uifr32)
29527a229387SArnd Bergmann {
2953a2116ed2SArnd Bergmann 	struct ifreq __user *uifr;
29547a229387SArnd Bergmann 	int err;
29557a229387SArnd Bergmann 
2956a2116ed2SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
2957a2116ed2SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(*uifr32)))
29587a229387SArnd Bergmann 		return -EFAULT;
2959a2116ed2SArnd Bergmann 
2960a2116ed2SArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr);
2961a2116ed2SArnd Bergmann 
29627a229387SArnd Bergmann 	if (!err) {
29637a229387SArnd Bergmann 		switch (cmd) {
29647a229387SArnd Bergmann 		case SIOCGIFFLAGS:
29657a229387SArnd Bergmann 		case SIOCGIFMETRIC:
29667a229387SArnd Bergmann 		case SIOCGIFMTU:
29677a229387SArnd Bergmann 		case SIOCGIFMEM:
29687a229387SArnd Bergmann 		case SIOCGIFHWADDR:
29697a229387SArnd Bergmann 		case SIOCGIFINDEX:
29707a229387SArnd Bergmann 		case SIOCGIFADDR:
29717a229387SArnd Bergmann 		case SIOCGIFBRDADDR:
29727a229387SArnd Bergmann 		case SIOCGIFDSTADDR:
29737a229387SArnd Bergmann 		case SIOCGIFNETMASK:
2974fab2532bSArnd Bergmann 		case SIOCGIFPFLAGS:
29757a229387SArnd Bergmann 		case SIOCGIFTXQLEN:
2976fab2532bSArnd Bergmann 		case SIOCGMIIPHY:
2977fab2532bSArnd Bergmann 		case SIOCGMIIREG:
2978a2116ed2SArnd Bergmann 			if (copy_in_user(uifr32, uifr, sizeof(*uifr32)))
2979a2116ed2SArnd Bergmann 				err = -EFAULT;
29807a229387SArnd Bergmann 			break;
2981a2116ed2SArnd Bergmann 		}
2982a2116ed2SArnd Bergmann 	}
2983a2116ed2SArnd Bergmann 	return err;
2984a2116ed2SArnd Bergmann }
2985a2116ed2SArnd Bergmann 
2986a2116ed2SArnd Bergmann static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
2987a2116ed2SArnd Bergmann 			struct compat_ifreq __user *uifr32)
2988a2116ed2SArnd Bergmann {
2989a2116ed2SArnd Bergmann 	struct ifreq ifr;
2990a2116ed2SArnd Bergmann 	struct compat_ifmap __user *uifmap32;
2991a2116ed2SArnd Bergmann 	mm_segment_t old_fs;
2992a2116ed2SArnd Bergmann 	int err;
2993a2116ed2SArnd Bergmann 
2994a2116ed2SArnd Bergmann 	uifmap32 = &uifr32->ifr_ifru.ifru_map;
2995a2116ed2SArnd Bergmann 	err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name));
2996a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
2997a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
2998a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
2999a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.irq, &uifmap32->irq);
3000a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.dma, &uifmap32->dma);
3001a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.port, &uifmap32->port);
3002a2116ed2SArnd Bergmann 	if (err)
3003a2116ed2SArnd Bergmann 		return -EFAULT;
3004a2116ed2SArnd Bergmann 
3005a2116ed2SArnd Bergmann 	old_fs = get_fs();
3006a2116ed2SArnd Bergmann 	set_fs(KERNEL_DS);
3007c3f52ae6Sstephen hemminger 	err = dev_ioctl(net, cmd, (void  __user __force *)&ifr);
3008a2116ed2SArnd Bergmann 	set_fs(old_fs);
3009a2116ed2SArnd Bergmann 
3010a2116ed2SArnd Bergmann 	if (cmd == SIOCGIFMAP && !err) {
30117a229387SArnd Bergmann 		err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name));
30127a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
30137a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
30147a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
30157a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.irq, &uifmap32->irq);
30167a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.dma, &uifmap32->dma);
30177a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.port, &uifmap32->port);
30187a229387SArnd Bergmann 		if (err)
30197a229387SArnd Bergmann 			err = -EFAULT;
30207a229387SArnd Bergmann 	}
30217a229387SArnd Bergmann 	return err;
30227a229387SArnd Bergmann }
30237a229387SArnd Bergmann 
3024a2116ed2SArnd Bergmann static int compat_siocshwtstamp(struct net *net, struct compat_ifreq __user *uifr32)
3025a2116ed2SArnd Bergmann {
3026a2116ed2SArnd Bergmann 	void __user *uptr;
3027a2116ed2SArnd Bergmann 	compat_uptr_t uptr32;
3028a2116ed2SArnd Bergmann 	struct ifreq __user *uifr;
3029a2116ed2SArnd Bergmann 
3030a2116ed2SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
3031a2116ed2SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
3032a2116ed2SArnd Bergmann 		return -EFAULT;
3033a2116ed2SArnd Bergmann 
3034a2116ed2SArnd Bergmann 	if (get_user(uptr32, &uifr32->ifr_data))
3035a2116ed2SArnd Bergmann 		return -EFAULT;
3036a2116ed2SArnd Bergmann 
3037a2116ed2SArnd Bergmann 	uptr = compat_ptr(uptr32);
3038a2116ed2SArnd Bergmann 
3039a2116ed2SArnd Bergmann 	if (put_user(uptr, &uifr->ifr_data))
3040a2116ed2SArnd Bergmann 		return -EFAULT;
3041a2116ed2SArnd Bergmann 
3042a2116ed2SArnd Bergmann 	return dev_ioctl(net, SIOCSHWTSTAMP, uifr);
3043a2116ed2SArnd Bergmann }
3044a2116ed2SArnd Bergmann 
30457a229387SArnd Bergmann struct rtentry32 {
30467a229387SArnd Bergmann 	u32		rt_pad1;
30477a229387SArnd Bergmann 	struct sockaddr rt_dst;         /* target address               */
30487a229387SArnd Bergmann 	struct sockaddr rt_gateway;     /* gateway addr (RTF_GATEWAY)   */
30497a229387SArnd Bergmann 	struct sockaddr rt_genmask;     /* target network mask (IP)     */
30507a229387SArnd Bergmann 	unsigned short	rt_flags;
30517a229387SArnd Bergmann 	short		rt_pad2;
30527a229387SArnd Bergmann 	u32		rt_pad3;
30537a229387SArnd Bergmann 	unsigned char	rt_tos;
30547a229387SArnd Bergmann 	unsigned char	rt_class;
30557a229387SArnd Bergmann 	short		rt_pad4;
30567a229387SArnd Bergmann 	short		rt_metric;      /* +1 for binary compatibility! */
30577a229387SArnd Bergmann 	/* char * */ u32 rt_dev;        /* forcing the device at add    */
30587a229387SArnd Bergmann 	u32		rt_mtu;         /* per route MTU/Window         */
30597a229387SArnd Bergmann 	u32		rt_window;      /* Window clamping              */
30607a229387SArnd Bergmann 	unsigned short  rt_irtt;        /* Initial RTT                  */
30617a229387SArnd Bergmann };
30627a229387SArnd Bergmann 
30637a229387SArnd Bergmann struct in6_rtmsg32 {
30647a229387SArnd Bergmann 	struct in6_addr		rtmsg_dst;
30657a229387SArnd Bergmann 	struct in6_addr		rtmsg_src;
30667a229387SArnd Bergmann 	struct in6_addr		rtmsg_gateway;
30677a229387SArnd Bergmann 	u32			rtmsg_type;
30687a229387SArnd Bergmann 	u16			rtmsg_dst_len;
30697a229387SArnd Bergmann 	u16			rtmsg_src_len;
30707a229387SArnd Bergmann 	u32			rtmsg_metric;
30717a229387SArnd Bergmann 	u32			rtmsg_info;
30727a229387SArnd Bergmann 	u32			rtmsg_flags;
30737a229387SArnd Bergmann 	s32			rtmsg_ifindex;
30747a229387SArnd Bergmann };
30757a229387SArnd Bergmann 
30766b96018bSArnd Bergmann static int routing_ioctl(struct net *net, struct socket *sock,
30776b96018bSArnd Bergmann 			 unsigned int cmd, void __user *argp)
30787a229387SArnd Bergmann {
30797a229387SArnd Bergmann 	int ret;
30807a229387SArnd Bergmann 	void *r = NULL;
30817a229387SArnd Bergmann 	struct in6_rtmsg r6;
30827a229387SArnd Bergmann 	struct rtentry r4;
30837a229387SArnd Bergmann 	char devname[16];
30847a229387SArnd Bergmann 	u32 rtdev;
30857a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
30867a229387SArnd Bergmann 
30876b96018bSArnd Bergmann 	if (sock && sock->sk && sock->sk->sk_family == AF_INET6) { /* ipv6 */
30886b96018bSArnd Bergmann 		struct in6_rtmsg32 __user *ur6 = argp;
30897a229387SArnd Bergmann 		ret = copy_from_user(&r6.rtmsg_dst, &(ur6->rtmsg_dst),
30907a229387SArnd Bergmann 			3 * sizeof(struct in6_addr));
30917a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_type, &(ur6->rtmsg_type));
30927a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len));
30937a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_src_len, &(ur6->rtmsg_src_len));
30947a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_metric, &(ur6->rtmsg_metric));
30957a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_info, &(ur6->rtmsg_info));
30967a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_flags, &(ur6->rtmsg_flags));
30977a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex));
30987a229387SArnd Bergmann 
30997a229387SArnd Bergmann 		r = (void *) &r6;
31007a229387SArnd Bergmann 	} else { /* ipv4 */
31016b96018bSArnd Bergmann 		struct rtentry32 __user *ur4 = argp;
31027a229387SArnd Bergmann 		ret = copy_from_user(&r4.rt_dst, &(ur4->rt_dst),
31037a229387SArnd Bergmann 					3 * sizeof(struct sockaddr));
31047a229387SArnd Bergmann 		ret |= __get_user(r4.rt_flags, &(ur4->rt_flags));
31057a229387SArnd Bergmann 		ret |= __get_user(r4.rt_metric, &(ur4->rt_metric));
31067a229387SArnd Bergmann 		ret |= __get_user(r4.rt_mtu, &(ur4->rt_mtu));
31077a229387SArnd Bergmann 		ret |= __get_user(r4.rt_window, &(ur4->rt_window));
31087a229387SArnd Bergmann 		ret |= __get_user(r4.rt_irtt, &(ur4->rt_irtt));
31097a229387SArnd Bergmann 		ret |= __get_user(rtdev, &(ur4->rt_dev));
31107a229387SArnd Bergmann 		if (rtdev) {
31117a229387SArnd Bergmann 			ret |= copy_from_user(devname, compat_ptr(rtdev), 15);
3112c3f52ae6Sstephen hemminger 			r4.rt_dev = (char __user __force *)devname;
3113c3f52ae6Sstephen hemminger 			devname[15] = 0;
31147a229387SArnd Bergmann 		} else
31157a229387SArnd Bergmann 			r4.rt_dev = NULL;
31167a229387SArnd Bergmann 
31177a229387SArnd Bergmann 		r = (void *) &r4;
31187a229387SArnd Bergmann 	}
31197a229387SArnd Bergmann 
31207a229387SArnd Bergmann 	if (ret) {
31217a229387SArnd Bergmann 		ret = -EFAULT;
31227a229387SArnd Bergmann 		goto out;
31237a229387SArnd Bergmann 	}
31247a229387SArnd Bergmann 
31257a229387SArnd Bergmann 	set_fs(KERNEL_DS);
31266b96018bSArnd Bergmann 	ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r);
31277a229387SArnd Bergmann 	set_fs(old_fs);
31287a229387SArnd Bergmann 
31297a229387SArnd Bergmann out:
31307a229387SArnd Bergmann 	return ret;
31317a229387SArnd Bergmann }
31327a229387SArnd Bergmann 
31337a229387SArnd Bergmann /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE
31347a229387SArnd Bergmann  * for some operations; this forces use of the newer bridge-utils that
313525985edcSLucas De Marchi  * use compatible ioctls
31367a229387SArnd Bergmann  */
31376b96018bSArnd Bergmann static int old_bridge_ioctl(compat_ulong_t __user *argp)
31387a229387SArnd Bergmann {
31396b96018bSArnd Bergmann 	compat_ulong_t tmp;
31407a229387SArnd Bergmann 
31416b96018bSArnd Bergmann 	if (get_user(tmp, argp))
31427a229387SArnd Bergmann 		return -EFAULT;
31437a229387SArnd Bergmann 	if (tmp == BRCTL_GET_VERSION)
31447a229387SArnd Bergmann 		return BRCTL_VERSION + 1;
31457a229387SArnd Bergmann 	return -EINVAL;
31467a229387SArnd Bergmann }
31477a229387SArnd Bergmann 
31486b96018bSArnd Bergmann static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
31496b96018bSArnd Bergmann 			 unsigned int cmd, unsigned long arg)
31506b96018bSArnd Bergmann {
31516b96018bSArnd Bergmann 	void __user *argp = compat_ptr(arg);
31526b96018bSArnd Bergmann 	struct sock *sk = sock->sk;
31536b96018bSArnd Bergmann 	struct net *net = sock_net(sk);
31547a229387SArnd Bergmann 
31556b96018bSArnd Bergmann 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
31566b96018bSArnd Bergmann 		return siocdevprivate_ioctl(net, cmd, argp);
31577a229387SArnd Bergmann 
31586b96018bSArnd Bergmann 	switch (cmd) {
31596b96018bSArnd Bergmann 	case SIOCSIFBR:
31606b96018bSArnd Bergmann 	case SIOCGIFBR:
31616b96018bSArnd Bergmann 		return old_bridge_ioctl(argp);
31626b96018bSArnd Bergmann 	case SIOCGIFNAME:
31636b96018bSArnd Bergmann 		return dev_ifname32(net, argp);
31646b96018bSArnd Bergmann 	case SIOCGIFCONF:
31656b96018bSArnd Bergmann 		return dev_ifconf(net, argp);
31666b96018bSArnd Bergmann 	case SIOCETHTOOL:
31676b96018bSArnd Bergmann 		return ethtool_ioctl(net, argp);
31687a50a240SArnd Bergmann 	case SIOCWANDEV:
31697a50a240SArnd Bergmann 		return compat_siocwandev(net, argp);
3170a2116ed2SArnd Bergmann 	case SIOCGIFMAP:
3171a2116ed2SArnd Bergmann 	case SIOCSIFMAP:
3172a2116ed2SArnd Bergmann 		return compat_sioc_ifmap(net, cmd, argp);
31736b96018bSArnd Bergmann 	case SIOCBONDENSLAVE:
31746b96018bSArnd Bergmann 	case SIOCBONDRELEASE:
31756b96018bSArnd Bergmann 	case SIOCBONDSETHWADDR:
31766b96018bSArnd Bergmann 	case SIOCBONDSLAVEINFOQUERY:
31776b96018bSArnd Bergmann 	case SIOCBONDINFOQUERY:
31786b96018bSArnd Bergmann 	case SIOCBONDCHANGEACTIVE:
31796b96018bSArnd Bergmann 		return bond_ioctl(net, cmd, argp);
31806b96018bSArnd Bergmann 	case SIOCADDRT:
31816b96018bSArnd Bergmann 	case SIOCDELRT:
31826b96018bSArnd Bergmann 		return routing_ioctl(net, sock, cmd, argp);
31836b96018bSArnd Bergmann 	case SIOCGSTAMP:
31846b96018bSArnd Bergmann 		return do_siocgstamp(net, sock, cmd, argp);
31856b96018bSArnd Bergmann 	case SIOCGSTAMPNS:
31866b96018bSArnd Bergmann 		return do_siocgstampns(net, sock, cmd, argp);
3187a2116ed2SArnd Bergmann 	case SIOCSHWTSTAMP:
3188a2116ed2SArnd Bergmann 		return compat_siocshwtstamp(net, argp);
31897a229387SArnd Bergmann 
31906b96018bSArnd Bergmann 	case FIOSETOWN:
31916b96018bSArnd Bergmann 	case SIOCSPGRP:
31926b96018bSArnd Bergmann 	case FIOGETOWN:
31936b96018bSArnd Bergmann 	case SIOCGPGRP:
31946b96018bSArnd Bergmann 	case SIOCBRADDBR:
31956b96018bSArnd Bergmann 	case SIOCBRDELBR:
31966b96018bSArnd Bergmann 	case SIOCGIFVLAN:
31976b96018bSArnd Bergmann 	case SIOCSIFVLAN:
31986b96018bSArnd Bergmann 	case SIOCADDDLCI:
31996b96018bSArnd Bergmann 	case SIOCDELDLCI:
32006b96018bSArnd Bergmann 		return sock_ioctl(file, cmd, arg);
32016b96018bSArnd Bergmann 
32026b96018bSArnd Bergmann 	case SIOCGIFFLAGS:
32036b96018bSArnd Bergmann 	case SIOCSIFFLAGS:
32046b96018bSArnd Bergmann 	case SIOCGIFMETRIC:
32056b96018bSArnd Bergmann 	case SIOCSIFMETRIC:
32066b96018bSArnd Bergmann 	case SIOCGIFMTU:
32076b96018bSArnd Bergmann 	case SIOCSIFMTU:
32086b96018bSArnd Bergmann 	case SIOCGIFMEM:
32096b96018bSArnd Bergmann 	case SIOCSIFMEM:
32106b96018bSArnd Bergmann 	case SIOCGIFHWADDR:
32116b96018bSArnd Bergmann 	case SIOCSIFHWADDR:
32126b96018bSArnd Bergmann 	case SIOCADDMULTI:
32136b96018bSArnd Bergmann 	case SIOCDELMULTI:
32146b96018bSArnd Bergmann 	case SIOCGIFINDEX:
32156b96018bSArnd Bergmann 	case SIOCGIFADDR:
32166b96018bSArnd Bergmann 	case SIOCSIFADDR:
32176b96018bSArnd Bergmann 	case SIOCSIFHWBROADCAST:
32186b96018bSArnd Bergmann 	case SIOCDIFADDR:
32196b96018bSArnd Bergmann 	case SIOCGIFBRDADDR:
32206b96018bSArnd Bergmann 	case SIOCSIFBRDADDR:
32216b96018bSArnd Bergmann 	case SIOCGIFDSTADDR:
32226b96018bSArnd Bergmann 	case SIOCSIFDSTADDR:
32236b96018bSArnd Bergmann 	case SIOCGIFNETMASK:
32246b96018bSArnd Bergmann 	case SIOCSIFNETMASK:
32256b96018bSArnd Bergmann 	case SIOCSIFPFLAGS:
32266b96018bSArnd Bergmann 	case SIOCGIFPFLAGS:
32276b96018bSArnd Bergmann 	case SIOCGIFTXQLEN:
32286b96018bSArnd Bergmann 	case SIOCSIFTXQLEN:
32296b96018bSArnd Bergmann 	case SIOCBRADDIF:
32306b96018bSArnd Bergmann 	case SIOCBRDELIF:
32319177efd3SArnd Bergmann 	case SIOCSIFNAME:
32329177efd3SArnd Bergmann 	case SIOCGMIIPHY:
32339177efd3SArnd Bergmann 	case SIOCGMIIREG:
32349177efd3SArnd Bergmann 	case SIOCSMIIREG:
32356b96018bSArnd Bergmann 		return dev_ifsioc(net, sock, cmd, argp);
32369177efd3SArnd Bergmann 
32376b96018bSArnd Bergmann 	case SIOCSARP:
32386b96018bSArnd Bergmann 	case SIOCGARP:
32396b96018bSArnd Bergmann 	case SIOCDARP:
32406b96018bSArnd Bergmann 	case SIOCATMARK:
32419177efd3SArnd Bergmann 		return sock_do_ioctl(net, sock, cmd, arg);
32429177efd3SArnd Bergmann 	}
32439177efd3SArnd Bergmann 
32446b96018bSArnd Bergmann 	return -ENOIOCTLCMD;
32456b96018bSArnd Bergmann }
32467a229387SArnd Bergmann 
324795c96174SEric Dumazet static long compat_sock_ioctl(struct file *file, unsigned int cmd,
324889bbfc95SShaun Pereira 			      unsigned long arg)
324989bbfc95SShaun Pereira {
325089bbfc95SShaun Pereira 	struct socket *sock = file->private_data;
325189bbfc95SShaun Pereira 	int ret = -ENOIOCTLCMD;
325287de87d5SDavid S. Miller 	struct sock *sk;
325387de87d5SDavid S. Miller 	struct net *net;
325487de87d5SDavid S. Miller 
325587de87d5SDavid S. Miller 	sk = sock->sk;
325687de87d5SDavid S. Miller 	net = sock_net(sk);
325789bbfc95SShaun Pereira 
325889bbfc95SShaun Pereira 	if (sock->ops->compat_ioctl)
325989bbfc95SShaun Pereira 		ret = sock->ops->compat_ioctl(sock, cmd, arg);
326089bbfc95SShaun Pereira 
326187de87d5SDavid S. Miller 	if (ret == -ENOIOCTLCMD &&
326287de87d5SDavid S. Miller 	    (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST))
326387de87d5SDavid S. Miller 		ret = compat_wext_handle_ioctl(net, cmd, arg);
326487de87d5SDavid S. Miller 
32656b96018bSArnd Bergmann 	if (ret == -ENOIOCTLCMD)
32666b96018bSArnd Bergmann 		ret = compat_sock_ioctl_trans(file, sock, cmd, arg);
32676b96018bSArnd Bergmann 
326889bbfc95SShaun Pereira 	return ret;
326989bbfc95SShaun Pereira }
327089bbfc95SShaun Pereira #endif
327189bbfc95SShaun Pereira 
3272ac5a488eSSridhar Samudrala int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
3273ac5a488eSSridhar Samudrala {
3274ac5a488eSSridhar Samudrala 	return sock->ops->bind(sock, addr, addrlen);
3275ac5a488eSSridhar Samudrala }
3276c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_bind);
3277ac5a488eSSridhar Samudrala 
3278ac5a488eSSridhar Samudrala int kernel_listen(struct socket *sock, int backlog)
3279ac5a488eSSridhar Samudrala {
3280ac5a488eSSridhar Samudrala 	return sock->ops->listen(sock, backlog);
3281ac5a488eSSridhar Samudrala }
3282c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_listen);
3283ac5a488eSSridhar Samudrala 
3284ac5a488eSSridhar Samudrala int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
3285ac5a488eSSridhar Samudrala {
3286ac5a488eSSridhar Samudrala 	struct sock *sk = sock->sk;
3287ac5a488eSSridhar Samudrala 	int err;
3288ac5a488eSSridhar Samudrala 
3289ac5a488eSSridhar Samudrala 	err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
3290ac5a488eSSridhar Samudrala 			       newsock);
3291ac5a488eSSridhar Samudrala 	if (err < 0)
3292ac5a488eSSridhar Samudrala 		goto done;
3293ac5a488eSSridhar Samudrala 
3294ac5a488eSSridhar Samudrala 	err = sock->ops->accept(sock, *newsock, flags);
3295ac5a488eSSridhar Samudrala 	if (err < 0) {
3296ac5a488eSSridhar Samudrala 		sock_release(*newsock);
3297fa8705b0STony Battersby 		*newsock = NULL;
3298ac5a488eSSridhar Samudrala 		goto done;
3299ac5a488eSSridhar Samudrala 	}
3300ac5a488eSSridhar Samudrala 
3301ac5a488eSSridhar Samudrala 	(*newsock)->ops = sock->ops;
33021b08534eSWei Yongjun 	__module_get((*newsock)->ops->owner);
3303ac5a488eSSridhar Samudrala 
3304ac5a488eSSridhar Samudrala done:
3305ac5a488eSSridhar Samudrala 	return err;
3306ac5a488eSSridhar Samudrala }
3307c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_accept);
3308ac5a488eSSridhar Samudrala 
3309ac5a488eSSridhar Samudrala int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
3310ac5a488eSSridhar Samudrala 		   int flags)
3311ac5a488eSSridhar Samudrala {
3312ac5a488eSSridhar Samudrala 	return sock->ops->connect(sock, addr, addrlen, flags);
3313ac5a488eSSridhar Samudrala }
3314c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_connect);
3315ac5a488eSSridhar Samudrala 
3316ac5a488eSSridhar Samudrala int kernel_getsockname(struct socket *sock, struct sockaddr *addr,
3317ac5a488eSSridhar Samudrala 			 int *addrlen)
3318ac5a488eSSridhar Samudrala {
3319ac5a488eSSridhar Samudrala 	return sock->ops->getname(sock, addr, addrlen, 0);
3320ac5a488eSSridhar Samudrala }
3321c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockname);
3322ac5a488eSSridhar Samudrala 
3323ac5a488eSSridhar Samudrala int kernel_getpeername(struct socket *sock, struct sockaddr *addr,
3324ac5a488eSSridhar Samudrala 			 int *addrlen)
3325ac5a488eSSridhar Samudrala {
3326ac5a488eSSridhar Samudrala 	return sock->ops->getname(sock, addr, addrlen, 1);
3327ac5a488eSSridhar Samudrala }
3328c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getpeername);
3329ac5a488eSSridhar Samudrala 
3330ac5a488eSSridhar Samudrala int kernel_getsockopt(struct socket *sock, int level, int optname,
3331ac5a488eSSridhar Samudrala 			char *optval, int *optlen)
3332ac5a488eSSridhar Samudrala {
3333ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3334fb8621bbSNamhyung Kim 	char __user *uoptval;
3335fb8621bbSNamhyung Kim 	int __user *uoptlen;
3336ac5a488eSSridhar Samudrala 	int err;
3337ac5a488eSSridhar Samudrala 
3338fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3339fb8621bbSNamhyung Kim 	uoptlen = (int __user __force *) optlen;
3340fb8621bbSNamhyung Kim 
3341ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3342ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3343fb8621bbSNamhyung Kim 		err = sock_getsockopt(sock, level, optname, uoptval, uoptlen);
3344ac5a488eSSridhar Samudrala 	else
3345fb8621bbSNamhyung Kim 		err = sock->ops->getsockopt(sock, level, optname, uoptval,
3346fb8621bbSNamhyung Kim 					    uoptlen);
3347ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3348ac5a488eSSridhar Samudrala 	return err;
3349ac5a488eSSridhar Samudrala }
3350c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockopt);
3351ac5a488eSSridhar Samudrala 
3352ac5a488eSSridhar Samudrala int kernel_setsockopt(struct socket *sock, int level, int optname,
3353b7058842SDavid S. Miller 			char *optval, unsigned int optlen)
3354ac5a488eSSridhar Samudrala {
3355ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3356fb8621bbSNamhyung Kim 	char __user *uoptval;
3357ac5a488eSSridhar Samudrala 	int err;
3358ac5a488eSSridhar Samudrala 
3359fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3360fb8621bbSNamhyung Kim 
3361ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3362ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3363fb8621bbSNamhyung Kim 		err = sock_setsockopt(sock, level, optname, uoptval, optlen);
3364ac5a488eSSridhar Samudrala 	else
3365fb8621bbSNamhyung Kim 		err = sock->ops->setsockopt(sock, level, optname, uoptval,
3366ac5a488eSSridhar Samudrala 					    optlen);
3367ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3368ac5a488eSSridhar Samudrala 	return err;
3369ac5a488eSSridhar Samudrala }
3370c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_setsockopt);
3371ac5a488eSSridhar Samudrala 
3372ac5a488eSSridhar Samudrala int kernel_sendpage(struct socket *sock, struct page *page, int offset,
3373ac5a488eSSridhar Samudrala 		    size_t size, int flags)
3374ac5a488eSSridhar Samudrala {
3375f8451725SHerbert Xu 	sock_update_classid(sock->sk);
3376f8451725SHerbert Xu 
3377ac5a488eSSridhar Samudrala 	if (sock->ops->sendpage)
3378ac5a488eSSridhar Samudrala 		return sock->ops->sendpage(sock, page, offset, size, flags);
3379ac5a488eSSridhar Samudrala 
3380ac5a488eSSridhar Samudrala 	return sock_no_sendpage(sock, page, offset, size, flags);
3381ac5a488eSSridhar Samudrala }
3382c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendpage);
3383ac5a488eSSridhar Samudrala 
3384ac5a488eSSridhar Samudrala int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg)
3385ac5a488eSSridhar Samudrala {
3386ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3387ac5a488eSSridhar Samudrala 	int err;
3388ac5a488eSSridhar Samudrala 
3389ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3390ac5a488eSSridhar Samudrala 	err = sock->ops->ioctl(sock, cmd, arg);
3391ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3392ac5a488eSSridhar Samudrala 
3393ac5a488eSSridhar Samudrala 	return err;
3394ac5a488eSSridhar Samudrala }
3395c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sock_ioctl);
3396ac5a488eSSridhar Samudrala 
339791cf45f0STrond Myklebust int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
339891cf45f0STrond Myklebust {
339991cf45f0STrond Myklebust 	return sock->ops->shutdown(sock, how);
340091cf45f0STrond Myklebust }
340191cf45f0STrond Myklebust EXPORT_SYMBOL(kernel_sock_shutdown);
3402