xref: /openbmc/linux/net/socket.c (revision 6d11cfdb)
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/if_bridge.h>
7320380731SArnaldo Carvalho de Melo #include <linux/if_frad.h>
7420380731SArnaldo Carvalho de Melo #include <linux/if_vlan.h>
751da177e4SLinus Torvalds #include <linux/init.h>
761da177e4SLinus Torvalds #include <linux/poll.h>
771da177e4SLinus Torvalds #include <linux/cache.h>
781da177e4SLinus Torvalds #include <linux/module.h>
791da177e4SLinus Torvalds #include <linux/highmem.h>
801da177e4SLinus Torvalds #include <linux/mount.h>
811da177e4SLinus Torvalds #include <linux/security.h>
821da177e4SLinus Torvalds #include <linux/syscalls.h>
831da177e4SLinus Torvalds #include <linux/compat.h>
841da177e4SLinus Torvalds #include <linux/kmod.h>
853ec3b2fbSDavid Woodhouse #include <linux/audit.h>
86d86b5e0eSAdrian Bunk #include <linux/wireless.h>
871b8d7ae4SEric W. Biederman #include <linux/nsproxy.h>
881fd7317dSNick Black #include <linux/magic.h>
895a0e3ad6STejun Heo #include <linux/slab.h>
90600e1779SMasatake YAMATO #include <linux/xattr.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 
349aab174f0SLinus Torvalds struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)
3501da177e4SLinus Torvalds {
3517cbe66b6SAl Viro 	struct qstr name = { .name = "" };
3522c48b9c4SAl Viro 	struct path path;
3537cbe66b6SAl Viro 	struct file *file;
3541da177e4SLinus Torvalds 
355600e1779SMasatake YAMATO 	if (dname) {
356600e1779SMasatake YAMATO 		name.name = dname;
357600e1779SMasatake YAMATO 		name.len = strlen(name.name);
358600e1779SMasatake YAMATO 	} else if (sock->sk) {
359600e1779SMasatake YAMATO 		name.name = sock->sk->sk_prot_creator->name;
360600e1779SMasatake YAMATO 		name.len = strlen(name.name);
361600e1779SMasatake YAMATO 	}
3624b936885SNick Piggin 	path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name);
36328407630SAl Viro 	if (unlikely(!path.dentry))
36428407630SAl Viro 		return ERR_PTR(-ENOMEM);
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);
37239b65252SAnatol Pomozov 	if (unlikely(IS_ERR(file))) {
373cc3808f8SAl Viro 		/* drop dentry, keep inode */
3747de9c6eeSAl Viro 		ihold(path.dentry->d_inode);
3752c48b9c4SAl Viro 		path_put(&path);
37639b65252SAnatol Pomozov 		return file;
377cc3808f8SAl Viro 	}
3781da177e4SLinus Torvalds 
3791da177e4SLinus Torvalds 	sock->file = file;
38077d27200SUlrich Drepper 	file->f_flags = O_RDWR | (flags & O_NONBLOCK);
38107dc3f07SBenjamin LaHaise 	file->private_data = sock;
38228407630SAl Viro 	return file;
3831da177e4SLinus Torvalds }
38456b31d1cSAl Viro EXPORT_SYMBOL(sock_alloc_file);
3851da177e4SLinus Torvalds 
38656b31d1cSAl Viro static int sock_map_fd(struct socket *sock, int flags)
38739d8c1b6SDavid S. Miller {
38839d8c1b6SDavid S. Miller 	struct file *newfile;
38928407630SAl Viro 	int fd = get_unused_fd_flags(flags);
39028407630SAl Viro 	if (unlikely(fd < 0))
3911da177e4SLinus Torvalds 		return fd;
3921da177e4SLinus Torvalds 
393aab174f0SLinus Torvalds 	newfile = sock_alloc_file(sock, flags, NULL);
39428407630SAl Viro 	if (likely(!IS_ERR(newfile))) {
3951da177e4SLinus Torvalds 		fd_install(fd, newfile);
3961da177e4SLinus Torvalds 		return fd;
3971da177e4SLinus Torvalds 	}
39828407630SAl Viro 
39928407630SAl Viro 	put_unused_fd(fd);
40028407630SAl Viro 	return PTR_ERR(newfile);
4011da177e4SLinus Torvalds }
4021da177e4SLinus Torvalds 
403406a3c63SJohn Fastabend struct socket *sock_from_file(struct file *file, int *err)
4046cb153caSBenjamin LaHaise {
4056cb153caSBenjamin LaHaise 	if (file->f_op == &socket_file_ops)
4066cb153caSBenjamin LaHaise 		return file->private_data;	/* set in sock_map_fd */
4076cb153caSBenjamin LaHaise 
4086cb153caSBenjamin LaHaise 	*err = -ENOTSOCK;
4096cb153caSBenjamin LaHaise 	return NULL;
4106cb153caSBenjamin LaHaise }
411406a3c63SJohn Fastabend EXPORT_SYMBOL(sock_from_file);
4126cb153caSBenjamin LaHaise 
4131da177e4SLinus Torvalds /**
4141da177e4SLinus Torvalds  *	sockfd_lookup - Go from a file number to its socket slot
4151da177e4SLinus Torvalds  *	@fd: file handle
4161da177e4SLinus Torvalds  *	@err: pointer to an error code return
4171da177e4SLinus Torvalds  *
4181da177e4SLinus Torvalds  *	The file handle passed in is locked and the socket it is bound
4191da177e4SLinus Torvalds  *	too is returned. If an error occurs the err pointer is overwritten
4201da177e4SLinus Torvalds  *	with a negative errno code and NULL is returned. The function checks
4211da177e4SLinus Torvalds  *	for both invalid handles and passing a handle which is not a socket.
4221da177e4SLinus Torvalds  *
4231da177e4SLinus Torvalds  *	On a success the socket object pointer is returned.
4241da177e4SLinus Torvalds  */
4251da177e4SLinus Torvalds 
4261da177e4SLinus Torvalds struct socket *sockfd_lookup(int fd, int *err)
4271da177e4SLinus Torvalds {
4281da177e4SLinus Torvalds 	struct file *file;
4291da177e4SLinus Torvalds 	struct socket *sock;
4301da177e4SLinus Torvalds 
43189bddce5SStephen Hemminger 	file = fget(fd);
43289bddce5SStephen Hemminger 	if (!file) {
4331da177e4SLinus Torvalds 		*err = -EBADF;
4341da177e4SLinus Torvalds 		return NULL;
4351da177e4SLinus Torvalds 	}
43689bddce5SStephen Hemminger 
4376cb153caSBenjamin LaHaise 	sock = sock_from_file(file, err);
4386cb153caSBenjamin LaHaise 	if (!sock)
4391da177e4SLinus Torvalds 		fput(file);
4406cb153caSBenjamin LaHaise 	return sock;
4411da177e4SLinus Torvalds }
442c6d409cfSEric Dumazet EXPORT_SYMBOL(sockfd_lookup);
4431da177e4SLinus Torvalds 
4446cb153caSBenjamin LaHaise static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
4456cb153caSBenjamin LaHaise {
4466cb153caSBenjamin LaHaise 	struct file *file;
4476cb153caSBenjamin LaHaise 	struct socket *sock;
4486cb153caSBenjamin LaHaise 
4493672558cSHua Zhong 	*err = -EBADF;
4506cb153caSBenjamin LaHaise 	file = fget_light(fd, fput_needed);
4516cb153caSBenjamin LaHaise 	if (file) {
4526cb153caSBenjamin LaHaise 		sock = sock_from_file(file, err);
4536cb153caSBenjamin LaHaise 		if (sock)
4541da177e4SLinus Torvalds 			return sock;
4556cb153caSBenjamin LaHaise 		fput_light(file, *fput_needed);
4566cb153caSBenjamin LaHaise 	}
4576cb153caSBenjamin LaHaise 	return NULL;
4581da177e4SLinus Torvalds }
4591da177e4SLinus Torvalds 
460600e1779SMasatake YAMATO #define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname"
461600e1779SMasatake YAMATO #define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX)
462600e1779SMasatake YAMATO #define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1)
463600e1779SMasatake YAMATO static ssize_t sockfs_getxattr(struct dentry *dentry,
464600e1779SMasatake YAMATO 			       const char *name, void *value, size_t size)
465600e1779SMasatake YAMATO {
466600e1779SMasatake YAMATO 	const char *proto_name;
467600e1779SMasatake YAMATO 	size_t proto_size;
468600e1779SMasatake YAMATO 	int error;
469600e1779SMasatake YAMATO 
470600e1779SMasatake YAMATO 	error = -ENODATA;
471600e1779SMasatake YAMATO 	if (!strncmp(name, XATTR_NAME_SOCKPROTONAME, XATTR_NAME_SOCKPROTONAME_LEN)) {
472600e1779SMasatake YAMATO 		proto_name = dentry->d_name.name;
473600e1779SMasatake YAMATO 		proto_size = strlen(proto_name);
474600e1779SMasatake YAMATO 
475600e1779SMasatake YAMATO 		if (value) {
476600e1779SMasatake YAMATO 			error = -ERANGE;
477600e1779SMasatake YAMATO 			if (proto_size + 1 > size)
478600e1779SMasatake YAMATO 				goto out;
479600e1779SMasatake YAMATO 
480600e1779SMasatake YAMATO 			strncpy(value, proto_name, proto_size + 1);
481600e1779SMasatake YAMATO 		}
482600e1779SMasatake YAMATO 		error = proto_size + 1;
483600e1779SMasatake YAMATO 	}
484600e1779SMasatake YAMATO 
485600e1779SMasatake YAMATO out:
486600e1779SMasatake YAMATO 	return error;
487600e1779SMasatake YAMATO }
488600e1779SMasatake YAMATO 
489600e1779SMasatake YAMATO static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer,
490600e1779SMasatake YAMATO 				size_t size)
491600e1779SMasatake YAMATO {
492600e1779SMasatake YAMATO 	ssize_t len;
493600e1779SMasatake YAMATO 	ssize_t used = 0;
494600e1779SMasatake YAMATO 
495600e1779SMasatake YAMATO 	len = security_inode_listsecurity(dentry->d_inode, buffer, size);
496600e1779SMasatake YAMATO 	if (len < 0)
497600e1779SMasatake YAMATO 		return len;
498600e1779SMasatake YAMATO 	used += len;
499600e1779SMasatake YAMATO 	if (buffer) {
500600e1779SMasatake YAMATO 		if (size < used)
501600e1779SMasatake YAMATO 			return -ERANGE;
502600e1779SMasatake YAMATO 		buffer += len;
503600e1779SMasatake YAMATO 	}
504600e1779SMasatake YAMATO 
505600e1779SMasatake YAMATO 	len = (XATTR_NAME_SOCKPROTONAME_LEN + 1);
506600e1779SMasatake YAMATO 	used += len;
507600e1779SMasatake YAMATO 	if (buffer) {
508600e1779SMasatake YAMATO 		if (size < used)
509600e1779SMasatake YAMATO 			return -ERANGE;
510600e1779SMasatake YAMATO 		memcpy(buffer, XATTR_NAME_SOCKPROTONAME, len);
511600e1779SMasatake YAMATO 		buffer += len;
512600e1779SMasatake YAMATO 	}
513600e1779SMasatake YAMATO 
514600e1779SMasatake YAMATO 	return used;
515600e1779SMasatake YAMATO }
516600e1779SMasatake YAMATO 
517600e1779SMasatake YAMATO static const struct inode_operations sockfs_inode_ops = {
518600e1779SMasatake YAMATO 	.getxattr = sockfs_getxattr,
519600e1779SMasatake YAMATO 	.listxattr = sockfs_listxattr,
520600e1779SMasatake YAMATO };
521600e1779SMasatake YAMATO 
5221da177e4SLinus Torvalds /**
5231da177e4SLinus Torvalds  *	sock_alloc	-	allocate a socket
5241da177e4SLinus Torvalds  *
5251da177e4SLinus Torvalds  *	Allocate a new inode and socket object. The two are bound together
5261da177e4SLinus Torvalds  *	and initialised. The socket is then returned. If we are out of inodes
5271da177e4SLinus Torvalds  *	NULL is returned.
5281da177e4SLinus Torvalds  */
5291da177e4SLinus Torvalds 
5301da177e4SLinus Torvalds static struct socket *sock_alloc(void)
5311da177e4SLinus Torvalds {
5321da177e4SLinus Torvalds 	struct inode *inode;
5331da177e4SLinus Torvalds 	struct socket *sock;
5341da177e4SLinus Torvalds 
535a209dfc7SEric Dumazet 	inode = new_inode_pseudo(sock_mnt->mnt_sb);
5361da177e4SLinus Torvalds 	if (!inode)
5371da177e4SLinus Torvalds 		return NULL;
5381da177e4SLinus Torvalds 
5391da177e4SLinus Torvalds 	sock = SOCKET_I(inode);
5401da177e4SLinus Torvalds 
54129a020d3SEric Dumazet 	kmemcheck_annotate_bitfield(sock, type);
54285fe4025SChristoph Hellwig 	inode->i_ino = get_next_ino();
5431da177e4SLinus Torvalds 	inode->i_mode = S_IFSOCK | S_IRWXUGO;
5448192b0c4SDavid Howells 	inode->i_uid = current_fsuid();
5458192b0c4SDavid Howells 	inode->i_gid = current_fsgid();
546600e1779SMasatake YAMATO 	inode->i_op = &sockfs_inode_ops;
5471da177e4SLinus Torvalds 
54819e8d69cSAlex Shi 	this_cpu_add(sockets_in_use, 1);
5491da177e4SLinus Torvalds 	return sock;
5501da177e4SLinus Torvalds }
5511da177e4SLinus Torvalds 
5521da177e4SLinus Torvalds /*
5531da177e4SLinus Torvalds  *	In theory you can't get an open on this inode, but /proc provides
5541da177e4SLinus Torvalds  *	a back door. Remember to keep it shut otherwise you'll let the
5551da177e4SLinus Torvalds  *	creepy crawlies in.
5561da177e4SLinus Torvalds  */
5571da177e4SLinus Torvalds 
5581da177e4SLinus Torvalds static int sock_no_open(struct inode *irrelevant, struct file *dontcare)
5591da177e4SLinus Torvalds {
5601da177e4SLinus Torvalds 	return -ENXIO;
5611da177e4SLinus Torvalds }
5621da177e4SLinus Torvalds 
5634b6f5d20SArjan van de Ven const struct file_operations bad_sock_fops = {
5641da177e4SLinus Torvalds 	.owner = THIS_MODULE,
5651da177e4SLinus Torvalds 	.open = sock_no_open,
5666038f373SArnd Bergmann 	.llseek = noop_llseek,
5671da177e4SLinus Torvalds };
5681da177e4SLinus Torvalds 
5691da177e4SLinus Torvalds /**
5701da177e4SLinus Torvalds  *	sock_release	-	close a socket
5711da177e4SLinus Torvalds  *	@sock: socket to close
5721da177e4SLinus Torvalds  *
5731da177e4SLinus Torvalds  *	The socket is released from the protocol stack if it has a release
5741da177e4SLinus Torvalds  *	callback, and the inode is then released if the socket is bound to
5751da177e4SLinus Torvalds  *	an inode not a file.
5761da177e4SLinus Torvalds  */
5771da177e4SLinus Torvalds 
5781da177e4SLinus Torvalds void sock_release(struct socket *sock)
5791da177e4SLinus Torvalds {
5801da177e4SLinus Torvalds 	if (sock->ops) {
5811da177e4SLinus Torvalds 		struct module *owner = sock->ops->owner;
5821da177e4SLinus Torvalds 
5831da177e4SLinus Torvalds 		sock->ops->release(sock);
5841da177e4SLinus Torvalds 		sock->ops = NULL;
5851da177e4SLinus Torvalds 		module_put(owner);
5861da177e4SLinus Torvalds 	}
5871da177e4SLinus Torvalds 
588eaefd110SEric Dumazet 	if (rcu_dereference_protected(sock->wq, 1)->fasync_list)
5891da177e4SLinus Torvalds 		printk(KERN_ERR "sock_release: fasync list not empty!\n");
5901da177e4SLinus Torvalds 
591b09e786bSMikulas Patocka 	if (test_bit(SOCK_EXTERNALLY_ALLOCATED, &sock->flags))
592b09e786bSMikulas Patocka 		return;
593b09e786bSMikulas Patocka 
59419e8d69cSAlex Shi 	this_cpu_sub(sockets_in_use, 1);
5951da177e4SLinus Torvalds 	if (!sock->file) {
5961da177e4SLinus Torvalds 		iput(SOCK_INODE(sock));
5971da177e4SLinus Torvalds 		return;
5981da177e4SLinus Torvalds 	}
5991da177e4SLinus Torvalds 	sock->file = NULL;
6001da177e4SLinus Torvalds }
601c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_release);
6021da177e4SLinus Torvalds 
603bf84a010SDaniel Borkmann void sock_tx_timestamp(struct sock *sk, __u8 *tx_flags)
60420d49473SPatrick Ohly {
6052244d07bSOliver Hartkopp 	*tx_flags = 0;
60620d49473SPatrick Ohly 	if (sock_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE))
6072244d07bSOliver Hartkopp 		*tx_flags |= SKBTX_HW_TSTAMP;
60820d49473SPatrick Ohly 	if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE))
6092244d07bSOliver Hartkopp 		*tx_flags |= SKBTX_SW_TSTAMP;
6106e3e939fSJohannes Berg 	if (sock_flag(sk, SOCK_WIFI_STATUS))
6116e3e939fSJohannes Berg 		*tx_flags |= SKBTX_WIFI_STATUS;
61220d49473SPatrick Ohly }
61320d49473SPatrick Ohly EXPORT_SYMBOL(sock_tx_timestamp);
61420d49473SPatrick Ohly 
615228e548eSAnton Blanchard static inline int __sock_sendmsg_nosec(struct kiocb *iocb, struct socket *sock,
6161da177e4SLinus Torvalds 				       struct msghdr *msg, size_t size)
6171da177e4SLinus Torvalds {
6181da177e4SLinus Torvalds 	struct sock_iocb *si = kiocb_to_siocb(iocb);
6191da177e4SLinus Torvalds 
6201da177e4SLinus Torvalds 	si->sock = sock;
6211da177e4SLinus Torvalds 	si->scm = NULL;
6221da177e4SLinus Torvalds 	si->msg = msg;
6231da177e4SLinus Torvalds 	si->size = size;
6241da177e4SLinus Torvalds 
6251da177e4SLinus Torvalds 	return sock->ops->sendmsg(iocb, sock, msg, size);
6261da177e4SLinus Torvalds }
6271da177e4SLinus Torvalds 
628228e548eSAnton Blanchard static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock,
629228e548eSAnton Blanchard 				 struct msghdr *msg, size_t size)
630228e548eSAnton Blanchard {
631228e548eSAnton Blanchard 	int err = security_socket_sendmsg(sock, msg, size);
632228e548eSAnton Blanchard 
633228e548eSAnton Blanchard 	return err ?: __sock_sendmsg_nosec(iocb, sock, msg, size);
634228e548eSAnton Blanchard }
635228e548eSAnton Blanchard 
6361da177e4SLinus Torvalds int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
6371da177e4SLinus Torvalds {
6381da177e4SLinus Torvalds 	struct kiocb iocb;
6391da177e4SLinus Torvalds 	struct sock_iocb siocb;
6401da177e4SLinus Torvalds 	int ret;
6411da177e4SLinus Torvalds 
6421da177e4SLinus Torvalds 	init_sync_kiocb(&iocb, NULL);
6431da177e4SLinus Torvalds 	iocb.private = &siocb;
6441da177e4SLinus Torvalds 	ret = __sock_sendmsg(&iocb, sock, msg, size);
6451da177e4SLinus Torvalds 	if (-EIOCBQUEUED == ret)
6461da177e4SLinus Torvalds 		ret = wait_on_sync_kiocb(&iocb);
6471da177e4SLinus Torvalds 	return ret;
6481da177e4SLinus Torvalds }
649c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_sendmsg);
6501da177e4SLinus Torvalds 
651894dc24cSEric Dumazet static int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg, size_t size)
652228e548eSAnton Blanchard {
653228e548eSAnton Blanchard 	struct kiocb iocb;
654228e548eSAnton Blanchard 	struct sock_iocb siocb;
655228e548eSAnton Blanchard 	int ret;
656228e548eSAnton Blanchard 
657228e548eSAnton Blanchard 	init_sync_kiocb(&iocb, NULL);
658228e548eSAnton Blanchard 	iocb.private = &siocb;
659228e548eSAnton Blanchard 	ret = __sock_sendmsg_nosec(&iocb, sock, msg, size);
660228e548eSAnton Blanchard 	if (-EIOCBQUEUED == ret)
661228e548eSAnton Blanchard 		ret = wait_on_sync_kiocb(&iocb);
662228e548eSAnton Blanchard 	return ret;
663228e548eSAnton Blanchard }
664228e548eSAnton Blanchard 
6651da177e4SLinus Torvalds int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
6661da177e4SLinus Torvalds 		   struct kvec *vec, size_t num, size_t size)
6671da177e4SLinus Torvalds {
6681da177e4SLinus Torvalds 	mm_segment_t oldfs = get_fs();
6691da177e4SLinus Torvalds 	int result;
6701da177e4SLinus Torvalds 
6711da177e4SLinus Torvalds 	set_fs(KERNEL_DS);
6721da177e4SLinus Torvalds 	/*
6731da177e4SLinus Torvalds 	 * the following is safe, since for compiler definitions of kvec and
6741da177e4SLinus Torvalds 	 * iovec are identical, yielding the same in-core layout and alignment
6751da177e4SLinus Torvalds 	 */
67689bddce5SStephen Hemminger 	msg->msg_iov = (struct iovec *)vec;
6771da177e4SLinus Torvalds 	msg->msg_iovlen = num;
6781da177e4SLinus Torvalds 	result = sock_sendmsg(sock, msg, size);
6791da177e4SLinus Torvalds 	set_fs(oldfs);
6801da177e4SLinus Torvalds 	return result;
6811da177e4SLinus Torvalds }
682c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendmsg);
6831da177e4SLinus Torvalds 
68492f37fd2SEric Dumazet /*
68592f37fd2SEric Dumazet  * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
68692f37fd2SEric Dumazet  */
68792f37fd2SEric Dumazet void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
68892f37fd2SEric Dumazet 	struct sk_buff *skb)
68992f37fd2SEric Dumazet {
69020d49473SPatrick Ohly 	int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
69120d49473SPatrick Ohly 	struct timespec ts[3];
69220d49473SPatrick Ohly 	int empty = 1;
69320d49473SPatrick Ohly 	struct skb_shared_hwtstamps *shhwtstamps =
69420d49473SPatrick Ohly 		skb_hwtstamps(skb);
69592f37fd2SEric Dumazet 
69620d49473SPatrick Ohly 	/* Race occurred between timestamp enabling and packet
69720d49473SPatrick Ohly 	   receiving.  Fill in the current time for now. */
69820d49473SPatrick Ohly 	if (need_software_tstamp && skb->tstamp.tv64 == 0)
69920d49473SPatrick Ohly 		__net_timestamp(skb);
70020d49473SPatrick Ohly 
70120d49473SPatrick Ohly 	if (need_software_tstamp) {
70292f37fd2SEric Dumazet 		if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
70392f37fd2SEric Dumazet 			struct timeval tv;
70420d49473SPatrick Ohly 			skb_get_timestamp(skb, &tv);
70520d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP,
70620d49473SPatrick Ohly 				 sizeof(tv), &tv);
70792f37fd2SEric Dumazet 		} else {
708842509b8SHagen Paul Pfeifer 			skb_get_timestampns(skb, &ts[0]);
70920d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS,
710842509b8SHagen Paul Pfeifer 				 sizeof(ts[0]), &ts[0]);
71192f37fd2SEric Dumazet 		}
71292f37fd2SEric Dumazet 	}
71392f37fd2SEric Dumazet 
71420d49473SPatrick Ohly 
71520d49473SPatrick Ohly 	memset(ts, 0, sizeof(ts));
7166e94d1efSDaniel Borkmann 	if (sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE) &&
7176e94d1efSDaniel Borkmann 	    ktime_to_timespec_cond(skb->tstamp, ts + 0))
71820d49473SPatrick Ohly 		empty = 0;
71920d49473SPatrick Ohly 	if (shhwtstamps) {
72020d49473SPatrick Ohly 		if (sock_flag(sk, SOCK_TIMESTAMPING_SYS_HARDWARE) &&
7216e94d1efSDaniel Borkmann 		    ktime_to_timespec_cond(shhwtstamps->syststamp, ts + 1))
72220d49473SPatrick Ohly 			empty = 0;
72320d49473SPatrick Ohly 		if (sock_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE) &&
7246e94d1efSDaniel Borkmann 		    ktime_to_timespec_cond(shhwtstamps->hwtstamp, ts + 2))
72520d49473SPatrick Ohly 			empty = 0;
72620d49473SPatrick Ohly 	}
72720d49473SPatrick Ohly 	if (!empty)
72820d49473SPatrick Ohly 		put_cmsg(msg, SOL_SOCKET,
72920d49473SPatrick Ohly 			 SCM_TIMESTAMPING, sizeof(ts), &ts);
73020d49473SPatrick Ohly }
7317c81fd8bSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
7327c81fd8bSArnaldo Carvalho de Melo 
7336e3e939fSJohannes Berg void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
7346e3e939fSJohannes Berg 	struct sk_buff *skb)
7356e3e939fSJohannes Berg {
7366e3e939fSJohannes Berg 	int ack;
7376e3e939fSJohannes Berg 
7386e3e939fSJohannes Berg 	if (!sock_flag(sk, SOCK_WIFI_STATUS))
7396e3e939fSJohannes Berg 		return;
7406e3e939fSJohannes Berg 	if (!skb->wifi_acked_valid)
7416e3e939fSJohannes Berg 		return;
7426e3e939fSJohannes Berg 
7436e3e939fSJohannes Berg 	ack = skb->wifi_acked;
7446e3e939fSJohannes Berg 
7456e3e939fSJohannes Berg 	put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack);
7466e3e939fSJohannes Berg }
7476e3e939fSJohannes Berg EXPORT_SYMBOL_GPL(__sock_recv_wifi_status);
7486e3e939fSJohannes Berg 
74911165f14Sstephen hemminger static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk,
75011165f14Sstephen hemminger 				   struct sk_buff *skb)
7513b885787SNeil Horman {
7523b885787SNeil Horman 	if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && skb->dropcount)
7533b885787SNeil Horman 		put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL,
7543b885787SNeil Horman 			sizeof(__u32), &skb->dropcount);
7553b885787SNeil Horman }
7563b885787SNeil Horman 
757767dd033SEric Dumazet void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
7583b885787SNeil Horman 	struct sk_buff *skb)
7593b885787SNeil Horman {
7603b885787SNeil Horman 	sock_recv_timestamp(msg, sk, skb);
7613b885787SNeil Horman 	sock_recv_drops(msg, sk, skb);
7623b885787SNeil Horman }
763767dd033SEric Dumazet EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops);
7643b885787SNeil Horman 
765a2e27255SArnaldo Carvalho de Melo static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock,
7661da177e4SLinus Torvalds 				       struct msghdr *msg, size_t size, int flags)
7671da177e4SLinus Torvalds {
7681da177e4SLinus Torvalds 	struct sock_iocb *si = kiocb_to_siocb(iocb);
7691da177e4SLinus Torvalds 
7701da177e4SLinus Torvalds 	si->sock = sock;
7711da177e4SLinus Torvalds 	si->scm = NULL;
7721da177e4SLinus Torvalds 	si->msg = msg;
7731da177e4SLinus Torvalds 	si->size = size;
7741da177e4SLinus Torvalds 	si->flags = flags;
7751da177e4SLinus Torvalds 
7761da177e4SLinus Torvalds 	return sock->ops->recvmsg(iocb, sock, msg, size, flags);
7771da177e4SLinus Torvalds }
7781da177e4SLinus Torvalds 
779a2e27255SArnaldo Carvalho de Melo static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock,
780a2e27255SArnaldo Carvalho de Melo 				 struct msghdr *msg, size_t size, int flags)
781a2e27255SArnaldo Carvalho de Melo {
782a2e27255SArnaldo Carvalho de Melo 	int err = security_socket_recvmsg(sock, msg, size, flags);
783a2e27255SArnaldo Carvalho de Melo 
784a2e27255SArnaldo Carvalho de Melo 	return err ?: __sock_recvmsg_nosec(iocb, sock, msg, size, flags);
785a2e27255SArnaldo Carvalho de Melo }
786a2e27255SArnaldo Carvalho de Melo 
7871da177e4SLinus Torvalds int sock_recvmsg(struct socket *sock, struct msghdr *msg,
7881da177e4SLinus Torvalds 		 size_t size, int flags)
7891da177e4SLinus Torvalds {
7901da177e4SLinus Torvalds 	struct kiocb iocb;
7911da177e4SLinus Torvalds 	struct sock_iocb siocb;
7921da177e4SLinus Torvalds 	int ret;
7931da177e4SLinus Torvalds 
7941da177e4SLinus Torvalds 	init_sync_kiocb(&iocb, NULL);
7951da177e4SLinus Torvalds 	iocb.private = &siocb;
7961da177e4SLinus Torvalds 	ret = __sock_recvmsg(&iocb, sock, msg, size, flags);
7971da177e4SLinus Torvalds 	if (-EIOCBQUEUED == ret)
7981da177e4SLinus Torvalds 		ret = wait_on_sync_kiocb(&iocb);
7991da177e4SLinus Torvalds 	return ret;
8001da177e4SLinus Torvalds }
801c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_recvmsg);
8021da177e4SLinus Torvalds 
803a2e27255SArnaldo Carvalho de Melo static int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
804a2e27255SArnaldo Carvalho de Melo 			      size_t size, int flags)
805a2e27255SArnaldo Carvalho de Melo {
806a2e27255SArnaldo Carvalho de Melo 	struct kiocb iocb;
807a2e27255SArnaldo Carvalho de Melo 	struct sock_iocb siocb;
808a2e27255SArnaldo Carvalho de Melo 	int ret;
809a2e27255SArnaldo Carvalho de Melo 
810a2e27255SArnaldo Carvalho de Melo 	init_sync_kiocb(&iocb, NULL);
811a2e27255SArnaldo Carvalho de Melo 	iocb.private = &siocb;
812a2e27255SArnaldo Carvalho de Melo 	ret = __sock_recvmsg_nosec(&iocb, sock, msg, size, flags);
813a2e27255SArnaldo Carvalho de Melo 	if (-EIOCBQUEUED == ret)
814a2e27255SArnaldo Carvalho de Melo 		ret = wait_on_sync_kiocb(&iocb);
815a2e27255SArnaldo Carvalho de Melo 	return ret;
816a2e27255SArnaldo Carvalho de Melo }
817a2e27255SArnaldo Carvalho de Melo 
818c1249c0aSMartin Lucina /**
819c1249c0aSMartin Lucina  * kernel_recvmsg - Receive a message from a socket (kernel space)
820c1249c0aSMartin Lucina  * @sock:       The socket to receive the message from
821c1249c0aSMartin Lucina  * @msg:        Received message
822c1249c0aSMartin Lucina  * @vec:        Input s/g array for message data
823c1249c0aSMartin Lucina  * @num:        Size of input s/g array
824c1249c0aSMartin Lucina  * @size:       Number of bytes to read
825c1249c0aSMartin Lucina  * @flags:      Message flags (MSG_DONTWAIT, etc...)
826c1249c0aSMartin Lucina  *
827c1249c0aSMartin Lucina  * On return the msg structure contains the scatter/gather array passed in the
828c1249c0aSMartin Lucina  * vec argument. The array is modified so that it consists of the unfilled
829c1249c0aSMartin Lucina  * portion of the original array.
830c1249c0aSMartin Lucina  *
831c1249c0aSMartin Lucina  * The returned value is the total number of bytes received, or an error.
832c1249c0aSMartin Lucina  */
8331da177e4SLinus Torvalds int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
83489bddce5SStephen Hemminger 		   struct kvec *vec, size_t num, size_t size, int flags)
8351da177e4SLinus Torvalds {
8361da177e4SLinus Torvalds 	mm_segment_t oldfs = get_fs();
8371da177e4SLinus Torvalds 	int result;
8381da177e4SLinus Torvalds 
8391da177e4SLinus Torvalds 	set_fs(KERNEL_DS);
8401da177e4SLinus Torvalds 	/*
8411da177e4SLinus Torvalds 	 * the following is safe, since for compiler definitions of kvec and
8421da177e4SLinus Torvalds 	 * iovec are identical, yielding the same in-core layout and alignment
8431da177e4SLinus Torvalds 	 */
84489bddce5SStephen Hemminger 	msg->msg_iov = (struct iovec *)vec, msg->msg_iovlen = num;
8451da177e4SLinus Torvalds 	result = sock_recvmsg(sock, msg, size, flags);
8461da177e4SLinus Torvalds 	set_fs(oldfs);
8471da177e4SLinus Torvalds 	return result;
8481da177e4SLinus Torvalds }
849c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_recvmsg);
8501da177e4SLinus Torvalds 
8511da177e4SLinus Torvalds static void sock_aio_dtor(struct kiocb *iocb)
8521da177e4SLinus Torvalds {
8531da177e4SLinus Torvalds 	kfree(iocb->private);
8541da177e4SLinus Torvalds }
8551da177e4SLinus Torvalds 
85620380731SArnaldo Carvalho de Melo static ssize_t sock_sendpage(struct file *file, struct page *page,
8571da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more)
8581da177e4SLinus Torvalds {
8591da177e4SLinus Torvalds 	struct socket *sock;
8601da177e4SLinus Torvalds 	int flags;
8611da177e4SLinus Torvalds 
862b69aee04SEric Dumazet 	sock = file->private_data;
8631da177e4SLinus Torvalds 
86435f9c09fSEric Dumazet 	flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
86535f9c09fSEric Dumazet 	/* more is a combination of MSG_MORE and MSG_SENDPAGE_NOTLAST */
86635f9c09fSEric Dumazet 	flags |= more;
8671da177e4SLinus Torvalds 
868e6949583SLinus Torvalds 	return kernel_sendpage(sock, page, offset, size, flags);
8691da177e4SLinus Torvalds }
8701da177e4SLinus Torvalds 
8719c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
8729c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
8739c55e01cSJens Axboe 				unsigned int flags)
8749c55e01cSJens Axboe {
8759c55e01cSJens Axboe 	struct socket *sock = file->private_data;
8769c55e01cSJens Axboe 
877997b37daSRémi Denis-Courmont 	if (unlikely(!sock->ops->splice_read))
878997b37daSRémi Denis-Courmont 		return -EINVAL;
879997b37daSRémi Denis-Courmont 
8809c55e01cSJens Axboe 	return sock->ops->splice_read(sock, ppos, pipe, len, flags);
8819c55e01cSJens Axboe }
8829c55e01cSJens Axboe 
883ce1d4d3eSChristoph Hellwig static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
88489bddce5SStephen Hemminger 					 struct sock_iocb *siocb)
885ce1d4d3eSChristoph Hellwig {
886ce1d4d3eSChristoph Hellwig 	if (!is_sync_kiocb(iocb)) {
887ce1d4d3eSChristoph Hellwig 		siocb = kmalloc(sizeof(*siocb), GFP_KERNEL);
888ce1d4d3eSChristoph Hellwig 		if (!siocb)
889ce1d4d3eSChristoph Hellwig 			return NULL;
890ce1d4d3eSChristoph Hellwig 		iocb->ki_dtor = sock_aio_dtor;
891ce1d4d3eSChristoph Hellwig 	}
892ce1d4d3eSChristoph Hellwig 
893ce1d4d3eSChristoph Hellwig 	siocb->kiocb = iocb;
894ce1d4d3eSChristoph Hellwig 	iocb->private = siocb;
895ce1d4d3eSChristoph Hellwig 	return siocb;
896ce1d4d3eSChristoph Hellwig }
897ce1d4d3eSChristoph Hellwig 
898ce1d4d3eSChristoph Hellwig static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb,
899027445c3SBadari Pulavarty 		struct file *file, const struct iovec *iov,
90089bddce5SStephen Hemminger 		unsigned long nr_segs)
901ce1d4d3eSChristoph Hellwig {
902ce1d4d3eSChristoph Hellwig 	struct socket *sock = file->private_data;
903ce1d4d3eSChristoph Hellwig 	size_t size = 0;
904ce1d4d3eSChristoph Hellwig 	int i;
905ce1d4d3eSChristoph Hellwig 
906ce1d4d3eSChristoph Hellwig 	for (i = 0; i < nr_segs; i++)
907ce1d4d3eSChristoph Hellwig 		size += iov[i].iov_len;
908ce1d4d3eSChristoph Hellwig 
909ce1d4d3eSChristoph Hellwig 	msg->msg_name = NULL;
910ce1d4d3eSChristoph Hellwig 	msg->msg_namelen = 0;
911ce1d4d3eSChristoph Hellwig 	msg->msg_control = NULL;
912ce1d4d3eSChristoph Hellwig 	msg->msg_controllen = 0;
913ce1d4d3eSChristoph Hellwig 	msg->msg_iov = (struct iovec *)iov;
914ce1d4d3eSChristoph Hellwig 	msg->msg_iovlen = nr_segs;
915ce1d4d3eSChristoph Hellwig 	msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
916ce1d4d3eSChristoph Hellwig 
917ce1d4d3eSChristoph Hellwig 	return __sock_recvmsg(iocb, sock, msg, size, msg->msg_flags);
918ce1d4d3eSChristoph Hellwig }
919ce1d4d3eSChristoph Hellwig 
920027445c3SBadari Pulavarty static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
921027445c3SBadari Pulavarty 				unsigned long nr_segs, loff_t pos)
922ce1d4d3eSChristoph Hellwig {
923ce1d4d3eSChristoph Hellwig 	struct sock_iocb siocb, *x;
924ce1d4d3eSChristoph Hellwig 
925ce1d4d3eSChristoph Hellwig 	if (pos != 0)
926ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
927027445c3SBadari Pulavarty 
928027445c3SBadari Pulavarty 	if (iocb->ki_left == 0)	/* Match SYS5 behaviour */
929ce1d4d3eSChristoph Hellwig 		return 0;
930ce1d4d3eSChristoph Hellwig 
931027445c3SBadari Pulavarty 
932027445c3SBadari Pulavarty 	x = alloc_sock_iocb(iocb, &siocb);
933ce1d4d3eSChristoph Hellwig 	if (!x)
934ce1d4d3eSChristoph Hellwig 		return -ENOMEM;
935027445c3SBadari Pulavarty 	return do_sock_read(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
936ce1d4d3eSChristoph Hellwig }
937ce1d4d3eSChristoph Hellwig 
938ce1d4d3eSChristoph Hellwig static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb,
939027445c3SBadari Pulavarty 			struct file *file, const struct iovec *iov,
94089bddce5SStephen Hemminger 			unsigned long nr_segs)
941ce1d4d3eSChristoph Hellwig {
942ce1d4d3eSChristoph Hellwig 	struct socket *sock = file->private_data;
943ce1d4d3eSChristoph Hellwig 	size_t size = 0;
944ce1d4d3eSChristoph Hellwig 	int i;
945ce1d4d3eSChristoph Hellwig 
946ce1d4d3eSChristoph Hellwig 	for (i = 0; i < nr_segs; i++)
947ce1d4d3eSChristoph Hellwig 		size += iov[i].iov_len;
948ce1d4d3eSChristoph Hellwig 
949ce1d4d3eSChristoph Hellwig 	msg->msg_name = NULL;
950ce1d4d3eSChristoph Hellwig 	msg->msg_namelen = 0;
951ce1d4d3eSChristoph Hellwig 	msg->msg_control = NULL;
952ce1d4d3eSChristoph Hellwig 	msg->msg_controllen = 0;
953ce1d4d3eSChristoph Hellwig 	msg->msg_iov = (struct iovec *)iov;
954ce1d4d3eSChristoph Hellwig 	msg->msg_iovlen = nr_segs;
955ce1d4d3eSChristoph Hellwig 	msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
956ce1d4d3eSChristoph Hellwig 	if (sock->type == SOCK_SEQPACKET)
957ce1d4d3eSChristoph Hellwig 		msg->msg_flags |= MSG_EOR;
958ce1d4d3eSChristoph Hellwig 
959ce1d4d3eSChristoph Hellwig 	return __sock_sendmsg(iocb, sock, msg, size);
960ce1d4d3eSChristoph Hellwig }
961ce1d4d3eSChristoph Hellwig 
962027445c3SBadari Pulavarty static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
963027445c3SBadari Pulavarty 			  unsigned long nr_segs, loff_t pos)
9641da177e4SLinus Torvalds {
965ce1d4d3eSChristoph Hellwig 	struct sock_iocb siocb, *x;
9661da177e4SLinus Torvalds 
967ce1d4d3eSChristoph Hellwig 	if (pos != 0)
968ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
969027445c3SBadari Pulavarty 
970027445c3SBadari Pulavarty 	x = alloc_sock_iocb(iocb, &siocb);
971ce1d4d3eSChristoph Hellwig 	if (!x)
972ce1d4d3eSChristoph Hellwig 		return -ENOMEM;
973ce1d4d3eSChristoph Hellwig 
974027445c3SBadari Pulavarty 	return do_sock_write(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
9751da177e4SLinus Torvalds }
9761da177e4SLinus Torvalds 
9771da177e4SLinus Torvalds /*
9781da177e4SLinus Torvalds  * Atomic setting of ioctl hooks to avoid race
9791da177e4SLinus Torvalds  * with module unload.
9801da177e4SLinus Torvalds  */
9811da177e4SLinus Torvalds 
9824a3e2f71SArjan van de Ven static DEFINE_MUTEX(br_ioctl_mutex);
983c6d409cfSEric Dumazet static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg);
9841da177e4SLinus Torvalds 
985881d966bSEric W. Biederman void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *))
9861da177e4SLinus Torvalds {
9874a3e2f71SArjan van de Ven 	mutex_lock(&br_ioctl_mutex);
9881da177e4SLinus Torvalds 	br_ioctl_hook = hook;
9894a3e2f71SArjan van de Ven 	mutex_unlock(&br_ioctl_mutex);
9901da177e4SLinus Torvalds }
9911da177e4SLinus Torvalds EXPORT_SYMBOL(brioctl_set);
9921da177e4SLinus Torvalds 
9934a3e2f71SArjan van de Ven static DEFINE_MUTEX(vlan_ioctl_mutex);
994881d966bSEric W. Biederman static int (*vlan_ioctl_hook) (struct net *, void __user *arg);
9951da177e4SLinus Torvalds 
996881d966bSEric W. Biederman void vlan_ioctl_set(int (*hook) (struct net *, void __user *))
9971da177e4SLinus Torvalds {
9984a3e2f71SArjan van de Ven 	mutex_lock(&vlan_ioctl_mutex);
9991da177e4SLinus Torvalds 	vlan_ioctl_hook = hook;
10004a3e2f71SArjan van de Ven 	mutex_unlock(&vlan_ioctl_mutex);
10011da177e4SLinus Torvalds }
10021da177e4SLinus Torvalds EXPORT_SYMBOL(vlan_ioctl_set);
10031da177e4SLinus Torvalds 
10044a3e2f71SArjan van de Ven static DEFINE_MUTEX(dlci_ioctl_mutex);
10051da177e4SLinus Torvalds static int (*dlci_ioctl_hook) (unsigned int, void __user *);
10061da177e4SLinus Torvalds 
10071da177e4SLinus Torvalds void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
10081da177e4SLinus Torvalds {
10094a3e2f71SArjan van de Ven 	mutex_lock(&dlci_ioctl_mutex);
10101da177e4SLinus Torvalds 	dlci_ioctl_hook = hook;
10114a3e2f71SArjan van de Ven 	mutex_unlock(&dlci_ioctl_mutex);
10121da177e4SLinus Torvalds }
10131da177e4SLinus Torvalds EXPORT_SYMBOL(dlci_ioctl_set);
10141da177e4SLinus Torvalds 
10156b96018bSArnd Bergmann static long sock_do_ioctl(struct net *net, struct socket *sock,
10166b96018bSArnd Bergmann 				 unsigned int cmd, unsigned long arg)
10176b96018bSArnd Bergmann {
10186b96018bSArnd Bergmann 	int err;
10196b96018bSArnd Bergmann 	void __user *argp = (void __user *)arg;
10206b96018bSArnd Bergmann 
10216b96018bSArnd Bergmann 	err = sock->ops->ioctl(sock, cmd, arg);
10226b96018bSArnd Bergmann 
10236b96018bSArnd Bergmann 	/*
10246b96018bSArnd Bergmann 	 * If this ioctl is unknown try to hand it down
10256b96018bSArnd Bergmann 	 * to the NIC driver.
10266b96018bSArnd Bergmann 	 */
10276b96018bSArnd Bergmann 	if (err == -ENOIOCTLCMD)
10286b96018bSArnd Bergmann 		err = dev_ioctl(net, cmd, argp);
10296b96018bSArnd Bergmann 
10306b96018bSArnd Bergmann 	return err;
10316b96018bSArnd Bergmann }
10326b96018bSArnd Bergmann 
10331da177e4SLinus Torvalds /*
10341da177e4SLinus Torvalds  *	With an ioctl, arg may well be a user mode pointer, but we don't know
10351da177e4SLinus Torvalds  *	what to do with it - that's up to the protocol still.
10361da177e4SLinus Torvalds  */
10371da177e4SLinus Torvalds 
10381da177e4SLinus Torvalds static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
10391da177e4SLinus Torvalds {
10401da177e4SLinus Torvalds 	struct socket *sock;
1041881d966bSEric W. Biederman 	struct sock *sk;
10421da177e4SLinus Torvalds 	void __user *argp = (void __user *)arg;
10431da177e4SLinus Torvalds 	int pid, err;
1044881d966bSEric W. Biederman 	struct net *net;
10451da177e4SLinus Torvalds 
1046b69aee04SEric Dumazet 	sock = file->private_data;
1047881d966bSEric W. Biederman 	sk = sock->sk;
10483b1e0a65SYOSHIFUJI Hideaki 	net = sock_net(sk);
10491da177e4SLinus Torvalds 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
1050881d966bSEric W. Biederman 		err = dev_ioctl(net, cmd, argp);
10511da177e4SLinus Torvalds 	} else
10523d23e349SJohannes Berg #ifdef CONFIG_WEXT_CORE
10531da177e4SLinus Torvalds 	if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
1054881d966bSEric W. Biederman 		err = dev_ioctl(net, cmd, argp);
10551da177e4SLinus Torvalds 	} else
10563d23e349SJohannes Berg #endif
10571da177e4SLinus Torvalds 		switch (cmd) {
10581da177e4SLinus Torvalds 		case FIOSETOWN:
10591da177e4SLinus Torvalds 		case SIOCSPGRP:
10601da177e4SLinus Torvalds 			err = -EFAULT;
10611da177e4SLinus Torvalds 			if (get_user(pid, (int __user *)argp))
10621da177e4SLinus Torvalds 				break;
10631da177e4SLinus Torvalds 			err = f_setown(sock->file, pid, 1);
10641da177e4SLinus Torvalds 			break;
10651da177e4SLinus Torvalds 		case FIOGETOWN:
10661da177e4SLinus Torvalds 		case SIOCGPGRP:
1067609d7fa9SEric W. Biederman 			err = put_user(f_getown(sock->file),
106889bddce5SStephen Hemminger 				       (int __user *)argp);
10691da177e4SLinus Torvalds 			break;
10701da177e4SLinus Torvalds 		case SIOCGIFBR:
10711da177e4SLinus Torvalds 		case SIOCSIFBR:
10721da177e4SLinus Torvalds 		case SIOCBRADDBR:
10731da177e4SLinus Torvalds 		case SIOCBRDELBR:
10741da177e4SLinus Torvalds 			err = -ENOPKG;
10751da177e4SLinus Torvalds 			if (!br_ioctl_hook)
10761da177e4SLinus Torvalds 				request_module("bridge");
10771da177e4SLinus Torvalds 
10784a3e2f71SArjan van de Ven 			mutex_lock(&br_ioctl_mutex);
10791da177e4SLinus Torvalds 			if (br_ioctl_hook)
1080881d966bSEric W. Biederman 				err = br_ioctl_hook(net, cmd, argp);
10814a3e2f71SArjan van de Ven 			mutex_unlock(&br_ioctl_mutex);
10821da177e4SLinus Torvalds 			break;
10831da177e4SLinus Torvalds 		case SIOCGIFVLAN:
10841da177e4SLinus Torvalds 		case SIOCSIFVLAN:
10851da177e4SLinus Torvalds 			err = -ENOPKG;
10861da177e4SLinus Torvalds 			if (!vlan_ioctl_hook)
10871da177e4SLinus Torvalds 				request_module("8021q");
10881da177e4SLinus Torvalds 
10894a3e2f71SArjan van de Ven 			mutex_lock(&vlan_ioctl_mutex);
10901da177e4SLinus Torvalds 			if (vlan_ioctl_hook)
1091881d966bSEric W. Biederman 				err = vlan_ioctl_hook(net, argp);
10924a3e2f71SArjan van de Ven 			mutex_unlock(&vlan_ioctl_mutex);
10931da177e4SLinus Torvalds 			break;
10941da177e4SLinus Torvalds 		case SIOCADDDLCI:
10951da177e4SLinus Torvalds 		case SIOCDELDLCI:
10961da177e4SLinus Torvalds 			err = -ENOPKG;
10971da177e4SLinus Torvalds 			if (!dlci_ioctl_hook)
10981da177e4SLinus Torvalds 				request_module("dlci");
10991da177e4SLinus Torvalds 
11004a3e2f71SArjan van de Ven 			mutex_lock(&dlci_ioctl_mutex);
11017512cbf6SPavel Emelyanov 			if (dlci_ioctl_hook)
11021da177e4SLinus Torvalds 				err = dlci_ioctl_hook(cmd, argp);
11034a3e2f71SArjan van de Ven 			mutex_unlock(&dlci_ioctl_mutex);
11041da177e4SLinus Torvalds 			break;
11051da177e4SLinus Torvalds 		default:
11066b96018bSArnd Bergmann 			err = sock_do_ioctl(net, sock, cmd, arg);
11071da177e4SLinus Torvalds 			break;
11081da177e4SLinus Torvalds 		}
11091da177e4SLinus Torvalds 	return err;
11101da177e4SLinus Torvalds }
11111da177e4SLinus Torvalds 
11121da177e4SLinus Torvalds int sock_create_lite(int family, int type, int protocol, struct socket **res)
11131da177e4SLinus Torvalds {
11141da177e4SLinus Torvalds 	int err;
11151da177e4SLinus Torvalds 	struct socket *sock = NULL;
11161da177e4SLinus Torvalds 
11171da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, 1);
11181da177e4SLinus Torvalds 	if (err)
11191da177e4SLinus Torvalds 		goto out;
11201da177e4SLinus Torvalds 
11211da177e4SLinus Torvalds 	sock = sock_alloc();
11221da177e4SLinus Torvalds 	if (!sock) {
11231da177e4SLinus Torvalds 		err = -ENOMEM;
11241da177e4SLinus Torvalds 		goto out;
11251da177e4SLinus Torvalds 	}
11261da177e4SLinus Torvalds 
11271da177e4SLinus Torvalds 	sock->type = type;
11287420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, 1);
11297420ed23SVenkat Yekkirala 	if (err)
11307420ed23SVenkat Yekkirala 		goto out_release;
11317420ed23SVenkat Yekkirala 
11321da177e4SLinus Torvalds out:
11331da177e4SLinus Torvalds 	*res = sock;
11341da177e4SLinus Torvalds 	return err;
11357420ed23SVenkat Yekkirala out_release:
11367420ed23SVenkat Yekkirala 	sock_release(sock);
11377420ed23SVenkat Yekkirala 	sock = NULL;
11387420ed23SVenkat Yekkirala 	goto out;
11391da177e4SLinus Torvalds }
1140c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_lite);
11411da177e4SLinus Torvalds 
11421da177e4SLinus Torvalds /* No kernel lock held - perfect */
11431da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file, poll_table *wait)
11441da177e4SLinus Torvalds {
11451da177e4SLinus Torvalds 	struct socket *sock;
11461da177e4SLinus Torvalds 
11471da177e4SLinus Torvalds 	/*
11481da177e4SLinus Torvalds 	 *      We can't return errors to poll, so it's either yes or no.
11491da177e4SLinus Torvalds 	 */
1150b69aee04SEric Dumazet 	sock = file->private_data;
11511da177e4SLinus Torvalds 	return sock->ops->poll(file, sock, wait);
11521da177e4SLinus Torvalds }
11531da177e4SLinus Torvalds 
11541da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma)
11551da177e4SLinus Torvalds {
1156b69aee04SEric Dumazet 	struct socket *sock = file->private_data;
11571da177e4SLinus Torvalds 
11581da177e4SLinus Torvalds 	return sock->ops->mmap(file, sock, vma);
11591da177e4SLinus Torvalds }
11601da177e4SLinus Torvalds 
116120380731SArnaldo Carvalho de Melo static int sock_close(struct inode *inode, struct file *filp)
11621da177e4SLinus Torvalds {
11631da177e4SLinus Torvalds 	sock_release(SOCKET_I(inode));
11641da177e4SLinus Torvalds 	return 0;
11651da177e4SLinus Torvalds }
11661da177e4SLinus Torvalds 
11671da177e4SLinus Torvalds /*
11681da177e4SLinus Torvalds  *	Update the socket async list
11691da177e4SLinus Torvalds  *
11701da177e4SLinus Torvalds  *	Fasync_list locking strategy.
11711da177e4SLinus Torvalds  *
11721da177e4SLinus Torvalds  *	1. fasync_list is modified only under process context socket lock
11731da177e4SLinus Torvalds  *	   i.e. under semaphore.
11741da177e4SLinus Torvalds  *	2. fasync_list is used under read_lock(&sk->sk_callback_lock)
1175989a2979SEric Dumazet  *	   or under socket lock
11761da177e4SLinus Torvalds  */
11771da177e4SLinus Torvalds 
11781da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on)
11791da177e4SLinus Torvalds {
1180989a2979SEric Dumazet 	struct socket *sock = filp->private_data;
1181989a2979SEric Dumazet 	struct sock *sk = sock->sk;
1182eaefd110SEric Dumazet 	struct socket_wq *wq;
11831da177e4SLinus Torvalds 
1184989a2979SEric Dumazet 	if (sk == NULL)
11851da177e4SLinus Torvalds 		return -EINVAL;
11861da177e4SLinus Torvalds 
11871da177e4SLinus Torvalds 	lock_sock(sk);
1188eaefd110SEric Dumazet 	wq = rcu_dereference_protected(sock->wq, sock_owned_by_user(sk));
1189eaefd110SEric Dumazet 	fasync_helper(fd, filp, on, &wq->fasync_list);
11901da177e4SLinus Torvalds 
1191eaefd110SEric Dumazet 	if (!wq->fasync_list)
1192bcdce719SEric Dumazet 		sock_reset_flag(sk, SOCK_FASYNC);
1193989a2979SEric Dumazet 	else
1194989a2979SEric Dumazet 		sock_set_flag(sk, SOCK_FASYNC);
11951da177e4SLinus Torvalds 
1196989a2979SEric Dumazet 	release_sock(sk);
11971da177e4SLinus Torvalds 	return 0;
11981da177e4SLinus Torvalds }
11991da177e4SLinus Torvalds 
120043815482SEric Dumazet /* This function may be called only under socket lock or callback_lock or rcu_lock */
12011da177e4SLinus Torvalds 
12021da177e4SLinus Torvalds int sock_wake_async(struct socket *sock, int how, int band)
12031da177e4SLinus Torvalds {
120443815482SEric Dumazet 	struct socket_wq *wq;
120543815482SEric Dumazet 
120643815482SEric Dumazet 	if (!sock)
12071da177e4SLinus Torvalds 		return -1;
120843815482SEric Dumazet 	rcu_read_lock();
120943815482SEric Dumazet 	wq = rcu_dereference(sock->wq);
121043815482SEric Dumazet 	if (!wq || !wq->fasync_list) {
121143815482SEric Dumazet 		rcu_read_unlock();
121243815482SEric Dumazet 		return -1;
121343815482SEric Dumazet 	}
121489bddce5SStephen Hemminger 	switch (how) {
12158d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_WAITD:
12161da177e4SLinus Torvalds 		if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
12171da177e4SLinus Torvalds 			break;
12181da177e4SLinus Torvalds 		goto call_kill;
12198d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_SPACE:
12201da177e4SLinus Torvalds 		if (!test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags))
12211da177e4SLinus Torvalds 			break;
12221da177e4SLinus Torvalds 		/* fall through */
12238d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_IO:
12241da177e4SLinus Torvalds call_kill:
122543815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGIO, band);
12261da177e4SLinus Torvalds 		break;
12278d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_URG:
122843815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGURG, band);
12291da177e4SLinus Torvalds 	}
123043815482SEric Dumazet 	rcu_read_unlock();
12311da177e4SLinus Torvalds 	return 0;
12321da177e4SLinus Torvalds }
1233c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_wake_async);
12341da177e4SLinus Torvalds 
1235721db93aSPavel Emelyanov int __sock_create(struct net *net, int family, int type, int protocol,
123689bddce5SStephen Hemminger 			 struct socket **res, int kern)
12371da177e4SLinus Torvalds {
12381da177e4SLinus Torvalds 	int err;
12391da177e4SLinus Torvalds 	struct socket *sock;
124055737fdaSStephen Hemminger 	const struct net_proto_family *pf;
12411da177e4SLinus Torvalds 
12421da177e4SLinus Torvalds 	/*
12431da177e4SLinus Torvalds 	 *      Check protocol is in range
12441da177e4SLinus Torvalds 	 */
12451da177e4SLinus Torvalds 	if (family < 0 || family >= NPROTO)
12461da177e4SLinus Torvalds 		return -EAFNOSUPPORT;
12471da177e4SLinus Torvalds 	if (type < 0 || type >= SOCK_MAX)
12481da177e4SLinus Torvalds 		return -EINVAL;
12491da177e4SLinus Torvalds 
12501da177e4SLinus Torvalds 	/* Compatibility.
12511da177e4SLinus Torvalds 
12521da177e4SLinus Torvalds 	   This uglymoron is moved from INET layer to here to avoid
12531da177e4SLinus Torvalds 	   deadlock in module load.
12541da177e4SLinus Torvalds 	 */
12551da177e4SLinus Torvalds 	if (family == PF_INET && type == SOCK_PACKET) {
12561da177e4SLinus Torvalds 		static int warned;
12571da177e4SLinus Torvalds 		if (!warned) {
12581da177e4SLinus Torvalds 			warned = 1;
125989bddce5SStephen Hemminger 			printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)\n",
126089bddce5SStephen Hemminger 			       current->comm);
12611da177e4SLinus Torvalds 		}
12621da177e4SLinus Torvalds 		family = PF_PACKET;
12631da177e4SLinus Torvalds 	}
12641da177e4SLinus Torvalds 
12651da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, kern);
12661da177e4SLinus Torvalds 	if (err)
12671da177e4SLinus Torvalds 		return err;
12681da177e4SLinus Torvalds 
126955737fdaSStephen Hemminger 	/*
127055737fdaSStephen Hemminger 	 *	Allocate the socket and allow the family to set things up. if
127155737fdaSStephen Hemminger 	 *	the protocol is 0, the family is instructed to select an appropriate
127255737fdaSStephen Hemminger 	 *	default.
127355737fdaSStephen Hemminger 	 */
127455737fdaSStephen Hemminger 	sock = sock_alloc();
127555737fdaSStephen Hemminger 	if (!sock) {
1276e87cc472SJoe Perches 		net_warn_ratelimited("socket: no more sockets\n");
127755737fdaSStephen Hemminger 		return -ENFILE;	/* Not exactly a match, but its the
127855737fdaSStephen Hemminger 				   closest posix thing */
127955737fdaSStephen Hemminger 	}
128055737fdaSStephen Hemminger 
128155737fdaSStephen Hemminger 	sock->type = type;
128255737fdaSStephen Hemminger 
128395a5afcaSJohannes Berg #ifdef CONFIG_MODULES
12841da177e4SLinus Torvalds 	/* Attempt to load a protocol module if the find failed.
12851da177e4SLinus Torvalds 	 *
12861da177e4SLinus Torvalds 	 * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
12871da177e4SLinus Torvalds 	 * requested real, full-featured networking support upon configuration.
12881da177e4SLinus Torvalds 	 * Otherwise module support will break!
12891da177e4SLinus Torvalds 	 */
1290190683a9SEric Dumazet 	if (rcu_access_pointer(net_families[family]) == NULL)
12911da177e4SLinus Torvalds 		request_module("net-pf-%d", family);
12921da177e4SLinus Torvalds #endif
12931da177e4SLinus Torvalds 
129455737fdaSStephen Hemminger 	rcu_read_lock();
129555737fdaSStephen Hemminger 	pf = rcu_dereference(net_families[family]);
12961da177e4SLinus Torvalds 	err = -EAFNOSUPPORT;
129755737fdaSStephen Hemminger 	if (!pf)
129855737fdaSStephen Hemminger 		goto out_release;
12991da177e4SLinus Torvalds 
13001da177e4SLinus Torvalds 	/*
13011da177e4SLinus Torvalds 	 * We will call the ->create function, that possibly is in a loadable
13021da177e4SLinus Torvalds 	 * module, so we have to bump that loadable module refcnt first.
13031da177e4SLinus Torvalds 	 */
130455737fdaSStephen Hemminger 	if (!try_module_get(pf->owner))
13051da177e4SLinus Torvalds 		goto out_release;
13061da177e4SLinus Torvalds 
130755737fdaSStephen Hemminger 	/* Now protected by module ref count */
130855737fdaSStephen Hemminger 	rcu_read_unlock();
130955737fdaSStephen Hemminger 
13103f378b68SEric Paris 	err = pf->create(net, sock, protocol, kern);
131155737fdaSStephen Hemminger 	if (err < 0)
13121da177e4SLinus Torvalds 		goto out_module_put;
1313a79af59eSFrank Filz 
13141da177e4SLinus Torvalds 	/*
13151da177e4SLinus Torvalds 	 * Now to bump the refcnt of the [loadable] module that owns this
13161da177e4SLinus Torvalds 	 * socket at sock_release time we decrement its refcnt.
13171da177e4SLinus Torvalds 	 */
131855737fdaSStephen Hemminger 	if (!try_module_get(sock->ops->owner))
131955737fdaSStephen Hemminger 		goto out_module_busy;
132055737fdaSStephen Hemminger 
13211da177e4SLinus Torvalds 	/*
13221da177e4SLinus Torvalds 	 * Now that we're done with the ->create function, the [loadable]
13231da177e4SLinus Torvalds 	 * module can have its refcnt decremented
13241da177e4SLinus Torvalds 	 */
132555737fdaSStephen Hemminger 	module_put(pf->owner);
13267420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, kern);
13277420ed23SVenkat Yekkirala 	if (err)
13283b185525SHerbert Xu 		goto out_sock_release;
132955737fdaSStephen Hemminger 	*res = sock;
13301da177e4SLinus Torvalds 
133155737fdaSStephen Hemminger 	return 0;
133255737fdaSStephen Hemminger 
133355737fdaSStephen Hemminger out_module_busy:
133455737fdaSStephen Hemminger 	err = -EAFNOSUPPORT;
13351da177e4SLinus Torvalds out_module_put:
133655737fdaSStephen Hemminger 	sock->ops = NULL;
133755737fdaSStephen Hemminger 	module_put(pf->owner);
133855737fdaSStephen Hemminger out_sock_release:
13391da177e4SLinus Torvalds 	sock_release(sock);
134055737fdaSStephen Hemminger 	return err;
134155737fdaSStephen Hemminger 
134255737fdaSStephen Hemminger out_release:
134355737fdaSStephen Hemminger 	rcu_read_unlock();
134455737fdaSStephen Hemminger 	goto out_sock_release;
13451da177e4SLinus Torvalds }
1346721db93aSPavel Emelyanov EXPORT_SYMBOL(__sock_create);
13471da177e4SLinus Torvalds 
13481da177e4SLinus Torvalds int sock_create(int family, int type, int protocol, struct socket **res)
13491da177e4SLinus Torvalds {
13501b8d7ae4SEric W. Biederman 	return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
13511da177e4SLinus Torvalds }
1352c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create);
13531da177e4SLinus Torvalds 
13541da177e4SLinus Torvalds int sock_create_kern(int family, int type, int protocol, struct socket **res)
13551da177e4SLinus Torvalds {
13561b8d7ae4SEric W. Biederman 	return __sock_create(&init_net, family, type, protocol, res, 1);
13571da177e4SLinus Torvalds }
1358c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_kern);
13591da177e4SLinus Torvalds 
13603e0fa65fSHeiko Carstens SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
13611da177e4SLinus Torvalds {
13621da177e4SLinus Torvalds 	int retval;
13631da177e4SLinus Torvalds 	struct socket *sock;
1364a677a039SUlrich Drepper 	int flags;
1365a677a039SUlrich Drepper 
1366e38b36f3SUlrich Drepper 	/* Check the SOCK_* constants for consistency.  */
1367e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
1368e38b36f3SUlrich Drepper 	BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
1369e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);
1370e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);
1371e38b36f3SUlrich 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 	retval = sock_create(family, type, protocol, &sock);
13811da177e4SLinus Torvalds 	if (retval < 0)
13821da177e4SLinus Torvalds 		goto out;
13831da177e4SLinus Torvalds 
138477d27200SUlrich Drepper 	retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
13851da177e4SLinus Torvalds 	if (retval < 0)
13861da177e4SLinus Torvalds 		goto out_release;
13871da177e4SLinus Torvalds 
13881da177e4SLinus Torvalds out:
13891da177e4SLinus Torvalds 	/* It may be already another descriptor 8) Not kernel problem. */
13901da177e4SLinus Torvalds 	return retval;
13911da177e4SLinus Torvalds 
13921da177e4SLinus Torvalds out_release:
13931da177e4SLinus Torvalds 	sock_release(sock);
13941da177e4SLinus Torvalds 	return retval;
13951da177e4SLinus Torvalds }
13961da177e4SLinus Torvalds 
13971da177e4SLinus Torvalds /*
13981da177e4SLinus Torvalds  *	Create a pair of connected sockets.
13991da177e4SLinus Torvalds  */
14001da177e4SLinus Torvalds 
14013e0fa65fSHeiko Carstens SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
14023e0fa65fSHeiko Carstens 		int __user *, usockvec)
14031da177e4SLinus Torvalds {
14041da177e4SLinus Torvalds 	struct socket *sock1, *sock2;
14051da177e4SLinus Torvalds 	int fd1, fd2, err;
1406db349509SAl Viro 	struct file *newfile1, *newfile2;
1407a677a039SUlrich Drepper 	int flags;
1408a677a039SUlrich Drepper 
1409a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
141077d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1411a677a039SUlrich Drepper 		return -EINVAL;
1412a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
14131da177e4SLinus Torvalds 
1414aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1415aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1416aaca0bdcSUlrich Drepper 
14171da177e4SLinus Torvalds 	/*
14181da177e4SLinus Torvalds 	 * Obtain the first socket and check if the underlying protocol
14191da177e4SLinus Torvalds 	 * supports the socketpair call.
14201da177e4SLinus Torvalds 	 */
14211da177e4SLinus Torvalds 
14221da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock1);
14231da177e4SLinus Torvalds 	if (err < 0)
14241da177e4SLinus Torvalds 		goto out;
14251da177e4SLinus Torvalds 
14261da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock2);
14271da177e4SLinus Torvalds 	if (err < 0)
14281da177e4SLinus Torvalds 		goto out_release_1;
14291da177e4SLinus Torvalds 
14301da177e4SLinus Torvalds 	err = sock1->ops->socketpair(sock1, sock2);
14311da177e4SLinus Torvalds 	if (err < 0)
14321da177e4SLinus Torvalds 		goto out_release_both;
14331da177e4SLinus Torvalds 
143428407630SAl Viro 	fd1 = get_unused_fd_flags(flags);
1435bf3c23d1SDavid S. Miller 	if (unlikely(fd1 < 0)) {
1436bf3c23d1SDavid S. Miller 		err = fd1;
14371da177e4SLinus Torvalds 		goto out_release_both;
1438bf3c23d1SDavid S. Miller 	}
143928407630SAl Viro 	fd2 = get_unused_fd_flags(flags);
1440198de4d7SAl Viro 	if (unlikely(fd2 < 0)) {
1441198de4d7SAl Viro 		err = fd2;
144228407630SAl Viro 		put_unused_fd(fd1);
144328407630SAl Viro 		goto out_release_both;
144428407630SAl Viro 	}
144528407630SAl Viro 
1446aab174f0SLinus Torvalds 	newfile1 = sock_alloc_file(sock1, flags, NULL);
144728407630SAl Viro 	if (unlikely(IS_ERR(newfile1))) {
144828407630SAl Viro 		err = PTR_ERR(newfile1);
144928407630SAl Viro 		put_unused_fd(fd1);
145028407630SAl Viro 		put_unused_fd(fd2);
145128407630SAl Viro 		goto out_release_both;
145228407630SAl Viro 	}
145328407630SAl Viro 
1454aab174f0SLinus Torvalds 	newfile2 = sock_alloc_file(sock2, flags, NULL);
145528407630SAl Viro 	if (IS_ERR(newfile2)) {
145628407630SAl Viro 		err = PTR_ERR(newfile2);
1457198de4d7SAl Viro 		fput(newfile1);
1458198de4d7SAl Viro 		put_unused_fd(fd1);
145928407630SAl Viro 		put_unused_fd(fd2);
1460198de4d7SAl Viro 		sock_release(sock2);
1461198de4d7SAl Viro 		goto out;
1462db349509SAl Viro 	}
1463db349509SAl Viro 
1464157cf649SAl Viro 	audit_fd_pair(fd1, fd2);
1465db349509SAl Viro 	fd_install(fd1, newfile1);
1466db349509SAl Viro 	fd_install(fd2, newfile2);
14671da177e4SLinus Torvalds 	/* fd1 and fd2 may be already another descriptors.
14681da177e4SLinus Torvalds 	 * Not kernel problem.
14691da177e4SLinus Torvalds 	 */
14701da177e4SLinus Torvalds 
14711da177e4SLinus Torvalds 	err = put_user(fd1, &usockvec[0]);
14721da177e4SLinus Torvalds 	if (!err)
14731da177e4SLinus Torvalds 		err = put_user(fd2, &usockvec[1]);
14741da177e4SLinus Torvalds 	if (!err)
14751da177e4SLinus Torvalds 		return 0;
14761da177e4SLinus Torvalds 
14771da177e4SLinus Torvalds 	sys_close(fd2);
14781da177e4SLinus Torvalds 	sys_close(fd1);
14791da177e4SLinus Torvalds 	return err;
14801da177e4SLinus Torvalds 
14811da177e4SLinus Torvalds out_release_both:
14821da177e4SLinus Torvalds 	sock_release(sock2);
14831da177e4SLinus Torvalds out_release_1:
14841da177e4SLinus Torvalds 	sock_release(sock1);
14851da177e4SLinus Torvalds out:
14861da177e4SLinus Torvalds 	return err;
14871da177e4SLinus Torvalds }
14881da177e4SLinus Torvalds 
14891da177e4SLinus Torvalds /*
14901da177e4SLinus Torvalds  *	Bind a name to a socket. Nothing much to do here since it's
14911da177e4SLinus Torvalds  *	the protocol's responsibility to handle the local address.
14921da177e4SLinus Torvalds  *
14931da177e4SLinus Torvalds  *	We move the socket address to kernel space before we call
14941da177e4SLinus Torvalds  *	the protocol layer (having also checked the address is ok).
14951da177e4SLinus Torvalds  */
14961da177e4SLinus Torvalds 
149720f37034SHeiko Carstens SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
14981da177e4SLinus Torvalds {
14991da177e4SLinus Torvalds 	struct socket *sock;
1500230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
15016cb153caSBenjamin LaHaise 	int err, fput_needed;
15021da177e4SLinus Torvalds 
150389bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
150489bddce5SStephen Hemminger 	if (sock) {
150543db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(umyaddr, addrlen, &address);
150689bddce5SStephen Hemminger 		if (err >= 0) {
150789bddce5SStephen Hemminger 			err = security_socket_bind(sock,
1508230b1839SYOSHIFUJI Hideaki 						   (struct sockaddr *)&address,
150989bddce5SStephen Hemminger 						   addrlen);
15106cb153caSBenjamin LaHaise 			if (!err)
15116cb153caSBenjamin LaHaise 				err = sock->ops->bind(sock,
151289bddce5SStephen Hemminger 						      (struct sockaddr *)
1513230b1839SYOSHIFUJI Hideaki 						      &address, addrlen);
15141da177e4SLinus Torvalds 		}
15156cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
15161da177e4SLinus Torvalds 	}
15171da177e4SLinus Torvalds 	return err;
15181da177e4SLinus Torvalds }
15191da177e4SLinus Torvalds 
15201da177e4SLinus Torvalds /*
15211da177e4SLinus Torvalds  *	Perform a listen. Basically, we allow the protocol to do anything
15221da177e4SLinus Torvalds  *	necessary for a listen, and if that works, we mark the socket as
15231da177e4SLinus Torvalds  *	ready for listening.
15241da177e4SLinus Torvalds  */
15251da177e4SLinus Torvalds 
15263e0fa65fSHeiko Carstens SYSCALL_DEFINE2(listen, int, fd, int, backlog)
15271da177e4SLinus Torvalds {
15281da177e4SLinus Torvalds 	struct socket *sock;
15296cb153caSBenjamin LaHaise 	int err, fput_needed;
1530b8e1f9b5SPavel Emelyanov 	int somaxconn;
15311da177e4SLinus Torvalds 
153289bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
153389bddce5SStephen Hemminger 	if (sock) {
15348efa6e93SPavel Emelyanov 		somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
153595c96174SEric Dumazet 		if ((unsigned int)backlog > somaxconn)
1536b8e1f9b5SPavel Emelyanov 			backlog = somaxconn;
15371da177e4SLinus Torvalds 
15381da177e4SLinus Torvalds 		err = security_socket_listen(sock, backlog);
15396cb153caSBenjamin LaHaise 		if (!err)
15401da177e4SLinus Torvalds 			err = sock->ops->listen(sock, backlog);
15416cb153caSBenjamin LaHaise 
15426cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
15431da177e4SLinus Torvalds 	}
15441da177e4SLinus Torvalds 	return err;
15451da177e4SLinus Torvalds }
15461da177e4SLinus Torvalds 
15471da177e4SLinus Torvalds /*
15481da177e4SLinus Torvalds  *	For accept, we attempt to create a new socket, set up the link
15491da177e4SLinus Torvalds  *	with the client, wake up the client, then return the new
15501da177e4SLinus Torvalds  *	connected fd. We collect the address of the connector in kernel
15511da177e4SLinus Torvalds  *	space and move it to user at the very end. This is unclean because
15521da177e4SLinus Torvalds  *	we open the socket then return an error.
15531da177e4SLinus Torvalds  *
15541da177e4SLinus Torvalds  *	1003.1g adds the ability to recvmsg() to query connection pending
15551da177e4SLinus Torvalds  *	status to recvmsg. We need to add that support in a way thats
15561da177e4SLinus Torvalds  *	clean when we restucture accept also.
15571da177e4SLinus Torvalds  */
15581da177e4SLinus Torvalds 
155920f37034SHeiko Carstens SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
156020f37034SHeiko Carstens 		int __user *, upeer_addrlen, int, flags)
15611da177e4SLinus Torvalds {
15621da177e4SLinus Torvalds 	struct socket *sock, *newsock;
156339d8c1b6SDavid S. Miller 	struct file *newfile;
15646cb153caSBenjamin LaHaise 	int err, len, newfd, fput_needed;
1565230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
15661da177e4SLinus Torvalds 
156777d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1568aaca0bdcSUlrich Drepper 		return -EINVAL;
1569aaca0bdcSUlrich Drepper 
1570aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1571aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1572aaca0bdcSUlrich Drepper 
15736cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
15741da177e4SLinus Torvalds 	if (!sock)
15751da177e4SLinus Torvalds 		goto out;
15761da177e4SLinus Torvalds 
15771da177e4SLinus Torvalds 	err = -ENFILE;
1578c6d409cfSEric Dumazet 	newsock = sock_alloc();
1579c6d409cfSEric Dumazet 	if (!newsock)
15801da177e4SLinus Torvalds 		goto out_put;
15811da177e4SLinus Torvalds 
15821da177e4SLinus Torvalds 	newsock->type = sock->type;
15831da177e4SLinus Torvalds 	newsock->ops = sock->ops;
15841da177e4SLinus Torvalds 
15851da177e4SLinus Torvalds 	/*
15861da177e4SLinus Torvalds 	 * We don't need try_module_get here, as the listening socket (sock)
15871da177e4SLinus Torvalds 	 * has the protocol module (sock->ops->owner) held.
15881da177e4SLinus Torvalds 	 */
15891da177e4SLinus Torvalds 	__module_get(newsock->ops->owner);
15901da177e4SLinus Torvalds 
159128407630SAl Viro 	newfd = get_unused_fd_flags(flags);
159239d8c1b6SDavid S. Miller 	if (unlikely(newfd < 0)) {
159339d8c1b6SDavid S. Miller 		err = newfd;
15949a1875e6SDavid S. Miller 		sock_release(newsock);
15959a1875e6SDavid S. Miller 		goto out_put;
159639d8c1b6SDavid S. Miller 	}
1597aab174f0SLinus Torvalds 	newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name);
159828407630SAl Viro 	if (unlikely(IS_ERR(newfile))) {
159928407630SAl Viro 		err = PTR_ERR(newfile);
160028407630SAl Viro 		put_unused_fd(newfd);
160128407630SAl Viro 		sock_release(newsock);
160228407630SAl Viro 		goto out_put;
160328407630SAl Viro 	}
160439d8c1b6SDavid S. Miller 
1605a79af59eSFrank Filz 	err = security_socket_accept(sock, newsock);
1606a79af59eSFrank Filz 	if (err)
160739d8c1b6SDavid S. Miller 		goto out_fd;
1608a79af59eSFrank Filz 
16091da177e4SLinus Torvalds 	err = sock->ops->accept(sock, newsock, sock->file->f_flags);
16101da177e4SLinus Torvalds 	if (err < 0)
161139d8c1b6SDavid S. Miller 		goto out_fd;
16121da177e4SLinus Torvalds 
16131da177e4SLinus Torvalds 	if (upeer_sockaddr) {
1614230b1839SYOSHIFUJI Hideaki 		if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
161589bddce5SStephen Hemminger 					  &len, 2) < 0) {
16161da177e4SLinus Torvalds 			err = -ECONNABORTED;
161739d8c1b6SDavid S. Miller 			goto out_fd;
16181da177e4SLinus Torvalds 		}
161943db362dSMaciej Żenczykowski 		err = move_addr_to_user(&address,
1620230b1839SYOSHIFUJI Hideaki 					len, upeer_sockaddr, upeer_addrlen);
16211da177e4SLinus Torvalds 		if (err < 0)
162239d8c1b6SDavid S. Miller 			goto out_fd;
16231da177e4SLinus Torvalds 	}
16241da177e4SLinus Torvalds 
16251da177e4SLinus Torvalds 	/* File flags are not inherited via accept() unlike another OSes. */
16261da177e4SLinus Torvalds 
162739d8c1b6SDavid S. Miller 	fd_install(newfd, newfile);
162839d8c1b6SDavid S. Miller 	err = newfd;
16291da177e4SLinus Torvalds 
16301da177e4SLinus Torvalds out_put:
16316cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
16321da177e4SLinus Torvalds out:
16331da177e4SLinus Torvalds 	return err;
163439d8c1b6SDavid S. Miller out_fd:
16359606a216SDavid S. Miller 	fput(newfile);
163639d8c1b6SDavid S. Miller 	put_unused_fd(newfd);
16371da177e4SLinus Torvalds 	goto out_put;
16381da177e4SLinus Torvalds }
16391da177e4SLinus Torvalds 
164020f37034SHeiko Carstens SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,
164120f37034SHeiko Carstens 		int __user *, upeer_addrlen)
1642aaca0bdcSUlrich Drepper {
1643de11defeSUlrich Drepper 	return sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0);
1644aaca0bdcSUlrich Drepper }
1645aaca0bdcSUlrich Drepper 
16461da177e4SLinus Torvalds /*
16471da177e4SLinus Torvalds  *	Attempt to connect to a socket with the server address.  The address
16481da177e4SLinus Torvalds  *	is in user space so we verify it is OK and move it to kernel space.
16491da177e4SLinus Torvalds  *
16501da177e4SLinus Torvalds  *	For 1003.1g we need to add clean support for a bind to AF_UNSPEC to
16511da177e4SLinus Torvalds  *	break bindings
16521da177e4SLinus Torvalds  *
16531da177e4SLinus Torvalds  *	NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and
16541da177e4SLinus Torvalds  *	other SEQPACKET protocols that take time to connect() as it doesn't
16551da177e4SLinus Torvalds  *	include the -EINPROGRESS status for such sockets.
16561da177e4SLinus Torvalds  */
16571da177e4SLinus Torvalds 
165820f37034SHeiko Carstens SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
165920f37034SHeiko Carstens 		int, addrlen)
16601da177e4SLinus Torvalds {
16611da177e4SLinus Torvalds 	struct socket *sock;
1662230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16636cb153caSBenjamin LaHaise 	int err, fput_needed;
16641da177e4SLinus Torvalds 
16656cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
16661da177e4SLinus Torvalds 	if (!sock)
16671da177e4SLinus Torvalds 		goto out;
166843db362dSMaciej Żenczykowski 	err = move_addr_to_kernel(uservaddr, addrlen, &address);
16691da177e4SLinus Torvalds 	if (err < 0)
16701da177e4SLinus Torvalds 		goto out_put;
16711da177e4SLinus Torvalds 
167289bddce5SStephen Hemminger 	err =
1673230b1839SYOSHIFUJI Hideaki 	    security_socket_connect(sock, (struct sockaddr *)&address, addrlen);
16741da177e4SLinus Torvalds 	if (err)
16751da177e4SLinus Torvalds 		goto out_put;
16761da177e4SLinus Torvalds 
1677230b1839SYOSHIFUJI Hideaki 	err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,
16781da177e4SLinus Torvalds 				 sock->file->f_flags);
16791da177e4SLinus Torvalds out_put:
16806cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
16811da177e4SLinus Torvalds out:
16821da177e4SLinus Torvalds 	return err;
16831da177e4SLinus Torvalds }
16841da177e4SLinus Torvalds 
16851da177e4SLinus Torvalds /*
16861da177e4SLinus Torvalds  *	Get the local address ('name') of a socket object. Move the obtained
16871da177e4SLinus Torvalds  *	name to user space.
16881da177e4SLinus Torvalds  */
16891da177e4SLinus Torvalds 
169020f37034SHeiko Carstens SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
169120f37034SHeiko Carstens 		int __user *, usockaddr_len)
16921da177e4SLinus Torvalds {
16931da177e4SLinus Torvalds 	struct socket *sock;
1694230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16956cb153caSBenjamin LaHaise 	int len, err, fput_needed;
16961da177e4SLinus Torvalds 
16976cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
16981da177e4SLinus Torvalds 	if (!sock)
16991da177e4SLinus Torvalds 		goto out;
17001da177e4SLinus Torvalds 
17011da177e4SLinus Torvalds 	err = security_socket_getsockname(sock);
17021da177e4SLinus Torvalds 	if (err)
17031da177e4SLinus Torvalds 		goto out_put;
17041da177e4SLinus Torvalds 
1705230b1839SYOSHIFUJI Hideaki 	err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0);
17061da177e4SLinus Torvalds 	if (err)
17071da177e4SLinus Torvalds 		goto out_put;
170843db362dSMaciej Żenczykowski 	err = move_addr_to_user(&address, len, usockaddr, usockaddr_len);
17091da177e4SLinus Torvalds 
17101da177e4SLinus Torvalds out_put:
17116cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
17121da177e4SLinus Torvalds out:
17131da177e4SLinus Torvalds 	return err;
17141da177e4SLinus Torvalds }
17151da177e4SLinus Torvalds 
17161da177e4SLinus Torvalds /*
17171da177e4SLinus Torvalds  *	Get the remote address ('name') of a socket object. Move the obtained
17181da177e4SLinus Torvalds  *	name to user space.
17191da177e4SLinus Torvalds  */
17201da177e4SLinus Torvalds 
172120f37034SHeiko Carstens SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
172220f37034SHeiko Carstens 		int __user *, usockaddr_len)
17231da177e4SLinus Torvalds {
17241da177e4SLinus Torvalds 	struct socket *sock;
1725230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
17266cb153caSBenjamin LaHaise 	int len, err, fput_needed;
17271da177e4SLinus Torvalds 
172889bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
172989bddce5SStephen Hemminger 	if (sock != NULL) {
17301da177e4SLinus Torvalds 		err = security_socket_getpeername(sock);
17311da177e4SLinus Torvalds 		if (err) {
17326cb153caSBenjamin LaHaise 			fput_light(sock->file, fput_needed);
17331da177e4SLinus Torvalds 			return err;
17341da177e4SLinus Torvalds 		}
17351da177e4SLinus Torvalds 
173689bddce5SStephen Hemminger 		err =
1737230b1839SYOSHIFUJI Hideaki 		    sock->ops->getname(sock, (struct sockaddr *)&address, &len,
173889bddce5SStephen Hemminger 				       1);
17391da177e4SLinus Torvalds 		if (!err)
174043db362dSMaciej Żenczykowski 			err = move_addr_to_user(&address, len, usockaddr,
174189bddce5SStephen Hemminger 						usockaddr_len);
17426cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
17431da177e4SLinus Torvalds 	}
17441da177e4SLinus Torvalds 	return err;
17451da177e4SLinus Torvalds }
17461da177e4SLinus Torvalds 
17471da177e4SLinus Torvalds /*
17481da177e4SLinus Torvalds  *	Send a datagram to a given address. We move the address into kernel
17491da177e4SLinus Torvalds  *	space and check the user space data area is readable before invoking
17501da177e4SLinus Torvalds  *	the protocol.
17511da177e4SLinus Torvalds  */
17521da177e4SLinus Torvalds 
17533e0fa65fSHeiko Carstens SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
175495c96174SEric Dumazet 		unsigned int, flags, struct sockaddr __user *, addr,
17553e0fa65fSHeiko Carstens 		int, addr_len)
17561da177e4SLinus Torvalds {
17571da177e4SLinus Torvalds 	struct socket *sock;
1758230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
17591da177e4SLinus Torvalds 	int err;
17601da177e4SLinus Torvalds 	struct msghdr msg;
17611da177e4SLinus Torvalds 	struct iovec iov;
17626cb153caSBenjamin LaHaise 	int fput_needed;
17631da177e4SLinus Torvalds 
1764253eacc0SLinus Torvalds 	if (len > INT_MAX)
1765253eacc0SLinus Torvalds 		len = INT_MAX;
1766de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1767de0fa95cSPavel Emelyanov 	if (!sock)
17684387ff75SDavid S. Miller 		goto out;
17696cb153caSBenjamin LaHaise 
17701da177e4SLinus Torvalds 	iov.iov_base = buff;
17711da177e4SLinus Torvalds 	iov.iov_len = len;
17721da177e4SLinus Torvalds 	msg.msg_name = NULL;
17731da177e4SLinus Torvalds 	msg.msg_iov = &iov;
17741da177e4SLinus Torvalds 	msg.msg_iovlen = 1;
17751da177e4SLinus Torvalds 	msg.msg_control = NULL;
17761da177e4SLinus Torvalds 	msg.msg_controllen = 0;
17771da177e4SLinus Torvalds 	msg.msg_namelen = 0;
17786cb153caSBenjamin LaHaise 	if (addr) {
177943db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(addr, addr_len, &address);
17801da177e4SLinus Torvalds 		if (err < 0)
17811da177e4SLinus Torvalds 			goto out_put;
1782230b1839SYOSHIFUJI Hideaki 		msg.msg_name = (struct sockaddr *)&address;
17831da177e4SLinus Torvalds 		msg.msg_namelen = addr_len;
17841da177e4SLinus Torvalds 	}
17851da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
17861da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
17871da177e4SLinus Torvalds 	msg.msg_flags = flags;
17881da177e4SLinus Torvalds 	err = sock_sendmsg(sock, &msg, len);
17891da177e4SLinus Torvalds 
17901da177e4SLinus Torvalds out_put:
1791de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
17924387ff75SDavid S. Miller out:
17931da177e4SLinus Torvalds 	return err;
17941da177e4SLinus Torvalds }
17951da177e4SLinus Torvalds 
17961da177e4SLinus Torvalds /*
17971da177e4SLinus Torvalds  *	Send a datagram down a socket.
17981da177e4SLinus Torvalds  */
17991da177e4SLinus Torvalds 
18003e0fa65fSHeiko Carstens SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len,
180195c96174SEric Dumazet 		unsigned int, flags)
18021da177e4SLinus Torvalds {
18031da177e4SLinus Torvalds 	return sys_sendto(fd, buff, len, flags, NULL, 0);
18041da177e4SLinus Torvalds }
18051da177e4SLinus Torvalds 
18061da177e4SLinus Torvalds /*
18071da177e4SLinus Torvalds  *	Receive a frame from the socket and optionally record the address of the
18081da177e4SLinus Torvalds  *	sender. We verify the buffers are writable and if needed move the
18091da177e4SLinus Torvalds  *	sender address from kernel to user space.
18101da177e4SLinus Torvalds  */
18111da177e4SLinus Torvalds 
18123e0fa65fSHeiko Carstens SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
181395c96174SEric Dumazet 		unsigned int, flags, struct sockaddr __user *, addr,
18143e0fa65fSHeiko Carstens 		int __user *, addr_len)
18151da177e4SLinus Torvalds {
18161da177e4SLinus Torvalds 	struct socket *sock;
18171da177e4SLinus Torvalds 	struct iovec iov;
18181da177e4SLinus Torvalds 	struct msghdr msg;
1819230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
18201da177e4SLinus Torvalds 	int err, err2;
18216cb153caSBenjamin LaHaise 	int fput_needed;
18221da177e4SLinus Torvalds 
1823253eacc0SLinus Torvalds 	if (size > INT_MAX)
1824253eacc0SLinus Torvalds 		size = INT_MAX;
1825de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
18261da177e4SLinus Torvalds 	if (!sock)
1827de0fa95cSPavel Emelyanov 		goto out;
18281da177e4SLinus Torvalds 
18291da177e4SLinus Torvalds 	msg.msg_control = NULL;
18301da177e4SLinus Torvalds 	msg.msg_controllen = 0;
18311da177e4SLinus Torvalds 	msg.msg_iovlen = 1;
18321da177e4SLinus Torvalds 	msg.msg_iov = &iov;
18331da177e4SLinus Torvalds 	iov.iov_len = size;
18341da177e4SLinus Torvalds 	iov.iov_base = ubuf;
1835230b1839SYOSHIFUJI Hideaki 	msg.msg_name = (struct sockaddr *)&address;
1836230b1839SYOSHIFUJI Hideaki 	msg.msg_namelen = sizeof(address);
18371da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
18381da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
18391da177e4SLinus Torvalds 	err = sock_recvmsg(sock, &msg, size, flags);
18401da177e4SLinus Torvalds 
184189bddce5SStephen Hemminger 	if (err >= 0 && addr != NULL) {
184243db362dSMaciej Żenczykowski 		err2 = move_addr_to_user(&address,
1843230b1839SYOSHIFUJI Hideaki 					 msg.msg_namelen, addr, addr_len);
18441da177e4SLinus Torvalds 		if (err2 < 0)
18451da177e4SLinus Torvalds 			err = err2;
18461da177e4SLinus Torvalds 	}
1847de0fa95cSPavel Emelyanov 
1848de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
18494387ff75SDavid S. Miller out:
18501da177e4SLinus Torvalds 	return err;
18511da177e4SLinus Torvalds }
18521da177e4SLinus Torvalds 
18531da177e4SLinus Torvalds /*
18541da177e4SLinus Torvalds  *	Receive a datagram from a socket.
18551da177e4SLinus Torvalds  */
18561da177e4SLinus Torvalds 
185789bddce5SStephen Hemminger asmlinkage long sys_recv(int fd, void __user *ubuf, size_t size,
185895c96174SEric Dumazet 			 unsigned int flags)
18591da177e4SLinus Torvalds {
18601da177e4SLinus Torvalds 	return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL);
18611da177e4SLinus Torvalds }
18621da177e4SLinus Torvalds 
18631da177e4SLinus Torvalds /*
18641da177e4SLinus Torvalds  *	Set a socket option. Because we don't know the option lengths we have
18651da177e4SLinus Torvalds  *	to pass the user mode parameter for the protocols to sort out.
18661da177e4SLinus Torvalds  */
18671da177e4SLinus Torvalds 
186820f37034SHeiko Carstens SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
186920f37034SHeiko Carstens 		char __user *, optval, int, optlen)
18701da177e4SLinus Torvalds {
18716cb153caSBenjamin LaHaise 	int err, fput_needed;
18721da177e4SLinus Torvalds 	struct socket *sock;
18731da177e4SLinus Torvalds 
18741da177e4SLinus Torvalds 	if (optlen < 0)
18751da177e4SLinus Torvalds 		return -EINVAL;
18761da177e4SLinus Torvalds 
187789bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
187889bddce5SStephen Hemminger 	if (sock != NULL) {
18791da177e4SLinus Torvalds 		err = security_socket_setsockopt(sock, level, optname);
18806cb153caSBenjamin LaHaise 		if (err)
18816cb153caSBenjamin LaHaise 			goto out_put;
18821da177e4SLinus Torvalds 
18831da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
188489bddce5SStephen Hemminger 			err =
188589bddce5SStephen Hemminger 			    sock_setsockopt(sock, level, optname, optval,
188689bddce5SStephen Hemminger 					    optlen);
18871da177e4SLinus Torvalds 		else
188889bddce5SStephen Hemminger 			err =
188989bddce5SStephen Hemminger 			    sock->ops->setsockopt(sock, level, optname, optval,
189089bddce5SStephen Hemminger 						  optlen);
18916cb153caSBenjamin LaHaise out_put:
18926cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
18931da177e4SLinus Torvalds 	}
18941da177e4SLinus Torvalds 	return err;
18951da177e4SLinus Torvalds }
18961da177e4SLinus Torvalds 
18971da177e4SLinus Torvalds /*
18981da177e4SLinus Torvalds  *	Get a socket option. Because we don't know the option lengths we have
18991da177e4SLinus Torvalds  *	to pass a user mode parameter for the protocols to sort out.
19001da177e4SLinus Torvalds  */
19011da177e4SLinus Torvalds 
190220f37034SHeiko Carstens SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
190320f37034SHeiko Carstens 		char __user *, optval, int __user *, optlen)
19041da177e4SLinus Torvalds {
19056cb153caSBenjamin LaHaise 	int err, fput_needed;
19061da177e4SLinus Torvalds 	struct socket *sock;
19071da177e4SLinus Torvalds 
190889bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
190989bddce5SStephen Hemminger 	if (sock != NULL) {
19106cb153caSBenjamin LaHaise 		err = security_socket_getsockopt(sock, level, optname);
19116cb153caSBenjamin LaHaise 		if (err)
19126cb153caSBenjamin LaHaise 			goto out_put;
19131da177e4SLinus Torvalds 
19141da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
191589bddce5SStephen Hemminger 			err =
191689bddce5SStephen Hemminger 			    sock_getsockopt(sock, level, optname, optval,
191789bddce5SStephen Hemminger 					    optlen);
19181da177e4SLinus Torvalds 		else
191989bddce5SStephen Hemminger 			err =
192089bddce5SStephen Hemminger 			    sock->ops->getsockopt(sock, level, optname, optval,
192189bddce5SStephen Hemminger 						  optlen);
19226cb153caSBenjamin LaHaise out_put:
19236cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
19241da177e4SLinus Torvalds 	}
19251da177e4SLinus Torvalds 	return err;
19261da177e4SLinus Torvalds }
19271da177e4SLinus Torvalds 
19281da177e4SLinus Torvalds /*
19291da177e4SLinus Torvalds  *	Shutdown a socket.
19301da177e4SLinus Torvalds  */
19311da177e4SLinus Torvalds 
1932754fe8d2SHeiko Carstens SYSCALL_DEFINE2(shutdown, int, fd, int, how)
19331da177e4SLinus Torvalds {
19346cb153caSBenjamin LaHaise 	int err, fput_needed;
19351da177e4SLinus Torvalds 	struct socket *sock;
19361da177e4SLinus Torvalds 
193789bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
193889bddce5SStephen Hemminger 	if (sock != NULL) {
19391da177e4SLinus Torvalds 		err = security_socket_shutdown(sock, how);
19406cb153caSBenjamin LaHaise 		if (!err)
19411da177e4SLinus Torvalds 			err = sock->ops->shutdown(sock, how);
19426cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
19431da177e4SLinus Torvalds 	}
19441da177e4SLinus Torvalds 	return err;
19451da177e4SLinus Torvalds }
19461da177e4SLinus Torvalds 
19471da177e4SLinus Torvalds /* A couple of helpful macros for getting the address of the 32/64 bit
19481da177e4SLinus Torvalds  * fields which are the same type (int / unsigned) on our platforms.
19491da177e4SLinus Torvalds  */
19501da177e4SLinus Torvalds #define COMPAT_MSG(msg, member)	((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member)
19511da177e4SLinus Torvalds #define COMPAT_NAMELEN(msg)	COMPAT_MSG(msg, msg_namelen)
19521da177e4SLinus Torvalds #define COMPAT_FLAGS(msg)	COMPAT_MSG(msg, msg_flags)
19531da177e4SLinus Torvalds 
1954c71d8ebeSTetsuo Handa struct used_address {
1955c71d8ebeSTetsuo Handa 	struct sockaddr_storage name;
1956c71d8ebeSTetsuo Handa 	unsigned int name_len;
1957c71d8ebeSTetsuo Handa };
1958c71d8ebeSTetsuo Handa 
1959228e548eSAnton Blanchard static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
196095c96174SEric Dumazet 			 struct msghdr *msg_sys, unsigned int flags,
1961c71d8ebeSTetsuo Handa 			 struct used_address *used_address)
19621da177e4SLinus Torvalds {
196389bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
196489bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
1965230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
19661da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
1967b9d717a7SAlex Williamson 	unsigned char ctl[sizeof(struct cmsghdr) + 20]
1968b9d717a7SAlex Williamson 	    __attribute__ ((aligned(sizeof(__kernel_size_t))));
1969b9d717a7SAlex Williamson 	/* 20 is size of ipv6_pktinfo */
19701da177e4SLinus Torvalds 	unsigned char *ctl_buf = ctl;
1971a74e9106SEric Dumazet 	int err, ctl_len, total_len;
19721da177e4SLinus Torvalds 
19731da177e4SLinus Torvalds 	err = -EFAULT;
19741da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
1975228e548eSAnton Blanchard 		if (get_compat_msghdr(msg_sys, msg_compat))
19761da177e4SLinus Torvalds 			return -EFAULT;
1977228e548eSAnton Blanchard 	} else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr)))
19781da177e4SLinus Torvalds 		return -EFAULT;
19791da177e4SLinus Torvalds 
1980a74e9106SEric Dumazet 	if (msg_sys->msg_iovlen > UIO_FASTIOV) {
19811da177e4SLinus Torvalds 		err = -EMSGSIZE;
1982228e548eSAnton Blanchard 		if (msg_sys->msg_iovlen > UIO_MAXIOV)
1983228e548eSAnton Blanchard 			goto out;
19841da177e4SLinus Torvalds 		err = -ENOMEM;
1985a74e9106SEric Dumazet 		iov = kmalloc(msg_sys->msg_iovlen * sizeof(struct iovec),
1986a74e9106SEric Dumazet 			      GFP_KERNEL);
19871da177e4SLinus Torvalds 		if (!iov)
1988228e548eSAnton Blanchard 			goto out;
19891da177e4SLinus Torvalds 	}
19901da177e4SLinus Torvalds 
19911da177e4SLinus Torvalds 	/* This will also move the address data into kernel space */
19921da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
199343db362dSMaciej Żenczykowski 		err = verify_compat_iovec(msg_sys, iov, &address, VERIFY_READ);
19941da177e4SLinus Torvalds 	} else
199543db362dSMaciej Żenczykowski 		err = verify_iovec(msg_sys, iov, &address, VERIFY_READ);
19961da177e4SLinus Torvalds 	if (err < 0)
19971da177e4SLinus Torvalds 		goto out_freeiov;
19981da177e4SLinus Torvalds 	total_len = err;
19991da177e4SLinus Torvalds 
20001da177e4SLinus Torvalds 	err = -ENOBUFS;
20011da177e4SLinus Torvalds 
2002228e548eSAnton Blanchard 	if (msg_sys->msg_controllen > INT_MAX)
20031da177e4SLinus Torvalds 		goto out_freeiov;
2004228e548eSAnton Blanchard 	ctl_len = msg_sys->msg_controllen;
20051da177e4SLinus Torvalds 	if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
200689bddce5SStephen Hemminger 		err =
2007228e548eSAnton Blanchard 		    cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl,
200889bddce5SStephen Hemminger 						     sizeof(ctl));
20091da177e4SLinus Torvalds 		if (err)
20101da177e4SLinus Torvalds 			goto out_freeiov;
2011228e548eSAnton Blanchard 		ctl_buf = msg_sys->msg_control;
2012228e548eSAnton Blanchard 		ctl_len = msg_sys->msg_controllen;
20131da177e4SLinus Torvalds 	} else if (ctl_len) {
201489bddce5SStephen Hemminger 		if (ctl_len > sizeof(ctl)) {
20151da177e4SLinus Torvalds 			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
20161da177e4SLinus Torvalds 			if (ctl_buf == NULL)
20171da177e4SLinus Torvalds 				goto out_freeiov;
20181da177e4SLinus Torvalds 		}
20191da177e4SLinus Torvalds 		err = -EFAULT;
20201da177e4SLinus Torvalds 		/*
2021228e548eSAnton Blanchard 		 * Careful! Before this, msg_sys->msg_control contains a user pointer.
20221da177e4SLinus Torvalds 		 * Afterwards, it will be a kernel pointer. Thus the compiler-assisted
20231da177e4SLinus Torvalds 		 * checking falls down on this.
20241da177e4SLinus Torvalds 		 */
2025fb8621bbSNamhyung Kim 		if (copy_from_user(ctl_buf,
2026228e548eSAnton Blanchard 				   (void __user __force *)msg_sys->msg_control,
202789bddce5SStephen Hemminger 				   ctl_len))
20281da177e4SLinus Torvalds 			goto out_freectl;
2029228e548eSAnton Blanchard 		msg_sys->msg_control = ctl_buf;
20301da177e4SLinus Torvalds 	}
2031228e548eSAnton Blanchard 	msg_sys->msg_flags = flags;
20321da177e4SLinus Torvalds 
20331da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
2034228e548eSAnton Blanchard 		msg_sys->msg_flags |= MSG_DONTWAIT;
2035c71d8ebeSTetsuo Handa 	/*
2036c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and current destination address is same as
2037c71d8ebeSTetsuo Handa 	 * previously succeeded address, omit asking LSM's decision.
2038c71d8ebeSTetsuo Handa 	 * used_address->name_len is initialized to UINT_MAX so that the first
2039c71d8ebeSTetsuo Handa 	 * destination address never matches.
2040c71d8ebeSTetsuo Handa 	 */
2041bc909d9dSMathieu Desnoyers 	if (used_address && msg_sys->msg_name &&
2042bc909d9dSMathieu Desnoyers 	    used_address->name_len == msg_sys->msg_namelen &&
2043bc909d9dSMathieu Desnoyers 	    !memcmp(&used_address->name, msg_sys->msg_name,
2044c71d8ebeSTetsuo Handa 		    used_address->name_len)) {
2045c71d8ebeSTetsuo Handa 		err = sock_sendmsg_nosec(sock, msg_sys, total_len);
2046c71d8ebeSTetsuo Handa 		goto out_freectl;
2047c71d8ebeSTetsuo Handa 	}
2048c71d8ebeSTetsuo Handa 	err = sock_sendmsg(sock, msg_sys, total_len);
2049c71d8ebeSTetsuo Handa 	/*
2050c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and sending to current destination address was
2051c71d8ebeSTetsuo Handa 	 * successful, remember it.
2052c71d8ebeSTetsuo Handa 	 */
2053c71d8ebeSTetsuo Handa 	if (used_address && err >= 0) {
2054c71d8ebeSTetsuo Handa 		used_address->name_len = msg_sys->msg_namelen;
2055bc909d9dSMathieu Desnoyers 		if (msg_sys->msg_name)
2056bc909d9dSMathieu Desnoyers 			memcpy(&used_address->name, msg_sys->msg_name,
2057c71d8ebeSTetsuo Handa 			       used_address->name_len);
2058c71d8ebeSTetsuo Handa 	}
20591da177e4SLinus Torvalds 
20601da177e4SLinus Torvalds out_freectl:
20611da177e4SLinus Torvalds 	if (ctl_buf != ctl)
20621da177e4SLinus Torvalds 		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
20631da177e4SLinus Torvalds out_freeiov:
20641da177e4SLinus Torvalds 	if (iov != iovstack)
2065a74e9106SEric Dumazet 		kfree(iov);
2066228e548eSAnton Blanchard out:
2067228e548eSAnton Blanchard 	return err;
2068228e548eSAnton Blanchard }
2069228e548eSAnton Blanchard 
2070228e548eSAnton Blanchard /*
2071228e548eSAnton Blanchard  *	BSD sendmsg interface
2072228e548eSAnton Blanchard  */
2073228e548eSAnton Blanchard 
207495c96174SEric Dumazet SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned int, flags)
2075228e548eSAnton Blanchard {
2076228e548eSAnton Blanchard 	int fput_needed, err;
2077228e548eSAnton Blanchard 	struct msghdr msg_sys;
2078228e548eSAnton Blanchard 	struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed);
2079228e548eSAnton Blanchard 
2080228e548eSAnton Blanchard 	if (!sock)
2081228e548eSAnton Blanchard 		goto out;
2082228e548eSAnton Blanchard 
2083c71d8ebeSTetsuo Handa 	err = __sys_sendmsg(sock, msg, &msg_sys, flags, NULL);
2084228e548eSAnton Blanchard 
20856cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
20861da177e4SLinus Torvalds out:
20871da177e4SLinus Torvalds 	return err;
20881da177e4SLinus Torvalds }
20891da177e4SLinus Torvalds 
2090228e548eSAnton Blanchard /*
2091228e548eSAnton Blanchard  *	Linux sendmmsg interface
2092228e548eSAnton Blanchard  */
2093228e548eSAnton Blanchard 
2094228e548eSAnton Blanchard int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2095228e548eSAnton Blanchard 		   unsigned int flags)
2096228e548eSAnton Blanchard {
2097228e548eSAnton Blanchard 	int fput_needed, err, datagrams;
2098228e548eSAnton Blanchard 	struct socket *sock;
2099228e548eSAnton Blanchard 	struct mmsghdr __user *entry;
2100228e548eSAnton Blanchard 	struct compat_mmsghdr __user *compat_entry;
2101228e548eSAnton Blanchard 	struct msghdr msg_sys;
2102c71d8ebeSTetsuo Handa 	struct used_address used_address;
2103228e548eSAnton Blanchard 
210498382f41SAnton Blanchard 	if (vlen > UIO_MAXIOV)
210598382f41SAnton Blanchard 		vlen = UIO_MAXIOV;
2106228e548eSAnton Blanchard 
2107228e548eSAnton Blanchard 	datagrams = 0;
2108228e548eSAnton Blanchard 
2109228e548eSAnton Blanchard 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2110228e548eSAnton Blanchard 	if (!sock)
2111228e548eSAnton Blanchard 		return err;
2112228e548eSAnton Blanchard 
2113c71d8ebeSTetsuo Handa 	used_address.name_len = UINT_MAX;
2114228e548eSAnton Blanchard 	entry = mmsg;
2115228e548eSAnton Blanchard 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2116728ffb86SAnton Blanchard 	err = 0;
2117228e548eSAnton Blanchard 
2118228e548eSAnton Blanchard 	while (datagrams < vlen) {
2119228e548eSAnton Blanchard 		if (MSG_CMSG_COMPAT & flags) {
2120228e548eSAnton Blanchard 			err = __sys_sendmsg(sock, (struct msghdr __user *)compat_entry,
2121c71d8ebeSTetsuo Handa 					    &msg_sys, flags, &used_address);
2122228e548eSAnton Blanchard 			if (err < 0)
2123228e548eSAnton Blanchard 				break;
2124228e548eSAnton Blanchard 			err = __put_user(err, &compat_entry->msg_len);
2125228e548eSAnton Blanchard 			++compat_entry;
2126228e548eSAnton Blanchard 		} else {
2127228e548eSAnton Blanchard 			err = __sys_sendmsg(sock, (struct msghdr __user *)entry,
2128c71d8ebeSTetsuo Handa 					    &msg_sys, flags, &used_address);
2129228e548eSAnton Blanchard 			if (err < 0)
2130228e548eSAnton Blanchard 				break;
2131228e548eSAnton Blanchard 			err = put_user(err, &entry->msg_len);
2132228e548eSAnton Blanchard 			++entry;
2133228e548eSAnton Blanchard 		}
2134228e548eSAnton Blanchard 
2135228e548eSAnton Blanchard 		if (err)
2136228e548eSAnton Blanchard 			break;
2137228e548eSAnton Blanchard 		++datagrams;
2138228e548eSAnton Blanchard 	}
2139228e548eSAnton Blanchard 
2140228e548eSAnton Blanchard 	fput_light(sock->file, fput_needed);
2141228e548eSAnton Blanchard 
2142728ffb86SAnton Blanchard 	/* We only return an error if no datagrams were able to be sent */
2143728ffb86SAnton Blanchard 	if (datagrams != 0)
2144228e548eSAnton Blanchard 		return datagrams;
2145228e548eSAnton Blanchard 
2146228e548eSAnton Blanchard 	return err;
2147228e548eSAnton Blanchard }
2148228e548eSAnton Blanchard 
2149228e548eSAnton Blanchard SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
2150228e548eSAnton Blanchard 		unsigned int, vlen, unsigned int, flags)
2151228e548eSAnton Blanchard {
2152228e548eSAnton Blanchard 	return __sys_sendmmsg(fd, mmsg, vlen, flags);
2153228e548eSAnton Blanchard }
2154228e548eSAnton Blanchard 
2155a2e27255SArnaldo Carvalho de Melo static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
215695c96174SEric Dumazet 			 struct msghdr *msg_sys, unsigned int flags, int nosec)
21571da177e4SLinus Torvalds {
215889bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
215989bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
21601da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV];
21611da177e4SLinus Torvalds 	struct iovec *iov = iovstack;
21621da177e4SLinus Torvalds 	unsigned long cmsg_ptr;
2163a74e9106SEric Dumazet 	int err, total_len, len;
21641da177e4SLinus Torvalds 
21651da177e4SLinus Torvalds 	/* kernel mode address */
2166230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage addr;
21671da177e4SLinus Torvalds 
21681da177e4SLinus Torvalds 	/* user mode address pointers */
21691da177e4SLinus Torvalds 	struct sockaddr __user *uaddr;
21701da177e4SLinus Torvalds 	int __user *uaddr_len;
21711da177e4SLinus Torvalds 
21721da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
2173a2e27255SArnaldo Carvalho de Melo 		if (get_compat_msghdr(msg_sys, msg_compat))
21741da177e4SLinus Torvalds 			return -EFAULT;
2175c6d409cfSEric Dumazet 	} else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr)))
21761da177e4SLinus Torvalds 		return -EFAULT;
21771da177e4SLinus Torvalds 
2178a74e9106SEric Dumazet 	if (msg_sys->msg_iovlen > UIO_FASTIOV) {
21791da177e4SLinus Torvalds 		err = -EMSGSIZE;
2180a2e27255SArnaldo Carvalho de Melo 		if (msg_sys->msg_iovlen > UIO_MAXIOV)
2181a2e27255SArnaldo Carvalho de Melo 			goto out;
21821da177e4SLinus Torvalds 		err = -ENOMEM;
2183a74e9106SEric Dumazet 		iov = kmalloc(msg_sys->msg_iovlen * sizeof(struct iovec),
2184a74e9106SEric Dumazet 			      GFP_KERNEL);
21851da177e4SLinus Torvalds 		if (!iov)
2186a2e27255SArnaldo Carvalho de Melo 			goto out;
21871da177e4SLinus Torvalds 	}
21881da177e4SLinus Torvalds 
21891da177e4SLinus Torvalds 	/*
21901da177e4SLinus Torvalds 	 *      Save the user-mode address (verify_iovec will change the
21911da177e4SLinus Torvalds 	 *      kernel msghdr to use the kernel address space)
21921da177e4SLinus Torvalds 	 */
21931da177e4SLinus Torvalds 
2194a2e27255SArnaldo Carvalho de Melo 	uaddr = (__force void __user *)msg_sys->msg_name;
21951da177e4SLinus Torvalds 	uaddr_len = COMPAT_NAMELEN(msg);
21961da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
219743db362dSMaciej Żenczykowski 		err = verify_compat_iovec(msg_sys, iov, &addr, VERIFY_WRITE);
21981da177e4SLinus Torvalds 	} else
219943db362dSMaciej Żenczykowski 		err = verify_iovec(msg_sys, iov, &addr, VERIFY_WRITE);
22001da177e4SLinus Torvalds 	if (err < 0)
22011da177e4SLinus Torvalds 		goto out_freeiov;
22021da177e4SLinus Torvalds 	total_len = err;
22031da177e4SLinus Torvalds 
2204a2e27255SArnaldo Carvalho de Melo 	cmsg_ptr = (unsigned long)msg_sys->msg_control;
2205a2e27255SArnaldo Carvalho de Melo 	msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
22061da177e4SLinus Torvalds 
22071da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
22081da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
2209a2e27255SArnaldo Carvalho de Melo 	err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys,
2210a2e27255SArnaldo Carvalho de Melo 							  total_len, flags);
22111da177e4SLinus Torvalds 	if (err < 0)
22121da177e4SLinus Torvalds 		goto out_freeiov;
22131da177e4SLinus Torvalds 	len = err;
22141da177e4SLinus Torvalds 
22151da177e4SLinus Torvalds 	if (uaddr != NULL) {
221643db362dSMaciej Żenczykowski 		err = move_addr_to_user(&addr,
2217a2e27255SArnaldo Carvalho de Melo 					msg_sys->msg_namelen, uaddr,
221889bddce5SStephen Hemminger 					uaddr_len);
22191da177e4SLinus Torvalds 		if (err < 0)
22201da177e4SLinus Torvalds 			goto out_freeiov;
22211da177e4SLinus Torvalds 	}
2222a2e27255SArnaldo Carvalho de Melo 	err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
222337f7f421SDavid S. Miller 			 COMPAT_FLAGS(msg));
22241da177e4SLinus Torvalds 	if (err)
22251da177e4SLinus Torvalds 		goto out_freeiov;
22261da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags)
2227a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
22281da177e4SLinus Torvalds 				 &msg_compat->msg_controllen);
22291da177e4SLinus Torvalds 	else
2230a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
22311da177e4SLinus Torvalds 				 &msg->msg_controllen);
22321da177e4SLinus Torvalds 	if (err)
22331da177e4SLinus Torvalds 		goto out_freeiov;
22341da177e4SLinus Torvalds 	err = len;
22351da177e4SLinus Torvalds 
22361da177e4SLinus Torvalds out_freeiov:
22371da177e4SLinus Torvalds 	if (iov != iovstack)
2238a74e9106SEric Dumazet 		kfree(iov);
2239a2e27255SArnaldo Carvalho de Melo out:
2240a2e27255SArnaldo Carvalho de Melo 	return err;
2241a2e27255SArnaldo Carvalho de Melo }
2242a2e27255SArnaldo Carvalho de Melo 
2243a2e27255SArnaldo Carvalho de Melo /*
2244a2e27255SArnaldo Carvalho de Melo  *	BSD recvmsg interface
2245a2e27255SArnaldo Carvalho de Melo  */
2246a2e27255SArnaldo Carvalho de Melo 
2247a2e27255SArnaldo Carvalho de Melo SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg,
2248a2e27255SArnaldo Carvalho de Melo 		unsigned int, flags)
2249a2e27255SArnaldo Carvalho de Melo {
2250a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err;
2251a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
2252a2e27255SArnaldo Carvalho de Melo 	struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed);
2253a2e27255SArnaldo Carvalho de Melo 
2254a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2255a2e27255SArnaldo Carvalho de Melo 		goto out;
2256a2e27255SArnaldo Carvalho de Melo 
2257a2e27255SArnaldo Carvalho de Melo 	err = __sys_recvmsg(sock, msg, &msg_sys, flags, 0);
2258a2e27255SArnaldo Carvalho de Melo 
22596cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
22601da177e4SLinus Torvalds out:
22611da177e4SLinus Torvalds 	return err;
22621da177e4SLinus Torvalds }
22631da177e4SLinus Torvalds 
2264a2e27255SArnaldo Carvalho de Melo /*
2265a2e27255SArnaldo Carvalho de Melo  *     Linux recvmmsg interface
2266a2e27255SArnaldo Carvalho de Melo  */
22671da177e4SLinus Torvalds 
2268a2e27255SArnaldo Carvalho de Melo int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2269a2e27255SArnaldo Carvalho de Melo 		   unsigned int flags, struct timespec *timeout)
2270a2e27255SArnaldo Carvalho de Melo {
2271a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err, datagrams;
2272a2e27255SArnaldo Carvalho de Melo 	struct socket *sock;
2273a2e27255SArnaldo Carvalho de Melo 	struct mmsghdr __user *entry;
2274d7256d0eSJean-Mickael Guerin 	struct compat_mmsghdr __user *compat_entry;
2275a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
2276a2e27255SArnaldo Carvalho de Melo 	struct timespec end_time;
2277a2e27255SArnaldo Carvalho de Melo 
2278a2e27255SArnaldo Carvalho de Melo 	if (timeout &&
2279a2e27255SArnaldo Carvalho de Melo 	    poll_select_set_timeout(&end_time, timeout->tv_sec,
2280a2e27255SArnaldo Carvalho de Melo 				    timeout->tv_nsec))
2281a2e27255SArnaldo Carvalho de Melo 		return -EINVAL;
2282a2e27255SArnaldo Carvalho de Melo 
2283a2e27255SArnaldo Carvalho de Melo 	datagrams = 0;
2284a2e27255SArnaldo Carvalho de Melo 
2285a2e27255SArnaldo Carvalho de Melo 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2286a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2287a2e27255SArnaldo Carvalho de Melo 		return err;
2288a2e27255SArnaldo Carvalho de Melo 
2289a2e27255SArnaldo Carvalho de Melo 	err = sock_error(sock->sk);
2290a2e27255SArnaldo Carvalho de Melo 	if (err)
2291a2e27255SArnaldo Carvalho de Melo 		goto out_put;
2292a2e27255SArnaldo Carvalho de Melo 
2293a2e27255SArnaldo Carvalho de Melo 	entry = mmsg;
2294d7256d0eSJean-Mickael Guerin 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2295a2e27255SArnaldo Carvalho de Melo 
2296a2e27255SArnaldo Carvalho de Melo 	while (datagrams < vlen) {
2297a2e27255SArnaldo Carvalho de Melo 		/*
2298a2e27255SArnaldo Carvalho de Melo 		 * No need to ask LSM for more than the first datagram.
2299a2e27255SArnaldo Carvalho de Melo 		 */
2300d7256d0eSJean-Mickael Guerin 		if (MSG_CMSG_COMPAT & flags) {
2301d7256d0eSJean-Mickael Guerin 			err = __sys_recvmsg(sock, (struct msghdr __user *)compat_entry,
2302b9eb8b87SAnton Blanchard 					    &msg_sys, flags & ~MSG_WAITFORONE,
2303b9eb8b87SAnton Blanchard 					    datagrams);
2304d7256d0eSJean-Mickael Guerin 			if (err < 0)
2305d7256d0eSJean-Mickael Guerin 				break;
2306d7256d0eSJean-Mickael Guerin 			err = __put_user(err, &compat_entry->msg_len);
2307d7256d0eSJean-Mickael Guerin 			++compat_entry;
2308d7256d0eSJean-Mickael Guerin 		} else {
2309a2e27255SArnaldo Carvalho de Melo 			err = __sys_recvmsg(sock, (struct msghdr __user *)entry,
2310b9eb8b87SAnton Blanchard 					    &msg_sys, flags & ~MSG_WAITFORONE,
2311b9eb8b87SAnton Blanchard 					    datagrams);
2312a2e27255SArnaldo Carvalho de Melo 			if (err < 0)
2313a2e27255SArnaldo Carvalho de Melo 				break;
2314a2e27255SArnaldo Carvalho de Melo 			err = put_user(err, &entry->msg_len);
2315d7256d0eSJean-Mickael Guerin 			++entry;
2316d7256d0eSJean-Mickael Guerin 		}
2317d7256d0eSJean-Mickael Guerin 
2318a2e27255SArnaldo Carvalho de Melo 		if (err)
2319a2e27255SArnaldo Carvalho de Melo 			break;
2320a2e27255SArnaldo Carvalho de Melo 		++datagrams;
2321a2e27255SArnaldo Carvalho de Melo 
232271c5c159SBrandon L Black 		/* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
232371c5c159SBrandon L Black 		if (flags & MSG_WAITFORONE)
232471c5c159SBrandon L Black 			flags |= MSG_DONTWAIT;
232571c5c159SBrandon L Black 
2326a2e27255SArnaldo Carvalho de Melo 		if (timeout) {
2327a2e27255SArnaldo Carvalho de Melo 			ktime_get_ts(timeout);
2328a2e27255SArnaldo Carvalho de Melo 			*timeout = timespec_sub(end_time, *timeout);
2329a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_sec < 0) {
2330a2e27255SArnaldo Carvalho de Melo 				timeout->tv_sec = timeout->tv_nsec = 0;
2331a2e27255SArnaldo Carvalho de Melo 				break;
2332a2e27255SArnaldo Carvalho de Melo 			}
2333a2e27255SArnaldo Carvalho de Melo 
2334a2e27255SArnaldo Carvalho de Melo 			/* Timeout, return less than vlen datagrams */
2335a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_nsec == 0 && timeout->tv_sec == 0)
2336a2e27255SArnaldo Carvalho de Melo 				break;
2337a2e27255SArnaldo Carvalho de Melo 		}
2338a2e27255SArnaldo Carvalho de Melo 
2339a2e27255SArnaldo Carvalho de Melo 		/* Out of band data, return right away */
2340a2e27255SArnaldo Carvalho de Melo 		if (msg_sys.msg_flags & MSG_OOB)
2341a2e27255SArnaldo Carvalho de Melo 			break;
2342a2e27255SArnaldo Carvalho de Melo 	}
2343a2e27255SArnaldo Carvalho de Melo 
2344a2e27255SArnaldo Carvalho de Melo out_put:
2345a2e27255SArnaldo Carvalho de Melo 	fput_light(sock->file, fput_needed);
2346a2e27255SArnaldo Carvalho de Melo 
2347a2e27255SArnaldo Carvalho de Melo 	if (err == 0)
2348a2e27255SArnaldo Carvalho de Melo 		return datagrams;
2349a2e27255SArnaldo Carvalho de Melo 
2350a2e27255SArnaldo Carvalho de Melo 	if (datagrams != 0) {
2351a2e27255SArnaldo Carvalho de Melo 		/*
2352a2e27255SArnaldo Carvalho de Melo 		 * We may return less entries than requested (vlen) if the
2353a2e27255SArnaldo Carvalho de Melo 		 * sock is non block and there aren't enough datagrams...
2354a2e27255SArnaldo Carvalho de Melo 		 */
2355a2e27255SArnaldo Carvalho de Melo 		if (err != -EAGAIN) {
2356a2e27255SArnaldo Carvalho de Melo 			/*
2357a2e27255SArnaldo Carvalho de Melo 			 * ... or  if recvmsg returns an error after we
2358a2e27255SArnaldo Carvalho de Melo 			 * received some datagrams, where we record the
2359a2e27255SArnaldo Carvalho de Melo 			 * error to return on the next call or if the
2360a2e27255SArnaldo Carvalho de Melo 			 * app asks about it using getsockopt(SO_ERROR).
2361a2e27255SArnaldo Carvalho de Melo 			 */
2362a2e27255SArnaldo Carvalho de Melo 			sock->sk->sk_err = -err;
2363a2e27255SArnaldo Carvalho de Melo 		}
2364a2e27255SArnaldo Carvalho de Melo 
2365a2e27255SArnaldo Carvalho de Melo 		return datagrams;
2366a2e27255SArnaldo Carvalho de Melo 	}
2367a2e27255SArnaldo Carvalho de Melo 
2368a2e27255SArnaldo Carvalho de Melo 	return err;
2369a2e27255SArnaldo Carvalho de Melo }
2370a2e27255SArnaldo Carvalho de Melo 
2371a2e27255SArnaldo Carvalho de Melo SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
2372a2e27255SArnaldo Carvalho de Melo 		unsigned int, vlen, unsigned int, flags,
2373a2e27255SArnaldo Carvalho de Melo 		struct timespec __user *, timeout)
2374a2e27255SArnaldo Carvalho de Melo {
2375a2e27255SArnaldo Carvalho de Melo 	int datagrams;
2376a2e27255SArnaldo Carvalho de Melo 	struct timespec timeout_sys;
2377a2e27255SArnaldo Carvalho de Melo 
2378a2e27255SArnaldo Carvalho de Melo 	if (!timeout)
2379a2e27255SArnaldo Carvalho de Melo 		return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL);
2380a2e27255SArnaldo Carvalho de Melo 
2381a2e27255SArnaldo Carvalho de Melo 	if (copy_from_user(&timeout_sys, timeout, sizeof(timeout_sys)))
2382a2e27255SArnaldo Carvalho de Melo 		return -EFAULT;
2383a2e27255SArnaldo Carvalho de Melo 
2384a2e27255SArnaldo Carvalho de Melo 	datagrams = __sys_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys);
2385a2e27255SArnaldo Carvalho de Melo 
2386a2e27255SArnaldo Carvalho de Melo 	if (datagrams > 0 &&
2387a2e27255SArnaldo Carvalho de Melo 	    copy_to_user(timeout, &timeout_sys, sizeof(timeout_sys)))
2388a2e27255SArnaldo Carvalho de Melo 		datagrams = -EFAULT;
2389a2e27255SArnaldo Carvalho de Melo 
2390a2e27255SArnaldo Carvalho de Melo 	return datagrams;
2391a2e27255SArnaldo Carvalho de Melo }
2392a2e27255SArnaldo Carvalho de Melo 
2393a2e27255SArnaldo Carvalho de Melo #ifdef __ARCH_WANT_SYS_SOCKETCALL
23941da177e4SLinus Torvalds /* Argument list sizes for sys_socketcall */
23951da177e4SLinus Torvalds #define AL(x) ((x) * sizeof(unsigned long))
2396228e548eSAnton Blanchard static const unsigned char nargs[21] = {
239789bddce5SStephen Hemminger 	AL(0), AL(3), AL(3), AL(3), AL(2), AL(3),
23981da177e4SLinus Torvalds 	AL(3), AL(3), AL(4), AL(4), AL(4), AL(6),
2399aaca0bdcSUlrich Drepper 	AL(6), AL(2), AL(5), AL(5), AL(3), AL(3),
2400228e548eSAnton Blanchard 	AL(4), AL(5), AL(4)
240189bddce5SStephen Hemminger };
240289bddce5SStephen Hemminger 
24031da177e4SLinus Torvalds #undef AL
24041da177e4SLinus Torvalds 
24051da177e4SLinus Torvalds /*
24061da177e4SLinus Torvalds  *	System call vectors.
24071da177e4SLinus Torvalds  *
24081da177e4SLinus Torvalds  *	Argument checking cleaned up. Saved 20% in size.
24091da177e4SLinus Torvalds  *  This function doesn't need to set the kernel lock because
24101da177e4SLinus Torvalds  *  it is set by the callees.
24111da177e4SLinus Torvalds  */
24121da177e4SLinus Torvalds 
24133e0fa65fSHeiko Carstens SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
24141da177e4SLinus Torvalds {
24152950fa9dSChen Gang 	unsigned long a[AUDITSC_ARGS];
24161da177e4SLinus Torvalds 	unsigned long a0, a1;
24171da177e4SLinus Torvalds 	int err;
241847379052SArjan van de Ven 	unsigned int len;
24191da177e4SLinus Torvalds 
2420228e548eSAnton Blanchard 	if (call < 1 || call > SYS_SENDMMSG)
24211da177e4SLinus Torvalds 		return -EINVAL;
24221da177e4SLinus Torvalds 
242347379052SArjan van de Ven 	len = nargs[call];
242447379052SArjan van de Ven 	if (len > sizeof(a))
242547379052SArjan van de Ven 		return -EINVAL;
242647379052SArjan van de Ven 
24271da177e4SLinus Torvalds 	/* copy_from_user should be SMP safe. */
242847379052SArjan van de Ven 	if (copy_from_user(a, args, len))
24291da177e4SLinus Torvalds 		return -EFAULT;
24301da177e4SLinus Torvalds 
24312950fa9dSChen Gang 	err = audit_socketcall(nargs[call] / sizeof(unsigned long), a);
24322950fa9dSChen Gang 	if (err)
24332950fa9dSChen Gang 		return err;
24343ec3b2fbSDavid Woodhouse 
24351da177e4SLinus Torvalds 	a0 = a[0];
24361da177e4SLinus Torvalds 	a1 = a[1];
24371da177e4SLinus Torvalds 
243889bddce5SStephen Hemminger 	switch (call) {
24391da177e4SLinus Torvalds 	case SYS_SOCKET:
24401da177e4SLinus Torvalds 		err = sys_socket(a0, a1, a[2]);
24411da177e4SLinus Torvalds 		break;
24421da177e4SLinus Torvalds 	case SYS_BIND:
24431da177e4SLinus Torvalds 		err = sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
24441da177e4SLinus Torvalds 		break;
24451da177e4SLinus Torvalds 	case SYS_CONNECT:
24461da177e4SLinus Torvalds 		err = sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
24471da177e4SLinus Torvalds 		break;
24481da177e4SLinus Torvalds 	case SYS_LISTEN:
24491da177e4SLinus Torvalds 		err = sys_listen(a0, a1);
24501da177e4SLinus Torvalds 		break;
24511da177e4SLinus Torvalds 	case SYS_ACCEPT:
2452de11defeSUlrich Drepper 		err = sys_accept4(a0, (struct sockaddr __user *)a1,
2453aaca0bdcSUlrich Drepper 				  (int __user *)a[2], 0);
24541da177e4SLinus Torvalds 		break;
24551da177e4SLinus Torvalds 	case SYS_GETSOCKNAME:
245689bddce5SStephen Hemminger 		err =
245789bddce5SStephen Hemminger 		    sys_getsockname(a0, (struct sockaddr __user *)a1,
245889bddce5SStephen Hemminger 				    (int __user *)a[2]);
24591da177e4SLinus Torvalds 		break;
24601da177e4SLinus Torvalds 	case SYS_GETPEERNAME:
246189bddce5SStephen Hemminger 		err =
246289bddce5SStephen Hemminger 		    sys_getpeername(a0, (struct sockaddr __user *)a1,
246389bddce5SStephen Hemminger 				    (int __user *)a[2]);
24641da177e4SLinus Torvalds 		break;
24651da177e4SLinus Torvalds 	case SYS_SOCKETPAIR:
24661da177e4SLinus Torvalds 		err = sys_socketpair(a0, a1, a[2], (int __user *)a[3]);
24671da177e4SLinus Torvalds 		break;
24681da177e4SLinus Torvalds 	case SYS_SEND:
24691da177e4SLinus Torvalds 		err = sys_send(a0, (void __user *)a1, a[2], a[3]);
24701da177e4SLinus Torvalds 		break;
24711da177e4SLinus Torvalds 	case SYS_SENDTO:
24721da177e4SLinus Torvalds 		err = sys_sendto(a0, (void __user *)a1, a[2], a[3],
24731da177e4SLinus Torvalds 				 (struct sockaddr __user *)a[4], a[5]);
24741da177e4SLinus Torvalds 		break;
24751da177e4SLinus Torvalds 	case SYS_RECV:
24761da177e4SLinus Torvalds 		err = sys_recv(a0, (void __user *)a1, a[2], a[3]);
24771da177e4SLinus Torvalds 		break;
24781da177e4SLinus Torvalds 	case SYS_RECVFROM:
24791da177e4SLinus Torvalds 		err = sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
248089bddce5SStephen Hemminger 				   (struct sockaddr __user *)a[4],
248189bddce5SStephen Hemminger 				   (int __user *)a[5]);
24821da177e4SLinus Torvalds 		break;
24831da177e4SLinus Torvalds 	case SYS_SHUTDOWN:
24841da177e4SLinus Torvalds 		err = sys_shutdown(a0, a1);
24851da177e4SLinus Torvalds 		break;
24861da177e4SLinus Torvalds 	case SYS_SETSOCKOPT:
24871da177e4SLinus Torvalds 		err = sys_setsockopt(a0, a1, a[2], (char __user *)a[3], a[4]);
24881da177e4SLinus Torvalds 		break;
24891da177e4SLinus Torvalds 	case SYS_GETSOCKOPT:
249089bddce5SStephen Hemminger 		err =
249189bddce5SStephen Hemminger 		    sys_getsockopt(a0, a1, a[2], (char __user *)a[3],
249289bddce5SStephen Hemminger 				   (int __user *)a[4]);
24931da177e4SLinus Torvalds 		break;
24941da177e4SLinus Torvalds 	case SYS_SENDMSG:
24951da177e4SLinus Torvalds 		err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]);
24961da177e4SLinus Torvalds 		break;
2497228e548eSAnton Blanchard 	case SYS_SENDMMSG:
2498228e548eSAnton Blanchard 		err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]);
2499228e548eSAnton Blanchard 		break;
25001da177e4SLinus Torvalds 	case SYS_RECVMSG:
25011da177e4SLinus Torvalds 		err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]);
25021da177e4SLinus Torvalds 		break;
2503a2e27255SArnaldo Carvalho de Melo 	case SYS_RECVMMSG:
2504a2e27255SArnaldo Carvalho de Melo 		err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3],
2505a2e27255SArnaldo Carvalho de Melo 				   (struct timespec __user *)a[4]);
2506a2e27255SArnaldo Carvalho de Melo 		break;
2507de11defeSUlrich Drepper 	case SYS_ACCEPT4:
2508de11defeSUlrich Drepper 		err = sys_accept4(a0, (struct sockaddr __user *)a1,
2509de11defeSUlrich Drepper 				  (int __user *)a[2], a[3]);
2510aaca0bdcSUlrich Drepper 		break;
25111da177e4SLinus Torvalds 	default:
25121da177e4SLinus Torvalds 		err = -EINVAL;
25131da177e4SLinus Torvalds 		break;
25141da177e4SLinus Torvalds 	}
25151da177e4SLinus Torvalds 	return err;
25161da177e4SLinus Torvalds }
25171da177e4SLinus Torvalds 
25181da177e4SLinus Torvalds #endif				/* __ARCH_WANT_SYS_SOCKETCALL */
25191da177e4SLinus Torvalds 
252055737fdaSStephen Hemminger /**
252155737fdaSStephen Hemminger  *	sock_register - add a socket protocol handler
252255737fdaSStephen Hemminger  *	@ops: description of protocol
252355737fdaSStephen Hemminger  *
25241da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
25251da177e4SLinus Torvalds  *	advertise its address family, and have it linked into the
252655737fdaSStephen Hemminger  *	socket interface. The value ops->family coresponds to the
252755737fdaSStephen Hemminger  *	socket system call protocol family.
25281da177e4SLinus Torvalds  */
2529f0fd27d4SStephen Hemminger int sock_register(const struct net_proto_family *ops)
25301da177e4SLinus Torvalds {
25311da177e4SLinus Torvalds 	int err;
25321da177e4SLinus Torvalds 
25331da177e4SLinus Torvalds 	if (ops->family >= NPROTO) {
253489bddce5SStephen Hemminger 		printk(KERN_CRIT "protocol %d >= NPROTO(%d)\n", ops->family,
253589bddce5SStephen Hemminger 		       NPROTO);
25361da177e4SLinus Torvalds 		return -ENOBUFS;
25371da177e4SLinus Torvalds 	}
253855737fdaSStephen Hemminger 
253955737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2540190683a9SEric Dumazet 	if (rcu_dereference_protected(net_families[ops->family],
2541190683a9SEric Dumazet 				      lockdep_is_held(&net_family_lock)))
25421da177e4SLinus Torvalds 		err = -EEXIST;
254355737fdaSStephen Hemminger 	else {
2544cf778b00SEric Dumazet 		rcu_assign_pointer(net_families[ops->family], ops);
25451da177e4SLinus Torvalds 		err = 0;
25461da177e4SLinus Torvalds 	}
254755737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
254855737fdaSStephen Hemminger 
254989bddce5SStephen Hemminger 	printk(KERN_INFO "NET: Registered protocol family %d\n", ops->family);
25501da177e4SLinus Torvalds 	return err;
25511da177e4SLinus Torvalds }
2552c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_register);
25531da177e4SLinus Torvalds 
255455737fdaSStephen Hemminger /**
255555737fdaSStephen Hemminger  *	sock_unregister - remove a protocol handler
255655737fdaSStephen Hemminger  *	@family: protocol family to remove
255755737fdaSStephen Hemminger  *
25581da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
25591da177e4SLinus Torvalds  *	remove its address family, and have it unlinked from the
256055737fdaSStephen Hemminger  *	new socket creation.
256155737fdaSStephen Hemminger  *
256255737fdaSStephen Hemminger  *	If protocol handler is a module, then it can use module reference
256355737fdaSStephen Hemminger  *	counts to protect against new references. If protocol handler is not
256455737fdaSStephen Hemminger  *	a module then it needs to provide its own protection in
256555737fdaSStephen Hemminger  *	the ops->create routine.
25661da177e4SLinus Torvalds  */
2567f0fd27d4SStephen Hemminger void sock_unregister(int family)
25681da177e4SLinus Torvalds {
2569f0fd27d4SStephen Hemminger 	BUG_ON(family < 0 || family >= NPROTO);
25701da177e4SLinus Torvalds 
257155737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2572a9b3cd7fSStephen Hemminger 	RCU_INIT_POINTER(net_families[family], NULL);
257355737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
257455737fdaSStephen Hemminger 
257555737fdaSStephen Hemminger 	synchronize_rcu();
257655737fdaSStephen Hemminger 
257789bddce5SStephen Hemminger 	printk(KERN_INFO "NET: Unregistered protocol family %d\n", family);
25781da177e4SLinus Torvalds }
2579c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_unregister);
25801da177e4SLinus Torvalds 
258177d76ea3SAndi Kleen static int __init sock_init(void)
25821da177e4SLinus Torvalds {
2583b3e19d92SNick Piggin 	int err;
25842ca794e5SEric W. Biederman 	/*
25852ca794e5SEric W. Biederman 	 *      Initialize the network sysctl infrastructure.
25862ca794e5SEric W. Biederman 	 */
25872ca794e5SEric W. Biederman 	err = net_sysctl_init();
25882ca794e5SEric W. Biederman 	if (err)
25892ca794e5SEric W. Biederman 		goto out;
2590b3e19d92SNick Piggin 
25911da177e4SLinus Torvalds 	/*
25921da177e4SLinus Torvalds 	 *      Initialize skbuff SLAB cache
25931da177e4SLinus Torvalds 	 */
25941da177e4SLinus Torvalds 	skb_init();
25951da177e4SLinus Torvalds 
25961da177e4SLinus Torvalds 	/*
25971da177e4SLinus Torvalds 	 *      Initialize the protocols module.
25981da177e4SLinus Torvalds 	 */
25991da177e4SLinus Torvalds 
26001da177e4SLinus Torvalds 	init_inodecache();
2601b3e19d92SNick Piggin 
2602b3e19d92SNick Piggin 	err = register_filesystem(&sock_fs_type);
2603b3e19d92SNick Piggin 	if (err)
2604b3e19d92SNick Piggin 		goto out_fs;
26051da177e4SLinus Torvalds 	sock_mnt = kern_mount(&sock_fs_type);
2606b3e19d92SNick Piggin 	if (IS_ERR(sock_mnt)) {
2607b3e19d92SNick Piggin 		err = PTR_ERR(sock_mnt);
2608b3e19d92SNick Piggin 		goto out_mount;
2609b3e19d92SNick Piggin 	}
261077d76ea3SAndi Kleen 
261177d76ea3SAndi Kleen 	/* The real protocol initialization is performed in later initcalls.
26121da177e4SLinus Torvalds 	 */
26131da177e4SLinus Torvalds 
26141da177e4SLinus Torvalds #ifdef CONFIG_NETFILTER
26156d11cfdbSPablo Neira Ayuso 	err = netfilter_init();
26166d11cfdbSPablo Neira Ayuso 	if (err)
26176d11cfdbSPablo Neira Ayuso 		goto out;
26181da177e4SLinus Torvalds #endif
2619cbeb321aSDavid S. Miller 
2620c1f19b51SRichard Cochran #ifdef CONFIG_NETWORK_PHY_TIMESTAMPING
2621c1f19b51SRichard Cochran 	skb_timestamping_init();
2622c1f19b51SRichard Cochran #endif
2623c1f19b51SRichard Cochran 
2624b3e19d92SNick Piggin out:
2625b3e19d92SNick Piggin 	return err;
2626b3e19d92SNick Piggin 
2627b3e19d92SNick Piggin out_mount:
2628b3e19d92SNick Piggin 	unregister_filesystem(&sock_fs_type);
2629b3e19d92SNick Piggin out_fs:
2630b3e19d92SNick Piggin 	goto out;
26311da177e4SLinus Torvalds }
26321da177e4SLinus Torvalds 
263377d76ea3SAndi Kleen core_initcall(sock_init);	/* early initcall */
263477d76ea3SAndi Kleen 
26351da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS
26361da177e4SLinus Torvalds void socket_seq_show(struct seq_file *seq)
26371da177e4SLinus Torvalds {
26381da177e4SLinus Torvalds 	int cpu;
26391da177e4SLinus Torvalds 	int counter = 0;
26401da177e4SLinus Torvalds 
26416f912042SKAMEZAWA Hiroyuki 	for_each_possible_cpu(cpu)
26421da177e4SLinus Torvalds 	    counter += per_cpu(sockets_in_use, cpu);
26431da177e4SLinus Torvalds 
26441da177e4SLinus Torvalds 	/* It can be negative, by the way. 8) */
26451da177e4SLinus Torvalds 	if (counter < 0)
26461da177e4SLinus Torvalds 		counter = 0;
26471da177e4SLinus Torvalds 
26481da177e4SLinus Torvalds 	seq_printf(seq, "sockets: used %d\n", counter);
26491da177e4SLinus Torvalds }
26501da177e4SLinus Torvalds #endif				/* CONFIG_PROC_FS */
26511da177e4SLinus Torvalds 
265289bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
26536b96018bSArnd Bergmann static int do_siocgstamp(struct net *net, struct socket *sock,
2654644595f8SH. Peter Anvin 			 unsigned int cmd, void __user *up)
26557a229387SArnd Bergmann {
26567a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
26577a229387SArnd Bergmann 	struct timeval ktv;
26587a229387SArnd Bergmann 	int err;
26597a229387SArnd Bergmann 
26607a229387SArnd Bergmann 	set_fs(KERNEL_DS);
26616b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv);
26627a229387SArnd Bergmann 	set_fs(old_fs);
2663644595f8SH. Peter Anvin 	if (!err)
2664ed6fe9d6SMikulas Patocka 		err = compat_put_timeval(&ktv, up);
2665644595f8SH. Peter Anvin 
26667a229387SArnd Bergmann 	return err;
26677a229387SArnd Bergmann }
26687a229387SArnd Bergmann 
26696b96018bSArnd Bergmann static int do_siocgstampns(struct net *net, struct socket *sock,
2670644595f8SH. Peter Anvin 			   unsigned int cmd, void __user *up)
26717a229387SArnd Bergmann {
26727a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
26737a229387SArnd Bergmann 	struct timespec kts;
26747a229387SArnd Bergmann 	int err;
26757a229387SArnd Bergmann 
26767a229387SArnd Bergmann 	set_fs(KERNEL_DS);
26776b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts);
26787a229387SArnd Bergmann 	set_fs(old_fs);
2679644595f8SH. Peter Anvin 	if (!err)
2680ed6fe9d6SMikulas Patocka 		err = compat_put_timespec(&kts, up);
2681644595f8SH. Peter Anvin 
26827a229387SArnd Bergmann 	return err;
26837a229387SArnd Bergmann }
26847a229387SArnd Bergmann 
26856b96018bSArnd Bergmann static int dev_ifname32(struct net *net, struct compat_ifreq __user *uifr32)
26867a229387SArnd Bergmann {
26877a229387SArnd Bergmann 	struct ifreq __user *uifr;
26887a229387SArnd Bergmann 	int err;
26897a229387SArnd Bergmann 
26907a229387SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(struct ifreq));
26916b96018bSArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
26927a229387SArnd Bergmann 		return -EFAULT;
26937a229387SArnd Bergmann 
26946b96018bSArnd Bergmann 	err = dev_ioctl(net, SIOCGIFNAME, uifr);
26957a229387SArnd Bergmann 	if (err)
26967a229387SArnd Bergmann 		return err;
26977a229387SArnd Bergmann 
26986b96018bSArnd Bergmann 	if (copy_in_user(uifr32, uifr, sizeof(struct compat_ifreq)))
26997a229387SArnd Bergmann 		return -EFAULT;
27007a229387SArnd Bergmann 
27017a229387SArnd Bergmann 	return 0;
27027a229387SArnd Bergmann }
27037a229387SArnd Bergmann 
27046b96018bSArnd Bergmann static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32)
27057a229387SArnd Bergmann {
27066b96018bSArnd Bergmann 	struct compat_ifconf ifc32;
27077a229387SArnd Bergmann 	struct ifconf ifc;
27087a229387SArnd Bergmann 	struct ifconf __user *uifc;
27096b96018bSArnd Bergmann 	struct compat_ifreq __user *ifr32;
27107a229387SArnd Bergmann 	struct ifreq __user *ifr;
27117a229387SArnd Bergmann 	unsigned int i, j;
27127a229387SArnd Bergmann 	int err;
27137a229387SArnd Bergmann 
27146b96018bSArnd Bergmann 	if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf)))
27157a229387SArnd Bergmann 		return -EFAULT;
27167a229387SArnd Bergmann 
271743da5f2eSMathias Krause 	memset(&ifc, 0, sizeof(ifc));
27187a229387SArnd Bergmann 	if (ifc32.ifcbuf == 0) {
27197a229387SArnd Bergmann 		ifc32.ifc_len = 0;
27207a229387SArnd Bergmann 		ifc.ifc_len = 0;
27217a229387SArnd Bergmann 		ifc.ifc_req = NULL;
27227a229387SArnd Bergmann 		uifc = compat_alloc_user_space(sizeof(struct ifconf));
27237a229387SArnd Bergmann 	} else {
27246b96018bSArnd Bergmann 		size_t len = ((ifc32.ifc_len / sizeof(struct compat_ifreq)) + 1) *
27257a229387SArnd Bergmann 			sizeof(struct ifreq);
27267a229387SArnd Bergmann 		uifc = compat_alloc_user_space(sizeof(struct ifconf) + len);
27277a229387SArnd Bergmann 		ifc.ifc_len = len;
27287a229387SArnd Bergmann 		ifr = ifc.ifc_req = (void __user *)(uifc + 1);
27297a229387SArnd Bergmann 		ifr32 = compat_ptr(ifc32.ifcbuf);
27306b96018bSArnd Bergmann 		for (i = 0; i < ifc32.ifc_len; i += sizeof(struct compat_ifreq)) {
27316b96018bSArnd Bergmann 			if (copy_in_user(ifr, ifr32, sizeof(struct compat_ifreq)))
27327a229387SArnd Bergmann 				return -EFAULT;
27337a229387SArnd Bergmann 			ifr++;
27347a229387SArnd Bergmann 			ifr32++;
27357a229387SArnd Bergmann 		}
27367a229387SArnd Bergmann 	}
27377a229387SArnd Bergmann 	if (copy_to_user(uifc, &ifc, sizeof(struct ifconf)))
27387a229387SArnd Bergmann 		return -EFAULT;
27397a229387SArnd Bergmann 
27406b96018bSArnd Bergmann 	err = dev_ioctl(net, SIOCGIFCONF, uifc);
27417a229387SArnd Bergmann 	if (err)
27427a229387SArnd Bergmann 		return err;
27437a229387SArnd Bergmann 
27447a229387SArnd Bergmann 	if (copy_from_user(&ifc, uifc, sizeof(struct ifconf)))
27457a229387SArnd Bergmann 		return -EFAULT;
27467a229387SArnd Bergmann 
27477a229387SArnd Bergmann 	ifr = ifc.ifc_req;
27487a229387SArnd Bergmann 	ifr32 = compat_ptr(ifc32.ifcbuf);
27497a229387SArnd Bergmann 	for (i = 0, j = 0;
27506b96018bSArnd Bergmann 	     i + sizeof(struct compat_ifreq) <= ifc32.ifc_len && j < ifc.ifc_len;
27516b96018bSArnd Bergmann 	     i += sizeof(struct compat_ifreq), j += sizeof(struct ifreq)) {
27526b96018bSArnd Bergmann 		if (copy_in_user(ifr32, ifr, sizeof(struct compat_ifreq)))
27537a229387SArnd Bergmann 			return -EFAULT;
27547a229387SArnd Bergmann 		ifr32++;
27557a229387SArnd Bergmann 		ifr++;
27567a229387SArnd Bergmann 	}
27577a229387SArnd Bergmann 
27587a229387SArnd Bergmann 	if (ifc32.ifcbuf == 0) {
27597a229387SArnd Bergmann 		/* Translate from 64-bit structure multiple to
27607a229387SArnd Bergmann 		 * a 32-bit one.
27617a229387SArnd Bergmann 		 */
27627a229387SArnd Bergmann 		i = ifc.ifc_len;
27636b96018bSArnd Bergmann 		i = ((i / sizeof(struct ifreq)) * sizeof(struct compat_ifreq));
27647a229387SArnd Bergmann 		ifc32.ifc_len = i;
27657a229387SArnd Bergmann 	} else {
27667a229387SArnd Bergmann 		ifc32.ifc_len = i;
27677a229387SArnd Bergmann 	}
27686b96018bSArnd Bergmann 	if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf)))
27697a229387SArnd Bergmann 		return -EFAULT;
27707a229387SArnd Bergmann 
27717a229387SArnd Bergmann 	return 0;
27727a229387SArnd Bergmann }
27737a229387SArnd Bergmann 
27746b96018bSArnd Bergmann static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
27757a229387SArnd Bergmann {
27763a7da39dSBen Hutchings 	struct compat_ethtool_rxnfc __user *compat_rxnfc;
27773a7da39dSBen Hutchings 	bool convert_in = false, convert_out = false;
27783a7da39dSBen Hutchings 	size_t buf_size = ALIGN(sizeof(struct ifreq), 8);
27793a7da39dSBen Hutchings 	struct ethtool_rxnfc __user *rxnfc;
27807a229387SArnd Bergmann 	struct ifreq __user *ifr;
27813a7da39dSBen Hutchings 	u32 rule_cnt = 0, actual_rule_cnt;
27823a7da39dSBen Hutchings 	u32 ethcmd;
27837a229387SArnd Bergmann 	u32 data;
27843a7da39dSBen Hutchings 	int ret;
27857a229387SArnd Bergmann 
27867a229387SArnd Bergmann 	if (get_user(data, &ifr32->ifr_ifru.ifru_data))
27877a229387SArnd Bergmann 		return -EFAULT;
27887a229387SArnd Bergmann 
27893a7da39dSBen Hutchings 	compat_rxnfc = compat_ptr(data);
27903a7da39dSBen Hutchings 
27913a7da39dSBen Hutchings 	if (get_user(ethcmd, &compat_rxnfc->cmd))
27927a229387SArnd Bergmann 		return -EFAULT;
27937a229387SArnd Bergmann 
27943a7da39dSBen Hutchings 	/* Most ethtool structures are defined without padding.
27953a7da39dSBen Hutchings 	 * Unfortunately struct ethtool_rxnfc is an exception.
27963a7da39dSBen Hutchings 	 */
27973a7da39dSBen Hutchings 	switch (ethcmd) {
27983a7da39dSBen Hutchings 	default:
27993a7da39dSBen Hutchings 		break;
28003a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLALL:
28013a7da39dSBen Hutchings 		/* Buffer size is variable */
28023a7da39dSBen Hutchings 		if (get_user(rule_cnt, &compat_rxnfc->rule_cnt))
28033a7da39dSBen Hutchings 			return -EFAULT;
28043a7da39dSBen Hutchings 		if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32))
28053a7da39dSBen Hutchings 			return -ENOMEM;
28063a7da39dSBen Hutchings 		buf_size += rule_cnt * sizeof(u32);
28073a7da39dSBen Hutchings 		/* fall through */
28083a7da39dSBen Hutchings 	case ETHTOOL_GRXRINGS:
28093a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLCNT:
28103a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRULE:
281155664f32SBen Hutchings 	case ETHTOOL_SRXCLSRLINS:
28123a7da39dSBen Hutchings 		convert_out = true;
28133a7da39dSBen Hutchings 		/* fall through */
28143a7da39dSBen Hutchings 	case ETHTOOL_SRXCLSRLDEL:
28153a7da39dSBen Hutchings 		buf_size += sizeof(struct ethtool_rxnfc);
28163a7da39dSBen Hutchings 		convert_in = true;
28173a7da39dSBen Hutchings 		break;
28183a7da39dSBen Hutchings 	}
28193a7da39dSBen Hutchings 
28203a7da39dSBen Hutchings 	ifr = compat_alloc_user_space(buf_size);
2821954b1244SStephen Hemminger 	rxnfc = (void __user *)ifr + ALIGN(sizeof(struct ifreq), 8);
28223a7da39dSBen Hutchings 
28233a7da39dSBen Hutchings 	if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
28243a7da39dSBen Hutchings 		return -EFAULT;
28253a7da39dSBen Hutchings 
28263a7da39dSBen Hutchings 	if (put_user(convert_in ? rxnfc : compat_ptr(data),
28273a7da39dSBen Hutchings 		     &ifr->ifr_ifru.ifru_data))
28283a7da39dSBen Hutchings 		return -EFAULT;
28293a7da39dSBen Hutchings 
28303a7da39dSBen Hutchings 	if (convert_in) {
2831127fe533SAlexander Duyck 		/* We expect there to be holes between fs.m_ext and
28323a7da39dSBen Hutchings 		 * fs.ring_cookie and at the end of fs, but nowhere else.
28333a7da39dSBen Hutchings 		 */
2834127fe533SAlexander Duyck 		BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_ext) +
2835127fe533SAlexander Duyck 			     sizeof(compat_rxnfc->fs.m_ext) !=
2836127fe533SAlexander Duyck 			     offsetof(struct ethtool_rxnfc, fs.m_ext) +
2837127fe533SAlexander Duyck 			     sizeof(rxnfc->fs.m_ext));
28383a7da39dSBen Hutchings 		BUILD_BUG_ON(
28393a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.location) -
28403a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) !=
28413a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.location) -
28423a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.ring_cookie));
28433a7da39dSBen Hutchings 
28443a7da39dSBen Hutchings 		if (copy_in_user(rxnfc, compat_rxnfc,
2845954b1244SStephen Hemminger 				 (void __user *)(&rxnfc->fs.m_ext + 1) -
2846954b1244SStephen Hemminger 				 (void __user *)rxnfc) ||
28473a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->fs.ring_cookie,
28483a7da39dSBen Hutchings 				 &compat_rxnfc->fs.ring_cookie,
2849954b1244SStephen Hemminger 				 (void __user *)(&rxnfc->fs.location + 1) -
2850954b1244SStephen Hemminger 				 (void __user *)&rxnfc->fs.ring_cookie) ||
28513a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt,
28523a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
28533a7da39dSBen Hutchings 			return -EFAULT;
28543a7da39dSBen Hutchings 	}
28553a7da39dSBen Hutchings 
28563a7da39dSBen Hutchings 	ret = dev_ioctl(net, SIOCETHTOOL, ifr);
28573a7da39dSBen Hutchings 	if (ret)
28583a7da39dSBen Hutchings 		return ret;
28593a7da39dSBen Hutchings 
28603a7da39dSBen Hutchings 	if (convert_out) {
28613a7da39dSBen Hutchings 		if (copy_in_user(compat_rxnfc, rxnfc,
2862954b1244SStephen Hemminger 				 (const void __user *)(&rxnfc->fs.m_ext + 1) -
2863954b1244SStephen Hemminger 				 (const void __user *)rxnfc) ||
28643a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->fs.ring_cookie,
28653a7da39dSBen Hutchings 				 &rxnfc->fs.ring_cookie,
2866954b1244SStephen Hemminger 				 (const void __user *)(&rxnfc->fs.location + 1) -
2867954b1244SStephen Hemminger 				 (const void __user *)&rxnfc->fs.ring_cookie) ||
28683a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt,
28693a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
28703a7da39dSBen Hutchings 			return -EFAULT;
28713a7da39dSBen Hutchings 
28723a7da39dSBen Hutchings 		if (ethcmd == ETHTOOL_GRXCLSRLALL) {
28733a7da39dSBen Hutchings 			/* As an optimisation, we only copy the actual
28743a7da39dSBen Hutchings 			 * number of rules that the underlying
28753a7da39dSBen Hutchings 			 * function returned.  Since Mallory might
28763a7da39dSBen Hutchings 			 * change the rule count in user memory, we
28773a7da39dSBen Hutchings 			 * check that it is less than the rule count
28783a7da39dSBen Hutchings 			 * originally given (as the user buffer size),
28793a7da39dSBen Hutchings 			 * which has been range-checked.
28803a7da39dSBen Hutchings 			 */
28813a7da39dSBen Hutchings 			if (get_user(actual_rule_cnt, &rxnfc->rule_cnt))
28823a7da39dSBen Hutchings 				return -EFAULT;
28833a7da39dSBen Hutchings 			if (actual_rule_cnt < rule_cnt)
28843a7da39dSBen Hutchings 				rule_cnt = actual_rule_cnt;
28853a7da39dSBen Hutchings 			if (copy_in_user(&compat_rxnfc->rule_locs[0],
28863a7da39dSBen Hutchings 					 &rxnfc->rule_locs[0],
28873a7da39dSBen Hutchings 					 rule_cnt * sizeof(u32)))
28883a7da39dSBen Hutchings 				return -EFAULT;
28893a7da39dSBen Hutchings 		}
28903a7da39dSBen Hutchings 	}
28913a7da39dSBen Hutchings 
28923a7da39dSBen Hutchings 	return 0;
28937a229387SArnd Bergmann }
28947a229387SArnd Bergmann 
28957a50a240SArnd Bergmann static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32)
28967a50a240SArnd Bergmann {
28977a50a240SArnd Bergmann 	void __user *uptr;
28987a50a240SArnd Bergmann 	compat_uptr_t uptr32;
28997a50a240SArnd Bergmann 	struct ifreq __user *uifr;
29007a50a240SArnd Bergmann 
29017a50a240SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
29027a50a240SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
29037a50a240SArnd Bergmann 		return -EFAULT;
29047a50a240SArnd Bergmann 
29057a50a240SArnd Bergmann 	if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu))
29067a50a240SArnd Bergmann 		return -EFAULT;
29077a50a240SArnd Bergmann 
29087a50a240SArnd Bergmann 	uptr = compat_ptr(uptr32);
29097a50a240SArnd Bergmann 
29107a50a240SArnd Bergmann 	if (put_user(uptr, &uifr->ifr_settings.ifs_ifsu.raw_hdlc))
29117a50a240SArnd Bergmann 		return -EFAULT;
29127a50a240SArnd Bergmann 
29137a50a240SArnd Bergmann 	return dev_ioctl(net, SIOCWANDEV, uifr);
29147a50a240SArnd Bergmann }
29157a50a240SArnd Bergmann 
29166b96018bSArnd Bergmann static int bond_ioctl(struct net *net, unsigned int cmd,
29176b96018bSArnd Bergmann 			 struct compat_ifreq __user *ifr32)
29187a229387SArnd Bergmann {
29197a229387SArnd Bergmann 	struct ifreq kifr;
29207a229387SArnd Bergmann 	struct ifreq __user *uifr;
29217a229387SArnd Bergmann 	mm_segment_t old_fs;
29227a229387SArnd Bergmann 	int err;
29237a229387SArnd Bergmann 	u32 data;
29247a229387SArnd Bergmann 	void __user *datap;
29257a229387SArnd Bergmann 
29267a229387SArnd Bergmann 	switch (cmd) {
29277a229387SArnd Bergmann 	case SIOCBONDENSLAVE:
29287a229387SArnd Bergmann 	case SIOCBONDRELEASE:
29297a229387SArnd Bergmann 	case SIOCBONDSETHWADDR:
29307a229387SArnd Bergmann 	case SIOCBONDCHANGEACTIVE:
29316b96018bSArnd Bergmann 		if (copy_from_user(&kifr, ifr32, sizeof(struct compat_ifreq)))
29327a229387SArnd Bergmann 			return -EFAULT;
29337a229387SArnd Bergmann 
29347a229387SArnd Bergmann 		old_fs = get_fs();
29357a229387SArnd Bergmann 		set_fs(KERNEL_DS);
2936c3f52ae6Sstephen hemminger 		err = dev_ioctl(net, cmd,
2937c3f52ae6Sstephen hemminger 				(struct ifreq __user __force *) &kifr);
29387a229387SArnd Bergmann 		set_fs(old_fs);
29397a229387SArnd Bergmann 
29407a229387SArnd Bergmann 		return err;
29417a229387SArnd Bergmann 	case SIOCBONDSLAVEINFOQUERY:
29427a229387SArnd Bergmann 	case SIOCBONDINFOQUERY:
29437a229387SArnd Bergmann 		uifr = compat_alloc_user_space(sizeof(*uifr));
29447a229387SArnd Bergmann 		if (copy_in_user(&uifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
29457a229387SArnd Bergmann 			return -EFAULT;
29467a229387SArnd Bergmann 
29477a229387SArnd Bergmann 		if (get_user(data, &ifr32->ifr_ifru.ifru_data))
29487a229387SArnd Bergmann 			return -EFAULT;
29497a229387SArnd Bergmann 
29507a229387SArnd Bergmann 		datap = compat_ptr(data);
29517a229387SArnd Bergmann 		if (put_user(datap, &uifr->ifr_ifru.ifru_data))
29527a229387SArnd Bergmann 			return -EFAULT;
29537a229387SArnd Bergmann 
29546b96018bSArnd Bergmann 		return dev_ioctl(net, cmd, uifr);
29557a229387SArnd Bergmann 	default:
295607d106d0SLinus Torvalds 		return -ENOIOCTLCMD;
2957ccbd6a5aSJoe Perches 	}
29587a229387SArnd Bergmann }
29597a229387SArnd Bergmann 
29606b96018bSArnd Bergmann static int siocdevprivate_ioctl(struct net *net, unsigned int cmd,
29616b96018bSArnd Bergmann 				 struct compat_ifreq __user *u_ifreq32)
29627a229387SArnd Bergmann {
29637a229387SArnd Bergmann 	struct ifreq __user *u_ifreq64;
29647a229387SArnd Bergmann 	char tmp_buf[IFNAMSIZ];
29657a229387SArnd Bergmann 	void __user *data64;
29667a229387SArnd Bergmann 	u32 data32;
29677a229387SArnd Bergmann 
29687a229387SArnd Bergmann 	if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]),
29697a229387SArnd Bergmann 			   IFNAMSIZ))
29707a229387SArnd Bergmann 		return -EFAULT;
29717a229387SArnd Bergmann 	if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data))
29727a229387SArnd Bergmann 		return -EFAULT;
29737a229387SArnd Bergmann 	data64 = compat_ptr(data32);
29747a229387SArnd Bergmann 
29757a229387SArnd Bergmann 	u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
29767a229387SArnd Bergmann 
29777a229387SArnd Bergmann 	/* Don't check these user accesses, just let that get trapped
29787a229387SArnd Bergmann 	 * in the ioctl handler instead.
29797a229387SArnd Bergmann 	 */
29807a229387SArnd Bergmann 	if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0],
29817a229387SArnd Bergmann 			 IFNAMSIZ))
29827a229387SArnd Bergmann 		return -EFAULT;
29837a229387SArnd Bergmann 	if (__put_user(data64, &u_ifreq64->ifr_ifru.ifru_data))
29847a229387SArnd Bergmann 		return -EFAULT;
29857a229387SArnd Bergmann 
29866b96018bSArnd Bergmann 	return dev_ioctl(net, cmd, u_ifreq64);
29877a229387SArnd Bergmann }
29887a229387SArnd Bergmann 
29896b96018bSArnd Bergmann static int dev_ifsioc(struct net *net, struct socket *sock,
29906b96018bSArnd Bergmann 			 unsigned int cmd, struct compat_ifreq __user *uifr32)
29917a229387SArnd Bergmann {
2992a2116ed2SArnd Bergmann 	struct ifreq __user *uifr;
29937a229387SArnd Bergmann 	int err;
29947a229387SArnd Bergmann 
2995a2116ed2SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
2996a2116ed2SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(*uifr32)))
29977a229387SArnd Bergmann 		return -EFAULT;
2998a2116ed2SArnd Bergmann 
2999a2116ed2SArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr);
3000a2116ed2SArnd Bergmann 
30017a229387SArnd Bergmann 	if (!err) {
30027a229387SArnd Bergmann 		switch (cmd) {
30037a229387SArnd Bergmann 		case SIOCGIFFLAGS:
30047a229387SArnd Bergmann 		case SIOCGIFMETRIC:
30057a229387SArnd Bergmann 		case SIOCGIFMTU:
30067a229387SArnd Bergmann 		case SIOCGIFMEM:
30077a229387SArnd Bergmann 		case SIOCGIFHWADDR:
30087a229387SArnd Bergmann 		case SIOCGIFINDEX:
30097a229387SArnd Bergmann 		case SIOCGIFADDR:
30107a229387SArnd Bergmann 		case SIOCGIFBRDADDR:
30117a229387SArnd Bergmann 		case SIOCGIFDSTADDR:
30127a229387SArnd Bergmann 		case SIOCGIFNETMASK:
3013fab2532bSArnd Bergmann 		case SIOCGIFPFLAGS:
30147a229387SArnd Bergmann 		case SIOCGIFTXQLEN:
3015fab2532bSArnd Bergmann 		case SIOCGMIIPHY:
3016fab2532bSArnd Bergmann 		case SIOCGMIIREG:
3017a2116ed2SArnd Bergmann 			if (copy_in_user(uifr32, uifr, sizeof(*uifr32)))
3018a2116ed2SArnd Bergmann 				err = -EFAULT;
30197a229387SArnd Bergmann 			break;
3020a2116ed2SArnd Bergmann 		}
3021a2116ed2SArnd Bergmann 	}
3022a2116ed2SArnd Bergmann 	return err;
3023a2116ed2SArnd Bergmann }
3024a2116ed2SArnd Bergmann 
3025a2116ed2SArnd Bergmann static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
3026a2116ed2SArnd Bergmann 			struct compat_ifreq __user *uifr32)
3027a2116ed2SArnd Bergmann {
3028a2116ed2SArnd Bergmann 	struct ifreq ifr;
3029a2116ed2SArnd Bergmann 	struct compat_ifmap __user *uifmap32;
3030a2116ed2SArnd Bergmann 	mm_segment_t old_fs;
3031a2116ed2SArnd Bergmann 	int err;
3032a2116ed2SArnd Bergmann 
3033a2116ed2SArnd Bergmann 	uifmap32 = &uifr32->ifr_ifru.ifru_map;
3034a2116ed2SArnd Bergmann 	err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name));
3035a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
3036a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
3037a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
3038a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.irq, &uifmap32->irq);
3039a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.dma, &uifmap32->dma);
3040a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.port, &uifmap32->port);
3041a2116ed2SArnd Bergmann 	if (err)
3042a2116ed2SArnd Bergmann 		return -EFAULT;
3043a2116ed2SArnd Bergmann 
3044a2116ed2SArnd Bergmann 	old_fs = get_fs();
3045a2116ed2SArnd Bergmann 	set_fs(KERNEL_DS);
3046c3f52ae6Sstephen hemminger 	err = dev_ioctl(net, cmd, (void  __user __force *)&ifr);
3047a2116ed2SArnd Bergmann 	set_fs(old_fs);
3048a2116ed2SArnd Bergmann 
3049a2116ed2SArnd Bergmann 	if (cmd == SIOCGIFMAP && !err) {
30507a229387SArnd Bergmann 		err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name));
30517a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
30527a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
30537a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
30547a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.irq, &uifmap32->irq);
30557a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.dma, &uifmap32->dma);
30567a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.port, &uifmap32->port);
30577a229387SArnd Bergmann 		if (err)
30587a229387SArnd Bergmann 			err = -EFAULT;
30597a229387SArnd Bergmann 	}
30607a229387SArnd Bergmann 	return err;
30617a229387SArnd Bergmann }
30627a229387SArnd Bergmann 
3063a2116ed2SArnd Bergmann static int compat_siocshwtstamp(struct net *net, struct compat_ifreq __user *uifr32)
3064a2116ed2SArnd Bergmann {
3065a2116ed2SArnd Bergmann 	void __user *uptr;
3066a2116ed2SArnd Bergmann 	compat_uptr_t uptr32;
3067a2116ed2SArnd Bergmann 	struct ifreq __user *uifr;
3068a2116ed2SArnd Bergmann 
3069a2116ed2SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
3070a2116ed2SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
3071a2116ed2SArnd Bergmann 		return -EFAULT;
3072a2116ed2SArnd Bergmann 
3073a2116ed2SArnd Bergmann 	if (get_user(uptr32, &uifr32->ifr_data))
3074a2116ed2SArnd Bergmann 		return -EFAULT;
3075a2116ed2SArnd Bergmann 
3076a2116ed2SArnd Bergmann 	uptr = compat_ptr(uptr32);
3077a2116ed2SArnd Bergmann 
3078a2116ed2SArnd Bergmann 	if (put_user(uptr, &uifr->ifr_data))
3079a2116ed2SArnd Bergmann 		return -EFAULT;
3080a2116ed2SArnd Bergmann 
3081a2116ed2SArnd Bergmann 	return dev_ioctl(net, SIOCSHWTSTAMP, uifr);
3082a2116ed2SArnd Bergmann }
3083a2116ed2SArnd Bergmann 
30847a229387SArnd Bergmann struct rtentry32 {
30857a229387SArnd Bergmann 	u32		rt_pad1;
30867a229387SArnd Bergmann 	struct sockaddr rt_dst;         /* target address               */
30877a229387SArnd Bergmann 	struct sockaddr rt_gateway;     /* gateway addr (RTF_GATEWAY)   */
30887a229387SArnd Bergmann 	struct sockaddr rt_genmask;     /* target network mask (IP)     */
30897a229387SArnd Bergmann 	unsigned short	rt_flags;
30907a229387SArnd Bergmann 	short		rt_pad2;
30917a229387SArnd Bergmann 	u32		rt_pad3;
30927a229387SArnd Bergmann 	unsigned char	rt_tos;
30937a229387SArnd Bergmann 	unsigned char	rt_class;
30947a229387SArnd Bergmann 	short		rt_pad4;
30957a229387SArnd Bergmann 	short		rt_metric;      /* +1 for binary compatibility! */
30967a229387SArnd Bergmann 	/* char * */ u32 rt_dev;        /* forcing the device at add    */
30977a229387SArnd Bergmann 	u32		rt_mtu;         /* per route MTU/Window         */
30987a229387SArnd Bergmann 	u32		rt_window;      /* Window clamping              */
30997a229387SArnd Bergmann 	unsigned short  rt_irtt;        /* Initial RTT                  */
31007a229387SArnd Bergmann };
31017a229387SArnd Bergmann 
31027a229387SArnd Bergmann struct in6_rtmsg32 {
31037a229387SArnd Bergmann 	struct in6_addr		rtmsg_dst;
31047a229387SArnd Bergmann 	struct in6_addr		rtmsg_src;
31057a229387SArnd Bergmann 	struct in6_addr		rtmsg_gateway;
31067a229387SArnd Bergmann 	u32			rtmsg_type;
31077a229387SArnd Bergmann 	u16			rtmsg_dst_len;
31087a229387SArnd Bergmann 	u16			rtmsg_src_len;
31097a229387SArnd Bergmann 	u32			rtmsg_metric;
31107a229387SArnd Bergmann 	u32			rtmsg_info;
31117a229387SArnd Bergmann 	u32			rtmsg_flags;
31127a229387SArnd Bergmann 	s32			rtmsg_ifindex;
31137a229387SArnd Bergmann };
31147a229387SArnd Bergmann 
31156b96018bSArnd Bergmann static int routing_ioctl(struct net *net, struct socket *sock,
31166b96018bSArnd Bergmann 			 unsigned int cmd, void __user *argp)
31177a229387SArnd Bergmann {
31187a229387SArnd Bergmann 	int ret;
31197a229387SArnd Bergmann 	void *r = NULL;
31207a229387SArnd Bergmann 	struct in6_rtmsg r6;
31217a229387SArnd Bergmann 	struct rtentry r4;
31227a229387SArnd Bergmann 	char devname[16];
31237a229387SArnd Bergmann 	u32 rtdev;
31247a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
31257a229387SArnd Bergmann 
31266b96018bSArnd Bergmann 	if (sock && sock->sk && sock->sk->sk_family == AF_INET6) { /* ipv6 */
31276b96018bSArnd Bergmann 		struct in6_rtmsg32 __user *ur6 = argp;
31287a229387SArnd Bergmann 		ret = copy_from_user(&r6.rtmsg_dst, &(ur6->rtmsg_dst),
31297a229387SArnd Bergmann 			3 * sizeof(struct in6_addr));
31307a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_type, &(ur6->rtmsg_type));
31317a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len));
31327a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_src_len, &(ur6->rtmsg_src_len));
31337a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_metric, &(ur6->rtmsg_metric));
31347a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_info, &(ur6->rtmsg_info));
31357a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_flags, &(ur6->rtmsg_flags));
31367a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex));
31377a229387SArnd Bergmann 
31387a229387SArnd Bergmann 		r = (void *) &r6;
31397a229387SArnd Bergmann 	} else { /* ipv4 */
31406b96018bSArnd Bergmann 		struct rtentry32 __user *ur4 = argp;
31417a229387SArnd Bergmann 		ret = copy_from_user(&r4.rt_dst, &(ur4->rt_dst),
31427a229387SArnd Bergmann 					3 * sizeof(struct sockaddr));
31437a229387SArnd Bergmann 		ret |= __get_user(r4.rt_flags, &(ur4->rt_flags));
31447a229387SArnd Bergmann 		ret |= __get_user(r4.rt_metric, &(ur4->rt_metric));
31457a229387SArnd Bergmann 		ret |= __get_user(r4.rt_mtu, &(ur4->rt_mtu));
31467a229387SArnd Bergmann 		ret |= __get_user(r4.rt_window, &(ur4->rt_window));
31477a229387SArnd Bergmann 		ret |= __get_user(r4.rt_irtt, &(ur4->rt_irtt));
31487a229387SArnd Bergmann 		ret |= __get_user(rtdev, &(ur4->rt_dev));
31497a229387SArnd Bergmann 		if (rtdev) {
31507a229387SArnd Bergmann 			ret |= copy_from_user(devname, compat_ptr(rtdev), 15);
3151c3f52ae6Sstephen hemminger 			r4.rt_dev = (char __user __force *)devname;
3152c3f52ae6Sstephen hemminger 			devname[15] = 0;
31537a229387SArnd Bergmann 		} else
31547a229387SArnd Bergmann 			r4.rt_dev = NULL;
31557a229387SArnd Bergmann 
31567a229387SArnd Bergmann 		r = (void *) &r4;
31577a229387SArnd Bergmann 	}
31587a229387SArnd Bergmann 
31597a229387SArnd Bergmann 	if (ret) {
31607a229387SArnd Bergmann 		ret = -EFAULT;
31617a229387SArnd Bergmann 		goto out;
31627a229387SArnd Bergmann 	}
31637a229387SArnd Bergmann 
31647a229387SArnd Bergmann 	set_fs(KERNEL_DS);
31656b96018bSArnd Bergmann 	ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r);
31667a229387SArnd Bergmann 	set_fs(old_fs);
31677a229387SArnd Bergmann 
31687a229387SArnd Bergmann out:
31697a229387SArnd Bergmann 	return ret;
31707a229387SArnd Bergmann }
31717a229387SArnd Bergmann 
31727a229387SArnd Bergmann /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE
31737a229387SArnd Bergmann  * for some operations; this forces use of the newer bridge-utils that
317425985edcSLucas De Marchi  * use compatible ioctls
31757a229387SArnd Bergmann  */
31766b96018bSArnd Bergmann static int old_bridge_ioctl(compat_ulong_t __user *argp)
31777a229387SArnd Bergmann {
31786b96018bSArnd Bergmann 	compat_ulong_t tmp;
31797a229387SArnd Bergmann 
31806b96018bSArnd Bergmann 	if (get_user(tmp, argp))
31817a229387SArnd Bergmann 		return -EFAULT;
31827a229387SArnd Bergmann 	if (tmp == BRCTL_GET_VERSION)
31837a229387SArnd Bergmann 		return BRCTL_VERSION + 1;
31847a229387SArnd Bergmann 	return -EINVAL;
31857a229387SArnd Bergmann }
31867a229387SArnd Bergmann 
31876b96018bSArnd Bergmann static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
31886b96018bSArnd Bergmann 			 unsigned int cmd, unsigned long arg)
31896b96018bSArnd Bergmann {
31906b96018bSArnd Bergmann 	void __user *argp = compat_ptr(arg);
31916b96018bSArnd Bergmann 	struct sock *sk = sock->sk;
31926b96018bSArnd Bergmann 	struct net *net = sock_net(sk);
31937a229387SArnd Bergmann 
31946b96018bSArnd Bergmann 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
31956b96018bSArnd Bergmann 		return siocdevprivate_ioctl(net, cmd, argp);
31967a229387SArnd Bergmann 
31976b96018bSArnd Bergmann 	switch (cmd) {
31986b96018bSArnd Bergmann 	case SIOCSIFBR:
31996b96018bSArnd Bergmann 	case SIOCGIFBR:
32006b96018bSArnd Bergmann 		return old_bridge_ioctl(argp);
32016b96018bSArnd Bergmann 	case SIOCGIFNAME:
32026b96018bSArnd Bergmann 		return dev_ifname32(net, argp);
32036b96018bSArnd Bergmann 	case SIOCGIFCONF:
32046b96018bSArnd Bergmann 		return dev_ifconf(net, argp);
32056b96018bSArnd Bergmann 	case SIOCETHTOOL:
32066b96018bSArnd Bergmann 		return ethtool_ioctl(net, argp);
32077a50a240SArnd Bergmann 	case SIOCWANDEV:
32087a50a240SArnd Bergmann 		return compat_siocwandev(net, argp);
3209a2116ed2SArnd Bergmann 	case SIOCGIFMAP:
3210a2116ed2SArnd Bergmann 	case SIOCSIFMAP:
3211a2116ed2SArnd Bergmann 		return compat_sioc_ifmap(net, cmd, argp);
32126b96018bSArnd Bergmann 	case SIOCBONDENSLAVE:
32136b96018bSArnd Bergmann 	case SIOCBONDRELEASE:
32146b96018bSArnd Bergmann 	case SIOCBONDSETHWADDR:
32156b96018bSArnd Bergmann 	case SIOCBONDSLAVEINFOQUERY:
32166b96018bSArnd Bergmann 	case SIOCBONDINFOQUERY:
32176b96018bSArnd Bergmann 	case SIOCBONDCHANGEACTIVE:
32186b96018bSArnd Bergmann 		return bond_ioctl(net, cmd, argp);
32196b96018bSArnd Bergmann 	case SIOCADDRT:
32206b96018bSArnd Bergmann 	case SIOCDELRT:
32216b96018bSArnd Bergmann 		return routing_ioctl(net, sock, cmd, argp);
32226b96018bSArnd Bergmann 	case SIOCGSTAMP:
32236b96018bSArnd Bergmann 		return do_siocgstamp(net, sock, cmd, argp);
32246b96018bSArnd Bergmann 	case SIOCGSTAMPNS:
32256b96018bSArnd Bergmann 		return do_siocgstampns(net, sock, cmd, argp);
3226a2116ed2SArnd Bergmann 	case SIOCSHWTSTAMP:
3227a2116ed2SArnd Bergmann 		return compat_siocshwtstamp(net, argp);
32287a229387SArnd Bergmann 
32296b96018bSArnd Bergmann 	case FIOSETOWN:
32306b96018bSArnd Bergmann 	case SIOCSPGRP:
32316b96018bSArnd Bergmann 	case FIOGETOWN:
32326b96018bSArnd Bergmann 	case SIOCGPGRP:
32336b96018bSArnd Bergmann 	case SIOCBRADDBR:
32346b96018bSArnd Bergmann 	case SIOCBRDELBR:
32356b96018bSArnd Bergmann 	case SIOCGIFVLAN:
32366b96018bSArnd Bergmann 	case SIOCSIFVLAN:
32376b96018bSArnd Bergmann 	case SIOCADDDLCI:
32386b96018bSArnd Bergmann 	case SIOCDELDLCI:
32396b96018bSArnd Bergmann 		return sock_ioctl(file, cmd, arg);
32406b96018bSArnd Bergmann 
32416b96018bSArnd Bergmann 	case SIOCGIFFLAGS:
32426b96018bSArnd Bergmann 	case SIOCSIFFLAGS:
32436b96018bSArnd Bergmann 	case SIOCGIFMETRIC:
32446b96018bSArnd Bergmann 	case SIOCSIFMETRIC:
32456b96018bSArnd Bergmann 	case SIOCGIFMTU:
32466b96018bSArnd Bergmann 	case SIOCSIFMTU:
32476b96018bSArnd Bergmann 	case SIOCGIFMEM:
32486b96018bSArnd Bergmann 	case SIOCSIFMEM:
32496b96018bSArnd Bergmann 	case SIOCGIFHWADDR:
32506b96018bSArnd Bergmann 	case SIOCSIFHWADDR:
32516b96018bSArnd Bergmann 	case SIOCADDMULTI:
32526b96018bSArnd Bergmann 	case SIOCDELMULTI:
32536b96018bSArnd Bergmann 	case SIOCGIFINDEX:
32546b96018bSArnd Bergmann 	case SIOCGIFADDR:
32556b96018bSArnd Bergmann 	case SIOCSIFADDR:
32566b96018bSArnd Bergmann 	case SIOCSIFHWBROADCAST:
32576b96018bSArnd Bergmann 	case SIOCDIFADDR:
32586b96018bSArnd Bergmann 	case SIOCGIFBRDADDR:
32596b96018bSArnd Bergmann 	case SIOCSIFBRDADDR:
32606b96018bSArnd Bergmann 	case SIOCGIFDSTADDR:
32616b96018bSArnd Bergmann 	case SIOCSIFDSTADDR:
32626b96018bSArnd Bergmann 	case SIOCGIFNETMASK:
32636b96018bSArnd Bergmann 	case SIOCSIFNETMASK:
32646b96018bSArnd Bergmann 	case SIOCSIFPFLAGS:
32656b96018bSArnd Bergmann 	case SIOCGIFPFLAGS:
32666b96018bSArnd Bergmann 	case SIOCGIFTXQLEN:
32676b96018bSArnd Bergmann 	case SIOCSIFTXQLEN:
32686b96018bSArnd Bergmann 	case SIOCBRADDIF:
32696b96018bSArnd Bergmann 	case SIOCBRDELIF:
32709177efd3SArnd Bergmann 	case SIOCSIFNAME:
32719177efd3SArnd Bergmann 	case SIOCGMIIPHY:
32729177efd3SArnd Bergmann 	case SIOCGMIIREG:
32739177efd3SArnd Bergmann 	case SIOCSMIIREG:
32746b96018bSArnd Bergmann 		return dev_ifsioc(net, sock, cmd, argp);
32759177efd3SArnd Bergmann 
32766b96018bSArnd Bergmann 	case SIOCSARP:
32776b96018bSArnd Bergmann 	case SIOCGARP:
32786b96018bSArnd Bergmann 	case SIOCDARP:
32796b96018bSArnd Bergmann 	case SIOCATMARK:
32809177efd3SArnd Bergmann 		return sock_do_ioctl(net, sock, cmd, arg);
32819177efd3SArnd Bergmann 	}
32829177efd3SArnd Bergmann 
32836b96018bSArnd Bergmann 	return -ENOIOCTLCMD;
32846b96018bSArnd Bergmann }
32857a229387SArnd Bergmann 
328695c96174SEric Dumazet static long compat_sock_ioctl(struct file *file, unsigned int cmd,
328789bbfc95SShaun Pereira 			      unsigned long arg)
328889bbfc95SShaun Pereira {
328989bbfc95SShaun Pereira 	struct socket *sock = file->private_data;
329089bbfc95SShaun Pereira 	int ret = -ENOIOCTLCMD;
329187de87d5SDavid S. Miller 	struct sock *sk;
329287de87d5SDavid S. Miller 	struct net *net;
329387de87d5SDavid S. Miller 
329487de87d5SDavid S. Miller 	sk = sock->sk;
329587de87d5SDavid S. Miller 	net = sock_net(sk);
329689bbfc95SShaun Pereira 
329789bbfc95SShaun Pereira 	if (sock->ops->compat_ioctl)
329889bbfc95SShaun Pereira 		ret = sock->ops->compat_ioctl(sock, cmd, arg);
329989bbfc95SShaun Pereira 
330087de87d5SDavid S. Miller 	if (ret == -ENOIOCTLCMD &&
330187de87d5SDavid S. Miller 	    (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST))
330287de87d5SDavid S. Miller 		ret = compat_wext_handle_ioctl(net, cmd, arg);
330387de87d5SDavid S. Miller 
33046b96018bSArnd Bergmann 	if (ret == -ENOIOCTLCMD)
33056b96018bSArnd Bergmann 		ret = compat_sock_ioctl_trans(file, sock, cmd, arg);
33066b96018bSArnd Bergmann 
330789bbfc95SShaun Pereira 	return ret;
330889bbfc95SShaun Pereira }
330989bbfc95SShaun Pereira #endif
331089bbfc95SShaun Pereira 
3311ac5a488eSSridhar Samudrala int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
3312ac5a488eSSridhar Samudrala {
3313ac5a488eSSridhar Samudrala 	return sock->ops->bind(sock, addr, addrlen);
3314ac5a488eSSridhar Samudrala }
3315c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_bind);
3316ac5a488eSSridhar Samudrala 
3317ac5a488eSSridhar Samudrala int kernel_listen(struct socket *sock, int backlog)
3318ac5a488eSSridhar Samudrala {
3319ac5a488eSSridhar Samudrala 	return sock->ops->listen(sock, backlog);
3320ac5a488eSSridhar Samudrala }
3321c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_listen);
3322ac5a488eSSridhar Samudrala 
3323ac5a488eSSridhar Samudrala int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
3324ac5a488eSSridhar Samudrala {
3325ac5a488eSSridhar Samudrala 	struct sock *sk = sock->sk;
3326ac5a488eSSridhar Samudrala 	int err;
3327ac5a488eSSridhar Samudrala 
3328ac5a488eSSridhar Samudrala 	err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
3329ac5a488eSSridhar Samudrala 			       newsock);
3330ac5a488eSSridhar Samudrala 	if (err < 0)
3331ac5a488eSSridhar Samudrala 		goto done;
3332ac5a488eSSridhar Samudrala 
3333ac5a488eSSridhar Samudrala 	err = sock->ops->accept(sock, *newsock, flags);
3334ac5a488eSSridhar Samudrala 	if (err < 0) {
3335ac5a488eSSridhar Samudrala 		sock_release(*newsock);
3336fa8705b0STony Battersby 		*newsock = NULL;
3337ac5a488eSSridhar Samudrala 		goto done;
3338ac5a488eSSridhar Samudrala 	}
3339ac5a488eSSridhar Samudrala 
3340ac5a488eSSridhar Samudrala 	(*newsock)->ops = sock->ops;
33411b08534eSWei Yongjun 	__module_get((*newsock)->ops->owner);
3342ac5a488eSSridhar Samudrala 
3343ac5a488eSSridhar Samudrala done:
3344ac5a488eSSridhar Samudrala 	return err;
3345ac5a488eSSridhar Samudrala }
3346c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_accept);
3347ac5a488eSSridhar Samudrala 
3348ac5a488eSSridhar Samudrala int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
3349ac5a488eSSridhar Samudrala 		   int flags)
3350ac5a488eSSridhar Samudrala {
3351ac5a488eSSridhar Samudrala 	return sock->ops->connect(sock, addr, addrlen, flags);
3352ac5a488eSSridhar Samudrala }
3353c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_connect);
3354ac5a488eSSridhar Samudrala 
3355ac5a488eSSridhar Samudrala int kernel_getsockname(struct socket *sock, struct sockaddr *addr,
3356ac5a488eSSridhar Samudrala 			 int *addrlen)
3357ac5a488eSSridhar Samudrala {
3358ac5a488eSSridhar Samudrala 	return sock->ops->getname(sock, addr, addrlen, 0);
3359ac5a488eSSridhar Samudrala }
3360c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockname);
3361ac5a488eSSridhar Samudrala 
3362ac5a488eSSridhar Samudrala int kernel_getpeername(struct socket *sock, struct sockaddr *addr,
3363ac5a488eSSridhar Samudrala 			 int *addrlen)
3364ac5a488eSSridhar Samudrala {
3365ac5a488eSSridhar Samudrala 	return sock->ops->getname(sock, addr, addrlen, 1);
3366ac5a488eSSridhar Samudrala }
3367c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getpeername);
3368ac5a488eSSridhar Samudrala 
3369ac5a488eSSridhar Samudrala int kernel_getsockopt(struct socket *sock, int level, int optname,
3370ac5a488eSSridhar Samudrala 			char *optval, int *optlen)
3371ac5a488eSSridhar Samudrala {
3372ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3373fb8621bbSNamhyung Kim 	char __user *uoptval;
3374fb8621bbSNamhyung Kim 	int __user *uoptlen;
3375ac5a488eSSridhar Samudrala 	int err;
3376ac5a488eSSridhar Samudrala 
3377fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3378fb8621bbSNamhyung Kim 	uoptlen = (int __user __force *) optlen;
3379fb8621bbSNamhyung Kim 
3380ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3381ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3382fb8621bbSNamhyung Kim 		err = sock_getsockopt(sock, level, optname, uoptval, uoptlen);
3383ac5a488eSSridhar Samudrala 	else
3384fb8621bbSNamhyung Kim 		err = sock->ops->getsockopt(sock, level, optname, uoptval,
3385fb8621bbSNamhyung Kim 					    uoptlen);
3386ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3387ac5a488eSSridhar Samudrala 	return err;
3388ac5a488eSSridhar Samudrala }
3389c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockopt);
3390ac5a488eSSridhar Samudrala 
3391ac5a488eSSridhar Samudrala int kernel_setsockopt(struct socket *sock, int level, int optname,
3392b7058842SDavid S. Miller 			char *optval, unsigned int optlen)
3393ac5a488eSSridhar Samudrala {
3394ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3395fb8621bbSNamhyung Kim 	char __user *uoptval;
3396ac5a488eSSridhar Samudrala 	int err;
3397ac5a488eSSridhar Samudrala 
3398fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3399fb8621bbSNamhyung Kim 
3400ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3401ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3402fb8621bbSNamhyung Kim 		err = sock_setsockopt(sock, level, optname, uoptval, optlen);
3403ac5a488eSSridhar Samudrala 	else
3404fb8621bbSNamhyung Kim 		err = sock->ops->setsockopt(sock, level, optname, uoptval,
3405ac5a488eSSridhar Samudrala 					    optlen);
3406ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3407ac5a488eSSridhar Samudrala 	return err;
3408ac5a488eSSridhar Samudrala }
3409c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_setsockopt);
3410ac5a488eSSridhar Samudrala 
3411ac5a488eSSridhar Samudrala int kernel_sendpage(struct socket *sock, struct page *page, int offset,
3412ac5a488eSSridhar Samudrala 		    size_t size, int flags)
3413ac5a488eSSridhar Samudrala {
3414ac5a488eSSridhar Samudrala 	if (sock->ops->sendpage)
3415ac5a488eSSridhar Samudrala 		return sock->ops->sendpage(sock, page, offset, size, flags);
3416ac5a488eSSridhar Samudrala 
3417ac5a488eSSridhar Samudrala 	return sock_no_sendpage(sock, page, offset, size, flags);
3418ac5a488eSSridhar Samudrala }
3419c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendpage);
3420ac5a488eSSridhar Samudrala 
3421ac5a488eSSridhar Samudrala int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg)
3422ac5a488eSSridhar Samudrala {
3423ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3424ac5a488eSSridhar Samudrala 	int err;
3425ac5a488eSSridhar Samudrala 
3426ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3427ac5a488eSSridhar Samudrala 	err = sock->ops->ioctl(sock, cmd, arg);
3428ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3429ac5a488eSSridhar Samudrala 
3430ac5a488eSSridhar Samudrala 	return err;
3431ac5a488eSSridhar Samudrala }
3432c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sock_ioctl);
3433ac5a488eSSridhar Samudrala 
343491cf45f0STrond Myklebust int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
343591cf45f0STrond Myklebust {
343691cf45f0STrond Myklebust 	return sock->ops->shutdown(sock, how);
343791cf45f0STrond Myklebust }
343891cf45f0STrond Myklebust EXPORT_SYMBOL(kernel_sock_shutdown);
3439