xref: /openbmc/linux/net/socket.c (revision d8d211a2)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * NET		An implementation of the SOCKET network access protocol.
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Version:	@(#)socket.c	1.1.93	18/02/95
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * Authors:	Orest Zborowski, <obz@Kodak.COM>
702c30a84SJesper Juhl  *		Ross Biro
81da177e4SLinus Torvalds  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
91da177e4SLinus Torvalds  *
101da177e4SLinus Torvalds  * Fixes:
111da177e4SLinus Torvalds  *		Anonymous	:	NOTSOCK/BADF cleanup. Error fix in
121da177e4SLinus Torvalds  *					shutdown()
131da177e4SLinus Torvalds  *		Alan Cox	:	verify_area() fixes
141da177e4SLinus Torvalds  *		Alan Cox	:	Removed DDI
151da177e4SLinus Torvalds  *		Jonathan Kamens	:	SOCK_DGRAM reconnect bug
161da177e4SLinus Torvalds  *		Alan Cox	:	Moved a load of checks to the very
171da177e4SLinus Torvalds  *					top level.
181da177e4SLinus Torvalds  *		Alan Cox	:	Move address structures to/from user
191da177e4SLinus Torvalds  *					mode above the protocol layers.
201da177e4SLinus Torvalds  *		Rob Janssen	:	Allow 0 length sends.
211da177e4SLinus Torvalds  *		Alan Cox	:	Asynchronous I/O support (cribbed from the
221da177e4SLinus Torvalds  *					tty drivers).
231da177e4SLinus Torvalds  *		Niibe Yutaka	:	Asynchronous I/O for writes (4.4BSD style)
241da177e4SLinus Torvalds  *		Jeff Uphoff	:	Made max number of sockets command-line
251da177e4SLinus Torvalds  *					configurable.
261da177e4SLinus Torvalds  *		Matti Aarnio	:	Made the number of sockets dynamic,
271da177e4SLinus Torvalds  *					to be allocated when needed, and mr.
281da177e4SLinus Torvalds  *					Uphoff's max is used as max to be
291da177e4SLinus Torvalds  *					allowed to allocate.
301da177e4SLinus Torvalds  *		Linus		:	Argh. removed all the socket allocation
311da177e4SLinus Torvalds  *					altogether: it's in the inode now.
321da177e4SLinus Torvalds  *		Alan Cox	:	Made sock_alloc()/sock_release() public
331da177e4SLinus Torvalds  *					for NetROM and future kernel nfsd type
341da177e4SLinus Torvalds  *					stuff.
351da177e4SLinus Torvalds  *		Alan Cox	:	sendmsg/recvmsg basics.
361da177e4SLinus Torvalds  *		Tom Dyas	:	Export net symbols.
371da177e4SLinus Torvalds  *		Marcin Dalecki	:	Fixed problems with CONFIG_NET="n".
381da177e4SLinus Torvalds  *		Alan Cox	:	Added thread locking to sys_* calls
391da177e4SLinus Torvalds  *					for sockets. May have errors at the
401da177e4SLinus Torvalds  *					moment.
411da177e4SLinus Torvalds  *		Kevin Buhr	:	Fixed the dumb errors in the above.
421da177e4SLinus Torvalds  *		Andi Kleen	:	Some small cleanups, optimizations,
431da177e4SLinus Torvalds  *					and fixed a copy_from_user() bug.
441da177e4SLinus Torvalds  *		Tigran Aivazian	:	sys_send(args) calls sys_sendto(args, NULL, 0)
451da177e4SLinus Torvalds  *		Tigran Aivazian	:	Made listen(2) backlog sanity checks
461da177e4SLinus Torvalds  *					protocol-independent
471da177e4SLinus Torvalds  *
481da177e4SLinus Torvalds  *
491da177e4SLinus Torvalds  *		This program is free software; you can redistribute it and/or
501da177e4SLinus Torvalds  *		modify it under the terms of the GNU General Public License
511da177e4SLinus Torvalds  *		as published by the Free Software Foundation; either version
521da177e4SLinus Torvalds  *		2 of the License, or (at your option) any later version.
531da177e4SLinus Torvalds  *
541da177e4SLinus Torvalds  *
551da177e4SLinus Torvalds  *	This module is effectively the top level interface to the BSD socket
561da177e4SLinus Torvalds  *	paradigm.
571da177e4SLinus Torvalds  *
581da177e4SLinus Torvalds  *	Based upon Swansea University Computer Society NET3.039
591da177e4SLinus Torvalds  */
601da177e4SLinus Torvalds 
611da177e4SLinus Torvalds #include <linux/mm.h>
621da177e4SLinus Torvalds #include <linux/socket.h>
631da177e4SLinus Torvalds #include <linux/file.h>
641da177e4SLinus Torvalds #include <linux/net.h>
651da177e4SLinus Torvalds #include <linux/interrupt.h>
66aaca0bdcSUlrich Drepper #include <linux/thread_info.h>
6755737fdaSStephen Hemminger #include <linux/rcupdate.h>
681da177e4SLinus Torvalds #include <linux/netdevice.h>
691da177e4SLinus Torvalds #include <linux/proc_fs.h>
701da177e4SLinus Torvalds #include <linux/seq_file.h>
714a3e2f71SArjan van de Ven #include <linux/mutex.h>
721da177e4SLinus Torvalds #include <linux/if_bridge.h>
7320380731SArnaldo Carvalho de Melo #include <linux/if_frad.h>
7420380731SArnaldo Carvalho de Melo #include <linux/if_vlan.h>
75408eccceSDaniel Borkmann #include <linux/ptp_classify.h>
761da177e4SLinus Torvalds #include <linux/init.h>
771da177e4SLinus Torvalds #include <linux/poll.h>
781da177e4SLinus Torvalds #include <linux/cache.h>
791da177e4SLinus Torvalds #include <linux/module.h>
801da177e4SLinus Torvalds #include <linux/highmem.h>
811da177e4SLinus Torvalds #include <linux/mount.h>
821da177e4SLinus Torvalds #include <linux/security.h>
831da177e4SLinus Torvalds #include <linux/syscalls.h>
841da177e4SLinus Torvalds #include <linux/compat.h>
851da177e4SLinus Torvalds #include <linux/kmod.h>
863ec3b2fbSDavid Woodhouse #include <linux/audit.h>
87d86b5e0eSAdrian Bunk #include <linux/wireless.h>
881b8d7ae4SEric W. Biederman #include <linux/nsproxy.h>
891fd7317dSNick Black #include <linux/magic.h>
905a0e3ad6STejun Heo #include <linux/slab.h>
91600e1779SMasatake YAMATO #include <linux/xattr.h>
921da177e4SLinus Torvalds 
937c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
941da177e4SLinus Torvalds #include <asm/unistd.h>
951da177e4SLinus Torvalds 
961da177e4SLinus Torvalds #include <net/compat.h>
9787de87d5SDavid S. Miller #include <net/wext.h>
98f8451725SHerbert Xu #include <net/cls_cgroup.h>
991da177e4SLinus Torvalds 
1001da177e4SLinus Torvalds #include <net/sock.h>
1011da177e4SLinus Torvalds #include <linux/netfilter.h>
1021da177e4SLinus Torvalds 
1036b96018bSArnd Bergmann #include <linux/if_tun.h>
1046b96018bSArnd Bergmann #include <linux/ipv6_route.h>
1056b96018bSArnd Bergmann #include <linux/route.h>
1066b96018bSArnd Bergmann #include <linux/sockios.h>
107076bb0c8SEliezer Tamir #include <net/busy_poll.h>
108f24b9be5SWillem de Bruijn #include <linux/errqueue.h>
10906021292SEliezer Tamir 
110e0d1095aSCong Wang #ifdef CONFIG_NET_RX_BUSY_POLL
11164b0dc51SEliezer Tamir unsigned int sysctl_net_busy_read __read_mostly;
11264b0dc51SEliezer Tamir unsigned int sysctl_net_busy_poll __read_mostly;
11306021292SEliezer Tamir #endif
1146b96018bSArnd Bergmann 
1158ae5e030SAl Viro static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to);
1168ae5e030SAl Viro static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from);
1171da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma);
1181da177e4SLinus Torvalds 
1191da177e4SLinus Torvalds static int sock_close(struct inode *inode, struct file *file);
120ade994f4SAl Viro static __poll_t sock_poll(struct file *file,
1211da177e4SLinus Torvalds 			      struct poll_table_struct *wait);
12289bddce5SStephen Hemminger static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
12389bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
12489bbfc95SShaun Pereira static long compat_sock_ioctl(struct file *file,
12589bbfc95SShaun Pereira 			      unsigned int cmd, unsigned long arg);
12689bbfc95SShaun Pereira #endif
1271da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on);
1281da177e4SLinus Torvalds static ssize_t sock_sendpage(struct file *file, struct page *page,
1291da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more);
1309c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
1319c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
1329c55e01cSJens Axboe 				unsigned int flags);
1331da177e4SLinus Torvalds 
1341da177e4SLinus Torvalds /*
1351da177e4SLinus Torvalds  *	Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
1361da177e4SLinus Torvalds  *	in the operation structures but are done directly via the socketcall() multiplexor.
1371da177e4SLinus Torvalds  */
1381da177e4SLinus Torvalds 
139da7071d7SArjan van de Ven static const struct file_operations socket_file_ops = {
1401da177e4SLinus Torvalds 	.owner =	THIS_MODULE,
1411da177e4SLinus Torvalds 	.llseek =	no_llseek,
1428ae5e030SAl Viro 	.read_iter =	sock_read_iter,
1438ae5e030SAl Viro 	.write_iter =	sock_write_iter,
1441da177e4SLinus Torvalds 	.poll =		sock_poll,
1451da177e4SLinus Torvalds 	.unlocked_ioctl = sock_ioctl,
14689bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
14789bbfc95SShaun Pereira 	.compat_ioctl = compat_sock_ioctl,
14889bbfc95SShaun Pereira #endif
1491da177e4SLinus Torvalds 	.mmap =		sock_mmap,
1501da177e4SLinus Torvalds 	.release =	sock_close,
1511da177e4SLinus Torvalds 	.fasync =	sock_fasync,
1525274f052SJens Axboe 	.sendpage =	sock_sendpage,
1535274f052SJens Axboe 	.splice_write = generic_splice_sendpage,
1549c55e01cSJens Axboe 	.splice_read =	sock_splice_read,
1551da177e4SLinus Torvalds };
1561da177e4SLinus Torvalds 
1571da177e4SLinus Torvalds /*
1581da177e4SLinus Torvalds  *	The protocol list. Each protocol is registered in here.
1591da177e4SLinus Torvalds  */
1601da177e4SLinus Torvalds 
1611da177e4SLinus Torvalds static DEFINE_SPINLOCK(net_family_lock);
162190683a9SEric Dumazet static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly;
1631da177e4SLinus Torvalds 
1641da177e4SLinus Torvalds /*
16589bddce5SStephen Hemminger  * Support routines.
16689bddce5SStephen Hemminger  * Move socket addresses back and forth across the kernel/user
1671da177e4SLinus Torvalds  * divide and look after the messy bits.
1681da177e4SLinus Torvalds  */
1691da177e4SLinus Torvalds 
1701da177e4SLinus Torvalds /**
1711da177e4SLinus Torvalds  *	move_addr_to_kernel	-	copy a socket address into kernel space
1721da177e4SLinus Torvalds  *	@uaddr: Address in user space
1731da177e4SLinus Torvalds  *	@kaddr: Address in kernel space
1741da177e4SLinus Torvalds  *	@ulen: Length in user space
1751da177e4SLinus Torvalds  *
1761da177e4SLinus Torvalds  *	The address is copied into kernel space. If the provided address is
1771da177e4SLinus Torvalds  *	too long an error code of -EINVAL is returned. If the copy gives
1781da177e4SLinus Torvalds  *	invalid addresses -EFAULT is returned. On a success 0 is returned.
1791da177e4SLinus Torvalds  */
1801da177e4SLinus Torvalds 
18143db362dSMaciej Żenczykowski int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr)
1821da177e4SLinus Torvalds {
183230b1839SYOSHIFUJI Hideaki 	if (ulen < 0 || ulen > sizeof(struct sockaddr_storage))
1841da177e4SLinus Torvalds 		return -EINVAL;
1851da177e4SLinus Torvalds 	if (ulen == 0)
1861da177e4SLinus Torvalds 		return 0;
1871da177e4SLinus Torvalds 	if (copy_from_user(kaddr, uaddr, ulen))
1881da177e4SLinus Torvalds 		return -EFAULT;
1893ec3b2fbSDavid Woodhouse 	return audit_sockaddr(ulen, kaddr);
1901da177e4SLinus Torvalds }
1911da177e4SLinus Torvalds 
1921da177e4SLinus Torvalds /**
1931da177e4SLinus Torvalds  *	move_addr_to_user	-	copy an address to user space
1941da177e4SLinus Torvalds  *	@kaddr: kernel space address
1951da177e4SLinus Torvalds  *	@klen: length of address in kernel
1961da177e4SLinus Torvalds  *	@uaddr: user space address
1971da177e4SLinus Torvalds  *	@ulen: pointer to user length field
1981da177e4SLinus Torvalds  *
1991da177e4SLinus Torvalds  *	The value pointed to by ulen on entry is the buffer length available.
2001da177e4SLinus Torvalds  *	This is overwritten with the buffer space used. -EINVAL is returned
2011da177e4SLinus Torvalds  *	if an overlong buffer is specified or a negative buffer size. -EFAULT
2021da177e4SLinus Torvalds  *	is returned if either the buffer or the length field are not
2031da177e4SLinus Torvalds  *	accessible.
2041da177e4SLinus Torvalds  *	After copying the data up to the limit the user specifies, the true
2051da177e4SLinus Torvalds  *	length of the data is written over the length limit the user
2061da177e4SLinus Torvalds  *	specified. Zero is returned for a success.
2071da177e4SLinus Torvalds  */
2081da177e4SLinus Torvalds 
20943db362dSMaciej Żenczykowski static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen,
21011165f14Sstephen hemminger 			     void __user *uaddr, int __user *ulen)
2111da177e4SLinus Torvalds {
2121da177e4SLinus Torvalds 	int err;
2131da177e4SLinus Torvalds 	int len;
2141da177e4SLinus Torvalds 
21568c6beb3SHannes Frederic Sowa 	BUG_ON(klen > sizeof(struct sockaddr_storage));
21689bddce5SStephen Hemminger 	err = get_user(len, ulen);
21789bddce5SStephen Hemminger 	if (err)
2181da177e4SLinus Torvalds 		return err;
2191da177e4SLinus Torvalds 	if (len > klen)
2201da177e4SLinus Torvalds 		len = klen;
22168c6beb3SHannes Frederic Sowa 	if (len < 0)
2221da177e4SLinus Torvalds 		return -EINVAL;
22389bddce5SStephen Hemminger 	if (len) {
224d6fe3945SSteve Grubb 		if (audit_sockaddr(klen, kaddr))
225d6fe3945SSteve Grubb 			return -ENOMEM;
2261da177e4SLinus Torvalds 		if (copy_to_user(uaddr, kaddr, len))
2271da177e4SLinus Torvalds 			return -EFAULT;
2281da177e4SLinus Torvalds 	}
2291da177e4SLinus Torvalds 	/*
2301da177e4SLinus Torvalds 	 *      "fromlen shall refer to the value before truncation.."
2311da177e4SLinus Torvalds 	 *                      1003.1g
2321da177e4SLinus Torvalds 	 */
2331da177e4SLinus Torvalds 	return __put_user(klen, ulen);
2341da177e4SLinus Torvalds }
2351da177e4SLinus Torvalds 
236e18b890bSChristoph Lameter static struct kmem_cache *sock_inode_cachep __read_mostly;
2371da177e4SLinus Torvalds 
2381da177e4SLinus Torvalds static struct inode *sock_alloc_inode(struct super_block *sb)
2391da177e4SLinus Torvalds {
2401da177e4SLinus Torvalds 	struct socket_alloc *ei;
241eaefd110SEric Dumazet 	struct socket_wq *wq;
24289bddce5SStephen Hemminger 
243e94b1766SChristoph Lameter 	ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL);
2441da177e4SLinus Torvalds 	if (!ei)
2451da177e4SLinus Torvalds 		return NULL;
246eaefd110SEric Dumazet 	wq = kmalloc(sizeof(*wq), GFP_KERNEL);
247eaefd110SEric Dumazet 	if (!wq) {
24843815482SEric Dumazet 		kmem_cache_free(sock_inode_cachep, ei);
24943815482SEric Dumazet 		return NULL;
25043815482SEric Dumazet 	}
251eaefd110SEric Dumazet 	init_waitqueue_head(&wq->wait);
252eaefd110SEric Dumazet 	wq->fasync_list = NULL;
253574aab1eSNicolai Stange 	wq->flags = 0;
254eaefd110SEric Dumazet 	RCU_INIT_POINTER(ei->socket.wq, wq);
2551da177e4SLinus Torvalds 
2561da177e4SLinus Torvalds 	ei->socket.state = SS_UNCONNECTED;
2571da177e4SLinus Torvalds 	ei->socket.flags = 0;
2581da177e4SLinus Torvalds 	ei->socket.ops = NULL;
2591da177e4SLinus Torvalds 	ei->socket.sk = NULL;
2601da177e4SLinus Torvalds 	ei->socket.file = NULL;
2611da177e4SLinus Torvalds 
2621da177e4SLinus Torvalds 	return &ei->vfs_inode;
2631da177e4SLinus Torvalds }
2641da177e4SLinus Torvalds 
2651da177e4SLinus Torvalds static void sock_destroy_inode(struct inode *inode)
2661da177e4SLinus Torvalds {
26743815482SEric Dumazet 	struct socket_alloc *ei;
268eaefd110SEric Dumazet 	struct socket_wq *wq;
26943815482SEric Dumazet 
27043815482SEric Dumazet 	ei = container_of(inode, struct socket_alloc, vfs_inode);
271eaefd110SEric Dumazet 	wq = rcu_dereference_protected(ei->socket.wq, 1);
27261845220SLai Jiangshan 	kfree_rcu(wq, rcu);
27343815482SEric Dumazet 	kmem_cache_free(sock_inode_cachep, ei);
2741da177e4SLinus Torvalds }
2751da177e4SLinus Torvalds 
27651cc5068SAlexey Dobriyan static void init_once(void *foo)
2771da177e4SLinus Torvalds {
2781da177e4SLinus Torvalds 	struct socket_alloc *ei = (struct socket_alloc *)foo;
2791da177e4SLinus Torvalds 
2801da177e4SLinus Torvalds 	inode_init_once(&ei->vfs_inode);
2811da177e4SLinus Torvalds }
2821da177e4SLinus Torvalds 
2831e911632Syuan linyu static void init_inodecache(void)
2841da177e4SLinus Torvalds {
2851da177e4SLinus Torvalds 	sock_inode_cachep = kmem_cache_create("sock_inode_cache",
2861da177e4SLinus Torvalds 					      sizeof(struct socket_alloc),
28789bddce5SStephen Hemminger 					      0,
28889bddce5SStephen Hemminger 					      (SLAB_HWCACHE_ALIGN |
28989bddce5SStephen Hemminger 					       SLAB_RECLAIM_ACCOUNT |
2905d097056SVladimir Davydov 					       SLAB_MEM_SPREAD | SLAB_ACCOUNT),
29120c2df83SPaul Mundt 					      init_once);
2921e911632Syuan linyu 	BUG_ON(sock_inode_cachep == NULL);
2931da177e4SLinus Torvalds }
2941da177e4SLinus Torvalds 
295b87221deSAlexey Dobriyan static const struct super_operations sockfs_ops = {
2961da177e4SLinus Torvalds 	.alloc_inode	= sock_alloc_inode,
2971da177e4SLinus Torvalds 	.destroy_inode	= sock_destroy_inode,
2981da177e4SLinus Torvalds 	.statfs		= simple_statfs,
2991da177e4SLinus Torvalds };
3001da177e4SLinus Torvalds 
301c23fbb6bSEric Dumazet /*
302c23fbb6bSEric Dumazet  * sockfs_dname() is called from d_path().
303c23fbb6bSEric Dumazet  */
304c23fbb6bSEric Dumazet static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen)
305c23fbb6bSEric Dumazet {
306c23fbb6bSEric Dumazet 	return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]",
307c5ef6035SDavid Howells 				d_inode(dentry)->i_ino);
308c23fbb6bSEric Dumazet }
309c23fbb6bSEric Dumazet 
3103ba13d17SAl Viro static const struct dentry_operations sockfs_dentry_operations = {
311c23fbb6bSEric Dumazet 	.d_dname  = sockfs_dname,
3121da177e4SLinus Torvalds };
3131da177e4SLinus Torvalds 
314bba0bd31SAndreas Gruenbacher static int sockfs_xattr_get(const struct xattr_handler *handler,
315bba0bd31SAndreas Gruenbacher 			    struct dentry *dentry, struct inode *inode,
316bba0bd31SAndreas Gruenbacher 			    const char *suffix, void *value, size_t size)
317bba0bd31SAndreas Gruenbacher {
318bba0bd31SAndreas Gruenbacher 	if (value) {
319bba0bd31SAndreas Gruenbacher 		if (dentry->d_name.len + 1 > size)
320bba0bd31SAndreas Gruenbacher 			return -ERANGE;
321bba0bd31SAndreas Gruenbacher 		memcpy(value, dentry->d_name.name, dentry->d_name.len + 1);
322bba0bd31SAndreas Gruenbacher 	}
323bba0bd31SAndreas Gruenbacher 	return dentry->d_name.len + 1;
324bba0bd31SAndreas Gruenbacher }
325bba0bd31SAndreas Gruenbacher 
326bba0bd31SAndreas Gruenbacher #define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname"
327bba0bd31SAndreas Gruenbacher #define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX)
328bba0bd31SAndreas Gruenbacher #define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1)
329bba0bd31SAndreas Gruenbacher 
330bba0bd31SAndreas Gruenbacher static const struct xattr_handler sockfs_xattr_handler = {
331bba0bd31SAndreas Gruenbacher 	.name = XATTR_NAME_SOCKPROTONAME,
332bba0bd31SAndreas Gruenbacher 	.get = sockfs_xattr_get,
333bba0bd31SAndreas Gruenbacher };
334bba0bd31SAndreas Gruenbacher 
3354a590153SAndreas Gruenbacher static int sockfs_security_xattr_set(const struct xattr_handler *handler,
3364a590153SAndreas Gruenbacher 				     struct dentry *dentry, struct inode *inode,
3374a590153SAndreas Gruenbacher 				     const char *suffix, const void *value,
3384a590153SAndreas Gruenbacher 				     size_t size, int flags)
3394a590153SAndreas Gruenbacher {
3404a590153SAndreas Gruenbacher 	/* Handled by LSM. */
3414a590153SAndreas Gruenbacher 	return -EAGAIN;
3424a590153SAndreas Gruenbacher }
3434a590153SAndreas Gruenbacher 
3444a590153SAndreas Gruenbacher static const struct xattr_handler sockfs_security_xattr_handler = {
3454a590153SAndreas Gruenbacher 	.prefix = XATTR_SECURITY_PREFIX,
3464a590153SAndreas Gruenbacher 	.set = sockfs_security_xattr_set,
3474a590153SAndreas Gruenbacher };
3484a590153SAndreas Gruenbacher 
349bba0bd31SAndreas Gruenbacher static const struct xattr_handler *sockfs_xattr_handlers[] = {
350bba0bd31SAndreas Gruenbacher 	&sockfs_xattr_handler,
3514a590153SAndreas Gruenbacher 	&sockfs_security_xattr_handler,
352bba0bd31SAndreas Gruenbacher 	NULL
353bba0bd31SAndreas Gruenbacher };
354bba0bd31SAndreas Gruenbacher 
355c74a1cbbSAl Viro static struct dentry *sockfs_mount(struct file_system_type *fs_type,
356c74a1cbbSAl Viro 			 int flags, const char *dev_name, void *data)
357c74a1cbbSAl Viro {
358bba0bd31SAndreas Gruenbacher 	return mount_pseudo_xattr(fs_type, "socket:", &sockfs_ops,
359bba0bd31SAndreas Gruenbacher 				  sockfs_xattr_handlers,
360c74a1cbbSAl Viro 				  &sockfs_dentry_operations, SOCKFS_MAGIC);
361c74a1cbbSAl Viro }
362c74a1cbbSAl Viro 
363c74a1cbbSAl Viro static struct vfsmount *sock_mnt __read_mostly;
364c74a1cbbSAl Viro 
365c74a1cbbSAl Viro static struct file_system_type sock_fs_type = {
366c74a1cbbSAl Viro 	.name =		"sockfs",
367c74a1cbbSAl Viro 	.mount =	sockfs_mount,
368c74a1cbbSAl Viro 	.kill_sb =	kill_anon_super,
369c74a1cbbSAl Viro };
370c74a1cbbSAl Viro 
3711da177e4SLinus Torvalds /*
3721da177e4SLinus Torvalds  *	Obtains the first available file descriptor and sets it up for use.
3731da177e4SLinus Torvalds  *
37439d8c1b6SDavid S. Miller  *	These functions create file structures and maps them to fd space
37539d8c1b6SDavid S. Miller  *	of the current process. On success it returns file descriptor
3761da177e4SLinus Torvalds  *	and file struct implicitly stored in sock->file.
3771da177e4SLinus Torvalds  *	Note that another thread may close file descriptor before we return
3781da177e4SLinus Torvalds  *	from this function. We use the fact that now we do not refer
3791da177e4SLinus Torvalds  *	to socket after mapping. If one day we will need it, this
3801da177e4SLinus Torvalds  *	function will increment ref. count on file by 1.
3811da177e4SLinus Torvalds  *
3821da177e4SLinus Torvalds  *	In any case returned fd MAY BE not valid!
3831da177e4SLinus Torvalds  *	This race condition is unavoidable
3841da177e4SLinus Torvalds  *	with shared fd spaces, we cannot solve it inside kernel,
3851da177e4SLinus Torvalds  *	but we take care of internal coherence yet.
3861da177e4SLinus Torvalds  */
3871da177e4SLinus Torvalds 
388aab174f0SLinus Torvalds struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)
3891da177e4SLinus Torvalds {
3907cbe66b6SAl Viro 	struct qstr name = { .name = "" };
3912c48b9c4SAl Viro 	struct path path;
3927cbe66b6SAl Viro 	struct file *file;
3931da177e4SLinus Torvalds 
394600e1779SMasatake YAMATO 	if (dname) {
395600e1779SMasatake YAMATO 		name.name = dname;
396600e1779SMasatake YAMATO 		name.len = strlen(name.name);
397600e1779SMasatake YAMATO 	} else if (sock->sk) {
398600e1779SMasatake YAMATO 		name.name = sock->sk->sk_prot_creator->name;
399600e1779SMasatake YAMATO 		name.len = strlen(name.name);
400600e1779SMasatake YAMATO 	}
4014b936885SNick Piggin 	path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name);
4028e1611e2SAl Viro 	if (unlikely(!path.dentry)) {
4038e1611e2SAl Viro 		sock_release(sock);
40428407630SAl Viro 		return ERR_PTR(-ENOMEM);
4058e1611e2SAl Viro 	}
4062c48b9c4SAl Viro 	path.mnt = mntget(sock_mnt);
40739d8c1b6SDavid S. Miller 
4082c48b9c4SAl Viro 	d_instantiate(path.dentry, SOCK_INODE(sock));
409cc3808f8SAl Viro 
4102c48b9c4SAl Viro 	file = alloc_file(&path, FMODE_READ | FMODE_WRITE,
411cc3808f8SAl Viro 		  &socket_file_ops);
412b5ffe634SViresh Kumar 	if (IS_ERR(file)) {
4138e1611e2SAl Viro 		/* drop dentry, keep inode for a bit */
414c5ef6035SDavid Howells 		ihold(d_inode(path.dentry));
4152c48b9c4SAl Viro 		path_put(&path);
4168e1611e2SAl Viro 		/* ... and now kill it properly */
4178e1611e2SAl Viro 		sock_release(sock);
41839b65252SAnatol Pomozov 		return file;
419cc3808f8SAl Viro 	}
4201da177e4SLinus Torvalds 
4211da177e4SLinus Torvalds 	sock->file = file;
42277d27200SUlrich Drepper 	file->f_flags = O_RDWR | (flags & O_NONBLOCK);
42307dc3f07SBenjamin LaHaise 	file->private_data = sock;
42428407630SAl Viro 	return file;
4251da177e4SLinus Torvalds }
42656b31d1cSAl Viro EXPORT_SYMBOL(sock_alloc_file);
4271da177e4SLinus Torvalds 
42856b31d1cSAl Viro static int sock_map_fd(struct socket *sock, int flags)
42939d8c1b6SDavid S. Miller {
43039d8c1b6SDavid S. Miller 	struct file *newfile;
43128407630SAl Viro 	int fd = get_unused_fd_flags(flags);
432ce4bb04cSAl Viro 	if (unlikely(fd < 0)) {
433ce4bb04cSAl Viro 		sock_release(sock);
4341da177e4SLinus Torvalds 		return fd;
435ce4bb04cSAl Viro 	}
4361da177e4SLinus Torvalds 
437aab174f0SLinus Torvalds 	newfile = sock_alloc_file(sock, flags, NULL);
43828407630SAl Viro 	if (likely(!IS_ERR(newfile))) {
4391da177e4SLinus Torvalds 		fd_install(fd, newfile);
4401da177e4SLinus Torvalds 		return fd;
4411da177e4SLinus Torvalds 	}
44228407630SAl Viro 
44328407630SAl Viro 	put_unused_fd(fd);
44428407630SAl Viro 	return PTR_ERR(newfile);
4451da177e4SLinus Torvalds }
4461da177e4SLinus Torvalds 
447406a3c63SJohn Fastabend struct socket *sock_from_file(struct file *file, int *err)
4486cb153caSBenjamin LaHaise {
4496cb153caSBenjamin LaHaise 	if (file->f_op == &socket_file_ops)
4506cb153caSBenjamin LaHaise 		return file->private_data;	/* set in sock_map_fd */
4516cb153caSBenjamin LaHaise 
4526cb153caSBenjamin LaHaise 	*err = -ENOTSOCK;
4536cb153caSBenjamin LaHaise 	return NULL;
4546cb153caSBenjamin LaHaise }
455406a3c63SJohn Fastabend EXPORT_SYMBOL(sock_from_file);
4566cb153caSBenjamin LaHaise 
4571da177e4SLinus Torvalds /**
4581da177e4SLinus Torvalds  *	sockfd_lookup - Go from a file number to its socket slot
4591da177e4SLinus Torvalds  *	@fd: file handle
4601da177e4SLinus Torvalds  *	@err: pointer to an error code return
4611da177e4SLinus Torvalds  *
4621da177e4SLinus Torvalds  *	The file handle passed in is locked and the socket it is bound
463241c4667SRosen, Rami  *	to is returned. If an error occurs the err pointer is overwritten
4641da177e4SLinus Torvalds  *	with a negative errno code and NULL is returned. The function checks
4651da177e4SLinus Torvalds  *	for both invalid handles and passing a handle which is not a socket.
4661da177e4SLinus Torvalds  *
4671da177e4SLinus Torvalds  *	On a success the socket object pointer is returned.
4681da177e4SLinus Torvalds  */
4691da177e4SLinus Torvalds 
4701da177e4SLinus Torvalds struct socket *sockfd_lookup(int fd, int *err)
4711da177e4SLinus Torvalds {
4721da177e4SLinus Torvalds 	struct file *file;
4731da177e4SLinus Torvalds 	struct socket *sock;
4741da177e4SLinus Torvalds 
47589bddce5SStephen Hemminger 	file = fget(fd);
47689bddce5SStephen Hemminger 	if (!file) {
4771da177e4SLinus Torvalds 		*err = -EBADF;
4781da177e4SLinus Torvalds 		return NULL;
4791da177e4SLinus Torvalds 	}
48089bddce5SStephen Hemminger 
4816cb153caSBenjamin LaHaise 	sock = sock_from_file(file, err);
4826cb153caSBenjamin LaHaise 	if (!sock)
4831da177e4SLinus Torvalds 		fput(file);
4846cb153caSBenjamin LaHaise 	return sock;
4851da177e4SLinus Torvalds }
486c6d409cfSEric Dumazet EXPORT_SYMBOL(sockfd_lookup);
4871da177e4SLinus Torvalds 
4886cb153caSBenjamin LaHaise static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
4896cb153caSBenjamin LaHaise {
49000e188efSAl Viro 	struct fd f = fdget(fd);
4916cb153caSBenjamin LaHaise 	struct socket *sock;
4926cb153caSBenjamin LaHaise 
4933672558cSHua Zhong 	*err = -EBADF;
49400e188efSAl Viro 	if (f.file) {
49500e188efSAl Viro 		sock = sock_from_file(f.file, err);
49600e188efSAl Viro 		if (likely(sock)) {
49700e188efSAl Viro 			*fput_needed = f.flags;
4981da177e4SLinus Torvalds 			return sock;
49900e188efSAl Viro 		}
50000e188efSAl Viro 		fdput(f);
5016cb153caSBenjamin LaHaise 	}
5026cb153caSBenjamin LaHaise 	return NULL;
5031da177e4SLinus Torvalds }
5041da177e4SLinus Torvalds 
505600e1779SMasatake YAMATO static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer,
506600e1779SMasatake YAMATO 				size_t size)
507600e1779SMasatake YAMATO {
508600e1779SMasatake YAMATO 	ssize_t len;
509600e1779SMasatake YAMATO 	ssize_t used = 0;
510600e1779SMasatake YAMATO 
511c5ef6035SDavid Howells 	len = security_inode_listsecurity(d_inode(dentry), buffer, size);
512600e1779SMasatake YAMATO 	if (len < 0)
513600e1779SMasatake YAMATO 		return len;
514600e1779SMasatake YAMATO 	used += len;
515600e1779SMasatake YAMATO 	if (buffer) {
516600e1779SMasatake YAMATO 		if (size < used)
517600e1779SMasatake YAMATO 			return -ERANGE;
518600e1779SMasatake YAMATO 		buffer += len;
519600e1779SMasatake YAMATO 	}
520600e1779SMasatake YAMATO 
521600e1779SMasatake YAMATO 	len = (XATTR_NAME_SOCKPROTONAME_LEN + 1);
522600e1779SMasatake YAMATO 	used += len;
523600e1779SMasatake YAMATO 	if (buffer) {
524600e1779SMasatake YAMATO 		if (size < used)
525600e1779SMasatake YAMATO 			return -ERANGE;
526600e1779SMasatake YAMATO 		memcpy(buffer, XATTR_NAME_SOCKPROTONAME, len);
527600e1779SMasatake YAMATO 		buffer += len;
528600e1779SMasatake YAMATO 	}
529600e1779SMasatake YAMATO 
530600e1779SMasatake YAMATO 	return used;
531600e1779SMasatake YAMATO }
532600e1779SMasatake YAMATO 
533dc647ec8STobias Klauser static int sockfs_setattr(struct dentry *dentry, struct iattr *iattr)
53486741ec2SLorenzo Colitti {
53586741ec2SLorenzo Colitti 	int err = simple_setattr(dentry, iattr);
53686741ec2SLorenzo Colitti 
537e1a3a60aSEric Biggers 	if (!err && (iattr->ia_valid & ATTR_UID)) {
53886741ec2SLorenzo Colitti 		struct socket *sock = SOCKET_I(d_inode(dentry));
53986741ec2SLorenzo Colitti 
54086741ec2SLorenzo Colitti 		sock->sk->sk_uid = iattr->ia_uid;
54186741ec2SLorenzo Colitti 	}
54286741ec2SLorenzo Colitti 
54386741ec2SLorenzo Colitti 	return err;
54486741ec2SLorenzo Colitti }
54586741ec2SLorenzo Colitti 
546600e1779SMasatake YAMATO static const struct inode_operations sockfs_inode_ops = {
547600e1779SMasatake YAMATO 	.listxattr = sockfs_listxattr,
54886741ec2SLorenzo Colitti 	.setattr = sockfs_setattr,
549600e1779SMasatake YAMATO };
550600e1779SMasatake YAMATO 
5511da177e4SLinus Torvalds /**
5521da177e4SLinus Torvalds  *	sock_alloc	-	allocate a socket
5531da177e4SLinus Torvalds  *
5541da177e4SLinus Torvalds  *	Allocate a new inode and socket object. The two are bound together
5551da177e4SLinus Torvalds  *	and initialised. The socket is then returned. If we are out of inodes
5561da177e4SLinus Torvalds  *	NULL is returned.
5571da177e4SLinus Torvalds  */
5581da177e4SLinus Torvalds 
559f4a00aacSTom Herbert struct socket *sock_alloc(void)
5601da177e4SLinus Torvalds {
5611da177e4SLinus Torvalds 	struct inode *inode;
5621da177e4SLinus Torvalds 	struct socket *sock;
5631da177e4SLinus Torvalds 
564a209dfc7SEric Dumazet 	inode = new_inode_pseudo(sock_mnt->mnt_sb);
5651da177e4SLinus Torvalds 	if (!inode)
5661da177e4SLinus Torvalds 		return NULL;
5671da177e4SLinus Torvalds 
5681da177e4SLinus Torvalds 	sock = SOCKET_I(inode);
5691da177e4SLinus Torvalds 
57085fe4025SChristoph Hellwig 	inode->i_ino = get_next_ino();
5711da177e4SLinus Torvalds 	inode->i_mode = S_IFSOCK | S_IRWXUGO;
5728192b0c4SDavid Howells 	inode->i_uid = current_fsuid();
5738192b0c4SDavid Howells 	inode->i_gid = current_fsgid();
574600e1779SMasatake YAMATO 	inode->i_op = &sockfs_inode_ops;
5751da177e4SLinus Torvalds 
5761da177e4SLinus Torvalds 	return sock;
5771da177e4SLinus Torvalds }
578f4a00aacSTom Herbert EXPORT_SYMBOL(sock_alloc);
5791da177e4SLinus Torvalds 
5801da177e4SLinus Torvalds /**
5811da177e4SLinus Torvalds  *	sock_release	-	close a socket
5821da177e4SLinus Torvalds  *	@sock: socket to close
5831da177e4SLinus Torvalds  *
5841da177e4SLinus Torvalds  *	The socket is released from the protocol stack if it has a release
5851da177e4SLinus Torvalds  *	callback, and the inode is then released if the socket is bound to
5861da177e4SLinus Torvalds  *	an inode not a file.
5871da177e4SLinus Torvalds  */
5881da177e4SLinus Torvalds 
5891da177e4SLinus Torvalds void sock_release(struct socket *sock)
5901da177e4SLinus Torvalds {
5911da177e4SLinus Torvalds 	if (sock->ops) {
5921da177e4SLinus Torvalds 		struct module *owner = sock->ops->owner;
5931da177e4SLinus Torvalds 
5941da177e4SLinus Torvalds 		sock->ops->release(sock);
5951da177e4SLinus Torvalds 		sock->ops = NULL;
5961da177e4SLinus Torvalds 		module_put(owner);
5971da177e4SLinus Torvalds 	}
5981da177e4SLinus Torvalds 
599eaefd110SEric Dumazet 	if (rcu_dereference_protected(sock->wq, 1)->fasync_list)
6003410f22eSYang Yingliang 		pr_err("%s: fasync list not empty!\n", __func__);
6011da177e4SLinus Torvalds 
6021da177e4SLinus Torvalds 	if (!sock->file) {
6031da177e4SLinus Torvalds 		iput(SOCK_INODE(sock));
6041da177e4SLinus Torvalds 		return;
6051da177e4SLinus Torvalds 	}
6061da177e4SLinus Torvalds 	sock->file = NULL;
6071da177e4SLinus Torvalds }
608c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_release);
6091da177e4SLinus Torvalds 
610c14ac945SSoheil Hassas Yeganeh void __sock_tx_timestamp(__u16 tsflags, __u8 *tx_flags)
61120d49473SPatrick Ohly {
612140c55d4SEric Dumazet 	u8 flags = *tx_flags;
613140c55d4SEric Dumazet 
614c14ac945SSoheil Hassas Yeganeh 	if (tsflags & SOF_TIMESTAMPING_TX_HARDWARE)
615140c55d4SEric Dumazet 		flags |= SKBTX_HW_TSTAMP;
616140c55d4SEric Dumazet 
617c14ac945SSoheil Hassas Yeganeh 	if (tsflags & SOF_TIMESTAMPING_TX_SOFTWARE)
618140c55d4SEric Dumazet 		flags |= SKBTX_SW_TSTAMP;
619140c55d4SEric Dumazet 
620c14ac945SSoheil Hassas Yeganeh 	if (tsflags & SOF_TIMESTAMPING_TX_SCHED)
621140c55d4SEric Dumazet 		flags |= SKBTX_SCHED_TSTAMP;
622140c55d4SEric Dumazet 
623140c55d4SEric Dumazet 	*tx_flags = flags;
62420d49473SPatrick Ohly }
62567cc0d40SWillem de Bruijn EXPORT_SYMBOL(__sock_tx_timestamp);
62620d49473SPatrick Ohly 
627d8725c86SAl Viro static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg)
6281da177e4SLinus Torvalds {
62901e97e65SAl Viro 	int ret = sock->ops->sendmsg(sock, msg, msg_data_left(msg));
630d8725c86SAl Viro 	BUG_ON(ret == -EIOCBQUEUED);
631d8725c86SAl Viro 	return ret;
6321da177e4SLinus Torvalds }
6330cf00c6fSGu Zheng 
634d8725c86SAl Viro int sock_sendmsg(struct socket *sock, struct msghdr *msg)
6350cf00c6fSGu Zheng {
636d8725c86SAl Viro 	int err = security_socket_sendmsg(sock, msg,
63701e97e65SAl Viro 					  msg_data_left(msg));
6381b784140SYing Xue 
639d8725c86SAl Viro 	return err ?: sock_sendmsg_nosec(sock, msg);
6400cf00c6fSGu Zheng }
641c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_sendmsg);
6421da177e4SLinus Torvalds 
6431da177e4SLinus Torvalds int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
6441da177e4SLinus Torvalds 		   struct kvec *vec, size_t num, size_t size)
6451da177e4SLinus Torvalds {
6466aa24814SAl Viro 	iov_iter_kvec(&msg->msg_iter, WRITE | ITER_KVEC, vec, num, size);
647d8725c86SAl Viro 	return sock_sendmsg(sock, msg);
6481da177e4SLinus Torvalds }
649c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendmsg);
6501da177e4SLinus Torvalds 
651306b13ebSTom Herbert int kernel_sendmsg_locked(struct sock *sk, struct msghdr *msg,
652306b13ebSTom Herbert 			  struct kvec *vec, size_t num, size_t size)
653306b13ebSTom Herbert {
654306b13ebSTom Herbert 	struct socket *sock = sk->sk_socket;
655306b13ebSTom Herbert 
656306b13ebSTom Herbert 	if (!sock->ops->sendmsg_locked)
657db5980d8SJohn Fastabend 		return sock_no_sendmsg_locked(sk, msg, size);
658306b13ebSTom Herbert 
659306b13ebSTom Herbert 	iov_iter_kvec(&msg->msg_iter, WRITE | ITER_KVEC, vec, num, size);
660306b13ebSTom Herbert 
661306b13ebSTom Herbert 	return sock->ops->sendmsg_locked(sk, msg, msg_data_left(msg));
662306b13ebSTom Herbert }
663306b13ebSTom Herbert EXPORT_SYMBOL(kernel_sendmsg_locked);
664306b13ebSTom Herbert 
6658605330aSSoheil Hassas Yeganeh static bool skb_is_err_queue(const struct sk_buff *skb)
6668605330aSSoheil Hassas Yeganeh {
6678605330aSSoheil Hassas Yeganeh 	/* pkt_type of skbs enqueued on the error queue are set to
6688605330aSSoheil Hassas Yeganeh 	 * PACKET_OUTGOING in skb_set_err_queue(). This is only safe to do
6698605330aSSoheil Hassas Yeganeh 	 * in recvmsg, since skbs received on a local socket will never
6708605330aSSoheil Hassas Yeganeh 	 * have a pkt_type of PACKET_OUTGOING.
6718605330aSSoheil Hassas Yeganeh 	 */
6728605330aSSoheil Hassas Yeganeh 	return skb->pkt_type == PACKET_OUTGOING;
6738605330aSSoheil Hassas Yeganeh }
6748605330aSSoheil Hassas Yeganeh 
675b50a5c70SMiroslav Lichvar /* On transmit, software and hardware timestamps are returned independently.
676b50a5c70SMiroslav Lichvar  * As the two skb clones share the hardware timestamp, which may be updated
677b50a5c70SMiroslav Lichvar  * before the software timestamp is received, a hardware TX timestamp may be
678b50a5c70SMiroslav Lichvar  * returned only if there is no software TX timestamp. Ignore false software
679b50a5c70SMiroslav Lichvar  * timestamps, which may be made in the __sock_recv_timestamp() call when the
680b50a5c70SMiroslav Lichvar  * option SO_TIMESTAMP(NS) is enabled on the socket, even when the skb has a
681b50a5c70SMiroslav Lichvar  * hardware timestamp.
682b50a5c70SMiroslav Lichvar  */
683b50a5c70SMiroslav Lichvar static bool skb_is_swtx_tstamp(const struct sk_buff *skb, int false_tstamp)
684b50a5c70SMiroslav Lichvar {
685b50a5c70SMiroslav Lichvar 	return skb->tstamp && !false_tstamp && skb_is_err_queue(skb);
686b50a5c70SMiroslav Lichvar }
687b50a5c70SMiroslav Lichvar 
688aad9c8c4SMiroslav Lichvar static void put_ts_pktinfo(struct msghdr *msg, struct sk_buff *skb)
689aad9c8c4SMiroslav Lichvar {
690aad9c8c4SMiroslav Lichvar 	struct scm_ts_pktinfo ts_pktinfo;
691aad9c8c4SMiroslav Lichvar 	struct net_device *orig_dev;
692aad9c8c4SMiroslav Lichvar 
693aad9c8c4SMiroslav Lichvar 	if (!skb_mac_header_was_set(skb))
694aad9c8c4SMiroslav Lichvar 		return;
695aad9c8c4SMiroslav Lichvar 
696aad9c8c4SMiroslav Lichvar 	memset(&ts_pktinfo, 0, sizeof(ts_pktinfo));
697aad9c8c4SMiroslav Lichvar 
698aad9c8c4SMiroslav Lichvar 	rcu_read_lock();
699aad9c8c4SMiroslav Lichvar 	orig_dev = dev_get_by_napi_id(skb_napi_id(skb));
700aad9c8c4SMiroslav Lichvar 	if (orig_dev)
701aad9c8c4SMiroslav Lichvar 		ts_pktinfo.if_index = orig_dev->ifindex;
702aad9c8c4SMiroslav Lichvar 	rcu_read_unlock();
703aad9c8c4SMiroslav Lichvar 
704aad9c8c4SMiroslav Lichvar 	ts_pktinfo.pkt_length = skb->len - skb_mac_offset(skb);
705aad9c8c4SMiroslav Lichvar 	put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_PKTINFO,
706aad9c8c4SMiroslav Lichvar 		 sizeof(ts_pktinfo), &ts_pktinfo);
707aad9c8c4SMiroslav Lichvar }
708aad9c8c4SMiroslav Lichvar 
70992f37fd2SEric Dumazet /*
71092f37fd2SEric Dumazet  * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
71192f37fd2SEric Dumazet  */
71292f37fd2SEric Dumazet void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
71392f37fd2SEric Dumazet 	struct sk_buff *skb)
71492f37fd2SEric Dumazet {
71520d49473SPatrick Ohly 	int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
716f24b9be5SWillem de Bruijn 	struct scm_timestamping tss;
717b50a5c70SMiroslav Lichvar 	int empty = 1, false_tstamp = 0;
71820d49473SPatrick Ohly 	struct skb_shared_hwtstamps *shhwtstamps =
71920d49473SPatrick Ohly 		skb_hwtstamps(skb);
72092f37fd2SEric Dumazet 
72120d49473SPatrick Ohly 	/* Race occurred between timestamp enabling and packet
72220d49473SPatrick Ohly 	   receiving.  Fill in the current time for now. */
723b50a5c70SMiroslav Lichvar 	if (need_software_tstamp && skb->tstamp == 0) {
72420d49473SPatrick Ohly 		__net_timestamp(skb);
725b50a5c70SMiroslav Lichvar 		false_tstamp = 1;
726b50a5c70SMiroslav Lichvar 	}
72720d49473SPatrick Ohly 
72820d49473SPatrick Ohly 	if (need_software_tstamp) {
72992f37fd2SEric Dumazet 		if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
73092f37fd2SEric Dumazet 			struct timeval tv;
73120d49473SPatrick Ohly 			skb_get_timestamp(skb, &tv);
73220d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP,
73320d49473SPatrick Ohly 				 sizeof(tv), &tv);
73492f37fd2SEric Dumazet 		} else {
735f24b9be5SWillem de Bruijn 			struct timespec ts;
736f24b9be5SWillem de Bruijn 			skb_get_timestampns(skb, &ts);
73720d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS,
738f24b9be5SWillem de Bruijn 				 sizeof(ts), &ts);
73992f37fd2SEric Dumazet 		}
74092f37fd2SEric Dumazet 	}
74192f37fd2SEric Dumazet 
742f24b9be5SWillem de Bruijn 	memset(&tss, 0, sizeof(tss));
743c199105dSWillem de Bruijn 	if ((sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE) &&
744f24b9be5SWillem de Bruijn 	    ktime_to_timespec_cond(skb->tstamp, tss.ts + 0))
74520d49473SPatrick Ohly 		empty = 0;
7464d276eb6SWillem de Bruijn 	if (shhwtstamps &&
747b9f40e21SWillem de Bruijn 	    (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
748b50a5c70SMiroslav Lichvar 	    !skb_is_swtx_tstamp(skb, false_tstamp) &&
749aad9c8c4SMiroslav Lichvar 	    ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2)) {
75020d49473SPatrick Ohly 		empty = 0;
751aad9c8c4SMiroslav Lichvar 		if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_PKTINFO) &&
752aad9c8c4SMiroslav Lichvar 		    !skb_is_err_queue(skb))
753aad9c8c4SMiroslav Lichvar 			put_ts_pktinfo(msg, skb);
754aad9c8c4SMiroslav Lichvar 	}
7551c885808SFrancis Yan 	if (!empty) {
75620d49473SPatrick Ohly 		put_cmsg(msg, SOL_SOCKET,
757f24b9be5SWillem de Bruijn 			 SCM_TIMESTAMPING, sizeof(tss), &tss);
7581c885808SFrancis Yan 
7598605330aSSoheil Hassas Yeganeh 		if (skb_is_err_queue(skb) && skb->len &&
7604ef1b286SSoheil Hassas Yeganeh 		    SKB_EXT_ERR(skb)->opt_stats)
7611c885808SFrancis Yan 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_OPT_STATS,
7621c885808SFrancis Yan 				 skb->len, skb->data);
7631c885808SFrancis Yan 	}
76420d49473SPatrick Ohly }
7657c81fd8bSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
7667c81fd8bSArnaldo Carvalho de Melo 
7676e3e939fSJohannes Berg void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
7686e3e939fSJohannes Berg 	struct sk_buff *skb)
7696e3e939fSJohannes Berg {
7706e3e939fSJohannes Berg 	int ack;
7716e3e939fSJohannes Berg 
7726e3e939fSJohannes Berg 	if (!sock_flag(sk, SOCK_WIFI_STATUS))
7736e3e939fSJohannes Berg 		return;
7746e3e939fSJohannes Berg 	if (!skb->wifi_acked_valid)
7756e3e939fSJohannes Berg 		return;
7766e3e939fSJohannes Berg 
7776e3e939fSJohannes Berg 	ack = skb->wifi_acked;
7786e3e939fSJohannes Berg 
7796e3e939fSJohannes Berg 	put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack);
7806e3e939fSJohannes Berg }
7816e3e939fSJohannes Berg EXPORT_SYMBOL_GPL(__sock_recv_wifi_status);
7826e3e939fSJohannes Berg 
78311165f14Sstephen hemminger static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk,
78411165f14Sstephen hemminger 				   struct sk_buff *skb)
7853b885787SNeil Horman {
786744d5a3eSEyal Birger 	if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && SOCK_SKB_CB(skb)->dropcount)
7873b885787SNeil Horman 		put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL,
788744d5a3eSEyal Birger 			sizeof(__u32), &SOCK_SKB_CB(skb)->dropcount);
7893b885787SNeil Horman }
7903b885787SNeil Horman 
791767dd033SEric Dumazet void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
7923b885787SNeil Horman 	struct sk_buff *skb)
7933b885787SNeil Horman {
7943b885787SNeil Horman 	sock_recv_timestamp(msg, sk, skb);
7953b885787SNeil Horman 	sock_recv_drops(msg, sk, skb);
7963b885787SNeil Horman }
797767dd033SEric Dumazet EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops);
7983b885787SNeil Horman 
7991b784140SYing Xue static inline int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
8001b784140SYing Xue 				     int flags)
801a2e27255SArnaldo Carvalho de Melo {
8022da62906SAl Viro 	return sock->ops->recvmsg(sock, msg, msg_data_left(msg), flags);
8032da62906SAl Viro }
804a2e27255SArnaldo Carvalho de Melo 
8052da62906SAl Viro int sock_recvmsg(struct socket *sock, struct msghdr *msg, int flags)
8062da62906SAl Viro {
8072da62906SAl Viro 	int err = security_socket_recvmsg(sock, msg, msg_data_left(msg), flags);
8082da62906SAl Viro 
8092da62906SAl Viro 	return err ?: sock_recvmsg_nosec(sock, msg, flags);
8101da177e4SLinus Torvalds }
811c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_recvmsg);
8121da177e4SLinus Torvalds 
813c1249c0aSMartin Lucina /**
814c1249c0aSMartin Lucina  * kernel_recvmsg - Receive a message from a socket (kernel space)
815c1249c0aSMartin Lucina  * @sock:       The socket to receive the message from
816c1249c0aSMartin Lucina  * @msg:        Received message
817c1249c0aSMartin Lucina  * @vec:        Input s/g array for message data
818c1249c0aSMartin Lucina  * @num:        Size of input s/g array
819c1249c0aSMartin Lucina  * @size:       Number of bytes to read
820c1249c0aSMartin Lucina  * @flags:      Message flags (MSG_DONTWAIT, etc...)
821c1249c0aSMartin Lucina  *
822c1249c0aSMartin Lucina  * On return the msg structure contains the scatter/gather array passed in the
823c1249c0aSMartin Lucina  * vec argument. The array is modified so that it consists of the unfilled
824c1249c0aSMartin Lucina  * portion of the original array.
825c1249c0aSMartin Lucina  *
826c1249c0aSMartin Lucina  * The returned value is the total number of bytes received, or an error.
827c1249c0aSMartin Lucina  */
8281da177e4SLinus Torvalds int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
82989bddce5SStephen Hemminger 		   struct kvec *vec, size_t num, size_t size, int flags)
8301da177e4SLinus Torvalds {
8311da177e4SLinus Torvalds 	mm_segment_t oldfs = get_fs();
8321da177e4SLinus Torvalds 	int result;
8331da177e4SLinus Torvalds 
8346aa24814SAl Viro 	iov_iter_kvec(&msg->msg_iter, READ | ITER_KVEC, vec, num, size);
8351da177e4SLinus Torvalds 	set_fs(KERNEL_DS);
8362da62906SAl Viro 	result = sock_recvmsg(sock, msg, flags);
8371da177e4SLinus Torvalds 	set_fs(oldfs);
8381da177e4SLinus Torvalds 	return result;
8391da177e4SLinus Torvalds }
840c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_recvmsg);
8411da177e4SLinus Torvalds 
84220380731SArnaldo Carvalho de Melo static ssize_t sock_sendpage(struct file *file, struct page *page,
8431da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more)
8441da177e4SLinus Torvalds {
8451da177e4SLinus Torvalds 	struct socket *sock;
8461da177e4SLinus Torvalds 	int flags;
8471da177e4SLinus Torvalds 
848b69aee04SEric Dumazet 	sock = file->private_data;
8491da177e4SLinus Torvalds 
85035f9c09fSEric Dumazet 	flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
85135f9c09fSEric Dumazet 	/* more is a combination of MSG_MORE and MSG_SENDPAGE_NOTLAST */
85235f9c09fSEric Dumazet 	flags |= more;
8531da177e4SLinus Torvalds 
854e6949583SLinus Torvalds 	return kernel_sendpage(sock, page, offset, size, flags);
8551da177e4SLinus Torvalds }
8561da177e4SLinus Torvalds 
8579c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
8589c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
8599c55e01cSJens Axboe 				unsigned int flags)
8609c55e01cSJens Axboe {
8619c55e01cSJens Axboe 	struct socket *sock = file->private_data;
8629c55e01cSJens Axboe 
863997b37daSRémi Denis-Courmont 	if (unlikely(!sock->ops->splice_read))
864997b37daSRémi Denis-Courmont 		return -EINVAL;
865997b37daSRémi Denis-Courmont 
8669c55e01cSJens Axboe 	return sock->ops->splice_read(sock, ppos, pipe, len, flags);
8679c55e01cSJens Axboe }
8689c55e01cSJens Axboe 
8698ae5e030SAl Viro static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to)
870ce1d4d3eSChristoph Hellwig {
8716d652330SAl Viro 	struct file *file = iocb->ki_filp;
8726d652330SAl Viro 	struct socket *sock = file->private_data;
8730345f931Stadeusz.struk@intel.com 	struct msghdr msg = {.msg_iter = *to,
8740345f931Stadeusz.struk@intel.com 			     .msg_iocb = iocb};
8758ae5e030SAl Viro 	ssize_t res;
876ce1d4d3eSChristoph Hellwig 
8778ae5e030SAl Viro 	if (file->f_flags & O_NONBLOCK)
8788ae5e030SAl Viro 		msg.msg_flags = MSG_DONTWAIT;
8798ae5e030SAl Viro 
8808ae5e030SAl Viro 	if (iocb->ki_pos != 0)
881ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
882027445c3SBadari Pulavarty 
88366ee59afSChristoph Hellwig 	if (!iov_iter_count(to))	/* Match SYS5 behaviour */
884ce1d4d3eSChristoph Hellwig 		return 0;
885ce1d4d3eSChristoph Hellwig 
8862da62906SAl Viro 	res = sock_recvmsg(sock, &msg, msg.msg_flags);
8878ae5e030SAl Viro 	*to = msg.msg_iter;
8888ae5e030SAl Viro 	return res;
889ce1d4d3eSChristoph Hellwig }
890ce1d4d3eSChristoph Hellwig 
8918ae5e030SAl Viro static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from)
8921da177e4SLinus Torvalds {
8936d652330SAl Viro 	struct file *file = iocb->ki_filp;
8946d652330SAl Viro 	struct socket *sock = file->private_data;
8950345f931Stadeusz.struk@intel.com 	struct msghdr msg = {.msg_iter = *from,
8960345f931Stadeusz.struk@intel.com 			     .msg_iocb = iocb};
8978ae5e030SAl Viro 	ssize_t res;
8981da177e4SLinus Torvalds 
8998ae5e030SAl Viro 	if (iocb->ki_pos != 0)
900ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
901027445c3SBadari Pulavarty 
9028ae5e030SAl Viro 	if (file->f_flags & O_NONBLOCK)
9038ae5e030SAl Viro 		msg.msg_flags = MSG_DONTWAIT;
9048ae5e030SAl Viro 
9056d652330SAl Viro 	if (sock->type == SOCK_SEQPACKET)
9066d652330SAl Viro 		msg.msg_flags |= MSG_EOR;
9076d652330SAl Viro 
908d8725c86SAl Viro 	res = sock_sendmsg(sock, &msg);
9098ae5e030SAl Viro 	*from = msg.msg_iter;
9108ae5e030SAl Viro 	return res;
9111da177e4SLinus Torvalds }
9121da177e4SLinus Torvalds 
9131da177e4SLinus Torvalds /*
9141da177e4SLinus Torvalds  * Atomic setting of ioctl hooks to avoid race
9151da177e4SLinus Torvalds  * with module unload.
9161da177e4SLinus Torvalds  */
9171da177e4SLinus Torvalds 
9184a3e2f71SArjan van de Ven static DEFINE_MUTEX(br_ioctl_mutex);
919c6d409cfSEric Dumazet static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg);
9201da177e4SLinus Torvalds 
921881d966bSEric W. Biederman void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *))
9221da177e4SLinus Torvalds {
9234a3e2f71SArjan van de Ven 	mutex_lock(&br_ioctl_mutex);
9241da177e4SLinus Torvalds 	br_ioctl_hook = hook;
9254a3e2f71SArjan van de Ven 	mutex_unlock(&br_ioctl_mutex);
9261da177e4SLinus Torvalds }
9271da177e4SLinus Torvalds EXPORT_SYMBOL(brioctl_set);
9281da177e4SLinus Torvalds 
9294a3e2f71SArjan van de Ven static DEFINE_MUTEX(vlan_ioctl_mutex);
930881d966bSEric W. Biederman static int (*vlan_ioctl_hook) (struct net *, void __user *arg);
9311da177e4SLinus Torvalds 
932881d966bSEric W. Biederman void vlan_ioctl_set(int (*hook) (struct net *, void __user *))
9331da177e4SLinus Torvalds {
9344a3e2f71SArjan van de Ven 	mutex_lock(&vlan_ioctl_mutex);
9351da177e4SLinus Torvalds 	vlan_ioctl_hook = hook;
9364a3e2f71SArjan van de Ven 	mutex_unlock(&vlan_ioctl_mutex);
9371da177e4SLinus Torvalds }
9381da177e4SLinus Torvalds EXPORT_SYMBOL(vlan_ioctl_set);
9391da177e4SLinus Torvalds 
9404a3e2f71SArjan van de Ven static DEFINE_MUTEX(dlci_ioctl_mutex);
9411da177e4SLinus Torvalds static int (*dlci_ioctl_hook) (unsigned int, void __user *);
9421da177e4SLinus Torvalds 
9431da177e4SLinus Torvalds void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
9441da177e4SLinus Torvalds {
9454a3e2f71SArjan van de Ven 	mutex_lock(&dlci_ioctl_mutex);
9461da177e4SLinus Torvalds 	dlci_ioctl_hook = hook;
9474a3e2f71SArjan van de Ven 	mutex_unlock(&dlci_ioctl_mutex);
9481da177e4SLinus Torvalds }
9491da177e4SLinus Torvalds EXPORT_SYMBOL(dlci_ioctl_set);
9501da177e4SLinus Torvalds 
9516b96018bSArnd Bergmann static long sock_do_ioctl(struct net *net, struct socket *sock,
9526b96018bSArnd Bergmann 				 unsigned int cmd, unsigned long arg)
9536b96018bSArnd Bergmann {
9546b96018bSArnd Bergmann 	int err;
9556b96018bSArnd Bergmann 	void __user *argp = (void __user *)arg;
9566b96018bSArnd Bergmann 
9576b96018bSArnd Bergmann 	err = sock->ops->ioctl(sock, cmd, arg);
9586b96018bSArnd Bergmann 
9596b96018bSArnd Bergmann 	/*
9606b96018bSArnd Bergmann 	 * If this ioctl is unknown try to hand it down
9616b96018bSArnd Bergmann 	 * to the NIC driver.
9626b96018bSArnd Bergmann 	 */
96336fd633eSAl Viro 	if (err != -ENOIOCTLCMD)
9646b96018bSArnd Bergmann 		return err;
9656b96018bSArnd Bergmann 
96636fd633eSAl Viro 	if (cmd == SIOCGIFCONF) {
96736fd633eSAl Viro 		struct ifconf ifc;
96836fd633eSAl Viro 		if (copy_from_user(&ifc, argp, sizeof(struct ifconf)))
96936fd633eSAl Viro 			return -EFAULT;
97036fd633eSAl Viro 		rtnl_lock();
97136fd633eSAl Viro 		err = dev_ifconf(net, &ifc, sizeof(struct ifreq));
97236fd633eSAl Viro 		rtnl_unlock();
97336fd633eSAl Viro 		if (!err && copy_to_user(argp, &ifc, sizeof(struct ifconf)))
97436fd633eSAl Viro 			err = -EFAULT;
97544c02a2cSAl Viro 	} else {
97644c02a2cSAl Viro 		struct ifreq ifr;
97744c02a2cSAl Viro 		bool need_copyout;
97844c02a2cSAl Viro 		if (copy_from_user(&ifr, argp, sizeof(struct ifreq)))
97944c02a2cSAl Viro 			return -EFAULT;
98044c02a2cSAl Viro 		err = dev_ioctl(net, cmd, &ifr, &need_copyout);
98144c02a2cSAl Viro 		if (!err && need_copyout)
98244c02a2cSAl Viro 			if (copy_to_user(argp, &ifr, sizeof(struct ifreq)))
98344c02a2cSAl Viro 				return -EFAULT;
98436fd633eSAl Viro 	}
9856b96018bSArnd Bergmann 	return err;
9866b96018bSArnd Bergmann }
9876b96018bSArnd Bergmann 
9881da177e4SLinus Torvalds /*
9891da177e4SLinus Torvalds  *	With an ioctl, arg may well be a user mode pointer, but we don't know
9901da177e4SLinus Torvalds  *	what to do with it - that's up to the protocol still.
9911da177e4SLinus Torvalds  */
9921da177e4SLinus Torvalds 
993d8d211a2SKirill Tkhai struct ns_common *get_net_ns(struct ns_common *ns)
994c62cce2cSAndrey Vagin {
995c62cce2cSAndrey Vagin 	return &get_net(container_of(ns, struct net, ns))->ns;
996c62cce2cSAndrey Vagin }
997d8d211a2SKirill Tkhai EXPORT_SYMBOL_GPL(get_net_ns);
998c62cce2cSAndrey Vagin 
9991da177e4SLinus Torvalds static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
10001da177e4SLinus Torvalds {
10011da177e4SLinus Torvalds 	struct socket *sock;
1002881d966bSEric W. Biederman 	struct sock *sk;
10031da177e4SLinus Torvalds 	void __user *argp = (void __user *)arg;
10041da177e4SLinus Torvalds 	int pid, err;
1005881d966bSEric W. Biederman 	struct net *net;
10061da177e4SLinus Torvalds 
1007b69aee04SEric Dumazet 	sock = file->private_data;
1008881d966bSEric W. Biederman 	sk = sock->sk;
10093b1e0a65SYOSHIFUJI Hideaki 	net = sock_net(sk);
101044c02a2cSAl Viro 	if (unlikely(cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))) {
101144c02a2cSAl Viro 		struct ifreq ifr;
101244c02a2cSAl Viro 		bool need_copyout;
101344c02a2cSAl Viro 		if (copy_from_user(&ifr, argp, sizeof(struct ifreq)))
101444c02a2cSAl Viro 			return -EFAULT;
101544c02a2cSAl Viro 		err = dev_ioctl(net, cmd, &ifr, &need_copyout);
101644c02a2cSAl Viro 		if (!err && need_copyout)
101744c02a2cSAl Viro 			if (copy_to_user(argp, &ifr, sizeof(struct ifreq)))
101844c02a2cSAl Viro 				return -EFAULT;
10191da177e4SLinus Torvalds 	} else
10203d23e349SJohannes Berg #ifdef CONFIG_WEXT_CORE
10211da177e4SLinus Torvalds 	if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
1022b1b0c245SAl Viro 		err = wext_handle_ioctl(net, cmd, argp);
10231da177e4SLinus Torvalds 	} else
10243d23e349SJohannes Berg #endif
10251da177e4SLinus Torvalds 		switch (cmd) {
10261da177e4SLinus Torvalds 		case FIOSETOWN:
10271da177e4SLinus Torvalds 		case SIOCSPGRP:
10281da177e4SLinus Torvalds 			err = -EFAULT;
10291da177e4SLinus Torvalds 			if (get_user(pid, (int __user *)argp))
10301da177e4SLinus Torvalds 				break;
1031393cc3f5SJiri Slaby 			err = f_setown(sock->file, pid, 1);
10321da177e4SLinus Torvalds 			break;
10331da177e4SLinus Torvalds 		case FIOGETOWN:
10341da177e4SLinus Torvalds 		case SIOCGPGRP:
1035609d7fa9SEric W. Biederman 			err = put_user(f_getown(sock->file),
103689bddce5SStephen Hemminger 				       (int __user *)argp);
10371da177e4SLinus Torvalds 			break;
10381da177e4SLinus Torvalds 		case SIOCGIFBR:
10391da177e4SLinus Torvalds 		case SIOCSIFBR:
10401da177e4SLinus Torvalds 		case SIOCBRADDBR:
10411da177e4SLinus Torvalds 		case SIOCBRDELBR:
10421da177e4SLinus Torvalds 			err = -ENOPKG;
10431da177e4SLinus Torvalds 			if (!br_ioctl_hook)
10441da177e4SLinus Torvalds 				request_module("bridge");
10451da177e4SLinus Torvalds 
10464a3e2f71SArjan van de Ven 			mutex_lock(&br_ioctl_mutex);
10471da177e4SLinus Torvalds 			if (br_ioctl_hook)
1048881d966bSEric W. Biederman 				err = br_ioctl_hook(net, cmd, argp);
10494a3e2f71SArjan van de Ven 			mutex_unlock(&br_ioctl_mutex);
10501da177e4SLinus Torvalds 			break;
10511da177e4SLinus Torvalds 		case SIOCGIFVLAN:
10521da177e4SLinus Torvalds 		case SIOCSIFVLAN:
10531da177e4SLinus Torvalds 			err = -ENOPKG;
10541da177e4SLinus Torvalds 			if (!vlan_ioctl_hook)
10551da177e4SLinus Torvalds 				request_module("8021q");
10561da177e4SLinus Torvalds 
10574a3e2f71SArjan van de Ven 			mutex_lock(&vlan_ioctl_mutex);
10581da177e4SLinus Torvalds 			if (vlan_ioctl_hook)
1059881d966bSEric W. Biederman 				err = vlan_ioctl_hook(net, argp);
10604a3e2f71SArjan van de Ven 			mutex_unlock(&vlan_ioctl_mutex);
10611da177e4SLinus Torvalds 			break;
10621da177e4SLinus Torvalds 		case SIOCADDDLCI:
10631da177e4SLinus Torvalds 		case SIOCDELDLCI:
10641da177e4SLinus Torvalds 			err = -ENOPKG;
10651da177e4SLinus Torvalds 			if (!dlci_ioctl_hook)
10661da177e4SLinus Torvalds 				request_module("dlci");
10671da177e4SLinus Torvalds 
10684a3e2f71SArjan van de Ven 			mutex_lock(&dlci_ioctl_mutex);
10697512cbf6SPavel Emelyanov 			if (dlci_ioctl_hook)
10701da177e4SLinus Torvalds 				err = dlci_ioctl_hook(cmd, argp);
10714a3e2f71SArjan van de Ven 			mutex_unlock(&dlci_ioctl_mutex);
10721da177e4SLinus Torvalds 			break;
1073c62cce2cSAndrey Vagin 		case SIOCGSKNS:
1074c62cce2cSAndrey Vagin 			err = -EPERM;
1075c62cce2cSAndrey Vagin 			if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
1076c62cce2cSAndrey Vagin 				break;
1077c62cce2cSAndrey Vagin 
1078c62cce2cSAndrey Vagin 			err = open_related_ns(&net->ns, get_net_ns);
1079c62cce2cSAndrey Vagin 			break;
10801da177e4SLinus Torvalds 		default:
10816b96018bSArnd Bergmann 			err = sock_do_ioctl(net, sock, cmd, arg);
10821da177e4SLinus Torvalds 			break;
10831da177e4SLinus Torvalds 		}
10841da177e4SLinus Torvalds 	return err;
10851da177e4SLinus Torvalds }
10861da177e4SLinus Torvalds 
10871da177e4SLinus Torvalds int sock_create_lite(int family, int type, int protocol, struct socket **res)
10881da177e4SLinus Torvalds {
10891da177e4SLinus Torvalds 	int err;
10901da177e4SLinus Torvalds 	struct socket *sock = NULL;
10911da177e4SLinus Torvalds 
10921da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, 1);
10931da177e4SLinus Torvalds 	if (err)
10941da177e4SLinus Torvalds 		goto out;
10951da177e4SLinus Torvalds 
10961da177e4SLinus Torvalds 	sock = sock_alloc();
10971da177e4SLinus Torvalds 	if (!sock) {
10981da177e4SLinus Torvalds 		err = -ENOMEM;
10991da177e4SLinus Torvalds 		goto out;
11001da177e4SLinus Torvalds 	}
11011da177e4SLinus Torvalds 
11021da177e4SLinus Torvalds 	sock->type = type;
11037420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, 1);
11047420ed23SVenkat Yekkirala 	if (err)
11057420ed23SVenkat Yekkirala 		goto out_release;
11067420ed23SVenkat Yekkirala 
11071da177e4SLinus Torvalds out:
11081da177e4SLinus Torvalds 	*res = sock;
11091da177e4SLinus Torvalds 	return err;
11107420ed23SVenkat Yekkirala out_release:
11117420ed23SVenkat Yekkirala 	sock_release(sock);
11127420ed23SVenkat Yekkirala 	sock = NULL;
11137420ed23SVenkat Yekkirala 	goto out;
11141da177e4SLinus Torvalds }
1115c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_lite);
11161da177e4SLinus Torvalds 
11171da177e4SLinus Torvalds /* No kernel lock held - perfect */
1118ade994f4SAl Viro static __poll_t sock_poll(struct file *file, poll_table *wait)
11191da177e4SLinus Torvalds {
1120e6c8adcaSAl Viro 	__poll_t busy_flag = 0;
11211da177e4SLinus Torvalds 	struct socket *sock;
11221da177e4SLinus Torvalds 
11231da177e4SLinus Torvalds 	/*
11241da177e4SLinus Torvalds 	 *      We can't return errors to poll, so it's either yes or no.
11251da177e4SLinus Torvalds 	 */
1126b69aee04SEric Dumazet 	sock = file->private_data;
11272d48d67fSEliezer Tamir 
1128cbf55001SEliezer Tamir 	if (sk_can_busy_loop(sock->sk)) {
11292d48d67fSEliezer Tamir 		/* this socket can poll_ll so tell the system call */
1130cbf55001SEliezer Tamir 		busy_flag = POLL_BUSY_LOOP;
11312d48d67fSEliezer Tamir 
11322d48d67fSEliezer Tamir 		/* once, only if requested by syscall */
1133cbf55001SEliezer Tamir 		if (wait && (wait->_key & POLL_BUSY_LOOP))
1134cbf55001SEliezer Tamir 			sk_busy_loop(sock->sk, 1);
11352d48d67fSEliezer Tamir 	}
11362d48d67fSEliezer Tamir 
1137cbf55001SEliezer Tamir 	return busy_flag | sock->ops->poll(file, sock, wait);
11381da177e4SLinus Torvalds }
11391da177e4SLinus Torvalds 
11401da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma)
11411da177e4SLinus Torvalds {
1142b69aee04SEric Dumazet 	struct socket *sock = file->private_data;
11431da177e4SLinus Torvalds 
11441da177e4SLinus Torvalds 	return sock->ops->mmap(file, sock, vma);
11451da177e4SLinus Torvalds }
11461da177e4SLinus Torvalds 
114720380731SArnaldo Carvalho de Melo static int sock_close(struct inode *inode, struct file *filp)
11481da177e4SLinus Torvalds {
11491da177e4SLinus Torvalds 	sock_release(SOCKET_I(inode));
11501da177e4SLinus Torvalds 	return 0;
11511da177e4SLinus Torvalds }
11521da177e4SLinus Torvalds 
11531da177e4SLinus Torvalds /*
11541da177e4SLinus Torvalds  *	Update the socket async list
11551da177e4SLinus Torvalds  *
11561da177e4SLinus Torvalds  *	Fasync_list locking strategy.
11571da177e4SLinus Torvalds  *
11581da177e4SLinus Torvalds  *	1. fasync_list is modified only under process context socket lock
11591da177e4SLinus Torvalds  *	   i.e. under semaphore.
11601da177e4SLinus Torvalds  *	2. fasync_list is used under read_lock(&sk->sk_callback_lock)
1161989a2979SEric Dumazet  *	   or under socket lock
11621da177e4SLinus Torvalds  */
11631da177e4SLinus Torvalds 
11641da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on)
11651da177e4SLinus Torvalds {
1166989a2979SEric Dumazet 	struct socket *sock = filp->private_data;
1167989a2979SEric Dumazet 	struct sock *sk = sock->sk;
1168eaefd110SEric Dumazet 	struct socket_wq *wq;
11691da177e4SLinus Torvalds 
1170989a2979SEric Dumazet 	if (sk == NULL)
11711da177e4SLinus Torvalds 		return -EINVAL;
11721da177e4SLinus Torvalds 
11731da177e4SLinus Torvalds 	lock_sock(sk);
11741e1d04e6SHannes Frederic Sowa 	wq = rcu_dereference_protected(sock->wq, lockdep_sock_is_held(sk));
1175eaefd110SEric Dumazet 	fasync_helper(fd, filp, on, &wq->fasync_list);
11761da177e4SLinus Torvalds 
1177eaefd110SEric Dumazet 	if (!wq->fasync_list)
1178bcdce719SEric Dumazet 		sock_reset_flag(sk, SOCK_FASYNC);
1179989a2979SEric Dumazet 	else
1180989a2979SEric Dumazet 		sock_set_flag(sk, SOCK_FASYNC);
11811da177e4SLinus Torvalds 
1182989a2979SEric Dumazet 	release_sock(sk);
11831da177e4SLinus Torvalds 	return 0;
11841da177e4SLinus Torvalds }
11851da177e4SLinus Torvalds 
1186ceb5d58bSEric Dumazet /* This function may be called only under rcu_lock */
11871da177e4SLinus Torvalds 
1188ceb5d58bSEric Dumazet int sock_wake_async(struct socket_wq *wq, int how, int band)
11891da177e4SLinus Torvalds {
1190ceb5d58bSEric Dumazet 	if (!wq || !wq->fasync_list)
1191ceb5d58bSEric Dumazet 		return -1;
119243815482SEric Dumazet 
119389bddce5SStephen Hemminger 	switch (how) {
11948d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_WAITD:
1195ceb5d58bSEric Dumazet 		if (test_bit(SOCKWQ_ASYNC_WAITDATA, &wq->flags))
11961da177e4SLinus Torvalds 			break;
11971da177e4SLinus Torvalds 		goto call_kill;
11988d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_SPACE:
1199ceb5d58bSEric Dumazet 		if (!test_and_clear_bit(SOCKWQ_ASYNC_NOSPACE, &wq->flags))
12001da177e4SLinus Torvalds 			break;
12011da177e4SLinus Torvalds 		/* fall through */
12028d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_IO:
12031da177e4SLinus Torvalds call_kill:
120443815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGIO, band);
12051da177e4SLinus Torvalds 		break;
12068d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_URG:
120743815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGURG, band);
12081da177e4SLinus Torvalds 	}
1209ceb5d58bSEric Dumazet 
12101da177e4SLinus Torvalds 	return 0;
12111da177e4SLinus Torvalds }
1212c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_wake_async);
12131da177e4SLinus Torvalds 
1214721db93aSPavel Emelyanov int __sock_create(struct net *net, int family, int type, int protocol,
121589bddce5SStephen Hemminger 			 struct socket **res, int kern)
12161da177e4SLinus Torvalds {
12171da177e4SLinus Torvalds 	int err;
12181da177e4SLinus Torvalds 	struct socket *sock;
121955737fdaSStephen Hemminger 	const struct net_proto_family *pf;
12201da177e4SLinus Torvalds 
12211da177e4SLinus Torvalds 	/*
12221da177e4SLinus Torvalds 	 *      Check protocol is in range
12231da177e4SLinus Torvalds 	 */
12241da177e4SLinus Torvalds 	if (family < 0 || family >= NPROTO)
12251da177e4SLinus Torvalds 		return -EAFNOSUPPORT;
12261da177e4SLinus Torvalds 	if (type < 0 || type >= SOCK_MAX)
12271da177e4SLinus Torvalds 		return -EINVAL;
12281da177e4SLinus Torvalds 
12291da177e4SLinus Torvalds 	/* Compatibility.
12301da177e4SLinus Torvalds 
12311da177e4SLinus Torvalds 	   This uglymoron is moved from INET layer to here to avoid
12321da177e4SLinus Torvalds 	   deadlock in module load.
12331da177e4SLinus Torvalds 	 */
12341da177e4SLinus Torvalds 	if (family == PF_INET && type == SOCK_PACKET) {
1235f3c98690Sliping.zhang 		pr_info_once("%s uses obsolete (PF_INET,SOCK_PACKET)\n",
123689bddce5SStephen Hemminger 			     current->comm);
12371da177e4SLinus Torvalds 		family = PF_PACKET;
12381da177e4SLinus Torvalds 	}
12391da177e4SLinus Torvalds 
12401da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, kern);
12411da177e4SLinus Torvalds 	if (err)
12421da177e4SLinus Torvalds 		return err;
12431da177e4SLinus Torvalds 
124455737fdaSStephen Hemminger 	/*
124555737fdaSStephen Hemminger 	 *	Allocate the socket and allow the family to set things up. if
124655737fdaSStephen Hemminger 	 *	the protocol is 0, the family is instructed to select an appropriate
124755737fdaSStephen Hemminger 	 *	default.
124855737fdaSStephen Hemminger 	 */
124955737fdaSStephen Hemminger 	sock = sock_alloc();
125055737fdaSStephen Hemminger 	if (!sock) {
1251e87cc472SJoe Perches 		net_warn_ratelimited("socket: no more sockets\n");
125255737fdaSStephen Hemminger 		return -ENFILE;	/* Not exactly a match, but its the
125355737fdaSStephen Hemminger 				   closest posix thing */
125455737fdaSStephen Hemminger 	}
125555737fdaSStephen Hemminger 
125655737fdaSStephen Hemminger 	sock->type = type;
125755737fdaSStephen Hemminger 
125895a5afcaSJohannes Berg #ifdef CONFIG_MODULES
12591da177e4SLinus Torvalds 	/* Attempt to load a protocol module if the find failed.
12601da177e4SLinus Torvalds 	 *
12611da177e4SLinus Torvalds 	 * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
12621da177e4SLinus Torvalds 	 * requested real, full-featured networking support upon configuration.
12631da177e4SLinus Torvalds 	 * Otherwise module support will break!
12641da177e4SLinus Torvalds 	 */
1265190683a9SEric Dumazet 	if (rcu_access_pointer(net_families[family]) == NULL)
12661da177e4SLinus Torvalds 		request_module("net-pf-%d", family);
12671da177e4SLinus Torvalds #endif
12681da177e4SLinus Torvalds 
126955737fdaSStephen Hemminger 	rcu_read_lock();
127055737fdaSStephen Hemminger 	pf = rcu_dereference(net_families[family]);
12711da177e4SLinus Torvalds 	err = -EAFNOSUPPORT;
127255737fdaSStephen Hemminger 	if (!pf)
127355737fdaSStephen Hemminger 		goto out_release;
12741da177e4SLinus Torvalds 
12751da177e4SLinus Torvalds 	/*
12761da177e4SLinus Torvalds 	 * We will call the ->create function, that possibly is in a loadable
12771da177e4SLinus Torvalds 	 * module, so we have to bump that loadable module refcnt first.
12781da177e4SLinus Torvalds 	 */
127955737fdaSStephen Hemminger 	if (!try_module_get(pf->owner))
12801da177e4SLinus Torvalds 		goto out_release;
12811da177e4SLinus Torvalds 
128255737fdaSStephen Hemminger 	/* Now protected by module ref count */
128355737fdaSStephen Hemminger 	rcu_read_unlock();
128455737fdaSStephen Hemminger 
12853f378b68SEric Paris 	err = pf->create(net, sock, protocol, kern);
128655737fdaSStephen Hemminger 	if (err < 0)
12871da177e4SLinus Torvalds 		goto out_module_put;
1288a79af59eSFrank Filz 
12891da177e4SLinus Torvalds 	/*
12901da177e4SLinus Torvalds 	 * Now to bump the refcnt of the [loadable] module that owns this
12911da177e4SLinus Torvalds 	 * socket at sock_release time we decrement its refcnt.
12921da177e4SLinus Torvalds 	 */
129355737fdaSStephen Hemminger 	if (!try_module_get(sock->ops->owner))
129455737fdaSStephen Hemminger 		goto out_module_busy;
129555737fdaSStephen Hemminger 
12961da177e4SLinus Torvalds 	/*
12971da177e4SLinus Torvalds 	 * Now that we're done with the ->create function, the [loadable]
12981da177e4SLinus Torvalds 	 * module can have its refcnt decremented
12991da177e4SLinus Torvalds 	 */
130055737fdaSStephen Hemminger 	module_put(pf->owner);
13017420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, kern);
13027420ed23SVenkat Yekkirala 	if (err)
13033b185525SHerbert Xu 		goto out_sock_release;
130455737fdaSStephen Hemminger 	*res = sock;
13051da177e4SLinus Torvalds 
130655737fdaSStephen Hemminger 	return 0;
130755737fdaSStephen Hemminger 
130855737fdaSStephen Hemminger out_module_busy:
130955737fdaSStephen Hemminger 	err = -EAFNOSUPPORT;
13101da177e4SLinus Torvalds out_module_put:
131155737fdaSStephen Hemminger 	sock->ops = NULL;
131255737fdaSStephen Hemminger 	module_put(pf->owner);
131355737fdaSStephen Hemminger out_sock_release:
13141da177e4SLinus Torvalds 	sock_release(sock);
131555737fdaSStephen Hemminger 	return err;
131655737fdaSStephen Hemminger 
131755737fdaSStephen Hemminger out_release:
131855737fdaSStephen Hemminger 	rcu_read_unlock();
131955737fdaSStephen Hemminger 	goto out_sock_release;
13201da177e4SLinus Torvalds }
1321721db93aSPavel Emelyanov EXPORT_SYMBOL(__sock_create);
13221da177e4SLinus Torvalds 
13231da177e4SLinus Torvalds int sock_create(int family, int type, int protocol, struct socket **res)
13241da177e4SLinus Torvalds {
13251b8d7ae4SEric W. Biederman 	return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
13261da177e4SLinus Torvalds }
1327c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create);
13281da177e4SLinus Torvalds 
1329eeb1bd5cSEric W. Biederman int sock_create_kern(struct net *net, int family, int type, int protocol, struct socket **res)
13301da177e4SLinus Torvalds {
1331eeb1bd5cSEric W. Biederman 	return __sock_create(net, family, type, protocol, res, 1);
13321da177e4SLinus Torvalds }
1333c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_kern);
13341da177e4SLinus Torvalds 
13353e0fa65fSHeiko Carstens SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
13361da177e4SLinus Torvalds {
13371da177e4SLinus Torvalds 	int retval;
13381da177e4SLinus Torvalds 	struct socket *sock;
1339a677a039SUlrich Drepper 	int flags;
1340a677a039SUlrich Drepper 
1341e38b36f3SUlrich Drepper 	/* Check the SOCK_* constants for consistency.  */
1342e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
1343e38b36f3SUlrich Drepper 	BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
1344e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);
1345e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);
1346e38b36f3SUlrich Drepper 
1347a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
134877d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1349a677a039SUlrich Drepper 		return -EINVAL;
1350a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
13511da177e4SLinus Torvalds 
1352aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1353aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1354aaca0bdcSUlrich Drepper 
13551da177e4SLinus Torvalds 	retval = sock_create(family, type, protocol, &sock);
13561da177e4SLinus Torvalds 	if (retval < 0)
13571da177e4SLinus Torvalds 		return retval;
13581da177e4SLinus Torvalds 
13598e1611e2SAl Viro 	return sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
13601da177e4SLinus Torvalds }
13611da177e4SLinus Torvalds 
13621da177e4SLinus Torvalds /*
13631da177e4SLinus Torvalds  *	Create a pair of connected sockets.
13641da177e4SLinus Torvalds  */
13651da177e4SLinus Torvalds 
13663e0fa65fSHeiko Carstens SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
13673e0fa65fSHeiko Carstens 		int __user *, usockvec)
13681da177e4SLinus Torvalds {
13691da177e4SLinus Torvalds 	struct socket *sock1, *sock2;
13701da177e4SLinus Torvalds 	int fd1, fd2, err;
1371db349509SAl Viro 	struct file *newfile1, *newfile2;
1372a677a039SUlrich Drepper 	int flags;
1373a677a039SUlrich Drepper 
1374a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
137577d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1376a677a039SUlrich Drepper 		return -EINVAL;
1377a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
13781da177e4SLinus Torvalds 
1379aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1380aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1381aaca0bdcSUlrich Drepper 
13821da177e4SLinus Torvalds 	/*
1383016a266bSAl Viro 	 * reserve descriptors and make sure we won't fail
1384016a266bSAl Viro 	 * to return them to userland.
1385016a266bSAl Viro 	 */
1386016a266bSAl Viro 	fd1 = get_unused_fd_flags(flags);
1387016a266bSAl Viro 	if (unlikely(fd1 < 0))
1388016a266bSAl Viro 		return fd1;
1389016a266bSAl Viro 
1390016a266bSAl Viro 	fd2 = get_unused_fd_flags(flags);
1391016a266bSAl Viro 	if (unlikely(fd2 < 0)) {
1392016a266bSAl Viro 		put_unused_fd(fd1);
1393016a266bSAl Viro 		return fd2;
1394016a266bSAl Viro 	}
1395016a266bSAl Viro 
1396016a266bSAl Viro 	err = put_user(fd1, &usockvec[0]);
1397016a266bSAl Viro 	if (err)
1398016a266bSAl Viro 		goto out;
1399016a266bSAl Viro 
1400016a266bSAl Viro 	err = put_user(fd2, &usockvec[1]);
1401016a266bSAl Viro 	if (err)
1402016a266bSAl Viro 		goto out;
1403016a266bSAl Viro 
1404016a266bSAl Viro 	/*
14051da177e4SLinus Torvalds 	 * Obtain the first socket and check if the underlying protocol
14061da177e4SLinus Torvalds 	 * supports the socketpair call.
14071da177e4SLinus Torvalds 	 */
14081da177e4SLinus Torvalds 
14091da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock1);
1410016a266bSAl Viro 	if (unlikely(err < 0))
14111da177e4SLinus Torvalds 		goto out;
14121da177e4SLinus Torvalds 
14131da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock2);
1414016a266bSAl Viro 	if (unlikely(err < 0)) {
1415016a266bSAl Viro 		sock_release(sock1);
1416016a266bSAl Viro 		goto out;
1417bf3c23d1SDavid S. Miller 	}
1418d73aa286SYann Droneaud 
1419016a266bSAl Viro 	err = sock1->ops->socketpair(sock1, sock2);
1420016a266bSAl Viro 	if (unlikely(err < 0)) {
1421016a266bSAl Viro 		sock_release(sock2);
1422016a266bSAl Viro 		sock_release(sock1);
1423016a266bSAl Viro 		goto out;
142428407630SAl Viro 	}
142528407630SAl Viro 
1426aab174f0SLinus Torvalds 	newfile1 = sock_alloc_file(sock1, flags, NULL);
1427b5ffe634SViresh Kumar 	if (IS_ERR(newfile1)) {
142828407630SAl Viro 		err = PTR_ERR(newfile1);
1429016a266bSAl Viro 		sock_release(sock2);
1430016a266bSAl Viro 		goto out;
143128407630SAl Viro 	}
143228407630SAl Viro 
1433aab174f0SLinus Torvalds 	newfile2 = sock_alloc_file(sock2, flags, NULL);
143428407630SAl Viro 	if (IS_ERR(newfile2)) {
143528407630SAl Viro 		err = PTR_ERR(newfile2);
1436016a266bSAl Viro 		fput(newfile1);
1437016a266bSAl Viro 		goto out;
1438db349509SAl Viro 	}
1439db349509SAl Viro 
1440157cf649SAl Viro 	audit_fd_pair(fd1, fd2);
1441d73aa286SYann Droneaud 
1442db349509SAl Viro 	fd_install(fd1, newfile1);
1443db349509SAl Viro 	fd_install(fd2, newfile2);
14441da177e4SLinus Torvalds 	return 0;
14451da177e4SLinus Torvalds 
14461da177e4SLinus Torvalds out:
1447016a266bSAl Viro 	put_unused_fd(fd2);
1448016a266bSAl Viro 	put_unused_fd(fd1);
14491da177e4SLinus Torvalds 	return err;
14501da177e4SLinus Torvalds }
14511da177e4SLinus Torvalds 
14521da177e4SLinus Torvalds /*
14531da177e4SLinus Torvalds  *	Bind a name to a socket. Nothing much to do here since it's
14541da177e4SLinus Torvalds  *	the protocol's responsibility to handle the local address.
14551da177e4SLinus Torvalds  *
14561da177e4SLinus Torvalds  *	We move the socket address to kernel space before we call
14571da177e4SLinus Torvalds  *	the protocol layer (having also checked the address is ok).
14581da177e4SLinus Torvalds  */
14591da177e4SLinus Torvalds 
146020f37034SHeiko Carstens SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
14611da177e4SLinus Torvalds {
14621da177e4SLinus Torvalds 	struct socket *sock;
1463230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
14646cb153caSBenjamin LaHaise 	int err, fput_needed;
14651da177e4SLinus Torvalds 
146689bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
146789bddce5SStephen Hemminger 	if (sock) {
146843db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(umyaddr, addrlen, &address);
146989bddce5SStephen Hemminger 		if (err >= 0) {
147089bddce5SStephen Hemminger 			err = security_socket_bind(sock,
1471230b1839SYOSHIFUJI Hideaki 						   (struct sockaddr *)&address,
147289bddce5SStephen Hemminger 						   addrlen);
14736cb153caSBenjamin LaHaise 			if (!err)
14746cb153caSBenjamin LaHaise 				err = sock->ops->bind(sock,
147589bddce5SStephen Hemminger 						      (struct sockaddr *)
1476230b1839SYOSHIFUJI Hideaki 						      &address, addrlen);
14771da177e4SLinus Torvalds 		}
14786cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
14791da177e4SLinus Torvalds 	}
14801da177e4SLinus Torvalds 	return err;
14811da177e4SLinus Torvalds }
14821da177e4SLinus Torvalds 
14831da177e4SLinus Torvalds /*
14841da177e4SLinus Torvalds  *	Perform a listen. Basically, we allow the protocol to do anything
14851da177e4SLinus Torvalds  *	necessary for a listen, and if that works, we mark the socket as
14861da177e4SLinus Torvalds  *	ready for listening.
14871da177e4SLinus Torvalds  */
14881da177e4SLinus Torvalds 
14893e0fa65fSHeiko Carstens SYSCALL_DEFINE2(listen, int, fd, int, backlog)
14901da177e4SLinus Torvalds {
14911da177e4SLinus Torvalds 	struct socket *sock;
14926cb153caSBenjamin LaHaise 	int err, fput_needed;
1493b8e1f9b5SPavel Emelyanov 	int somaxconn;
14941da177e4SLinus Torvalds 
149589bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
149689bddce5SStephen Hemminger 	if (sock) {
14978efa6e93SPavel Emelyanov 		somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
149895c96174SEric Dumazet 		if ((unsigned int)backlog > somaxconn)
1499b8e1f9b5SPavel Emelyanov 			backlog = somaxconn;
15001da177e4SLinus Torvalds 
15011da177e4SLinus Torvalds 		err = security_socket_listen(sock, backlog);
15026cb153caSBenjamin LaHaise 		if (!err)
15031da177e4SLinus Torvalds 			err = sock->ops->listen(sock, backlog);
15046cb153caSBenjamin LaHaise 
15056cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
15061da177e4SLinus Torvalds 	}
15071da177e4SLinus Torvalds 	return err;
15081da177e4SLinus Torvalds }
15091da177e4SLinus Torvalds 
15101da177e4SLinus Torvalds /*
15111da177e4SLinus Torvalds  *	For accept, we attempt to create a new socket, set up the link
15121da177e4SLinus Torvalds  *	with the client, wake up the client, then return the new
15131da177e4SLinus Torvalds  *	connected fd. We collect the address of the connector in kernel
15141da177e4SLinus Torvalds  *	space and move it to user at the very end. This is unclean because
15151da177e4SLinus Torvalds  *	we open the socket then return an error.
15161da177e4SLinus Torvalds  *
15171da177e4SLinus Torvalds  *	1003.1g adds the ability to recvmsg() to query connection pending
15181da177e4SLinus Torvalds  *	status to recvmsg. We need to add that support in a way thats
15191da177e4SLinus Torvalds  *	clean when we restucture accept also.
15201da177e4SLinus Torvalds  */
15211da177e4SLinus Torvalds 
152220f37034SHeiko Carstens SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
152320f37034SHeiko Carstens 		int __user *, upeer_addrlen, int, flags)
15241da177e4SLinus Torvalds {
15251da177e4SLinus Torvalds 	struct socket *sock, *newsock;
152639d8c1b6SDavid S. Miller 	struct file *newfile;
15276cb153caSBenjamin LaHaise 	int err, len, newfd, fput_needed;
1528230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
15291da177e4SLinus Torvalds 
153077d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1531aaca0bdcSUlrich Drepper 		return -EINVAL;
1532aaca0bdcSUlrich Drepper 
1533aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1534aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1535aaca0bdcSUlrich Drepper 
15366cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
15371da177e4SLinus Torvalds 	if (!sock)
15381da177e4SLinus Torvalds 		goto out;
15391da177e4SLinus Torvalds 
15401da177e4SLinus Torvalds 	err = -ENFILE;
1541c6d409cfSEric Dumazet 	newsock = sock_alloc();
1542c6d409cfSEric Dumazet 	if (!newsock)
15431da177e4SLinus Torvalds 		goto out_put;
15441da177e4SLinus Torvalds 
15451da177e4SLinus Torvalds 	newsock->type = sock->type;
15461da177e4SLinus Torvalds 	newsock->ops = sock->ops;
15471da177e4SLinus Torvalds 
15481da177e4SLinus Torvalds 	/*
15491da177e4SLinus Torvalds 	 * We don't need try_module_get here, as the listening socket (sock)
15501da177e4SLinus Torvalds 	 * has the protocol module (sock->ops->owner) held.
15511da177e4SLinus Torvalds 	 */
15521da177e4SLinus Torvalds 	__module_get(newsock->ops->owner);
15531da177e4SLinus Torvalds 
155428407630SAl Viro 	newfd = get_unused_fd_flags(flags);
155539d8c1b6SDavid S. Miller 	if (unlikely(newfd < 0)) {
155639d8c1b6SDavid S. Miller 		err = newfd;
15579a1875e6SDavid S. Miller 		sock_release(newsock);
15589a1875e6SDavid S. Miller 		goto out_put;
155939d8c1b6SDavid S. Miller 	}
1560aab174f0SLinus Torvalds 	newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name);
1561b5ffe634SViresh Kumar 	if (IS_ERR(newfile)) {
156228407630SAl Viro 		err = PTR_ERR(newfile);
156328407630SAl Viro 		put_unused_fd(newfd);
156428407630SAl Viro 		goto out_put;
156528407630SAl Viro 	}
156639d8c1b6SDavid S. Miller 
1567a79af59eSFrank Filz 	err = security_socket_accept(sock, newsock);
1568a79af59eSFrank Filz 	if (err)
156939d8c1b6SDavid S. Miller 		goto out_fd;
1570a79af59eSFrank Filz 
1571cdfbabfbSDavid Howells 	err = sock->ops->accept(sock, newsock, sock->file->f_flags, false);
15721da177e4SLinus Torvalds 	if (err < 0)
157339d8c1b6SDavid S. Miller 		goto out_fd;
15741da177e4SLinus Torvalds 
15751da177e4SLinus Torvalds 	if (upeer_sockaddr) {
15769b2c45d4SDenys Vlasenko 		len = newsock->ops->getname(newsock,
15779b2c45d4SDenys Vlasenko 					(struct sockaddr *)&address, 2);
15789b2c45d4SDenys Vlasenko 		if (len < 0) {
15791da177e4SLinus Torvalds 			err = -ECONNABORTED;
158039d8c1b6SDavid S. Miller 			goto out_fd;
15811da177e4SLinus Torvalds 		}
158243db362dSMaciej Żenczykowski 		err = move_addr_to_user(&address,
1583230b1839SYOSHIFUJI Hideaki 					len, upeer_sockaddr, upeer_addrlen);
15841da177e4SLinus Torvalds 		if (err < 0)
158539d8c1b6SDavid S. Miller 			goto out_fd;
15861da177e4SLinus Torvalds 	}
15871da177e4SLinus Torvalds 
15881da177e4SLinus Torvalds 	/* File flags are not inherited via accept() unlike another OSes. */
15891da177e4SLinus Torvalds 
159039d8c1b6SDavid S. Miller 	fd_install(newfd, newfile);
159139d8c1b6SDavid S. Miller 	err = newfd;
15921da177e4SLinus Torvalds 
15931da177e4SLinus Torvalds out_put:
15946cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
15951da177e4SLinus Torvalds out:
15961da177e4SLinus Torvalds 	return err;
159739d8c1b6SDavid S. Miller out_fd:
15989606a216SDavid S. Miller 	fput(newfile);
159939d8c1b6SDavid S. Miller 	put_unused_fd(newfd);
16001da177e4SLinus Torvalds 	goto out_put;
16011da177e4SLinus Torvalds }
16021da177e4SLinus Torvalds 
160320f37034SHeiko Carstens SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,
160420f37034SHeiko Carstens 		int __user *, upeer_addrlen)
1605aaca0bdcSUlrich Drepper {
1606de11defeSUlrich Drepper 	return sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0);
1607aaca0bdcSUlrich Drepper }
1608aaca0bdcSUlrich Drepper 
16091da177e4SLinus Torvalds /*
16101da177e4SLinus Torvalds  *	Attempt to connect to a socket with the server address.  The address
16111da177e4SLinus Torvalds  *	is in user space so we verify it is OK and move it to kernel space.
16121da177e4SLinus Torvalds  *
16131da177e4SLinus Torvalds  *	For 1003.1g we need to add clean support for a bind to AF_UNSPEC to
16141da177e4SLinus Torvalds  *	break bindings
16151da177e4SLinus Torvalds  *
16161da177e4SLinus Torvalds  *	NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and
16171da177e4SLinus Torvalds  *	other SEQPACKET protocols that take time to connect() as it doesn't
16181da177e4SLinus Torvalds  *	include the -EINPROGRESS status for such sockets.
16191da177e4SLinus Torvalds  */
16201da177e4SLinus Torvalds 
162120f37034SHeiko Carstens SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
162220f37034SHeiko Carstens 		int, addrlen)
16231da177e4SLinus Torvalds {
16241da177e4SLinus Torvalds 	struct socket *sock;
1625230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16266cb153caSBenjamin LaHaise 	int err, fput_needed;
16271da177e4SLinus Torvalds 
16286cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
16291da177e4SLinus Torvalds 	if (!sock)
16301da177e4SLinus Torvalds 		goto out;
163143db362dSMaciej Żenczykowski 	err = move_addr_to_kernel(uservaddr, addrlen, &address);
16321da177e4SLinus Torvalds 	if (err < 0)
16331da177e4SLinus Torvalds 		goto out_put;
16341da177e4SLinus Torvalds 
163589bddce5SStephen Hemminger 	err =
1636230b1839SYOSHIFUJI Hideaki 	    security_socket_connect(sock, (struct sockaddr *)&address, addrlen);
16371da177e4SLinus Torvalds 	if (err)
16381da177e4SLinus Torvalds 		goto out_put;
16391da177e4SLinus Torvalds 
1640230b1839SYOSHIFUJI Hideaki 	err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,
16411da177e4SLinus Torvalds 				 sock->file->f_flags);
16421da177e4SLinus Torvalds out_put:
16436cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
16441da177e4SLinus Torvalds out:
16451da177e4SLinus Torvalds 	return err;
16461da177e4SLinus Torvalds }
16471da177e4SLinus Torvalds 
16481da177e4SLinus Torvalds /*
16491da177e4SLinus Torvalds  *	Get the local address ('name') of a socket object. Move the obtained
16501da177e4SLinus Torvalds  *	name to user space.
16511da177e4SLinus Torvalds  */
16521da177e4SLinus Torvalds 
165320f37034SHeiko Carstens SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
165420f37034SHeiko Carstens 		int __user *, usockaddr_len)
16551da177e4SLinus Torvalds {
16561da177e4SLinus Torvalds 	struct socket *sock;
1657230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16589b2c45d4SDenys Vlasenko 	int err, fput_needed;
16591da177e4SLinus Torvalds 
16606cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
16611da177e4SLinus Torvalds 	if (!sock)
16621da177e4SLinus Torvalds 		goto out;
16631da177e4SLinus Torvalds 
16641da177e4SLinus Torvalds 	err = security_socket_getsockname(sock);
16651da177e4SLinus Torvalds 	if (err)
16661da177e4SLinus Torvalds 		goto out_put;
16671da177e4SLinus Torvalds 
16689b2c45d4SDenys Vlasenko 	err = sock->ops->getname(sock, (struct sockaddr *)&address, 0);
16699b2c45d4SDenys Vlasenko 	if (err < 0)
16701da177e4SLinus Torvalds 		goto out_put;
16719b2c45d4SDenys Vlasenko         /* "err" is actually length in this case */
16729b2c45d4SDenys Vlasenko 	err = move_addr_to_user(&address, err, usockaddr, usockaddr_len);
16731da177e4SLinus Torvalds 
16741da177e4SLinus Torvalds out_put:
16756cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
16761da177e4SLinus Torvalds out:
16771da177e4SLinus Torvalds 	return err;
16781da177e4SLinus Torvalds }
16791da177e4SLinus Torvalds 
16801da177e4SLinus Torvalds /*
16811da177e4SLinus Torvalds  *	Get the remote address ('name') of a socket object. Move the obtained
16821da177e4SLinus Torvalds  *	name to user space.
16831da177e4SLinus Torvalds  */
16841da177e4SLinus Torvalds 
168520f37034SHeiko Carstens SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
168620f37034SHeiko Carstens 		int __user *, usockaddr_len)
16871da177e4SLinus Torvalds {
16881da177e4SLinus Torvalds 	struct socket *sock;
1689230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16909b2c45d4SDenys Vlasenko 	int err, fput_needed;
16911da177e4SLinus Torvalds 
169289bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
169389bddce5SStephen Hemminger 	if (sock != NULL) {
16941da177e4SLinus Torvalds 		err = security_socket_getpeername(sock);
16951da177e4SLinus Torvalds 		if (err) {
16966cb153caSBenjamin LaHaise 			fput_light(sock->file, fput_needed);
16971da177e4SLinus Torvalds 			return err;
16981da177e4SLinus Torvalds 		}
16991da177e4SLinus Torvalds 
17009b2c45d4SDenys Vlasenko 		err = sock->ops->getname(sock, (struct sockaddr *)&address, 1);
17019b2c45d4SDenys Vlasenko 		if (err >= 0)
17029b2c45d4SDenys Vlasenko 			/* "err" is actually length in this case */
17039b2c45d4SDenys Vlasenko 			err = move_addr_to_user(&address, err, usockaddr,
170489bddce5SStephen Hemminger 						usockaddr_len);
17056cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
17061da177e4SLinus Torvalds 	}
17071da177e4SLinus Torvalds 	return err;
17081da177e4SLinus Torvalds }
17091da177e4SLinus Torvalds 
17101da177e4SLinus Torvalds /*
17111da177e4SLinus Torvalds  *	Send a datagram to a given address. We move the address into kernel
17121da177e4SLinus Torvalds  *	space and check the user space data area is readable before invoking
17131da177e4SLinus Torvalds  *	the protocol.
17141da177e4SLinus Torvalds  */
17151da177e4SLinus Torvalds 
17163e0fa65fSHeiko Carstens SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
171795c96174SEric Dumazet 		unsigned int, flags, struct sockaddr __user *, addr,
17183e0fa65fSHeiko Carstens 		int, addr_len)
17191da177e4SLinus Torvalds {
17201da177e4SLinus Torvalds 	struct socket *sock;
1721230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
17221da177e4SLinus Torvalds 	int err;
17231da177e4SLinus Torvalds 	struct msghdr msg;
17241da177e4SLinus Torvalds 	struct iovec iov;
17256cb153caSBenjamin LaHaise 	int fput_needed;
17261da177e4SLinus Torvalds 
1727602bd0e9SAl Viro 	err = import_single_range(WRITE, buff, len, &iov, &msg.msg_iter);
1728602bd0e9SAl Viro 	if (unlikely(err))
1729602bd0e9SAl Viro 		return err;
1730de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1731de0fa95cSPavel Emelyanov 	if (!sock)
17324387ff75SDavid S. Miller 		goto out;
17336cb153caSBenjamin LaHaise 
17341da177e4SLinus Torvalds 	msg.msg_name = NULL;
17351da177e4SLinus Torvalds 	msg.msg_control = NULL;
17361da177e4SLinus Torvalds 	msg.msg_controllen = 0;
17371da177e4SLinus Torvalds 	msg.msg_namelen = 0;
17386cb153caSBenjamin LaHaise 	if (addr) {
173943db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(addr, addr_len, &address);
17401da177e4SLinus Torvalds 		if (err < 0)
17411da177e4SLinus Torvalds 			goto out_put;
1742230b1839SYOSHIFUJI Hideaki 		msg.msg_name = (struct sockaddr *)&address;
17431da177e4SLinus Torvalds 		msg.msg_namelen = addr_len;
17441da177e4SLinus Torvalds 	}
17451da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
17461da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
17471da177e4SLinus Torvalds 	msg.msg_flags = flags;
1748d8725c86SAl Viro 	err = sock_sendmsg(sock, &msg);
17491da177e4SLinus Torvalds 
17501da177e4SLinus Torvalds out_put:
1751de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
17524387ff75SDavid S. Miller out:
17531da177e4SLinus Torvalds 	return err;
17541da177e4SLinus Torvalds }
17551da177e4SLinus Torvalds 
17561da177e4SLinus Torvalds /*
17571da177e4SLinus Torvalds  *	Send a datagram down a socket.
17581da177e4SLinus Torvalds  */
17591da177e4SLinus Torvalds 
17603e0fa65fSHeiko Carstens SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len,
176195c96174SEric Dumazet 		unsigned int, flags)
17621da177e4SLinus Torvalds {
17631da177e4SLinus Torvalds 	return sys_sendto(fd, buff, len, flags, NULL, 0);
17641da177e4SLinus Torvalds }
17651da177e4SLinus Torvalds 
17661da177e4SLinus Torvalds /*
17671da177e4SLinus Torvalds  *	Receive a frame from the socket and optionally record the address of the
17681da177e4SLinus Torvalds  *	sender. We verify the buffers are writable and if needed move the
17691da177e4SLinus Torvalds  *	sender address from kernel to user space.
17701da177e4SLinus Torvalds  */
17711da177e4SLinus Torvalds 
17723e0fa65fSHeiko Carstens SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
177395c96174SEric Dumazet 		unsigned int, flags, struct sockaddr __user *, addr,
17743e0fa65fSHeiko Carstens 		int __user *, addr_len)
17751da177e4SLinus Torvalds {
17761da177e4SLinus Torvalds 	struct socket *sock;
17771da177e4SLinus Torvalds 	struct iovec iov;
17781da177e4SLinus Torvalds 	struct msghdr msg;
1779230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
17801da177e4SLinus Torvalds 	int err, err2;
17816cb153caSBenjamin LaHaise 	int fput_needed;
17821da177e4SLinus Torvalds 
1783602bd0e9SAl Viro 	err = import_single_range(READ, ubuf, size, &iov, &msg.msg_iter);
1784602bd0e9SAl Viro 	if (unlikely(err))
1785602bd0e9SAl Viro 		return err;
1786de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
17871da177e4SLinus Torvalds 	if (!sock)
1788de0fa95cSPavel Emelyanov 		goto out;
17891da177e4SLinus Torvalds 
17901da177e4SLinus Torvalds 	msg.msg_control = NULL;
17911da177e4SLinus Torvalds 	msg.msg_controllen = 0;
1792f3d33426SHannes Frederic Sowa 	/* Save some cycles and don't copy the address if not needed */
1793f3d33426SHannes Frederic Sowa 	msg.msg_name = addr ? (struct sockaddr *)&address : NULL;
1794f3d33426SHannes Frederic Sowa 	/* We assume all kernel code knows the size of sockaddr_storage */
1795f3d33426SHannes Frederic Sowa 	msg.msg_namelen = 0;
1796130ed5d1Stadeusz.struk@intel.com 	msg.msg_iocb = NULL;
17979f138fa6SAlexander Potapenko 	msg.msg_flags = 0;
17981da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
17991da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
18002da62906SAl Viro 	err = sock_recvmsg(sock, &msg, flags);
18011da177e4SLinus Torvalds 
180289bddce5SStephen Hemminger 	if (err >= 0 && addr != NULL) {
180343db362dSMaciej Żenczykowski 		err2 = move_addr_to_user(&address,
1804230b1839SYOSHIFUJI Hideaki 					 msg.msg_namelen, addr, addr_len);
18051da177e4SLinus Torvalds 		if (err2 < 0)
18061da177e4SLinus Torvalds 			err = err2;
18071da177e4SLinus Torvalds 	}
1808de0fa95cSPavel Emelyanov 
1809de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
18104387ff75SDavid S. Miller out:
18111da177e4SLinus Torvalds 	return err;
18121da177e4SLinus Torvalds }
18131da177e4SLinus Torvalds 
18141da177e4SLinus Torvalds /*
18151da177e4SLinus Torvalds  *	Receive a datagram from a socket.
18161da177e4SLinus Torvalds  */
18171da177e4SLinus Torvalds 
1818b7c0ddf5SJan Glauber SYSCALL_DEFINE4(recv, int, fd, void __user *, ubuf, size_t, size,
1819b7c0ddf5SJan Glauber 		unsigned int, flags)
18201da177e4SLinus Torvalds {
18211da177e4SLinus Torvalds 	return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL);
18221da177e4SLinus Torvalds }
18231da177e4SLinus Torvalds 
18241da177e4SLinus Torvalds /*
18251da177e4SLinus Torvalds  *	Set a socket option. Because we don't know the option lengths we have
18261da177e4SLinus Torvalds  *	to pass the user mode parameter for the protocols to sort out.
18271da177e4SLinus Torvalds  */
18281da177e4SLinus Torvalds 
182920f37034SHeiko Carstens SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
183020f37034SHeiko Carstens 		char __user *, optval, int, optlen)
18311da177e4SLinus Torvalds {
18326cb153caSBenjamin LaHaise 	int err, fput_needed;
18331da177e4SLinus Torvalds 	struct socket *sock;
18341da177e4SLinus Torvalds 
18351da177e4SLinus Torvalds 	if (optlen < 0)
18361da177e4SLinus Torvalds 		return -EINVAL;
18371da177e4SLinus Torvalds 
183889bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
183989bddce5SStephen Hemminger 	if (sock != NULL) {
18401da177e4SLinus Torvalds 		err = security_socket_setsockopt(sock, level, optname);
18416cb153caSBenjamin LaHaise 		if (err)
18426cb153caSBenjamin LaHaise 			goto out_put;
18431da177e4SLinus Torvalds 
18441da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
184589bddce5SStephen Hemminger 			err =
184689bddce5SStephen Hemminger 			    sock_setsockopt(sock, level, optname, optval,
184789bddce5SStephen Hemminger 					    optlen);
18481da177e4SLinus Torvalds 		else
184989bddce5SStephen Hemminger 			err =
185089bddce5SStephen Hemminger 			    sock->ops->setsockopt(sock, level, optname, optval,
185189bddce5SStephen Hemminger 						  optlen);
18526cb153caSBenjamin LaHaise out_put:
18536cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
18541da177e4SLinus Torvalds 	}
18551da177e4SLinus Torvalds 	return err;
18561da177e4SLinus Torvalds }
18571da177e4SLinus Torvalds 
18581da177e4SLinus Torvalds /*
18591da177e4SLinus Torvalds  *	Get a socket option. Because we don't know the option lengths we have
18601da177e4SLinus Torvalds  *	to pass a user mode parameter for the protocols to sort out.
18611da177e4SLinus Torvalds  */
18621da177e4SLinus Torvalds 
186320f37034SHeiko Carstens SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
186420f37034SHeiko Carstens 		char __user *, optval, int __user *, optlen)
18651da177e4SLinus Torvalds {
18666cb153caSBenjamin LaHaise 	int err, fput_needed;
18671da177e4SLinus Torvalds 	struct socket *sock;
18681da177e4SLinus Torvalds 
186989bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
187089bddce5SStephen Hemminger 	if (sock != NULL) {
18716cb153caSBenjamin LaHaise 		err = security_socket_getsockopt(sock, level, optname);
18726cb153caSBenjamin LaHaise 		if (err)
18736cb153caSBenjamin LaHaise 			goto out_put;
18741da177e4SLinus Torvalds 
18751da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
187689bddce5SStephen Hemminger 			err =
187789bddce5SStephen Hemminger 			    sock_getsockopt(sock, level, optname, optval,
187889bddce5SStephen Hemminger 					    optlen);
18791da177e4SLinus Torvalds 		else
188089bddce5SStephen Hemminger 			err =
188189bddce5SStephen Hemminger 			    sock->ops->getsockopt(sock, level, optname, optval,
188289bddce5SStephen Hemminger 						  optlen);
18836cb153caSBenjamin LaHaise out_put:
18846cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
18851da177e4SLinus Torvalds 	}
18861da177e4SLinus Torvalds 	return err;
18871da177e4SLinus Torvalds }
18881da177e4SLinus Torvalds 
18891da177e4SLinus Torvalds /*
18901da177e4SLinus Torvalds  *	Shutdown a socket.
18911da177e4SLinus Torvalds  */
18921da177e4SLinus Torvalds 
1893754fe8d2SHeiko Carstens SYSCALL_DEFINE2(shutdown, int, fd, int, how)
18941da177e4SLinus Torvalds {
18956cb153caSBenjamin LaHaise 	int err, fput_needed;
18961da177e4SLinus Torvalds 	struct socket *sock;
18971da177e4SLinus Torvalds 
189889bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
189989bddce5SStephen Hemminger 	if (sock != NULL) {
19001da177e4SLinus Torvalds 		err = security_socket_shutdown(sock, how);
19016cb153caSBenjamin LaHaise 		if (!err)
19021da177e4SLinus Torvalds 			err = sock->ops->shutdown(sock, how);
19036cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
19041da177e4SLinus Torvalds 	}
19051da177e4SLinus Torvalds 	return err;
19061da177e4SLinus Torvalds }
19071da177e4SLinus Torvalds 
19081da177e4SLinus Torvalds /* A couple of helpful macros for getting the address of the 32/64 bit
19091da177e4SLinus Torvalds  * fields which are the same type (int / unsigned) on our platforms.
19101da177e4SLinus Torvalds  */
19111da177e4SLinus Torvalds #define COMPAT_MSG(msg, member)	((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member)
19121da177e4SLinus Torvalds #define COMPAT_NAMELEN(msg)	COMPAT_MSG(msg, msg_namelen)
19131da177e4SLinus Torvalds #define COMPAT_FLAGS(msg)	COMPAT_MSG(msg, msg_flags)
19141da177e4SLinus Torvalds 
1915c71d8ebeSTetsuo Handa struct used_address {
1916c71d8ebeSTetsuo Handa 	struct sockaddr_storage name;
1917c71d8ebeSTetsuo Handa 	unsigned int name_len;
1918c71d8ebeSTetsuo Handa };
1919c71d8ebeSTetsuo Handa 
1920da184284SAl Viro static int copy_msghdr_from_user(struct msghdr *kmsg,
192108adb7daSAl Viro 				 struct user_msghdr __user *umsg,
192208adb7daSAl Viro 				 struct sockaddr __user **save_addr,
192308adb7daSAl Viro 				 struct iovec **iov)
19241661bf36SDan Carpenter {
1925ffb07550SAl Viro 	struct user_msghdr msg;
192608adb7daSAl Viro 	ssize_t err;
192708adb7daSAl Viro 
1928ffb07550SAl Viro 	if (copy_from_user(&msg, umsg, sizeof(*umsg)))
19291661bf36SDan Carpenter 		return -EFAULT;
1930dbb490b9SMatthew Leach 
1931864d9664SPaolo Abeni 	kmsg->msg_control = (void __force *)msg.msg_control;
1932ffb07550SAl Viro 	kmsg->msg_controllen = msg.msg_controllen;
1933ffb07550SAl Viro 	kmsg->msg_flags = msg.msg_flags;
1934ffb07550SAl Viro 
1935ffb07550SAl Viro 	kmsg->msg_namelen = msg.msg_namelen;
1936ffb07550SAl Viro 	if (!msg.msg_name)
19376a2a2b3aSAni Sinha 		kmsg->msg_namelen = 0;
19386a2a2b3aSAni Sinha 
1939dbb490b9SMatthew Leach 	if (kmsg->msg_namelen < 0)
1940dbb490b9SMatthew Leach 		return -EINVAL;
1941dbb490b9SMatthew Leach 
19421661bf36SDan Carpenter 	if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
1943db31c55aSDan Carpenter 		kmsg->msg_namelen = sizeof(struct sockaddr_storage);
194408adb7daSAl Viro 
194508adb7daSAl Viro 	if (save_addr)
1946ffb07550SAl Viro 		*save_addr = msg.msg_name;
194708adb7daSAl Viro 
1948ffb07550SAl Viro 	if (msg.msg_name && kmsg->msg_namelen) {
194908adb7daSAl Viro 		if (!save_addr) {
1950864d9664SPaolo Abeni 			err = move_addr_to_kernel(msg.msg_name,
1951864d9664SPaolo Abeni 						  kmsg->msg_namelen,
195208adb7daSAl Viro 						  kmsg->msg_name);
195308adb7daSAl Viro 			if (err < 0)
195408adb7daSAl Viro 				return err;
195508adb7daSAl Viro 		}
195608adb7daSAl Viro 	} else {
195708adb7daSAl Viro 		kmsg->msg_name = NULL;
195808adb7daSAl Viro 		kmsg->msg_namelen = 0;
195908adb7daSAl Viro 	}
196008adb7daSAl Viro 
1961ffb07550SAl Viro 	if (msg.msg_iovlen > UIO_MAXIOV)
196208adb7daSAl Viro 		return -EMSGSIZE;
196308adb7daSAl Viro 
19640345f931Stadeusz.struk@intel.com 	kmsg->msg_iocb = NULL;
19650345f931Stadeusz.struk@intel.com 
1966ffb07550SAl Viro 	return import_iovec(save_addr ? READ : WRITE,
1967ffb07550SAl Viro 			    msg.msg_iov, msg.msg_iovlen,
1968da184284SAl Viro 			    UIO_FASTIOV, iov, &kmsg->msg_iter);
19691661bf36SDan Carpenter }
19701661bf36SDan Carpenter 
1971666547ffSAl Viro static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
197295c96174SEric Dumazet 			 struct msghdr *msg_sys, unsigned int flags,
197328a94d8fSTom Herbert 			 struct used_address *used_address,
197428a94d8fSTom Herbert 			 unsigned int allowed_msghdr_flags)
19751da177e4SLinus Torvalds {
197689bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
197789bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
1978230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
19791da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
1980b9d717a7SAlex Williamson 	unsigned char ctl[sizeof(struct cmsghdr) + 20]
1981846cc123SAmit Kushwaha 				__aligned(sizeof(__kernel_size_t));
1982b9d717a7SAlex Williamson 	/* 20 is size of ipv6_pktinfo */
19831da177e4SLinus Torvalds 	unsigned char *ctl_buf = ctl;
1984d8725c86SAl Viro 	int ctl_len;
198508adb7daSAl Viro 	ssize_t err;
19861da177e4SLinus Torvalds 
198708adb7daSAl Viro 	msg_sys->msg_name = &address;
19881da177e4SLinus Torvalds 
198908449320SAl Viro 	if (MSG_CMSG_COMPAT & flags)
199008adb7daSAl Viro 		err = get_compat_msghdr(msg_sys, msg_compat, NULL, &iov);
199108449320SAl Viro 	else
199208adb7daSAl Viro 		err = copy_msghdr_from_user(msg_sys, msg, NULL, &iov);
19931da177e4SLinus Torvalds 	if (err < 0)
1994da184284SAl Viro 		return err;
19951da177e4SLinus Torvalds 
19961da177e4SLinus Torvalds 	err = -ENOBUFS;
19971da177e4SLinus Torvalds 
1998228e548eSAnton Blanchard 	if (msg_sys->msg_controllen > INT_MAX)
19991da177e4SLinus Torvalds 		goto out_freeiov;
200028a94d8fSTom Herbert 	flags |= (msg_sys->msg_flags & allowed_msghdr_flags);
2001228e548eSAnton Blanchard 	ctl_len = msg_sys->msg_controllen;
20021da177e4SLinus Torvalds 	if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
200389bddce5SStephen Hemminger 		err =
2004228e548eSAnton Blanchard 		    cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl,
200589bddce5SStephen Hemminger 						     sizeof(ctl));
20061da177e4SLinus Torvalds 		if (err)
20071da177e4SLinus Torvalds 			goto out_freeiov;
2008228e548eSAnton Blanchard 		ctl_buf = msg_sys->msg_control;
2009228e548eSAnton Blanchard 		ctl_len = msg_sys->msg_controllen;
20101da177e4SLinus Torvalds 	} else if (ctl_len) {
2011ac4340fcSDavid S. Miller 		BUILD_BUG_ON(sizeof(struct cmsghdr) !=
2012ac4340fcSDavid S. Miller 			     CMSG_ALIGN(sizeof(struct cmsghdr)));
201389bddce5SStephen Hemminger 		if (ctl_len > sizeof(ctl)) {
20141da177e4SLinus Torvalds 			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
20151da177e4SLinus Torvalds 			if (ctl_buf == NULL)
20161da177e4SLinus Torvalds 				goto out_freeiov;
20171da177e4SLinus Torvalds 		}
20181da177e4SLinus Torvalds 		err = -EFAULT;
20191da177e4SLinus Torvalds 		/*
2020228e548eSAnton Blanchard 		 * Careful! Before this, msg_sys->msg_control contains a user pointer.
20211da177e4SLinus Torvalds 		 * Afterwards, it will be a kernel pointer. Thus the compiler-assisted
20221da177e4SLinus Torvalds 		 * checking falls down on this.
20231da177e4SLinus Torvalds 		 */
2024fb8621bbSNamhyung Kim 		if (copy_from_user(ctl_buf,
2025228e548eSAnton Blanchard 				   (void __user __force *)msg_sys->msg_control,
202689bddce5SStephen Hemminger 				   ctl_len))
20271da177e4SLinus Torvalds 			goto out_freectl;
2028228e548eSAnton Blanchard 		msg_sys->msg_control = ctl_buf;
20291da177e4SLinus Torvalds 	}
2030228e548eSAnton Blanchard 	msg_sys->msg_flags = flags;
20311da177e4SLinus Torvalds 
20321da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
2033228e548eSAnton Blanchard 		msg_sys->msg_flags |= MSG_DONTWAIT;
2034c71d8ebeSTetsuo Handa 	/*
2035c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and current destination address is same as
2036c71d8ebeSTetsuo Handa 	 * previously succeeded address, omit asking LSM's decision.
2037c71d8ebeSTetsuo Handa 	 * used_address->name_len is initialized to UINT_MAX so that the first
2038c71d8ebeSTetsuo Handa 	 * destination address never matches.
2039c71d8ebeSTetsuo Handa 	 */
2040bc909d9dSMathieu Desnoyers 	if (used_address && msg_sys->msg_name &&
2041bc909d9dSMathieu Desnoyers 	    used_address->name_len == msg_sys->msg_namelen &&
2042bc909d9dSMathieu Desnoyers 	    !memcmp(&used_address->name, msg_sys->msg_name,
2043c71d8ebeSTetsuo Handa 		    used_address->name_len)) {
2044d8725c86SAl Viro 		err = sock_sendmsg_nosec(sock, msg_sys);
2045c71d8ebeSTetsuo Handa 		goto out_freectl;
2046c71d8ebeSTetsuo Handa 	}
2047d8725c86SAl Viro 	err = sock_sendmsg(sock, msg_sys);
2048c71d8ebeSTetsuo Handa 	/*
2049c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and sending to current destination address was
2050c71d8ebeSTetsuo Handa 	 * successful, remember it.
2051c71d8ebeSTetsuo Handa 	 */
2052c71d8ebeSTetsuo Handa 	if (used_address && err >= 0) {
2053c71d8ebeSTetsuo Handa 		used_address->name_len = msg_sys->msg_namelen;
2054bc909d9dSMathieu Desnoyers 		if (msg_sys->msg_name)
2055bc909d9dSMathieu Desnoyers 			memcpy(&used_address->name, msg_sys->msg_name,
2056c71d8ebeSTetsuo Handa 			       used_address->name_len);
2057c71d8ebeSTetsuo Handa 	}
20581da177e4SLinus Torvalds 
20591da177e4SLinus Torvalds out_freectl:
20601da177e4SLinus Torvalds 	if (ctl_buf != ctl)
20611da177e4SLinus Torvalds 		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
20621da177e4SLinus Torvalds out_freeiov:
2063a74e9106SEric Dumazet 	kfree(iov);
2064228e548eSAnton Blanchard 	return err;
2065228e548eSAnton Blanchard }
2066228e548eSAnton Blanchard 
2067228e548eSAnton Blanchard /*
2068228e548eSAnton Blanchard  *	BSD sendmsg interface
2069228e548eSAnton Blanchard  */
2070228e548eSAnton Blanchard 
2071666547ffSAl Viro long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned flags)
2072228e548eSAnton Blanchard {
2073228e548eSAnton Blanchard 	int fput_needed, err;
2074228e548eSAnton Blanchard 	struct msghdr msg_sys;
20751be374a0SAndy Lutomirski 	struct socket *sock;
2076228e548eSAnton Blanchard 
20771be374a0SAndy Lutomirski 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2078228e548eSAnton Blanchard 	if (!sock)
2079228e548eSAnton Blanchard 		goto out;
2080228e548eSAnton Blanchard 
208128a94d8fSTom Herbert 	err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL, 0);
2082228e548eSAnton Blanchard 
20836cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
20841da177e4SLinus Torvalds out:
20851da177e4SLinus Torvalds 	return err;
20861da177e4SLinus Torvalds }
20871da177e4SLinus Torvalds 
2088666547ffSAl Viro SYSCALL_DEFINE3(sendmsg, int, fd, struct user_msghdr __user *, msg, unsigned int, flags)
2089a7526eb5SAndy Lutomirski {
2090a7526eb5SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
2091a7526eb5SAndy Lutomirski 		return -EINVAL;
2092a7526eb5SAndy Lutomirski 	return __sys_sendmsg(fd, msg, flags);
2093a7526eb5SAndy Lutomirski }
2094a7526eb5SAndy Lutomirski 
2095228e548eSAnton Blanchard /*
2096228e548eSAnton Blanchard  *	Linux sendmmsg interface
2097228e548eSAnton Blanchard  */
2098228e548eSAnton Blanchard 
2099228e548eSAnton Blanchard int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2100228e548eSAnton Blanchard 		   unsigned int flags)
2101228e548eSAnton Blanchard {
2102228e548eSAnton Blanchard 	int fput_needed, err, datagrams;
2103228e548eSAnton Blanchard 	struct socket *sock;
2104228e548eSAnton Blanchard 	struct mmsghdr __user *entry;
2105228e548eSAnton Blanchard 	struct compat_mmsghdr __user *compat_entry;
2106228e548eSAnton Blanchard 	struct msghdr msg_sys;
2107c71d8ebeSTetsuo Handa 	struct used_address used_address;
2108f092276dSTom Herbert 	unsigned int oflags = flags;
2109228e548eSAnton Blanchard 
211098382f41SAnton Blanchard 	if (vlen > UIO_MAXIOV)
211198382f41SAnton Blanchard 		vlen = UIO_MAXIOV;
2112228e548eSAnton Blanchard 
2113228e548eSAnton Blanchard 	datagrams = 0;
2114228e548eSAnton Blanchard 
2115228e548eSAnton Blanchard 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2116228e548eSAnton Blanchard 	if (!sock)
2117228e548eSAnton Blanchard 		return err;
2118228e548eSAnton Blanchard 
2119c71d8ebeSTetsuo Handa 	used_address.name_len = UINT_MAX;
2120228e548eSAnton Blanchard 	entry = mmsg;
2121228e548eSAnton Blanchard 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2122728ffb86SAnton Blanchard 	err = 0;
2123f092276dSTom Herbert 	flags |= MSG_BATCH;
2124228e548eSAnton Blanchard 
2125228e548eSAnton Blanchard 	while (datagrams < vlen) {
2126f092276dSTom Herbert 		if (datagrams == vlen - 1)
2127f092276dSTom Herbert 			flags = oflags;
2128f092276dSTom Herbert 
2129228e548eSAnton Blanchard 		if (MSG_CMSG_COMPAT & flags) {
2130666547ffSAl Viro 			err = ___sys_sendmsg(sock, (struct user_msghdr __user *)compat_entry,
213128a94d8fSTom Herbert 					     &msg_sys, flags, &used_address, MSG_EOR);
2132228e548eSAnton Blanchard 			if (err < 0)
2133228e548eSAnton Blanchard 				break;
2134228e548eSAnton Blanchard 			err = __put_user(err, &compat_entry->msg_len);
2135228e548eSAnton Blanchard 			++compat_entry;
2136228e548eSAnton Blanchard 		} else {
2137a7526eb5SAndy Lutomirski 			err = ___sys_sendmsg(sock,
2138666547ffSAl Viro 					     (struct user_msghdr __user *)entry,
213928a94d8fSTom Herbert 					     &msg_sys, flags, &used_address, MSG_EOR);
2140228e548eSAnton Blanchard 			if (err < 0)
2141228e548eSAnton Blanchard 				break;
2142228e548eSAnton Blanchard 			err = put_user(err, &entry->msg_len);
2143228e548eSAnton Blanchard 			++entry;
2144228e548eSAnton Blanchard 		}
2145228e548eSAnton Blanchard 
2146228e548eSAnton Blanchard 		if (err)
2147228e548eSAnton Blanchard 			break;
2148228e548eSAnton Blanchard 		++datagrams;
21493023898bSSoheil Hassas Yeganeh 		if (msg_data_left(&msg_sys))
21503023898bSSoheil Hassas Yeganeh 			break;
2151a78cb84cSEric Dumazet 		cond_resched();
2152228e548eSAnton Blanchard 	}
2153228e548eSAnton Blanchard 
2154228e548eSAnton Blanchard 	fput_light(sock->file, fput_needed);
2155228e548eSAnton Blanchard 
2156728ffb86SAnton Blanchard 	/* We only return an error if no datagrams were able to be sent */
2157728ffb86SAnton Blanchard 	if (datagrams != 0)
2158228e548eSAnton Blanchard 		return datagrams;
2159228e548eSAnton Blanchard 
2160228e548eSAnton Blanchard 	return err;
2161228e548eSAnton Blanchard }
2162228e548eSAnton Blanchard 
2163228e548eSAnton Blanchard SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
2164228e548eSAnton Blanchard 		unsigned int, vlen, unsigned int, flags)
2165228e548eSAnton Blanchard {
21661be374a0SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
21671be374a0SAndy Lutomirski 		return -EINVAL;
2168228e548eSAnton Blanchard 	return __sys_sendmmsg(fd, mmsg, vlen, flags);
2169228e548eSAnton Blanchard }
2170228e548eSAnton Blanchard 
2171666547ffSAl Viro static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg,
217295c96174SEric Dumazet 			 struct msghdr *msg_sys, unsigned int flags, int nosec)
21731da177e4SLinus Torvalds {
217489bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
217589bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
21761da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV];
21771da177e4SLinus Torvalds 	struct iovec *iov = iovstack;
21781da177e4SLinus Torvalds 	unsigned long cmsg_ptr;
21792da62906SAl Viro 	int len;
218008adb7daSAl Viro 	ssize_t err;
21811da177e4SLinus Torvalds 
21821da177e4SLinus Torvalds 	/* kernel mode address */
2183230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage addr;
21841da177e4SLinus Torvalds 
21851da177e4SLinus Torvalds 	/* user mode address pointers */
21861da177e4SLinus Torvalds 	struct sockaddr __user *uaddr;
218708adb7daSAl Viro 	int __user *uaddr_len = COMPAT_NAMELEN(msg);
21881da177e4SLinus Torvalds 
218908adb7daSAl Viro 	msg_sys->msg_name = &addr;
21901da177e4SLinus Torvalds 
2191f3d33426SHannes Frederic Sowa 	if (MSG_CMSG_COMPAT & flags)
219208adb7daSAl Viro 		err = get_compat_msghdr(msg_sys, msg_compat, &uaddr, &iov);
2193f3d33426SHannes Frederic Sowa 	else
219408adb7daSAl Viro 		err = copy_msghdr_from_user(msg_sys, msg, &uaddr, &iov);
21951da177e4SLinus Torvalds 	if (err < 0)
2196da184284SAl Viro 		return err;
21971da177e4SLinus Torvalds 
2198a2e27255SArnaldo Carvalho de Melo 	cmsg_ptr = (unsigned long)msg_sys->msg_control;
2199a2e27255SArnaldo Carvalho de Melo 	msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
22001da177e4SLinus Torvalds 
2201f3d33426SHannes Frederic Sowa 	/* We assume all kernel code knows the size of sockaddr_storage */
2202f3d33426SHannes Frederic Sowa 	msg_sys->msg_namelen = 0;
2203f3d33426SHannes Frederic Sowa 
22041da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
22051da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
22062da62906SAl Viro 	err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys, flags);
22071da177e4SLinus Torvalds 	if (err < 0)
22081da177e4SLinus Torvalds 		goto out_freeiov;
22091da177e4SLinus Torvalds 	len = err;
22101da177e4SLinus Torvalds 
22111da177e4SLinus Torvalds 	if (uaddr != NULL) {
221243db362dSMaciej Żenczykowski 		err = move_addr_to_user(&addr,
2213a2e27255SArnaldo Carvalho de Melo 					msg_sys->msg_namelen, uaddr,
221489bddce5SStephen Hemminger 					uaddr_len);
22151da177e4SLinus Torvalds 		if (err < 0)
22161da177e4SLinus Torvalds 			goto out_freeiov;
22171da177e4SLinus Torvalds 	}
2218a2e27255SArnaldo Carvalho de Melo 	err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
221937f7f421SDavid S. Miller 			 COMPAT_FLAGS(msg));
22201da177e4SLinus Torvalds 	if (err)
22211da177e4SLinus Torvalds 		goto out_freeiov;
22221da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags)
2223a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
22241da177e4SLinus Torvalds 				 &msg_compat->msg_controllen);
22251da177e4SLinus Torvalds 	else
2226a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
22271da177e4SLinus Torvalds 				 &msg->msg_controllen);
22281da177e4SLinus Torvalds 	if (err)
22291da177e4SLinus Torvalds 		goto out_freeiov;
22301da177e4SLinus Torvalds 	err = len;
22311da177e4SLinus Torvalds 
22321da177e4SLinus Torvalds out_freeiov:
2233a74e9106SEric Dumazet 	kfree(iov);
2234a2e27255SArnaldo Carvalho de Melo 	return err;
2235a2e27255SArnaldo Carvalho de Melo }
2236a2e27255SArnaldo Carvalho de Melo 
2237a2e27255SArnaldo Carvalho de Melo /*
2238a2e27255SArnaldo Carvalho de Melo  *	BSD recvmsg interface
2239a2e27255SArnaldo Carvalho de Melo  */
2240a2e27255SArnaldo Carvalho de Melo 
2241666547ffSAl Viro long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned flags)
2242a2e27255SArnaldo Carvalho de Melo {
2243a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err;
2244a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
22451be374a0SAndy Lutomirski 	struct socket *sock;
2246a2e27255SArnaldo Carvalho de Melo 
22471be374a0SAndy Lutomirski 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2248a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2249a2e27255SArnaldo Carvalho de Melo 		goto out;
2250a2e27255SArnaldo Carvalho de Melo 
2251a7526eb5SAndy Lutomirski 	err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0);
2252a2e27255SArnaldo Carvalho de Melo 
22536cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
22541da177e4SLinus Torvalds out:
22551da177e4SLinus Torvalds 	return err;
22561da177e4SLinus Torvalds }
22571da177e4SLinus Torvalds 
2258666547ffSAl Viro SYSCALL_DEFINE3(recvmsg, int, fd, struct user_msghdr __user *, msg,
2259a7526eb5SAndy Lutomirski 		unsigned int, flags)
2260a7526eb5SAndy Lutomirski {
2261a7526eb5SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
2262a7526eb5SAndy Lutomirski 		return -EINVAL;
2263a7526eb5SAndy Lutomirski 	return __sys_recvmsg(fd, msg, flags);
2264a7526eb5SAndy Lutomirski }
2265a7526eb5SAndy Lutomirski 
2266a2e27255SArnaldo Carvalho de Melo /*
2267a2e27255SArnaldo Carvalho de Melo  *     Linux recvmmsg interface
2268a2e27255SArnaldo Carvalho de Melo  */
22691da177e4SLinus Torvalds 
2270a2e27255SArnaldo Carvalho de Melo int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2271a2e27255SArnaldo Carvalho de Melo 		   unsigned int flags, struct timespec *timeout)
2272a2e27255SArnaldo Carvalho de Melo {
2273a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err, datagrams;
2274a2e27255SArnaldo Carvalho de Melo 	struct socket *sock;
2275a2e27255SArnaldo Carvalho de Melo 	struct mmsghdr __user *entry;
2276d7256d0eSJean-Mickael Guerin 	struct compat_mmsghdr __user *compat_entry;
2277a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
2278766b9f92SDeepa Dinamani 	struct timespec64 end_time;
2279766b9f92SDeepa Dinamani 	struct timespec64 timeout64;
2280a2e27255SArnaldo Carvalho de Melo 
2281a2e27255SArnaldo Carvalho de Melo 	if (timeout &&
2282a2e27255SArnaldo Carvalho de Melo 	    poll_select_set_timeout(&end_time, timeout->tv_sec,
2283a2e27255SArnaldo Carvalho de Melo 				    timeout->tv_nsec))
2284a2e27255SArnaldo Carvalho de Melo 		return -EINVAL;
2285a2e27255SArnaldo Carvalho de Melo 
2286a2e27255SArnaldo Carvalho de Melo 	datagrams = 0;
2287a2e27255SArnaldo Carvalho de Melo 
2288a2e27255SArnaldo Carvalho de Melo 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2289a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2290a2e27255SArnaldo Carvalho de Melo 		return err;
2291a2e27255SArnaldo Carvalho de Melo 
2292a2e27255SArnaldo Carvalho de Melo 	err = sock_error(sock->sk);
2293e623a9e9SMaxime Jayat 	if (err) {
2294e623a9e9SMaxime Jayat 		datagrams = err;
2295a2e27255SArnaldo Carvalho de Melo 		goto out_put;
2296e623a9e9SMaxime Jayat 	}
2297a2e27255SArnaldo Carvalho de Melo 
2298a2e27255SArnaldo Carvalho de Melo 	entry = mmsg;
2299d7256d0eSJean-Mickael Guerin 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2300a2e27255SArnaldo Carvalho de Melo 
2301a2e27255SArnaldo Carvalho de Melo 	while (datagrams < vlen) {
2302a2e27255SArnaldo Carvalho de Melo 		/*
2303a2e27255SArnaldo Carvalho de Melo 		 * No need to ask LSM for more than the first datagram.
2304a2e27255SArnaldo Carvalho de Melo 		 */
2305d7256d0eSJean-Mickael Guerin 		if (MSG_CMSG_COMPAT & flags) {
2306666547ffSAl Viro 			err = ___sys_recvmsg(sock, (struct user_msghdr __user *)compat_entry,
2307b9eb8b87SAnton Blanchard 					     &msg_sys, flags & ~MSG_WAITFORONE,
2308b9eb8b87SAnton Blanchard 					     datagrams);
2309d7256d0eSJean-Mickael Guerin 			if (err < 0)
2310d7256d0eSJean-Mickael Guerin 				break;
2311d7256d0eSJean-Mickael Guerin 			err = __put_user(err, &compat_entry->msg_len);
2312d7256d0eSJean-Mickael Guerin 			++compat_entry;
2313d7256d0eSJean-Mickael Guerin 		} else {
2314a7526eb5SAndy Lutomirski 			err = ___sys_recvmsg(sock,
2315666547ffSAl Viro 					     (struct user_msghdr __user *)entry,
2316b9eb8b87SAnton Blanchard 					     &msg_sys, flags & ~MSG_WAITFORONE,
2317b9eb8b87SAnton Blanchard 					     datagrams);
2318a2e27255SArnaldo Carvalho de Melo 			if (err < 0)
2319a2e27255SArnaldo Carvalho de Melo 				break;
2320a2e27255SArnaldo Carvalho de Melo 			err = put_user(err, &entry->msg_len);
2321d7256d0eSJean-Mickael Guerin 			++entry;
2322d7256d0eSJean-Mickael Guerin 		}
2323d7256d0eSJean-Mickael Guerin 
2324a2e27255SArnaldo Carvalho de Melo 		if (err)
2325a2e27255SArnaldo Carvalho de Melo 			break;
2326a2e27255SArnaldo Carvalho de Melo 		++datagrams;
2327a2e27255SArnaldo Carvalho de Melo 
232871c5c159SBrandon L Black 		/* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
232971c5c159SBrandon L Black 		if (flags & MSG_WAITFORONE)
233071c5c159SBrandon L Black 			flags |= MSG_DONTWAIT;
233171c5c159SBrandon L Black 
2332a2e27255SArnaldo Carvalho de Melo 		if (timeout) {
2333766b9f92SDeepa Dinamani 			ktime_get_ts64(&timeout64);
2334766b9f92SDeepa Dinamani 			*timeout = timespec64_to_timespec(
2335766b9f92SDeepa Dinamani 					timespec64_sub(end_time, timeout64));
2336a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_sec < 0) {
2337a2e27255SArnaldo Carvalho de Melo 				timeout->tv_sec = timeout->tv_nsec = 0;
2338a2e27255SArnaldo Carvalho de Melo 				break;
2339a2e27255SArnaldo Carvalho de Melo 			}
2340a2e27255SArnaldo Carvalho de Melo 
2341a2e27255SArnaldo Carvalho de Melo 			/* Timeout, return less than vlen datagrams */
2342a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_nsec == 0 && timeout->tv_sec == 0)
2343a2e27255SArnaldo Carvalho de Melo 				break;
2344a2e27255SArnaldo Carvalho de Melo 		}
2345a2e27255SArnaldo Carvalho de Melo 
2346a2e27255SArnaldo Carvalho de Melo 		/* Out of band data, return right away */
2347a2e27255SArnaldo Carvalho de Melo 		if (msg_sys.msg_flags & MSG_OOB)
2348a2e27255SArnaldo Carvalho de Melo 			break;
2349a78cb84cSEric Dumazet 		cond_resched();
2350a2e27255SArnaldo Carvalho de Melo 	}
2351a2e27255SArnaldo Carvalho de Melo 
2352a2e27255SArnaldo Carvalho de Melo 	if (err == 0)
235334b88a68SArnaldo Carvalho de Melo 		goto out_put;
2354a2e27255SArnaldo Carvalho de Melo 
235534b88a68SArnaldo Carvalho de Melo 	if (datagrams == 0) {
235634b88a68SArnaldo Carvalho de Melo 		datagrams = err;
235734b88a68SArnaldo Carvalho de Melo 		goto out_put;
235834b88a68SArnaldo Carvalho de Melo 	}
235934b88a68SArnaldo Carvalho de Melo 
2360a2e27255SArnaldo Carvalho de Melo 	/*
2361a2e27255SArnaldo Carvalho de Melo 	 * We may return less entries than requested (vlen) if the
2362a2e27255SArnaldo Carvalho de Melo 	 * sock is non block and there aren't enough datagrams...
2363a2e27255SArnaldo Carvalho de Melo 	 */
2364a2e27255SArnaldo Carvalho de Melo 	if (err != -EAGAIN) {
2365a2e27255SArnaldo Carvalho de Melo 		/*
2366a2e27255SArnaldo Carvalho de Melo 		 * ... or  if recvmsg returns an error after we
2367a2e27255SArnaldo Carvalho de Melo 		 * received some datagrams, where we record the
2368a2e27255SArnaldo Carvalho de Melo 		 * error to return on the next call or if the
2369a2e27255SArnaldo Carvalho de Melo 		 * app asks about it using getsockopt(SO_ERROR).
2370a2e27255SArnaldo Carvalho de Melo 		 */
2371a2e27255SArnaldo Carvalho de Melo 		sock->sk->sk_err = -err;
2372a2e27255SArnaldo Carvalho de Melo 	}
237334b88a68SArnaldo Carvalho de Melo out_put:
237434b88a68SArnaldo Carvalho de Melo 	fput_light(sock->file, fput_needed);
2375a2e27255SArnaldo Carvalho de Melo 
2376a2e27255SArnaldo Carvalho de Melo 	return datagrams;
2377a2e27255SArnaldo Carvalho de Melo }
2378a2e27255SArnaldo Carvalho de Melo 
2379a2e27255SArnaldo Carvalho de Melo SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
2380a2e27255SArnaldo Carvalho de Melo 		unsigned int, vlen, unsigned int, flags,
2381a2e27255SArnaldo Carvalho de Melo 		struct timespec __user *, timeout)
2382a2e27255SArnaldo Carvalho de Melo {
2383a2e27255SArnaldo Carvalho de Melo 	int datagrams;
2384a2e27255SArnaldo Carvalho de Melo 	struct timespec timeout_sys;
2385a2e27255SArnaldo Carvalho de Melo 
23861be374a0SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
23871be374a0SAndy Lutomirski 		return -EINVAL;
23881be374a0SAndy Lutomirski 
2389a2e27255SArnaldo Carvalho de Melo 	if (!timeout)
2390a2e27255SArnaldo Carvalho de Melo 		return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL);
2391a2e27255SArnaldo Carvalho de Melo 
2392a2e27255SArnaldo Carvalho de Melo 	if (copy_from_user(&timeout_sys, timeout, sizeof(timeout_sys)))
2393a2e27255SArnaldo Carvalho de Melo 		return -EFAULT;
2394a2e27255SArnaldo Carvalho de Melo 
2395a2e27255SArnaldo Carvalho de Melo 	datagrams = __sys_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys);
2396a2e27255SArnaldo Carvalho de Melo 
2397a2e27255SArnaldo Carvalho de Melo 	if (datagrams > 0 &&
2398a2e27255SArnaldo Carvalho de Melo 	    copy_to_user(timeout, &timeout_sys, sizeof(timeout_sys)))
2399a2e27255SArnaldo Carvalho de Melo 		datagrams = -EFAULT;
2400a2e27255SArnaldo Carvalho de Melo 
2401a2e27255SArnaldo Carvalho de Melo 	return datagrams;
2402a2e27255SArnaldo Carvalho de Melo }
2403a2e27255SArnaldo Carvalho de Melo 
2404a2e27255SArnaldo Carvalho de Melo #ifdef __ARCH_WANT_SYS_SOCKETCALL
24051da177e4SLinus Torvalds /* Argument list sizes for sys_socketcall */
24061da177e4SLinus Torvalds #define AL(x) ((x) * sizeof(unsigned long))
2407228e548eSAnton Blanchard static const unsigned char nargs[21] = {
240889bddce5SStephen Hemminger 	AL(0), AL(3), AL(3), AL(3), AL(2), AL(3),
24091da177e4SLinus Torvalds 	AL(3), AL(3), AL(4), AL(4), AL(4), AL(6),
2410aaca0bdcSUlrich Drepper 	AL(6), AL(2), AL(5), AL(5), AL(3), AL(3),
2411228e548eSAnton Blanchard 	AL(4), AL(5), AL(4)
241289bddce5SStephen Hemminger };
241389bddce5SStephen Hemminger 
24141da177e4SLinus Torvalds #undef AL
24151da177e4SLinus Torvalds 
24161da177e4SLinus Torvalds /*
24171da177e4SLinus Torvalds  *	System call vectors.
24181da177e4SLinus Torvalds  *
24191da177e4SLinus Torvalds  *	Argument checking cleaned up. Saved 20% in size.
24201da177e4SLinus Torvalds  *  This function doesn't need to set the kernel lock because
24211da177e4SLinus Torvalds  *  it is set by the callees.
24221da177e4SLinus Torvalds  */
24231da177e4SLinus Torvalds 
24243e0fa65fSHeiko Carstens SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
24251da177e4SLinus Torvalds {
24262950fa9dSChen Gang 	unsigned long a[AUDITSC_ARGS];
24271da177e4SLinus Torvalds 	unsigned long a0, a1;
24281da177e4SLinus Torvalds 	int err;
242947379052SArjan van de Ven 	unsigned int len;
24301da177e4SLinus Torvalds 
2431228e548eSAnton Blanchard 	if (call < 1 || call > SYS_SENDMMSG)
24321da177e4SLinus Torvalds 		return -EINVAL;
24331da177e4SLinus Torvalds 
243447379052SArjan van de Ven 	len = nargs[call];
243547379052SArjan van de Ven 	if (len > sizeof(a))
243647379052SArjan van de Ven 		return -EINVAL;
243747379052SArjan van de Ven 
24381da177e4SLinus Torvalds 	/* copy_from_user should be SMP safe. */
243947379052SArjan van de Ven 	if (copy_from_user(a, args, len))
24401da177e4SLinus Torvalds 		return -EFAULT;
24411da177e4SLinus Torvalds 
24422950fa9dSChen Gang 	err = audit_socketcall(nargs[call] / sizeof(unsigned long), a);
24432950fa9dSChen Gang 	if (err)
24442950fa9dSChen Gang 		return err;
24453ec3b2fbSDavid Woodhouse 
24461da177e4SLinus Torvalds 	a0 = a[0];
24471da177e4SLinus Torvalds 	a1 = a[1];
24481da177e4SLinus Torvalds 
244989bddce5SStephen Hemminger 	switch (call) {
24501da177e4SLinus Torvalds 	case SYS_SOCKET:
24511da177e4SLinus Torvalds 		err = sys_socket(a0, a1, a[2]);
24521da177e4SLinus Torvalds 		break;
24531da177e4SLinus Torvalds 	case SYS_BIND:
24541da177e4SLinus Torvalds 		err = sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
24551da177e4SLinus Torvalds 		break;
24561da177e4SLinus Torvalds 	case SYS_CONNECT:
24571da177e4SLinus Torvalds 		err = sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
24581da177e4SLinus Torvalds 		break;
24591da177e4SLinus Torvalds 	case SYS_LISTEN:
24601da177e4SLinus Torvalds 		err = sys_listen(a0, a1);
24611da177e4SLinus Torvalds 		break;
24621da177e4SLinus Torvalds 	case SYS_ACCEPT:
2463de11defeSUlrich Drepper 		err = sys_accept4(a0, (struct sockaddr __user *)a1,
2464aaca0bdcSUlrich Drepper 				  (int __user *)a[2], 0);
24651da177e4SLinus Torvalds 		break;
24661da177e4SLinus Torvalds 	case SYS_GETSOCKNAME:
246789bddce5SStephen Hemminger 		err =
246889bddce5SStephen Hemminger 		    sys_getsockname(a0, (struct sockaddr __user *)a1,
246989bddce5SStephen Hemminger 				    (int __user *)a[2]);
24701da177e4SLinus Torvalds 		break;
24711da177e4SLinus Torvalds 	case SYS_GETPEERNAME:
247289bddce5SStephen Hemminger 		err =
247389bddce5SStephen Hemminger 		    sys_getpeername(a0, (struct sockaddr __user *)a1,
247489bddce5SStephen Hemminger 				    (int __user *)a[2]);
24751da177e4SLinus Torvalds 		break;
24761da177e4SLinus Torvalds 	case SYS_SOCKETPAIR:
24771da177e4SLinus Torvalds 		err = sys_socketpair(a0, a1, a[2], (int __user *)a[3]);
24781da177e4SLinus Torvalds 		break;
24791da177e4SLinus Torvalds 	case SYS_SEND:
24801da177e4SLinus Torvalds 		err = sys_send(a0, (void __user *)a1, a[2], a[3]);
24811da177e4SLinus Torvalds 		break;
24821da177e4SLinus Torvalds 	case SYS_SENDTO:
24831da177e4SLinus Torvalds 		err = sys_sendto(a0, (void __user *)a1, a[2], a[3],
24841da177e4SLinus Torvalds 				 (struct sockaddr __user *)a[4], a[5]);
24851da177e4SLinus Torvalds 		break;
24861da177e4SLinus Torvalds 	case SYS_RECV:
24871da177e4SLinus Torvalds 		err = sys_recv(a0, (void __user *)a1, a[2], a[3]);
24881da177e4SLinus Torvalds 		break;
24891da177e4SLinus Torvalds 	case SYS_RECVFROM:
24901da177e4SLinus Torvalds 		err = sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
249189bddce5SStephen Hemminger 				   (struct sockaddr __user *)a[4],
249289bddce5SStephen Hemminger 				   (int __user *)a[5]);
24931da177e4SLinus Torvalds 		break;
24941da177e4SLinus Torvalds 	case SYS_SHUTDOWN:
24951da177e4SLinus Torvalds 		err = sys_shutdown(a0, a1);
24961da177e4SLinus Torvalds 		break;
24971da177e4SLinus Torvalds 	case SYS_SETSOCKOPT:
24981da177e4SLinus Torvalds 		err = sys_setsockopt(a0, a1, a[2], (char __user *)a[3], a[4]);
24991da177e4SLinus Torvalds 		break;
25001da177e4SLinus Torvalds 	case SYS_GETSOCKOPT:
250189bddce5SStephen Hemminger 		err =
250289bddce5SStephen Hemminger 		    sys_getsockopt(a0, a1, a[2], (char __user *)a[3],
250389bddce5SStephen Hemminger 				   (int __user *)a[4]);
25041da177e4SLinus Torvalds 		break;
25051da177e4SLinus Torvalds 	case SYS_SENDMSG:
2506666547ffSAl Viro 		err = sys_sendmsg(a0, (struct user_msghdr __user *)a1, a[2]);
25071da177e4SLinus Torvalds 		break;
2508228e548eSAnton Blanchard 	case SYS_SENDMMSG:
2509228e548eSAnton Blanchard 		err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]);
2510228e548eSAnton Blanchard 		break;
25111da177e4SLinus Torvalds 	case SYS_RECVMSG:
2512666547ffSAl Viro 		err = sys_recvmsg(a0, (struct user_msghdr __user *)a1, a[2]);
25131da177e4SLinus Torvalds 		break;
2514a2e27255SArnaldo Carvalho de Melo 	case SYS_RECVMMSG:
2515a2e27255SArnaldo Carvalho de Melo 		err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3],
2516a2e27255SArnaldo Carvalho de Melo 				   (struct timespec __user *)a[4]);
2517a2e27255SArnaldo Carvalho de Melo 		break;
2518de11defeSUlrich Drepper 	case SYS_ACCEPT4:
2519de11defeSUlrich Drepper 		err = sys_accept4(a0, (struct sockaddr __user *)a1,
2520de11defeSUlrich Drepper 				  (int __user *)a[2], a[3]);
2521aaca0bdcSUlrich Drepper 		break;
25221da177e4SLinus Torvalds 	default:
25231da177e4SLinus Torvalds 		err = -EINVAL;
25241da177e4SLinus Torvalds 		break;
25251da177e4SLinus Torvalds 	}
25261da177e4SLinus Torvalds 	return err;
25271da177e4SLinus Torvalds }
25281da177e4SLinus Torvalds 
25291da177e4SLinus Torvalds #endif				/* __ARCH_WANT_SYS_SOCKETCALL */
25301da177e4SLinus Torvalds 
253155737fdaSStephen Hemminger /**
253255737fdaSStephen Hemminger  *	sock_register - add a socket protocol handler
253355737fdaSStephen Hemminger  *	@ops: description of protocol
253455737fdaSStephen Hemminger  *
25351da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
25361da177e4SLinus Torvalds  *	advertise its address family, and have it linked into the
2537e793c0f7SMasanari Iida  *	socket interface. The value ops->family corresponds to the
253855737fdaSStephen Hemminger  *	socket system call protocol family.
25391da177e4SLinus Torvalds  */
2540f0fd27d4SStephen Hemminger int sock_register(const struct net_proto_family *ops)
25411da177e4SLinus Torvalds {
25421da177e4SLinus Torvalds 	int err;
25431da177e4SLinus Torvalds 
25441da177e4SLinus Torvalds 	if (ops->family >= NPROTO) {
25453410f22eSYang Yingliang 		pr_crit("protocol %d >= NPROTO(%d)\n", ops->family, NPROTO);
25461da177e4SLinus Torvalds 		return -ENOBUFS;
25471da177e4SLinus Torvalds 	}
254855737fdaSStephen Hemminger 
254955737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2550190683a9SEric Dumazet 	if (rcu_dereference_protected(net_families[ops->family],
2551190683a9SEric Dumazet 				      lockdep_is_held(&net_family_lock)))
25521da177e4SLinus Torvalds 		err = -EEXIST;
255355737fdaSStephen Hemminger 	else {
2554cf778b00SEric Dumazet 		rcu_assign_pointer(net_families[ops->family], ops);
25551da177e4SLinus Torvalds 		err = 0;
25561da177e4SLinus Torvalds 	}
255755737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
255855737fdaSStephen Hemminger 
25593410f22eSYang Yingliang 	pr_info("NET: Registered protocol family %d\n", ops->family);
25601da177e4SLinus Torvalds 	return err;
25611da177e4SLinus Torvalds }
2562c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_register);
25631da177e4SLinus Torvalds 
256455737fdaSStephen Hemminger /**
256555737fdaSStephen Hemminger  *	sock_unregister - remove a protocol handler
256655737fdaSStephen Hemminger  *	@family: protocol family to remove
256755737fdaSStephen Hemminger  *
25681da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
25691da177e4SLinus Torvalds  *	remove its address family, and have it unlinked from the
257055737fdaSStephen Hemminger  *	new socket creation.
257155737fdaSStephen Hemminger  *
257255737fdaSStephen Hemminger  *	If protocol handler is a module, then it can use module reference
257355737fdaSStephen Hemminger  *	counts to protect against new references. If protocol handler is not
257455737fdaSStephen Hemminger  *	a module then it needs to provide its own protection in
257555737fdaSStephen Hemminger  *	the ops->create routine.
25761da177e4SLinus Torvalds  */
2577f0fd27d4SStephen Hemminger void sock_unregister(int family)
25781da177e4SLinus Torvalds {
2579f0fd27d4SStephen Hemminger 	BUG_ON(family < 0 || family >= NPROTO);
25801da177e4SLinus Torvalds 
258155737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2582a9b3cd7fSStephen Hemminger 	RCU_INIT_POINTER(net_families[family], NULL);
258355737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
258455737fdaSStephen Hemminger 
258555737fdaSStephen Hemminger 	synchronize_rcu();
258655737fdaSStephen Hemminger 
25873410f22eSYang Yingliang 	pr_info("NET: Unregistered protocol family %d\n", family);
25881da177e4SLinus Torvalds }
2589c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_unregister);
25901da177e4SLinus Torvalds 
259177d76ea3SAndi Kleen static int __init sock_init(void)
25921da177e4SLinus Torvalds {
2593b3e19d92SNick Piggin 	int err;
25942ca794e5SEric W. Biederman 	/*
25952ca794e5SEric W. Biederman 	 *      Initialize the network sysctl infrastructure.
25962ca794e5SEric W. Biederman 	 */
25972ca794e5SEric W. Biederman 	err = net_sysctl_init();
25982ca794e5SEric W. Biederman 	if (err)
25992ca794e5SEric W. Biederman 		goto out;
2600b3e19d92SNick Piggin 
26011da177e4SLinus Torvalds 	/*
26021da177e4SLinus Torvalds 	 *      Initialize skbuff SLAB cache
26031da177e4SLinus Torvalds 	 */
26041da177e4SLinus Torvalds 	skb_init();
26051da177e4SLinus Torvalds 
26061da177e4SLinus Torvalds 	/*
26071da177e4SLinus Torvalds 	 *      Initialize the protocols module.
26081da177e4SLinus Torvalds 	 */
26091da177e4SLinus Torvalds 
26101da177e4SLinus Torvalds 	init_inodecache();
2611b3e19d92SNick Piggin 
2612b3e19d92SNick Piggin 	err = register_filesystem(&sock_fs_type);
2613b3e19d92SNick Piggin 	if (err)
2614b3e19d92SNick Piggin 		goto out_fs;
26151da177e4SLinus Torvalds 	sock_mnt = kern_mount(&sock_fs_type);
2616b3e19d92SNick Piggin 	if (IS_ERR(sock_mnt)) {
2617b3e19d92SNick Piggin 		err = PTR_ERR(sock_mnt);
2618b3e19d92SNick Piggin 		goto out_mount;
2619b3e19d92SNick Piggin 	}
262077d76ea3SAndi Kleen 
262177d76ea3SAndi Kleen 	/* The real protocol initialization is performed in later initcalls.
26221da177e4SLinus Torvalds 	 */
26231da177e4SLinus Torvalds 
26241da177e4SLinus Torvalds #ifdef CONFIG_NETFILTER
26256d11cfdbSPablo Neira Ayuso 	err = netfilter_init();
26266d11cfdbSPablo Neira Ayuso 	if (err)
26276d11cfdbSPablo Neira Ayuso 		goto out;
26281da177e4SLinus Torvalds #endif
2629cbeb321aSDavid S. Miller 
2630408eccceSDaniel Borkmann 	ptp_classifier_init();
2631c1f19b51SRichard Cochran 
2632b3e19d92SNick Piggin out:
2633b3e19d92SNick Piggin 	return err;
2634b3e19d92SNick Piggin 
2635b3e19d92SNick Piggin out_mount:
2636b3e19d92SNick Piggin 	unregister_filesystem(&sock_fs_type);
2637b3e19d92SNick Piggin out_fs:
2638b3e19d92SNick Piggin 	goto out;
26391da177e4SLinus Torvalds }
26401da177e4SLinus Torvalds 
264177d76ea3SAndi Kleen core_initcall(sock_init);	/* early initcall */
264277d76ea3SAndi Kleen 
26431da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS
26441da177e4SLinus Torvalds void socket_seq_show(struct seq_file *seq)
26451da177e4SLinus Torvalds {
2646648845abSTonghao Zhang 	seq_printf(seq, "sockets: used %d\n",
2647648845abSTonghao Zhang 		   sock_inuse_get(seq->private));
26481da177e4SLinus Torvalds }
26491da177e4SLinus Torvalds #endif				/* CONFIG_PROC_FS */
26501da177e4SLinus Torvalds 
265189bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
26526b96018bSArnd Bergmann static int do_siocgstamp(struct net *net, struct socket *sock,
2653644595f8SH. Peter Anvin 			 unsigned int cmd, void __user *up)
26547a229387SArnd Bergmann {
26557a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
26567a229387SArnd Bergmann 	struct timeval ktv;
26577a229387SArnd Bergmann 	int err;
26587a229387SArnd Bergmann 
26597a229387SArnd Bergmann 	set_fs(KERNEL_DS);
26606b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv);
26617a229387SArnd Bergmann 	set_fs(old_fs);
2662644595f8SH. Peter Anvin 	if (!err)
2663ed6fe9d6SMikulas Patocka 		err = compat_put_timeval(&ktv, up);
2664644595f8SH. Peter Anvin 
26657a229387SArnd Bergmann 	return err;
26667a229387SArnd Bergmann }
26677a229387SArnd Bergmann 
26686b96018bSArnd Bergmann static int do_siocgstampns(struct net *net, struct socket *sock,
2669644595f8SH. Peter Anvin 			   unsigned int cmd, void __user *up)
26707a229387SArnd Bergmann {
26717a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
26727a229387SArnd Bergmann 	struct timespec kts;
26737a229387SArnd Bergmann 	int err;
26747a229387SArnd Bergmann 
26757a229387SArnd Bergmann 	set_fs(KERNEL_DS);
26766b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts);
26777a229387SArnd Bergmann 	set_fs(old_fs);
2678644595f8SH. Peter Anvin 	if (!err)
2679ed6fe9d6SMikulas Patocka 		err = compat_put_timespec(&kts, up);
2680644595f8SH. Peter Anvin 
26817a229387SArnd Bergmann 	return err;
26827a229387SArnd Bergmann }
26837a229387SArnd Bergmann 
268436fd633eSAl Viro static int compat_dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32)
26857a229387SArnd Bergmann {
26866b96018bSArnd Bergmann 	struct compat_ifconf ifc32;
26877a229387SArnd Bergmann 	struct ifconf ifc;
26887a229387SArnd Bergmann 	int err;
26897a229387SArnd Bergmann 
26906b96018bSArnd Bergmann 	if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf)))
26917a229387SArnd Bergmann 		return -EFAULT;
26927a229387SArnd Bergmann 
269336fd633eSAl Viro 	ifc.ifc_len = ifc32.ifc_len;
269436fd633eSAl Viro 	ifc.ifc_req = compat_ptr(ifc32.ifcbuf);
26957a229387SArnd Bergmann 
269636fd633eSAl Viro 	rtnl_lock();
269736fd633eSAl Viro 	err = dev_ifconf(net, &ifc, sizeof(struct compat_ifreq));
269836fd633eSAl Viro 	rtnl_unlock();
26997a229387SArnd Bergmann 	if (err)
27007a229387SArnd Bergmann 		return err;
27017a229387SArnd Bergmann 
270236fd633eSAl Viro 	ifc32.ifc_len = ifc.ifc_len;
27036b96018bSArnd Bergmann 	if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf)))
27047a229387SArnd Bergmann 		return -EFAULT;
27057a229387SArnd Bergmann 
27067a229387SArnd Bergmann 	return 0;
27077a229387SArnd Bergmann }
27087a229387SArnd Bergmann 
27096b96018bSArnd Bergmann static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
27107a229387SArnd Bergmann {
27113a7da39dSBen Hutchings 	struct compat_ethtool_rxnfc __user *compat_rxnfc;
27123a7da39dSBen Hutchings 	bool convert_in = false, convert_out = false;
271344c02a2cSAl Viro 	size_t buf_size = 0;
271444c02a2cSAl Viro 	struct ethtool_rxnfc __user *rxnfc = NULL;
271544c02a2cSAl Viro 	struct ifreq ifr;
27163a7da39dSBen Hutchings 	u32 rule_cnt = 0, actual_rule_cnt;
27173a7da39dSBen Hutchings 	u32 ethcmd;
27187a229387SArnd Bergmann 	u32 data;
27193a7da39dSBen Hutchings 	int ret;
27207a229387SArnd Bergmann 
27217a229387SArnd Bergmann 	if (get_user(data, &ifr32->ifr_ifru.ifru_data))
27227a229387SArnd Bergmann 		return -EFAULT;
27237a229387SArnd Bergmann 
27243a7da39dSBen Hutchings 	compat_rxnfc = compat_ptr(data);
27253a7da39dSBen Hutchings 
27263a7da39dSBen Hutchings 	if (get_user(ethcmd, &compat_rxnfc->cmd))
27277a229387SArnd Bergmann 		return -EFAULT;
27287a229387SArnd Bergmann 
27293a7da39dSBen Hutchings 	/* Most ethtool structures are defined without padding.
27303a7da39dSBen Hutchings 	 * Unfortunately struct ethtool_rxnfc is an exception.
27313a7da39dSBen Hutchings 	 */
27323a7da39dSBen Hutchings 	switch (ethcmd) {
27333a7da39dSBen Hutchings 	default:
27343a7da39dSBen Hutchings 		break;
27353a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLALL:
27363a7da39dSBen Hutchings 		/* Buffer size is variable */
27373a7da39dSBen Hutchings 		if (get_user(rule_cnt, &compat_rxnfc->rule_cnt))
27383a7da39dSBen Hutchings 			return -EFAULT;
27393a7da39dSBen Hutchings 		if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32))
27403a7da39dSBen Hutchings 			return -ENOMEM;
27413a7da39dSBen Hutchings 		buf_size += rule_cnt * sizeof(u32);
27423a7da39dSBen Hutchings 		/* fall through */
27433a7da39dSBen Hutchings 	case ETHTOOL_GRXRINGS:
27443a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLCNT:
27453a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRULE:
274655664f32SBen Hutchings 	case ETHTOOL_SRXCLSRLINS:
27473a7da39dSBen Hutchings 		convert_out = true;
27483a7da39dSBen Hutchings 		/* fall through */
27493a7da39dSBen Hutchings 	case ETHTOOL_SRXCLSRLDEL:
27503a7da39dSBen Hutchings 		buf_size += sizeof(struct ethtool_rxnfc);
27513a7da39dSBen Hutchings 		convert_in = true;
275244c02a2cSAl Viro 		rxnfc = compat_alloc_user_space(buf_size);
27533a7da39dSBen Hutchings 		break;
27543a7da39dSBen Hutchings 	}
27553a7da39dSBen Hutchings 
275644c02a2cSAl Viro 	if (copy_from_user(&ifr.ifr_name, &ifr32->ifr_name, IFNAMSIZ))
27573a7da39dSBen Hutchings 		return -EFAULT;
27583a7da39dSBen Hutchings 
275944c02a2cSAl Viro 	ifr.ifr_data = convert_in ? rxnfc : (void __user *)compat_rxnfc;
27603a7da39dSBen Hutchings 
27613a7da39dSBen Hutchings 	if (convert_in) {
2762127fe533SAlexander Duyck 		/* We expect there to be holes between fs.m_ext and
27633a7da39dSBen Hutchings 		 * fs.ring_cookie and at the end of fs, but nowhere else.
27643a7da39dSBen Hutchings 		 */
2765127fe533SAlexander Duyck 		BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_ext) +
2766127fe533SAlexander Duyck 			     sizeof(compat_rxnfc->fs.m_ext) !=
2767127fe533SAlexander Duyck 			     offsetof(struct ethtool_rxnfc, fs.m_ext) +
2768127fe533SAlexander Duyck 			     sizeof(rxnfc->fs.m_ext));
27693a7da39dSBen Hutchings 		BUILD_BUG_ON(
27703a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.location) -
27713a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) !=
27723a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.location) -
27733a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.ring_cookie));
27743a7da39dSBen Hutchings 
27753a7da39dSBen Hutchings 		if (copy_in_user(rxnfc, compat_rxnfc,
2776954b1244SStephen Hemminger 				 (void __user *)(&rxnfc->fs.m_ext + 1) -
2777954b1244SStephen Hemminger 				 (void __user *)rxnfc) ||
27783a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->fs.ring_cookie,
27793a7da39dSBen Hutchings 				 &compat_rxnfc->fs.ring_cookie,
2780954b1244SStephen Hemminger 				 (void __user *)(&rxnfc->fs.location + 1) -
2781954b1244SStephen Hemminger 				 (void __user *)&rxnfc->fs.ring_cookie) ||
27823a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt,
27833a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
27843a7da39dSBen Hutchings 			return -EFAULT;
27853a7da39dSBen Hutchings 	}
27863a7da39dSBen Hutchings 
278744c02a2cSAl Viro 	ret = dev_ioctl(net, SIOCETHTOOL, &ifr, NULL);
27883a7da39dSBen Hutchings 	if (ret)
27893a7da39dSBen Hutchings 		return ret;
27903a7da39dSBen Hutchings 
27913a7da39dSBen Hutchings 	if (convert_out) {
27923a7da39dSBen Hutchings 		if (copy_in_user(compat_rxnfc, rxnfc,
2793954b1244SStephen Hemminger 				 (const void __user *)(&rxnfc->fs.m_ext + 1) -
2794954b1244SStephen Hemminger 				 (const void __user *)rxnfc) ||
27953a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->fs.ring_cookie,
27963a7da39dSBen Hutchings 				 &rxnfc->fs.ring_cookie,
2797954b1244SStephen Hemminger 				 (const void __user *)(&rxnfc->fs.location + 1) -
2798954b1244SStephen Hemminger 				 (const void __user *)&rxnfc->fs.ring_cookie) ||
27993a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt,
28003a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
28013a7da39dSBen Hutchings 			return -EFAULT;
28023a7da39dSBen Hutchings 
28033a7da39dSBen Hutchings 		if (ethcmd == ETHTOOL_GRXCLSRLALL) {
28043a7da39dSBen Hutchings 			/* As an optimisation, we only copy the actual
28053a7da39dSBen Hutchings 			 * number of rules that the underlying
28063a7da39dSBen Hutchings 			 * function returned.  Since Mallory might
28073a7da39dSBen Hutchings 			 * change the rule count in user memory, we
28083a7da39dSBen Hutchings 			 * check that it is less than the rule count
28093a7da39dSBen Hutchings 			 * originally given (as the user buffer size),
28103a7da39dSBen Hutchings 			 * which has been range-checked.
28113a7da39dSBen Hutchings 			 */
28123a7da39dSBen Hutchings 			if (get_user(actual_rule_cnt, &rxnfc->rule_cnt))
28133a7da39dSBen Hutchings 				return -EFAULT;
28143a7da39dSBen Hutchings 			if (actual_rule_cnt < rule_cnt)
28153a7da39dSBen Hutchings 				rule_cnt = actual_rule_cnt;
28163a7da39dSBen Hutchings 			if (copy_in_user(&compat_rxnfc->rule_locs[0],
28173a7da39dSBen Hutchings 					 &rxnfc->rule_locs[0],
28183a7da39dSBen Hutchings 					 rule_cnt * sizeof(u32)))
28193a7da39dSBen Hutchings 				return -EFAULT;
28203a7da39dSBen Hutchings 		}
28213a7da39dSBen Hutchings 	}
28223a7da39dSBen Hutchings 
28233a7da39dSBen Hutchings 	return 0;
28247a229387SArnd Bergmann }
28257a229387SArnd Bergmann 
28267a50a240SArnd Bergmann static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32)
28277a50a240SArnd Bergmann {
28287a50a240SArnd Bergmann 	compat_uptr_t uptr32;
282944c02a2cSAl Viro 	struct ifreq ifr;
283044c02a2cSAl Viro 	void __user *saved;
283144c02a2cSAl Viro 	int err;
28327a50a240SArnd Bergmann 
283344c02a2cSAl Viro 	if (copy_from_user(&ifr, uifr32, sizeof(struct compat_ifreq)))
28347a50a240SArnd Bergmann 		return -EFAULT;
28357a50a240SArnd Bergmann 
28367a50a240SArnd Bergmann 	if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu))
28377a50a240SArnd Bergmann 		return -EFAULT;
28387a50a240SArnd Bergmann 
283944c02a2cSAl Viro 	saved = ifr.ifr_settings.ifs_ifsu.raw_hdlc;
284044c02a2cSAl Viro 	ifr.ifr_settings.ifs_ifsu.raw_hdlc = compat_ptr(uptr32);
28417a50a240SArnd Bergmann 
284244c02a2cSAl Viro 	err = dev_ioctl(net, SIOCWANDEV, &ifr, NULL);
284344c02a2cSAl Viro 	if (!err) {
284444c02a2cSAl Viro 		ifr.ifr_settings.ifs_ifsu.raw_hdlc = saved;
284544c02a2cSAl Viro 		if (copy_to_user(uifr32, &ifr, sizeof(struct compat_ifreq)))
284644c02a2cSAl Viro 			err = -EFAULT;
28477a50a240SArnd Bergmann 	}
28487a229387SArnd Bergmann 	return err;
28497a229387SArnd Bergmann }
28507a229387SArnd Bergmann 
2851590d4693SBen Hutchings /* Handle ioctls that use ifreq::ifr_data and just need struct ifreq converted */
2852590d4693SBen Hutchings static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd,
28536b96018bSArnd Bergmann 				 struct compat_ifreq __user *u_ifreq32)
28547a229387SArnd Bergmann {
285544c02a2cSAl Viro 	struct ifreq ifreq;
28567a229387SArnd Bergmann 	u32 data32;
28577a229387SArnd Bergmann 
285844c02a2cSAl Viro 	if (copy_from_user(ifreq.ifr_name, u_ifreq32->ifr_name, IFNAMSIZ))
28597a229387SArnd Bergmann 		return -EFAULT;
286044c02a2cSAl Viro 	if (get_user(data32, &u_ifreq32->ifr_data))
28617a229387SArnd Bergmann 		return -EFAULT;
286244c02a2cSAl Viro 	ifreq.ifr_data = compat_ptr(data32);
28637a229387SArnd Bergmann 
286444c02a2cSAl Viro 	return dev_ioctl(net, cmd, &ifreq, NULL);
2865a2116ed2SArnd Bergmann }
2866a2116ed2SArnd Bergmann 
2867a2116ed2SArnd Bergmann static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
2868a2116ed2SArnd Bergmann 			struct compat_ifreq __user *uifr32)
2869a2116ed2SArnd Bergmann {
2870a2116ed2SArnd Bergmann 	struct ifreq ifr;
2871a2116ed2SArnd Bergmann 	struct compat_ifmap __user *uifmap32;
2872a2116ed2SArnd Bergmann 	int err;
2873a2116ed2SArnd Bergmann 
2874a2116ed2SArnd Bergmann 	uifmap32 = &uifr32->ifr_ifru.ifru_map;
2875a2116ed2SArnd Bergmann 	err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name));
28763ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
28773ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
28783ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
28793ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.irq, &uifmap32->irq);
28803ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.dma, &uifmap32->dma);
28813ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.port, &uifmap32->port);
2882a2116ed2SArnd Bergmann 	if (err)
2883a2116ed2SArnd Bergmann 		return -EFAULT;
2884a2116ed2SArnd Bergmann 
288544c02a2cSAl Viro 	err = dev_ioctl(net, cmd, &ifr, NULL);
2886a2116ed2SArnd Bergmann 
2887a2116ed2SArnd Bergmann 	if (cmd == SIOCGIFMAP && !err) {
28887a229387SArnd Bergmann 		err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name));
28893ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
28903ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
28913ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
28923ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.irq, &uifmap32->irq);
28933ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.dma, &uifmap32->dma);
28943ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.port, &uifmap32->port);
28957a229387SArnd Bergmann 		if (err)
28967a229387SArnd Bergmann 			err = -EFAULT;
28977a229387SArnd Bergmann 	}
28987a229387SArnd Bergmann 	return err;
28997a229387SArnd Bergmann }
29007a229387SArnd Bergmann 
29017a229387SArnd Bergmann struct rtentry32 {
29027a229387SArnd Bergmann 	u32		rt_pad1;
29037a229387SArnd Bergmann 	struct sockaddr rt_dst;         /* target address               */
29047a229387SArnd Bergmann 	struct sockaddr rt_gateway;     /* gateway addr (RTF_GATEWAY)   */
29057a229387SArnd Bergmann 	struct sockaddr rt_genmask;     /* target network mask (IP)     */
29067a229387SArnd Bergmann 	unsigned short	rt_flags;
29077a229387SArnd Bergmann 	short		rt_pad2;
29087a229387SArnd Bergmann 	u32		rt_pad3;
29097a229387SArnd Bergmann 	unsigned char	rt_tos;
29107a229387SArnd Bergmann 	unsigned char	rt_class;
29117a229387SArnd Bergmann 	short		rt_pad4;
29127a229387SArnd Bergmann 	short		rt_metric;      /* +1 for binary compatibility! */
29137a229387SArnd Bergmann 	/* char * */ u32 rt_dev;        /* forcing the device at add    */
29147a229387SArnd Bergmann 	u32		rt_mtu;         /* per route MTU/Window         */
29157a229387SArnd Bergmann 	u32		rt_window;      /* Window clamping              */
29167a229387SArnd Bergmann 	unsigned short  rt_irtt;        /* Initial RTT                  */
29177a229387SArnd Bergmann };
29187a229387SArnd Bergmann 
29197a229387SArnd Bergmann struct in6_rtmsg32 {
29207a229387SArnd Bergmann 	struct in6_addr		rtmsg_dst;
29217a229387SArnd Bergmann 	struct in6_addr		rtmsg_src;
29227a229387SArnd Bergmann 	struct in6_addr		rtmsg_gateway;
29237a229387SArnd Bergmann 	u32			rtmsg_type;
29247a229387SArnd Bergmann 	u16			rtmsg_dst_len;
29257a229387SArnd Bergmann 	u16			rtmsg_src_len;
29267a229387SArnd Bergmann 	u32			rtmsg_metric;
29277a229387SArnd Bergmann 	u32			rtmsg_info;
29287a229387SArnd Bergmann 	u32			rtmsg_flags;
29297a229387SArnd Bergmann 	s32			rtmsg_ifindex;
29307a229387SArnd Bergmann };
29317a229387SArnd Bergmann 
29326b96018bSArnd Bergmann static int routing_ioctl(struct net *net, struct socket *sock,
29336b96018bSArnd Bergmann 			 unsigned int cmd, void __user *argp)
29347a229387SArnd Bergmann {
29357a229387SArnd Bergmann 	int ret;
29367a229387SArnd Bergmann 	void *r = NULL;
29377a229387SArnd Bergmann 	struct in6_rtmsg r6;
29387a229387SArnd Bergmann 	struct rtentry r4;
29397a229387SArnd Bergmann 	char devname[16];
29407a229387SArnd Bergmann 	u32 rtdev;
29417a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
29427a229387SArnd Bergmann 
29436b96018bSArnd Bergmann 	if (sock && sock->sk && sock->sk->sk_family == AF_INET6) { /* ipv6 */
29446b96018bSArnd Bergmann 		struct in6_rtmsg32 __user *ur6 = argp;
29457a229387SArnd Bergmann 		ret = copy_from_user(&r6.rtmsg_dst, &(ur6->rtmsg_dst),
29467a229387SArnd Bergmann 			3 * sizeof(struct in6_addr));
29473ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_type, &(ur6->rtmsg_type));
29483ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len));
29493ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_src_len, &(ur6->rtmsg_src_len));
29503ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_metric, &(ur6->rtmsg_metric));
29513ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_info, &(ur6->rtmsg_info));
29523ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_flags, &(ur6->rtmsg_flags));
29533ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex));
29547a229387SArnd Bergmann 
29557a229387SArnd Bergmann 		r = (void *) &r6;
29567a229387SArnd Bergmann 	} else { /* ipv4 */
29576b96018bSArnd Bergmann 		struct rtentry32 __user *ur4 = argp;
29587a229387SArnd Bergmann 		ret = copy_from_user(&r4.rt_dst, &(ur4->rt_dst),
29597a229387SArnd Bergmann 					3 * sizeof(struct sockaddr));
29603ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_flags, &(ur4->rt_flags));
29613ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_metric, &(ur4->rt_metric));
29623ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_mtu, &(ur4->rt_mtu));
29633ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_window, &(ur4->rt_window));
29643ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_irtt, &(ur4->rt_irtt));
29653ddc5b46SMathieu Desnoyers 		ret |= get_user(rtdev, &(ur4->rt_dev));
29667a229387SArnd Bergmann 		if (rtdev) {
29677a229387SArnd Bergmann 			ret |= copy_from_user(devname, compat_ptr(rtdev), 15);
2968c3f52ae6Sstephen hemminger 			r4.rt_dev = (char __user __force *)devname;
2969c3f52ae6Sstephen hemminger 			devname[15] = 0;
29707a229387SArnd Bergmann 		} else
29717a229387SArnd Bergmann 			r4.rt_dev = NULL;
29727a229387SArnd Bergmann 
29737a229387SArnd Bergmann 		r = (void *) &r4;
29747a229387SArnd Bergmann 	}
29757a229387SArnd Bergmann 
29767a229387SArnd Bergmann 	if (ret) {
29777a229387SArnd Bergmann 		ret = -EFAULT;
29787a229387SArnd Bergmann 		goto out;
29797a229387SArnd Bergmann 	}
29807a229387SArnd Bergmann 
29817a229387SArnd Bergmann 	set_fs(KERNEL_DS);
29826b96018bSArnd Bergmann 	ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r);
29837a229387SArnd Bergmann 	set_fs(old_fs);
29847a229387SArnd Bergmann 
29857a229387SArnd Bergmann out:
29867a229387SArnd Bergmann 	return ret;
29877a229387SArnd Bergmann }
29887a229387SArnd Bergmann 
29897a229387SArnd Bergmann /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE
29907a229387SArnd Bergmann  * for some operations; this forces use of the newer bridge-utils that
299125985edcSLucas De Marchi  * use compatible ioctls
29927a229387SArnd Bergmann  */
29936b96018bSArnd Bergmann static int old_bridge_ioctl(compat_ulong_t __user *argp)
29947a229387SArnd Bergmann {
29956b96018bSArnd Bergmann 	compat_ulong_t tmp;
29967a229387SArnd Bergmann 
29976b96018bSArnd Bergmann 	if (get_user(tmp, argp))
29987a229387SArnd Bergmann 		return -EFAULT;
29997a229387SArnd Bergmann 	if (tmp == BRCTL_GET_VERSION)
30007a229387SArnd Bergmann 		return BRCTL_VERSION + 1;
30017a229387SArnd Bergmann 	return -EINVAL;
30027a229387SArnd Bergmann }
30037a229387SArnd Bergmann 
30046b96018bSArnd Bergmann static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
30056b96018bSArnd Bergmann 			 unsigned int cmd, unsigned long arg)
30066b96018bSArnd Bergmann {
30076b96018bSArnd Bergmann 	void __user *argp = compat_ptr(arg);
30086b96018bSArnd Bergmann 	struct sock *sk = sock->sk;
30096b96018bSArnd Bergmann 	struct net *net = sock_net(sk);
30107a229387SArnd Bergmann 
30116b96018bSArnd Bergmann 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
3012590d4693SBen Hutchings 		return compat_ifr_data_ioctl(net, cmd, argp);
30137a229387SArnd Bergmann 
30146b96018bSArnd Bergmann 	switch (cmd) {
30156b96018bSArnd Bergmann 	case SIOCSIFBR:
30166b96018bSArnd Bergmann 	case SIOCGIFBR:
30176b96018bSArnd Bergmann 		return old_bridge_ioctl(argp);
30186b96018bSArnd Bergmann 	case SIOCGIFCONF:
301936fd633eSAl Viro 		return compat_dev_ifconf(net, argp);
30206b96018bSArnd Bergmann 	case SIOCETHTOOL:
30216b96018bSArnd Bergmann 		return ethtool_ioctl(net, argp);
30227a50a240SArnd Bergmann 	case SIOCWANDEV:
30237a50a240SArnd Bergmann 		return compat_siocwandev(net, argp);
3024a2116ed2SArnd Bergmann 	case SIOCGIFMAP:
3025a2116ed2SArnd Bergmann 	case SIOCSIFMAP:
3026a2116ed2SArnd Bergmann 		return compat_sioc_ifmap(net, cmd, argp);
30276b96018bSArnd Bergmann 	case SIOCADDRT:
30286b96018bSArnd Bergmann 	case SIOCDELRT:
30296b96018bSArnd Bergmann 		return routing_ioctl(net, sock, cmd, argp);
30306b96018bSArnd Bergmann 	case SIOCGSTAMP:
30316b96018bSArnd Bergmann 		return do_siocgstamp(net, sock, cmd, argp);
30326b96018bSArnd Bergmann 	case SIOCGSTAMPNS:
30336b96018bSArnd Bergmann 		return do_siocgstampns(net, sock, cmd, argp);
3034590d4693SBen Hutchings 	case SIOCBONDSLAVEINFOQUERY:
3035590d4693SBen Hutchings 	case SIOCBONDINFOQUERY:
3036a2116ed2SArnd Bergmann 	case SIOCSHWTSTAMP:
3037fd468c74SBen Hutchings 	case SIOCGHWTSTAMP:
3038590d4693SBen Hutchings 		return compat_ifr_data_ioctl(net, cmd, argp);
30397a229387SArnd Bergmann 
30406b96018bSArnd Bergmann 	case FIOSETOWN:
30416b96018bSArnd Bergmann 	case SIOCSPGRP:
30426b96018bSArnd Bergmann 	case FIOGETOWN:
30436b96018bSArnd Bergmann 	case SIOCGPGRP:
30446b96018bSArnd Bergmann 	case SIOCBRADDBR:
30456b96018bSArnd Bergmann 	case SIOCBRDELBR:
30466b96018bSArnd Bergmann 	case SIOCGIFVLAN:
30476b96018bSArnd Bergmann 	case SIOCSIFVLAN:
30486b96018bSArnd Bergmann 	case SIOCADDDLCI:
30496b96018bSArnd Bergmann 	case SIOCDELDLCI:
3050c62cce2cSAndrey Vagin 	case SIOCGSKNS:
30516b96018bSArnd Bergmann 		return sock_ioctl(file, cmd, arg);
30526b96018bSArnd Bergmann 
30536b96018bSArnd Bergmann 	case SIOCGIFFLAGS:
30546b96018bSArnd Bergmann 	case SIOCSIFFLAGS:
30556b96018bSArnd Bergmann 	case SIOCGIFMETRIC:
30566b96018bSArnd Bergmann 	case SIOCSIFMETRIC:
30576b96018bSArnd Bergmann 	case SIOCGIFMTU:
30586b96018bSArnd Bergmann 	case SIOCSIFMTU:
30596b96018bSArnd Bergmann 	case SIOCGIFMEM:
30606b96018bSArnd Bergmann 	case SIOCSIFMEM:
30616b96018bSArnd Bergmann 	case SIOCGIFHWADDR:
30626b96018bSArnd Bergmann 	case SIOCSIFHWADDR:
30636b96018bSArnd Bergmann 	case SIOCADDMULTI:
30646b96018bSArnd Bergmann 	case SIOCDELMULTI:
30656b96018bSArnd Bergmann 	case SIOCGIFINDEX:
30666b96018bSArnd Bergmann 	case SIOCGIFADDR:
30676b96018bSArnd Bergmann 	case SIOCSIFADDR:
30686b96018bSArnd Bergmann 	case SIOCSIFHWBROADCAST:
30696b96018bSArnd Bergmann 	case SIOCDIFADDR:
30706b96018bSArnd Bergmann 	case SIOCGIFBRDADDR:
30716b96018bSArnd Bergmann 	case SIOCSIFBRDADDR:
30726b96018bSArnd Bergmann 	case SIOCGIFDSTADDR:
30736b96018bSArnd Bergmann 	case SIOCSIFDSTADDR:
30746b96018bSArnd Bergmann 	case SIOCGIFNETMASK:
30756b96018bSArnd Bergmann 	case SIOCSIFNETMASK:
30766b96018bSArnd Bergmann 	case SIOCSIFPFLAGS:
30776b96018bSArnd Bergmann 	case SIOCGIFPFLAGS:
30786b96018bSArnd Bergmann 	case SIOCGIFTXQLEN:
30796b96018bSArnd Bergmann 	case SIOCSIFTXQLEN:
30806b96018bSArnd Bergmann 	case SIOCBRADDIF:
30816b96018bSArnd Bergmann 	case SIOCBRDELIF:
30829177efd3SArnd Bergmann 	case SIOCSIFNAME:
30839177efd3SArnd Bergmann 	case SIOCGMIIPHY:
30849177efd3SArnd Bergmann 	case SIOCGMIIREG:
30859177efd3SArnd Bergmann 	case SIOCSMIIREG:
30866b96018bSArnd Bergmann 	case SIOCSARP:
30876b96018bSArnd Bergmann 	case SIOCGARP:
30886b96018bSArnd Bergmann 	case SIOCDARP:
30896b96018bSArnd Bergmann 	case SIOCATMARK:
3090f92d4fc9SAl Viro 	case SIOCBONDENSLAVE:
3091f92d4fc9SAl Viro 	case SIOCBONDRELEASE:
3092f92d4fc9SAl Viro 	case SIOCBONDSETHWADDR:
3093f92d4fc9SAl Viro 	case SIOCBONDCHANGEACTIVE:
30944cf808e7SAl Viro 	case SIOCGIFNAME:
30959177efd3SArnd Bergmann 		return sock_do_ioctl(net, sock, cmd, arg);
30969177efd3SArnd Bergmann 	}
30979177efd3SArnd Bergmann 
30986b96018bSArnd Bergmann 	return -ENOIOCTLCMD;
30996b96018bSArnd Bergmann }
31007a229387SArnd Bergmann 
310195c96174SEric Dumazet static long compat_sock_ioctl(struct file *file, unsigned int cmd,
310289bbfc95SShaun Pereira 			      unsigned long arg)
310389bbfc95SShaun Pereira {
310489bbfc95SShaun Pereira 	struct socket *sock = file->private_data;
310589bbfc95SShaun Pereira 	int ret = -ENOIOCTLCMD;
310687de87d5SDavid S. Miller 	struct sock *sk;
310787de87d5SDavid S. Miller 	struct net *net;
310887de87d5SDavid S. Miller 
310987de87d5SDavid S. Miller 	sk = sock->sk;
311087de87d5SDavid S. Miller 	net = sock_net(sk);
311189bbfc95SShaun Pereira 
311289bbfc95SShaun Pereira 	if (sock->ops->compat_ioctl)
311389bbfc95SShaun Pereira 		ret = sock->ops->compat_ioctl(sock, cmd, arg);
311489bbfc95SShaun Pereira 
311587de87d5SDavid S. Miller 	if (ret == -ENOIOCTLCMD &&
311687de87d5SDavid S. Miller 	    (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST))
311787de87d5SDavid S. Miller 		ret = compat_wext_handle_ioctl(net, cmd, arg);
311887de87d5SDavid S. Miller 
31196b96018bSArnd Bergmann 	if (ret == -ENOIOCTLCMD)
31206b96018bSArnd Bergmann 		ret = compat_sock_ioctl_trans(file, sock, cmd, arg);
31216b96018bSArnd Bergmann 
312289bbfc95SShaun Pereira 	return ret;
312389bbfc95SShaun Pereira }
312489bbfc95SShaun Pereira #endif
312589bbfc95SShaun Pereira 
3126ac5a488eSSridhar Samudrala int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
3127ac5a488eSSridhar Samudrala {
3128ac5a488eSSridhar Samudrala 	return sock->ops->bind(sock, addr, addrlen);
3129ac5a488eSSridhar Samudrala }
3130c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_bind);
3131ac5a488eSSridhar Samudrala 
3132ac5a488eSSridhar Samudrala int kernel_listen(struct socket *sock, int backlog)
3133ac5a488eSSridhar Samudrala {
3134ac5a488eSSridhar Samudrala 	return sock->ops->listen(sock, backlog);
3135ac5a488eSSridhar Samudrala }
3136c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_listen);
3137ac5a488eSSridhar Samudrala 
3138ac5a488eSSridhar Samudrala int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
3139ac5a488eSSridhar Samudrala {
3140ac5a488eSSridhar Samudrala 	struct sock *sk = sock->sk;
3141ac5a488eSSridhar Samudrala 	int err;
3142ac5a488eSSridhar Samudrala 
3143ac5a488eSSridhar Samudrala 	err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
3144ac5a488eSSridhar Samudrala 			       newsock);
3145ac5a488eSSridhar Samudrala 	if (err < 0)
3146ac5a488eSSridhar Samudrala 		goto done;
3147ac5a488eSSridhar Samudrala 
3148cdfbabfbSDavid Howells 	err = sock->ops->accept(sock, *newsock, flags, true);
3149ac5a488eSSridhar Samudrala 	if (err < 0) {
3150ac5a488eSSridhar Samudrala 		sock_release(*newsock);
3151fa8705b0STony Battersby 		*newsock = NULL;
3152ac5a488eSSridhar Samudrala 		goto done;
3153ac5a488eSSridhar Samudrala 	}
3154ac5a488eSSridhar Samudrala 
3155ac5a488eSSridhar Samudrala 	(*newsock)->ops = sock->ops;
31561b08534eSWei Yongjun 	__module_get((*newsock)->ops->owner);
3157ac5a488eSSridhar Samudrala 
3158ac5a488eSSridhar Samudrala done:
3159ac5a488eSSridhar Samudrala 	return err;
3160ac5a488eSSridhar Samudrala }
3161c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_accept);
3162ac5a488eSSridhar Samudrala 
3163ac5a488eSSridhar Samudrala int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
3164ac5a488eSSridhar Samudrala 		   int flags)
3165ac5a488eSSridhar Samudrala {
3166ac5a488eSSridhar Samudrala 	return sock->ops->connect(sock, addr, addrlen, flags);
3167ac5a488eSSridhar Samudrala }
3168c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_connect);
3169ac5a488eSSridhar Samudrala 
31709b2c45d4SDenys Vlasenko int kernel_getsockname(struct socket *sock, struct sockaddr *addr)
3171ac5a488eSSridhar Samudrala {
31729b2c45d4SDenys Vlasenko 	return sock->ops->getname(sock, addr, 0);
3173ac5a488eSSridhar Samudrala }
3174c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockname);
3175ac5a488eSSridhar Samudrala 
31769b2c45d4SDenys Vlasenko int kernel_getpeername(struct socket *sock, struct sockaddr *addr)
3177ac5a488eSSridhar Samudrala {
31789b2c45d4SDenys Vlasenko 	return sock->ops->getname(sock, addr, 1);
3179ac5a488eSSridhar Samudrala }
3180c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getpeername);
3181ac5a488eSSridhar Samudrala 
3182ac5a488eSSridhar Samudrala int kernel_getsockopt(struct socket *sock, int level, int optname,
3183ac5a488eSSridhar Samudrala 			char *optval, int *optlen)
3184ac5a488eSSridhar Samudrala {
3185ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3186fb8621bbSNamhyung Kim 	char __user *uoptval;
3187fb8621bbSNamhyung Kim 	int __user *uoptlen;
3188ac5a488eSSridhar Samudrala 	int err;
3189ac5a488eSSridhar Samudrala 
3190fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3191fb8621bbSNamhyung Kim 	uoptlen = (int __user __force *) optlen;
3192fb8621bbSNamhyung Kim 
3193ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3194ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3195fb8621bbSNamhyung Kim 		err = sock_getsockopt(sock, level, optname, uoptval, uoptlen);
3196ac5a488eSSridhar Samudrala 	else
3197fb8621bbSNamhyung Kim 		err = sock->ops->getsockopt(sock, level, optname, uoptval,
3198fb8621bbSNamhyung Kim 					    uoptlen);
3199ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3200ac5a488eSSridhar Samudrala 	return err;
3201ac5a488eSSridhar Samudrala }
3202c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockopt);
3203ac5a488eSSridhar Samudrala 
3204ac5a488eSSridhar Samudrala int kernel_setsockopt(struct socket *sock, int level, int optname,
3205b7058842SDavid S. Miller 			char *optval, unsigned int optlen)
3206ac5a488eSSridhar Samudrala {
3207ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3208fb8621bbSNamhyung Kim 	char __user *uoptval;
3209ac5a488eSSridhar Samudrala 	int err;
3210ac5a488eSSridhar Samudrala 
3211fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3212fb8621bbSNamhyung Kim 
3213ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3214ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3215fb8621bbSNamhyung Kim 		err = sock_setsockopt(sock, level, optname, uoptval, optlen);
3216ac5a488eSSridhar Samudrala 	else
3217fb8621bbSNamhyung Kim 		err = sock->ops->setsockopt(sock, level, optname, uoptval,
3218ac5a488eSSridhar Samudrala 					    optlen);
3219ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3220ac5a488eSSridhar Samudrala 	return err;
3221ac5a488eSSridhar Samudrala }
3222c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_setsockopt);
3223ac5a488eSSridhar Samudrala 
3224ac5a488eSSridhar Samudrala int kernel_sendpage(struct socket *sock, struct page *page, int offset,
3225ac5a488eSSridhar Samudrala 		    size_t size, int flags)
3226ac5a488eSSridhar Samudrala {
3227ac5a488eSSridhar Samudrala 	if (sock->ops->sendpage)
3228ac5a488eSSridhar Samudrala 		return sock->ops->sendpage(sock, page, offset, size, flags);
3229ac5a488eSSridhar Samudrala 
3230ac5a488eSSridhar Samudrala 	return sock_no_sendpage(sock, page, offset, size, flags);
3231ac5a488eSSridhar Samudrala }
3232c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendpage);
3233ac5a488eSSridhar Samudrala 
3234306b13ebSTom Herbert int kernel_sendpage_locked(struct sock *sk, struct page *page, int offset,
3235306b13ebSTom Herbert 			   size_t size, int flags)
3236306b13ebSTom Herbert {
3237306b13ebSTom Herbert 	struct socket *sock = sk->sk_socket;
3238306b13ebSTom Herbert 
3239306b13ebSTom Herbert 	if (sock->ops->sendpage_locked)
3240306b13ebSTom Herbert 		return sock->ops->sendpage_locked(sk, page, offset, size,
3241306b13ebSTom Herbert 						  flags);
3242306b13ebSTom Herbert 
3243306b13ebSTom Herbert 	return sock_no_sendpage_locked(sk, page, offset, size, flags);
3244306b13ebSTom Herbert }
3245306b13ebSTom Herbert EXPORT_SYMBOL(kernel_sendpage_locked);
3246306b13ebSTom Herbert 
324791cf45f0STrond Myklebust int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
324891cf45f0STrond Myklebust {
324991cf45f0STrond Myklebust 	return sock->ops->shutdown(sock, how);
325091cf45f0STrond Myklebust }
325191cf45f0STrond Myklebust EXPORT_SYMBOL(kernel_sock_shutdown);
3252113c3075SR. Parameswaran 
3253113c3075SR. Parameswaran /* This routine returns the IP overhead imposed by a socket i.e.
3254113c3075SR. Parameswaran  * the length of the underlying IP header, depending on whether
3255113c3075SR. Parameswaran  * this is an IPv4 or IPv6 socket and the length from IP options turned
325657240d00SR. Parameswaran  * on at the socket. Assumes that the caller has a lock on the socket.
3257113c3075SR. Parameswaran  */
3258113c3075SR. Parameswaran u32 kernel_sock_ip_overhead(struct sock *sk)
3259113c3075SR. Parameswaran {
3260113c3075SR. Parameswaran 	struct inet_sock *inet;
3261113c3075SR. Parameswaran 	struct ip_options_rcu *opt;
3262113c3075SR. Parameswaran 	u32 overhead = 0;
3263113c3075SR. Parameswaran #if IS_ENABLED(CONFIG_IPV6)
3264113c3075SR. Parameswaran 	struct ipv6_pinfo *np;
3265113c3075SR. Parameswaran 	struct ipv6_txoptions *optv6 = NULL;
3266113c3075SR. Parameswaran #endif /* IS_ENABLED(CONFIG_IPV6) */
3267113c3075SR. Parameswaran 
3268113c3075SR. Parameswaran 	if (!sk)
3269113c3075SR. Parameswaran 		return overhead;
3270113c3075SR. Parameswaran 
3271113c3075SR. Parameswaran 	switch (sk->sk_family) {
3272113c3075SR. Parameswaran 	case AF_INET:
3273113c3075SR. Parameswaran 		inet = inet_sk(sk);
3274113c3075SR. Parameswaran 		overhead += sizeof(struct iphdr);
3275113c3075SR. Parameswaran 		opt = rcu_dereference_protected(inet->inet_opt,
3276614d79c0Sstephen hemminger 						sock_owned_by_user(sk));
3277113c3075SR. Parameswaran 		if (opt)
3278113c3075SR. Parameswaran 			overhead += opt->opt.optlen;
3279113c3075SR. Parameswaran 		return overhead;
3280113c3075SR. Parameswaran #if IS_ENABLED(CONFIG_IPV6)
3281113c3075SR. Parameswaran 	case AF_INET6:
3282113c3075SR. Parameswaran 		np = inet6_sk(sk);
3283113c3075SR. Parameswaran 		overhead += sizeof(struct ipv6hdr);
3284113c3075SR. Parameswaran 		if (np)
3285113c3075SR. Parameswaran 			optv6 = rcu_dereference_protected(np->opt,
3286614d79c0Sstephen hemminger 							  sock_owned_by_user(sk));
3287113c3075SR. Parameswaran 		if (optv6)
3288113c3075SR. Parameswaran 			overhead += (optv6->opt_flen + optv6->opt_nflen);
3289113c3075SR. Parameswaran 		return overhead;
3290113c3075SR. Parameswaran #endif /* IS_ENABLED(CONFIG_IPV6) */
3291113c3075SR. Parameswaran 	default: /* Returns 0 overhead if the socket is not ipv4 or ipv6 */
3292113c3075SR. Parameswaran 		return overhead;
3293113c3075SR. Parameswaran 	}
3294113c3075SR. Parameswaran }
3295113c3075SR. Parameswaran EXPORT_SYMBOL(kernel_sock_ip_overhead);
3296