xref: /openbmc/linux/net/socket.c (revision ed6fe9d6)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * NET		An implementation of the SOCKET network access protocol.
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Version:	@(#)socket.c	1.1.93	18/02/95
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * Authors:	Orest Zborowski, <obz@Kodak.COM>
702c30a84SJesper Juhl  *		Ross Biro
81da177e4SLinus Torvalds  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
91da177e4SLinus Torvalds  *
101da177e4SLinus Torvalds  * Fixes:
111da177e4SLinus Torvalds  *		Anonymous	:	NOTSOCK/BADF cleanup. Error fix in
121da177e4SLinus Torvalds  *					shutdown()
131da177e4SLinus Torvalds  *		Alan Cox	:	verify_area() fixes
141da177e4SLinus Torvalds  *		Alan Cox	:	Removed DDI
151da177e4SLinus Torvalds  *		Jonathan Kamens	:	SOCK_DGRAM reconnect bug
161da177e4SLinus Torvalds  *		Alan Cox	:	Moved a load of checks to the very
171da177e4SLinus Torvalds  *					top level.
181da177e4SLinus Torvalds  *		Alan Cox	:	Move address structures to/from user
191da177e4SLinus Torvalds  *					mode above the protocol layers.
201da177e4SLinus Torvalds  *		Rob Janssen	:	Allow 0 length sends.
211da177e4SLinus Torvalds  *		Alan Cox	:	Asynchronous I/O support (cribbed from the
221da177e4SLinus Torvalds  *					tty drivers).
231da177e4SLinus Torvalds  *		Niibe Yutaka	:	Asynchronous I/O for writes (4.4BSD style)
241da177e4SLinus Torvalds  *		Jeff Uphoff	:	Made max number of sockets command-line
251da177e4SLinus Torvalds  *					configurable.
261da177e4SLinus Torvalds  *		Matti Aarnio	:	Made the number of sockets dynamic,
271da177e4SLinus Torvalds  *					to be allocated when needed, and mr.
281da177e4SLinus Torvalds  *					Uphoff's max is used as max to be
291da177e4SLinus Torvalds  *					allowed to allocate.
301da177e4SLinus Torvalds  *		Linus		:	Argh. removed all the socket allocation
311da177e4SLinus Torvalds  *					altogether: it's in the inode now.
321da177e4SLinus Torvalds  *		Alan Cox	:	Made sock_alloc()/sock_release() public
331da177e4SLinus Torvalds  *					for NetROM and future kernel nfsd type
341da177e4SLinus Torvalds  *					stuff.
351da177e4SLinus Torvalds  *		Alan Cox	:	sendmsg/recvmsg basics.
361da177e4SLinus Torvalds  *		Tom Dyas	:	Export net symbols.
371da177e4SLinus Torvalds  *		Marcin Dalecki	:	Fixed problems with CONFIG_NET="n".
381da177e4SLinus Torvalds  *		Alan Cox	:	Added thread locking to sys_* calls
391da177e4SLinus Torvalds  *					for sockets. May have errors at the
401da177e4SLinus Torvalds  *					moment.
411da177e4SLinus Torvalds  *		Kevin Buhr	:	Fixed the dumb errors in the above.
421da177e4SLinus Torvalds  *		Andi Kleen	:	Some small cleanups, optimizations,
431da177e4SLinus Torvalds  *					and fixed a copy_from_user() bug.
441da177e4SLinus Torvalds  *		Tigran Aivazian	:	sys_send(args) calls sys_sendto(args, NULL, 0)
451da177e4SLinus Torvalds  *		Tigran Aivazian	:	Made listen(2) backlog sanity checks
461da177e4SLinus Torvalds  *					protocol-independent
471da177e4SLinus Torvalds  *
481da177e4SLinus Torvalds  *
491da177e4SLinus Torvalds  *		This program is free software; you can redistribute it and/or
501da177e4SLinus Torvalds  *		modify it under the terms of the GNU General Public License
511da177e4SLinus Torvalds  *		as published by the Free Software Foundation; either version
521da177e4SLinus Torvalds  *		2 of the License, or (at your option) any later version.
531da177e4SLinus Torvalds  *
541da177e4SLinus Torvalds  *
551da177e4SLinus Torvalds  *	This module is effectively the top level interface to the BSD socket
561da177e4SLinus Torvalds  *	paradigm.
571da177e4SLinus Torvalds  *
581da177e4SLinus Torvalds  *	Based upon Swansea University Computer Society NET3.039
591da177e4SLinus Torvalds  */
601da177e4SLinus Torvalds 
611da177e4SLinus Torvalds #include <linux/mm.h>
621da177e4SLinus Torvalds #include <linux/socket.h>
631da177e4SLinus Torvalds #include <linux/file.h>
641da177e4SLinus Torvalds #include <linux/net.h>
651da177e4SLinus Torvalds #include <linux/interrupt.h>
66aaca0bdcSUlrich Drepper #include <linux/thread_info.h>
6755737fdaSStephen Hemminger #include <linux/rcupdate.h>
681da177e4SLinus Torvalds #include <linux/netdevice.h>
691da177e4SLinus Torvalds #include <linux/proc_fs.h>
701da177e4SLinus Torvalds #include <linux/seq_file.h>
714a3e2f71SArjan van de Ven #include <linux/mutex.h>
721da177e4SLinus Torvalds #include <linux/wanrouter.h>
731da177e4SLinus Torvalds #include <linux/if_bridge.h>
7420380731SArnaldo Carvalho de Melo #include <linux/if_frad.h>
7520380731SArnaldo Carvalho de Melo #include <linux/if_vlan.h>
761da177e4SLinus Torvalds #include <linux/init.h>
771da177e4SLinus Torvalds #include <linux/poll.h>
781da177e4SLinus Torvalds #include <linux/cache.h>
791da177e4SLinus Torvalds #include <linux/module.h>
801da177e4SLinus Torvalds #include <linux/highmem.h>
811da177e4SLinus Torvalds #include <linux/mount.h>
821da177e4SLinus Torvalds #include <linux/security.h>
831da177e4SLinus Torvalds #include <linux/syscalls.h>
841da177e4SLinus Torvalds #include <linux/compat.h>
851da177e4SLinus Torvalds #include <linux/kmod.h>
863ec3b2fbSDavid Woodhouse #include <linux/audit.h>
87d86b5e0eSAdrian Bunk #include <linux/wireless.h>
881b8d7ae4SEric W. Biederman #include <linux/nsproxy.h>
891fd7317dSNick Black #include <linux/magic.h>
905a0e3ad6STejun Heo #include <linux/slab.h>
911da177e4SLinus Torvalds 
921da177e4SLinus Torvalds #include <asm/uaccess.h>
931da177e4SLinus Torvalds #include <asm/unistd.h>
941da177e4SLinus Torvalds 
951da177e4SLinus Torvalds #include <net/compat.h>
9687de87d5SDavid S. Miller #include <net/wext.h>
97f8451725SHerbert Xu #include <net/cls_cgroup.h>
981da177e4SLinus Torvalds 
991da177e4SLinus Torvalds #include <net/sock.h>
1001da177e4SLinus Torvalds #include <linux/netfilter.h>
1011da177e4SLinus Torvalds 
1026b96018bSArnd Bergmann #include <linux/if_tun.h>
1036b96018bSArnd Bergmann #include <linux/ipv6_route.h>
1046b96018bSArnd Bergmann #include <linux/route.h>
1056b96018bSArnd Bergmann #include <linux/sockios.h>
1066b96018bSArnd Bergmann #include <linux/atalk.h>
1076b96018bSArnd Bergmann 
1081da177e4SLinus Torvalds static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
109027445c3SBadari Pulavarty static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
110027445c3SBadari Pulavarty 			 unsigned long nr_segs, loff_t pos);
111027445c3SBadari Pulavarty static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
112027445c3SBadari Pulavarty 			  unsigned long nr_segs, loff_t pos);
1131da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma);
1141da177e4SLinus Torvalds 
1151da177e4SLinus Torvalds static int sock_close(struct inode *inode, struct file *file);
1161da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file,
1171da177e4SLinus Torvalds 			      struct poll_table_struct *wait);
11889bddce5SStephen Hemminger static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
11989bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
12089bbfc95SShaun Pereira static long compat_sock_ioctl(struct file *file,
12189bbfc95SShaun Pereira 			      unsigned int cmd, unsigned long arg);
12289bbfc95SShaun Pereira #endif
1231da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on);
1241da177e4SLinus Torvalds static ssize_t sock_sendpage(struct file *file, struct page *page,
1251da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more);
1269c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
1279c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
1289c55e01cSJens Axboe 				unsigned int flags);
1291da177e4SLinus Torvalds 
1301da177e4SLinus Torvalds /*
1311da177e4SLinus Torvalds  *	Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
1321da177e4SLinus Torvalds  *	in the operation structures but are done directly via the socketcall() multiplexor.
1331da177e4SLinus Torvalds  */
1341da177e4SLinus Torvalds 
135da7071d7SArjan van de Ven static const struct file_operations socket_file_ops = {
1361da177e4SLinus Torvalds 	.owner =	THIS_MODULE,
1371da177e4SLinus Torvalds 	.llseek =	no_llseek,
1381da177e4SLinus Torvalds 	.aio_read =	sock_aio_read,
1391da177e4SLinus Torvalds 	.aio_write =	sock_aio_write,
1401da177e4SLinus Torvalds 	.poll =		sock_poll,
1411da177e4SLinus Torvalds 	.unlocked_ioctl = sock_ioctl,
14289bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
14389bbfc95SShaun Pereira 	.compat_ioctl = compat_sock_ioctl,
14489bbfc95SShaun Pereira #endif
1451da177e4SLinus Torvalds 	.mmap =		sock_mmap,
1461da177e4SLinus Torvalds 	.open =		sock_no_open,	/* special open code to disallow open via /proc */
1471da177e4SLinus Torvalds 	.release =	sock_close,
1481da177e4SLinus Torvalds 	.fasync =	sock_fasync,
1495274f052SJens Axboe 	.sendpage =	sock_sendpage,
1505274f052SJens Axboe 	.splice_write = generic_splice_sendpage,
1519c55e01cSJens Axboe 	.splice_read =	sock_splice_read,
1521da177e4SLinus Torvalds };
1531da177e4SLinus Torvalds 
1541da177e4SLinus Torvalds /*
1551da177e4SLinus Torvalds  *	The protocol list. Each protocol is registered in here.
1561da177e4SLinus Torvalds  */
1571da177e4SLinus Torvalds 
1581da177e4SLinus Torvalds static DEFINE_SPINLOCK(net_family_lock);
159190683a9SEric Dumazet static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly;
1601da177e4SLinus Torvalds 
1611da177e4SLinus Torvalds /*
1621da177e4SLinus Torvalds  *	Statistics counters of the socket lists
1631da177e4SLinus Torvalds  */
1641da177e4SLinus Torvalds 
165c6d409cfSEric Dumazet static DEFINE_PER_CPU(int, sockets_in_use);
1661da177e4SLinus Torvalds 
1671da177e4SLinus Torvalds /*
16889bddce5SStephen Hemminger  * Support routines.
16989bddce5SStephen Hemminger  * Move socket addresses back and forth across the kernel/user
1701da177e4SLinus Torvalds  * divide and look after the messy bits.
1711da177e4SLinus Torvalds  */
1721da177e4SLinus Torvalds 
1731da177e4SLinus Torvalds /**
1741da177e4SLinus Torvalds  *	move_addr_to_kernel	-	copy a socket address into kernel space
1751da177e4SLinus Torvalds  *	@uaddr: Address in user space
1761da177e4SLinus Torvalds  *	@kaddr: Address in kernel space
1771da177e4SLinus Torvalds  *	@ulen: Length in user space
1781da177e4SLinus Torvalds  *
1791da177e4SLinus Torvalds  *	The address is copied into kernel space. If the provided address is
1801da177e4SLinus Torvalds  *	too long an error code of -EINVAL is returned. If the copy gives
1811da177e4SLinus Torvalds  *	invalid addresses -EFAULT is returned. On a success 0 is returned.
1821da177e4SLinus Torvalds  */
1831da177e4SLinus Torvalds 
18443db362dSMaciej Żenczykowski int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr)
1851da177e4SLinus Torvalds {
186230b1839SYOSHIFUJI Hideaki 	if (ulen < 0 || ulen > sizeof(struct sockaddr_storage))
1871da177e4SLinus Torvalds 		return -EINVAL;
1881da177e4SLinus Torvalds 	if (ulen == 0)
1891da177e4SLinus Torvalds 		return 0;
1901da177e4SLinus Torvalds 	if (copy_from_user(kaddr, uaddr, ulen))
1911da177e4SLinus Torvalds 		return -EFAULT;
1923ec3b2fbSDavid Woodhouse 	return audit_sockaddr(ulen, kaddr);
1931da177e4SLinus Torvalds }
1941da177e4SLinus Torvalds 
1951da177e4SLinus Torvalds /**
1961da177e4SLinus Torvalds  *	move_addr_to_user	-	copy an address to user space
1971da177e4SLinus Torvalds  *	@kaddr: kernel space address
1981da177e4SLinus Torvalds  *	@klen: length of address in kernel
1991da177e4SLinus Torvalds  *	@uaddr: user space address
2001da177e4SLinus Torvalds  *	@ulen: pointer to user length field
2011da177e4SLinus Torvalds  *
2021da177e4SLinus Torvalds  *	The value pointed to by ulen on entry is the buffer length available.
2031da177e4SLinus Torvalds  *	This is overwritten with the buffer space used. -EINVAL is returned
2041da177e4SLinus Torvalds  *	if an overlong buffer is specified or a negative buffer size. -EFAULT
2051da177e4SLinus Torvalds  *	is returned if either the buffer or the length field are not
2061da177e4SLinus Torvalds  *	accessible.
2071da177e4SLinus Torvalds  *	After copying the data up to the limit the user specifies, the true
2081da177e4SLinus Torvalds  *	length of the data is written over the length limit the user
2091da177e4SLinus Torvalds  *	specified. Zero is returned for a success.
2101da177e4SLinus Torvalds  */
2111da177e4SLinus Torvalds 
21243db362dSMaciej Żenczykowski static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen,
21311165f14Sstephen hemminger 			     void __user *uaddr, int __user *ulen)
2141da177e4SLinus Torvalds {
2151da177e4SLinus Torvalds 	int err;
2161da177e4SLinus Torvalds 	int len;
2171da177e4SLinus Torvalds 
21889bddce5SStephen Hemminger 	err = get_user(len, ulen);
21989bddce5SStephen Hemminger 	if (err)
2201da177e4SLinus Torvalds 		return err;
2211da177e4SLinus Torvalds 	if (len > klen)
2221da177e4SLinus Torvalds 		len = klen;
223230b1839SYOSHIFUJI Hideaki 	if (len < 0 || len > sizeof(struct sockaddr_storage))
2241da177e4SLinus Torvalds 		return -EINVAL;
22589bddce5SStephen Hemminger 	if (len) {
226d6fe3945SSteve Grubb 		if (audit_sockaddr(klen, kaddr))
227d6fe3945SSteve Grubb 			return -ENOMEM;
2281da177e4SLinus Torvalds 		if (copy_to_user(uaddr, kaddr, len))
2291da177e4SLinus Torvalds 			return -EFAULT;
2301da177e4SLinus Torvalds 	}
2311da177e4SLinus Torvalds 	/*
2321da177e4SLinus Torvalds 	 *      "fromlen shall refer to the value before truncation.."
2331da177e4SLinus Torvalds 	 *                      1003.1g
2341da177e4SLinus Torvalds 	 */
2351da177e4SLinus Torvalds 	return __put_user(klen, ulen);
2361da177e4SLinus Torvalds }
2371da177e4SLinus Torvalds 
238e18b890bSChristoph Lameter static struct kmem_cache *sock_inode_cachep __read_mostly;
2391da177e4SLinus Torvalds 
2401da177e4SLinus Torvalds static struct inode *sock_alloc_inode(struct super_block *sb)
2411da177e4SLinus Torvalds {
2421da177e4SLinus Torvalds 	struct socket_alloc *ei;
243eaefd110SEric Dumazet 	struct socket_wq *wq;
24489bddce5SStephen Hemminger 
245e94b1766SChristoph Lameter 	ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL);
2461da177e4SLinus Torvalds 	if (!ei)
2471da177e4SLinus Torvalds 		return NULL;
248eaefd110SEric Dumazet 	wq = kmalloc(sizeof(*wq), GFP_KERNEL);
249eaefd110SEric Dumazet 	if (!wq) {
25043815482SEric Dumazet 		kmem_cache_free(sock_inode_cachep, ei);
25143815482SEric Dumazet 		return NULL;
25243815482SEric Dumazet 	}
253eaefd110SEric Dumazet 	init_waitqueue_head(&wq->wait);
254eaefd110SEric Dumazet 	wq->fasync_list = NULL;
255eaefd110SEric Dumazet 	RCU_INIT_POINTER(ei->socket.wq, wq);
2561da177e4SLinus Torvalds 
2571da177e4SLinus Torvalds 	ei->socket.state = SS_UNCONNECTED;
2581da177e4SLinus Torvalds 	ei->socket.flags = 0;
2591da177e4SLinus Torvalds 	ei->socket.ops = NULL;
2601da177e4SLinus Torvalds 	ei->socket.sk = NULL;
2611da177e4SLinus Torvalds 	ei->socket.file = NULL;
2621da177e4SLinus Torvalds 
2631da177e4SLinus Torvalds 	return &ei->vfs_inode;
2641da177e4SLinus Torvalds }
2651da177e4SLinus Torvalds 
2661da177e4SLinus Torvalds static void sock_destroy_inode(struct inode *inode)
2671da177e4SLinus Torvalds {
26843815482SEric Dumazet 	struct socket_alloc *ei;
269eaefd110SEric Dumazet 	struct socket_wq *wq;
27043815482SEric Dumazet 
27143815482SEric Dumazet 	ei = container_of(inode, struct socket_alloc, vfs_inode);
272eaefd110SEric Dumazet 	wq = rcu_dereference_protected(ei->socket.wq, 1);
27361845220SLai Jiangshan 	kfree_rcu(wq, rcu);
27443815482SEric Dumazet 	kmem_cache_free(sock_inode_cachep, ei);
2751da177e4SLinus Torvalds }
2761da177e4SLinus Torvalds 
27751cc5068SAlexey Dobriyan static void init_once(void *foo)
2781da177e4SLinus Torvalds {
2791da177e4SLinus Torvalds 	struct socket_alloc *ei = (struct socket_alloc *)foo;
2801da177e4SLinus Torvalds 
2811da177e4SLinus Torvalds 	inode_init_once(&ei->vfs_inode);
2821da177e4SLinus Torvalds }
2831da177e4SLinus Torvalds 
2841da177e4SLinus Torvalds static int init_inodecache(void)
2851da177e4SLinus Torvalds {
2861da177e4SLinus Torvalds 	sock_inode_cachep = kmem_cache_create("sock_inode_cache",
2871da177e4SLinus Torvalds 					      sizeof(struct socket_alloc),
28889bddce5SStephen Hemminger 					      0,
28989bddce5SStephen Hemminger 					      (SLAB_HWCACHE_ALIGN |
29089bddce5SStephen Hemminger 					       SLAB_RECLAIM_ACCOUNT |
291fffb60f9SPaul Jackson 					       SLAB_MEM_SPREAD),
29220c2df83SPaul Mundt 					      init_once);
2931da177e4SLinus Torvalds 	if (sock_inode_cachep == NULL)
2941da177e4SLinus Torvalds 		return -ENOMEM;
2951da177e4SLinus Torvalds 	return 0;
2961da177e4SLinus Torvalds }
2971da177e4SLinus Torvalds 
298b87221deSAlexey Dobriyan static const struct super_operations sockfs_ops = {
2991da177e4SLinus Torvalds 	.alloc_inode	= sock_alloc_inode,
3001da177e4SLinus Torvalds 	.destroy_inode	= sock_destroy_inode,
3011da177e4SLinus Torvalds 	.statfs		= simple_statfs,
3021da177e4SLinus Torvalds };
3031da177e4SLinus Torvalds 
304c23fbb6bSEric Dumazet /*
305c23fbb6bSEric Dumazet  * sockfs_dname() is called from d_path().
306c23fbb6bSEric Dumazet  */
307c23fbb6bSEric Dumazet static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen)
308c23fbb6bSEric Dumazet {
309c23fbb6bSEric Dumazet 	return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]",
310c23fbb6bSEric Dumazet 				dentry->d_inode->i_ino);
311c23fbb6bSEric Dumazet }
312c23fbb6bSEric Dumazet 
3133ba13d17SAl Viro static const struct dentry_operations sockfs_dentry_operations = {
314c23fbb6bSEric Dumazet 	.d_dname  = sockfs_dname,
3151da177e4SLinus Torvalds };
3161da177e4SLinus Torvalds 
317c74a1cbbSAl Viro static struct dentry *sockfs_mount(struct file_system_type *fs_type,
318c74a1cbbSAl Viro 			 int flags, const char *dev_name, void *data)
319c74a1cbbSAl Viro {
320c74a1cbbSAl Viro 	return mount_pseudo(fs_type, "socket:", &sockfs_ops,
321c74a1cbbSAl Viro 		&sockfs_dentry_operations, SOCKFS_MAGIC);
322c74a1cbbSAl Viro }
323c74a1cbbSAl Viro 
324c74a1cbbSAl Viro static struct vfsmount *sock_mnt __read_mostly;
325c74a1cbbSAl Viro 
326c74a1cbbSAl Viro static struct file_system_type sock_fs_type = {
327c74a1cbbSAl Viro 	.name =		"sockfs",
328c74a1cbbSAl Viro 	.mount =	sockfs_mount,
329c74a1cbbSAl Viro 	.kill_sb =	kill_anon_super,
330c74a1cbbSAl Viro };
331c74a1cbbSAl Viro 
3321da177e4SLinus Torvalds /*
3331da177e4SLinus Torvalds  *	Obtains the first available file descriptor and sets it up for use.
3341da177e4SLinus Torvalds  *
33539d8c1b6SDavid S. Miller  *	These functions create file structures and maps them to fd space
33639d8c1b6SDavid S. Miller  *	of the current process. On success it returns file descriptor
3371da177e4SLinus Torvalds  *	and file struct implicitly stored in sock->file.
3381da177e4SLinus Torvalds  *	Note that another thread may close file descriptor before we return
3391da177e4SLinus Torvalds  *	from this function. We use the fact that now we do not refer
3401da177e4SLinus Torvalds  *	to socket after mapping. If one day we will need it, this
3411da177e4SLinus Torvalds  *	function will increment ref. count on file by 1.
3421da177e4SLinus Torvalds  *
3431da177e4SLinus Torvalds  *	In any case returned fd MAY BE not valid!
3441da177e4SLinus Torvalds  *	This race condition is unavoidable
3451da177e4SLinus Torvalds  *	with shared fd spaces, we cannot solve it inside kernel,
3461da177e4SLinus Torvalds  *	but we take care of internal coherence yet.
3471da177e4SLinus Torvalds  */
3481da177e4SLinus Torvalds 
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 
401406a3c63SJohn Fastabend 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 }
409406a3c63SJohn Fastabend EXPORT_SYMBOL(sock_from_file);
4106cb153caSBenjamin LaHaise 
4111da177e4SLinus Torvalds /**
4121da177e4SLinus Torvalds  *	sockfd_lookup - Go from a file number to its socket slot
4131da177e4SLinus Torvalds  *	@fd: file handle
4141da177e4SLinus Torvalds  *	@err: pointer to an error code return
4151da177e4SLinus Torvalds  *
4161da177e4SLinus Torvalds  *	The file handle passed in is locked and the socket it is bound
4171da177e4SLinus Torvalds  *	too is returned. If an error occurs the err pointer is overwritten
4181da177e4SLinus Torvalds  *	with a negative errno code and NULL is returned. The function checks
4191da177e4SLinus Torvalds  *	for both invalid handles and passing a handle which is not a socket.
4201da177e4SLinus Torvalds  *
4211da177e4SLinus Torvalds  *	On a success the socket object pointer is returned.
4221da177e4SLinus Torvalds  */
4231da177e4SLinus Torvalds 
4241da177e4SLinus Torvalds struct socket *sockfd_lookup(int fd, int *err)
4251da177e4SLinus Torvalds {
4261da177e4SLinus Torvalds 	struct file *file;
4271da177e4SLinus Torvalds 	struct socket *sock;
4281da177e4SLinus Torvalds 
42989bddce5SStephen Hemminger 	file = fget(fd);
43089bddce5SStephen Hemminger 	if (!file) {
4311da177e4SLinus Torvalds 		*err = -EBADF;
4321da177e4SLinus Torvalds 		return NULL;
4331da177e4SLinus Torvalds 	}
43489bddce5SStephen Hemminger 
4356cb153caSBenjamin LaHaise 	sock = sock_from_file(file, err);
4366cb153caSBenjamin LaHaise 	if (!sock)
4371da177e4SLinus Torvalds 		fput(file);
4386cb153caSBenjamin LaHaise 	return sock;
4391da177e4SLinus Torvalds }
440c6d409cfSEric Dumazet EXPORT_SYMBOL(sockfd_lookup);
4411da177e4SLinus Torvalds 
4426cb153caSBenjamin LaHaise static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
4436cb153caSBenjamin LaHaise {
4446cb153caSBenjamin LaHaise 	struct file *file;
4456cb153caSBenjamin LaHaise 	struct socket *sock;
4466cb153caSBenjamin LaHaise 
4473672558cSHua Zhong 	*err = -EBADF;
4486cb153caSBenjamin LaHaise 	file = fget_light(fd, fput_needed);
4496cb153caSBenjamin LaHaise 	if (file) {
4506cb153caSBenjamin LaHaise 		sock = sock_from_file(file, err);
4516cb153caSBenjamin LaHaise 		if (sock)
4521da177e4SLinus Torvalds 			return sock;
4536cb153caSBenjamin LaHaise 		fput_light(file, *fput_needed);
4546cb153caSBenjamin LaHaise 	}
4556cb153caSBenjamin LaHaise 	return NULL;
4561da177e4SLinus Torvalds }
4571da177e4SLinus Torvalds 
4581da177e4SLinus Torvalds /**
4591da177e4SLinus Torvalds  *	sock_alloc	-	allocate a socket
4601da177e4SLinus Torvalds  *
4611da177e4SLinus Torvalds  *	Allocate a new inode and socket object. The two are bound together
4621da177e4SLinus Torvalds  *	and initialised. The socket is then returned. If we are out of inodes
4631da177e4SLinus Torvalds  *	NULL is returned.
4641da177e4SLinus Torvalds  */
4651da177e4SLinus Torvalds 
4661da177e4SLinus Torvalds static struct socket *sock_alloc(void)
4671da177e4SLinus Torvalds {
4681da177e4SLinus Torvalds 	struct inode *inode;
4691da177e4SLinus Torvalds 	struct socket *sock;
4701da177e4SLinus Torvalds 
471a209dfc7SEric Dumazet 	inode = new_inode_pseudo(sock_mnt->mnt_sb);
4721da177e4SLinus Torvalds 	if (!inode)
4731da177e4SLinus Torvalds 		return NULL;
4741da177e4SLinus Torvalds 
4751da177e4SLinus Torvalds 	sock = SOCKET_I(inode);
4761da177e4SLinus Torvalds 
47729a020d3SEric Dumazet 	kmemcheck_annotate_bitfield(sock, type);
47885fe4025SChristoph Hellwig 	inode->i_ino = get_next_ino();
4791da177e4SLinus Torvalds 	inode->i_mode = S_IFSOCK | S_IRWXUGO;
4808192b0c4SDavid Howells 	inode->i_uid = current_fsuid();
4818192b0c4SDavid Howells 	inode->i_gid = current_fsgid();
4821da177e4SLinus Torvalds 
48319e8d69cSAlex Shi 	this_cpu_add(sockets_in_use, 1);
4841da177e4SLinus Torvalds 	return sock;
4851da177e4SLinus Torvalds }
4861da177e4SLinus Torvalds 
4871da177e4SLinus Torvalds /*
4881da177e4SLinus Torvalds  *	In theory you can't get an open on this inode, but /proc provides
4891da177e4SLinus Torvalds  *	a back door. Remember to keep it shut otherwise you'll let the
4901da177e4SLinus Torvalds  *	creepy crawlies in.
4911da177e4SLinus Torvalds  */
4921da177e4SLinus Torvalds 
4931da177e4SLinus Torvalds static int sock_no_open(struct inode *irrelevant, struct file *dontcare)
4941da177e4SLinus Torvalds {
4951da177e4SLinus Torvalds 	return -ENXIO;
4961da177e4SLinus Torvalds }
4971da177e4SLinus Torvalds 
4984b6f5d20SArjan van de Ven const struct file_operations bad_sock_fops = {
4991da177e4SLinus Torvalds 	.owner = THIS_MODULE,
5001da177e4SLinus Torvalds 	.open = sock_no_open,
5016038f373SArnd Bergmann 	.llseek = noop_llseek,
5021da177e4SLinus Torvalds };
5031da177e4SLinus Torvalds 
5041da177e4SLinus Torvalds /**
5051da177e4SLinus Torvalds  *	sock_release	-	close a socket
5061da177e4SLinus Torvalds  *	@sock: socket to close
5071da177e4SLinus Torvalds  *
5081da177e4SLinus Torvalds  *	The socket is released from the protocol stack if it has a release
5091da177e4SLinus Torvalds  *	callback, and the inode is then released if the socket is bound to
5101da177e4SLinus Torvalds  *	an inode not a file.
5111da177e4SLinus Torvalds  */
5121da177e4SLinus Torvalds 
5131da177e4SLinus Torvalds void sock_release(struct socket *sock)
5141da177e4SLinus Torvalds {
5151da177e4SLinus Torvalds 	if (sock->ops) {
5161da177e4SLinus Torvalds 		struct module *owner = sock->ops->owner;
5171da177e4SLinus Torvalds 
5181da177e4SLinus Torvalds 		sock->ops->release(sock);
5191da177e4SLinus Torvalds 		sock->ops = NULL;
5201da177e4SLinus Torvalds 		module_put(owner);
5211da177e4SLinus Torvalds 	}
5221da177e4SLinus Torvalds 
523eaefd110SEric Dumazet 	if (rcu_dereference_protected(sock->wq, 1)->fasync_list)
5241da177e4SLinus Torvalds 		printk(KERN_ERR "sock_release: fasync list not empty!\n");
5251da177e4SLinus Torvalds 
526b09e786bSMikulas Patocka 	if (test_bit(SOCK_EXTERNALLY_ALLOCATED, &sock->flags))
527b09e786bSMikulas Patocka 		return;
528b09e786bSMikulas Patocka 
52919e8d69cSAlex Shi 	this_cpu_sub(sockets_in_use, 1);
5301da177e4SLinus Torvalds 	if (!sock->file) {
5311da177e4SLinus Torvalds 		iput(SOCK_INODE(sock));
5321da177e4SLinus Torvalds 		return;
5331da177e4SLinus Torvalds 	}
5341da177e4SLinus Torvalds 	sock->file = NULL;
5351da177e4SLinus Torvalds }
536c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_release);
5371da177e4SLinus Torvalds 
5382244d07bSOliver Hartkopp int sock_tx_timestamp(struct sock *sk, __u8 *tx_flags)
53920d49473SPatrick Ohly {
5402244d07bSOliver Hartkopp 	*tx_flags = 0;
54120d49473SPatrick Ohly 	if (sock_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE))
5422244d07bSOliver Hartkopp 		*tx_flags |= SKBTX_HW_TSTAMP;
54320d49473SPatrick Ohly 	if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE))
5442244d07bSOliver Hartkopp 		*tx_flags |= SKBTX_SW_TSTAMP;
5456e3e939fSJohannes Berg 	if (sock_flag(sk, SOCK_WIFI_STATUS))
5466e3e939fSJohannes Berg 		*tx_flags |= SKBTX_WIFI_STATUS;
54720d49473SPatrick Ohly 	return 0;
54820d49473SPatrick Ohly }
54920d49473SPatrick Ohly EXPORT_SYMBOL(sock_tx_timestamp);
55020d49473SPatrick Ohly 
551228e548eSAnton Blanchard static inline int __sock_sendmsg_nosec(struct kiocb *iocb, struct socket *sock,
5521da177e4SLinus Torvalds 				       struct msghdr *msg, size_t size)
5531da177e4SLinus Torvalds {
5541da177e4SLinus Torvalds 	struct sock_iocb *si = kiocb_to_siocb(iocb);
5551da177e4SLinus Torvalds 
556f8451725SHerbert Xu 	sock_update_classid(sock->sk);
557f8451725SHerbert Xu 
5581da177e4SLinus Torvalds 	si->sock = sock;
5591da177e4SLinus Torvalds 	si->scm = NULL;
5601da177e4SLinus Torvalds 	si->msg = msg;
5611da177e4SLinus Torvalds 	si->size = size;
5621da177e4SLinus Torvalds 
5631da177e4SLinus Torvalds 	return sock->ops->sendmsg(iocb, sock, msg, size);
5641da177e4SLinus Torvalds }
5651da177e4SLinus Torvalds 
566228e548eSAnton Blanchard static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock,
567228e548eSAnton Blanchard 				 struct msghdr *msg, size_t size)
568228e548eSAnton Blanchard {
569228e548eSAnton Blanchard 	int err = security_socket_sendmsg(sock, msg, size);
570228e548eSAnton Blanchard 
571228e548eSAnton Blanchard 	return err ?: __sock_sendmsg_nosec(iocb, sock, msg, size);
572228e548eSAnton Blanchard }
573228e548eSAnton Blanchard 
5741da177e4SLinus Torvalds int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
5751da177e4SLinus Torvalds {
5761da177e4SLinus Torvalds 	struct kiocb iocb;
5771da177e4SLinus Torvalds 	struct sock_iocb siocb;
5781da177e4SLinus Torvalds 	int ret;
5791da177e4SLinus Torvalds 
5801da177e4SLinus Torvalds 	init_sync_kiocb(&iocb, NULL);
5811da177e4SLinus Torvalds 	iocb.private = &siocb;
5821da177e4SLinus Torvalds 	ret = __sock_sendmsg(&iocb, sock, msg, size);
5831da177e4SLinus Torvalds 	if (-EIOCBQUEUED == ret)
5841da177e4SLinus Torvalds 		ret = wait_on_sync_kiocb(&iocb);
5851da177e4SLinus Torvalds 	return ret;
5861da177e4SLinus Torvalds }
587c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_sendmsg);
5881da177e4SLinus Torvalds 
589894dc24cSEric Dumazet static int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg, size_t size)
590228e548eSAnton Blanchard {
591228e548eSAnton Blanchard 	struct kiocb iocb;
592228e548eSAnton Blanchard 	struct sock_iocb siocb;
593228e548eSAnton Blanchard 	int ret;
594228e548eSAnton Blanchard 
595228e548eSAnton Blanchard 	init_sync_kiocb(&iocb, NULL);
596228e548eSAnton Blanchard 	iocb.private = &siocb;
597228e548eSAnton Blanchard 	ret = __sock_sendmsg_nosec(&iocb, sock, msg, size);
598228e548eSAnton Blanchard 	if (-EIOCBQUEUED == ret)
599228e548eSAnton Blanchard 		ret = wait_on_sync_kiocb(&iocb);
600228e548eSAnton Blanchard 	return ret;
601228e548eSAnton Blanchard }
602228e548eSAnton Blanchard 
6031da177e4SLinus Torvalds int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
6041da177e4SLinus Torvalds 		   struct kvec *vec, size_t num, size_t size)
6051da177e4SLinus Torvalds {
6061da177e4SLinus Torvalds 	mm_segment_t oldfs = get_fs();
6071da177e4SLinus Torvalds 	int result;
6081da177e4SLinus Torvalds 
6091da177e4SLinus Torvalds 	set_fs(KERNEL_DS);
6101da177e4SLinus Torvalds 	/*
6111da177e4SLinus Torvalds 	 * the following is safe, since for compiler definitions of kvec and
6121da177e4SLinus Torvalds 	 * iovec are identical, yielding the same in-core layout and alignment
6131da177e4SLinus Torvalds 	 */
61489bddce5SStephen Hemminger 	msg->msg_iov = (struct iovec *)vec;
6151da177e4SLinus Torvalds 	msg->msg_iovlen = num;
6161da177e4SLinus Torvalds 	result = sock_sendmsg(sock, msg, size);
6171da177e4SLinus Torvalds 	set_fs(oldfs);
6181da177e4SLinus Torvalds 	return result;
6191da177e4SLinus Torvalds }
620c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendmsg);
6211da177e4SLinus Torvalds 
62220d49473SPatrick Ohly static int ktime2ts(ktime_t kt, struct timespec *ts)
62320d49473SPatrick Ohly {
62420d49473SPatrick Ohly 	if (kt.tv64) {
62520d49473SPatrick Ohly 		*ts = ktime_to_timespec(kt);
62620d49473SPatrick Ohly 		return 1;
62720d49473SPatrick Ohly 	} else {
62820d49473SPatrick Ohly 		return 0;
62920d49473SPatrick Ohly 	}
63020d49473SPatrick Ohly }
63120d49473SPatrick Ohly 
63292f37fd2SEric Dumazet /*
63392f37fd2SEric Dumazet  * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
63492f37fd2SEric Dumazet  */
63592f37fd2SEric Dumazet void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
63692f37fd2SEric Dumazet 	struct sk_buff *skb)
63792f37fd2SEric Dumazet {
63820d49473SPatrick Ohly 	int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
63920d49473SPatrick Ohly 	struct timespec ts[3];
64020d49473SPatrick Ohly 	int empty = 1;
64120d49473SPatrick Ohly 	struct skb_shared_hwtstamps *shhwtstamps =
64220d49473SPatrick Ohly 		skb_hwtstamps(skb);
64392f37fd2SEric Dumazet 
64420d49473SPatrick Ohly 	/* Race occurred between timestamp enabling and packet
64520d49473SPatrick Ohly 	   receiving.  Fill in the current time for now. */
64620d49473SPatrick Ohly 	if (need_software_tstamp && skb->tstamp.tv64 == 0)
64720d49473SPatrick Ohly 		__net_timestamp(skb);
64820d49473SPatrick Ohly 
64920d49473SPatrick Ohly 	if (need_software_tstamp) {
65092f37fd2SEric Dumazet 		if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
65192f37fd2SEric Dumazet 			struct timeval tv;
65220d49473SPatrick Ohly 			skb_get_timestamp(skb, &tv);
65320d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP,
65420d49473SPatrick Ohly 				 sizeof(tv), &tv);
65592f37fd2SEric Dumazet 		} else {
656842509b8SHagen Paul Pfeifer 			skb_get_timestampns(skb, &ts[0]);
65720d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS,
658842509b8SHagen Paul Pfeifer 				 sizeof(ts[0]), &ts[0]);
65992f37fd2SEric Dumazet 		}
66092f37fd2SEric Dumazet 	}
66192f37fd2SEric Dumazet 
66220d49473SPatrick Ohly 
66320d49473SPatrick Ohly 	memset(ts, 0, sizeof(ts));
66420d49473SPatrick Ohly 	if (skb->tstamp.tv64 &&
66520d49473SPatrick Ohly 	    sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE)) {
66620d49473SPatrick Ohly 		skb_get_timestampns(skb, ts + 0);
66720d49473SPatrick Ohly 		empty = 0;
66820d49473SPatrick Ohly 	}
66920d49473SPatrick Ohly 	if (shhwtstamps) {
67020d49473SPatrick Ohly 		if (sock_flag(sk, SOCK_TIMESTAMPING_SYS_HARDWARE) &&
67120d49473SPatrick Ohly 		    ktime2ts(shhwtstamps->syststamp, ts + 1))
67220d49473SPatrick Ohly 			empty = 0;
67320d49473SPatrick Ohly 		if (sock_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE) &&
67420d49473SPatrick Ohly 		    ktime2ts(shhwtstamps->hwtstamp, ts + 2))
67520d49473SPatrick Ohly 			empty = 0;
67620d49473SPatrick Ohly 	}
67720d49473SPatrick Ohly 	if (!empty)
67820d49473SPatrick Ohly 		put_cmsg(msg, SOL_SOCKET,
67920d49473SPatrick Ohly 			 SCM_TIMESTAMPING, sizeof(ts), &ts);
68020d49473SPatrick Ohly }
6817c81fd8bSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
6827c81fd8bSArnaldo Carvalho de Melo 
6836e3e939fSJohannes Berg void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
6846e3e939fSJohannes Berg 	struct sk_buff *skb)
6856e3e939fSJohannes Berg {
6866e3e939fSJohannes Berg 	int ack;
6876e3e939fSJohannes Berg 
6886e3e939fSJohannes Berg 	if (!sock_flag(sk, SOCK_WIFI_STATUS))
6896e3e939fSJohannes Berg 		return;
6906e3e939fSJohannes Berg 	if (!skb->wifi_acked_valid)
6916e3e939fSJohannes Berg 		return;
6926e3e939fSJohannes Berg 
6936e3e939fSJohannes Berg 	ack = skb->wifi_acked;
6946e3e939fSJohannes Berg 
6956e3e939fSJohannes Berg 	put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack);
6966e3e939fSJohannes Berg }
6976e3e939fSJohannes Berg EXPORT_SYMBOL_GPL(__sock_recv_wifi_status);
6986e3e939fSJohannes Berg 
69911165f14Sstephen hemminger static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk,
70011165f14Sstephen hemminger 				   struct sk_buff *skb)
7013b885787SNeil Horman {
7023b885787SNeil Horman 	if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && skb->dropcount)
7033b885787SNeil Horman 		put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL,
7043b885787SNeil Horman 			sizeof(__u32), &skb->dropcount);
7053b885787SNeil Horman }
7063b885787SNeil Horman 
707767dd033SEric Dumazet void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
7083b885787SNeil Horman 	struct sk_buff *skb)
7093b885787SNeil Horman {
7103b885787SNeil Horman 	sock_recv_timestamp(msg, sk, skb);
7113b885787SNeil Horman 	sock_recv_drops(msg, sk, skb);
7123b885787SNeil Horman }
713767dd033SEric Dumazet EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops);
7143b885787SNeil Horman 
715a2e27255SArnaldo Carvalho de Melo static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock,
7161da177e4SLinus Torvalds 				       struct msghdr *msg, size_t size, int flags)
7171da177e4SLinus Torvalds {
7181da177e4SLinus Torvalds 	struct sock_iocb *si = kiocb_to_siocb(iocb);
7191da177e4SLinus Torvalds 
720f8451725SHerbert Xu 	sock_update_classid(sock->sk);
721f8451725SHerbert Xu 
7221da177e4SLinus Torvalds 	si->sock = sock;
7231da177e4SLinus Torvalds 	si->scm = NULL;
7241da177e4SLinus Torvalds 	si->msg = msg;
7251da177e4SLinus Torvalds 	si->size = size;
7261da177e4SLinus Torvalds 	si->flags = flags;
7271da177e4SLinus Torvalds 
7281da177e4SLinus Torvalds 	return sock->ops->recvmsg(iocb, sock, msg, size, flags);
7291da177e4SLinus Torvalds }
7301da177e4SLinus Torvalds 
731a2e27255SArnaldo Carvalho de Melo static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock,
732a2e27255SArnaldo Carvalho de Melo 				 struct msghdr *msg, size_t size, int flags)
733a2e27255SArnaldo Carvalho de Melo {
734a2e27255SArnaldo Carvalho de Melo 	int err = security_socket_recvmsg(sock, msg, size, flags);
735a2e27255SArnaldo Carvalho de Melo 
736a2e27255SArnaldo Carvalho de Melo 	return err ?: __sock_recvmsg_nosec(iocb, sock, msg, size, flags);
737a2e27255SArnaldo Carvalho de Melo }
738a2e27255SArnaldo Carvalho de Melo 
7391da177e4SLinus Torvalds int sock_recvmsg(struct socket *sock, struct msghdr *msg,
7401da177e4SLinus Torvalds 		 size_t size, int flags)
7411da177e4SLinus Torvalds {
7421da177e4SLinus Torvalds 	struct kiocb iocb;
7431da177e4SLinus Torvalds 	struct sock_iocb siocb;
7441da177e4SLinus Torvalds 	int ret;
7451da177e4SLinus Torvalds 
7461da177e4SLinus Torvalds 	init_sync_kiocb(&iocb, NULL);
7471da177e4SLinus Torvalds 	iocb.private = &siocb;
7481da177e4SLinus Torvalds 	ret = __sock_recvmsg(&iocb, sock, msg, size, flags);
7491da177e4SLinus Torvalds 	if (-EIOCBQUEUED == ret)
7501da177e4SLinus Torvalds 		ret = wait_on_sync_kiocb(&iocb);
7511da177e4SLinus Torvalds 	return ret;
7521da177e4SLinus Torvalds }
753c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_recvmsg);
7541da177e4SLinus Torvalds 
755a2e27255SArnaldo Carvalho de Melo static int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
756a2e27255SArnaldo Carvalho de Melo 			      size_t size, int flags)
757a2e27255SArnaldo Carvalho de Melo {
758a2e27255SArnaldo Carvalho de Melo 	struct kiocb iocb;
759a2e27255SArnaldo Carvalho de Melo 	struct sock_iocb siocb;
760a2e27255SArnaldo Carvalho de Melo 	int ret;
761a2e27255SArnaldo Carvalho de Melo 
762a2e27255SArnaldo Carvalho de Melo 	init_sync_kiocb(&iocb, NULL);
763a2e27255SArnaldo Carvalho de Melo 	iocb.private = &siocb;
764a2e27255SArnaldo Carvalho de Melo 	ret = __sock_recvmsg_nosec(&iocb, sock, msg, size, flags);
765a2e27255SArnaldo Carvalho de Melo 	if (-EIOCBQUEUED == ret)
766a2e27255SArnaldo Carvalho de Melo 		ret = wait_on_sync_kiocb(&iocb);
767a2e27255SArnaldo Carvalho de Melo 	return ret;
768a2e27255SArnaldo Carvalho de Melo }
769a2e27255SArnaldo Carvalho de Melo 
770c1249c0aSMartin Lucina /**
771c1249c0aSMartin Lucina  * kernel_recvmsg - Receive a message from a socket (kernel space)
772c1249c0aSMartin Lucina  * @sock:       The socket to receive the message from
773c1249c0aSMartin Lucina  * @msg:        Received message
774c1249c0aSMartin Lucina  * @vec:        Input s/g array for message data
775c1249c0aSMartin Lucina  * @num:        Size of input s/g array
776c1249c0aSMartin Lucina  * @size:       Number of bytes to read
777c1249c0aSMartin Lucina  * @flags:      Message flags (MSG_DONTWAIT, etc...)
778c1249c0aSMartin Lucina  *
779c1249c0aSMartin Lucina  * On return the msg structure contains the scatter/gather array passed in the
780c1249c0aSMartin Lucina  * vec argument. The array is modified so that it consists of the unfilled
781c1249c0aSMartin Lucina  * portion of the original array.
782c1249c0aSMartin Lucina  *
783c1249c0aSMartin Lucina  * The returned value is the total number of bytes received, or an error.
784c1249c0aSMartin Lucina  */
7851da177e4SLinus Torvalds int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
78689bddce5SStephen Hemminger 		   struct kvec *vec, size_t num, size_t size, int flags)
7871da177e4SLinus Torvalds {
7881da177e4SLinus Torvalds 	mm_segment_t oldfs = get_fs();
7891da177e4SLinus Torvalds 	int result;
7901da177e4SLinus Torvalds 
7911da177e4SLinus Torvalds 	set_fs(KERNEL_DS);
7921da177e4SLinus Torvalds 	/*
7931da177e4SLinus Torvalds 	 * the following is safe, since for compiler definitions of kvec and
7941da177e4SLinus Torvalds 	 * iovec are identical, yielding the same in-core layout and alignment
7951da177e4SLinus Torvalds 	 */
79689bddce5SStephen Hemminger 	msg->msg_iov = (struct iovec *)vec, msg->msg_iovlen = num;
7971da177e4SLinus Torvalds 	result = sock_recvmsg(sock, msg, size, flags);
7981da177e4SLinus Torvalds 	set_fs(oldfs);
7991da177e4SLinus Torvalds 	return result;
8001da177e4SLinus Torvalds }
801c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_recvmsg);
8021da177e4SLinus Torvalds 
8031da177e4SLinus Torvalds static void sock_aio_dtor(struct kiocb *iocb)
8041da177e4SLinus Torvalds {
8051da177e4SLinus Torvalds 	kfree(iocb->private);
8061da177e4SLinus Torvalds }
8071da177e4SLinus Torvalds 
80820380731SArnaldo Carvalho de Melo static ssize_t sock_sendpage(struct file *file, struct page *page,
8091da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more)
8101da177e4SLinus Torvalds {
8111da177e4SLinus Torvalds 	struct socket *sock;
8121da177e4SLinus Torvalds 	int flags;
8131da177e4SLinus Torvalds 
814b69aee04SEric Dumazet 	sock = file->private_data;
8151da177e4SLinus Torvalds 
81635f9c09fSEric Dumazet 	flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
81735f9c09fSEric Dumazet 	/* more is a combination of MSG_MORE and MSG_SENDPAGE_NOTLAST */
81835f9c09fSEric Dumazet 	flags |= more;
8191da177e4SLinus Torvalds 
820e6949583SLinus Torvalds 	return kernel_sendpage(sock, page, offset, size, flags);
8211da177e4SLinus Torvalds }
8221da177e4SLinus Torvalds 
8239c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
8249c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
8259c55e01cSJens Axboe 				unsigned int flags)
8269c55e01cSJens Axboe {
8279c55e01cSJens Axboe 	struct socket *sock = file->private_data;
8289c55e01cSJens Axboe 
829997b37daSRémi Denis-Courmont 	if (unlikely(!sock->ops->splice_read))
830997b37daSRémi Denis-Courmont 		return -EINVAL;
831997b37daSRémi Denis-Courmont 
832f8451725SHerbert Xu 	sock_update_classid(sock->sk);
833f8451725SHerbert Xu 
8349c55e01cSJens Axboe 	return sock->ops->splice_read(sock, ppos, pipe, len, flags);
8359c55e01cSJens Axboe }
8369c55e01cSJens Axboe 
837ce1d4d3eSChristoph Hellwig static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
83889bddce5SStephen Hemminger 					 struct sock_iocb *siocb)
839ce1d4d3eSChristoph Hellwig {
840ce1d4d3eSChristoph Hellwig 	if (!is_sync_kiocb(iocb)) {
841ce1d4d3eSChristoph Hellwig 		siocb = kmalloc(sizeof(*siocb), GFP_KERNEL);
842ce1d4d3eSChristoph Hellwig 		if (!siocb)
843ce1d4d3eSChristoph Hellwig 			return NULL;
844ce1d4d3eSChristoph Hellwig 		iocb->ki_dtor = sock_aio_dtor;
845ce1d4d3eSChristoph Hellwig 	}
846ce1d4d3eSChristoph Hellwig 
847ce1d4d3eSChristoph Hellwig 	siocb->kiocb = iocb;
848ce1d4d3eSChristoph Hellwig 	iocb->private = siocb;
849ce1d4d3eSChristoph Hellwig 	return siocb;
850ce1d4d3eSChristoph Hellwig }
851ce1d4d3eSChristoph Hellwig 
852ce1d4d3eSChristoph Hellwig static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb,
853027445c3SBadari Pulavarty 		struct file *file, const struct iovec *iov,
85489bddce5SStephen Hemminger 		unsigned long nr_segs)
855ce1d4d3eSChristoph Hellwig {
856ce1d4d3eSChristoph Hellwig 	struct socket *sock = file->private_data;
857ce1d4d3eSChristoph Hellwig 	size_t size = 0;
858ce1d4d3eSChristoph Hellwig 	int i;
859ce1d4d3eSChristoph Hellwig 
860ce1d4d3eSChristoph Hellwig 	for (i = 0; i < nr_segs; i++)
861ce1d4d3eSChristoph Hellwig 		size += iov[i].iov_len;
862ce1d4d3eSChristoph Hellwig 
863ce1d4d3eSChristoph Hellwig 	msg->msg_name = NULL;
864ce1d4d3eSChristoph Hellwig 	msg->msg_namelen = 0;
865ce1d4d3eSChristoph Hellwig 	msg->msg_control = NULL;
866ce1d4d3eSChristoph Hellwig 	msg->msg_controllen = 0;
867ce1d4d3eSChristoph Hellwig 	msg->msg_iov = (struct iovec *)iov;
868ce1d4d3eSChristoph Hellwig 	msg->msg_iovlen = nr_segs;
869ce1d4d3eSChristoph Hellwig 	msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
870ce1d4d3eSChristoph Hellwig 
871ce1d4d3eSChristoph Hellwig 	return __sock_recvmsg(iocb, sock, msg, size, msg->msg_flags);
872ce1d4d3eSChristoph Hellwig }
873ce1d4d3eSChristoph Hellwig 
874027445c3SBadari Pulavarty static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
875027445c3SBadari Pulavarty 				unsigned long nr_segs, loff_t pos)
876ce1d4d3eSChristoph Hellwig {
877ce1d4d3eSChristoph Hellwig 	struct sock_iocb siocb, *x;
878ce1d4d3eSChristoph Hellwig 
879ce1d4d3eSChristoph Hellwig 	if (pos != 0)
880ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
881027445c3SBadari Pulavarty 
882027445c3SBadari Pulavarty 	if (iocb->ki_left == 0)	/* Match SYS5 behaviour */
883ce1d4d3eSChristoph Hellwig 		return 0;
884ce1d4d3eSChristoph Hellwig 
885027445c3SBadari Pulavarty 
886027445c3SBadari Pulavarty 	x = alloc_sock_iocb(iocb, &siocb);
887ce1d4d3eSChristoph Hellwig 	if (!x)
888ce1d4d3eSChristoph Hellwig 		return -ENOMEM;
889027445c3SBadari Pulavarty 	return do_sock_read(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
890ce1d4d3eSChristoph Hellwig }
891ce1d4d3eSChristoph Hellwig 
892ce1d4d3eSChristoph Hellwig static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb,
893027445c3SBadari Pulavarty 			struct file *file, const struct iovec *iov,
89489bddce5SStephen Hemminger 			unsigned long nr_segs)
895ce1d4d3eSChristoph Hellwig {
896ce1d4d3eSChristoph Hellwig 	struct socket *sock = file->private_data;
897ce1d4d3eSChristoph Hellwig 	size_t size = 0;
898ce1d4d3eSChristoph Hellwig 	int i;
899ce1d4d3eSChristoph Hellwig 
900ce1d4d3eSChristoph Hellwig 	for (i = 0; i < nr_segs; i++)
901ce1d4d3eSChristoph Hellwig 		size += iov[i].iov_len;
902ce1d4d3eSChristoph Hellwig 
903ce1d4d3eSChristoph Hellwig 	msg->msg_name = NULL;
904ce1d4d3eSChristoph Hellwig 	msg->msg_namelen = 0;
905ce1d4d3eSChristoph Hellwig 	msg->msg_control = NULL;
906ce1d4d3eSChristoph Hellwig 	msg->msg_controllen = 0;
907ce1d4d3eSChristoph Hellwig 	msg->msg_iov = (struct iovec *)iov;
908ce1d4d3eSChristoph Hellwig 	msg->msg_iovlen = nr_segs;
909ce1d4d3eSChristoph Hellwig 	msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
910ce1d4d3eSChristoph Hellwig 	if (sock->type == SOCK_SEQPACKET)
911ce1d4d3eSChristoph Hellwig 		msg->msg_flags |= MSG_EOR;
912ce1d4d3eSChristoph Hellwig 
913ce1d4d3eSChristoph Hellwig 	return __sock_sendmsg(iocb, sock, msg, size);
914ce1d4d3eSChristoph Hellwig }
915ce1d4d3eSChristoph Hellwig 
916027445c3SBadari Pulavarty static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
917027445c3SBadari Pulavarty 			  unsigned long nr_segs, loff_t pos)
9181da177e4SLinus Torvalds {
919ce1d4d3eSChristoph Hellwig 	struct sock_iocb siocb, *x;
9201da177e4SLinus Torvalds 
921ce1d4d3eSChristoph Hellwig 	if (pos != 0)
922ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
923027445c3SBadari Pulavarty 
924027445c3SBadari Pulavarty 	x = alloc_sock_iocb(iocb, &siocb);
925ce1d4d3eSChristoph Hellwig 	if (!x)
926ce1d4d3eSChristoph Hellwig 		return -ENOMEM;
927ce1d4d3eSChristoph Hellwig 
928027445c3SBadari Pulavarty 	return do_sock_write(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
9291da177e4SLinus Torvalds }
9301da177e4SLinus Torvalds 
9311da177e4SLinus Torvalds /*
9321da177e4SLinus Torvalds  * Atomic setting of ioctl hooks to avoid race
9331da177e4SLinus Torvalds  * with module unload.
9341da177e4SLinus Torvalds  */
9351da177e4SLinus Torvalds 
9364a3e2f71SArjan van de Ven static DEFINE_MUTEX(br_ioctl_mutex);
937c6d409cfSEric Dumazet static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg);
9381da177e4SLinus Torvalds 
939881d966bSEric W. Biederman void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *))
9401da177e4SLinus Torvalds {
9414a3e2f71SArjan van de Ven 	mutex_lock(&br_ioctl_mutex);
9421da177e4SLinus Torvalds 	br_ioctl_hook = hook;
9434a3e2f71SArjan van de Ven 	mutex_unlock(&br_ioctl_mutex);
9441da177e4SLinus Torvalds }
9451da177e4SLinus Torvalds EXPORT_SYMBOL(brioctl_set);
9461da177e4SLinus Torvalds 
9474a3e2f71SArjan van de Ven static DEFINE_MUTEX(vlan_ioctl_mutex);
948881d966bSEric W. Biederman static int (*vlan_ioctl_hook) (struct net *, void __user *arg);
9491da177e4SLinus Torvalds 
950881d966bSEric W. Biederman void vlan_ioctl_set(int (*hook) (struct net *, void __user *))
9511da177e4SLinus Torvalds {
9524a3e2f71SArjan van de Ven 	mutex_lock(&vlan_ioctl_mutex);
9531da177e4SLinus Torvalds 	vlan_ioctl_hook = hook;
9544a3e2f71SArjan van de Ven 	mutex_unlock(&vlan_ioctl_mutex);
9551da177e4SLinus Torvalds }
9561da177e4SLinus Torvalds EXPORT_SYMBOL(vlan_ioctl_set);
9571da177e4SLinus Torvalds 
9584a3e2f71SArjan van de Ven static DEFINE_MUTEX(dlci_ioctl_mutex);
9591da177e4SLinus Torvalds static int (*dlci_ioctl_hook) (unsigned int, void __user *);
9601da177e4SLinus Torvalds 
9611da177e4SLinus Torvalds void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
9621da177e4SLinus Torvalds {
9634a3e2f71SArjan van de Ven 	mutex_lock(&dlci_ioctl_mutex);
9641da177e4SLinus Torvalds 	dlci_ioctl_hook = hook;
9654a3e2f71SArjan van de Ven 	mutex_unlock(&dlci_ioctl_mutex);
9661da177e4SLinus Torvalds }
9671da177e4SLinus Torvalds EXPORT_SYMBOL(dlci_ioctl_set);
9681da177e4SLinus Torvalds 
9696b96018bSArnd Bergmann static long sock_do_ioctl(struct net *net, struct socket *sock,
9706b96018bSArnd Bergmann 				 unsigned int cmd, unsigned long arg)
9716b96018bSArnd Bergmann {
9726b96018bSArnd Bergmann 	int err;
9736b96018bSArnd Bergmann 	void __user *argp = (void __user *)arg;
9746b96018bSArnd Bergmann 
9756b96018bSArnd Bergmann 	err = sock->ops->ioctl(sock, cmd, arg);
9766b96018bSArnd Bergmann 
9776b96018bSArnd Bergmann 	/*
9786b96018bSArnd Bergmann 	 * If this ioctl is unknown try to hand it down
9796b96018bSArnd Bergmann 	 * to the NIC driver.
9806b96018bSArnd Bergmann 	 */
9816b96018bSArnd Bergmann 	if (err == -ENOIOCTLCMD)
9826b96018bSArnd Bergmann 		err = dev_ioctl(net, cmd, argp);
9836b96018bSArnd Bergmann 
9846b96018bSArnd Bergmann 	return err;
9856b96018bSArnd Bergmann }
9866b96018bSArnd Bergmann 
9871da177e4SLinus Torvalds /*
9881da177e4SLinus Torvalds  *	With an ioctl, arg may well be a user mode pointer, but we don't know
9891da177e4SLinus Torvalds  *	what to do with it - that's up to the protocol still.
9901da177e4SLinus Torvalds  */
9911da177e4SLinus Torvalds 
9921da177e4SLinus Torvalds static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
9931da177e4SLinus Torvalds {
9941da177e4SLinus Torvalds 	struct socket *sock;
995881d966bSEric W. Biederman 	struct sock *sk;
9961da177e4SLinus Torvalds 	void __user *argp = (void __user *)arg;
9971da177e4SLinus Torvalds 	int pid, err;
998881d966bSEric W. Biederman 	struct net *net;
9991da177e4SLinus Torvalds 
1000b69aee04SEric Dumazet 	sock = file->private_data;
1001881d966bSEric W. Biederman 	sk = sock->sk;
10023b1e0a65SYOSHIFUJI Hideaki 	net = sock_net(sk);
10031da177e4SLinus Torvalds 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
1004881d966bSEric W. Biederman 		err = dev_ioctl(net, cmd, argp);
10051da177e4SLinus Torvalds 	} else
10063d23e349SJohannes Berg #ifdef CONFIG_WEXT_CORE
10071da177e4SLinus Torvalds 	if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
1008881d966bSEric W. Biederman 		err = dev_ioctl(net, cmd, argp);
10091da177e4SLinus Torvalds 	} else
10103d23e349SJohannes Berg #endif
10111da177e4SLinus Torvalds 		switch (cmd) {
10121da177e4SLinus Torvalds 		case FIOSETOWN:
10131da177e4SLinus Torvalds 		case SIOCSPGRP:
10141da177e4SLinus Torvalds 			err = -EFAULT;
10151da177e4SLinus Torvalds 			if (get_user(pid, (int __user *)argp))
10161da177e4SLinus Torvalds 				break;
10171da177e4SLinus Torvalds 			err = f_setown(sock->file, pid, 1);
10181da177e4SLinus Torvalds 			break;
10191da177e4SLinus Torvalds 		case FIOGETOWN:
10201da177e4SLinus Torvalds 		case SIOCGPGRP:
1021609d7fa9SEric W. Biederman 			err = put_user(f_getown(sock->file),
102289bddce5SStephen Hemminger 				       (int __user *)argp);
10231da177e4SLinus Torvalds 			break;
10241da177e4SLinus Torvalds 		case SIOCGIFBR:
10251da177e4SLinus Torvalds 		case SIOCSIFBR:
10261da177e4SLinus Torvalds 		case SIOCBRADDBR:
10271da177e4SLinus Torvalds 		case SIOCBRDELBR:
10281da177e4SLinus Torvalds 			err = -ENOPKG;
10291da177e4SLinus Torvalds 			if (!br_ioctl_hook)
10301da177e4SLinus Torvalds 				request_module("bridge");
10311da177e4SLinus Torvalds 
10324a3e2f71SArjan van de Ven 			mutex_lock(&br_ioctl_mutex);
10331da177e4SLinus Torvalds 			if (br_ioctl_hook)
1034881d966bSEric W. Biederman 				err = br_ioctl_hook(net, cmd, argp);
10354a3e2f71SArjan van de Ven 			mutex_unlock(&br_ioctl_mutex);
10361da177e4SLinus Torvalds 			break;
10371da177e4SLinus Torvalds 		case SIOCGIFVLAN:
10381da177e4SLinus Torvalds 		case SIOCSIFVLAN:
10391da177e4SLinus Torvalds 			err = -ENOPKG;
10401da177e4SLinus Torvalds 			if (!vlan_ioctl_hook)
10411da177e4SLinus Torvalds 				request_module("8021q");
10421da177e4SLinus Torvalds 
10434a3e2f71SArjan van de Ven 			mutex_lock(&vlan_ioctl_mutex);
10441da177e4SLinus Torvalds 			if (vlan_ioctl_hook)
1045881d966bSEric W. Biederman 				err = vlan_ioctl_hook(net, argp);
10464a3e2f71SArjan van de Ven 			mutex_unlock(&vlan_ioctl_mutex);
10471da177e4SLinus Torvalds 			break;
10481da177e4SLinus Torvalds 		case SIOCADDDLCI:
10491da177e4SLinus Torvalds 		case SIOCDELDLCI:
10501da177e4SLinus Torvalds 			err = -ENOPKG;
10511da177e4SLinus Torvalds 			if (!dlci_ioctl_hook)
10521da177e4SLinus Torvalds 				request_module("dlci");
10531da177e4SLinus Torvalds 
10544a3e2f71SArjan van de Ven 			mutex_lock(&dlci_ioctl_mutex);
10557512cbf6SPavel Emelyanov 			if (dlci_ioctl_hook)
10561da177e4SLinus Torvalds 				err = dlci_ioctl_hook(cmd, argp);
10574a3e2f71SArjan van de Ven 			mutex_unlock(&dlci_ioctl_mutex);
10581da177e4SLinus Torvalds 			break;
10591da177e4SLinus Torvalds 		default:
10606b96018bSArnd Bergmann 			err = sock_do_ioctl(net, sock, cmd, arg);
10611da177e4SLinus Torvalds 			break;
10621da177e4SLinus Torvalds 		}
10631da177e4SLinus Torvalds 	return err;
10641da177e4SLinus Torvalds }
10651da177e4SLinus Torvalds 
10661da177e4SLinus Torvalds int sock_create_lite(int family, int type, int protocol, struct socket **res)
10671da177e4SLinus Torvalds {
10681da177e4SLinus Torvalds 	int err;
10691da177e4SLinus Torvalds 	struct socket *sock = NULL;
10701da177e4SLinus Torvalds 
10711da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, 1);
10721da177e4SLinus Torvalds 	if (err)
10731da177e4SLinus Torvalds 		goto out;
10741da177e4SLinus Torvalds 
10751da177e4SLinus Torvalds 	sock = sock_alloc();
10761da177e4SLinus Torvalds 	if (!sock) {
10771da177e4SLinus Torvalds 		err = -ENOMEM;
10781da177e4SLinus Torvalds 		goto out;
10791da177e4SLinus Torvalds 	}
10801da177e4SLinus Torvalds 
10811da177e4SLinus Torvalds 	sock->type = type;
10827420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, 1);
10837420ed23SVenkat Yekkirala 	if (err)
10847420ed23SVenkat Yekkirala 		goto out_release;
10857420ed23SVenkat Yekkirala 
10861da177e4SLinus Torvalds out:
10871da177e4SLinus Torvalds 	*res = sock;
10881da177e4SLinus Torvalds 	return err;
10897420ed23SVenkat Yekkirala out_release:
10907420ed23SVenkat Yekkirala 	sock_release(sock);
10917420ed23SVenkat Yekkirala 	sock = NULL;
10927420ed23SVenkat Yekkirala 	goto out;
10931da177e4SLinus Torvalds }
1094c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_lite);
10951da177e4SLinus Torvalds 
10961da177e4SLinus Torvalds /* No kernel lock held - perfect */
10971da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file, poll_table *wait)
10981da177e4SLinus Torvalds {
10991da177e4SLinus Torvalds 	struct socket *sock;
11001da177e4SLinus Torvalds 
11011da177e4SLinus Torvalds 	/*
11021da177e4SLinus Torvalds 	 *      We can't return errors to poll, so it's either yes or no.
11031da177e4SLinus Torvalds 	 */
1104b69aee04SEric Dumazet 	sock = file->private_data;
11051da177e4SLinus Torvalds 	return sock->ops->poll(file, sock, wait);
11061da177e4SLinus Torvalds }
11071da177e4SLinus Torvalds 
11081da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma)
11091da177e4SLinus Torvalds {
1110b69aee04SEric Dumazet 	struct socket *sock = file->private_data;
11111da177e4SLinus Torvalds 
11121da177e4SLinus Torvalds 	return sock->ops->mmap(file, sock, vma);
11131da177e4SLinus Torvalds }
11141da177e4SLinus Torvalds 
111520380731SArnaldo Carvalho de Melo static int sock_close(struct inode *inode, struct file *filp)
11161da177e4SLinus Torvalds {
11171da177e4SLinus Torvalds 	/*
11181da177e4SLinus Torvalds 	 *      It was possible the inode is NULL we were
11191da177e4SLinus Torvalds 	 *      closing an unfinished socket.
11201da177e4SLinus Torvalds 	 */
11211da177e4SLinus Torvalds 
112289bddce5SStephen Hemminger 	if (!inode) {
11231da177e4SLinus Torvalds 		printk(KERN_DEBUG "sock_close: NULL inode\n");
11241da177e4SLinus Torvalds 		return 0;
11251da177e4SLinus Torvalds 	}
11261da177e4SLinus Torvalds 	sock_release(SOCKET_I(inode));
11271da177e4SLinus Torvalds 	return 0;
11281da177e4SLinus Torvalds }
11291da177e4SLinus Torvalds 
11301da177e4SLinus Torvalds /*
11311da177e4SLinus Torvalds  *	Update the socket async list
11321da177e4SLinus Torvalds  *
11331da177e4SLinus Torvalds  *	Fasync_list locking strategy.
11341da177e4SLinus Torvalds  *
11351da177e4SLinus Torvalds  *	1. fasync_list is modified only under process context socket lock
11361da177e4SLinus Torvalds  *	   i.e. under semaphore.
11371da177e4SLinus Torvalds  *	2. fasync_list is used under read_lock(&sk->sk_callback_lock)
1138989a2979SEric Dumazet  *	   or under socket lock
11391da177e4SLinus Torvalds  */
11401da177e4SLinus Torvalds 
11411da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on)
11421da177e4SLinus Torvalds {
1143989a2979SEric Dumazet 	struct socket *sock = filp->private_data;
1144989a2979SEric Dumazet 	struct sock *sk = sock->sk;
1145eaefd110SEric Dumazet 	struct socket_wq *wq;
11461da177e4SLinus Torvalds 
1147989a2979SEric Dumazet 	if (sk == NULL)
11481da177e4SLinus Torvalds 		return -EINVAL;
11491da177e4SLinus Torvalds 
11501da177e4SLinus Torvalds 	lock_sock(sk);
1151eaefd110SEric Dumazet 	wq = rcu_dereference_protected(sock->wq, sock_owned_by_user(sk));
1152eaefd110SEric Dumazet 	fasync_helper(fd, filp, on, &wq->fasync_list);
11531da177e4SLinus Torvalds 
1154eaefd110SEric Dumazet 	if (!wq->fasync_list)
1155bcdce719SEric Dumazet 		sock_reset_flag(sk, SOCK_FASYNC);
1156989a2979SEric Dumazet 	else
1157989a2979SEric Dumazet 		sock_set_flag(sk, SOCK_FASYNC);
11581da177e4SLinus Torvalds 
1159989a2979SEric Dumazet 	release_sock(sk);
11601da177e4SLinus Torvalds 	return 0;
11611da177e4SLinus Torvalds }
11621da177e4SLinus Torvalds 
116343815482SEric Dumazet /* This function may be called only under socket lock or callback_lock or rcu_lock */
11641da177e4SLinus Torvalds 
11651da177e4SLinus Torvalds int sock_wake_async(struct socket *sock, int how, int band)
11661da177e4SLinus Torvalds {
116743815482SEric Dumazet 	struct socket_wq *wq;
116843815482SEric Dumazet 
116943815482SEric Dumazet 	if (!sock)
11701da177e4SLinus Torvalds 		return -1;
117143815482SEric Dumazet 	rcu_read_lock();
117243815482SEric Dumazet 	wq = rcu_dereference(sock->wq);
117343815482SEric Dumazet 	if (!wq || !wq->fasync_list) {
117443815482SEric Dumazet 		rcu_read_unlock();
117543815482SEric Dumazet 		return -1;
117643815482SEric Dumazet 	}
117789bddce5SStephen Hemminger 	switch (how) {
11788d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_WAITD:
11791da177e4SLinus Torvalds 		if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
11801da177e4SLinus Torvalds 			break;
11811da177e4SLinus Torvalds 		goto call_kill;
11828d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_SPACE:
11831da177e4SLinus Torvalds 		if (!test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags))
11841da177e4SLinus Torvalds 			break;
11851da177e4SLinus Torvalds 		/* fall through */
11868d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_IO:
11871da177e4SLinus Torvalds call_kill:
118843815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGIO, band);
11891da177e4SLinus Torvalds 		break;
11908d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_URG:
119143815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGURG, band);
11921da177e4SLinus Torvalds 	}
119343815482SEric Dumazet 	rcu_read_unlock();
11941da177e4SLinus Torvalds 	return 0;
11951da177e4SLinus Torvalds }
1196c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_wake_async);
11971da177e4SLinus Torvalds 
1198721db93aSPavel Emelyanov int __sock_create(struct net *net, int family, int type, int protocol,
119989bddce5SStephen Hemminger 			 struct socket **res, int kern)
12001da177e4SLinus Torvalds {
12011da177e4SLinus Torvalds 	int err;
12021da177e4SLinus Torvalds 	struct socket *sock;
120355737fdaSStephen Hemminger 	const struct net_proto_family *pf;
12041da177e4SLinus Torvalds 
12051da177e4SLinus Torvalds 	/*
12061da177e4SLinus Torvalds 	 *      Check protocol is in range
12071da177e4SLinus Torvalds 	 */
12081da177e4SLinus Torvalds 	if (family < 0 || family >= NPROTO)
12091da177e4SLinus Torvalds 		return -EAFNOSUPPORT;
12101da177e4SLinus Torvalds 	if (type < 0 || type >= SOCK_MAX)
12111da177e4SLinus Torvalds 		return -EINVAL;
12121da177e4SLinus Torvalds 
12131da177e4SLinus Torvalds 	/* Compatibility.
12141da177e4SLinus Torvalds 
12151da177e4SLinus Torvalds 	   This uglymoron is moved from INET layer to here to avoid
12161da177e4SLinus Torvalds 	   deadlock in module load.
12171da177e4SLinus Torvalds 	 */
12181da177e4SLinus Torvalds 	if (family == PF_INET && type == SOCK_PACKET) {
12191da177e4SLinus Torvalds 		static int warned;
12201da177e4SLinus Torvalds 		if (!warned) {
12211da177e4SLinus Torvalds 			warned = 1;
122289bddce5SStephen Hemminger 			printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)\n",
122389bddce5SStephen Hemminger 			       current->comm);
12241da177e4SLinus Torvalds 		}
12251da177e4SLinus Torvalds 		family = PF_PACKET;
12261da177e4SLinus Torvalds 	}
12271da177e4SLinus Torvalds 
12281da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, kern);
12291da177e4SLinus Torvalds 	if (err)
12301da177e4SLinus Torvalds 		return err;
12311da177e4SLinus Torvalds 
123255737fdaSStephen Hemminger 	/*
123355737fdaSStephen Hemminger 	 *	Allocate the socket and allow the family to set things up. if
123455737fdaSStephen Hemminger 	 *	the protocol is 0, the family is instructed to select an appropriate
123555737fdaSStephen Hemminger 	 *	default.
123655737fdaSStephen Hemminger 	 */
123755737fdaSStephen Hemminger 	sock = sock_alloc();
123855737fdaSStephen Hemminger 	if (!sock) {
1239e87cc472SJoe Perches 		net_warn_ratelimited("socket: no more sockets\n");
124055737fdaSStephen Hemminger 		return -ENFILE;	/* Not exactly a match, but its the
124155737fdaSStephen Hemminger 				   closest posix thing */
124255737fdaSStephen Hemminger 	}
124355737fdaSStephen Hemminger 
124455737fdaSStephen Hemminger 	sock->type = type;
124555737fdaSStephen Hemminger 
124695a5afcaSJohannes Berg #ifdef CONFIG_MODULES
12471da177e4SLinus Torvalds 	/* Attempt to load a protocol module if the find failed.
12481da177e4SLinus Torvalds 	 *
12491da177e4SLinus Torvalds 	 * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
12501da177e4SLinus Torvalds 	 * requested real, full-featured networking support upon configuration.
12511da177e4SLinus Torvalds 	 * Otherwise module support will break!
12521da177e4SLinus Torvalds 	 */
1253190683a9SEric Dumazet 	if (rcu_access_pointer(net_families[family]) == NULL)
12541da177e4SLinus Torvalds 		request_module("net-pf-%d", family);
12551da177e4SLinus Torvalds #endif
12561da177e4SLinus Torvalds 
125755737fdaSStephen Hemminger 	rcu_read_lock();
125855737fdaSStephen Hemminger 	pf = rcu_dereference(net_families[family]);
12591da177e4SLinus Torvalds 	err = -EAFNOSUPPORT;
126055737fdaSStephen Hemminger 	if (!pf)
126155737fdaSStephen Hemminger 		goto out_release;
12621da177e4SLinus Torvalds 
12631da177e4SLinus Torvalds 	/*
12641da177e4SLinus Torvalds 	 * We will call the ->create function, that possibly is in a loadable
12651da177e4SLinus Torvalds 	 * module, so we have to bump that loadable module refcnt first.
12661da177e4SLinus Torvalds 	 */
126755737fdaSStephen Hemminger 	if (!try_module_get(pf->owner))
12681da177e4SLinus Torvalds 		goto out_release;
12691da177e4SLinus Torvalds 
127055737fdaSStephen Hemminger 	/* Now protected by module ref count */
127155737fdaSStephen Hemminger 	rcu_read_unlock();
127255737fdaSStephen Hemminger 
12733f378b68SEric Paris 	err = pf->create(net, sock, protocol, kern);
127455737fdaSStephen Hemminger 	if (err < 0)
12751da177e4SLinus Torvalds 		goto out_module_put;
1276a79af59eSFrank Filz 
12771da177e4SLinus Torvalds 	/*
12781da177e4SLinus Torvalds 	 * Now to bump the refcnt of the [loadable] module that owns this
12791da177e4SLinus Torvalds 	 * socket at sock_release time we decrement its refcnt.
12801da177e4SLinus Torvalds 	 */
128155737fdaSStephen Hemminger 	if (!try_module_get(sock->ops->owner))
128255737fdaSStephen Hemminger 		goto out_module_busy;
128355737fdaSStephen Hemminger 
12841da177e4SLinus Torvalds 	/*
12851da177e4SLinus Torvalds 	 * Now that we're done with the ->create function, the [loadable]
12861da177e4SLinus Torvalds 	 * module can have its refcnt decremented
12871da177e4SLinus Torvalds 	 */
128855737fdaSStephen Hemminger 	module_put(pf->owner);
12897420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, kern);
12907420ed23SVenkat Yekkirala 	if (err)
12913b185525SHerbert Xu 		goto out_sock_release;
129255737fdaSStephen Hemminger 	*res = sock;
12931da177e4SLinus Torvalds 
129455737fdaSStephen Hemminger 	return 0;
129555737fdaSStephen Hemminger 
129655737fdaSStephen Hemminger out_module_busy:
129755737fdaSStephen Hemminger 	err = -EAFNOSUPPORT;
12981da177e4SLinus Torvalds out_module_put:
129955737fdaSStephen Hemminger 	sock->ops = NULL;
130055737fdaSStephen Hemminger 	module_put(pf->owner);
130155737fdaSStephen Hemminger out_sock_release:
13021da177e4SLinus Torvalds 	sock_release(sock);
130355737fdaSStephen Hemminger 	return err;
130455737fdaSStephen Hemminger 
130555737fdaSStephen Hemminger out_release:
130655737fdaSStephen Hemminger 	rcu_read_unlock();
130755737fdaSStephen Hemminger 	goto out_sock_release;
13081da177e4SLinus Torvalds }
1309721db93aSPavel Emelyanov EXPORT_SYMBOL(__sock_create);
13101da177e4SLinus Torvalds 
13111da177e4SLinus Torvalds int sock_create(int family, int type, int protocol, struct socket **res)
13121da177e4SLinus Torvalds {
13131b8d7ae4SEric W. Biederman 	return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
13141da177e4SLinus Torvalds }
1315c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create);
13161da177e4SLinus Torvalds 
13171da177e4SLinus Torvalds int sock_create_kern(int family, int type, int protocol, struct socket **res)
13181da177e4SLinus Torvalds {
13191b8d7ae4SEric W. Biederman 	return __sock_create(&init_net, family, type, protocol, res, 1);
13201da177e4SLinus Torvalds }
1321c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_kern);
13221da177e4SLinus Torvalds 
13233e0fa65fSHeiko Carstens SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
13241da177e4SLinus Torvalds {
13251da177e4SLinus Torvalds 	int retval;
13261da177e4SLinus Torvalds 	struct socket *sock;
1327a677a039SUlrich Drepper 	int flags;
1328a677a039SUlrich Drepper 
1329e38b36f3SUlrich Drepper 	/* Check the SOCK_* constants for consistency.  */
1330e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
1331e38b36f3SUlrich Drepper 	BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
1332e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);
1333e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);
1334e38b36f3SUlrich Drepper 
1335a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
133677d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1337a677a039SUlrich Drepper 		return -EINVAL;
1338a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
13391da177e4SLinus Torvalds 
1340aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1341aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1342aaca0bdcSUlrich Drepper 
13431da177e4SLinus Torvalds 	retval = sock_create(family, type, protocol, &sock);
13441da177e4SLinus Torvalds 	if (retval < 0)
13451da177e4SLinus Torvalds 		goto out;
13461da177e4SLinus Torvalds 
134777d27200SUlrich Drepper 	retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
13481da177e4SLinus Torvalds 	if (retval < 0)
13491da177e4SLinus Torvalds 		goto out_release;
13501da177e4SLinus Torvalds 
13511da177e4SLinus Torvalds out:
13521da177e4SLinus Torvalds 	/* It may be already another descriptor 8) Not kernel problem. */
13531da177e4SLinus Torvalds 	return retval;
13541da177e4SLinus Torvalds 
13551da177e4SLinus Torvalds out_release:
13561da177e4SLinus Torvalds 	sock_release(sock);
13571da177e4SLinus Torvalds 	return retval;
13581da177e4SLinus Torvalds }
13591da177e4SLinus Torvalds 
13601da177e4SLinus Torvalds /*
13611da177e4SLinus Torvalds  *	Create a pair of connected sockets.
13621da177e4SLinus Torvalds  */
13631da177e4SLinus Torvalds 
13643e0fa65fSHeiko Carstens SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
13653e0fa65fSHeiko Carstens 		int __user *, usockvec)
13661da177e4SLinus Torvalds {
13671da177e4SLinus Torvalds 	struct socket *sock1, *sock2;
13681da177e4SLinus Torvalds 	int fd1, fd2, err;
1369db349509SAl Viro 	struct file *newfile1, *newfile2;
1370a677a039SUlrich Drepper 	int flags;
1371a677a039SUlrich Drepper 
1372a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
137377d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1374a677a039SUlrich Drepper 		return -EINVAL;
1375a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
13761da177e4SLinus Torvalds 
1377aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1378aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1379aaca0bdcSUlrich Drepper 
13801da177e4SLinus Torvalds 	/*
13811da177e4SLinus Torvalds 	 * Obtain the first socket and check if the underlying protocol
13821da177e4SLinus Torvalds 	 * supports the socketpair call.
13831da177e4SLinus Torvalds 	 */
13841da177e4SLinus Torvalds 
13851da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock1);
13861da177e4SLinus Torvalds 	if (err < 0)
13871da177e4SLinus Torvalds 		goto out;
13881da177e4SLinus Torvalds 
13891da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock2);
13901da177e4SLinus Torvalds 	if (err < 0)
13911da177e4SLinus Torvalds 		goto out_release_1;
13921da177e4SLinus Torvalds 
13931da177e4SLinus Torvalds 	err = sock1->ops->socketpair(sock1, sock2);
13941da177e4SLinus Torvalds 	if (err < 0)
13951da177e4SLinus Torvalds 		goto out_release_both;
13961da177e4SLinus Torvalds 
13977cbe66b6SAl Viro 	fd1 = sock_alloc_file(sock1, &newfile1, flags);
1398bf3c23d1SDavid S. Miller 	if (unlikely(fd1 < 0)) {
1399bf3c23d1SDavid S. Miller 		err = fd1;
14001da177e4SLinus Torvalds 		goto out_release_both;
1401bf3c23d1SDavid S. Miller 	}
14021da177e4SLinus Torvalds 
14037cbe66b6SAl Viro 	fd2 = sock_alloc_file(sock2, &newfile2, flags);
1404198de4d7SAl Viro 	if (unlikely(fd2 < 0)) {
1405198de4d7SAl Viro 		err = fd2;
1406198de4d7SAl Viro 		fput(newfile1);
1407198de4d7SAl Viro 		put_unused_fd(fd1);
1408198de4d7SAl Viro 		sock_release(sock2);
1409198de4d7SAl Viro 		goto out;
1410db349509SAl Viro 	}
1411db349509SAl Viro 
1412157cf649SAl Viro 	audit_fd_pair(fd1, fd2);
1413db349509SAl Viro 	fd_install(fd1, newfile1);
1414db349509SAl Viro 	fd_install(fd2, newfile2);
14151da177e4SLinus Torvalds 	/* fd1 and fd2 may be already another descriptors.
14161da177e4SLinus Torvalds 	 * Not kernel problem.
14171da177e4SLinus Torvalds 	 */
14181da177e4SLinus Torvalds 
14191da177e4SLinus Torvalds 	err = put_user(fd1, &usockvec[0]);
14201da177e4SLinus Torvalds 	if (!err)
14211da177e4SLinus Torvalds 		err = put_user(fd2, &usockvec[1]);
14221da177e4SLinus Torvalds 	if (!err)
14231da177e4SLinus Torvalds 		return 0;
14241da177e4SLinus Torvalds 
14251da177e4SLinus Torvalds 	sys_close(fd2);
14261da177e4SLinus Torvalds 	sys_close(fd1);
14271da177e4SLinus Torvalds 	return err;
14281da177e4SLinus Torvalds 
14291da177e4SLinus Torvalds out_release_both:
14301da177e4SLinus Torvalds 	sock_release(sock2);
14311da177e4SLinus Torvalds out_release_1:
14321da177e4SLinus Torvalds 	sock_release(sock1);
14331da177e4SLinus Torvalds out:
14341da177e4SLinus Torvalds 	return err;
14351da177e4SLinus Torvalds }
14361da177e4SLinus Torvalds 
14371da177e4SLinus Torvalds /*
14381da177e4SLinus Torvalds  *	Bind a name to a socket. Nothing much to do here since it's
14391da177e4SLinus Torvalds  *	the protocol's responsibility to handle the local address.
14401da177e4SLinus Torvalds  *
14411da177e4SLinus Torvalds  *	We move the socket address to kernel space before we call
14421da177e4SLinus Torvalds  *	the protocol layer (having also checked the address is ok).
14431da177e4SLinus Torvalds  */
14441da177e4SLinus Torvalds 
144520f37034SHeiko Carstens SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
14461da177e4SLinus Torvalds {
14471da177e4SLinus Torvalds 	struct socket *sock;
1448230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
14496cb153caSBenjamin LaHaise 	int err, fput_needed;
14501da177e4SLinus Torvalds 
145189bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
145289bddce5SStephen Hemminger 	if (sock) {
145343db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(umyaddr, addrlen, &address);
145489bddce5SStephen Hemminger 		if (err >= 0) {
145589bddce5SStephen Hemminger 			err = security_socket_bind(sock,
1456230b1839SYOSHIFUJI Hideaki 						   (struct sockaddr *)&address,
145789bddce5SStephen Hemminger 						   addrlen);
14586cb153caSBenjamin LaHaise 			if (!err)
14596cb153caSBenjamin LaHaise 				err = sock->ops->bind(sock,
146089bddce5SStephen Hemminger 						      (struct sockaddr *)
1461230b1839SYOSHIFUJI Hideaki 						      &address, addrlen);
14621da177e4SLinus Torvalds 		}
14636cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
14641da177e4SLinus Torvalds 	}
14651da177e4SLinus Torvalds 	return err;
14661da177e4SLinus Torvalds }
14671da177e4SLinus Torvalds 
14681da177e4SLinus Torvalds /*
14691da177e4SLinus Torvalds  *	Perform a listen. Basically, we allow the protocol to do anything
14701da177e4SLinus Torvalds  *	necessary for a listen, and if that works, we mark the socket as
14711da177e4SLinus Torvalds  *	ready for listening.
14721da177e4SLinus Torvalds  */
14731da177e4SLinus Torvalds 
14743e0fa65fSHeiko Carstens SYSCALL_DEFINE2(listen, int, fd, int, backlog)
14751da177e4SLinus Torvalds {
14761da177e4SLinus Torvalds 	struct socket *sock;
14776cb153caSBenjamin LaHaise 	int err, fput_needed;
1478b8e1f9b5SPavel Emelyanov 	int somaxconn;
14791da177e4SLinus Torvalds 
148089bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
148189bddce5SStephen Hemminger 	if (sock) {
14828efa6e93SPavel Emelyanov 		somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
148395c96174SEric Dumazet 		if ((unsigned int)backlog > somaxconn)
1484b8e1f9b5SPavel Emelyanov 			backlog = somaxconn;
14851da177e4SLinus Torvalds 
14861da177e4SLinus Torvalds 		err = security_socket_listen(sock, backlog);
14876cb153caSBenjamin LaHaise 		if (!err)
14881da177e4SLinus Torvalds 			err = sock->ops->listen(sock, backlog);
14896cb153caSBenjamin LaHaise 
14906cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
14911da177e4SLinus Torvalds 	}
14921da177e4SLinus Torvalds 	return err;
14931da177e4SLinus Torvalds }
14941da177e4SLinus Torvalds 
14951da177e4SLinus Torvalds /*
14961da177e4SLinus Torvalds  *	For accept, we attempt to create a new socket, set up the link
14971da177e4SLinus Torvalds  *	with the client, wake up the client, then return the new
14981da177e4SLinus Torvalds  *	connected fd. We collect the address of the connector in kernel
14991da177e4SLinus Torvalds  *	space and move it to user at the very end. This is unclean because
15001da177e4SLinus Torvalds  *	we open the socket then return an error.
15011da177e4SLinus Torvalds  *
15021da177e4SLinus Torvalds  *	1003.1g adds the ability to recvmsg() to query connection pending
15031da177e4SLinus Torvalds  *	status to recvmsg. We need to add that support in a way thats
15041da177e4SLinus Torvalds  *	clean when we restucture accept also.
15051da177e4SLinus Torvalds  */
15061da177e4SLinus Torvalds 
150720f37034SHeiko Carstens SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
150820f37034SHeiko Carstens 		int __user *, upeer_addrlen, int, flags)
15091da177e4SLinus Torvalds {
15101da177e4SLinus Torvalds 	struct socket *sock, *newsock;
151139d8c1b6SDavid S. Miller 	struct file *newfile;
15126cb153caSBenjamin LaHaise 	int err, len, newfd, fput_needed;
1513230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
15141da177e4SLinus Torvalds 
151577d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1516aaca0bdcSUlrich Drepper 		return -EINVAL;
1517aaca0bdcSUlrich Drepper 
1518aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1519aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1520aaca0bdcSUlrich Drepper 
15216cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
15221da177e4SLinus Torvalds 	if (!sock)
15231da177e4SLinus Torvalds 		goto out;
15241da177e4SLinus Torvalds 
15251da177e4SLinus Torvalds 	err = -ENFILE;
1526c6d409cfSEric Dumazet 	newsock = sock_alloc();
1527c6d409cfSEric Dumazet 	if (!newsock)
15281da177e4SLinus Torvalds 		goto out_put;
15291da177e4SLinus Torvalds 
15301da177e4SLinus Torvalds 	newsock->type = sock->type;
15311da177e4SLinus Torvalds 	newsock->ops = sock->ops;
15321da177e4SLinus Torvalds 
15331da177e4SLinus Torvalds 	/*
15341da177e4SLinus Torvalds 	 * We don't need try_module_get here, as the listening socket (sock)
15351da177e4SLinus Torvalds 	 * has the protocol module (sock->ops->owner) held.
15361da177e4SLinus Torvalds 	 */
15371da177e4SLinus Torvalds 	__module_get(newsock->ops->owner);
15381da177e4SLinus Torvalds 
15397cbe66b6SAl Viro 	newfd = sock_alloc_file(newsock, &newfile, flags);
154039d8c1b6SDavid S. Miller 	if (unlikely(newfd < 0)) {
154139d8c1b6SDavid S. Miller 		err = newfd;
15429a1875e6SDavid S. Miller 		sock_release(newsock);
15439a1875e6SDavid S. Miller 		goto out_put;
154439d8c1b6SDavid S. Miller 	}
154539d8c1b6SDavid S. Miller 
1546a79af59eSFrank Filz 	err = security_socket_accept(sock, newsock);
1547a79af59eSFrank Filz 	if (err)
154839d8c1b6SDavid S. Miller 		goto out_fd;
1549a79af59eSFrank Filz 
15501da177e4SLinus Torvalds 	err = sock->ops->accept(sock, newsock, sock->file->f_flags);
15511da177e4SLinus Torvalds 	if (err < 0)
155239d8c1b6SDavid S. Miller 		goto out_fd;
15531da177e4SLinus Torvalds 
15541da177e4SLinus Torvalds 	if (upeer_sockaddr) {
1555230b1839SYOSHIFUJI Hideaki 		if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
155689bddce5SStephen Hemminger 					  &len, 2) < 0) {
15571da177e4SLinus Torvalds 			err = -ECONNABORTED;
155839d8c1b6SDavid S. Miller 			goto out_fd;
15591da177e4SLinus Torvalds 		}
156043db362dSMaciej Żenczykowski 		err = move_addr_to_user(&address,
1561230b1839SYOSHIFUJI Hideaki 					len, upeer_sockaddr, upeer_addrlen);
15621da177e4SLinus Torvalds 		if (err < 0)
156339d8c1b6SDavid S. Miller 			goto out_fd;
15641da177e4SLinus Torvalds 	}
15651da177e4SLinus Torvalds 
15661da177e4SLinus Torvalds 	/* File flags are not inherited via accept() unlike another OSes. */
15671da177e4SLinus Torvalds 
156839d8c1b6SDavid S. Miller 	fd_install(newfd, newfile);
156939d8c1b6SDavid S. Miller 	err = newfd;
15701da177e4SLinus Torvalds 
15711da177e4SLinus Torvalds out_put:
15726cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
15731da177e4SLinus Torvalds out:
15741da177e4SLinus Torvalds 	return err;
157539d8c1b6SDavid S. Miller out_fd:
15769606a216SDavid S. Miller 	fput(newfile);
157739d8c1b6SDavid S. Miller 	put_unused_fd(newfd);
15781da177e4SLinus Torvalds 	goto out_put;
15791da177e4SLinus Torvalds }
15801da177e4SLinus Torvalds 
158120f37034SHeiko Carstens SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,
158220f37034SHeiko Carstens 		int __user *, upeer_addrlen)
1583aaca0bdcSUlrich Drepper {
1584de11defeSUlrich Drepper 	return sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0);
1585aaca0bdcSUlrich Drepper }
1586aaca0bdcSUlrich Drepper 
15871da177e4SLinus Torvalds /*
15881da177e4SLinus Torvalds  *	Attempt to connect to a socket with the server address.  The address
15891da177e4SLinus Torvalds  *	is in user space so we verify it is OK and move it to kernel space.
15901da177e4SLinus Torvalds  *
15911da177e4SLinus Torvalds  *	For 1003.1g we need to add clean support for a bind to AF_UNSPEC to
15921da177e4SLinus Torvalds  *	break bindings
15931da177e4SLinus Torvalds  *
15941da177e4SLinus Torvalds  *	NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and
15951da177e4SLinus Torvalds  *	other SEQPACKET protocols that take time to connect() as it doesn't
15961da177e4SLinus Torvalds  *	include the -EINPROGRESS status for such sockets.
15971da177e4SLinus Torvalds  */
15981da177e4SLinus Torvalds 
159920f37034SHeiko Carstens SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
160020f37034SHeiko Carstens 		int, addrlen)
16011da177e4SLinus Torvalds {
16021da177e4SLinus Torvalds 	struct socket *sock;
1603230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16046cb153caSBenjamin LaHaise 	int err, fput_needed;
16051da177e4SLinus Torvalds 
16066cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
16071da177e4SLinus Torvalds 	if (!sock)
16081da177e4SLinus Torvalds 		goto out;
160943db362dSMaciej Żenczykowski 	err = move_addr_to_kernel(uservaddr, addrlen, &address);
16101da177e4SLinus Torvalds 	if (err < 0)
16111da177e4SLinus Torvalds 		goto out_put;
16121da177e4SLinus Torvalds 
161389bddce5SStephen Hemminger 	err =
1614230b1839SYOSHIFUJI Hideaki 	    security_socket_connect(sock, (struct sockaddr *)&address, addrlen);
16151da177e4SLinus Torvalds 	if (err)
16161da177e4SLinus Torvalds 		goto out_put;
16171da177e4SLinus Torvalds 
1618230b1839SYOSHIFUJI Hideaki 	err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,
16191da177e4SLinus Torvalds 				 sock->file->f_flags);
16201da177e4SLinus Torvalds out_put:
16216cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
16221da177e4SLinus Torvalds out:
16231da177e4SLinus Torvalds 	return err;
16241da177e4SLinus Torvalds }
16251da177e4SLinus Torvalds 
16261da177e4SLinus Torvalds /*
16271da177e4SLinus Torvalds  *	Get the local address ('name') of a socket object. Move the obtained
16281da177e4SLinus Torvalds  *	name to user space.
16291da177e4SLinus Torvalds  */
16301da177e4SLinus Torvalds 
163120f37034SHeiko Carstens SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
163220f37034SHeiko Carstens 		int __user *, usockaddr_len)
16331da177e4SLinus Torvalds {
16341da177e4SLinus Torvalds 	struct socket *sock;
1635230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16366cb153caSBenjamin LaHaise 	int len, err, fput_needed;
16371da177e4SLinus Torvalds 
16386cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
16391da177e4SLinus Torvalds 	if (!sock)
16401da177e4SLinus Torvalds 		goto out;
16411da177e4SLinus Torvalds 
16421da177e4SLinus Torvalds 	err = security_socket_getsockname(sock);
16431da177e4SLinus Torvalds 	if (err)
16441da177e4SLinus Torvalds 		goto out_put;
16451da177e4SLinus Torvalds 
1646230b1839SYOSHIFUJI Hideaki 	err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0);
16471da177e4SLinus Torvalds 	if (err)
16481da177e4SLinus Torvalds 		goto out_put;
164943db362dSMaciej Żenczykowski 	err = move_addr_to_user(&address, len, usockaddr, usockaddr_len);
16501da177e4SLinus Torvalds 
16511da177e4SLinus Torvalds out_put:
16526cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
16531da177e4SLinus Torvalds out:
16541da177e4SLinus Torvalds 	return err;
16551da177e4SLinus Torvalds }
16561da177e4SLinus Torvalds 
16571da177e4SLinus Torvalds /*
16581da177e4SLinus Torvalds  *	Get the remote address ('name') of a socket object. Move the obtained
16591da177e4SLinus Torvalds  *	name to user space.
16601da177e4SLinus Torvalds  */
16611da177e4SLinus Torvalds 
166220f37034SHeiko Carstens SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
166320f37034SHeiko Carstens 		int __user *, usockaddr_len)
16641da177e4SLinus Torvalds {
16651da177e4SLinus Torvalds 	struct socket *sock;
1666230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16676cb153caSBenjamin LaHaise 	int len, err, fput_needed;
16681da177e4SLinus Torvalds 
166989bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
167089bddce5SStephen Hemminger 	if (sock != NULL) {
16711da177e4SLinus Torvalds 		err = security_socket_getpeername(sock);
16721da177e4SLinus Torvalds 		if (err) {
16736cb153caSBenjamin LaHaise 			fput_light(sock->file, fput_needed);
16741da177e4SLinus Torvalds 			return err;
16751da177e4SLinus Torvalds 		}
16761da177e4SLinus Torvalds 
167789bddce5SStephen Hemminger 		err =
1678230b1839SYOSHIFUJI Hideaki 		    sock->ops->getname(sock, (struct sockaddr *)&address, &len,
167989bddce5SStephen Hemminger 				       1);
16801da177e4SLinus Torvalds 		if (!err)
168143db362dSMaciej Żenczykowski 			err = move_addr_to_user(&address, len, usockaddr,
168289bddce5SStephen Hemminger 						usockaddr_len);
16836cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
16841da177e4SLinus Torvalds 	}
16851da177e4SLinus Torvalds 	return err;
16861da177e4SLinus Torvalds }
16871da177e4SLinus Torvalds 
16881da177e4SLinus Torvalds /*
16891da177e4SLinus Torvalds  *	Send a datagram to a given address. We move the address into kernel
16901da177e4SLinus Torvalds  *	space and check the user space data area is readable before invoking
16911da177e4SLinus Torvalds  *	the protocol.
16921da177e4SLinus Torvalds  */
16931da177e4SLinus Torvalds 
16943e0fa65fSHeiko Carstens SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
169595c96174SEric Dumazet 		unsigned int, flags, struct sockaddr __user *, addr,
16963e0fa65fSHeiko Carstens 		int, addr_len)
16971da177e4SLinus Torvalds {
16981da177e4SLinus Torvalds 	struct socket *sock;
1699230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
17001da177e4SLinus Torvalds 	int err;
17011da177e4SLinus Torvalds 	struct msghdr msg;
17021da177e4SLinus Torvalds 	struct iovec iov;
17036cb153caSBenjamin LaHaise 	int fput_needed;
17041da177e4SLinus Torvalds 
1705253eacc0SLinus Torvalds 	if (len > INT_MAX)
1706253eacc0SLinus Torvalds 		len = INT_MAX;
1707de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1708de0fa95cSPavel Emelyanov 	if (!sock)
17094387ff75SDavid S. Miller 		goto out;
17106cb153caSBenjamin LaHaise 
17111da177e4SLinus Torvalds 	iov.iov_base = buff;
17121da177e4SLinus Torvalds 	iov.iov_len = len;
17131da177e4SLinus Torvalds 	msg.msg_name = NULL;
17141da177e4SLinus Torvalds 	msg.msg_iov = &iov;
17151da177e4SLinus Torvalds 	msg.msg_iovlen = 1;
17161da177e4SLinus Torvalds 	msg.msg_control = NULL;
17171da177e4SLinus Torvalds 	msg.msg_controllen = 0;
17181da177e4SLinus Torvalds 	msg.msg_namelen = 0;
17196cb153caSBenjamin LaHaise 	if (addr) {
172043db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(addr, addr_len, &address);
17211da177e4SLinus Torvalds 		if (err < 0)
17221da177e4SLinus Torvalds 			goto out_put;
1723230b1839SYOSHIFUJI Hideaki 		msg.msg_name = (struct sockaddr *)&address;
17241da177e4SLinus Torvalds 		msg.msg_namelen = addr_len;
17251da177e4SLinus Torvalds 	}
17261da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
17271da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
17281da177e4SLinus Torvalds 	msg.msg_flags = flags;
17291da177e4SLinus Torvalds 	err = sock_sendmsg(sock, &msg, len);
17301da177e4SLinus Torvalds 
17311da177e4SLinus Torvalds out_put:
1732de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
17334387ff75SDavid S. Miller out:
17341da177e4SLinus Torvalds 	return err;
17351da177e4SLinus Torvalds }
17361da177e4SLinus Torvalds 
17371da177e4SLinus Torvalds /*
17381da177e4SLinus Torvalds  *	Send a datagram down a socket.
17391da177e4SLinus Torvalds  */
17401da177e4SLinus Torvalds 
17413e0fa65fSHeiko Carstens SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len,
174295c96174SEric Dumazet 		unsigned int, flags)
17431da177e4SLinus Torvalds {
17441da177e4SLinus Torvalds 	return sys_sendto(fd, buff, len, flags, NULL, 0);
17451da177e4SLinus Torvalds }
17461da177e4SLinus Torvalds 
17471da177e4SLinus Torvalds /*
17481da177e4SLinus Torvalds  *	Receive a frame from the socket and optionally record the address of the
17491da177e4SLinus Torvalds  *	sender. We verify the buffers are writable and if needed move the
17501da177e4SLinus Torvalds  *	sender address from kernel to user space.
17511da177e4SLinus Torvalds  */
17521da177e4SLinus Torvalds 
17533e0fa65fSHeiko Carstens SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
175495c96174SEric Dumazet 		unsigned int, flags, struct sockaddr __user *, addr,
17553e0fa65fSHeiko Carstens 		int __user *, addr_len)
17561da177e4SLinus Torvalds {
17571da177e4SLinus Torvalds 	struct socket *sock;
17581da177e4SLinus Torvalds 	struct iovec iov;
17591da177e4SLinus Torvalds 	struct msghdr msg;
1760230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
17611da177e4SLinus Torvalds 	int err, err2;
17626cb153caSBenjamin LaHaise 	int fput_needed;
17631da177e4SLinus Torvalds 
1764253eacc0SLinus Torvalds 	if (size > INT_MAX)
1765253eacc0SLinus Torvalds 		size = INT_MAX;
1766de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
17671da177e4SLinus Torvalds 	if (!sock)
1768de0fa95cSPavel Emelyanov 		goto out;
17691da177e4SLinus Torvalds 
17701da177e4SLinus Torvalds 	msg.msg_control = NULL;
17711da177e4SLinus Torvalds 	msg.msg_controllen = 0;
17721da177e4SLinus Torvalds 	msg.msg_iovlen = 1;
17731da177e4SLinus Torvalds 	msg.msg_iov = &iov;
17741da177e4SLinus Torvalds 	iov.iov_len = size;
17751da177e4SLinus Torvalds 	iov.iov_base = ubuf;
1776230b1839SYOSHIFUJI Hideaki 	msg.msg_name = (struct sockaddr *)&address;
1777230b1839SYOSHIFUJI Hideaki 	msg.msg_namelen = sizeof(address);
17781da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
17791da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
17801da177e4SLinus Torvalds 	err = sock_recvmsg(sock, &msg, size, flags);
17811da177e4SLinus Torvalds 
178289bddce5SStephen Hemminger 	if (err >= 0 && addr != NULL) {
178343db362dSMaciej Żenczykowski 		err2 = move_addr_to_user(&address,
1784230b1839SYOSHIFUJI Hideaki 					 msg.msg_namelen, addr, addr_len);
17851da177e4SLinus Torvalds 		if (err2 < 0)
17861da177e4SLinus Torvalds 			err = err2;
17871da177e4SLinus Torvalds 	}
1788de0fa95cSPavel Emelyanov 
1789de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
17904387ff75SDavid S. Miller out:
17911da177e4SLinus Torvalds 	return err;
17921da177e4SLinus Torvalds }
17931da177e4SLinus Torvalds 
17941da177e4SLinus Torvalds /*
17951da177e4SLinus Torvalds  *	Receive a datagram from a socket.
17961da177e4SLinus Torvalds  */
17971da177e4SLinus Torvalds 
179889bddce5SStephen Hemminger asmlinkage long sys_recv(int fd, void __user *ubuf, size_t size,
179995c96174SEric Dumazet 			 unsigned int flags)
18001da177e4SLinus Torvalds {
18011da177e4SLinus Torvalds 	return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL);
18021da177e4SLinus Torvalds }
18031da177e4SLinus Torvalds 
18041da177e4SLinus Torvalds /*
18051da177e4SLinus Torvalds  *	Set a socket option. Because we don't know the option lengths we have
18061da177e4SLinus Torvalds  *	to pass the user mode parameter for the protocols to sort out.
18071da177e4SLinus Torvalds  */
18081da177e4SLinus Torvalds 
180920f37034SHeiko Carstens SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
181020f37034SHeiko Carstens 		char __user *, optval, int, optlen)
18111da177e4SLinus Torvalds {
18126cb153caSBenjamin LaHaise 	int err, fput_needed;
18131da177e4SLinus Torvalds 	struct socket *sock;
18141da177e4SLinus Torvalds 
18151da177e4SLinus Torvalds 	if (optlen < 0)
18161da177e4SLinus Torvalds 		return -EINVAL;
18171da177e4SLinus Torvalds 
181889bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
181989bddce5SStephen Hemminger 	if (sock != NULL) {
18201da177e4SLinus Torvalds 		err = security_socket_setsockopt(sock, level, optname);
18216cb153caSBenjamin LaHaise 		if (err)
18226cb153caSBenjamin LaHaise 			goto out_put;
18231da177e4SLinus Torvalds 
18241da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
182589bddce5SStephen Hemminger 			err =
182689bddce5SStephen Hemminger 			    sock_setsockopt(sock, level, optname, optval,
182789bddce5SStephen Hemminger 					    optlen);
18281da177e4SLinus Torvalds 		else
182989bddce5SStephen Hemminger 			err =
183089bddce5SStephen Hemminger 			    sock->ops->setsockopt(sock, level, optname, optval,
183189bddce5SStephen Hemminger 						  optlen);
18326cb153caSBenjamin LaHaise out_put:
18336cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
18341da177e4SLinus Torvalds 	}
18351da177e4SLinus Torvalds 	return err;
18361da177e4SLinus Torvalds }
18371da177e4SLinus Torvalds 
18381da177e4SLinus Torvalds /*
18391da177e4SLinus Torvalds  *	Get a socket option. Because we don't know the option lengths we have
18401da177e4SLinus Torvalds  *	to pass a user mode parameter for the protocols to sort out.
18411da177e4SLinus Torvalds  */
18421da177e4SLinus Torvalds 
184320f37034SHeiko Carstens SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
184420f37034SHeiko Carstens 		char __user *, optval, int __user *, optlen)
18451da177e4SLinus Torvalds {
18466cb153caSBenjamin LaHaise 	int err, fput_needed;
18471da177e4SLinus Torvalds 	struct socket *sock;
18481da177e4SLinus Torvalds 
184989bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
185089bddce5SStephen Hemminger 	if (sock != NULL) {
18516cb153caSBenjamin LaHaise 		err = security_socket_getsockopt(sock, level, optname);
18526cb153caSBenjamin LaHaise 		if (err)
18536cb153caSBenjamin LaHaise 			goto out_put;
18541da177e4SLinus Torvalds 
18551da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
185689bddce5SStephen Hemminger 			err =
185789bddce5SStephen Hemminger 			    sock_getsockopt(sock, level, optname, optval,
185889bddce5SStephen Hemminger 					    optlen);
18591da177e4SLinus Torvalds 		else
186089bddce5SStephen Hemminger 			err =
186189bddce5SStephen Hemminger 			    sock->ops->getsockopt(sock, level, optname, optval,
186289bddce5SStephen Hemminger 						  optlen);
18636cb153caSBenjamin LaHaise out_put:
18646cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
18651da177e4SLinus Torvalds 	}
18661da177e4SLinus Torvalds 	return err;
18671da177e4SLinus Torvalds }
18681da177e4SLinus Torvalds 
18691da177e4SLinus Torvalds /*
18701da177e4SLinus Torvalds  *	Shutdown a socket.
18711da177e4SLinus Torvalds  */
18721da177e4SLinus Torvalds 
1873754fe8d2SHeiko Carstens SYSCALL_DEFINE2(shutdown, int, fd, int, how)
18741da177e4SLinus Torvalds {
18756cb153caSBenjamin LaHaise 	int err, fput_needed;
18761da177e4SLinus Torvalds 	struct socket *sock;
18771da177e4SLinus Torvalds 
187889bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
187989bddce5SStephen Hemminger 	if (sock != NULL) {
18801da177e4SLinus Torvalds 		err = security_socket_shutdown(sock, how);
18816cb153caSBenjamin LaHaise 		if (!err)
18821da177e4SLinus Torvalds 			err = sock->ops->shutdown(sock, how);
18836cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
18841da177e4SLinus Torvalds 	}
18851da177e4SLinus Torvalds 	return err;
18861da177e4SLinus Torvalds }
18871da177e4SLinus Torvalds 
18881da177e4SLinus Torvalds /* A couple of helpful macros for getting the address of the 32/64 bit
18891da177e4SLinus Torvalds  * fields which are the same type (int / unsigned) on our platforms.
18901da177e4SLinus Torvalds  */
18911da177e4SLinus Torvalds #define COMPAT_MSG(msg, member)	((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member)
18921da177e4SLinus Torvalds #define COMPAT_NAMELEN(msg)	COMPAT_MSG(msg, msg_namelen)
18931da177e4SLinus Torvalds #define COMPAT_FLAGS(msg)	COMPAT_MSG(msg, msg_flags)
18941da177e4SLinus Torvalds 
1895c71d8ebeSTetsuo Handa struct used_address {
1896c71d8ebeSTetsuo Handa 	struct sockaddr_storage name;
1897c71d8ebeSTetsuo Handa 	unsigned int name_len;
1898c71d8ebeSTetsuo Handa };
1899c71d8ebeSTetsuo Handa 
1900228e548eSAnton Blanchard static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
190195c96174SEric Dumazet 			 struct msghdr *msg_sys, unsigned int flags,
1902c71d8ebeSTetsuo Handa 			 struct used_address *used_address)
19031da177e4SLinus Torvalds {
190489bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
190589bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
1906230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
19071da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
1908b9d717a7SAlex Williamson 	unsigned char ctl[sizeof(struct cmsghdr) + 20]
1909b9d717a7SAlex Williamson 	    __attribute__ ((aligned(sizeof(__kernel_size_t))));
1910b9d717a7SAlex Williamson 	/* 20 is size of ipv6_pktinfo */
19111da177e4SLinus Torvalds 	unsigned char *ctl_buf = ctl;
1912a74e9106SEric Dumazet 	int err, ctl_len, total_len;
19131da177e4SLinus Torvalds 
19141da177e4SLinus Torvalds 	err = -EFAULT;
19151da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
1916228e548eSAnton Blanchard 		if (get_compat_msghdr(msg_sys, msg_compat))
19171da177e4SLinus Torvalds 			return -EFAULT;
1918228e548eSAnton Blanchard 	} else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr)))
19191da177e4SLinus Torvalds 		return -EFAULT;
19201da177e4SLinus Torvalds 
1921a74e9106SEric Dumazet 	if (msg_sys->msg_iovlen > UIO_FASTIOV) {
19221da177e4SLinus Torvalds 		err = -EMSGSIZE;
1923228e548eSAnton Blanchard 		if (msg_sys->msg_iovlen > UIO_MAXIOV)
1924228e548eSAnton Blanchard 			goto out;
19251da177e4SLinus Torvalds 		err = -ENOMEM;
1926a74e9106SEric Dumazet 		iov = kmalloc(msg_sys->msg_iovlen * sizeof(struct iovec),
1927a74e9106SEric Dumazet 			      GFP_KERNEL);
19281da177e4SLinus Torvalds 		if (!iov)
1929228e548eSAnton Blanchard 			goto out;
19301da177e4SLinus Torvalds 	}
19311da177e4SLinus Torvalds 
19321da177e4SLinus Torvalds 	/* This will also move the address data into kernel space */
19331da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
193443db362dSMaciej Żenczykowski 		err = verify_compat_iovec(msg_sys, iov, &address, VERIFY_READ);
19351da177e4SLinus Torvalds 	} else
193643db362dSMaciej Żenczykowski 		err = verify_iovec(msg_sys, iov, &address, VERIFY_READ);
19371da177e4SLinus Torvalds 	if (err < 0)
19381da177e4SLinus Torvalds 		goto out_freeiov;
19391da177e4SLinus Torvalds 	total_len = err;
19401da177e4SLinus Torvalds 
19411da177e4SLinus Torvalds 	err = -ENOBUFS;
19421da177e4SLinus Torvalds 
1943228e548eSAnton Blanchard 	if (msg_sys->msg_controllen > INT_MAX)
19441da177e4SLinus Torvalds 		goto out_freeiov;
1945228e548eSAnton Blanchard 	ctl_len = msg_sys->msg_controllen;
19461da177e4SLinus Torvalds 	if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
194789bddce5SStephen Hemminger 		err =
1948228e548eSAnton Blanchard 		    cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl,
194989bddce5SStephen Hemminger 						     sizeof(ctl));
19501da177e4SLinus Torvalds 		if (err)
19511da177e4SLinus Torvalds 			goto out_freeiov;
1952228e548eSAnton Blanchard 		ctl_buf = msg_sys->msg_control;
1953228e548eSAnton Blanchard 		ctl_len = msg_sys->msg_controllen;
19541da177e4SLinus Torvalds 	} else if (ctl_len) {
195589bddce5SStephen Hemminger 		if (ctl_len > sizeof(ctl)) {
19561da177e4SLinus Torvalds 			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
19571da177e4SLinus Torvalds 			if (ctl_buf == NULL)
19581da177e4SLinus Torvalds 				goto out_freeiov;
19591da177e4SLinus Torvalds 		}
19601da177e4SLinus Torvalds 		err = -EFAULT;
19611da177e4SLinus Torvalds 		/*
1962228e548eSAnton Blanchard 		 * Careful! Before this, msg_sys->msg_control contains a user pointer.
19631da177e4SLinus Torvalds 		 * Afterwards, it will be a kernel pointer. Thus the compiler-assisted
19641da177e4SLinus Torvalds 		 * checking falls down on this.
19651da177e4SLinus Torvalds 		 */
1966fb8621bbSNamhyung Kim 		if (copy_from_user(ctl_buf,
1967228e548eSAnton Blanchard 				   (void __user __force *)msg_sys->msg_control,
196889bddce5SStephen Hemminger 				   ctl_len))
19691da177e4SLinus Torvalds 			goto out_freectl;
1970228e548eSAnton Blanchard 		msg_sys->msg_control = ctl_buf;
19711da177e4SLinus Torvalds 	}
1972228e548eSAnton Blanchard 	msg_sys->msg_flags = flags;
19731da177e4SLinus Torvalds 
19741da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
1975228e548eSAnton Blanchard 		msg_sys->msg_flags |= MSG_DONTWAIT;
1976c71d8ebeSTetsuo Handa 	/*
1977c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and current destination address is same as
1978c71d8ebeSTetsuo Handa 	 * previously succeeded address, omit asking LSM's decision.
1979c71d8ebeSTetsuo Handa 	 * used_address->name_len is initialized to UINT_MAX so that the first
1980c71d8ebeSTetsuo Handa 	 * destination address never matches.
1981c71d8ebeSTetsuo Handa 	 */
1982bc909d9dSMathieu Desnoyers 	if (used_address && msg_sys->msg_name &&
1983bc909d9dSMathieu Desnoyers 	    used_address->name_len == msg_sys->msg_namelen &&
1984bc909d9dSMathieu Desnoyers 	    !memcmp(&used_address->name, msg_sys->msg_name,
1985c71d8ebeSTetsuo Handa 		    used_address->name_len)) {
1986c71d8ebeSTetsuo Handa 		err = sock_sendmsg_nosec(sock, msg_sys, total_len);
1987c71d8ebeSTetsuo Handa 		goto out_freectl;
1988c71d8ebeSTetsuo Handa 	}
1989c71d8ebeSTetsuo Handa 	err = sock_sendmsg(sock, msg_sys, total_len);
1990c71d8ebeSTetsuo Handa 	/*
1991c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and sending to current destination address was
1992c71d8ebeSTetsuo Handa 	 * successful, remember it.
1993c71d8ebeSTetsuo Handa 	 */
1994c71d8ebeSTetsuo Handa 	if (used_address && err >= 0) {
1995c71d8ebeSTetsuo Handa 		used_address->name_len = msg_sys->msg_namelen;
1996bc909d9dSMathieu Desnoyers 		if (msg_sys->msg_name)
1997bc909d9dSMathieu Desnoyers 			memcpy(&used_address->name, msg_sys->msg_name,
1998c71d8ebeSTetsuo Handa 			       used_address->name_len);
1999c71d8ebeSTetsuo Handa 	}
20001da177e4SLinus Torvalds 
20011da177e4SLinus Torvalds out_freectl:
20021da177e4SLinus Torvalds 	if (ctl_buf != ctl)
20031da177e4SLinus Torvalds 		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
20041da177e4SLinus Torvalds out_freeiov:
20051da177e4SLinus Torvalds 	if (iov != iovstack)
2006a74e9106SEric Dumazet 		kfree(iov);
2007228e548eSAnton Blanchard out:
2008228e548eSAnton Blanchard 	return err;
2009228e548eSAnton Blanchard }
2010228e548eSAnton Blanchard 
2011228e548eSAnton Blanchard /*
2012228e548eSAnton Blanchard  *	BSD sendmsg interface
2013228e548eSAnton Blanchard  */
2014228e548eSAnton Blanchard 
201595c96174SEric Dumazet SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned int, flags)
2016228e548eSAnton Blanchard {
2017228e548eSAnton Blanchard 	int fput_needed, err;
2018228e548eSAnton Blanchard 	struct msghdr msg_sys;
2019228e548eSAnton Blanchard 	struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed);
2020228e548eSAnton Blanchard 
2021228e548eSAnton Blanchard 	if (!sock)
2022228e548eSAnton Blanchard 		goto out;
2023228e548eSAnton Blanchard 
2024c71d8ebeSTetsuo Handa 	err = __sys_sendmsg(sock, msg, &msg_sys, flags, NULL);
2025228e548eSAnton Blanchard 
20266cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
20271da177e4SLinus Torvalds out:
20281da177e4SLinus Torvalds 	return err;
20291da177e4SLinus Torvalds }
20301da177e4SLinus Torvalds 
2031228e548eSAnton Blanchard /*
2032228e548eSAnton Blanchard  *	Linux sendmmsg interface
2033228e548eSAnton Blanchard  */
2034228e548eSAnton Blanchard 
2035228e548eSAnton Blanchard int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2036228e548eSAnton Blanchard 		   unsigned int flags)
2037228e548eSAnton Blanchard {
2038228e548eSAnton Blanchard 	int fput_needed, err, datagrams;
2039228e548eSAnton Blanchard 	struct socket *sock;
2040228e548eSAnton Blanchard 	struct mmsghdr __user *entry;
2041228e548eSAnton Blanchard 	struct compat_mmsghdr __user *compat_entry;
2042228e548eSAnton Blanchard 	struct msghdr msg_sys;
2043c71d8ebeSTetsuo Handa 	struct used_address used_address;
2044228e548eSAnton Blanchard 
204598382f41SAnton Blanchard 	if (vlen > UIO_MAXIOV)
204698382f41SAnton Blanchard 		vlen = UIO_MAXIOV;
2047228e548eSAnton Blanchard 
2048228e548eSAnton Blanchard 	datagrams = 0;
2049228e548eSAnton Blanchard 
2050228e548eSAnton Blanchard 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2051228e548eSAnton Blanchard 	if (!sock)
2052228e548eSAnton Blanchard 		return err;
2053228e548eSAnton Blanchard 
2054c71d8ebeSTetsuo Handa 	used_address.name_len = UINT_MAX;
2055228e548eSAnton Blanchard 	entry = mmsg;
2056228e548eSAnton Blanchard 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2057728ffb86SAnton Blanchard 	err = 0;
2058228e548eSAnton Blanchard 
2059228e548eSAnton Blanchard 	while (datagrams < vlen) {
2060228e548eSAnton Blanchard 		if (MSG_CMSG_COMPAT & flags) {
2061228e548eSAnton Blanchard 			err = __sys_sendmsg(sock, (struct msghdr __user *)compat_entry,
2062c71d8ebeSTetsuo Handa 					    &msg_sys, flags, &used_address);
2063228e548eSAnton Blanchard 			if (err < 0)
2064228e548eSAnton Blanchard 				break;
2065228e548eSAnton Blanchard 			err = __put_user(err, &compat_entry->msg_len);
2066228e548eSAnton Blanchard 			++compat_entry;
2067228e548eSAnton Blanchard 		} else {
2068228e548eSAnton Blanchard 			err = __sys_sendmsg(sock, (struct msghdr __user *)entry,
2069c71d8ebeSTetsuo Handa 					    &msg_sys, flags, &used_address);
2070228e548eSAnton Blanchard 			if (err < 0)
2071228e548eSAnton Blanchard 				break;
2072228e548eSAnton Blanchard 			err = put_user(err, &entry->msg_len);
2073228e548eSAnton Blanchard 			++entry;
2074228e548eSAnton Blanchard 		}
2075228e548eSAnton Blanchard 
2076228e548eSAnton Blanchard 		if (err)
2077228e548eSAnton Blanchard 			break;
2078228e548eSAnton Blanchard 		++datagrams;
2079228e548eSAnton Blanchard 	}
2080228e548eSAnton Blanchard 
2081228e548eSAnton Blanchard 	fput_light(sock->file, fput_needed);
2082228e548eSAnton Blanchard 
2083728ffb86SAnton Blanchard 	/* We only return an error if no datagrams were able to be sent */
2084728ffb86SAnton Blanchard 	if (datagrams != 0)
2085228e548eSAnton Blanchard 		return datagrams;
2086228e548eSAnton Blanchard 
2087228e548eSAnton Blanchard 	return err;
2088228e548eSAnton Blanchard }
2089228e548eSAnton Blanchard 
2090228e548eSAnton Blanchard SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
2091228e548eSAnton Blanchard 		unsigned int, vlen, unsigned int, flags)
2092228e548eSAnton Blanchard {
2093228e548eSAnton Blanchard 	return __sys_sendmmsg(fd, mmsg, vlen, flags);
2094228e548eSAnton Blanchard }
2095228e548eSAnton Blanchard 
2096a2e27255SArnaldo Carvalho de Melo static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
209795c96174SEric Dumazet 			 struct msghdr *msg_sys, unsigned int flags, int nosec)
20981da177e4SLinus Torvalds {
209989bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
210089bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
21011da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV];
21021da177e4SLinus Torvalds 	struct iovec *iov = iovstack;
21031da177e4SLinus Torvalds 	unsigned long cmsg_ptr;
2104a74e9106SEric Dumazet 	int err, total_len, len;
21051da177e4SLinus Torvalds 
21061da177e4SLinus Torvalds 	/* kernel mode address */
2107230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage addr;
21081da177e4SLinus Torvalds 
21091da177e4SLinus Torvalds 	/* user mode address pointers */
21101da177e4SLinus Torvalds 	struct sockaddr __user *uaddr;
21111da177e4SLinus Torvalds 	int __user *uaddr_len;
21121da177e4SLinus Torvalds 
21131da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
2114a2e27255SArnaldo Carvalho de Melo 		if (get_compat_msghdr(msg_sys, msg_compat))
21151da177e4SLinus Torvalds 			return -EFAULT;
2116c6d409cfSEric Dumazet 	} else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr)))
21171da177e4SLinus Torvalds 		return -EFAULT;
21181da177e4SLinus Torvalds 
2119a74e9106SEric Dumazet 	if (msg_sys->msg_iovlen > UIO_FASTIOV) {
21201da177e4SLinus Torvalds 		err = -EMSGSIZE;
2121a2e27255SArnaldo Carvalho de Melo 		if (msg_sys->msg_iovlen > UIO_MAXIOV)
2122a2e27255SArnaldo Carvalho de Melo 			goto out;
21231da177e4SLinus Torvalds 		err = -ENOMEM;
2124a74e9106SEric Dumazet 		iov = kmalloc(msg_sys->msg_iovlen * sizeof(struct iovec),
2125a74e9106SEric Dumazet 			      GFP_KERNEL);
21261da177e4SLinus Torvalds 		if (!iov)
2127a2e27255SArnaldo Carvalho de Melo 			goto out;
21281da177e4SLinus Torvalds 	}
21291da177e4SLinus Torvalds 
21301da177e4SLinus Torvalds 	/*
21311da177e4SLinus Torvalds 	 *      Save the user-mode address (verify_iovec will change the
21321da177e4SLinus Torvalds 	 *      kernel msghdr to use the kernel address space)
21331da177e4SLinus Torvalds 	 */
21341da177e4SLinus Torvalds 
2135a2e27255SArnaldo Carvalho de Melo 	uaddr = (__force void __user *)msg_sys->msg_name;
21361da177e4SLinus Torvalds 	uaddr_len = COMPAT_NAMELEN(msg);
21371da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
213843db362dSMaciej Żenczykowski 		err = verify_compat_iovec(msg_sys, iov, &addr, VERIFY_WRITE);
21391da177e4SLinus Torvalds 	} else
214043db362dSMaciej Żenczykowski 		err = verify_iovec(msg_sys, iov, &addr, VERIFY_WRITE);
21411da177e4SLinus Torvalds 	if (err < 0)
21421da177e4SLinus Torvalds 		goto out_freeiov;
21431da177e4SLinus Torvalds 	total_len = err;
21441da177e4SLinus Torvalds 
2145a2e27255SArnaldo Carvalho de Melo 	cmsg_ptr = (unsigned long)msg_sys->msg_control;
2146a2e27255SArnaldo Carvalho de Melo 	msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
21471da177e4SLinus Torvalds 
21481da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
21491da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
2150a2e27255SArnaldo Carvalho de Melo 	err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys,
2151a2e27255SArnaldo Carvalho de Melo 							  total_len, flags);
21521da177e4SLinus Torvalds 	if (err < 0)
21531da177e4SLinus Torvalds 		goto out_freeiov;
21541da177e4SLinus Torvalds 	len = err;
21551da177e4SLinus Torvalds 
21561da177e4SLinus Torvalds 	if (uaddr != NULL) {
215743db362dSMaciej Żenczykowski 		err = move_addr_to_user(&addr,
2158a2e27255SArnaldo Carvalho de Melo 					msg_sys->msg_namelen, uaddr,
215989bddce5SStephen Hemminger 					uaddr_len);
21601da177e4SLinus Torvalds 		if (err < 0)
21611da177e4SLinus Torvalds 			goto out_freeiov;
21621da177e4SLinus Torvalds 	}
2163a2e27255SArnaldo Carvalho de Melo 	err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
216437f7f421SDavid S. Miller 			 COMPAT_FLAGS(msg));
21651da177e4SLinus Torvalds 	if (err)
21661da177e4SLinus Torvalds 		goto out_freeiov;
21671da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags)
2168a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
21691da177e4SLinus Torvalds 				 &msg_compat->msg_controllen);
21701da177e4SLinus Torvalds 	else
2171a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
21721da177e4SLinus Torvalds 				 &msg->msg_controllen);
21731da177e4SLinus Torvalds 	if (err)
21741da177e4SLinus Torvalds 		goto out_freeiov;
21751da177e4SLinus Torvalds 	err = len;
21761da177e4SLinus Torvalds 
21771da177e4SLinus Torvalds out_freeiov:
21781da177e4SLinus Torvalds 	if (iov != iovstack)
2179a74e9106SEric Dumazet 		kfree(iov);
2180a2e27255SArnaldo Carvalho de Melo out:
2181a2e27255SArnaldo Carvalho de Melo 	return err;
2182a2e27255SArnaldo Carvalho de Melo }
2183a2e27255SArnaldo Carvalho de Melo 
2184a2e27255SArnaldo Carvalho de Melo /*
2185a2e27255SArnaldo Carvalho de Melo  *	BSD recvmsg interface
2186a2e27255SArnaldo Carvalho de Melo  */
2187a2e27255SArnaldo Carvalho de Melo 
2188a2e27255SArnaldo Carvalho de Melo SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg,
2189a2e27255SArnaldo Carvalho de Melo 		unsigned int, flags)
2190a2e27255SArnaldo Carvalho de Melo {
2191a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err;
2192a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
2193a2e27255SArnaldo Carvalho de Melo 	struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed);
2194a2e27255SArnaldo Carvalho de Melo 
2195a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2196a2e27255SArnaldo Carvalho de Melo 		goto out;
2197a2e27255SArnaldo Carvalho de Melo 
2198a2e27255SArnaldo Carvalho de Melo 	err = __sys_recvmsg(sock, msg, &msg_sys, flags, 0);
2199a2e27255SArnaldo Carvalho de Melo 
22006cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
22011da177e4SLinus Torvalds out:
22021da177e4SLinus Torvalds 	return err;
22031da177e4SLinus Torvalds }
22041da177e4SLinus Torvalds 
2205a2e27255SArnaldo Carvalho de Melo /*
2206a2e27255SArnaldo Carvalho de Melo  *     Linux recvmmsg interface
2207a2e27255SArnaldo Carvalho de Melo  */
22081da177e4SLinus Torvalds 
2209a2e27255SArnaldo Carvalho de Melo int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2210a2e27255SArnaldo Carvalho de Melo 		   unsigned int flags, struct timespec *timeout)
2211a2e27255SArnaldo Carvalho de Melo {
2212a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err, datagrams;
2213a2e27255SArnaldo Carvalho de Melo 	struct socket *sock;
2214a2e27255SArnaldo Carvalho de Melo 	struct mmsghdr __user *entry;
2215d7256d0eSJean-Mickael Guerin 	struct compat_mmsghdr __user *compat_entry;
2216a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
2217a2e27255SArnaldo Carvalho de Melo 	struct timespec end_time;
2218a2e27255SArnaldo Carvalho de Melo 
2219a2e27255SArnaldo Carvalho de Melo 	if (timeout &&
2220a2e27255SArnaldo Carvalho de Melo 	    poll_select_set_timeout(&end_time, timeout->tv_sec,
2221a2e27255SArnaldo Carvalho de Melo 				    timeout->tv_nsec))
2222a2e27255SArnaldo Carvalho de Melo 		return -EINVAL;
2223a2e27255SArnaldo Carvalho de Melo 
2224a2e27255SArnaldo Carvalho de Melo 	datagrams = 0;
2225a2e27255SArnaldo Carvalho de Melo 
2226a2e27255SArnaldo Carvalho de Melo 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2227a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2228a2e27255SArnaldo Carvalho de Melo 		return err;
2229a2e27255SArnaldo Carvalho de Melo 
2230a2e27255SArnaldo Carvalho de Melo 	err = sock_error(sock->sk);
2231a2e27255SArnaldo Carvalho de Melo 	if (err)
2232a2e27255SArnaldo Carvalho de Melo 		goto out_put;
2233a2e27255SArnaldo Carvalho de Melo 
2234a2e27255SArnaldo Carvalho de Melo 	entry = mmsg;
2235d7256d0eSJean-Mickael Guerin 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2236a2e27255SArnaldo Carvalho de Melo 
2237a2e27255SArnaldo Carvalho de Melo 	while (datagrams < vlen) {
2238a2e27255SArnaldo Carvalho de Melo 		/*
2239a2e27255SArnaldo Carvalho de Melo 		 * No need to ask LSM for more than the first datagram.
2240a2e27255SArnaldo Carvalho de Melo 		 */
2241d7256d0eSJean-Mickael Guerin 		if (MSG_CMSG_COMPAT & flags) {
2242d7256d0eSJean-Mickael Guerin 			err = __sys_recvmsg(sock, (struct msghdr __user *)compat_entry,
2243b9eb8b87SAnton Blanchard 					    &msg_sys, flags & ~MSG_WAITFORONE,
2244b9eb8b87SAnton Blanchard 					    datagrams);
2245d7256d0eSJean-Mickael Guerin 			if (err < 0)
2246d7256d0eSJean-Mickael Guerin 				break;
2247d7256d0eSJean-Mickael Guerin 			err = __put_user(err, &compat_entry->msg_len);
2248d7256d0eSJean-Mickael Guerin 			++compat_entry;
2249d7256d0eSJean-Mickael Guerin 		} else {
2250a2e27255SArnaldo Carvalho de Melo 			err = __sys_recvmsg(sock, (struct msghdr __user *)entry,
2251b9eb8b87SAnton Blanchard 					    &msg_sys, flags & ~MSG_WAITFORONE,
2252b9eb8b87SAnton Blanchard 					    datagrams);
2253a2e27255SArnaldo Carvalho de Melo 			if (err < 0)
2254a2e27255SArnaldo Carvalho de Melo 				break;
2255a2e27255SArnaldo Carvalho de Melo 			err = put_user(err, &entry->msg_len);
2256d7256d0eSJean-Mickael Guerin 			++entry;
2257d7256d0eSJean-Mickael Guerin 		}
2258d7256d0eSJean-Mickael Guerin 
2259a2e27255SArnaldo Carvalho de Melo 		if (err)
2260a2e27255SArnaldo Carvalho de Melo 			break;
2261a2e27255SArnaldo Carvalho de Melo 		++datagrams;
2262a2e27255SArnaldo Carvalho de Melo 
226371c5c159SBrandon L Black 		/* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
226471c5c159SBrandon L Black 		if (flags & MSG_WAITFORONE)
226571c5c159SBrandon L Black 			flags |= MSG_DONTWAIT;
226671c5c159SBrandon L Black 
2267a2e27255SArnaldo Carvalho de Melo 		if (timeout) {
2268a2e27255SArnaldo Carvalho de Melo 			ktime_get_ts(timeout);
2269a2e27255SArnaldo Carvalho de Melo 			*timeout = timespec_sub(end_time, *timeout);
2270a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_sec < 0) {
2271a2e27255SArnaldo Carvalho de Melo 				timeout->tv_sec = timeout->tv_nsec = 0;
2272a2e27255SArnaldo Carvalho de Melo 				break;
2273a2e27255SArnaldo Carvalho de Melo 			}
2274a2e27255SArnaldo Carvalho de Melo 
2275a2e27255SArnaldo Carvalho de Melo 			/* Timeout, return less than vlen datagrams */
2276a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_nsec == 0 && timeout->tv_sec == 0)
2277a2e27255SArnaldo Carvalho de Melo 				break;
2278a2e27255SArnaldo Carvalho de Melo 		}
2279a2e27255SArnaldo Carvalho de Melo 
2280a2e27255SArnaldo Carvalho de Melo 		/* Out of band data, return right away */
2281a2e27255SArnaldo Carvalho de Melo 		if (msg_sys.msg_flags & MSG_OOB)
2282a2e27255SArnaldo Carvalho de Melo 			break;
2283a2e27255SArnaldo Carvalho de Melo 	}
2284a2e27255SArnaldo Carvalho de Melo 
2285a2e27255SArnaldo Carvalho de Melo out_put:
2286a2e27255SArnaldo Carvalho de Melo 	fput_light(sock->file, fput_needed);
2287a2e27255SArnaldo Carvalho de Melo 
2288a2e27255SArnaldo Carvalho de Melo 	if (err == 0)
2289a2e27255SArnaldo Carvalho de Melo 		return datagrams;
2290a2e27255SArnaldo Carvalho de Melo 
2291a2e27255SArnaldo Carvalho de Melo 	if (datagrams != 0) {
2292a2e27255SArnaldo Carvalho de Melo 		/*
2293a2e27255SArnaldo Carvalho de Melo 		 * We may return less entries than requested (vlen) if the
2294a2e27255SArnaldo Carvalho de Melo 		 * sock is non block and there aren't enough datagrams...
2295a2e27255SArnaldo Carvalho de Melo 		 */
2296a2e27255SArnaldo Carvalho de Melo 		if (err != -EAGAIN) {
2297a2e27255SArnaldo Carvalho de Melo 			/*
2298a2e27255SArnaldo Carvalho de Melo 			 * ... or  if recvmsg returns an error after we
2299a2e27255SArnaldo Carvalho de Melo 			 * received some datagrams, where we record the
2300a2e27255SArnaldo Carvalho de Melo 			 * error to return on the next call or if the
2301a2e27255SArnaldo Carvalho de Melo 			 * app asks about it using getsockopt(SO_ERROR).
2302a2e27255SArnaldo Carvalho de Melo 			 */
2303a2e27255SArnaldo Carvalho de Melo 			sock->sk->sk_err = -err;
2304a2e27255SArnaldo Carvalho de Melo 		}
2305a2e27255SArnaldo Carvalho de Melo 
2306a2e27255SArnaldo Carvalho de Melo 		return datagrams;
2307a2e27255SArnaldo Carvalho de Melo 	}
2308a2e27255SArnaldo Carvalho de Melo 
2309a2e27255SArnaldo Carvalho de Melo 	return err;
2310a2e27255SArnaldo Carvalho de Melo }
2311a2e27255SArnaldo Carvalho de Melo 
2312a2e27255SArnaldo Carvalho de Melo SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
2313a2e27255SArnaldo Carvalho de Melo 		unsigned int, vlen, unsigned int, flags,
2314a2e27255SArnaldo Carvalho de Melo 		struct timespec __user *, timeout)
2315a2e27255SArnaldo Carvalho de Melo {
2316a2e27255SArnaldo Carvalho de Melo 	int datagrams;
2317a2e27255SArnaldo Carvalho de Melo 	struct timespec timeout_sys;
2318a2e27255SArnaldo Carvalho de Melo 
2319a2e27255SArnaldo Carvalho de Melo 	if (!timeout)
2320a2e27255SArnaldo Carvalho de Melo 		return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL);
2321a2e27255SArnaldo Carvalho de Melo 
2322a2e27255SArnaldo Carvalho de Melo 	if (copy_from_user(&timeout_sys, timeout, sizeof(timeout_sys)))
2323a2e27255SArnaldo Carvalho de Melo 		return -EFAULT;
2324a2e27255SArnaldo Carvalho de Melo 
2325a2e27255SArnaldo Carvalho de Melo 	datagrams = __sys_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys);
2326a2e27255SArnaldo Carvalho de Melo 
2327a2e27255SArnaldo Carvalho de Melo 	if (datagrams > 0 &&
2328a2e27255SArnaldo Carvalho de Melo 	    copy_to_user(timeout, &timeout_sys, sizeof(timeout_sys)))
2329a2e27255SArnaldo Carvalho de Melo 		datagrams = -EFAULT;
2330a2e27255SArnaldo Carvalho de Melo 
2331a2e27255SArnaldo Carvalho de Melo 	return datagrams;
2332a2e27255SArnaldo Carvalho de Melo }
2333a2e27255SArnaldo Carvalho de Melo 
2334a2e27255SArnaldo Carvalho de Melo #ifdef __ARCH_WANT_SYS_SOCKETCALL
23351da177e4SLinus Torvalds /* Argument list sizes for sys_socketcall */
23361da177e4SLinus Torvalds #define AL(x) ((x) * sizeof(unsigned long))
2337228e548eSAnton Blanchard static const unsigned char nargs[21] = {
233889bddce5SStephen Hemminger 	AL(0), AL(3), AL(3), AL(3), AL(2), AL(3),
23391da177e4SLinus Torvalds 	AL(3), AL(3), AL(4), AL(4), AL(4), AL(6),
2340aaca0bdcSUlrich Drepper 	AL(6), AL(2), AL(5), AL(5), AL(3), AL(3),
2341228e548eSAnton Blanchard 	AL(4), AL(5), AL(4)
234289bddce5SStephen Hemminger };
234389bddce5SStephen Hemminger 
23441da177e4SLinus Torvalds #undef AL
23451da177e4SLinus Torvalds 
23461da177e4SLinus Torvalds /*
23471da177e4SLinus Torvalds  *	System call vectors.
23481da177e4SLinus Torvalds  *
23491da177e4SLinus Torvalds  *	Argument checking cleaned up. Saved 20% in size.
23501da177e4SLinus Torvalds  *  This function doesn't need to set the kernel lock because
23511da177e4SLinus Torvalds  *  it is set by the callees.
23521da177e4SLinus Torvalds  */
23531da177e4SLinus Torvalds 
23543e0fa65fSHeiko Carstens SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
23551da177e4SLinus Torvalds {
23561da177e4SLinus Torvalds 	unsigned long a[6];
23571da177e4SLinus Torvalds 	unsigned long a0, a1;
23581da177e4SLinus Torvalds 	int err;
235947379052SArjan van de Ven 	unsigned int len;
23601da177e4SLinus Torvalds 
2361228e548eSAnton Blanchard 	if (call < 1 || call > SYS_SENDMMSG)
23621da177e4SLinus Torvalds 		return -EINVAL;
23631da177e4SLinus Torvalds 
236447379052SArjan van de Ven 	len = nargs[call];
236547379052SArjan van de Ven 	if (len > sizeof(a))
236647379052SArjan van de Ven 		return -EINVAL;
236747379052SArjan van de Ven 
23681da177e4SLinus Torvalds 	/* copy_from_user should be SMP safe. */
236947379052SArjan van de Ven 	if (copy_from_user(a, args, len))
23701da177e4SLinus Torvalds 		return -EFAULT;
23711da177e4SLinus Torvalds 
2372f3298dc4SAl Viro 	audit_socketcall(nargs[call] / sizeof(unsigned long), a);
23733ec3b2fbSDavid Woodhouse 
23741da177e4SLinus Torvalds 	a0 = a[0];
23751da177e4SLinus Torvalds 	a1 = a[1];
23761da177e4SLinus Torvalds 
237789bddce5SStephen Hemminger 	switch (call) {
23781da177e4SLinus Torvalds 	case SYS_SOCKET:
23791da177e4SLinus Torvalds 		err = sys_socket(a0, a1, a[2]);
23801da177e4SLinus Torvalds 		break;
23811da177e4SLinus Torvalds 	case SYS_BIND:
23821da177e4SLinus Torvalds 		err = sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
23831da177e4SLinus Torvalds 		break;
23841da177e4SLinus Torvalds 	case SYS_CONNECT:
23851da177e4SLinus Torvalds 		err = sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
23861da177e4SLinus Torvalds 		break;
23871da177e4SLinus Torvalds 	case SYS_LISTEN:
23881da177e4SLinus Torvalds 		err = sys_listen(a0, a1);
23891da177e4SLinus Torvalds 		break;
23901da177e4SLinus Torvalds 	case SYS_ACCEPT:
2391de11defeSUlrich Drepper 		err = sys_accept4(a0, (struct sockaddr __user *)a1,
2392aaca0bdcSUlrich Drepper 				  (int __user *)a[2], 0);
23931da177e4SLinus Torvalds 		break;
23941da177e4SLinus Torvalds 	case SYS_GETSOCKNAME:
239589bddce5SStephen Hemminger 		err =
239689bddce5SStephen Hemminger 		    sys_getsockname(a0, (struct sockaddr __user *)a1,
239789bddce5SStephen Hemminger 				    (int __user *)a[2]);
23981da177e4SLinus Torvalds 		break;
23991da177e4SLinus Torvalds 	case SYS_GETPEERNAME:
240089bddce5SStephen Hemminger 		err =
240189bddce5SStephen Hemminger 		    sys_getpeername(a0, (struct sockaddr __user *)a1,
240289bddce5SStephen Hemminger 				    (int __user *)a[2]);
24031da177e4SLinus Torvalds 		break;
24041da177e4SLinus Torvalds 	case SYS_SOCKETPAIR:
24051da177e4SLinus Torvalds 		err = sys_socketpair(a0, a1, a[2], (int __user *)a[3]);
24061da177e4SLinus Torvalds 		break;
24071da177e4SLinus Torvalds 	case SYS_SEND:
24081da177e4SLinus Torvalds 		err = sys_send(a0, (void __user *)a1, a[2], a[3]);
24091da177e4SLinus Torvalds 		break;
24101da177e4SLinus Torvalds 	case SYS_SENDTO:
24111da177e4SLinus Torvalds 		err = sys_sendto(a0, (void __user *)a1, a[2], a[3],
24121da177e4SLinus Torvalds 				 (struct sockaddr __user *)a[4], a[5]);
24131da177e4SLinus Torvalds 		break;
24141da177e4SLinus Torvalds 	case SYS_RECV:
24151da177e4SLinus Torvalds 		err = sys_recv(a0, (void __user *)a1, a[2], a[3]);
24161da177e4SLinus Torvalds 		break;
24171da177e4SLinus Torvalds 	case SYS_RECVFROM:
24181da177e4SLinus Torvalds 		err = sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
241989bddce5SStephen Hemminger 				   (struct sockaddr __user *)a[4],
242089bddce5SStephen Hemminger 				   (int __user *)a[5]);
24211da177e4SLinus Torvalds 		break;
24221da177e4SLinus Torvalds 	case SYS_SHUTDOWN:
24231da177e4SLinus Torvalds 		err = sys_shutdown(a0, a1);
24241da177e4SLinus Torvalds 		break;
24251da177e4SLinus Torvalds 	case SYS_SETSOCKOPT:
24261da177e4SLinus Torvalds 		err = sys_setsockopt(a0, a1, a[2], (char __user *)a[3], a[4]);
24271da177e4SLinus Torvalds 		break;
24281da177e4SLinus Torvalds 	case SYS_GETSOCKOPT:
242989bddce5SStephen Hemminger 		err =
243089bddce5SStephen Hemminger 		    sys_getsockopt(a0, a1, a[2], (char __user *)a[3],
243189bddce5SStephen Hemminger 				   (int __user *)a[4]);
24321da177e4SLinus Torvalds 		break;
24331da177e4SLinus Torvalds 	case SYS_SENDMSG:
24341da177e4SLinus Torvalds 		err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]);
24351da177e4SLinus Torvalds 		break;
2436228e548eSAnton Blanchard 	case SYS_SENDMMSG:
2437228e548eSAnton Blanchard 		err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]);
2438228e548eSAnton Blanchard 		break;
24391da177e4SLinus Torvalds 	case SYS_RECVMSG:
24401da177e4SLinus Torvalds 		err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]);
24411da177e4SLinus Torvalds 		break;
2442a2e27255SArnaldo Carvalho de Melo 	case SYS_RECVMMSG:
2443a2e27255SArnaldo Carvalho de Melo 		err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3],
2444a2e27255SArnaldo Carvalho de Melo 				   (struct timespec __user *)a[4]);
2445a2e27255SArnaldo Carvalho de Melo 		break;
2446de11defeSUlrich Drepper 	case SYS_ACCEPT4:
2447de11defeSUlrich Drepper 		err = sys_accept4(a0, (struct sockaddr __user *)a1,
2448de11defeSUlrich Drepper 				  (int __user *)a[2], a[3]);
2449aaca0bdcSUlrich Drepper 		break;
24501da177e4SLinus Torvalds 	default:
24511da177e4SLinus Torvalds 		err = -EINVAL;
24521da177e4SLinus Torvalds 		break;
24531da177e4SLinus Torvalds 	}
24541da177e4SLinus Torvalds 	return err;
24551da177e4SLinus Torvalds }
24561da177e4SLinus Torvalds 
24571da177e4SLinus Torvalds #endif				/* __ARCH_WANT_SYS_SOCKETCALL */
24581da177e4SLinus Torvalds 
245955737fdaSStephen Hemminger /**
246055737fdaSStephen Hemminger  *	sock_register - add a socket protocol handler
246155737fdaSStephen Hemminger  *	@ops: description of protocol
246255737fdaSStephen Hemminger  *
24631da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
24641da177e4SLinus Torvalds  *	advertise its address family, and have it linked into the
246555737fdaSStephen Hemminger  *	socket interface. The value ops->family coresponds to the
246655737fdaSStephen Hemminger  *	socket system call protocol family.
24671da177e4SLinus Torvalds  */
2468f0fd27d4SStephen Hemminger int sock_register(const struct net_proto_family *ops)
24691da177e4SLinus Torvalds {
24701da177e4SLinus Torvalds 	int err;
24711da177e4SLinus Torvalds 
24721da177e4SLinus Torvalds 	if (ops->family >= NPROTO) {
247389bddce5SStephen Hemminger 		printk(KERN_CRIT "protocol %d >= NPROTO(%d)\n", ops->family,
247489bddce5SStephen Hemminger 		       NPROTO);
24751da177e4SLinus Torvalds 		return -ENOBUFS;
24761da177e4SLinus Torvalds 	}
247755737fdaSStephen Hemminger 
247855737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2479190683a9SEric Dumazet 	if (rcu_dereference_protected(net_families[ops->family],
2480190683a9SEric Dumazet 				      lockdep_is_held(&net_family_lock)))
24811da177e4SLinus Torvalds 		err = -EEXIST;
248255737fdaSStephen Hemminger 	else {
2483cf778b00SEric Dumazet 		rcu_assign_pointer(net_families[ops->family], ops);
24841da177e4SLinus Torvalds 		err = 0;
24851da177e4SLinus Torvalds 	}
248655737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
248755737fdaSStephen Hemminger 
248889bddce5SStephen Hemminger 	printk(KERN_INFO "NET: Registered protocol family %d\n", ops->family);
24891da177e4SLinus Torvalds 	return err;
24901da177e4SLinus Torvalds }
2491c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_register);
24921da177e4SLinus Torvalds 
249355737fdaSStephen Hemminger /**
249455737fdaSStephen Hemminger  *	sock_unregister - remove a protocol handler
249555737fdaSStephen Hemminger  *	@family: protocol family to remove
249655737fdaSStephen Hemminger  *
24971da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
24981da177e4SLinus Torvalds  *	remove its address family, and have it unlinked from the
249955737fdaSStephen Hemminger  *	new socket creation.
250055737fdaSStephen Hemminger  *
250155737fdaSStephen Hemminger  *	If protocol handler is a module, then it can use module reference
250255737fdaSStephen Hemminger  *	counts to protect against new references. If protocol handler is not
250355737fdaSStephen Hemminger  *	a module then it needs to provide its own protection in
250455737fdaSStephen Hemminger  *	the ops->create routine.
25051da177e4SLinus Torvalds  */
2506f0fd27d4SStephen Hemminger void sock_unregister(int family)
25071da177e4SLinus Torvalds {
2508f0fd27d4SStephen Hemminger 	BUG_ON(family < 0 || family >= NPROTO);
25091da177e4SLinus Torvalds 
251055737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2511a9b3cd7fSStephen Hemminger 	RCU_INIT_POINTER(net_families[family], NULL);
251255737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
251355737fdaSStephen Hemminger 
251455737fdaSStephen Hemminger 	synchronize_rcu();
251555737fdaSStephen Hemminger 
251689bddce5SStephen Hemminger 	printk(KERN_INFO "NET: Unregistered protocol family %d\n", family);
25171da177e4SLinus Torvalds }
2518c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_unregister);
25191da177e4SLinus Torvalds 
252077d76ea3SAndi Kleen static int __init sock_init(void)
25211da177e4SLinus Torvalds {
2522b3e19d92SNick Piggin 	int err;
25232ca794e5SEric W. Biederman 	/*
25242ca794e5SEric W. Biederman 	 *      Initialize the network sysctl infrastructure.
25252ca794e5SEric W. Biederman 	 */
25262ca794e5SEric W. Biederman 	err = net_sysctl_init();
25272ca794e5SEric W. Biederman 	if (err)
25282ca794e5SEric W. Biederman 		goto out;
2529b3e19d92SNick Piggin 
25301da177e4SLinus Torvalds 	/*
25311da177e4SLinus Torvalds 	 *      Initialize sock SLAB cache.
25321da177e4SLinus Torvalds 	 */
25331da177e4SLinus Torvalds 
25341da177e4SLinus Torvalds 	sk_init();
25351da177e4SLinus Torvalds 
25361da177e4SLinus Torvalds 	/*
25371da177e4SLinus Torvalds 	 *      Initialize skbuff SLAB cache
25381da177e4SLinus Torvalds 	 */
25391da177e4SLinus Torvalds 	skb_init();
25401da177e4SLinus Torvalds 
25411da177e4SLinus Torvalds 	/*
25421da177e4SLinus Torvalds 	 *      Initialize the protocols module.
25431da177e4SLinus Torvalds 	 */
25441da177e4SLinus Torvalds 
25451da177e4SLinus Torvalds 	init_inodecache();
2546b3e19d92SNick Piggin 
2547b3e19d92SNick Piggin 	err = register_filesystem(&sock_fs_type);
2548b3e19d92SNick Piggin 	if (err)
2549b3e19d92SNick Piggin 		goto out_fs;
25501da177e4SLinus Torvalds 	sock_mnt = kern_mount(&sock_fs_type);
2551b3e19d92SNick Piggin 	if (IS_ERR(sock_mnt)) {
2552b3e19d92SNick Piggin 		err = PTR_ERR(sock_mnt);
2553b3e19d92SNick Piggin 		goto out_mount;
2554b3e19d92SNick Piggin 	}
255577d76ea3SAndi Kleen 
255677d76ea3SAndi Kleen 	/* The real protocol initialization is performed in later initcalls.
25571da177e4SLinus Torvalds 	 */
25581da177e4SLinus Torvalds 
25591da177e4SLinus Torvalds #ifdef CONFIG_NETFILTER
25601da177e4SLinus Torvalds 	netfilter_init();
25611da177e4SLinus Torvalds #endif
2562cbeb321aSDavid S. Miller 
2563c1f19b51SRichard Cochran #ifdef CONFIG_NETWORK_PHY_TIMESTAMPING
2564c1f19b51SRichard Cochran 	skb_timestamping_init();
2565c1f19b51SRichard Cochran #endif
2566c1f19b51SRichard Cochran 
2567b3e19d92SNick Piggin out:
2568b3e19d92SNick Piggin 	return err;
2569b3e19d92SNick Piggin 
2570b3e19d92SNick Piggin out_mount:
2571b3e19d92SNick Piggin 	unregister_filesystem(&sock_fs_type);
2572b3e19d92SNick Piggin out_fs:
2573b3e19d92SNick Piggin 	goto out;
25741da177e4SLinus Torvalds }
25751da177e4SLinus Torvalds 
257677d76ea3SAndi Kleen core_initcall(sock_init);	/* early initcall */
257777d76ea3SAndi Kleen 
25781da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS
25791da177e4SLinus Torvalds void socket_seq_show(struct seq_file *seq)
25801da177e4SLinus Torvalds {
25811da177e4SLinus Torvalds 	int cpu;
25821da177e4SLinus Torvalds 	int counter = 0;
25831da177e4SLinus Torvalds 
25846f912042SKAMEZAWA Hiroyuki 	for_each_possible_cpu(cpu)
25851da177e4SLinus Torvalds 	    counter += per_cpu(sockets_in_use, cpu);
25861da177e4SLinus Torvalds 
25871da177e4SLinus Torvalds 	/* It can be negative, by the way. 8) */
25881da177e4SLinus Torvalds 	if (counter < 0)
25891da177e4SLinus Torvalds 		counter = 0;
25901da177e4SLinus Torvalds 
25911da177e4SLinus Torvalds 	seq_printf(seq, "sockets: used %d\n", counter);
25921da177e4SLinus Torvalds }
25931da177e4SLinus Torvalds #endif				/* CONFIG_PROC_FS */
25941da177e4SLinus Torvalds 
259589bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
25966b96018bSArnd Bergmann static int do_siocgstamp(struct net *net, struct socket *sock,
2597644595f8SH. Peter Anvin 			 unsigned int cmd, void __user *up)
25987a229387SArnd Bergmann {
25997a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
26007a229387SArnd Bergmann 	struct timeval ktv;
26017a229387SArnd Bergmann 	int err;
26027a229387SArnd Bergmann 
26037a229387SArnd Bergmann 	set_fs(KERNEL_DS);
26046b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv);
26057a229387SArnd Bergmann 	set_fs(old_fs);
2606644595f8SH. Peter Anvin 	if (!err)
2607ed6fe9d6SMikulas Patocka 		err = compat_put_timeval(&ktv, up);
2608644595f8SH. Peter Anvin 
26097a229387SArnd Bergmann 	return err;
26107a229387SArnd Bergmann }
26117a229387SArnd Bergmann 
26126b96018bSArnd Bergmann static int do_siocgstampns(struct net *net, struct socket *sock,
2613644595f8SH. Peter Anvin 			   unsigned int cmd, void __user *up)
26147a229387SArnd Bergmann {
26157a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
26167a229387SArnd Bergmann 	struct timespec kts;
26177a229387SArnd Bergmann 	int err;
26187a229387SArnd Bergmann 
26197a229387SArnd Bergmann 	set_fs(KERNEL_DS);
26206b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts);
26217a229387SArnd Bergmann 	set_fs(old_fs);
2622644595f8SH. Peter Anvin 	if (!err)
2623ed6fe9d6SMikulas Patocka 		err = compat_put_timespec(&kts, up);
2624644595f8SH. Peter Anvin 
26257a229387SArnd Bergmann 	return err;
26267a229387SArnd Bergmann }
26277a229387SArnd Bergmann 
26286b96018bSArnd Bergmann static int dev_ifname32(struct net *net, struct compat_ifreq __user *uifr32)
26297a229387SArnd Bergmann {
26307a229387SArnd Bergmann 	struct ifreq __user *uifr;
26317a229387SArnd Bergmann 	int err;
26327a229387SArnd Bergmann 
26337a229387SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(struct ifreq));
26346b96018bSArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
26357a229387SArnd Bergmann 		return -EFAULT;
26367a229387SArnd Bergmann 
26376b96018bSArnd Bergmann 	err = dev_ioctl(net, SIOCGIFNAME, uifr);
26387a229387SArnd Bergmann 	if (err)
26397a229387SArnd Bergmann 		return err;
26407a229387SArnd Bergmann 
26416b96018bSArnd Bergmann 	if (copy_in_user(uifr32, uifr, sizeof(struct compat_ifreq)))
26427a229387SArnd Bergmann 		return -EFAULT;
26437a229387SArnd Bergmann 
26447a229387SArnd Bergmann 	return 0;
26457a229387SArnd Bergmann }
26467a229387SArnd Bergmann 
26476b96018bSArnd Bergmann static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32)
26487a229387SArnd Bergmann {
26496b96018bSArnd Bergmann 	struct compat_ifconf ifc32;
26507a229387SArnd Bergmann 	struct ifconf ifc;
26517a229387SArnd Bergmann 	struct ifconf __user *uifc;
26526b96018bSArnd Bergmann 	struct compat_ifreq __user *ifr32;
26537a229387SArnd Bergmann 	struct ifreq __user *ifr;
26547a229387SArnd Bergmann 	unsigned int i, j;
26557a229387SArnd Bergmann 	int err;
26567a229387SArnd Bergmann 
26576b96018bSArnd Bergmann 	if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf)))
26587a229387SArnd Bergmann 		return -EFAULT;
26597a229387SArnd Bergmann 
266043da5f2eSMathias Krause 	memset(&ifc, 0, sizeof(ifc));
26617a229387SArnd Bergmann 	if (ifc32.ifcbuf == 0) {
26627a229387SArnd Bergmann 		ifc32.ifc_len = 0;
26637a229387SArnd Bergmann 		ifc.ifc_len = 0;
26647a229387SArnd Bergmann 		ifc.ifc_req = NULL;
26657a229387SArnd Bergmann 		uifc = compat_alloc_user_space(sizeof(struct ifconf));
26667a229387SArnd Bergmann 	} else {
26676b96018bSArnd Bergmann 		size_t len = ((ifc32.ifc_len / sizeof(struct compat_ifreq)) + 1) *
26687a229387SArnd Bergmann 			sizeof(struct ifreq);
26697a229387SArnd Bergmann 		uifc = compat_alloc_user_space(sizeof(struct ifconf) + len);
26707a229387SArnd Bergmann 		ifc.ifc_len = len;
26717a229387SArnd Bergmann 		ifr = ifc.ifc_req = (void __user *)(uifc + 1);
26727a229387SArnd Bergmann 		ifr32 = compat_ptr(ifc32.ifcbuf);
26736b96018bSArnd Bergmann 		for (i = 0; i < ifc32.ifc_len; i += sizeof(struct compat_ifreq)) {
26746b96018bSArnd Bergmann 			if (copy_in_user(ifr, ifr32, sizeof(struct compat_ifreq)))
26757a229387SArnd Bergmann 				return -EFAULT;
26767a229387SArnd Bergmann 			ifr++;
26777a229387SArnd Bergmann 			ifr32++;
26787a229387SArnd Bergmann 		}
26797a229387SArnd Bergmann 	}
26807a229387SArnd Bergmann 	if (copy_to_user(uifc, &ifc, sizeof(struct ifconf)))
26817a229387SArnd Bergmann 		return -EFAULT;
26827a229387SArnd Bergmann 
26836b96018bSArnd Bergmann 	err = dev_ioctl(net, SIOCGIFCONF, uifc);
26847a229387SArnd Bergmann 	if (err)
26857a229387SArnd Bergmann 		return err;
26867a229387SArnd Bergmann 
26877a229387SArnd Bergmann 	if (copy_from_user(&ifc, uifc, sizeof(struct ifconf)))
26887a229387SArnd Bergmann 		return -EFAULT;
26897a229387SArnd Bergmann 
26907a229387SArnd Bergmann 	ifr = ifc.ifc_req;
26917a229387SArnd Bergmann 	ifr32 = compat_ptr(ifc32.ifcbuf);
26927a229387SArnd Bergmann 	for (i = 0, j = 0;
26936b96018bSArnd Bergmann 	     i + sizeof(struct compat_ifreq) <= ifc32.ifc_len && j < ifc.ifc_len;
26946b96018bSArnd Bergmann 	     i += sizeof(struct compat_ifreq), j += sizeof(struct ifreq)) {
26956b96018bSArnd Bergmann 		if (copy_in_user(ifr32, ifr, sizeof(struct compat_ifreq)))
26967a229387SArnd Bergmann 			return -EFAULT;
26977a229387SArnd Bergmann 		ifr32++;
26987a229387SArnd Bergmann 		ifr++;
26997a229387SArnd Bergmann 	}
27007a229387SArnd Bergmann 
27017a229387SArnd Bergmann 	if (ifc32.ifcbuf == 0) {
27027a229387SArnd Bergmann 		/* Translate from 64-bit structure multiple to
27037a229387SArnd Bergmann 		 * a 32-bit one.
27047a229387SArnd Bergmann 		 */
27057a229387SArnd Bergmann 		i = ifc.ifc_len;
27066b96018bSArnd Bergmann 		i = ((i / sizeof(struct ifreq)) * sizeof(struct compat_ifreq));
27077a229387SArnd Bergmann 		ifc32.ifc_len = i;
27087a229387SArnd Bergmann 	} else {
27097a229387SArnd Bergmann 		ifc32.ifc_len = i;
27107a229387SArnd Bergmann 	}
27116b96018bSArnd Bergmann 	if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf)))
27127a229387SArnd Bergmann 		return -EFAULT;
27137a229387SArnd Bergmann 
27147a229387SArnd Bergmann 	return 0;
27157a229387SArnd Bergmann }
27167a229387SArnd Bergmann 
27176b96018bSArnd Bergmann static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
27187a229387SArnd Bergmann {
27193a7da39dSBen Hutchings 	struct compat_ethtool_rxnfc __user *compat_rxnfc;
27203a7da39dSBen Hutchings 	bool convert_in = false, convert_out = false;
27213a7da39dSBen Hutchings 	size_t buf_size = ALIGN(sizeof(struct ifreq), 8);
27223a7da39dSBen Hutchings 	struct ethtool_rxnfc __user *rxnfc;
27237a229387SArnd Bergmann 	struct ifreq __user *ifr;
27243a7da39dSBen Hutchings 	u32 rule_cnt = 0, actual_rule_cnt;
27253a7da39dSBen Hutchings 	u32 ethcmd;
27267a229387SArnd Bergmann 	u32 data;
27273a7da39dSBen Hutchings 	int ret;
27287a229387SArnd Bergmann 
27297a229387SArnd Bergmann 	if (get_user(data, &ifr32->ifr_ifru.ifru_data))
27307a229387SArnd Bergmann 		return -EFAULT;
27317a229387SArnd Bergmann 
27323a7da39dSBen Hutchings 	compat_rxnfc = compat_ptr(data);
27333a7da39dSBen Hutchings 
27343a7da39dSBen Hutchings 	if (get_user(ethcmd, &compat_rxnfc->cmd))
27357a229387SArnd Bergmann 		return -EFAULT;
27367a229387SArnd Bergmann 
27373a7da39dSBen Hutchings 	/* Most ethtool structures are defined without padding.
27383a7da39dSBen Hutchings 	 * Unfortunately struct ethtool_rxnfc is an exception.
27393a7da39dSBen Hutchings 	 */
27403a7da39dSBen Hutchings 	switch (ethcmd) {
27413a7da39dSBen Hutchings 	default:
27423a7da39dSBen Hutchings 		break;
27433a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLALL:
27443a7da39dSBen Hutchings 		/* Buffer size is variable */
27453a7da39dSBen Hutchings 		if (get_user(rule_cnt, &compat_rxnfc->rule_cnt))
27463a7da39dSBen Hutchings 			return -EFAULT;
27473a7da39dSBen Hutchings 		if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32))
27483a7da39dSBen Hutchings 			return -ENOMEM;
27493a7da39dSBen Hutchings 		buf_size += rule_cnt * sizeof(u32);
27503a7da39dSBen Hutchings 		/* fall through */
27513a7da39dSBen Hutchings 	case ETHTOOL_GRXRINGS:
27523a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLCNT:
27533a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRULE:
275455664f32SBen Hutchings 	case ETHTOOL_SRXCLSRLINS:
27553a7da39dSBen Hutchings 		convert_out = true;
27563a7da39dSBen Hutchings 		/* fall through */
27573a7da39dSBen Hutchings 	case ETHTOOL_SRXCLSRLDEL:
27583a7da39dSBen Hutchings 		buf_size += sizeof(struct ethtool_rxnfc);
27593a7da39dSBen Hutchings 		convert_in = true;
27603a7da39dSBen Hutchings 		break;
27613a7da39dSBen Hutchings 	}
27623a7da39dSBen Hutchings 
27633a7da39dSBen Hutchings 	ifr = compat_alloc_user_space(buf_size);
27643a7da39dSBen Hutchings 	rxnfc = (void *)ifr + ALIGN(sizeof(struct ifreq), 8);
27653a7da39dSBen Hutchings 
27663a7da39dSBen Hutchings 	if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
27673a7da39dSBen Hutchings 		return -EFAULT;
27683a7da39dSBen Hutchings 
27693a7da39dSBen Hutchings 	if (put_user(convert_in ? rxnfc : compat_ptr(data),
27703a7da39dSBen Hutchings 		     &ifr->ifr_ifru.ifru_data))
27713a7da39dSBen Hutchings 		return -EFAULT;
27723a7da39dSBen Hutchings 
27733a7da39dSBen Hutchings 	if (convert_in) {
2774127fe533SAlexander Duyck 		/* We expect there to be holes between fs.m_ext and
27753a7da39dSBen Hutchings 		 * fs.ring_cookie and at the end of fs, but nowhere else.
27763a7da39dSBen Hutchings 		 */
2777127fe533SAlexander Duyck 		BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_ext) +
2778127fe533SAlexander Duyck 			     sizeof(compat_rxnfc->fs.m_ext) !=
2779127fe533SAlexander Duyck 			     offsetof(struct ethtool_rxnfc, fs.m_ext) +
2780127fe533SAlexander Duyck 			     sizeof(rxnfc->fs.m_ext));
27813a7da39dSBen Hutchings 		BUILD_BUG_ON(
27823a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.location) -
27833a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) !=
27843a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.location) -
27853a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.ring_cookie));
27863a7da39dSBen Hutchings 
27873a7da39dSBen Hutchings 		if (copy_in_user(rxnfc, compat_rxnfc,
2788127fe533SAlexander Duyck 				 (void *)(&rxnfc->fs.m_ext + 1) -
27893a7da39dSBen Hutchings 				 (void *)rxnfc) ||
27903a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->fs.ring_cookie,
27913a7da39dSBen Hutchings 				 &compat_rxnfc->fs.ring_cookie,
27923a7da39dSBen Hutchings 				 (void *)(&rxnfc->fs.location + 1) -
27933a7da39dSBen Hutchings 				 (void *)&rxnfc->fs.ring_cookie) ||
27943a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt,
27953a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
27963a7da39dSBen Hutchings 			return -EFAULT;
27973a7da39dSBen Hutchings 	}
27983a7da39dSBen Hutchings 
27993a7da39dSBen Hutchings 	ret = dev_ioctl(net, SIOCETHTOOL, ifr);
28003a7da39dSBen Hutchings 	if (ret)
28013a7da39dSBen Hutchings 		return ret;
28023a7da39dSBen Hutchings 
28033a7da39dSBen Hutchings 	if (convert_out) {
28043a7da39dSBen Hutchings 		if (copy_in_user(compat_rxnfc, rxnfc,
2805127fe533SAlexander Duyck 				 (const void *)(&rxnfc->fs.m_ext + 1) -
28063a7da39dSBen Hutchings 				 (const void *)rxnfc) ||
28073a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->fs.ring_cookie,
28083a7da39dSBen Hutchings 				 &rxnfc->fs.ring_cookie,
28093a7da39dSBen Hutchings 				 (const void *)(&rxnfc->fs.location + 1) -
28103a7da39dSBen Hutchings 				 (const void *)&rxnfc->fs.ring_cookie) ||
28113a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt,
28123a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
28133a7da39dSBen Hutchings 			return -EFAULT;
28143a7da39dSBen Hutchings 
28153a7da39dSBen Hutchings 		if (ethcmd == ETHTOOL_GRXCLSRLALL) {
28163a7da39dSBen Hutchings 			/* As an optimisation, we only copy the actual
28173a7da39dSBen Hutchings 			 * number of rules that the underlying
28183a7da39dSBen Hutchings 			 * function returned.  Since Mallory might
28193a7da39dSBen Hutchings 			 * change the rule count in user memory, we
28203a7da39dSBen Hutchings 			 * check that it is less than the rule count
28213a7da39dSBen Hutchings 			 * originally given (as the user buffer size),
28223a7da39dSBen Hutchings 			 * which has been range-checked.
28233a7da39dSBen Hutchings 			 */
28243a7da39dSBen Hutchings 			if (get_user(actual_rule_cnt, &rxnfc->rule_cnt))
28253a7da39dSBen Hutchings 				return -EFAULT;
28263a7da39dSBen Hutchings 			if (actual_rule_cnt < rule_cnt)
28273a7da39dSBen Hutchings 				rule_cnt = actual_rule_cnt;
28283a7da39dSBen Hutchings 			if (copy_in_user(&compat_rxnfc->rule_locs[0],
28293a7da39dSBen Hutchings 					 &rxnfc->rule_locs[0],
28303a7da39dSBen Hutchings 					 rule_cnt * sizeof(u32)))
28313a7da39dSBen Hutchings 				return -EFAULT;
28323a7da39dSBen Hutchings 		}
28333a7da39dSBen Hutchings 	}
28343a7da39dSBen Hutchings 
28353a7da39dSBen Hutchings 	return 0;
28367a229387SArnd Bergmann }
28377a229387SArnd Bergmann 
28387a50a240SArnd Bergmann static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32)
28397a50a240SArnd Bergmann {
28407a50a240SArnd Bergmann 	void __user *uptr;
28417a50a240SArnd Bergmann 	compat_uptr_t uptr32;
28427a50a240SArnd Bergmann 	struct ifreq __user *uifr;
28437a50a240SArnd Bergmann 
28447a50a240SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
28457a50a240SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
28467a50a240SArnd Bergmann 		return -EFAULT;
28477a50a240SArnd Bergmann 
28487a50a240SArnd Bergmann 	if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu))
28497a50a240SArnd Bergmann 		return -EFAULT;
28507a50a240SArnd Bergmann 
28517a50a240SArnd Bergmann 	uptr = compat_ptr(uptr32);
28527a50a240SArnd Bergmann 
28537a50a240SArnd Bergmann 	if (put_user(uptr, &uifr->ifr_settings.ifs_ifsu.raw_hdlc))
28547a50a240SArnd Bergmann 		return -EFAULT;
28557a50a240SArnd Bergmann 
28567a50a240SArnd Bergmann 	return dev_ioctl(net, SIOCWANDEV, uifr);
28577a50a240SArnd Bergmann }
28587a50a240SArnd Bergmann 
28596b96018bSArnd Bergmann static int bond_ioctl(struct net *net, unsigned int cmd,
28606b96018bSArnd Bergmann 			 struct compat_ifreq __user *ifr32)
28617a229387SArnd Bergmann {
28627a229387SArnd Bergmann 	struct ifreq kifr;
28637a229387SArnd Bergmann 	struct ifreq __user *uifr;
28647a229387SArnd Bergmann 	mm_segment_t old_fs;
28657a229387SArnd Bergmann 	int err;
28667a229387SArnd Bergmann 	u32 data;
28677a229387SArnd Bergmann 	void __user *datap;
28687a229387SArnd Bergmann 
28697a229387SArnd Bergmann 	switch (cmd) {
28707a229387SArnd Bergmann 	case SIOCBONDENSLAVE:
28717a229387SArnd Bergmann 	case SIOCBONDRELEASE:
28727a229387SArnd Bergmann 	case SIOCBONDSETHWADDR:
28737a229387SArnd Bergmann 	case SIOCBONDCHANGEACTIVE:
28746b96018bSArnd Bergmann 		if (copy_from_user(&kifr, ifr32, sizeof(struct compat_ifreq)))
28757a229387SArnd Bergmann 			return -EFAULT;
28767a229387SArnd Bergmann 
28777a229387SArnd Bergmann 		old_fs = get_fs();
28787a229387SArnd Bergmann 		set_fs(KERNEL_DS);
2879c3f52ae6Sstephen hemminger 		err = dev_ioctl(net, cmd,
2880c3f52ae6Sstephen hemminger 				(struct ifreq __user __force *) &kifr);
28817a229387SArnd Bergmann 		set_fs(old_fs);
28827a229387SArnd Bergmann 
28837a229387SArnd Bergmann 		return err;
28847a229387SArnd Bergmann 	case SIOCBONDSLAVEINFOQUERY:
28857a229387SArnd Bergmann 	case SIOCBONDINFOQUERY:
28867a229387SArnd Bergmann 		uifr = compat_alloc_user_space(sizeof(*uifr));
28877a229387SArnd Bergmann 		if (copy_in_user(&uifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
28887a229387SArnd Bergmann 			return -EFAULT;
28897a229387SArnd Bergmann 
28907a229387SArnd Bergmann 		if (get_user(data, &ifr32->ifr_ifru.ifru_data))
28917a229387SArnd Bergmann 			return -EFAULT;
28927a229387SArnd Bergmann 
28937a229387SArnd Bergmann 		datap = compat_ptr(data);
28947a229387SArnd Bergmann 		if (put_user(datap, &uifr->ifr_ifru.ifru_data))
28957a229387SArnd Bergmann 			return -EFAULT;
28967a229387SArnd Bergmann 
28976b96018bSArnd Bergmann 		return dev_ioctl(net, cmd, uifr);
28987a229387SArnd Bergmann 	default:
289907d106d0SLinus Torvalds 		return -ENOIOCTLCMD;
2900ccbd6a5aSJoe Perches 	}
29017a229387SArnd Bergmann }
29027a229387SArnd Bergmann 
29036b96018bSArnd Bergmann static int siocdevprivate_ioctl(struct net *net, unsigned int cmd,
29046b96018bSArnd Bergmann 				 struct compat_ifreq __user *u_ifreq32)
29057a229387SArnd Bergmann {
29067a229387SArnd Bergmann 	struct ifreq __user *u_ifreq64;
29077a229387SArnd Bergmann 	char tmp_buf[IFNAMSIZ];
29087a229387SArnd Bergmann 	void __user *data64;
29097a229387SArnd Bergmann 	u32 data32;
29107a229387SArnd Bergmann 
29117a229387SArnd Bergmann 	if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]),
29127a229387SArnd Bergmann 			   IFNAMSIZ))
29137a229387SArnd Bergmann 		return -EFAULT;
29147a229387SArnd Bergmann 	if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data))
29157a229387SArnd Bergmann 		return -EFAULT;
29167a229387SArnd Bergmann 	data64 = compat_ptr(data32);
29177a229387SArnd Bergmann 
29187a229387SArnd Bergmann 	u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
29197a229387SArnd Bergmann 
29207a229387SArnd Bergmann 	/* Don't check these user accesses, just let that get trapped
29217a229387SArnd Bergmann 	 * in the ioctl handler instead.
29227a229387SArnd Bergmann 	 */
29237a229387SArnd Bergmann 	if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0],
29247a229387SArnd Bergmann 			 IFNAMSIZ))
29257a229387SArnd Bergmann 		return -EFAULT;
29267a229387SArnd Bergmann 	if (__put_user(data64, &u_ifreq64->ifr_ifru.ifru_data))
29277a229387SArnd Bergmann 		return -EFAULT;
29287a229387SArnd Bergmann 
29296b96018bSArnd Bergmann 	return dev_ioctl(net, cmd, u_ifreq64);
29307a229387SArnd Bergmann }
29317a229387SArnd Bergmann 
29326b96018bSArnd Bergmann static int dev_ifsioc(struct net *net, struct socket *sock,
29336b96018bSArnd Bergmann 			 unsigned int cmd, struct compat_ifreq __user *uifr32)
29347a229387SArnd Bergmann {
2935a2116ed2SArnd Bergmann 	struct ifreq __user *uifr;
29367a229387SArnd Bergmann 	int err;
29377a229387SArnd Bergmann 
2938a2116ed2SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
2939a2116ed2SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(*uifr32)))
29407a229387SArnd Bergmann 		return -EFAULT;
2941a2116ed2SArnd Bergmann 
2942a2116ed2SArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr);
2943a2116ed2SArnd Bergmann 
29447a229387SArnd Bergmann 	if (!err) {
29457a229387SArnd Bergmann 		switch (cmd) {
29467a229387SArnd Bergmann 		case SIOCGIFFLAGS:
29477a229387SArnd Bergmann 		case SIOCGIFMETRIC:
29487a229387SArnd Bergmann 		case SIOCGIFMTU:
29497a229387SArnd Bergmann 		case SIOCGIFMEM:
29507a229387SArnd Bergmann 		case SIOCGIFHWADDR:
29517a229387SArnd Bergmann 		case SIOCGIFINDEX:
29527a229387SArnd Bergmann 		case SIOCGIFADDR:
29537a229387SArnd Bergmann 		case SIOCGIFBRDADDR:
29547a229387SArnd Bergmann 		case SIOCGIFDSTADDR:
29557a229387SArnd Bergmann 		case SIOCGIFNETMASK:
2956fab2532bSArnd Bergmann 		case SIOCGIFPFLAGS:
29577a229387SArnd Bergmann 		case SIOCGIFTXQLEN:
2958fab2532bSArnd Bergmann 		case SIOCGMIIPHY:
2959fab2532bSArnd Bergmann 		case SIOCGMIIREG:
2960a2116ed2SArnd Bergmann 			if (copy_in_user(uifr32, uifr, sizeof(*uifr32)))
2961a2116ed2SArnd Bergmann 				err = -EFAULT;
29627a229387SArnd Bergmann 			break;
2963a2116ed2SArnd Bergmann 		}
2964a2116ed2SArnd Bergmann 	}
2965a2116ed2SArnd Bergmann 	return err;
2966a2116ed2SArnd Bergmann }
2967a2116ed2SArnd Bergmann 
2968a2116ed2SArnd Bergmann static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
2969a2116ed2SArnd Bergmann 			struct compat_ifreq __user *uifr32)
2970a2116ed2SArnd Bergmann {
2971a2116ed2SArnd Bergmann 	struct ifreq ifr;
2972a2116ed2SArnd Bergmann 	struct compat_ifmap __user *uifmap32;
2973a2116ed2SArnd Bergmann 	mm_segment_t old_fs;
2974a2116ed2SArnd Bergmann 	int err;
2975a2116ed2SArnd Bergmann 
2976a2116ed2SArnd Bergmann 	uifmap32 = &uifr32->ifr_ifru.ifru_map;
2977a2116ed2SArnd Bergmann 	err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name));
2978a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
2979a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
2980a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
2981a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.irq, &uifmap32->irq);
2982a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.dma, &uifmap32->dma);
2983a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.port, &uifmap32->port);
2984a2116ed2SArnd Bergmann 	if (err)
2985a2116ed2SArnd Bergmann 		return -EFAULT;
2986a2116ed2SArnd Bergmann 
2987a2116ed2SArnd Bergmann 	old_fs = get_fs();
2988a2116ed2SArnd Bergmann 	set_fs(KERNEL_DS);
2989c3f52ae6Sstephen hemminger 	err = dev_ioctl(net, cmd, (void  __user __force *)&ifr);
2990a2116ed2SArnd Bergmann 	set_fs(old_fs);
2991a2116ed2SArnd Bergmann 
2992a2116ed2SArnd Bergmann 	if (cmd == SIOCGIFMAP && !err) {
29937a229387SArnd Bergmann 		err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name));
29947a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
29957a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
29967a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
29977a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.irq, &uifmap32->irq);
29987a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.dma, &uifmap32->dma);
29997a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.port, &uifmap32->port);
30007a229387SArnd Bergmann 		if (err)
30017a229387SArnd Bergmann 			err = -EFAULT;
30027a229387SArnd Bergmann 	}
30037a229387SArnd Bergmann 	return err;
30047a229387SArnd Bergmann }
30057a229387SArnd Bergmann 
3006a2116ed2SArnd Bergmann static int compat_siocshwtstamp(struct net *net, struct compat_ifreq __user *uifr32)
3007a2116ed2SArnd Bergmann {
3008a2116ed2SArnd Bergmann 	void __user *uptr;
3009a2116ed2SArnd Bergmann 	compat_uptr_t uptr32;
3010a2116ed2SArnd Bergmann 	struct ifreq __user *uifr;
3011a2116ed2SArnd Bergmann 
3012a2116ed2SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
3013a2116ed2SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
3014a2116ed2SArnd Bergmann 		return -EFAULT;
3015a2116ed2SArnd Bergmann 
3016a2116ed2SArnd Bergmann 	if (get_user(uptr32, &uifr32->ifr_data))
3017a2116ed2SArnd Bergmann 		return -EFAULT;
3018a2116ed2SArnd Bergmann 
3019a2116ed2SArnd Bergmann 	uptr = compat_ptr(uptr32);
3020a2116ed2SArnd Bergmann 
3021a2116ed2SArnd Bergmann 	if (put_user(uptr, &uifr->ifr_data))
3022a2116ed2SArnd Bergmann 		return -EFAULT;
3023a2116ed2SArnd Bergmann 
3024a2116ed2SArnd Bergmann 	return dev_ioctl(net, SIOCSHWTSTAMP, uifr);
3025a2116ed2SArnd Bergmann }
3026a2116ed2SArnd Bergmann 
30277a229387SArnd Bergmann struct rtentry32 {
30287a229387SArnd Bergmann 	u32		rt_pad1;
30297a229387SArnd Bergmann 	struct sockaddr rt_dst;         /* target address               */
30307a229387SArnd Bergmann 	struct sockaddr rt_gateway;     /* gateway addr (RTF_GATEWAY)   */
30317a229387SArnd Bergmann 	struct sockaddr rt_genmask;     /* target network mask (IP)     */
30327a229387SArnd Bergmann 	unsigned short	rt_flags;
30337a229387SArnd Bergmann 	short		rt_pad2;
30347a229387SArnd Bergmann 	u32		rt_pad3;
30357a229387SArnd Bergmann 	unsigned char	rt_tos;
30367a229387SArnd Bergmann 	unsigned char	rt_class;
30377a229387SArnd Bergmann 	short		rt_pad4;
30387a229387SArnd Bergmann 	short		rt_metric;      /* +1 for binary compatibility! */
30397a229387SArnd Bergmann 	/* char * */ u32 rt_dev;        /* forcing the device at add    */
30407a229387SArnd Bergmann 	u32		rt_mtu;         /* per route MTU/Window         */
30417a229387SArnd Bergmann 	u32		rt_window;      /* Window clamping              */
30427a229387SArnd Bergmann 	unsigned short  rt_irtt;        /* Initial RTT                  */
30437a229387SArnd Bergmann };
30447a229387SArnd Bergmann 
30457a229387SArnd Bergmann struct in6_rtmsg32 {
30467a229387SArnd Bergmann 	struct in6_addr		rtmsg_dst;
30477a229387SArnd Bergmann 	struct in6_addr		rtmsg_src;
30487a229387SArnd Bergmann 	struct in6_addr		rtmsg_gateway;
30497a229387SArnd Bergmann 	u32			rtmsg_type;
30507a229387SArnd Bergmann 	u16			rtmsg_dst_len;
30517a229387SArnd Bergmann 	u16			rtmsg_src_len;
30527a229387SArnd Bergmann 	u32			rtmsg_metric;
30537a229387SArnd Bergmann 	u32			rtmsg_info;
30547a229387SArnd Bergmann 	u32			rtmsg_flags;
30557a229387SArnd Bergmann 	s32			rtmsg_ifindex;
30567a229387SArnd Bergmann };
30577a229387SArnd Bergmann 
30586b96018bSArnd Bergmann static int routing_ioctl(struct net *net, struct socket *sock,
30596b96018bSArnd Bergmann 			 unsigned int cmd, void __user *argp)
30607a229387SArnd Bergmann {
30617a229387SArnd Bergmann 	int ret;
30627a229387SArnd Bergmann 	void *r = NULL;
30637a229387SArnd Bergmann 	struct in6_rtmsg r6;
30647a229387SArnd Bergmann 	struct rtentry r4;
30657a229387SArnd Bergmann 	char devname[16];
30667a229387SArnd Bergmann 	u32 rtdev;
30677a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
30687a229387SArnd Bergmann 
30696b96018bSArnd Bergmann 	if (sock && sock->sk && sock->sk->sk_family == AF_INET6) { /* ipv6 */
30706b96018bSArnd Bergmann 		struct in6_rtmsg32 __user *ur6 = argp;
30717a229387SArnd Bergmann 		ret = copy_from_user(&r6.rtmsg_dst, &(ur6->rtmsg_dst),
30727a229387SArnd Bergmann 			3 * sizeof(struct in6_addr));
30737a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_type, &(ur6->rtmsg_type));
30747a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len));
30757a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_src_len, &(ur6->rtmsg_src_len));
30767a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_metric, &(ur6->rtmsg_metric));
30777a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_info, &(ur6->rtmsg_info));
30787a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_flags, &(ur6->rtmsg_flags));
30797a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex));
30807a229387SArnd Bergmann 
30817a229387SArnd Bergmann 		r = (void *) &r6;
30827a229387SArnd Bergmann 	} else { /* ipv4 */
30836b96018bSArnd Bergmann 		struct rtentry32 __user *ur4 = argp;
30847a229387SArnd Bergmann 		ret = copy_from_user(&r4.rt_dst, &(ur4->rt_dst),
30857a229387SArnd Bergmann 					3 * sizeof(struct sockaddr));
30867a229387SArnd Bergmann 		ret |= __get_user(r4.rt_flags, &(ur4->rt_flags));
30877a229387SArnd Bergmann 		ret |= __get_user(r4.rt_metric, &(ur4->rt_metric));
30887a229387SArnd Bergmann 		ret |= __get_user(r4.rt_mtu, &(ur4->rt_mtu));
30897a229387SArnd Bergmann 		ret |= __get_user(r4.rt_window, &(ur4->rt_window));
30907a229387SArnd Bergmann 		ret |= __get_user(r4.rt_irtt, &(ur4->rt_irtt));
30917a229387SArnd Bergmann 		ret |= __get_user(rtdev, &(ur4->rt_dev));
30927a229387SArnd Bergmann 		if (rtdev) {
30937a229387SArnd Bergmann 			ret |= copy_from_user(devname, compat_ptr(rtdev), 15);
3094c3f52ae6Sstephen hemminger 			r4.rt_dev = (char __user __force *)devname;
3095c3f52ae6Sstephen hemminger 			devname[15] = 0;
30967a229387SArnd Bergmann 		} else
30977a229387SArnd Bergmann 			r4.rt_dev = NULL;
30987a229387SArnd Bergmann 
30997a229387SArnd Bergmann 		r = (void *) &r4;
31007a229387SArnd Bergmann 	}
31017a229387SArnd Bergmann 
31027a229387SArnd Bergmann 	if (ret) {
31037a229387SArnd Bergmann 		ret = -EFAULT;
31047a229387SArnd Bergmann 		goto out;
31057a229387SArnd Bergmann 	}
31067a229387SArnd Bergmann 
31077a229387SArnd Bergmann 	set_fs(KERNEL_DS);
31086b96018bSArnd Bergmann 	ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r);
31097a229387SArnd Bergmann 	set_fs(old_fs);
31107a229387SArnd Bergmann 
31117a229387SArnd Bergmann out:
31127a229387SArnd Bergmann 	return ret;
31137a229387SArnd Bergmann }
31147a229387SArnd Bergmann 
31157a229387SArnd Bergmann /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE
31167a229387SArnd Bergmann  * for some operations; this forces use of the newer bridge-utils that
311725985edcSLucas De Marchi  * use compatible ioctls
31187a229387SArnd Bergmann  */
31196b96018bSArnd Bergmann static int old_bridge_ioctl(compat_ulong_t __user *argp)
31207a229387SArnd Bergmann {
31216b96018bSArnd Bergmann 	compat_ulong_t tmp;
31227a229387SArnd Bergmann 
31236b96018bSArnd Bergmann 	if (get_user(tmp, argp))
31247a229387SArnd Bergmann 		return -EFAULT;
31257a229387SArnd Bergmann 	if (tmp == BRCTL_GET_VERSION)
31267a229387SArnd Bergmann 		return BRCTL_VERSION + 1;
31277a229387SArnd Bergmann 	return -EINVAL;
31287a229387SArnd Bergmann }
31297a229387SArnd Bergmann 
31306b96018bSArnd Bergmann static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
31316b96018bSArnd Bergmann 			 unsigned int cmd, unsigned long arg)
31326b96018bSArnd Bergmann {
31336b96018bSArnd Bergmann 	void __user *argp = compat_ptr(arg);
31346b96018bSArnd Bergmann 	struct sock *sk = sock->sk;
31356b96018bSArnd Bergmann 	struct net *net = sock_net(sk);
31367a229387SArnd Bergmann 
31376b96018bSArnd Bergmann 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
31386b96018bSArnd Bergmann 		return siocdevprivate_ioctl(net, cmd, argp);
31397a229387SArnd Bergmann 
31406b96018bSArnd Bergmann 	switch (cmd) {
31416b96018bSArnd Bergmann 	case SIOCSIFBR:
31426b96018bSArnd Bergmann 	case SIOCGIFBR:
31436b96018bSArnd Bergmann 		return old_bridge_ioctl(argp);
31446b96018bSArnd Bergmann 	case SIOCGIFNAME:
31456b96018bSArnd Bergmann 		return dev_ifname32(net, argp);
31466b96018bSArnd Bergmann 	case SIOCGIFCONF:
31476b96018bSArnd Bergmann 		return dev_ifconf(net, argp);
31486b96018bSArnd Bergmann 	case SIOCETHTOOL:
31496b96018bSArnd Bergmann 		return ethtool_ioctl(net, argp);
31507a50a240SArnd Bergmann 	case SIOCWANDEV:
31517a50a240SArnd Bergmann 		return compat_siocwandev(net, argp);
3152a2116ed2SArnd Bergmann 	case SIOCGIFMAP:
3153a2116ed2SArnd Bergmann 	case SIOCSIFMAP:
3154a2116ed2SArnd Bergmann 		return compat_sioc_ifmap(net, cmd, argp);
31556b96018bSArnd Bergmann 	case SIOCBONDENSLAVE:
31566b96018bSArnd Bergmann 	case SIOCBONDRELEASE:
31576b96018bSArnd Bergmann 	case SIOCBONDSETHWADDR:
31586b96018bSArnd Bergmann 	case SIOCBONDSLAVEINFOQUERY:
31596b96018bSArnd Bergmann 	case SIOCBONDINFOQUERY:
31606b96018bSArnd Bergmann 	case SIOCBONDCHANGEACTIVE:
31616b96018bSArnd Bergmann 		return bond_ioctl(net, cmd, argp);
31626b96018bSArnd Bergmann 	case SIOCADDRT:
31636b96018bSArnd Bergmann 	case SIOCDELRT:
31646b96018bSArnd Bergmann 		return routing_ioctl(net, sock, cmd, argp);
31656b96018bSArnd Bergmann 	case SIOCGSTAMP:
31666b96018bSArnd Bergmann 		return do_siocgstamp(net, sock, cmd, argp);
31676b96018bSArnd Bergmann 	case SIOCGSTAMPNS:
31686b96018bSArnd Bergmann 		return do_siocgstampns(net, sock, cmd, argp);
3169a2116ed2SArnd Bergmann 	case SIOCSHWTSTAMP:
3170a2116ed2SArnd Bergmann 		return compat_siocshwtstamp(net, argp);
31717a229387SArnd Bergmann 
31726b96018bSArnd Bergmann 	case FIOSETOWN:
31736b96018bSArnd Bergmann 	case SIOCSPGRP:
31746b96018bSArnd Bergmann 	case FIOGETOWN:
31756b96018bSArnd Bergmann 	case SIOCGPGRP:
31766b96018bSArnd Bergmann 	case SIOCBRADDBR:
31776b96018bSArnd Bergmann 	case SIOCBRDELBR:
31786b96018bSArnd Bergmann 	case SIOCGIFVLAN:
31796b96018bSArnd Bergmann 	case SIOCSIFVLAN:
31806b96018bSArnd Bergmann 	case SIOCADDDLCI:
31816b96018bSArnd Bergmann 	case SIOCDELDLCI:
31826b96018bSArnd Bergmann 		return sock_ioctl(file, cmd, arg);
31836b96018bSArnd Bergmann 
31846b96018bSArnd Bergmann 	case SIOCGIFFLAGS:
31856b96018bSArnd Bergmann 	case SIOCSIFFLAGS:
31866b96018bSArnd Bergmann 	case SIOCGIFMETRIC:
31876b96018bSArnd Bergmann 	case SIOCSIFMETRIC:
31886b96018bSArnd Bergmann 	case SIOCGIFMTU:
31896b96018bSArnd Bergmann 	case SIOCSIFMTU:
31906b96018bSArnd Bergmann 	case SIOCGIFMEM:
31916b96018bSArnd Bergmann 	case SIOCSIFMEM:
31926b96018bSArnd Bergmann 	case SIOCGIFHWADDR:
31936b96018bSArnd Bergmann 	case SIOCSIFHWADDR:
31946b96018bSArnd Bergmann 	case SIOCADDMULTI:
31956b96018bSArnd Bergmann 	case SIOCDELMULTI:
31966b96018bSArnd Bergmann 	case SIOCGIFINDEX:
31976b96018bSArnd Bergmann 	case SIOCGIFADDR:
31986b96018bSArnd Bergmann 	case SIOCSIFADDR:
31996b96018bSArnd Bergmann 	case SIOCSIFHWBROADCAST:
32006b96018bSArnd Bergmann 	case SIOCDIFADDR:
32016b96018bSArnd Bergmann 	case SIOCGIFBRDADDR:
32026b96018bSArnd Bergmann 	case SIOCSIFBRDADDR:
32036b96018bSArnd Bergmann 	case SIOCGIFDSTADDR:
32046b96018bSArnd Bergmann 	case SIOCSIFDSTADDR:
32056b96018bSArnd Bergmann 	case SIOCGIFNETMASK:
32066b96018bSArnd Bergmann 	case SIOCSIFNETMASK:
32076b96018bSArnd Bergmann 	case SIOCSIFPFLAGS:
32086b96018bSArnd Bergmann 	case SIOCGIFPFLAGS:
32096b96018bSArnd Bergmann 	case SIOCGIFTXQLEN:
32106b96018bSArnd Bergmann 	case SIOCSIFTXQLEN:
32116b96018bSArnd Bergmann 	case SIOCBRADDIF:
32126b96018bSArnd Bergmann 	case SIOCBRDELIF:
32139177efd3SArnd Bergmann 	case SIOCSIFNAME:
32149177efd3SArnd Bergmann 	case SIOCGMIIPHY:
32159177efd3SArnd Bergmann 	case SIOCGMIIREG:
32169177efd3SArnd Bergmann 	case SIOCSMIIREG:
32176b96018bSArnd Bergmann 		return dev_ifsioc(net, sock, cmd, argp);
32189177efd3SArnd Bergmann 
32196b96018bSArnd Bergmann 	case SIOCSARP:
32206b96018bSArnd Bergmann 	case SIOCGARP:
32216b96018bSArnd Bergmann 	case SIOCDARP:
32226b96018bSArnd Bergmann 	case SIOCATMARK:
32239177efd3SArnd Bergmann 		return sock_do_ioctl(net, sock, cmd, arg);
32249177efd3SArnd Bergmann 	}
32259177efd3SArnd Bergmann 
32266b96018bSArnd Bergmann 	return -ENOIOCTLCMD;
32276b96018bSArnd Bergmann }
32287a229387SArnd Bergmann 
322995c96174SEric Dumazet static long compat_sock_ioctl(struct file *file, unsigned int cmd,
323089bbfc95SShaun Pereira 			      unsigned long arg)
323189bbfc95SShaun Pereira {
323289bbfc95SShaun Pereira 	struct socket *sock = file->private_data;
323389bbfc95SShaun Pereira 	int ret = -ENOIOCTLCMD;
323487de87d5SDavid S. Miller 	struct sock *sk;
323587de87d5SDavid S. Miller 	struct net *net;
323687de87d5SDavid S. Miller 
323787de87d5SDavid S. Miller 	sk = sock->sk;
323887de87d5SDavid S. Miller 	net = sock_net(sk);
323989bbfc95SShaun Pereira 
324089bbfc95SShaun Pereira 	if (sock->ops->compat_ioctl)
324189bbfc95SShaun Pereira 		ret = sock->ops->compat_ioctl(sock, cmd, arg);
324289bbfc95SShaun Pereira 
324387de87d5SDavid S. Miller 	if (ret == -ENOIOCTLCMD &&
324487de87d5SDavid S. Miller 	    (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST))
324587de87d5SDavid S. Miller 		ret = compat_wext_handle_ioctl(net, cmd, arg);
324687de87d5SDavid S. Miller 
32476b96018bSArnd Bergmann 	if (ret == -ENOIOCTLCMD)
32486b96018bSArnd Bergmann 		ret = compat_sock_ioctl_trans(file, sock, cmd, arg);
32496b96018bSArnd Bergmann 
325089bbfc95SShaun Pereira 	return ret;
325189bbfc95SShaun Pereira }
325289bbfc95SShaun Pereira #endif
325389bbfc95SShaun Pereira 
3254ac5a488eSSridhar Samudrala int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
3255ac5a488eSSridhar Samudrala {
3256ac5a488eSSridhar Samudrala 	return sock->ops->bind(sock, addr, addrlen);
3257ac5a488eSSridhar Samudrala }
3258c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_bind);
3259ac5a488eSSridhar Samudrala 
3260ac5a488eSSridhar Samudrala int kernel_listen(struct socket *sock, int backlog)
3261ac5a488eSSridhar Samudrala {
3262ac5a488eSSridhar Samudrala 	return sock->ops->listen(sock, backlog);
3263ac5a488eSSridhar Samudrala }
3264c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_listen);
3265ac5a488eSSridhar Samudrala 
3266ac5a488eSSridhar Samudrala int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
3267ac5a488eSSridhar Samudrala {
3268ac5a488eSSridhar Samudrala 	struct sock *sk = sock->sk;
3269ac5a488eSSridhar Samudrala 	int err;
3270ac5a488eSSridhar Samudrala 
3271ac5a488eSSridhar Samudrala 	err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
3272ac5a488eSSridhar Samudrala 			       newsock);
3273ac5a488eSSridhar Samudrala 	if (err < 0)
3274ac5a488eSSridhar Samudrala 		goto done;
3275ac5a488eSSridhar Samudrala 
3276ac5a488eSSridhar Samudrala 	err = sock->ops->accept(sock, *newsock, flags);
3277ac5a488eSSridhar Samudrala 	if (err < 0) {
3278ac5a488eSSridhar Samudrala 		sock_release(*newsock);
3279fa8705b0STony Battersby 		*newsock = NULL;
3280ac5a488eSSridhar Samudrala 		goto done;
3281ac5a488eSSridhar Samudrala 	}
3282ac5a488eSSridhar Samudrala 
3283ac5a488eSSridhar Samudrala 	(*newsock)->ops = sock->ops;
32841b08534eSWei Yongjun 	__module_get((*newsock)->ops->owner);
3285ac5a488eSSridhar Samudrala 
3286ac5a488eSSridhar Samudrala done:
3287ac5a488eSSridhar Samudrala 	return err;
3288ac5a488eSSridhar Samudrala }
3289c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_accept);
3290ac5a488eSSridhar Samudrala 
3291ac5a488eSSridhar Samudrala int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
3292ac5a488eSSridhar Samudrala 		   int flags)
3293ac5a488eSSridhar Samudrala {
3294ac5a488eSSridhar Samudrala 	return sock->ops->connect(sock, addr, addrlen, flags);
3295ac5a488eSSridhar Samudrala }
3296c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_connect);
3297ac5a488eSSridhar Samudrala 
3298ac5a488eSSridhar Samudrala int kernel_getsockname(struct socket *sock, struct sockaddr *addr,
3299ac5a488eSSridhar Samudrala 			 int *addrlen)
3300ac5a488eSSridhar Samudrala {
3301ac5a488eSSridhar Samudrala 	return sock->ops->getname(sock, addr, addrlen, 0);
3302ac5a488eSSridhar Samudrala }
3303c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockname);
3304ac5a488eSSridhar Samudrala 
3305ac5a488eSSridhar Samudrala int kernel_getpeername(struct socket *sock, struct sockaddr *addr,
3306ac5a488eSSridhar Samudrala 			 int *addrlen)
3307ac5a488eSSridhar Samudrala {
3308ac5a488eSSridhar Samudrala 	return sock->ops->getname(sock, addr, addrlen, 1);
3309ac5a488eSSridhar Samudrala }
3310c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getpeername);
3311ac5a488eSSridhar Samudrala 
3312ac5a488eSSridhar Samudrala int kernel_getsockopt(struct socket *sock, int level, int optname,
3313ac5a488eSSridhar Samudrala 			char *optval, int *optlen)
3314ac5a488eSSridhar Samudrala {
3315ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3316fb8621bbSNamhyung Kim 	char __user *uoptval;
3317fb8621bbSNamhyung Kim 	int __user *uoptlen;
3318ac5a488eSSridhar Samudrala 	int err;
3319ac5a488eSSridhar Samudrala 
3320fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3321fb8621bbSNamhyung Kim 	uoptlen = (int __user __force *) optlen;
3322fb8621bbSNamhyung Kim 
3323ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3324ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3325fb8621bbSNamhyung Kim 		err = sock_getsockopt(sock, level, optname, uoptval, uoptlen);
3326ac5a488eSSridhar Samudrala 	else
3327fb8621bbSNamhyung Kim 		err = sock->ops->getsockopt(sock, level, optname, uoptval,
3328fb8621bbSNamhyung Kim 					    uoptlen);
3329ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3330ac5a488eSSridhar Samudrala 	return err;
3331ac5a488eSSridhar Samudrala }
3332c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockopt);
3333ac5a488eSSridhar Samudrala 
3334ac5a488eSSridhar Samudrala int kernel_setsockopt(struct socket *sock, int level, int optname,
3335b7058842SDavid S. Miller 			char *optval, unsigned int optlen)
3336ac5a488eSSridhar Samudrala {
3337ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3338fb8621bbSNamhyung Kim 	char __user *uoptval;
3339ac5a488eSSridhar Samudrala 	int err;
3340ac5a488eSSridhar Samudrala 
3341fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3342fb8621bbSNamhyung Kim 
3343ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3344ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3345fb8621bbSNamhyung Kim 		err = sock_setsockopt(sock, level, optname, uoptval, optlen);
3346ac5a488eSSridhar Samudrala 	else
3347fb8621bbSNamhyung Kim 		err = sock->ops->setsockopt(sock, level, optname, uoptval,
3348ac5a488eSSridhar Samudrala 					    optlen);
3349ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3350ac5a488eSSridhar Samudrala 	return err;
3351ac5a488eSSridhar Samudrala }
3352c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_setsockopt);
3353ac5a488eSSridhar Samudrala 
3354ac5a488eSSridhar Samudrala int kernel_sendpage(struct socket *sock, struct page *page, int offset,
3355ac5a488eSSridhar Samudrala 		    size_t size, int flags)
3356ac5a488eSSridhar Samudrala {
3357f8451725SHerbert Xu 	sock_update_classid(sock->sk);
3358f8451725SHerbert Xu 
3359ac5a488eSSridhar Samudrala 	if (sock->ops->sendpage)
3360ac5a488eSSridhar Samudrala 		return sock->ops->sendpage(sock, page, offset, size, flags);
3361ac5a488eSSridhar Samudrala 
3362ac5a488eSSridhar Samudrala 	return sock_no_sendpage(sock, page, offset, size, flags);
3363ac5a488eSSridhar Samudrala }
3364c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendpage);
3365ac5a488eSSridhar Samudrala 
3366ac5a488eSSridhar Samudrala int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg)
3367ac5a488eSSridhar Samudrala {
3368ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3369ac5a488eSSridhar Samudrala 	int err;
3370ac5a488eSSridhar Samudrala 
3371ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3372ac5a488eSSridhar Samudrala 	err = sock->ops->ioctl(sock, cmd, arg);
3373ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3374ac5a488eSSridhar Samudrala 
3375ac5a488eSSridhar Samudrala 	return err;
3376ac5a488eSSridhar Samudrala }
3377c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sock_ioctl);
3378ac5a488eSSridhar Samudrala 
337991cf45f0STrond Myklebust int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
338091cf45f0STrond Myklebust {
338191cf45f0STrond Myklebust 	return sock->ops->shutdown(sock, how);
338291cf45f0STrond Myklebust }
338391cf45f0STrond Myklebust EXPORT_SYMBOL(kernel_sock_shutdown);
3384