xref: /openbmc/linux/net/socket.c (revision 3023898b)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * NET		An implementation of the SOCKET network access protocol.
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Version:	@(#)socket.c	1.1.93	18/02/95
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * Authors:	Orest Zborowski, <obz@Kodak.COM>
702c30a84SJesper Juhl  *		Ross Biro
81da177e4SLinus Torvalds  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
91da177e4SLinus Torvalds  *
101da177e4SLinus Torvalds  * Fixes:
111da177e4SLinus Torvalds  *		Anonymous	:	NOTSOCK/BADF cleanup. Error fix in
121da177e4SLinus Torvalds  *					shutdown()
131da177e4SLinus Torvalds  *		Alan Cox	:	verify_area() fixes
141da177e4SLinus Torvalds  *		Alan Cox	:	Removed DDI
151da177e4SLinus Torvalds  *		Jonathan Kamens	:	SOCK_DGRAM reconnect bug
161da177e4SLinus Torvalds  *		Alan Cox	:	Moved a load of checks to the very
171da177e4SLinus Torvalds  *					top level.
181da177e4SLinus Torvalds  *		Alan Cox	:	Move address structures to/from user
191da177e4SLinus Torvalds  *					mode above the protocol layers.
201da177e4SLinus Torvalds  *		Rob Janssen	:	Allow 0 length sends.
211da177e4SLinus Torvalds  *		Alan Cox	:	Asynchronous I/O support (cribbed from the
221da177e4SLinus Torvalds  *					tty drivers).
231da177e4SLinus Torvalds  *		Niibe Yutaka	:	Asynchronous I/O for writes (4.4BSD style)
241da177e4SLinus Torvalds  *		Jeff Uphoff	:	Made max number of sockets command-line
251da177e4SLinus Torvalds  *					configurable.
261da177e4SLinus Torvalds  *		Matti Aarnio	:	Made the number of sockets dynamic,
271da177e4SLinus Torvalds  *					to be allocated when needed, and mr.
281da177e4SLinus Torvalds  *					Uphoff's max is used as max to be
291da177e4SLinus Torvalds  *					allowed to allocate.
301da177e4SLinus Torvalds  *		Linus		:	Argh. removed all the socket allocation
311da177e4SLinus Torvalds  *					altogether: it's in the inode now.
321da177e4SLinus Torvalds  *		Alan Cox	:	Made sock_alloc()/sock_release() public
331da177e4SLinus Torvalds  *					for NetROM and future kernel nfsd type
341da177e4SLinus Torvalds  *					stuff.
351da177e4SLinus Torvalds  *		Alan Cox	:	sendmsg/recvmsg basics.
361da177e4SLinus Torvalds  *		Tom Dyas	:	Export net symbols.
371da177e4SLinus Torvalds  *		Marcin Dalecki	:	Fixed problems with CONFIG_NET="n".
381da177e4SLinus Torvalds  *		Alan Cox	:	Added thread locking to sys_* calls
391da177e4SLinus Torvalds  *					for sockets. May have errors at the
401da177e4SLinus Torvalds  *					moment.
411da177e4SLinus Torvalds  *		Kevin Buhr	:	Fixed the dumb errors in the above.
421da177e4SLinus Torvalds  *		Andi Kleen	:	Some small cleanups, optimizations,
431da177e4SLinus Torvalds  *					and fixed a copy_from_user() bug.
441da177e4SLinus Torvalds  *		Tigran Aivazian	:	sys_send(args) calls sys_sendto(args, NULL, 0)
451da177e4SLinus Torvalds  *		Tigran Aivazian	:	Made listen(2) backlog sanity checks
461da177e4SLinus Torvalds  *					protocol-independent
471da177e4SLinus Torvalds  *
481da177e4SLinus Torvalds  *
491da177e4SLinus Torvalds  *		This program is free software; you can redistribute it and/or
501da177e4SLinus Torvalds  *		modify it under the terms of the GNU General Public License
511da177e4SLinus Torvalds  *		as published by the Free Software Foundation; either version
521da177e4SLinus Torvalds  *		2 of the License, or (at your option) any later version.
531da177e4SLinus Torvalds  *
541da177e4SLinus Torvalds  *
551da177e4SLinus Torvalds  *	This module is effectively the top level interface to the BSD socket
561da177e4SLinus Torvalds  *	paradigm.
571da177e4SLinus Torvalds  *
581da177e4SLinus Torvalds  *	Based upon Swansea University Computer Society NET3.039
591da177e4SLinus Torvalds  */
601da177e4SLinus Torvalds 
611da177e4SLinus Torvalds #include <linux/mm.h>
621da177e4SLinus Torvalds #include <linux/socket.h>
631da177e4SLinus Torvalds #include <linux/file.h>
641da177e4SLinus Torvalds #include <linux/net.h>
651da177e4SLinus Torvalds #include <linux/interrupt.h>
66aaca0bdcSUlrich Drepper #include <linux/thread_info.h>
6755737fdaSStephen Hemminger #include <linux/rcupdate.h>
681da177e4SLinus Torvalds #include <linux/netdevice.h>
691da177e4SLinus Torvalds #include <linux/proc_fs.h>
701da177e4SLinus Torvalds #include <linux/seq_file.h>
714a3e2f71SArjan van de Ven #include <linux/mutex.h>
721da177e4SLinus Torvalds #include <linux/if_bridge.h>
7320380731SArnaldo Carvalho de Melo #include <linux/if_frad.h>
7420380731SArnaldo Carvalho de Melo #include <linux/if_vlan.h>
75408eccceSDaniel Borkmann #include <linux/ptp_classify.h>
761da177e4SLinus Torvalds #include <linux/init.h>
771da177e4SLinus Torvalds #include <linux/poll.h>
781da177e4SLinus Torvalds #include <linux/cache.h>
791da177e4SLinus Torvalds #include <linux/module.h>
801da177e4SLinus Torvalds #include <linux/highmem.h>
811da177e4SLinus Torvalds #include <linux/mount.h>
821da177e4SLinus Torvalds #include <linux/security.h>
831da177e4SLinus Torvalds #include <linux/syscalls.h>
841da177e4SLinus Torvalds #include <linux/compat.h>
851da177e4SLinus Torvalds #include <linux/kmod.h>
863ec3b2fbSDavid Woodhouse #include <linux/audit.h>
87d86b5e0eSAdrian Bunk #include <linux/wireless.h>
881b8d7ae4SEric W. Biederman #include <linux/nsproxy.h>
891fd7317dSNick Black #include <linux/magic.h>
905a0e3ad6STejun Heo #include <linux/slab.h>
91600e1779SMasatake YAMATO #include <linux/xattr.h>
921da177e4SLinus Torvalds 
931da177e4SLinus Torvalds #include <asm/uaccess.h>
941da177e4SLinus Torvalds #include <asm/unistd.h>
951da177e4SLinus Torvalds 
961da177e4SLinus Torvalds #include <net/compat.h>
9787de87d5SDavid S. Miller #include <net/wext.h>
98f8451725SHerbert Xu #include <net/cls_cgroup.h>
991da177e4SLinus Torvalds 
1001da177e4SLinus Torvalds #include <net/sock.h>
1011da177e4SLinus Torvalds #include <linux/netfilter.h>
1021da177e4SLinus Torvalds 
1036b96018bSArnd Bergmann #include <linux/if_tun.h>
1046b96018bSArnd Bergmann #include <linux/ipv6_route.h>
1056b96018bSArnd Bergmann #include <linux/route.h>
1066b96018bSArnd Bergmann #include <linux/sockios.h>
1076b96018bSArnd Bergmann #include <linux/atalk.h>
108076bb0c8SEliezer Tamir #include <net/busy_poll.h>
109f24b9be5SWillem de Bruijn #include <linux/errqueue.h>
11006021292SEliezer Tamir 
111e0d1095aSCong Wang #ifdef CONFIG_NET_RX_BUSY_POLL
11264b0dc51SEliezer Tamir unsigned int sysctl_net_busy_read __read_mostly;
11364b0dc51SEliezer Tamir unsigned int sysctl_net_busy_poll __read_mostly;
11406021292SEliezer Tamir #endif
1156b96018bSArnd Bergmann 
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 
2901da177e4SLinus Torvalds static int 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);
2991da177e4SLinus Torvalds 	if (sock_inode_cachep == NULL)
3001da177e4SLinus Torvalds 		return -ENOMEM;
3011da177e4SLinus Torvalds 	return 0;
3021da177e4SLinus Torvalds }
3031da177e4SLinus Torvalds 
304b87221deSAlexey Dobriyan static const struct super_operations sockfs_ops = {
3051da177e4SLinus Torvalds 	.alloc_inode	= sock_alloc_inode,
3061da177e4SLinus Torvalds 	.destroy_inode	= sock_destroy_inode,
3071da177e4SLinus Torvalds 	.statfs		= simple_statfs,
3081da177e4SLinus Torvalds };
3091da177e4SLinus Torvalds 
310c23fbb6bSEric Dumazet /*
311c23fbb6bSEric Dumazet  * sockfs_dname() is called from d_path().
312c23fbb6bSEric Dumazet  */
313c23fbb6bSEric Dumazet static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen)
314c23fbb6bSEric Dumazet {
315c23fbb6bSEric Dumazet 	return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]",
316c5ef6035SDavid Howells 				d_inode(dentry)->i_ino);
317c23fbb6bSEric Dumazet }
318c23fbb6bSEric Dumazet 
3193ba13d17SAl Viro static const struct dentry_operations sockfs_dentry_operations = {
320c23fbb6bSEric Dumazet 	.d_dname  = sockfs_dname,
3211da177e4SLinus Torvalds };
3221da177e4SLinus Torvalds 
323bba0bd31SAndreas Gruenbacher static int sockfs_xattr_get(const struct xattr_handler *handler,
324bba0bd31SAndreas Gruenbacher 			    struct dentry *dentry, struct inode *inode,
325bba0bd31SAndreas Gruenbacher 			    const char *suffix, void *value, size_t size)
326bba0bd31SAndreas Gruenbacher {
327bba0bd31SAndreas Gruenbacher 	if (value) {
328bba0bd31SAndreas Gruenbacher 		if (dentry->d_name.len + 1 > size)
329bba0bd31SAndreas Gruenbacher 			return -ERANGE;
330bba0bd31SAndreas Gruenbacher 		memcpy(value, dentry->d_name.name, dentry->d_name.len + 1);
331bba0bd31SAndreas Gruenbacher 	}
332bba0bd31SAndreas Gruenbacher 	return dentry->d_name.len + 1;
333bba0bd31SAndreas Gruenbacher }
334bba0bd31SAndreas Gruenbacher 
335bba0bd31SAndreas Gruenbacher #define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname"
336bba0bd31SAndreas Gruenbacher #define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX)
337bba0bd31SAndreas Gruenbacher #define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1)
338bba0bd31SAndreas Gruenbacher 
339bba0bd31SAndreas Gruenbacher static const struct xattr_handler sockfs_xattr_handler = {
340bba0bd31SAndreas Gruenbacher 	.name = XATTR_NAME_SOCKPROTONAME,
341bba0bd31SAndreas Gruenbacher 	.get = sockfs_xattr_get,
342bba0bd31SAndreas Gruenbacher };
343bba0bd31SAndreas Gruenbacher 
344bba0bd31SAndreas Gruenbacher static const struct xattr_handler *sockfs_xattr_handlers[] = {
345bba0bd31SAndreas Gruenbacher 	&sockfs_xattr_handler,
346bba0bd31SAndreas Gruenbacher 	NULL
347bba0bd31SAndreas Gruenbacher };
348bba0bd31SAndreas Gruenbacher 
349c74a1cbbSAl Viro static struct dentry *sockfs_mount(struct file_system_type *fs_type,
350c74a1cbbSAl Viro 			 int flags, const char *dev_name, void *data)
351c74a1cbbSAl Viro {
352bba0bd31SAndreas Gruenbacher 	return mount_pseudo_xattr(fs_type, "socket:", &sockfs_ops,
353bba0bd31SAndreas Gruenbacher 				  sockfs_xattr_handlers,
354c74a1cbbSAl Viro 				  &sockfs_dentry_operations, SOCKFS_MAGIC);
355c74a1cbbSAl Viro }
356c74a1cbbSAl Viro 
357c74a1cbbSAl Viro static struct vfsmount *sock_mnt __read_mostly;
358c74a1cbbSAl Viro 
359c74a1cbbSAl Viro static struct file_system_type sock_fs_type = {
360c74a1cbbSAl Viro 	.name =		"sockfs",
361c74a1cbbSAl Viro 	.mount =	sockfs_mount,
362c74a1cbbSAl Viro 	.kill_sb =	kill_anon_super,
363c74a1cbbSAl Viro };
364c74a1cbbSAl Viro 
3651da177e4SLinus Torvalds /*
3661da177e4SLinus Torvalds  *	Obtains the first available file descriptor and sets it up for use.
3671da177e4SLinus Torvalds  *
36839d8c1b6SDavid S. Miller  *	These functions create file structures and maps them to fd space
36939d8c1b6SDavid S. Miller  *	of the current process. On success it returns file descriptor
3701da177e4SLinus Torvalds  *	and file struct implicitly stored in sock->file.
3711da177e4SLinus Torvalds  *	Note that another thread may close file descriptor before we return
3721da177e4SLinus Torvalds  *	from this function. We use the fact that now we do not refer
3731da177e4SLinus Torvalds  *	to socket after mapping. If one day we will need it, this
3741da177e4SLinus Torvalds  *	function will increment ref. count on file by 1.
3751da177e4SLinus Torvalds  *
3761da177e4SLinus Torvalds  *	In any case returned fd MAY BE not valid!
3771da177e4SLinus Torvalds  *	This race condition is unavoidable
3781da177e4SLinus Torvalds  *	with shared fd spaces, we cannot solve it inside kernel,
3791da177e4SLinus Torvalds  *	but we take care of internal coherence yet.
3801da177e4SLinus Torvalds  */
3811da177e4SLinus Torvalds 
382aab174f0SLinus Torvalds struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)
3831da177e4SLinus Torvalds {
3847cbe66b6SAl Viro 	struct qstr name = { .name = "" };
3852c48b9c4SAl Viro 	struct path path;
3867cbe66b6SAl Viro 	struct file *file;
3871da177e4SLinus Torvalds 
388600e1779SMasatake YAMATO 	if (dname) {
389600e1779SMasatake YAMATO 		name.name = dname;
390600e1779SMasatake YAMATO 		name.len = strlen(name.name);
391600e1779SMasatake YAMATO 	} else if (sock->sk) {
392600e1779SMasatake YAMATO 		name.name = sock->sk->sk_prot_creator->name;
393600e1779SMasatake YAMATO 		name.len = strlen(name.name);
394600e1779SMasatake YAMATO 	}
3954b936885SNick Piggin 	path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name);
39628407630SAl Viro 	if (unlikely(!path.dentry))
39728407630SAl Viro 		return ERR_PTR(-ENOMEM);
3982c48b9c4SAl Viro 	path.mnt = mntget(sock_mnt);
39939d8c1b6SDavid S. Miller 
4002c48b9c4SAl Viro 	d_instantiate(path.dentry, SOCK_INODE(sock));
401cc3808f8SAl Viro 
4022c48b9c4SAl Viro 	file = alloc_file(&path, FMODE_READ | FMODE_WRITE,
403cc3808f8SAl Viro 		  &socket_file_ops);
404b5ffe634SViresh Kumar 	if (IS_ERR(file)) {
405cc3808f8SAl Viro 		/* drop dentry, keep inode */
406c5ef6035SDavid Howells 		ihold(d_inode(path.dentry));
4072c48b9c4SAl Viro 		path_put(&path);
40839b65252SAnatol Pomozov 		return file;
409cc3808f8SAl Viro 	}
4101da177e4SLinus Torvalds 
4111da177e4SLinus Torvalds 	sock->file = file;
41277d27200SUlrich Drepper 	file->f_flags = O_RDWR | (flags & O_NONBLOCK);
41307dc3f07SBenjamin LaHaise 	file->private_data = sock;
41428407630SAl Viro 	return file;
4151da177e4SLinus Torvalds }
41656b31d1cSAl Viro EXPORT_SYMBOL(sock_alloc_file);
4171da177e4SLinus Torvalds 
41856b31d1cSAl Viro static int sock_map_fd(struct socket *sock, int flags)
41939d8c1b6SDavid S. Miller {
42039d8c1b6SDavid S. Miller 	struct file *newfile;
42128407630SAl Viro 	int fd = get_unused_fd_flags(flags);
42228407630SAl Viro 	if (unlikely(fd < 0))
4231da177e4SLinus Torvalds 		return fd;
4241da177e4SLinus Torvalds 
425aab174f0SLinus Torvalds 	newfile = sock_alloc_file(sock, flags, NULL);
42628407630SAl Viro 	if (likely(!IS_ERR(newfile))) {
4271da177e4SLinus Torvalds 		fd_install(fd, newfile);
4281da177e4SLinus Torvalds 		return fd;
4291da177e4SLinus Torvalds 	}
43028407630SAl Viro 
43128407630SAl Viro 	put_unused_fd(fd);
43228407630SAl Viro 	return PTR_ERR(newfile);
4331da177e4SLinus Torvalds }
4341da177e4SLinus Torvalds 
435406a3c63SJohn Fastabend struct socket *sock_from_file(struct file *file, int *err)
4366cb153caSBenjamin LaHaise {
4376cb153caSBenjamin LaHaise 	if (file->f_op == &socket_file_ops)
4386cb153caSBenjamin LaHaise 		return file->private_data;	/* set in sock_map_fd */
4396cb153caSBenjamin LaHaise 
4406cb153caSBenjamin LaHaise 	*err = -ENOTSOCK;
4416cb153caSBenjamin LaHaise 	return NULL;
4426cb153caSBenjamin LaHaise }
443406a3c63SJohn Fastabend EXPORT_SYMBOL(sock_from_file);
4446cb153caSBenjamin LaHaise 
4451da177e4SLinus Torvalds /**
4461da177e4SLinus Torvalds  *	sockfd_lookup - Go from a file number to its socket slot
4471da177e4SLinus Torvalds  *	@fd: file handle
4481da177e4SLinus Torvalds  *	@err: pointer to an error code return
4491da177e4SLinus Torvalds  *
4501da177e4SLinus Torvalds  *	The file handle passed in is locked and the socket it is bound
4511da177e4SLinus Torvalds  *	too is returned. If an error occurs the err pointer is overwritten
4521da177e4SLinus Torvalds  *	with a negative errno code and NULL is returned. The function checks
4531da177e4SLinus Torvalds  *	for both invalid handles and passing a handle which is not a socket.
4541da177e4SLinus Torvalds  *
4551da177e4SLinus Torvalds  *	On a success the socket object pointer is returned.
4561da177e4SLinus Torvalds  */
4571da177e4SLinus Torvalds 
4581da177e4SLinus Torvalds struct socket *sockfd_lookup(int fd, int *err)
4591da177e4SLinus Torvalds {
4601da177e4SLinus Torvalds 	struct file *file;
4611da177e4SLinus Torvalds 	struct socket *sock;
4621da177e4SLinus Torvalds 
46389bddce5SStephen Hemminger 	file = fget(fd);
46489bddce5SStephen Hemminger 	if (!file) {
4651da177e4SLinus Torvalds 		*err = -EBADF;
4661da177e4SLinus Torvalds 		return NULL;
4671da177e4SLinus Torvalds 	}
46889bddce5SStephen Hemminger 
4696cb153caSBenjamin LaHaise 	sock = sock_from_file(file, err);
4706cb153caSBenjamin LaHaise 	if (!sock)
4711da177e4SLinus Torvalds 		fput(file);
4726cb153caSBenjamin LaHaise 	return sock;
4731da177e4SLinus Torvalds }
474c6d409cfSEric Dumazet EXPORT_SYMBOL(sockfd_lookup);
4751da177e4SLinus Torvalds 
4766cb153caSBenjamin LaHaise static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
4776cb153caSBenjamin LaHaise {
47800e188efSAl Viro 	struct fd f = fdget(fd);
4796cb153caSBenjamin LaHaise 	struct socket *sock;
4806cb153caSBenjamin LaHaise 
4813672558cSHua Zhong 	*err = -EBADF;
48200e188efSAl Viro 	if (f.file) {
48300e188efSAl Viro 		sock = sock_from_file(f.file, err);
48400e188efSAl Viro 		if (likely(sock)) {
48500e188efSAl Viro 			*fput_needed = f.flags;
4861da177e4SLinus Torvalds 			return sock;
48700e188efSAl Viro 		}
48800e188efSAl Viro 		fdput(f);
4896cb153caSBenjamin LaHaise 	}
4906cb153caSBenjamin LaHaise 	return NULL;
4911da177e4SLinus Torvalds }
4921da177e4SLinus Torvalds 
493600e1779SMasatake YAMATO static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer,
494600e1779SMasatake YAMATO 				size_t size)
495600e1779SMasatake YAMATO {
496600e1779SMasatake YAMATO 	ssize_t len;
497600e1779SMasatake YAMATO 	ssize_t used = 0;
498600e1779SMasatake YAMATO 
499c5ef6035SDavid Howells 	len = security_inode_listsecurity(d_inode(dentry), buffer, size);
500600e1779SMasatake YAMATO 	if (len < 0)
501600e1779SMasatake YAMATO 		return len;
502600e1779SMasatake YAMATO 	used += len;
503600e1779SMasatake YAMATO 	if (buffer) {
504600e1779SMasatake YAMATO 		if (size < used)
505600e1779SMasatake YAMATO 			return -ERANGE;
506600e1779SMasatake YAMATO 		buffer += len;
507600e1779SMasatake YAMATO 	}
508600e1779SMasatake YAMATO 
509600e1779SMasatake YAMATO 	len = (XATTR_NAME_SOCKPROTONAME_LEN + 1);
510600e1779SMasatake YAMATO 	used += len;
511600e1779SMasatake YAMATO 	if (buffer) {
512600e1779SMasatake YAMATO 		if (size < used)
513600e1779SMasatake YAMATO 			return -ERANGE;
514600e1779SMasatake YAMATO 		memcpy(buffer, XATTR_NAME_SOCKPROTONAME, len);
515600e1779SMasatake YAMATO 		buffer += len;
516600e1779SMasatake YAMATO 	}
517600e1779SMasatake YAMATO 
518600e1779SMasatake YAMATO 	return used;
519600e1779SMasatake YAMATO }
520600e1779SMasatake YAMATO 
521600e1779SMasatake YAMATO static const struct inode_operations sockfs_inode_ops = {
522600e1779SMasatake YAMATO 	.listxattr = sockfs_listxattr,
523600e1779SMasatake YAMATO };
524600e1779SMasatake YAMATO 
5251da177e4SLinus Torvalds /**
5261da177e4SLinus Torvalds  *	sock_alloc	-	allocate a socket
5271da177e4SLinus Torvalds  *
5281da177e4SLinus Torvalds  *	Allocate a new inode and socket object. The two are bound together
5291da177e4SLinus Torvalds  *	and initialised. The socket is then returned. If we are out of inodes
5301da177e4SLinus Torvalds  *	NULL is returned.
5311da177e4SLinus Torvalds  */
5321da177e4SLinus Torvalds 
533f4a00aacSTom Herbert struct socket *sock_alloc(void)
5341da177e4SLinus Torvalds {
5351da177e4SLinus Torvalds 	struct inode *inode;
5361da177e4SLinus Torvalds 	struct socket *sock;
5371da177e4SLinus Torvalds 
538a209dfc7SEric Dumazet 	inode = new_inode_pseudo(sock_mnt->mnt_sb);
5391da177e4SLinus Torvalds 	if (!inode)
5401da177e4SLinus Torvalds 		return NULL;
5411da177e4SLinus Torvalds 
5421da177e4SLinus Torvalds 	sock = SOCKET_I(inode);
5431da177e4SLinus Torvalds 
54429a020d3SEric Dumazet 	kmemcheck_annotate_bitfield(sock, type);
54585fe4025SChristoph Hellwig 	inode->i_ino = get_next_ino();
5461da177e4SLinus Torvalds 	inode->i_mode = S_IFSOCK | S_IRWXUGO;
5478192b0c4SDavid Howells 	inode->i_uid = current_fsuid();
5488192b0c4SDavid Howells 	inode->i_gid = current_fsgid();
549600e1779SMasatake YAMATO 	inode->i_op = &sockfs_inode_ops;
5501da177e4SLinus Torvalds 
55119e8d69cSAlex Shi 	this_cpu_add(sockets_in_use, 1);
5521da177e4SLinus Torvalds 	return sock;
5531da177e4SLinus Torvalds }
554f4a00aacSTom Herbert EXPORT_SYMBOL(sock_alloc);
5551da177e4SLinus Torvalds 
5561da177e4SLinus Torvalds /**
5571da177e4SLinus Torvalds  *	sock_release	-	close a socket
5581da177e4SLinus Torvalds  *	@sock: socket to close
5591da177e4SLinus Torvalds  *
5601da177e4SLinus Torvalds  *	The socket is released from the protocol stack if it has a release
5611da177e4SLinus Torvalds  *	callback, and the inode is then released if the socket is bound to
5621da177e4SLinus Torvalds  *	an inode not a file.
5631da177e4SLinus Torvalds  */
5641da177e4SLinus Torvalds 
5651da177e4SLinus Torvalds void sock_release(struct socket *sock)
5661da177e4SLinus Torvalds {
5671da177e4SLinus Torvalds 	if (sock->ops) {
5681da177e4SLinus Torvalds 		struct module *owner = sock->ops->owner;
5691da177e4SLinus Torvalds 
5701da177e4SLinus Torvalds 		sock->ops->release(sock);
5711da177e4SLinus Torvalds 		sock->ops = NULL;
5721da177e4SLinus Torvalds 		module_put(owner);
5731da177e4SLinus Torvalds 	}
5741da177e4SLinus Torvalds 
575eaefd110SEric Dumazet 	if (rcu_dereference_protected(sock->wq, 1)->fasync_list)
5763410f22eSYang Yingliang 		pr_err("%s: fasync list not empty!\n", __func__);
5771da177e4SLinus Torvalds 
57819e8d69cSAlex Shi 	this_cpu_sub(sockets_in_use, 1);
5791da177e4SLinus Torvalds 	if (!sock->file) {
5801da177e4SLinus Torvalds 		iput(SOCK_INODE(sock));
5811da177e4SLinus Torvalds 		return;
5821da177e4SLinus Torvalds 	}
5831da177e4SLinus Torvalds 	sock->file = NULL;
5841da177e4SLinus Torvalds }
585c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_release);
5861da177e4SLinus Torvalds 
587c14ac945SSoheil Hassas Yeganeh void __sock_tx_timestamp(__u16 tsflags, __u8 *tx_flags)
58820d49473SPatrick Ohly {
589140c55d4SEric Dumazet 	u8 flags = *tx_flags;
590140c55d4SEric Dumazet 
591c14ac945SSoheil Hassas Yeganeh 	if (tsflags & SOF_TIMESTAMPING_TX_HARDWARE)
592140c55d4SEric Dumazet 		flags |= SKBTX_HW_TSTAMP;
593140c55d4SEric Dumazet 
594c14ac945SSoheil Hassas Yeganeh 	if (tsflags & SOF_TIMESTAMPING_TX_SOFTWARE)
595140c55d4SEric Dumazet 		flags |= SKBTX_SW_TSTAMP;
596140c55d4SEric Dumazet 
597c14ac945SSoheil Hassas Yeganeh 	if (tsflags & SOF_TIMESTAMPING_TX_SCHED)
598140c55d4SEric Dumazet 		flags |= SKBTX_SCHED_TSTAMP;
599140c55d4SEric Dumazet 
600140c55d4SEric Dumazet 	*tx_flags = flags;
60120d49473SPatrick Ohly }
60267cc0d40SWillem de Bruijn EXPORT_SYMBOL(__sock_tx_timestamp);
60320d49473SPatrick Ohly 
604d8725c86SAl Viro static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg)
6051da177e4SLinus Torvalds {
60601e97e65SAl Viro 	int ret = sock->ops->sendmsg(sock, msg, msg_data_left(msg));
607d8725c86SAl Viro 	BUG_ON(ret == -EIOCBQUEUED);
608d8725c86SAl Viro 	return ret;
6091da177e4SLinus Torvalds }
6100cf00c6fSGu Zheng 
611d8725c86SAl Viro int sock_sendmsg(struct socket *sock, struct msghdr *msg)
6120cf00c6fSGu Zheng {
613d8725c86SAl Viro 	int err = security_socket_sendmsg(sock, msg,
61401e97e65SAl Viro 					  msg_data_left(msg));
6151b784140SYing Xue 
616d8725c86SAl Viro 	return err ?: sock_sendmsg_nosec(sock, msg);
6170cf00c6fSGu Zheng }
618c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_sendmsg);
6191da177e4SLinus Torvalds 
6201da177e4SLinus Torvalds int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
6211da177e4SLinus Torvalds 		   struct kvec *vec, size_t num, size_t size)
6221da177e4SLinus Torvalds {
6236aa24814SAl Viro 	iov_iter_kvec(&msg->msg_iter, WRITE | ITER_KVEC, vec, num, size);
624d8725c86SAl Viro 	return sock_sendmsg(sock, msg);
6251da177e4SLinus Torvalds }
626c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendmsg);
6271da177e4SLinus Torvalds 
62892f37fd2SEric Dumazet /*
62992f37fd2SEric Dumazet  * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
63092f37fd2SEric Dumazet  */
63192f37fd2SEric Dumazet void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
63292f37fd2SEric Dumazet 	struct sk_buff *skb)
63392f37fd2SEric Dumazet {
63420d49473SPatrick Ohly 	int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
635f24b9be5SWillem de Bruijn 	struct scm_timestamping tss;
63620d49473SPatrick Ohly 	int empty = 1;
63720d49473SPatrick Ohly 	struct skb_shared_hwtstamps *shhwtstamps =
63820d49473SPatrick Ohly 		skb_hwtstamps(skb);
63992f37fd2SEric Dumazet 
64020d49473SPatrick Ohly 	/* Race occurred between timestamp enabling and packet
64120d49473SPatrick Ohly 	   receiving.  Fill in the current time for now. */
64220d49473SPatrick Ohly 	if (need_software_tstamp && skb->tstamp.tv64 == 0)
64320d49473SPatrick Ohly 		__net_timestamp(skb);
64420d49473SPatrick Ohly 
64520d49473SPatrick Ohly 	if (need_software_tstamp) {
64692f37fd2SEric Dumazet 		if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
64792f37fd2SEric Dumazet 			struct timeval tv;
64820d49473SPatrick Ohly 			skb_get_timestamp(skb, &tv);
64920d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP,
65020d49473SPatrick Ohly 				 sizeof(tv), &tv);
65192f37fd2SEric Dumazet 		} else {
652f24b9be5SWillem de Bruijn 			struct timespec ts;
653f24b9be5SWillem de Bruijn 			skb_get_timestampns(skb, &ts);
65420d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS,
655f24b9be5SWillem de Bruijn 				 sizeof(ts), &ts);
65692f37fd2SEric Dumazet 		}
65792f37fd2SEric Dumazet 	}
65892f37fd2SEric Dumazet 
659f24b9be5SWillem de Bruijn 	memset(&tss, 0, sizeof(tss));
660c199105dSWillem de Bruijn 	if ((sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE) &&
661f24b9be5SWillem de Bruijn 	    ktime_to_timespec_cond(skb->tstamp, tss.ts + 0))
66220d49473SPatrick Ohly 		empty = 0;
6634d276eb6SWillem de Bruijn 	if (shhwtstamps &&
664b9f40e21SWillem de Bruijn 	    (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
665f24b9be5SWillem de Bruijn 	    ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2))
66620d49473SPatrick Ohly 		empty = 0;
66720d49473SPatrick Ohly 	if (!empty)
66820d49473SPatrick Ohly 		put_cmsg(msg, SOL_SOCKET,
669f24b9be5SWillem de Bruijn 			 SCM_TIMESTAMPING, sizeof(tss), &tss);
67020d49473SPatrick Ohly }
6717c81fd8bSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
6727c81fd8bSArnaldo Carvalho de Melo 
6736e3e939fSJohannes Berg void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
6746e3e939fSJohannes Berg 	struct sk_buff *skb)
6756e3e939fSJohannes Berg {
6766e3e939fSJohannes Berg 	int ack;
6776e3e939fSJohannes Berg 
6786e3e939fSJohannes Berg 	if (!sock_flag(sk, SOCK_WIFI_STATUS))
6796e3e939fSJohannes Berg 		return;
6806e3e939fSJohannes Berg 	if (!skb->wifi_acked_valid)
6816e3e939fSJohannes Berg 		return;
6826e3e939fSJohannes Berg 
6836e3e939fSJohannes Berg 	ack = skb->wifi_acked;
6846e3e939fSJohannes Berg 
6856e3e939fSJohannes Berg 	put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack);
6866e3e939fSJohannes Berg }
6876e3e939fSJohannes Berg EXPORT_SYMBOL_GPL(__sock_recv_wifi_status);
6886e3e939fSJohannes Berg 
68911165f14Sstephen hemminger static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk,
69011165f14Sstephen hemminger 				   struct sk_buff *skb)
6913b885787SNeil Horman {
692744d5a3eSEyal Birger 	if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && SOCK_SKB_CB(skb)->dropcount)
6933b885787SNeil Horman 		put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL,
694744d5a3eSEyal Birger 			sizeof(__u32), &SOCK_SKB_CB(skb)->dropcount);
6953b885787SNeil Horman }
6963b885787SNeil Horman 
697767dd033SEric Dumazet void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
6983b885787SNeil Horman 	struct sk_buff *skb)
6993b885787SNeil Horman {
7003b885787SNeil Horman 	sock_recv_timestamp(msg, sk, skb);
7013b885787SNeil Horman 	sock_recv_drops(msg, sk, skb);
7023b885787SNeil Horman }
703767dd033SEric Dumazet EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops);
7043b885787SNeil Horman 
7051b784140SYing Xue static inline int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
7061b784140SYing Xue 				     int flags)
707a2e27255SArnaldo Carvalho de Melo {
7082da62906SAl Viro 	return sock->ops->recvmsg(sock, msg, msg_data_left(msg), flags);
7092da62906SAl Viro }
710a2e27255SArnaldo Carvalho de Melo 
7112da62906SAl Viro int sock_recvmsg(struct socket *sock, struct msghdr *msg, int flags)
7122da62906SAl Viro {
7132da62906SAl Viro 	int err = security_socket_recvmsg(sock, msg, msg_data_left(msg), flags);
7142da62906SAl Viro 
7152da62906SAl Viro 	return err ?: sock_recvmsg_nosec(sock, msg, flags);
7161da177e4SLinus Torvalds }
717c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_recvmsg);
7181da177e4SLinus Torvalds 
719c1249c0aSMartin Lucina /**
720c1249c0aSMartin Lucina  * kernel_recvmsg - Receive a message from a socket (kernel space)
721c1249c0aSMartin Lucina  * @sock:       The socket to receive the message from
722c1249c0aSMartin Lucina  * @msg:        Received message
723c1249c0aSMartin Lucina  * @vec:        Input s/g array for message data
724c1249c0aSMartin Lucina  * @num:        Size of input s/g array
725c1249c0aSMartin Lucina  * @size:       Number of bytes to read
726c1249c0aSMartin Lucina  * @flags:      Message flags (MSG_DONTWAIT, etc...)
727c1249c0aSMartin Lucina  *
728c1249c0aSMartin Lucina  * On return the msg structure contains the scatter/gather array passed in the
729c1249c0aSMartin Lucina  * vec argument. The array is modified so that it consists of the unfilled
730c1249c0aSMartin Lucina  * portion of the original array.
731c1249c0aSMartin Lucina  *
732c1249c0aSMartin Lucina  * The returned value is the total number of bytes received, or an error.
733c1249c0aSMartin Lucina  */
7341da177e4SLinus Torvalds int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
73589bddce5SStephen Hemminger 		   struct kvec *vec, size_t num, size_t size, int flags)
7361da177e4SLinus Torvalds {
7371da177e4SLinus Torvalds 	mm_segment_t oldfs = get_fs();
7381da177e4SLinus Torvalds 	int result;
7391da177e4SLinus Torvalds 
7406aa24814SAl Viro 	iov_iter_kvec(&msg->msg_iter, READ | ITER_KVEC, vec, num, size);
7411da177e4SLinus Torvalds 	set_fs(KERNEL_DS);
7422da62906SAl Viro 	result = sock_recvmsg(sock, msg, flags);
7431da177e4SLinus Torvalds 	set_fs(oldfs);
7441da177e4SLinus Torvalds 	return result;
7451da177e4SLinus Torvalds }
746c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_recvmsg);
7471da177e4SLinus Torvalds 
74820380731SArnaldo Carvalho de Melo static ssize_t sock_sendpage(struct file *file, struct page *page,
7491da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more)
7501da177e4SLinus Torvalds {
7511da177e4SLinus Torvalds 	struct socket *sock;
7521da177e4SLinus Torvalds 	int flags;
7531da177e4SLinus Torvalds 
754b69aee04SEric Dumazet 	sock = file->private_data;
7551da177e4SLinus Torvalds 
75635f9c09fSEric Dumazet 	flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
75735f9c09fSEric Dumazet 	/* more is a combination of MSG_MORE and MSG_SENDPAGE_NOTLAST */
75835f9c09fSEric Dumazet 	flags |= more;
7591da177e4SLinus Torvalds 
760e6949583SLinus Torvalds 	return kernel_sendpage(sock, page, offset, size, flags);
7611da177e4SLinus Torvalds }
7621da177e4SLinus Torvalds 
7639c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
7649c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
7659c55e01cSJens Axboe 				unsigned int flags)
7669c55e01cSJens Axboe {
7679c55e01cSJens Axboe 	struct socket *sock = file->private_data;
7689c55e01cSJens Axboe 
769997b37daSRémi Denis-Courmont 	if (unlikely(!sock->ops->splice_read))
770997b37daSRémi Denis-Courmont 		return -EINVAL;
771997b37daSRémi Denis-Courmont 
7729c55e01cSJens Axboe 	return sock->ops->splice_read(sock, ppos, pipe, len, flags);
7739c55e01cSJens Axboe }
7749c55e01cSJens Axboe 
7758ae5e030SAl Viro static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to)
776ce1d4d3eSChristoph Hellwig {
7776d652330SAl Viro 	struct file *file = iocb->ki_filp;
7786d652330SAl Viro 	struct socket *sock = file->private_data;
7790345f931Stadeusz.struk@intel.com 	struct msghdr msg = {.msg_iter = *to,
7800345f931Stadeusz.struk@intel.com 			     .msg_iocb = iocb};
7818ae5e030SAl Viro 	ssize_t res;
782ce1d4d3eSChristoph Hellwig 
7838ae5e030SAl Viro 	if (file->f_flags & O_NONBLOCK)
7848ae5e030SAl Viro 		msg.msg_flags = MSG_DONTWAIT;
7858ae5e030SAl Viro 
7868ae5e030SAl Viro 	if (iocb->ki_pos != 0)
787ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
788027445c3SBadari Pulavarty 
78966ee59afSChristoph Hellwig 	if (!iov_iter_count(to))	/* Match SYS5 behaviour */
790ce1d4d3eSChristoph Hellwig 		return 0;
791ce1d4d3eSChristoph Hellwig 
7922da62906SAl Viro 	res = sock_recvmsg(sock, &msg, msg.msg_flags);
7938ae5e030SAl Viro 	*to = msg.msg_iter;
7948ae5e030SAl Viro 	return res;
795ce1d4d3eSChristoph Hellwig }
796ce1d4d3eSChristoph Hellwig 
7978ae5e030SAl Viro static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from)
7981da177e4SLinus Torvalds {
7996d652330SAl Viro 	struct file *file = iocb->ki_filp;
8006d652330SAl Viro 	struct socket *sock = file->private_data;
8010345f931Stadeusz.struk@intel.com 	struct msghdr msg = {.msg_iter = *from,
8020345f931Stadeusz.struk@intel.com 			     .msg_iocb = iocb};
8038ae5e030SAl Viro 	ssize_t res;
8041da177e4SLinus Torvalds 
8058ae5e030SAl Viro 	if (iocb->ki_pos != 0)
806ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
807027445c3SBadari Pulavarty 
8088ae5e030SAl Viro 	if (file->f_flags & O_NONBLOCK)
8098ae5e030SAl Viro 		msg.msg_flags = MSG_DONTWAIT;
8108ae5e030SAl Viro 
8116d652330SAl Viro 	if (sock->type == SOCK_SEQPACKET)
8126d652330SAl Viro 		msg.msg_flags |= MSG_EOR;
8136d652330SAl Viro 
814d8725c86SAl Viro 	res = sock_sendmsg(sock, &msg);
8158ae5e030SAl Viro 	*from = msg.msg_iter;
8168ae5e030SAl Viro 	return res;
8171da177e4SLinus Torvalds }
8181da177e4SLinus Torvalds 
8191da177e4SLinus Torvalds /*
8201da177e4SLinus Torvalds  * Atomic setting of ioctl hooks to avoid race
8211da177e4SLinus Torvalds  * with module unload.
8221da177e4SLinus Torvalds  */
8231da177e4SLinus Torvalds 
8244a3e2f71SArjan van de Ven static DEFINE_MUTEX(br_ioctl_mutex);
825c6d409cfSEric Dumazet static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg);
8261da177e4SLinus Torvalds 
827881d966bSEric W. Biederman void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *))
8281da177e4SLinus Torvalds {
8294a3e2f71SArjan van de Ven 	mutex_lock(&br_ioctl_mutex);
8301da177e4SLinus Torvalds 	br_ioctl_hook = hook;
8314a3e2f71SArjan van de Ven 	mutex_unlock(&br_ioctl_mutex);
8321da177e4SLinus Torvalds }
8331da177e4SLinus Torvalds EXPORT_SYMBOL(brioctl_set);
8341da177e4SLinus Torvalds 
8354a3e2f71SArjan van de Ven static DEFINE_MUTEX(vlan_ioctl_mutex);
836881d966bSEric W. Biederman static int (*vlan_ioctl_hook) (struct net *, void __user *arg);
8371da177e4SLinus Torvalds 
838881d966bSEric W. Biederman void vlan_ioctl_set(int (*hook) (struct net *, void __user *))
8391da177e4SLinus Torvalds {
8404a3e2f71SArjan van de Ven 	mutex_lock(&vlan_ioctl_mutex);
8411da177e4SLinus Torvalds 	vlan_ioctl_hook = hook;
8424a3e2f71SArjan van de Ven 	mutex_unlock(&vlan_ioctl_mutex);
8431da177e4SLinus Torvalds }
8441da177e4SLinus Torvalds EXPORT_SYMBOL(vlan_ioctl_set);
8451da177e4SLinus Torvalds 
8464a3e2f71SArjan van de Ven static DEFINE_MUTEX(dlci_ioctl_mutex);
8471da177e4SLinus Torvalds static int (*dlci_ioctl_hook) (unsigned int, void __user *);
8481da177e4SLinus Torvalds 
8491da177e4SLinus Torvalds void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
8501da177e4SLinus Torvalds {
8514a3e2f71SArjan van de Ven 	mutex_lock(&dlci_ioctl_mutex);
8521da177e4SLinus Torvalds 	dlci_ioctl_hook = hook;
8534a3e2f71SArjan van de Ven 	mutex_unlock(&dlci_ioctl_mutex);
8541da177e4SLinus Torvalds }
8551da177e4SLinus Torvalds EXPORT_SYMBOL(dlci_ioctl_set);
8561da177e4SLinus Torvalds 
8576b96018bSArnd Bergmann static long sock_do_ioctl(struct net *net, struct socket *sock,
8586b96018bSArnd Bergmann 				 unsigned int cmd, unsigned long arg)
8596b96018bSArnd Bergmann {
8606b96018bSArnd Bergmann 	int err;
8616b96018bSArnd Bergmann 	void __user *argp = (void __user *)arg;
8626b96018bSArnd Bergmann 
8636b96018bSArnd Bergmann 	err = sock->ops->ioctl(sock, cmd, arg);
8646b96018bSArnd Bergmann 
8656b96018bSArnd Bergmann 	/*
8666b96018bSArnd Bergmann 	 * If this ioctl is unknown try to hand it down
8676b96018bSArnd Bergmann 	 * to the NIC driver.
8686b96018bSArnd Bergmann 	 */
8696b96018bSArnd Bergmann 	if (err == -ENOIOCTLCMD)
8706b96018bSArnd Bergmann 		err = dev_ioctl(net, cmd, argp);
8716b96018bSArnd Bergmann 
8726b96018bSArnd Bergmann 	return err;
8736b96018bSArnd Bergmann }
8746b96018bSArnd Bergmann 
8751da177e4SLinus Torvalds /*
8761da177e4SLinus Torvalds  *	With an ioctl, arg may well be a user mode pointer, but we don't know
8771da177e4SLinus Torvalds  *	what to do with it - that's up to the protocol still.
8781da177e4SLinus Torvalds  */
8791da177e4SLinus Torvalds 
8801da177e4SLinus Torvalds static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
8811da177e4SLinus Torvalds {
8821da177e4SLinus Torvalds 	struct socket *sock;
883881d966bSEric W. Biederman 	struct sock *sk;
8841da177e4SLinus Torvalds 	void __user *argp = (void __user *)arg;
8851da177e4SLinus Torvalds 	int pid, err;
886881d966bSEric W. Biederman 	struct net *net;
8871da177e4SLinus Torvalds 
888b69aee04SEric Dumazet 	sock = file->private_data;
889881d966bSEric W. Biederman 	sk = sock->sk;
8903b1e0a65SYOSHIFUJI Hideaki 	net = sock_net(sk);
8911da177e4SLinus Torvalds 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
892881d966bSEric W. Biederman 		err = dev_ioctl(net, cmd, argp);
8931da177e4SLinus Torvalds 	} else
8943d23e349SJohannes Berg #ifdef CONFIG_WEXT_CORE
8951da177e4SLinus Torvalds 	if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
896881d966bSEric W. Biederman 		err = dev_ioctl(net, cmd, argp);
8971da177e4SLinus Torvalds 	} else
8983d23e349SJohannes Berg #endif
8991da177e4SLinus Torvalds 		switch (cmd) {
9001da177e4SLinus Torvalds 		case FIOSETOWN:
9011da177e4SLinus Torvalds 		case SIOCSPGRP:
9021da177e4SLinus Torvalds 			err = -EFAULT;
9031da177e4SLinus Torvalds 			if (get_user(pid, (int __user *)argp))
9041da177e4SLinus Torvalds 				break;
905e0b93eddSJeff Layton 			f_setown(sock->file, pid, 1);
906e0b93eddSJeff Layton 			err = 0;
9071da177e4SLinus Torvalds 			break;
9081da177e4SLinus Torvalds 		case FIOGETOWN:
9091da177e4SLinus Torvalds 		case SIOCGPGRP:
910609d7fa9SEric W. Biederman 			err = put_user(f_getown(sock->file),
91189bddce5SStephen Hemminger 				       (int __user *)argp);
9121da177e4SLinus Torvalds 			break;
9131da177e4SLinus Torvalds 		case SIOCGIFBR:
9141da177e4SLinus Torvalds 		case SIOCSIFBR:
9151da177e4SLinus Torvalds 		case SIOCBRADDBR:
9161da177e4SLinus Torvalds 		case SIOCBRDELBR:
9171da177e4SLinus Torvalds 			err = -ENOPKG;
9181da177e4SLinus Torvalds 			if (!br_ioctl_hook)
9191da177e4SLinus Torvalds 				request_module("bridge");
9201da177e4SLinus Torvalds 
9214a3e2f71SArjan van de Ven 			mutex_lock(&br_ioctl_mutex);
9221da177e4SLinus Torvalds 			if (br_ioctl_hook)
923881d966bSEric W. Biederman 				err = br_ioctl_hook(net, cmd, argp);
9244a3e2f71SArjan van de Ven 			mutex_unlock(&br_ioctl_mutex);
9251da177e4SLinus Torvalds 			break;
9261da177e4SLinus Torvalds 		case SIOCGIFVLAN:
9271da177e4SLinus Torvalds 		case SIOCSIFVLAN:
9281da177e4SLinus Torvalds 			err = -ENOPKG;
9291da177e4SLinus Torvalds 			if (!vlan_ioctl_hook)
9301da177e4SLinus Torvalds 				request_module("8021q");
9311da177e4SLinus Torvalds 
9324a3e2f71SArjan van de Ven 			mutex_lock(&vlan_ioctl_mutex);
9331da177e4SLinus Torvalds 			if (vlan_ioctl_hook)
934881d966bSEric W. Biederman 				err = vlan_ioctl_hook(net, argp);
9354a3e2f71SArjan van de Ven 			mutex_unlock(&vlan_ioctl_mutex);
9361da177e4SLinus Torvalds 			break;
9371da177e4SLinus Torvalds 		case SIOCADDDLCI:
9381da177e4SLinus Torvalds 		case SIOCDELDLCI:
9391da177e4SLinus Torvalds 			err = -ENOPKG;
9401da177e4SLinus Torvalds 			if (!dlci_ioctl_hook)
9411da177e4SLinus Torvalds 				request_module("dlci");
9421da177e4SLinus Torvalds 
9434a3e2f71SArjan van de Ven 			mutex_lock(&dlci_ioctl_mutex);
9447512cbf6SPavel Emelyanov 			if (dlci_ioctl_hook)
9451da177e4SLinus Torvalds 				err = dlci_ioctl_hook(cmd, argp);
9464a3e2f71SArjan van de Ven 			mutex_unlock(&dlci_ioctl_mutex);
9471da177e4SLinus Torvalds 			break;
9481da177e4SLinus Torvalds 		default:
9496b96018bSArnd Bergmann 			err = sock_do_ioctl(net, sock, cmd, arg);
9501da177e4SLinus Torvalds 			break;
9511da177e4SLinus Torvalds 		}
9521da177e4SLinus Torvalds 	return err;
9531da177e4SLinus Torvalds }
9541da177e4SLinus Torvalds 
9551da177e4SLinus Torvalds int sock_create_lite(int family, int type, int protocol, struct socket **res)
9561da177e4SLinus Torvalds {
9571da177e4SLinus Torvalds 	int err;
9581da177e4SLinus Torvalds 	struct socket *sock = NULL;
9591da177e4SLinus Torvalds 
9601da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, 1);
9611da177e4SLinus Torvalds 	if (err)
9621da177e4SLinus Torvalds 		goto out;
9631da177e4SLinus Torvalds 
9641da177e4SLinus Torvalds 	sock = sock_alloc();
9651da177e4SLinus Torvalds 	if (!sock) {
9661da177e4SLinus Torvalds 		err = -ENOMEM;
9671da177e4SLinus Torvalds 		goto out;
9681da177e4SLinus Torvalds 	}
9691da177e4SLinus Torvalds 
9701da177e4SLinus Torvalds 	sock->type = type;
9717420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, 1);
9727420ed23SVenkat Yekkirala 	if (err)
9737420ed23SVenkat Yekkirala 		goto out_release;
9747420ed23SVenkat Yekkirala 
9751da177e4SLinus Torvalds out:
9761da177e4SLinus Torvalds 	*res = sock;
9771da177e4SLinus Torvalds 	return err;
9787420ed23SVenkat Yekkirala out_release:
9797420ed23SVenkat Yekkirala 	sock_release(sock);
9807420ed23SVenkat Yekkirala 	sock = NULL;
9817420ed23SVenkat Yekkirala 	goto out;
9821da177e4SLinus Torvalds }
983c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_lite);
9841da177e4SLinus Torvalds 
9851da177e4SLinus Torvalds /* No kernel lock held - perfect */
9861da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file, poll_table *wait)
9871da177e4SLinus Torvalds {
988cbf55001SEliezer Tamir 	unsigned int busy_flag = 0;
9891da177e4SLinus Torvalds 	struct socket *sock;
9901da177e4SLinus Torvalds 
9911da177e4SLinus Torvalds 	/*
9921da177e4SLinus Torvalds 	 *      We can't return errors to poll, so it's either yes or no.
9931da177e4SLinus Torvalds 	 */
994b69aee04SEric Dumazet 	sock = file->private_data;
9952d48d67fSEliezer Tamir 
996cbf55001SEliezer Tamir 	if (sk_can_busy_loop(sock->sk)) {
9972d48d67fSEliezer Tamir 		/* this socket can poll_ll so tell the system call */
998cbf55001SEliezer Tamir 		busy_flag = POLL_BUSY_LOOP;
9992d48d67fSEliezer Tamir 
10002d48d67fSEliezer Tamir 		/* once, only if requested by syscall */
1001cbf55001SEliezer Tamir 		if (wait && (wait->_key & POLL_BUSY_LOOP))
1002cbf55001SEliezer Tamir 			sk_busy_loop(sock->sk, 1);
10032d48d67fSEliezer Tamir 	}
10042d48d67fSEliezer Tamir 
1005cbf55001SEliezer Tamir 	return busy_flag | sock->ops->poll(file, sock, wait);
10061da177e4SLinus Torvalds }
10071da177e4SLinus Torvalds 
10081da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma)
10091da177e4SLinus Torvalds {
1010b69aee04SEric Dumazet 	struct socket *sock = file->private_data;
10111da177e4SLinus Torvalds 
10121da177e4SLinus Torvalds 	return sock->ops->mmap(file, sock, vma);
10131da177e4SLinus Torvalds }
10141da177e4SLinus Torvalds 
101520380731SArnaldo Carvalho de Melo static int sock_close(struct inode *inode, struct file *filp)
10161da177e4SLinus Torvalds {
10171da177e4SLinus Torvalds 	sock_release(SOCKET_I(inode));
10181da177e4SLinus Torvalds 	return 0;
10191da177e4SLinus Torvalds }
10201da177e4SLinus Torvalds 
10211da177e4SLinus Torvalds /*
10221da177e4SLinus Torvalds  *	Update the socket async list
10231da177e4SLinus Torvalds  *
10241da177e4SLinus Torvalds  *	Fasync_list locking strategy.
10251da177e4SLinus Torvalds  *
10261da177e4SLinus Torvalds  *	1. fasync_list is modified only under process context socket lock
10271da177e4SLinus Torvalds  *	   i.e. under semaphore.
10281da177e4SLinus Torvalds  *	2. fasync_list is used under read_lock(&sk->sk_callback_lock)
1029989a2979SEric Dumazet  *	   or under socket lock
10301da177e4SLinus Torvalds  */
10311da177e4SLinus Torvalds 
10321da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on)
10331da177e4SLinus Torvalds {
1034989a2979SEric Dumazet 	struct socket *sock = filp->private_data;
1035989a2979SEric Dumazet 	struct sock *sk = sock->sk;
1036eaefd110SEric Dumazet 	struct socket_wq *wq;
10371da177e4SLinus Torvalds 
1038989a2979SEric Dumazet 	if (sk == NULL)
10391da177e4SLinus Torvalds 		return -EINVAL;
10401da177e4SLinus Torvalds 
10411da177e4SLinus Torvalds 	lock_sock(sk);
10421e1d04e6SHannes Frederic Sowa 	wq = rcu_dereference_protected(sock->wq, lockdep_sock_is_held(sk));
1043eaefd110SEric Dumazet 	fasync_helper(fd, filp, on, &wq->fasync_list);
10441da177e4SLinus Torvalds 
1045eaefd110SEric Dumazet 	if (!wq->fasync_list)
1046bcdce719SEric Dumazet 		sock_reset_flag(sk, SOCK_FASYNC);
1047989a2979SEric Dumazet 	else
1048989a2979SEric Dumazet 		sock_set_flag(sk, SOCK_FASYNC);
10491da177e4SLinus Torvalds 
1050989a2979SEric Dumazet 	release_sock(sk);
10511da177e4SLinus Torvalds 	return 0;
10521da177e4SLinus Torvalds }
10531da177e4SLinus Torvalds 
1054ceb5d58bSEric Dumazet /* This function may be called only under rcu_lock */
10551da177e4SLinus Torvalds 
1056ceb5d58bSEric Dumazet int sock_wake_async(struct socket_wq *wq, int how, int band)
10571da177e4SLinus Torvalds {
1058ceb5d58bSEric Dumazet 	if (!wq || !wq->fasync_list)
1059ceb5d58bSEric Dumazet 		return -1;
106043815482SEric Dumazet 
106189bddce5SStephen Hemminger 	switch (how) {
10628d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_WAITD:
1063ceb5d58bSEric Dumazet 		if (test_bit(SOCKWQ_ASYNC_WAITDATA, &wq->flags))
10641da177e4SLinus Torvalds 			break;
10651da177e4SLinus Torvalds 		goto call_kill;
10668d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_SPACE:
1067ceb5d58bSEric Dumazet 		if (!test_and_clear_bit(SOCKWQ_ASYNC_NOSPACE, &wq->flags))
10681da177e4SLinus Torvalds 			break;
10691da177e4SLinus Torvalds 		/* fall through */
10708d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_IO:
10711da177e4SLinus Torvalds call_kill:
107243815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGIO, band);
10731da177e4SLinus Torvalds 		break;
10748d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_URG:
107543815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGURG, band);
10761da177e4SLinus Torvalds 	}
1077ceb5d58bSEric Dumazet 
10781da177e4SLinus Torvalds 	return 0;
10791da177e4SLinus Torvalds }
1080c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_wake_async);
10811da177e4SLinus Torvalds 
1082721db93aSPavel Emelyanov int __sock_create(struct net *net, int family, int type, int protocol,
108389bddce5SStephen Hemminger 			 struct socket **res, int kern)
10841da177e4SLinus Torvalds {
10851da177e4SLinus Torvalds 	int err;
10861da177e4SLinus Torvalds 	struct socket *sock;
108755737fdaSStephen Hemminger 	const struct net_proto_family *pf;
10881da177e4SLinus Torvalds 
10891da177e4SLinus Torvalds 	/*
10901da177e4SLinus Torvalds 	 *      Check protocol is in range
10911da177e4SLinus Torvalds 	 */
10921da177e4SLinus Torvalds 	if (family < 0 || family >= NPROTO)
10931da177e4SLinus Torvalds 		return -EAFNOSUPPORT;
10941da177e4SLinus Torvalds 	if (type < 0 || type >= SOCK_MAX)
10951da177e4SLinus Torvalds 		return -EINVAL;
10961da177e4SLinus Torvalds 
10971da177e4SLinus Torvalds 	/* Compatibility.
10981da177e4SLinus Torvalds 
10991da177e4SLinus Torvalds 	   This uglymoron is moved from INET layer to here to avoid
11001da177e4SLinus Torvalds 	   deadlock in module load.
11011da177e4SLinus Torvalds 	 */
11021da177e4SLinus Torvalds 	if (family == PF_INET && type == SOCK_PACKET) {
1103f3c98690Sliping.zhang 		pr_info_once("%s uses obsolete (PF_INET,SOCK_PACKET)\n",
110489bddce5SStephen Hemminger 			     current->comm);
11051da177e4SLinus Torvalds 		family = PF_PACKET;
11061da177e4SLinus Torvalds 	}
11071da177e4SLinus Torvalds 
11081da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, kern);
11091da177e4SLinus Torvalds 	if (err)
11101da177e4SLinus Torvalds 		return err;
11111da177e4SLinus Torvalds 
111255737fdaSStephen Hemminger 	/*
111355737fdaSStephen Hemminger 	 *	Allocate the socket and allow the family to set things up. if
111455737fdaSStephen Hemminger 	 *	the protocol is 0, the family is instructed to select an appropriate
111555737fdaSStephen Hemminger 	 *	default.
111655737fdaSStephen Hemminger 	 */
111755737fdaSStephen Hemminger 	sock = sock_alloc();
111855737fdaSStephen Hemminger 	if (!sock) {
1119e87cc472SJoe Perches 		net_warn_ratelimited("socket: no more sockets\n");
112055737fdaSStephen Hemminger 		return -ENFILE;	/* Not exactly a match, but its the
112155737fdaSStephen Hemminger 				   closest posix thing */
112255737fdaSStephen Hemminger 	}
112355737fdaSStephen Hemminger 
112455737fdaSStephen Hemminger 	sock->type = type;
112555737fdaSStephen Hemminger 
112695a5afcaSJohannes Berg #ifdef CONFIG_MODULES
11271da177e4SLinus Torvalds 	/* Attempt to load a protocol module if the find failed.
11281da177e4SLinus Torvalds 	 *
11291da177e4SLinus Torvalds 	 * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
11301da177e4SLinus Torvalds 	 * requested real, full-featured networking support upon configuration.
11311da177e4SLinus Torvalds 	 * Otherwise module support will break!
11321da177e4SLinus Torvalds 	 */
1133190683a9SEric Dumazet 	if (rcu_access_pointer(net_families[family]) == NULL)
11341da177e4SLinus Torvalds 		request_module("net-pf-%d", family);
11351da177e4SLinus Torvalds #endif
11361da177e4SLinus Torvalds 
113755737fdaSStephen Hemminger 	rcu_read_lock();
113855737fdaSStephen Hemminger 	pf = rcu_dereference(net_families[family]);
11391da177e4SLinus Torvalds 	err = -EAFNOSUPPORT;
114055737fdaSStephen Hemminger 	if (!pf)
114155737fdaSStephen Hemminger 		goto out_release;
11421da177e4SLinus Torvalds 
11431da177e4SLinus Torvalds 	/*
11441da177e4SLinus Torvalds 	 * We will call the ->create function, that possibly is in a loadable
11451da177e4SLinus Torvalds 	 * module, so we have to bump that loadable module refcnt first.
11461da177e4SLinus Torvalds 	 */
114755737fdaSStephen Hemminger 	if (!try_module_get(pf->owner))
11481da177e4SLinus Torvalds 		goto out_release;
11491da177e4SLinus Torvalds 
115055737fdaSStephen Hemminger 	/* Now protected by module ref count */
115155737fdaSStephen Hemminger 	rcu_read_unlock();
115255737fdaSStephen Hemminger 
11533f378b68SEric Paris 	err = pf->create(net, sock, protocol, kern);
115455737fdaSStephen Hemminger 	if (err < 0)
11551da177e4SLinus Torvalds 		goto out_module_put;
1156a79af59eSFrank Filz 
11571da177e4SLinus Torvalds 	/*
11581da177e4SLinus Torvalds 	 * Now to bump the refcnt of the [loadable] module that owns this
11591da177e4SLinus Torvalds 	 * socket at sock_release time we decrement its refcnt.
11601da177e4SLinus Torvalds 	 */
116155737fdaSStephen Hemminger 	if (!try_module_get(sock->ops->owner))
116255737fdaSStephen Hemminger 		goto out_module_busy;
116355737fdaSStephen Hemminger 
11641da177e4SLinus Torvalds 	/*
11651da177e4SLinus Torvalds 	 * Now that we're done with the ->create function, the [loadable]
11661da177e4SLinus Torvalds 	 * module can have its refcnt decremented
11671da177e4SLinus Torvalds 	 */
116855737fdaSStephen Hemminger 	module_put(pf->owner);
11697420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, kern);
11707420ed23SVenkat Yekkirala 	if (err)
11713b185525SHerbert Xu 		goto out_sock_release;
117255737fdaSStephen Hemminger 	*res = sock;
11731da177e4SLinus Torvalds 
117455737fdaSStephen Hemminger 	return 0;
117555737fdaSStephen Hemminger 
117655737fdaSStephen Hemminger out_module_busy:
117755737fdaSStephen Hemminger 	err = -EAFNOSUPPORT;
11781da177e4SLinus Torvalds out_module_put:
117955737fdaSStephen Hemminger 	sock->ops = NULL;
118055737fdaSStephen Hemminger 	module_put(pf->owner);
118155737fdaSStephen Hemminger out_sock_release:
11821da177e4SLinus Torvalds 	sock_release(sock);
118355737fdaSStephen Hemminger 	return err;
118455737fdaSStephen Hemminger 
118555737fdaSStephen Hemminger out_release:
118655737fdaSStephen Hemminger 	rcu_read_unlock();
118755737fdaSStephen Hemminger 	goto out_sock_release;
11881da177e4SLinus Torvalds }
1189721db93aSPavel Emelyanov EXPORT_SYMBOL(__sock_create);
11901da177e4SLinus Torvalds 
11911da177e4SLinus Torvalds int sock_create(int family, int type, int protocol, struct socket **res)
11921da177e4SLinus Torvalds {
11931b8d7ae4SEric W. Biederman 	return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
11941da177e4SLinus Torvalds }
1195c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create);
11961da177e4SLinus Torvalds 
1197eeb1bd5cSEric W. Biederman int sock_create_kern(struct net *net, int family, int type, int protocol, struct socket **res)
11981da177e4SLinus Torvalds {
1199eeb1bd5cSEric W. Biederman 	return __sock_create(net, family, type, protocol, res, 1);
12001da177e4SLinus Torvalds }
1201c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_kern);
12021da177e4SLinus Torvalds 
12033e0fa65fSHeiko Carstens SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
12041da177e4SLinus Torvalds {
12051da177e4SLinus Torvalds 	int retval;
12061da177e4SLinus Torvalds 	struct socket *sock;
1207a677a039SUlrich Drepper 	int flags;
1208a677a039SUlrich Drepper 
1209e38b36f3SUlrich Drepper 	/* Check the SOCK_* constants for consistency.  */
1210e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
1211e38b36f3SUlrich Drepper 	BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
1212e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);
1213e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);
1214e38b36f3SUlrich Drepper 
1215a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
121677d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1217a677a039SUlrich Drepper 		return -EINVAL;
1218a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
12191da177e4SLinus Torvalds 
1220aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1221aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1222aaca0bdcSUlrich Drepper 
12231da177e4SLinus Torvalds 	retval = sock_create(family, type, protocol, &sock);
12241da177e4SLinus Torvalds 	if (retval < 0)
12251da177e4SLinus Torvalds 		goto out;
12261da177e4SLinus Torvalds 
122777d27200SUlrich Drepper 	retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
12281da177e4SLinus Torvalds 	if (retval < 0)
12291da177e4SLinus Torvalds 		goto out_release;
12301da177e4SLinus Torvalds 
12311da177e4SLinus Torvalds out:
12321da177e4SLinus Torvalds 	/* It may be already another descriptor 8) Not kernel problem. */
12331da177e4SLinus Torvalds 	return retval;
12341da177e4SLinus Torvalds 
12351da177e4SLinus Torvalds out_release:
12361da177e4SLinus Torvalds 	sock_release(sock);
12371da177e4SLinus Torvalds 	return retval;
12381da177e4SLinus Torvalds }
12391da177e4SLinus Torvalds 
12401da177e4SLinus Torvalds /*
12411da177e4SLinus Torvalds  *	Create a pair of connected sockets.
12421da177e4SLinus Torvalds  */
12431da177e4SLinus Torvalds 
12443e0fa65fSHeiko Carstens SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
12453e0fa65fSHeiko Carstens 		int __user *, usockvec)
12461da177e4SLinus Torvalds {
12471da177e4SLinus Torvalds 	struct socket *sock1, *sock2;
12481da177e4SLinus Torvalds 	int fd1, fd2, err;
1249db349509SAl Viro 	struct file *newfile1, *newfile2;
1250a677a039SUlrich Drepper 	int flags;
1251a677a039SUlrich Drepper 
1252a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
125377d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1254a677a039SUlrich Drepper 		return -EINVAL;
1255a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
12561da177e4SLinus Torvalds 
1257aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1258aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1259aaca0bdcSUlrich Drepper 
12601da177e4SLinus Torvalds 	/*
12611da177e4SLinus Torvalds 	 * Obtain the first socket and check if the underlying protocol
12621da177e4SLinus Torvalds 	 * supports the socketpair call.
12631da177e4SLinus Torvalds 	 */
12641da177e4SLinus Torvalds 
12651da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock1);
12661da177e4SLinus Torvalds 	if (err < 0)
12671da177e4SLinus Torvalds 		goto out;
12681da177e4SLinus Torvalds 
12691da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock2);
12701da177e4SLinus Torvalds 	if (err < 0)
12711da177e4SLinus Torvalds 		goto out_release_1;
12721da177e4SLinus Torvalds 
12731da177e4SLinus Torvalds 	err = sock1->ops->socketpair(sock1, sock2);
12741da177e4SLinus Torvalds 	if (err < 0)
12751da177e4SLinus Torvalds 		goto out_release_both;
12761da177e4SLinus Torvalds 
127728407630SAl Viro 	fd1 = get_unused_fd_flags(flags);
1278bf3c23d1SDavid S. Miller 	if (unlikely(fd1 < 0)) {
1279bf3c23d1SDavid S. Miller 		err = fd1;
12801da177e4SLinus Torvalds 		goto out_release_both;
1281bf3c23d1SDavid S. Miller 	}
1282d73aa286SYann Droneaud 
128328407630SAl Viro 	fd2 = get_unused_fd_flags(flags);
1284198de4d7SAl Viro 	if (unlikely(fd2 < 0)) {
1285198de4d7SAl Viro 		err = fd2;
1286d73aa286SYann Droneaud 		goto out_put_unused_1;
128728407630SAl Viro 	}
128828407630SAl Viro 
1289aab174f0SLinus Torvalds 	newfile1 = sock_alloc_file(sock1, flags, NULL);
1290b5ffe634SViresh Kumar 	if (IS_ERR(newfile1)) {
129128407630SAl Viro 		err = PTR_ERR(newfile1);
1292d73aa286SYann Droneaud 		goto out_put_unused_both;
129328407630SAl Viro 	}
129428407630SAl Viro 
1295aab174f0SLinus Torvalds 	newfile2 = sock_alloc_file(sock2, flags, NULL);
129628407630SAl Viro 	if (IS_ERR(newfile2)) {
129728407630SAl Viro 		err = PTR_ERR(newfile2);
1298d73aa286SYann Droneaud 		goto out_fput_1;
1299db349509SAl Viro 	}
1300db349509SAl Viro 
1301d73aa286SYann Droneaud 	err = put_user(fd1, &usockvec[0]);
1302d73aa286SYann Droneaud 	if (err)
1303d73aa286SYann Droneaud 		goto out_fput_both;
1304d73aa286SYann Droneaud 
1305d73aa286SYann Droneaud 	err = put_user(fd2, &usockvec[1]);
1306d73aa286SYann Droneaud 	if (err)
1307d73aa286SYann Droneaud 		goto out_fput_both;
1308d73aa286SYann Droneaud 
1309157cf649SAl Viro 	audit_fd_pair(fd1, fd2);
1310d73aa286SYann Droneaud 
1311db349509SAl Viro 	fd_install(fd1, newfile1);
1312db349509SAl Viro 	fd_install(fd2, newfile2);
13131da177e4SLinus Torvalds 	/* fd1 and fd2 may be already another descriptors.
13141da177e4SLinus Torvalds 	 * Not kernel problem.
13151da177e4SLinus Torvalds 	 */
13161da177e4SLinus Torvalds 
13171da177e4SLinus Torvalds 	return 0;
13181da177e4SLinus Torvalds 
1319d73aa286SYann Droneaud out_fput_both:
1320d73aa286SYann Droneaud 	fput(newfile2);
1321d73aa286SYann Droneaud 	fput(newfile1);
1322d73aa286SYann Droneaud 	put_unused_fd(fd2);
1323d73aa286SYann Droneaud 	put_unused_fd(fd1);
1324d73aa286SYann Droneaud 	goto out;
13251da177e4SLinus Torvalds 
1326d73aa286SYann Droneaud out_fput_1:
1327d73aa286SYann Droneaud 	fput(newfile1);
1328d73aa286SYann Droneaud 	put_unused_fd(fd2);
1329d73aa286SYann Droneaud 	put_unused_fd(fd1);
1330d73aa286SYann Droneaud 	sock_release(sock2);
1331d73aa286SYann Droneaud 	goto out;
1332d73aa286SYann Droneaud 
1333d73aa286SYann Droneaud out_put_unused_both:
1334d73aa286SYann Droneaud 	put_unused_fd(fd2);
1335d73aa286SYann Droneaud out_put_unused_1:
1336d73aa286SYann Droneaud 	put_unused_fd(fd1);
13371da177e4SLinus Torvalds out_release_both:
13381da177e4SLinus Torvalds 	sock_release(sock2);
13391da177e4SLinus Torvalds out_release_1:
13401da177e4SLinus Torvalds 	sock_release(sock1);
13411da177e4SLinus Torvalds out:
13421da177e4SLinus Torvalds 	return err;
13431da177e4SLinus Torvalds }
13441da177e4SLinus Torvalds 
13451da177e4SLinus Torvalds /*
13461da177e4SLinus Torvalds  *	Bind a name to a socket. Nothing much to do here since it's
13471da177e4SLinus Torvalds  *	the protocol's responsibility to handle the local address.
13481da177e4SLinus Torvalds  *
13491da177e4SLinus Torvalds  *	We move the socket address to kernel space before we call
13501da177e4SLinus Torvalds  *	the protocol layer (having also checked the address is ok).
13511da177e4SLinus Torvalds  */
13521da177e4SLinus Torvalds 
135320f37034SHeiko Carstens SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
13541da177e4SLinus Torvalds {
13551da177e4SLinus Torvalds 	struct socket *sock;
1356230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
13576cb153caSBenjamin LaHaise 	int err, fput_needed;
13581da177e4SLinus Torvalds 
135989bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
136089bddce5SStephen Hemminger 	if (sock) {
136143db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(umyaddr, addrlen, &address);
136289bddce5SStephen Hemminger 		if (err >= 0) {
136389bddce5SStephen Hemminger 			err = security_socket_bind(sock,
1364230b1839SYOSHIFUJI Hideaki 						   (struct sockaddr *)&address,
136589bddce5SStephen Hemminger 						   addrlen);
13666cb153caSBenjamin LaHaise 			if (!err)
13676cb153caSBenjamin LaHaise 				err = sock->ops->bind(sock,
136889bddce5SStephen Hemminger 						      (struct sockaddr *)
1369230b1839SYOSHIFUJI Hideaki 						      &address, addrlen);
13701da177e4SLinus Torvalds 		}
13716cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
13721da177e4SLinus Torvalds 	}
13731da177e4SLinus Torvalds 	return err;
13741da177e4SLinus Torvalds }
13751da177e4SLinus Torvalds 
13761da177e4SLinus Torvalds /*
13771da177e4SLinus Torvalds  *	Perform a listen. Basically, we allow the protocol to do anything
13781da177e4SLinus Torvalds  *	necessary for a listen, and if that works, we mark the socket as
13791da177e4SLinus Torvalds  *	ready for listening.
13801da177e4SLinus Torvalds  */
13811da177e4SLinus Torvalds 
13823e0fa65fSHeiko Carstens SYSCALL_DEFINE2(listen, int, fd, int, backlog)
13831da177e4SLinus Torvalds {
13841da177e4SLinus Torvalds 	struct socket *sock;
13856cb153caSBenjamin LaHaise 	int err, fput_needed;
1386b8e1f9b5SPavel Emelyanov 	int somaxconn;
13871da177e4SLinus Torvalds 
138889bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
138989bddce5SStephen Hemminger 	if (sock) {
13908efa6e93SPavel Emelyanov 		somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
139195c96174SEric Dumazet 		if ((unsigned int)backlog > somaxconn)
1392b8e1f9b5SPavel Emelyanov 			backlog = somaxconn;
13931da177e4SLinus Torvalds 
13941da177e4SLinus Torvalds 		err = security_socket_listen(sock, backlog);
13956cb153caSBenjamin LaHaise 		if (!err)
13961da177e4SLinus Torvalds 			err = sock->ops->listen(sock, backlog);
13976cb153caSBenjamin LaHaise 
13986cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
13991da177e4SLinus Torvalds 	}
14001da177e4SLinus Torvalds 	return err;
14011da177e4SLinus Torvalds }
14021da177e4SLinus Torvalds 
14031da177e4SLinus Torvalds /*
14041da177e4SLinus Torvalds  *	For accept, we attempt to create a new socket, set up the link
14051da177e4SLinus Torvalds  *	with the client, wake up the client, then return the new
14061da177e4SLinus Torvalds  *	connected fd. We collect the address of the connector in kernel
14071da177e4SLinus Torvalds  *	space and move it to user at the very end. This is unclean because
14081da177e4SLinus Torvalds  *	we open the socket then return an error.
14091da177e4SLinus Torvalds  *
14101da177e4SLinus Torvalds  *	1003.1g adds the ability to recvmsg() to query connection pending
14111da177e4SLinus Torvalds  *	status to recvmsg. We need to add that support in a way thats
14121da177e4SLinus Torvalds  *	clean when we restucture accept also.
14131da177e4SLinus Torvalds  */
14141da177e4SLinus Torvalds 
141520f37034SHeiko Carstens SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
141620f37034SHeiko Carstens 		int __user *, upeer_addrlen, int, flags)
14171da177e4SLinus Torvalds {
14181da177e4SLinus Torvalds 	struct socket *sock, *newsock;
141939d8c1b6SDavid S. Miller 	struct file *newfile;
14206cb153caSBenjamin LaHaise 	int err, len, newfd, fput_needed;
1421230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
14221da177e4SLinus Torvalds 
142377d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1424aaca0bdcSUlrich Drepper 		return -EINVAL;
1425aaca0bdcSUlrich Drepper 
1426aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1427aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1428aaca0bdcSUlrich Drepper 
14296cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
14301da177e4SLinus Torvalds 	if (!sock)
14311da177e4SLinus Torvalds 		goto out;
14321da177e4SLinus Torvalds 
14331da177e4SLinus Torvalds 	err = -ENFILE;
1434c6d409cfSEric Dumazet 	newsock = sock_alloc();
1435c6d409cfSEric Dumazet 	if (!newsock)
14361da177e4SLinus Torvalds 		goto out_put;
14371da177e4SLinus Torvalds 
14381da177e4SLinus Torvalds 	newsock->type = sock->type;
14391da177e4SLinus Torvalds 	newsock->ops = sock->ops;
14401da177e4SLinus Torvalds 
14411da177e4SLinus Torvalds 	/*
14421da177e4SLinus Torvalds 	 * We don't need try_module_get here, as the listening socket (sock)
14431da177e4SLinus Torvalds 	 * has the protocol module (sock->ops->owner) held.
14441da177e4SLinus Torvalds 	 */
14451da177e4SLinus Torvalds 	__module_get(newsock->ops->owner);
14461da177e4SLinus Torvalds 
144728407630SAl Viro 	newfd = get_unused_fd_flags(flags);
144839d8c1b6SDavid S. Miller 	if (unlikely(newfd < 0)) {
144939d8c1b6SDavid S. Miller 		err = newfd;
14509a1875e6SDavid S. Miller 		sock_release(newsock);
14519a1875e6SDavid S. Miller 		goto out_put;
145239d8c1b6SDavid S. Miller 	}
1453aab174f0SLinus Torvalds 	newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name);
1454b5ffe634SViresh Kumar 	if (IS_ERR(newfile)) {
145528407630SAl Viro 		err = PTR_ERR(newfile);
145628407630SAl Viro 		put_unused_fd(newfd);
145728407630SAl Viro 		sock_release(newsock);
145828407630SAl Viro 		goto out_put;
145928407630SAl Viro 	}
146039d8c1b6SDavid S. Miller 
1461a79af59eSFrank Filz 	err = security_socket_accept(sock, newsock);
1462a79af59eSFrank Filz 	if (err)
146339d8c1b6SDavid S. Miller 		goto out_fd;
1464a79af59eSFrank Filz 
14651da177e4SLinus Torvalds 	err = sock->ops->accept(sock, newsock, sock->file->f_flags);
14661da177e4SLinus Torvalds 	if (err < 0)
146739d8c1b6SDavid S. Miller 		goto out_fd;
14681da177e4SLinus Torvalds 
14691da177e4SLinus Torvalds 	if (upeer_sockaddr) {
1470230b1839SYOSHIFUJI Hideaki 		if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
147189bddce5SStephen Hemminger 					  &len, 2) < 0) {
14721da177e4SLinus Torvalds 			err = -ECONNABORTED;
147339d8c1b6SDavid S. Miller 			goto out_fd;
14741da177e4SLinus Torvalds 		}
147543db362dSMaciej Żenczykowski 		err = move_addr_to_user(&address,
1476230b1839SYOSHIFUJI Hideaki 					len, upeer_sockaddr, upeer_addrlen);
14771da177e4SLinus Torvalds 		if (err < 0)
147839d8c1b6SDavid S. Miller 			goto out_fd;
14791da177e4SLinus Torvalds 	}
14801da177e4SLinus Torvalds 
14811da177e4SLinus Torvalds 	/* File flags are not inherited via accept() unlike another OSes. */
14821da177e4SLinus Torvalds 
148339d8c1b6SDavid S. Miller 	fd_install(newfd, newfile);
148439d8c1b6SDavid S. Miller 	err = newfd;
14851da177e4SLinus Torvalds 
14861da177e4SLinus Torvalds out_put:
14876cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
14881da177e4SLinus Torvalds out:
14891da177e4SLinus Torvalds 	return err;
149039d8c1b6SDavid S. Miller out_fd:
14919606a216SDavid S. Miller 	fput(newfile);
149239d8c1b6SDavid S. Miller 	put_unused_fd(newfd);
14931da177e4SLinus Torvalds 	goto out_put;
14941da177e4SLinus Torvalds }
14951da177e4SLinus Torvalds 
149620f37034SHeiko Carstens SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,
149720f37034SHeiko Carstens 		int __user *, upeer_addrlen)
1498aaca0bdcSUlrich Drepper {
1499de11defeSUlrich Drepper 	return sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0);
1500aaca0bdcSUlrich Drepper }
1501aaca0bdcSUlrich Drepper 
15021da177e4SLinus Torvalds /*
15031da177e4SLinus Torvalds  *	Attempt to connect to a socket with the server address.  The address
15041da177e4SLinus Torvalds  *	is in user space so we verify it is OK and move it to kernel space.
15051da177e4SLinus Torvalds  *
15061da177e4SLinus Torvalds  *	For 1003.1g we need to add clean support for a bind to AF_UNSPEC to
15071da177e4SLinus Torvalds  *	break bindings
15081da177e4SLinus Torvalds  *
15091da177e4SLinus Torvalds  *	NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and
15101da177e4SLinus Torvalds  *	other SEQPACKET protocols that take time to connect() as it doesn't
15111da177e4SLinus Torvalds  *	include the -EINPROGRESS status for such sockets.
15121da177e4SLinus Torvalds  */
15131da177e4SLinus Torvalds 
151420f37034SHeiko Carstens SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
151520f37034SHeiko Carstens 		int, addrlen)
15161da177e4SLinus Torvalds {
15171da177e4SLinus Torvalds 	struct socket *sock;
1518230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
15196cb153caSBenjamin LaHaise 	int err, fput_needed;
15201da177e4SLinus Torvalds 
15216cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
15221da177e4SLinus Torvalds 	if (!sock)
15231da177e4SLinus Torvalds 		goto out;
152443db362dSMaciej Żenczykowski 	err = move_addr_to_kernel(uservaddr, addrlen, &address);
15251da177e4SLinus Torvalds 	if (err < 0)
15261da177e4SLinus Torvalds 		goto out_put;
15271da177e4SLinus Torvalds 
152889bddce5SStephen Hemminger 	err =
1529230b1839SYOSHIFUJI Hideaki 	    security_socket_connect(sock, (struct sockaddr *)&address, addrlen);
15301da177e4SLinus Torvalds 	if (err)
15311da177e4SLinus Torvalds 		goto out_put;
15321da177e4SLinus Torvalds 
1533230b1839SYOSHIFUJI Hideaki 	err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,
15341da177e4SLinus Torvalds 				 sock->file->f_flags);
15351da177e4SLinus Torvalds out_put:
15366cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
15371da177e4SLinus Torvalds out:
15381da177e4SLinus Torvalds 	return err;
15391da177e4SLinus Torvalds }
15401da177e4SLinus Torvalds 
15411da177e4SLinus Torvalds /*
15421da177e4SLinus Torvalds  *	Get the local address ('name') of a socket object. Move the obtained
15431da177e4SLinus Torvalds  *	name to user space.
15441da177e4SLinus Torvalds  */
15451da177e4SLinus Torvalds 
154620f37034SHeiko Carstens SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
154720f37034SHeiko Carstens 		int __user *, usockaddr_len)
15481da177e4SLinus Torvalds {
15491da177e4SLinus Torvalds 	struct socket *sock;
1550230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
15516cb153caSBenjamin LaHaise 	int len, err, fput_needed;
15521da177e4SLinus Torvalds 
15536cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
15541da177e4SLinus Torvalds 	if (!sock)
15551da177e4SLinus Torvalds 		goto out;
15561da177e4SLinus Torvalds 
15571da177e4SLinus Torvalds 	err = security_socket_getsockname(sock);
15581da177e4SLinus Torvalds 	if (err)
15591da177e4SLinus Torvalds 		goto out_put;
15601da177e4SLinus Torvalds 
1561230b1839SYOSHIFUJI Hideaki 	err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0);
15621da177e4SLinus Torvalds 	if (err)
15631da177e4SLinus Torvalds 		goto out_put;
156443db362dSMaciej Żenczykowski 	err = move_addr_to_user(&address, len, usockaddr, usockaddr_len);
15651da177e4SLinus Torvalds 
15661da177e4SLinus Torvalds out_put:
15676cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
15681da177e4SLinus Torvalds out:
15691da177e4SLinus Torvalds 	return err;
15701da177e4SLinus Torvalds }
15711da177e4SLinus Torvalds 
15721da177e4SLinus Torvalds /*
15731da177e4SLinus Torvalds  *	Get the remote address ('name') of a socket object. Move the obtained
15741da177e4SLinus Torvalds  *	name to user space.
15751da177e4SLinus Torvalds  */
15761da177e4SLinus Torvalds 
157720f37034SHeiko Carstens SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
157820f37034SHeiko Carstens 		int __user *, usockaddr_len)
15791da177e4SLinus Torvalds {
15801da177e4SLinus Torvalds 	struct socket *sock;
1581230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
15826cb153caSBenjamin LaHaise 	int len, err, fput_needed;
15831da177e4SLinus Torvalds 
158489bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
158589bddce5SStephen Hemminger 	if (sock != NULL) {
15861da177e4SLinus Torvalds 		err = security_socket_getpeername(sock);
15871da177e4SLinus Torvalds 		if (err) {
15886cb153caSBenjamin LaHaise 			fput_light(sock->file, fput_needed);
15891da177e4SLinus Torvalds 			return err;
15901da177e4SLinus Torvalds 		}
15911da177e4SLinus Torvalds 
159289bddce5SStephen Hemminger 		err =
1593230b1839SYOSHIFUJI Hideaki 		    sock->ops->getname(sock, (struct sockaddr *)&address, &len,
159489bddce5SStephen Hemminger 				       1);
15951da177e4SLinus Torvalds 		if (!err)
159643db362dSMaciej Żenczykowski 			err = move_addr_to_user(&address, len, usockaddr,
159789bddce5SStephen Hemminger 						usockaddr_len);
15986cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
15991da177e4SLinus Torvalds 	}
16001da177e4SLinus Torvalds 	return err;
16011da177e4SLinus Torvalds }
16021da177e4SLinus Torvalds 
16031da177e4SLinus Torvalds /*
16041da177e4SLinus Torvalds  *	Send a datagram to a given address. We move the address into kernel
16051da177e4SLinus Torvalds  *	space and check the user space data area is readable before invoking
16061da177e4SLinus Torvalds  *	the protocol.
16071da177e4SLinus Torvalds  */
16081da177e4SLinus Torvalds 
16093e0fa65fSHeiko Carstens SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
161095c96174SEric Dumazet 		unsigned int, flags, struct sockaddr __user *, addr,
16113e0fa65fSHeiko Carstens 		int, addr_len)
16121da177e4SLinus Torvalds {
16131da177e4SLinus Torvalds 	struct socket *sock;
1614230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16151da177e4SLinus Torvalds 	int err;
16161da177e4SLinus Torvalds 	struct msghdr msg;
16171da177e4SLinus Torvalds 	struct iovec iov;
16186cb153caSBenjamin LaHaise 	int fput_needed;
16191da177e4SLinus Torvalds 
1620602bd0e9SAl Viro 	err = import_single_range(WRITE, buff, len, &iov, &msg.msg_iter);
1621602bd0e9SAl Viro 	if (unlikely(err))
1622602bd0e9SAl Viro 		return err;
1623de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1624de0fa95cSPavel Emelyanov 	if (!sock)
16254387ff75SDavid S. Miller 		goto out;
16266cb153caSBenjamin LaHaise 
16271da177e4SLinus Torvalds 	msg.msg_name = NULL;
16281da177e4SLinus Torvalds 	msg.msg_control = NULL;
16291da177e4SLinus Torvalds 	msg.msg_controllen = 0;
16301da177e4SLinus Torvalds 	msg.msg_namelen = 0;
16316cb153caSBenjamin LaHaise 	if (addr) {
163243db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(addr, addr_len, &address);
16331da177e4SLinus Torvalds 		if (err < 0)
16341da177e4SLinus Torvalds 			goto out_put;
1635230b1839SYOSHIFUJI Hideaki 		msg.msg_name = (struct sockaddr *)&address;
16361da177e4SLinus Torvalds 		msg.msg_namelen = addr_len;
16371da177e4SLinus Torvalds 	}
16381da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
16391da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
16401da177e4SLinus Torvalds 	msg.msg_flags = flags;
1641d8725c86SAl Viro 	err = sock_sendmsg(sock, &msg);
16421da177e4SLinus Torvalds 
16431da177e4SLinus Torvalds out_put:
1644de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
16454387ff75SDavid S. Miller out:
16461da177e4SLinus Torvalds 	return err;
16471da177e4SLinus Torvalds }
16481da177e4SLinus Torvalds 
16491da177e4SLinus Torvalds /*
16501da177e4SLinus Torvalds  *	Send a datagram down a socket.
16511da177e4SLinus Torvalds  */
16521da177e4SLinus Torvalds 
16533e0fa65fSHeiko Carstens SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len,
165495c96174SEric Dumazet 		unsigned int, flags)
16551da177e4SLinus Torvalds {
16561da177e4SLinus Torvalds 	return sys_sendto(fd, buff, len, flags, NULL, 0);
16571da177e4SLinus Torvalds }
16581da177e4SLinus Torvalds 
16591da177e4SLinus Torvalds /*
16601da177e4SLinus Torvalds  *	Receive a frame from the socket and optionally record the address of the
16611da177e4SLinus Torvalds  *	sender. We verify the buffers are writable and if needed move the
16621da177e4SLinus Torvalds  *	sender address from kernel to user space.
16631da177e4SLinus Torvalds  */
16641da177e4SLinus Torvalds 
16653e0fa65fSHeiko Carstens SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
166695c96174SEric Dumazet 		unsigned int, flags, struct sockaddr __user *, addr,
16673e0fa65fSHeiko Carstens 		int __user *, addr_len)
16681da177e4SLinus Torvalds {
16691da177e4SLinus Torvalds 	struct socket *sock;
16701da177e4SLinus Torvalds 	struct iovec iov;
16711da177e4SLinus Torvalds 	struct msghdr msg;
1672230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16731da177e4SLinus Torvalds 	int err, err2;
16746cb153caSBenjamin LaHaise 	int fput_needed;
16751da177e4SLinus Torvalds 
1676602bd0e9SAl Viro 	err = import_single_range(READ, ubuf, size, &iov, &msg.msg_iter);
1677602bd0e9SAl Viro 	if (unlikely(err))
1678602bd0e9SAl Viro 		return err;
1679de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
16801da177e4SLinus Torvalds 	if (!sock)
1681de0fa95cSPavel Emelyanov 		goto out;
16821da177e4SLinus Torvalds 
16831da177e4SLinus Torvalds 	msg.msg_control = NULL;
16841da177e4SLinus Torvalds 	msg.msg_controllen = 0;
1685f3d33426SHannes Frederic Sowa 	/* Save some cycles and don't copy the address if not needed */
1686f3d33426SHannes Frederic Sowa 	msg.msg_name = addr ? (struct sockaddr *)&address : NULL;
1687f3d33426SHannes Frederic Sowa 	/* We assume all kernel code knows the size of sockaddr_storage */
1688f3d33426SHannes Frederic Sowa 	msg.msg_namelen = 0;
1689130ed5d1Stadeusz.struk@intel.com 	msg.msg_iocb = NULL;
16901da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
16911da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
16922da62906SAl Viro 	err = sock_recvmsg(sock, &msg, flags);
16931da177e4SLinus Torvalds 
169489bddce5SStephen Hemminger 	if (err >= 0 && addr != NULL) {
169543db362dSMaciej Żenczykowski 		err2 = move_addr_to_user(&address,
1696230b1839SYOSHIFUJI Hideaki 					 msg.msg_namelen, addr, addr_len);
16971da177e4SLinus Torvalds 		if (err2 < 0)
16981da177e4SLinus Torvalds 			err = err2;
16991da177e4SLinus Torvalds 	}
1700de0fa95cSPavel Emelyanov 
1701de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
17024387ff75SDavid S. Miller out:
17031da177e4SLinus Torvalds 	return err;
17041da177e4SLinus Torvalds }
17051da177e4SLinus Torvalds 
17061da177e4SLinus Torvalds /*
17071da177e4SLinus Torvalds  *	Receive a datagram from a socket.
17081da177e4SLinus Torvalds  */
17091da177e4SLinus Torvalds 
1710b7c0ddf5SJan Glauber SYSCALL_DEFINE4(recv, int, fd, void __user *, ubuf, size_t, size,
1711b7c0ddf5SJan Glauber 		unsigned int, flags)
17121da177e4SLinus Torvalds {
17131da177e4SLinus Torvalds 	return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL);
17141da177e4SLinus Torvalds }
17151da177e4SLinus Torvalds 
17161da177e4SLinus Torvalds /*
17171da177e4SLinus Torvalds  *	Set a socket option. Because we don't know the option lengths we have
17181da177e4SLinus Torvalds  *	to pass the user mode parameter for the protocols to sort out.
17191da177e4SLinus Torvalds  */
17201da177e4SLinus Torvalds 
172120f37034SHeiko Carstens SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
172220f37034SHeiko Carstens 		char __user *, optval, int, optlen)
17231da177e4SLinus Torvalds {
17246cb153caSBenjamin LaHaise 	int err, fput_needed;
17251da177e4SLinus Torvalds 	struct socket *sock;
17261da177e4SLinus Torvalds 
17271da177e4SLinus Torvalds 	if (optlen < 0)
17281da177e4SLinus Torvalds 		return -EINVAL;
17291da177e4SLinus Torvalds 
173089bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
173189bddce5SStephen Hemminger 	if (sock != NULL) {
17321da177e4SLinus Torvalds 		err = security_socket_setsockopt(sock, level, optname);
17336cb153caSBenjamin LaHaise 		if (err)
17346cb153caSBenjamin LaHaise 			goto out_put;
17351da177e4SLinus Torvalds 
17361da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
173789bddce5SStephen Hemminger 			err =
173889bddce5SStephen Hemminger 			    sock_setsockopt(sock, level, optname, optval,
173989bddce5SStephen Hemminger 					    optlen);
17401da177e4SLinus Torvalds 		else
174189bddce5SStephen Hemminger 			err =
174289bddce5SStephen Hemminger 			    sock->ops->setsockopt(sock, level, optname, optval,
174389bddce5SStephen Hemminger 						  optlen);
17446cb153caSBenjamin LaHaise out_put:
17456cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
17461da177e4SLinus Torvalds 	}
17471da177e4SLinus Torvalds 	return err;
17481da177e4SLinus Torvalds }
17491da177e4SLinus Torvalds 
17501da177e4SLinus Torvalds /*
17511da177e4SLinus Torvalds  *	Get a socket option. Because we don't know the option lengths we have
17521da177e4SLinus Torvalds  *	to pass a user mode parameter for the protocols to sort out.
17531da177e4SLinus Torvalds  */
17541da177e4SLinus Torvalds 
175520f37034SHeiko Carstens SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
175620f37034SHeiko Carstens 		char __user *, optval, int __user *, optlen)
17571da177e4SLinus Torvalds {
17586cb153caSBenjamin LaHaise 	int err, fput_needed;
17591da177e4SLinus Torvalds 	struct socket *sock;
17601da177e4SLinus Torvalds 
176189bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
176289bddce5SStephen Hemminger 	if (sock != NULL) {
17636cb153caSBenjamin LaHaise 		err = security_socket_getsockopt(sock, level, optname);
17646cb153caSBenjamin LaHaise 		if (err)
17656cb153caSBenjamin LaHaise 			goto out_put;
17661da177e4SLinus Torvalds 
17671da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
176889bddce5SStephen Hemminger 			err =
176989bddce5SStephen Hemminger 			    sock_getsockopt(sock, level, optname, optval,
177089bddce5SStephen Hemminger 					    optlen);
17711da177e4SLinus Torvalds 		else
177289bddce5SStephen Hemminger 			err =
177389bddce5SStephen Hemminger 			    sock->ops->getsockopt(sock, level, optname, optval,
177489bddce5SStephen Hemminger 						  optlen);
17756cb153caSBenjamin LaHaise out_put:
17766cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
17771da177e4SLinus Torvalds 	}
17781da177e4SLinus Torvalds 	return err;
17791da177e4SLinus Torvalds }
17801da177e4SLinus Torvalds 
17811da177e4SLinus Torvalds /*
17821da177e4SLinus Torvalds  *	Shutdown a socket.
17831da177e4SLinus Torvalds  */
17841da177e4SLinus Torvalds 
1785754fe8d2SHeiko Carstens SYSCALL_DEFINE2(shutdown, int, fd, int, how)
17861da177e4SLinus Torvalds {
17876cb153caSBenjamin LaHaise 	int err, fput_needed;
17881da177e4SLinus Torvalds 	struct socket *sock;
17891da177e4SLinus Torvalds 
179089bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
179189bddce5SStephen Hemminger 	if (sock != NULL) {
17921da177e4SLinus Torvalds 		err = security_socket_shutdown(sock, how);
17936cb153caSBenjamin LaHaise 		if (!err)
17941da177e4SLinus Torvalds 			err = sock->ops->shutdown(sock, how);
17956cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
17961da177e4SLinus Torvalds 	}
17971da177e4SLinus Torvalds 	return err;
17981da177e4SLinus Torvalds }
17991da177e4SLinus Torvalds 
18001da177e4SLinus Torvalds /* A couple of helpful macros for getting the address of the 32/64 bit
18011da177e4SLinus Torvalds  * fields which are the same type (int / unsigned) on our platforms.
18021da177e4SLinus Torvalds  */
18031da177e4SLinus Torvalds #define COMPAT_MSG(msg, member)	((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member)
18041da177e4SLinus Torvalds #define COMPAT_NAMELEN(msg)	COMPAT_MSG(msg, msg_namelen)
18051da177e4SLinus Torvalds #define COMPAT_FLAGS(msg)	COMPAT_MSG(msg, msg_flags)
18061da177e4SLinus Torvalds 
1807c71d8ebeSTetsuo Handa struct used_address {
1808c71d8ebeSTetsuo Handa 	struct sockaddr_storage name;
1809c71d8ebeSTetsuo Handa 	unsigned int name_len;
1810c71d8ebeSTetsuo Handa };
1811c71d8ebeSTetsuo Handa 
1812da184284SAl Viro static int copy_msghdr_from_user(struct msghdr *kmsg,
181308adb7daSAl Viro 				 struct user_msghdr __user *umsg,
181408adb7daSAl Viro 				 struct sockaddr __user **save_addr,
181508adb7daSAl Viro 				 struct iovec **iov)
18161661bf36SDan Carpenter {
181708adb7daSAl Viro 	struct sockaddr __user *uaddr;
181808adb7daSAl Viro 	struct iovec __user *uiov;
1819c0371da6SAl Viro 	size_t nr_segs;
182008adb7daSAl Viro 	ssize_t err;
182108adb7daSAl Viro 
182208adb7daSAl Viro 	if (!access_ok(VERIFY_READ, umsg, sizeof(*umsg)) ||
182308adb7daSAl Viro 	    __get_user(uaddr, &umsg->msg_name) ||
182408adb7daSAl Viro 	    __get_user(kmsg->msg_namelen, &umsg->msg_namelen) ||
182508adb7daSAl Viro 	    __get_user(uiov, &umsg->msg_iov) ||
1826c0371da6SAl Viro 	    __get_user(nr_segs, &umsg->msg_iovlen) ||
182708adb7daSAl Viro 	    __get_user(kmsg->msg_control, &umsg->msg_control) ||
182808adb7daSAl Viro 	    __get_user(kmsg->msg_controllen, &umsg->msg_controllen) ||
182908adb7daSAl Viro 	    __get_user(kmsg->msg_flags, &umsg->msg_flags))
18301661bf36SDan Carpenter 		return -EFAULT;
1831dbb490b9SMatthew Leach 
183208adb7daSAl Viro 	if (!uaddr)
18336a2a2b3aSAni Sinha 		kmsg->msg_namelen = 0;
18346a2a2b3aSAni Sinha 
1835dbb490b9SMatthew Leach 	if (kmsg->msg_namelen < 0)
1836dbb490b9SMatthew Leach 		return -EINVAL;
1837dbb490b9SMatthew Leach 
18381661bf36SDan Carpenter 	if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
1839db31c55aSDan Carpenter 		kmsg->msg_namelen = sizeof(struct sockaddr_storage);
184008adb7daSAl Viro 
184108adb7daSAl Viro 	if (save_addr)
184208adb7daSAl Viro 		*save_addr = uaddr;
184308adb7daSAl Viro 
184408adb7daSAl Viro 	if (uaddr && kmsg->msg_namelen) {
184508adb7daSAl Viro 		if (!save_addr) {
184608adb7daSAl Viro 			err = move_addr_to_kernel(uaddr, kmsg->msg_namelen,
184708adb7daSAl Viro 						  kmsg->msg_name);
184808adb7daSAl Viro 			if (err < 0)
184908adb7daSAl Viro 				return err;
185008adb7daSAl Viro 		}
185108adb7daSAl Viro 	} else {
185208adb7daSAl Viro 		kmsg->msg_name = NULL;
185308adb7daSAl Viro 		kmsg->msg_namelen = 0;
185408adb7daSAl Viro 	}
185508adb7daSAl Viro 
1856c0371da6SAl Viro 	if (nr_segs > UIO_MAXIOV)
185708adb7daSAl Viro 		return -EMSGSIZE;
185808adb7daSAl Viro 
18590345f931Stadeusz.struk@intel.com 	kmsg->msg_iocb = NULL;
18600345f931Stadeusz.struk@intel.com 
1861da184284SAl Viro 	return import_iovec(save_addr ? READ : WRITE, uiov, nr_segs,
1862da184284SAl Viro 			    UIO_FASTIOV, iov, &kmsg->msg_iter);
18631661bf36SDan Carpenter }
18641661bf36SDan Carpenter 
1865666547ffSAl Viro static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
186695c96174SEric Dumazet 			 struct msghdr *msg_sys, unsigned int flags,
186728a94d8fSTom Herbert 			 struct used_address *used_address,
186828a94d8fSTom Herbert 			 unsigned int allowed_msghdr_flags)
18691da177e4SLinus Torvalds {
187089bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
187189bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
1872230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
18731da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
1874b9d717a7SAlex Williamson 	unsigned char ctl[sizeof(struct cmsghdr) + 20]
1875b9d717a7SAlex Williamson 	    __attribute__ ((aligned(sizeof(__kernel_size_t))));
1876b9d717a7SAlex Williamson 	/* 20 is size of ipv6_pktinfo */
18771da177e4SLinus Torvalds 	unsigned char *ctl_buf = ctl;
1878d8725c86SAl Viro 	int ctl_len;
187908adb7daSAl Viro 	ssize_t err;
18801da177e4SLinus Torvalds 
188108adb7daSAl Viro 	msg_sys->msg_name = &address;
18821da177e4SLinus Torvalds 
188308449320SAl Viro 	if (MSG_CMSG_COMPAT & flags)
188408adb7daSAl Viro 		err = get_compat_msghdr(msg_sys, msg_compat, NULL, &iov);
188508449320SAl Viro 	else
188608adb7daSAl Viro 		err = copy_msghdr_from_user(msg_sys, msg, NULL, &iov);
18871da177e4SLinus Torvalds 	if (err < 0)
1888da184284SAl Viro 		return err;
18891da177e4SLinus Torvalds 
18901da177e4SLinus Torvalds 	err = -ENOBUFS;
18911da177e4SLinus Torvalds 
1892228e548eSAnton Blanchard 	if (msg_sys->msg_controllen > INT_MAX)
18931da177e4SLinus Torvalds 		goto out_freeiov;
189428a94d8fSTom Herbert 	flags |= (msg_sys->msg_flags & allowed_msghdr_flags);
1895228e548eSAnton Blanchard 	ctl_len = msg_sys->msg_controllen;
18961da177e4SLinus Torvalds 	if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
189789bddce5SStephen Hemminger 		err =
1898228e548eSAnton Blanchard 		    cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl,
189989bddce5SStephen Hemminger 						     sizeof(ctl));
19001da177e4SLinus Torvalds 		if (err)
19011da177e4SLinus Torvalds 			goto out_freeiov;
1902228e548eSAnton Blanchard 		ctl_buf = msg_sys->msg_control;
1903228e548eSAnton Blanchard 		ctl_len = msg_sys->msg_controllen;
19041da177e4SLinus Torvalds 	} else if (ctl_len) {
190589bddce5SStephen Hemminger 		if (ctl_len > sizeof(ctl)) {
19061da177e4SLinus Torvalds 			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
19071da177e4SLinus Torvalds 			if (ctl_buf == NULL)
19081da177e4SLinus Torvalds 				goto out_freeiov;
19091da177e4SLinus Torvalds 		}
19101da177e4SLinus Torvalds 		err = -EFAULT;
19111da177e4SLinus Torvalds 		/*
1912228e548eSAnton Blanchard 		 * Careful! Before this, msg_sys->msg_control contains a user pointer.
19131da177e4SLinus Torvalds 		 * Afterwards, it will be a kernel pointer. Thus the compiler-assisted
19141da177e4SLinus Torvalds 		 * checking falls down on this.
19151da177e4SLinus Torvalds 		 */
1916fb8621bbSNamhyung Kim 		if (copy_from_user(ctl_buf,
1917228e548eSAnton Blanchard 				   (void __user __force *)msg_sys->msg_control,
191889bddce5SStephen Hemminger 				   ctl_len))
19191da177e4SLinus Torvalds 			goto out_freectl;
1920228e548eSAnton Blanchard 		msg_sys->msg_control = ctl_buf;
19211da177e4SLinus Torvalds 	}
1922228e548eSAnton Blanchard 	msg_sys->msg_flags = flags;
19231da177e4SLinus Torvalds 
19241da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
1925228e548eSAnton Blanchard 		msg_sys->msg_flags |= MSG_DONTWAIT;
1926c71d8ebeSTetsuo Handa 	/*
1927c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and current destination address is same as
1928c71d8ebeSTetsuo Handa 	 * previously succeeded address, omit asking LSM's decision.
1929c71d8ebeSTetsuo Handa 	 * used_address->name_len is initialized to UINT_MAX so that the first
1930c71d8ebeSTetsuo Handa 	 * destination address never matches.
1931c71d8ebeSTetsuo Handa 	 */
1932bc909d9dSMathieu Desnoyers 	if (used_address && msg_sys->msg_name &&
1933bc909d9dSMathieu Desnoyers 	    used_address->name_len == msg_sys->msg_namelen &&
1934bc909d9dSMathieu Desnoyers 	    !memcmp(&used_address->name, msg_sys->msg_name,
1935c71d8ebeSTetsuo Handa 		    used_address->name_len)) {
1936d8725c86SAl Viro 		err = sock_sendmsg_nosec(sock, msg_sys);
1937c71d8ebeSTetsuo Handa 		goto out_freectl;
1938c71d8ebeSTetsuo Handa 	}
1939d8725c86SAl Viro 	err = sock_sendmsg(sock, msg_sys);
1940c71d8ebeSTetsuo Handa 	/*
1941c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and sending to current destination address was
1942c71d8ebeSTetsuo Handa 	 * successful, remember it.
1943c71d8ebeSTetsuo Handa 	 */
1944c71d8ebeSTetsuo Handa 	if (used_address && err >= 0) {
1945c71d8ebeSTetsuo Handa 		used_address->name_len = msg_sys->msg_namelen;
1946bc909d9dSMathieu Desnoyers 		if (msg_sys->msg_name)
1947bc909d9dSMathieu Desnoyers 			memcpy(&used_address->name, msg_sys->msg_name,
1948c71d8ebeSTetsuo Handa 			       used_address->name_len);
1949c71d8ebeSTetsuo Handa 	}
19501da177e4SLinus Torvalds 
19511da177e4SLinus Torvalds out_freectl:
19521da177e4SLinus Torvalds 	if (ctl_buf != ctl)
19531da177e4SLinus Torvalds 		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
19541da177e4SLinus Torvalds out_freeiov:
1955a74e9106SEric Dumazet 	kfree(iov);
1956228e548eSAnton Blanchard 	return err;
1957228e548eSAnton Blanchard }
1958228e548eSAnton Blanchard 
1959228e548eSAnton Blanchard /*
1960228e548eSAnton Blanchard  *	BSD sendmsg interface
1961228e548eSAnton Blanchard  */
1962228e548eSAnton Blanchard 
1963666547ffSAl Viro long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned flags)
1964228e548eSAnton Blanchard {
1965228e548eSAnton Blanchard 	int fput_needed, err;
1966228e548eSAnton Blanchard 	struct msghdr msg_sys;
19671be374a0SAndy Lutomirski 	struct socket *sock;
1968228e548eSAnton Blanchard 
19691be374a0SAndy Lutomirski 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1970228e548eSAnton Blanchard 	if (!sock)
1971228e548eSAnton Blanchard 		goto out;
1972228e548eSAnton Blanchard 
197328a94d8fSTom Herbert 	err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL, 0);
1974228e548eSAnton Blanchard 
19756cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
19761da177e4SLinus Torvalds out:
19771da177e4SLinus Torvalds 	return err;
19781da177e4SLinus Torvalds }
19791da177e4SLinus Torvalds 
1980666547ffSAl Viro SYSCALL_DEFINE3(sendmsg, int, fd, struct user_msghdr __user *, msg, unsigned int, flags)
1981a7526eb5SAndy Lutomirski {
1982a7526eb5SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
1983a7526eb5SAndy Lutomirski 		return -EINVAL;
1984a7526eb5SAndy Lutomirski 	return __sys_sendmsg(fd, msg, flags);
1985a7526eb5SAndy Lutomirski }
1986a7526eb5SAndy Lutomirski 
1987228e548eSAnton Blanchard /*
1988228e548eSAnton Blanchard  *	Linux sendmmsg interface
1989228e548eSAnton Blanchard  */
1990228e548eSAnton Blanchard 
1991228e548eSAnton Blanchard int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
1992228e548eSAnton Blanchard 		   unsigned int flags)
1993228e548eSAnton Blanchard {
1994228e548eSAnton Blanchard 	int fput_needed, err, datagrams;
1995228e548eSAnton Blanchard 	struct socket *sock;
1996228e548eSAnton Blanchard 	struct mmsghdr __user *entry;
1997228e548eSAnton Blanchard 	struct compat_mmsghdr __user *compat_entry;
1998228e548eSAnton Blanchard 	struct msghdr msg_sys;
1999c71d8ebeSTetsuo Handa 	struct used_address used_address;
2000f092276dSTom Herbert 	unsigned int oflags = flags;
2001228e548eSAnton Blanchard 
200298382f41SAnton Blanchard 	if (vlen > UIO_MAXIOV)
200398382f41SAnton Blanchard 		vlen = UIO_MAXIOV;
2004228e548eSAnton Blanchard 
2005228e548eSAnton Blanchard 	datagrams = 0;
2006228e548eSAnton Blanchard 
2007228e548eSAnton Blanchard 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2008228e548eSAnton Blanchard 	if (!sock)
2009228e548eSAnton Blanchard 		return err;
2010228e548eSAnton Blanchard 
2011c71d8ebeSTetsuo Handa 	used_address.name_len = UINT_MAX;
2012228e548eSAnton Blanchard 	entry = mmsg;
2013228e548eSAnton Blanchard 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2014728ffb86SAnton Blanchard 	err = 0;
2015f092276dSTom Herbert 	flags |= MSG_BATCH;
2016228e548eSAnton Blanchard 
2017228e548eSAnton Blanchard 	while (datagrams < vlen) {
2018f092276dSTom Herbert 		if (datagrams == vlen - 1)
2019f092276dSTom Herbert 			flags = oflags;
2020f092276dSTom Herbert 
2021228e548eSAnton Blanchard 		if (MSG_CMSG_COMPAT & flags) {
2022666547ffSAl Viro 			err = ___sys_sendmsg(sock, (struct user_msghdr __user *)compat_entry,
202328a94d8fSTom Herbert 					     &msg_sys, flags, &used_address, MSG_EOR);
2024228e548eSAnton Blanchard 			if (err < 0)
2025228e548eSAnton Blanchard 				break;
2026228e548eSAnton Blanchard 			err = __put_user(err, &compat_entry->msg_len);
2027228e548eSAnton Blanchard 			++compat_entry;
2028228e548eSAnton Blanchard 		} else {
2029a7526eb5SAndy Lutomirski 			err = ___sys_sendmsg(sock,
2030666547ffSAl Viro 					     (struct user_msghdr __user *)entry,
203128a94d8fSTom Herbert 					     &msg_sys, flags, &used_address, MSG_EOR);
2032228e548eSAnton Blanchard 			if (err < 0)
2033228e548eSAnton Blanchard 				break;
2034228e548eSAnton Blanchard 			err = put_user(err, &entry->msg_len);
2035228e548eSAnton Blanchard 			++entry;
2036228e548eSAnton Blanchard 		}
2037228e548eSAnton Blanchard 
2038228e548eSAnton Blanchard 		if (err)
2039228e548eSAnton Blanchard 			break;
2040228e548eSAnton Blanchard 		++datagrams;
20413023898bSSoheil Hassas Yeganeh 		if (msg_data_left(&msg_sys))
20423023898bSSoheil Hassas Yeganeh 			break;
2043a78cb84cSEric Dumazet 		cond_resched();
2044228e548eSAnton Blanchard 	}
2045228e548eSAnton Blanchard 
2046228e548eSAnton Blanchard 	fput_light(sock->file, fput_needed);
2047228e548eSAnton Blanchard 
2048728ffb86SAnton Blanchard 	/* We only return an error if no datagrams were able to be sent */
2049728ffb86SAnton Blanchard 	if (datagrams != 0)
2050228e548eSAnton Blanchard 		return datagrams;
2051228e548eSAnton Blanchard 
2052228e548eSAnton Blanchard 	return err;
2053228e548eSAnton Blanchard }
2054228e548eSAnton Blanchard 
2055228e548eSAnton Blanchard SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
2056228e548eSAnton Blanchard 		unsigned int, vlen, unsigned int, flags)
2057228e548eSAnton Blanchard {
20581be374a0SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
20591be374a0SAndy Lutomirski 		return -EINVAL;
2060228e548eSAnton Blanchard 	return __sys_sendmmsg(fd, mmsg, vlen, flags);
2061228e548eSAnton Blanchard }
2062228e548eSAnton Blanchard 
2063666547ffSAl Viro static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg,
206495c96174SEric Dumazet 			 struct msghdr *msg_sys, unsigned int flags, int nosec)
20651da177e4SLinus Torvalds {
206689bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
206789bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
20681da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV];
20691da177e4SLinus Torvalds 	struct iovec *iov = iovstack;
20701da177e4SLinus Torvalds 	unsigned long cmsg_ptr;
20712da62906SAl Viro 	int len;
207208adb7daSAl Viro 	ssize_t err;
20731da177e4SLinus Torvalds 
20741da177e4SLinus Torvalds 	/* kernel mode address */
2075230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage addr;
20761da177e4SLinus Torvalds 
20771da177e4SLinus Torvalds 	/* user mode address pointers */
20781da177e4SLinus Torvalds 	struct sockaddr __user *uaddr;
207908adb7daSAl Viro 	int __user *uaddr_len = COMPAT_NAMELEN(msg);
20801da177e4SLinus Torvalds 
208108adb7daSAl Viro 	msg_sys->msg_name = &addr;
20821da177e4SLinus Torvalds 
2083f3d33426SHannes Frederic Sowa 	if (MSG_CMSG_COMPAT & flags)
208408adb7daSAl Viro 		err = get_compat_msghdr(msg_sys, msg_compat, &uaddr, &iov);
2085f3d33426SHannes Frederic Sowa 	else
208608adb7daSAl Viro 		err = copy_msghdr_from_user(msg_sys, msg, &uaddr, &iov);
20871da177e4SLinus Torvalds 	if (err < 0)
2088da184284SAl Viro 		return err;
20891da177e4SLinus Torvalds 
2090a2e27255SArnaldo Carvalho de Melo 	cmsg_ptr = (unsigned long)msg_sys->msg_control;
2091a2e27255SArnaldo Carvalho de Melo 	msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
20921da177e4SLinus Torvalds 
2093f3d33426SHannes Frederic Sowa 	/* We assume all kernel code knows the size of sockaddr_storage */
2094f3d33426SHannes Frederic Sowa 	msg_sys->msg_namelen = 0;
2095f3d33426SHannes Frederic Sowa 
20961da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
20971da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
20982da62906SAl Viro 	err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys, flags);
20991da177e4SLinus Torvalds 	if (err < 0)
21001da177e4SLinus Torvalds 		goto out_freeiov;
21011da177e4SLinus Torvalds 	len = err;
21021da177e4SLinus Torvalds 
21031da177e4SLinus Torvalds 	if (uaddr != NULL) {
210443db362dSMaciej Żenczykowski 		err = move_addr_to_user(&addr,
2105a2e27255SArnaldo Carvalho de Melo 					msg_sys->msg_namelen, uaddr,
210689bddce5SStephen Hemminger 					uaddr_len);
21071da177e4SLinus Torvalds 		if (err < 0)
21081da177e4SLinus Torvalds 			goto out_freeiov;
21091da177e4SLinus Torvalds 	}
2110a2e27255SArnaldo Carvalho de Melo 	err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
211137f7f421SDavid S. Miller 			 COMPAT_FLAGS(msg));
21121da177e4SLinus Torvalds 	if (err)
21131da177e4SLinus Torvalds 		goto out_freeiov;
21141da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags)
2115a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
21161da177e4SLinus Torvalds 				 &msg_compat->msg_controllen);
21171da177e4SLinus Torvalds 	else
2118a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
21191da177e4SLinus Torvalds 				 &msg->msg_controllen);
21201da177e4SLinus Torvalds 	if (err)
21211da177e4SLinus Torvalds 		goto out_freeiov;
21221da177e4SLinus Torvalds 	err = len;
21231da177e4SLinus Torvalds 
21241da177e4SLinus Torvalds out_freeiov:
2125a74e9106SEric Dumazet 	kfree(iov);
2126a2e27255SArnaldo Carvalho de Melo 	return err;
2127a2e27255SArnaldo Carvalho de Melo }
2128a2e27255SArnaldo Carvalho de Melo 
2129a2e27255SArnaldo Carvalho de Melo /*
2130a2e27255SArnaldo Carvalho de Melo  *	BSD recvmsg interface
2131a2e27255SArnaldo Carvalho de Melo  */
2132a2e27255SArnaldo Carvalho de Melo 
2133666547ffSAl Viro long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned flags)
2134a2e27255SArnaldo Carvalho de Melo {
2135a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err;
2136a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
21371be374a0SAndy Lutomirski 	struct socket *sock;
2138a2e27255SArnaldo Carvalho de Melo 
21391be374a0SAndy Lutomirski 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2140a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2141a2e27255SArnaldo Carvalho de Melo 		goto out;
2142a2e27255SArnaldo Carvalho de Melo 
2143a7526eb5SAndy Lutomirski 	err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0);
2144a2e27255SArnaldo Carvalho de Melo 
21456cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
21461da177e4SLinus Torvalds out:
21471da177e4SLinus Torvalds 	return err;
21481da177e4SLinus Torvalds }
21491da177e4SLinus Torvalds 
2150666547ffSAl Viro SYSCALL_DEFINE3(recvmsg, int, fd, struct user_msghdr __user *, msg,
2151a7526eb5SAndy Lutomirski 		unsigned int, flags)
2152a7526eb5SAndy Lutomirski {
2153a7526eb5SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
2154a7526eb5SAndy Lutomirski 		return -EINVAL;
2155a7526eb5SAndy Lutomirski 	return __sys_recvmsg(fd, msg, flags);
2156a7526eb5SAndy Lutomirski }
2157a7526eb5SAndy Lutomirski 
2158a2e27255SArnaldo Carvalho de Melo /*
2159a2e27255SArnaldo Carvalho de Melo  *     Linux recvmmsg interface
2160a2e27255SArnaldo Carvalho de Melo  */
21611da177e4SLinus Torvalds 
2162a2e27255SArnaldo Carvalho de Melo int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2163a2e27255SArnaldo Carvalho de Melo 		   unsigned int flags, struct timespec *timeout)
2164a2e27255SArnaldo Carvalho de Melo {
2165a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err, datagrams;
2166a2e27255SArnaldo Carvalho de Melo 	struct socket *sock;
2167a2e27255SArnaldo Carvalho de Melo 	struct mmsghdr __user *entry;
2168d7256d0eSJean-Mickael Guerin 	struct compat_mmsghdr __user *compat_entry;
2169a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
2170766b9f92SDeepa Dinamani 	struct timespec64 end_time;
2171766b9f92SDeepa Dinamani 	struct timespec64 timeout64;
2172a2e27255SArnaldo Carvalho de Melo 
2173a2e27255SArnaldo Carvalho de Melo 	if (timeout &&
2174a2e27255SArnaldo Carvalho de Melo 	    poll_select_set_timeout(&end_time, timeout->tv_sec,
2175a2e27255SArnaldo Carvalho de Melo 				    timeout->tv_nsec))
2176a2e27255SArnaldo Carvalho de Melo 		return -EINVAL;
2177a2e27255SArnaldo Carvalho de Melo 
2178a2e27255SArnaldo Carvalho de Melo 	datagrams = 0;
2179a2e27255SArnaldo Carvalho de Melo 
2180a2e27255SArnaldo Carvalho de Melo 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2181a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2182a2e27255SArnaldo Carvalho de Melo 		return err;
2183a2e27255SArnaldo Carvalho de Melo 
2184a2e27255SArnaldo Carvalho de Melo 	err = sock_error(sock->sk);
2185a2e27255SArnaldo Carvalho de Melo 	if (err)
2186a2e27255SArnaldo Carvalho de Melo 		goto out_put;
2187a2e27255SArnaldo Carvalho de Melo 
2188a2e27255SArnaldo Carvalho de Melo 	entry = mmsg;
2189d7256d0eSJean-Mickael Guerin 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2190a2e27255SArnaldo Carvalho de Melo 
2191a2e27255SArnaldo Carvalho de Melo 	while (datagrams < vlen) {
2192a2e27255SArnaldo Carvalho de Melo 		/*
2193a2e27255SArnaldo Carvalho de Melo 		 * No need to ask LSM for more than the first datagram.
2194a2e27255SArnaldo Carvalho de Melo 		 */
2195d7256d0eSJean-Mickael Guerin 		if (MSG_CMSG_COMPAT & flags) {
2196666547ffSAl Viro 			err = ___sys_recvmsg(sock, (struct user_msghdr __user *)compat_entry,
2197b9eb8b87SAnton Blanchard 					     &msg_sys, flags & ~MSG_WAITFORONE,
2198b9eb8b87SAnton Blanchard 					     datagrams);
2199d7256d0eSJean-Mickael Guerin 			if (err < 0)
2200d7256d0eSJean-Mickael Guerin 				break;
2201d7256d0eSJean-Mickael Guerin 			err = __put_user(err, &compat_entry->msg_len);
2202d7256d0eSJean-Mickael Guerin 			++compat_entry;
2203d7256d0eSJean-Mickael Guerin 		} else {
2204a7526eb5SAndy Lutomirski 			err = ___sys_recvmsg(sock,
2205666547ffSAl Viro 					     (struct user_msghdr __user *)entry,
2206b9eb8b87SAnton Blanchard 					     &msg_sys, flags & ~MSG_WAITFORONE,
2207b9eb8b87SAnton Blanchard 					     datagrams);
2208a2e27255SArnaldo Carvalho de Melo 			if (err < 0)
2209a2e27255SArnaldo Carvalho de Melo 				break;
2210a2e27255SArnaldo Carvalho de Melo 			err = put_user(err, &entry->msg_len);
2211d7256d0eSJean-Mickael Guerin 			++entry;
2212d7256d0eSJean-Mickael Guerin 		}
2213d7256d0eSJean-Mickael Guerin 
2214a2e27255SArnaldo Carvalho de Melo 		if (err)
2215a2e27255SArnaldo Carvalho de Melo 			break;
2216a2e27255SArnaldo Carvalho de Melo 		++datagrams;
2217a2e27255SArnaldo Carvalho de Melo 
221871c5c159SBrandon L Black 		/* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
221971c5c159SBrandon L Black 		if (flags & MSG_WAITFORONE)
222071c5c159SBrandon L Black 			flags |= MSG_DONTWAIT;
222171c5c159SBrandon L Black 
2222a2e27255SArnaldo Carvalho de Melo 		if (timeout) {
2223766b9f92SDeepa Dinamani 			ktime_get_ts64(&timeout64);
2224766b9f92SDeepa Dinamani 			*timeout = timespec64_to_timespec(
2225766b9f92SDeepa Dinamani 					timespec64_sub(end_time, timeout64));
2226a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_sec < 0) {
2227a2e27255SArnaldo Carvalho de Melo 				timeout->tv_sec = timeout->tv_nsec = 0;
2228a2e27255SArnaldo Carvalho de Melo 				break;
2229a2e27255SArnaldo Carvalho de Melo 			}
2230a2e27255SArnaldo Carvalho de Melo 
2231a2e27255SArnaldo Carvalho de Melo 			/* Timeout, return less than vlen datagrams */
2232a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_nsec == 0 && timeout->tv_sec == 0)
2233a2e27255SArnaldo Carvalho de Melo 				break;
2234a2e27255SArnaldo Carvalho de Melo 		}
2235a2e27255SArnaldo Carvalho de Melo 
2236a2e27255SArnaldo Carvalho de Melo 		/* Out of band data, return right away */
2237a2e27255SArnaldo Carvalho de Melo 		if (msg_sys.msg_flags & MSG_OOB)
2238a2e27255SArnaldo Carvalho de Melo 			break;
2239a78cb84cSEric Dumazet 		cond_resched();
2240a2e27255SArnaldo Carvalho de Melo 	}
2241a2e27255SArnaldo Carvalho de Melo 
2242a2e27255SArnaldo Carvalho de Melo 	if (err == 0)
224334b88a68SArnaldo Carvalho de Melo 		goto out_put;
2244a2e27255SArnaldo Carvalho de Melo 
224534b88a68SArnaldo Carvalho de Melo 	if (datagrams == 0) {
224634b88a68SArnaldo Carvalho de Melo 		datagrams = err;
224734b88a68SArnaldo Carvalho de Melo 		goto out_put;
224834b88a68SArnaldo Carvalho de Melo 	}
224934b88a68SArnaldo Carvalho de Melo 
2250a2e27255SArnaldo Carvalho de Melo 	/*
2251a2e27255SArnaldo Carvalho de Melo 	 * We may return less entries than requested (vlen) if the
2252a2e27255SArnaldo Carvalho de Melo 	 * sock is non block and there aren't enough datagrams...
2253a2e27255SArnaldo Carvalho de Melo 	 */
2254a2e27255SArnaldo Carvalho de Melo 	if (err != -EAGAIN) {
2255a2e27255SArnaldo Carvalho de Melo 		/*
2256a2e27255SArnaldo Carvalho de Melo 		 * ... or  if recvmsg returns an error after we
2257a2e27255SArnaldo Carvalho de Melo 		 * received some datagrams, where we record the
2258a2e27255SArnaldo Carvalho de Melo 		 * error to return on the next call or if the
2259a2e27255SArnaldo Carvalho de Melo 		 * app asks about it using getsockopt(SO_ERROR).
2260a2e27255SArnaldo Carvalho de Melo 		 */
2261a2e27255SArnaldo Carvalho de Melo 		sock->sk->sk_err = -err;
2262a2e27255SArnaldo Carvalho de Melo 	}
226334b88a68SArnaldo Carvalho de Melo out_put:
226434b88a68SArnaldo Carvalho de Melo 	fput_light(sock->file, fput_needed);
2265a2e27255SArnaldo Carvalho de Melo 
2266a2e27255SArnaldo Carvalho de Melo 	return datagrams;
2267a2e27255SArnaldo Carvalho de Melo }
2268a2e27255SArnaldo Carvalho de Melo 
2269a2e27255SArnaldo Carvalho de Melo SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
2270a2e27255SArnaldo Carvalho de Melo 		unsigned int, vlen, unsigned int, flags,
2271a2e27255SArnaldo Carvalho de Melo 		struct timespec __user *, timeout)
2272a2e27255SArnaldo Carvalho de Melo {
2273a2e27255SArnaldo Carvalho de Melo 	int datagrams;
2274a2e27255SArnaldo Carvalho de Melo 	struct timespec timeout_sys;
2275a2e27255SArnaldo Carvalho de Melo 
22761be374a0SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
22771be374a0SAndy Lutomirski 		return -EINVAL;
22781be374a0SAndy Lutomirski 
2279a2e27255SArnaldo Carvalho de Melo 	if (!timeout)
2280a2e27255SArnaldo Carvalho de Melo 		return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL);
2281a2e27255SArnaldo Carvalho de Melo 
2282a2e27255SArnaldo Carvalho de Melo 	if (copy_from_user(&timeout_sys, timeout, sizeof(timeout_sys)))
2283a2e27255SArnaldo Carvalho de Melo 		return -EFAULT;
2284a2e27255SArnaldo Carvalho de Melo 
2285a2e27255SArnaldo Carvalho de Melo 	datagrams = __sys_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys);
2286a2e27255SArnaldo Carvalho de Melo 
2287a2e27255SArnaldo Carvalho de Melo 	if (datagrams > 0 &&
2288a2e27255SArnaldo Carvalho de Melo 	    copy_to_user(timeout, &timeout_sys, sizeof(timeout_sys)))
2289a2e27255SArnaldo Carvalho de Melo 		datagrams = -EFAULT;
2290a2e27255SArnaldo Carvalho de Melo 
2291a2e27255SArnaldo Carvalho de Melo 	return datagrams;
2292a2e27255SArnaldo Carvalho de Melo }
2293a2e27255SArnaldo Carvalho de Melo 
2294a2e27255SArnaldo Carvalho de Melo #ifdef __ARCH_WANT_SYS_SOCKETCALL
22951da177e4SLinus Torvalds /* Argument list sizes for sys_socketcall */
22961da177e4SLinus Torvalds #define AL(x) ((x) * sizeof(unsigned long))
2297228e548eSAnton Blanchard static const unsigned char nargs[21] = {
229889bddce5SStephen Hemminger 	AL(0), AL(3), AL(3), AL(3), AL(2), AL(3),
22991da177e4SLinus Torvalds 	AL(3), AL(3), AL(4), AL(4), AL(4), AL(6),
2300aaca0bdcSUlrich Drepper 	AL(6), AL(2), AL(5), AL(5), AL(3), AL(3),
2301228e548eSAnton Blanchard 	AL(4), AL(5), AL(4)
230289bddce5SStephen Hemminger };
230389bddce5SStephen Hemminger 
23041da177e4SLinus Torvalds #undef AL
23051da177e4SLinus Torvalds 
23061da177e4SLinus Torvalds /*
23071da177e4SLinus Torvalds  *	System call vectors.
23081da177e4SLinus Torvalds  *
23091da177e4SLinus Torvalds  *	Argument checking cleaned up. Saved 20% in size.
23101da177e4SLinus Torvalds  *  This function doesn't need to set the kernel lock because
23111da177e4SLinus Torvalds  *  it is set by the callees.
23121da177e4SLinus Torvalds  */
23131da177e4SLinus Torvalds 
23143e0fa65fSHeiko Carstens SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
23151da177e4SLinus Torvalds {
23162950fa9dSChen Gang 	unsigned long a[AUDITSC_ARGS];
23171da177e4SLinus Torvalds 	unsigned long a0, a1;
23181da177e4SLinus Torvalds 	int err;
231947379052SArjan van de Ven 	unsigned int len;
23201da177e4SLinus Torvalds 
2321228e548eSAnton Blanchard 	if (call < 1 || call > SYS_SENDMMSG)
23221da177e4SLinus Torvalds 		return -EINVAL;
23231da177e4SLinus Torvalds 
232447379052SArjan van de Ven 	len = nargs[call];
232547379052SArjan van de Ven 	if (len > sizeof(a))
232647379052SArjan van de Ven 		return -EINVAL;
232747379052SArjan van de Ven 
23281da177e4SLinus Torvalds 	/* copy_from_user should be SMP safe. */
232947379052SArjan van de Ven 	if (copy_from_user(a, args, len))
23301da177e4SLinus Torvalds 		return -EFAULT;
23311da177e4SLinus Torvalds 
23322950fa9dSChen Gang 	err = audit_socketcall(nargs[call] / sizeof(unsigned long), a);
23332950fa9dSChen Gang 	if (err)
23342950fa9dSChen Gang 		return err;
23353ec3b2fbSDavid Woodhouse 
23361da177e4SLinus Torvalds 	a0 = a[0];
23371da177e4SLinus Torvalds 	a1 = a[1];
23381da177e4SLinus Torvalds 
233989bddce5SStephen Hemminger 	switch (call) {
23401da177e4SLinus Torvalds 	case SYS_SOCKET:
23411da177e4SLinus Torvalds 		err = sys_socket(a0, a1, a[2]);
23421da177e4SLinus Torvalds 		break;
23431da177e4SLinus Torvalds 	case SYS_BIND:
23441da177e4SLinus Torvalds 		err = sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
23451da177e4SLinus Torvalds 		break;
23461da177e4SLinus Torvalds 	case SYS_CONNECT:
23471da177e4SLinus Torvalds 		err = sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
23481da177e4SLinus Torvalds 		break;
23491da177e4SLinus Torvalds 	case SYS_LISTEN:
23501da177e4SLinus Torvalds 		err = sys_listen(a0, a1);
23511da177e4SLinus Torvalds 		break;
23521da177e4SLinus Torvalds 	case SYS_ACCEPT:
2353de11defeSUlrich Drepper 		err = sys_accept4(a0, (struct sockaddr __user *)a1,
2354aaca0bdcSUlrich Drepper 				  (int __user *)a[2], 0);
23551da177e4SLinus Torvalds 		break;
23561da177e4SLinus Torvalds 	case SYS_GETSOCKNAME:
235789bddce5SStephen Hemminger 		err =
235889bddce5SStephen Hemminger 		    sys_getsockname(a0, (struct sockaddr __user *)a1,
235989bddce5SStephen Hemminger 				    (int __user *)a[2]);
23601da177e4SLinus Torvalds 		break;
23611da177e4SLinus Torvalds 	case SYS_GETPEERNAME:
236289bddce5SStephen Hemminger 		err =
236389bddce5SStephen Hemminger 		    sys_getpeername(a0, (struct sockaddr __user *)a1,
236489bddce5SStephen Hemminger 				    (int __user *)a[2]);
23651da177e4SLinus Torvalds 		break;
23661da177e4SLinus Torvalds 	case SYS_SOCKETPAIR:
23671da177e4SLinus Torvalds 		err = sys_socketpair(a0, a1, a[2], (int __user *)a[3]);
23681da177e4SLinus Torvalds 		break;
23691da177e4SLinus Torvalds 	case SYS_SEND:
23701da177e4SLinus Torvalds 		err = sys_send(a0, (void __user *)a1, a[2], a[3]);
23711da177e4SLinus Torvalds 		break;
23721da177e4SLinus Torvalds 	case SYS_SENDTO:
23731da177e4SLinus Torvalds 		err = sys_sendto(a0, (void __user *)a1, a[2], a[3],
23741da177e4SLinus Torvalds 				 (struct sockaddr __user *)a[4], a[5]);
23751da177e4SLinus Torvalds 		break;
23761da177e4SLinus Torvalds 	case SYS_RECV:
23771da177e4SLinus Torvalds 		err = sys_recv(a0, (void __user *)a1, a[2], a[3]);
23781da177e4SLinus Torvalds 		break;
23791da177e4SLinus Torvalds 	case SYS_RECVFROM:
23801da177e4SLinus Torvalds 		err = sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
238189bddce5SStephen Hemminger 				   (struct sockaddr __user *)a[4],
238289bddce5SStephen Hemminger 				   (int __user *)a[5]);
23831da177e4SLinus Torvalds 		break;
23841da177e4SLinus Torvalds 	case SYS_SHUTDOWN:
23851da177e4SLinus Torvalds 		err = sys_shutdown(a0, a1);
23861da177e4SLinus Torvalds 		break;
23871da177e4SLinus Torvalds 	case SYS_SETSOCKOPT:
23881da177e4SLinus Torvalds 		err = sys_setsockopt(a0, a1, a[2], (char __user *)a[3], a[4]);
23891da177e4SLinus Torvalds 		break;
23901da177e4SLinus Torvalds 	case SYS_GETSOCKOPT:
239189bddce5SStephen Hemminger 		err =
239289bddce5SStephen Hemminger 		    sys_getsockopt(a0, a1, a[2], (char __user *)a[3],
239389bddce5SStephen Hemminger 				   (int __user *)a[4]);
23941da177e4SLinus Torvalds 		break;
23951da177e4SLinus Torvalds 	case SYS_SENDMSG:
2396666547ffSAl Viro 		err = sys_sendmsg(a0, (struct user_msghdr __user *)a1, a[2]);
23971da177e4SLinus Torvalds 		break;
2398228e548eSAnton Blanchard 	case SYS_SENDMMSG:
2399228e548eSAnton Blanchard 		err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]);
2400228e548eSAnton Blanchard 		break;
24011da177e4SLinus Torvalds 	case SYS_RECVMSG:
2402666547ffSAl Viro 		err = sys_recvmsg(a0, (struct user_msghdr __user *)a1, a[2]);
24031da177e4SLinus Torvalds 		break;
2404a2e27255SArnaldo Carvalho de Melo 	case SYS_RECVMMSG:
2405a2e27255SArnaldo Carvalho de Melo 		err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3],
2406a2e27255SArnaldo Carvalho de Melo 				   (struct timespec __user *)a[4]);
2407a2e27255SArnaldo Carvalho de Melo 		break;
2408de11defeSUlrich Drepper 	case SYS_ACCEPT4:
2409de11defeSUlrich Drepper 		err = sys_accept4(a0, (struct sockaddr __user *)a1,
2410de11defeSUlrich Drepper 				  (int __user *)a[2], a[3]);
2411aaca0bdcSUlrich Drepper 		break;
24121da177e4SLinus Torvalds 	default:
24131da177e4SLinus Torvalds 		err = -EINVAL;
24141da177e4SLinus Torvalds 		break;
24151da177e4SLinus Torvalds 	}
24161da177e4SLinus Torvalds 	return err;
24171da177e4SLinus Torvalds }
24181da177e4SLinus Torvalds 
24191da177e4SLinus Torvalds #endif				/* __ARCH_WANT_SYS_SOCKETCALL */
24201da177e4SLinus Torvalds 
242155737fdaSStephen Hemminger /**
242255737fdaSStephen Hemminger  *	sock_register - add a socket protocol handler
242355737fdaSStephen Hemminger  *	@ops: description of protocol
242455737fdaSStephen Hemminger  *
24251da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
24261da177e4SLinus Torvalds  *	advertise its address family, and have it linked into the
2427e793c0f7SMasanari Iida  *	socket interface. The value ops->family corresponds to the
242855737fdaSStephen Hemminger  *	socket system call protocol family.
24291da177e4SLinus Torvalds  */
2430f0fd27d4SStephen Hemminger int sock_register(const struct net_proto_family *ops)
24311da177e4SLinus Torvalds {
24321da177e4SLinus Torvalds 	int err;
24331da177e4SLinus Torvalds 
24341da177e4SLinus Torvalds 	if (ops->family >= NPROTO) {
24353410f22eSYang Yingliang 		pr_crit("protocol %d >= NPROTO(%d)\n", ops->family, NPROTO);
24361da177e4SLinus Torvalds 		return -ENOBUFS;
24371da177e4SLinus Torvalds 	}
243855737fdaSStephen Hemminger 
243955737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2440190683a9SEric Dumazet 	if (rcu_dereference_protected(net_families[ops->family],
2441190683a9SEric Dumazet 				      lockdep_is_held(&net_family_lock)))
24421da177e4SLinus Torvalds 		err = -EEXIST;
244355737fdaSStephen Hemminger 	else {
2444cf778b00SEric Dumazet 		rcu_assign_pointer(net_families[ops->family], ops);
24451da177e4SLinus Torvalds 		err = 0;
24461da177e4SLinus Torvalds 	}
244755737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
244855737fdaSStephen Hemminger 
24493410f22eSYang Yingliang 	pr_info("NET: Registered protocol family %d\n", ops->family);
24501da177e4SLinus Torvalds 	return err;
24511da177e4SLinus Torvalds }
2452c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_register);
24531da177e4SLinus Torvalds 
245455737fdaSStephen Hemminger /**
245555737fdaSStephen Hemminger  *	sock_unregister - remove a protocol handler
245655737fdaSStephen Hemminger  *	@family: protocol family to remove
245755737fdaSStephen Hemminger  *
24581da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
24591da177e4SLinus Torvalds  *	remove its address family, and have it unlinked from the
246055737fdaSStephen Hemminger  *	new socket creation.
246155737fdaSStephen Hemminger  *
246255737fdaSStephen Hemminger  *	If protocol handler is a module, then it can use module reference
246355737fdaSStephen Hemminger  *	counts to protect against new references. If protocol handler is not
246455737fdaSStephen Hemminger  *	a module then it needs to provide its own protection in
246555737fdaSStephen Hemminger  *	the ops->create routine.
24661da177e4SLinus Torvalds  */
2467f0fd27d4SStephen Hemminger void sock_unregister(int family)
24681da177e4SLinus Torvalds {
2469f0fd27d4SStephen Hemminger 	BUG_ON(family < 0 || family >= NPROTO);
24701da177e4SLinus Torvalds 
247155737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2472a9b3cd7fSStephen Hemminger 	RCU_INIT_POINTER(net_families[family], NULL);
247355737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
247455737fdaSStephen Hemminger 
247555737fdaSStephen Hemminger 	synchronize_rcu();
247655737fdaSStephen Hemminger 
24773410f22eSYang Yingliang 	pr_info("NET: Unregistered protocol family %d\n", family);
24781da177e4SLinus Torvalds }
2479c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_unregister);
24801da177e4SLinus Torvalds 
248177d76ea3SAndi Kleen static int __init sock_init(void)
24821da177e4SLinus Torvalds {
2483b3e19d92SNick Piggin 	int err;
24842ca794e5SEric W. Biederman 	/*
24852ca794e5SEric W. Biederman 	 *      Initialize the network sysctl infrastructure.
24862ca794e5SEric W. Biederman 	 */
24872ca794e5SEric W. Biederman 	err = net_sysctl_init();
24882ca794e5SEric W. Biederman 	if (err)
24892ca794e5SEric W. Biederman 		goto out;
2490b3e19d92SNick Piggin 
24911da177e4SLinus Torvalds 	/*
24921da177e4SLinus Torvalds 	 *      Initialize skbuff SLAB cache
24931da177e4SLinus Torvalds 	 */
24941da177e4SLinus Torvalds 	skb_init();
24951da177e4SLinus Torvalds 
24961da177e4SLinus Torvalds 	/*
24971da177e4SLinus Torvalds 	 *      Initialize the protocols module.
24981da177e4SLinus Torvalds 	 */
24991da177e4SLinus Torvalds 
25001da177e4SLinus Torvalds 	init_inodecache();
2501b3e19d92SNick Piggin 
2502b3e19d92SNick Piggin 	err = register_filesystem(&sock_fs_type);
2503b3e19d92SNick Piggin 	if (err)
2504b3e19d92SNick Piggin 		goto out_fs;
25051da177e4SLinus Torvalds 	sock_mnt = kern_mount(&sock_fs_type);
2506b3e19d92SNick Piggin 	if (IS_ERR(sock_mnt)) {
2507b3e19d92SNick Piggin 		err = PTR_ERR(sock_mnt);
2508b3e19d92SNick Piggin 		goto out_mount;
2509b3e19d92SNick Piggin 	}
251077d76ea3SAndi Kleen 
251177d76ea3SAndi Kleen 	/* The real protocol initialization is performed in later initcalls.
25121da177e4SLinus Torvalds 	 */
25131da177e4SLinus Torvalds 
25141da177e4SLinus Torvalds #ifdef CONFIG_NETFILTER
25156d11cfdbSPablo Neira Ayuso 	err = netfilter_init();
25166d11cfdbSPablo Neira Ayuso 	if (err)
25176d11cfdbSPablo Neira Ayuso 		goto out;
25181da177e4SLinus Torvalds #endif
2519cbeb321aSDavid S. Miller 
2520408eccceSDaniel Borkmann 	ptp_classifier_init();
2521c1f19b51SRichard Cochran 
2522b3e19d92SNick Piggin out:
2523b3e19d92SNick Piggin 	return err;
2524b3e19d92SNick Piggin 
2525b3e19d92SNick Piggin out_mount:
2526b3e19d92SNick Piggin 	unregister_filesystem(&sock_fs_type);
2527b3e19d92SNick Piggin out_fs:
2528b3e19d92SNick Piggin 	goto out;
25291da177e4SLinus Torvalds }
25301da177e4SLinus Torvalds 
253177d76ea3SAndi Kleen core_initcall(sock_init);	/* early initcall */
253277d76ea3SAndi Kleen 
25331da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS
25341da177e4SLinus Torvalds void socket_seq_show(struct seq_file *seq)
25351da177e4SLinus Torvalds {
25361da177e4SLinus Torvalds 	int cpu;
25371da177e4SLinus Torvalds 	int counter = 0;
25381da177e4SLinus Torvalds 
25396f912042SKAMEZAWA Hiroyuki 	for_each_possible_cpu(cpu)
25401da177e4SLinus Torvalds 	    counter += per_cpu(sockets_in_use, cpu);
25411da177e4SLinus Torvalds 
25421da177e4SLinus Torvalds 	/* It can be negative, by the way. 8) */
25431da177e4SLinus Torvalds 	if (counter < 0)
25441da177e4SLinus Torvalds 		counter = 0;
25451da177e4SLinus Torvalds 
25461da177e4SLinus Torvalds 	seq_printf(seq, "sockets: used %d\n", counter);
25471da177e4SLinus Torvalds }
25481da177e4SLinus Torvalds #endif				/* CONFIG_PROC_FS */
25491da177e4SLinus Torvalds 
255089bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
25516b96018bSArnd Bergmann static int do_siocgstamp(struct net *net, struct socket *sock,
2552644595f8SH. Peter Anvin 			 unsigned int cmd, void __user *up)
25537a229387SArnd Bergmann {
25547a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
25557a229387SArnd Bergmann 	struct timeval ktv;
25567a229387SArnd Bergmann 	int err;
25577a229387SArnd Bergmann 
25587a229387SArnd Bergmann 	set_fs(KERNEL_DS);
25596b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv);
25607a229387SArnd Bergmann 	set_fs(old_fs);
2561644595f8SH. Peter Anvin 	if (!err)
2562ed6fe9d6SMikulas Patocka 		err = compat_put_timeval(&ktv, up);
2563644595f8SH. Peter Anvin 
25647a229387SArnd Bergmann 	return err;
25657a229387SArnd Bergmann }
25667a229387SArnd Bergmann 
25676b96018bSArnd Bergmann static int do_siocgstampns(struct net *net, struct socket *sock,
2568644595f8SH. Peter Anvin 			   unsigned int cmd, void __user *up)
25697a229387SArnd Bergmann {
25707a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
25717a229387SArnd Bergmann 	struct timespec kts;
25727a229387SArnd Bergmann 	int err;
25737a229387SArnd Bergmann 
25747a229387SArnd Bergmann 	set_fs(KERNEL_DS);
25756b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts);
25767a229387SArnd Bergmann 	set_fs(old_fs);
2577644595f8SH. Peter Anvin 	if (!err)
2578ed6fe9d6SMikulas Patocka 		err = compat_put_timespec(&kts, up);
2579644595f8SH. Peter Anvin 
25807a229387SArnd Bergmann 	return err;
25817a229387SArnd Bergmann }
25827a229387SArnd Bergmann 
25836b96018bSArnd Bergmann static int dev_ifname32(struct net *net, struct compat_ifreq __user *uifr32)
25847a229387SArnd Bergmann {
25857a229387SArnd Bergmann 	struct ifreq __user *uifr;
25867a229387SArnd Bergmann 	int err;
25877a229387SArnd Bergmann 
25887a229387SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(struct ifreq));
25896b96018bSArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
25907a229387SArnd Bergmann 		return -EFAULT;
25917a229387SArnd Bergmann 
25926b96018bSArnd Bergmann 	err = dev_ioctl(net, SIOCGIFNAME, uifr);
25937a229387SArnd Bergmann 	if (err)
25947a229387SArnd Bergmann 		return err;
25957a229387SArnd Bergmann 
25966b96018bSArnd Bergmann 	if (copy_in_user(uifr32, uifr, sizeof(struct compat_ifreq)))
25977a229387SArnd Bergmann 		return -EFAULT;
25987a229387SArnd Bergmann 
25997a229387SArnd Bergmann 	return 0;
26007a229387SArnd Bergmann }
26017a229387SArnd Bergmann 
26026b96018bSArnd Bergmann static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32)
26037a229387SArnd Bergmann {
26046b96018bSArnd Bergmann 	struct compat_ifconf ifc32;
26057a229387SArnd Bergmann 	struct ifconf ifc;
26067a229387SArnd Bergmann 	struct ifconf __user *uifc;
26076b96018bSArnd Bergmann 	struct compat_ifreq __user *ifr32;
26087a229387SArnd Bergmann 	struct ifreq __user *ifr;
26097a229387SArnd Bergmann 	unsigned int i, j;
26107a229387SArnd Bergmann 	int err;
26117a229387SArnd Bergmann 
26126b96018bSArnd Bergmann 	if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf)))
26137a229387SArnd Bergmann 		return -EFAULT;
26147a229387SArnd Bergmann 
261543da5f2eSMathias Krause 	memset(&ifc, 0, sizeof(ifc));
26167a229387SArnd Bergmann 	if (ifc32.ifcbuf == 0) {
26177a229387SArnd Bergmann 		ifc32.ifc_len = 0;
26187a229387SArnd Bergmann 		ifc.ifc_len = 0;
26197a229387SArnd Bergmann 		ifc.ifc_req = NULL;
26207a229387SArnd Bergmann 		uifc = compat_alloc_user_space(sizeof(struct ifconf));
26217a229387SArnd Bergmann 	} else {
26226b96018bSArnd Bergmann 		size_t len = ((ifc32.ifc_len / sizeof(struct compat_ifreq)) + 1) *
26237a229387SArnd Bergmann 			sizeof(struct ifreq);
26247a229387SArnd Bergmann 		uifc = compat_alloc_user_space(sizeof(struct ifconf) + len);
26257a229387SArnd Bergmann 		ifc.ifc_len = len;
26267a229387SArnd Bergmann 		ifr = ifc.ifc_req = (void __user *)(uifc + 1);
26277a229387SArnd Bergmann 		ifr32 = compat_ptr(ifc32.ifcbuf);
26286b96018bSArnd Bergmann 		for (i = 0; i < ifc32.ifc_len; i += sizeof(struct compat_ifreq)) {
26296b96018bSArnd Bergmann 			if (copy_in_user(ifr, ifr32, sizeof(struct compat_ifreq)))
26307a229387SArnd Bergmann 				return -EFAULT;
26317a229387SArnd Bergmann 			ifr++;
26327a229387SArnd Bergmann 			ifr32++;
26337a229387SArnd Bergmann 		}
26347a229387SArnd Bergmann 	}
26357a229387SArnd Bergmann 	if (copy_to_user(uifc, &ifc, sizeof(struct ifconf)))
26367a229387SArnd Bergmann 		return -EFAULT;
26377a229387SArnd Bergmann 
26386b96018bSArnd Bergmann 	err = dev_ioctl(net, SIOCGIFCONF, uifc);
26397a229387SArnd Bergmann 	if (err)
26407a229387SArnd Bergmann 		return err;
26417a229387SArnd Bergmann 
26427a229387SArnd Bergmann 	if (copy_from_user(&ifc, uifc, sizeof(struct ifconf)))
26437a229387SArnd Bergmann 		return -EFAULT;
26447a229387SArnd Bergmann 
26457a229387SArnd Bergmann 	ifr = ifc.ifc_req;
26467a229387SArnd Bergmann 	ifr32 = compat_ptr(ifc32.ifcbuf);
26477a229387SArnd Bergmann 	for (i = 0, j = 0;
26486b96018bSArnd Bergmann 	     i + sizeof(struct compat_ifreq) <= ifc32.ifc_len && j < ifc.ifc_len;
26496b96018bSArnd Bergmann 	     i += sizeof(struct compat_ifreq), j += sizeof(struct ifreq)) {
26506b96018bSArnd Bergmann 		if (copy_in_user(ifr32, ifr, sizeof(struct compat_ifreq)))
26517a229387SArnd Bergmann 			return -EFAULT;
26527a229387SArnd Bergmann 		ifr32++;
26537a229387SArnd Bergmann 		ifr++;
26547a229387SArnd Bergmann 	}
26557a229387SArnd Bergmann 
26567a229387SArnd Bergmann 	if (ifc32.ifcbuf == 0) {
26577a229387SArnd Bergmann 		/* Translate from 64-bit structure multiple to
26587a229387SArnd Bergmann 		 * a 32-bit one.
26597a229387SArnd Bergmann 		 */
26607a229387SArnd Bergmann 		i = ifc.ifc_len;
26616b96018bSArnd Bergmann 		i = ((i / sizeof(struct ifreq)) * sizeof(struct compat_ifreq));
26627a229387SArnd Bergmann 		ifc32.ifc_len = i;
26637a229387SArnd Bergmann 	} else {
26647a229387SArnd Bergmann 		ifc32.ifc_len = i;
26657a229387SArnd Bergmann 	}
26666b96018bSArnd Bergmann 	if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf)))
26677a229387SArnd Bergmann 		return -EFAULT;
26687a229387SArnd Bergmann 
26697a229387SArnd Bergmann 	return 0;
26707a229387SArnd Bergmann }
26717a229387SArnd Bergmann 
26726b96018bSArnd Bergmann static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
26737a229387SArnd Bergmann {
26743a7da39dSBen Hutchings 	struct compat_ethtool_rxnfc __user *compat_rxnfc;
26753a7da39dSBen Hutchings 	bool convert_in = false, convert_out = false;
26763a7da39dSBen Hutchings 	size_t buf_size = ALIGN(sizeof(struct ifreq), 8);
26773a7da39dSBen Hutchings 	struct ethtool_rxnfc __user *rxnfc;
26787a229387SArnd Bergmann 	struct ifreq __user *ifr;
26793a7da39dSBen Hutchings 	u32 rule_cnt = 0, actual_rule_cnt;
26803a7da39dSBen Hutchings 	u32 ethcmd;
26817a229387SArnd Bergmann 	u32 data;
26823a7da39dSBen Hutchings 	int ret;
26837a229387SArnd Bergmann 
26847a229387SArnd Bergmann 	if (get_user(data, &ifr32->ifr_ifru.ifru_data))
26857a229387SArnd Bergmann 		return -EFAULT;
26867a229387SArnd Bergmann 
26873a7da39dSBen Hutchings 	compat_rxnfc = compat_ptr(data);
26883a7da39dSBen Hutchings 
26893a7da39dSBen Hutchings 	if (get_user(ethcmd, &compat_rxnfc->cmd))
26907a229387SArnd Bergmann 		return -EFAULT;
26917a229387SArnd Bergmann 
26923a7da39dSBen Hutchings 	/* Most ethtool structures are defined without padding.
26933a7da39dSBen Hutchings 	 * Unfortunately struct ethtool_rxnfc is an exception.
26943a7da39dSBen Hutchings 	 */
26953a7da39dSBen Hutchings 	switch (ethcmd) {
26963a7da39dSBen Hutchings 	default:
26973a7da39dSBen Hutchings 		break;
26983a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLALL:
26993a7da39dSBen Hutchings 		/* Buffer size is variable */
27003a7da39dSBen Hutchings 		if (get_user(rule_cnt, &compat_rxnfc->rule_cnt))
27013a7da39dSBen Hutchings 			return -EFAULT;
27023a7da39dSBen Hutchings 		if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32))
27033a7da39dSBen Hutchings 			return -ENOMEM;
27043a7da39dSBen Hutchings 		buf_size += rule_cnt * sizeof(u32);
27053a7da39dSBen Hutchings 		/* fall through */
27063a7da39dSBen Hutchings 	case ETHTOOL_GRXRINGS:
27073a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLCNT:
27083a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRULE:
270955664f32SBen Hutchings 	case ETHTOOL_SRXCLSRLINS:
27103a7da39dSBen Hutchings 		convert_out = true;
27113a7da39dSBen Hutchings 		/* fall through */
27123a7da39dSBen Hutchings 	case ETHTOOL_SRXCLSRLDEL:
27133a7da39dSBen Hutchings 		buf_size += sizeof(struct ethtool_rxnfc);
27143a7da39dSBen Hutchings 		convert_in = true;
27153a7da39dSBen Hutchings 		break;
27163a7da39dSBen Hutchings 	}
27173a7da39dSBen Hutchings 
27183a7da39dSBen Hutchings 	ifr = compat_alloc_user_space(buf_size);
2719954b1244SStephen Hemminger 	rxnfc = (void __user *)ifr + ALIGN(sizeof(struct ifreq), 8);
27203a7da39dSBen Hutchings 
27213a7da39dSBen Hutchings 	if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
27223a7da39dSBen Hutchings 		return -EFAULT;
27233a7da39dSBen Hutchings 
27243a7da39dSBen Hutchings 	if (put_user(convert_in ? rxnfc : compat_ptr(data),
27253a7da39dSBen Hutchings 		     &ifr->ifr_ifru.ifru_data))
27263a7da39dSBen Hutchings 		return -EFAULT;
27273a7da39dSBen Hutchings 
27283a7da39dSBen Hutchings 	if (convert_in) {
2729127fe533SAlexander Duyck 		/* We expect there to be holes between fs.m_ext and
27303a7da39dSBen Hutchings 		 * fs.ring_cookie and at the end of fs, but nowhere else.
27313a7da39dSBen Hutchings 		 */
2732127fe533SAlexander Duyck 		BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_ext) +
2733127fe533SAlexander Duyck 			     sizeof(compat_rxnfc->fs.m_ext) !=
2734127fe533SAlexander Duyck 			     offsetof(struct ethtool_rxnfc, fs.m_ext) +
2735127fe533SAlexander Duyck 			     sizeof(rxnfc->fs.m_ext));
27363a7da39dSBen Hutchings 		BUILD_BUG_ON(
27373a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.location) -
27383a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) !=
27393a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.location) -
27403a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.ring_cookie));
27413a7da39dSBen Hutchings 
27423a7da39dSBen Hutchings 		if (copy_in_user(rxnfc, compat_rxnfc,
2743954b1244SStephen Hemminger 				 (void __user *)(&rxnfc->fs.m_ext + 1) -
2744954b1244SStephen Hemminger 				 (void __user *)rxnfc) ||
27453a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->fs.ring_cookie,
27463a7da39dSBen Hutchings 				 &compat_rxnfc->fs.ring_cookie,
2747954b1244SStephen Hemminger 				 (void __user *)(&rxnfc->fs.location + 1) -
2748954b1244SStephen Hemminger 				 (void __user *)&rxnfc->fs.ring_cookie) ||
27493a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt,
27503a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
27513a7da39dSBen Hutchings 			return -EFAULT;
27523a7da39dSBen Hutchings 	}
27533a7da39dSBen Hutchings 
27543a7da39dSBen Hutchings 	ret = dev_ioctl(net, SIOCETHTOOL, ifr);
27553a7da39dSBen Hutchings 	if (ret)
27563a7da39dSBen Hutchings 		return ret;
27573a7da39dSBen Hutchings 
27583a7da39dSBen Hutchings 	if (convert_out) {
27593a7da39dSBen Hutchings 		if (copy_in_user(compat_rxnfc, rxnfc,
2760954b1244SStephen Hemminger 				 (const void __user *)(&rxnfc->fs.m_ext + 1) -
2761954b1244SStephen Hemminger 				 (const void __user *)rxnfc) ||
27623a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->fs.ring_cookie,
27633a7da39dSBen Hutchings 				 &rxnfc->fs.ring_cookie,
2764954b1244SStephen Hemminger 				 (const void __user *)(&rxnfc->fs.location + 1) -
2765954b1244SStephen Hemminger 				 (const void __user *)&rxnfc->fs.ring_cookie) ||
27663a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt,
27673a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
27683a7da39dSBen Hutchings 			return -EFAULT;
27693a7da39dSBen Hutchings 
27703a7da39dSBen Hutchings 		if (ethcmd == ETHTOOL_GRXCLSRLALL) {
27713a7da39dSBen Hutchings 			/* As an optimisation, we only copy the actual
27723a7da39dSBen Hutchings 			 * number of rules that the underlying
27733a7da39dSBen Hutchings 			 * function returned.  Since Mallory might
27743a7da39dSBen Hutchings 			 * change the rule count in user memory, we
27753a7da39dSBen Hutchings 			 * check that it is less than the rule count
27763a7da39dSBen Hutchings 			 * originally given (as the user buffer size),
27773a7da39dSBen Hutchings 			 * which has been range-checked.
27783a7da39dSBen Hutchings 			 */
27793a7da39dSBen Hutchings 			if (get_user(actual_rule_cnt, &rxnfc->rule_cnt))
27803a7da39dSBen Hutchings 				return -EFAULT;
27813a7da39dSBen Hutchings 			if (actual_rule_cnt < rule_cnt)
27823a7da39dSBen Hutchings 				rule_cnt = actual_rule_cnt;
27833a7da39dSBen Hutchings 			if (copy_in_user(&compat_rxnfc->rule_locs[0],
27843a7da39dSBen Hutchings 					 &rxnfc->rule_locs[0],
27853a7da39dSBen Hutchings 					 rule_cnt * sizeof(u32)))
27863a7da39dSBen Hutchings 				return -EFAULT;
27873a7da39dSBen Hutchings 		}
27883a7da39dSBen Hutchings 	}
27893a7da39dSBen Hutchings 
27903a7da39dSBen Hutchings 	return 0;
27917a229387SArnd Bergmann }
27927a229387SArnd Bergmann 
27937a50a240SArnd Bergmann static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32)
27947a50a240SArnd Bergmann {
27957a50a240SArnd Bergmann 	void __user *uptr;
27967a50a240SArnd Bergmann 	compat_uptr_t uptr32;
27977a50a240SArnd Bergmann 	struct ifreq __user *uifr;
27987a50a240SArnd Bergmann 
27997a50a240SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
28007a50a240SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
28017a50a240SArnd Bergmann 		return -EFAULT;
28027a50a240SArnd Bergmann 
28037a50a240SArnd Bergmann 	if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu))
28047a50a240SArnd Bergmann 		return -EFAULT;
28057a50a240SArnd Bergmann 
28067a50a240SArnd Bergmann 	uptr = compat_ptr(uptr32);
28077a50a240SArnd Bergmann 
28087a50a240SArnd Bergmann 	if (put_user(uptr, &uifr->ifr_settings.ifs_ifsu.raw_hdlc))
28097a50a240SArnd Bergmann 		return -EFAULT;
28107a50a240SArnd Bergmann 
28117a50a240SArnd Bergmann 	return dev_ioctl(net, SIOCWANDEV, uifr);
28127a50a240SArnd Bergmann }
28137a50a240SArnd Bergmann 
28146b96018bSArnd Bergmann static int bond_ioctl(struct net *net, unsigned int cmd,
28156b96018bSArnd Bergmann 			 struct compat_ifreq __user *ifr32)
28167a229387SArnd Bergmann {
28177a229387SArnd Bergmann 	struct ifreq kifr;
28187a229387SArnd Bergmann 	mm_segment_t old_fs;
28197a229387SArnd Bergmann 	int err;
28207a229387SArnd Bergmann 
28217a229387SArnd Bergmann 	switch (cmd) {
28227a229387SArnd Bergmann 	case SIOCBONDENSLAVE:
28237a229387SArnd Bergmann 	case SIOCBONDRELEASE:
28247a229387SArnd Bergmann 	case SIOCBONDSETHWADDR:
28257a229387SArnd Bergmann 	case SIOCBONDCHANGEACTIVE:
28266b96018bSArnd Bergmann 		if (copy_from_user(&kifr, ifr32, sizeof(struct compat_ifreq)))
28277a229387SArnd Bergmann 			return -EFAULT;
28287a229387SArnd Bergmann 
28297a229387SArnd Bergmann 		old_fs = get_fs();
28307a229387SArnd Bergmann 		set_fs(KERNEL_DS);
2831c3f52ae6Sstephen hemminger 		err = dev_ioctl(net, cmd,
2832c3f52ae6Sstephen hemminger 				(struct ifreq __user __force *) &kifr);
28337a229387SArnd Bergmann 		set_fs(old_fs);
28347a229387SArnd Bergmann 
28357a229387SArnd Bergmann 		return err;
28367a229387SArnd Bergmann 	default:
283707d106d0SLinus Torvalds 		return -ENOIOCTLCMD;
2838ccbd6a5aSJoe Perches 	}
28397a229387SArnd Bergmann }
28407a229387SArnd Bergmann 
2841590d4693SBen Hutchings /* Handle ioctls that use ifreq::ifr_data and just need struct ifreq converted */
2842590d4693SBen Hutchings static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd,
28436b96018bSArnd Bergmann 				 struct compat_ifreq __user *u_ifreq32)
28447a229387SArnd Bergmann {
28457a229387SArnd Bergmann 	struct ifreq __user *u_ifreq64;
28467a229387SArnd Bergmann 	char tmp_buf[IFNAMSIZ];
28477a229387SArnd Bergmann 	void __user *data64;
28487a229387SArnd Bergmann 	u32 data32;
28497a229387SArnd Bergmann 
28507a229387SArnd Bergmann 	if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]),
28517a229387SArnd Bergmann 			   IFNAMSIZ))
28527a229387SArnd Bergmann 		return -EFAULT;
2853417c3522SBen Hutchings 	if (get_user(data32, &u_ifreq32->ifr_ifru.ifru_data))
28547a229387SArnd Bergmann 		return -EFAULT;
28557a229387SArnd Bergmann 	data64 = compat_ptr(data32);
28567a229387SArnd Bergmann 
28577a229387SArnd Bergmann 	u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
28587a229387SArnd Bergmann 
28597a229387SArnd Bergmann 	if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0],
28607a229387SArnd Bergmann 			 IFNAMSIZ))
28617a229387SArnd Bergmann 		return -EFAULT;
2862417c3522SBen Hutchings 	if (put_user(data64, &u_ifreq64->ifr_ifru.ifru_data))
28637a229387SArnd Bergmann 		return -EFAULT;
28647a229387SArnd Bergmann 
28656b96018bSArnd Bergmann 	return dev_ioctl(net, cmd, u_ifreq64);
28667a229387SArnd Bergmann }
28677a229387SArnd Bergmann 
28686b96018bSArnd Bergmann static int dev_ifsioc(struct net *net, struct socket *sock,
28696b96018bSArnd Bergmann 			 unsigned int cmd, struct compat_ifreq __user *uifr32)
28707a229387SArnd Bergmann {
2871a2116ed2SArnd Bergmann 	struct ifreq __user *uifr;
28727a229387SArnd Bergmann 	int err;
28737a229387SArnd Bergmann 
2874a2116ed2SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
2875a2116ed2SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(*uifr32)))
28767a229387SArnd Bergmann 		return -EFAULT;
2877a2116ed2SArnd Bergmann 
2878a2116ed2SArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr);
2879a2116ed2SArnd Bergmann 
28807a229387SArnd Bergmann 	if (!err) {
28817a229387SArnd Bergmann 		switch (cmd) {
28827a229387SArnd Bergmann 		case SIOCGIFFLAGS:
28837a229387SArnd Bergmann 		case SIOCGIFMETRIC:
28847a229387SArnd Bergmann 		case SIOCGIFMTU:
28857a229387SArnd Bergmann 		case SIOCGIFMEM:
28867a229387SArnd Bergmann 		case SIOCGIFHWADDR:
28877a229387SArnd Bergmann 		case SIOCGIFINDEX:
28887a229387SArnd Bergmann 		case SIOCGIFADDR:
28897a229387SArnd Bergmann 		case SIOCGIFBRDADDR:
28907a229387SArnd Bergmann 		case SIOCGIFDSTADDR:
28917a229387SArnd Bergmann 		case SIOCGIFNETMASK:
2892fab2532bSArnd Bergmann 		case SIOCGIFPFLAGS:
28937a229387SArnd Bergmann 		case SIOCGIFTXQLEN:
2894fab2532bSArnd Bergmann 		case SIOCGMIIPHY:
2895fab2532bSArnd Bergmann 		case SIOCGMIIREG:
2896a2116ed2SArnd Bergmann 			if (copy_in_user(uifr32, uifr, sizeof(*uifr32)))
2897a2116ed2SArnd Bergmann 				err = -EFAULT;
28987a229387SArnd Bergmann 			break;
2899a2116ed2SArnd Bergmann 		}
2900a2116ed2SArnd Bergmann 	}
2901a2116ed2SArnd Bergmann 	return err;
2902a2116ed2SArnd Bergmann }
2903a2116ed2SArnd Bergmann 
2904a2116ed2SArnd Bergmann static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
2905a2116ed2SArnd Bergmann 			struct compat_ifreq __user *uifr32)
2906a2116ed2SArnd Bergmann {
2907a2116ed2SArnd Bergmann 	struct ifreq ifr;
2908a2116ed2SArnd Bergmann 	struct compat_ifmap __user *uifmap32;
2909a2116ed2SArnd Bergmann 	mm_segment_t old_fs;
2910a2116ed2SArnd Bergmann 	int err;
2911a2116ed2SArnd Bergmann 
2912a2116ed2SArnd Bergmann 	uifmap32 = &uifr32->ifr_ifru.ifru_map;
2913a2116ed2SArnd Bergmann 	err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name));
29143ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
29153ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
29163ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
29173ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.irq, &uifmap32->irq);
29183ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.dma, &uifmap32->dma);
29193ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.port, &uifmap32->port);
2920a2116ed2SArnd Bergmann 	if (err)
2921a2116ed2SArnd Bergmann 		return -EFAULT;
2922a2116ed2SArnd Bergmann 
2923a2116ed2SArnd Bergmann 	old_fs = get_fs();
2924a2116ed2SArnd Bergmann 	set_fs(KERNEL_DS);
2925c3f52ae6Sstephen hemminger 	err = dev_ioctl(net, cmd, (void  __user __force *)&ifr);
2926a2116ed2SArnd Bergmann 	set_fs(old_fs);
2927a2116ed2SArnd Bergmann 
2928a2116ed2SArnd Bergmann 	if (cmd == SIOCGIFMAP && !err) {
29297a229387SArnd Bergmann 		err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name));
29303ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
29313ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
29323ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
29333ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.irq, &uifmap32->irq);
29343ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.dma, &uifmap32->dma);
29353ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.port, &uifmap32->port);
29367a229387SArnd Bergmann 		if (err)
29377a229387SArnd Bergmann 			err = -EFAULT;
29387a229387SArnd Bergmann 	}
29397a229387SArnd Bergmann 	return err;
29407a229387SArnd Bergmann }
29417a229387SArnd Bergmann 
29427a229387SArnd Bergmann struct rtentry32 {
29437a229387SArnd Bergmann 	u32		rt_pad1;
29447a229387SArnd Bergmann 	struct sockaddr rt_dst;         /* target address               */
29457a229387SArnd Bergmann 	struct sockaddr rt_gateway;     /* gateway addr (RTF_GATEWAY)   */
29467a229387SArnd Bergmann 	struct sockaddr rt_genmask;     /* target network mask (IP)     */
29477a229387SArnd Bergmann 	unsigned short	rt_flags;
29487a229387SArnd Bergmann 	short		rt_pad2;
29497a229387SArnd Bergmann 	u32		rt_pad3;
29507a229387SArnd Bergmann 	unsigned char	rt_tos;
29517a229387SArnd Bergmann 	unsigned char	rt_class;
29527a229387SArnd Bergmann 	short		rt_pad4;
29537a229387SArnd Bergmann 	short		rt_metric;      /* +1 for binary compatibility! */
29547a229387SArnd Bergmann 	/* char * */ u32 rt_dev;        /* forcing the device at add    */
29557a229387SArnd Bergmann 	u32		rt_mtu;         /* per route MTU/Window         */
29567a229387SArnd Bergmann 	u32		rt_window;      /* Window clamping              */
29577a229387SArnd Bergmann 	unsigned short  rt_irtt;        /* Initial RTT                  */
29587a229387SArnd Bergmann };
29597a229387SArnd Bergmann 
29607a229387SArnd Bergmann struct in6_rtmsg32 {
29617a229387SArnd Bergmann 	struct in6_addr		rtmsg_dst;
29627a229387SArnd Bergmann 	struct in6_addr		rtmsg_src;
29637a229387SArnd Bergmann 	struct in6_addr		rtmsg_gateway;
29647a229387SArnd Bergmann 	u32			rtmsg_type;
29657a229387SArnd Bergmann 	u16			rtmsg_dst_len;
29667a229387SArnd Bergmann 	u16			rtmsg_src_len;
29677a229387SArnd Bergmann 	u32			rtmsg_metric;
29687a229387SArnd Bergmann 	u32			rtmsg_info;
29697a229387SArnd Bergmann 	u32			rtmsg_flags;
29707a229387SArnd Bergmann 	s32			rtmsg_ifindex;
29717a229387SArnd Bergmann };
29727a229387SArnd Bergmann 
29736b96018bSArnd Bergmann static int routing_ioctl(struct net *net, struct socket *sock,
29746b96018bSArnd Bergmann 			 unsigned int cmd, void __user *argp)
29757a229387SArnd Bergmann {
29767a229387SArnd Bergmann 	int ret;
29777a229387SArnd Bergmann 	void *r = NULL;
29787a229387SArnd Bergmann 	struct in6_rtmsg r6;
29797a229387SArnd Bergmann 	struct rtentry r4;
29807a229387SArnd Bergmann 	char devname[16];
29817a229387SArnd Bergmann 	u32 rtdev;
29827a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
29837a229387SArnd Bergmann 
29846b96018bSArnd Bergmann 	if (sock && sock->sk && sock->sk->sk_family == AF_INET6) { /* ipv6 */
29856b96018bSArnd Bergmann 		struct in6_rtmsg32 __user *ur6 = argp;
29867a229387SArnd Bergmann 		ret = copy_from_user(&r6.rtmsg_dst, &(ur6->rtmsg_dst),
29877a229387SArnd Bergmann 			3 * sizeof(struct in6_addr));
29883ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_type, &(ur6->rtmsg_type));
29893ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len));
29903ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_src_len, &(ur6->rtmsg_src_len));
29913ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_metric, &(ur6->rtmsg_metric));
29923ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_info, &(ur6->rtmsg_info));
29933ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_flags, &(ur6->rtmsg_flags));
29943ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex));
29957a229387SArnd Bergmann 
29967a229387SArnd Bergmann 		r = (void *) &r6;
29977a229387SArnd Bergmann 	} else { /* ipv4 */
29986b96018bSArnd Bergmann 		struct rtentry32 __user *ur4 = argp;
29997a229387SArnd Bergmann 		ret = copy_from_user(&r4.rt_dst, &(ur4->rt_dst),
30007a229387SArnd Bergmann 					3 * sizeof(struct sockaddr));
30013ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_flags, &(ur4->rt_flags));
30023ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_metric, &(ur4->rt_metric));
30033ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_mtu, &(ur4->rt_mtu));
30043ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_window, &(ur4->rt_window));
30053ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_irtt, &(ur4->rt_irtt));
30063ddc5b46SMathieu Desnoyers 		ret |= get_user(rtdev, &(ur4->rt_dev));
30077a229387SArnd Bergmann 		if (rtdev) {
30087a229387SArnd Bergmann 			ret |= copy_from_user(devname, compat_ptr(rtdev), 15);
3009c3f52ae6Sstephen hemminger 			r4.rt_dev = (char __user __force *)devname;
3010c3f52ae6Sstephen hemminger 			devname[15] = 0;
30117a229387SArnd Bergmann 		} else
30127a229387SArnd Bergmann 			r4.rt_dev = NULL;
30137a229387SArnd Bergmann 
30147a229387SArnd Bergmann 		r = (void *) &r4;
30157a229387SArnd Bergmann 	}
30167a229387SArnd Bergmann 
30177a229387SArnd Bergmann 	if (ret) {
30187a229387SArnd Bergmann 		ret = -EFAULT;
30197a229387SArnd Bergmann 		goto out;
30207a229387SArnd Bergmann 	}
30217a229387SArnd Bergmann 
30227a229387SArnd Bergmann 	set_fs(KERNEL_DS);
30236b96018bSArnd Bergmann 	ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r);
30247a229387SArnd Bergmann 	set_fs(old_fs);
30257a229387SArnd Bergmann 
30267a229387SArnd Bergmann out:
30277a229387SArnd Bergmann 	return ret;
30287a229387SArnd Bergmann }
30297a229387SArnd Bergmann 
30307a229387SArnd Bergmann /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE
30317a229387SArnd Bergmann  * for some operations; this forces use of the newer bridge-utils that
303225985edcSLucas De Marchi  * use compatible ioctls
30337a229387SArnd Bergmann  */
30346b96018bSArnd Bergmann static int old_bridge_ioctl(compat_ulong_t __user *argp)
30357a229387SArnd Bergmann {
30366b96018bSArnd Bergmann 	compat_ulong_t tmp;
30377a229387SArnd Bergmann 
30386b96018bSArnd Bergmann 	if (get_user(tmp, argp))
30397a229387SArnd Bergmann 		return -EFAULT;
30407a229387SArnd Bergmann 	if (tmp == BRCTL_GET_VERSION)
30417a229387SArnd Bergmann 		return BRCTL_VERSION + 1;
30427a229387SArnd Bergmann 	return -EINVAL;
30437a229387SArnd Bergmann }
30447a229387SArnd Bergmann 
30456b96018bSArnd Bergmann static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
30466b96018bSArnd Bergmann 			 unsigned int cmd, unsigned long arg)
30476b96018bSArnd Bergmann {
30486b96018bSArnd Bergmann 	void __user *argp = compat_ptr(arg);
30496b96018bSArnd Bergmann 	struct sock *sk = sock->sk;
30506b96018bSArnd Bergmann 	struct net *net = sock_net(sk);
30517a229387SArnd Bergmann 
30526b96018bSArnd Bergmann 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
3053590d4693SBen Hutchings 		return compat_ifr_data_ioctl(net, cmd, argp);
30547a229387SArnd Bergmann 
30556b96018bSArnd Bergmann 	switch (cmd) {
30566b96018bSArnd Bergmann 	case SIOCSIFBR:
30576b96018bSArnd Bergmann 	case SIOCGIFBR:
30586b96018bSArnd Bergmann 		return old_bridge_ioctl(argp);
30596b96018bSArnd Bergmann 	case SIOCGIFNAME:
30606b96018bSArnd Bergmann 		return dev_ifname32(net, argp);
30616b96018bSArnd Bergmann 	case SIOCGIFCONF:
30626b96018bSArnd Bergmann 		return dev_ifconf(net, argp);
30636b96018bSArnd Bergmann 	case SIOCETHTOOL:
30646b96018bSArnd Bergmann 		return ethtool_ioctl(net, argp);
30657a50a240SArnd Bergmann 	case SIOCWANDEV:
30667a50a240SArnd Bergmann 		return compat_siocwandev(net, argp);
3067a2116ed2SArnd Bergmann 	case SIOCGIFMAP:
3068a2116ed2SArnd Bergmann 	case SIOCSIFMAP:
3069a2116ed2SArnd Bergmann 		return compat_sioc_ifmap(net, cmd, argp);
30706b96018bSArnd Bergmann 	case SIOCBONDENSLAVE:
30716b96018bSArnd Bergmann 	case SIOCBONDRELEASE:
30726b96018bSArnd Bergmann 	case SIOCBONDSETHWADDR:
30736b96018bSArnd Bergmann 	case SIOCBONDCHANGEACTIVE:
30746b96018bSArnd Bergmann 		return bond_ioctl(net, cmd, argp);
30756b96018bSArnd Bergmann 	case SIOCADDRT:
30766b96018bSArnd Bergmann 	case SIOCDELRT:
30776b96018bSArnd Bergmann 		return routing_ioctl(net, sock, cmd, argp);
30786b96018bSArnd Bergmann 	case SIOCGSTAMP:
30796b96018bSArnd Bergmann 		return do_siocgstamp(net, sock, cmd, argp);
30806b96018bSArnd Bergmann 	case SIOCGSTAMPNS:
30816b96018bSArnd Bergmann 		return do_siocgstampns(net, sock, cmd, argp);
3082590d4693SBen Hutchings 	case SIOCBONDSLAVEINFOQUERY:
3083590d4693SBen Hutchings 	case SIOCBONDINFOQUERY:
3084a2116ed2SArnd Bergmann 	case SIOCSHWTSTAMP:
3085fd468c74SBen Hutchings 	case SIOCGHWTSTAMP:
3086590d4693SBen Hutchings 		return compat_ifr_data_ioctl(net, cmd, argp);
30877a229387SArnd Bergmann 
30886b96018bSArnd Bergmann 	case FIOSETOWN:
30896b96018bSArnd Bergmann 	case SIOCSPGRP:
30906b96018bSArnd Bergmann 	case FIOGETOWN:
30916b96018bSArnd Bergmann 	case SIOCGPGRP:
30926b96018bSArnd Bergmann 	case SIOCBRADDBR:
30936b96018bSArnd Bergmann 	case SIOCBRDELBR:
30946b96018bSArnd Bergmann 	case SIOCGIFVLAN:
30956b96018bSArnd Bergmann 	case SIOCSIFVLAN:
30966b96018bSArnd Bergmann 	case SIOCADDDLCI:
30976b96018bSArnd Bergmann 	case SIOCDELDLCI:
30986b96018bSArnd Bergmann 		return sock_ioctl(file, cmd, arg);
30996b96018bSArnd Bergmann 
31006b96018bSArnd Bergmann 	case SIOCGIFFLAGS:
31016b96018bSArnd Bergmann 	case SIOCSIFFLAGS:
31026b96018bSArnd Bergmann 	case SIOCGIFMETRIC:
31036b96018bSArnd Bergmann 	case SIOCSIFMETRIC:
31046b96018bSArnd Bergmann 	case SIOCGIFMTU:
31056b96018bSArnd Bergmann 	case SIOCSIFMTU:
31066b96018bSArnd Bergmann 	case SIOCGIFMEM:
31076b96018bSArnd Bergmann 	case SIOCSIFMEM:
31086b96018bSArnd Bergmann 	case SIOCGIFHWADDR:
31096b96018bSArnd Bergmann 	case SIOCSIFHWADDR:
31106b96018bSArnd Bergmann 	case SIOCADDMULTI:
31116b96018bSArnd Bergmann 	case SIOCDELMULTI:
31126b96018bSArnd Bergmann 	case SIOCGIFINDEX:
31136b96018bSArnd Bergmann 	case SIOCGIFADDR:
31146b96018bSArnd Bergmann 	case SIOCSIFADDR:
31156b96018bSArnd Bergmann 	case SIOCSIFHWBROADCAST:
31166b96018bSArnd Bergmann 	case SIOCDIFADDR:
31176b96018bSArnd Bergmann 	case SIOCGIFBRDADDR:
31186b96018bSArnd Bergmann 	case SIOCSIFBRDADDR:
31196b96018bSArnd Bergmann 	case SIOCGIFDSTADDR:
31206b96018bSArnd Bergmann 	case SIOCSIFDSTADDR:
31216b96018bSArnd Bergmann 	case SIOCGIFNETMASK:
31226b96018bSArnd Bergmann 	case SIOCSIFNETMASK:
31236b96018bSArnd Bergmann 	case SIOCSIFPFLAGS:
31246b96018bSArnd Bergmann 	case SIOCGIFPFLAGS:
31256b96018bSArnd Bergmann 	case SIOCGIFTXQLEN:
31266b96018bSArnd Bergmann 	case SIOCSIFTXQLEN:
31276b96018bSArnd Bergmann 	case SIOCBRADDIF:
31286b96018bSArnd Bergmann 	case SIOCBRDELIF:
31299177efd3SArnd Bergmann 	case SIOCSIFNAME:
31309177efd3SArnd Bergmann 	case SIOCGMIIPHY:
31319177efd3SArnd Bergmann 	case SIOCGMIIREG:
31329177efd3SArnd Bergmann 	case SIOCSMIIREG:
31336b96018bSArnd Bergmann 		return dev_ifsioc(net, sock, cmd, argp);
31349177efd3SArnd Bergmann 
31356b96018bSArnd Bergmann 	case SIOCSARP:
31366b96018bSArnd Bergmann 	case SIOCGARP:
31376b96018bSArnd Bergmann 	case SIOCDARP:
31386b96018bSArnd Bergmann 	case SIOCATMARK:
31399177efd3SArnd Bergmann 		return sock_do_ioctl(net, sock, cmd, arg);
31409177efd3SArnd Bergmann 	}
31419177efd3SArnd Bergmann 
31426b96018bSArnd Bergmann 	return -ENOIOCTLCMD;
31436b96018bSArnd Bergmann }
31447a229387SArnd Bergmann 
314595c96174SEric Dumazet static long compat_sock_ioctl(struct file *file, unsigned int cmd,
314689bbfc95SShaun Pereira 			      unsigned long arg)
314789bbfc95SShaun Pereira {
314889bbfc95SShaun Pereira 	struct socket *sock = file->private_data;
314989bbfc95SShaun Pereira 	int ret = -ENOIOCTLCMD;
315087de87d5SDavid S. Miller 	struct sock *sk;
315187de87d5SDavid S. Miller 	struct net *net;
315287de87d5SDavid S. Miller 
315387de87d5SDavid S. Miller 	sk = sock->sk;
315487de87d5SDavid S. Miller 	net = sock_net(sk);
315589bbfc95SShaun Pereira 
315689bbfc95SShaun Pereira 	if (sock->ops->compat_ioctl)
315789bbfc95SShaun Pereira 		ret = sock->ops->compat_ioctl(sock, cmd, arg);
315889bbfc95SShaun Pereira 
315987de87d5SDavid S. Miller 	if (ret == -ENOIOCTLCMD &&
316087de87d5SDavid S. Miller 	    (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST))
316187de87d5SDavid S. Miller 		ret = compat_wext_handle_ioctl(net, cmd, arg);
316287de87d5SDavid S. Miller 
31636b96018bSArnd Bergmann 	if (ret == -ENOIOCTLCMD)
31646b96018bSArnd Bergmann 		ret = compat_sock_ioctl_trans(file, sock, cmd, arg);
31656b96018bSArnd Bergmann 
316689bbfc95SShaun Pereira 	return ret;
316789bbfc95SShaun Pereira }
316889bbfc95SShaun Pereira #endif
316989bbfc95SShaun Pereira 
3170ac5a488eSSridhar Samudrala int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
3171ac5a488eSSridhar Samudrala {
3172ac5a488eSSridhar Samudrala 	return sock->ops->bind(sock, addr, addrlen);
3173ac5a488eSSridhar Samudrala }
3174c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_bind);
3175ac5a488eSSridhar Samudrala 
3176ac5a488eSSridhar Samudrala int kernel_listen(struct socket *sock, int backlog)
3177ac5a488eSSridhar Samudrala {
3178ac5a488eSSridhar Samudrala 	return sock->ops->listen(sock, backlog);
3179ac5a488eSSridhar Samudrala }
3180c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_listen);
3181ac5a488eSSridhar Samudrala 
3182ac5a488eSSridhar Samudrala int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
3183ac5a488eSSridhar Samudrala {
3184ac5a488eSSridhar Samudrala 	struct sock *sk = sock->sk;
3185ac5a488eSSridhar Samudrala 	int err;
3186ac5a488eSSridhar Samudrala 
3187ac5a488eSSridhar Samudrala 	err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
3188ac5a488eSSridhar Samudrala 			       newsock);
3189ac5a488eSSridhar Samudrala 	if (err < 0)
3190ac5a488eSSridhar Samudrala 		goto done;
3191ac5a488eSSridhar Samudrala 
3192ac5a488eSSridhar Samudrala 	err = sock->ops->accept(sock, *newsock, flags);
3193ac5a488eSSridhar Samudrala 	if (err < 0) {
3194ac5a488eSSridhar Samudrala 		sock_release(*newsock);
3195fa8705b0STony Battersby 		*newsock = NULL;
3196ac5a488eSSridhar Samudrala 		goto done;
3197ac5a488eSSridhar Samudrala 	}
3198ac5a488eSSridhar Samudrala 
3199ac5a488eSSridhar Samudrala 	(*newsock)->ops = sock->ops;
32001b08534eSWei Yongjun 	__module_get((*newsock)->ops->owner);
3201ac5a488eSSridhar Samudrala 
3202ac5a488eSSridhar Samudrala done:
3203ac5a488eSSridhar Samudrala 	return err;
3204ac5a488eSSridhar Samudrala }
3205c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_accept);
3206ac5a488eSSridhar Samudrala 
3207ac5a488eSSridhar Samudrala int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
3208ac5a488eSSridhar Samudrala 		   int flags)
3209ac5a488eSSridhar Samudrala {
3210ac5a488eSSridhar Samudrala 	return sock->ops->connect(sock, addr, addrlen, flags);
3211ac5a488eSSridhar Samudrala }
3212c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_connect);
3213ac5a488eSSridhar Samudrala 
3214ac5a488eSSridhar Samudrala int kernel_getsockname(struct socket *sock, struct sockaddr *addr,
3215ac5a488eSSridhar Samudrala 			 int *addrlen)
3216ac5a488eSSridhar Samudrala {
3217ac5a488eSSridhar Samudrala 	return sock->ops->getname(sock, addr, addrlen, 0);
3218ac5a488eSSridhar Samudrala }
3219c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockname);
3220ac5a488eSSridhar Samudrala 
3221ac5a488eSSridhar Samudrala int kernel_getpeername(struct socket *sock, struct sockaddr *addr,
3222ac5a488eSSridhar Samudrala 			 int *addrlen)
3223ac5a488eSSridhar Samudrala {
3224ac5a488eSSridhar Samudrala 	return sock->ops->getname(sock, addr, addrlen, 1);
3225ac5a488eSSridhar Samudrala }
3226c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getpeername);
3227ac5a488eSSridhar Samudrala 
3228ac5a488eSSridhar Samudrala int kernel_getsockopt(struct socket *sock, int level, int optname,
3229ac5a488eSSridhar Samudrala 			char *optval, int *optlen)
3230ac5a488eSSridhar Samudrala {
3231ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3232fb8621bbSNamhyung Kim 	char __user *uoptval;
3233fb8621bbSNamhyung Kim 	int __user *uoptlen;
3234ac5a488eSSridhar Samudrala 	int err;
3235ac5a488eSSridhar Samudrala 
3236fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3237fb8621bbSNamhyung Kim 	uoptlen = (int __user __force *) optlen;
3238fb8621bbSNamhyung Kim 
3239ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3240ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3241fb8621bbSNamhyung Kim 		err = sock_getsockopt(sock, level, optname, uoptval, uoptlen);
3242ac5a488eSSridhar Samudrala 	else
3243fb8621bbSNamhyung Kim 		err = sock->ops->getsockopt(sock, level, optname, uoptval,
3244fb8621bbSNamhyung Kim 					    uoptlen);
3245ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3246ac5a488eSSridhar Samudrala 	return err;
3247ac5a488eSSridhar Samudrala }
3248c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockopt);
3249ac5a488eSSridhar Samudrala 
3250ac5a488eSSridhar Samudrala int kernel_setsockopt(struct socket *sock, int level, int optname,
3251b7058842SDavid S. Miller 			char *optval, unsigned int optlen)
3252ac5a488eSSridhar Samudrala {
3253ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3254fb8621bbSNamhyung Kim 	char __user *uoptval;
3255ac5a488eSSridhar Samudrala 	int err;
3256ac5a488eSSridhar Samudrala 
3257fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3258fb8621bbSNamhyung Kim 
3259ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3260ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3261fb8621bbSNamhyung Kim 		err = sock_setsockopt(sock, level, optname, uoptval, optlen);
3262ac5a488eSSridhar Samudrala 	else
3263fb8621bbSNamhyung Kim 		err = sock->ops->setsockopt(sock, level, optname, uoptval,
3264ac5a488eSSridhar Samudrala 					    optlen);
3265ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3266ac5a488eSSridhar Samudrala 	return err;
3267ac5a488eSSridhar Samudrala }
3268c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_setsockopt);
3269ac5a488eSSridhar Samudrala 
3270ac5a488eSSridhar Samudrala int kernel_sendpage(struct socket *sock, struct page *page, int offset,
3271ac5a488eSSridhar Samudrala 		    size_t size, int flags)
3272ac5a488eSSridhar Samudrala {
3273ac5a488eSSridhar Samudrala 	if (sock->ops->sendpage)
3274ac5a488eSSridhar Samudrala 		return sock->ops->sendpage(sock, page, offset, size, flags);
3275ac5a488eSSridhar Samudrala 
3276ac5a488eSSridhar Samudrala 	return sock_no_sendpage(sock, page, offset, size, flags);
3277ac5a488eSSridhar Samudrala }
3278c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendpage);
3279ac5a488eSSridhar Samudrala 
3280ac5a488eSSridhar Samudrala int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg)
3281ac5a488eSSridhar Samudrala {
3282ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3283ac5a488eSSridhar Samudrala 	int err;
3284ac5a488eSSridhar Samudrala 
3285ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3286ac5a488eSSridhar Samudrala 	err = sock->ops->ioctl(sock, cmd, arg);
3287ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3288ac5a488eSSridhar Samudrala 
3289ac5a488eSSridhar Samudrala 	return err;
3290ac5a488eSSridhar Samudrala }
3291c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sock_ioctl);
3292ac5a488eSSridhar Samudrala 
329391cf45f0STrond Myklebust int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
329491cf45f0STrond Myklebust {
329591cf45f0STrond Myklebust 	return sock->ops->shutdown(sock, how);
329691cf45f0STrond Myklebust }
329791cf45f0STrond Myklebust EXPORT_SYMBOL(kernel_sock_shutdown);
3298