xref: /openbmc/linux/net/socket.c (revision 6d652330)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * NET		An implementation of the SOCKET network access protocol.
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Version:	@(#)socket.c	1.1.93	18/02/95
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * Authors:	Orest Zborowski, <obz@Kodak.COM>
702c30a84SJesper Juhl  *		Ross Biro
81da177e4SLinus Torvalds  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
91da177e4SLinus Torvalds  *
101da177e4SLinus Torvalds  * Fixes:
111da177e4SLinus Torvalds  *		Anonymous	:	NOTSOCK/BADF cleanup. Error fix in
121da177e4SLinus Torvalds  *					shutdown()
131da177e4SLinus Torvalds  *		Alan Cox	:	verify_area() fixes
141da177e4SLinus Torvalds  *		Alan Cox	:	Removed DDI
151da177e4SLinus Torvalds  *		Jonathan Kamens	:	SOCK_DGRAM reconnect bug
161da177e4SLinus Torvalds  *		Alan Cox	:	Moved a load of checks to the very
171da177e4SLinus Torvalds  *					top level.
181da177e4SLinus Torvalds  *		Alan Cox	:	Move address structures to/from user
191da177e4SLinus Torvalds  *					mode above the protocol layers.
201da177e4SLinus Torvalds  *		Rob Janssen	:	Allow 0 length sends.
211da177e4SLinus Torvalds  *		Alan Cox	:	Asynchronous I/O support (cribbed from the
221da177e4SLinus Torvalds  *					tty drivers).
231da177e4SLinus Torvalds  *		Niibe Yutaka	:	Asynchronous I/O for writes (4.4BSD style)
241da177e4SLinus Torvalds  *		Jeff Uphoff	:	Made max number of sockets command-line
251da177e4SLinus Torvalds  *					configurable.
261da177e4SLinus Torvalds  *		Matti Aarnio	:	Made the number of sockets dynamic,
271da177e4SLinus Torvalds  *					to be allocated when needed, and mr.
281da177e4SLinus Torvalds  *					Uphoff's max is used as max to be
291da177e4SLinus Torvalds  *					allowed to allocate.
301da177e4SLinus Torvalds  *		Linus		:	Argh. removed all the socket allocation
311da177e4SLinus Torvalds  *					altogether: it's in the inode now.
321da177e4SLinus Torvalds  *		Alan Cox	:	Made sock_alloc()/sock_release() public
331da177e4SLinus Torvalds  *					for NetROM and future kernel nfsd type
341da177e4SLinus Torvalds  *					stuff.
351da177e4SLinus Torvalds  *		Alan Cox	:	sendmsg/recvmsg basics.
361da177e4SLinus Torvalds  *		Tom Dyas	:	Export net symbols.
371da177e4SLinus Torvalds  *		Marcin Dalecki	:	Fixed problems with CONFIG_NET="n".
381da177e4SLinus Torvalds  *		Alan Cox	:	Added thread locking to sys_* calls
391da177e4SLinus Torvalds  *					for sockets. May have errors at the
401da177e4SLinus Torvalds  *					moment.
411da177e4SLinus Torvalds  *		Kevin Buhr	:	Fixed the dumb errors in the above.
421da177e4SLinus Torvalds  *		Andi Kleen	:	Some small cleanups, optimizations,
431da177e4SLinus Torvalds  *					and fixed a copy_from_user() bug.
441da177e4SLinus Torvalds  *		Tigran Aivazian	:	sys_send(args) calls sys_sendto(args, NULL, 0)
451da177e4SLinus Torvalds  *		Tigran Aivazian	:	Made listen(2) backlog sanity checks
461da177e4SLinus Torvalds  *					protocol-independent
471da177e4SLinus Torvalds  *
481da177e4SLinus Torvalds  *
491da177e4SLinus Torvalds  *		This program is free software; you can redistribute it and/or
501da177e4SLinus Torvalds  *		modify it under the terms of the GNU General Public License
511da177e4SLinus Torvalds  *		as published by the Free Software Foundation; either version
521da177e4SLinus Torvalds  *		2 of the License, or (at your option) any later version.
531da177e4SLinus Torvalds  *
541da177e4SLinus Torvalds  *
551da177e4SLinus Torvalds  *	This module is effectively the top level interface to the BSD socket
561da177e4SLinus Torvalds  *	paradigm.
571da177e4SLinus Torvalds  *
581da177e4SLinus Torvalds  *	Based upon Swansea University Computer Society NET3.039
591da177e4SLinus Torvalds  */
601da177e4SLinus Torvalds 
611da177e4SLinus Torvalds #include <linux/mm.h>
621da177e4SLinus Torvalds #include <linux/socket.h>
631da177e4SLinus Torvalds #include <linux/file.h>
641da177e4SLinus Torvalds #include <linux/net.h>
651da177e4SLinus Torvalds #include <linux/interrupt.h>
66aaca0bdcSUlrich Drepper #include <linux/thread_info.h>
6755737fdaSStephen Hemminger #include <linux/rcupdate.h>
681da177e4SLinus Torvalds #include <linux/netdevice.h>
691da177e4SLinus Torvalds #include <linux/proc_fs.h>
701da177e4SLinus Torvalds #include <linux/seq_file.h>
714a3e2f71SArjan van de Ven #include <linux/mutex.h>
721da177e4SLinus Torvalds #include <linux/if_bridge.h>
7320380731SArnaldo Carvalho de Melo #include <linux/if_frad.h>
7420380731SArnaldo Carvalho de Melo #include <linux/if_vlan.h>
75408eccceSDaniel Borkmann #include <linux/ptp_classify.h>
761da177e4SLinus Torvalds #include <linux/init.h>
771da177e4SLinus Torvalds #include <linux/poll.h>
781da177e4SLinus Torvalds #include <linux/cache.h>
791da177e4SLinus Torvalds #include <linux/module.h>
801da177e4SLinus Torvalds #include <linux/highmem.h>
811da177e4SLinus Torvalds #include <linux/mount.h>
821da177e4SLinus Torvalds #include <linux/security.h>
831da177e4SLinus Torvalds #include <linux/syscalls.h>
841da177e4SLinus Torvalds #include <linux/compat.h>
851da177e4SLinus Torvalds #include <linux/kmod.h>
863ec3b2fbSDavid Woodhouse #include <linux/audit.h>
87d86b5e0eSAdrian Bunk #include <linux/wireless.h>
881b8d7ae4SEric W. Biederman #include <linux/nsproxy.h>
891fd7317dSNick Black #include <linux/magic.h>
905a0e3ad6STejun Heo #include <linux/slab.h>
91600e1779SMasatake YAMATO #include <linux/xattr.h>
921da177e4SLinus Torvalds 
931da177e4SLinus Torvalds #include <asm/uaccess.h>
941da177e4SLinus Torvalds #include <asm/unistd.h>
951da177e4SLinus Torvalds 
961da177e4SLinus Torvalds #include <net/compat.h>
9787de87d5SDavid S. Miller #include <net/wext.h>
98f8451725SHerbert Xu #include <net/cls_cgroup.h>
991da177e4SLinus Torvalds 
1001da177e4SLinus Torvalds #include <net/sock.h>
1011da177e4SLinus Torvalds #include <linux/netfilter.h>
1021da177e4SLinus Torvalds 
1036b96018bSArnd Bergmann #include <linux/if_tun.h>
1046b96018bSArnd Bergmann #include <linux/ipv6_route.h>
1056b96018bSArnd Bergmann #include <linux/route.h>
1066b96018bSArnd Bergmann #include <linux/sockios.h>
1076b96018bSArnd Bergmann #include <linux/atalk.h>
108076bb0c8SEliezer Tamir #include <net/busy_poll.h>
109f24b9be5SWillem de Bruijn #include <linux/errqueue.h>
11006021292SEliezer Tamir 
111e0d1095aSCong Wang #ifdef CONFIG_NET_RX_BUSY_POLL
11264b0dc51SEliezer Tamir unsigned int sysctl_net_busy_read __read_mostly;
11364b0dc51SEliezer Tamir unsigned int sysctl_net_busy_poll __read_mostly;
11406021292SEliezer Tamir #endif
1156b96018bSArnd Bergmann 
116027445c3SBadari Pulavarty static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
117027445c3SBadari Pulavarty 			 unsigned long nr_segs, loff_t pos);
118027445c3SBadari Pulavarty static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
119027445c3SBadari Pulavarty 			  unsigned long nr_segs, loff_t pos);
1201da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma);
1211da177e4SLinus Torvalds 
1221da177e4SLinus Torvalds static int sock_close(struct inode *inode, struct file *file);
1231da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file,
1241da177e4SLinus Torvalds 			      struct poll_table_struct *wait);
12589bddce5SStephen Hemminger static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
12689bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
12789bbfc95SShaun Pereira static long compat_sock_ioctl(struct file *file,
12889bbfc95SShaun Pereira 			      unsigned int cmd, unsigned long arg);
12989bbfc95SShaun Pereira #endif
1301da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on);
1311da177e4SLinus Torvalds static ssize_t sock_sendpage(struct file *file, struct page *page,
1321da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more);
1339c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
1349c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
1359c55e01cSJens Axboe 				unsigned int flags);
1361da177e4SLinus Torvalds 
1371da177e4SLinus Torvalds /*
1381da177e4SLinus Torvalds  *	Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
1391da177e4SLinus Torvalds  *	in the operation structures but are done directly via the socketcall() multiplexor.
1401da177e4SLinus Torvalds  */
1411da177e4SLinus Torvalds 
142da7071d7SArjan van de Ven static const struct file_operations socket_file_ops = {
1431da177e4SLinus Torvalds 	.owner =	THIS_MODULE,
1441da177e4SLinus Torvalds 	.llseek =	no_llseek,
1451da177e4SLinus Torvalds 	.aio_read =	sock_aio_read,
1461da177e4SLinus Torvalds 	.aio_write =	sock_aio_write,
1471da177e4SLinus Torvalds 	.poll =		sock_poll,
1481da177e4SLinus Torvalds 	.unlocked_ioctl = sock_ioctl,
14989bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
15089bbfc95SShaun Pereira 	.compat_ioctl = compat_sock_ioctl,
15189bbfc95SShaun Pereira #endif
1521da177e4SLinus Torvalds 	.mmap =		sock_mmap,
1531da177e4SLinus Torvalds 	.release =	sock_close,
1541da177e4SLinus Torvalds 	.fasync =	sock_fasync,
1555274f052SJens Axboe 	.sendpage =	sock_sendpage,
1565274f052SJens Axboe 	.splice_write = generic_splice_sendpage,
1579c55e01cSJens Axboe 	.splice_read =	sock_splice_read,
1581da177e4SLinus Torvalds };
1591da177e4SLinus Torvalds 
1601da177e4SLinus Torvalds /*
1611da177e4SLinus Torvalds  *	The protocol list. Each protocol is registered in here.
1621da177e4SLinus Torvalds  */
1631da177e4SLinus Torvalds 
1641da177e4SLinus Torvalds static DEFINE_SPINLOCK(net_family_lock);
165190683a9SEric Dumazet static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly;
1661da177e4SLinus Torvalds 
1671da177e4SLinus Torvalds /*
1681da177e4SLinus Torvalds  *	Statistics counters of the socket lists
1691da177e4SLinus Torvalds  */
1701da177e4SLinus Torvalds 
171c6d409cfSEric Dumazet static DEFINE_PER_CPU(int, sockets_in_use);
1721da177e4SLinus Torvalds 
1731da177e4SLinus Torvalds /*
17489bddce5SStephen Hemminger  * Support routines.
17589bddce5SStephen Hemminger  * Move socket addresses back and forth across the kernel/user
1761da177e4SLinus Torvalds  * divide and look after the messy bits.
1771da177e4SLinus Torvalds  */
1781da177e4SLinus Torvalds 
1791da177e4SLinus Torvalds /**
1801da177e4SLinus Torvalds  *	move_addr_to_kernel	-	copy a socket address into kernel space
1811da177e4SLinus Torvalds  *	@uaddr: Address in user space
1821da177e4SLinus Torvalds  *	@kaddr: Address in kernel space
1831da177e4SLinus Torvalds  *	@ulen: Length in user space
1841da177e4SLinus Torvalds  *
1851da177e4SLinus Torvalds  *	The address is copied into kernel space. If the provided address is
1861da177e4SLinus Torvalds  *	too long an error code of -EINVAL is returned. If the copy gives
1871da177e4SLinus Torvalds  *	invalid addresses -EFAULT is returned. On a success 0 is returned.
1881da177e4SLinus Torvalds  */
1891da177e4SLinus Torvalds 
19043db362dSMaciej Żenczykowski int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr)
1911da177e4SLinus Torvalds {
192230b1839SYOSHIFUJI Hideaki 	if (ulen < 0 || ulen > sizeof(struct sockaddr_storage))
1931da177e4SLinus Torvalds 		return -EINVAL;
1941da177e4SLinus Torvalds 	if (ulen == 0)
1951da177e4SLinus Torvalds 		return 0;
1961da177e4SLinus Torvalds 	if (copy_from_user(kaddr, uaddr, ulen))
1971da177e4SLinus Torvalds 		return -EFAULT;
1983ec3b2fbSDavid Woodhouse 	return audit_sockaddr(ulen, kaddr);
1991da177e4SLinus Torvalds }
2001da177e4SLinus Torvalds 
2011da177e4SLinus Torvalds /**
2021da177e4SLinus Torvalds  *	move_addr_to_user	-	copy an address to user space
2031da177e4SLinus Torvalds  *	@kaddr: kernel space address
2041da177e4SLinus Torvalds  *	@klen: length of address in kernel
2051da177e4SLinus Torvalds  *	@uaddr: user space address
2061da177e4SLinus Torvalds  *	@ulen: pointer to user length field
2071da177e4SLinus Torvalds  *
2081da177e4SLinus Torvalds  *	The value pointed to by ulen on entry is the buffer length available.
2091da177e4SLinus Torvalds  *	This is overwritten with the buffer space used. -EINVAL is returned
2101da177e4SLinus Torvalds  *	if an overlong buffer is specified or a negative buffer size. -EFAULT
2111da177e4SLinus Torvalds  *	is returned if either the buffer or the length field are not
2121da177e4SLinus Torvalds  *	accessible.
2131da177e4SLinus Torvalds  *	After copying the data up to the limit the user specifies, the true
2141da177e4SLinus Torvalds  *	length of the data is written over the length limit the user
2151da177e4SLinus Torvalds  *	specified. Zero is returned for a success.
2161da177e4SLinus Torvalds  */
2171da177e4SLinus Torvalds 
21843db362dSMaciej Żenczykowski static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen,
21911165f14Sstephen hemminger 			     void __user *uaddr, int __user *ulen)
2201da177e4SLinus Torvalds {
2211da177e4SLinus Torvalds 	int err;
2221da177e4SLinus Torvalds 	int len;
2231da177e4SLinus Torvalds 
22468c6beb3SHannes Frederic Sowa 	BUG_ON(klen > sizeof(struct sockaddr_storage));
22589bddce5SStephen Hemminger 	err = get_user(len, ulen);
22689bddce5SStephen Hemminger 	if (err)
2271da177e4SLinus Torvalds 		return err;
2281da177e4SLinus Torvalds 	if (len > klen)
2291da177e4SLinus Torvalds 		len = klen;
23068c6beb3SHannes Frederic Sowa 	if (len < 0)
2311da177e4SLinus Torvalds 		return -EINVAL;
23289bddce5SStephen Hemminger 	if (len) {
233d6fe3945SSteve Grubb 		if (audit_sockaddr(klen, kaddr))
234d6fe3945SSteve Grubb 			return -ENOMEM;
2351da177e4SLinus Torvalds 		if (copy_to_user(uaddr, kaddr, len))
2361da177e4SLinus Torvalds 			return -EFAULT;
2371da177e4SLinus Torvalds 	}
2381da177e4SLinus Torvalds 	/*
2391da177e4SLinus Torvalds 	 *      "fromlen shall refer to the value before truncation.."
2401da177e4SLinus Torvalds 	 *                      1003.1g
2411da177e4SLinus Torvalds 	 */
2421da177e4SLinus Torvalds 	return __put_user(klen, ulen);
2431da177e4SLinus Torvalds }
2441da177e4SLinus Torvalds 
245e18b890bSChristoph Lameter static struct kmem_cache *sock_inode_cachep __read_mostly;
2461da177e4SLinus Torvalds 
2471da177e4SLinus Torvalds static struct inode *sock_alloc_inode(struct super_block *sb)
2481da177e4SLinus Torvalds {
2491da177e4SLinus Torvalds 	struct socket_alloc *ei;
250eaefd110SEric Dumazet 	struct socket_wq *wq;
25189bddce5SStephen Hemminger 
252e94b1766SChristoph Lameter 	ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL);
2531da177e4SLinus Torvalds 	if (!ei)
2541da177e4SLinus Torvalds 		return NULL;
255eaefd110SEric Dumazet 	wq = kmalloc(sizeof(*wq), GFP_KERNEL);
256eaefd110SEric Dumazet 	if (!wq) {
25743815482SEric Dumazet 		kmem_cache_free(sock_inode_cachep, ei);
25843815482SEric Dumazet 		return NULL;
25943815482SEric Dumazet 	}
260eaefd110SEric Dumazet 	init_waitqueue_head(&wq->wait);
261eaefd110SEric Dumazet 	wq->fasync_list = NULL;
262eaefd110SEric Dumazet 	RCU_INIT_POINTER(ei->socket.wq, wq);
2631da177e4SLinus Torvalds 
2641da177e4SLinus Torvalds 	ei->socket.state = SS_UNCONNECTED;
2651da177e4SLinus Torvalds 	ei->socket.flags = 0;
2661da177e4SLinus Torvalds 	ei->socket.ops = NULL;
2671da177e4SLinus Torvalds 	ei->socket.sk = NULL;
2681da177e4SLinus Torvalds 	ei->socket.file = NULL;
2691da177e4SLinus Torvalds 
2701da177e4SLinus Torvalds 	return &ei->vfs_inode;
2711da177e4SLinus Torvalds }
2721da177e4SLinus Torvalds 
2731da177e4SLinus Torvalds static void sock_destroy_inode(struct inode *inode)
2741da177e4SLinus Torvalds {
27543815482SEric Dumazet 	struct socket_alloc *ei;
276eaefd110SEric Dumazet 	struct socket_wq *wq;
27743815482SEric Dumazet 
27843815482SEric Dumazet 	ei = container_of(inode, struct socket_alloc, vfs_inode);
279eaefd110SEric Dumazet 	wq = rcu_dereference_protected(ei->socket.wq, 1);
28061845220SLai Jiangshan 	kfree_rcu(wq, rcu);
28143815482SEric Dumazet 	kmem_cache_free(sock_inode_cachep, ei);
2821da177e4SLinus Torvalds }
2831da177e4SLinus Torvalds 
28451cc5068SAlexey Dobriyan static void init_once(void *foo)
2851da177e4SLinus Torvalds {
2861da177e4SLinus Torvalds 	struct socket_alloc *ei = (struct socket_alloc *)foo;
2871da177e4SLinus Torvalds 
2881da177e4SLinus Torvalds 	inode_init_once(&ei->vfs_inode);
2891da177e4SLinus Torvalds }
2901da177e4SLinus Torvalds 
2911da177e4SLinus Torvalds static int init_inodecache(void)
2921da177e4SLinus Torvalds {
2931da177e4SLinus Torvalds 	sock_inode_cachep = kmem_cache_create("sock_inode_cache",
2941da177e4SLinus Torvalds 					      sizeof(struct socket_alloc),
29589bddce5SStephen Hemminger 					      0,
29689bddce5SStephen Hemminger 					      (SLAB_HWCACHE_ALIGN |
29789bddce5SStephen Hemminger 					       SLAB_RECLAIM_ACCOUNT |
298fffb60f9SPaul Jackson 					       SLAB_MEM_SPREAD),
29920c2df83SPaul Mundt 					      init_once);
3001da177e4SLinus Torvalds 	if (sock_inode_cachep == NULL)
3011da177e4SLinus Torvalds 		return -ENOMEM;
3021da177e4SLinus Torvalds 	return 0;
3031da177e4SLinus Torvalds }
3041da177e4SLinus Torvalds 
305b87221deSAlexey Dobriyan static const struct super_operations sockfs_ops = {
3061da177e4SLinus Torvalds 	.alloc_inode	= sock_alloc_inode,
3071da177e4SLinus Torvalds 	.destroy_inode	= sock_destroy_inode,
3081da177e4SLinus Torvalds 	.statfs		= simple_statfs,
3091da177e4SLinus Torvalds };
3101da177e4SLinus Torvalds 
311c23fbb6bSEric Dumazet /*
312c23fbb6bSEric Dumazet  * sockfs_dname() is called from d_path().
313c23fbb6bSEric Dumazet  */
314c23fbb6bSEric Dumazet static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen)
315c23fbb6bSEric Dumazet {
316c23fbb6bSEric Dumazet 	return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]",
317c23fbb6bSEric Dumazet 				dentry->d_inode->i_ino);
318c23fbb6bSEric Dumazet }
319c23fbb6bSEric Dumazet 
3203ba13d17SAl Viro static const struct dentry_operations sockfs_dentry_operations = {
321c23fbb6bSEric Dumazet 	.d_dname  = sockfs_dname,
3221da177e4SLinus Torvalds };
3231da177e4SLinus Torvalds 
324c74a1cbbSAl Viro static struct dentry *sockfs_mount(struct file_system_type *fs_type,
325c74a1cbbSAl Viro 			 int flags, const char *dev_name, void *data)
326c74a1cbbSAl Viro {
327c74a1cbbSAl Viro 	return mount_pseudo(fs_type, "socket:", &sockfs_ops,
328c74a1cbbSAl Viro 		&sockfs_dentry_operations, SOCKFS_MAGIC);
329c74a1cbbSAl Viro }
330c74a1cbbSAl Viro 
331c74a1cbbSAl Viro static struct vfsmount *sock_mnt __read_mostly;
332c74a1cbbSAl Viro 
333c74a1cbbSAl Viro static struct file_system_type sock_fs_type = {
334c74a1cbbSAl Viro 	.name =		"sockfs",
335c74a1cbbSAl Viro 	.mount =	sockfs_mount,
336c74a1cbbSAl Viro 	.kill_sb =	kill_anon_super,
337c74a1cbbSAl Viro };
338c74a1cbbSAl Viro 
3391da177e4SLinus Torvalds /*
3401da177e4SLinus Torvalds  *	Obtains the first available file descriptor and sets it up for use.
3411da177e4SLinus Torvalds  *
34239d8c1b6SDavid S. Miller  *	These functions create file structures and maps them to fd space
34339d8c1b6SDavid S. Miller  *	of the current process. On success it returns file descriptor
3441da177e4SLinus Torvalds  *	and file struct implicitly stored in sock->file.
3451da177e4SLinus Torvalds  *	Note that another thread may close file descriptor before we return
3461da177e4SLinus Torvalds  *	from this function. We use the fact that now we do not refer
3471da177e4SLinus Torvalds  *	to socket after mapping. If one day we will need it, this
3481da177e4SLinus Torvalds  *	function will increment ref. count on file by 1.
3491da177e4SLinus Torvalds  *
3501da177e4SLinus Torvalds  *	In any case returned fd MAY BE not valid!
3511da177e4SLinus Torvalds  *	This race condition is unavoidable
3521da177e4SLinus Torvalds  *	with shared fd spaces, we cannot solve it inside kernel,
3531da177e4SLinus Torvalds  *	but we take care of internal coherence yet.
3541da177e4SLinus Torvalds  */
3551da177e4SLinus Torvalds 
356aab174f0SLinus Torvalds struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)
3571da177e4SLinus Torvalds {
3587cbe66b6SAl Viro 	struct qstr name = { .name = "" };
3592c48b9c4SAl Viro 	struct path path;
3607cbe66b6SAl Viro 	struct file *file;
3611da177e4SLinus Torvalds 
362600e1779SMasatake YAMATO 	if (dname) {
363600e1779SMasatake YAMATO 		name.name = dname;
364600e1779SMasatake YAMATO 		name.len = strlen(name.name);
365600e1779SMasatake YAMATO 	} else if (sock->sk) {
366600e1779SMasatake YAMATO 		name.name = sock->sk->sk_prot_creator->name;
367600e1779SMasatake YAMATO 		name.len = strlen(name.name);
368600e1779SMasatake YAMATO 	}
3694b936885SNick Piggin 	path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name);
37028407630SAl Viro 	if (unlikely(!path.dentry))
37128407630SAl Viro 		return ERR_PTR(-ENOMEM);
3722c48b9c4SAl Viro 	path.mnt = mntget(sock_mnt);
37339d8c1b6SDavid S. Miller 
3742c48b9c4SAl Viro 	d_instantiate(path.dentry, SOCK_INODE(sock));
375cc3808f8SAl Viro 
3762c48b9c4SAl Viro 	file = alloc_file(&path, FMODE_READ | FMODE_WRITE,
377cc3808f8SAl Viro 		  &socket_file_ops);
37839b65252SAnatol Pomozov 	if (unlikely(IS_ERR(file))) {
379cc3808f8SAl Viro 		/* drop dentry, keep inode */
3807de9c6eeSAl Viro 		ihold(path.dentry->d_inode);
3812c48b9c4SAl Viro 		path_put(&path);
38239b65252SAnatol Pomozov 		return file;
383cc3808f8SAl Viro 	}
3841da177e4SLinus Torvalds 
3851da177e4SLinus Torvalds 	sock->file = file;
38677d27200SUlrich Drepper 	file->f_flags = O_RDWR | (flags & O_NONBLOCK);
38707dc3f07SBenjamin LaHaise 	file->private_data = sock;
38828407630SAl Viro 	return file;
3891da177e4SLinus Torvalds }
39056b31d1cSAl Viro EXPORT_SYMBOL(sock_alloc_file);
3911da177e4SLinus Torvalds 
39256b31d1cSAl Viro static int sock_map_fd(struct socket *sock, int flags)
39339d8c1b6SDavid S. Miller {
39439d8c1b6SDavid S. Miller 	struct file *newfile;
39528407630SAl Viro 	int fd = get_unused_fd_flags(flags);
39628407630SAl Viro 	if (unlikely(fd < 0))
3971da177e4SLinus Torvalds 		return fd;
3981da177e4SLinus Torvalds 
399aab174f0SLinus Torvalds 	newfile = sock_alloc_file(sock, flags, NULL);
40028407630SAl Viro 	if (likely(!IS_ERR(newfile))) {
4011da177e4SLinus Torvalds 		fd_install(fd, newfile);
4021da177e4SLinus Torvalds 		return fd;
4031da177e4SLinus Torvalds 	}
40428407630SAl Viro 
40528407630SAl Viro 	put_unused_fd(fd);
40628407630SAl Viro 	return PTR_ERR(newfile);
4071da177e4SLinus Torvalds }
4081da177e4SLinus Torvalds 
409406a3c63SJohn Fastabend struct socket *sock_from_file(struct file *file, int *err)
4106cb153caSBenjamin LaHaise {
4116cb153caSBenjamin LaHaise 	if (file->f_op == &socket_file_ops)
4126cb153caSBenjamin LaHaise 		return file->private_data;	/* set in sock_map_fd */
4136cb153caSBenjamin LaHaise 
4146cb153caSBenjamin LaHaise 	*err = -ENOTSOCK;
4156cb153caSBenjamin LaHaise 	return NULL;
4166cb153caSBenjamin LaHaise }
417406a3c63SJohn Fastabend EXPORT_SYMBOL(sock_from_file);
4186cb153caSBenjamin LaHaise 
4191da177e4SLinus Torvalds /**
4201da177e4SLinus Torvalds  *	sockfd_lookup - Go from a file number to its socket slot
4211da177e4SLinus Torvalds  *	@fd: file handle
4221da177e4SLinus Torvalds  *	@err: pointer to an error code return
4231da177e4SLinus Torvalds  *
4241da177e4SLinus Torvalds  *	The file handle passed in is locked and the socket it is bound
4251da177e4SLinus Torvalds  *	too is returned. If an error occurs the err pointer is overwritten
4261da177e4SLinus Torvalds  *	with a negative errno code and NULL is returned. The function checks
4271da177e4SLinus Torvalds  *	for both invalid handles and passing a handle which is not a socket.
4281da177e4SLinus Torvalds  *
4291da177e4SLinus Torvalds  *	On a success the socket object pointer is returned.
4301da177e4SLinus Torvalds  */
4311da177e4SLinus Torvalds 
4321da177e4SLinus Torvalds struct socket *sockfd_lookup(int fd, int *err)
4331da177e4SLinus Torvalds {
4341da177e4SLinus Torvalds 	struct file *file;
4351da177e4SLinus Torvalds 	struct socket *sock;
4361da177e4SLinus Torvalds 
43789bddce5SStephen Hemminger 	file = fget(fd);
43889bddce5SStephen Hemminger 	if (!file) {
4391da177e4SLinus Torvalds 		*err = -EBADF;
4401da177e4SLinus Torvalds 		return NULL;
4411da177e4SLinus Torvalds 	}
44289bddce5SStephen Hemminger 
4436cb153caSBenjamin LaHaise 	sock = sock_from_file(file, err);
4446cb153caSBenjamin LaHaise 	if (!sock)
4451da177e4SLinus Torvalds 		fput(file);
4466cb153caSBenjamin LaHaise 	return sock;
4471da177e4SLinus Torvalds }
448c6d409cfSEric Dumazet EXPORT_SYMBOL(sockfd_lookup);
4491da177e4SLinus Torvalds 
4506cb153caSBenjamin LaHaise static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
4516cb153caSBenjamin LaHaise {
45200e188efSAl Viro 	struct fd f = fdget(fd);
4536cb153caSBenjamin LaHaise 	struct socket *sock;
4546cb153caSBenjamin LaHaise 
4553672558cSHua Zhong 	*err = -EBADF;
45600e188efSAl Viro 	if (f.file) {
45700e188efSAl Viro 		sock = sock_from_file(f.file, err);
45800e188efSAl Viro 		if (likely(sock)) {
45900e188efSAl Viro 			*fput_needed = f.flags;
4601da177e4SLinus Torvalds 			return sock;
46100e188efSAl Viro 		}
46200e188efSAl Viro 		fdput(f);
4636cb153caSBenjamin LaHaise 	}
4646cb153caSBenjamin LaHaise 	return NULL;
4651da177e4SLinus Torvalds }
4661da177e4SLinus Torvalds 
467600e1779SMasatake YAMATO #define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname"
468600e1779SMasatake YAMATO #define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX)
469600e1779SMasatake YAMATO #define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1)
470600e1779SMasatake YAMATO static ssize_t sockfs_getxattr(struct dentry *dentry,
471600e1779SMasatake YAMATO 			       const char *name, void *value, size_t size)
472600e1779SMasatake YAMATO {
473600e1779SMasatake YAMATO 	const char *proto_name;
474600e1779SMasatake YAMATO 	size_t proto_size;
475600e1779SMasatake YAMATO 	int error;
476600e1779SMasatake YAMATO 
477600e1779SMasatake YAMATO 	error = -ENODATA;
478600e1779SMasatake YAMATO 	if (!strncmp(name, XATTR_NAME_SOCKPROTONAME, XATTR_NAME_SOCKPROTONAME_LEN)) {
479600e1779SMasatake YAMATO 		proto_name = dentry->d_name.name;
480600e1779SMasatake YAMATO 		proto_size = strlen(proto_name);
481600e1779SMasatake YAMATO 
482600e1779SMasatake YAMATO 		if (value) {
483600e1779SMasatake YAMATO 			error = -ERANGE;
484600e1779SMasatake YAMATO 			if (proto_size + 1 > size)
485600e1779SMasatake YAMATO 				goto out;
486600e1779SMasatake YAMATO 
487600e1779SMasatake YAMATO 			strncpy(value, proto_name, proto_size + 1);
488600e1779SMasatake YAMATO 		}
489600e1779SMasatake YAMATO 		error = proto_size + 1;
490600e1779SMasatake YAMATO 	}
491600e1779SMasatake YAMATO 
492600e1779SMasatake YAMATO out:
493600e1779SMasatake YAMATO 	return error;
494600e1779SMasatake YAMATO }
495600e1779SMasatake YAMATO 
496600e1779SMasatake YAMATO static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer,
497600e1779SMasatake YAMATO 				size_t size)
498600e1779SMasatake YAMATO {
499600e1779SMasatake YAMATO 	ssize_t len;
500600e1779SMasatake YAMATO 	ssize_t used = 0;
501600e1779SMasatake YAMATO 
502600e1779SMasatake YAMATO 	len = security_inode_listsecurity(dentry->d_inode, buffer, size);
503600e1779SMasatake YAMATO 	if (len < 0)
504600e1779SMasatake YAMATO 		return len;
505600e1779SMasatake YAMATO 	used += len;
506600e1779SMasatake YAMATO 	if (buffer) {
507600e1779SMasatake YAMATO 		if (size < used)
508600e1779SMasatake YAMATO 			return -ERANGE;
509600e1779SMasatake YAMATO 		buffer += len;
510600e1779SMasatake YAMATO 	}
511600e1779SMasatake YAMATO 
512600e1779SMasatake YAMATO 	len = (XATTR_NAME_SOCKPROTONAME_LEN + 1);
513600e1779SMasatake YAMATO 	used += len;
514600e1779SMasatake YAMATO 	if (buffer) {
515600e1779SMasatake YAMATO 		if (size < used)
516600e1779SMasatake YAMATO 			return -ERANGE;
517600e1779SMasatake YAMATO 		memcpy(buffer, XATTR_NAME_SOCKPROTONAME, len);
518600e1779SMasatake YAMATO 		buffer += len;
519600e1779SMasatake YAMATO 	}
520600e1779SMasatake YAMATO 
521600e1779SMasatake YAMATO 	return used;
522600e1779SMasatake YAMATO }
523600e1779SMasatake YAMATO 
524600e1779SMasatake YAMATO static const struct inode_operations sockfs_inode_ops = {
525600e1779SMasatake YAMATO 	.getxattr = sockfs_getxattr,
526600e1779SMasatake YAMATO 	.listxattr = sockfs_listxattr,
527600e1779SMasatake YAMATO };
528600e1779SMasatake YAMATO 
5291da177e4SLinus Torvalds /**
5301da177e4SLinus Torvalds  *	sock_alloc	-	allocate a socket
5311da177e4SLinus Torvalds  *
5321da177e4SLinus Torvalds  *	Allocate a new inode and socket object. The two are bound together
5331da177e4SLinus Torvalds  *	and initialised. The socket is then returned. If we are out of inodes
5341da177e4SLinus Torvalds  *	NULL is returned.
5351da177e4SLinus Torvalds  */
5361da177e4SLinus Torvalds 
5371da177e4SLinus Torvalds static struct socket *sock_alloc(void)
5381da177e4SLinus Torvalds {
5391da177e4SLinus Torvalds 	struct inode *inode;
5401da177e4SLinus Torvalds 	struct socket *sock;
5411da177e4SLinus Torvalds 
542a209dfc7SEric Dumazet 	inode = new_inode_pseudo(sock_mnt->mnt_sb);
5431da177e4SLinus Torvalds 	if (!inode)
5441da177e4SLinus Torvalds 		return NULL;
5451da177e4SLinus Torvalds 
5461da177e4SLinus Torvalds 	sock = SOCKET_I(inode);
5471da177e4SLinus Torvalds 
54829a020d3SEric Dumazet 	kmemcheck_annotate_bitfield(sock, type);
54985fe4025SChristoph Hellwig 	inode->i_ino = get_next_ino();
5501da177e4SLinus Torvalds 	inode->i_mode = S_IFSOCK | S_IRWXUGO;
5518192b0c4SDavid Howells 	inode->i_uid = current_fsuid();
5528192b0c4SDavid Howells 	inode->i_gid = current_fsgid();
553600e1779SMasatake YAMATO 	inode->i_op = &sockfs_inode_ops;
5541da177e4SLinus Torvalds 
55519e8d69cSAlex Shi 	this_cpu_add(sockets_in_use, 1);
5561da177e4SLinus Torvalds 	return sock;
5571da177e4SLinus Torvalds }
5581da177e4SLinus Torvalds 
5591da177e4SLinus Torvalds /**
5601da177e4SLinus Torvalds  *	sock_release	-	close a socket
5611da177e4SLinus Torvalds  *	@sock: socket to close
5621da177e4SLinus Torvalds  *
5631da177e4SLinus Torvalds  *	The socket is released from the protocol stack if it has a release
5641da177e4SLinus Torvalds  *	callback, and the inode is then released if the socket is bound to
5651da177e4SLinus Torvalds  *	an inode not a file.
5661da177e4SLinus Torvalds  */
5671da177e4SLinus Torvalds 
5681da177e4SLinus Torvalds void sock_release(struct socket *sock)
5691da177e4SLinus Torvalds {
5701da177e4SLinus Torvalds 	if (sock->ops) {
5711da177e4SLinus Torvalds 		struct module *owner = sock->ops->owner;
5721da177e4SLinus Torvalds 
5731da177e4SLinus Torvalds 		sock->ops->release(sock);
5741da177e4SLinus Torvalds 		sock->ops = NULL;
5751da177e4SLinus Torvalds 		module_put(owner);
5761da177e4SLinus Torvalds 	}
5771da177e4SLinus Torvalds 
578eaefd110SEric Dumazet 	if (rcu_dereference_protected(sock->wq, 1)->fasync_list)
5793410f22eSYang Yingliang 		pr_err("%s: fasync list not empty!\n", __func__);
5801da177e4SLinus Torvalds 
581b09e786bSMikulas Patocka 	if (test_bit(SOCK_EXTERNALLY_ALLOCATED, &sock->flags))
582b09e786bSMikulas Patocka 		return;
583b09e786bSMikulas Patocka 
58419e8d69cSAlex Shi 	this_cpu_sub(sockets_in_use, 1);
5851da177e4SLinus Torvalds 	if (!sock->file) {
5861da177e4SLinus Torvalds 		iput(SOCK_INODE(sock));
5871da177e4SLinus Torvalds 		return;
5881da177e4SLinus Torvalds 	}
5891da177e4SLinus Torvalds 	sock->file = NULL;
5901da177e4SLinus Torvalds }
591c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_release);
5921da177e4SLinus Torvalds 
59367cc0d40SWillem de Bruijn void __sock_tx_timestamp(const struct sock *sk, __u8 *tx_flags)
59420d49473SPatrick Ohly {
595140c55d4SEric Dumazet 	u8 flags = *tx_flags;
596140c55d4SEric Dumazet 
597b9f40e21SWillem de Bruijn 	if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_HARDWARE)
598140c55d4SEric Dumazet 		flags |= SKBTX_HW_TSTAMP;
599140c55d4SEric Dumazet 
600b9f40e21SWillem de Bruijn 	if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_SOFTWARE)
601140c55d4SEric Dumazet 		flags |= SKBTX_SW_TSTAMP;
602140c55d4SEric Dumazet 
603e7fd2885SWillem de Bruijn 	if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_SCHED)
604140c55d4SEric Dumazet 		flags |= SKBTX_SCHED_TSTAMP;
605140c55d4SEric Dumazet 
606e1c8a607SWillem de Bruijn 	if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_ACK)
607140c55d4SEric Dumazet 		flags |= SKBTX_ACK_TSTAMP;
608e7fd2885SWillem de Bruijn 
609140c55d4SEric Dumazet 	*tx_flags = flags;
61020d49473SPatrick Ohly }
61167cc0d40SWillem de Bruijn EXPORT_SYMBOL(__sock_tx_timestamp);
61220d49473SPatrick Ohly 
613228e548eSAnton Blanchard static inline int __sock_sendmsg_nosec(struct kiocb *iocb, struct socket *sock,
6141da177e4SLinus Torvalds 				       struct msghdr *msg, size_t size)
6151da177e4SLinus Torvalds {
6161da177e4SLinus Torvalds 	return sock->ops->sendmsg(iocb, sock, msg, size);
6171da177e4SLinus Torvalds }
6181da177e4SLinus Torvalds 
619228e548eSAnton Blanchard static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock,
620228e548eSAnton Blanchard 				 struct msghdr *msg, size_t size)
621228e548eSAnton Blanchard {
622228e548eSAnton Blanchard 	int err = security_socket_sendmsg(sock, msg, size);
623228e548eSAnton Blanchard 
624228e548eSAnton Blanchard 	return err ?: __sock_sendmsg_nosec(iocb, sock, msg, size);
625228e548eSAnton Blanchard }
626228e548eSAnton Blanchard 
6270cf00c6fSGu Zheng static int do_sock_sendmsg(struct socket *sock, struct msghdr *msg,
6280cf00c6fSGu Zheng 			   size_t size, bool nosec)
6291da177e4SLinus Torvalds {
6301da177e4SLinus Torvalds 	struct kiocb iocb;
6311da177e4SLinus Torvalds 	int ret;
6321da177e4SLinus Torvalds 
6331da177e4SLinus Torvalds 	init_sync_kiocb(&iocb, NULL);
6340cf00c6fSGu Zheng 	ret = nosec ? __sock_sendmsg_nosec(&iocb, sock, msg, size) :
6350cf00c6fSGu Zheng 		      __sock_sendmsg(&iocb, sock, msg, size);
6361da177e4SLinus Torvalds 	if (-EIOCBQUEUED == ret)
6371da177e4SLinus Torvalds 		ret = wait_on_sync_kiocb(&iocb);
6381da177e4SLinus Torvalds 	return ret;
6391da177e4SLinus Torvalds }
6400cf00c6fSGu Zheng 
6410cf00c6fSGu Zheng int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
6420cf00c6fSGu Zheng {
6430cf00c6fSGu Zheng 	return do_sock_sendmsg(sock, msg, size, false);
6440cf00c6fSGu Zheng }
645c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_sendmsg);
6461da177e4SLinus Torvalds 
647894dc24cSEric Dumazet static int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg, size_t size)
648228e548eSAnton Blanchard {
6490cf00c6fSGu Zheng 	return do_sock_sendmsg(sock, msg, size, true);
650228e548eSAnton Blanchard }
651228e548eSAnton Blanchard 
6521da177e4SLinus Torvalds int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
6531da177e4SLinus Torvalds 		   struct kvec *vec, size_t num, size_t size)
6541da177e4SLinus Torvalds {
6551da177e4SLinus Torvalds 	mm_segment_t oldfs = get_fs();
6561da177e4SLinus Torvalds 	int result;
6571da177e4SLinus Torvalds 
6581da177e4SLinus Torvalds 	set_fs(KERNEL_DS);
6591da177e4SLinus Torvalds 	/*
6601da177e4SLinus Torvalds 	 * the following is safe, since for compiler definitions of kvec and
6611da177e4SLinus Torvalds 	 * iovec are identical, yielding the same in-core layout and alignment
6621da177e4SLinus Torvalds 	 */
663c0371da6SAl Viro 	iov_iter_init(&msg->msg_iter, WRITE, (struct iovec *)vec, num, size);
6641da177e4SLinus Torvalds 	result = sock_sendmsg(sock, msg, size);
6651da177e4SLinus Torvalds 	set_fs(oldfs);
6661da177e4SLinus Torvalds 	return result;
6671da177e4SLinus Torvalds }
668c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendmsg);
6691da177e4SLinus Torvalds 
67092f37fd2SEric Dumazet /*
67192f37fd2SEric Dumazet  * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
67292f37fd2SEric Dumazet  */
67392f37fd2SEric Dumazet void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
67492f37fd2SEric Dumazet 	struct sk_buff *skb)
67592f37fd2SEric Dumazet {
67620d49473SPatrick Ohly 	int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
677f24b9be5SWillem de Bruijn 	struct scm_timestamping tss;
67820d49473SPatrick Ohly 	int empty = 1;
67920d49473SPatrick Ohly 	struct skb_shared_hwtstamps *shhwtstamps =
68020d49473SPatrick Ohly 		skb_hwtstamps(skb);
68192f37fd2SEric Dumazet 
68220d49473SPatrick Ohly 	/* Race occurred between timestamp enabling and packet
68320d49473SPatrick Ohly 	   receiving.  Fill in the current time for now. */
68420d49473SPatrick Ohly 	if (need_software_tstamp && skb->tstamp.tv64 == 0)
68520d49473SPatrick Ohly 		__net_timestamp(skb);
68620d49473SPatrick Ohly 
68720d49473SPatrick Ohly 	if (need_software_tstamp) {
68892f37fd2SEric Dumazet 		if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
68992f37fd2SEric Dumazet 			struct timeval tv;
69020d49473SPatrick Ohly 			skb_get_timestamp(skb, &tv);
69120d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP,
69220d49473SPatrick Ohly 				 sizeof(tv), &tv);
69392f37fd2SEric Dumazet 		} else {
694f24b9be5SWillem de Bruijn 			struct timespec ts;
695f24b9be5SWillem de Bruijn 			skb_get_timestampns(skb, &ts);
69620d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS,
697f24b9be5SWillem de Bruijn 				 sizeof(ts), &ts);
69892f37fd2SEric Dumazet 		}
69992f37fd2SEric Dumazet 	}
70092f37fd2SEric Dumazet 
701f24b9be5SWillem de Bruijn 	memset(&tss, 0, sizeof(tss));
702c199105dSWillem de Bruijn 	if ((sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE) &&
703f24b9be5SWillem de Bruijn 	    ktime_to_timespec_cond(skb->tstamp, tss.ts + 0))
70420d49473SPatrick Ohly 		empty = 0;
7054d276eb6SWillem de Bruijn 	if (shhwtstamps &&
706b9f40e21SWillem de Bruijn 	    (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
707f24b9be5SWillem de Bruijn 	    ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2))
70820d49473SPatrick Ohly 		empty = 0;
70920d49473SPatrick Ohly 	if (!empty)
71020d49473SPatrick Ohly 		put_cmsg(msg, SOL_SOCKET,
711f24b9be5SWillem de Bruijn 			 SCM_TIMESTAMPING, sizeof(tss), &tss);
71220d49473SPatrick Ohly }
7137c81fd8bSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
7147c81fd8bSArnaldo Carvalho de Melo 
7156e3e939fSJohannes Berg void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
7166e3e939fSJohannes Berg 	struct sk_buff *skb)
7176e3e939fSJohannes Berg {
7186e3e939fSJohannes Berg 	int ack;
7196e3e939fSJohannes Berg 
7206e3e939fSJohannes Berg 	if (!sock_flag(sk, SOCK_WIFI_STATUS))
7216e3e939fSJohannes Berg 		return;
7226e3e939fSJohannes Berg 	if (!skb->wifi_acked_valid)
7236e3e939fSJohannes Berg 		return;
7246e3e939fSJohannes Berg 
7256e3e939fSJohannes Berg 	ack = skb->wifi_acked;
7266e3e939fSJohannes Berg 
7276e3e939fSJohannes Berg 	put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack);
7286e3e939fSJohannes Berg }
7296e3e939fSJohannes Berg EXPORT_SYMBOL_GPL(__sock_recv_wifi_status);
7306e3e939fSJohannes Berg 
73111165f14Sstephen hemminger static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk,
73211165f14Sstephen hemminger 				   struct sk_buff *skb)
7333b885787SNeil Horman {
7343b885787SNeil Horman 	if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && skb->dropcount)
7353b885787SNeil Horman 		put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL,
7363b885787SNeil Horman 			sizeof(__u32), &skb->dropcount);
7373b885787SNeil Horman }
7383b885787SNeil Horman 
739767dd033SEric Dumazet void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
7403b885787SNeil Horman 	struct sk_buff *skb)
7413b885787SNeil Horman {
7423b885787SNeil Horman 	sock_recv_timestamp(msg, sk, skb);
7433b885787SNeil Horman 	sock_recv_drops(msg, sk, skb);
7443b885787SNeil Horman }
745767dd033SEric Dumazet EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops);
7463b885787SNeil Horman 
747a2e27255SArnaldo Carvalho de Melo static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock,
7481da177e4SLinus Torvalds 				       struct msghdr *msg, size_t size, int flags)
7491da177e4SLinus Torvalds {
7501da177e4SLinus Torvalds 	return sock->ops->recvmsg(iocb, sock, msg, size, flags);
7511da177e4SLinus Torvalds }
7521da177e4SLinus Torvalds 
753a2e27255SArnaldo Carvalho de Melo static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock,
754a2e27255SArnaldo Carvalho de Melo 				 struct msghdr *msg, size_t size, int flags)
755a2e27255SArnaldo Carvalho de Melo {
756a2e27255SArnaldo Carvalho de Melo 	int err = security_socket_recvmsg(sock, msg, size, flags);
757a2e27255SArnaldo Carvalho de Melo 
758a2e27255SArnaldo Carvalho de Melo 	return err ?: __sock_recvmsg_nosec(iocb, sock, msg, size, flags);
759a2e27255SArnaldo Carvalho de Melo }
760a2e27255SArnaldo Carvalho de Melo 
7611da177e4SLinus Torvalds int sock_recvmsg(struct socket *sock, struct msghdr *msg,
7621da177e4SLinus Torvalds 		 size_t size, int flags)
7631da177e4SLinus Torvalds {
7641da177e4SLinus Torvalds 	struct kiocb iocb;
7651da177e4SLinus Torvalds 	int ret;
7661da177e4SLinus Torvalds 
7671da177e4SLinus Torvalds 	init_sync_kiocb(&iocb, NULL);
7681da177e4SLinus Torvalds 	ret = __sock_recvmsg(&iocb, sock, msg, size, flags);
7691da177e4SLinus Torvalds 	if (-EIOCBQUEUED == ret)
7701da177e4SLinus Torvalds 		ret = wait_on_sync_kiocb(&iocb);
7711da177e4SLinus Torvalds 	return ret;
7721da177e4SLinus Torvalds }
773c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_recvmsg);
7741da177e4SLinus Torvalds 
775a2e27255SArnaldo Carvalho de Melo static int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
776a2e27255SArnaldo Carvalho de Melo 			      size_t size, int flags)
777a2e27255SArnaldo Carvalho de Melo {
778a2e27255SArnaldo Carvalho de Melo 	struct kiocb iocb;
779a2e27255SArnaldo Carvalho de Melo 	int ret;
780a2e27255SArnaldo Carvalho de Melo 
781a2e27255SArnaldo Carvalho de Melo 	init_sync_kiocb(&iocb, NULL);
782a2e27255SArnaldo Carvalho de Melo 	ret = __sock_recvmsg_nosec(&iocb, sock, msg, size, flags);
783a2e27255SArnaldo Carvalho de Melo 	if (-EIOCBQUEUED == ret)
784a2e27255SArnaldo Carvalho de Melo 		ret = wait_on_sync_kiocb(&iocb);
785a2e27255SArnaldo Carvalho de Melo 	return ret;
786a2e27255SArnaldo Carvalho de Melo }
787a2e27255SArnaldo Carvalho de Melo 
788c1249c0aSMartin Lucina /**
789c1249c0aSMartin Lucina  * kernel_recvmsg - Receive a message from a socket (kernel space)
790c1249c0aSMartin Lucina  * @sock:       The socket to receive the message from
791c1249c0aSMartin Lucina  * @msg:        Received message
792c1249c0aSMartin Lucina  * @vec:        Input s/g array for message data
793c1249c0aSMartin Lucina  * @num:        Size of input s/g array
794c1249c0aSMartin Lucina  * @size:       Number of bytes to read
795c1249c0aSMartin Lucina  * @flags:      Message flags (MSG_DONTWAIT, etc...)
796c1249c0aSMartin Lucina  *
797c1249c0aSMartin Lucina  * On return the msg structure contains the scatter/gather array passed in the
798c1249c0aSMartin Lucina  * vec argument. The array is modified so that it consists of the unfilled
799c1249c0aSMartin Lucina  * portion of the original array.
800c1249c0aSMartin Lucina  *
801c1249c0aSMartin Lucina  * The returned value is the total number of bytes received, or an error.
802c1249c0aSMartin Lucina  */
8031da177e4SLinus Torvalds int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
80489bddce5SStephen Hemminger 		   struct kvec *vec, size_t num, size_t size, int flags)
8051da177e4SLinus Torvalds {
8061da177e4SLinus Torvalds 	mm_segment_t oldfs = get_fs();
8071da177e4SLinus Torvalds 	int result;
8081da177e4SLinus Torvalds 
8091da177e4SLinus Torvalds 	set_fs(KERNEL_DS);
8101da177e4SLinus Torvalds 	/*
8111da177e4SLinus Torvalds 	 * the following is safe, since for compiler definitions of kvec and
8121da177e4SLinus Torvalds 	 * iovec are identical, yielding the same in-core layout and alignment
8131da177e4SLinus Torvalds 	 */
814c0371da6SAl Viro 	iov_iter_init(&msg->msg_iter, READ, (struct iovec *)vec, num, size);
8151da177e4SLinus Torvalds 	result = sock_recvmsg(sock, msg, size, flags);
8161da177e4SLinus Torvalds 	set_fs(oldfs);
8171da177e4SLinus Torvalds 	return result;
8181da177e4SLinus Torvalds }
819c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_recvmsg);
8201da177e4SLinus Torvalds 
82120380731SArnaldo Carvalho de Melo static ssize_t sock_sendpage(struct file *file, struct page *page,
8221da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more)
8231da177e4SLinus Torvalds {
8241da177e4SLinus Torvalds 	struct socket *sock;
8251da177e4SLinus Torvalds 	int flags;
8261da177e4SLinus Torvalds 
827b69aee04SEric Dumazet 	sock = file->private_data;
8281da177e4SLinus Torvalds 
82935f9c09fSEric Dumazet 	flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
83035f9c09fSEric Dumazet 	/* more is a combination of MSG_MORE and MSG_SENDPAGE_NOTLAST */
83135f9c09fSEric Dumazet 	flags |= more;
8321da177e4SLinus Torvalds 
833e6949583SLinus Torvalds 	return kernel_sendpage(sock, page, offset, size, flags);
8341da177e4SLinus Torvalds }
8351da177e4SLinus Torvalds 
8369c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
8379c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
8389c55e01cSJens Axboe 				unsigned int flags)
8399c55e01cSJens Axboe {
8409c55e01cSJens Axboe 	struct socket *sock = file->private_data;
8419c55e01cSJens Axboe 
842997b37daSRémi Denis-Courmont 	if (unlikely(!sock->ops->splice_read))
843997b37daSRémi Denis-Courmont 		return -EINVAL;
844997b37daSRémi Denis-Courmont 
8459c55e01cSJens Axboe 	return sock->ops->splice_read(sock, ppos, pipe, len, flags);
8469c55e01cSJens Axboe }
8479c55e01cSJens Axboe 
848027445c3SBadari Pulavarty static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
849027445c3SBadari Pulavarty 				unsigned long nr_segs, loff_t pos)
850ce1d4d3eSChristoph Hellwig {
851*6d652330SAl Viro 	struct file *file = iocb->ki_filp;
852*6d652330SAl Viro 	struct socket *sock = file->private_data;
8537cc05662SChristoph Hellwig 	struct msghdr msg;
854ce1d4d3eSChristoph Hellwig 
855ce1d4d3eSChristoph Hellwig 	if (pos != 0)
856ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
857027445c3SBadari Pulavarty 
85873a7075eSKent Overstreet 	if (iocb->ki_nbytes == 0)	/* Match SYS5 behaviour */
859ce1d4d3eSChristoph Hellwig 		return 0;
860ce1d4d3eSChristoph Hellwig 
861*6d652330SAl Viro 	msg.msg_name = NULL;
862*6d652330SAl Viro 	msg.msg_namelen = 0;
863*6d652330SAl Viro 	msg.msg_control = NULL;
864*6d652330SAl Viro 	msg.msg_controllen = 0;
865*6d652330SAl Viro 	iov_iter_init(&msg.msg_iter, READ, iov, nr_segs, iocb->ki_nbytes);
866*6d652330SAl Viro 	msg.msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
867ce1d4d3eSChristoph Hellwig 
868*6d652330SAl Viro 	return __sock_recvmsg(iocb, sock, &msg, iocb->ki_nbytes, msg.msg_flags);
869ce1d4d3eSChristoph Hellwig }
870ce1d4d3eSChristoph Hellwig 
871027445c3SBadari Pulavarty static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
872027445c3SBadari Pulavarty 			  unsigned long nr_segs, loff_t pos)
8731da177e4SLinus Torvalds {
874*6d652330SAl Viro 	struct file *file = iocb->ki_filp;
875*6d652330SAl Viro 	struct socket *sock = file->private_data;
8767cc05662SChristoph Hellwig 	struct msghdr msg;
8771da177e4SLinus Torvalds 
878ce1d4d3eSChristoph Hellwig 	if (pos != 0)
879ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
880027445c3SBadari Pulavarty 
881*6d652330SAl Viro 	msg.msg_name = NULL;
882*6d652330SAl Viro 	msg.msg_namelen = 0;
883*6d652330SAl Viro 	msg.msg_control = NULL;
884*6d652330SAl Viro 	msg.msg_controllen = 0;
885*6d652330SAl Viro 	iov_iter_init(&msg.msg_iter, WRITE, iov, nr_segs, iocb->ki_nbytes);
886*6d652330SAl Viro 	msg.msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
887*6d652330SAl Viro 	if (sock->type == SOCK_SEQPACKET)
888*6d652330SAl Viro 		msg.msg_flags |= MSG_EOR;
889*6d652330SAl Viro 
890*6d652330SAl Viro 	return __sock_sendmsg(iocb, sock, &msg, iocb->ki_nbytes);
8911da177e4SLinus Torvalds }
8921da177e4SLinus Torvalds 
8931da177e4SLinus Torvalds /*
8941da177e4SLinus Torvalds  * Atomic setting of ioctl hooks to avoid race
8951da177e4SLinus Torvalds  * with module unload.
8961da177e4SLinus Torvalds  */
8971da177e4SLinus Torvalds 
8984a3e2f71SArjan van de Ven static DEFINE_MUTEX(br_ioctl_mutex);
899c6d409cfSEric Dumazet static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg);
9001da177e4SLinus Torvalds 
901881d966bSEric W. Biederman void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *))
9021da177e4SLinus Torvalds {
9034a3e2f71SArjan van de Ven 	mutex_lock(&br_ioctl_mutex);
9041da177e4SLinus Torvalds 	br_ioctl_hook = hook;
9054a3e2f71SArjan van de Ven 	mutex_unlock(&br_ioctl_mutex);
9061da177e4SLinus Torvalds }
9071da177e4SLinus Torvalds EXPORT_SYMBOL(brioctl_set);
9081da177e4SLinus Torvalds 
9094a3e2f71SArjan van de Ven static DEFINE_MUTEX(vlan_ioctl_mutex);
910881d966bSEric W. Biederman static int (*vlan_ioctl_hook) (struct net *, void __user *arg);
9111da177e4SLinus Torvalds 
912881d966bSEric W. Biederman void vlan_ioctl_set(int (*hook) (struct net *, void __user *))
9131da177e4SLinus Torvalds {
9144a3e2f71SArjan van de Ven 	mutex_lock(&vlan_ioctl_mutex);
9151da177e4SLinus Torvalds 	vlan_ioctl_hook = hook;
9164a3e2f71SArjan van de Ven 	mutex_unlock(&vlan_ioctl_mutex);
9171da177e4SLinus Torvalds }
9181da177e4SLinus Torvalds EXPORT_SYMBOL(vlan_ioctl_set);
9191da177e4SLinus Torvalds 
9204a3e2f71SArjan van de Ven static DEFINE_MUTEX(dlci_ioctl_mutex);
9211da177e4SLinus Torvalds static int (*dlci_ioctl_hook) (unsigned int, void __user *);
9221da177e4SLinus Torvalds 
9231da177e4SLinus Torvalds void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
9241da177e4SLinus Torvalds {
9254a3e2f71SArjan van de Ven 	mutex_lock(&dlci_ioctl_mutex);
9261da177e4SLinus Torvalds 	dlci_ioctl_hook = hook;
9274a3e2f71SArjan van de Ven 	mutex_unlock(&dlci_ioctl_mutex);
9281da177e4SLinus Torvalds }
9291da177e4SLinus Torvalds EXPORT_SYMBOL(dlci_ioctl_set);
9301da177e4SLinus Torvalds 
9316b96018bSArnd Bergmann static long sock_do_ioctl(struct net *net, struct socket *sock,
9326b96018bSArnd Bergmann 				 unsigned int cmd, unsigned long arg)
9336b96018bSArnd Bergmann {
9346b96018bSArnd Bergmann 	int err;
9356b96018bSArnd Bergmann 	void __user *argp = (void __user *)arg;
9366b96018bSArnd Bergmann 
9376b96018bSArnd Bergmann 	err = sock->ops->ioctl(sock, cmd, arg);
9386b96018bSArnd Bergmann 
9396b96018bSArnd Bergmann 	/*
9406b96018bSArnd Bergmann 	 * If this ioctl is unknown try to hand it down
9416b96018bSArnd Bergmann 	 * to the NIC driver.
9426b96018bSArnd Bergmann 	 */
9436b96018bSArnd Bergmann 	if (err == -ENOIOCTLCMD)
9446b96018bSArnd Bergmann 		err = dev_ioctl(net, cmd, argp);
9456b96018bSArnd Bergmann 
9466b96018bSArnd Bergmann 	return err;
9476b96018bSArnd Bergmann }
9486b96018bSArnd Bergmann 
9491da177e4SLinus Torvalds /*
9501da177e4SLinus Torvalds  *	With an ioctl, arg may well be a user mode pointer, but we don't know
9511da177e4SLinus Torvalds  *	what to do with it - that's up to the protocol still.
9521da177e4SLinus Torvalds  */
9531da177e4SLinus Torvalds 
9541da177e4SLinus Torvalds static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
9551da177e4SLinus Torvalds {
9561da177e4SLinus Torvalds 	struct socket *sock;
957881d966bSEric W. Biederman 	struct sock *sk;
9581da177e4SLinus Torvalds 	void __user *argp = (void __user *)arg;
9591da177e4SLinus Torvalds 	int pid, err;
960881d966bSEric W. Biederman 	struct net *net;
9611da177e4SLinus Torvalds 
962b69aee04SEric Dumazet 	sock = file->private_data;
963881d966bSEric W. Biederman 	sk = sock->sk;
9643b1e0a65SYOSHIFUJI Hideaki 	net = sock_net(sk);
9651da177e4SLinus Torvalds 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
966881d966bSEric W. Biederman 		err = dev_ioctl(net, cmd, argp);
9671da177e4SLinus Torvalds 	} else
9683d23e349SJohannes Berg #ifdef CONFIG_WEXT_CORE
9691da177e4SLinus Torvalds 	if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
970881d966bSEric W. Biederman 		err = dev_ioctl(net, cmd, argp);
9711da177e4SLinus Torvalds 	} else
9723d23e349SJohannes Berg #endif
9731da177e4SLinus Torvalds 		switch (cmd) {
9741da177e4SLinus Torvalds 		case FIOSETOWN:
9751da177e4SLinus Torvalds 		case SIOCSPGRP:
9761da177e4SLinus Torvalds 			err = -EFAULT;
9771da177e4SLinus Torvalds 			if (get_user(pid, (int __user *)argp))
9781da177e4SLinus Torvalds 				break;
979e0b93eddSJeff Layton 			f_setown(sock->file, pid, 1);
980e0b93eddSJeff Layton 			err = 0;
9811da177e4SLinus Torvalds 			break;
9821da177e4SLinus Torvalds 		case FIOGETOWN:
9831da177e4SLinus Torvalds 		case SIOCGPGRP:
984609d7fa9SEric W. Biederman 			err = put_user(f_getown(sock->file),
98589bddce5SStephen Hemminger 				       (int __user *)argp);
9861da177e4SLinus Torvalds 			break;
9871da177e4SLinus Torvalds 		case SIOCGIFBR:
9881da177e4SLinus Torvalds 		case SIOCSIFBR:
9891da177e4SLinus Torvalds 		case SIOCBRADDBR:
9901da177e4SLinus Torvalds 		case SIOCBRDELBR:
9911da177e4SLinus Torvalds 			err = -ENOPKG;
9921da177e4SLinus Torvalds 			if (!br_ioctl_hook)
9931da177e4SLinus Torvalds 				request_module("bridge");
9941da177e4SLinus Torvalds 
9954a3e2f71SArjan van de Ven 			mutex_lock(&br_ioctl_mutex);
9961da177e4SLinus Torvalds 			if (br_ioctl_hook)
997881d966bSEric W. Biederman 				err = br_ioctl_hook(net, cmd, argp);
9984a3e2f71SArjan van de Ven 			mutex_unlock(&br_ioctl_mutex);
9991da177e4SLinus Torvalds 			break;
10001da177e4SLinus Torvalds 		case SIOCGIFVLAN:
10011da177e4SLinus Torvalds 		case SIOCSIFVLAN:
10021da177e4SLinus Torvalds 			err = -ENOPKG;
10031da177e4SLinus Torvalds 			if (!vlan_ioctl_hook)
10041da177e4SLinus Torvalds 				request_module("8021q");
10051da177e4SLinus Torvalds 
10064a3e2f71SArjan van de Ven 			mutex_lock(&vlan_ioctl_mutex);
10071da177e4SLinus Torvalds 			if (vlan_ioctl_hook)
1008881d966bSEric W. Biederman 				err = vlan_ioctl_hook(net, argp);
10094a3e2f71SArjan van de Ven 			mutex_unlock(&vlan_ioctl_mutex);
10101da177e4SLinus Torvalds 			break;
10111da177e4SLinus Torvalds 		case SIOCADDDLCI:
10121da177e4SLinus Torvalds 		case SIOCDELDLCI:
10131da177e4SLinus Torvalds 			err = -ENOPKG;
10141da177e4SLinus Torvalds 			if (!dlci_ioctl_hook)
10151da177e4SLinus Torvalds 				request_module("dlci");
10161da177e4SLinus Torvalds 
10174a3e2f71SArjan van de Ven 			mutex_lock(&dlci_ioctl_mutex);
10187512cbf6SPavel Emelyanov 			if (dlci_ioctl_hook)
10191da177e4SLinus Torvalds 				err = dlci_ioctl_hook(cmd, argp);
10204a3e2f71SArjan van de Ven 			mutex_unlock(&dlci_ioctl_mutex);
10211da177e4SLinus Torvalds 			break;
10221da177e4SLinus Torvalds 		default:
10236b96018bSArnd Bergmann 			err = sock_do_ioctl(net, sock, cmd, arg);
10241da177e4SLinus Torvalds 			break;
10251da177e4SLinus Torvalds 		}
10261da177e4SLinus Torvalds 	return err;
10271da177e4SLinus Torvalds }
10281da177e4SLinus Torvalds 
10291da177e4SLinus Torvalds int sock_create_lite(int family, int type, int protocol, struct socket **res)
10301da177e4SLinus Torvalds {
10311da177e4SLinus Torvalds 	int err;
10321da177e4SLinus Torvalds 	struct socket *sock = NULL;
10331da177e4SLinus Torvalds 
10341da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, 1);
10351da177e4SLinus Torvalds 	if (err)
10361da177e4SLinus Torvalds 		goto out;
10371da177e4SLinus Torvalds 
10381da177e4SLinus Torvalds 	sock = sock_alloc();
10391da177e4SLinus Torvalds 	if (!sock) {
10401da177e4SLinus Torvalds 		err = -ENOMEM;
10411da177e4SLinus Torvalds 		goto out;
10421da177e4SLinus Torvalds 	}
10431da177e4SLinus Torvalds 
10441da177e4SLinus Torvalds 	sock->type = type;
10457420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, 1);
10467420ed23SVenkat Yekkirala 	if (err)
10477420ed23SVenkat Yekkirala 		goto out_release;
10487420ed23SVenkat Yekkirala 
10491da177e4SLinus Torvalds out:
10501da177e4SLinus Torvalds 	*res = sock;
10511da177e4SLinus Torvalds 	return err;
10527420ed23SVenkat Yekkirala out_release:
10537420ed23SVenkat Yekkirala 	sock_release(sock);
10547420ed23SVenkat Yekkirala 	sock = NULL;
10557420ed23SVenkat Yekkirala 	goto out;
10561da177e4SLinus Torvalds }
1057c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_lite);
10581da177e4SLinus Torvalds 
10591da177e4SLinus Torvalds /* No kernel lock held - perfect */
10601da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file, poll_table *wait)
10611da177e4SLinus Torvalds {
1062cbf55001SEliezer Tamir 	unsigned int busy_flag = 0;
10631da177e4SLinus Torvalds 	struct socket *sock;
10641da177e4SLinus Torvalds 
10651da177e4SLinus Torvalds 	/*
10661da177e4SLinus Torvalds 	 *      We can't return errors to poll, so it's either yes or no.
10671da177e4SLinus Torvalds 	 */
1068b69aee04SEric Dumazet 	sock = file->private_data;
10692d48d67fSEliezer Tamir 
1070cbf55001SEliezer Tamir 	if (sk_can_busy_loop(sock->sk)) {
10712d48d67fSEliezer Tamir 		/* this socket can poll_ll so tell the system call */
1072cbf55001SEliezer Tamir 		busy_flag = POLL_BUSY_LOOP;
10732d48d67fSEliezer Tamir 
10742d48d67fSEliezer Tamir 		/* once, only if requested by syscall */
1075cbf55001SEliezer Tamir 		if (wait && (wait->_key & POLL_BUSY_LOOP))
1076cbf55001SEliezer Tamir 			sk_busy_loop(sock->sk, 1);
10772d48d67fSEliezer Tamir 	}
10782d48d67fSEliezer Tamir 
1079cbf55001SEliezer Tamir 	return busy_flag | sock->ops->poll(file, sock, wait);
10801da177e4SLinus Torvalds }
10811da177e4SLinus Torvalds 
10821da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma)
10831da177e4SLinus Torvalds {
1084b69aee04SEric Dumazet 	struct socket *sock = file->private_data;
10851da177e4SLinus Torvalds 
10861da177e4SLinus Torvalds 	return sock->ops->mmap(file, sock, vma);
10871da177e4SLinus Torvalds }
10881da177e4SLinus Torvalds 
108920380731SArnaldo Carvalho de Melo static int sock_close(struct inode *inode, struct file *filp)
10901da177e4SLinus Torvalds {
10911da177e4SLinus Torvalds 	sock_release(SOCKET_I(inode));
10921da177e4SLinus Torvalds 	return 0;
10931da177e4SLinus Torvalds }
10941da177e4SLinus Torvalds 
10951da177e4SLinus Torvalds /*
10961da177e4SLinus Torvalds  *	Update the socket async list
10971da177e4SLinus Torvalds  *
10981da177e4SLinus Torvalds  *	Fasync_list locking strategy.
10991da177e4SLinus Torvalds  *
11001da177e4SLinus Torvalds  *	1. fasync_list is modified only under process context socket lock
11011da177e4SLinus Torvalds  *	   i.e. under semaphore.
11021da177e4SLinus Torvalds  *	2. fasync_list is used under read_lock(&sk->sk_callback_lock)
1103989a2979SEric Dumazet  *	   or under socket lock
11041da177e4SLinus Torvalds  */
11051da177e4SLinus Torvalds 
11061da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on)
11071da177e4SLinus Torvalds {
1108989a2979SEric Dumazet 	struct socket *sock = filp->private_data;
1109989a2979SEric Dumazet 	struct sock *sk = sock->sk;
1110eaefd110SEric Dumazet 	struct socket_wq *wq;
11111da177e4SLinus Torvalds 
1112989a2979SEric Dumazet 	if (sk == NULL)
11131da177e4SLinus Torvalds 		return -EINVAL;
11141da177e4SLinus Torvalds 
11151da177e4SLinus Torvalds 	lock_sock(sk);
1116eaefd110SEric Dumazet 	wq = rcu_dereference_protected(sock->wq, sock_owned_by_user(sk));
1117eaefd110SEric Dumazet 	fasync_helper(fd, filp, on, &wq->fasync_list);
11181da177e4SLinus Torvalds 
1119eaefd110SEric Dumazet 	if (!wq->fasync_list)
1120bcdce719SEric Dumazet 		sock_reset_flag(sk, SOCK_FASYNC);
1121989a2979SEric Dumazet 	else
1122989a2979SEric Dumazet 		sock_set_flag(sk, SOCK_FASYNC);
11231da177e4SLinus Torvalds 
1124989a2979SEric Dumazet 	release_sock(sk);
11251da177e4SLinus Torvalds 	return 0;
11261da177e4SLinus Torvalds }
11271da177e4SLinus Torvalds 
112843815482SEric Dumazet /* This function may be called only under socket lock or callback_lock or rcu_lock */
11291da177e4SLinus Torvalds 
11301da177e4SLinus Torvalds int sock_wake_async(struct socket *sock, int how, int band)
11311da177e4SLinus Torvalds {
113243815482SEric Dumazet 	struct socket_wq *wq;
113343815482SEric Dumazet 
113443815482SEric Dumazet 	if (!sock)
11351da177e4SLinus Torvalds 		return -1;
113643815482SEric Dumazet 	rcu_read_lock();
113743815482SEric Dumazet 	wq = rcu_dereference(sock->wq);
113843815482SEric Dumazet 	if (!wq || !wq->fasync_list) {
113943815482SEric Dumazet 		rcu_read_unlock();
114043815482SEric Dumazet 		return -1;
114143815482SEric Dumazet 	}
114289bddce5SStephen Hemminger 	switch (how) {
11438d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_WAITD:
11441da177e4SLinus Torvalds 		if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
11451da177e4SLinus Torvalds 			break;
11461da177e4SLinus Torvalds 		goto call_kill;
11478d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_SPACE:
11481da177e4SLinus Torvalds 		if (!test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags))
11491da177e4SLinus Torvalds 			break;
11501da177e4SLinus Torvalds 		/* fall through */
11518d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_IO:
11521da177e4SLinus Torvalds call_kill:
115343815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGIO, band);
11541da177e4SLinus Torvalds 		break;
11558d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_URG:
115643815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGURG, band);
11571da177e4SLinus Torvalds 	}
115843815482SEric Dumazet 	rcu_read_unlock();
11591da177e4SLinus Torvalds 	return 0;
11601da177e4SLinus Torvalds }
1161c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_wake_async);
11621da177e4SLinus Torvalds 
1163721db93aSPavel Emelyanov int __sock_create(struct net *net, int family, int type, int protocol,
116489bddce5SStephen Hemminger 			 struct socket **res, int kern)
11651da177e4SLinus Torvalds {
11661da177e4SLinus Torvalds 	int err;
11671da177e4SLinus Torvalds 	struct socket *sock;
116855737fdaSStephen Hemminger 	const struct net_proto_family *pf;
11691da177e4SLinus Torvalds 
11701da177e4SLinus Torvalds 	/*
11711da177e4SLinus Torvalds 	 *      Check protocol is in range
11721da177e4SLinus Torvalds 	 */
11731da177e4SLinus Torvalds 	if (family < 0 || family >= NPROTO)
11741da177e4SLinus Torvalds 		return -EAFNOSUPPORT;
11751da177e4SLinus Torvalds 	if (type < 0 || type >= SOCK_MAX)
11761da177e4SLinus Torvalds 		return -EINVAL;
11771da177e4SLinus Torvalds 
11781da177e4SLinus Torvalds 	/* Compatibility.
11791da177e4SLinus Torvalds 
11801da177e4SLinus Torvalds 	   This uglymoron is moved from INET layer to here to avoid
11811da177e4SLinus Torvalds 	   deadlock in module load.
11821da177e4SLinus Torvalds 	 */
11831da177e4SLinus Torvalds 	if (family == PF_INET && type == SOCK_PACKET) {
11841da177e4SLinus Torvalds 		static int warned;
11851da177e4SLinus Torvalds 		if (!warned) {
11861da177e4SLinus Torvalds 			warned = 1;
11873410f22eSYang Yingliang 			pr_info("%s uses obsolete (PF_INET,SOCK_PACKET)\n",
118889bddce5SStephen Hemminger 				current->comm);
11891da177e4SLinus Torvalds 		}
11901da177e4SLinus Torvalds 		family = PF_PACKET;
11911da177e4SLinus Torvalds 	}
11921da177e4SLinus Torvalds 
11931da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, kern);
11941da177e4SLinus Torvalds 	if (err)
11951da177e4SLinus Torvalds 		return err;
11961da177e4SLinus Torvalds 
119755737fdaSStephen Hemminger 	/*
119855737fdaSStephen Hemminger 	 *	Allocate the socket and allow the family to set things up. if
119955737fdaSStephen Hemminger 	 *	the protocol is 0, the family is instructed to select an appropriate
120055737fdaSStephen Hemminger 	 *	default.
120155737fdaSStephen Hemminger 	 */
120255737fdaSStephen Hemminger 	sock = sock_alloc();
120355737fdaSStephen Hemminger 	if (!sock) {
1204e87cc472SJoe Perches 		net_warn_ratelimited("socket: no more sockets\n");
120555737fdaSStephen Hemminger 		return -ENFILE;	/* Not exactly a match, but its the
120655737fdaSStephen Hemminger 				   closest posix thing */
120755737fdaSStephen Hemminger 	}
120855737fdaSStephen Hemminger 
120955737fdaSStephen Hemminger 	sock->type = type;
121055737fdaSStephen Hemminger 
121195a5afcaSJohannes Berg #ifdef CONFIG_MODULES
12121da177e4SLinus Torvalds 	/* Attempt to load a protocol module if the find failed.
12131da177e4SLinus Torvalds 	 *
12141da177e4SLinus Torvalds 	 * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
12151da177e4SLinus Torvalds 	 * requested real, full-featured networking support upon configuration.
12161da177e4SLinus Torvalds 	 * Otherwise module support will break!
12171da177e4SLinus Torvalds 	 */
1218190683a9SEric Dumazet 	if (rcu_access_pointer(net_families[family]) == NULL)
12191da177e4SLinus Torvalds 		request_module("net-pf-%d", family);
12201da177e4SLinus Torvalds #endif
12211da177e4SLinus Torvalds 
122255737fdaSStephen Hemminger 	rcu_read_lock();
122355737fdaSStephen Hemminger 	pf = rcu_dereference(net_families[family]);
12241da177e4SLinus Torvalds 	err = -EAFNOSUPPORT;
122555737fdaSStephen Hemminger 	if (!pf)
122655737fdaSStephen Hemminger 		goto out_release;
12271da177e4SLinus Torvalds 
12281da177e4SLinus Torvalds 	/*
12291da177e4SLinus Torvalds 	 * We will call the ->create function, that possibly is in a loadable
12301da177e4SLinus Torvalds 	 * module, so we have to bump that loadable module refcnt first.
12311da177e4SLinus Torvalds 	 */
123255737fdaSStephen Hemminger 	if (!try_module_get(pf->owner))
12331da177e4SLinus Torvalds 		goto out_release;
12341da177e4SLinus Torvalds 
123555737fdaSStephen Hemminger 	/* Now protected by module ref count */
123655737fdaSStephen Hemminger 	rcu_read_unlock();
123755737fdaSStephen Hemminger 
12383f378b68SEric Paris 	err = pf->create(net, sock, protocol, kern);
123955737fdaSStephen Hemminger 	if (err < 0)
12401da177e4SLinus Torvalds 		goto out_module_put;
1241a79af59eSFrank Filz 
12421da177e4SLinus Torvalds 	/*
12431da177e4SLinus Torvalds 	 * Now to bump the refcnt of the [loadable] module that owns this
12441da177e4SLinus Torvalds 	 * socket at sock_release time we decrement its refcnt.
12451da177e4SLinus Torvalds 	 */
124655737fdaSStephen Hemminger 	if (!try_module_get(sock->ops->owner))
124755737fdaSStephen Hemminger 		goto out_module_busy;
124855737fdaSStephen Hemminger 
12491da177e4SLinus Torvalds 	/*
12501da177e4SLinus Torvalds 	 * Now that we're done with the ->create function, the [loadable]
12511da177e4SLinus Torvalds 	 * module can have its refcnt decremented
12521da177e4SLinus Torvalds 	 */
125355737fdaSStephen Hemminger 	module_put(pf->owner);
12547420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, kern);
12557420ed23SVenkat Yekkirala 	if (err)
12563b185525SHerbert Xu 		goto out_sock_release;
125755737fdaSStephen Hemminger 	*res = sock;
12581da177e4SLinus Torvalds 
125955737fdaSStephen Hemminger 	return 0;
126055737fdaSStephen Hemminger 
126155737fdaSStephen Hemminger out_module_busy:
126255737fdaSStephen Hemminger 	err = -EAFNOSUPPORT;
12631da177e4SLinus Torvalds out_module_put:
126455737fdaSStephen Hemminger 	sock->ops = NULL;
126555737fdaSStephen Hemminger 	module_put(pf->owner);
126655737fdaSStephen Hemminger out_sock_release:
12671da177e4SLinus Torvalds 	sock_release(sock);
126855737fdaSStephen Hemminger 	return err;
126955737fdaSStephen Hemminger 
127055737fdaSStephen Hemminger out_release:
127155737fdaSStephen Hemminger 	rcu_read_unlock();
127255737fdaSStephen Hemminger 	goto out_sock_release;
12731da177e4SLinus Torvalds }
1274721db93aSPavel Emelyanov EXPORT_SYMBOL(__sock_create);
12751da177e4SLinus Torvalds 
12761da177e4SLinus Torvalds int sock_create(int family, int type, int protocol, struct socket **res)
12771da177e4SLinus Torvalds {
12781b8d7ae4SEric W. Biederman 	return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
12791da177e4SLinus Torvalds }
1280c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create);
12811da177e4SLinus Torvalds 
12821da177e4SLinus Torvalds int sock_create_kern(int family, int type, int protocol, struct socket **res)
12831da177e4SLinus Torvalds {
12841b8d7ae4SEric W. Biederman 	return __sock_create(&init_net, family, type, protocol, res, 1);
12851da177e4SLinus Torvalds }
1286c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_kern);
12871da177e4SLinus Torvalds 
12883e0fa65fSHeiko Carstens SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
12891da177e4SLinus Torvalds {
12901da177e4SLinus Torvalds 	int retval;
12911da177e4SLinus Torvalds 	struct socket *sock;
1292a677a039SUlrich Drepper 	int flags;
1293a677a039SUlrich Drepper 
1294e38b36f3SUlrich Drepper 	/* Check the SOCK_* constants for consistency.  */
1295e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
1296e38b36f3SUlrich Drepper 	BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
1297e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);
1298e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);
1299e38b36f3SUlrich Drepper 
1300a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
130177d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1302a677a039SUlrich Drepper 		return -EINVAL;
1303a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
13041da177e4SLinus Torvalds 
1305aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1306aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1307aaca0bdcSUlrich Drepper 
13081da177e4SLinus Torvalds 	retval = sock_create(family, type, protocol, &sock);
13091da177e4SLinus Torvalds 	if (retval < 0)
13101da177e4SLinus Torvalds 		goto out;
13111da177e4SLinus Torvalds 
131277d27200SUlrich Drepper 	retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
13131da177e4SLinus Torvalds 	if (retval < 0)
13141da177e4SLinus Torvalds 		goto out_release;
13151da177e4SLinus Torvalds 
13161da177e4SLinus Torvalds out:
13171da177e4SLinus Torvalds 	/* It may be already another descriptor 8) Not kernel problem. */
13181da177e4SLinus Torvalds 	return retval;
13191da177e4SLinus Torvalds 
13201da177e4SLinus Torvalds out_release:
13211da177e4SLinus Torvalds 	sock_release(sock);
13221da177e4SLinus Torvalds 	return retval;
13231da177e4SLinus Torvalds }
13241da177e4SLinus Torvalds 
13251da177e4SLinus Torvalds /*
13261da177e4SLinus Torvalds  *	Create a pair of connected sockets.
13271da177e4SLinus Torvalds  */
13281da177e4SLinus Torvalds 
13293e0fa65fSHeiko Carstens SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
13303e0fa65fSHeiko Carstens 		int __user *, usockvec)
13311da177e4SLinus Torvalds {
13321da177e4SLinus Torvalds 	struct socket *sock1, *sock2;
13331da177e4SLinus Torvalds 	int fd1, fd2, err;
1334db349509SAl Viro 	struct file *newfile1, *newfile2;
1335a677a039SUlrich Drepper 	int flags;
1336a677a039SUlrich Drepper 
1337a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
133877d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1339a677a039SUlrich Drepper 		return -EINVAL;
1340a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
13411da177e4SLinus Torvalds 
1342aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1343aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1344aaca0bdcSUlrich Drepper 
13451da177e4SLinus Torvalds 	/*
13461da177e4SLinus Torvalds 	 * Obtain the first socket and check if the underlying protocol
13471da177e4SLinus Torvalds 	 * supports the socketpair call.
13481da177e4SLinus Torvalds 	 */
13491da177e4SLinus Torvalds 
13501da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock1);
13511da177e4SLinus Torvalds 	if (err < 0)
13521da177e4SLinus Torvalds 		goto out;
13531da177e4SLinus Torvalds 
13541da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock2);
13551da177e4SLinus Torvalds 	if (err < 0)
13561da177e4SLinus Torvalds 		goto out_release_1;
13571da177e4SLinus Torvalds 
13581da177e4SLinus Torvalds 	err = sock1->ops->socketpair(sock1, sock2);
13591da177e4SLinus Torvalds 	if (err < 0)
13601da177e4SLinus Torvalds 		goto out_release_both;
13611da177e4SLinus Torvalds 
136228407630SAl Viro 	fd1 = get_unused_fd_flags(flags);
1363bf3c23d1SDavid S. Miller 	if (unlikely(fd1 < 0)) {
1364bf3c23d1SDavid S. Miller 		err = fd1;
13651da177e4SLinus Torvalds 		goto out_release_both;
1366bf3c23d1SDavid S. Miller 	}
1367d73aa286SYann Droneaud 
136828407630SAl Viro 	fd2 = get_unused_fd_flags(flags);
1369198de4d7SAl Viro 	if (unlikely(fd2 < 0)) {
1370198de4d7SAl Viro 		err = fd2;
1371d73aa286SYann Droneaud 		goto out_put_unused_1;
137228407630SAl Viro 	}
137328407630SAl Viro 
1374aab174f0SLinus Torvalds 	newfile1 = sock_alloc_file(sock1, flags, NULL);
137528407630SAl Viro 	if (unlikely(IS_ERR(newfile1))) {
137628407630SAl Viro 		err = PTR_ERR(newfile1);
1377d73aa286SYann Droneaud 		goto out_put_unused_both;
137828407630SAl Viro 	}
137928407630SAl Viro 
1380aab174f0SLinus Torvalds 	newfile2 = sock_alloc_file(sock2, flags, NULL);
138128407630SAl Viro 	if (IS_ERR(newfile2)) {
138228407630SAl Viro 		err = PTR_ERR(newfile2);
1383d73aa286SYann Droneaud 		goto out_fput_1;
1384db349509SAl Viro 	}
1385db349509SAl Viro 
1386d73aa286SYann Droneaud 	err = put_user(fd1, &usockvec[0]);
1387d73aa286SYann Droneaud 	if (err)
1388d73aa286SYann Droneaud 		goto out_fput_both;
1389d73aa286SYann Droneaud 
1390d73aa286SYann Droneaud 	err = put_user(fd2, &usockvec[1]);
1391d73aa286SYann Droneaud 	if (err)
1392d73aa286SYann Droneaud 		goto out_fput_both;
1393d73aa286SYann Droneaud 
1394157cf649SAl Viro 	audit_fd_pair(fd1, fd2);
1395d73aa286SYann Droneaud 
1396db349509SAl Viro 	fd_install(fd1, newfile1);
1397db349509SAl Viro 	fd_install(fd2, newfile2);
13981da177e4SLinus Torvalds 	/* fd1 and fd2 may be already another descriptors.
13991da177e4SLinus Torvalds 	 * Not kernel problem.
14001da177e4SLinus Torvalds 	 */
14011da177e4SLinus Torvalds 
14021da177e4SLinus Torvalds 	return 0;
14031da177e4SLinus Torvalds 
1404d73aa286SYann Droneaud out_fput_both:
1405d73aa286SYann Droneaud 	fput(newfile2);
1406d73aa286SYann Droneaud 	fput(newfile1);
1407d73aa286SYann Droneaud 	put_unused_fd(fd2);
1408d73aa286SYann Droneaud 	put_unused_fd(fd1);
1409d73aa286SYann Droneaud 	goto out;
14101da177e4SLinus Torvalds 
1411d73aa286SYann Droneaud out_fput_1:
1412d73aa286SYann Droneaud 	fput(newfile1);
1413d73aa286SYann Droneaud 	put_unused_fd(fd2);
1414d73aa286SYann Droneaud 	put_unused_fd(fd1);
1415d73aa286SYann Droneaud 	sock_release(sock2);
1416d73aa286SYann Droneaud 	goto out;
1417d73aa286SYann Droneaud 
1418d73aa286SYann Droneaud out_put_unused_both:
1419d73aa286SYann Droneaud 	put_unused_fd(fd2);
1420d73aa286SYann Droneaud out_put_unused_1:
1421d73aa286SYann Droneaud 	put_unused_fd(fd1);
14221da177e4SLinus Torvalds out_release_both:
14231da177e4SLinus Torvalds 	sock_release(sock2);
14241da177e4SLinus Torvalds out_release_1:
14251da177e4SLinus Torvalds 	sock_release(sock1);
14261da177e4SLinus Torvalds out:
14271da177e4SLinus Torvalds 	return err;
14281da177e4SLinus Torvalds }
14291da177e4SLinus Torvalds 
14301da177e4SLinus Torvalds /*
14311da177e4SLinus Torvalds  *	Bind a name to a socket. Nothing much to do here since it's
14321da177e4SLinus Torvalds  *	the protocol's responsibility to handle the local address.
14331da177e4SLinus Torvalds  *
14341da177e4SLinus Torvalds  *	We move the socket address to kernel space before we call
14351da177e4SLinus Torvalds  *	the protocol layer (having also checked the address is ok).
14361da177e4SLinus Torvalds  */
14371da177e4SLinus Torvalds 
143820f37034SHeiko Carstens SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
14391da177e4SLinus Torvalds {
14401da177e4SLinus Torvalds 	struct socket *sock;
1441230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
14426cb153caSBenjamin LaHaise 	int err, fput_needed;
14431da177e4SLinus Torvalds 
144489bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
144589bddce5SStephen Hemminger 	if (sock) {
144643db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(umyaddr, addrlen, &address);
144789bddce5SStephen Hemminger 		if (err >= 0) {
144889bddce5SStephen Hemminger 			err = security_socket_bind(sock,
1449230b1839SYOSHIFUJI Hideaki 						   (struct sockaddr *)&address,
145089bddce5SStephen Hemminger 						   addrlen);
14516cb153caSBenjamin LaHaise 			if (!err)
14526cb153caSBenjamin LaHaise 				err = sock->ops->bind(sock,
145389bddce5SStephen Hemminger 						      (struct sockaddr *)
1454230b1839SYOSHIFUJI Hideaki 						      &address, addrlen);
14551da177e4SLinus Torvalds 		}
14566cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
14571da177e4SLinus Torvalds 	}
14581da177e4SLinus Torvalds 	return err;
14591da177e4SLinus Torvalds }
14601da177e4SLinus Torvalds 
14611da177e4SLinus Torvalds /*
14621da177e4SLinus Torvalds  *	Perform a listen. Basically, we allow the protocol to do anything
14631da177e4SLinus Torvalds  *	necessary for a listen, and if that works, we mark the socket as
14641da177e4SLinus Torvalds  *	ready for listening.
14651da177e4SLinus Torvalds  */
14661da177e4SLinus Torvalds 
14673e0fa65fSHeiko Carstens SYSCALL_DEFINE2(listen, int, fd, int, backlog)
14681da177e4SLinus Torvalds {
14691da177e4SLinus Torvalds 	struct socket *sock;
14706cb153caSBenjamin LaHaise 	int err, fput_needed;
1471b8e1f9b5SPavel Emelyanov 	int somaxconn;
14721da177e4SLinus Torvalds 
147389bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
147489bddce5SStephen Hemminger 	if (sock) {
14758efa6e93SPavel Emelyanov 		somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
147695c96174SEric Dumazet 		if ((unsigned int)backlog > somaxconn)
1477b8e1f9b5SPavel Emelyanov 			backlog = somaxconn;
14781da177e4SLinus Torvalds 
14791da177e4SLinus Torvalds 		err = security_socket_listen(sock, backlog);
14806cb153caSBenjamin LaHaise 		if (!err)
14811da177e4SLinus Torvalds 			err = sock->ops->listen(sock, backlog);
14826cb153caSBenjamin LaHaise 
14836cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
14841da177e4SLinus Torvalds 	}
14851da177e4SLinus Torvalds 	return err;
14861da177e4SLinus Torvalds }
14871da177e4SLinus Torvalds 
14881da177e4SLinus Torvalds /*
14891da177e4SLinus Torvalds  *	For accept, we attempt to create a new socket, set up the link
14901da177e4SLinus Torvalds  *	with the client, wake up the client, then return the new
14911da177e4SLinus Torvalds  *	connected fd. We collect the address of the connector in kernel
14921da177e4SLinus Torvalds  *	space and move it to user at the very end. This is unclean because
14931da177e4SLinus Torvalds  *	we open the socket then return an error.
14941da177e4SLinus Torvalds  *
14951da177e4SLinus Torvalds  *	1003.1g adds the ability to recvmsg() to query connection pending
14961da177e4SLinus Torvalds  *	status to recvmsg. We need to add that support in a way thats
14971da177e4SLinus Torvalds  *	clean when we restucture accept also.
14981da177e4SLinus Torvalds  */
14991da177e4SLinus Torvalds 
150020f37034SHeiko Carstens SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
150120f37034SHeiko Carstens 		int __user *, upeer_addrlen, int, flags)
15021da177e4SLinus Torvalds {
15031da177e4SLinus Torvalds 	struct socket *sock, *newsock;
150439d8c1b6SDavid S. Miller 	struct file *newfile;
15056cb153caSBenjamin LaHaise 	int err, len, newfd, fput_needed;
1506230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
15071da177e4SLinus Torvalds 
150877d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1509aaca0bdcSUlrich Drepper 		return -EINVAL;
1510aaca0bdcSUlrich Drepper 
1511aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1512aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1513aaca0bdcSUlrich Drepper 
15146cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
15151da177e4SLinus Torvalds 	if (!sock)
15161da177e4SLinus Torvalds 		goto out;
15171da177e4SLinus Torvalds 
15181da177e4SLinus Torvalds 	err = -ENFILE;
1519c6d409cfSEric Dumazet 	newsock = sock_alloc();
1520c6d409cfSEric Dumazet 	if (!newsock)
15211da177e4SLinus Torvalds 		goto out_put;
15221da177e4SLinus Torvalds 
15231da177e4SLinus Torvalds 	newsock->type = sock->type;
15241da177e4SLinus Torvalds 	newsock->ops = sock->ops;
15251da177e4SLinus Torvalds 
15261da177e4SLinus Torvalds 	/*
15271da177e4SLinus Torvalds 	 * We don't need try_module_get here, as the listening socket (sock)
15281da177e4SLinus Torvalds 	 * has the protocol module (sock->ops->owner) held.
15291da177e4SLinus Torvalds 	 */
15301da177e4SLinus Torvalds 	__module_get(newsock->ops->owner);
15311da177e4SLinus Torvalds 
153228407630SAl Viro 	newfd = get_unused_fd_flags(flags);
153339d8c1b6SDavid S. Miller 	if (unlikely(newfd < 0)) {
153439d8c1b6SDavid S. Miller 		err = newfd;
15359a1875e6SDavid S. Miller 		sock_release(newsock);
15369a1875e6SDavid S. Miller 		goto out_put;
153739d8c1b6SDavid S. Miller 	}
1538aab174f0SLinus Torvalds 	newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name);
153928407630SAl Viro 	if (unlikely(IS_ERR(newfile))) {
154028407630SAl Viro 		err = PTR_ERR(newfile);
154128407630SAl Viro 		put_unused_fd(newfd);
154228407630SAl Viro 		sock_release(newsock);
154328407630SAl Viro 		goto out_put;
154428407630SAl Viro 	}
154539d8c1b6SDavid S. Miller 
1546a79af59eSFrank Filz 	err = security_socket_accept(sock, newsock);
1547a79af59eSFrank Filz 	if (err)
154839d8c1b6SDavid S. Miller 		goto out_fd;
1549a79af59eSFrank Filz 
15501da177e4SLinus Torvalds 	err = sock->ops->accept(sock, newsock, sock->file->f_flags);
15511da177e4SLinus Torvalds 	if (err < 0)
155239d8c1b6SDavid S. Miller 		goto out_fd;
15531da177e4SLinus Torvalds 
15541da177e4SLinus Torvalds 	if (upeer_sockaddr) {
1555230b1839SYOSHIFUJI Hideaki 		if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
155689bddce5SStephen Hemminger 					  &len, 2) < 0) {
15571da177e4SLinus Torvalds 			err = -ECONNABORTED;
155839d8c1b6SDavid S. Miller 			goto out_fd;
15591da177e4SLinus Torvalds 		}
156043db362dSMaciej Żenczykowski 		err = move_addr_to_user(&address,
1561230b1839SYOSHIFUJI Hideaki 					len, upeer_sockaddr, upeer_addrlen);
15621da177e4SLinus Torvalds 		if (err < 0)
156339d8c1b6SDavid S. Miller 			goto out_fd;
15641da177e4SLinus Torvalds 	}
15651da177e4SLinus Torvalds 
15661da177e4SLinus Torvalds 	/* File flags are not inherited via accept() unlike another OSes. */
15671da177e4SLinus Torvalds 
156839d8c1b6SDavid S. Miller 	fd_install(newfd, newfile);
156939d8c1b6SDavid S. Miller 	err = newfd;
15701da177e4SLinus Torvalds 
15711da177e4SLinus Torvalds out_put:
15726cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
15731da177e4SLinus Torvalds out:
15741da177e4SLinus Torvalds 	return err;
157539d8c1b6SDavid S. Miller out_fd:
15769606a216SDavid S. Miller 	fput(newfile);
157739d8c1b6SDavid S. Miller 	put_unused_fd(newfd);
15781da177e4SLinus Torvalds 	goto out_put;
15791da177e4SLinus Torvalds }
15801da177e4SLinus Torvalds 
158120f37034SHeiko Carstens SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,
158220f37034SHeiko Carstens 		int __user *, upeer_addrlen)
1583aaca0bdcSUlrich Drepper {
1584de11defeSUlrich Drepper 	return sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0);
1585aaca0bdcSUlrich Drepper }
1586aaca0bdcSUlrich Drepper 
15871da177e4SLinus Torvalds /*
15881da177e4SLinus Torvalds  *	Attempt to connect to a socket with the server address.  The address
15891da177e4SLinus Torvalds  *	is in user space so we verify it is OK and move it to kernel space.
15901da177e4SLinus Torvalds  *
15911da177e4SLinus Torvalds  *	For 1003.1g we need to add clean support for a bind to AF_UNSPEC to
15921da177e4SLinus Torvalds  *	break bindings
15931da177e4SLinus Torvalds  *
15941da177e4SLinus Torvalds  *	NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and
15951da177e4SLinus Torvalds  *	other SEQPACKET protocols that take time to connect() as it doesn't
15961da177e4SLinus Torvalds  *	include the -EINPROGRESS status for such sockets.
15971da177e4SLinus Torvalds  */
15981da177e4SLinus Torvalds 
159920f37034SHeiko Carstens SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
160020f37034SHeiko Carstens 		int, addrlen)
16011da177e4SLinus Torvalds {
16021da177e4SLinus Torvalds 	struct socket *sock;
1603230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16046cb153caSBenjamin LaHaise 	int err, fput_needed;
16051da177e4SLinus Torvalds 
16066cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
16071da177e4SLinus Torvalds 	if (!sock)
16081da177e4SLinus Torvalds 		goto out;
160943db362dSMaciej Żenczykowski 	err = move_addr_to_kernel(uservaddr, addrlen, &address);
16101da177e4SLinus Torvalds 	if (err < 0)
16111da177e4SLinus Torvalds 		goto out_put;
16121da177e4SLinus Torvalds 
161389bddce5SStephen Hemminger 	err =
1614230b1839SYOSHIFUJI Hideaki 	    security_socket_connect(sock, (struct sockaddr *)&address, addrlen);
16151da177e4SLinus Torvalds 	if (err)
16161da177e4SLinus Torvalds 		goto out_put;
16171da177e4SLinus Torvalds 
1618230b1839SYOSHIFUJI Hideaki 	err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,
16191da177e4SLinus Torvalds 				 sock->file->f_flags);
16201da177e4SLinus Torvalds out_put:
16216cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
16221da177e4SLinus Torvalds out:
16231da177e4SLinus Torvalds 	return err;
16241da177e4SLinus Torvalds }
16251da177e4SLinus Torvalds 
16261da177e4SLinus Torvalds /*
16271da177e4SLinus Torvalds  *	Get the local address ('name') of a socket object. Move the obtained
16281da177e4SLinus Torvalds  *	name to user space.
16291da177e4SLinus Torvalds  */
16301da177e4SLinus Torvalds 
163120f37034SHeiko Carstens SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
163220f37034SHeiko Carstens 		int __user *, usockaddr_len)
16331da177e4SLinus Torvalds {
16341da177e4SLinus Torvalds 	struct socket *sock;
1635230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16366cb153caSBenjamin LaHaise 	int len, err, fput_needed;
16371da177e4SLinus Torvalds 
16386cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
16391da177e4SLinus Torvalds 	if (!sock)
16401da177e4SLinus Torvalds 		goto out;
16411da177e4SLinus Torvalds 
16421da177e4SLinus Torvalds 	err = security_socket_getsockname(sock);
16431da177e4SLinus Torvalds 	if (err)
16441da177e4SLinus Torvalds 		goto out_put;
16451da177e4SLinus Torvalds 
1646230b1839SYOSHIFUJI Hideaki 	err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0);
16471da177e4SLinus Torvalds 	if (err)
16481da177e4SLinus Torvalds 		goto out_put;
164943db362dSMaciej Żenczykowski 	err = move_addr_to_user(&address, len, usockaddr, usockaddr_len);
16501da177e4SLinus Torvalds 
16511da177e4SLinus Torvalds out_put:
16526cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
16531da177e4SLinus Torvalds out:
16541da177e4SLinus Torvalds 	return err;
16551da177e4SLinus Torvalds }
16561da177e4SLinus Torvalds 
16571da177e4SLinus Torvalds /*
16581da177e4SLinus Torvalds  *	Get the remote address ('name') of a socket object. Move the obtained
16591da177e4SLinus Torvalds  *	name to user space.
16601da177e4SLinus Torvalds  */
16611da177e4SLinus Torvalds 
166220f37034SHeiko Carstens SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
166320f37034SHeiko Carstens 		int __user *, usockaddr_len)
16641da177e4SLinus Torvalds {
16651da177e4SLinus Torvalds 	struct socket *sock;
1666230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16676cb153caSBenjamin LaHaise 	int len, err, fput_needed;
16681da177e4SLinus Torvalds 
166989bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
167089bddce5SStephen Hemminger 	if (sock != NULL) {
16711da177e4SLinus Torvalds 		err = security_socket_getpeername(sock);
16721da177e4SLinus Torvalds 		if (err) {
16736cb153caSBenjamin LaHaise 			fput_light(sock->file, fput_needed);
16741da177e4SLinus Torvalds 			return err;
16751da177e4SLinus Torvalds 		}
16761da177e4SLinus Torvalds 
167789bddce5SStephen Hemminger 		err =
1678230b1839SYOSHIFUJI Hideaki 		    sock->ops->getname(sock, (struct sockaddr *)&address, &len,
167989bddce5SStephen Hemminger 				       1);
16801da177e4SLinus Torvalds 		if (!err)
168143db362dSMaciej Żenczykowski 			err = move_addr_to_user(&address, len, usockaddr,
168289bddce5SStephen Hemminger 						usockaddr_len);
16836cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
16841da177e4SLinus Torvalds 	}
16851da177e4SLinus Torvalds 	return err;
16861da177e4SLinus Torvalds }
16871da177e4SLinus Torvalds 
16881da177e4SLinus Torvalds /*
16891da177e4SLinus Torvalds  *	Send a datagram to a given address. We move the address into kernel
16901da177e4SLinus Torvalds  *	space and check the user space data area is readable before invoking
16911da177e4SLinus Torvalds  *	the protocol.
16921da177e4SLinus Torvalds  */
16931da177e4SLinus Torvalds 
16943e0fa65fSHeiko Carstens SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
169595c96174SEric Dumazet 		unsigned int, flags, struct sockaddr __user *, addr,
16963e0fa65fSHeiko Carstens 		int, addr_len)
16971da177e4SLinus Torvalds {
16981da177e4SLinus Torvalds 	struct socket *sock;
1699230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
17001da177e4SLinus Torvalds 	int err;
17011da177e4SLinus Torvalds 	struct msghdr msg;
17021da177e4SLinus Torvalds 	struct iovec iov;
17036cb153caSBenjamin LaHaise 	int fput_needed;
17041da177e4SLinus Torvalds 
1705253eacc0SLinus Torvalds 	if (len > INT_MAX)
1706253eacc0SLinus Torvalds 		len = INT_MAX;
1707de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1708de0fa95cSPavel Emelyanov 	if (!sock)
17094387ff75SDavid S. Miller 		goto out;
17106cb153caSBenjamin LaHaise 
17111da177e4SLinus Torvalds 	iov.iov_base = buff;
17121da177e4SLinus Torvalds 	iov.iov_len = len;
17131da177e4SLinus Torvalds 	msg.msg_name = NULL;
1714c0371da6SAl Viro 	iov_iter_init(&msg.msg_iter, WRITE, &iov, 1, len);
17151da177e4SLinus Torvalds 	msg.msg_control = NULL;
17161da177e4SLinus Torvalds 	msg.msg_controllen = 0;
17171da177e4SLinus Torvalds 	msg.msg_namelen = 0;
17186cb153caSBenjamin LaHaise 	if (addr) {
171943db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(addr, addr_len, &address);
17201da177e4SLinus Torvalds 		if (err < 0)
17211da177e4SLinus Torvalds 			goto out_put;
1722230b1839SYOSHIFUJI Hideaki 		msg.msg_name = (struct sockaddr *)&address;
17231da177e4SLinus Torvalds 		msg.msg_namelen = addr_len;
17241da177e4SLinus Torvalds 	}
17251da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
17261da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
17271da177e4SLinus Torvalds 	msg.msg_flags = flags;
17281da177e4SLinus Torvalds 	err = sock_sendmsg(sock, &msg, len);
17291da177e4SLinus Torvalds 
17301da177e4SLinus Torvalds out_put:
1731de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
17324387ff75SDavid S. Miller out:
17331da177e4SLinus Torvalds 	return err;
17341da177e4SLinus Torvalds }
17351da177e4SLinus Torvalds 
17361da177e4SLinus Torvalds /*
17371da177e4SLinus Torvalds  *	Send a datagram down a socket.
17381da177e4SLinus Torvalds  */
17391da177e4SLinus Torvalds 
17403e0fa65fSHeiko Carstens SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len,
174195c96174SEric Dumazet 		unsigned int, flags)
17421da177e4SLinus Torvalds {
17431da177e4SLinus Torvalds 	return sys_sendto(fd, buff, len, flags, NULL, 0);
17441da177e4SLinus Torvalds }
17451da177e4SLinus Torvalds 
17461da177e4SLinus Torvalds /*
17471da177e4SLinus Torvalds  *	Receive a frame from the socket and optionally record the address of the
17481da177e4SLinus Torvalds  *	sender. We verify the buffers are writable and if needed move the
17491da177e4SLinus Torvalds  *	sender address from kernel to user space.
17501da177e4SLinus Torvalds  */
17511da177e4SLinus Torvalds 
17523e0fa65fSHeiko Carstens SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
175395c96174SEric Dumazet 		unsigned int, flags, struct sockaddr __user *, addr,
17543e0fa65fSHeiko Carstens 		int __user *, addr_len)
17551da177e4SLinus Torvalds {
17561da177e4SLinus Torvalds 	struct socket *sock;
17571da177e4SLinus Torvalds 	struct iovec iov;
17581da177e4SLinus Torvalds 	struct msghdr msg;
1759230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
17601da177e4SLinus Torvalds 	int err, err2;
17616cb153caSBenjamin LaHaise 	int fput_needed;
17621da177e4SLinus Torvalds 
1763253eacc0SLinus Torvalds 	if (size > INT_MAX)
1764253eacc0SLinus Torvalds 		size = INT_MAX;
1765de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
17661da177e4SLinus Torvalds 	if (!sock)
1767de0fa95cSPavel Emelyanov 		goto out;
17681da177e4SLinus Torvalds 
17691da177e4SLinus Torvalds 	msg.msg_control = NULL;
17701da177e4SLinus Torvalds 	msg.msg_controllen = 0;
17711da177e4SLinus Torvalds 	iov.iov_len = size;
17721da177e4SLinus Torvalds 	iov.iov_base = ubuf;
1773c0371da6SAl Viro 	iov_iter_init(&msg.msg_iter, READ, &iov, 1, size);
1774f3d33426SHannes Frederic Sowa 	/* Save some cycles and don't copy the address if not needed */
1775f3d33426SHannes Frederic Sowa 	msg.msg_name = addr ? (struct sockaddr *)&address : NULL;
1776f3d33426SHannes Frederic Sowa 	/* We assume all kernel code knows the size of sockaddr_storage */
1777f3d33426SHannes Frederic Sowa 	msg.msg_namelen = 0;
17781da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
17791da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
17801da177e4SLinus Torvalds 	err = sock_recvmsg(sock, &msg, size, flags);
17811da177e4SLinus Torvalds 
178289bddce5SStephen Hemminger 	if (err >= 0 && addr != NULL) {
178343db362dSMaciej Żenczykowski 		err2 = move_addr_to_user(&address,
1784230b1839SYOSHIFUJI Hideaki 					 msg.msg_namelen, addr, addr_len);
17851da177e4SLinus Torvalds 		if (err2 < 0)
17861da177e4SLinus Torvalds 			err = err2;
17871da177e4SLinus Torvalds 	}
1788de0fa95cSPavel Emelyanov 
1789de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
17904387ff75SDavid S. Miller out:
17911da177e4SLinus Torvalds 	return err;
17921da177e4SLinus Torvalds }
17931da177e4SLinus Torvalds 
17941da177e4SLinus Torvalds /*
17951da177e4SLinus Torvalds  *	Receive a datagram from a socket.
17961da177e4SLinus Torvalds  */
17971da177e4SLinus Torvalds 
1798b7c0ddf5SJan Glauber SYSCALL_DEFINE4(recv, int, fd, void __user *, ubuf, size_t, size,
1799b7c0ddf5SJan Glauber 		unsigned int, flags)
18001da177e4SLinus Torvalds {
18011da177e4SLinus Torvalds 	return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL);
18021da177e4SLinus Torvalds }
18031da177e4SLinus Torvalds 
18041da177e4SLinus Torvalds /*
18051da177e4SLinus Torvalds  *	Set a socket option. Because we don't know the option lengths we have
18061da177e4SLinus Torvalds  *	to pass the user mode parameter for the protocols to sort out.
18071da177e4SLinus Torvalds  */
18081da177e4SLinus Torvalds 
180920f37034SHeiko Carstens SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
181020f37034SHeiko Carstens 		char __user *, optval, int, optlen)
18111da177e4SLinus Torvalds {
18126cb153caSBenjamin LaHaise 	int err, fput_needed;
18131da177e4SLinus Torvalds 	struct socket *sock;
18141da177e4SLinus Torvalds 
18151da177e4SLinus Torvalds 	if (optlen < 0)
18161da177e4SLinus Torvalds 		return -EINVAL;
18171da177e4SLinus Torvalds 
181889bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
181989bddce5SStephen Hemminger 	if (sock != NULL) {
18201da177e4SLinus Torvalds 		err = security_socket_setsockopt(sock, level, optname);
18216cb153caSBenjamin LaHaise 		if (err)
18226cb153caSBenjamin LaHaise 			goto out_put;
18231da177e4SLinus Torvalds 
18241da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
182589bddce5SStephen Hemminger 			err =
182689bddce5SStephen Hemminger 			    sock_setsockopt(sock, level, optname, optval,
182789bddce5SStephen Hemminger 					    optlen);
18281da177e4SLinus Torvalds 		else
182989bddce5SStephen Hemminger 			err =
183089bddce5SStephen Hemminger 			    sock->ops->setsockopt(sock, level, optname, optval,
183189bddce5SStephen Hemminger 						  optlen);
18326cb153caSBenjamin LaHaise out_put:
18336cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
18341da177e4SLinus Torvalds 	}
18351da177e4SLinus Torvalds 	return err;
18361da177e4SLinus Torvalds }
18371da177e4SLinus Torvalds 
18381da177e4SLinus Torvalds /*
18391da177e4SLinus Torvalds  *	Get a socket option. Because we don't know the option lengths we have
18401da177e4SLinus Torvalds  *	to pass a user mode parameter for the protocols to sort out.
18411da177e4SLinus Torvalds  */
18421da177e4SLinus Torvalds 
184320f37034SHeiko Carstens SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
184420f37034SHeiko Carstens 		char __user *, optval, int __user *, optlen)
18451da177e4SLinus Torvalds {
18466cb153caSBenjamin LaHaise 	int err, fput_needed;
18471da177e4SLinus Torvalds 	struct socket *sock;
18481da177e4SLinus Torvalds 
184989bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
185089bddce5SStephen Hemminger 	if (sock != NULL) {
18516cb153caSBenjamin LaHaise 		err = security_socket_getsockopt(sock, level, optname);
18526cb153caSBenjamin LaHaise 		if (err)
18536cb153caSBenjamin LaHaise 			goto out_put;
18541da177e4SLinus Torvalds 
18551da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
185689bddce5SStephen Hemminger 			err =
185789bddce5SStephen Hemminger 			    sock_getsockopt(sock, level, optname, optval,
185889bddce5SStephen Hemminger 					    optlen);
18591da177e4SLinus Torvalds 		else
186089bddce5SStephen Hemminger 			err =
186189bddce5SStephen Hemminger 			    sock->ops->getsockopt(sock, level, optname, optval,
186289bddce5SStephen Hemminger 						  optlen);
18636cb153caSBenjamin LaHaise out_put:
18646cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
18651da177e4SLinus Torvalds 	}
18661da177e4SLinus Torvalds 	return err;
18671da177e4SLinus Torvalds }
18681da177e4SLinus Torvalds 
18691da177e4SLinus Torvalds /*
18701da177e4SLinus Torvalds  *	Shutdown a socket.
18711da177e4SLinus Torvalds  */
18721da177e4SLinus Torvalds 
1873754fe8d2SHeiko Carstens SYSCALL_DEFINE2(shutdown, int, fd, int, how)
18741da177e4SLinus Torvalds {
18756cb153caSBenjamin LaHaise 	int err, fput_needed;
18761da177e4SLinus Torvalds 	struct socket *sock;
18771da177e4SLinus Torvalds 
187889bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
187989bddce5SStephen Hemminger 	if (sock != NULL) {
18801da177e4SLinus Torvalds 		err = security_socket_shutdown(sock, how);
18816cb153caSBenjamin LaHaise 		if (!err)
18821da177e4SLinus Torvalds 			err = sock->ops->shutdown(sock, how);
18836cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
18841da177e4SLinus Torvalds 	}
18851da177e4SLinus Torvalds 	return err;
18861da177e4SLinus Torvalds }
18871da177e4SLinus Torvalds 
18881da177e4SLinus Torvalds /* A couple of helpful macros for getting the address of the 32/64 bit
18891da177e4SLinus Torvalds  * fields which are the same type (int / unsigned) on our platforms.
18901da177e4SLinus Torvalds  */
18911da177e4SLinus Torvalds #define COMPAT_MSG(msg, member)	((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member)
18921da177e4SLinus Torvalds #define COMPAT_NAMELEN(msg)	COMPAT_MSG(msg, msg_namelen)
18931da177e4SLinus Torvalds #define COMPAT_FLAGS(msg)	COMPAT_MSG(msg, msg_flags)
18941da177e4SLinus Torvalds 
1895c71d8ebeSTetsuo Handa struct used_address {
1896c71d8ebeSTetsuo Handa 	struct sockaddr_storage name;
1897c71d8ebeSTetsuo Handa 	unsigned int name_len;
1898c71d8ebeSTetsuo Handa };
1899c71d8ebeSTetsuo Handa 
190008adb7daSAl Viro static ssize_t copy_msghdr_from_user(struct msghdr *kmsg,
190108adb7daSAl Viro 				     struct user_msghdr __user *umsg,
190208adb7daSAl Viro 				     struct sockaddr __user **save_addr,
190308adb7daSAl Viro 				     struct iovec **iov)
19041661bf36SDan Carpenter {
190508adb7daSAl Viro 	struct sockaddr __user *uaddr;
190608adb7daSAl Viro 	struct iovec __user *uiov;
1907c0371da6SAl Viro 	size_t nr_segs;
190808adb7daSAl Viro 	ssize_t err;
190908adb7daSAl Viro 
191008adb7daSAl Viro 	if (!access_ok(VERIFY_READ, umsg, sizeof(*umsg)) ||
191108adb7daSAl Viro 	    __get_user(uaddr, &umsg->msg_name) ||
191208adb7daSAl Viro 	    __get_user(kmsg->msg_namelen, &umsg->msg_namelen) ||
191308adb7daSAl Viro 	    __get_user(uiov, &umsg->msg_iov) ||
1914c0371da6SAl Viro 	    __get_user(nr_segs, &umsg->msg_iovlen) ||
191508adb7daSAl Viro 	    __get_user(kmsg->msg_control, &umsg->msg_control) ||
191608adb7daSAl Viro 	    __get_user(kmsg->msg_controllen, &umsg->msg_controllen) ||
191708adb7daSAl Viro 	    __get_user(kmsg->msg_flags, &umsg->msg_flags))
19181661bf36SDan Carpenter 		return -EFAULT;
1919dbb490b9SMatthew Leach 
192008adb7daSAl Viro 	if (!uaddr)
19216a2a2b3aSAni Sinha 		kmsg->msg_namelen = 0;
19226a2a2b3aSAni Sinha 
1923dbb490b9SMatthew Leach 	if (kmsg->msg_namelen < 0)
1924dbb490b9SMatthew Leach 		return -EINVAL;
1925dbb490b9SMatthew Leach 
19261661bf36SDan Carpenter 	if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
1927db31c55aSDan Carpenter 		kmsg->msg_namelen = sizeof(struct sockaddr_storage);
192808adb7daSAl Viro 
192908adb7daSAl Viro 	if (save_addr)
193008adb7daSAl Viro 		*save_addr = uaddr;
193108adb7daSAl Viro 
193208adb7daSAl Viro 	if (uaddr && kmsg->msg_namelen) {
193308adb7daSAl Viro 		if (!save_addr) {
193408adb7daSAl Viro 			err = move_addr_to_kernel(uaddr, kmsg->msg_namelen,
193508adb7daSAl Viro 						  kmsg->msg_name);
193608adb7daSAl Viro 			if (err < 0)
193708adb7daSAl Viro 				return err;
193808adb7daSAl Viro 		}
193908adb7daSAl Viro 	} else {
194008adb7daSAl Viro 		kmsg->msg_name = NULL;
194108adb7daSAl Viro 		kmsg->msg_namelen = 0;
194208adb7daSAl Viro 	}
194308adb7daSAl Viro 
1944c0371da6SAl Viro 	if (nr_segs > UIO_MAXIOV)
194508adb7daSAl Viro 		return -EMSGSIZE;
194608adb7daSAl Viro 
194708adb7daSAl Viro 	err = rw_copy_check_uvector(save_addr ? READ : WRITE,
1948c0371da6SAl Viro 				    uiov, nr_segs,
194908adb7daSAl Viro 				    UIO_FASTIOV, *iov, iov);
195008adb7daSAl Viro 	if (err >= 0)
1951c0371da6SAl Viro 		iov_iter_init(&kmsg->msg_iter, save_addr ? READ : WRITE,
1952c0371da6SAl Viro 			      *iov, nr_segs, err);
195308adb7daSAl Viro 	return err;
19541661bf36SDan Carpenter }
19551661bf36SDan Carpenter 
1956666547ffSAl Viro static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
195795c96174SEric Dumazet 			 struct msghdr *msg_sys, unsigned int flags,
1958c71d8ebeSTetsuo Handa 			 struct used_address *used_address)
19591da177e4SLinus Torvalds {
196089bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
196189bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
1962230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
19631da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
1964b9d717a7SAlex Williamson 	unsigned char ctl[sizeof(struct cmsghdr) + 20]
1965b9d717a7SAlex Williamson 	    __attribute__ ((aligned(sizeof(__kernel_size_t))));
1966b9d717a7SAlex Williamson 	/* 20 is size of ipv6_pktinfo */
19671da177e4SLinus Torvalds 	unsigned char *ctl_buf = ctl;
196808adb7daSAl Viro 	int ctl_len, total_len;
196908adb7daSAl Viro 	ssize_t err;
19701da177e4SLinus Torvalds 
197108adb7daSAl Viro 	msg_sys->msg_name = &address;
19721da177e4SLinus Torvalds 
197308449320SAl Viro 	if (MSG_CMSG_COMPAT & flags)
197408adb7daSAl Viro 		err = get_compat_msghdr(msg_sys, msg_compat, NULL, &iov);
197508449320SAl Viro 	else
197608adb7daSAl Viro 		err = copy_msghdr_from_user(msg_sys, msg, NULL, &iov);
19771da177e4SLinus Torvalds 	if (err < 0)
19781da177e4SLinus Torvalds 		goto out_freeiov;
19791da177e4SLinus Torvalds 	total_len = err;
19801da177e4SLinus Torvalds 
19811da177e4SLinus Torvalds 	err = -ENOBUFS;
19821da177e4SLinus Torvalds 
1983228e548eSAnton Blanchard 	if (msg_sys->msg_controllen > INT_MAX)
19841da177e4SLinus Torvalds 		goto out_freeiov;
1985228e548eSAnton Blanchard 	ctl_len = msg_sys->msg_controllen;
19861da177e4SLinus Torvalds 	if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
198789bddce5SStephen Hemminger 		err =
1988228e548eSAnton Blanchard 		    cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl,
198989bddce5SStephen Hemminger 						     sizeof(ctl));
19901da177e4SLinus Torvalds 		if (err)
19911da177e4SLinus Torvalds 			goto out_freeiov;
1992228e548eSAnton Blanchard 		ctl_buf = msg_sys->msg_control;
1993228e548eSAnton Blanchard 		ctl_len = msg_sys->msg_controllen;
19941da177e4SLinus Torvalds 	} else if (ctl_len) {
199589bddce5SStephen Hemminger 		if (ctl_len > sizeof(ctl)) {
19961da177e4SLinus Torvalds 			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
19971da177e4SLinus Torvalds 			if (ctl_buf == NULL)
19981da177e4SLinus Torvalds 				goto out_freeiov;
19991da177e4SLinus Torvalds 		}
20001da177e4SLinus Torvalds 		err = -EFAULT;
20011da177e4SLinus Torvalds 		/*
2002228e548eSAnton Blanchard 		 * Careful! Before this, msg_sys->msg_control contains a user pointer.
20031da177e4SLinus Torvalds 		 * Afterwards, it will be a kernel pointer. Thus the compiler-assisted
20041da177e4SLinus Torvalds 		 * checking falls down on this.
20051da177e4SLinus Torvalds 		 */
2006fb8621bbSNamhyung Kim 		if (copy_from_user(ctl_buf,
2007228e548eSAnton Blanchard 				   (void __user __force *)msg_sys->msg_control,
200889bddce5SStephen Hemminger 				   ctl_len))
20091da177e4SLinus Torvalds 			goto out_freectl;
2010228e548eSAnton Blanchard 		msg_sys->msg_control = ctl_buf;
20111da177e4SLinus Torvalds 	}
2012228e548eSAnton Blanchard 	msg_sys->msg_flags = flags;
20131da177e4SLinus Torvalds 
20141da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
2015228e548eSAnton Blanchard 		msg_sys->msg_flags |= MSG_DONTWAIT;
2016c71d8ebeSTetsuo Handa 	/*
2017c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and current destination address is same as
2018c71d8ebeSTetsuo Handa 	 * previously succeeded address, omit asking LSM's decision.
2019c71d8ebeSTetsuo Handa 	 * used_address->name_len is initialized to UINT_MAX so that the first
2020c71d8ebeSTetsuo Handa 	 * destination address never matches.
2021c71d8ebeSTetsuo Handa 	 */
2022bc909d9dSMathieu Desnoyers 	if (used_address && msg_sys->msg_name &&
2023bc909d9dSMathieu Desnoyers 	    used_address->name_len == msg_sys->msg_namelen &&
2024bc909d9dSMathieu Desnoyers 	    !memcmp(&used_address->name, msg_sys->msg_name,
2025c71d8ebeSTetsuo Handa 		    used_address->name_len)) {
2026c71d8ebeSTetsuo Handa 		err = sock_sendmsg_nosec(sock, msg_sys, total_len);
2027c71d8ebeSTetsuo Handa 		goto out_freectl;
2028c71d8ebeSTetsuo Handa 	}
2029c71d8ebeSTetsuo Handa 	err = sock_sendmsg(sock, msg_sys, total_len);
2030c71d8ebeSTetsuo Handa 	/*
2031c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and sending to current destination address was
2032c71d8ebeSTetsuo Handa 	 * successful, remember it.
2033c71d8ebeSTetsuo Handa 	 */
2034c71d8ebeSTetsuo Handa 	if (used_address && err >= 0) {
2035c71d8ebeSTetsuo Handa 		used_address->name_len = msg_sys->msg_namelen;
2036bc909d9dSMathieu Desnoyers 		if (msg_sys->msg_name)
2037bc909d9dSMathieu Desnoyers 			memcpy(&used_address->name, msg_sys->msg_name,
2038c71d8ebeSTetsuo Handa 			       used_address->name_len);
2039c71d8ebeSTetsuo Handa 	}
20401da177e4SLinus Torvalds 
20411da177e4SLinus Torvalds out_freectl:
20421da177e4SLinus Torvalds 	if (ctl_buf != ctl)
20431da177e4SLinus Torvalds 		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
20441da177e4SLinus Torvalds out_freeiov:
20451da177e4SLinus Torvalds 	if (iov != iovstack)
2046a74e9106SEric Dumazet 		kfree(iov);
2047228e548eSAnton Blanchard 	return err;
2048228e548eSAnton Blanchard }
2049228e548eSAnton Blanchard 
2050228e548eSAnton Blanchard /*
2051228e548eSAnton Blanchard  *	BSD sendmsg interface
2052228e548eSAnton Blanchard  */
2053228e548eSAnton Blanchard 
2054666547ffSAl Viro long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned flags)
2055228e548eSAnton Blanchard {
2056228e548eSAnton Blanchard 	int fput_needed, err;
2057228e548eSAnton Blanchard 	struct msghdr msg_sys;
20581be374a0SAndy Lutomirski 	struct socket *sock;
2059228e548eSAnton Blanchard 
20601be374a0SAndy Lutomirski 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2061228e548eSAnton Blanchard 	if (!sock)
2062228e548eSAnton Blanchard 		goto out;
2063228e548eSAnton Blanchard 
2064a7526eb5SAndy Lutomirski 	err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL);
2065228e548eSAnton Blanchard 
20666cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
20671da177e4SLinus Torvalds out:
20681da177e4SLinus Torvalds 	return err;
20691da177e4SLinus Torvalds }
20701da177e4SLinus Torvalds 
2071666547ffSAl Viro SYSCALL_DEFINE3(sendmsg, int, fd, struct user_msghdr __user *, msg, unsigned int, flags)
2072a7526eb5SAndy Lutomirski {
2073a7526eb5SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
2074a7526eb5SAndy Lutomirski 		return -EINVAL;
2075a7526eb5SAndy Lutomirski 	return __sys_sendmsg(fd, msg, flags);
2076a7526eb5SAndy Lutomirski }
2077a7526eb5SAndy Lutomirski 
2078228e548eSAnton Blanchard /*
2079228e548eSAnton Blanchard  *	Linux sendmmsg interface
2080228e548eSAnton Blanchard  */
2081228e548eSAnton Blanchard 
2082228e548eSAnton Blanchard int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2083228e548eSAnton Blanchard 		   unsigned int flags)
2084228e548eSAnton Blanchard {
2085228e548eSAnton Blanchard 	int fput_needed, err, datagrams;
2086228e548eSAnton Blanchard 	struct socket *sock;
2087228e548eSAnton Blanchard 	struct mmsghdr __user *entry;
2088228e548eSAnton Blanchard 	struct compat_mmsghdr __user *compat_entry;
2089228e548eSAnton Blanchard 	struct msghdr msg_sys;
2090c71d8ebeSTetsuo Handa 	struct used_address used_address;
2091228e548eSAnton Blanchard 
209298382f41SAnton Blanchard 	if (vlen > UIO_MAXIOV)
209398382f41SAnton Blanchard 		vlen = UIO_MAXIOV;
2094228e548eSAnton Blanchard 
2095228e548eSAnton Blanchard 	datagrams = 0;
2096228e548eSAnton Blanchard 
2097228e548eSAnton Blanchard 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2098228e548eSAnton Blanchard 	if (!sock)
2099228e548eSAnton Blanchard 		return err;
2100228e548eSAnton Blanchard 
2101c71d8ebeSTetsuo Handa 	used_address.name_len = UINT_MAX;
2102228e548eSAnton Blanchard 	entry = mmsg;
2103228e548eSAnton Blanchard 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2104728ffb86SAnton Blanchard 	err = 0;
2105228e548eSAnton Blanchard 
2106228e548eSAnton Blanchard 	while (datagrams < vlen) {
2107228e548eSAnton Blanchard 		if (MSG_CMSG_COMPAT & flags) {
2108666547ffSAl Viro 			err = ___sys_sendmsg(sock, (struct user_msghdr __user *)compat_entry,
2109c71d8ebeSTetsuo Handa 					     &msg_sys, flags, &used_address);
2110228e548eSAnton Blanchard 			if (err < 0)
2111228e548eSAnton Blanchard 				break;
2112228e548eSAnton Blanchard 			err = __put_user(err, &compat_entry->msg_len);
2113228e548eSAnton Blanchard 			++compat_entry;
2114228e548eSAnton Blanchard 		} else {
2115a7526eb5SAndy Lutomirski 			err = ___sys_sendmsg(sock,
2116666547ffSAl Viro 					     (struct user_msghdr __user *)entry,
2117c71d8ebeSTetsuo Handa 					     &msg_sys, flags, &used_address);
2118228e548eSAnton Blanchard 			if (err < 0)
2119228e548eSAnton Blanchard 				break;
2120228e548eSAnton Blanchard 			err = put_user(err, &entry->msg_len);
2121228e548eSAnton Blanchard 			++entry;
2122228e548eSAnton Blanchard 		}
2123228e548eSAnton Blanchard 
2124228e548eSAnton Blanchard 		if (err)
2125228e548eSAnton Blanchard 			break;
2126228e548eSAnton Blanchard 		++datagrams;
2127228e548eSAnton Blanchard 	}
2128228e548eSAnton Blanchard 
2129228e548eSAnton Blanchard 	fput_light(sock->file, fput_needed);
2130228e548eSAnton Blanchard 
2131728ffb86SAnton Blanchard 	/* We only return an error if no datagrams were able to be sent */
2132728ffb86SAnton Blanchard 	if (datagrams != 0)
2133228e548eSAnton Blanchard 		return datagrams;
2134228e548eSAnton Blanchard 
2135228e548eSAnton Blanchard 	return err;
2136228e548eSAnton Blanchard }
2137228e548eSAnton Blanchard 
2138228e548eSAnton Blanchard SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
2139228e548eSAnton Blanchard 		unsigned int, vlen, unsigned int, flags)
2140228e548eSAnton Blanchard {
21411be374a0SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
21421be374a0SAndy Lutomirski 		return -EINVAL;
2143228e548eSAnton Blanchard 	return __sys_sendmmsg(fd, mmsg, vlen, flags);
2144228e548eSAnton Blanchard }
2145228e548eSAnton Blanchard 
2146666547ffSAl Viro static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg,
214795c96174SEric Dumazet 			 struct msghdr *msg_sys, unsigned int flags, int nosec)
21481da177e4SLinus Torvalds {
214989bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
215089bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
21511da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV];
21521da177e4SLinus Torvalds 	struct iovec *iov = iovstack;
21531da177e4SLinus Torvalds 	unsigned long cmsg_ptr;
215408adb7daSAl Viro 	int total_len, len;
215508adb7daSAl Viro 	ssize_t err;
21561da177e4SLinus Torvalds 
21571da177e4SLinus Torvalds 	/* kernel mode address */
2158230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage addr;
21591da177e4SLinus Torvalds 
21601da177e4SLinus Torvalds 	/* user mode address pointers */
21611da177e4SLinus Torvalds 	struct sockaddr __user *uaddr;
216208adb7daSAl Viro 	int __user *uaddr_len = COMPAT_NAMELEN(msg);
21631da177e4SLinus Torvalds 
216408adb7daSAl Viro 	msg_sys->msg_name = &addr;
21651da177e4SLinus Torvalds 
2166f3d33426SHannes Frederic Sowa 	if (MSG_CMSG_COMPAT & flags)
216708adb7daSAl Viro 		err = get_compat_msghdr(msg_sys, msg_compat, &uaddr, &iov);
2168f3d33426SHannes Frederic Sowa 	else
216908adb7daSAl Viro 		err = copy_msghdr_from_user(msg_sys, msg, &uaddr, &iov);
21701da177e4SLinus Torvalds 	if (err < 0)
21711da177e4SLinus Torvalds 		goto out_freeiov;
21721da177e4SLinus Torvalds 	total_len = err;
21731da177e4SLinus Torvalds 
2174a2e27255SArnaldo Carvalho de Melo 	cmsg_ptr = (unsigned long)msg_sys->msg_control;
2175a2e27255SArnaldo Carvalho de Melo 	msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
21761da177e4SLinus Torvalds 
2177f3d33426SHannes Frederic Sowa 	/* We assume all kernel code knows the size of sockaddr_storage */
2178f3d33426SHannes Frederic Sowa 	msg_sys->msg_namelen = 0;
2179f3d33426SHannes Frederic Sowa 
21801da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
21811da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
2182a2e27255SArnaldo Carvalho de Melo 	err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys,
2183a2e27255SArnaldo Carvalho de Melo 							  total_len, flags);
21841da177e4SLinus Torvalds 	if (err < 0)
21851da177e4SLinus Torvalds 		goto out_freeiov;
21861da177e4SLinus Torvalds 	len = err;
21871da177e4SLinus Torvalds 
21881da177e4SLinus Torvalds 	if (uaddr != NULL) {
218943db362dSMaciej Żenczykowski 		err = move_addr_to_user(&addr,
2190a2e27255SArnaldo Carvalho de Melo 					msg_sys->msg_namelen, uaddr,
219189bddce5SStephen Hemminger 					uaddr_len);
21921da177e4SLinus Torvalds 		if (err < 0)
21931da177e4SLinus Torvalds 			goto out_freeiov;
21941da177e4SLinus Torvalds 	}
2195a2e27255SArnaldo Carvalho de Melo 	err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
219637f7f421SDavid S. Miller 			 COMPAT_FLAGS(msg));
21971da177e4SLinus Torvalds 	if (err)
21981da177e4SLinus Torvalds 		goto out_freeiov;
21991da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags)
2200a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
22011da177e4SLinus Torvalds 				 &msg_compat->msg_controllen);
22021da177e4SLinus Torvalds 	else
2203a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
22041da177e4SLinus Torvalds 				 &msg->msg_controllen);
22051da177e4SLinus Torvalds 	if (err)
22061da177e4SLinus Torvalds 		goto out_freeiov;
22071da177e4SLinus Torvalds 	err = len;
22081da177e4SLinus Torvalds 
22091da177e4SLinus Torvalds out_freeiov:
22101da177e4SLinus Torvalds 	if (iov != iovstack)
2211a74e9106SEric Dumazet 		kfree(iov);
2212a2e27255SArnaldo Carvalho de Melo 	return err;
2213a2e27255SArnaldo Carvalho de Melo }
2214a2e27255SArnaldo Carvalho de Melo 
2215a2e27255SArnaldo Carvalho de Melo /*
2216a2e27255SArnaldo Carvalho de Melo  *	BSD recvmsg interface
2217a2e27255SArnaldo Carvalho de Melo  */
2218a2e27255SArnaldo Carvalho de Melo 
2219666547ffSAl Viro long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned flags)
2220a2e27255SArnaldo Carvalho de Melo {
2221a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err;
2222a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
22231be374a0SAndy Lutomirski 	struct socket *sock;
2224a2e27255SArnaldo Carvalho de Melo 
22251be374a0SAndy Lutomirski 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2226a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2227a2e27255SArnaldo Carvalho de Melo 		goto out;
2228a2e27255SArnaldo Carvalho de Melo 
2229a7526eb5SAndy Lutomirski 	err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0);
2230a2e27255SArnaldo Carvalho de Melo 
22316cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
22321da177e4SLinus Torvalds out:
22331da177e4SLinus Torvalds 	return err;
22341da177e4SLinus Torvalds }
22351da177e4SLinus Torvalds 
2236666547ffSAl Viro SYSCALL_DEFINE3(recvmsg, int, fd, struct user_msghdr __user *, msg,
2237a7526eb5SAndy Lutomirski 		unsigned int, flags)
2238a7526eb5SAndy Lutomirski {
2239a7526eb5SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
2240a7526eb5SAndy Lutomirski 		return -EINVAL;
2241a7526eb5SAndy Lutomirski 	return __sys_recvmsg(fd, msg, flags);
2242a7526eb5SAndy Lutomirski }
2243a7526eb5SAndy Lutomirski 
2244a2e27255SArnaldo Carvalho de Melo /*
2245a2e27255SArnaldo Carvalho de Melo  *     Linux recvmmsg interface
2246a2e27255SArnaldo Carvalho de Melo  */
22471da177e4SLinus Torvalds 
2248a2e27255SArnaldo Carvalho de Melo int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2249a2e27255SArnaldo Carvalho de Melo 		   unsigned int flags, struct timespec *timeout)
2250a2e27255SArnaldo Carvalho de Melo {
2251a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err, datagrams;
2252a2e27255SArnaldo Carvalho de Melo 	struct socket *sock;
2253a2e27255SArnaldo Carvalho de Melo 	struct mmsghdr __user *entry;
2254d7256d0eSJean-Mickael Guerin 	struct compat_mmsghdr __user *compat_entry;
2255a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
2256a2e27255SArnaldo Carvalho de Melo 	struct timespec end_time;
2257a2e27255SArnaldo Carvalho de Melo 
2258a2e27255SArnaldo Carvalho de Melo 	if (timeout &&
2259a2e27255SArnaldo Carvalho de Melo 	    poll_select_set_timeout(&end_time, timeout->tv_sec,
2260a2e27255SArnaldo Carvalho de Melo 				    timeout->tv_nsec))
2261a2e27255SArnaldo Carvalho de Melo 		return -EINVAL;
2262a2e27255SArnaldo Carvalho de Melo 
2263a2e27255SArnaldo Carvalho de Melo 	datagrams = 0;
2264a2e27255SArnaldo Carvalho de Melo 
2265a2e27255SArnaldo Carvalho de Melo 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2266a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2267a2e27255SArnaldo Carvalho de Melo 		return err;
2268a2e27255SArnaldo Carvalho de Melo 
2269a2e27255SArnaldo Carvalho de Melo 	err = sock_error(sock->sk);
2270a2e27255SArnaldo Carvalho de Melo 	if (err)
2271a2e27255SArnaldo Carvalho de Melo 		goto out_put;
2272a2e27255SArnaldo Carvalho de Melo 
2273a2e27255SArnaldo Carvalho de Melo 	entry = mmsg;
2274d7256d0eSJean-Mickael Guerin 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2275a2e27255SArnaldo Carvalho de Melo 
2276a2e27255SArnaldo Carvalho de Melo 	while (datagrams < vlen) {
2277a2e27255SArnaldo Carvalho de Melo 		/*
2278a2e27255SArnaldo Carvalho de Melo 		 * No need to ask LSM for more than the first datagram.
2279a2e27255SArnaldo Carvalho de Melo 		 */
2280d7256d0eSJean-Mickael Guerin 		if (MSG_CMSG_COMPAT & flags) {
2281666547ffSAl Viro 			err = ___sys_recvmsg(sock, (struct user_msghdr __user *)compat_entry,
2282b9eb8b87SAnton Blanchard 					     &msg_sys, flags & ~MSG_WAITFORONE,
2283b9eb8b87SAnton Blanchard 					     datagrams);
2284d7256d0eSJean-Mickael Guerin 			if (err < 0)
2285d7256d0eSJean-Mickael Guerin 				break;
2286d7256d0eSJean-Mickael Guerin 			err = __put_user(err, &compat_entry->msg_len);
2287d7256d0eSJean-Mickael Guerin 			++compat_entry;
2288d7256d0eSJean-Mickael Guerin 		} else {
2289a7526eb5SAndy Lutomirski 			err = ___sys_recvmsg(sock,
2290666547ffSAl Viro 					     (struct user_msghdr __user *)entry,
2291b9eb8b87SAnton Blanchard 					     &msg_sys, flags & ~MSG_WAITFORONE,
2292b9eb8b87SAnton Blanchard 					     datagrams);
2293a2e27255SArnaldo Carvalho de Melo 			if (err < 0)
2294a2e27255SArnaldo Carvalho de Melo 				break;
2295a2e27255SArnaldo Carvalho de Melo 			err = put_user(err, &entry->msg_len);
2296d7256d0eSJean-Mickael Guerin 			++entry;
2297d7256d0eSJean-Mickael Guerin 		}
2298d7256d0eSJean-Mickael Guerin 
2299a2e27255SArnaldo Carvalho de Melo 		if (err)
2300a2e27255SArnaldo Carvalho de Melo 			break;
2301a2e27255SArnaldo Carvalho de Melo 		++datagrams;
2302a2e27255SArnaldo Carvalho de Melo 
230371c5c159SBrandon L Black 		/* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
230471c5c159SBrandon L Black 		if (flags & MSG_WAITFORONE)
230571c5c159SBrandon L Black 			flags |= MSG_DONTWAIT;
230671c5c159SBrandon L Black 
2307a2e27255SArnaldo Carvalho de Melo 		if (timeout) {
2308a2e27255SArnaldo Carvalho de Melo 			ktime_get_ts(timeout);
2309a2e27255SArnaldo Carvalho de Melo 			*timeout = timespec_sub(end_time, *timeout);
2310a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_sec < 0) {
2311a2e27255SArnaldo Carvalho de Melo 				timeout->tv_sec = timeout->tv_nsec = 0;
2312a2e27255SArnaldo Carvalho de Melo 				break;
2313a2e27255SArnaldo Carvalho de Melo 			}
2314a2e27255SArnaldo Carvalho de Melo 
2315a2e27255SArnaldo Carvalho de Melo 			/* Timeout, return less than vlen datagrams */
2316a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_nsec == 0 && timeout->tv_sec == 0)
2317a2e27255SArnaldo Carvalho de Melo 				break;
2318a2e27255SArnaldo Carvalho de Melo 		}
2319a2e27255SArnaldo Carvalho de Melo 
2320a2e27255SArnaldo Carvalho de Melo 		/* Out of band data, return right away */
2321a2e27255SArnaldo Carvalho de Melo 		if (msg_sys.msg_flags & MSG_OOB)
2322a2e27255SArnaldo Carvalho de Melo 			break;
2323a2e27255SArnaldo Carvalho de Melo 	}
2324a2e27255SArnaldo Carvalho de Melo 
2325a2e27255SArnaldo Carvalho de Melo out_put:
2326a2e27255SArnaldo Carvalho de Melo 	fput_light(sock->file, fput_needed);
2327a2e27255SArnaldo Carvalho de Melo 
2328a2e27255SArnaldo Carvalho de Melo 	if (err == 0)
2329a2e27255SArnaldo Carvalho de Melo 		return datagrams;
2330a2e27255SArnaldo Carvalho de Melo 
2331a2e27255SArnaldo Carvalho de Melo 	if (datagrams != 0) {
2332a2e27255SArnaldo Carvalho de Melo 		/*
2333a2e27255SArnaldo Carvalho de Melo 		 * We may return less entries than requested (vlen) if the
2334a2e27255SArnaldo Carvalho de Melo 		 * sock is non block and there aren't enough datagrams...
2335a2e27255SArnaldo Carvalho de Melo 		 */
2336a2e27255SArnaldo Carvalho de Melo 		if (err != -EAGAIN) {
2337a2e27255SArnaldo Carvalho de Melo 			/*
2338a2e27255SArnaldo Carvalho de Melo 			 * ... or  if recvmsg returns an error after we
2339a2e27255SArnaldo Carvalho de Melo 			 * received some datagrams, where we record the
2340a2e27255SArnaldo Carvalho de Melo 			 * error to return on the next call or if the
2341a2e27255SArnaldo Carvalho de Melo 			 * app asks about it using getsockopt(SO_ERROR).
2342a2e27255SArnaldo Carvalho de Melo 			 */
2343a2e27255SArnaldo Carvalho de Melo 			sock->sk->sk_err = -err;
2344a2e27255SArnaldo Carvalho de Melo 		}
2345a2e27255SArnaldo Carvalho de Melo 
2346a2e27255SArnaldo Carvalho de Melo 		return datagrams;
2347a2e27255SArnaldo Carvalho de Melo 	}
2348a2e27255SArnaldo Carvalho de Melo 
2349a2e27255SArnaldo Carvalho de Melo 	return err;
2350a2e27255SArnaldo Carvalho de Melo }
2351a2e27255SArnaldo Carvalho de Melo 
2352a2e27255SArnaldo Carvalho de Melo SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
2353a2e27255SArnaldo Carvalho de Melo 		unsigned int, vlen, unsigned int, flags,
2354a2e27255SArnaldo Carvalho de Melo 		struct timespec __user *, timeout)
2355a2e27255SArnaldo Carvalho de Melo {
2356a2e27255SArnaldo Carvalho de Melo 	int datagrams;
2357a2e27255SArnaldo Carvalho de Melo 	struct timespec timeout_sys;
2358a2e27255SArnaldo Carvalho de Melo 
23591be374a0SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
23601be374a0SAndy Lutomirski 		return -EINVAL;
23611be374a0SAndy Lutomirski 
2362a2e27255SArnaldo Carvalho de Melo 	if (!timeout)
2363a2e27255SArnaldo Carvalho de Melo 		return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL);
2364a2e27255SArnaldo Carvalho de Melo 
2365a2e27255SArnaldo Carvalho de Melo 	if (copy_from_user(&timeout_sys, timeout, sizeof(timeout_sys)))
2366a2e27255SArnaldo Carvalho de Melo 		return -EFAULT;
2367a2e27255SArnaldo Carvalho de Melo 
2368a2e27255SArnaldo Carvalho de Melo 	datagrams = __sys_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys);
2369a2e27255SArnaldo Carvalho de Melo 
2370a2e27255SArnaldo Carvalho de Melo 	if (datagrams > 0 &&
2371a2e27255SArnaldo Carvalho de Melo 	    copy_to_user(timeout, &timeout_sys, sizeof(timeout_sys)))
2372a2e27255SArnaldo Carvalho de Melo 		datagrams = -EFAULT;
2373a2e27255SArnaldo Carvalho de Melo 
2374a2e27255SArnaldo Carvalho de Melo 	return datagrams;
2375a2e27255SArnaldo Carvalho de Melo }
2376a2e27255SArnaldo Carvalho de Melo 
2377a2e27255SArnaldo Carvalho de Melo #ifdef __ARCH_WANT_SYS_SOCKETCALL
23781da177e4SLinus Torvalds /* Argument list sizes for sys_socketcall */
23791da177e4SLinus Torvalds #define AL(x) ((x) * sizeof(unsigned long))
2380228e548eSAnton Blanchard static const unsigned char nargs[21] = {
238189bddce5SStephen Hemminger 	AL(0), AL(3), AL(3), AL(3), AL(2), AL(3),
23821da177e4SLinus Torvalds 	AL(3), AL(3), AL(4), AL(4), AL(4), AL(6),
2383aaca0bdcSUlrich Drepper 	AL(6), AL(2), AL(5), AL(5), AL(3), AL(3),
2384228e548eSAnton Blanchard 	AL(4), AL(5), AL(4)
238589bddce5SStephen Hemminger };
238689bddce5SStephen Hemminger 
23871da177e4SLinus Torvalds #undef AL
23881da177e4SLinus Torvalds 
23891da177e4SLinus Torvalds /*
23901da177e4SLinus Torvalds  *	System call vectors.
23911da177e4SLinus Torvalds  *
23921da177e4SLinus Torvalds  *	Argument checking cleaned up. Saved 20% in size.
23931da177e4SLinus Torvalds  *  This function doesn't need to set the kernel lock because
23941da177e4SLinus Torvalds  *  it is set by the callees.
23951da177e4SLinus Torvalds  */
23961da177e4SLinus Torvalds 
23973e0fa65fSHeiko Carstens SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
23981da177e4SLinus Torvalds {
23992950fa9dSChen Gang 	unsigned long a[AUDITSC_ARGS];
24001da177e4SLinus Torvalds 	unsigned long a0, a1;
24011da177e4SLinus Torvalds 	int err;
240247379052SArjan van de Ven 	unsigned int len;
24031da177e4SLinus Torvalds 
2404228e548eSAnton Blanchard 	if (call < 1 || call > SYS_SENDMMSG)
24051da177e4SLinus Torvalds 		return -EINVAL;
24061da177e4SLinus Torvalds 
240747379052SArjan van de Ven 	len = nargs[call];
240847379052SArjan van de Ven 	if (len > sizeof(a))
240947379052SArjan van de Ven 		return -EINVAL;
241047379052SArjan van de Ven 
24111da177e4SLinus Torvalds 	/* copy_from_user should be SMP safe. */
241247379052SArjan van de Ven 	if (copy_from_user(a, args, len))
24131da177e4SLinus Torvalds 		return -EFAULT;
24141da177e4SLinus Torvalds 
24152950fa9dSChen Gang 	err = audit_socketcall(nargs[call] / sizeof(unsigned long), a);
24162950fa9dSChen Gang 	if (err)
24172950fa9dSChen Gang 		return err;
24183ec3b2fbSDavid Woodhouse 
24191da177e4SLinus Torvalds 	a0 = a[0];
24201da177e4SLinus Torvalds 	a1 = a[1];
24211da177e4SLinus Torvalds 
242289bddce5SStephen Hemminger 	switch (call) {
24231da177e4SLinus Torvalds 	case SYS_SOCKET:
24241da177e4SLinus Torvalds 		err = sys_socket(a0, a1, a[2]);
24251da177e4SLinus Torvalds 		break;
24261da177e4SLinus Torvalds 	case SYS_BIND:
24271da177e4SLinus Torvalds 		err = sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
24281da177e4SLinus Torvalds 		break;
24291da177e4SLinus Torvalds 	case SYS_CONNECT:
24301da177e4SLinus Torvalds 		err = sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
24311da177e4SLinus Torvalds 		break;
24321da177e4SLinus Torvalds 	case SYS_LISTEN:
24331da177e4SLinus Torvalds 		err = sys_listen(a0, a1);
24341da177e4SLinus Torvalds 		break;
24351da177e4SLinus Torvalds 	case SYS_ACCEPT:
2436de11defeSUlrich Drepper 		err = sys_accept4(a0, (struct sockaddr __user *)a1,
2437aaca0bdcSUlrich Drepper 				  (int __user *)a[2], 0);
24381da177e4SLinus Torvalds 		break;
24391da177e4SLinus Torvalds 	case SYS_GETSOCKNAME:
244089bddce5SStephen Hemminger 		err =
244189bddce5SStephen Hemminger 		    sys_getsockname(a0, (struct sockaddr __user *)a1,
244289bddce5SStephen Hemminger 				    (int __user *)a[2]);
24431da177e4SLinus Torvalds 		break;
24441da177e4SLinus Torvalds 	case SYS_GETPEERNAME:
244589bddce5SStephen Hemminger 		err =
244689bddce5SStephen Hemminger 		    sys_getpeername(a0, (struct sockaddr __user *)a1,
244789bddce5SStephen Hemminger 				    (int __user *)a[2]);
24481da177e4SLinus Torvalds 		break;
24491da177e4SLinus Torvalds 	case SYS_SOCKETPAIR:
24501da177e4SLinus Torvalds 		err = sys_socketpair(a0, a1, a[2], (int __user *)a[3]);
24511da177e4SLinus Torvalds 		break;
24521da177e4SLinus Torvalds 	case SYS_SEND:
24531da177e4SLinus Torvalds 		err = sys_send(a0, (void __user *)a1, a[2], a[3]);
24541da177e4SLinus Torvalds 		break;
24551da177e4SLinus Torvalds 	case SYS_SENDTO:
24561da177e4SLinus Torvalds 		err = sys_sendto(a0, (void __user *)a1, a[2], a[3],
24571da177e4SLinus Torvalds 				 (struct sockaddr __user *)a[4], a[5]);
24581da177e4SLinus Torvalds 		break;
24591da177e4SLinus Torvalds 	case SYS_RECV:
24601da177e4SLinus Torvalds 		err = sys_recv(a0, (void __user *)a1, a[2], a[3]);
24611da177e4SLinus Torvalds 		break;
24621da177e4SLinus Torvalds 	case SYS_RECVFROM:
24631da177e4SLinus Torvalds 		err = sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
246489bddce5SStephen Hemminger 				   (struct sockaddr __user *)a[4],
246589bddce5SStephen Hemminger 				   (int __user *)a[5]);
24661da177e4SLinus Torvalds 		break;
24671da177e4SLinus Torvalds 	case SYS_SHUTDOWN:
24681da177e4SLinus Torvalds 		err = sys_shutdown(a0, a1);
24691da177e4SLinus Torvalds 		break;
24701da177e4SLinus Torvalds 	case SYS_SETSOCKOPT:
24711da177e4SLinus Torvalds 		err = sys_setsockopt(a0, a1, a[2], (char __user *)a[3], a[4]);
24721da177e4SLinus Torvalds 		break;
24731da177e4SLinus Torvalds 	case SYS_GETSOCKOPT:
247489bddce5SStephen Hemminger 		err =
247589bddce5SStephen Hemminger 		    sys_getsockopt(a0, a1, a[2], (char __user *)a[3],
247689bddce5SStephen Hemminger 				   (int __user *)a[4]);
24771da177e4SLinus Torvalds 		break;
24781da177e4SLinus Torvalds 	case SYS_SENDMSG:
2479666547ffSAl Viro 		err = sys_sendmsg(a0, (struct user_msghdr __user *)a1, a[2]);
24801da177e4SLinus Torvalds 		break;
2481228e548eSAnton Blanchard 	case SYS_SENDMMSG:
2482228e548eSAnton Blanchard 		err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]);
2483228e548eSAnton Blanchard 		break;
24841da177e4SLinus Torvalds 	case SYS_RECVMSG:
2485666547ffSAl Viro 		err = sys_recvmsg(a0, (struct user_msghdr __user *)a1, a[2]);
24861da177e4SLinus Torvalds 		break;
2487a2e27255SArnaldo Carvalho de Melo 	case SYS_RECVMMSG:
2488a2e27255SArnaldo Carvalho de Melo 		err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3],
2489a2e27255SArnaldo Carvalho de Melo 				   (struct timespec __user *)a[4]);
2490a2e27255SArnaldo Carvalho de Melo 		break;
2491de11defeSUlrich Drepper 	case SYS_ACCEPT4:
2492de11defeSUlrich Drepper 		err = sys_accept4(a0, (struct sockaddr __user *)a1,
2493de11defeSUlrich Drepper 				  (int __user *)a[2], a[3]);
2494aaca0bdcSUlrich Drepper 		break;
24951da177e4SLinus Torvalds 	default:
24961da177e4SLinus Torvalds 		err = -EINVAL;
24971da177e4SLinus Torvalds 		break;
24981da177e4SLinus Torvalds 	}
24991da177e4SLinus Torvalds 	return err;
25001da177e4SLinus Torvalds }
25011da177e4SLinus Torvalds 
25021da177e4SLinus Torvalds #endif				/* __ARCH_WANT_SYS_SOCKETCALL */
25031da177e4SLinus Torvalds 
250455737fdaSStephen Hemminger /**
250555737fdaSStephen Hemminger  *	sock_register - add a socket protocol handler
250655737fdaSStephen Hemminger  *	@ops: description of protocol
250755737fdaSStephen Hemminger  *
25081da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
25091da177e4SLinus Torvalds  *	advertise its address family, and have it linked into the
2510e793c0f7SMasanari Iida  *	socket interface. The value ops->family corresponds to the
251155737fdaSStephen Hemminger  *	socket system call protocol family.
25121da177e4SLinus Torvalds  */
2513f0fd27d4SStephen Hemminger int sock_register(const struct net_proto_family *ops)
25141da177e4SLinus Torvalds {
25151da177e4SLinus Torvalds 	int err;
25161da177e4SLinus Torvalds 
25171da177e4SLinus Torvalds 	if (ops->family >= NPROTO) {
25183410f22eSYang Yingliang 		pr_crit("protocol %d >= NPROTO(%d)\n", ops->family, NPROTO);
25191da177e4SLinus Torvalds 		return -ENOBUFS;
25201da177e4SLinus Torvalds 	}
252155737fdaSStephen Hemminger 
252255737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2523190683a9SEric Dumazet 	if (rcu_dereference_protected(net_families[ops->family],
2524190683a9SEric Dumazet 				      lockdep_is_held(&net_family_lock)))
25251da177e4SLinus Torvalds 		err = -EEXIST;
252655737fdaSStephen Hemminger 	else {
2527cf778b00SEric Dumazet 		rcu_assign_pointer(net_families[ops->family], ops);
25281da177e4SLinus Torvalds 		err = 0;
25291da177e4SLinus Torvalds 	}
253055737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
253155737fdaSStephen Hemminger 
25323410f22eSYang Yingliang 	pr_info("NET: Registered protocol family %d\n", ops->family);
25331da177e4SLinus Torvalds 	return err;
25341da177e4SLinus Torvalds }
2535c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_register);
25361da177e4SLinus Torvalds 
253755737fdaSStephen Hemminger /**
253855737fdaSStephen Hemminger  *	sock_unregister - remove a protocol handler
253955737fdaSStephen Hemminger  *	@family: protocol family to remove
254055737fdaSStephen Hemminger  *
25411da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
25421da177e4SLinus Torvalds  *	remove its address family, and have it unlinked from the
254355737fdaSStephen Hemminger  *	new socket creation.
254455737fdaSStephen Hemminger  *
254555737fdaSStephen Hemminger  *	If protocol handler is a module, then it can use module reference
254655737fdaSStephen Hemminger  *	counts to protect against new references. If protocol handler is not
254755737fdaSStephen Hemminger  *	a module then it needs to provide its own protection in
254855737fdaSStephen Hemminger  *	the ops->create routine.
25491da177e4SLinus Torvalds  */
2550f0fd27d4SStephen Hemminger void sock_unregister(int family)
25511da177e4SLinus Torvalds {
2552f0fd27d4SStephen Hemminger 	BUG_ON(family < 0 || family >= NPROTO);
25531da177e4SLinus Torvalds 
255455737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2555a9b3cd7fSStephen Hemminger 	RCU_INIT_POINTER(net_families[family], NULL);
255655737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
255755737fdaSStephen Hemminger 
255855737fdaSStephen Hemminger 	synchronize_rcu();
255955737fdaSStephen Hemminger 
25603410f22eSYang Yingliang 	pr_info("NET: Unregistered protocol family %d\n", family);
25611da177e4SLinus Torvalds }
2562c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_unregister);
25631da177e4SLinus Torvalds 
256477d76ea3SAndi Kleen static int __init sock_init(void)
25651da177e4SLinus Torvalds {
2566b3e19d92SNick Piggin 	int err;
25672ca794e5SEric W. Biederman 	/*
25682ca794e5SEric W. Biederman 	 *      Initialize the network sysctl infrastructure.
25692ca794e5SEric W. Biederman 	 */
25702ca794e5SEric W. Biederman 	err = net_sysctl_init();
25712ca794e5SEric W. Biederman 	if (err)
25722ca794e5SEric W. Biederman 		goto out;
2573b3e19d92SNick Piggin 
25741da177e4SLinus Torvalds 	/*
25751da177e4SLinus Torvalds 	 *      Initialize skbuff SLAB cache
25761da177e4SLinus Torvalds 	 */
25771da177e4SLinus Torvalds 	skb_init();
25781da177e4SLinus Torvalds 
25791da177e4SLinus Torvalds 	/*
25801da177e4SLinus Torvalds 	 *      Initialize the protocols module.
25811da177e4SLinus Torvalds 	 */
25821da177e4SLinus Torvalds 
25831da177e4SLinus Torvalds 	init_inodecache();
2584b3e19d92SNick Piggin 
2585b3e19d92SNick Piggin 	err = register_filesystem(&sock_fs_type);
2586b3e19d92SNick Piggin 	if (err)
2587b3e19d92SNick Piggin 		goto out_fs;
25881da177e4SLinus Torvalds 	sock_mnt = kern_mount(&sock_fs_type);
2589b3e19d92SNick Piggin 	if (IS_ERR(sock_mnt)) {
2590b3e19d92SNick Piggin 		err = PTR_ERR(sock_mnt);
2591b3e19d92SNick Piggin 		goto out_mount;
2592b3e19d92SNick Piggin 	}
259377d76ea3SAndi Kleen 
259477d76ea3SAndi Kleen 	/* The real protocol initialization is performed in later initcalls.
25951da177e4SLinus Torvalds 	 */
25961da177e4SLinus Torvalds 
25971da177e4SLinus Torvalds #ifdef CONFIG_NETFILTER
25986d11cfdbSPablo Neira Ayuso 	err = netfilter_init();
25996d11cfdbSPablo Neira Ayuso 	if (err)
26006d11cfdbSPablo Neira Ayuso 		goto out;
26011da177e4SLinus Torvalds #endif
2602cbeb321aSDavid S. Miller 
2603408eccceSDaniel Borkmann 	ptp_classifier_init();
2604c1f19b51SRichard Cochran 
2605b3e19d92SNick Piggin out:
2606b3e19d92SNick Piggin 	return err;
2607b3e19d92SNick Piggin 
2608b3e19d92SNick Piggin out_mount:
2609b3e19d92SNick Piggin 	unregister_filesystem(&sock_fs_type);
2610b3e19d92SNick Piggin out_fs:
2611b3e19d92SNick Piggin 	goto out;
26121da177e4SLinus Torvalds }
26131da177e4SLinus Torvalds 
261477d76ea3SAndi Kleen core_initcall(sock_init);	/* early initcall */
261577d76ea3SAndi Kleen 
26161da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS
26171da177e4SLinus Torvalds void socket_seq_show(struct seq_file *seq)
26181da177e4SLinus Torvalds {
26191da177e4SLinus Torvalds 	int cpu;
26201da177e4SLinus Torvalds 	int counter = 0;
26211da177e4SLinus Torvalds 
26226f912042SKAMEZAWA Hiroyuki 	for_each_possible_cpu(cpu)
26231da177e4SLinus Torvalds 	    counter += per_cpu(sockets_in_use, cpu);
26241da177e4SLinus Torvalds 
26251da177e4SLinus Torvalds 	/* It can be negative, by the way. 8) */
26261da177e4SLinus Torvalds 	if (counter < 0)
26271da177e4SLinus Torvalds 		counter = 0;
26281da177e4SLinus Torvalds 
26291da177e4SLinus Torvalds 	seq_printf(seq, "sockets: used %d\n", counter);
26301da177e4SLinus Torvalds }
26311da177e4SLinus Torvalds #endif				/* CONFIG_PROC_FS */
26321da177e4SLinus Torvalds 
263389bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
26346b96018bSArnd Bergmann static int do_siocgstamp(struct net *net, struct socket *sock,
2635644595f8SH. Peter Anvin 			 unsigned int cmd, void __user *up)
26367a229387SArnd Bergmann {
26377a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
26387a229387SArnd Bergmann 	struct timeval ktv;
26397a229387SArnd Bergmann 	int err;
26407a229387SArnd Bergmann 
26417a229387SArnd Bergmann 	set_fs(KERNEL_DS);
26426b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv);
26437a229387SArnd Bergmann 	set_fs(old_fs);
2644644595f8SH. Peter Anvin 	if (!err)
2645ed6fe9d6SMikulas Patocka 		err = compat_put_timeval(&ktv, up);
2646644595f8SH. Peter Anvin 
26477a229387SArnd Bergmann 	return err;
26487a229387SArnd Bergmann }
26497a229387SArnd Bergmann 
26506b96018bSArnd Bergmann static int do_siocgstampns(struct net *net, struct socket *sock,
2651644595f8SH. Peter Anvin 			   unsigned int cmd, void __user *up)
26527a229387SArnd Bergmann {
26537a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
26547a229387SArnd Bergmann 	struct timespec kts;
26557a229387SArnd Bergmann 	int err;
26567a229387SArnd Bergmann 
26577a229387SArnd Bergmann 	set_fs(KERNEL_DS);
26586b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts);
26597a229387SArnd Bergmann 	set_fs(old_fs);
2660644595f8SH. Peter Anvin 	if (!err)
2661ed6fe9d6SMikulas Patocka 		err = compat_put_timespec(&kts, up);
2662644595f8SH. Peter Anvin 
26637a229387SArnd Bergmann 	return err;
26647a229387SArnd Bergmann }
26657a229387SArnd Bergmann 
26666b96018bSArnd Bergmann static int dev_ifname32(struct net *net, struct compat_ifreq __user *uifr32)
26677a229387SArnd Bergmann {
26687a229387SArnd Bergmann 	struct ifreq __user *uifr;
26697a229387SArnd Bergmann 	int err;
26707a229387SArnd Bergmann 
26717a229387SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(struct ifreq));
26726b96018bSArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
26737a229387SArnd Bergmann 		return -EFAULT;
26747a229387SArnd Bergmann 
26756b96018bSArnd Bergmann 	err = dev_ioctl(net, SIOCGIFNAME, uifr);
26767a229387SArnd Bergmann 	if (err)
26777a229387SArnd Bergmann 		return err;
26787a229387SArnd Bergmann 
26796b96018bSArnd Bergmann 	if (copy_in_user(uifr32, uifr, sizeof(struct compat_ifreq)))
26807a229387SArnd Bergmann 		return -EFAULT;
26817a229387SArnd Bergmann 
26827a229387SArnd Bergmann 	return 0;
26837a229387SArnd Bergmann }
26847a229387SArnd Bergmann 
26856b96018bSArnd Bergmann static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32)
26867a229387SArnd Bergmann {
26876b96018bSArnd Bergmann 	struct compat_ifconf ifc32;
26887a229387SArnd Bergmann 	struct ifconf ifc;
26897a229387SArnd Bergmann 	struct ifconf __user *uifc;
26906b96018bSArnd Bergmann 	struct compat_ifreq __user *ifr32;
26917a229387SArnd Bergmann 	struct ifreq __user *ifr;
26927a229387SArnd Bergmann 	unsigned int i, j;
26937a229387SArnd Bergmann 	int err;
26947a229387SArnd Bergmann 
26956b96018bSArnd Bergmann 	if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf)))
26967a229387SArnd Bergmann 		return -EFAULT;
26977a229387SArnd Bergmann 
269843da5f2eSMathias Krause 	memset(&ifc, 0, sizeof(ifc));
26997a229387SArnd Bergmann 	if (ifc32.ifcbuf == 0) {
27007a229387SArnd Bergmann 		ifc32.ifc_len = 0;
27017a229387SArnd Bergmann 		ifc.ifc_len = 0;
27027a229387SArnd Bergmann 		ifc.ifc_req = NULL;
27037a229387SArnd Bergmann 		uifc = compat_alloc_user_space(sizeof(struct ifconf));
27047a229387SArnd Bergmann 	} else {
27056b96018bSArnd Bergmann 		size_t len = ((ifc32.ifc_len / sizeof(struct compat_ifreq)) + 1) *
27067a229387SArnd Bergmann 			sizeof(struct ifreq);
27077a229387SArnd Bergmann 		uifc = compat_alloc_user_space(sizeof(struct ifconf) + len);
27087a229387SArnd Bergmann 		ifc.ifc_len = len;
27097a229387SArnd Bergmann 		ifr = ifc.ifc_req = (void __user *)(uifc + 1);
27107a229387SArnd Bergmann 		ifr32 = compat_ptr(ifc32.ifcbuf);
27116b96018bSArnd Bergmann 		for (i = 0; i < ifc32.ifc_len; i += sizeof(struct compat_ifreq)) {
27126b96018bSArnd Bergmann 			if (copy_in_user(ifr, ifr32, sizeof(struct compat_ifreq)))
27137a229387SArnd Bergmann 				return -EFAULT;
27147a229387SArnd Bergmann 			ifr++;
27157a229387SArnd Bergmann 			ifr32++;
27167a229387SArnd Bergmann 		}
27177a229387SArnd Bergmann 	}
27187a229387SArnd Bergmann 	if (copy_to_user(uifc, &ifc, sizeof(struct ifconf)))
27197a229387SArnd Bergmann 		return -EFAULT;
27207a229387SArnd Bergmann 
27216b96018bSArnd Bergmann 	err = dev_ioctl(net, SIOCGIFCONF, uifc);
27227a229387SArnd Bergmann 	if (err)
27237a229387SArnd Bergmann 		return err;
27247a229387SArnd Bergmann 
27257a229387SArnd Bergmann 	if (copy_from_user(&ifc, uifc, sizeof(struct ifconf)))
27267a229387SArnd Bergmann 		return -EFAULT;
27277a229387SArnd Bergmann 
27287a229387SArnd Bergmann 	ifr = ifc.ifc_req;
27297a229387SArnd Bergmann 	ifr32 = compat_ptr(ifc32.ifcbuf);
27307a229387SArnd Bergmann 	for (i = 0, j = 0;
27316b96018bSArnd Bergmann 	     i + sizeof(struct compat_ifreq) <= ifc32.ifc_len && j < ifc.ifc_len;
27326b96018bSArnd Bergmann 	     i += sizeof(struct compat_ifreq), j += sizeof(struct ifreq)) {
27336b96018bSArnd Bergmann 		if (copy_in_user(ifr32, ifr, sizeof(struct compat_ifreq)))
27347a229387SArnd Bergmann 			return -EFAULT;
27357a229387SArnd Bergmann 		ifr32++;
27367a229387SArnd Bergmann 		ifr++;
27377a229387SArnd Bergmann 	}
27387a229387SArnd Bergmann 
27397a229387SArnd Bergmann 	if (ifc32.ifcbuf == 0) {
27407a229387SArnd Bergmann 		/* Translate from 64-bit structure multiple to
27417a229387SArnd Bergmann 		 * a 32-bit one.
27427a229387SArnd Bergmann 		 */
27437a229387SArnd Bergmann 		i = ifc.ifc_len;
27446b96018bSArnd Bergmann 		i = ((i / sizeof(struct ifreq)) * sizeof(struct compat_ifreq));
27457a229387SArnd Bergmann 		ifc32.ifc_len = i;
27467a229387SArnd Bergmann 	} else {
27477a229387SArnd Bergmann 		ifc32.ifc_len = i;
27487a229387SArnd Bergmann 	}
27496b96018bSArnd Bergmann 	if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf)))
27507a229387SArnd Bergmann 		return -EFAULT;
27517a229387SArnd Bergmann 
27527a229387SArnd Bergmann 	return 0;
27537a229387SArnd Bergmann }
27547a229387SArnd Bergmann 
27556b96018bSArnd Bergmann static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
27567a229387SArnd Bergmann {
27573a7da39dSBen Hutchings 	struct compat_ethtool_rxnfc __user *compat_rxnfc;
27583a7da39dSBen Hutchings 	bool convert_in = false, convert_out = false;
27593a7da39dSBen Hutchings 	size_t buf_size = ALIGN(sizeof(struct ifreq), 8);
27603a7da39dSBen Hutchings 	struct ethtool_rxnfc __user *rxnfc;
27617a229387SArnd Bergmann 	struct ifreq __user *ifr;
27623a7da39dSBen Hutchings 	u32 rule_cnt = 0, actual_rule_cnt;
27633a7da39dSBen Hutchings 	u32 ethcmd;
27647a229387SArnd Bergmann 	u32 data;
27653a7da39dSBen Hutchings 	int ret;
27667a229387SArnd Bergmann 
27677a229387SArnd Bergmann 	if (get_user(data, &ifr32->ifr_ifru.ifru_data))
27687a229387SArnd Bergmann 		return -EFAULT;
27697a229387SArnd Bergmann 
27703a7da39dSBen Hutchings 	compat_rxnfc = compat_ptr(data);
27713a7da39dSBen Hutchings 
27723a7da39dSBen Hutchings 	if (get_user(ethcmd, &compat_rxnfc->cmd))
27737a229387SArnd Bergmann 		return -EFAULT;
27747a229387SArnd Bergmann 
27753a7da39dSBen Hutchings 	/* Most ethtool structures are defined without padding.
27763a7da39dSBen Hutchings 	 * Unfortunately struct ethtool_rxnfc is an exception.
27773a7da39dSBen Hutchings 	 */
27783a7da39dSBen Hutchings 	switch (ethcmd) {
27793a7da39dSBen Hutchings 	default:
27803a7da39dSBen Hutchings 		break;
27813a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLALL:
27823a7da39dSBen Hutchings 		/* Buffer size is variable */
27833a7da39dSBen Hutchings 		if (get_user(rule_cnt, &compat_rxnfc->rule_cnt))
27843a7da39dSBen Hutchings 			return -EFAULT;
27853a7da39dSBen Hutchings 		if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32))
27863a7da39dSBen Hutchings 			return -ENOMEM;
27873a7da39dSBen Hutchings 		buf_size += rule_cnt * sizeof(u32);
27883a7da39dSBen Hutchings 		/* fall through */
27893a7da39dSBen Hutchings 	case ETHTOOL_GRXRINGS:
27903a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLCNT:
27913a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRULE:
279255664f32SBen Hutchings 	case ETHTOOL_SRXCLSRLINS:
27933a7da39dSBen Hutchings 		convert_out = true;
27943a7da39dSBen Hutchings 		/* fall through */
27953a7da39dSBen Hutchings 	case ETHTOOL_SRXCLSRLDEL:
27963a7da39dSBen Hutchings 		buf_size += sizeof(struct ethtool_rxnfc);
27973a7da39dSBen Hutchings 		convert_in = true;
27983a7da39dSBen Hutchings 		break;
27993a7da39dSBen Hutchings 	}
28003a7da39dSBen Hutchings 
28013a7da39dSBen Hutchings 	ifr = compat_alloc_user_space(buf_size);
2802954b1244SStephen Hemminger 	rxnfc = (void __user *)ifr + ALIGN(sizeof(struct ifreq), 8);
28033a7da39dSBen Hutchings 
28043a7da39dSBen Hutchings 	if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
28053a7da39dSBen Hutchings 		return -EFAULT;
28063a7da39dSBen Hutchings 
28073a7da39dSBen Hutchings 	if (put_user(convert_in ? rxnfc : compat_ptr(data),
28083a7da39dSBen Hutchings 		     &ifr->ifr_ifru.ifru_data))
28093a7da39dSBen Hutchings 		return -EFAULT;
28103a7da39dSBen Hutchings 
28113a7da39dSBen Hutchings 	if (convert_in) {
2812127fe533SAlexander Duyck 		/* We expect there to be holes between fs.m_ext and
28133a7da39dSBen Hutchings 		 * fs.ring_cookie and at the end of fs, but nowhere else.
28143a7da39dSBen Hutchings 		 */
2815127fe533SAlexander Duyck 		BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_ext) +
2816127fe533SAlexander Duyck 			     sizeof(compat_rxnfc->fs.m_ext) !=
2817127fe533SAlexander Duyck 			     offsetof(struct ethtool_rxnfc, fs.m_ext) +
2818127fe533SAlexander Duyck 			     sizeof(rxnfc->fs.m_ext));
28193a7da39dSBen Hutchings 		BUILD_BUG_ON(
28203a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.location) -
28213a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) !=
28223a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.location) -
28233a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.ring_cookie));
28243a7da39dSBen Hutchings 
28253a7da39dSBen Hutchings 		if (copy_in_user(rxnfc, compat_rxnfc,
2826954b1244SStephen Hemminger 				 (void __user *)(&rxnfc->fs.m_ext + 1) -
2827954b1244SStephen Hemminger 				 (void __user *)rxnfc) ||
28283a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->fs.ring_cookie,
28293a7da39dSBen Hutchings 				 &compat_rxnfc->fs.ring_cookie,
2830954b1244SStephen Hemminger 				 (void __user *)(&rxnfc->fs.location + 1) -
2831954b1244SStephen Hemminger 				 (void __user *)&rxnfc->fs.ring_cookie) ||
28323a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt,
28333a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
28343a7da39dSBen Hutchings 			return -EFAULT;
28353a7da39dSBen Hutchings 	}
28363a7da39dSBen Hutchings 
28373a7da39dSBen Hutchings 	ret = dev_ioctl(net, SIOCETHTOOL, ifr);
28383a7da39dSBen Hutchings 	if (ret)
28393a7da39dSBen Hutchings 		return ret;
28403a7da39dSBen Hutchings 
28413a7da39dSBen Hutchings 	if (convert_out) {
28423a7da39dSBen Hutchings 		if (copy_in_user(compat_rxnfc, rxnfc,
2843954b1244SStephen Hemminger 				 (const void __user *)(&rxnfc->fs.m_ext + 1) -
2844954b1244SStephen Hemminger 				 (const void __user *)rxnfc) ||
28453a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->fs.ring_cookie,
28463a7da39dSBen Hutchings 				 &rxnfc->fs.ring_cookie,
2847954b1244SStephen Hemminger 				 (const void __user *)(&rxnfc->fs.location + 1) -
2848954b1244SStephen Hemminger 				 (const void __user *)&rxnfc->fs.ring_cookie) ||
28493a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt,
28503a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
28513a7da39dSBen Hutchings 			return -EFAULT;
28523a7da39dSBen Hutchings 
28533a7da39dSBen Hutchings 		if (ethcmd == ETHTOOL_GRXCLSRLALL) {
28543a7da39dSBen Hutchings 			/* As an optimisation, we only copy the actual
28553a7da39dSBen Hutchings 			 * number of rules that the underlying
28563a7da39dSBen Hutchings 			 * function returned.  Since Mallory might
28573a7da39dSBen Hutchings 			 * change the rule count in user memory, we
28583a7da39dSBen Hutchings 			 * check that it is less than the rule count
28593a7da39dSBen Hutchings 			 * originally given (as the user buffer size),
28603a7da39dSBen Hutchings 			 * which has been range-checked.
28613a7da39dSBen Hutchings 			 */
28623a7da39dSBen Hutchings 			if (get_user(actual_rule_cnt, &rxnfc->rule_cnt))
28633a7da39dSBen Hutchings 				return -EFAULT;
28643a7da39dSBen Hutchings 			if (actual_rule_cnt < rule_cnt)
28653a7da39dSBen Hutchings 				rule_cnt = actual_rule_cnt;
28663a7da39dSBen Hutchings 			if (copy_in_user(&compat_rxnfc->rule_locs[0],
28673a7da39dSBen Hutchings 					 &rxnfc->rule_locs[0],
28683a7da39dSBen Hutchings 					 rule_cnt * sizeof(u32)))
28693a7da39dSBen Hutchings 				return -EFAULT;
28703a7da39dSBen Hutchings 		}
28713a7da39dSBen Hutchings 	}
28723a7da39dSBen Hutchings 
28733a7da39dSBen Hutchings 	return 0;
28747a229387SArnd Bergmann }
28757a229387SArnd Bergmann 
28767a50a240SArnd Bergmann static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32)
28777a50a240SArnd Bergmann {
28787a50a240SArnd Bergmann 	void __user *uptr;
28797a50a240SArnd Bergmann 	compat_uptr_t uptr32;
28807a50a240SArnd Bergmann 	struct ifreq __user *uifr;
28817a50a240SArnd Bergmann 
28827a50a240SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
28837a50a240SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
28847a50a240SArnd Bergmann 		return -EFAULT;
28857a50a240SArnd Bergmann 
28867a50a240SArnd Bergmann 	if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu))
28877a50a240SArnd Bergmann 		return -EFAULT;
28887a50a240SArnd Bergmann 
28897a50a240SArnd Bergmann 	uptr = compat_ptr(uptr32);
28907a50a240SArnd Bergmann 
28917a50a240SArnd Bergmann 	if (put_user(uptr, &uifr->ifr_settings.ifs_ifsu.raw_hdlc))
28927a50a240SArnd Bergmann 		return -EFAULT;
28937a50a240SArnd Bergmann 
28947a50a240SArnd Bergmann 	return dev_ioctl(net, SIOCWANDEV, uifr);
28957a50a240SArnd Bergmann }
28967a50a240SArnd Bergmann 
28976b96018bSArnd Bergmann static int bond_ioctl(struct net *net, unsigned int cmd,
28986b96018bSArnd Bergmann 			 struct compat_ifreq __user *ifr32)
28997a229387SArnd Bergmann {
29007a229387SArnd Bergmann 	struct ifreq kifr;
29017a229387SArnd Bergmann 	mm_segment_t old_fs;
29027a229387SArnd Bergmann 	int err;
29037a229387SArnd Bergmann 
29047a229387SArnd Bergmann 	switch (cmd) {
29057a229387SArnd Bergmann 	case SIOCBONDENSLAVE:
29067a229387SArnd Bergmann 	case SIOCBONDRELEASE:
29077a229387SArnd Bergmann 	case SIOCBONDSETHWADDR:
29087a229387SArnd Bergmann 	case SIOCBONDCHANGEACTIVE:
29096b96018bSArnd Bergmann 		if (copy_from_user(&kifr, ifr32, sizeof(struct compat_ifreq)))
29107a229387SArnd Bergmann 			return -EFAULT;
29117a229387SArnd Bergmann 
29127a229387SArnd Bergmann 		old_fs = get_fs();
29137a229387SArnd Bergmann 		set_fs(KERNEL_DS);
2914c3f52ae6Sstephen hemminger 		err = dev_ioctl(net, cmd,
2915c3f52ae6Sstephen hemminger 				(struct ifreq __user __force *) &kifr);
29167a229387SArnd Bergmann 		set_fs(old_fs);
29177a229387SArnd Bergmann 
29187a229387SArnd Bergmann 		return err;
29197a229387SArnd Bergmann 	default:
292007d106d0SLinus Torvalds 		return -ENOIOCTLCMD;
2921ccbd6a5aSJoe Perches 	}
29227a229387SArnd Bergmann }
29237a229387SArnd Bergmann 
2924590d4693SBen Hutchings /* Handle ioctls that use ifreq::ifr_data and just need struct ifreq converted */
2925590d4693SBen Hutchings static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd,
29266b96018bSArnd Bergmann 				 struct compat_ifreq __user *u_ifreq32)
29277a229387SArnd Bergmann {
29287a229387SArnd Bergmann 	struct ifreq __user *u_ifreq64;
29297a229387SArnd Bergmann 	char tmp_buf[IFNAMSIZ];
29307a229387SArnd Bergmann 	void __user *data64;
29317a229387SArnd Bergmann 	u32 data32;
29327a229387SArnd Bergmann 
29337a229387SArnd Bergmann 	if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]),
29347a229387SArnd Bergmann 			   IFNAMSIZ))
29357a229387SArnd Bergmann 		return -EFAULT;
2936417c3522SBen Hutchings 	if (get_user(data32, &u_ifreq32->ifr_ifru.ifru_data))
29377a229387SArnd Bergmann 		return -EFAULT;
29387a229387SArnd Bergmann 	data64 = compat_ptr(data32);
29397a229387SArnd Bergmann 
29407a229387SArnd Bergmann 	u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
29417a229387SArnd Bergmann 
29427a229387SArnd Bergmann 	if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0],
29437a229387SArnd Bergmann 			 IFNAMSIZ))
29447a229387SArnd Bergmann 		return -EFAULT;
2945417c3522SBen Hutchings 	if (put_user(data64, &u_ifreq64->ifr_ifru.ifru_data))
29467a229387SArnd Bergmann 		return -EFAULT;
29477a229387SArnd Bergmann 
29486b96018bSArnd Bergmann 	return dev_ioctl(net, cmd, u_ifreq64);
29497a229387SArnd Bergmann }
29507a229387SArnd Bergmann 
29516b96018bSArnd Bergmann static int dev_ifsioc(struct net *net, struct socket *sock,
29526b96018bSArnd Bergmann 			 unsigned int cmd, struct compat_ifreq __user *uifr32)
29537a229387SArnd Bergmann {
2954a2116ed2SArnd Bergmann 	struct ifreq __user *uifr;
29557a229387SArnd Bergmann 	int err;
29567a229387SArnd Bergmann 
2957a2116ed2SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
2958a2116ed2SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(*uifr32)))
29597a229387SArnd Bergmann 		return -EFAULT;
2960a2116ed2SArnd Bergmann 
2961a2116ed2SArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr);
2962a2116ed2SArnd Bergmann 
29637a229387SArnd Bergmann 	if (!err) {
29647a229387SArnd Bergmann 		switch (cmd) {
29657a229387SArnd Bergmann 		case SIOCGIFFLAGS:
29667a229387SArnd Bergmann 		case SIOCGIFMETRIC:
29677a229387SArnd Bergmann 		case SIOCGIFMTU:
29687a229387SArnd Bergmann 		case SIOCGIFMEM:
29697a229387SArnd Bergmann 		case SIOCGIFHWADDR:
29707a229387SArnd Bergmann 		case SIOCGIFINDEX:
29717a229387SArnd Bergmann 		case SIOCGIFADDR:
29727a229387SArnd Bergmann 		case SIOCGIFBRDADDR:
29737a229387SArnd Bergmann 		case SIOCGIFDSTADDR:
29747a229387SArnd Bergmann 		case SIOCGIFNETMASK:
2975fab2532bSArnd Bergmann 		case SIOCGIFPFLAGS:
29767a229387SArnd Bergmann 		case SIOCGIFTXQLEN:
2977fab2532bSArnd Bergmann 		case SIOCGMIIPHY:
2978fab2532bSArnd Bergmann 		case SIOCGMIIREG:
2979a2116ed2SArnd Bergmann 			if (copy_in_user(uifr32, uifr, sizeof(*uifr32)))
2980a2116ed2SArnd Bergmann 				err = -EFAULT;
29817a229387SArnd Bergmann 			break;
2982a2116ed2SArnd Bergmann 		}
2983a2116ed2SArnd Bergmann 	}
2984a2116ed2SArnd Bergmann 	return err;
2985a2116ed2SArnd Bergmann }
2986a2116ed2SArnd Bergmann 
2987a2116ed2SArnd Bergmann static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
2988a2116ed2SArnd Bergmann 			struct compat_ifreq __user *uifr32)
2989a2116ed2SArnd Bergmann {
2990a2116ed2SArnd Bergmann 	struct ifreq ifr;
2991a2116ed2SArnd Bergmann 	struct compat_ifmap __user *uifmap32;
2992a2116ed2SArnd Bergmann 	mm_segment_t old_fs;
2993a2116ed2SArnd Bergmann 	int err;
2994a2116ed2SArnd Bergmann 
2995a2116ed2SArnd Bergmann 	uifmap32 = &uifr32->ifr_ifru.ifru_map;
2996a2116ed2SArnd Bergmann 	err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name));
29973ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
29983ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
29993ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
30003ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.irq, &uifmap32->irq);
30013ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.dma, &uifmap32->dma);
30023ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.port, &uifmap32->port);
3003a2116ed2SArnd Bergmann 	if (err)
3004a2116ed2SArnd Bergmann 		return -EFAULT;
3005a2116ed2SArnd Bergmann 
3006a2116ed2SArnd Bergmann 	old_fs = get_fs();
3007a2116ed2SArnd Bergmann 	set_fs(KERNEL_DS);
3008c3f52ae6Sstephen hemminger 	err = dev_ioctl(net, cmd, (void  __user __force *)&ifr);
3009a2116ed2SArnd Bergmann 	set_fs(old_fs);
3010a2116ed2SArnd Bergmann 
3011a2116ed2SArnd Bergmann 	if (cmd == SIOCGIFMAP && !err) {
30127a229387SArnd Bergmann 		err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name));
30133ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
30143ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
30153ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
30163ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.irq, &uifmap32->irq);
30173ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.dma, &uifmap32->dma);
30183ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.port, &uifmap32->port);
30197a229387SArnd Bergmann 		if (err)
30207a229387SArnd Bergmann 			err = -EFAULT;
30217a229387SArnd Bergmann 	}
30227a229387SArnd Bergmann 	return err;
30237a229387SArnd Bergmann }
30247a229387SArnd Bergmann 
30257a229387SArnd Bergmann struct rtentry32 {
30267a229387SArnd Bergmann 	u32		rt_pad1;
30277a229387SArnd Bergmann 	struct sockaddr rt_dst;         /* target address               */
30287a229387SArnd Bergmann 	struct sockaddr rt_gateway;     /* gateway addr (RTF_GATEWAY)   */
30297a229387SArnd Bergmann 	struct sockaddr rt_genmask;     /* target network mask (IP)     */
30307a229387SArnd Bergmann 	unsigned short	rt_flags;
30317a229387SArnd Bergmann 	short		rt_pad2;
30327a229387SArnd Bergmann 	u32		rt_pad3;
30337a229387SArnd Bergmann 	unsigned char	rt_tos;
30347a229387SArnd Bergmann 	unsigned char	rt_class;
30357a229387SArnd Bergmann 	short		rt_pad4;
30367a229387SArnd Bergmann 	short		rt_metric;      /* +1 for binary compatibility! */
30377a229387SArnd Bergmann 	/* char * */ u32 rt_dev;        /* forcing the device at add    */
30387a229387SArnd Bergmann 	u32		rt_mtu;         /* per route MTU/Window         */
30397a229387SArnd Bergmann 	u32		rt_window;      /* Window clamping              */
30407a229387SArnd Bergmann 	unsigned short  rt_irtt;        /* Initial RTT                  */
30417a229387SArnd Bergmann };
30427a229387SArnd Bergmann 
30437a229387SArnd Bergmann struct in6_rtmsg32 {
30447a229387SArnd Bergmann 	struct in6_addr		rtmsg_dst;
30457a229387SArnd Bergmann 	struct in6_addr		rtmsg_src;
30467a229387SArnd Bergmann 	struct in6_addr		rtmsg_gateway;
30477a229387SArnd Bergmann 	u32			rtmsg_type;
30487a229387SArnd Bergmann 	u16			rtmsg_dst_len;
30497a229387SArnd Bergmann 	u16			rtmsg_src_len;
30507a229387SArnd Bergmann 	u32			rtmsg_metric;
30517a229387SArnd Bergmann 	u32			rtmsg_info;
30527a229387SArnd Bergmann 	u32			rtmsg_flags;
30537a229387SArnd Bergmann 	s32			rtmsg_ifindex;
30547a229387SArnd Bergmann };
30557a229387SArnd Bergmann 
30566b96018bSArnd Bergmann static int routing_ioctl(struct net *net, struct socket *sock,
30576b96018bSArnd Bergmann 			 unsigned int cmd, void __user *argp)
30587a229387SArnd Bergmann {
30597a229387SArnd Bergmann 	int ret;
30607a229387SArnd Bergmann 	void *r = NULL;
30617a229387SArnd Bergmann 	struct in6_rtmsg r6;
30627a229387SArnd Bergmann 	struct rtentry r4;
30637a229387SArnd Bergmann 	char devname[16];
30647a229387SArnd Bergmann 	u32 rtdev;
30657a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
30667a229387SArnd Bergmann 
30676b96018bSArnd Bergmann 	if (sock && sock->sk && sock->sk->sk_family == AF_INET6) { /* ipv6 */
30686b96018bSArnd Bergmann 		struct in6_rtmsg32 __user *ur6 = argp;
30697a229387SArnd Bergmann 		ret = copy_from_user(&r6.rtmsg_dst, &(ur6->rtmsg_dst),
30707a229387SArnd Bergmann 			3 * sizeof(struct in6_addr));
30713ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_type, &(ur6->rtmsg_type));
30723ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len));
30733ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_src_len, &(ur6->rtmsg_src_len));
30743ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_metric, &(ur6->rtmsg_metric));
30753ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_info, &(ur6->rtmsg_info));
30763ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_flags, &(ur6->rtmsg_flags));
30773ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex));
30787a229387SArnd Bergmann 
30797a229387SArnd Bergmann 		r = (void *) &r6;
30807a229387SArnd Bergmann 	} else { /* ipv4 */
30816b96018bSArnd Bergmann 		struct rtentry32 __user *ur4 = argp;
30827a229387SArnd Bergmann 		ret = copy_from_user(&r4.rt_dst, &(ur4->rt_dst),
30837a229387SArnd Bergmann 					3 * sizeof(struct sockaddr));
30843ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_flags, &(ur4->rt_flags));
30853ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_metric, &(ur4->rt_metric));
30863ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_mtu, &(ur4->rt_mtu));
30873ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_window, &(ur4->rt_window));
30883ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_irtt, &(ur4->rt_irtt));
30893ddc5b46SMathieu Desnoyers 		ret |= get_user(rtdev, &(ur4->rt_dev));
30907a229387SArnd Bergmann 		if (rtdev) {
30917a229387SArnd Bergmann 			ret |= copy_from_user(devname, compat_ptr(rtdev), 15);
3092c3f52ae6Sstephen hemminger 			r4.rt_dev = (char __user __force *)devname;
3093c3f52ae6Sstephen hemminger 			devname[15] = 0;
30947a229387SArnd Bergmann 		} else
30957a229387SArnd Bergmann 			r4.rt_dev = NULL;
30967a229387SArnd Bergmann 
30977a229387SArnd Bergmann 		r = (void *) &r4;
30987a229387SArnd Bergmann 	}
30997a229387SArnd Bergmann 
31007a229387SArnd Bergmann 	if (ret) {
31017a229387SArnd Bergmann 		ret = -EFAULT;
31027a229387SArnd Bergmann 		goto out;
31037a229387SArnd Bergmann 	}
31047a229387SArnd Bergmann 
31057a229387SArnd Bergmann 	set_fs(KERNEL_DS);
31066b96018bSArnd Bergmann 	ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r);
31077a229387SArnd Bergmann 	set_fs(old_fs);
31087a229387SArnd Bergmann 
31097a229387SArnd Bergmann out:
31107a229387SArnd Bergmann 	return ret;
31117a229387SArnd Bergmann }
31127a229387SArnd Bergmann 
31137a229387SArnd Bergmann /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE
31147a229387SArnd Bergmann  * for some operations; this forces use of the newer bridge-utils that
311525985edcSLucas De Marchi  * use compatible ioctls
31167a229387SArnd Bergmann  */
31176b96018bSArnd Bergmann static int old_bridge_ioctl(compat_ulong_t __user *argp)
31187a229387SArnd Bergmann {
31196b96018bSArnd Bergmann 	compat_ulong_t tmp;
31207a229387SArnd Bergmann 
31216b96018bSArnd Bergmann 	if (get_user(tmp, argp))
31227a229387SArnd Bergmann 		return -EFAULT;
31237a229387SArnd Bergmann 	if (tmp == BRCTL_GET_VERSION)
31247a229387SArnd Bergmann 		return BRCTL_VERSION + 1;
31257a229387SArnd Bergmann 	return -EINVAL;
31267a229387SArnd Bergmann }
31277a229387SArnd Bergmann 
31286b96018bSArnd Bergmann static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
31296b96018bSArnd Bergmann 			 unsigned int cmd, unsigned long arg)
31306b96018bSArnd Bergmann {
31316b96018bSArnd Bergmann 	void __user *argp = compat_ptr(arg);
31326b96018bSArnd Bergmann 	struct sock *sk = sock->sk;
31336b96018bSArnd Bergmann 	struct net *net = sock_net(sk);
31347a229387SArnd Bergmann 
31356b96018bSArnd Bergmann 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
3136590d4693SBen Hutchings 		return compat_ifr_data_ioctl(net, cmd, argp);
31377a229387SArnd Bergmann 
31386b96018bSArnd Bergmann 	switch (cmd) {
31396b96018bSArnd Bergmann 	case SIOCSIFBR:
31406b96018bSArnd Bergmann 	case SIOCGIFBR:
31416b96018bSArnd Bergmann 		return old_bridge_ioctl(argp);
31426b96018bSArnd Bergmann 	case SIOCGIFNAME:
31436b96018bSArnd Bergmann 		return dev_ifname32(net, argp);
31446b96018bSArnd Bergmann 	case SIOCGIFCONF:
31456b96018bSArnd Bergmann 		return dev_ifconf(net, argp);
31466b96018bSArnd Bergmann 	case SIOCETHTOOL:
31476b96018bSArnd Bergmann 		return ethtool_ioctl(net, argp);
31487a50a240SArnd Bergmann 	case SIOCWANDEV:
31497a50a240SArnd Bergmann 		return compat_siocwandev(net, argp);
3150a2116ed2SArnd Bergmann 	case SIOCGIFMAP:
3151a2116ed2SArnd Bergmann 	case SIOCSIFMAP:
3152a2116ed2SArnd Bergmann 		return compat_sioc_ifmap(net, cmd, argp);
31536b96018bSArnd Bergmann 	case SIOCBONDENSLAVE:
31546b96018bSArnd Bergmann 	case SIOCBONDRELEASE:
31556b96018bSArnd Bergmann 	case SIOCBONDSETHWADDR:
31566b96018bSArnd Bergmann 	case SIOCBONDCHANGEACTIVE:
31576b96018bSArnd Bergmann 		return bond_ioctl(net, cmd, argp);
31586b96018bSArnd Bergmann 	case SIOCADDRT:
31596b96018bSArnd Bergmann 	case SIOCDELRT:
31606b96018bSArnd Bergmann 		return routing_ioctl(net, sock, cmd, argp);
31616b96018bSArnd Bergmann 	case SIOCGSTAMP:
31626b96018bSArnd Bergmann 		return do_siocgstamp(net, sock, cmd, argp);
31636b96018bSArnd Bergmann 	case SIOCGSTAMPNS:
31646b96018bSArnd Bergmann 		return do_siocgstampns(net, sock, cmd, argp);
3165590d4693SBen Hutchings 	case SIOCBONDSLAVEINFOQUERY:
3166590d4693SBen Hutchings 	case SIOCBONDINFOQUERY:
3167a2116ed2SArnd Bergmann 	case SIOCSHWTSTAMP:
3168fd468c74SBen Hutchings 	case SIOCGHWTSTAMP:
3169590d4693SBen Hutchings 		return compat_ifr_data_ioctl(net, cmd, argp);
31707a229387SArnd Bergmann 
31716b96018bSArnd Bergmann 	case FIOSETOWN:
31726b96018bSArnd Bergmann 	case SIOCSPGRP:
31736b96018bSArnd Bergmann 	case FIOGETOWN:
31746b96018bSArnd Bergmann 	case SIOCGPGRP:
31756b96018bSArnd Bergmann 	case SIOCBRADDBR:
31766b96018bSArnd Bergmann 	case SIOCBRDELBR:
31776b96018bSArnd Bergmann 	case SIOCGIFVLAN:
31786b96018bSArnd Bergmann 	case SIOCSIFVLAN:
31796b96018bSArnd Bergmann 	case SIOCADDDLCI:
31806b96018bSArnd Bergmann 	case SIOCDELDLCI:
31816b96018bSArnd Bergmann 		return sock_ioctl(file, cmd, arg);
31826b96018bSArnd Bergmann 
31836b96018bSArnd Bergmann 	case SIOCGIFFLAGS:
31846b96018bSArnd Bergmann 	case SIOCSIFFLAGS:
31856b96018bSArnd Bergmann 	case SIOCGIFMETRIC:
31866b96018bSArnd Bergmann 	case SIOCSIFMETRIC:
31876b96018bSArnd Bergmann 	case SIOCGIFMTU:
31886b96018bSArnd Bergmann 	case SIOCSIFMTU:
31896b96018bSArnd Bergmann 	case SIOCGIFMEM:
31906b96018bSArnd Bergmann 	case SIOCSIFMEM:
31916b96018bSArnd Bergmann 	case SIOCGIFHWADDR:
31926b96018bSArnd Bergmann 	case SIOCSIFHWADDR:
31936b96018bSArnd Bergmann 	case SIOCADDMULTI:
31946b96018bSArnd Bergmann 	case SIOCDELMULTI:
31956b96018bSArnd Bergmann 	case SIOCGIFINDEX:
31966b96018bSArnd Bergmann 	case SIOCGIFADDR:
31976b96018bSArnd Bergmann 	case SIOCSIFADDR:
31986b96018bSArnd Bergmann 	case SIOCSIFHWBROADCAST:
31996b96018bSArnd Bergmann 	case SIOCDIFADDR:
32006b96018bSArnd Bergmann 	case SIOCGIFBRDADDR:
32016b96018bSArnd Bergmann 	case SIOCSIFBRDADDR:
32026b96018bSArnd Bergmann 	case SIOCGIFDSTADDR:
32036b96018bSArnd Bergmann 	case SIOCSIFDSTADDR:
32046b96018bSArnd Bergmann 	case SIOCGIFNETMASK:
32056b96018bSArnd Bergmann 	case SIOCSIFNETMASK:
32066b96018bSArnd Bergmann 	case SIOCSIFPFLAGS:
32076b96018bSArnd Bergmann 	case SIOCGIFPFLAGS:
32086b96018bSArnd Bergmann 	case SIOCGIFTXQLEN:
32096b96018bSArnd Bergmann 	case SIOCSIFTXQLEN:
32106b96018bSArnd Bergmann 	case SIOCBRADDIF:
32116b96018bSArnd Bergmann 	case SIOCBRDELIF:
32129177efd3SArnd Bergmann 	case SIOCSIFNAME:
32139177efd3SArnd Bergmann 	case SIOCGMIIPHY:
32149177efd3SArnd Bergmann 	case SIOCGMIIREG:
32159177efd3SArnd Bergmann 	case SIOCSMIIREG:
32166b96018bSArnd Bergmann 		return dev_ifsioc(net, sock, cmd, argp);
32179177efd3SArnd Bergmann 
32186b96018bSArnd Bergmann 	case SIOCSARP:
32196b96018bSArnd Bergmann 	case SIOCGARP:
32206b96018bSArnd Bergmann 	case SIOCDARP:
32216b96018bSArnd Bergmann 	case SIOCATMARK:
32229177efd3SArnd Bergmann 		return sock_do_ioctl(net, sock, cmd, arg);
32239177efd3SArnd Bergmann 	}
32249177efd3SArnd Bergmann 
32256b96018bSArnd Bergmann 	return -ENOIOCTLCMD;
32266b96018bSArnd Bergmann }
32277a229387SArnd Bergmann 
322895c96174SEric Dumazet static long compat_sock_ioctl(struct file *file, unsigned int cmd,
322989bbfc95SShaun Pereira 			      unsigned long arg)
323089bbfc95SShaun Pereira {
323189bbfc95SShaun Pereira 	struct socket *sock = file->private_data;
323289bbfc95SShaun Pereira 	int ret = -ENOIOCTLCMD;
323387de87d5SDavid S. Miller 	struct sock *sk;
323487de87d5SDavid S. Miller 	struct net *net;
323587de87d5SDavid S. Miller 
323687de87d5SDavid S. Miller 	sk = sock->sk;
323787de87d5SDavid S. Miller 	net = sock_net(sk);
323889bbfc95SShaun Pereira 
323989bbfc95SShaun Pereira 	if (sock->ops->compat_ioctl)
324089bbfc95SShaun Pereira 		ret = sock->ops->compat_ioctl(sock, cmd, arg);
324189bbfc95SShaun Pereira 
324287de87d5SDavid S. Miller 	if (ret == -ENOIOCTLCMD &&
324387de87d5SDavid S. Miller 	    (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST))
324487de87d5SDavid S. Miller 		ret = compat_wext_handle_ioctl(net, cmd, arg);
324587de87d5SDavid S. Miller 
32466b96018bSArnd Bergmann 	if (ret == -ENOIOCTLCMD)
32476b96018bSArnd Bergmann 		ret = compat_sock_ioctl_trans(file, sock, cmd, arg);
32486b96018bSArnd Bergmann 
324989bbfc95SShaun Pereira 	return ret;
325089bbfc95SShaun Pereira }
325189bbfc95SShaun Pereira #endif
325289bbfc95SShaun Pereira 
3253ac5a488eSSridhar Samudrala int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
3254ac5a488eSSridhar Samudrala {
3255ac5a488eSSridhar Samudrala 	return sock->ops->bind(sock, addr, addrlen);
3256ac5a488eSSridhar Samudrala }
3257c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_bind);
3258ac5a488eSSridhar Samudrala 
3259ac5a488eSSridhar Samudrala int kernel_listen(struct socket *sock, int backlog)
3260ac5a488eSSridhar Samudrala {
3261ac5a488eSSridhar Samudrala 	return sock->ops->listen(sock, backlog);
3262ac5a488eSSridhar Samudrala }
3263c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_listen);
3264ac5a488eSSridhar Samudrala 
3265ac5a488eSSridhar Samudrala int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
3266ac5a488eSSridhar Samudrala {
3267ac5a488eSSridhar Samudrala 	struct sock *sk = sock->sk;
3268ac5a488eSSridhar Samudrala 	int err;
3269ac5a488eSSridhar Samudrala 
3270ac5a488eSSridhar Samudrala 	err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
3271ac5a488eSSridhar Samudrala 			       newsock);
3272ac5a488eSSridhar Samudrala 	if (err < 0)
3273ac5a488eSSridhar Samudrala 		goto done;
3274ac5a488eSSridhar Samudrala 
3275ac5a488eSSridhar Samudrala 	err = sock->ops->accept(sock, *newsock, flags);
3276ac5a488eSSridhar Samudrala 	if (err < 0) {
3277ac5a488eSSridhar Samudrala 		sock_release(*newsock);
3278fa8705b0STony Battersby 		*newsock = NULL;
3279ac5a488eSSridhar Samudrala 		goto done;
3280ac5a488eSSridhar Samudrala 	}
3281ac5a488eSSridhar Samudrala 
3282ac5a488eSSridhar Samudrala 	(*newsock)->ops = sock->ops;
32831b08534eSWei Yongjun 	__module_get((*newsock)->ops->owner);
3284ac5a488eSSridhar Samudrala 
3285ac5a488eSSridhar Samudrala done:
3286ac5a488eSSridhar Samudrala 	return err;
3287ac5a488eSSridhar Samudrala }
3288c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_accept);
3289ac5a488eSSridhar Samudrala 
3290ac5a488eSSridhar Samudrala int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
3291ac5a488eSSridhar Samudrala 		   int flags)
3292ac5a488eSSridhar Samudrala {
3293ac5a488eSSridhar Samudrala 	return sock->ops->connect(sock, addr, addrlen, flags);
3294ac5a488eSSridhar Samudrala }
3295c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_connect);
3296ac5a488eSSridhar Samudrala 
3297ac5a488eSSridhar Samudrala int kernel_getsockname(struct socket *sock, struct sockaddr *addr,
3298ac5a488eSSridhar Samudrala 			 int *addrlen)
3299ac5a488eSSridhar Samudrala {
3300ac5a488eSSridhar Samudrala 	return sock->ops->getname(sock, addr, addrlen, 0);
3301ac5a488eSSridhar Samudrala }
3302c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockname);
3303ac5a488eSSridhar Samudrala 
3304ac5a488eSSridhar Samudrala int kernel_getpeername(struct socket *sock, struct sockaddr *addr,
3305ac5a488eSSridhar Samudrala 			 int *addrlen)
3306ac5a488eSSridhar Samudrala {
3307ac5a488eSSridhar Samudrala 	return sock->ops->getname(sock, addr, addrlen, 1);
3308ac5a488eSSridhar Samudrala }
3309c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getpeername);
3310ac5a488eSSridhar Samudrala 
3311ac5a488eSSridhar Samudrala int kernel_getsockopt(struct socket *sock, int level, int optname,
3312ac5a488eSSridhar Samudrala 			char *optval, int *optlen)
3313ac5a488eSSridhar Samudrala {
3314ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3315fb8621bbSNamhyung Kim 	char __user *uoptval;
3316fb8621bbSNamhyung Kim 	int __user *uoptlen;
3317ac5a488eSSridhar Samudrala 	int err;
3318ac5a488eSSridhar Samudrala 
3319fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3320fb8621bbSNamhyung Kim 	uoptlen = (int __user __force *) optlen;
3321fb8621bbSNamhyung Kim 
3322ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3323ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3324fb8621bbSNamhyung Kim 		err = sock_getsockopt(sock, level, optname, uoptval, uoptlen);
3325ac5a488eSSridhar Samudrala 	else
3326fb8621bbSNamhyung Kim 		err = sock->ops->getsockopt(sock, level, optname, uoptval,
3327fb8621bbSNamhyung Kim 					    uoptlen);
3328ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3329ac5a488eSSridhar Samudrala 	return err;
3330ac5a488eSSridhar Samudrala }
3331c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockopt);
3332ac5a488eSSridhar Samudrala 
3333ac5a488eSSridhar Samudrala int kernel_setsockopt(struct socket *sock, int level, int optname,
3334b7058842SDavid S. Miller 			char *optval, unsigned int optlen)
3335ac5a488eSSridhar Samudrala {
3336ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3337fb8621bbSNamhyung Kim 	char __user *uoptval;
3338ac5a488eSSridhar Samudrala 	int err;
3339ac5a488eSSridhar Samudrala 
3340fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3341fb8621bbSNamhyung Kim 
3342ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3343ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3344fb8621bbSNamhyung Kim 		err = sock_setsockopt(sock, level, optname, uoptval, optlen);
3345ac5a488eSSridhar Samudrala 	else
3346fb8621bbSNamhyung Kim 		err = sock->ops->setsockopt(sock, level, optname, uoptval,
3347ac5a488eSSridhar Samudrala 					    optlen);
3348ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3349ac5a488eSSridhar Samudrala 	return err;
3350ac5a488eSSridhar Samudrala }
3351c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_setsockopt);
3352ac5a488eSSridhar Samudrala 
3353ac5a488eSSridhar Samudrala int kernel_sendpage(struct socket *sock, struct page *page, int offset,
3354ac5a488eSSridhar Samudrala 		    size_t size, int flags)
3355ac5a488eSSridhar Samudrala {
3356ac5a488eSSridhar Samudrala 	if (sock->ops->sendpage)
3357ac5a488eSSridhar Samudrala 		return sock->ops->sendpage(sock, page, offset, size, flags);
3358ac5a488eSSridhar Samudrala 
3359ac5a488eSSridhar Samudrala 	return sock_no_sendpage(sock, page, offset, size, flags);
3360ac5a488eSSridhar Samudrala }
3361c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendpage);
3362ac5a488eSSridhar Samudrala 
3363ac5a488eSSridhar Samudrala int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg)
3364ac5a488eSSridhar Samudrala {
3365ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3366ac5a488eSSridhar Samudrala 	int err;
3367ac5a488eSSridhar Samudrala 
3368ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3369ac5a488eSSridhar Samudrala 	err = sock->ops->ioctl(sock, cmd, arg);
3370ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3371ac5a488eSSridhar Samudrala 
3372ac5a488eSSridhar Samudrala 	return err;
3373ac5a488eSSridhar Samudrala }
3374c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sock_ioctl);
3375ac5a488eSSridhar Samudrala 
337691cf45f0STrond Myklebust int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
337791cf45f0STrond Myklebust {
337891cf45f0STrond Myklebust 	return sock->ops->shutdown(sock, how);
337991cf45f0STrond Myklebust }
338091cf45f0STrond Myklebust EXPORT_SYMBOL(kernel_sock_shutdown);
3381