xref: /openbmc/linux/net/socket.c (revision 005a1aea)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * NET		An implementation of the SOCKET network access protocol.
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Version:	@(#)socket.c	1.1.93	18/02/95
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * Authors:	Orest Zborowski, <obz@Kodak.COM>
702c30a84SJesper Juhl  *		Ross Biro
81da177e4SLinus Torvalds  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
91da177e4SLinus Torvalds  *
101da177e4SLinus Torvalds  * Fixes:
111da177e4SLinus Torvalds  *		Anonymous	:	NOTSOCK/BADF cleanup. Error fix in
121da177e4SLinus Torvalds  *					shutdown()
131da177e4SLinus Torvalds  *		Alan Cox	:	verify_area() fixes
141da177e4SLinus Torvalds  *		Alan Cox	:	Removed DDI
151da177e4SLinus Torvalds  *		Jonathan Kamens	:	SOCK_DGRAM reconnect bug
161da177e4SLinus Torvalds  *		Alan Cox	:	Moved a load of checks to the very
171da177e4SLinus Torvalds  *					top level.
181da177e4SLinus Torvalds  *		Alan Cox	:	Move address structures to/from user
191da177e4SLinus Torvalds  *					mode above the protocol layers.
201da177e4SLinus Torvalds  *		Rob Janssen	:	Allow 0 length sends.
211da177e4SLinus Torvalds  *		Alan Cox	:	Asynchronous I/O support (cribbed from the
221da177e4SLinus Torvalds  *					tty drivers).
231da177e4SLinus Torvalds  *		Niibe Yutaka	:	Asynchronous I/O for writes (4.4BSD style)
241da177e4SLinus Torvalds  *		Jeff Uphoff	:	Made max number of sockets command-line
251da177e4SLinus Torvalds  *					configurable.
261da177e4SLinus Torvalds  *		Matti Aarnio	:	Made the number of sockets dynamic,
271da177e4SLinus Torvalds  *					to be allocated when needed, and mr.
281da177e4SLinus Torvalds  *					Uphoff's max is used as max to be
291da177e4SLinus Torvalds  *					allowed to allocate.
301da177e4SLinus Torvalds  *		Linus		:	Argh. removed all the socket allocation
311da177e4SLinus Torvalds  *					altogether: it's in the inode now.
321da177e4SLinus Torvalds  *		Alan Cox	:	Made sock_alloc()/sock_release() public
331da177e4SLinus Torvalds  *					for NetROM and future kernel nfsd type
341da177e4SLinus Torvalds  *					stuff.
351da177e4SLinus Torvalds  *		Alan Cox	:	sendmsg/recvmsg basics.
361da177e4SLinus Torvalds  *		Tom Dyas	:	Export net symbols.
371da177e4SLinus Torvalds  *		Marcin Dalecki	:	Fixed problems with CONFIG_NET="n".
381da177e4SLinus Torvalds  *		Alan Cox	:	Added thread locking to sys_* calls
391da177e4SLinus Torvalds  *					for sockets. May have errors at the
401da177e4SLinus Torvalds  *					moment.
411da177e4SLinus Torvalds  *		Kevin Buhr	:	Fixed the dumb errors in the above.
421da177e4SLinus Torvalds  *		Andi Kleen	:	Some small cleanups, optimizations,
431da177e4SLinus Torvalds  *					and fixed a copy_from_user() bug.
441da177e4SLinus Torvalds  *		Tigran Aivazian	:	sys_send(args) calls sys_sendto(args, NULL, 0)
451da177e4SLinus Torvalds  *		Tigran Aivazian	:	Made listen(2) backlog sanity checks
461da177e4SLinus Torvalds  *					protocol-independent
471da177e4SLinus Torvalds  *
481da177e4SLinus Torvalds  *
491da177e4SLinus Torvalds  *		This program is free software; you can redistribute it and/or
501da177e4SLinus Torvalds  *		modify it under the terms of the GNU General Public License
511da177e4SLinus Torvalds  *		as published by the Free Software Foundation; either version
521da177e4SLinus Torvalds  *		2 of the License, or (at your option) any later version.
531da177e4SLinus Torvalds  *
541da177e4SLinus Torvalds  *
551da177e4SLinus Torvalds  *	This module is effectively the top level interface to the BSD socket
561da177e4SLinus Torvalds  *	paradigm.
571da177e4SLinus Torvalds  *
581da177e4SLinus Torvalds  *	Based upon Swansea University Computer Society NET3.039
591da177e4SLinus Torvalds  */
601da177e4SLinus Torvalds 
611da177e4SLinus Torvalds #include <linux/mm.h>
621da177e4SLinus Torvalds #include <linux/socket.h>
631da177e4SLinus Torvalds #include <linux/file.h>
641da177e4SLinus Torvalds #include <linux/net.h>
651da177e4SLinus Torvalds #include <linux/interrupt.h>
66aaca0bdcSUlrich Drepper #include <linux/thread_info.h>
6755737fdaSStephen Hemminger #include <linux/rcupdate.h>
681da177e4SLinus Torvalds #include <linux/netdevice.h>
691da177e4SLinus Torvalds #include <linux/proc_fs.h>
701da177e4SLinus Torvalds #include <linux/seq_file.h>
714a3e2f71SArjan van de Ven #include <linux/mutex.h>
721da177e4SLinus Torvalds #include <linux/if_bridge.h>
7320380731SArnaldo Carvalho de Melo #include <linux/if_frad.h>
7420380731SArnaldo Carvalho de Melo #include <linux/if_vlan.h>
75408eccceSDaniel Borkmann #include <linux/ptp_classify.h>
761da177e4SLinus Torvalds #include <linux/init.h>
771da177e4SLinus Torvalds #include <linux/poll.h>
781da177e4SLinus Torvalds #include <linux/cache.h>
791da177e4SLinus Torvalds #include <linux/module.h>
801da177e4SLinus Torvalds #include <linux/highmem.h>
811da177e4SLinus Torvalds #include <linux/mount.h>
821da177e4SLinus Torvalds #include <linux/security.h>
831da177e4SLinus Torvalds #include <linux/syscalls.h>
841da177e4SLinus Torvalds #include <linux/compat.h>
851da177e4SLinus Torvalds #include <linux/kmod.h>
863ec3b2fbSDavid Woodhouse #include <linux/audit.h>
87d86b5e0eSAdrian Bunk #include <linux/wireless.h>
881b8d7ae4SEric W. Biederman #include <linux/nsproxy.h>
891fd7317dSNick Black #include <linux/magic.h>
905a0e3ad6STejun Heo #include <linux/slab.h>
91600e1779SMasatake YAMATO #include <linux/xattr.h>
921da177e4SLinus Torvalds 
937c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
941da177e4SLinus Torvalds #include <asm/unistd.h>
951da177e4SLinus Torvalds 
961da177e4SLinus Torvalds #include <net/compat.h>
9787de87d5SDavid S. Miller #include <net/wext.h>
98f8451725SHerbert Xu #include <net/cls_cgroup.h>
991da177e4SLinus Torvalds 
1001da177e4SLinus Torvalds #include <net/sock.h>
1011da177e4SLinus Torvalds #include <linux/netfilter.h>
1021da177e4SLinus Torvalds 
1036b96018bSArnd Bergmann #include <linux/if_tun.h>
1046b96018bSArnd Bergmann #include <linux/ipv6_route.h>
1056b96018bSArnd Bergmann #include <linux/route.h>
1066b96018bSArnd Bergmann #include <linux/sockios.h>
1076b96018bSArnd Bergmann #include <linux/atalk.h>
108076bb0c8SEliezer Tamir #include <net/busy_poll.h>
109f24b9be5SWillem de Bruijn #include <linux/errqueue.h>
11006021292SEliezer Tamir 
111e0d1095aSCong Wang #ifdef CONFIG_NET_RX_BUSY_POLL
11264b0dc51SEliezer Tamir unsigned int sysctl_net_busy_read __read_mostly;
11364b0dc51SEliezer Tamir unsigned int sysctl_net_busy_poll __read_mostly;
11406021292SEliezer Tamir #endif
1156b96018bSArnd Bergmann 
1168ae5e030SAl Viro static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to);
1178ae5e030SAl Viro static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from);
1181da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma);
1191da177e4SLinus Torvalds 
1201da177e4SLinus Torvalds static int sock_close(struct inode *inode, struct file *file);
121ade994f4SAl Viro static __poll_t sock_poll(struct file *file,
1221da177e4SLinus Torvalds 			      struct poll_table_struct *wait);
12389bddce5SStephen Hemminger static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
12489bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
12589bbfc95SShaun Pereira static long compat_sock_ioctl(struct file *file,
12689bbfc95SShaun Pereira 			      unsigned int cmd, unsigned long arg);
12789bbfc95SShaun Pereira #endif
1281da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on);
1291da177e4SLinus Torvalds static ssize_t sock_sendpage(struct file *file, struct page *page,
1301da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more);
1319c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
1329c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
1339c55e01cSJens Axboe 				unsigned int flags);
1341da177e4SLinus Torvalds 
1351da177e4SLinus Torvalds /*
1361da177e4SLinus Torvalds  *	Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
1371da177e4SLinus Torvalds  *	in the operation structures but are done directly via the socketcall() multiplexor.
1381da177e4SLinus Torvalds  */
1391da177e4SLinus Torvalds 
140da7071d7SArjan van de Ven static const struct file_operations socket_file_ops = {
1411da177e4SLinus Torvalds 	.owner =	THIS_MODULE,
1421da177e4SLinus Torvalds 	.llseek =	no_llseek,
1438ae5e030SAl Viro 	.read_iter =	sock_read_iter,
1448ae5e030SAl Viro 	.write_iter =	sock_write_iter,
1451da177e4SLinus Torvalds 	.poll =		sock_poll,
1461da177e4SLinus Torvalds 	.unlocked_ioctl = sock_ioctl,
14789bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
14889bbfc95SShaun Pereira 	.compat_ioctl = compat_sock_ioctl,
14989bbfc95SShaun Pereira #endif
1501da177e4SLinus Torvalds 	.mmap =		sock_mmap,
1511da177e4SLinus Torvalds 	.release =	sock_close,
1521da177e4SLinus Torvalds 	.fasync =	sock_fasync,
1535274f052SJens Axboe 	.sendpage =	sock_sendpage,
1545274f052SJens Axboe 	.splice_write = generic_splice_sendpage,
1559c55e01cSJens Axboe 	.splice_read =	sock_splice_read,
1561da177e4SLinus Torvalds };
1571da177e4SLinus Torvalds 
1581da177e4SLinus Torvalds /*
1591da177e4SLinus Torvalds  *	The protocol list. Each protocol is registered in here.
1601da177e4SLinus Torvalds  */
1611da177e4SLinus Torvalds 
1621da177e4SLinus Torvalds static DEFINE_SPINLOCK(net_family_lock);
163190683a9SEric Dumazet static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly;
1641da177e4SLinus Torvalds 
1651da177e4SLinus Torvalds /*
16689bddce5SStephen Hemminger  * Support routines.
16789bddce5SStephen Hemminger  * Move socket addresses back and forth across the kernel/user
1681da177e4SLinus Torvalds  * divide and look after the messy bits.
1691da177e4SLinus Torvalds  */
1701da177e4SLinus Torvalds 
1711da177e4SLinus Torvalds /**
1721da177e4SLinus Torvalds  *	move_addr_to_kernel	-	copy a socket address into kernel space
1731da177e4SLinus Torvalds  *	@uaddr: Address in user space
1741da177e4SLinus Torvalds  *	@kaddr: Address in kernel space
1751da177e4SLinus Torvalds  *	@ulen: Length in user space
1761da177e4SLinus Torvalds  *
1771da177e4SLinus Torvalds  *	The address is copied into kernel space. If the provided address is
1781da177e4SLinus Torvalds  *	too long an error code of -EINVAL is returned. If the copy gives
1791da177e4SLinus Torvalds  *	invalid addresses -EFAULT is returned. On a success 0 is returned.
1801da177e4SLinus Torvalds  */
1811da177e4SLinus Torvalds 
18243db362dSMaciej Żenczykowski int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr)
1831da177e4SLinus Torvalds {
184230b1839SYOSHIFUJI Hideaki 	if (ulen < 0 || ulen > sizeof(struct sockaddr_storage))
1851da177e4SLinus Torvalds 		return -EINVAL;
1861da177e4SLinus Torvalds 	if (ulen == 0)
1871da177e4SLinus Torvalds 		return 0;
1881da177e4SLinus Torvalds 	if (copy_from_user(kaddr, uaddr, ulen))
1891da177e4SLinus Torvalds 		return -EFAULT;
1903ec3b2fbSDavid Woodhouse 	return audit_sockaddr(ulen, kaddr);
1911da177e4SLinus Torvalds }
1921da177e4SLinus Torvalds 
1931da177e4SLinus Torvalds /**
1941da177e4SLinus Torvalds  *	move_addr_to_user	-	copy an address to user space
1951da177e4SLinus Torvalds  *	@kaddr: kernel space address
1961da177e4SLinus Torvalds  *	@klen: length of address in kernel
1971da177e4SLinus Torvalds  *	@uaddr: user space address
1981da177e4SLinus Torvalds  *	@ulen: pointer to user length field
1991da177e4SLinus Torvalds  *
2001da177e4SLinus Torvalds  *	The value pointed to by ulen on entry is the buffer length available.
2011da177e4SLinus Torvalds  *	This is overwritten with the buffer space used. -EINVAL is returned
2021da177e4SLinus Torvalds  *	if an overlong buffer is specified or a negative buffer size. -EFAULT
2031da177e4SLinus Torvalds  *	is returned if either the buffer or the length field are not
2041da177e4SLinus Torvalds  *	accessible.
2051da177e4SLinus Torvalds  *	After copying the data up to the limit the user specifies, the true
2061da177e4SLinus Torvalds  *	length of the data is written over the length limit the user
2071da177e4SLinus Torvalds  *	specified. Zero is returned for a success.
2081da177e4SLinus Torvalds  */
2091da177e4SLinus Torvalds 
21043db362dSMaciej Żenczykowski static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen,
21111165f14Sstephen hemminger 			     void __user *uaddr, int __user *ulen)
2121da177e4SLinus Torvalds {
2131da177e4SLinus Torvalds 	int err;
2141da177e4SLinus Torvalds 	int len;
2151da177e4SLinus Torvalds 
21668c6beb3SHannes Frederic Sowa 	BUG_ON(klen > sizeof(struct sockaddr_storage));
21789bddce5SStephen Hemminger 	err = get_user(len, ulen);
21889bddce5SStephen Hemminger 	if (err)
2191da177e4SLinus Torvalds 		return err;
2201da177e4SLinus Torvalds 	if (len > klen)
2211da177e4SLinus Torvalds 		len = klen;
22268c6beb3SHannes Frederic Sowa 	if (len < 0)
2231da177e4SLinus Torvalds 		return -EINVAL;
22489bddce5SStephen Hemminger 	if (len) {
225d6fe3945SSteve Grubb 		if (audit_sockaddr(klen, kaddr))
226d6fe3945SSteve Grubb 			return -ENOMEM;
2271da177e4SLinus Torvalds 		if (copy_to_user(uaddr, kaddr, len))
2281da177e4SLinus Torvalds 			return -EFAULT;
2291da177e4SLinus Torvalds 	}
2301da177e4SLinus Torvalds 	/*
2311da177e4SLinus Torvalds 	 *      "fromlen shall refer to the value before truncation.."
2321da177e4SLinus Torvalds 	 *                      1003.1g
2331da177e4SLinus Torvalds 	 */
2341da177e4SLinus Torvalds 	return __put_user(klen, ulen);
2351da177e4SLinus Torvalds }
2361da177e4SLinus Torvalds 
237e18b890bSChristoph Lameter static struct kmem_cache *sock_inode_cachep __read_mostly;
2381da177e4SLinus Torvalds 
2391da177e4SLinus Torvalds static struct inode *sock_alloc_inode(struct super_block *sb)
2401da177e4SLinus Torvalds {
2411da177e4SLinus Torvalds 	struct socket_alloc *ei;
242eaefd110SEric Dumazet 	struct socket_wq *wq;
24389bddce5SStephen Hemminger 
244e94b1766SChristoph Lameter 	ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL);
2451da177e4SLinus Torvalds 	if (!ei)
2461da177e4SLinus Torvalds 		return NULL;
247eaefd110SEric Dumazet 	wq = kmalloc(sizeof(*wq), GFP_KERNEL);
248eaefd110SEric Dumazet 	if (!wq) {
24943815482SEric Dumazet 		kmem_cache_free(sock_inode_cachep, ei);
25043815482SEric Dumazet 		return NULL;
25143815482SEric Dumazet 	}
252eaefd110SEric Dumazet 	init_waitqueue_head(&wq->wait);
253eaefd110SEric Dumazet 	wq->fasync_list = NULL;
254574aab1eSNicolai Stange 	wq->flags = 0;
255eaefd110SEric Dumazet 	RCU_INIT_POINTER(ei->socket.wq, wq);
2561da177e4SLinus Torvalds 
2571da177e4SLinus Torvalds 	ei->socket.state = SS_UNCONNECTED;
2581da177e4SLinus Torvalds 	ei->socket.flags = 0;
2591da177e4SLinus Torvalds 	ei->socket.ops = NULL;
2601da177e4SLinus Torvalds 	ei->socket.sk = NULL;
2611da177e4SLinus Torvalds 	ei->socket.file = NULL;
2621da177e4SLinus Torvalds 
2631da177e4SLinus Torvalds 	return &ei->vfs_inode;
2641da177e4SLinus Torvalds }
2651da177e4SLinus Torvalds 
2661da177e4SLinus Torvalds static void sock_destroy_inode(struct inode *inode)
2671da177e4SLinus Torvalds {
26843815482SEric Dumazet 	struct socket_alloc *ei;
269eaefd110SEric Dumazet 	struct socket_wq *wq;
27043815482SEric Dumazet 
27143815482SEric Dumazet 	ei = container_of(inode, struct socket_alloc, vfs_inode);
272eaefd110SEric Dumazet 	wq = rcu_dereference_protected(ei->socket.wq, 1);
27361845220SLai Jiangshan 	kfree_rcu(wq, rcu);
27443815482SEric Dumazet 	kmem_cache_free(sock_inode_cachep, ei);
2751da177e4SLinus Torvalds }
2761da177e4SLinus Torvalds 
27751cc5068SAlexey Dobriyan static void init_once(void *foo)
2781da177e4SLinus Torvalds {
2791da177e4SLinus Torvalds 	struct socket_alloc *ei = (struct socket_alloc *)foo;
2801da177e4SLinus Torvalds 
2811da177e4SLinus Torvalds 	inode_init_once(&ei->vfs_inode);
2821da177e4SLinus Torvalds }
2831da177e4SLinus Torvalds 
2841e911632Syuan linyu static void init_inodecache(void)
2851da177e4SLinus Torvalds {
2861da177e4SLinus Torvalds 	sock_inode_cachep = kmem_cache_create("sock_inode_cache",
2871da177e4SLinus Torvalds 					      sizeof(struct socket_alloc),
28889bddce5SStephen Hemminger 					      0,
28989bddce5SStephen Hemminger 					      (SLAB_HWCACHE_ALIGN |
29089bddce5SStephen Hemminger 					       SLAB_RECLAIM_ACCOUNT |
2915d097056SVladimir Davydov 					       SLAB_MEM_SPREAD | SLAB_ACCOUNT),
29220c2df83SPaul Mundt 					      init_once);
2931e911632Syuan linyu 	BUG_ON(sock_inode_cachep == NULL);
2941da177e4SLinus Torvalds }
2951da177e4SLinus Torvalds 
296b87221deSAlexey Dobriyan static const struct super_operations sockfs_ops = {
2971da177e4SLinus Torvalds 	.alloc_inode	= sock_alloc_inode,
2981da177e4SLinus Torvalds 	.destroy_inode	= sock_destroy_inode,
2991da177e4SLinus Torvalds 	.statfs		= simple_statfs,
3001da177e4SLinus Torvalds };
3011da177e4SLinus Torvalds 
302c23fbb6bSEric Dumazet /*
303c23fbb6bSEric Dumazet  * sockfs_dname() is called from d_path().
304c23fbb6bSEric Dumazet  */
305c23fbb6bSEric Dumazet static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen)
306c23fbb6bSEric Dumazet {
307c23fbb6bSEric Dumazet 	return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]",
308c5ef6035SDavid Howells 				d_inode(dentry)->i_ino);
309c23fbb6bSEric Dumazet }
310c23fbb6bSEric Dumazet 
3113ba13d17SAl Viro static const struct dentry_operations sockfs_dentry_operations = {
312c23fbb6bSEric Dumazet 	.d_dname  = sockfs_dname,
3131da177e4SLinus Torvalds };
3141da177e4SLinus Torvalds 
315bba0bd31SAndreas Gruenbacher static int sockfs_xattr_get(const struct xattr_handler *handler,
316bba0bd31SAndreas Gruenbacher 			    struct dentry *dentry, struct inode *inode,
317bba0bd31SAndreas Gruenbacher 			    const char *suffix, void *value, size_t size)
318bba0bd31SAndreas Gruenbacher {
319bba0bd31SAndreas Gruenbacher 	if (value) {
320bba0bd31SAndreas Gruenbacher 		if (dentry->d_name.len + 1 > size)
321bba0bd31SAndreas Gruenbacher 			return -ERANGE;
322bba0bd31SAndreas Gruenbacher 		memcpy(value, dentry->d_name.name, dentry->d_name.len + 1);
323bba0bd31SAndreas Gruenbacher 	}
324bba0bd31SAndreas Gruenbacher 	return dentry->d_name.len + 1;
325bba0bd31SAndreas Gruenbacher }
326bba0bd31SAndreas Gruenbacher 
327bba0bd31SAndreas Gruenbacher #define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname"
328bba0bd31SAndreas Gruenbacher #define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX)
329bba0bd31SAndreas Gruenbacher #define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1)
330bba0bd31SAndreas Gruenbacher 
331bba0bd31SAndreas Gruenbacher static const struct xattr_handler sockfs_xattr_handler = {
332bba0bd31SAndreas Gruenbacher 	.name = XATTR_NAME_SOCKPROTONAME,
333bba0bd31SAndreas Gruenbacher 	.get = sockfs_xattr_get,
334bba0bd31SAndreas Gruenbacher };
335bba0bd31SAndreas Gruenbacher 
3364a590153SAndreas Gruenbacher static int sockfs_security_xattr_set(const struct xattr_handler *handler,
3374a590153SAndreas Gruenbacher 				     struct dentry *dentry, struct inode *inode,
3384a590153SAndreas Gruenbacher 				     const char *suffix, const void *value,
3394a590153SAndreas Gruenbacher 				     size_t size, int flags)
3404a590153SAndreas Gruenbacher {
3414a590153SAndreas Gruenbacher 	/* Handled by LSM. */
3424a590153SAndreas Gruenbacher 	return -EAGAIN;
3434a590153SAndreas Gruenbacher }
3444a590153SAndreas Gruenbacher 
3454a590153SAndreas Gruenbacher static const struct xattr_handler sockfs_security_xattr_handler = {
3464a590153SAndreas Gruenbacher 	.prefix = XATTR_SECURITY_PREFIX,
3474a590153SAndreas Gruenbacher 	.set = sockfs_security_xattr_set,
3484a590153SAndreas Gruenbacher };
3494a590153SAndreas Gruenbacher 
350bba0bd31SAndreas Gruenbacher static const struct xattr_handler *sockfs_xattr_handlers[] = {
351bba0bd31SAndreas Gruenbacher 	&sockfs_xattr_handler,
3524a590153SAndreas Gruenbacher 	&sockfs_security_xattr_handler,
353bba0bd31SAndreas Gruenbacher 	NULL
354bba0bd31SAndreas Gruenbacher };
355bba0bd31SAndreas Gruenbacher 
356c74a1cbbSAl Viro static struct dentry *sockfs_mount(struct file_system_type *fs_type,
357c74a1cbbSAl Viro 			 int flags, const char *dev_name, void *data)
358c74a1cbbSAl Viro {
359bba0bd31SAndreas Gruenbacher 	return mount_pseudo_xattr(fs_type, "socket:", &sockfs_ops,
360bba0bd31SAndreas Gruenbacher 				  sockfs_xattr_handlers,
361c74a1cbbSAl Viro 				  &sockfs_dentry_operations, SOCKFS_MAGIC);
362c74a1cbbSAl Viro }
363c74a1cbbSAl Viro 
364c74a1cbbSAl Viro static struct vfsmount *sock_mnt __read_mostly;
365c74a1cbbSAl Viro 
366c74a1cbbSAl Viro static struct file_system_type sock_fs_type = {
367c74a1cbbSAl Viro 	.name =		"sockfs",
368c74a1cbbSAl Viro 	.mount =	sockfs_mount,
369c74a1cbbSAl Viro 	.kill_sb =	kill_anon_super,
370c74a1cbbSAl Viro };
371c74a1cbbSAl Viro 
3721da177e4SLinus Torvalds /*
3731da177e4SLinus Torvalds  *	Obtains the first available file descriptor and sets it up for use.
3741da177e4SLinus Torvalds  *
37539d8c1b6SDavid S. Miller  *	These functions create file structures and maps them to fd space
37639d8c1b6SDavid S. Miller  *	of the current process. On success it returns file descriptor
3771da177e4SLinus Torvalds  *	and file struct implicitly stored in sock->file.
3781da177e4SLinus Torvalds  *	Note that another thread may close file descriptor before we return
3791da177e4SLinus Torvalds  *	from this function. We use the fact that now we do not refer
3801da177e4SLinus Torvalds  *	to socket after mapping. If one day we will need it, this
3811da177e4SLinus Torvalds  *	function will increment ref. count on file by 1.
3821da177e4SLinus Torvalds  *
3831da177e4SLinus Torvalds  *	In any case returned fd MAY BE not valid!
3841da177e4SLinus Torvalds  *	This race condition is unavoidable
3851da177e4SLinus Torvalds  *	with shared fd spaces, we cannot solve it inside kernel,
3861da177e4SLinus Torvalds  *	but we take care of internal coherence yet.
3871da177e4SLinus Torvalds  */
3881da177e4SLinus Torvalds 
389aab174f0SLinus Torvalds struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)
3901da177e4SLinus Torvalds {
3917cbe66b6SAl Viro 	struct qstr name = { .name = "" };
3922c48b9c4SAl Viro 	struct path path;
3937cbe66b6SAl Viro 	struct file *file;
3941da177e4SLinus Torvalds 
395600e1779SMasatake YAMATO 	if (dname) {
396600e1779SMasatake YAMATO 		name.name = dname;
397600e1779SMasatake YAMATO 		name.len = strlen(name.name);
398600e1779SMasatake YAMATO 	} else if (sock->sk) {
399600e1779SMasatake YAMATO 		name.name = sock->sk->sk_prot_creator->name;
400600e1779SMasatake YAMATO 		name.len = strlen(name.name);
401600e1779SMasatake YAMATO 	}
4024b936885SNick Piggin 	path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name);
4038e1611e2SAl Viro 	if (unlikely(!path.dentry)) {
4048e1611e2SAl Viro 		sock_release(sock);
40528407630SAl Viro 		return ERR_PTR(-ENOMEM);
4068e1611e2SAl Viro 	}
4072c48b9c4SAl Viro 	path.mnt = mntget(sock_mnt);
40839d8c1b6SDavid S. Miller 
4092c48b9c4SAl Viro 	d_instantiate(path.dentry, SOCK_INODE(sock));
410cc3808f8SAl Viro 
4112c48b9c4SAl Viro 	file = alloc_file(&path, FMODE_READ | FMODE_WRITE,
412cc3808f8SAl Viro 		  &socket_file_ops);
413b5ffe634SViresh Kumar 	if (IS_ERR(file)) {
4148e1611e2SAl Viro 		/* drop dentry, keep inode for a bit */
415c5ef6035SDavid Howells 		ihold(d_inode(path.dentry));
4162c48b9c4SAl Viro 		path_put(&path);
4178e1611e2SAl Viro 		/* ... and now kill it properly */
4188e1611e2SAl Viro 		sock_release(sock);
41939b65252SAnatol Pomozov 		return file;
420cc3808f8SAl Viro 	}
4211da177e4SLinus Torvalds 
4221da177e4SLinus Torvalds 	sock->file = file;
42377d27200SUlrich Drepper 	file->f_flags = O_RDWR | (flags & O_NONBLOCK);
42407dc3f07SBenjamin LaHaise 	file->private_data = sock;
42528407630SAl Viro 	return file;
4261da177e4SLinus Torvalds }
42756b31d1cSAl Viro EXPORT_SYMBOL(sock_alloc_file);
4281da177e4SLinus Torvalds 
42956b31d1cSAl Viro static int sock_map_fd(struct socket *sock, int flags)
43039d8c1b6SDavid S. Miller {
43139d8c1b6SDavid S. Miller 	struct file *newfile;
43228407630SAl Viro 	int fd = get_unused_fd_flags(flags);
433ce4bb04cSAl Viro 	if (unlikely(fd < 0)) {
434ce4bb04cSAl Viro 		sock_release(sock);
4351da177e4SLinus Torvalds 		return fd;
436ce4bb04cSAl Viro 	}
4371da177e4SLinus Torvalds 
438aab174f0SLinus Torvalds 	newfile = sock_alloc_file(sock, flags, NULL);
43928407630SAl Viro 	if (likely(!IS_ERR(newfile))) {
4401da177e4SLinus Torvalds 		fd_install(fd, newfile);
4411da177e4SLinus Torvalds 		return fd;
4421da177e4SLinus Torvalds 	}
44328407630SAl Viro 
44428407630SAl Viro 	put_unused_fd(fd);
44528407630SAl Viro 	return PTR_ERR(newfile);
4461da177e4SLinus Torvalds }
4471da177e4SLinus Torvalds 
448406a3c63SJohn Fastabend struct socket *sock_from_file(struct file *file, int *err)
4496cb153caSBenjamin LaHaise {
4506cb153caSBenjamin LaHaise 	if (file->f_op == &socket_file_ops)
4516cb153caSBenjamin LaHaise 		return file->private_data;	/* set in sock_map_fd */
4526cb153caSBenjamin LaHaise 
4536cb153caSBenjamin LaHaise 	*err = -ENOTSOCK;
4546cb153caSBenjamin LaHaise 	return NULL;
4556cb153caSBenjamin LaHaise }
456406a3c63SJohn Fastabend EXPORT_SYMBOL(sock_from_file);
4576cb153caSBenjamin LaHaise 
4581da177e4SLinus Torvalds /**
4591da177e4SLinus Torvalds  *	sockfd_lookup - Go from a file number to its socket slot
4601da177e4SLinus Torvalds  *	@fd: file handle
4611da177e4SLinus Torvalds  *	@err: pointer to an error code return
4621da177e4SLinus Torvalds  *
4631da177e4SLinus Torvalds  *	The file handle passed in is locked and the socket it is bound
464241c4667SRosen, Rami  *	to is returned. If an error occurs the err pointer is overwritten
4651da177e4SLinus Torvalds  *	with a negative errno code and NULL is returned. The function checks
4661da177e4SLinus Torvalds  *	for both invalid handles and passing a handle which is not a socket.
4671da177e4SLinus Torvalds  *
4681da177e4SLinus Torvalds  *	On a success the socket object pointer is returned.
4691da177e4SLinus Torvalds  */
4701da177e4SLinus Torvalds 
4711da177e4SLinus Torvalds struct socket *sockfd_lookup(int fd, int *err)
4721da177e4SLinus Torvalds {
4731da177e4SLinus Torvalds 	struct file *file;
4741da177e4SLinus Torvalds 	struct socket *sock;
4751da177e4SLinus Torvalds 
47689bddce5SStephen Hemminger 	file = fget(fd);
47789bddce5SStephen Hemminger 	if (!file) {
4781da177e4SLinus Torvalds 		*err = -EBADF;
4791da177e4SLinus Torvalds 		return NULL;
4801da177e4SLinus Torvalds 	}
48189bddce5SStephen Hemminger 
4826cb153caSBenjamin LaHaise 	sock = sock_from_file(file, err);
4836cb153caSBenjamin LaHaise 	if (!sock)
4841da177e4SLinus Torvalds 		fput(file);
4856cb153caSBenjamin LaHaise 	return sock;
4861da177e4SLinus Torvalds }
487c6d409cfSEric Dumazet EXPORT_SYMBOL(sockfd_lookup);
4881da177e4SLinus Torvalds 
4896cb153caSBenjamin LaHaise static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
4906cb153caSBenjamin LaHaise {
49100e188efSAl Viro 	struct fd f = fdget(fd);
4926cb153caSBenjamin LaHaise 	struct socket *sock;
4936cb153caSBenjamin LaHaise 
4943672558cSHua Zhong 	*err = -EBADF;
49500e188efSAl Viro 	if (f.file) {
49600e188efSAl Viro 		sock = sock_from_file(f.file, err);
49700e188efSAl Viro 		if (likely(sock)) {
49800e188efSAl Viro 			*fput_needed = f.flags;
4991da177e4SLinus Torvalds 			return sock;
50000e188efSAl Viro 		}
50100e188efSAl Viro 		fdput(f);
5026cb153caSBenjamin LaHaise 	}
5036cb153caSBenjamin LaHaise 	return NULL;
5041da177e4SLinus Torvalds }
5051da177e4SLinus Torvalds 
506600e1779SMasatake YAMATO static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer,
507600e1779SMasatake YAMATO 				size_t size)
508600e1779SMasatake YAMATO {
509600e1779SMasatake YAMATO 	ssize_t len;
510600e1779SMasatake YAMATO 	ssize_t used = 0;
511600e1779SMasatake YAMATO 
512c5ef6035SDavid Howells 	len = security_inode_listsecurity(d_inode(dentry), buffer, size);
513600e1779SMasatake YAMATO 	if (len < 0)
514600e1779SMasatake YAMATO 		return len;
515600e1779SMasatake YAMATO 	used += len;
516600e1779SMasatake YAMATO 	if (buffer) {
517600e1779SMasatake YAMATO 		if (size < used)
518600e1779SMasatake YAMATO 			return -ERANGE;
519600e1779SMasatake YAMATO 		buffer += len;
520600e1779SMasatake YAMATO 	}
521600e1779SMasatake YAMATO 
522600e1779SMasatake YAMATO 	len = (XATTR_NAME_SOCKPROTONAME_LEN + 1);
523600e1779SMasatake YAMATO 	used += len;
524600e1779SMasatake YAMATO 	if (buffer) {
525600e1779SMasatake YAMATO 		if (size < used)
526600e1779SMasatake YAMATO 			return -ERANGE;
527600e1779SMasatake YAMATO 		memcpy(buffer, XATTR_NAME_SOCKPROTONAME, len);
528600e1779SMasatake YAMATO 		buffer += len;
529600e1779SMasatake YAMATO 	}
530600e1779SMasatake YAMATO 
531600e1779SMasatake YAMATO 	return used;
532600e1779SMasatake YAMATO }
533600e1779SMasatake YAMATO 
534dc647ec8STobias Klauser static int sockfs_setattr(struct dentry *dentry, struct iattr *iattr)
53586741ec2SLorenzo Colitti {
53686741ec2SLorenzo Colitti 	int err = simple_setattr(dentry, iattr);
53786741ec2SLorenzo Colitti 
538e1a3a60aSEric Biggers 	if (!err && (iattr->ia_valid & ATTR_UID)) {
53986741ec2SLorenzo Colitti 		struct socket *sock = SOCKET_I(d_inode(dentry));
54086741ec2SLorenzo Colitti 
54186741ec2SLorenzo Colitti 		sock->sk->sk_uid = iattr->ia_uid;
54286741ec2SLorenzo Colitti 	}
54386741ec2SLorenzo Colitti 
54486741ec2SLorenzo Colitti 	return err;
54586741ec2SLorenzo Colitti }
54686741ec2SLorenzo Colitti 
547600e1779SMasatake YAMATO static const struct inode_operations sockfs_inode_ops = {
548600e1779SMasatake YAMATO 	.listxattr = sockfs_listxattr,
54986741ec2SLorenzo Colitti 	.setattr = sockfs_setattr,
550600e1779SMasatake YAMATO };
551600e1779SMasatake YAMATO 
5521da177e4SLinus Torvalds /**
5531da177e4SLinus Torvalds  *	sock_alloc	-	allocate a socket
5541da177e4SLinus Torvalds  *
5551da177e4SLinus Torvalds  *	Allocate a new inode and socket object. The two are bound together
5561da177e4SLinus Torvalds  *	and initialised. The socket is then returned. If we are out of inodes
5571da177e4SLinus Torvalds  *	NULL is returned.
5581da177e4SLinus Torvalds  */
5591da177e4SLinus Torvalds 
560f4a00aacSTom Herbert struct socket *sock_alloc(void)
5611da177e4SLinus Torvalds {
5621da177e4SLinus Torvalds 	struct inode *inode;
5631da177e4SLinus Torvalds 	struct socket *sock;
5641da177e4SLinus Torvalds 
565a209dfc7SEric Dumazet 	inode = new_inode_pseudo(sock_mnt->mnt_sb);
5661da177e4SLinus Torvalds 	if (!inode)
5671da177e4SLinus Torvalds 		return NULL;
5681da177e4SLinus Torvalds 
5691da177e4SLinus Torvalds 	sock = SOCKET_I(inode);
5701da177e4SLinus Torvalds 
57185fe4025SChristoph Hellwig 	inode->i_ino = get_next_ino();
5721da177e4SLinus Torvalds 	inode->i_mode = S_IFSOCK | S_IRWXUGO;
5738192b0c4SDavid Howells 	inode->i_uid = current_fsuid();
5748192b0c4SDavid Howells 	inode->i_gid = current_fsgid();
575600e1779SMasatake YAMATO 	inode->i_op = &sockfs_inode_ops;
5761da177e4SLinus Torvalds 
5771da177e4SLinus Torvalds 	return sock;
5781da177e4SLinus Torvalds }
579f4a00aacSTom Herbert EXPORT_SYMBOL(sock_alloc);
5801da177e4SLinus Torvalds 
5811da177e4SLinus Torvalds /**
5821da177e4SLinus Torvalds  *	sock_release	-	close a socket
5831da177e4SLinus Torvalds  *	@sock: socket to close
5841da177e4SLinus Torvalds  *
5851da177e4SLinus Torvalds  *	The socket is released from the protocol stack if it has a release
5861da177e4SLinus Torvalds  *	callback, and the inode is then released if the socket is bound to
5871da177e4SLinus Torvalds  *	an inode not a file.
5881da177e4SLinus Torvalds  */
5891da177e4SLinus Torvalds 
5901da177e4SLinus Torvalds void sock_release(struct socket *sock)
5911da177e4SLinus Torvalds {
5921da177e4SLinus Torvalds 	if (sock->ops) {
5931da177e4SLinus Torvalds 		struct module *owner = sock->ops->owner;
5941da177e4SLinus Torvalds 
5951da177e4SLinus Torvalds 		sock->ops->release(sock);
5961da177e4SLinus Torvalds 		sock->ops = NULL;
5971da177e4SLinus Torvalds 		module_put(owner);
5981da177e4SLinus Torvalds 	}
5991da177e4SLinus Torvalds 
600eaefd110SEric Dumazet 	if (rcu_dereference_protected(sock->wq, 1)->fasync_list)
6013410f22eSYang Yingliang 		pr_err("%s: fasync list not empty!\n", __func__);
6021da177e4SLinus Torvalds 
6031da177e4SLinus Torvalds 	if (!sock->file) {
6041da177e4SLinus Torvalds 		iput(SOCK_INODE(sock));
6051da177e4SLinus Torvalds 		return;
6061da177e4SLinus Torvalds 	}
6071da177e4SLinus Torvalds 	sock->file = NULL;
6081da177e4SLinus Torvalds }
609c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_release);
6101da177e4SLinus Torvalds 
611c14ac945SSoheil Hassas Yeganeh void __sock_tx_timestamp(__u16 tsflags, __u8 *tx_flags)
61220d49473SPatrick Ohly {
613140c55d4SEric Dumazet 	u8 flags = *tx_flags;
614140c55d4SEric Dumazet 
615c14ac945SSoheil Hassas Yeganeh 	if (tsflags & SOF_TIMESTAMPING_TX_HARDWARE)
616140c55d4SEric Dumazet 		flags |= SKBTX_HW_TSTAMP;
617140c55d4SEric Dumazet 
618c14ac945SSoheil Hassas Yeganeh 	if (tsflags & SOF_TIMESTAMPING_TX_SOFTWARE)
619140c55d4SEric Dumazet 		flags |= SKBTX_SW_TSTAMP;
620140c55d4SEric Dumazet 
621c14ac945SSoheil Hassas Yeganeh 	if (tsflags & SOF_TIMESTAMPING_TX_SCHED)
622140c55d4SEric Dumazet 		flags |= SKBTX_SCHED_TSTAMP;
623140c55d4SEric Dumazet 
624140c55d4SEric Dumazet 	*tx_flags = flags;
62520d49473SPatrick Ohly }
62667cc0d40SWillem de Bruijn EXPORT_SYMBOL(__sock_tx_timestamp);
62720d49473SPatrick Ohly 
628d8725c86SAl Viro static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg)
6291da177e4SLinus Torvalds {
63001e97e65SAl Viro 	int ret = sock->ops->sendmsg(sock, msg, msg_data_left(msg));
631d8725c86SAl Viro 	BUG_ON(ret == -EIOCBQUEUED);
632d8725c86SAl Viro 	return ret;
6331da177e4SLinus Torvalds }
6340cf00c6fSGu Zheng 
635d8725c86SAl Viro int sock_sendmsg(struct socket *sock, struct msghdr *msg)
6360cf00c6fSGu Zheng {
637d8725c86SAl Viro 	int err = security_socket_sendmsg(sock, msg,
63801e97e65SAl Viro 					  msg_data_left(msg));
6391b784140SYing Xue 
640d8725c86SAl Viro 	return err ?: sock_sendmsg_nosec(sock, msg);
6410cf00c6fSGu Zheng }
642c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_sendmsg);
6431da177e4SLinus Torvalds 
6441da177e4SLinus Torvalds int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
6451da177e4SLinus Torvalds 		   struct kvec *vec, size_t num, size_t size)
6461da177e4SLinus Torvalds {
6476aa24814SAl Viro 	iov_iter_kvec(&msg->msg_iter, WRITE | ITER_KVEC, vec, num, size);
648d8725c86SAl Viro 	return sock_sendmsg(sock, msg);
6491da177e4SLinus Torvalds }
650c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendmsg);
6511da177e4SLinus Torvalds 
652306b13ebSTom Herbert int kernel_sendmsg_locked(struct sock *sk, struct msghdr *msg,
653306b13ebSTom Herbert 			  struct kvec *vec, size_t num, size_t size)
654306b13ebSTom Herbert {
655306b13ebSTom Herbert 	struct socket *sock = sk->sk_socket;
656306b13ebSTom Herbert 
657306b13ebSTom Herbert 	if (!sock->ops->sendmsg_locked)
658db5980d8SJohn Fastabend 		return sock_no_sendmsg_locked(sk, msg, size);
659306b13ebSTom Herbert 
660306b13ebSTom Herbert 	iov_iter_kvec(&msg->msg_iter, WRITE | ITER_KVEC, vec, num, size);
661306b13ebSTom Herbert 
662306b13ebSTom Herbert 	return sock->ops->sendmsg_locked(sk, msg, msg_data_left(msg));
663306b13ebSTom Herbert }
664306b13ebSTom Herbert EXPORT_SYMBOL(kernel_sendmsg_locked);
665306b13ebSTom Herbert 
6668605330aSSoheil Hassas Yeganeh static bool skb_is_err_queue(const struct sk_buff *skb)
6678605330aSSoheil Hassas Yeganeh {
6688605330aSSoheil Hassas Yeganeh 	/* pkt_type of skbs enqueued on the error queue are set to
6698605330aSSoheil Hassas Yeganeh 	 * PACKET_OUTGOING in skb_set_err_queue(). This is only safe to do
6708605330aSSoheil Hassas Yeganeh 	 * in recvmsg, since skbs received on a local socket will never
6718605330aSSoheil Hassas Yeganeh 	 * have a pkt_type of PACKET_OUTGOING.
6728605330aSSoheil Hassas Yeganeh 	 */
6738605330aSSoheil Hassas Yeganeh 	return skb->pkt_type == PACKET_OUTGOING;
6748605330aSSoheil Hassas Yeganeh }
6758605330aSSoheil Hassas Yeganeh 
676b50a5c70SMiroslav Lichvar /* On transmit, software and hardware timestamps are returned independently.
677b50a5c70SMiroslav Lichvar  * As the two skb clones share the hardware timestamp, which may be updated
678b50a5c70SMiroslav Lichvar  * before the software timestamp is received, a hardware TX timestamp may be
679b50a5c70SMiroslav Lichvar  * returned only if there is no software TX timestamp. Ignore false software
680b50a5c70SMiroslav Lichvar  * timestamps, which may be made in the __sock_recv_timestamp() call when the
681b50a5c70SMiroslav Lichvar  * option SO_TIMESTAMP(NS) is enabled on the socket, even when the skb has a
682b50a5c70SMiroslav Lichvar  * hardware timestamp.
683b50a5c70SMiroslav Lichvar  */
684b50a5c70SMiroslav Lichvar static bool skb_is_swtx_tstamp(const struct sk_buff *skb, int false_tstamp)
685b50a5c70SMiroslav Lichvar {
686b50a5c70SMiroslav Lichvar 	return skb->tstamp && !false_tstamp && skb_is_err_queue(skb);
687b50a5c70SMiroslav Lichvar }
688b50a5c70SMiroslav Lichvar 
689aad9c8c4SMiroslav Lichvar static void put_ts_pktinfo(struct msghdr *msg, struct sk_buff *skb)
690aad9c8c4SMiroslav Lichvar {
691aad9c8c4SMiroslav Lichvar 	struct scm_ts_pktinfo ts_pktinfo;
692aad9c8c4SMiroslav Lichvar 	struct net_device *orig_dev;
693aad9c8c4SMiroslav Lichvar 
694aad9c8c4SMiroslav Lichvar 	if (!skb_mac_header_was_set(skb))
695aad9c8c4SMiroslav Lichvar 		return;
696aad9c8c4SMiroslav Lichvar 
697aad9c8c4SMiroslav Lichvar 	memset(&ts_pktinfo, 0, sizeof(ts_pktinfo));
698aad9c8c4SMiroslav Lichvar 
699aad9c8c4SMiroslav Lichvar 	rcu_read_lock();
700aad9c8c4SMiroslav Lichvar 	orig_dev = dev_get_by_napi_id(skb_napi_id(skb));
701aad9c8c4SMiroslav Lichvar 	if (orig_dev)
702aad9c8c4SMiroslav Lichvar 		ts_pktinfo.if_index = orig_dev->ifindex;
703aad9c8c4SMiroslav Lichvar 	rcu_read_unlock();
704aad9c8c4SMiroslav Lichvar 
705aad9c8c4SMiroslav Lichvar 	ts_pktinfo.pkt_length = skb->len - skb_mac_offset(skb);
706aad9c8c4SMiroslav Lichvar 	put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_PKTINFO,
707aad9c8c4SMiroslav Lichvar 		 sizeof(ts_pktinfo), &ts_pktinfo);
708aad9c8c4SMiroslav Lichvar }
709aad9c8c4SMiroslav Lichvar 
71092f37fd2SEric Dumazet /*
71192f37fd2SEric Dumazet  * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
71292f37fd2SEric Dumazet  */
71392f37fd2SEric Dumazet void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
71492f37fd2SEric Dumazet 	struct sk_buff *skb)
71592f37fd2SEric Dumazet {
71620d49473SPatrick Ohly 	int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
717f24b9be5SWillem de Bruijn 	struct scm_timestamping tss;
718b50a5c70SMiroslav Lichvar 	int empty = 1, false_tstamp = 0;
71920d49473SPatrick Ohly 	struct skb_shared_hwtstamps *shhwtstamps =
72020d49473SPatrick Ohly 		skb_hwtstamps(skb);
72192f37fd2SEric Dumazet 
72220d49473SPatrick Ohly 	/* Race occurred between timestamp enabling and packet
72320d49473SPatrick Ohly 	   receiving.  Fill in the current time for now. */
724b50a5c70SMiroslav Lichvar 	if (need_software_tstamp && skb->tstamp == 0) {
72520d49473SPatrick Ohly 		__net_timestamp(skb);
726b50a5c70SMiroslav Lichvar 		false_tstamp = 1;
727b50a5c70SMiroslav Lichvar 	}
72820d49473SPatrick Ohly 
72920d49473SPatrick Ohly 	if (need_software_tstamp) {
73092f37fd2SEric Dumazet 		if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
73192f37fd2SEric Dumazet 			struct timeval tv;
73220d49473SPatrick Ohly 			skb_get_timestamp(skb, &tv);
73320d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP,
73420d49473SPatrick Ohly 				 sizeof(tv), &tv);
73592f37fd2SEric Dumazet 		} else {
736f24b9be5SWillem de Bruijn 			struct timespec ts;
737f24b9be5SWillem de Bruijn 			skb_get_timestampns(skb, &ts);
73820d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS,
739f24b9be5SWillem de Bruijn 				 sizeof(ts), &ts);
74092f37fd2SEric Dumazet 		}
74192f37fd2SEric Dumazet 	}
74292f37fd2SEric Dumazet 
743f24b9be5SWillem de Bruijn 	memset(&tss, 0, sizeof(tss));
744c199105dSWillem de Bruijn 	if ((sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE) &&
745f24b9be5SWillem de Bruijn 	    ktime_to_timespec_cond(skb->tstamp, tss.ts + 0))
74620d49473SPatrick Ohly 		empty = 0;
7474d276eb6SWillem de Bruijn 	if (shhwtstamps &&
748b9f40e21SWillem de Bruijn 	    (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
749b50a5c70SMiroslav Lichvar 	    !skb_is_swtx_tstamp(skb, false_tstamp) &&
750aad9c8c4SMiroslav Lichvar 	    ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2)) {
75120d49473SPatrick Ohly 		empty = 0;
752aad9c8c4SMiroslav Lichvar 		if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_PKTINFO) &&
753aad9c8c4SMiroslav Lichvar 		    !skb_is_err_queue(skb))
754aad9c8c4SMiroslav Lichvar 			put_ts_pktinfo(msg, skb);
755aad9c8c4SMiroslav Lichvar 	}
7561c885808SFrancis Yan 	if (!empty) {
75720d49473SPatrick Ohly 		put_cmsg(msg, SOL_SOCKET,
758f24b9be5SWillem de Bruijn 			 SCM_TIMESTAMPING, sizeof(tss), &tss);
7591c885808SFrancis Yan 
7608605330aSSoheil Hassas Yeganeh 		if (skb_is_err_queue(skb) && skb->len &&
7614ef1b286SSoheil Hassas Yeganeh 		    SKB_EXT_ERR(skb)->opt_stats)
7621c885808SFrancis Yan 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_OPT_STATS,
7631c885808SFrancis Yan 				 skb->len, skb->data);
7641c885808SFrancis Yan 	}
76520d49473SPatrick Ohly }
7667c81fd8bSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
7677c81fd8bSArnaldo Carvalho de Melo 
7686e3e939fSJohannes Berg void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
7696e3e939fSJohannes Berg 	struct sk_buff *skb)
7706e3e939fSJohannes Berg {
7716e3e939fSJohannes Berg 	int ack;
7726e3e939fSJohannes Berg 
7736e3e939fSJohannes Berg 	if (!sock_flag(sk, SOCK_WIFI_STATUS))
7746e3e939fSJohannes Berg 		return;
7756e3e939fSJohannes Berg 	if (!skb->wifi_acked_valid)
7766e3e939fSJohannes Berg 		return;
7776e3e939fSJohannes Berg 
7786e3e939fSJohannes Berg 	ack = skb->wifi_acked;
7796e3e939fSJohannes Berg 
7806e3e939fSJohannes Berg 	put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack);
7816e3e939fSJohannes Berg }
7826e3e939fSJohannes Berg EXPORT_SYMBOL_GPL(__sock_recv_wifi_status);
7836e3e939fSJohannes Berg 
78411165f14Sstephen hemminger static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk,
78511165f14Sstephen hemminger 				   struct sk_buff *skb)
7863b885787SNeil Horman {
787744d5a3eSEyal Birger 	if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && SOCK_SKB_CB(skb)->dropcount)
7883b885787SNeil Horman 		put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL,
789744d5a3eSEyal Birger 			sizeof(__u32), &SOCK_SKB_CB(skb)->dropcount);
7903b885787SNeil Horman }
7913b885787SNeil Horman 
792767dd033SEric Dumazet void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
7933b885787SNeil Horman 	struct sk_buff *skb)
7943b885787SNeil Horman {
7953b885787SNeil Horman 	sock_recv_timestamp(msg, sk, skb);
7963b885787SNeil Horman 	sock_recv_drops(msg, sk, skb);
7973b885787SNeil Horman }
798767dd033SEric Dumazet EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops);
7993b885787SNeil Horman 
8001b784140SYing Xue static inline int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
8011b784140SYing Xue 				     int flags)
802a2e27255SArnaldo Carvalho de Melo {
8032da62906SAl Viro 	return sock->ops->recvmsg(sock, msg, msg_data_left(msg), flags);
8042da62906SAl Viro }
805a2e27255SArnaldo Carvalho de Melo 
8062da62906SAl Viro int sock_recvmsg(struct socket *sock, struct msghdr *msg, int flags)
8072da62906SAl Viro {
8082da62906SAl Viro 	int err = security_socket_recvmsg(sock, msg, msg_data_left(msg), flags);
8092da62906SAl Viro 
8102da62906SAl Viro 	return err ?: sock_recvmsg_nosec(sock, msg, flags);
8111da177e4SLinus Torvalds }
812c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_recvmsg);
8131da177e4SLinus Torvalds 
814c1249c0aSMartin Lucina /**
815c1249c0aSMartin Lucina  * kernel_recvmsg - Receive a message from a socket (kernel space)
816c1249c0aSMartin Lucina  * @sock:       The socket to receive the message from
817c1249c0aSMartin Lucina  * @msg:        Received message
818c1249c0aSMartin Lucina  * @vec:        Input s/g array for message data
819c1249c0aSMartin Lucina  * @num:        Size of input s/g array
820c1249c0aSMartin Lucina  * @size:       Number of bytes to read
821c1249c0aSMartin Lucina  * @flags:      Message flags (MSG_DONTWAIT, etc...)
822c1249c0aSMartin Lucina  *
823c1249c0aSMartin Lucina  * On return the msg structure contains the scatter/gather array passed in the
824c1249c0aSMartin Lucina  * vec argument. The array is modified so that it consists of the unfilled
825c1249c0aSMartin Lucina  * portion of the original array.
826c1249c0aSMartin Lucina  *
827c1249c0aSMartin Lucina  * The returned value is the total number of bytes received, or an error.
828c1249c0aSMartin Lucina  */
8291da177e4SLinus Torvalds int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
83089bddce5SStephen Hemminger 		   struct kvec *vec, size_t num, size_t size, int flags)
8311da177e4SLinus Torvalds {
8321da177e4SLinus Torvalds 	mm_segment_t oldfs = get_fs();
8331da177e4SLinus Torvalds 	int result;
8341da177e4SLinus Torvalds 
8356aa24814SAl Viro 	iov_iter_kvec(&msg->msg_iter, READ | ITER_KVEC, vec, num, size);
8361da177e4SLinus Torvalds 	set_fs(KERNEL_DS);
8372da62906SAl Viro 	result = sock_recvmsg(sock, msg, flags);
8381da177e4SLinus Torvalds 	set_fs(oldfs);
8391da177e4SLinus Torvalds 	return result;
8401da177e4SLinus Torvalds }
841c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_recvmsg);
8421da177e4SLinus Torvalds 
84320380731SArnaldo Carvalho de Melo static ssize_t sock_sendpage(struct file *file, struct page *page,
8441da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more)
8451da177e4SLinus Torvalds {
8461da177e4SLinus Torvalds 	struct socket *sock;
8471da177e4SLinus Torvalds 	int flags;
8481da177e4SLinus Torvalds 
849b69aee04SEric Dumazet 	sock = file->private_data;
8501da177e4SLinus Torvalds 
85135f9c09fSEric Dumazet 	flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
85235f9c09fSEric Dumazet 	/* more is a combination of MSG_MORE and MSG_SENDPAGE_NOTLAST */
85335f9c09fSEric Dumazet 	flags |= more;
8541da177e4SLinus Torvalds 
855e6949583SLinus Torvalds 	return kernel_sendpage(sock, page, offset, size, flags);
8561da177e4SLinus Torvalds }
8571da177e4SLinus Torvalds 
8589c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
8599c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
8609c55e01cSJens Axboe 				unsigned int flags)
8619c55e01cSJens Axboe {
8629c55e01cSJens Axboe 	struct socket *sock = file->private_data;
8639c55e01cSJens Axboe 
864997b37daSRémi Denis-Courmont 	if (unlikely(!sock->ops->splice_read))
865997b37daSRémi Denis-Courmont 		return -EINVAL;
866997b37daSRémi Denis-Courmont 
8679c55e01cSJens Axboe 	return sock->ops->splice_read(sock, ppos, pipe, len, flags);
8689c55e01cSJens Axboe }
8699c55e01cSJens Axboe 
8708ae5e030SAl Viro static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to)
871ce1d4d3eSChristoph Hellwig {
8726d652330SAl Viro 	struct file *file = iocb->ki_filp;
8736d652330SAl Viro 	struct socket *sock = file->private_data;
8740345f931Stadeusz.struk@intel.com 	struct msghdr msg = {.msg_iter = *to,
8750345f931Stadeusz.struk@intel.com 			     .msg_iocb = iocb};
8768ae5e030SAl Viro 	ssize_t res;
877ce1d4d3eSChristoph Hellwig 
8788ae5e030SAl Viro 	if (file->f_flags & O_NONBLOCK)
8798ae5e030SAl Viro 		msg.msg_flags = MSG_DONTWAIT;
8808ae5e030SAl Viro 
8818ae5e030SAl Viro 	if (iocb->ki_pos != 0)
882ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
883027445c3SBadari Pulavarty 
88466ee59afSChristoph Hellwig 	if (!iov_iter_count(to))	/* Match SYS5 behaviour */
885ce1d4d3eSChristoph Hellwig 		return 0;
886ce1d4d3eSChristoph Hellwig 
8872da62906SAl Viro 	res = sock_recvmsg(sock, &msg, msg.msg_flags);
8888ae5e030SAl Viro 	*to = msg.msg_iter;
8898ae5e030SAl Viro 	return res;
890ce1d4d3eSChristoph Hellwig }
891ce1d4d3eSChristoph Hellwig 
8928ae5e030SAl Viro static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from)
8931da177e4SLinus Torvalds {
8946d652330SAl Viro 	struct file *file = iocb->ki_filp;
8956d652330SAl Viro 	struct socket *sock = file->private_data;
8960345f931Stadeusz.struk@intel.com 	struct msghdr msg = {.msg_iter = *from,
8970345f931Stadeusz.struk@intel.com 			     .msg_iocb = iocb};
8988ae5e030SAl Viro 	ssize_t res;
8991da177e4SLinus Torvalds 
9008ae5e030SAl Viro 	if (iocb->ki_pos != 0)
901ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
902027445c3SBadari Pulavarty 
9038ae5e030SAl Viro 	if (file->f_flags & O_NONBLOCK)
9048ae5e030SAl Viro 		msg.msg_flags = MSG_DONTWAIT;
9058ae5e030SAl Viro 
9066d652330SAl Viro 	if (sock->type == SOCK_SEQPACKET)
9076d652330SAl Viro 		msg.msg_flags |= MSG_EOR;
9086d652330SAl Viro 
909d8725c86SAl Viro 	res = sock_sendmsg(sock, &msg);
9108ae5e030SAl Viro 	*from = msg.msg_iter;
9118ae5e030SAl Viro 	return res;
9121da177e4SLinus Torvalds }
9131da177e4SLinus Torvalds 
9141da177e4SLinus Torvalds /*
9151da177e4SLinus Torvalds  * Atomic setting of ioctl hooks to avoid race
9161da177e4SLinus Torvalds  * with module unload.
9171da177e4SLinus Torvalds  */
9181da177e4SLinus Torvalds 
9194a3e2f71SArjan van de Ven static DEFINE_MUTEX(br_ioctl_mutex);
920c6d409cfSEric Dumazet static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg);
9211da177e4SLinus Torvalds 
922881d966bSEric W. Biederman void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *))
9231da177e4SLinus Torvalds {
9244a3e2f71SArjan van de Ven 	mutex_lock(&br_ioctl_mutex);
9251da177e4SLinus Torvalds 	br_ioctl_hook = hook;
9264a3e2f71SArjan van de Ven 	mutex_unlock(&br_ioctl_mutex);
9271da177e4SLinus Torvalds }
9281da177e4SLinus Torvalds EXPORT_SYMBOL(brioctl_set);
9291da177e4SLinus Torvalds 
9304a3e2f71SArjan van de Ven static DEFINE_MUTEX(vlan_ioctl_mutex);
931881d966bSEric W. Biederman static int (*vlan_ioctl_hook) (struct net *, void __user *arg);
9321da177e4SLinus Torvalds 
933881d966bSEric W. Biederman void vlan_ioctl_set(int (*hook) (struct net *, void __user *))
9341da177e4SLinus Torvalds {
9354a3e2f71SArjan van de Ven 	mutex_lock(&vlan_ioctl_mutex);
9361da177e4SLinus Torvalds 	vlan_ioctl_hook = hook;
9374a3e2f71SArjan van de Ven 	mutex_unlock(&vlan_ioctl_mutex);
9381da177e4SLinus Torvalds }
9391da177e4SLinus Torvalds EXPORT_SYMBOL(vlan_ioctl_set);
9401da177e4SLinus Torvalds 
9414a3e2f71SArjan van de Ven static DEFINE_MUTEX(dlci_ioctl_mutex);
9421da177e4SLinus Torvalds static int (*dlci_ioctl_hook) (unsigned int, void __user *);
9431da177e4SLinus Torvalds 
9441da177e4SLinus Torvalds void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
9451da177e4SLinus Torvalds {
9464a3e2f71SArjan van de Ven 	mutex_lock(&dlci_ioctl_mutex);
9471da177e4SLinus Torvalds 	dlci_ioctl_hook = hook;
9484a3e2f71SArjan van de Ven 	mutex_unlock(&dlci_ioctl_mutex);
9491da177e4SLinus Torvalds }
9501da177e4SLinus Torvalds EXPORT_SYMBOL(dlci_ioctl_set);
9511da177e4SLinus Torvalds 
9526b96018bSArnd Bergmann static long sock_do_ioctl(struct net *net, struct socket *sock,
9536b96018bSArnd Bergmann 				 unsigned int cmd, unsigned long arg)
9546b96018bSArnd Bergmann {
9556b96018bSArnd Bergmann 	int err;
9566b96018bSArnd Bergmann 	void __user *argp = (void __user *)arg;
9576b96018bSArnd Bergmann 
9586b96018bSArnd Bergmann 	err = sock->ops->ioctl(sock, cmd, arg);
9596b96018bSArnd Bergmann 
9606b96018bSArnd Bergmann 	/*
9616b96018bSArnd Bergmann 	 * If this ioctl is unknown try to hand it down
9626b96018bSArnd Bergmann 	 * to the NIC driver.
9636b96018bSArnd Bergmann 	 */
96436fd633eSAl Viro 	if (err != -ENOIOCTLCMD)
9656b96018bSArnd Bergmann 		return err;
9666b96018bSArnd Bergmann 
96736fd633eSAl Viro 	if (cmd == SIOCGIFCONF) {
96836fd633eSAl Viro 		struct ifconf ifc;
96936fd633eSAl Viro 		if (copy_from_user(&ifc, argp, sizeof(struct ifconf)))
97036fd633eSAl Viro 			return -EFAULT;
97136fd633eSAl Viro 		rtnl_lock();
97236fd633eSAl Viro 		err = dev_ifconf(net, &ifc, sizeof(struct ifreq));
97336fd633eSAl Viro 		rtnl_unlock();
97436fd633eSAl Viro 		if (!err && copy_to_user(argp, &ifc, sizeof(struct ifconf)))
97536fd633eSAl Viro 			err = -EFAULT;
97644c02a2cSAl Viro 	} else {
97744c02a2cSAl Viro 		struct ifreq ifr;
97844c02a2cSAl Viro 		bool need_copyout;
97944c02a2cSAl Viro 		if (copy_from_user(&ifr, argp, sizeof(struct ifreq)))
98044c02a2cSAl Viro 			return -EFAULT;
98144c02a2cSAl Viro 		err = dev_ioctl(net, cmd, &ifr, &need_copyout);
98244c02a2cSAl Viro 		if (!err && need_copyout)
98344c02a2cSAl Viro 			if (copy_to_user(argp, &ifr, sizeof(struct ifreq)))
98444c02a2cSAl Viro 				return -EFAULT;
98536fd633eSAl Viro 	}
9866b96018bSArnd Bergmann 	return err;
9876b96018bSArnd Bergmann }
9886b96018bSArnd Bergmann 
9891da177e4SLinus Torvalds /*
9901da177e4SLinus Torvalds  *	With an ioctl, arg may well be a user mode pointer, but we don't know
9911da177e4SLinus Torvalds  *	what to do with it - that's up to the protocol still.
9921da177e4SLinus Torvalds  */
9931da177e4SLinus Torvalds 
994c62cce2cSAndrey Vagin static struct ns_common *get_net_ns(struct ns_common *ns)
995c62cce2cSAndrey Vagin {
996c62cce2cSAndrey Vagin 	return &get_net(container_of(ns, struct net, ns))->ns;
997c62cce2cSAndrey Vagin }
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 
13359d6a15c3SDominik Brodowski int __sys_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 
13629d6a15c3SDominik Brodowski SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
13639d6a15c3SDominik Brodowski {
13649d6a15c3SDominik Brodowski 	return __sys_socket(family, type, protocol);
13659d6a15c3SDominik Brodowski }
13669d6a15c3SDominik Brodowski 
13671da177e4SLinus Torvalds /*
13681da177e4SLinus Torvalds  *	Create a pair of connected sockets.
13691da177e4SLinus Torvalds  */
13701da177e4SLinus Torvalds 
13716debc8d8SDominik Brodowski int __sys_socketpair(int family, int type, int protocol, int __user *usockvec)
13721da177e4SLinus Torvalds {
13731da177e4SLinus Torvalds 	struct socket *sock1, *sock2;
13741da177e4SLinus Torvalds 	int fd1, fd2, err;
1375db349509SAl Viro 	struct file *newfile1, *newfile2;
1376a677a039SUlrich Drepper 	int flags;
1377a677a039SUlrich Drepper 
1378a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
137977d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1380a677a039SUlrich Drepper 		return -EINVAL;
1381a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
13821da177e4SLinus Torvalds 
1383aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1384aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1385aaca0bdcSUlrich Drepper 
13861da177e4SLinus Torvalds 	/*
1387016a266bSAl Viro 	 * reserve descriptors and make sure we won't fail
1388016a266bSAl Viro 	 * to return them to userland.
1389016a266bSAl Viro 	 */
1390016a266bSAl Viro 	fd1 = get_unused_fd_flags(flags);
1391016a266bSAl Viro 	if (unlikely(fd1 < 0))
1392016a266bSAl Viro 		return fd1;
1393016a266bSAl Viro 
1394016a266bSAl Viro 	fd2 = get_unused_fd_flags(flags);
1395016a266bSAl Viro 	if (unlikely(fd2 < 0)) {
1396016a266bSAl Viro 		put_unused_fd(fd1);
1397016a266bSAl Viro 		return fd2;
1398016a266bSAl Viro 	}
1399016a266bSAl Viro 
1400016a266bSAl Viro 	err = put_user(fd1, &usockvec[0]);
1401016a266bSAl Viro 	if (err)
1402016a266bSAl Viro 		goto out;
1403016a266bSAl Viro 
1404016a266bSAl Viro 	err = put_user(fd2, &usockvec[1]);
1405016a266bSAl Viro 	if (err)
1406016a266bSAl Viro 		goto out;
1407016a266bSAl Viro 
1408016a266bSAl Viro 	/*
14091da177e4SLinus Torvalds 	 * Obtain the first socket and check if the underlying protocol
14101da177e4SLinus Torvalds 	 * supports the socketpair call.
14111da177e4SLinus Torvalds 	 */
14121da177e4SLinus Torvalds 
14131da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock1);
1414016a266bSAl Viro 	if (unlikely(err < 0))
14151da177e4SLinus Torvalds 		goto out;
14161da177e4SLinus Torvalds 
14171da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock2);
1418016a266bSAl Viro 	if (unlikely(err < 0)) {
1419016a266bSAl Viro 		sock_release(sock1);
1420016a266bSAl Viro 		goto out;
1421bf3c23d1SDavid S. Miller 	}
1422d73aa286SYann Droneaud 
1423016a266bSAl Viro 	err = sock1->ops->socketpair(sock1, sock2);
1424016a266bSAl Viro 	if (unlikely(err < 0)) {
1425016a266bSAl Viro 		sock_release(sock2);
1426016a266bSAl Viro 		sock_release(sock1);
1427016a266bSAl Viro 		goto out;
142828407630SAl Viro 	}
142928407630SAl Viro 
1430aab174f0SLinus Torvalds 	newfile1 = sock_alloc_file(sock1, flags, NULL);
1431b5ffe634SViresh Kumar 	if (IS_ERR(newfile1)) {
143228407630SAl Viro 		err = PTR_ERR(newfile1);
1433016a266bSAl Viro 		sock_release(sock2);
1434016a266bSAl Viro 		goto out;
143528407630SAl Viro 	}
143628407630SAl Viro 
1437aab174f0SLinus Torvalds 	newfile2 = sock_alloc_file(sock2, flags, NULL);
143828407630SAl Viro 	if (IS_ERR(newfile2)) {
143928407630SAl Viro 		err = PTR_ERR(newfile2);
1440016a266bSAl Viro 		fput(newfile1);
1441016a266bSAl Viro 		goto out;
1442db349509SAl Viro 	}
1443db349509SAl Viro 
1444157cf649SAl Viro 	audit_fd_pair(fd1, fd2);
1445d73aa286SYann Droneaud 
1446db349509SAl Viro 	fd_install(fd1, newfile1);
1447db349509SAl Viro 	fd_install(fd2, newfile2);
14481da177e4SLinus Torvalds 	return 0;
14491da177e4SLinus Torvalds 
14501da177e4SLinus Torvalds out:
1451016a266bSAl Viro 	put_unused_fd(fd2);
1452016a266bSAl Viro 	put_unused_fd(fd1);
14531da177e4SLinus Torvalds 	return err;
14541da177e4SLinus Torvalds }
14551da177e4SLinus Torvalds 
14566debc8d8SDominik Brodowski SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
14576debc8d8SDominik Brodowski 		int __user *, usockvec)
14586debc8d8SDominik Brodowski {
14596debc8d8SDominik Brodowski 	return __sys_socketpair(family, type, protocol, usockvec);
14606debc8d8SDominik Brodowski }
14616debc8d8SDominik Brodowski 
14621da177e4SLinus Torvalds /*
14631da177e4SLinus Torvalds  *	Bind a name to a socket. Nothing much to do here since it's
14641da177e4SLinus Torvalds  *	the protocol's responsibility to handle the local address.
14651da177e4SLinus Torvalds  *
14661da177e4SLinus Torvalds  *	We move the socket address to kernel space before we call
14671da177e4SLinus Torvalds  *	the protocol layer (having also checked the address is ok).
14681da177e4SLinus Torvalds  */
14691da177e4SLinus Torvalds 
1470a87d35d8SDominik Brodowski int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)
14711da177e4SLinus Torvalds {
14721da177e4SLinus Torvalds 	struct socket *sock;
1473230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
14746cb153caSBenjamin LaHaise 	int err, fput_needed;
14751da177e4SLinus Torvalds 
147689bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
147789bddce5SStephen Hemminger 	if (sock) {
147843db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(umyaddr, addrlen, &address);
147989bddce5SStephen Hemminger 		if (err >= 0) {
148089bddce5SStephen Hemminger 			err = security_socket_bind(sock,
1481230b1839SYOSHIFUJI Hideaki 						   (struct sockaddr *)&address,
148289bddce5SStephen Hemminger 						   addrlen);
14836cb153caSBenjamin LaHaise 			if (!err)
14846cb153caSBenjamin LaHaise 				err = sock->ops->bind(sock,
148589bddce5SStephen Hemminger 						      (struct sockaddr *)
1486230b1839SYOSHIFUJI Hideaki 						      &address, addrlen);
14871da177e4SLinus Torvalds 		}
14886cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
14891da177e4SLinus Torvalds 	}
14901da177e4SLinus Torvalds 	return err;
14911da177e4SLinus Torvalds }
14921da177e4SLinus Torvalds 
1493a87d35d8SDominik Brodowski SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
1494a87d35d8SDominik Brodowski {
1495a87d35d8SDominik Brodowski 	return __sys_bind(fd, umyaddr, addrlen);
1496a87d35d8SDominik Brodowski }
1497a87d35d8SDominik Brodowski 
14981da177e4SLinus Torvalds /*
14991da177e4SLinus Torvalds  *	Perform a listen. Basically, we allow the protocol to do anything
15001da177e4SLinus Torvalds  *	necessary for a listen, and if that works, we mark the socket as
15011da177e4SLinus Torvalds  *	ready for listening.
15021da177e4SLinus Torvalds  */
15031da177e4SLinus Torvalds 
150425e290eeSDominik Brodowski int __sys_listen(int fd, int backlog)
15051da177e4SLinus Torvalds {
15061da177e4SLinus Torvalds 	struct socket *sock;
15076cb153caSBenjamin LaHaise 	int err, fput_needed;
1508b8e1f9b5SPavel Emelyanov 	int somaxconn;
15091da177e4SLinus Torvalds 
151089bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
151189bddce5SStephen Hemminger 	if (sock) {
15128efa6e93SPavel Emelyanov 		somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
151395c96174SEric Dumazet 		if ((unsigned int)backlog > somaxconn)
1514b8e1f9b5SPavel Emelyanov 			backlog = somaxconn;
15151da177e4SLinus Torvalds 
15161da177e4SLinus Torvalds 		err = security_socket_listen(sock, backlog);
15176cb153caSBenjamin LaHaise 		if (!err)
15181da177e4SLinus Torvalds 			err = sock->ops->listen(sock, backlog);
15196cb153caSBenjamin LaHaise 
15206cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
15211da177e4SLinus Torvalds 	}
15221da177e4SLinus Torvalds 	return err;
15231da177e4SLinus Torvalds }
15241da177e4SLinus Torvalds 
152525e290eeSDominik Brodowski SYSCALL_DEFINE2(listen, int, fd, int, backlog)
152625e290eeSDominik Brodowski {
152725e290eeSDominik Brodowski 	return __sys_listen(fd, backlog);
152825e290eeSDominik Brodowski }
152925e290eeSDominik Brodowski 
15301da177e4SLinus Torvalds /*
15311da177e4SLinus Torvalds  *	For accept, we attempt to create a new socket, set up the link
15321da177e4SLinus Torvalds  *	with the client, wake up the client, then return the new
15331da177e4SLinus Torvalds  *	connected fd. We collect the address of the connector in kernel
15341da177e4SLinus Torvalds  *	space and move it to user at the very end. This is unclean because
15351da177e4SLinus Torvalds  *	we open the socket then return an error.
15361da177e4SLinus Torvalds  *
15371da177e4SLinus Torvalds  *	1003.1g adds the ability to recvmsg() to query connection pending
15381da177e4SLinus Torvalds  *	status to recvmsg. We need to add that support in a way thats
15391da177e4SLinus Torvalds  *	clean when we restucture accept also.
15401da177e4SLinus Torvalds  */
15411da177e4SLinus Torvalds 
15424541e805SDominik Brodowski int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
15434541e805SDominik Brodowski 		  int __user *upeer_addrlen, int flags)
15441da177e4SLinus Torvalds {
15451da177e4SLinus Torvalds 	struct socket *sock, *newsock;
154639d8c1b6SDavid S. Miller 	struct file *newfile;
15476cb153caSBenjamin LaHaise 	int err, len, newfd, fput_needed;
1548230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
15491da177e4SLinus Torvalds 
155077d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1551aaca0bdcSUlrich Drepper 		return -EINVAL;
1552aaca0bdcSUlrich Drepper 
1553aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1554aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1555aaca0bdcSUlrich Drepper 
15566cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
15571da177e4SLinus Torvalds 	if (!sock)
15581da177e4SLinus Torvalds 		goto out;
15591da177e4SLinus Torvalds 
15601da177e4SLinus Torvalds 	err = -ENFILE;
1561c6d409cfSEric Dumazet 	newsock = sock_alloc();
1562c6d409cfSEric Dumazet 	if (!newsock)
15631da177e4SLinus Torvalds 		goto out_put;
15641da177e4SLinus Torvalds 
15651da177e4SLinus Torvalds 	newsock->type = sock->type;
15661da177e4SLinus Torvalds 	newsock->ops = sock->ops;
15671da177e4SLinus Torvalds 
15681da177e4SLinus Torvalds 	/*
15691da177e4SLinus Torvalds 	 * We don't need try_module_get here, as the listening socket (sock)
15701da177e4SLinus Torvalds 	 * has the protocol module (sock->ops->owner) held.
15711da177e4SLinus Torvalds 	 */
15721da177e4SLinus Torvalds 	__module_get(newsock->ops->owner);
15731da177e4SLinus Torvalds 
157428407630SAl Viro 	newfd = get_unused_fd_flags(flags);
157539d8c1b6SDavid S. Miller 	if (unlikely(newfd < 0)) {
157639d8c1b6SDavid S. Miller 		err = newfd;
15779a1875e6SDavid S. Miller 		sock_release(newsock);
15789a1875e6SDavid S. Miller 		goto out_put;
157939d8c1b6SDavid S. Miller 	}
1580aab174f0SLinus Torvalds 	newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name);
1581b5ffe634SViresh Kumar 	if (IS_ERR(newfile)) {
158228407630SAl Viro 		err = PTR_ERR(newfile);
158328407630SAl Viro 		put_unused_fd(newfd);
158428407630SAl Viro 		goto out_put;
158528407630SAl Viro 	}
158639d8c1b6SDavid S. Miller 
1587a79af59eSFrank Filz 	err = security_socket_accept(sock, newsock);
1588a79af59eSFrank Filz 	if (err)
158939d8c1b6SDavid S. Miller 		goto out_fd;
1590a79af59eSFrank Filz 
1591cdfbabfbSDavid Howells 	err = sock->ops->accept(sock, newsock, sock->file->f_flags, false);
15921da177e4SLinus Torvalds 	if (err < 0)
159339d8c1b6SDavid S. Miller 		goto out_fd;
15941da177e4SLinus Torvalds 
15951da177e4SLinus Torvalds 	if (upeer_sockaddr) {
1596230b1839SYOSHIFUJI Hideaki 		if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
159789bddce5SStephen Hemminger 					  &len, 2) < 0) {
15981da177e4SLinus Torvalds 			err = -ECONNABORTED;
159939d8c1b6SDavid S. Miller 			goto out_fd;
16001da177e4SLinus Torvalds 		}
160143db362dSMaciej Żenczykowski 		err = move_addr_to_user(&address,
1602230b1839SYOSHIFUJI Hideaki 					len, upeer_sockaddr, upeer_addrlen);
16031da177e4SLinus Torvalds 		if (err < 0)
160439d8c1b6SDavid S. Miller 			goto out_fd;
16051da177e4SLinus Torvalds 	}
16061da177e4SLinus Torvalds 
16071da177e4SLinus Torvalds 	/* File flags are not inherited via accept() unlike another OSes. */
16081da177e4SLinus Torvalds 
160939d8c1b6SDavid S. Miller 	fd_install(newfd, newfile);
161039d8c1b6SDavid S. Miller 	err = newfd;
16111da177e4SLinus Torvalds 
16121da177e4SLinus Torvalds out_put:
16136cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
16141da177e4SLinus Torvalds out:
16151da177e4SLinus Torvalds 	return err;
161639d8c1b6SDavid S. Miller out_fd:
16179606a216SDavid S. Miller 	fput(newfile);
161839d8c1b6SDavid S. Miller 	put_unused_fd(newfd);
16191da177e4SLinus Torvalds 	goto out_put;
16201da177e4SLinus Torvalds }
16211da177e4SLinus Torvalds 
16224541e805SDominik Brodowski SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
16234541e805SDominik Brodowski 		int __user *, upeer_addrlen, int, flags)
16244541e805SDominik Brodowski {
16254541e805SDominik Brodowski 	return __sys_accept4(fd, upeer_sockaddr, upeer_addrlen, flags);
16264541e805SDominik Brodowski }
16274541e805SDominik Brodowski 
162820f37034SHeiko Carstens SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,
162920f37034SHeiko Carstens 		int __user *, upeer_addrlen)
1630aaca0bdcSUlrich Drepper {
16314541e805SDominik Brodowski 	return __sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0);
1632aaca0bdcSUlrich Drepper }
1633aaca0bdcSUlrich Drepper 
16341da177e4SLinus Torvalds /*
16351da177e4SLinus Torvalds  *	Attempt to connect to a socket with the server address.  The address
16361da177e4SLinus Torvalds  *	is in user space so we verify it is OK and move it to kernel space.
16371da177e4SLinus Torvalds  *
16381da177e4SLinus Torvalds  *	For 1003.1g we need to add clean support for a bind to AF_UNSPEC to
16391da177e4SLinus Torvalds  *	break bindings
16401da177e4SLinus Torvalds  *
16411da177e4SLinus Torvalds  *	NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and
16421da177e4SLinus Torvalds  *	other SEQPACKET protocols that take time to connect() as it doesn't
16431da177e4SLinus Torvalds  *	include the -EINPROGRESS status for such sockets.
16441da177e4SLinus Torvalds  */
16451da177e4SLinus Torvalds 
16461387c2c2SDominik Brodowski int __sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen)
16471da177e4SLinus Torvalds {
16481da177e4SLinus Torvalds 	struct socket *sock;
1649230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16506cb153caSBenjamin LaHaise 	int err, fput_needed;
16511da177e4SLinus Torvalds 
16526cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
16531da177e4SLinus Torvalds 	if (!sock)
16541da177e4SLinus Torvalds 		goto out;
165543db362dSMaciej Żenczykowski 	err = move_addr_to_kernel(uservaddr, addrlen, &address);
16561da177e4SLinus Torvalds 	if (err < 0)
16571da177e4SLinus Torvalds 		goto out_put;
16581da177e4SLinus Torvalds 
165989bddce5SStephen Hemminger 	err =
1660230b1839SYOSHIFUJI Hideaki 	    security_socket_connect(sock, (struct sockaddr *)&address, addrlen);
16611da177e4SLinus Torvalds 	if (err)
16621da177e4SLinus Torvalds 		goto out_put;
16631da177e4SLinus Torvalds 
1664230b1839SYOSHIFUJI Hideaki 	err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,
16651da177e4SLinus Torvalds 				 sock->file->f_flags);
16661da177e4SLinus Torvalds out_put:
16676cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
16681da177e4SLinus Torvalds out:
16691da177e4SLinus Torvalds 	return err;
16701da177e4SLinus Torvalds }
16711da177e4SLinus Torvalds 
16721387c2c2SDominik Brodowski SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
16731387c2c2SDominik Brodowski 		int, addrlen)
16741387c2c2SDominik Brodowski {
16751387c2c2SDominik Brodowski 	return __sys_connect(fd, uservaddr, addrlen);
16761387c2c2SDominik Brodowski }
16771387c2c2SDominik Brodowski 
16781da177e4SLinus Torvalds /*
16791da177e4SLinus Torvalds  *	Get the local address ('name') of a socket object. Move the obtained
16801da177e4SLinus Torvalds  *	name to user space.
16811da177e4SLinus Torvalds  */
16821da177e4SLinus Torvalds 
16838882a107SDominik Brodowski int __sys_getsockname(int fd, struct sockaddr __user *usockaddr,
16848882a107SDominik Brodowski 		      int __user *usockaddr_len)
16851da177e4SLinus Torvalds {
16861da177e4SLinus Torvalds 	struct socket *sock;
1687230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16886cb153caSBenjamin LaHaise 	int len, err, fput_needed;
16891da177e4SLinus Torvalds 
16906cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
16911da177e4SLinus Torvalds 	if (!sock)
16921da177e4SLinus Torvalds 		goto out;
16931da177e4SLinus Torvalds 
16941da177e4SLinus Torvalds 	err = security_socket_getsockname(sock);
16951da177e4SLinus Torvalds 	if (err)
16961da177e4SLinus Torvalds 		goto out_put;
16971da177e4SLinus Torvalds 
1698230b1839SYOSHIFUJI Hideaki 	err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0);
16991da177e4SLinus Torvalds 	if (err)
17001da177e4SLinus Torvalds 		goto out_put;
170143db362dSMaciej Żenczykowski 	err = move_addr_to_user(&address, len, usockaddr, usockaddr_len);
17021da177e4SLinus Torvalds 
17031da177e4SLinus Torvalds out_put:
17046cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
17051da177e4SLinus Torvalds out:
17061da177e4SLinus Torvalds 	return err;
17071da177e4SLinus Torvalds }
17081da177e4SLinus Torvalds 
17098882a107SDominik Brodowski SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
17108882a107SDominik Brodowski 		int __user *, usockaddr_len)
17118882a107SDominik Brodowski {
17128882a107SDominik Brodowski 	return __sys_getsockname(fd, usockaddr, usockaddr_len);
17138882a107SDominik Brodowski }
17148882a107SDominik Brodowski 
17151da177e4SLinus Torvalds /*
17161da177e4SLinus Torvalds  *	Get the remote address ('name') of a socket object. Move the obtained
17171da177e4SLinus Torvalds  *	name to user space.
17181da177e4SLinus Torvalds  */
17191da177e4SLinus Torvalds 
1720b21c8f83SDominik Brodowski int __sys_getpeername(int fd, struct sockaddr __user *usockaddr,
1721b21c8f83SDominik Brodowski 		      int __user *usockaddr_len)
17221da177e4SLinus Torvalds {
17231da177e4SLinus Torvalds 	struct socket *sock;
1724230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
17256cb153caSBenjamin LaHaise 	int len, err, fput_needed;
17261da177e4SLinus Torvalds 
172789bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
172889bddce5SStephen Hemminger 	if (sock != NULL) {
17291da177e4SLinus Torvalds 		err = security_socket_getpeername(sock);
17301da177e4SLinus Torvalds 		if (err) {
17316cb153caSBenjamin LaHaise 			fput_light(sock->file, fput_needed);
17321da177e4SLinus Torvalds 			return err;
17331da177e4SLinus Torvalds 		}
17341da177e4SLinus Torvalds 
173589bddce5SStephen Hemminger 		err =
1736230b1839SYOSHIFUJI Hideaki 		    sock->ops->getname(sock, (struct sockaddr *)&address, &len,
173789bddce5SStephen Hemminger 				       1);
17381da177e4SLinus Torvalds 		if (!err)
173943db362dSMaciej Żenczykowski 			err = move_addr_to_user(&address, len, usockaddr,
174089bddce5SStephen Hemminger 						usockaddr_len);
17416cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
17421da177e4SLinus Torvalds 	}
17431da177e4SLinus Torvalds 	return err;
17441da177e4SLinus Torvalds }
17451da177e4SLinus Torvalds 
1746b21c8f83SDominik Brodowski SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
1747b21c8f83SDominik Brodowski 		int __user *, usockaddr_len)
1748b21c8f83SDominik Brodowski {
1749b21c8f83SDominik Brodowski 	return __sys_getpeername(fd, usockaddr, usockaddr_len);
1750b21c8f83SDominik Brodowski }
1751b21c8f83SDominik Brodowski 
17521da177e4SLinus Torvalds /*
17531da177e4SLinus Torvalds  *	Send a datagram to a given address. We move the address into kernel
17541da177e4SLinus Torvalds  *	space and check the user space data area is readable before invoking
17551da177e4SLinus Torvalds  *	the protocol.
17561da177e4SLinus Torvalds  */
1757211b634bSDominik Brodowski int __sys_sendto(int fd, void __user *buff, size_t len, unsigned int flags,
1758211b634bSDominik Brodowski 		 struct sockaddr __user *addr,  int addr_len)
17591da177e4SLinus Torvalds {
17601da177e4SLinus Torvalds 	struct socket *sock;
1761230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
17621da177e4SLinus Torvalds 	int err;
17631da177e4SLinus Torvalds 	struct msghdr msg;
17641da177e4SLinus Torvalds 	struct iovec iov;
17656cb153caSBenjamin LaHaise 	int fput_needed;
17661da177e4SLinus Torvalds 
1767602bd0e9SAl Viro 	err = import_single_range(WRITE, buff, len, &iov, &msg.msg_iter);
1768602bd0e9SAl Viro 	if (unlikely(err))
1769602bd0e9SAl Viro 		return err;
1770de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1771de0fa95cSPavel Emelyanov 	if (!sock)
17724387ff75SDavid S. Miller 		goto out;
17736cb153caSBenjamin LaHaise 
17741da177e4SLinus Torvalds 	msg.msg_name = NULL;
17751da177e4SLinus Torvalds 	msg.msg_control = NULL;
17761da177e4SLinus Torvalds 	msg.msg_controllen = 0;
17771da177e4SLinus Torvalds 	msg.msg_namelen = 0;
17786cb153caSBenjamin LaHaise 	if (addr) {
177943db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(addr, addr_len, &address);
17801da177e4SLinus Torvalds 		if (err < 0)
17811da177e4SLinus Torvalds 			goto out_put;
1782230b1839SYOSHIFUJI Hideaki 		msg.msg_name = (struct sockaddr *)&address;
17831da177e4SLinus Torvalds 		msg.msg_namelen = addr_len;
17841da177e4SLinus Torvalds 	}
17851da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
17861da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
17871da177e4SLinus Torvalds 	msg.msg_flags = flags;
1788d8725c86SAl Viro 	err = sock_sendmsg(sock, &msg);
17891da177e4SLinus Torvalds 
17901da177e4SLinus Torvalds out_put:
1791de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
17924387ff75SDavid S. Miller out:
17931da177e4SLinus Torvalds 	return err;
17941da177e4SLinus Torvalds }
17951da177e4SLinus Torvalds 
1796211b634bSDominik Brodowski SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
1797211b634bSDominik Brodowski 		unsigned int, flags, struct sockaddr __user *, addr,
1798211b634bSDominik Brodowski 		int, addr_len)
1799211b634bSDominik Brodowski {
1800211b634bSDominik Brodowski 	return __sys_sendto(fd, buff, len, flags, addr, addr_len);
1801211b634bSDominik Brodowski }
1802211b634bSDominik Brodowski 
18031da177e4SLinus Torvalds /*
18041da177e4SLinus Torvalds  *	Send a datagram down a socket.
18051da177e4SLinus Torvalds  */
18061da177e4SLinus Torvalds 
18073e0fa65fSHeiko Carstens SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len,
180895c96174SEric Dumazet 		unsigned int, flags)
18091da177e4SLinus Torvalds {
1810211b634bSDominik Brodowski 	return __sys_sendto(fd, buff, len, flags, NULL, 0);
18111da177e4SLinus Torvalds }
18121da177e4SLinus Torvalds 
18131da177e4SLinus Torvalds /*
18141da177e4SLinus Torvalds  *	Receive a frame from the socket and optionally record the address of the
18151da177e4SLinus Torvalds  *	sender. We verify the buffers are writable and if needed move the
18161da177e4SLinus Torvalds  *	sender address from kernel to user space.
18171da177e4SLinus Torvalds  */
18187a09e1ebSDominik Brodowski int __sys_recvfrom(int fd, void __user *ubuf, size_t size, unsigned int flags,
18197a09e1ebSDominik Brodowski 		   struct sockaddr __user *addr, int __user *addr_len)
18201da177e4SLinus Torvalds {
18211da177e4SLinus Torvalds 	struct socket *sock;
18221da177e4SLinus Torvalds 	struct iovec iov;
18231da177e4SLinus Torvalds 	struct msghdr msg;
1824230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
18251da177e4SLinus Torvalds 	int err, err2;
18266cb153caSBenjamin LaHaise 	int fput_needed;
18271da177e4SLinus Torvalds 
1828602bd0e9SAl Viro 	err = import_single_range(READ, ubuf, size, &iov, &msg.msg_iter);
1829602bd0e9SAl Viro 	if (unlikely(err))
1830602bd0e9SAl Viro 		return err;
1831de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
18321da177e4SLinus Torvalds 	if (!sock)
1833de0fa95cSPavel Emelyanov 		goto out;
18341da177e4SLinus Torvalds 
18351da177e4SLinus Torvalds 	msg.msg_control = NULL;
18361da177e4SLinus Torvalds 	msg.msg_controllen = 0;
1837f3d33426SHannes Frederic Sowa 	/* Save some cycles and don't copy the address if not needed */
1838f3d33426SHannes Frederic Sowa 	msg.msg_name = addr ? (struct sockaddr *)&address : NULL;
1839f3d33426SHannes Frederic Sowa 	/* We assume all kernel code knows the size of sockaddr_storage */
1840f3d33426SHannes Frederic Sowa 	msg.msg_namelen = 0;
1841130ed5d1Stadeusz.struk@intel.com 	msg.msg_iocb = NULL;
18429f138fa6SAlexander Potapenko 	msg.msg_flags = 0;
18431da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
18441da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
18452da62906SAl Viro 	err = sock_recvmsg(sock, &msg, flags);
18461da177e4SLinus Torvalds 
184789bddce5SStephen Hemminger 	if (err >= 0 && addr != NULL) {
184843db362dSMaciej Żenczykowski 		err2 = move_addr_to_user(&address,
1849230b1839SYOSHIFUJI Hideaki 					 msg.msg_namelen, addr, addr_len);
18501da177e4SLinus Torvalds 		if (err2 < 0)
18511da177e4SLinus Torvalds 			err = err2;
18521da177e4SLinus Torvalds 	}
1853de0fa95cSPavel Emelyanov 
1854de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
18554387ff75SDavid S. Miller out:
18561da177e4SLinus Torvalds 	return err;
18571da177e4SLinus Torvalds }
18581da177e4SLinus Torvalds 
18597a09e1ebSDominik Brodowski SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
18607a09e1ebSDominik Brodowski 		unsigned int, flags, struct sockaddr __user *, addr,
18617a09e1ebSDominik Brodowski 		int __user *, addr_len)
18627a09e1ebSDominik Brodowski {
18637a09e1ebSDominik Brodowski 	return __sys_recvfrom(fd, ubuf, size, flags, addr, addr_len);
18647a09e1ebSDominik Brodowski }
18657a09e1ebSDominik Brodowski 
18661da177e4SLinus Torvalds /*
18671da177e4SLinus Torvalds  *	Receive a datagram from a socket.
18681da177e4SLinus Torvalds  */
18691da177e4SLinus Torvalds 
1870b7c0ddf5SJan Glauber SYSCALL_DEFINE4(recv, int, fd, void __user *, ubuf, size_t, size,
1871b7c0ddf5SJan Glauber 		unsigned int, flags)
18721da177e4SLinus Torvalds {
18737a09e1ebSDominik Brodowski 	return __sys_recvfrom(fd, ubuf, size, flags, NULL, NULL);
18741da177e4SLinus Torvalds }
18751da177e4SLinus Torvalds 
18761da177e4SLinus Torvalds /*
18771da177e4SLinus Torvalds  *	Set a socket option. Because we don't know the option lengths we have
18781da177e4SLinus Torvalds  *	to pass the user mode parameter for the protocols to sort out.
18791da177e4SLinus Torvalds  */
18801da177e4SLinus Torvalds 
188120f37034SHeiko Carstens SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
188220f37034SHeiko Carstens 		char __user *, optval, int, optlen)
18831da177e4SLinus Torvalds {
18846cb153caSBenjamin LaHaise 	int err, fput_needed;
18851da177e4SLinus Torvalds 	struct socket *sock;
18861da177e4SLinus Torvalds 
18871da177e4SLinus Torvalds 	if (optlen < 0)
18881da177e4SLinus Torvalds 		return -EINVAL;
18891da177e4SLinus Torvalds 
189089bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
189189bddce5SStephen Hemminger 	if (sock != NULL) {
18921da177e4SLinus Torvalds 		err = security_socket_setsockopt(sock, level, optname);
18936cb153caSBenjamin LaHaise 		if (err)
18946cb153caSBenjamin LaHaise 			goto out_put;
18951da177e4SLinus Torvalds 
18961da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
189789bddce5SStephen Hemminger 			err =
189889bddce5SStephen Hemminger 			    sock_setsockopt(sock, level, optname, optval,
189989bddce5SStephen Hemminger 					    optlen);
19001da177e4SLinus Torvalds 		else
190189bddce5SStephen Hemminger 			err =
190289bddce5SStephen Hemminger 			    sock->ops->setsockopt(sock, level, optname, optval,
190389bddce5SStephen Hemminger 						  optlen);
19046cb153caSBenjamin LaHaise out_put:
19056cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
19061da177e4SLinus Torvalds 	}
19071da177e4SLinus Torvalds 	return err;
19081da177e4SLinus Torvalds }
19091da177e4SLinus Torvalds 
19101da177e4SLinus Torvalds /*
19111da177e4SLinus Torvalds  *	Get a socket option. Because we don't know the option lengths we have
19121da177e4SLinus Torvalds  *	to pass a user mode parameter for the protocols to sort out.
19131da177e4SLinus Torvalds  */
19141da177e4SLinus Torvalds 
191520f37034SHeiko Carstens SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
191620f37034SHeiko Carstens 		char __user *, optval, int __user *, optlen)
19171da177e4SLinus Torvalds {
19186cb153caSBenjamin LaHaise 	int err, fput_needed;
19191da177e4SLinus Torvalds 	struct socket *sock;
19201da177e4SLinus Torvalds 
192189bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
192289bddce5SStephen Hemminger 	if (sock != NULL) {
19236cb153caSBenjamin LaHaise 		err = security_socket_getsockopt(sock, level, optname);
19246cb153caSBenjamin LaHaise 		if (err)
19256cb153caSBenjamin LaHaise 			goto out_put;
19261da177e4SLinus Torvalds 
19271da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
192889bddce5SStephen Hemminger 			err =
192989bddce5SStephen Hemminger 			    sock_getsockopt(sock, level, optname, optval,
193089bddce5SStephen Hemminger 					    optlen);
19311da177e4SLinus Torvalds 		else
193289bddce5SStephen Hemminger 			err =
193389bddce5SStephen Hemminger 			    sock->ops->getsockopt(sock, level, optname, optval,
193489bddce5SStephen Hemminger 						  optlen);
19356cb153caSBenjamin LaHaise out_put:
19366cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
19371da177e4SLinus Torvalds 	}
19381da177e4SLinus Torvalds 	return err;
19391da177e4SLinus Torvalds }
19401da177e4SLinus Torvalds 
19411da177e4SLinus Torvalds /*
19421da177e4SLinus Torvalds  *	Shutdown a socket.
19431da177e4SLinus Torvalds  */
19441da177e4SLinus Torvalds 
1945005a1aeaSDominik Brodowski int __sys_shutdown(int fd, int how)
19461da177e4SLinus Torvalds {
19476cb153caSBenjamin LaHaise 	int err, fput_needed;
19481da177e4SLinus Torvalds 	struct socket *sock;
19491da177e4SLinus Torvalds 
195089bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
195189bddce5SStephen Hemminger 	if (sock != NULL) {
19521da177e4SLinus Torvalds 		err = security_socket_shutdown(sock, how);
19536cb153caSBenjamin LaHaise 		if (!err)
19541da177e4SLinus Torvalds 			err = sock->ops->shutdown(sock, how);
19556cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
19561da177e4SLinus Torvalds 	}
19571da177e4SLinus Torvalds 	return err;
19581da177e4SLinus Torvalds }
19591da177e4SLinus Torvalds 
1960005a1aeaSDominik Brodowski SYSCALL_DEFINE2(shutdown, int, fd, int, how)
1961005a1aeaSDominik Brodowski {
1962005a1aeaSDominik Brodowski 	return __sys_shutdown(fd, how);
1963005a1aeaSDominik Brodowski }
1964005a1aeaSDominik Brodowski 
19651da177e4SLinus Torvalds /* A couple of helpful macros for getting the address of the 32/64 bit
19661da177e4SLinus Torvalds  * fields which are the same type (int / unsigned) on our platforms.
19671da177e4SLinus Torvalds  */
19681da177e4SLinus Torvalds #define COMPAT_MSG(msg, member)	((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member)
19691da177e4SLinus Torvalds #define COMPAT_NAMELEN(msg)	COMPAT_MSG(msg, msg_namelen)
19701da177e4SLinus Torvalds #define COMPAT_FLAGS(msg)	COMPAT_MSG(msg, msg_flags)
19711da177e4SLinus Torvalds 
1972c71d8ebeSTetsuo Handa struct used_address {
1973c71d8ebeSTetsuo Handa 	struct sockaddr_storage name;
1974c71d8ebeSTetsuo Handa 	unsigned int name_len;
1975c71d8ebeSTetsuo Handa };
1976c71d8ebeSTetsuo Handa 
1977da184284SAl Viro static int copy_msghdr_from_user(struct msghdr *kmsg,
197808adb7daSAl Viro 				 struct user_msghdr __user *umsg,
197908adb7daSAl Viro 				 struct sockaddr __user **save_addr,
198008adb7daSAl Viro 				 struct iovec **iov)
19811661bf36SDan Carpenter {
1982ffb07550SAl Viro 	struct user_msghdr msg;
198308adb7daSAl Viro 	ssize_t err;
198408adb7daSAl Viro 
1985ffb07550SAl Viro 	if (copy_from_user(&msg, umsg, sizeof(*umsg)))
19861661bf36SDan Carpenter 		return -EFAULT;
1987dbb490b9SMatthew Leach 
1988864d9664SPaolo Abeni 	kmsg->msg_control = (void __force *)msg.msg_control;
1989ffb07550SAl Viro 	kmsg->msg_controllen = msg.msg_controllen;
1990ffb07550SAl Viro 	kmsg->msg_flags = msg.msg_flags;
1991ffb07550SAl Viro 
1992ffb07550SAl Viro 	kmsg->msg_namelen = msg.msg_namelen;
1993ffb07550SAl Viro 	if (!msg.msg_name)
19946a2a2b3aSAni Sinha 		kmsg->msg_namelen = 0;
19956a2a2b3aSAni Sinha 
1996dbb490b9SMatthew Leach 	if (kmsg->msg_namelen < 0)
1997dbb490b9SMatthew Leach 		return -EINVAL;
1998dbb490b9SMatthew Leach 
19991661bf36SDan Carpenter 	if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
2000db31c55aSDan Carpenter 		kmsg->msg_namelen = sizeof(struct sockaddr_storage);
200108adb7daSAl Viro 
200208adb7daSAl Viro 	if (save_addr)
2003ffb07550SAl Viro 		*save_addr = msg.msg_name;
200408adb7daSAl Viro 
2005ffb07550SAl Viro 	if (msg.msg_name && kmsg->msg_namelen) {
200608adb7daSAl Viro 		if (!save_addr) {
2007864d9664SPaolo Abeni 			err = move_addr_to_kernel(msg.msg_name,
2008864d9664SPaolo Abeni 						  kmsg->msg_namelen,
200908adb7daSAl Viro 						  kmsg->msg_name);
201008adb7daSAl Viro 			if (err < 0)
201108adb7daSAl Viro 				return err;
201208adb7daSAl Viro 		}
201308adb7daSAl Viro 	} else {
201408adb7daSAl Viro 		kmsg->msg_name = NULL;
201508adb7daSAl Viro 		kmsg->msg_namelen = 0;
201608adb7daSAl Viro 	}
201708adb7daSAl Viro 
2018ffb07550SAl Viro 	if (msg.msg_iovlen > UIO_MAXIOV)
201908adb7daSAl Viro 		return -EMSGSIZE;
202008adb7daSAl Viro 
20210345f931Stadeusz.struk@intel.com 	kmsg->msg_iocb = NULL;
20220345f931Stadeusz.struk@intel.com 
2023ffb07550SAl Viro 	return import_iovec(save_addr ? READ : WRITE,
2024ffb07550SAl Viro 			    msg.msg_iov, msg.msg_iovlen,
2025da184284SAl Viro 			    UIO_FASTIOV, iov, &kmsg->msg_iter);
20261661bf36SDan Carpenter }
20271661bf36SDan Carpenter 
2028666547ffSAl Viro static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
202995c96174SEric Dumazet 			 struct msghdr *msg_sys, unsigned int flags,
203028a94d8fSTom Herbert 			 struct used_address *used_address,
203128a94d8fSTom Herbert 			 unsigned int allowed_msghdr_flags)
20321da177e4SLinus Torvalds {
203389bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
203489bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
2035230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
20361da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
2037b9d717a7SAlex Williamson 	unsigned char ctl[sizeof(struct cmsghdr) + 20]
2038846cc123SAmit Kushwaha 				__aligned(sizeof(__kernel_size_t));
2039b9d717a7SAlex Williamson 	/* 20 is size of ipv6_pktinfo */
20401da177e4SLinus Torvalds 	unsigned char *ctl_buf = ctl;
2041d8725c86SAl Viro 	int ctl_len;
204208adb7daSAl Viro 	ssize_t err;
20431da177e4SLinus Torvalds 
204408adb7daSAl Viro 	msg_sys->msg_name = &address;
20451da177e4SLinus Torvalds 
204608449320SAl Viro 	if (MSG_CMSG_COMPAT & flags)
204708adb7daSAl Viro 		err = get_compat_msghdr(msg_sys, msg_compat, NULL, &iov);
204808449320SAl Viro 	else
204908adb7daSAl Viro 		err = copy_msghdr_from_user(msg_sys, msg, NULL, &iov);
20501da177e4SLinus Torvalds 	if (err < 0)
2051da184284SAl Viro 		return err;
20521da177e4SLinus Torvalds 
20531da177e4SLinus Torvalds 	err = -ENOBUFS;
20541da177e4SLinus Torvalds 
2055228e548eSAnton Blanchard 	if (msg_sys->msg_controllen > INT_MAX)
20561da177e4SLinus Torvalds 		goto out_freeiov;
205728a94d8fSTom Herbert 	flags |= (msg_sys->msg_flags & allowed_msghdr_flags);
2058228e548eSAnton Blanchard 	ctl_len = msg_sys->msg_controllen;
20591da177e4SLinus Torvalds 	if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
206089bddce5SStephen Hemminger 		err =
2061228e548eSAnton Blanchard 		    cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl,
206289bddce5SStephen Hemminger 						     sizeof(ctl));
20631da177e4SLinus Torvalds 		if (err)
20641da177e4SLinus Torvalds 			goto out_freeiov;
2065228e548eSAnton Blanchard 		ctl_buf = msg_sys->msg_control;
2066228e548eSAnton Blanchard 		ctl_len = msg_sys->msg_controllen;
20671da177e4SLinus Torvalds 	} else if (ctl_len) {
2068ac4340fcSDavid S. Miller 		BUILD_BUG_ON(sizeof(struct cmsghdr) !=
2069ac4340fcSDavid S. Miller 			     CMSG_ALIGN(sizeof(struct cmsghdr)));
207089bddce5SStephen Hemminger 		if (ctl_len > sizeof(ctl)) {
20711da177e4SLinus Torvalds 			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
20721da177e4SLinus Torvalds 			if (ctl_buf == NULL)
20731da177e4SLinus Torvalds 				goto out_freeiov;
20741da177e4SLinus Torvalds 		}
20751da177e4SLinus Torvalds 		err = -EFAULT;
20761da177e4SLinus Torvalds 		/*
2077228e548eSAnton Blanchard 		 * Careful! Before this, msg_sys->msg_control contains a user pointer.
20781da177e4SLinus Torvalds 		 * Afterwards, it will be a kernel pointer. Thus the compiler-assisted
20791da177e4SLinus Torvalds 		 * checking falls down on this.
20801da177e4SLinus Torvalds 		 */
2081fb8621bbSNamhyung Kim 		if (copy_from_user(ctl_buf,
2082228e548eSAnton Blanchard 				   (void __user __force *)msg_sys->msg_control,
208389bddce5SStephen Hemminger 				   ctl_len))
20841da177e4SLinus Torvalds 			goto out_freectl;
2085228e548eSAnton Blanchard 		msg_sys->msg_control = ctl_buf;
20861da177e4SLinus Torvalds 	}
2087228e548eSAnton Blanchard 	msg_sys->msg_flags = flags;
20881da177e4SLinus Torvalds 
20891da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
2090228e548eSAnton Blanchard 		msg_sys->msg_flags |= MSG_DONTWAIT;
2091c71d8ebeSTetsuo Handa 	/*
2092c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and current destination address is same as
2093c71d8ebeSTetsuo Handa 	 * previously succeeded address, omit asking LSM's decision.
2094c71d8ebeSTetsuo Handa 	 * used_address->name_len is initialized to UINT_MAX so that the first
2095c71d8ebeSTetsuo Handa 	 * destination address never matches.
2096c71d8ebeSTetsuo Handa 	 */
2097bc909d9dSMathieu Desnoyers 	if (used_address && msg_sys->msg_name &&
2098bc909d9dSMathieu Desnoyers 	    used_address->name_len == msg_sys->msg_namelen &&
2099bc909d9dSMathieu Desnoyers 	    !memcmp(&used_address->name, msg_sys->msg_name,
2100c71d8ebeSTetsuo Handa 		    used_address->name_len)) {
2101d8725c86SAl Viro 		err = sock_sendmsg_nosec(sock, msg_sys);
2102c71d8ebeSTetsuo Handa 		goto out_freectl;
2103c71d8ebeSTetsuo Handa 	}
2104d8725c86SAl Viro 	err = sock_sendmsg(sock, msg_sys);
2105c71d8ebeSTetsuo Handa 	/*
2106c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and sending to current destination address was
2107c71d8ebeSTetsuo Handa 	 * successful, remember it.
2108c71d8ebeSTetsuo Handa 	 */
2109c71d8ebeSTetsuo Handa 	if (used_address && err >= 0) {
2110c71d8ebeSTetsuo Handa 		used_address->name_len = msg_sys->msg_namelen;
2111bc909d9dSMathieu Desnoyers 		if (msg_sys->msg_name)
2112bc909d9dSMathieu Desnoyers 			memcpy(&used_address->name, msg_sys->msg_name,
2113c71d8ebeSTetsuo Handa 			       used_address->name_len);
2114c71d8ebeSTetsuo Handa 	}
21151da177e4SLinus Torvalds 
21161da177e4SLinus Torvalds out_freectl:
21171da177e4SLinus Torvalds 	if (ctl_buf != ctl)
21181da177e4SLinus Torvalds 		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
21191da177e4SLinus Torvalds out_freeiov:
2120a74e9106SEric Dumazet 	kfree(iov);
2121228e548eSAnton Blanchard 	return err;
2122228e548eSAnton Blanchard }
2123228e548eSAnton Blanchard 
2124228e548eSAnton Blanchard /*
2125228e548eSAnton Blanchard  *	BSD sendmsg interface
2126228e548eSAnton Blanchard  */
2127228e548eSAnton Blanchard 
2128666547ffSAl Viro long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned flags)
2129228e548eSAnton Blanchard {
2130228e548eSAnton Blanchard 	int fput_needed, err;
2131228e548eSAnton Blanchard 	struct msghdr msg_sys;
21321be374a0SAndy Lutomirski 	struct socket *sock;
2133228e548eSAnton Blanchard 
21341be374a0SAndy Lutomirski 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2135228e548eSAnton Blanchard 	if (!sock)
2136228e548eSAnton Blanchard 		goto out;
2137228e548eSAnton Blanchard 
213828a94d8fSTom Herbert 	err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL, 0);
2139228e548eSAnton Blanchard 
21406cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
21411da177e4SLinus Torvalds out:
21421da177e4SLinus Torvalds 	return err;
21431da177e4SLinus Torvalds }
21441da177e4SLinus Torvalds 
2145666547ffSAl Viro SYSCALL_DEFINE3(sendmsg, int, fd, struct user_msghdr __user *, msg, unsigned int, flags)
2146a7526eb5SAndy Lutomirski {
2147a7526eb5SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
2148a7526eb5SAndy Lutomirski 		return -EINVAL;
2149a7526eb5SAndy Lutomirski 	return __sys_sendmsg(fd, msg, flags);
2150a7526eb5SAndy Lutomirski }
2151a7526eb5SAndy Lutomirski 
2152228e548eSAnton Blanchard /*
2153228e548eSAnton Blanchard  *	Linux sendmmsg interface
2154228e548eSAnton Blanchard  */
2155228e548eSAnton Blanchard 
2156228e548eSAnton Blanchard int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2157228e548eSAnton Blanchard 		   unsigned int flags)
2158228e548eSAnton Blanchard {
2159228e548eSAnton Blanchard 	int fput_needed, err, datagrams;
2160228e548eSAnton Blanchard 	struct socket *sock;
2161228e548eSAnton Blanchard 	struct mmsghdr __user *entry;
2162228e548eSAnton Blanchard 	struct compat_mmsghdr __user *compat_entry;
2163228e548eSAnton Blanchard 	struct msghdr msg_sys;
2164c71d8ebeSTetsuo Handa 	struct used_address used_address;
2165f092276dSTom Herbert 	unsigned int oflags = flags;
2166228e548eSAnton Blanchard 
216798382f41SAnton Blanchard 	if (vlen > UIO_MAXIOV)
216898382f41SAnton Blanchard 		vlen = UIO_MAXIOV;
2169228e548eSAnton Blanchard 
2170228e548eSAnton Blanchard 	datagrams = 0;
2171228e548eSAnton Blanchard 
2172228e548eSAnton Blanchard 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2173228e548eSAnton Blanchard 	if (!sock)
2174228e548eSAnton Blanchard 		return err;
2175228e548eSAnton Blanchard 
2176c71d8ebeSTetsuo Handa 	used_address.name_len = UINT_MAX;
2177228e548eSAnton Blanchard 	entry = mmsg;
2178228e548eSAnton Blanchard 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2179728ffb86SAnton Blanchard 	err = 0;
2180f092276dSTom Herbert 	flags |= MSG_BATCH;
2181228e548eSAnton Blanchard 
2182228e548eSAnton Blanchard 	while (datagrams < vlen) {
2183f092276dSTom Herbert 		if (datagrams == vlen - 1)
2184f092276dSTom Herbert 			flags = oflags;
2185f092276dSTom Herbert 
2186228e548eSAnton Blanchard 		if (MSG_CMSG_COMPAT & flags) {
2187666547ffSAl Viro 			err = ___sys_sendmsg(sock, (struct user_msghdr __user *)compat_entry,
218828a94d8fSTom Herbert 					     &msg_sys, flags, &used_address, MSG_EOR);
2189228e548eSAnton Blanchard 			if (err < 0)
2190228e548eSAnton Blanchard 				break;
2191228e548eSAnton Blanchard 			err = __put_user(err, &compat_entry->msg_len);
2192228e548eSAnton Blanchard 			++compat_entry;
2193228e548eSAnton Blanchard 		} else {
2194a7526eb5SAndy Lutomirski 			err = ___sys_sendmsg(sock,
2195666547ffSAl Viro 					     (struct user_msghdr __user *)entry,
219628a94d8fSTom Herbert 					     &msg_sys, flags, &used_address, MSG_EOR);
2197228e548eSAnton Blanchard 			if (err < 0)
2198228e548eSAnton Blanchard 				break;
2199228e548eSAnton Blanchard 			err = put_user(err, &entry->msg_len);
2200228e548eSAnton Blanchard 			++entry;
2201228e548eSAnton Blanchard 		}
2202228e548eSAnton Blanchard 
2203228e548eSAnton Blanchard 		if (err)
2204228e548eSAnton Blanchard 			break;
2205228e548eSAnton Blanchard 		++datagrams;
22063023898bSSoheil Hassas Yeganeh 		if (msg_data_left(&msg_sys))
22073023898bSSoheil Hassas Yeganeh 			break;
2208a78cb84cSEric Dumazet 		cond_resched();
2209228e548eSAnton Blanchard 	}
2210228e548eSAnton Blanchard 
2211228e548eSAnton Blanchard 	fput_light(sock->file, fput_needed);
2212228e548eSAnton Blanchard 
2213728ffb86SAnton Blanchard 	/* We only return an error if no datagrams were able to be sent */
2214728ffb86SAnton Blanchard 	if (datagrams != 0)
2215228e548eSAnton Blanchard 		return datagrams;
2216228e548eSAnton Blanchard 
2217228e548eSAnton Blanchard 	return err;
2218228e548eSAnton Blanchard }
2219228e548eSAnton Blanchard 
2220228e548eSAnton Blanchard SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
2221228e548eSAnton Blanchard 		unsigned int, vlen, unsigned int, flags)
2222228e548eSAnton Blanchard {
22231be374a0SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
22241be374a0SAndy Lutomirski 		return -EINVAL;
2225228e548eSAnton Blanchard 	return __sys_sendmmsg(fd, mmsg, vlen, flags);
2226228e548eSAnton Blanchard }
2227228e548eSAnton Blanchard 
2228666547ffSAl Viro static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg,
222995c96174SEric Dumazet 			 struct msghdr *msg_sys, unsigned int flags, int nosec)
22301da177e4SLinus Torvalds {
223189bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
223289bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
22331da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV];
22341da177e4SLinus Torvalds 	struct iovec *iov = iovstack;
22351da177e4SLinus Torvalds 	unsigned long cmsg_ptr;
22362da62906SAl Viro 	int len;
223708adb7daSAl Viro 	ssize_t err;
22381da177e4SLinus Torvalds 
22391da177e4SLinus Torvalds 	/* kernel mode address */
2240230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage addr;
22411da177e4SLinus Torvalds 
22421da177e4SLinus Torvalds 	/* user mode address pointers */
22431da177e4SLinus Torvalds 	struct sockaddr __user *uaddr;
224408adb7daSAl Viro 	int __user *uaddr_len = COMPAT_NAMELEN(msg);
22451da177e4SLinus Torvalds 
224608adb7daSAl Viro 	msg_sys->msg_name = &addr;
22471da177e4SLinus Torvalds 
2248f3d33426SHannes Frederic Sowa 	if (MSG_CMSG_COMPAT & flags)
224908adb7daSAl Viro 		err = get_compat_msghdr(msg_sys, msg_compat, &uaddr, &iov);
2250f3d33426SHannes Frederic Sowa 	else
225108adb7daSAl Viro 		err = copy_msghdr_from_user(msg_sys, msg, &uaddr, &iov);
22521da177e4SLinus Torvalds 	if (err < 0)
2253da184284SAl Viro 		return err;
22541da177e4SLinus Torvalds 
2255a2e27255SArnaldo Carvalho de Melo 	cmsg_ptr = (unsigned long)msg_sys->msg_control;
2256a2e27255SArnaldo Carvalho de Melo 	msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
22571da177e4SLinus Torvalds 
2258f3d33426SHannes Frederic Sowa 	/* We assume all kernel code knows the size of sockaddr_storage */
2259f3d33426SHannes Frederic Sowa 	msg_sys->msg_namelen = 0;
2260f3d33426SHannes Frederic Sowa 
22611da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
22621da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
22632da62906SAl Viro 	err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys, flags);
22641da177e4SLinus Torvalds 	if (err < 0)
22651da177e4SLinus Torvalds 		goto out_freeiov;
22661da177e4SLinus Torvalds 	len = err;
22671da177e4SLinus Torvalds 
22681da177e4SLinus Torvalds 	if (uaddr != NULL) {
226943db362dSMaciej Żenczykowski 		err = move_addr_to_user(&addr,
2270a2e27255SArnaldo Carvalho de Melo 					msg_sys->msg_namelen, uaddr,
227189bddce5SStephen Hemminger 					uaddr_len);
22721da177e4SLinus Torvalds 		if (err < 0)
22731da177e4SLinus Torvalds 			goto out_freeiov;
22741da177e4SLinus Torvalds 	}
2275a2e27255SArnaldo Carvalho de Melo 	err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
227637f7f421SDavid S. Miller 			 COMPAT_FLAGS(msg));
22771da177e4SLinus Torvalds 	if (err)
22781da177e4SLinus Torvalds 		goto out_freeiov;
22791da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags)
2280a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
22811da177e4SLinus Torvalds 				 &msg_compat->msg_controllen);
22821da177e4SLinus Torvalds 	else
2283a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
22841da177e4SLinus Torvalds 				 &msg->msg_controllen);
22851da177e4SLinus Torvalds 	if (err)
22861da177e4SLinus Torvalds 		goto out_freeiov;
22871da177e4SLinus Torvalds 	err = len;
22881da177e4SLinus Torvalds 
22891da177e4SLinus Torvalds out_freeiov:
2290a74e9106SEric Dumazet 	kfree(iov);
2291a2e27255SArnaldo Carvalho de Melo 	return err;
2292a2e27255SArnaldo Carvalho de Melo }
2293a2e27255SArnaldo Carvalho de Melo 
2294a2e27255SArnaldo Carvalho de Melo /*
2295a2e27255SArnaldo Carvalho de Melo  *	BSD recvmsg interface
2296a2e27255SArnaldo Carvalho de Melo  */
2297a2e27255SArnaldo Carvalho de Melo 
2298666547ffSAl Viro long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned flags)
2299a2e27255SArnaldo Carvalho de Melo {
2300a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err;
2301a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
23021be374a0SAndy Lutomirski 	struct socket *sock;
2303a2e27255SArnaldo Carvalho de Melo 
23041be374a0SAndy Lutomirski 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2305a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2306a2e27255SArnaldo Carvalho de Melo 		goto out;
2307a2e27255SArnaldo Carvalho de Melo 
2308a7526eb5SAndy Lutomirski 	err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0);
2309a2e27255SArnaldo Carvalho de Melo 
23106cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
23111da177e4SLinus Torvalds out:
23121da177e4SLinus Torvalds 	return err;
23131da177e4SLinus Torvalds }
23141da177e4SLinus Torvalds 
2315666547ffSAl Viro SYSCALL_DEFINE3(recvmsg, int, fd, struct user_msghdr __user *, msg,
2316a7526eb5SAndy Lutomirski 		unsigned int, flags)
2317a7526eb5SAndy Lutomirski {
2318a7526eb5SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
2319a7526eb5SAndy Lutomirski 		return -EINVAL;
2320a7526eb5SAndy Lutomirski 	return __sys_recvmsg(fd, msg, flags);
2321a7526eb5SAndy Lutomirski }
2322a7526eb5SAndy Lutomirski 
2323a2e27255SArnaldo Carvalho de Melo /*
2324a2e27255SArnaldo Carvalho de Melo  *     Linux recvmmsg interface
2325a2e27255SArnaldo Carvalho de Melo  */
23261da177e4SLinus Torvalds 
2327a2e27255SArnaldo Carvalho de Melo int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2328a2e27255SArnaldo Carvalho de Melo 		   unsigned int flags, struct timespec *timeout)
2329a2e27255SArnaldo Carvalho de Melo {
2330a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err, datagrams;
2331a2e27255SArnaldo Carvalho de Melo 	struct socket *sock;
2332a2e27255SArnaldo Carvalho de Melo 	struct mmsghdr __user *entry;
2333d7256d0eSJean-Mickael Guerin 	struct compat_mmsghdr __user *compat_entry;
2334a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
2335766b9f92SDeepa Dinamani 	struct timespec64 end_time;
2336766b9f92SDeepa Dinamani 	struct timespec64 timeout64;
2337a2e27255SArnaldo Carvalho de Melo 
2338a2e27255SArnaldo Carvalho de Melo 	if (timeout &&
2339a2e27255SArnaldo Carvalho de Melo 	    poll_select_set_timeout(&end_time, timeout->tv_sec,
2340a2e27255SArnaldo Carvalho de Melo 				    timeout->tv_nsec))
2341a2e27255SArnaldo Carvalho de Melo 		return -EINVAL;
2342a2e27255SArnaldo Carvalho de Melo 
2343a2e27255SArnaldo Carvalho de Melo 	datagrams = 0;
2344a2e27255SArnaldo Carvalho de Melo 
2345a2e27255SArnaldo Carvalho de Melo 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2346a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2347a2e27255SArnaldo Carvalho de Melo 		return err;
2348a2e27255SArnaldo Carvalho de Melo 
2349a2e27255SArnaldo Carvalho de Melo 	err = sock_error(sock->sk);
2350e623a9e9SMaxime Jayat 	if (err) {
2351e623a9e9SMaxime Jayat 		datagrams = err;
2352a2e27255SArnaldo Carvalho de Melo 		goto out_put;
2353e623a9e9SMaxime Jayat 	}
2354a2e27255SArnaldo Carvalho de Melo 
2355a2e27255SArnaldo Carvalho de Melo 	entry = mmsg;
2356d7256d0eSJean-Mickael Guerin 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2357a2e27255SArnaldo Carvalho de Melo 
2358a2e27255SArnaldo Carvalho de Melo 	while (datagrams < vlen) {
2359a2e27255SArnaldo Carvalho de Melo 		/*
2360a2e27255SArnaldo Carvalho de Melo 		 * No need to ask LSM for more than the first datagram.
2361a2e27255SArnaldo Carvalho de Melo 		 */
2362d7256d0eSJean-Mickael Guerin 		if (MSG_CMSG_COMPAT & flags) {
2363666547ffSAl Viro 			err = ___sys_recvmsg(sock, (struct user_msghdr __user *)compat_entry,
2364b9eb8b87SAnton Blanchard 					     &msg_sys, flags & ~MSG_WAITFORONE,
2365b9eb8b87SAnton Blanchard 					     datagrams);
2366d7256d0eSJean-Mickael Guerin 			if (err < 0)
2367d7256d0eSJean-Mickael Guerin 				break;
2368d7256d0eSJean-Mickael Guerin 			err = __put_user(err, &compat_entry->msg_len);
2369d7256d0eSJean-Mickael Guerin 			++compat_entry;
2370d7256d0eSJean-Mickael Guerin 		} else {
2371a7526eb5SAndy Lutomirski 			err = ___sys_recvmsg(sock,
2372666547ffSAl Viro 					     (struct user_msghdr __user *)entry,
2373b9eb8b87SAnton Blanchard 					     &msg_sys, flags & ~MSG_WAITFORONE,
2374b9eb8b87SAnton Blanchard 					     datagrams);
2375a2e27255SArnaldo Carvalho de Melo 			if (err < 0)
2376a2e27255SArnaldo Carvalho de Melo 				break;
2377a2e27255SArnaldo Carvalho de Melo 			err = put_user(err, &entry->msg_len);
2378d7256d0eSJean-Mickael Guerin 			++entry;
2379d7256d0eSJean-Mickael Guerin 		}
2380d7256d0eSJean-Mickael Guerin 
2381a2e27255SArnaldo Carvalho de Melo 		if (err)
2382a2e27255SArnaldo Carvalho de Melo 			break;
2383a2e27255SArnaldo Carvalho de Melo 		++datagrams;
2384a2e27255SArnaldo Carvalho de Melo 
238571c5c159SBrandon L Black 		/* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
238671c5c159SBrandon L Black 		if (flags & MSG_WAITFORONE)
238771c5c159SBrandon L Black 			flags |= MSG_DONTWAIT;
238871c5c159SBrandon L Black 
2389a2e27255SArnaldo Carvalho de Melo 		if (timeout) {
2390766b9f92SDeepa Dinamani 			ktime_get_ts64(&timeout64);
2391766b9f92SDeepa Dinamani 			*timeout = timespec64_to_timespec(
2392766b9f92SDeepa Dinamani 					timespec64_sub(end_time, timeout64));
2393a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_sec < 0) {
2394a2e27255SArnaldo Carvalho de Melo 				timeout->tv_sec = timeout->tv_nsec = 0;
2395a2e27255SArnaldo Carvalho de Melo 				break;
2396a2e27255SArnaldo Carvalho de Melo 			}
2397a2e27255SArnaldo Carvalho de Melo 
2398a2e27255SArnaldo Carvalho de Melo 			/* Timeout, return less than vlen datagrams */
2399a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_nsec == 0 && timeout->tv_sec == 0)
2400a2e27255SArnaldo Carvalho de Melo 				break;
2401a2e27255SArnaldo Carvalho de Melo 		}
2402a2e27255SArnaldo Carvalho de Melo 
2403a2e27255SArnaldo Carvalho de Melo 		/* Out of band data, return right away */
2404a2e27255SArnaldo Carvalho de Melo 		if (msg_sys.msg_flags & MSG_OOB)
2405a2e27255SArnaldo Carvalho de Melo 			break;
2406a78cb84cSEric Dumazet 		cond_resched();
2407a2e27255SArnaldo Carvalho de Melo 	}
2408a2e27255SArnaldo Carvalho de Melo 
2409a2e27255SArnaldo Carvalho de Melo 	if (err == 0)
241034b88a68SArnaldo Carvalho de Melo 		goto out_put;
2411a2e27255SArnaldo Carvalho de Melo 
241234b88a68SArnaldo Carvalho de Melo 	if (datagrams == 0) {
241334b88a68SArnaldo Carvalho de Melo 		datagrams = err;
241434b88a68SArnaldo Carvalho de Melo 		goto out_put;
241534b88a68SArnaldo Carvalho de Melo 	}
241634b88a68SArnaldo Carvalho de Melo 
2417a2e27255SArnaldo Carvalho de Melo 	/*
2418a2e27255SArnaldo Carvalho de Melo 	 * We may return less entries than requested (vlen) if the
2419a2e27255SArnaldo Carvalho de Melo 	 * sock is non block and there aren't enough datagrams...
2420a2e27255SArnaldo Carvalho de Melo 	 */
2421a2e27255SArnaldo Carvalho de Melo 	if (err != -EAGAIN) {
2422a2e27255SArnaldo Carvalho de Melo 		/*
2423a2e27255SArnaldo Carvalho de Melo 		 * ... or  if recvmsg returns an error after we
2424a2e27255SArnaldo Carvalho de Melo 		 * received some datagrams, where we record the
2425a2e27255SArnaldo Carvalho de Melo 		 * error to return on the next call or if the
2426a2e27255SArnaldo Carvalho de Melo 		 * app asks about it using getsockopt(SO_ERROR).
2427a2e27255SArnaldo Carvalho de Melo 		 */
2428a2e27255SArnaldo Carvalho de Melo 		sock->sk->sk_err = -err;
2429a2e27255SArnaldo Carvalho de Melo 	}
243034b88a68SArnaldo Carvalho de Melo out_put:
243134b88a68SArnaldo Carvalho de Melo 	fput_light(sock->file, fput_needed);
2432a2e27255SArnaldo Carvalho de Melo 
2433a2e27255SArnaldo Carvalho de Melo 	return datagrams;
2434a2e27255SArnaldo Carvalho de Melo }
2435a2e27255SArnaldo Carvalho de Melo 
2436a2e27255SArnaldo Carvalho de Melo SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
2437a2e27255SArnaldo Carvalho de Melo 		unsigned int, vlen, unsigned int, flags,
2438a2e27255SArnaldo Carvalho de Melo 		struct timespec __user *, timeout)
2439a2e27255SArnaldo Carvalho de Melo {
2440a2e27255SArnaldo Carvalho de Melo 	int datagrams;
2441a2e27255SArnaldo Carvalho de Melo 	struct timespec timeout_sys;
2442a2e27255SArnaldo Carvalho de Melo 
24431be374a0SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
24441be374a0SAndy Lutomirski 		return -EINVAL;
24451be374a0SAndy Lutomirski 
2446a2e27255SArnaldo Carvalho de Melo 	if (!timeout)
2447a2e27255SArnaldo Carvalho de Melo 		return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL);
2448a2e27255SArnaldo Carvalho de Melo 
2449a2e27255SArnaldo Carvalho de Melo 	if (copy_from_user(&timeout_sys, timeout, sizeof(timeout_sys)))
2450a2e27255SArnaldo Carvalho de Melo 		return -EFAULT;
2451a2e27255SArnaldo Carvalho de Melo 
2452a2e27255SArnaldo Carvalho de Melo 	datagrams = __sys_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys);
2453a2e27255SArnaldo Carvalho de Melo 
2454a2e27255SArnaldo Carvalho de Melo 	if (datagrams > 0 &&
2455a2e27255SArnaldo Carvalho de Melo 	    copy_to_user(timeout, &timeout_sys, sizeof(timeout_sys)))
2456a2e27255SArnaldo Carvalho de Melo 		datagrams = -EFAULT;
2457a2e27255SArnaldo Carvalho de Melo 
2458a2e27255SArnaldo Carvalho de Melo 	return datagrams;
2459a2e27255SArnaldo Carvalho de Melo }
2460a2e27255SArnaldo Carvalho de Melo 
2461a2e27255SArnaldo Carvalho de Melo #ifdef __ARCH_WANT_SYS_SOCKETCALL
24621da177e4SLinus Torvalds /* Argument list sizes for sys_socketcall */
24631da177e4SLinus Torvalds #define AL(x) ((x) * sizeof(unsigned long))
2464228e548eSAnton Blanchard static const unsigned char nargs[21] = {
246589bddce5SStephen Hemminger 	AL(0), AL(3), AL(3), AL(3), AL(2), AL(3),
24661da177e4SLinus Torvalds 	AL(3), AL(3), AL(4), AL(4), AL(4), AL(6),
2467aaca0bdcSUlrich Drepper 	AL(6), AL(2), AL(5), AL(5), AL(3), AL(3),
2468228e548eSAnton Blanchard 	AL(4), AL(5), AL(4)
246989bddce5SStephen Hemminger };
247089bddce5SStephen Hemminger 
24711da177e4SLinus Torvalds #undef AL
24721da177e4SLinus Torvalds 
24731da177e4SLinus Torvalds /*
24741da177e4SLinus Torvalds  *	System call vectors.
24751da177e4SLinus Torvalds  *
24761da177e4SLinus Torvalds  *	Argument checking cleaned up. Saved 20% in size.
24771da177e4SLinus Torvalds  *  This function doesn't need to set the kernel lock because
24781da177e4SLinus Torvalds  *  it is set by the callees.
24791da177e4SLinus Torvalds  */
24801da177e4SLinus Torvalds 
24813e0fa65fSHeiko Carstens SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
24821da177e4SLinus Torvalds {
24832950fa9dSChen Gang 	unsigned long a[AUDITSC_ARGS];
24841da177e4SLinus Torvalds 	unsigned long a0, a1;
24851da177e4SLinus Torvalds 	int err;
248647379052SArjan van de Ven 	unsigned int len;
24871da177e4SLinus Torvalds 
2488228e548eSAnton Blanchard 	if (call < 1 || call > SYS_SENDMMSG)
24891da177e4SLinus Torvalds 		return -EINVAL;
24901da177e4SLinus Torvalds 
249147379052SArjan van de Ven 	len = nargs[call];
249247379052SArjan van de Ven 	if (len > sizeof(a))
249347379052SArjan van de Ven 		return -EINVAL;
249447379052SArjan van de Ven 
24951da177e4SLinus Torvalds 	/* copy_from_user should be SMP safe. */
249647379052SArjan van de Ven 	if (copy_from_user(a, args, len))
24971da177e4SLinus Torvalds 		return -EFAULT;
24981da177e4SLinus Torvalds 
24992950fa9dSChen Gang 	err = audit_socketcall(nargs[call] / sizeof(unsigned long), a);
25002950fa9dSChen Gang 	if (err)
25012950fa9dSChen Gang 		return err;
25023ec3b2fbSDavid Woodhouse 
25031da177e4SLinus Torvalds 	a0 = a[0];
25041da177e4SLinus Torvalds 	a1 = a[1];
25051da177e4SLinus Torvalds 
250689bddce5SStephen Hemminger 	switch (call) {
25071da177e4SLinus Torvalds 	case SYS_SOCKET:
25089d6a15c3SDominik Brodowski 		err = __sys_socket(a0, a1, a[2]);
25091da177e4SLinus Torvalds 		break;
25101da177e4SLinus Torvalds 	case SYS_BIND:
2511a87d35d8SDominik Brodowski 		err = __sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
25121da177e4SLinus Torvalds 		break;
25131da177e4SLinus Torvalds 	case SYS_CONNECT:
25141387c2c2SDominik Brodowski 		err = __sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
25151da177e4SLinus Torvalds 		break;
25161da177e4SLinus Torvalds 	case SYS_LISTEN:
251725e290eeSDominik Brodowski 		err = __sys_listen(a0, a1);
25181da177e4SLinus Torvalds 		break;
25191da177e4SLinus Torvalds 	case SYS_ACCEPT:
25204541e805SDominik Brodowski 		err = __sys_accept4(a0, (struct sockaddr __user *)a1,
2521aaca0bdcSUlrich Drepper 				    (int __user *)a[2], 0);
25221da177e4SLinus Torvalds 		break;
25231da177e4SLinus Torvalds 	case SYS_GETSOCKNAME:
252489bddce5SStephen Hemminger 		err =
25258882a107SDominik Brodowski 		    __sys_getsockname(a0, (struct sockaddr __user *)a1,
252689bddce5SStephen Hemminger 				      (int __user *)a[2]);
25271da177e4SLinus Torvalds 		break;
25281da177e4SLinus Torvalds 	case SYS_GETPEERNAME:
252989bddce5SStephen Hemminger 		err =
2530b21c8f83SDominik Brodowski 		    __sys_getpeername(a0, (struct sockaddr __user *)a1,
253189bddce5SStephen Hemminger 				      (int __user *)a[2]);
25321da177e4SLinus Torvalds 		break;
25331da177e4SLinus Torvalds 	case SYS_SOCKETPAIR:
25346debc8d8SDominik Brodowski 		err = __sys_socketpair(a0, a1, a[2], (int __user *)a[3]);
25351da177e4SLinus Torvalds 		break;
25361da177e4SLinus Torvalds 	case SYS_SEND:
25371da177e4SLinus Torvalds 		err = sys_send(a0, (void __user *)a1, a[2], a[3]);
25381da177e4SLinus Torvalds 		break;
25391da177e4SLinus Torvalds 	case SYS_SENDTO:
2540211b634bSDominik Brodowski 		err = __sys_sendto(a0, (void __user *)a1, a[2], a[3],
25411da177e4SLinus Torvalds 				   (struct sockaddr __user *)a[4], a[5]);
25421da177e4SLinus Torvalds 		break;
25431da177e4SLinus Torvalds 	case SYS_RECV:
25441da177e4SLinus Torvalds 		err = sys_recv(a0, (void __user *)a1, a[2], a[3]);
25451da177e4SLinus Torvalds 		break;
25461da177e4SLinus Torvalds 	case SYS_RECVFROM:
25477a09e1ebSDominik Brodowski 		err = __sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
254889bddce5SStephen Hemminger 				     (struct sockaddr __user *)a[4],
254989bddce5SStephen Hemminger 				     (int __user *)a[5]);
25501da177e4SLinus Torvalds 		break;
25511da177e4SLinus Torvalds 	case SYS_SHUTDOWN:
2552005a1aeaSDominik Brodowski 		err = __sys_shutdown(a0, a1);
25531da177e4SLinus Torvalds 		break;
25541da177e4SLinus Torvalds 	case SYS_SETSOCKOPT:
25551da177e4SLinus Torvalds 		err = sys_setsockopt(a0, a1, a[2], (char __user *)a[3], a[4]);
25561da177e4SLinus Torvalds 		break;
25571da177e4SLinus Torvalds 	case SYS_GETSOCKOPT:
255889bddce5SStephen Hemminger 		err =
255989bddce5SStephen Hemminger 		    sys_getsockopt(a0, a1, a[2], (char __user *)a[3],
256089bddce5SStephen Hemminger 				   (int __user *)a[4]);
25611da177e4SLinus Torvalds 		break;
25621da177e4SLinus Torvalds 	case SYS_SENDMSG:
2563666547ffSAl Viro 		err = sys_sendmsg(a0, (struct user_msghdr __user *)a1, a[2]);
25641da177e4SLinus Torvalds 		break;
2565228e548eSAnton Blanchard 	case SYS_SENDMMSG:
2566228e548eSAnton Blanchard 		err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]);
2567228e548eSAnton Blanchard 		break;
25681da177e4SLinus Torvalds 	case SYS_RECVMSG:
2569666547ffSAl Viro 		err = sys_recvmsg(a0, (struct user_msghdr __user *)a1, a[2]);
25701da177e4SLinus Torvalds 		break;
2571a2e27255SArnaldo Carvalho de Melo 	case SYS_RECVMMSG:
2572a2e27255SArnaldo Carvalho de Melo 		err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3],
2573a2e27255SArnaldo Carvalho de Melo 				   (struct timespec __user *)a[4]);
2574a2e27255SArnaldo Carvalho de Melo 		break;
2575de11defeSUlrich Drepper 	case SYS_ACCEPT4:
25764541e805SDominik Brodowski 		err = __sys_accept4(a0, (struct sockaddr __user *)a1,
2577de11defeSUlrich Drepper 				    (int __user *)a[2], a[3]);
2578aaca0bdcSUlrich Drepper 		break;
25791da177e4SLinus Torvalds 	default:
25801da177e4SLinus Torvalds 		err = -EINVAL;
25811da177e4SLinus Torvalds 		break;
25821da177e4SLinus Torvalds 	}
25831da177e4SLinus Torvalds 	return err;
25841da177e4SLinus Torvalds }
25851da177e4SLinus Torvalds 
25861da177e4SLinus Torvalds #endif				/* __ARCH_WANT_SYS_SOCKETCALL */
25871da177e4SLinus Torvalds 
258855737fdaSStephen Hemminger /**
258955737fdaSStephen Hemminger  *	sock_register - add a socket protocol handler
259055737fdaSStephen Hemminger  *	@ops: description of protocol
259155737fdaSStephen Hemminger  *
25921da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
25931da177e4SLinus Torvalds  *	advertise its address family, and have it linked into the
2594e793c0f7SMasanari Iida  *	socket interface. The value ops->family corresponds to the
259555737fdaSStephen Hemminger  *	socket system call protocol family.
25961da177e4SLinus Torvalds  */
2597f0fd27d4SStephen Hemminger int sock_register(const struct net_proto_family *ops)
25981da177e4SLinus Torvalds {
25991da177e4SLinus Torvalds 	int err;
26001da177e4SLinus Torvalds 
26011da177e4SLinus Torvalds 	if (ops->family >= NPROTO) {
26023410f22eSYang Yingliang 		pr_crit("protocol %d >= NPROTO(%d)\n", ops->family, NPROTO);
26031da177e4SLinus Torvalds 		return -ENOBUFS;
26041da177e4SLinus Torvalds 	}
260555737fdaSStephen Hemminger 
260655737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2607190683a9SEric Dumazet 	if (rcu_dereference_protected(net_families[ops->family],
2608190683a9SEric Dumazet 				      lockdep_is_held(&net_family_lock)))
26091da177e4SLinus Torvalds 		err = -EEXIST;
261055737fdaSStephen Hemminger 	else {
2611cf778b00SEric Dumazet 		rcu_assign_pointer(net_families[ops->family], ops);
26121da177e4SLinus Torvalds 		err = 0;
26131da177e4SLinus Torvalds 	}
261455737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
261555737fdaSStephen Hemminger 
26163410f22eSYang Yingliang 	pr_info("NET: Registered protocol family %d\n", ops->family);
26171da177e4SLinus Torvalds 	return err;
26181da177e4SLinus Torvalds }
2619c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_register);
26201da177e4SLinus Torvalds 
262155737fdaSStephen Hemminger /**
262255737fdaSStephen Hemminger  *	sock_unregister - remove a protocol handler
262355737fdaSStephen Hemminger  *	@family: protocol family to remove
262455737fdaSStephen Hemminger  *
26251da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
26261da177e4SLinus Torvalds  *	remove its address family, and have it unlinked from the
262755737fdaSStephen Hemminger  *	new socket creation.
262855737fdaSStephen Hemminger  *
262955737fdaSStephen Hemminger  *	If protocol handler is a module, then it can use module reference
263055737fdaSStephen Hemminger  *	counts to protect against new references. If protocol handler is not
263155737fdaSStephen Hemminger  *	a module then it needs to provide its own protection in
263255737fdaSStephen Hemminger  *	the ops->create routine.
26331da177e4SLinus Torvalds  */
2634f0fd27d4SStephen Hemminger void sock_unregister(int family)
26351da177e4SLinus Torvalds {
2636f0fd27d4SStephen Hemminger 	BUG_ON(family < 0 || family >= NPROTO);
26371da177e4SLinus Torvalds 
263855737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2639a9b3cd7fSStephen Hemminger 	RCU_INIT_POINTER(net_families[family], NULL);
264055737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
264155737fdaSStephen Hemminger 
264255737fdaSStephen Hemminger 	synchronize_rcu();
264355737fdaSStephen Hemminger 
26443410f22eSYang Yingliang 	pr_info("NET: Unregistered protocol family %d\n", family);
26451da177e4SLinus Torvalds }
2646c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_unregister);
26471da177e4SLinus Torvalds 
264877d76ea3SAndi Kleen static int __init sock_init(void)
26491da177e4SLinus Torvalds {
2650b3e19d92SNick Piggin 	int err;
26512ca794e5SEric W. Biederman 	/*
26522ca794e5SEric W. Biederman 	 *      Initialize the network sysctl infrastructure.
26532ca794e5SEric W. Biederman 	 */
26542ca794e5SEric W. Biederman 	err = net_sysctl_init();
26552ca794e5SEric W. Biederman 	if (err)
26562ca794e5SEric W. Biederman 		goto out;
2657b3e19d92SNick Piggin 
26581da177e4SLinus Torvalds 	/*
26591da177e4SLinus Torvalds 	 *      Initialize skbuff SLAB cache
26601da177e4SLinus Torvalds 	 */
26611da177e4SLinus Torvalds 	skb_init();
26621da177e4SLinus Torvalds 
26631da177e4SLinus Torvalds 	/*
26641da177e4SLinus Torvalds 	 *      Initialize the protocols module.
26651da177e4SLinus Torvalds 	 */
26661da177e4SLinus Torvalds 
26671da177e4SLinus Torvalds 	init_inodecache();
2668b3e19d92SNick Piggin 
2669b3e19d92SNick Piggin 	err = register_filesystem(&sock_fs_type);
2670b3e19d92SNick Piggin 	if (err)
2671b3e19d92SNick Piggin 		goto out_fs;
26721da177e4SLinus Torvalds 	sock_mnt = kern_mount(&sock_fs_type);
2673b3e19d92SNick Piggin 	if (IS_ERR(sock_mnt)) {
2674b3e19d92SNick Piggin 		err = PTR_ERR(sock_mnt);
2675b3e19d92SNick Piggin 		goto out_mount;
2676b3e19d92SNick Piggin 	}
267777d76ea3SAndi Kleen 
267877d76ea3SAndi Kleen 	/* The real protocol initialization is performed in later initcalls.
26791da177e4SLinus Torvalds 	 */
26801da177e4SLinus Torvalds 
26811da177e4SLinus Torvalds #ifdef CONFIG_NETFILTER
26826d11cfdbSPablo Neira Ayuso 	err = netfilter_init();
26836d11cfdbSPablo Neira Ayuso 	if (err)
26846d11cfdbSPablo Neira Ayuso 		goto out;
26851da177e4SLinus Torvalds #endif
2686cbeb321aSDavid S. Miller 
2687408eccceSDaniel Borkmann 	ptp_classifier_init();
2688c1f19b51SRichard Cochran 
2689b3e19d92SNick Piggin out:
2690b3e19d92SNick Piggin 	return err;
2691b3e19d92SNick Piggin 
2692b3e19d92SNick Piggin out_mount:
2693b3e19d92SNick Piggin 	unregister_filesystem(&sock_fs_type);
2694b3e19d92SNick Piggin out_fs:
2695b3e19d92SNick Piggin 	goto out;
26961da177e4SLinus Torvalds }
26971da177e4SLinus Torvalds 
269877d76ea3SAndi Kleen core_initcall(sock_init);	/* early initcall */
269977d76ea3SAndi Kleen 
27001da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS
27011da177e4SLinus Torvalds void socket_seq_show(struct seq_file *seq)
27021da177e4SLinus Torvalds {
2703648845abSTonghao Zhang 	seq_printf(seq, "sockets: used %d\n",
2704648845abSTonghao Zhang 		   sock_inuse_get(seq->private));
27051da177e4SLinus Torvalds }
27061da177e4SLinus Torvalds #endif				/* CONFIG_PROC_FS */
27071da177e4SLinus Torvalds 
270889bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
27096b96018bSArnd Bergmann static int do_siocgstamp(struct net *net, struct socket *sock,
2710644595f8SH. Peter Anvin 			 unsigned int cmd, void __user *up)
27117a229387SArnd Bergmann {
27127a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
27137a229387SArnd Bergmann 	struct timeval ktv;
27147a229387SArnd Bergmann 	int err;
27157a229387SArnd Bergmann 
27167a229387SArnd Bergmann 	set_fs(KERNEL_DS);
27176b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv);
27187a229387SArnd Bergmann 	set_fs(old_fs);
2719644595f8SH. Peter Anvin 	if (!err)
2720ed6fe9d6SMikulas Patocka 		err = compat_put_timeval(&ktv, up);
2721644595f8SH. Peter Anvin 
27227a229387SArnd Bergmann 	return err;
27237a229387SArnd Bergmann }
27247a229387SArnd Bergmann 
27256b96018bSArnd Bergmann static int do_siocgstampns(struct net *net, struct socket *sock,
2726644595f8SH. Peter Anvin 			   unsigned int cmd, void __user *up)
27277a229387SArnd Bergmann {
27287a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
27297a229387SArnd Bergmann 	struct timespec kts;
27307a229387SArnd Bergmann 	int err;
27317a229387SArnd Bergmann 
27327a229387SArnd Bergmann 	set_fs(KERNEL_DS);
27336b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts);
27347a229387SArnd Bergmann 	set_fs(old_fs);
2735644595f8SH. Peter Anvin 	if (!err)
2736ed6fe9d6SMikulas Patocka 		err = compat_put_timespec(&kts, up);
2737644595f8SH. Peter Anvin 
27387a229387SArnd Bergmann 	return err;
27397a229387SArnd Bergmann }
27407a229387SArnd Bergmann 
274136fd633eSAl Viro static int compat_dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32)
27427a229387SArnd Bergmann {
27436b96018bSArnd Bergmann 	struct compat_ifconf ifc32;
27447a229387SArnd Bergmann 	struct ifconf ifc;
27457a229387SArnd Bergmann 	int err;
27467a229387SArnd Bergmann 
27476b96018bSArnd Bergmann 	if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf)))
27487a229387SArnd Bergmann 		return -EFAULT;
27497a229387SArnd Bergmann 
275036fd633eSAl Viro 	ifc.ifc_len = ifc32.ifc_len;
275136fd633eSAl Viro 	ifc.ifc_req = compat_ptr(ifc32.ifcbuf);
27527a229387SArnd Bergmann 
275336fd633eSAl Viro 	rtnl_lock();
275436fd633eSAl Viro 	err = dev_ifconf(net, &ifc, sizeof(struct compat_ifreq));
275536fd633eSAl Viro 	rtnl_unlock();
27567a229387SArnd Bergmann 	if (err)
27577a229387SArnd Bergmann 		return err;
27587a229387SArnd Bergmann 
275936fd633eSAl Viro 	ifc32.ifc_len = ifc.ifc_len;
27606b96018bSArnd Bergmann 	if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf)))
27617a229387SArnd Bergmann 		return -EFAULT;
27627a229387SArnd Bergmann 
27637a229387SArnd Bergmann 	return 0;
27647a229387SArnd Bergmann }
27657a229387SArnd Bergmann 
27666b96018bSArnd Bergmann static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
27677a229387SArnd Bergmann {
27683a7da39dSBen Hutchings 	struct compat_ethtool_rxnfc __user *compat_rxnfc;
27693a7da39dSBen Hutchings 	bool convert_in = false, convert_out = false;
277044c02a2cSAl Viro 	size_t buf_size = 0;
277144c02a2cSAl Viro 	struct ethtool_rxnfc __user *rxnfc = NULL;
277244c02a2cSAl Viro 	struct ifreq ifr;
27733a7da39dSBen Hutchings 	u32 rule_cnt = 0, actual_rule_cnt;
27743a7da39dSBen Hutchings 	u32 ethcmd;
27757a229387SArnd Bergmann 	u32 data;
27763a7da39dSBen Hutchings 	int ret;
27777a229387SArnd Bergmann 
27787a229387SArnd Bergmann 	if (get_user(data, &ifr32->ifr_ifru.ifru_data))
27797a229387SArnd Bergmann 		return -EFAULT;
27807a229387SArnd Bergmann 
27813a7da39dSBen Hutchings 	compat_rxnfc = compat_ptr(data);
27823a7da39dSBen Hutchings 
27833a7da39dSBen Hutchings 	if (get_user(ethcmd, &compat_rxnfc->cmd))
27847a229387SArnd Bergmann 		return -EFAULT;
27857a229387SArnd Bergmann 
27863a7da39dSBen Hutchings 	/* Most ethtool structures are defined without padding.
27873a7da39dSBen Hutchings 	 * Unfortunately struct ethtool_rxnfc is an exception.
27883a7da39dSBen Hutchings 	 */
27893a7da39dSBen Hutchings 	switch (ethcmd) {
27903a7da39dSBen Hutchings 	default:
27913a7da39dSBen Hutchings 		break;
27923a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLALL:
27933a7da39dSBen Hutchings 		/* Buffer size is variable */
27943a7da39dSBen Hutchings 		if (get_user(rule_cnt, &compat_rxnfc->rule_cnt))
27953a7da39dSBen Hutchings 			return -EFAULT;
27963a7da39dSBen Hutchings 		if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32))
27973a7da39dSBen Hutchings 			return -ENOMEM;
27983a7da39dSBen Hutchings 		buf_size += rule_cnt * sizeof(u32);
27993a7da39dSBen Hutchings 		/* fall through */
28003a7da39dSBen Hutchings 	case ETHTOOL_GRXRINGS:
28013a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLCNT:
28023a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRULE:
280355664f32SBen Hutchings 	case ETHTOOL_SRXCLSRLINS:
28043a7da39dSBen Hutchings 		convert_out = true;
28053a7da39dSBen Hutchings 		/* fall through */
28063a7da39dSBen Hutchings 	case ETHTOOL_SRXCLSRLDEL:
28073a7da39dSBen Hutchings 		buf_size += sizeof(struct ethtool_rxnfc);
28083a7da39dSBen Hutchings 		convert_in = true;
280944c02a2cSAl Viro 		rxnfc = compat_alloc_user_space(buf_size);
28103a7da39dSBen Hutchings 		break;
28113a7da39dSBen Hutchings 	}
28123a7da39dSBen Hutchings 
281344c02a2cSAl Viro 	if (copy_from_user(&ifr.ifr_name, &ifr32->ifr_name, IFNAMSIZ))
28143a7da39dSBen Hutchings 		return -EFAULT;
28153a7da39dSBen Hutchings 
281644c02a2cSAl Viro 	ifr.ifr_data = convert_in ? rxnfc : (void __user *)compat_rxnfc;
28173a7da39dSBen Hutchings 
28183a7da39dSBen Hutchings 	if (convert_in) {
2819127fe533SAlexander Duyck 		/* We expect there to be holes between fs.m_ext and
28203a7da39dSBen Hutchings 		 * fs.ring_cookie and at the end of fs, but nowhere else.
28213a7da39dSBen Hutchings 		 */
2822127fe533SAlexander Duyck 		BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_ext) +
2823127fe533SAlexander Duyck 			     sizeof(compat_rxnfc->fs.m_ext) !=
2824127fe533SAlexander Duyck 			     offsetof(struct ethtool_rxnfc, fs.m_ext) +
2825127fe533SAlexander Duyck 			     sizeof(rxnfc->fs.m_ext));
28263a7da39dSBen Hutchings 		BUILD_BUG_ON(
28273a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.location) -
28283a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) !=
28293a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.location) -
28303a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.ring_cookie));
28313a7da39dSBen Hutchings 
28323a7da39dSBen Hutchings 		if (copy_in_user(rxnfc, compat_rxnfc,
2833954b1244SStephen Hemminger 				 (void __user *)(&rxnfc->fs.m_ext + 1) -
2834954b1244SStephen Hemminger 				 (void __user *)rxnfc) ||
28353a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->fs.ring_cookie,
28363a7da39dSBen Hutchings 				 &compat_rxnfc->fs.ring_cookie,
2837954b1244SStephen Hemminger 				 (void __user *)(&rxnfc->fs.location + 1) -
2838954b1244SStephen Hemminger 				 (void __user *)&rxnfc->fs.ring_cookie) ||
28393a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt,
28403a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
28413a7da39dSBen Hutchings 			return -EFAULT;
28423a7da39dSBen Hutchings 	}
28433a7da39dSBen Hutchings 
284444c02a2cSAl Viro 	ret = dev_ioctl(net, SIOCETHTOOL, &ifr, NULL);
28453a7da39dSBen Hutchings 	if (ret)
28463a7da39dSBen Hutchings 		return ret;
28473a7da39dSBen Hutchings 
28483a7da39dSBen Hutchings 	if (convert_out) {
28493a7da39dSBen Hutchings 		if (copy_in_user(compat_rxnfc, rxnfc,
2850954b1244SStephen Hemminger 				 (const void __user *)(&rxnfc->fs.m_ext + 1) -
2851954b1244SStephen Hemminger 				 (const void __user *)rxnfc) ||
28523a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->fs.ring_cookie,
28533a7da39dSBen Hutchings 				 &rxnfc->fs.ring_cookie,
2854954b1244SStephen Hemminger 				 (const void __user *)(&rxnfc->fs.location + 1) -
2855954b1244SStephen Hemminger 				 (const void __user *)&rxnfc->fs.ring_cookie) ||
28563a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt,
28573a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
28583a7da39dSBen Hutchings 			return -EFAULT;
28593a7da39dSBen Hutchings 
28603a7da39dSBen Hutchings 		if (ethcmd == ETHTOOL_GRXCLSRLALL) {
28613a7da39dSBen Hutchings 			/* As an optimisation, we only copy the actual
28623a7da39dSBen Hutchings 			 * number of rules that the underlying
28633a7da39dSBen Hutchings 			 * function returned.  Since Mallory might
28643a7da39dSBen Hutchings 			 * change the rule count in user memory, we
28653a7da39dSBen Hutchings 			 * check that it is less than the rule count
28663a7da39dSBen Hutchings 			 * originally given (as the user buffer size),
28673a7da39dSBen Hutchings 			 * which has been range-checked.
28683a7da39dSBen Hutchings 			 */
28693a7da39dSBen Hutchings 			if (get_user(actual_rule_cnt, &rxnfc->rule_cnt))
28703a7da39dSBen Hutchings 				return -EFAULT;
28713a7da39dSBen Hutchings 			if (actual_rule_cnt < rule_cnt)
28723a7da39dSBen Hutchings 				rule_cnt = actual_rule_cnt;
28733a7da39dSBen Hutchings 			if (copy_in_user(&compat_rxnfc->rule_locs[0],
28743a7da39dSBen Hutchings 					 &rxnfc->rule_locs[0],
28753a7da39dSBen Hutchings 					 rule_cnt * sizeof(u32)))
28763a7da39dSBen Hutchings 				return -EFAULT;
28773a7da39dSBen Hutchings 		}
28783a7da39dSBen Hutchings 	}
28793a7da39dSBen Hutchings 
28803a7da39dSBen Hutchings 	return 0;
28817a229387SArnd Bergmann }
28827a229387SArnd Bergmann 
28837a50a240SArnd Bergmann static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32)
28847a50a240SArnd Bergmann {
28857a50a240SArnd Bergmann 	compat_uptr_t uptr32;
288644c02a2cSAl Viro 	struct ifreq ifr;
288744c02a2cSAl Viro 	void __user *saved;
288844c02a2cSAl Viro 	int err;
28897a50a240SArnd Bergmann 
289044c02a2cSAl Viro 	if (copy_from_user(&ifr, uifr32, sizeof(struct compat_ifreq)))
28917a50a240SArnd Bergmann 		return -EFAULT;
28927a50a240SArnd Bergmann 
28937a50a240SArnd Bergmann 	if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu))
28947a50a240SArnd Bergmann 		return -EFAULT;
28957a50a240SArnd Bergmann 
289644c02a2cSAl Viro 	saved = ifr.ifr_settings.ifs_ifsu.raw_hdlc;
289744c02a2cSAl Viro 	ifr.ifr_settings.ifs_ifsu.raw_hdlc = compat_ptr(uptr32);
28987a50a240SArnd Bergmann 
289944c02a2cSAl Viro 	err = dev_ioctl(net, SIOCWANDEV, &ifr, NULL);
290044c02a2cSAl Viro 	if (!err) {
290144c02a2cSAl Viro 		ifr.ifr_settings.ifs_ifsu.raw_hdlc = saved;
290244c02a2cSAl Viro 		if (copy_to_user(uifr32, &ifr, sizeof(struct compat_ifreq)))
290344c02a2cSAl Viro 			err = -EFAULT;
29047a50a240SArnd Bergmann 	}
29057a229387SArnd Bergmann 	return err;
29067a229387SArnd Bergmann }
29077a229387SArnd Bergmann 
2908590d4693SBen Hutchings /* Handle ioctls that use ifreq::ifr_data and just need struct ifreq converted */
2909590d4693SBen Hutchings static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd,
29106b96018bSArnd Bergmann 				 struct compat_ifreq __user *u_ifreq32)
29117a229387SArnd Bergmann {
291244c02a2cSAl Viro 	struct ifreq ifreq;
29137a229387SArnd Bergmann 	u32 data32;
29147a229387SArnd Bergmann 
291544c02a2cSAl Viro 	if (copy_from_user(ifreq.ifr_name, u_ifreq32->ifr_name, IFNAMSIZ))
29167a229387SArnd Bergmann 		return -EFAULT;
291744c02a2cSAl Viro 	if (get_user(data32, &u_ifreq32->ifr_data))
29187a229387SArnd Bergmann 		return -EFAULT;
291944c02a2cSAl Viro 	ifreq.ifr_data = compat_ptr(data32);
29207a229387SArnd Bergmann 
292144c02a2cSAl Viro 	return dev_ioctl(net, cmd, &ifreq, NULL);
2922a2116ed2SArnd Bergmann }
2923a2116ed2SArnd Bergmann 
2924a2116ed2SArnd Bergmann static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
2925a2116ed2SArnd Bergmann 			struct compat_ifreq __user *uifr32)
2926a2116ed2SArnd Bergmann {
2927a2116ed2SArnd Bergmann 	struct ifreq ifr;
2928a2116ed2SArnd Bergmann 	struct compat_ifmap __user *uifmap32;
2929a2116ed2SArnd Bergmann 	int err;
2930a2116ed2SArnd Bergmann 
2931a2116ed2SArnd Bergmann 	uifmap32 = &uifr32->ifr_ifru.ifru_map;
2932a2116ed2SArnd Bergmann 	err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name));
29333ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
29343ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
29353ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
29363ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.irq, &uifmap32->irq);
29373ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.dma, &uifmap32->dma);
29383ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.port, &uifmap32->port);
2939a2116ed2SArnd Bergmann 	if (err)
2940a2116ed2SArnd Bergmann 		return -EFAULT;
2941a2116ed2SArnd Bergmann 
294244c02a2cSAl Viro 	err = dev_ioctl(net, cmd, &ifr, NULL);
2943a2116ed2SArnd Bergmann 
2944a2116ed2SArnd Bergmann 	if (cmd == SIOCGIFMAP && !err) {
29457a229387SArnd Bergmann 		err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name));
29463ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
29473ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
29483ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
29493ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.irq, &uifmap32->irq);
29503ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.dma, &uifmap32->dma);
29513ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.port, &uifmap32->port);
29527a229387SArnd Bergmann 		if (err)
29537a229387SArnd Bergmann 			err = -EFAULT;
29547a229387SArnd Bergmann 	}
29557a229387SArnd Bergmann 	return err;
29567a229387SArnd Bergmann }
29577a229387SArnd Bergmann 
29587a229387SArnd Bergmann struct rtentry32 {
29597a229387SArnd Bergmann 	u32		rt_pad1;
29607a229387SArnd Bergmann 	struct sockaddr rt_dst;         /* target address               */
29617a229387SArnd Bergmann 	struct sockaddr rt_gateway;     /* gateway addr (RTF_GATEWAY)   */
29627a229387SArnd Bergmann 	struct sockaddr rt_genmask;     /* target network mask (IP)     */
29637a229387SArnd Bergmann 	unsigned short	rt_flags;
29647a229387SArnd Bergmann 	short		rt_pad2;
29657a229387SArnd Bergmann 	u32		rt_pad3;
29667a229387SArnd Bergmann 	unsigned char	rt_tos;
29677a229387SArnd Bergmann 	unsigned char	rt_class;
29687a229387SArnd Bergmann 	short		rt_pad4;
29697a229387SArnd Bergmann 	short		rt_metric;      /* +1 for binary compatibility! */
29707a229387SArnd Bergmann 	/* char * */ u32 rt_dev;        /* forcing the device at add    */
29717a229387SArnd Bergmann 	u32		rt_mtu;         /* per route MTU/Window         */
29727a229387SArnd Bergmann 	u32		rt_window;      /* Window clamping              */
29737a229387SArnd Bergmann 	unsigned short  rt_irtt;        /* Initial RTT                  */
29747a229387SArnd Bergmann };
29757a229387SArnd Bergmann 
29767a229387SArnd Bergmann struct in6_rtmsg32 {
29777a229387SArnd Bergmann 	struct in6_addr		rtmsg_dst;
29787a229387SArnd Bergmann 	struct in6_addr		rtmsg_src;
29797a229387SArnd Bergmann 	struct in6_addr		rtmsg_gateway;
29807a229387SArnd Bergmann 	u32			rtmsg_type;
29817a229387SArnd Bergmann 	u16			rtmsg_dst_len;
29827a229387SArnd Bergmann 	u16			rtmsg_src_len;
29837a229387SArnd Bergmann 	u32			rtmsg_metric;
29847a229387SArnd Bergmann 	u32			rtmsg_info;
29857a229387SArnd Bergmann 	u32			rtmsg_flags;
29867a229387SArnd Bergmann 	s32			rtmsg_ifindex;
29877a229387SArnd Bergmann };
29887a229387SArnd Bergmann 
29896b96018bSArnd Bergmann static int routing_ioctl(struct net *net, struct socket *sock,
29906b96018bSArnd Bergmann 			 unsigned int cmd, void __user *argp)
29917a229387SArnd Bergmann {
29927a229387SArnd Bergmann 	int ret;
29937a229387SArnd Bergmann 	void *r = NULL;
29947a229387SArnd Bergmann 	struct in6_rtmsg r6;
29957a229387SArnd Bergmann 	struct rtentry r4;
29967a229387SArnd Bergmann 	char devname[16];
29977a229387SArnd Bergmann 	u32 rtdev;
29987a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
29997a229387SArnd Bergmann 
30006b96018bSArnd Bergmann 	if (sock && sock->sk && sock->sk->sk_family == AF_INET6) { /* ipv6 */
30016b96018bSArnd Bergmann 		struct in6_rtmsg32 __user *ur6 = argp;
30027a229387SArnd Bergmann 		ret = copy_from_user(&r6.rtmsg_dst, &(ur6->rtmsg_dst),
30037a229387SArnd Bergmann 			3 * sizeof(struct in6_addr));
30043ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_type, &(ur6->rtmsg_type));
30053ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len));
30063ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_src_len, &(ur6->rtmsg_src_len));
30073ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_metric, &(ur6->rtmsg_metric));
30083ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_info, &(ur6->rtmsg_info));
30093ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_flags, &(ur6->rtmsg_flags));
30103ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex));
30117a229387SArnd Bergmann 
30127a229387SArnd Bergmann 		r = (void *) &r6;
30137a229387SArnd Bergmann 	} else { /* ipv4 */
30146b96018bSArnd Bergmann 		struct rtentry32 __user *ur4 = argp;
30157a229387SArnd Bergmann 		ret = copy_from_user(&r4.rt_dst, &(ur4->rt_dst),
30167a229387SArnd Bergmann 					3 * sizeof(struct sockaddr));
30173ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_flags, &(ur4->rt_flags));
30183ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_metric, &(ur4->rt_metric));
30193ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_mtu, &(ur4->rt_mtu));
30203ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_window, &(ur4->rt_window));
30213ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_irtt, &(ur4->rt_irtt));
30223ddc5b46SMathieu Desnoyers 		ret |= get_user(rtdev, &(ur4->rt_dev));
30237a229387SArnd Bergmann 		if (rtdev) {
30247a229387SArnd Bergmann 			ret |= copy_from_user(devname, compat_ptr(rtdev), 15);
3025c3f52ae6Sstephen hemminger 			r4.rt_dev = (char __user __force *)devname;
3026c3f52ae6Sstephen hemminger 			devname[15] = 0;
30277a229387SArnd Bergmann 		} else
30287a229387SArnd Bergmann 			r4.rt_dev = NULL;
30297a229387SArnd Bergmann 
30307a229387SArnd Bergmann 		r = (void *) &r4;
30317a229387SArnd Bergmann 	}
30327a229387SArnd Bergmann 
30337a229387SArnd Bergmann 	if (ret) {
30347a229387SArnd Bergmann 		ret = -EFAULT;
30357a229387SArnd Bergmann 		goto out;
30367a229387SArnd Bergmann 	}
30377a229387SArnd Bergmann 
30387a229387SArnd Bergmann 	set_fs(KERNEL_DS);
30396b96018bSArnd Bergmann 	ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r);
30407a229387SArnd Bergmann 	set_fs(old_fs);
30417a229387SArnd Bergmann 
30427a229387SArnd Bergmann out:
30437a229387SArnd Bergmann 	return ret;
30447a229387SArnd Bergmann }
30457a229387SArnd Bergmann 
30467a229387SArnd Bergmann /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE
30477a229387SArnd Bergmann  * for some operations; this forces use of the newer bridge-utils that
304825985edcSLucas De Marchi  * use compatible ioctls
30497a229387SArnd Bergmann  */
30506b96018bSArnd Bergmann static int old_bridge_ioctl(compat_ulong_t __user *argp)
30517a229387SArnd Bergmann {
30526b96018bSArnd Bergmann 	compat_ulong_t tmp;
30537a229387SArnd Bergmann 
30546b96018bSArnd Bergmann 	if (get_user(tmp, argp))
30557a229387SArnd Bergmann 		return -EFAULT;
30567a229387SArnd Bergmann 	if (tmp == BRCTL_GET_VERSION)
30577a229387SArnd Bergmann 		return BRCTL_VERSION + 1;
30587a229387SArnd Bergmann 	return -EINVAL;
30597a229387SArnd Bergmann }
30607a229387SArnd Bergmann 
30616b96018bSArnd Bergmann static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
30626b96018bSArnd Bergmann 			 unsigned int cmd, unsigned long arg)
30636b96018bSArnd Bergmann {
30646b96018bSArnd Bergmann 	void __user *argp = compat_ptr(arg);
30656b96018bSArnd Bergmann 	struct sock *sk = sock->sk;
30666b96018bSArnd Bergmann 	struct net *net = sock_net(sk);
30677a229387SArnd Bergmann 
30686b96018bSArnd Bergmann 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
3069590d4693SBen Hutchings 		return compat_ifr_data_ioctl(net, cmd, argp);
30707a229387SArnd Bergmann 
30716b96018bSArnd Bergmann 	switch (cmd) {
30726b96018bSArnd Bergmann 	case SIOCSIFBR:
30736b96018bSArnd Bergmann 	case SIOCGIFBR:
30746b96018bSArnd Bergmann 		return old_bridge_ioctl(argp);
30756b96018bSArnd Bergmann 	case SIOCGIFCONF:
307636fd633eSAl Viro 		return compat_dev_ifconf(net, argp);
30776b96018bSArnd Bergmann 	case SIOCETHTOOL:
30786b96018bSArnd Bergmann 		return ethtool_ioctl(net, argp);
30797a50a240SArnd Bergmann 	case SIOCWANDEV:
30807a50a240SArnd Bergmann 		return compat_siocwandev(net, argp);
3081a2116ed2SArnd Bergmann 	case SIOCGIFMAP:
3082a2116ed2SArnd Bergmann 	case SIOCSIFMAP:
3083a2116ed2SArnd Bergmann 		return compat_sioc_ifmap(net, cmd, argp);
30846b96018bSArnd Bergmann 	case SIOCADDRT:
30856b96018bSArnd Bergmann 	case SIOCDELRT:
30866b96018bSArnd Bergmann 		return routing_ioctl(net, sock, cmd, argp);
30876b96018bSArnd Bergmann 	case SIOCGSTAMP:
30886b96018bSArnd Bergmann 		return do_siocgstamp(net, sock, cmd, argp);
30896b96018bSArnd Bergmann 	case SIOCGSTAMPNS:
30906b96018bSArnd Bergmann 		return do_siocgstampns(net, sock, cmd, argp);
3091590d4693SBen Hutchings 	case SIOCBONDSLAVEINFOQUERY:
3092590d4693SBen Hutchings 	case SIOCBONDINFOQUERY:
3093a2116ed2SArnd Bergmann 	case SIOCSHWTSTAMP:
3094fd468c74SBen Hutchings 	case SIOCGHWTSTAMP:
3095590d4693SBen Hutchings 		return compat_ifr_data_ioctl(net, cmd, argp);
30967a229387SArnd Bergmann 
30976b96018bSArnd Bergmann 	case FIOSETOWN:
30986b96018bSArnd Bergmann 	case SIOCSPGRP:
30996b96018bSArnd Bergmann 	case FIOGETOWN:
31006b96018bSArnd Bergmann 	case SIOCGPGRP:
31016b96018bSArnd Bergmann 	case SIOCBRADDBR:
31026b96018bSArnd Bergmann 	case SIOCBRDELBR:
31036b96018bSArnd Bergmann 	case SIOCGIFVLAN:
31046b96018bSArnd Bergmann 	case SIOCSIFVLAN:
31056b96018bSArnd Bergmann 	case SIOCADDDLCI:
31066b96018bSArnd Bergmann 	case SIOCDELDLCI:
3107c62cce2cSAndrey Vagin 	case SIOCGSKNS:
31086b96018bSArnd Bergmann 		return sock_ioctl(file, cmd, arg);
31096b96018bSArnd Bergmann 
31106b96018bSArnd Bergmann 	case SIOCGIFFLAGS:
31116b96018bSArnd Bergmann 	case SIOCSIFFLAGS:
31126b96018bSArnd Bergmann 	case SIOCGIFMETRIC:
31136b96018bSArnd Bergmann 	case SIOCSIFMETRIC:
31146b96018bSArnd Bergmann 	case SIOCGIFMTU:
31156b96018bSArnd Bergmann 	case SIOCSIFMTU:
31166b96018bSArnd Bergmann 	case SIOCGIFMEM:
31176b96018bSArnd Bergmann 	case SIOCSIFMEM:
31186b96018bSArnd Bergmann 	case SIOCGIFHWADDR:
31196b96018bSArnd Bergmann 	case SIOCSIFHWADDR:
31206b96018bSArnd Bergmann 	case SIOCADDMULTI:
31216b96018bSArnd Bergmann 	case SIOCDELMULTI:
31226b96018bSArnd Bergmann 	case SIOCGIFINDEX:
31236b96018bSArnd Bergmann 	case SIOCGIFADDR:
31246b96018bSArnd Bergmann 	case SIOCSIFADDR:
31256b96018bSArnd Bergmann 	case SIOCSIFHWBROADCAST:
31266b96018bSArnd Bergmann 	case SIOCDIFADDR:
31276b96018bSArnd Bergmann 	case SIOCGIFBRDADDR:
31286b96018bSArnd Bergmann 	case SIOCSIFBRDADDR:
31296b96018bSArnd Bergmann 	case SIOCGIFDSTADDR:
31306b96018bSArnd Bergmann 	case SIOCSIFDSTADDR:
31316b96018bSArnd Bergmann 	case SIOCGIFNETMASK:
31326b96018bSArnd Bergmann 	case SIOCSIFNETMASK:
31336b96018bSArnd Bergmann 	case SIOCSIFPFLAGS:
31346b96018bSArnd Bergmann 	case SIOCGIFPFLAGS:
31356b96018bSArnd Bergmann 	case SIOCGIFTXQLEN:
31366b96018bSArnd Bergmann 	case SIOCSIFTXQLEN:
31376b96018bSArnd Bergmann 	case SIOCBRADDIF:
31386b96018bSArnd Bergmann 	case SIOCBRDELIF:
31399177efd3SArnd Bergmann 	case SIOCSIFNAME:
31409177efd3SArnd Bergmann 	case SIOCGMIIPHY:
31419177efd3SArnd Bergmann 	case SIOCGMIIREG:
31429177efd3SArnd Bergmann 	case SIOCSMIIREG:
31436b96018bSArnd Bergmann 	case SIOCSARP:
31446b96018bSArnd Bergmann 	case SIOCGARP:
31456b96018bSArnd Bergmann 	case SIOCDARP:
31466b96018bSArnd Bergmann 	case SIOCATMARK:
3147f92d4fc9SAl Viro 	case SIOCBONDENSLAVE:
3148f92d4fc9SAl Viro 	case SIOCBONDRELEASE:
3149f92d4fc9SAl Viro 	case SIOCBONDSETHWADDR:
3150f92d4fc9SAl Viro 	case SIOCBONDCHANGEACTIVE:
31514cf808e7SAl Viro 	case SIOCGIFNAME:
31529177efd3SArnd Bergmann 		return sock_do_ioctl(net, sock, cmd, arg);
31539177efd3SArnd Bergmann 	}
31549177efd3SArnd Bergmann 
31556b96018bSArnd Bergmann 	return -ENOIOCTLCMD;
31566b96018bSArnd Bergmann }
31577a229387SArnd Bergmann 
315895c96174SEric Dumazet static long compat_sock_ioctl(struct file *file, unsigned int cmd,
315989bbfc95SShaun Pereira 			      unsigned long arg)
316089bbfc95SShaun Pereira {
316189bbfc95SShaun Pereira 	struct socket *sock = file->private_data;
316289bbfc95SShaun Pereira 	int ret = -ENOIOCTLCMD;
316387de87d5SDavid S. Miller 	struct sock *sk;
316487de87d5SDavid S. Miller 	struct net *net;
316587de87d5SDavid S. Miller 
316687de87d5SDavid S. Miller 	sk = sock->sk;
316787de87d5SDavid S. Miller 	net = sock_net(sk);
316889bbfc95SShaun Pereira 
316989bbfc95SShaun Pereira 	if (sock->ops->compat_ioctl)
317089bbfc95SShaun Pereira 		ret = sock->ops->compat_ioctl(sock, cmd, arg);
317189bbfc95SShaun Pereira 
317287de87d5SDavid S. Miller 	if (ret == -ENOIOCTLCMD &&
317387de87d5SDavid S. Miller 	    (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST))
317487de87d5SDavid S. Miller 		ret = compat_wext_handle_ioctl(net, cmd, arg);
317587de87d5SDavid S. Miller 
31766b96018bSArnd Bergmann 	if (ret == -ENOIOCTLCMD)
31776b96018bSArnd Bergmann 		ret = compat_sock_ioctl_trans(file, sock, cmd, arg);
31786b96018bSArnd Bergmann 
317989bbfc95SShaun Pereira 	return ret;
318089bbfc95SShaun Pereira }
318189bbfc95SShaun Pereira #endif
318289bbfc95SShaun Pereira 
3183ac5a488eSSridhar Samudrala int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
3184ac5a488eSSridhar Samudrala {
3185ac5a488eSSridhar Samudrala 	return sock->ops->bind(sock, addr, addrlen);
3186ac5a488eSSridhar Samudrala }
3187c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_bind);
3188ac5a488eSSridhar Samudrala 
3189ac5a488eSSridhar Samudrala int kernel_listen(struct socket *sock, int backlog)
3190ac5a488eSSridhar Samudrala {
3191ac5a488eSSridhar Samudrala 	return sock->ops->listen(sock, backlog);
3192ac5a488eSSridhar Samudrala }
3193c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_listen);
3194ac5a488eSSridhar Samudrala 
3195ac5a488eSSridhar Samudrala int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
3196ac5a488eSSridhar Samudrala {
3197ac5a488eSSridhar Samudrala 	struct sock *sk = sock->sk;
3198ac5a488eSSridhar Samudrala 	int err;
3199ac5a488eSSridhar Samudrala 
3200ac5a488eSSridhar Samudrala 	err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
3201ac5a488eSSridhar Samudrala 			       newsock);
3202ac5a488eSSridhar Samudrala 	if (err < 0)
3203ac5a488eSSridhar Samudrala 		goto done;
3204ac5a488eSSridhar Samudrala 
3205cdfbabfbSDavid Howells 	err = sock->ops->accept(sock, *newsock, flags, true);
3206ac5a488eSSridhar Samudrala 	if (err < 0) {
3207ac5a488eSSridhar Samudrala 		sock_release(*newsock);
3208fa8705b0STony Battersby 		*newsock = NULL;
3209ac5a488eSSridhar Samudrala 		goto done;
3210ac5a488eSSridhar Samudrala 	}
3211ac5a488eSSridhar Samudrala 
3212ac5a488eSSridhar Samudrala 	(*newsock)->ops = sock->ops;
32131b08534eSWei Yongjun 	__module_get((*newsock)->ops->owner);
3214ac5a488eSSridhar Samudrala 
3215ac5a488eSSridhar Samudrala done:
3216ac5a488eSSridhar Samudrala 	return err;
3217ac5a488eSSridhar Samudrala }
3218c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_accept);
3219ac5a488eSSridhar Samudrala 
3220ac5a488eSSridhar Samudrala int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
3221ac5a488eSSridhar Samudrala 		   int flags)
3222ac5a488eSSridhar Samudrala {
3223ac5a488eSSridhar Samudrala 	return sock->ops->connect(sock, addr, addrlen, flags);
3224ac5a488eSSridhar Samudrala }
3225c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_connect);
3226ac5a488eSSridhar Samudrala 
3227ac5a488eSSridhar Samudrala int kernel_getsockname(struct socket *sock, struct sockaddr *addr,
3228ac5a488eSSridhar Samudrala 			 int *addrlen)
3229ac5a488eSSridhar Samudrala {
3230ac5a488eSSridhar Samudrala 	return sock->ops->getname(sock, addr, addrlen, 0);
3231ac5a488eSSridhar Samudrala }
3232c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockname);
3233ac5a488eSSridhar Samudrala 
3234ac5a488eSSridhar Samudrala int kernel_getpeername(struct socket *sock, struct sockaddr *addr,
3235ac5a488eSSridhar Samudrala 			 int *addrlen)
3236ac5a488eSSridhar Samudrala {
3237ac5a488eSSridhar Samudrala 	return sock->ops->getname(sock, addr, addrlen, 1);
3238ac5a488eSSridhar Samudrala }
3239c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getpeername);
3240ac5a488eSSridhar Samudrala 
3241ac5a488eSSridhar Samudrala int kernel_getsockopt(struct socket *sock, int level, int optname,
3242ac5a488eSSridhar Samudrala 			char *optval, int *optlen)
3243ac5a488eSSridhar Samudrala {
3244ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3245fb8621bbSNamhyung Kim 	char __user *uoptval;
3246fb8621bbSNamhyung Kim 	int __user *uoptlen;
3247ac5a488eSSridhar Samudrala 	int err;
3248ac5a488eSSridhar Samudrala 
3249fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3250fb8621bbSNamhyung Kim 	uoptlen = (int __user __force *) optlen;
3251fb8621bbSNamhyung Kim 
3252ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3253ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3254fb8621bbSNamhyung Kim 		err = sock_getsockopt(sock, level, optname, uoptval, uoptlen);
3255ac5a488eSSridhar Samudrala 	else
3256fb8621bbSNamhyung Kim 		err = sock->ops->getsockopt(sock, level, optname, uoptval,
3257fb8621bbSNamhyung Kim 					    uoptlen);
3258ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3259ac5a488eSSridhar Samudrala 	return err;
3260ac5a488eSSridhar Samudrala }
3261c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockopt);
3262ac5a488eSSridhar Samudrala 
3263ac5a488eSSridhar Samudrala int kernel_setsockopt(struct socket *sock, int level, int optname,
3264b7058842SDavid S. Miller 			char *optval, unsigned int optlen)
3265ac5a488eSSridhar Samudrala {
3266ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3267fb8621bbSNamhyung Kim 	char __user *uoptval;
3268ac5a488eSSridhar Samudrala 	int err;
3269ac5a488eSSridhar Samudrala 
3270fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3271fb8621bbSNamhyung Kim 
3272ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3273ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3274fb8621bbSNamhyung Kim 		err = sock_setsockopt(sock, level, optname, uoptval, optlen);
3275ac5a488eSSridhar Samudrala 	else
3276fb8621bbSNamhyung Kim 		err = sock->ops->setsockopt(sock, level, optname, uoptval,
3277ac5a488eSSridhar Samudrala 					    optlen);
3278ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3279ac5a488eSSridhar Samudrala 	return err;
3280ac5a488eSSridhar Samudrala }
3281c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_setsockopt);
3282ac5a488eSSridhar Samudrala 
3283ac5a488eSSridhar Samudrala int kernel_sendpage(struct socket *sock, struct page *page, int offset,
3284ac5a488eSSridhar Samudrala 		    size_t size, int flags)
3285ac5a488eSSridhar Samudrala {
3286ac5a488eSSridhar Samudrala 	if (sock->ops->sendpage)
3287ac5a488eSSridhar Samudrala 		return sock->ops->sendpage(sock, page, offset, size, flags);
3288ac5a488eSSridhar Samudrala 
3289ac5a488eSSridhar Samudrala 	return sock_no_sendpage(sock, page, offset, size, flags);
3290ac5a488eSSridhar Samudrala }
3291c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendpage);
3292ac5a488eSSridhar Samudrala 
3293306b13ebSTom Herbert int kernel_sendpage_locked(struct sock *sk, struct page *page, int offset,
3294306b13ebSTom Herbert 			   size_t size, int flags)
3295306b13ebSTom Herbert {
3296306b13ebSTom Herbert 	struct socket *sock = sk->sk_socket;
3297306b13ebSTom Herbert 
3298306b13ebSTom Herbert 	if (sock->ops->sendpage_locked)
3299306b13ebSTom Herbert 		return sock->ops->sendpage_locked(sk, page, offset, size,
3300306b13ebSTom Herbert 						  flags);
3301306b13ebSTom Herbert 
3302306b13ebSTom Herbert 	return sock_no_sendpage_locked(sk, page, offset, size, flags);
3303306b13ebSTom Herbert }
3304306b13ebSTom Herbert EXPORT_SYMBOL(kernel_sendpage_locked);
3305306b13ebSTom Herbert 
330691cf45f0STrond Myklebust int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
330791cf45f0STrond Myklebust {
330891cf45f0STrond Myklebust 	return sock->ops->shutdown(sock, how);
330991cf45f0STrond Myklebust }
331091cf45f0STrond Myklebust EXPORT_SYMBOL(kernel_sock_shutdown);
3311113c3075SR. Parameswaran 
3312113c3075SR. Parameswaran /* This routine returns the IP overhead imposed by a socket i.e.
3313113c3075SR. Parameswaran  * the length of the underlying IP header, depending on whether
3314113c3075SR. Parameswaran  * this is an IPv4 or IPv6 socket and the length from IP options turned
331557240d00SR. Parameswaran  * on at the socket. Assumes that the caller has a lock on the socket.
3316113c3075SR. Parameswaran  */
3317113c3075SR. Parameswaran u32 kernel_sock_ip_overhead(struct sock *sk)
3318113c3075SR. Parameswaran {
3319113c3075SR. Parameswaran 	struct inet_sock *inet;
3320113c3075SR. Parameswaran 	struct ip_options_rcu *opt;
3321113c3075SR. Parameswaran 	u32 overhead = 0;
3322113c3075SR. Parameswaran #if IS_ENABLED(CONFIG_IPV6)
3323113c3075SR. Parameswaran 	struct ipv6_pinfo *np;
3324113c3075SR. Parameswaran 	struct ipv6_txoptions *optv6 = NULL;
3325113c3075SR. Parameswaran #endif /* IS_ENABLED(CONFIG_IPV6) */
3326113c3075SR. Parameswaran 
3327113c3075SR. Parameswaran 	if (!sk)
3328113c3075SR. Parameswaran 		return overhead;
3329113c3075SR. Parameswaran 
3330113c3075SR. Parameswaran 	switch (sk->sk_family) {
3331113c3075SR. Parameswaran 	case AF_INET:
3332113c3075SR. Parameswaran 		inet = inet_sk(sk);
3333113c3075SR. Parameswaran 		overhead += sizeof(struct iphdr);
3334113c3075SR. Parameswaran 		opt = rcu_dereference_protected(inet->inet_opt,
3335614d79c0Sstephen hemminger 						sock_owned_by_user(sk));
3336113c3075SR. Parameswaran 		if (opt)
3337113c3075SR. Parameswaran 			overhead += opt->opt.optlen;
3338113c3075SR. Parameswaran 		return overhead;
3339113c3075SR. Parameswaran #if IS_ENABLED(CONFIG_IPV6)
3340113c3075SR. Parameswaran 	case AF_INET6:
3341113c3075SR. Parameswaran 		np = inet6_sk(sk);
3342113c3075SR. Parameswaran 		overhead += sizeof(struct ipv6hdr);
3343113c3075SR. Parameswaran 		if (np)
3344113c3075SR. Parameswaran 			optv6 = rcu_dereference_protected(np->opt,
3345614d79c0Sstephen hemminger 							  sock_owned_by_user(sk));
3346113c3075SR. Parameswaran 		if (optv6)
3347113c3075SR. Parameswaran 			overhead += (optv6->opt_flen + optv6->opt_nflen);
3348113c3075SR. Parameswaran 		return overhead;
3349113c3075SR. Parameswaran #endif /* IS_ENABLED(CONFIG_IPV6) */
3350113c3075SR. Parameswaran 	default: /* Returns 0 overhead if the socket is not ipv4 or ipv6 */
3351113c3075SR. Parameswaran 		return overhead;
3352113c3075SR. Parameswaran 	}
3353113c3075SR. Parameswaran }
3354113c3075SR. Parameswaran EXPORT_SYMBOL(kernel_sock_ip_overhead);
3355