xref: /openbmc/linux/net/socket.c (revision e0b93edd)
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>
75408eccceSDaniel Borkmann #include <linux/ptp_classify.h>
761da177e4SLinus Torvalds #include <linux/init.h>
771da177e4SLinus Torvalds #include <linux/poll.h>
781da177e4SLinus Torvalds #include <linux/cache.h>
791da177e4SLinus Torvalds #include <linux/module.h>
801da177e4SLinus Torvalds #include <linux/highmem.h>
811da177e4SLinus Torvalds #include <linux/mount.h>
821da177e4SLinus Torvalds #include <linux/security.h>
831da177e4SLinus Torvalds #include <linux/syscalls.h>
841da177e4SLinus Torvalds #include <linux/compat.h>
851da177e4SLinus Torvalds #include <linux/kmod.h>
863ec3b2fbSDavid Woodhouse #include <linux/audit.h>
87d86b5e0eSAdrian Bunk #include <linux/wireless.h>
881b8d7ae4SEric W. Biederman #include <linux/nsproxy.h>
891fd7317dSNick Black #include <linux/magic.h>
905a0e3ad6STejun Heo #include <linux/slab.h>
91600e1779SMasatake YAMATO #include <linux/xattr.h>
921da177e4SLinus Torvalds 
931da177e4SLinus Torvalds #include <asm/uaccess.h>
941da177e4SLinus Torvalds #include <asm/unistd.h>
951da177e4SLinus Torvalds 
961da177e4SLinus Torvalds #include <net/compat.h>
9787de87d5SDavid S. Miller #include <net/wext.h>
98f8451725SHerbert Xu #include <net/cls_cgroup.h>
991da177e4SLinus Torvalds 
1001da177e4SLinus Torvalds #include <net/sock.h>
1011da177e4SLinus Torvalds #include <linux/netfilter.h>
1021da177e4SLinus Torvalds 
1036b96018bSArnd Bergmann #include <linux/if_tun.h>
1046b96018bSArnd Bergmann #include <linux/ipv6_route.h>
1056b96018bSArnd Bergmann #include <linux/route.h>
1066b96018bSArnd Bergmann #include <linux/sockios.h>
1076b96018bSArnd Bergmann #include <linux/atalk.h>
108076bb0c8SEliezer Tamir #include <net/busy_poll.h>
109f24b9be5SWillem de Bruijn #include <linux/errqueue.h>
11006021292SEliezer Tamir 
111e0d1095aSCong Wang #ifdef CONFIG_NET_RX_BUSY_POLL
11264b0dc51SEliezer Tamir unsigned int sysctl_net_busy_read __read_mostly;
11364b0dc51SEliezer Tamir unsigned int sysctl_net_busy_poll __read_mostly;
11406021292SEliezer Tamir #endif
1156b96018bSArnd Bergmann 
1161da177e4SLinus Torvalds static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
117027445c3SBadari Pulavarty static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
118027445c3SBadari Pulavarty 			 unsigned long nr_segs, loff_t pos);
119027445c3SBadari Pulavarty static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
120027445c3SBadari Pulavarty 			  unsigned long nr_segs, loff_t pos);
1211da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma);
1221da177e4SLinus Torvalds 
1231da177e4SLinus Torvalds static int sock_close(struct inode *inode, struct file *file);
1241da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file,
1251da177e4SLinus Torvalds 			      struct poll_table_struct *wait);
12689bddce5SStephen Hemminger static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
12789bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
12889bbfc95SShaun Pereira static long compat_sock_ioctl(struct file *file,
12989bbfc95SShaun Pereira 			      unsigned int cmd, unsigned long arg);
13089bbfc95SShaun Pereira #endif
1311da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on);
1321da177e4SLinus Torvalds static ssize_t sock_sendpage(struct file *file, struct page *page,
1331da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more);
1349c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
1359c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
1369c55e01cSJens Axboe 				unsigned int flags);
1371da177e4SLinus Torvalds 
1381da177e4SLinus Torvalds /*
1391da177e4SLinus Torvalds  *	Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
1401da177e4SLinus Torvalds  *	in the operation structures but are done directly via the socketcall() multiplexor.
1411da177e4SLinus Torvalds  */
1421da177e4SLinus Torvalds 
143da7071d7SArjan van de Ven static const struct file_operations socket_file_ops = {
1441da177e4SLinus Torvalds 	.owner =	THIS_MODULE,
1451da177e4SLinus Torvalds 	.llseek =	no_llseek,
1461da177e4SLinus Torvalds 	.aio_read =	sock_aio_read,
1471da177e4SLinus Torvalds 	.aio_write =	sock_aio_write,
1481da177e4SLinus Torvalds 	.poll =		sock_poll,
1491da177e4SLinus Torvalds 	.unlocked_ioctl = sock_ioctl,
15089bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
15189bbfc95SShaun Pereira 	.compat_ioctl = compat_sock_ioctl,
15289bbfc95SShaun Pereira #endif
1531da177e4SLinus Torvalds 	.mmap =		sock_mmap,
1541da177e4SLinus Torvalds 	.open =		sock_no_open,	/* special open code to disallow open via /proc */
1551da177e4SLinus Torvalds 	.release =	sock_close,
1561da177e4SLinus Torvalds 	.fasync =	sock_fasync,
1575274f052SJens Axboe 	.sendpage =	sock_sendpage,
1585274f052SJens Axboe 	.splice_write = generic_splice_sendpage,
1599c55e01cSJens Axboe 	.splice_read =	sock_splice_read,
1601da177e4SLinus Torvalds };
1611da177e4SLinus Torvalds 
1621da177e4SLinus Torvalds /*
1631da177e4SLinus Torvalds  *	The protocol list. Each protocol is registered in here.
1641da177e4SLinus Torvalds  */
1651da177e4SLinus Torvalds 
1661da177e4SLinus Torvalds static DEFINE_SPINLOCK(net_family_lock);
167190683a9SEric Dumazet static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly;
1681da177e4SLinus Torvalds 
1691da177e4SLinus Torvalds /*
1701da177e4SLinus Torvalds  *	Statistics counters of the socket lists
1711da177e4SLinus Torvalds  */
1721da177e4SLinus Torvalds 
173c6d409cfSEric Dumazet static DEFINE_PER_CPU(int, sockets_in_use);
1741da177e4SLinus Torvalds 
1751da177e4SLinus Torvalds /*
17689bddce5SStephen Hemminger  * Support routines.
17789bddce5SStephen Hemminger  * Move socket addresses back and forth across the kernel/user
1781da177e4SLinus Torvalds  * divide and look after the messy bits.
1791da177e4SLinus Torvalds  */
1801da177e4SLinus Torvalds 
1811da177e4SLinus Torvalds /**
1821da177e4SLinus Torvalds  *	move_addr_to_kernel	-	copy a socket address into kernel space
1831da177e4SLinus Torvalds  *	@uaddr: Address in user space
1841da177e4SLinus Torvalds  *	@kaddr: Address in kernel space
1851da177e4SLinus Torvalds  *	@ulen: Length in user space
1861da177e4SLinus Torvalds  *
1871da177e4SLinus Torvalds  *	The address is copied into kernel space. If the provided address is
1881da177e4SLinus Torvalds  *	too long an error code of -EINVAL is returned. If the copy gives
1891da177e4SLinus Torvalds  *	invalid addresses -EFAULT is returned. On a success 0 is returned.
1901da177e4SLinus Torvalds  */
1911da177e4SLinus Torvalds 
19243db362dSMaciej Żenczykowski int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr)
1931da177e4SLinus Torvalds {
194230b1839SYOSHIFUJI Hideaki 	if (ulen < 0 || ulen > sizeof(struct sockaddr_storage))
1951da177e4SLinus Torvalds 		return -EINVAL;
1961da177e4SLinus Torvalds 	if (ulen == 0)
1971da177e4SLinus Torvalds 		return 0;
1981da177e4SLinus Torvalds 	if (copy_from_user(kaddr, uaddr, ulen))
1991da177e4SLinus Torvalds 		return -EFAULT;
2003ec3b2fbSDavid Woodhouse 	return audit_sockaddr(ulen, kaddr);
2011da177e4SLinus Torvalds }
2021da177e4SLinus Torvalds 
2031da177e4SLinus Torvalds /**
2041da177e4SLinus Torvalds  *	move_addr_to_user	-	copy an address to user space
2051da177e4SLinus Torvalds  *	@kaddr: kernel space address
2061da177e4SLinus Torvalds  *	@klen: length of address in kernel
2071da177e4SLinus Torvalds  *	@uaddr: user space address
2081da177e4SLinus Torvalds  *	@ulen: pointer to user length field
2091da177e4SLinus Torvalds  *
2101da177e4SLinus Torvalds  *	The value pointed to by ulen on entry is the buffer length available.
2111da177e4SLinus Torvalds  *	This is overwritten with the buffer space used. -EINVAL is returned
2121da177e4SLinus Torvalds  *	if an overlong buffer is specified or a negative buffer size. -EFAULT
2131da177e4SLinus Torvalds  *	is returned if either the buffer or the length field are not
2141da177e4SLinus Torvalds  *	accessible.
2151da177e4SLinus Torvalds  *	After copying the data up to the limit the user specifies, the true
2161da177e4SLinus Torvalds  *	length of the data is written over the length limit the user
2171da177e4SLinus Torvalds  *	specified. Zero is returned for a success.
2181da177e4SLinus Torvalds  */
2191da177e4SLinus Torvalds 
22043db362dSMaciej Żenczykowski static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen,
22111165f14Sstephen hemminger 			     void __user *uaddr, int __user *ulen)
2221da177e4SLinus Torvalds {
2231da177e4SLinus Torvalds 	int err;
2241da177e4SLinus Torvalds 	int len;
2251da177e4SLinus Torvalds 
22668c6beb3SHannes Frederic Sowa 	BUG_ON(klen > sizeof(struct sockaddr_storage));
22789bddce5SStephen Hemminger 	err = get_user(len, ulen);
22889bddce5SStephen Hemminger 	if (err)
2291da177e4SLinus Torvalds 		return err;
2301da177e4SLinus Torvalds 	if (len > klen)
2311da177e4SLinus Torvalds 		len = klen;
23268c6beb3SHannes Frederic Sowa 	if (len < 0)
2331da177e4SLinus Torvalds 		return -EINVAL;
23489bddce5SStephen Hemminger 	if (len) {
235d6fe3945SSteve Grubb 		if (audit_sockaddr(klen, kaddr))
236d6fe3945SSteve Grubb 			return -ENOMEM;
2371da177e4SLinus Torvalds 		if (copy_to_user(uaddr, kaddr, len))
2381da177e4SLinus Torvalds 			return -EFAULT;
2391da177e4SLinus Torvalds 	}
2401da177e4SLinus Torvalds 	/*
2411da177e4SLinus Torvalds 	 *      "fromlen shall refer to the value before truncation.."
2421da177e4SLinus Torvalds 	 *                      1003.1g
2431da177e4SLinus Torvalds 	 */
2441da177e4SLinus Torvalds 	return __put_user(klen, ulen);
2451da177e4SLinus Torvalds }
2461da177e4SLinus Torvalds 
247e18b890bSChristoph Lameter static struct kmem_cache *sock_inode_cachep __read_mostly;
2481da177e4SLinus Torvalds 
2491da177e4SLinus Torvalds static struct inode *sock_alloc_inode(struct super_block *sb)
2501da177e4SLinus Torvalds {
2511da177e4SLinus Torvalds 	struct socket_alloc *ei;
252eaefd110SEric Dumazet 	struct socket_wq *wq;
25389bddce5SStephen Hemminger 
254e94b1766SChristoph Lameter 	ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL);
2551da177e4SLinus Torvalds 	if (!ei)
2561da177e4SLinus Torvalds 		return NULL;
257eaefd110SEric Dumazet 	wq = kmalloc(sizeof(*wq), GFP_KERNEL);
258eaefd110SEric Dumazet 	if (!wq) {
25943815482SEric Dumazet 		kmem_cache_free(sock_inode_cachep, ei);
26043815482SEric Dumazet 		return NULL;
26143815482SEric Dumazet 	}
262eaefd110SEric Dumazet 	init_waitqueue_head(&wq->wait);
263eaefd110SEric Dumazet 	wq->fasync_list = NULL;
264eaefd110SEric Dumazet 	RCU_INIT_POINTER(ei->socket.wq, wq);
2651da177e4SLinus Torvalds 
2661da177e4SLinus Torvalds 	ei->socket.state = SS_UNCONNECTED;
2671da177e4SLinus Torvalds 	ei->socket.flags = 0;
2681da177e4SLinus Torvalds 	ei->socket.ops = NULL;
2691da177e4SLinus Torvalds 	ei->socket.sk = NULL;
2701da177e4SLinus Torvalds 	ei->socket.file = NULL;
2711da177e4SLinus Torvalds 
2721da177e4SLinus Torvalds 	return &ei->vfs_inode;
2731da177e4SLinus Torvalds }
2741da177e4SLinus Torvalds 
2751da177e4SLinus Torvalds static void sock_destroy_inode(struct inode *inode)
2761da177e4SLinus Torvalds {
27743815482SEric Dumazet 	struct socket_alloc *ei;
278eaefd110SEric Dumazet 	struct socket_wq *wq;
27943815482SEric Dumazet 
28043815482SEric Dumazet 	ei = container_of(inode, struct socket_alloc, vfs_inode);
281eaefd110SEric Dumazet 	wq = rcu_dereference_protected(ei->socket.wq, 1);
28261845220SLai Jiangshan 	kfree_rcu(wq, rcu);
28343815482SEric Dumazet 	kmem_cache_free(sock_inode_cachep, ei);
2841da177e4SLinus Torvalds }
2851da177e4SLinus Torvalds 
28651cc5068SAlexey Dobriyan static void init_once(void *foo)
2871da177e4SLinus Torvalds {
2881da177e4SLinus Torvalds 	struct socket_alloc *ei = (struct socket_alloc *)foo;
2891da177e4SLinus Torvalds 
2901da177e4SLinus Torvalds 	inode_init_once(&ei->vfs_inode);
2911da177e4SLinus Torvalds }
2921da177e4SLinus Torvalds 
2931da177e4SLinus Torvalds static int init_inodecache(void)
2941da177e4SLinus Torvalds {
2951da177e4SLinus Torvalds 	sock_inode_cachep = kmem_cache_create("sock_inode_cache",
2961da177e4SLinus Torvalds 					      sizeof(struct socket_alloc),
29789bddce5SStephen Hemminger 					      0,
29889bddce5SStephen Hemminger 					      (SLAB_HWCACHE_ALIGN |
29989bddce5SStephen Hemminger 					       SLAB_RECLAIM_ACCOUNT |
300fffb60f9SPaul Jackson 					       SLAB_MEM_SPREAD),
30120c2df83SPaul Mundt 					      init_once);
3021da177e4SLinus Torvalds 	if (sock_inode_cachep == NULL)
3031da177e4SLinus Torvalds 		return -ENOMEM;
3041da177e4SLinus Torvalds 	return 0;
3051da177e4SLinus Torvalds }
3061da177e4SLinus Torvalds 
307b87221deSAlexey Dobriyan static const struct super_operations sockfs_ops = {
3081da177e4SLinus Torvalds 	.alloc_inode	= sock_alloc_inode,
3091da177e4SLinus Torvalds 	.destroy_inode	= sock_destroy_inode,
3101da177e4SLinus Torvalds 	.statfs		= simple_statfs,
3111da177e4SLinus Torvalds };
3121da177e4SLinus Torvalds 
313c23fbb6bSEric Dumazet /*
314c23fbb6bSEric Dumazet  * sockfs_dname() is called from d_path().
315c23fbb6bSEric Dumazet  */
316c23fbb6bSEric Dumazet static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen)
317c23fbb6bSEric Dumazet {
318c23fbb6bSEric Dumazet 	return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]",
319c23fbb6bSEric Dumazet 				dentry->d_inode->i_ino);
320c23fbb6bSEric Dumazet }
321c23fbb6bSEric Dumazet 
3223ba13d17SAl Viro static const struct dentry_operations sockfs_dentry_operations = {
323c23fbb6bSEric Dumazet 	.d_dname  = sockfs_dname,
3241da177e4SLinus Torvalds };
3251da177e4SLinus Torvalds 
326c74a1cbbSAl Viro static struct dentry *sockfs_mount(struct file_system_type *fs_type,
327c74a1cbbSAl Viro 			 int flags, const char *dev_name, void *data)
328c74a1cbbSAl Viro {
329c74a1cbbSAl Viro 	return mount_pseudo(fs_type, "socket:", &sockfs_ops,
330c74a1cbbSAl Viro 		&sockfs_dentry_operations, SOCKFS_MAGIC);
331c74a1cbbSAl Viro }
332c74a1cbbSAl Viro 
333c74a1cbbSAl Viro static struct vfsmount *sock_mnt __read_mostly;
334c74a1cbbSAl Viro 
335c74a1cbbSAl Viro static struct file_system_type sock_fs_type = {
336c74a1cbbSAl Viro 	.name =		"sockfs",
337c74a1cbbSAl Viro 	.mount =	sockfs_mount,
338c74a1cbbSAl Viro 	.kill_sb =	kill_anon_super,
339c74a1cbbSAl Viro };
340c74a1cbbSAl Viro 
3411da177e4SLinus Torvalds /*
3421da177e4SLinus Torvalds  *	Obtains the first available file descriptor and sets it up for use.
3431da177e4SLinus Torvalds  *
34439d8c1b6SDavid S. Miller  *	These functions create file structures and maps them to fd space
34539d8c1b6SDavid S. Miller  *	of the current process. On success it returns file descriptor
3461da177e4SLinus Torvalds  *	and file struct implicitly stored in sock->file.
3471da177e4SLinus Torvalds  *	Note that another thread may close file descriptor before we return
3481da177e4SLinus Torvalds  *	from this function. We use the fact that now we do not refer
3491da177e4SLinus Torvalds  *	to socket after mapping. If one day we will need it, this
3501da177e4SLinus Torvalds  *	function will increment ref. count on file by 1.
3511da177e4SLinus Torvalds  *
3521da177e4SLinus Torvalds  *	In any case returned fd MAY BE not valid!
3531da177e4SLinus Torvalds  *	This race condition is unavoidable
3541da177e4SLinus Torvalds  *	with shared fd spaces, we cannot solve it inside kernel,
3551da177e4SLinus Torvalds  *	but we take care of internal coherence yet.
3561da177e4SLinus Torvalds  */
3571da177e4SLinus Torvalds 
358aab174f0SLinus Torvalds struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)
3591da177e4SLinus Torvalds {
3607cbe66b6SAl Viro 	struct qstr name = { .name = "" };
3612c48b9c4SAl Viro 	struct path path;
3627cbe66b6SAl Viro 	struct file *file;
3631da177e4SLinus Torvalds 
364600e1779SMasatake YAMATO 	if (dname) {
365600e1779SMasatake YAMATO 		name.name = dname;
366600e1779SMasatake YAMATO 		name.len = strlen(name.name);
367600e1779SMasatake YAMATO 	} else if (sock->sk) {
368600e1779SMasatake YAMATO 		name.name = sock->sk->sk_prot_creator->name;
369600e1779SMasatake YAMATO 		name.len = strlen(name.name);
370600e1779SMasatake YAMATO 	}
3714b936885SNick Piggin 	path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name);
37228407630SAl Viro 	if (unlikely(!path.dentry))
37328407630SAl Viro 		return ERR_PTR(-ENOMEM);
3742c48b9c4SAl Viro 	path.mnt = mntget(sock_mnt);
37539d8c1b6SDavid S. Miller 
3762c48b9c4SAl Viro 	d_instantiate(path.dentry, SOCK_INODE(sock));
377cc3808f8SAl Viro 	SOCK_INODE(sock)->i_fop = &socket_file_ops;
378cc3808f8SAl Viro 
3792c48b9c4SAl Viro 	file = alloc_file(&path, FMODE_READ | FMODE_WRITE,
380cc3808f8SAl Viro 		  &socket_file_ops);
38139b65252SAnatol Pomozov 	if (unlikely(IS_ERR(file))) {
382cc3808f8SAl Viro 		/* drop dentry, keep inode */
3837de9c6eeSAl Viro 		ihold(path.dentry->d_inode);
3842c48b9c4SAl Viro 		path_put(&path);
38539b65252SAnatol Pomozov 		return file;
386cc3808f8SAl Viro 	}
3871da177e4SLinus Torvalds 
3881da177e4SLinus Torvalds 	sock->file = file;
38977d27200SUlrich Drepper 	file->f_flags = O_RDWR | (flags & O_NONBLOCK);
39007dc3f07SBenjamin LaHaise 	file->private_data = sock;
39128407630SAl Viro 	return file;
3921da177e4SLinus Torvalds }
39356b31d1cSAl Viro EXPORT_SYMBOL(sock_alloc_file);
3941da177e4SLinus Torvalds 
39556b31d1cSAl Viro static int sock_map_fd(struct socket *sock, int flags)
39639d8c1b6SDavid S. Miller {
39739d8c1b6SDavid S. Miller 	struct file *newfile;
39828407630SAl Viro 	int fd = get_unused_fd_flags(flags);
39928407630SAl Viro 	if (unlikely(fd < 0))
4001da177e4SLinus Torvalds 		return fd;
4011da177e4SLinus Torvalds 
402aab174f0SLinus Torvalds 	newfile = sock_alloc_file(sock, flags, NULL);
40328407630SAl Viro 	if (likely(!IS_ERR(newfile))) {
4041da177e4SLinus Torvalds 		fd_install(fd, newfile);
4051da177e4SLinus Torvalds 		return fd;
4061da177e4SLinus Torvalds 	}
40728407630SAl Viro 
40828407630SAl Viro 	put_unused_fd(fd);
40928407630SAl Viro 	return PTR_ERR(newfile);
4101da177e4SLinus Torvalds }
4111da177e4SLinus Torvalds 
412406a3c63SJohn Fastabend struct socket *sock_from_file(struct file *file, int *err)
4136cb153caSBenjamin LaHaise {
4146cb153caSBenjamin LaHaise 	if (file->f_op == &socket_file_ops)
4156cb153caSBenjamin LaHaise 		return file->private_data;	/* set in sock_map_fd */
4166cb153caSBenjamin LaHaise 
4176cb153caSBenjamin LaHaise 	*err = -ENOTSOCK;
4186cb153caSBenjamin LaHaise 	return NULL;
4196cb153caSBenjamin LaHaise }
420406a3c63SJohn Fastabend EXPORT_SYMBOL(sock_from_file);
4216cb153caSBenjamin LaHaise 
4221da177e4SLinus Torvalds /**
4231da177e4SLinus Torvalds  *	sockfd_lookup - Go from a file number to its socket slot
4241da177e4SLinus Torvalds  *	@fd: file handle
4251da177e4SLinus Torvalds  *	@err: pointer to an error code return
4261da177e4SLinus Torvalds  *
4271da177e4SLinus Torvalds  *	The file handle passed in is locked and the socket it is bound
4281da177e4SLinus Torvalds  *	too is returned. If an error occurs the err pointer is overwritten
4291da177e4SLinus Torvalds  *	with a negative errno code and NULL is returned. The function checks
4301da177e4SLinus Torvalds  *	for both invalid handles and passing a handle which is not a socket.
4311da177e4SLinus Torvalds  *
4321da177e4SLinus Torvalds  *	On a success the socket object pointer is returned.
4331da177e4SLinus Torvalds  */
4341da177e4SLinus Torvalds 
4351da177e4SLinus Torvalds struct socket *sockfd_lookup(int fd, int *err)
4361da177e4SLinus Torvalds {
4371da177e4SLinus Torvalds 	struct file *file;
4381da177e4SLinus Torvalds 	struct socket *sock;
4391da177e4SLinus Torvalds 
44089bddce5SStephen Hemminger 	file = fget(fd);
44189bddce5SStephen Hemminger 	if (!file) {
4421da177e4SLinus Torvalds 		*err = -EBADF;
4431da177e4SLinus Torvalds 		return NULL;
4441da177e4SLinus Torvalds 	}
44589bddce5SStephen Hemminger 
4466cb153caSBenjamin LaHaise 	sock = sock_from_file(file, err);
4476cb153caSBenjamin LaHaise 	if (!sock)
4481da177e4SLinus Torvalds 		fput(file);
4496cb153caSBenjamin LaHaise 	return sock;
4501da177e4SLinus Torvalds }
451c6d409cfSEric Dumazet EXPORT_SYMBOL(sockfd_lookup);
4521da177e4SLinus Torvalds 
4536cb153caSBenjamin LaHaise static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
4546cb153caSBenjamin LaHaise {
45500e188efSAl Viro 	struct fd f = fdget(fd);
4566cb153caSBenjamin LaHaise 	struct socket *sock;
4576cb153caSBenjamin LaHaise 
4583672558cSHua Zhong 	*err = -EBADF;
45900e188efSAl Viro 	if (f.file) {
46000e188efSAl Viro 		sock = sock_from_file(f.file, err);
46100e188efSAl Viro 		if (likely(sock)) {
46200e188efSAl Viro 			*fput_needed = f.flags;
4631da177e4SLinus Torvalds 			return sock;
46400e188efSAl Viro 		}
46500e188efSAl Viro 		fdput(f);
4666cb153caSBenjamin LaHaise 	}
4676cb153caSBenjamin LaHaise 	return NULL;
4681da177e4SLinus Torvalds }
4691da177e4SLinus Torvalds 
470600e1779SMasatake YAMATO #define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname"
471600e1779SMasatake YAMATO #define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX)
472600e1779SMasatake YAMATO #define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1)
473600e1779SMasatake YAMATO static ssize_t sockfs_getxattr(struct dentry *dentry,
474600e1779SMasatake YAMATO 			       const char *name, void *value, size_t size)
475600e1779SMasatake YAMATO {
476600e1779SMasatake YAMATO 	const char *proto_name;
477600e1779SMasatake YAMATO 	size_t proto_size;
478600e1779SMasatake YAMATO 	int error;
479600e1779SMasatake YAMATO 
480600e1779SMasatake YAMATO 	error = -ENODATA;
481600e1779SMasatake YAMATO 	if (!strncmp(name, XATTR_NAME_SOCKPROTONAME, XATTR_NAME_SOCKPROTONAME_LEN)) {
482600e1779SMasatake YAMATO 		proto_name = dentry->d_name.name;
483600e1779SMasatake YAMATO 		proto_size = strlen(proto_name);
484600e1779SMasatake YAMATO 
485600e1779SMasatake YAMATO 		if (value) {
486600e1779SMasatake YAMATO 			error = -ERANGE;
487600e1779SMasatake YAMATO 			if (proto_size + 1 > size)
488600e1779SMasatake YAMATO 				goto out;
489600e1779SMasatake YAMATO 
490600e1779SMasatake YAMATO 			strncpy(value, proto_name, proto_size + 1);
491600e1779SMasatake YAMATO 		}
492600e1779SMasatake YAMATO 		error = proto_size + 1;
493600e1779SMasatake YAMATO 	}
494600e1779SMasatake YAMATO 
495600e1779SMasatake YAMATO out:
496600e1779SMasatake YAMATO 	return error;
497600e1779SMasatake YAMATO }
498600e1779SMasatake YAMATO 
499600e1779SMasatake YAMATO static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer,
500600e1779SMasatake YAMATO 				size_t size)
501600e1779SMasatake YAMATO {
502600e1779SMasatake YAMATO 	ssize_t len;
503600e1779SMasatake YAMATO 	ssize_t used = 0;
504600e1779SMasatake YAMATO 
505600e1779SMasatake YAMATO 	len = security_inode_listsecurity(dentry->d_inode, buffer, size);
506600e1779SMasatake YAMATO 	if (len < 0)
507600e1779SMasatake YAMATO 		return len;
508600e1779SMasatake YAMATO 	used += len;
509600e1779SMasatake YAMATO 	if (buffer) {
510600e1779SMasatake YAMATO 		if (size < used)
511600e1779SMasatake YAMATO 			return -ERANGE;
512600e1779SMasatake YAMATO 		buffer += len;
513600e1779SMasatake YAMATO 	}
514600e1779SMasatake YAMATO 
515600e1779SMasatake YAMATO 	len = (XATTR_NAME_SOCKPROTONAME_LEN + 1);
516600e1779SMasatake YAMATO 	used += len;
517600e1779SMasatake YAMATO 	if (buffer) {
518600e1779SMasatake YAMATO 		if (size < used)
519600e1779SMasatake YAMATO 			return -ERANGE;
520600e1779SMasatake YAMATO 		memcpy(buffer, XATTR_NAME_SOCKPROTONAME, len);
521600e1779SMasatake YAMATO 		buffer += len;
522600e1779SMasatake YAMATO 	}
523600e1779SMasatake YAMATO 
524600e1779SMasatake YAMATO 	return used;
525600e1779SMasatake YAMATO }
526600e1779SMasatake YAMATO 
527600e1779SMasatake YAMATO static const struct inode_operations sockfs_inode_ops = {
528600e1779SMasatake YAMATO 	.getxattr = sockfs_getxattr,
529600e1779SMasatake YAMATO 	.listxattr = sockfs_listxattr,
530600e1779SMasatake YAMATO };
531600e1779SMasatake YAMATO 
5321da177e4SLinus Torvalds /**
5331da177e4SLinus Torvalds  *	sock_alloc	-	allocate a socket
5341da177e4SLinus Torvalds  *
5351da177e4SLinus Torvalds  *	Allocate a new inode and socket object. The two are bound together
5361da177e4SLinus Torvalds  *	and initialised. The socket is then returned. If we are out of inodes
5371da177e4SLinus Torvalds  *	NULL is returned.
5381da177e4SLinus Torvalds  */
5391da177e4SLinus Torvalds 
5401da177e4SLinus Torvalds static struct socket *sock_alloc(void)
5411da177e4SLinus Torvalds {
5421da177e4SLinus Torvalds 	struct inode *inode;
5431da177e4SLinus Torvalds 	struct socket *sock;
5441da177e4SLinus Torvalds 
545a209dfc7SEric Dumazet 	inode = new_inode_pseudo(sock_mnt->mnt_sb);
5461da177e4SLinus Torvalds 	if (!inode)
5471da177e4SLinus Torvalds 		return NULL;
5481da177e4SLinus Torvalds 
5491da177e4SLinus Torvalds 	sock = SOCKET_I(inode);
5501da177e4SLinus Torvalds 
55129a020d3SEric Dumazet 	kmemcheck_annotate_bitfield(sock, type);
55285fe4025SChristoph Hellwig 	inode->i_ino = get_next_ino();
5531da177e4SLinus Torvalds 	inode->i_mode = S_IFSOCK | S_IRWXUGO;
5548192b0c4SDavid Howells 	inode->i_uid = current_fsuid();
5558192b0c4SDavid Howells 	inode->i_gid = current_fsgid();
556600e1779SMasatake YAMATO 	inode->i_op = &sockfs_inode_ops;
5571da177e4SLinus Torvalds 
55819e8d69cSAlex Shi 	this_cpu_add(sockets_in_use, 1);
5591da177e4SLinus Torvalds 	return sock;
5601da177e4SLinus Torvalds }
5611da177e4SLinus Torvalds 
5621da177e4SLinus Torvalds /*
5631da177e4SLinus Torvalds  *	In theory you can't get an open on this inode, but /proc provides
5641da177e4SLinus Torvalds  *	a back door. Remember to keep it shut otherwise you'll let the
5651da177e4SLinus Torvalds  *	creepy crawlies in.
5661da177e4SLinus Torvalds  */
5671da177e4SLinus Torvalds 
5681da177e4SLinus Torvalds static int sock_no_open(struct inode *irrelevant, struct file *dontcare)
5691da177e4SLinus Torvalds {
5701da177e4SLinus Torvalds 	return -ENXIO;
5711da177e4SLinus Torvalds }
5721da177e4SLinus Torvalds 
5734b6f5d20SArjan van de Ven const struct file_operations bad_sock_fops = {
5741da177e4SLinus Torvalds 	.owner = THIS_MODULE,
5751da177e4SLinus Torvalds 	.open = sock_no_open,
5766038f373SArnd Bergmann 	.llseek = noop_llseek,
5771da177e4SLinus Torvalds };
5781da177e4SLinus Torvalds 
5791da177e4SLinus Torvalds /**
5801da177e4SLinus Torvalds  *	sock_release	-	close a socket
5811da177e4SLinus Torvalds  *	@sock: socket to close
5821da177e4SLinus Torvalds  *
5831da177e4SLinus Torvalds  *	The socket is released from the protocol stack if it has a release
5841da177e4SLinus Torvalds  *	callback, and the inode is then released if the socket is bound to
5851da177e4SLinus Torvalds  *	an inode not a file.
5861da177e4SLinus Torvalds  */
5871da177e4SLinus Torvalds 
5881da177e4SLinus Torvalds void sock_release(struct socket *sock)
5891da177e4SLinus Torvalds {
5901da177e4SLinus Torvalds 	if (sock->ops) {
5911da177e4SLinus Torvalds 		struct module *owner = sock->ops->owner;
5921da177e4SLinus Torvalds 
5931da177e4SLinus Torvalds 		sock->ops->release(sock);
5941da177e4SLinus Torvalds 		sock->ops = NULL;
5951da177e4SLinus Torvalds 		module_put(owner);
5961da177e4SLinus Torvalds 	}
5971da177e4SLinus Torvalds 
598eaefd110SEric Dumazet 	if (rcu_dereference_protected(sock->wq, 1)->fasync_list)
5993410f22eSYang Yingliang 		pr_err("%s: fasync list not empty!\n", __func__);
6001da177e4SLinus Torvalds 
601b09e786bSMikulas Patocka 	if (test_bit(SOCK_EXTERNALLY_ALLOCATED, &sock->flags))
602b09e786bSMikulas Patocka 		return;
603b09e786bSMikulas Patocka 
60419e8d69cSAlex Shi 	this_cpu_sub(sockets_in_use, 1);
6051da177e4SLinus Torvalds 	if (!sock->file) {
6061da177e4SLinus Torvalds 		iput(SOCK_INODE(sock));
6071da177e4SLinus Torvalds 		return;
6081da177e4SLinus Torvalds 	}
6091da177e4SLinus Torvalds 	sock->file = NULL;
6101da177e4SLinus Torvalds }
611c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_release);
6121da177e4SLinus Torvalds 
613140c55d4SEric Dumazet void sock_tx_timestamp(const struct sock *sk, __u8 *tx_flags)
61420d49473SPatrick Ohly {
615140c55d4SEric Dumazet 	u8 flags = *tx_flags;
616140c55d4SEric Dumazet 
617b9f40e21SWillem de Bruijn 	if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_HARDWARE)
618140c55d4SEric Dumazet 		flags |= SKBTX_HW_TSTAMP;
619140c55d4SEric Dumazet 
620b9f40e21SWillem de Bruijn 	if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_SOFTWARE)
621140c55d4SEric Dumazet 		flags |= SKBTX_SW_TSTAMP;
622140c55d4SEric Dumazet 
623e7fd2885SWillem de Bruijn 	if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_SCHED)
624140c55d4SEric Dumazet 		flags |= SKBTX_SCHED_TSTAMP;
625140c55d4SEric Dumazet 
626e1c8a607SWillem de Bruijn 	if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_ACK)
627140c55d4SEric Dumazet 		flags |= SKBTX_ACK_TSTAMP;
628e7fd2885SWillem de Bruijn 
6296e3e939fSJohannes Berg 	if (sock_flag(sk, SOCK_WIFI_STATUS))
630140c55d4SEric Dumazet 		flags |= SKBTX_WIFI_STATUS;
631140c55d4SEric Dumazet 
632140c55d4SEric Dumazet 	*tx_flags = flags;
63320d49473SPatrick Ohly }
63420d49473SPatrick Ohly EXPORT_SYMBOL(sock_tx_timestamp);
63520d49473SPatrick Ohly 
636228e548eSAnton Blanchard static inline int __sock_sendmsg_nosec(struct kiocb *iocb, struct socket *sock,
6371da177e4SLinus Torvalds 				       struct msghdr *msg, size_t size)
6381da177e4SLinus Torvalds {
6391da177e4SLinus Torvalds 	struct sock_iocb *si = kiocb_to_siocb(iocb);
6401da177e4SLinus Torvalds 
6411da177e4SLinus Torvalds 	si->sock = sock;
6421da177e4SLinus Torvalds 	si->scm = NULL;
6431da177e4SLinus Torvalds 	si->msg = msg;
6441da177e4SLinus Torvalds 	si->size = size;
6451da177e4SLinus Torvalds 
6461da177e4SLinus Torvalds 	return sock->ops->sendmsg(iocb, sock, msg, size);
6471da177e4SLinus Torvalds }
6481da177e4SLinus Torvalds 
649228e548eSAnton Blanchard static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock,
650228e548eSAnton Blanchard 				 struct msghdr *msg, size_t size)
651228e548eSAnton Blanchard {
652228e548eSAnton Blanchard 	int err = security_socket_sendmsg(sock, msg, size);
653228e548eSAnton Blanchard 
654228e548eSAnton Blanchard 	return err ?: __sock_sendmsg_nosec(iocb, sock, msg, size);
655228e548eSAnton Blanchard }
656228e548eSAnton Blanchard 
6571da177e4SLinus Torvalds int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
6581da177e4SLinus Torvalds {
6591da177e4SLinus Torvalds 	struct kiocb iocb;
6601da177e4SLinus Torvalds 	struct sock_iocb siocb;
6611da177e4SLinus Torvalds 	int ret;
6621da177e4SLinus Torvalds 
6631da177e4SLinus Torvalds 	init_sync_kiocb(&iocb, NULL);
6641da177e4SLinus Torvalds 	iocb.private = &siocb;
6651da177e4SLinus Torvalds 	ret = __sock_sendmsg(&iocb, sock, msg, size);
6661da177e4SLinus Torvalds 	if (-EIOCBQUEUED == ret)
6671da177e4SLinus Torvalds 		ret = wait_on_sync_kiocb(&iocb);
6681da177e4SLinus Torvalds 	return ret;
6691da177e4SLinus Torvalds }
670c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_sendmsg);
6711da177e4SLinus Torvalds 
672894dc24cSEric Dumazet static int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg, size_t size)
673228e548eSAnton Blanchard {
674228e548eSAnton Blanchard 	struct kiocb iocb;
675228e548eSAnton Blanchard 	struct sock_iocb siocb;
676228e548eSAnton Blanchard 	int ret;
677228e548eSAnton Blanchard 
678228e548eSAnton Blanchard 	init_sync_kiocb(&iocb, NULL);
679228e548eSAnton Blanchard 	iocb.private = &siocb;
680228e548eSAnton Blanchard 	ret = __sock_sendmsg_nosec(&iocb, sock, msg, size);
681228e548eSAnton Blanchard 	if (-EIOCBQUEUED == ret)
682228e548eSAnton Blanchard 		ret = wait_on_sync_kiocb(&iocb);
683228e548eSAnton Blanchard 	return ret;
684228e548eSAnton Blanchard }
685228e548eSAnton Blanchard 
6861da177e4SLinus Torvalds int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
6871da177e4SLinus Torvalds 		   struct kvec *vec, size_t num, size_t size)
6881da177e4SLinus Torvalds {
6891da177e4SLinus Torvalds 	mm_segment_t oldfs = get_fs();
6901da177e4SLinus Torvalds 	int result;
6911da177e4SLinus Torvalds 
6921da177e4SLinus Torvalds 	set_fs(KERNEL_DS);
6931da177e4SLinus Torvalds 	/*
6941da177e4SLinus Torvalds 	 * the following is safe, since for compiler definitions of kvec and
6951da177e4SLinus Torvalds 	 * iovec are identical, yielding the same in-core layout and alignment
6961da177e4SLinus Torvalds 	 */
69789bddce5SStephen Hemminger 	msg->msg_iov = (struct iovec *)vec;
6981da177e4SLinus Torvalds 	msg->msg_iovlen = num;
6991da177e4SLinus Torvalds 	result = sock_sendmsg(sock, msg, size);
7001da177e4SLinus Torvalds 	set_fs(oldfs);
7011da177e4SLinus Torvalds 	return result;
7021da177e4SLinus Torvalds }
703c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendmsg);
7041da177e4SLinus Torvalds 
70592f37fd2SEric Dumazet /*
70692f37fd2SEric Dumazet  * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
70792f37fd2SEric Dumazet  */
70892f37fd2SEric Dumazet void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
70992f37fd2SEric Dumazet 	struct sk_buff *skb)
71092f37fd2SEric Dumazet {
71120d49473SPatrick Ohly 	int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
712f24b9be5SWillem de Bruijn 	struct scm_timestamping tss;
71320d49473SPatrick Ohly 	int empty = 1;
71420d49473SPatrick Ohly 	struct skb_shared_hwtstamps *shhwtstamps =
71520d49473SPatrick Ohly 		skb_hwtstamps(skb);
71692f37fd2SEric Dumazet 
71720d49473SPatrick Ohly 	/* Race occurred between timestamp enabling and packet
71820d49473SPatrick Ohly 	   receiving.  Fill in the current time for now. */
71920d49473SPatrick Ohly 	if (need_software_tstamp && skb->tstamp.tv64 == 0)
72020d49473SPatrick Ohly 		__net_timestamp(skb);
72120d49473SPatrick Ohly 
72220d49473SPatrick Ohly 	if (need_software_tstamp) {
72392f37fd2SEric Dumazet 		if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
72492f37fd2SEric Dumazet 			struct timeval tv;
72520d49473SPatrick Ohly 			skb_get_timestamp(skb, &tv);
72620d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP,
72720d49473SPatrick Ohly 				 sizeof(tv), &tv);
72892f37fd2SEric Dumazet 		} else {
729f24b9be5SWillem de Bruijn 			struct timespec ts;
730f24b9be5SWillem de Bruijn 			skb_get_timestampns(skb, &ts);
73120d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS,
732f24b9be5SWillem de Bruijn 				 sizeof(ts), &ts);
73392f37fd2SEric Dumazet 		}
73492f37fd2SEric Dumazet 	}
73592f37fd2SEric Dumazet 
736f24b9be5SWillem de Bruijn 	memset(&tss, 0, sizeof(tss));
737b9f40e21SWillem de Bruijn 	if ((sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE ||
738f24b9be5SWillem de Bruijn 	     skb_shinfo(skb)->tx_flags & SKBTX_ANY_SW_TSTAMP) &&
739f24b9be5SWillem de Bruijn 	    ktime_to_timespec_cond(skb->tstamp, tss.ts + 0))
74020d49473SPatrick Ohly 		empty = 0;
7414d276eb6SWillem de Bruijn 	if (shhwtstamps &&
742b9f40e21SWillem de Bruijn 	    (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
743f24b9be5SWillem de Bruijn 	    ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2))
74420d49473SPatrick Ohly 		empty = 0;
74520d49473SPatrick Ohly 	if (!empty)
74620d49473SPatrick Ohly 		put_cmsg(msg, SOL_SOCKET,
747f24b9be5SWillem de Bruijn 			 SCM_TIMESTAMPING, sizeof(tss), &tss);
74820d49473SPatrick Ohly }
7497c81fd8bSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
7507c81fd8bSArnaldo Carvalho de Melo 
7516e3e939fSJohannes Berg void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
7526e3e939fSJohannes Berg 	struct sk_buff *skb)
7536e3e939fSJohannes Berg {
7546e3e939fSJohannes Berg 	int ack;
7556e3e939fSJohannes Berg 
7566e3e939fSJohannes Berg 	if (!sock_flag(sk, SOCK_WIFI_STATUS))
7576e3e939fSJohannes Berg 		return;
7586e3e939fSJohannes Berg 	if (!skb->wifi_acked_valid)
7596e3e939fSJohannes Berg 		return;
7606e3e939fSJohannes Berg 
7616e3e939fSJohannes Berg 	ack = skb->wifi_acked;
7626e3e939fSJohannes Berg 
7636e3e939fSJohannes Berg 	put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack);
7646e3e939fSJohannes Berg }
7656e3e939fSJohannes Berg EXPORT_SYMBOL_GPL(__sock_recv_wifi_status);
7666e3e939fSJohannes Berg 
76711165f14Sstephen hemminger static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk,
76811165f14Sstephen hemminger 				   struct sk_buff *skb)
7693b885787SNeil Horman {
7703b885787SNeil Horman 	if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && skb->dropcount)
7713b885787SNeil Horman 		put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL,
7723b885787SNeil Horman 			sizeof(__u32), &skb->dropcount);
7733b885787SNeil Horman }
7743b885787SNeil Horman 
775767dd033SEric Dumazet void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
7763b885787SNeil Horman 	struct sk_buff *skb)
7773b885787SNeil Horman {
7783b885787SNeil Horman 	sock_recv_timestamp(msg, sk, skb);
7793b885787SNeil Horman 	sock_recv_drops(msg, sk, skb);
7803b885787SNeil Horman }
781767dd033SEric Dumazet EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops);
7823b885787SNeil Horman 
783a2e27255SArnaldo Carvalho de Melo static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock,
7841da177e4SLinus Torvalds 				       struct msghdr *msg, size_t size, int flags)
7851da177e4SLinus Torvalds {
7861da177e4SLinus Torvalds 	struct sock_iocb *si = kiocb_to_siocb(iocb);
7871da177e4SLinus Torvalds 
7881da177e4SLinus Torvalds 	si->sock = sock;
7891da177e4SLinus Torvalds 	si->scm = NULL;
7901da177e4SLinus Torvalds 	si->msg = msg;
7911da177e4SLinus Torvalds 	si->size = size;
7921da177e4SLinus Torvalds 	si->flags = flags;
7931da177e4SLinus Torvalds 
7941da177e4SLinus Torvalds 	return sock->ops->recvmsg(iocb, sock, msg, size, flags);
7951da177e4SLinus Torvalds }
7961da177e4SLinus Torvalds 
797a2e27255SArnaldo Carvalho de Melo static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock,
798a2e27255SArnaldo Carvalho de Melo 				 struct msghdr *msg, size_t size, int flags)
799a2e27255SArnaldo Carvalho de Melo {
800a2e27255SArnaldo Carvalho de Melo 	int err = security_socket_recvmsg(sock, msg, size, flags);
801a2e27255SArnaldo Carvalho de Melo 
802a2e27255SArnaldo Carvalho de Melo 	return err ?: __sock_recvmsg_nosec(iocb, sock, msg, size, flags);
803a2e27255SArnaldo Carvalho de Melo }
804a2e27255SArnaldo Carvalho de Melo 
8051da177e4SLinus Torvalds int sock_recvmsg(struct socket *sock, struct msghdr *msg,
8061da177e4SLinus Torvalds 		 size_t size, int flags)
8071da177e4SLinus Torvalds {
8081da177e4SLinus Torvalds 	struct kiocb iocb;
8091da177e4SLinus Torvalds 	struct sock_iocb siocb;
8101da177e4SLinus Torvalds 	int ret;
8111da177e4SLinus Torvalds 
8121da177e4SLinus Torvalds 	init_sync_kiocb(&iocb, NULL);
8131da177e4SLinus Torvalds 	iocb.private = &siocb;
8141da177e4SLinus Torvalds 	ret = __sock_recvmsg(&iocb, sock, msg, size, flags);
8151da177e4SLinus Torvalds 	if (-EIOCBQUEUED == ret)
8161da177e4SLinus Torvalds 		ret = wait_on_sync_kiocb(&iocb);
8171da177e4SLinus Torvalds 	return ret;
8181da177e4SLinus Torvalds }
819c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_recvmsg);
8201da177e4SLinus Torvalds 
821a2e27255SArnaldo Carvalho de Melo static int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
822a2e27255SArnaldo Carvalho de Melo 			      size_t size, int flags)
823a2e27255SArnaldo Carvalho de Melo {
824a2e27255SArnaldo Carvalho de Melo 	struct kiocb iocb;
825a2e27255SArnaldo Carvalho de Melo 	struct sock_iocb siocb;
826a2e27255SArnaldo Carvalho de Melo 	int ret;
827a2e27255SArnaldo Carvalho de Melo 
828a2e27255SArnaldo Carvalho de Melo 	init_sync_kiocb(&iocb, NULL);
829a2e27255SArnaldo Carvalho de Melo 	iocb.private = &siocb;
830a2e27255SArnaldo Carvalho de Melo 	ret = __sock_recvmsg_nosec(&iocb, sock, msg, size, flags);
831a2e27255SArnaldo Carvalho de Melo 	if (-EIOCBQUEUED == ret)
832a2e27255SArnaldo Carvalho de Melo 		ret = wait_on_sync_kiocb(&iocb);
833a2e27255SArnaldo Carvalho de Melo 	return ret;
834a2e27255SArnaldo Carvalho de Melo }
835a2e27255SArnaldo Carvalho de Melo 
836c1249c0aSMartin Lucina /**
837c1249c0aSMartin Lucina  * kernel_recvmsg - Receive a message from a socket (kernel space)
838c1249c0aSMartin Lucina  * @sock:       The socket to receive the message from
839c1249c0aSMartin Lucina  * @msg:        Received message
840c1249c0aSMartin Lucina  * @vec:        Input s/g array for message data
841c1249c0aSMartin Lucina  * @num:        Size of input s/g array
842c1249c0aSMartin Lucina  * @size:       Number of bytes to read
843c1249c0aSMartin Lucina  * @flags:      Message flags (MSG_DONTWAIT, etc...)
844c1249c0aSMartin Lucina  *
845c1249c0aSMartin Lucina  * On return the msg structure contains the scatter/gather array passed in the
846c1249c0aSMartin Lucina  * vec argument. The array is modified so that it consists of the unfilled
847c1249c0aSMartin Lucina  * portion of the original array.
848c1249c0aSMartin Lucina  *
849c1249c0aSMartin Lucina  * The returned value is the total number of bytes received, or an error.
850c1249c0aSMartin Lucina  */
8511da177e4SLinus Torvalds int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
85289bddce5SStephen Hemminger 		   struct kvec *vec, size_t num, size_t size, int flags)
8531da177e4SLinus Torvalds {
8541da177e4SLinus Torvalds 	mm_segment_t oldfs = get_fs();
8551da177e4SLinus Torvalds 	int result;
8561da177e4SLinus Torvalds 
8571da177e4SLinus Torvalds 	set_fs(KERNEL_DS);
8581da177e4SLinus Torvalds 	/*
8591da177e4SLinus Torvalds 	 * the following is safe, since for compiler definitions of kvec and
8601da177e4SLinus Torvalds 	 * iovec are identical, yielding the same in-core layout and alignment
8611da177e4SLinus Torvalds 	 */
86289bddce5SStephen Hemminger 	msg->msg_iov = (struct iovec *)vec, msg->msg_iovlen = num;
8631da177e4SLinus Torvalds 	result = sock_recvmsg(sock, msg, size, flags);
8641da177e4SLinus Torvalds 	set_fs(oldfs);
8651da177e4SLinus Torvalds 	return result;
8661da177e4SLinus Torvalds }
867c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_recvmsg);
8681da177e4SLinus Torvalds 
86920380731SArnaldo Carvalho de Melo static ssize_t sock_sendpage(struct file *file, struct page *page,
8701da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more)
8711da177e4SLinus Torvalds {
8721da177e4SLinus Torvalds 	struct socket *sock;
8731da177e4SLinus Torvalds 	int flags;
8741da177e4SLinus Torvalds 
875b69aee04SEric Dumazet 	sock = file->private_data;
8761da177e4SLinus Torvalds 
87735f9c09fSEric Dumazet 	flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
87835f9c09fSEric Dumazet 	/* more is a combination of MSG_MORE and MSG_SENDPAGE_NOTLAST */
87935f9c09fSEric Dumazet 	flags |= more;
8801da177e4SLinus Torvalds 
881e6949583SLinus Torvalds 	return kernel_sendpage(sock, page, offset, size, flags);
8821da177e4SLinus Torvalds }
8831da177e4SLinus Torvalds 
8849c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
8859c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
8869c55e01cSJens Axboe 				unsigned int flags)
8879c55e01cSJens Axboe {
8889c55e01cSJens Axboe 	struct socket *sock = file->private_data;
8899c55e01cSJens Axboe 
890997b37daSRémi Denis-Courmont 	if (unlikely(!sock->ops->splice_read))
891997b37daSRémi Denis-Courmont 		return -EINVAL;
892997b37daSRémi Denis-Courmont 
8939c55e01cSJens Axboe 	return sock->ops->splice_read(sock, ppos, pipe, len, flags);
8949c55e01cSJens Axboe }
8959c55e01cSJens Axboe 
896ce1d4d3eSChristoph Hellwig static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
89789bddce5SStephen Hemminger 					 struct sock_iocb *siocb)
898ce1d4d3eSChristoph Hellwig {
899d29c445bSKent Overstreet 	if (!is_sync_kiocb(iocb))
900d29c445bSKent Overstreet 		BUG();
901ce1d4d3eSChristoph Hellwig 
902ce1d4d3eSChristoph Hellwig 	siocb->kiocb = iocb;
903ce1d4d3eSChristoph Hellwig 	iocb->private = siocb;
904ce1d4d3eSChristoph Hellwig 	return siocb;
905ce1d4d3eSChristoph Hellwig }
906ce1d4d3eSChristoph Hellwig 
907ce1d4d3eSChristoph Hellwig static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb,
908027445c3SBadari Pulavarty 		struct file *file, const struct iovec *iov,
90989bddce5SStephen Hemminger 		unsigned long nr_segs)
910ce1d4d3eSChristoph Hellwig {
911ce1d4d3eSChristoph Hellwig 	struct socket *sock = file->private_data;
912ce1d4d3eSChristoph Hellwig 	size_t size = 0;
913ce1d4d3eSChristoph Hellwig 	int i;
914ce1d4d3eSChristoph Hellwig 
915ce1d4d3eSChristoph Hellwig 	for (i = 0; i < nr_segs; i++)
916ce1d4d3eSChristoph Hellwig 		size += iov[i].iov_len;
917ce1d4d3eSChristoph Hellwig 
918ce1d4d3eSChristoph Hellwig 	msg->msg_name = NULL;
919ce1d4d3eSChristoph Hellwig 	msg->msg_namelen = 0;
920ce1d4d3eSChristoph Hellwig 	msg->msg_control = NULL;
921ce1d4d3eSChristoph Hellwig 	msg->msg_controllen = 0;
922ce1d4d3eSChristoph Hellwig 	msg->msg_iov = (struct iovec *)iov;
923ce1d4d3eSChristoph Hellwig 	msg->msg_iovlen = nr_segs;
924ce1d4d3eSChristoph Hellwig 	msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
925ce1d4d3eSChristoph Hellwig 
926ce1d4d3eSChristoph Hellwig 	return __sock_recvmsg(iocb, sock, msg, size, msg->msg_flags);
927ce1d4d3eSChristoph Hellwig }
928ce1d4d3eSChristoph Hellwig 
929027445c3SBadari Pulavarty static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
930027445c3SBadari Pulavarty 				unsigned long nr_segs, loff_t pos)
931ce1d4d3eSChristoph Hellwig {
932ce1d4d3eSChristoph Hellwig 	struct sock_iocb siocb, *x;
933ce1d4d3eSChristoph Hellwig 
934ce1d4d3eSChristoph Hellwig 	if (pos != 0)
935ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
936027445c3SBadari Pulavarty 
93773a7075eSKent Overstreet 	if (iocb->ki_nbytes == 0)	/* Match SYS5 behaviour */
938ce1d4d3eSChristoph Hellwig 		return 0;
939ce1d4d3eSChristoph Hellwig 
940027445c3SBadari Pulavarty 
941027445c3SBadari Pulavarty 	x = alloc_sock_iocb(iocb, &siocb);
942ce1d4d3eSChristoph Hellwig 	if (!x)
943ce1d4d3eSChristoph Hellwig 		return -ENOMEM;
944027445c3SBadari Pulavarty 	return do_sock_read(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
945ce1d4d3eSChristoph Hellwig }
946ce1d4d3eSChristoph Hellwig 
947ce1d4d3eSChristoph Hellwig static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb,
948027445c3SBadari Pulavarty 			struct file *file, const struct iovec *iov,
94989bddce5SStephen Hemminger 			unsigned long nr_segs)
950ce1d4d3eSChristoph Hellwig {
951ce1d4d3eSChristoph Hellwig 	struct socket *sock = file->private_data;
952ce1d4d3eSChristoph Hellwig 	size_t size = 0;
953ce1d4d3eSChristoph Hellwig 	int i;
954ce1d4d3eSChristoph Hellwig 
955ce1d4d3eSChristoph Hellwig 	for (i = 0; i < nr_segs; i++)
956ce1d4d3eSChristoph Hellwig 		size += iov[i].iov_len;
957ce1d4d3eSChristoph Hellwig 
958ce1d4d3eSChristoph Hellwig 	msg->msg_name = NULL;
959ce1d4d3eSChristoph Hellwig 	msg->msg_namelen = 0;
960ce1d4d3eSChristoph Hellwig 	msg->msg_control = NULL;
961ce1d4d3eSChristoph Hellwig 	msg->msg_controllen = 0;
962ce1d4d3eSChristoph Hellwig 	msg->msg_iov = (struct iovec *)iov;
963ce1d4d3eSChristoph Hellwig 	msg->msg_iovlen = nr_segs;
964ce1d4d3eSChristoph Hellwig 	msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
965ce1d4d3eSChristoph Hellwig 	if (sock->type == SOCK_SEQPACKET)
966ce1d4d3eSChristoph Hellwig 		msg->msg_flags |= MSG_EOR;
967ce1d4d3eSChristoph Hellwig 
968ce1d4d3eSChristoph Hellwig 	return __sock_sendmsg(iocb, sock, msg, size);
969ce1d4d3eSChristoph Hellwig }
970ce1d4d3eSChristoph Hellwig 
971027445c3SBadari Pulavarty static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
972027445c3SBadari Pulavarty 			  unsigned long nr_segs, loff_t pos)
9731da177e4SLinus Torvalds {
974ce1d4d3eSChristoph Hellwig 	struct sock_iocb siocb, *x;
9751da177e4SLinus Torvalds 
976ce1d4d3eSChristoph Hellwig 	if (pos != 0)
977ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
978027445c3SBadari Pulavarty 
979027445c3SBadari Pulavarty 	x = alloc_sock_iocb(iocb, &siocb);
980ce1d4d3eSChristoph Hellwig 	if (!x)
981ce1d4d3eSChristoph Hellwig 		return -ENOMEM;
982ce1d4d3eSChristoph Hellwig 
983027445c3SBadari Pulavarty 	return do_sock_write(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
9841da177e4SLinus Torvalds }
9851da177e4SLinus Torvalds 
9861da177e4SLinus Torvalds /*
9871da177e4SLinus Torvalds  * Atomic setting of ioctl hooks to avoid race
9881da177e4SLinus Torvalds  * with module unload.
9891da177e4SLinus Torvalds  */
9901da177e4SLinus Torvalds 
9914a3e2f71SArjan van de Ven static DEFINE_MUTEX(br_ioctl_mutex);
992c6d409cfSEric Dumazet static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg);
9931da177e4SLinus Torvalds 
994881d966bSEric W. Biederman void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *))
9951da177e4SLinus Torvalds {
9964a3e2f71SArjan van de Ven 	mutex_lock(&br_ioctl_mutex);
9971da177e4SLinus Torvalds 	br_ioctl_hook = hook;
9984a3e2f71SArjan van de Ven 	mutex_unlock(&br_ioctl_mutex);
9991da177e4SLinus Torvalds }
10001da177e4SLinus Torvalds EXPORT_SYMBOL(brioctl_set);
10011da177e4SLinus Torvalds 
10024a3e2f71SArjan van de Ven static DEFINE_MUTEX(vlan_ioctl_mutex);
1003881d966bSEric W. Biederman static int (*vlan_ioctl_hook) (struct net *, void __user *arg);
10041da177e4SLinus Torvalds 
1005881d966bSEric W. Biederman void vlan_ioctl_set(int (*hook) (struct net *, void __user *))
10061da177e4SLinus Torvalds {
10074a3e2f71SArjan van de Ven 	mutex_lock(&vlan_ioctl_mutex);
10081da177e4SLinus Torvalds 	vlan_ioctl_hook = hook;
10094a3e2f71SArjan van de Ven 	mutex_unlock(&vlan_ioctl_mutex);
10101da177e4SLinus Torvalds }
10111da177e4SLinus Torvalds EXPORT_SYMBOL(vlan_ioctl_set);
10121da177e4SLinus Torvalds 
10134a3e2f71SArjan van de Ven static DEFINE_MUTEX(dlci_ioctl_mutex);
10141da177e4SLinus Torvalds static int (*dlci_ioctl_hook) (unsigned int, void __user *);
10151da177e4SLinus Torvalds 
10161da177e4SLinus Torvalds void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
10171da177e4SLinus Torvalds {
10184a3e2f71SArjan van de Ven 	mutex_lock(&dlci_ioctl_mutex);
10191da177e4SLinus Torvalds 	dlci_ioctl_hook = hook;
10204a3e2f71SArjan van de Ven 	mutex_unlock(&dlci_ioctl_mutex);
10211da177e4SLinus Torvalds }
10221da177e4SLinus Torvalds EXPORT_SYMBOL(dlci_ioctl_set);
10231da177e4SLinus Torvalds 
10246b96018bSArnd Bergmann static long sock_do_ioctl(struct net *net, struct socket *sock,
10256b96018bSArnd Bergmann 				 unsigned int cmd, unsigned long arg)
10266b96018bSArnd Bergmann {
10276b96018bSArnd Bergmann 	int err;
10286b96018bSArnd Bergmann 	void __user *argp = (void __user *)arg;
10296b96018bSArnd Bergmann 
10306b96018bSArnd Bergmann 	err = sock->ops->ioctl(sock, cmd, arg);
10316b96018bSArnd Bergmann 
10326b96018bSArnd Bergmann 	/*
10336b96018bSArnd Bergmann 	 * If this ioctl is unknown try to hand it down
10346b96018bSArnd Bergmann 	 * to the NIC driver.
10356b96018bSArnd Bergmann 	 */
10366b96018bSArnd Bergmann 	if (err == -ENOIOCTLCMD)
10376b96018bSArnd Bergmann 		err = dev_ioctl(net, cmd, argp);
10386b96018bSArnd Bergmann 
10396b96018bSArnd Bergmann 	return err;
10406b96018bSArnd Bergmann }
10416b96018bSArnd Bergmann 
10421da177e4SLinus Torvalds /*
10431da177e4SLinus Torvalds  *	With an ioctl, arg may well be a user mode pointer, but we don't know
10441da177e4SLinus Torvalds  *	what to do with it - that's up to the protocol still.
10451da177e4SLinus Torvalds  */
10461da177e4SLinus Torvalds 
10471da177e4SLinus Torvalds static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
10481da177e4SLinus Torvalds {
10491da177e4SLinus Torvalds 	struct socket *sock;
1050881d966bSEric W. Biederman 	struct sock *sk;
10511da177e4SLinus Torvalds 	void __user *argp = (void __user *)arg;
10521da177e4SLinus Torvalds 	int pid, err;
1053881d966bSEric W. Biederman 	struct net *net;
10541da177e4SLinus Torvalds 
1055b69aee04SEric Dumazet 	sock = file->private_data;
1056881d966bSEric W. Biederman 	sk = sock->sk;
10573b1e0a65SYOSHIFUJI Hideaki 	net = sock_net(sk);
10581da177e4SLinus Torvalds 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
1059881d966bSEric W. Biederman 		err = dev_ioctl(net, cmd, argp);
10601da177e4SLinus Torvalds 	} else
10613d23e349SJohannes Berg #ifdef CONFIG_WEXT_CORE
10621da177e4SLinus Torvalds 	if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
1063881d966bSEric W. Biederman 		err = dev_ioctl(net, cmd, argp);
10641da177e4SLinus Torvalds 	} else
10653d23e349SJohannes Berg #endif
10661da177e4SLinus Torvalds 		switch (cmd) {
10671da177e4SLinus Torvalds 		case FIOSETOWN:
10681da177e4SLinus Torvalds 		case SIOCSPGRP:
10691da177e4SLinus Torvalds 			err = -EFAULT;
10701da177e4SLinus Torvalds 			if (get_user(pid, (int __user *)argp))
10711da177e4SLinus Torvalds 				break;
1072e0b93eddSJeff Layton 			f_setown(sock->file, pid, 1);
1073e0b93eddSJeff Layton 			err = 0;
10741da177e4SLinus Torvalds 			break;
10751da177e4SLinus Torvalds 		case FIOGETOWN:
10761da177e4SLinus Torvalds 		case SIOCGPGRP:
1077609d7fa9SEric W. Biederman 			err = put_user(f_getown(sock->file),
107889bddce5SStephen Hemminger 				       (int __user *)argp);
10791da177e4SLinus Torvalds 			break;
10801da177e4SLinus Torvalds 		case SIOCGIFBR:
10811da177e4SLinus Torvalds 		case SIOCSIFBR:
10821da177e4SLinus Torvalds 		case SIOCBRADDBR:
10831da177e4SLinus Torvalds 		case SIOCBRDELBR:
10841da177e4SLinus Torvalds 			err = -ENOPKG;
10851da177e4SLinus Torvalds 			if (!br_ioctl_hook)
10861da177e4SLinus Torvalds 				request_module("bridge");
10871da177e4SLinus Torvalds 
10884a3e2f71SArjan van de Ven 			mutex_lock(&br_ioctl_mutex);
10891da177e4SLinus Torvalds 			if (br_ioctl_hook)
1090881d966bSEric W. Biederman 				err = br_ioctl_hook(net, cmd, argp);
10914a3e2f71SArjan van de Ven 			mutex_unlock(&br_ioctl_mutex);
10921da177e4SLinus Torvalds 			break;
10931da177e4SLinus Torvalds 		case SIOCGIFVLAN:
10941da177e4SLinus Torvalds 		case SIOCSIFVLAN:
10951da177e4SLinus Torvalds 			err = -ENOPKG;
10961da177e4SLinus Torvalds 			if (!vlan_ioctl_hook)
10971da177e4SLinus Torvalds 				request_module("8021q");
10981da177e4SLinus Torvalds 
10994a3e2f71SArjan van de Ven 			mutex_lock(&vlan_ioctl_mutex);
11001da177e4SLinus Torvalds 			if (vlan_ioctl_hook)
1101881d966bSEric W. Biederman 				err = vlan_ioctl_hook(net, argp);
11024a3e2f71SArjan van de Ven 			mutex_unlock(&vlan_ioctl_mutex);
11031da177e4SLinus Torvalds 			break;
11041da177e4SLinus Torvalds 		case SIOCADDDLCI:
11051da177e4SLinus Torvalds 		case SIOCDELDLCI:
11061da177e4SLinus Torvalds 			err = -ENOPKG;
11071da177e4SLinus Torvalds 			if (!dlci_ioctl_hook)
11081da177e4SLinus Torvalds 				request_module("dlci");
11091da177e4SLinus Torvalds 
11104a3e2f71SArjan van de Ven 			mutex_lock(&dlci_ioctl_mutex);
11117512cbf6SPavel Emelyanov 			if (dlci_ioctl_hook)
11121da177e4SLinus Torvalds 				err = dlci_ioctl_hook(cmd, argp);
11134a3e2f71SArjan van de Ven 			mutex_unlock(&dlci_ioctl_mutex);
11141da177e4SLinus Torvalds 			break;
11151da177e4SLinus Torvalds 		default:
11166b96018bSArnd Bergmann 			err = sock_do_ioctl(net, sock, cmd, arg);
11171da177e4SLinus Torvalds 			break;
11181da177e4SLinus Torvalds 		}
11191da177e4SLinus Torvalds 	return err;
11201da177e4SLinus Torvalds }
11211da177e4SLinus Torvalds 
11221da177e4SLinus Torvalds int sock_create_lite(int family, int type, int protocol, struct socket **res)
11231da177e4SLinus Torvalds {
11241da177e4SLinus Torvalds 	int err;
11251da177e4SLinus Torvalds 	struct socket *sock = NULL;
11261da177e4SLinus Torvalds 
11271da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, 1);
11281da177e4SLinus Torvalds 	if (err)
11291da177e4SLinus Torvalds 		goto out;
11301da177e4SLinus Torvalds 
11311da177e4SLinus Torvalds 	sock = sock_alloc();
11321da177e4SLinus Torvalds 	if (!sock) {
11331da177e4SLinus Torvalds 		err = -ENOMEM;
11341da177e4SLinus Torvalds 		goto out;
11351da177e4SLinus Torvalds 	}
11361da177e4SLinus Torvalds 
11371da177e4SLinus Torvalds 	sock->type = type;
11387420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, 1);
11397420ed23SVenkat Yekkirala 	if (err)
11407420ed23SVenkat Yekkirala 		goto out_release;
11417420ed23SVenkat Yekkirala 
11421da177e4SLinus Torvalds out:
11431da177e4SLinus Torvalds 	*res = sock;
11441da177e4SLinus Torvalds 	return err;
11457420ed23SVenkat Yekkirala out_release:
11467420ed23SVenkat Yekkirala 	sock_release(sock);
11477420ed23SVenkat Yekkirala 	sock = NULL;
11487420ed23SVenkat Yekkirala 	goto out;
11491da177e4SLinus Torvalds }
1150c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_lite);
11511da177e4SLinus Torvalds 
11521da177e4SLinus Torvalds /* No kernel lock held - perfect */
11531da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file, poll_table *wait)
11541da177e4SLinus Torvalds {
1155cbf55001SEliezer Tamir 	unsigned int busy_flag = 0;
11561da177e4SLinus Torvalds 	struct socket *sock;
11571da177e4SLinus Torvalds 
11581da177e4SLinus Torvalds 	/*
11591da177e4SLinus Torvalds 	 *      We can't return errors to poll, so it's either yes or no.
11601da177e4SLinus Torvalds 	 */
1161b69aee04SEric Dumazet 	sock = file->private_data;
11622d48d67fSEliezer Tamir 
1163cbf55001SEliezer Tamir 	if (sk_can_busy_loop(sock->sk)) {
11642d48d67fSEliezer Tamir 		/* this socket can poll_ll so tell the system call */
1165cbf55001SEliezer Tamir 		busy_flag = POLL_BUSY_LOOP;
11662d48d67fSEliezer Tamir 
11672d48d67fSEliezer Tamir 		/* once, only if requested by syscall */
1168cbf55001SEliezer Tamir 		if (wait && (wait->_key & POLL_BUSY_LOOP))
1169cbf55001SEliezer Tamir 			sk_busy_loop(sock->sk, 1);
11702d48d67fSEliezer Tamir 	}
11712d48d67fSEliezer Tamir 
1172cbf55001SEliezer Tamir 	return busy_flag | sock->ops->poll(file, sock, wait);
11731da177e4SLinus Torvalds }
11741da177e4SLinus Torvalds 
11751da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma)
11761da177e4SLinus Torvalds {
1177b69aee04SEric Dumazet 	struct socket *sock = file->private_data;
11781da177e4SLinus Torvalds 
11791da177e4SLinus Torvalds 	return sock->ops->mmap(file, sock, vma);
11801da177e4SLinus Torvalds }
11811da177e4SLinus Torvalds 
118220380731SArnaldo Carvalho de Melo static int sock_close(struct inode *inode, struct file *filp)
11831da177e4SLinus Torvalds {
11841da177e4SLinus Torvalds 	sock_release(SOCKET_I(inode));
11851da177e4SLinus Torvalds 	return 0;
11861da177e4SLinus Torvalds }
11871da177e4SLinus Torvalds 
11881da177e4SLinus Torvalds /*
11891da177e4SLinus Torvalds  *	Update the socket async list
11901da177e4SLinus Torvalds  *
11911da177e4SLinus Torvalds  *	Fasync_list locking strategy.
11921da177e4SLinus Torvalds  *
11931da177e4SLinus Torvalds  *	1. fasync_list is modified only under process context socket lock
11941da177e4SLinus Torvalds  *	   i.e. under semaphore.
11951da177e4SLinus Torvalds  *	2. fasync_list is used under read_lock(&sk->sk_callback_lock)
1196989a2979SEric Dumazet  *	   or under socket lock
11971da177e4SLinus Torvalds  */
11981da177e4SLinus Torvalds 
11991da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on)
12001da177e4SLinus Torvalds {
1201989a2979SEric Dumazet 	struct socket *sock = filp->private_data;
1202989a2979SEric Dumazet 	struct sock *sk = sock->sk;
1203eaefd110SEric Dumazet 	struct socket_wq *wq;
12041da177e4SLinus Torvalds 
1205989a2979SEric Dumazet 	if (sk == NULL)
12061da177e4SLinus Torvalds 		return -EINVAL;
12071da177e4SLinus Torvalds 
12081da177e4SLinus Torvalds 	lock_sock(sk);
1209eaefd110SEric Dumazet 	wq = rcu_dereference_protected(sock->wq, sock_owned_by_user(sk));
1210eaefd110SEric Dumazet 	fasync_helper(fd, filp, on, &wq->fasync_list);
12111da177e4SLinus Torvalds 
1212eaefd110SEric Dumazet 	if (!wq->fasync_list)
1213bcdce719SEric Dumazet 		sock_reset_flag(sk, SOCK_FASYNC);
1214989a2979SEric Dumazet 	else
1215989a2979SEric Dumazet 		sock_set_flag(sk, SOCK_FASYNC);
12161da177e4SLinus Torvalds 
1217989a2979SEric Dumazet 	release_sock(sk);
12181da177e4SLinus Torvalds 	return 0;
12191da177e4SLinus Torvalds }
12201da177e4SLinus Torvalds 
122143815482SEric Dumazet /* This function may be called only under socket lock or callback_lock or rcu_lock */
12221da177e4SLinus Torvalds 
12231da177e4SLinus Torvalds int sock_wake_async(struct socket *sock, int how, int band)
12241da177e4SLinus Torvalds {
122543815482SEric Dumazet 	struct socket_wq *wq;
122643815482SEric Dumazet 
122743815482SEric Dumazet 	if (!sock)
12281da177e4SLinus Torvalds 		return -1;
122943815482SEric Dumazet 	rcu_read_lock();
123043815482SEric Dumazet 	wq = rcu_dereference(sock->wq);
123143815482SEric Dumazet 	if (!wq || !wq->fasync_list) {
123243815482SEric Dumazet 		rcu_read_unlock();
123343815482SEric Dumazet 		return -1;
123443815482SEric Dumazet 	}
123589bddce5SStephen Hemminger 	switch (how) {
12368d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_WAITD:
12371da177e4SLinus Torvalds 		if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
12381da177e4SLinus Torvalds 			break;
12391da177e4SLinus Torvalds 		goto call_kill;
12408d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_SPACE:
12411da177e4SLinus Torvalds 		if (!test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags))
12421da177e4SLinus Torvalds 			break;
12431da177e4SLinus Torvalds 		/* fall through */
12448d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_IO:
12451da177e4SLinus Torvalds call_kill:
124643815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGIO, band);
12471da177e4SLinus Torvalds 		break;
12488d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_URG:
124943815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGURG, band);
12501da177e4SLinus Torvalds 	}
125143815482SEric Dumazet 	rcu_read_unlock();
12521da177e4SLinus Torvalds 	return 0;
12531da177e4SLinus Torvalds }
1254c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_wake_async);
12551da177e4SLinus Torvalds 
1256721db93aSPavel Emelyanov int __sock_create(struct net *net, int family, int type, int protocol,
125789bddce5SStephen Hemminger 			 struct socket **res, int kern)
12581da177e4SLinus Torvalds {
12591da177e4SLinus Torvalds 	int err;
12601da177e4SLinus Torvalds 	struct socket *sock;
126155737fdaSStephen Hemminger 	const struct net_proto_family *pf;
12621da177e4SLinus Torvalds 
12631da177e4SLinus Torvalds 	/*
12641da177e4SLinus Torvalds 	 *      Check protocol is in range
12651da177e4SLinus Torvalds 	 */
12661da177e4SLinus Torvalds 	if (family < 0 || family >= NPROTO)
12671da177e4SLinus Torvalds 		return -EAFNOSUPPORT;
12681da177e4SLinus Torvalds 	if (type < 0 || type >= SOCK_MAX)
12691da177e4SLinus Torvalds 		return -EINVAL;
12701da177e4SLinus Torvalds 
12711da177e4SLinus Torvalds 	/* Compatibility.
12721da177e4SLinus Torvalds 
12731da177e4SLinus Torvalds 	   This uglymoron is moved from INET layer to here to avoid
12741da177e4SLinus Torvalds 	   deadlock in module load.
12751da177e4SLinus Torvalds 	 */
12761da177e4SLinus Torvalds 	if (family == PF_INET && type == SOCK_PACKET) {
12771da177e4SLinus Torvalds 		static int warned;
12781da177e4SLinus Torvalds 		if (!warned) {
12791da177e4SLinus Torvalds 			warned = 1;
12803410f22eSYang Yingliang 			pr_info("%s uses obsolete (PF_INET,SOCK_PACKET)\n",
128189bddce5SStephen Hemminger 				current->comm);
12821da177e4SLinus Torvalds 		}
12831da177e4SLinus Torvalds 		family = PF_PACKET;
12841da177e4SLinus Torvalds 	}
12851da177e4SLinus Torvalds 
12861da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, kern);
12871da177e4SLinus Torvalds 	if (err)
12881da177e4SLinus Torvalds 		return err;
12891da177e4SLinus Torvalds 
129055737fdaSStephen Hemminger 	/*
129155737fdaSStephen Hemminger 	 *	Allocate the socket and allow the family to set things up. if
129255737fdaSStephen Hemminger 	 *	the protocol is 0, the family is instructed to select an appropriate
129355737fdaSStephen Hemminger 	 *	default.
129455737fdaSStephen Hemminger 	 */
129555737fdaSStephen Hemminger 	sock = sock_alloc();
129655737fdaSStephen Hemminger 	if (!sock) {
1297e87cc472SJoe Perches 		net_warn_ratelimited("socket: no more sockets\n");
129855737fdaSStephen Hemminger 		return -ENFILE;	/* Not exactly a match, but its the
129955737fdaSStephen Hemminger 				   closest posix thing */
130055737fdaSStephen Hemminger 	}
130155737fdaSStephen Hemminger 
130255737fdaSStephen Hemminger 	sock->type = type;
130355737fdaSStephen Hemminger 
130495a5afcaSJohannes Berg #ifdef CONFIG_MODULES
13051da177e4SLinus Torvalds 	/* Attempt to load a protocol module if the find failed.
13061da177e4SLinus Torvalds 	 *
13071da177e4SLinus Torvalds 	 * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
13081da177e4SLinus Torvalds 	 * requested real, full-featured networking support upon configuration.
13091da177e4SLinus Torvalds 	 * Otherwise module support will break!
13101da177e4SLinus Torvalds 	 */
1311190683a9SEric Dumazet 	if (rcu_access_pointer(net_families[family]) == NULL)
13121da177e4SLinus Torvalds 		request_module("net-pf-%d", family);
13131da177e4SLinus Torvalds #endif
13141da177e4SLinus Torvalds 
131555737fdaSStephen Hemminger 	rcu_read_lock();
131655737fdaSStephen Hemminger 	pf = rcu_dereference(net_families[family]);
13171da177e4SLinus Torvalds 	err = -EAFNOSUPPORT;
131855737fdaSStephen Hemminger 	if (!pf)
131955737fdaSStephen Hemminger 		goto out_release;
13201da177e4SLinus Torvalds 
13211da177e4SLinus Torvalds 	/*
13221da177e4SLinus Torvalds 	 * We will call the ->create function, that possibly is in a loadable
13231da177e4SLinus Torvalds 	 * module, so we have to bump that loadable module refcnt first.
13241da177e4SLinus Torvalds 	 */
132555737fdaSStephen Hemminger 	if (!try_module_get(pf->owner))
13261da177e4SLinus Torvalds 		goto out_release;
13271da177e4SLinus Torvalds 
132855737fdaSStephen Hemminger 	/* Now protected by module ref count */
132955737fdaSStephen Hemminger 	rcu_read_unlock();
133055737fdaSStephen Hemminger 
13313f378b68SEric Paris 	err = pf->create(net, sock, protocol, kern);
133255737fdaSStephen Hemminger 	if (err < 0)
13331da177e4SLinus Torvalds 		goto out_module_put;
1334a79af59eSFrank Filz 
13351da177e4SLinus Torvalds 	/*
13361da177e4SLinus Torvalds 	 * Now to bump the refcnt of the [loadable] module that owns this
13371da177e4SLinus Torvalds 	 * socket at sock_release time we decrement its refcnt.
13381da177e4SLinus Torvalds 	 */
133955737fdaSStephen Hemminger 	if (!try_module_get(sock->ops->owner))
134055737fdaSStephen Hemminger 		goto out_module_busy;
134155737fdaSStephen Hemminger 
13421da177e4SLinus Torvalds 	/*
13431da177e4SLinus Torvalds 	 * Now that we're done with the ->create function, the [loadable]
13441da177e4SLinus Torvalds 	 * module can have its refcnt decremented
13451da177e4SLinus Torvalds 	 */
134655737fdaSStephen Hemminger 	module_put(pf->owner);
13477420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, kern);
13487420ed23SVenkat Yekkirala 	if (err)
13493b185525SHerbert Xu 		goto out_sock_release;
135055737fdaSStephen Hemminger 	*res = sock;
13511da177e4SLinus Torvalds 
135255737fdaSStephen Hemminger 	return 0;
135355737fdaSStephen Hemminger 
135455737fdaSStephen Hemminger out_module_busy:
135555737fdaSStephen Hemminger 	err = -EAFNOSUPPORT;
13561da177e4SLinus Torvalds out_module_put:
135755737fdaSStephen Hemminger 	sock->ops = NULL;
135855737fdaSStephen Hemminger 	module_put(pf->owner);
135955737fdaSStephen Hemminger out_sock_release:
13601da177e4SLinus Torvalds 	sock_release(sock);
136155737fdaSStephen Hemminger 	return err;
136255737fdaSStephen Hemminger 
136355737fdaSStephen Hemminger out_release:
136455737fdaSStephen Hemminger 	rcu_read_unlock();
136555737fdaSStephen Hemminger 	goto out_sock_release;
13661da177e4SLinus Torvalds }
1367721db93aSPavel Emelyanov EXPORT_SYMBOL(__sock_create);
13681da177e4SLinus Torvalds 
13691da177e4SLinus Torvalds int sock_create(int family, int type, int protocol, struct socket **res)
13701da177e4SLinus Torvalds {
13711b8d7ae4SEric W. Biederman 	return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
13721da177e4SLinus Torvalds }
1373c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create);
13741da177e4SLinus Torvalds 
13751da177e4SLinus Torvalds int sock_create_kern(int family, int type, int protocol, struct socket **res)
13761da177e4SLinus Torvalds {
13771b8d7ae4SEric W. Biederman 	return __sock_create(&init_net, family, type, protocol, res, 1);
13781da177e4SLinus Torvalds }
1379c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_kern);
13801da177e4SLinus Torvalds 
13813e0fa65fSHeiko Carstens SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
13821da177e4SLinus Torvalds {
13831da177e4SLinus Torvalds 	int retval;
13841da177e4SLinus Torvalds 	struct socket *sock;
1385a677a039SUlrich Drepper 	int flags;
1386a677a039SUlrich Drepper 
1387e38b36f3SUlrich Drepper 	/* Check the SOCK_* constants for consistency.  */
1388e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
1389e38b36f3SUlrich Drepper 	BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
1390e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);
1391e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);
1392e38b36f3SUlrich Drepper 
1393a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
139477d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1395a677a039SUlrich Drepper 		return -EINVAL;
1396a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
13971da177e4SLinus Torvalds 
1398aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1399aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1400aaca0bdcSUlrich Drepper 
14011da177e4SLinus Torvalds 	retval = sock_create(family, type, protocol, &sock);
14021da177e4SLinus Torvalds 	if (retval < 0)
14031da177e4SLinus Torvalds 		goto out;
14041da177e4SLinus Torvalds 
140577d27200SUlrich Drepper 	retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
14061da177e4SLinus Torvalds 	if (retval < 0)
14071da177e4SLinus Torvalds 		goto out_release;
14081da177e4SLinus Torvalds 
14091da177e4SLinus Torvalds out:
14101da177e4SLinus Torvalds 	/* It may be already another descriptor 8) Not kernel problem. */
14111da177e4SLinus Torvalds 	return retval;
14121da177e4SLinus Torvalds 
14131da177e4SLinus Torvalds out_release:
14141da177e4SLinus Torvalds 	sock_release(sock);
14151da177e4SLinus Torvalds 	return retval;
14161da177e4SLinus Torvalds }
14171da177e4SLinus Torvalds 
14181da177e4SLinus Torvalds /*
14191da177e4SLinus Torvalds  *	Create a pair of connected sockets.
14201da177e4SLinus Torvalds  */
14211da177e4SLinus Torvalds 
14223e0fa65fSHeiko Carstens SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
14233e0fa65fSHeiko Carstens 		int __user *, usockvec)
14241da177e4SLinus Torvalds {
14251da177e4SLinus Torvalds 	struct socket *sock1, *sock2;
14261da177e4SLinus Torvalds 	int fd1, fd2, err;
1427db349509SAl Viro 	struct file *newfile1, *newfile2;
1428a677a039SUlrich Drepper 	int flags;
1429a677a039SUlrich Drepper 
1430a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
143177d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1432a677a039SUlrich Drepper 		return -EINVAL;
1433a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
14341da177e4SLinus Torvalds 
1435aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1436aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1437aaca0bdcSUlrich Drepper 
14381da177e4SLinus Torvalds 	/*
14391da177e4SLinus Torvalds 	 * Obtain the first socket and check if the underlying protocol
14401da177e4SLinus Torvalds 	 * supports the socketpair call.
14411da177e4SLinus Torvalds 	 */
14421da177e4SLinus Torvalds 
14431da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock1);
14441da177e4SLinus Torvalds 	if (err < 0)
14451da177e4SLinus Torvalds 		goto out;
14461da177e4SLinus Torvalds 
14471da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock2);
14481da177e4SLinus Torvalds 	if (err < 0)
14491da177e4SLinus Torvalds 		goto out_release_1;
14501da177e4SLinus Torvalds 
14511da177e4SLinus Torvalds 	err = sock1->ops->socketpair(sock1, sock2);
14521da177e4SLinus Torvalds 	if (err < 0)
14531da177e4SLinus Torvalds 		goto out_release_both;
14541da177e4SLinus Torvalds 
145528407630SAl Viro 	fd1 = get_unused_fd_flags(flags);
1456bf3c23d1SDavid S. Miller 	if (unlikely(fd1 < 0)) {
1457bf3c23d1SDavid S. Miller 		err = fd1;
14581da177e4SLinus Torvalds 		goto out_release_both;
1459bf3c23d1SDavid S. Miller 	}
1460d73aa286SYann Droneaud 
146128407630SAl Viro 	fd2 = get_unused_fd_flags(flags);
1462198de4d7SAl Viro 	if (unlikely(fd2 < 0)) {
1463198de4d7SAl Viro 		err = fd2;
1464d73aa286SYann Droneaud 		goto out_put_unused_1;
146528407630SAl Viro 	}
146628407630SAl Viro 
1467aab174f0SLinus Torvalds 	newfile1 = sock_alloc_file(sock1, flags, NULL);
146828407630SAl Viro 	if (unlikely(IS_ERR(newfile1))) {
146928407630SAl Viro 		err = PTR_ERR(newfile1);
1470d73aa286SYann Droneaud 		goto out_put_unused_both;
147128407630SAl Viro 	}
147228407630SAl Viro 
1473aab174f0SLinus Torvalds 	newfile2 = sock_alloc_file(sock2, flags, NULL);
147428407630SAl Viro 	if (IS_ERR(newfile2)) {
147528407630SAl Viro 		err = PTR_ERR(newfile2);
1476d73aa286SYann Droneaud 		goto out_fput_1;
1477db349509SAl Viro 	}
1478db349509SAl Viro 
1479d73aa286SYann Droneaud 	err = put_user(fd1, &usockvec[0]);
1480d73aa286SYann Droneaud 	if (err)
1481d73aa286SYann Droneaud 		goto out_fput_both;
1482d73aa286SYann Droneaud 
1483d73aa286SYann Droneaud 	err = put_user(fd2, &usockvec[1]);
1484d73aa286SYann Droneaud 	if (err)
1485d73aa286SYann Droneaud 		goto out_fput_both;
1486d73aa286SYann Droneaud 
1487157cf649SAl Viro 	audit_fd_pair(fd1, fd2);
1488d73aa286SYann Droneaud 
1489db349509SAl Viro 	fd_install(fd1, newfile1);
1490db349509SAl Viro 	fd_install(fd2, newfile2);
14911da177e4SLinus Torvalds 	/* fd1 and fd2 may be already another descriptors.
14921da177e4SLinus Torvalds 	 * Not kernel problem.
14931da177e4SLinus Torvalds 	 */
14941da177e4SLinus Torvalds 
14951da177e4SLinus Torvalds 	return 0;
14961da177e4SLinus Torvalds 
1497d73aa286SYann Droneaud out_fput_both:
1498d73aa286SYann Droneaud 	fput(newfile2);
1499d73aa286SYann Droneaud 	fput(newfile1);
1500d73aa286SYann Droneaud 	put_unused_fd(fd2);
1501d73aa286SYann Droneaud 	put_unused_fd(fd1);
1502d73aa286SYann Droneaud 	goto out;
15031da177e4SLinus Torvalds 
1504d73aa286SYann Droneaud out_fput_1:
1505d73aa286SYann Droneaud 	fput(newfile1);
1506d73aa286SYann Droneaud 	put_unused_fd(fd2);
1507d73aa286SYann Droneaud 	put_unused_fd(fd1);
1508d73aa286SYann Droneaud 	sock_release(sock2);
1509d73aa286SYann Droneaud 	goto out;
1510d73aa286SYann Droneaud 
1511d73aa286SYann Droneaud out_put_unused_both:
1512d73aa286SYann Droneaud 	put_unused_fd(fd2);
1513d73aa286SYann Droneaud out_put_unused_1:
1514d73aa286SYann Droneaud 	put_unused_fd(fd1);
15151da177e4SLinus Torvalds out_release_both:
15161da177e4SLinus Torvalds 	sock_release(sock2);
15171da177e4SLinus Torvalds out_release_1:
15181da177e4SLinus Torvalds 	sock_release(sock1);
15191da177e4SLinus Torvalds out:
15201da177e4SLinus Torvalds 	return err;
15211da177e4SLinus Torvalds }
15221da177e4SLinus Torvalds 
15231da177e4SLinus Torvalds /*
15241da177e4SLinus Torvalds  *	Bind a name to a socket. Nothing much to do here since it's
15251da177e4SLinus Torvalds  *	the protocol's responsibility to handle the local address.
15261da177e4SLinus Torvalds  *
15271da177e4SLinus Torvalds  *	We move the socket address to kernel space before we call
15281da177e4SLinus Torvalds  *	the protocol layer (having also checked the address is ok).
15291da177e4SLinus Torvalds  */
15301da177e4SLinus Torvalds 
153120f37034SHeiko Carstens SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
15321da177e4SLinus Torvalds {
15331da177e4SLinus Torvalds 	struct socket *sock;
1534230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
15356cb153caSBenjamin LaHaise 	int err, fput_needed;
15361da177e4SLinus Torvalds 
153789bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
153889bddce5SStephen Hemminger 	if (sock) {
153943db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(umyaddr, addrlen, &address);
154089bddce5SStephen Hemminger 		if (err >= 0) {
154189bddce5SStephen Hemminger 			err = security_socket_bind(sock,
1542230b1839SYOSHIFUJI Hideaki 						   (struct sockaddr *)&address,
154389bddce5SStephen Hemminger 						   addrlen);
15446cb153caSBenjamin LaHaise 			if (!err)
15456cb153caSBenjamin LaHaise 				err = sock->ops->bind(sock,
154689bddce5SStephen Hemminger 						      (struct sockaddr *)
1547230b1839SYOSHIFUJI Hideaki 						      &address, addrlen);
15481da177e4SLinus Torvalds 		}
15496cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
15501da177e4SLinus Torvalds 	}
15511da177e4SLinus Torvalds 	return err;
15521da177e4SLinus Torvalds }
15531da177e4SLinus Torvalds 
15541da177e4SLinus Torvalds /*
15551da177e4SLinus Torvalds  *	Perform a listen. Basically, we allow the protocol to do anything
15561da177e4SLinus Torvalds  *	necessary for a listen, and if that works, we mark the socket as
15571da177e4SLinus Torvalds  *	ready for listening.
15581da177e4SLinus Torvalds  */
15591da177e4SLinus Torvalds 
15603e0fa65fSHeiko Carstens SYSCALL_DEFINE2(listen, int, fd, int, backlog)
15611da177e4SLinus Torvalds {
15621da177e4SLinus Torvalds 	struct socket *sock;
15636cb153caSBenjamin LaHaise 	int err, fput_needed;
1564b8e1f9b5SPavel Emelyanov 	int somaxconn;
15651da177e4SLinus Torvalds 
156689bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
156789bddce5SStephen Hemminger 	if (sock) {
15688efa6e93SPavel Emelyanov 		somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
156995c96174SEric Dumazet 		if ((unsigned int)backlog > somaxconn)
1570b8e1f9b5SPavel Emelyanov 			backlog = somaxconn;
15711da177e4SLinus Torvalds 
15721da177e4SLinus Torvalds 		err = security_socket_listen(sock, backlog);
15736cb153caSBenjamin LaHaise 		if (!err)
15741da177e4SLinus Torvalds 			err = sock->ops->listen(sock, backlog);
15756cb153caSBenjamin LaHaise 
15766cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
15771da177e4SLinus Torvalds 	}
15781da177e4SLinus Torvalds 	return err;
15791da177e4SLinus Torvalds }
15801da177e4SLinus Torvalds 
15811da177e4SLinus Torvalds /*
15821da177e4SLinus Torvalds  *	For accept, we attempt to create a new socket, set up the link
15831da177e4SLinus Torvalds  *	with the client, wake up the client, then return the new
15841da177e4SLinus Torvalds  *	connected fd. We collect the address of the connector in kernel
15851da177e4SLinus Torvalds  *	space and move it to user at the very end. This is unclean because
15861da177e4SLinus Torvalds  *	we open the socket then return an error.
15871da177e4SLinus Torvalds  *
15881da177e4SLinus Torvalds  *	1003.1g adds the ability to recvmsg() to query connection pending
15891da177e4SLinus Torvalds  *	status to recvmsg. We need to add that support in a way thats
15901da177e4SLinus Torvalds  *	clean when we restucture accept also.
15911da177e4SLinus Torvalds  */
15921da177e4SLinus Torvalds 
159320f37034SHeiko Carstens SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
159420f37034SHeiko Carstens 		int __user *, upeer_addrlen, int, flags)
15951da177e4SLinus Torvalds {
15961da177e4SLinus Torvalds 	struct socket *sock, *newsock;
159739d8c1b6SDavid S. Miller 	struct file *newfile;
15986cb153caSBenjamin LaHaise 	int err, len, newfd, fput_needed;
1599230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16001da177e4SLinus Torvalds 
160177d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1602aaca0bdcSUlrich Drepper 		return -EINVAL;
1603aaca0bdcSUlrich Drepper 
1604aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1605aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1606aaca0bdcSUlrich Drepper 
16076cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
16081da177e4SLinus Torvalds 	if (!sock)
16091da177e4SLinus Torvalds 		goto out;
16101da177e4SLinus Torvalds 
16111da177e4SLinus Torvalds 	err = -ENFILE;
1612c6d409cfSEric Dumazet 	newsock = sock_alloc();
1613c6d409cfSEric Dumazet 	if (!newsock)
16141da177e4SLinus Torvalds 		goto out_put;
16151da177e4SLinus Torvalds 
16161da177e4SLinus Torvalds 	newsock->type = sock->type;
16171da177e4SLinus Torvalds 	newsock->ops = sock->ops;
16181da177e4SLinus Torvalds 
16191da177e4SLinus Torvalds 	/*
16201da177e4SLinus Torvalds 	 * We don't need try_module_get here, as the listening socket (sock)
16211da177e4SLinus Torvalds 	 * has the protocol module (sock->ops->owner) held.
16221da177e4SLinus Torvalds 	 */
16231da177e4SLinus Torvalds 	__module_get(newsock->ops->owner);
16241da177e4SLinus Torvalds 
162528407630SAl Viro 	newfd = get_unused_fd_flags(flags);
162639d8c1b6SDavid S. Miller 	if (unlikely(newfd < 0)) {
162739d8c1b6SDavid S. Miller 		err = newfd;
16289a1875e6SDavid S. Miller 		sock_release(newsock);
16299a1875e6SDavid S. Miller 		goto out_put;
163039d8c1b6SDavid S. Miller 	}
1631aab174f0SLinus Torvalds 	newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name);
163228407630SAl Viro 	if (unlikely(IS_ERR(newfile))) {
163328407630SAl Viro 		err = PTR_ERR(newfile);
163428407630SAl Viro 		put_unused_fd(newfd);
163528407630SAl Viro 		sock_release(newsock);
163628407630SAl Viro 		goto out_put;
163728407630SAl Viro 	}
163839d8c1b6SDavid S. Miller 
1639a79af59eSFrank Filz 	err = security_socket_accept(sock, newsock);
1640a79af59eSFrank Filz 	if (err)
164139d8c1b6SDavid S. Miller 		goto out_fd;
1642a79af59eSFrank Filz 
16431da177e4SLinus Torvalds 	err = sock->ops->accept(sock, newsock, sock->file->f_flags);
16441da177e4SLinus Torvalds 	if (err < 0)
164539d8c1b6SDavid S. Miller 		goto out_fd;
16461da177e4SLinus Torvalds 
16471da177e4SLinus Torvalds 	if (upeer_sockaddr) {
1648230b1839SYOSHIFUJI Hideaki 		if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
164989bddce5SStephen Hemminger 					  &len, 2) < 0) {
16501da177e4SLinus Torvalds 			err = -ECONNABORTED;
165139d8c1b6SDavid S. Miller 			goto out_fd;
16521da177e4SLinus Torvalds 		}
165343db362dSMaciej Żenczykowski 		err = move_addr_to_user(&address,
1654230b1839SYOSHIFUJI Hideaki 					len, upeer_sockaddr, upeer_addrlen);
16551da177e4SLinus Torvalds 		if (err < 0)
165639d8c1b6SDavid S. Miller 			goto out_fd;
16571da177e4SLinus Torvalds 	}
16581da177e4SLinus Torvalds 
16591da177e4SLinus Torvalds 	/* File flags are not inherited via accept() unlike another OSes. */
16601da177e4SLinus Torvalds 
166139d8c1b6SDavid S. Miller 	fd_install(newfd, newfile);
166239d8c1b6SDavid S. Miller 	err = newfd;
16631da177e4SLinus Torvalds 
16641da177e4SLinus Torvalds out_put:
16656cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
16661da177e4SLinus Torvalds out:
16671da177e4SLinus Torvalds 	return err;
166839d8c1b6SDavid S. Miller out_fd:
16699606a216SDavid S. Miller 	fput(newfile);
167039d8c1b6SDavid S. Miller 	put_unused_fd(newfd);
16711da177e4SLinus Torvalds 	goto out_put;
16721da177e4SLinus Torvalds }
16731da177e4SLinus Torvalds 
167420f37034SHeiko Carstens SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,
167520f37034SHeiko Carstens 		int __user *, upeer_addrlen)
1676aaca0bdcSUlrich Drepper {
1677de11defeSUlrich Drepper 	return sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0);
1678aaca0bdcSUlrich Drepper }
1679aaca0bdcSUlrich Drepper 
16801da177e4SLinus Torvalds /*
16811da177e4SLinus Torvalds  *	Attempt to connect to a socket with the server address.  The address
16821da177e4SLinus Torvalds  *	is in user space so we verify it is OK and move it to kernel space.
16831da177e4SLinus Torvalds  *
16841da177e4SLinus Torvalds  *	For 1003.1g we need to add clean support for a bind to AF_UNSPEC to
16851da177e4SLinus Torvalds  *	break bindings
16861da177e4SLinus Torvalds  *
16871da177e4SLinus Torvalds  *	NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and
16881da177e4SLinus Torvalds  *	other SEQPACKET protocols that take time to connect() as it doesn't
16891da177e4SLinus Torvalds  *	include the -EINPROGRESS status for such sockets.
16901da177e4SLinus Torvalds  */
16911da177e4SLinus Torvalds 
169220f37034SHeiko Carstens SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
169320f37034SHeiko Carstens 		int, addrlen)
16941da177e4SLinus Torvalds {
16951da177e4SLinus Torvalds 	struct socket *sock;
1696230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16976cb153caSBenjamin LaHaise 	int err, fput_needed;
16981da177e4SLinus Torvalds 
16996cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
17001da177e4SLinus Torvalds 	if (!sock)
17011da177e4SLinus Torvalds 		goto out;
170243db362dSMaciej Żenczykowski 	err = move_addr_to_kernel(uservaddr, addrlen, &address);
17031da177e4SLinus Torvalds 	if (err < 0)
17041da177e4SLinus Torvalds 		goto out_put;
17051da177e4SLinus Torvalds 
170689bddce5SStephen Hemminger 	err =
1707230b1839SYOSHIFUJI Hideaki 	    security_socket_connect(sock, (struct sockaddr *)&address, addrlen);
17081da177e4SLinus Torvalds 	if (err)
17091da177e4SLinus Torvalds 		goto out_put;
17101da177e4SLinus Torvalds 
1711230b1839SYOSHIFUJI Hideaki 	err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,
17121da177e4SLinus Torvalds 				 sock->file->f_flags);
17131da177e4SLinus Torvalds out_put:
17146cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
17151da177e4SLinus Torvalds out:
17161da177e4SLinus Torvalds 	return err;
17171da177e4SLinus Torvalds }
17181da177e4SLinus Torvalds 
17191da177e4SLinus Torvalds /*
17201da177e4SLinus Torvalds  *	Get the local address ('name') of a socket object. Move the obtained
17211da177e4SLinus Torvalds  *	name to user space.
17221da177e4SLinus Torvalds  */
17231da177e4SLinus Torvalds 
172420f37034SHeiko Carstens SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
172520f37034SHeiko Carstens 		int __user *, usockaddr_len)
17261da177e4SLinus Torvalds {
17271da177e4SLinus Torvalds 	struct socket *sock;
1728230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
17296cb153caSBenjamin LaHaise 	int len, err, fput_needed;
17301da177e4SLinus Torvalds 
17316cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
17321da177e4SLinus Torvalds 	if (!sock)
17331da177e4SLinus Torvalds 		goto out;
17341da177e4SLinus Torvalds 
17351da177e4SLinus Torvalds 	err = security_socket_getsockname(sock);
17361da177e4SLinus Torvalds 	if (err)
17371da177e4SLinus Torvalds 		goto out_put;
17381da177e4SLinus Torvalds 
1739230b1839SYOSHIFUJI Hideaki 	err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0);
17401da177e4SLinus Torvalds 	if (err)
17411da177e4SLinus Torvalds 		goto out_put;
174243db362dSMaciej Żenczykowski 	err = move_addr_to_user(&address, len, usockaddr, usockaddr_len);
17431da177e4SLinus Torvalds 
17441da177e4SLinus Torvalds out_put:
17456cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
17461da177e4SLinus Torvalds out:
17471da177e4SLinus Torvalds 	return err;
17481da177e4SLinus Torvalds }
17491da177e4SLinus Torvalds 
17501da177e4SLinus Torvalds /*
17511da177e4SLinus Torvalds  *	Get the remote address ('name') of a socket object. Move the obtained
17521da177e4SLinus Torvalds  *	name to user space.
17531da177e4SLinus Torvalds  */
17541da177e4SLinus Torvalds 
175520f37034SHeiko Carstens SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
175620f37034SHeiko Carstens 		int __user *, usockaddr_len)
17571da177e4SLinus Torvalds {
17581da177e4SLinus Torvalds 	struct socket *sock;
1759230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
17606cb153caSBenjamin LaHaise 	int len, err, fput_needed;
17611da177e4SLinus Torvalds 
176289bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
176389bddce5SStephen Hemminger 	if (sock != NULL) {
17641da177e4SLinus Torvalds 		err = security_socket_getpeername(sock);
17651da177e4SLinus Torvalds 		if (err) {
17666cb153caSBenjamin LaHaise 			fput_light(sock->file, fput_needed);
17671da177e4SLinus Torvalds 			return err;
17681da177e4SLinus Torvalds 		}
17691da177e4SLinus Torvalds 
177089bddce5SStephen Hemminger 		err =
1771230b1839SYOSHIFUJI Hideaki 		    sock->ops->getname(sock, (struct sockaddr *)&address, &len,
177289bddce5SStephen Hemminger 				       1);
17731da177e4SLinus Torvalds 		if (!err)
177443db362dSMaciej Żenczykowski 			err = move_addr_to_user(&address, len, usockaddr,
177589bddce5SStephen Hemminger 						usockaddr_len);
17766cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
17771da177e4SLinus Torvalds 	}
17781da177e4SLinus Torvalds 	return err;
17791da177e4SLinus Torvalds }
17801da177e4SLinus Torvalds 
17811da177e4SLinus Torvalds /*
17821da177e4SLinus Torvalds  *	Send a datagram to a given address. We move the address into kernel
17831da177e4SLinus Torvalds  *	space and check the user space data area is readable before invoking
17841da177e4SLinus Torvalds  *	the protocol.
17851da177e4SLinus Torvalds  */
17861da177e4SLinus Torvalds 
17873e0fa65fSHeiko Carstens SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
178895c96174SEric Dumazet 		unsigned int, flags, struct sockaddr __user *, addr,
17893e0fa65fSHeiko Carstens 		int, addr_len)
17901da177e4SLinus Torvalds {
17911da177e4SLinus Torvalds 	struct socket *sock;
1792230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
17931da177e4SLinus Torvalds 	int err;
17941da177e4SLinus Torvalds 	struct msghdr msg;
17951da177e4SLinus Torvalds 	struct iovec iov;
17966cb153caSBenjamin LaHaise 	int fput_needed;
17971da177e4SLinus Torvalds 
1798253eacc0SLinus Torvalds 	if (len > INT_MAX)
1799253eacc0SLinus Torvalds 		len = INT_MAX;
1800de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1801de0fa95cSPavel Emelyanov 	if (!sock)
18024387ff75SDavid S. Miller 		goto out;
18036cb153caSBenjamin LaHaise 
18041da177e4SLinus Torvalds 	iov.iov_base = buff;
18051da177e4SLinus Torvalds 	iov.iov_len = len;
18061da177e4SLinus Torvalds 	msg.msg_name = NULL;
18071da177e4SLinus Torvalds 	msg.msg_iov = &iov;
18081da177e4SLinus Torvalds 	msg.msg_iovlen = 1;
18091da177e4SLinus Torvalds 	msg.msg_control = NULL;
18101da177e4SLinus Torvalds 	msg.msg_controllen = 0;
18111da177e4SLinus Torvalds 	msg.msg_namelen = 0;
18126cb153caSBenjamin LaHaise 	if (addr) {
181343db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(addr, addr_len, &address);
18141da177e4SLinus Torvalds 		if (err < 0)
18151da177e4SLinus Torvalds 			goto out_put;
1816230b1839SYOSHIFUJI Hideaki 		msg.msg_name = (struct sockaddr *)&address;
18171da177e4SLinus Torvalds 		msg.msg_namelen = addr_len;
18181da177e4SLinus Torvalds 	}
18191da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
18201da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
18211da177e4SLinus Torvalds 	msg.msg_flags = flags;
18221da177e4SLinus Torvalds 	err = sock_sendmsg(sock, &msg, len);
18231da177e4SLinus Torvalds 
18241da177e4SLinus Torvalds out_put:
1825de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
18264387ff75SDavid S. Miller out:
18271da177e4SLinus Torvalds 	return err;
18281da177e4SLinus Torvalds }
18291da177e4SLinus Torvalds 
18301da177e4SLinus Torvalds /*
18311da177e4SLinus Torvalds  *	Send a datagram down a socket.
18321da177e4SLinus Torvalds  */
18331da177e4SLinus Torvalds 
18343e0fa65fSHeiko Carstens SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len,
183595c96174SEric Dumazet 		unsigned int, flags)
18361da177e4SLinus Torvalds {
18371da177e4SLinus Torvalds 	return sys_sendto(fd, buff, len, flags, NULL, 0);
18381da177e4SLinus Torvalds }
18391da177e4SLinus Torvalds 
18401da177e4SLinus Torvalds /*
18411da177e4SLinus Torvalds  *	Receive a frame from the socket and optionally record the address of the
18421da177e4SLinus Torvalds  *	sender. We verify the buffers are writable and if needed move the
18431da177e4SLinus Torvalds  *	sender address from kernel to user space.
18441da177e4SLinus Torvalds  */
18451da177e4SLinus Torvalds 
18463e0fa65fSHeiko Carstens SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
184795c96174SEric Dumazet 		unsigned int, flags, struct sockaddr __user *, addr,
18483e0fa65fSHeiko Carstens 		int __user *, addr_len)
18491da177e4SLinus Torvalds {
18501da177e4SLinus Torvalds 	struct socket *sock;
18511da177e4SLinus Torvalds 	struct iovec iov;
18521da177e4SLinus Torvalds 	struct msghdr msg;
1853230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
18541da177e4SLinus Torvalds 	int err, err2;
18556cb153caSBenjamin LaHaise 	int fput_needed;
18561da177e4SLinus Torvalds 
1857253eacc0SLinus Torvalds 	if (size > INT_MAX)
1858253eacc0SLinus Torvalds 		size = INT_MAX;
1859de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
18601da177e4SLinus Torvalds 	if (!sock)
1861de0fa95cSPavel Emelyanov 		goto out;
18621da177e4SLinus Torvalds 
18631da177e4SLinus Torvalds 	msg.msg_control = NULL;
18641da177e4SLinus Torvalds 	msg.msg_controllen = 0;
18651da177e4SLinus Torvalds 	msg.msg_iovlen = 1;
18661da177e4SLinus Torvalds 	msg.msg_iov = &iov;
18671da177e4SLinus Torvalds 	iov.iov_len = size;
18681da177e4SLinus Torvalds 	iov.iov_base = ubuf;
1869f3d33426SHannes Frederic Sowa 	/* Save some cycles and don't copy the address if not needed */
1870f3d33426SHannes Frederic Sowa 	msg.msg_name = addr ? (struct sockaddr *)&address : NULL;
1871f3d33426SHannes Frederic Sowa 	/* We assume all kernel code knows the size of sockaddr_storage */
1872f3d33426SHannes Frederic Sowa 	msg.msg_namelen = 0;
18731da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
18741da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
18751da177e4SLinus Torvalds 	err = sock_recvmsg(sock, &msg, size, flags);
18761da177e4SLinus Torvalds 
187789bddce5SStephen Hemminger 	if (err >= 0 && addr != NULL) {
187843db362dSMaciej Żenczykowski 		err2 = move_addr_to_user(&address,
1879230b1839SYOSHIFUJI Hideaki 					 msg.msg_namelen, addr, addr_len);
18801da177e4SLinus Torvalds 		if (err2 < 0)
18811da177e4SLinus Torvalds 			err = err2;
18821da177e4SLinus Torvalds 	}
1883de0fa95cSPavel Emelyanov 
1884de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
18854387ff75SDavid S. Miller out:
18861da177e4SLinus Torvalds 	return err;
18871da177e4SLinus Torvalds }
18881da177e4SLinus Torvalds 
18891da177e4SLinus Torvalds /*
18901da177e4SLinus Torvalds  *	Receive a datagram from a socket.
18911da177e4SLinus Torvalds  */
18921da177e4SLinus Torvalds 
1893b7c0ddf5SJan Glauber SYSCALL_DEFINE4(recv, int, fd, void __user *, ubuf, size_t, size,
1894b7c0ddf5SJan Glauber 		unsigned int, flags)
18951da177e4SLinus Torvalds {
18961da177e4SLinus Torvalds 	return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL);
18971da177e4SLinus Torvalds }
18981da177e4SLinus Torvalds 
18991da177e4SLinus Torvalds /*
19001da177e4SLinus Torvalds  *	Set a socket option. Because we don't know the option lengths we have
19011da177e4SLinus Torvalds  *	to pass the user mode parameter for the protocols to sort out.
19021da177e4SLinus Torvalds  */
19031da177e4SLinus Torvalds 
190420f37034SHeiko Carstens SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
190520f37034SHeiko Carstens 		char __user *, optval, int, optlen)
19061da177e4SLinus Torvalds {
19076cb153caSBenjamin LaHaise 	int err, fput_needed;
19081da177e4SLinus Torvalds 	struct socket *sock;
19091da177e4SLinus Torvalds 
19101da177e4SLinus Torvalds 	if (optlen < 0)
19111da177e4SLinus Torvalds 		return -EINVAL;
19121da177e4SLinus Torvalds 
191389bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
191489bddce5SStephen Hemminger 	if (sock != NULL) {
19151da177e4SLinus Torvalds 		err = security_socket_setsockopt(sock, level, optname);
19166cb153caSBenjamin LaHaise 		if (err)
19176cb153caSBenjamin LaHaise 			goto out_put;
19181da177e4SLinus Torvalds 
19191da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
192089bddce5SStephen Hemminger 			err =
192189bddce5SStephen Hemminger 			    sock_setsockopt(sock, level, optname, optval,
192289bddce5SStephen Hemminger 					    optlen);
19231da177e4SLinus Torvalds 		else
192489bddce5SStephen Hemminger 			err =
192589bddce5SStephen Hemminger 			    sock->ops->setsockopt(sock, level, optname, optval,
192689bddce5SStephen Hemminger 						  optlen);
19276cb153caSBenjamin LaHaise out_put:
19286cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
19291da177e4SLinus Torvalds 	}
19301da177e4SLinus Torvalds 	return err;
19311da177e4SLinus Torvalds }
19321da177e4SLinus Torvalds 
19331da177e4SLinus Torvalds /*
19341da177e4SLinus Torvalds  *	Get a socket option. Because we don't know the option lengths we have
19351da177e4SLinus Torvalds  *	to pass a user mode parameter for the protocols to sort out.
19361da177e4SLinus Torvalds  */
19371da177e4SLinus Torvalds 
193820f37034SHeiko Carstens SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
193920f37034SHeiko Carstens 		char __user *, optval, int __user *, optlen)
19401da177e4SLinus Torvalds {
19416cb153caSBenjamin LaHaise 	int err, fput_needed;
19421da177e4SLinus Torvalds 	struct socket *sock;
19431da177e4SLinus Torvalds 
194489bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
194589bddce5SStephen Hemminger 	if (sock != NULL) {
19466cb153caSBenjamin LaHaise 		err = security_socket_getsockopt(sock, level, optname);
19476cb153caSBenjamin LaHaise 		if (err)
19486cb153caSBenjamin LaHaise 			goto out_put;
19491da177e4SLinus Torvalds 
19501da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
195189bddce5SStephen Hemminger 			err =
195289bddce5SStephen Hemminger 			    sock_getsockopt(sock, level, optname, optval,
195389bddce5SStephen Hemminger 					    optlen);
19541da177e4SLinus Torvalds 		else
195589bddce5SStephen Hemminger 			err =
195689bddce5SStephen Hemminger 			    sock->ops->getsockopt(sock, level, optname, optval,
195789bddce5SStephen Hemminger 						  optlen);
19586cb153caSBenjamin LaHaise out_put:
19596cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
19601da177e4SLinus Torvalds 	}
19611da177e4SLinus Torvalds 	return err;
19621da177e4SLinus Torvalds }
19631da177e4SLinus Torvalds 
19641da177e4SLinus Torvalds /*
19651da177e4SLinus Torvalds  *	Shutdown a socket.
19661da177e4SLinus Torvalds  */
19671da177e4SLinus Torvalds 
1968754fe8d2SHeiko Carstens SYSCALL_DEFINE2(shutdown, int, fd, int, how)
19691da177e4SLinus Torvalds {
19706cb153caSBenjamin LaHaise 	int err, fput_needed;
19711da177e4SLinus Torvalds 	struct socket *sock;
19721da177e4SLinus Torvalds 
197389bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
197489bddce5SStephen Hemminger 	if (sock != NULL) {
19751da177e4SLinus Torvalds 		err = security_socket_shutdown(sock, how);
19766cb153caSBenjamin LaHaise 		if (!err)
19771da177e4SLinus Torvalds 			err = sock->ops->shutdown(sock, how);
19786cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
19791da177e4SLinus Torvalds 	}
19801da177e4SLinus Torvalds 	return err;
19811da177e4SLinus Torvalds }
19821da177e4SLinus Torvalds 
19831da177e4SLinus Torvalds /* A couple of helpful macros for getting the address of the 32/64 bit
19841da177e4SLinus Torvalds  * fields which are the same type (int / unsigned) on our platforms.
19851da177e4SLinus Torvalds  */
19861da177e4SLinus Torvalds #define COMPAT_MSG(msg, member)	((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member)
19871da177e4SLinus Torvalds #define COMPAT_NAMELEN(msg)	COMPAT_MSG(msg, msg_namelen)
19881da177e4SLinus Torvalds #define COMPAT_FLAGS(msg)	COMPAT_MSG(msg, msg_flags)
19891da177e4SLinus Torvalds 
1990c71d8ebeSTetsuo Handa struct used_address {
1991c71d8ebeSTetsuo Handa 	struct sockaddr_storage name;
1992c71d8ebeSTetsuo Handa 	unsigned int name_len;
1993c71d8ebeSTetsuo Handa };
1994c71d8ebeSTetsuo Handa 
19951661bf36SDan Carpenter static int copy_msghdr_from_user(struct msghdr *kmsg,
19961661bf36SDan Carpenter 				 struct msghdr __user *umsg)
19971661bf36SDan Carpenter {
19981661bf36SDan Carpenter 	if (copy_from_user(kmsg, umsg, sizeof(struct msghdr)))
19991661bf36SDan Carpenter 		return -EFAULT;
2000dbb490b9SMatthew Leach 
2001dbb490b9SMatthew Leach 	if (kmsg->msg_namelen < 0)
2002dbb490b9SMatthew Leach 		return -EINVAL;
2003dbb490b9SMatthew Leach 
20041661bf36SDan Carpenter 	if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
2005db31c55aSDan Carpenter 		kmsg->msg_namelen = sizeof(struct sockaddr_storage);
20061661bf36SDan Carpenter 	return 0;
20071661bf36SDan Carpenter }
20081661bf36SDan Carpenter 
2009a7526eb5SAndy Lutomirski static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
201095c96174SEric Dumazet 			 struct msghdr *msg_sys, unsigned int flags,
2011c71d8ebeSTetsuo Handa 			 struct used_address *used_address)
20121da177e4SLinus Torvalds {
201389bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
201489bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
2015230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
20161da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
2017b9d717a7SAlex Williamson 	unsigned char ctl[sizeof(struct cmsghdr) + 20]
2018b9d717a7SAlex Williamson 	    __attribute__ ((aligned(sizeof(__kernel_size_t))));
2019b9d717a7SAlex Williamson 	/* 20 is size of ipv6_pktinfo */
20201da177e4SLinus Torvalds 	unsigned char *ctl_buf = ctl;
2021a74e9106SEric Dumazet 	int err, ctl_len, total_len;
20221da177e4SLinus Torvalds 
20231da177e4SLinus Torvalds 	err = -EFAULT;
20241da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
2025228e548eSAnton Blanchard 		if (get_compat_msghdr(msg_sys, msg_compat))
20261da177e4SLinus Torvalds 			return -EFAULT;
20271661bf36SDan Carpenter 	} else {
20281661bf36SDan Carpenter 		err = copy_msghdr_from_user(msg_sys, msg);
20291661bf36SDan Carpenter 		if (err)
20301661bf36SDan Carpenter 			return err;
20311661bf36SDan Carpenter 	}
20321da177e4SLinus Torvalds 
2033a74e9106SEric Dumazet 	if (msg_sys->msg_iovlen > UIO_FASTIOV) {
20341da177e4SLinus Torvalds 		err = -EMSGSIZE;
2035228e548eSAnton Blanchard 		if (msg_sys->msg_iovlen > UIO_MAXIOV)
2036228e548eSAnton Blanchard 			goto out;
20371da177e4SLinus Torvalds 		err = -ENOMEM;
2038a74e9106SEric Dumazet 		iov = kmalloc(msg_sys->msg_iovlen * sizeof(struct iovec),
2039a74e9106SEric Dumazet 			      GFP_KERNEL);
20401da177e4SLinus Torvalds 		if (!iov)
2041228e548eSAnton Blanchard 			goto out;
20421da177e4SLinus Torvalds 	}
20431da177e4SLinus Torvalds 
20441da177e4SLinus Torvalds 	/* This will also move the address data into kernel space */
20451da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
204643db362dSMaciej Żenczykowski 		err = verify_compat_iovec(msg_sys, iov, &address, VERIFY_READ);
20471da177e4SLinus Torvalds 	} else
204843db362dSMaciej Żenczykowski 		err = verify_iovec(msg_sys, iov, &address, VERIFY_READ);
20491da177e4SLinus Torvalds 	if (err < 0)
20501da177e4SLinus Torvalds 		goto out_freeiov;
20511da177e4SLinus Torvalds 	total_len = err;
20521da177e4SLinus Torvalds 
20531da177e4SLinus Torvalds 	err = -ENOBUFS;
20541da177e4SLinus Torvalds 
2055228e548eSAnton Blanchard 	if (msg_sys->msg_controllen > INT_MAX)
20561da177e4SLinus Torvalds 		goto out_freeiov;
2057228e548eSAnton Blanchard 	ctl_len = msg_sys->msg_controllen;
20581da177e4SLinus Torvalds 	if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
205989bddce5SStephen Hemminger 		err =
2060228e548eSAnton Blanchard 		    cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl,
206189bddce5SStephen Hemminger 						     sizeof(ctl));
20621da177e4SLinus Torvalds 		if (err)
20631da177e4SLinus Torvalds 			goto out_freeiov;
2064228e548eSAnton Blanchard 		ctl_buf = msg_sys->msg_control;
2065228e548eSAnton Blanchard 		ctl_len = msg_sys->msg_controllen;
20661da177e4SLinus Torvalds 	} else if (ctl_len) {
206789bddce5SStephen Hemminger 		if (ctl_len > sizeof(ctl)) {
20681da177e4SLinus Torvalds 			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
20691da177e4SLinus Torvalds 			if (ctl_buf == NULL)
20701da177e4SLinus Torvalds 				goto out_freeiov;
20711da177e4SLinus Torvalds 		}
20721da177e4SLinus Torvalds 		err = -EFAULT;
20731da177e4SLinus Torvalds 		/*
2074228e548eSAnton Blanchard 		 * Careful! Before this, msg_sys->msg_control contains a user pointer.
20751da177e4SLinus Torvalds 		 * Afterwards, it will be a kernel pointer. Thus the compiler-assisted
20761da177e4SLinus Torvalds 		 * checking falls down on this.
20771da177e4SLinus Torvalds 		 */
2078fb8621bbSNamhyung Kim 		if (copy_from_user(ctl_buf,
2079228e548eSAnton Blanchard 				   (void __user __force *)msg_sys->msg_control,
208089bddce5SStephen Hemminger 				   ctl_len))
20811da177e4SLinus Torvalds 			goto out_freectl;
2082228e548eSAnton Blanchard 		msg_sys->msg_control = ctl_buf;
20831da177e4SLinus Torvalds 	}
2084228e548eSAnton Blanchard 	msg_sys->msg_flags = flags;
20851da177e4SLinus Torvalds 
20861da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
2087228e548eSAnton Blanchard 		msg_sys->msg_flags |= MSG_DONTWAIT;
2088c71d8ebeSTetsuo Handa 	/*
2089c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and current destination address is same as
2090c71d8ebeSTetsuo Handa 	 * previously succeeded address, omit asking LSM's decision.
2091c71d8ebeSTetsuo Handa 	 * used_address->name_len is initialized to UINT_MAX so that the first
2092c71d8ebeSTetsuo Handa 	 * destination address never matches.
2093c71d8ebeSTetsuo Handa 	 */
2094bc909d9dSMathieu Desnoyers 	if (used_address && msg_sys->msg_name &&
2095bc909d9dSMathieu Desnoyers 	    used_address->name_len == msg_sys->msg_namelen &&
2096bc909d9dSMathieu Desnoyers 	    !memcmp(&used_address->name, msg_sys->msg_name,
2097c71d8ebeSTetsuo Handa 		    used_address->name_len)) {
2098c71d8ebeSTetsuo Handa 		err = sock_sendmsg_nosec(sock, msg_sys, total_len);
2099c71d8ebeSTetsuo Handa 		goto out_freectl;
2100c71d8ebeSTetsuo Handa 	}
2101c71d8ebeSTetsuo Handa 	err = sock_sendmsg(sock, msg_sys, total_len);
2102c71d8ebeSTetsuo Handa 	/*
2103c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and sending to current destination address was
2104c71d8ebeSTetsuo Handa 	 * successful, remember it.
2105c71d8ebeSTetsuo Handa 	 */
2106c71d8ebeSTetsuo Handa 	if (used_address && err >= 0) {
2107c71d8ebeSTetsuo Handa 		used_address->name_len = msg_sys->msg_namelen;
2108bc909d9dSMathieu Desnoyers 		if (msg_sys->msg_name)
2109bc909d9dSMathieu Desnoyers 			memcpy(&used_address->name, msg_sys->msg_name,
2110c71d8ebeSTetsuo Handa 			       used_address->name_len);
2111c71d8ebeSTetsuo Handa 	}
21121da177e4SLinus Torvalds 
21131da177e4SLinus Torvalds out_freectl:
21141da177e4SLinus Torvalds 	if (ctl_buf != ctl)
21151da177e4SLinus Torvalds 		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
21161da177e4SLinus Torvalds out_freeiov:
21171da177e4SLinus Torvalds 	if (iov != iovstack)
2118a74e9106SEric Dumazet 		kfree(iov);
2119228e548eSAnton Blanchard out:
2120228e548eSAnton Blanchard 	return err;
2121228e548eSAnton Blanchard }
2122228e548eSAnton Blanchard 
2123228e548eSAnton Blanchard /*
2124228e548eSAnton Blanchard  *	BSD sendmsg interface
2125228e548eSAnton Blanchard  */
2126228e548eSAnton Blanchard 
2127a7526eb5SAndy Lutomirski long __sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
2128228e548eSAnton Blanchard {
2129228e548eSAnton Blanchard 	int fput_needed, err;
2130228e548eSAnton Blanchard 	struct msghdr msg_sys;
21311be374a0SAndy Lutomirski 	struct socket *sock;
2132228e548eSAnton Blanchard 
21331be374a0SAndy Lutomirski 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2134228e548eSAnton Blanchard 	if (!sock)
2135228e548eSAnton Blanchard 		goto out;
2136228e548eSAnton Blanchard 
2137a7526eb5SAndy Lutomirski 	err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL);
2138228e548eSAnton Blanchard 
21396cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
21401da177e4SLinus Torvalds out:
21411da177e4SLinus Torvalds 	return err;
21421da177e4SLinus Torvalds }
21431da177e4SLinus Torvalds 
2144a7526eb5SAndy Lutomirski SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned int, flags)
2145a7526eb5SAndy Lutomirski {
2146a7526eb5SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
2147a7526eb5SAndy Lutomirski 		return -EINVAL;
2148a7526eb5SAndy Lutomirski 	return __sys_sendmsg(fd, msg, flags);
2149a7526eb5SAndy Lutomirski }
2150a7526eb5SAndy Lutomirski 
2151228e548eSAnton Blanchard /*
2152228e548eSAnton Blanchard  *	Linux sendmmsg interface
2153228e548eSAnton Blanchard  */
2154228e548eSAnton Blanchard 
2155228e548eSAnton Blanchard int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2156228e548eSAnton Blanchard 		   unsigned int flags)
2157228e548eSAnton Blanchard {
2158228e548eSAnton Blanchard 	int fput_needed, err, datagrams;
2159228e548eSAnton Blanchard 	struct socket *sock;
2160228e548eSAnton Blanchard 	struct mmsghdr __user *entry;
2161228e548eSAnton Blanchard 	struct compat_mmsghdr __user *compat_entry;
2162228e548eSAnton Blanchard 	struct msghdr msg_sys;
2163c71d8ebeSTetsuo Handa 	struct used_address used_address;
2164228e548eSAnton Blanchard 
216598382f41SAnton Blanchard 	if (vlen > UIO_MAXIOV)
216698382f41SAnton Blanchard 		vlen = UIO_MAXIOV;
2167228e548eSAnton Blanchard 
2168228e548eSAnton Blanchard 	datagrams = 0;
2169228e548eSAnton Blanchard 
2170228e548eSAnton Blanchard 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2171228e548eSAnton Blanchard 	if (!sock)
2172228e548eSAnton Blanchard 		return err;
2173228e548eSAnton Blanchard 
2174c71d8ebeSTetsuo Handa 	used_address.name_len = UINT_MAX;
2175228e548eSAnton Blanchard 	entry = mmsg;
2176228e548eSAnton Blanchard 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2177728ffb86SAnton Blanchard 	err = 0;
2178228e548eSAnton Blanchard 
2179228e548eSAnton Blanchard 	while (datagrams < vlen) {
2180228e548eSAnton Blanchard 		if (MSG_CMSG_COMPAT & flags) {
2181a7526eb5SAndy Lutomirski 			err = ___sys_sendmsg(sock, (struct msghdr __user *)compat_entry,
2182c71d8ebeSTetsuo Handa 					     &msg_sys, flags, &used_address);
2183228e548eSAnton Blanchard 			if (err < 0)
2184228e548eSAnton Blanchard 				break;
2185228e548eSAnton Blanchard 			err = __put_user(err, &compat_entry->msg_len);
2186228e548eSAnton Blanchard 			++compat_entry;
2187228e548eSAnton Blanchard 		} else {
2188a7526eb5SAndy Lutomirski 			err = ___sys_sendmsg(sock,
2189a7526eb5SAndy Lutomirski 					     (struct msghdr __user *)entry,
2190c71d8ebeSTetsuo Handa 					     &msg_sys, flags, &used_address);
2191228e548eSAnton Blanchard 			if (err < 0)
2192228e548eSAnton Blanchard 				break;
2193228e548eSAnton Blanchard 			err = put_user(err, &entry->msg_len);
2194228e548eSAnton Blanchard 			++entry;
2195228e548eSAnton Blanchard 		}
2196228e548eSAnton Blanchard 
2197228e548eSAnton Blanchard 		if (err)
2198228e548eSAnton Blanchard 			break;
2199228e548eSAnton Blanchard 		++datagrams;
2200228e548eSAnton Blanchard 	}
2201228e548eSAnton Blanchard 
2202228e548eSAnton Blanchard 	fput_light(sock->file, fput_needed);
2203228e548eSAnton Blanchard 
2204728ffb86SAnton Blanchard 	/* We only return an error if no datagrams were able to be sent */
2205728ffb86SAnton Blanchard 	if (datagrams != 0)
2206228e548eSAnton Blanchard 		return datagrams;
2207228e548eSAnton Blanchard 
2208228e548eSAnton Blanchard 	return err;
2209228e548eSAnton Blanchard }
2210228e548eSAnton Blanchard 
2211228e548eSAnton Blanchard SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
2212228e548eSAnton Blanchard 		unsigned int, vlen, unsigned int, flags)
2213228e548eSAnton Blanchard {
22141be374a0SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
22151be374a0SAndy Lutomirski 		return -EINVAL;
2216228e548eSAnton Blanchard 	return __sys_sendmmsg(fd, mmsg, vlen, flags);
2217228e548eSAnton Blanchard }
2218228e548eSAnton Blanchard 
2219a7526eb5SAndy Lutomirski static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
222095c96174SEric Dumazet 			 struct msghdr *msg_sys, unsigned int flags, int nosec)
22211da177e4SLinus Torvalds {
222289bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
222389bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
22241da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV];
22251da177e4SLinus Torvalds 	struct iovec *iov = iovstack;
22261da177e4SLinus Torvalds 	unsigned long cmsg_ptr;
2227a74e9106SEric Dumazet 	int err, total_len, len;
22281da177e4SLinus Torvalds 
22291da177e4SLinus Torvalds 	/* kernel mode address */
2230230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage addr;
22311da177e4SLinus Torvalds 
22321da177e4SLinus Torvalds 	/* user mode address pointers */
22331da177e4SLinus Torvalds 	struct sockaddr __user *uaddr;
22341da177e4SLinus Torvalds 	int __user *uaddr_len;
22351da177e4SLinus Torvalds 
22361da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
2237a2e27255SArnaldo Carvalho de Melo 		if (get_compat_msghdr(msg_sys, msg_compat))
22381da177e4SLinus Torvalds 			return -EFAULT;
22391661bf36SDan Carpenter 	} else {
22401661bf36SDan Carpenter 		err = copy_msghdr_from_user(msg_sys, msg);
22411661bf36SDan Carpenter 		if (err)
22421661bf36SDan Carpenter 			return err;
22431661bf36SDan Carpenter 	}
22441da177e4SLinus Torvalds 
2245a74e9106SEric Dumazet 	if (msg_sys->msg_iovlen > UIO_FASTIOV) {
22461da177e4SLinus Torvalds 		err = -EMSGSIZE;
2247a2e27255SArnaldo Carvalho de Melo 		if (msg_sys->msg_iovlen > UIO_MAXIOV)
2248a2e27255SArnaldo Carvalho de Melo 			goto out;
22491da177e4SLinus Torvalds 		err = -ENOMEM;
2250a74e9106SEric Dumazet 		iov = kmalloc(msg_sys->msg_iovlen * sizeof(struct iovec),
2251a74e9106SEric Dumazet 			      GFP_KERNEL);
22521da177e4SLinus Torvalds 		if (!iov)
2253a2e27255SArnaldo Carvalho de Melo 			goto out;
22541da177e4SLinus Torvalds 	}
22551da177e4SLinus Torvalds 
2256f3d33426SHannes Frederic Sowa 	/* Save the user-mode address (verify_iovec will change the
22571da177e4SLinus Torvalds 	 * kernel msghdr to use the kernel address space)
22581da177e4SLinus Torvalds 	 */
2259a2e27255SArnaldo Carvalho de Melo 	uaddr = (__force void __user *)msg_sys->msg_name;
22601da177e4SLinus Torvalds 	uaddr_len = COMPAT_NAMELEN(msg);
2261f3d33426SHannes Frederic Sowa 	if (MSG_CMSG_COMPAT & flags)
226243db362dSMaciej Żenczykowski 		err = verify_compat_iovec(msg_sys, iov, &addr, VERIFY_WRITE);
2263f3d33426SHannes Frederic Sowa 	else
226443db362dSMaciej Żenczykowski 		err = verify_iovec(msg_sys, iov, &addr, VERIFY_WRITE);
22651da177e4SLinus Torvalds 	if (err < 0)
22661da177e4SLinus Torvalds 		goto out_freeiov;
22671da177e4SLinus Torvalds 	total_len = err;
22681da177e4SLinus Torvalds 
2269a2e27255SArnaldo Carvalho de Melo 	cmsg_ptr = (unsigned long)msg_sys->msg_control;
2270a2e27255SArnaldo Carvalho de Melo 	msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
22711da177e4SLinus Torvalds 
2272f3d33426SHannes Frederic Sowa 	/* We assume all kernel code knows the size of sockaddr_storage */
2273f3d33426SHannes Frederic Sowa 	msg_sys->msg_namelen = 0;
2274f3d33426SHannes Frederic Sowa 
22751da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
22761da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
2277a2e27255SArnaldo Carvalho de Melo 	err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys,
2278a2e27255SArnaldo Carvalho de Melo 							  total_len, flags);
22791da177e4SLinus Torvalds 	if (err < 0)
22801da177e4SLinus Torvalds 		goto out_freeiov;
22811da177e4SLinus Torvalds 	len = err;
22821da177e4SLinus Torvalds 
22831da177e4SLinus Torvalds 	if (uaddr != NULL) {
228443db362dSMaciej Żenczykowski 		err = move_addr_to_user(&addr,
2285a2e27255SArnaldo Carvalho de Melo 					msg_sys->msg_namelen, uaddr,
228689bddce5SStephen Hemminger 					uaddr_len);
22871da177e4SLinus Torvalds 		if (err < 0)
22881da177e4SLinus Torvalds 			goto out_freeiov;
22891da177e4SLinus Torvalds 	}
2290a2e27255SArnaldo Carvalho de Melo 	err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
229137f7f421SDavid S. Miller 			 COMPAT_FLAGS(msg));
22921da177e4SLinus Torvalds 	if (err)
22931da177e4SLinus Torvalds 		goto out_freeiov;
22941da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags)
2295a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
22961da177e4SLinus Torvalds 				 &msg_compat->msg_controllen);
22971da177e4SLinus Torvalds 	else
2298a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
22991da177e4SLinus Torvalds 				 &msg->msg_controllen);
23001da177e4SLinus Torvalds 	if (err)
23011da177e4SLinus Torvalds 		goto out_freeiov;
23021da177e4SLinus Torvalds 	err = len;
23031da177e4SLinus Torvalds 
23041da177e4SLinus Torvalds out_freeiov:
23051da177e4SLinus Torvalds 	if (iov != iovstack)
2306a74e9106SEric Dumazet 		kfree(iov);
2307a2e27255SArnaldo Carvalho de Melo out:
2308a2e27255SArnaldo Carvalho de Melo 	return err;
2309a2e27255SArnaldo Carvalho de Melo }
2310a2e27255SArnaldo Carvalho de Melo 
2311a2e27255SArnaldo Carvalho de Melo /*
2312a2e27255SArnaldo Carvalho de Melo  *	BSD recvmsg interface
2313a2e27255SArnaldo Carvalho de Melo  */
2314a2e27255SArnaldo Carvalho de Melo 
2315a7526eb5SAndy Lutomirski long __sys_recvmsg(int fd, struct msghdr __user *msg, unsigned flags)
2316a2e27255SArnaldo Carvalho de Melo {
2317a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err;
2318a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
23191be374a0SAndy Lutomirski 	struct socket *sock;
2320a2e27255SArnaldo Carvalho de Melo 
23211be374a0SAndy Lutomirski 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2322a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2323a2e27255SArnaldo Carvalho de Melo 		goto out;
2324a2e27255SArnaldo Carvalho de Melo 
2325a7526eb5SAndy Lutomirski 	err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0);
2326a2e27255SArnaldo Carvalho de Melo 
23276cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
23281da177e4SLinus Torvalds out:
23291da177e4SLinus Torvalds 	return err;
23301da177e4SLinus Torvalds }
23311da177e4SLinus Torvalds 
2332a7526eb5SAndy Lutomirski SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg,
2333a7526eb5SAndy Lutomirski 		unsigned int, flags)
2334a7526eb5SAndy Lutomirski {
2335a7526eb5SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
2336a7526eb5SAndy Lutomirski 		return -EINVAL;
2337a7526eb5SAndy Lutomirski 	return __sys_recvmsg(fd, msg, flags);
2338a7526eb5SAndy Lutomirski }
2339a7526eb5SAndy Lutomirski 
2340a2e27255SArnaldo Carvalho de Melo /*
2341a2e27255SArnaldo Carvalho de Melo  *     Linux recvmmsg interface
2342a2e27255SArnaldo Carvalho de Melo  */
23431da177e4SLinus Torvalds 
2344a2e27255SArnaldo Carvalho de Melo int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2345a2e27255SArnaldo Carvalho de Melo 		   unsigned int flags, struct timespec *timeout)
2346a2e27255SArnaldo Carvalho de Melo {
2347a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err, datagrams;
2348a2e27255SArnaldo Carvalho de Melo 	struct socket *sock;
2349a2e27255SArnaldo Carvalho de Melo 	struct mmsghdr __user *entry;
2350d7256d0eSJean-Mickael Guerin 	struct compat_mmsghdr __user *compat_entry;
2351a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
2352a2e27255SArnaldo Carvalho de Melo 	struct timespec end_time;
2353a2e27255SArnaldo Carvalho de Melo 
2354a2e27255SArnaldo Carvalho de Melo 	if (timeout &&
2355a2e27255SArnaldo Carvalho de Melo 	    poll_select_set_timeout(&end_time, timeout->tv_sec,
2356a2e27255SArnaldo Carvalho de Melo 				    timeout->tv_nsec))
2357a2e27255SArnaldo Carvalho de Melo 		return -EINVAL;
2358a2e27255SArnaldo Carvalho de Melo 
2359a2e27255SArnaldo Carvalho de Melo 	datagrams = 0;
2360a2e27255SArnaldo Carvalho de Melo 
2361a2e27255SArnaldo Carvalho de Melo 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2362a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2363a2e27255SArnaldo Carvalho de Melo 		return err;
2364a2e27255SArnaldo Carvalho de Melo 
2365a2e27255SArnaldo Carvalho de Melo 	err = sock_error(sock->sk);
2366a2e27255SArnaldo Carvalho de Melo 	if (err)
2367a2e27255SArnaldo Carvalho de Melo 		goto out_put;
2368a2e27255SArnaldo Carvalho de Melo 
2369a2e27255SArnaldo Carvalho de Melo 	entry = mmsg;
2370d7256d0eSJean-Mickael Guerin 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2371a2e27255SArnaldo Carvalho de Melo 
2372a2e27255SArnaldo Carvalho de Melo 	while (datagrams < vlen) {
2373a2e27255SArnaldo Carvalho de Melo 		/*
2374a2e27255SArnaldo Carvalho de Melo 		 * No need to ask LSM for more than the first datagram.
2375a2e27255SArnaldo Carvalho de Melo 		 */
2376d7256d0eSJean-Mickael Guerin 		if (MSG_CMSG_COMPAT & flags) {
2377a7526eb5SAndy Lutomirski 			err = ___sys_recvmsg(sock, (struct msghdr __user *)compat_entry,
2378b9eb8b87SAnton Blanchard 					     &msg_sys, flags & ~MSG_WAITFORONE,
2379b9eb8b87SAnton Blanchard 					     datagrams);
2380d7256d0eSJean-Mickael Guerin 			if (err < 0)
2381d7256d0eSJean-Mickael Guerin 				break;
2382d7256d0eSJean-Mickael Guerin 			err = __put_user(err, &compat_entry->msg_len);
2383d7256d0eSJean-Mickael Guerin 			++compat_entry;
2384d7256d0eSJean-Mickael Guerin 		} else {
2385a7526eb5SAndy Lutomirski 			err = ___sys_recvmsg(sock,
2386a7526eb5SAndy Lutomirski 					     (struct msghdr __user *)entry,
2387b9eb8b87SAnton Blanchard 					     &msg_sys, flags & ~MSG_WAITFORONE,
2388b9eb8b87SAnton Blanchard 					     datagrams);
2389a2e27255SArnaldo Carvalho de Melo 			if (err < 0)
2390a2e27255SArnaldo Carvalho de Melo 				break;
2391a2e27255SArnaldo Carvalho de Melo 			err = put_user(err, &entry->msg_len);
2392d7256d0eSJean-Mickael Guerin 			++entry;
2393d7256d0eSJean-Mickael Guerin 		}
2394d7256d0eSJean-Mickael Guerin 
2395a2e27255SArnaldo Carvalho de Melo 		if (err)
2396a2e27255SArnaldo Carvalho de Melo 			break;
2397a2e27255SArnaldo Carvalho de Melo 		++datagrams;
2398a2e27255SArnaldo Carvalho de Melo 
239971c5c159SBrandon L Black 		/* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
240071c5c159SBrandon L Black 		if (flags & MSG_WAITFORONE)
240171c5c159SBrandon L Black 			flags |= MSG_DONTWAIT;
240271c5c159SBrandon L Black 
2403a2e27255SArnaldo Carvalho de Melo 		if (timeout) {
2404a2e27255SArnaldo Carvalho de Melo 			ktime_get_ts(timeout);
2405a2e27255SArnaldo Carvalho de Melo 			*timeout = timespec_sub(end_time, *timeout);
2406a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_sec < 0) {
2407a2e27255SArnaldo Carvalho de Melo 				timeout->tv_sec = timeout->tv_nsec = 0;
2408a2e27255SArnaldo Carvalho de Melo 				break;
2409a2e27255SArnaldo Carvalho de Melo 			}
2410a2e27255SArnaldo Carvalho de Melo 
2411a2e27255SArnaldo Carvalho de Melo 			/* Timeout, return less than vlen datagrams */
2412a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_nsec == 0 && timeout->tv_sec == 0)
2413a2e27255SArnaldo Carvalho de Melo 				break;
2414a2e27255SArnaldo Carvalho de Melo 		}
2415a2e27255SArnaldo Carvalho de Melo 
2416a2e27255SArnaldo Carvalho de Melo 		/* Out of band data, return right away */
2417a2e27255SArnaldo Carvalho de Melo 		if (msg_sys.msg_flags & MSG_OOB)
2418a2e27255SArnaldo Carvalho de Melo 			break;
2419a2e27255SArnaldo Carvalho de Melo 	}
2420a2e27255SArnaldo Carvalho de Melo 
2421a2e27255SArnaldo Carvalho de Melo out_put:
2422a2e27255SArnaldo Carvalho de Melo 	fput_light(sock->file, fput_needed);
2423a2e27255SArnaldo Carvalho de Melo 
2424a2e27255SArnaldo Carvalho de Melo 	if (err == 0)
2425a2e27255SArnaldo Carvalho de Melo 		return datagrams;
2426a2e27255SArnaldo Carvalho de Melo 
2427a2e27255SArnaldo Carvalho de Melo 	if (datagrams != 0) {
2428a2e27255SArnaldo Carvalho de Melo 		/*
2429a2e27255SArnaldo Carvalho de Melo 		 * We may return less entries than requested (vlen) if the
2430a2e27255SArnaldo Carvalho de Melo 		 * sock is non block and there aren't enough datagrams...
2431a2e27255SArnaldo Carvalho de Melo 		 */
2432a2e27255SArnaldo Carvalho de Melo 		if (err != -EAGAIN) {
2433a2e27255SArnaldo Carvalho de Melo 			/*
2434a2e27255SArnaldo Carvalho de Melo 			 * ... or  if recvmsg returns an error after we
2435a2e27255SArnaldo Carvalho de Melo 			 * received some datagrams, where we record the
2436a2e27255SArnaldo Carvalho de Melo 			 * error to return on the next call or if the
2437a2e27255SArnaldo Carvalho de Melo 			 * app asks about it using getsockopt(SO_ERROR).
2438a2e27255SArnaldo Carvalho de Melo 			 */
2439a2e27255SArnaldo Carvalho de Melo 			sock->sk->sk_err = -err;
2440a2e27255SArnaldo Carvalho de Melo 		}
2441a2e27255SArnaldo Carvalho de Melo 
2442a2e27255SArnaldo Carvalho de Melo 		return datagrams;
2443a2e27255SArnaldo Carvalho de Melo 	}
2444a2e27255SArnaldo Carvalho de Melo 
2445a2e27255SArnaldo Carvalho de Melo 	return err;
2446a2e27255SArnaldo Carvalho de Melo }
2447a2e27255SArnaldo Carvalho de Melo 
2448a2e27255SArnaldo Carvalho de Melo SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
2449a2e27255SArnaldo Carvalho de Melo 		unsigned int, vlen, unsigned int, flags,
2450a2e27255SArnaldo Carvalho de Melo 		struct timespec __user *, timeout)
2451a2e27255SArnaldo Carvalho de Melo {
2452a2e27255SArnaldo Carvalho de Melo 	int datagrams;
2453a2e27255SArnaldo Carvalho de Melo 	struct timespec timeout_sys;
2454a2e27255SArnaldo Carvalho de Melo 
24551be374a0SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
24561be374a0SAndy Lutomirski 		return -EINVAL;
24571be374a0SAndy Lutomirski 
2458a2e27255SArnaldo Carvalho de Melo 	if (!timeout)
2459a2e27255SArnaldo Carvalho de Melo 		return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL);
2460a2e27255SArnaldo Carvalho de Melo 
2461a2e27255SArnaldo Carvalho de Melo 	if (copy_from_user(&timeout_sys, timeout, sizeof(timeout_sys)))
2462a2e27255SArnaldo Carvalho de Melo 		return -EFAULT;
2463a2e27255SArnaldo Carvalho de Melo 
2464a2e27255SArnaldo Carvalho de Melo 	datagrams = __sys_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys);
2465a2e27255SArnaldo Carvalho de Melo 
2466a2e27255SArnaldo Carvalho de Melo 	if (datagrams > 0 &&
2467a2e27255SArnaldo Carvalho de Melo 	    copy_to_user(timeout, &timeout_sys, sizeof(timeout_sys)))
2468a2e27255SArnaldo Carvalho de Melo 		datagrams = -EFAULT;
2469a2e27255SArnaldo Carvalho de Melo 
2470a2e27255SArnaldo Carvalho de Melo 	return datagrams;
2471a2e27255SArnaldo Carvalho de Melo }
2472a2e27255SArnaldo Carvalho de Melo 
2473a2e27255SArnaldo Carvalho de Melo #ifdef __ARCH_WANT_SYS_SOCKETCALL
24741da177e4SLinus Torvalds /* Argument list sizes for sys_socketcall */
24751da177e4SLinus Torvalds #define AL(x) ((x) * sizeof(unsigned long))
2476228e548eSAnton Blanchard static const unsigned char nargs[21] = {
247789bddce5SStephen Hemminger 	AL(0), AL(3), AL(3), AL(3), AL(2), AL(3),
24781da177e4SLinus Torvalds 	AL(3), AL(3), AL(4), AL(4), AL(4), AL(6),
2479aaca0bdcSUlrich Drepper 	AL(6), AL(2), AL(5), AL(5), AL(3), AL(3),
2480228e548eSAnton Blanchard 	AL(4), AL(5), AL(4)
248189bddce5SStephen Hemminger };
248289bddce5SStephen Hemminger 
24831da177e4SLinus Torvalds #undef AL
24841da177e4SLinus Torvalds 
24851da177e4SLinus Torvalds /*
24861da177e4SLinus Torvalds  *	System call vectors.
24871da177e4SLinus Torvalds  *
24881da177e4SLinus Torvalds  *	Argument checking cleaned up. Saved 20% in size.
24891da177e4SLinus Torvalds  *  This function doesn't need to set the kernel lock because
24901da177e4SLinus Torvalds  *  it is set by the callees.
24911da177e4SLinus Torvalds  */
24921da177e4SLinus Torvalds 
24933e0fa65fSHeiko Carstens SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
24941da177e4SLinus Torvalds {
24952950fa9dSChen Gang 	unsigned long a[AUDITSC_ARGS];
24961da177e4SLinus Torvalds 	unsigned long a0, a1;
24971da177e4SLinus Torvalds 	int err;
249847379052SArjan van de Ven 	unsigned int len;
24991da177e4SLinus Torvalds 
2500228e548eSAnton Blanchard 	if (call < 1 || call > SYS_SENDMMSG)
25011da177e4SLinus Torvalds 		return -EINVAL;
25021da177e4SLinus Torvalds 
250347379052SArjan van de Ven 	len = nargs[call];
250447379052SArjan van de Ven 	if (len > sizeof(a))
250547379052SArjan van de Ven 		return -EINVAL;
250647379052SArjan van de Ven 
25071da177e4SLinus Torvalds 	/* copy_from_user should be SMP safe. */
250847379052SArjan van de Ven 	if (copy_from_user(a, args, len))
25091da177e4SLinus Torvalds 		return -EFAULT;
25101da177e4SLinus Torvalds 
25112950fa9dSChen Gang 	err = audit_socketcall(nargs[call] / sizeof(unsigned long), a);
25122950fa9dSChen Gang 	if (err)
25132950fa9dSChen Gang 		return err;
25143ec3b2fbSDavid Woodhouse 
25151da177e4SLinus Torvalds 	a0 = a[0];
25161da177e4SLinus Torvalds 	a1 = a[1];
25171da177e4SLinus Torvalds 
251889bddce5SStephen Hemminger 	switch (call) {
25191da177e4SLinus Torvalds 	case SYS_SOCKET:
25201da177e4SLinus Torvalds 		err = sys_socket(a0, a1, a[2]);
25211da177e4SLinus Torvalds 		break;
25221da177e4SLinus Torvalds 	case SYS_BIND:
25231da177e4SLinus Torvalds 		err = sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
25241da177e4SLinus Torvalds 		break;
25251da177e4SLinus Torvalds 	case SYS_CONNECT:
25261da177e4SLinus Torvalds 		err = sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
25271da177e4SLinus Torvalds 		break;
25281da177e4SLinus Torvalds 	case SYS_LISTEN:
25291da177e4SLinus Torvalds 		err = sys_listen(a0, a1);
25301da177e4SLinus Torvalds 		break;
25311da177e4SLinus Torvalds 	case SYS_ACCEPT:
2532de11defeSUlrich Drepper 		err = sys_accept4(a0, (struct sockaddr __user *)a1,
2533aaca0bdcSUlrich Drepper 				  (int __user *)a[2], 0);
25341da177e4SLinus Torvalds 		break;
25351da177e4SLinus Torvalds 	case SYS_GETSOCKNAME:
253689bddce5SStephen Hemminger 		err =
253789bddce5SStephen Hemminger 		    sys_getsockname(a0, (struct sockaddr __user *)a1,
253889bddce5SStephen Hemminger 				    (int __user *)a[2]);
25391da177e4SLinus Torvalds 		break;
25401da177e4SLinus Torvalds 	case SYS_GETPEERNAME:
254189bddce5SStephen Hemminger 		err =
254289bddce5SStephen Hemminger 		    sys_getpeername(a0, (struct sockaddr __user *)a1,
254389bddce5SStephen Hemminger 				    (int __user *)a[2]);
25441da177e4SLinus Torvalds 		break;
25451da177e4SLinus Torvalds 	case SYS_SOCKETPAIR:
25461da177e4SLinus Torvalds 		err = sys_socketpair(a0, a1, a[2], (int __user *)a[3]);
25471da177e4SLinus Torvalds 		break;
25481da177e4SLinus Torvalds 	case SYS_SEND:
25491da177e4SLinus Torvalds 		err = sys_send(a0, (void __user *)a1, a[2], a[3]);
25501da177e4SLinus Torvalds 		break;
25511da177e4SLinus Torvalds 	case SYS_SENDTO:
25521da177e4SLinus Torvalds 		err = sys_sendto(a0, (void __user *)a1, a[2], a[3],
25531da177e4SLinus Torvalds 				 (struct sockaddr __user *)a[4], a[5]);
25541da177e4SLinus Torvalds 		break;
25551da177e4SLinus Torvalds 	case SYS_RECV:
25561da177e4SLinus Torvalds 		err = sys_recv(a0, (void __user *)a1, a[2], a[3]);
25571da177e4SLinus Torvalds 		break;
25581da177e4SLinus Torvalds 	case SYS_RECVFROM:
25591da177e4SLinus Torvalds 		err = sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
256089bddce5SStephen Hemminger 				   (struct sockaddr __user *)a[4],
256189bddce5SStephen Hemminger 				   (int __user *)a[5]);
25621da177e4SLinus Torvalds 		break;
25631da177e4SLinus Torvalds 	case SYS_SHUTDOWN:
25641da177e4SLinus Torvalds 		err = sys_shutdown(a0, a1);
25651da177e4SLinus Torvalds 		break;
25661da177e4SLinus Torvalds 	case SYS_SETSOCKOPT:
25671da177e4SLinus Torvalds 		err = sys_setsockopt(a0, a1, a[2], (char __user *)a[3], a[4]);
25681da177e4SLinus Torvalds 		break;
25691da177e4SLinus Torvalds 	case SYS_GETSOCKOPT:
257089bddce5SStephen Hemminger 		err =
257189bddce5SStephen Hemminger 		    sys_getsockopt(a0, a1, a[2], (char __user *)a[3],
257289bddce5SStephen Hemminger 				   (int __user *)a[4]);
25731da177e4SLinus Torvalds 		break;
25741da177e4SLinus Torvalds 	case SYS_SENDMSG:
25751da177e4SLinus Torvalds 		err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]);
25761da177e4SLinus Torvalds 		break;
2577228e548eSAnton Blanchard 	case SYS_SENDMMSG:
2578228e548eSAnton Blanchard 		err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]);
2579228e548eSAnton Blanchard 		break;
25801da177e4SLinus Torvalds 	case SYS_RECVMSG:
25811da177e4SLinus Torvalds 		err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]);
25821da177e4SLinus Torvalds 		break;
2583a2e27255SArnaldo Carvalho de Melo 	case SYS_RECVMMSG:
2584a2e27255SArnaldo Carvalho de Melo 		err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3],
2585a2e27255SArnaldo Carvalho de Melo 				   (struct timespec __user *)a[4]);
2586a2e27255SArnaldo Carvalho de Melo 		break;
2587de11defeSUlrich Drepper 	case SYS_ACCEPT4:
2588de11defeSUlrich Drepper 		err = sys_accept4(a0, (struct sockaddr __user *)a1,
2589de11defeSUlrich Drepper 				  (int __user *)a[2], a[3]);
2590aaca0bdcSUlrich Drepper 		break;
25911da177e4SLinus Torvalds 	default:
25921da177e4SLinus Torvalds 		err = -EINVAL;
25931da177e4SLinus Torvalds 		break;
25941da177e4SLinus Torvalds 	}
25951da177e4SLinus Torvalds 	return err;
25961da177e4SLinus Torvalds }
25971da177e4SLinus Torvalds 
25981da177e4SLinus Torvalds #endif				/* __ARCH_WANT_SYS_SOCKETCALL */
25991da177e4SLinus Torvalds 
260055737fdaSStephen Hemminger /**
260155737fdaSStephen Hemminger  *	sock_register - add a socket protocol handler
260255737fdaSStephen Hemminger  *	@ops: description of protocol
260355737fdaSStephen Hemminger  *
26041da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
26051da177e4SLinus Torvalds  *	advertise its address family, and have it linked into the
260655737fdaSStephen Hemminger  *	socket interface. The value ops->family coresponds to the
260755737fdaSStephen Hemminger  *	socket system call protocol family.
26081da177e4SLinus Torvalds  */
2609f0fd27d4SStephen Hemminger int sock_register(const struct net_proto_family *ops)
26101da177e4SLinus Torvalds {
26111da177e4SLinus Torvalds 	int err;
26121da177e4SLinus Torvalds 
26131da177e4SLinus Torvalds 	if (ops->family >= NPROTO) {
26143410f22eSYang Yingliang 		pr_crit("protocol %d >= NPROTO(%d)\n", ops->family, NPROTO);
26151da177e4SLinus Torvalds 		return -ENOBUFS;
26161da177e4SLinus Torvalds 	}
261755737fdaSStephen Hemminger 
261855737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2619190683a9SEric Dumazet 	if (rcu_dereference_protected(net_families[ops->family],
2620190683a9SEric Dumazet 				      lockdep_is_held(&net_family_lock)))
26211da177e4SLinus Torvalds 		err = -EEXIST;
262255737fdaSStephen Hemminger 	else {
2623cf778b00SEric Dumazet 		rcu_assign_pointer(net_families[ops->family], ops);
26241da177e4SLinus Torvalds 		err = 0;
26251da177e4SLinus Torvalds 	}
262655737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
262755737fdaSStephen Hemminger 
26283410f22eSYang Yingliang 	pr_info("NET: Registered protocol family %d\n", ops->family);
26291da177e4SLinus Torvalds 	return err;
26301da177e4SLinus Torvalds }
2631c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_register);
26321da177e4SLinus Torvalds 
263355737fdaSStephen Hemminger /**
263455737fdaSStephen Hemminger  *	sock_unregister - remove a protocol handler
263555737fdaSStephen Hemminger  *	@family: protocol family to remove
263655737fdaSStephen Hemminger  *
26371da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
26381da177e4SLinus Torvalds  *	remove its address family, and have it unlinked from the
263955737fdaSStephen Hemminger  *	new socket creation.
264055737fdaSStephen Hemminger  *
264155737fdaSStephen Hemminger  *	If protocol handler is a module, then it can use module reference
264255737fdaSStephen Hemminger  *	counts to protect against new references. If protocol handler is not
264355737fdaSStephen Hemminger  *	a module then it needs to provide its own protection in
264455737fdaSStephen Hemminger  *	the ops->create routine.
26451da177e4SLinus Torvalds  */
2646f0fd27d4SStephen Hemminger void sock_unregister(int family)
26471da177e4SLinus Torvalds {
2648f0fd27d4SStephen Hemminger 	BUG_ON(family < 0 || family >= NPROTO);
26491da177e4SLinus Torvalds 
265055737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2651a9b3cd7fSStephen Hemminger 	RCU_INIT_POINTER(net_families[family], NULL);
265255737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
265355737fdaSStephen Hemminger 
265455737fdaSStephen Hemminger 	synchronize_rcu();
265555737fdaSStephen Hemminger 
26563410f22eSYang Yingliang 	pr_info("NET: Unregistered protocol family %d\n", family);
26571da177e4SLinus Torvalds }
2658c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_unregister);
26591da177e4SLinus Torvalds 
266077d76ea3SAndi Kleen static int __init sock_init(void)
26611da177e4SLinus Torvalds {
2662b3e19d92SNick Piggin 	int err;
26632ca794e5SEric W. Biederman 	/*
26642ca794e5SEric W. Biederman 	 *      Initialize the network sysctl infrastructure.
26652ca794e5SEric W. Biederman 	 */
26662ca794e5SEric W. Biederman 	err = net_sysctl_init();
26672ca794e5SEric W. Biederman 	if (err)
26682ca794e5SEric W. Biederman 		goto out;
2669b3e19d92SNick Piggin 
26701da177e4SLinus Torvalds 	/*
26711da177e4SLinus Torvalds 	 *      Initialize skbuff SLAB cache
26721da177e4SLinus Torvalds 	 */
26731da177e4SLinus Torvalds 	skb_init();
26741da177e4SLinus Torvalds 
26751da177e4SLinus Torvalds 	/*
26761da177e4SLinus Torvalds 	 *      Initialize the protocols module.
26771da177e4SLinus Torvalds 	 */
26781da177e4SLinus Torvalds 
26791da177e4SLinus Torvalds 	init_inodecache();
2680b3e19d92SNick Piggin 
2681b3e19d92SNick Piggin 	err = register_filesystem(&sock_fs_type);
2682b3e19d92SNick Piggin 	if (err)
2683b3e19d92SNick Piggin 		goto out_fs;
26841da177e4SLinus Torvalds 	sock_mnt = kern_mount(&sock_fs_type);
2685b3e19d92SNick Piggin 	if (IS_ERR(sock_mnt)) {
2686b3e19d92SNick Piggin 		err = PTR_ERR(sock_mnt);
2687b3e19d92SNick Piggin 		goto out_mount;
2688b3e19d92SNick Piggin 	}
268977d76ea3SAndi Kleen 
269077d76ea3SAndi Kleen 	/* The real protocol initialization is performed in later initcalls.
26911da177e4SLinus Torvalds 	 */
26921da177e4SLinus Torvalds 
26931da177e4SLinus Torvalds #ifdef CONFIG_NETFILTER
26946d11cfdbSPablo Neira Ayuso 	err = netfilter_init();
26956d11cfdbSPablo Neira Ayuso 	if (err)
26966d11cfdbSPablo Neira Ayuso 		goto out;
26971da177e4SLinus Torvalds #endif
2698cbeb321aSDavid S. Miller 
2699408eccceSDaniel Borkmann 	ptp_classifier_init();
2700c1f19b51SRichard Cochran 
2701b3e19d92SNick Piggin out:
2702b3e19d92SNick Piggin 	return err;
2703b3e19d92SNick Piggin 
2704b3e19d92SNick Piggin out_mount:
2705b3e19d92SNick Piggin 	unregister_filesystem(&sock_fs_type);
2706b3e19d92SNick Piggin out_fs:
2707b3e19d92SNick Piggin 	goto out;
27081da177e4SLinus Torvalds }
27091da177e4SLinus Torvalds 
271077d76ea3SAndi Kleen core_initcall(sock_init);	/* early initcall */
271177d76ea3SAndi Kleen 
27121da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS
27131da177e4SLinus Torvalds void socket_seq_show(struct seq_file *seq)
27141da177e4SLinus Torvalds {
27151da177e4SLinus Torvalds 	int cpu;
27161da177e4SLinus Torvalds 	int counter = 0;
27171da177e4SLinus Torvalds 
27186f912042SKAMEZAWA Hiroyuki 	for_each_possible_cpu(cpu)
27191da177e4SLinus Torvalds 	    counter += per_cpu(sockets_in_use, cpu);
27201da177e4SLinus Torvalds 
27211da177e4SLinus Torvalds 	/* It can be negative, by the way. 8) */
27221da177e4SLinus Torvalds 	if (counter < 0)
27231da177e4SLinus Torvalds 		counter = 0;
27241da177e4SLinus Torvalds 
27251da177e4SLinus Torvalds 	seq_printf(seq, "sockets: used %d\n", counter);
27261da177e4SLinus Torvalds }
27271da177e4SLinus Torvalds #endif				/* CONFIG_PROC_FS */
27281da177e4SLinus Torvalds 
272989bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
27306b96018bSArnd Bergmann static int do_siocgstamp(struct net *net, struct socket *sock,
2731644595f8SH. Peter Anvin 			 unsigned int cmd, void __user *up)
27327a229387SArnd Bergmann {
27337a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
27347a229387SArnd Bergmann 	struct timeval ktv;
27357a229387SArnd Bergmann 	int err;
27367a229387SArnd Bergmann 
27377a229387SArnd Bergmann 	set_fs(KERNEL_DS);
27386b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv);
27397a229387SArnd Bergmann 	set_fs(old_fs);
2740644595f8SH. Peter Anvin 	if (!err)
2741ed6fe9d6SMikulas Patocka 		err = compat_put_timeval(&ktv, up);
2742644595f8SH. Peter Anvin 
27437a229387SArnd Bergmann 	return err;
27447a229387SArnd Bergmann }
27457a229387SArnd Bergmann 
27466b96018bSArnd Bergmann static int do_siocgstampns(struct net *net, struct socket *sock,
2747644595f8SH. Peter Anvin 			   unsigned int cmd, void __user *up)
27487a229387SArnd Bergmann {
27497a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
27507a229387SArnd Bergmann 	struct timespec kts;
27517a229387SArnd Bergmann 	int err;
27527a229387SArnd Bergmann 
27537a229387SArnd Bergmann 	set_fs(KERNEL_DS);
27546b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts);
27557a229387SArnd Bergmann 	set_fs(old_fs);
2756644595f8SH. Peter Anvin 	if (!err)
2757ed6fe9d6SMikulas Patocka 		err = compat_put_timespec(&kts, up);
2758644595f8SH. Peter Anvin 
27597a229387SArnd Bergmann 	return err;
27607a229387SArnd Bergmann }
27617a229387SArnd Bergmann 
27626b96018bSArnd Bergmann static int dev_ifname32(struct net *net, struct compat_ifreq __user *uifr32)
27637a229387SArnd Bergmann {
27647a229387SArnd Bergmann 	struct ifreq __user *uifr;
27657a229387SArnd Bergmann 	int err;
27667a229387SArnd Bergmann 
27677a229387SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(struct ifreq));
27686b96018bSArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
27697a229387SArnd Bergmann 		return -EFAULT;
27707a229387SArnd Bergmann 
27716b96018bSArnd Bergmann 	err = dev_ioctl(net, SIOCGIFNAME, uifr);
27727a229387SArnd Bergmann 	if (err)
27737a229387SArnd Bergmann 		return err;
27747a229387SArnd Bergmann 
27756b96018bSArnd Bergmann 	if (copy_in_user(uifr32, uifr, sizeof(struct compat_ifreq)))
27767a229387SArnd Bergmann 		return -EFAULT;
27777a229387SArnd Bergmann 
27787a229387SArnd Bergmann 	return 0;
27797a229387SArnd Bergmann }
27807a229387SArnd Bergmann 
27816b96018bSArnd Bergmann static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32)
27827a229387SArnd Bergmann {
27836b96018bSArnd Bergmann 	struct compat_ifconf ifc32;
27847a229387SArnd Bergmann 	struct ifconf ifc;
27857a229387SArnd Bergmann 	struct ifconf __user *uifc;
27866b96018bSArnd Bergmann 	struct compat_ifreq __user *ifr32;
27877a229387SArnd Bergmann 	struct ifreq __user *ifr;
27887a229387SArnd Bergmann 	unsigned int i, j;
27897a229387SArnd Bergmann 	int err;
27907a229387SArnd Bergmann 
27916b96018bSArnd Bergmann 	if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf)))
27927a229387SArnd Bergmann 		return -EFAULT;
27937a229387SArnd Bergmann 
279443da5f2eSMathias Krause 	memset(&ifc, 0, sizeof(ifc));
27957a229387SArnd Bergmann 	if (ifc32.ifcbuf == 0) {
27967a229387SArnd Bergmann 		ifc32.ifc_len = 0;
27977a229387SArnd Bergmann 		ifc.ifc_len = 0;
27987a229387SArnd Bergmann 		ifc.ifc_req = NULL;
27997a229387SArnd Bergmann 		uifc = compat_alloc_user_space(sizeof(struct ifconf));
28007a229387SArnd Bergmann 	} else {
28016b96018bSArnd Bergmann 		size_t len = ((ifc32.ifc_len / sizeof(struct compat_ifreq)) + 1) *
28027a229387SArnd Bergmann 			sizeof(struct ifreq);
28037a229387SArnd Bergmann 		uifc = compat_alloc_user_space(sizeof(struct ifconf) + len);
28047a229387SArnd Bergmann 		ifc.ifc_len = len;
28057a229387SArnd Bergmann 		ifr = ifc.ifc_req = (void __user *)(uifc + 1);
28067a229387SArnd Bergmann 		ifr32 = compat_ptr(ifc32.ifcbuf);
28076b96018bSArnd Bergmann 		for (i = 0; i < ifc32.ifc_len; i += sizeof(struct compat_ifreq)) {
28086b96018bSArnd Bergmann 			if (copy_in_user(ifr, ifr32, sizeof(struct compat_ifreq)))
28097a229387SArnd Bergmann 				return -EFAULT;
28107a229387SArnd Bergmann 			ifr++;
28117a229387SArnd Bergmann 			ifr32++;
28127a229387SArnd Bergmann 		}
28137a229387SArnd Bergmann 	}
28147a229387SArnd Bergmann 	if (copy_to_user(uifc, &ifc, sizeof(struct ifconf)))
28157a229387SArnd Bergmann 		return -EFAULT;
28167a229387SArnd Bergmann 
28176b96018bSArnd Bergmann 	err = dev_ioctl(net, SIOCGIFCONF, uifc);
28187a229387SArnd Bergmann 	if (err)
28197a229387SArnd Bergmann 		return err;
28207a229387SArnd Bergmann 
28217a229387SArnd Bergmann 	if (copy_from_user(&ifc, uifc, sizeof(struct ifconf)))
28227a229387SArnd Bergmann 		return -EFAULT;
28237a229387SArnd Bergmann 
28247a229387SArnd Bergmann 	ifr = ifc.ifc_req;
28257a229387SArnd Bergmann 	ifr32 = compat_ptr(ifc32.ifcbuf);
28267a229387SArnd Bergmann 	for (i = 0, j = 0;
28276b96018bSArnd Bergmann 	     i + sizeof(struct compat_ifreq) <= ifc32.ifc_len && j < ifc.ifc_len;
28286b96018bSArnd Bergmann 	     i += sizeof(struct compat_ifreq), j += sizeof(struct ifreq)) {
28296b96018bSArnd Bergmann 		if (copy_in_user(ifr32, ifr, sizeof(struct compat_ifreq)))
28307a229387SArnd Bergmann 			return -EFAULT;
28317a229387SArnd Bergmann 		ifr32++;
28327a229387SArnd Bergmann 		ifr++;
28337a229387SArnd Bergmann 	}
28347a229387SArnd Bergmann 
28357a229387SArnd Bergmann 	if (ifc32.ifcbuf == 0) {
28367a229387SArnd Bergmann 		/* Translate from 64-bit structure multiple to
28377a229387SArnd Bergmann 		 * a 32-bit one.
28387a229387SArnd Bergmann 		 */
28397a229387SArnd Bergmann 		i = ifc.ifc_len;
28406b96018bSArnd Bergmann 		i = ((i / sizeof(struct ifreq)) * sizeof(struct compat_ifreq));
28417a229387SArnd Bergmann 		ifc32.ifc_len = i;
28427a229387SArnd Bergmann 	} else {
28437a229387SArnd Bergmann 		ifc32.ifc_len = i;
28447a229387SArnd Bergmann 	}
28456b96018bSArnd Bergmann 	if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf)))
28467a229387SArnd Bergmann 		return -EFAULT;
28477a229387SArnd Bergmann 
28487a229387SArnd Bergmann 	return 0;
28497a229387SArnd Bergmann }
28507a229387SArnd Bergmann 
28516b96018bSArnd Bergmann static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
28527a229387SArnd Bergmann {
28533a7da39dSBen Hutchings 	struct compat_ethtool_rxnfc __user *compat_rxnfc;
28543a7da39dSBen Hutchings 	bool convert_in = false, convert_out = false;
28553a7da39dSBen Hutchings 	size_t buf_size = ALIGN(sizeof(struct ifreq), 8);
28563a7da39dSBen Hutchings 	struct ethtool_rxnfc __user *rxnfc;
28577a229387SArnd Bergmann 	struct ifreq __user *ifr;
28583a7da39dSBen Hutchings 	u32 rule_cnt = 0, actual_rule_cnt;
28593a7da39dSBen Hutchings 	u32 ethcmd;
28607a229387SArnd Bergmann 	u32 data;
28613a7da39dSBen Hutchings 	int ret;
28627a229387SArnd Bergmann 
28637a229387SArnd Bergmann 	if (get_user(data, &ifr32->ifr_ifru.ifru_data))
28647a229387SArnd Bergmann 		return -EFAULT;
28657a229387SArnd Bergmann 
28663a7da39dSBen Hutchings 	compat_rxnfc = compat_ptr(data);
28673a7da39dSBen Hutchings 
28683a7da39dSBen Hutchings 	if (get_user(ethcmd, &compat_rxnfc->cmd))
28697a229387SArnd Bergmann 		return -EFAULT;
28707a229387SArnd Bergmann 
28713a7da39dSBen Hutchings 	/* Most ethtool structures are defined without padding.
28723a7da39dSBen Hutchings 	 * Unfortunately struct ethtool_rxnfc is an exception.
28733a7da39dSBen Hutchings 	 */
28743a7da39dSBen Hutchings 	switch (ethcmd) {
28753a7da39dSBen Hutchings 	default:
28763a7da39dSBen Hutchings 		break;
28773a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLALL:
28783a7da39dSBen Hutchings 		/* Buffer size is variable */
28793a7da39dSBen Hutchings 		if (get_user(rule_cnt, &compat_rxnfc->rule_cnt))
28803a7da39dSBen Hutchings 			return -EFAULT;
28813a7da39dSBen Hutchings 		if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32))
28823a7da39dSBen Hutchings 			return -ENOMEM;
28833a7da39dSBen Hutchings 		buf_size += rule_cnt * sizeof(u32);
28843a7da39dSBen Hutchings 		/* fall through */
28853a7da39dSBen Hutchings 	case ETHTOOL_GRXRINGS:
28863a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLCNT:
28873a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRULE:
288855664f32SBen Hutchings 	case ETHTOOL_SRXCLSRLINS:
28893a7da39dSBen Hutchings 		convert_out = true;
28903a7da39dSBen Hutchings 		/* fall through */
28913a7da39dSBen Hutchings 	case ETHTOOL_SRXCLSRLDEL:
28923a7da39dSBen Hutchings 		buf_size += sizeof(struct ethtool_rxnfc);
28933a7da39dSBen Hutchings 		convert_in = true;
28943a7da39dSBen Hutchings 		break;
28953a7da39dSBen Hutchings 	}
28963a7da39dSBen Hutchings 
28973a7da39dSBen Hutchings 	ifr = compat_alloc_user_space(buf_size);
2898954b1244SStephen Hemminger 	rxnfc = (void __user *)ifr + ALIGN(sizeof(struct ifreq), 8);
28993a7da39dSBen Hutchings 
29003a7da39dSBen Hutchings 	if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
29013a7da39dSBen Hutchings 		return -EFAULT;
29023a7da39dSBen Hutchings 
29033a7da39dSBen Hutchings 	if (put_user(convert_in ? rxnfc : compat_ptr(data),
29043a7da39dSBen Hutchings 		     &ifr->ifr_ifru.ifru_data))
29053a7da39dSBen Hutchings 		return -EFAULT;
29063a7da39dSBen Hutchings 
29073a7da39dSBen Hutchings 	if (convert_in) {
2908127fe533SAlexander Duyck 		/* We expect there to be holes between fs.m_ext and
29093a7da39dSBen Hutchings 		 * fs.ring_cookie and at the end of fs, but nowhere else.
29103a7da39dSBen Hutchings 		 */
2911127fe533SAlexander Duyck 		BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_ext) +
2912127fe533SAlexander Duyck 			     sizeof(compat_rxnfc->fs.m_ext) !=
2913127fe533SAlexander Duyck 			     offsetof(struct ethtool_rxnfc, fs.m_ext) +
2914127fe533SAlexander Duyck 			     sizeof(rxnfc->fs.m_ext));
29153a7da39dSBen Hutchings 		BUILD_BUG_ON(
29163a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.location) -
29173a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) !=
29183a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.location) -
29193a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.ring_cookie));
29203a7da39dSBen Hutchings 
29213a7da39dSBen Hutchings 		if (copy_in_user(rxnfc, compat_rxnfc,
2922954b1244SStephen Hemminger 				 (void __user *)(&rxnfc->fs.m_ext + 1) -
2923954b1244SStephen Hemminger 				 (void __user *)rxnfc) ||
29243a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->fs.ring_cookie,
29253a7da39dSBen Hutchings 				 &compat_rxnfc->fs.ring_cookie,
2926954b1244SStephen Hemminger 				 (void __user *)(&rxnfc->fs.location + 1) -
2927954b1244SStephen Hemminger 				 (void __user *)&rxnfc->fs.ring_cookie) ||
29283a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt,
29293a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
29303a7da39dSBen Hutchings 			return -EFAULT;
29313a7da39dSBen Hutchings 	}
29323a7da39dSBen Hutchings 
29333a7da39dSBen Hutchings 	ret = dev_ioctl(net, SIOCETHTOOL, ifr);
29343a7da39dSBen Hutchings 	if (ret)
29353a7da39dSBen Hutchings 		return ret;
29363a7da39dSBen Hutchings 
29373a7da39dSBen Hutchings 	if (convert_out) {
29383a7da39dSBen Hutchings 		if (copy_in_user(compat_rxnfc, rxnfc,
2939954b1244SStephen Hemminger 				 (const void __user *)(&rxnfc->fs.m_ext + 1) -
2940954b1244SStephen Hemminger 				 (const void __user *)rxnfc) ||
29413a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->fs.ring_cookie,
29423a7da39dSBen Hutchings 				 &rxnfc->fs.ring_cookie,
2943954b1244SStephen Hemminger 				 (const void __user *)(&rxnfc->fs.location + 1) -
2944954b1244SStephen Hemminger 				 (const void __user *)&rxnfc->fs.ring_cookie) ||
29453a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt,
29463a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
29473a7da39dSBen Hutchings 			return -EFAULT;
29483a7da39dSBen Hutchings 
29493a7da39dSBen Hutchings 		if (ethcmd == ETHTOOL_GRXCLSRLALL) {
29503a7da39dSBen Hutchings 			/* As an optimisation, we only copy the actual
29513a7da39dSBen Hutchings 			 * number of rules that the underlying
29523a7da39dSBen Hutchings 			 * function returned.  Since Mallory might
29533a7da39dSBen Hutchings 			 * change the rule count in user memory, we
29543a7da39dSBen Hutchings 			 * check that it is less than the rule count
29553a7da39dSBen Hutchings 			 * originally given (as the user buffer size),
29563a7da39dSBen Hutchings 			 * which has been range-checked.
29573a7da39dSBen Hutchings 			 */
29583a7da39dSBen Hutchings 			if (get_user(actual_rule_cnt, &rxnfc->rule_cnt))
29593a7da39dSBen Hutchings 				return -EFAULT;
29603a7da39dSBen Hutchings 			if (actual_rule_cnt < rule_cnt)
29613a7da39dSBen Hutchings 				rule_cnt = actual_rule_cnt;
29623a7da39dSBen Hutchings 			if (copy_in_user(&compat_rxnfc->rule_locs[0],
29633a7da39dSBen Hutchings 					 &rxnfc->rule_locs[0],
29643a7da39dSBen Hutchings 					 rule_cnt * sizeof(u32)))
29653a7da39dSBen Hutchings 				return -EFAULT;
29663a7da39dSBen Hutchings 		}
29673a7da39dSBen Hutchings 	}
29683a7da39dSBen Hutchings 
29693a7da39dSBen Hutchings 	return 0;
29707a229387SArnd Bergmann }
29717a229387SArnd Bergmann 
29727a50a240SArnd Bergmann static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32)
29737a50a240SArnd Bergmann {
29747a50a240SArnd Bergmann 	void __user *uptr;
29757a50a240SArnd Bergmann 	compat_uptr_t uptr32;
29767a50a240SArnd Bergmann 	struct ifreq __user *uifr;
29777a50a240SArnd Bergmann 
29787a50a240SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
29797a50a240SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
29807a50a240SArnd Bergmann 		return -EFAULT;
29817a50a240SArnd Bergmann 
29827a50a240SArnd Bergmann 	if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu))
29837a50a240SArnd Bergmann 		return -EFAULT;
29847a50a240SArnd Bergmann 
29857a50a240SArnd Bergmann 	uptr = compat_ptr(uptr32);
29867a50a240SArnd Bergmann 
29877a50a240SArnd Bergmann 	if (put_user(uptr, &uifr->ifr_settings.ifs_ifsu.raw_hdlc))
29887a50a240SArnd Bergmann 		return -EFAULT;
29897a50a240SArnd Bergmann 
29907a50a240SArnd Bergmann 	return dev_ioctl(net, SIOCWANDEV, uifr);
29917a50a240SArnd Bergmann }
29927a50a240SArnd Bergmann 
29936b96018bSArnd Bergmann static int bond_ioctl(struct net *net, unsigned int cmd,
29946b96018bSArnd Bergmann 			 struct compat_ifreq __user *ifr32)
29957a229387SArnd Bergmann {
29967a229387SArnd Bergmann 	struct ifreq kifr;
29977a229387SArnd Bergmann 	mm_segment_t old_fs;
29987a229387SArnd Bergmann 	int err;
29997a229387SArnd Bergmann 
30007a229387SArnd Bergmann 	switch (cmd) {
30017a229387SArnd Bergmann 	case SIOCBONDENSLAVE:
30027a229387SArnd Bergmann 	case SIOCBONDRELEASE:
30037a229387SArnd Bergmann 	case SIOCBONDSETHWADDR:
30047a229387SArnd Bergmann 	case SIOCBONDCHANGEACTIVE:
30056b96018bSArnd Bergmann 		if (copy_from_user(&kifr, ifr32, sizeof(struct compat_ifreq)))
30067a229387SArnd Bergmann 			return -EFAULT;
30077a229387SArnd Bergmann 
30087a229387SArnd Bergmann 		old_fs = get_fs();
30097a229387SArnd Bergmann 		set_fs(KERNEL_DS);
3010c3f52ae6Sstephen hemminger 		err = dev_ioctl(net, cmd,
3011c3f52ae6Sstephen hemminger 				(struct ifreq __user __force *) &kifr);
30127a229387SArnd Bergmann 		set_fs(old_fs);
30137a229387SArnd Bergmann 
30147a229387SArnd Bergmann 		return err;
30157a229387SArnd Bergmann 	default:
301607d106d0SLinus Torvalds 		return -ENOIOCTLCMD;
3017ccbd6a5aSJoe Perches 	}
30187a229387SArnd Bergmann }
30197a229387SArnd Bergmann 
3020590d4693SBen Hutchings /* Handle ioctls that use ifreq::ifr_data and just need struct ifreq converted */
3021590d4693SBen Hutchings static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd,
30226b96018bSArnd Bergmann 				 struct compat_ifreq __user *u_ifreq32)
30237a229387SArnd Bergmann {
30247a229387SArnd Bergmann 	struct ifreq __user *u_ifreq64;
30257a229387SArnd Bergmann 	char tmp_buf[IFNAMSIZ];
30267a229387SArnd Bergmann 	void __user *data64;
30277a229387SArnd Bergmann 	u32 data32;
30287a229387SArnd Bergmann 
30297a229387SArnd Bergmann 	if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]),
30307a229387SArnd Bergmann 			   IFNAMSIZ))
30317a229387SArnd Bergmann 		return -EFAULT;
3032417c3522SBen Hutchings 	if (get_user(data32, &u_ifreq32->ifr_ifru.ifru_data))
30337a229387SArnd Bergmann 		return -EFAULT;
30347a229387SArnd Bergmann 	data64 = compat_ptr(data32);
30357a229387SArnd Bergmann 
30367a229387SArnd Bergmann 	u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
30377a229387SArnd Bergmann 
30387a229387SArnd Bergmann 	if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0],
30397a229387SArnd Bergmann 			 IFNAMSIZ))
30407a229387SArnd Bergmann 		return -EFAULT;
3041417c3522SBen Hutchings 	if (put_user(data64, &u_ifreq64->ifr_ifru.ifru_data))
30427a229387SArnd Bergmann 		return -EFAULT;
30437a229387SArnd Bergmann 
30446b96018bSArnd Bergmann 	return dev_ioctl(net, cmd, u_ifreq64);
30457a229387SArnd Bergmann }
30467a229387SArnd Bergmann 
30476b96018bSArnd Bergmann static int dev_ifsioc(struct net *net, struct socket *sock,
30486b96018bSArnd Bergmann 			 unsigned int cmd, struct compat_ifreq __user *uifr32)
30497a229387SArnd Bergmann {
3050a2116ed2SArnd Bergmann 	struct ifreq __user *uifr;
30517a229387SArnd Bergmann 	int err;
30527a229387SArnd Bergmann 
3053a2116ed2SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
3054a2116ed2SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(*uifr32)))
30557a229387SArnd Bergmann 		return -EFAULT;
3056a2116ed2SArnd Bergmann 
3057a2116ed2SArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr);
3058a2116ed2SArnd Bergmann 
30597a229387SArnd Bergmann 	if (!err) {
30607a229387SArnd Bergmann 		switch (cmd) {
30617a229387SArnd Bergmann 		case SIOCGIFFLAGS:
30627a229387SArnd Bergmann 		case SIOCGIFMETRIC:
30637a229387SArnd Bergmann 		case SIOCGIFMTU:
30647a229387SArnd Bergmann 		case SIOCGIFMEM:
30657a229387SArnd Bergmann 		case SIOCGIFHWADDR:
30667a229387SArnd Bergmann 		case SIOCGIFINDEX:
30677a229387SArnd Bergmann 		case SIOCGIFADDR:
30687a229387SArnd Bergmann 		case SIOCGIFBRDADDR:
30697a229387SArnd Bergmann 		case SIOCGIFDSTADDR:
30707a229387SArnd Bergmann 		case SIOCGIFNETMASK:
3071fab2532bSArnd Bergmann 		case SIOCGIFPFLAGS:
30727a229387SArnd Bergmann 		case SIOCGIFTXQLEN:
3073fab2532bSArnd Bergmann 		case SIOCGMIIPHY:
3074fab2532bSArnd Bergmann 		case SIOCGMIIREG:
3075a2116ed2SArnd Bergmann 			if (copy_in_user(uifr32, uifr, sizeof(*uifr32)))
3076a2116ed2SArnd Bergmann 				err = -EFAULT;
30777a229387SArnd Bergmann 			break;
3078a2116ed2SArnd Bergmann 		}
3079a2116ed2SArnd Bergmann 	}
3080a2116ed2SArnd Bergmann 	return err;
3081a2116ed2SArnd Bergmann }
3082a2116ed2SArnd Bergmann 
3083a2116ed2SArnd Bergmann static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
3084a2116ed2SArnd Bergmann 			struct compat_ifreq __user *uifr32)
3085a2116ed2SArnd Bergmann {
3086a2116ed2SArnd Bergmann 	struct ifreq ifr;
3087a2116ed2SArnd Bergmann 	struct compat_ifmap __user *uifmap32;
3088a2116ed2SArnd Bergmann 	mm_segment_t old_fs;
3089a2116ed2SArnd Bergmann 	int err;
3090a2116ed2SArnd Bergmann 
3091a2116ed2SArnd Bergmann 	uifmap32 = &uifr32->ifr_ifru.ifru_map;
3092a2116ed2SArnd Bergmann 	err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name));
30933ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
30943ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
30953ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
30963ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.irq, &uifmap32->irq);
30973ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.dma, &uifmap32->dma);
30983ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.port, &uifmap32->port);
3099a2116ed2SArnd Bergmann 	if (err)
3100a2116ed2SArnd Bergmann 		return -EFAULT;
3101a2116ed2SArnd Bergmann 
3102a2116ed2SArnd Bergmann 	old_fs = get_fs();
3103a2116ed2SArnd Bergmann 	set_fs(KERNEL_DS);
3104c3f52ae6Sstephen hemminger 	err = dev_ioctl(net, cmd, (void  __user __force *)&ifr);
3105a2116ed2SArnd Bergmann 	set_fs(old_fs);
3106a2116ed2SArnd Bergmann 
3107a2116ed2SArnd Bergmann 	if (cmd == SIOCGIFMAP && !err) {
31087a229387SArnd Bergmann 		err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name));
31093ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
31103ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
31113ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
31123ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.irq, &uifmap32->irq);
31133ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.dma, &uifmap32->dma);
31143ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.port, &uifmap32->port);
31157a229387SArnd Bergmann 		if (err)
31167a229387SArnd Bergmann 			err = -EFAULT;
31177a229387SArnd Bergmann 	}
31187a229387SArnd Bergmann 	return err;
31197a229387SArnd Bergmann }
31207a229387SArnd Bergmann 
31217a229387SArnd Bergmann struct rtentry32 {
31227a229387SArnd Bergmann 	u32		rt_pad1;
31237a229387SArnd Bergmann 	struct sockaddr rt_dst;         /* target address               */
31247a229387SArnd Bergmann 	struct sockaddr rt_gateway;     /* gateway addr (RTF_GATEWAY)   */
31257a229387SArnd Bergmann 	struct sockaddr rt_genmask;     /* target network mask (IP)     */
31267a229387SArnd Bergmann 	unsigned short	rt_flags;
31277a229387SArnd Bergmann 	short		rt_pad2;
31287a229387SArnd Bergmann 	u32		rt_pad3;
31297a229387SArnd Bergmann 	unsigned char	rt_tos;
31307a229387SArnd Bergmann 	unsigned char	rt_class;
31317a229387SArnd Bergmann 	short		rt_pad4;
31327a229387SArnd Bergmann 	short		rt_metric;      /* +1 for binary compatibility! */
31337a229387SArnd Bergmann 	/* char * */ u32 rt_dev;        /* forcing the device at add    */
31347a229387SArnd Bergmann 	u32		rt_mtu;         /* per route MTU/Window         */
31357a229387SArnd Bergmann 	u32		rt_window;      /* Window clamping              */
31367a229387SArnd Bergmann 	unsigned short  rt_irtt;        /* Initial RTT                  */
31377a229387SArnd Bergmann };
31387a229387SArnd Bergmann 
31397a229387SArnd Bergmann struct in6_rtmsg32 {
31407a229387SArnd Bergmann 	struct in6_addr		rtmsg_dst;
31417a229387SArnd Bergmann 	struct in6_addr		rtmsg_src;
31427a229387SArnd Bergmann 	struct in6_addr		rtmsg_gateway;
31437a229387SArnd Bergmann 	u32			rtmsg_type;
31447a229387SArnd Bergmann 	u16			rtmsg_dst_len;
31457a229387SArnd Bergmann 	u16			rtmsg_src_len;
31467a229387SArnd Bergmann 	u32			rtmsg_metric;
31477a229387SArnd Bergmann 	u32			rtmsg_info;
31487a229387SArnd Bergmann 	u32			rtmsg_flags;
31497a229387SArnd Bergmann 	s32			rtmsg_ifindex;
31507a229387SArnd Bergmann };
31517a229387SArnd Bergmann 
31526b96018bSArnd Bergmann static int routing_ioctl(struct net *net, struct socket *sock,
31536b96018bSArnd Bergmann 			 unsigned int cmd, void __user *argp)
31547a229387SArnd Bergmann {
31557a229387SArnd Bergmann 	int ret;
31567a229387SArnd Bergmann 	void *r = NULL;
31577a229387SArnd Bergmann 	struct in6_rtmsg r6;
31587a229387SArnd Bergmann 	struct rtentry r4;
31597a229387SArnd Bergmann 	char devname[16];
31607a229387SArnd Bergmann 	u32 rtdev;
31617a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
31627a229387SArnd Bergmann 
31636b96018bSArnd Bergmann 	if (sock && sock->sk && sock->sk->sk_family == AF_INET6) { /* ipv6 */
31646b96018bSArnd Bergmann 		struct in6_rtmsg32 __user *ur6 = argp;
31657a229387SArnd Bergmann 		ret = copy_from_user(&r6.rtmsg_dst, &(ur6->rtmsg_dst),
31667a229387SArnd Bergmann 			3 * sizeof(struct in6_addr));
31673ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_type, &(ur6->rtmsg_type));
31683ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len));
31693ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_src_len, &(ur6->rtmsg_src_len));
31703ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_metric, &(ur6->rtmsg_metric));
31713ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_info, &(ur6->rtmsg_info));
31723ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_flags, &(ur6->rtmsg_flags));
31733ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex));
31747a229387SArnd Bergmann 
31757a229387SArnd Bergmann 		r = (void *) &r6;
31767a229387SArnd Bergmann 	} else { /* ipv4 */
31776b96018bSArnd Bergmann 		struct rtentry32 __user *ur4 = argp;
31787a229387SArnd Bergmann 		ret = copy_from_user(&r4.rt_dst, &(ur4->rt_dst),
31797a229387SArnd Bergmann 					3 * sizeof(struct sockaddr));
31803ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_flags, &(ur4->rt_flags));
31813ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_metric, &(ur4->rt_metric));
31823ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_mtu, &(ur4->rt_mtu));
31833ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_window, &(ur4->rt_window));
31843ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_irtt, &(ur4->rt_irtt));
31853ddc5b46SMathieu Desnoyers 		ret |= get_user(rtdev, &(ur4->rt_dev));
31867a229387SArnd Bergmann 		if (rtdev) {
31877a229387SArnd Bergmann 			ret |= copy_from_user(devname, compat_ptr(rtdev), 15);
3188c3f52ae6Sstephen hemminger 			r4.rt_dev = (char __user __force *)devname;
3189c3f52ae6Sstephen hemminger 			devname[15] = 0;
31907a229387SArnd Bergmann 		} else
31917a229387SArnd Bergmann 			r4.rt_dev = NULL;
31927a229387SArnd Bergmann 
31937a229387SArnd Bergmann 		r = (void *) &r4;
31947a229387SArnd Bergmann 	}
31957a229387SArnd Bergmann 
31967a229387SArnd Bergmann 	if (ret) {
31977a229387SArnd Bergmann 		ret = -EFAULT;
31987a229387SArnd Bergmann 		goto out;
31997a229387SArnd Bergmann 	}
32007a229387SArnd Bergmann 
32017a229387SArnd Bergmann 	set_fs(KERNEL_DS);
32026b96018bSArnd Bergmann 	ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r);
32037a229387SArnd Bergmann 	set_fs(old_fs);
32047a229387SArnd Bergmann 
32057a229387SArnd Bergmann out:
32067a229387SArnd Bergmann 	return ret;
32077a229387SArnd Bergmann }
32087a229387SArnd Bergmann 
32097a229387SArnd Bergmann /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE
32107a229387SArnd Bergmann  * for some operations; this forces use of the newer bridge-utils that
321125985edcSLucas De Marchi  * use compatible ioctls
32127a229387SArnd Bergmann  */
32136b96018bSArnd Bergmann static int old_bridge_ioctl(compat_ulong_t __user *argp)
32147a229387SArnd Bergmann {
32156b96018bSArnd Bergmann 	compat_ulong_t tmp;
32167a229387SArnd Bergmann 
32176b96018bSArnd Bergmann 	if (get_user(tmp, argp))
32187a229387SArnd Bergmann 		return -EFAULT;
32197a229387SArnd Bergmann 	if (tmp == BRCTL_GET_VERSION)
32207a229387SArnd Bergmann 		return BRCTL_VERSION + 1;
32217a229387SArnd Bergmann 	return -EINVAL;
32227a229387SArnd Bergmann }
32237a229387SArnd Bergmann 
32246b96018bSArnd Bergmann static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
32256b96018bSArnd Bergmann 			 unsigned int cmd, unsigned long arg)
32266b96018bSArnd Bergmann {
32276b96018bSArnd Bergmann 	void __user *argp = compat_ptr(arg);
32286b96018bSArnd Bergmann 	struct sock *sk = sock->sk;
32296b96018bSArnd Bergmann 	struct net *net = sock_net(sk);
32307a229387SArnd Bergmann 
32316b96018bSArnd Bergmann 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
3232590d4693SBen Hutchings 		return compat_ifr_data_ioctl(net, cmd, argp);
32337a229387SArnd Bergmann 
32346b96018bSArnd Bergmann 	switch (cmd) {
32356b96018bSArnd Bergmann 	case SIOCSIFBR:
32366b96018bSArnd Bergmann 	case SIOCGIFBR:
32376b96018bSArnd Bergmann 		return old_bridge_ioctl(argp);
32386b96018bSArnd Bergmann 	case SIOCGIFNAME:
32396b96018bSArnd Bergmann 		return dev_ifname32(net, argp);
32406b96018bSArnd Bergmann 	case SIOCGIFCONF:
32416b96018bSArnd Bergmann 		return dev_ifconf(net, argp);
32426b96018bSArnd Bergmann 	case SIOCETHTOOL:
32436b96018bSArnd Bergmann 		return ethtool_ioctl(net, argp);
32447a50a240SArnd Bergmann 	case SIOCWANDEV:
32457a50a240SArnd Bergmann 		return compat_siocwandev(net, argp);
3246a2116ed2SArnd Bergmann 	case SIOCGIFMAP:
3247a2116ed2SArnd Bergmann 	case SIOCSIFMAP:
3248a2116ed2SArnd Bergmann 		return compat_sioc_ifmap(net, cmd, argp);
32496b96018bSArnd Bergmann 	case SIOCBONDENSLAVE:
32506b96018bSArnd Bergmann 	case SIOCBONDRELEASE:
32516b96018bSArnd Bergmann 	case SIOCBONDSETHWADDR:
32526b96018bSArnd Bergmann 	case SIOCBONDCHANGEACTIVE:
32536b96018bSArnd Bergmann 		return bond_ioctl(net, cmd, argp);
32546b96018bSArnd Bergmann 	case SIOCADDRT:
32556b96018bSArnd Bergmann 	case SIOCDELRT:
32566b96018bSArnd Bergmann 		return routing_ioctl(net, sock, cmd, argp);
32576b96018bSArnd Bergmann 	case SIOCGSTAMP:
32586b96018bSArnd Bergmann 		return do_siocgstamp(net, sock, cmd, argp);
32596b96018bSArnd Bergmann 	case SIOCGSTAMPNS:
32606b96018bSArnd Bergmann 		return do_siocgstampns(net, sock, cmd, argp);
3261590d4693SBen Hutchings 	case SIOCBONDSLAVEINFOQUERY:
3262590d4693SBen Hutchings 	case SIOCBONDINFOQUERY:
3263a2116ed2SArnd Bergmann 	case SIOCSHWTSTAMP:
3264fd468c74SBen Hutchings 	case SIOCGHWTSTAMP:
3265590d4693SBen Hutchings 		return compat_ifr_data_ioctl(net, cmd, argp);
32667a229387SArnd Bergmann 
32676b96018bSArnd Bergmann 	case FIOSETOWN:
32686b96018bSArnd Bergmann 	case SIOCSPGRP:
32696b96018bSArnd Bergmann 	case FIOGETOWN:
32706b96018bSArnd Bergmann 	case SIOCGPGRP:
32716b96018bSArnd Bergmann 	case SIOCBRADDBR:
32726b96018bSArnd Bergmann 	case SIOCBRDELBR:
32736b96018bSArnd Bergmann 	case SIOCGIFVLAN:
32746b96018bSArnd Bergmann 	case SIOCSIFVLAN:
32756b96018bSArnd Bergmann 	case SIOCADDDLCI:
32766b96018bSArnd Bergmann 	case SIOCDELDLCI:
32776b96018bSArnd Bergmann 		return sock_ioctl(file, cmd, arg);
32786b96018bSArnd Bergmann 
32796b96018bSArnd Bergmann 	case SIOCGIFFLAGS:
32806b96018bSArnd Bergmann 	case SIOCSIFFLAGS:
32816b96018bSArnd Bergmann 	case SIOCGIFMETRIC:
32826b96018bSArnd Bergmann 	case SIOCSIFMETRIC:
32836b96018bSArnd Bergmann 	case SIOCGIFMTU:
32846b96018bSArnd Bergmann 	case SIOCSIFMTU:
32856b96018bSArnd Bergmann 	case SIOCGIFMEM:
32866b96018bSArnd Bergmann 	case SIOCSIFMEM:
32876b96018bSArnd Bergmann 	case SIOCGIFHWADDR:
32886b96018bSArnd Bergmann 	case SIOCSIFHWADDR:
32896b96018bSArnd Bergmann 	case SIOCADDMULTI:
32906b96018bSArnd Bergmann 	case SIOCDELMULTI:
32916b96018bSArnd Bergmann 	case SIOCGIFINDEX:
32926b96018bSArnd Bergmann 	case SIOCGIFADDR:
32936b96018bSArnd Bergmann 	case SIOCSIFADDR:
32946b96018bSArnd Bergmann 	case SIOCSIFHWBROADCAST:
32956b96018bSArnd Bergmann 	case SIOCDIFADDR:
32966b96018bSArnd Bergmann 	case SIOCGIFBRDADDR:
32976b96018bSArnd Bergmann 	case SIOCSIFBRDADDR:
32986b96018bSArnd Bergmann 	case SIOCGIFDSTADDR:
32996b96018bSArnd Bergmann 	case SIOCSIFDSTADDR:
33006b96018bSArnd Bergmann 	case SIOCGIFNETMASK:
33016b96018bSArnd Bergmann 	case SIOCSIFNETMASK:
33026b96018bSArnd Bergmann 	case SIOCSIFPFLAGS:
33036b96018bSArnd Bergmann 	case SIOCGIFPFLAGS:
33046b96018bSArnd Bergmann 	case SIOCGIFTXQLEN:
33056b96018bSArnd Bergmann 	case SIOCSIFTXQLEN:
33066b96018bSArnd Bergmann 	case SIOCBRADDIF:
33076b96018bSArnd Bergmann 	case SIOCBRDELIF:
33089177efd3SArnd Bergmann 	case SIOCSIFNAME:
33099177efd3SArnd Bergmann 	case SIOCGMIIPHY:
33109177efd3SArnd Bergmann 	case SIOCGMIIREG:
33119177efd3SArnd Bergmann 	case SIOCSMIIREG:
33126b96018bSArnd Bergmann 		return dev_ifsioc(net, sock, cmd, argp);
33139177efd3SArnd Bergmann 
33146b96018bSArnd Bergmann 	case SIOCSARP:
33156b96018bSArnd Bergmann 	case SIOCGARP:
33166b96018bSArnd Bergmann 	case SIOCDARP:
33176b96018bSArnd Bergmann 	case SIOCATMARK:
33189177efd3SArnd Bergmann 		return sock_do_ioctl(net, sock, cmd, arg);
33199177efd3SArnd Bergmann 	}
33209177efd3SArnd Bergmann 
33216b96018bSArnd Bergmann 	return -ENOIOCTLCMD;
33226b96018bSArnd Bergmann }
33237a229387SArnd Bergmann 
332495c96174SEric Dumazet static long compat_sock_ioctl(struct file *file, unsigned int cmd,
332589bbfc95SShaun Pereira 			      unsigned long arg)
332689bbfc95SShaun Pereira {
332789bbfc95SShaun Pereira 	struct socket *sock = file->private_data;
332889bbfc95SShaun Pereira 	int ret = -ENOIOCTLCMD;
332987de87d5SDavid S. Miller 	struct sock *sk;
333087de87d5SDavid S. Miller 	struct net *net;
333187de87d5SDavid S. Miller 
333287de87d5SDavid S. Miller 	sk = sock->sk;
333387de87d5SDavid S. Miller 	net = sock_net(sk);
333489bbfc95SShaun Pereira 
333589bbfc95SShaun Pereira 	if (sock->ops->compat_ioctl)
333689bbfc95SShaun Pereira 		ret = sock->ops->compat_ioctl(sock, cmd, arg);
333789bbfc95SShaun Pereira 
333887de87d5SDavid S. Miller 	if (ret == -ENOIOCTLCMD &&
333987de87d5SDavid S. Miller 	    (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST))
334087de87d5SDavid S. Miller 		ret = compat_wext_handle_ioctl(net, cmd, arg);
334187de87d5SDavid S. Miller 
33426b96018bSArnd Bergmann 	if (ret == -ENOIOCTLCMD)
33436b96018bSArnd Bergmann 		ret = compat_sock_ioctl_trans(file, sock, cmd, arg);
33446b96018bSArnd Bergmann 
334589bbfc95SShaun Pereira 	return ret;
334689bbfc95SShaun Pereira }
334789bbfc95SShaun Pereira #endif
334889bbfc95SShaun Pereira 
3349ac5a488eSSridhar Samudrala int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
3350ac5a488eSSridhar Samudrala {
3351ac5a488eSSridhar Samudrala 	return sock->ops->bind(sock, addr, addrlen);
3352ac5a488eSSridhar Samudrala }
3353c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_bind);
3354ac5a488eSSridhar Samudrala 
3355ac5a488eSSridhar Samudrala int kernel_listen(struct socket *sock, int backlog)
3356ac5a488eSSridhar Samudrala {
3357ac5a488eSSridhar Samudrala 	return sock->ops->listen(sock, backlog);
3358ac5a488eSSridhar Samudrala }
3359c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_listen);
3360ac5a488eSSridhar Samudrala 
3361ac5a488eSSridhar Samudrala int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
3362ac5a488eSSridhar Samudrala {
3363ac5a488eSSridhar Samudrala 	struct sock *sk = sock->sk;
3364ac5a488eSSridhar Samudrala 	int err;
3365ac5a488eSSridhar Samudrala 
3366ac5a488eSSridhar Samudrala 	err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
3367ac5a488eSSridhar Samudrala 			       newsock);
3368ac5a488eSSridhar Samudrala 	if (err < 0)
3369ac5a488eSSridhar Samudrala 		goto done;
3370ac5a488eSSridhar Samudrala 
3371ac5a488eSSridhar Samudrala 	err = sock->ops->accept(sock, *newsock, flags);
3372ac5a488eSSridhar Samudrala 	if (err < 0) {
3373ac5a488eSSridhar Samudrala 		sock_release(*newsock);
3374fa8705b0STony Battersby 		*newsock = NULL;
3375ac5a488eSSridhar Samudrala 		goto done;
3376ac5a488eSSridhar Samudrala 	}
3377ac5a488eSSridhar Samudrala 
3378ac5a488eSSridhar Samudrala 	(*newsock)->ops = sock->ops;
33791b08534eSWei Yongjun 	__module_get((*newsock)->ops->owner);
3380ac5a488eSSridhar Samudrala 
3381ac5a488eSSridhar Samudrala done:
3382ac5a488eSSridhar Samudrala 	return err;
3383ac5a488eSSridhar Samudrala }
3384c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_accept);
3385ac5a488eSSridhar Samudrala 
3386ac5a488eSSridhar Samudrala int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
3387ac5a488eSSridhar Samudrala 		   int flags)
3388ac5a488eSSridhar Samudrala {
3389ac5a488eSSridhar Samudrala 	return sock->ops->connect(sock, addr, addrlen, flags);
3390ac5a488eSSridhar Samudrala }
3391c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_connect);
3392ac5a488eSSridhar Samudrala 
3393ac5a488eSSridhar Samudrala int kernel_getsockname(struct socket *sock, struct sockaddr *addr,
3394ac5a488eSSridhar Samudrala 			 int *addrlen)
3395ac5a488eSSridhar Samudrala {
3396ac5a488eSSridhar Samudrala 	return sock->ops->getname(sock, addr, addrlen, 0);
3397ac5a488eSSridhar Samudrala }
3398c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockname);
3399ac5a488eSSridhar Samudrala 
3400ac5a488eSSridhar Samudrala int kernel_getpeername(struct socket *sock, struct sockaddr *addr,
3401ac5a488eSSridhar Samudrala 			 int *addrlen)
3402ac5a488eSSridhar Samudrala {
3403ac5a488eSSridhar Samudrala 	return sock->ops->getname(sock, addr, addrlen, 1);
3404ac5a488eSSridhar Samudrala }
3405c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getpeername);
3406ac5a488eSSridhar Samudrala 
3407ac5a488eSSridhar Samudrala int kernel_getsockopt(struct socket *sock, int level, int optname,
3408ac5a488eSSridhar Samudrala 			char *optval, int *optlen)
3409ac5a488eSSridhar Samudrala {
3410ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3411fb8621bbSNamhyung Kim 	char __user *uoptval;
3412fb8621bbSNamhyung Kim 	int __user *uoptlen;
3413ac5a488eSSridhar Samudrala 	int err;
3414ac5a488eSSridhar Samudrala 
3415fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3416fb8621bbSNamhyung Kim 	uoptlen = (int __user __force *) optlen;
3417fb8621bbSNamhyung Kim 
3418ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3419ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3420fb8621bbSNamhyung Kim 		err = sock_getsockopt(sock, level, optname, uoptval, uoptlen);
3421ac5a488eSSridhar Samudrala 	else
3422fb8621bbSNamhyung Kim 		err = sock->ops->getsockopt(sock, level, optname, uoptval,
3423fb8621bbSNamhyung Kim 					    uoptlen);
3424ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3425ac5a488eSSridhar Samudrala 	return err;
3426ac5a488eSSridhar Samudrala }
3427c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockopt);
3428ac5a488eSSridhar Samudrala 
3429ac5a488eSSridhar Samudrala int kernel_setsockopt(struct socket *sock, int level, int optname,
3430b7058842SDavid S. Miller 			char *optval, unsigned int optlen)
3431ac5a488eSSridhar Samudrala {
3432ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3433fb8621bbSNamhyung Kim 	char __user *uoptval;
3434ac5a488eSSridhar Samudrala 	int err;
3435ac5a488eSSridhar Samudrala 
3436fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3437fb8621bbSNamhyung Kim 
3438ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3439ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3440fb8621bbSNamhyung Kim 		err = sock_setsockopt(sock, level, optname, uoptval, optlen);
3441ac5a488eSSridhar Samudrala 	else
3442fb8621bbSNamhyung Kim 		err = sock->ops->setsockopt(sock, level, optname, uoptval,
3443ac5a488eSSridhar Samudrala 					    optlen);
3444ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3445ac5a488eSSridhar Samudrala 	return err;
3446ac5a488eSSridhar Samudrala }
3447c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_setsockopt);
3448ac5a488eSSridhar Samudrala 
3449ac5a488eSSridhar Samudrala int kernel_sendpage(struct socket *sock, struct page *page, int offset,
3450ac5a488eSSridhar Samudrala 		    size_t size, int flags)
3451ac5a488eSSridhar Samudrala {
3452ac5a488eSSridhar Samudrala 	if (sock->ops->sendpage)
3453ac5a488eSSridhar Samudrala 		return sock->ops->sendpage(sock, page, offset, size, flags);
3454ac5a488eSSridhar Samudrala 
3455ac5a488eSSridhar Samudrala 	return sock_no_sendpage(sock, page, offset, size, flags);
3456ac5a488eSSridhar Samudrala }
3457c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendpage);
3458ac5a488eSSridhar Samudrala 
3459ac5a488eSSridhar Samudrala int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg)
3460ac5a488eSSridhar Samudrala {
3461ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3462ac5a488eSSridhar Samudrala 	int err;
3463ac5a488eSSridhar Samudrala 
3464ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3465ac5a488eSSridhar Samudrala 	err = sock->ops->ioctl(sock, cmd, arg);
3466ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3467ac5a488eSSridhar Samudrala 
3468ac5a488eSSridhar Samudrala 	return err;
3469ac5a488eSSridhar Samudrala }
3470c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sock_ioctl);
3471ac5a488eSSridhar Samudrala 
347291cf45f0STrond Myklebust int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
347391cf45f0STrond Myklebust {
347491cf45f0STrond Myklebust 	return sock->ops->shutdown(sock, how);
347591cf45f0STrond Myklebust }
347691cf45f0STrond Myklebust EXPORT_SYMBOL(kernel_sock_shutdown);
3477