xref: /openbmc/linux/net/socket.c (revision 644595f8)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * NET		An implementation of the SOCKET network access protocol.
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Version:	@(#)socket.c	1.1.93	18/02/95
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * Authors:	Orest Zborowski, <obz@Kodak.COM>
702c30a84SJesper Juhl  *		Ross Biro
81da177e4SLinus Torvalds  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
91da177e4SLinus Torvalds  *
101da177e4SLinus Torvalds  * Fixes:
111da177e4SLinus Torvalds  *		Anonymous	:	NOTSOCK/BADF cleanup. Error fix in
121da177e4SLinus Torvalds  *					shutdown()
131da177e4SLinus Torvalds  *		Alan Cox	:	verify_area() fixes
141da177e4SLinus Torvalds  *		Alan Cox	:	Removed DDI
151da177e4SLinus Torvalds  *		Jonathan Kamens	:	SOCK_DGRAM reconnect bug
161da177e4SLinus Torvalds  *		Alan Cox	:	Moved a load of checks to the very
171da177e4SLinus Torvalds  *					top level.
181da177e4SLinus Torvalds  *		Alan Cox	:	Move address structures to/from user
191da177e4SLinus Torvalds  *					mode above the protocol layers.
201da177e4SLinus Torvalds  *		Rob Janssen	:	Allow 0 length sends.
211da177e4SLinus Torvalds  *		Alan Cox	:	Asynchronous I/O support (cribbed from the
221da177e4SLinus Torvalds  *					tty drivers).
231da177e4SLinus Torvalds  *		Niibe Yutaka	:	Asynchronous I/O for writes (4.4BSD style)
241da177e4SLinus Torvalds  *		Jeff Uphoff	:	Made max number of sockets command-line
251da177e4SLinus Torvalds  *					configurable.
261da177e4SLinus Torvalds  *		Matti Aarnio	:	Made the number of sockets dynamic,
271da177e4SLinus Torvalds  *					to be allocated when needed, and mr.
281da177e4SLinus Torvalds  *					Uphoff's max is used as max to be
291da177e4SLinus Torvalds  *					allowed to allocate.
301da177e4SLinus Torvalds  *		Linus		:	Argh. removed all the socket allocation
311da177e4SLinus Torvalds  *					altogether: it's in the inode now.
321da177e4SLinus Torvalds  *		Alan Cox	:	Made sock_alloc()/sock_release() public
331da177e4SLinus Torvalds  *					for NetROM and future kernel nfsd type
341da177e4SLinus Torvalds  *					stuff.
351da177e4SLinus Torvalds  *		Alan Cox	:	sendmsg/recvmsg basics.
361da177e4SLinus Torvalds  *		Tom Dyas	:	Export net symbols.
371da177e4SLinus Torvalds  *		Marcin Dalecki	:	Fixed problems with CONFIG_NET="n".
381da177e4SLinus Torvalds  *		Alan Cox	:	Added thread locking to sys_* calls
391da177e4SLinus Torvalds  *					for sockets. May have errors at the
401da177e4SLinus Torvalds  *					moment.
411da177e4SLinus Torvalds  *		Kevin Buhr	:	Fixed the dumb errors in the above.
421da177e4SLinus Torvalds  *		Andi Kleen	:	Some small cleanups, optimizations,
431da177e4SLinus Torvalds  *					and fixed a copy_from_user() bug.
441da177e4SLinus Torvalds  *		Tigran Aivazian	:	sys_send(args) calls sys_sendto(args, NULL, 0)
451da177e4SLinus Torvalds  *		Tigran Aivazian	:	Made listen(2) backlog sanity checks
461da177e4SLinus Torvalds  *					protocol-independent
471da177e4SLinus Torvalds  *
481da177e4SLinus Torvalds  *
491da177e4SLinus Torvalds  *		This program is free software; you can redistribute it and/or
501da177e4SLinus Torvalds  *		modify it under the terms of the GNU General Public License
511da177e4SLinus Torvalds  *		as published by the Free Software Foundation; either version
521da177e4SLinus Torvalds  *		2 of the License, or (at your option) any later version.
531da177e4SLinus Torvalds  *
541da177e4SLinus Torvalds  *
551da177e4SLinus Torvalds  *	This module is effectively the top level interface to the BSD socket
561da177e4SLinus Torvalds  *	paradigm.
571da177e4SLinus Torvalds  *
581da177e4SLinus Torvalds  *	Based upon Swansea University Computer Society NET3.039
591da177e4SLinus Torvalds  */
601da177e4SLinus Torvalds 
611da177e4SLinus Torvalds #include <linux/mm.h>
621da177e4SLinus Torvalds #include <linux/socket.h>
631da177e4SLinus Torvalds #include <linux/file.h>
641da177e4SLinus Torvalds #include <linux/net.h>
651da177e4SLinus Torvalds #include <linux/interrupt.h>
66aaca0bdcSUlrich Drepper #include <linux/thread_info.h>
6755737fdaSStephen Hemminger #include <linux/rcupdate.h>
681da177e4SLinus Torvalds #include <linux/netdevice.h>
691da177e4SLinus Torvalds #include <linux/proc_fs.h>
701da177e4SLinus Torvalds #include <linux/seq_file.h>
714a3e2f71SArjan van de Ven #include <linux/mutex.h>
721da177e4SLinus Torvalds #include <linux/wanrouter.h>
731da177e4SLinus Torvalds #include <linux/if_bridge.h>
7420380731SArnaldo Carvalho de Melo #include <linux/if_frad.h>
7520380731SArnaldo Carvalho de Melo #include <linux/if_vlan.h>
761da177e4SLinus Torvalds #include <linux/init.h>
771da177e4SLinus Torvalds #include <linux/poll.h>
781da177e4SLinus Torvalds #include <linux/cache.h>
791da177e4SLinus Torvalds #include <linux/module.h>
801da177e4SLinus Torvalds #include <linux/highmem.h>
811da177e4SLinus Torvalds #include <linux/mount.h>
821da177e4SLinus Torvalds #include <linux/security.h>
831da177e4SLinus Torvalds #include <linux/syscalls.h>
841da177e4SLinus Torvalds #include <linux/compat.h>
851da177e4SLinus Torvalds #include <linux/kmod.h>
863ec3b2fbSDavid Woodhouse #include <linux/audit.h>
87d86b5e0eSAdrian Bunk #include <linux/wireless.h>
881b8d7ae4SEric W. Biederman #include <linux/nsproxy.h>
891fd7317dSNick Black #include <linux/magic.h>
905a0e3ad6STejun Heo #include <linux/slab.h>
911da177e4SLinus Torvalds 
921da177e4SLinus Torvalds #include <asm/uaccess.h>
931da177e4SLinus Torvalds #include <asm/unistd.h>
941da177e4SLinus Torvalds 
951da177e4SLinus Torvalds #include <net/compat.h>
9687de87d5SDavid S. Miller #include <net/wext.h>
97f8451725SHerbert Xu #include <net/cls_cgroup.h>
981da177e4SLinus Torvalds 
991da177e4SLinus Torvalds #include <net/sock.h>
1001da177e4SLinus Torvalds #include <linux/netfilter.h>
1011da177e4SLinus Torvalds 
1026b96018bSArnd Bergmann #include <linux/if_tun.h>
1036b96018bSArnd Bergmann #include <linux/ipv6_route.h>
1046b96018bSArnd Bergmann #include <linux/route.h>
1056b96018bSArnd Bergmann #include <linux/sockios.h>
1066b96018bSArnd Bergmann #include <linux/atalk.h>
1076b96018bSArnd Bergmann 
1081da177e4SLinus Torvalds static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
109027445c3SBadari Pulavarty static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
110027445c3SBadari Pulavarty 			 unsigned long nr_segs, loff_t pos);
111027445c3SBadari Pulavarty static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
112027445c3SBadari Pulavarty 			  unsigned long nr_segs, loff_t pos);
1131da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma);
1141da177e4SLinus Torvalds 
1151da177e4SLinus Torvalds static int sock_close(struct inode *inode, struct file *file);
1161da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file,
1171da177e4SLinus Torvalds 			      struct poll_table_struct *wait);
11889bddce5SStephen Hemminger static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
11989bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
12089bbfc95SShaun Pereira static long compat_sock_ioctl(struct file *file,
12189bbfc95SShaun Pereira 			      unsigned int cmd, unsigned long arg);
12289bbfc95SShaun Pereira #endif
1231da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on);
1241da177e4SLinus Torvalds static ssize_t sock_sendpage(struct file *file, struct page *page,
1251da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more);
1269c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
1279c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
1289c55e01cSJens Axboe 				unsigned int flags);
1291da177e4SLinus Torvalds 
1301da177e4SLinus Torvalds /*
1311da177e4SLinus Torvalds  *	Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
1321da177e4SLinus Torvalds  *	in the operation structures but are done directly via the socketcall() multiplexor.
1331da177e4SLinus Torvalds  */
1341da177e4SLinus Torvalds 
135da7071d7SArjan van de Ven static const struct file_operations socket_file_ops = {
1361da177e4SLinus Torvalds 	.owner =	THIS_MODULE,
1371da177e4SLinus Torvalds 	.llseek =	no_llseek,
1381da177e4SLinus Torvalds 	.aio_read =	sock_aio_read,
1391da177e4SLinus Torvalds 	.aio_write =	sock_aio_write,
1401da177e4SLinus Torvalds 	.poll =		sock_poll,
1411da177e4SLinus Torvalds 	.unlocked_ioctl = sock_ioctl,
14289bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
14389bbfc95SShaun Pereira 	.compat_ioctl = compat_sock_ioctl,
14489bbfc95SShaun Pereira #endif
1451da177e4SLinus Torvalds 	.mmap =		sock_mmap,
1461da177e4SLinus Torvalds 	.open =		sock_no_open,	/* special open code to disallow open via /proc */
1471da177e4SLinus Torvalds 	.release =	sock_close,
1481da177e4SLinus Torvalds 	.fasync =	sock_fasync,
1495274f052SJens Axboe 	.sendpage =	sock_sendpage,
1505274f052SJens Axboe 	.splice_write = generic_splice_sendpage,
1519c55e01cSJens Axboe 	.splice_read =	sock_splice_read,
1521da177e4SLinus Torvalds };
1531da177e4SLinus Torvalds 
1541da177e4SLinus Torvalds /*
1551da177e4SLinus Torvalds  *	The protocol list. Each protocol is registered in here.
1561da177e4SLinus Torvalds  */
1571da177e4SLinus Torvalds 
1581da177e4SLinus Torvalds static DEFINE_SPINLOCK(net_family_lock);
159190683a9SEric Dumazet static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly;
1601da177e4SLinus Torvalds 
1611da177e4SLinus Torvalds /*
1621da177e4SLinus Torvalds  *	Statistics counters of the socket lists
1631da177e4SLinus Torvalds  */
1641da177e4SLinus Torvalds 
165c6d409cfSEric Dumazet static DEFINE_PER_CPU(int, sockets_in_use);
1661da177e4SLinus Torvalds 
1671da177e4SLinus Torvalds /*
16889bddce5SStephen Hemminger  * Support routines.
16989bddce5SStephen Hemminger  * Move socket addresses back and forth across the kernel/user
1701da177e4SLinus Torvalds  * divide and look after the messy bits.
1711da177e4SLinus Torvalds  */
1721da177e4SLinus Torvalds 
1731da177e4SLinus Torvalds /**
1741da177e4SLinus Torvalds  *	move_addr_to_kernel	-	copy a socket address into kernel space
1751da177e4SLinus Torvalds  *	@uaddr: Address in user space
1761da177e4SLinus Torvalds  *	@kaddr: Address in kernel space
1771da177e4SLinus Torvalds  *	@ulen: Length in user space
1781da177e4SLinus Torvalds  *
1791da177e4SLinus Torvalds  *	The address is copied into kernel space. If the provided address is
1801da177e4SLinus Torvalds  *	too long an error code of -EINVAL is returned. If the copy gives
1811da177e4SLinus Torvalds  *	invalid addresses -EFAULT is returned. On a success 0 is returned.
1821da177e4SLinus Torvalds  */
1831da177e4SLinus Torvalds 
184230b1839SYOSHIFUJI Hideaki int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr *kaddr)
1851da177e4SLinus Torvalds {
186230b1839SYOSHIFUJI Hideaki 	if (ulen < 0 || ulen > sizeof(struct sockaddr_storage))
1871da177e4SLinus Torvalds 		return -EINVAL;
1881da177e4SLinus Torvalds 	if (ulen == 0)
1891da177e4SLinus Torvalds 		return 0;
1901da177e4SLinus Torvalds 	if (copy_from_user(kaddr, uaddr, ulen))
1911da177e4SLinus Torvalds 		return -EFAULT;
1923ec3b2fbSDavid Woodhouse 	return audit_sockaddr(ulen, kaddr);
1931da177e4SLinus Torvalds }
1941da177e4SLinus Torvalds 
1951da177e4SLinus Torvalds /**
1961da177e4SLinus Torvalds  *	move_addr_to_user	-	copy an address to user space
1971da177e4SLinus Torvalds  *	@kaddr: kernel space address
1981da177e4SLinus Torvalds  *	@klen: length of address in kernel
1991da177e4SLinus Torvalds  *	@uaddr: user space address
2001da177e4SLinus Torvalds  *	@ulen: pointer to user length field
2011da177e4SLinus Torvalds  *
2021da177e4SLinus Torvalds  *	The value pointed to by ulen on entry is the buffer length available.
2031da177e4SLinus Torvalds  *	This is overwritten with the buffer space used. -EINVAL is returned
2041da177e4SLinus Torvalds  *	if an overlong buffer is specified or a negative buffer size. -EFAULT
2051da177e4SLinus Torvalds  *	is returned if either the buffer or the length field are not
2061da177e4SLinus Torvalds  *	accessible.
2071da177e4SLinus Torvalds  *	After copying the data up to the limit the user specifies, the true
2081da177e4SLinus Torvalds  *	length of the data is written over the length limit the user
2091da177e4SLinus Torvalds  *	specified. Zero is returned for a success.
2101da177e4SLinus Torvalds  */
2111da177e4SLinus Torvalds 
21211165f14Sstephen hemminger static int move_addr_to_user(struct sockaddr *kaddr, int klen,
21311165f14Sstephen hemminger 			     void __user *uaddr, int __user *ulen)
2141da177e4SLinus Torvalds {
2151da177e4SLinus Torvalds 	int err;
2161da177e4SLinus Torvalds 	int len;
2171da177e4SLinus Torvalds 
21889bddce5SStephen Hemminger 	err = get_user(len, ulen);
21989bddce5SStephen Hemminger 	if (err)
2201da177e4SLinus Torvalds 		return err;
2211da177e4SLinus Torvalds 	if (len > klen)
2221da177e4SLinus Torvalds 		len = klen;
223230b1839SYOSHIFUJI Hideaki 	if (len < 0 || len > sizeof(struct sockaddr_storage))
2241da177e4SLinus Torvalds 		return -EINVAL;
22589bddce5SStephen Hemminger 	if (len) {
226d6fe3945SSteve Grubb 		if (audit_sockaddr(klen, kaddr))
227d6fe3945SSteve Grubb 			return -ENOMEM;
2281da177e4SLinus Torvalds 		if (copy_to_user(uaddr, kaddr, len))
2291da177e4SLinus Torvalds 			return -EFAULT;
2301da177e4SLinus Torvalds 	}
2311da177e4SLinus Torvalds 	/*
2321da177e4SLinus Torvalds 	 *      "fromlen shall refer to the value before truncation.."
2331da177e4SLinus Torvalds 	 *                      1003.1g
2341da177e4SLinus Torvalds 	 */
2351da177e4SLinus Torvalds 	return __put_user(klen, ulen);
2361da177e4SLinus Torvalds }
2371da177e4SLinus Torvalds 
238e18b890bSChristoph Lameter static struct kmem_cache *sock_inode_cachep __read_mostly;
2391da177e4SLinus Torvalds 
2401da177e4SLinus Torvalds static struct inode *sock_alloc_inode(struct super_block *sb)
2411da177e4SLinus Torvalds {
2421da177e4SLinus Torvalds 	struct socket_alloc *ei;
243eaefd110SEric Dumazet 	struct socket_wq *wq;
24489bddce5SStephen Hemminger 
245e94b1766SChristoph Lameter 	ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL);
2461da177e4SLinus Torvalds 	if (!ei)
2471da177e4SLinus Torvalds 		return NULL;
248eaefd110SEric Dumazet 	wq = kmalloc(sizeof(*wq), GFP_KERNEL);
249eaefd110SEric Dumazet 	if (!wq) {
25043815482SEric Dumazet 		kmem_cache_free(sock_inode_cachep, ei);
25143815482SEric Dumazet 		return NULL;
25243815482SEric Dumazet 	}
253eaefd110SEric Dumazet 	init_waitqueue_head(&wq->wait);
254eaefd110SEric Dumazet 	wq->fasync_list = NULL;
255eaefd110SEric Dumazet 	RCU_INIT_POINTER(ei->socket.wq, wq);
2561da177e4SLinus Torvalds 
2571da177e4SLinus Torvalds 	ei->socket.state = SS_UNCONNECTED;
2581da177e4SLinus Torvalds 	ei->socket.flags = 0;
2591da177e4SLinus Torvalds 	ei->socket.ops = NULL;
2601da177e4SLinus Torvalds 	ei->socket.sk = NULL;
2611da177e4SLinus Torvalds 	ei->socket.file = NULL;
2621da177e4SLinus Torvalds 
2631da177e4SLinus Torvalds 	return &ei->vfs_inode;
2641da177e4SLinus Torvalds }
2651da177e4SLinus Torvalds 
2661da177e4SLinus Torvalds static void sock_destroy_inode(struct inode *inode)
2671da177e4SLinus Torvalds {
26843815482SEric Dumazet 	struct socket_alloc *ei;
269eaefd110SEric Dumazet 	struct socket_wq *wq;
27043815482SEric Dumazet 
27143815482SEric Dumazet 	ei = container_of(inode, struct socket_alloc, vfs_inode);
272eaefd110SEric Dumazet 	wq = rcu_dereference_protected(ei->socket.wq, 1);
27361845220SLai Jiangshan 	kfree_rcu(wq, rcu);
27443815482SEric Dumazet 	kmem_cache_free(sock_inode_cachep, ei);
2751da177e4SLinus Torvalds }
2761da177e4SLinus Torvalds 
27751cc5068SAlexey Dobriyan static void init_once(void *foo)
2781da177e4SLinus Torvalds {
2791da177e4SLinus Torvalds 	struct socket_alloc *ei = (struct socket_alloc *)foo;
2801da177e4SLinus Torvalds 
2811da177e4SLinus Torvalds 	inode_init_once(&ei->vfs_inode);
2821da177e4SLinus Torvalds }
2831da177e4SLinus Torvalds 
2841da177e4SLinus Torvalds static int init_inodecache(void)
2851da177e4SLinus Torvalds {
2861da177e4SLinus Torvalds 	sock_inode_cachep = kmem_cache_create("sock_inode_cache",
2871da177e4SLinus Torvalds 					      sizeof(struct socket_alloc),
28889bddce5SStephen Hemminger 					      0,
28989bddce5SStephen Hemminger 					      (SLAB_HWCACHE_ALIGN |
29089bddce5SStephen Hemminger 					       SLAB_RECLAIM_ACCOUNT |
291fffb60f9SPaul Jackson 					       SLAB_MEM_SPREAD),
29220c2df83SPaul Mundt 					      init_once);
2931da177e4SLinus Torvalds 	if (sock_inode_cachep == NULL)
2941da177e4SLinus Torvalds 		return -ENOMEM;
2951da177e4SLinus Torvalds 	return 0;
2961da177e4SLinus Torvalds }
2971da177e4SLinus Torvalds 
298b87221deSAlexey Dobriyan static const struct super_operations sockfs_ops = {
2991da177e4SLinus Torvalds 	.alloc_inode	= sock_alloc_inode,
3001da177e4SLinus Torvalds 	.destroy_inode	= sock_destroy_inode,
3011da177e4SLinus Torvalds 	.statfs		= simple_statfs,
3021da177e4SLinus Torvalds };
3031da177e4SLinus Torvalds 
304c23fbb6bSEric Dumazet /*
305c23fbb6bSEric Dumazet  * sockfs_dname() is called from d_path().
306c23fbb6bSEric Dumazet  */
307c23fbb6bSEric Dumazet static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen)
308c23fbb6bSEric Dumazet {
309c23fbb6bSEric Dumazet 	return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]",
310c23fbb6bSEric Dumazet 				dentry->d_inode->i_ino);
311c23fbb6bSEric Dumazet }
312c23fbb6bSEric Dumazet 
3133ba13d17SAl Viro static const struct dentry_operations sockfs_dentry_operations = {
314c23fbb6bSEric Dumazet 	.d_dname  = sockfs_dname,
3151da177e4SLinus Torvalds };
3161da177e4SLinus Torvalds 
317c74a1cbbSAl Viro static struct dentry *sockfs_mount(struct file_system_type *fs_type,
318c74a1cbbSAl Viro 			 int flags, const char *dev_name, void *data)
319c74a1cbbSAl Viro {
320c74a1cbbSAl Viro 	return mount_pseudo(fs_type, "socket:", &sockfs_ops,
321c74a1cbbSAl Viro 		&sockfs_dentry_operations, SOCKFS_MAGIC);
322c74a1cbbSAl Viro }
323c74a1cbbSAl Viro 
324c74a1cbbSAl Viro static struct vfsmount *sock_mnt __read_mostly;
325c74a1cbbSAl Viro 
326c74a1cbbSAl Viro static struct file_system_type sock_fs_type = {
327c74a1cbbSAl Viro 	.name =		"sockfs",
328c74a1cbbSAl Viro 	.mount =	sockfs_mount,
329c74a1cbbSAl Viro 	.kill_sb =	kill_anon_super,
330c74a1cbbSAl Viro };
331c74a1cbbSAl Viro 
3321da177e4SLinus Torvalds /*
3331da177e4SLinus Torvalds  *	Obtains the first available file descriptor and sets it up for use.
3341da177e4SLinus Torvalds  *
33539d8c1b6SDavid S. Miller  *	These functions create file structures and maps them to fd space
33639d8c1b6SDavid S. Miller  *	of the current process. On success it returns file descriptor
3371da177e4SLinus Torvalds  *	and file struct implicitly stored in sock->file.
3381da177e4SLinus Torvalds  *	Note that another thread may close file descriptor before we return
3391da177e4SLinus Torvalds  *	from this function. We use the fact that now we do not refer
3401da177e4SLinus Torvalds  *	to socket after mapping. If one day we will need it, this
3411da177e4SLinus Torvalds  *	function will increment ref. count on file by 1.
3421da177e4SLinus Torvalds  *
3431da177e4SLinus Torvalds  *	In any case returned fd MAY BE not valid!
3441da177e4SLinus Torvalds  *	This race condition is unavoidable
3451da177e4SLinus Torvalds  *	with shared fd spaces, we cannot solve it inside kernel,
3461da177e4SLinus Torvalds  *	but we take care of internal coherence yet.
3471da177e4SLinus Torvalds  */
3481da177e4SLinus Torvalds 
3497cbe66b6SAl Viro static int sock_alloc_file(struct socket *sock, struct file **f, int flags)
3501da177e4SLinus Torvalds {
3517cbe66b6SAl Viro 	struct qstr name = { .name = "" };
3522c48b9c4SAl Viro 	struct path path;
3537cbe66b6SAl Viro 	struct file *file;
3541da177e4SLinus Torvalds 	int fd;
3551da177e4SLinus Torvalds 
356a677a039SUlrich Drepper 	fd = get_unused_fd_flags(flags);
3577cbe66b6SAl Viro 	if (unlikely(fd < 0))
3587cbe66b6SAl Viro 		return fd;
3591da177e4SLinus Torvalds 
3604b936885SNick Piggin 	path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name);
3612c48b9c4SAl Viro 	if (unlikely(!path.dentry)) {
3627cbe66b6SAl Viro 		put_unused_fd(fd);
36339d8c1b6SDavid S. Miller 		return -ENOMEM;
3647cbe66b6SAl Viro 	}
3652c48b9c4SAl Viro 	path.mnt = mntget(sock_mnt);
36639d8c1b6SDavid S. Miller 
3672c48b9c4SAl Viro 	d_instantiate(path.dentry, SOCK_INODE(sock));
368cc3808f8SAl Viro 	SOCK_INODE(sock)->i_fop = &socket_file_ops;
369cc3808f8SAl Viro 
3702c48b9c4SAl Viro 	file = alloc_file(&path, FMODE_READ | FMODE_WRITE,
371cc3808f8SAl Viro 		  &socket_file_ops);
372cc3808f8SAl Viro 	if (unlikely(!file)) {
373cc3808f8SAl Viro 		/* drop dentry, keep inode */
3747de9c6eeSAl Viro 		ihold(path.dentry->d_inode);
3752c48b9c4SAl Viro 		path_put(&path);
376cc3808f8SAl Viro 		put_unused_fd(fd);
377cc3808f8SAl Viro 		return -ENFILE;
378cc3808f8SAl Viro 	}
3791da177e4SLinus Torvalds 
3801da177e4SLinus Torvalds 	sock->file = file;
38177d27200SUlrich Drepper 	file->f_flags = O_RDWR | (flags & O_NONBLOCK);
3821da177e4SLinus Torvalds 	file->f_pos = 0;
38307dc3f07SBenjamin LaHaise 	file->private_data = sock;
38439d8c1b6SDavid S. Miller 
3857cbe66b6SAl Viro 	*f = file;
3867cbe66b6SAl Viro 	return fd;
3871da177e4SLinus Torvalds }
3881da177e4SLinus Torvalds 
389a677a039SUlrich Drepper int sock_map_fd(struct socket *sock, int flags)
39039d8c1b6SDavid S. Miller {
39139d8c1b6SDavid S. Miller 	struct file *newfile;
3927cbe66b6SAl Viro 	int fd = sock_alloc_file(sock, &newfile, flags);
39339d8c1b6SDavid S. Miller 
3947cbe66b6SAl Viro 	if (likely(fd >= 0))
39539d8c1b6SDavid S. Miller 		fd_install(fd, newfile);
3967cbe66b6SAl Viro 
3971da177e4SLinus Torvalds 	return fd;
3981da177e4SLinus Torvalds }
399c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_map_fd);
4001da177e4SLinus Torvalds 
4016cb153caSBenjamin LaHaise static struct socket *sock_from_file(struct file *file, int *err)
4026cb153caSBenjamin LaHaise {
4036cb153caSBenjamin LaHaise 	if (file->f_op == &socket_file_ops)
4046cb153caSBenjamin LaHaise 		return file->private_data;	/* set in sock_map_fd */
4056cb153caSBenjamin LaHaise 
4066cb153caSBenjamin LaHaise 	*err = -ENOTSOCK;
4076cb153caSBenjamin LaHaise 	return NULL;
4086cb153caSBenjamin LaHaise }
4096cb153caSBenjamin LaHaise 
4101da177e4SLinus Torvalds /**
4111da177e4SLinus Torvalds  *	sockfd_lookup - Go from a file number to its socket slot
4121da177e4SLinus Torvalds  *	@fd: file handle
4131da177e4SLinus Torvalds  *	@err: pointer to an error code return
4141da177e4SLinus Torvalds  *
4151da177e4SLinus Torvalds  *	The file handle passed in is locked and the socket it is bound
4161da177e4SLinus Torvalds  *	too is returned. If an error occurs the err pointer is overwritten
4171da177e4SLinus Torvalds  *	with a negative errno code and NULL is returned. The function checks
4181da177e4SLinus Torvalds  *	for both invalid handles and passing a handle which is not a socket.
4191da177e4SLinus Torvalds  *
4201da177e4SLinus Torvalds  *	On a success the socket object pointer is returned.
4211da177e4SLinus Torvalds  */
4221da177e4SLinus Torvalds 
4231da177e4SLinus Torvalds struct socket *sockfd_lookup(int fd, int *err)
4241da177e4SLinus Torvalds {
4251da177e4SLinus Torvalds 	struct file *file;
4261da177e4SLinus Torvalds 	struct socket *sock;
4271da177e4SLinus Torvalds 
42889bddce5SStephen Hemminger 	file = fget(fd);
42989bddce5SStephen Hemminger 	if (!file) {
4301da177e4SLinus Torvalds 		*err = -EBADF;
4311da177e4SLinus Torvalds 		return NULL;
4321da177e4SLinus Torvalds 	}
43389bddce5SStephen Hemminger 
4346cb153caSBenjamin LaHaise 	sock = sock_from_file(file, err);
4356cb153caSBenjamin LaHaise 	if (!sock)
4361da177e4SLinus Torvalds 		fput(file);
4376cb153caSBenjamin LaHaise 	return sock;
4381da177e4SLinus Torvalds }
439c6d409cfSEric Dumazet EXPORT_SYMBOL(sockfd_lookup);
4401da177e4SLinus Torvalds 
4416cb153caSBenjamin LaHaise static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
4426cb153caSBenjamin LaHaise {
4436cb153caSBenjamin LaHaise 	struct file *file;
4446cb153caSBenjamin LaHaise 	struct socket *sock;
4456cb153caSBenjamin LaHaise 
4463672558cSHua Zhong 	*err = -EBADF;
4476cb153caSBenjamin LaHaise 	file = fget_light(fd, fput_needed);
4486cb153caSBenjamin LaHaise 	if (file) {
4496cb153caSBenjamin LaHaise 		sock = sock_from_file(file, err);
4506cb153caSBenjamin LaHaise 		if (sock)
4511da177e4SLinus Torvalds 			return sock;
4526cb153caSBenjamin LaHaise 		fput_light(file, *fput_needed);
4536cb153caSBenjamin LaHaise 	}
4546cb153caSBenjamin LaHaise 	return NULL;
4551da177e4SLinus Torvalds }
4561da177e4SLinus Torvalds 
4571da177e4SLinus Torvalds /**
4581da177e4SLinus Torvalds  *	sock_alloc	-	allocate a socket
4591da177e4SLinus Torvalds  *
4601da177e4SLinus Torvalds  *	Allocate a new inode and socket object. The two are bound together
4611da177e4SLinus Torvalds  *	and initialised. The socket is then returned. If we are out of inodes
4621da177e4SLinus Torvalds  *	NULL is returned.
4631da177e4SLinus Torvalds  */
4641da177e4SLinus Torvalds 
4651da177e4SLinus Torvalds static struct socket *sock_alloc(void)
4661da177e4SLinus Torvalds {
4671da177e4SLinus Torvalds 	struct inode *inode;
4681da177e4SLinus Torvalds 	struct socket *sock;
4691da177e4SLinus Torvalds 
470a209dfc7SEric Dumazet 	inode = new_inode_pseudo(sock_mnt->mnt_sb);
4711da177e4SLinus Torvalds 	if (!inode)
4721da177e4SLinus Torvalds 		return NULL;
4731da177e4SLinus Torvalds 
4741da177e4SLinus Torvalds 	sock = SOCKET_I(inode);
4751da177e4SLinus Torvalds 
47629a020d3SEric Dumazet 	kmemcheck_annotate_bitfield(sock, type);
47785fe4025SChristoph Hellwig 	inode->i_ino = get_next_ino();
4781da177e4SLinus Torvalds 	inode->i_mode = S_IFSOCK | S_IRWXUGO;
4798192b0c4SDavid Howells 	inode->i_uid = current_fsuid();
4808192b0c4SDavid Howells 	inode->i_gid = current_fsgid();
4811da177e4SLinus Torvalds 
4824e69489aSEric Dumazet 	percpu_add(sockets_in_use, 1);
4831da177e4SLinus Torvalds 	return sock;
4841da177e4SLinus Torvalds }
4851da177e4SLinus Torvalds 
4861da177e4SLinus Torvalds /*
4871da177e4SLinus Torvalds  *	In theory you can't get an open on this inode, but /proc provides
4881da177e4SLinus Torvalds  *	a back door. Remember to keep it shut otherwise you'll let the
4891da177e4SLinus Torvalds  *	creepy crawlies in.
4901da177e4SLinus Torvalds  */
4911da177e4SLinus Torvalds 
4921da177e4SLinus Torvalds static int sock_no_open(struct inode *irrelevant, struct file *dontcare)
4931da177e4SLinus Torvalds {
4941da177e4SLinus Torvalds 	return -ENXIO;
4951da177e4SLinus Torvalds }
4961da177e4SLinus Torvalds 
4974b6f5d20SArjan van de Ven const struct file_operations bad_sock_fops = {
4981da177e4SLinus Torvalds 	.owner = THIS_MODULE,
4991da177e4SLinus Torvalds 	.open = sock_no_open,
5006038f373SArnd Bergmann 	.llseek = noop_llseek,
5011da177e4SLinus Torvalds };
5021da177e4SLinus Torvalds 
5031da177e4SLinus Torvalds /**
5041da177e4SLinus Torvalds  *	sock_release	-	close a socket
5051da177e4SLinus Torvalds  *	@sock: socket to close
5061da177e4SLinus Torvalds  *
5071da177e4SLinus Torvalds  *	The socket is released from the protocol stack if it has a release
5081da177e4SLinus Torvalds  *	callback, and the inode is then released if the socket is bound to
5091da177e4SLinus Torvalds  *	an inode not a file.
5101da177e4SLinus Torvalds  */
5111da177e4SLinus Torvalds 
5121da177e4SLinus Torvalds void sock_release(struct socket *sock)
5131da177e4SLinus Torvalds {
5141da177e4SLinus Torvalds 	if (sock->ops) {
5151da177e4SLinus Torvalds 		struct module *owner = sock->ops->owner;
5161da177e4SLinus Torvalds 
5171da177e4SLinus Torvalds 		sock->ops->release(sock);
5181da177e4SLinus Torvalds 		sock->ops = NULL;
5191da177e4SLinus Torvalds 		module_put(owner);
5201da177e4SLinus Torvalds 	}
5211da177e4SLinus Torvalds 
522eaefd110SEric Dumazet 	if (rcu_dereference_protected(sock->wq, 1)->fasync_list)
5231da177e4SLinus Torvalds 		printk(KERN_ERR "sock_release: fasync list not empty!\n");
5241da177e4SLinus Torvalds 
5254e69489aSEric Dumazet 	percpu_sub(sockets_in_use, 1);
5261da177e4SLinus Torvalds 	if (!sock->file) {
5271da177e4SLinus Torvalds 		iput(SOCK_INODE(sock));
5281da177e4SLinus Torvalds 		return;
5291da177e4SLinus Torvalds 	}
5301da177e4SLinus Torvalds 	sock->file = NULL;
5311da177e4SLinus Torvalds }
532c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_release);
5331da177e4SLinus Torvalds 
5342244d07bSOliver Hartkopp int sock_tx_timestamp(struct sock *sk, __u8 *tx_flags)
53520d49473SPatrick Ohly {
5362244d07bSOliver Hartkopp 	*tx_flags = 0;
53720d49473SPatrick Ohly 	if (sock_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE))
5382244d07bSOliver Hartkopp 		*tx_flags |= SKBTX_HW_TSTAMP;
53920d49473SPatrick Ohly 	if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE))
5402244d07bSOliver Hartkopp 		*tx_flags |= SKBTX_SW_TSTAMP;
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 
5545bc1421eSNeil Horman 	sock_update_netprioidx(sock->sk);
5555bc1421eSNeil Horman 
5561da177e4SLinus Torvalds 	si->sock = sock;
5571da177e4SLinus Torvalds 	si->scm = NULL;
5581da177e4SLinus Torvalds 	si->msg = msg;
5591da177e4SLinus Torvalds 	si->size = size;
5601da177e4SLinus Torvalds 
5611da177e4SLinus Torvalds 	return sock->ops->sendmsg(iocb, sock, msg, size);
5621da177e4SLinus Torvalds }
5631da177e4SLinus Torvalds 
564228e548eSAnton Blanchard static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock,
565228e548eSAnton Blanchard 				 struct msghdr *msg, size_t size)
566228e548eSAnton Blanchard {
567228e548eSAnton Blanchard 	int err = security_socket_sendmsg(sock, msg, size);
568228e548eSAnton Blanchard 
569228e548eSAnton Blanchard 	return err ?: __sock_sendmsg_nosec(iocb, sock, msg, size);
570228e548eSAnton Blanchard }
571228e548eSAnton Blanchard 
5721da177e4SLinus Torvalds int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
5731da177e4SLinus Torvalds {
5741da177e4SLinus Torvalds 	struct kiocb iocb;
5751da177e4SLinus Torvalds 	struct sock_iocb siocb;
5761da177e4SLinus Torvalds 	int ret;
5771da177e4SLinus Torvalds 
5781da177e4SLinus Torvalds 	init_sync_kiocb(&iocb, NULL);
5791da177e4SLinus Torvalds 	iocb.private = &siocb;
5801da177e4SLinus Torvalds 	ret = __sock_sendmsg(&iocb, sock, msg, size);
5811da177e4SLinus Torvalds 	if (-EIOCBQUEUED == ret)
5821da177e4SLinus Torvalds 		ret = wait_on_sync_kiocb(&iocb);
5831da177e4SLinus Torvalds 	return ret;
5841da177e4SLinus Torvalds }
585c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_sendmsg);
5861da177e4SLinus Torvalds 
587894dc24cSEric Dumazet static int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg, size_t size)
588228e548eSAnton Blanchard {
589228e548eSAnton Blanchard 	struct kiocb iocb;
590228e548eSAnton Blanchard 	struct sock_iocb siocb;
591228e548eSAnton Blanchard 	int ret;
592228e548eSAnton Blanchard 
593228e548eSAnton Blanchard 	init_sync_kiocb(&iocb, NULL);
594228e548eSAnton Blanchard 	iocb.private = &siocb;
595228e548eSAnton Blanchard 	ret = __sock_sendmsg_nosec(&iocb, sock, msg, size);
596228e548eSAnton Blanchard 	if (-EIOCBQUEUED == ret)
597228e548eSAnton Blanchard 		ret = wait_on_sync_kiocb(&iocb);
598228e548eSAnton Blanchard 	return ret;
599228e548eSAnton Blanchard }
600228e548eSAnton Blanchard 
6011da177e4SLinus Torvalds int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
6021da177e4SLinus Torvalds 		   struct kvec *vec, size_t num, size_t size)
6031da177e4SLinus Torvalds {
6041da177e4SLinus Torvalds 	mm_segment_t oldfs = get_fs();
6051da177e4SLinus Torvalds 	int result;
6061da177e4SLinus Torvalds 
6071da177e4SLinus Torvalds 	set_fs(KERNEL_DS);
6081da177e4SLinus Torvalds 	/*
6091da177e4SLinus Torvalds 	 * the following is safe, since for compiler definitions of kvec and
6101da177e4SLinus Torvalds 	 * iovec are identical, yielding the same in-core layout and alignment
6111da177e4SLinus Torvalds 	 */
61289bddce5SStephen Hemminger 	msg->msg_iov = (struct iovec *)vec;
6131da177e4SLinus Torvalds 	msg->msg_iovlen = num;
6141da177e4SLinus Torvalds 	result = sock_sendmsg(sock, msg, size);
6151da177e4SLinus Torvalds 	set_fs(oldfs);
6161da177e4SLinus Torvalds 	return result;
6171da177e4SLinus Torvalds }
618c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendmsg);
6191da177e4SLinus Torvalds 
62020d49473SPatrick Ohly static int ktime2ts(ktime_t kt, struct timespec *ts)
62120d49473SPatrick Ohly {
62220d49473SPatrick Ohly 	if (kt.tv64) {
62320d49473SPatrick Ohly 		*ts = ktime_to_timespec(kt);
62420d49473SPatrick Ohly 		return 1;
62520d49473SPatrick Ohly 	} else {
62620d49473SPatrick Ohly 		return 0;
62720d49473SPatrick Ohly 	}
62820d49473SPatrick Ohly }
62920d49473SPatrick Ohly 
63092f37fd2SEric Dumazet /*
63192f37fd2SEric Dumazet  * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
63292f37fd2SEric Dumazet  */
63392f37fd2SEric Dumazet void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
63492f37fd2SEric Dumazet 	struct sk_buff *skb)
63592f37fd2SEric Dumazet {
63620d49473SPatrick Ohly 	int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
63720d49473SPatrick Ohly 	struct timespec ts[3];
63820d49473SPatrick Ohly 	int empty = 1;
63920d49473SPatrick Ohly 	struct skb_shared_hwtstamps *shhwtstamps =
64020d49473SPatrick Ohly 		skb_hwtstamps(skb);
64192f37fd2SEric Dumazet 
64220d49473SPatrick Ohly 	/* Race occurred between timestamp enabling and packet
64320d49473SPatrick Ohly 	   receiving.  Fill in the current time for now. */
64420d49473SPatrick Ohly 	if (need_software_tstamp && skb->tstamp.tv64 == 0)
64520d49473SPatrick Ohly 		__net_timestamp(skb);
64620d49473SPatrick Ohly 
64720d49473SPatrick Ohly 	if (need_software_tstamp) {
64892f37fd2SEric Dumazet 		if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
64992f37fd2SEric Dumazet 			struct timeval tv;
65020d49473SPatrick Ohly 			skb_get_timestamp(skb, &tv);
65120d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP,
65220d49473SPatrick Ohly 				 sizeof(tv), &tv);
65392f37fd2SEric Dumazet 		} else {
654842509b8SHagen Paul Pfeifer 			skb_get_timestampns(skb, &ts[0]);
65520d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS,
656842509b8SHagen Paul Pfeifer 				 sizeof(ts[0]), &ts[0]);
65792f37fd2SEric Dumazet 		}
65892f37fd2SEric Dumazet 	}
65992f37fd2SEric Dumazet 
66020d49473SPatrick Ohly 
66120d49473SPatrick Ohly 	memset(ts, 0, sizeof(ts));
66220d49473SPatrick Ohly 	if (skb->tstamp.tv64 &&
66320d49473SPatrick Ohly 	    sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE)) {
66420d49473SPatrick Ohly 		skb_get_timestampns(skb, ts + 0);
66520d49473SPatrick Ohly 		empty = 0;
66620d49473SPatrick Ohly 	}
66720d49473SPatrick Ohly 	if (shhwtstamps) {
66820d49473SPatrick Ohly 		if (sock_flag(sk, SOCK_TIMESTAMPING_SYS_HARDWARE) &&
66920d49473SPatrick Ohly 		    ktime2ts(shhwtstamps->syststamp, ts + 1))
67020d49473SPatrick Ohly 			empty = 0;
67120d49473SPatrick Ohly 		if (sock_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE) &&
67220d49473SPatrick Ohly 		    ktime2ts(shhwtstamps->hwtstamp, ts + 2))
67320d49473SPatrick Ohly 			empty = 0;
67420d49473SPatrick Ohly 	}
67520d49473SPatrick Ohly 	if (!empty)
67620d49473SPatrick Ohly 		put_cmsg(msg, SOL_SOCKET,
67720d49473SPatrick Ohly 			 SCM_TIMESTAMPING, sizeof(ts), &ts);
67820d49473SPatrick Ohly }
6797c81fd8bSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
6807c81fd8bSArnaldo Carvalho de Melo 
6816e3e939fSJohannes Berg void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
6826e3e939fSJohannes Berg 	struct sk_buff *skb)
6836e3e939fSJohannes Berg {
6846e3e939fSJohannes Berg 	int ack;
6856e3e939fSJohannes Berg 
6866e3e939fSJohannes Berg 	if (!sock_flag(sk, SOCK_WIFI_STATUS))
6876e3e939fSJohannes Berg 		return;
6886e3e939fSJohannes Berg 	if (!skb->wifi_acked_valid)
6896e3e939fSJohannes Berg 		return;
6906e3e939fSJohannes Berg 
6916e3e939fSJohannes Berg 	ack = skb->wifi_acked;
6926e3e939fSJohannes Berg 
6936e3e939fSJohannes Berg 	put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack);
6946e3e939fSJohannes Berg }
6956e3e939fSJohannes Berg EXPORT_SYMBOL_GPL(__sock_recv_wifi_status);
6966e3e939fSJohannes Berg 
69711165f14Sstephen hemminger static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk,
69811165f14Sstephen hemminger 				   struct sk_buff *skb)
6993b885787SNeil Horman {
7003b885787SNeil Horman 	if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && skb->dropcount)
7013b885787SNeil Horman 		put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL,
7023b885787SNeil Horman 			sizeof(__u32), &skb->dropcount);
7033b885787SNeil Horman }
7043b885787SNeil Horman 
705767dd033SEric Dumazet void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
7063b885787SNeil Horman 	struct sk_buff *skb)
7073b885787SNeil Horman {
7083b885787SNeil Horman 	sock_recv_timestamp(msg, sk, skb);
7093b885787SNeil Horman 	sock_recv_drops(msg, sk, skb);
7103b885787SNeil Horman }
711767dd033SEric Dumazet EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops);
7123b885787SNeil Horman 
713a2e27255SArnaldo Carvalho de Melo static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock,
7141da177e4SLinus Torvalds 				       struct msghdr *msg, size_t size, int flags)
7151da177e4SLinus Torvalds {
7161da177e4SLinus Torvalds 	struct sock_iocb *si = kiocb_to_siocb(iocb);
7171da177e4SLinus Torvalds 
718f8451725SHerbert Xu 	sock_update_classid(sock->sk);
719f8451725SHerbert Xu 
7201da177e4SLinus Torvalds 	si->sock = sock;
7211da177e4SLinus Torvalds 	si->scm = NULL;
7221da177e4SLinus Torvalds 	si->msg = msg;
7231da177e4SLinus Torvalds 	si->size = size;
7241da177e4SLinus Torvalds 	si->flags = flags;
7251da177e4SLinus Torvalds 
7261da177e4SLinus Torvalds 	return sock->ops->recvmsg(iocb, sock, msg, size, flags);
7271da177e4SLinus Torvalds }
7281da177e4SLinus Torvalds 
729a2e27255SArnaldo Carvalho de Melo static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock,
730a2e27255SArnaldo Carvalho de Melo 				 struct msghdr *msg, size_t size, int flags)
731a2e27255SArnaldo Carvalho de Melo {
732a2e27255SArnaldo Carvalho de Melo 	int err = security_socket_recvmsg(sock, msg, size, flags);
733a2e27255SArnaldo Carvalho de Melo 
734a2e27255SArnaldo Carvalho de Melo 	return err ?: __sock_recvmsg_nosec(iocb, sock, msg, size, flags);
735a2e27255SArnaldo Carvalho de Melo }
736a2e27255SArnaldo Carvalho de Melo 
7371da177e4SLinus Torvalds int sock_recvmsg(struct socket *sock, struct msghdr *msg,
7381da177e4SLinus Torvalds 		 size_t size, int flags)
7391da177e4SLinus Torvalds {
7401da177e4SLinus Torvalds 	struct kiocb iocb;
7411da177e4SLinus Torvalds 	struct sock_iocb siocb;
7421da177e4SLinus Torvalds 	int ret;
7431da177e4SLinus Torvalds 
7441da177e4SLinus Torvalds 	init_sync_kiocb(&iocb, NULL);
7451da177e4SLinus Torvalds 	iocb.private = &siocb;
7461da177e4SLinus Torvalds 	ret = __sock_recvmsg(&iocb, sock, msg, size, flags);
7471da177e4SLinus Torvalds 	if (-EIOCBQUEUED == ret)
7481da177e4SLinus Torvalds 		ret = wait_on_sync_kiocb(&iocb);
7491da177e4SLinus Torvalds 	return ret;
7501da177e4SLinus Torvalds }
751c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_recvmsg);
7521da177e4SLinus Torvalds 
753a2e27255SArnaldo Carvalho de Melo static int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
754a2e27255SArnaldo Carvalho de Melo 			      size_t size, int flags)
755a2e27255SArnaldo Carvalho de Melo {
756a2e27255SArnaldo Carvalho de Melo 	struct kiocb iocb;
757a2e27255SArnaldo Carvalho de Melo 	struct sock_iocb siocb;
758a2e27255SArnaldo Carvalho de Melo 	int ret;
759a2e27255SArnaldo Carvalho de Melo 
760a2e27255SArnaldo Carvalho de Melo 	init_sync_kiocb(&iocb, NULL);
761a2e27255SArnaldo Carvalho de Melo 	iocb.private = &siocb;
762a2e27255SArnaldo Carvalho de Melo 	ret = __sock_recvmsg_nosec(&iocb, sock, msg, size, flags);
763a2e27255SArnaldo Carvalho de Melo 	if (-EIOCBQUEUED == ret)
764a2e27255SArnaldo Carvalho de Melo 		ret = wait_on_sync_kiocb(&iocb);
765a2e27255SArnaldo Carvalho de Melo 	return ret;
766a2e27255SArnaldo Carvalho de Melo }
767a2e27255SArnaldo Carvalho de Melo 
768c1249c0aSMartin Lucina /**
769c1249c0aSMartin Lucina  * kernel_recvmsg - Receive a message from a socket (kernel space)
770c1249c0aSMartin Lucina  * @sock:       The socket to receive the message from
771c1249c0aSMartin Lucina  * @msg:        Received message
772c1249c0aSMartin Lucina  * @vec:        Input s/g array for message data
773c1249c0aSMartin Lucina  * @num:        Size of input s/g array
774c1249c0aSMartin Lucina  * @size:       Number of bytes to read
775c1249c0aSMartin Lucina  * @flags:      Message flags (MSG_DONTWAIT, etc...)
776c1249c0aSMartin Lucina  *
777c1249c0aSMartin Lucina  * On return the msg structure contains the scatter/gather array passed in the
778c1249c0aSMartin Lucina  * vec argument. The array is modified so that it consists of the unfilled
779c1249c0aSMartin Lucina  * portion of the original array.
780c1249c0aSMartin Lucina  *
781c1249c0aSMartin Lucina  * The returned value is the total number of bytes received, or an error.
782c1249c0aSMartin Lucina  */
7831da177e4SLinus Torvalds int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
78489bddce5SStephen Hemminger 		   struct kvec *vec, size_t num, size_t size, int flags)
7851da177e4SLinus Torvalds {
7861da177e4SLinus Torvalds 	mm_segment_t oldfs = get_fs();
7871da177e4SLinus Torvalds 	int result;
7881da177e4SLinus Torvalds 
7891da177e4SLinus Torvalds 	set_fs(KERNEL_DS);
7901da177e4SLinus Torvalds 	/*
7911da177e4SLinus Torvalds 	 * the following is safe, since for compiler definitions of kvec and
7921da177e4SLinus Torvalds 	 * iovec are identical, yielding the same in-core layout and alignment
7931da177e4SLinus Torvalds 	 */
79489bddce5SStephen Hemminger 	msg->msg_iov = (struct iovec *)vec, msg->msg_iovlen = num;
7951da177e4SLinus Torvalds 	result = sock_recvmsg(sock, msg, size, flags);
7961da177e4SLinus Torvalds 	set_fs(oldfs);
7971da177e4SLinus Torvalds 	return result;
7981da177e4SLinus Torvalds }
799c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_recvmsg);
8001da177e4SLinus Torvalds 
8011da177e4SLinus Torvalds static void sock_aio_dtor(struct kiocb *iocb)
8021da177e4SLinus Torvalds {
8031da177e4SLinus Torvalds 	kfree(iocb->private);
8041da177e4SLinus Torvalds }
8051da177e4SLinus Torvalds 
80620380731SArnaldo Carvalho de Melo static ssize_t sock_sendpage(struct file *file, struct page *page,
8071da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more)
8081da177e4SLinus Torvalds {
8091da177e4SLinus Torvalds 	struct socket *sock;
8101da177e4SLinus Torvalds 	int flags;
8111da177e4SLinus Torvalds 
812b69aee04SEric Dumazet 	sock = file->private_data;
8131da177e4SLinus Torvalds 
8141da177e4SLinus Torvalds 	flags = !(file->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT;
8151da177e4SLinus Torvalds 	if (more)
8161da177e4SLinus Torvalds 		flags |= MSG_MORE;
8171da177e4SLinus Torvalds 
818e6949583SLinus Torvalds 	return kernel_sendpage(sock, page, offset, size, flags);
8191da177e4SLinus Torvalds }
8201da177e4SLinus Torvalds 
8219c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
8229c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
8239c55e01cSJens Axboe 				unsigned int flags)
8249c55e01cSJens Axboe {
8259c55e01cSJens Axboe 	struct socket *sock = file->private_data;
8269c55e01cSJens Axboe 
827997b37daSRémi Denis-Courmont 	if (unlikely(!sock->ops->splice_read))
828997b37daSRémi Denis-Courmont 		return -EINVAL;
829997b37daSRémi Denis-Courmont 
830f8451725SHerbert Xu 	sock_update_classid(sock->sk);
831f8451725SHerbert Xu 
8329c55e01cSJens Axboe 	return sock->ops->splice_read(sock, ppos, pipe, len, flags);
8339c55e01cSJens Axboe }
8349c55e01cSJens Axboe 
835ce1d4d3eSChristoph Hellwig static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
83689bddce5SStephen Hemminger 					 struct sock_iocb *siocb)
837ce1d4d3eSChristoph Hellwig {
838ce1d4d3eSChristoph Hellwig 	if (!is_sync_kiocb(iocb)) {
839ce1d4d3eSChristoph Hellwig 		siocb = kmalloc(sizeof(*siocb), GFP_KERNEL);
840ce1d4d3eSChristoph Hellwig 		if (!siocb)
841ce1d4d3eSChristoph Hellwig 			return NULL;
842ce1d4d3eSChristoph Hellwig 		iocb->ki_dtor = sock_aio_dtor;
843ce1d4d3eSChristoph Hellwig 	}
844ce1d4d3eSChristoph Hellwig 
845ce1d4d3eSChristoph Hellwig 	siocb->kiocb = iocb;
846ce1d4d3eSChristoph Hellwig 	iocb->private = siocb;
847ce1d4d3eSChristoph Hellwig 	return siocb;
848ce1d4d3eSChristoph Hellwig }
849ce1d4d3eSChristoph Hellwig 
850ce1d4d3eSChristoph Hellwig static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb,
851027445c3SBadari Pulavarty 		struct file *file, const struct iovec *iov,
85289bddce5SStephen Hemminger 		unsigned long nr_segs)
853ce1d4d3eSChristoph Hellwig {
854ce1d4d3eSChristoph Hellwig 	struct socket *sock = file->private_data;
855ce1d4d3eSChristoph Hellwig 	size_t size = 0;
856ce1d4d3eSChristoph Hellwig 	int i;
857ce1d4d3eSChristoph Hellwig 
858ce1d4d3eSChristoph Hellwig 	for (i = 0; i < nr_segs; i++)
859ce1d4d3eSChristoph Hellwig 		size += iov[i].iov_len;
860ce1d4d3eSChristoph Hellwig 
861ce1d4d3eSChristoph Hellwig 	msg->msg_name = NULL;
862ce1d4d3eSChristoph Hellwig 	msg->msg_namelen = 0;
863ce1d4d3eSChristoph Hellwig 	msg->msg_control = NULL;
864ce1d4d3eSChristoph Hellwig 	msg->msg_controllen = 0;
865ce1d4d3eSChristoph Hellwig 	msg->msg_iov = (struct iovec *)iov;
866ce1d4d3eSChristoph Hellwig 	msg->msg_iovlen = nr_segs;
867ce1d4d3eSChristoph Hellwig 	msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
868ce1d4d3eSChristoph Hellwig 
869ce1d4d3eSChristoph Hellwig 	return __sock_recvmsg(iocb, sock, msg, size, msg->msg_flags);
870ce1d4d3eSChristoph Hellwig }
871ce1d4d3eSChristoph Hellwig 
872027445c3SBadari Pulavarty static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
873027445c3SBadari Pulavarty 				unsigned long nr_segs, loff_t pos)
874ce1d4d3eSChristoph Hellwig {
875ce1d4d3eSChristoph Hellwig 	struct sock_iocb siocb, *x;
876ce1d4d3eSChristoph Hellwig 
877ce1d4d3eSChristoph Hellwig 	if (pos != 0)
878ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
879027445c3SBadari Pulavarty 
880027445c3SBadari Pulavarty 	if (iocb->ki_left == 0)	/* Match SYS5 behaviour */
881ce1d4d3eSChristoph Hellwig 		return 0;
882ce1d4d3eSChristoph Hellwig 
883027445c3SBadari Pulavarty 
884027445c3SBadari Pulavarty 	x = alloc_sock_iocb(iocb, &siocb);
885ce1d4d3eSChristoph Hellwig 	if (!x)
886ce1d4d3eSChristoph Hellwig 		return -ENOMEM;
887027445c3SBadari Pulavarty 	return do_sock_read(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
888ce1d4d3eSChristoph Hellwig }
889ce1d4d3eSChristoph Hellwig 
890ce1d4d3eSChristoph Hellwig static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb,
891027445c3SBadari Pulavarty 			struct file *file, const struct iovec *iov,
89289bddce5SStephen Hemminger 			unsigned long nr_segs)
893ce1d4d3eSChristoph Hellwig {
894ce1d4d3eSChristoph Hellwig 	struct socket *sock = file->private_data;
895ce1d4d3eSChristoph Hellwig 	size_t size = 0;
896ce1d4d3eSChristoph Hellwig 	int i;
897ce1d4d3eSChristoph Hellwig 
898ce1d4d3eSChristoph Hellwig 	for (i = 0; i < nr_segs; i++)
899ce1d4d3eSChristoph Hellwig 		size += iov[i].iov_len;
900ce1d4d3eSChristoph Hellwig 
901ce1d4d3eSChristoph Hellwig 	msg->msg_name = NULL;
902ce1d4d3eSChristoph Hellwig 	msg->msg_namelen = 0;
903ce1d4d3eSChristoph Hellwig 	msg->msg_control = NULL;
904ce1d4d3eSChristoph Hellwig 	msg->msg_controllen = 0;
905ce1d4d3eSChristoph Hellwig 	msg->msg_iov = (struct iovec *)iov;
906ce1d4d3eSChristoph Hellwig 	msg->msg_iovlen = nr_segs;
907ce1d4d3eSChristoph Hellwig 	msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
908ce1d4d3eSChristoph Hellwig 	if (sock->type == SOCK_SEQPACKET)
909ce1d4d3eSChristoph Hellwig 		msg->msg_flags |= MSG_EOR;
910ce1d4d3eSChristoph Hellwig 
911ce1d4d3eSChristoph Hellwig 	return __sock_sendmsg(iocb, sock, msg, size);
912ce1d4d3eSChristoph Hellwig }
913ce1d4d3eSChristoph Hellwig 
914027445c3SBadari Pulavarty static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
915027445c3SBadari Pulavarty 			  unsigned long nr_segs, loff_t pos)
9161da177e4SLinus Torvalds {
917ce1d4d3eSChristoph Hellwig 	struct sock_iocb siocb, *x;
9181da177e4SLinus Torvalds 
919ce1d4d3eSChristoph Hellwig 	if (pos != 0)
920ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
921027445c3SBadari Pulavarty 
922027445c3SBadari Pulavarty 	x = alloc_sock_iocb(iocb, &siocb);
923ce1d4d3eSChristoph Hellwig 	if (!x)
924ce1d4d3eSChristoph Hellwig 		return -ENOMEM;
925ce1d4d3eSChristoph Hellwig 
926027445c3SBadari Pulavarty 	return do_sock_write(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
9271da177e4SLinus Torvalds }
9281da177e4SLinus Torvalds 
9291da177e4SLinus Torvalds /*
9301da177e4SLinus Torvalds  * Atomic setting of ioctl hooks to avoid race
9311da177e4SLinus Torvalds  * with module unload.
9321da177e4SLinus Torvalds  */
9331da177e4SLinus Torvalds 
9344a3e2f71SArjan van de Ven static DEFINE_MUTEX(br_ioctl_mutex);
935c6d409cfSEric Dumazet static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg);
9361da177e4SLinus Torvalds 
937881d966bSEric W. Biederman void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *))
9381da177e4SLinus Torvalds {
9394a3e2f71SArjan van de Ven 	mutex_lock(&br_ioctl_mutex);
9401da177e4SLinus Torvalds 	br_ioctl_hook = hook;
9414a3e2f71SArjan van de Ven 	mutex_unlock(&br_ioctl_mutex);
9421da177e4SLinus Torvalds }
9431da177e4SLinus Torvalds EXPORT_SYMBOL(brioctl_set);
9441da177e4SLinus Torvalds 
9454a3e2f71SArjan van de Ven static DEFINE_MUTEX(vlan_ioctl_mutex);
946881d966bSEric W. Biederman static int (*vlan_ioctl_hook) (struct net *, void __user *arg);
9471da177e4SLinus Torvalds 
948881d966bSEric W. Biederman void vlan_ioctl_set(int (*hook) (struct net *, void __user *))
9491da177e4SLinus Torvalds {
9504a3e2f71SArjan van de Ven 	mutex_lock(&vlan_ioctl_mutex);
9511da177e4SLinus Torvalds 	vlan_ioctl_hook = hook;
9524a3e2f71SArjan van de Ven 	mutex_unlock(&vlan_ioctl_mutex);
9531da177e4SLinus Torvalds }
9541da177e4SLinus Torvalds EXPORT_SYMBOL(vlan_ioctl_set);
9551da177e4SLinus Torvalds 
9564a3e2f71SArjan van de Ven static DEFINE_MUTEX(dlci_ioctl_mutex);
9571da177e4SLinus Torvalds static int (*dlci_ioctl_hook) (unsigned int, void __user *);
9581da177e4SLinus Torvalds 
9591da177e4SLinus Torvalds void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
9601da177e4SLinus Torvalds {
9614a3e2f71SArjan van de Ven 	mutex_lock(&dlci_ioctl_mutex);
9621da177e4SLinus Torvalds 	dlci_ioctl_hook = hook;
9634a3e2f71SArjan van de Ven 	mutex_unlock(&dlci_ioctl_mutex);
9641da177e4SLinus Torvalds }
9651da177e4SLinus Torvalds EXPORT_SYMBOL(dlci_ioctl_set);
9661da177e4SLinus Torvalds 
9676b96018bSArnd Bergmann static long sock_do_ioctl(struct net *net, struct socket *sock,
9686b96018bSArnd Bergmann 				 unsigned int cmd, unsigned long arg)
9696b96018bSArnd Bergmann {
9706b96018bSArnd Bergmann 	int err;
9716b96018bSArnd Bergmann 	void __user *argp = (void __user *)arg;
9726b96018bSArnd Bergmann 
9736b96018bSArnd Bergmann 	err = sock->ops->ioctl(sock, cmd, arg);
9746b96018bSArnd Bergmann 
9756b96018bSArnd Bergmann 	/*
9766b96018bSArnd Bergmann 	 * If this ioctl is unknown try to hand it down
9776b96018bSArnd Bergmann 	 * to the NIC driver.
9786b96018bSArnd Bergmann 	 */
9796b96018bSArnd Bergmann 	if (err == -ENOIOCTLCMD)
9806b96018bSArnd Bergmann 		err = dev_ioctl(net, cmd, argp);
9816b96018bSArnd Bergmann 
9826b96018bSArnd Bergmann 	return err;
9836b96018bSArnd Bergmann }
9846b96018bSArnd Bergmann 
9851da177e4SLinus Torvalds /*
9861da177e4SLinus Torvalds  *	With an ioctl, arg may well be a user mode pointer, but we don't know
9871da177e4SLinus Torvalds  *	what to do with it - that's up to the protocol still.
9881da177e4SLinus Torvalds  */
9891da177e4SLinus Torvalds 
9901da177e4SLinus Torvalds static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
9911da177e4SLinus Torvalds {
9921da177e4SLinus Torvalds 	struct socket *sock;
993881d966bSEric W. Biederman 	struct sock *sk;
9941da177e4SLinus Torvalds 	void __user *argp = (void __user *)arg;
9951da177e4SLinus Torvalds 	int pid, err;
996881d966bSEric W. Biederman 	struct net *net;
9971da177e4SLinus Torvalds 
998b69aee04SEric Dumazet 	sock = file->private_data;
999881d966bSEric W. Biederman 	sk = sock->sk;
10003b1e0a65SYOSHIFUJI Hideaki 	net = sock_net(sk);
10011da177e4SLinus Torvalds 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
1002881d966bSEric W. Biederman 		err = dev_ioctl(net, cmd, argp);
10031da177e4SLinus Torvalds 	} else
10043d23e349SJohannes Berg #ifdef CONFIG_WEXT_CORE
10051da177e4SLinus Torvalds 	if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
1006881d966bSEric W. Biederman 		err = dev_ioctl(net, cmd, argp);
10071da177e4SLinus Torvalds 	} else
10083d23e349SJohannes Berg #endif
10091da177e4SLinus Torvalds 		switch (cmd) {
10101da177e4SLinus Torvalds 		case FIOSETOWN:
10111da177e4SLinus Torvalds 		case SIOCSPGRP:
10121da177e4SLinus Torvalds 			err = -EFAULT;
10131da177e4SLinus Torvalds 			if (get_user(pid, (int __user *)argp))
10141da177e4SLinus Torvalds 				break;
10151da177e4SLinus Torvalds 			err = f_setown(sock->file, pid, 1);
10161da177e4SLinus Torvalds 			break;
10171da177e4SLinus Torvalds 		case FIOGETOWN:
10181da177e4SLinus Torvalds 		case SIOCGPGRP:
1019609d7fa9SEric W. Biederman 			err = put_user(f_getown(sock->file),
102089bddce5SStephen Hemminger 				       (int __user *)argp);
10211da177e4SLinus Torvalds 			break;
10221da177e4SLinus Torvalds 		case SIOCGIFBR:
10231da177e4SLinus Torvalds 		case SIOCSIFBR:
10241da177e4SLinus Torvalds 		case SIOCBRADDBR:
10251da177e4SLinus Torvalds 		case SIOCBRDELBR:
10261da177e4SLinus Torvalds 			err = -ENOPKG;
10271da177e4SLinus Torvalds 			if (!br_ioctl_hook)
10281da177e4SLinus Torvalds 				request_module("bridge");
10291da177e4SLinus Torvalds 
10304a3e2f71SArjan van de Ven 			mutex_lock(&br_ioctl_mutex);
10311da177e4SLinus Torvalds 			if (br_ioctl_hook)
1032881d966bSEric W. Biederman 				err = br_ioctl_hook(net, cmd, argp);
10334a3e2f71SArjan van de Ven 			mutex_unlock(&br_ioctl_mutex);
10341da177e4SLinus Torvalds 			break;
10351da177e4SLinus Torvalds 		case SIOCGIFVLAN:
10361da177e4SLinus Torvalds 		case SIOCSIFVLAN:
10371da177e4SLinus Torvalds 			err = -ENOPKG;
10381da177e4SLinus Torvalds 			if (!vlan_ioctl_hook)
10391da177e4SLinus Torvalds 				request_module("8021q");
10401da177e4SLinus Torvalds 
10414a3e2f71SArjan van de Ven 			mutex_lock(&vlan_ioctl_mutex);
10421da177e4SLinus Torvalds 			if (vlan_ioctl_hook)
1043881d966bSEric W. Biederman 				err = vlan_ioctl_hook(net, argp);
10444a3e2f71SArjan van de Ven 			mutex_unlock(&vlan_ioctl_mutex);
10451da177e4SLinus Torvalds 			break;
10461da177e4SLinus Torvalds 		case SIOCADDDLCI:
10471da177e4SLinus Torvalds 		case SIOCDELDLCI:
10481da177e4SLinus Torvalds 			err = -ENOPKG;
10491da177e4SLinus Torvalds 			if (!dlci_ioctl_hook)
10501da177e4SLinus Torvalds 				request_module("dlci");
10511da177e4SLinus Torvalds 
10524a3e2f71SArjan van de Ven 			mutex_lock(&dlci_ioctl_mutex);
10537512cbf6SPavel Emelyanov 			if (dlci_ioctl_hook)
10541da177e4SLinus Torvalds 				err = dlci_ioctl_hook(cmd, argp);
10554a3e2f71SArjan van de Ven 			mutex_unlock(&dlci_ioctl_mutex);
10561da177e4SLinus Torvalds 			break;
10571da177e4SLinus Torvalds 		default:
10586b96018bSArnd Bergmann 			err = sock_do_ioctl(net, sock, cmd, arg);
10591da177e4SLinus Torvalds 			break;
10601da177e4SLinus Torvalds 		}
10611da177e4SLinus Torvalds 	return err;
10621da177e4SLinus Torvalds }
10631da177e4SLinus Torvalds 
10641da177e4SLinus Torvalds int sock_create_lite(int family, int type, int protocol, struct socket **res)
10651da177e4SLinus Torvalds {
10661da177e4SLinus Torvalds 	int err;
10671da177e4SLinus Torvalds 	struct socket *sock = NULL;
10681da177e4SLinus Torvalds 
10691da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, 1);
10701da177e4SLinus Torvalds 	if (err)
10711da177e4SLinus Torvalds 		goto out;
10721da177e4SLinus Torvalds 
10731da177e4SLinus Torvalds 	sock = sock_alloc();
10741da177e4SLinus Torvalds 	if (!sock) {
10751da177e4SLinus Torvalds 		err = -ENOMEM;
10761da177e4SLinus Torvalds 		goto out;
10771da177e4SLinus Torvalds 	}
10781da177e4SLinus Torvalds 
10791da177e4SLinus Torvalds 	sock->type = type;
10807420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, 1);
10817420ed23SVenkat Yekkirala 	if (err)
10827420ed23SVenkat Yekkirala 		goto out_release;
10837420ed23SVenkat Yekkirala 
10841da177e4SLinus Torvalds out:
10851da177e4SLinus Torvalds 	*res = sock;
10861da177e4SLinus Torvalds 	return err;
10877420ed23SVenkat Yekkirala out_release:
10887420ed23SVenkat Yekkirala 	sock_release(sock);
10897420ed23SVenkat Yekkirala 	sock = NULL;
10907420ed23SVenkat Yekkirala 	goto out;
10911da177e4SLinus Torvalds }
1092c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_lite);
10931da177e4SLinus Torvalds 
10941da177e4SLinus Torvalds /* No kernel lock held - perfect */
10951da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file, poll_table *wait)
10961da177e4SLinus Torvalds {
10971da177e4SLinus Torvalds 	struct socket *sock;
10981da177e4SLinus Torvalds 
10991da177e4SLinus Torvalds 	/*
11001da177e4SLinus Torvalds 	 *      We can't return errors to poll, so it's either yes or no.
11011da177e4SLinus Torvalds 	 */
1102b69aee04SEric Dumazet 	sock = file->private_data;
11031da177e4SLinus Torvalds 	return sock->ops->poll(file, sock, wait);
11041da177e4SLinus Torvalds }
11051da177e4SLinus Torvalds 
11061da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma)
11071da177e4SLinus Torvalds {
1108b69aee04SEric Dumazet 	struct socket *sock = file->private_data;
11091da177e4SLinus Torvalds 
11101da177e4SLinus Torvalds 	return sock->ops->mmap(file, sock, vma);
11111da177e4SLinus Torvalds }
11121da177e4SLinus Torvalds 
111320380731SArnaldo Carvalho de Melo static int sock_close(struct inode *inode, struct file *filp)
11141da177e4SLinus Torvalds {
11151da177e4SLinus Torvalds 	/*
11161da177e4SLinus Torvalds 	 *      It was possible the inode is NULL we were
11171da177e4SLinus Torvalds 	 *      closing an unfinished socket.
11181da177e4SLinus Torvalds 	 */
11191da177e4SLinus Torvalds 
112089bddce5SStephen Hemminger 	if (!inode) {
11211da177e4SLinus Torvalds 		printk(KERN_DEBUG "sock_close: NULL inode\n");
11221da177e4SLinus Torvalds 		return 0;
11231da177e4SLinus Torvalds 	}
11241da177e4SLinus Torvalds 	sock_release(SOCKET_I(inode));
11251da177e4SLinus Torvalds 	return 0;
11261da177e4SLinus Torvalds }
11271da177e4SLinus Torvalds 
11281da177e4SLinus Torvalds /*
11291da177e4SLinus Torvalds  *	Update the socket async list
11301da177e4SLinus Torvalds  *
11311da177e4SLinus Torvalds  *	Fasync_list locking strategy.
11321da177e4SLinus Torvalds  *
11331da177e4SLinus Torvalds  *	1. fasync_list is modified only under process context socket lock
11341da177e4SLinus Torvalds  *	   i.e. under semaphore.
11351da177e4SLinus Torvalds  *	2. fasync_list is used under read_lock(&sk->sk_callback_lock)
1136989a2979SEric Dumazet  *	   or under socket lock
11371da177e4SLinus Torvalds  */
11381da177e4SLinus Torvalds 
11391da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on)
11401da177e4SLinus Torvalds {
1141989a2979SEric Dumazet 	struct socket *sock = filp->private_data;
1142989a2979SEric Dumazet 	struct sock *sk = sock->sk;
1143eaefd110SEric Dumazet 	struct socket_wq *wq;
11441da177e4SLinus Torvalds 
1145989a2979SEric Dumazet 	if (sk == NULL)
11461da177e4SLinus Torvalds 		return -EINVAL;
11471da177e4SLinus Torvalds 
11481da177e4SLinus Torvalds 	lock_sock(sk);
1149eaefd110SEric Dumazet 	wq = rcu_dereference_protected(sock->wq, sock_owned_by_user(sk));
1150eaefd110SEric Dumazet 	fasync_helper(fd, filp, on, &wq->fasync_list);
11511da177e4SLinus Torvalds 
1152eaefd110SEric Dumazet 	if (!wq->fasync_list)
1153bcdce719SEric Dumazet 		sock_reset_flag(sk, SOCK_FASYNC);
1154989a2979SEric Dumazet 	else
1155989a2979SEric Dumazet 		sock_set_flag(sk, SOCK_FASYNC);
11561da177e4SLinus Torvalds 
1157989a2979SEric Dumazet 	release_sock(sk);
11581da177e4SLinus Torvalds 	return 0;
11591da177e4SLinus Torvalds }
11601da177e4SLinus Torvalds 
116143815482SEric Dumazet /* This function may be called only under socket lock or callback_lock or rcu_lock */
11621da177e4SLinus Torvalds 
11631da177e4SLinus Torvalds int sock_wake_async(struct socket *sock, int how, int band)
11641da177e4SLinus Torvalds {
116543815482SEric Dumazet 	struct socket_wq *wq;
116643815482SEric Dumazet 
116743815482SEric Dumazet 	if (!sock)
11681da177e4SLinus Torvalds 		return -1;
116943815482SEric Dumazet 	rcu_read_lock();
117043815482SEric Dumazet 	wq = rcu_dereference(sock->wq);
117143815482SEric Dumazet 	if (!wq || !wq->fasync_list) {
117243815482SEric Dumazet 		rcu_read_unlock();
117343815482SEric Dumazet 		return -1;
117443815482SEric Dumazet 	}
117589bddce5SStephen Hemminger 	switch (how) {
11768d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_WAITD:
11771da177e4SLinus Torvalds 		if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
11781da177e4SLinus Torvalds 			break;
11791da177e4SLinus Torvalds 		goto call_kill;
11808d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_SPACE:
11811da177e4SLinus Torvalds 		if (!test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags))
11821da177e4SLinus Torvalds 			break;
11831da177e4SLinus Torvalds 		/* fall through */
11848d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_IO:
11851da177e4SLinus Torvalds call_kill:
118643815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGIO, band);
11871da177e4SLinus Torvalds 		break;
11888d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_URG:
118943815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGURG, band);
11901da177e4SLinus Torvalds 	}
119143815482SEric Dumazet 	rcu_read_unlock();
11921da177e4SLinus Torvalds 	return 0;
11931da177e4SLinus Torvalds }
1194c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_wake_async);
11951da177e4SLinus Torvalds 
1196721db93aSPavel Emelyanov int __sock_create(struct net *net, int family, int type, int protocol,
119789bddce5SStephen Hemminger 			 struct socket **res, int kern)
11981da177e4SLinus Torvalds {
11991da177e4SLinus Torvalds 	int err;
12001da177e4SLinus Torvalds 	struct socket *sock;
120155737fdaSStephen Hemminger 	const struct net_proto_family *pf;
12021da177e4SLinus Torvalds 
12031da177e4SLinus Torvalds 	/*
12041da177e4SLinus Torvalds 	 *      Check protocol is in range
12051da177e4SLinus Torvalds 	 */
12061da177e4SLinus Torvalds 	if (family < 0 || family >= NPROTO)
12071da177e4SLinus Torvalds 		return -EAFNOSUPPORT;
12081da177e4SLinus Torvalds 	if (type < 0 || type >= SOCK_MAX)
12091da177e4SLinus Torvalds 		return -EINVAL;
12101da177e4SLinus Torvalds 
12111da177e4SLinus Torvalds 	/* Compatibility.
12121da177e4SLinus Torvalds 
12131da177e4SLinus Torvalds 	   This uglymoron is moved from INET layer to here to avoid
12141da177e4SLinus Torvalds 	   deadlock in module load.
12151da177e4SLinus Torvalds 	 */
12161da177e4SLinus Torvalds 	if (family == PF_INET && type == SOCK_PACKET) {
12171da177e4SLinus Torvalds 		static int warned;
12181da177e4SLinus Torvalds 		if (!warned) {
12191da177e4SLinus Torvalds 			warned = 1;
122089bddce5SStephen Hemminger 			printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)\n",
122189bddce5SStephen Hemminger 			       current->comm);
12221da177e4SLinus Torvalds 		}
12231da177e4SLinus Torvalds 		family = PF_PACKET;
12241da177e4SLinus Torvalds 	}
12251da177e4SLinus Torvalds 
12261da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, kern);
12271da177e4SLinus Torvalds 	if (err)
12281da177e4SLinus Torvalds 		return err;
12291da177e4SLinus Torvalds 
123055737fdaSStephen Hemminger 	/*
123155737fdaSStephen Hemminger 	 *	Allocate the socket and allow the family to set things up. if
123255737fdaSStephen Hemminger 	 *	the protocol is 0, the family is instructed to select an appropriate
123355737fdaSStephen Hemminger 	 *	default.
123455737fdaSStephen Hemminger 	 */
123555737fdaSStephen Hemminger 	sock = sock_alloc();
123655737fdaSStephen Hemminger 	if (!sock) {
123755737fdaSStephen Hemminger 		if (net_ratelimit())
123855737fdaSStephen Hemminger 			printk(KERN_WARNING "socket: no more sockets\n");
123955737fdaSStephen Hemminger 		return -ENFILE;	/* Not exactly a match, but its the
124055737fdaSStephen Hemminger 				   closest posix thing */
124155737fdaSStephen Hemminger 	}
124255737fdaSStephen Hemminger 
124355737fdaSStephen Hemminger 	sock->type = type;
124455737fdaSStephen Hemminger 
124595a5afcaSJohannes Berg #ifdef CONFIG_MODULES
12461da177e4SLinus Torvalds 	/* Attempt to load a protocol module if the find failed.
12471da177e4SLinus Torvalds 	 *
12481da177e4SLinus Torvalds 	 * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
12491da177e4SLinus Torvalds 	 * requested real, full-featured networking support upon configuration.
12501da177e4SLinus Torvalds 	 * Otherwise module support will break!
12511da177e4SLinus Torvalds 	 */
1252190683a9SEric Dumazet 	if (rcu_access_pointer(net_families[family]) == NULL)
12531da177e4SLinus Torvalds 		request_module("net-pf-%d", family);
12541da177e4SLinus Torvalds #endif
12551da177e4SLinus Torvalds 
125655737fdaSStephen Hemminger 	rcu_read_lock();
125755737fdaSStephen Hemminger 	pf = rcu_dereference(net_families[family]);
12581da177e4SLinus Torvalds 	err = -EAFNOSUPPORT;
125955737fdaSStephen Hemminger 	if (!pf)
126055737fdaSStephen Hemminger 		goto out_release;
12611da177e4SLinus Torvalds 
12621da177e4SLinus Torvalds 	/*
12631da177e4SLinus Torvalds 	 * We will call the ->create function, that possibly is in a loadable
12641da177e4SLinus Torvalds 	 * module, so we have to bump that loadable module refcnt first.
12651da177e4SLinus Torvalds 	 */
126655737fdaSStephen Hemminger 	if (!try_module_get(pf->owner))
12671da177e4SLinus Torvalds 		goto out_release;
12681da177e4SLinus Torvalds 
126955737fdaSStephen Hemminger 	/* Now protected by module ref count */
127055737fdaSStephen Hemminger 	rcu_read_unlock();
127155737fdaSStephen Hemminger 
12723f378b68SEric Paris 	err = pf->create(net, sock, protocol, kern);
127355737fdaSStephen Hemminger 	if (err < 0)
12741da177e4SLinus Torvalds 		goto out_module_put;
1275a79af59eSFrank Filz 
12761da177e4SLinus Torvalds 	/*
12771da177e4SLinus Torvalds 	 * Now to bump the refcnt of the [loadable] module that owns this
12781da177e4SLinus Torvalds 	 * socket at sock_release time we decrement its refcnt.
12791da177e4SLinus Torvalds 	 */
128055737fdaSStephen Hemminger 	if (!try_module_get(sock->ops->owner))
128155737fdaSStephen Hemminger 		goto out_module_busy;
128255737fdaSStephen Hemminger 
12831da177e4SLinus Torvalds 	/*
12841da177e4SLinus Torvalds 	 * Now that we're done with the ->create function, the [loadable]
12851da177e4SLinus Torvalds 	 * module can have its refcnt decremented
12861da177e4SLinus Torvalds 	 */
128755737fdaSStephen Hemminger 	module_put(pf->owner);
12887420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, kern);
12897420ed23SVenkat Yekkirala 	if (err)
12903b185525SHerbert Xu 		goto out_sock_release;
129155737fdaSStephen Hemminger 	*res = sock;
12921da177e4SLinus Torvalds 
129355737fdaSStephen Hemminger 	return 0;
129455737fdaSStephen Hemminger 
129555737fdaSStephen Hemminger out_module_busy:
129655737fdaSStephen Hemminger 	err = -EAFNOSUPPORT;
12971da177e4SLinus Torvalds out_module_put:
129855737fdaSStephen Hemminger 	sock->ops = NULL;
129955737fdaSStephen Hemminger 	module_put(pf->owner);
130055737fdaSStephen Hemminger out_sock_release:
13011da177e4SLinus Torvalds 	sock_release(sock);
130255737fdaSStephen Hemminger 	return err;
130355737fdaSStephen Hemminger 
130455737fdaSStephen Hemminger out_release:
130555737fdaSStephen Hemminger 	rcu_read_unlock();
130655737fdaSStephen Hemminger 	goto out_sock_release;
13071da177e4SLinus Torvalds }
1308721db93aSPavel Emelyanov EXPORT_SYMBOL(__sock_create);
13091da177e4SLinus Torvalds 
13101da177e4SLinus Torvalds int sock_create(int family, int type, int protocol, struct socket **res)
13111da177e4SLinus Torvalds {
13121b8d7ae4SEric W. Biederman 	return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
13131da177e4SLinus Torvalds }
1314c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create);
13151da177e4SLinus Torvalds 
13161da177e4SLinus Torvalds int sock_create_kern(int family, int type, int protocol, struct socket **res)
13171da177e4SLinus Torvalds {
13181b8d7ae4SEric W. Biederman 	return __sock_create(&init_net, family, type, protocol, res, 1);
13191da177e4SLinus Torvalds }
1320c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_kern);
13211da177e4SLinus Torvalds 
13223e0fa65fSHeiko Carstens SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
13231da177e4SLinus Torvalds {
13241da177e4SLinus Torvalds 	int retval;
13251da177e4SLinus Torvalds 	struct socket *sock;
1326a677a039SUlrich Drepper 	int flags;
1327a677a039SUlrich Drepper 
1328e38b36f3SUlrich Drepper 	/* Check the SOCK_* constants for consistency.  */
1329e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
1330e38b36f3SUlrich Drepper 	BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
1331e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);
1332e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);
1333e38b36f3SUlrich Drepper 
1334a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
133577d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1336a677a039SUlrich Drepper 		return -EINVAL;
1337a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
13381da177e4SLinus Torvalds 
1339aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1340aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1341aaca0bdcSUlrich Drepper 
13421da177e4SLinus Torvalds 	retval = sock_create(family, type, protocol, &sock);
13431da177e4SLinus Torvalds 	if (retval < 0)
13441da177e4SLinus Torvalds 		goto out;
13451da177e4SLinus Torvalds 
134677d27200SUlrich Drepper 	retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
13471da177e4SLinus Torvalds 	if (retval < 0)
13481da177e4SLinus Torvalds 		goto out_release;
13491da177e4SLinus Torvalds 
13501da177e4SLinus Torvalds out:
13511da177e4SLinus Torvalds 	/* It may be already another descriptor 8) Not kernel problem. */
13521da177e4SLinus Torvalds 	return retval;
13531da177e4SLinus Torvalds 
13541da177e4SLinus Torvalds out_release:
13551da177e4SLinus Torvalds 	sock_release(sock);
13561da177e4SLinus Torvalds 	return retval;
13571da177e4SLinus Torvalds }
13581da177e4SLinus Torvalds 
13591da177e4SLinus Torvalds /*
13601da177e4SLinus Torvalds  *	Create a pair of connected sockets.
13611da177e4SLinus Torvalds  */
13621da177e4SLinus Torvalds 
13633e0fa65fSHeiko Carstens SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
13643e0fa65fSHeiko Carstens 		int __user *, usockvec)
13651da177e4SLinus Torvalds {
13661da177e4SLinus Torvalds 	struct socket *sock1, *sock2;
13671da177e4SLinus Torvalds 	int fd1, fd2, err;
1368db349509SAl Viro 	struct file *newfile1, *newfile2;
1369a677a039SUlrich Drepper 	int flags;
1370a677a039SUlrich Drepper 
1371a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
137277d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1373a677a039SUlrich Drepper 		return -EINVAL;
1374a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
13751da177e4SLinus Torvalds 
1376aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1377aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1378aaca0bdcSUlrich Drepper 
13791da177e4SLinus Torvalds 	/*
13801da177e4SLinus Torvalds 	 * Obtain the first socket and check if the underlying protocol
13811da177e4SLinus Torvalds 	 * supports the socketpair call.
13821da177e4SLinus Torvalds 	 */
13831da177e4SLinus Torvalds 
13841da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock1);
13851da177e4SLinus Torvalds 	if (err < 0)
13861da177e4SLinus Torvalds 		goto out;
13871da177e4SLinus Torvalds 
13881da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock2);
13891da177e4SLinus Torvalds 	if (err < 0)
13901da177e4SLinus Torvalds 		goto out_release_1;
13911da177e4SLinus Torvalds 
13921da177e4SLinus Torvalds 	err = sock1->ops->socketpair(sock1, sock2);
13931da177e4SLinus Torvalds 	if (err < 0)
13941da177e4SLinus Torvalds 		goto out_release_both;
13951da177e4SLinus Torvalds 
13967cbe66b6SAl Viro 	fd1 = sock_alloc_file(sock1, &newfile1, flags);
1397bf3c23d1SDavid S. Miller 	if (unlikely(fd1 < 0)) {
1398bf3c23d1SDavid S. Miller 		err = fd1;
13991da177e4SLinus Torvalds 		goto out_release_both;
1400bf3c23d1SDavid S. Miller 	}
14011da177e4SLinus Torvalds 
14027cbe66b6SAl Viro 	fd2 = sock_alloc_file(sock2, &newfile2, flags);
1403198de4d7SAl Viro 	if (unlikely(fd2 < 0)) {
1404198de4d7SAl Viro 		err = fd2;
1405198de4d7SAl Viro 		fput(newfile1);
1406198de4d7SAl Viro 		put_unused_fd(fd1);
1407198de4d7SAl Viro 		sock_release(sock2);
1408198de4d7SAl Viro 		goto out;
1409db349509SAl Viro 	}
1410db349509SAl Viro 
1411157cf649SAl Viro 	audit_fd_pair(fd1, fd2);
1412db349509SAl Viro 	fd_install(fd1, newfile1);
1413db349509SAl Viro 	fd_install(fd2, newfile2);
14141da177e4SLinus Torvalds 	/* fd1 and fd2 may be already another descriptors.
14151da177e4SLinus Torvalds 	 * Not kernel problem.
14161da177e4SLinus Torvalds 	 */
14171da177e4SLinus Torvalds 
14181da177e4SLinus Torvalds 	err = put_user(fd1, &usockvec[0]);
14191da177e4SLinus Torvalds 	if (!err)
14201da177e4SLinus Torvalds 		err = put_user(fd2, &usockvec[1]);
14211da177e4SLinus Torvalds 	if (!err)
14221da177e4SLinus Torvalds 		return 0;
14231da177e4SLinus Torvalds 
14241da177e4SLinus Torvalds 	sys_close(fd2);
14251da177e4SLinus Torvalds 	sys_close(fd1);
14261da177e4SLinus Torvalds 	return err;
14271da177e4SLinus Torvalds 
14281da177e4SLinus Torvalds out_release_both:
14291da177e4SLinus Torvalds 	sock_release(sock2);
14301da177e4SLinus Torvalds out_release_1:
14311da177e4SLinus Torvalds 	sock_release(sock1);
14321da177e4SLinus Torvalds out:
14331da177e4SLinus Torvalds 	return err;
14341da177e4SLinus Torvalds }
14351da177e4SLinus Torvalds 
14361da177e4SLinus Torvalds /*
14371da177e4SLinus Torvalds  *	Bind a name to a socket. Nothing much to do here since it's
14381da177e4SLinus Torvalds  *	the protocol's responsibility to handle the local address.
14391da177e4SLinus Torvalds  *
14401da177e4SLinus Torvalds  *	We move the socket address to kernel space before we call
14411da177e4SLinus Torvalds  *	the protocol layer (having also checked the address is ok).
14421da177e4SLinus Torvalds  */
14431da177e4SLinus Torvalds 
144420f37034SHeiko Carstens SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
14451da177e4SLinus Torvalds {
14461da177e4SLinus Torvalds 	struct socket *sock;
1447230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
14486cb153caSBenjamin LaHaise 	int err, fput_needed;
14491da177e4SLinus Torvalds 
145089bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
145189bddce5SStephen Hemminger 	if (sock) {
1452230b1839SYOSHIFUJI Hideaki 		err = move_addr_to_kernel(umyaddr, addrlen, (struct sockaddr *)&address);
145389bddce5SStephen Hemminger 		if (err >= 0) {
145489bddce5SStephen Hemminger 			err = security_socket_bind(sock,
1455230b1839SYOSHIFUJI Hideaki 						   (struct sockaddr *)&address,
145689bddce5SStephen Hemminger 						   addrlen);
14576cb153caSBenjamin LaHaise 			if (!err)
14586cb153caSBenjamin LaHaise 				err = sock->ops->bind(sock,
145989bddce5SStephen Hemminger 						      (struct sockaddr *)
1460230b1839SYOSHIFUJI Hideaki 						      &address, addrlen);
14611da177e4SLinus Torvalds 		}
14626cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
14631da177e4SLinus Torvalds 	}
14641da177e4SLinus Torvalds 	return err;
14651da177e4SLinus Torvalds }
14661da177e4SLinus Torvalds 
14671da177e4SLinus Torvalds /*
14681da177e4SLinus Torvalds  *	Perform a listen. Basically, we allow the protocol to do anything
14691da177e4SLinus Torvalds  *	necessary for a listen, and if that works, we mark the socket as
14701da177e4SLinus Torvalds  *	ready for listening.
14711da177e4SLinus Torvalds  */
14721da177e4SLinus Torvalds 
14733e0fa65fSHeiko Carstens SYSCALL_DEFINE2(listen, int, fd, int, backlog)
14741da177e4SLinus Torvalds {
14751da177e4SLinus Torvalds 	struct socket *sock;
14766cb153caSBenjamin LaHaise 	int err, fput_needed;
1477b8e1f9b5SPavel Emelyanov 	int somaxconn;
14781da177e4SLinus Torvalds 
147989bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
148089bddce5SStephen Hemminger 	if (sock) {
14818efa6e93SPavel Emelyanov 		somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
1482b8e1f9b5SPavel Emelyanov 		if ((unsigned)backlog > somaxconn)
1483b8e1f9b5SPavel Emelyanov 			backlog = somaxconn;
14841da177e4SLinus Torvalds 
14851da177e4SLinus Torvalds 		err = security_socket_listen(sock, backlog);
14866cb153caSBenjamin LaHaise 		if (!err)
14871da177e4SLinus Torvalds 			err = sock->ops->listen(sock, backlog);
14886cb153caSBenjamin LaHaise 
14896cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
14901da177e4SLinus Torvalds 	}
14911da177e4SLinus Torvalds 	return err;
14921da177e4SLinus Torvalds }
14931da177e4SLinus Torvalds 
14941da177e4SLinus Torvalds /*
14951da177e4SLinus Torvalds  *	For accept, we attempt to create a new socket, set up the link
14961da177e4SLinus Torvalds  *	with the client, wake up the client, then return the new
14971da177e4SLinus Torvalds  *	connected fd. We collect the address of the connector in kernel
14981da177e4SLinus Torvalds  *	space and move it to user at the very end. This is unclean because
14991da177e4SLinus Torvalds  *	we open the socket then return an error.
15001da177e4SLinus Torvalds  *
15011da177e4SLinus Torvalds  *	1003.1g adds the ability to recvmsg() to query connection pending
15021da177e4SLinus Torvalds  *	status to recvmsg. We need to add that support in a way thats
15031da177e4SLinus Torvalds  *	clean when we restucture accept also.
15041da177e4SLinus Torvalds  */
15051da177e4SLinus Torvalds 
150620f37034SHeiko Carstens SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
150720f37034SHeiko Carstens 		int __user *, upeer_addrlen, int, flags)
15081da177e4SLinus Torvalds {
15091da177e4SLinus Torvalds 	struct socket *sock, *newsock;
151039d8c1b6SDavid S. Miller 	struct file *newfile;
15116cb153caSBenjamin LaHaise 	int err, len, newfd, fput_needed;
1512230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
15131da177e4SLinus Torvalds 
151477d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1515aaca0bdcSUlrich Drepper 		return -EINVAL;
1516aaca0bdcSUlrich Drepper 
1517aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1518aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1519aaca0bdcSUlrich Drepper 
15206cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
15211da177e4SLinus Torvalds 	if (!sock)
15221da177e4SLinus Torvalds 		goto out;
15231da177e4SLinus Torvalds 
15241da177e4SLinus Torvalds 	err = -ENFILE;
1525c6d409cfSEric Dumazet 	newsock = sock_alloc();
1526c6d409cfSEric Dumazet 	if (!newsock)
15271da177e4SLinus Torvalds 		goto out_put;
15281da177e4SLinus Torvalds 
15291da177e4SLinus Torvalds 	newsock->type = sock->type;
15301da177e4SLinus Torvalds 	newsock->ops = sock->ops;
15311da177e4SLinus Torvalds 
15321da177e4SLinus Torvalds 	/*
15331da177e4SLinus Torvalds 	 * We don't need try_module_get here, as the listening socket (sock)
15341da177e4SLinus Torvalds 	 * has the protocol module (sock->ops->owner) held.
15351da177e4SLinus Torvalds 	 */
15361da177e4SLinus Torvalds 	__module_get(newsock->ops->owner);
15371da177e4SLinus Torvalds 
15387cbe66b6SAl Viro 	newfd = sock_alloc_file(newsock, &newfile, flags);
153939d8c1b6SDavid S. Miller 	if (unlikely(newfd < 0)) {
154039d8c1b6SDavid S. Miller 		err = newfd;
15419a1875e6SDavid S. Miller 		sock_release(newsock);
15429a1875e6SDavid S. Miller 		goto out_put;
154339d8c1b6SDavid S. Miller 	}
154439d8c1b6SDavid S. Miller 
1545a79af59eSFrank Filz 	err = security_socket_accept(sock, newsock);
1546a79af59eSFrank Filz 	if (err)
154739d8c1b6SDavid S. Miller 		goto out_fd;
1548a79af59eSFrank Filz 
15491da177e4SLinus Torvalds 	err = sock->ops->accept(sock, newsock, sock->file->f_flags);
15501da177e4SLinus Torvalds 	if (err < 0)
155139d8c1b6SDavid S. Miller 		goto out_fd;
15521da177e4SLinus Torvalds 
15531da177e4SLinus Torvalds 	if (upeer_sockaddr) {
1554230b1839SYOSHIFUJI Hideaki 		if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
155589bddce5SStephen Hemminger 					  &len, 2) < 0) {
15561da177e4SLinus Torvalds 			err = -ECONNABORTED;
155739d8c1b6SDavid S. Miller 			goto out_fd;
15581da177e4SLinus Torvalds 		}
1559230b1839SYOSHIFUJI Hideaki 		err = move_addr_to_user((struct sockaddr *)&address,
1560230b1839SYOSHIFUJI Hideaki 					len, upeer_sockaddr, upeer_addrlen);
15611da177e4SLinus Torvalds 		if (err < 0)
156239d8c1b6SDavid S. Miller 			goto out_fd;
15631da177e4SLinus Torvalds 	}
15641da177e4SLinus Torvalds 
15651da177e4SLinus Torvalds 	/* File flags are not inherited via accept() unlike another OSes. */
15661da177e4SLinus Torvalds 
156739d8c1b6SDavid S. Miller 	fd_install(newfd, newfile);
156839d8c1b6SDavid S. Miller 	err = newfd;
15691da177e4SLinus Torvalds 
15701da177e4SLinus Torvalds out_put:
15716cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
15721da177e4SLinus Torvalds out:
15731da177e4SLinus Torvalds 	return err;
157439d8c1b6SDavid S. Miller out_fd:
15759606a216SDavid S. Miller 	fput(newfile);
157639d8c1b6SDavid S. Miller 	put_unused_fd(newfd);
15771da177e4SLinus Torvalds 	goto out_put;
15781da177e4SLinus Torvalds }
15791da177e4SLinus Torvalds 
158020f37034SHeiko Carstens SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,
158120f37034SHeiko Carstens 		int __user *, upeer_addrlen)
1582aaca0bdcSUlrich Drepper {
1583de11defeSUlrich Drepper 	return sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0);
1584aaca0bdcSUlrich Drepper }
1585aaca0bdcSUlrich Drepper 
15861da177e4SLinus Torvalds /*
15871da177e4SLinus Torvalds  *	Attempt to connect to a socket with the server address.  The address
15881da177e4SLinus Torvalds  *	is in user space so we verify it is OK and move it to kernel space.
15891da177e4SLinus Torvalds  *
15901da177e4SLinus Torvalds  *	For 1003.1g we need to add clean support for a bind to AF_UNSPEC to
15911da177e4SLinus Torvalds  *	break bindings
15921da177e4SLinus Torvalds  *
15931da177e4SLinus Torvalds  *	NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and
15941da177e4SLinus Torvalds  *	other SEQPACKET protocols that take time to connect() as it doesn't
15951da177e4SLinus Torvalds  *	include the -EINPROGRESS status for such sockets.
15961da177e4SLinus Torvalds  */
15971da177e4SLinus Torvalds 
159820f37034SHeiko Carstens SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
159920f37034SHeiko Carstens 		int, addrlen)
16001da177e4SLinus Torvalds {
16011da177e4SLinus Torvalds 	struct socket *sock;
1602230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16036cb153caSBenjamin LaHaise 	int err, fput_needed;
16041da177e4SLinus Torvalds 
16056cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
16061da177e4SLinus Torvalds 	if (!sock)
16071da177e4SLinus Torvalds 		goto out;
1608230b1839SYOSHIFUJI Hideaki 	err = move_addr_to_kernel(uservaddr, addrlen, (struct sockaddr *)&address);
16091da177e4SLinus Torvalds 	if (err < 0)
16101da177e4SLinus Torvalds 		goto out_put;
16111da177e4SLinus Torvalds 
161289bddce5SStephen Hemminger 	err =
1613230b1839SYOSHIFUJI Hideaki 	    security_socket_connect(sock, (struct sockaddr *)&address, addrlen);
16141da177e4SLinus Torvalds 	if (err)
16151da177e4SLinus Torvalds 		goto out_put;
16161da177e4SLinus Torvalds 
1617230b1839SYOSHIFUJI Hideaki 	err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,
16181da177e4SLinus Torvalds 				 sock->file->f_flags);
16191da177e4SLinus Torvalds out_put:
16206cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
16211da177e4SLinus Torvalds out:
16221da177e4SLinus Torvalds 	return err;
16231da177e4SLinus Torvalds }
16241da177e4SLinus Torvalds 
16251da177e4SLinus Torvalds /*
16261da177e4SLinus Torvalds  *	Get the local address ('name') of a socket object. Move the obtained
16271da177e4SLinus Torvalds  *	name to user space.
16281da177e4SLinus Torvalds  */
16291da177e4SLinus Torvalds 
163020f37034SHeiko Carstens SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
163120f37034SHeiko Carstens 		int __user *, usockaddr_len)
16321da177e4SLinus Torvalds {
16331da177e4SLinus Torvalds 	struct socket *sock;
1634230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16356cb153caSBenjamin LaHaise 	int len, err, fput_needed;
16361da177e4SLinus Torvalds 
16376cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
16381da177e4SLinus Torvalds 	if (!sock)
16391da177e4SLinus Torvalds 		goto out;
16401da177e4SLinus Torvalds 
16411da177e4SLinus Torvalds 	err = security_socket_getsockname(sock);
16421da177e4SLinus Torvalds 	if (err)
16431da177e4SLinus Torvalds 		goto out_put;
16441da177e4SLinus Torvalds 
1645230b1839SYOSHIFUJI Hideaki 	err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0);
16461da177e4SLinus Torvalds 	if (err)
16471da177e4SLinus Torvalds 		goto out_put;
1648230b1839SYOSHIFUJI Hideaki 	err = move_addr_to_user((struct sockaddr *)&address, len, usockaddr, usockaddr_len);
16491da177e4SLinus Torvalds 
16501da177e4SLinus Torvalds out_put:
16516cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
16521da177e4SLinus Torvalds out:
16531da177e4SLinus Torvalds 	return err;
16541da177e4SLinus Torvalds }
16551da177e4SLinus Torvalds 
16561da177e4SLinus Torvalds /*
16571da177e4SLinus Torvalds  *	Get the remote address ('name') of a socket object. Move the obtained
16581da177e4SLinus Torvalds  *	name to user space.
16591da177e4SLinus Torvalds  */
16601da177e4SLinus Torvalds 
166120f37034SHeiko Carstens SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
166220f37034SHeiko Carstens 		int __user *, usockaddr_len)
16631da177e4SLinus Torvalds {
16641da177e4SLinus Torvalds 	struct socket *sock;
1665230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16666cb153caSBenjamin LaHaise 	int len, err, fput_needed;
16671da177e4SLinus Torvalds 
166889bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
166989bddce5SStephen Hemminger 	if (sock != NULL) {
16701da177e4SLinus Torvalds 		err = security_socket_getpeername(sock);
16711da177e4SLinus Torvalds 		if (err) {
16726cb153caSBenjamin LaHaise 			fput_light(sock->file, fput_needed);
16731da177e4SLinus Torvalds 			return err;
16741da177e4SLinus Torvalds 		}
16751da177e4SLinus Torvalds 
167689bddce5SStephen Hemminger 		err =
1677230b1839SYOSHIFUJI Hideaki 		    sock->ops->getname(sock, (struct sockaddr *)&address, &len,
167889bddce5SStephen Hemminger 				       1);
16791da177e4SLinus Torvalds 		if (!err)
1680230b1839SYOSHIFUJI Hideaki 			err = move_addr_to_user((struct sockaddr *)&address, len, usockaddr,
168189bddce5SStephen Hemminger 						usockaddr_len);
16826cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
16831da177e4SLinus Torvalds 	}
16841da177e4SLinus Torvalds 	return err;
16851da177e4SLinus Torvalds }
16861da177e4SLinus Torvalds 
16871da177e4SLinus Torvalds /*
16881da177e4SLinus Torvalds  *	Send a datagram to a given address. We move the address into kernel
16891da177e4SLinus Torvalds  *	space and check the user space data area is readable before invoking
16901da177e4SLinus Torvalds  *	the protocol.
16911da177e4SLinus Torvalds  */
16921da177e4SLinus Torvalds 
16933e0fa65fSHeiko Carstens SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
16943e0fa65fSHeiko Carstens 		unsigned, flags, struct sockaddr __user *, addr,
16953e0fa65fSHeiko Carstens 		int, addr_len)
16961da177e4SLinus Torvalds {
16971da177e4SLinus Torvalds 	struct socket *sock;
1698230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16991da177e4SLinus Torvalds 	int err;
17001da177e4SLinus Torvalds 	struct msghdr msg;
17011da177e4SLinus Torvalds 	struct iovec iov;
17026cb153caSBenjamin LaHaise 	int fput_needed;
17031da177e4SLinus Torvalds 
1704253eacc0SLinus Torvalds 	if (len > INT_MAX)
1705253eacc0SLinus Torvalds 		len = INT_MAX;
1706de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1707de0fa95cSPavel Emelyanov 	if (!sock)
17084387ff75SDavid S. Miller 		goto out;
17096cb153caSBenjamin LaHaise 
17101da177e4SLinus Torvalds 	iov.iov_base = buff;
17111da177e4SLinus Torvalds 	iov.iov_len = len;
17121da177e4SLinus Torvalds 	msg.msg_name = NULL;
17131da177e4SLinus Torvalds 	msg.msg_iov = &iov;
17141da177e4SLinus Torvalds 	msg.msg_iovlen = 1;
17151da177e4SLinus Torvalds 	msg.msg_control = NULL;
17161da177e4SLinus Torvalds 	msg.msg_controllen = 0;
17171da177e4SLinus Torvalds 	msg.msg_namelen = 0;
17186cb153caSBenjamin LaHaise 	if (addr) {
1719230b1839SYOSHIFUJI Hideaki 		err = move_addr_to_kernel(addr, addr_len, (struct sockaddr *)&address);
17201da177e4SLinus Torvalds 		if (err < 0)
17211da177e4SLinus Torvalds 			goto out_put;
1722230b1839SYOSHIFUJI Hideaki 		msg.msg_name = (struct sockaddr *)&address;
17231da177e4SLinus Torvalds 		msg.msg_namelen = addr_len;
17241da177e4SLinus Torvalds 	}
17251da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
17261da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
17271da177e4SLinus Torvalds 	msg.msg_flags = flags;
17281da177e4SLinus Torvalds 	err = sock_sendmsg(sock, &msg, len);
17291da177e4SLinus Torvalds 
17301da177e4SLinus Torvalds out_put:
1731de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
17324387ff75SDavid S. Miller out:
17331da177e4SLinus Torvalds 	return err;
17341da177e4SLinus Torvalds }
17351da177e4SLinus Torvalds 
17361da177e4SLinus Torvalds /*
17371da177e4SLinus Torvalds  *	Send a datagram down a socket.
17381da177e4SLinus Torvalds  */
17391da177e4SLinus Torvalds 
17403e0fa65fSHeiko Carstens SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len,
17413e0fa65fSHeiko Carstens 		unsigned, flags)
17421da177e4SLinus Torvalds {
17431da177e4SLinus Torvalds 	return sys_sendto(fd, buff, len, flags, NULL, 0);
17441da177e4SLinus Torvalds }
17451da177e4SLinus Torvalds 
17461da177e4SLinus Torvalds /*
17471da177e4SLinus Torvalds  *	Receive a frame from the socket and optionally record the address of the
17481da177e4SLinus Torvalds  *	sender. We verify the buffers are writable and if needed move the
17491da177e4SLinus Torvalds  *	sender address from kernel to user space.
17501da177e4SLinus Torvalds  */
17511da177e4SLinus Torvalds 
17523e0fa65fSHeiko Carstens SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
17533e0fa65fSHeiko Carstens 		unsigned, flags, struct sockaddr __user *, addr,
17543e0fa65fSHeiko Carstens 		int __user *, addr_len)
17551da177e4SLinus Torvalds {
17561da177e4SLinus Torvalds 	struct socket *sock;
17571da177e4SLinus Torvalds 	struct iovec iov;
17581da177e4SLinus Torvalds 	struct msghdr msg;
1759230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
17601da177e4SLinus Torvalds 	int err, err2;
17616cb153caSBenjamin LaHaise 	int fput_needed;
17621da177e4SLinus Torvalds 
1763253eacc0SLinus Torvalds 	if (size > INT_MAX)
1764253eacc0SLinus Torvalds 		size = INT_MAX;
1765de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
17661da177e4SLinus Torvalds 	if (!sock)
1767de0fa95cSPavel Emelyanov 		goto out;
17681da177e4SLinus Torvalds 
17691da177e4SLinus Torvalds 	msg.msg_control = NULL;
17701da177e4SLinus Torvalds 	msg.msg_controllen = 0;
17711da177e4SLinus Torvalds 	msg.msg_iovlen = 1;
17721da177e4SLinus Torvalds 	msg.msg_iov = &iov;
17731da177e4SLinus Torvalds 	iov.iov_len = size;
17741da177e4SLinus Torvalds 	iov.iov_base = ubuf;
1775230b1839SYOSHIFUJI Hideaki 	msg.msg_name = (struct sockaddr *)&address;
1776230b1839SYOSHIFUJI Hideaki 	msg.msg_namelen = sizeof(address);
17771da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
17781da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
17791da177e4SLinus Torvalds 	err = sock_recvmsg(sock, &msg, size, flags);
17801da177e4SLinus Torvalds 
178189bddce5SStephen Hemminger 	if (err >= 0 && addr != NULL) {
1782230b1839SYOSHIFUJI Hideaki 		err2 = move_addr_to_user((struct sockaddr *)&address,
1783230b1839SYOSHIFUJI Hideaki 					 msg.msg_namelen, addr, addr_len);
17841da177e4SLinus Torvalds 		if (err2 < 0)
17851da177e4SLinus Torvalds 			err = err2;
17861da177e4SLinus Torvalds 	}
1787de0fa95cSPavel Emelyanov 
1788de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
17894387ff75SDavid S. Miller out:
17901da177e4SLinus Torvalds 	return err;
17911da177e4SLinus Torvalds }
17921da177e4SLinus Torvalds 
17931da177e4SLinus Torvalds /*
17941da177e4SLinus Torvalds  *	Receive a datagram from a socket.
17951da177e4SLinus Torvalds  */
17961da177e4SLinus Torvalds 
179789bddce5SStephen Hemminger asmlinkage long sys_recv(int fd, void __user *ubuf, size_t size,
179889bddce5SStephen Hemminger 			 unsigned flags)
17991da177e4SLinus Torvalds {
18001da177e4SLinus Torvalds 	return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL);
18011da177e4SLinus Torvalds }
18021da177e4SLinus Torvalds 
18031da177e4SLinus Torvalds /*
18041da177e4SLinus Torvalds  *	Set a socket option. Because we don't know the option lengths we have
18051da177e4SLinus Torvalds  *	to pass the user mode parameter for the protocols to sort out.
18061da177e4SLinus Torvalds  */
18071da177e4SLinus Torvalds 
180820f37034SHeiko Carstens SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
180920f37034SHeiko Carstens 		char __user *, optval, int, optlen)
18101da177e4SLinus Torvalds {
18116cb153caSBenjamin LaHaise 	int err, fput_needed;
18121da177e4SLinus Torvalds 	struct socket *sock;
18131da177e4SLinus Torvalds 
18141da177e4SLinus Torvalds 	if (optlen < 0)
18151da177e4SLinus Torvalds 		return -EINVAL;
18161da177e4SLinus Torvalds 
181789bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
181889bddce5SStephen Hemminger 	if (sock != NULL) {
18191da177e4SLinus Torvalds 		err = security_socket_setsockopt(sock, level, optname);
18206cb153caSBenjamin LaHaise 		if (err)
18216cb153caSBenjamin LaHaise 			goto out_put;
18221da177e4SLinus Torvalds 
18231da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
182489bddce5SStephen Hemminger 			err =
182589bddce5SStephen Hemminger 			    sock_setsockopt(sock, level, optname, optval,
182689bddce5SStephen Hemminger 					    optlen);
18271da177e4SLinus Torvalds 		else
182889bddce5SStephen Hemminger 			err =
182989bddce5SStephen Hemminger 			    sock->ops->setsockopt(sock, level, optname, optval,
183089bddce5SStephen Hemminger 						  optlen);
18316cb153caSBenjamin LaHaise out_put:
18326cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
18331da177e4SLinus Torvalds 	}
18341da177e4SLinus Torvalds 	return err;
18351da177e4SLinus Torvalds }
18361da177e4SLinus Torvalds 
18371da177e4SLinus Torvalds /*
18381da177e4SLinus Torvalds  *	Get a socket option. Because we don't know the option lengths we have
18391da177e4SLinus Torvalds  *	to pass a user mode parameter for the protocols to sort out.
18401da177e4SLinus Torvalds  */
18411da177e4SLinus Torvalds 
184220f37034SHeiko Carstens SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
184320f37034SHeiko Carstens 		char __user *, optval, int __user *, optlen)
18441da177e4SLinus Torvalds {
18456cb153caSBenjamin LaHaise 	int err, fput_needed;
18461da177e4SLinus Torvalds 	struct socket *sock;
18471da177e4SLinus Torvalds 
184889bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
184989bddce5SStephen Hemminger 	if (sock != NULL) {
18506cb153caSBenjamin LaHaise 		err = security_socket_getsockopt(sock, level, optname);
18516cb153caSBenjamin LaHaise 		if (err)
18526cb153caSBenjamin LaHaise 			goto out_put;
18531da177e4SLinus Torvalds 
18541da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
185589bddce5SStephen Hemminger 			err =
185689bddce5SStephen Hemminger 			    sock_getsockopt(sock, level, optname, optval,
185789bddce5SStephen Hemminger 					    optlen);
18581da177e4SLinus Torvalds 		else
185989bddce5SStephen Hemminger 			err =
186089bddce5SStephen Hemminger 			    sock->ops->getsockopt(sock, level, optname, optval,
186189bddce5SStephen Hemminger 						  optlen);
18626cb153caSBenjamin LaHaise out_put:
18636cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
18641da177e4SLinus Torvalds 	}
18651da177e4SLinus Torvalds 	return err;
18661da177e4SLinus Torvalds }
18671da177e4SLinus Torvalds 
18681da177e4SLinus Torvalds /*
18691da177e4SLinus Torvalds  *	Shutdown a socket.
18701da177e4SLinus Torvalds  */
18711da177e4SLinus Torvalds 
1872754fe8d2SHeiko Carstens SYSCALL_DEFINE2(shutdown, int, fd, int, how)
18731da177e4SLinus Torvalds {
18746cb153caSBenjamin LaHaise 	int err, fput_needed;
18751da177e4SLinus Torvalds 	struct socket *sock;
18761da177e4SLinus Torvalds 
187789bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
187889bddce5SStephen Hemminger 	if (sock != NULL) {
18791da177e4SLinus Torvalds 		err = security_socket_shutdown(sock, how);
18806cb153caSBenjamin LaHaise 		if (!err)
18811da177e4SLinus Torvalds 			err = sock->ops->shutdown(sock, how);
18826cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
18831da177e4SLinus Torvalds 	}
18841da177e4SLinus Torvalds 	return err;
18851da177e4SLinus Torvalds }
18861da177e4SLinus Torvalds 
18871da177e4SLinus Torvalds /* A couple of helpful macros for getting the address of the 32/64 bit
18881da177e4SLinus Torvalds  * fields which are the same type (int / unsigned) on our platforms.
18891da177e4SLinus Torvalds  */
18901da177e4SLinus Torvalds #define COMPAT_MSG(msg, member)	((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member)
18911da177e4SLinus Torvalds #define COMPAT_NAMELEN(msg)	COMPAT_MSG(msg, msg_namelen)
18921da177e4SLinus Torvalds #define COMPAT_FLAGS(msg)	COMPAT_MSG(msg, msg_flags)
18931da177e4SLinus Torvalds 
1894c71d8ebeSTetsuo Handa struct used_address {
1895c71d8ebeSTetsuo Handa 	struct sockaddr_storage name;
1896c71d8ebeSTetsuo Handa 	unsigned int name_len;
1897c71d8ebeSTetsuo Handa };
1898c71d8ebeSTetsuo Handa 
1899228e548eSAnton Blanchard static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
1900c71d8ebeSTetsuo Handa 			 struct msghdr *msg_sys, unsigned flags,
1901c71d8ebeSTetsuo Handa 			 struct used_address *used_address)
19021da177e4SLinus Torvalds {
190389bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
190489bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
1905230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
19061da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
1907b9d717a7SAlex Williamson 	unsigned char ctl[sizeof(struct cmsghdr) + 20]
1908b9d717a7SAlex Williamson 	    __attribute__ ((aligned(sizeof(__kernel_size_t))));
1909b9d717a7SAlex Williamson 	/* 20 is size of ipv6_pktinfo */
19101da177e4SLinus Torvalds 	unsigned char *ctl_buf = ctl;
19111da177e4SLinus Torvalds 	int err, ctl_len, iov_size, total_len;
19121da177e4SLinus Torvalds 
19131da177e4SLinus Torvalds 	err = -EFAULT;
19141da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
1915228e548eSAnton Blanchard 		if (get_compat_msghdr(msg_sys, msg_compat))
19161da177e4SLinus Torvalds 			return -EFAULT;
1917228e548eSAnton Blanchard 	} else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr)))
19181da177e4SLinus Torvalds 		return -EFAULT;
19191da177e4SLinus Torvalds 
19201da177e4SLinus Torvalds 	/* do not move before msg_sys is valid */
19211da177e4SLinus Torvalds 	err = -EMSGSIZE;
1922228e548eSAnton Blanchard 	if (msg_sys->msg_iovlen > UIO_MAXIOV)
1923228e548eSAnton Blanchard 		goto out;
19241da177e4SLinus Torvalds 
19251da177e4SLinus Torvalds 	/* Check whether to allocate the iovec area */
19261da177e4SLinus Torvalds 	err = -ENOMEM;
1927228e548eSAnton Blanchard 	iov_size = msg_sys->msg_iovlen * sizeof(struct iovec);
1928228e548eSAnton Blanchard 	if (msg_sys->msg_iovlen > UIO_FASTIOV) {
19291da177e4SLinus Torvalds 		iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
19301da177e4SLinus Torvalds 		if (!iov)
1931228e548eSAnton Blanchard 			goto out;
19321da177e4SLinus Torvalds 	}
19331da177e4SLinus Torvalds 
19341da177e4SLinus Torvalds 	/* This will also move the address data into kernel space */
19351da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
1936228e548eSAnton Blanchard 		err = verify_compat_iovec(msg_sys, iov,
1937230b1839SYOSHIFUJI Hideaki 					  (struct sockaddr *)&address,
1938230b1839SYOSHIFUJI Hideaki 					  VERIFY_READ);
19391da177e4SLinus Torvalds 	} else
1940228e548eSAnton Blanchard 		err = verify_iovec(msg_sys, iov,
1941230b1839SYOSHIFUJI Hideaki 				   (struct sockaddr *)&address,
1942230b1839SYOSHIFUJI Hideaki 				   VERIFY_READ);
19431da177e4SLinus Torvalds 	if (err < 0)
19441da177e4SLinus Torvalds 		goto out_freeiov;
19451da177e4SLinus Torvalds 	total_len = err;
19461da177e4SLinus Torvalds 
19471da177e4SLinus Torvalds 	err = -ENOBUFS;
19481da177e4SLinus Torvalds 
1949228e548eSAnton Blanchard 	if (msg_sys->msg_controllen > INT_MAX)
19501da177e4SLinus Torvalds 		goto out_freeiov;
1951228e548eSAnton Blanchard 	ctl_len = msg_sys->msg_controllen;
19521da177e4SLinus Torvalds 	if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
195389bddce5SStephen Hemminger 		err =
1954228e548eSAnton Blanchard 		    cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl,
195589bddce5SStephen Hemminger 						     sizeof(ctl));
19561da177e4SLinus Torvalds 		if (err)
19571da177e4SLinus Torvalds 			goto out_freeiov;
1958228e548eSAnton Blanchard 		ctl_buf = msg_sys->msg_control;
1959228e548eSAnton Blanchard 		ctl_len = msg_sys->msg_controllen;
19601da177e4SLinus Torvalds 	} else if (ctl_len) {
196189bddce5SStephen Hemminger 		if (ctl_len > sizeof(ctl)) {
19621da177e4SLinus Torvalds 			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
19631da177e4SLinus Torvalds 			if (ctl_buf == NULL)
19641da177e4SLinus Torvalds 				goto out_freeiov;
19651da177e4SLinus Torvalds 		}
19661da177e4SLinus Torvalds 		err = -EFAULT;
19671da177e4SLinus Torvalds 		/*
1968228e548eSAnton Blanchard 		 * Careful! Before this, msg_sys->msg_control contains a user pointer.
19691da177e4SLinus Torvalds 		 * Afterwards, it will be a kernel pointer. Thus the compiler-assisted
19701da177e4SLinus Torvalds 		 * checking falls down on this.
19711da177e4SLinus Torvalds 		 */
1972fb8621bbSNamhyung Kim 		if (copy_from_user(ctl_buf,
1973228e548eSAnton Blanchard 				   (void __user __force *)msg_sys->msg_control,
197489bddce5SStephen Hemminger 				   ctl_len))
19751da177e4SLinus Torvalds 			goto out_freectl;
1976228e548eSAnton Blanchard 		msg_sys->msg_control = ctl_buf;
19771da177e4SLinus Torvalds 	}
1978228e548eSAnton Blanchard 	msg_sys->msg_flags = flags;
19791da177e4SLinus Torvalds 
19801da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
1981228e548eSAnton Blanchard 		msg_sys->msg_flags |= MSG_DONTWAIT;
1982c71d8ebeSTetsuo Handa 	/*
1983c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and current destination address is same as
1984c71d8ebeSTetsuo Handa 	 * previously succeeded address, omit asking LSM's decision.
1985c71d8ebeSTetsuo Handa 	 * used_address->name_len is initialized to UINT_MAX so that the first
1986c71d8ebeSTetsuo Handa 	 * destination address never matches.
1987c71d8ebeSTetsuo Handa 	 */
1988bc909d9dSMathieu Desnoyers 	if (used_address && msg_sys->msg_name &&
1989bc909d9dSMathieu Desnoyers 	    used_address->name_len == msg_sys->msg_namelen &&
1990bc909d9dSMathieu Desnoyers 	    !memcmp(&used_address->name, msg_sys->msg_name,
1991c71d8ebeSTetsuo Handa 		    used_address->name_len)) {
1992c71d8ebeSTetsuo Handa 		err = sock_sendmsg_nosec(sock, msg_sys, total_len);
1993c71d8ebeSTetsuo Handa 		goto out_freectl;
1994c71d8ebeSTetsuo Handa 	}
1995c71d8ebeSTetsuo Handa 	err = sock_sendmsg(sock, msg_sys, total_len);
1996c71d8ebeSTetsuo Handa 	/*
1997c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and sending to current destination address was
1998c71d8ebeSTetsuo Handa 	 * successful, remember it.
1999c71d8ebeSTetsuo Handa 	 */
2000c71d8ebeSTetsuo Handa 	if (used_address && err >= 0) {
2001c71d8ebeSTetsuo Handa 		used_address->name_len = msg_sys->msg_namelen;
2002bc909d9dSMathieu Desnoyers 		if (msg_sys->msg_name)
2003bc909d9dSMathieu Desnoyers 			memcpy(&used_address->name, msg_sys->msg_name,
2004c71d8ebeSTetsuo Handa 			       used_address->name_len);
2005c71d8ebeSTetsuo Handa 	}
20061da177e4SLinus Torvalds 
20071da177e4SLinus Torvalds out_freectl:
20081da177e4SLinus Torvalds 	if (ctl_buf != ctl)
20091da177e4SLinus Torvalds 		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
20101da177e4SLinus Torvalds out_freeiov:
20111da177e4SLinus Torvalds 	if (iov != iovstack)
20121da177e4SLinus Torvalds 		sock_kfree_s(sock->sk, iov, iov_size);
2013228e548eSAnton Blanchard out:
2014228e548eSAnton Blanchard 	return err;
2015228e548eSAnton Blanchard }
2016228e548eSAnton Blanchard 
2017228e548eSAnton Blanchard /*
2018228e548eSAnton Blanchard  *	BSD sendmsg interface
2019228e548eSAnton Blanchard  */
2020228e548eSAnton Blanchard 
2021228e548eSAnton Blanchard SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned, flags)
2022228e548eSAnton Blanchard {
2023228e548eSAnton Blanchard 	int fput_needed, err;
2024228e548eSAnton Blanchard 	struct msghdr msg_sys;
2025228e548eSAnton Blanchard 	struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed);
2026228e548eSAnton Blanchard 
2027228e548eSAnton Blanchard 	if (!sock)
2028228e548eSAnton Blanchard 		goto out;
2029228e548eSAnton Blanchard 
2030c71d8ebeSTetsuo Handa 	err = __sys_sendmsg(sock, msg, &msg_sys, flags, NULL);
2031228e548eSAnton Blanchard 
20326cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
20331da177e4SLinus Torvalds out:
20341da177e4SLinus Torvalds 	return err;
20351da177e4SLinus Torvalds }
20361da177e4SLinus Torvalds 
2037228e548eSAnton Blanchard /*
2038228e548eSAnton Blanchard  *	Linux sendmmsg interface
2039228e548eSAnton Blanchard  */
2040228e548eSAnton Blanchard 
2041228e548eSAnton Blanchard int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2042228e548eSAnton Blanchard 		   unsigned int flags)
2043228e548eSAnton Blanchard {
2044228e548eSAnton Blanchard 	int fput_needed, err, datagrams;
2045228e548eSAnton Blanchard 	struct socket *sock;
2046228e548eSAnton Blanchard 	struct mmsghdr __user *entry;
2047228e548eSAnton Blanchard 	struct compat_mmsghdr __user *compat_entry;
2048228e548eSAnton Blanchard 	struct msghdr msg_sys;
2049c71d8ebeSTetsuo Handa 	struct used_address used_address;
2050228e548eSAnton Blanchard 
205198382f41SAnton Blanchard 	if (vlen > UIO_MAXIOV)
205298382f41SAnton Blanchard 		vlen = UIO_MAXIOV;
2053228e548eSAnton Blanchard 
2054228e548eSAnton Blanchard 	datagrams = 0;
2055228e548eSAnton Blanchard 
2056228e548eSAnton Blanchard 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2057228e548eSAnton Blanchard 	if (!sock)
2058228e548eSAnton Blanchard 		return err;
2059228e548eSAnton Blanchard 
2060c71d8ebeSTetsuo Handa 	used_address.name_len = UINT_MAX;
2061228e548eSAnton Blanchard 	entry = mmsg;
2062228e548eSAnton Blanchard 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2063728ffb86SAnton Blanchard 	err = 0;
2064228e548eSAnton Blanchard 
2065228e548eSAnton Blanchard 	while (datagrams < vlen) {
2066228e548eSAnton Blanchard 		if (MSG_CMSG_COMPAT & flags) {
2067228e548eSAnton Blanchard 			err = __sys_sendmsg(sock, (struct msghdr __user *)compat_entry,
2068c71d8ebeSTetsuo Handa 					    &msg_sys, flags, &used_address);
2069228e548eSAnton Blanchard 			if (err < 0)
2070228e548eSAnton Blanchard 				break;
2071228e548eSAnton Blanchard 			err = __put_user(err, &compat_entry->msg_len);
2072228e548eSAnton Blanchard 			++compat_entry;
2073228e548eSAnton Blanchard 		} else {
2074228e548eSAnton Blanchard 			err = __sys_sendmsg(sock, (struct msghdr __user *)entry,
2075c71d8ebeSTetsuo Handa 					    &msg_sys, flags, &used_address);
2076228e548eSAnton Blanchard 			if (err < 0)
2077228e548eSAnton Blanchard 				break;
2078228e548eSAnton Blanchard 			err = put_user(err, &entry->msg_len);
2079228e548eSAnton Blanchard 			++entry;
2080228e548eSAnton Blanchard 		}
2081228e548eSAnton Blanchard 
2082228e548eSAnton Blanchard 		if (err)
2083228e548eSAnton Blanchard 			break;
2084228e548eSAnton Blanchard 		++datagrams;
2085228e548eSAnton Blanchard 	}
2086228e548eSAnton Blanchard 
2087228e548eSAnton Blanchard 	fput_light(sock->file, fput_needed);
2088228e548eSAnton Blanchard 
2089728ffb86SAnton Blanchard 	/* We only return an error if no datagrams were able to be sent */
2090728ffb86SAnton Blanchard 	if (datagrams != 0)
2091228e548eSAnton Blanchard 		return datagrams;
2092228e548eSAnton Blanchard 
2093228e548eSAnton Blanchard 	return err;
2094228e548eSAnton Blanchard }
2095228e548eSAnton Blanchard 
2096228e548eSAnton Blanchard SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
2097228e548eSAnton Blanchard 		unsigned int, vlen, unsigned int, flags)
2098228e548eSAnton Blanchard {
2099228e548eSAnton Blanchard 	return __sys_sendmmsg(fd, mmsg, vlen, flags);
2100228e548eSAnton Blanchard }
2101228e548eSAnton Blanchard 
2102a2e27255SArnaldo Carvalho de Melo static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
2103a2e27255SArnaldo Carvalho de Melo 			 struct msghdr *msg_sys, unsigned flags, int nosec)
21041da177e4SLinus Torvalds {
210589bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
210689bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
21071da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV];
21081da177e4SLinus Torvalds 	struct iovec *iov = iovstack;
21091da177e4SLinus Torvalds 	unsigned long cmsg_ptr;
21101da177e4SLinus Torvalds 	int err, iov_size, total_len, len;
21111da177e4SLinus Torvalds 
21121da177e4SLinus Torvalds 	/* kernel mode address */
2113230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage addr;
21141da177e4SLinus Torvalds 
21151da177e4SLinus Torvalds 	/* user mode address pointers */
21161da177e4SLinus Torvalds 	struct sockaddr __user *uaddr;
21171da177e4SLinus Torvalds 	int __user *uaddr_len;
21181da177e4SLinus Torvalds 
21191da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
2120a2e27255SArnaldo Carvalho de Melo 		if (get_compat_msghdr(msg_sys, msg_compat))
21211da177e4SLinus Torvalds 			return -EFAULT;
2122c6d409cfSEric Dumazet 	} else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr)))
21231da177e4SLinus Torvalds 		return -EFAULT;
21241da177e4SLinus Torvalds 
21251da177e4SLinus Torvalds 	err = -EMSGSIZE;
2126a2e27255SArnaldo Carvalho de Melo 	if (msg_sys->msg_iovlen > UIO_MAXIOV)
2127a2e27255SArnaldo Carvalho de Melo 		goto out;
21281da177e4SLinus Torvalds 
21291da177e4SLinus Torvalds 	/* Check whether to allocate the iovec area */
21301da177e4SLinus Torvalds 	err = -ENOMEM;
2131a2e27255SArnaldo Carvalho de Melo 	iov_size = msg_sys->msg_iovlen * sizeof(struct iovec);
2132a2e27255SArnaldo Carvalho de Melo 	if (msg_sys->msg_iovlen > UIO_FASTIOV) {
21331da177e4SLinus Torvalds 		iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
21341da177e4SLinus Torvalds 		if (!iov)
2135a2e27255SArnaldo Carvalho de Melo 			goto out;
21361da177e4SLinus Torvalds 	}
21371da177e4SLinus Torvalds 
21381da177e4SLinus Torvalds 	/*
21391da177e4SLinus Torvalds 	 *      Save the user-mode address (verify_iovec will change the
21401da177e4SLinus Torvalds 	 *      kernel msghdr to use the kernel address space)
21411da177e4SLinus Torvalds 	 */
21421da177e4SLinus Torvalds 
2143a2e27255SArnaldo Carvalho de Melo 	uaddr = (__force void __user *)msg_sys->msg_name;
21441da177e4SLinus Torvalds 	uaddr_len = COMPAT_NAMELEN(msg);
21451da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
2146a2e27255SArnaldo Carvalho de Melo 		err = verify_compat_iovec(msg_sys, iov,
2147230b1839SYOSHIFUJI Hideaki 					  (struct sockaddr *)&addr,
2148230b1839SYOSHIFUJI Hideaki 					  VERIFY_WRITE);
21491da177e4SLinus Torvalds 	} else
2150a2e27255SArnaldo Carvalho de Melo 		err = verify_iovec(msg_sys, iov,
2151230b1839SYOSHIFUJI Hideaki 				   (struct sockaddr *)&addr,
2152230b1839SYOSHIFUJI Hideaki 				   VERIFY_WRITE);
21531da177e4SLinus Torvalds 	if (err < 0)
21541da177e4SLinus Torvalds 		goto out_freeiov;
21551da177e4SLinus Torvalds 	total_len = err;
21561da177e4SLinus Torvalds 
2157a2e27255SArnaldo Carvalho de Melo 	cmsg_ptr = (unsigned long)msg_sys->msg_control;
2158a2e27255SArnaldo Carvalho de Melo 	msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
21591da177e4SLinus Torvalds 
21601da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
21611da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
2162a2e27255SArnaldo Carvalho de Melo 	err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys,
2163a2e27255SArnaldo Carvalho de Melo 							  total_len, flags);
21641da177e4SLinus Torvalds 	if (err < 0)
21651da177e4SLinus Torvalds 		goto out_freeiov;
21661da177e4SLinus Torvalds 	len = err;
21671da177e4SLinus Torvalds 
21681da177e4SLinus Torvalds 	if (uaddr != NULL) {
2169230b1839SYOSHIFUJI Hideaki 		err = move_addr_to_user((struct sockaddr *)&addr,
2170a2e27255SArnaldo Carvalho de Melo 					msg_sys->msg_namelen, uaddr,
217189bddce5SStephen Hemminger 					uaddr_len);
21721da177e4SLinus Torvalds 		if (err < 0)
21731da177e4SLinus Torvalds 			goto out_freeiov;
21741da177e4SLinus Torvalds 	}
2175a2e27255SArnaldo Carvalho de Melo 	err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
217637f7f421SDavid S. Miller 			 COMPAT_FLAGS(msg));
21771da177e4SLinus Torvalds 	if (err)
21781da177e4SLinus Torvalds 		goto out_freeiov;
21791da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags)
2180a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
21811da177e4SLinus Torvalds 				 &msg_compat->msg_controllen);
21821da177e4SLinus Torvalds 	else
2183a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
21841da177e4SLinus Torvalds 				 &msg->msg_controllen);
21851da177e4SLinus Torvalds 	if (err)
21861da177e4SLinus Torvalds 		goto out_freeiov;
21871da177e4SLinus Torvalds 	err = len;
21881da177e4SLinus Torvalds 
21891da177e4SLinus Torvalds out_freeiov:
21901da177e4SLinus Torvalds 	if (iov != iovstack)
21911da177e4SLinus Torvalds 		sock_kfree_s(sock->sk, iov, iov_size);
2192a2e27255SArnaldo Carvalho de Melo out:
2193a2e27255SArnaldo Carvalho de Melo 	return err;
2194a2e27255SArnaldo Carvalho de Melo }
2195a2e27255SArnaldo Carvalho de Melo 
2196a2e27255SArnaldo Carvalho de Melo /*
2197a2e27255SArnaldo Carvalho de Melo  *	BSD recvmsg interface
2198a2e27255SArnaldo Carvalho de Melo  */
2199a2e27255SArnaldo Carvalho de Melo 
2200a2e27255SArnaldo Carvalho de Melo SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg,
2201a2e27255SArnaldo Carvalho de Melo 		unsigned int, flags)
2202a2e27255SArnaldo Carvalho de Melo {
2203a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err;
2204a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
2205a2e27255SArnaldo Carvalho de Melo 	struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed);
2206a2e27255SArnaldo Carvalho de Melo 
2207a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2208a2e27255SArnaldo Carvalho de Melo 		goto out;
2209a2e27255SArnaldo Carvalho de Melo 
2210a2e27255SArnaldo Carvalho de Melo 	err = __sys_recvmsg(sock, msg, &msg_sys, flags, 0);
2211a2e27255SArnaldo Carvalho de Melo 
22126cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
22131da177e4SLinus Torvalds out:
22141da177e4SLinus Torvalds 	return err;
22151da177e4SLinus Torvalds }
22161da177e4SLinus Torvalds 
2217a2e27255SArnaldo Carvalho de Melo /*
2218a2e27255SArnaldo Carvalho de Melo  *     Linux recvmmsg interface
2219a2e27255SArnaldo Carvalho de Melo  */
22201da177e4SLinus Torvalds 
2221a2e27255SArnaldo Carvalho de Melo int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2222a2e27255SArnaldo Carvalho de Melo 		   unsigned int flags, struct timespec *timeout)
2223a2e27255SArnaldo Carvalho de Melo {
2224a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err, datagrams;
2225a2e27255SArnaldo Carvalho de Melo 	struct socket *sock;
2226a2e27255SArnaldo Carvalho de Melo 	struct mmsghdr __user *entry;
2227d7256d0eSJean-Mickael Guerin 	struct compat_mmsghdr __user *compat_entry;
2228a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
2229a2e27255SArnaldo Carvalho de Melo 	struct timespec end_time;
2230a2e27255SArnaldo Carvalho de Melo 
2231a2e27255SArnaldo Carvalho de Melo 	if (timeout &&
2232a2e27255SArnaldo Carvalho de Melo 	    poll_select_set_timeout(&end_time, timeout->tv_sec,
2233a2e27255SArnaldo Carvalho de Melo 				    timeout->tv_nsec))
2234a2e27255SArnaldo Carvalho de Melo 		return -EINVAL;
2235a2e27255SArnaldo Carvalho de Melo 
2236a2e27255SArnaldo Carvalho de Melo 	datagrams = 0;
2237a2e27255SArnaldo Carvalho de Melo 
2238a2e27255SArnaldo Carvalho de Melo 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2239a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2240a2e27255SArnaldo Carvalho de Melo 		return err;
2241a2e27255SArnaldo Carvalho de Melo 
2242a2e27255SArnaldo Carvalho de Melo 	err = sock_error(sock->sk);
2243a2e27255SArnaldo Carvalho de Melo 	if (err)
2244a2e27255SArnaldo Carvalho de Melo 		goto out_put;
2245a2e27255SArnaldo Carvalho de Melo 
2246a2e27255SArnaldo Carvalho de Melo 	entry = mmsg;
2247d7256d0eSJean-Mickael Guerin 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2248a2e27255SArnaldo Carvalho de Melo 
2249a2e27255SArnaldo Carvalho de Melo 	while (datagrams < vlen) {
2250a2e27255SArnaldo Carvalho de Melo 		/*
2251a2e27255SArnaldo Carvalho de Melo 		 * No need to ask LSM for more than the first datagram.
2252a2e27255SArnaldo Carvalho de Melo 		 */
2253d7256d0eSJean-Mickael Guerin 		if (MSG_CMSG_COMPAT & flags) {
2254d7256d0eSJean-Mickael Guerin 			err = __sys_recvmsg(sock, (struct msghdr __user *)compat_entry,
2255b9eb8b87SAnton Blanchard 					    &msg_sys, flags & ~MSG_WAITFORONE,
2256b9eb8b87SAnton Blanchard 					    datagrams);
2257d7256d0eSJean-Mickael Guerin 			if (err < 0)
2258d7256d0eSJean-Mickael Guerin 				break;
2259d7256d0eSJean-Mickael Guerin 			err = __put_user(err, &compat_entry->msg_len);
2260d7256d0eSJean-Mickael Guerin 			++compat_entry;
2261d7256d0eSJean-Mickael Guerin 		} else {
2262a2e27255SArnaldo Carvalho de Melo 			err = __sys_recvmsg(sock, (struct msghdr __user *)entry,
2263b9eb8b87SAnton Blanchard 					    &msg_sys, flags & ~MSG_WAITFORONE,
2264b9eb8b87SAnton Blanchard 					    datagrams);
2265a2e27255SArnaldo Carvalho de Melo 			if (err < 0)
2266a2e27255SArnaldo Carvalho de Melo 				break;
2267a2e27255SArnaldo Carvalho de Melo 			err = put_user(err, &entry->msg_len);
2268d7256d0eSJean-Mickael Guerin 			++entry;
2269d7256d0eSJean-Mickael Guerin 		}
2270d7256d0eSJean-Mickael Guerin 
2271a2e27255SArnaldo Carvalho de Melo 		if (err)
2272a2e27255SArnaldo Carvalho de Melo 			break;
2273a2e27255SArnaldo Carvalho de Melo 		++datagrams;
2274a2e27255SArnaldo Carvalho de Melo 
227571c5c159SBrandon L Black 		/* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
227671c5c159SBrandon L Black 		if (flags & MSG_WAITFORONE)
227771c5c159SBrandon L Black 			flags |= MSG_DONTWAIT;
227871c5c159SBrandon L Black 
2279a2e27255SArnaldo Carvalho de Melo 		if (timeout) {
2280a2e27255SArnaldo Carvalho de Melo 			ktime_get_ts(timeout);
2281a2e27255SArnaldo Carvalho de Melo 			*timeout = timespec_sub(end_time, *timeout);
2282a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_sec < 0) {
2283a2e27255SArnaldo Carvalho de Melo 				timeout->tv_sec = timeout->tv_nsec = 0;
2284a2e27255SArnaldo Carvalho de Melo 				break;
2285a2e27255SArnaldo Carvalho de Melo 			}
2286a2e27255SArnaldo Carvalho de Melo 
2287a2e27255SArnaldo Carvalho de Melo 			/* Timeout, return less than vlen datagrams */
2288a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_nsec == 0 && timeout->tv_sec == 0)
2289a2e27255SArnaldo Carvalho de Melo 				break;
2290a2e27255SArnaldo Carvalho de Melo 		}
2291a2e27255SArnaldo Carvalho de Melo 
2292a2e27255SArnaldo Carvalho de Melo 		/* Out of band data, return right away */
2293a2e27255SArnaldo Carvalho de Melo 		if (msg_sys.msg_flags & MSG_OOB)
2294a2e27255SArnaldo Carvalho de Melo 			break;
2295a2e27255SArnaldo Carvalho de Melo 	}
2296a2e27255SArnaldo Carvalho de Melo 
2297a2e27255SArnaldo Carvalho de Melo out_put:
2298a2e27255SArnaldo Carvalho de Melo 	fput_light(sock->file, fput_needed);
2299a2e27255SArnaldo Carvalho de Melo 
2300a2e27255SArnaldo Carvalho de Melo 	if (err == 0)
2301a2e27255SArnaldo Carvalho de Melo 		return datagrams;
2302a2e27255SArnaldo Carvalho de Melo 
2303a2e27255SArnaldo Carvalho de Melo 	if (datagrams != 0) {
2304a2e27255SArnaldo Carvalho de Melo 		/*
2305a2e27255SArnaldo Carvalho de Melo 		 * We may return less entries than requested (vlen) if the
2306a2e27255SArnaldo Carvalho de Melo 		 * sock is non block and there aren't enough datagrams...
2307a2e27255SArnaldo Carvalho de Melo 		 */
2308a2e27255SArnaldo Carvalho de Melo 		if (err != -EAGAIN) {
2309a2e27255SArnaldo Carvalho de Melo 			/*
2310a2e27255SArnaldo Carvalho de Melo 			 * ... or  if recvmsg returns an error after we
2311a2e27255SArnaldo Carvalho de Melo 			 * received some datagrams, where we record the
2312a2e27255SArnaldo Carvalho de Melo 			 * error to return on the next call or if the
2313a2e27255SArnaldo Carvalho de Melo 			 * app asks about it using getsockopt(SO_ERROR).
2314a2e27255SArnaldo Carvalho de Melo 			 */
2315a2e27255SArnaldo Carvalho de Melo 			sock->sk->sk_err = -err;
2316a2e27255SArnaldo Carvalho de Melo 		}
2317a2e27255SArnaldo Carvalho de Melo 
2318a2e27255SArnaldo Carvalho de Melo 		return datagrams;
2319a2e27255SArnaldo Carvalho de Melo 	}
2320a2e27255SArnaldo Carvalho de Melo 
2321a2e27255SArnaldo Carvalho de Melo 	return err;
2322a2e27255SArnaldo Carvalho de Melo }
2323a2e27255SArnaldo Carvalho de Melo 
2324a2e27255SArnaldo Carvalho de Melo SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
2325a2e27255SArnaldo Carvalho de Melo 		unsigned int, vlen, unsigned int, flags,
2326a2e27255SArnaldo Carvalho de Melo 		struct timespec __user *, timeout)
2327a2e27255SArnaldo Carvalho de Melo {
2328a2e27255SArnaldo Carvalho de Melo 	int datagrams;
2329a2e27255SArnaldo Carvalho de Melo 	struct timespec timeout_sys;
2330a2e27255SArnaldo Carvalho de Melo 
2331a2e27255SArnaldo Carvalho de Melo 	if (!timeout)
2332a2e27255SArnaldo Carvalho de Melo 		return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL);
2333a2e27255SArnaldo Carvalho de Melo 
2334a2e27255SArnaldo Carvalho de Melo 	if (copy_from_user(&timeout_sys, timeout, sizeof(timeout_sys)))
2335a2e27255SArnaldo Carvalho de Melo 		return -EFAULT;
2336a2e27255SArnaldo Carvalho de Melo 
2337a2e27255SArnaldo Carvalho de Melo 	datagrams = __sys_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys);
2338a2e27255SArnaldo Carvalho de Melo 
2339a2e27255SArnaldo Carvalho de Melo 	if (datagrams > 0 &&
2340a2e27255SArnaldo Carvalho de Melo 	    copy_to_user(timeout, &timeout_sys, sizeof(timeout_sys)))
2341a2e27255SArnaldo Carvalho de Melo 		datagrams = -EFAULT;
2342a2e27255SArnaldo Carvalho de Melo 
2343a2e27255SArnaldo Carvalho de Melo 	return datagrams;
2344a2e27255SArnaldo Carvalho de Melo }
2345a2e27255SArnaldo Carvalho de Melo 
2346a2e27255SArnaldo Carvalho de Melo #ifdef __ARCH_WANT_SYS_SOCKETCALL
23471da177e4SLinus Torvalds /* Argument list sizes for sys_socketcall */
23481da177e4SLinus Torvalds #define AL(x) ((x) * sizeof(unsigned long))
2349228e548eSAnton Blanchard static const unsigned char nargs[21] = {
235089bddce5SStephen Hemminger 	AL(0), AL(3), AL(3), AL(3), AL(2), AL(3),
23511da177e4SLinus Torvalds 	AL(3), AL(3), AL(4), AL(4), AL(4), AL(6),
2352aaca0bdcSUlrich Drepper 	AL(6), AL(2), AL(5), AL(5), AL(3), AL(3),
2353228e548eSAnton Blanchard 	AL(4), AL(5), AL(4)
235489bddce5SStephen Hemminger };
235589bddce5SStephen Hemminger 
23561da177e4SLinus Torvalds #undef AL
23571da177e4SLinus Torvalds 
23581da177e4SLinus Torvalds /*
23591da177e4SLinus Torvalds  *	System call vectors.
23601da177e4SLinus Torvalds  *
23611da177e4SLinus Torvalds  *	Argument checking cleaned up. Saved 20% in size.
23621da177e4SLinus Torvalds  *  This function doesn't need to set the kernel lock because
23631da177e4SLinus Torvalds  *  it is set by the callees.
23641da177e4SLinus Torvalds  */
23651da177e4SLinus Torvalds 
23663e0fa65fSHeiko Carstens SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
23671da177e4SLinus Torvalds {
23681da177e4SLinus Torvalds 	unsigned long a[6];
23691da177e4SLinus Torvalds 	unsigned long a0, a1;
23701da177e4SLinus Torvalds 	int err;
237147379052SArjan van de Ven 	unsigned int len;
23721da177e4SLinus Torvalds 
2373228e548eSAnton Blanchard 	if (call < 1 || call > SYS_SENDMMSG)
23741da177e4SLinus Torvalds 		return -EINVAL;
23751da177e4SLinus Torvalds 
237647379052SArjan van de Ven 	len = nargs[call];
237747379052SArjan van de Ven 	if (len > sizeof(a))
237847379052SArjan van de Ven 		return -EINVAL;
237947379052SArjan van de Ven 
23801da177e4SLinus Torvalds 	/* copy_from_user should be SMP safe. */
238147379052SArjan van de Ven 	if (copy_from_user(a, args, len))
23821da177e4SLinus Torvalds 		return -EFAULT;
23831da177e4SLinus Torvalds 
2384f3298dc4SAl Viro 	audit_socketcall(nargs[call] / sizeof(unsigned long), a);
23853ec3b2fbSDavid Woodhouse 
23861da177e4SLinus Torvalds 	a0 = a[0];
23871da177e4SLinus Torvalds 	a1 = a[1];
23881da177e4SLinus Torvalds 
238989bddce5SStephen Hemminger 	switch (call) {
23901da177e4SLinus Torvalds 	case SYS_SOCKET:
23911da177e4SLinus Torvalds 		err = sys_socket(a0, a1, a[2]);
23921da177e4SLinus Torvalds 		break;
23931da177e4SLinus Torvalds 	case SYS_BIND:
23941da177e4SLinus Torvalds 		err = sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
23951da177e4SLinus Torvalds 		break;
23961da177e4SLinus Torvalds 	case SYS_CONNECT:
23971da177e4SLinus Torvalds 		err = sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
23981da177e4SLinus Torvalds 		break;
23991da177e4SLinus Torvalds 	case SYS_LISTEN:
24001da177e4SLinus Torvalds 		err = sys_listen(a0, a1);
24011da177e4SLinus Torvalds 		break;
24021da177e4SLinus Torvalds 	case SYS_ACCEPT:
2403de11defeSUlrich Drepper 		err = sys_accept4(a0, (struct sockaddr __user *)a1,
2404aaca0bdcSUlrich Drepper 				  (int __user *)a[2], 0);
24051da177e4SLinus Torvalds 		break;
24061da177e4SLinus Torvalds 	case SYS_GETSOCKNAME:
240789bddce5SStephen Hemminger 		err =
240889bddce5SStephen Hemminger 		    sys_getsockname(a0, (struct sockaddr __user *)a1,
240989bddce5SStephen Hemminger 				    (int __user *)a[2]);
24101da177e4SLinus Torvalds 		break;
24111da177e4SLinus Torvalds 	case SYS_GETPEERNAME:
241289bddce5SStephen Hemminger 		err =
241389bddce5SStephen Hemminger 		    sys_getpeername(a0, (struct sockaddr __user *)a1,
241489bddce5SStephen Hemminger 				    (int __user *)a[2]);
24151da177e4SLinus Torvalds 		break;
24161da177e4SLinus Torvalds 	case SYS_SOCKETPAIR:
24171da177e4SLinus Torvalds 		err = sys_socketpair(a0, a1, a[2], (int __user *)a[3]);
24181da177e4SLinus Torvalds 		break;
24191da177e4SLinus Torvalds 	case SYS_SEND:
24201da177e4SLinus Torvalds 		err = sys_send(a0, (void __user *)a1, a[2], a[3]);
24211da177e4SLinus Torvalds 		break;
24221da177e4SLinus Torvalds 	case SYS_SENDTO:
24231da177e4SLinus Torvalds 		err = sys_sendto(a0, (void __user *)a1, a[2], a[3],
24241da177e4SLinus Torvalds 				 (struct sockaddr __user *)a[4], a[5]);
24251da177e4SLinus Torvalds 		break;
24261da177e4SLinus Torvalds 	case SYS_RECV:
24271da177e4SLinus Torvalds 		err = sys_recv(a0, (void __user *)a1, a[2], a[3]);
24281da177e4SLinus Torvalds 		break;
24291da177e4SLinus Torvalds 	case SYS_RECVFROM:
24301da177e4SLinus Torvalds 		err = sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
243189bddce5SStephen Hemminger 				   (struct sockaddr __user *)a[4],
243289bddce5SStephen Hemminger 				   (int __user *)a[5]);
24331da177e4SLinus Torvalds 		break;
24341da177e4SLinus Torvalds 	case SYS_SHUTDOWN:
24351da177e4SLinus Torvalds 		err = sys_shutdown(a0, a1);
24361da177e4SLinus Torvalds 		break;
24371da177e4SLinus Torvalds 	case SYS_SETSOCKOPT:
24381da177e4SLinus Torvalds 		err = sys_setsockopt(a0, a1, a[2], (char __user *)a[3], a[4]);
24391da177e4SLinus Torvalds 		break;
24401da177e4SLinus Torvalds 	case SYS_GETSOCKOPT:
244189bddce5SStephen Hemminger 		err =
244289bddce5SStephen Hemminger 		    sys_getsockopt(a0, a1, a[2], (char __user *)a[3],
244389bddce5SStephen Hemminger 				   (int __user *)a[4]);
24441da177e4SLinus Torvalds 		break;
24451da177e4SLinus Torvalds 	case SYS_SENDMSG:
24461da177e4SLinus Torvalds 		err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]);
24471da177e4SLinus Torvalds 		break;
2448228e548eSAnton Blanchard 	case SYS_SENDMMSG:
2449228e548eSAnton Blanchard 		err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]);
2450228e548eSAnton Blanchard 		break;
24511da177e4SLinus Torvalds 	case SYS_RECVMSG:
24521da177e4SLinus Torvalds 		err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]);
24531da177e4SLinus Torvalds 		break;
2454a2e27255SArnaldo Carvalho de Melo 	case SYS_RECVMMSG:
2455a2e27255SArnaldo Carvalho de Melo 		err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3],
2456a2e27255SArnaldo Carvalho de Melo 				   (struct timespec __user *)a[4]);
2457a2e27255SArnaldo Carvalho de Melo 		break;
2458de11defeSUlrich Drepper 	case SYS_ACCEPT4:
2459de11defeSUlrich Drepper 		err = sys_accept4(a0, (struct sockaddr __user *)a1,
2460de11defeSUlrich Drepper 				  (int __user *)a[2], a[3]);
2461aaca0bdcSUlrich Drepper 		break;
24621da177e4SLinus Torvalds 	default:
24631da177e4SLinus Torvalds 		err = -EINVAL;
24641da177e4SLinus Torvalds 		break;
24651da177e4SLinus Torvalds 	}
24661da177e4SLinus Torvalds 	return err;
24671da177e4SLinus Torvalds }
24681da177e4SLinus Torvalds 
24691da177e4SLinus Torvalds #endif				/* __ARCH_WANT_SYS_SOCKETCALL */
24701da177e4SLinus Torvalds 
247155737fdaSStephen Hemminger /**
247255737fdaSStephen Hemminger  *	sock_register - add a socket protocol handler
247355737fdaSStephen Hemminger  *	@ops: description of protocol
247455737fdaSStephen Hemminger  *
24751da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
24761da177e4SLinus Torvalds  *	advertise its address family, and have it linked into the
247755737fdaSStephen Hemminger  *	socket interface. The value ops->family coresponds to the
247855737fdaSStephen Hemminger  *	socket system call protocol family.
24791da177e4SLinus Torvalds  */
2480f0fd27d4SStephen Hemminger int sock_register(const struct net_proto_family *ops)
24811da177e4SLinus Torvalds {
24821da177e4SLinus Torvalds 	int err;
24831da177e4SLinus Torvalds 
24841da177e4SLinus Torvalds 	if (ops->family >= NPROTO) {
248589bddce5SStephen Hemminger 		printk(KERN_CRIT "protocol %d >= NPROTO(%d)\n", ops->family,
248689bddce5SStephen Hemminger 		       NPROTO);
24871da177e4SLinus Torvalds 		return -ENOBUFS;
24881da177e4SLinus Torvalds 	}
248955737fdaSStephen Hemminger 
249055737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2491190683a9SEric Dumazet 	if (rcu_dereference_protected(net_families[ops->family],
2492190683a9SEric Dumazet 				      lockdep_is_held(&net_family_lock)))
24931da177e4SLinus Torvalds 		err = -EEXIST;
249455737fdaSStephen Hemminger 	else {
2495cf778b00SEric Dumazet 		rcu_assign_pointer(net_families[ops->family], ops);
24961da177e4SLinus Torvalds 		err = 0;
24971da177e4SLinus Torvalds 	}
249855737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
249955737fdaSStephen Hemminger 
250089bddce5SStephen Hemminger 	printk(KERN_INFO "NET: Registered protocol family %d\n", ops->family);
25011da177e4SLinus Torvalds 	return err;
25021da177e4SLinus Torvalds }
2503c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_register);
25041da177e4SLinus Torvalds 
250555737fdaSStephen Hemminger /**
250655737fdaSStephen Hemminger  *	sock_unregister - remove a protocol handler
250755737fdaSStephen Hemminger  *	@family: protocol family to remove
250855737fdaSStephen Hemminger  *
25091da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
25101da177e4SLinus Torvalds  *	remove its address family, and have it unlinked from the
251155737fdaSStephen Hemminger  *	new socket creation.
251255737fdaSStephen Hemminger  *
251355737fdaSStephen Hemminger  *	If protocol handler is a module, then it can use module reference
251455737fdaSStephen Hemminger  *	counts to protect against new references. If protocol handler is not
251555737fdaSStephen Hemminger  *	a module then it needs to provide its own protection in
251655737fdaSStephen Hemminger  *	the ops->create routine.
25171da177e4SLinus Torvalds  */
2518f0fd27d4SStephen Hemminger void sock_unregister(int family)
25191da177e4SLinus Torvalds {
2520f0fd27d4SStephen Hemminger 	BUG_ON(family < 0 || family >= NPROTO);
25211da177e4SLinus Torvalds 
252255737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2523a9b3cd7fSStephen Hemminger 	RCU_INIT_POINTER(net_families[family], NULL);
252455737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
252555737fdaSStephen Hemminger 
252655737fdaSStephen Hemminger 	synchronize_rcu();
252755737fdaSStephen Hemminger 
252889bddce5SStephen Hemminger 	printk(KERN_INFO "NET: Unregistered protocol family %d\n", family);
25291da177e4SLinus Torvalds }
2530c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_unregister);
25311da177e4SLinus Torvalds 
253277d76ea3SAndi Kleen static int __init sock_init(void)
25331da177e4SLinus Torvalds {
2534b3e19d92SNick Piggin 	int err;
2535b3e19d92SNick Piggin 
25361da177e4SLinus Torvalds 	/*
25371da177e4SLinus Torvalds 	 *      Initialize sock SLAB cache.
25381da177e4SLinus Torvalds 	 */
25391da177e4SLinus Torvalds 
25401da177e4SLinus Torvalds 	sk_init();
25411da177e4SLinus Torvalds 
25421da177e4SLinus Torvalds 	/*
25431da177e4SLinus Torvalds 	 *      Initialize skbuff SLAB cache
25441da177e4SLinus Torvalds 	 */
25451da177e4SLinus Torvalds 	skb_init();
25461da177e4SLinus Torvalds 
25471da177e4SLinus Torvalds 	/*
25481da177e4SLinus Torvalds 	 *      Initialize the protocols module.
25491da177e4SLinus Torvalds 	 */
25501da177e4SLinus Torvalds 
25511da177e4SLinus Torvalds 	init_inodecache();
2552b3e19d92SNick Piggin 
2553b3e19d92SNick Piggin 	err = register_filesystem(&sock_fs_type);
2554b3e19d92SNick Piggin 	if (err)
2555b3e19d92SNick Piggin 		goto out_fs;
25561da177e4SLinus Torvalds 	sock_mnt = kern_mount(&sock_fs_type);
2557b3e19d92SNick Piggin 	if (IS_ERR(sock_mnt)) {
2558b3e19d92SNick Piggin 		err = PTR_ERR(sock_mnt);
2559b3e19d92SNick Piggin 		goto out_mount;
2560b3e19d92SNick Piggin 	}
256177d76ea3SAndi Kleen 
256277d76ea3SAndi Kleen 	/* The real protocol initialization is performed in later initcalls.
25631da177e4SLinus Torvalds 	 */
25641da177e4SLinus Torvalds 
25651da177e4SLinus Torvalds #ifdef CONFIG_NETFILTER
25661da177e4SLinus Torvalds 	netfilter_init();
25671da177e4SLinus Torvalds #endif
2568cbeb321aSDavid S. Miller 
2569c1f19b51SRichard Cochran #ifdef CONFIG_NETWORK_PHY_TIMESTAMPING
2570c1f19b51SRichard Cochran 	skb_timestamping_init();
2571c1f19b51SRichard Cochran #endif
2572c1f19b51SRichard Cochran 
2573b3e19d92SNick Piggin out:
2574b3e19d92SNick Piggin 	return err;
2575b3e19d92SNick Piggin 
2576b3e19d92SNick Piggin out_mount:
2577b3e19d92SNick Piggin 	unregister_filesystem(&sock_fs_type);
2578b3e19d92SNick Piggin out_fs:
2579b3e19d92SNick Piggin 	goto out;
25801da177e4SLinus Torvalds }
25811da177e4SLinus Torvalds 
258277d76ea3SAndi Kleen core_initcall(sock_init);	/* early initcall */
258377d76ea3SAndi Kleen 
25841da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS
25851da177e4SLinus Torvalds void socket_seq_show(struct seq_file *seq)
25861da177e4SLinus Torvalds {
25871da177e4SLinus Torvalds 	int cpu;
25881da177e4SLinus Torvalds 	int counter = 0;
25891da177e4SLinus Torvalds 
25906f912042SKAMEZAWA Hiroyuki 	for_each_possible_cpu(cpu)
25911da177e4SLinus Torvalds 	    counter += per_cpu(sockets_in_use, cpu);
25921da177e4SLinus Torvalds 
25931da177e4SLinus Torvalds 	/* It can be negative, by the way. 8) */
25941da177e4SLinus Torvalds 	if (counter < 0)
25951da177e4SLinus Torvalds 		counter = 0;
25961da177e4SLinus Torvalds 
25971da177e4SLinus Torvalds 	seq_printf(seq, "sockets: used %d\n", counter);
25981da177e4SLinus Torvalds }
25991da177e4SLinus Torvalds #endif				/* CONFIG_PROC_FS */
26001da177e4SLinus Torvalds 
260189bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
26026b96018bSArnd Bergmann static int do_siocgstamp(struct net *net, struct socket *sock,
2603644595f8SH. Peter Anvin 			 unsigned int cmd, void __user *up)
26047a229387SArnd Bergmann {
26057a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
26067a229387SArnd Bergmann 	struct timeval ktv;
26077a229387SArnd Bergmann 	int err;
26087a229387SArnd Bergmann 
26097a229387SArnd Bergmann 	set_fs(KERNEL_DS);
26106b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv);
26117a229387SArnd Bergmann 	set_fs(old_fs);
2612644595f8SH. Peter Anvin 	if (!err)
2613644595f8SH. Peter Anvin 		err = compat_put_timeval(up, &ktv);
2614644595f8SH. Peter Anvin 
26157a229387SArnd Bergmann 	return err;
26167a229387SArnd Bergmann }
26177a229387SArnd Bergmann 
26186b96018bSArnd Bergmann static int do_siocgstampns(struct net *net, struct socket *sock,
2619644595f8SH. Peter Anvin 			   unsigned int cmd, void __user *up)
26207a229387SArnd Bergmann {
26217a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
26227a229387SArnd Bergmann 	struct timespec kts;
26237a229387SArnd Bergmann 	int err;
26247a229387SArnd Bergmann 
26257a229387SArnd Bergmann 	set_fs(KERNEL_DS);
26266b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts);
26277a229387SArnd Bergmann 	set_fs(old_fs);
2628644595f8SH. Peter Anvin 	if (!err)
2629644595f8SH. Peter Anvin 		err = compat_put_timespec(up, &kts);
2630644595f8SH. Peter Anvin 
26317a229387SArnd Bergmann 	return err;
26327a229387SArnd Bergmann }
26337a229387SArnd Bergmann 
26346b96018bSArnd Bergmann static int dev_ifname32(struct net *net, struct compat_ifreq __user *uifr32)
26357a229387SArnd Bergmann {
26367a229387SArnd Bergmann 	struct ifreq __user *uifr;
26377a229387SArnd Bergmann 	int err;
26387a229387SArnd Bergmann 
26397a229387SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(struct ifreq));
26406b96018bSArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
26417a229387SArnd Bergmann 		return -EFAULT;
26427a229387SArnd Bergmann 
26436b96018bSArnd Bergmann 	err = dev_ioctl(net, SIOCGIFNAME, uifr);
26447a229387SArnd Bergmann 	if (err)
26457a229387SArnd Bergmann 		return err;
26467a229387SArnd Bergmann 
26476b96018bSArnd Bergmann 	if (copy_in_user(uifr32, uifr, sizeof(struct compat_ifreq)))
26487a229387SArnd Bergmann 		return -EFAULT;
26497a229387SArnd Bergmann 
26507a229387SArnd Bergmann 	return 0;
26517a229387SArnd Bergmann }
26527a229387SArnd Bergmann 
26536b96018bSArnd Bergmann static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32)
26547a229387SArnd Bergmann {
26556b96018bSArnd Bergmann 	struct compat_ifconf ifc32;
26567a229387SArnd Bergmann 	struct ifconf ifc;
26577a229387SArnd Bergmann 	struct ifconf __user *uifc;
26586b96018bSArnd Bergmann 	struct compat_ifreq __user *ifr32;
26597a229387SArnd Bergmann 	struct ifreq __user *ifr;
26607a229387SArnd Bergmann 	unsigned int i, j;
26617a229387SArnd Bergmann 	int err;
26627a229387SArnd Bergmann 
26636b96018bSArnd Bergmann 	if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf)))
26647a229387SArnd Bergmann 		return -EFAULT;
26657a229387SArnd Bergmann 
26667a229387SArnd Bergmann 	if (ifc32.ifcbuf == 0) {
26677a229387SArnd Bergmann 		ifc32.ifc_len = 0;
26687a229387SArnd Bergmann 		ifc.ifc_len = 0;
26697a229387SArnd Bergmann 		ifc.ifc_req = NULL;
26707a229387SArnd Bergmann 		uifc = compat_alloc_user_space(sizeof(struct ifconf));
26717a229387SArnd Bergmann 	} else {
26726b96018bSArnd Bergmann 		size_t len = ((ifc32.ifc_len / sizeof(struct compat_ifreq)) + 1) *
26737a229387SArnd Bergmann 			sizeof(struct ifreq);
26747a229387SArnd Bergmann 		uifc = compat_alloc_user_space(sizeof(struct ifconf) + len);
26757a229387SArnd Bergmann 		ifc.ifc_len = len;
26767a229387SArnd Bergmann 		ifr = ifc.ifc_req = (void __user *)(uifc + 1);
26777a229387SArnd Bergmann 		ifr32 = compat_ptr(ifc32.ifcbuf);
26786b96018bSArnd Bergmann 		for (i = 0; i < ifc32.ifc_len; i += sizeof(struct compat_ifreq)) {
26796b96018bSArnd Bergmann 			if (copy_in_user(ifr, ifr32, sizeof(struct compat_ifreq)))
26807a229387SArnd Bergmann 				return -EFAULT;
26817a229387SArnd Bergmann 			ifr++;
26827a229387SArnd Bergmann 			ifr32++;
26837a229387SArnd Bergmann 		}
26847a229387SArnd Bergmann 	}
26857a229387SArnd Bergmann 	if (copy_to_user(uifc, &ifc, sizeof(struct ifconf)))
26867a229387SArnd Bergmann 		return -EFAULT;
26877a229387SArnd Bergmann 
26886b96018bSArnd Bergmann 	err = dev_ioctl(net, SIOCGIFCONF, uifc);
26897a229387SArnd Bergmann 	if (err)
26907a229387SArnd Bergmann 		return err;
26917a229387SArnd Bergmann 
26927a229387SArnd Bergmann 	if (copy_from_user(&ifc, uifc, sizeof(struct ifconf)))
26937a229387SArnd Bergmann 		return -EFAULT;
26947a229387SArnd Bergmann 
26957a229387SArnd Bergmann 	ifr = ifc.ifc_req;
26967a229387SArnd Bergmann 	ifr32 = compat_ptr(ifc32.ifcbuf);
26977a229387SArnd Bergmann 	for (i = 0, j = 0;
26986b96018bSArnd Bergmann 	     i + sizeof(struct compat_ifreq) <= ifc32.ifc_len && j < ifc.ifc_len;
26996b96018bSArnd Bergmann 	     i += sizeof(struct compat_ifreq), j += sizeof(struct ifreq)) {
27006b96018bSArnd Bergmann 		if (copy_in_user(ifr32, ifr, sizeof(struct compat_ifreq)))
27017a229387SArnd Bergmann 			return -EFAULT;
27027a229387SArnd Bergmann 		ifr32++;
27037a229387SArnd Bergmann 		ifr++;
27047a229387SArnd Bergmann 	}
27057a229387SArnd Bergmann 
27067a229387SArnd Bergmann 	if (ifc32.ifcbuf == 0) {
27077a229387SArnd Bergmann 		/* Translate from 64-bit structure multiple to
27087a229387SArnd Bergmann 		 * a 32-bit one.
27097a229387SArnd Bergmann 		 */
27107a229387SArnd Bergmann 		i = ifc.ifc_len;
27116b96018bSArnd Bergmann 		i = ((i / sizeof(struct ifreq)) * sizeof(struct compat_ifreq));
27127a229387SArnd Bergmann 		ifc32.ifc_len = i;
27137a229387SArnd Bergmann 	} else {
27147a229387SArnd Bergmann 		ifc32.ifc_len = i;
27157a229387SArnd Bergmann 	}
27166b96018bSArnd Bergmann 	if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf)))
27177a229387SArnd Bergmann 		return -EFAULT;
27187a229387SArnd Bergmann 
27197a229387SArnd Bergmann 	return 0;
27207a229387SArnd Bergmann }
27217a229387SArnd Bergmann 
27226b96018bSArnd Bergmann static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
27237a229387SArnd Bergmann {
27243a7da39dSBen Hutchings 	struct compat_ethtool_rxnfc __user *compat_rxnfc;
27253a7da39dSBen Hutchings 	bool convert_in = false, convert_out = false;
27263a7da39dSBen Hutchings 	size_t buf_size = ALIGN(sizeof(struct ifreq), 8);
27273a7da39dSBen Hutchings 	struct ethtool_rxnfc __user *rxnfc;
27287a229387SArnd Bergmann 	struct ifreq __user *ifr;
27293a7da39dSBen Hutchings 	u32 rule_cnt = 0, actual_rule_cnt;
27303a7da39dSBen Hutchings 	u32 ethcmd;
27317a229387SArnd Bergmann 	u32 data;
27323a7da39dSBen Hutchings 	int ret;
27337a229387SArnd Bergmann 
27347a229387SArnd Bergmann 	if (get_user(data, &ifr32->ifr_ifru.ifru_data))
27357a229387SArnd Bergmann 		return -EFAULT;
27367a229387SArnd Bergmann 
27373a7da39dSBen Hutchings 	compat_rxnfc = compat_ptr(data);
27383a7da39dSBen Hutchings 
27393a7da39dSBen Hutchings 	if (get_user(ethcmd, &compat_rxnfc->cmd))
27407a229387SArnd Bergmann 		return -EFAULT;
27417a229387SArnd Bergmann 
27423a7da39dSBen Hutchings 	/* Most ethtool structures are defined without padding.
27433a7da39dSBen Hutchings 	 * Unfortunately struct ethtool_rxnfc is an exception.
27443a7da39dSBen Hutchings 	 */
27453a7da39dSBen Hutchings 	switch (ethcmd) {
27463a7da39dSBen Hutchings 	default:
27473a7da39dSBen Hutchings 		break;
27483a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLALL:
27493a7da39dSBen Hutchings 		/* Buffer size is variable */
27503a7da39dSBen Hutchings 		if (get_user(rule_cnt, &compat_rxnfc->rule_cnt))
27513a7da39dSBen Hutchings 			return -EFAULT;
27523a7da39dSBen Hutchings 		if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32))
27533a7da39dSBen Hutchings 			return -ENOMEM;
27543a7da39dSBen Hutchings 		buf_size += rule_cnt * sizeof(u32);
27553a7da39dSBen Hutchings 		/* fall through */
27563a7da39dSBen Hutchings 	case ETHTOOL_GRXRINGS:
27573a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLCNT:
27583a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRULE:
275955664f32SBen Hutchings 	case ETHTOOL_SRXCLSRLINS:
27603a7da39dSBen Hutchings 		convert_out = true;
27613a7da39dSBen Hutchings 		/* fall through */
27623a7da39dSBen Hutchings 	case ETHTOOL_SRXCLSRLDEL:
27633a7da39dSBen Hutchings 		buf_size += sizeof(struct ethtool_rxnfc);
27643a7da39dSBen Hutchings 		convert_in = true;
27653a7da39dSBen Hutchings 		break;
27663a7da39dSBen Hutchings 	}
27673a7da39dSBen Hutchings 
27683a7da39dSBen Hutchings 	ifr = compat_alloc_user_space(buf_size);
27693a7da39dSBen Hutchings 	rxnfc = (void *)ifr + ALIGN(sizeof(struct ifreq), 8);
27703a7da39dSBen Hutchings 
27713a7da39dSBen Hutchings 	if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
27723a7da39dSBen Hutchings 		return -EFAULT;
27733a7da39dSBen Hutchings 
27743a7da39dSBen Hutchings 	if (put_user(convert_in ? rxnfc : compat_ptr(data),
27753a7da39dSBen Hutchings 		     &ifr->ifr_ifru.ifru_data))
27763a7da39dSBen Hutchings 		return -EFAULT;
27773a7da39dSBen Hutchings 
27783a7da39dSBen Hutchings 	if (convert_in) {
2779127fe533SAlexander Duyck 		/* We expect there to be holes between fs.m_ext and
27803a7da39dSBen Hutchings 		 * fs.ring_cookie and at the end of fs, but nowhere else.
27813a7da39dSBen Hutchings 		 */
2782127fe533SAlexander Duyck 		BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_ext) +
2783127fe533SAlexander Duyck 			     sizeof(compat_rxnfc->fs.m_ext) !=
2784127fe533SAlexander Duyck 			     offsetof(struct ethtool_rxnfc, fs.m_ext) +
2785127fe533SAlexander Duyck 			     sizeof(rxnfc->fs.m_ext));
27863a7da39dSBen Hutchings 		BUILD_BUG_ON(
27873a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.location) -
27883a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) !=
27893a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.location) -
27903a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.ring_cookie));
27913a7da39dSBen Hutchings 
27923a7da39dSBen Hutchings 		if (copy_in_user(rxnfc, compat_rxnfc,
2793127fe533SAlexander Duyck 				 (void *)(&rxnfc->fs.m_ext + 1) -
27943a7da39dSBen Hutchings 				 (void *)rxnfc) ||
27953a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->fs.ring_cookie,
27963a7da39dSBen Hutchings 				 &compat_rxnfc->fs.ring_cookie,
27973a7da39dSBen Hutchings 				 (void *)(&rxnfc->fs.location + 1) -
27983a7da39dSBen Hutchings 				 (void *)&rxnfc->fs.ring_cookie) ||
27993a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt,
28003a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
28013a7da39dSBen Hutchings 			return -EFAULT;
28023a7da39dSBen Hutchings 	}
28033a7da39dSBen Hutchings 
28043a7da39dSBen Hutchings 	ret = dev_ioctl(net, SIOCETHTOOL, ifr);
28053a7da39dSBen Hutchings 	if (ret)
28063a7da39dSBen Hutchings 		return ret;
28073a7da39dSBen Hutchings 
28083a7da39dSBen Hutchings 	if (convert_out) {
28093a7da39dSBen Hutchings 		if (copy_in_user(compat_rxnfc, rxnfc,
2810127fe533SAlexander Duyck 				 (const void *)(&rxnfc->fs.m_ext + 1) -
28113a7da39dSBen Hutchings 				 (const void *)rxnfc) ||
28123a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->fs.ring_cookie,
28133a7da39dSBen Hutchings 				 &rxnfc->fs.ring_cookie,
28143a7da39dSBen Hutchings 				 (const void *)(&rxnfc->fs.location + 1) -
28153a7da39dSBen Hutchings 				 (const void *)&rxnfc->fs.ring_cookie) ||
28163a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt,
28173a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
28183a7da39dSBen Hutchings 			return -EFAULT;
28193a7da39dSBen Hutchings 
28203a7da39dSBen Hutchings 		if (ethcmd == ETHTOOL_GRXCLSRLALL) {
28213a7da39dSBen Hutchings 			/* As an optimisation, we only copy the actual
28223a7da39dSBen Hutchings 			 * number of rules that the underlying
28233a7da39dSBen Hutchings 			 * function returned.  Since Mallory might
28243a7da39dSBen Hutchings 			 * change the rule count in user memory, we
28253a7da39dSBen Hutchings 			 * check that it is less than the rule count
28263a7da39dSBen Hutchings 			 * originally given (as the user buffer size),
28273a7da39dSBen Hutchings 			 * which has been range-checked.
28283a7da39dSBen Hutchings 			 */
28293a7da39dSBen Hutchings 			if (get_user(actual_rule_cnt, &rxnfc->rule_cnt))
28303a7da39dSBen Hutchings 				return -EFAULT;
28313a7da39dSBen Hutchings 			if (actual_rule_cnt < rule_cnt)
28323a7da39dSBen Hutchings 				rule_cnt = actual_rule_cnt;
28333a7da39dSBen Hutchings 			if (copy_in_user(&compat_rxnfc->rule_locs[0],
28343a7da39dSBen Hutchings 					 &rxnfc->rule_locs[0],
28353a7da39dSBen Hutchings 					 rule_cnt * sizeof(u32)))
28363a7da39dSBen Hutchings 				return -EFAULT;
28373a7da39dSBen Hutchings 		}
28383a7da39dSBen Hutchings 	}
28393a7da39dSBen Hutchings 
28403a7da39dSBen Hutchings 	return 0;
28417a229387SArnd Bergmann }
28427a229387SArnd Bergmann 
28437a50a240SArnd Bergmann static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32)
28447a50a240SArnd Bergmann {
28457a50a240SArnd Bergmann 	void __user *uptr;
28467a50a240SArnd Bergmann 	compat_uptr_t uptr32;
28477a50a240SArnd Bergmann 	struct ifreq __user *uifr;
28487a50a240SArnd Bergmann 
28497a50a240SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
28507a50a240SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
28517a50a240SArnd Bergmann 		return -EFAULT;
28527a50a240SArnd Bergmann 
28537a50a240SArnd Bergmann 	if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu))
28547a50a240SArnd Bergmann 		return -EFAULT;
28557a50a240SArnd Bergmann 
28567a50a240SArnd Bergmann 	uptr = compat_ptr(uptr32);
28577a50a240SArnd Bergmann 
28587a50a240SArnd Bergmann 	if (put_user(uptr, &uifr->ifr_settings.ifs_ifsu.raw_hdlc))
28597a50a240SArnd Bergmann 		return -EFAULT;
28607a50a240SArnd Bergmann 
28617a50a240SArnd Bergmann 	return dev_ioctl(net, SIOCWANDEV, uifr);
28627a50a240SArnd Bergmann }
28637a50a240SArnd Bergmann 
28646b96018bSArnd Bergmann static int bond_ioctl(struct net *net, unsigned int cmd,
28656b96018bSArnd Bergmann 			 struct compat_ifreq __user *ifr32)
28667a229387SArnd Bergmann {
28677a229387SArnd Bergmann 	struct ifreq kifr;
28687a229387SArnd Bergmann 	struct ifreq __user *uifr;
28697a229387SArnd Bergmann 	mm_segment_t old_fs;
28707a229387SArnd Bergmann 	int err;
28717a229387SArnd Bergmann 	u32 data;
28727a229387SArnd Bergmann 	void __user *datap;
28737a229387SArnd Bergmann 
28747a229387SArnd Bergmann 	switch (cmd) {
28757a229387SArnd Bergmann 	case SIOCBONDENSLAVE:
28767a229387SArnd Bergmann 	case SIOCBONDRELEASE:
28777a229387SArnd Bergmann 	case SIOCBONDSETHWADDR:
28787a229387SArnd Bergmann 	case SIOCBONDCHANGEACTIVE:
28796b96018bSArnd Bergmann 		if (copy_from_user(&kifr, ifr32, sizeof(struct compat_ifreq)))
28807a229387SArnd Bergmann 			return -EFAULT;
28817a229387SArnd Bergmann 
28827a229387SArnd Bergmann 		old_fs = get_fs();
28837a229387SArnd Bergmann 		set_fs(KERNEL_DS);
2884c3f52ae6Sstephen hemminger 		err = dev_ioctl(net, cmd,
2885c3f52ae6Sstephen hemminger 				(struct ifreq __user __force *) &kifr);
28867a229387SArnd Bergmann 		set_fs(old_fs);
28877a229387SArnd Bergmann 
28887a229387SArnd Bergmann 		return err;
28897a229387SArnd Bergmann 	case SIOCBONDSLAVEINFOQUERY:
28907a229387SArnd Bergmann 	case SIOCBONDINFOQUERY:
28917a229387SArnd Bergmann 		uifr = compat_alloc_user_space(sizeof(*uifr));
28927a229387SArnd Bergmann 		if (copy_in_user(&uifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
28937a229387SArnd Bergmann 			return -EFAULT;
28947a229387SArnd Bergmann 
28957a229387SArnd Bergmann 		if (get_user(data, &ifr32->ifr_ifru.ifru_data))
28967a229387SArnd Bergmann 			return -EFAULT;
28977a229387SArnd Bergmann 
28987a229387SArnd Bergmann 		datap = compat_ptr(data);
28997a229387SArnd Bergmann 		if (put_user(datap, &uifr->ifr_ifru.ifru_data))
29007a229387SArnd Bergmann 			return -EFAULT;
29017a229387SArnd Bergmann 
29026b96018bSArnd Bergmann 		return dev_ioctl(net, cmd, uifr);
29037a229387SArnd Bergmann 	default:
290407d106d0SLinus Torvalds 		return -ENOIOCTLCMD;
2905ccbd6a5aSJoe Perches 	}
29067a229387SArnd Bergmann }
29077a229387SArnd Bergmann 
29086b96018bSArnd Bergmann static int siocdevprivate_ioctl(struct net *net, unsigned int cmd,
29096b96018bSArnd Bergmann 				 struct compat_ifreq __user *u_ifreq32)
29107a229387SArnd Bergmann {
29117a229387SArnd Bergmann 	struct ifreq __user *u_ifreq64;
29127a229387SArnd Bergmann 	char tmp_buf[IFNAMSIZ];
29137a229387SArnd Bergmann 	void __user *data64;
29147a229387SArnd Bergmann 	u32 data32;
29157a229387SArnd Bergmann 
29167a229387SArnd Bergmann 	if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]),
29177a229387SArnd Bergmann 			   IFNAMSIZ))
29187a229387SArnd Bergmann 		return -EFAULT;
29197a229387SArnd Bergmann 	if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data))
29207a229387SArnd Bergmann 		return -EFAULT;
29217a229387SArnd Bergmann 	data64 = compat_ptr(data32);
29227a229387SArnd Bergmann 
29237a229387SArnd Bergmann 	u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
29247a229387SArnd Bergmann 
29257a229387SArnd Bergmann 	/* Don't check these user accesses, just let that get trapped
29267a229387SArnd Bergmann 	 * in the ioctl handler instead.
29277a229387SArnd Bergmann 	 */
29287a229387SArnd Bergmann 	if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0],
29297a229387SArnd Bergmann 			 IFNAMSIZ))
29307a229387SArnd Bergmann 		return -EFAULT;
29317a229387SArnd Bergmann 	if (__put_user(data64, &u_ifreq64->ifr_ifru.ifru_data))
29327a229387SArnd Bergmann 		return -EFAULT;
29337a229387SArnd Bergmann 
29346b96018bSArnd Bergmann 	return dev_ioctl(net, cmd, u_ifreq64);
29357a229387SArnd Bergmann }
29367a229387SArnd Bergmann 
29376b96018bSArnd Bergmann static int dev_ifsioc(struct net *net, struct socket *sock,
29386b96018bSArnd Bergmann 			 unsigned int cmd, struct compat_ifreq __user *uifr32)
29397a229387SArnd Bergmann {
2940a2116ed2SArnd Bergmann 	struct ifreq __user *uifr;
29417a229387SArnd Bergmann 	int err;
29427a229387SArnd Bergmann 
2943a2116ed2SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
2944a2116ed2SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(*uifr32)))
29457a229387SArnd Bergmann 		return -EFAULT;
2946a2116ed2SArnd Bergmann 
2947a2116ed2SArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr);
2948a2116ed2SArnd Bergmann 
29497a229387SArnd Bergmann 	if (!err) {
29507a229387SArnd Bergmann 		switch (cmd) {
29517a229387SArnd Bergmann 		case SIOCGIFFLAGS:
29527a229387SArnd Bergmann 		case SIOCGIFMETRIC:
29537a229387SArnd Bergmann 		case SIOCGIFMTU:
29547a229387SArnd Bergmann 		case SIOCGIFMEM:
29557a229387SArnd Bergmann 		case SIOCGIFHWADDR:
29567a229387SArnd Bergmann 		case SIOCGIFINDEX:
29577a229387SArnd Bergmann 		case SIOCGIFADDR:
29587a229387SArnd Bergmann 		case SIOCGIFBRDADDR:
29597a229387SArnd Bergmann 		case SIOCGIFDSTADDR:
29607a229387SArnd Bergmann 		case SIOCGIFNETMASK:
2961fab2532bSArnd Bergmann 		case SIOCGIFPFLAGS:
29627a229387SArnd Bergmann 		case SIOCGIFTXQLEN:
2963fab2532bSArnd Bergmann 		case SIOCGMIIPHY:
2964fab2532bSArnd Bergmann 		case SIOCGMIIREG:
2965a2116ed2SArnd Bergmann 			if (copy_in_user(uifr32, uifr, sizeof(*uifr32)))
2966a2116ed2SArnd Bergmann 				err = -EFAULT;
29677a229387SArnd Bergmann 			break;
2968a2116ed2SArnd Bergmann 		}
2969a2116ed2SArnd Bergmann 	}
2970a2116ed2SArnd Bergmann 	return err;
2971a2116ed2SArnd Bergmann }
2972a2116ed2SArnd Bergmann 
2973a2116ed2SArnd Bergmann static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
2974a2116ed2SArnd Bergmann 			struct compat_ifreq __user *uifr32)
2975a2116ed2SArnd Bergmann {
2976a2116ed2SArnd Bergmann 	struct ifreq ifr;
2977a2116ed2SArnd Bergmann 	struct compat_ifmap __user *uifmap32;
2978a2116ed2SArnd Bergmann 	mm_segment_t old_fs;
2979a2116ed2SArnd Bergmann 	int err;
2980a2116ed2SArnd Bergmann 
2981a2116ed2SArnd Bergmann 	uifmap32 = &uifr32->ifr_ifru.ifru_map;
2982a2116ed2SArnd Bergmann 	err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name));
2983a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
2984a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
2985a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
2986a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.irq, &uifmap32->irq);
2987a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.dma, &uifmap32->dma);
2988a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.port, &uifmap32->port);
2989a2116ed2SArnd Bergmann 	if (err)
2990a2116ed2SArnd Bergmann 		return -EFAULT;
2991a2116ed2SArnd Bergmann 
2992a2116ed2SArnd Bergmann 	old_fs = get_fs();
2993a2116ed2SArnd Bergmann 	set_fs(KERNEL_DS);
2994c3f52ae6Sstephen hemminger 	err = dev_ioctl(net, cmd, (void  __user __force *)&ifr);
2995a2116ed2SArnd Bergmann 	set_fs(old_fs);
2996a2116ed2SArnd Bergmann 
2997a2116ed2SArnd Bergmann 	if (cmd == SIOCGIFMAP && !err) {
29987a229387SArnd Bergmann 		err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name));
29997a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
30007a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
30017a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
30027a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.irq, &uifmap32->irq);
30037a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.dma, &uifmap32->dma);
30047a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.port, &uifmap32->port);
30057a229387SArnd Bergmann 		if (err)
30067a229387SArnd Bergmann 			err = -EFAULT;
30077a229387SArnd Bergmann 	}
30087a229387SArnd Bergmann 	return err;
30097a229387SArnd Bergmann }
30107a229387SArnd Bergmann 
3011a2116ed2SArnd Bergmann static int compat_siocshwtstamp(struct net *net, struct compat_ifreq __user *uifr32)
3012a2116ed2SArnd Bergmann {
3013a2116ed2SArnd Bergmann 	void __user *uptr;
3014a2116ed2SArnd Bergmann 	compat_uptr_t uptr32;
3015a2116ed2SArnd Bergmann 	struct ifreq __user *uifr;
3016a2116ed2SArnd Bergmann 
3017a2116ed2SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
3018a2116ed2SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
3019a2116ed2SArnd Bergmann 		return -EFAULT;
3020a2116ed2SArnd Bergmann 
3021a2116ed2SArnd Bergmann 	if (get_user(uptr32, &uifr32->ifr_data))
3022a2116ed2SArnd Bergmann 		return -EFAULT;
3023a2116ed2SArnd Bergmann 
3024a2116ed2SArnd Bergmann 	uptr = compat_ptr(uptr32);
3025a2116ed2SArnd Bergmann 
3026a2116ed2SArnd Bergmann 	if (put_user(uptr, &uifr->ifr_data))
3027a2116ed2SArnd Bergmann 		return -EFAULT;
3028a2116ed2SArnd Bergmann 
3029a2116ed2SArnd Bergmann 	return dev_ioctl(net, SIOCSHWTSTAMP, uifr);
3030a2116ed2SArnd Bergmann }
3031a2116ed2SArnd Bergmann 
30327a229387SArnd Bergmann struct rtentry32 {
30337a229387SArnd Bergmann 	u32		rt_pad1;
30347a229387SArnd Bergmann 	struct sockaddr rt_dst;         /* target address               */
30357a229387SArnd Bergmann 	struct sockaddr rt_gateway;     /* gateway addr (RTF_GATEWAY)   */
30367a229387SArnd Bergmann 	struct sockaddr rt_genmask;     /* target network mask (IP)     */
30377a229387SArnd Bergmann 	unsigned short	rt_flags;
30387a229387SArnd Bergmann 	short		rt_pad2;
30397a229387SArnd Bergmann 	u32		rt_pad3;
30407a229387SArnd Bergmann 	unsigned char	rt_tos;
30417a229387SArnd Bergmann 	unsigned char	rt_class;
30427a229387SArnd Bergmann 	short		rt_pad4;
30437a229387SArnd Bergmann 	short		rt_metric;      /* +1 for binary compatibility! */
30447a229387SArnd Bergmann 	/* char * */ u32 rt_dev;        /* forcing the device at add    */
30457a229387SArnd Bergmann 	u32		rt_mtu;         /* per route MTU/Window         */
30467a229387SArnd Bergmann 	u32		rt_window;      /* Window clamping              */
30477a229387SArnd Bergmann 	unsigned short  rt_irtt;        /* Initial RTT                  */
30487a229387SArnd Bergmann };
30497a229387SArnd Bergmann 
30507a229387SArnd Bergmann struct in6_rtmsg32 {
30517a229387SArnd Bergmann 	struct in6_addr		rtmsg_dst;
30527a229387SArnd Bergmann 	struct in6_addr		rtmsg_src;
30537a229387SArnd Bergmann 	struct in6_addr		rtmsg_gateway;
30547a229387SArnd Bergmann 	u32			rtmsg_type;
30557a229387SArnd Bergmann 	u16			rtmsg_dst_len;
30567a229387SArnd Bergmann 	u16			rtmsg_src_len;
30577a229387SArnd Bergmann 	u32			rtmsg_metric;
30587a229387SArnd Bergmann 	u32			rtmsg_info;
30597a229387SArnd Bergmann 	u32			rtmsg_flags;
30607a229387SArnd Bergmann 	s32			rtmsg_ifindex;
30617a229387SArnd Bergmann };
30627a229387SArnd Bergmann 
30636b96018bSArnd Bergmann static int routing_ioctl(struct net *net, struct socket *sock,
30646b96018bSArnd Bergmann 			 unsigned int cmd, void __user *argp)
30657a229387SArnd Bergmann {
30667a229387SArnd Bergmann 	int ret;
30677a229387SArnd Bergmann 	void *r = NULL;
30687a229387SArnd Bergmann 	struct in6_rtmsg r6;
30697a229387SArnd Bergmann 	struct rtentry r4;
30707a229387SArnd Bergmann 	char devname[16];
30717a229387SArnd Bergmann 	u32 rtdev;
30727a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
30737a229387SArnd Bergmann 
30746b96018bSArnd Bergmann 	if (sock && sock->sk && sock->sk->sk_family == AF_INET6) { /* ipv6 */
30756b96018bSArnd Bergmann 		struct in6_rtmsg32 __user *ur6 = argp;
30767a229387SArnd Bergmann 		ret = copy_from_user(&r6.rtmsg_dst, &(ur6->rtmsg_dst),
30777a229387SArnd Bergmann 			3 * sizeof(struct in6_addr));
30787a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_type, &(ur6->rtmsg_type));
30797a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len));
30807a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_src_len, &(ur6->rtmsg_src_len));
30817a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_metric, &(ur6->rtmsg_metric));
30827a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_info, &(ur6->rtmsg_info));
30837a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_flags, &(ur6->rtmsg_flags));
30847a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex));
30857a229387SArnd Bergmann 
30867a229387SArnd Bergmann 		r = (void *) &r6;
30877a229387SArnd Bergmann 	} else { /* ipv4 */
30886b96018bSArnd Bergmann 		struct rtentry32 __user *ur4 = argp;
30897a229387SArnd Bergmann 		ret = copy_from_user(&r4.rt_dst, &(ur4->rt_dst),
30907a229387SArnd Bergmann 					3 * sizeof(struct sockaddr));
30917a229387SArnd Bergmann 		ret |= __get_user(r4.rt_flags, &(ur4->rt_flags));
30927a229387SArnd Bergmann 		ret |= __get_user(r4.rt_metric, &(ur4->rt_metric));
30937a229387SArnd Bergmann 		ret |= __get_user(r4.rt_mtu, &(ur4->rt_mtu));
30947a229387SArnd Bergmann 		ret |= __get_user(r4.rt_window, &(ur4->rt_window));
30957a229387SArnd Bergmann 		ret |= __get_user(r4.rt_irtt, &(ur4->rt_irtt));
30967a229387SArnd Bergmann 		ret |= __get_user(rtdev, &(ur4->rt_dev));
30977a229387SArnd Bergmann 		if (rtdev) {
30987a229387SArnd Bergmann 			ret |= copy_from_user(devname, compat_ptr(rtdev), 15);
3099c3f52ae6Sstephen hemminger 			r4.rt_dev = (char __user __force *)devname;
3100c3f52ae6Sstephen hemminger 			devname[15] = 0;
31017a229387SArnd Bergmann 		} else
31027a229387SArnd Bergmann 			r4.rt_dev = NULL;
31037a229387SArnd Bergmann 
31047a229387SArnd Bergmann 		r = (void *) &r4;
31057a229387SArnd Bergmann 	}
31067a229387SArnd Bergmann 
31077a229387SArnd Bergmann 	if (ret) {
31087a229387SArnd Bergmann 		ret = -EFAULT;
31097a229387SArnd Bergmann 		goto out;
31107a229387SArnd Bergmann 	}
31117a229387SArnd Bergmann 
31127a229387SArnd Bergmann 	set_fs(KERNEL_DS);
31136b96018bSArnd Bergmann 	ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r);
31147a229387SArnd Bergmann 	set_fs(old_fs);
31157a229387SArnd Bergmann 
31167a229387SArnd Bergmann out:
31177a229387SArnd Bergmann 	return ret;
31187a229387SArnd Bergmann }
31197a229387SArnd Bergmann 
31207a229387SArnd Bergmann /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE
31217a229387SArnd Bergmann  * for some operations; this forces use of the newer bridge-utils that
312225985edcSLucas De Marchi  * use compatible ioctls
31237a229387SArnd Bergmann  */
31246b96018bSArnd Bergmann static int old_bridge_ioctl(compat_ulong_t __user *argp)
31257a229387SArnd Bergmann {
31266b96018bSArnd Bergmann 	compat_ulong_t tmp;
31277a229387SArnd Bergmann 
31286b96018bSArnd Bergmann 	if (get_user(tmp, argp))
31297a229387SArnd Bergmann 		return -EFAULT;
31307a229387SArnd Bergmann 	if (tmp == BRCTL_GET_VERSION)
31317a229387SArnd Bergmann 		return BRCTL_VERSION + 1;
31327a229387SArnd Bergmann 	return -EINVAL;
31337a229387SArnd Bergmann }
31347a229387SArnd Bergmann 
31356b96018bSArnd Bergmann static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
31366b96018bSArnd Bergmann 			 unsigned int cmd, unsigned long arg)
31376b96018bSArnd Bergmann {
31386b96018bSArnd Bergmann 	void __user *argp = compat_ptr(arg);
31396b96018bSArnd Bergmann 	struct sock *sk = sock->sk;
31406b96018bSArnd Bergmann 	struct net *net = sock_net(sk);
31417a229387SArnd Bergmann 
31426b96018bSArnd Bergmann 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
31436b96018bSArnd Bergmann 		return siocdevprivate_ioctl(net, cmd, argp);
31447a229387SArnd Bergmann 
31456b96018bSArnd Bergmann 	switch (cmd) {
31466b96018bSArnd Bergmann 	case SIOCSIFBR:
31476b96018bSArnd Bergmann 	case SIOCGIFBR:
31486b96018bSArnd Bergmann 		return old_bridge_ioctl(argp);
31496b96018bSArnd Bergmann 	case SIOCGIFNAME:
31506b96018bSArnd Bergmann 		return dev_ifname32(net, argp);
31516b96018bSArnd Bergmann 	case SIOCGIFCONF:
31526b96018bSArnd Bergmann 		return dev_ifconf(net, argp);
31536b96018bSArnd Bergmann 	case SIOCETHTOOL:
31546b96018bSArnd Bergmann 		return ethtool_ioctl(net, argp);
31557a50a240SArnd Bergmann 	case SIOCWANDEV:
31567a50a240SArnd Bergmann 		return compat_siocwandev(net, argp);
3157a2116ed2SArnd Bergmann 	case SIOCGIFMAP:
3158a2116ed2SArnd Bergmann 	case SIOCSIFMAP:
3159a2116ed2SArnd Bergmann 		return compat_sioc_ifmap(net, cmd, argp);
31606b96018bSArnd Bergmann 	case SIOCBONDENSLAVE:
31616b96018bSArnd Bergmann 	case SIOCBONDRELEASE:
31626b96018bSArnd Bergmann 	case SIOCBONDSETHWADDR:
31636b96018bSArnd Bergmann 	case SIOCBONDSLAVEINFOQUERY:
31646b96018bSArnd Bergmann 	case SIOCBONDINFOQUERY:
31656b96018bSArnd Bergmann 	case SIOCBONDCHANGEACTIVE:
31666b96018bSArnd Bergmann 		return bond_ioctl(net, cmd, argp);
31676b96018bSArnd Bergmann 	case SIOCADDRT:
31686b96018bSArnd Bergmann 	case SIOCDELRT:
31696b96018bSArnd Bergmann 		return routing_ioctl(net, sock, cmd, argp);
31706b96018bSArnd Bergmann 	case SIOCGSTAMP:
31716b96018bSArnd Bergmann 		return do_siocgstamp(net, sock, cmd, argp);
31726b96018bSArnd Bergmann 	case SIOCGSTAMPNS:
31736b96018bSArnd Bergmann 		return do_siocgstampns(net, sock, cmd, argp);
3174a2116ed2SArnd Bergmann 	case SIOCSHWTSTAMP:
3175a2116ed2SArnd Bergmann 		return compat_siocshwtstamp(net, argp);
31767a229387SArnd Bergmann 
31776b96018bSArnd Bergmann 	case FIOSETOWN:
31786b96018bSArnd Bergmann 	case SIOCSPGRP:
31796b96018bSArnd Bergmann 	case FIOGETOWN:
31806b96018bSArnd Bergmann 	case SIOCGPGRP:
31816b96018bSArnd Bergmann 	case SIOCBRADDBR:
31826b96018bSArnd Bergmann 	case SIOCBRDELBR:
31836b96018bSArnd Bergmann 	case SIOCGIFVLAN:
31846b96018bSArnd Bergmann 	case SIOCSIFVLAN:
31856b96018bSArnd Bergmann 	case SIOCADDDLCI:
31866b96018bSArnd Bergmann 	case SIOCDELDLCI:
31876b96018bSArnd Bergmann 		return sock_ioctl(file, cmd, arg);
31886b96018bSArnd Bergmann 
31896b96018bSArnd Bergmann 	case SIOCGIFFLAGS:
31906b96018bSArnd Bergmann 	case SIOCSIFFLAGS:
31916b96018bSArnd Bergmann 	case SIOCGIFMETRIC:
31926b96018bSArnd Bergmann 	case SIOCSIFMETRIC:
31936b96018bSArnd Bergmann 	case SIOCGIFMTU:
31946b96018bSArnd Bergmann 	case SIOCSIFMTU:
31956b96018bSArnd Bergmann 	case SIOCGIFMEM:
31966b96018bSArnd Bergmann 	case SIOCSIFMEM:
31976b96018bSArnd Bergmann 	case SIOCGIFHWADDR:
31986b96018bSArnd Bergmann 	case SIOCSIFHWADDR:
31996b96018bSArnd Bergmann 	case SIOCADDMULTI:
32006b96018bSArnd Bergmann 	case SIOCDELMULTI:
32016b96018bSArnd Bergmann 	case SIOCGIFINDEX:
32026b96018bSArnd Bergmann 	case SIOCGIFADDR:
32036b96018bSArnd Bergmann 	case SIOCSIFADDR:
32046b96018bSArnd Bergmann 	case SIOCSIFHWBROADCAST:
32056b96018bSArnd Bergmann 	case SIOCDIFADDR:
32066b96018bSArnd Bergmann 	case SIOCGIFBRDADDR:
32076b96018bSArnd Bergmann 	case SIOCSIFBRDADDR:
32086b96018bSArnd Bergmann 	case SIOCGIFDSTADDR:
32096b96018bSArnd Bergmann 	case SIOCSIFDSTADDR:
32106b96018bSArnd Bergmann 	case SIOCGIFNETMASK:
32116b96018bSArnd Bergmann 	case SIOCSIFNETMASK:
32126b96018bSArnd Bergmann 	case SIOCSIFPFLAGS:
32136b96018bSArnd Bergmann 	case SIOCGIFPFLAGS:
32146b96018bSArnd Bergmann 	case SIOCGIFTXQLEN:
32156b96018bSArnd Bergmann 	case SIOCSIFTXQLEN:
32166b96018bSArnd Bergmann 	case SIOCBRADDIF:
32176b96018bSArnd Bergmann 	case SIOCBRDELIF:
32189177efd3SArnd Bergmann 	case SIOCSIFNAME:
32199177efd3SArnd Bergmann 	case SIOCGMIIPHY:
32209177efd3SArnd Bergmann 	case SIOCGMIIREG:
32219177efd3SArnd Bergmann 	case SIOCSMIIREG:
32226b96018bSArnd Bergmann 		return dev_ifsioc(net, sock, cmd, argp);
32239177efd3SArnd Bergmann 
32246b96018bSArnd Bergmann 	case SIOCSARP:
32256b96018bSArnd Bergmann 	case SIOCGARP:
32266b96018bSArnd Bergmann 	case SIOCDARP:
32276b96018bSArnd Bergmann 	case SIOCATMARK:
32289177efd3SArnd Bergmann 		return sock_do_ioctl(net, sock, cmd, arg);
32299177efd3SArnd Bergmann 	}
32309177efd3SArnd Bergmann 
32316b96018bSArnd Bergmann 	return -ENOIOCTLCMD;
32326b96018bSArnd Bergmann }
32337a229387SArnd Bergmann 
323489bbfc95SShaun Pereira static long compat_sock_ioctl(struct file *file, unsigned cmd,
323589bbfc95SShaun Pereira 			      unsigned long arg)
323689bbfc95SShaun Pereira {
323789bbfc95SShaun Pereira 	struct socket *sock = file->private_data;
323889bbfc95SShaun Pereira 	int ret = -ENOIOCTLCMD;
323987de87d5SDavid S. Miller 	struct sock *sk;
324087de87d5SDavid S. Miller 	struct net *net;
324187de87d5SDavid S. Miller 
324287de87d5SDavid S. Miller 	sk = sock->sk;
324387de87d5SDavid S. Miller 	net = sock_net(sk);
324489bbfc95SShaun Pereira 
324589bbfc95SShaun Pereira 	if (sock->ops->compat_ioctl)
324689bbfc95SShaun Pereira 		ret = sock->ops->compat_ioctl(sock, cmd, arg);
324789bbfc95SShaun Pereira 
324887de87d5SDavid S. Miller 	if (ret == -ENOIOCTLCMD &&
324987de87d5SDavid S. Miller 	    (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST))
325087de87d5SDavid S. Miller 		ret = compat_wext_handle_ioctl(net, cmd, arg);
325187de87d5SDavid S. Miller 
32526b96018bSArnd Bergmann 	if (ret == -ENOIOCTLCMD)
32536b96018bSArnd Bergmann 		ret = compat_sock_ioctl_trans(file, sock, cmd, arg);
32546b96018bSArnd Bergmann 
325589bbfc95SShaun Pereira 	return ret;
325689bbfc95SShaun Pereira }
325789bbfc95SShaun Pereira #endif
325889bbfc95SShaun Pereira 
3259ac5a488eSSridhar Samudrala int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
3260ac5a488eSSridhar Samudrala {
3261ac5a488eSSridhar Samudrala 	return sock->ops->bind(sock, addr, addrlen);
3262ac5a488eSSridhar Samudrala }
3263c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_bind);
3264ac5a488eSSridhar Samudrala 
3265ac5a488eSSridhar Samudrala int kernel_listen(struct socket *sock, int backlog)
3266ac5a488eSSridhar Samudrala {
3267ac5a488eSSridhar Samudrala 	return sock->ops->listen(sock, backlog);
3268ac5a488eSSridhar Samudrala }
3269c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_listen);
3270ac5a488eSSridhar Samudrala 
3271ac5a488eSSridhar Samudrala int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
3272ac5a488eSSridhar Samudrala {
3273ac5a488eSSridhar Samudrala 	struct sock *sk = sock->sk;
3274ac5a488eSSridhar Samudrala 	int err;
3275ac5a488eSSridhar Samudrala 
3276ac5a488eSSridhar Samudrala 	err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
3277ac5a488eSSridhar Samudrala 			       newsock);
3278ac5a488eSSridhar Samudrala 	if (err < 0)
3279ac5a488eSSridhar Samudrala 		goto done;
3280ac5a488eSSridhar Samudrala 
3281ac5a488eSSridhar Samudrala 	err = sock->ops->accept(sock, *newsock, flags);
3282ac5a488eSSridhar Samudrala 	if (err < 0) {
3283ac5a488eSSridhar Samudrala 		sock_release(*newsock);
3284fa8705b0STony Battersby 		*newsock = NULL;
3285ac5a488eSSridhar Samudrala 		goto done;
3286ac5a488eSSridhar Samudrala 	}
3287ac5a488eSSridhar Samudrala 
3288ac5a488eSSridhar Samudrala 	(*newsock)->ops = sock->ops;
32891b08534eSWei Yongjun 	__module_get((*newsock)->ops->owner);
3290ac5a488eSSridhar Samudrala 
3291ac5a488eSSridhar Samudrala done:
3292ac5a488eSSridhar Samudrala 	return err;
3293ac5a488eSSridhar Samudrala }
3294c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_accept);
3295ac5a488eSSridhar Samudrala 
3296ac5a488eSSridhar Samudrala int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
3297ac5a488eSSridhar Samudrala 		   int flags)
3298ac5a488eSSridhar Samudrala {
3299ac5a488eSSridhar Samudrala 	return sock->ops->connect(sock, addr, addrlen, flags);
3300ac5a488eSSridhar Samudrala }
3301c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_connect);
3302ac5a488eSSridhar Samudrala 
3303ac5a488eSSridhar Samudrala int kernel_getsockname(struct socket *sock, struct sockaddr *addr,
3304ac5a488eSSridhar Samudrala 			 int *addrlen)
3305ac5a488eSSridhar Samudrala {
3306ac5a488eSSridhar Samudrala 	return sock->ops->getname(sock, addr, addrlen, 0);
3307ac5a488eSSridhar Samudrala }
3308c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockname);
3309ac5a488eSSridhar Samudrala 
3310ac5a488eSSridhar Samudrala int kernel_getpeername(struct socket *sock, struct sockaddr *addr,
3311ac5a488eSSridhar Samudrala 			 int *addrlen)
3312ac5a488eSSridhar Samudrala {
3313ac5a488eSSridhar Samudrala 	return sock->ops->getname(sock, addr, addrlen, 1);
3314ac5a488eSSridhar Samudrala }
3315c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getpeername);
3316ac5a488eSSridhar Samudrala 
3317ac5a488eSSridhar Samudrala int kernel_getsockopt(struct socket *sock, int level, int optname,
3318ac5a488eSSridhar Samudrala 			char *optval, int *optlen)
3319ac5a488eSSridhar Samudrala {
3320ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3321fb8621bbSNamhyung Kim 	char __user *uoptval;
3322fb8621bbSNamhyung Kim 	int __user *uoptlen;
3323ac5a488eSSridhar Samudrala 	int err;
3324ac5a488eSSridhar Samudrala 
3325fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3326fb8621bbSNamhyung Kim 	uoptlen = (int __user __force *) optlen;
3327fb8621bbSNamhyung Kim 
3328ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3329ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3330fb8621bbSNamhyung Kim 		err = sock_getsockopt(sock, level, optname, uoptval, uoptlen);
3331ac5a488eSSridhar Samudrala 	else
3332fb8621bbSNamhyung Kim 		err = sock->ops->getsockopt(sock, level, optname, uoptval,
3333fb8621bbSNamhyung Kim 					    uoptlen);
3334ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3335ac5a488eSSridhar Samudrala 	return err;
3336ac5a488eSSridhar Samudrala }
3337c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockopt);
3338ac5a488eSSridhar Samudrala 
3339ac5a488eSSridhar Samudrala int kernel_setsockopt(struct socket *sock, int level, int optname,
3340b7058842SDavid S. Miller 			char *optval, unsigned int optlen)
3341ac5a488eSSridhar Samudrala {
3342ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3343fb8621bbSNamhyung Kim 	char __user *uoptval;
3344ac5a488eSSridhar Samudrala 	int err;
3345ac5a488eSSridhar Samudrala 
3346fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3347fb8621bbSNamhyung Kim 
3348ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3349ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3350fb8621bbSNamhyung Kim 		err = sock_setsockopt(sock, level, optname, uoptval, optlen);
3351ac5a488eSSridhar Samudrala 	else
3352fb8621bbSNamhyung Kim 		err = sock->ops->setsockopt(sock, level, optname, uoptval,
3353ac5a488eSSridhar Samudrala 					    optlen);
3354ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3355ac5a488eSSridhar Samudrala 	return err;
3356ac5a488eSSridhar Samudrala }
3357c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_setsockopt);
3358ac5a488eSSridhar Samudrala 
3359ac5a488eSSridhar Samudrala int kernel_sendpage(struct socket *sock, struct page *page, int offset,
3360ac5a488eSSridhar Samudrala 		    size_t size, int flags)
3361ac5a488eSSridhar Samudrala {
3362f8451725SHerbert Xu 	sock_update_classid(sock->sk);
3363f8451725SHerbert Xu 
3364ac5a488eSSridhar Samudrala 	if (sock->ops->sendpage)
3365ac5a488eSSridhar Samudrala 		return sock->ops->sendpage(sock, page, offset, size, flags);
3366ac5a488eSSridhar Samudrala 
3367ac5a488eSSridhar Samudrala 	return sock_no_sendpage(sock, page, offset, size, flags);
3368ac5a488eSSridhar Samudrala }
3369c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendpage);
3370ac5a488eSSridhar Samudrala 
3371ac5a488eSSridhar Samudrala int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg)
3372ac5a488eSSridhar Samudrala {
3373ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3374ac5a488eSSridhar Samudrala 	int err;
3375ac5a488eSSridhar Samudrala 
3376ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3377ac5a488eSSridhar Samudrala 	err = sock->ops->ioctl(sock, cmd, arg);
3378ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3379ac5a488eSSridhar Samudrala 
3380ac5a488eSSridhar Samudrala 	return err;
3381ac5a488eSSridhar Samudrala }
3382c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sock_ioctl);
3383ac5a488eSSridhar Samudrala 
338491cf45f0STrond Myklebust int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
338591cf45f0STrond Myklebust {
338691cf45f0STrond Myklebust 	return sock->ops->shutdown(sock, how);
338791cf45f0STrond Myklebust }
338891cf45f0STrond Myklebust EXPORT_SYMBOL(kernel_sock_shutdown);
3389