xref: /openbmc/linux/net/socket.c (revision 4257c8ca)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * NET		An implementation of the SOCKET network access protocol.
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  * Version:	@(#)socket.c	1.1.93	18/02/95
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  * Authors:	Orest Zborowski, <obz@Kodak.COM>
802c30a84SJesper Juhl  *		Ross Biro
91da177e4SLinus Torvalds  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
101da177e4SLinus Torvalds  *
111da177e4SLinus Torvalds  * Fixes:
121da177e4SLinus Torvalds  *		Anonymous	:	NOTSOCK/BADF cleanup. Error fix in
131da177e4SLinus Torvalds  *					shutdown()
141da177e4SLinus Torvalds  *		Alan Cox	:	verify_area() fixes
151da177e4SLinus Torvalds  *		Alan Cox	:	Removed DDI
161da177e4SLinus Torvalds  *		Jonathan Kamens	:	SOCK_DGRAM reconnect bug
171da177e4SLinus Torvalds  *		Alan Cox	:	Moved a load of checks to the very
181da177e4SLinus Torvalds  *					top level.
191da177e4SLinus Torvalds  *		Alan Cox	:	Move address structures to/from user
201da177e4SLinus Torvalds  *					mode above the protocol layers.
211da177e4SLinus Torvalds  *		Rob Janssen	:	Allow 0 length sends.
221da177e4SLinus Torvalds  *		Alan Cox	:	Asynchronous I/O support (cribbed from the
231da177e4SLinus Torvalds  *					tty drivers).
241da177e4SLinus Torvalds  *		Niibe Yutaka	:	Asynchronous I/O for writes (4.4BSD style)
251da177e4SLinus Torvalds  *		Jeff Uphoff	:	Made max number of sockets command-line
261da177e4SLinus Torvalds  *					configurable.
271da177e4SLinus Torvalds  *		Matti Aarnio	:	Made the number of sockets dynamic,
281da177e4SLinus Torvalds  *					to be allocated when needed, and mr.
291da177e4SLinus Torvalds  *					Uphoff's max is used as max to be
301da177e4SLinus Torvalds  *					allowed to allocate.
311da177e4SLinus Torvalds  *		Linus		:	Argh. removed all the socket allocation
321da177e4SLinus Torvalds  *					altogether: it's in the inode now.
331da177e4SLinus Torvalds  *		Alan Cox	:	Made sock_alloc()/sock_release() public
341da177e4SLinus Torvalds  *					for NetROM and future kernel nfsd type
351da177e4SLinus Torvalds  *					stuff.
361da177e4SLinus Torvalds  *		Alan Cox	:	sendmsg/recvmsg basics.
371da177e4SLinus Torvalds  *		Tom Dyas	:	Export net symbols.
381da177e4SLinus Torvalds  *		Marcin Dalecki	:	Fixed problems with CONFIG_NET="n".
391da177e4SLinus Torvalds  *		Alan Cox	:	Added thread locking to sys_* calls
401da177e4SLinus Torvalds  *					for sockets. May have errors at the
411da177e4SLinus Torvalds  *					moment.
421da177e4SLinus Torvalds  *		Kevin Buhr	:	Fixed the dumb errors in the above.
431da177e4SLinus Torvalds  *		Andi Kleen	:	Some small cleanups, optimizations,
441da177e4SLinus Torvalds  *					and fixed a copy_from_user() bug.
451da177e4SLinus Torvalds  *		Tigran Aivazian	:	sys_send(args) calls sys_sendto(args, NULL, 0)
461da177e4SLinus Torvalds  *		Tigran Aivazian	:	Made listen(2) backlog sanity checks
471da177e4SLinus Torvalds  *					protocol-independent
481da177e4SLinus Torvalds  *
491da177e4SLinus Torvalds  *	This module is effectively the top level interface to the BSD socket
501da177e4SLinus Torvalds  *	paradigm.
511da177e4SLinus Torvalds  *
521da177e4SLinus Torvalds  *	Based upon Swansea University Computer Society NET3.039
531da177e4SLinus Torvalds  */
541da177e4SLinus Torvalds 
551da177e4SLinus Torvalds #include <linux/mm.h>
561da177e4SLinus Torvalds #include <linux/socket.h>
571da177e4SLinus Torvalds #include <linux/file.h>
581da177e4SLinus Torvalds #include <linux/net.h>
591da177e4SLinus Torvalds #include <linux/interrupt.h>
60aaca0bdcSUlrich Drepper #include <linux/thread_info.h>
6155737fdaSStephen Hemminger #include <linux/rcupdate.h>
621da177e4SLinus Torvalds #include <linux/netdevice.h>
631da177e4SLinus Torvalds #include <linux/proc_fs.h>
641da177e4SLinus Torvalds #include <linux/seq_file.h>
654a3e2f71SArjan van de Ven #include <linux/mutex.h>
661da177e4SLinus Torvalds #include <linux/if_bridge.h>
6720380731SArnaldo Carvalho de Melo #include <linux/if_frad.h>
6820380731SArnaldo Carvalho de Melo #include <linux/if_vlan.h>
69408eccceSDaniel Borkmann #include <linux/ptp_classify.h>
701da177e4SLinus Torvalds #include <linux/init.h>
711da177e4SLinus Torvalds #include <linux/poll.h>
721da177e4SLinus Torvalds #include <linux/cache.h>
731da177e4SLinus Torvalds #include <linux/module.h>
741da177e4SLinus Torvalds #include <linux/highmem.h>
751da177e4SLinus Torvalds #include <linux/mount.h>
76fba9be49SDavid Howells #include <linux/pseudo_fs.h>
771da177e4SLinus Torvalds #include <linux/security.h>
781da177e4SLinus Torvalds #include <linux/syscalls.h>
791da177e4SLinus Torvalds #include <linux/compat.h>
801da177e4SLinus Torvalds #include <linux/kmod.h>
813ec3b2fbSDavid Woodhouse #include <linux/audit.h>
82d86b5e0eSAdrian Bunk #include <linux/wireless.h>
831b8d7ae4SEric W. Biederman #include <linux/nsproxy.h>
841fd7317dSNick Black #include <linux/magic.h>
855a0e3ad6STejun Heo #include <linux/slab.h>
86600e1779SMasatake YAMATO #include <linux/xattr.h>
87c8e8cd57SJeremy Cline #include <linux/nospec.h>
888c3c447bSPaolo Abeni #include <linux/indirect_call_wrapper.h>
891da177e4SLinus Torvalds 
907c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
911da177e4SLinus Torvalds #include <asm/unistd.h>
921da177e4SLinus Torvalds 
931da177e4SLinus Torvalds #include <net/compat.h>
9487de87d5SDavid S. Miller #include <net/wext.h>
95f8451725SHerbert Xu #include <net/cls_cgroup.h>
961da177e4SLinus Torvalds 
971da177e4SLinus Torvalds #include <net/sock.h>
981da177e4SLinus Torvalds #include <linux/netfilter.h>
991da177e4SLinus Torvalds 
1006b96018bSArnd Bergmann #include <linux/if_tun.h>
1016b96018bSArnd Bergmann #include <linux/ipv6_route.h>
1026b96018bSArnd Bergmann #include <linux/route.h>
1036b96018bSArnd Bergmann #include <linux/sockios.h>
104076bb0c8SEliezer Tamir #include <net/busy_poll.h>
105f24b9be5SWillem de Bruijn #include <linux/errqueue.h>
10606021292SEliezer Tamir 
107e0d1095aSCong Wang #ifdef CONFIG_NET_RX_BUSY_POLL
10864b0dc51SEliezer Tamir unsigned int sysctl_net_busy_read __read_mostly;
10964b0dc51SEliezer Tamir unsigned int sysctl_net_busy_poll __read_mostly;
11006021292SEliezer Tamir #endif
1116b96018bSArnd Bergmann 
1128ae5e030SAl Viro static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to);
1138ae5e030SAl Viro static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from);
1141da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma);
1151da177e4SLinus Torvalds 
1161da177e4SLinus Torvalds static int sock_close(struct inode *inode, struct file *file);
117a11e1d43SLinus Torvalds static __poll_t sock_poll(struct file *file,
118a11e1d43SLinus Torvalds 			      struct poll_table_struct *wait);
11989bddce5SStephen Hemminger static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
12089bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
12189bbfc95SShaun Pereira static long compat_sock_ioctl(struct file *file,
12289bbfc95SShaun Pereira 			      unsigned int cmd, unsigned long arg);
12389bbfc95SShaun Pereira #endif
1241da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on);
1251da177e4SLinus Torvalds static ssize_t sock_sendpage(struct file *file, struct page *page,
1261da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more);
1279c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
1289c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
1299c55e01cSJens Axboe 				unsigned int flags);
1301da177e4SLinus Torvalds 
1311da177e4SLinus Torvalds /*
1321da177e4SLinus Torvalds  *	Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
1331da177e4SLinus Torvalds  *	in the operation structures but are done directly via the socketcall() multiplexor.
1341da177e4SLinus Torvalds  */
1351da177e4SLinus Torvalds 
136da7071d7SArjan van de Ven static const struct file_operations socket_file_ops = {
1371da177e4SLinus Torvalds 	.owner =	THIS_MODULE,
1381da177e4SLinus Torvalds 	.llseek =	no_llseek,
1398ae5e030SAl Viro 	.read_iter =	sock_read_iter,
1408ae5e030SAl Viro 	.write_iter =	sock_write_iter,
1411da177e4SLinus Torvalds 	.poll =		sock_poll,
1421da177e4SLinus Torvalds 	.unlocked_ioctl = sock_ioctl,
14389bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
14489bbfc95SShaun Pereira 	.compat_ioctl = compat_sock_ioctl,
14589bbfc95SShaun Pereira #endif
1461da177e4SLinus Torvalds 	.mmap =		sock_mmap,
1471da177e4SLinus Torvalds 	.release =	sock_close,
1481da177e4SLinus Torvalds 	.fasync =	sock_fasync,
1495274f052SJens Axboe 	.sendpage =	sock_sendpage,
1505274f052SJens Axboe 	.splice_write = generic_splice_sendpage,
1519c55e01cSJens Axboe 	.splice_read =	sock_splice_read,
1521da177e4SLinus Torvalds };
1531da177e4SLinus Torvalds 
1541da177e4SLinus Torvalds /*
1551da177e4SLinus Torvalds  *	The protocol list. Each protocol is registered in here.
1561da177e4SLinus Torvalds  */
1571da177e4SLinus Torvalds 
1581da177e4SLinus Torvalds static DEFINE_SPINLOCK(net_family_lock);
159190683a9SEric Dumazet static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly;
1601da177e4SLinus Torvalds 
1611da177e4SLinus Torvalds /*
16289bddce5SStephen Hemminger  * Support routines.
16389bddce5SStephen Hemminger  * Move socket addresses back and forth across the kernel/user
1641da177e4SLinus Torvalds  * divide and look after the messy bits.
1651da177e4SLinus Torvalds  */
1661da177e4SLinus Torvalds 
1671da177e4SLinus Torvalds /**
1681da177e4SLinus Torvalds  *	move_addr_to_kernel	-	copy a socket address into kernel space
1691da177e4SLinus Torvalds  *	@uaddr: Address in user space
1701da177e4SLinus Torvalds  *	@kaddr: Address in kernel space
1711da177e4SLinus Torvalds  *	@ulen: Length in user space
1721da177e4SLinus Torvalds  *
1731da177e4SLinus Torvalds  *	The address is copied into kernel space. If the provided address is
1741da177e4SLinus Torvalds  *	too long an error code of -EINVAL is returned. If the copy gives
1751da177e4SLinus Torvalds  *	invalid addresses -EFAULT is returned. On a success 0 is returned.
1761da177e4SLinus Torvalds  */
1771da177e4SLinus Torvalds 
17843db362dSMaciej Żenczykowski int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr)
1791da177e4SLinus Torvalds {
180230b1839SYOSHIFUJI Hideaki 	if (ulen < 0 || ulen > sizeof(struct sockaddr_storage))
1811da177e4SLinus Torvalds 		return -EINVAL;
1821da177e4SLinus Torvalds 	if (ulen == 0)
1831da177e4SLinus Torvalds 		return 0;
1841da177e4SLinus Torvalds 	if (copy_from_user(kaddr, uaddr, ulen))
1851da177e4SLinus Torvalds 		return -EFAULT;
1863ec3b2fbSDavid Woodhouse 	return audit_sockaddr(ulen, kaddr);
1871da177e4SLinus Torvalds }
1881da177e4SLinus Torvalds 
1891da177e4SLinus Torvalds /**
1901da177e4SLinus Torvalds  *	move_addr_to_user	-	copy an address to user space
1911da177e4SLinus Torvalds  *	@kaddr: kernel space address
1921da177e4SLinus Torvalds  *	@klen: length of address in kernel
1931da177e4SLinus Torvalds  *	@uaddr: user space address
1941da177e4SLinus Torvalds  *	@ulen: pointer to user length field
1951da177e4SLinus Torvalds  *
1961da177e4SLinus Torvalds  *	The value pointed to by ulen on entry is the buffer length available.
1971da177e4SLinus Torvalds  *	This is overwritten with the buffer space used. -EINVAL is returned
1981da177e4SLinus Torvalds  *	if an overlong buffer is specified or a negative buffer size. -EFAULT
1991da177e4SLinus Torvalds  *	is returned if either the buffer or the length field are not
2001da177e4SLinus Torvalds  *	accessible.
2011da177e4SLinus Torvalds  *	After copying the data up to the limit the user specifies, the true
2021da177e4SLinus Torvalds  *	length of the data is written over the length limit the user
2031da177e4SLinus Torvalds  *	specified. Zero is returned for a success.
2041da177e4SLinus Torvalds  */
2051da177e4SLinus Torvalds 
20643db362dSMaciej Żenczykowski static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen,
20711165f14Sstephen hemminger 			     void __user *uaddr, int __user *ulen)
2081da177e4SLinus Torvalds {
2091da177e4SLinus Torvalds 	int err;
2101da177e4SLinus Torvalds 	int len;
2111da177e4SLinus Torvalds 
21268c6beb3SHannes Frederic Sowa 	BUG_ON(klen > sizeof(struct sockaddr_storage));
21389bddce5SStephen Hemminger 	err = get_user(len, ulen);
21489bddce5SStephen Hemminger 	if (err)
2151da177e4SLinus Torvalds 		return err;
2161da177e4SLinus Torvalds 	if (len > klen)
2171da177e4SLinus Torvalds 		len = klen;
21868c6beb3SHannes Frederic Sowa 	if (len < 0)
2191da177e4SLinus Torvalds 		return -EINVAL;
22089bddce5SStephen Hemminger 	if (len) {
221d6fe3945SSteve Grubb 		if (audit_sockaddr(klen, kaddr))
222d6fe3945SSteve Grubb 			return -ENOMEM;
2231da177e4SLinus Torvalds 		if (copy_to_user(uaddr, kaddr, len))
2241da177e4SLinus Torvalds 			return -EFAULT;
2251da177e4SLinus Torvalds 	}
2261da177e4SLinus Torvalds 	/*
2271da177e4SLinus Torvalds 	 *      "fromlen shall refer to the value before truncation.."
2281da177e4SLinus Torvalds 	 *                      1003.1g
2291da177e4SLinus Torvalds 	 */
2301da177e4SLinus Torvalds 	return __put_user(klen, ulen);
2311da177e4SLinus Torvalds }
2321da177e4SLinus Torvalds 
23308009a76SAlexey Dobriyan static struct kmem_cache *sock_inode_cachep __ro_after_init;
2341da177e4SLinus Torvalds 
2351da177e4SLinus Torvalds static struct inode *sock_alloc_inode(struct super_block *sb)
2361da177e4SLinus Torvalds {
2371da177e4SLinus Torvalds 	struct socket_alloc *ei;
23889bddce5SStephen Hemminger 
239e94b1766SChristoph Lameter 	ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL);
2401da177e4SLinus Torvalds 	if (!ei)
2411da177e4SLinus Torvalds 		return NULL;
242333f7909SAl Viro 	init_waitqueue_head(&ei->socket.wq.wait);
243333f7909SAl Viro 	ei->socket.wq.fasync_list = NULL;
244333f7909SAl Viro 	ei->socket.wq.flags = 0;
2451da177e4SLinus Torvalds 
2461da177e4SLinus Torvalds 	ei->socket.state = SS_UNCONNECTED;
2471da177e4SLinus Torvalds 	ei->socket.flags = 0;
2481da177e4SLinus Torvalds 	ei->socket.ops = NULL;
2491da177e4SLinus Torvalds 	ei->socket.sk = NULL;
2501da177e4SLinus Torvalds 	ei->socket.file = NULL;
2511da177e4SLinus Torvalds 
2521da177e4SLinus Torvalds 	return &ei->vfs_inode;
2531da177e4SLinus Torvalds }
2541da177e4SLinus Torvalds 
2556d7855c5SAl Viro static void sock_free_inode(struct inode *inode)
2561da177e4SLinus Torvalds {
25743815482SEric Dumazet 	struct socket_alloc *ei;
25843815482SEric Dumazet 
25943815482SEric Dumazet 	ei = container_of(inode, struct socket_alloc, vfs_inode);
26043815482SEric Dumazet 	kmem_cache_free(sock_inode_cachep, ei);
2611da177e4SLinus Torvalds }
2621da177e4SLinus Torvalds 
26351cc5068SAlexey Dobriyan static void init_once(void *foo)
2641da177e4SLinus Torvalds {
2651da177e4SLinus Torvalds 	struct socket_alloc *ei = (struct socket_alloc *)foo;
2661da177e4SLinus Torvalds 
2671da177e4SLinus Torvalds 	inode_init_once(&ei->vfs_inode);
2681da177e4SLinus Torvalds }
2691da177e4SLinus Torvalds 
2701e911632Syuan linyu static void init_inodecache(void)
2711da177e4SLinus Torvalds {
2721da177e4SLinus Torvalds 	sock_inode_cachep = kmem_cache_create("sock_inode_cache",
2731da177e4SLinus Torvalds 					      sizeof(struct socket_alloc),
27489bddce5SStephen Hemminger 					      0,
27589bddce5SStephen Hemminger 					      (SLAB_HWCACHE_ALIGN |
27689bddce5SStephen Hemminger 					       SLAB_RECLAIM_ACCOUNT |
2775d097056SVladimir Davydov 					       SLAB_MEM_SPREAD | SLAB_ACCOUNT),
27820c2df83SPaul Mundt 					      init_once);
2791e911632Syuan linyu 	BUG_ON(sock_inode_cachep == NULL);
2801da177e4SLinus Torvalds }
2811da177e4SLinus Torvalds 
282b87221deSAlexey Dobriyan static const struct super_operations sockfs_ops = {
2831da177e4SLinus Torvalds 	.alloc_inode	= sock_alloc_inode,
2846d7855c5SAl Viro 	.free_inode	= sock_free_inode,
2851da177e4SLinus Torvalds 	.statfs		= simple_statfs,
2861da177e4SLinus Torvalds };
2871da177e4SLinus Torvalds 
288c23fbb6bSEric Dumazet /*
289c23fbb6bSEric Dumazet  * sockfs_dname() is called from d_path().
290c23fbb6bSEric Dumazet  */
291c23fbb6bSEric Dumazet static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen)
292c23fbb6bSEric Dumazet {
293c23fbb6bSEric Dumazet 	return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]",
294c5ef6035SDavid Howells 				d_inode(dentry)->i_ino);
295c23fbb6bSEric Dumazet }
296c23fbb6bSEric Dumazet 
2973ba13d17SAl Viro static const struct dentry_operations sockfs_dentry_operations = {
298c23fbb6bSEric Dumazet 	.d_dname  = sockfs_dname,
2991da177e4SLinus Torvalds };
3001da177e4SLinus Torvalds 
301bba0bd31SAndreas Gruenbacher static int sockfs_xattr_get(const struct xattr_handler *handler,
302bba0bd31SAndreas Gruenbacher 			    struct dentry *dentry, struct inode *inode,
303bba0bd31SAndreas Gruenbacher 			    const char *suffix, void *value, size_t size)
304bba0bd31SAndreas Gruenbacher {
305bba0bd31SAndreas Gruenbacher 	if (value) {
306bba0bd31SAndreas Gruenbacher 		if (dentry->d_name.len + 1 > size)
307bba0bd31SAndreas Gruenbacher 			return -ERANGE;
308bba0bd31SAndreas Gruenbacher 		memcpy(value, dentry->d_name.name, dentry->d_name.len + 1);
309bba0bd31SAndreas Gruenbacher 	}
310bba0bd31SAndreas Gruenbacher 	return dentry->d_name.len + 1;
311bba0bd31SAndreas Gruenbacher }
312bba0bd31SAndreas Gruenbacher 
313bba0bd31SAndreas Gruenbacher #define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname"
314bba0bd31SAndreas Gruenbacher #define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX)
315bba0bd31SAndreas Gruenbacher #define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1)
316bba0bd31SAndreas Gruenbacher 
317bba0bd31SAndreas Gruenbacher static const struct xattr_handler sockfs_xattr_handler = {
318bba0bd31SAndreas Gruenbacher 	.name = XATTR_NAME_SOCKPROTONAME,
319bba0bd31SAndreas Gruenbacher 	.get = sockfs_xattr_get,
320bba0bd31SAndreas Gruenbacher };
321bba0bd31SAndreas Gruenbacher 
3224a590153SAndreas Gruenbacher static int sockfs_security_xattr_set(const struct xattr_handler *handler,
3234a590153SAndreas Gruenbacher 				     struct dentry *dentry, struct inode *inode,
3244a590153SAndreas Gruenbacher 				     const char *suffix, const void *value,
3254a590153SAndreas Gruenbacher 				     size_t size, int flags)
3264a590153SAndreas Gruenbacher {
3274a590153SAndreas Gruenbacher 	/* Handled by LSM. */
3284a590153SAndreas Gruenbacher 	return -EAGAIN;
3294a590153SAndreas Gruenbacher }
3304a590153SAndreas Gruenbacher 
3314a590153SAndreas Gruenbacher static const struct xattr_handler sockfs_security_xattr_handler = {
3324a590153SAndreas Gruenbacher 	.prefix = XATTR_SECURITY_PREFIX,
3334a590153SAndreas Gruenbacher 	.set = sockfs_security_xattr_set,
3344a590153SAndreas Gruenbacher };
3354a590153SAndreas Gruenbacher 
336bba0bd31SAndreas Gruenbacher static const struct xattr_handler *sockfs_xattr_handlers[] = {
337bba0bd31SAndreas Gruenbacher 	&sockfs_xattr_handler,
3384a590153SAndreas Gruenbacher 	&sockfs_security_xattr_handler,
339bba0bd31SAndreas Gruenbacher 	NULL
340bba0bd31SAndreas Gruenbacher };
341bba0bd31SAndreas Gruenbacher 
342fba9be49SDavid Howells static int sockfs_init_fs_context(struct fs_context *fc)
343c74a1cbbSAl Viro {
344fba9be49SDavid Howells 	struct pseudo_fs_context *ctx = init_pseudo(fc, SOCKFS_MAGIC);
345fba9be49SDavid Howells 	if (!ctx)
346fba9be49SDavid Howells 		return -ENOMEM;
347fba9be49SDavid Howells 	ctx->ops = &sockfs_ops;
348fba9be49SDavid Howells 	ctx->dops = &sockfs_dentry_operations;
349fba9be49SDavid Howells 	ctx->xattr = sockfs_xattr_handlers;
350fba9be49SDavid Howells 	return 0;
351c74a1cbbSAl Viro }
352c74a1cbbSAl Viro 
353c74a1cbbSAl Viro static struct vfsmount *sock_mnt __read_mostly;
354c74a1cbbSAl Viro 
355c74a1cbbSAl Viro static struct file_system_type sock_fs_type = {
356c74a1cbbSAl Viro 	.name =		"sockfs",
357fba9be49SDavid Howells 	.init_fs_context = sockfs_init_fs_context,
358c74a1cbbSAl Viro 	.kill_sb =	kill_anon_super,
359c74a1cbbSAl Viro };
360c74a1cbbSAl Viro 
3611da177e4SLinus Torvalds /*
3621da177e4SLinus Torvalds  *	Obtains the first available file descriptor and sets it up for use.
3631da177e4SLinus Torvalds  *
36439d8c1b6SDavid S. Miller  *	These functions create file structures and maps them to fd space
36539d8c1b6SDavid S. Miller  *	of the current process. On success it returns file descriptor
3661da177e4SLinus Torvalds  *	and file struct implicitly stored in sock->file.
3671da177e4SLinus Torvalds  *	Note that another thread may close file descriptor before we return
3681da177e4SLinus Torvalds  *	from this function. We use the fact that now we do not refer
3691da177e4SLinus Torvalds  *	to socket after mapping. If one day we will need it, this
3701da177e4SLinus Torvalds  *	function will increment ref. count on file by 1.
3711da177e4SLinus Torvalds  *
3721da177e4SLinus Torvalds  *	In any case returned fd MAY BE not valid!
3731da177e4SLinus Torvalds  *	This race condition is unavoidable
3741da177e4SLinus Torvalds  *	with shared fd spaces, we cannot solve it inside kernel,
3751da177e4SLinus Torvalds  *	but we take care of internal coherence yet.
3761da177e4SLinus Torvalds  */
3771da177e4SLinus Torvalds 
3788a3c245cSPedro Tammela /**
3798a3c245cSPedro Tammela  *	sock_alloc_file - Bind a &socket to a &file
3808a3c245cSPedro Tammela  *	@sock: socket
3818a3c245cSPedro Tammela  *	@flags: file status flags
3828a3c245cSPedro Tammela  *	@dname: protocol name
3838a3c245cSPedro Tammela  *
3848a3c245cSPedro Tammela  *	Returns the &file bound with @sock, implicitly storing it
3858a3c245cSPedro Tammela  *	in sock->file. If dname is %NULL, sets to "".
3868a3c245cSPedro Tammela  *	On failure the return is a ERR pointer (see linux/err.h).
3878a3c245cSPedro Tammela  *	This function uses GFP_KERNEL internally.
3888a3c245cSPedro Tammela  */
3898a3c245cSPedro Tammela 
390aab174f0SLinus Torvalds struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)
3911da177e4SLinus Torvalds {
3927cbe66b6SAl Viro 	struct file *file;
3931da177e4SLinus Torvalds 
394d93aa9d8SAl Viro 	if (!dname)
395d93aa9d8SAl Viro 		dname = sock->sk ? sock->sk->sk_prot_creator->name : "";
39639d8c1b6SDavid S. Miller 
397d93aa9d8SAl Viro 	file = alloc_file_pseudo(SOCK_INODE(sock), sock_mnt, dname,
398d93aa9d8SAl Viro 				O_RDWR | (flags & O_NONBLOCK),
399cc3808f8SAl Viro 				&socket_file_ops);
400b5ffe634SViresh Kumar 	if (IS_ERR(file)) {
4018e1611e2SAl Viro 		sock_release(sock);
40239b65252SAnatol Pomozov 		return file;
403cc3808f8SAl Viro 	}
4041da177e4SLinus Torvalds 
4051da177e4SLinus Torvalds 	sock->file = file;
40607dc3f07SBenjamin LaHaise 	file->private_data = sock;
407d8e464ecSLinus Torvalds 	stream_open(SOCK_INODE(sock), file);
40828407630SAl Viro 	return file;
4091da177e4SLinus Torvalds }
41056b31d1cSAl Viro EXPORT_SYMBOL(sock_alloc_file);
4111da177e4SLinus Torvalds 
41256b31d1cSAl Viro static int sock_map_fd(struct socket *sock, int flags)
41339d8c1b6SDavid S. Miller {
41439d8c1b6SDavid S. Miller 	struct file *newfile;
41528407630SAl Viro 	int fd = get_unused_fd_flags(flags);
416ce4bb04cSAl Viro 	if (unlikely(fd < 0)) {
417ce4bb04cSAl Viro 		sock_release(sock);
4181da177e4SLinus Torvalds 		return fd;
419ce4bb04cSAl Viro 	}
4201da177e4SLinus Torvalds 
421aab174f0SLinus Torvalds 	newfile = sock_alloc_file(sock, flags, NULL);
4224546e44cSEnrico Weigelt 	if (!IS_ERR(newfile)) {
4231da177e4SLinus Torvalds 		fd_install(fd, newfile);
4241da177e4SLinus Torvalds 		return fd;
4251da177e4SLinus Torvalds 	}
42628407630SAl Viro 
42728407630SAl Viro 	put_unused_fd(fd);
42828407630SAl Viro 	return PTR_ERR(newfile);
4291da177e4SLinus Torvalds }
4301da177e4SLinus Torvalds 
4318a3c245cSPedro Tammela /**
4328a3c245cSPedro Tammela  *	sock_from_file - Return the &socket bounded to @file.
4338a3c245cSPedro Tammela  *	@file: file
4348a3c245cSPedro Tammela  *	@err: pointer to an error code return
4358a3c245cSPedro Tammela  *
4368a3c245cSPedro Tammela  *	On failure returns %NULL and assigns -ENOTSOCK to @err.
4378a3c245cSPedro Tammela  */
4388a3c245cSPedro Tammela 
439406a3c63SJohn Fastabend struct socket *sock_from_file(struct file *file, int *err)
4406cb153caSBenjamin LaHaise {
4416cb153caSBenjamin LaHaise 	if (file->f_op == &socket_file_ops)
4426cb153caSBenjamin LaHaise 		return file->private_data;	/* set in sock_map_fd */
4436cb153caSBenjamin LaHaise 
4446cb153caSBenjamin LaHaise 	*err = -ENOTSOCK;
4456cb153caSBenjamin LaHaise 	return NULL;
4466cb153caSBenjamin LaHaise }
447406a3c63SJohn Fastabend EXPORT_SYMBOL(sock_from_file);
4486cb153caSBenjamin LaHaise 
4491da177e4SLinus Torvalds /**
4501da177e4SLinus Torvalds  *	sockfd_lookup - Go from a file number to its socket slot
4511da177e4SLinus Torvalds  *	@fd: file handle
4521da177e4SLinus Torvalds  *	@err: pointer to an error code return
4531da177e4SLinus Torvalds  *
4541da177e4SLinus Torvalds  *	The file handle passed in is locked and the socket it is bound
455241c4667SRosen, Rami  *	to is returned. If an error occurs the err pointer is overwritten
4561da177e4SLinus Torvalds  *	with a negative errno code and NULL is returned. The function checks
4571da177e4SLinus Torvalds  *	for both invalid handles and passing a handle which is not a socket.
4581da177e4SLinus Torvalds  *
4591da177e4SLinus Torvalds  *	On a success the socket object pointer is returned.
4601da177e4SLinus Torvalds  */
4611da177e4SLinus Torvalds 
4621da177e4SLinus Torvalds struct socket *sockfd_lookup(int fd, int *err)
4631da177e4SLinus Torvalds {
4641da177e4SLinus Torvalds 	struct file *file;
4651da177e4SLinus Torvalds 	struct socket *sock;
4661da177e4SLinus Torvalds 
46789bddce5SStephen Hemminger 	file = fget(fd);
46889bddce5SStephen Hemminger 	if (!file) {
4691da177e4SLinus Torvalds 		*err = -EBADF;
4701da177e4SLinus Torvalds 		return NULL;
4711da177e4SLinus Torvalds 	}
47289bddce5SStephen Hemminger 
4736cb153caSBenjamin LaHaise 	sock = sock_from_file(file, err);
4746cb153caSBenjamin LaHaise 	if (!sock)
4751da177e4SLinus Torvalds 		fput(file);
4766cb153caSBenjamin LaHaise 	return sock;
4771da177e4SLinus Torvalds }
478c6d409cfSEric Dumazet EXPORT_SYMBOL(sockfd_lookup);
4791da177e4SLinus Torvalds 
4806cb153caSBenjamin LaHaise static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
4816cb153caSBenjamin LaHaise {
48200e188efSAl Viro 	struct fd f = fdget(fd);
4836cb153caSBenjamin LaHaise 	struct socket *sock;
4846cb153caSBenjamin LaHaise 
4853672558cSHua Zhong 	*err = -EBADF;
48600e188efSAl Viro 	if (f.file) {
48700e188efSAl Viro 		sock = sock_from_file(f.file, err);
48800e188efSAl Viro 		if (likely(sock)) {
48900e188efSAl Viro 			*fput_needed = f.flags;
4901da177e4SLinus Torvalds 			return sock;
49100e188efSAl Viro 		}
49200e188efSAl Viro 		fdput(f);
4936cb153caSBenjamin LaHaise 	}
4946cb153caSBenjamin LaHaise 	return NULL;
4951da177e4SLinus Torvalds }
4961da177e4SLinus Torvalds 
497600e1779SMasatake YAMATO static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer,
498600e1779SMasatake YAMATO 				size_t size)
499600e1779SMasatake YAMATO {
500600e1779SMasatake YAMATO 	ssize_t len;
501600e1779SMasatake YAMATO 	ssize_t used = 0;
502600e1779SMasatake YAMATO 
503c5ef6035SDavid Howells 	len = security_inode_listsecurity(d_inode(dentry), buffer, size);
504600e1779SMasatake YAMATO 	if (len < 0)
505600e1779SMasatake YAMATO 		return len;
506600e1779SMasatake YAMATO 	used += len;
507600e1779SMasatake YAMATO 	if (buffer) {
508600e1779SMasatake YAMATO 		if (size < used)
509600e1779SMasatake YAMATO 			return -ERANGE;
510600e1779SMasatake YAMATO 		buffer += len;
511600e1779SMasatake YAMATO 	}
512600e1779SMasatake YAMATO 
513600e1779SMasatake YAMATO 	len = (XATTR_NAME_SOCKPROTONAME_LEN + 1);
514600e1779SMasatake YAMATO 	used += len;
515600e1779SMasatake YAMATO 	if (buffer) {
516600e1779SMasatake YAMATO 		if (size < used)
517600e1779SMasatake YAMATO 			return -ERANGE;
518600e1779SMasatake YAMATO 		memcpy(buffer, XATTR_NAME_SOCKPROTONAME, len);
519600e1779SMasatake YAMATO 		buffer += len;
520600e1779SMasatake YAMATO 	}
521600e1779SMasatake YAMATO 
522600e1779SMasatake YAMATO 	return used;
523600e1779SMasatake YAMATO }
524600e1779SMasatake YAMATO 
525dc647ec8STobias Klauser static int sockfs_setattr(struct dentry *dentry, struct iattr *iattr)
52686741ec2SLorenzo Colitti {
52786741ec2SLorenzo Colitti 	int err = simple_setattr(dentry, iattr);
52886741ec2SLorenzo Colitti 
529e1a3a60aSEric Biggers 	if (!err && (iattr->ia_valid & ATTR_UID)) {
53086741ec2SLorenzo Colitti 		struct socket *sock = SOCKET_I(d_inode(dentry));
53186741ec2SLorenzo Colitti 
5326d8c50dcSCong Wang 		if (sock->sk)
53386741ec2SLorenzo Colitti 			sock->sk->sk_uid = iattr->ia_uid;
5346d8c50dcSCong Wang 		else
5356d8c50dcSCong Wang 			err = -ENOENT;
53686741ec2SLorenzo Colitti 	}
53786741ec2SLorenzo Colitti 
53886741ec2SLorenzo Colitti 	return err;
53986741ec2SLorenzo Colitti }
54086741ec2SLorenzo Colitti 
541600e1779SMasatake YAMATO static const struct inode_operations sockfs_inode_ops = {
542600e1779SMasatake YAMATO 	.listxattr = sockfs_listxattr,
54386741ec2SLorenzo Colitti 	.setattr = sockfs_setattr,
544600e1779SMasatake YAMATO };
545600e1779SMasatake YAMATO 
5461da177e4SLinus Torvalds /**
5471da177e4SLinus Torvalds  *	sock_alloc - allocate a socket
5481da177e4SLinus Torvalds  *
5491da177e4SLinus Torvalds  *	Allocate a new inode and socket object. The two are bound together
5501da177e4SLinus Torvalds  *	and initialised. The socket is then returned. If we are out of inodes
5518a3c245cSPedro Tammela  *	NULL is returned. This functions uses GFP_KERNEL internally.
5521da177e4SLinus Torvalds  */
5531da177e4SLinus Torvalds 
554f4a00aacSTom Herbert struct socket *sock_alloc(void)
5551da177e4SLinus Torvalds {
5561da177e4SLinus Torvalds 	struct inode *inode;
5571da177e4SLinus Torvalds 	struct socket *sock;
5581da177e4SLinus Torvalds 
559a209dfc7SEric Dumazet 	inode = new_inode_pseudo(sock_mnt->mnt_sb);
5601da177e4SLinus Torvalds 	if (!inode)
5611da177e4SLinus Torvalds 		return NULL;
5621da177e4SLinus Torvalds 
5631da177e4SLinus Torvalds 	sock = SOCKET_I(inode);
5641da177e4SLinus Torvalds 
56585fe4025SChristoph Hellwig 	inode->i_ino = get_next_ino();
5661da177e4SLinus Torvalds 	inode->i_mode = S_IFSOCK | S_IRWXUGO;
5678192b0c4SDavid Howells 	inode->i_uid = current_fsuid();
5688192b0c4SDavid Howells 	inode->i_gid = current_fsgid();
569600e1779SMasatake YAMATO 	inode->i_op = &sockfs_inode_ops;
5701da177e4SLinus Torvalds 
5711da177e4SLinus Torvalds 	return sock;
5721da177e4SLinus Torvalds }
573f4a00aacSTom Herbert EXPORT_SYMBOL(sock_alloc);
5741da177e4SLinus Torvalds 
5751da177e4SLinus Torvalds /**
5761da177e4SLinus Torvalds  *	sock_release - close a socket
5771da177e4SLinus Torvalds  *	@sock: socket to close
5781da177e4SLinus Torvalds  *
5791da177e4SLinus Torvalds  *	The socket is released from the protocol stack if it has a release
5801da177e4SLinus Torvalds  *	callback, and the inode is then released if the socket is bound to
5811da177e4SLinus Torvalds  *	an inode not a file.
5821da177e4SLinus Torvalds  */
5831da177e4SLinus Torvalds 
5846d8c50dcSCong Wang static void __sock_release(struct socket *sock, struct inode *inode)
5851da177e4SLinus Torvalds {
5861da177e4SLinus Torvalds 	if (sock->ops) {
5871da177e4SLinus Torvalds 		struct module *owner = sock->ops->owner;
5881da177e4SLinus Torvalds 
5896d8c50dcSCong Wang 		if (inode)
5906d8c50dcSCong Wang 			inode_lock(inode);
5911da177e4SLinus Torvalds 		sock->ops->release(sock);
592ff7b11aaSEric Biggers 		sock->sk = NULL;
5936d8c50dcSCong Wang 		if (inode)
5946d8c50dcSCong Wang 			inode_unlock(inode);
5951da177e4SLinus Torvalds 		sock->ops = NULL;
5961da177e4SLinus Torvalds 		module_put(owner);
5971da177e4SLinus Torvalds 	}
5981da177e4SLinus Torvalds 
599333f7909SAl Viro 	if (sock->wq.fasync_list)
6003410f22eSYang Yingliang 		pr_err("%s: fasync list not empty!\n", __func__);
6011da177e4SLinus Torvalds 
6021da177e4SLinus Torvalds 	if (!sock->file) {
6031da177e4SLinus Torvalds 		iput(SOCK_INODE(sock));
6041da177e4SLinus Torvalds 		return;
6051da177e4SLinus Torvalds 	}
6061da177e4SLinus Torvalds 	sock->file = NULL;
6071da177e4SLinus Torvalds }
6086d8c50dcSCong Wang 
6096d8c50dcSCong Wang void sock_release(struct socket *sock)
6106d8c50dcSCong Wang {
6116d8c50dcSCong Wang 	__sock_release(sock, NULL);
6126d8c50dcSCong Wang }
613c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_release);
6141da177e4SLinus Torvalds 
615c14ac945SSoheil Hassas Yeganeh void __sock_tx_timestamp(__u16 tsflags, __u8 *tx_flags)
61620d49473SPatrick Ohly {
617140c55d4SEric Dumazet 	u8 flags = *tx_flags;
618140c55d4SEric Dumazet 
619c14ac945SSoheil Hassas Yeganeh 	if (tsflags & SOF_TIMESTAMPING_TX_HARDWARE)
620140c55d4SEric Dumazet 		flags |= SKBTX_HW_TSTAMP;
621140c55d4SEric Dumazet 
622c14ac945SSoheil Hassas Yeganeh 	if (tsflags & SOF_TIMESTAMPING_TX_SOFTWARE)
623140c55d4SEric Dumazet 		flags |= SKBTX_SW_TSTAMP;
624140c55d4SEric Dumazet 
625c14ac945SSoheil Hassas Yeganeh 	if (tsflags & SOF_TIMESTAMPING_TX_SCHED)
626140c55d4SEric Dumazet 		flags |= SKBTX_SCHED_TSTAMP;
627140c55d4SEric Dumazet 
628140c55d4SEric Dumazet 	*tx_flags = flags;
62920d49473SPatrick Ohly }
63067cc0d40SWillem de Bruijn EXPORT_SYMBOL(__sock_tx_timestamp);
63120d49473SPatrick Ohly 
6328c3c447bSPaolo Abeni INDIRECT_CALLABLE_DECLARE(int inet_sendmsg(struct socket *, struct msghdr *,
6338c3c447bSPaolo Abeni 					   size_t));
634a648a592SPaolo Abeni INDIRECT_CALLABLE_DECLARE(int inet6_sendmsg(struct socket *, struct msghdr *,
635a648a592SPaolo Abeni 					    size_t));
636d8725c86SAl Viro static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg)
6371da177e4SLinus Torvalds {
638a648a592SPaolo Abeni 	int ret = INDIRECT_CALL_INET(sock->ops->sendmsg, inet6_sendmsg,
639a648a592SPaolo Abeni 				     inet_sendmsg, sock, msg,
640a648a592SPaolo Abeni 				     msg_data_left(msg));
641d8725c86SAl Viro 	BUG_ON(ret == -EIOCBQUEUED);
642d8725c86SAl Viro 	return ret;
6431da177e4SLinus Torvalds }
6440cf00c6fSGu Zheng 
64585806af0SRandy Dunlap /**
64685806af0SRandy Dunlap  *	sock_sendmsg - send a message through @sock
64785806af0SRandy Dunlap  *	@sock: socket
64885806af0SRandy Dunlap  *	@msg: message to send
64985806af0SRandy Dunlap  *
65085806af0SRandy Dunlap  *	Sends @msg through @sock, passing through LSM.
65185806af0SRandy Dunlap  *	Returns the number of bytes sent, or an error code.
65285806af0SRandy Dunlap  */
653d8725c86SAl Viro int sock_sendmsg(struct socket *sock, struct msghdr *msg)
6540cf00c6fSGu Zheng {
655d8725c86SAl Viro 	int err = security_socket_sendmsg(sock, msg,
65601e97e65SAl Viro 					  msg_data_left(msg));
6571b784140SYing Xue 
658d8725c86SAl Viro 	return err ?: sock_sendmsg_nosec(sock, msg);
6590cf00c6fSGu Zheng }
660c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_sendmsg);
6611da177e4SLinus Torvalds 
6628a3c245cSPedro Tammela /**
6638a3c245cSPedro Tammela  *	kernel_sendmsg - send a message through @sock (kernel-space)
6648a3c245cSPedro Tammela  *	@sock: socket
6658a3c245cSPedro Tammela  *	@msg: message header
6668a3c245cSPedro Tammela  *	@vec: kernel vec
6678a3c245cSPedro Tammela  *	@num: vec array length
6688a3c245cSPedro Tammela  *	@size: total message data size
6698a3c245cSPedro Tammela  *
6708a3c245cSPedro Tammela  *	Builds the message data with @vec and sends it through @sock.
6718a3c245cSPedro Tammela  *	Returns the number of bytes sent, or an error code.
6728a3c245cSPedro Tammela  */
6738a3c245cSPedro Tammela 
6741da177e4SLinus Torvalds int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
6751da177e4SLinus Torvalds 		   struct kvec *vec, size_t num, size_t size)
6761da177e4SLinus Torvalds {
677aa563d7bSDavid Howells 	iov_iter_kvec(&msg->msg_iter, WRITE, vec, num, size);
678d8725c86SAl Viro 	return sock_sendmsg(sock, msg);
6791da177e4SLinus Torvalds }
680c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendmsg);
6811da177e4SLinus Torvalds 
6828a3c245cSPedro Tammela /**
6838a3c245cSPedro Tammela  *	kernel_sendmsg_locked - send a message through @sock (kernel-space)
6848a3c245cSPedro Tammela  *	@sk: sock
6858a3c245cSPedro Tammela  *	@msg: message header
6868a3c245cSPedro Tammela  *	@vec: output s/g array
6878a3c245cSPedro Tammela  *	@num: output s/g array length
6888a3c245cSPedro Tammela  *	@size: total message data size
6898a3c245cSPedro Tammela  *
6908a3c245cSPedro Tammela  *	Builds the message data with @vec and sends it through @sock.
6918a3c245cSPedro Tammela  *	Returns the number of bytes sent, or an error code.
6928a3c245cSPedro Tammela  *	Caller must hold @sk.
6938a3c245cSPedro Tammela  */
6948a3c245cSPedro Tammela 
695306b13ebSTom Herbert int kernel_sendmsg_locked(struct sock *sk, struct msghdr *msg,
696306b13ebSTom Herbert 			  struct kvec *vec, size_t num, size_t size)
697306b13ebSTom Herbert {
698306b13ebSTom Herbert 	struct socket *sock = sk->sk_socket;
699306b13ebSTom Herbert 
700306b13ebSTom Herbert 	if (!sock->ops->sendmsg_locked)
701db5980d8SJohn Fastabend 		return sock_no_sendmsg_locked(sk, msg, size);
702306b13ebSTom Herbert 
703aa563d7bSDavid Howells 	iov_iter_kvec(&msg->msg_iter, WRITE, vec, num, size);
704306b13ebSTom Herbert 
705306b13ebSTom Herbert 	return sock->ops->sendmsg_locked(sk, msg, msg_data_left(msg));
706306b13ebSTom Herbert }
707306b13ebSTom Herbert EXPORT_SYMBOL(kernel_sendmsg_locked);
708306b13ebSTom Herbert 
7098605330aSSoheil Hassas Yeganeh static bool skb_is_err_queue(const struct sk_buff *skb)
7108605330aSSoheil Hassas Yeganeh {
7118605330aSSoheil Hassas Yeganeh 	/* pkt_type of skbs enqueued on the error queue are set to
7128605330aSSoheil Hassas Yeganeh 	 * PACKET_OUTGOING in skb_set_err_queue(). This is only safe to do
7138605330aSSoheil Hassas Yeganeh 	 * in recvmsg, since skbs received on a local socket will never
7148605330aSSoheil Hassas Yeganeh 	 * have a pkt_type of PACKET_OUTGOING.
7158605330aSSoheil Hassas Yeganeh 	 */
7168605330aSSoheil Hassas Yeganeh 	return skb->pkt_type == PACKET_OUTGOING;
7178605330aSSoheil Hassas Yeganeh }
7188605330aSSoheil Hassas Yeganeh 
719b50a5c70SMiroslav Lichvar /* On transmit, software and hardware timestamps are returned independently.
720b50a5c70SMiroslav Lichvar  * As the two skb clones share the hardware timestamp, which may be updated
721b50a5c70SMiroslav Lichvar  * before the software timestamp is received, a hardware TX timestamp may be
722b50a5c70SMiroslav Lichvar  * returned only if there is no software TX timestamp. Ignore false software
723b50a5c70SMiroslav Lichvar  * timestamps, which may be made in the __sock_recv_timestamp() call when the
7247f1bc6e9SDeepa Dinamani  * option SO_TIMESTAMP_OLD(NS) is enabled on the socket, even when the skb has a
725b50a5c70SMiroslav Lichvar  * hardware timestamp.
726b50a5c70SMiroslav Lichvar  */
727b50a5c70SMiroslav Lichvar static bool skb_is_swtx_tstamp(const struct sk_buff *skb, int false_tstamp)
728b50a5c70SMiroslav Lichvar {
729b50a5c70SMiroslav Lichvar 	return skb->tstamp && !false_tstamp && skb_is_err_queue(skb);
730b50a5c70SMiroslav Lichvar }
731b50a5c70SMiroslav Lichvar 
732aad9c8c4SMiroslav Lichvar static void put_ts_pktinfo(struct msghdr *msg, struct sk_buff *skb)
733aad9c8c4SMiroslav Lichvar {
734aad9c8c4SMiroslav Lichvar 	struct scm_ts_pktinfo ts_pktinfo;
735aad9c8c4SMiroslav Lichvar 	struct net_device *orig_dev;
736aad9c8c4SMiroslav Lichvar 
737aad9c8c4SMiroslav Lichvar 	if (!skb_mac_header_was_set(skb))
738aad9c8c4SMiroslav Lichvar 		return;
739aad9c8c4SMiroslav Lichvar 
740aad9c8c4SMiroslav Lichvar 	memset(&ts_pktinfo, 0, sizeof(ts_pktinfo));
741aad9c8c4SMiroslav Lichvar 
742aad9c8c4SMiroslav Lichvar 	rcu_read_lock();
743aad9c8c4SMiroslav Lichvar 	orig_dev = dev_get_by_napi_id(skb_napi_id(skb));
744aad9c8c4SMiroslav Lichvar 	if (orig_dev)
745aad9c8c4SMiroslav Lichvar 		ts_pktinfo.if_index = orig_dev->ifindex;
746aad9c8c4SMiroslav Lichvar 	rcu_read_unlock();
747aad9c8c4SMiroslav Lichvar 
748aad9c8c4SMiroslav Lichvar 	ts_pktinfo.pkt_length = skb->len - skb_mac_offset(skb);
749aad9c8c4SMiroslav Lichvar 	put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_PKTINFO,
750aad9c8c4SMiroslav Lichvar 		 sizeof(ts_pktinfo), &ts_pktinfo);
751aad9c8c4SMiroslav Lichvar }
752aad9c8c4SMiroslav Lichvar 
75392f37fd2SEric Dumazet /*
75492f37fd2SEric Dumazet  * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
75592f37fd2SEric Dumazet  */
75692f37fd2SEric Dumazet void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
75792f37fd2SEric Dumazet 	struct sk_buff *skb)
75892f37fd2SEric Dumazet {
75920d49473SPatrick Ohly 	int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
760887feae3SDeepa Dinamani 	int new_tstamp = sock_flag(sk, SOCK_TSTAMP_NEW);
7619718475eSDeepa Dinamani 	struct scm_timestamping_internal tss;
7629718475eSDeepa Dinamani 
763b50a5c70SMiroslav Lichvar 	int empty = 1, false_tstamp = 0;
76420d49473SPatrick Ohly 	struct skb_shared_hwtstamps *shhwtstamps =
76520d49473SPatrick Ohly 		skb_hwtstamps(skb);
76692f37fd2SEric Dumazet 
76720d49473SPatrick Ohly 	/* Race occurred between timestamp enabling and packet
76820d49473SPatrick Ohly 	   receiving.  Fill in the current time for now. */
769b50a5c70SMiroslav Lichvar 	if (need_software_tstamp && skb->tstamp == 0) {
77020d49473SPatrick Ohly 		__net_timestamp(skb);
771b50a5c70SMiroslav Lichvar 		false_tstamp = 1;
772b50a5c70SMiroslav Lichvar 	}
77320d49473SPatrick Ohly 
77420d49473SPatrick Ohly 	if (need_software_tstamp) {
77592f37fd2SEric Dumazet 		if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
776887feae3SDeepa Dinamani 			if (new_tstamp) {
777887feae3SDeepa Dinamani 				struct __kernel_sock_timeval tv;
778887feae3SDeepa Dinamani 
779887feae3SDeepa Dinamani 				skb_get_new_timestamp(skb, &tv);
780887feae3SDeepa Dinamani 				put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_NEW,
781887feae3SDeepa Dinamani 					 sizeof(tv), &tv);
782887feae3SDeepa Dinamani 			} else {
78313c6ee2aSDeepa Dinamani 				struct __kernel_old_timeval tv;
784887feae3SDeepa Dinamani 
78520d49473SPatrick Ohly 				skb_get_timestamp(skb, &tv);
7867f1bc6e9SDeepa Dinamani 				put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_OLD,
78720d49473SPatrick Ohly 					 sizeof(tv), &tv);
788887feae3SDeepa Dinamani 			}
789887feae3SDeepa Dinamani 		} else {
790887feae3SDeepa Dinamani 			if (new_tstamp) {
791887feae3SDeepa Dinamani 				struct __kernel_timespec ts;
792887feae3SDeepa Dinamani 
793887feae3SDeepa Dinamani 				skb_get_new_timestampns(skb, &ts);
794887feae3SDeepa Dinamani 				put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_NEW,
795887feae3SDeepa Dinamani 					 sizeof(ts), &ts);
79692f37fd2SEric Dumazet 			} else {
797f24b9be5SWillem de Bruijn 				struct timespec ts;
798887feae3SDeepa Dinamani 
799f24b9be5SWillem de Bruijn 				skb_get_timestampns(skb, &ts);
8007f1bc6e9SDeepa Dinamani 				put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_OLD,
801f24b9be5SWillem de Bruijn 					 sizeof(ts), &ts);
80292f37fd2SEric Dumazet 			}
80392f37fd2SEric Dumazet 		}
804887feae3SDeepa Dinamani 	}
80592f37fd2SEric Dumazet 
806f24b9be5SWillem de Bruijn 	memset(&tss, 0, sizeof(tss));
807c199105dSWillem de Bruijn 	if ((sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE) &&
8089718475eSDeepa Dinamani 	    ktime_to_timespec64_cond(skb->tstamp, tss.ts + 0))
80920d49473SPatrick Ohly 		empty = 0;
8104d276eb6SWillem de Bruijn 	if (shhwtstamps &&
811b9f40e21SWillem de Bruijn 	    (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
812b50a5c70SMiroslav Lichvar 	    !skb_is_swtx_tstamp(skb, false_tstamp) &&
8139718475eSDeepa Dinamani 	    ktime_to_timespec64_cond(shhwtstamps->hwtstamp, tss.ts + 2)) {
81420d49473SPatrick Ohly 		empty = 0;
815aad9c8c4SMiroslav Lichvar 		if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_PKTINFO) &&
816aad9c8c4SMiroslav Lichvar 		    !skb_is_err_queue(skb))
817aad9c8c4SMiroslav Lichvar 			put_ts_pktinfo(msg, skb);
818aad9c8c4SMiroslav Lichvar 	}
8191c885808SFrancis Yan 	if (!empty) {
8209718475eSDeepa Dinamani 		if (sock_flag(sk, SOCK_TSTAMP_NEW))
8219718475eSDeepa Dinamani 			put_cmsg_scm_timestamping64(msg, &tss);
8229718475eSDeepa Dinamani 		else
8239718475eSDeepa Dinamani 			put_cmsg_scm_timestamping(msg, &tss);
8241c885808SFrancis Yan 
8258605330aSSoheil Hassas Yeganeh 		if (skb_is_err_queue(skb) && skb->len &&
8264ef1b286SSoheil Hassas Yeganeh 		    SKB_EXT_ERR(skb)->opt_stats)
8271c885808SFrancis Yan 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_OPT_STATS,
8281c885808SFrancis Yan 				 skb->len, skb->data);
8291c885808SFrancis Yan 	}
83020d49473SPatrick Ohly }
8317c81fd8bSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
8327c81fd8bSArnaldo Carvalho de Melo 
8336e3e939fSJohannes Berg void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
8346e3e939fSJohannes Berg 	struct sk_buff *skb)
8356e3e939fSJohannes Berg {
8366e3e939fSJohannes Berg 	int ack;
8376e3e939fSJohannes Berg 
8386e3e939fSJohannes Berg 	if (!sock_flag(sk, SOCK_WIFI_STATUS))
8396e3e939fSJohannes Berg 		return;
8406e3e939fSJohannes Berg 	if (!skb->wifi_acked_valid)
8416e3e939fSJohannes Berg 		return;
8426e3e939fSJohannes Berg 
8436e3e939fSJohannes Berg 	ack = skb->wifi_acked;
8446e3e939fSJohannes Berg 
8456e3e939fSJohannes Berg 	put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack);
8466e3e939fSJohannes Berg }
8476e3e939fSJohannes Berg EXPORT_SYMBOL_GPL(__sock_recv_wifi_status);
8486e3e939fSJohannes Berg 
84911165f14Sstephen hemminger static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk,
85011165f14Sstephen hemminger 				   struct sk_buff *skb)
8513b885787SNeil Horman {
852744d5a3eSEyal Birger 	if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && SOCK_SKB_CB(skb)->dropcount)
8533b885787SNeil Horman 		put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL,
854744d5a3eSEyal Birger 			sizeof(__u32), &SOCK_SKB_CB(skb)->dropcount);
8553b885787SNeil Horman }
8563b885787SNeil Horman 
857767dd033SEric Dumazet void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
8583b885787SNeil Horman 	struct sk_buff *skb)
8593b885787SNeil Horman {
8603b885787SNeil Horman 	sock_recv_timestamp(msg, sk, skb);
8613b885787SNeil Horman 	sock_recv_drops(msg, sk, skb);
8623b885787SNeil Horman }
863767dd033SEric Dumazet EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops);
8643b885787SNeil Horman 
8658c3c447bSPaolo Abeni INDIRECT_CALLABLE_DECLARE(int inet_recvmsg(struct socket *, struct msghdr *,
8668c3c447bSPaolo Abeni 					   size_t, int));
867a648a592SPaolo Abeni INDIRECT_CALLABLE_DECLARE(int inet6_recvmsg(struct socket *, struct msghdr *,
868a648a592SPaolo Abeni 					    size_t, int));
8691b784140SYing Xue static inline int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
8701b784140SYing Xue 				     int flags)
871a2e27255SArnaldo Carvalho de Melo {
872a648a592SPaolo Abeni 	return INDIRECT_CALL_INET(sock->ops->recvmsg, inet6_recvmsg,
873a648a592SPaolo Abeni 				  inet_recvmsg, sock, msg, msg_data_left(msg),
874a648a592SPaolo Abeni 				  flags);
8752da62906SAl Viro }
876a2e27255SArnaldo Carvalho de Melo 
87785806af0SRandy Dunlap /**
87885806af0SRandy Dunlap  *	sock_recvmsg - receive a message from @sock
87985806af0SRandy Dunlap  *	@sock: socket
88085806af0SRandy Dunlap  *	@msg: message to receive
88185806af0SRandy Dunlap  *	@flags: message flags
88285806af0SRandy Dunlap  *
88385806af0SRandy Dunlap  *	Receives @msg from @sock, passing through LSM. Returns the total number
88485806af0SRandy Dunlap  *	of bytes received, or an error.
88585806af0SRandy Dunlap  */
8862da62906SAl Viro int sock_recvmsg(struct socket *sock, struct msghdr *msg, int flags)
8872da62906SAl Viro {
8882da62906SAl Viro 	int err = security_socket_recvmsg(sock, msg, msg_data_left(msg), flags);
8892da62906SAl Viro 
8902da62906SAl Viro 	return err ?: sock_recvmsg_nosec(sock, msg, flags);
8911da177e4SLinus Torvalds }
892c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_recvmsg);
8931da177e4SLinus Torvalds 
894c1249c0aSMartin Lucina /**
895c1249c0aSMartin Lucina  *	kernel_recvmsg - Receive a message from a socket (kernel space)
896c1249c0aSMartin Lucina  *	@sock: The socket to receive the message from
897c1249c0aSMartin Lucina  *	@msg: Received message
898c1249c0aSMartin Lucina  *	@vec: Input s/g array for message data
899c1249c0aSMartin Lucina  *	@num: Size of input s/g array
900c1249c0aSMartin Lucina  *	@size: Number of bytes to read
901c1249c0aSMartin Lucina  *	@flags: Message flags (MSG_DONTWAIT, etc...)
902c1249c0aSMartin Lucina  *
903c1249c0aSMartin Lucina  *	On return the msg structure contains the scatter/gather array passed in the
904c1249c0aSMartin Lucina  *	vec argument. The array is modified so that it consists of the unfilled
905c1249c0aSMartin Lucina  *	portion of the original array.
906c1249c0aSMartin Lucina  *
907c1249c0aSMartin Lucina  *	The returned value is the total number of bytes received, or an error.
908c1249c0aSMartin Lucina  */
9098a3c245cSPedro Tammela 
9101da177e4SLinus Torvalds int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
91189bddce5SStephen Hemminger 		   struct kvec *vec, size_t num, size_t size, int flags)
9121da177e4SLinus Torvalds {
9131da177e4SLinus Torvalds 	mm_segment_t oldfs = get_fs();
9141da177e4SLinus Torvalds 	int result;
9151da177e4SLinus Torvalds 
916aa563d7bSDavid Howells 	iov_iter_kvec(&msg->msg_iter, READ, vec, num, size);
9171da177e4SLinus Torvalds 	set_fs(KERNEL_DS);
9182da62906SAl Viro 	result = sock_recvmsg(sock, msg, flags);
9191da177e4SLinus Torvalds 	set_fs(oldfs);
9201da177e4SLinus Torvalds 	return result;
9211da177e4SLinus Torvalds }
922c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_recvmsg);
9231da177e4SLinus Torvalds 
92420380731SArnaldo Carvalho de Melo static ssize_t sock_sendpage(struct file *file, struct page *page,
9251da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more)
9261da177e4SLinus Torvalds {
9271da177e4SLinus Torvalds 	struct socket *sock;
9281da177e4SLinus Torvalds 	int flags;
9291da177e4SLinus Torvalds 
930b69aee04SEric Dumazet 	sock = file->private_data;
9311da177e4SLinus Torvalds 
93235f9c09fSEric Dumazet 	flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
93335f9c09fSEric Dumazet 	/* more is a combination of MSG_MORE and MSG_SENDPAGE_NOTLAST */
93435f9c09fSEric Dumazet 	flags |= more;
9351da177e4SLinus Torvalds 
936e6949583SLinus Torvalds 	return kernel_sendpage(sock, page, offset, size, flags);
9371da177e4SLinus Torvalds }
9381da177e4SLinus Torvalds 
9399c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
9409c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
9419c55e01cSJens Axboe 				unsigned int flags)
9429c55e01cSJens Axboe {
9439c55e01cSJens Axboe 	struct socket *sock = file->private_data;
9449c55e01cSJens Axboe 
945997b37daSRémi Denis-Courmont 	if (unlikely(!sock->ops->splice_read))
94695506588SSlavomir Kaslev 		return generic_file_splice_read(file, ppos, pipe, len, flags);
947997b37daSRémi Denis-Courmont 
9489c55e01cSJens Axboe 	return sock->ops->splice_read(sock, ppos, pipe, len, flags);
9499c55e01cSJens Axboe }
9509c55e01cSJens Axboe 
9518ae5e030SAl Viro static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to)
952ce1d4d3eSChristoph Hellwig {
9536d652330SAl Viro 	struct file *file = iocb->ki_filp;
9546d652330SAl Viro 	struct socket *sock = file->private_data;
9550345f931Stadeusz.struk@intel.com 	struct msghdr msg = {.msg_iter = *to,
9560345f931Stadeusz.struk@intel.com 			     .msg_iocb = iocb};
9578ae5e030SAl Viro 	ssize_t res;
958ce1d4d3eSChristoph Hellwig 
9598ae5e030SAl Viro 	if (file->f_flags & O_NONBLOCK)
9608ae5e030SAl Viro 		msg.msg_flags = MSG_DONTWAIT;
9618ae5e030SAl Viro 
9628ae5e030SAl Viro 	if (iocb->ki_pos != 0)
963ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
964027445c3SBadari Pulavarty 
96566ee59afSChristoph Hellwig 	if (!iov_iter_count(to))	/* Match SYS5 behaviour */
966ce1d4d3eSChristoph Hellwig 		return 0;
967ce1d4d3eSChristoph Hellwig 
9682da62906SAl Viro 	res = sock_recvmsg(sock, &msg, msg.msg_flags);
9698ae5e030SAl Viro 	*to = msg.msg_iter;
9708ae5e030SAl Viro 	return res;
971ce1d4d3eSChristoph Hellwig }
972ce1d4d3eSChristoph Hellwig 
9738ae5e030SAl Viro static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from)
9741da177e4SLinus Torvalds {
9756d652330SAl Viro 	struct file *file = iocb->ki_filp;
9766d652330SAl Viro 	struct socket *sock = file->private_data;
9770345f931Stadeusz.struk@intel.com 	struct msghdr msg = {.msg_iter = *from,
9780345f931Stadeusz.struk@intel.com 			     .msg_iocb = iocb};
9798ae5e030SAl Viro 	ssize_t res;
9801da177e4SLinus Torvalds 
9818ae5e030SAl Viro 	if (iocb->ki_pos != 0)
982ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
983027445c3SBadari Pulavarty 
9848ae5e030SAl Viro 	if (file->f_flags & O_NONBLOCK)
9858ae5e030SAl Viro 		msg.msg_flags = MSG_DONTWAIT;
9868ae5e030SAl Viro 
9876d652330SAl Viro 	if (sock->type == SOCK_SEQPACKET)
9886d652330SAl Viro 		msg.msg_flags |= MSG_EOR;
9896d652330SAl Viro 
990d8725c86SAl Viro 	res = sock_sendmsg(sock, &msg);
9918ae5e030SAl Viro 	*from = msg.msg_iter;
9928ae5e030SAl Viro 	return res;
9931da177e4SLinus Torvalds }
9941da177e4SLinus Torvalds 
9951da177e4SLinus Torvalds /*
9961da177e4SLinus Torvalds  * Atomic setting of ioctl hooks to avoid race
9971da177e4SLinus Torvalds  * with module unload.
9981da177e4SLinus Torvalds  */
9991da177e4SLinus Torvalds 
10004a3e2f71SArjan van de Ven static DEFINE_MUTEX(br_ioctl_mutex);
1001c6d409cfSEric Dumazet static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg);
10021da177e4SLinus Torvalds 
1003881d966bSEric W. Biederman void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *))
10041da177e4SLinus Torvalds {
10054a3e2f71SArjan van de Ven 	mutex_lock(&br_ioctl_mutex);
10061da177e4SLinus Torvalds 	br_ioctl_hook = hook;
10074a3e2f71SArjan van de Ven 	mutex_unlock(&br_ioctl_mutex);
10081da177e4SLinus Torvalds }
10091da177e4SLinus Torvalds EXPORT_SYMBOL(brioctl_set);
10101da177e4SLinus Torvalds 
10114a3e2f71SArjan van de Ven static DEFINE_MUTEX(vlan_ioctl_mutex);
1012881d966bSEric W. Biederman static int (*vlan_ioctl_hook) (struct net *, void __user *arg);
10131da177e4SLinus Torvalds 
1014881d966bSEric W. Biederman void vlan_ioctl_set(int (*hook) (struct net *, void __user *))
10151da177e4SLinus Torvalds {
10164a3e2f71SArjan van de Ven 	mutex_lock(&vlan_ioctl_mutex);
10171da177e4SLinus Torvalds 	vlan_ioctl_hook = hook;
10184a3e2f71SArjan van de Ven 	mutex_unlock(&vlan_ioctl_mutex);
10191da177e4SLinus Torvalds }
10201da177e4SLinus Torvalds EXPORT_SYMBOL(vlan_ioctl_set);
10211da177e4SLinus Torvalds 
10224a3e2f71SArjan van de Ven static DEFINE_MUTEX(dlci_ioctl_mutex);
10231da177e4SLinus Torvalds static int (*dlci_ioctl_hook) (unsigned int, void __user *);
10241da177e4SLinus Torvalds 
10251da177e4SLinus Torvalds void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
10261da177e4SLinus Torvalds {
10274a3e2f71SArjan van de Ven 	mutex_lock(&dlci_ioctl_mutex);
10281da177e4SLinus Torvalds 	dlci_ioctl_hook = hook;
10294a3e2f71SArjan van de Ven 	mutex_unlock(&dlci_ioctl_mutex);
10301da177e4SLinus Torvalds }
10311da177e4SLinus Torvalds EXPORT_SYMBOL(dlci_ioctl_set);
10321da177e4SLinus Torvalds 
10336b96018bSArnd Bergmann static long sock_do_ioctl(struct net *net, struct socket *sock,
103463ff03abSJohannes Berg 			  unsigned int cmd, unsigned long arg)
10356b96018bSArnd Bergmann {
10366b96018bSArnd Bergmann 	int err;
10376b96018bSArnd Bergmann 	void __user *argp = (void __user *)arg;
10386b96018bSArnd Bergmann 
10396b96018bSArnd Bergmann 	err = sock->ops->ioctl(sock, cmd, arg);
10406b96018bSArnd Bergmann 
10416b96018bSArnd Bergmann 	/*
10426b96018bSArnd Bergmann 	 * If this ioctl is unknown try to hand it down
10436b96018bSArnd Bergmann 	 * to the NIC driver.
10446b96018bSArnd Bergmann 	 */
104536fd633eSAl Viro 	if (err != -ENOIOCTLCMD)
10466b96018bSArnd Bergmann 		return err;
10476b96018bSArnd Bergmann 
104836fd633eSAl Viro 	if (cmd == SIOCGIFCONF) {
104936fd633eSAl Viro 		struct ifconf ifc;
105036fd633eSAl Viro 		if (copy_from_user(&ifc, argp, sizeof(struct ifconf)))
105136fd633eSAl Viro 			return -EFAULT;
105236fd633eSAl Viro 		rtnl_lock();
105336fd633eSAl Viro 		err = dev_ifconf(net, &ifc, sizeof(struct ifreq));
105436fd633eSAl Viro 		rtnl_unlock();
105536fd633eSAl Viro 		if (!err && copy_to_user(argp, &ifc, sizeof(struct ifconf)))
105636fd633eSAl Viro 			err = -EFAULT;
105744c02a2cSAl Viro 	} else {
105844c02a2cSAl Viro 		struct ifreq ifr;
105944c02a2cSAl Viro 		bool need_copyout;
106063ff03abSJohannes Berg 		if (copy_from_user(&ifr, argp, sizeof(struct ifreq)))
106144c02a2cSAl Viro 			return -EFAULT;
106244c02a2cSAl Viro 		err = dev_ioctl(net, cmd, &ifr, &need_copyout);
106344c02a2cSAl Viro 		if (!err && need_copyout)
106463ff03abSJohannes Berg 			if (copy_to_user(argp, &ifr, sizeof(struct ifreq)))
106544c02a2cSAl Viro 				return -EFAULT;
106636fd633eSAl Viro 	}
10676b96018bSArnd Bergmann 	return err;
10686b96018bSArnd Bergmann }
10696b96018bSArnd Bergmann 
10701da177e4SLinus Torvalds /*
10711da177e4SLinus Torvalds  *	With an ioctl, arg may well be a user mode pointer, but we don't know
10721da177e4SLinus Torvalds  *	what to do with it - that's up to the protocol still.
10731da177e4SLinus Torvalds  */
10741da177e4SLinus Torvalds 
10758a3c245cSPedro Tammela /**
10768a3c245cSPedro Tammela  *	get_net_ns - increment the refcount of the network namespace
10778a3c245cSPedro Tammela  *	@ns: common namespace (net)
10788a3c245cSPedro Tammela  *
10798a3c245cSPedro Tammela  *	Returns the net's common namespace.
10808a3c245cSPedro Tammela  */
10818a3c245cSPedro Tammela 
1082d8d211a2SKirill Tkhai struct ns_common *get_net_ns(struct ns_common *ns)
1083c62cce2cSAndrey Vagin {
1084c62cce2cSAndrey Vagin 	return &get_net(container_of(ns, struct net, ns))->ns;
1085c62cce2cSAndrey Vagin }
1086d8d211a2SKirill Tkhai EXPORT_SYMBOL_GPL(get_net_ns);
1087c62cce2cSAndrey Vagin 
10881da177e4SLinus Torvalds static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
10891da177e4SLinus Torvalds {
10901da177e4SLinus Torvalds 	struct socket *sock;
1091881d966bSEric W. Biederman 	struct sock *sk;
10921da177e4SLinus Torvalds 	void __user *argp = (void __user *)arg;
10931da177e4SLinus Torvalds 	int pid, err;
1094881d966bSEric W. Biederman 	struct net *net;
10951da177e4SLinus Torvalds 
1096b69aee04SEric Dumazet 	sock = file->private_data;
1097881d966bSEric W. Biederman 	sk = sock->sk;
10983b1e0a65SYOSHIFUJI Hideaki 	net = sock_net(sk);
109944c02a2cSAl Viro 	if (unlikely(cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))) {
110044c02a2cSAl Viro 		struct ifreq ifr;
110144c02a2cSAl Viro 		bool need_copyout;
110244c02a2cSAl Viro 		if (copy_from_user(&ifr, argp, sizeof(struct ifreq)))
110344c02a2cSAl Viro 			return -EFAULT;
110444c02a2cSAl Viro 		err = dev_ioctl(net, cmd, &ifr, &need_copyout);
110544c02a2cSAl Viro 		if (!err && need_copyout)
110644c02a2cSAl Viro 			if (copy_to_user(argp, &ifr, sizeof(struct ifreq)))
110744c02a2cSAl Viro 				return -EFAULT;
11081da177e4SLinus Torvalds 	} else
11093d23e349SJohannes Berg #ifdef CONFIG_WEXT_CORE
11101da177e4SLinus Torvalds 	if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
1111b1b0c245SAl Viro 		err = wext_handle_ioctl(net, cmd, argp);
11121da177e4SLinus Torvalds 	} else
11133d23e349SJohannes Berg #endif
11141da177e4SLinus Torvalds 		switch (cmd) {
11151da177e4SLinus Torvalds 		case FIOSETOWN:
11161da177e4SLinus Torvalds 		case SIOCSPGRP:
11171da177e4SLinus Torvalds 			err = -EFAULT;
11181da177e4SLinus Torvalds 			if (get_user(pid, (int __user *)argp))
11191da177e4SLinus Torvalds 				break;
1120393cc3f5SJiri Slaby 			err = f_setown(sock->file, pid, 1);
11211da177e4SLinus Torvalds 			break;
11221da177e4SLinus Torvalds 		case FIOGETOWN:
11231da177e4SLinus Torvalds 		case SIOCGPGRP:
1124609d7fa9SEric W. Biederman 			err = put_user(f_getown(sock->file),
112589bddce5SStephen Hemminger 				       (int __user *)argp);
11261da177e4SLinus Torvalds 			break;
11271da177e4SLinus Torvalds 		case SIOCGIFBR:
11281da177e4SLinus Torvalds 		case SIOCSIFBR:
11291da177e4SLinus Torvalds 		case SIOCBRADDBR:
11301da177e4SLinus Torvalds 		case SIOCBRDELBR:
11311da177e4SLinus Torvalds 			err = -ENOPKG;
11321da177e4SLinus Torvalds 			if (!br_ioctl_hook)
11331da177e4SLinus Torvalds 				request_module("bridge");
11341da177e4SLinus Torvalds 
11354a3e2f71SArjan van de Ven 			mutex_lock(&br_ioctl_mutex);
11361da177e4SLinus Torvalds 			if (br_ioctl_hook)
1137881d966bSEric W. Biederman 				err = br_ioctl_hook(net, cmd, argp);
11384a3e2f71SArjan van de Ven 			mutex_unlock(&br_ioctl_mutex);
11391da177e4SLinus Torvalds 			break;
11401da177e4SLinus Torvalds 		case SIOCGIFVLAN:
11411da177e4SLinus Torvalds 		case SIOCSIFVLAN:
11421da177e4SLinus Torvalds 			err = -ENOPKG;
11431da177e4SLinus Torvalds 			if (!vlan_ioctl_hook)
11441da177e4SLinus Torvalds 				request_module("8021q");
11451da177e4SLinus Torvalds 
11464a3e2f71SArjan van de Ven 			mutex_lock(&vlan_ioctl_mutex);
11471da177e4SLinus Torvalds 			if (vlan_ioctl_hook)
1148881d966bSEric W. Biederman 				err = vlan_ioctl_hook(net, argp);
11494a3e2f71SArjan van de Ven 			mutex_unlock(&vlan_ioctl_mutex);
11501da177e4SLinus Torvalds 			break;
11511da177e4SLinus Torvalds 		case SIOCADDDLCI:
11521da177e4SLinus Torvalds 		case SIOCDELDLCI:
11531da177e4SLinus Torvalds 			err = -ENOPKG;
11541da177e4SLinus Torvalds 			if (!dlci_ioctl_hook)
11551da177e4SLinus Torvalds 				request_module("dlci");
11561da177e4SLinus Torvalds 
11574a3e2f71SArjan van de Ven 			mutex_lock(&dlci_ioctl_mutex);
11587512cbf6SPavel Emelyanov 			if (dlci_ioctl_hook)
11591da177e4SLinus Torvalds 				err = dlci_ioctl_hook(cmd, argp);
11604a3e2f71SArjan van de Ven 			mutex_unlock(&dlci_ioctl_mutex);
11611da177e4SLinus Torvalds 			break;
1162c62cce2cSAndrey Vagin 		case SIOCGSKNS:
1163c62cce2cSAndrey Vagin 			err = -EPERM;
1164c62cce2cSAndrey Vagin 			if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
1165c62cce2cSAndrey Vagin 				break;
1166c62cce2cSAndrey Vagin 
1167c62cce2cSAndrey Vagin 			err = open_related_ns(&net->ns, get_net_ns);
1168c62cce2cSAndrey Vagin 			break;
11690768e170SArnd Bergmann 		case SIOCGSTAMP_OLD:
11700768e170SArnd Bergmann 		case SIOCGSTAMPNS_OLD:
1171c7cbdbf2SArnd Bergmann 			if (!sock->ops->gettstamp) {
1172c7cbdbf2SArnd Bergmann 				err = -ENOIOCTLCMD;
1173c7cbdbf2SArnd Bergmann 				break;
1174c7cbdbf2SArnd Bergmann 			}
1175c7cbdbf2SArnd Bergmann 			err = sock->ops->gettstamp(sock, argp,
11760768e170SArnd Bergmann 						   cmd == SIOCGSTAMP_OLD,
11770768e170SArnd Bergmann 						   !IS_ENABLED(CONFIG_64BIT));
117860747828SGustavo A. R. Silva 			break;
11790768e170SArnd Bergmann 		case SIOCGSTAMP_NEW:
11800768e170SArnd Bergmann 		case SIOCGSTAMPNS_NEW:
11810768e170SArnd Bergmann 			if (!sock->ops->gettstamp) {
11820768e170SArnd Bergmann 				err = -ENOIOCTLCMD;
11830768e170SArnd Bergmann 				break;
11840768e170SArnd Bergmann 			}
11850768e170SArnd Bergmann 			err = sock->ops->gettstamp(sock, argp,
11860768e170SArnd Bergmann 						   cmd == SIOCGSTAMP_NEW,
11870768e170SArnd Bergmann 						   false);
1188c7cbdbf2SArnd Bergmann 			break;
11891da177e4SLinus Torvalds 		default:
119063ff03abSJohannes Berg 			err = sock_do_ioctl(net, sock, cmd, arg);
11911da177e4SLinus Torvalds 			break;
11921da177e4SLinus Torvalds 		}
11931da177e4SLinus Torvalds 	return err;
11941da177e4SLinus Torvalds }
11951da177e4SLinus Torvalds 
11968a3c245cSPedro Tammela /**
11978a3c245cSPedro Tammela  *	sock_create_lite - creates a socket
11988a3c245cSPedro Tammela  *	@family: protocol family (AF_INET, ...)
11998a3c245cSPedro Tammela  *	@type: communication type (SOCK_STREAM, ...)
12008a3c245cSPedro Tammela  *	@protocol: protocol (0, ...)
12018a3c245cSPedro Tammela  *	@res: new socket
12028a3c245cSPedro Tammela  *
12038a3c245cSPedro Tammela  *	Creates a new socket and assigns it to @res, passing through LSM.
12048a3c245cSPedro Tammela  *	The new socket initialization is not complete, see kernel_accept().
12058a3c245cSPedro Tammela  *	Returns 0 or an error. On failure @res is set to %NULL.
12068a3c245cSPedro Tammela  *	This function internally uses GFP_KERNEL.
12078a3c245cSPedro Tammela  */
12088a3c245cSPedro Tammela 
12091da177e4SLinus Torvalds int sock_create_lite(int family, int type, int protocol, struct socket **res)
12101da177e4SLinus Torvalds {
12111da177e4SLinus Torvalds 	int err;
12121da177e4SLinus Torvalds 	struct socket *sock = NULL;
12131da177e4SLinus Torvalds 
12141da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, 1);
12151da177e4SLinus Torvalds 	if (err)
12161da177e4SLinus Torvalds 		goto out;
12171da177e4SLinus Torvalds 
12181da177e4SLinus Torvalds 	sock = sock_alloc();
12191da177e4SLinus Torvalds 	if (!sock) {
12201da177e4SLinus Torvalds 		err = -ENOMEM;
12211da177e4SLinus Torvalds 		goto out;
12221da177e4SLinus Torvalds 	}
12231da177e4SLinus Torvalds 
12241da177e4SLinus Torvalds 	sock->type = type;
12257420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, 1);
12267420ed23SVenkat Yekkirala 	if (err)
12277420ed23SVenkat Yekkirala 		goto out_release;
12287420ed23SVenkat Yekkirala 
12291da177e4SLinus Torvalds out:
12301da177e4SLinus Torvalds 	*res = sock;
12311da177e4SLinus Torvalds 	return err;
12327420ed23SVenkat Yekkirala out_release:
12337420ed23SVenkat Yekkirala 	sock_release(sock);
12347420ed23SVenkat Yekkirala 	sock = NULL;
12357420ed23SVenkat Yekkirala 	goto out;
12361da177e4SLinus Torvalds }
1237c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_lite);
12381da177e4SLinus Torvalds 
12391da177e4SLinus Torvalds /* No kernel lock held - perfect */
1240ade994f4SAl Viro static __poll_t sock_poll(struct file *file, poll_table *wait)
12411da177e4SLinus Torvalds {
12423cafb376SChristoph Hellwig 	struct socket *sock = file->private_data;
1243a331de3bSChristoph Hellwig 	__poll_t events = poll_requested_events(wait), flag = 0;
12441da177e4SLinus Torvalds 
1245e88958e6SChristoph Hellwig 	if (!sock->ops->poll)
1246e88958e6SChristoph Hellwig 		return 0;
1247f641f13bSChristoph Hellwig 
1248a331de3bSChristoph Hellwig 	if (sk_can_busy_loop(sock->sk)) {
1249f641f13bSChristoph Hellwig 		/* poll once if requested by the syscall */
1250a331de3bSChristoph Hellwig 		if (events & POLL_BUSY_LOOP)
1251f641f13bSChristoph Hellwig 			sk_busy_loop(sock->sk, 1);
1252a331de3bSChristoph Hellwig 
1253a331de3bSChristoph Hellwig 		/* if this socket can poll_ll, tell the system call */
1254a331de3bSChristoph Hellwig 		flag = POLL_BUSY_LOOP;
1255a331de3bSChristoph Hellwig 	}
1256a331de3bSChristoph Hellwig 
1257a331de3bSChristoph Hellwig 	return sock->ops->poll(file, sock, wait) | flag;
12581da177e4SLinus Torvalds }
12591da177e4SLinus Torvalds 
12601da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma)
12611da177e4SLinus Torvalds {
1262b69aee04SEric Dumazet 	struct socket *sock = file->private_data;
12631da177e4SLinus Torvalds 
12641da177e4SLinus Torvalds 	return sock->ops->mmap(file, sock, vma);
12651da177e4SLinus Torvalds }
12661da177e4SLinus Torvalds 
126720380731SArnaldo Carvalho de Melo static int sock_close(struct inode *inode, struct file *filp)
12681da177e4SLinus Torvalds {
12696d8c50dcSCong Wang 	__sock_release(SOCKET_I(inode), inode);
12701da177e4SLinus Torvalds 	return 0;
12711da177e4SLinus Torvalds }
12721da177e4SLinus Torvalds 
12731da177e4SLinus Torvalds /*
12741da177e4SLinus Torvalds  *	Update the socket async list
12751da177e4SLinus Torvalds  *
12761da177e4SLinus Torvalds  *	Fasync_list locking strategy.
12771da177e4SLinus Torvalds  *
12781da177e4SLinus Torvalds  *	1. fasync_list is modified only under process context socket lock
12791da177e4SLinus Torvalds  *	   i.e. under semaphore.
12801da177e4SLinus Torvalds  *	2. fasync_list is used under read_lock(&sk->sk_callback_lock)
1281989a2979SEric Dumazet  *	   or under socket lock
12821da177e4SLinus Torvalds  */
12831da177e4SLinus Torvalds 
12841da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on)
12851da177e4SLinus Torvalds {
1286989a2979SEric Dumazet 	struct socket *sock = filp->private_data;
1287989a2979SEric Dumazet 	struct sock *sk = sock->sk;
1288333f7909SAl Viro 	struct socket_wq *wq = &sock->wq;
12891da177e4SLinus Torvalds 
1290989a2979SEric Dumazet 	if (sk == NULL)
12911da177e4SLinus Torvalds 		return -EINVAL;
12921da177e4SLinus Torvalds 
12931da177e4SLinus Torvalds 	lock_sock(sk);
1294eaefd110SEric Dumazet 	fasync_helper(fd, filp, on, &wq->fasync_list);
12951da177e4SLinus Torvalds 
1296eaefd110SEric Dumazet 	if (!wq->fasync_list)
1297bcdce719SEric Dumazet 		sock_reset_flag(sk, SOCK_FASYNC);
1298989a2979SEric Dumazet 	else
1299989a2979SEric Dumazet 		sock_set_flag(sk, SOCK_FASYNC);
13001da177e4SLinus Torvalds 
1301989a2979SEric Dumazet 	release_sock(sk);
13021da177e4SLinus Torvalds 	return 0;
13031da177e4SLinus Torvalds }
13041da177e4SLinus Torvalds 
1305ceb5d58bSEric Dumazet /* This function may be called only under rcu_lock */
13061da177e4SLinus Torvalds 
1307ceb5d58bSEric Dumazet int sock_wake_async(struct socket_wq *wq, int how, int band)
13081da177e4SLinus Torvalds {
1309ceb5d58bSEric Dumazet 	if (!wq || !wq->fasync_list)
1310ceb5d58bSEric Dumazet 		return -1;
131143815482SEric Dumazet 
131289bddce5SStephen Hemminger 	switch (how) {
13138d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_WAITD:
1314ceb5d58bSEric Dumazet 		if (test_bit(SOCKWQ_ASYNC_WAITDATA, &wq->flags))
13151da177e4SLinus Torvalds 			break;
13161da177e4SLinus Torvalds 		goto call_kill;
13178d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_SPACE:
1318ceb5d58bSEric Dumazet 		if (!test_and_clear_bit(SOCKWQ_ASYNC_NOSPACE, &wq->flags))
13191da177e4SLinus Torvalds 			break;
13201da177e4SLinus Torvalds 		/* fall through */
13218d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_IO:
13221da177e4SLinus Torvalds call_kill:
132343815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGIO, band);
13241da177e4SLinus Torvalds 		break;
13258d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_URG:
132643815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGURG, band);
13271da177e4SLinus Torvalds 	}
1328ceb5d58bSEric Dumazet 
13291da177e4SLinus Torvalds 	return 0;
13301da177e4SLinus Torvalds }
1331c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_wake_async);
13321da177e4SLinus Torvalds 
13338a3c245cSPedro Tammela /**
13348a3c245cSPedro Tammela  *	__sock_create - creates a socket
13358a3c245cSPedro Tammela  *	@net: net namespace
13368a3c245cSPedro Tammela  *	@family: protocol family (AF_INET, ...)
13378a3c245cSPedro Tammela  *	@type: communication type (SOCK_STREAM, ...)
13388a3c245cSPedro Tammela  *	@protocol: protocol (0, ...)
13398a3c245cSPedro Tammela  *	@res: new socket
13408a3c245cSPedro Tammela  *	@kern: boolean for kernel space sockets
13418a3c245cSPedro Tammela  *
13428a3c245cSPedro Tammela  *	Creates a new socket and assigns it to @res, passing through LSM.
13438a3c245cSPedro Tammela  *	Returns 0 or an error. On failure @res is set to %NULL. @kern must
13448a3c245cSPedro Tammela  *	be set to true if the socket resides in kernel space.
13458a3c245cSPedro Tammela  *	This function internally uses GFP_KERNEL.
13468a3c245cSPedro Tammela  */
13478a3c245cSPedro Tammela 
1348721db93aSPavel Emelyanov int __sock_create(struct net *net, int family, int type, int protocol,
134989bddce5SStephen Hemminger 			 struct socket **res, int kern)
13501da177e4SLinus Torvalds {
13511da177e4SLinus Torvalds 	int err;
13521da177e4SLinus Torvalds 	struct socket *sock;
135355737fdaSStephen Hemminger 	const struct net_proto_family *pf;
13541da177e4SLinus Torvalds 
13551da177e4SLinus Torvalds 	/*
13561da177e4SLinus Torvalds 	 *      Check protocol is in range
13571da177e4SLinus Torvalds 	 */
13581da177e4SLinus Torvalds 	if (family < 0 || family >= NPROTO)
13591da177e4SLinus Torvalds 		return -EAFNOSUPPORT;
13601da177e4SLinus Torvalds 	if (type < 0 || type >= SOCK_MAX)
13611da177e4SLinus Torvalds 		return -EINVAL;
13621da177e4SLinus Torvalds 
13631da177e4SLinus Torvalds 	/* Compatibility.
13641da177e4SLinus Torvalds 
13651da177e4SLinus Torvalds 	   This uglymoron is moved from INET layer to here to avoid
13661da177e4SLinus Torvalds 	   deadlock in module load.
13671da177e4SLinus Torvalds 	 */
13681da177e4SLinus Torvalds 	if (family == PF_INET && type == SOCK_PACKET) {
1369f3c98690Sliping.zhang 		pr_info_once("%s uses obsolete (PF_INET,SOCK_PACKET)\n",
137089bddce5SStephen Hemminger 			     current->comm);
13711da177e4SLinus Torvalds 		family = PF_PACKET;
13721da177e4SLinus Torvalds 	}
13731da177e4SLinus Torvalds 
13741da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, kern);
13751da177e4SLinus Torvalds 	if (err)
13761da177e4SLinus Torvalds 		return err;
13771da177e4SLinus Torvalds 
137855737fdaSStephen Hemminger 	/*
137955737fdaSStephen Hemminger 	 *	Allocate the socket and allow the family to set things up. if
138055737fdaSStephen Hemminger 	 *	the protocol is 0, the family is instructed to select an appropriate
138155737fdaSStephen Hemminger 	 *	default.
138255737fdaSStephen Hemminger 	 */
138355737fdaSStephen Hemminger 	sock = sock_alloc();
138455737fdaSStephen Hemminger 	if (!sock) {
1385e87cc472SJoe Perches 		net_warn_ratelimited("socket: no more sockets\n");
138655737fdaSStephen Hemminger 		return -ENFILE;	/* Not exactly a match, but its the
138755737fdaSStephen Hemminger 				   closest posix thing */
138855737fdaSStephen Hemminger 	}
138955737fdaSStephen Hemminger 
139055737fdaSStephen Hemminger 	sock->type = type;
139155737fdaSStephen Hemminger 
139295a5afcaSJohannes Berg #ifdef CONFIG_MODULES
13931da177e4SLinus Torvalds 	/* Attempt to load a protocol module if the find failed.
13941da177e4SLinus Torvalds 	 *
13951da177e4SLinus Torvalds 	 * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
13961da177e4SLinus Torvalds 	 * requested real, full-featured networking support upon configuration.
13971da177e4SLinus Torvalds 	 * Otherwise module support will break!
13981da177e4SLinus Torvalds 	 */
1399190683a9SEric Dumazet 	if (rcu_access_pointer(net_families[family]) == NULL)
14001da177e4SLinus Torvalds 		request_module("net-pf-%d", family);
14011da177e4SLinus Torvalds #endif
14021da177e4SLinus Torvalds 
140355737fdaSStephen Hemminger 	rcu_read_lock();
140455737fdaSStephen Hemminger 	pf = rcu_dereference(net_families[family]);
14051da177e4SLinus Torvalds 	err = -EAFNOSUPPORT;
140655737fdaSStephen Hemminger 	if (!pf)
140755737fdaSStephen Hemminger 		goto out_release;
14081da177e4SLinus Torvalds 
14091da177e4SLinus Torvalds 	/*
14101da177e4SLinus Torvalds 	 * We will call the ->create function, that possibly is in a loadable
14111da177e4SLinus Torvalds 	 * module, so we have to bump that loadable module refcnt first.
14121da177e4SLinus Torvalds 	 */
141355737fdaSStephen Hemminger 	if (!try_module_get(pf->owner))
14141da177e4SLinus Torvalds 		goto out_release;
14151da177e4SLinus Torvalds 
141655737fdaSStephen Hemminger 	/* Now protected by module ref count */
141755737fdaSStephen Hemminger 	rcu_read_unlock();
141855737fdaSStephen Hemminger 
14193f378b68SEric Paris 	err = pf->create(net, sock, protocol, kern);
142055737fdaSStephen Hemminger 	if (err < 0)
14211da177e4SLinus Torvalds 		goto out_module_put;
1422a79af59eSFrank Filz 
14231da177e4SLinus Torvalds 	/*
14241da177e4SLinus Torvalds 	 * Now to bump the refcnt of the [loadable] module that owns this
14251da177e4SLinus Torvalds 	 * socket at sock_release time we decrement its refcnt.
14261da177e4SLinus Torvalds 	 */
142755737fdaSStephen Hemminger 	if (!try_module_get(sock->ops->owner))
142855737fdaSStephen Hemminger 		goto out_module_busy;
142955737fdaSStephen Hemminger 
14301da177e4SLinus Torvalds 	/*
14311da177e4SLinus Torvalds 	 * Now that we're done with the ->create function, the [loadable]
14321da177e4SLinus Torvalds 	 * module can have its refcnt decremented
14331da177e4SLinus Torvalds 	 */
143455737fdaSStephen Hemminger 	module_put(pf->owner);
14357420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, kern);
14367420ed23SVenkat Yekkirala 	if (err)
14373b185525SHerbert Xu 		goto out_sock_release;
143855737fdaSStephen Hemminger 	*res = sock;
14391da177e4SLinus Torvalds 
144055737fdaSStephen Hemminger 	return 0;
144155737fdaSStephen Hemminger 
144255737fdaSStephen Hemminger out_module_busy:
144355737fdaSStephen Hemminger 	err = -EAFNOSUPPORT;
14441da177e4SLinus Torvalds out_module_put:
144555737fdaSStephen Hemminger 	sock->ops = NULL;
144655737fdaSStephen Hemminger 	module_put(pf->owner);
144755737fdaSStephen Hemminger out_sock_release:
14481da177e4SLinus Torvalds 	sock_release(sock);
144955737fdaSStephen Hemminger 	return err;
145055737fdaSStephen Hemminger 
145155737fdaSStephen Hemminger out_release:
145255737fdaSStephen Hemminger 	rcu_read_unlock();
145355737fdaSStephen Hemminger 	goto out_sock_release;
14541da177e4SLinus Torvalds }
1455721db93aSPavel Emelyanov EXPORT_SYMBOL(__sock_create);
14561da177e4SLinus Torvalds 
14578a3c245cSPedro Tammela /**
14588a3c245cSPedro Tammela  *	sock_create - creates a socket
14598a3c245cSPedro Tammela  *	@family: protocol family (AF_INET, ...)
14608a3c245cSPedro Tammela  *	@type: communication type (SOCK_STREAM, ...)
14618a3c245cSPedro Tammela  *	@protocol: protocol (0, ...)
14628a3c245cSPedro Tammela  *	@res: new socket
14638a3c245cSPedro Tammela  *
14648a3c245cSPedro Tammela  *	A wrapper around __sock_create().
14658a3c245cSPedro Tammela  *	Returns 0 or an error. This function internally uses GFP_KERNEL.
14668a3c245cSPedro Tammela  */
14678a3c245cSPedro Tammela 
14681da177e4SLinus Torvalds int sock_create(int family, int type, int protocol, struct socket **res)
14691da177e4SLinus Torvalds {
14701b8d7ae4SEric W. Biederman 	return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
14711da177e4SLinus Torvalds }
1472c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create);
14731da177e4SLinus Torvalds 
14748a3c245cSPedro Tammela /**
14758a3c245cSPedro Tammela  *	sock_create_kern - creates a socket (kernel space)
14768a3c245cSPedro Tammela  *	@net: net namespace
14778a3c245cSPedro Tammela  *	@family: protocol family (AF_INET, ...)
14788a3c245cSPedro Tammela  *	@type: communication type (SOCK_STREAM, ...)
14798a3c245cSPedro Tammela  *	@protocol: protocol (0, ...)
14808a3c245cSPedro Tammela  *	@res: new socket
14818a3c245cSPedro Tammela  *
14828a3c245cSPedro Tammela  *	A wrapper around __sock_create().
14838a3c245cSPedro Tammela  *	Returns 0 or an error. This function internally uses GFP_KERNEL.
14848a3c245cSPedro Tammela  */
14858a3c245cSPedro Tammela 
1486eeb1bd5cSEric W. Biederman int sock_create_kern(struct net *net, int family, int type, int protocol, struct socket **res)
14871da177e4SLinus Torvalds {
1488eeb1bd5cSEric W. Biederman 	return __sock_create(net, family, type, protocol, res, 1);
14891da177e4SLinus Torvalds }
1490c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_kern);
14911da177e4SLinus Torvalds 
14929d6a15c3SDominik Brodowski int __sys_socket(int family, int type, int protocol)
14931da177e4SLinus Torvalds {
14941da177e4SLinus Torvalds 	int retval;
14951da177e4SLinus Torvalds 	struct socket *sock;
1496a677a039SUlrich Drepper 	int flags;
1497a677a039SUlrich Drepper 
1498e38b36f3SUlrich Drepper 	/* Check the SOCK_* constants for consistency.  */
1499e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
1500e38b36f3SUlrich Drepper 	BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
1501e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);
1502e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);
1503e38b36f3SUlrich Drepper 
1504a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
150577d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1506a677a039SUlrich Drepper 		return -EINVAL;
1507a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
15081da177e4SLinus Torvalds 
1509aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1510aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1511aaca0bdcSUlrich Drepper 
15121da177e4SLinus Torvalds 	retval = sock_create(family, type, protocol, &sock);
15131da177e4SLinus Torvalds 	if (retval < 0)
15141da177e4SLinus Torvalds 		return retval;
15151da177e4SLinus Torvalds 
15168e1611e2SAl Viro 	return sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
15171da177e4SLinus Torvalds }
15181da177e4SLinus Torvalds 
15199d6a15c3SDominik Brodowski SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
15209d6a15c3SDominik Brodowski {
15219d6a15c3SDominik Brodowski 	return __sys_socket(family, type, protocol);
15229d6a15c3SDominik Brodowski }
15239d6a15c3SDominik Brodowski 
15241da177e4SLinus Torvalds /*
15251da177e4SLinus Torvalds  *	Create a pair of connected sockets.
15261da177e4SLinus Torvalds  */
15271da177e4SLinus Torvalds 
15286debc8d8SDominik Brodowski int __sys_socketpair(int family, int type, int protocol, int __user *usockvec)
15291da177e4SLinus Torvalds {
15301da177e4SLinus Torvalds 	struct socket *sock1, *sock2;
15311da177e4SLinus Torvalds 	int fd1, fd2, err;
1532db349509SAl Viro 	struct file *newfile1, *newfile2;
1533a677a039SUlrich Drepper 	int flags;
1534a677a039SUlrich Drepper 
1535a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
153677d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1537a677a039SUlrich Drepper 		return -EINVAL;
1538a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
15391da177e4SLinus Torvalds 
1540aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1541aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1542aaca0bdcSUlrich Drepper 
15431da177e4SLinus Torvalds 	/*
1544016a266bSAl Viro 	 * reserve descriptors and make sure we won't fail
1545016a266bSAl Viro 	 * to return them to userland.
1546016a266bSAl Viro 	 */
1547016a266bSAl Viro 	fd1 = get_unused_fd_flags(flags);
1548016a266bSAl Viro 	if (unlikely(fd1 < 0))
1549016a266bSAl Viro 		return fd1;
1550016a266bSAl Viro 
1551016a266bSAl Viro 	fd2 = get_unused_fd_flags(flags);
1552016a266bSAl Viro 	if (unlikely(fd2 < 0)) {
1553016a266bSAl Viro 		put_unused_fd(fd1);
1554016a266bSAl Viro 		return fd2;
1555016a266bSAl Viro 	}
1556016a266bSAl Viro 
1557016a266bSAl Viro 	err = put_user(fd1, &usockvec[0]);
1558016a266bSAl Viro 	if (err)
1559016a266bSAl Viro 		goto out;
1560016a266bSAl Viro 
1561016a266bSAl Viro 	err = put_user(fd2, &usockvec[1]);
1562016a266bSAl Viro 	if (err)
1563016a266bSAl Viro 		goto out;
1564016a266bSAl Viro 
1565016a266bSAl Viro 	/*
15661da177e4SLinus Torvalds 	 * Obtain the first socket and check if the underlying protocol
15671da177e4SLinus Torvalds 	 * supports the socketpair call.
15681da177e4SLinus Torvalds 	 */
15691da177e4SLinus Torvalds 
15701da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock1);
1571016a266bSAl Viro 	if (unlikely(err < 0))
15721da177e4SLinus Torvalds 		goto out;
15731da177e4SLinus Torvalds 
15741da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock2);
1575016a266bSAl Viro 	if (unlikely(err < 0)) {
1576016a266bSAl Viro 		sock_release(sock1);
1577016a266bSAl Viro 		goto out;
1578bf3c23d1SDavid S. Miller 	}
1579d73aa286SYann Droneaud 
1580d47cd945SDavid Herrmann 	err = security_socket_socketpair(sock1, sock2);
1581d47cd945SDavid Herrmann 	if (unlikely(err)) {
1582d47cd945SDavid Herrmann 		sock_release(sock2);
1583d47cd945SDavid Herrmann 		sock_release(sock1);
1584d47cd945SDavid Herrmann 		goto out;
1585d47cd945SDavid Herrmann 	}
1586d47cd945SDavid Herrmann 
1587016a266bSAl Viro 	err = sock1->ops->socketpair(sock1, sock2);
1588016a266bSAl Viro 	if (unlikely(err < 0)) {
1589016a266bSAl Viro 		sock_release(sock2);
1590016a266bSAl Viro 		sock_release(sock1);
1591016a266bSAl Viro 		goto out;
159228407630SAl Viro 	}
159328407630SAl Viro 
1594aab174f0SLinus Torvalds 	newfile1 = sock_alloc_file(sock1, flags, NULL);
1595b5ffe634SViresh Kumar 	if (IS_ERR(newfile1)) {
159628407630SAl Viro 		err = PTR_ERR(newfile1);
1597016a266bSAl Viro 		sock_release(sock2);
1598016a266bSAl Viro 		goto out;
159928407630SAl Viro 	}
160028407630SAl Viro 
1601aab174f0SLinus Torvalds 	newfile2 = sock_alloc_file(sock2, flags, NULL);
160228407630SAl Viro 	if (IS_ERR(newfile2)) {
160328407630SAl Viro 		err = PTR_ERR(newfile2);
1604016a266bSAl Viro 		fput(newfile1);
1605016a266bSAl Viro 		goto out;
1606db349509SAl Viro 	}
1607db349509SAl Viro 
1608157cf649SAl Viro 	audit_fd_pair(fd1, fd2);
1609d73aa286SYann Droneaud 
1610db349509SAl Viro 	fd_install(fd1, newfile1);
1611db349509SAl Viro 	fd_install(fd2, newfile2);
16121da177e4SLinus Torvalds 	return 0;
16131da177e4SLinus Torvalds 
16141da177e4SLinus Torvalds out:
1615016a266bSAl Viro 	put_unused_fd(fd2);
1616016a266bSAl Viro 	put_unused_fd(fd1);
16171da177e4SLinus Torvalds 	return err;
16181da177e4SLinus Torvalds }
16191da177e4SLinus Torvalds 
16206debc8d8SDominik Brodowski SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
16216debc8d8SDominik Brodowski 		int __user *, usockvec)
16226debc8d8SDominik Brodowski {
16236debc8d8SDominik Brodowski 	return __sys_socketpair(family, type, protocol, usockvec);
16246debc8d8SDominik Brodowski }
16256debc8d8SDominik Brodowski 
16261da177e4SLinus Torvalds /*
16271da177e4SLinus Torvalds  *	Bind a name to a socket. Nothing much to do here since it's
16281da177e4SLinus Torvalds  *	the protocol's responsibility to handle the local address.
16291da177e4SLinus Torvalds  *
16301da177e4SLinus Torvalds  *	We move the socket address to kernel space before we call
16311da177e4SLinus Torvalds  *	the protocol layer (having also checked the address is ok).
16321da177e4SLinus Torvalds  */
16331da177e4SLinus Torvalds 
1634a87d35d8SDominik Brodowski int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)
16351da177e4SLinus Torvalds {
16361da177e4SLinus Torvalds 	struct socket *sock;
1637230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16386cb153caSBenjamin LaHaise 	int err, fput_needed;
16391da177e4SLinus Torvalds 
164089bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
164189bddce5SStephen Hemminger 	if (sock) {
164243db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(umyaddr, addrlen, &address);
1643068b88ccSJakub Sitnicki 		if (!err) {
164489bddce5SStephen Hemminger 			err = security_socket_bind(sock,
1645230b1839SYOSHIFUJI Hideaki 						   (struct sockaddr *)&address,
164689bddce5SStephen Hemminger 						   addrlen);
16476cb153caSBenjamin LaHaise 			if (!err)
16486cb153caSBenjamin LaHaise 				err = sock->ops->bind(sock,
164989bddce5SStephen Hemminger 						      (struct sockaddr *)
1650230b1839SYOSHIFUJI Hideaki 						      &address, addrlen);
16511da177e4SLinus Torvalds 		}
16526cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
16531da177e4SLinus Torvalds 	}
16541da177e4SLinus Torvalds 	return err;
16551da177e4SLinus Torvalds }
16561da177e4SLinus Torvalds 
1657a87d35d8SDominik Brodowski SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
1658a87d35d8SDominik Brodowski {
1659a87d35d8SDominik Brodowski 	return __sys_bind(fd, umyaddr, addrlen);
1660a87d35d8SDominik Brodowski }
1661a87d35d8SDominik Brodowski 
16621da177e4SLinus Torvalds /*
16631da177e4SLinus Torvalds  *	Perform a listen. Basically, we allow the protocol to do anything
16641da177e4SLinus Torvalds  *	necessary for a listen, and if that works, we mark the socket as
16651da177e4SLinus Torvalds  *	ready for listening.
16661da177e4SLinus Torvalds  */
16671da177e4SLinus Torvalds 
166825e290eeSDominik Brodowski int __sys_listen(int fd, int backlog)
16691da177e4SLinus Torvalds {
16701da177e4SLinus Torvalds 	struct socket *sock;
16716cb153caSBenjamin LaHaise 	int err, fput_needed;
1672b8e1f9b5SPavel Emelyanov 	int somaxconn;
16731da177e4SLinus Torvalds 
167489bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
167589bddce5SStephen Hemminger 	if (sock) {
16768efa6e93SPavel Emelyanov 		somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
167795c96174SEric Dumazet 		if ((unsigned int)backlog > somaxconn)
1678b8e1f9b5SPavel Emelyanov 			backlog = somaxconn;
16791da177e4SLinus Torvalds 
16801da177e4SLinus Torvalds 		err = security_socket_listen(sock, backlog);
16816cb153caSBenjamin LaHaise 		if (!err)
16821da177e4SLinus Torvalds 			err = sock->ops->listen(sock, backlog);
16836cb153caSBenjamin LaHaise 
16846cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
16851da177e4SLinus Torvalds 	}
16861da177e4SLinus Torvalds 	return err;
16871da177e4SLinus Torvalds }
16881da177e4SLinus Torvalds 
168925e290eeSDominik Brodowski SYSCALL_DEFINE2(listen, int, fd, int, backlog)
169025e290eeSDominik Brodowski {
169125e290eeSDominik Brodowski 	return __sys_listen(fd, backlog);
169225e290eeSDominik Brodowski }
169325e290eeSDominik Brodowski 
1694de2ea4b6SJens Axboe int __sys_accept4_file(struct file *file, unsigned file_flags,
1695de2ea4b6SJens Axboe 		       struct sockaddr __user *upeer_sockaddr,
16964541e805SDominik Brodowski 		       int __user *upeer_addrlen, int flags)
16971da177e4SLinus Torvalds {
16981da177e4SLinus Torvalds 	struct socket *sock, *newsock;
169939d8c1b6SDavid S. Miller 	struct file *newfile;
1700de2ea4b6SJens Axboe 	int err, len, newfd;
1701230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
17021da177e4SLinus Torvalds 
170377d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1704aaca0bdcSUlrich Drepper 		return -EINVAL;
1705aaca0bdcSUlrich Drepper 
1706aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1707aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1708aaca0bdcSUlrich Drepper 
1709de2ea4b6SJens Axboe 	sock = sock_from_file(file, &err);
17101da177e4SLinus Torvalds 	if (!sock)
17111da177e4SLinus Torvalds 		goto out;
17121da177e4SLinus Torvalds 
17131da177e4SLinus Torvalds 	err = -ENFILE;
1714c6d409cfSEric Dumazet 	newsock = sock_alloc();
1715c6d409cfSEric Dumazet 	if (!newsock)
1716de2ea4b6SJens Axboe 		goto out;
17171da177e4SLinus Torvalds 
17181da177e4SLinus Torvalds 	newsock->type = sock->type;
17191da177e4SLinus Torvalds 	newsock->ops = sock->ops;
17201da177e4SLinus Torvalds 
17211da177e4SLinus Torvalds 	/*
17221da177e4SLinus Torvalds 	 * We don't need try_module_get here, as the listening socket (sock)
17231da177e4SLinus Torvalds 	 * has the protocol module (sock->ops->owner) held.
17241da177e4SLinus Torvalds 	 */
17251da177e4SLinus Torvalds 	__module_get(newsock->ops->owner);
17261da177e4SLinus Torvalds 
172728407630SAl Viro 	newfd = get_unused_fd_flags(flags);
172839d8c1b6SDavid S. Miller 	if (unlikely(newfd < 0)) {
172939d8c1b6SDavid S. Miller 		err = newfd;
17309a1875e6SDavid S. Miller 		sock_release(newsock);
1731de2ea4b6SJens Axboe 		goto out;
173239d8c1b6SDavid S. Miller 	}
1733aab174f0SLinus Torvalds 	newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name);
1734b5ffe634SViresh Kumar 	if (IS_ERR(newfile)) {
173528407630SAl Viro 		err = PTR_ERR(newfile);
173628407630SAl Viro 		put_unused_fd(newfd);
1737de2ea4b6SJens Axboe 		goto out;
173828407630SAl Viro 	}
173939d8c1b6SDavid S. Miller 
1740a79af59eSFrank Filz 	err = security_socket_accept(sock, newsock);
1741a79af59eSFrank Filz 	if (err)
174239d8c1b6SDavid S. Miller 		goto out_fd;
1743a79af59eSFrank Filz 
1744de2ea4b6SJens Axboe 	err = sock->ops->accept(sock, newsock, sock->file->f_flags | file_flags,
1745de2ea4b6SJens Axboe 					false);
17461da177e4SLinus Torvalds 	if (err < 0)
174739d8c1b6SDavid S. Miller 		goto out_fd;
17481da177e4SLinus Torvalds 
17491da177e4SLinus Torvalds 	if (upeer_sockaddr) {
17509b2c45d4SDenys Vlasenko 		len = newsock->ops->getname(newsock,
17519b2c45d4SDenys Vlasenko 					(struct sockaddr *)&address, 2);
17529b2c45d4SDenys Vlasenko 		if (len < 0) {
17531da177e4SLinus Torvalds 			err = -ECONNABORTED;
175439d8c1b6SDavid S. Miller 			goto out_fd;
17551da177e4SLinus Torvalds 		}
175643db362dSMaciej Żenczykowski 		err = move_addr_to_user(&address,
1757230b1839SYOSHIFUJI Hideaki 					len, upeer_sockaddr, upeer_addrlen);
17581da177e4SLinus Torvalds 		if (err < 0)
175939d8c1b6SDavid S. Miller 			goto out_fd;
17601da177e4SLinus Torvalds 	}
17611da177e4SLinus Torvalds 
17621da177e4SLinus Torvalds 	/* File flags are not inherited via accept() unlike another OSes. */
17631da177e4SLinus Torvalds 
176439d8c1b6SDavid S. Miller 	fd_install(newfd, newfile);
176539d8c1b6SDavid S. Miller 	err = newfd;
17661da177e4SLinus Torvalds out:
17671da177e4SLinus Torvalds 	return err;
176839d8c1b6SDavid S. Miller out_fd:
17699606a216SDavid S. Miller 	fput(newfile);
177039d8c1b6SDavid S. Miller 	put_unused_fd(newfd);
1771de2ea4b6SJens Axboe 	goto out;
1772de2ea4b6SJens Axboe 
1773de2ea4b6SJens Axboe }
1774de2ea4b6SJens Axboe 
1775de2ea4b6SJens Axboe /*
1776de2ea4b6SJens Axboe  *	For accept, we attempt to create a new socket, set up the link
1777de2ea4b6SJens Axboe  *	with the client, wake up the client, then return the new
1778de2ea4b6SJens Axboe  *	connected fd. We collect the address of the connector in kernel
1779de2ea4b6SJens Axboe  *	space and move it to user at the very end. This is unclean because
1780de2ea4b6SJens Axboe  *	we open the socket then return an error.
1781de2ea4b6SJens Axboe  *
1782de2ea4b6SJens Axboe  *	1003.1g adds the ability to recvmsg() to query connection pending
1783de2ea4b6SJens Axboe  *	status to recvmsg. We need to add that support in a way thats
1784de2ea4b6SJens Axboe  *	clean when we restructure accept also.
1785de2ea4b6SJens Axboe  */
1786de2ea4b6SJens Axboe 
1787de2ea4b6SJens Axboe int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
1788de2ea4b6SJens Axboe 		  int __user *upeer_addrlen, int flags)
1789de2ea4b6SJens Axboe {
1790de2ea4b6SJens Axboe 	int ret = -EBADF;
1791de2ea4b6SJens Axboe 	struct fd f;
1792de2ea4b6SJens Axboe 
1793de2ea4b6SJens Axboe 	f = fdget(fd);
1794de2ea4b6SJens Axboe 	if (f.file) {
1795de2ea4b6SJens Axboe 		ret = __sys_accept4_file(f.file, 0, upeer_sockaddr,
1796de2ea4b6SJens Axboe 						upeer_addrlen, flags);
1797de2ea4b6SJens Axboe 		if (f.flags)
1798de2ea4b6SJens Axboe 			fput(f.file);
1799de2ea4b6SJens Axboe 	}
1800de2ea4b6SJens Axboe 
1801de2ea4b6SJens Axboe 	return ret;
18021da177e4SLinus Torvalds }
18031da177e4SLinus Torvalds 
18044541e805SDominik Brodowski SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
18054541e805SDominik Brodowski 		int __user *, upeer_addrlen, int, flags)
18064541e805SDominik Brodowski {
18074541e805SDominik Brodowski 	return __sys_accept4(fd, upeer_sockaddr, upeer_addrlen, flags);
18084541e805SDominik Brodowski }
18094541e805SDominik Brodowski 
181020f37034SHeiko Carstens SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,
181120f37034SHeiko Carstens 		int __user *, upeer_addrlen)
1812aaca0bdcSUlrich Drepper {
18134541e805SDominik Brodowski 	return __sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0);
1814aaca0bdcSUlrich Drepper }
1815aaca0bdcSUlrich Drepper 
18161da177e4SLinus Torvalds /*
18171da177e4SLinus Torvalds  *	Attempt to connect to a socket with the server address.  The address
18181da177e4SLinus Torvalds  *	is in user space so we verify it is OK and move it to kernel space.
18191da177e4SLinus Torvalds  *
18201da177e4SLinus Torvalds  *	For 1003.1g we need to add clean support for a bind to AF_UNSPEC to
18211da177e4SLinus Torvalds  *	break bindings
18221da177e4SLinus Torvalds  *
18231da177e4SLinus Torvalds  *	NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and
18241da177e4SLinus Torvalds  *	other SEQPACKET protocols that take time to connect() as it doesn't
18251da177e4SLinus Torvalds  *	include the -EINPROGRESS status for such sockets.
18261da177e4SLinus Torvalds  */
18271da177e4SLinus Torvalds 
1828bd3ded31SJens Axboe int __sys_connect_file(struct file *file, struct sockaddr __user *uservaddr,
1829bd3ded31SJens Axboe 		       int addrlen, int file_flags)
18301da177e4SLinus Torvalds {
18311da177e4SLinus Torvalds 	struct socket *sock;
1832230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
1833bd3ded31SJens Axboe 	int err;
18341da177e4SLinus Torvalds 
1835bd3ded31SJens Axboe 	sock = sock_from_file(file, &err);
18361da177e4SLinus Torvalds 	if (!sock)
18371da177e4SLinus Torvalds 		goto out;
183843db362dSMaciej Żenczykowski 	err = move_addr_to_kernel(uservaddr, addrlen, &address);
18391da177e4SLinus Torvalds 	if (err < 0)
1840bd3ded31SJens Axboe 		goto out;
18411da177e4SLinus Torvalds 
184289bddce5SStephen Hemminger 	err =
1843230b1839SYOSHIFUJI Hideaki 	    security_socket_connect(sock, (struct sockaddr *)&address, addrlen);
18441da177e4SLinus Torvalds 	if (err)
1845bd3ded31SJens Axboe 		goto out;
18461da177e4SLinus Torvalds 
1847230b1839SYOSHIFUJI Hideaki 	err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,
1848bd3ded31SJens Axboe 				 sock->file->f_flags | file_flags);
18491da177e4SLinus Torvalds out:
18501da177e4SLinus Torvalds 	return err;
18511da177e4SLinus Torvalds }
18521da177e4SLinus Torvalds 
1853bd3ded31SJens Axboe int __sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen)
1854bd3ded31SJens Axboe {
1855bd3ded31SJens Axboe 	int ret = -EBADF;
1856bd3ded31SJens Axboe 	struct fd f;
1857bd3ded31SJens Axboe 
1858bd3ded31SJens Axboe 	f = fdget(fd);
1859bd3ded31SJens Axboe 	if (f.file) {
1860bd3ded31SJens Axboe 		ret = __sys_connect_file(f.file, uservaddr, addrlen, 0);
1861bd3ded31SJens Axboe 		if (f.flags)
1862bd3ded31SJens Axboe 			fput(f.file);
1863bd3ded31SJens Axboe 	}
1864bd3ded31SJens Axboe 
1865bd3ded31SJens Axboe 	return ret;
1866bd3ded31SJens Axboe }
1867bd3ded31SJens Axboe 
18681387c2c2SDominik Brodowski SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
18691387c2c2SDominik Brodowski 		int, addrlen)
18701387c2c2SDominik Brodowski {
18711387c2c2SDominik Brodowski 	return __sys_connect(fd, uservaddr, addrlen);
18721387c2c2SDominik Brodowski }
18731387c2c2SDominik Brodowski 
18741da177e4SLinus Torvalds /*
18751da177e4SLinus Torvalds  *	Get the local address ('name') of a socket object. Move the obtained
18761da177e4SLinus Torvalds  *	name to user space.
18771da177e4SLinus Torvalds  */
18781da177e4SLinus Torvalds 
18798882a107SDominik Brodowski int __sys_getsockname(int fd, struct sockaddr __user *usockaddr,
18808882a107SDominik Brodowski 		      int __user *usockaddr_len)
18811da177e4SLinus Torvalds {
18821da177e4SLinus Torvalds 	struct socket *sock;
1883230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
18849b2c45d4SDenys Vlasenko 	int err, fput_needed;
18851da177e4SLinus Torvalds 
18866cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
18871da177e4SLinus Torvalds 	if (!sock)
18881da177e4SLinus Torvalds 		goto out;
18891da177e4SLinus Torvalds 
18901da177e4SLinus Torvalds 	err = security_socket_getsockname(sock);
18911da177e4SLinus Torvalds 	if (err)
18921da177e4SLinus Torvalds 		goto out_put;
18931da177e4SLinus Torvalds 
18949b2c45d4SDenys Vlasenko 	err = sock->ops->getname(sock, (struct sockaddr *)&address, 0);
18959b2c45d4SDenys Vlasenko 	if (err < 0)
18961da177e4SLinus Torvalds 		goto out_put;
18979b2c45d4SDenys Vlasenko         /* "err" is actually length in this case */
18989b2c45d4SDenys Vlasenko 	err = move_addr_to_user(&address, err, usockaddr, usockaddr_len);
18991da177e4SLinus Torvalds 
19001da177e4SLinus Torvalds out_put:
19016cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
19021da177e4SLinus Torvalds out:
19031da177e4SLinus Torvalds 	return err;
19041da177e4SLinus Torvalds }
19051da177e4SLinus Torvalds 
19068882a107SDominik Brodowski SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
19078882a107SDominik Brodowski 		int __user *, usockaddr_len)
19088882a107SDominik Brodowski {
19098882a107SDominik Brodowski 	return __sys_getsockname(fd, usockaddr, usockaddr_len);
19108882a107SDominik Brodowski }
19118882a107SDominik Brodowski 
19121da177e4SLinus Torvalds /*
19131da177e4SLinus Torvalds  *	Get the remote address ('name') of a socket object. Move the obtained
19141da177e4SLinus Torvalds  *	name to user space.
19151da177e4SLinus Torvalds  */
19161da177e4SLinus Torvalds 
1917b21c8f83SDominik Brodowski int __sys_getpeername(int fd, struct sockaddr __user *usockaddr,
1918b21c8f83SDominik Brodowski 		      int __user *usockaddr_len)
19191da177e4SLinus Torvalds {
19201da177e4SLinus Torvalds 	struct socket *sock;
1921230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
19229b2c45d4SDenys Vlasenko 	int err, fput_needed;
19231da177e4SLinus Torvalds 
192489bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
192589bddce5SStephen Hemminger 	if (sock != NULL) {
19261da177e4SLinus Torvalds 		err = security_socket_getpeername(sock);
19271da177e4SLinus Torvalds 		if (err) {
19286cb153caSBenjamin LaHaise 			fput_light(sock->file, fput_needed);
19291da177e4SLinus Torvalds 			return err;
19301da177e4SLinus Torvalds 		}
19311da177e4SLinus Torvalds 
19329b2c45d4SDenys Vlasenko 		err = sock->ops->getname(sock, (struct sockaddr *)&address, 1);
19339b2c45d4SDenys Vlasenko 		if (err >= 0)
19349b2c45d4SDenys Vlasenko 			/* "err" is actually length in this case */
19359b2c45d4SDenys Vlasenko 			err = move_addr_to_user(&address, err, usockaddr,
193689bddce5SStephen Hemminger 						usockaddr_len);
19376cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
19381da177e4SLinus Torvalds 	}
19391da177e4SLinus Torvalds 	return err;
19401da177e4SLinus Torvalds }
19411da177e4SLinus Torvalds 
1942b21c8f83SDominik Brodowski SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
1943b21c8f83SDominik Brodowski 		int __user *, usockaddr_len)
1944b21c8f83SDominik Brodowski {
1945b21c8f83SDominik Brodowski 	return __sys_getpeername(fd, usockaddr, usockaddr_len);
1946b21c8f83SDominik Brodowski }
1947b21c8f83SDominik Brodowski 
19481da177e4SLinus Torvalds /*
19491da177e4SLinus Torvalds  *	Send a datagram to a given address. We move the address into kernel
19501da177e4SLinus Torvalds  *	space and check the user space data area is readable before invoking
19511da177e4SLinus Torvalds  *	the protocol.
19521da177e4SLinus Torvalds  */
1953211b634bSDominik Brodowski int __sys_sendto(int fd, void __user *buff, size_t len, unsigned int flags,
1954211b634bSDominik Brodowski 		 struct sockaddr __user *addr,  int addr_len)
19551da177e4SLinus Torvalds {
19561da177e4SLinus Torvalds 	struct socket *sock;
1957230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
19581da177e4SLinus Torvalds 	int err;
19591da177e4SLinus Torvalds 	struct msghdr msg;
19601da177e4SLinus Torvalds 	struct iovec iov;
19616cb153caSBenjamin LaHaise 	int fput_needed;
19621da177e4SLinus Torvalds 
1963602bd0e9SAl Viro 	err = import_single_range(WRITE, buff, len, &iov, &msg.msg_iter);
1964602bd0e9SAl Viro 	if (unlikely(err))
1965602bd0e9SAl Viro 		return err;
1966de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1967de0fa95cSPavel Emelyanov 	if (!sock)
19684387ff75SDavid S. Miller 		goto out;
19696cb153caSBenjamin LaHaise 
19701da177e4SLinus Torvalds 	msg.msg_name = NULL;
19711da177e4SLinus Torvalds 	msg.msg_control = NULL;
19721da177e4SLinus Torvalds 	msg.msg_controllen = 0;
19731da177e4SLinus Torvalds 	msg.msg_namelen = 0;
19746cb153caSBenjamin LaHaise 	if (addr) {
197543db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(addr, addr_len, &address);
19761da177e4SLinus Torvalds 		if (err < 0)
19771da177e4SLinus Torvalds 			goto out_put;
1978230b1839SYOSHIFUJI Hideaki 		msg.msg_name = (struct sockaddr *)&address;
19791da177e4SLinus Torvalds 		msg.msg_namelen = addr_len;
19801da177e4SLinus Torvalds 	}
19811da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
19821da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
19831da177e4SLinus Torvalds 	msg.msg_flags = flags;
1984d8725c86SAl Viro 	err = sock_sendmsg(sock, &msg);
19851da177e4SLinus Torvalds 
19861da177e4SLinus Torvalds out_put:
1987de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
19884387ff75SDavid S. Miller out:
19891da177e4SLinus Torvalds 	return err;
19901da177e4SLinus Torvalds }
19911da177e4SLinus Torvalds 
1992211b634bSDominik Brodowski SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
1993211b634bSDominik Brodowski 		unsigned int, flags, struct sockaddr __user *, addr,
1994211b634bSDominik Brodowski 		int, addr_len)
1995211b634bSDominik Brodowski {
1996211b634bSDominik Brodowski 	return __sys_sendto(fd, buff, len, flags, addr, addr_len);
1997211b634bSDominik Brodowski }
1998211b634bSDominik Brodowski 
19991da177e4SLinus Torvalds /*
20001da177e4SLinus Torvalds  *	Send a datagram down a socket.
20011da177e4SLinus Torvalds  */
20021da177e4SLinus Torvalds 
20033e0fa65fSHeiko Carstens SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len,
200495c96174SEric Dumazet 		unsigned int, flags)
20051da177e4SLinus Torvalds {
2006211b634bSDominik Brodowski 	return __sys_sendto(fd, buff, len, flags, NULL, 0);
20071da177e4SLinus Torvalds }
20081da177e4SLinus Torvalds 
20091da177e4SLinus Torvalds /*
20101da177e4SLinus Torvalds  *	Receive a frame from the socket and optionally record the address of the
20111da177e4SLinus Torvalds  *	sender. We verify the buffers are writable and if needed move the
20121da177e4SLinus Torvalds  *	sender address from kernel to user space.
20131da177e4SLinus Torvalds  */
20147a09e1ebSDominik Brodowski int __sys_recvfrom(int fd, void __user *ubuf, size_t size, unsigned int flags,
20157a09e1ebSDominik Brodowski 		   struct sockaddr __user *addr, int __user *addr_len)
20161da177e4SLinus Torvalds {
20171da177e4SLinus Torvalds 	struct socket *sock;
20181da177e4SLinus Torvalds 	struct iovec iov;
20191da177e4SLinus Torvalds 	struct msghdr msg;
2020230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
20211da177e4SLinus Torvalds 	int err, err2;
20226cb153caSBenjamin LaHaise 	int fput_needed;
20231da177e4SLinus Torvalds 
2024602bd0e9SAl Viro 	err = import_single_range(READ, ubuf, size, &iov, &msg.msg_iter);
2025602bd0e9SAl Viro 	if (unlikely(err))
2026602bd0e9SAl Viro 		return err;
2027de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
20281da177e4SLinus Torvalds 	if (!sock)
2029de0fa95cSPavel Emelyanov 		goto out;
20301da177e4SLinus Torvalds 
20311da177e4SLinus Torvalds 	msg.msg_control = NULL;
20321da177e4SLinus Torvalds 	msg.msg_controllen = 0;
2033f3d33426SHannes Frederic Sowa 	/* Save some cycles and don't copy the address if not needed */
2034f3d33426SHannes Frederic Sowa 	msg.msg_name = addr ? (struct sockaddr *)&address : NULL;
2035f3d33426SHannes Frederic Sowa 	/* We assume all kernel code knows the size of sockaddr_storage */
2036f3d33426SHannes Frederic Sowa 	msg.msg_namelen = 0;
2037130ed5d1Stadeusz.struk@intel.com 	msg.msg_iocb = NULL;
20389f138fa6SAlexander Potapenko 	msg.msg_flags = 0;
20391da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
20401da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
20412da62906SAl Viro 	err = sock_recvmsg(sock, &msg, flags);
20421da177e4SLinus Torvalds 
204389bddce5SStephen Hemminger 	if (err >= 0 && addr != NULL) {
204443db362dSMaciej Żenczykowski 		err2 = move_addr_to_user(&address,
2045230b1839SYOSHIFUJI Hideaki 					 msg.msg_namelen, addr, addr_len);
20461da177e4SLinus Torvalds 		if (err2 < 0)
20471da177e4SLinus Torvalds 			err = err2;
20481da177e4SLinus Torvalds 	}
2049de0fa95cSPavel Emelyanov 
2050de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
20514387ff75SDavid S. Miller out:
20521da177e4SLinus Torvalds 	return err;
20531da177e4SLinus Torvalds }
20541da177e4SLinus Torvalds 
20557a09e1ebSDominik Brodowski SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
20567a09e1ebSDominik Brodowski 		unsigned int, flags, struct sockaddr __user *, addr,
20577a09e1ebSDominik Brodowski 		int __user *, addr_len)
20587a09e1ebSDominik Brodowski {
20597a09e1ebSDominik Brodowski 	return __sys_recvfrom(fd, ubuf, size, flags, addr, addr_len);
20607a09e1ebSDominik Brodowski }
20617a09e1ebSDominik Brodowski 
20621da177e4SLinus Torvalds /*
20631da177e4SLinus Torvalds  *	Receive a datagram from a socket.
20641da177e4SLinus Torvalds  */
20651da177e4SLinus Torvalds 
2066b7c0ddf5SJan Glauber SYSCALL_DEFINE4(recv, int, fd, void __user *, ubuf, size_t, size,
2067b7c0ddf5SJan Glauber 		unsigned int, flags)
20681da177e4SLinus Torvalds {
20697a09e1ebSDominik Brodowski 	return __sys_recvfrom(fd, ubuf, size, flags, NULL, NULL);
20701da177e4SLinus Torvalds }
20711da177e4SLinus Torvalds 
20721da177e4SLinus Torvalds /*
20731da177e4SLinus Torvalds  *	Set a socket option. Because we don't know the option lengths we have
20741da177e4SLinus Torvalds  *	to pass the user mode parameter for the protocols to sort out.
20751da177e4SLinus Torvalds  */
20761da177e4SLinus Torvalds 
2077cc36dca0SDominik Brodowski static int __sys_setsockopt(int fd, int level, int optname,
2078cc36dca0SDominik Brodowski 			    char __user *optval, int optlen)
20791da177e4SLinus Torvalds {
20800d01da6aSStanislav Fomichev 	mm_segment_t oldfs = get_fs();
20810d01da6aSStanislav Fomichev 	char *kernel_optval = NULL;
20826cb153caSBenjamin LaHaise 	int err, fput_needed;
20831da177e4SLinus Torvalds 	struct socket *sock;
20841da177e4SLinus Torvalds 
20851da177e4SLinus Torvalds 	if (optlen < 0)
20861da177e4SLinus Torvalds 		return -EINVAL;
20871da177e4SLinus Torvalds 
208889bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
208989bddce5SStephen Hemminger 	if (sock != NULL) {
20901da177e4SLinus Torvalds 		err = security_socket_setsockopt(sock, level, optname);
20916cb153caSBenjamin LaHaise 		if (err)
20926cb153caSBenjamin LaHaise 			goto out_put;
20931da177e4SLinus Torvalds 
20940d01da6aSStanislav Fomichev 		err = BPF_CGROUP_RUN_PROG_SETSOCKOPT(sock->sk, &level,
20950d01da6aSStanislav Fomichev 						     &optname, optval, &optlen,
20960d01da6aSStanislav Fomichev 						     &kernel_optval);
20970d01da6aSStanislav Fomichev 
20980d01da6aSStanislav Fomichev 		if (err < 0) {
20990d01da6aSStanislav Fomichev 			goto out_put;
21000d01da6aSStanislav Fomichev 		} else if (err > 0) {
21010d01da6aSStanislav Fomichev 			err = 0;
21020d01da6aSStanislav Fomichev 			goto out_put;
21030d01da6aSStanislav Fomichev 		}
21040d01da6aSStanislav Fomichev 
21050d01da6aSStanislav Fomichev 		if (kernel_optval) {
21060d01da6aSStanislav Fomichev 			set_fs(KERNEL_DS);
21070d01da6aSStanislav Fomichev 			optval = (char __user __force *)kernel_optval;
21080d01da6aSStanislav Fomichev 		}
21090d01da6aSStanislav Fomichev 
21101da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
211189bddce5SStephen Hemminger 			err =
211289bddce5SStephen Hemminger 			    sock_setsockopt(sock, level, optname, optval,
211389bddce5SStephen Hemminger 					    optlen);
21141da177e4SLinus Torvalds 		else
211589bddce5SStephen Hemminger 			err =
211689bddce5SStephen Hemminger 			    sock->ops->setsockopt(sock, level, optname, optval,
211789bddce5SStephen Hemminger 						  optlen);
21180d01da6aSStanislav Fomichev 
21190d01da6aSStanislav Fomichev 		if (kernel_optval) {
21200d01da6aSStanislav Fomichev 			set_fs(oldfs);
21210d01da6aSStanislav Fomichev 			kfree(kernel_optval);
21220d01da6aSStanislav Fomichev 		}
21236cb153caSBenjamin LaHaise out_put:
21246cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
21251da177e4SLinus Torvalds 	}
21261da177e4SLinus Torvalds 	return err;
21271da177e4SLinus Torvalds }
21281da177e4SLinus Torvalds 
2129cc36dca0SDominik Brodowski SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
2130cc36dca0SDominik Brodowski 		char __user *, optval, int, optlen)
2131cc36dca0SDominik Brodowski {
2132cc36dca0SDominik Brodowski 	return __sys_setsockopt(fd, level, optname, optval, optlen);
2133cc36dca0SDominik Brodowski }
2134cc36dca0SDominik Brodowski 
21351da177e4SLinus Torvalds /*
21361da177e4SLinus Torvalds  *	Get a socket option. Because we don't know the option lengths we have
21371da177e4SLinus Torvalds  *	to pass a user mode parameter for the protocols to sort out.
21381da177e4SLinus Torvalds  */
21391da177e4SLinus Torvalds 
214013a2d70eSDominik Brodowski static int __sys_getsockopt(int fd, int level, int optname,
214113a2d70eSDominik Brodowski 			    char __user *optval, int __user *optlen)
21421da177e4SLinus Torvalds {
21436cb153caSBenjamin LaHaise 	int err, fput_needed;
21441da177e4SLinus Torvalds 	struct socket *sock;
21450d01da6aSStanislav Fomichev 	int max_optlen;
21461da177e4SLinus Torvalds 
214789bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
214889bddce5SStephen Hemminger 	if (sock != NULL) {
21496cb153caSBenjamin LaHaise 		err = security_socket_getsockopt(sock, level, optname);
21506cb153caSBenjamin LaHaise 		if (err)
21516cb153caSBenjamin LaHaise 			goto out_put;
21521da177e4SLinus Torvalds 
21530d01da6aSStanislav Fomichev 		max_optlen = BPF_CGROUP_GETSOCKOPT_MAX_OPTLEN(optlen);
21540d01da6aSStanislav Fomichev 
21551da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
215689bddce5SStephen Hemminger 			err =
215789bddce5SStephen Hemminger 			    sock_getsockopt(sock, level, optname, optval,
215889bddce5SStephen Hemminger 					    optlen);
21591da177e4SLinus Torvalds 		else
216089bddce5SStephen Hemminger 			err =
216189bddce5SStephen Hemminger 			    sock->ops->getsockopt(sock, level, optname, optval,
216289bddce5SStephen Hemminger 						  optlen);
21630d01da6aSStanislav Fomichev 
21640d01da6aSStanislav Fomichev 		err = BPF_CGROUP_RUN_PROG_GETSOCKOPT(sock->sk, level, optname,
21650d01da6aSStanislav Fomichev 						     optval, optlen,
21660d01da6aSStanislav Fomichev 						     max_optlen, err);
21676cb153caSBenjamin LaHaise out_put:
21686cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
21691da177e4SLinus Torvalds 	}
21701da177e4SLinus Torvalds 	return err;
21711da177e4SLinus Torvalds }
21721da177e4SLinus Torvalds 
217313a2d70eSDominik Brodowski SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
217413a2d70eSDominik Brodowski 		char __user *, optval, int __user *, optlen)
217513a2d70eSDominik Brodowski {
217613a2d70eSDominik Brodowski 	return __sys_getsockopt(fd, level, optname, optval, optlen);
217713a2d70eSDominik Brodowski }
217813a2d70eSDominik Brodowski 
21791da177e4SLinus Torvalds /*
21801da177e4SLinus Torvalds  *	Shutdown a socket.
21811da177e4SLinus Torvalds  */
21821da177e4SLinus Torvalds 
2183005a1aeaSDominik Brodowski int __sys_shutdown(int fd, int how)
21841da177e4SLinus Torvalds {
21856cb153caSBenjamin LaHaise 	int err, fput_needed;
21861da177e4SLinus Torvalds 	struct socket *sock;
21871da177e4SLinus Torvalds 
218889bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
218989bddce5SStephen Hemminger 	if (sock != NULL) {
21901da177e4SLinus Torvalds 		err = security_socket_shutdown(sock, how);
21916cb153caSBenjamin LaHaise 		if (!err)
21921da177e4SLinus Torvalds 			err = sock->ops->shutdown(sock, how);
21936cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
21941da177e4SLinus Torvalds 	}
21951da177e4SLinus Torvalds 	return err;
21961da177e4SLinus Torvalds }
21971da177e4SLinus Torvalds 
2198005a1aeaSDominik Brodowski SYSCALL_DEFINE2(shutdown, int, fd, int, how)
2199005a1aeaSDominik Brodowski {
2200005a1aeaSDominik Brodowski 	return __sys_shutdown(fd, how);
2201005a1aeaSDominik Brodowski }
2202005a1aeaSDominik Brodowski 
22031da177e4SLinus Torvalds /* A couple of helpful macros for getting the address of the 32/64 bit
22041da177e4SLinus Torvalds  * fields which are the same type (int / unsigned) on our platforms.
22051da177e4SLinus Torvalds  */
22061da177e4SLinus Torvalds #define COMPAT_MSG(msg, member)	((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member)
22071da177e4SLinus Torvalds #define COMPAT_NAMELEN(msg)	COMPAT_MSG(msg, msg_namelen)
22081da177e4SLinus Torvalds #define COMPAT_FLAGS(msg)	COMPAT_MSG(msg, msg_flags)
22091da177e4SLinus Torvalds 
2210c71d8ebeSTetsuo Handa struct used_address {
2211c71d8ebeSTetsuo Handa 	struct sockaddr_storage name;
2212c71d8ebeSTetsuo Handa 	unsigned int name_len;
2213c71d8ebeSTetsuo Handa };
2214c71d8ebeSTetsuo Handa 
2215da184284SAl Viro static int copy_msghdr_from_user(struct msghdr *kmsg,
221608adb7daSAl Viro 				 struct user_msghdr __user *umsg,
221708adb7daSAl Viro 				 struct sockaddr __user **save_addr,
221808adb7daSAl Viro 				 struct iovec **iov)
22191661bf36SDan Carpenter {
2220ffb07550SAl Viro 	struct user_msghdr msg;
222108adb7daSAl Viro 	ssize_t err;
222208adb7daSAl Viro 
2223ffb07550SAl Viro 	if (copy_from_user(&msg, umsg, sizeof(*umsg)))
22241661bf36SDan Carpenter 		return -EFAULT;
2225dbb490b9SMatthew Leach 
2226864d9664SPaolo Abeni 	kmsg->msg_control = (void __force *)msg.msg_control;
2227ffb07550SAl Viro 	kmsg->msg_controllen = msg.msg_controllen;
2228ffb07550SAl Viro 	kmsg->msg_flags = msg.msg_flags;
2229ffb07550SAl Viro 
2230ffb07550SAl Viro 	kmsg->msg_namelen = msg.msg_namelen;
2231ffb07550SAl Viro 	if (!msg.msg_name)
22326a2a2b3aSAni Sinha 		kmsg->msg_namelen = 0;
22336a2a2b3aSAni Sinha 
2234dbb490b9SMatthew Leach 	if (kmsg->msg_namelen < 0)
2235dbb490b9SMatthew Leach 		return -EINVAL;
2236dbb490b9SMatthew Leach 
22371661bf36SDan Carpenter 	if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
2238db31c55aSDan Carpenter 		kmsg->msg_namelen = sizeof(struct sockaddr_storage);
223908adb7daSAl Viro 
224008adb7daSAl Viro 	if (save_addr)
2241ffb07550SAl Viro 		*save_addr = msg.msg_name;
224208adb7daSAl Viro 
2243ffb07550SAl Viro 	if (msg.msg_name && kmsg->msg_namelen) {
224408adb7daSAl Viro 		if (!save_addr) {
2245864d9664SPaolo Abeni 			err = move_addr_to_kernel(msg.msg_name,
2246864d9664SPaolo Abeni 						  kmsg->msg_namelen,
224708adb7daSAl Viro 						  kmsg->msg_name);
224808adb7daSAl Viro 			if (err < 0)
224908adb7daSAl Viro 				return err;
225008adb7daSAl Viro 		}
225108adb7daSAl Viro 	} else {
225208adb7daSAl Viro 		kmsg->msg_name = NULL;
225308adb7daSAl Viro 		kmsg->msg_namelen = 0;
225408adb7daSAl Viro 	}
225508adb7daSAl Viro 
2256ffb07550SAl Viro 	if (msg.msg_iovlen > UIO_MAXIOV)
225708adb7daSAl Viro 		return -EMSGSIZE;
225808adb7daSAl Viro 
22590345f931Stadeusz.struk@intel.com 	kmsg->msg_iocb = NULL;
22600345f931Stadeusz.struk@intel.com 
226187e5e6daSJens Axboe 	err = import_iovec(save_addr ? READ : WRITE,
2262ffb07550SAl Viro 			    msg.msg_iov, msg.msg_iovlen,
2263da184284SAl Viro 			    UIO_FASTIOV, iov, &kmsg->msg_iter);
226487e5e6daSJens Axboe 	return err < 0 ? err : 0;
22651661bf36SDan Carpenter }
22661661bf36SDan Carpenter 
22674257c8caSJens Axboe static int ____sys_sendmsg(struct socket *sock, struct msghdr *msg_sys,
22684257c8caSJens Axboe 			   unsigned int flags, struct used_address *used_address,
226928a94d8fSTom Herbert 			   unsigned int allowed_msghdr_flags)
22701da177e4SLinus Torvalds {
2271b9d717a7SAlex Williamson 	unsigned char ctl[sizeof(struct cmsghdr) + 20]
2272846cc123SAmit Kushwaha 				__aligned(sizeof(__kernel_size_t));
2273b9d717a7SAlex Williamson 	/* 20 is size of ipv6_pktinfo */
22741da177e4SLinus Torvalds 	unsigned char *ctl_buf = ctl;
2275d8725c86SAl Viro 	int ctl_len;
227608adb7daSAl Viro 	ssize_t err;
22771da177e4SLinus Torvalds 
22781da177e4SLinus Torvalds 	err = -ENOBUFS;
22791da177e4SLinus Torvalds 
2280228e548eSAnton Blanchard 	if (msg_sys->msg_controllen > INT_MAX)
22814257c8caSJens Axboe 		goto out;
228228a94d8fSTom Herbert 	flags |= (msg_sys->msg_flags & allowed_msghdr_flags);
2283228e548eSAnton Blanchard 	ctl_len = msg_sys->msg_controllen;
22841da177e4SLinus Torvalds 	if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
228589bddce5SStephen Hemminger 		err =
2286228e548eSAnton Blanchard 		    cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl,
228789bddce5SStephen Hemminger 						     sizeof(ctl));
22881da177e4SLinus Torvalds 		if (err)
22894257c8caSJens Axboe 			goto out;
2290228e548eSAnton Blanchard 		ctl_buf = msg_sys->msg_control;
2291228e548eSAnton Blanchard 		ctl_len = msg_sys->msg_controllen;
22921da177e4SLinus Torvalds 	} else if (ctl_len) {
2293ac4340fcSDavid S. Miller 		BUILD_BUG_ON(sizeof(struct cmsghdr) !=
2294ac4340fcSDavid S. Miller 			     CMSG_ALIGN(sizeof(struct cmsghdr)));
229589bddce5SStephen Hemminger 		if (ctl_len > sizeof(ctl)) {
22961da177e4SLinus Torvalds 			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
22971da177e4SLinus Torvalds 			if (ctl_buf == NULL)
22984257c8caSJens Axboe 				goto out;
22991da177e4SLinus Torvalds 		}
23001da177e4SLinus Torvalds 		err = -EFAULT;
23011da177e4SLinus Torvalds 		/*
2302228e548eSAnton Blanchard 		 * Careful! Before this, msg_sys->msg_control contains a user pointer.
23031da177e4SLinus Torvalds 		 * Afterwards, it will be a kernel pointer. Thus the compiler-assisted
23041da177e4SLinus Torvalds 		 * checking falls down on this.
23051da177e4SLinus Torvalds 		 */
2306fb8621bbSNamhyung Kim 		if (copy_from_user(ctl_buf,
2307228e548eSAnton Blanchard 				   (void __user __force *)msg_sys->msg_control,
230889bddce5SStephen Hemminger 				   ctl_len))
23091da177e4SLinus Torvalds 			goto out_freectl;
2310228e548eSAnton Blanchard 		msg_sys->msg_control = ctl_buf;
23111da177e4SLinus Torvalds 	}
2312228e548eSAnton Blanchard 	msg_sys->msg_flags = flags;
23131da177e4SLinus Torvalds 
23141da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
2315228e548eSAnton Blanchard 		msg_sys->msg_flags |= MSG_DONTWAIT;
2316c71d8ebeSTetsuo Handa 	/*
2317c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and current destination address is same as
2318c71d8ebeSTetsuo Handa 	 * previously succeeded address, omit asking LSM's decision.
2319c71d8ebeSTetsuo Handa 	 * used_address->name_len is initialized to UINT_MAX so that the first
2320c71d8ebeSTetsuo Handa 	 * destination address never matches.
2321c71d8ebeSTetsuo Handa 	 */
2322bc909d9dSMathieu Desnoyers 	if (used_address && msg_sys->msg_name &&
2323bc909d9dSMathieu Desnoyers 	    used_address->name_len == msg_sys->msg_namelen &&
2324bc909d9dSMathieu Desnoyers 	    !memcmp(&used_address->name, msg_sys->msg_name,
2325c71d8ebeSTetsuo Handa 		    used_address->name_len)) {
2326d8725c86SAl Viro 		err = sock_sendmsg_nosec(sock, msg_sys);
2327c71d8ebeSTetsuo Handa 		goto out_freectl;
2328c71d8ebeSTetsuo Handa 	}
2329d8725c86SAl Viro 	err = sock_sendmsg(sock, msg_sys);
2330c71d8ebeSTetsuo Handa 	/*
2331c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and sending to current destination address was
2332c71d8ebeSTetsuo Handa 	 * successful, remember it.
2333c71d8ebeSTetsuo Handa 	 */
2334c71d8ebeSTetsuo Handa 	if (used_address && err >= 0) {
2335c71d8ebeSTetsuo Handa 		used_address->name_len = msg_sys->msg_namelen;
2336bc909d9dSMathieu Desnoyers 		if (msg_sys->msg_name)
2337bc909d9dSMathieu Desnoyers 			memcpy(&used_address->name, msg_sys->msg_name,
2338c71d8ebeSTetsuo Handa 			       used_address->name_len);
2339c71d8ebeSTetsuo Handa 	}
23401da177e4SLinus Torvalds 
23411da177e4SLinus Torvalds out_freectl:
23421da177e4SLinus Torvalds 	if (ctl_buf != ctl)
23431da177e4SLinus Torvalds 		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
23444257c8caSJens Axboe out:
23454257c8caSJens Axboe 	return err;
23464257c8caSJens Axboe }
23474257c8caSJens Axboe 
23484257c8caSJens Axboe static int sendmsg_copy_msghdr(struct msghdr *msg,
23494257c8caSJens Axboe 			       struct user_msghdr __user *umsg, unsigned flags,
23504257c8caSJens Axboe 			       struct iovec **iov)
23514257c8caSJens Axboe {
23524257c8caSJens Axboe 	int err;
23534257c8caSJens Axboe 
23544257c8caSJens Axboe 	if (flags & MSG_CMSG_COMPAT) {
23554257c8caSJens Axboe 		struct compat_msghdr __user *msg_compat;
23564257c8caSJens Axboe 
23574257c8caSJens Axboe 		msg_compat = (struct compat_msghdr __user *) umsg;
23584257c8caSJens Axboe 		err = get_compat_msghdr(msg, msg_compat, NULL, iov);
23594257c8caSJens Axboe 	} else {
23604257c8caSJens Axboe 		err = copy_msghdr_from_user(msg, umsg, NULL, iov);
23614257c8caSJens Axboe 	}
23624257c8caSJens Axboe 	if (err < 0)
23634257c8caSJens Axboe 		return err;
23644257c8caSJens Axboe 
23654257c8caSJens Axboe 	return 0;
23664257c8caSJens Axboe }
23674257c8caSJens Axboe 
23684257c8caSJens Axboe static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
23694257c8caSJens Axboe 			 struct msghdr *msg_sys, unsigned int flags,
23704257c8caSJens Axboe 			 struct used_address *used_address,
23714257c8caSJens Axboe 			 unsigned int allowed_msghdr_flags)
23724257c8caSJens Axboe {
23734257c8caSJens Axboe 	struct sockaddr_storage address;
23744257c8caSJens Axboe 	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
23754257c8caSJens Axboe 	ssize_t err;
23764257c8caSJens Axboe 
23774257c8caSJens Axboe 	msg_sys->msg_name = &address;
23784257c8caSJens Axboe 
23794257c8caSJens Axboe 	err = sendmsg_copy_msghdr(msg_sys, msg, flags, &iov);
23804257c8caSJens Axboe 	if (err < 0)
23814257c8caSJens Axboe 		return err;
23824257c8caSJens Axboe 
23834257c8caSJens Axboe 	err = ____sys_sendmsg(sock, msg_sys, flags, used_address,
23844257c8caSJens Axboe 				allowed_msghdr_flags);
2385a74e9106SEric Dumazet 	kfree(iov);
2386228e548eSAnton Blanchard 	return err;
2387228e548eSAnton Blanchard }
2388228e548eSAnton Blanchard 
2389228e548eSAnton Blanchard /*
2390228e548eSAnton Blanchard  *	BSD sendmsg interface
2391228e548eSAnton Blanchard  */
23920fa03c62SJens Axboe long __sys_sendmsg_sock(struct socket *sock, struct user_msghdr __user *msg,
23930fa03c62SJens Axboe 			unsigned int flags)
23940fa03c62SJens Axboe {
23950fa03c62SJens Axboe 	struct msghdr msg_sys;
23960fa03c62SJens Axboe 
23970fa03c62SJens Axboe 	return ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL, 0);
23980fa03c62SJens Axboe }
2399228e548eSAnton Blanchard 
2400e1834a32SDominik Brodowski long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned int flags,
2401e1834a32SDominik Brodowski 		   bool forbid_cmsg_compat)
2402228e548eSAnton Blanchard {
2403228e548eSAnton Blanchard 	int fput_needed, err;
2404228e548eSAnton Blanchard 	struct msghdr msg_sys;
24051be374a0SAndy Lutomirski 	struct socket *sock;
2406228e548eSAnton Blanchard 
2407e1834a32SDominik Brodowski 	if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT))
2408e1834a32SDominik Brodowski 		return -EINVAL;
2409e1834a32SDominik Brodowski 
24101be374a0SAndy Lutomirski 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2411228e548eSAnton Blanchard 	if (!sock)
2412228e548eSAnton Blanchard 		goto out;
2413228e548eSAnton Blanchard 
241428a94d8fSTom Herbert 	err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL, 0);
2415228e548eSAnton Blanchard 
24166cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
24171da177e4SLinus Torvalds out:
24181da177e4SLinus Torvalds 	return err;
24191da177e4SLinus Torvalds }
24201da177e4SLinus Torvalds 
2421666547ffSAl Viro SYSCALL_DEFINE3(sendmsg, int, fd, struct user_msghdr __user *, msg, unsigned int, flags)
2422a7526eb5SAndy Lutomirski {
2423e1834a32SDominik Brodowski 	return __sys_sendmsg(fd, msg, flags, true);
2424a7526eb5SAndy Lutomirski }
2425a7526eb5SAndy Lutomirski 
2426228e548eSAnton Blanchard /*
2427228e548eSAnton Blanchard  *	Linux sendmmsg interface
2428228e548eSAnton Blanchard  */
2429228e548eSAnton Blanchard 
2430228e548eSAnton Blanchard int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2431e1834a32SDominik Brodowski 		   unsigned int flags, bool forbid_cmsg_compat)
2432228e548eSAnton Blanchard {
2433228e548eSAnton Blanchard 	int fput_needed, err, datagrams;
2434228e548eSAnton Blanchard 	struct socket *sock;
2435228e548eSAnton Blanchard 	struct mmsghdr __user *entry;
2436228e548eSAnton Blanchard 	struct compat_mmsghdr __user *compat_entry;
2437228e548eSAnton Blanchard 	struct msghdr msg_sys;
2438c71d8ebeSTetsuo Handa 	struct used_address used_address;
2439f092276dSTom Herbert 	unsigned int oflags = flags;
2440228e548eSAnton Blanchard 
2441e1834a32SDominik Brodowski 	if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT))
2442e1834a32SDominik Brodowski 		return -EINVAL;
2443e1834a32SDominik Brodowski 
244498382f41SAnton Blanchard 	if (vlen > UIO_MAXIOV)
244598382f41SAnton Blanchard 		vlen = UIO_MAXIOV;
2446228e548eSAnton Blanchard 
2447228e548eSAnton Blanchard 	datagrams = 0;
2448228e548eSAnton Blanchard 
2449228e548eSAnton Blanchard 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2450228e548eSAnton Blanchard 	if (!sock)
2451228e548eSAnton Blanchard 		return err;
2452228e548eSAnton Blanchard 
2453c71d8ebeSTetsuo Handa 	used_address.name_len = UINT_MAX;
2454228e548eSAnton Blanchard 	entry = mmsg;
2455228e548eSAnton Blanchard 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2456728ffb86SAnton Blanchard 	err = 0;
2457f092276dSTom Herbert 	flags |= MSG_BATCH;
2458228e548eSAnton Blanchard 
2459228e548eSAnton Blanchard 	while (datagrams < vlen) {
2460f092276dSTom Herbert 		if (datagrams == vlen - 1)
2461f092276dSTom Herbert 			flags = oflags;
2462f092276dSTom Herbert 
2463228e548eSAnton Blanchard 		if (MSG_CMSG_COMPAT & flags) {
2464666547ffSAl Viro 			err = ___sys_sendmsg(sock, (struct user_msghdr __user *)compat_entry,
246528a94d8fSTom Herbert 					     &msg_sys, flags, &used_address, MSG_EOR);
2466228e548eSAnton Blanchard 			if (err < 0)
2467228e548eSAnton Blanchard 				break;
2468228e548eSAnton Blanchard 			err = __put_user(err, &compat_entry->msg_len);
2469228e548eSAnton Blanchard 			++compat_entry;
2470228e548eSAnton Blanchard 		} else {
2471a7526eb5SAndy Lutomirski 			err = ___sys_sendmsg(sock,
2472666547ffSAl Viro 					     (struct user_msghdr __user *)entry,
247328a94d8fSTom Herbert 					     &msg_sys, flags, &used_address, MSG_EOR);
2474228e548eSAnton Blanchard 			if (err < 0)
2475228e548eSAnton Blanchard 				break;
2476228e548eSAnton Blanchard 			err = put_user(err, &entry->msg_len);
2477228e548eSAnton Blanchard 			++entry;
2478228e548eSAnton Blanchard 		}
2479228e548eSAnton Blanchard 
2480228e548eSAnton Blanchard 		if (err)
2481228e548eSAnton Blanchard 			break;
2482228e548eSAnton Blanchard 		++datagrams;
24833023898bSSoheil Hassas Yeganeh 		if (msg_data_left(&msg_sys))
24843023898bSSoheil Hassas Yeganeh 			break;
2485a78cb84cSEric Dumazet 		cond_resched();
2486228e548eSAnton Blanchard 	}
2487228e548eSAnton Blanchard 
2488228e548eSAnton Blanchard 	fput_light(sock->file, fput_needed);
2489228e548eSAnton Blanchard 
2490728ffb86SAnton Blanchard 	/* We only return an error if no datagrams were able to be sent */
2491728ffb86SAnton Blanchard 	if (datagrams != 0)
2492228e548eSAnton Blanchard 		return datagrams;
2493228e548eSAnton Blanchard 
2494228e548eSAnton Blanchard 	return err;
2495228e548eSAnton Blanchard }
2496228e548eSAnton Blanchard 
2497228e548eSAnton Blanchard SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
2498228e548eSAnton Blanchard 		unsigned int, vlen, unsigned int, flags)
2499228e548eSAnton Blanchard {
2500e1834a32SDominik Brodowski 	return __sys_sendmmsg(fd, mmsg, vlen, flags, true);
2501228e548eSAnton Blanchard }
2502228e548eSAnton Blanchard 
25034257c8caSJens Axboe static int recvmsg_copy_msghdr(struct msghdr *msg,
25044257c8caSJens Axboe 			       struct user_msghdr __user *umsg, unsigned flags,
25054257c8caSJens Axboe 			       struct sockaddr __user **uaddr,
25064257c8caSJens Axboe 			       struct iovec **iov)
25074257c8caSJens Axboe {
25084257c8caSJens Axboe 	ssize_t err;
25094257c8caSJens Axboe 
25104257c8caSJens Axboe 	if (MSG_CMSG_COMPAT & flags) {
25114257c8caSJens Axboe 		struct compat_msghdr __user *msg_compat;
25124257c8caSJens Axboe 
25134257c8caSJens Axboe 		msg_compat = (struct compat_msghdr __user *) umsg;
25144257c8caSJens Axboe 		err = get_compat_msghdr(msg, msg_compat, uaddr, iov);
25154257c8caSJens Axboe 	} else {
25164257c8caSJens Axboe 		err = copy_msghdr_from_user(msg, umsg, uaddr, iov);
25174257c8caSJens Axboe 	}
25184257c8caSJens Axboe 	if (err < 0)
25194257c8caSJens Axboe 		return err;
25204257c8caSJens Axboe 
25214257c8caSJens Axboe 	return 0;
25224257c8caSJens Axboe }
25234257c8caSJens Axboe 
25244257c8caSJens Axboe static int ____sys_recvmsg(struct socket *sock, struct msghdr *msg_sys,
25254257c8caSJens Axboe 			   struct user_msghdr __user *msg,
25264257c8caSJens Axboe 			   struct sockaddr __user *uaddr,
25274257c8caSJens Axboe 			   unsigned int flags, int nosec)
25281da177e4SLinus Torvalds {
252989bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
253089bddce5SStephen Hemminger 					(struct compat_msghdr __user *) msg;
25314257c8caSJens Axboe 	int __user *uaddr_len = COMPAT_NAMELEN(msg);
25324257c8caSJens Axboe 	struct sockaddr_storage addr;
25331da177e4SLinus Torvalds 	unsigned long cmsg_ptr;
25342da62906SAl Viro 	int len;
253508adb7daSAl Viro 	ssize_t err;
25361da177e4SLinus Torvalds 
253708adb7daSAl Viro 	msg_sys->msg_name = &addr;
2538a2e27255SArnaldo Carvalho de Melo 	cmsg_ptr = (unsigned long)msg_sys->msg_control;
2539a2e27255SArnaldo Carvalho de Melo 	msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
25401da177e4SLinus Torvalds 
2541f3d33426SHannes Frederic Sowa 	/* We assume all kernel code knows the size of sockaddr_storage */
2542f3d33426SHannes Frederic Sowa 	msg_sys->msg_namelen = 0;
2543f3d33426SHannes Frederic Sowa 
25441da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
25451da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
25462da62906SAl Viro 	err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys, flags);
25471da177e4SLinus Torvalds 	if (err < 0)
25484257c8caSJens Axboe 		goto out;
25491da177e4SLinus Torvalds 	len = err;
25501da177e4SLinus Torvalds 
25511da177e4SLinus Torvalds 	if (uaddr != NULL) {
255243db362dSMaciej Żenczykowski 		err = move_addr_to_user(&addr,
2553a2e27255SArnaldo Carvalho de Melo 					msg_sys->msg_namelen, uaddr,
255489bddce5SStephen Hemminger 					uaddr_len);
25551da177e4SLinus Torvalds 		if (err < 0)
25564257c8caSJens Axboe 			goto out;
25571da177e4SLinus Torvalds 	}
2558a2e27255SArnaldo Carvalho de Melo 	err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
255937f7f421SDavid S. Miller 			 COMPAT_FLAGS(msg));
25601da177e4SLinus Torvalds 	if (err)
25614257c8caSJens Axboe 		goto out;
25621da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags)
2563a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
25641da177e4SLinus Torvalds 				 &msg_compat->msg_controllen);
25651da177e4SLinus Torvalds 	else
2566a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
25671da177e4SLinus Torvalds 				 &msg->msg_controllen);
25681da177e4SLinus Torvalds 	if (err)
25694257c8caSJens Axboe 		goto out;
25701da177e4SLinus Torvalds 	err = len;
25714257c8caSJens Axboe out:
25724257c8caSJens Axboe 	return err;
25734257c8caSJens Axboe }
25741da177e4SLinus Torvalds 
25754257c8caSJens Axboe static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg,
25764257c8caSJens Axboe 			 struct msghdr *msg_sys, unsigned int flags, int nosec)
25774257c8caSJens Axboe {
25784257c8caSJens Axboe 	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
25794257c8caSJens Axboe 	/* user mode address pointers */
25804257c8caSJens Axboe 	struct sockaddr __user *uaddr;
25814257c8caSJens Axboe 	ssize_t err;
25824257c8caSJens Axboe 
25834257c8caSJens Axboe 	err = recvmsg_copy_msghdr(msg_sys, msg, flags, &uaddr, &iov);
25844257c8caSJens Axboe 	if (err < 0)
25854257c8caSJens Axboe 		return err;
25864257c8caSJens Axboe 
25874257c8caSJens Axboe 	err = ____sys_recvmsg(sock, msg_sys, msg, uaddr, flags, nosec);
2588a74e9106SEric Dumazet 	kfree(iov);
2589a2e27255SArnaldo Carvalho de Melo 	return err;
2590a2e27255SArnaldo Carvalho de Melo }
2591a2e27255SArnaldo Carvalho de Melo 
2592a2e27255SArnaldo Carvalho de Melo /*
2593a2e27255SArnaldo Carvalho de Melo  *	BSD recvmsg interface
2594a2e27255SArnaldo Carvalho de Melo  */
2595a2e27255SArnaldo Carvalho de Melo 
2596aa1fa28fSJens Axboe long __sys_recvmsg_sock(struct socket *sock, struct user_msghdr __user *msg,
2597aa1fa28fSJens Axboe 			unsigned int flags)
2598aa1fa28fSJens Axboe {
2599aa1fa28fSJens Axboe 	struct msghdr msg_sys;
2600aa1fa28fSJens Axboe 
2601aa1fa28fSJens Axboe 	return ___sys_recvmsg(sock, msg, &msg_sys, flags, 0);
2602aa1fa28fSJens Axboe }
2603aa1fa28fSJens Axboe 
2604e1834a32SDominik Brodowski long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned int flags,
2605e1834a32SDominik Brodowski 		   bool forbid_cmsg_compat)
2606a2e27255SArnaldo Carvalho de Melo {
2607a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err;
2608a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
26091be374a0SAndy Lutomirski 	struct socket *sock;
2610a2e27255SArnaldo Carvalho de Melo 
2611e1834a32SDominik Brodowski 	if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT))
2612e1834a32SDominik Brodowski 		return -EINVAL;
2613e1834a32SDominik Brodowski 
26141be374a0SAndy Lutomirski 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2615a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2616a2e27255SArnaldo Carvalho de Melo 		goto out;
2617a2e27255SArnaldo Carvalho de Melo 
2618a7526eb5SAndy Lutomirski 	err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0);
2619a2e27255SArnaldo Carvalho de Melo 
26206cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
26211da177e4SLinus Torvalds out:
26221da177e4SLinus Torvalds 	return err;
26231da177e4SLinus Torvalds }
26241da177e4SLinus Torvalds 
2625666547ffSAl Viro SYSCALL_DEFINE3(recvmsg, int, fd, struct user_msghdr __user *, msg,
2626a7526eb5SAndy Lutomirski 		unsigned int, flags)
2627a7526eb5SAndy Lutomirski {
2628e1834a32SDominik Brodowski 	return __sys_recvmsg(fd, msg, flags, true);
2629a7526eb5SAndy Lutomirski }
2630a7526eb5SAndy Lutomirski 
2631a2e27255SArnaldo Carvalho de Melo /*
2632a2e27255SArnaldo Carvalho de Melo  *     Linux recvmmsg interface
2633a2e27255SArnaldo Carvalho de Melo  */
26341da177e4SLinus Torvalds 
2635e11d4284SArnd Bergmann static int do_recvmmsg(int fd, struct mmsghdr __user *mmsg,
2636e11d4284SArnd Bergmann 			  unsigned int vlen, unsigned int flags,
2637e11d4284SArnd Bergmann 			  struct timespec64 *timeout)
2638a2e27255SArnaldo Carvalho de Melo {
2639a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err, datagrams;
2640a2e27255SArnaldo Carvalho de Melo 	struct socket *sock;
2641a2e27255SArnaldo Carvalho de Melo 	struct mmsghdr __user *entry;
2642d7256d0eSJean-Mickael Guerin 	struct compat_mmsghdr __user *compat_entry;
2643a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
2644766b9f92SDeepa Dinamani 	struct timespec64 end_time;
2645766b9f92SDeepa Dinamani 	struct timespec64 timeout64;
2646a2e27255SArnaldo Carvalho de Melo 
2647a2e27255SArnaldo Carvalho de Melo 	if (timeout &&
2648a2e27255SArnaldo Carvalho de Melo 	    poll_select_set_timeout(&end_time, timeout->tv_sec,
2649a2e27255SArnaldo Carvalho de Melo 				    timeout->tv_nsec))
2650a2e27255SArnaldo Carvalho de Melo 		return -EINVAL;
2651a2e27255SArnaldo Carvalho de Melo 
2652a2e27255SArnaldo Carvalho de Melo 	datagrams = 0;
2653a2e27255SArnaldo Carvalho de Melo 
2654a2e27255SArnaldo Carvalho de Melo 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2655a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2656a2e27255SArnaldo Carvalho de Melo 		return err;
2657a2e27255SArnaldo Carvalho de Melo 
26587797dc41SSoheil Hassas Yeganeh 	if (likely(!(flags & MSG_ERRQUEUE))) {
2659a2e27255SArnaldo Carvalho de Melo 		err = sock_error(sock->sk);
2660e623a9e9SMaxime Jayat 		if (err) {
2661e623a9e9SMaxime Jayat 			datagrams = err;
2662a2e27255SArnaldo Carvalho de Melo 			goto out_put;
2663e623a9e9SMaxime Jayat 		}
26647797dc41SSoheil Hassas Yeganeh 	}
2665a2e27255SArnaldo Carvalho de Melo 
2666a2e27255SArnaldo Carvalho de Melo 	entry = mmsg;
2667d7256d0eSJean-Mickael Guerin 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2668a2e27255SArnaldo Carvalho de Melo 
2669a2e27255SArnaldo Carvalho de Melo 	while (datagrams < vlen) {
2670a2e27255SArnaldo Carvalho de Melo 		/*
2671a2e27255SArnaldo Carvalho de Melo 		 * No need to ask LSM for more than the first datagram.
2672a2e27255SArnaldo Carvalho de Melo 		 */
2673d7256d0eSJean-Mickael Guerin 		if (MSG_CMSG_COMPAT & flags) {
2674666547ffSAl Viro 			err = ___sys_recvmsg(sock, (struct user_msghdr __user *)compat_entry,
2675b9eb8b87SAnton Blanchard 					     &msg_sys, flags & ~MSG_WAITFORONE,
2676b9eb8b87SAnton Blanchard 					     datagrams);
2677d7256d0eSJean-Mickael Guerin 			if (err < 0)
2678d7256d0eSJean-Mickael Guerin 				break;
2679d7256d0eSJean-Mickael Guerin 			err = __put_user(err, &compat_entry->msg_len);
2680d7256d0eSJean-Mickael Guerin 			++compat_entry;
2681d7256d0eSJean-Mickael Guerin 		} else {
2682a7526eb5SAndy Lutomirski 			err = ___sys_recvmsg(sock,
2683666547ffSAl Viro 					     (struct user_msghdr __user *)entry,
2684b9eb8b87SAnton Blanchard 					     &msg_sys, flags & ~MSG_WAITFORONE,
2685b9eb8b87SAnton Blanchard 					     datagrams);
2686a2e27255SArnaldo Carvalho de Melo 			if (err < 0)
2687a2e27255SArnaldo Carvalho de Melo 				break;
2688a2e27255SArnaldo Carvalho de Melo 			err = put_user(err, &entry->msg_len);
2689d7256d0eSJean-Mickael Guerin 			++entry;
2690d7256d0eSJean-Mickael Guerin 		}
2691d7256d0eSJean-Mickael Guerin 
2692a2e27255SArnaldo Carvalho de Melo 		if (err)
2693a2e27255SArnaldo Carvalho de Melo 			break;
2694a2e27255SArnaldo Carvalho de Melo 		++datagrams;
2695a2e27255SArnaldo Carvalho de Melo 
269671c5c159SBrandon L Black 		/* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
269771c5c159SBrandon L Black 		if (flags & MSG_WAITFORONE)
269871c5c159SBrandon L Black 			flags |= MSG_DONTWAIT;
269971c5c159SBrandon L Black 
2700a2e27255SArnaldo Carvalho de Melo 		if (timeout) {
2701766b9f92SDeepa Dinamani 			ktime_get_ts64(&timeout64);
2702c2e6c856SArnd Bergmann 			*timeout = timespec64_sub(end_time, timeout64);
2703a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_sec < 0) {
2704a2e27255SArnaldo Carvalho de Melo 				timeout->tv_sec = timeout->tv_nsec = 0;
2705a2e27255SArnaldo Carvalho de Melo 				break;
2706a2e27255SArnaldo Carvalho de Melo 			}
2707a2e27255SArnaldo Carvalho de Melo 
2708a2e27255SArnaldo Carvalho de Melo 			/* Timeout, return less than vlen datagrams */
2709a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_nsec == 0 && timeout->tv_sec == 0)
2710a2e27255SArnaldo Carvalho de Melo 				break;
2711a2e27255SArnaldo Carvalho de Melo 		}
2712a2e27255SArnaldo Carvalho de Melo 
2713a2e27255SArnaldo Carvalho de Melo 		/* Out of band data, return right away */
2714a2e27255SArnaldo Carvalho de Melo 		if (msg_sys.msg_flags & MSG_OOB)
2715a2e27255SArnaldo Carvalho de Melo 			break;
2716a78cb84cSEric Dumazet 		cond_resched();
2717a2e27255SArnaldo Carvalho de Melo 	}
2718a2e27255SArnaldo Carvalho de Melo 
2719a2e27255SArnaldo Carvalho de Melo 	if (err == 0)
272034b88a68SArnaldo Carvalho de Melo 		goto out_put;
2721a2e27255SArnaldo Carvalho de Melo 
272234b88a68SArnaldo Carvalho de Melo 	if (datagrams == 0) {
272334b88a68SArnaldo Carvalho de Melo 		datagrams = err;
272434b88a68SArnaldo Carvalho de Melo 		goto out_put;
272534b88a68SArnaldo Carvalho de Melo 	}
272634b88a68SArnaldo Carvalho de Melo 
2727a2e27255SArnaldo Carvalho de Melo 	/*
2728a2e27255SArnaldo Carvalho de Melo 	 * We may return less entries than requested (vlen) if the
2729a2e27255SArnaldo Carvalho de Melo 	 * sock is non block and there aren't enough datagrams...
2730a2e27255SArnaldo Carvalho de Melo 	 */
2731a2e27255SArnaldo Carvalho de Melo 	if (err != -EAGAIN) {
2732a2e27255SArnaldo Carvalho de Melo 		/*
2733a2e27255SArnaldo Carvalho de Melo 		 * ... or  if recvmsg returns an error after we
2734a2e27255SArnaldo Carvalho de Melo 		 * received some datagrams, where we record the
2735a2e27255SArnaldo Carvalho de Melo 		 * error to return on the next call or if the
2736a2e27255SArnaldo Carvalho de Melo 		 * app asks about it using getsockopt(SO_ERROR).
2737a2e27255SArnaldo Carvalho de Melo 		 */
2738a2e27255SArnaldo Carvalho de Melo 		sock->sk->sk_err = -err;
2739a2e27255SArnaldo Carvalho de Melo 	}
274034b88a68SArnaldo Carvalho de Melo out_put:
274134b88a68SArnaldo Carvalho de Melo 	fput_light(sock->file, fput_needed);
2742a2e27255SArnaldo Carvalho de Melo 
2743a2e27255SArnaldo Carvalho de Melo 	return datagrams;
2744a2e27255SArnaldo Carvalho de Melo }
2745a2e27255SArnaldo Carvalho de Melo 
2746e11d4284SArnd Bergmann int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg,
27471255e269SDominik Brodowski 		   unsigned int vlen, unsigned int flags,
2748e11d4284SArnd Bergmann 		   struct __kernel_timespec __user *timeout,
2749e11d4284SArnd Bergmann 		   struct old_timespec32 __user *timeout32)
2750a2e27255SArnaldo Carvalho de Melo {
2751a2e27255SArnaldo Carvalho de Melo 	int datagrams;
2752c2e6c856SArnd Bergmann 	struct timespec64 timeout_sys;
2753a2e27255SArnaldo Carvalho de Melo 
2754e11d4284SArnd Bergmann 	if (timeout && get_timespec64(&timeout_sys, timeout))
2755a2e27255SArnaldo Carvalho de Melo 		return -EFAULT;
2756a2e27255SArnaldo Carvalho de Melo 
2757e11d4284SArnd Bergmann 	if (timeout32 && get_old_timespec32(&timeout_sys, timeout32))
2758e11d4284SArnd Bergmann 		return -EFAULT;
2759a2e27255SArnaldo Carvalho de Melo 
2760e11d4284SArnd Bergmann 	if (!timeout && !timeout32)
2761e11d4284SArnd Bergmann 		return do_recvmmsg(fd, mmsg, vlen, flags, NULL);
2762e11d4284SArnd Bergmann 
2763e11d4284SArnd Bergmann 	datagrams = do_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys);
2764e11d4284SArnd Bergmann 
2765e11d4284SArnd Bergmann 	if (datagrams <= 0)
2766e11d4284SArnd Bergmann 		return datagrams;
2767e11d4284SArnd Bergmann 
2768e11d4284SArnd Bergmann 	if (timeout && put_timespec64(&timeout_sys, timeout))
2769e11d4284SArnd Bergmann 		datagrams = -EFAULT;
2770e11d4284SArnd Bergmann 
2771e11d4284SArnd Bergmann 	if (timeout32 && put_old_timespec32(&timeout_sys, timeout32))
2772a2e27255SArnaldo Carvalho de Melo 		datagrams = -EFAULT;
2773a2e27255SArnaldo Carvalho de Melo 
2774a2e27255SArnaldo Carvalho de Melo 	return datagrams;
2775a2e27255SArnaldo Carvalho de Melo }
2776a2e27255SArnaldo Carvalho de Melo 
27771255e269SDominik Brodowski SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
27781255e269SDominik Brodowski 		unsigned int, vlen, unsigned int, flags,
2779c2e6c856SArnd Bergmann 		struct __kernel_timespec __user *, timeout)
27801255e269SDominik Brodowski {
2781e11d4284SArnd Bergmann 	if (flags & MSG_CMSG_COMPAT)
2782e11d4284SArnd Bergmann 		return -EINVAL;
2783e11d4284SArnd Bergmann 
2784e11d4284SArnd Bergmann 	return __sys_recvmmsg(fd, mmsg, vlen, flags, timeout, NULL);
27851255e269SDominik Brodowski }
27861255e269SDominik Brodowski 
2787e11d4284SArnd Bergmann #ifdef CONFIG_COMPAT_32BIT_TIME
2788e11d4284SArnd Bergmann SYSCALL_DEFINE5(recvmmsg_time32, int, fd, struct mmsghdr __user *, mmsg,
2789e11d4284SArnd Bergmann 		unsigned int, vlen, unsigned int, flags,
2790e11d4284SArnd Bergmann 		struct old_timespec32 __user *, timeout)
2791e11d4284SArnd Bergmann {
2792e11d4284SArnd Bergmann 	if (flags & MSG_CMSG_COMPAT)
2793e11d4284SArnd Bergmann 		return -EINVAL;
2794e11d4284SArnd Bergmann 
2795e11d4284SArnd Bergmann 	return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL, timeout);
2796e11d4284SArnd Bergmann }
2797e11d4284SArnd Bergmann #endif
2798e11d4284SArnd Bergmann 
2799a2e27255SArnaldo Carvalho de Melo #ifdef __ARCH_WANT_SYS_SOCKETCALL
28001da177e4SLinus Torvalds /* Argument list sizes for sys_socketcall */
28011da177e4SLinus Torvalds #define AL(x) ((x) * sizeof(unsigned long))
2802228e548eSAnton Blanchard static const unsigned char nargs[21] = {
280389bddce5SStephen Hemminger 	AL(0), AL(3), AL(3), AL(3), AL(2), AL(3),
28041da177e4SLinus Torvalds 	AL(3), AL(3), AL(4), AL(4), AL(4), AL(6),
2805aaca0bdcSUlrich Drepper 	AL(6), AL(2), AL(5), AL(5), AL(3), AL(3),
2806228e548eSAnton Blanchard 	AL(4), AL(5), AL(4)
280789bddce5SStephen Hemminger };
280889bddce5SStephen Hemminger 
28091da177e4SLinus Torvalds #undef AL
28101da177e4SLinus Torvalds 
28111da177e4SLinus Torvalds /*
28121da177e4SLinus Torvalds  *	System call vectors.
28131da177e4SLinus Torvalds  *
28141da177e4SLinus Torvalds  *	Argument checking cleaned up. Saved 20% in size.
28151da177e4SLinus Torvalds  *  This function doesn't need to set the kernel lock because
28161da177e4SLinus Torvalds  *  it is set by the callees.
28171da177e4SLinus Torvalds  */
28181da177e4SLinus Torvalds 
28193e0fa65fSHeiko Carstens SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
28201da177e4SLinus Torvalds {
28212950fa9dSChen Gang 	unsigned long a[AUDITSC_ARGS];
28221da177e4SLinus Torvalds 	unsigned long a0, a1;
28231da177e4SLinus Torvalds 	int err;
282447379052SArjan van de Ven 	unsigned int len;
28251da177e4SLinus Torvalds 
2826228e548eSAnton Blanchard 	if (call < 1 || call > SYS_SENDMMSG)
28271da177e4SLinus Torvalds 		return -EINVAL;
2828c8e8cd57SJeremy Cline 	call = array_index_nospec(call, SYS_SENDMMSG + 1);
28291da177e4SLinus Torvalds 
283047379052SArjan van de Ven 	len = nargs[call];
283147379052SArjan van de Ven 	if (len > sizeof(a))
283247379052SArjan van de Ven 		return -EINVAL;
283347379052SArjan van de Ven 
28341da177e4SLinus Torvalds 	/* copy_from_user should be SMP safe. */
283547379052SArjan van de Ven 	if (copy_from_user(a, args, len))
28361da177e4SLinus Torvalds 		return -EFAULT;
28371da177e4SLinus Torvalds 
28382950fa9dSChen Gang 	err = audit_socketcall(nargs[call] / sizeof(unsigned long), a);
28392950fa9dSChen Gang 	if (err)
28402950fa9dSChen Gang 		return err;
28413ec3b2fbSDavid Woodhouse 
28421da177e4SLinus Torvalds 	a0 = a[0];
28431da177e4SLinus Torvalds 	a1 = a[1];
28441da177e4SLinus Torvalds 
284589bddce5SStephen Hemminger 	switch (call) {
28461da177e4SLinus Torvalds 	case SYS_SOCKET:
28479d6a15c3SDominik Brodowski 		err = __sys_socket(a0, a1, a[2]);
28481da177e4SLinus Torvalds 		break;
28491da177e4SLinus Torvalds 	case SYS_BIND:
2850a87d35d8SDominik Brodowski 		err = __sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
28511da177e4SLinus Torvalds 		break;
28521da177e4SLinus Torvalds 	case SYS_CONNECT:
28531387c2c2SDominik Brodowski 		err = __sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
28541da177e4SLinus Torvalds 		break;
28551da177e4SLinus Torvalds 	case SYS_LISTEN:
285625e290eeSDominik Brodowski 		err = __sys_listen(a0, a1);
28571da177e4SLinus Torvalds 		break;
28581da177e4SLinus Torvalds 	case SYS_ACCEPT:
28594541e805SDominik Brodowski 		err = __sys_accept4(a0, (struct sockaddr __user *)a1,
2860aaca0bdcSUlrich Drepper 				    (int __user *)a[2], 0);
28611da177e4SLinus Torvalds 		break;
28621da177e4SLinus Torvalds 	case SYS_GETSOCKNAME:
286389bddce5SStephen Hemminger 		err =
28648882a107SDominik Brodowski 		    __sys_getsockname(a0, (struct sockaddr __user *)a1,
286589bddce5SStephen Hemminger 				      (int __user *)a[2]);
28661da177e4SLinus Torvalds 		break;
28671da177e4SLinus Torvalds 	case SYS_GETPEERNAME:
286889bddce5SStephen Hemminger 		err =
2869b21c8f83SDominik Brodowski 		    __sys_getpeername(a0, (struct sockaddr __user *)a1,
287089bddce5SStephen Hemminger 				      (int __user *)a[2]);
28711da177e4SLinus Torvalds 		break;
28721da177e4SLinus Torvalds 	case SYS_SOCKETPAIR:
28736debc8d8SDominik Brodowski 		err = __sys_socketpair(a0, a1, a[2], (int __user *)a[3]);
28741da177e4SLinus Torvalds 		break;
28751da177e4SLinus Torvalds 	case SYS_SEND:
2876f3bf896bSDominik Brodowski 		err = __sys_sendto(a0, (void __user *)a1, a[2], a[3],
2877f3bf896bSDominik Brodowski 				   NULL, 0);
28781da177e4SLinus Torvalds 		break;
28791da177e4SLinus Torvalds 	case SYS_SENDTO:
2880211b634bSDominik Brodowski 		err = __sys_sendto(a0, (void __user *)a1, a[2], a[3],
28811da177e4SLinus Torvalds 				   (struct sockaddr __user *)a[4], a[5]);
28821da177e4SLinus Torvalds 		break;
28831da177e4SLinus Torvalds 	case SYS_RECV:
2884d27e9afcSDominik Brodowski 		err = __sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
2885d27e9afcSDominik Brodowski 				     NULL, NULL);
28861da177e4SLinus Torvalds 		break;
28871da177e4SLinus Torvalds 	case SYS_RECVFROM:
28887a09e1ebSDominik Brodowski 		err = __sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
288989bddce5SStephen Hemminger 				     (struct sockaddr __user *)a[4],
289089bddce5SStephen Hemminger 				     (int __user *)a[5]);
28911da177e4SLinus Torvalds 		break;
28921da177e4SLinus Torvalds 	case SYS_SHUTDOWN:
2893005a1aeaSDominik Brodowski 		err = __sys_shutdown(a0, a1);
28941da177e4SLinus Torvalds 		break;
28951da177e4SLinus Torvalds 	case SYS_SETSOCKOPT:
2896cc36dca0SDominik Brodowski 		err = __sys_setsockopt(a0, a1, a[2], (char __user *)a[3],
2897cc36dca0SDominik Brodowski 				       a[4]);
28981da177e4SLinus Torvalds 		break;
28991da177e4SLinus Torvalds 	case SYS_GETSOCKOPT:
290089bddce5SStephen Hemminger 		err =
290113a2d70eSDominik Brodowski 		    __sys_getsockopt(a0, a1, a[2], (char __user *)a[3],
290289bddce5SStephen Hemminger 				     (int __user *)a[4]);
29031da177e4SLinus Torvalds 		break;
29041da177e4SLinus Torvalds 	case SYS_SENDMSG:
2905e1834a32SDominik Brodowski 		err = __sys_sendmsg(a0, (struct user_msghdr __user *)a1,
2906e1834a32SDominik Brodowski 				    a[2], true);
29071da177e4SLinus Torvalds 		break;
2908228e548eSAnton Blanchard 	case SYS_SENDMMSG:
2909e1834a32SDominik Brodowski 		err = __sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2],
2910e1834a32SDominik Brodowski 				     a[3], true);
2911228e548eSAnton Blanchard 		break;
29121da177e4SLinus Torvalds 	case SYS_RECVMSG:
2913e1834a32SDominik Brodowski 		err = __sys_recvmsg(a0, (struct user_msghdr __user *)a1,
2914e1834a32SDominik Brodowski 				    a[2], true);
29151da177e4SLinus Torvalds 		break;
2916a2e27255SArnaldo Carvalho de Melo 	case SYS_RECVMMSG:
2917e11d4284SArnd Bergmann 		if (IS_ENABLED(CONFIG_64BIT) || !IS_ENABLED(CONFIG_64BIT_TIME))
2918e11d4284SArnd Bergmann 			err = __sys_recvmmsg(a0, (struct mmsghdr __user *)a1,
2919e11d4284SArnd Bergmann 					     a[2], a[3],
2920e11d4284SArnd Bergmann 					     (struct __kernel_timespec __user *)a[4],
2921e11d4284SArnd Bergmann 					     NULL);
2922e11d4284SArnd Bergmann 		else
2923e11d4284SArnd Bergmann 			err = __sys_recvmmsg(a0, (struct mmsghdr __user *)a1,
2924e11d4284SArnd Bergmann 					     a[2], a[3], NULL,
2925e11d4284SArnd Bergmann 					     (struct old_timespec32 __user *)a[4]);
2926a2e27255SArnaldo Carvalho de Melo 		break;
2927de11defeSUlrich Drepper 	case SYS_ACCEPT4:
29284541e805SDominik Brodowski 		err = __sys_accept4(a0, (struct sockaddr __user *)a1,
2929de11defeSUlrich Drepper 				    (int __user *)a[2], a[3]);
2930aaca0bdcSUlrich Drepper 		break;
29311da177e4SLinus Torvalds 	default:
29321da177e4SLinus Torvalds 		err = -EINVAL;
29331da177e4SLinus Torvalds 		break;
29341da177e4SLinus Torvalds 	}
29351da177e4SLinus Torvalds 	return err;
29361da177e4SLinus Torvalds }
29371da177e4SLinus Torvalds 
29381da177e4SLinus Torvalds #endif				/* __ARCH_WANT_SYS_SOCKETCALL */
29391da177e4SLinus Torvalds 
294055737fdaSStephen Hemminger /**
294155737fdaSStephen Hemminger  *	sock_register - add a socket protocol handler
294255737fdaSStephen Hemminger  *	@ops: description of protocol
294355737fdaSStephen Hemminger  *
29441da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
29451da177e4SLinus Torvalds  *	advertise its address family, and have it linked into the
2946e793c0f7SMasanari Iida  *	socket interface. The value ops->family corresponds to the
294755737fdaSStephen Hemminger  *	socket system call protocol family.
29481da177e4SLinus Torvalds  */
2949f0fd27d4SStephen Hemminger int sock_register(const struct net_proto_family *ops)
29501da177e4SLinus Torvalds {
29511da177e4SLinus Torvalds 	int err;
29521da177e4SLinus Torvalds 
29531da177e4SLinus Torvalds 	if (ops->family >= NPROTO) {
29543410f22eSYang Yingliang 		pr_crit("protocol %d >= NPROTO(%d)\n", ops->family, NPROTO);
29551da177e4SLinus Torvalds 		return -ENOBUFS;
29561da177e4SLinus Torvalds 	}
295755737fdaSStephen Hemminger 
295855737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2959190683a9SEric Dumazet 	if (rcu_dereference_protected(net_families[ops->family],
2960190683a9SEric Dumazet 				      lockdep_is_held(&net_family_lock)))
29611da177e4SLinus Torvalds 		err = -EEXIST;
296255737fdaSStephen Hemminger 	else {
2963cf778b00SEric Dumazet 		rcu_assign_pointer(net_families[ops->family], ops);
29641da177e4SLinus Torvalds 		err = 0;
29651da177e4SLinus Torvalds 	}
296655737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
296755737fdaSStephen Hemminger 
29683410f22eSYang Yingliang 	pr_info("NET: Registered protocol family %d\n", ops->family);
29691da177e4SLinus Torvalds 	return err;
29701da177e4SLinus Torvalds }
2971c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_register);
29721da177e4SLinus Torvalds 
297355737fdaSStephen Hemminger /**
297455737fdaSStephen Hemminger  *	sock_unregister - remove a protocol handler
297555737fdaSStephen Hemminger  *	@family: protocol family to remove
297655737fdaSStephen Hemminger  *
29771da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
29781da177e4SLinus Torvalds  *	remove its address family, and have it unlinked from the
297955737fdaSStephen Hemminger  *	new socket creation.
298055737fdaSStephen Hemminger  *
298155737fdaSStephen Hemminger  *	If protocol handler is a module, then it can use module reference
298255737fdaSStephen Hemminger  *	counts to protect against new references. If protocol handler is not
298355737fdaSStephen Hemminger  *	a module then it needs to provide its own protection in
298455737fdaSStephen Hemminger  *	the ops->create routine.
29851da177e4SLinus Torvalds  */
2986f0fd27d4SStephen Hemminger void sock_unregister(int family)
29871da177e4SLinus Torvalds {
2988f0fd27d4SStephen Hemminger 	BUG_ON(family < 0 || family >= NPROTO);
29891da177e4SLinus Torvalds 
299055737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2991a9b3cd7fSStephen Hemminger 	RCU_INIT_POINTER(net_families[family], NULL);
299255737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
299355737fdaSStephen Hemminger 
299455737fdaSStephen Hemminger 	synchronize_rcu();
299555737fdaSStephen Hemminger 
29963410f22eSYang Yingliang 	pr_info("NET: Unregistered protocol family %d\n", family);
29971da177e4SLinus Torvalds }
2998c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_unregister);
29991da177e4SLinus Torvalds 
3000bf2ae2e4SXin Long bool sock_is_registered(int family)
3001bf2ae2e4SXin Long {
300266b51b0aSJeremy Cline 	return family < NPROTO && rcu_access_pointer(net_families[family]);
3003bf2ae2e4SXin Long }
3004bf2ae2e4SXin Long 
300577d76ea3SAndi Kleen static int __init sock_init(void)
30061da177e4SLinus Torvalds {
3007b3e19d92SNick Piggin 	int err;
30082ca794e5SEric W. Biederman 	/*
30092ca794e5SEric W. Biederman 	 *      Initialize the network sysctl infrastructure.
30102ca794e5SEric W. Biederman 	 */
30112ca794e5SEric W. Biederman 	err = net_sysctl_init();
30122ca794e5SEric W. Biederman 	if (err)
30132ca794e5SEric W. Biederman 		goto out;
3014b3e19d92SNick Piggin 
30151da177e4SLinus Torvalds 	/*
30161da177e4SLinus Torvalds 	 *      Initialize skbuff SLAB cache
30171da177e4SLinus Torvalds 	 */
30181da177e4SLinus Torvalds 	skb_init();
30191da177e4SLinus Torvalds 
30201da177e4SLinus Torvalds 	/*
30211da177e4SLinus Torvalds 	 *      Initialize the protocols module.
30221da177e4SLinus Torvalds 	 */
30231da177e4SLinus Torvalds 
30241da177e4SLinus Torvalds 	init_inodecache();
3025b3e19d92SNick Piggin 
3026b3e19d92SNick Piggin 	err = register_filesystem(&sock_fs_type);
3027b3e19d92SNick Piggin 	if (err)
3028b3e19d92SNick Piggin 		goto out_fs;
30291da177e4SLinus Torvalds 	sock_mnt = kern_mount(&sock_fs_type);
3030b3e19d92SNick Piggin 	if (IS_ERR(sock_mnt)) {
3031b3e19d92SNick Piggin 		err = PTR_ERR(sock_mnt);
3032b3e19d92SNick Piggin 		goto out_mount;
3033b3e19d92SNick Piggin 	}
303477d76ea3SAndi Kleen 
303577d76ea3SAndi Kleen 	/* The real protocol initialization is performed in later initcalls.
30361da177e4SLinus Torvalds 	 */
30371da177e4SLinus Torvalds 
30381da177e4SLinus Torvalds #ifdef CONFIG_NETFILTER
30396d11cfdbSPablo Neira Ayuso 	err = netfilter_init();
30406d11cfdbSPablo Neira Ayuso 	if (err)
30416d11cfdbSPablo Neira Ayuso 		goto out;
30421da177e4SLinus Torvalds #endif
3043cbeb321aSDavid S. Miller 
3044408eccceSDaniel Borkmann 	ptp_classifier_init();
3045c1f19b51SRichard Cochran 
3046b3e19d92SNick Piggin out:
3047b3e19d92SNick Piggin 	return err;
3048b3e19d92SNick Piggin 
3049b3e19d92SNick Piggin out_mount:
3050b3e19d92SNick Piggin 	unregister_filesystem(&sock_fs_type);
3051b3e19d92SNick Piggin out_fs:
3052b3e19d92SNick Piggin 	goto out;
30531da177e4SLinus Torvalds }
30541da177e4SLinus Torvalds 
305577d76ea3SAndi Kleen core_initcall(sock_init);	/* early initcall */
305677d76ea3SAndi Kleen 
30571da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS
30581da177e4SLinus Torvalds void socket_seq_show(struct seq_file *seq)
30591da177e4SLinus Torvalds {
3060648845abSTonghao Zhang 	seq_printf(seq, "sockets: used %d\n",
3061648845abSTonghao Zhang 		   sock_inuse_get(seq->private));
30621da177e4SLinus Torvalds }
30631da177e4SLinus Torvalds #endif				/* CONFIG_PROC_FS */
30641da177e4SLinus Torvalds 
306589bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
306636fd633eSAl Viro static int compat_dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32)
30677a229387SArnd Bergmann {
30686b96018bSArnd Bergmann 	struct compat_ifconf ifc32;
30697a229387SArnd Bergmann 	struct ifconf ifc;
30707a229387SArnd Bergmann 	int err;
30717a229387SArnd Bergmann 
30726b96018bSArnd Bergmann 	if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf)))
30737a229387SArnd Bergmann 		return -EFAULT;
30747a229387SArnd Bergmann 
307536fd633eSAl Viro 	ifc.ifc_len = ifc32.ifc_len;
307636fd633eSAl Viro 	ifc.ifc_req = compat_ptr(ifc32.ifcbuf);
30777a229387SArnd Bergmann 
307836fd633eSAl Viro 	rtnl_lock();
307936fd633eSAl Viro 	err = dev_ifconf(net, &ifc, sizeof(struct compat_ifreq));
308036fd633eSAl Viro 	rtnl_unlock();
30817a229387SArnd Bergmann 	if (err)
30827a229387SArnd Bergmann 		return err;
30837a229387SArnd Bergmann 
308436fd633eSAl Viro 	ifc32.ifc_len = ifc.ifc_len;
30856b96018bSArnd Bergmann 	if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf)))
30867a229387SArnd Bergmann 		return -EFAULT;
30877a229387SArnd Bergmann 
30887a229387SArnd Bergmann 	return 0;
30897a229387SArnd Bergmann }
30907a229387SArnd Bergmann 
30916b96018bSArnd Bergmann static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
30927a229387SArnd Bergmann {
30933a7da39dSBen Hutchings 	struct compat_ethtool_rxnfc __user *compat_rxnfc;
30943a7da39dSBen Hutchings 	bool convert_in = false, convert_out = false;
309544c02a2cSAl Viro 	size_t buf_size = 0;
309644c02a2cSAl Viro 	struct ethtool_rxnfc __user *rxnfc = NULL;
309744c02a2cSAl Viro 	struct ifreq ifr;
30983a7da39dSBen Hutchings 	u32 rule_cnt = 0, actual_rule_cnt;
30993a7da39dSBen Hutchings 	u32 ethcmd;
31007a229387SArnd Bergmann 	u32 data;
31013a7da39dSBen Hutchings 	int ret;
31027a229387SArnd Bergmann 
31037a229387SArnd Bergmann 	if (get_user(data, &ifr32->ifr_ifru.ifru_data))
31047a229387SArnd Bergmann 		return -EFAULT;
31057a229387SArnd Bergmann 
31063a7da39dSBen Hutchings 	compat_rxnfc = compat_ptr(data);
31073a7da39dSBen Hutchings 
31083a7da39dSBen Hutchings 	if (get_user(ethcmd, &compat_rxnfc->cmd))
31097a229387SArnd Bergmann 		return -EFAULT;
31107a229387SArnd Bergmann 
31113a7da39dSBen Hutchings 	/* Most ethtool structures are defined without padding.
31123a7da39dSBen Hutchings 	 * Unfortunately struct ethtool_rxnfc is an exception.
31133a7da39dSBen Hutchings 	 */
31143a7da39dSBen Hutchings 	switch (ethcmd) {
31153a7da39dSBen Hutchings 	default:
31163a7da39dSBen Hutchings 		break;
31173a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLALL:
31183a7da39dSBen Hutchings 		/* Buffer size is variable */
31193a7da39dSBen Hutchings 		if (get_user(rule_cnt, &compat_rxnfc->rule_cnt))
31203a7da39dSBen Hutchings 			return -EFAULT;
31213a7da39dSBen Hutchings 		if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32))
31223a7da39dSBen Hutchings 			return -ENOMEM;
31233a7da39dSBen Hutchings 		buf_size += rule_cnt * sizeof(u32);
31243a7da39dSBen Hutchings 		/* fall through */
31253a7da39dSBen Hutchings 	case ETHTOOL_GRXRINGS:
31263a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLCNT:
31273a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRULE:
312855664f32SBen Hutchings 	case ETHTOOL_SRXCLSRLINS:
31293a7da39dSBen Hutchings 		convert_out = true;
31303a7da39dSBen Hutchings 		/* fall through */
31313a7da39dSBen Hutchings 	case ETHTOOL_SRXCLSRLDEL:
31323a7da39dSBen Hutchings 		buf_size += sizeof(struct ethtool_rxnfc);
31333a7da39dSBen Hutchings 		convert_in = true;
313444c02a2cSAl Viro 		rxnfc = compat_alloc_user_space(buf_size);
31353a7da39dSBen Hutchings 		break;
31363a7da39dSBen Hutchings 	}
31373a7da39dSBen Hutchings 
313844c02a2cSAl Viro 	if (copy_from_user(&ifr.ifr_name, &ifr32->ifr_name, IFNAMSIZ))
31393a7da39dSBen Hutchings 		return -EFAULT;
31403a7da39dSBen Hutchings 
314144c02a2cSAl Viro 	ifr.ifr_data = convert_in ? rxnfc : (void __user *)compat_rxnfc;
31423a7da39dSBen Hutchings 
31433a7da39dSBen Hutchings 	if (convert_in) {
3144127fe533SAlexander Duyck 		/* We expect there to be holes between fs.m_ext and
31453a7da39dSBen Hutchings 		 * fs.ring_cookie and at the end of fs, but nowhere else.
31463a7da39dSBen Hutchings 		 */
3147127fe533SAlexander Duyck 		BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_ext) +
3148127fe533SAlexander Duyck 			     sizeof(compat_rxnfc->fs.m_ext) !=
3149127fe533SAlexander Duyck 			     offsetof(struct ethtool_rxnfc, fs.m_ext) +
3150127fe533SAlexander Duyck 			     sizeof(rxnfc->fs.m_ext));
31513a7da39dSBen Hutchings 		BUILD_BUG_ON(
31523a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.location) -
31533a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) !=
31543a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.location) -
31553a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.ring_cookie));
31563a7da39dSBen Hutchings 
31573a7da39dSBen Hutchings 		if (copy_in_user(rxnfc, compat_rxnfc,
3158954b1244SStephen Hemminger 				 (void __user *)(&rxnfc->fs.m_ext + 1) -
3159954b1244SStephen Hemminger 				 (void __user *)rxnfc) ||
31603a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->fs.ring_cookie,
31613a7da39dSBen Hutchings 				 &compat_rxnfc->fs.ring_cookie,
3162954b1244SStephen Hemminger 				 (void __user *)(&rxnfc->fs.location + 1) -
3163b6168562SWenwen Wang 				 (void __user *)&rxnfc->fs.ring_cookie))
3164b6168562SWenwen Wang 			return -EFAULT;
3165b6168562SWenwen Wang 		if (ethcmd == ETHTOOL_GRXCLSRLALL) {
3166b6168562SWenwen Wang 			if (put_user(rule_cnt, &rxnfc->rule_cnt))
3167b6168562SWenwen Wang 				return -EFAULT;
3168b6168562SWenwen Wang 		} else if (copy_in_user(&rxnfc->rule_cnt,
3169b6168562SWenwen Wang 					&compat_rxnfc->rule_cnt,
31703a7da39dSBen Hutchings 					sizeof(rxnfc->rule_cnt)))
31713a7da39dSBen Hutchings 			return -EFAULT;
31723a7da39dSBen Hutchings 	}
31733a7da39dSBen Hutchings 
317444c02a2cSAl Viro 	ret = dev_ioctl(net, SIOCETHTOOL, &ifr, NULL);
31753a7da39dSBen Hutchings 	if (ret)
31763a7da39dSBen Hutchings 		return ret;
31773a7da39dSBen Hutchings 
31783a7da39dSBen Hutchings 	if (convert_out) {
31793a7da39dSBen Hutchings 		if (copy_in_user(compat_rxnfc, rxnfc,
3180954b1244SStephen Hemminger 				 (const void __user *)(&rxnfc->fs.m_ext + 1) -
3181954b1244SStephen Hemminger 				 (const void __user *)rxnfc) ||
31823a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->fs.ring_cookie,
31833a7da39dSBen Hutchings 				 &rxnfc->fs.ring_cookie,
3184954b1244SStephen Hemminger 				 (const void __user *)(&rxnfc->fs.location + 1) -
3185954b1244SStephen Hemminger 				 (const void __user *)&rxnfc->fs.ring_cookie) ||
31863a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt,
31873a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
31883a7da39dSBen Hutchings 			return -EFAULT;
31893a7da39dSBen Hutchings 
31903a7da39dSBen Hutchings 		if (ethcmd == ETHTOOL_GRXCLSRLALL) {
31913a7da39dSBen Hutchings 			/* As an optimisation, we only copy the actual
31923a7da39dSBen Hutchings 			 * number of rules that the underlying
31933a7da39dSBen Hutchings 			 * function returned.  Since Mallory might
31943a7da39dSBen Hutchings 			 * change the rule count in user memory, we
31953a7da39dSBen Hutchings 			 * check that it is less than the rule count
31963a7da39dSBen Hutchings 			 * originally given (as the user buffer size),
31973a7da39dSBen Hutchings 			 * which has been range-checked.
31983a7da39dSBen Hutchings 			 */
31993a7da39dSBen Hutchings 			if (get_user(actual_rule_cnt, &rxnfc->rule_cnt))
32003a7da39dSBen Hutchings 				return -EFAULT;
32013a7da39dSBen Hutchings 			if (actual_rule_cnt < rule_cnt)
32023a7da39dSBen Hutchings 				rule_cnt = actual_rule_cnt;
32033a7da39dSBen Hutchings 			if (copy_in_user(&compat_rxnfc->rule_locs[0],
32043a7da39dSBen Hutchings 					 &rxnfc->rule_locs[0],
32053a7da39dSBen Hutchings 					 rule_cnt * sizeof(u32)))
32063a7da39dSBen Hutchings 				return -EFAULT;
32073a7da39dSBen Hutchings 		}
32083a7da39dSBen Hutchings 	}
32093a7da39dSBen Hutchings 
32103a7da39dSBen Hutchings 	return 0;
32117a229387SArnd Bergmann }
32127a229387SArnd Bergmann 
32137a50a240SArnd Bergmann static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32)
32147a50a240SArnd Bergmann {
32157a50a240SArnd Bergmann 	compat_uptr_t uptr32;
321644c02a2cSAl Viro 	struct ifreq ifr;
321744c02a2cSAl Viro 	void __user *saved;
321844c02a2cSAl Viro 	int err;
32197a50a240SArnd Bergmann 
322044c02a2cSAl Viro 	if (copy_from_user(&ifr, uifr32, sizeof(struct compat_ifreq)))
32217a50a240SArnd Bergmann 		return -EFAULT;
32227a50a240SArnd Bergmann 
32237a50a240SArnd Bergmann 	if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu))
32247a50a240SArnd Bergmann 		return -EFAULT;
32257a50a240SArnd Bergmann 
322644c02a2cSAl Viro 	saved = ifr.ifr_settings.ifs_ifsu.raw_hdlc;
322744c02a2cSAl Viro 	ifr.ifr_settings.ifs_ifsu.raw_hdlc = compat_ptr(uptr32);
32287a50a240SArnd Bergmann 
322944c02a2cSAl Viro 	err = dev_ioctl(net, SIOCWANDEV, &ifr, NULL);
323044c02a2cSAl Viro 	if (!err) {
323144c02a2cSAl Viro 		ifr.ifr_settings.ifs_ifsu.raw_hdlc = saved;
323244c02a2cSAl Viro 		if (copy_to_user(uifr32, &ifr, sizeof(struct compat_ifreq)))
323344c02a2cSAl Viro 			err = -EFAULT;
32347a50a240SArnd Bergmann 	}
32357a229387SArnd Bergmann 	return err;
32367a229387SArnd Bergmann }
32377a229387SArnd Bergmann 
3238590d4693SBen Hutchings /* Handle ioctls that use ifreq::ifr_data and just need struct ifreq converted */
3239590d4693SBen Hutchings static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd,
32406b96018bSArnd Bergmann 				 struct compat_ifreq __user *u_ifreq32)
32417a229387SArnd Bergmann {
324244c02a2cSAl Viro 	struct ifreq ifreq;
32437a229387SArnd Bergmann 	u32 data32;
32447a229387SArnd Bergmann 
324544c02a2cSAl Viro 	if (copy_from_user(ifreq.ifr_name, u_ifreq32->ifr_name, IFNAMSIZ))
32467a229387SArnd Bergmann 		return -EFAULT;
324744c02a2cSAl Viro 	if (get_user(data32, &u_ifreq32->ifr_data))
32487a229387SArnd Bergmann 		return -EFAULT;
324944c02a2cSAl Viro 	ifreq.ifr_data = compat_ptr(data32);
32507a229387SArnd Bergmann 
325144c02a2cSAl Viro 	return dev_ioctl(net, cmd, &ifreq, NULL);
3252a2116ed2SArnd Bergmann }
3253a2116ed2SArnd Bergmann 
325437ac39bdSJohannes Berg static int compat_ifreq_ioctl(struct net *net, struct socket *sock,
325537ac39bdSJohannes Berg 			      unsigned int cmd,
325637ac39bdSJohannes Berg 			      struct compat_ifreq __user *uifr32)
325737ac39bdSJohannes Berg {
325837ac39bdSJohannes Berg 	struct ifreq __user *uifr;
325937ac39bdSJohannes Berg 	int err;
326037ac39bdSJohannes Berg 
326137ac39bdSJohannes Berg 	/* Handle the fact that while struct ifreq has the same *layout* on
326237ac39bdSJohannes Berg 	 * 32/64 for everything but ifreq::ifru_ifmap and ifreq::ifru_data,
326337ac39bdSJohannes Berg 	 * which are handled elsewhere, it still has different *size* due to
326437ac39bdSJohannes Berg 	 * ifreq::ifru_ifmap (which is 16 bytes on 32 bit, 24 bytes on 64-bit,
326537ac39bdSJohannes Berg 	 * resulting in struct ifreq being 32 and 40 bytes respectively).
326637ac39bdSJohannes Berg 	 * As a result, if the struct happens to be at the end of a page and
326737ac39bdSJohannes Berg 	 * the next page isn't readable/writable, we get a fault. To prevent
326837ac39bdSJohannes Berg 	 * that, copy back and forth to the full size.
326937ac39bdSJohannes Berg 	 */
327037ac39bdSJohannes Berg 
327137ac39bdSJohannes Berg 	uifr = compat_alloc_user_space(sizeof(*uifr));
327237ac39bdSJohannes Berg 	if (copy_in_user(uifr, uifr32, sizeof(*uifr32)))
327337ac39bdSJohannes Berg 		return -EFAULT;
327437ac39bdSJohannes Berg 
327537ac39bdSJohannes Berg 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr);
327637ac39bdSJohannes Berg 
327737ac39bdSJohannes Berg 	if (!err) {
327837ac39bdSJohannes Berg 		switch (cmd) {
327937ac39bdSJohannes Berg 		case SIOCGIFFLAGS:
328037ac39bdSJohannes Berg 		case SIOCGIFMETRIC:
328137ac39bdSJohannes Berg 		case SIOCGIFMTU:
328237ac39bdSJohannes Berg 		case SIOCGIFMEM:
328337ac39bdSJohannes Berg 		case SIOCGIFHWADDR:
328437ac39bdSJohannes Berg 		case SIOCGIFINDEX:
328537ac39bdSJohannes Berg 		case SIOCGIFADDR:
328637ac39bdSJohannes Berg 		case SIOCGIFBRDADDR:
328737ac39bdSJohannes Berg 		case SIOCGIFDSTADDR:
328837ac39bdSJohannes Berg 		case SIOCGIFNETMASK:
328937ac39bdSJohannes Berg 		case SIOCGIFPFLAGS:
329037ac39bdSJohannes Berg 		case SIOCGIFTXQLEN:
329137ac39bdSJohannes Berg 		case SIOCGMIIPHY:
329237ac39bdSJohannes Berg 		case SIOCGMIIREG:
3293c6c9fee3SJohannes Berg 		case SIOCGIFNAME:
329437ac39bdSJohannes Berg 			if (copy_in_user(uifr32, uifr, sizeof(*uifr32)))
329537ac39bdSJohannes Berg 				err = -EFAULT;
329637ac39bdSJohannes Berg 			break;
329737ac39bdSJohannes Berg 		}
329837ac39bdSJohannes Berg 	}
329937ac39bdSJohannes Berg 	return err;
330037ac39bdSJohannes Berg }
330137ac39bdSJohannes Berg 
3302a2116ed2SArnd Bergmann static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
3303a2116ed2SArnd Bergmann 			struct compat_ifreq __user *uifr32)
3304a2116ed2SArnd Bergmann {
3305a2116ed2SArnd Bergmann 	struct ifreq ifr;
3306a2116ed2SArnd Bergmann 	struct compat_ifmap __user *uifmap32;
3307a2116ed2SArnd Bergmann 	int err;
3308a2116ed2SArnd Bergmann 
3309a2116ed2SArnd Bergmann 	uifmap32 = &uifr32->ifr_ifru.ifru_map;
3310a2116ed2SArnd Bergmann 	err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name));
33113ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
33123ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
33133ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
33143ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.irq, &uifmap32->irq);
33153ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.dma, &uifmap32->dma);
33163ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.port, &uifmap32->port);
3317a2116ed2SArnd Bergmann 	if (err)
3318a2116ed2SArnd Bergmann 		return -EFAULT;
3319a2116ed2SArnd Bergmann 
332044c02a2cSAl Viro 	err = dev_ioctl(net, cmd, &ifr, NULL);
3321a2116ed2SArnd Bergmann 
3322a2116ed2SArnd Bergmann 	if (cmd == SIOCGIFMAP && !err) {
33237a229387SArnd Bergmann 		err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name));
33243ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
33253ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
33263ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
33273ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.irq, &uifmap32->irq);
33283ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.dma, &uifmap32->dma);
33293ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.port, &uifmap32->port);
33307a229387SArnd Bergmann 		if (err)
33317a229387SArnd Bergmann 			err = -EFAULT;
33327a229387SArnd Bergmann 	}
33337a229387SArnd Bergmann 	return err;
33347a229387SArnd Bergmann }
33357a229387SArnd Bergmann 
33367a229387SArnd Bergmann struct rtentry32 {
33377a229387SArnd Bergmann 	u32		rt_pad1;
33387a229387SArnd Bergmann 	struct sockaddr rt_dst;         /* target address               */
33397a229387SArnd Bergmann 	struct sockaddr rt_gateway;     /* gateway addr (RTF_GATEWAY)   */
33407a229387SArnd Bergmann 	struct sockaddr rt_genmask;     /* target network mask (IP)     */
33417a229387SArnd Bergmann 	unsigned short	rt_flags;
33427a229387SArnd Bergmann 	short		rt_pad2;
33437a229387SArnd Bergmann 	u32		rt_pad3;
33447a229387SArnd Bergmann 	unsigned char	rt_tos;
33457a229387SArnd Bergmann 	unsigned char	rt_class;
33467a229387SArnd Bergmann 	short		rt_pad4;
33477a229387SArnd Bergmann 	short		rt_metric;      /* +1 for binary compatibility! */
33487a229387SArnd Bergmann 	/* char * */ u32 rt_dev;        /* forcing the device at add    */
33497a229387SArnd Bergmann 	u32		rt_mtu;         /* per route MTU/Window         */
33507a229387SArnd Bergmann 	u32		rt_window;      /* Window clamping              */
33517a229387SArnd Bergmann 	unsigned short  rt_irtt;        /* Initial RTT                  */
33527a229387SArnd Bergmann };
33537a229387SArnd Bergmann 
33547a229387SArnd Bergmann struct in6_rtmsg32 {
33557a229387SArnd Bergmann 	struct in6_addr		rtmsg_dst;
33567a229387SArnd Bergmann 	struct in6_addr		rtmsg_src;
33577a229387SArnd Bergmann 	struct in6_addr		rtmsg_gateway;
33587a229387SArnd Bergmann 	u32			rtmsg_type;
33597a229387SArnd Bergmann 	u16			rtmsg_dst_len;
33607a229387SArnd Bergmann 	u16			rtmsg_src_len;
33617a229387SArnd Bergmann 	u32			rtmsg_metric;
33627a229387SArnd Bergmann 	u32			rtmsg_info;
33637a229387SArnd Bergmann 	u32			rtmsg_flags;
33647a229387SArnd Bergmann 	s32			rtmsg_ifindex;
33657a229387SArnd Bergmann };
33667a229387SArnd Bergmann 
33676b96018bSArnd Bergmann static int routing_ioctl(struct net *net, struct socket *sock,
33686b96018bSArnd Bergmann 			 unsigned int cmd, void __user *argp)
33697a229387SArnd Bergmann {
33707a229387SArnd Bergmann 	int ret;
33717a229387SArnd Bergmann 	void *r = NULL;
33727a229387SArnd Bergmann 	struct in6_rtmsg r6;
33737a229387SArnd Bergmann 	struct rtentry r4;
33747a229387SArnd Bergmann 	char devname[16];
33757a229387SArnd Bergmann 	u32 rtdev;
33767a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
33777a229387SArnd Bergmann 
33786b96018bSArnd Bergmann 	if (sock && sock->sk && sock->sk->sk_family == AF_INET6) { /* ipv6 */
33796b96018bSArnd Bergmann 		struct in6_rtmsg32 __user *ur6 = argp;
33807a229387SArnd Bergmann 		ret = copy_from_user(&r6.rtmsg_dst, &(ur6->rtmsg_dst),
33817a229387SArnd Bergmann 			3 * sizeof(struct in6_addr));
33823ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_type, &(ur6->rtmsg_type));
33833ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len));
33843ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_src_len, &(ur6->rtmsg_src_len));
33853ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_metric, &(ur6->rtmsg_metric));
33863ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_info, &(ur6->rtmsg_info));
33873ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_flags, &(ur6->rtmsg_flags));
33883ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex));
33897a229387SArnd Bergmann 
33907a229387SArnd Bergmann 		r = (void *) &r6;
33917a229387SArnd Bergmann 	} else { /* ipv4 */
33926b96018bSArnd Bergmann 		struct rtentry32 __user *ur4 = argp;
33937a229387SArnd Bergmann 		ret = copy_from_user(&r4.rt_dst, &(ur4->rt_dst),
33947a229387SArnd Bergmann 					3 * sizeof(struct sockaddr));
33953ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_flags, &(ur4->rt_flags));
33963ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_metric, &(ur4->rt_metric));
33973ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_mtu, &(ur4->rt_mtu));
33983ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_window, &(ur4->rt_window));
33993ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_irtt, &(ur4->rt_irtt));
34003ddc5b46SMathieu Desnoyers 		ret |= get_user(rtdev, &(ur4->rt_dev));
34017a229387SArnd Bergmann 		if (rtdev) {
34027a229387SArnd Bergmann 			ret |= copy_from_user(devname, compat_ptr(rtdev), 15);
3403c3f52ae6Sstephen hemminger 			r4.rt_dev = (char __user __force *)devname;
3404c3f52ae6Sstephen hemminger 			devname[15] = 0;
34057a229387SArnd Bergmann 		} else
34067a229387SArnd Bergmann 			r4.rt_dev = NULL;
34077a229387SArnd Bergmann 
34087a229387SArnd Bergmann 		r = (void *) &r4;
34097a229387SArnd Bergmann 	}
34107a229387SArnd Bergmann 
34117a229387SArnd Bergmann 	if (ret) {
34127a229387SArnd Bergmann 		ret = -EFAULT;
34137a229387SArnd Bergmann 		goto out;
34147a229387SArnd Bergmann 	}
34157a229387SArnd Bergmann 
34167a229387SArnd Bergmann 	set_fs(KERNEL_DS);
341763ff03abSJohannes Berg 	ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r);
34187a229387SArnd Bergmann 	set_fs(old_fs);
34197a229387SArnd Bergmann 
34207a229387SArnd Bergmann out:
34217a229387SArnd Bergmann 	return ret;
34227a229387SArnd Bergmann }
34237a229387SArnd Bergmann 
34247a229387SArnd Bergmann /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE
34257a229387SArnd Bergmann  * for some operations; this forces use of the newer bridge-utils that
342625985edcSLucas De Marchi  * use compatible ioctls
34277a229387SArnd Bergmann  */
34286b96018bSArnd Bergmann static int old_bridge_ioctl(compat_ulong_t __user *argp)
34297a229387SArnd Bergmann {
34306b96018bSArnd Bergmann 	compat_ulong_t tmp;
34317a229387SArnd Bergmann 
34326b96018bSArnd Bergmann 	if (get_user(tmp, argp))
34337a229387SArnd Bergmann 		return -EFAULT;
34347a229387SArnd Bergmann 	if (tmp == BRCTL_GET_VERSION)
34357a229387SArnd Bergmann 		return BRCTL_VERSION + 1;
34367a229387SArnd Bergmann 	return -EINVAL;
34377a229387SArnd Bergmann }
34387a229387SArnd Bergmann 
34396b96018bSArnd Bergmann static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
34406b96018bSArnd Bergmann 			 unsigned int cmd, unsigned long arg)
34416b96018bSArnd Bergmann {
34426b96018bSArnd Bergmann 	void __user *argp = compat_ptr(arg);
34436b96018bSArnd Bergmann 	struct sock *sk = sock->sk;
34446b96018bSArnd Bergmann 	struct net *net = sock_net(sk);
34457a229387SArnd Bergmann 
34466b96018bSArnd Bergmann 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
3447590d4693SBen Hutchings 		return compat_ifr_data_ioctl(net, cmd, argp);
34487a229387SArnd Bergmann 
34496b96018bSArnd Bergmann 	switch (cmd) {
34506b96018bSArnd Bergmann 	case SIOCSIFBR:
34516b96018bSArnd Bergmann 	case SIOCGIFBR:
34526b96018bSArnd Bergmann 		return old_bridge_ioctl(argp);
34536b96018bSArnd Bergmann 	case SIOCGIFCONF:
345436fd633eSAl Viro 		return compat_dev_ifconf(net, argp);
34556b96018bSArnd Bergmann 	case SIOCETHTOOL:
34566b96018bSArnd Bergmann 		return ethtool_ioctl(net, argp);
34577a50a240SArnd Bergmann 	case SIOCWANDEV:
34587a50a240SArnd Bergmann 		return compat_siocwandev(net, argp);
3459a2116ed2SArnd Bergmann 	case SIOCGIFMAP:
3460a2116ed2SArnd Bergmann 	case SIOCSIFMAP:
3461a2116ed2SArnd Bergmann 		return compat_sioc_ifmap(net, cmd, argp);
34626b96018bSArnd Bergmann 	case SIOCADDRT:
34636b96018bSArnd Bergmann 	case SIOCDELRT:
34646b96018bSArnd Bergmann 		return routing_ioctl(net, sock, cmd, argp);
34650768e170SArnd Bergmann 	case SIOCGSTAMP_OLD:
34660768e170SArnd Bergmann 	case SIOCGSTAMPNS_OLD:
3467c7cbdbf2SArnd Bergmann 		if (!sock->ops->gettstamp)
3468c7cbdbf2SArnd Bergmann 			return -ENOIOCTLCMD;
34690768e170SArnd Bergmann 		return sock->ops->gettstamp(sock, argp, cmd == SIOCGSTAMP_OLD,
3470c7cbdbf2SArnd Bergmann 					    !COMPAT_USE_64BIT_TIME);
3471c7cbdbf2SArnd Bergmann 
3472590d4693SBen Hutchings 	case SIOCBONDSLAVEINFOQUERY:
3473590d4693SBen Hutchings 	case SIOCBONDINFOQUERY:
3474a2116ed2SArnd Bergmann 	case SIOCSHWTSTAMP:
3475fd468c74SBen Hutchings 	case SIOCGHWTSTAMP:
3476590d4693SBen Hutchings 		return compat_ifr_data_ioctl(net, cmd, argp);
34777a229387SArnd Bergmann 
34786b96018bSArnd Bergmann 	case FIOSETOWN:
34796b96018bSArnd Bergmann 	case SIOCSPGRP:
34806b96018bSArnd Bergmann 	case FIOGETOWN:
34816b96018bSArnd Bergmann 	case SIOCGPGRP:
34826b96018bSArnd Bergmann 	case SIOCBRADDBR:
34836b96018bSArnd Bergmann 	case SIOCBRDELBR:
34846b96018bSArnd Bergmann 	case SIOCGIFVLAN:
34856b96018bSArnd Bergmann 	case SIOCSIFVLAN:
34866b96018bSArnd Bergmann 	case SIOCADDDLCI:
34876b96018bSArnd Bergmann 	case SIOCDELDLCI:
3488c62cce2cSAndrey Vagin 	case SIOCGSKNS:
34890768e170SArnd Bergmann 	case SIOCGSTAMP_NEW:
34900768e170SArnd Bergmann 	case SIOCGSTAMPNS_NEW:
34916b96018bSArnd Bergmann 		return sock_ioctl(file, cmd, arg);
34926b96018bSArnd Bergmann 
34936b96018bSArnd Bergmann 	case SIOCGIFFLAGS:
34946b96018bSArnd Bergmann 	case SIOCSIFFLAGS:
34956b96018bSArnd Bergmann 	case SIOCGIFMETRIC:
34966b96018bSArnd Bergmann 	case SIOCSIFMETRIC:
34976b96018bSArnd Bergmann 	case SIOCGIFMTU:
34986b96018bSArnd Bergmann 	case SIOCSIFMTU:
34996b96018bSArnd Bergmann 	case SIOCGIFMEM:
35006b96018bSArnd Bergmann 	case SIOCSIFMEM:
35016b96018bSArnd Bergmann 	case SIOCGIFHWADDR:
35026b96018bSArnd Bergmann 	case SIOCSIFHWADDR:
35036b96018bSArnd Bergmann 	case SIOCADDMULTI:
35046b96018bSArnd Bergmann 	case SIOCDELMULTI:
35056b96018bSArnd Bergmann 	case SIOCGIFINDEX:
35066b96018bSArnd Bergmann 	case SIOCGIFADDR:
35076b96018bSArnd Bergmann 	case SIOCSIFADDR:
35086b96018bSArnd Bergmann 	case SIOCSIFHWBROADCAST:
35096b96018bSArnd Bergmann 	case SIOCDIFADDR:
35106b96018bSArnd Bergmann 	case SIOCGIFBRDADDR:
35116b96018bSArnd Bergmann 	case SIOCSIFBRDADDR:
35126b96018bSArnd Bergmann 	case SIOCGIFDSTADDR:
35136b96018bSArnd Bergmann 	case SIOCSIFDSTADDR:
35146b96018bSArnd Bergmann 	case SIOCGIFNETMASK:
35156b96018bSArnd Bergmann 	case SIOCSIFNETMASK:
35166b96018bSArnd Bergmann 	case SIOCSIFPFLAGS:
35176b96018bSArnd Bergmann 	case SIOCGIFPFLAGS:
35186b96018bSArnd Bergmann 	case SIOCGIFTXQLEN:
35196b96018bSArnd Bergmann 	case SIOCSIFTXQLEN:
35206b96018bSArnd Bergmann 	case SIOCBRADDIF:
35216b96018bSArnd Bergmann 	case SIOCBRDELIF:
3522c6c9fee3SJohannes Berg 	case SIOCGIFNAME:
35239177efd3SArnd Bergmann 	case SIOCSIFNAME:
35249177efd3SArnd Bergmann 	case SIOCGMIIPHY:
35259177efd3SArnd Bergmann 	case SIOCGMIIREG:
35269177efd3SArnd Bergmann 	case SIOCSMIIREG:
3527f92d4fc9SAl Viro 	case SIOCBONDENSLAVE:
3528f92d4fc9SAl Viro 	case SIOCBONDRELEASE:
3529f92d4fc9SAl Viro 	case SIOCBONDSETHWADDR:
3530f92d4fc9SAl Viro 	case SIOCBONDCHANGEACTIVE:
353137ac39bdSJohannes Berg 		return compat_ifreq_ioctl(net, sock, cmd, argp);
353237ac39bdSJohannes Berg 
35336b96018bSArnd Bergmann 	case SIOCSARP:
35346b96018bSArnd Bergmann 	case SIOCGARP:
35356b96018bSArnd Bergmann 	case SIOCDARP:
35366b96018bSArnd Bergmann 	case SIOCATMARK:
353763ff03abSJohannes Berg 		return sock_do_ioctl(net, sock, cmd, arg);
35389177efd3SArnd Bergmann 	}
35399177efd3SArnd Bergmann 
35406b96018bSArnd Bergmann 	return -ENOIOCTLCMD;
35416b96018bSArnd Bergmann }
35427a229387SArnd Bergmann 
354395c96174SEric Dumazet static long compat_sock_ioctl(struct file *file, unsigned int cmd,
354489bbfc95SShaun Pereira 			      unsigned long arg)
354589bbfc95SShaun Pereira {
354689bbfc95SShaun Pereira 	struct socket *sock = file->private_data;
354789bbfc95SShaun Pereira 	int ret = -ENOIOCTLCMD;
354887de87d5SDavid S. Miller 	struct sock *sk;
354987de87d5SDavid S. Miller 	struct net *net;
355087de87d5SDavid S. Miller 
355187de87d5SDavid S. Miller 	sk = sock->sk;
355287de87d5SDavid S. Miller 	net = sock_net(sk);
355389bbfc95SShaun Pereira 
355489bbfc95SShaun Pereira 	if (sock->ops->compat_ioctl)
355589bbfc95SShaun Pereira 		ret = sock->ops->compat_ioctl(sock, cmd, arg);
355689bbfc95SShaun Pereira 
355787de87d5SDavid S. Miller 	if (ret == -ENOIOCTLCMD &&
355887de87d5SDavid S. Miller 	    (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST))
355987de87d5SDavid S. Miller 		ret = compat_wext_handle_ioctl(net, cmd, arg);
356087de87d5SDavid S. Miller 
35616b96018bSArnd Bergmann 	if (ret == -ENOIOCTLCMD)
35626b96018bSArnd Bergmann 		ret = compat_sock_ioctl_trans(file, sock, cmd, arg);
35636b96018bSArnd Bergmann 
356489bbfc95SShaun Pereira 	return ret;
356589bbfc95SShaun Pereira }
356689bbfc95SShaun Pereira #endif
356789bbfc95SShaun Pereira 
35688a3c245cSPedro Tammela /**
35698a3c245cSPedro Tammela  *	kernel_bind - bind an address to a socket (kernel space)
35708a3c245cSPedro Tammela  *	@sock: socket
35718a3c245cSPedro Tammela  *	@addr: address
35728a3c245cSPedro Tammela  *	@addrlen: length of address
35738a3c245cSPedro Tammela  *
35748a3c245cSPedro Tammela  *	Returns 0 or an error.
35758a3c245cSPedro Tammela  */
35768a3c245cSPedro Tammela 
3577ac5a488eSSridhar Samudrala int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
3578ac5a488eSSridhar Samudrala {
3579ac5a488eSSridhar Samudrala 	return sock->ops->bind(sock, addr, addrlen);
3580ac5a488eSSridhar Samudrala }
3581c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_bind);
3582ac5a488eSSridhar Samudrala 
35838a3c245cSPedro Tammela /**
35848a3c245cSPedro Tammela  *	kernel_listen - move socket to listening state (kernel space)
35858a3c245cSPedro Tammela  *	@sock: socket
35868a3c245cSPedro Tammela  *	@backlog: pending connections queue size
35878a3c245cSPedro Tammela  *
35888a3c245cSPedro Tammela  *	Returns 0 or an error.
35898a3c245cSPedro Tammela  */
35908a3c245cSPedro Tammela 
3591ac5a488eSSridhar Samudrala int kernel_listen(struct socket *sock, int backlog)
3592ac5a488eSSridhar Samudrala {
3593ac5a488eSSridhar Samudrala 	return sock->ops->listen(sock, backlog);
3594ac5a488eSSridhar Samudrala }
3595c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_listen);
3596ac5a488eSSridhar Samudrala 
35978a3c245cSPedro Tammela /**
35988a3c245cSPedro Tammela  *	kernel_accept - accept a connection (kernel space)
35998a3c245cSPedro Tammela  *	@sock: listening socket
36008a3c245cSPedro Tammela  *	@newsock: new connected socket
36018a3c245cSPedro Tammela  *	@flags: flags
36028a3c245cSPedro Tammela  *
36038a3c245cSPedro Tammela  *	@flags must be SOCK_CLOEXEC, SOCK_NONBLOCK or 0.
36048a3c245cSPedro Tammela  *	If it fails, @newsock is guaranteed to be %NULL.
36058a3c245cSPedro Tammela  *	Returns 0 or an error.
36068a3c245cSPedro Tammela  */
36078a3c245cSPedro Tammela 
3608ac5a488eSSridhar Samudrala int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
3609ac5a488eSSridhar Samudrala {
3610ac5a488eSSridhar Samudrala 	struct sock *sk = sock->sk;
3611ac5a488eSSridhar Samudrala 	int err;
3612ac5a488eSSridhar Samudrala 
3613ac5a488eSSridhar Samudrala 	err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
3614ac5a488eSSridhar Samudrala 			       newsock);
3615ac5a488eSSridhar Samudrala 	if (err < 0)
3616ac5a488eSSridhar Samudrala 		goto done;
3617ac5a488eSSridhar Samudrala 
3618cdfbabfbSDavid Howells 	err = sock->ops->accept(sock, *newsock, flags, true);
3619ac5a488eSSridhar Samudrala 	if (err < 0) {
3620ac5a488eSSridhar Samudrala 		sock_release(*newsock);
3621fa8705b0STony Battersby 		*newsock = NULL;
3622ac5a488eSSridhar Samudrala 		goto done;
3623ac5a488eSSridhar Samudrala 	}
3624ac5a488eSSridhar Samudrala 
3625ac5a488eSSridhar Samudrala 	(*newsock)->ops = sock->ops;
36261b08534eSWei Yongjun 	__module_get((*newsock)->ops->owner);
3627ac5a488eSSridhar Samudrala 
3628ac5a488eSSridhar Samudrala done:
3629ac5a488eSSridhar Samudrala 	return err;
3630ac5a488eSSridhar Samudrala }
3631c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_accept);
3632ac5a488eSSridhar Samudrala 
36338a3c245cSPedro Tammela /**
36348a3c245cSPedro Tammela  *	kernel_connect - connect a socket (kernel space)
36358a3c245cSPedro Tammela  *	@sock: socket
36368a3c245cSPedro Tammela  *	@addr: address
36378a3c245cSPedro Tammela  *	@addrlen: address length
36388a3c245cSPedro Tammela  *	@flags: flags (O_NONBLOCK, ...)
36398a3c245cSPedro Tammela  *
36408a3c245cSPedro Tammela  *	For datagram sockets, @addr is the addres to which datagrams are sent
36418a3c245cSPedro Tammela  *	by default, and the only address from which datagrams are received.
36428a3c245cSPedro Tammela  *	For stream sockets, attempts to connect to @addr.
36438a3c245cSPedro Tammela  *	Returns 0 or an error code.
36448a3c245cSPedro Tammela  */
36458a3c245cSPedro Tammela 
3646ac5a488eSSridhar Samudrala int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
3647ac5a488eSSridhar Samudrala 		   int flags)
3648ac5a488eSSridhar Samudrala {
3649ac5a488eSSridhar Samudrala 	return sock->ops->connect(sock, addr, addrlen, flags);
3650ac5a488eSSridhar Samudrala }
3651c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_connect);
3652ac5a488eSSridhar Samudrala 
36538a3c245cSPedro Tammela /**
36548a3c245cSPedro Tammela  *	kernel_getsockname - get the address which the socket is bound (kernel space)
36558a3c245cSPedro Tammela  *	@sock: socket
36568a3c245cSPedro Tammela  *	@addr: address holder
36578a3c245cSPedro Tammela  *
36588a3c245cSPedro Tammela  * 	Fills the @addr pointer with the address which the socket is bound.
36598a3c245cSPedro Tammela  *	Returns 0 or an error code.
36608a3c245cSPedro Tammela  */
36618a3c245cSPedro Tammela 
36629b2c45d4SDenys Vlasenko int kernel_getsockname(struct socket *sock, struct sockaddr *addr)
3663ac5a488eSSridhar Samudrala {
36649b2c45d4SDenys Vlasenko 	return sock->ops->getname(sock, addr, 0);
3665ac5a488eSSridhar Samudrala }
3666c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockname);
3667ac5a488eSSridhar Samudrala 
36688a3c245cSPedro Tammela /**
36698a3c245cSPedro Tammela  *	kernel_peername - get the address which the socket is connected (kernel space)
36708a3c245cSPedro Tammela  *	@sock: socket
36718a3c245cSPedro Tammela  *	@addr: address holder
36728a3c245cSPedro Tammela  *
36738a3c245cSPedro Tammela  * 	Fills the @addr pointer with the address which the socket is connected.
36748a3c245cSPedro Tammela  *	Returns 0 or an error code.
36758a3c245cSPedro Tammela  */
36768a3c245cSPedro Tammela 
36779b2c45d4SDenys Vlasenko int kernel_getpeername(struct socket *sock, struct sockaddr *addr)
3678ac5a488eSSridhar Samudrala {
36799b2c45d4SDenys Vlasenko 	return sock->ops->getname(sock, addr, 1);
3680ac5a488eSSridhar Samudrala }
3681c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getpeername);
3682ac5a488eSSridhar Samudrala 
36838a3c245cSPedro Tammela /**
36848a3c245cSPedro Tammela  *	kernel_getsockopt - get a socket option (kernel space)
36858a3c245cSPedro Tammela  *	@sock: socket
36868a3c245cSPedro Tammela  *	@level: API level (SOL_SOCKET, ...)
36878a3c245cSPedro Tammela  *	@optname: option tag
36888a3c245cSPedro Tammela  *	@optval: option value
36898a3c245cSPedro Tammela  *	@optlen: option length
36908a3c245cSPedro Tammela  *
36918a3c245cSPedro Tammela  *	Assigns the option length to @optlen.
36928a3c245cSPedro Tammela  *	Returns 0 or an error.
36938a3c245cSPedro Tammela  */
36948a3c245cSPedro Tammela 
3695ac5a488eSSridhar Samudrala int kernel_getsockopt(struct socket *sock, int level, int optname,
3696ac5a488eSSridhar Samudrala 			char *optval, int *optlen)
3697ac5a488eSSridhar Samudrala {
3698ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3699fb8621bbSNamhyung Kim 	char __user *uoptval;
3700fb8621bbSNamhyung Kim 	int __user *uoptlen;
3701ac5a488eSSridhar Samudrala 	int err;
3702ac5a488eSSridhar Samudrala 
3703fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3704fb8621bbSNamhyung Kim 	uoptlen = (int __user __force *) optlen;
3705fb8621bbSNamhyung Kim 
3706ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3707ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3708fb8621bbSNamhyung Kim 		err = sock_getsockopt(sock, level, optname, uoptval, uoptlen);
3709ac5a488eSSridhar Samudrala 	else
3710fb8621bbSNamhyung Kim 		err = sock->ops->getsockopt(sock, level, optname, uoptval,
3711fb8621bbSNamhyung Kim 					    uoptlen);
3712ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3713ac5a488eSSridhar Samudrala 	return err;
3714ac5a488eSSridhar Samudrala }
3715c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockopt);
3716ac5a488eSSridhar Samudrala 
37178a3c245cSPedro Tammela /**
37188a3c245cSPedro Tammela  *	kernel_setsockopt - set a socket option (kernel space)
37198a3c245cSPedro Tammela  *	@sock: socket
37208a3c245cSPedro Tammela  *	@level: API level (SOL_SOCKET, ...)
37218a3c245cSPedro Tammela  *	@optname: option tag
37228a3c245cSPedro Tammela  *	@optval: option value
37238a3c245cSPedro Tammela  *	@optlen: option length
37248a3c245cSPedro Tammela  *
37258a3c245cSPedro Tammela  *	Returns 0 or an error.
37268a3c245cSPedro Tammela  */
37278a3c245cSPedro Tammela 
3728ac5a488eSSridhar Samudrala int kernel_setsockopt(struct socket *sock, int level, int optname,
3729b7058842SDavid S. Miller 			char *optval, unsigned int optlen)
3730ac5a488eSSridhar Samudrala {
3731ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3732fb8621bbSNamhyung Kim 	char __user *uoptval;
3733ac5a488eSSridhar Samudrala 	int err;
3734ac5a488eSSridhar Samudrala 
3735fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3736fb8621bbSNamhyung Kim 
3737ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3738ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3739fb8621bbSNamhyung Kim 		err = sock_setsockopt(sock, level, optname, uoptval, optlen);
3740ac5a488eSSridhar Samudrala 	else
3741fb8621bbSNamhyung Kim 		err = sock->ops->setsockopt(sock, level, optname, uoptval,
3742ac5a488eSSridhar Samudrala 					    optlen);
3743ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3744ac5a488eSSridhar Samudrala 	return err;
3745ac5a488eSSridhar Samudrala }
3746c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_setsockopt);
3747ac5a488eSSridhar Samudrala 
37488a3c245cSPedro Tammela /**
37498a3c245cSPedro Tammela  *	kernel_sendpage - send a &page through a socket (kernel space)
37508a3c245cSPedro Tammela  *	@sock: socket
37518a3c245cSPedro Tammela  *	@page: page
37528a3c245cSPedro Tammela  *	@offset: page offset
37538a3c245cSPedro Tammela  *	@size: total size in bytes
37548a3c245cSPedro Tammela  *	@flags: flags (MSG_DONTWAIT, ...)
37558a3c245cSPedro Tammela  *
37568a3c245cSPedro Tammela  *	Returns the total amount sent in bytes or an error.
37578a3c245cSPedro Tammela  */
37588a3c245cSPedro Tammela 
3759ac5a488eSSridhar Samudrala int kernel_sendpage(struct socket *sock, struct page *page, int offset,
3760ac5a488eSSridhar Samudrala 		    size_t size, int flags)
3761ac5a488eSSridhar Samudrala {
3762ac5a488eSSridhar Samudrala 	if (sock->ops->sendpage)
3763ac5a488eSSridhar Samudrala 		return sock->ops->sendpage(sock, page, offset, size, flags);
3764ac5a488eSSridhar Samudrala 
3765ac5a488eSSridhar Samudrala 	return sock_no_sendpage(sock, page, offset, size, flags);
3766ac5a488eSSridhar Samudrala }
3767c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendpage);
3768ac5a488eSSridhar Samudrala 
37698a3c245cSPedro Tammela /**
37708a3c245cSPedro Tammela  *	kernel_sendpage_locked - send a &page through the locked sock (kernel space)
37718a3c245cSPedro Tammela  *	@sk: sock
37728a3c245cSPedro Tammela  *	@page: page
37738a3c245cSPedro Tammela  *	@offset: page offset
37748a3c245cSPedro Tammela  *	@size: total size in bytes
37758a3c245cSPedro Tammela  *	@flags: flags (MSG_DONTWAIT, ...)
37768a3c245cSPedro Tammela  *
37778a3c245cSPedro Tammela  *	Returns the total amount sent in bytes or an error.
37788a3c245cSPedro Tammela  *	Caller must hold @sk.
37798a3c245cSPedro Tammela  */
37808a3c245cSPedro Tammela 
3781306b13ebSTom Herbert int kernel_sendpage_locked(struct sock *sk, struct page *page, int offset,
3782306b13ebSTom Herbert 			   size_t size, int flags)
3783306b13ebSTom Herbert {
3784306b13ebSTom Herbert 	struct socket *sock = sk->sk_socket;
3785306b13ebSTom Herbert 
3786306b13ebSTom Herbert 	if (sock->ops->sendpage_locked)
3787306b13ebSTom Herbert 		return sock->ops->sendpage_locked(sk, page, offset, size,
3788306b13ebSTom Herbert 						  flags);
3789306b13ebSTom Herbert 
3790306b13ebSTom Herbert 	return sock_no_sendpage_locked(sk, page, offset, size, flags);
3791306b13ebSTom Herbert }
3792306b13ebSTom Herbert EXPORT_SYMBOL(kernel_sendpage_locked);
3793306b13ebSTom Herbert 
37948a3c245cSPedro Tammela /**
37958a3c245cSPedro Tammela  *	kernel_shutdown - shut down part of a full-duplex connection (kernel space)
37968a3c245cSPedro Tammela  *	@sock: socket
37978a3c245cSPedro Tammela  *	@how: connection part
37988a3c245cSPedro Tammela  *
37998a3c245cSPedro Tammela  *	Returns 0 or an error.
38008a3c245cSPedro Tammela  */
38018a3c245cSPedro Tammela 
380291cf45f0STrond Myklebust int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
380391cf45f0STrond Myklebust {
380491cf45f0STrond Myklebust 	return sock->ops->shutdown(sock, how);
380591cf45f0STrond Myklebust }
380691cf45f0STrond Myklebust EXPORT_SYMBOL(kernel_sock_shutdown);
3807113c3075SR. Parameswaran 
38088a3c245cSPedro Tammela /**
38098a3c245cSPedro Tammela  *	kernel_sock_ip_overhead - returns the IP overhead imposed by a socket
38108a3c245cSPedro Tammela  *	@sk: socket
38118a3c245cSPedro Tammela  *
38128a3c245cSPedro Tammela  *	This routine returns the IP overhead imposed by a socket i.e.
3813113c3075SR. Parameswaran  *	the length of the underlying IP header, depending on whether
3814113c3075SR. Parameswaran  *	this is an IPv4 or IPv6 socket and the length from IP options turned
381557240d00SR. Parameswaran  *	on at the socket. Assumes that the caller has a lock on the socket.
3816113c3075SR. Parameswaran  */
38178a3c245cSPedro Tammela 
3818113c3075SR. Parameswaran u32 kernel_sock_ip_overhead(struct sock *sk)
3819113c3075SR. Parameswaran {
3820113c3075SR. Parameswaran 	struct inet_sock *inet;
3821113c3075SR. Parameswaran 	struct ip_options_rcu *opt;
3822113c3075SR. Parameswaran 	u32 overhead = 0;
3823113c3075SR. Parameswaran #if IS_ENABLED(CONFIG_IPV6)
3824113c3075SR. Parameswaran 	struct ipv6_pinfo *np;
3825113c3075SR. Parameswaran 	struct ipv6_txoptions *optv6 = NULL;
3826113c3075SR. Parameswaran #endif /* IS_ENABLED(CONFIG_IPV6) */
3827113c3075SR. Parameswaran 
3828113c3075SR. Parameswaran 	if (!sk)
3829113c3075SR. Parameswaran 		return overhead;
3830113c3075SR. Parameswaran 
3831113c3075SR. Parameswaran 	switch (sk->sk_family) {
3832113c3075SR. Parameswaran 	case AF_INET:
3833113c3075SR. Parameswaran 		inet = inet_sk(sk);
3834113c3075SR. Parameswaran 		overhead += sizeof(struct iphdr);
3835113c3075SR. Parameswaran 		opt = rcu_dereference_protected(inet->inet_opt,
3836614d79c0Sstephen hemminger 						sock_owned_by_user(sk));
3837113c3075SR. Parameswaran 		if (opt)
3838113c3075SR. Parameswaran 			overhead += opt->opt.optlen;
3839113c3075SR. Parameswaran 		return overhead;
3840113c3075SR. Parameswaran #if IS_ENABLED(CONFIG_IPV6)
3841113c3075SR. Parameswaran 	case AF_INET6:
3842113c3075SR. Parameswaran 		np = inet6_sk(sk);
3843113c3075SR. Parameswaran 		overhead += sizeof(struct ipv6hdr);
3844113c3075SR. Parameswaran 		if (np)
3845113c3075SR. Parameswaran 			optv6 = rcu_dereference_protected(np->opt,
3846614d79c0Sstephen hemminger 							  sock_owned_by_user(sk));
3847113c3075SR. Parameswaran 		if (optv6)
3848113c3075SR. Parameswaran 			overhead += (optv6->opt_flen + optv6->opt_nflen);
3849113c3075SR. Parameswaran 		return overhead;
3850113c3075SR. Parameswaran #endif /* IS_ENABLED(CONFIG_IPV6) */
3851113c3075SR. Parameswaran 	default: /* Returns 0 overhead if the socket is not ipv4 or ipv6 */
3852113c3075SR. Parameswaran 		return overhead;
3853113c3075SR. Parameswaran 	}
3854113c3075SR. Parameswaran }
3855113c3075SR. Parameswaran EXPORT_SYMBOL(kernel_sock_ip_overhead);
3856