xref: /openbmc/linux/net/socket.c (revision 9f138fa6)
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 
937c0f6ba6SLinus Torvalds #include <linux/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 
1168ae5e030SAl Viro static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to);
1178ae5e030SAl Viro static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from);
1181da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma);
1191da177e4SLinus Torvalds 
1201da177e4SLinus Torvalds static int sock_close(struct inode *inode, struct file *file);
1211da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file,
1221da177e4SLinus Torvalds 			      struct poll_table_struct *wait);
12389bddce5SStephen Hemminger static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
12489bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
12589bbfc95SShaun Pereira static long compat_sock_ioctl(struct file *file,
12689bbfc95SShaun Pereira 			      unsigned int cmd, unsigned long arg);
12789bbfc95SShaun Pereira #endif
1281da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on);
1291da177e4SLinus Torvalds static ssize_t sock_sendpage(struct file *file, struct page *page,
1301da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more);
1319c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
1329c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
1339c55e01cSJens Axboe 				unsigned int flags);
1341da177e4SLinus Torvalds 
1351da177e4SLinus Torvalds /*
1361da177e4SLinus Torvalds  *	Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
1371da177e4SLinus Torvalds  *	in the operation structures but are done directly via the socketcall() multiplexor.
1381da177e4SLinus Torvalds  */
1391da177e4SLinus Torvalds 
140da7071d7SArjan van de Ven static const struct file_operations socket_file_ops = {
1411da177e4SLinus Torvalds 	.owner =	THIS_MODULE,
1421da177e4SLinus Torvalds 	.llseek =	no_llseek,
1438ae5e030SAl Viro 	.read_iter =	sock_read_iter,
1448ae5e030SAl Viro 	.write_iter =	sock_write_iter,
1451da177e4SLinus Torvalds 	.poll =		sock_poll,
1461da177e4SLinus Torvalds 	.unlocked_ioctl = sock_ioctl,
14789bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
14889bbfc95SShaun Pereira 	.compat_ioctl = compat_sock_ioctl,
14989bbfc95SShaun Pereira #endif
1501da177e4SLinus Torvalds 	.mmap =		sock_mmap,
1511da177e4SLinus Torvalds 	.release =	sock_close,
1521da177e4SLinus Torvalds 	.fasync =	sock_fasync,
1535274f052SJens Axboe 	.sendpage =	sock_sendpage,
1545274f052SJens Axboe 	.splice_write = generic_splice_sendpage,
1559c55e01cSJens Axboe 	.splice_read =	sock_splice_read,
1561da177e4SLinus Torvalds };
1571da177e4SLinus Torvalds 
1581da177e4SLinus Torvalds /*
1591da177e4SLinus Torvalds  *	The protocol list. Each protocol is registered in here.
1601da177e4SLinus Torvalds  */
1611da177e4SLinus Torvalds 
1621da177e4SLinus Torvalds static DEFINE_SPINLOCK(net_family_lock);
163190683a9SEric Dumazet static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly;
1641da177e4SLinus Torvalds 
1651da177e4SLinus Torvalds /*
1661da177e4SLinus Torvalds  *	Statistics counters of the socket lists
1671da177e4SLinus Torvalds  */
1681da177e4SLinus Torvalds 
169c6d409cfSEric Dumazet static DEFINE_PER_CPU(int, sockets_in_use);
1701da177e4SLinus Torvalds 
1711da177e4SLinus Torvalds /*
17289bddce5SStephen Hemminger  * Support routines.
17389bddce5SStephen Hemminger  * Move socket addresses back and forth across the kernel/user
1741da177e4SLinus Torvalds  * divide and look after the messy bits.
1751da177e4SLinus Torvalds  */
1761da177e4SLinus Torvalds 
1771da177e4SLinus Torvalds /**
1781da177e4SLinus Torvalds  *	move_addr_to_kernel	-	copy a socket address into kernel space
1791da177e4SLinus Torvalds  *	@uaddr: Address in user space
1801da177e4SLinus Torvalds  *	@kaddr: Address in kernel space
1811da177e4SLinus Torvalds  *	@ulen: Length in user space
1821da177e4SLinus Torvalds  *
1831da177e4SLinus Torvalds  *	The address is copied into kernel space. If the provided address is
1841da177e4SLinus Torvalds  *	too long an error code of -EINVAL is returned. If the copy gives
1851da177e4SLinus Torvalds  *	invalid addresses -EFAULT is returned. On a success 0 is returned.
1861da177e4SLinus Torvalds  */
1871da177e4SLinus Torvalds 
18843db362dSMaciej Żenczykowski int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr)
1891da177e4SLinus Torvalds {
190230b1839SYOSHIFUJI Hideaki 	if (ulen < 0 || ulen > sizeof(struct sockaddr_storage))
1911da177e4SLinus Torvalds 		return -EINVAL;
1921da177e4SLinus Torvalds 	if (ulen == 0)
1931da177e4SLinus Torvalds 		return 0;
1941da177e4SLinus Torvalds 	if (copy_from_user(kaddr, uaddr, ulen))
1951da177e4SLinus Torvalds 		return -EFAULT;
1963ec3b2fbSDavid Woodhouse 	return audit_sockaddr(ulen, kaddr);
1971da177e4SLinus Torvalds }
1981da177e4SLinus Torvalds 
1991da177e4SLinus Torvalds /**
2001da177e4SLinus Torvalds  *	move_addr_to_user	-	copy an address to user space
2011da177e4SLinus Torvalds  *	@kaddr: kernel space address
2021da177e4SLinus Torvalds  *	@klen: length of address in kernel
2031da177e4SLinus Torvalds  *	@uaddr: user space address
2041da177e4SLinus Torvalds  *	@ulen: pointer to user length field
2051da177e4SLinus Torvalds  *
2061da177e4SLinus Torvalds  *	The value pointed to by ulen on entry is the buffer length available.
2071da177e4SLinus Torvalds  *	This is overwritten with the buffer space used. -EINVAL is returned
2081da177e4SLinus Torvalds  *	if an overlong buffer is specified or a negative buffer size. -EFAULT
2091da177e4SLinus Torvalds  *	is returned if either the buffer or the length field are not
2101da177e4SLinus Torvalds  *	accessible.
2111da177e4SLinus Torvalds  *	After copying the data up to the limit the user specifies, the true
2121da177e4SLinus Torvalds  *	length of the data is written over the length limit the user
2131da177e4SLinus Torvalds  *	specified. Zero is returned for a success.
2141da177e4SLinus Torvalds  */
2151da177e4SLinus Torvalds 
21643db362dSMaciej Żenczykowski static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen,
21711165f14Sstephen hemminger 			     void __user *uaddr, int __user *ulen)
2181da177e4SLinus Torvalds {
2191da177e4SLinus Torvalds 	int err;
2201da177e4SLinus Torvalds 	int len;
2211da177e4SLinus Torvalds 
22268c6beb3SHannes Frederic Sowa 	BUG_ON(klen > sizeof(struct sockaddr_storage));
22389bddce5SStephen Hemminger 	err = get_user(len, ulen);
22489bddce5SStephen Hemminger 	if (err)
2251da177e4SLinus Torvalds 		return err;
2261da177e4SLinus Torvalds 	if (len > klen)
2271da177e4SLinus Torvalds 		len = klen;
22868c6beb3SHannes Frederic Sowa 	if (len < 0)
2291da177e4SLinus Torvalds 		return -EINVAL;
23089bddce5SStephen Hemminger 	if (len) {
231d6fe3945SSteve Grubb 		if (audit_sockaddr(klen, kaddr))
232d6fe3945SSteve Grubb 			return -ENOMEM;
2331da177e4SLinus Torvalds 		if (copy_to_user(uaddr, kaddr, len))
2341da177e4SLinus Torvalds 			return -EFAULT;
2351da177e4SLinus Torvalds 	}
2361da177e4SLinus Torvalds 	/*
2371da177e4SLinus Torvalds 	 *      "fromlen shall refer to the value before truncation.."
2381da177e4SLinus Torvalds 	 *                      1003.1g
2391da177e4SLinus Torvalds 	 */
2401da177e4SLinus Torvalds 	return __put_user(klen, ulen);
2411da177e4SLinus Torvalds }
2421da177e4SLinus Torvalds 
243e18b890bSChristoph Lameter static struct kmem_cache *sock_inode_cachep __read_mostly;
2441da177e4SLinus Torvalds 
2451da177e4SLinus Torvalds static struct inode *sock_alloc_inode(struct super_block *sb)
2461da177e4SLinus Torvalds {
2471da177e4SLinus Torvalds 	struct socket_alloc *ei;
248eaefd110SEric Dumazet 	struct socket_wq *wq;
24989bddce5SStephen Hemminger 
250e94b1766SChristoph Lameter 	ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL);
2511da177e4SLinus Torvalds 	if (!ei)
2521da177e4SLinus Torvalds 		return NULL;
253eaefd110SEric Dumazet 	wq = kmalloc(sizeof(*wq), GFP_KERNEL);
254eaefd110SEric Dumazet 	if (!wq) {
25543815482SEric Dumazet 		kmem_cache_free(sock_inode_cachep, ei);
25643815482SEric Dumazet 		return NULL;
25743815482SEric Dumazet 	}
258eaefd110SEric Dumazet 	init_waitqueue_head(&wq->wait);
259eaefd110SEric Dumazet 	wq->fasync_list = NULL;
260574aab1eSNicolai Stange 	wq->flags = 0;
261eaefd110SEric Dumazet 	RCU_INIT_POINTER(ei->socket.wq, wq);
2621da177e4SLinus Torvalds 
2631da177e4SLinus Torvalds 	ei->socket.state = SS_UNCONNECTED;
2641da177e4SLinus Torvalds 	ei->socket.flags = 0;
2651da177e4SLinus Torvalds 	ei->socket.ops = NULL;
2661da177e4SLinus Torvalds 	ei->socket.sk = NULL;
2671da177e4SLinus Torvalds 	ei->socket.file = NULL;
2681da177e4SLinus Torvalds 
2691da177e4SLinus Torvalds 	return &ei->vfs_inode;
2701da177e4SLinus Torvalds }
2711da177e4SLinus Torvalds 
2721da177e4SLinus Torvalds static void sock_destroy_inode(struct inode *inode)
2731da177e4SLinus Torvalds {
27443815482SEric Dumazet 	struct socket_alloc *ei;
275eaefd110SEric Dumazet 	struct socket_wq *wq;
27643815482SEric Dumazet 
27743815482SEric Dumazet 	ei = container_of(inode, struct socket_alloc, vfs_inode);
278eaefd110SEric Dumazet 	wq = rcu_dereference_protected(ei->socket.wq, 1);
27961845220SLai Jiangshan 	kfree_rcu(wq, rcu);
28043815482SEric Dumazet 	kmem_cache_free(sock_inode_cachep, ei);
2811da177e4SLinus Torvalds }
2821da177e4SLinus Torvalds 
28351cc5068SAlexey Dobriyan static void init_once(void *foo)
2841da177e4SLinus Torvalds {
2851da177e4SLinus Torvalds 	struct socket_alloc *ei = (struct socket_alloc *)foo;
2861da177e4SLinus Torvalds 
2871da177e4SLinus Torvalds 	inode_init_once(&ei->vfs_inode);
2881da177e4SLinus Torvalds }
2891da177e4SLinus Torvalds 
2901e911632Syuan linyu static void init_inodecache(void)
2911da177e4SLinus Torvalds {
2921da177e4SLinus Torvalds 	sock_inode_cachep = kmem_cache_create("sock_inode_cache",
2931da177e4SLinus Torvalds 					      sizeof(struct socket_alloc),
29489bddce5SStephen Hemminger 					      0,
29589bddce5SStephen Hemminger 					      (SLAB_HWCACHE_ALIGN |
29689bddce5SStephen Hemminger 					       SLAB_RECLAIM_ACCOUNT |
2975d097056SVladimir Davydov 					       SLAB_MEM_SPREAD | SLAB_ACCOUNT),
29820c2df83SPaul Mundt 					      init_once);
2991e911632Syuan linyu 	BUG_ON(sock_inode_cachep == NULL);
3001da177e4SLinus Torvalds }
3011da177e4SLinus Torvalds 
302b87221deSAlexey Dobriyan static const struct super_operations sockfs_ops = {
3031da177e4SLinus Torvalds 	.alloc_inode	= sock_alloc_inode,
3041da177e4SLinus Torvalds 	.destroy_inode	= sock_destroy_inode,
3051da177e4SLinus Torvalds 	.statfs		= simple_statfs,
3061da177e4SLinus Torvalds };
3071da177e4SLinus Torvalds 
308c23fbb6bSEric Dumazet /*
309c23fbb6bSEric Dumazet  * sockfs_dname() is called from d_path().
310c23fbb6bSEric Dumazet  */
311c23fbb6bSEric Dumazet static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen)
312c23fbb6bSEric Dumazet {
313c23fbb6bSEric Dumazet 	return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]",
314c5ef6035SDavid Howells 				d_inode(dentry)->i_ino);
315c23fbb6bSEric Dumazet }
316c23fbb6bSEric Dumazet 
3173ba13d17SAl Viro static const struct dentry_operations sockfs_dentry_operations = {
318c23fbb6bSEric Dumazet 	.d_dname  = sockfs_dname,
3191da177e4SLinus Torvalds };
3201da177e4SLinus Torvalds 
321bba0bd31SAndreas Gruenbacher static int sockfs_xattr_get(const struct xattr_handler *handler,
322bba0bd31SAndreas Gruenbacher 			    struct dentry *dentry, struct inode *inode,
323bba0bd31SAndreas Gruenbacher 			    const char *suffix, void *value, size_t size)
324bba0bd31SAndreas Gruenbacher {
325bba0bd31SAndreas Gruenbacher 	if (value) {
326bba0bd31SAndreas Gruenbacher 		if (dentry->d_name.len + 1 > size)
327bba0bd31SAndreas Gruenbacher 			return -ERANGE;
328bba0bd31SAndreas Gruenbacher 		memcpy(value, dentry->d_name.name, dentry->d_name.len + 1);
329bba0bd31SAndreas Gruenbacher 	}
330bba0bd31SAndreas Gruenbacher 	return dentry->d_name.len + 1;
331bba0bd31SAndreas Gruenbacher }
332bba0bd31SAndreas Gruenbacher 
333bba0bd31SAndreas Gruenbacher #define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname"
334bba0bd31SAndreas Gruenbacher #define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX)
335bba0bd31SAndreas Gruenbacher #define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1)
336bba0bd31SAndreas Gruenbacher 
337bba0bd31SAndreas Gruenbacher static const struct xattr_handler sockfs_xattr_handler = {
338bba0bd31SAndreas Gruenbacher 	.name = XATTR_NAME_SOCKPROTONAME,
339bba0bd31SAndreas Gruenbacher 	.get = sockfs_xattr_get,
340bba0bd31SAndreas Gruenbacher };
341bba0bd31SAndreas Gruenbacher 
3424a590153SAndreas Gruenbacher static int sockfs_security_xattr_set(const struct xattr_handler *handler,
3434a590153SAndreas Gruenbacher 				     struct dentry *dentry, struct inode *inode,
3444a590153SAndreas Gruenbacher 				     const char *suffix, const void *value,
3454a590153SAndreas Gruenbacher 				     size_t size, int flags)
3464a590153SAndreas Gruenbacher {
3474a590153SAndreas Gruenbacher 	/* Handled by LSM. */
3484a590153SAndreas Gruenbacher 	return -EAGAIN;
3494a590153SAndreas Gruenbacher }
3504a590153SAndreas Gruenbacher 
3514a590153SAndreas Gruenbacher static const struct xattr_handler sockfs_security_xattr_handler = {
3524a590153SAndreas Gruenbacher 	.prefix = XATTR_SECURITY_PREFIX,
3534a590153SAndreas Gruenbacher 	.set = sockfs_security_xattr_set,
3544a590153SAndreas Gruenbacher };
3554a590153SAndreas Gruenbacher 
356bba0bd31SAndreas Gruenbacher static const struct xattr_handler *sockfs_xattr_handlers[] = {
357bba0bd31SAndreas Gruenbacher 	&sockfs_xattr_handler,
3584a590153SAndreas Gruenbacher 	&sockfs_security_xattr_handler,
359bba0bd31SAndreas Gruenbacher 	NULL
360bba0bd31SAndreas Gruenbacher };
361bba0bd31SAndreas Gruenbacher 
362c74a1cbbSAl Viro static struct dentry *sockfs_mount(struct file_system_type *fs_type,
363c74a1cbbSAl Viro 			 int flags, const char *dev_name, void *data)
364c74a1cbbSAl Viro {
365bba0bd31SAndreas Gruenbacher 	return mount_pseudo_xattr(fs_type, "socket:", &sockfs_ops,
366bba0bd31SAndreas Gruenbacher 				  sockfs_xattr_handlers,
367c74a1cbbSAl Viro 				  &sockfs_dentry_operations, SOCKFS_MAGIC);
368c74a1cbbSAl Viro }
369c74a1cbbSAl Viro 
370c74a1cbbSAl Viro static struct vfsmount *sock_mnt __read_mostly;
371c74a1cbbSAl Viro 
372c74a1cbbSAl Viro static struct file_system_type sock_fs_type = {
373c74a1cbbSAl Viro 	.name =		"sockfs",
374c74a1cbbSAl Viro 	.mount =	sockfs_mount,
375c74a1cbbSAl Viro 	.kill_sb =	kill_anon_super,
376c74a1cbbSAl Viro };
377c74a1cbbSAl Viro 
3781da177e4SLinus Torvalds /*
3791da177e4SLinus Torvalds  *	Obtains the first available file descriptor and sets it up for use.
3801da177e4SLinus Torvalds  *
38139d8c1b6SDavid S. Miller  *	These functions create file structures and maps them to fd space
38239d8c1b6SDavid S. Miller  *	of the current process. On success it returns file descriptor
3831da177e4SLinus Torvalds  *	and file struct implicitly stored in sock->file.
3841da177e4SLinus Torvalds  *	Note that another thread may close file descriptor before we return
3851da177e4SLinus Torvalds  *	from this function. We use the fact that now we do not refer
3861da177e4SLinus Torvalds  *	to socket after mapping. If one day we will need it, this
3871da177e4SLinus Torvalds  *	function will increment ref. count on file by 1.
3881da177e4SLinus Torvalds  *
3891da177e4SLinus Torvalds  *	In any case returned fd MAY BE not valid!
3901da177e4SLinus Torvalds  *	This race condition is unavoidable
3911da177e4SLinus Torvalds  *	with shared fd spaces, we cannot solve it inside kernel,
3921da177e4SLinus Torvalds  *	but we take care of internal coherence yet.
3931da177e4SLinus Torvalds  */
3941da177e4SLinus Torvalds 
395aab174f0SLinus Torvalds struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)
3961da177e4SLinus Torvalds {
3977cbe66b6SAl Viro 	struct qstr name = { .name = "" };
3982c48b9c4SAl Viro 	struct path path;
3997cbe66b6SAl Viro 	struct file *file;
4001da177e4SLinus Torvalds 
401600e1779SMasatake YAMATO 	if (dname) {
402600e1779SMasatake YAMATO 		name.name = dname;
403600e1779SMasatake YAMATO 		name.len = strlen(name.name);
404600e1779SMasatake YAMATO 	} else if (sock->sk) {
405600e1779SMasatake YAMATO 		name.name = sock->sk->sk_prot_creator->name;
406600e1779SMasatake YAMATO 		name.len = strlen(name.name);
407600e1779SMasatake YAMATO 	}
4084b936885SNick Piggin 	path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name);
40928407630SAl Viro 	if (unlikely(!path.dentry))
41028407630SAl Viro 		return ERR_PTR(-ENOMEM);
4112c48b9c4SAl Viro 	path.mnt = mntget(sock_mnt);
41239d8c1b6SDavid S. Miller 
4132c48b9c4SAl Viro 	d_instantiate(path.dentry, SOCK_INODE(sock));
414cc3808f8SAl Viro 
4152c48b9c4SAl Viro 	file = alloc_file(&path, FMODE_READ | FMODE_WRITE,
416cc3808f8SAl Viro 		  &socket_file_ops);
417b5ffe634SViresh Kumar 	if (IS_ERR(file)) {
418cc3808f8SAl Viro 		/* drop dentry, keep inode */
419c5ef6035SDavid Howells 		ihold(d_inode(path.dentry));
4202c48b9c4SAl Viro 		path_put(&path);
42139b65252SAnatol Pomozov 		return file;
422cc3808f8SAl Viro 	}
4231da177e4SLinus Torvalds 
4241da177e4SLinus Torvalds 	sock->file = file;
42577d27200SUlrich Drepper 	file->f_flags = O_RDWR | (flags & O_NONBLOCK);
42607dc3f07SBenjamin LaHaise 	file->private_data = sock;
42728407630SAl Viro 	return file;
4281da177e4SLinus Torvalds }
42956b31d1cSAl Viro EXPORT_SYMBOL(sock_alloc_file);
4301da177e4SLinus Torvalds 
43156b31d1cSAl Viro static int sock_map_fd(struct socket *sock, int flags)
43239d8c1b6SDavid S. Miller {
43339d8c1b6SDavid S. Miller 	struct file *newfile;
43428407630SAl Viro 	int fd = get_unused_fd_flags(flags);
43528407630SAl Viro 	if (unlikely(fd < 0))
4361da177e4SLinus Torvalds 		return fd;
4371da177e4SLinus Torvalds 
438aab174f0SLinus Torvalds 	newfile = sock_alloc_file(sock, flags, NULL);
43928407630SAl Viro 	if (likely(!IS_ERR(newfile))) {
4401da177e4SLinus Torvalds 		fd_install(fd, newfile);
4411da177e4SLinus Torvalds 		return fd;
4421da177e4SLinus Torvalds 	}
44328407630SAl Viro 
44428407630SAl Viro 	put_unused_fd(fd);
44528407630SAl Viro 	return PTR_ERR(newfile);
4461da177e4SLinus Torvalds }
4471da177e4SLinus Torvalds 
448406a3c63SJohn Fastabend struct socket *sock_from_file(struct file *file, int *err)
4496cb153caSBenjamin LaHaise {
4506cb153caSBenjamin LaHaise 	if (file->f_op == &socket_file_ops)
4516cb153caSBenjamin LaHaise 		return file->private_data;	/* set in sock_map_fd */
4526cb153caSBenjamin LaHaise 
4536cb153caSBenjamin LaHaise 	*err = -ENOTSOCK;
4546cb153caSBenjamin LaHaise 	return NULL;
4556cb153caSBenjamin LaHaise }
456406a3c63SJohn Fastabend EXPORT_SYMBOL(sock_from_file);
4576cb153caSBenjamin LaHaise 
4581da177e4SLinus Torvalds /**
4591da177e4SLinus Torvalds  *	sockfd_lookup - Go from a file number to its socket slot
4601da177e4SLinus Torvalds  *	@fd: file handle
4611da177e4SLinus Torvalds  *	@err: pointer to an error code return
4621da177e4SLinus Torvalds  *
4631da177e4SLinus Torvalds  *	The file handle passed in is locked and the socket it is bound
4641da177e4SLinus Torvalds  *	too is returned. If an error occurs the err pointer is overwritten
4651da177e4SLinus Torvalds  *	with a negative errno code and NULL is returned. The function checks
4661da177e4SLinus Torvalds  *	for both invalid handles and passing a handle which is not a socket.
4671da177e4SLinus Torvalds  *
4681da177e4SLinus Torvalds  *	On a success the socket object pointer is returned.
4691da177e4SLinus Torvalds  */
4701da177e4SLinus Torvalds 
4711da177e4SLinus Torvalds struct socket *sockfd_lookup(int fd, int *err)
4721da177e4SLinus Torvalds {
4731da177e4SLinus Torvalds 	struct file *file;
4741da177e4SLinus Torvalds 	struct socket *sock;
4751da177e4SLinus Torvalds 
47689bddce5SStephen Hemminger 	file = fget(fd);
47789bddce5SStephen Hemminger 	if (!file) {
4781da177e4SLinus Torvalds 		*err = -EBADF;
4791da177e4SLinus Torvalds 		return NULL;
4801da177e4SLinus Torvalds 	}
48189bddce5SStephen Hemminger 
4826cb153caSBenjamin LaHaise 	sock = sock_from_file(file, err);
4836cb153caSBenjamin LaHaise 	if (!sock)
4841da177e4SLinus Torvalds 		fput(file);
4856cb153caSBenjamin LaHaise 	return sock;
4861da177e4SLinus Torvalds }
487c6d409cfSEric Dumazet EXPORT_SYMBOL(sockfd_lookup);
4881da177e4SLinus Torvalds 
4896cb153caSBenjamin LaHaise static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
4906cb153caSBenjamin LaHaise {
49100e188efSAl Viro 	struct fd f = fdget(fd);
4926cb153caSBenjamin LaHaise 	struct socket *sock;
4936cb153caSBenjamin LaHaise 
4943672558cSHua Zhong 	*err = -EBADF;
49500e188efSAl Viro 	if (f.file) {
49600e188efSAl Viro 		sock = sock_from_file(f.file, err);
49700e188efSAl Viro 		if (likely(sock)) {
49800e188efSAl Viro 			*fput_needed = f.flags;
4991da177e4SLinus Torvalds 			return sock;
50000e188efSAl Viro 		}
50100e188efSAl Viro 		fdput(f);
5026cb153caSBenjamin LaHaise 	}
5036cb153caSBenjamin LaHaise 	return NULL;
5041da177e4SLinus Torvalds }
5051da177e4SLinus Torvalds 
506600e1779SMasatake YAMATO static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer,
507600e1779SMasatake YAMATO 				size_t size)
508600e1779SMasatake YAMATO {
509600e1779SMasatake YAMATO 	ssize_t len;
510600e1779SMasatake YAMATO 	ssize_t used = 0;
511600e1779SMasatake YAMATO 
512c5ef6035SDavid Howells 	len = security_inode_listsecurity(d_inode(dentry), buffer, size);
513600e1779SMasatake YAMATO 	if (len < 0)
514600e1779SMasatake YAMATO 		return len;
515600e1779SMasatake YAMATO 	used += len;
516600e1779SMasatake YAMATO 	if (buffer) {
517600e1779SMasatake YAMATO 		if (size < used)
518600e1779SMasatake YAMATO 			return -ERANGE;
519600e1779SMasatake YAMATO 		buffer += len;
520600e1779SMasatake YAMATO 	}
521600e1779SMasatake YAMATO 
522600e1779SMasatake YAMATO 	len = (XATTR_NAME_SOCKPROTONAME_LEN + 1);
523600e1779SMasatake YAMATO 	used += len;
524600e1779SMasatake YAMATO 	if (buffer) {
525600e1779SMasatake YAMATO 		if (size < used)
526600e1779SMasatake YAMATO 			return -ERANGE;
527600e1779SMasatake YAMATO 		memcpy(buffer, XATTR_NAME_SOCKPROTONAME, len);
528600e1779SMasatake YAMATO 		buffer += len;
529600e1779SMasatake YAMATO 	}
530600e1779SMasatake YAMATO 
531600e1779SMasatake YAMATO 	return used;
532600e1779SMasatake YAMATO }
533600e1779SMasatake YAMATO 
534dc647ec8STobias Klauser static int sockfs_setattr(struct dentry *dentry, struct iattr *iattr)
53586741ec2SLorenzo Colitti {
53686741ec2SLorenzo Colitti 	int err = simple_setattr(dentry, iattr);
53786741ec2SLorenzo Colitti 
538e1a3a60aSEric Biggers 	if (!err && (iattr->ia_valid & ATTR_UID)) {
53986741ec2SLorenzo Colitti 		struct socket *sock = SOCKET_I(d_inode(dentry));
54086741ec2SLorenzo Colitti 
54186741ec2SLorenzo Colitti 		sock->sk->sk_uid = iattr->ia_uid;
54286741ec2SLorenzo Colitti 	}
54386741ec2SLorenzo Colitti 
54486741ec2SLorenzo Colitti 	return err;
54586741ec2SLorenzo Colitti }
54686741ec2SLorenzo Colitti 
547600e1779SMasatake YAMATO static const struct inode_operations sockfs_inode_ops = {
548600e1779SMasatake YAMATO 	.listxattr = sockfs_listxattr,
54986741ec2SLorenzo Colitti 	.setattr = sockfs_setattr,
550600e1779SMasatake YAMATO };
551600e1779SMasatake YAMATO 
5521da177e4SLinus Torvalds /**
5531da177e4SLinus Torvalds  *	sock_alloc	-	allocate a socket
5541da177e4SLinus Torvalds  *
5551da177e4SLinus Torvalds  *	Allocate a new inode and socket object. The two are bound together
5561da177e4SLinus Torvalds  *	and initialised. The socket is then returned. If we are out of inodes
5571da177e4SLinus Torvalds  *	NULL is returned.
5581da177e4SLinus Torvalds  */
5591da177e4SLinus Torvalds 
560f4a00aacSTom Herbert struct socket *sock_alloc(void)
5611da177e4SLinus Torvalds {
5621da177e4SLinus Torvalds 	struct inode *inode;
5631da177e4SLinus Torvalds 	struct socket *sock;
5641da177e4SLinus Torvalds 
565a209dfc7SEric Dumazet 	inode = new_inode_pseudo(sock_mnt->mnt_sb);
5661da177e4SLinus Torvalds 	if (!inode)
5671da177e4SLinus Torvalds 		return NULL;
5681da177e4SLinus Torvalds 
5691da177e4SLinus Torvalds 	sock = SOCKET_I(inode);
5701da177e4SLinus Torvalds 
57129a020d3SEric Dumazet 	kmemcheck_annotate_bitfield(sock, type);
57285fe4025SChristoph Hellwig 	inode->i_ino = get_next_ino();
5731da177e4SLinus Torvalds 	inode->i_mode = S_IFSOCK | S_IRWXUGO;
5748192b0c4SDavid Howells 	inode->i_uid = current_fsuid();
5758192b0c4SDavid Howells 	inode->i_gid = current_fsgid();
576600e1779SMasatake YAMATO 	inode->i_op = &sockfs_inode_ops;
5771da177e4SLinus Torvalds 
57819e8d69cSAlex Shi 	this_cpu_add(sockets_in_use, 1);
5791da177e4SLinus Torvalds 	return sock;
5801da177e4SLinus Torvalds }
581f4a00aacSTom Herbert EXPORT_SYMBOL(sock_alloc);
5821da177e4SLinus Torvalds 
5831da177e4SLinus Torvalds /**
5841da177e4SLinus Torvalds  *	sock_release	-	close a socket
5851da177e4SLinus Torvalds  *	@sock: socket to close
5861da177e4SLinus Torvalds  *
5871da177e4SLinus Torvalds  *	The socket is released from the protocol stack if it has a release
5881da177e4SLinus Torvalds  *	callback, and the inode is then released if the socket is bound to
5891da177e4SLinus Torvalds  *	an inode not a file.
5901da177e4SLinus Torvalds  */
5911da177e4SLinus Torvalds 
5921da177e4SLinus Torvalds void sock_release(struct socket *sock)
5931da177e4SLinus Torvalds {
5941da177e4SLinus Torvalds 	if (sock->ops) {
5951da177e4SLinus Torvalds 		struct module *owner = sock->ops->owner;
5961da177e4SLinus Torvalds 
5971da177e4SLinus Torvalds 		sock->ops->release(sock);
5981da177e4SLinus Torvalds 		sock->ops = NULL;
5991da177e4SLinus Torvalds 		module_put(owner);
6001da177e4SLinus Torvalds 	}
6011da177e4SLinus Torvalds 
602eaefd110SEric Dumazet 	if (rcu_dereference_protected(sock->wq, 1)->fasync_list)
6033410f22eSYang Yingliang 		pr_err("%s: fasync list not empty!\n", __func__);
6041da177e4SLinus Torvalds 
60519e8d69cSAlex Shi 	this_cpu_sub(sockets_in_use, 1);
6061da177e4SLinus Torvalds 	if (!sock->file) {
6071da177e4SLinus Torvalds 		iput(SOCK_INODE(sock));
6081da177e4SLinus Torvalds 		return;
6091da177e4SLinus Torvalds 	}
6101da177e4SLinus Torvalds 	sock->file = NULL;
6111da177e4SLinus Torvalds }
612c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_release);
6131da177e4SLinus Torvalds 
614c14ac945SSoheil Hassas Yeganeh void __sock_tx_timestamp(__u16 tsflags, __u8 *tx_flags)
61520d49473SPatrick Ohly {
616140c55d4SEric Dumazet 	u8 flags = *tx_flags;
617140c55d4SEric Dumazet 
618c14ac945SSoheil Hassas Yeganeh 	if (tsflags & SOF_TIMESTAMPING_TX_HARDWARE)
619140c55d4SEric Dumazet 		flags |= SKBTX_HW_TSTAMP;
620140c55d4SEric Dumazet 
621c14ac945SSoheil Hassas Yeganeh 	if (tsflags & SOF_TIMESTAMPING_TX_SOFTWARE)
622140c55d4SEric Dumazet 		flags |= SKBTX_SW_TSTAMP;
623140c55d4SEric Dumazet 
624c14ac945SSoheil Hassas Yeganeh 	if (tsflags & SOF_TIMESTAMPING_TX_SCHED)
625140c55d4SEric Dumazet 		flags |= SKBTX_SCHED_TSTAMP;
626140c55d4SEric Dumazet 
627140c55d4SEric Dumazet 	*tx_flags = flags;
62820d49473SPatrick Ohly }
62967cc0d40SWillem de Bruijn EXPORT_SYMBOL(__sock_tx_timestamp);
63020d49473SPatrick Ohly 
631d8725c86SAl Viro static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg)
6321da177e4SLinus Torvalds {
63301e97e65SAl Viro 	int ret = sock->ops->sendmsg(sock, msg, msg_data_left(msg));
634d8725c86SAl Viro 	BUG_ON(ret == -EIOCBQUEUED);
635d8725c86SAl Viro 	return ret;
6361da177e4SLinus Torvalds }
6370cf00c6fSGu Zheng 
638d8725c86SAl Viro int sock_sendmsg(struct socket *sock, struct msghdr *msg)
6390cf00c6fSGu Zheng {
640d8725c86SAl Viro 	int err = security_socket_sendmsg(sock, msg,
64101e97e65SAl Viro 					  msg_data_left(msg));
6421b784140SYing Xue 
643d8725c86SAl Viro 	return err ?: sock_sendmsg_nosec(sock, msg);
6440cf00c6fSGu Zheng }
645c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_sendmsg);
6461da177e4SLinus Torvalds 
6471da177e4SLinus Torvalds int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
6481da177e4SLinus Torvalds 		   struct kvec *vec, size_t num, size_t size)
6491da177e4SLinus Torvalds {
6506aa24814SAl Viro 	iov_iter_kvec(&msg->msg_iter, WRITE | ITER_KVEC, vec, num, size);
651d8725c86SAl Viro 	return sock_sendmsg(sock, msg);
6521da177e4SLinus Torvalds }
653c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendmsg);
6541da177e4SLinus Torvalds 
65592f37fd2SEric Dumazet /*
65692f37fd2SEric Dumazet  * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
65792f37fd2SEric Dumazet  */
65892f37fd2SEric Dumazet void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
65992f37fd2SEric Dumazet 	struct sk_buff *skb)
66092f37fd2SEric Dumazet {
66120d49473SPatrick Ohly 	int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
662f24b9be5SWillem de Bruijn 	struct scm_timestamping tss;
66320d49473SPatrick Ohly 	int empty = 1;
66420d49473SPatrick Ohly 	struct skb_shared_hwtstamps *shhwtstamps =
66520d49473SPatrick Ohly 		skb_hwtstamps(skb);
66692f37fd2SEric Dumazet 
66720d49473SPatrick Ohly 	/* Race occurred between timestamp enabling and packet
66820d49473SPatrick Ohly 	   receiving.  Fill in the current time for now. */
6692456e855SThomas Gleixner 	if (need_software_tstamp && skb->tstamp == 0)
67020d49473SPatrick Ohly 		__net_timestamp(skb);
67120d49473SPatrick Ohly 
67220d49473SPatrick Ohly 	if (need_software_tstamp) {
67392f37fd2SEric Dumazet 		if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
67492f37fd2SEric Dumazet 			struct timeval tv;
67520d49473SPatrick Ohly 			skb_get_timestamp(skb, &tv);
67620d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP,
67720d49473SPatrick Ohly 				 sizeof(tv), &tv);
67892f37fd2SEric Dumazet 		} else {
679f24b9be5SWillem de Bruijn 			struct timespec ts;
680f24b9be5SWillem de Bruijn 			skb_get_timestampns(skb, &ts);
68120d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS,
682f24b9be5SWillem de Bruijn 				 sizeof(ts), &ts);
68392f37fd2SEric Dumazet 		}
68492f37fd2SEric Dumazet 	}
68592f37fd2SEric Dumazet 
686f24b9be5SWillem de Bruijn 	memset(&tss, 0, sizeof(tss));
687c199105dSWillem de Bruijn 	if ((sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE) &&
688f24b9be5SWillem de Bruijn 	    ktime_to_timespec_cond(skb->tstamp, tss.ts + 0))
68920d49473SPatrick Ohly 		empty = 0;
6904d276eb6SWillem de Bruijn 	if (shhwtstamps &&
691b9f40e21SWillem de Bruijn 	    (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
692f24b9be5SWillem de Bruijn 	    ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2))
69320d49473SPatrick Ohly 		empty = 0;
6941c885808SFrancis Yan 	if (!empty) {
69520d49473SPatrick Ohly 		put_cmsg(msg, SOL_SOCKET,
696f24b9be5SWillem de Bruijn 			 SCM_TIMESTAMPING, sizeof(tss), &tss);
6971c885808SFrancis Yan 
6981c885808SFrancis Yan 		if (skb->len && (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_STATS))
6991c885808SFrancis Yan 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_OPT_STATS,
7001c885808SFrancis Yan 				 skb->len, skb->data);
7011c885808SFrancis Yan 	}
70220d49473SPatrick Ohly }
7037c81fd8bSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
7047c81fd8bSArnaldo Carvalho de Melo 
7056e3e939fSJohannes Berg void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
7066e3e939fSJohannes Berg 	struct sk_buff *skb)
7076e3e939fSJohannes Berg {
7086e3e939fSJohannes Berg 	int ack;
7096e3e939fSJohannes Berg 
7106e3e939fSJohannes Berg 	if (!sock_flag(sk, SOCK_WIFI_STATUS))
7116e3e939fSJohannes Berg 		return;
7126e3e939fSJohannes Berg 	if (!skb->wifi_acked_valid)
7136e3e939fSJohannes Berg 		return;
7146e3e939fSJohannes Berg 
7156e3e939fSJohannes Berg 	ack = skb->wifi_acked;
7166e3e939fSJohannes Berg 
7176e3e939fSJohannes Berg 	put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack);
7186e3e939fSJohannes Berg }
7196e3e939fSJohannes Berg EXPORT_SYMBOL_GPL(__sock_recv_wifi_status);
7206e3e939fSJohannes Berg 
72111165f14Sstephen hemminger static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk,
72211165f14Sstephen hemminger 				   struct sk_buff *skb)
7233b885787SNeil Horman {
724744d5a3eSEyal Birger 	if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && SOCK_SKB_CB(skb)->dropcount)
7253b885787SNeil Horman 		put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL,
726744d5a3eSEyal Birger 			sizeof(__u32), &SOCK_SKB_CB(skb)->dropcount);
7273b885787SNeil Horman }
7283b885787SNeil Horman 
729767dd033SEric Dumazet void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
7303b885787SNeil Horman 	struct sk_buff *skb)
7313b885787SNeil Horman {
7323b885787SNeil Horman 	sock_recv_timestamp(msg, sk, skb);
7333b885787SNeil Horman 	sock_recv_drops(msg, sk, skb);
7343b885787SNeil Horman }
735767dd033SEric Dumazet EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops);
7363b885787SNeil Horman 
7371b784140SYing Xue static inline int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
7381b784140SYing Xue 				     int flags)
739a2e27255SArnaldo Carvalho de Melo {
7402da62906SAl Viro 	return sock->ops->recvmsg(sock, msg, msg_data_left(msg), flags);
7412da62906SAl Viro }
742a2e27255SArnaldo Carvalho de Melo 
7432da62906SAl Viro int sock_recvmsg(struct socket *sock, struct msghdr *msg, int flags)
7442da62906SAl Viro {
7452da62906SAl Viro 	int err = security_socket_recvmsg(sock, msg, msg_data_left(msg), flags);
7462da62906SAl Viro 
7472da62906SAl Viro 	return err ?: sock_recvmsg_nosec(sock, msg, flags);
7481da177e4SLinus Torvalds }
749c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_recvmsg);
7501da177e4SLinus Torvalds 
751c1249c0aSMartin Lucina /**
752c1249c0aSMartin Lucina  * kernel_recvmsg - Receive a message from a socket (kernel space)
753c1249c0aSMartin Lucina  * @sock:       The socket to receive the message from
754c1249c0aSMartin Lucina  * @msg:        Received message
755c1249c0aSMartin Lucina  * @vec:        Input s/g array for message data
756c1249c0aSMartin Lucina  * @num:        Size of input s/g array
757c1249c0aSMartin Lucina  * @size:       Number of bytes to read
758c1249c0aSMartin Lucina  * @flags:      Message flags (MSG_DONTWAIT, etc...)
759c1249c0aSMartin Lucina  *
760c1249c0aSMartin Lucina  * On return the msg structure contains the scatter/gather array passed in the
761c1249c0aSMartin Lucina  * vec argument. The array is modified so that it consists of the unfilled
762c1249c0aSMartin Lucina  * portion of the original array.
763c1249c0aSMartin Lucina  *
764c1249c0aSMartin Lucina  * The returned value is the total number of bytes received, or an error.
765c1249c0aSMartin Lucina  */
7661da177e4SLinus Torvalds int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
76789bddce5SStephen Hemminger 		   struct kvec *vec, size_t num, size_t size, int flags)
7681da177e4SLinus Torvalds {
7691da177e4SLinus Torvalds 	mm_segment_t oldfs = get_fs();
7701da177e4SLinus Torvalds 	int result;
7711da177e4SLinus Torvalds 
7726aa24814SAl Viro 	iov_iter_kvec(&msg->msg_iter, READ | ITER_KVEC, vec, num, size);
7731da177e4SLinus Torvalds 	set_fs(KERNEL_DS);
7742da62906SAl Viro 	result = sock_recvmsg(sock, msg, flags);
7751da177e4SLinus Torvalds 	set_fs(oldfs);
7761da177e4SLinus Torvalds 	return result;
7771da177e4SLinus Torvalds }
778c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_recvmsg);
7791da177e4SLinus Torvalds 
78020380731SArnaldo Carvalho de Melo static ssize_t sock_sendpage(struct file *file, struct page *page,
7811da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more)
7821da177e4SLinus Torvalds {
7831da177e4SLinus Torvalds 	struct socket *sock;
7841da177e4SLinus Torvalds 	int flags;
7851da177e4SLinus Torvalds 
786b69aee04SEric Dumazet 	sock = file->private_data;
7871da177e4SLinus Torvalds 
78835f9c09fSEric Dumazet 	flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
78935f9c09fSEric Dumazet 	/* more is a combination of MSG_MORE and MSG_SENDPAGE_NOTLAST */
79035f9c09fSEric Dumazet 	flags |= more;
7911da177e4SLinus Torvalds 
792e6949583SLinus Torvalds 	return kernel_sendpage(sock, page, offset, size, flags);
7931da177e4SLinus Torvalds }
7941da177e4SLinus Torvalds 
7959c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
7969c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
7979c55e01cSJens Axboe 				unsigned int flags)
7989c55e01cSJens Axboe {
7999c55e01cSJens Axboe 	struct socket *sock = file->private_data;
8009c55e01cSJens Axboe 
801997b37daSRémi Denis-Courmont 	if (unlikely(!sock->ops->splice_read))
802997b37daSRémi Denis-Courmont 		return -EINVAL;
803997b37daSRémi Denis-Courmont 
8049c55e01cSJens Axboe 	return sock->ops->splice_read(sock, ppos, pipe, len, flags);
8059c55e01cSJens Axboe }
8069c55e01cSJens Axboe 
8078ae5e030SAl Viro static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to)
808ce1d4d3eSChristoph Hellwig {
8096d652330SAl Viro 	struct file *file = iocb->ki_filp;
8106d652330SAl Viro 	struct socket *sock = file->private_data;
8110345f931Stadeusz.struk@intel.com 	struct msghdr msg = {.msg_iter = *to,
8120345f931Stadeusz.struk@intel.com 			     .msg_iocb = iocb};
8138ae5e030SAl Viro 	ssize_t res;
814ce1d4d3eSChristoph Hellwig 
8158ae5e030SAl Viro 	if (file->f_flags & O_NONBLOCK)
8168ae5e030SAl Viro 		msg.msg_flags = MSG_DONTWAIT;
8178ae5e030SAl Viro 
8188ae5e030SAl Viro 	if (iocb->ki_pos != 0)
819ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
820027445c3SBadari Pulavarty 
82166ee59afSChristoph Hellwig 	if (!iov_iter_count(to))	/* Match SYS5 behaviour */
822ce1d4d3eSChristoph Hellwig 		return 0;
823ce1d4d3eSChristoph Hellwig 
8242da62906SAl Viro 	res = sock_recvmsg(sock, &msg, msg.msg_flags);
8258ae5e030SAl Viro 	*to = msg.msg_iter;
8268ae5e030SAl Viro 	return res;
827ce1d4d3eSChristoph Hellwig }
828ce1d4d3eSChristoph Hellwig 
8298ae5e030SAl Viro static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from)
8301da177e4SLinus Torvalds {
8316d652330SAl Viro 	struct file *file = iocb->ki_filp;
8326d652330SAl Viro 	struct socket *sock = file->private_data;
8330345f931Stadeusz.struk@intel.com 	struct msghdr msg = {.msg_iter = *from,
8340345f931Stadeusz.struk@intel.com 			     .msg_iocb = iocb};
8358ae5e030SAl Viro 	ssize_t res;
8361da177e4SLinus Torvalds 
8378ae5e030SAl Viro 	if (iocb->ki_pos != 0)
838ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
839027445c3SBadari Pulavarty 
8408ae5e030SAl Viro 	if (file->f_flags & O_NONBLOCK)
8418ae5e030SAl Viro 		msg.msg_flags = MSG_DONTWAIT;
8428ae5e030SAl Viro 
8436d652330SAl Viro 	if (sock->type == SOCK_SEQPACKET)
8446d652330SAl Viro 		msg.msg_flags |= MSG_EOR;
8456d652330SAl Viro 
846d8725c86SAl Viro 	res = sock_sendmsg(sock, &msg);
8478ae5e030SAl Viro 	*from = msg.msg_iter;
8488ae5e030SAl Viro 	return res;
8491da177e4SLinus Torvalds }
8501da177e4SLinus Torvalds 
8511da177e4SLinus Torvalds /*
8521da177e4SLinus Torvalds  * Atomic setting of ioctl hooks to avoid race
8531da177e4SLinus Torvalds  * with module unload.
8541da177e4SLinus Torvalds  */
8551da177e4SLinus Torvalds 
8564a3e2f71SArjan van de Ven static DEFINE_MUTEX(br_ioctl_mutex);
857c6d409cfSEric Dumazet static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg);
8581da177e4SLinus Torvalds 
859881d966bSEric W. Biederman void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *))
8601da177e4SLinus Torvalds {
8614a3e2f71SArjan van de Ven 	mutex_lock(&br_ioctl_mutex);
8621da177e4SLinus Torvalds 	br_ioctl_hook = hook;
8634a3e2f71SArjan van de Ven 	mutex_unlock(&br_ioctl_mutex);
8641da177e4SLinus Torvalds }
8651da177e4SLinus Torvalds EXPORT_SYMBOL(brioctl_set);
8661da177e4SLinus Torvalds 
8674a3e2f71SArjan van de Ven static DEFINE_MUTEX(vlan_ioctl_mutex);
868881d966bSEric W. Biederman static int (*vlan_ioctl_hook) (struct net *, void __user *arg);
8691da177e4SLinus Torvalds 
870881d966bSEric W. Biederman void vlan_ioctl_set(int (*hook) (struct net *, void __user *))
8711da177e4SLinus Torvalds {
8724a3e2f71SArjan van de Ven 	mutex_lock(&vlan_ioctl_mutex);
8731da177e4SLinus Torvalds 	vlan_ioctl_hook = hook;
8744a3e2f71SArjan van de Ven 	mutex_unlock(&vlan_ioctl_mutex);
8751da177e4SLinus Torvalds }
8761da177e4SLinus Torvalds EXPORT_SYMBOL(vlan_ioctl_set);
8771da177e4SLinus Torvalds 
8784a3e2f71SArjan van de Ven static DEFINE_MUTEX(dlci_ioctl_mutex);
8791da177e4SLinus Torvalds static int (*dlci_ioctl_hook) (unsigned int, void __user *);
8801da177e4SLinus Torvalds 
8811da177e4SLinus Torvalds void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
8821da177e4SLinus Torvalds {
8834a3e2f71SArjan van de Ven 	mutex_lock(&dlci_ioctl_mutex);
8841da177e4SLinus Torvalds 	dlci_ioctl_hook = hook;
8854a3e2f71SArjan van de Ven 	mutex_unlock(&dlci_ioctl_mutex);
8861da177e4SLinus Torvalds }
8871da177e4SLinus Torvalds EXPORT_SYMBOL(dlci_ioctl_set);
8881da177e4SLinus Torvalds 
8896b96018bSArnd Bergmann static long sock_do_ioctl(struct net *net, struct socket *sock,
8906b96018bSArnd Bergmann 				 unsigned int cmd, unsigned long arg)
8916b96018bSArnd Bergmann {
8926b96018bSArnd Bergmann 	int err;
8936b96018bSArnd Bergmann 	void __user *argp = (void __user *)arg;
8946b96018bSArnd Bergmann 
8956b96018bSArnd Bergmann 	err = sock->ops->ioctl(sock, cmd, arg);
8966b96018bSArnd Bergmann 
8976b96018bSArnd Bergmann 	/*
8986b96018bSArnd Bergmann 	 * If this ioctl is unknown try to hand it down
8996b96018bSArnd Bergmann 	 * to the NIC driver.
9006b96018bSArnd Bergmann 	 */
9016b96018bSArnd Bergmann 	if (err == -ENOIOCTLCMD)
9026b96018bSArnd Bergmann 		err = dev_ioctl(net, cmd, argp);
9036b96018bSArnd Bergmann 
9046b96018bSArnd Bergmann 	return err;
9056b96018bSArnd Bergmann }
9066b96018bSArnd Bergmann 
9071da177e4SLinus Torvalds /*
9081da177e4SLinus Torvalds  *	With an ioctl, arg may well be a user mode pointer, but we don't know
9091da177e4SLinus Torvalds  *	what to do with it - that's up to the protocol still.
9101da177e4SLinus Torvalds  */
9111da177e4SLinus Torvalds 
912c62cce2cSAndrey Vagin static struct ns_common *get_net_ns(struct ns_common *ns)
913c62cce2cSAndrey Vagin {
914c62cce2cSAndrey Vagin 	return &get_net(container_of(ns, struct net, ns))->ns;
915c62cce2cSAndrey Vagin }
916c62cce2cSAndrey Vagin 
9171da177e4SLinus Torvalds static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
9181da177e4SLinus Torvalds {
9191da177e4SLinus Torvalds 	struct socket *sock;
920881d966bSEric W. Biederman 	struct sock *sk;
9211da177e4SLinus Torvalds 	void __user *argp = (void __user *)arg;
9221da177e4SLinus Torvalds 	int pid, err;
923881d966bSEric W. Biederman 	struct net *net;
9241da177e4SLinus Torvalds 
925b69aee04SEric Dumazet 	sock = file->private_data;
926881d966bSEric W. Biederman 	sk = sock->sk;
9273b1e0a65SYOSHIFUJI Hideaki 	net = sock_net(sk);
9281da177e4SLinus Torvalds 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
929881d966bSEric W. Biederman 		err = dev_ioctl(net, cmd, argp);
9301da177e4SLinus Torvalds 	} else
9313d23e349SJohannes Berg #ifdef CONFIG_WEXT_CORE
9321da177e4SLinus Torvalds 	if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
933881d966bSEric W. Biederman 		err = dev_ioctl(net, cmd, argp);
9341da177e4SLinus Torvalds 	} else
9353d23e349SJohannes Berg #endif
9361da177e4SLinus Torvalds 		switch (cmd) {
9371da177e4SLinus Torvalds 		case FIOSETOWN:
9381da177e4SLinus Torvalds 		case SIOCSPGRP:
9391da177e4SLinus Torvalds 			err = -EFAULT;
9401da177e4SLinus Torvalds 			if (get_user(pid, (int __user *)argp))
9411da177e4SLinus Torvalds 				break;
942e0b93eddSJeff Layton 			f_setown(sock->file, pid, 1);
943e0b93eddSJeff Layton 			err = 0;
9441da177e4SLinus Torvalds 			break;
9451da177e4SLinus Torvalds 		case FIOGETOWN:
9461da177e4SLinus Torvalds 		case SIOCGPGRP:
947609d7fa9SEric W. Biederman 			err = put_user(f_getown(sock->file),
94889bddce5SStephen Hemminger 				       (int __user *)argp);
9491da177e4SLinus Torvalds 			break;
9501da177e4SLinus Torvalds 		case SIOCGIFBR:
9511da177e4SLinus Torvalds 		case SIOCSIFBR:
9521da177e4SLinus Torvalds 		case SIOCBRADDBR:
9531da177e4SLinus Torvalds 		case SIOCBRDELBR:
9541da177e4SLinus Torvalds 			err = -ENOPKG;
9551da177e4SLinus Torvalds 			if (!br_ioctl_hook)
9561da177e4SLinus Torvalds 				request_module("bridge");
9571da177e4SLinus Torvalds 
9584a3e2f71SArjan van de Ven 			mutex_lock(&br_ioctl_mutex);
9591da177e4SLinus Torvalds 			if (br_ioctl_hook)
960881d966bSEric W. Biederman 				err = br_ioctl_hook(net, cmd, argp);
9614a3e2f71SArjan van de Ven 			mutex_unlock(&br_ioctl_mutex);
9621da177e4SLinus Torvalds 			break;
9631da177e4SLinus Torvalds 		case SIOCGIFVLAN:
9641da177e4SLinus Torvalds 		case SIOCSIFVLAN:
9651da177e4SLinus Torvalds 			err = -ENOPKG;
9661da177e4SLinus Torvalds 			if (!vlan_ioctl_hook)
9671da177e4SLinus Torvalds 				request_module("8021q");
9681da177e4SLinus Torvalds 
9694a3e2f71SArjan van de Ven 			mutex_lock(&vlan_ioctl_mutex);
9701da177e4SLinus Torvalds 			if (vlan_ioctl_hook)
971881d966bSEric W. Biederman 				err = vlan_ioctl_hook(net, argp);
9724a3e2f71SArjan van de Ven 			mutex_unlock(&vlan_ioctl_mutex);
9731da177e4SLinus Torvalds 			break;
9741da177e4SLinus Torvalds 		case SIOCADDDLCI:
9751da177e4SLinus Torvalds 		case SIOCDELDLCI:
9761da177e4SLinus Torvalds 			err = -ENOPKG;
9771da177e4SLinus Torvalds 			if (!dlci_ioctl_hook)
9781da177e4SLinus Torvalds 				request_module("dlci");
9791da177e4SLinus Torvalds 
9804a3e2f71SArjan van de Ven 			mutex_lock(&dlci_ioctl_mutex);
9817512cbf6SPavel Emelyanov 			if (dlci_ioctl_hook)
9821da177e4SLinus Torvalds 				err = dlci_ioctl_hook(cmd, argp);
9834a3e2f71SArjan van de Ven 			mutex_unlock(&dlci_ioctl_mutex);
9841da177e4SLinus Torvalds 			break;
985c62cce2cSAndrey Vagin 		case SIOCGSKNS:
986c62cce2cSAndrey Vagin 			err = -EPERM;
987c62cce2cSAndrey Vagin 			if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
988c62cce2cSAndrey Vagin 				break;
989c62cce2cSAndrey Vagin 
990c62cce2cSAndrey Vagin 			err = open_related_ns(&net->ns, get_net_ns);
991c62cce2cSAndrey Vagin 			break;
9921da177e4SLinus Torvalds 		default:
9936b96018bSArnd Bergmann 			err = sock_do_ioctl(net, sock, cmd, arg);
9941da177e4SLinus Torvalds 			break;
9951da177e4SLinus Torvalds 		}
9961da177e4SLinus Torvalds 	return err;
9971da177e4SLinus Torvalds }
9981da177e4SLinus Torvalds 
9991da177e4SLinus Torvalds int sock_create_lite(int family, int type, int protocol, struct socket **res)
10001da177e4SLinus Torvalds {
10011da177e4SLinus Torvalds 	int err;
10021da177e4SLinus Torvalds 	struct socket *sock = NULL;
10031da177e4SLinus Torvalds 
10041da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, 1);
10051da177e4SLinus Torvalds 	if (err)
10061da177e4SLinus Torvalds 		goto out;
10071da177e4SLinus Torvalds 
10081da177e4SLinus Torvalds 	sock = sock_alloc();
10091da177e4SLinus Torvalds 	if (!sock) {
10101da177e4SLinus Torvalds 		err = -ENOMEM;
10111da177e4SLinus Torvalds 		goto out;
10121da177e4SLinus Torvalds 	}
10131da177e4SLinus Torvalds 
10141da177e4SLinus Torvalds 	sock->type = type;
10157420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, 1);
10167420ed23SVenkat Yekkirala 	if (err)
10177420ed23SVenkat Yekkirala 		goto out_release;
10187420ed23SVenkat Yekkirala 
10191da177e4SLinus Torvalds out:
10201da177e4SLinus Torvalds 	*res = sock;
10211da177e4SLinus Torvalds 	return err;
10227420ed23SVenkat Yekkirala out_release:
10237420ed23SVenkat Yekkirala 	sock_release(sock);
10247420ed23SVenkat Yekkirala 	sock = NULL;
10257420ed23SVenkat Yekkirala 	goto out;
10261da177e4SLinus Torvalds }
1027c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_lite);
10281da177e4SLinus Torvalds 
10291da177e4SLinus Torvalds /* No kernel lock held - perfect */
10301da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file, poll_table *wait)
10311da177e4SLinus Torvalds {
1032cbf55001SEliezer Tamir 	unsigned int busy_flag = 0;
10331da177e4SLinus Torvalds 	struct socket *sock;
10341da177e4SLinus Torvalds 
10351da177e4SLinus Torvalds 	/*
10361da177e4SLinus Torvalds 	 *      We can't return errors to poll, so it's either yes or no.
10371da177e4SLinus Torvalds 	 */
1038b69aee04SEric Dumazet 	sock = file->private_data;
10392d48d67fSEliezer Tamir 
1040cbf55001SEliezer Tamir 	if (sk_can_busy_loop(sock->sk)) {
10412d48d67fSEliezer Tamir 		/* this socket can poll_ll so tell the system call */
1042cbf55001SEliezer Tamir 		busy_flag = POLL_BUSY_LOOP;
10432d48d67fSEliezer Tamir 
10442d48d67fSEliezer Tamir 		/* once, only if requested by syscall */
1045cbf55001SEliezer Tamir 		if (wait && (wait->_key & POLL_BUSY_LOOP))
1046cbf55001SEliezer Tamir 			sk_busy_loop(sock->sk, 1);
10472d48d67fSEliezer Tamir 	}
10482d48d67fSEliezer Tamir 
1049cbf55001SEliezer Tamir 	return busy_flag | sock->ops->poll(file, sock, wait);
10501da177e4SLinus Torvalds }
10511da177e4SLinus Torvalds 
10521da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma)
10531da177e4SLinus Torvalds {
1054b69aee04SEric Dumazet 	struct socket *sock = file->private_data;
10551da177e4SLinus Torvalds 
10561da177e4SLinus Torvalds 	return sock->ops->mmap(file, sock, vma);
10571da177e4SLinus Torvalds }
10581da177e4SLinus Torvalds 
105920380731SArnaldo Carvalho de Melo static int sock_close(struct inode *inode, struct file *filp)
10601da177e4SLinus Torvalds {
10611da177e4SLinus Torvalds 	sock_release(SOCKET_I(inode));
10621da177e4SLinus Torvalds 	return 0;
10631da177e4SLinus Torvalds }
10641da177e4SLinus Torvalds 
10651da177e4SLinus Torvalds /*
10661da177e4SLinus Torvalds  *	Update the socket async list
10671da177e4SLinus Torvalds  *
10681da177e4SLinus Torvalds  *	Fasync_list locking strategy.
10691da177e4SLinus Torvalds  *
10701da177e4SLinus Torvalds  *	1. fasync_list is modified only under process context socket lock
10711da177e4SLinus Torvalds  *	   i.e. under semaphore.
10721da177e4SLinus Torvalds  *	2. fasync_list is used under read_lock(&sk->sk_callback_lock)
1073989a2979SEric Dumazet  *	   or under socket lock
10741da177e4SLinus Torvalds  */
10751da177e4SLinus Torvalds 
10761da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on)
10771da177e4SLinus Torvalds {
1078989a2979SEric Dumazet 	struct socket *sock = filp->private_data;
1079989a2979SEric Dumazet 	struct sock *sk = sock->sk;
1080eaefd110SEric Dumazet 	struct socket_wq *wq;
10811da177e4SLinus Torvalds 
1082989a2979SEric Dumazet 	if (sk == NULL)
10831da177e4SLinus Torvalds 		return -EINVAL;
10841da177e4SLinus Torvalds 
10851da177e4SLinus Torvalds 	lock_sock(sk);
10861e1d04e6SHannes Frederic Sowa 	wq = rcu_dereference_protected(sock->wq, lockdep_sock_is_held(sk));
1087eaefd110SEric Dumazet 	fasync_helper(fd, filp, on, &wq->fasync_list);
10881da177e4SLinus Torvalds 
1089eaefd110SEric Dumazet 	if (!wq->fasync_list)
1090bcdce719SEric Dumazet 		sock_reset_flag(sk, SOCK_FASYNC);
1091989a2979SEric Dumazet 	else
1092989a2979SEric Dumazet 		sock_set_flag(sk, SOCK_FASYNC);
10931da177e4SLinus Torvalds 
1094989a2979SEric Dumazet 	release_sock(sk);
10951da177e4SLinus Torvalds 	return 0;
10961da177e4SLinus Torvalds }
10971da177e4SLinus Torvalds 
1098ceb5d58bSEric Dumazet /* This function may be called only under rcu_lock */
10991da177e4SLinus Torvalds 
1100ceb5d58bSEric Dumazet int sock_wake_async(struct socket_wq *wq, int how, int band)
11011da177e4SLinus Torvalds {
1102ceb5d58bSEric Dumazet 	if (!wq || !wq->fasync_list)
1103ceb5d58bSEric Dumazet 		return -1;
110443815482SEric Dumazet 
110589bddce5SStephen Hemminger 	switch (how) {
11068d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_WAITD:
1107ceb5d58bSEric Dumazet 		if (test_bit(SOCKWQ_ASYNC_WAITDATA, &wq->flags))
11081da177e4SLinus Torvalds 			break;
11091da177e4SLinus Torvalds 		goto call_kill;
11108d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_SPACE:
1111ceb5d58bSEric Dumazet 		if (!test_and_clear_bit(SOCKWQ_ASYNC_NOSPACE, &wq->flags))
11121da177e4SLinus Torvalds 			break;
11131da177e4SLinus Torvalds 		/* fall through */
11148d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_IO:
11151da177e4SLinus Torvalds call_kill:
111643815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGIO, band);
11171da177e4SLinus Torvalds 		break;
11188d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_URG:
111943815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGURG, band);
11201da177e4SLinus Torvalds 	}
1121ceb5d58bSEric Dumazet 
11221da177e4SLinus Torvalds 	return 0;
11231da177e4SLinus Torvalds }
1124c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_wake_async);
11251da177e4SLinus Torvalds 
1126721db93aSPavel Emelyanov int __sock_create(struct net *net, int family, int type, int protocol,
112789bddce5SStephen Hemminger 			 struct socket **res, int kern)
11281da177e4SLinus Torvalds {
11291da177e4SLinus Torvalds 	int err;
11301da177e4SLinus Torvalds 	struct socket *sock;
113155737fdaSStephen Hemminger 	const struct net_proto_family *pf;
11321da177e4SLinus Torvalds 
11331da177e4SLinus Torvalds 	/*
11341da177e4SLinus Torvalds 	 *      Check protocol is in range
11351da177e4SLinus Torvalds 	 */
11361da177e4SLinus Torvalds 	if (family < 0 || family >= NPROTO)
11371da177e4SLinus Torvalds 		return -EAFNOSUPPORT;
11381da177e4SLinus Torvalds 	if (type < 0 || type >= SOCK_MAX)
11391da177e4SLinus Torvalds 		return -EINVAL;
11401da177e4SLinus Torvalds 
11411da177e4SLinus Torvalds 	/* Compatibility.
11421da177e4SLinus Torvalds 
11431da177e4SLinus Torvalds 	   This uglymoron is moved from INET layer to here to avoid
11441da177e4SLinus Torvalds 	   deadlock in module load.
11451da177e4SLinus Torvalds 	 */
11461da177e4SLinus Torvalds 	if (family == PF_INET && type == SOCK_PACKET) {
1147f3c98690Sliping.zhang 		pr_info_once("%s uses obsolete (PF_INET,SOCK_PACKET)\n",
114889bddce5SStephen Hemminger 			     current->comm);
11491da177e4SLinus Torvalds 		family = PF_PACKET;
11501da177e4SLinus Torvalds 	}
11511da177e4SLinus Torvalds 
11521da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, kern);
11531da177e4SLinus Torvalds 	if (err)
11541da177e4SLinus Torvalds 		return err;
11551da177e4SLinus Torvalds 
115655737fdaSStephen Hemminger 	/*
115755737fdaSStephen Hemminger 	 *	Allocate the socket and allow the family to set things up. if
115855737fdaSStephen Hemminger 	 *	the protocol is 0, the family is instructed to select an appropriate
115955737fdaSStephen Hemminger 	 *	default.
116055737fdaSStephen Hemminger 	 */
116155737fdaSStephen Hemminger 	sock = sock_alloc();
116255737fdaSStephen Hemminger 	if (!sock) {
1163e87cc472SJoe Perches 		net_warn_ratelimited("socket: no more sockets\n");
116455737fdaSStephen Hemminger 		return -ENFILE;	/* Not exactly a match, but its the
116555737fdaSStephen Hemminger 				   closest posix thing */
116655737fdaSStephen Hemminger 	}
116755737fdaSStephen Hemminger 
116855737fdaSStephen Hemminger 	sock->type = type;
116955737fdaSStephen Hemminger 
117095a5afcaSJohannes Berg #ifdef CONFIG_MODULES
11711da177e4SLinus Torvalds 	/* Attempt to load a protocol module if the find failed.
11721da177e4SLinus Torvalds 	 *
11731da177e4SLinus Torvalds 	 * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
11741da177e4SLinus Torvalds 	 * requested real, full-featured networking support upon configuration.
11751da177e4SLinus Torvalds 	 * Otherwise module support will break!
11761da177e4SLinus Torvalds 	 */
1177190683a9SEric Dumazet 	if (rcu_access_pointer(net_families[family]) == NULL)
11781da177e4SLinus Torvalds 		request_module("net-pf-%d", family);
11791da177e4SLinus Torvalds #endif
11801da177e4SLinus Torvalds 
118155737fdaSStephen Hemminger 	rcu_read_lock();
118255737fdaSStephen Hemminger 	pf = rcu_dereference(net_families[family]);
11831da177e4SLinus Torvalds 	err = -EAFNOSUPPORT;
118455737fdaSStephen Hemminger 	if (!pf)
118555737fdaSStephen Hemminger 		goto out_release;
11861da177e4SLinus Torvalds 
11871da177e4SLinus Torvalds 	/*
11881da177e4SLinus Torvalds 	 * We will call the ->create function, that possibly is in a loadable
11891da177e4SLinus Torvalds 	 * module, so we have to bump that loadable module refcnt first.
11901da177e4SLinus Torvalds 	 */
119155737fdaSStephen Hemminger 	if (!try_module_get(pf->owner))
11921da177e4SLinus Torvalds 		goto out_release;
11931da177e4SLinus Torvalds 
119455737fdaSStephen Hemminger 	/* Now protected by module ref count */
119555737fdaSStephen Hemminger 	rcu_read_unlock();
119655737fdaSStephen Hemminger 
11973f378b68SEric Paris 	err = pf->create(net, sock, protocol, kern);
119855737fdaSStephen Hemminger 	if (err < 0)
11991da177e4SLinus Torvalds 		goto out_module_put;
1200a79af59eSFrank Filz 
12011da177e4SLinus Torvalds 	/*
12021da177e4SLinus Torvalds 	 * Now to bump the refcnt of the [loadable] module that owns this
12031da177e4SLinus Torvalds 	 * socket at sock_release time we decrement its refcnt.
12041da177e4SLinus Torvalds 	 */
120555737fdaSStephen Hemminger 	if (!try_module_get(sock->ops->owner))
120655737fdaSStephen Hemminger 		goto out_module_busy;
120755737fdaSStephen Hemminger 
12081da177e4SLinus Torvalds 	/*
12091da177e4SLinus Torvalds 	 * Now that we're done with the ->create function, the [loadable]
12101da177e4SLinus Torvalds 	 * module can have its refcnt decremented
12111da177e4SLinus Torvalds 	 */
121255737fdaSStephen Hemminger 	module_put(pf->owner);
12137420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, kern);
12147420ed23SVenkat Yekkirala 	if (err)
12153b185525SHerbert Xu 		goto out_sock_release;
121655737fdaSStephen Hemminger 	*res = sock;
12171da177e4SLinus Torvalds 
121855737fdaSStephen Hemminger 	return 0;
121955737fdaSStephen Hemminger 
122055737fdaSStephen Hemminger out_module_busy:
122155737fdaSStephen Hemminger 	err = -EAFNOSUPPORT;
12221da177e4SLinus Torvalds out_module_put:
122355737fdaSStephen Hemminger 	sock->ops = NULL;
122455737fdaSStephen Hemminger 	module_put(pf->owner);
122555737fdaSStephen Hemminger out_sock_release:
12261da177e4SLinus Torvalds 	sock_release(sock);
122755737fdaSStephen Hemminger 	return err;
122855737fdaSStephen Hemminger 
122955737fdaSStephen Hemminger out_release:
123055737fdaSStephen Hemminger 	rcu_read_unlock();
123155737fdaSStephen Hemminger 	goto out_sock_release;
12321da177e4SLinus Torvalds }
1233721db93aSPavel Emelyanov EXPORT_SYMBOL(__sock_create);
12341da177e4SLinus Torvalds 
12351da177e4SLinus Torvalds int sock_create(int family, int type, int protocol, struct socket **res)
12361da177e4SLinus Torvalds {
12371b8d7ae4SEric W. Biederman 	return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
12381da177e4SLinus Torvalds }
1239c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create);
12401da177e4SLinus Torvalds 
1241eeb1bd5cSEric W. Biederman int sock_create_kern(struct net *net, int family, int type, int protocol, struct socket **res)
12421da177e4SLinus Torvalds {
1243eeb1bd5cSEric W. Biederman 	return __sock_create(net, family, type, protocol, res, 1);
12441da177e4SLinus Torvalds }
1245c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_kern);
12461da177e4SLinus Torvalds 
12473e0fa65fSHeiko Carstens SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
12481da177e4SLinus Torvalds {
12491da177e4SLinus Torvalds 	int retval;
12501da177e4SLinus Torvalds 	struct socket *sock;
1251a677a039SUlrich Drepper 	int flags;
1252a677a039SUlrich Drepper 
1253e38b36f3SUlrich Drepper 	/* Check the SOCK_* constants for consistency.  */
1254e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
1255e38b36f3SUlrich Drepper 	BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
1256e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);
1257e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);
1258e38b36f3SUlrich Drepper 
1259a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
126077d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1261a677a039SUlrich Drepper 		return -EINVAL;
1262a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
12631da177e4SLinus Torvalds 
1264aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1265aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1266aaca0bdcSUlrich Drepper 
12671da177e4SLinus Torvalds 	retval = sock_create(family, type, protocol, &sock);
12681da177e4SLinus Torvalds 	if (retval < 0)
12691da177e4SLinus Torvalds 		goto out;
12701da177e4SLinus Torvalds 
127177d27200SUlrich Drepper 	retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
12721da177e4SLinus Torvalds 	if (retval < 0)
12731da177e4SLinus Torvalds 		goto out_release;
12741da177e4SLinus Torvalds 
12751da177e4SLinus Torvalds out:
12761da177e4SLinus Torvalds 	/* It may be already another descriptor 8) Not kernel problem. */
12771da177e4SLinus Torvalds 	return retval;
12781da177e4SLinus Torvalds 
12791da177e4SLinus Torvalds out_release:
12801da177e4SLinus Torvalds 	sock_release(sock);
12811da177e4SLinus Torvalds 	return retval;
12821da177e4SLinus Torvalds }
12831da177e4SLinus Torvalds 
12841da177e4SLinus Torvalds /*
12851da177e4SLinus Torvalds  *	Create a pair of connected sockets.
12861da177e4SLinus Torvalds  */
12871da177e4SLinus Torvalds 
12883e0fa65fSHeiko Carstens SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
12893e0fa65fSHeiko Carstens 		int __user *, usockvec)
12901da177e4SLinus Torvalds {
12911da177e4SLinus Torvalds 	struct socket *sock1, *sock2;
12921da177e4SLinus Torvalds 	int fd1, fd2, err;
1293db349509SAl Viro 	struct file *newfile1, *newfile2;
1294a677a039SUlrich Drepper 	int flags;
1295a677a039SUlrich Drepper 
1296a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
129777d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1298a677a039SUlrich Drepper 		return -EINVAL;
1299a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
13001da177e4SLinus Torvalds 
1301aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1302aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1303aaca0bdcSUlrich Drepper 
13041da177e4SLinus Torvalds 	/*
13051da177e4SLinus Torvalds 	 * Obtain the first socket and check if the underlying protocol
13061da177e4SLinus Torvalds 	 * supports the socketpair call.
13071da177e4SLinus Torvalds 	 */
13081da177e4SLinus Torvalds 
13091da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock1);
13101da177e4SLinus Torvalds 	if (err < 0)
13111da177e4SLinus Torvalds 		goto out;
13121da177e4SLinus Torvalds 
13131da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock2);
13141da177e4SLinus Torvalds 	if (err < 0)
13151da177e4SLinus Torvalds 		goto out_release_1;
13161da177e4SLinus Torvalds 
13171da177e4SLinus Torvalds 	err = sock1->ops->socketpair(sock1, sock2);
13181da177e4SLinus Torvalds 	if (err < 0)
13191da177e4SLinus Torvalds 		goto out_release_both;
13201da177e4SLinus Torvalds 
132128407630SAl Viro 	fd1 = get_unused_fd_flags(flags);
1322bf3c23d1SDavid S. Miller 	if (unlikely(fd1 < 0)) {
1323bf3c23d1SDavid S. Miller 		err = fd1;
13241da177e4SLinus Torvalds 		goto out_release_both;
1325bf3c23d1SDavid S. Miller 	}
1326d73aa286SYann Droneaud 
132728407630SAl Viro 	fd2 = get_unused_fd_flags(flags);
1328198de4d7SAl Viro 	if (unlikely(fd2 < 0)) {
1329198de4d7SAl Viro 		err = fd2;
1330d73aa286SYann Droneaud 		goto out_put_unused_1;
133128407630SAl Viro 	}
133228407630SAl Viro 
1333aab174f0SLinus Torvalds 	newfile1 = sock_alloc_file(sock1, flags, NULL);
1334b5ffe634SViresh Kumar 	if (IS_ERR(newfile1)) {
133528407630SAl Viro 		err = PTR_ERR(newfile1);
1336d73aa286SYann Droneaud 		goto out_put_unused_both;
133728407630SAl Viro 	}
133828407630SAl Viro 
1339aab174f0SLinus Torvalds 	newfile2 = sock_alloc_file(sock2, flags, NULL);
134028407630SAl Viro 	if (IS_ERR(newfile2)) {
134128407630SAl Viro 		err = PTR_ERR(newfile2);
1342d73aa286SYann Droneaud 		goto out_fput_1;
1343db349509SAl Viro 	}
1344db349509SAl Viro 
1345d73aa286SYann Droneaud 	err = put_user(fd1, &usockvec[0]);
1346d73aa286SYann Droneaud 	if (err)
1347d73aa286SYann Droneaud 		goto out_fput_both;
1348d73aa286SYann Droneaud 
1349d73aa286SYann Droneaud 	err = put_user(fd2, &usockvec[1]);
1350d73aa286SYann Droneaud 	if (err)
1351d73aa286SYann Droneaud 		goto out_fput_both;
1352d73aa286SYann Droneaud 
1353157cf649SAl Viro 	audit_fd_pair(fd1, fd2);
1354d73aa286SYann Droneaud 
1355db349509SAl Viro 	fd_install(fd1, newfile1);
1356db349509SAl Viro 	fd_install(fd2, newfile2);
13571da177e4SLinus Torvalds 	/* fd1 and fd2 may be already another descriptors.
13581da177e4SLinus Torvalds 	 * Not kernel problem.
13591da177e4SLinus Torvalds 	 */
13601da177e4SLinus Torvalds 
13611da177e4SLinus Torvalds 	return 0;
13621da177e4SLinus Torvalds 
1363d73aa286SYann Droneaud out_fput_both:
1364d73aa286SYann Droneaud 	fput(newfile2);
1365d73aa286SYann Droneaud 	fput(newfile1);
1366d73aa286SYann Droneaud 	put_unused_fd(fd2);
1367d73aa286SYann Droneaud 	put_unused_fd(fd1);
1368d73aa286SYann Droneaud 	goto out;
13691da177e4SLinus Torvalds 
1370d73aa286SYann Droneaud out_fput_1:
1371d73aa286SYann Droneaud 	fput(newfile1);
1372d73aa286SYann Droneaud 	put_unused_fd(fd2);
1373d73aa286SYann Droneaud 	put_unused_fd(fd1);
1374d73aa286SYann Droneaud 	sock_release(sock2);
1375d73aa286SYann Droneaud 	goto out;
1376d73aa286SYann Droneaud 
1377d73aa286SYann Droneaud out_put_unused_both:
1378d73aa286SYann Droneaud 	put_unused_fd(fd2);
1379d73aa286SYann Droneaud out_put_unused_1:
1380d73aa286SYann Droneaud 	put_unused_fd(fd1);
13811da177e4SLinus Torvalds out_release_both:
13821da177e4SLinus Torvalds 	sock_release(sock2);
13831da177e4SLinus Torvalds out_release_1:
13841da177e4SLinus Torvalds 	sock_release(sock1);
13851da177e4SLinus Torvalds out:
13861da177e4SLinus Torvalds 	return err;
13871da177e4SLinus Torvalds }
13881da177e4SLinus Torvalds 
13891da177e4SLinus Torvalds /*
13901da177e4SLinus Torvalds  *	Bind a name to a socket. Nothing much to do here since it's
13911da177e4SLinus Torvalds  *	the protocol's responsibility to handle the local address.
13921da177e4SLinus Torvalds  *
13931da177e4SLinus Torvalds  *	We move the socket address to kernel space before we call
13941da177e4SLinus Torvalds  *	the protocol layer (having also checked the address is ok).
13951da177e4SLinus Torvalds  */
13961da177e4SLinus Torvalds 
139720f37034SHeiko Carstens SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
13981da177e4SLinus Torvalds {
13991da177e4SLinus Torvalds 	struct socket *sock;
1400230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
14016cb153caSBenjamin LaHaise 	int err, fput_needed;
14021da177e4SLinus Torvalds 
140389bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
140489bddce5SStephen Hemminger 	if (sock) {
140543db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(umyaddr, addrlen, &address);
140689bddce5SStephen Hemminger 		if (err >= 0) {
140789bddce5SStephen Hemminger 			err = security_socket_bind(sock,
1408230b1839SYOSHIFUJI Hideaki 						   (struct sockaddr *)&address,
140989bddce5SStephen Hemminger 						   addrlen);
14106cb153caSBenjamin LaHaise 			if (!err)
14116cb153caSBenjamin LaHaise 				err = sock->ops->bind(sock,
141289bddce5SStephen Hemminger 						      (struct sockaddr *)
1413230b1839SYOSHIFUJI Hideaki 						      &address, addrlen);
14141da177e4SLinus Torvalds 		}
14156cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
14161da177e4SLinus Torvalds 	}
14171da177e4SLinus Torvalds 	return err;
14181da177e4SLinus Torvalds }
14191da177e4SLinus Torvalds 
14201da177e4SLinus Torvalds /*
14211da177e4SLinus Torvalds  *	Perform a listen. Basically, we allow the protocol to do anything
14221da177e4SLinus Torvalds  *	necessary for a listen, and if that works, we mark the socket as
14231da177e4SLinus Torvalds  *	ready for listening.
14241da177e4SLinus Torvalds  */
14251da177e4SLinus Torvalds 
14263e0fa65fSHeiko Carstens SYSCALL_DEFINE2(listen, int, fd, int, backlog)
14271da177e4SLinus Torvalds {
14281da177e4SLinus Torvalds 	struct socket *sock;
14296cb153caSBenjamin LaHaise 	int err, fput_needed;
1430b8e1f9b5SPavel Emelyanov 	int somaxconn;
14311da177e4SLinus Torvalds 
143289bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
143389bddce5SStephen Hemminger 	if (sock) {
14348efa6e93SPavel Emelyanov 		somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
143595c96174SEric Dumazet 		if ((unsigned int)backlog > somaxconn)
1436b8e1f9b5SPavel Emelyanov 			backlog = somaxconn;
14371da177e4SLinus Torvalds 
14381da177e4SLinus Torvalds 		err = security_socket_listen(sock, backlog);
14396cb153caSBenjamin LaHaise 		if (!err)
14401da177e4SLinus Torvalds 			err = sock->ops->listen(sock, backlog);
14416cb153caSBenjamin LaHaise 
14426cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
14431da177e4SLinus Torvalds 	}
14441da177e4SLinus Torvalds 	return err;
14451da177e4SLinus Torvalds }
14461da177e4SLinus Torvalds 
14471da177e4SLinus Torvalds /*
14481da177e4SLinus Torvalds  *	For accept, we attempt to create a new socket, set up the link
14491da177e4SLinus Torvalds  *	with the client, wake up the client, then return the new
14501da177e4SLinus Torvalds  *	connected fd. We collect the address of the connector in kernel
14511da177e4SLinus Torvalds  *	space and move it to user at the very end. This is unclean because
14521da177e4SLinus Torvalds  *	we open the socket then return an error.
14531da177e4SLinus Torvalds  *
14541da177e4SLinus Torvalds  *	1003.1g adds the ability to recvmsg() to query connection pending
14551da177e4SLinus Torvalds  *	status to recvmsg. We need to add that support in a way thats
14561da177e4SLinus Torvalds  *	clean when we restucture accept also.
14571da177e4SLinus Torvalds  */
14581da177e4SLinus Torvalds 
145920f37034SHeiko Carstens SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
146020f37034SHeiko Carstens 		int __user *, upeer_addrlen, int, flags)
14611da177e4SLinus Torvalds {
14621da177e4SLinus Torvalds 	struct socket *sock, *newsock;
146339d8c1b6SDavid S. Miller 	struct file *newfile;
14646cb153caSBenjamin LaHaise 	int err, len, newfd, fput_needed;
1465230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
14661da177e4SLinus Torvalds 
146777d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1468aaca0bdcSUlrich Drepper 		return -EINVAL;
1469aaca0bdcSUlrich Drepper 
1470aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1471aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1472aaca0bdcSUlrich Drepper 
14736cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
14741da177e4SLinus Torvalds 	if (!sock)
14751da177e4SLinus Torvalds 		goto out;
14761da177e4SLinus Torvalds 
14771da177e4SLinus Torvalds 	err = -ENFILE;
1478c6d409cfSEric Dumazet 	newsock = sock_alloc();
1479c6d409cfSEric Dumazet 	if (!newsock)
14801da177e4SLinus Torvalds 		goto out_put;
14811da177e4SLinus Torvalds 
14821da177e4SLinus Torvalds 	newsock->type = sock->type;
14831da177e4SLinus Torvalds 	newsock->ops = sock->ops;
14841da177e4SLinus Torvalds 
14851da177e4SLinus Torvalds 	/*
14861da177e4SLinus Torvalds 	 * We don't need try_module_get here, as the listening socket (sock)
14871da177e4SLinus Torvalds 	 * has the protocol module (sock->ops->owner) held.
14881da177e4SLinus Torvalds 	 */
14891da177e4SLinus Torvalds 	__module_get(newsock->ops->owner);
14901da177e4SLinus Torvalds 
149128407630SAl Viro 	newfd = get_unused_fd_flags(flags);
149239d8c1b6SDavid S. Miller 	if (unlikely(newfd < 0)) {
149339d8c1b6SDavid S. Miller 		err = newfd;
14949a1875e6SDavid S. Miller 		sock_release(newsock);
14959a1875e6SDavid S. Miller 		goto out_put;
149639d8c1b6SDavid S. Miller 	}
1497aab174f0SLinus Torvalds 	newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name);
1498b5ffe634SViresh Kumar 	if (IS_ERR(newfile)) {
149928407630SAl Viro 		err = PTR_ERR(newfile);
150028407630SAl Viro 		put_unused_fd(newfd);
150128407630SAl Viro 		sock_release(newsock);
150228407630SAl Viro 		goto out_put;
150328407630SAl Viro 	}
150439d8c1b6SDavid S. Miller 
1505a79af59eSFrank Filz 	err = security_socket_accept(sock, newsock);
1506a79af59eSFrank Filz 	if (err)
150739d8c1b6SDavid S. Miller 		goto out_fd;
1508a79af59eSFrank Filz 
15091da177e4SLinus Torvalds 	err = sock->ops->accept(sock, newsock, sock->file->f_flags);
15101da177e4SLinus Torvalds 	if (err < 0)
151139d8c1b6SDavid S. Miller 		goto out_fd;
15121da177e4SLinus Torvalds 
15131da177e4SLinus Torvalds 	if (upeer_sockaddr) {
1514230b1839SYOSHIFUJI Hideaki 		if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
151589bddce5SStephen Hemminger 					  &len, 2) < 0) {
15161da177e4SLinus Torvalds 			err = -ECONNABORTED;
151739d8c1b6SDavid S. Miller 			goto out_fd;
15181da177e4SLinus Torvalds 		}
151943db362dSMaciej Żenczykowski 		err = move_addr_to_user(&address,
1520230b1839SYOSHIFUJI Hideaki 					len, upeer_sockaddr, upeer_addrlen);
15211da177e4SLinus Torvalds 		if (err < 0)
152239d8c1b6SDavid S. Miller 			goto out_fd;
15231da177e4SLinus Torvalds 	}
15241da177e4SLinus Torvalds 
15251da177e4SLinus Torvalds 	/* File flags are not inherited via accept() unlike another OSes. */
15261da177e4SLinus Torvalds 
152739d8c1b6SDavid S. Miller 	fd_install(newfd, newfile);
152839d8c1b6SDavid S. Miller 	err = newfd;
15291da177e4SLinus Torvalds 
15301da177e4SLinus Torvalds out_put:
15316cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
15321da177e4SLinus Torvalds out:
15331da177e4SLinus Torvalds 	return err;
153439d8c1b6SDavid S. Miller out_fd:
15359606a216SDavid S. Miller 	fput(newfile);
153639d8c1b6SDavid S. Miller 	put_unused_fd(newfd);
15371da177e4SLinus Torvalds 	goto out_put;
15381da177e4SLinus Torvalds }
15391da177e4SLinus Torvalds 
154020f37034SHeiko Carstens SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,
154120f37034SHeiko Carstens 		int __user *, upeer_addrlen)
1542aaca0bdcSUlrich Drepper {
1543de11defeSUlrich Drepper 	return sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0);
1544aaca0bdcSUlrich Drepper }
1545aaca0bdcSUlrich Drepper 
15461da177e4SLinus Torvalds /*
15471da177e4SLinus Torvalds  *	Attempt to connect to a socket with the server address.  The address
15481da177e4SLinus Torvalds  *	is in user space so we verify it is OK and move it to kernel space.
15491da177e4SLinus Torvalds  *
15501da177e4SLinus Torvalds  *	For 1003.1g we need to add clean support for a bind to AF_UNSPEC to
15511da177e4SLinus Torvalds  *	break bindings
15521da177e4SLinus Torvalds  *
15531da177e4SLinus Torvalds  *	NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and
15541da177e4SLinus Torvalds  *	other SEQPACKET protocols that take time to connect() as it doesn't
15551da177e4SLinus Torvalds  *	include the -EINPROGRESS status for such sockets.
15561da177e4SLinus Torvalds  */
15571da177e4SLinus Torvalds 
155820f37034SHeiko Carstens SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
155920f37034SHeiko Carstens 		int, addrlen)
15601da177e4SLinus Torvalds {
15611da177e4SLinus Torvalds 	struct socket *sock;
1562230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
15636cb153caSBenjamin LaHaise 	int err, fput_needed;
15641da177e4SLinus Torvalds 
15656cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
15661da177e4SLinus Torvalds 	if (!sock)
15671da177e4SLinus Torvalds 		goto out;
156843db362dSMaciej Żenczykowski 	err = move_addr_to_kernel(uservaddr, addrlen, &address);
15691da177e4SLinus Torvalds 	if (err < 0)
15701da177e4SLinus Torvalds 		goto out_put;
15711da177e4SLinus Torvalds 
157289bddce5SStephen Hemminger 	err =
1573230b1839SYOSHIFUJI Hideaki 	    security_socket_connect(sock, (struct sockaddr *)&address, addrlen);
15741da177e4SLinus Torvalds 	if (err)
15751da177e4SLinus Torvalds 		goto out_put;
15761da177e4SLinus Torvalds 
1577230b1839SYOSHIFUJI Hideaki 	err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,
15781da177e4SLinus Torvalds 				 sock->file->f_flags);
15791da177e4SLinus Torvalds out_put:
15806cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
15811da177e4SLinus Torvalds out:
15821da177e4SLinus Torvalds 	return err;
15831da177e4SLinus Torvalds }
15841da177e4SLinus Torvalds 
15851da177e4SLinus Torvalds /*
15861da177e4SLinus Torvalds  *	Get the local address ('name') of a socket object. Move the obtained
15871da177e4SLinus Torvalds  *	name to user space.
15881da177e4SLinus Torvalds  */
15891da177e4SLinus Torvalds 
159020f37034SHeiko Carstens SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
159120f37034SHeiko Carstens 		int __user *, usockaddr_len)
15921da177e4SLinus Torvalds {
15931da177e4SLinus Torvalds 	struct socket *sock;
1594230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
15956cb153caSBenjamin LaHaise 	int len, err, fput_needed;
15961da177e4SLinus Torvalds 
15976cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
15981da177e4SLinus Torvalds 	if (!sock)
15991da177e4SLinus Torvalds 		goto out;
16001da177e4SLinus Torvalds 
16011da177e4SLinus Torvalds 	err = security_socket_getsockname(sock);
16021da177e4SLinus Torvalds 	if (err)
16031da177e4SLinus Torvalds 		goto out_put;
16041da177e4SLinus Torvalds 
1605230b1839SYOSHIFUJI Hideaki 	err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0);
16061da177e4SLinus Torvalds 	if (err)
16071da177e4SLinus Torvalds 		goto out_put;
160843db362dSMaciej Żenczykowski 	err = move_addr_to_user(&address, len, usockaddr, usockaddr_len);
16091da177e4SLinus Torvalds 
16101da177e4SLinus Torvalds out_put:
16116cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
16121da177e4SLinus Torvalds out:
16131da177e4SLinus Torvalds 	return err;
16141da177e4SLinus Torvalds }
16151da177e4SLinus Torvalds 
16161da177e4SLinus Torvalds /*
16171da177e4SLinus Torvalds  *	Get the remote address ('name') of a socket object. Move the obtained
16181da177e4SLinus Torvalds  *	name to user space.
16191da177e4SLinus Torvalds  */
16201da177e4SLinus Torvalds 
162120f37034SHeiko Carstens SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
162220f37034SHeiko Carstens 		int __user *, usockaddr_len)
16231da177e4SLinus Torvalds {
16241da177e4SLinus Torvalds 	struct socket *sock;
1625230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16266cb153caSBenjamin LaHaise 	int len, err, fput_needed;
16271da177e4SLinus Torvalds 
162889bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
162989bddce5SStephen Hemminger 	if (sock != NULL) {
16301da177e4SLinus Torvalds 		err = security_socket_getpeername(sock);
16311da177e4SLinus Torvalds 		if (err) {
16326cb153caSBenjamin LaHaise 			fput_light(sock->file, fput_needed);
16331da177e4SLinus Torvalds 			return err;
16341da177e4SLinus Torvalds 		}
16351da177e4SLinus Torvalds 
163689bddce5SStephen Hemminger 		err =
1637230b1839SYOSHIFUJI Hideaki 		    sock->ops->getname(sock, (struct sockaddr *)&address, &len,
163889bddce5SStephen Hemminger 				       1);
16391da177e4SLinus Torvalds 		if (!err)
164043db362dSMaciej Żenczykowski 			err = move_addr_to_user(&address, len, usockaddr,
164189bddce5SStephen Hemminger 						usockaddr_len);
16426cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
16431da177e4SLinus Torvalds 	}
16441da177e4SLinus Torvalds 	return err;
16451da177e4SLinus Torvalds }
16461da177e4SLinus Torvalds 
16471da177e4SLinus Torvalds /*
16481da177e4SLinus Torvalds  *	Send a datagram to a given address. We move the address into kernel
16491da177e4SLinus Torvalds  *	space and check the user space data area is readable before invoking
16501da177e4SLinus Torvalds  *	the protocol.
16511da177e4SLinus Torvalds  */
16521da177e4SLinus Torvalds 
16533e0fa65fSHeiko Carstens SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
165495c96174SEric Dumazet 		unsigned int, flags, struct sockaddr __user *, addr,
16553e0fa65fSHeiko Carstens 		int, addr_len)
16561da177e4SLinus Torvalds {
16571da177e4SLinus Torvalds 	struct socket *sock;
1658230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16591da177e4SLinus Torvalds 	int err;
16601da177e4SLinus Torvalds 	struct msghdr msg;
16611da177e4SLinus Torvalds 	struct iovec iov;
16626cb153caSBenjamin LaHaise 	int fput_needed;
16631da177e4SLinus Torvalds 
1664602bd0e9SAl Viro 	err = import_single_range(WRITE, buff, len, &iov, &msg.msg_iter);
1665602bd0e9SAl Viro 	if (unlikely(err))
1666602bd0e9SAl Viro 		return err;
1667de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1668de0fa95cSPavel Emelyanov 	if (!sock)
16694387ff75SDavid S. Miller 		goto out;
16706cb153caSBenjamin LaHaise 
16711da177e4SLinus Torvalds 	msg.msg_name = NULL;
16721da177e4SLinus Torvalds 	msg.msg_control = NULL;
16731da177e4SLinus Torvalds 	msg.msg_controllen = 0;
16741da177e4SLinus Torvalds 	msg.msg_namelen = 0;
16756cb153caSBenjamin LaHaise 	if (addr) {
167643db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(addr, addr_len, &address);
16771da177e4SLinus Torvalds 		if (err < 0)
16781da177e4SLinus Torvalds 			goto out_put;
1679230b1839SYOSHIFUJI Hideaki 		msg.msg_name = (struct sockaddr *)&address;
16801da177e4SLinus Torvalds 		msg.msg_namelen = addr_len;
16811da177e4SLinus Torvalds 	}
16821da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
16831da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
16841da177e4SLinus Torvalds 	msg.msg_flags = flags;
1685d8725c86SAl Viro 	err = sock_sendmsg(sock, &msg);
16861da177e4SLinus Torvalds 
16871da177e4SLinus Torvalds out_put:
1688de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
16894387ff75SDavid S. Miller out:
16901da177e4SLinus Torvalds 	return err;
16911da177e4SLinus Torvalds }
16921da177e4SLinus Torvalds 
16931da177e4SLinus Torvalds /*
16941da177e4SLinus Torvalds  *	Send a datagram down a socket.
16951da177e4SLinus Torvalds  */
16961da177e4SLinus Torvalds 
16973e0fa65fSHeiko Carstens SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len,
169895c96174SEric Dumazet 		unsigned int, flags)
16991da177e4SLinus Torvalds {
17001da177e4SLinus Torvalds 	return sys_sendto(fd, buff, len, flags, NULL, 0);
17011da177e4SLinus Torvalds }
17021da177e4SLinus Torvalds 
17031da177e4SLinus Torvalds /*
17041da177e4SLinus Torvalds  *	Receive a frame from the socket and optionally record the address of the
17051da177e4SLinus Torvalds  *	sender. We verify the buffers are writable and if needed move the
17061da177e4SLinus Torvalds  *	sender address from kernel to user space.
17071da177e4SLinus Torvalds  */
17081da177e4SLinus Torvalds 
17093e0fa65fSHeiko Carstens SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
171095c96174SEric Dumazet 		unsigned int, flags, struct sockaddr __user *, addr,
17113e0fa65fSHeiko Carstens 		int __user *, addr_len)
17121da177e4SLinus Torvalds {
17131da177e4SLinus Torvalds 	struct socket *sock;
17141da177e4SLinus Torvalds 	struct iovec iov;
17151da177e4SLinus Torvalds 	struct msghdr msg;
1716230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
17171da177e4SLinus Torvalds 	int err, err2;
17186cb153caSBenjamin LaHaise 	int fput_needed;
17191da177e4SLinus Torvalds 
1720602bd0e9SAl Viro 	err = import_single_range(READ, ubuf, size, &iov, &msg.msg_iter);
1721602bd0e9SAl Viro 	if (unlikely(err))
1722602bd0e9SAl Viro 		return err;
1723de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
17241da177e4SLinus Torvalds 	if (!sock)
1725de0fa95cSPavel Emelyanov 		goto out;
17261da177e4SLinus Torvalds 
17271da177e4SLinus Torvalds 	msg.msg_control = NULL;
17281da177e4SLinus Torvalds 	msg.msg_controllen = 0;
1729f3d33426SHannes Frederic Sowa 	/* Save some cycles and don't copy the address if not needed */
1730f3d33426SHannes Frederic Sowa 	msg.msg_name = addr ? (struct sockaddr *)&address : NULL;
1731f3d33426SHannes Frederic Sowa 	/* We assume all kernel code knows the size of sockaddr_storage */
1732f3d33426SHannes Frederic Sowa 	msg.msg_namelen = 0;
1733130ed5d1Stadeusz.struk@intel.com 	msg.msg_iocb = NULL;
17349f138fa6SAlexander Potapenko 	msg.msg_flags = 0;
17351da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
17361da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
17372da62906SAl Viro 	err = sock_recvmsg(sock, &msg, flags);
17381da177e4SLinus Torvalds 
173989bddce5SStephen Hemminger 	if (err >= 0 && addr != NULL) {
174043db362dSMaciej Żenczykowski 		err2 = move_addr_to_user(&address,
1741230b1839SYOSHIFUJI Hideaki 					 msg.msg_namelen, addr, addr_len);
17421da177e4SLinus Torvalds 		if (err2 < 0)
17431da177e4SLinus Torvalds 			err = err2;
17441da177e4SLinus Torvalds 	}
1745de0fa95cSPavel Emelyanov 
1746de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
17474387ff75SDavid S. Miller out:
17481da177e4SLinus Torvalds 	return err;
17491da177e4SLinus Torvalds }
17501da177e4SLinus Torvalds 
17511da177e4SLinus Torvalds /*
17521da177e4SLinus Torvalds  *	Receive a datagram from a socket.
17531da177e4SLinus Torvalds  */
17541da177e4SLinus Torvalds 
1755b7c0ddf5SJan Glauber SYSCALL_DEFINE4(recv, int, fd, void __user *, ubuf, size_t, size,
1756b7c0ddf5SJan Glauber 		unsigned int, flags)
17571da177e4SLinus Torvalds {
17581da177e4SLinus Torvalds 	return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL);
17591da177e4SLinus Torvalds }
17601da177e4SLinus Torvalds 
17611da177e4SLinus Torvalds /*
17621da177e4SLinus Torvalds  *	Set a socket option. Because we don't know the option lengths we have
17631da177e4SLinus Torvalds  *	to pass the user mode parameter for the protocols to sort out.
17641da177e4SLinus Torvalds  */
17651da177e4SLinus Torvalds 
176620f37034SHeiko Carstens SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
176720f37034SHeiko Carstens 		char __user *, optval, int, optlen)
17681da177e4SLinus Torvalds {
17696cb153caSBenjamin LaHaise 	int err, fput_needed;
17701da177e4SLinus Torvalds 	struct socket *sock;
17711da177e4SLinus Torvalds 
17721da177e4SLinus Torvalds 	if (optlen < 0)
17731da177e4SLinus Torvalds 		return -EINVAL;
17741da177e4SLinus Torvalds 
177589bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
177689bddce5SStephen Hemminger 	if (sock != NULL) {
17771da177e4SLinus Torvalds 		err = security_socket_setsockopt(sock, level, optname);
17786cb153caSBenjamin LaHaise 		if (err)
17796cb153caSBenjamin LaHaise 			goto out_put;
17801da177e4SLinus Torvalds 
17811da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
178289bddce5SStephen Hemminger 			err =
178389bddce5SStephen Hemminger 			    sock_setsockopt(sock, level, optname, optval,
178489bddce5SStephen Hemminger 					    optlen);
17851da177e4SLinus Torvalds 		else
178689bddce5SStephen Hemminger 			err =
178789bddce5SStephen Hemminger 			    sock->ops->setsockopt(sock, level, optname, optval,
178889bddce5SStephen Hemminger 						  optlen);
17896cb153caSBenjamin LaHaise out_put:
17906cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
17911da177e4SLinus Torvalds 	}
17921da177e4SLinus Torvalds 	return err;
17931da177e4SLinus Torvalds }
17941da177e4SLinus Torvalds 
17951da177e4SLinus Torvalds /*
17961da177e4SLinus Torvalds  *	Get a socket option. Because we don't know the option lengths we have
17971da177e4SLinus Torvalds  *	to pass a user mode parameter for the protocols to sort out.
17981da177e4SLinus Torvalds  */
17991da177e4SLinus Torvalds 
180020f37034SHeiko Carstens SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
180120f37034SHeiko Carstens 		char __user *, optval, int __user *, optlen)
18021da177e4SLinus Torvalds {
18036cb153caSBenjamin LaHaise 	int err, fput_needed;
18041da177e4SLinus Torvalds 	struct socket *sock;
18051da177e4SLinus Torvalds 
180689bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
180789bddce5SStephen Hemminger 	if (sock != NULL) {
18086cb153caSBenjamin LaHaise 		err = security_socket_getsockopt(sock, level, optname);
18096cb153caSBenjamin LaHaise 		if (err)
18106cb153caSBenjamin LaHaise 			goto out_put;
18111da177e4SLinus Torvalds 
18121da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
181389bddce5SStephen Hemminger 			err =
181489bddce5SStephen Hemminger 			    sock_getsockopt(sock, level, optname, optval,
181589bddce5SStephen Hemminger 					    optlen);
18161da177e4SLinus Torvalds 		else
181789bddce5SStephen Hemminger 			err =
181889bddce5SStephen Hemminger 			    sock->ops->getsockopt(sock, level, optname, optval,
181989bddce5SStephen Hemminger 						  optlen);
18206cb153caSBenjamin LaHaise out_put:
18216cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
18221da177e4SLinus Torvalds 	}
18231da177e4SLinus Torvalds 	return err;
18241da177e4SLinus Torvalds }
18251da177e4SLinus Torvalds 
18261da177e4SLinus Torvalds /*
18271da177e4SLinus Torvalds  *	Shutdown a socket.
18281da177e4SLinus Torvalds  */
18291da177e4SLinus Torvalds 
1830754fe8d2SHeiko Carstens SYSCALL_DEFINE2(shutdown, int, fd, int, how)
18311da177e4SLinus Torvalds {
18326cb153caSBenjamin LaHaise 	int err, fput_needed;
18331da177e4SLinus Torvalds 	struct socket *sock;
18341da177e4SLinus Torvalds 
183589bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
183689bddce5SStephen Hemminger 	if (sock != NULL) {
18371da177e4SLinus Torvalds 		err = security_socket_shutdown(sock, how);
18386cb153caSBenjamin LaHaise 		if (!err)
18391da177e4SLinus Torvalds 			err = sock->ops->shutdown(sock, how);
18406cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
18411da177e4SLinus Torvalds 	}
18421da177e4SLinus Torvalds 	return err;
18431da177e4SLinus Torvalds }
18441da177e4SLinus Torvalds 
18451da177e4SLinus Torvalds /* A couple of helpful macros for getting the address of the 32/64 bit
18461da177e4SLinus Torvalds  * fields which are the same type (int / unsigned) on our platforms.
18471da177e4SLinus Torvalds  */
18481da177e4SLinus Torvalds #define COMPAT_MSG(msg, member)	((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member)
18491da177e4SLinus Torvalds #define COMPAT_NAMELEN(msg)	COMPAT_MSG(msg, msg_namelen)
18501da177e4SLinus Torvalds #define COMPAT_FLAGS(msg)	COMPAT_MSG(msg, msg_flags)
18511da177e4SLinus Torvalds 
1852c71d8ebeSTetsuo Handa struct used_address {
1853c71d8ebeSTetsuo Handa 	struct sockaddr_storage name;
1854c71d8ebeSTetsuo Handa 	unsigned int name_len;
1855c71d8ebeSTetsuo Handa };
1856c71d8ebeSTetsuo Handa 
1857da184284SAl Viro static int copy_msghdr_from_user(struct msghdr *kmsg,
185808adb7daSAl Viro 				 struct user_msghdr __user *umsg,
185908adb7daSAl Viro 				 struct sockaddr __user **save_addr,
186008adb7daSAl Viro 				 struct iovec **iov)
18611661bf36SDan Carpenter {
186208adb7daSAl Viro 	struct sockaddr __user *uaddr;
186308adb7daSAl Viro 	struct iovec __user *uiov;
1864c0371da6SAl Viro 	size_t nr_segs;
186508adb7daSAl Viro 	ssize_t err;
186608adb7daSAl Viro 
186708adb7daSAl Viro 	if (!access_ok(VERIFY_READ, umsg, sizeof(*umsg)) ||
186808adb7daSAl Viro 	    __get_user(uaddr, &umsg->msg_name) ||
186908adb7daSAl Viro 	    __get_user(kmsg->msg_namelen, &umsg->msg_namelen) ||
187008adb7daSAl Viro 	    __get_user(uiov, &umsg->msg_iov) ||
1871c0371da6SAl Viro 	    __get_user(nr_segs, &umsg->msg_iovlen) ||
187208adb7daSAl Viro 	    __get_user(kmsg->msg_control, &umsg->msg_control) ||
187308adb7daSAl Viro 	    __get_user(kmsg->msg_controllen, &umsg->msg_controllen) ||
187408adb7daSAl Viro 	    __get_user(kmsg->msg_flags, &umsg->msg_flags))
18751661bf36SDan Carpenter 		return -EFAULT;
1876dbb490b9SMatthew Leach 
187708adb7daSAl Viro 	if (!uaddr)
18786a2a2b3aSAni Sinha 		kmsg->msg_namelen = 0;
18796a2a2b3aSAni Sinha 
1880dbb490b9SMatthew Leach 	if (kmsg->msg_namelen < 0)
1881dbb490b9SMatthew Leach 		return -EINVAL;
1882dbb490b9SMatthew Leach 
18831661bf36SDan Carpenter 	if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
1884db31c55aSDan Carpenter 		kmsg->msg_namelen = sizeof(struct sockaddr_storage);
188508adb7daSAl Viro 
188608adb7daSAl Viro 	if (save_addr)
188708adb7daSAl Viro 		*save_addr = uaddr;
188808adb7daSAl Viro 
188908adb7daSAl Viro 	if (uaddr && kmsg->msg_namelen) {
189008adb7daSAl Viro 		if (!save_addr) {
189108adb7daSAl Viro 			err = move_addr_to_kernel(uaddr, kmsg->msg_namelen,
189208adb7daSAl Viro 						  kmsg->msg_name);
189308adb7daSAl Viro 			if (err < 0)
189408adb7daSAl Viro 				return err;
189508adb7daSAl Viro 		}
189608adb7daSAl Viro 	} else {
189708adb7daSAl Viro 		kmsg->msg_name = NULL;
189808adb7daSAl Viro 		kmsg->msg_namelen = 0;
189908adb7daSAl Viro 	}
190008adb7daSAl Viro 
1901c0371da6SAl Viro 	if (nr_segs > UIO_MAXIOV)
190208adb7daSAl Viro 		return -EMSGSIZE;
190308adb7daSAl Viro 
19040345f931Stadeusz.struk@intel.com 	kmsg->msg_iocb = NULL;
19050345f931Stadeusz.struk@intel.com 
1906da184284SAl Viro 	return import_iovec(save_addr ? READ : WRITE, uiov, nr_segs,
1907da184284SAl Viro 			    UIO_FASTIOV, iov, &kmsg->msg_iter);
19081661bf36SDan Carpenter }
19091661bf36SDan Carpenter 
1910666547ffSAl Viro static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
191195c96174SEric Dumazet 			 struct msghdr *msg_sys, unsigned int flags,
191228a94d8fSTom Herbert 			 struct used_address *used_address,
191328a94d8fSTom Herbert 			 unsigned int allowed_msghdr_flags)
19141da177e4SLinus Torvalds {
191589bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
191689bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
1917230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
19181da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
1919b9d717a7SAlex Williamson 	unsigned char ctl[sizeof(struct cmsghdr) + 20]
1920846cc123SAmit Kushwaha 				__aligned(sizeof(__kernel_size_t));
1921b9d717a7SAlex Williamson 	/* 20 is size of ipv6_pktinfo */
19221da177e4SLinus Torvalds 	unsigned char *ctl_buf = ctl;
1923d8725c86SAl Viro 	int ctl_len;
192408adb7daSAl Viro 	ssize_t err;
19251da177e4SLinus Torvalds 
192608adb7daSAl Viro 	msg_sys->msg_name = &address;
19271da177e4SLinus Torvalds 
192808449320SAl Viro 	if (MSG_CMSG_COMPAT & flags)
192908adb7daSAl Viro 		err = get_compat_msghdr(msg_sys, msg_compat, NULL, &iov);
193008449320SAl Viro 	else
193108adb7daSAl Viro 		err = copy_msghdr_from_user(msg_sys, msg, NULL, &iov);
19321da177e4SLinus Torvalds 	if (err < 0)
1933da184284SAl Viro 		return err;
19341da177e4SLinus Torvalds 
19351da177e4SLinus Torvalds 	err = -ENOBUFS;
19361da177e4SLinus Torvalds 
1937228e548eSAnton Blanchard 	if (msg_sys->msg_controllen > INT_MAX)
19381da177e4SLinus Torvalds 		goto out_freeiov;
193928a94d8fSTom Herbert 	flags |= (msg_sys->msg_flags & allowed_msghdr_flags);
1940228e548eSAnton Blanchard 	ctl_len = msg_sys->msg_controllen;
19411da177e4SLinus Torvalds 	if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
194289bddce5SStephen Hemminger 		err =
1943228e548eSAnton Blanchard 		    cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl,
194489bddce5SStephen Hemminger 						     sizeof(ctl));
19451da177e4SLinus Torvalds 		if (err)
19461da177e4SLinus Torvalds 			goto out_freeiov;
1947228e548eSAnton Blanchard 		ctl_buf = msg_sys->msg_control;
1948228e548eSAnton Blanchard 		ctl_len = msg_sys->msg_controllen;
19491da177e4SLinus Torvalds 	} else if (ctl_len) {
1950ac4340fcSDavid S. Miller 		BUILD_BUG_ON(sizeof(struct cmsghdr) !=
1951ac4340fcSDavid S. Miller 			     CMSG_ALIGN(sizeof(struct cmsghdr)));
195289bddce5SStephen Hemminger 		if (ctl_len > sizeof(ctl)) {
19531da177e4SLinus Torvalds 			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
19541da177e4SLinus Torvalds 			if (ctl_buf == NULL)
19551da177e4SLinus Torvalds 				goto out_freeiov;
19561da177e4SLinus Torvalds 		}
19571da177e4SLinus Torvalds 		err = -EFAULT;
19581da177e4SLinus Torvalds 		/*
1959228e548eSAnton Blanchard 		 * Careful! Before this, msg_sys->msg_control contains a user pointer.
19601da177e4SLinus Torvalds 		 * Afterwards, it will be a kernel pointer. Thus the compiler-assisted
19611da177e4SLinus Torvalds 		 * checking falls down on this.
19621da177e4SLinus Torvalds 		 */
1963fb8621bbSNamhyung Kim 		if (copy_from_user(ctl_buf,
1964228e548eSAnton Blanchard 				   (void __user __force *)msg_sys->msg_control,
196589bddce5SStephen Hemminger 				   ctl_len))
19661da177e4SLinus Torvalds 			goto out_freectl;
1967228e548eSAnton Blanchard 		msg_sys->msg_control = ctl_buf;
19681da177e4SLinus Torvalds 	}
1969228e548eSAnton Blanchard 	msg_sys->msg_flags = flags;
19701da177e4SLinus Torvalds 
19711da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
1972228e548eSAnton Blanchard 		msg_sys->msg_flags |= MSG_DONTWAIT;
1973c71d8ebeSTetsuo Handa 	/*
1974c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and current destination address is same as
1975c71d8ebeSTetsuo Handa 	 * previously succeeded address, omit asking LSM's decision.
1976c71d8ebeSTetsuo Handa 	 * used_address->name_len is initialized to UINT_MAX so that the first
1977c71d8ebeSTetsuo Handa 	 * destination address never matches.
1978c71d8ebeSTetsuo Handa 	 */
1979bc909d9dSMathieu Desnoyers 	if (used_address && msg_sys->msg_name &&
1980bc909d9dSMathieu Desnoyers 	    used_address->name_len == msg_sys->msg_namelen &&
1981bc909d9dSMathieu Desnoyers 	    !memcmp(&used_address->name, msg_sys->msg_name,
1982c71d8ebeSTetsuo Handa 		    used_address->name_len)) {
1983d8725c86SAl Viro 		err = sock_sendmsg_nosec(sock, msg_sys);
1984c71d8ebeSTetsuo Handa 		goto out_freectl;
1985c71d8ebeSTetsuo Handa 	}
1986d8725c86SAl Viro 	err = sock_sendmsg(sock, msg_sys);
1987c71d8ebeSTetsuo Handa 	/*
1988c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and sending to current destination address was
1989c71d8ebeSTetsuo Handa 	 * successful, remember it.
1990c71d8ebeSTetsuo Handa 	 */
1991c71d8ebeSTetsuo Handa 	if (used_address && err >= 0) {
1992c71d8ebeSTetsuo Handa 		used_address->name_len = msg_sys->msg_namelen;
1993bc909d9dSMathieu Desnoyers 		if (msg_sys->msg_name)
1994bc909d9dSMathieu Desnoyers 			memcpy(&used_address->name, msg_sys->msg_name,
1995c71d8ebeSTetsuo Handa 			       used_address->name_len);
1996c71d8ebeSTetsuo Handa 	}
19971da177e4SLinus Torvalds 
19981da177e4SLinus Torvalds out_freectl:
19991da177e4SLinus Torvalds 	if (ctl_buf != ctl)
20001da177e4SLinus Torvalds 		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
20011da177e4SLinus Torvalds out_freeiov:
2002a74e9106SEric Dumazet 	kfree(iov);
2003228e548eSAnton Blanchard 	return err;
2004228e548eSAnton Blanchard }
2005228e548eSAnton Blanchard 
2006228e548eSAnton Blanchard /*
2007228e548eSAnton Blanchard  *	BSD sendmsg interface
2008228e548eSAnton Blanchard  */
2009228e548eSAnton Blanchard 
2010666547ffSAl Viro long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned flags)
2011228e548eSAnton Blanchard {
2012228e548eSAnton Blanchard 	int fput_needed, err;
2013228e548eSAnton Blanchard 	struct msghdr msg_sys;
20141be374a0SAndy Lutomirski 	struct socket *sock;
2015228e548eSAnton Blanchard 
20161be374a0SAndy Lutomirski 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2017228e548eSAnton Blanchard 	if (!sock)
2018228e548eSAnton Blanchard 		goto out;
2019228e548eSAnton Blanchard 
202028a94d8fSTom Herbert 	err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL, 0);
2021228e548eSAnton Blanchard 
20226cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
20231da177e4SLinus Torvalds out:
20241da177e4SLinus Torvalds 	return err;
20251da177e4SLinus Torvalds }
20261da177e4SLinus Torvalds 
2027666547ffSAl Viro SYSCALL_DEFINE3(sendmsg, int, fd, struct user_msghdr __user *, msg, unsigned int, flags)
2028a7526eb5SAndy Lutomirski {
2029a7526eb5SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
2030a7526eb5SAndy Lutomirski 		return -EINVAL;
2031a7526eb5SAndy Lutomirski 	return __sys_sendmsg(fd, msg, flags);
2032a7526eb5SAndy Lutomirski }
2033a7526eb5SAndy Lutomirski 
2034228e548eSAnton Blanchard /*
2035228e548eSAnton Blanchard  *	Linux sendmmsg interface
2036228e548eSAnton Blanchard  */
2037228e548eSAnton Blanchard 
2038228e548eSAnton Blanchard int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2039228e548eSAnton Blanchard 		   unsigned int flags)
2040228e548eSAnton Blanchard {
2041228e548eSAnton Blanchard 	int fput_needed, err, datagrams;
2042228e548eSAnton Blanchard 	struct socket *sock;
2043228e548eSAnton Blanchard 	struct mmsghdr __user *entry;
2044228e548eSAnton Blanchard 	struct compat_mmsghdr __user *compat_entry;
2045228e548eSAnton Blanchard 	struct msghdr msg_sys;
2046c71d8ebeSTetsuo Handa 	struct used_address used_address;
2047f092276dSTom Herbert 	unsigned int oflags = flags;
2048228e548eSAnton Blanchard 
204998382f41SAnton Blanchard 	if (vlen > UIO_MAXIOV)
205098382f41SAnton Blanchard 		vlen = UIO_MAXIOV;
2051228e548eSAnton Blanchard 
2052228e548eSAnton Blanchard 	datagrams = 0;
2053228e548eSAnton Blanchard 
2054228e548eSAnton Blanchard 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2055228e548eSAnton Blanchard 	if (!sock)
2056228e548eSAnton Blanchard 		return err;
2057228e548eSAnton Blanchard 
2058c71d8ebeSTetsuo Handa 	used_address.name_len = UINT_MAX;
2059228e548eSAnton Blanchard 	entry = mmsg;
2060228e548eSAnton Blanchard 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2061728ffb86SAnton Blanchard 	err = 0;
2062f092276dSTom Herbert 	flags |= MSG_BATCH;
2063228e548eSAnton Blanchard 
2064228e548eSAnton Blanchard 	while (datagrams < vlen) {
2065f092276dSTom Herbert 		if (datagrams == vlen - 1)
2066f092276dSTom Herbert 			flags = oflags;
2067f092276dSTom Herbert 
2068228e548eSAnton Blanchard 		if (MSG_CMSG_COMPAT & flags) {
2069666547ffSAl Viro 			err = ___sys_sendmsg(sock, (struct user_msghdr __user *)compat_entry,
207028a94d8fSTom Herbert 					     &msg_sys, flags, &used_address, MSG_EOR);
2071228e548eSAnton Blanchard 			if (err < 0)
2072228e548eSAnton Blanchard 				break;
2073228e548eSAnton Blanchard 			err = __put_user(err, &compat_entry->msg_len);
2074228e548eSAnton Blanchard 			++compat_entry;
2075228e548eSAnton Blanchard 		} else {
2076a7526eb5SAndy Lutomirski 			err = ___sys_sendmsg(sock,
2077666547ffSAl Viro 					     (struct user_msghdr __user *)entry,
207828a94d8fSTom Herbert 					     &msg_sys, flags, &used_address, MSG_EOR);
2079228e548eSAnton Blanchard 			if (err < 0)
2080228e548eSAnton Blanchard 				break;
2081228e548eSAnton Blanchard 			err = put_user(err, &entry->msg_len);
2082228e548eSAnton Blanchard 			++entry;
2083228e548eSAnton Blanchard 		}
2084228e548eSAnton Blanchard 
2085228e548eSAnton Blanchard 		if (err)
2086228e548eSAnton Blanchard 			break;
2087228e548eSAnton Blanchard 		++datagrams;
20883023898bSSoheil Hassas Yeganeh 		if (msg_data_left(&msg_sys))
20893023898bSSoheil Hassas Yeganeh 			break;
2090a78cb84cSEric Dumazet 		cond_resched();
2091228e548eSAnton Blanchard 	}
2092228e548eSAnton Blanchard 
2093228e548eSAnton Blanchard 	fput_light(sock->file, fput_needed);
2094228e548eSAnton Blanchard 
2095728ffb86SAnton Blanchard 	/* We only return an error if no datagrams were able to be sent */
2096728ffb86SAnton Blanchard 	if (datagrams != 0)
2097228e548eSAnton Blanchard 		return datagrams;
2098228e548eSAnton Blanchard 
2099228e548eSAnton Blanchard 	return err;
2100228e548eSAnton Blanchard }
2101228e548eSAnton Blanchard 
2102228e548eSAnton Blanchard SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
2103228e548eSAnton Blanchard 		unsigned int, vlen, unsigned int, flags)
2104228e548eSAnton Blanchard {
21051be374a0SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
21061be374a0SAndy Lutomirski 		return -EINVAL;
2107228e548eSAnton Blanchard 	return __sys_sendmmsg(fd, mmsg, vlen, flags);
2108228e548eSAnton Blanchard }
2109228e548eSAnton Blanchard 
2110666547ffSAl Viro static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg,
211195c96174SEric Dumazet 			 struct msghdr *msg_sys, unsigned int flags, int nosec)
21121da177e4SLinus Torvalds {
211389bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
211489bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
21151da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV];
21161da177e4SLinus Torvalds 	struct iovec *iov = iovstack;
21171da177e4SLinus Torvalds 	unsigned long cmsg_ptr;
21182da62906SAl Viro 	int len;
211908adb7daSAl Viro 	ssize_t err;
21201da177e4SLinus Torvalds 
21211da177e4SLinus Torvalds 	/* kernel mode address */
2122230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage addr;
21231da177e4SLinus Torvalds 
21241da177e4SLinus Torvalds 	/* user mode address pointers */
21251da177e4SLinus Torvalds 	struct sockaddr __user *uaddr;
212608adb7daSAl Viro 	int __user *uaddr_len = COMPAT_NAMELEN(msg);
21271da177e4SLinus Torvalds 
212808adb7daSAl Viro 	msg_sys->msg_name = &addr;
21291da177e4SLinus Torvalds 
2130f3d33426SHannes Frederic Sowa 	if (MSG_CMSG_COMPAT & flags)
213108adb7daSAl Viro 		err = get_compat_msghdr(msg_sys, msg_compat, &uaddr, &iov);
2132f3d33426SHannes Frederic Sowa 	else
213308adb7daSAl Viro 		err = copy_msghdr_from_user(msg_sys, msg, &uaddr, &iov);
21341da177e4SLinus Torvalds 	if (err < 0)
2135da184284SAl Viro 		return err;
21361da177e4SLinus Torvalds 
2137a2e27255SArnaldo Carvalho de Melo 	cmsg_ptr = (unsigned long)msg_sys->msg_control;
2138a2e27255SArnaldo Carvalho de Melo 	msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
21391da177e4SLinus Torvalds 
2140f3d33426SHannes Frederic Sowa 	/* We assume all kernel code knows the size of sockaddr_storage */
2141f3d33426SHannes Frederic Sowa 	msg_sys->msg_namelen = 0;
2142f3d33426SHannes Frederic Sowa 
21431da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
21441da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
21452da62906SAl Viro 	err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys, flags);
21461da177e4SLinus Torvalds 	if (err < 0)
21471da177e4SLinus Torvalds 		goto out_freeiov;
21481da177e4SLinus Torvalds 	len = err;
21491da177e4SLinus Torvalds 
21501da177e4SLinus Torvalds 	if (uaddr != NULL) {
215143db362dSMaciej Żenczykowski 		err = move_addr_to_user(&addr,
2152a2e27255SArnaldo Carvalho de Melo 					msg_sys->msg_namelen, uaddr,
215389bddce5SStephen Hemminger 					uaddr_len);
21541da177e4SLinus Torvalds 		if (err < 0)
21551da177e4SLinus Torvalds 			goto out_freeiov;
21561da177e4SLinus Torvalds 	}
2157a2e27255SArnaldo Carvalho de Melo 	err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
215837f7f421SDavid S. Miller 			 COMPAT_FLAGS(msg));
21591da177e4SLinus Torvalds 	if (err)
21601da177e4SLinus Torvalds 		goto out_freeiov;
21611da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags)
2162a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
21631da177e4SLinus Torvalds 				 &msg_compat->msg_controllen);
21641da177e4SLinus Torvalds 	else
2165a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
21661da177e4SLinus Torvalds 				 &msg->msg_controllen);
21671da177e4SLinus Torvalds 	if (err)
21681da177e4SLinus Torvalds 		goto out_freeiov;
21691da177e4SLinus Torvalds 	err = len;
21701da177e4SLinus Torvalds 
21711da177e4SLinus Torvalds out_freeiov:
2172a74e9106SEric Dumazet 	kfree(iov);
2173a2e27255SArnaldo Carvalho de Melo 	return err;
2174a2e27255SArnaldo Carvalho de Melo }
2175a2e27255SArnaldo Carvalho de Melo 
2176a2e27255SArnaldo Carvalho de Melo /*
2177a2e27255SArnaldo Carvalho de Melo  *	BSD recvmsg interface
2178a2e27255SArnaldo Carvalho de Melo  */
2179a2e27255SArnaldo Carvalho de Melo 
2180666547ffSAl Viro long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned flags)
2181a2e27255SArnaldo Carvalho de Melo {
2182a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err;
2183a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
21841be374a0SAndy Lutomirski 	struct socket *sock;
2185a2e27255SArnaldo Carvalho de Melo 
21861be374a0SAndy Lutomirski 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2187a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2188a2e27255SArnaldo Carvalho de Melo 		goto out;
2189a2e27255SArnaldo Carvalho de Melo 
2190a7526eb5SAndy Lutomirski 	err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0);
2191a2e27255SArnaldo Carvalho de Melo 
21926cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
21931da177e4SLinus Torvalds out:
21941da177e4SLinus Torvalds 	return err;
21951da177e4SLinus Torvalds }
21961da177e4SLinus Torvalds 
2197666547ffSAl Viro SYSCALL_DEFINE3(recvmsg, int, fd, struct user_msghdr __user *, msg,
2198a7526eb5SAndy Lutomirski 		unsigned int, flags)
2199a7526eb5SAndy Lutomirski {
2200a7526eb5SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
2201a7526eb5SAndy Lutomirski 		return -EINVAL;
2202a7526eb5SAndy Lutomirski 	return __sys_recvmsg(fd, msg, flags);
2203a7526eb5SAndy Lutomirski }
2204a7526eb5SAndy Lutomirski 
2205a2e27255SArnaldo Carvalho de Melo /*
2206a2e27255SArnaldo Carvalho de Melo  *     Linux recvmmsg interface
2207a2e27255SArnaldo Carvalho de Melo  */
22081da177e4SLinus Torvalds 
2209a2e27255SArnaldo Carvalho de Melo int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2210a2e27255SArnaldo Carvalho de Melo 		   unsigned int flags, struct timespec *timeout)
2211a2e27255SArnaldo Carvalho de Melo {
2212a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err, datagrams;
2213a2e27255SArnaldo Carvalho de Melo 	struct socket *sock;
2214a2e27255SArnaldo Carvalho de Melo 	struct mmsghdr __user *entry;
2215d7256d0eSJean-Mickael Guerin 	struct compat_mmsghdr __user *compat_entry;
2216a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
2217766b9f92SDeepa Dinamani 	struct timespec64 end_time;
2218766b9f92SDeepa Dinamani 	struct timespec64 timeout64;
2219a2e27255SArnaldo Carvalho de Melo 
2220a2e27255SArnaldo Carvalho de Melo 	if (timeout &&
2221a2e27255SArnaldo Carvalho de Melo 	    poll_select_set_timeout(&end_time, timeout->tv_sec,
2222a2e27255SArnaldo Carvalho de Melo 				    timeout->tv_nsec))
2223a2e27255SArnaldo Carvalho de Melo 		return -EINVAL;
2224a2e27255SArnaldo Carvalho de Melo 
2225a2e27255SArnaldo Carvalho de Melo 	datagrams = 0;
2226a2e27255SArnaldo Carvalho de Melo 
2227a2e27255SArnaldo Carvalho de Melo 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2228a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2229a2e27255SArnaldo Carvalho de Melo 		return err;
2230a2e27255SArnaldo Carvalho de Melo 
2231a2e27255SArnaldo Carvalho de Melo 	err = sock_error(sock->sk);
2232e623a9e9SMaxime Jayat 	if (err) {
2233e623a9e9SMaxime Jayat 		datagrams = err;
2234a2e27255SArnaldo Carvalho de Melo 		goto out_put;
2235e623a9e9SMaxime Jayat 	}
2236a2e27255SArnaldo Carvalho de Melo 
2237a2e27255SArnaldo Carvalho de Melo 	entry = mmsg;
2238d7256d0eSJean-Mickael Guerin 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2239a2e27255SArnaldo Carvalho de Melo 
2240a2e27255SArnaldo Carvalho de Melo 	while (datagrams < vlen) {
2241a2e27255SArnaldo Carvalho de Melo 		/*
2242a2e27255SArnaldo Carvalho de Melo 		 * No need to ask LSM for more than the first datagram.
2243a2e27255SArnaldo Carvalho de Melo 		 */
2244d7256d0eSJean-Mickael Guerin 		if (MSG_CMSG_COMPAT & flags) {
2245666547ffSAl Viro 			err = ___sys_recvmsg(sock, (struct user_msghdr __user *)compat_entry,
2246b9eb8b87SAnton Blanchard 					     &msg_sys, flags & ~MSG_WAITFORONE,
2247b9eb8b87SAnton Blanchard 					     datagrams);
2248d7256d0eSJean-Mickael Guerin 			if (err < 0)
2249d7256d0eSJean-Mickael Guerin 				break;
2250d7256d0eSJean-Mickael Guerin 			err = __put_user(err, &compat_entry->msg_len);
2251d7256d0eSJean-Mickael Guerin 			++compat_entry;
2252d7256d0eSJean-Mickael Guerin 		} else {
2253a7526eb5SAndy Lutomirski 			err = ___sys_recvmsg(sock,
2254666547ffSAl Viro 					     (struct user_msghdr __user *)entry,
2255b9eb8b87SAnton Blanchard 					     &msg_sys, flags & ~MSG_WAITFORONE,
2256b9eb8b87SAnton Blanchard 					     datagrams);
2257a2e27255SArnaldo Carvalho de Melo 			if (err < 0)
2258a2e27255SArnaldo Carvalho de Melo 				break;
2259a2e27255SArnaldo Carvalho de Melo 			err = put_user(err, &entry->msg_len);
2260d7256d0eSJean-Mickael Guerin 			++entry;
2261d7256d0eSJean-Mickael Guerin 		}
2262d7256d0eSJean-Mickael Guerin 
2263a2e27255SArnaldo Carvalho de Melo 		if (err)
2264a2e27255SArnaldo Carvalho de Melo 			break;
2265a2e27255SArnaldo Carvalho de Melo 		++datagrams;
2266a2e27255SArnaldo Carvalho de Melo 
226771c5c159SBrandon L Black 		/* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
226871c5c159SBrandon L Black 		if (flags & MSG_WAITFORONE)
226971c5c159SBrandon L Black 			flags |= MSG_DONTWAIT;
227071c5c159SBrandon L Black 
2271a2e27255SArnaldo Carvalho de Melo 		if (timeout) {
2272766b9f92SDeepa Dinamani 			ktime_get_ts64(&timeout64);
2273766b9f92SDeepa Dinamani 			*timeout = timespec64_to_timespec(
2274766b9f92SDeepa Dinamani 					timespec64_sub(end_time, timeout64));
2275a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_sec < 0) {
2276a2e27255SArnaldo Carvalho de Melo 				timeout->tv_sec = timeout->tv_nsec = 0;
2277a2e27255SArnaldo Carvalho de Melo 				break;
2278a2e27255SArnaldo Carvalho de Melo 			}
2279a2e27255SArnaldo Carvalho de Melo 
2280a2e27255SArnaldo Carvalho de Melo 			/* Timeout, return less than vlen datagrams */
2281a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_nsec == 0 && timeout->tv_sec == 0)
2282a2e27255SArnaldo Carvalho de Melo 				break;
2283a2e27255SArnaldo Carvalho de Melo 		}
2284a2e27255SArnaldo Carvalho de Melo 
2285a2e27255SArnaldo Carvalho de Melo 		/* Out of band data, return right away */
2286a2e27255SArnaldo Carvalho de Melo 		if (msg_sys.msg_flags & MSG_OOB)
2287a2e27255SArnaldo Carvalho de Melo 			break;
2288a78cb84cSEric Dumazet 		cond_resched();
2289a2e27255SArnaldo Carvalho de Melo 	}
2290a2e27255SArnaldo Carvalho de Melo 
2291a2e27255SArnaldo Carvalho de Melo 	if (err == 0)
229234b88a68SArnaldo Carvalho de Melo 		goto out_put;
2293a2e27255SArnaldo Carvalho de Melo 
229434b88a68SArnaldo Carvalho de Melo 	if (datagrams == 0) {
229534b88a68SArnaldo Carvalho de Melo 		datagrams = err;
229634b88a68SArnaldo Carvalho de Melo 		goto out_put;
229734b88a68SArnaldo Carvalho de Melo 	}
229834b88a68SArnaldo Carvalho de Melo 
2299a2e27255SArnaldo Carvalho de Melo 	/*
2300a2e27255SArnaldo Carvalho de Melo 	 * We may return less entries than requested (vlen) if the
2301a2e27255SArnaldo Carvalho de Melo 	 * sock is non block and there aren't enough datagrams...
2302a2e27255SArnaldo Carvalho de Melo 	 */
2303a2e27255SArnaldo Carvalho de Melo 	if (err != -EAGAIN) {
2304a2e27255SArnaldo Carvalho de Melo 		/*
2305a2e27255SArnaldo Carvalho de Melo 		 * ... or  if recvmsg returns an error after we
2306a2e27255SArnaldo Carvalho de Melo 		 * received some datagrams, where we record the
2307a2e27255SArnaldo Carvalho de Melo 		 * error to return on the next call or if the
2308a2e27255SArnaldo Carvalho de Melo 		 * app asks about it using getsockopt(SO_ERROR).
2309a2e27255SArnaldo Carvalho de Melo 		 */
2310a2e27255SArnaldo Carvalho de Melo 		sock->sk->sk_err = -err;
2311a2e27255SArnaldo Carvalho de Melo 	}
231234b88a68SArnaldo Carvalho de Melo out_put:
231334b88a68SArnaldo Carvalho de Melo 	fput_light(sock->file, fput_needed);
2314a2e27255SArnaldo Carvalho de Melo 
2315a2e27255SArnaldo Carvalho de Melo 	return datagrams;
2316a2e27255SArnaldo Carvalho de Melo }
2317a2e27255SArnaldo Carvalho de Melo 
2318a2e27255SArnaldo Carvalho de Melo SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
2319a2e27255SArnaldo Carvalho de Melo 		unsigned int, vlen, unsigned int, flags,
2320a2e27255SArnaldo Carvalho de Melo 		struct timespec __user *, timeout)
2321a2e27255SArnaldo Carvalho de Melo {
2322a2e27255SArnaldo Carvalho de Melo 	int datagrams;
2323a2e27255SArnaldo Carvalho de Melo 	struct timespec timeout_sys;
2324a2e27255SArnaldo Carvalho de Melo 
23251be374a0SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
23261be374a0SAndy Lutomirski 		return -EINVAL;
23271be374a0SAndy Lutomirski 
2328a2e27255SArnaldo Carvalho de Melo 	if (!timeout)
2329a2e27255SArnaldo Carvalho de Melo 		return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL);
2330a2e27255SArnaldo Carvalho de Melo 
2331a2e27255SArnaldo Carvalho de Melo 	if (copy_from_user(&timeout_sys, timeout, sizeof(timeout_sys)))
2332a2e27255SArnaldo Carvalho de Melo 		return -EFAULT;
2333a2e27255SArnaldo Carvalho de Melo 
2334a2e27255SArnaldo Carvalho de Melo 	datagrams = __sys_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys);
2335a2e27255SArnaldo Carvalho de Melo 
2336a2e27255SArnaldo Carvalho de Melo 	if (datagrams > 0 &&
2337a2e27255SArnaldo Carvalho de Melo 	    copy_to_user(timeout, &timeout_sys, sizeof(timeout_sys)))
2338a2e27255SArnaldo Carvalho de Melo 		datagrams = -EFAULT;
2339a2e27255SArnaldo Carvalho de Melo 
2340a2e27255SArnaldo Carvalho de Melo 	return datagrams;
2341a2e27255SArnaldo Carvalho de Melo }
2342a2e27255SArnaldo Carvalho de Melo 
2343a2e27255SArnaldo Carvalho de Melo #ifdef __ARCH_WANT_SYS_SOCKETCALL
23441da177e4SLinus Torvalds /* Argument list sizes for sys_socketcall */
23451da177e4SLinus Torvalds #define AL(x) ((x) * sizeof(unsigned long))
2346228e548eSAnton Blanchard static const unsigned char nargs[21] = {
234789bddce5SStephen Hemminger 	AL(0), AL(3), AL(3), AL(3), AL(2), AL(3),
23481da177e4SLinus Torvalds 	AL(3), AL(3), AL(4), AL(4), AL(4), AL(6),
2349aaca0bdcSUlrich Drepper 	AL(6), AL(2), AL(5), AL(5), AL(3), AL(3),
2350228e548eSAnton Blanchard 	AL(4), AL(5), AL(4)
235189bddce5SStephen Hemminger };
235289bddce5SStephen Hemminger 
23531da177e4SLinus Torvalds #undef AL
23541da177e4SLinus Torvalds 
23551da177e4SLinus Torvalds /*
23561da177e4SLinus Torvalds  *	System call vectors.
23571da177e4SLinus Torvalds  *
23581da177e4SLinus Torvalds  *	Argument checking cleaned up. Saved 20% in size.
23591da177e4SLinus Torvalds  *  This function doesn't need to set the kernel lock because
23601da177e4SLinus Torvalds  *  it is set by the callees.
23611da177e4SLinus Torvalds  */
23621da177e4SLinus Torvalds 
23633e0fa65fSHeiko Carstens SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
23641da177e4SLinus Torvalds {
23652950fa9dSChen Gang 	unsigned long a[AUDITSC_ARGS];
23661da177e4SLinus Torvalds 	unsigned long a0, a1;
23671da177e4SLinus Torvalds 	int err;
236847379052SArjan van de Ven 	unsigned int len;
23691da177e4SLinus Torvalds 
2370228e548eSAnton Blanchard 	if (call < 1 || call > SYS_SENDMMSG)
23711da177e4SLinus Torvalds 		return -EINVAL;
23721da177e4SLinus Torvalds 
237347379052SArjan van de Ven 	len = nargs[call];
237447379052SArjan van de Ven 	if (len > sizeof(a))
237547379052SArjan van de Ven 		return -EINVAL;
237647379052SArjan van de Ven 
23771da177e4SLinus Torvalds 	/* copy_from_user should be SMP safe. */
237847379052SArjan van de Ven 	if (copy_from_user(a, args, len))
23791da177e4SLinus Torvalds 		return -EFAULT;
23801da177e4SLinus Torvalds 
23812950fa9dSChen Gang 	err = audit_socketcall(nargs[call] / sizeof(unsigned long), a);
23822950fa9dSChen Gang 	if (err)
23832950fa9dSChen Gang 		return err;
23843ec3b2fbSDavid Woodhouse 
23851da177e4SLinus Torvalds 	a0 = a[0];
23861da177e4SLinus Torvalds 	a1 = a[1];
23871da177e4SLinus Torvalds 
238889bddce5SStephen Hemminger 	switch (call) {
23891da177e4SLinus Torvalds 	case SYS_SOCKET:
23901da177e4SLinus Torvalds 		err = sys_socket(a0, a1, a[2]);
23911da177e4SLinus Torvalds 		break;
23921da177e4SLinus Torvalds 	case SYS_BIND:
23931da177e4SLinus Torvalds 		err = sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
23941da177e4SLinus Torvalds 		break;
23951da177e4SLinus Torvalds 	case SYS_CONNECT:
23961da177e4SLinus Torvalds 		err = sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
23971da177e4SLinus Torvalds 		break;
23981da177e4SLinus Torvalds 	case SYS_LISTEN:
23991da177e4SLinus Torvalds 		err = sys_listen(a0, a1);
24001da177e4SLinus Torvalds 		break;
24011da177e4SLinus Torvalds 	case SYS_ACCEPT:
2402de11defeSUlrich Drepper 		err = sys_accept4(a0, (struct sockaddr __user *)a1,
2403aaca0bdcSUlrich Drepper 				  (int __user *)a[2], 0);
24041da177e4SLinus Torvalds 		break;
24051da177e4SLinus Torvalds 	case SYS_GETSOCKNAME:
240689bddce5SStephen Hemminger 		err =
240789bddce5SStephen Hemminger 		    sys_getsockname(a0, (struct sockaddr __user *)a1,
240889bddce5SStephen Hemminger 				    (int __user *)a[2]);
24091da177e4SLinus Torvalds 		break;
24101da177e4SLinus Torvalds 	case SYS_GETPEERNAME:
241189bddce5SStephen Hemminger 		err =
241289bddce5SStephen Hemminger 		    sys_getpeername(a0, (struct sockaddr __user *)a1,
241389bddce5SStephen Hemminger 				    (int __user *)a[2]);
24141da177e4SLinus Torvalds 		break;
24151da177e4SLinus Torvalds 	case SYS_SOCKETPAIR:
24161da177e4SLinus Torvalds 		err = sys_socketpair(a0, a1, a[2], (int __user *)a[3]);
24171da177e4SLinus Torvalds 		break;
24181da177e4SLinus Torvalds 	case SYS_SEND:
24191da177e4SLinus Torvalds 		err = sys_send(a0, (void __user *)a1, a[2], a[3]);
24201da177e4SLinus Torvalds 		break;
24211da177e4SLinus Torvalds 	case SYS_SENDTO:
24221da177e4SLinus Torvalds 		err = sys_sendto(a0, (void __user *)a1, a[2], a[3],
24231da177e4SLinus Torvalds 				 (struct sockaddr __user *)a[4], a[5]);
24241da177e4SLinus Torvalds 		break;
24251da177e4SLinus Torvalds 	case SYS_RECV:
24261da177e4SLinus Torvalds 		err = sys_recv(a0, (void __user *)a1, a[2], a[3]);
24271da177e4SLinus Torvalds 		break;
24281da177e4SLinus Torvalds 	case SYS_RECVFROM:
24291da177e4SLinus Torvalds 		err = sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
243089bddce5SStephen Hemminger 				   (struct sockaddr __user *)a[4],
243189bddce5SStephen Hemminger 				   (int __user *)a[5]);
24321da177e4SLinus Torvalds 		break;
24331da177e4SLinus Torvalds 	case SYS_SHUTDOWN:
24341da177e4SLinus Torvalds 		err = sys_shutdown(a0, a1);
24351da177e4SLinus Torvalds 		break;
24361da177e4SLinus Torvalds 	case SYS_SETSOCKOPT:
24371da177e4SLinus Torvalds 		err = sys_setsockopt(a0, a1, a[2], (char __user *)a[3], a[4]);
24381da177e4SLinus Torvalds 		break;
24391da177e4SLinus Torvalds 	case SYS_GETSOCKOPT:
244089bddce5SStephen Hemminger 		err =
244189bddce5SStephen Hemminger 		    sys_getsockopt(a0, a1, a[2], (char __user *)a[3],
244289bddce5SStephen Hemminger 				   (int __user *)a[4]);
24431da177e4SLinus Torvalds 		break;
24441da177e4SLinus Torvalds 	case SYS_SENDMSG:
2445666547ffSAl Viro 		err = sys_sendmsg(a0, (struct user_msghdr __user *)a1, a[2]);
24461da177e4SLinus Torvalds 		break;
2447228e548eSAnton Blanchard 	case SYS_SENDMMSG:
2448228e548eSAnton Blanchard 		err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]);
2449228e548eSAnton Blanchard 		break;
24501da177e4SLinus Torvalds 	case SYS_RECVMSG:
2451666547ffSAl Viro 		err = sys_recvmsg(a0, (struct user_msghdr __user *)a1, a[2]);
24521da177e4SLinus Torvalds 		break;
2453a2e27255SArnaldo Carvalho de Melo 	case SYS_RECVMMSG:
2454a2e27255SArnaldo Carvalho de Melo 		err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3],
2455a2e27255SArnaldo Carvalho de Melo 				   (struct timespec __user *)a[4]);
2456a2e27255SArnaldo Carvalho de Melo 		break;
2457de11defeSUlrich Drepper 	case SYS_ACCEPT4:
2458de11defeSUlrich Drepper 		err = sys_accept4(a0, (struct sockaddr __user *)a1,
2459de11defeSUlrich Drepper 				  (int __user *)a[2], a[3]);
2460aaca0bdcSUlrich Drepper 		break;
24611da177e4SLinus Torvalds 	default:
24621da177e4SLinus Torvalds 		err = -EINVAL;
24631da177e4SLinus Torvalds 		break;
24641da177e4SLinus Torvalds 	}
24651da177e4SLinus Torvalds 	return err;
24661da177e4SLinus Torvalds }
24671da177e4SLinus Torvalds 
24681da177e4SLinus Torvalds #endif				/* __ARCH_WANT_SYS_SOCKETCALL */
24691da177e4SLinus Torvalds 
247055737fdaSStephen Hemminger /**
247155737fdaSStephen Hemminger  *	sock_register - add a socket protocol handler
247255737fdaSStephen Hemminger  *	@ops: description of protocol
247355737fdaSStephen Hemminger  *
24741da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
24751da177e4SLinus Torvalds  *	advertise its address family, and have it linked into the
2476e793c0f7SMasanari Iida  *	socket interface. The value ops->family corresponds to the
247755737fdaSStephen Hemminger  *	socket system call protocol family.
24781da177e4SLinus Torvalds  */
2479f0fd27d4SStephen Hemminger int sock_register(const struct net_proto_family *ops)
24801da177e4SLinus Torvalds {
24811da177e4SLinus Torvalds 	int err;
24821da177e4SLinus Torvalds 
24831da177e4SLinus Torvalds 	if (ops->family >= NPROTO) {
24843410f22eSYang Yingliang 		pr_crit("protocol %d >= NPROTO(%d)\n", ops->family, NPROTO);
24851da177e4SLinus Torvalds 		return -ENOBUFS;
24861da177e4SLinus Torvalds 	}
248755737fdaSStephen Hemminger 
248855737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2489190683a9SEric Dumazet 	if (rcu_dereference_protected(net_families[ops->family],
2490190683a9SEric Dumazet 				      lockdep_is_held(&net_family_lock)))
24911da177e4SLinus Torvalds 		err = -EEXIST;
249255737fdaSStephen Hemminger 	else {
2493cf778b00SEric Dumazet 		rcu_assign_pointer(net_families[ops->family], ops);
24941da177e4SLinus Torvalds 		err = 0;
24951da177e4SLinus Torvalds 	}
249655737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
249755737fdaSStephen Hemminger 
24983410f22eSYang Yingliang 	pr_info("NET: Registered protocol family %d\n", ops->family);
24991da177e4SLinus Torvalds 	return err;
25001da177e4SLinus Torvalds }
2501c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_register);
25021da177e4SLinus Torvalds 
250355737fdaSStephen Hemminger /**
250455737fdaSStephen Hemminger  *	sock_unregister - remove a protocol handler
250555737fdaSStephen Hemminger  *	@family: protocol family to remove
250655737fdaSStephen Hemminger  *
25071da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
25081da177e4SLinus Torvalds  *	remove its address family, and have it unlinked from the
250955737fdaSStephen Hemminger  *	new socket creation.
251055737fdaSStephen Hemminger  *
251155737fdaSStephen Hemminger  *	If protocol handler is a module, then it can use module reference
251255737fdaSStephen Hemminger  *	counts to protect against new references. If protocol handler is not
251355737fdaSStephen Hemminger  *	a module then it needs to provide its own protection in
251455737fdaSStephen Hemminger  *	the ops->create routine.
25151da177e4SLinus Torvalds  */
2516f0fd27d4SStephen Hemminger void sock_unregister(int family)
25171da177e4SLinus Torvalds {
2518f0fd27d4SStephen Hemminger 	BUG_ON(family < 0 || family >= NPROTO);
25191da177e4SLinus Torvalds 
252055737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2521a9b3cd7fSStephen Hemminger 	RCU_INIT_POINTER(net_families[family], NULL);
252255737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
252355737fdaSStephen Hemminger 
252455737fdaSStephen Hemminger 	synchronize_rcu();
252555737fdaSStephen Hemminger 
25263410f22eSYang Yingliang 	pr_info("NET: Unregistered protocol family %d\n", family);
25271da177e4SLinus Torvalds }
2528c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_unregister);
25291da177e4SLinus Torvalds 
253077d76ea3SAndi Kleen static int __init sock_init(void)
25311da177e4SLinus Torvalds {
2532b3e19d92SNick Piggin 	int err;
25332ca794e5SEric W. Biederman 	/*
25342ca794e5SEric W. Biederman 	 *      Initialize the network sysctl infrastructure.
25352ca794e5SEric W. Biederman 	 */
25362ca794e5SEric W. Biederman 	err = net_sysctl_init();
25372ca794e5SEric W. Biederman 	if (err)
25382ca794e5SEric W. Biederman 		goto out;
2539b3e19d92SNick Piggin 
25401da177e4SLinus Torvalds 	/*
25411da177e4SLinus Torvalds 	 *      Initialize skbuff SLAB cache
25421da177e4SLinus Torvalds 	 */
25431da177e4SLinus Torvalds 	skb_init();
25441da177e4SLinus Torvalds 
25451da177e4SLinus Torvalds 	/*
25461da177e4SLinus Torvalds 	 *      Initialize the protocols module.
25471da177e4SLinus Torvalds 	 */
25481da177e4SLinus Torvalds 
25491da177e4SLinus Torvalds 	init_inodecache();
2550b3e19d92SNick Piggin 
2551b3e19d92SNick Piggin 	err = register_filesystem(&sock_fs_type);
2552b3e19d92SNick Piggin 	if (err)
2553b3e19d92SNick Piggin 		goto out_fs;
25541da177e4SLinus Torvalds 	sock_mnt = kern_mount(&sock_fs_type);
2555b3e19d92SNick Piggin 	if (IS_ERR(sock_mnt)) {
2556b3e19d92SNick Piggin 		err = PTR_ERR(sock_mnt);
2557b3e19d92SNick Piggin 		goto out_mount;
2558b3e19d92SNick Piggin 	}
255977d76ea3SAndi Kleen 
256077d76ea3SAndi Kleen 	/* The real protocol initialization is performed in later initcalls.
25611da177e4SLinus Torvalds 	 */
25621da177e4SLinus Torvalds 
25631da177e4SLinus Torvalds #ifdef CONFIG_NETFILTER
25646d11cfdbSPablo Neira Ayuso 	err = netfilter_init();
25656d11cfdbSPablo Neira Ayuso 	if (err)
25666d11cfdbSPablo Neira Ayuso 		goto out;
25671da177e4SLinus Torvalds #endif
2568cbeb321aSDavid S. Miller 
2569408eccceSDaniel Borkmann 	ptp_classifier_init();
2570c1f19b51SRichard Cochran 
2571b3e19d92SNick Piggin out:
2572b3e19d92SNick Piggin 	return err;
2573b3e19d92SNick Piggin 
2574b3e19d92SNick Piggin out_mount:
2575b3e19d92SNick Piggin 	unregister_filesystem(&sock_fs_type);
2576b3e19d92SNick Piggin out_fs:
2577b3e19d92SNick Piggin 	goto out;
25781da177e4SLinus Torvalds }
25791da177e4SLinus Torvalds 
258077d76ea3SAndi Kleen core_initcall(sock_init);	/* early initcall */
258177d76ea3SAndi Kleen 
25821da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS
25831da177e4SLinus Torvalds void socket_seq_show(struct seq_file *seq)
25841da177e4SLinus Torvalds {
25851da177e4SLinus Torvalds 	int cpu;
25861da177e4SLinus Torvalds 	int counter = 0;
25871da177e4SLinus Torvalds 
25886f912042SKAMEZAWA Hiroyuki 	for_each_possible_cpu(cpu)
25891da177e4SLinus Torvalds 	    counter += per_cpu(sockets_in_use, cpu);
25901da177e4SLinus Torvalds 
25911da177e4SLinus Torvalds 	/* It can be negative, by the way. 8) */
25921da177e4SLinus Torvalds 	if (counter < 0)
25931da177e4SLinus Torvalds 		counter = 0;
25941da177e4SLinus Torvalds 
25951da177e4SLinus Torvalds 	seq_printf(seq, "sockets: used %d\n", counter);
25961da177e4SLinus Torvalds }
25971da177e4SLinus Torvalds #endif				/* CONFIG_PROC_FS */
25981da177e4SLinus Torvalds 
259989bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
26006b96018bSArnd Bergmann static int do_siocgstamp(struct net *net, struct socket *sock,
2601644595f8SH. Peter Anvin 			 unsigned int cmd, void __user *up)
26027a229387SArnd Bergmann {
26037a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
26047a229387SArnd Bergmann 	struct timeval ktv;
26057a229387SArnd Bergmann 	int err;
26067a229387SArnd Bergmann 
26077a229387SArnd Bergmann 	set_fs(KERNEL_DS);
26086b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv);
26097a229387SArnd Bergmann 	set_fs(old_fs);
2610644595f8SH. Peter Anvin 	if (!err)
2611ed6fe9d6SMikulas Patocka 		err = compat_put_timeval(&ktv, up);
2612644595f8SH. Peter Anvin 
26137a229387SArnd Bergmann 	return err;
26147a229387SArnd Bergmann }
26157a229387SArnd Bergmann 
26166b96018bSArnd Bergmann static int do_siocgstampns(struct net *net, struct socket *sock,
2617644595f8SH. Peter Anvin 			   unsigned int cmd, void __user *up)
26187a229387SArnd Bergmann {
26197a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
26207a229387SArnd Bergmann 	struct timespec kts;
26217a229387SArnd Bergmann 	int err;
26227a229387SArnd Bergmann 
26237a229387SArnd Bergmann 	set_fs(KERNEL_DS);
26246b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts);
26257a229387SArnd Bergmann 	set_fs(old_fs);
2626644595f8SH. Peter Anvin 	if (!err)
2627ed6fe9d6SMikulas Patocka 		err = compat_put_timespec(&kts, up);
2628644595f8SH. Peter Anvin 
26297a229387SArnd Bergmann 	return err;
26307a229387SArnd Bergmann }
26317a229387SArnd Bergmann 
26326b96018bSArnd Bergmann static int dev_ifname32(struct net *net, struct compat_ifreq __user *uifr32)
26337a229387SArnd Bergmann {
26347a229387SArnd Bergmann 	struct ifreq __user *uifr;
26357a229387SArnd Bergmann 	int err;
26367a229387SArnd Bergmann 
26377a229387SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(struct ifreq));
26386b96018bSArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
26397a229387SArnd Bergmann 		return -EFAULT;
26407a229387SArnd Bergmann 
26416b96018bSArnd Bergmann 	err = dev_ioctl(net, SIOCGIFNAME, uifr);
26427a229387SArnd Bergmann 	if (err)
26437a229387SArnd Bergmann 		return err;
26447a229387SArnd Bergmann 
26456b96018bSArnd Bergmann 	if (copy_in_user(uifr32, uifr, sizeof(struct compat_ifreq)))
26467a229387SArnd Bergmann 		return -EFAULT;
26477a229387SArnd Bergmann 
26487a229387SArnd Bergmann 	return 0;
26497a229387SArnd Bergmann }
26507a229387SArnd Bergmann 
26516b96018bSArnd Bergmann static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32)
26527a229387SArnd Bergmann {
26536b96018bSArnd Bergmann 	struct compat_ifconf ifc32;
26547a229387SArnd Bergmann 	struct ifconf ifc;
26557a229387SArnd Bergmann 	struct ifconf __user *uifc;
26566b96018bSArnd Bergmann 	struct compat_ifreq __user *ifr32;
26577a229387SArnd Bergmann 	struct ifreq __user *ifr;
26587a229387SArnd Bergmann 	unsigned int i, j;
26597a229387SArnd Bergmann 	int err;
26607a229387SArnd Bergmann 
26616b96018bSArnd Bergmann 	if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf)))
26627a229387SArnd Bergmann 		return -EFAULT;
26637a229387SArnd Bergmann 
266443da5f2eSMathias Krause 	memset(&ifc, 0, sizeof(ifc));
26657a229387SArnd Bergmann 	if (ifc32.ifcbuf == 0) {
26667a229387SArnd Bergmann 		ifc32.ifc_len = 0;
26677a229387SArnd Bergmann 		ifc.ifc_len = 0;
26687a229387SArnd Bergmann 		ifc.ifc_req = NULL;
26697a229387SArnd Bergmann 		uifc = compat_alloc_user_space(sizeof(struct ifconf));
26707a229387SArnd Bergmann 	} else {
26716b96018bSArnd Bergmann 		size_t len = ((ifc32.ifc_len / sizeof(struct compat_ifreq)) + 1) *
26727a229387SArnd Bergmann 			sizeof(struct ifreq);
26737a229387SArnd Bergmann 		uifc = compat_alloc_user_space(sizeof(struct ifconf) + len);
26747a229387SArnd Bergmann 		ifc.ifc_len = len;
26757a229387SArnd Bergmann 		ifr = ifc.ifc_req = (void __user *)(uifc + 1);
26767a229387SArnd Bergmann 		ifr32 = compat_ptr(ifc32.ifcbuf);
26776b96018bSArnd Bergmann 		for (i = 0; i < ifc32.ifc_len; i += sizeof(struct compat_ifreq)) {
26786b96018bSArnd Bergmann 			if (copy_in_user(ifr, ifr32, sizeof(struct compat_ifreq)))
26797a229387SArnd Bergmann 				return -EFAULT;
26807a229387SArnd Bergmann 			ifr++;
26817a229387SArnd Bergmann 			ifr32++;
26827a229387SArnd Bergmann 		}
26837a229387SArnd Bergmann 	}
26847a229387SArnd Bergmann 	if (copy_to_user(uifc, &ifc, sizeof(struct ifconf)))
26857a229387SArnd Bergmann 		return -EFAULT;
26867a229387SArnd Bergmann 
26876b96018bSArnd Bergmann 	err = dev_ioctl(net, SIOCGIFCONF, uifc);
26887a229387SArnd Bergmann 	if (err)
26897a229387SArnd Bergmann 		return err;
26907a229387SArnd Bergmann 
26917a229387SArnd Bergmann 	if (copy_from_user(&ifc, uifc, sizeof(struct ifconf)))
26927a229387SArnd Bergmann 		return -EFAULT;
26937a229387SArnd Bergmann 
26947a229387SArnd Bergmann 	ifr = ifc.ifc_req;
26957a229387SArnd Bergmann 	ifr32 = compat_ptr(ifc32.ifcbuf);
26967a229387SArnd Bergmann 	for (i = 0, j = 0;
26976b96018bSArnd Bergmann 	     i + sizeof(struct compat_ifreq) <= ifc32.ifc_len && j < ifc.ifc_len;
26986b96018bSArnd Bergmann 	     i += sizeof(struct compat_ifreq), j += sizeof(struct ifreq)) {
26996b96018bSArnd Bergmann 		if (copy_in_user(ifr32, ifr, sizeof(struct compat_ifreq)))
27007a229387SArnd Bergmann 			return -EFAULT;
27017a229387SArnd Bergmann 		ifr32++;
27027a229387SArnd Bergmann 		ifr++;
27037a229387SArnd Bergmann 	}
27047a229387SArnd Bergmann 
27057a229387SArnd Bergmann 	if (ifc32.ifcbuf == 0) {
27067a229387SArnd Bergmann 		/* Translate from 64-bit structure multiple to
27077a229387SArnd Bergmann 		 * a 32-bit one.
27087a229387SArnd Bergmann 		 */
27097a229387SArnd Bergmann 		i = ifc.ifc_len;
27106b96018bSArnd Bergmann 		i = ((i / sizeof(struct ifreq)) * sizeof(struct compat_ifreq));
27117a229387SArnd Bergmann 		ifc32.ifc_len = i;
27127a229387SArnd Bergmann 	} else {
27137a229387SArnd Bergmann 		ifc32.ifc_len = i;
27147a229387SArnd Bergmann 	}
27156b96018bSArnd Bergmann 	if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf)))
27167a229387SArnd Bergmann 		return -EFAULT;
27177a229387SArnd Bergmann 
27187a229387SArnd Bergmann 	return 0;
27197a229387SArnd Bergmann }
27207a229387SArnd Bergmann 
27216b96018bSArnd Bergmann static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
27227a229387SArnd Bergmann {
27233a7da39dSBen Hutchings 	struct compat_ethtool_rxnfc __user *compat_rxnfc;
27243a7da39dSBen Hutchings 	bool convert_in = false, convert_out = false;
27253a7da39dSBen Hutchings 	size_t buf_size = ALIGN(sizeof(struct ifreq), 8);
27263a7da39dSBen Hutchings 	struct ethtool_rxnfc __user *rxnfc;
27277a229387SArnd Bergmann 	struct ifreq __user *ifr;
27283a7da39dSBen Hutchings 	u32 rule_cnt = 0, actual_rule_cnt;
27293a7da39dSBen Hutchings 	u32 ethcmd;
27307a229387SArnd Bergmann 	u32 data;
27313a7da39dSBen Hutchings 	int ret;
27327a229387SArnd Bergmann 
27337a229387SArnd Bergmann 	if (get_user(data, &ifr32->ifr_ifru.ifru_data))
27347a229387SArnd Bergmann 		return -EFAULT;
27357a229387SArnd Bergmann 
27363a7da39dSBen Hutchings 	compat_rxnfc = compat_ptr(data);
27373a7da39dSBen Hutchings 
27383a7da39dSBen Hutchings 	if (get_user(ethcmd, &compat_rxnfc->cmd))
27397a229387SArnd Bergmann 		return -EFAULT;
27407a229387SArnd Bergmann 
27413a7da39dSBen Hutchings 	/* Most ethtool structures are defined without padding.
27423a7da39dSBen Hutchings 	 * Unfortunately struct ethtool_rxnfc is an exception.
27433a7da39dSBen Hutchings 	 */
27443a7da39dSBen Hutchings 	switch (ethcmd) {
27453a7da39dSBen Hutchings 	default:
27463a7da39dSBen Hutchings 		break;
27473a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLALL:
27483a7da39dSBen Hutchings 		/* Buffer size is variable */
27493a7da39dSBen Hutchings 		if (get_user(rule_cnt, &compat_rxnfc->rule_cnt))
27503a7da39dSBen Hutchings 			return -EFAULT;
27513a7da39dSBen Hutchings 		if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32))
27523a7da39dSBen Hutchings 			return -ENOMEM;
27533a7da39dSBen Hutchings 		buf_size += rule_cnt * sizeof(u32);
27543a7da39dSBen Hutchings 		/* fall through */
27553a7da39dSBen Hutchings 	case ETHTOOL_GRXRINGS:
27563a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLCNT:
27573a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRULE:
275855664f32SBen Hutchings 	case ETHTOOL_SRXCLSRLINS:
27593a7da39dSBen Hutchings 		convert_out = true;
27603a7da39dSBen Hutchings 		/* fall through */
27613a7da39dSBen Hutchings 	case ETHTOOL_SRXCLSRLDEL:
27623a7da39dSBen Hutchings 		buf_size += sizeof(struct ethtool_rxnfc);
27633a7da39dSBen Hutchings 		convert_in = true;
27643a7da39dSBen Hutchings 		break;
27653a7da39dSBen Hutchings 	}
27663a7da39dSBen Hutchings 
27673a7da39dSBen Hutchings 	ifr = compat_alloc_user_space(buf_size);
2768954b1244SStephen Hemminger 	rxnfc = (void __user *)ifr + ALIGN(sizeof(struct ifreq), 8);
27693a7da39dSBen Hutchings 
27703a7da39dSBen Hutchings 	if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
27713a7da39dSBen Hutchings 		return -EFAULT;
27723a7da39dSBen Hutchings 
27733a7da39dSBen Hutchings 	if (put_user(convert_in ? rxnfc : compat_ptr(data),
27743a7da39dSBen Hutchings 		     &ifr->ifr_ifru.ifru_data))
27753a7da39dSBen Hutchings 		return -EFAULT;
27763a7da39dSBen Hutchings 
27773a7da39dSBen Hutchings 	if (convert_in) {
2778127fe533SAlexander Duyck 		/* We expect there to be holes between fs.m_ext and
27793a7da39dSBen Hutchings 		 * fs.ring_cookie and at the end of fs, but nowhere else.
27803a7da39dSBen Hutchings 		 */
2781127fe533SAlexander Duyck 		BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_ext) +
2782127fe533SAlexander Duyck 			     sizeof(compat_rxnfc->fs.m_ext) !=
2783127fe533SAlexander Duyck 			     offsetof(struct ethtool_rxnfc, fs.m_ext) +
2784127fe533SAlexander Duyck 			     sizeof(rxnfc->fs.m_ext));
27853a7da39dSBen Hutchings 		BUILD_BUG_ON(
27863a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.location) -
27873a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) !=
27883a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.location) -
27893a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.ring_cookie));
27903a7da39dSBen Hutchings 
27913a7da39dSBen Hutchings 		if (copy_in_user(rxnfc, compat_rxnfc,
2792954b1244SStephen Hemminger 				 (void __user *)(&rxnfc->fs.m_ext + 1) -
2793954b1244SStephen Hemminger 				 (void __user *)rxnfc) ||
27943a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->fs.ring_cookie,
27953a7da39dSBen Hutchings 				 &compat_rxnfc->fs.ring_cookie,
2796954b1244SStephen Hemminger 				 (void __user *)(&rxnfc->fs.location + 1) -
2797954b1244SStephen Hemminger 				 (void __user *)&rxnfc->fs.ring_cookie) ||
27983a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt,
27993a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
28003a7da39dSBen Hutchings 			return -EFAULT;
28013a7da39dSBen Hutchings 	}
28023a7da39dSBen Hutchings 
28033a7da39dSBen Hutchings 	ret = dev_ioctl(net, SIOCETHTOOL, ifr);
28043a7da39dSBen Hutchings 	if (ret)
28053a7da39dSBen Hutchings 		return ret;
28063a7da39dSBen Hutchings 
28073a7da39dSBen Hutchings 	if (convert_out) {
28083a7da39dSBen Hutchings 		if (copy_in_user(compat_rxnfc, rxnfc,
2809954b1244SStephen Hemminger 				 (const void __user *)(&rxnfc->fs.m_ext + 1) -
2810954b1244SStephen Hemminger 				 (const void __user *)rxnfc) ||
28113a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->fs.ring_cookie,
28123a7da39dSBen Hutchings 				 &rxnfc->fs.ring_cookie,
2813954b1244SStephen Hemminger 				 (const void __user *)(&rxnfc->fs.location + 1) -
2814954b1244SStephen Hemminger 				 (const void __user *)&rxnfc->fs.ring_cookie) ||
28153a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt,
28163a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
28173a7da39dSBen Hutchings 			return -EFAULT;
28183a7da39dSBen Hutchings 
28193a7da39dSBen Hutchings 		if (ethcmd == ETHTOOL_GRXCLSRLALL) {
28203a7da39dSBen Hutchings 			/* As an optimisation, we only copy the actual
28213a7da39dSBen Hutchings 			 * number of rules that the underlying
28223a7da39dSBen Hutchings 			 * function returned.  Since Mallory might
28233a7da39dSBen Hutchings 			 * change the rule count in user memory, we
28243a7da39dSBen Hutchings 			 * check that it is less than the rule count
28253a7da39dSBen Hutchings 			 * originally given (as the user buffer size),
28263a7da39dSBen Hutchings 			 * which has been range-checked.
28273a7da39dSBen Hutchings 			 */
28283a7da39dSBen Hutchings 			if (get_user(actual_rule_cnt, &rxnfc->rule_cnt))
28293a7da39dSBen Hutchings 				return -EFAULT;
28303a7da39dSBen Hutchings 			if (actual_rule_cnt < rule_cnt)
28313a7da39dSBen Hutchings 				rule_cnt = actual_rule_cnt;
28323a7da39dSBen Hutchings 			if (copy_in_user(&compat_rxnfc->rule_locs[0],
28333a7da39dSBen Hutchings 					 &rxnfc->rule_locs[0],
28343a7da39dSBen Hutchings 					 rule_cnt * sizeof(u32)))
28353a7da39dSBen Hutchings 				return -EFAULT;
28363a7da39dSBen Hutchings 		}
28373a7da39dSBen Hutchings 	}
28383a7da39dSBen Hutchings 
28393a7da39dSBen Hutchings 	return 0;
28407a229387SArnd Bergmann }
28417a229387SArnd Bergmann 
28427a50a240SArnd Bergmann static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32)
28437a50a240SArnd Bergmann {
28447a50a240SArnd Bergmann 	void __user *uptr;
28457a50a240SArnd Bergmann 	compat_uptr_t uptr32;
28467a50a240SArnd Bergmann 	struct ifreq __user *uifr;
28477a50a240SArnd Bergmann 
28487a50a240SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
28497a50a240SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
28507a50a240SArnd Bergmann 		return -EFAULT;
28517a50a240SArnd Bergmann 
28527a50a240SArnd Bergmann 	if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu))
28537a50a240SArnd Bergmann 		return -EFAULT;
28547a50a240SArnd Bergmann 
28557a50a240SArnd Bergmann 	uptr = compat_ptr(uptr32);
28567a50a240SArnd Bergmann 
28577a50a240SArnd Bergmann 	if (put_user(uptr, &uifr->ifr_settings.ifs_ifsu.raw_hdlc))
28587a50a240SArnd Bergmann 		return -EFAULT;
28597a50a240SArnd Bergmann 
28607a50a240SArnd Bergmann 	return dev_ioctl(net, SIOCWANDEV, uifr);
28617a50a240SArnd Bergmann }
28627a50a240SArnd Bergmann 
28636b96018bSArnd Bergmann static int bond_ioctl(struct net *net, unsigned int cmd,
28646b96018bSArnd Bergmann 			 struct compat_ifreq __user *ifr32)
28657a229387SArnd Bergmann {
28667a229387SArnd Bergmann 	struct ifreq kifr;
28677a229387SArnd Bergmann 	mm_segment_t old_fs;
28687a229387SArnd Bergmann 	int err;
28697a229387SArnd Bergmann 
28707a229387SArnd Bergmann 	switch (cmd) {
28717a229387SArnd Bergmann 	case SIOCBONDENSLAVE:
28727a229387SArnd Bergmann 	case SIOCBONDRELEASE:
28737a229387SArnd Bergmann 	case SIOCBONDSETHWADDR:
28747a229387SArnd Bergmann 	case SIOCBONDCHANGEACTIVE:
28756b96018bSArnd Bergmann 		if (copy_from_user(&kifr, ifr32, sizeof(struct compat_ifreq)))
28767a229387SArnd Bergmann 			return -EFAULT;
28777a229387SArnd Bergmann 
28787a229387SArnd Bergmann 		old_fs = get_fs();
28797a229387SArnd Bergmann 		set_fs(KERNEL_DS);
2880c3f52ae6Sstephen hemminger 		err = dev_ioctl(net, cmd,
2881c3f52ae6Sstephen hemminger 				(struct ifreq __user __force *) &kifr);
28827a229387SArnd Bergmann 		set_fs(old_fs);
28837a229387SArnd Bergmann 
28847a229387SArnd Bergmann 		return err;
28857a229387SArnd Bergmann 	default:
288607d106d0SLinus Torvalds 		return -ENOIOCTLCMD;
2887ccbd6a5aSJoe Perches 	}
28887a229387SArnd Bergmann }
28897a229387SArnd Bergmann 
2890590d4693SBen Hutchings /* Handle ioctls that use ifreq::ifr_data and just need struct ifreq converted */
2891590d4693SBen Hutchings static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd,
28926b96018bSArnd Bergmann 				 struct compat_ifreq __user *u_ifreq32)
28937a229387SArnd Bergmann {
28947a229387SArnd Bergmann 	struct ifreq __user *u_ifreq64;
28957a229387SArnd Bergmann 	char tmp_buf[IFNAMSIZ];
28967a229387SArnd Bergmann 	void __user *data64;
28977a229387SArnd Bergmann 	u32 data32;
28987a229387SArnd Bergmann 
28997a229387SArnd Bergmann 	if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]),
29007a229387SArnd Bergmann 			   IFNAMSIZ))
29017a229387SArnd Bergmann 		return -EFAULT;
2902417c3522SBen Hutchings 	if (get_user(data32, &u_ifreq32->ifr_ifru.ifru_data))
29037a229387SArnd Bergmann 		return -EFAULT;
29047a229387SArnd Bergmann 	data64 = compat_ptr(data32);
29057a229387SArnd Bergmann 
29067a229387SArnd Bergmann 	u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
29077a229387SArnd Bergmann 
29087a229387SArnd Bergmann 	if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0],
29097a229387SArnd Bergmann 			 IFNAMSIZ))
29107a229387SArnd Bergmann 		return -EFAULT;
2911417c3522SBen Hutchings 	if (put_user(data64, &u_ifreq64->ifr_ifru.ifru_data))
29127a229387SArnd Bergmann 		return -EFAULT;
29137a229387SArnd Bergmann 
29146b96018bSArnd Bergmann 	return dev_ioctl(net, cmd, u_ifreq64);
29157a229387SArnd Bergmann }
29167a229387SArnd Bergmann 
29176b96018bSArnd Bergmann static int dev_ifsioc(struct net *net, struct socket *sock,
29186b96018bSArnd Bergmann 			 unsigned int cmd, struct compat_ifreq __user *uifr32)
29197a229387SArnd Bergmann {
2920a2116ed2SArnd Bergmann 	struct ifreq __user *uifr;
29217a229387SArnd Bergmann 	int err;
29227a229387SArnd Bergmann 
2923a2116ed2SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
2924a2116ed2SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(*uifr32)))
29257a229387SArnd Bergmann 		return -EFAULT;
2926a2116ed2SArnd Bergmann 
2927a2116ed2SArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr);
2928a2116ed2SArnd Bergmann 
29297a229387SArnd Bergmann 	if (!err) {
29307a229387SArnd Bergmann 		switch (cmd) {
29317a229387SArnd Bergmann 		case SIOCGIFFLAGS:
29327a229387SArnd Bergmann 		case SIOCGIFMETRIC:
29337a229387SArnd Bergmann 		case SIOCGIFMTU:
29347a229387SArnd Bergmann 		case SIOCGIFMEM:
29357a229387SArnd Bergmann 		case SIOCGIFHWADDR:
29367a229387SArnd Bergmann 		case SIOCGIFINDEX:
29377a229387SArnd Bergmann 		case SIOCGIFADDR:
29387a229387SArnd Bergmann 		case SIOCGIFBRDADDR:
29397a229387SArnd Bergmann 		case SIOCGIFDSTADDR:
29407a229387SArnd Bergmann 		case SIOCGIFNETMASK:
2941fab2532bSArnd Bergmann 		case SIOCGIFPFLAGS:
29427a229387SArnd Bergmann 		case SIOCGIFTXQLEN:
2943fab2532bSArnd Bergmann 		case SIOCGMIIPHY:
2944fab2532bSArnd Bergmann 		case SIOCGMIIREG:
2945a2116ed2SArnd Bergmann 			if (copy_in_user(uifr32, uifr, sizeof(*uifr32)))
2946a2116ed2SArnd Bergmann 				err = -EFAULT;
29477a229387SArnd Bergmann 			break;
2948a2116ed2SArnd Bergmann 		}
2949a2116ed2SArnd Bergmann 	}
2950a2116ed2SArnd Bergmann 	return err;
2951a2116ed2SArnd Bergmann }
2952a2116ed2SArnd Bergmann 
2953a2116ed2SArnd Bergmann static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
2954a2116ed2SArnd Bergmann 			struct compat_ifreq __user *uifr32)
2955a2116ed2SArnd Bergmann {
2956a2116ed2SArnd Bergmann 	struct ifreq ifr;
2957a2116ed2SArnd Bergmann 	struct compat_ifmap __user *uifmap32;
2958a2116ed2SArnd Bergmann 	mm_segment_t old_fs;
2959a2116ed2SArnd Bergmann 	int err;
2960a2116ed2SArnd Bergmann 
2961a2116ed2SArnd Bergmann 	uifmap32 = &uifr32->ifr_ifru.ifru_map;
2962a2116ed2SArnd Bergmann 	err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name));
29633ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
29643ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
29653ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
29663ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.irq, &uifmap32->irq);
29673ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.dma, &uifmap32->dma);
29683ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.port, &uifmap32->port);
2969a2116ed2SArnd Bergmann 	if (err)
2970a2116ed2SArnd Bergmann 		return -EFAULT;
2971a2116ed2SArnd Bergmann 
2972a2116ed2SArnd Bergmann 	old_fs = get_fs();
2973a2116ed2SArnd Bergmann 	set_fs(KERNEL_DS);
2974c3f52ae6Sstephen hemminger 	err = dev_ioctl(net, cmd, (void  __user __force *)&ifr);
2975a2116ed2SArnd Bergmann 	set_fs(old_fs);
2976a2116ed2SArnd Bergmann 
2977a2116ed2SArnd Bergmann 	if (cmd == SIOCGIFMAP && !err) {
29787a229387SArnd Bergmann 		err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name));
29793ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
29803ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
29813ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
29823ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.irq, &uifmap32->irq);
29833ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.dma, &uifmap32->dma);
29843ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.port, &uifmap32->port);
29857a229387SArnd Bergmann 		if (err)
29867a229387SArnd Bergmann 			err = -EFAULT;
29877a229387SArnd Bergmann 	}
29887a229387SArnd Bergmann 	return err;
29897a229387SArnd Bergmann }
29907a229387SArnd Bergmann 
29917a229387SArnd Bergmann struct rtentry32 {
29927a229387SArnd Bergmann 	u32		rt_pad1;
29937a229387SArnd Bergmann 	struct sockaddr rt_dst;         /* target address               */
29947a229387SArnd Bergmann 	struct sockaddr rt_gateway;     /* gateway addr (RTF_GATEWAY)   */
29957a229387SArnd Bergmann 	struct sockaddr rt_genmask;     /* target network mask (IP)     */
29967a229387SArnd Bergmann 	unsigned short	rt_flags;
29977a229387SArnd Bergmann 	short		rt_pad2;
29987a229387SArnd Bergmann 	u32		rt_pad3;
29997a229387SArnd Bergmann 	unsigned char	rt_tos;
30007a229387SArnd Bergmann 	unsigned char	rt_class;
30017a229387SArnd Bergmann 	short		rt_pad4;
30027a229387SArnd Bergmann 	short		rt_metric;      /* +1 for binary compatibility! */
30037a229387SArnd Bergmann 	/* char * */ u32 rt_dev;        /* forcing the device at add    */
30047a229387SArnd Bergmann 	u32		rt_mtu;         /* per route MTU/Window         */
30057a229387SArnd Bergmann 	u32		rt_window;      /* Window clamping              */
30067a229387SArnd Bergmann 	unsigned short  rt_irtt;        /* Initial RTT                  */
30077a229387SArnd Bergmann };
30087a229387SArnd Bergmann 
30097a229387SArnd Bergmann struct in6_rtmsg32 {
30107a229387SArnd Bergmann 	struct in6_addr		rtmsg_dst;
30117a229387SArnd Bergmann 	struct in6_addr		rtmsg_src;
30127a229387SArnd Bergmann 	struct in6_addr		rtmsg_gateway;
30137a229387SArnd Bergmann 	u32			rtmsg_type;
30147a229387SArnd Bergmann 	u16			rtmsg_dst_len;
30157a229387SArnd Bergmann 	u16			rtmsg_src_len;
30167a229387SArnd Bergmann 	u32			rtmsg_metric;
30177a229387SArnd Bergmann 	u32			rtmsg_info;
30187a229387SArnd Bergmann 	u32			rtmsg_flags;
30197a229387SArnd Bergmann 	s32			rtmsg_ifindex;
30207a229387SArnd Bergmann };
30217a229387SArnd Bergmann 
30226b96018bSArnd Bergmann static int routing_ioctl(struct net *net, struct socket *sock,
30236b96018bSArnd Bergmann 			 unsigned int cmd, void __user *argp)
30247a229387SArnd Bergmann {
30257a229387SArnd Bergmann 	int ret;
30267a229387SArnd Bergmann 	void *r = NULL;
30277a229387SArnd Bergmann 	struct in6_rtmsg r6;
30287a229387SArnd Bergmann 	struct rtentry r4;
30297a229387SArnd Bergmann 	char devname[16];
30307a229387SArnd Bergmann 	u32 rtdev;
30317a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
30327a229387SArnd Bergmann 
30336b96018bSArnd Bergmann 	if (sock && sock->sk && sock->sk->sk_family == AF_INET6) { /* ipv6 */
30346b96018bSArnd Bergmann 		struct in6_rtmsg32 __user *ur6 = argp;
30357a229387SArnd Bergmann 		ret = copy_from_user(&r6.rtmsg_dst, &(ur6->rtmsg_dst),
30367a229387SArnd Bergmann 			3 * sizeof(struct in6_addr));
30373ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_type, &(ur6->rtmsg_type));
30383ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len));
30393ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_src_len, &(ur6->rtmsg_src_len));
30403ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_metric, &(ur6->rtmsg_metric));
30413ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_info, &(ur6->rtmsg_info));
30423ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_flags, &(ur6->rtmsg_flags));
30433ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex));
30447a229387SArnd Bergmann 
30457a229387SArnd Bergmann 		r = (void *) &r6;
30467a229387SArnd Bergmann 	} else { /* ipv4 */
30476b96018bSArnd Bergmann 		struct rtentry32 __user *ur4 = argp;
30487a229387SArnd Bergmann 		ret = copy_from_user(&r4.rt_dst, &(ur4->rt_dst),
30497a229387SArnd Bergmann 					3 * sizeof(struct sockaddr));
30503ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_flags, &(ur4->rt_flags));
30513ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_metric, &(ur4->rt_metric));
30523ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_mtu, &(ur4->rt_mtu));
30533ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_window, &(ur4->rt_window));
30543ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_irtt, &(ur4->rt_irtt));
30553ddc5b46SMathieu Desnoyers 		ret |= get_user(rtdev, &(ur4->rt_dev));
30567a229387SArnd Bergmann 		if (rtdev) {
30577a229387SArnd Bergmann 			ret |= copy_from_user(devname, compat_ptr(rtdev), 15);
3058c3f52ae6Sstephen hemminger 			r4.rt_dev = (char __user __force *)devname;
3059c3f52ae6Sstephen hemminger 			devname[15] = 0;
30607a229387SArnd Bergmann 		} else
30617a229387SArnd Bergmann 			r4.rt_dev = NULL;
30627a229387SArnd Bergmann 
30637a229387SArnd Bergmann 		r = (void *) &r4;
30647a229387SArnd Bergmann 	}
30657a229387SArnd Bergmann 
30667a229387SArnd Bergmann 	if (ret) {
30677a229387SArnd Bergmann 		ret = -EFAULT;
30687a229387SArnd Bergmann 		goto out;
30697a229387SArnd Bergmann 	}
30707a229387SArnd Bergmann 
30717a229387SArnd Bergmann 	set_fs(KERNEL_DS);
30726b96018bSArnd Bergmann 	ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r);
30737a229387SArnd Bergmann 	set_fs(old_fs);
30747a229387SArnd Bergmann 
30757a229387SArnd Bergmann out:
30767a229387SArnd Bergmann 	return ret;
30777a229387SArnd Bergmann }
30787a229387SArnd Bergmann 
30797a229387SArnd Bergmann /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE
30807a229387SArnd Bergmann  * for some operations; this forces use of the newer bridge-utils that
308125985edcSLucas De Marchi  * use compatible ioctls
30827a229387SArnd Bergmann  */
30836b96018bSArnd Bergmann static int old_bridge_ioctl(compat_ulong_t __user *argp)
30847a229387SArnd Bergmann {
30856b96018bSArnd Bergmann 	compat_ulong_t tmp;
30867a229387SArnd Bergmann 
30876b96018bSArnd Bergmann 	if (get_user(tmp, argp))
30887a229387SArnd Bergmann 		return -EFAULT;
30897a229387SArnd Bergmann 	if (tmp == BRCTL_GET_VERSION)
30907a229387SArnd Bergmann 		return BRCTL_VERSION + 1;
30917a229387SArnd Bergmann 	return -EINVAL;
30927a229387SArnd Bergmann }
30937a229387SArnd Bergmann 
30946b96018bSArnd Bergmann static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
30956b96018bSArnd Bergmann 			 unsigned int cmd, unsigned long arg)
30966b96018bSArnd Bergmann {
30976b96018bSArnd Bergmann 	void __user *argp = compat_ptr(arg);
30986b96018bSArnd Bergmann 	struct sock *sk = sock->sk;
30996b96018bSArnd Bergmann 	struct net *net = sock_net(sk);
31007a229387SArnd Bergmann 
31016b96018bSArnd Bergmann 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
3102590d4693SBen Hutchings 		return compat_ifr_data_ioctl(net, cmd, argp);
31037a229387SArnd Bergmann 
31046b96018bSArnd Bergmann 	switch (cmd) {
31056b96018bSArnd Bergmann 	case SIOCSIFBR:
31066b96018bSArnd Bergmann 	case SIOCGIFBR:
31076b96018bSArnd Bergmann 		return old_bridge_ioctl(argp);
31086b96018bSArnd Bergmann 	case SIOCGIFNAME:
31096b96018bSArnd Bergmann 		return dev_ifname32(net, argp);
31106b96018bSArnd Bergmann 	case SIOCGIFCONF:
31116b96018bSArnd Bergmann 		return dev_ifconf(net, argp);
31126b96018bSArnd Bergmann 	case SIOCETHTOOL:
31136b96018bSArnd Bergmann 		return ethtool_ioctl(net, argp);
31147a50a240SArnd Bergmann 	case SIOCWANDEV:
31157a50a240SArnd Bergmann 		return compat_siocwandev(net, argp);
3116a2116ed2SArnd Bergmann 	case SIOCGIFMAP:
3117a2116ed2SArnd Bergmann 	case SIOCSIFMAP:
3118a2116ed2SArnd Bergmann 		return compat_sioc_ifmap(net, cmd, argp);
31196b96018bSArnd Bergmann 	case SIOCBONDENSLAVE:
31206b96018bSArnd Bergmann 	case SIOCBONDRELEASE:
31216b96018bSArnd Bergmann 	case SIOCBONDSETHWADDR:
31226b96018bSArnd Bergmann 	case SIOCBONDCHANGEACTIVE:
31236b96018bSArnd Bergmann 		return bond_ioctl(net, cmd, argp);
31246b96018bSArnd Bergmann 	case SIOCADDRT:
31256b96018bSArnd Bergmann 	case SIOCDELRT:
31266b96018bSArnd Bergmann 		return routing_ioctl(net, sock, cmd, argp);
31276b96018bSArnd Bergmann 	case SIOCGSTAMP:
31286b96018bSArnd Bergmann 		return do_siocgstamp(net, sock, cmd, argp);
31296b96018bSArnd Bergmann 	case SIOCGSTAMPNS:
31306b96018bSArnd Bergmann 		return do_siocgstampns(net, sock, cmd, argp);
3131590d4693SBen Hutchings 	case SIOCBONDSLAVEINFOQUERY:
3132590d4693SBen Hutchings 	case SIOCBONDINFOQUERY:
3133a2116ed2SArnd Bergmann 	case SIOCSHWTSTAMP:
3134fd468c74SBen Hutchings 	case SIOCGHWTSTAMP:
3135590d4693SBen Hutchings 		return compat_ifr_data_ioctl(net, cmd, argp);
31367a229387SArnd Bergmann 
31376b96018bSArnd Bergmann 	case FIOSETOWN:
31386b96018bSArnd Bergmann 	case SIOCSPGRP:
31396b96018bSArnd Bergmann 	case FIOGETOWN:
31406b96018bSArnd Bergmann 	case SIOCGPGRP:
31416b96018bSArnd Bergmann 	case SIOCBRADDBR:
31426b96018bSArnd Bergmann 	case SIOCBRDELBR:
31436b96018bSArnd Bergmann 	case SIOCGIFVLAN:
31446b96018bSArnd Bergmann 	case SIOCSIFVLAN:
31456b96018bSArnd Bergmann 	case SIOCADDDLCI:
31466b96018bSArnd Bergmann 	case SIOCDELDLCI:
3147c62cce2cSAndrey Vagin 	case SIOCGSKNS:
31486b96018bSArnd Bergmann 		return sock_ioctl(file, cmd, arg);
31496b96018bSArnd Bergmann 
31506b96018bSArnd Bergmann 	case SIOCGIFFLAGS:
31516b96018bSArnd Bergmann 	case SIOCSIFFLAGS:
31526b96018bSArnd Bergmann 	case SIOCGIFMETRIC:
31536b96018bSArnd Bergmann 	case SIOCSIFMETRIC:
31546b96018bSArnd Bergmann 	case SIOCGIFMTU:
31556b96018bSArnd Bergmann 	case SIOCSIFMTU:
31566b96018bSArnd Bergmann 	case SIOCGIFMEM:
31576b96018bSArnd Bergmann 	case SIOCSIFMEM:
31586b96018bSArnd Bergmann 	case SIOCGIFHWADDR:
31596b96018bSArnd Bergmann 	case SIOCSIFHWADDR:
31606b96018bSArnd Bergmann 	case SIOCADDMULTI:
31616b96018bSArnd Bergmann 	case SIOCDELMULTI:
31626b96018bSArnd Bergmann 	case SIOCGIFINDEX:
31636b96018bSArnd Bergmann 	case SIOCGIFADDR:
31646b96018bSArnd Bergmann 	case SIOCSIFADDR:
31656b96018bSArnd Bergmann 	case SIOCSIFHWBROADCAST:
31666b96018bSArnd Bergmann 	case SIOCDIFADDR:
31676b96018bSArnd Bergmann 	case SIOCGIFBRDADDR:
31686b96018bSArnd Bergmann 	case SIOCSIFBRDADDR:
31696b96018bSArnd Bergmann 	case SIOCGIFDSTADDR:
31706b96018bSArnd Bergmann 	case SIOCSIFDSTADDR:
31716b96018bSArnd Bergmann 	case SIOCGIFNETMASK:
31726b96018bSArnd Bergmann 	case SIOCSIFNETMASK:
31736b96018bSArnd Bergmann 	case SIOCSIFPFLAGS:
31746b96018bSArnd Bergmann 	case SIOCGIFPFLAGS:
31756b96018bSArnd Bergmann 	case SIOCGIFTXQLEN:
31766b96018bSArnd Bergmann 	case SIOCSIFTXQLEN:
31776b96018bSArnd Bergmann 	case SIOCBRADDIF:
31786b96018bSArnd Bergmann 	case SIOCBRDELIF:
31799177efd3SArnd Bergmann 	case SIOCSIFNAME:
31809177efd3SArnd Bergmann 	case SIOCGMIIPHY:
31819177efd3SArnd Bergmann 	case SIOCGMIIREG:
31829177efd3SArnd Bergmann 	case SIOCSMIIREG:
31836b96018bSArnd Bergmann 		return dev_ifsioc(net, sock, cmd, argp);
31849177efd3SArnd Bergmann 
31856b96018bSArnd Bergmann 	case SIOCSARP:
31866b96018bSArnd Bergmann 	case SIOCGARP:
31876b96018bSArnd Bergmann 	case SIOCDARP:
31886b96018bSArnd Bergmann 	case SIOCATMARK:
31899177efd3SArnd Bergmann 		return sock_do_ioctl(net, sock, cmd, arg);
31909177efd3SArnd Bergmann 	}
31919177efd3SArnd Bergmann 
31926b96018bSArnd Bergmann 	return -ENOIOCTLCMD;
31936b96018bSArnd Bergmann }
31947a229387SArnd Bergmann 
319595c96174SEric Dumazet static long compat_sock_ioctl(struct file *file, unsigned int cmd,
319689bbfc95SShaun Pereira 			      unsigned long arg)
319789bbfc95SShaun Pereira {
319889bbfc95SShaun Pereira 	struct socket *sock = file->private_data;
319989bbfc95SShaun Pereira 	int ret = -ENOIOCTLCMD;
320087de87d5SDavid S. Miller 	struct sock *sk;
320187de87d5SDavid S. Miller 	struct net *net;
320287de87d5SDavid S. Miller 
320387de87d5SDavid S. Miller 	sk = sock->sk;
320487de87d5SDavid S. Miller 	net = sock_net(sk);
320589bbfc95SShaun Pereira 
320689bbfc95SShaun Pereira 	if (sock->ops->compat_ioctl)
320789bbfc95SShaun Pereira 		ret = sock->ops->compat_ioctl(sock, cmd, arg);
320889bbfc95SShaun Pereira 
320987de87d5SDavid S. Miller 	if (ret == -ENOIOCTLCMD &&
321087de87d5SDavid S. Miller 	    (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST))
321187de87d5SDavid S. Miller 		ret = compat_wext_handle_ioctl(net, cmd, arg);
321287de87d5SDavid S. Miller 
32136b96018bSArnd Bergmann 	if (ret == -ENOIOCTLCMD)
32146b96018bSArnd Bergmann 		ret = compat_sock_ioctl_trans(file, sock, cmd, arg);
32156b96018bSArnd Bergmann 
321689bbfc95SShaun Pereira 	return ret;
321789bbfc95SShaun Pereira }
321889bbfc95SShaun Pereira #endif
321989bbfc95SShaun Pereira 
3220ac5a488eSSridhar Samudrala int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
3221ac5a488eSSridhar Samudrala {
3222ac5a488eSSridhar Samudrala 	return sock->ops->bind(sock, addr, addrlen);
3223ac5a488eSSridhar Samudrala }
3224c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_bind);
3225ac5a488eSSridhar Samudrala 
3226ac5a488eSSridhar Samudrala int kernel_listen(struct socket *sock, int backlog)
3227ac5a488eSSridhar Samudrala {
3228ac5a488eSSridhar Samudrala 	return sock->ops->listen(sock, backlog);
3229ac5a488eSSridhar Samudrala }
3230c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_listen);
3231ac5a488eSSridhar Samudrala 
3232ac5a488eSSridhar Samudrala int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
3233ac5a488eSSridhar Samudrala {
3234ac5a488eSSridhar Samudrala 	struct sock *sk = sock->sk;
3235ac5a488eSSridhar Samudrala 	int err;
3236ac5a488eSSridhar Samudrala 
3237ac5a488eSSridhar Samudrala 	err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
3238ac5a488eSSridhar Samudrala 			       newsock);
3239ac5a488eSSridhar Samudrala 	if (err < 0)
3240ac5a488eSSridhar Samudrala 		goto done;
3241ac5a488eSSridhar Samudrala 
3242ac5a488eSSridhar Samudrala 	err = sock->ops->accept(sock, *newsock, flags);
3243ac5a488eSSridhar Samudrala 	if (err < 0) {
3244ac5a488eSSridhar Samudrala 		sock_release(*newsock);
3245fa8705b0STony Battersby 		*newsock = NULL;
3246ac5a488eSSridhar Samudrala 		goto done;
3247ac5a488eSSridhar Samudrala 	}
3248ac5a488eSSridhar Samudrala 
3249ac5a488eSSridhar Samudrala 	(*newsock)->ops = sock->ops;
32501b08534eSWei Yongjun 	__module_get((*newsock)->ops->owner);
3251ac5a488eSSridhar Samudrala 
3252ac5a488eSSridhar Samudrala done:
3253ac5a488eSSridhar Samudrala 	return err;
3254ac5a488eSSridhar Samudrala }
3255c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_accept);
3256ac5a488eSSridhar Samudrala 
3257ac5a488eSSridhar Samudrala int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
3258ac5a488eSSridhar Samudrala 		   int flags)
3259ac5a488eSSridhar Samudrala {
3260ac5a488eSSridhar Samudrala 	return sock->ops->connect(sock, addr, addrlen, flags);
3261ac5a488eSSridhar Samudrala }
3262c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_connect);
3263ac5a488eSSridhar Samudrala 
3264ac5a488eSSridhar Samudrala int kernel_getsockname(struct socket *sock, struct sockaddr *addr,
3265ac5a488eSSridhar Samudrala 			 int *addrlen)
3266ac5a488eSSridhar Samudrala {
3267ac5a488eSSridhar Samudrala 	return sock->ops->getname(sock, addr, addrlen, 0);
3268ac5a488eSSridhar Samudrala }
3269c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockname);
3270ac5a488eSSridhar Samudrala 
3271ac5a488eSSridhar Samudrala int kernel_getpeername(struct socket *sock, struct sockaddr *addr,
3272ac5a488eSSridhar Samudrala 			 int *addrlen)
3273ac5a488eSSridhar Samudrala {
3274ac5a488eSSridhar Samudrala 	return sock->ops->getname(sock, addr, addrlen, 1);
3275ac5a488eSSridhar Samudrala }
3276c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getpeername);
3277ac5a488eSSridhar Samudrala 
3278ac5a488eSSridhar Samudrala int kernel_getsockopt(struct socket *sock, int level, int optname,
3279ac5a488eSSridhar Samudrala 			char *optval, int *optlen)
3280ac5a488eSSridhar Samudrala {
3281ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3282fb8621bbSNamhyung Kim 	char __user *uoptval;
3283fb8621bbSNamhyung Kim 	int __user *uoptlen;
3284ac5a488eSSridhar Samudrala 	int err;
3285ac5a488eSSridhar Samudrala 
3286fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3287fb8621bbSNamhyung Kim 	uoptlen = (int __user __force *) optlen;
3288fb8621bbSNamhyung Kim 
3289ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3290ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3291fb8621bbSNamhyung Kim 		err = sock_getsockopt(sock, level, optname, uoptval, uoptlen);
3292ac5a488eSSridhar Samudrala 	else
3293fb8621bbSNamhyung Kim 		err = sock->ops->getsockopt(sock, level, optname, uoptval,
3294fb8621bbSNamhyung Kim 					    uoptlen);
3295ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3296ac5a488eSSridhar Samudrala 	return err;
3297ac5a488eSSridhar Samudrala }
3298c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockopt);
3299ac5a488eSSridhar Samudrala 
3300ac5a488eSSridhar Samudrala int kernel_setsockopt(struct socket *sock, int level, int optname,
3301b7058842SDavid S. Miller 			char *optval, unsigned int optlen)
3302ac5a488eSSridhar Samudrala {
3303ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3304fb8621bbSNamhyung Kim 	char __user *uoptval;
3305ac5a488eSSridhar Samudrala 	int err;
3306ac5a488eSSridhar Samudrala 
3307fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3308fb8621bbSNamhyung Kim 
3309ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3310ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3311fb8621bbSNamhyung Kim 		err = sock_setsockopt(sock, level, optname, uoptval, optlen);
3312ac5a488eSSridhar Samudrala 	else
3313fb8621bbSNamhyung Kim 		err = sock->ops->setsockopt(sock, level, optname, uoptval,
3314ac5a488eSSridhar Samudrala 					    optlen);
3315ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3316ac5a488eSSridhar Samudrala 	return err;
3317ac5a488eSSridhar Samudrala }
3318c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_setsockopt);
3319ac5a488eSSridhar Samudrala 
3320ac5a488eSSridhar Samudrala int kernel_sendpage(struct socket *sock, struct page *page, int offset,
3321ac5a488eSSridhar Samudrala 		    size_t size, int flags)
3322ac5a488eSSridhar Samudrala {
3323ac5a488eSSridhar Samudrala 	if (sock->ops->sendpage)
3324ac5a488eSSridhar Samudrala 		return sock->ops->sendpage(sock, page, offset, size, flags);
3325ac5a488eSSridhar Samudrala 
3326ac5a488eSSridhar Samudrala 	return sock_no_sendpage(sock, page, offset, size, flags);
3327ac5a488eSSridhar Samudrala }
3328c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendpage);
3329ac5a488eSSridhar Samudrala 
3330ac5a488eSSridhar Samudrala int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg)
3331ac5a488eSSridhar Samudrala {
3332ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3333ac5a488eSSridhar Samudrala 	int err;
3334ac5a488eSSridhar Samudrala 
3335ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3336ac5a488eSSridhar Samudrala 	err = sock->ops->ioctl(sock, cmd, arg);
3337ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3338ac5a488eSSridhar Samudrala 
3339ac5a488eSSridhar Samudrala 	return err;
3340ac5a488eSSridhar Samudrala }
3341c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sock_ioctl);
3342ac5a488eSSridhar Samudrala 
334391cf45f0STrond Myklebust int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
334491cf45f0STrond Myklebust {
334591cf45f0STrond Myklebust 	return sock->ops->shutdown(sock, how);
334691cf45f0STrond Myklebust }
334791cf45f0STrond Myklebust EXPORT_SYMBOL(kernel_sock_shutdown);
3348