xref: /openbmc/linux/net/socket.c (revision 6d8c50dc)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * NET		An implementation of the SOCKET network access protocol.
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Version:	@(#)socket.c	1.1.93	18/02/95
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * Authors:	Orest Zborowski, <obz@Kodak.COM>
702c30a84SJesper Juhl  *		Ross Biro
81da177e4SLinus Torvalds  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
91da177e4SLinus Torvalds  *
101da177e4SLinus Torvalds  * Fixes:
111da177e4SLinus Torvalds  *		Anonymous	:	NOTSOCK/BADF cleanup. Error fix in
121da177e4SLinus Torvalds  *					shutdown()
131da177e4SLinus Torvalds  *		Alan Cox	:	verify_area() fixes
141da177e4SLinus Torvalds  *		Alan Cox	:	Removed DDI
151da177e4SLinus Torvalds  *		Jonathan Kamens	:	SOCK_DGRAM reconnect bug
161da177e4SLinus Torvalds  *		Alan Cox	:	Moved a load of checks to the very
171da177e4SLinus Torvalds  *					top level.
181da177e4SLinus Torvalds  *		Alan Cox	:	Move address structures to/from user
191da177e4SLinus Torvalds  *					mode above the protocol layers.
201da177e4SLinus Torvalds  *		Rob Janssen	:	Allow 0 length sends.
211da177e4SLinus Torvalds  *		Alan Cox	:	Asynchronous I/O support (cribbed from the
221da177e4SLinus Torvalds  *					tty drivers).
231da177e4SLinus Torvalds  *		Niibe Yutaka	:	Asynchronous I/O for writes (4.4BSD style)
241da177e4SLinus Torvalds  *		Jeff Uphoff	:	Made max number of sockets command-line
251da177e4SLinus Torvalds  *					configurable.
261da177e4SLinus Torvalds  *		Matti Aarnio	:	Made the number of sockets dynamic,
271da177e4SLinus Torvalds  *					to be allocated when needed, and mr.
281da177e4SLinus Torvalds  *					Uphoff's max is used as max to be
291da177e4SLinus Torvalds  *					allowed to allocate.
301da177e4SLinus Torvalds  *		Linus		:	Argh. removed all the socket allocation
311da177e4SLinus Torvalds  *					altogether: it's in the inode now.
321da177e4SLinus Torvalds  *		Alan Cox	:	Made sock_alloc()/sock_release() public
331da177e4SLinus Torvalds  *					for NetROM and future kernel nfsd type
341da177e4SLinus Torvalds  *					stuff.
351da177e4SLinus Torvalds  *		Alan Cox	:	sendmsg/recvmsg basics.
361da177e4SLinus Torvalds  *		Tom Dyas	:	Export net symbols.
371da177e4SLinus Torvalds  *		Marcin Dalecki	:	Fixed problems with CONFIG_NET="n".
381da177e4SLinus Torvalds  *		Alan Cox	:	Added thread locking to sys_* calls
391da177e4SLinus Torvalds  *					for sockets. May have errors at the
401da177e4SLinus Torvalds  *					moment.
411da177e4SLinus Torvalds  *		Kevin Buhr	:	Fixed the dumb errors in the above.
421da177e4SLinus Torvalds  *		Andi Kleen	:	Some small cleanups, optimizations,
431da177e4SLinus Torvalds  *					and fixed a copy_from_user() bug.
441da177e4SLinus Torvalds  *		Tigran Aivazian	:	sys_send(args) calls sys_sendto(args, NULL, 0)
451da177e4SLinus Torvalds  *		Tigran Aivazian	:	Made listen(2) backlog sanity checks
461da177e4SLinus Torvalds  *					protocol-independent
471da177e4SLinus Torvalds  *
481da177e4SLinus Torvalds  *
491da177e4SLinus Torvalds  *		This program is free software; you can redistribute it and/or
501da177e4SLinus Torvalds  *		modify it under the terms of the GNU General Public License
511da177e4SLinus Torvalds  *		as published by the Free Software Foundation; either version
521da177e4SLinus Torvalds  *		2 of the License, or (at your option) any later version.
531da177e4SLinus Torvalds  *
541da177e4SLinus Torvalds  *
551da177e4SLinus Torvalds  *	This module is effectively the top level interface to the BSD socket
561da177e4SLinus Torvalds  *	paradigm.
571da177e4SLinus Torvalds  *
581da177e4SLinus Torvalds  *	Based upon Swansea University Computer Society NET3.039
591da177e4SLinus Torvalds  */
601da177e4SLinus Torvalds 
611da177e4SLinus Torvalds #include <linux/mm.h>
621da177e4SLinus Torvalds #include <linux/socket.h>
631da177e4SLinus Torvalds #include <linux/file.h>
641da177e4SLinus Torvalds #include <linux/net.h>
651da177e4SLinus Torvalds #include <linux/interrupt.h>
66aaca0bdcSUlrich Drepper #include <linux/thread_info.h>
6755737fdaSStephen Hemminger #include <linux/rcupdate.h>
681da177e4SLinus Torvalds #include <linux/netdevice.h>
691da177e4SLinus Torvalds #include <linux/proc_fs.h>
701da177e4SLinus Torvalds #include <linux/seq_file.h>
714a3e2f71SArjan van de Ven #include <linux/mutex.h>
721da177e4SLinus Torvalds #include <linux/if_bridge.h>
7320380731SArnaldo Carvalho de Melo #include <linux/if_frad.h>
7420380731SArnaldo Carvalho de Melo #include <linux/if_vlan.h>
75408eccceSDaniel Borkmann #include <linux/ptp_classify.h>
761da177e4SLinus Torvalds #include <linux/init.h>
771da177e4SLinus Torvalds #include <linux/poll.h>
781da177e4SLinus Torvalds #include <linux/cache.h>
791da177e4SLinus Torvalds #include <linux/module.h>
801da177e4SLinus Torvalds #include <linux/highmem.h>
811da177e4SLinus Torvalds #include <linux/mount.h>
821da177e4SLinus Torvalds #include <linux/security.h>
831da177e4SLinus Torvalds #include <linux/syscalls.h>
841da177e4SLinus Torvalds #include <linux/compat.h>
851da177e4SLinus Torvalds #include <linux/kmod.h>
863ec3b2fbSDavid Woodhouse #include <linux/audit.h>
87d86b5e0eSAdrian Bunk #include <linux/wireless.h>
881b8d7ae4SEric W. Biederman #include <linux/nsproxy.h>
891fd7317dSNick Black #include <linux/magic.h>
905a0e3ad6STejun Heo #include <linux/slab.h>
91600e1779SMasatake YAMATO #include <linux/xattr.h>
921da177e4SLinus Torvalds 
937c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
941da177e4SLinus Torvalds #include <asm/unistd.h>
951da177e4SLinus Torvalds 
961da177e4SLinus Torvalds #include <net/compat.h>
9787de87d5SDavid S. Miller #include <net/wext.h>
98f8451725SHerbert Xu #include <net/cls_cgroup.h>
991da177e4SLinus Torvalds 
1001da177e4SLinus Torvalds #include <net/sock.h>
1011da177e4SLinus Torvalds #include <linux/netfilter.h>
1021da177e4SLinus Torvalds 
1036b96018bSArnd Bergmann #include <linux/if_tun.h>
1046b96018bSArnd Bergmann #include <linux/ipv6_route.h>
1056b96018bSArnd Bergmann #include <linux/route.h>
1066b96018bSArnd Bergmann #include <linux/sockios.h>
107076bb0c8SEliezer Tamir #include <net/busy_poll.h>
108f24b9be5SWillem de Bruijn #include <linux/errqueue.h>
10906021292SEliezer Tamir 
110e0d1095aSCong Wang #ifdef CONFIG_NET_RX_BUSY_POLL
11164b0dc51SEliezer Tamir unsigned int sysctl_net_busy_read __read_mostly;
11264b0dc51SEliezer Tamir unsigned int sysctl_net_busy_poll __read_mostly;
11306021292SEliezer Tamir #endif
1146b96018bSArnd Bergmann 
1158ae5e030SAl Viro static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to);
1168ae5e030SAl Viro static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from);
1171da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma);
1181da177e4SLinus Torvalds 
1191da177e4SLinus Torvalds static int sock_close(struct inode *inode, struct file *file);
12015252423SChristoph Hellwig static struct wait_queue_head *sock_get_poll_head(struct file *file,
12115252423SChristoph Hellwig 		__poll_t events);
12215252423SChristoph Hellwig static __poll_t sock_poll_mask(struct file *file, __poll_t);
12315252423SChristoph Hellwig static __poll_t sock_poll(struct file *file, struct poll_table_struct *wait);
12489bddce5SStephen Hemminger static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
12589bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
12689bbfc95SShaun Pereira static long compat_sock_ioctl(struct file *file,
12789bbfc95SShaun Pereira 			      unsigned int cmd, unsigned long arg);
12889bbfc95SShaun Pereira #endif
1291da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on);
1301da177e4SLinus Torvalds static ssize_t sock_sendpage(struct file *file, struct page *page,
1311da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more);
1329c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
1339c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
1349c55e01cSJens Axboe 				unsigned int flags);
1351da177e4SLinus Torvalds 
1361da177e4SLinus Torvalds /*
1371da177e4SLinus Torvalds  *	Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
1381da177e4SLinus Torvalds  *	in the operation structures but are done directly via the socketcall() multiplexor.
1391da177e4SLinus Torvalds  */
1401da177e4SLinus Torvalds 
141da7071d7SArjan van de Ven static const struct file_operations socket_file_ops = {
1421da177e4SLinus Torvalds 	.owner =	THIS_MODULE,
1431da177e4SLinus Torvalds 	.llseek =	no_llseek,
1448ae5e030SAl Viro 	.read_iter =	sock_read_iter,
1458ae5e030SAl Viro 	.write_iter =	sock_write_iter,
14615252423SChristoph Hellwig 	.get_poll_head = sock_get_poll_head,
14715252423SChristoph Hellwig 	.poll_mask =	sock_poll_mask,
1481da177e4SLinus Torvalds 	.poll =		sock_poll,
1491da177e4SLinus Torvalds 	.unlocked_ioctl = sock_ioctl,
15089bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
15189bbfc95SShaun Pereira 	.compat_ioctl = compat_sock_ioctl,
15289bbfc95SShaun Pereira #endif
1531da177e4SLinus Torvalds 	.mmap =		sock_mmap,
1541da177e4SLinus Torvalds 	.release =	sock_close,
1551da177e4SLinus Torvalds 	.fasync =	sock_fasync,
1565274f052SJens Axboe 	.sendpage =	sock_sendpage,
1575274f052SJens Axboe 	.splice_write = generic_splice_sendpage,
1589c55e01cSJens Axboe 	.splice_read =	sock_splice_read,
1591da177e4SLinus Torvalds };
1601da177e4SLinus Torvalds 
1611da177e4SLinus Torvalds /*
1621da177e4SLinus Torvalds  *	The protocol list. Each protocol is registered in here.
1631da177e4SLinus Torvalds  */
1641da177e4SLinus Torvalds 
1651da177e4SLinus Torvalds static DEFINE_SPINLOCK(net_family_lock);
166190683a9SEric Dumazet static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly;
1671da177e4SLinus Torvalds 
1681da177e4SLinus Torvalds /*
16989bddce5SStephen Hemminger  * Support routines.
17089bddce5SStephen Hemminger  * Move socket addresses back and forth across the kernel/user
1711da177e4SLinus Torvalds  * divide and look after the messy bits.
1721da177e4SLinus Torvalds  */
1731da177e4SLinus Torvalds 
1741da177e4SLinus Torvalds /**
1751da177e4SLinus Torvalds  *	move_addr_to_kernel	-	copy a socket address into kernel space
1761da177e4SLinus Torvalds  *	@uaddr: Address in user space
1771da177e4SLinus Torvalds  *	@kaddr: Address in kernel space
1781da177e4SLinus Torvalds  *	@ulen: Length in user space
1791da177e4SLinus Torvalds  *
1801da177e4SLinus Torvalds  *	The address is copied into kernel space. If the provided address is
1811da177e4SLinus Torvalds  *	too long an error code of -EINVAL is returned. If the copy gives
1821da177e4SLinus Torvalds  *	invalid addresses -EFAULT is returned. On a success 0 is returned.
1831da177e4SLinus Torvalds  */
1841da177e4SLinus Torvalds 
18543db362dSMaciej Żenczykowski int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr)
1861da177e4SLinus Torvalds {
187230b1839SYOSHIFUJI Hideaki 	if (ulen < 0 || ulen > sizeof(struct sockaddr_storage))
1881da177e4SLinus Torvalds 		return -EINVAL;
1891da177e4SLinus Torvalds 	if (ulen == 0)
1901da177e4SLinus Torvalds 		return 0;
1911da177e4SLinus Torvalds 	if (copy_from_user(kaddr, uaddr, ulen))
1921da177e4SLinus Torvalds 		return -EFAULT;
1933ec3b2fbSDavid Woodhouse 	return audit_sockaddr(ulen, kaddr);
1941da177e4SLinus Torvalds }
1951da177e4SLinus Torvalds 
1961da177e4SLinus Torvalds /**
1971da177e4SLinus Torvalds  *	move_addr_to_user	-	copy an address to user space
1981da177e4SLinus Torvalds  *	@kaddr: kernel space address
1991da177e4SLinus Torvalds  *	@klen: length of address in kernel
2001da177e4SLinus Torvalds  *	@uaddr: user space address
2011da177e4SLinus Torvalds  *	@ulen: pointer to user length field
2021da177e4SLinus Torvalds  *
2031da177e4SLinus Torvalds  *	The value pointed to by ulen on entry is the buffer length available.
2041da177e4SLinus Torvalds  *	This is overwritten with the buffer space used. -EINVAL is returned
2051da177e4SLinus Torvalds  *	if an overlong buffer is specified or a negative buffer size. -EFAULT
2061da177e4SLinus Torvalds  *	is returned if either the buffer or the length field are not
2071da177e4SLinus Torvalds  *	accessible.
2081da177e4SLinus Torvalds  *	After copying the data up to the limit the user specifies, the true
2091da177e4SLinus Torvalds  *	length of the data is written over the length limit the user
2101da177e4SLinus Torvalds  *	specified. Zero is returned for a success.
2111da177e4SLinus Torvalds  */
2121da177e4SLinus Torvalds 
21343db362dSMaciej Żenczykowski static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen,
21411165f14Sstephen hemminger 			     void __user *uaddr, int __user *ulen)
2151da177e4SLinus Torvalds {
2161da177e4SLinus Torvalds 	int err;
2171da177e4SLinus Torvalds 	int len;
2181da177e4SLinus Torvalds 
21968c6beb3SHannes Frederic Sowa 	BUG_ON(klen > sizeof(struct sockaddr_storage));
22089bddce5SStephen Hemminger 	err = get_user(len, ulen);
22189bddce5SStephen Hemminger 	if (err)
2221da177e4SLinus Torvalds 		return err;
2231da177e4SLinus Torvalds 	if (len > klen)
2241da177e4SLinus Torvalds 		len = klen;
22568c6beb3SHannes Frederic Sowa 	if (len < 0)
2261da177e4SLinus Torvalds 		return -EINVAL;
22789bddce5SStephen Hemminger 	if (len) {
228d6fe3945SSteve Grubb 		if (audit_sockaddr(klen, kaddr))
229d6fe3945SSteve Grubb 			return -ENOMEM;
2301da177e4SLinus Torvalds 		if (copy_to_user(uaddr, kaddr, len))
2311da177e4SLinus Torvalds 			return -EFAULT;
2321da177e4SLinus Torvalds 	}
2331da177e4SLinus Torvalds 	/*
2341da177e4SLinus Torvalds 	 *      "fromlen shall refer to the value before truncation.."
2351da177e4SLinus Torvalds 	 *                      1003.1g
2361da177e4SLinus Torvalds 	 */
2371da177e4SLinus Torvalds 	return __put_user(klen, ulen);
2381da177e4SLinus Torvalds }
2391da177e4SLinus Torvalds 
24008009a76SAlexey Dobriyan static struct kmem_cache *sock_inode_cachep __ro_after_init;
2411da177e4SLinus Torvalds 
2421da177e4SLinus Torvalds static struct inode *sock_alloc_inode(struct super_block *sb)
2431da177e4SLinus Torvalds {
2441da177e4SLinus Torvalds 	struct socket_alloc *ei;
245eaefd110SEric Dumazet 	struct socket_wq *wq;
24689bddce5SStephen Hemminger 
247e94b1766SChristoph Lameter 	ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL);
2481da177e4SLinus Torvalds 	if (!ei)
2491da177e4SLinus Torvalds 		return NULL;
250eaefd110SEric Dumazet 	wq = kmalloc(sizeof(*wq), GFP_KERNEL);
251eaefd110SEric Dumazet 	if (!wq) {
25243815482SEric Dumazet 		kmem_cache_free(sock_inode_cachep, ei);
25343815482SEric Dumazet 		return NULL;
25443815482SEric Dumazet 	}
255eaefd110SEric Dumazet 	init_waitqueue_head(&wq->wait);
256eaefd110SEric Dumazet 	wq->fasync_list = NULL;
257574aab1eSNicolai Stange 	wq->flags = 0;
258eaefd110SEric Dumazet 	RCU_INIT_POINTER(ei->socket.wq, wq);
2591da177e4SLinus Torvalds 
2601da177e4SLinus Torvalds 	ei->socket.state = SS_UNCONNECTED;
2611da177e4SLinus Torvalds 	ei->socket.flags = 0;
2621da177e4SLinus Torvalds 	ei->socket.ops = NULL;
2631da177e4SLinus Torvalds 	ei->socket.sk = NULL;
2641da177e4SLinus Torvalds 	ei->socket.file = NULL;
2651da177e4SLinus Torvalds 
2661da177e4SLinus Torvalds 	return &ei->vfs_inode;
2671da177e4SLinus Torvalds }
2681da177e4SLinus Torvalds 
2691da177e4SLinus Torvalds static void sock_destroy_inode(struct inode *inode)
2701da177e4SLinus Torvalds {
27143815482SEric Dumazet 	struct socket_alloc *ei;
272eaefd110SEric Dumazet 	struct socket_wq *wq;
27343815482SEric Dumazet 
27443815482SEric Dumazet 	ei = container_of(inode, struct socket_alloc, vfs_inode);
275eaefd110SEric Dumazet 	wq = rcu_dereference_protected(ei->socket.wq, 1);
27661845220SLai Jiangshan 	kfree_rcu(wq, rcu);
27743815482SEric Dumazet 	kmem_cache_free(sock_inode_cachep, ei);
2781da177e4SLinus Torvalds }
2791da177e4SLinus Torvalds 
28051cc5068SAlexey Dobriyan static void init_once(void *foo)
2811da177e4SLinus Torvalds {
2821da177e4SLinus Torvalds 	struct socket_alloc *ei = (struct socket_alloc *)foo;
2831da177e4SLinus Torvalds 
2841da177e4SLinus Torvalds 	inode_init_once(&ei->vfs_inode);
2851da177e4SLinus Torvalds }
2861da177e4SLinus Torvalds 
2871e911632Syuan linyu static void init_inodecache(void)
2881da177e4SLinus Torvalds {
2891da177e4SLinus Torvalds 	sock_inode_cachep = kmem_cache_create("sock_inode_cache",
2901da177e4SLinus Torvalds 					      sizeof(struct socket_alloc),
29189bddce5SStephen Hemminger 					      0,
29289bddce5SStephen Hemminger 					      (SLAB_HWCACHE_ALIGN |
29389bddce5SStephen Hemminger 					       SLAB_RECLAIM_ACCOUNT |
2945d097056SVladimir Davydov 					       SLAB_MEM_SPREAD | SLAB_ACCOUNT),
29520c2df83SPaul Mundt 					      init_once);
2961e911632Syuan linyu 	BUG_ON(sock_inode_cachep == NULL);
2971da177e4SLinus Torvalds }
2981da177e4SLinus Torvalds 
299b87221deSAlexey Dobriyan static const struct super_operations sockfs_ops = {
3001da177e4SLinus Torvalds 	.alloc_inode	= sock_alloc_inode,
3011da177e4SLinus Torvalds 	.destroy_inode	= sock_destroy_inode,
3021da177e4SLinus Torvalds 	.statfs		= simple_statfs,
3031da177e4SLinus Torvalds };
3041da177e4SLinus Torvalds 
305c23fbb6bSEric Dumazet /*
306c23fbb6bSEric Dumazet  * sockfs_dname() is called from d_path().
307c23fbb6bSEric Dumazet  */
308c23fbb6bSEric Dumazet static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen)
309c23fbb6bSEric Dumazet {
310c23fbb6bSEric Dumazet 	return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]",
311c5ef6035SDavid Howells 				d_inode(dentry)->i_ino);
312c23fbb6bSEric Dumazet }
313c23fbb6bSEric Dumazet 
3143ba13d17SAl Viro static const struct dentry_operations sockfs_dentry_operations = {
315c23fbb6bSEric Dumazet 	.d_dname  = sockfs_dname,
3161da177e4SLinus Torvalds };
3171da177e4SLinus Torvalds 
318bba0bd31SAndreas Gruenbacher static int sockfs_xattr_get(const struct xattr_handler *handler,
319bba0bd31SAndreas Gruenbacher 			    struct dentry *dentry, struct inode *inode,
320bba0bd31SAndreas Gruenbacher 			    const char *suffix, void *value, size_t size)
321bba0bd31SAndreas Gruenbacher {
322bba0bd31SAndreas Gruenbacher 	if (value) {
323bba0bd31SAndreas Gruenbacher 		if (dentry->d_name.len + 1 > size)
324bba0bd31SAndreas Gruenbacher 			return -ERANGE;
325bba0bd31SAndreas Gruenbacher 		memcpy(value, dentry->d_name.name, dentry->d_name.len + 1);
326bba0bd31SAndreas Gruenbacher 	}
327bba0bd31SAndreas Gruenbacher 	return dentry->d_name.len + 1;
328bba0bd31SAndreas Gruenbacher }
329bba0bd31SAndreas Gruenbacher 
330bba0bd31SAndreas Gruenbacher #define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname"
331bba0bd31SAndreas Gruenbacher #define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX)
332bba0bd31SAndreas Gruenbacher #define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1)
333bba0bd31SAndreas Gruenbacher 
334bba0bd31SAndreas Gruenbacher static const struct xattr_handler sockfs_xattr_handler = {
335bba0bd31SAndreas Gruenbacher 	.name = XATTR_NAME_SOCKPROTONAME,
336bba0bd31SAndreas Gruenbacher 	.get = sockfs_xattr_get,
337bba0bd31SAndreas Gruenbacher };
338bba0bd31SAndreas Gruenbacher 
3394a590153SAndreas Gruenbacher static int sockfs_security_xattr_set(const struct xattr_handler *handler,
3404a590153SAndreas Gruenbacher 				     struct dentry *dentry, struct inode *inode,
3414a590153SAndreas Gruenbacher 				     const char *suffix, const void *value,
3424a590153SAndreas Gruenbacher 				     size_t size, int flags)
3434a590153SAndreas Gruenbacher {
3444a590153SAndreas Gruenbacher 	/* Handled by LSM. */
3454a590153SAndreas Gruenbacher 	return -EAGAIN;
3464a590153SAndreas Gruenbacher }
3474a590153SAndreas Gruenbacher 
3484a590153SAndreas Gruenbacher static const struct xattr_handler sockfs_security_xattr_handler = {
3494a590153SAndreas Gruenbacher 	.prefix = XATTR_SECURITY_PREFIX,
3504a590153SAndreas Gruenbacher 	.set = sockfs_security_xattr_set,
3514a590153SAndreas Gruenbacher };
3524a590153SAndreas Gruenbacher 
353bba0bd31SAndreas Gruenbacher static const struct xattr_handler *sockfs_xattr_handlers[] = {
354bba0bd31SAndreas Gruenbacher 	&sockfs_xattr_handler,
3554a590153SAndreas Gruenbacher 	&sockfs_security_xattr_handler,
356bba0bd31SAndreas Gruenbacher 	NULL
357bba0bd31SAndreas Gruenbacher };
358bba0bd31SAndreas Gruenbacher 
359c74a1cbbSAl Viro static struct dentry *sockfs_mount(struct file_system_type *fs_type,
360c74a1cbbSAl Viro 			 int flags, const char *dev_name, void *data)
361c74a1cbbSAl Viro {
362bba0bd31SAndreas Gruenbacher 	return mount_pseudo_xattr(fs_type, "socket:", &sockfs_ops,
363bba0bd31SAndreas Gruenbacher 				  sockfs_xattr_handlers,
364c74a1cbbSAl Viro 				  &sockfs_dentry_operations, SOCKFS_MAGIC);
365c74a1cbbSAl Viro }
366c74a1cbbSAl Viro 
367c74a1cbbSAl Viro static struct vfsmount *sock_mnt __read_mostly;
368c74a1cbbSAl Viro 
369c74a1cbbSAl Viro static struct file_system_type sock_fs_type = {
370c74a1cbbSAl Viro 	.name =		"sockfs",
371c74a1cbbSAl Viro 	.mount =	sockfs_mount,
372c74a1cbbSAl Viro 	.kill_sb =	kill_anon_super,
373c74a1cbbSAl Viro };
374c74a1cbbSAl Viro 
3751da177e4SLinus Torvalds /*
3761da177e4SLinus Torvalds  *	Obtains the first available file descriptor and sets it up for use.
3771da177e4SLinus Torvalds  *
37839d8c1b6SDavid S. Miller  *	These functions create file structures and maps them to fd space
37939d8c1b6SDavid S. Miller  *	of the current process. On success it returns file descriptor
3801da177e4SLinus Torvalds  *	and file struct implicitly stored in sock->file.
3811da177e4SLinus Torvalds  *	Note that another thread may close file descriptor before we return
3821da177e4SLinus Torvalds  *	from this function. We use the fact that now we do not refer
3831da177e4SLinus Torvalds  *	to socket after mapping. If one day we will need it, this
3841da177e4SLinus Torvalds  *	function will increment ref. count on file by 1.
3851da177e4SLinus Torvalds  *
3861da177e4SLinus Torvalds  *	In any case returned fd MAY BE not valid!
3871da177e4SLinus Torvalds  *	This race condition is unavoidable
3881da177e4SLinus Torvalds  *	with shared fd spaces, we cannot solve it inside kernel,
3891da177e4SLinus Torvalds  *	but we take care of internal coherence yet.
3901da177e4SLinus Torvalds  */
3911da177e4SLinus Torvalds 
392aab174f0SLinus Torvalds struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)
3931da177e4SLinus Torvalds {
3947cbe66b6SAl Viro 	struct qstr name = { .name = "" };
3952c48b9c4SAl Viro 	struct path path;
3967cbe66b6SAl Viro 	struct file *file;
3971da177e4SLinus Torvalds 
398600e1779SMasatake YAMATO 	if (dname) {
399600e1779SMasatake YAMATO 		name.name = dname;
400600e1779SMasatake YAMATO 		name.len = strlen(name.name);
401600e1779SMasatake YAMATO 	} else if (sock->sk) {
402600e1779SMasatake YAMATO 		name.name = sock->sk->sk_prot_creator->name;
403600e1779SMasatake YAMATO 		name.len = strlen(name.name);
404600e1779SMasatake YAMATO 	}
4054b936885SNick Piggin 	path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name);
4068e1611e2SAl Viro 	if (unlikely(!path.dentry)) {
4078e1611e2SAl Viro 		sock_release(sock);
40828407630SAl Viro 		return ERR_PTR(-ENOMEM);
4098e1611e2SAl Viro 	}
4102c48b9c4SAl Viro 	path.mnt = mntget(sock_mnt);
41139d8c1b6SDavid S. Miller 
4122c48b9c4SAl Viro 	d_instantiate(path.dentry, SOCK_INODE(sock));
413cc3808f8SAl Viro 
4142c48b9c4SAl Viro 	file = alloc_file(&path, FMODE_READ | FMODE_WRITE,
415cc3808f8SAl Viro 		  &socket_file_ops);
416b5ffe634SViresh Kumar 	if (IS_ERR(file)) {
4178e1611e2SAl Viro 		/* drop dentry, keep inode for a bit */
418c5ef6035SDavid Howells 		ihold(d_inode(path.dentry));
4192c48b9c4SAl Viro 		path_put(&path);
4208e1611e2SAl Viro 		/* ... and now kill it properly */
4218e1611e2SAl Viro 		sock_release(sock);
42239b65252SAnatol Pomozov 		return file;
423cc3808f8SAl Viro 	}
4241da177e4SLinus Torvalds 
4251da177e4SLinus Torvalds 	sock->file = file;
42677d27200SUlrich Drepper 	file->f_flags = O_RDWR | (flags & O_NONBLOCK);
42707dc3f07SBenjamin LaHaise 	file->private_data = sock;
42828407630SAl Viro 	return file;
4291da177e4SLinus Torvalds }
43056b31d1cSAl Viro EXPORT_SYMBOL(sock_alloc_file);
4311da177e4SLinus Torvalds 
43256b31d1cSAl Viro static int sock_map_fd(struct socket *sock, int flags)
43339d8c1b6SDavid S. Miller {
43439d8c1b6SDavid S. Miller 	struct file *newfile;
43528407630SAl Viro 	int fd = get_unused_fd_flags(flags);
436ce4bb04cSAl Viro 	if (unlikely(fd < 0)) {
437ce4bb04cSAl Viro 		sock_release(sock);
4381da177e4SLinus Torvalds 		return fd;
439ce4bb04cSAl Viro 	}
4401da177e4SLinus Torvalds 
441aab174f0SLinus Torvalds 	newfile = sock_alloc_file(sock, flags, NULL);
44228407630SAl Viro 	if (likely(!IS_ERR(newfile))) {
4431da177e4SLinus Torvalds 		fd_install(fd, newfile);
4441da177e4SLinus Torvalds 		return fd;
4451da177e4SLinus Torvalds 	}
44628407630SAl Viro 
44728407630SAl Viro 	put_unused_fd(fd);
44828407630SAl Viro 	return PTR_ERR(newfile);
4491da177e4SLinus Torvalds }
4501da177e4SLinus Torvalds 
451406a3c63SJohn Fastabend struct socket *sock_from_file(struct file *file, int *err)
4526cb153caSBenjamin LaHaise {
4536cb153caSBenjamin LaHaise 	if (file->f_op == &socket_file_ops)
4546cb153caSBenjamin LaHaise 		return file->private_data;	/* set in sock_map_fd */
4556cb153caSBenjamin LaHaise 
4566cb153caSBenjamin LaHaise 	*err = -ENOTSOCK;
4576cb153caSBenjamin LaHaise 	return NULL;
4586cb153caSBenjamin LaHaise }
459406a3c63SJohn Fastabend EXPORT_SYMBOL(sock_from_file);
4606cb153caSBenjamin LaHaise 
4611da177e4SLinus Torvalds /**
4621da177e4SLinus Torvalds  *	sockfd_lookup - Go from a file number to its socket slot
4631da177e4SLinus Torvalds  *	@fd: file handle
4641da177e4SLinus Torvalds  *	@err: pointer to an error code return
4651da177e4SLinus Torvalds  *
4661da177e4SLinus Torvalds  *	The file handle passed in is locked and the socket it is bound
467241c4667SRosen, Rami  *	to is returned. If an error occurs the err pointer is overwritten
4681da177e4SLinus Torvalds  *	with a negative errno code and NULL is returned. The function checks
4691da177e4SLinus Torvalds  *	for both invalid handles and passing a handle which is not a socket.
4701da177e4SLinus Torvalds  *
4711da177e4SLinus Torvalds  *	On a success the socket object pointer is returned.
4721da177e4SLinus Torvalds  */
4731da177e4SLinus Torvalds 
4741da177e4SLinus Torvalds struct socket *sockfd_lookup(int fd, int *err)
4751da177e4SLinus Torvalds {
4761da177e4SLinus Torvalds 	struct file *file;
4771da177e4SLinus Torvalds 	struct socket *sock;
4781da177e4SLinus Torvalds 
47989bddce5SStephen Hemminger 	file = fget(fd);
48089bddce5SStephen Hemminger 	if (!file) {
4811da177e4SLinus Torvalds 		*err = -EBADF;
4821da177e4SLinus Torvalds 		return NULL;
4831da177e4SLinus Torvalds 	}
48489bddce5SStephen Hemminger 
4856cb153caSBenjamin LaHaise 	sock = sock_from_file(file, err);
4866cb153caSBenjamin LaHaise 	if (!sock)
4871da177e4SLinus Torvalds 		fput(file);
4886cb153caSBenjamin LaHaise 	return sock;
4891da177e4SLinus Torvalds }
490c6d409cfSEric Dumazet EXPORT_SYMBOL(sockfd_lookup);
4911da177e4SLinus Torvalds 
4926cb153caSBenjamin LaHaise static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
4936cb153caSBenjamin LaHaise {
49400e188efSAl Viro 	struct fd f = fdget(fd);
4956cb153caSBenjamin LaHaise 	struct socket *sock;
4966cb153caSBenjamin LaHaise 
4973672558cSHua Zhong 	*err = -EBADF;
49800e188efSAl Viro 	if (f.file) {
49900e188efSAl Viro 		sock = sock_from_file(f.file, err);
50000e188efSAl Viro 		if (likely(sock)) {
50100e188efSAl Viro 			*fput_needed = f.flags;
5021da177e4SLinus Torvalds 			return sock;
50300e188efSAl Viro 		}
50400e188efSAl Viro 		fdput(f);
5056cb153caSBenjamin LaHaise 	}
5066cb153caSBenjamin LaHaise 	return NULL;
5071da177e4SLinus Torvalds }
5081da177e4SLinus Torvalds 
509600e1779SMasatake YAMATO static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer,
510600e1779SMasatake YAMATO 				size_t size)
511600e1779SMasatake YAMATO {
512600e1779SMasatake YAMATO 	ssize_t len;
513600e1779SMasatake YAMATO 	ssize_t used = 0;
514600e1779SMasatake YAMATO 
515c5ef6035SDavid Howells 	len = security_inode_listsecurity(d_inode(dentry), buffer, size);
516600e1779SMasatake YAMATO 	if (len < 0)
517600e1779SMasatake YAMATO 		return len;
518600e1779SMasatake YAMATO 	used += len;
519600e1779SMasatake YAMATO 	if (buffer) {
520600e1779SMasatake YAMATO 		if (size < used)
521600e1779SMasatake YAMATO 			return -ERANGE;
522600e1779SMasatake YAMATO 		buffer += len;
523600e1779SMasatake YAMATO 	}
524600e1779SMasatake YAMATO 
525600e1779SMasatake YAMATO 	len = (XATTR_NAME_SOCKPROTONAME_LEN + 1);
526600e1779SMasatake YAMATO 	used += len;
527600e1779SMasatake YAMATO 	if (buffer) {
528600e1779SMasatake YAMATO 		if (size < used)
529600e1779SMasatake YAMATO 			return -ERANGE;
530600e1779SMasatake YAMATO 		memcpy(buffer, XATTR_NAME_SOCKPROTONAME, len);
531600e1779SMasatake YAMATO 		buffer += len;
532600e1779SMasatake YAMATO 	}
533600e1779SMasatake YAMATO 
534600e1779SMasatake YAMATO 	return used;
535600e1779SMasatake YAMATO }
536600e1779SMasatake YAMATO 
537dc647ec8STobias Klauser static int sockfs_setattr(struct dentry *dentry, struct iattr *iattr)
53886741ec2SLorenzo Colitti {
53986741ec2SLorenzo Colitti 	int err = simple_setattr(dentry, iattr);
54086741ec2SLorenzo Colitti 
541e1a3a60aSEric Biggers 	if (!err && (iattr->ia_valid & ATTR_UID)) {
54286741ec2SLorenzo Colitti 		struct socket *sock = SOCKET_I(d_inode(dentry));
54386741ec2SLorenzo Colitti 
5446d8c50dcSCong Wang 		if (sock->sk)
54586741ec2SLorenzo Colitti 			sock->sk->sk_uid = iattr->ia_uid;
5466d8c50dcSCong Wang 		else
5476d8c50dcSCong Wang 			err = -ENOENT;
54886741ec2SLorenzo Colitti 	}
54986741ec2SLorenzo Colitti 
55086741ec2SLorenzo Colitti 	return err;
55186741ec2SLorenzo Colitti }
55286741ec2SLorenzo Colitti 
553600e1779SMasatake YAMATO static const struct inode_operations sockfs_inode_ops = {
554600e1779SMasatake YAMATO 	.listxattr = sockfs_listxattr,
55586741ec2SLorenzo Colitti 	.setattr = sockfs_setattr,
556600e1779SMasatake YAMATO };
557600e1779SMasatake YAMATO 
5581da177e4SLinus Torvalds /**
5591da177e4SLinus Torvalds  *	sock_alloc	-	allocate a socket
5601da177e4SLinus Torvalds  *
5611da177e4SLinus Torvalds  *	Allocate a new inode and socket object. The two are bound together
5621da177e4SLinus Torvalds  *	and initialised. The socket is then returned. If we are out of inodes
5631da177e4SLinus Torvalds  *	NULL is returned.
5641da177e4SLinus Torvalds  */
5651da177e4SLinus Torvalds 
566f4a00aacSTom Herbert struct socket *sock_alloc(void)
5671da177e4SLinus Torvalds {
5681da177e4SLinus Torvalds 	struct inode *inode;
5691da177e4SLinus Torvalds 	struct socket *sock;
5701da177e4SLinus Torvalds 
571a209dfc7SEric Dumazet 	inode = new_inode_pseudo(sock_mnt->mnt_sb);
5721da177e4SLinus Torvalds 	if (!inode)
5731da177e4SLinus Torvalds 		return NULL;
5741da177e4SLinus Torvalds 
5751da177e4SLinus Torvalds 	sock = SOCKET_I(inode);
5761da177e4SLinus Torvalds 
57785fe4025SChristoph Hellwig 	inode->i_ino = get_next_ino();
5781da177e4SLinus Torvalds 	inode->i_mode = S_IFSOCK | S_IRWXUGO;
5798192b0c4SDavid Howells 	inode->i_uid = current_fsuid();
5808192b0c4SDavid Howells 	inode->i_gid = current_fsgid();
581600e1779SMasatake YAMATO 	inode->i_op = &sockfs_inode_ops;
5821da177e4SLinus Torvalds 
5831da177e4SLinus Torvalds 	return sock;
5841da177e4SLinus Torvalds }
585f4a00aacSTom Herbert EXPORT_SYMBOL(sock_alloc);
5861da177e4SLinus Torvalds 
5871da177e4SLinus Torvalds /**
5881da177e4SLinus Torvalds  *	sock_release	-	close a socket
5891da177e4SLinus Torvalds  *	@sock: socket to close
5901da177e4SLinus Torvalds  *
5911da177e4SLinus Torvalds  *	The socket is released from the protocol stack if it has a release
5921da177e4SLinus Torvalds  *	callback, and the inode is then released if the socket is bound to
5931da177e4SLinus Torvalds  *	an inode not a file.
5941da177e4SLinus Torvalds  */
5951da177e4SLinus Torvalds 
5966d8c50dcSCong Wang static void __sock_release(struct socket *sock, struct inode *inode)
5971da177e4SLinus Torvalds {
5981da177e4SLinus Torvalds 	if (sock->ops) {
5991da177e4SLinus Torvalds 		struct module *owner = sock->ops->owner;
6001da177e4SLinus Torvalds 
6016d8c50dcSCong Wang 		if (inode)
6026d8c50dcSCong Wang 			inode_lock(inode);
6031da177e4SLinus Torvalds 		sock->ops->release(sock);
6046d8c50dcSCong Wang 		if (inode)
6056d8c50dcSCong Wang 			inode_unlock(inode);
6061da177e4SLinus Torvalds 		sock->ops = NULL;
6071da177e4SLinus Torvalds 		module_put(owner);
6081da177e4SLinus Torvalds 	}
6091da177e4SLinus Torvalds 
610eaefd110SEric Dumazet 	if (rcu_dereference_protected(sock->wq, 1)->fasync_list)
6113410f22eSYang Yingliang 		pr_err("%s: fasync list not empty!\n", __func__);
6121da177e4SLinus Torvalds 
6131da177e4SLinus Torvalds 	if (!sock->file) {
6141da177e4SLinus Torvalds 		iput(SOCK_INODE(sock));
6151da177e4SLinus Torvalds 		return;
6161da177e4SLinus Torvalds 	}
6171da177e4SLinus Torvalds 	sock->file = NULL;
6181da177e4SLinus Torvalds }
6196d8c50dcSCong Wang 
6206d8c50dcSCong Wang void sock_release(struct socket *sock)
6216d8c50dcSCong Wang {
6226d8c50dcSCong Wang 	__sock_release(sock, NULL);
6236d8c50dcSCong Wang }
624c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_release);
6251da177e4SLinus Torvalds 
626c14ac945SSoheil Hassas Yeganeh void __sock_tx_timestamp(__u16 tsflags, __u8 *tx_flags)
62720d49473SPatrick Ohly {
628140c55d4SEric Dumazet 	u8 flags = *tx_flags;
629140c55d4SEric Dumazet 
630c14ac945SSoheil Hassas Yeganeh 	if (tsflags & SOF_TIMESTAMPING_TX_HARDWARE)
631140c55d4SEric Dumazet 		flags |= SKBTX_HW_TSTAMP;
632140c55d4SEric Dumazet 
633c14ac945SSoheil Hassas Yeganeh 	if (tsflags & SOF_TIMESTAMPING_TX_SOFTWARE)
634140c55d4SEric Dumazet 		flags |= SKBTX_SW_TSTAMP;
635140c55d4SEric Dumazet 
636c14ac945SSoheil Hassas Yeganeh 	if (tsflags & SOF_TIMESTAMPING_TX_SCHED)
637140c55d4SEric Dumazet 		flags |= SKBTX_SCHED_TSTAMP;
638140c55d4SEric Dumazet 
639140c55d4SEric Dumazet 	*tx_flags = flags;
64020d49473SPatrick Ohly }
64167cc0d40SWillem de Bruijn EXPORT_SYMBOL(__sock_tx_timestamp);
64220d49473SPatrick Ohly 
643d8725c86SAl Viro static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg)
6441da177e4SLinus Torvalds {
64501e97e65SAl Viro 	int ret = sock->ops->sendmsg(sock, msg, msg_data_left(msg));
646d8725c86SAl Viro 	BUG_ON(ret == -EIOCBQUEUED);
647d8725c86SAl Viro 	return ret;
6481da177e4SLinus Torvalds }
6490cf00c6fSGu Zheng 
650d8725c86SAl Viro int sock_sendmsg(struct socket *sock, struct msghdr *msg)
6510cf00c6fSGu Zheng {
652d8725c86SAl Viro 	int err = security_socket_sendmsg(sock, msg,
65301e97e65SAl Viro 					  msg_data_left(msg));
6541b784140SYing Xue 
655d8725c86SAl Viro 	return err ?: sock_sendmsg_nosec(sock, msg);
6560cf00c6fSGu Zheng }
657c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_sendmsg);
6581da177e4SLinus Torvalds 
6591da177e4SLinus Torvalds int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
6601da177e4SLinus Torvalds 		   struct kvec *vec, size_t num, size_t size)
6611da177e4SLinus Torvalds {
6626aa24814SAl Viro 	iov_iter_kvec(&msg->msg_iter, WRITE | ITER_KVEC, vec, num, size);
663d8725c86SAl Viro 	return sock_sendmsg(sock, msg);
6641da177e4SLinus Torvalds }
665c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendmsg);
6661da177e4SLinus Torvalds 
667306b13ebSTom Herbert int kernel_sendmsg_locked(struct sock *sk, struct msghdr *msg,
668306b13ebSTom Herbert 			  struct kvec *vec, size_t num, size_t size)
669306b13ebSTom Herbert {
670306b13ebSTom Herbert 	struct socket *sock = sk->sk_socket;
671306b13ebSTom Herbert 
672306b13ebSTom Herbert 	if (!sock->ops->sendmsg_locked)
673db5980d8SJohn Fastabend 		return sock_no_sendmsg_locked(sk, msg, size);
674306b13ebSTom Herbert 
675306b13ebSTom Herbert 	iov_iter_kvec(&msg->msg_iter, WRITE | ITER_KVEC, vec, num, size);
676306b13ebSTom Herbert 
677306b13ebSTom Herbert 	return sock->ops->sendmsg_locked(sk, msg, msg_data_left(msg));
678306b13ebSTom Herbert }
679306b13ebSTom Herbert EXPORT_SYMBOL(kernel_sendmsg_locked);
680306b13ebSTom Herbert 
6818605330aSSoheil Hassas Yeganeh static bool skb_is_err_queue(const struct sk_buff *skb)
6828605330aSSoheil Hassas Yeganeh {
6838605330aSSoheil Hassas Yeganeh 	/* pkt_type of skbs enqueued on the error queue are set to
6848605330aSSoheil Hassas Yeganeh 	 * PACKET_OUTGOING in skb_set_err_queue(). This is only safe to do
6858605330aSSoheil Hassas Yeganeh 	 * in recvmsg, since skbs received on a local socket will never
6868605330aSSoheil Hassas Yeganeh 	 * have a pkt_type of PACKET_OUTGOING.
6878605330aSSoheil Hassas Yeganeh 	 */
6888605330aSSoheil Hassas Yeganeh 	return skb->pkt_type == PACKET_OUTGOING;
6898605330aSSoheil Hassas Yeganeh }
6908605330aSSoheil Hassas Yeganeh 
691b50a5c70SMiroslav Lichvar /* On transmit, software and hardware timestamps are returned independently.
692b50a5c70SMiroslav Lichvar  * As the two skb clones share the hardware timestamp, which may be updated
693b50a5c70SMiroslav Lichvar  * before the software timestamp is received, a hardware TX timestamp may be
694b50a5c70SMiroslav Lichvar  * returned only if there is no software TX timestamp. Ignore false software
695b50a5c70SMiroslav Lichvar  * timestamps, which may be made in the __sock_recv_timestamp() call when the
696b50a5c70SMiroslav Lichvar  * option SO_TIMESTAMP(NS) is enabled on the socket, even when the skb has a
697b50a5c70SMiroslav Lichvar  * hardware timestamp.
698b50a5c70SMiroslav Lichvar  */
699b50a5c70SMiroslav Lichvar static bool skb_is_swtx_tstamp(const struct sk_buff *skb, int false_tstamp)
700b50a5c70SMiroslav Lichvar {
701b50a5c70SMiroslav Lichvar 	return skb->tstamp && !false_tstamp && skb_is_err_queue(skb);
702b50a5c70SMiroslav Lichvar }
703b50a5c70SMiroslav Lichvar 
704aad9c8c4SMiroslav Lichvar static void put_ts_pktinfo(struct msghdr *msg, struct sk_buff *skb)
705aad9c8c4SMiroslav Lichvar {
706aad9c8c4SMiroslav Lichvar 	struct scm_ts_pktinfo ts_pktinfo;
707aad9c8c4SMiroslav Lichvar 	struct net_device *orig_dev;
708aad9c8c4SMiroslav Lichvar 
709aad9c8c4SMiroslav Lichvar 	if (!skb_mac_header_was_set(skb))
710aad9c8c4SMiroslav Lichvar 		return;
711aad9c8c4SMiroslav Lichvar 
712aad9c8c4SMiroslav Lichvar 	memset(&ts_pktinfo, 0, sizeof(ts_pktinfo));
713aad9c8c4SMiroslav Lichvar 
714aad9c8c4SMiroslav Lichvar 	rcu_read_lock();
715aad9c8c4SMiroslav Lichvar 	orig_dev = dev_get_by_napi_id(skb_napi_id(skb));
716aad9c8c4SMiroslav Lichvar 	if (orig_dev)
717aad9c8c4SMiroslav Lichvar 		ts_pktinfo.if_index = orig_dev->ifindex;
718aad9c8c4SMiroslav Lichvar 	rcu_read_unlock();
719aad9c8c4SMiroslav Lichvar 
720aad9c8c4SMiroslav Lichvar 	ts_pktinfo.pkt_length = skb->len - skb_mac_offset(skb);
721aad9c8c4SMiroslav Lichvar 	put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_PKTINFO,
722aad9c8c4SMiroslav Lichvar 		 sizeof(ts_pktinfo), &ts_pktinfo);
723aad9c8c4SMiroslav Lichvar }
724aad9c8c4SMiroslav Lichvar 
72592f37fd2SEric Dumazet /*
72692f37fd2SEric Dumazet  * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
72792f37fd2SEric Dumazet  */
72892f37fd2SEric Dumazet void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
72992f37fd2SEric Dumazet 	struct sk_buff *skb)
73092f37fd2SEric Dumazet {
73120d49473SPatrick Ohly 	int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
732f24b9be5SWillem de Bruijn 	struct scm_timestamping tss;
733b50a5c70SMiroslav Lichvar 	int empty = 1, false_tstamp = 0;
73420d49473SPatrick Ohly 	struct skb_shared_hwtstamps *shhwtstamps =
73520d49473SPatrick Ohly 		skb_hwtstamps(skb);
73692f37fd2SEric Dumazet 
73720d49473SPatrick Ohly 	/* Race occurred between timestamp enabling and packet
73820d49473SPatrick Ohly 	   receiving.  Fill in the current time for now. */
739b50a5c70SMiroslav Lichvar 	if (need_software_tstamp && skb->tstamp == 0) {
74020d49473SPatrick Ohly 		__net_timestamp(skb);
741b50a5c70SMiroslav Lichvar 		false_tstamp = 1;
742b50a5c70SMiroslav Lichvar 	}
74320d49473SPatrick Ohly 
74420d49473SPatrick Ohly 	if (need_software_tstamp) {
74592f37fd2SEric Dumazet 		if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
74692f37fd2SEric Dumazet 			struct timeval tv;
74720d49473SPatrick Ohly 			skb_get_timestamp(skb, &tv);
74820d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP,
74920d49473SPatrick Ohly 				 sizeof(tv), &tv);
75092f37fd2SEric Dumazet 		} else {
751f24b9be5SWillem de Bruijn 			struct timespec ts;
752f24b9be5SWillem de Bruijn 			skb_get_timestampns(skb, &ts);
75320d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS,
754f24b9be5SWillem de Bruijn 				 sizeof(ts), &ts);
75592f37fd2SEric Dumazet 		}
75692f37fd2SEric Dumazet 	}
75792f37fd2SEric Dumazet 
758f24b9be5SWillem de Bruijn 	memset(&tss, 0, sizeof(tss));
759c199105dSWillem de Bruijn 	if ((sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE) &&
760f24b9be5SWillem de Bruijn 	    ktime_to_timespec_cond(skb->tstamp, tss.ts + 0))
76120d49473SPatrick Ohly 		empty = 0;
7624d276eb6SWillem de Bruijn 	if (shhwtstamps &&
763b9f40e21SWillem de Bruijn 	    (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
764b50a5c70SMiroslav Lichvar 	    !skb_is_swtx_tstamp(skb, false_tstamp) &&
765aad9c8c4SMiroslav Lichvar 	    ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2)) {
76620d49473SPatrick Ohly 		empty = 0;
767aad9c8c4SMiroslav Lichvar 		if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_PKTINFO) &&
768aad9c8c4SMiroslav Lichvar 		    !skb_is_err_queue(skb))
769aad9c8c4SMiroslav Lichvar 			put_ts_pktinfo(msg, skb);
770aad9c8c4SMiroslav Lichvar 	}
7711c885808SFrancis Yan 	if (!empty) {
77220d49473SPatrick Ohly 		put_cmsg(msg, SOL_SOCKET,
773f24b9be5SWillem de Bruijn 			 SCM_TIMESTAMPING, sizeof(tss), &tss);
7741c885808SFrancis Yan 
7758605330aSSoheil Hassas Yeganeh 		if (skb_is_err_queue(skb) && skb->len &&
7764ef1b286SSoheil Hassas Yeganeh 		    SKB_EXT_ERR(skb)->opt_stats)
7771c885808SFrancis Yan 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_OPT_STATS,
7781c885808SFrancis Yan 				 skb->len, skb->data);
7791c885808SFrancis Yan 	}
78020d49473SPatrick Ohly }
7817c81fd8bSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
7827c81fd8bSArnaldo Carvalho de Melo 
7836e3e939fSJohannes Berg void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
7846e3e939fSJohannes Berg 	struct sk_buff *skb)
7856e3e939fSJohannes Berg {
7866e3e939fSJohannes Berg 	int ack;
7876e3e939fSJohannes Berg 
7886e3e939fSJohannes Berg 	if (!sock_flag(sk, SOCK_WIFI_STATUS))
7896e3e939fSJohannes Berg 		return;
7906e3e939fSJohannes Berg 	if (!skb->wifi_acked_valid)
7916e3e939fSJohannes Berg 		return;
7926e3e939fSJohannes Berg 
7936e3e939fSJohannes Berg 	ack = skb->wifi_acked;
7946e3e939fSJohannes Berg 
7956e3e939fSJohannes Berg 	put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack);
7966e3e939fSJohannes Berg }
7976e3e939fSJohannes Berg EXPORT_SYMBOL_GPL(__sock_recv_wifi_status);
7986e3e939fSJohannes Berg 
79911165f14Sstephen hemminger static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk,
80011165f14Sstephen hemminger 				   struct sk_buff *skb)
8013b885787SNeil Horman {
802744d5a3eSEyal Birger 	if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && SOCK_SKB_CB(skb)->dropcount)
8033b885787SNeil Horman 		put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL,
804744d5a3eSEyal Birger 			sizeof(__u32), &SOCK_SKB_CB(skb)->dropcount);
8053b885787SNeil Horman }
8063b885787SNeil Horman 
807767dd033SEric Dumazet void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
8083b885787SNeil Horman 	struct sk_buff *skb)
8093b885787SNeil Horman {
8103b885787SNeil Horman 	sock_recv_timestamp(msg, sk, skb);
8113b885787SNeil Horman 	sock_recv_drops(msg, sk, skb);
8123b885787SNeil Horman }
813767dd033SEric Dumazet EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops);
8143b885787SNeil Horman 
8151b784140SYing Xue static inline int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
8161b784140SYing Xue 				     int flags)
817a2e27255SArnaldo Carvalho de Melo {
8182da62906SAl Viro 	return sock->ops->recvmsg(sock, msg, msg_data_left(msg), flags);
8192da62906SAl Viro }
820a2e27255SArnaldo Carvalho de Melo 
8212da62906SAl Viro int sock_recvmsg(struct socket *sock, struct msghdr *msg, int flags)
8222da62906SAl Viro {
8232da62906SAl Viro 	int err = security_socket_recvmsg(sock, msg, msg_data_left(msg), flags);
8242da62906SAl Viro 
8252da62906SAl Viro 	return err ?: sock_recvmsg_nosec(sock, msg, flags);
8261da177e4SLinus Torvalds }
827c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_recvmsg);
8281da177e4SLinus Torvalds 
829c1249c0aSMartin Lucina /**
830c1249c0aSMartin Lucina  * kernel_recvmsg - Receive a message from a socket (kernel space)
831c1249c0aSMartin Lucina  * @sock:       The socket to receive the message from
832c1249c0aSMartin Lucina  * @msg:        Received message
833c1249c0aSMartin Lucina  * @vec:        Input s/g array for message data
834c1249c0aSMartin Lucina  * @num:        Size of input s/g array
835c1249c0aSMartin Lucina  * @size:       Number of bytes to read
836c1249c0aSMartin Lucina  * @flags:      Message flags (MSG_DONTWAIT, etc...)
837c1249c0aSMartin Lucina  *
838c1249c0aSMartin Lucina  * On return the msg structure contains the scatter/gather array passed in the
839c1249c0aSMartin Lucina  * vec argument. The array is modified so that it consists of the unfilled
840c1249c0aSMartin Lucina  * portion of the original array.
841c1249c0aSMartin Lucina  *
842c1249c0aSMartin Lucina  * The returned value is the total number of bytes received, or an error.
843c1249c0aSMartin Lucina  */
8441da177e4SLinus Torvalds int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
84589bddce5SStephen Hemminger 		   struct kvec *vec, size_t num, size_t size, int flags)
8461da177e4SLinus Torvalds {
8471da177e4SLinus Torvalds 	mm_segment_t oldfs = get_fs();
8481da177e4SLinus Torvalds 	int result;
8491da177e4SLinus Torvalds 
8506aa24814SAl Viro 	iov_iter_kvec(&msg->msg_iter, READ | ITER_KVEC, vec, num, size);
8511da177e4SLinus Torvalds 	set_fs(KERNEL_DS);
8522da62906SAl Viro 	result = sock_recvmsg(sock, msg, flags);
8531da177e4SLinus Torvalds 	set_fs(oldfs);
8541da177e4SLinus Torvalds 	return result;
8551da177e4SLinus Torvalds }
856c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_recvmsg);
8571da177e4SLinus Torvalds 
85820380731SArnaldo Carvalho de Melo static ssize_t sock_sendpage(struct file *file, struct page *page,
8591da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more)
8601da177e4SLinus Torvalds {
8611da177e4SLinus Torvalds 	struct socket *sock;
8621da177e4SLinus Torvalds 	int flags;
8631da177e4SLinus Torvalds 
864b69aee04SEric Dumazet 	sock = file->private_data;
8651da177e4SLinus Torvalds 
86635f9c09fSEric Dumazet 	flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
86735f9c09fSEric Dumazet 	/* more is a combination of MSG_MORE and MSG_SENDPAGE_NOTLAST */
86835f9c09fSEric Dumazet 	flags |= more;
8691da177e4SLinus Torvalds 
870e6949583SLinus Torvalds 	return kernel_sendpage(sock, page, offset, size, flags);
8711da177e4SLinus Torvalds }
8721da177e4SLinus Torvalds 
8739c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
8749c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
8759c55e01cSJens Axboe 				unsigned int flags)
8769c55e01cSJens Axboe {
8779c55e01cSJens Axboe 	struct socket *sock = file->private_data;
8789c55e01cSJens Axboe 
879997b37daSRémi Denis-Courmont 	if (unlikely(!sock->ops->splice_read))
880997b37daSRémi Denis-Courmont 		return -EINVAL;
881997b37daSRémi Denis-Courmont 
8829c55e01cSJens Axboe 	return sock->ops->splice_read(sock, ppos, pipe, len, flags);
8839c55e01cSJens Axboe }
8849c55e01cSJens Axboe 
8858ae5e030SAl Viro static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to)
886ce1d4d3eSChristoph Hellwig {
8876d652330SAl Viro 	struct file *file = iocb->ki_filp;
8886d652330SAl Viro 	struct socket *sock = file->private_data;
8890345f931Stadeusz.struk@intel.com 	struct msghdr msg = {.msg_iter = *to,
8900345f931Stadeusz.struk@intel.com 			     .msg_iocb = iocb};
8918ae5e030SAl Viro 	ssize_t res;
892ce1d4d3eSChristoph Hellwig 
8938ae5e030SAl Viro 	if (file->f_flags & O_NONBLOCK)
8948ae5e030SAl Viro 		msg.msg_flags = MSG_DONTWAIT;
8958ae5e030SAl Viro 
8968ae5e030SAl Viro 	if (iocb->ki_pos != 0)
897ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
898027445c3SBadari Pulavarty 
89966ee59afSChristoph Hellwig 	if (!iov_iter_count(to))	/* Match SYS5 behaviour */
900ce1d4d3eSChristoph Hellwig 		return 0;
901ce1d4d3eSChristoph Hellwig 
9022da62906SAl Viro 	res = sock_recvmsg(sock, &msg, msg.msg_flags);
9038ae5e030SAl Viro 	*to = msg.msg_iter;
9048ae5e030SAl Viro 	return res;
905ce1d4d3eSChristoph Hellwig }
906ce1d4d3eSChristoph Hellwig 
9078ae5e030SAl Viro static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from)
9081da177e4SLinus Torvalds {
9096d652330SAl Viro 	struct file *file = iocb->ki_filp;
9106d652330SAl Viro 	struct socket *sock = file->private_data;
9110345f931Stadeusz.struk@intel.com 	struct msghdr msg = {.msg_iter = *from,
9120345f931Stadeusz.struk@intel.com 			     .msg_iocb = iocb};
9138ae5e030SAl Viro 	ssize_t res;
9141da177e4SLinus Torvalds 
9158ae5e030SAl Viro 	if (iocb->ki_pos != 0)
916ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
917027445c3SBadari Pulavarty 
9188ae5e030SAl Viro 	if (file->f_flags & O_NONBLOCK)
9198ae5e030SAl Viro 		msg.msg_flags = MSG_DONTWAIT;
9208ae5e030SAl Viro 
9216d652330SAl Viro 	if (sock->type == SOCK_SEQPACKET)
9226d652330SAl Viro 		msg.msg_flags |= MSG_EOR;
9236d652330SAl Viro 
924d8725c86SAl Viro 	res = sock_sendmsg(sock, &msg);
9258ae5e030SAl Viro 	*from = msg.msg_iter;
9268ae5e030SAl Viro 	return res;
9271da177e4SLinus Torvalds }
9281da177e4SLinus Torvalds 
9291da177e4SLinus Torvalds /*
9301da177e4SLinus Torvalds  * Atomic setting of ioctl hooks to avoid race
9311da177e4SLinus Torvalds  * with module unload.
9321da177e4SLinus Torvalds  */
9331da177e4SLinus Torvalds 
9344a3e2f71SArjan van de Ven static DEFINE_MUTEX(br_ioctl_mutex);
935c6d409cfSEric Dumazet static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg);
9361da177e4SLinus Torvalds 
937881d966bSEric W. Biederman void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *))
9381da177e4SLinus Torvalds {
9394a3e2f71SArjan van de Ven 	mutex_lock(&br_ioctl_mutex);
9401da177e4SLinus Torvalds 	br_ioctl_hook = hook;
9414a3e2f71SArjan van de Ven 	mutex_unlock(&br_ioctl_mutex);
9421da177e4SLinus Torvalds }
9431da177e4SLinus Torvalds EXPORT_SYMBOL(brioctl_set);
9441da177e4SLinus Torvalds 
9454a3e2f71SArjan van de Ven static DEFINE_MUTEX(vlan_ioctl_mutex);
946881d966bSEric W. Biederman static int (*vlan_ioctl_hook) (struct net *, void __user *arg);
9471da177e4SLinus Torvalds 
948881d966bSEric W. Biederman void vlan_ioctl_set(int (*hook) (struct net *, void __user *))
9491da177e4SLinus Torvalds {
9504a3e2f71SArjan van de Ven 	mutex_lock(&vlan_ioctl_mutex);
9511da177e4SLinus Torvalds 	vlan_ioctl_hook = hook;
9524a3e2f71SArjan van de Ven 	mutex_unlock(&vlan_ioctl_mutex);
9531da177e4SLinus Torvalds }
9541da177e4SLinus Torvalds EXPORT_SYMBOL(vlan_ioctl_set);
9551da177e4SLinus Torvalds 
9564a3e2f71SArjan van de Ven static DEFINE_MUTEX(dlci_ioctl_mutex);
9571da177e4SLinus Torvalds static int (*dlci_ioctl_hook) (unsigned int, void __user *);
9581da177e4SLinus Torvalds 
9591da177e4SLinus Torvalds void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
9601da177e4SLinus Torvalds {
9614a3e2f71SArjan van de Ven 	mutex_lock(&dlci_ioctl_mutex);
9621da177e4SLinus Torvalds 	dlci_ioctl_hook = hook;
9634a3e2f71SArjan van de Ven 	mutex_unlock(&dlci_ioctl_mutex);
9641da177e4SLinus Torvalds }
9651da177e4SLinus Torvalds EXPORT_SYMBOL(dlci_ioctl_set);
9661da177e4SLinus Torvalds 
9676b96018bSArnd Bergmann static long sock_do_ioctl(struct net *net, struct socket *sock,
9686b96018bSArnd Bergmann 				 unsigned int cmd, unsigned long arg)
9696b96018bSArnd Bergmann {
9706b96018bSArnd Bergmann 	int err;
9716b96018bSArnd Bergmann 	void __user *argp = (void __user *)arg;
9726b96018bSArnd Bergmann 
9736b96018bSArnd Bergmann 	err = sock->ops->ioctl(sock, cmd, arg);
9746b96018bSArnd Bergmann 
9756b96018bSArnd Bergmann 	/*
9766b96018bSArnd Bergmann 	 * If this ioctl is unknown try to hand it down
9776b96018bSArnd Bergmann 	 * to the NIC driver.
9786b96018bSArnd Bergmann 	 */
97936fd633eSAl Viro 	if (err != -ENOIOCTLCMD)
9806b96018bSArnd Bergmann 		return err;
9816b96018bSArnd Bergmann 
98236fd633eSAl Viro 	if (cmd == SIOCGIFCONF) {
98336fd633eSAl Viro 		struct ifconf ifc;
98436fd633eSAl Viro 		if (copy_from_user(&ifc, argp, sizeof(struct ifconf)))
98536fd633eSAl Viro 			return -EFAULT;
98636fd633eSAl Viro 		rtnl_lock();
98736fd633eSAl Viro 		err = dev_ifconf(net, &ifc, sizeof(struct ifreq));
98836fd633eSAl Viro 		rtnl_unlock();
98936fd633eSAl Viro 		if (!err && copy_to_user(argp, &ifc, sizeof(struct ifconf)))
99036fd633eSAl Viro 			err = -EFAULT;
99144c02a2cSAl Viro 	} else {
99244c02a2cSAl Viro 		struct ifreq ifr;
99344c02a2cSAl Viro 		bool need_copyout;
99444c02a2cSAl Viro 		if (copy_from_user(&ifr, argp, sizeof(struct ifreq)))
99544c02a2cSAl Viro 			return -EFAULT;
99644c02a2cSAl Viro 		err = dev_ioctl(net, cmd, &ifr, &need_copyout);
99744c02a2cSAl Viro 		if (!err && need_copyout)
99844c02a2cSAl Viro 			if (copy_to_user(argp, &ifr, sizeof(struct ifreq)))
99944c02a2cSAl Viro 				return -EFAULT;
100036fd633eSAl Viro 	}
10016b96018bSArnd Bergmann 	return err;
10026b96018bSArnd Bergmann }
10036b96018bSArnd Bergmann 
10041da177e4SLinus Torvalds /*
10051da177e4SLinus Torvalds  *	With an ioctl, arg may well be a user mode pointer, but we don't know
10061da177e4SLinus Torvalds  *	what to do with it - that's up to the protocol still.
10071da177e4SLinus Torvalds  */
10081da177e4SLinus Torvalds 
1009d8d211a2SKirill Tkhai struct ns_common *get_net_ns(struct ns_common *ns)
1010c62cce2cSAndrey Vagin {
1011c62cce2cSAndrey Vagin 	return &get_net(container_of(ns, struct net, ns))->ns;
1012c62cce2cSAndrey Vagin }
1013d8d211a2SKirill Tkhai EXPORT_SYMBOL_GPL(get_net_ns);
1014c62cce2cSAndrey Vagin 
10151da177e4SLinus Torvalds static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
10161da177e4SLinus Torvalds {
10171da177e4SLinus Torvalds 	struct socket *sock;
1018881d966bSEric W. Biederman 	struct sock *sk;
10191da177e4SLinus Torvalds 	void __user *argp = (void __user *)arg;
10201da177e4SLinus Torvalds 	int pid, err;
1021881d966bSEric W. Biederman 	struct net *net;
10221da177e4SLinus Torvalds 
1023b69aee04SEric Dumazet 	sock = file->private_data;
1024881d966bSEric W. Biederman 	sk = sock->sk;
10253b1e0a65SYOSHIFUJI Hideaki 	net = sock_net(sk);
102644c02a2cSAl Viro 	if (unlikely(cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))) {
102744c02a2cSAl Viro 		struct ifreq ifr;
102844c02a2cSAl Viro 		bool need_copyout;
102944c02a2cSAl Viro 		if (copy_from_user(&ifr, argp, sizeof(struct ifreq)))
103044c02a2cSAl Viro 			return -EFAULT;
103144c02a2cSAl Viro 		err = dev_ioctl(net, cmd, &ifr, &need_copyout);
103244c02a2cSAl Viro 		if (!err && need_copyout)
103344c02a2cSAl Viro 			if (copy_to_user(argp, &ifr, sizeof(struct ifreq)))
103444c02a2cSAl Viro 				return -EFAULT;
10351da177e4SLinus Torvalds 	} else
10363d23e349SJohannes Berg #ifdef CONFIG_WEXT_CORE
10371da177e4SLinus Torvalds 	if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
1038b1b0c245SAl Viro 		err = wext_handle_ioctl(net, cmd, argp);
10391da177e4SLinus Torvalds 	} else
10403d23e349SJohannes Berg #endif
10411da177e4SLinus Torvalds 		switch (cmd) {
10421da177e4SLinus Torvalds 		case FIOSETOWN:
10431da177e4SLinus Torvalds 		case SIOCSPGRP:
10441da177e4SLinus Torvalds 			err = -EFAULT;
10451da177e4SLinus Torvalds 			if (get_user(pid, (int __user *)argp))
10461da177e4SLinus Torvalds 				break;
1047393cc3f5SJiri Slaby 			err = f_setown(sock->file, pid, 1);
10481da177e4SLinus Torvalds 			break;
10491da177e4SLinus Torvalds 		case FIOGETOWN:
10501da177e4SLinus Torvalds 		case SIOCGPGRP:
1051609d7fa9SEric W. Biederman 			err = put_user(f_getown(sock->file),
105289bddce5SStephen Hemminger 				       (int __user *)argp);
10531da177e4SLinus Torvalds 			break;
10541da177e4SLinus Torvalds 		case SIOCGIFBR:
10551da177e4SLinus Torvalds 		case SIOCSIFBR:
10561da177e4SLinus Torvalds 		case SIOCBRADDBR:
10571da177e4SLinus Torvalds 		case SIOCBRDELBR:
10581da177e4SLinus Torvalds 			err = -ENOPKG;
10591da177e4SLinus Torvalds 			if (!br_ioctl_hook)
10601da177e4SLinus Torvalds 				request_module("bridge");
10611da177e4SLinus Torvalds 
10624a3e2f71SArjan van de Ven 			mutex_lock(&br_ioctl_mutex);
10631da177e4SLinus Torvalds 			if (br_ioctl_hook)
1064881d966bSEric W. Biederman 				err = br_ioctl_hook(net, cmd, argp);
10654a3e2f71SArjan van de Ven 			mutex_unlock(&br_ioctl_mutex);
10661da177e4SLinus Torvalds 			break;
10671da177e4SLinus Torvalds 		case SIOCGIFVLAN:
10681da177e4SLinus Torvalds 		case SIOCSIFVLAN:
10691da177e4SLinus Torvalds 			err = -ENOPKG;
10701da177e4SLinus Torvalds 			if (!vlan_ioctl_hook)
10711da177e4SLinus Torvalds 				request_module("8021q");
10721da177e4SLinus Torvalds 
10734a3e2f71SArjan van de Ven 			mutex_lock(&vlan_ioctl_mutex);
10741da177e4SLinus Torvalds 			if (vlan_ioctl_hook)
1075881d966bSEric W. Biederman 				err = vlan_ioctl_hook(net, argp);
10764a3e2f71SArjan van de Ven 			mutex_unlock(&vlan_ioctl_mutex);
10771da177e4SLinus Torvalds 			break;
10781da177e4SLinus Torvalds 		case SIOCADDDLCI:
10791da177e4SLinus Torvalds 		case SIOCDELDLCI:
10801da177e4SLinus Torvalds 			err = -ENOPKG;
10811da177e4SLinus Torvalds 			if (!dlci_ioctl_hook)
10821da177e4SLinus Torvalds 				request_module("dlci");
10831da177e4SLinus Torvalds 
10844a3e2f71SArjan van de Ven 			mutex_lock(&dlci_ioctl_mutex);
10857512cbf6SPavel Emelyanov 			if (dlci_ioctl_hook)
10861da177e4SLinus Torvalds 				err = dlci_ioctl_hook(cmd, argp);
10874a3e2f71SArjan van de Ven 			mutex_unlock(&dlci_ioctl_mutex);
10881da177e4SLinus Torvalds 			break;
1089c62cce2cSAndrey Vagin 		case SIOCGSKNS:
1090c62cce2cSAndrey Vagin 			err = -EPERM;
1091c62cce2cSAndrey Vagin 			if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
1092c62cce2cSAndrey Vagin 				break;
1093c62cce2cSAndrey Vagin 
1094c62cce2cSAndrey Vagin 			err = open_related_ns(&net->ns, get_net_ns);
1095c62cce2cSAndrey Vagin 			break;
10961da177e4SLinus Torvalds 		default:
10976b96018bSArnd Bergmann 			err = sock_do_ioctl(net, sock, cmd, arg);
10981da177e4SLinus Torvalds 			break;
10991da177e4SLinus Torvalds 		}
11001da177e4SLinus Torvalds 	return err;
11011da177e4SLinus Torvalds }
11021da177e4SLinus Torvalds 
11031da177e4SLinus Torvalds int sock_create_lite(int family, int type, int protocol, struct socket **res)
11041da177e4SLinus Torvalds {
11051da177e4SLinus Torvalds 	int err;
11061da177e4SLinus Torvalds 	struct socket *sock = NULL;
11071da177e4SLinus Torvalds 
11081da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, 1);
11091da177e4SLinus Torvalds 	if (err)
11101da177e4SLinus Torvalds 		goto out;
11111da177e4SLinus Torvalds 
11121da177e4SLinus Torvalds 	sock = sock_alloc();
11131da177e4SLinus Torvalds 	if (!sock) {
11141da177e4SLinus Torvalds 		err = -ENOMEM;
11151da177e4SLinus Torvalds 		goto out;
11161da177e4SLinus Torvalds 	}
11171da177e4SLinus Torvalds 
11181da177e4SLinus Torvalds 	sock->type = type;
11197420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, 1);
11207420ed23SVenkat Yekkirala 	if (err)
11217420ed23SVenkat Yekkirala 		goto out_release;
11227420ed23SVenkat Yekkirala 
11231da177e4SLinus Torvalds out:
11241da177e4SLinus Torvalds 	*res = sock;
11251da177e4SLinus Torvalds 	return err;
11267420ed23SVenkat Yekkirala out_release:
11277420ed23SVenkat Yekkirala 	sock_release(sock);
11287420ed23SVenkat Yekkirala 	sock = NULL;
11297420ed23SVenkat Yekkirala 	goto out;
11301da177e4SLinus Torvalds }
1131c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_lite);
11321da177e4SLinus Torvalds 
113315252423SChristoph Hellwig static struct wait_queue_head *sock_get_poll_head(struct file *file,
113415252423SChristoph Hellwig 		__poll_t events)
113515252423SChristoph Hellwig {
113615252423SChristoph Hellwig 	struct socket *sock = file->private_data;
113715252423SChristoph Hellwig 
113815252423SChristoph Hellwig 	if (!sock->ops->poll_mask)
113915252423SChristoph Hellwig 		return NULL;
114015252423SChristoph Hellwig 	sock_poll_busy_loop(sock, events);
114115252423SChristoph Hellwig 	return sk_sleep(sock->sk);
114215252423SChristoph Hellwig }
114315252423SChristoph Hellwig 
114415252423SChristoph Hellwig static __poll_t sock_poll_mask(struct file *file, __poll_t events)
114515252423SChristoph Hellwig {
114615252423SChristoph Hellwig 	struct socket *sock = file->private_data;
114715252423SChristoph Hellwig 
114815252423SChristoph Hellwig 	/*
114915252423SChristoph Hellwig 	 * We need to be sure we are in sync with the socket flags modification.
115015252423SChristoph Hellwig 	 *
115115252423SChristoph Hellwig 	 * This memory barrier is paired in the wq_has_sleeper.
115215252423SChristoph Hellwig 	 */
115315252423SChristoph Hellwig 	smp_mb();
115415252423SChristoph Hellwig 
115515252423SChristoph Hellwig 	/* this socket can poll_ll so tell the system call */
115615252423SChristoph Hellwig 	return sock->ops->poll_mask(sock, events) |
115715252423SChristoph Hellwig 		(sk_can_busy_loop(sock->sk) ? POLL_BUSY_LOOP : 0);
115815252423SChristoph Hellwig }
115915252423SChristoph Hellwig 
11601da177e4SLinus Torvalds /* No kernel lock held - perfect */
1161ade994f4SAl Viro static __poll_t sock_poll(struct file *file, poll_table *wait)
11621da177e4SLinus Torvalds {
11633cafb376SChristoph Hellwig 	struct socket *sock = file->private_data;
116415252423SChristoph Hellwig 	__poll_t events = poll_requested_events(wait), mask = 0;
11651da177e4SLinus Torvalds 
116615252423SChristoph Hellwig 	if (sock->ops->poll) {
11673cafb376SChristoph Hellwig 		sock_poll_busy_loop(sock, events);
116815252423SChristoph Hellwig 		mask = sock->ops->poll(file, sock, wait);
116915252423SChristoph Hellwig 	} else if (sock->ops->poll_mask) {
117015252423SChristoph Hellwig 		sock_poll_wait(file, sock_get_poll_head(file, events), wait);
117115252423SChristoph Hellwig 		mask = sock->ops->poll_mask(sock, events);
117215252423SChristoph Hellwig 	}
117315252423SChristoph Hellwig 
117415252423SChristoph Hellwig 	return mask | sock_poll_busy_flag(sock);
11751da177e4SLinus Torvalds }
11761da177e4SLinus Torvalds 
11771da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma)
11781da177e4SLinus Torvalds {
1179b69aee04SEric Dumazet 	struct socket *sock = file->private_data;
11801da177e4SLinus Torvalds 
11811da177e4SLinus Torvalds 	return sock->ops->mmap(file, sock, vma);
11821da177e4SLinus Torvalds }
11831da177e4SLinus Torvalds 
118420380731SArnaldo Carvalho de Melo static int sock_close(struct inode *inode, struct file *filp)
11851da177e4SLinus Torvalds {
11866d8c50dcSCong Wang 	__sock_release(SOCKET_I(inode), inode);
11871da177e4SLinus Torvalds 	return 0;
11881da177e4SLinus Torvalds }
11891da177e4SLinus Torvalds 
11901da177e4SLinus Torvalds /*
11911da177e4SLinus Torvalds  *	Update the socket async list
11921da177e4SLinus Torvalds  *
11931da177e4SLinus Torvalds  *	Fasync_list locking strategy.
11941da177e4SLinus Torvalds  *
11951da177e4SLinus Torvalds  *	1. fasync_list is modified only under process context socket lock
11961da177e4SLinus Torvalds  *	   i.e. under semaphore.
11971da177e4SLinus Torvalds  *	2. fasync_list is used under read_lock(&sk->sk_callback_lock)
1198989a2979SEric Dumazet  *	   or under socket lock
11991da177e4SLinus Torvalds  */
12001da177e4SLinus Torvalds 
12011da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on)
12021da177e4SLinus Torvalds {
1203989a2979SEric Dumazet 	struct socket *sock = filp->private_data;
1204989a2979SEric Dumazet 	struct sock *sk = sock->sk;
1205eaefd110SEric Dumazet 	struct socket_wq *wq;
12061da177e4SLinus Torvalds 
1207989a2979SEric Dumazet 	if (sk == NULL)
12081da177e4SLinus Torvalds 		return -EINVAL;
12091da177e4SLinus Torvalds 
12101da177e4SLinus Torvalds 	lock_sock(sk);
12111e1d04e6SHannes Frederic Sowa 	wq = rcu_dereference_protected(sock->wq, lockdep_sock_is_held(sk));
1212eaefd110SEric Dumazet 	fasync_helper(fd, filp, on, &wq->fasync_list);
12131da177e4SLinus Torvalds 
1214eaefd110SEric Dumazet 	if (!wq->fasync_list)
1215bcdce719SEric Dumazet 		sock_reset_flag(sk, SOCK_FASYNC);
1216989a2979SEric Dumazet 	else
1217989a2979SEric Dumazet 		sock_set_flag(sk, SOCK_FASYNC);
12181da177e4SLinus Torvalds 
1219989a2979SEric Dumazet 	release_sock(sk);
12201da177e4SLinus Torvalds 	return 0;
12211da177e4SLinus Torvalds }
12221da177e4SLinus Torvalds 
1223ceb5d58bSEric Dumazet /* This function may be called only under rcu_lock */
12241da177e4SLinus Torvalds 
1225ceb5d58bSEric Dumazet int sock_wake_async(struct socket_wq *wq, int how, int band)
12261da177e4SLinus Torvalds {
1227ceb5d58bSEric Dumazet 	if (!wq || !wq->fasync_list)
1228ceb5d58bSEric Dumazet 		return -1;
122943815482SEric Dumazet 
123089bddce5SStephen Hemminger 	switch (how) {
12318d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_WAITD:
1232ceb5d58bSEric Dumazet 		if (test_bit(SOCKWQ_ASYNC_WAITDATA, &wq->flags))
12331da177e4SLinus Torvalds 			break;
12341da177e4SLinus Torvalds 		goto call_kill;
12358d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_SPACE:
1236ceb5d58bSEric Dumazet 		if (!test_and_clear_bit(SOCKWQ_ASYNC_NOSPACE, &wq->flags))
12371da177e4SLinus Torvalds 			break;
12381da177e4SLinus Torvalds 		/* fall through */
12398d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_IO:
12401da177e4SLinus Torvalds call_kill:
124143815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGIO, band);
12421da177e4SLinus Torvalds 		break;
12438d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_URG:
124443815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGURG, band);
12451da177e4SLinus Torvalds 	}
1246ceb5d58bSEric Dumazet 
12471da177e4SLinus Torvalds 	return 0;
12481da177e4SLinus Torvalds }
1249c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_wake_async);
12501da177e4SLinus Torvalds 
1251721db93aSPavel Emelyanov int __sock_create(struct net *net, int family, int type, int protocol,
125289bddce5SStephen Hemminger 			 struct socket **res, int kern)
12531da177e4SLinus Torvalds {
12541da177e4SLinus Torvalds 	int err;
12551da177e4SLinus Torvalds 	struct socket *sock;
125655737fdaSStephen Hemminger 	const struct net_proto_family *pf;
12571da177e4SLinus Torvalds 
12581da177e4SLinus Torvalds 	/*
12591da177e4SLinus Torvalds 	 *      Check protocol is in range
12601da177e4SLinus Torvalds 	 */
12611da177e4SLinus Torvalds 	if (family < 0 || family >= NPROTO)
12621da177e4SLinus Torvalds 		return -EAFNOSUPPORT;
12631da177e4SLinus Torvalds 	if (type < 0 || type >= SOCK_MAX)
12641da177e4SLinus Torvalds 		return -EINVAL;
12651da177e4SLinus Torvalds 
12661da177e4SLinus Torvalds 	/* Compatibility.
12671da177e4SLinus Torvalds 
12681da177e4SLinus Torvalds 	   This uglymoron is moved from INET layer to here to avoid
12691da177e4SLinus Torvalds 	   deadlock in module load.
12701da177e4SLinus Torvalds 	 */
12711da177e4SLinus Torvalds 	if (family == PF_INET && type == SOCK_PACKET) {
1272f3c98690Sliping.zhang 		pr_info_once("%s uses obsolete (PF_INET,SOCK_PACKET)\n",
127389bddce5SStephen Hemminger 			     current->comm);
12741da177e4SLinus Torvalds 		family = PF_PACKET;
12751da177e4SLinus Torvalds 	}
12761da177e4SLinus Torvalds 
12771da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, kern);
12781da177e4SLinus Torvalds 	if (err)
12791da177e4SLinus Torvalds 		return err;
12801da177e4SLinus Torvalds 
128155737fdaSStephen Hemminger 	/*
128255737fdaSStephen Hemminger 	 *	Allocate the socket and allow the family to set things up. if
128355737fdaSStephen Hemminger 	 *	the protocol is 0, the family is instructed to select an appropriate
128455737fdaSStephen Hemminger 	 *	default.
128555737fdaSStephen Hemminger 	 */
128655737fdaSStephen Hemminger 	sock = sock_alloc();
128755737fdaSStephen Hemminger 	if (!sock) {
1288e87cc472SJoe Perches 		net_warn_ratelimited("socket: no more sockets\n");
128955737fdaSStephen Hemminger 		return -ENFILE;	/* Not exactly a match, but its the
129055737fdaSStephen Hemminger 				   closest posix thing */
129155737fdaSStephen Hemminger 	}
129255737fdaSStephen Hemminger 
129355737fdaSStephen Hemminger 	sock->type = type;
129455737fdaSStephen Hemminger 
129595a5afcaSJohannes Berg #ifdef CONFIG_MODULES
12961da177e4SLinus Torvalds 	/* Attempt to load a protocol module if the find failed.
12971da177e4SLinus Torvalds 	 *
12981da177e4SLinus Torvalds 	 * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
12991da177e4SLinus Torvalds 	 * requested real, full-featured networking support upon configuration.
13001da177e4SLinus Torvalds 	 * Otherwise module support will break!
13011da177e4SLinus Torvalds 	 */
1302190683a9SEric Dumazet 	if (rcu_access_pointer(net_families[family]) == NULL)
13031da177e4SLinus Torvalds 		request_module("net-pf-%d", family);
13041da177e4SLinus Torvalds #endif
13051da177e4SLinus Torvalds 
130655737fdaSStephen Hemminger 	rcu_read_lock();
130755737fdaSStephen Hemminger 	pf = rcu_dereference(net_families[family]);
13081da177e4SLinus Torvalds 	err = -EAFNOSUPPORT;
130955737fdaSStephen Hemminger 	if (!pf)
131055737fdaSStephen Hemminger 		goto out_release;
13111da177e4SLinus Torvalds 
13121da177e4SLinus Torvalds 	/*
13131da177e4SLinus Torvalds 	 * We will call the ->create function, that possibly is in a loadable
13141da177e4SLinus Torvalds 	 * module, so we have to bump that loadable module refcnt first.
13151da177e4SLinus Torvalds 	 */
131655737fdaSStephen Hemminger 	if (!try_module_get(pf->owner))
13171da177e4SLinus Torvalds 		goto out_release;
13181da177e4SLinus Torvalds 
131955737fdaSStephen Hemminger 	/* Now protected by module ref count */
132055737fdaSStephen Hemminger 	rcu_read_unlock();
132155737fdaSStephen Hemminger 
13223f378b68SEric Paris 	err = pf->create(net, sock, protocol, kern);
132355737fdaSStephen Hemminger 	if (err < 0)
13241da177e4SLinus Torvalds 		goto out_module_put;
1325a79af59eSFrank Filz 
13261da177e4SLinus Torvalds 	/*
13271da177e4SLinus Torvalds 	 * Now to bump the refcnt of the [loadable] module that owns this
13281da177e4SLinus Torvalds 	 * socket at sock_release time we decrement its refcnt.
13291da177e4SLinus Torvalds 	 */
133055737fdaSStephen Hemminger 	if (!try_module_get(sock->ops->owner))
133155737fdaSStephen Hemminger 		goto out_module_busy;
133255737fdaSStephen Hemminger 
13331da177e4SLinus Torvalds 	/*
13341da177e4SLinus Torvalds 	 * Now that we're done with the ->create function, the [loadable]
13351da177e4SLinus Torvalds 	 * module can have its refcnt decremented
13361da177e4SLinus Torvalds 	 */
133755737fdaSStephen Hemminger 	module_put(pf->owner);
13387420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, kern);
13397420ed23SVenkat Yekkirala 	if (err)
13403b185525SHerbert Xu 		goto out_sock_release;
134155737fdaSStephen Hemminger 	*res = sock;
13421da177e4SLinus Torvalds 
134355737fdaSStephen Hemminger 	return 0;
134455737fdaSStephen Hemminger 
134555737fdaSStephen Hemminger out_module_busy:
134655737fdaSStephen Hemminger 	err = -EAFNOSUPPORT;
13471da177e4SLinus Torvalds out_module_put:
134855737fdaSStephen Hemminger 	sock->ops = NULL;
134955737fdaSStephen Hemminger 	module_put(pf->owner);
135055737fdaSStephen Hemminger out_sock_release:
13511da177e4SLinus Torvalds 	sock_release(sock);
135255737fdaSStephen Hemminger 	return err;
135355737fdaSStephen Hemminger 
135455737fdaSStephen Hemminger out_release:
135555737fdaSStephen Hemminger 	rcu_read_unlock();
135655737fdaSStephen Hemminger 	goto out_sock_release;
13571da177e4SLinus Torvalds }
1358721db93aSPavel Emelyanov EXPORT_SYMBOL(__sock_create);
13591da177e4SLinus Torvalds 
13601da177e4SLinus Torvalds int sock_create(int family, int type, int protocol, struct socket **res)
13611da177e4SLinus Torvalds {
13621b8d7ae4SEric W. Biederman 	return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
13631da177e4SLinus Torvalds }
1364c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create);
13651da177e4SLinus Torvalds 
1366eeb1bd5cSEric W. Biederman int sock_create_kern(struct net *net, int family, int type, int protocol, struct socket **res)
13671da177e4SLinus Torvalds {
1368eeb1bd5cSEric W. Biederman 	return __sock_create(net, family, type, protocol, res, 1);
13691da177e4SLinus Torvalds }
1370c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_kern);
13711da177e4SLinus Torvalds 
13729d6a15c3SDominik Brodowski int __sys_socket(int family, int type, int protocol)
13731da177e4SLinus Torvalds {
13741da177e4SLinus Torvalds 	int retval;
13751da177e4SLinus Torvalds 	struct socket *sock;
1376a677a039SUlrich Drepper 	int flags;
1377a677a039SUlrich Drepper 
1378e38b36f3SUlrich Drepper 	/* Check the SOCK_* constants for consistency.  */
1379e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
1380e38b36f3SUlrich Drepper 	BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
1381e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);
1382e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);
1383e38b36f3SUlrich Drepper 
1384a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
138577d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1386a677a039SUlrich Drepper 		return -EINVAL;
1387a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
13881da177e4SLinus Torvalds 
1389aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1390aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1391aaca0bdcSUlrich Drepper 
13921da177e4SLinus Torvalds 	retval = sock_create(family, type, protocol, &sock);
13931da177e4SLinus Torvalds 	if (retval < 0)
13941da177e4SLinus Torvalds 		return retval;
13951da177e4SLinus Torvalds 
13968e1611e2SAl Viro 	return sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
13971da177e4SLinus Torvalds }
13981da177e4SLinus Torvalds 
13999d6a15c3SDominik Brodowski SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
14009d6a15c3SDominik Brodowski {
14019d6a15c3SDominik Brodowski 	return __sys_socket(family, type, protocol);
14029d6a15c3SDominik Brodowski }
14039d6a15c3SDominik Brodowski 
14041da177e4SLinus Torvalds /*
14051da177e4SLinus Torvalds  *	Create a pair of connected sockets.
14061da177e4SLinus Torvalds  */
14071da177e4SLinus Torvalds 
14086debc8d8SDominik Brodowski int __sys_socketpair(int family, int type, int protocol, int __user *usockvec)
14091da177e4SLinus Torvalds {
14101da177e4SLinus Torvalds 	struct socket *sock1, *sock2;
14111da177e4SLinus Torvalds 	int fd1, fd2, err;
1412db349509SAl Viro 	struct file *newfile1, *newfile2;
1413a677a039SUlrich Drepper 	int flags;
1414a677a039SUlrich Drepper 
1415a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
141677d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1417a677a039SUlrich Drepper 		return -EINVAL;
1418a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
14191da177e4SLinus Torvalds 
1420aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1421aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1422aaca0bdcSUlrich Drepper 
14231da177e4SLinus Torvalds 	/*
1424016a266bSAl Viro 	 * reserve descriptors and make sure we won't fail
1425016a266bSAl Viro 	 * to return them to userland.
1426016a266bSAl Viro 	 */
1427016a266bSAl Viro 	fd1 = get_unused_fd_flags(flags);
1428016a266bSAl Viro 	if (unlikely(fd1 < 0))
1429016a266bSAl Viro 		return fd1;
1430016a266bSAl Viro 
1431016a266bSAl Viro 	fd2 = get_unused_fd_flags(flags);
1432016a266bSAl Viro 	if (unlikely(fd2 < 0)) {
1433016a266bSAl Viro 		put_unused_fd(fd1);
1434016a266bSAl Viro 		return fd2;
1435016a266bSAl Viro 	}
1436016a266bSAl Viro 
1437016a266bSAl Viro 	err = put_user(fd1, &usockvec[0]);
1438016a266bSAl Viro 	if (err)
1439016a266bSAl Viro 		goto out;
1440016a266bSAl Viro 
1441016a266bSAl Viro 	err = put_user(fd2, &usockvec[1]);
1442016a266bSAl Viro 	if (err)
1443016a266bSAl Viro 		goto out;
1444016a266bSAl Viro 
1445016a266bSAl Viro 	/*
14461da177e4SLinus Torvalds 	 * Obtain the first socket and check if the underlying protocol
14471da177e4SLinus Torvalds 	 * supports the socketpair call.
14481da177e4SLinus Torvalds 	 */
14491da177e4SLinus Torvalds 
14501da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock1);
1451016a266bSAl Viro 	if (unlikely(err < 0))
14521da177e4SLinus Torvalds 		goto out;
14531da177e4SLinus Torvalds 
14541da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock2);
1455016a266bSAl Viro 	if (unlikely(err < 0)) {
1456016a266bSAl Viro 		sock_release(sock1);
1457016a266bSAl Viro 		goto out;
1458bf3c23d1SDavid S. Miller 	}
1459d73aa286SYann Droneaud 
1460d47cd945SDavid Herrmann 	err = security_socket_socketpair(sock1, sock2);
1461d47cd945SDavid Herrmann 	if (unlikely(err)) {
1462d47cd945SDavid Herrmann 		sock_release(sock2);
1463d47cd945SDavid Herrmann 		sock_release(sock1);
1464d47cd945SDavid Herrmann 		goto out;
1465d47cd945SDavid Herrmann 	}
1466d47cd945SDavid Herrmann 
1467016a266bSAl Viro 	err = sock1->ops->socketpair(sock1, sock2);
1468016a266bSAl Viro 	if (unlikely(err < 0)) {
1469016a266bSAl Viro 		sock_release(sock2);
1470016a266bSAl Viro 		sock_release(sock1);
1471016a266bSAl Viro 		goto out;
147228407630SAl Viro 	}
147328407630SAl Viro 
1474aab174f0SLinus Torvalds 	newfile1 = sock_alloc_file(sock1, flags, NULL);
1475b5ffe634SViresh Kumar 	if (IS_ERR(newfile1)) {
147628407630SAl Viro 		err = PTR_ERR(newfile1);
1477016a266bSAl Viro 		sock_release(sock2);
1478016a266bSAl Viro 		goto out;
147928407630SAl Viro 	}
148028407630SAl Viro 
1481aab174f0SLinus Torvalds 	newfile2 = sock_alloc_file(sock2, flags, NULL);
148228407630SAl Viro 	if (IS_ERR(newfile2)) {
148328407630SAl Viro 		err = PTR_ERR(newfile2);
1484016a266bSAl Viro 		fput(newfile1);
1485016a266bSAl Viro 		goto out;
1486db349509SAl Viro 	}
1487db349509SAl Viro 
1488157cf649SAl Viro 	audit_fd_pair(fd1, fd2);
1489d73aa286SYann Droneaud 
1490db349509SAl Viro 	fd_install(fd1, newfile1);
1491db349509SAl Viro 	fd_install(fd2, newfile2);
14921da177e4SLinus Torvalds 	return 0;
14931da177e4SLinus Torvalds 
14941da177e4SLinus Torvalds out:
1495016a266bSAl Viro 	put_unused_fd(fd2);
1496016a266bSAl Viro 	put_unused_fd(fd1);
14971da177e4SLinus Torvalds 	return err;
14981da177e4SLinus Torvalds }
14991da177e4SLinus Torvalds 
15006debc8d8SDominik Brodowski SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
15016debc8d8SDominik Brodowski 		int __user *, usockvec)
15026debc8d8SDominik Brodowski {
15036debc8d8SDominik Brodowski 	return __sys_socketpair(family, type, protocol, usockvec);
15046debc8d8SDominik Brodowski }
15056debc8d8SDominik Brodowski 
15061da177e4SLinus Torvalds /*
15071da177e4SLinus Torvalds  *	Bind a name to a socket. Nothing much to do here since it's
15081da177e4SLinus Torvalds  *	the protocol's responsibility to handle the local address.
15091da177e4SLinus Torvalds  *
15101da177e4SLinus Torvalds  *	We move the socket address to kernel space before we call
15111da177e4SLinus Torvalds  *	the protocol layer (having also checked the address is ok).
15121da177e4SLinus Torvalds  */
15131da177e4SLinus Torvalds 
1514a87d35d8SDominik Brodowski int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)
15151da177e4SLinus Torvalds {
15161da177e4SLinus Torvalds 	struct socket *sock;
1517230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
15186cb153caSBenjamin LaHaise 	int err, fput_needed;
15191da177e4SLinus Torvalds 
152089bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
152189bddce5SStephen Hemminger 	if (sock) {
152243db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(umyaddr, addrlen, &address);
152389bddce5SStephen Hemminger 		if (err >= 0) {
152489bddce5SStephen Hemminger 			err = security_socket_bind(sock,
1525230b1839SYOSHIFUJI Hideaki 						   (struct sockaddr *)&address,
152689bddce5SStephen Hemminger 						   addrlen);
15276cb153caSBenjamin LaHaise 			if (!err)
15286cb153caSBenjamin LaHaise 				err = sock->ops->bind(sock,
152989bddce5SStephen Hemminger 						      (struct sockaddr *)
1530230b1839SYOSHIFUJI Hideaki 						      &address, addrlen);
15311da177e4SLinus Torvalds 		}
15326cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
15331da177e4SLinus Torvalds 	}
15341da177e4SLinus Torvalds 	return err;
15351da177e4SLinus Torvalds }
15361da177e4SLinus Torvalds 
1537a87d35d8SDominik Brodowski SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
1538a87d35d8SDominik Brodowski {
1539a87d35d8SDominik Brodowski 	return __sys_bind(fd, umyaddr, addrlen);
1540a87d35d8SDominik Brodowski }
1541a87d35d8SDominik Brodowski 
15421da177e4SLinus Torvalds /*
15431da177e4SLinus Torvalds  *	Perform a listen. Basically, we allow the protocol to do anything
15441da177e4SLinus Torvalds  *	necessary for a listen, and if that works, we mark the socket as
15451da177e4SLinus Torvalds  *	ready for listening.
15461da177e4SLinus Torvalds  */
15471da177e4SLinus Torvalds 
154825e290eeSDominik Brodowski int __sys_listen(int fd, int backlog)
15491da177e4SLinus Torvalds {
15501da177e4SLinus Torvalds 	struct socket *sock;
15516cb153caSBenjamin LaHaise 	int err, fput_needed;
1552b8e1f9b5SPavel Emelyanov 	int somaxconn;
15531da177e4SLinus Torvalds 
155489bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
155589bddce5SStephen Hemminger 	if (sock) {
15568efa6e93SPavel Emelyanov 		somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
155795c96174SEric Dumazet 		if ((unsigned int)backlog > somaxconn)
1558b8e1f9b5SPavel Emelyanov 			backlog = somaxconn;
15591da177e4SLinus Torvalds 
15601da177e4SLinus Torvalds 		err = security_socket_listen(sock, backlog);
15616cb153caSBenjamin LaHaise 		if (!err)
15621da177e4SLinus Torvalds 			err = sock->ops->listen(sock, backlog);
15636cb153caSBenjamin LaHaise 
15646cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
15651da177e4SLinus Torvalds 	}
15661da177e4SLinus Torvalds 	return err;
15671da177e4SLinus Torvalds }
15681da177e4SLinus Torvalds 
156925e290eeSDominik Brodowski SYSCALL_DEFINE2(listen, int, fd, int, backlog)
157025e290eeSDominik Brodowski {
157125e290eeSDominik Brodowski 	return __sys_listen(fd, backlog);
157225e290eeSDominik Brodowski }
157325e290eeSDominik Brodowski 
15741da177e4SLinus Torvalds /*
15751da177e4SLinus Torvalds  *	For accept, we attempt to create a new socket, set up the link
15761da177e4SLinus Torvalds  *	with the client, wake up the client, then return the new
15771da177e4SLinus Torvalds  *	connected fd. We collect the address of the connector in kernel
15781da177e4SLinus Torvalds  *	space and move it to user at the very end. This is unclean because
15791da177e4SLinus Torvalds  *	we open the socket then return an error.
15801da177e4SLinus Torvalds  *
15811da177e4SLinus Torvalds  *	1003.1g adds the ability to recvmsg() to query connection pending
15821da177e4SLinus Torvalds  *	status to recvmsg. We need to add that support in a way thats
1583b903036aSGeert Uytterhoeven  *	clean when we restructure accept also.
15841da177e4SLinus Torvalds  */
15851da177e4SLinus Torvalds 
15864541e805SDominik Brodowski int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
15874541e805SDominik Brodowski 		  int __user *upeer_addrlen, int flags)
15881da177e4SLinus Torvalds {
15891da177e4SLinus Torvalds 	struct socket *sock, *newsock;
159039d8c1b6SDavid S. Miller 	struct file *newfile;
15916cb153caSBenjamin LaHaise 	int err, len, newfd, fput_needed;
1592230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
15931da177e4SLinus Torvalds 
159477d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1595aaca0bdcSUlrich Drepper 		return -EINVAL;
1596aaca0bdcSUlrich Drepper 
1597aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1598aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1599aaca0bdcSUlrich Drepper 
16006cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
16011da177e4SLinus Torvalds 	if (!sock)
16021da177e4SLinus Torvalds 		goto out;
16031da177e4SLinus Torvalds 
16041da177e4SLinus Torvalds 	err = -ENFILE;
1605c6d409cfSEric Dumazet 	newsock = sock_alloc();
1606c6d409cfSEric Dumazet 	if (!newsock)
16071da177e4SLinus Torvalds 		goto out_put;
16081da177e4SLinus Torvalds 
16091da177e4SLinus Torvalds 	newsock->type = sock->type;
16101da177e4SLinus Torvalds 	newsock->ops = sock->ops;
16111da177e4SLinus Torvalds 
16121da177e4SLinus Torvalds 	/*
16131da177e4SLinus Torvalds 	 * We don't need try_module_get here, as the listening socket (sock)
16141da177e4SLinus Torvalds 	 * has the protocol module (sock->ops->owner) held.
16151da177e4SLinus Torvalds 	 */
16161da177e4SLinus Torvalds 	__module_get(newsock->ops->owner);
16171da177e4SLinus Torvalds 
161828407630SAl Viro 	newfd = get_unused_fd_flags(flags);
161939d8c1b6SDavid S. Miller 	if (unlikely(newfd < 0)) {
162039d8c1b6SDavid S. Miller 		err = newfd;
16219a1875e6SDavid S. Miller 		sock_release(newsock);
16229a1875e6SDavid S. Miller 		goto out_put;
162339d8c1b6SDavid S. Miller 	}
1624aab174f0SLinus Torvalds 	newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name);
1625b5ffe634SViresh Kumar 	if (IS_ERR(newfile)) {
162628407630SAl Viro 		err = PTR_ERR(newfile);
162728407630SAl Viro 		put_unused_fd(newfd);
162828407630SAl Viro 		goto out_put;
162928407630SAl Viro 	}
163039d8c1b6SDavid S. Miller 
1631a79af59eSFrank Filz 	err = security_socket_accept(sock, newsock);
1632a79af59eSFrank Filz 	if (err)
163339d8c1b6SDavid S. Miller 		goto out_fd;
1634a79af59eSFrank Filz 
1635cdfbabfbSDavid Howells 	err = sock->ops->accept(sock, newsock, sock->file->f_flags, false);
16361da177e4SLinus Torvalds 	if (err < 0)
163739d8c1b6SDavid S. Miller 		goto out_fd;
16381da177e4SLinus Torvalds 
16391da177e4SLinus Torvalds 	if (upeer_sockaddr) {
16409b2c45d4SDenys Vlasenko 		len = newsock->ops->getname(newsock,
16419b2c45d4SDenys Vlasenko 					(struct sockaddr *)&address, 2);
16429b2c45d4SDenys Vlasenko 		if (len < 0) {
16431da177e4SLinus Torvalds 			err = -ECONNABORTED;
164439d8c1b6SDavid S. Miller 			goto out_fd;
16451da177e4SLinus Torvalds 		}
164643db362dSMaciej Żenczykowski 		err = move_addr_to_user(&address,
1647230b1839SYOSHIFUJI Hideaki 					len, upeer_sockaddr, upeer_addrlen);
16481da177e4SLinus Torvalds 		if (err < 0)
164939d8c1b6SDavid S. Miller 			goto out_fd;
16501da177e4SLinus Torvalds 	}
16511da177e4SLinus Torvalds 
16521da177e4SLinus Torvalds 	/* File flags are not inherited via accept() unlike another OSes. */
16531da177e4SLinus Torvalds 
165439d8c1b6SDavid S. Miller 	fd_install(newfd, newfile);
165539d8c1b6SDavid S. Miller 	err = newfd;
16561da177e4SLinus Torvalds 
16571da177e4SLinus Torvalds out_put:
16586cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
16591da177e4SLinus Torvalds out:
16601da177e4SLinus Torvalds 	return err;
166139d8c1b6SDavid S. Miller out_fd:
16629606a216SDavid S. Miller 	fput(newfile);
166339d8c1b6SDavid S. Miller 	put_unused_fd(newfd);
16641da177e4SLinus Torvalds 	goto out_put;
16651da177e4SLinus Torvalds }
16661da177e4SLinus Torvalds 
16674541e805SDominik Brodowski SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
16684541e805SDominik Brodowski 		int __user *, upeer_addrlen, int, flags)
16694541e805SDominik Brodowski {
16704541e805SDominik Brodowski 	return __sys_accept4(fd, upeer_sockaddr, upeer_addrlen, flags);
16714541e805SDominik Brodowski }
16724541e805SDominik Brodowski 
167320f37034SHeiko Carstens SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,
167420f37034SHeiko Carstens 		int __user *, upeer_addrlen)
1675aaca0bdcSUlrich Drepper {
16764541e805SDominik Brodowski 	return __sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0);
1677aaca0bdcSUlrich Drepper }
1678aaca0bdcSUlrich Drepper 
16791da177e4SLinus Torvalds /*
16801da177e4SLinus Torvalds  *	Attempt to connect to a socket with the server address.  The address
16811da177e4SLinus Torvalds  *	is in user space so we verify it is OK and move it to kernel space.
16821da177e4SLinus Torvalds  *
16831da177e4SLinus Torvalds  *	For 1003.1g we need to add clean support for a bind to AF_UNSPEC to
16841da177e4SLinus Torvalds  *	break bindings
16851da177e4SLinus Torvalds  *
16861da177e4SLinus Torvalds  *	NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and
16871da177e4SLinus Torvalds  *	other SEQPACKET protocols that take time to connect() as it doesn't
16881da177e4SLinus Torvalds  *	include the -EINPROGRESS status for such sockets.
16891da177e4SLinus Torvalds  */
16901da177e4SLinus Torvalds 
16911387c2c2SDominik Brodowski int __sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen)
16921da177e4SLinus Torvalds {
16931da177e4SLinus Torvalds 	struct socket *sock;
1694230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16956cb153caSBenjamin LaHaise 	int err, fput_needed;
16961da177e4SLinus Torvalds 
16976cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
16981da177e4SLinus Torvalds 	if (!sock)
16991da177e4SLinus Torvalds 		goto out;
170043db362dSMaciej Żenczykowski 	err = move_addr_to_kernel(uservaddr, addrlen, &address);
17011da177e4SLinus Torvalds 	if (err < 0)
17021da177e4SLinus Torvalds 		goto out_put;
17031da177e4SLinus Torvalds 
170489bddce5SStephen Hemminger 	err =
1705230b1839SYOSHIFUJI Hideaki 	    security_socket_connect(sock, (struct sockaddr *)&address, addrlen);
17061da177e4SLinus Torvalds 	if (err)
17071da177e4SLinus Torvalds 		goto out_put;
17081da177e4SLinus Torvalds 
1709230b1839SYOSHIFUJI Hideaki 	err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,
17101da177e4SLinus Torvalds 				 sock->file->f_flags);
17111da177e4SLinus Torvalds out_put:
17126cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
17131da177e4SLinus Torvalds out:
17141da177e4SLinus Torvalds 	return err;
17151da177e4SLinus Torvalds }
17161da177e4SLinus Torvalds 
17171387c2c2SDominik Brodowski SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
17181387c2c2SDominik Brodowski 		int, addrlen)
17191387c2c2SDominik Brodowski {
17201387c2c2SDominik Brodowski 	return __sys_connect(fd, uservaddr, addrlen);
17211387c2c2SDominik Brodowski }
17221387c2c2SDominik Brodowski 
17231da177e4SLinus Torvalds /*
17241da177e4SLinus Torvalds  *	Get the local address ('name') of a socket object. Move the obtained
17251da177e4SLinus Torvalds  *	name to user space.
17261da177e4SLinus Torvalds  */
17271da177e4SLinus Torvalds 
17288882a107SDominik Brodowski int __sys_getsockname(int fd, struct sockaddr __user *usockaddr,
17298882a107SDominik Brodowski 		      int __user *usockaddr_len)
17301da177e4SLinus Torvalds {
17311da177e4SLinus Torvalds 	struct socket *sock;
1732230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
17339b2c45d4SDenys Vlasenko 	int err, fput_needed;
17341da177e4SLinus Torvalds 
17356cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
17361da177e4SLinus Torvalds 	if (!sock)
17371da177e4SLinus Torvalds 		goto out;
17381da177e4SLinus Torvalds 
17391da177e4SLinus Torvalds 	err = security_socket_getsockname(sock);
17401da177e4SLinus Torvalds 	if (err)
17411da177e4SLinus Torvalds 		goto out_put;
17421da177e4SLinus Torvalds 
17439b2c45d4SDenys Vlasenko 	err = sock->ops->getname(sock, (struct sockaddr *)&address, 0);
17449b2c45d4SDenys Vlasenko 	if (err < 0)
17451da177e4SLinus Torvalds 		goto out_put;
17469b2c45d4SDenys Vlasenko         /* "err" is actually length in this case */
17479b2c45d4SDenys Vlasenko 	err = move_addr_to_user(&address, err, usockaddr, usockaddr_len);
17481da177e4SLinus Torvalds 
17491da177e4SLinus Torvalds out_put:
17506cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
17511da177e4SLinus Torvalds out:
17521da177e4SLinus Torvalds 	return err;
17531da177e4SLinus Torvalds }
17541da177e4SLinus Torvalds 
17558882a107SDominik Brodowski SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
17568882a107SDominik Brodowski 		int __user *, usockaddr_len)
17578882a107SDominik Brodowski {
17588882a107SDominik Brodowski 	return __sys_getsockname(fd, usockaddr, usockaddr_len);
17598882a107SDominik Brodowski }
17608882a107SDominik Brodowski 
17611da177e4SLinus Torvalds /*
17621da177e4SLinus Torvalds  *	Get the remote address ('name') of a socket object. Move the obtained
17631da177e4SLinus Torvalds  *	name to user space.
17641da177e4SLinus Torvalds  */
17651da177e4SLinus Torvalds 
1766b21c8f83SDominik Brodowski int __sys_getpeername(int fd, struct sockaddr __user *usockaddr,
1767b21c8f83SDominik Brodowski 		      int __user *usockaddr_len)
17681da177e4SLinus Torvalds {
17691da177e4SLinus Torvalds 	struct socket *sock;
1770230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
17719b2c45d4SDenys Vlasenko 	int err, fput_needed;
17721da177e4SLinus Torvalds 
177389bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
177489bddce5SStephen Hemminger 	if (sock != NULL) {
17751da177e4SLinus Torvalds 		err = security_socket_getpeername(sock);
17761da177e4SLinus Torvalds 		if (err) {
17776cb153caSBenjamin LaHaise 			fput_light(sock->file, fput_needed);
17781da177e4SLinus Torvalds 			return err;
17791da177e4SLinus Torvalds 		}
17801da177e4SLinus Torvalds 
17819b2c45d4SDenys Vlasenko 		err = sock->ops->getname(sock, (struct sockaddr *)&address, 1);
17829b2c45d4SDenys Vlasenko 		if (err >= 0)
17839b2c45d4SDenys Vlasenko 			/* "err" is actually length in this case */
17849b2c45d4SDenys Vlasenko 			err = move_addr_to_user(&address, err, usockaddr,
178589bddce5SStephen Hemminger 						usockaddr_len);
17866cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
17871da177e4SLinus Torvalds 	}
17881da177e4SLinus Torvalds 	return err;
17891da177e4SLinus Torvalds }
17901da177e4SLinus Torvalds 
1791b21c8f83SDominik Brodowski SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
1792b21c8f83SDominik Brodowski 		int __user *, usockaddr_len)
1793b21c8f83SDominik Brodowski {
1794b21c8f83SDominik Brodowski 	return __sys_getpeername(fd, usockaddr, usockaddr_len);
1795b21c8f83SDominik Brodowski }
1796b21c8f83SDominik Brodowski 
17971da177e4SLinus Torvalds /*
17981da177e4SLinus Torvalds  *	Send a datagram to a given address. We move the address into kernel
17991da177e4SLinus Torvalds  *	space and check the user space data area is readable before invoking
18001da177e4SLinus Torvalds  *	the protocol.
18011da177e4SLinus Torvalds  */
1802211b634bSDominik Brodowski int __sys_sendto(int fd, void __user *buff, size_t len, unsigned int flags,
1803211b634bSDominik Brodowski 		 struct sockaddr __user *addr,  int addr_len)
18041da177e4SLinus Torvalds {
18051da177e4SLinus Torvalds 	struct socket *sock;
1806230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
18071da177e4SLinus Torvalds 	int err;
18081da177e4SLinus Torvalds 	struct msghdr msg;
18091da177e4SLinus Torvalds 	struct iovec iov;
18106cb153caSBenjamin LaHaise 	int fput_needed;
18111da177e4SLinus Torvalds 
1812602bd0e9SAl Viro 	err = import_single_range(WRITE, buff, len, &iov, &msg.msg_iter);
1813602bd0e9SAl Viro 	if (unlikely(err))
1814602bd0e9SAl Viro 		return err;
1815de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1816de0fa95cSPavel Emelyanov 	if (!sock)
18174387ff75SDavid S. Miller 		goto out;
18186cb153caSBenjamin LaHaise 
18191da177e4SLinus Torvalds 	msg.msg_name = NULL;
18201da177e4SLinus Torvalds 	msg.msg_control = NULL;
18211da177e4SLinus Torvalds 	msg.msg_controllen = 0;
18221da177e4SLinus Torvalds 	msg.msg_namelen = 0;
18236cb153caSBenjamin LaHaise 	if (addr) {
182443db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(addr, addr_len, &address);
18251da177e4SLinus Torvalds 		if (err < 0)
18261da177e4SLinus Torvalds 			goto out_put;
1827230b1839SYOSHIFUJI Hideaki 		msg.msg_name = (struct sockaddr *)&address;
18281da177e4SLinus Torvalds 		msg.msg_namelen = addr_len;
18291da177e4SLinus Torvalds 	}
18301da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
18311da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
18321da177e4SLinus Torvalds 	msg.msg_flags = flags;
1833d8725c86SAl Viro 	err = sock_sendmsg(sock, &msg);
18341da177e4SLinus Torvalds 
18351da177e4SLinus Torvalds out_put:
1836de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
18374387ff75SDavid S. Miller out:
18381da177e4SLinus Torvalds 	return err;
18391da177e4SLinus Torvalds }
18401da177e4SLinus Torvalds 
1841211b634bSDominik Brodowski SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
1842211b634bSDominik Brodowski 		unsigned int, flags, struct sockaddr __user *, addr,
1843211b634bSDominik Brodowski 		int, addr_len)
1844211b634bSDominik Brodowski {
1845211b634bSDominik Brodowski 	return __sys_sendto(fd, buff, len, flags, addr, addr_len);
1846211b634bSDominik Brodowski }
1847211b634bSDominik Brodowski 
18481da177e4SLinus Torvalds /*
18491da177e4SLinus Torvalds  *	Send a datagram down a socket.
18501da177e4SLinus Torvalds  */
18511da177e4SLinus Torvalds 
18523e0fa65fSHeiko Carstens SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len,
185395c96174SEric Dumazet 		unsigned int, flags)
18541da177e4SLinus Torvalds {
1855211b634bSDominik Brodowski 	return __sys_sendto(fd, buff, len, flags, NULL, 0);
18561da177e4SLinus Torvalds }
18571da177e4SLinus Torvalds 
18581da177e4SLinus Torvalds /*
18591da177e4SLinus Torvalds  *	Receive a frame from the socket and optionally record the address of the
18601da177e4SLinus Torvalds  *	sender. We verify the buffers are writable and if needed move the
18611da177e4SLinus Torvalds  *	sender address from kernel to user space.
18621da177e4SLinus Torvalds  */
18637a09e1ebSDominik Brodowski int __sys_recvfrom(int fd, void __user *ubuf, size_t size, unsigned int flags,
18647a09e1ebSDominik Brodowski 		   struct sockaddr __user *addr, int __user *addr_len)
18651da177e4SLinus Torvalds {
18661da177e4SLinus Torvalds 	struct socket *sock;
18671da177e4SLinus Torvalds 	struct iovec iov;
18681da177e4SLinus Torvalds 	struct msghdr msg;
1869230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
18701da177e4SLinus Torvalds 	int err, err2;
18716cb153caSBenjamin LaHaise 	int fput_needed;
18721da177e4SLinus Torvalds 
1873602bd0e9SAl Viro 	err = import_single_range(READ, ubuf, size, &iov, &msg.msg_iter);
1874602bd0e9SAl Viro 	if (unlikely(err))
1875602bd0e9SAl Viro 		return err;
1876de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
18771da177e4SLinus Torvalds 	if (!sock)
1878de0fa95cSPavel Emelyanov 		goto out;
18791da177e4SLinus Torvalds 
18801da177e4SLinus Torvalds 	msg.msg_control = NULL;
18811da177e4SLinus Torvalds 	msg.msg_controllen = 0;
1882f3d33426SHannes Frederic Sowa 	/* Save some cycles and don't copy the address if not needed */
1883f3d33426SHannes Frederic Sowa 	msg.msg_name = addr ? (struct sockaddr *)&address : NULL;
1884f3d33426SHannes Frederic Sowa 	/* We assume all kernel code knows the size of sockaddr_storage */
1885f3d33426SHannes Frederic Sowa 	msg.msg_namelen = 0;
1886130ed5d1Stadeusz.struk@intel.com 	msg.msg_iocb = NULL;
18879f138fa6SAlexander Potapenko 	msg.msg_flags = 0;
18881da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
18891da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
18902da62906SAl Viro 	err = sock_recvmsg(sock, &msg, flags);
18911da177e4SLinus Torvalds 
189289bddce5SStephen Hemminger 	if (err >= 0 && addr != NULL) {
189343db362dSMaciej Żenczykowski 		err2 = move_addr_to_user(&address,
1894230b1839SYOSHIFUJI Hideaki 					 msg.msg_namelen, addr, addr_len);
18951da177e4SLinus Torvalds 		if (err2 < 0)
18961da177e4SLinus Torvalds 			err = err2;
18971da177e4SLinus Torvalds 	}
1898de0fa95cSPavel Emelyanov 
1899de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
19004387ff75SDavid S. Miller out:
19011da177e4SLinus Torvalds 	return err;
19021da177e4SLinus Torvalds }
19031da177e4SLinus Torvalds 
19047a09e1ebSDominik Brodowski SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
19057a09e1ebSDominik Brodowski 		unsigned int, flags, struct sockaddr __user *, addr,
19067a09e1ebSDominik Brodowski 		int __user *, addr_len)
19077a09e1ebSDominik Brodowski {
19087a09e1ebSDominik Brodowski 	return __sys_recvfrom(fd, ubuf, size, flags, addr, addr_len);
19097a09e1ebSDominik Brodowski }
19107a09e1ebSDominik Brodowski 
19111da177e4SLinus Torvalds /*
19121da177e4SLinus Torvalds  *	Receive a datagram from a socket.
19131da177e4SLinus Torvalds  */
19141da177e4SLinus Torvalds 
1915b7c0ddf5SJan Glauber SYSCALL_DEFINE4(recv, int, fd, void __user *, ubuf, size_t, size,
1916b7c0ddf5SJan Glauber 		unsigned int, flags)
19171da177e4SLinus Torvalds {
19187a09e1ebSDominik Brodowski 	return __sys_recvfrom(fd, ubuf, size, flags, NULL, NULL);
19191da177e4SLinus Torvalds }
19201da177e4SLinus Torvalds 
19211da177e4SLinus Torvalds /*
19221da177e4SLinus Torvalds  *	Set a socket option. Because we don't know the option lengths we have
19231da177e4SLinus Torvalds  *	to pass the user mode parameter for the protocols to sort out.
19241da177e4SLinus Torvalds  */
19251da177e4SLinus Torvalds 
1926cc36dca0SDominik Brodowski static int __sys_setsockopt(int fd, int level, int optname,
1927cc36dca0SDominik Brodowski 			    char __user *optval, int optlen)
19281da177e4SLinus Torvalds {
19296cb153caSBenjamin LaHaise 	int err, fput_needed;
19301da177e4SLinus Torvalds 	struct socket *sock;
19311da177e4SLinus Torvalds 
19321da177e4SLinus Torvalds 	if (optlen < 0)
19331da177e4SLinus Torvalds 		return -EINVAL;
19341da177e4SLinus Torvalds 
193589bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
193689bddce5SStephen Hemminger 	if (sock != NULL) {
19371da177e4SLinus Torvalds 		err = security_socket_setsockopt(sock, level, optname);
19386cb153caSBenjamin LaHaise 		if (err)
19396cb153caSBenjamin LaHaise 			goto out_put;
19401da177e4SLinus Torvalds 
19411da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
194289bddce5SStephen Hemminger 			err =
194389bddce5SStephen Hemminger 			    sock_setsockopt(sock, level, optname, optval,
194489bddce5SStephen Hemminger 					    optlen);
19451da177e4SLinus Torvalds 		else
194689bddce5SStephen Hemminger 			err =
194789bddce5SStephen Hemminger 			    sock->ops->setsockopt(sock, level, optname, optval,
194889bddce5SStephen Hemminger 						  optlen);
19496cb153caSBenjamin LaHaise out_put:
19506cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
19511da177e4SLinus Torvalds 	}
19521da177e4SLinus Torvalds 	return err;
19531da177e4SLinus Torvalds }
19541da177e4SLinus Torvalds 
1955cc36dca0SDominik Brodowski SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
1956cc36dca0SDominik Brodowski 		char __user *, optval, int, optlen)
1957cc36dca0SDominik Brodowski {
1958cc36dca0SDominik Brodowski 	return __sys_setsockopt(fd, level, optname, optval, optlen);
1959cc36dca0SDominik Brodowski }
1960cc36dca0SDominik Brodowski 
19611da177e4SLinus Torvalds /*
19621da177e4SLinus Torvalds  *	Get a socket option. Because we don't know the option lengths we have
19631da177e4SLinus Torvalds  *	to pass a user mode parameter for the protocols to sort out.
19641da177e4SLinus Torvalds  */
19651da177e4SLinus Torvalds 
196613a2d70eSDominik Brodowski static int __sys_getsockopt(int fd, int level, int optname,
196713a2d70eSDominik Brodowski 			    char __user *optval, int __user *optlen)
19681da177e4SLinus Torvalds {
19696cb153caSBenjamin LaHaise 	int err, fput_needed;
19701da177e4SLinus Torvalds 	struct socket *sock;
19711da177e4SLinus Torvalds 
197289bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
197389bddce5SStephen Hemminger 	if (sock != NULL) {
19746cb153caSBenjamin LaHaise 		err = security_socket_getsockopt(sock, level, optname);
19756cb153caSBenjamin LaHaise 		if (err)
19766cb153caSBenjamin LaHaise 			goto out_put;
19771da177e4SLinus Torvalds 
19781da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
197989bddce5SStephen Hemminger 			err =
198089bddce5SStephen Hemminger 			    sock_getsockopt(sock, level, optname, optval,
198189bddce5SStephen Hemminger 					    optlen);
19821da177e4SLinus Torvalds 		else
198389bddce5SStephen Hemminger 			err =
198489bddce5SStephen Hemminger 			    sock->ops->getsockopt(sock, level, optname, optval,
198589bddce5SStephen Hemminger 						  optlen);
19866cb153caSBenjamin LaHaise out_put:
19876cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
19881da177e4SLinus Torvalds 	}
19891da177e4SLinus Torvalds 	return err;
19901da177e4SLinus Torvalds }
19911da177e4SLinus Torvalds 
199213a2d70eSDominik Brodowski SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
199313a2d70eSDominik Brodowski 		char __user *, optval, int __user *, optlen)
199413a2d70eSDominik Brodowski {
199513a2d70eSDominik Brodowski 	return __sys_getsockopt(fd, level, optname, optval, optlen);
199613a2d70eSDominik Brodowski }
199713a2d70eSDominik Brodowski 
19981da177e4SLinus Torvalds /*
19991da177e4SLinus Torvalds  *	Shutdown a socket.
20001da177e4SLinus Torvalds  */
20011da177e4SLinus Torvalds 
2002005a1aeaSDominik Brodowski int __sys_shutdown(int fd, int how)
20031da177e4SLinus Torvalds {
20046cb153caSBenjamin LaHaise 	int err, fput_needed;
20051da177e4SLinus Torvalds 	struct socket *sock;
20061da177e4SLinus Torvalds 
200789bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
200889bddce5SStephen Hemminger 	if (sock != NULL) {
20091da177e4SLinus Torvalds 		err = security_socket_shutdown(sock, how);
20106cb153caSBenjamin LaHaise 		if (!err)
20111da177e4SLinus Torvalds 			err = sock->ops->shutdown(sock, how);
20126cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
20131da177e4SLinus Torvalds 	}
20141da177e4SLinus Torvalds 	return err;
20151da177e4SLinus Torvalds }
20161da177e4SLinus Torvalds 
2017005a1aeaSDominik Brodowski SYSCALL_DEFINE2(shutdown, int, fd, int, how)
2018005a1aeaSDominik Brodowski {
2019005a1aeaSDominik Brodowski 	return __sys_shutdown(fd, how);
2020005a1aeaSDominik Brodowski }
2021005a1aeaSDominik Brodowski 
20221da177e4SLinus Torvalds /* A couple of helpful macros for getting the address of the 32/64 bit
20231da177e4SLinus Torvalds  * fields which are the same type (int / unsigned) on our platforms.
20241da177e4SLinus Torvalds  */
20251da177e4SLinus Torvalds #define COMPAT_MSG(msg, member)	((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member)
20261da177e4SLinus Torvalds #define COMPAT_NAMELEN(msg)	COMPAT_MSG(msg, msg_namelen)
20271da177e4SLinus Torvalds #define COMPAT_FLAGS(msg)	COMPAT_MSG(msg, msg_flags)
20281da177e4SLinus Torvalds 
2029c71d8ebeSTetsuo Handa struct used_address {
2030c71d8ebeSTetsuo Handa 	struct sockaddr_storage name;
2031c71d8ebeSTetsuo Handa 	unsigned int name_len;
2032c71d8ebeSTetsuo Handa };
2033c71d8ebeSTetsuo Handa 
2034da184284SAl Viro static int copy_msghdr_from_user(struct msghdr *kmsg,
203508adb7daSAl Viro 				 struct user_msghdr __user *umsg,
203608adb7daSAl Viro 				 struct sockaddr __user **save_addr,
203708adb7daSAl Viro 				 struct iovec **iov)
20381661bf36SDan Carpenter {
2039ffb07550SAl Viro 	struct user_msghdr msg;
204008adb7daSAl Viro 	ssize_t err;
204108adb7daSAl Viro 
2042ffb07550SAl Viro 	if (copy_from_user(&msg, umsg, sizeof(*umsg)))
20431661bf36SDan Carpenter 		return -EFAULT;
2044dbb490b9SMatthew Leach 
2045864d9664SPaolo Abeni 	kmsg->msg_control = (void __force *)msg.msg_control;
2046ffb07550SAl Viro 	kmsg->msg_controllen = msg.msg_controllen;
2047ffb07550SAl Viro 	kmsg->msg_flags = msg.msg_flags;
2048ffb07550SAl Viro 
2049ffb07550SAl Viro 	kmsg->msg_namelen = msg.msg_namelen;
2050ffb07550SAl Viro 	if (!msg.msg_name)
20516a2a2b3aSAni Sinha 		kmsg->msg_namelen = 0;
20526a2a2b3aSAni Sinha 
2053dbb490b9SMatthew Leach 	if (kmsg->msg_namelen < 0)
2054dbb490b9SMatthew Leach 		return -EINVAL;
2055dbb490b9SMatthew Leach 
20561661bf36SDan Carpenter 	if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
2057db31c55aSDan Carpenter 		kmsg->msg_namelen = sizeof(struct sockaddr_storage);
205808adb7daSAl Viro 
205908adb7daSAl Viro 	if (save_addr)
2060ffb07550SAl Viro 		*save_addr = msg.msg_name;
206108adb7daSAl Viro 
2062ffb07550SAl Viro 	if (msg.msg_name && kmsg->msg_namelen) {
206308adb7daSAl Viro 		if (!save_addr) {
2064864d9664SPaolo Abeni 			err = move_addr_to_kernel(msg.msg_name,
2065864d9664SPaolo Abeni 						  kmsg->msg_namelen,
206608adb7daSAl Viro 						  kmsg->msg_name);
206708adb7daSAl Viro 			if (err < 0)
206808adb7daSAl Viro 				return err;
206908adb7daSAl Viro 		}
207008adb7daSAl Viro 	} else {
207108adb7daSAl Viro 		kmsg->msg_name = NULL;
207208adb7daSAl Viro 		kmsg->msg_namelen = 0;
207308adb7daSAl Viro 	}
207408adb7daSAl Viro 
2075ffb07550SAl Viro 	if (msg.msg_iovlen > UIO_MAXIOV)
207608adb7daSAl Viro 		return -EMSGSIZE;
207708adb7daSAl Viro 
20780345f931Stadeusz.struk@intel.com 	kmsg->msg_iocb = NULL;
20790345f931Stadeusz.struk@intel.com 
2080ffb07550SAl Viro 	return import_iovec(save_addr ? READ : WRITE,
2081ffb07550SAl Viro 			    msg.msg_iov, msg.msg_iovlen,
2082da184284SAl Viro 			    UIO_FASTIOV, iov, &kmsg->msg_iter);
20831661bf36SDan Carpenter }
20841661bf36SDan Carpenter 
2085666547ffSAl Viro static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
208695c96174SEric Dumazet 			 struct msghdr *msg_sys, unsigned int flags,
208728a94d8fSTom Herbert 			 struct used_address *used_address,
208828a94d8fSTom Herbert 			 unsigned int allowed_msghdr_flags)
20891da177e4SLinus Torvalds {
209089bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
209189bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
2092230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
20931da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
2094b9d717a7SAlex Williamson 	unsigned char ctl[sizeof(struct cmsghdr) + 20]
2095846cc123SAmit Kushwaha 				__aligned(sizeof(__kernel_size_t));
2096b9d717a7SAlex Williamson 	/* 20 is size of ipv6_pktinfo */
20971da177e4SLinus Torvalds 	unsigned char *ctl_buf = ctl;
2098d8725c86SAl Viro 	int ctl_len;
209908adb7daSAl Viro 	ssize_t err;
21001da177e4SLinus Torvalds 
210108adb7daSAl Viro 	msg_sys->msg_name = &address;
21021da177e4SLinus Torvalds 
210308449320SAl Viro 	if (MSG_CMSG_COMPAT & flags)
210408adb7daSAl Viro 		err = get_compat_msghdr(msg_sys, msg_compat, NULL, &iov);
210508449320SAl Viro 	else
210608adb7daSAl Viro 		err = copy_msghdr_from_user(msg_sys, msg, NULL, &iov);
21071da177e4SLinus Torvalds 	if (err < 0)
2108da184284SAl Viro 		return err;
21091da177e4SLinus Torvalds 
21101da177e4SLinus Torvalds 	err = -ENOBUFS;
21111da177e4SLinus Torvalds 
2112228e548eSAnton Blanchard 	if (msg_sys->msg_controllen > INT_MAX)
21131da177e4SLinus Torvalds 		goto out_freeiov;
211428a94d8fSTom Herbert 	flags |= (msg_sys->msg_flags & allowed_msghdr_flags);
2115228e548eSAnton Blanchard 	ctl_len = msg_sys->msg_controllen;
21161da177e4SLinus Torvalds 	if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
211789bddce5SStephen Hemminger 		err =
2118228e548eSAnton Blanchard 		    cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl,
211989bddce5SStephen Hemminger 						     sizeof(ctl));
21201da177e4SLinus Torvalds 		if (err)
21211da177e4SLinus Torvalds 			goto out_freeiov;
2122228e548eSAnton Blanchard 		ctl_buf = msg_sys->msg_control;
2123228e548eSAnton Blanchard 		ctl_len = msg_sys->msg_controllen;
21241da177e4SLinus Torvalds 	} else if (ctl_len) {
2125ac4340fcSDavid S. Miller 		BUILD_BUG_ON(sizeof(struct cmsghdr) !=
2126ac4340fcSDavid S. Miller 			     CMSG_ALIGN(sizeof(struct cmsghdr)));
212789bddce5SStephen Hemminger 		if (ctl_len > sizeof(ctl)) {
21281da177e4SLinus Torvalds 			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
21291da177e4SLinus Torvalds 			if (ctl_buf == NULL)
21301da177e4SLinus Torvalds 				goto out_freeiov;
21311da177e4SLinus Torvalds 		}
21321da177e4SLinus Torvalds 		err = -EFAULT;
21331da177e4SLinus Torvalds 		/*
2134228e548eSAnton Blanchard 		 * Careful! Before this, msg_sys->msg_control contains a user pointer.
21351da177e4SLinus Torvalds 		 * Afterwards, it will be a kernel pointer. Thus the compiler-assisted
21361da177e4SLinus Torvalds 		 * checking falls down on this.
21371da177e4SLinus Torvalds 		 */
2138fb8621bbSNamhyung Kim 		if (copy_from_user(ctl_buf,
2139228e548eSAnton Blanchard 				   (void __user __force *)msg_sys->msg_control,
214089bddce5SStephen Hemminger 				   ctl_len))
21411da177e4SLinus Torvalds 			goto out_freectl;
2142228e548eSAnton Blanchard 		msg_sys->msg_control = ctl_buf;
21431da177e4SLinus Torvalds 	}
2144228e548eSAnton Blanchard 	msg_sys->msg_flags = flags;
21451da177e4SLinus Torvalds 
21461da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
2147228e548eSAnton Blanchard 		msg_sys->msg_flags |= MSG_DONTWAIT;
2148c71d8ebeSTetsuo Handa 	/*
2149c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and current destination address is same as
2150c71d8ebeSTetsuo Handa 	 * previously succeeded address, omit asking LSM's decision.
2151c71d8ebeSTetsuo Handa 	 * used_address->name_len is initialized to UINT_MAX so that the first
2152c71d8ebeSTetsuo Handa 	 * destination address never matches.
2153c71d8ebeSTetsuo Handa 	 */
2154bc909d9dSMathieu Desnoyers 	if (used_address && msg_sys->msg_name &&
2155bc909d9dSMathieu Desnoyers 	    used_address->name_len == msg_sys->msg_namelen &&
2156bc909d9dSMathieu Desnoyers 	    !memcmp(&used_address->name, msg_sys->msg_name,
2157c71d8ebeSTetsuo Handa 		    used_address->name_len)) {
2158d8725c86SAl Viro 		err = sock_sendmsg_nosec(sock, msg_sys);
2159c71d8ebeSTetsuo Handa 		goto out_freectl;
2160c71d8ebeSTetsuo Handa 	}
2161d8725c86SAl Viro 	err = sock_sendmsg(sock, msg_sys);
2162c71d8ebeSTetsuo Handa 	/*
2163c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and sending to current destination address was
2164c71d8ebeSTetsuo Handa 	 * successful, remember it.
2165c71d8ebeSTetsuo Handa 	 */
2166c71d8ebeSTetsuo Handa 	if (used_address && err >= 0) {
2167c71d8ebeSTetsuo Handa 		used_address->name_len = msg_sys->msg_namelen;
2168bc909d9dSMathieu Desnoyers 		if (msg_sys->msg_name)
2169bc909d9dSMathieu Desnoyers 			memcpy(&used_address->name, msg_sys->msg_name,
2170c71d8ebeSTetsuo Handa 			       used_address->name_len);
2171c71d8ebeSTetsuo Handa 	}
21721da177e4SLinus Torvalds 
21731da177e4SLinus Torvalds out_freectl:
21741da177e4SLinus Torvalds 	if (ctl_buf != ctl)
21751da177e4SLinus Torvalds 		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
21761da177e4SLinus Torvalds out_freeiov:
2177a74e9106SEric Dumazet 	kfree(iov);
2178228e548eSAnton Blanchard 	return err;
2179228e548eSAnton Blanchard }
2180228e548eSAnton Blanchard 
2181228e548eSAnton Blanchard /*
2182228e548eSAnton Blanchard  *	BSD sendmsg interface
2183228e548eSAnton Blanchard  */
2184228e548eSAnton Blanchard 
2185e1834a32SDominik Brodowski long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned int flags,
2186e1834a32SDominik Brodowski 		   bool forbid_cmsg_compat)
2187228e548eSAnton Blanchard {
2188228e548eSAnton Blanchard 	int fput_needed, err;
2189228e548eSAnton Blanchard 	struct msghdr msg_sys;
21901be374a0SAndy Lutomirski 	struct socket *sock;
2191228e548eSAnton Blanchard 
2192e1834a32SDominik Brodowski 	if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT))
2193e1834a32SDominik Brodowski 		return -EINVAL;
2194e1834a32SDominik Brodowski 
21951be374a0SAndy Lutomirski 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2196228e548eSAnton Blanchard 	if (!sock)
2197228e548eSAnton Blanchard 		goto out;
2198228e548eSAnton Blanchard 
219928a94d8fSTom Herbert 	err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL, 0);
2200228e548eSAnton Blanchard 
22016cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
22021da177e4SLinus Torvalds out:
22031da177e4SLinus Torvalds 	return err;
22041da177e4SLinus Torvalds }
22051da177e4SLinus Torvalds 
2206666547ffSAl Viro SYSCALL_DEFINE3(sendmsg, int, fd, struct user_msghdr __user *, msg, unsigned int, flags)
2207a7526eb5SAndy Lutomirski {
2208e1834a32SDominik Brodowski 	return __sys_sendmsg(fd, msg, flags, true);
2209a7526eb5SAndy Lutomirski }
2210a7526eb5SAndy Lutomirski 
2211228e548eSAnton Blanchard /*
2212228e548eSAnton Blanchard  *	Linux sendmmsg interface
2213228e548eSAnton Blanchard  */
2214228e548eSAnton Blanchard 
2215228e548eSAnton Blanchard int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2216e1834a32SDominik Brodowski 		   unsigned int flags, bool forbid_cmsg_compat)
2217228e548eSAnton Blanchard {
2218228e548eSAnton Blanchard 	int fput_needed, err, datagrams;
2219228e548eSAnton Blanchard 	struct socket *sock;
2220228e548eSAnton Blanchard 	struct mmsghdr __user *entry;
2221228e548eSAnton Blanchard 	struct compat_mmsghdr __user *compat_entry;
2222228e548eSAnton Blanchard 	struct msghdr msg_sys;
2223c71d8ebeSTetsuo Handa 	struct used_address used_address;
2224f092276dSTom Herbert 	unsigned int oflags = flags;
2225228e548eSAnton Blanchard 
2226e1834a32SDominik Brodowski 	if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT))
2227e1834a32SDominik Brodowski 		return -EINVAL;
2228e1834a32SDominik Brodowski 
222998382f41SAnton Blanchard 	if (vlen > UIO_MAXIOV)
223098382f41SAnton Blanchard 		vlen = UIO_MAXIOV;
2231228e548eSAnton Blanchard 
2232228e548eSAnton Blanchard 	datagrams = 0;
2233228e548eSAnton Blanchard 
2234228e548eSAnton Blanchard 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2235228e548eSAnton Blanchard 	if (!sock)
2236228e548eSAnton Blanchard 		return err;
2237228e548eSAnton Blanchard 
2238c71d8ebeSTetsuo Handa 	used_address.name_len = UINT_MAX;
2239228e548eSAnton Blanchard 	entry = mmsg;
2240228e548eSAnton Blanchard 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2241728ffb86SAnton Blanchard 	err = 0;
2242f092276dSTom Herbert 	flags |= MSG_BATCH;
2243228e548eSAnton Blanchard 
2244228e548eSAnton Blanchard 	while (datagrams < vlen) {
2245f092276dSTom Herbert 		if (datagrams == vlen - 1)
2246f092276dSTom Herbert 			flags = oflags;
2247f092276dSTom Herbert 
2248228e548eSAnton Blanchard 		if (MSG_CMSG_COMPAT & flags) {
2249666547ffSAl Viro 			err = ___sys_sendmsg(sock, (struct user_msghdr __user *)compat_entry,
225028a94d8fSTom Herbert 					     &msg_sys, flags, &used_address, MSG_EOR);
2251228e548eSAnton Blanchard 			if (err < 0)
2252228e548eSAnton Blanchard 				break;
2253228e548eSAnton Blanchard 			err = __put_user(err, &compat_entry->msg_len);
2254228e548eSAnton Blanchard 			++compat_entry;
2255228e548eSAnton Blanchard 		} else {
2256a7526eb5SAndy Lutomirski 			err = ___sys_sendmsg(sock,
2257666547ffSAl Viro 					     (struct user_msghdr __user *)entry,
225828a94d8fSTom Herbert 					     &msg_sys, flags, &used_address, MSG_EOR);
2259228e548eSAnton Blanchard 			if (err < 0)
2260228e548eSAnton Blanchard 				break;
2261228e548eSAnton Blanchard 			err = put_user(err, &entry->msg_len);
2262228e548eSAnton Blanchard 			++entry;
2263228e548eSAnton Blanchard 		}
2264228e548eSAnton Blanchard 
2265228e548eSAnton Blanchard 		if (err)
2266228e548eSAnton Blanchard 			break;
2267228e548eSAnton Blanchard 		++datagrams;
22683023898bSSoheil Hassas Yeganeh 		if (msg_data_left(&msg_sys))
22693023898bSSoheil Hassas Yeganeh 			break;
2270a78cb84cSEric Dumazet 		cond_resched();
2271228e548eSAnton Blanchard 	}
2272228e548eSAnton Blanchard 
2273228e548eSAnton Blanchard 	fput_light(sock->file, fput_needed);
2274228e548eSAnton Blanchard 
2275728ffb86SAnton Blanchard 	/* We only return an error if no datagrams were able to be sent */
2276728ffb86SAnton Blanchard 	if (datagrams != 0)
2277228e548eSAnton Blanchard 		return datagrams;
2278228e548eSAnton Blanchard 
2279228e548eSAnton Blanchard 	return err;
2280228e548eSAnton Blanchard }
2281228e548eSAnton Blanchard 
2282228e548eSAnton Blanchard SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
2283228e548eSAnton Blanchard 		unsigned int, vlen, unsigned int, flags)
2284228e548eSAnton Blanchard {
2285e1834a32SDominik Brodowski 	return __sys_sendmmsg(fd, mmsg, vlen, flags, true);
2286228e548eSAnton Blanchard }
2287228e548eSAnton Blanchard 
2288666547ffSAl Viro static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg,
228995c96174SEric Dumazet 			 struct msghdr *msg_sys, unsigned int flags, int nosec)
22901da177e4SLinus Torvalds {
229189bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
229289bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
22931da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV];
22941da177e4SLinus Torvalds 	struct iovec *iov = iovstack;
22951da177e4SLinus Torvalds 	unsigned long cmsg_ptr;
22962da62906SAl Viro 	int len;
229708adb7daSAl Viro 	ssize_t err;
22981da177e4SLinus Torvalds 
22991da177e4SLinus Torvalds 	/* kernel mode address */
2300230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage addr;
23011da177e4SLinus Torvalds 
23021da177e4SLinus Torvalds 	/* user mode address pointers */
23031da177e4SLinus Torvalds 	struct sockaddr __user *uaddr;
230408adb7daSAl Viro 	int __user *uaddr_len = COMPAT_NAMELEN(msg);
23051da177e4SLinus Torvalds 
230608adb7daSAl Viro 	msg_sys->msg_name = &addr;
23071da177e4SLinus Torvalds 
2308f3d33426SHannes Frederic Sowa 	if (MSG_CMSG_COMPAT & flags)
230908adb7daSAl Viro 		err = get_compat_msghdr(msg_sys, msg_compat, &uaddr, &iov);
2310f3d33426SHannes Frederic Sowa 	else
231108adb7daSAl Viro 		err = copy_msghdr_from_user(msg_sys, msg, &uaddr, &iov);
23121da177e4SLinus Torvalds 	if (err < 0)
2313da184284SAl Viro 		return err;
23141da177e4SLinus Torvalds 
2315a2e27255SArnaldo Carvalho de Melo 	cmsg_ptr = (unsigned long)msg_sys->msg_control;
2316a2e27255SArnaldo Carvalho de Melo 	msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
23171da177e4SLinus Torvalds 
2318f3d33426SHannes Frederic Sowa 	/* We assume all kernel code knows the size of sockaddr_storage */
2319f3d33426SHannes Frederic Sowa 	msg_sys->msg_namelen = 0;
2320f3d33426SHannes Frederic Sowa 
23211da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
23221da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
23232da62906SAl Viro 	err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys, flags);
23241da177e4SLinus Torvalds 	if (err < 0)
23251da177e4SLinus Torvalds 		goto out_freeiov;
23261da177e4SLinus Torvalds 	len = err;
23271da177e4SLinus Torvalds 
23281da177e4SLinus Torvalds 	if (uaddr != NULL) {
232943db362dSMaciej Żenczykowski 		err = move_addr_to_user(&addr,
2330a2e27255SArnaldo Carvalho de Melo 					msg_sys->msg_namelen, uaddr,
233189bddce5SStephen Hemminger 					uaddr_len);
23321da177e4SLinus Torvalds 		if (err < 0)
23331da177e4SLinus Torvalds 			goto out_freeiov;
23341da177e4SLinus Torvalds 	}
2335a2e27255SArnaldo Carvalho de Melo 	err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
233637f7f421SDavid S. Miller 			 COMPAT_FLAGS(msg));
23371da177e4SLinus Torvalds 	if (err)
23381da177e4SLinus Torvalds 		goto out_freeiov;
23391da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags)
2340a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
23411da177e4SLinus Torvalds 				 &msg_compat->msg_controllen);
23421da177e4SLinus Torvalds 	else
2343a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
23441da177e4SLinus Torvalds 				 &msg->msg_controllen);
23451da177e4SLinus Torvalds 	if (err)
23461da177e4SLinus Torvalds 		goto out_freeiov;
23471da177e4SLinus Torvalds 	err = len;
23481da177e4SLinus Torvalds 
23491da177e4SLinus Torvalds out_freeiov:
2350a74e9106SEric Dumazet 	kfree(iov);
2351a2e27255SArnaldo Carvalho de Melo 	return err;
2352a2e27255SArnaldo Carvalho de Melo }
2353a2e27255SArnaldo Carvalho de Melo 
2354a2e27255SArnaldo Carvalho de Melo /*
2355a2e27255SArnaldo Carvalho de Melo  *	BSD recvmsg interface
2356a2e27255SArnaldo Carvalho de Melo  */
2357a2e27255SArnaldo Carvalho de Melo 
2358e1834a32SDominik Brodowski long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned int flags,
2359e1834a32SDominik Brodowski 		   bool forbid_cmsg_compat)
2360a2e27255SArnaldo Carvalho de Melo {
2361a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err;
2362a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
23631be374a0SAndy Lutomirski 	struct socket *sock;
2364a2e27255SArnaldo Carvalho de Melo 
2365e1834a32SDominik Brodowski 	if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT))
2366e1834a32SDominik Brodowski 		return -EINVAL;
2367e1834a32SDominik Brodowski 
23681be374a0SAndy Lutomirski 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2369a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2370a2e27255SArnaldo Carvalho de Melo 		goto out;
2371a2e27255SArnaldo Carvalho de Melo 
2372a7526eb5SAndy Lutomirski 	err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0);
2373a2e27255SArnaldo Carvalho de Melo 
23746cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
23751da177e4SLinus Torvalds out:
23761da177e4SLinus Torvalds 	return err;
23771da177e4SLinus Torvalds }
23781da177e4SLinus Torvalds 
2379666547ffSAl Viro SYSCALL_DEFINE3(recvmsg, int, fd, struct user_msghdr __user *, msg,
2380a7526eb5SAndy Lutomirski 		unsigned int, flags)
2381a7526eb5SAndy Lutomirski {
2382e1834a32SDominik Brodowski 	return __sys_recvmsg(fd, msg, flags, true);
2383a7526eb5SAndy Lutomirski }
2384a7526eb5SAndy Lutomirski 
2385a2e27255SArnaldo Carvalho de Melo /*
2386a2e27255SArnaldo Carvalho de Melo  *     Linux recvmmsg interface
2387a2e27255SArnaldo Carvalho de Melo  */
23881da177e4SLinus Torvalds 
2389a2e27255SArnaldo Carvalho de Melo int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2390a2e27255SArnaldo Carvalho de Melo 		   unsigned int flags, struct timespec *timeout)
2391a2e27255SArnaldo Carvalho de Melo {
2392a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err, datagrams;
2393a2e27255SArnaldo Carvalho de Melo 	struct socket *sock;
2394a2e27255SArnaldo Carvalho de Melo 	struct mmsghdr __user *entry;
2395d7256d0eSJean-Mickael Guerin 	struct compat_mmsghdr __user *compat_entry;
2396a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
2397766b9f92SDeepa Dinamani 	struct timespec64 end_time;
2398766b9f92SDeepa Dinamani 	struct timespec64 timeout64;
2399a2e27255SArnaldo Carvalho de Melo 
2400a2e27255SArnaldo Carvalho de Melo 	if (timeout &&
2401a2e27255SArnaldo Carvalho de Melo 	    poll_select_set_timeout(&end_time, timeout->tv_sec,
2402a2e27255SArnaldo Carvalho de Melo 				    timeout->tv_nsec))
2403a2e27255SArnaldo Carvalho de Melo 		return -EINVAL;
2404a2e27255SArnaldo Carvalho de Melo 
2405a2e27255SArnaldo Carvalho de Melo 	datagrams = 0;
2406a2e27255SArnaldo Carvalho de Melo 
2407a2e27255SArnaldo Carvalho de Melo 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2408a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2409a2e27255SArnaldo Carvalho de Melo 		return err;
2410a2e27255SArnaldo Carvalho de Melo 
24117797dc41SSoheil Hassas Yeganeh 	if (likely(!(flags & MSG_ERRQUEUE))) {
2412a2e27255SArnaldo Carvalho de Melo 		err = sock_error(sock->sk);
2413e623a9e9SMaxime Jayat 		if (err) {
2414e623a9e9SMaxime Jayat 			datagrams = err;
2415a2e27255SArnaldo Carvalho de Melo 			goto out_put;
2416e623a9e9SMaxime Jayat 		}
24177797dc41SSoheil Hassas Yeganeh 	}
2418a2e27255SArnaldo Carvalho de Melo 
2419a2e27255SArnaldo Carvalho de Melo 	entry = mmsg;
2420d7256d0eSJean-Mickael Guerin 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2421a2e27255SArnaldo Carvalho de Melo 
2422a2e27255SArnaldo Carvalho de Melo 	while (datagrams < vlen) {
2423a2e27255SArnaldo Carvalho de Melo 		/*
2424a2e27255SArnaldo Carvalho de Melo 		 * No need to ask LSM for more than the first datagram.
2425a2e27255SArnaldo Carvalho de Melo 		 */
2426d7256d0eSJean-Mickael Guerin 		if (MSG_CMSG_COMPAT & flags) {
2427666547ffSAl Viro 			err = ___sys_recvmsg(sock, (struct user_msghdr __user *)compat_entry,
2428b9eb8b87SAnton Blanchard 					     &msg_sys, flags & ~MSG_WAITFORONE,
2429b9eb8b87SAnton Blanchard 					     datagrams);
2430d7256d0eSJean-Mickael Guerin 			if (err < 0)
2431d7256d0eSJean-Mickael Guerin 				break;
2432d7256d0eSJean-Mickael Guerin 			err = __put_user(err, &compat_entry->msg_len);
2433d7256d0eSJean-Mickael Guerin 			++compat_entry;
2434d7256d0eSJean-Mickael Guerin 		} else {
2435a7526eb5SAndy Lutomirski 			err = ___sys_recvmsg(sock,
2436666547ffSAl Viro 					     (struct user_msghdr __user *)entry,
2437b9eb8b87SAnton Blanchard 					     &msg_sys, flags & ~MSG_WAITFORONE,
2438b9eb8b87SAnton Blanchard 					     datagrams);
2439a2e27255SArnaldo Carvalho de Melo 			if (err < 0)
2440a2e27255SArnaldo Carvalho de Melo 				break;
2441a2e27255SArnaldo Carvalho de Melo 			err = put_user(err, &entry->msg_len);
2442d7256d0eSJean-Mickael Guerin 			++entry;
2443d7256d0eSJean-Mickael Guerin 		}
2444d7256d0eSJean-Mickael Guerin 
2445a2e27255SArnaldo Carvalho de Melo 		if (err)
2446a2e27255SArnaldo Carvalho de Melo 			break;
2447a2e27255SArnaldo Carvalho de Melo 		++datagrams;
2448a2e27255SArnaldo Carvalho de Melo 
244971c5c159SBrandon L Black 		/* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
245071c5c159SBrandon L Black 		if (flags & MSG_WAITFORONE)
245171c5c159SBrandon L Black 			flags |= MSG_DONTWAIT;
245271c5c159SBrandon L Black 
2453a2e27255SArnaldo Carvalho de Melo 		if (timeout) {
2454766b9f92SDeepa Dinamani 			ktime_get_ts64(&timeout64);
2455766b9f92SDeepa Dinamani 			*timeout = timespec64_to_timespec(
2456766b9f92SDeepa Dinamani 					timespec64_sub(end_time, timeout64));
2457a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_sec < 0) {
2458a2e27255SArnaldo Carvalho de Melo 				timeout->tv_sec = timeout->tv_nsec = 0;
2459a2e27255SArnaldo Carvalho de Melo 				break;
2460a2e27255SArnaldo Carvalho de Melo 			}
2461a2e27255SArnaldo Carvalho de Melo 
2462a2e27255SArnaldo Carvalho de Melo 			/* Timeout, return less than vlen datagrams */
2463a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_nsec == 0 && timeout->tv_sec == 0)
2464a2e27255SArnaldo Carvalho de Melo 				break;
2465a2e27255SArnaldo Carvalho de Melo 		}
2466a2e27255SArnaldo Carvalho de Melo 
2467a2e27255SArnaldo Carvalho de Melo 		/* Out of band data, return right away */
2468a2e27255SArnaldo Carvalho de Melo 		if (msg_sys.msg_flags & MSG_OOB)
2469a2e27255SArnaldo Carvalho de Melo 			break;
2470a78cb84cSEric Dumazet 		cond_resched();
2471a2e27255SArnaldo Carvalho de Melo 	}
2472a2e27255SArnaldo Carvalho de Melo 
2473a2e27255SArnaldo Carvalho de Melo 	if (err == 0)
247434b88a68SArnaldo Carvalho de Melo 		goto out_put;
2475a2e27255SArnaldo Carvalho de Melo 
247634b88a68SArnaldo Carvalho de Melo 	if (datagrams == 0) {
247734b88a68SArnaldo Carvalho de Melo 		datagrams = err;
247834b88a68SArnaldo Carvalho de Melo 		goto out_put;
247934b88a68SArnaldo Carvalho de Melo 	}
248034b88a68SArnaldo Carvalho de Melo 
2481a2e27255SArnaldo Carvalho de Melo 	/*
2482a2e27255SArnaldo Carvalho de Melo 	 * We may return less entries than requested (vlen) if the
2483a2e27255SArnaldo Carvalho de Melo 	 * sock is non block and there aren't enough datagrams...
2484a2e27255SArnaldo Carvalho de Melo 	 */
2485a2e27255SArnaldo Carvalho de Melo 	if (err != -EAGAIN) {
2486a2e27255SArnaldo Carvalho de Melo 		/*
2487a2e27255SArnaldo Carvalho de Melo 		 * ... or  if recvmsg returns an error after we
2488a2e27255SArnaldo Carvalho de Melo 		 * received some datagrams, where we record the
2489a2e27255SArnaldo Carvalho de Melo 		 * error to return on the next call or if the
2490a2e27255SArnaldo Carvalho de Melo 		 * app asks about it using getsockopt(SO_ERROR).
2491a2e27255SArnaldo Carvalho de Melo 		 */
2492a2e27255SArnaldo Carvalho de Melo 		sock->sk->sk_err = -err;
2493a2e27255SArnaldo Carvalho de Melo 	}
249434b88a68SArnaldo Carvalho de Melo out_put:
249534b88a68SArnaldo Carvalho de Melo 	fput_light(sock->file, fput_needed);
2496a2e27255SArnaldo Carvalho de Melo 
2497a2e27255SArnaldo Carvalho de Melo 	return datagrams;
2498a2e27255SArnaldo Carvalho de Melo }
2499a2e27255SArnaldo Carvalho de Melo 
25001255e269SDominik Brodowski static int do_sys_recvmmsg(int fd, struct mmsghdr __user *mmsg,
25011255e269SDominik Brodowski 			   unsigned int vlen, unsigned int flags,
25021255e269SDominik Brodowski 			   struct timespec __user *timeout)
2503a2e27255SArnaldo Carvalho de Melo {
2504a2e27255SArnaldo Carvalho de Melo 	int datagrams;
2505a2e27255SArnaldo Carvalho de Melo 	struct timespec timeout_sys;
2506a2e27255SArnaldo Carvalho de Melo 
25071be374a0SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
25081be374a0SAndy Lutomirski 		return -EINVAL;
25091be374a0SAndy Lutomirski 
2510a2e27255SArnaldo Carvalho de Melo 	if (!timeout)
2511a2e27255SArnaldo Carvalho de Melo 		return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL);
2512a2e27255SArnaldo Carvalho de Melo 
2513a2e27255SArnaldo Carvalho de Melo 	if (copy_from_user(&timeout_sys, timeout, sizeof(timeout_sys)))
2514a2e27255SArnaldo Carvalho de Melo 		return -EFAULT;
2515a2e27255SArnaldo Carvalho de Melo 
2516a2e27255SArnaldo Carvalho de Melo 	datagrams = __sys_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys);
2517a2e27255SArnaldo Carvalho de Melo 
2518a2e27255SArnaldo Carvalho de Melo 	if (datagrams > 0 &&
2519a2e27255SArnaldo Carvalho de Melo 	    copy_to_user(timeout, &timeout_sys, sizeof(timeout_sys)))
2520a2e27255SArnaldo Carvalho de Melo 		datagrams = -EFAULT;
2521a2e27255SArnaldo Carvalho de Melo 
2522a2e27255SArnaldo Carvalho de Melo 	return datagrams;
2523a2e27255SArnaldo Carvalho de Melo }
2524a2e27255SArnaldo Carvalho de Melo 
25251255e269SDominik Brodowski SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
25261255e269SDominik Brodowski 		unsigned int, vlen, unsigned int, flags,
25271255e269SDominik Brodowski 		struct timespec __user *, timeout)
25281255e269SDominik Brodowski {
25291255e269SDominik Brodowski 	return do_sys_recvmmsg(fd, mmsg, vlen, flags, timeout);
25301255e269SDominik Brodowski }
25311255e269SDominik Brodowski 
2532a2e27255SArnaldo Carvalho de Melo #ifdef __ARCH_WANT_SYS_SOCKETCALL
25331da177e4SLinus Torvalds /* Argument list sizes for sys_socketcall */
25341da177e4SLinus Torvalds #define AL(x) ((x) * sizeof(unsigned long))
2535228e548eSAnton Blanchard static const unsigned char nargs[21] = {
253689bddce5SStephen Hemminger 	AL(0), AL(3), AL(3), AL(3), AL(2), AL(3),
25371da177e4SLinus Torvalds 	AL(3), AL(3), AL(4), AL(4), AL(4), AL(6),
2538aaca0bdcSUlrich Drepper 	AL(6), AL(2), AL(5), AL(5), AL(3), AL(3),
2539228e548eSAnton Blanchard 	AL(4), AL(5), AL(4)
254089bddce5SStephen Hemminger };
254189bddce5SStephen Hemminger 
25421da177e4SLinus Torvalds #undef AL
25431da177e4SLinus Torvalds 
25441da177e4SLinus Torvalds /*
25451da177e4SLinus Torvalds  *	System call vectors.
25461da177e4SLinus Torvalds  *
25471da177e4SLinus Torvalds  *	Argument checking cleaned up. Saved 20% in size.
25481da177e4SLinus Torvalds  *  This function doesn't need to set the kernel lock because
25491da177e4SLinus Torvalds  *  it is set by the callees.
25501da177e4SLinus Torvalds  */
25511da177e4SLinus Torvalds 
25523e0fa65fSHeiko Carstens SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
25531da177e4SLinus Torvalds {
25542950fa9dSChen Gang 	unsigned long a[AUDITSC_ARGS];
25551da177e4SLinus Torvalds 	unsigned long a0, a1;
25561da177e4SLinus Torvalds 	int err;
255747379052SArjan van de Ven 	unsigned int len;
25581da177e4SLinus Torvalds 
2559228e548eSAnton Blanchard 	if (call < 1 || call > SYS_SENDMMSG)
25601da177e4SLinus Torvalds 		return -EINVAL;
25611da177e4SLinus Torvalds 
256247379052SArjan van de Ven 	len = nargs[call];
256347379052SArjan van de Ven 	if (len > sizeof(a))
256447379052SArjan van de Ven 		return -EINVAL;
256547379052SArjan van de Ven 
25661da177e4SLinus Torvalds 	/* copy_from_user should be SMP safe. */
256747379052SArjan van de Ven 	if (copy_from_user(a, args, len))
25681da177e4SLinus Torvalds 		return -EFAULT;
25691da177e4SLinus Torvalds 
25702950fa9dSChen Gang 	err = audit_socketcall(nargs[call] / sizeof(unsigned long), a);
25712950fa9dSChen Gang 	if (err)
25722950fa9dSChen Gang 		return err;
25733ec3b2fbSDavid Woodhouse 
25741da177e4SLinus Torvalds 	a0 = a[0];
25751da177e4SLinus Torvalds 	a1 = a[1];
25761da177e4SLinus Torvalds 
257789bddce5SStephen Hemminger 	switch (call) {
25781da177e4SLinus Torvalds 	case SYS_SOCKET:
25799d6a15c3SDominik Brodowski 		err = __sys_socket(a0, a1, a[2]);
25801da177e4SLinus Torvalds 		break;
25811da177e4SLinus Torvalds 	case SYS_BIND:
2582a87d35d8SDominik Brodowski 		err = __sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
25831da177e4SLinus Torvalds 		break;
25841da177e4SLinus Torvalds 	case SYS_CONNECT:
25851387c2c2SDominik Brodowski 		err = __sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
25861da177e4SLinus Torvalds 		break;
25871da177e4SLinus Torvalds 	case SYS_LISTEN:
258825e290eeSDominik Brodowski 		err = __sys_listen(a0, a1);
25891da177e4SLinus Torvalds 		break;
25901da177e4SLinus Torvalds 	case SYS_ACCEPT:
25914541e805SDominik Brodowski 		err = __sys_accept4(a0, (struct sockaddr __user *)a1,
2592aaca0bdcSUlrich Drepper 				    (int __user *)a[2], 0);
25931da177e4SLinus Torvalds 		break;
25941da177e4SLinus Torvalds 	case SYS_GETSOCKNAME:
259589bddce5SStephen Hemminger 		err =
25968882a107SDominik Brodowski 		    __sys_getsockname(a0, (struct sockaddr __user *)a1,
259789bddce5SStephen Hemminger 				      (int __user *)a[2]);
25981da177e4SLinus Torvalds 		break;
25991da177e4SLinus Torvalds 	case SYS_GETPEERNAME:
260089bddce5SStephen Hemminger 		err =
2601b21c8f83SDominik Brodowski 		    __sys_getpeername(a0, (struct sockaddr __user *)a1,
260289bddce5SStephen Hemminger 				      (int __user *)a[2]);
26031da177e4SLinus Torvalds 		break;
26041da177e4SLinus Torvalds 	case SYS_SOCKETPAIR:
26056debc8d8SDominik Brodowski 		err = __sys_socketpair(a0, a1, a[2], (int __user *)a[3]);
26061da177e4SLinus Torvalds 		break;
26071da177e4SLinus Torvalds 	case SYS_SEND:
2608f3bf896bSDominik Brodowski 		err = __sys_sendto(a0, (void __user *)a1, a[2], a[3],
2609f3bf896bSDominik Brodowski 				   NULL, 0);
26101da177e4SLinus Torvalds 		break;
26111da177e4SLinus Torvalds 	case SYS_SENDTO:
2612211b634bSDominik Brodowski 		err = __sys_sendto(a0, (void __user *)a1, a[2], a[3],
26131da177e4SLinus Torvalds 				   (struct sockaddr __user *)a[4], a[5]);
26141da177e4SLinus Torvalds 		break;
26151da177e4SLinus Torvalds 	case SYS_RECV:
2616d27e9afcSDominik Brodowski 		err = __sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
2617d27e9afcSDominik Brodowski 				     NULL, NULL);
26181da177e4SLinus Torvalds 		break;
26191da177e4SLinus Torvalds 	case SYS_RECVFROM:
26207a09e1ebSDominik Brodowski 		err = __sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
262189bddce5SStephen Hemminger 				     (struct sockaddr __user *)a[4],
262289bddce5SStephen Hemminger 				     (int __user *)a[5]);
26231da177e4SLinus Torvalds 		break;
26241da177e4SLinus Torvalds 	case SYS_SHUTDOWN:
2625005a1aeaSDominik Brodowski 		err = __sys_shutdown(a0, a1);
26261da177e4SLinus Torvalds 		break;
26271da177e4SLinus Torvalds 	case SYS_SETSOCKOPT:
2628cc36dca0SDominik Brodowski 		err = __sys_setsockopt(a0, a1, a[2], (char __user *)a[3],
2629cc36dca0SDominik Brodowski 				       a[4]);
26301da177e4SLinus Torvalds 		break;
26311da177e4SLinus Torvalds 	case SYS_GETSOCKOPT:
263289bddce5SStephen Hemminger 		err =
263313a2d70eSDominik Brodowski 		    __sys_getsockopt(a0, a1, a[2], (char __user *)a[3],
263489bddce5SStephen Hemminger 				     (int __user *)a[4]);
26351da177e4SLinus Torvalds 		break;
26361da177e4SLinus Torvalds 	case SYS_SENDMSG:
2637e1834a32SDominik Brodowski 		err = __sys_sendmsg(a0, (struct user_msghdr __user *)a1,
2638e1834a32SDominik Brodowski 				    a[2], true);
26391da177e4SLinus Torvalds 		break;
2640228e548eSAnton Blanchard 	case SYS_SENDMMSG:
2641e1834a32SDominik Brodowski 		err = __sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2],
2642e1834a32SDominik Brodowski 				     a[3], true);
2643228e548eSAnton Blanchard 		break;
26441da177e4SLinus Torvalds 	case SYS_RECVMSG:
2645e1834a32SDominik Brodowski 		err = __sys_recvmsg(a0, (struct user_msghdr __user *)a1,
2646e1834a32SDominik Brodowski 				    a[2], true);
26471da177e4SLinus Torvalds 		break;
2648a2e27255SArnaldo Carvalho de Melo 	case SYS_RECVMMSG:
26491255e269SDominik Brodowski 		err = do_sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2],
26501255e269SDominik Brodowski 				      a[3], (struct timespec __user *)a[4]);
2651a2e27255SArnaldo Carvalho de Melo 		break;
2652de11defeSUlrich Drepper 	case SYS_ACCEPT4:
26534541e805SDominik Brodowski 		err = __sys_accept4(a0, (struct sockaddr __user *)a1,
2654de11defeSUlrich Drepper 				    (int __user *)a[2], a[3]);
2655aaca0bdcSUlrich Drepper 		break;
26561da177e4SLinus Torvalds 	default:
26571da177e4SLinus Torvalds 		err = -EINVAL;
26581da177e4SLinus Torvalds 		break;
26591da177e4SLinus Torvalds 	}
26601da177e4SLinus Torvalds 	return err;
26611da177e4SLinus Torvalds }
26621da177e4SLinus Torvalds 
26631da177e4SLinus Torvalds #endif				/* __ARCH_WANT_SYS_SOCKETCALL */
26641da177e4SLinus Torvalds 
266555737fdaSStephen Hemminger /**
266655737fdaSStephen Hemminger  *	sock_register - add a socket protocol handler
266755737fdaSStephen Hemminger  *	@ops: description of protocol
266855737fdaSStephen Hemminger  *
26691da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
26701da177e4SLinus Torvalds  *	advertise its address family, and have it linked into the
2671e793c0f7SMasanari Iida  *	socket interface. The value ops->family corresponds to the
267255737fdaSStephen Hemminger  *	socket system call protocol family.
26731da177e4SLinus Torvalds  */
2674f0fd27d4SStephen Hemminger int sock_register(const struct net_proto_family *ops)
26751da177e4SLinus Torvalds {
26761da177e4SLinus Torvalds 	int err;
26771da177e4SLinus Torvalds 
26781da177e4SLinus Torvalds 	if (ops->family >= NPROTO) {
26793410f22eSYang Yingliang 		pr_crit("protocol %d >= NPROTO(%d)\n", ops->family, NPROTO);
26801da177e4SLinus Torvalds 		return -ENOBUFS;
26811da177e4SLinus Torvalds 	}
268255737fdaSStephen Hemminger 
268355737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2684190683a9SEric Dumazet 	if (rcu_dereference_protected(net_families[ops->family],
2685190683a9SEric Dumazet 				      lockdep_is_held(&net_family_lock)))
26861da177e4SLinus Torvalds 		err = -EEXIST;
268755737fdaSStephen Hemminger 	else {
2688cf778b00SEric Dumazet 		rcu_assign_pointer(net_families[ops->family], ops);
26891da177e4SLinus Torvalds 		err = 0;
26901da177e4SLinus Torvalds 	}
269155737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
269255737fdaSStephen Hemminger 
26933410f22eSYang Yingliang 	pr_info("NET: Registered protocol family %d\n", ops->family);
26941da177e4SLinus Torvalds 	return err;
26951da177e4SLinus Torvalds }
2696c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_register);
26971da177e4SLinus Torvalds 
269855737fdaSStephen Hemminger /**
269955737fdaSStephen Hemminger  *	sock_unregister - remove a protocol handler
270055737fdaSStephen Hemminger  *	@family: protocol family to remove
270155737fdaSStephen Hemminger  *
27021da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
27031da177e4SLinus Torvalds  *	remove its address family, and have it unlinked from the
270455737fdaSStephen Hemminger  *	new socket creation.
270555737fdaSStephen Hemminger  *
270655737fdaSStephen Hemminger  *	If protocol handler is a module, then it can use module reference
270755737fdaSStephen Hemminger  *	counts to protect against new references. If protocol handler is not
270855737fdaSStephen Hemminger  *	a module then it needs to provide its own protection in
270955737fdaSStephen Hemminger  *	the ops->create routine.
27101da177e4SLinus Torvalds  */
2711f0fd27d4SStephen Hemminger void sock_unregister(int family)
27121da177e4SLinus Torvalds {
2713f0fd27d4SStephen Hemminger 	BUG_ON(family < 0 || family >= NPROTO);
27141da177e4SLinus Torvalds 
271555737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2716a9b3cd7fSStephen Hemminger 	RCU_INIT_POINTER(net_families[family], NULL);
271755737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
271855737fdaSStephen Hemminger 
271955737fdaSStephen Hemminger 	synchronize_rcu();
272055737fdaSStephen Hemminger 
27213410f22eSYang Yingliang 	pr_info("NET: Unregistered protocol family %d\n", family);
27221da177e4SLinus Torvalds }
2723c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_unregister);
27241da177e4SLinus Torvalds 
2725bf2ae2e4SXin Long bool sock_is_registered(int family)
2726bf2ae2e4SXin Long {
2727bf2ae2e4SXin Long 	return family < NPROTO && rcu_access_pointer(net_families[family]);
2728bf2ae2e4SXin Long }
2729bf2ae2e4SXin Long 
273077d76ea3SAndi Kleen static int __init sock_init(void)
27311da177e4SLinus Torvalds {
2732b3e19d92SNick Piggin 	int err;
27332ca794e5SEric W. Biederman 	/*
27342ca794e5SEric W. Biederman 	 *      Initialize the network sysctl infrastructure.
27352ca794e5SEric W. Biederman 	 */
27362ca794e5SEric W. Biederman 	err = net_sysctl_init();
27372ca794e5SEric W. Biederman 	if (err)
27382ca794e5SEric W. Biederman 		goto out;
2739b3e19d92SNick Piggin 
27401da177e4SLinus Torvalds 	/*
27411da177e4SLinus Torvalds 	 *      Initialize skbuff SLAB cache
27421da177e4SLinus Torvalds 	 */
27431da177e4SLinus Torvalds 	skb_init();
27441da177e4SLinus Torvalds 
27451da177e4SLinus Torvalds 	/*
27461da177e4SLinus Torvalds 	 *      Initialize the protocols module.
27471da177e4SLinus Torvalds 	 */
27481da177e4SLinus Torvalds 
27491da177e4SLinus Torvalds 	init_inodecache();
2750b3e19d92SNick Piggin 
2751b3e19d92SNick Piggin 	err = register_filesystem(&sock_fs_type);
2752b3e19d92SNick Piggin 	if (err)
2753b3e19d92SNick Piggin 		goto out_fs;
27541da177e4SLinus Torvalds 	sock_mnt = kern_mount(&sock_fs_type);
2755b3e19d92SNick Piggin 	if (IS_ERR(sock_mnt)) {
2756b3e19d92SNick Piggin 		err = PTR_ERR(sock_mnt);
2757b3e19d92SNick Piggin 		goto out_mount;
2758b3e19d92SNick Piggin 	}
275977d76ea3SAndi Kleen 
276077d76ea3SAndi Kleen 	/* The real protocol initialization is performed in later initcalls.
27611da177e4SLinus Torvalds 	 */
27621da177e4SLinus Torvalds 
27631da177e4SLinus Torvalds #ifdef CONFIG_NETFILTER
27646d11cfdbSPablo Neira Ayuso 	err = netfilter_init();
27656d11cfdbSPablo Neira Ayuso 	if (err)
27666d11cfdbSPablo Neira Ayuso 		goto out;
27671da177e4SLinus Torvalds #endif
2768cbeb321aSDavid S. Miller 
2769408eccceSDaniel Borkmann 	ptp_classifier_init();
2770c1f19b51SRichard Cochran 
2771b3e19d92SNick Piggin out:
2772b3e19d92SNick Piggin 	return err;
2773b3e19d92SNick Piggin 
2774b3e19d92SNick Piggin out_mount:
2775b3e19d92SNick Piggin 	unregister_filesystem(&sock_fs_type);
2776b3e19d92SNick Piggin out_fs:
2777b3e19d92SNick Piggin 	goto out;
27781da177e4SLinus Torvalds }
27791da177e4SLinus Torvalds 
278077d76ea3SAndi Kleen core_initcall(sock_init);	/* early initcall */
278177d76ea3SAndi Kleen 
27821da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS
27831da177e4SLinus Torvalds void socket_seq_show(struct seq_file *seq)
27841da177e4SLinus Torvalds {
2785648845abSTonghao Zhang 	seq_printf(seq, "sockets: used %d\n",
2786648845abSTonghao Zhang 		   sock_inuse_get(seq->private));
27871da177e4SLinus Torvalds }
27881da177e4SLinus Torvalds #endif				/* CONFIG_PROC_FS */
27891da177e4SLinus Torvalds 
279089bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
27916b96018bSArnd Bergmann static int do_siocgstamp(struct net *net, struct socket *sock,
2792644595f8SH. Peter Anvin 			 unsigned int cmd, void __user *up)
27937a229387SArnd Bergmann {
27947a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
27957a229387SArnd Bergmann 	struct timeval ktv;
27967a229387SArnd Bergmann 	int err;
27977a229387SArnd Bergmann 
27987a229387SArnd Bergmann 	set_fs(KERNEL_DS);
27996b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv);
28007a229387SArnd Bergmann 	set_fs(old_fs);
2801644595f8SH. Peter Anvin 	if (!err)
2802ed6fe9d6SMikulas Patocka 		err = compat_put_timeval(&ktv, up);
2803644595f8SH. Peter Anvin 
28047a229387SArnd Bergmann 	return err;
28057a229387SArnd Bergmann }
28067a229387SArnd Bergmann 
28076b96018bSArnd Bergmann static int do_siocgstampns(struct net *net, struct socket *sock,
2808644595f8SH. Peter Anvin 			   unsigned int cmd, void __user *up)
28097a229387SArnd Bergmann {
28107a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
28117a229387SArnd Bergmann 	struct timespec kts;
28127a229387SArnd Bergmann 	int err;
28137a229387SArnd Bergmann 
28147a229387SArnd Bergmann 	set_fs(KERNEL_DS);
28156b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts);
28167a229387SArnd Bergmann 	set_fs(old_fs);
2817644595f8SH. Peter Anvin 	if (!err)
2818ed6fe9d6SMikulas Patocka 		err = compat_put_timespec(&kts, up);
2819644595f8SH. Peter Anvin 
28207a229387SArnd Bergmann 	return err;
28217a229387SArnd Bergmann }
28227a229387SArnd Bergmann 
282336fd633eSAl Viro static int compat_dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32)
28247a229387SArnd Bergmann {
28256b96018bSArnd Bergmann 	struct compat_ifconf ifc32;
28267a229387SArnd Bergmann 	struct ifconf ifc;
28277a229387SArnd Bergmann 	int err;
28287a229387SArnd Bergmann 
28296b96018bSArnd Bergmann 	if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf)))
28307a229387SArnd Bergmann 		return -EFAULT;
28317a229387SArnd Bergmann 
283236fd633eSAl Viro 	ifc.ifc_len = ifc32.ifc_len;
283336fd633eSAl Viro 	ifc.ifc_req = compat_ptr(ifc32.ifcbuf);
28347a229387SArnd Bergmann 
283536fd633eSAl Viro 	rtnl_lock();
283636fd633eSAl Viro 	err = dev_ifconf(net, &ifc, sizeof(struct compat_ifreq));
283736fd633eSAl Viro 	rtnl_unlock();
28387a229387SArnd Bergmann 	if (err)
28397a229387SArnd Bergmann 		return err;
28407a229387SArnd Bergmann 
284136fd633eSAl Viro 	ifc32.ifc_len = ifc.ifc_len;
28426b96018bSArnd Bergmann 	if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf)))
28437a229387SArnd Bergmann 		return -EFAULT;
28447a229387SArnd Bergmann 
28457a229387SArnd Bergmann 	return 0;
28467a229387SArnd Bergmann }
28477a229387SArnd Bergmann 
28486b96018bSArnd Bergmann static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
28497a229387SArnd Bergmann {
28503a7da39dSBen Hutchings 	struct compat_ethtool_rxnfc __user *compat_rxnfc;
28513a7da39dSBen Hutchings 	bool convert_in = false, convert_out = false;
285244c02a2cSAl Viro 	size_t buf_size = 0;
285344c02a2cSAl Viro 	struct ethtool_rxnfc __user *rxnfc = NULL;
285444c02a2cSAl Viro 	struct ifreq ifr;
28553a7da39dSBen Hutchings 	u32 rule_cnt = 0, actual_rule_cnt;
28563a7da39dSBen Hutchings 	u32 ethcmd;
28577a229387SArnd Bergmann 	u32 data;
28583a7da39dSBen Hutchings 	int ret;
28597a229387SArnd Bergmann 
28607a229387SArnd Bergmann 	if (get_user(data, &ifr32->ifr_ifru.ifru_data))
28617a229387SArnd Bergmann 		return -EFAULT;
28627a229387SArnd Bergmann 
28633a7da39dSBen Hutchings 	compat_rxnfc = compat_ptr(data);
28643a7da39dSBen Hutchings 
28653a7da39dSBen Hutchings 	if (get_user(ethcmd, &compat_rxnfc->cmd))
28667a229387SArnd Bergmann 		return -EFAULT;
28677a229387SArnd Bergmann 
28683a7da39dSBen Hutchings 	/* Most ethtool structures are defined without padding.
28693a7da39dSBen Hutchings 	 * Unfortunately struct ethtool_rxnfc is an exception.
28703a7da39dSBen Hutchings 	 */
28713a7da39dSBen Hutchings 	switch (ethcmd) {
28723a7da39dSBen Hutchings 	default:
28733a7da39dSBen Hutchings 		break;
28743a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLALL:
28753a7da39dSBen Hutchings 		/* Buffer size is variable */
28763a7da39dSBen Hutchings 		if (get_user(rule_cnt, &compat_rxnfc->rule_cnt))
28773a7da39dSBen Hutchings 			return -EFAULT;
28783a7da39dSBen Hutchings 		if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32))
28793a7da39dSBen Hutchings 			return -ENOMEM;
28803a7da39dSBen Hutchings 		buf_size += rule_cnt * sizeof(u32);
28813a7da39dSBen Hutchings 		/* fall through */
28823a7da39dSBen Hutchings 	case ETHTOOL_GRXRINGS:
28833a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLCNT:
28843a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRULE:
288555664f32SBen Hutchings 	case ETHTOOL_SRXCLSRLINS:
28863a7da39dSBen Hutchings 		convert_out = true;
28873a7da39dSBen Hutchings 		/* fall through */
28883a7da39dSBen Hutchings 	case ETHTOOL_SRXCLSRLDEL:
28893a7da39dSBen Hutchings 		buf_size += sizeof(struct ethtool_rxnfc);
28903a7da39dSBen Hutchings 		convert_in = true;
289144c02a2cSAl Viro 		rxnfc = compat_alloc_user_space(buf_size);
28923a7da39dSBen Hutchings 		break;
28933a7da39dSBen Hutchings 	}
28943a7da39dSBen Hutchings 
289544c02a2cSAl Viro 	if (copy_from_user(&ifr.ifr_name, &ifr32->ifr_name, IFNAMSIZ))
28963a7da39dSBen Hutchings 		return -EFAULT;
28973a7da39dSBen Hutchings 
289844c02a2cSAl Viro 	ifr.ifr_data = convert_in ? rxnfc : (void __user *)compat_rxnfc;
28993a7da39dSBen Hutchings 
29003a7da39dSBen Hutchings 	if (convert_in) {
2901127fe533SAlexander Duyck 		/* We expect there to be holes between fs.m_ext and
29023a7da39dSBen Hutchings 		 * fs.ring_cookie and at the end of fs, but nowhere else.
29033a7da39dSBen Hutchings 		 */
2904127fe533SAlexander Duyck 		BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_ext) +
2905127fe533SAlexander Duyck 			     sizeof(compat_rxnfc->fs.m_ext) !=
2906127fe533SAlexander Duyck 			     offsetof(struct ethtool_rxnfc, fs.m_ext) +
2907127fe533SAlexander Duyck 			     sizeof(rxnfc->fs.m_ext));
29083a7da39dSBen Hutchings 		BUILD_BUG_ON(
29093a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.location) -
29103a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) !=
29113a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.location) -
29123a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.ring_cookie));
29133a7da39dSBen Hutchings 
29143a7da39dSBen Hutchings 		if (copy_in_user(rxnfc, compat_rxnfc,
2915954b1244SStephen Hemminger 				 (void __user *)(&rxnfc->fs.m_ext + 1) -
2916954b1244SStephen Hemminger 				 (void __user *)rxnfc) ||
29173a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->fs.ring_cookie,
29183a7da39dSBen Hutchings 				 &compat_rxnfc->fs.ring_cookie,
2919954b1244SStephen Hemminger 				 (void __user *)(&rxnfc->fs.location + 1) -
2920954b1244SStephen Hemminger 				 (void __user *)&rxnfc->fs.ring_cookie) ||
29213a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt,
29223a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
29233a7da39dSBen Hutchings 			return -EFAULT;
29243a7da39dSBen Hutchings 	}
29253a7da39dSBen Hutchings 
292644c02a2cSAl Viro 	ret = dev_ioctl(net, SIOCETHTOOL, &ifr, NULL);
29273a7da39dSBen Hutchings 	if (ret)
29283a7da39dSBen Hutchings 		return ret;
29293a7da39dSBen Hutchings 
29303a7da39dSBen Hutchings 	if (convert_out) {
29313a7da39dSBen Hutchings 		if (copy_in_user(compat_rxnfc, rxnfc,
2932954b1244SStephen Hemminger 				 (const void __user *)(&rxnfc->fs.m_ext + 1) -
2933954b1244SStephen Hemminger 				 (const void __user *)rxnfc) ||
29343a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->fs.ring_cookie,
29353a7da39dSBen Hutchings 				 &rxnfc->fs.ring_cookie,
2936954b1244SStephen Hemminger 				 (const void __user *)(&rxnfc->fs.location + 1) -
2937954b1244SStephen Hemminger 				 (const void __user *)&rxnfc->fs.ring_cookie) ||
29383a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt,
29393a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
29403a7da39dSBen Hutchings 			return -EFAULT;
29413a7da39dSBen Hutchings 
29423a7da39dSBen Hutchings 		if (ethcmd == ETHTOOL_GRXCLSRLALL) {
29433a7da39dSBen Hutchings 			/* As an optimisation, we only copy the actual
29443a7da39dSBen Hutchings 			 * number of rules that the underlying
29453a7da39dSBen Hutchings 			 * function returned.  Since Mallory might
29463a7da39dSBen Hutchings 			 * change the rule count in user memory, we
29473a7da39dSBen Hutchings 			 * check that it is less than the rule count
29483a7da39dSBen Hutchings 			 * originally given (as the user buffer size),
29493a7da39dSBen Hutchings 			 * which has been range-checked.
29503a7da39dSBen Hutchings 			 */
29513a7da39dSBen Hutchings 			if (get_user(actual_rule_cnt, &rxnfc->rule_cnt))
29523a7da39dSBen Hutchings 				return -EFAULT;
29533a7da39dSBen Hutchings 			if (actual_rule_cnt < rule_cnt)
29543a7da39dSBen Hutchings 				rule_cnt = actual_rule_cnt;
29553a7da39dSBen Hutchings 			if (copy_in_user(&compat_rxnfc->rule_locs[0],
29563a7da39dSBen Hutchings 					 &rxnfc->rule_locs[0],
29573a7da39dSBen Hutchings 					 rule_cnt * sizeof(u32)))
29583a7da39dSBen Hutchings 				return -EFAULT;
29593a7da39dSBen Hutchings 		}
29603a7da39dSBen Hutchings 	}
29613a7da39dSBen Hutchings 
29623a7da39dSBen Hutchings 	return 0;
29637a229387SArnd Bergmann }
29647a229387SArnd Bergmann 
29657a50a240SArnd Bergmann static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32)
29667a50a240SArnd Bergmann {
29677a50a240SArnd Bergmann 	compat_uptr_t uptr32;
296844c02a2cSAl Viro 	struct ifreq ifr;
296944c02a2cSAl Viro 	void __user *saved;
297044c02a2cSAl Viro 	int err;
29717a50a240SArnd Bergmann 
297244c02a2cSAl Viro 	if (copy_from_user(&ifr, uifr32, sizeof(struct compat_ifreq)))
29737a50a240SArnd Bergmann 		return -EFAULT;
29747a50a240SArnd Bergmann 
29757a50a240SArnd Bergmann 	if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu))
29767a50a240SArnd Bergmann 		return -EFAULT;
29777a50a240SArnd Bergmann 
297844c02a2cSAl Viro 	saved = ifr.ifr_settings.ifs_ifsu.raw_hdlc;
297944c02a2cSAl Viro 	ifr.ifr_settings.ifs_ifsu.raw_hdlc = compat_ptr(uptr32);
29807a50a240SArnd Bergmann 
298144c02a2cSAl Viro 	err = dev_ioctl(net, SIOCWANDEV, &ifr, NULL);
298244c02a2cSAl Viro 	if (!err) {
298344c02a2cSAl Viro 		ifr.ifr_settings.ifs_ifsu.raw_hdlc = saved;
298444c02a2cSAl Viro 		if (copy_to_user(uifr32, &ifr, sizeof(struct compat_ifreq)))
298544c02a2cSAl Viro 			err = -EFAULT;
29867a50a240SArnd Bergmann 	}
29877a229387SArnd Bergmann 	return err;
29887a229387SArnd Bergmann }
29897a229387SArnd Bergmann 
2990590d4693SBen Hutchings /* Handle ioctls that use ifreq::ifr_data and just need struct ifreq converted */
2991590d4693SBen Hutchings static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd,
29926b96018bSArnd Bergmann 				 struct compat_ifreq __user *u_ifreq32)
29937a229387SArnd Bergmann {
299444c02a2cSAl Viro 	struct ifreq ifreq;
29957a229387SArnd Bergmann 	u32 data32;
29967a229387SArnd Bergmann 
299744c02a2cSAl Viro 	if (copy_from_user(ifreq.ifr_name, u_ifreq32->ifr_name, IFNAMSIZ))
29987a229387SArnd Bergmann 		return -EFAULT;
299944c02a2cSAl Viro 	if (get_user(data32, &u_ifreq32->ifr_data))
30007a229387SArnd Bergmann 		return -EFAULT;
300144c02a2cSAl Viro 	ifreq.ifr_data = compat_ptr(data32);
30027a229387SArnd Bergmann 
300344c02a2cSAl Viro 	return dev_ioctl(net, cmd, &ifreq, NULL);
3004a2116ed2SArnd Bergmann }
3005a2116ed2SArnd Bergmann 
3006a2116ed2SArnd Bergmann static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
3007a2116ed2SArnd Bergmann 			struct compat_ifreq __user *uifr32)
3008a2116ed2SArnd Bergmann {
3009a2116ed2SArnd Bergmann 	struct ifreq ifr;
3010a2116ed2SArnd Bergmann 	struct compat_ifmap __user *uifmap32;
3011a2116ed2SArnd Bergmann 	int err;
3012a2116ed2SArnd Bergmann 
3013a2116ed2SArnd Bergmann 	uifmap32 = &uifr32->ifr_ifru.ifru_map;
3014a2116ed2SArnd Bergmann 	err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name));
30153ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
30163ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
30173ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
30183ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.irq, &uifmap32->irq);
30193ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.dma, &uifmap32->dma);
30203ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.port, &uifmap32->port);
3021a2116ed2SArnd Bergmann 	if (err)
3022a2116ed2SArnd Bergmann 		return -EFAULT;
3023a2116ed2SArnd Bergmann 
302444c02a2cSAl Viro 	err = dev_ioctl(net, cmd, &ifr, NULL);
3025a2116ed2SArnd Bergmann 
3026a2116ed2SArnd Bergmann 	if (cmd == SIOCGIFMAP && !err) {
30277a229387SArnd Bergmann 		err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name));
30283ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
30293ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
30303ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
30313ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.irq, &uifmap32->irq);
30323ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.dma, &uifmap32->dma);
30333ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.port, &uifmap32->port);
30347a229387SArnd Bergmann 		if (err)
30357a229387SArnd Bergmann 			err = -EFAULT;
30367a229387SArnd Bergmann 	}
30377a229387SArnd Bergmann 	return err;
30387a229387SArnd Bergmann }
30397a229387SArnd Bergmann 
30407a229387SArnd Bergmann struct rtentry32 {
30417a229387SArnd Bergmann 	u32		rt_pad1;
30427a229387SArnd Bergmann 	struct sockaddr rt_dst;         /* target address               */
30437a229387SArnd Bergmann 	struct sockaddr rt_gateway;     /* gateway addr (RTF_GATEWAY)   */
30447a229387SArnd Bergmann 	struct sockaddr rt_genmask;     /* target network mask (IP)     */
30457a229387SArnd Bergmann 	unsigned short	rt_flags;
30467a229387SArnd Bergmann 	short		rt_pad2;
30477a229387SArnd Bergmann 	u32		rt_pad3;
30487a229387SArnd Bergmann 	unsigned char	rt_tos;
30497a229387SArnd Bergmann 	unsigned char	rt_class;
30507a229387SArnd Bergmann 	short		rt_pad4;
30517a229387SArnd Bergmann 	short		rt_metric;      /* +1 for binary compatibility! */
30527a229387SArnd Bergmann 	/* char * */ u32 rt_dev;        /* forcing the device at add    */
30537a229387SArnd Bergmann 	u32		rt_mtu;         /* per route MTU/Window         */
30547a229387SArnd Bergmann 	u32		rt_window;      /* Window clamping              */
30557a229387SArnd Bergmann 	unsigned short  rt_irtt;        /* Initial RTT                  */
30567a229387SArnd Bergmann };
30577a229387SArnd Bergmann 
30587a229387SArnd Bergmann struct in6_rtmsg32 {
30597a229387SArnd Bergmann 	struct in6_addr		rtmsg_dst;
30607a229387SArnd Bergmann 	struct in6_addr		rtmsg_src;
30617a229387SArnd Bergmann 	struct in6_addr		rtmsg_gateway;
30627a229387SArnd Bergmann 	u32			rtmsg_type;
30637a229387SArnd Bergmann 	u16			rtmsg_dst_len;
30647a229387SArnd Bergmann 	u16			rtmsg_src_len;
30657a229387SArnd Bergmann 	u32			rtmsg_metric;
30667a229387SArnd Bergmann 	u32			rtmsg_info;
30677a229387SArnd Bergmann 	u32			rtmsg_flags;
30687a229387SArnd Bergmann 	s32			rtmsg_ifindex;
30697a229387SArnd Bergmann };
30707a229387SArnd Bergmann 
30716b96018bSArnd Bergmann static int routing_ioctl(struct net *net, struct socket *sock,
30726b96018bSArnd Bergmann 			 unsigned int cmd, void __user *argp)
30737a229387SArnd Bergmann {
30747a229387SArnd Bergmann 	int ret;
30757a229387SArnd Bergmann 	void *r = NULL;
30767a229387SArnd Bergmann 	struct in6_rtmsg r6;
30777a229387SArnd Bergmann 	struct rtentry r4;
30787a229387SArnd Bergmann 	char devname[16];
30797a229387SArnd Bergmann 	u32 rtdev;
30807a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
30817a229387SArnd Bergmann 
30826b96018bSArnd Bergmann 	if (sock && sock->sk && sock->sk->sk_family == AF_INET6) { /* ipv6 */
30836b96018bSArnd Bergmann 		struct in6_rtmsg32 __user *ur6 = argp;
30847a229387SArnd Bergmann 		ret = copy_from_user(&r6.rtmsg_dst, &(ur6->rtmsg_dst),
30857a229387SArnd Bergmann 			3 * sizeof(struct in6_addr));
30863ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_type, &(ur6->rtmsg_type));
30873ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len));
30883ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_src_len, &(ur6->rtmsg_src_len));
30893ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_metric, &(ur6->rtmsg_metric));
30903ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_info, &(ur6->rtmsg_info));
30913ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_flags, &(ur6->rtmsg_flags));
30923ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex));
30937a229387SArnd Bergmann 
30947a229387SArnd Bergmann 		r = (void *) &r6;
30957a229387SArnd Bergmann 	} else { /* ipv4 */
30966b96018bSArnd Bergmann 		struct rtentry32 __user *ur4 = argp;
30977a229387SArnd Bergmann 		ret = copy_from_user(&r4.rt_dst, &(ur4->rt_dst),
30987a229387SArnd Bergmann 					3 * sizeof(struct sockaddr));
30993ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_flags, &(ur4->rt_flags));
31003ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_metric, &(ur4->rt_metric));
31013ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_mtu, &(ur4->rt_mtu));
31023ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_window, &(ur4->rt_window));
31033ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_irtt, &(ur4->rt_irtt));
31043ddc5b46SMathieu Desnoyers 		ret |= get_user(rtdev, &(ur4->rt_dev));
31057a229387SArnd Bergmann 		if (rtdev) {
31067a229387SArnd Bergmann 			ret |= copy_from_user(devname, compat_ptr(rtdev), 15);
3107c3f52ae6Sstephen hemminger 			r4.rt_dev = (char __user __force *)devname;
3108c3f52ae6Sstephen hemminger 			devname[15] = 0;
31097a229387SArnd Bergmann 		} else
31107a229387SArnd Bergmann 			r4.rt_dev = NULL;
31117a229387SArnd Bergmann 
31127a229387SArnd Bergmann 		r = (void *) &r4;
31137a229387SArnd Bergmann 	}
31147a229387SArnd Bergmann 
31157a229387SArnd Bergmann 	if (ret) {
31167a229387SArnd Bergmann 		ret = -EFAULT;
31177a229387SArnd Bergmann 		goto out;
31187a229387SArnd Bergmann 	}
31197a229387SArnd Bergmann 
31207a229387SArnd Bergmann 	set_fs(KERNEL_DS);
31216b96018bSArnd Bergmann 	ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r);
31227a229387SArnd Bergmann 	set_fs(old_fs);
31237a229387SArnd Bergmann 
31247a229387SArnd Bergmann out:
31257a229387SArnd Bergmann 	return ret;
31267a229387SArnd Bergmann }
31277a229387SArnd Bergmann 
31287a229387SArnd Bergmann /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE
31297a229387SArnd Bergmann  * for some operations; this forces use of the newer bridge-utils that
313025985edcSLucas De Marchi  * use compatible ioctls
31317a229387SArnd Bergmann  */
31326b96018bSArnd Bergmann static int old_bridge_ioctl(compat_ulong_t __user *argp)
31337a229387SArnd Bergmann {
31346b96018bSArnd Bergmann 	compat_ulong_t tmp;
31357a229387SArnd Bergmann 
31366b96018bSArnd Bergmann 	if (get_user(tmp, argp))
31377a229387SArnd Bergmann 		return -EFAULT;
31387a229387SArnd Bergmann 	if (tmp == BRCTL_GET_VERSION)
31397a229387SArnd Bergmann 		return BRCTL_VERSION + 1;
31407a229387SArnd Bergmann 	return -EINVAL;
31417a229387SArnd Bergmann }
31427a229387SArnd Bergmann 
31436b96018bSArnd Bergmann static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
31446b96018bSArnd Bergmann 			 unsigned int cmd, unsigned long arg)
31456b96018bSArnd Bergmann {
31466b96018bSArnd Bergmann 	void __user *argp = compat_ptr(arg);
31476b96018bSArnd Bergmann 	struct sock *sk = sock->sk;
31486b96018bSArnd Bergmann 	struct net *net = sock_net(sk);
31497a229387SArnd Bergmann 
31506b96018bSArnd Bergmann 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
3151590d4693SBen Hutchings 		return compat_ifr_data_ioctl(net, cmd, argp);
31527a229387SArnd Bergmann 
31536b96018bSArnd Bergmann 	switch (cmd) {
31546b96018bSArnd Bergmann 	case SIOCSIFBR:
31556b96018bSArnd Bergmann 	case SIOCGIFBR:
31566b96018bSArnd Bergmann 		return old_bridge_ioctl(argp);
31576b96018bSArnd Bergmann 	case SIOCGIFCONF:
315836fd633eSAl Viro 		return compat_dev_ifconf(net, argp);
31596b96018bSArnd Bergmann 	case SIOCETHTOOL:
31606b96018bSArnd Bergmann 		return ethtool_ioctl(net, argp);
31617a50a240SArnd Bergmann 	case SIOCWANDEV:
31627a50a240SArnd Bergmann 		return compat_siocwandev(net, argp);
3163a2116ed2SArnd Bergmann 	case SIOCGIFMAP:
3164a2116ed2SArnd Bergmann 	case SIOCSIFMAP:
3165a2116ed2SArnd Bergmann 		return compat_sioc_ifmap(net, cmd, argp);
31666b96018bSArnd Bergmann 	case SIOCADDRT:
31676b96018bSArnd Bergmann 	case SIOCDELRT:
31686b96018bSArnd Bergmann 		return routing_ioctl(net, sock, cmd, argp);
31696b96018bSArnd Bergmann 	case SIOCGSTAMP:
31706b96018bSArnd Bergmann 		return do_siocgstamp(net, sock, cmd, argp);
31716b96018bSArnd Bergmann 	case SIOCGSTAMPNS:
31726b96018bSArnd Bergmann 		return do_siocgstampns(net, sock, cmd, argp);
3173590d4693SBen Hutchings 	case SIOCBONDSLAVEINFOQUERY:
3174590d4693SBen Hutchings 	case SIOCBONDINFOQUERY:
3175a2116ed2SArnd Bergmann 	case SIOCSHWTSTAMP:
3176fd468c74SBen Hutchings 	case SIOCGHWTSTAMP:
3177590d4693SBen Hutchings 		return compat_ifr_data_ioctl(net, cmd, argp);
31787a229387SArnd Bergmann 
31796b96018bSArnd Bergmann 	case FIOSETOWN:
31806b96018bSArnd Bergmann 	case SIOCSPGRP:
31816b96018bSArnd Bergmann 	case FIOGETOWN:
31826b96018bSArnd Bergmann 	case SIOCGPGRP:
31836b96018bSArnd Bergmann 	case SIOCBRADDBR:
31846b96018bSArnd Bergmann 	case SIOCBRDELBR:
31856b96018bSArnd Bergmann 	case SIOCGIFVLAN:
31866b96018bSArnd Bergmann 	case SIOCSIFVLAN:
31876b96018bSArnd Bergmann 	case SIOCADDDLCI:
31886b96018bSArnd Bergmann 	case SIOCDELDLCI:
3189c62cce2cSAndrey Vagin 	case SIOCGSKNS:
31906b96018bSArnd Bergmann 		return sock_ioctl(file, cmd, arg);
31916b96018bSArnd Bergmann 
31926b96018bSArnd Bergmann 	case SIOCGIFFLAGS:
31936b96018bSArnd Bergmann 	case SIOCSIFFLAGS:
31946b96018bSArnd Bergmann 	case SIOCGIFMETRIC:
31956b96018bSArnd Bergmann 	case SIOCSIFMETRIC:
31966b96018bSArnd Bergmann 	case SIOCGIFMTU:
31976b96018bSArnd Bergmann 	case SIOCSIFMTU:
31986b96018bSArnd Bergmann 	case SIOCGIFMEM:
31996b96018bSArnd Bergmann 	case SIOCSIFMEM:
32006b96018bSArnd Bergmann 	case SIOCGIFHWADDR:
32016b96018bSArnd Bergmann 	case SIOCSIFHWADDR:
32026b96018bSArnd Bergmann 	case SIOCADDMULTI:
32036b96018bSArnd Bergmann 	case SIOCDELMULTI:
32046b96018bSArnd Bergmann 	case SIOCGIFINDEX:
32056b96018bSArnd Bergmann 	case SIOCGIFADDR:
32066b96018bSArnd Bergmann 	case SIOCSIFADDR:
32076b96018bSArnd Bergmann 	case SIOCSIFHWBROADCAST:
32086b96018bSArnd Bergmann 	case SIOCDIFADDR:
32096b96018bSArnd Bergmann 	case SIOCGIFBRDADDR:
32106b96018bSArnd Bergmann 	case SIOCSIFBRDADDR:
32116b96018bSArnd Bergmann 	case SIOCGIFDSTADDR:
32126b96018bSArnd Bergmann 	case SIOCSIFDSTADDR:
32136b96018bSArnd Bergmann 	case SIOCGIFNETMASK:
32146b96018bSArnd Bergmann 	case SIOCSIFNETMASK:
32156b96018bSArnd Bergmann 	case SIOCSIFPFLAGS:
32166b96018bSArnd Bergmann 	case SIOCGIFPFLAGS:
32176b96018bSArnd Bergmann 	case SIOCGIFTXQLEN:
32186b96018bSArnd Bergmann 	case SIOCSIFTXQLEN:
32196b96018bSArnd Bergmann 	case SIOCBRADDIF:
32206b96018bSArnd Bergmann 	case SIOCBRDELIF:
32219177efd3SArnd Bergmann 	case SIOCSIFNAME:
32229177efd3SArnd Bergmann 	case SIOCGMIIPHY:
32239177efd3SArnd Bergmann 	case SIOCGMIIREG:
32249177efd3SArnd Bergmann 	case SIOCSMIIREG:
32256b96018bSArnd Bergmann 	case SIOCSARP:
32266b96018bSArnd Bergmann 	case SIOCGARP:
32276b96018bSArnd Bergmann 	case SIOCDARP:
32286b96018bSArnd Bergmann 	case SIOCATMARK:
3229f92d4fc9SAl Viro 	case SIOCBONDENSLAVE:
3230f92d4fc9SAl Viro 	case SIOCBONDRELEASE:
3231f92d4fc9SAl Viro 	case SIOCBONDSETHWADDR:
3232f92d4fc9SAl Viro 	case SIOCBONDCHANGEACTIVE:
32334cf808e7SAl Viro 	case SIOCGIFNAME:
32349177efd3SArnd Bergmann 		return sock_do_ioctl(net, sock, cmd, arg);
32359177efd3SArnd Bergmann 	}
32369177efd3SArnd Bergmann 
32376b96018bSArnd Bergmann 	return -ENOIOCTLCMD;
32386b96018bSArnd Bergmann }
32397a229387SArnd Bergmann 
324095c96174SEric Dumazet static long compat_sock_ioctl(struct file *file, unsigned int cmd,
324189bbfc95SShaun Pereira 			      unsigned long arg)
324289bbfc95SShaun Pereira {
324389bbfc95SShaun Pereira 	struct socket *sock = file->private_data;
324489bbfc95SShaun Pereira 	int ret = -ENOIOCTLCMD;
324587de87d5SDavid S. Miller 	struct sock *sk;
324687de87d5SDavid S. Miller 	struct net *net;
324787de87d5SDavid S. Miller 
324887de87d5SDavid S. Miller 	sk = sock->sk;
324987de87d5SDavid S. Miller 	net = sock_net(sk);
325089bbfc95SShaun Pereira 
325189bbfc95SShaun Pereira 	if (sock->ops->compat_ioctl)
325289bbfc95SShaun Pereira 		ret = sock->ops->compat_ioctl(sock, cmd, arg);
325389bbfc95SShaun Pereira 
325487de87d5SDavid S. Miller 	if (ret == -ENOIOCTLCMD &&
325587de87d5SDavid S. Miller 	    (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST))
325687de87d5SDavid S. Miller 		ret = compat_wext_handle_ioctl(net, cmd, arg);
325787de87d5SDavid S. Miller 
32586b96018bSArnd Bergmann 	if (ret == -ENOIOCTLCMD)
32596b96018bSArnd Bergmann 		ret = compat_sock_ioctl_trans(file, sock, cmd, arg);
32606b96018bSArnd Bergmann 
326189bbfc95SShaun Pereira 	return ret;
326289bbfc95SShaun Pereira }
326389bbfc95SShaun Pereira #endif
326489bbfc95SShaun Pereira 
3265ac5a488eSSridhar Samudrala int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
3266ac5a488eSSridhar Samudrala {
3267ac5a488eSSridhar Samudrala 	return sock->ops->bind(sock, addr, addrlen);
3268ac5a488eSSridhar Samudrala }
3269c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_bind);
3270ac5a488eSSridhar Samudrala 
3271ac5a488eSSridhar Samudrala int kernel_listen(struct socket *sock, int backlog)
3272ac5a488eSSridhar Samudrala {
3273ac5a488eSSridhar Samudrala 	return sock->ops->listen(sock, backlog);
3274ac5a488eSSridhar Samudrala }
3275c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_listen);
3276ac5a488eSSridhar Samudrala 
3277ac5a488eSSridhar Samudrala int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
3278ac5a488eSSridhar Samudrala {
3279ac5a488eSSridhar Samudrala 	struct sock *sk = sock->sk;
3280ac5a488eSSridhar Samudrala 	int err;
3281ac5a488eSSridhar Samudrala 
3282ac5a488eSSridhar Samudrala 	err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
3283ac5a488eSSridhar Samudrala 			       newsock);
3284ac5a488eSSridhar Samudrala 	if (err < 0)
3285ac5a488eSSridhar Samudrala 		goto done;
3286ac5a488eSSridhar Samudrala 
3287cdfbabfbSDavid Howells 	err = sock->ops->accept(sock, *newsock, flags, true);
3288ac5a488eSSridhar Samudrala 	if (err < 0) {
3289ac5a488eSSridhar Samudrala 		sock_release(*newsock);
3290fa8705b0STony Battersby 		*newsock = NULL;
3291ac5a488eSSridhar Samudrala 		goto done;
3292ac5a488eSSridhar Samudrala 	}
3293ac5a488eSSridhar Samudrala 
3294ac5a488eSSridhar Samudrala 	(*newsock)->ops = sock->ops;
32951b08534eSWei Yongjun 	__module_get((*newsock)->ops->owner);
3296ac5a488eSSridhar Samudrala 
3297ac5a488eSSridhar Samudrala done:
3298ac5a488eSSridhar Samudrala 	return err;
3299ac5a488eSSridhar Samudrala }
3300c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_accept);
3301ac5a488eSSridhar Samudrala 
3302ac5a488eSSridhar Samudrala int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
3303ac5a488eSSridhar Samudrala 		   int flags)
3304ac5a488eSSridhar Samudrala {
3305ac5a488eSSridhar Samudrala 	return sock->ops->connect(sock, addr, addrlen, flags);
3306ac5a488eSSridhar Samudrala }
3307c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_connect);
3308ac5a488eSSridhar Samudrala 
33099b2c45d4SDenys Vlasenko int kernel_getsockname(struct socket *sock, struct sockaddr *addr)
3310ac5a488eSSridhar Samudrala {
33119b2c45d4SDenys Vlasenko 	return sock->ops->getname(sock, addr, 0);
3312ac5a488eSSridhar Samudrala }
3313c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockname);
3314ac5a488eSSridhar Samudrala 
33159b2c45d4SDenys Vlasenko int kernel_getpeername(struct socket *sock, struct sockaddr *addr)
3316ac5a488eSSridhar Samudrala {
33179b2c45d4SDenys Vlasenko 	return sock->ops->getname(sock, addr, 1);
3318ac5a488eSSridhar Samudrala }
3319c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getpeername);
3320ac5a488eSSridhar Samudrala 
3321ac5a488eSSridhar Samudrala int kernel_getsockopt(struct socket *sock, int level, int optname,
3322ac5a488eSSridhar Samudrala 			char *optval, int *optlen)
3323ac5a488eSSridhar Samudrala {
3324ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3325fb8621bbSNamhyung Kim 	char __user *uoptval;
3326fb8621bbSNamhyung Kim 	int __user *uoptlen;
3327ac5a488eSSridhar Samudrala 	int err;
3328ac5a488eSSridhar Samudrala 
3329fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3330fb8621bbSNamhyung Kim 	uoptlen = (int __user __force *) optlen;
3331fb8621bbSNamhyung Kim 
3332ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3333ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3334fb8621bbSNamhyung Kim 		err = sock_getsockopt(sock, level, optname, uoptval, uoptlen);
3335ac5a488eSSridhar Samudrala 	else
3336fb8621bbSNamhyung Kim 		err = sock->ops->getsockopt(sock, level, optname, uoptval,
3337fb8621bbSNamhyung Kim 					    uoptlen);
3338ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3339ac5a488eSSridhar Samudrala 	return err;
3340ac5a488eSSridhar Samudrala }
3341c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockopt);
3342ac5a488eSSridhar Samudrala 
3343ac5a488eSSridhar Samudrala int kernel_setsockopt(struct socket *sock, int level, int optname,
3344b7058842SDavid S. Miller 			char *optval, unsigned int optlen)
3345ac5a488eSSridhar Samudrala {
3346ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3347fb8621bbSNamhyung Kim 	char __user *uoptval;
3348ac5a488eSSridhar Samudrala 	int err;
3349ac5a488eSSridhar Samudrala 
3350fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3351fb8621bbSNamhyung Kim 
3352ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3353ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3354fb8621bbSNamhyung Kim 		err = sock_setsockopt(sock, level, optname, uoptval, optlen);
3355ac5a488eSSridhar Samudrala 	else
3356fb8621bbSNamhyung Kim 		err = sock->ops->setsockopt(sock, level, optname, uoptval,
3357ac5a488eSSridhar Samudrala 					    optlen);
3358ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3359ac5a488eSSridhar Samudrala 	return err;
3360ac5a488eSSridhar Samudrala }
3361c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_setsockopt);
3362ac5a488eSSridhar Samudrala 
3363ac5a488eSSridhar Samudrala int kernel_sendpage(struct socket *sock, struct page *page, int offset,
3364ac5a488eSSridhar Samudrala 		    size_t size, int flags)
3365ac5a488eSSridhar Samudrala {
3366ac5a488eSSridhar Samudrala 	if (sock->ops->sendpage)
3367ac5a488eSSridhar Samudrala 		return sock->ops->sendpage(sock, page, offset, size, flags);
3368ac5a488eSSridhar Samudrala 
3369ac5a488eSSridhar Samudrala 	return sock_no_sendpage(sock, page, offset, size, flags);
3370ac5a488eSSridhar Samudrala }
3371c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendpage);
3372ac5a488eSSridhar Samudrala 
3373306b13ebSTom Herbert int kernel_sendpage_locked(struct sock *sk, struct page *page, int offset,
3374306b13ebSTom Herbert 			   size_t size, int flags)
3375306b13ebSTom Herbert {
3376306b13ebSTom Herbert 	struct socket *sock = sk->sk_socket;
3377306b13ebSTom Herbert 
3378306b13ebSTom Herbert 	if (sock->ops->sendpage_locked)
3379306b13ebSTom Herbert 		return sock->ops->sendpage_locked(sk, page, offset, size,
3380306b13ebSTom Herbert 						  flags);
3381306b13ebSTom Herbert 
3382306b13ebSTom Herbert 	return sock_no_sendpage_locked(sk, page, offset, size, flags);
3383306b13ebSTom Herbert }
3384306b13ebSTom Herbert EXPORT_SYMBOL(kernel_sendpage_locked);
3385306b13ebSTom Herbert 
338691cf45f0STrond Myklebust int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
338791cf45f0STrond Myklebust {
338891cf45f0STrond Myklebust 	return sock->ops->shutdown(sock, how);
338991cf45f0STrond Myklebust }
339091cf45f0STrond Myklebust EXPORT_SYMBOL(kernel_sock_shutdown);
3391113c3075SR. Parameswaran 
3392113c3075SR. Parameswaran /* This routine returns the IP overhead imposed by a socket i.e.
3393113c3075SR. Parameswaran  * the length of the underlying IP header, depending on whether
3394113c3075SR. Parameswaran  * this is an IPv4 or IPv6 socket and the length from IP options turned
339557240d00SR. Parameswaran  * on at the socket. Assumes that the caller has a lock on the socket.
3396113c3075SR. Parameswaran  */
3397113c3075SR. Parameswaran u32 kernel_sock_ip_overhead(struct sock *sk)
3398113c3075SR. Parameswaran {
3399113c3075SR. Parameswaran 	struct inet_sock *inet;
3400113c3075SR. Parameswaran 	struct ip_options_rcu *opt;
3401113c3075SR. Parameswaran 	u32 overhead = 0;
3402113c3075SR. Parameswaran #if IS_ENABLED(CONFIG_IPV6)
3403113c3075SR. Parameswaran 	struct ipv6_pinfo *np;
3404113c3075SR. Parameswaran 	struct ipv6_txoptions *optv6 = NULL;
3405113c3075SR. Parameswaran #endif /* IS_ENABLED(CONFIG_IPV6) */
3406113c3075SR. Parameswaran 
3407113c3075SR. Parameswaran 	if (!sk)
3408113c3075SR. Parameswaran 		return overhead;
3409113c3075SR. Parameswaran 
3410113c3075SR. Parameswaran 	switch (sk->sk_family) {
3411113c3075SR. Parameswaran 	case AF_INET:
3412113c3075SR. Parameswaran 		inet = inet_sk(sk);
3413113c3075SR. Parameswaran 		overhead += sizeof(struct iphdr);
3414113c3075SR. Parameswaran 		opt = rcu_dereference_protected(inet->inet_opt,
3415614d79c0Sstephen hemminger 						sock_owned_by_user(sk));
3416113c3075SR. Parameswaran 		if (opt)
3417113c3075SR. Parameswaran 			overhead += opt->opt.optlen;
3418113c3075SR. Parameswaran 		return overhead;
3419113c3075SR. Parameswaran #if IS_ENABLED(CONFIG_IPV6)
3420113c3075SR. Parameswaran 	case AF_INET6:
3421113c3075SR. Parameswaran 		np = inet6_sk(sk);
3422113c3075SR. Parameswaran 		overhead += sizeof(struct ipv6hdr);
3423113c3075SR. Parameswaran 		if (np)
3424113c3075SR. Parameswaran 			optv6 = rcu_dereference_protected(np->opt,
3425614d79c0Sstephen hemminger 							  sock_owned_by_user(sk));
3426113c3075SR. Parameswaran 		if (optv6)
3427113c3075SR. Parameswaran 			overhead += (optv6->opt_flen + optv6->opt_nflen);
3428113c3075SR. Parameswaran 		return overhead;
3429113c3075SR. Parameswaran #endif /* IS_ENABLED(CONFIG_IPV6) */
3430113c3075SR. Parameswaran 	default: /* Returns 0 overhead if the socket is not ipv4 or ipv6 */
3431113c3075SR. Parameswaran 		return overhead;
3432113c3075SR. Parameswaran 	}
3433113c3075SR. Parameswaran }
3434113c3075SR. Parameswaran EXPORT_SYMBOL(kernel_sock_ip_overhead);
3435