xref: /openbmc/linux/net/socket.c (revision aad9c8c4)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * NET		An implementation of the SOCKET network access protocol.
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Version:	@(#)socket.c	1.1.93	18/02/95
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * Authors:	Orest Zborowski, <obz@Kodak.COM>
702c30a84SJesper Juhl  *		Ross Biro
81da177e4SLinus Torvalds  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
91da177e4SLinus Torvalds  *
101da177e4SLinus Torvalds  * Fixes:
111da177e4SLinus Torvalds  *		Anonymous	:	NOTSOCK/BADF cleanup. Error fix in
121da177e4SLinus Torvalds  *					shutdown()
131da177e4SLinus Torvalds  *		Alan Cox	:	verify_area() fixes
141da177e4SLinus Torvalds  *		Alan Cox	:	Removed DDI
151da177e4SLinus Torvalds  *		Jonathan Kamens	:	SOCK_DGRAM reconnect bug
161da177e4SLinus Torvalds  *		Alan Cox	:	Moved a load of checks to the very
171da177e4SLinus Torvalds  *					top level.
181da177e4SLinus Torvalds  *		Alan Cox	:	Move address structures to/from user
191da177e4SLinus Torvalds  *					mode above the protocol layers.
201da177e4SLinus Torvalds  *		Rob Janssen	:	Allow 0 length sends.
211da177e4SLinus Torvalds  *		Alan Cox	:	Asynchronous I/O support (cribbed from the
221da177e4SLinus Torvalds  *					tty drivers).
231da177e4SLinus Torvalds  *		Niibe Yutaka	:	Asynchronous I/O for writes (4.4BSD style)
241da177e4SLinus Torvalds  *		Jeff Uphoff	:	Made max number of sockets command-line
251da177e4SLinus Torvalds  *					configurable.
261da177e4SLinus Torvalds  *		Matti Aarnio	:	Made the number of sockets dynamic,
271da177e4SLinus Torvalds  *					to be allocated when needed, and mr.
281da177e4SLinus Torvalds  *					Uphoff's max is used as max to be
291da177e4SLinus Torvalds  *					allowed to allocate.
301da177e4SLinus Torvalds  *		Linus		:	Argh. removed all the socket allocation
311da177e4SLinus Torvalds  *					altogether: it's in the inode now.
321da177e4SLinus Torvalds  *		Alan Cox	:	Made sock_alloc()/sock_release() public
331da177e4SLinus Torvalds  *					for NetROM and future kernel nfsd type
341da177e4SLinus Torvalds  *					stuff.
351da177e4SLinus Torvalds  *		Alan Cox	:	sendmsg/recvmsg basics.
361da177e4SLinus Torvalds  *		Tom Dyas	:	Export net symbols.
371da177e4SLinus Torvalds  *		Marcin Dalecki	:	Fixed problems with CONFIG_NET="n".
381da177e4SLinus Torvalds  *		Alan Cox	:	Added thread locking to sys_* calls
391da177e4SLinus Torvalds  *					for sockets. May have errors at the
401da177e4SLinus Torvalds  *					moment.
411da177e4SLinus Torvalds  *		Kevin Buhr	:	Fixed the dumb errors in the above.
421da177e4SLinus Torvalds  *		Andi Kleen	:	Some small cleanups, optimizations,
431da177e4SLinus Torvalds  *					and fixed a copy_from_user() bug.
441da177e4SLinus Torvalds  *		Tigran Aivazian	:	sys_send(args) calls sys_sendto(args, NULL, 0)
451da177e4SLinus Torvalds  *		Tigran Aivazian	:	Made listen(2) backlog sanity checks
461da177e4SLinus Torvalds  *					protocol-independent
471da177e4SLinus Torvalds  *
481da177e4SLinus Torvalds  *
491da177e4SLinus Torvalds  *		This program is free software; you can redistribute it and/or
501da177e4SLinus Torvalds  *		modify it under the terms of the GNU General Public License
511da177e4SLinus Torvalds  *		as published by the Free Software Foundation; either version
521da177e4SLinus Torvalds  *		2 of the License, or (at your option) any later version.
531da177e4SLinus Torvalds  *
541da177e4SLinus Torvalds  *
551da177e4SLinus Torvalds  *	This module is effectively the top level interface to the BSD socket
561da177e4SLinus Torvalds  *	paradigm.
571da177e4SLinus Torvalds  *
581da177e4SLinus Torvalds  *	Based upon Swansea University Computer Society NET3.039
591da177e4SLinus Torvalds  */
601da177e4SLinus Torvalds 
611da177e4SLinus Torvalds #include <linux/mm.h>
621da177e4SLinus Torvalds #include <linux/socket.h>
631da177e4SLinus Torvalds #include <linux/file.h>
641da177e4SLinus Torvalds #include <linux/net.h>
651da177e4SLinus Torvalds #include <linux/interrupt.h>
66aaca0bdcSUlrich Drepper #include <linux/thread_info.h>
6755737fdaSStephen Hemminger #include <linux/rcupdate.h>
681da177e4SLinus Torvalds #include <linux/netdevice.h>
691da177e4SLinus Torvalds #include <linux/proc_fs.h>
701da177e4SLinus Torvalds #include <linux/seq_file.h>
714a3e2f71SArjan van de Ven #include <linux/mutex.h>
721da177e4SLinus Torvalds #include <linux/if_bridge.h>
7320380731SArnaldo Carvalho de Melo #include <linux/if_frad.h>
7420380731SArnaldo Carvalho de Melo #include <linux/if_vlan.h>
75408eccceSDaniel Borkmann #include <linux/ptp_classify.h>
761da177e4SLinus Torvalds #include <linux/init.h>
771da177e4SLinus Torvalds #include <linux/poll.h>
781da177e4SLinus Torvalds #include <linux/cache.h>
791da177e4SLinus Torvalds #include <linux/module.h>
801da177e4SLinus Torvalds #include <linux/highmem.h>
811da177e4SLinus Torvalds #include <linux/mount.h>
821da177e4SLinus Torvalds #include <linux/security.h>
831da177e4SLinus Torvalds #include <linux/syscalls.h>
841da177e4SLinus Torvalds #include <linux/compat.h>
851da177e4SLinus Torvalds #include <linux/kmod.h>
863ec3b2fbSDavid Woodhouse #include <linux/audit.h>
87d86b5e0eSAdrian Bunk #include <linux/wireless.h>
881b8d7ae4SEric W. Biederman #include <linux/nsproxy.h>
891fd7317dSNick Black #include <linux/magic.h>
905a0e3ad6STejun Heo #include <linux/slab.h>
91600e1779SMasatake YAMATO #include <linux/xattr.h>
921da177e4SLinus Torvalds 
937c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
941da177e4SLinus Torvalds #include <asm/unistd.h>
951da177e4SLinus Torvalds 
961da177e4SLinus Torvalds #include <net/compat.h>
9787de87d5SDavid S. Miller #include <net/wext.h>
98f8451725SHerbert Xu #include <net/cls_cgroup.h>
991da177e4SLinus Torvalds 
1001da177e4SLinus Torvalds #include <net/sock.h>
1011da177e4SLinus Torvalds #include <linux/netfilter.h>
1021da177e4SLinus Torvalds 
1036b96018bSArnd Bergmann #include <linux/if_tun.h>
1046b96018bSArnd Bergmann #include <linux/ipv6_route.h>
1056b96018bSArnd Bergmann #include <linux/route.h>
1066b96018bSArnd Bergmann #include <linux/sockios.h>
1076b96018bSArnd Bergmann #include <linux/atalk.h>
108076bb0c8SEliezer Tamir #include <net/busy_poll.h>
109f24b9be5SWillem de Bruijn #include <linux/errqueue.h>
11006021292SEliezer Tamir 
111e0d1095aSCong Wang #ifdef CONFIG_NET_RX_BUSY_POLL
11264b0dc51SEliezer Tamir unsigned int sysctl_net_busy_read __read_mostly;
11364b0dc51SEliezer Tamir unsigned int sysctl_net_busy_poll __read_mostly;
11406021292SEliezer Tamir #endif
1156b96018bSArnd Bergmann 
1168ae5e030SAl Viro static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to);
1178ae5e030SAl Viro static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from);
1181da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma);
1191da177e4SLinus Torvalds 
1201da177e4SLinus Torvalds static int sock_close(struct inode *inode, struct file *file);
1211da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file,
1221da177e4SLinus Torvalds 			      struct poll_table_struct *wait);
12389bddce5SStephen Hemminger static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
12489bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
12589bbfc95SShaun Pereira static long compat_sock_ioctl(struct file *file,
12689bbfc95SShaun Pereira 			      unsigned int cmd, unsigned long arg);
12789bbfc95SShaun Pereira #endif
1281da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on);
1291da177e4SLinus Torvalds static ssize_t sock_sendpage(struct file *file, struct page *page,
1301da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more);
1319c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
1329c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
1339c55e01cSJens Axboe 				unsigned int flags);
1341da177e4SLinus Torvalds 
1351da177e4SLinus Torvalds /*
1361da177e4SLinus Torvalds  *	Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
1371da177e4SLinus Torvalds  *	in the operation structures but are done directly via the socketcall() multiplexor.
1381da177e4SLinus Torvalds  */
1391da177e4SLinus Torvalds 
140da7071d7SArjan van de Ven static const struct file_operations socket_file_ops = {
1411da177e4SLinus Torvalds 	.owner =	THIS_MODULE,
1421da177e4SLinus Torvalds 	.llseek =	no_llseek,
1438ae5e030SAl Viro 	.read_iter =	sock_read_iter,
1448ae5e030SAl Viro 	.write_iter =	sock_write_iter,
1451da177e4SLinus Torvalds 	.poll =		sock_poll,
1461da177e4SLinus Torvalds 	.unlocked_ioctl = sock_ioctl,
14789bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
14889bbfc95SShaun Pereira 	.compat_ioctl = compat_sock_ioctl,
14989bbfc95SShaun Pereira #endif
1501da177e4SLinus Torvalds 	.mmap =		sock_mmap,
1511da177e4SLinus Torvalds 	.release =	sock_close,
1521da177e4SLinus Torvalds 	.fasync =	sock_fasync,
1535274f052SJens Axboe 	.sendpage =	sock_sendpage,
1545274f052SJens Axboe 	.splice_write = generic_splice_sendpage,
1559c55e01cSJens Axboe 	.splice_read =	sock_splice_read,
1561da177e4SLinus Torvalds };
1571da177e4SLinus Torvalds 
1581da177e4SLinus Torvalds /*
1591da177e4SLinus Torvalds  *	The protocol list. Each protocol is registered in here.
1601da177e4SLinus Torvalds  */
1611da177e4SLinus Torvalds 
1621da177e4SLinus Torvalds static DEFINE_SPINLOCK(net_family_lock);
163190683a9SEric Dumazet static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly;
1641da177e4SLinus Torvalds 
1651da177e4SLinus Torvalds /*
1661da177e4SLinus Torvalds  *	Statistics counters of the socket lists
1671da177e4SLinus Torvalds  */
1681da177e4SLinus Torvalds 
169c6d409cfSEric Dumazet static DEFINE_PER_CPU(int, sockets_in_use);
1701da177e4SLinus Torvalds 
1711da177e4SLinus Torvalds /*
17289bddce5SStephen Hemminger  * Support routines.
17389bddce5SStephen Hemminger  * Move socket addresses back and forth across the kernel/user
1741da177e4SLinus Torvalds  * divide and look after the messy bits.
1751da177e4SLinus Torvalds  */
1761da177e4SLinus Torvalds 
1771da177e4SLinus Torvalds /**
1781da177e4SLinus Torvalds  *	move_addr_to_kernel	-	copy a socket address into kernel space
1791da177e4SLinus Torvalds  *	@uaddr: Address in user space
1801da177e4SLinus Torvalds  *	@kaddr: Address in kernel space
1811da177e4SLinus Torvalds  *	@ulen: Length in user space
1821da177e4SLinus Torvalds  *
1831da177e4SLinus Torvalds  *	The address is copied into kernel space. If the provided address is
1841da177e4SLinus Torvalds  *	too long an error code of -EINVAL is returned. If the copy gives
1851da177e4SLinus Torvalds  *	invalid addresses -EFAULT is returned. On a success 0 is returned.
1861da177e4SLinus Torvalds  */
1871da177e4SLinus Torvalds 
18843db362dSMaciej Żenczykowski int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr)
1891da177e4SLinus Torvalds {
190230b1839SYOSHIFUJI Hideaki 	if (ulen < 0 || ulen > sizeof(struct sockaddr_storage))
1911da177e4SLinus Torvalds 		return -EINVAL;
1921da177e4SLinus Torvalds 	if (ulen == 0)
1931da177e4SLinus Torvalds 		return 0;
1941da177e4SLinus Torvalds 	if (copy_from_user(kaddr, uaddr, ulen))
1951da177e4SLinus Torvalds 		return -EFAULT;
1963ec3b2fbSDavid Woodhouse 	return audit_sockaddr(ulen, kaddr);
1971da177e4SLinus Torvalds }
1981da177e4SLinus Torvalds 
1991da177e4SLinus Torvalds /**
2001da177e4SLinus Torvalds  *	move_addr_to_user	-	copy an address to user space
2011da177e4SLinus Torvalds  *	@kaddr: kernel space address
2021da177e4SLinus Torvalds  *	@klen: length of address in kernel
2031da177e4SLinus Torvalds  *	@uaddr: user space address
2041da177e4SLinus Torvalds  *	@ulen: pointer to user length field
2051da177e4SLinus Torvalds  *
2061da177e4SLinus Torvalds  *	The value pointed to by ulen on entry is the buffer length available.
2071da177e4SLinus Torvalds  *	This is overwritten with the buffer space used. -EINVAL is returned
2081da177e4SLinus Torvalds  *	if an overlong buffer is specified or a negative buffer size. -EFAULT
2091da177e4SLinus Torvalds  *	is returned if either the buffer or the length field are not
2101da177e4SLinus Torvalds  *	accessible.
2111da177e4SLinus Torvalds  *	After copying the data up to the limit the user specifies, the true
2121da177e4SLinus Torvalds  *	length of the data is written over the length limit the user
2131da177e4SLinus Torvalds  *	specified. Zero is returned for a success.
2141da177e4SLinus Torvalds  */
2151da177e4SLinus Torvalds 
21643db362dSMaciej Żenczykowski static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen,
21711165f14Sstephen hemminger 			     void __user *uaddr, int __user *ulen)
2181da177e4SLinus Torvalds {
2191da177e4SLinus Torvalds 	int err;
2201da177e4SLinus Torvalds 	int len;
2211da177e4SLinus Torvalds 
22268c6beb3SHannes Frederic Sowa 	BUG_ON(klen > sizeof(struct sockaddr_storage));
22389bddce5SStephen Hemminger 	err = get_user(len, ulen);
22489bddce5SStephen Hemminger 	if (err)
2251da177e4SLinus Torvalds 		return err;
2261da177e4SLinus Torvalds 	if (len > klen)
2271da177e4SLinus Torvalds 		len = klen;
22868c6beb3SHannes Frederic Sowa 	if (len < 0)
2291da177e4SLinus Torvalds 		return -EINVAL;
23089bddce5SStephen Hemminger 	if (len) {
231d6fe3945SSteve Grubb 		if (audit_sockaddr(klen, kaddr))
232d6fe3945SSteve Grubb 			return -ENOMEM;
2331da177e4SLinus Torvalds 		if (copy_to_user(uaddr, kaddr, len))
2341da177e4SLinus Torvalds 			return -EFAULT;
2351da177e4SLinus Torvalds 	}
2361da177e4SLinus Torvalds 	/*
2371da177e4SLinus Torvalds 	 *      "fromlen shall refer to the value before truncation.."
2381da177e4SLinus Torvalds 	 *                      1003.1g
2391da177e4SLinus Torvalds 	 */
2401da177e4SLinus Torvalds 	return __put_user(klen, ulen);
2411da177e4SLinus Torvalds }
2421da177e4SLinus Torvalds 
243e18b890bSChristoph Lameter static struct kmem_cache *sock_inode_cachep __read_mostly;
2441da177e4SLinus Torvalds 
2451da177e4SLinus Torvalds static struct inode *sock_alloc_inode(struct super_block *sb)
2461da177e4SLinus Torvalds {
2471da177e4SLinus Torvalds 	struct socket_alloc *ei;
248eaefd110SEric Dumazet 	struct socket_wq *wq;
24989bddce5SStephen Hemminger 
250e94b1766SChristoph Lameter 	ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL);
2511da177e4SLinus Torvalds 	if (!ei)
2521da177e4SLinus Torvalds 		return NULL;
253eaefd110SEric Dumazet 	wq = kmalloc(sizeof(*wq), GFP_KERNEL);
254eaefd110SEric Dumazet 	if (!wq) {
25543815482SEric Dumazet 		kmem_cache_free(sock_inode_cachep, ei);
25643815482SEric Dumazet 		return NULL;
25743815482SEric Dumazet 	}
258eaefd110SEric Dumazet 	init_waitqueue_head(&wq->wait);
259eaefd110SEric Dumazet 	wq->fasync_list = NULL;
260574aab1eSNicolai Stange 	wq->flags = 0;
261eaefd110SEric Dumazet 	RCU_INIT_POINTER(ei->socket.wq, wq);
2621da177e4SLinus Torvalds 
2631da177e4SLinus Torvalds 	ei->socket.state = SS_UNCONNECTED;
2641da177e4SLinus Torvalds 	ei->socket.flags = 0;
2651da177e4SLinus Torvalds 	ei->socket.ops = NULL;
2661da177e4SLinus Torvalds 	ei->socket.sk = NULL;
2671da177e4SLinus Torvalds 	ei->socket.file = NULL;
2681da177e4SLinus Torvalds 
2691da177e4SLinus Torvalds 	return &ei->vfs_inode;
2701da177e4SLinus Torvalds }
2711da177e4SLinus Torvalds 
2721da177e4SLinus Torvalds static void sock_destroy_inode(struct inode *inode)
2731da177e4SLinus Torvalds {
27443815482SEric Dumazet 	struct socket_alloc *ei;
275eaefd110SEric Dumazet 	struct socket_wq *wq;
27643815482SEric Dumazet 
27743815482SEric Dumazet 	ei = container_of(inode, struct socket_alloc, vfs_inode);
278eaefd110SEric Dumazet 	wq = rcu_dereference_protected(ei->socket.wq, 1);
27961845220SLai Jiangshan 	kfree_rcu(wq, rcu);
28043815482SEric Dumazet 	kmem_cache_free(sock_inode_cachep, ei);
2811da177e4SLinus Torvalds }
2821da177e4SLinus Torvalds 
28351cc5068SAlexey Dobriyan static void init_once(void *foo)
2841da177e4SLinus Torvalds {
2851da177e4SLinus Torvalds 	struct socket_alloc *ei = (struct socket_alloc *)foo;
2861da177e4SLinus Torvalds 
2871da177e4SLinus Torvalds 	inode_init_once(&ei->vfs_inode);
2881da177e4SLinus Torvalds }
2891da177e4SLinus Torvalds 
2901e911632Syuan linyu static void init_inodecache(void)
2911da177e4SLinus Torvalds {
2921da177e4SLinus Torvalds 	sock_inode_cachep = kmem_cache_create("sock_inode_cache",
2931da177e4SLinus Torvalds 					      sizeof(struct socket_alloc),
29489bddce5SStephen Hemminger 					      0,
29589bddce5SStephen Hemminger 					      (SLAB_HWCACHE_ALIGN |
29689bddce5SStephen Hemminger 					       SLAB_RECLAIM_ACCOUNT |
2975d097056SVladimir Davydov 					       SLAB_MEM_SPREAD | SLAB_ACCOUNT),
29820c2df83SPaul Mundt 					      init_once);
2991e911632Syuan linyu 	BUG_ON(sock_inode_cachep == NULL);
3001da177e4SLinus Torvalds }
3011da177e4SLinus Torvalds 
302b87221deSAlexey Dobriyan static const struct super_operations sockfs_ops = {
3031da177e4SLinus Torvalds 	.alloc_inode	= sock_alloc_inode,
3041da177e4SLinus Torvalds 	.destroy_inode	= sock_destroy_inode,
3051da177e4SLinus Torvalds 	.statfs		= simple_statfs,
3061da177e4SLinus Torvalds };
3071da177e4SLinus Torvalds 
308c23fbb6bSEric Dumazet /*
309c23fbb6bSEric Dumazet  * sockfs_dname() is called from d_path().
310c23fbb6bSEric Dumazet  */
311c23fbb6bSEric Dumazet static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen)
312c23fbb6bSEric Dumazet {
313c23fbb6bSEric Dumazet 	return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]",
314c5ef6035SDavid Howells 				d_inode(dentry)->i_ino);
315c23fbb6bSEric Dumazet }
316c23fbb6bSEric Dumazet 
3173ba13d17SAl Viro static const struct dentry_operations sockfs_dentry_operations = {
318c23fbb6bSEric Dumazet 	.d_dname  = sockfs_dname,
3191da177e4SLinus Torvalds };
3201da177e4SLinus Torvalds 
321bba0bd31SAndreas Gruenbacher static int sockfs_xattr_get(const struct xattr_handler *handler,
322bba0bd31SAndreas Gruenbacher 			    struct dentry *dentry, struct inode *inode,
323bba0bd31SAndreas Gruenbacher 			    const char *suffix, void *value, size_t size)
324bba0bd31SAndreas Gruenbacher {
325bba0bd31SAndreas Gruenbacher 	if (value) {
326bba0bd31SAndreas Gruenbacher 		if (dentry->d_name.len + 1 > size)
327bba0bd31SAndreas Gruenbacher 			return -ERANGE;
328bba0bd31SAndreas Gruenbacher 		memcpy(value, dentry->d_name.name, dentry->d_name.len + 1);
329bba0bd31SAndreas Gruenbacher 	}
330bba0bd31SAndreas Gruenbacher 	return dentry->d_name.len + 1;
331bba0bd31SAndreas Gruenbacher }
332bba0bd31SAndreas Gruenbacher 
333bba0bd31SAndreas Gruenbacher #define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname"
334bba0bd31SAndreas Gruenbacher #define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX)
335bba0bd31SAndreas Gruenbacher #define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1)
336bba0bd31SAndreas Gruenbacher 
337bba0bd31SAndreas Gruenbacher static const struct xattr_handler sockfs_xattr_handler = {
338bba0bd31SAndreas Gruenbacher 	.name = XATTR_NAME_SOCKPROTONAME,
339bba0bd31SAndreas Gruenbacher 	.get = sockfs_xattr_get,
340bba0bd31SAndreas Gruenbacher };
341bba0bd31SAndreas Gruenbacher 
3424a590153SAndreas Gruenbacher static int sockfs_security_xattr_set(const struct xattr_handler *handler,
3434a590153SAndreas Gruenbacher 				     struct dentry *dentry, struct inode *inode,
3444a590153SAndreas Gruenbacher 				     const char *suffix, const void *value,
3454a590153SAndreas Gruenbacher 				     size_t size, int flags)
3464a590153SAndreas Gruenbacher {
3474a590153SAndreas Gruenbacher 	/* Handled by LSM. */
3484a590153SAndreas Gruenbacher 	return -EAGAIN;
3494a590153SAndreas Gruenbacher }
3504a590153SAndreas Gruenbacher 
3514a590153SAndreas Gruenbacher static const struct xattr_handler sockfs_security_xattr_handler = {
3524a590153SAndreas Gruenbacher 	.prefix = XATTR_SECURITY_PREFIX,
3534a590153SAndreas Gruenbacher 	.set = sockfs_security_xattr_set,
3544a590153SAndreas Gruenbacher };
3554a590153SAndreas Gruenbacher 
356bba0bd31SAndreas Gruenbacher static const struct xattr_handler *sockfs_xattr_handlers[] = {
357bba0bd31SAndreas Gruenbacher 	&sockfs_xattr_handler,
3584a590153SAndreas Gruenbacher 	&sockfs_security_xattr_handler,
359bba0bd31SAndreas Gruenbacher 	NULL
360bba0bd31SAndreas Gruenbacher };
361bba0bd31SAndreas Gruenbacher 
362c74a1cbbSAl Viro static struct dentry *sockfs_mount(struct file_system_type *fs_type,
363c74a1cbbSAl Viro 			 int flags, const char *dev_name, void *data)
364c74a1cbbSAl Viro {
365bba0bd31SAndreas Gruenbacher 	return mount_pseudo_xattr(fs_type, "socket:", &sockfs_ops,
366bba0bd31SAndreas Gruenbacher 				  sockfs_xattr_handlers,
367c74a1cbbSAl Viro 				  &sockfs_dentry_operations, SOCKFS_MAGIC);
368c74a1cbbSAl Viro }
369c74a1cbbSAl Viro 
370c74a1cbbSAl Viro static struct vfsmount *sock_mnt __read_mostly;
371c74a1cbbSAl Viro 
372c74a1cbbSAl Viro static struct file_system_type sock_fs_type = {
373c74a1cbbSAl Viro 	.name =		"sockfs",
374c74a1cbbSAl Viro 	.mount =	sockfs_mount,
375c74a1cbbSAl Viro 	.kill_sb =	kill_anon_super,
376c74a1cbbSAl Viro };
377c74a1cbbSAl Viro 
3781da177e4SLinus Torvalds /*
3791da177e4SLinus Torvalds  *	Obtains the first available file descriptor and sets it up for use.
3801da177e4SLinus Torvalds  *
38139d8c1b6SDavid S. Miller  *	These functions create file structures and maps them to fd space
38239d8c1b6SDavid S. Miller  *	of the current process. On success it returns file descriptor
3831da177e4SLinus Torvalds  *	and file struct implicitly stored in sock->file.
3841da177e4SLinus Torvalds  *	Note that another thread may close file descriptor before we return
3851da177e4SLinus Torvalds  *	from this function. We use the fact that now we do not refer
3861da177e4SLinus Torvalds  *	to socket after mapping. If one day we will need it, this
3871da177e4SLinus Torvalds  *	function will increment ref. count on file by 1.
3881da177e4SLinus Torvalds  *
3891da177e4SLinus Torvalds  *	In any case returned fd MAY BE not valid!
3901da177e4SLinus Torvalds  *	This race condition is unavoidable
3911da177e4SLinus Torvalds  *	with shared fd spaces, we cannot solve it inside kernel,
3921da177e4SLinus Torvalds  *	but we take care of internal coherence yet.
3931da177e4SLinus Torvalds  */
3941da177e4SLinus Torvalds 
395aab174f0SLinus Torvalds struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)
3961da177e4SLinus Torvalds {
3977cbe66b6SAl Viro 	struct qstr name = { .name = "" };
3982c48b9c4SAl Viro 	struct path path;
3997cbe66b6SAl Viro 	struct file *file;
4001da177e4SLinus Torvalds 
401600e1779SMasatake YAMATO 	if (dname) {
402600e1779SMasatake YAMATO 		name.name = dname;
403600e1779SMasatake YAMATO 		name.len = strlen(name.name);
404600e1779SMasatake YAMATO 	} else if (sock->sk) {
405600e1779SMasatake YAMATO 		name.name = sock->sk->sk_prot_creator->name;
406600e1779SMasatake YAMATO 		name.len = strlen(name.name);
407600e1779SMasatake YAMATO 	}
4084b936885SNick Piggin 	path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name);
40928407630SAl Viro 	if (unlikely(!path.dentry))
41028407630SAl Viro 		return ERR_PTR(-ENOMEM);
4112c48b9c4SAl Viro 	path.mnt = mntget(sock_mnt);
41239d8c1b6SDavid S. Miller 
4132c48b9c4SAl Viro 	d_instantiate(path.dentry, SOCK_INODE(sock));
414cc3808f8SAl Viro 
4152c48b9c4SAl Viro 	file = alloc_file(&path, FMODE_READ | FMODE_WRITE,
416cc3808f8SAl Viro 		  &socket_file_ops);
417b5ffe634SViresh Kumar 	if (IS_ERR(file)) {
418cc3808f8SAl Viro 		/* drop dentry, keep inode */
419c5ef6035SDavid Howells 		ihold(d_inode(path.dentry));
4202c48b9c4SAl Viro 		path_put(&path);
42139b65252SAnatol Pomozov 		return file;
422cc3808f8SAl Viro 	}
4231da177e4SLinus Torvalds 
4241da177e4SLinus Torvalds 	sock->file = file;
42577d27200SUlrich Drepper 	file->f_flags = O_RDWR | (flags & O_NONBLOCK);
42607dc3f07SBenjamin LaHaise 	file->private_data = sock;
42728407630SAl Viro 	return file;
4281da177e4SLinus Torvalds }
42956b31d1cSAl Viro EXPORT_SYMBOL(sock_alloc_file);
4301da177e4SLinus Torvalds 
43156b31d1cSAl Viro static int sock_map_fd(struct socket *sock, int flags)
43239d8c1b6SDavid S. Miller {
43339d8c1b6SDavid S. Miller 	struct file *newfile;
43428407630SAl Viro 	int fd = get_unused_fd_flags(flags);
43528407630SAl Viro 	if (unlikely(fd < 0))
4361da177e4SLinus Torvalds 		return fd;
4371da177e4SLinus Torvalds 
438aab174f0SLinus Torvalds 	newfile = sock_alloc_file(sock, flags, NULL);
43928407630SAl Viro 	if (likely(!IS_ERR(newfile))) {
4401da177e4SLinus Torvalds 		fd_install(fd, newfile);
4411da177e4SLinus Torvalds 		return fd;
4421da177e4SLinus Torvalds 	}
44328407630SAl Viro 
44428407630SAl Viro 	put_unused_fd(fd);
44528407630SAl Viro 	return PTR_ERR(newfile);
4461da177e4SLinus Torvalds }
4471da177e4SLinus Torvalds 
448406a3c63SJohn Fastabend struct socket *sock_from_file(struct file *file, int *err)
4496cb153caSBenjamin LaHaise {
4506cb153caSBenjamin LaHaise 	if (file->f_op == &socket_file_ops)
4516cb153caSBenjamin LaHaise 		return file->private_data;	/* set in sock_map_fd */
4526cb153caSBenjamin LaHaise 
4536cb153caSBenjamin LaHaise 	*err = -ENOTSOCK;
4546cb153caSBenjamin LaHaise 	return NULL;
4556cb153caSBenjamin LaHaise }
456406a3c63SJohn Fastabend EXPORT_SYMBOL(sock_from_file);
4576cb153caSBenjamin LaHaise 
4581da177e4SLinus Torvalds /**
4591da177e4SLinus Torvalds  *	sockfd_lookup - Go from a file number to its socket slot
4601da177e4SLinus Torvalds  *	@fd: file handle
4611da177e4SLinus Torvalds  *	@err: pointer to an error code return
4621da177e4SLinus Torvalds  *
4631da177e4SLinus Torvalds  *	The file handle passed in is locked and the socket it is bound
4641da177e4SLinus Torvalds  *	too is returned. If an error occurs the err pointer is overwritten
4651da177e4SLinus Torvalds  *	with a negative errno code and NULL is returned. The function checks
4661da177e4SLinus Torvalds  *	for both invalid handles and passing a handle which is not a socket.
4671da177e4SLinus Torvalds  *
4681da177e4SLinus Torvalds  *	On a success the socket object pointer is returned.
4691da177e4SLinus Torvalds  */
4701da177e4SLinus Torvalds 
4711da177e4SLinus Torvalds struct socket *sockfd_lookup(int fd, int *err)
4721da177e4SLinus Torvalds {
4731da177e4SLinus Torvalds 	struct file *file;
4741da177e4SLinus Torvalds 	struct socket *sock;
4751da177e4SLinus Torvalds 
47689bddce5SStephen Hemminger 	file = fget(fd);
47789bddce5SStephen Hemminger 	if (!file) {
4781da177e4SLinus Torvalds 		*err = -EBADF;
4791da177e4SLinus Torvalds 		return NULL;
4801da177e4SLinus Torvalds 	}
48189bddce5SStephen Hemminger 
4826cb153caSBenjamin LaHaise 	sock = sock_from_file(file, err);
4836cb153caSBenjamin LaHaise 	if (!sock)
4841da177e4SLinus Torvalds 		fput(file);
4856cb153caSBenjamin LaHaise 	return sock;
4861da177e4SLinus Torvalds }
487c6d409cfSEric Dumazet EXPORT_SYMBOL(sockfd_lookup);
4881da177e4SLinus Torvalds 
4896cb153caSBenjamin LaHaise static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
4906cb153caSBenjamin LaHaise {
49100e188efSAl Viro 	struct fd f = fdget(fd);
4926cb153caSBenjamin LaHaise 	struct socket *sock;
4936cb153caSBenjamin LaHaise 
4943672558cSHua Zhong 	*err = -EBADF;
49500e188efSAl Viro 	if (f.file) {
49600e188efSAl Viro 		sock = sock_from_file(f.file, err);
49700e188efSAl Viro 		if (likely(sock)) {
49800e188efSAl Viro 			*fput_needed = f.flags;
4991da177e4SLinus Torvalds 			return sock;
50000e188efSAl Viro 		}
50100e188efSAl Viro 		fdput(f);
5026cb153caSBenjamin LaHaise 	}
5036cb153caSBenjamin LaHaise 	return NULL;
5041da177e4SLinus Torvalds }
5051da177e4SLinus Torvalds 
506600e1779SMasatake YAMATO static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer,
507600e1779SMasatake YAMATO 				size_t size)
508600e1779SMasatake YAMATO {
509600e1779SMasatake YAMATO 	ssize_t len;
510600e1779SMasatake YAMATO 	ssize_t used = 0;
511600e1779SMasatake YAMATO 
512c5ef6035SDavid Howells 	len = security_inode_listsecurity(d_inode(dentry), buffer, size);
513600e1779SMasatake YAMATO 	if (len < 0)
514600e1779SMasatake YAMATO 		return len;
515600e1779SMasatake YAMATO 	used += len;
516600e1779SMasatake YAMATO 	if (buffer) {
517600e1779SMasatake YAMATO 		if (size < used)
518600e1779SMasatake YAMATO 			return -ERANGE;
519600e1779SMasatake YAMATO 		buffer += len;
520600e1779SMasatake YAMATO 	}
521600e1779SMasatake YAMATO 
522600e1779SMasatake YAMATO 	len = (XATTR_NAME_SOCKPROTONAME_LEN + 1);
523600e1779SMasatake YAMATO 	used += len;
524600e1779SMasatake YAMATO 	if (buffer) {
525600e1779SMasatake YAMATO 		if (size < used)
526600e1779SMasatake YAMATO 			return -ERANGE;
527600e1779SMasatake YAMATO 		memcpy(buffer, XATTR_NAME_SOCKPROTONAME, len);
528600e1779SMasatake YAMATO 		buffer += len;
529600e1779SMasatake YAMATO 	}
530600e1779SMasatake YAMATO 
531600e1779SMasatake YAMATO 	return used;
532600e1779SMasatake YAMATO }
533600e1779SMasatake YAMATO 
534dc647ec8STobias Klauser static int sockfs_setattr(struct dentry *dentry, struct iattr *iattr)
53586741ec2SLorenzo Colitti {
53686741ec2SLorenzo Colitti 	int err = simple_setattr(dentry, iattr);
53786741ec2SLorenzo Colitti 
538e1a3a60aSEric Biggers 	if (!err && (iattr->ia_valid & ATTR_UID)) {
53986741ec2SLorenzo Colitti 		struct socket *sock = SOCKET_I(d_inode(dentry));
54086741ec2SLorenzo Colitti 
54186741ec2SLorenzo Colitti 		sock->sk->sk_uid = iattr->ia_uid;
54286741ec2SLorenzo Colitti 	}
54386741ec2SLorenzo Colitti 
54486741ec2SLorenzo Colitti 	return err;
54586741ec2SLorenzo Colitti }
54686741ec2SLorenzo Colitti 
547600e1779SMasatake YAMATO static const struct inode_operations sockfs_inode_ops = {
548600e1779SMasatake YAMATO 	.listxattr = sockfs_listxattr,
54986741ec2SLorenzo Colitti 	.setattr = sockfs_setattr,
550600e1779SMasatake YAMATO };
551600e1779SMasatake YAMATO 
5521da177e4SLinus Torvalds /**
5531da177e4SLinus Torvalds  *	sock_alloc	-	allocate a socket
5541da177e4SLinus Torvalds  *
5551da177e4SLinus Torvalds  *	Allocate a new inode and socket object. The two are bound together
5561da177e4SLinus Torvalds  *	and initialised. The socket is then returned. If we are out of inodes
5571da177e4SLinus Torvalds  *	NULL is returned.
5581da177e4SLinus Torvalds  */
5591da177e4SLinus Torvalds 
560f4a00aacSTom Herbert struct socket *sock_alloc(void)
5611da177e4SLinus Torvalds {
5621da177e4SLinus Torvalds 	struct inode *inode;
5631da177e4SLinus Torvalds 	struct socket *sock;
5641da177e4SLinus Torvalds 
565a209dfc7SEric Dumazet 	inode = new_inode_pseudo(sock_mnt->mnt_sb);
5661da177e4SLinus Torvalds 	if (!inode)
5671da177e4SLinus Torvalds 		return NULL;
5681da177e4SLinus Torvalds 
5691da177e4SLinus Torvalds 	sock = SOCKET_I(inode);
5701da177e4SLinus Torvalds 
57129a020d3SEric Dumazet 	kmemcheck_annotate_bitfield(sock, type);
57285fe4025SChristoph Hellwig 	inode->i_ino = get_next_ino();
5731da177e4SLinus Torvalds 	inode->i_mode = S_IFSOCK | S_IRWXUGO;
5748192b0c4SDavid Howells 	inode->i_uid = current_fsuid();
5758192b0c4SDavid Howells 	inode->i_gid = current_fsgid();
576600e1779SMasatake YAMATO 	inode->i_op = &sockfs_inode_ops;
5771da177e4SLinus Torvalds 
57819e8d69cSAlex Shi 	this_cpu_add(sockets_in_use, 1);
5791da177e4SLinus Torvalds 	return sock;
5801da177e4SLinus Torvalds }
581f4a00aacSTom Herbert EXPORT_SYMBOL(sock_alloc);
5821da177e4SLinus Torvalds 
5831da177e4SLinus Torvalds /**
5841da177e4SLinus Torvalds  *	sock_release	-	close a socket
5851da177e4SLinus Torvalds  *	@sock: socket to close
5861da177e4SLinus Torvalds  *
5871da177e4SLinus Torvalds  *	The socket is released from the protocol stack if it has a release
5881da177e4SLinus Torvalds  *	callback, and the inode is then released if the socket is bound to
5891da177e4SLinus Torvalds  *	an inode not a file.
5901da177e4SLinus Torvalds  */
5911da177e4SLinus Torvalds 
5921da177e4SLinus Torvalds void sock_release(struct socket *sock)
5931da177e4SLinus Torvalds {
5941da177e4SLinus Torvalds 	if (sock->ops) {
5951da177e4SLinus Torvalds 		struct module *owner = sock->ops->owner;
5961da177e4SLinus Torvalds 
5971da177e4SLinus Torvalds 		sock->ops->release(sock);
5981da177e4SLinus Torvalds 		sock->ops = NULL;
5991da177e4SLinus Torvalds 		module_put(owner);
6001da177e4SLinus Torvalds 	}
6011da177e4SLinus Torvalds 
602eaefd110SEric Dumazet 	if (rcu_dereference_protected(sock->wq, 1)->fasync_list)
6033410f22eSYang Yingliang 		pr_err("%s: fasync list not empty!\n", __func__);
6041da177e4SLinus Torvalds 
60519e8d69cSAlex Shi 	this_cpu_sub(sockets_in_use, 1);
6061da177e4SLinus Torvalds 	if (!sock->file) {
6071da177e4SLinus Torvalds 		iput(SOCK_INODE(sock));
6081da177e4SLinus Torvalds 		return;
6091da177e4SLinus Torvalds 	}
6101da177e4SLinus Torvalds 	sock->file = NULL;
6111da177e4SLinus Torvalds }
612c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_release);
6131da177e4SLinus Torvalds 
614c14ac945SSoheil Hassas Yeganeh void __sock_tx_timestamp(__u16 tsflags, __u8 *tx_flags)
61520d49473SPatrick Ohly {
616140c55d4SEric Dumazet 	u8 flags = *tx_flags;
617140c55d4SEric Dumazet 
618c14ac945SSoheil Hassas Yeganeh 	if (tsflags & SOF_TIMESTAMPING_TX_HARDWARE)
619140c55d4SEric Dumazet 		flags |= SKBTX_HW_TSTAMP;
620140c55d4SEric Dumazet 
621c14ac945SSoheil Hassas Yeganeh 	if (tsflags & SOF_TIMESTAMPING_TX_SOFTWARE)
622140c55d4SEric Dumazet 		flags |= SKBTX_SW_TSTAMP;
623140c55d4SEric Dumazet 
624c14ac945SSoheil Hassas Yeganeh 	if (tsflags & SOF_TIMESTAMPING_TX_SCHED)
625140c55d4SEric Dumazet 		flags |= SKBTX_SCHED_TSTAMP;
626140c55d4SEric Dumazet 
627140c55d4SEric Dumazet 	*tx_flags = flags;
62820d49473SPatrick Ohly }
62967cc0d40SWillem de Bruijn EXPORT_SYMBOL(__sock_tx_timestamp);
63020d49473SPatrick Ohly 
631d8725c86SAl Viro static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg)
6321da177e4SLinus Torvalds {
63301e97e65SAl Viro 	int ret = sock->ops->sendmsg(sock, msg, msg_data_left(msg));
634d8725c86SAl Viro 	BUG_ON(ret == -EIOCBQUEUED);
635d8725c86SAl Viro 	return ret;
6361da177e4SLinus Torvalds }
6370cf00c6fSGu Zheng 
638d8725c86SAl Viro int sock_sendmsg(struct socket *sock, struct msghdr *msg)
6390cf00c6fSGu Zheng {
640d8725c86SAl Viro 	int err = security_socket_sendmsg(sock, msg,
64101e97e65SAl Viro 					  msg_data_left(msg));
6421b784140SYing Xue 
643d8725c86SAl Viro 	return err ?: sock_sendmsg_nosec(sock, msg);
6440cf00c6fSGu Zheng }
645c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_sendmsg);
6461da177e4SLinus Torvalds 
6471da177e4SLinus Torvalds int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
6481da177e4SLinus Torvalds 		   struct kvec *vec, size_t num, size_t size)
6491da177e4SLinus Torvalds {
6506aa24814SAl Viro 	iov_iter_kvec(&msg->msg_iter, WRITE | ITER_KVEC, vec, num, size);
651d8725c86SAl Viro 	return sock_sendmsg(sock, msg);
6521da177e4SLinus Torvalds }
653c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendmsg);
6541da177e4SLinus Torvalds 
6558605330aSSoheil Hassas Yeganeh static bool skb_is_err_queue(const struct sk_buff *skb)
6568605330aSSoheil Hassas Yeganeh {
6578605330aSSoheil Hassas Yeganeh 	/* pkt_type of skbs enqueued on the error queue are set to
6588605330aSSoheil Hassas Yeganeh 	 * PACKET_OUTGOING in skb_set_err_queue(). This is only safe to do
6598605330aSSoheil Hassas Yeganeh 	 * in recvmsg, since skbs received on a local socket will never
6608605330aSSoheil Hassas Yeganeh 	 * have a pkt_type of PACKET_OUTGOING.
6618605330aSSoheil Hassas Yeganeh 	 */
6628605330aSSoheil Hassas Yeganeh 	return skb->pkt_type == PACKET_OUTGOING;
6638605330aSSoheil Hassas Yeganeh }
6648605330aSSoheil Hassas Yeganeh 
665aad9c8c4SMiroslav Lichvar static void put_ts_pktinfo(struct msghdr *msg, struct sk_buff *skb)
666aad9c8c4SMiroslav Lichvar {
667aad9c8c4SMiroslav Lichvar 	struct scm_ts_pktinfo ts_pktinfo;
668aad9c8c4SMiroslav Lichvar 	struct net_device *orig_dev;
669aad9c8c4SMiroslav Lichvar 
670aad9c8c4SMiroslav Lichvar 	if (!skb_mac_header_was_set(skb))
671aad9c8c4SMiroslav Lichvar 		return;
672aad9c8c4SMiroslav Lichvar 
673aad9c8c4SMiroslav Lichvar 	memset(&ts_pktinfo, 0, sizeof(ts_pktinfo));
674aad9c8c4SMiroslav Lichvar 
675aad9c8c4SMiroslav Lichvar 	rcu_read_lock();
676aad9c8c4SMiroslav Lichvar 	orig_dev = dev_get_by_napi_id(skb_napi_id(skb));
677aad9c8c4SMiroslav Lichvar 	if (orig_dev)
678aad9c8c4SMiroslav Lichvar 		ts_pktinfo.if_index = orig_dev->ifindex;
679aad9c8c4SMiroslav Lichvar 	rcu_read_unlock();
680aad9c8c4SMiroslav Lichvar 
681aad9c8c4SMiroslav Lichvar 	ts_pktinfo.pkt_length = skb->len - skb_mac_offset(skb);
682aad9c8c4SMiroslav Lichvar 	put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_PKTINFO,
683aad9c8c4SMiroslav Lichvar 		 sizeof(ts_pktinfo), &ts_pktinfo);
684aad9c8c4SMiroslav Lichvar }
685aad9c8c4SMiroslav Lichvar 
68692f37fd2SEric Dumazet /*
68792f37fd2SEric Dumazet  * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
68892f37fd2SEric Dumazet  */
68992f37fd2SEric Dumazet void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
69092f37fd2SEric Dumazet 	struct sk_buff *skb)
69192f37fd2SEric Dumazet {
69220d49473SPatrick Ohly 	int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
693f24b9be5SWillem de Bruijn 	struct scm_timestamping tss;
69420d49473SPatrick Ohly 	int empty = 1;
69520d49473SPatrick Ohly 	struct skb_shared_hwtstamps *shhwtstamps =
69620d49473SPatrick Ohly 		skb_hwtstamps(skb);
69792f37fd2SEric Dumazet 
69820d49473SPatrick Ohly 	/* Race occurred between timestamp enabling and packet
69920d49473SPatrick Ohly 	   receiving.  Fill in the current time for now. */
7002456e855SThomas Gleixner 	if (need_software_tstamp && skb->tstamp == 0)
70120d49473SPatrick Ohly 		__net_timestamp(skb);
70220d49473SPatrick Ohly 
70320d49473SPatrick Ohly 	if (need_software_tstamp) {
70492f37fd2SEric Dumazet 		if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
70592f37fd2SEric Dumazet 			struct timeval tv;
70620d49473SPatrick Ohly 			skb_get_timestamp(skb, &tv);
70720d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP,
70820d49473SPatrick Ohly 				 sizeof(tv), &tv);
70992f37fd2SEric Dumazet 		} else {
710f24b9be5SWillem de Bruijn 			struct timespec ts;
711f24b9be5SWillem de Bruijn 			skb_get_timestampns(skb, &ts);
71220d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS,
713f24b9be5SWillem de Bruijn 				 sizeof(ts), &ts);
71492f37fd2SEric Dumazet 		}
71592f37fd2SEric Dumazet 	}
71692f37fd2SEric Dumazet 
717f24b9be5SWillem de Bruijn 	memset(&tss, 0, sizeof(tss));
718c199105dSWillem de Bruijn 	if ((sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE) &&
719f24b9be5SWillem de Bruijn 	    ktime_to_timespec_cond(skb->tstamp, tss.ts + 0))
72020d49473SPatrick Ohly 		empty = 0;
7214d276eb6SWillem de Bruijn 	if (shhwtstamps &&
722b9f40e21SWillem de Bruijn 	    (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
723aad9c8c4SMiroslav Lichvar 	    ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2)) {
72420d49473SPatrick Ohly 		empty = 0;
725aad9c8c4SMiroslav Lichvar 		if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_PKTINFO) &&
726aad9c8c4SMiroslav Lichvar 		    !skb_is_err_queue(skb))
727aad9c8c4SMiroslav Lichvar 			put_ts_pktinfo(msg, skb);
728aad9c8c4SMiroslav Lichvar 	}
7291c885808SFrancis Yan 	if (!empty) {
73020d49473SPatrick Ohly 		put_cmsg(msg, SOL_SOCKET,
731f24b9be5SWillem de Bruijn 			 SCM_TIMESTAMPING, sizeof(tss), &tss);
7321c885808SFrancis Yan 
7338605330aSSoheil Hassas Yeganeh 		if (skb_is_err_queue(skb) && skb->len &&
7344ef1b286SSoheil Hassas Yeganeh 		    SKB_EXT_ERR(skb)->opt_stats)
7351c885808SFrancis Yan 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_OPT_STATS,
7361c885808SFrancis Yan 				 skb->len, skb->data);
7371c885808SFrancis Yan 	}
73820d49473SPatrick Ohly }
7397c81fd8bSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
7407c81fd8bSArnaldo Carvalho de Melo 
7416e3e939fSJohannes Berg void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
7426e3e939fSJohannes Berg 	struct sk_buff *skb)
7436e3e939fSJohannes Berg {
7446e3e939fSJohannes Berg 	int ack;
7456e3e939fSJohannes Berg 
7466e3e939fSJohannes Berg 	if (!sock_flag(sk, SOCK_WIFI_STATUS))
7476e3e939fSJohannes Berg 		return;
7486e3e939fSJohannes Berg 	if (!skb->wifi_acked_valid)
7496e3e939fSJohannes Berg 		return;
7506e3e939fSJohannes Berg 
7516e3e939fSJohannes Berg 	ack = skb->wifi_acked;
7526e3e939fSJohannes Berg 
7536e3e939fSJohannes Berg 	put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack);
7546e3e939fSJohannes Berg }
7556e3e939fSJohannes Berg EXPORT_SYMBOL_GPL(__sock_recv_wifi_status);
7566e3e939fSJohannes Berg 
75711165f14Sstephen hemminger static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk,
75811165f14Sstephen hemminger 				   struct sk_buff *skb)
7593b885787SNeil Horman {
760744d5a3eSEyal Birger 	if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && SOCK_SKB_CB(skb)->dropcount)
7613b885787SNeil Horman 		put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL,
762744d5a3eSEyal Birger 			sizeof(__u32), &SOCK_SKB_CB(skb)->dropcount);
7633b885787SNeil Horman }
7643b885787SNeil Horman 
765767dd033SEric Dumazet void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
7663b885787SNeil Horman 	struct sk_buff *skb)
7673b885787SNeil Horman {
7683b885787SNeil Horman 	sock_recv_timestamp(msg, sk, skb);
7693b885787SNeil Horman 	sock_recv_drops(msg, sk, skb);
7703b885787SNeil Horman }
771767dd033SEric Dumazet EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops);
7723b885787SNeil Horman 
7731b784140SYing Xue static inline int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
7741b784140SYing Xue 				     int flags)
775a2e27255SArnaldo Carvalho de Melo {
7762da62906SAl Viro 	return sock->ops->recvmsg(sock, msg, msg_data_left(msg), flags);
7772da62906SAl Viro }
778a2e27255SArnaldo Carvalho de Melo 
7792da62906SAl Viro int sock_recvmsg(struct socket *sock, struct msghdr *msg, int flags)
7802da62906SAl Viro {
7812da62906SAl Viro 	int err = security_socket_recvmsg(sock, msg, msg_data_left(msg), flags);
7822da62906SAl Viro 
7832da62906SAl Viro 	return err ?: sock_recvmsg_nosec(sock, msg, flags);
7841da177e4SLinus Torvalds }
785c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_recvmsg);
7861da177e4SLinus Torvalds 
787c1249c0aSMartin Lucina /**
788c1249c0aSMartin Lucina  * kernel_recvmsg - Receive a message from a socket (kernel space)
789c1249c0aSMartin Lucina  * @sock:       The socket to receive the message from
790c1249c0aSMartin Lucina  * @msg:        Received message
791c1249c0aSMartin Lucina  * @vec:        Input s/g array for message data
792c1249c0aSMartin Lucina  * @num:        Size of input s/g array
793c1249c0aSMartin Lucina  * @size:       Number of bytes to read
794c1249c0aSMartin Lucina  * @flags:      Message flags (MSG_DONTWAIT, etc...)
795c1249c0aSMartin Lucina  *
796c1249c0aSMartin Lucina  * On return the msg structure contains the scatter/gather array passed in the
797c1249c0aSMartin Lucina  * vec argument. The array is modified so that it consists of the unfilled
798c1249c0aSMartin Lucina  * portion of the original array.
799c1249c0aSMartin Lucina  *
800c1249c0aSMartin Lucina  * The returned value is the total number of bytes received, or an error.
801c1249c0aSMartin Lucina  */
8021da177e4SLinus Torvalds int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
80389bddce5SStephen Hemminger 		   struct kvec *vec, size_t num, size_t size, int flags)
8041da177e4SLinus Torvalds {
8051da177e4SLinus Torvalds 	mm_segment_t oldfs = get_fs();
8061da177e4SLinus Torvalds 	int result;
8071da177e4SLinus Torvalds 
8086aa24814SAl Viro 	iov_iter_kvec(&msg->msg_iter, READ | ITER_KVEC, vec, num, size);
8091da177e4SLinus Torvalds 	set_fs(KERNEL_DS);
8102da62906SAl Viro 	result = sock_recvmsg(sock, msg, flags);
8111da177e4SLinus Torvalds 	set_fs(oldfs);
8121da177e4SLinus Torvalds 	return result;
8131da177e4SLinus Torvalds }
814c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_recvmsg);
8151da177e4SLinus Torvalds 
81620380731SArnaldo Carvalho de Melo static ssize_t sock_sendpage(struct file *file, struct page *page,
8171da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more)
8181da177e4SLinus Torvalds {
8191da177e4SLinus Torvalds 	struct socket *sock;
8201da177e4SLinus Torvalds 	int flags;
8211da177e4SLinus Torvalds 
822b69aee04SEric Dumazet 	sock = file->private_data;
8231da177e4SLinus Torvalds 
82435f9c09fSEric Dumazet 	flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
82535f9c09fSEric Dumazet 	/* more is a combination of MSG_MORE and MSG_SENDPAGE_NOTLAST */
82635f9c09fSEric Dumazet 	flags |= more;
8271da177e4SLinus Torvalds 
828e6949583SLinus Torvalds 	return kernel_sendpage(sock, page, offset, size, flags);
8291da177e4SLinus Torvalds }
8301da177e4SLinus Torvalds 
8319c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
8329c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
8339c55e01cSJens Axboe 				unsigned int flags)
8349c55e01cSJens Axboe {
8359c55e01cSJens Axboe 	struct socket *sock = file->private_data;
8369c55e01cSJens Axboe 
837997b37daSRémi Denis-Courmont 	if (unlikely(!sock->ops->splice_read))
838997b37daSRémi Denis-Courmont 		return -EINVAL;
839997b37daSRémi Denis-Courmont 
8409c55e01cSJens Axboe 	return sock->ops->splice_read(sock, ppos, pipe, len, flags);
8419c55e01cSJens Axboe }
8429c55e01cSJens Axboe 
8438ae5e030SAl Viro static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to)
844ce1d4d3eSChristoph Hellwig {
8456d652330SAl Viro 	struct file *file = iocb->ki_filp;
8466d652330SAl Viro 	struct socket *sock = file->private_data;
8470345f931Stadeusz.struk@intel.com 	struct msghdr msg = {.msg_iter = *to,
8480345f931Stadeusz.struk@intel.com 			     .msg_iocb = iocb};
8498ae5e030SAl Viro 	ssize_t res;
850ce1d4d3eSChristoph Hellwig 
8518ae5e030SAl Viro 	if (file->f_flags & O_NONBLOCK)
8528ae5e030SAl Viro 		msg.msg_flags = MSG_DONTWAIT;
8538ae5e030SAl Viro 
8548ae5e030SAl Viro 	if (iocb->ki_pos != 0)
855ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
856027445c3SBadari Pulavarty 
85766ee59afSChristoph Hellwig 	if (!iov_iter_count(to))	/* Match SYS5 behaviour */
858ce1d4d3eSChristoph Hellwig 		return 0;
859ce1d4d3eSChristoph Hellwig 
8602da62906SAl Viro 	res = sock_recvmsg(sock, &msg, msg.msg_flags);
8618ae5e030SAl Viro 	*to = msg.msg_iter;
8628ae5e030SAl Viro 	return res;
863ce1d4d3eSChristoph Hellwig }
864ce1d4d3eSChristoph Hellwig 
8658ae5e030SAl Viro static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from)
8661da177e4SLinus Torvalds {
8676d652330SAl Viro 	struct file *file = iocb->ki_filp;
8686d652330SAl Viro 	struct socket *sock = file->private_data;
8690345f931Stadeusz.struk@intel.com 	struct msghdr msg = {.msg_iter = *from,
8700345f931Stadeusz.struk@intel.com 			     .msg_iocb = iocb};
8718ae5e030SAl Viro 	ssize_t res;
8721da177e4SLinus Torvalds 
8738ae5e030SAl Viro 	if (iocb->ki_pos != 0)
874ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
875027445c3SBadari Pulavarty 
8768ae5e030SAl Viro 	if (file->f_flags & O_NONBLOCK)
8778ae5e030SAl Viro 		msg.msg_flags = MSG_DONTWAIT;
8788ae5e030SAl Viro 
8796d652330SAl Viro 	if (sock->type == SOCK_SEQPACKET)
8806d652330SAl Viro 		msg.msg_flags |= MSG_EOR;
8816d652330SAl Viro 
882d8725c86SAl Viro 	res = sock_sendmsg(sock, &msg);
8838ae5e030SAl Viro 	*from = msg.msg_iter;
8848ae5e030SAl Viro 	return res;
8851da177e4SLinus Torvalds }
8861da177e4SLinus Torvalds 
8871da177e4SLinus Torvalds /*
8881da177e4SLinus Torvalds  * Atomic setting of ioctl hooks to avoid race
8891da177e4SLinus Torvalds  * with module unload.
8901da177e4SLinus Torvalds  */
8911da177e4SLinus Torvalds 
8924a3e2f71SArjan van de Ven static DEFINE_MUTEX(br_ioctl_mutex);
893c6d409cfSEric Dumazet static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg);
8941da177e4SLinus Torvalds 
895881d966bSEric W. Biederman void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *))
8961da177e4SLinus Torvalds {
8974a3e2f71SArjan van de Ven 	mutex_lock(&br_ioctl_mutex);
8981da177e4SLinus Torvalds 	br_ioctl_hook = hook;
8994a3e2f71SArjan van de Ven 	mutex_unlock(&br_ioctl_mutex);
9001da177e4SLinus Torvalds }
9011da177e4SLinus Torvalds EXPORT_SYMBOL(brioctl_set);
9021da177e4SLinus Torvalds 
9034a3e2f71SArjan van de Ven static DEFINE_MUTEX(vlan_ioctl_mutex);
904881d966bSEric W. Biederman static int (*vlan_ioctl_hook) (struct net *, void __user *arg);
9051da177e4SLinus Torvalds 
906881d966bSEric W. Biederman void vlan_ioctl_set(int (*hook) (struct net *, void __user *))
9071da177e4SLinus Torvalds {
9084a3e2f71SArjan van de Ven 	mutex_lock(&vlan_ioctl_mutex);
9091da177e4SLinus Torvalds 	vlan_ioctl_hook = hook;
9104a3e2f71SArjan van de Ven 	mutex_unlock(&vlan_ioctl_mutex);
9111da177e4SLinus Torvalds }
9121da177e4SLinus Torvalds EXPORT_SYMBOL(vlan_ioctl_set);
9131da177e4SLinus Torvalds 
9144a3e2f71SArjan van de Ven static DEFINE_MUTEX(dlci_ioctl_mutex);
9151da177e4SLinus Torvalds static int (*dlci_ioctl_hook) (unsigned int, void __user *);
9161da177e4SLinus Torvalds 
9171da177e4SLinus Torvalds void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
9181da177e4SLinus Torvalds {
9194a3e2f71SArjan van de Ven 	mutex_lock(&dlci_ioctl_mutex);
9201da177e4SLinus Torvalds 	dlci_ioctl_hook = hook;
9214a3e2f71SArjan van de Ven 	mutex_unlock(&dlci_ioctl_mutex);
9221da177e4SLinus Torvalds }
9231da177e4SLinus Torvalds EXPORT_SYMBOL(dlci_ioctl_set);
9241da177e4SLinus Torvalds 
9256b96018bSArnd Bergmann static long sock_do_ioctl(struct net *net, struct socket *sock,
9266b96018bSArnd Bergmann 				 unsigned int cmd, unsigned long arg)
9276b96018bSArnd Bergmann {
9286b96018bSArnd Bergmann 	int err;
9296b96018bSArnd Bergmann 	void __user *argp = (void __user *)arg;
9306b96018bSArnd Bergmann 
9316b96018bSArnd Bergmann 	err = sock->ops->ioctl(sock, cmd, arg);
9326b96018bSArnd Bergmann 
9336b96018bSArnd Bergmann 	/*
9346b96018bSArnd Bergmann 	 * If this ioctl is unknown try to hand it down
9356b96018bSArnd Bergmann 	 * to the NIC driver.
9366b96018bSArnd Bergmann 	 */
9376b96018bSArnd Bergmann 	if (err == -ENOIOCTLCMD)
9386b96018bSArnd Bergmann 		err = dev_ioctl(net, cmd, argp);
9396b96018bSArnd Bergmann 
9406b96018bSArnd Bergmann 	return err;
9416b96018bSArnd Bergmann }
9426b96018bSArnd Bergmann 
9431da177e4SLinus Torvalds /*
9441da177e4SLinus Torvalds  *	With an ioctl, arg may well be a user mode pointer, but we don't know
9451da177e4SLinus Torvalds  *	what to do with it - that's up to the protocol still.
9461da177e4SLinus Torvalds  */
9471da177e4SLinus Torvalds 
948c62cce2cSAndrey Vagin static struct ns_common *get_net_ns(struct ns_common *ns)
949c62cce2cSAndrey Vagin {
950c62cce2cSAndrey Vagin 	return &get_net(container_of(ns, struct net, ns))->ns;
951c62cce2cSAndrey Vagin }
952c62cce2cSAndrey Vagin 
9531da177e4SLinus Torvalds static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
9541da177e4SLinus Torvalds {
9551da177e4SLinus Torvalds 	struct socket *sock;
956881d966bSEric W. Biederman 	struct sock *sk;
9571da177e4SLinus Torvalds 	void __user *argp = (void __user *)arg;
9581da177e4SLinus Torvalds 	int pid, err;
959881d966bSEric W. Biederman 	struct net *net;
9601da177e4SLinus Torvalds 
961b69aee04SEric Dumazet 	sock = file->private_data;
962881d966bSEric W. Biederman 	sk = sock->sk;
9633b1e0a65SYOSHIFUJI Hideaki 	net = sock_net(sk);
9641da177e4SLinus Torvalds 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
965881d966bSEric W. Biederman 		err = dev_ioctl(net, cmd, argp);
9661da177e4SLinus Torvalds 	} else
9673d23e349SJohannes Berg #ifdef CONFIG_WEXT_CORE
9681da177e4SLinus Torvalds 	if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
969881d966bSEric W. Biederman 		err = dev_ioctl(net, cmd, argp);
9701da177e4SLinus Torvalds 	} else
9713d23e349SJohannes Berg #endif
9721da177e4SLinus Torvalds 		switch (cmd) {
9731da177e4SLinus Torvalds 		case FIOSETOWN:
9741da177e4SLinus Torvalds 		case SIOCSPGRP:
9751da177e4SLinus Torvalds 			err = -EFAULT;
9761da177e4SLinus Torvalds 			if (get_user(pid, (int __user *)argp))
9771da177e4SLinus Torvalds 				break;
978e0b93eddSJeff Layton 			f_setown(sock->file, pid, 1);
979e0b93eddSJeff Layton 			err = 0;
9801da177e4SLinus Torvalds 			break;
9811da177e4SLinus Torvalds 		case FIOGETOWN:
9821da177e4SLinus Torvalds 		case SIOCGPGRP:
983609d7fa9SEric W. Biederman 			err = put_user(f_getown(sock->file),
98489bddce5SStephen Hemminger 				       (int __user *)argp);
9851da177e4SLinus Torvalds 			break;
9861da177e4SLinus Torvalds 		case SIOCGIFBR:
9871da177e4SLinus Torvalds 		case SIOCSIFBR:
9881da177e4SLinus Torvalds 		case SIOCBRADDBR:
9891da177e4SLinus Torvalds 		case SIOCBRDELBR:
9901da177e4SLinus Torvalds 			err = -ENOPKG;
9911da177e4SLinus Torvalds 			if (!br_ioctl_hook)
9921da177e4SLinus Torvalds 				request_module("bridge");
9931da177e4SLinus Torvalds 
9944a3e2f71SArjan van de Ven 			mutex_lock(&br_ioctl_mutex);
9951da177e4SLinus Torvalds 			if (br_ioctl_hook)
996881d966bSEric W. Biederman 				err = br_ioctl_hook(net, cmd, argp);
9974a3e2f71SArjan van de Ven 			mutex_unlock(&br_ioctl_mutex);
9981da177e4SLinus Torvalds 			break;
9991da177e4SLinus Torvalds 		case SIOCGIFVLAN:
10001da177e4SLinus Torvalds 		case SIOCSIFVLAN:
10011da177e4SLinus Torvalds 			err = -ENOPKG;
10021da177e4SLinus Torvalds 			if (!vlan_ioctl_hook)
10031da177e4SLinus Torvalds 				request_module("8021q");
10041da177e4SLinus Torvalds 
10054a3e2f71SArjan van de Ven 			mutex_lock(&vlan_ioctl_mutex);
10061da177e4SLinus Torvalds 			if (vlan_ioctl_hook)
1007881d966bSEric W. Biederman 				err = vlan_ioctl_hook(net, argp);
10084a3e2f71SArjan van de Ven 			mutex_unlock(&vlan_ioctl_mutex);
10091da177e4SLinus Torvalds 			break;
10101da177e4SLinus Torvalds 		case SIOCADDDLCI:
10111da177e4SLinus Torvalds 		case SIOCDELDLCI:
10121da177e4SLinus Torvalds 			err = -ENOPKG;
10131da177e4SLinus Torvalds 			if (!dlci_ioctl_hook)
10141da177e4SLinus Torvalds 				request_module("dlci");
10151da177e4SLinus Torvalds 
10164a3e2f71SArjan van de Ven 			mutex_lock(&dlci_ioctl_mutex);
10177512cbf6SPavel Emelyanov 			if (dlci_ioctl_hook)
10181da177e4SLinus Torvalds 				err = dlci_ioctl_hook(cmd, argp);
10194a3e2f71SArjan van de Ven 			mutex_unlock(&dlci_ioctl_mutex);
10201da177e4SLinus Torvalds 			break;
1021c62cce2cSAndrey Vagin 		case SIOCGSKNS:
1022c62cce2cSAndrey Vagin 			err = -EPERM;
1023c62cce2cSAndrey Vagin 			if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
1024c62cce2cSAndrey Vagin 				break;
1025c62cce2cSAndrey Vagin 
1026c62cce2cSAndrey Vagin 			err = open_related_ns(&net->ns, get_net_ns);
1027c62cce2cSAndrey Vagin 			break;
10281da177e4SLinus Torvalds 		default:
10296b96018bSArnd Bergmann 			err = sock_do_ioctl(net, sock, cmd, arg);
10301da177e4SLinus Torvalds 			break;
10311da177e4SLinus Torvalds 		}
10321da177e4SLinus Torvalds 	return err;
10331da177e4SLinus Torvalds }
10341da177e4SLinus Torvalds 
10351da177e4SLinus Torvalds int sock_create_lite(int family, int type, int protocol, struct socket **res)
10361da177e4SLinus Torvalds {
10371da177e4SLinus Torvalds 	int err;
10381da177e4SLinus Torvalds 	struct socket *sock = NULL;
10391da177e4SLinus Torvalds 
10401da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, 1);
10411da177e4SLinus Torvalds 	if (err)
10421da177e4SLinus Torvalds 		goto out;
10431da177e4SLinus Torvalds 
10441da177e4SLinus Torvalds 	sock = sock_alloc();
10451da177e4SLinus Torvalds 	if (!sock) {
10461da177e4SLinus Torvalds 		err = -ENOMEM;
10471da177e4SLinus Torvalds 		goto out;
10481da177e4SLinus Torvalds 	}
10491da177e4SLinus Torvalds 
10501da177e4SLinus Torvalds 	sock->type = type;
10517420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, 1);
10527420ed23SVenkat Yekkirala 	if (err)
10537420ed23SVenkat Yekkirala 		goto out_release;
10547420ed23SVenkat Yekkirala 
10551da177e4SLinus Torvalds out:
10561da177e4SLinus Torvalds 	*res = sock;
10571da177e4SLinus Torvalds 	return err;
10587420ed23SVenkat Yekkirala out_release:
10597420ed23SVenkat Yekkirala 	sock_release(sock);
10607420ed23SVenkat Yekkirala 	sock = NULL;
10617420ed23SVenkat Yekkirala 	goto out;
10621da177e4SLinus Torvalds }
1063c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_lite);
10641da177e4SLinus Torvalds 
10651da177e4SLinus Torvalds /* No kernel lock held - perfect */
10661da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file, poll_table *wait)
10671da177e4SLinus Torvalds {
1068cbf55001SEliezer Tamir 	unsigned int busy_flag = 0;
10691da177e4SLinus Torvalds 	struct socket *sock;
10701da177e4SLinus Torvalds 
10711da177e4SLinus Torvalds 	/*
10721da177e4SLinus Torvalds 	 *      We can't return errors to poll, so it's either yes or no.
10731da177e4SLinus Torvalds 	 */
1074b69aee04SEric Dumazet 	sock = file->private_data;
10752d48d67fSEliezer Tamir 
1076cbf55001SEliezer Tamir 	if (sk_can_busy_loop(sock->sk)) {
10772d48d67fSEliezer Tamir 		/* this socket can poll_ll so tell the system call */
1078cbf55001SEliezer Tamir 		busy_flag = POLL_BUSY_LOOP;
10792d48d67fSEliezer Tamir 
10802d48d67fSEliezer Tamir 		/* once, only if requested by syscall */
1081cbf55001SEliezer Tamir 		if (wait && (wait->_key & POLL_BUSY_LOOP))
1082cbf55001SEliezer Tamir 			sk_busy_loop(sock->sk, 1);
10832d48d67fSEliezer Tamir 	}
10842d48d67fSEliezer Tamir 
1085cbf55001SEliezer Tamir 	return busy_flag | sock->ops->poll(file, sock, wait);
10861da177e4SLinus Torvalds }
10871da177e4SLinus Torvalds 
10881da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma)
10891da177e4SLinus Torvalds {
1090b69aee04SEric Dumazet 	struct socket *sock = file->private_data;
10911da177e4SLinus Torvalds 
10921da177e4SLinus Torvalds 	return sock->ops->mmap(file, sock, vma);
10931da177e4SLinus Torvalds }
10941da177e4SLinus Torvalds 
109520380731SArnaldo Carvalho de Melo static int sock_close(struct inode *inode, struct file *filp)
10961da177e4SLinus Torvalds {
10971da177e4SLinus Torvalds 	sock_release(SOCKET_I(inode));
10981da177e4SLinus Torvalds 	return 0;
10991da177e4SLinus Torvalds }
11001da177e4SLinus Torvalds 
11011da177e4SLinus Torvalds /*
11021da177e4SLinus Torvalds  *	Update the socket async list
11031da177e4SLinus Torvalds  *
11041da177e4SLinus Torvalds  *	Fasync_list locking strategy.
11051da177e4SLinus Torvalds  *
11061da177e4SLinus Torvalds  *	1. fasync_list is modified only under process context socket lock
11071da177e4SLinus Torvalds  *	   i.e. under semaphore.
11081da177e4SLinus Torvalds  *	2. fasync_list is used under read_lock(&sk->sk_callback_lock)
1109989a2979SEric Dumazet  *	   or under socket lock
11101da177e4SLinus Torvalds  */
11111da177e4SLinus Torvalds 
11121da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on)
11131da177e4SLinus Torvalds {
1114989a2979SEric Dumazet 	struct socket *sock = filp->private_data;
1115989a2979SEric Dumazet 	struct sock *sk = sock->sk;
1116eaefd110SEric Dumazet 	struct socket_wq *wq;
11171da177e4SLinus Torvalds 
1118989a2979SEric Dumazet 	if (sk == NULL)
11191da177e4SLinus Torvalds 		return -EINVAL;
11201da177e4SLinus Torvalds 
11211da177e4SLinus Torvalds 	lock_sock(sk);
11221e1d04e6SHannes Frederic Sowa 	wq = rcu_dereference_protected(sock->wq, lockdep_sock_is_held(sk));
1123eaefd110SEric Dumazet 	fasync_helper(fd, filp, on, &wq->fasync_list);
11241da177e4SLinus Torvalds 
1125eaefd110SEric Dumazet 	if (!wq->fasync_list)
1126bcdce719SEric Dumazet 		sock_reset_flag(sk, SOCK_FASYNC);
1127989a2979SEric Dumazet 	else
1128989a2979SEric Dumazet 		sock_set_flag(sk, SOCK_FASYNC);
11291da177e4SLinus Torvalds 
1130989a2979SEric Dumazet 	release_sock(sk);
11311da177e4SLinus Torvalds 	return 0;
11321da177e4SLinus Torvalds }
11331da177e4SLinus Torvalds 
1134ceb5d58bSEric Dumazet /* This function may be called only under rcu_lock */
11351da177e4SLinus Torvalds 
1136ceb5d58bSEric Dumazet int sock_wake_async(struct socket_wq *wq, int how, int band)
11371da177e4SLinus Torvalds {
1138ceb5d58bSEric Dumazet 	if (!wq || !wq->fasync_list)
1139ceb5d58bSEric Dumazet 		return -1;
114043815482SEric Dumazet 
114189bddce5SStephen Hemminger 	switch (how) {
11428d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_WAITD:
1143ceb5d58bSEric Dumazet 		if (test_bit(SOCKWQ_ASYNC_WAITDATA, &wq->flags))
11441da177e4SLinus Torvalds 			break;
11451da177e4SLinus Torvalds 		goto call_kill;
11468d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_SPACE:
1147ceb5d58bSEric Dumazet 		if (!test_and_clear_bit(SOCKWQ_ASYNC_NOSPACE, &wq->flags))
11481da177e4SLinus Torvalds 			break;
11491da177e4SLinus Torvalds 		/* fall through */
11508d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_IO:
11511da177e4SLinus Torvalds call_kill:
115243815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGIO, band);
11531da177e4SLinus Torvalds 		break;
11548d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_URG:
115543815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGURG, band);
11561da177e4SLinus Torvalds 	}
1157ceb5d58bSEric Dumazet 
11581da177e4SLinus Torvalds 	return 0;
11591da177e4SLinus Torvalds }
1160c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_wake_async);
11611da177e4SLinus Torvalds 
1162721db93aSPavel Emelyanov int __sock_create(struct net *net, int family, int type, int protocol,
116389bddce5SStephen Hemminger 			 struct socket **res, int kern)
11641da177e4SLinus Torvalds {
11651da177e4SLinus Torvalds 	int err;
11661da177e4SLinus Torvalds 	struct socket *sock;
116755737fdaSStephen Hemminger 	const struct net_proto_family *pf;
11681da177e4SLinus Torvalds 
11691da177e4SLinus Torvalds 	/*
11701da177e4SLinus Torvalds 	 *      Check protocol is in range
11711da177e4SLinus Torvalds 	 */
11721da177e4SLinus Torvalds 	if (family < 0 || family >= NPROTO)
11731da177e4SLinus Torvalds 		return -EAFNOSUPPORT;
11741da177e4SLinus Torvalds 	if (type < 0 || type >= SOCK_MAX)
11751da177e4SLinus Torvalds 		return -EINVAL;
11761da177e4SLinus Torvalds 
11771da177e4SLinus Torvalds 	/* Compatibility.
11781da177e4SLinus Torvalds 
11791da177e4SLinus Torvalds 	   This uglymoron is moved from INET layer to here to avoid
11801da177e4SLinus Torvalds 	   deadlock in module load.
11811da177e4SLinus Torvalds 	 */
11821da177e4SLinus Torvalds 	if (family == PF_INET && type == SOCK_PACKET) {
1183f3c98690Sliping.zhang 		pr_info_once("%s uses obsolete (PF_INET,SOCK_PACKET)\n",
118489bddce5SStephen Hemminger 			     current->comm);
11851da177e4SLinus Torvalds 		family = PF_PACKET;
11861da177e4SLinus Torvalds 	}
11871da177e4SLinus Torvalds 
11881da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, kern);
11891da177e4SLinus Torvalds 	if (err)
11901da177e4SLinus Torvalds 		return err;
11911da177e4SLinus Torvalds 
119255737fdaSStephen Hemminger 	/*
119355737fdaSStephen Hemminger 	 *	Allocate the socket and allow the family to set things up. if
119455737fdaSStephen Hemminger 	 *	the protocol is 0, the family is instructed to select an appropriate
119555737fdaSStephen Hemminger 	 *	default.
119655737fdaSStephen Hemminger 	 */
119755737fdaSStephen Hemminger 	sock = sock_alloc();
119855737fdaSStephen Hemminger 	if (!sock) {
1199e87cc472SJoe Perches 		net_warn_ratelimited("socket: no more sockets\n");
120055737fdaSStephen Hemminger 		return -ENFILE;	/* Not exactly a match, but its the
120155737fdaSStephen Hemminger 				   closest posix thing */
120255737fdaSStephen Hemminger 	}
120355737fdaSStephen Hemminger 
120455737fdaSStephen Hemminger 	sock->type = type;
120555737fdaSStephen Hemminger 
120695a5afcaSJohannes Berg #ifdef CONFIG_MODULES
12071da177e4SLinus Torvalds 	/* Attempt to load a protocol module if the find failed.
12081da177e4SLinus Torvalds 	 *
12091da177e4SLinus Torvalds 	 * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
12101da177e4SLinus Torvalds 	 * requested real, full-featured networking support upon configuration.
12111da177e4SLinus Torvalds 	 * Otherwise module support will break!
12121da177e4SLinus Torvalds 	 */
1213190683a9SEric Dumazet 	if (rcu_access_pointer(net_families[family]) == NULL)
12141da177e4SLinus Torvalds 		request_module("net-pf-%d", family);
12151da177e4SLinus Torvalds #endif
12161da177e4SLinus Torvalds 
121755737fdaSStephen Hemminger 	rcu_read_lock();
121855737fdaSStephen Hemminger 	pf = rcu_dereference(net_families[family]);
12191da177e4SLinus Torvalds 	err = -EAFNOSUPPORT;
122055737fdaSStephen Hemminger 	if (!pf)
122155737fdaSStephen Hemminger 		goto out_release;
12221da177e4SLinus Torvalds 
12231da177e4SLinus Torvalds 	/*
12241da177e4SLinus Torvalds 	 * We will call the ->create function, that possibly is in a loadable
12251da177e4SLinus Torvalds 	 * module, so we have to bump that loadable module refcnt first.
12261da177e4SLinus Torvalds 	 */
122755737fdaSStephen Hemminger 	if (!try_module_get(pf->owner))
12281da177e4SLinus Torvalds 		goto out_release;
12291da177e4SLinus Torvalds 
123055737fdaSStephen Hemminger 	/* Now protected by module ref count */
123155737fdaSStephen Hemminger 	rcu_read_unlock();
123255737fdaSStephen Hemminger 
12333f378b68SEric Paris 	err = pf->create(net, sock, protocol, kern);
123455737fdaSStephen Hemminger 	if (err < 0)
12351da177e4SLinus Torvalds 		goto out_module_put;
1236a79af59eSFrank Filz 
12371da177e4SLinus Torvalds 	/*
12381da177e4SLinus Torvalds 	 * Now to bump the refcnt of the [loadable] module that owns this
12391da177e4SLinus Torvalds 	 * socket at sock_release time we decrement its refcnt.
12401da177e4SLinus Torvalds 	 */
124155737fdaSStephen Hemminger 	if (!try_module_get(sock->ops->owner))
124255737fdaSStephen Hemminger 		goto out_module_busy;
124355737fdaSStephen Hemminger 
12441da177e4SLinus Torvalds 	/*
12451da177e4SLinus Torvalds 	 * Now that we're done with the ->create function, the [loadable]
12461da177e4SLinus Torvalds 	 * module can have its refcnt decremented
12471da177e4SLinus Torvalds 	 */
124855737fdaSStephen Hemminger 	module_put(pf->owner);
12497420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, kern);
12507420ed23SVenkat Yekkirala 	if (err)
12513b185525SHerbert Xu 		goto out_sock_release;
125255737fdaSStephen Hemminger 	*res = sock;
12531da177e4SLinus Torvalds 
125455737fdaSStephen Hemminger 	return 0;
125555737fdaSStephen Hemminger 
125655737fdaSStephen Hemminger out_module_busy:
125755737fdaSStephen Hemminger 	err = -EAFNOSUPPORT;
12581da177e4SLinus Torvalds out_module_put:
125955737fdaSStephen Hemminger 	sock->ops = NULL;
126055737fdaSStephen Hemminger 	module_put(pf->owner);
126155737fdaSStephen Hemminger out_sock_release:
12621da177e4SLinus Torvalds 	sock_release(sock);
126355737fdaSStephen Hemminger 	return err;
126455737fdaSStephen Hemminger 
126555737fdaSStephen Hemminger out_release:
126655737fdaSStephen Hemminger 	rcu_read_unlock();
126755737fdaSStephen Hemminger 	goto out_sock_release;
12681da177e4SLinus Torvalds }
1269721db93aSPavel Emelyanov EXPORT_SYMBOL(__sock_create);
12701da177e4SLinus Torvalds 
12711da177e4SLinus Torvalds int sock_create(int family, int type, int protocol, struct socket **res)
12721da177e4SLinus Torvalds {
12731b8d7ae4SEric W. Biederman 	return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
12741da177e4SLinus Torvalds }
1275c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create);
12761da177e4SLinus Torvalds 
1277eeb1bd5cSEric W. Biederman int sock_create_kern(struct net *net, int family, int type, int protocol, struct socket **res)
12781da177e4SLinus Torvalds {
1279eeb1bd5cSEric W. Biederman 	return __sock_create(net, family, type, protocol, res, 1);
12801da177e4SLinus Torvalds }
1281c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_kern);
12821da177e4SLinus Torvalds 
12833e0fa65fSHeiko Carstens SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
12841da177e4SLinus Torvalds {
12851da177e4SLinus Torvalds 	int retval;
12861da177e4SLinus Torvalds 	struct socket *sock;
1287a677a039SUlrich Drepper 	int flags;
1288a677a039SUlrich Drepper 
1289e38b36f3SUlrich Drepper 	/* Check the SOCK_* constants for consistency.  */
1290e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
1291e38b36f3SUlrich Drepper 	BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
1292e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);
1293e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);
1294e38b36f3SUlrich Drepper 
1295a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
129677d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1297a677a039SUlrich Drepper 		return -EINVAL;
1298a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
12991da177e4SLinus Torvalds 
1300aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1301aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1302aaca0bdcSUlrich Drepper 
13031da177e4SLinus Torvalds 	retval = sock_create(family, type, protocol, &sock);
13041da177e4SLinus Torvalds 	if (retval < 0)
13051da177e4SLinus Torvalds 		goto out;
13061da177e4SLinus Torvalds 
130777d27200SUlrich Drepper 	retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
13081da177e4SLinus Torvalds 	if (retval < 0)
13091da177e4SLinus Torvalds 		goto out_release;
13101da177e4SLinus Torvalds 
13111da177e4SLinus Torvalds out:
13121da177e4SLinus Torvalds 	/* It may be already another descriptor 8) Not kernel problem. */
13131da177e4SLinus Torvalds 	return retval;
13141da177e4SLinus Torvalds 
13151da177e4SLinus Torvalds out_release:
13161da177e4SLinus Torvalds 	sock_release(sock);
13171da177e4SLinus Torvalds 	return retval;
13181da177e4SLinus Torvalds }
13191da177e4SLinus Torvalds 
13201da177e4SLinus Torvalds /*
13211da177e4SLinus Torvalds  *	Create a pair of connected sockets.
13221da177e4SLinus Torvalds  */
13231da177e4SLinus Torvalds 
13243e0fa65fSHeiko Carstens SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
13253e0fa65fSHeiko Carstens 		int __user *, usockvec)
13261da177e4SLinus Torvalds {
13271da177e4SLinus Torvalds 	struct socket *sock1, *sock2;
13281da177e4SLinus Torvalds 	int fd1, fd2, err;
1329db349509SAl Viro 	struct file *newfile1, *newfile2;
1330a677a039SUlrich Drepper 	int flags;
1331a677a039SUlrich Drepper 
1332a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
133377d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1334a677a039SUlrich Drepper 		return -EINVAL;
1335a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
13361da177e4SLinus Torvalds 
1337aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1338aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1339aaca0bdcSUlrich Drepper 
13401da177e4SLinus Torvalds 	/*
13411da177e4SLinus Torvalds 	 * Obtain the first socket and check if the underlying protocol
13421da177e4SLinus Torvalds 	 * supports the socketpair call.
13431da177e4SLinus Torvalds 	 */
13441da177e4SLinus Torvalds 
13451da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock1);
13461da177e4SLinus Torvalds 	if (err < 0)
13471da177e4SLinus Torvalds 		goto out;
13481da177e4SLinus Torvalds 
13491da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock2);
13501da177e4SLinus Torvalds 	if (err < 0)
13511da177e4SLinus Torvalds 		goto out_release_1;
13521da177e4SLinus Torvalds 
13531da177e4SLinus Torvalds 	err = sock1->ops->socketpair(sock1, sock2);
13541da177e4SLinus Torvalds 	if (err < 0)
13551da177e4SLinus Torvalds 		goto out_release_both;
13561da177e4SLinus Torvalds 
135728407630SAl Viro 	fd1 = get_unused_fd_flags(flags);
1358bf3c23d1SDavid S. Miller 	if (unlikely(fd1 < 0)) {
1359bf3c23d1SDavid S. Miller 		err = fd1;
13601da177e4SLinus Torvalds 		goto out_release_both;
1361bf3c23d1SDavid S. Miller 	}
1362d73aa286SYann Droneaud 
136328407630SAl Viro 	fd2 = get_unused_fd_flags(flags);
1364198de4d7SAl Viro 	if (unlikely(fd2 < 0)) {
1365198de4d7SAl Viro 		err = fd2;
1366d73aa286SYann Droneaud 		goto out_put_unused_1;
136728407630SAl Viro 	}
136828407630SAl Viro 
1369aab174f0SLinus Torvalds 	newfile1 = sock_alloc_file(sock1, flags, NULL);
1370b5ffe634SViresh Kumar 	if (IS_ERR(newfile1)) {
137128407630SAl Viro 		err = PTR_ERR(newfile1);
1372d73aa286SYann Droneaud 		goto out_put_unused_both;
137328407630SAl Viro 	}
137428407630SAl Viro 
1375aab174f0SLinus Torvalds 	newfile2 = sock_alloc_file(sock2, flags, NULL);
137628407630SAl Viro 	if (IS_ERR(newfile2)) {
137728407630SAl Viro 		err = PTR_ERR(newfile2);
1378d73aa286SYann Droneaud 		goto out_fput_1;
1379db349509SAl Viro 	}
1380db349509SAl Viro 
1381d73aa286SYann Droneaud 	err = put_user(fd1, &usockvec[0]);
1382d73aa286SYann Droneaud 	if (err)
1383d73aa286SYann Droneaud 		goto out_fput_both;
1384d73aa286SYann Droneaud 
1385d73aa286SYann Droneaud 	err = put_user(fd2, &usockvec[1]);
1386d73aa286SYann Droneaud 	if (err)
1387d73aa286SYann Droneaud 		goto out_fput_both;
1388d73aa286SYann Droneaud 
1389157cf649SAl Viro 	audit_fd_pair(fd1, fd2);
1390d73aa286SYann Droneaud 
1391db349509SAl Viro 	fd_install(fd1, newfile1);
1392db349509SAl Viro 	fd_install(fd2, newfile2);
13931da177e4SLinus Torvalds 	/* fd1 and fd2 may be already another descriptors.
13941da177e4SLinus Torvalds 	 * Not kernel problem.
13951da177e4SLinus Torvalds 	 */
13961da177e4SLinus Torvalds 
13971da177e4SLinus Torvalds 	return 0;
13981da177e4SLinus Torvalds 
1399d73aa286SYann Droneaud out_fput_both:
1400d73aa286SYann Droneaud 	fput(newfile2);
1401d73aa286SYann Droneaud 	fput(newfile1);
1402d73aa286SYann Droneaud 	put_unused_fd(fd2);
1403d73aa286SYann Droneaud 	put_unused_fd(fd1);
1404d73aa286SYann Droneaud 	goto out;
14051da177e4SLinus Torvalds 
1406d73aa286SYann Droneaud out_fput_1:
1407d73aa286SYann Droneaud 	fput(newfile1);
1408d73aa286SYann Droneaud 	put_unused_fd(fd2);
1409d73aa286SYann Droneaud 	put_unused_fd(fd1);
1410d73aa286SYann Droneaud 	sock_release(sock2);
1411d73aa286SYann Droneaud 	goto out;
1412d73aa286SYann Droneaud 
1413d73aa286SYann Droneaud out_put_unused_both:
1414d73aa286SYann Droneaud 	put_unused_fd(fd2);
1415d73aa286SYann Droneaud out_put_unused_1:
1416d73aa286SYann Droneaud 	put_unused_fd(fd1);
14171da177e4SLinus Torvalds out_release_both:
14181da177e4SLinus Torvalds 	sock_release(sock2);
14191da177e4SLinus Torvalds out_release_1:
14201da177e4SLinus Torvalds 	sock_release(sock1);
14211da177e4SLinus Torvalds out:
14221da177e4SLinus Torvalds 	return err;
14231da177e4SLinus Torvalds }
14241da177e4SLinus Torvalds 
14251da177e4SLinus Torvalds /*
14261da177e4SLinus Torvalds  *	Bind a name to a socket. Nothing much to do here since it's
14271da177e4SLinus Torvalds  *	the protocol's responsibility to handle the local address.
14281da177e4SLinus Torvalds  *
14291da177e4SLinus Torvalds  *	We move the socket address to kernel space before we call
14301da177e4SLinus Torvalds  *	the protocol layer (having also checked the address is ok).
14311da177e4SLinus Torvalds  */
14321da177e4SLinus Torvalds 
143320f37034SHeiko Carstens SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
14341da177e4SLinus Torvalds {
14351da177e4SLinus Torvalds 	struct socket *sock;
1436230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
14376cb153caSBenjamin LaHaise 	int err, fput_needed;
14381da177e4SLinus Torvalds 
143989bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
144089bddce5SStephen Hemminger 	if (sock) {
144143db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(umyaddr, addrlen, &address);
144289bddce5SStephen Hemminger 		if (err >= 0) {
144389bddce5SStephen Hemminger 			err = security_socket_bind(sock,
1444230b1839SYOSHIFUJI Hideaki 						   (struct sockaddr *)&address,
144589bddce5SStephen Hemminger 						   addrlen);
14466cb153caSBenjamin LaHaise 			if (!err)
14476cb153caSBenjamin LaHaise 				err = sock->ops->bind(sock,
144889bddce5SStephen Hemminger 						      (struct sockaddr *)
1449230b1839SYOSHIFUJI Hideaki 						      &address, addrlen);
14501da177e4SLinus Torvalds 		}
14516cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
14521da177e4SLinus Torvalds 	}
14531da177e4SLinus Torvalds 	return err;
14541da177e4SLinus Torvalds }
14551da177e4SLinus Torvalds 
14561da177e4SLinus Torvalds /*
14571da177e4SLinus Torvalds  *	Perform a listen. Basically, we allow the protocol to do anything
14581da177e4SLinus Torvalds  *	necessary for a listen, and if that works, we mark the socket as
14591da177e4SLinus Torvalds  *	ready for listening.
14601da177e4SLinus Torvalds  */
14611da177e4SLinus Torvalds 
14623e0fa65fSHeiko Carstens SYSCALL_DEFINE2(listen, int, fd, int, backlog)
14631da177e4SLinus Torvalds {
14641da177e4SLinus Torvalds 	struct socket *sock;
14656cb153caSBenjamin LaHaise 	int err, fput_needed;
1466b8e1f9b5SPavel Emelyanov 	int somaxconn;
14671da177e4SLinus Torvalds 
146889bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
146989bddce5SStephen Hemminger 	if (sock) {
14708efa6e93SPavel Emelyanov 		somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
147195c96174SEric Dumazet 		if ((unsigned int)backlog > somaxconn)
1472b8e1f9b5SPavel Emelyanov 			backlog = somaxconn;
14731da177e4SLinus Torvalds 
14741da177e4SLinus Torvalds 		err = security_socket_listen(sock, backlog);
14756cb153caSBenjamin LaHaise 		if (!err)
14761da177e4SLinus Torvalds 			err = sock->ops->listen(sock, backlog);
14776cb153caSBenjamin LaHaise 
14786cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
14791da177e4SLinus Torvalds 	}
14801da177e4SLinus Torvalds 	return err;
14811da177e4SLinus Torvalds }
14821da177e4SLinus Torvalds 
14831da177e4SLinus Torvalds /*
14841da177e4SLinus Torvalds  *	For accept, we attempt to create a new socket, set up the link
14851da177e4SLinus Torvalds  *	with the client, wake up the client, then return the new
14861da177e4SLinus Torvalds  *	connected fd. We collect the address of the connector in kernel
14871da177e4SLinus Torvalds  *	space and move it to user at the very end. This is unclean because
14881da177e4SLinus Torvalds  *	we open the socket then return an error.
14891da177e4SLinus Torvalds  *
14901da177e4SLinus Torvalds  *	1003.1g adds the ability to recvmsg() to query connection pending
14911da177e4SLinus Torvalds  *	status to recvmsg. We need to add that support in a way thats
14921da177e4SLinus Torvalds  *	clean when we restucture accept also.
14931da177e4SLinus Torvalds  */
14941da177e4SLinus Torvalds 
149520f37034SHeiko Carstens SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
149620f37034SHeiko Carstens 		int __user *, upeer_addrlen, int, flags)
14971da177e4SLinus Torvalds {
14981da177e4SLinus Torvalds 	struct socket *sock, *newsock;
149939d8c1b6SDavid S. Miller 	struct file *newfile;
15006cb153caSBenjamin LaHaise 	int err, len, newfd, fput_needed;
1501230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
15021da177e4SLinus Torvalds 
150377d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1504aaca0bdcSUlrich Drepper 		return -EINVAL;
1505aaca0bdcSUlrich Drepper 
1506aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1507aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1508aaca0bdcSUlrich Drepper 
15096cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
15101da177e4SLinus Torvalds 	if (!sock)
15111da177e4SLinus Torvalds 		goto out;
15121da177e4SLinus Torvalds 
15131da177e4SLinus Torvalds 	err = -ENFILE;
1514c6d409cfSEric Dumazet 	newsock = sock_alloc();
1515c6d409cfSEric Dumazet 	if (!newsock)
15161da177e4SLinus Torvalds 		goto out_put;
15171da177e4SLinus Torvalds 
15181da177e4SLinus Torvalds 	newsock->type = sock->type;
15191da177e4SLinus Torvalds 	newsock->ops = sock->ops;
15201da177e4SLinus Torvalds 
15211da177e4SLinus Torvalds 	/*
15221da177e4SLinus Torvalds 	 * We don't need try_module_get here, as the listening socket (sock)
15231da177e4SLinus Torvalds 	 * has the protocol module (sock->ops->owner) held.
15241da177e4SLinus Torvalds 	 */
15251da177e4SLinus Torvalds 	__module_get(newsock->ops->owner);
15261da177e4SLinus Torvalds 
152728407630SAl Viro 	newfd = get_unused_fd_flags(flags);
152839d8c1b6SDavid S. Miller 	if (unlikely(newfd < 0)) {
152939d8c1b6SDavid S. Miller 		err = newfd;
15309a1875e6SDavid S. Miller 		sock_release(newsock);
15319a1875e6SDavid S. Miller 		goto out_put;
153239d8c1b6SDavid S. Miller 	}
1533aab174f0SLinus Torvalds 	newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name);
1534b5ffe634SViresh Kumar 	if (IS_ERR(newfile)) {
153528407630SAl Viro 		err = PTR_ERR(newfile);
153628407630SAl Viro 		put_unused_fd(newfd);
153728407630SAl Viro 		sock_release(newsock);
153828407630SAl Viro 		goto out_put;
153928407630SAl Viro 	}
154039d8c1b6SDavid S. Miller 
1541a79af59eSFrank Filz 	err = security_socket_accept(sock, newsock);
1542a79af59eSFrank Filz 	if (err)
154339d8c1b6SDavid S. Miller 		goto out_fd;
1544a79af59eSFrank Filz 
1545cdfbabfbSDavid Howells 	err = sock->ops->accept(sock, newsock, sock->file->f_flags, false);
15461da177e4SLinus Torvalds 	if (err < 0)
154739d8c1b6SDavid S. Miller 		goto out_fd;
15481da177e4SLinus Torvalds 
15491da177e4SLinus Torvalds 	if (upeer_sockaddr) {
1550230b1839SYOSHIFUJI Hideaki 		if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
155189bddce5SStephen Hemminger 					  &len, 2) < 0) {
15521da177e4SLinus Torvalds 			err = -ECONNABORTED;
155339d8c1b6SDavid S. Miller 			goto out_fd;
15541da177e4SLinus Torvalds 		}
155543db362dSMaciej Żenczykowski 		err = move_addr_to_user(&address,
1556230b1839SYOSHIFUJI Hideaki 					len, upeer_sockaddr, upeer_addrlen);
15571da177e4SLinus Torvalds 		if (err < 0)
155839d8c1b6SDavid S. Miller 			goto out_fd;
15591da177e4SLinus Torvalds 	}
15601da177e4SLinus Torvalds 
15611da177e4SLinus Torvalds 	/* File flags are not inherited via accept() unlike another OSes. */
15621da177e4SLinus Torvalds 
156339d8c1b6SDavid S. Miller 	fd_install(newfd, newfile);
156439d8c1b6SDavid S. Miller 	err = newfd;
15651da177e4SLinus Torvalds 
15661da177e4SLinus Torvalds out_put:
15676cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
15681da177e4SLinus Torvalds out:
15691da177e4SLinus Torvalds 	return err;
157039d8c1b6SDavid S. Miller out_fd:
15719606a216SDavid S. Miller 	fput(newfile);
157239d8c1b6SDavid S. Miller 	put_unused_fd(newfd);
15731da177e4SLinus Torvalds 	goto out_put;
15741da177e4SLinus Torvalds }
15751da177e4SLinus Torvalds 
157620f37034SHeiko Carstens SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,
157720f37034SHeiko Carstens 		int __user *, upeer_addrlen)
1578aaca0bdcSUlrich Drepper {
1579de11defeSUlrich Drepper 	return sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0);
1580aaca0bdcSUlrich Drepper }
1581aaca0bdcSUlrich Drepper 
15821da177e4SLinus Torvalds /*
15831da177e4SLinus Torvalds  *	Attempt to connect to a socket with the server address.  The address
15841da177e4SLinus Torvalds  *	is in user space so we verify it is OK and move it to kernel space.
15851da177e4SLinus Torvalds  *
15861da177e4SLinus Torvalds  *	For 1003.1g we need to add clean support for a bind to AF_UNSPEC to
15871da177e4SLinus Torvalds  *	break bindings
15881da177e4SLinus Torvalds  *
15891da177e4SLinus Torvalds  *	NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and
15901da177e4SLinus Torvalds  *	other SEQPACKET protocols that take time to connect() as it doesn't
15911da177e4SLinus Torvalds  *	include the -EINPROGRESS status for such sockets.
15921da177e4SLinus Torvalds  */
15931da177e4SLinus Torvalds 
159420f37034SHeiko Carstens SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
159520f37034SHeiko Carstens 		int, addrlen)
15961da177e4SLinus Torvalds {
15971da177e4SLinus Torvalds 	struct socket *sock;
1598230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
15996cb153caSBenjamin LaHaise 	int err, fput_needed;
16001da177e4SLinus Torvalds 
16016cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
16021da177e4SLinus Torvalds 	if (!sock)
16031da177e4SLinus Torvalds 		goto out;
160443db362dSMaciej Żenczykowski 	err = move_addr_to_kernel(uservaddr, addrlen, &address);
16051da177e4SLinus Torvalds 	if (err < 0)
16061da177e4SLinus Torvalds 		goto out_put;
16071da177e4SLinus Torvalds 
160889bddce5SStephen Hemminger 	err =
1609230b1839SYOSHIFUJI Hideaki 	    security_socket_connect(sock, (struct sockaddr *)&address, addrlen);
16101da177e4SLinus Torvalds 	if (err)
16111da177e4SLinus Torvalds 		goto out_put;
16121da177e4SLinus Torvalds 
1613230b1839SYOSHIFUJI Hideaki 	err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,
16141da177e4SLinus Torvalds 				 sock->file->f_flags);
16151da177e4SLinus Torvalds out_put:
16166cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
16171da177e4SLinus Torvalds out:
16181da177e4SLinus Torvalds 	return err;
16191da177e4SLinus Torvalds }
16201da177e4SLinus Torvalds 
16211da177e4SLinus Torvalds /*
16221da177e4SLinus Torvalds  *	Get the local address ('name') of a socket object. Move the obtained
16231da177e4SLinus Torvalds  *	name to user space.
16241da177e4SLinus Torvalds  */
16251da177e4SLinus Torvalds 
162620f37034SHeiko Carstens SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
162720f37034SHeiko Carstens 		int __user *, usockaddr_len)
16281da177e4SLinus Torvalds {
16291da177e4SLinus Torvalds 	struct socket *sock;
1630230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16316cb153caSBenjamin LaHaise 	int len, err, fput_needed;
16321da177e4SLinus Torvalds 
16336cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
16341da177e4SLinus Torvalds 	if (!sock)
16351da177e4SLinus Torvalds 		goto out;
16361da177e4SLinus Torvalds 
16371da177e4SLinus Torvalds 	err = security_socket_getsockname(sock);
16381da177e4SLinus Torvalds 	if (err)
16391da177e4SLinus Torvalds 		goto out_put;
16401da177e4SLinus Torvalds 
1641230b1839SYOSHIFUJI Hideaki 	err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0);
16421da177e4SLinus Torvalds 	if (err)
16431da177e4SLinus Torvalds 		goto out_put;
164443db362dSMaciej Żenczykowski 	err = move_addr_to_user(&address, len, usockaddr, usockaddr_len);
16451da177e4SLinus Torvalds 
16461da177e4SLinus Torvalds out_put:
16476cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
16481da177e4SLinus Torvalds out:
16491da177e4SLinus Torvalds 	return err;
16501da177e4SLinus Torvalds }
16511da177e4SLinus Torvalds 
16521da177e4SLinus Torvalds /*
16531da177e4SLinus Torvalds  *	Get the remote address ('name') of a socket object. Move the obtained
16541da177e4SLinus Torvalds  *	name to user space.
16551da177e4SLinus Torvalds  */
16561da177e4SLinus Torvalds 
165720f37034SHeiko Carstens SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
165820f37034SHeiko Carstens 		int __user *, usockaddr_len)
16591da177e4SLinus Torvalds {
16601da177e4SLinus Torvalds 	struct socket *sock;
1661230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16626cb153caSBenjamin LaHaise 	int len, err, fput_needed;
16631da177e4SLinus Torvalds 
166489bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
166589bddce5SStephen Hemminger 	if (sock != NULL) {
16661da177e4SLinus Torvalds 		err = security_socket_getpeername(sock);
16671da177e4SLinus Torvalds 		if (err) {
16686cb153caSBenjamin LaHaise 			fput_light(sock->file, fput_needed);
16691da177e4SLinus Torvalds 			return err;
16701da177e4SLinus Torvalds 		}
16711da177e4SLinus Torvalds 
167289bddce5SStephen Hemminger 		err =
1673230b1839SYOSHIFUJI Hideaki 		    sock->ops->getname(sock, (struct sockaddr *)&address, &len,
167489bddce5SStephen Hemminger 				       1);
16751da177e4SLinus Torvalds 		if (!err)
167643db362dSMaciej Żenczykowski 			err = move_addr_to_user(&address, len, usockaddr,
167789bddce5SStephen Hemminger 						usockaddr_len);
16786cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
16791da177e4SLinus Torvalds 	}
16801da177e4SLinus Torvalds 	return err;
16811da177e4SLinus Torvalds }
16821da177e4SLinus Torvalds 
16831da177e4SLinus Torvalds /*
16841da177e4SLinus Torvalds  *	Send a datagram to a given address. We move the address into kernel
16851da177e4SLinus Torvalds  *	space and check the user space data area is readable before invoking
16861da177e4SLinus Torvalds  *	the protocol.
16871da177e4SLinus Torvalds  */
16881da177e4SLinus Torvalds 
16893e0fa65fSHeiko Carstens SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
169095c96174SEric Dumazet 		unsigned int, flags, struct sockaddr __user *, addr,
16913e0fa65fSHeiko Carstens 		int, addr_len)
16921da177e4SLinus Torvalds {
16931da177e4SLinus Torvalds 	struct socket *sock;
1694230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16951da177e4SLinus Torvalds 	int err;
16961da177e4SLinus Torvalds 	struct msghdr msg;
16971da177e4SLinus Torvalds 	struct iovec iov;
16986cb153caSBenjamin LaHaise 	int fput_needed;
16991da177e4SLinus Torvalds 
1700602bd0e9SAl Viro 	err = import_single_range(WRITE, buff, len, &iov, &msg.msg_iter);
1701602bd0e9SAl Viro 	if (unlikely(err))
1702602bd0e9SAl Viro 		return err;
1703de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1704de0fa95cSPavel Emelyanov 	if (!sock)
17054387ff75SDavid S. Miller 		goto out;
17066cb153caSBenjamin LaHaise 
17071da177e4SLinus Torvalds 	msg.msg_name = NULL;
17081da177e4SLinus Torvalds 	msg.msg_control = NULL;
17091da177e4SLinus Torvalds 	msg.msg_controllen = 0;
17101da177e4SLinus Torvalds 	msg.msg_namelen = 0;
17116cb153caSBenjamin LaHaise 	if (addr) {
171243db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(addr, addr_len, &address);
17131da177e4SLinus Torvalds 		if (err < 0)
17141da177e4SLinus Torvalds 			goto out_put;
1715230b1839SYOSHIFUJI Hideaki 		msg.msg_name = (struct sockaddr *)&address;
17161da177e4SLinus Torvalds 		msg.msg_namelen = addr_len;
17171da177e4SLinus Torvalds 	}
17181da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
17191da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
17201da177e4SLinus Torvalds 	msg.msg_flags = flags;
1721d8725c86SAl Viro 	err = sock_sendmsg(sock, &msg);
17221da177e4SLinus Torvalds 
17231da177e4SLinus Torvalds out_put:
1724de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
17254387ff75SDavid S. Miller out:
17261da177e4SLinus Torvalds 	return err;
17271da177e4SLinus Torvalds }
17281da177e4SLinus Torvalds 
17291da177e4SLinus Torvalds /*
17301da177e4SLinus Torvalds  *	Send a datagram down a socket.
17311da177e4SLinus Torvalds  */
17321da177e4SLinus Torvalds 
17333e0fa65fSHeiko Carstens SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len,
173495c96174SEric Dumazet 		unsigned int, flags)
17351da177e4SLinus Torvalds {
17361da177e4SLinus Torvalds 	return sys_sendto(fd, buff, len, flags, NULL, 0);
17371da177e4SLinus Torvalds }
17381da177e4SLinus Torvalds 
17391da177e4SLinus Torvalds /*
17401da177e4SLinus Torvalds  *	Receive a frame from the socket and optionally record the address of the
17411da177e4SLinus Torvalds  *	sender. We verify the buffers are writable and if needed move the
17421da177e4SLinus Torvalds  *	sender address from kernel to user space.
17431da177e4SLinus Torvalds  */
17441da177e4SLinus Torvalds 
17453e0fa65fSHeiko Carstens SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
174695c96174SEric Dumazet 		unsigned int, flags, struct sockaddr __user *, addr,
17473e0fa65fSHeiko Carstens 		int __user *, addr_len)
17481da177e4SLinus Torvalds {
17491da177e4SLinus Torvalds 	struct socket *sock;
17501da177e4SLinus Torvalds 	struct iovec iov;
17511da177e4SLinus Torvalds 	struct msghdr msg;
1752230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
17531da177e4SLinus Torvalds 	int err, err2;
17546cb153caSBenjamin LaHaise 	int fput_needed;
17551da177e4SLinus Torvalds 
1756602bd0e9SAl Viro 	err = import_single_range(READ, ubuf, size, &iov, &msg.msg_iter);
1757602bd0e9SAl Viro 	if (unlikely(err))
1758602bd0e9SAl Viro 		return err;
1759de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
17601da177e4SLinus Torvalds 	if (!sock)
1761de0fa95cSPavel Emelyanov 		goto out;
17621da177e4SLinus Torvalds 
17631da177e4SLinus Torvalds 	msg.msg_control = NULL;
17641da177e4SLinus Torvalds 	msg.msg_controllen = 0;
1765f3d33426SHannes Frederic Sowa 	/* Save some cycles and don't copy the address if not needed */
1766f3d33426SHannes Frederic Sowa 	msg.msg_name = addr ? (struct sockaddr *)&address : NULL;
1767f3d33426SHannes Frederic Sowa 	/* We assume all kernel code knows the size of sockaddr_storage */
1768f3d33426SHannes Frederic Sowa 	msg.msg_namelen = 0;
1769130ed5d1Stadeusz.struk@intel.com 	msg.msg_iocb = NULL;
17709f138fa6SAlexander Potapenko 	msg.msg_flags = 0;
17711da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
17721da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
17732da62906SAl Viro 	err = sock_recvmsg(sock, &msg, flags);
17741da177e4SLinus Torvalds 
177589bddce5SStephen Hemminger 	if (err >= 0 && addr != NULL) {
177643db362dSMaciej Żenczykowski 		err2 = move_addr_to_user(&address,
1777230b1839SYOSHIFUJI Hideaki 					 msg.msg_namelen, addr, addr_len);
17781da177e4SLinus Torvalds 		if (err2 < 0)
17791da177e4SLinus Torvalds 			err = err2;
17801da177e4SLinus Torvalds 	}
1781de0fa95cSPavel Emelyanov 
1782de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
17834387ff75SDavid S. Miller out:
17841da177e4SLinus Torvalds 	return err;
17851da177e4SLinus Torvalds }
17861da177e4SLinus Torvalds 
17871da177e4SLinus Torvalds /*
17881da177e4SLinus Torvalds  *	Receive a datagram from a socket.
17891da177e4SLinus Torvalds  */
17901da177e4SLinus Torvalds 
1791b7c0ddf5SJan Glauber SYSCALL_DEFINE4(recv, int, fd, void __user *, ubuf, size_t, size,
1792b7c0ddf5SJan Glauber 		unsigned int, flags)
17931da177e4SLinus Torvalds {
17941da177e4SLinus Torvalds 	return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL);
17951da177e4SLinus Torvalds }
17961da177e4SLinus Torvalds 
17971da177e4SLinus Torvalds /*
17981da177e4SLinus Torvalds  *	Set a socket option. Because we don't know the option lengths we have
17991da177e4SLinus Torvalds  *	to pass the user mode parameter for the protocols to sort out.
18001da177e4SLinus Torvalds  */
18011da177e4SLinus Torvalds 
180220f37034SHeiko Carstens SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
180320f37034SHeiko Carstens 		char __user *, optval, int, optlen)
18041da177e4SLinus Torvalds {
18056cb153caSBenjamin LaHaise 	int err, fput_needed;
18061da177e4SLinus Torvalds 	struct socket *sock;
18071da177e4SLinus Torvalds 
18081da177e4SLinus Torvalds 	if (optlen < 0)
18091da177e4SLinus Torvalds 		return -EINVAL;
18101da177e4SLinus Torvalds 
181189bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
181289bddce5SStephen Hemminger 	if (sock != NULL) {
18131da177e4SLinus Torvalds 		err = security_socket_setsockopt(sock, level, optname);
18146cb153caSBenjamin LaHaise 		if (err)
18156cb153caSBenjamin LaHaise 			goto out_put;
18161da177e4SLinus Torvalds 
18171da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
181889bddce5SStephen Hemminger 			err =
181989bddce5SStephen Hemminger 			    sock_setsockopt(sock, level, optname, optval,
182089bddce5SStephen Hemminger 					    optlen);
18211da177e4SLinus Torvalds 		else
182289bddce5SStephen Hemminger 			err =
182389bddce5SStephen Hemminger 			    sock->ops->setsockopt(sock, level, optname, optval,
182489bddce5SStephen Hemminger 						  optlen);
18256cb153caSBenjamin LaHaise out_put:
18266cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
18271da177e4SLinus Torvalds 	}
18281da177e4SLinus Torvalds 	return err;
18291da177e4SLinus Torvalds }
18301da177e4SLinus Torvalds 
18311da177e4SLinus Torvalds /*
18321da177e4SLinus Torvalds  *	Get a socket option. Because we don't know the option lengths we have
18331da177e4SLinus Torvalds  *	to pass a user mode parameter for the protocols to sort out.
18341da177e4SLinus Torvalds  */
18351da177e4SLinus Torvalds 
183620f37034SHeiko Carstens SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
183720f37034SHeiko Carstens 		char __user *, optval, int __user *, optlen)
18381da177e4SLinus Torvalds {
18396cb153caSBenjamin LaHaise 	int err, fput_needed;
18401da177e4SLinus Torvalds 	struct socket *sock;
18411da177e4SLinus Torvalds 
184289bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
184389bddce5SStephen Hemminger 	if (sock != NULL) {
18446cb153caSBenjamin LaHaise 		err = security_socket_getsockopt(sock, level, optname);
18456cb153caSBenjamin LaHaise 		if (err)
18466cb153caSBenjamin LaHaise 			goto out_put;
18471da177e4SLinus Torvalds 
18481da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
184989bddce5SStephen Hemminger 			err =
185089bddce5SStephen Hemminger 			    sock_getsockopt(sock, level, optname, optval,
185189bddce5SStephen Hemminger 					    optlen);
18521da177e4SLinus Torvalds 		else
185389bddce5SStephen Hemminger 			err =
185489bddce5SStephen Hemminger 			    sock->ops->getsockopt(sock, level, optname, optval,
185589bddce5SStephen Hemminger 						  optlen);
18566cb153caSBenjamin LaHaise out_put:
18576cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
18581da177e4SLinus Torvalds 	}
18591da177e4SLinus Torvalds 	return err;
18601da177e4SLinus Torvalds }
18611da177e4SLinus Torvalds 
18621da177e4SLinus Torvalds /*
18631da177e4SLinus Torvalds  *	Shutdown a socket.
18641da177e4SLinus Torvalds  */
18651da177e4SLinus Torvalds 
1866754fe8d2SHeiko Carstens SYSCALL_DEFINE2(shutdown, int, fd, int, how)
18671da177e4SLinus Torvalds {
18686cb153caSBenjamin LaHaise 	int err, fput_needed;
18691da177e4SLinus Torvalds 	struct socket *sock;
18701da177e4SLinus Torvalds 
187189bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
187289bddce5SStephen Hemminger 	if (sock != NULL) {
18731da177e4SLinus Torvalds 		err = security_socket_shutdown(sock, how);
18746cb153caSBenjamin LaHaise 		if (!err)
18751da177e4SLinus Torvalds 			err = sock->ops->shutdown(sock, how);
18766cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
18771da177e4SLinus Torvalds 	}
18781da177e4SLinus Torvalds 	return err;
18791da177e4SLinus Torvalds }
18801da177e4SLinus Torvalds 
18811da177e4SLinus Torvalds /* A couple of helpful macros for getting the address of the 32/64 bit
18821da177e4SLinus Torvalds  * fields which are the same type (int / unsigned) on our platforms.
18831da177e4SLinus Torvalds  */
18841da177e4SLinus Torvalds #define COMPAT_MSG(msg, member)	((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member)
18851da177e4SLinus Torvalds #define COMPAT_NAMELEN(msg)	COMPAT_MSG(msg, msg_namelen)
18861da177e4SLinus Torvalds #define COMPAT_FLAGS(msg)	COMPAT_MSG(msg, msg_flags)
18871da177e4SLinus Torvalds 
1888c71d8ebeSTetsuo Handa struct used_address {
1889c71d8ebeSTetsuo Handa 	struct sockaddr_storage name;
1890c71d8ebeSTetsuo Handa 	unsigned int name_len;
1891c71d8ebeSTetsuo Handa };
1892c71d8ebeSTetsuo Handa 
1893da184284SAl Viro static int copy_msghdr_from_user(struct msghdr *kmsg,
189408adb7daSAl Viro 				 struct user_msghdr __user *umsg,
189508adb7daSAl Viro 				 struct sockaddr __user **save_addr,
189608adb7daSAl Viro 				 struct iovec **iov)
18971661bf36SDan Carpenter {
189808adb7daSAl Viro 	struct sockaddr __user *uaddr;
189908adb7daSAl Viro 	struct iovec __user *uiov;
1900c0371da6SAl Viro 	size_t nr_segs;
190108adb7daSAl Viro 	ssize_t err;
190208adb7daSAl Viro 
190308adb7daSAl Viro 	if (!access_ok(VERIFY_READ, umsg, sizeof(*umsg)) ||
190408adb7daSAl Viro 	    __get_user(uaddr, &umsg->msg_name) ||
190508adb7daSAl Viro 	    __get_user(kmsg->msg_namelen, &umsg->msg_namelen) ||
190608adb7daSAl Viro 	    __get_user(uiov, &umsg->msg_iov) ||
1907c0371da6SAl Viro 	    __get_user(nr_segs, &umsg->msg_iovlen) ||
190808adb7daSAl Viro 	    __get_user(kmsg->msg_control, &umsg->msg_control) ||
190908adb7daSAl Viro 	    __get_user(kmsg->msg_controllen, &umsg->msg_controllen) ||
191008adb7daSAl Viro 	    __get_user(kmsg->msg_flags, &umsg->msg_flags))
19111661bf36SDan Carpenter 		return -EFAULT;
1912dbb490b9SMatthew Leach 
191308adb7daSAl Viro 	if (!uaddr)
19146a2a2b3aSAni Sinha 		kmsg->msg_namelen = 0;
19156a2a2b3aSAni Sinha 
1916dbb490b9SMatthew Leach 	if (kmsg->msg_namelen < 0)
1917dbb490b9SMatthew Leach 		return -EINVAL;
1918dbb490b9SMatthew Leach 
19191661bf36SDan Carpenter 	if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
1920db31c55aSDan Carpenter 		kmsg->msg_namelen = sizeof(struct sockaddr_storage);
192108adb7daSAl Viro 
192208adb7daSAl Viro 	if (save_addr)
192308adb7daSAl Viro 		*save_addr = uaddr;
192408adb7daSAl Viro 
192508adb7daSAl Viro 	if (uaddr && kmsg->msg_namelen) {
192608adb7daSAl Viro 		if (!save_addr) {
192708adb7daSAl Viro 			err = move_addr_to_kernel(uaddr, kmsg->msg_namelen,
192808adb7daSAl Viro 						  kmsg->msg_name);
192908adb7daSAl Viro 			if (err < 0)
193008adb7daSAl Viro 				return err;
193108adb7daSAl Viro 		}
193208adb7daSAl Viro 	} else {
193308adb7daSAl Viro 		kmsg->msg_name = NULL;
193408adb7daSAl Viro 		kmsg->msg_namelen = 0;
193508adb7daSAl Viro 	}
193608adb7daSAl Viro 
1937c0371da6SAl Viro 	if (nr_segs > UIO_MAXIOV)
193808adb7daSAl Viro 		return -EMSGSIZE;
193908adb7daSAl Viro 
19400345f931Stadeusz.struk@intel.com 	kmsg->msg_iocb = NULL;
19410345f931Stadeusz.struk@intel.com 
1942da184284SAl Viro 	return import_iovec(save_addr ? READ : WRITE, uiov, nr_segs,
1943da184284SAl Viro 			    UIO_FASTIOV, iov, &kmsg->msg_iter);
19441661bf36SDan Carpenter }
19451661bf36SDan Carpenter 
1946666547ffSAl Viro static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
194795c96174SEric Dumazet 			 struct msghdr *msg_sys, unsigned int flags,
194828a94d8fSTom Herbert 			 struct used_address *used_address,
194928a94d8fSTom Herbert 			 unsigned int allowed_msghdr_flags)
19501da177e4SLinus Torvalds {
195189bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
195289bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
1953230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
19541da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
1955b9d717a7SAlex Williamson 	unsigned char ctl[sizeof(struct cmsghdr) + 20]
1956846cc123SAmit Kushwaha 				__aligned(sizeof(__kernel_size_t));
1957b9d717a7SAlex Williamson 	/* 20 is size of ipv6_pktinfo */
19581da177e4SLinus Torvalds 	unsigned char *ctl_buf = ctl;
1959d8725c86SAl Viro 	int ctl_len;
196008adb7daSAl Viro 	ssize_t err;
19611da177e4SLinus Torvalds 
196208adb7daSAl Viro 	msg_sys->msg_name = &address;
19631da177e4SLinus Torvalds 
196408449320SAl Viro 	if (MSG_CMSG_COMPAT & flags)
196508adb7daSAl Viro 		err = get_compat_msghdr(msg_sys, msg_compat, NULL, &iov);
196608449320SAl Viro 	else
196708adb7daSAl Viro 		err = copy_msghdr_from_user(msg_sys, msg, NULL, &iov);
19681da177e4SLinus Torvalds 	if (err < 0)
1969da184284SAl Viro 		return err;
19701da177e4SLinus Torvalds 
19711da177e4SLinus Torvalds 	err = -ENOBUFS;
19721da177e4SLinus Torvalds 
1973228e548eSAnton Blanchard 	if (msg_sys->msg_controllen > INT_MAX)
19741da177e4SLinus Torvalds 		goto out_freeiov;
197528a94d8fSTom Herbert 	flags |= (msg_sys->msg_flags & allowed_msghdr_flags);
1976228e548eSAnton Blanchard 	ctl_len = msg_sys->msg_controllen;
19771da177e4SLinus Torvalds 	if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
197889bddce5SStephen Hemminger 		err =
1979228e548eSAnton Blanchard 		    cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl,
198089bddce5SStephen Hemminger 						     sizeof(ctl));
19811da177e4SLinus Torvalds 		if (err)
19821da177e4SLinus Torvalds 			goto out_freeiov;
1983228e548eSAnton Blanchard 		ctl_buf = msg_sys->msg_control;
1984228e548eSAnton Blanchard 		ctl_len = msg_sys->msg_controllen;
19851da177e4SLinus Torvalds 	} else if (ctl_len) {
1986ac4340fcSDavid S. Miller 		BUILD_BUG_ON(sizeof(struct cmsghdr) !=
1987ac4340fcSDavid S. Miller 			     CMSG_ALIGN(sizeof(struct cmsghdr)));
198889bddce5SStephen Hemminger 		if (ctl_len > sizeof(ctl)) {
19891da177e4SLinus Torvalds 			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
19901da177e4SLinus Torvalds 			if (ctl_buf == NULL)
19911da177e4SLinus Torvalds 				goto out_freeiov;
19921da177e4SLinus Torvalds 		}
19931da177e4SLinus Torvalds 		err = -EFAULT;
19941da177e4SLinus Torvalds 		/*
1995228e548eSAnton Blanchard 		 * Careful! Before this, msg_sys->msg_control contains a user pointer.
19961da177e4SLinus Torvalds 		 * Afterwards, it will be a kernel pointer. Thus the compiler-assisted
19971da177e4SLinus Torvalds 		 * checking falls down on this.
19981da177e4SLinus Torvalds 		 */
1999fb8621bbSNamhyung Kim 		if (copy_from_user(ctl_buf,
2000228e548eSAnton Blanchard 				   (void __user __force *)msg_sys->msg_control,
200189bddce5SStephen Hemminger 				   ctl_len))
20021da177e4SLinus Torvalds 			goto out_freectl;
2003228e548eSAnton Blanchard 		msg_sys->msg_control = ctl_buf;
20041da177e4SLinus Torvalds 	}
2005228e548eSAnton Blanchard 	msg_sys->msg_flags = flags;
20061da177e4SLinus Torvalds 
20071da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
2008228e548eSAnton Blanchard 		msg_sys->msg_flags |= MSG_DONTWAIT;
2009c71d8ebeSTetsuo Handa 	/*
2010c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and current destination address is same as
2011c71d8ebeSTetsuo Handa 	 * previously succeeded address, omit asking LSM's decision.
2012c71d8ebeSTetsuo Handa 	 * used_address->name_len is initialized to UINT_MAX so that the first
2013c71d8ebeSTetsuo Handa 	 * destination address never matches.
2014c71d8ebeSTetsuo Handa 	 */
2015bc909d9dSMathieu Desnoyers 	if (used_address && msg_sys->msg_name &&
2016bc909d9dSMathieu Desnoyers 	    used_address->name_len == msg_sys->msg_namelen &&
2017bc909d9dSMathieu Desnoyers 	    !memcmp(&used_address->name, msg_sys->msg_name,
2018c71d8ebeSTetsuo Handa 		    used_address->name_len)) {
2019d8725c86SAl Viro 		err = sock_sendmsg_nosec(sock, msg_sys);
2020c71d8ebeSTetsuo Handa 		goto out_freectl;
2021c71d8ebeSTetsuo Handa 	}
2022d8725c86SAl Viro 	err = sock_sendmsg(sock, msg_sys);
2023c71d8ebeSTetsuo Handa 	/*
2024c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and sending to current destination address was
2025c71d8ebeSTetsuo Handa 	 * successful, remember it.
2026c71d8ebeSTetsuo Handa 	 */
2027c71d8ebeSTetsuo Handa 	if (used_address && err >= 0) {
2028c71d8ebeSTetsuo Handa 		used_address->name_len = msg_sys->msg_namelen;
2029bc909d9dSMathieu Desnoyers 		if (msg_sys->msg_name)
2030bc909d9dSMathieu Desnoyers 			memcpy(&used_address->name, msg_sys->msg_name,
2031c71d8ebeSTetsuo Handa 			       used_address->name_len);
2032c71d8ebeSTetsuo Handa 	}
20331da177e4SLinus Torvalds 
20341da177e4SLinus Torvalds out_freectl:
20351da177e4SLinus Torvalds 	if (ctl_buf != ctl)
20361da177e4SLinus Torvalds 		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
20371da177e4SLinus Torvalds out_freeiov:
2038a74e9106SEric Dumazet 	kfree(iov);
2039228e548eSAnton Blanchard 	return err;
2040228e548eSAnton Blanchard }
2041228e548eSAnton Blanchard 
2042228e548eSAnton Blanchard /*
2043228e548eSAnton Blanchard  *	BSD sendmsg interface
2044228e548eSAnton Blanchard  */
2045228e548eSAnton Blanchard 
2046666547ffSAl Viro long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned flags)
2047228e548eSAnton Blanchard {
2048228e548eSAnton Blanchard 	int fput_needed, err;
2049228e548eSAnton Blanchard 	struct msghdr msg_sys;
20501be374a0SAndy Lutomirski 	struct socket *sock;
2051228e548eSAnton Blanchard 
20521be374a0SAndy Lutomirski 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2053228e548eSAnton Blanchard 	if (!sock)
2054228e548eSAnton Blanchard 		goto out;
2055228e548eSAnton Blanchard 
205628a94d8fSTom Herbert 	err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL, 0);
2057228e548eSAnton Blanchard 
20586cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
20591da177e4SLinus Torvalds out:
20601da177e4SLinus Torvalds 	return err;
20611da177e4SLinus Torvalds }
20621da177e4SLinus Torvalds 
2063666547ffSAl Viro SYSCALL_DEFINE3(sendmsg, int, fd, struct user_msghdr __user *, msg, unsigned int, flags)
2064a7526eb5SAndy Lutomirski {
2065a7526eb5SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
2066a7526eb5SAndy Lutomirski 		return -EINVAL;
2067a7526eb5SAndy Lutomirski 	return __sys_sendmsg(fd, msg, flags);
2068a7526eb5SAndy Lutomirski }
2069a7526eb5SAndy Lutomirski 
2070228e548eSAnton Blanchard /*
2071228e548eSAnton Blanchard  *	Linux sendmmsg interface
2072228e548eSAnton Blanchard  */
2073228e548eSAnton Blanchard 
2074228e548eSAnton Blanchard int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2075228e548eSAnton Blanchard 		   unsigned int flags)
2076228e548eSAnton Blanchard {
2077228e548eSAnton Blanchard 	int fput_needed, err, datagrams;
2078228e548eSAnton Blanchard 	struct socket *sock;
2079228e548eSAnton Blanchard 	struct mmsghdr __user *entry;
2080228e548eSAnton Blanchard 	struct compat_mmsghdr __user *compat_entry;
2081228e548eSAnton Blanchard 	struct msghdr msg_sys;
2082c71d8ebeSTetsuo Handa 	struct used_address used_address;
2083f092276dSTom Herbert 	unsigned int oflags = flags;
2084228e548eSAnton Blanchard 
208598382f41SAnton Blanchard 	if (vlen > UIO_MAXIOV)
208698382f41SAnton Blanchard 		vlen = UIO_MAXIOV;
2087228e548eSAnton Blanchard 
2088228e548eSAnton Blanchard 	datagrams = 0;
2089228e548eSAnton Blanchard 
2090228e548eSAnton Blanchard 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2091228e548eSAnton Blanchard 	if (!sock)
2092228e548eSAnton Blanchard 		return err;
2093228e548eSAnton Blanchard 
2094c71d8ebeSTetsuo Handa 	used_address.name_len = UINT_MAX;
2095228e548eSAnton Blanchard 	entry = mmsg;
2096228e548eSAnton Blanchard 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2097728ffb86SAnton Blanchard 	err = 0;
2098f092276dSTom Herbert 	flags |= MSG_BATCH;
2099228e548eSAnton Blanchard 
2100228e548eSAnton Blanchard 	while (datagrams < vlen) {
2101f092276dSTom Herbert 		if (datagrams == vlen - 1)
2102f092276dSTom Herbert 			flags = oflags;
2103f092276dSTom Herbert 
2104228e548eSAnton Blanchard 		if (MSG_CMSG_COMPAT & flags) {
2105666547ffSAl Viro 			err = ___sys_sendmsg(sock, (struct user_msghdr __user *)compat_entry,
210628a94d8fSTom Herbert 					     &msg_sys, flags, &used_address, MSG_EOR);
2107228e548eSAnton Blanchard 			if (err < 0)
2108228e548eSAnton Blanchard 				break;
2109228e548eSAnton Blanchard 			err = __put_user(err, &compat_entry->msg_len);
2110228e548eSAnton Blanchard 			++compat_entry;
2111228e548eSAnton Blanchard 		} else {
2112a7526eb5SAndy Lutomirski 			err = ___sys_sendmsg(sock,
2113666547ffSAl Viro 					     (struct user_msghdr __user *)entry,
211428a94d8fSTom Herbert 					     &msg_sys, flags, &used_address, MSG_EOR);
2115228e548eSAnton Blanchard 			if (err < 0)
2116228e548eSAnton Blanchard 				break;
2117228e548eSAnton Blanchard 			err = put_user(err, &entry->msg_len);
2118228e548eSAnton Blanchard 			++entry;
2119228e548eSAnton Blanchard 		}
2120228e548eSAnton Blanchard 
2121228e548eSAnton Blanchard 		if (err)
2122228e548eSAnton Blanchard 			break;
2123228e548eSAnton Blanchard 		++datagrams;
21243023898bSSoheil Hassas Yeganeh 		if (msg_data_left(&msg_sys))
21253023898bSSoheil Hassas Yeganeh 			break;
2126a78cb84cSEric Dumazet 		cond_resched();
2127228e548eSAnton Blanchard 	}
2128228e548eSAnton Blanchard 
2129228e548eSAnton Blanchard 	fput_light(sock->file, fput_needed);
2130228e548eSAnton Blanchard 
2131728ffb86SAnton Blanchard 	/* We only return an error if no datagrams were able to be sent */
2132728ffb86SAnton Blanchard 	if (datagrams != 0)
2133228e548eSAnton Blanchard 		return datagrams;
2134228e548eSAnton Blanchard 
2135228e548eSAnton Blanchard 	return err;
2136228e548eSAnton Blanchard }
2137228e548eSAnton Blanchard 
2138228e548eSAnton Blanchard SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
2139228e548eSAnton Blanchard 		unsigned int, vlen, unsigned int, flags)
2140228e548eSAnton Blanchard {
21411be374a0SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
21421be374a0SAndy Lutomirski 		return -EINVAL;
2143228e548eSAnton Blanchard 	return __sys_sendmmsg(fd, mmsg, vlen, flags);
2144228e548eSAnton Blanchard }
2145228e548eSAnton Blanchard 
2146666547ffSAl Viro static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg,
214795c96174SEric Dumazet 			 struct msghdr *msg_sys, unsigned int flags, int nosec)
21481da177e4SLinus Torvalds {
214989bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
215089bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
21511da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV];
21521da177e4SLinus Torvalds 	struct iovec *iov = iovstack;
21531da177e4SLinus Torvalds 	unsigned long cmsg_ptr;
21542da62906SAl Viro 	int len;
215508adb7daSAl Viro 	ssize_t err;
21561da177e4SLinus Torvalds 
21571da177e4SLinus Torvalds 	/* kernel mode address */
2158230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage addr;
21591da177e4SLinus Torvalds 
21601da177e4SLinus Torvalds 	/* user mode address pointers */
21611da177e4SLinus Torvalds 	struct sockaddr __user *uaddr;
216208adb7daSAl Viro 	int __user *uaddr_len = COMPAT_NAMELEN(msg);
21631da177e4SLinus Torvalds 
216408adb7daSAl Viro 	msg_sys->msg_name = &addr;
21651da177e4SLinus Torvalds 
2166f3d33426SHannes Frederic Sowa 	if (MSG_CMSG_COMPAT & flags)
216708adb7daSAl Viro 		err = get_compat_msghdr(msg_sys, msg_compat, &uaddr, &iov);
2168f3d33426SHannes Frederic Sowa 	else
216908adb7daSAl Viro 		err = copy_msghdr_from_user(msg_sys, msg, &uaddr, &iov);
21701da177e4SLinus Torvalds 	if (err < 0)
2171da184284SAl Viro 		return err;
21721da177e4SLinus Torvalds 
2173a2e27255SArnaldo Carvalho de Melo 	cmsg_ptr = (unsigned long)msg_sys->msg_control;
2174a2e27255SArnaldo Carvalho de Melo 	msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
21751da177e4SLinus Torvalds 
2176f3d33426SHannes Frederic Sowa 	/* We assume all kernel code knows the size of sockaddr_storage */
2177f3d33426SHannes Frederic Sowa 	msg_sys->msg_namelen = 0;
2178f3d33426SHannes Frederic Sowa 
21791da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
21801da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
21812da62906SAl Viro 	err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys, flags);
21821da177e4SLinus Torvalds 	if (err < 0)
21831da177e4SLinus Torvalds 		goto out_freeiov;
21841da177e4SLinus Torvalds 	len = err;
21851da177e4SLinus Torvalds 
21861da177e4SLinus Torvalds 	if (uaddr != NULL) {
218743db362dSMaciej Żenczykowski 		err = move_addr_to_user(&addr,
2188a2e27255SArnaldo Carvalho de Melo 					msg_sys->msg_namelen, uaddr,
218989bddce5SStephen Hemminger 					uaddr_len);
21901da177e4SLinus Torvalds 		if (err < 0)
21911da177e4SLinus Torvalds 			goto out_freeiov;
21921da177e4SLinus Torvalds 	}
2193a2e27255SArnaldo Carvalho de Melo 	err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
219437f7f421SDavid S. Miller 			 COMPAT_FLAGS(msg));
21951da177e4SLinus Torvalds 	if (err)
21961da177e4SLinus Torvalds 		goto out_freeiov;
21971da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags)
2198a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
21991da177e4SLinus Torvalds 				 &msg_compat->msg_controllen);
22001da177e4SLinus Torvalds 	else
2201a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
22021da177e4SLinus Torvalds 				 &msg->msg_controllen);
22031da177e4SLinus Torvalds 	if (err)
22041da177e4SLinus Torvalds 		goto out_freeiov;
22051da177e4SLinus Torvalds 	err = len;
22061da177e4SLinus Torvalds 
22071da177e4SLinus Torvalds out_freeiov:
2208a74e9106SEric Dumazet 	kfree(iov);
2209a2e27255SArnaldo Carvalho de Melo 	return err;
2210a2e27255SArnaldo Carvalho de Melo }
2211a2e27255SArnaldo Carvalho de Melo 
2212a2e27255SArnaldo Carvalho de Melo /*
2213a2e27255SArnaldo Carvalho de Melo  *	BSD recvmsg interface
2214a2e27255SArnaldo Carvalho de Melo  */
2215a2e27255SArnaldo Carvalho de Melo 
2216666547ffSAl Viro long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned flags)
2217a2e27255SArnaldo Carvalho de Melo {
2218a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err;
2219a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
22201be374a0SAndy Lutomirski 	struct socket *sock;
2221a2e27255SArnaldo Carvalho de Melo 
22221be374a0SAndy Lutomirski 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2223a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2224a2e27255SArnaldo Carvalho de Melo 		goto out;
2225a2e27255SArnaldo Carvalho de Melo 
2226a7526eb5SAndy Lutomirski 	err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0);
2227a2e27255SArnaldo Carvalho de Melo 
22286cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
22291da177e4SLinus Torvalds out:
22301da177e4SLinus Torvalds 	return err;
22311da177e4SLinus Torvalds }
22321da177e4SLinus Torvalds 
2233666547ffSAl Viro SYSCALL_DEFINE3(recvmsg, int, fd, struct user_msghdr __user *, msg,
2234a7526eb5SAndy Lutomirski 		unsigned int, flags)
2235a7526eb5SAndy Lutomirski {
2236a7526eb5SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
2237a7526eb5SAndy Lutomirski 		return -EINVAL;
2238a7526eb5SAndy Lutomirski 	return __sys_recvmsg(fd, msg, flags);
2239a7526eb5SAndy Lutomirski }
2240a7526eb5SAndy Lutomirski 
2241a2e27255SArnaldo Carvalho de Melo /*
2242a2e27255SArnaldo Carvalho de Melo  *     Linux recvmmsg interface
2243a2e27255SArnaldo Carvalho de Melo  */
22441da177e4SLinus Torvalds 
2245a2e27255SArnaldo Carvalho de Melo int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2246a2e27255SArnaldo Carvalho de Melo 		   unsigned int flags, struct timespec *timeout)
2247a2e27255SArnaldo Carvalho de Melo {
2248a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err, datagrams;
2249a2e27255SArnaldo Carvalho de Melo 	struct socket *sock;
2250a2e27255SArnaldo Carvalho de Melo 	struct mmsghdr __user *entry;
2251d7256d0eSJean-Mickael Guerin 	struct compat_mmsghdr __user *compat_entry;
2252a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
2253766b9f92SDeepa Dinamani 	struct timespec64 end_time;
2254766b9f92SDeepa Dinamani 	struct timespec64 timeout64;
2255a2e27255SArnaldo Carvalho de Melo 
2256a2e27255SArnaldo Carvalho de Melo 	if (timeout &&
2257a2e27255SArnaldo Carvalho de Melo 	    poll_select_set_timeout(&end_time, timeout->tv_sec,
2258a2e27255SArnaldo Carvalho de Melo 				    timeout->tv_nsec))
2259a2e27255SArnaldo Carvalho de Melo 		return -EINVAL;
2260a2e27255SArnaldo Carvalho de Melo 
2261a2e27255SArnaldo Carvalho de Melo 	datagrams = 0;
2262a2e27255SArnaldo Carvalho de Melo 
2263a2e27255SArnaldo Carvalho de Melo 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2264a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2265a2e27255SArnaldo Carvalho de Melo 		return err;
2266a2e27255SArnaldo Carvalho de Melo 
2267a2e27255SArnaldo Carvalho de Melo 	err = sock_error(sock->sk);
2268e623a9e9SMaxime Jayat 	if (err) {
2269e623a9e9SMaxime Jayat 		datagrams = err;
2270a2e27255SArnaldo Carvalho de Melo 		goto out_put;
2271e623a9e9SMaxime Jayat 	}
2272a2e27255SArnaldo Carvalho de Melo 
2273a2e27255SArnaldo Carvalho de Melo 	entry = mmsg;
2274d7256d0eSJean-Mickael Guerin 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2275a2e27255SArnaldo Carvalho de Melo 
2276a2e27255SArnaldo Carvalho de Melo 	while (datagrams < vlen) {
2277a2e27255SArnaldo Carvalho de Melo 		/*
2278a2e27255SArnaldo Carvalho de Melo 		 * No need to ask LSM for more than the first datagram.
2279a2e27255SArnaldo Carvalho de Melo 		 */
2280d7256d0eSJean-Mickael Guerin 		if (MSG_CMSG_COMPAT & flags) {
2281666547ffSAl Viro 			err = ___sys_recvmsg(sock, (struct user_msghdr __user *)compat_entry,
2282b9eb8b87SAnton Blanchard 					     &msg_sys, flags & ~MSG_WAITFORONE,
2283b9eb8b87SAnton Blanchard 					     datagrams);
2284d7256d0eSJean-Mickael Guerin 			if (err < 0)
2285d7256d0eSJean-Mickael Guerin 				break;
2286d7256d0eSJean-Mickael Guerin 			err = __put_user(err, &compat_entry->msg_len);
2287d7256d0eSJean-Mickael Guerin 			++compat_entry;
2288d7256d0eSJean-Mickael Guerin 		} else {
2289a7526eb5SAndy Lutomirski 			err = ___sys_recvmsg(sock,
2290666547ffSAl Viro 					     (struct user_msghdr __user *)entry,
2291b9eb8b87SAnton Blanchard 					     &msg_sys, flags & ~MSG_WAITFORONE,
2292b9eb8b87SAnton Blanchard 					     datagrams);
2293a2e27255SArnaldo Carvalho de Melo 			if (err < 0)
2294a2e27255SArnaldo Carvalho de Melo 				break;
2295a2e27255SArnaldo Carvalho de Melo 			err = put_user(err, &entry->msg_len);
2296d7256d0eSJean-Mickael Guerin 			++entry;
2297d7256d0eSJean-Mickael Guerin 		}
2298d7256d0eSJean-Mickael Guerin 
2299a2e27255SArnaldo Carvalho de Melo 		if (err)
2300a2e27255SArnaldo Carvalho de Melo 			break;
2301a2e27255SArnaldo Carvalho de Melo 		++datagrams;
2302a2e27255SArnaldo Carvalho de Melo 
230371c5c159SBrandon L Black 		/* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
230471c5c159SBrandon L Black 		if (flags & MSG_WAITFORONE)
230571c5c159SBrandon L Black 			flags |= MSG_DONTWAIT;
230671c5c159SBrandon L Black 
2307a2e27255SArnaldo Carvalho de Melo 		if (timeout) {
2308766b9f92SDeepa Dinamani 			ktime_get_ts64(&timeout64);
2309766b9f92SDeepa Dinamani 			*timeout = timespec64_to_timespec(
2310766b9f92SDeepa Dinamani 					timespec64_sub(end_time, timeout64));
2311a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_sec < 0) {
2312a2e27255SArnaldo Carvalho de Melo 				timeout->tv_sec = timeout->tv_nsec = 0;
2313a2e27255SArnaldo Carvalho de Melo 				break;
2314a2e27255SArnaldo Carvalho de Melo 			}
2315a2e27255SArnaldo Carvalho de Melo 
2316a2e27255SArnaldo Carvalho de Melo 			/* Timeout, return less than vlen datagrams */
2317a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_nsec == 0 && timeout->tv_sec == 0)
2318a2e27255SArnaldo Carvalho de Melo 				break;
2319a2e27255SArnaldo Carvalho de Melo 		}
2320a2e27255SArnaldo Carvalho de Melo 
2321a2e27255SArnaldo Carvalho de Melo 		/* Out of band data, return right away */
2322a2e27255SArnaldo Carvalho de Melo 		if (msg_sys.msg_flags & MSG_OOB)
2323a2e27255SArnaldo Carvalho de Melo 			break;
2324a78cb84cSEric Dumazet 		cond_resched();
2325a2e27255SArnaldo Carvalho de Melo 	}
2326a2e27255SArnaldo Carvalho de Melo 
2327a2e27255SArnaldo Carvalho de Melo 	if (err == 0)
232834b88a68SArnaldo Carvalho de Melo 		goto out_put;
2329a2e27255SArnaldo Carvalho de Melo 
233034b88a68SArnaldo Carvalho de Melo 	if (datagrams == 0) {
233134b88a68SArnaldo Carvalho de Melo 		datagrams = err;
233234b88a68SArnaldo Carvalho de Melo 		goto out_put;
233334b88a68SArnaldo Carvalho de Melo 	}
233434b88a68SArnaldo Carvalho de Melo 
2335a2e27255SArnaldo Carvalho de Melo 	/*
2336a2e27255SArnaldo Carvalho de Melo 	 * We may return less entries than requested (vlen) if the
2337a2e27255SArnaldo Carvalho de Melo 	 * sock is non block and there aren't enough datagrams...
2338a2e27255SArnaldo Carvalho de Melo 	 */
2339a2e27255SArnaldo Carvalho de Melo 	if (err != -EAGAIN) {
2340a2e27255SArnaldo Carvalho de Melo 		/*
2341a2e27255SArnaldo Carvalho de Melo 		 * ... or  if recvmsg returns an error after we
2342a2e27255SArnaldo Carvalho de Melo 		 * received some datagrams, where we record the
2343a2e27255SArnaldo Carvalho de Melo 		 * error to return on the next call or if the
2344a2e27255SArnaldo Carvalho de Melo 		 * app asks about it using getsockopt(SO_ERROR).
2345a2e27255SArnaldo Carvalho de Melo 		 */
2346a2e27255SArnaldo Carvalho de Melo 		sock->sk->sk_err = -err;
2347a2e27255SArnaldo Carvalho de Melo 	}
234834b88a68SArnaldo Carvalho de Melo out_put:
234934b88a68SArnaldo Carvalho de Melo 	fput_light(sock->file, fput_needed);
2350a2e27255SArnaldo Carvalho de Melo 
2351a2e27255SArnaldo Carvalho de Melo 	return datagrams;
2352a2e27255SArnaldo Carvalho de Melo }
2353a2e27255SArnaldo Carvalho de Melo 
2354a2e27255SArnaldo Carvalho de Melo SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
2355a2e27255SArnaldo Carvalho de Melo 		unsigned int, vlen, unsigned int, flags,
2356a2e27255SArnaldo Carvalho de Melo 		struct timespec __user *, timeout)
2357a2e27255SArnaldo Carvalho de Melo {
2358a2e27255SArnaldo Carvalho de Melo 	int datagrams;
2359a2e27255SArnaldo Carvalho de Melo 	struct timespec timeout_sys;
2360a2e27255SArnaldo Carvalho de Melo 
23611be374a0SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
23621be374a0SAndy Lutomirski 		return -EINVAL;
23631be374a0SAndy Lutomirski 
2364a2e27255SArnaldo Carvalho de Melo 	if (!timeout)
2365a2e27255SArnaldo Carvalho de Melo 		return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL);
2366a2e27255SArnaldo Carvalho de Melo 
2367a2e27255SArnaldo Carvalho de Melo 	if (copy_from_user(&timeout_sys, timeout, sizeof(timeout_sys)))
2368a2e27255SArnaldo Carvalho de Melo 		return -EFAULT;
2369a2e27255SArnaldo Carvalho de Melo 
2370a2e27255SArnaldo Carvalho de Melo 	datagrams = __sys_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys);
2371a2e27255SArnaldo Carvalho de Melo 
2372a2e27255SArnaldo Carvalho de Melo 	if (datagrams > 0 &&
2373a2e27255SArnaldo Carvalho de Melo 	    copy_to_user(timeout, &timeout_sys, sizeof(timeout_sys)))
2374a2e27255SArnaldo Carvalho de Melo 		datagrams = -EFAULT;
2375a2e27255SArnaldo Carvalho de Melo 
2376a2e27255SArnaldo Carvalho de Melo 	return datagrams;
2377a2e27255SArnaldo Carvalho de Melo }
2378a2e27255SArnaldo Carvalho de Melo 
2379a2e27255SArnaldo Carvalho de Melo #ifdef __ARCH_WANT_SYS_SOCKETCALL
23801da177e4SLinus Torvalds /* Argument list sizes for sys_socketcall */
23811da177e4SLinus Torvalds #define AL(x) ((x) * sizeof(unsigned long))
2382228e548eSAnton Blanchard static const unsigned char nargs[21] = {
238389bddce5SStephen Hemminger 	AL(0), AL(3), AL(3), AL(3), AL(2), AL(3),
23841da177e4SLinus Torvalds 	AL(3), AL(3), AL(4), AL(4), AL(4), AL(6),
2385aaca0bdcSUlrich Drepper 	AL(6), AL(2), AL(5), AL(5), AL(3), AL(3),
2386228e548eSAnton Blanchard 	AL(4), AL(5), AL(4)
238789bddce5SStephen Hemminger };
238889bddce5SStephen Hemminger 
23891da177e4SLinus Torvalds #undef AL
23901da177e4SLinus Torvalds 
23911da177e4SLinus Torvalds /*
23921da177e4SLinus Torvalds  *	System call vectors.
23931da177e4SLinus Torvalds  *
23941da177e4SLinus Torvalds  *	Argument checking cleaned up. Saved 20% in size.
23951da177e4SLinus Torvalds  *  This function doesn't need to set the kernel lock because
23961da177e4SLinus Torvalds  *  it is set by the callees.
23971da177e4SLinus Torvalds  */
23981da177e4SLinus Torvalds 
23993e0fa65fSHeiko Carstens SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
24001da177e4SLinus Torvalds {
24012950fa9dSChen Gang 	unsigned long a[AUDITSC_ARGS];
24021da177e4SLinus Torvalds 	unsigned long a0, a1;
24031da177e4SLinus Torvalds 	int err;
240447379052SArjan van de Ven 	unsigned int len;
24051da177e4SLinus Torvalds 
2406228e548eSAnton Blanchard 	if (call < 1 || call > SYS_SENDMMSG)
24071da177e4SLinus Torvalds 		return -EINVAL;
24081da177e4SLinus Torvalds 
240947379052SArjan van de Ven 	len = nargs[call];
241047379052SArjan van de Ven 	if (len > sizeof(a))
241147379052SArjan van de Ven 		return -EINVAL;
241247379052SArjan van de Ven 
24131da177e4SLinus Torvalds 	/* copy_from_user should be SMP safe. */
241447379052SArjan van de Ven 	if (copy_from_user(a, args, len))
24151da177e4SLinus Torvalds 		return -EFAULT;
24161da177e4SLinus Torvalds 
24172950fa9dSChen Gang 	err = audit_socketcall(nargs[call] / sizeof(unsigned long), a);
24182950fa9dSChen Gang 	if (err)
24192950fa9dSChen Gang 		return err;
24203ec3b2fbSDavid Woodhouse 
24211da177e4SLinus Torvalds 	a0 = a[0];
24221da177e4SLinus Torvalds 	a1 = a[1];
24231da177e4SLinus Torvalds 
242489bddce5SStephen Hemminger 	switch (call) {
24251da177e4SLinus Torvalds 	case SYS_SOCKET:
24261da177e4SLinus Torvalds 		err = sys_socket(a0, a1, a[2]);
24271da177e4SLinus Torvalds 		break;
24281da177e4SLinus Torvalds 	case SYS_BIND:
24291da177e4SLinus Torvalds 		err = sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
24301da177e4SLinus Torvalds 		break;
24311da177e4SLinus Torvalds 	case SYS_CONNECT:
24321da177e4SLinus Torvalds 		err = sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
24331da177e4SLinus Torvalds 		break;
24341da177e4SLinus Torvalds 	case SYS_LISTEN:
24351da177e4SLinus Torvalds 		err = sys_listen(a0, a1);
24361da177e4SLinus Torvalds 		break;
24371da177e4SLinus Torvalds 	case SYS_ACCEPT:
2438de11defeSUlrich Drepper 		err = sys_accept4(a0, (struct sockaddr __user *)a1,
2439aaca0bdcSUlrich Drepper 				  (int __user *)a[2], 0);
24401da177e4SLinus Torvalds 		break;
24411da177e4SLinus Torvalds 	case SYS_GETSOCKNAME:
244289bddce5SStephen Hemminger 		err =
244389bddce5SStephen Hemminger 		    sys_getsockname(a0, (struct sockaddr __user *)a1,
244489bddce5SStephen Hemminger 				    (int __user *)a[2]);
24451da177e4SLinus Torvalds 		break;
24461da177e4SLinus Torvalds 	case SYS_GETPEERNAME:
244789bddce5SStephen Hemminger 		err =
244889bddce5SStephen Hemminger 		    sys_getpeername(a0, (struct sockaddr __user *)a1,
244989bddce5SStephen Hemminger 				    (int __user *)a[2]);
24501da177e4SLinus Torvalds 		break;
24511da177e4SLinus Torvalds 	case SYS_SOCKETPAIR:
24521da177e4SLinus Torvalds 		err = sys_socketpair(a0, a1, a[2], (int __user *)a[3]);
24531da177e4SLinus Torvalds 		break;
24541da177e4SLinus Torvalds 	case SYS_SEND:
24551da177e4SLinus Torvalds 		err = sys_send(a0, (void __user *)a1, a[2], a[3]);
24561da177e4SLinus Torvalds 		break;
24571da177e4SLinus Torvalds 	case SYS_SENDTO:
24581da177e4SLinus Torvalds 		err = sys_sendto(a0, (void __user *)a1, a[2], a[3],
24591da177e4SLinus Torvalds 				 (struct sockaddr __user *)a[4], a[5]);
24601da177e4SLinus Torvalds 		break;
24611da177e4SLinus Torvalds 	case SYS_RECV:
24621da177e4SLinus Torvalds 		err = sys_recv(a0, (void __user *)a1, a[2], a[3]);
24631da177e4SLinus Torvalds 		break;
24641da177e4SLinus Torvalds 	case SYS_RECVFROM:
24651da177e4SLinus Torvalds 		err = sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
246689bddce5SStephen Hemminger 				   (struct sockaddr __user *)a[4],
246789bddce5SStephen Hemminger 				   (int __user *)a[5]);
24681da177e4SLinus Torvalds 		break;
24691da177e4SLinus Torvalds 	case SYS_SHUTDOWN:
24701da177e4SLinus Torvalds 		err = sys_shutdown(a0, a1);
24711da177e4SLinus Torvalds 		break;
24721da177e4SLinus Torvalds 	case SYS_SETSOCKOPT:
24731da177e4SLinus Torvalds 		err = sys_setsockopt(a0, a1, a[2], (char __user *)a[3], a[4]);
24741da177e4SLinus Torvalds 		break;
24751da177e4SLinus Torvalds 	case SYS_GETSOCKOPT:
247689bddce5SStephen Hemminger 		err =
247789bddce5SStephen Hemminger 		    sys_getsockopt(a0, a1, a[2], (char __user *)a[3],
247889bddce5SStephen Hemminger 				   (int __user *)a[4]);
24791da177e4SLinus Torvalds 		break;
24801da177e4SLinus Torvalds 	case SYS_SENDMSG:
2481666547ffSAl Viro 		err = sys_sendmsg(a0, (struct user_msghdr __user *)a1, a[2]);
24821da177e4SLinus Torvalds 		break;
2483228e548eSAnton Blanchard 	case SYS_SENDMMSG:
2484228e548eSAnton Blanchard 		err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]);
2485228e548eSAnton Blanchard 		break;
24861da177e4SLinus Torvalds 	case SYS_RECVMSG:
2487666547ffSAl Viro 		err = sys_recvmsg(a0, (struct user_msghdr __user *)a1, a[2]);
24881da177e4SLinus Torvalds 		break;
2489a2e27255SArnaldo Carvalho de Melo 	case SYS_RECVMMSG:
2490a2e27255SArnaldo Carvalho de Melo 		err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3],
2491a2e27255SArnaldo Carvalho de Melo 				   (struct timespec __user *)a[4]);
2492a2e27255SArnaldo Carvalho de Melo 		break;
2493de11defeSUlrich Drepper 	case SYS_ACCEPT4:
2494de11defeSUlrich Drepper 		err = sys_accept4(a0, (struct sockaddr __user *)a1,
2495de11defeSUlrich Drepper 				  (int __user *)a[2], a[3]);
2496aaca0bdcSUlrich Drepper 		break;
24971da177e4SLinus Torvalds 	default:
24981da177e4SLinus Torvalds 		err = -EINVAL;
24991da177e4SLinus Torvalds 		break;
25001da177e4SLinus Torvalds 	}
25011da177e4SLinus Torvalds 	return err;
25021da177e4SLinus Torvalds }
25031da177e4SLinus Torvalds 
25041da177e4SLinus Torvalds #endif				/* __ARCH_WANT_SYS_SOCKETCALL */
25051da177e4SLinus Torvalds 
250655737fdaSStephen Hemminger /**
250755737fdaSStephen Hemminger  *	sock_register - add a socket protocol handler
250855737fdaSStephen Hemminger  *	@ops: description of protocol
250955737fdaSStephen Hemminger  *
25101da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
25111da177e4SLinus Torvalds  *	advertise its address family, and have it linked into the
2512e793c0f7SMasanari Iida  *	socket interface. The value ops->family corresponds to the
251355737fdaSStephen Hemminger  *	socket system call protocol family.
25141da177e4SLinus Torvalds  */
2515f0fd27d4SStephen Hemminger int sock_register(const struct net_proto_family *ops)
25161da177e4SLinus Torvalds {
25171da177e4SLinus Torvalds 	int err;
25181da177e4SLinus Torvalds 
25191da177e4SLinus Torvalds 	if (ops->family >= NPROTO) {
25203410f22eSYang Yingliang 		pr_crit("protocol %d >= NPROTO(%d)\n", ops->family, NPROTO);
25211da177e4SLinus Torvalds 		return -ENOBUFS;
25221da177e4SLinus Torvalds 	}
252355737fdaSStephen Hemminger 
252455737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2525190683a9SEric Dumazet 	if (rcu_dereference_protected(net_families[ops->family],
2526190683a9SEric Dumazet 				      lockdep_is_held(&net_family_lock)))
25271da177e4SLinus Torvalds 		err = -EEXIST;
252855737fdaSStephen Hemminger 	else {
2529cf778b00SEric Dumazet 		rcu_assign_pointer(net_families[ops->family], ops);
25301da177e4SLinus Torvalds 		err = 0;
25311da177e4SLinus Torvalds 	}
253255737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
253355737fdaSStephen Hemminger 
25343410f22eSYang Yingliang 	pr_info("NET: Registered protocol family %d\n", ops->family);
25351da177e4SLinus Torvalds 	return err;
25361da177e4SLinus Torvalds }
2537c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_register);
25381da177e4SLinus Torvalds 
253955737fdaSStephen Hemminger /**
254055737fdaSStephen Hemminger  *	sock_unregister - remove a protocol handler
254155737fdaSStephen Hemminger  *	@family: protocol family to remove
254255737fdaSStephen Hemminger  *
25431da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
25441da177e4SLinus Torvalds  *	remove its address family, and have it unlinked from the
254555737fdaSStephen Hemminger  *	new socket creation.
254655737fdaSStephen Hemminger  *
254755737fdaSStephen Hemminger  *	If protocol handler is a module, then it can use module reference
254855737fdaSStephen Hemminger  *	counts to protect against new references. If protocol handler is not
254955737fdaSStephen Hemminger  *	a module then it needs to provide its own protection in
255055737fdaSStephen Hemminger  *	the ops->create routine.
25511da177e4SLinus Torvalds  */
2552f0fd27d4SStephen Hemminger void sock_unregister(int family)
25531da177e4SLinus Torvalds {
2554f0fd27d4SStephen Hemminger 	BUG_ON(family < 0 || family >= NPROTO);
25551da177e4SLinus Torvalds 
255655737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2557a9b3cd7fSStephen Hemminger 	RCU_INIT_POINTER(net_families[family], NULL);
255855737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
255955737fdaSStephen Hemminger 
256055737fdaSStephen Hemminger 	synchronize_rcu();
256155737fdaSStephen Hemminger 
25623410f22eSYang Yingliang 	pr_info("NET: Unregistered protocol family %d\n", family);
25631da177e4SLinus Torvalds }
2564c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_unregister);
25651da177e4SLinus Torvalds 
256677d76ea3SAndi Kleen static int __init sock_init(void)
25671da177e4SLinus Torvalds {
2568b3e19d92SNick Piggin 	int err;
25692ca794e5SEric W. Biederman 	/*
25702ca794e5SEric W. Biederman 	 *      Initialize the network sysctl infrastructure.
25712ca794e5SEric W. Biederman 	 */
25722ca794e5SEric W. Biederman 	err = net_sysctl_init();
25732ca794e5SEric W. Biederman 	if (err)
25742ca794e5SEric W. Biederman 		goto out;
2575b3e19d92SNick Piggin 
25761da177e4SLinus Torvalds 	/*
25771da177e4SLinus Torvalds 	 *      Initialize skbuff SLAB cache
25781da177e4SLinus Torvalds 	 */
25791da177e4SLinus Torvalds 	skb_init();
25801da177e4SLinus Torvalds 
25811da177e4SLinus Torvalds 	/*
25821da177e4SLinus Torvalds 	 *      Initialize the protocols module.
25831da177e4SLinus Torvalds 	 */
25841da177e4SLinus Torvalds 
25851da177e4SLinus Torvalds 	init_inodecache();
2586b3e19d92SNick Piggin 
2587b3e19d92SNick Piggin 	err = register_filesystem(&sock_fs_type);
2588b3e19d92SNick Piggin 	if (err)
2589b3e19d92SNick Piggin 		goto out_fs;
25901da177e4SLinus Torvalds 	sock_mnt = kern_mount(&sock_fs_type);
2591b3e19d92SNick Piggin 	if (IS_ERR(sock_mnt)) {
2592b3e19d92SNick Piggin 		err = PTR_ERR(sock_mnt);
2593b3e19d92SNick Piggin 		goto out_mount;
2594b3e19d92SNick Piggin 	}
259577d76ea3SAndi Kleen 
259677d76ea3SAndi Kleen 	/* The real protocol initialization is performed in later initcalls.
25971da177e4SLinus Torvalds 	 */
25981da177e4SLinus Torvalds 
25991da177e4SLinus Torvalds #ifdef CONFIG_NETFILTER
26006d11cfdbSPablo Neira Ayuso 	err = netfilter_init();
26016d11cfdbSPablo Neira Ayuso 	if (err)
26026d11cfdbSPablo Neira Ayuso 		goto out;
26031da177e4SLinus Torvalds #endif
2604cbeb321aSDavid S. Miller 
2605408eccceSDaniel Borkmann 	ptp_classifier_init();
2606c1f19b51SRichard Cochran 
2607b3e19d92SNick Piggin out:
2608b3e19d92SNick Piggin 	return err;
2609b3e19d92SNick Piggin 
2610b3e19d92SNick Piggin out_mount:
2611b3e19d92SNick Piggin 	unregister_filesystem(&sock_fs_type);
2612b3e19d92SNick Piggin out_fs:
2613b3e19d92SNick Piggin 	goto out;
26141da177e4SLinus Torvalds }
26151da177e4SLinus Torvalds 
261677d76ea3SAndi Kleen core_initcall(sock_init);	/* early initcall */
261777d76ea3SAndi Kleen 
26181da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS
26191da177e4SLinus Torvalds void socket_seq_show(struct seq_file *seq)
26201da177e4SLinus Torvalds {
26211da177e4SLinus Torvalds 	int cpu;
26221da177e4SLinus Torvalds 	int counter = 0;
26231da177e4SLinus Torvalds 
26246f912042SKAMEZAWA Hiroyuki 	for_each_possible_cpu(cpu)
26251da177e4SLinus Torvalds 	    counter += per_cpu(sockets_in_use, cpu);
26261da177e4SLinus Torvalds 
26271da177e4SLinus Torvalds 	/* It can be negative, by the way. 8) */
26281da177e4SLinus Torvalds 	if (counter < 0)
26291da177e4SLinus Torvalds 		counter = 0;
26301da177e4SLinus Torvalds 
26311da177e4SLinus Torvalds 	seq_printf(seq, "sockets: used %d\n", counter);
26321da177e4SLinus Torvalds }
26331da177e4SLinus Torvalds #endif				/* CONFIG_PROC_FS */
26341da177e4SLinus Torvalds 
263589bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
26366b96018bSArnd Bergmann static int do_siocgstamp(struct net *net, struct socket *sock,
2637644595f8SH. Peter Anvin 			 unsigned int cmd, void __user *up)
26387a229387SArnd Bergmann {
26397a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
26407a229387SArnd Bergmann 	struct timeval ktv;
26417a229387SArnd Bergmann 	int err;
26427a229387SArnd Bergmann 
26437a229387SArnd Bergmann 	set_fs(KERNEL_DS);
26446b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv);
26457a229387SArnd Bergmann 	set_fs(old_fs);
2646644595f8SH. Peter Anvin 	if (!err)
2647ed6fe9d6SMikulas Patocka 		err = compat_put_timeval(&ktv, up);
2648644595f8SH. Peter Anvin 
26497a229387SArnd Bergmann 	return err;
26507a229387SArnd Bergmann }
26517a229387SArnd Bergmann 
26526b96018bSArnd Bergmann static int do_siocgstampns(struct net *net, struct socket *sock,
2653644595f8SH. Peter Anvin 			   unsigned int cmd, void __user *up)
26547a229387SArnd Bergmann {
26557a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
26567a229387SArnd Bergmann 	struct timespec kts;
26577a229387SArnd Bergmann 	int err;
26587a229387SArnd Bergmann 
26597a229387SArnd Bergmann 	set_fs(KERNEL_DS);
26606b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts);
26617a229387SArnd Bergmann 	set_fs(old_fs);
2662644595f8SH. Peter Anvin 	if (!err)
2663ed6fe9d6SMikulas Patocka 		err = compat_put_timespec(&kts, up);
2664644595f8SH. Peter Anvin 
26657a229387SArnd Bergmann 	return err;
26667a229387SArnd Bergmann }
26677a229387SArnd Bergmann 
26686b96018bSArnd Bergmann static int dev_ifname32(struct net *net, struct compat_ifreq __user *uifr32)
26697a229387SArnd Bergmann {
26707a229387SArnd Bergmann 	struct ifreq __user *uifr;
26717a229387SArnd Bergmann 	int err;
26727a229387SArnd Bergmann 
26737a229387SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(struct ifreq));
26746b96018bSArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
26757a229387SArnd Bergmann 		return -EFAULT;
26767a229387SArnd Bergmann 
26776b96018bSArnd Bergmann 	err = dev_ioctl(net, SIOCGIFNAME, uifr);
26787a229387SArnd Bergmann 	if (err)
26797a229387SArnd Bergmann 		return err;
26807a229387SArnd Bergmann 
26816b96018bSArnd Bergmann 	if (copy_in_user(uifr32, uifr, sizeof(struct compat_ifreq)))
26827a229387SArnd Bergmann 		return -EFAULT;
26837a229387SArnd Bergmann 
26847a229387SArnd Bergmann 	return 0;
26857a229387SArnd Bergmann }
26867a229387SArnd Bergmann 
26876b96018bSArnd Bergmann static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32)
26887a229387SArnd Bergmann {
26896b96018bSArnd Bergmann 	struct compat_ifconf ifc32;
26907a229387SArnd Bergmann 	struct ifconf ifc;
26917a229387SArnd Bergmann 	struct ifconf __user *uifc;
26926b96018bSArnd Bergmann 	struct compat_ifreq __user *ifr32;
26937a229387SArnd Bergmann 	struct ifreq __user *ifr;
26947a229387SArnd Bergmann 	unsigned int i, j;
26957a229387SArnd Bergmann 	int err;
26967a229387SArnd Bergmann 
26976b96018bSArnd Bergmann 	if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf)))
26987a229387SArnd Bergmann 		return -EFAULT;
26997a229387SArnd Bergmann 
270043da5f2eSMathias Krause 	memset(&ifc, 0, sizeof(ifc));
27017a229387SArnd Bergmann 	if (ifc32.ifcbuf == 0) {
27027a229387SArnd Bergmann 		ifc32.ifc_len = 0;
27037a229387SArnd Bergmann 		ifc.ifc_len = 0;
27047a229387SArnd Bergmann 		ifc.ifc_req = NULL;
27057a229387SArnd Bergmann 		uifc = compat_alloc_user_space(sizeof(struct ifconf));
27067a229387SArnd Bergmann 	} else {
27076b96018bSArnd Bergmann 		size_t len = ((ifc32.ifc_len / sizeof(struct compat_ifreq)) + 1) *
27087a229387SArnd Bergmann 			sizeof(struct ifreq);
27097a229387SArnd Bergmann 		uifc = compat_alloc_user_space(sizeof(struct ifconf) + len);
27107a229387SArnd Bergmann 		ifc.ifc_len = len;
27117a229387SArnd Bergmann 		ifr = ifc.ifc_req = (void __user *)(uifc + 1);
27127a229387SArnd Bergmann 		ifr32 = compat_ptr(ifc32.ifcbuf);
27136b96018bSArnd Bergmann 		for (i = 0; i < ifc32.ifc_len; i += sizeof(struct compat_ifreq)) {
27146b96018bSArnd Bergmann 			if (copy_in_user(ifr, ifr32, sizeof(struct compat_ifreq)))
27157a229387SArnd Bergmann 				return -EFAULT;
27167a229387SArnd Bergmann 			ifr++;
27177a229387SArnd Bergmann 			ifr32++;
27187a229387SArnd Bergmann 		}
27197a229387SArnd Bergmann 	}
27207a229387SArnd Bergmann 	if (copy_to_user(uifc, &ifc, sizeof(struct ifconf)))
27217a229387SArnd Bergmann 		return -EFAULT;
27227a229387SArnd Bergmann 
27236b96018bSArnd Bergmann 	err = dev_ioctl(net, SIOCGIFCONF, uifc);
27247a229387SArnd Bergmann 	if (err)
27257a229387SArnd Bergmann 		return err;
27267a229387SArnd Bergmann 
27277a229387SArnd Bergmann 	if (copy_from_user(&ifc, uifc, sizeof(struct ifconf)))
27287a229387SArnd Bergmann 		return -EFAULT;
27297a229387SArnd Bergmann 
27307a229387SArnd Bergmann 	ifr = ifc.ifc_req;
27317a229387SArnd Bergmann 	ifr32 = compat_ptr(ifc32.ifcbuf);
27327a229387SArnd Bergmann 	for (i = 0, j = 0;
27336b96018bSArnd Bergmann 	     i + sizeof(struct compat_ifreq) <= ifc32.ifc_len && j < ifc.ifc_len;
27346b96018bSArnd Bergmann 	     i += sizeof(struct compat_ifreq), j += sizeof(struct ifreq)) {
27356b96018bSArnd Bergmann 		if (copy_in_user(ifr32, ifr, sizeof(struct compat_ifreq)))
27367a229387SArnd Bergmann 			return -EFAULT;
27377a229387SArnd Bergmann 		ifr32++;
27387a229387SArnd Bergmann 		ifr++;
27397a229387SArnd Bergmann 	}
27407a229387SArnd Bergmann 
27417a229387SArnd Bergmann 	if (ifc32.ifcbuf == 0) {
27427a229387SArnd Bergmann 		/* Translate from 64-bit structure multiple to
27437a229387SArnd Bergmann 		 * a 32-bit one.
27447a229387SArnd Bergmann 		 */
27457a229387SArnd Bergmann 		i = ifc.ifc_len;
27466b96018bSArnd Bergmann 		i = ((i / sizeof(struct ifreq)) * sizeof(struct compat_ifreq));
27477a229387SArnd Bergmann 		ifc32.ifc_len = i;
27487a229387SArnd Bergmann 	} else {
27497a229387SArnd Bergmann 		ifc32.ifc_len = i;
27507a229387SArnd Bergmann 	}
27516b96018bSArnd Bergmann 	if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf)))
27527a229387SArnd Bergmann 		return -EFAULT;
27537a229387SArnd Bergmann 
27547a229387SArnd Bergmann 	return 0;
27557a229387SArnd Bergmann }
27567a229387SArnd Bergmann 
27576b96018bSArnd Bergmann static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
27587a229387SArnd Bergmann {
27593a7da39dSBen Hutchings 	struct compat_ethtool_rxnfc __user *compat_rxnfc;
27603a7da39dSBen Hutchings 	bool convert_in = false, convert_out = false;
27613a7da39dSBen Hutchings 	size_t buf_size = ALIGN(sizeof(struct ifreq), 8);
27623a7da39dSBen Hutchings 	struct ethtool_rxnfc __user *rxnfc;
27637a229387SArnd Bergmann 	struct ifreq __user *ifr;
27643a7da39dSBen Hutchings 	u32 rule_cnt = 0, actual_rule_cnt;
27653a7da39dSBen Hutchings 	u32 ethcmd;
27667a229387SArnd Bergmann 	u32 data;
27673a7da39dSBen Hutchings 	int ret;
27687a229387SArnd Bergmann 
27697a229387SArnd Bergmann 	if (get_user(data, &ifr32->ifr_ifru.ifru_data))
27707a229387SArnd Bergmann 		return -EFAULT;
27717a229387SArnd Bergmann 
27723a7da39dSBen Hutchings 	compat_rxnfc = compat_ptr(data);
27733a7da39dSBen Hutchings 
27743a7da39dSBen Hutchings 	if (get_user(ethcmd, &compat_rxnfc->cmd))
27757a229387SArnd Bergmann 		return -EFAULT;
27767a229387SArnd Bergmann 
27773a7da39dSBen Hutchings 	/* Most ethtool structures are defined without padding.
27783a7da39dSBen Hutchings 	 * Unfortunately struct ethtool_rxnfc is an exception.
27793a7da39dSBen Hutchings 	 */
27803a7da39dSBen Hutchings 	switch (ethcmd) {
27813a7da39dSBen Hutchings 	default:
27823a7da39dSBen Hutchings 		break;
27833a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLALL:
27843a7da39dSBen Hutchings 		/* Buffer size is variable */
27853a7da39dSBen Hutchings 		if (get_user(rule_cnt, &compat_rxnfc->rule_cnt))
27863a7da39dSBen Hutchings 			return -EFAULT;
27873a7da39dSBen Hutchings 		if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32))
27883a7da39dSBen Hutchings 			return -ENOMEM;
27893a7da39dSBen Hutchings 		buf_size += rule_cnt * sizeof(u32);
27903a7da39dSBen Hutchings 		/* fall through */
27913a7da39dSBen Hutchings 	case ETHTOOL_GRXRINGS:
27923a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLCNT:
27933a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRULE:
279455664f32SBen Hutchings 	case ETHTOOL_SRXCLSRLINS:
27953a7da39dSBen Hutchings 		convert_out = true;
27963a7da39dSBen Hutchings 		/* fall through */
27973a7da39dSBen Hutchings 	case ETHTOOL_SRXCLSRLDEL:
27983a7da39dSBen Hutchings 		buf_size += sizeof(struct ethtool_rxnfc);
27993a7da39dSBen Hutchings 		convert_in = true;
28003a7da39dSBen Hutchings 		break;
28013a7da39dSBen Hutchings 	}
28023a7da39dSBen Hutchings 
28033a7da39dSBen Hutchings 	ifr = compat_alloc_user_space(buf_size);
2804954b1244SStephen Hemminger 	rxnfc = (void __user *)ifr + ALIGN(sizeof(struct ifreq), 8);
28053a7da39dSBen Hutchings 
28063a7da39dSBen Hutchings 	if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
28073a7da39dSBen Hutchings 		return -EFAULT;
28083a7da39dSBen Hutchings 
28093a7da39dSBen Hutchings 	if (put_user(convert_in ? rxnfc : compat_ptr(data),
28103a7da39dSBen Hutchings 		     &ifr->ifr_ifru.ifru_data))
28113a7da39dSBen Hutchings 		return -EFAULT;
28123a7da39dSBen Hutchings 
28133a7da39dSBen Hutchings 	if (convert_in) {
2814127fe533SAlexander Duyck 		/* We expect there to be holes between fs.m_ext and
28153a7da39dSBen Hutchings 		 * fs.ring_cookie and at the end of fs, but nowhere else.
28163a7da39dSBen Hutchings 		 */
2817127fe533SAlexander Duyck 		BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_ext) +
2818127fe533SAlexander Duyck 			     sizeof(compat_rxnfc->fs.m_ext) !=
2819127fe533SAlexander Duyck 			     offsetof(struct ethtool_rxnfc, fs.m_ext) +
2820127fe533SAlexander Duyck 			     sizeof(rxnfc->fs.m_ext));
28213a7da39dSBen Hutchings 		BUILD_BUG_ON(
28223a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.location) -
28233a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) !=
28243a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.location) -
28253a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.ring_cookie));
28263a7da39dSBen Hutchings 
28273a7da39dSBen Hutchings 		if (copy_in_user(rxnfc, compat_rxnfc,
2828954b1244SStephen Hemminger 				 (void __user *)(&rxnfc->fs.m_ext + 1) -
2829954b1244SStephen Hemminger 				 (void __user *)rxnfc) ||
28303a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->fs.ring_cookie,
28313a7da39dSBen Hutchings 				 &compat_rxnfc->fs.ring_cookie,
2832954b1244SStephen Hemminger 				 (void __user *)(&rxnfc->fs.location + 1) -
2833954b1244SStephen Hemminger 				 (void __user *)&rxnfc->fs.ring_cookie) ||
28343a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt,
28353a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
28363a7da39dSBen Hutchings 			return -EFAULT;
28373a7da39dSBen Hutchings 	}
28383a7da39dSBen Hutchings 
28393a7da39dSBen Hutchings 	ret = dev_ioctl(net, SIOCETHTOOL, ifr);
28403a7da39dSBen Hutchings 	if (ret)
28413a7da39dSBen Hutchings 		return ret;
28423a7da39dSBen Hutchings 
28433a7da39dSBen Hutchings 	if (convert_out) {
28443a7da39dSBen Hutchings 		if (copy_in_user(compat_rxnfc, rxnfc,
2845954b1244SStephen Hemminger 				 (const void __user *)(&rxnfc->fs.m_ext + 1) -
2846954b1244SStephen Hemminger 				 (const void __user *)rxnfc) ||
28473a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->fs.ring_cookie,
28483a7da39dSBen Hutchings 				 &rxnfc->fs.ring_cookie,
2849954b1244SStephen Hemminger 				 (const void __user *)(&rxnfc->fs.location + 1) -
2850954b1244SStephen Hemminger 				 (const void __user *)&rxnfc->fs.ring_cookie) ||
28513a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt,
28523a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
28533a7da39dSBen Hutchings 			return -EFAULT;
28543a7da39dSBen Hutchings 
28553a7da39dSBen Hutchings 		if (ethcmd == ETHTOOL_GRXCLSRLALL) {
28563a7da39dSBen Hutchings 			/* As an optimisation, we only copy the actual
28573a7da39dSBen Hutchings 			 * number of rules that the underlying
28583a7da39dSBen Hutchings 			 * function returned.  Since Mallory might
28593a7da39dSBen Hutchings 			 * change the rule count in user memory, we
28603a7da39dSBen Hutchings 			 * check that it is less than the rule count
28613a7da39dSBen Hutchings 			 * originally given (as the user buffer size),
28623a7da39dSBen Hutchings 			 * which has been range-checked.
28633a7da39dSBen Hutchings 			 */
28643a7da39dSBen Hutchings 			if (get_user(actual_rule_cnt, &rxnfc->rule_cnt))
28653a7da39dSBen Hutchings 				return -EFAULT;
28663a7da39dSBen Hutchings 			if (actual_rule_cnt < rule_cnt)
28673a7da39dSBen Hutchings 				rule_cnt = actual_rule_cnt;
28683a7da39dSBen Hutchings 			if (copy_in_user(&compat_rxnfc->rule_locs[0],
28693a7da39dSBen Hutchings 					 &rxnfc->rule_locs[0],
28703a7da39dSBen Hutchings 					 rule_cnt * sizeof(u32)))
28713a7da39dSBen Hutchings 				return -EFAULT;
28723a7da39dSBen Hutchings 		}
28733a7da39dSBen Hutchings 	}
28743a7da39dSBen Hutchings 
28753a7da39dSBen Hutchings 	return 0;
28767a229387SArnd Bergmann }
28777a229387SArnd Bergmann 
28787a50a240SArnd Bergmann static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32)
28797a50a240SArnd Bergmann {
28807a50a240SArnd Bergmann 	void __user *uptr;
28817a50a240SArnd Bergmann 	compat_uptr_t uptr32;
28827a50a240SArnd Bergmann 	struct ifreq __user *uifr;
28837a50a240SArnd Bergmann 
28847a50a240SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
28857a50a240SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
28867a50a240SArnd Bergmann 		return -EFAULT;
28877a50a240SArnd Bergmann 
28887a50a240SArnd Bergmann 	if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu))
28897a50a240SArnd Bergmann 		return -EFAULT;
28907a50a240SArnd Bergmann 
28917a50a240SArnd Bergmann 	uptr = compat_ptr(uptr32);
28927a50a240SArnd Bergmann 
28937a50a240SArnd Bergmann 	if (put_user(uptr, &uifr->ifr_settings.ifs_ifsu.raw_hdlc))
28947a50a240SArnd Bergmann 		return -EFAULT;
28957a50a240SArnd Bergmann 
28967a50a240SArnd Bergmann 	return dev_ioctl(net, SIOCWANDEV, uifr);
28977a50a240SArnd Bergmann }
28987a50a240SArnd Bergmann 
28996b96018bSArnd Bergmann static int bond_ioctl(struct net *net, unsigned int cmd,
29006b96018bSArnd Bergmann 			 struct compat_ifreq __user *ifr32)
29017a229387SArnd Bergmann {
29027a229387SArnd Bergmann 	struct ifreq kifr;
29037a229387SArnd Bergmann 	mm_segment_t old_fs;
29047a229387SArnd Bergmann 	int err;
29057a229387SArnd Bergmann 
29067a229387SArnd Bergmann 	switch (cmd) {
29077a229387SArnd Bergmann 	case SIOCBONDENSLAVE:
29087a229387SArnd Bergmann 	case SIOCBONDRELEASE:
29097a229387SArnd Bergmann 	case SIOCBONDSETHWADDR:
29107a229387SArnd Bergmann 	case SIOCBONDCHANGEACTIVE:
29116b96018bSArnd Bergmann 		if (copy_from_user(&kifr, ifr32, sizeof(struct compat_ifreq)))
29127a229387SArnd Bergmann 			return -EFAULT;
29137a229387SArnd Bergmann 
29147a229387SArnd Bergmann 		old_fs = get_fs();
29157a229387SArnd Bergmann 		set_fs(KERNEL_DS);
2916c3f52ae6Sstephen hemminger 		err = dev_ioctl(net, cmd,
2917c3f52ae6Sstephen hemminger 				(struct ifreq __user __force *) &kifr);
29187a229387SArnd Bergmann 		set_fs(old_fs);
29197a229387SArnd Bergmann 
29207a229387SArnd Bergmann 		return err;
29217a229387SArnd Bergmann 	default:
292207d106d0SLinus Torvalds 		return -ENOIOCTLCMD;
2923ccbd6a5aSJoe Perches 	}
29247a229387SArnd Bergmann }
29257a229387SArnd Bergmann 
2926590d4693SBen Hutchings /* Handle ioctls that use ifreq::ifr_data and just need struct ifreq converted */
2927590d4693SBen Hutchings static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd,
29286b96018bSArnd Bergmann 				 struct compat_ifreq __user *u_ifreq32)
29297a229387SArnd Bergmann {
29307a229387SArnd Bergmann 	struct ifreq __user *u_ifreq64;
29317a229387SArnd Bergmann 	char tmp_buf[IFNAMSIZ];
29327a229387SArnd Bergmann 	void __user *data64;
29337a229387SArnd Bergmann 	u32 data32;
29347a229387SArnd Bergmann 
29357a229387SArnd Bergmann 	if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]),
29367a229387SArnd Bergmann 			   IFNAMSIZ))
29377a229387SArnd Bergmann 		return -EFAULT;
2938417c3522SBen Hutchings 	if (get_user(data32, &u_ifreq32->ifr_ifru.ifru_data))
29397a229387SArnd Bergmann 		return -EFAULT;
29407a229387SArnd Bergmann 	data64 = compat_ptr(data32);
29417a229387SArnd Bergmann 
29427a229387SArnd Bergmann 	u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
29437a229387SArnd Bergmann 
29447a229387SArnd Bergmann 	if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0],
29457a229387SArnd Bergmann 			 IFNAMSIZ))
29467a229387SArnd Bergmann 		return -EFAULT;
2947417c3522SBen Hutchings 	if (put_user(data64, &u_ifreq64->ifr_ifru.ifru_data))
29487a229387SArnd Bergmann 		return -EFAULT;
29497a229387SArnd Bergmann 
29506b96018bSArnd Bergmann 	return dev_ioctl(net, cmd, u_ifreq64);
29517a229387SArnd Bergmann }
29527a229387SArnd Bergmann 
29536b96018bSArnd Bergmann static int dev_ifsioc(struct net *net, struct socket *sock,
29546b96018bSArnd Bergmann 			 unsigned int cmd, struct compat_ifreq __user *uifr32)
29557a229387SArnd Bergmann {
2956a2116ed2SArnd Bergmann 	struct ifreq __user *uifr;
29577a229387SArnd Bergmann 	int err;
29587a229387SArnd Bergmann 
2959a2116ed2SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
2960a2116ed2SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(*uifr32)))
29617a229387SArnd Bergmann 		return -EFAULT;
2962a2116ed2SArnd Bergmann 
2963a2116ed2SArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr);
2964a2116ed2SArnd Bergmann 
29657a229387SArnd Bergmann 	if (!err) {
29667a229387SArnd Bergmann 		switch (cmd) {
29677a229387SArnd Bergmann 		case SIOCGIFFLAGS:
29687a229387SArnd Bergmann 		case SIOCGIFMETRIC:
29697a229387SArnd Bergmann 		case SIOCGIFMTU:
29707a229387SArnd Bergmann 		case SIOCGIFMEM:
29717a229387SArnd Bergmann 		case SIOCGIFHWADDR:
29727a229387SArnd Bergmann 		case SIOCGIFINDEX:
29737a229387SArnd Bergmann 		case SIOCGIFADDR:
29747a229387SArnd Bergmann 		case SIOCGIFBRDADDR:
29757a229387SArnd Bergmann 		case SIOCGIFDSTADDR:
29767a229387SArnd Bergmann 		case SIOCGIFNETMASK:
2977fab2532bSArnd Bergmann 		case SIOCGIFPFLAGS:
29787a229387SArnd Bergmann 		case SIOCGIFTXQLEN:
2979fab2532bSArnd Bergmann 		case SIOCGMIIPHY:
2980fab2532bSArnd Bergmann 		case SIOCGMIIREG:
2981a2116ed2SArnd Bergmann 			if (copy_in_user(uifr32, uifr, sizeof(*uifr32)))
2982a2116ed2SArnd Bergmann 				err = -EFAULT;
29837a229387SArnd Bergmann 			break;
2984a2116ed2SArnd Bergmann 		}
2985a2116ed2SArnd Bergmann 	}
2986a2116ed2SArnd Bergmann 	return err;
2987a2116ed2SArnd Bergmann }
2988a2116ed2SArnd Bergmann 
2989a2116ed2SArnd Bergmann static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
2990a2116ed2SArnd Bergmann 			struct compat_ifreq __user *uifr32)
2991a2116ed2SArnd Bergmann {
2992a2116ed2SArnd Bergmann 	struct ifreq ifr;
2993a2116ed2SArnd Bergmann 	struct compat_ifmap __user *uifmap32;
2994a2116ed2SArnd Bergmann 	mm_segment_t old_fs;
2995a2116ed2SArnd Bergmann 	int err;
2996a2116ed2SArnd Bergmann 
2997a2116ed2SArnd Bergmann 	uifmap32 = &uifr32->ifr_ifru.ifru_map;
2998a2116ed2SArnd Bergmann 	err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name));
29993ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
30003ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
30013ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
30023ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.irq, &uifmap32->irq);
30033ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.dma, &uifmap32->dma);
30043ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.port, &uifmap32->port);
3005a2116ed2SArnd Bergmann 	if (err)
3006a2116ed2SArnd Bergmann 		return -EFAULT;
3007a2116ed2SArnd Bergmann 
3008a2116ed2SArnd Bergmann 	old_fs = get_fs();
3009a2116ed2SArnd Bergmann 	set_fs(KERNEL_DS);
3010c3f52ae6Sstephen hemminger 	err = dev_ioctl(net, cmd, (void  __user __force *)&ifr);
3011a2116ed2SArnd Bergmann 	set_fs(old_fs);
3012a2116ed2SArnd Bergmann 
3013a2116ed2SArnd Bergmann 	if (cmd == SIOCGIFMAP && !err) {
30147a229387SArnd Bergmann 		err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name));
30153ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
30163ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
30173ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
30183ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.irq, &uifmap32->irq);
30193ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.dma, &uifmap32->dma);
30203ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.port, &uifmap32->port);
30217a229387SArnd Bergmann 		if (err)
30227a229387SArnd Bergmann 			err = -EFAULT;
30237a229387SArnd Bergmann 	}
30247a229387SArnd Bergmann 	return err;
30257a229387SArnd Bergmann }
30267a229387SArnd Bergmann 
30277a229387SArnd Bergmann struct rtentry32 {
30287a229387SArnd Bergmann 	u32		rt_pad1;
30297a229387SArnd Bergmann 	struct sockaddr rt_dst;         /* target address               */
30307a229387SArnd Bergmann 	struct sockaddr rt_gateway;     /* gateway addr (RTF_GATEWAY)   */
30317a229387SArnd Bergmann 	struct sockaddr rt_genmask;     /* target network mask (IP)     */
30327a229387SArnd Bergmann 	unsigned short	rt_flags;
30337a229387SArnd Bergmann 	short		rt_pad2;
30347a229387SArnd Bergmann 	u32		rt_pad3;
30357a229387SArnd Bergmann 	unsigned char	rt_tos;
30367a229387SArnd Bergmann 	unsigned char	rt_class;
30377a229387SArnd Bergmann 	short		rt_pad4;
30387a229387SArnd Bergmann 	short		rt_metric;      /* +1 for binary compatibility! */
30397a229387SArnd Bergmann 	/* char * */ u32 rt_dev;        /* forcing the device at add    */
30407a229387SArnd Bergmann 	u32		rt_mtu;         /* per route MTU/Window         */
30417a229387SArnd Bergmann 	u32		rt_window;      /* Window clamping              */
30427a229387SArnd Bergmann 	unsigned short  rt_irtt;        /* Initial RTT                  */
30437a229387SArnd Bergmann };
30447a229387SArnd Bergmann 
30457a229387SArnd Bergmann struct in6_rtmsg32 {
30467a229387SArnd Bergmann 	struct in6_addr		rtmsg_dst;
30477a229387SArnd Bergmann 	struct in6_addr		rtmsg_src;
30487a229387SArnd Bergmann 	struct in6_addr		rtmsg_gateway;
30497a229387SArnd Bergmann 	u32			rtmsg_type;
30507a229387SArnd Bergmann 	u16			rtmsg_dst_len;
30517a229387SArnd Bergmann 	u16			rtmsg_src_len;
30527a229387SArnd Bergmann 	u32			rtmsg_metric;
30537a229387SArnd Bergmann 	u32			rtmsg_info;
30547a229387SArnd Bergmann 	u32			rtmsg_flags;
30557a229387SArnd Bergmann 	s32			rtmsg_ifindex;
30567a229387SArnd Bergmann };
30577a229387SArnd Bergmann 
30586b96018bSArnd Bergmann static int routing_ioctl(struct net *net, struct socket *sock,
30596b96018bSArnd Bergmann 			 unsigned int cmd, void __user *argp)
30607a229387SArnd Bergmann {
30617a229387SArnd Bergmann 	int ret;
30627a229387SArnd Bergmann 	void *r = NULL;
30637a229387SArnd Bergmann 	struct in6_rtmsg r6;
30647a229387SArnd Bergmann 	struct rtentry r4;
30657a229387SArnd Bergmann 	char devname[16];
30667a229387SArnd Bergmann 	u32 rtdev;
30677a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
30687a229387SArnd Bergmann 
30696b96018bSArnd Bergmann 	if (sock && sock->sk && sock->sk->sk_family == AF_INET6) { /* ipv6 */
30706b96018bSArnd Bergmann 		struct in6_rtmsg32 __user *ur6 = argp;
30717a229387SArnd Bergmann 		ret = copy_from_user(&r6.rtmsg_dst, &(ur6->rtmsg_dst),
30727a229387SArnd Bergmann 			3 * sizeof(struct in6_addr));
30733ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_type, &(ur6->rtmsg_type));
30743ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len));
30753ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_src_len, &(ur6->rtmsg_src_len));
30763ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_metric, &(ur6->rtmsg_metric));
30773ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_info, &(ur6->rtmsg_info));
30783ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_flags, &(ur6->rtmsg_flags));
30793ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex));
30807a229387SArnd Bergmann 
30817a229387SArnd Bergmann 		r = (void *) &r6;
30827a229387SArnd Bergmann 	} else { /* ipv4 */
30836b96018bSArnd Bergmann 		struct rtentry32 __user *ur4 = argp;
30847a229387SArnd Bergmann 		ret = copy_from_user(&r4.rt_dst, &(ur4->rt_dst),
30857a229387SArnd Bergmann 					3 * sizeof(struct sockaddr));
30863ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_flags, &(ur4->rt_flags));
30873ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_metric, &(ur4->rt_metric));
30883ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_mtu, &(ur4->rt_mtu));
30893ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_window, &(ur4->rt_window));
30903ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_irtt, &(ur4->rt_irtt));
30913ddc5b46SMathieu Desnoyers 		ret |= get_user(rtdev, &(ur4->rt_dev));
30927a229387SArnd Bergmann 		if (rtdev) {
30937a229387SArnd Bergmann 			ret |= copy_from_user(devname, compat_ptr(rtdev), 15);
3094c3f52ae6Sstephen hemminger 			r4.rt_dev = (char __user __force *)devname;
3095c3f52ae6Sstephen hemminger 			devname[15] = 0;
30967a229387SArnd Bergmann 		} else
30977a229387SArnd Bergmann 			r4.rt_dev = NULL;
30987a229387SArnd Bergmann 
30997a229387SArnd Bergmann 		r = (void *) &r4;
31007a229387SArnd Bergmann 	}
31017a229387SArnd Bergmann 
31027a229387SArnd Bergmann 	if (ret) {
31037a229387SArnd Bergmann 		ret = -EFAULT;
31047a229387SArnd Bergmann 		goto out;
31057a229387SArnd Bergmann 	}
31067a229387SArnd Bergmann 
31077a229387SArnd Bergmann 	set_fs(KERNEL_DS);
31086b96018bSArnd Bergmann 	ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r);
31097a229387SArnd Bergmann 	set_fs(old_fs);
31107a229387SArnd Bergmann 
31117a229387SArnd Bergmann out:
31127a229387SArnd Bergmann 	return ret;
31137a229387SArnd Bergmann }
31147a229387SArnd Bergmann 
31157a229387SArnd Bergmann /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE
31167a229387SArnd Bergmann  * for some operations; this forces use of the newer bridge-utils that
311725985edcSLucas De Marchi  * use compatible ioctls
31187a229387SArnd Bergmann  */
31196b96018bSArnd Bergmann static int old_bridge_ioctl(compat_ulong_t __user *argp)
31207a229387SArnd Bergmann {
31216b96018bSArnd Bergmann 	compat_ulong_t tmp;
31227a229387SArnd Bergmann 
31236b96018bSArnd Bergmann 	if (get_user(tmp, argp))
31247a229387SArnd Bergmann 		return -EFAULT;
31257a229387SArnd Bergmann 	if (tmp == BRCTL_GET_VERSION)
31267a229387SArnd Bergmann 		return BRCTL_VERSION + 1;
31277a229387SArnd Bergmann 	return -EINVAL;
31287a229387SArnd Bergmann }
31297a229387SArnd Bergmann 
31306b96018bSArnd Bergmann static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
31316b96018bSArnd Bergmann 			 unsigned int cmd, unsigned long arg)
31326b96018bSArnd Bergmann {
31336b96018bSArnd Bergmann 	void __user *argp = compat_ptr(arg);
31346b96018bSArnd Bergmann 	struct sock *sk = sock->sk;
31356b96018bSArnd Bergmann 	struct net *net = sock_net(sk);
31367a229387SArnd Bergmann 
31376b96018bSArnd Bergmann 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
3138590d4693SBen Hutchings 		return compat_ifr_data_ioctl(net, cmd, argp);
31397a229387SArnd Bergmann 
31406b96018bSArnd Bergmann 	switch (cmd) {
31416b96018bSArnd Bergmann 	case SIOCSIFBR:
31426b96018bSArnd Bergmann 	case SIOCGIFBR:
31436b96018bSArnd Bergmann 		return old_bridge_ioctl(argp);
31446b96018bSArnd Bergmann 	case SIOCGIFNAME:
31456b96018bSArnd Bergmann 		return dev_ifname32(net, argp);
31466b96018bSArnd Bergmann 	case SIOCGIFCONF:
31476b96018bSArnd Bergmann 		return dev_ifconf(net, argp);
31486b96018bSArnd Bergmann 	case SIOCETHTOOL:
31496b96018bSArnd Bergmann 		return ethtool_ioctl(net, argp);
31507a50a240SArnd Bergmann 	case SIOCWANDEV:
31517a50a240SArnd Bergmann 		return compat_siocwandev(net, argp);
3152a2116ed2SArnd Bergmann 	case SIOCGIFMAP:
3153a2116ed2SArnd Bergmann 	case SIOCSIFMAP:
3154a2116ed2SArnd Bergmann 		return compat_sioc_ifmap(net, cmd, argp);
31556b96018bSArnd Bergmann 	case SIOCBONDENSLAVE:
31566b96018bSArnd Bergmann 	case SIOCBONDRELEASE:
31576b96018bSArnd Bergmann 	case SIOCBONDSETHWADDR:
31586b96018bSArnd Bergmann 	case SIOCBONDCHANGEACTIVE:
31596b96018bSArnd Bergmann 		return bond_ioctl(net, cmd, argp);
31606b96018bSArnd Bergmann 	case SIOCADDRT:
31616b96018bSArnd Bergmann 	case SIOCDELRT:
31626b96018bSArnd Bergmann 		return routing_ioctl(net, sock, cmd, argp);
31636b96018bSArnd Bergmann 	case SIOCGSTAMP:
31646b96018bSArnd Bergmann 		return do_siocgstamp(net, sock, cmd, argp);
31656b96018bSArnd Bergmann 	case SIOCGSTAMPNS:
31666b96018bSArnd Bergmann 		return do_siocgstampns(net, sock, cmd, argp);
3167590d4693SBen Hutchings 	case SIOCBONDSLAVEINFOQUERY:
3168590d4693SBen Hutchings 	case SIOCBONDINFOQUERY:
3169a2116ed2SArnd Bergmann 	case SIOCSHWTSTAMP:
3170fd468c74SBen Hutchings 	case SIOCGHWTSTAMP:
3171590d4693SBen Hutchings 		return compat_ifr_data_ioctl(net, cmd, argp);
31727a229387SArnd Bergmann 
31736b96018bSArnd Bergmann 	case FIOSETOWN:
31746b96018bSArnd Bergmann 	case SIOCSPGRP:
31756b96018bSArnd Bergmann 	case FIOGETOWN:
31766b96018bSArnd Bergmann 	case SIOCGPGRP:
31776b96018bSArnd Bergmann 	case SIOCBRADDBR:
31786b96018bSArnd Bergmann 	case SIOCBRDELBR:
31796b96018bSArnd Bergmann 	case SIOCGIFVLAN:
31806b96018bSArnd Bergmann 	case SIOCSIFVLAN:
31816b96018bSArnd Bergmann 	case SIOCADDDLCI:
31826b96018bSArnd Bergmann 	case SIOCDELDLCI:
3183c62cce2cSAndrey Vagin 	case SIOCGSKNS:
31846b96018bSArnd Bergmann 		return sock_ioctl(file, cmd, arg);
31856b96018bSArnd Bergmann 
31866b96018bSArnd Bergmann 	case SIOCGIFFLAGS:
31876b96018bSArnd Bergmann 	case SIOCSIFFLAGS:
31886b96018bSArnd Bergmann 	case SIOCGIFMETRIC:
31896b96018bSArnd Bergmann 	case SIOCSIFMETRIC:
31906b96018bSArnd Bergmann 	case SIOCGIFMTU:
31916b96018bSArnd Bergmann 	case SIOCSIFMTU:
31926b96018bSArnd Bergmann 	case SIOCGIFMEM:
31936b96018bSArnd Bergmann 	case SIOCSIFMEM:
31946b96018bSArnd Bergmann 	case SIOCGIFHWADDR:
31956b96018bSArnd Bergmann 	case SIOCSIFHWADDR:
31966b96018bSArnd Bergmann 	case SIOCADDMULTI:
31976b96018bSArnd Bergmann 	case SIOCDELMULTI:
31986b96018bSArnd Bergmann 	case SIOCGIFINDEX:
31996b96018bSArnd Bergmann 	case SIOCGIFADDR:
32006b96018bSArnd Bergmann 	case SIOCSIFADDR:
32016b96018bSArnd Bergmann 	case SIOCSIFHWBROADCAST:
32026b96018bSArnd Bergmann 	case SIOCDIFADDR:
32036b96018bSArnd Bergmann 	case SIOCGIFBRDADDR:
32046b96018bSArnd Bergmann 	case SIOCSIFBRDADDR:
32056b96018bSArnd Bergmann 	case SIOCGIFDSTADDR:
32066b96018bSArnd Bergmann 	case SIOCSIFDSTADDR:
32076b96018bSArnd Bergmann 	case SIOCGIFNETMASK:
32086b96018bSArnd Bergmann 	case SIOCSIFNETMASK:
32096b96018bSArnd Bergmann 	case SIOCSIFPFLAGS:
32106b96018bSArnd Bergmann 	case SIOCGIFPFLAGS:
32116b96018bSArnd Bergmann 	case SIOCGIFTXQLEN:
32126b96018bSArnd Bergmann 	case SIOCSIFTXQLEN:
32136b96018bSArnd Bergmann 	case SIOCBRADDIF:
32146b96018bSArnd Bergmann 	case SIOCBRDELIF:
32159177efd3SArnd Bergmann 	case SIOCSIFNAME:
32169177efd3SArnd Bergmann 	case SIOCGMIIPHY:
32179177efd3SArnd Bergmann 	case SIOCGMIIREG:
32189177efd3SArnd Bergmann 	case SIOCSMIIREG:
32196b96018bSArnd Bergmann 		return dev_ifsioc(net, sock, cmd, argp);
32209177efd3SArnd Bergmann 
32216b96018bSArnd Bergmann 	case SIOCSARP:
32226b96018bSArnd Bergmann 	case SIOCGARP:
32236b96018bSArnd Bergmann 	case SIOCDARP:
32246b96018bSArnd Bergmann 	case SIOCATMARK:
32259177efd3SArnd Bergmann 		return sock_do_ioctl(net, sock, cmd, arg);
32269177efd3SArnd Bergmann 	}
32279177efd3SArnd Bergmann 
32286b96018bSArnd Bergmann 	return -ENOIOCTLCMD;
32296b96018bSArnd Bergmann }
32307a229387SArnd Bergmann 
323195c96174SEric Dumazet static long compat_sock_ioctl(struct file *file, unsigned int cmd,
323289bbfc95SShaun Pereira 			      unsigned long arg)
323389bbfc95SShaun Pereira {
323489bbfc95SShaun Pereira 	struct socket *sock = file->private_data;
323589bbfc95SShaun Pereira 	int ret = -ENOIOCTLCMD;
323687de87d5SDavid S. Miller 	struct sock *sk;
323787de87d5SDavid S. Miller 	struct net *net;
323887de87d5SDavid S. Miller 
323987de87d5SDavid S. Miller 	sk = sock->sk;
324087de87d5SDavid S. Miller 	net = sock_net(sk);
324189bbfc95SShaun Pereira 
324289bbfc95SShaun Pereira 	if (sock->ops->compat_ioctl)
324389bbfc95SShaun Pereira 		ret = sock->ops->compat_ioctl(sock, cmd, arg);
324489bbfc95SShaun Pereira 
324587de87d5SDavid S. Miller 	if (ret == -ENOIOCTLCMD &&
324687de87d5SDavid S. Miller 	    (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST))
324787de87d5SDavid S. Miller 		ret = compat_wext_handle_ioctl(net, cmd, arg);
324887de87d5SDavid S. Miller 
32496b96018bSArnd Bergmann 	if (ret == -ENOIOCTLCMD)
32506b96018bSArnd Bergmann 		ret = compat_sock_ioctl_trans(file, sock, cmd, arg);
32516b96018bSArnd Bergmann 
325289bbfc95SShaun Pereira 	return ret;
325389bbfc95SShaun Pereira }
325489bbfc95SShaun Pereira #endif
325589bbfc95SShaun Pereira 
3256ac5a488eSSridhar Samudrala int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
3257ac5a488eSSridhar Samudrala {
3258ac5a488eSSridhar Samudrala 	return sock->ops->bind(sock, addr, addrlen);
3259ac5a488eSSridhar Samudrala }
3260c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_bind);
3261ac5a488eSSridhar Samudrala 
3262ac5a488eSSridhar Samudrala int kernel_listen(struct socket *sock, int backlog)
3263ac5a488eSSridhar Samudrala {
3264ac5a488eSSridhar Samudrala 	return sock->ops->listen(sock, backlog);
3265ac5a488eSSridhar Samudrala }
3266c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_listen);
3267ac5a488eSSridhar Samudrala 
3268ac5a488eSSridhar Samudrala int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
3269ac5a488eSSridhar Samudrala {
3270ac5a488eSSridhar Samudrala 	struct sock *sk = sock->sk;
3271ac5a488eSSridhar Samudrala 	int err;
3272ac5a488eSSridhar Samudrala 
3273ac5a488eSSridhar Samudrala 	err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
3274ac5a488eSSridhar Samudrala 			       newsock);
3275ac5a488eSSridhar Samudrala 	if (err < 0)
3276ac5a488eSSridhar Samudrala 		goto done;
3277ac5a488eSSridhar Samudrala 
3278cdfbabfbSDavid Howells 	err = sock->ops->accept(sock, *newsock, flags, true);
3279ac5a488eSSridhar Samudrala 	if (err < 0) {
3280ac5a488eSSridhar Samudrala 		sock_release(*newsock);
3281fa8705b0STony Battersby 		*newsock = NULL;
3282ac5a488eSSridhar Samudrala 		goto done;
3283ac5a488eSSridhar Samudrala 	}
3284ac5a488eSSridhar Samudrala 
3285ac5a488eSSridhar Samudrala 	(*newsock)->ops = sock->ops;
32861b08534eSWei Yongjun 	__module_get((*newsock)->ops->owner);
3287ac5a488eSSridhar Samudrala 
3288ac5a488eSSridhar Samudrala done:
3289ac5a488eSSridhar Samudrala 	return err;
3290ac5a488eSSridhar Samudrala }
3291c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_accept);
3292ac5a488eSSridhar Samudrala 
3293ac5a488eSSridhar Samudrala int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
3294ac5a488eSSridhar Samudrala 		   int flags)
3295ac5a488eSSridhar Samudrala {
3296ac5a488eSSridhar Samudrala 	return sock->ops->connect(sock, addr, addrlen, flags);
3297ac5a488eSSridhar Samudrala }
3298c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_connect);
3299ac5a488eSSridhar Samudrala 
3300ac5a488eSSridhar Samudrala int kernel_getsockname(struct socket *sock, struct sockaddr *addr,
3301ac5a488eSSridhar Samudrala 			 int *addrlen)
3302ac5a488eSSridhar Samudrala {
3303ac5a488eSSridhar Samudrala 	return sock->ops->getname(sock, addr, addrlen, 0);
3304ac5a488eSSridhar Samudrala }
3305c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockname);
3306ac5a488eSSridhar Samudrala 
3307ac5a488eSSridhar Samudrala int kernel_getpeername(struct socket *sock, struct sockaddr *addr,
3308ac5a488eSSridhar Samudrala 			 int *addrlen)
3309ac5a488eSSridhar Samudrala {
3310ac5a488eSSridhar Samudrala 	return sock->ops->getname(sock, addr, addrlen, 1);
3311ac5a488eSSridhar Samudrala }
3312c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getpeername);
3313ac5a488eSSridhar Samudrala 
3314ac5a488eSSridhar Samudrala int kernel_getsockopt(struct socket *sock, int level, int optname,
3315ac5a488eSSridhar Samudrala 			char *optval, int *optlen)
3316ac5a488eSSridhar Samudrala {
3317ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3318fb8621bbSNamhyung Kim 	char __user *uoptval;
3319fb8621bbSNamhyung Kim 	int __user *uoptlen;
3320ac5a488eSSridhar Samudrala 	int err;
3321ac5a488eSSridhar Samudrala 
3322fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3323fb8621bbSNamhyung Kim 	uoptlen = (int __user __force *) optlen;
3324fb8621bbSNamhyung Kim 
3325ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3326ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3327fb8621bbSNamhyung Kim 		err = sock_getsockopt(sock, level, optname, uoptval, uoptlen);
3328ac5a488eSSridhar Samudrala 	else
3329fb8621bbSNamhyung Kim 		err = sock->ops->getsockopt(sock, level, optname, uoptval,
3330fb8621bbSNamhyung Kim 					    uoptlen);
3331ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3332ac5a488eSSridhar Samudrala 	return err;
3333ac5a488eSSridhar Samudrala }
3334c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockopt);
3335ac5a488eSSridhar Samudrala 
3336ac5a488eSSridhar Samudrala int kernel_setsockopt(struct socket *sock, int level, int optname,
3337b7058842SDavid S. Miller 			char *optval, unsigned int optlen)
3338ac5a488eSSridhar Samudrala {
3339ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3340fb8621bbSNamhyung Kim 	char __user *uoptval;
3341ac5a488eSSridhar Samudrala 	int err;
3342ac5a488eSSridhar Samudrala 
3343fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3344fb8621bbSNamhyung Kim 
3345ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3346ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3347fb8621bbSNamhyung Kim 		err = sock_setsockopt(sock, level, optname, uoptval, optlen);
3348ac5a488eSSridhar Samudrala 	else
3349fb8621bbSNamhyung Kim 		err = sock->ops->setsockopt(sock, level, optname, uoptval,
3350ac5a488eSSridhar Samudrala 					    optlen);
3351ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3352ac5a488eSSridhar Samudrala 	return err;
3353ac5a488eSSridhar Samudrala }
3354c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_setsockopt);
3355ac5a488eSSridhar Samudrala 
3356ac5a488eSSridhar Samudrala int kernel_sendpage(struct socket *sock, struct page *page, int offset,
3357ac5a488eSSridhar Samudrala 		    size_t size, int flags)
3358ac5a488eSSridhar Samudrala {
3359ac5a488eSSridhar Samudrala 	if (sock->ops->sendpage)
3360ac5a488eSSridhar Samudrala 		return sock->ops->sendpage(sock, page, offset, size, flags);
3361ac5a488eSSridhar Samudrala 
3362ac5a488eSSridhar Samudrala 	return sock_no_sendpage(sock, page, offset, size, flags);
3363ac5a488eSSridhar Samudrala }
3364c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendpage);
3365ac5a488eSSridhar Samudrala 
3366ac5a488eSSridhar Samudrala int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg)
3367ac5a488eSSridhar Samudrala {
3368ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3369ac5a488eSSridhar Samudrala 	int err;
3370ac5a488eSSridhar Samudrala 
3371ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3372ac5a488eSSridhar Samudrala 	err = sock->ops->ioctl(sock, cmd, arg);
3373ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3374ac5a488eSSridhar Samudrala 
3375ac5a488eSSridhar Samudrala 	return err;
3376ac5a488eSSridhar Samudrala }
3377c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sock_ioctl);
3378ac5a488eSSridhar Samudrala 
337991cf45f0STrond Myklebust int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
338091cf45f0STrond Myklebust {
338191cf45f0STrond Myklebust 	return sock->ops->shutdown(sock, how);
338291cf45f0STrond Myklebust }
338391cf45f0STrond Myklebust EXPORT_SYMBOL(kernel_sock_shutdown);
3384113c3075SR. Parameswaran 
3385113c3075SR. Parameswaran /* This routine returns the IP overhead imposed by a socket i.e.
3386113c3075SR. Parameswaran  * the length of the underlying IP header, depending on whether
3387113c3075SR. Parameswaran  * this is an IPv4 or IPv6 socket and the length from IP options turned
338857240d00SR. Parameswaran  * on at the socket. Assumes that the caller has a lock on the socket.
3389113c3075SR. Parameswaran  */
3390113c3075SR. Parameswaran u32 kernel_sock_ip_overhead(struct sock *sk)
3391113c3075SR. Parameswaran {
3392113c3075SR. Parameswaran 	struct inet_sock *inet;
3393113c3075SR. Parameswaran 	struct ip_options_rcu *opt;
3394113c3075SR. Parameswaran 	u32 overhead = 0;
3395113c3075SR. Parameswaran 	bool owned_by_user;
3396113c3075SR. Parameswaran #if IS_ENABLED(CONFIG_IPV6)
3397113c3075SR. Parameswaran 	struct ipv6_pinfo *np;
3398113c3075SR. Parameswaran 	struct ipv6_txoptions *optv6 = NULL;
3399113c3075SR. Parameswaran #endif /* IS_ENABLED(CONFIG_IPV6) */
3400113c3075SR. Parameswaran 
3401113c3075SR. Parameswaran 	if (!sk)
3402113c3075SR. Parameswaran 		return overhead;
3403113c3075SR. Parameswaran 
3404113c3075SR. Parameswaran 	owned_by_user = sock_owned_by_user(sk);
3405113c3075SR. Parameswaran 	switch (sk->sk_family) {
3406113c3075SR. Parameswaran 	case AF_INET:
3407113c3075SR. Parameswaran 		inet = inet_sk(sk);
3408113c3075SR. Parameswaran 		overhead += sizeof(struct iphdr);
3409113c3075SR. Parameswaran 		opt = rcu_dereference_protected(inet->inet_opt,
3410113c3075SR. Parameswaran 						owned_by_user);
3411113c3075SR. Parameswaran 		if (opt)
3412113c3075SR. Parameswaran 			overhead += opt->opt.optlen;
3413113c3075SR. Parameswaran 		return overhead;
3414113c3075SR. Parameswaran #if IS_ENABLED(CONFIG_IPV6)
3415113c3075SR. Parameswaran 	case AF_INET6:
3416113c3075SR. Parameswaran 		np = inet6_sk(sk);
3417113c3075SR. Parameswaran 		overhead += sizeof(struct ipv6hdr);
3418113c3075SR. Parameswaran 		if (np)
3419113c3075SR. Parameswaran 			optv6 = rcu_dereference_protected(np->opt,
3420113c3075SR. Parameswaran 							  owned_by_user);
3421113c3075SR. Parameswaran 		if (optv6)
3422113c3075SR. Parameswaran 			overhead += (optv6->opt_flen + optv6->opt_nflen);
3423113c3075SR. Parameswaran 		return overhead;
3424113c3075SR. Parameswaran #endif /* IS_ENABLED(CONFIG_IPV6) */
3425113c3075SR. Parameswaran 	default: /* Returns 0 overhead if the socket is not ipv4 or ipv6 */
3426113c3075SR. Parameswaran 		return overhead;
3427113c3075SR. Parameswaran 	}
3428113c3075SR. Parameswaran }
3429113c3075SR. Parameswaran EXPORT_SYMBOL(kernel_sock_ip_overhead);
3430