xref: /openbmc/linux/net/socket.c (revision 39b65252)
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/wanrouter.h>
731da177e4SLinus Torvalds #include <linux/if_bridge.h>
7420380731SArnaldo Carvalho de Melo #include <linux/if_frad.h>
7520380731SArnaldo Carvalho de Melo #include <linux/if_vlan.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>
1086b96018bSArnd Bergmann 
1091da177e4SLinus Torvalds static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
110027445c3SBadari Pulavarty static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
111027445c3SBadari Pulavarty 			 unsigned long nr_segs, loff_t pos);
112027445c3SBadari Pulavarty static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
113027445c3SBadari Pulavarty 			  unsigned long nr_segs, loff_t pos);
1141da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma);
1151da177e4SLinus Torvalds 
1161da177e4SLinus Torvalds static int sock_close(struct inode *inode, struct file *file);
1171da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file,
1181da177e4SLinus Torvalds 			      struct poll_table_struct *wait);
11989bddce5SStephen Hemminger static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
12089bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
12189bbfc95SShaun Pereira static long compat_sock_ioctl(struct file *file,
12289bbfc95SShaun Pereira 			      unsigned int cmd, unsigned long arg);
12389bbfc95SShaun Pereira #endif
1241da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on);
1251da177e4SLinus Torvalds static ssize_t sock_sendpage(struct file *file, struct page *page,
1261da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more);
1279c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
1289c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
1299c55e01cSJens Axboe 				unsigned int flags);
1301da177e4SLinus Torvalds 
1311da177e4SLinus Torvalds /*
1321da177e4SLinus Torvalds  *	Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
1331da177e4SLinus Torvalds  *	in the operation structures but are done directly via the socketcall() multiplexor.
1341da177e4SLinus Torvalds  */
1351da177e4SLinus Torvalds 
136da7071d7SArjan van de Ven static const struct file_operations socket_file_ops = {
1371da177e4SLinus Torvalds 	.owner =	THIS_MODULE,
1381da177e4SLinus Torvalds 	.llseek =	no_llseek,
1391da177e4SLinus Torvalds 	.aio_read =	sock_aio_read,
1401da177e4SLinus Torvalds 	.aio_write =	sock_aio_write,
1411da177e4SLinus Torvalds 	.poll =		sock_poll,
1421da177e4SLinus Torvalds 	.unlocked_ioctl = sock_ioctl,
14389bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
14489bbfc95SShaun Pereira 	.compat_ioctl = compat_sock_ioctl,
14589bbfc95SShaun Pereira #endif
1461da177e4SLinus Torvalds 	.mmap =		sock_mmap,
1471da177e4SLinus Torvalds 	.open =		sock_no_open,	/* special open code to disallow open via /proc */
1481da177e4SLinus Torvalds 	.release =	sock_close,
1491da177e4SLinus Torvalds 	.fasync =	sock_fasync,
1505274f052SJens Axboe 	.sendpage =	sock_sendpage,
1515274f052SJens Axboe 	.splice_write = generic_splice_sendpage,
1529c55e01cSJens Axboe 	.splice_read =	sock_splice_read,
1531da177e4SLinus Torvalds };
1541da177e4SLinus Torvalds 
1551da177e4SLinus Torvalds /*
1561da177e4SLinus Torvalds  *	The protocol list. Each protocol is registered in here.
1571da177e4SLinus Torvalds  */
1581da177e4SLinus Torvalds 
1591da177e4SLinus Torvalds static DEFINE_SPINLOCK(net_family_lock);
160190683a9SEric Dumazet static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly;
1611da177e4SLinus Torvalds 
1621da177e4SLinus Torvalds /*
1631da177e4SLinus Torvalds  *	Statistics counters of the socket lists
1641da177e4SLinus Torvalds  */
1651da177e4SLinus Torvalds 
166c6d409cfSEric Dumazet static DEFINE_PER_CPU(int, sockets_in_use);
1671da177e4SLinus Torvalds 
1681da177e4SLinus Torvalds /*
16989bddce5SStephen Hemminger  * Support routines.
17089bddce5SStephen Hemminger  * Move socket addresses back and forth across the kernel/user
1711da177e4SLinus Torvalds  * divide and look after the messy bits.
1721da177e4SLinus Torvalds  */
1731da177e4SLinus Torvalds 
1741da177e4SLinus Torvalds /**
1751da177e4SLinus Torvalds  *	move_addr_to_kernel	-	copy a socket address into kernel space
1761da177e4SLinus Torvalds  *	@uaddr: Address in user space
1771da177e4SLinus Torvalds  *	@kaddr: Address in kernel space
1781da177e4SLinus Torvalds  *	@ulen: Length in user space
1791da177e4SLinus Torvalds  *
1801da177e4SLinus Torvalds  *	The address is copied into kernel space. If the provided address is
1811da177e4SLinus Torvalds  *	too long an error code of -EINVAL is returned. If the copy gives
1821da177e4SLinus Torvalds  *	invalid addresses -EFAULT is returned. On a success 0 is returned.
1831da177e4SLinus Torvalds  */
1841da177e4SLinus Torvalds 
18543db362dSMaciej Żenczykowski int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr)
1861da177e4SLinus Torvalds {
187230b1839SYOSHIFUJI Hideaki 	if (ulen < 0 || ulen > sizeof(struct sockaddr_storage))
1881da177e4SLinus Torvalds 		return -EINVAL;
1891da177e4SLinus Torvalds 	if (ulen == 0)
1901da177e4SLinus Torvalds 		return 0;
1911da177e4SLinus Torvalds 	if (copy_from_user(kaddr, uaddr, ulen))
1921da177e4SLinus Torvalds 		return -EFAULT;
1933ec3b2fbSDavid Woodhouse 	return audit_sockaddr(ulen, kaddr);
1941da177e4SLinus Torvalds }
1951da177e4SLinus Torvalds 
1961da177e4SLinus Torvalds /**
1971da177e4SLinus Torvalds  *	move_addr_to_user	-	copy an address to user space
1981da177e4SLinus Torvalds  *	@kaddr: kernel space address
1991da177e4SLinus Torvalds  *	@klen: length of address in kernel
2001da177e4SLinus Torvalds  *	@uaddr: user space address
2011da177e4SLinus Torvalds  *	@ulen: pointer to user length field
2021da177e4SLinus Torvalds  *
2031da177e4SLinus Torvalds  *	The value pointed to by ulen on entry is the buffer length available.
2041da177e4SLinus Torvalds  *	This is overwritten with the buffer space used. -EINVAL is returned
2051da177e4SLinus Torvalds  *	if an overlong buffer is specified or a negative buffer size. -EFAULT
2061da177e4SLinus Torvalds  *	is returned if either the buffer or the length field are not
2071da177e4SLinus Torvalds  *	accessible.
2081da177e4SLinus Torvalds  *	After copying the data up to the limit the user specifies, the true
2091da177e4SLinus Torvalds  *	length of the data is written over the length limit the user
2101da177e4SLinus Torvalds  *	specified. Zero is returned for a success.
2111da177e4SLinus Torvalds  */
2121da177e4SLinus Torvalds 
21343db362dSMaciej Żenczykowski static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen,
21411165f14Sstephen hemminger 			     void __user *uaddr, int __user *ulen)
2151da177e4SLinus Torvalds {
2161da177e4SLinus Torvalds 	int err;
2171da177e4SLinus Torvalds 	int len;
2181da177e4SLinus Torvalds 
21989bddce5SStephen Hemminger 	err = get_user(len, ulen);
22089bddce5SStephen Hemminger 	if (err)
2211da177e4SLinus Torvalds 		return err;
2221da177e4SLinus Torvalds 	if (len > klen)
2231da177e4SLinus Torvalds 		len = klen;
224230b1839SYOSHIFUJI Hideaki 	if (len < 0 || len > sizeof(struct sockaddr_storage))
2251da177e4SLinus Torvalds 		return -EINVAL;
22689bddce5SStephen Hemminger 	if (len) {
227d6fe3945SSteve Grubb 		if (audit_sockaddr(klen, kaddr))
228d6fe3945SSteve Grubb 			return -ENOMEM;
2291da177e4SLinus Torvalds 		if (copy_to_user(uaddr, kaddr, len))
2301da177e4SLinus Torvalds 			return -EFAULT;
2311da177e4SLinus Torvalds 	}
2321da177e4SLinus Torvalds 	/*
2331da177e4SLinus Torvalds 	 *      "fromlen shall refer to the value before truncation.."
2341da177e4SLinus Torvalds 	 *                      1003.1g
2351da177e4SLinus Torvalds 	 */
2361da177e4SLinus Torvalds 	return __put_user(klen, ulen);
2371da177e4SLinus Torvalds }
2381da177e4SLinus Torvalds 
239e18b890bSChristoph Lameter static struct kmem_cache *sock_inode_cachep __read_mostly;
2401da177e4SLinus Torvalds 
2411da177e4SLinus Torvalds static struct inode *sock_alloc_inode(struct super_block *sb)
2421da177e4SLinus Torvalds {
2431da177e4SLinus Torvalds 	struct socket_alloc *ei;
244eaefd110SEric Dumazet 	struct socket_wq *wq;
24589bddce5SStephen Hemminger 
246e94b1766SChristoph Lameter 	ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL);
2471da177e4SLinus Torvalds 	if (!ei)
2481da177e4SLinus Torvalds 		return NULL;
249eaefd110SEric Dumazet 	wq = kmalloc(sizeof(*wq), GFP_KERNEL);
250eaefd110SEric Dumazet 	if (!wq) {
25143815482SEric Dumazet 		kmem_cache_free(sock_inode_cachep, ei);
25243815482SEric Dumazet 		return NULL;
25343815482SEric Dumazet 	}
254eaefd110SEric Dumazet 	init_waitqueue_head(&wq->wait);
255eaefd110SEric Dumazet 	wq->fasync_list = NULL;
256eaefd110SEric Dumazet 	RCU_INIT_POINTER(ei->socket.wq, wq);
2571da177e4SLinus Torvalds 
2581da177e4SLinus Torvalds 	ei->socket.state = SS_UNCONNECTED;
2591da177e4SLinus Torvalds 	ei->socket.flags = 0;
2601da177e4SLinus Torvalds 	ei->socket.ops = NULL;
2611da177e4SLinus Torvalds 	ei->socket.sk = NULL;
2621da177e4SLinus Torvalds 	ei->socket.file = NULL;
2631da177e4SLinus Torvalds 
2641da177e4SLinus Torvalds 	return &ei->vfs_inode;
2651da177e4SLinus Torvalds }
2661da177e4SLinus Torvalds 
2671da177e4SLinus Torvalds static void sock_destroy_inode(struct inode *inode)
2681da177e4SLinus Torvalds {
26943815482SEric Dumazet 	struct socket_alloc *ei;
270eaefd110SEric Dumazet 	struct socket_wq *wq;
27143815482SEric Dumazet 
27243815482SEric Dumazet 	ei = container_of(inode, struct socket_alloc, vfs_inode);
273eaefd110SEric Dumazet 	wq = rcu_dereference_protected(ei->socket.wq, 1);
27461845220SLai Jiangshan 	kfree_rcu(wq, rcu);
27543815482SEric Dumazet 	kmem_cache_free(sock_inode_cachep, ei);
2761da177e4SLinus Torvalds }
2771da177e4SLinus Torvalds 
27851cc5068SAlexey Dobriyan static void init_once(void *foo)
2791da177e4SLinus Torvalds {
2801da177e4SLinus Torvalds 	struct socket_alloc *ei = (struct socket_alloc *)foo;
2811da177e4SLinus Torvalds 
2821da177e4SLinus Torvalds 	inode_init_once(&ei->vfs_inode);
2831da177e4SLinus Torvalds }
2841da177e4SLinus Torvalds 
2851da177e4SLinus Torvalds static int init_inodecache(void)
2861da177e4SLinus Torvalds {
2871da177e4SLinus Torvalds 	sock_inode_cachep = kmem_cache_create("sock_inode_cache",
2881da177e4SLinus Torvalds 					      sizeof(struct socket_alloc),
28989bddce5SStephen Hemminger 					      0,
29089bddce5SStephen Hemminger 					      (SLAB_HWCACHE_ALIGN |
29189bddce5SStephen Hemminger 					       SLAB_RECLAIM_ACCOUNT |
292fffb60f9SPaul Jackson 					       SLAB_MEM_SPREAD),
29320c2df83SPaul Mundt 					      init_once);
2941da177e4SLinus Torvalds 	if (sock_inode_cachep == NULL)
2951da177e4SLinus Torvalds 		return -ENOMEM;
2961da177e4SLinus Torvalds 	return 0;
2971da177e4SLinus Torvalds }
2981da177e4SLinus Torvalds 
299b87221deSAlexey Dobriyan static const struct super_operations sockfs_ops = {
3001da177e4SLinus Torvalds 	.alloc_inode	= sock_alloc_inode,
3011da177e4SLinus Torvalds 	.destroy_inode	= sock_destroy_inode,
3021da177e4SLinus Torvalds 	.statfs		= simple_statfs,
3031da177e4SLinus Torvalds };
3041da177e4SLinus Torvalds 
305c23fbb6bSEric Dumazet /*
306c23fbb6bSEric Dumazet  * sockfs_dname() is called from d_path().
307c23fbb6bSEric Dumazet  */
308c23fbb6bSEric Dumazet static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen)
309c23fbb6bSEric Dumazet {
310c23fbb6bSEric Dumazet 	return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]",
311c23fbb6bSEric Dumazet 				dentry->d_inode->i_ino);
312c23fbb6bSEric Dumazet }
313c23fbb6bSEric Dumazet 
3143ba13d17SAl Viro static const struct dentry_operations sockfs_dentry_operations = {
315c23fbb6bSEric Dumazet 	.d_dname  = sockfs_dname,
3161da177e4SLinus Torvalds };
3171da177e4SLinus Torvalds 
318c74a1cbbSAl Viro static struct dentry *sockfs_mount(struct file_system_type *fs_type,
319c74a1cbbSAl Viro 			 int flags, const char *dev_name, void *data)
320c74a1cbbSAl Viro {
321c74a1cbbSAl Viro 	return mount_pseudo(fs_type, "socket:", &sockfs_ops,
322c74a1cbbSAl Viro 		&sockfs_dentry_operations, SOCKFS_MAGIC);
323c74a1cbbSAl Viro }
324c74a1cbbSAl Viro 
325c74a1cbbSAl Viro static struct vfsmount *sock_mnt __read_mostly;
326c74a1cbbSAl Viro 
327c74a1cbbSAl Viro static struct file_system_type sock_fs_type = {
328c74a1cbbSAl Viro 	.name =		"sockfs",
329c74a1cbbSAl Viro 	.mount =	sockfs_mount,
330c74a1cbbSAl Viro 	.kill_sb =	kill_anon_super,
331c74a1cbbSAl Viro };
332c74a1cbbSAl Viro 
3331da177e4SLinus Torvalds /*
3341da177e4SLinus Torvalds  *	Obtains the first available file descriptor and sets it up for use.
3351da177e4SLinus Torvalds  *
33639d8c1b6SDavid S. Miller  *	These functions create file structures and maps them to fd space
33739d8c1b6SDavid S. Miller  *	of the current process. On success it returns file descriptor
3381da177e4SLinus Torvalds  *	and file struct implicitly stored in sock->file.
3391da177e4SLinus Torvalds  *	Note that another thread may close file descriptor before we return
3401da177e4SLinus Torvalds  *	from this function. We use the fact that now we do not refer
3411da177e4SLinus Torvalds  *	to socket after mapping. If one day we will need it, this
3421da177e4SLinus Torvalds  *	function will increment ref. count on file by 1.
3431da177e4SLinus Torvalds  *
3441da177e4SLinus Torvalds  *	In any case returned fd MAY BE not valid!
3451da177e4SLinus Torvalds  *	This race condition is unavoidable
3461da177e4SLinus Torvalds  *	with shared fd spaces, we cannot solve it inside kernel,
3471da177e4SLinus Torvalds  *	but we take care of internal coherence yet.
3481da177e4SLinus Torvalds  */
3491da177e4SLinus Torvalds 
350aab174f0SLinus Torvalds struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)
3511da177e4SLinus Torvalds {
3527cbe66b6SAl Viro 	struct qstr name = { .name = "" };
3532c48b9c4SAl Viro 	struct path path;
3547cbe66b6SAl Viro 	struct file *file;
3551da177e4SLinus Torvalds 
356600e1779SMasatake YAMATO 	if (dname) {
357600e1779SMasatake YAMATO 		name.name = dname;
358600e1779SMasatake YAMATO 		name.len = strlen(name.name);
359600e1779SMasatake YAMATO 	} else if (sock->sk) {
360600e1779SMasatake YAMATO 		name.name = sock->sk->sk_prot_creator->name;
361600e1779SMasatake YAMATO 		name.len = strlen(name.name);
362600e1779SMasatake YAMATO 	}
3634b936885SNick Piggin 	path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name);
36428407630SAl Viro 	if (unlikely(!path.dentry))
36528407630SAl Viro 		return ERR_PTR(-ENOMEM);
3662c48b9c4SAl Viro 	path.mnt = mntget(sock_mnt);
36739d8c1b6SDavid S. Miller 
3682c48b9c4SAl Viro 	d_instantiate(path.dentry, SOCK_INODE(sock));
369cc3808f8SAl Viro 	SOCK_INODE(sock)->i_fop = &socket_file_ops;
370cc3808f8SAl Viro 
3712c48b9c4SAl Viro 	file = alloc_file(&path, FMODE_READ | FMODE_WRITE,
372cc3808f8SAl Viro 		  &socket_file_ops);
373*39b65252SAnatol Pomozov 	if (unlikely(IS_ERR(file))) {
374cc3808f8SAl Viro 		/* drop dentry, keep inode */
3757de9c6eeSAl Viro 		ihold(path.dentry->d_inode);
3762c48b9c4SAl Viro 		path_put(&path);
377*39b65252SAnatol Pomozov 		return file;
378cc3808f8SAl Viro 	}
3791da177e4SLinus Torvalds 
3801da177e4SLinus Torvalds 	sock->file = file;
38177d27200SUlrich Drepper 	file->f_flags = O_RDWR | (flags & O_NONBLOCK);
3821da177e4SLinus Torvalds 	file->f_pos = 0;
38307dc3f07SBenjamin LaHaise 	file->private_data = sock;
38428407630SAl Viro 	return file;
3851da177e4SLinus Torvalds }
38656b31d1cSAl Viro EXPORT_SYMBOL(sock_alloc_file);
3871da177e4SLinus Torvalds 
38856b31d1cSAl Viro static int sock_map_fd(struct socket *sock, int flags)
38939d8c1b6SDavid S. Miller {
39039d8c1b6SDavid S. Miller 	struct file *newfile;
39128407630SAl Viro 	int fd = get_unused_fd_flags(flags);
39228407630SAl Viro 	if (unlikely(fd < 0))
3931da177e4SLinus Torvalds 		return fd;
3941da177e4SLinus Torvalds 
395aab174f0SLinus Torvalds 	newfile = sock_alloc_file(sock, flags, NULL);
39628407630SAl Viro 	if (likely(!IS_ERR(newfile))) {
3971da177e4SLinus Torvalds 		fd_install(fd, newfile);
3981da177e4SLinus Torvalds 		return fd;
3991da177e4SLinus Torvalds 	}
40028407630SAl Viro 
40128407630SAl Viro 	put_unused_fd(fd);
40228407630SAl Viro 	return PTR_ERR(newfile);
4031da177e4SLinus Torvalds }
4041da177e4SLinus Torvalds 
405406a3c63SJohn Fastabend struct socket *sock_from_file(struct file *file, int *err)
4066cb153caSBenjamin LaHaise {
4076cb153caSBenjamin LaHaise 	if (file->f_op == &socket_file_ops)
4086cb153caSBenjamin LaHaise 		return file->private_data;	/* set in sock_map_fd */
4096cb153caSBenjamin LaHaise 
4106cb153caSBenjamin LaHaise 	*err = -ENOTSOCK;
4116cb153caSBenjamin LaHaise 	return NULL;
4126cb153caSBenjamin LaHaise }
413406a3c63SJohn Fastabend EXPORT_SYMBOL(sock_from_file);
4146cb153caSBenjamin LaHaise 
4151da177e4SLinus Torvalds /**
4161da177e4SLinus Torvalds  *	sockfd_lookup - Go from a file number to its socket slot
4171da177e4SLinus Torvalds  *	@fd: file handle
4181da177e4SLinus Torvalds  *	@err: pointer to an error code return
4191da177e4SLinus Torvalds  *
4201da177e4SLinus Torvalds  *	The file handle passed in is locked and the socket it is bound
4211da177e4SLinus Torvalds  *	too is returned. If an error occurs the err pointer is overwritten
4221da177e4SLinus Torvalds  *	with a negative errno code and NULL is returned. The function checks
4231da177e4SLinus Torvalds  *	for both invalid handles and passing a handle which is not a socket.
4241da177e4SLinus Torvalds  *
4251da177e4SLinus Torvalds  *	On a success the socket object pointer is returned.
4261da177e4SLinus Torvalds  */
4271da177e4SLinus Torvalds 
4281da177e4SLinus Torvalds struct socket *sockfd_lookup(int fd, int *err)
4291da177e4SLinus Torvalds {
4301da177e4SLinus Torvalds 	struct file *file;
4311da177e4SLinus Torvalds 	struct socket *sock;
4321da177e4SLinus Torvalds 
43389bddce5SStephen Hemminger 	file = fget(fd);
43489bddce5SStephen Hemminger 	if (!file) {
4351da177e4SLinus Torvalds 		*err = -EBADF;
4361da177e4SLinus Torvalds 		return NULL;
4371da177e4SLinus Torvalds 	}
43889bddce5SStephen Hemminger 
4396cb153caSBenjamin LaHaise 	sock = sock_from_file(file, err);
4406cb153caSBenjamin LaHaise 	if (!sock)
4411da177e4SLinus Torvalds 		fput(file);
4426cb153caSBenjamin LaHaise 	return sock;
4431da177e4SLinus Torvalds }
444c6d409cfSEric Dumazet EXPORT_SYMBOL(sockfd_lookup);
4451da177e4SLinus Torvalds 
4466cb153caSBenjamin LaHaise static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
4476cb153caSBenjamin LaHaise {
4486cb153caSBenjamin LaHaise 	struct file *file;
4496cb153caSBenjamin LaHaise 	struct socket *sock;
4506cb153caSBenjamin LaHaise 
4513672558cSHua Zhong 	*err = -EBADF;
4526cb153caSBenjamin LaHaise 	file = fget_light(fd, fput_needed);
4536cb153caSBenjamin LaHaise 	if (file) {
4546cb153caSBenjamin LaHaise 		sock = sock_from_file(file, err);
4556cb153caSBenjamin LaHaise 		if (sock)
4561da177e4SLinus Torvalds 			return sock;
4576cb153caSBenjamin LaHaise 		fput_light(file, *fput_needed);
4586cb153caSBenjamin LaHaise 	}
4596cb153caSBenjamin LaHaise 	return NULL;
4601da177e4SLinus Torvalds }
4611da177e4SLinus Torvalds 
462600e1779SMasatake YAMATO #define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname"
463600e1779SMasatake YAMATO #define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX)
464600e1779SMasatake YAMATO #define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1)
465600e1779SMasatake YAMATO static ssize_t sockfs_getxattr(struct dentry *dentry,
466600e1779SMasatake YAMATO 			       const char *name, void *value, size_t size)
467600e1779SMasatake YAMATO {
468600e1779SMasatake YAMATO 	const char *proto_name;
469600e1779SMasatake YAMATO 	size_t proto_size;
470600e1779SMasatake YAMATO 	int error;
471600e1779SMasatake YAMATO 
472600e1779SMasatake YAMATO 	error = -ENODATA;
473600e1779SMasatake YAMATO 	if (!strncmp(name, XATTR_NAME_SOCKPROTONAME, XATTR_NAME_SOCKPROTONAME_LEN)) {
474600e1779SMasatake YAMATO 		proto_name = dentry->d_name.name;
475600e1779SMasatake YAMATO 		proto_size = strlen(proto_name);
476600e1779SMasatake YAMATO 
477600e1779SMasatake YAMATO 		if (value) {
478600e1779SMasatake YAMATO 			error = -ERANGE;
479600e1779SMasatake YAMATO 			if (proto_size + 1 > size)
480600e1779SMasatake YAMATO 				goto out;
481600e1779SMasatake YAMATO 
482600e1779SMasatake YAMATO 			strncpy(value, proto_name, proto_size + 1);
483600e1779SMasatake YAMATO 		}
484600e1779SMasatake YAMATO 		error = proto_size + 1;
485600e1779SMasatake YAMATO 	}
486600e1779SMasatake YAMATO 
487600e1779SMasatake YAMATO out:
488600e1779SMasatake YAMATO 	return error;
489600e1779SMasatake YAMATO }
490600e1779SMasatake YAMATO 
491600e1779SMasatake YAMATO static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer,
492600e1779SMasatake YAMATO 				size_t size)
493600e1779SMasatake YAMATO {
494600e1779SMasatake YAMATO 	ssize_t len;
495600e1779SMasatake YAMATO 	ssize_t used = 0;
496600e1779SMasatake YAMATO 
497600e1779SMasatake YAMATO 	len = security_inode_listsecurity(dentry->d_inode, buffer, size);
498600e1779SMasatake YAMATO 	if (len < 0)
499600e1779SMasatake YAMATO 		return len;
500600e1779SMasatake YAMATO 	used += len;
501600e1779SMasatake YAMATO 	if (buffer) {
502600e1779SMasatake YAMATO 		if (size < used)
503600e1779SMasatake YAMATO 			return -ERANGE;
504600e1779SMasatake YAMATO 		buffer += len;
505600e1779SMasatake YAMATO 	}
506600e1779SMasatake YAMATO 
507600e1779SMasatake YAMATO 	len = (XATTR_NAME_SOCKPROTONAME_LEN + 1);
508600e1779SMasatake YAMATO 	used += len;
509600e1779SMasatake YAMATO 	if (buffer) {
510600e1779SMasatake YAMATO 		if (size < used)
511600e1779SMasatake YAMATO 			return -ERANGE;
512600e1779SMasatake YAMATO 		memcpy(buffer, XATTR_NAME_SOCKPROTONAME, len);
513600e1779SMasatake YAMATO 		buffer += len;
514600e1779SMasatake YAMATO 	}
515600e1779SMasatake YAMATO 
516600e1779SMasatake YAMATO 	return used;
517600e1779SMasatake YAMATO }
518600e1779SMasatake YAMATO 
519600e1779SMasatake YAMATO static const struct inode_operations sockfs_inode_ops = {
520600e1779SMasatake YAMATO 	.getxattr = sockfs_getxattr,
521600e1779SMasatake YAMATO 	.listxattr = sockfs_listxattr,
522600e1779SMasatake YAMATO };
523600e1779SMasatake YAMATO 
5241da177e4SLinus Torvalds /**
5251da177e4SLinus Torvalds  *	sock_alloc	-	allocate a socket
5261da177e4SLinus Torvalds  *
5271da177e4SLinus Torvalds  *	Allocate a new inode and socket object. The two are bound together
5281da177e4SLinus Torvalds  *	and initialised. The socket is then returned. If we are out of inodes
5291da177e4SLinus Torvalds  *	NULL is returned.
5301da177e4SLinus Torvalds  */
5311da177e4SLinus Torvalds 
5321da177e4SLinus Torvalds static struct socket *sock_alloc(void)
5331da177e4SLinus Torvalds {
5341da177e4SLinus Torvalds 	struct inode *inode;
5351da177e4SLinus Torvalds 	struct socket *sock;
5361da177e4SLinus Torvalds 
537a209dfc7SEric Dumazet 	inode = new_inode_pseudo(sock_mnt->mnt_sb);
5381da177e4SLinus Torvalds 	if (!inode)
5391da177e4SLinus Torvalds 		return NULL;
5401da177e4SLinus Torvalds 
5411da177e4SLinus Torvalds 	sock = SOCKET_I(inode);
5421da177e4SLinus Torvalds 
54329a020d3SEric Dumazet 	kmemcheck_annotate_bitfield(sock, type);
54485fe4025SChristoph Hellwig 	inode->i_ino = get_next_ino();
5451da177e4SLinus Torvalds 	inode->i_mode = S_IFSOCK | S_IRWXUGO;
5468192b0c4SDavid Howells 	inode->i_uid = current_fsuid();
5478192b0c4SDavid Howells 	inode->i_gid = current_fsgid();
548600e1779SMasatake YAMATO 	inode->i_op = &sockfs_inode_ops;
5491da177e4SLinus Torvalds 
55019e8d69cSAlex Shi 	this_cpu_add(sockets_in_use, 1);
5511da177e4SLinus Torvalds 	return sock;
5521da177e4SLinus Torvalds }
5531da177e4SLinus Torvalds 
5541da177e4SLinus Torvalds /*
5551da177e4SLinus Torvalds  *	In theory you can't get an open on this inode, but /proc provides
5561da177e4SLinus Torvalds  *	a back door. Remember to keep it shut otherwise you'll let the
5571da177e4SLinus Torvalds  *	creepy crawlies in.
5581da177e4SLinus Torvalds  */
5591da177e4SLinus Torvalds 
5601da177e4SLinus Torvalds static int sock_no_open(struct inode *irrelevant, struct file *dontcare)
5611da177e4SLinus Torvalds {
5621da177e4SLinus Torvalds 	return -ENXIO;
5631da177e4SLinus Torvalds }
5641da177e4SLinus Torvalds 
5654b6f5d20SArjan van de Ven const struct file_operations bad_sock_fops = {
5661da177e4SLinus Torvalds 	.owner = THIS_MODULE,
5671da177e4SLinus Torvalds 	.open = sock_no_open,
5686038f373SArnd Bergmann 	.llseek = noop_llseek,
5691da177e4SLinus Torvalds };
5701da177e4SLinus Torvalds 
5711da177e4SLinus Torvalds /**
5721da177e4SLinus Torvalds  *	sock_release	-	close a socket
5731da177e4SLinus Torvalds  *	@sock: socket to close
5741da177e4SLinus Torvalds  *
5751da177e4SLinus Torvalds  *	The socket is released from the protocol stack if it has a release
5761da177e4SLinus Torvalds  *	callback, and the inode is then released if the socket is bound to
5771da177e4SLinus Torvalds  *	an inode not a file.
5781da177e4SLinus Torvalds  */
5791da177e4SLinus Torvalds 
5801da177e4SLinus Torvalds void sock_release(struct socket *sock)
5811da177e4SLinus Torvalds {
5821da177e4SLinus Torvalds 	if (sock->ops) {
5831da177e4SLinus Torvalds 		struct module *owner = sock->ops->owner;
5841da177e4SLinus Torvalds 
5851da177e4SLinus Torvalds 		sock->ops->release(sock);
5861da177e4SLinus Torvalds 		sock->ops = NULL;
5871da177e4SLinus Torvalds 		module_put(owner);
5881da177e4SLinus Torvalds 	}
5891da177e4SLinus Torvalds 
590eaefd110SEric Dumazet 	if (rcu_dereference_protected(sock->wq, 1)->fasync_list)
5911da177e4SLinus Torvalds 		printk(KERN_ERR "sock_release: fasync list not empty!\n");
5921da177e4SLinus Torvalds 
593b09e786bSMikulas Patocka 	if (test_bit(SOCK_EXTERNALLY_ALLOCATED, &sock->flags))
594b09e786bSMikulas Patocka 		return;
595b09e786bSMikulas Patocka 
59619e8d69cSAlex Shi 	this_cpu_sub(sockets_in_use, 1);
5971da177e4SLinus Torvalds 	if (!sock->file) {
5981da177e4SLinus Torvalds 		iput(SOCK_INODE(sock));
5991da177e4SLinus Torvalds 		return;
6001da177e4SLinus Torvalds 	}
6011da177e4SLinus Torvalds 	sock->file = NULL;
6021da177e4SLinus Torvalds }
603c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_release);
6041da177e4SLinus Torvalds 
6052244d07bSOliver Hartkopp int sock_tx_timestamp(struct sock *sk, __u8 *tx_flags)
60620d49473SPatrick Ohly {
6072244d07bSOliver Hartkopp 	*tx_flags = 0;
60820d49473SPatrick Ohly 	if (sock_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE))
6092244d07bSOliver Hartkopp 		*tx_flags |= SKBTX_HW_TSTAMP;
61020d49473SPatrick Ohly 	if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE))
6112244d07bSOliver Hartkopp 		*tx_flags |= SKBTX_SW_TSTAMP;
6126e3e939fSJohannes Berg 	if (sock_flag(sk, SOCK_WIFI_STATUS))
6136e3e939fSJohannes Berg 		*tx_flags |= SKBTX_WIFI_STATUS;
61420d49473SPatrick Ohly 	return 0;
61520d49473SPatrick Ohly }
61620d49473SPatrick Ohly EXPORT_SYMBOL(sock_tx_timestamp);
61720d49473SPatrick Ohly 
618228e548eSAnton Blanchard static inline int __sock_sendmsg_nosec(struct kiocb *iocb, struct socket *sock,
6191da177e4SLinus Torvalds 				       struct msghdr *msg, size_t size)
6201da177e4SLinus Torvalds {
6211da177e4SLinus Torvalds 	struct sock_iocb *si = kiocb_to_siocb(iocb);
6221da177e4SLinus Torvalds 
6231da177e4SLinus Torvalds 	si->sock = sock;
6241da177e4SLinus Torvalds 	si->scm = NULL;
6251da177e4SLinus Torvalds 	si->msg = msg;
6261da177e4SLinus Torvalds 	si->size = size;
6271da177e4SLinus Torvalds 
6281da177e4SLinus Torvalds 	return sock->ops->sendmsg(iocb, sock, msg, size);
6291da177e4SLinus Torvalds }
6301da177e4SLinus Torvalds 
631228e548eSAnton Blanchard static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock,
632228e548eSAnton Blanchard 				 struct msghdr *msg, size_t size)
633228e548eSAnton Blanchard {
634228e548eSAnton Blanchard 	int err = security_socket_sendmsg(sock, msg, size);
635228e548eSAnton Blanchard 
636228e548eSAnton Blanchard 	return err ?: __sock_sendmsg_nosec(iocb, sock, msg, size);
637228e548eSAnton Blanchard }
638228e548eSAnton Blanchard 
6391da177e4SLinus Torvalds int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
6401da177e4SLinus Torvalds {
6411da177e4SLinus Torvalds 	struct kiocb iocb;
6421da177e4SLinus Torvalds 	struct sock_iocb siocb;
6431da177e4SLinus Torvalds 	int ret;
6441da177e4SLinus Torvalds 
6451da177e4SLinus Torvalds 	init_sync_kiocb(&iocb, NULL);
6461da177e4SLinus Torvalds 	iocb.private = &siocb;
6471da177e4SLinus Torvalds 	ret = __sock_sendmsg(&iocb, sock, msg, size);
6481da177e4SLinus Torvalds 	if (-EIOCBQUEUED == ret)
6491da177e4SLinus Torvalds 		ret = wait_on_sync_kiocb(&iocb);
6501da177e4SLinus Torvalds 	return ret;
6511da177e4SLinus Torvalds }
652c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_sendmsg);
6531da177e4SLinus Torvalds 
654894dc24cSEric Dumazet static int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg, size_t size)
655228e548eSAnton Blanchard {
656228e548eSAnton Blanchard 	struct kiocb iocb;
657228e548eSAnton Blanchard 	struct sock_iocb siocb;
658228e548eSAnton Blanchard 	int ret;
659228e548eSAnton Blanchard 
660228e548eSAnton Blanchard 	init_sync_kiocb(&iocb, NULL);
661228e548eSAnton Blanchard 	iocb.private = &siocb;
662228e548eSAnton Blanchard 	ret = __sock_sendmsg_nosec(&iocb, sock, msg, size);
663228e548eSAnton Blanchard 	if (-EIOCBQUEUED == ret)
664228e548eSAnton Blanchard 		ret = wait_on_sync_kiocb(&iocb);
665228e548eSAnton Blanchard 	return ret;
666228e548eSAnton Blanchard }
667228e548eSAnton Blanchard 
6681da177e4SLinus Torvalds int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
6691da177e4SLinus Torvalds 		   struct kvec *vec, size_t num, size_t size)
6701da177e4SLinus Torvalds {
6711da177e4SLinus Torvalds 	mm_segment_t oldfs = get_fs();
6721da177e4SLinus Torvalds 	int result;
6731da177e4SLinus Torvalds 
6741da177e4SLinus Torvalds 	set_fs(KERNEL_DS);
6751da177e4SLinus Torvalds 	/*
6761da177e4SLinus Torvalds 	 * the following is safe, since for compiler definitions of kvec and
6771da177e4SLinus Torvalds 	 * iovec are identical, yielding the same in-core layout and alignment
6781da177e4SLinus Torvalds 	 */
67989bddce5SStephen Hemminger 	msg->msg_iov = (struct iovec *)vec;
6801da177e4SLinus Torvalds 	msg->msg_iovlen = num;
6811da177e4SLinus Torvalds 	result = sock_sendmsg(sock, msg, size);
6821da177e4SLinus Torvalds 	set_fs(oldfs);
6831da177e4SLinus Torvalds 	return result;
6841da177e4SLinus Torvalds }
685c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendmsg);
6861da177e4SLinus Torvalds 
68720d49473SPatrick Ohly static int ktime2ts(ktime_t kt, struct timespec *ts)
68820d49473SPatrick Ohly {
68920d49473SPatrick Ohly 	if (kt.tv64) {
69020d49473SPatrick Ohly 		*ts = ktime_to_timespec(kt);
69120d49473SPatrick Ohly 		return 1;
69220d49473SPatrick Ohly 	} else {
69320d49473SPatrick Ohly 		return 0;
69420d49473SPatrick Ohly 	}
69520d49473SPatrick Ohly }
69620d49473SPatrick Ohly 
69792f37fd2SEric Dumazet /*
69892f37fd2SEric Dumazet  * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
69992f37fd2SEric Dumazet  */
70092f37fd2SEric Dumazet void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
70192f37fd2SEric Dumazet 	struct sk_buff *skb)
70292f37fd2SEric Dumazet {
70320d49473SPatrick Ohly 	int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
70420d49473SPatrick Ohly 	struct timespec ts[3];
70520d49473SPatrick Ohly 	int empty = 1;
70620d49473SPatrick Ohly 	struct skb_shared_hwtstamps *shhwtstamps =
70720d49473SPatrick Ohly 		skb_hwtstamps(skb);
70892f37fd2SEric Dumazet 
70920d49473SPatrick Ohly 	/* Race occurred between timestamp enabling and packet
71020d49473SPatrick Ohly 	   receiving.  Fill in the current time for now. */
71120d49473SPatrick Ohly 	if (need_software_tstamp && skb->tstamp.tv64 == 0)
71220d49473SPatrick Ohly 		__net_timestamp(skb);
71320d49473SPatrick Ohly 
71420d49473SPatrick Ohly 	if (need_software_tstamp) {
71592f37fd2SEric Dumazet 		if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
71692f37fd2SEric Dumazet 			struct timeval tv;
71720d49473SPatrick Ohly 			skb_get_timestamp(skb, &tv);
71820d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP,
71920d49473SPatrick Ohly 				 sizeof(tv), &tv);
72092f37fd2SEric Dumazet 		} else {
721842509b8SHagen Paul Pfeifer 			skb_get_timestampns(skb, &ts[0]);
72220d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS,
723842509b8SHagen Paul Pfeifer 				 sizeof(ts[0]), &ts[0]);
72492f37fd2SEric Dumazet 		}
72592f37fd2SEric Dumazet 	}
72692f37fd2SEric Dumazet 
72720d49473SPatrick Ohly 
72820d49473SPatrick Ohly 	memset(ts, 0, sizeof(ts));
72920d49473SPatrick Ohly 	if (skb->tstamp.tv64 &&
73020d49473SPatrick Ohly 	    sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE)) {
73120d49473SPatrick Ohly 		skb_get_timestampns(skb, ts + 0);
73220d49473SPatrick Ohly 		empty = 0;
73320d49473SPatrick Ohly 	}
73420d49473SPatrick Ohly 	if (shhwtstamps) {
73520d49473SPatrick Ohly 		if (sock_flag(sk, SOCK_TIMESTAMPING_SYS_HARDWARE) &&
73620d49473SPatrick Ohly 		    ktime2ts(shhwtstamps->syststamp, ts + 1))
73720d49473SPatrick Ohly 			empty = 0;
73820d49473SPatrick Ohly 		if (sock_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE) &&
73920d49473SPatrick Ohly 		    ktime2ts(shhwtstamps->hwtstamp, ts + 2))
74020d49473SPatrick Ohly 			empty = 0;
74120d49473SPatrick Ohly 	}
74220d49473SPatrick Ohly 	if (!empty)
74320d49473SPatrick Ohly 		put_cmsg(msg, SOL_SOCKET,
74420d49473SPatrick Ohly 			 SCM_TIMESTAMPING, sizeof(ts), &ts);
74520d49473SPatrick Ohly }
7467c81fd8bSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
7477c81fd8bSArnaldo Carvalho de Melo 
7486e3e939fSJohannes Berg void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
7496e3e939fSJohannes Berg 	struct sk_buff *skb)
7506e3e939fSJohannes Berg {
7516e3e939fSJohannes Berg 	int ack;
7526e3e939fSJohannes Berg 
7536e3e939fSJohannes Berg 	if (!sock_flag(sk, SOCK_WIFI_STATUS))
7546e3e939fSJohannes Berg 		return;
7556e3e939fSJohannes Berg 	if (!skb->wifi_acked_valid)
7566e3e939fSJohannes Berg 		return;
7576e3e939fSJohannes Berg 
7586e3e939fSJohannes Berg 	ack = skb->wifi_acked;
7596e3e939fSJohannes Berg 
7606e3e939fSJohannes Berg 	put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack);
7616e3e939fSJohannes Berg }
7626e3e939fSJohannes Berg EXPORT_SYMBOL_GPL(__sock_recv_wifi_status);
7636e3e939fSJohannes Berg 
76411165f14Sstephen hemminger static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk,
76511165f14Sstephen hemminger 				   struct sk_buff *skb)
7663b885787SNeil Horman {
7673b885787SNeil Horman 	if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && skb->dropcount)
7683b885787SNeil Horman 		put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL,
7693b885787SNeil Horman 			sizeof(__u32), &skb->dropcount);
7703b885787SNeil Horman }
7713b885787SNeil Horman 
772767dd033SEric Dumazet void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
7733b885787SNeil Horman 	struct sk_buff *skb)
7743b885787SNeil Horman {
7753b885787SNeil Horman 	sock_recv_timestamp(msg, sk, skb);
7763b885787SNeil Horman 	sock_recv_drops(msg, sk, skb);
7773b885787SNeil Horman }
778767dd033SEric Dumazet EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops);
7793b885787SNeil Horman 
780a2e27255SArnaldo Carvalho de Melo static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock,
7811da177e4SLinus Torvalds 				       struct msghdr *msg, size_t size, int flags)
7821da177e4SLinus Torvalds {
7831da177e4SLinus Torvalds 	struct sock_iocb *si = kiocb_to_siocb(iocb);
7841da177e4SLinus Torvalds 
7851da177e4SLinus Torvalds 	si->sock = sock;
7861da177e4SLinus Torvalds 	si->scm = NULL;
7871da177e4SLinus Torvalds 	si->msg = msg;
7881da177e4SLinus Torvalds 	si->size = size;
7891da177e4SLinus Torvalds 	si->flags = flags;
7901da177e4SLinus Torvalds 
7911da177e4SLinus Torvalds 	return sock->ops->recvmsg(iocb, sock, msg, size, flags);
7921da177e4SLinus Torvalds }
7931da177e4SLinus Torvalds 
794a2e27255SArnaldo Carvalho de Melo static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock,
795a2e27255SArnaldo Carvalho de Melo 				 struct msghdr *msg, size_t size, int flags)
796a2e27255SArnaldo Carvalho de Melo {
797a2e27255SArnaldo Carvalho de Melo 	int err = security_socket_recvmsg(sock, msg, size, flags);
798a2e27255SArnaldo Carvalho de Melo 
799a2e27255SArnaldo Carvalho de Melo 	return err ?: __sock_recvmsg_nosec(iocb, sock, msg, size, flags);
800a2e27255SArnaldo Carvalho de Melo }
801a2e27255SArnaldo Carvalho de Melo 
8021da177e4SLinus Torvalds int sock_recvmsg(struct socket *sock, struct msghdr *msg,
8031da177e4SLinus Torvalds 		 size_t size, int flags)
8041da177e4SLinus Torvalds {
8051da177e4SLinus Torvalds 	struct kiocb iocb;
8061da177e4SLinus Torvalds 	struct sock_iocb siocb;
8071da177e4SLinus Torvalds 	int ret;
8081da177e4SLinus Torvalds 
8091da177e4SLinus Torvalds 	init_sync_kiocb(&iocb, NULL);
8101da177e4SLinus Torvalds 	iocb.private = &siocb;
8111da177e4SLinus Torvalds 	ret = __sock_recvmsg(&iocb, sock, msg, size, flags);
8121da177e4SLinus Torvalds 	if (-EIOCBQUEUED == ret)
8131da177e4SLinus Torvalds 		ret = wait_on_sync_kiocb(&iocb);
8141da177e4SLinus Torvalds 	return ret;
8151da177e4SLinus Torvalds }
816c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_recvmsg);
8171da177e4SLinus Torvalds 
818a2e27255SArnaldo Carvalho de Melo static int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
819a2e27255SArnaldo Carvalho de Melo 			      size_t size, int flags)
820a2e27255SArnaldo Carvalho de Melo {
821a2e27255SArnaldo Carvalho de Melo 	struct kiocb iocb;
822a2e27255SArnaldo Carvalho de Melo 	struct sock_iocb siocb;
823a2e27255SArnaldo Carvalho de Melo 	int ret;
824a2e27255SArnaldo Carvalho de Melo 
825a2e27255SArnaldo Carvalho de Melo 	init_sync_kiocb(&iocb, NULL);
826a2e27255SArnaldo Carvalho de Melo 	iocb.private = &siocb;
827a2e27255SArnaldo Carvalho de Melo 	ret = __sock_recvmsg_nosec(&iocb, sock, msg, size, flags);
828a2e27255SArnaldo Carvalho de Melo 	if (-EIOCBQUEUED == ret)
829a2e27255SArnaldo Carvalho de Melo 		ret = wait_on_sync_kiocb(&iocb);
830a2e27255SArnaldo Carvalho de Melo 	return ret;
831a2e27255SArnaldo Carvalho de Melo }
832a2e27255SArnaldo Carvalho de Melo 
833c1249c0aSMartin Lucina /**
834c1249c0aSMartin Lucina  * kernel_recvmsg - Receive a message from a socket (kernel space)
835c1249c0aSMartin Lucina  * @sock:       The socket to receive the message from
836c1249c0aSMartin Lucina  * @msg:        Received message
837c1249c0aSMartin Lucina  * @vec:        Input s/g array for message data
838c1249c0aSMartin Lucina  * @num:        Size of input s/g array
839c1249c0aSMartin Lucina  * @size:       Number of bytes to read
840c1249c0aSMartin Lucina  * @flags:      Message flags (MSG_DONTWAIT, etc...)
841c1249c0aSMartin Lucina  *
842c1249c0aSMartin Lucina  * On return the msg structure contains the scatter/gather array passed in the
843c1249c0aSMartin Lucina  * vec argument. The array is modified so that it consists of the unfilled
844c1249c0aSMartin Lucina  * portion of the original array.
845c1249c0aSMartin Lucina  *
846c1249c0aSMartin Lucina  * The returned value is the total number of bytes received, or an error.
847c1249c0aSMartin Lucina  */
8481da177e4SLinus Torvalds int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
84989bddce5SStephen Hemminger 		   struct kvec *vec, size_t num, size_t size, int flags)
8501da177e4SLinus Torvalds {
8511da177e4SLinus Torvalds 	mm_segment_t oldfs = get_fs();
8521da177e4SLinus Torvalds 	int result;
8531da177e4SLinus Torvalds 
8541da177e4SLinus Torvalds 	set_fs(KERNEL_DS);
8551da177e4SLinus Torvalds 	/*
8561da177e4SLinus Torvalds 	 * the following is safe, since for compiler definitions of kvec and
8571da177e4SLinus Torvalds 	 * iovec are identical, yielding the same in-core layout and alignment
8581da177e4SLinus Torvalds 	 */
85989bddce5SStephen Hemminger 	msg->msg_iov = (struct iovec *)vec, msg->msg_iovlen = num;
8601da177e4SLinus Torvalds 	result = sock_recvmsg(sock, msg, size, flags);
8611da177e4SLinus Torvalds 	set_fs(oldfs);
8621da177e4SLinus Torvalds 	return result;
8631da177e4SLinus Torvalds }
864c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_recvmsg);
8651da177e4SLinus Torvalds 
8661da177e4SLinus Torvalds static void sock_aio_dtor(struct kiocb *iocb)
8671da177e4SLinus Torvalds {
8681da177e4SLinus Torvalds 	kfree(iocb->private);
8691da177e4SLinus Torvalds }
8701da177e4SLinus Torvalds 
87120380731SArnaldo Carvalho de Melo static ssize_t sock_sendpage(struct file *file, struct page *page,
8721da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more)
8731da177e4SLinus Torvalds {
8741da177e4SLinus Torvalds 	struct socket *sock;
8751da177e4SLinus Torvalds 	int flags;
8761da177e4SLinus Torvalds 
877b69aee04SEric Dumazet 	sock = file->private_data;
8781da177e4SLinus Torvalds 
87935f9c09fSEric Dumazet 	flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
88035f9c09fSEric Dumazet 	/* more is a combination of MSG_MORE and MSG_SENDPAGE_NOTLAST */
88135f9c09fSEric Dumazet 	flags |= more;
8821da177e4SLinus Torvalds 
883e6949583SLinus Torvalds 	return kernel_sendpage(sock, page, offset, size, flags);
8841da177e4SLinus Torvalds }
8851da177e4SLinus Torvalds 
8869c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
8879c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
8889c55e01cSJens Axboe 				unsigned int flags)
8899c55e01cSJens Axboe {
8909c55e01cSJens Axboe 	struct socket *sock = file->private_data;
8919c55e01cSJens Axboe 
892997b37daSRémi Denis-Courmont 	if (unlikely(!sock->ops->splice_read))
893997b37daSRémi Denis-Courmont 		return -EINVAL;
894997b37daSRémi Denis-Courmont 
8959c55e01cSJens Axboe 	return sock->ops->splice_read(sock, ppos, pipe, len, flags);
8969c55e01cSJens Axboe }
8979c55e01cSJens Axboe 
898ce1d4d3eSChristoph Hellwig static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
89989bddce5SStephen Hemminger 					 struct sock_iocb *siocb)
900ce1d4d3eSChristoph Hellwig {
901ce1d4d3eSChristoph Hellwig 	if (!is_sync_kiocb(iocb)) {
902ce1d4d3eSChristoph Hellwig 		siocb = kmalloc(sizeof(*siocb), GFP_KERNEL);
903ce1d4d3eSChristoph Hellwig 		if (!siocb)
904ce1d4d3eSChristoph Hellwig 			return NULL;
905ce1d4d3eSChristoph Hellwig 		iocb->ki_dtor = sock_aio_dtor;
906ce1d4d3eSChristoph Hellwig 	}
907ce1d4d3eSChristoph Hellwig 
908ce1d4d3eSChristoph Hellwig 	siocb->kiocb = iocb;
909ce1d4d3eSChristoph Hellwig 	iocb->private = siocb;
910ce1d4d3eSChristoph Hellwig 	return siocb;
911ce1d4d3eSChristoph Hellwig }
912ce1d4d3eSChristoph Hellwig 
913ce1d4d3eSChristoph Hellwig static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb,
914027445c3SBadari Pulavarty 		struct file *file, const struct iovec *iov,
91589bddce5SStephen Hemminger 		unsigned long nr_segs)
916ce1d4d3eSChristoph Hellwig {
917ce1d4d3eSChristoph Hellwig 	struct socket *sock = file->private_data;
918ce1d4d3eSChristoph Hellwig 	size_t size = 0;
919ce1d4d3eSChristoph Hellwig 	int i;
920ce1d4d3eSChristoph Hellwig 
921ce1d4d3eSChristoph Hellwig 	for (i = 0; i < nr_segs; i++)
922ce1d4d3eSChristoph Hellwig 		size += iov[i].iov_len;
923ce1d4d3eSChristoph Hellwig 
924ce1d4d3eSChristoph Hellwig 	msg->msg_name = NULL;
925ce1d4d3eSChristoph Hellwig 	msg->msg_namelen = 0;
926ce1d4d3eSChristoph Hellwig 	msg->msg_control = NULL;
927ce1d4d3eSChristoph Hellwig 	msg->msg_controllen = 0;
928ce1d4d3eSChristoph Hellwig 	msg->msg_iov = (struct iovec *)iov;
929ce1d4d3eSChristoph Hellwig 	msg->msg_iovlen = nr_segs;
930ce1d4d3eSChristoph Hellwig 	msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
931ce1d4d3eSChristoph Hellwig 
932ce1d4d3eSChristoph Hellwig 	return __sock_recvmsg(iocb, sock, msg, size, msg->msg_flags);
933ce1d4d3eSChristoph Hellwig }
934ce1d4d3eSChristoph Hellwig 
935027445c3SBadari Pulavarty static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
936027445c3SBadari Pulavarty 				unsigned long nr_segs, loff_t pos)
937ce1d4d3eSChristoph Hellwig {
938ce1d4d3eSChristoph Hellwig 	struct sock_iocb siocb, *x;
939ce1d4d3eSChristoph Hellwig 
940ce1d4d3eSChristoph Hellwig 	if (pos != 0)
941ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
942027445c3SBadari Pulavarty 
943027445c3SBadari Pulavarty 	if (iocb->ki_left == 0)	/* Match SYS5 behaviour */
944ce1d4d3eSChristoph Hellwig 		return 0;
945ce1d4d3eSChristoph Hellwig 
946027445c3SBadari Pulavarty 
947027445c3SBadari Pulavarty 	x = alloc_sock_iocb(iocb, &siocb);
948ce1d4d3eSChristoph Hellwig 	if (!x)
949ce1d4d3eSChristoph Hellwig 		return -ENOMEM;
950027445c3SBadari Pulavarty 	return do_sock_read(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
951ce1d4d3eSChristoph Hellwig }
952ce1d4d3eSChristoph Hellwig 
953ce1d4d3eSChristoph Hellwig static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb,
954027445c3SBadari Pulavarty 			struct file *file, const struct iovec *iov,
95589bddce5SStephen Hemminger 			unsigned long nr_segs)
956ce1d4d3eSChristoph Hellwig {
957ce1d4d3eSChristoph Hellwig 	struct socket *sock = file->private_data;
958ce1d4d3eSChristoph Hellwig 	size_t size = 0;
959ce1d4d3eSChristoph Hellwig 	int i;
960ce1d4d3eSChristoph Hellwig 
961ce1d4d3eSChristoph Hellwig 	for (i = 0; i < nr_segs; i++)
962ce1d4d3eSChristoph Hellwig 		size += iov[i].iov_len;
963ce1d4d3eSChristoph Hellwig 
964ce1d4d3eSChristoph Hellwig 	msg->msg_name = NULL;
965ce1d4d3eSChristoph Hellwig 	msg->msg_namelen = 0;
966ce1d4d3eSChristoph Hellwig 	msg->msg_control = NULL;
967ce1d4d3eSChristoph Hellwig 	msg->msg_controllen = 0;
968ce1d4d3eSChristoph Hellwig 	msg->msg_iov = (struct iovec *)iov;
969ce1d4d3eSChristoph Hellwig 	msg->msg_iovlen = nr_segs;
970ce1d4d3eSChristoph Hellwig 	msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
971ce1d4d3eSChristoph Hellwig 	if (sock->type == SOCK_SEQPACKET)
972ce1d4d3eSChristoph Hellwig 		msg->msg_flags |= MSG_EOR;
973ce1d4d3eSChristoph Hellwig 
974ce1d4d3eSChristoph Hellwig 	return __sock_sendmsg(iocb, sock, msg, size);
975ce1d4d3eSChristoph Hellwig }
976ce1d4d3eSChristoph Hellwig 
977027445c3SBadari Pulavarty static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
978027445c3SBadari Pulavarty 			  unsigned long nr_segs, loff_t pos)
9791da177e4SLinus Torvalds {
980ce1d4d3eSChristoph Hellwig 	struct sock_iocb siocb, *x;
9811da177e4SLinus Torvalds 
982ce1d4d3eSChristoph Hellwig 	if (pos != 0)
983ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
984027445c3SBadari Pulavarty 
985027445c3SBadari Pulavarty 	x = alloc_sock_iocb(iocb, &siocb);
986ce1d4d3eSChristoph Hellwig 	if (!x)
987ce1d4d3eSChristoph Hellwig 		return -ENOMEM;
988ce1d4d3eSChristoph Hellwig 
989027445c3SBadari Pulavarty 	return do_sock_write(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
9901da177e4SLinus Torvalds }
9911da177e4SLinus Torvalds 
9921da177e4SLinus Torvalds /*
9931da177e4SLinus Torvalds  * Atomic setting of ioctl hooks to avoid race
9941da177e4SLinus Torvalds  * with module unload.
9951da177e4SLinus Torvalds  */
9961da177e4SLinus Torvalds 
9974a3e2f71SArjan van de Ven static DEFINE_MUTEX(br_ioctl_mutex);
998c6d409cfSEric Dumazet static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg);
9991da177e4SLinus Torvalds 
1000881d966bSEric W. Biederman void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *))
10011da177e4SLinus Torvalds {
10024a3e2f71SArjan van de Ven 	mutex_lock(&br_ioctl_mutex);
10031da177e4SLinus Torvalds 	br_ioctl_hook = hook;
10044a3e2f71SArjan van de Ven 	mutex_unlock(&br_ioctl_mutex);
10051da177e4SLinus Torvalds }
10061da177e4SLinus Torvalds EXPORT_SYMBOL(brioctl_set);
10071da177e4SLinus Torvalds 
10084a3e2f71SArjan van de Ven static DEFINE_MUTEX(vlan_ioctl_mutex);
1009881d966bSEric W. Biederman static int (*vlan_ioctl_hook) (struct net *, void __user *arg);
10101da177e4SLinus Torvalds 
1011881d966bSEric W. Biederman void vlan_ioctl_set(int (*hook) (struct net *, void __user *))
10121da177e4SLinus Torvalds {
10134a3e2f71SArjan van de Ven 	mutex_lock(&vlan_ioctl_mutex);
10141da177e4SLinus Torvalds 	vlan_ioctl_hook = hook;
10154a3e2f71SArjan van de Ven 	mutex_unlock(&vlan_ioctl_mutex);
10161da177e4SLinus Torvalds }
10171da177e4SLinus Torvalds EXPORT_SYMBOL(vlan_ioctl_set);
10181da177e4SLinus Torvalds 
10194a3e2f71SArjan van de Ven static DEFINE_MUTEX(dlci_ioctl_mutex);
10201da177e4SLinus Torvalds static int (*dlci_ioctl_hook) (unsigned int, void __user *);
10211da177e4SLinus Torvalds 
10221da177e4SLinus Torvalds void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
10231da177e4SLinus Torvalds {
10244a3e2f71SArjan van de Ven 	mutex_lock(&dlci_ioctl_mutex);
10251da177e4SLinus Torvalds 	dlci_ioctl_hook = hook;
10264a3e2f71SArjan van de Ven 	mutex_unlock(&dlci_ioctl_mutex);
10271da177e4SLinus Torvalds }
10281da177e4SLinus Torvalds EXPORT_SYMBOL(dlci_ioctl_set);
10291da177e4SLinus Torvalds 
10306b96018bSArnd Bergmann static long sock_do_ioctl(struct net *net, struct socket *sock,
10316b96018bSArnd Bergmann 				 unsigned int cmd, unsigned long arg)
10326b96018bSArnd Bergmann {
10336b96018bSArnd Bergmann 	int err;
10346b96018bSArnd Bergmann 	void __user *argp = (void __user *)arg;
10356b96018bSArnd Bergmann 
10366b96018bSArnd Bergmann 	err = sock->ops->ioctl(sock, cmd, arg);
10376b96018bSArnd Bergmann 
10386b96018bSArnd Bergmann 	/*
10396b96018bSArnd Bergmann 	 * If this ioctl is unknown try to hand it down
10406b96018bSArnd Bergmann 	 * to the NIC driver.
10416b96018bSArnd Bergmann 	 */
10426b96018bSArnd Bergmann 	if (err == -ENOIOCTLCMD)
10436b96018bSArnd Bergmann 		err = dev_ioctl(net, cmd, argp);
10446b96018bSArnd Bergmann 
10456b96018bSArnd Bergmann 	return err;
10466b96018bSArnd Bergmann }
10476b96018bSArnd Bergmann 
10481da177e4SLinus Torvalds /*
10491da177e4SLinus Torvalds  *	With an ioctl, arg may well be a user mode pointer, but we don't know
10501da177e4SLinus Torvalds  *	what to do with it - that's up to the protocol still.
10511da177e4SLinus Torvalds  */
10521da177e4SLinus Torvalds 
10531da177e4SLinus Torvalds static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
10541da177e4SLinus Torvalds {
10551da177e4SLinus Torvalds 	struct socket *sock;
1056881d966bSEric W. Biederman 	struct sock *sk;
10571da177e4SLinus Torvalds 	void __user *argp = (void __user *)arg;
10581da177e4SLinus Torvalds 	int pid, err;
1059881d966bSEric W. Biederman 	struct net *net;
10601da177e4SLinus Torvalds 
1061b69aee04SEric Dumazet 	sock = file->private_data;
1062881d966bSEric W. Biederman 	sk = sock->sk;
10633b1e0a65SYOSHIFUJI Hideaki 	net = sock_net(sk);
10641da177e4SLinus Torvalds 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
1065881d966bSEric W. Biederman 		err = dev_ioctl(net, cmd, argp);
10661da177e4SLinus Torvalds 	} else
10673d23e349SJohannes Berg #ifdef CONFIG_WEXT_CORE
10681da177e4SLinus Torvalds 	if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
1069881d966bSEric W. Biederman 		err = dev_ioctl(net, cmd, argp);
10701da177e4SLinus Torvalds 	} else
10713d23e349SJohannes Berg #endif
10721da177e4SLinus Torvalds 		switch (cmd) {
10731da177e4SLinus Torvalds 		case FIOSETOWN:
10741da177e4SLinus Torvalds 		case SIOCSPGRP:
10751da177e4SLinus Torvalds 			err = -EFAULT;
10761da177e4SLinus Torvalds 			if (get_user(pid, (int __user *)argp))
10771da177e4SLinus Torvalds 				break;
10781da177e4SLinus Torvalds 			err = f_setown(sock->file, pid, 1);
10791da177e4SLinus Torvalds 			break;
10801da177e4SLinus Torvalds 		case FIOGETOWN:
10811da177e4SLinus Torvalds 		case SIOCGPGRP:
1082609d7fa9SEric W. Biederman 			err = put_user(f_getown(sock->file),
108389bddce5SStephen Hemminger 				       (int __user *)argp);
10841da177e4SLinus Torvalds 			break;
10851da177e4SLinus Torvalds 		case SIOCGIFBR:
10861da177e4SLinus Torvalds 		case SIOCSIFBR:
10871da177e4SLinus Torvalds 		case SIOCBRADDBR:
10881da177e4SLinus Torvalds 		case SIOCBRDELBR:
10891da177e4SLinus Torvalds 			err = -ENOPKG;
10901da177e4SLinus Torvalds 			if (!br_ioctl_hook)
10911da177e4SLinus Torvalds 				request_module("bridge");
10921da177e4SLinus Torvalds 
10934a3e2f71SArjan van de Ven 			mutex_lock(&br_ioctl_mutex);
10941da177e4SLinus Torvalds 			if (br_ioctl_hook)
1095881d966bSEric W. Biederman 				err = br_ioctl_hook(net, cmd, argp);
10964a3e2f71SArjan van de Ven 			mutex_unlock(&br_ioctl_mutex);
10971da177e4SLinus Torvalds 			break;
10981da177e4SLinus Torvalds 		case SIOCGIFVLAN:
10991da177e4SLinus Torvalds 		case SIOCSIFVLAN:
11001da177e4SLinus Torvalds 			err = -ENOPKG;
11011da177e4SLinus Torvalds 			if (!vlan_ioctl_hook)
11021da177e4SLinus Torvalds 				request_module("8021q");
11031da177e4SLinus Torvalds 
11044a3e2f71SArjan van de Ven 			mutex_lock(&vlan_ioctl_mutex);
11051da177e4SLinus Torvalds 			if (vlan_ioctl_hook)
1106881d966bSEric W. Biederman 				err = vlan_ioctl_hook(net, argp);
11074a3e2f71SArjan van de Ven 			mutex_unlock(&vlan_ioctl_mutex);
11081da177e4SLinus Torvalds 			break;
11091da177e4SLinus Torvalds 		case SIOCADDDLCI:
11101da177e4SLinus Torvalds 		case SIOCDELDLCI:
11111da177e4SLinus Torvalds 			err = -ENOPKG;
11121da177e4SLinus Torvalds 			if (!dlci_ioctl_hook)
11131da177e4SLinus Torvalds 				request_module("dlci");
11141da177e4SLinus Torvalds 
11154a3e2f71SArjan van de Ven 			mutex_lock(&dlci_ioctl_mutex);
11167512cbf6SPavel Emelyanov 			if (dlci_ioctl_hook)
11171da177e4SLinus Torvalds 				err = dlci_ioctl_hook(cmd, argp);
11184a3e2f71SArjan van de Ven 			mutex_unlock(&dlci_ioctl_mutex);
11191da177e4SLinus Torvalds 			break;
11201da177e4SLinus Torvalds 		default:
11216b96018bSArnd Bergmann 			err = sock_do_ioctl(net, sock, cmd, arg);
11221da177e4SLinus Torvalds 			break;
11231da177e4SLinus Torvalds 		}
11241da177e4SLinus Torvalds 	return err;
11251da177e4SLinus Torvalds }
11261da177e4SLinus Torvalds 
11271da177e4SLinus Torvalds int sock_create_lite(int family, int type, int protocol, struct socket **res)
11281da177e4SLinus Torvalds {
11291da177e4SLinus Torvalds 	int err;
11301da177e4SLinus Torvalds 	struct socket *sock = NULL;
11311da177e4SLinus Torvalds 
11321da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, 1);
11331da177e4SLinus Torvalds 	if (err)
11341da177e4SLinus Torvalds 		goto out;
11351da177e4SLinus Torvalds 
11361da177e4SLinus Torvalds 	sock = sock_alloc();
11371da177e4SLinus Torvalds 	if (!sock) {
11381da177e4SLinus Torvalds 		err = -ENOMEM;
11391da177e4SLinus Torvalds 		goto out;
11401da177e4SLinus Torvalds 	}
11411da177e4SLinus Torvalds 
11421da177e4SLinus Torvalds 	sock->type = type;
11437420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, 1);
11447420ed23SVenkat Yekkirala 	if (err)
11457420ed23SVenkat Yekkirala 		goto out_release;
11467420ed23SVenkat Yekkirala 
11471da177e4SLinus Torvalds out:
11481da177e4SLinus Torvalds 	*res = sock;
11491da177e4SLinus Torvalds 	return err;
11507420ed23SVenkat Yekkirala out_release:
11517420ed23SVenkat Yekkirala 	sock_release(sock);
11527420ed23SVenkat Yekkirala 	sock = NULL;
11537420ed23SVenkat Yekkirala 	goto out;
11541da177e4SLinus Torvalds }
1155c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_lite);
11561da177e4SLinus Torvalds 
11571da177e4SLinus Torvalds /* No kernel lock held - perfect */
11581da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file, poll_table *wait)
11591da177e4SLinus Torvalds {
11601da177e4SLinus Torvalds 	struct socket *sock;
11611da177e4SLinus Torvalds 
11621da177e4SLinus Torvalds 	/*
11631da177e4SLinus Torvalds 	 *      We can't return errors to poll, so it's either yes or no.
11641da177e4SLinus Torvalds 	 */
1165b69aee04SEric Dumazet 	sock = file->private_data;
11661da177e4SLinus Torvalds 	return sock->ops->poll(file, sock, wait);
11671da177e4SLinus Torvalds }
11681da177e4SLinus Torvalds 
11691da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma)
11701da177e4SLinus Torvalds {
1171b69aee04SEric Dumazet 	struct socket *sock = file->private_data;
11721da177e4SLinus Torvalds 
11731da177e4SLinus Torvalds 	return sock->ops->mmap(file, sock, vma);
11741da177e4SLinus Torvalds }
11751da177e4SLinus Torvalds 
117620380731SArnaldo Carvalho de Melo static int sock_close(struct inode *inode, struct file *filp)
11771da177e4SLinus Torvalds {
11781da177e4SLinus Torvalds 	/*
11791da177e4SLinus Torvalds 	 *      It was possible the inode is NULL we were
11801da177e4SLinus Torvalds 	 *      closing an unfinished socket.
11811da177e4SLinus Torvalds 	 */
11821da177e4SLinus Torvalds 
118389bddce5SStephen Hemminger 	if (!inode) {
11841da177e4SLinus Torvalds 		printk(KERN_DEBUG "sock_close: NULL inode\n");
11851da177e4SLinus Torvalds 		return 0;
11861da177e4SLinus Torvalds 	}
11871da177e4SLinus Torvalds 	sock_release(SOCKET_I(inode));
11881da177e4SLinus Torvalds 	return 0;
11891da177e4SLinus Torvalds }
11901da177e4SLinus Torvalds 
11911da177e4SLinus Torvalds /*
11921da177e4SLinus Torvalds  *	Update the socket async list
11931da177e4SLinus Torvalds  *
11941da177e4SLinus Torvalds  *	Fasync_list locking strategy.
11951da177e4SLinus Torvalds  *
11961da177e4SLinus Torvalds  *	1. fasync_list is modified only under process context socket lock
11971da177e4SLinus Torvalds  *	   i.e. under semaphore.
11981da177e4SLinus Torvalds  *	2. fasync_list is used under read_lock(&sk->sk_callback_lock)
1199989a2979SEric Dumazet  *	   or under socket lock
12001da177e4SLinus Torvalds  */
12011da177e4SLinus Torvalds 
12021da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on)
12031da177e4SLinus Torvalds {
1204989a2979SEric Dumazet 	struct socket *sock = filp->private_data;
1205989a2979SEric Dumazet 	struct sock *sk = sock->sk;
1206eaefd110SEric Dumazet 	struct socket_wq *wq;
12071da177e4SLinus Torvalds 
1208989a2979SEric Dumazet 	if (sk == NULL)
12091da177e4SLinus Torvalds 		return -EINVAL;
12101da177e4SLinus Torvalds 
12111da177e4SLinus Torvalds 	lock_sock(sk);
1212eaefd110SEric Dumazet 	wq = rcu_dereference_protected(sock->wq, sock_owned_by_user(sk));
1213eaefd110SEric Dumazet 	fasync_helper(fd, filp, on, &wq->fasync_list);
12141da177e4SLinus Torvalds 
1215eaefd110SEric Dumazet 	if (!wq->fasync_list)
1216bcdce719SEric Dumazet 		sock_reset_flag(sk, SOCK_FASYNC);
1217989a2979SEric Dumazet 	else
1218989a2979SEric Dumazet 		sock_set_flag(sk, SOCK_FASYNC);
12191da177e4SLinus Torvalds 
1220989a2979SEric Dumazet 	release_sock(sk);
12211da177e4SLinus Torvalds 	return 0;
12221da177e4SLinus Torvalds }
12231da177e4SLinus Torvalds 
122443815482SEric Dumazet /* This function may be called only under socket lock or callback_lock or rcu_lock */
12251da177e4SLinus Torvalds 
12261da177e4SLinus Torvalds int sock_wake_async(struct socket *sock, int how, int band)
12271da177e4SLinus Torvalds {
122843815482SEric Dumazet 	struct socket_wq *wq;
122943815482SEric Dumazet 
123043815482SEric Dumazet 	if (!sock)
12311da177e4SLinus Torvalds 		return -1;
123243815482SEric Dumazet 	rcu_read_lock();
123343815482SEric Dumazet 	wq = rcu_dereference(sock->wq);
123443815482SEric Dumazet 	if (!wq || !wq->fasync_list) {
123543815482SEric Dumazet 		rcu_read_unlock();
123643815482SEric Dumazet 		return -1;
123743815482SEric Dumazet 	}
123889bddce5SStephen Hemminger 	switch (how) {
12398d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_WAITD:
12401da177e4SLinus Torvalds 		if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
12411da177e4SLinus Torvalds 			break;
12421da177e4SLinus Torvalds 		goto call_kill;
12438d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_SPACE:
12441da177e4SLinus Torvalds 		if (!test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags))
12451da177e4SLinus Torvalds 			break;
12461da177e4SLinus Torvalds 		/* fall through */
12478d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_IO:
12481da177e4SLinus Torvalds call_kill:
124943815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGIO, band);
12501da177e4SLinus Torvalds 		break;
12518d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_URG:
125243815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGURG, band);
12531da177e4SLinus Torvalds 	}
125443815482SEric Dumazet 	rcu_read_unlock();
12551da177e4SLinus Torvalds 	return 0;
12561da177e4SLinus Torvalds }
1257c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_wake_async);
12581da177e4SLinus Torvalds 
1259721db93aSPavel Emelyanov int __sock_create(struct net *net, int family, int type, int protocol,
126089bddce5SStephen Hemminger 			 struct socket **res, int kern)
12611da177e4SLinus Torvalds {
12621da177e4SLinus Torvalds 	int err;
12631da177e4SLinus Torvalds 	struct socket *sock;
126455737fdaSStephen Hemminger 	const struct net_proto_family *pf;
12651da177e4SLinus Torvalds 
12661da177e4SLinus Torvalds 	/*
12671da177e4SLinus Torvalds 	 *      Check protocol is in range
12681da177e4SLinus Torvalds 	 */
12691da177e4SLinus Torvalds 	if (family < 0 || family >= NPROTO)
12701da177e4SLinus Torvalds 		return -EAFNOSUPPORT;
12711da177e4SLinus Torvalds 	if (type < 0 || type >= SOCK_MAX)
12721da177e4SLinus Torvalds 		return -EINVAL;
12731da177e4SLinus Torvalds 
12741da177e4SLinus Torvalds 	/* Compatibility.
12751da177e4SLinus Torvalds 
12761da177e4SLinus Torvalds 	   This uglymoron is moved from INET layer to here to avoid
12771da177e4SLinus Torvalds 	   deadlock in module load.
12781da177e4SLinus Torvalds 	 */
12791da177e4SLinus Torvalds 	if (family == PF_INET && type == SOCK_PACKET) {
12801da177e4SLinus Torvalds 		static int warned;
12811da177e4SLinus Torvalds 		if (!warned) {
12821da177e4SLinus Torvalds 			warned = 1;
128389bddce5SStephen Hemminger 			printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)\n",
128489bddce5SStephen Hemminger 			       current->comm);
12851da177e4SLinus Torvalds 		}
12861da177e4SLinus Torvalds 		family = PF_PACKET;
12871da177e4SLinus Torvalds 	}
12881da177e4SLinus Torvalds 
12891da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, kern);
12901da177e4SLinus Torvalds 	if (err)
12911da177e4SLinus Torvalds 		return err;
12921da177e4SLinus Torvalds 
129355737fdaSStephen Hemminger 	/*
129455737fdaSStephen Hemminger 	 *	Allocate the socket and allow the family to set things up. if
129555737fdaSStephen Hemminger 	 *	the protocol is 0, the family is instructed to select an appropriate
129655737fdaSStephen Hemminger 	 *	default.
129755737fdaSStephen Hemminger 	 */
129855737fdaSStephen Hemminger 	sock = sock_alloc();
129955737fdaSStephen Hemminger 	if (!sock) {
1300e87cc472SJoe Perches 		net_warn_ratelimited("socket: no more sockets\n");
130155737fdaSStephen Hemminger 		return -ENFILE;	/* Not exactly a match, but its the
130255737fdaSStephen Hemminger 				   closest posix thing */
130355737fdaSStephen Hemminger 	}
130455737fdaSStephen Hemminger 
130555737fdaSStephen Hemminger 	sock->type = type;
130655737fdaSStephen Hemminger 
130795a5afcaSJohannes Berg #ifdef CONFIG_MODULES
13081da177e4SLinus Torvalds 	/* Attempt to load a protocol module if the find failed.
13091da177e4SLinus Torvalds 	 *
13101da177e4SLinus Torvalds 	 * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
13111da177e4SLinus Torvalds 	 * requested real, full-featured networking support upon configuration.
13121da177e4SLinus Torvalds 	 * Otherwise module support will break!
13131da177e4SLinus Torvalds 	 */
1314190683a9SEric Dumazet 	if (rcu_access_pointer(net_families[family]) == NULL)
13151da177e4SLinus Torvalds 		request_module("net-pf-%d", family);
13161da177e4SLinus Torvalds #endif
13171da177e4SLinus Torvalds 
131855737fdaSStephen Hemminger 	rcu_read_lock();
131955737fdaSStephen Hemminger 	pf = rcu_dereference(net_families[family]);
13201da177e4SLinus Torvalds 	err = -EAFNOSUPPORT;
132155737fdaSStephen Hemminger 	if (!pf)
132255737fdaSStephen Hemminger 		goto out_release;
13231da177e4SLinus Torvalds 
13241da177e4SLinus Torvalds 	/*
13251da177e4SLinus Torvalds 	 * We will call the ->create function, that possibly is in a loadable
13261da177e4SLinus Torvalds 	 * module, so we have to bump that loadable module refcnt first.
13271da177e4SLinus Torvalds 	 */
132855737fdaSStephen Hemminger 	if (!try_module_get(pf->owner))
13291da177e4SLinus Torvalds 		goto out_release;
13301da177e4SLinus Torvalds 
133155737fdaSStephen Hemminger 	/* Now protected by module ref count */
133255737fdaSStephen Hemminger 	rcu_read_unlock();
133355737fdaSStephen Hemminger 
13343f378b68SEric Paris 	err = pf->create(net, sock, protocol, kern);
133555737fdaSStephen Hemminger 	if (err < 0)
13361da177e4SLinus Torvalds 		goto out_module_put;
1337a79af59eSFrank Filz 
13381da177e4SLinus Torvalds 	/*
13391da177e4SLinus Torvalds 	 * Now to bump the refcnt of the [loadable] module that owns this
13401da177e4SLinus Torvalds 	 * socket at sock_release time we decrement its refcnt.
13411da177e4SLinus Torvalds 	 */
134255737fdaSStephen Hemminger 	if (!try_module_get(sock->ops->owner))
134355737fdaSStephen Hemminger 		goto out_module_busy;
134455737fdaSStephen Hemminger 
13451da177e4SLinus Torvalds 	/*
13461da177e4SLinus Torvalds 	 * Now that we're done with the ->create function, the [loadable]
13471da177e4SLinus Torvalds 	 * module can have its refcnt decremented
13481da177e4SLinus Torvalds 	 */
134955737fdaSStephen Hemminger 	module_put(pf->owner);
13507420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, kern);
13517420ed23SVenkat Yekkirala 	if (err)
13523b185525SHerbert Xu 		goto out_sock_release;
135355737fdaSStephen Hemminger 	*res = sock;
13541da177e4SLinus Torvalds 
135555737fdaSStephen Hemminger 	return 0;
135655737fdaSStephen Hemminger 
135755737fdaSStephen Hemminger out_module_busy:
135855737fdaSStephen Hemminger 	err = -EAFNOSUPPORT;
13591da177e4SLinus Torvalds out_module_put:
136055737fdaSStephen Hemminger 	sock->ops = NULL;
136155737fdaSStephen Hemminger 	module_put(pf->owner);
136255737fdaSStephen Hemminger out_sock_release:
13631da177e4SLinus Torvalds 	sock_release(sock);
136455737fdaSStephen Hemminger 	return err;
136555737fdaSStephen Hemminger 
136655737fdaSStephen Hemminger out_release:
136755737fdaSStephen Hemminger 	rcu_read_unlock();
136855737fdaSStephen Hemminger 	goto out_sock_release;
13691da177e4SLinus Torvalds }
1370721db93aSPavel Emelyanov EXPORT_SYMBOL(__sock_create);
13711da177e4SLinus Torvalds 
13721da177e4SLinus Torvalds int sock_create(int family, int type, int protocol, struct socket **res)
13731da177e4SLinus Torvalds {
13741b8d7ae4SEric W. Biederman 	return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
13751da177e4SLinus Torvalds }
1376c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create);
13771da177e4SLinus Torvalds 
13781da177e4SLinus Torvalds int sock_create_kern(int family, int type, int protocol, struct socket **res)
13791da177e4SLinus Torvalds {
13801b8d7ae4SEric W. Biederman 	return __sock_create(&init_net, family, type, protocol, res, 1);
13811da177e4SLinus Torvalds }
1382c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_kern);
13831da177e4SLinus Torvalds 
13843e0fa65fSHeiko Carstens SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
13851da177e4SLinus Torvalds {
13861da177e4SLinus Torvalds 	int retval;
13871da177e4SLinus Torvalds 	struct socket *sock;
1388a677a039SUlrich Drepper 	int flags;
1389a677a039SUlrich Drepper 
1390e38b36f3SUlrich Drepper 	/* Check the SOCK_* constants for consistency.  */
1391e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
1392e38b36f3SUlrich Drepper 	BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
1393e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);
1394e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);
1395e38b36f3SUlrich Drepper 
1396a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
139777d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1398a677a039SUlrich Drepper 		return -EINVAL;
1399a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
14001da177e4SLinus Torvalds 
1401aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1402aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1403aaca0bdcSUlrich Drepper 
14041da177e4SLinus Torvalds 	retval = sock_create(family, type, protocol, &sock);
14051da177e4SLinus Torvalds 	if (retval < 0)
14061da177e4SLinus Torvalds 		goto out;
14071da177e4SLinus Torvalds 
140877d27200SUlrich Drepper 	retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
14091da177e4SLinus Torvalds 	if (retval < 0)
14101da177e4SLinus Torvalds 		goto out_release;
14111da177e4SLinus Torvalds 
14121da177e4SLinus Torvalds out:
14131da177e4SLinus Torvalds 	/* It may be already another descriptor 8) Not kernel problem. */
14141da177e4SLinus Torvalds 	return retval;
14151da177e4SLinus Torvalds 
14161da177e4SLinus Torvalds out_release:
14171da177e4SLinus Torvalds 	sock_release(sock);
14181da177e4SLinus Torvalds 	return retval;
14191da177e4SLinus Torvalds }
14201da177e4SLinus Torvalds 
14211da177e4SLinus Torvalds /*
14221da177e4SLinus Torvalds  *	Create a pair of connected sockets.
14231da177e4SLinus Torvalds  */
14241da177e4SLinus Torvalds 
14253e0fa65fSHeiko Carstens SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
14263e0fa65fSHeiko Carstens 		int __user *, usockvec)
14271da177e4SLinus Torvalds {
14281da177e4SLinus Torvalds 	struct socket *sock1, *sock2;
14291da177e4SLinus Torvalds 	int fd1, fd2, err;
1430db349509SAl Viro 	struct file *newfile1, *newfile2;
1431a677a039SUlrich Drepper 	int flags;
1432a677a039SUlrich Drepper 
1433a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
143477d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1435a677a039SUlrich Drepper 		return -EINVAL;
1436a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
14371da177e4SLinus Torvalds 
1438aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1439aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1440aaca0bdcSUlrich Drepper 
14411da177e4SLinus Torvalds 	/*
14421da177e4SLinus Torvalds 	 * Obtain the first socket and check if the underlying protocol
14431da177e4SLinus Torvalds 	 * supports the socketpair call.
14441da177e4SLinus Torvalds 	 */
14451da177e4SLinus Torvalds 
14461da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock1);
14471da177e4SLinus Torvalds 	if (err < 0)
14481da177e4SLinus Torvalds 		goto out;
14491da177e4SLinus Torvalds 
14501da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock2);
14511da177e4SLinus Torvalds 	if (err < 0)
14521da177e4SLinus Torvalds 		goto out_release_1;
14531da177e4SLinus Torvalds 
14541da177e4SLinus Torvalds 	err = sock1->ops->socketpair(sock1, sock2);
14551da177e4SLinus Torvalds 	if (err < 0)
14561da177e4SLinus Torvalds 		goto out_release_both;
14571da177e4SLinus Torvalds 
145828407630SAl Viro 	fd1 = get_unused_fd_flags(flags);
1459bf3c23d1SDavid S. Miller 	if (unlikely(fd1 < 0)) {
1460bf3c23d1SDavid S. Miller 		err = fd1;
14611da177e4SLinus Torvalds 		goto out_release_both;
1462bf3c23d1SDavid S. Miller 	}
146328407630SAl Viro 	fd2 = get_unused_fd_flags(flags);
1464198de4d7SAl Viro 	if (unlikely(fd2 < 0)) {
1465198de4d7SAl Viro 		err = fd2;
146628407630SAl Viro 		put_unused_fd(fd1);
146728407630SAl Viro 		goto out_release_both;
146828407630SAl Viro 	}
146928407630SAl Viro 
1470aab174f0SLinus Torvalds 	newfile1 = sock_alloc_file(sock1, flags, NULL);
147128407630SAl Viro 	if (unlikely(IS_ERR(newfile1))) {
147228407630SAl Viro 		err = PTR_ERR(newfile1);
147328407630SAl Viro 		put_unused_fd(fd1);
147428407630SAl Viro 		put_unused_fd(fd2);
147528407630SAl Viro 		goto out_release_both;
147628407630SAl Viro 	}
147728407630SAl Viro 
1478aab174f0SLinus Torvalds 	newfile2 = sock_alloc_file(sock2, flags, NULL);
147928407630SAl Viro 	if (IS_ERR(newfile2)) {
148028407630SAl Viro 		err = PTR_ERR(newfile2);
1481198de4d7SAl Viro 		fput(newfile1);
1482198de4d7SAl Viro 		put_unused_fd(fd1);
148328407630SAl Viro 		put_unused_fd(fd2);
1484198de4d7SAl Viro 		sock_release(sock2);
1485198de4d7SAl Viro 		goto out;
1486db349509SAl Viro 	}
1487db349509SAl Viro 
1488157cf649SAl Viro 	audit_fd_pair(fd1, fd2);
1489db349509SAl Viro 	fd_install(fd1, newfile1);
1490db349509SAl Viro 	fd_install(fd2, newfile2);
14911da177e4SLinus Torvalds 	/* fd1 and fd2 may be already another descriptors.
14921da177e4SLinus Torvalds 	 * Not kernel problem.
14931da177e4SLinus Torvalds 	 */
14941da177e4SLinus Torvalds 
14951da177e4SLinus Torvalds 	err = put_user(fd1, &usockvec[0]);
14961da177e4SLinus Torvalds 	if (!err)
14971da177e4SLinus Torvalds 		err = put_user(fd2, &usockvec[1]);
14981da177e4SLinus Torvalds 	if (!err)
14991da177e4SLinus Torvalds 		return 0;
15001da177e4SLinus Torvalds 
15011da177e4SLinus Torvalds 	sys_close(fd2);
15021da177e4SLinus Torvalds 	sys_close(fd1);
15031da177e4SLinus Torvalds 	return err;
15041da177e4SLinus Torvalds 
15051da177e4SLinus Torvalds out_release_both:
15061da177e4SLinus Torvalds 	sock_release(sock2);
15071da177e4SLinus Torvalds out_release_1:
15081da177e4SLinus Torvalds 	sock_release(sock1);
15091da177e4SLinus Torvalds out:
15101da177e4SLinus Torvalds 	return err;
15111da177e4SLinus Torvalds }
15121da177e4SLinus Torvalds 
15131da177e4SLinus Torvalds /*
15141da177e4SLinus Torvalds  *	Bind a name to a socket. Nothing much to do here since it's
15151da177e4SLinus Torvalds  *	the protocol's responsibility to handle the local address.
15161da177e4SLinus Torvalds  *
15171da177e4SLinus Torvalds  *	We move the socket address to kernel space before we call
15181da177e4SLinus Torvalds  *	the protocol layer (having also checked the address is ok).
15191da177e4SLinus Torvalds  */
15201da177e4SLinus Torvalds 
152120f37034SHeiko Carstens SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
15221da177e4SLinus Torvalds {
15231da177e4SLinus Torvalds 	struct socket *sock;
1524230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
15256cb153caSBenjamin LaHaise 	int err, fput_needed;
15261da177e4SLinus Torvalds 
152789bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
152889bddce5SStephen Hemminger 	if (sock) {
152943db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(umyaddr, addrlen, &address);
153089bddce5SStephen Hemminger 		if (err >= 0) {
153189bddce5SStephen Hemminger 			err = security_socket_bind(sock,
1532230b1839SYOSHIFUJI Hideaki 						   (struct sockaddr *)&address,
153389bddce5SStephen Hemminger 						   addrlen);
15346cb153caSBenjamin LaHaise 			if (!err)
15356cb153caSBenjamin LaHaise 				err = sock->ops->bind(sock,
153689bddce5SStephen Hemminger 						      (struct sockaddr *)
1537230b1839SYOSHIFUJI Hideaki 						      &address, addrlen);
15381da177e4SLinus Torvalds 		}
15396cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
15401da177e4SLinus Torvalds 	}
15411da177e4SLinus Torvalds 	return err;
15421da177e4SLinus Torvalds }
15431da177e4SLinus Torvalds 
15441da177e4SLinus Torvalds /*
15451da177e4SLinus Torvalds  *	Perform a listen. Basically, we allow the protocol to do anything
15461da177e4SLinus Torvalds  *	necessary for a listen, and if that works, we mark the socket as
15471da177e4SLinus Torvalds  *	ready for listening.
15481da177e4SLinus Torvalds  */
15491da177e4SLinus Torvalds 
15503e0fa65fSHeiko Carstens SYSCALL_DEFINE2(listen, int, fd, int, backlog)
15511da177e4SLinus Torvalds {
15521da177e4SLinus Torvalds 	struct socket *sock;
15536cb153caSBenjamin LaHaise 	int err, fput_needed;
1554b8e1f9b5SPavel Emelyanov 	int somaxconn;
15551da177e4SLinus Torvalds 
155689bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
155789bddce5SStephen Hemminger 	if (sock) {
15588efa6e93SPavel Emelyanov 		somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
155995c96174SEric Dumazet 		if ((unsigned int)backlog > somaxconn)
1560b8e1f9b5SPavel Emelyanov 			backlog = somaxconn;
15611da177e4SLinus Torvalds 
15621da177e4SLinus Torvalds 		err = security_socket_listen(sock, backlog);
15636cb153caSBenjamin LaHaise 		if (!err)
15641da177e4SLinus Torvalds 			err = sock->ops->listen(sock, backlog);
15656cb153caSBenjamin LaHaise 
15666cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
15671da177e4SLinus Torvalds 	}
15681da177e4SLinus Torvalds 	return err;
15691da177e4SLinus Torvalds }
15701da177e4SLinus Torvalds 
15711da177e4SLinus Torvalds /*
15721da177e4SLinus Torvalds  *	For accept, we attempt to create a new socket, set up the link
15731da177e4SLinus Torvalds  *	with the client, wake up the client, then return the new
15741da177e4SLinus Torvalds  *	connected fd. We collect the address of the connector in kernel
15751da177e4SLinus Torvalds  *	space and move it to user at the very end. This is unclean because
15761da177e4SLinus Torvalds  *	we open the socket then return an error.
15771da177e4SLinus Torvalds  *
15781da177e4SLinus Torvalds  *	1003.1g adds the ability to recvmsg() to query connection pending
15791da177e4SLinus Torvalds  *	status to recvmsg. We need to add that support in a way thats
15801da177e4SLinus Torvalds  *	clean when we restucture accept also.
15811da177e4SLinus Torvalds  */
15821da177e4SLinus Torvalds 
158320f37034SHeiko Carstens SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
158420f37034SHeiko Carstens 		int __user *, upeer_addrlen, int, flags)
15851da177e4SLinus Torvalds {
15861da177e4SLinus Torvalds 	struct socket *sock, *newsock;
158739d8c1b6SDavid S. Miller 	struct file *newfile;
15886cb153caSBenjamin LaHaise 	int err, len, newfd, fput_needed;
1589230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
15901da177e4SLinus Torvalds 
159177d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1592aaca0bdcSUlrich Drepper 		return -EINVAL;
1593aaca0bdcSUlrich Drepper 
1594aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1595aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1596aaca0bdcSUlrich Drepper 
15976cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
15981da177e4SLinus Torvalds 	if (!sock)
15991da177e4SLinus Torvalds 		goto out;
16001da177e4SLinus Torvalds 
16011da177e4SLinus Torvalds 	err = -ENFILE;
1602c6d409cfSEric Dumazet 	newsock = sock_alloc();
1603c6d409cfSEric Dumazet 	if (!newsock)
16041da177e4SLinus Torvalds 		goto out_put;
16051da177e4SLinus Torvalds 
16061da177e4SLinus Torvalds 	newsock->type = sock->type;
16071da177e4SLinus Torvalds 	newsock->ops = sock->ops;
16081da177e4SLinus Torvalds 
16091da177e4SLinus Torvalds 	/*
16101da177e4SLinus Torvalds 	 * We don't need try_module_get here, as the listening socket (sock)
16111da177e4SLinus Torvalds 	 * has the protocol module (sock->ops->owner) held.
16121da177e4SLinus Torvalds 	 */
16131da177e4SLinus Torvalds 	__module_get(newsock->ops->owner);
16141da177e4SLinus Torvalds 
161528407630SAl Viro 	newfd = get_unused_fd_flags(flags);
161639d8c1b6SDavid S. Miller 	if (unlikely(newfd < 0)) {
161739d8c1b6SDavid S. Miller 		err = newfd;
16189a1875e6SDavid S. Miller 		sock_release(newsock);
16199a1875e6SDavid S. Miller 		goto out_put;
162039d8c1b6SDavid S. Miller 	}
1621aab174f0SLinus Torvalds 	newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name);
162228407630SAl Viro 	if (unlikely(IS_ERR(newfile))) {
162328407630SAl Viro 		err = PTR_ERR(newfile);
162428407630SAl Viro 		put_unused_fd(newfd);
162528407630SAl Viro 		sock_release(newsock);
162628407630SAl Viro 		goto out_put;
162728407630SAl Viro 	}
162839d8c1b6SDavid S. Miller 
1629a79af59eSFrank Filz 	err = security_socket_accept(sock, newsock);
1630a79af59eSFrank Filz 	if (err)
163139d8c1b6SDavid S. Miller 		goto out_fd;
1632a79af59eSFrank Filz 
16331da177e4SLinus Torvalds 	err = sock->ops->accept(sock, newsock, sock->file->f_flags);
16341da177e4SLinus Torvalds 	if (err < 0)
163539d8c1b6SDavid S. Miller 		goto out_fd;
16361da177e4SLinus Torvalds 
16371da177e4SLinus Torvalds 	if (upeer_sockaddr) {
1638230b1839SYOSHIFUJI Hideaki 		if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
163989bddce5SStephen Hemminger 					  &len, 2) < 0) {
16401da177e4SLinus Torvalds 			err = -ECONNABORTED;
164139d8c1b6SDavid S. Miller 			goto out_fd;
16421da177e4SLinus Torvalds 		}
164343db362dSMaciej Żenczykowski 		err = move_addr_to_user(&address,
1644230b1839SYOSHIFUJI Hideaki 					len, upeer_sockaddr, upeer_addrlen);
16451da177e4SLinus Torvalds 		if (err < 0)
164639d8c1b6SDavid S. Miller 			goto out_fd;
16471da177e4SLinus Torvalds 	}
16481da177e4SLinus Torvalds 
16491da177e4SLinus Torvalds 	/* File flags are not inherited via accept() unlike another OSes. */
16501da177e4SLinus Torvalds 
165139d8c1b6SDavid S. Miller 	fd_install(newfd, newfile);
165239d8c1b6SDavid S. Miller 	err = newfd;
16531da177e4SLinus Torvalds 
16541da177e4SLinus Torvalds out_put:
16556cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
16561da177e4SLinus Torvalds out:
16571da177e4SLinus Torvalds 	return err;
165839d8c1b6SDavid S. Miller out_fd:
16599606a216SDavid S. Miller 	fput(newfile);
166039d8c1b6SDavid S. Miller 	put_unused_fd(newfd);
16611da177e4SLinus Torvalds 	goto out_put;
16621da177e4SLinus Torvalds }
16631da177e4SLinus Torvalds 
166420f37034SHeiko Carstens SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,
166520f37034SHeiko Carstens 		int __user *, upeer_addrlen)
1666aaca0bdcSUlrich Drepper {
1667de11defeSUlrich Drepper 	return sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0);
1668aaca0bdcSUlrich Drepper }
1669aaca0bdcSUlrich Drepper 
16701da177e4SLinus Torvalds /*
16711da177e4SLinus Torvalds  *	Attempt to connect to a socket with the server address.  The address
16721da177e4SLinus Torvalds  *	is in user space so we verify it is OK and move it to kernel space.
16731da177e4SLinus Torvalds  *
16741da177e4SLinus Torvalds  *	For 1003.1g we need to add clean support for a bind to AF_UNSPEC to
16751da177e4SLinus Torvalds  *	break bindings
16761da177e4SLinus Torvalds  *
16771da177e4SLinus Torvalds  *	NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and
16781da177e4SLinus Torvalds  *	other SEQPACKET protocols that take time to connect() as it doesn't
16791da177e4SLinus Torvalds  *	include the -EINPROGRESS status for such sockets.
16801da177e4SLinus Torvalds  */
16811da177e4SLinus Torvalds 
168220f37034SHeiko Carstens SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
168320f37034SHeiko Carstens 		int, addrlen)
16841da177e4SLinus Torvalds {
16851da177e4SLinus Torvalds 	struct socket *sock;
1686230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16876cb153caSBenjamin LaHaise 	int err, fput_needed;
16881da177e4SLinus Torvalds 
16896cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
16901da177e4SLinus Torvalds 	if (!sock)
16911da177e4SLinus Torvalds 		goto out;
169243db362dSMaciej Żenczykowski 	err = move_addr_to_kernel(uservaddr, addrlen, &address);
16931da177e4SLinus Torvalds 	if (err < 0)
16941da177e4SLinus Torvalds 		goto out_put;
16951da177e4SLinus Torvalds 
169689bddce5SStephen Hemminger 	err =
1697230b1839SYOSHIFUJI Hideaki 	    security_socket_connect(sock, (struct sockaddr *)&address, addrlen);
16981da177e4SLinus Torvalds 	if (err)
16991da177e4SLinus Torvalds 		goto out_put;
17001da177e4SLinus Torvalds 
1701230b1839SYOSHIFUJI Hideaki 	err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,
17021da177e4SLinus Torvalds 				 sock->file->f_flags);
17031da177e4SLinus Torvalds out_put:
17046cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
17051da177e4SLinus Torvalds out:
17061da177e4SLinus Torvalds 	return err;
17071da177e4SLinus Torvalds }
17081da177e4SLinus Torvalds 
17091da177e4SLinus Torvalds /*
17101da177e4SLinus Torvalds  *	Get the local address ('name') of a socket object. Move the obtained
17111da177e4SLinus Torvalds  *	name to user space.
17121da177e4SLinus Torvalds  */
17131da177e4SLinus Torvalds 
171420f37034SHeiko Carstens SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
171520f37034SHeiko Carstens 		int __user *, usockaddr_len)
17161da177e4SLinus Torvalds {
17171da177e4SLinus Torvalds 	struct socket *sock;
1718230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
17196cb153caSBenjamin LaHaise 	int len, err, fput_needed;
17201da177e4SLinus Torvalds 
17216cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
17221da177e4SLinus Torvalds 	if (!sock)
17231da177e4SLinus Torvalds 		goto out;
17241da177e4SLinus Torvalds 
17251da177e4SLinus Torvalds 	err = security_socket_getsockname(sock);
17261da177e4SLinus Torvalds 	if (err)
17271da177e4SLinus Torvalds 		goto out_put;
17281da177e4SLinus Torvalds 
1729230b1839SYOSHIFUJI Hideaki 	err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0);
17301da177e4SLinus Torvalds 	if (err)
17311da177e4SLinus Torvalds 		goto out_put;
173243db362dSMaciej Żenczykowski 	err = move_addr_to_user(&address, len, usockaddr, usockaddr_len);
17331da177e4SLinus Torvalds 
17341da177e4SLinus Torvalds out_put:
17356cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
17361da177e4SLinus Torvalds out:
17371da177e4SLinus Torvalds 	return err;
17381da177e4SLinus Torvalds }
17391da177e4SLinus Torvalds 
17401da177e4SLinus Torvalds /*
17411da177e4SLinus Torvalds  *	Get the remote address ('name') of a socket object. Move the obtained
17421da177e4SLinus Torvalds  *	name to user space.
17431da177e4SLinus Torvalds  */
17441da177e4SLinus Torvalds 
174520f37034SHeiko Carstens SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
174620f37034SHeiko Carstens 		int __user *, usockaddr_len)
17471da177e4SLinus Torvalds {
17481da177e4SLinus Torvalds 	struct socket *sock;
1749230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
17506cb153caSBenjamin LaHaise 	int len, err, fput_needed;
17511da177e4SLinus Torvalds 
175289bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
175389bddce5SStephen Hemminger 	if (sock != NULL) {
17541da177e4SLinus Torvalds 		err = security_socket_getpeername(sock);
17551da177e4SLinus Torvalds 		if (err) {
17566cb153caSBenjamin LaHaise 			fput_light(sock->file, fput_needed);
17571da177e4SLinus Torvalds 			return err;
17581da177e4SLinus Torvalds 		}
17591da177e4SLinus Torvalds 
176089bddce5SStephen Hemminger 		err =
1761230b1839SYOSHIFUJI Hideaki 		    sock->ops->getname(sock, (struct sockaddr *)&address, &len,
176289bddce5SStephen Hemminger 				       1);
17631da177e4SLinus Torvalds 		if (!err)
176443db362dSMaciej Żenczykowski 			err = move_addr_to_user(&address, len, usockaddr,
176589bddce5SStephen Hemminger 						usockaddr_len);
17666cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
17671da177e4SLinus Torvalds 	}
17681da177e4SLinus Torvalds 	return err;
17691da177e4SLinus Torvalds }
17701da177e4SLinus Torvalds 
17711da177e4SLinus Torvalds /*
17721da177e4SLinus Torvalds  *	Send a datagram to a given address. We move the address into kernel
17731da177e4SLinus Torvalds  *	space and check the user space data area is readable before invoking
17741da177e4SLinus Torvalds  *	the protocol.
17751da177e4SLinus Torvalds  */
17761da177e4SLinus Torvalds 
17773e0fa65fSHeiko Carstens SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
177895c96174SEric Dumazet 		unsigned int, flags, struct sockaddr __user *, addr,
17793e0fa65fSHeiko Carstens 		int, addr_len)
17801da177e4SLinus Torvalds {
17811da177e4SLinus Torvalds 	struct socket *sock;
1782230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
17831da177e4SLinus Torvalds 	int err;
17841da177e4SLinus Torvalds 	struct msghdr msg;
17851da177e4SLinus Torvalds 	struct iovec iov;
17866cb153caSBenjamin LaHaise 	int fput_needed;
17871da177e4SLinus Torvalds 
1788253eacc0SLinus Torvalds 	if (len > INT_MAX)
1789253eacc0SLinus Torvalds 		len = INT_MAX;
1790de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1791de0fa95cSPavel Emelyanov 	if (!sock)
17924387ff75SDavid S. Miller 		goto out;
17936cb153caSBenjamin LaHaise 
17941da177e4SLinus Torvalds 	iov.iov_base = buff;
17951da177e4SLinus Torvalds 	iov.iov_len = len;
17961da177e4SLinus Torvalds 	msg.msg_name = NULL;
17971da177e4SLinus Torvalds 	msg.msg_iov = &iov;
17981da177e4SLinus Torvalds 	msg.msg_iovlen = 1;
17991da177e4SLinus Torvalds 	msg.msg_control = NULL;
18001da177e4SLinus Torvalds 	msg.msg_controllen = 0;
18011da177e4SLinus Torvalds 	msg.msg_namelen = 0;
18026cb153caSBenjamin LaHaise 	if (addr) {
180343db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(addr, addr_len, &address);
18041da177e4SLinus Torvalds 		if (err < 0)
18051da177e4SLinus Torvalds 			goto out_put;
1806230b1839SYOSHIFUJI Hideaki 		msg.msg_name = (struct sockaddr *)&address;
18071da177e4SLinus Torvalds 		msg.msg_namelen = addr_len;
18081da177e4SLinus Torvalds 	}
18091da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
18101da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
18111da177e4SLinus Torvalds 	msg.msg_flags = flags;
18121da177e4SLinus Torvalds 	err = sock_sendmsg(sock, &msg, len);
18131da177e4SLinus Torvalds 
18141da177e4SLinus Torvalds out_put:
1815de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
18164387ff75SDavid S. Miller out:
18171da177e4SLinus Torvalds 	return err;
18181da177e4SLinus Torvalds }
18191da177e4SLinus Torvalds 
18201da177e4SLinus Torvalds /*
18211da177e4SLinus Torvalds  *	Send a datagram down a socket.
18221da177e4SLinus Torvalds  */
18231da177e4SLinus Torvalds 
18243e0fa65fSHeiko Carstens SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len,
182595c96174SEric Dumazet 		unsigned int, flags)
18261da177e4SLinus Torvalds {
18271da177e4SLinus Torvalds 	return sys_sendto(fd, buff, len, flags, NULL, 0);
18281da177e4SLinus Torvalds }
18291da177e4SLinus Torvalds 
18301da177e4SLinus Torvalds /*
18311da177e4SLinus Torvalds  *	Receive a frame from the socket and optionally record the address of the
18321da177e4SLinus Torvalds  *	sender. We verify the buffers are writable and if needed move the
18331da177e4SLinus Torvalds  *	sender address from kernel to user space.
18341da177e4SLinus Torvalds  */
18351da177e4SLinus Torvalds 
18363e0fa65fSHeiko Carstens SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
183795c96174SEric Dumazet 		unsigned int, flags, struct sockaddr __user *, addr,
18383e0fa65fSHeiko Carstens 		int __user *, addr_len)
18391da177e4SLinus Torvalds {
18401da177e4SLinus Torvalds 	struct socket *sock;
18411da177e4SLinus Torvalds 	struct iovec iov;
18421da177e4SLinus Torvalds 	struct msghdr msg;
1843230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
18441da177e4SLinus Torvalds 	int err, err2;
18456cb153caSBenjamin LaHaise 	int fput_needed;
18461da177e4SLinus Torvalds 
1847253eacc0SLinus Torvalds 	if (size > INT_MAX)
1848253eacc0SLinus Torvalds 		size = INT_MAX;
1849de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
18501da177e4SLinus Torvalds 	if (!sock)
1851de0fa95cSPavel Emelyanov 		goto out;
18521da177e4SLinus Torvalds 
18531da177e4SLinus Torvalds 	msg.msg_control = NULL;
18541da177e4SLinus Torvalds 	msg.msg_controllen = 0;
18551da177e4SLinus Torvalds 	msg.msg_iovlen = 1;
18561da177e4SLinus Torvalds 	msg.msg_iov = &iov;
18571da177e4SLinus Torvalds 	iov.iov_len = size;
18581da177e4SLinus Torvalds 	iov.iov_base = ubuf;
1859230b1839SYOSHIFUJI Hideaki 	msg.msg_name = (struct sockaddr *)&address;
1860230b1839SYOSHIFUJI Hideaki 	msg.msg_namelen = sizeof(address);
18611da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
18621da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
18631da177e4SLinus Torvalds 	err = sock_recvmsg(sock, &msg, size, flags);
18641da177e4SLinus Torvalds 
186589bddce5SStephen Hemminger 	if (err >= 0 && addr != NULL) {
186643db362dSMaciej Żenczykowski 		err2 = move_addr_to_user(&address,
1867230b1839SYOSHIFUJI Hideaki 					 msg.msg_namelen, addr, addr_len);
18681da177e4SLinus Torvalds 		if (err2 < 0)
18691da177e4SLinus Torvalds 			err = err2;
18701da177e4SLinus Torvalds 	}
1871de0fa95cSPavel Emelyanov 
1872de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
18734387ff75SDavid S. Miller out:
18741da177e4SLinus Torvalds 	return err;
18751da177e4SLinus Torvalds }
18761da177e4SLinus Torvalds 
18771da177e4SLinus Torvalds /*
18781da177e4SLinus Torvalds  *	Receive a datagram from a socket.
18791da177e4SLinus Torvalds  */
18801da177e4SLinus Torvalds 
188189bddce5SStephen Hemminger asmlinkage long sys_recv(int fd, void __user *ubuf, size_t size,
188295c96174SEric Dumazet 			 unsigned int flags)
18831da177e4SLinus Torvalds {
18841da177e4SLinus Torvalds 	return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL);
18851da177e4SLinus Torvalds }
18861da177e4SLinus Torvalds 
18871da177e4SLinus Torvalds /*
18881da177e4SLinus Torvalds  *	Set a socket option. Because we don't know the option lengths we have
18891da177e4SLinus Torvalds  *	to pass the user mode parameter for the protocols to sort out.
18901da177e4SLinus Torvalds  */
18911da177e4SLinus Torvalds 
189220f37034SHeiko Carstens SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
189320f37034SHeiko Carstens 		char __user *, optval, int, optlen)
18941da177e4SLinus Torvalds {
18956cb153caSBenjamin LaHaise 	int err, fput_needed;
18961da177e4SLinus Torvalds 	struct socket *sock;
18971da177e4SLinus Torvalds 
18981da177e4SLinus Torvalds 	if (optlen < 0)
18991da177e4SLinus Torvalds 		return -EINVAL;
19001da177e4SLinus Torvalds 
190189bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
190289bddce5SStephen Hemminger 	if (sock != NULL) {
19031da177e4SLinus Torvalds 		err = security_socket_setsockopt(sock, level, optname);
19046cb153caSBenjamin LaHaise 		if (err)
19056cb153caSBenjamin LaHaise 			goto out_put;
19061da177e4SLinus Torvalds 
19071da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
190889bddce5SStephen Hemminger 			err =
190989bddce5SStephen Hemminger 			    sock_setsockopt(sock, level, optname, optval,
191089bddce5SStephen Hemminger 					    optlen);
19111da177e4SLinus Torvalds 		else
191289bddce5SStephen Hemminger 			err =
191389bddce5SStephen Hemminger 			    sock->ops->setsockopt(sock, level, optname, optval,
191489bddce5SStephen Hemminger 						  optlen);
19156cb153caSBenjamin LaHaise out_put:
19166cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
19171da177e4SLinus Torvalds 	}
19181da177e4SLinus Torvalds 	return err;
19191da177e4SLinus Torvalds }
19201da177e4SLinus Torvalds 
19211da177e4SLinus Torvalds /*
19221da177e4SLinus Torvalds  *	Get a socket option. Because we don't know the option lengths we have
19231da177e4SLinus Torvalds  *	to pass a user mode parameter for the protocols to sort out.
19241da177e4SLinus Torvalds  */
19251da177e4SLinus Torvalds 
192620f37034SHeiko Carstens SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
192720f37034SHeiko Carstens 		char __user *, optval, int __user *, optlen)
19281da177e4SLinus Torvalds {
19296cb153caSBenjamin LaHaise 	int err, fput_needed;
19301da177e4SLinus Torvalds 	struct socket *sock;
19311da177e4SLinus Torvalds 
193289bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
193389bddce5SStephen Hemminger 	if (sock != NULL) {
19346cb153caSBenjamin LaHaise 		err = security_socket_getsockopt(sock, level, optname);
19356cb153caSBenjamin LaHaise 		if (err)
19366cb153caSBenjamin LaHaise 			goto out_put;
19371da177e4SLinus Torvalds 
19381da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
193989bddce5SStephen Hemminger 			err =
194089bddce5SStephen Hemminger 			    sock_getsockopt(sock, level, optname, optval,
194189bddce5SStephen Hemminger 					    optlen);
19421da177e4SLinus Torvalds 		else
194389bddce5SStephen Hemminger 			err =
194489bddce5SStephen Hemminger 			    sock->ops->getsockopt(sock, level, optname, optval,
194589bddce5SStephen Hemminger 						  optlen);
19466cb153caSBenjamin LaHaise out_put:
19476cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
19481da177e4SLinus Torvalds 	}
19491da177e4SLinus Torvalds 	return err;
19501da177e4SLinus Torvalds }
19511da177e4SLinus Torvalds 
19521da177e4SLinus Torvalds /*
19531da177e4SLinus Torvalds  *	Shutdown a socket.
19541da177e4SLinus Torvalds  */
19551da177e4SLinus Torvalds 
1956754fe8d2SHeiko Carstens SYSCALL_DEFINE2(shutdown, int, fd, int, how)
19571da177e4SLinus Torvalds {
19586cb153caSBenjamin LaHaise 	int err, fput_needed;
19591da177e4SLinus Torvalds 	struct socket *sock;
19601da177e4SLinus Torvalds 
196189bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
196289bddce5SStephen Hemminger 	if (sock != NULL) {
19631da177e4SLinus Torvalds 		err = security_socket_shutdown(sock, how);
19646cb153caSBenjamin LaHaise 		if (!err)
19651da177e4SLinus Torvalds 			err = sock->ops->shutdown(sock, how);
19666cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
19671da177e4SLinus Torvalds 	}
19681da177e4SLinus Torvalds 	return err;
19691da177e4SLinus Torvalds }
19701da177e4SLinus Torvalds 
19711da177e4SLinus Torvalds /* A couple of helpful macros for getting the address of the 32/64 bit
19721da177e4SLinus Torvalds  * fields which are the same type (int / unsigned) on our platforms.
19731da177e4SLinus Torvalds  */
19741da177e4SLinus Torvalds #define COMPAT_MSG(msg, member)	((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member)
19751da177e4SLinus Torvalds #define COMPAT_NAMELEN(msg)	COMPAT_MSG(msg, msg_namelen)
19761da177e4SLinus Torvalds #define COMPAT_FLAGS(msg)	COMPAT_MSG(msg, msg_flags)
19771da177e4SLinus Torvalds 
1978c71d8ebeSTetsuo Handa struct used_address {
1979c71d8ebeSTetsuo Handa 	struct sockaddr_storage name;
1980c71d8ebeSTetsuo Handa 	unsigned int name_len;
1981c71d8ebeSTetsuo Handa };
1982c71d8ebeSTetsuo Handa 
1983228e548eSAnton Blanchard static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
198495c96174SEric Dumazet 			 struct msghdr *msg_sys, unsigned int flags,
1985c71d8ebeSTetsuo Handa 			 struct used_address *used_address)
19861da177e4SLinus Torvalds {
198789bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
198889bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
1989230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
19901da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
1991b9d717a7SAlex Williamson 	unsigned char ctl[sizeof(struct cmsghdr) + 20]
1992b9d717a7SAlex Williamson 	    __attribute__ ((aligned(sizeof(__kernel_size_t))));
1993b9d717a7SAlex Williamson 	/* 20 is size of ipv6_pktinfo */
19941da177e4SLinus Torvalds 	unsigned char *ctl_buf = ctl;
1995a74e9106SEric Dumazet 	int err, ctl_len, total_len;
19961da177e4SLinus Torvalds 
19971da177e4SLinus Torvalds 	err = -EFAULT;
19981da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
1999228e548eSAnton Blanchard 		if (get_compat_msghdr(msg_sys, msg_compat))
20001da177e4SLinus Torvalds 			return -EFAULT;
2001228e548eSAnton Blanchard 	} else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr)))
20021da177e4SLinus Torvalds 		return -EFAULT;
20031da177e4SLinus Torvalds 
2004a74e9106SEric Dumazet 	if (msg_sys->msg_iovlen > UIO_FASTIOV) {
20051da177e4SLinus Torvalds 		err = -EMSGSIZE;
2006228e548eSAnton Blanchard 		if (msg_sys->msg_iovlen > UIO_MAXIOV)
2007228e548eSAnton Blanchard 			goto out;
20081da177e4SLinus Torvalds 		err = -ENOMEM;
2009a74e9106SEric Dumazet 		iov = kmalloc(msg_sys->msg_iovlen * sizeof(struct iovec),
2010a74e9106SEric Dumazet 			      GFP_KERNEL);
20111da177e4SLinus Torvalds 		if (!iov)
2012228e548eSAnton Blanchard 			goto out;
20131da177e4SLinus Torvalds 	}
20141da177e4SLinus Torvalds 
20151da177e4SLinus Torvalds 	/* This will also move the address data into kernel space */
20161da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
201743db362dSMaciej Żenczykowski 		err = verify_compat_iovec(msg_sys, iov, &address, VERIFY_READ);
20181da177e4SLinus Torvalds 	} else
201943db362dSMaciej Żenczykowski 		err = verify_iovec(msg_sys, iov, &address, VERIFY_READ);
20201da177e4SLinus Torvalds 	if (err < 0)
20211da177e4SLinus Torvalds 		goto out_freeiov;
20221da177e4SLinus Torvalds 	total_len = err;
20231da177e4SLinus Torvalds 
20241da177e4SLinus Torvalds 	err = -ENOBUFS;
20251da177e4SLinus Torvalds 
2026228e548eSAnton Blanchard 	if (msg_sys->msg_controllen > INT_MAX)
20271da177e4SLinus Torvalds 		goto out_freeiov;
2028228e548eSAnton Blanchard 	ctl_len = msg_sys->msg_controllen;
20291da177e4SLinus Torvalds 	if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
203089bddce5SStephen Hemminger 		err =
2031228e548eSAnton Blanchard 		    cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl,
203289bddce5SStephen Hemminger 						     sizeof(ctl));
20331da177e4SLinus Torvalds 		if (err)
20341da177e4SLinus Torvalds 			goto out_freeiov;
2035228e548eSAnton Blanchard 		ctl_buf = msg_sys->msg_control;
2036228e548eSAnton Blanchard 		ctl_len = msg_sys->msg_controllen;
20371da177e4SLinus Torvalds 	} else if (ctl_len) {
203889bddce5SStephen Hemminger 		if (ctl_len > sizeof(ctl)) {
20391da177e4SLinus Torvalds 			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
20401da177e4SLinus Torvalds 			if (ctl_buf == NULL)
20411da177e4SLinus Torvalds 				goto out_freeiov;
20421da177e4SLinus Torvalds 		}
20431da177e4SLinus Torvalds 		err = -EFAULT;
20441da177e4SLinus Torvalds 		/*
2045228e548eSAnton Blanchard 		 * Careful! Before this, msg_sys->msg_control contains a user pointer.
20461da177e4SLinus Torvalds 		 * Afterwards, it will be a kernel pointer. Thus the compiler-assisted
20471da177e4SLinus Torvalds 		 * checking falls down on this.
20481da177e4SLinus Torvalds 		 */
2049fb8621bbSNamhyung Kim 		if (copy_from_user(ctl_buf,
2050228e548eSAnton Blanchard 				   (void __user __force *)msg_sys->msg_control,
205189bddce5SStephen Hemminger 				   ctl_len))
20521da177e4SLinus Torvalds 			goto out_freectl;
2053228e548eSAnton Blanchard 		msg_sys->msg_control = ctl_buf;
20541da177e4SLinus Torvalds 	}
2055228e548eSAnton Blanchard 	msg_sys->msg_flags = flags;
20561da177e4SLinus Torvalds 
20571da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
2058228e548eSAnton Blanchard 		msg_sys->msg_flags |= MSG_DONTWAIT;
2059c71d8ebeSTetsuo Handa 	/*
2060c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and current destination address is same as
2061c71d8ebeSTetsuo Handa 	 * previously succeeded address, omit asking LSM's decision.
2062c71d8ebeSTetsuo Handa 	 * used_address->name_len is initialized to UINT_MAX so that the first
2063c71d8ebeSTetsuo Handa 	 * destination address never matches.
2064c71d8ebeSTetsuo Handa 	 */
2065bc909d9dSMathieu Desnoyers 	if (used_address && msg_sys->msg_name &&
2066bc909d9dSMathieu Desnoyers 	    used_address->name_len == msg_sys->msg_namelen &&
2067bc909d9dSMathieu Desnoyers 	    !memcmp(&used_address->name, msg_sys->msg_name,
2068c71d8ebeSTetsuo Handa 		    used_address->name_len)) {
2069c71d8ebeSTetsuo Handa 		err = sock_sendmsg_nosec(sock, msg_sys, total_len);
2070c71d8ebeSTetsuo Handa 		goto out_freectl;
2071c71d8ebeSTetsuo Handa 	}
2072c71d8ebeSTetsuo Handa 	err = sock_sendmsg(sock, msg_sys, total_len);
2073c71d8ebeSTetsuo Handa 	/*
2074c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and sending to current destination address was
2075c71d8ebeSTetsuo Handa 	 * successful, remember it.
2076c71d8ebeSTetsuo Handa 	 */
2077c71d8ebeSTetsuo Handa 	if (used_address && err >= 0) {
2078c71d8ebeSTetsuo Handa 		used_address->name_len = msg_sys->msg_namelen;
2079bc909d9dSMathieu Desnoyers 		if (msg_sys->msg_name)
2080bc909d9dSMathieu Desnoyers 			memcpy(&used_address->name, msg_sys->msg_name,
2081c71d8ebeSTetsuo Handa 			       used_address->name_len);
2082c71d8ebeSTetsuo Handa 	}
20831da177e4SLinus Torvalds 
20841da177e4SLinus Torvalds out_freectl:
20851da177e4SLinus Torvalds 	if (ctl_buf != ctl)
20861da177e4SLinus Torvalds 		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
20871da177e4SLinus Torvalds out_freeiov:
20881da177e4SLinus Torvalds 	if (iov != iovstack)
2089a74e9106SEric Dumazet 		kfree(iov);
2090228e548eSAnton Blanchard out:
2091228e548eSAnton Blanchard 	return err;
2092228e548eSAnton Blanchard }
2093228e548eSAnton Blanchard 
2094228e548eSAnton Blanchard /*
2095228e548eSAnton Blanchard  *	BSD sendmsg interface
2096228e548eSAnton Blanchard  */
2097228e548eSAnton Blanchard 
209895c96174SEric Dumazet SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned int, flags)
2099228e548eSAnton Blanchard {
2100228e548eSAnton Blanchard 	int fput_needed, err;
2101228e548eSAnton Blanchard 	struct msghdr msg_sys;
2102228e548eSAnton Blanchard 	struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed);
2103228e548eSAnton Blanchard 
2104228e548eSAnton Blanchard 	if (!sock)
2105228e548eSAnton Blanchard 		goto out;
2106228e548eSAnton Blanchard 
2107c71d8ebeSTetsuo Handa 	err = __sys_sendmsg(sock, msg, &msg_sys, flags, NULL);
2108228e548eSAnton Blanchard 
21096cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
21101da177e4SLinus Torvalds out:
21111da177e4SLinus Torvalds 	return err;
21121da177e4SLinus Torvalds }
21131da177e4SLinus Torvalds 
2114228e548eSAnton Blanchard /*
2115228e548eSAnton Blanchard  *	Linux sendmmsg interface
2116228e548eSAnton Blanchard  */
2117228e548eSAnton Blanchard 
2118228e548eSAnton Blanchard int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2119228e548eSAnton Blanchard 		   unsigned int flags)
2120228e548eSAnton Blanchard {
2121228e548eSAnton Blanchard 	int fput_needed, err, datagrams;
2122228e548eSAnton Blanchard 	struct socket *sock;
2123228e548eSAnton Blanchard 	struct mmsghdr __user *entry;
2124228e548eSAnton Blanchard 	struct compat_mmsghdr __user *compat_entry;
2125228e548eSAnton Blanchard 	struct msghdr msg_sys;
2126c71d8ebeSTetsuo Handa 	struct used_address used_address;
2127228e548eSAnton Blanchard 
212898382f41SAnton Blanchard 	if (vlen > UIO_MAXIOV)
212998382f41SAnton Blanchard 		vlen = UIO_MAXIOV;
2130228e548eSAnton Blanchard 
2131228e548eSAnton Blanchard 	datagrams = 0;
2132228e548eSAnton Blanchard 
2133228e548eSAnton Blanchard 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2134228e548eSAnton Blanchard 	if (!sock)
2135228e548eSAnton Blanchard 		return err;
2136228e548eSAnton Blanchard 
2137c71d8ebeSTetsuo Handa 	used_address.name_len = UINT_MAX;
2138228e548eSAnton Blanchard 	entry = mmsg;
2139228e548eSAnton Blanchard 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2140728ffb86SAnton Blanchard 	err = 0;
2141228e548eSAnton Blanchard 
2142228e548eSAnton Blanchard 	while (datagrams < vlen) {
2143228e548eSAnton Blanchard 		if (MSG_CMSG_COMPAT & flags) {
2144228e548eSAnton Blanchard 			err = __sys_sendmsg(sock, (struct msghdr __user *)compat_entry,
2145c71d8ebeSTetsuo Handa 					    &msg_sys, flags, &used_address);
2146228e548eSAnton Blanchard 			if (err < 0)
2147228e548eSAnton Blanchard 				break;
2148228e548eSAnton Blanchard 			err = __put_user(err, &compat_entry->msg_len);
2149228e548eSAnton Blanchard 			++compat_entry;
2150228e548eSAnton Blanchard 		} else {
2151228e548eSAnton Blanchard 			err = __sys_sendmsg(sock, (struct msghdr __user *)entry,
2152c71d8ebeSTetsuo Handa 					    &msg_sys, flags, &used_address);
2153228e548eSAnton Blanchard 			if (err < 0)
2154228e548eSAnton Blanchard 				break;
2155228e548eSAnton Blanchard 			err = put_user(err, &entry->msg_len);
2156228e548eSAnton Blanchard 			++entry;
2157228e548eSAnton Blanchard 		}
2158228e548eSAnton Blanchard 
2159228e548eSAnton Blanchard 		if (err)
2160228e548eSAnton Blanchard 			break;
2161228e548eSAnton Blanchard 		++datagrams;
2162228e548eSAnton Blanchard 	}
2163228e548eSAnton Blanchard 
2164228e548eSAnton Blanchard 	fput_light(sock->file, fput_needed);
2165228e548eSAnton Blanchard 
2166728ffb86SAnton Blanchard 	/* We only return an error if no datagrams were able to be sent */
2167728ffb86SAnton Blanchard 	if (datagrams != 0)
2168228e548eSAnton Blanchard 		return datagrams;
2169228e548eSAnton Blanchard 
2170228e548eSAnton Blanchard 	return err;
2171228e548eSAnton Blanchard }
2172228e548eSAnton Blanchard 
2173228e548eSAnton Blanchard SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
2174228e548eSAnton Blanchard 		unsigned int, vlen, unsigned int, flags)
2175228e548eSAnton Blanchard {
2176228e548eSAnton Blanchard 	return __sys_sendmmsg(fd, mmsg, vlen, flags);
2177228e548eSAnton Blanchard }
2178228e548eSAnton Blanchard 
2179a2e27255SArnaldo Carvalho de Melo static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
218095c96174SEric Dumazet 			 struct msghdr *msg_sys, unsigned int flags, int nosec)
21811da177e4SLinus Torvalds {
218289bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
218389bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
21841da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV];
21851da177e4SLinus Torvalds 	struct iovec *iov = iovstack;
21861da177e4SLinus Torvalds 	unsigned long cmsg_ptr;
2187a74e9106SEric Dumazet 	int err, total_len, len;
21881da177e4SLinus Torvalds 
21891da177e4SLinus Torvalds 	/* kernel mode address */
2190230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage addr;
21911da177e4SLinus Torvalds 
21921da177e4SLinus Torvalds 	/* user mode address pointers */
21931da177e4SLinus Torvalds 	struct sockaddr __user *uaddr;
21941da177e4SLinus Torvalds 	int __user *uaddr_len;
21951da177e4SLinus Torvalds 
21961da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
2197a2e27255SArnaldo Carvalho de Melo 		if (get_compat_msghdr(msg_sys, msg_compat))
21981da177e4SLinus Torvalds 			return -EFAULT;
2199c6d409cfSEric Dumazet 	} else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr)))
22001da177e4SLinus Torvalds 		return -EFAULT;
22011da177e4SLinus Torvalds 
2202a74e9106SEric Dumazet 	if (msg_sys->msg_iovlen > UIO_FASTIOV) {
22031da177e4SLinus Torvalds 		err = -EMSGSIZE;
2204a2e27255SArnaldo Carvalho de Melo 		if (msg_sys->msg_iovlen > UIO_MAXIOV)
2205a2e27255SArnaldo Carvalho de Melo 			goto out;
22061da177e4SLinus Torvalds 		err = -ENOMEM;
2207a74e9106SEric Dumazet 		iov = kmalloc(msg_sys->msg_iovlen * sizeof(struct iovec),
2208a74e9106SEric Dumazet 			      GFP_KERNEL);
22091da177e4SLinus Torvalds 		if (!iov)
2210a2e27255SArnaldo Carvalho de Melo 			goto out;
22111da177e4SLinus Torvalds 	}
22121da177e4SLinus Torvalds 
22131da177e4SLinus Torvalds 	/*
22141da177e4SLinus Torvalds 	 *      Save the user-mode address (verify_iovec will change the
22151da177e4SLinus Torvalds 	 *      kernel msghdr to use the kernel address space)
22161da177e4SLinus Torvalds 	 */
22171da177e4SLinus Torvalds 
2218a2e27255SArnaldo Carvalho de Melo 	uaddr = (__force void __user *)msg_sys->msg_name;
22191da177e4SLinus Torvalds 	uaddr_len = COMPAT_NAMELEN(msg);
22201da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
222143db362dSMaciej Żenczykowski 		err = verify_compat_iovec(msg_sys, iov, &addr, VERIFY_WRITE);
22221da177e4SLinus Torvalds 	} else
222343db362dSMaciej Żenczykowski 		err = verify_iovec(msg_sys, iov, &addr, VERIFY_WRITE);
22241da177e4SLinus Torvalds 	if (err < 0)
22251da177e4SLinus Torvalds 		goto out_freeiov;
22261da177e4SLinus Torvalds 	total_len = err;
22271da177e4SLinus Torvalds 
2228a2e27255SArnaldo Carvalho de Melo 	cmsg_ptr = (unsigned long)msg_sys->msg_control;
2229a2e27255SArnaldo Carvalho de Melo 	msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
22301da177e4SLinus Torvalds 
22311da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
22321da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
2233a2e27255SArnaldo Carvalho de Melo 	err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys,
2234a2e27255SArnaldo Carvalho de Melo 							  total_len, flags);
22351da177e4SLinus Torvalds 	if (err < 0)
22361da177e4SLinus Torvalds 		goto out_freeiov;
22371da177e4SLinus Torvalds 	len = err;
22381da177e4SLinus Torvalds 
22391da177e4SLinus Torvalds 	if (uaddr != NULL) {
224043db362dSMaciej Żenczykowski 		err = move_addr_to_user(&addr,
2241a2e27255SArnaldo Carvalho de Melo 					msg_sys->msg_namelen, uaddr,
224289bddce5SStephen Hemminger 					uaddr_len);
22431da177e4SLinus Torvalds 		if (err < 0)
22441da177e4SLinus Torvalds 			goto out_freeiov;
22451da177e4SLinus Torvalds 	}
2246a2e27255SArnaldo Carvalho de Melo 	err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
224737f7f421SDavid S. Miller 			 COMPAT_FLAGS(msg));
22481da177e4SLinus Torvalds 	if (err)
22491da177e4SLinus Torvalds 		goto out_freeiov;
22501da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags)
2251a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
22521da177e4SLinus Torvalds 				 &msg_compat->msg_controllen);
22531da177e4SLinus Torvalds 	else
2254a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
22551da177e4SLinus Torvalds 				 &msg->msg_controllen);
22561da177e4SLinus Torvalds 	if (err)
22571da177e4SLinus Torvalds 		goto out_freeiov;
22581da177e4SLinus Torvalds 	err = len;
22591da177e4SLinus Torvalds 
22601da177e4SLinus Torvalds out_freeiov:
22611da177e4SLinus Torvalds 	if (iov != iovstack)
2262a74e9106SEric Dumazet 		kfree(iov);
2263a2e27255SArnaldo Carvalho de Melo out:
2264a2e27255SArnaldo Carvalho de Melo 	return err;
2265a2e27255SArnaldo Carvalho de Melo }
2266a2e27255SArnaldo Carvalho de Melo 
2267a2e27255SArnaldo Carvalho de Melo /*
2268a2e27255SArnaldo Carvalho de Melo  *	BSD recvmsg interface
2269a2e27255SArnaldo Carvalho de Melo  */
2270a2e27255SArnaldo Carvalho de Melo 
2271a2e27255SArnaldo Carvalho de Melo SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg,
2272a2e27255SArnaldo Carvalho de Melo 		unsigned int, flags)
2273a2e27255SArnaldo Carvalho de Melo {
2274a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err;
2275a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
2276a2e27255SArnaldo Carvalho de Melo 	struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed);
2277a2e27255SArnaldo Carvalho de Melo 
2278a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2279a2e27255SArnaldo Carvalho de Melo 		goto out;
2280a2e27255SArnaldo Carvalho de Melo 
2281a2e27255SArnaldo Carvalho de Melo 	err = __sys_recvmsg(sock, msg, &msg_sys, flags, 0);
2282a2e27255SArnaldo Carvalho de Melo 
22836cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
22841da177e4SLinus Torvalds out:
22851da177e4SLinus Torvalds 	return err;
22861da177e4SLinus Torvalds }
22871da177e4SLinus Torvalds 
2288a2e27255SArnaldo Carvalho de Melo /*
2289a2e27255SArnaldo Carvalho de Melo  *     Linux recvmmsg interface
2290a2e27255SArnaldo Carvalho de Melo  */
22911da177e4SLinus Torvalds 
2292a2e27255SArnaldo Carvalho de Melo int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2293a2e27255SArnaldo Carvalho de Melo 		   unsigned int flags, struct timespec *timeout)
2294a2e27255SArnaldo Carvalho de Melo {
2295a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err, datagrams;
2296a2e27255SArnaldo Carvalho de Melo 	struct socket *sock;
2297a2e27255SArnaldo Carvalho de Melo 	struct mmsghdr __user *entry;
2298d7256d0eSJean-Mickael Guerin 	struct compat_mmsghdr __user *compat_entry;
2299a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
2300a2e27255SArnaldo Carvalho de Melo 	struct timespec end_time;
2301a2e27255SArnaldo Carvalho de Melo 
2302a2e27255SArnaldo Carvalho de Melo 	if (timeout &&
2303a2e27255SArnaldo Carvalho de Melo 	    poll_select_set_timeout(&end_time, timeout->tv_sec,
2304a2e27255SArnaldo Carvalho de Melo 				    timeout->tv_nsec))
2305a2e27255SArnaldo Carvalho de Melo 		return -EINVAL;
2306a2e27255SArnaldo Carvalho de Melo 
2307a2e27255SArnaldo Carvalho de Melo 	datagrams = 0;
2308a2e27255SArnaldo Carvalho de Melo 
2309a2e27255SArnaldo Carvalho de Melo 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2310a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2311a2e27255SArnaldo Carvalho de Melo 		return err;
2312a2e27255SArnaldo Carvalho de Melo 
2313a2e27255SArnaldo Carvalho de Melo 	err = sock_error(sock->sk);
2314a2e27255SArnaldo Carvalho de Melo 	if (err)
2315a2e27255SArnaldo Carvalho de Melo 		goto out_put;
2316a2e27255SArnaldo Carvalho de Melo 
2317a2e27255SArnaldo Carvalho de Melo 	entry = mmsg;
2318d7256d0eSJean-Mickael Guerin 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2319a2e27255SArnaldo Carvalho de Melo 
2320a2e27255SArnaldo Carvalho de Melo 	while (datagrams < vlen) {
2321a2e27255SArnaldo Carvalho de Melo 		/*
2322a2e27255SArnaldo Carvalho de Melo 		 * No need to ask LSM for more than the first datagram.
2323a2e27255SArnaldo Carvalho de Melo 		 */
2324d7256d0eSJean-Mickael Guerin 		if (MSG_CMSG_COMPAT & flags) {
2325d7256d0eSJean-Mickael Guerin 			err = __sys_recvmsg(sock, (struct msghdr __user *)compat_entry,
2326b9eb8b87SAnton Blanchard 					    &msg_sys, flags & ~MSG_WAITFORONE,
2327b9eb8b87SAnton Blanchard 					    datagrams);
2328d7256d0eSJean-Mickael Guerin 			if (err < 0)
2329d7256d0eSJean-Mickael Guerin 				break;
2330d7256d0eSJean-Mickael Guerin 			err = __put_user(err, &compat_entry->msg_len);
2331d7256d0eSJean-Mickael Guerin 			++compat_entry;
2332d7256d0eSJean-Mickael Guerin 		} else {
2333a2e27255SArnaldo Carvalho de Melo 			err = __sys_recvmsg(sock, (struct msghdr __user *)entry,
2334b9eb8b87SAnton Blanchard 					    &msg_sys, flags & ~MSG_WAITFORONE,
2335b9eb8b87SAnton Blanchard 					    datagrams);
2336a2e27255SArnaldo Carvalho de Melo 			if (err < 0)
2337a2e27255SArnaldo Carvalho de Melo 				break;
2338a2e27255SArnaldo Carvalho de Melo 			err = put_user(err, &entry->msg_len);
2339d7256d0eSJean-Mickael Guerin 			++entry;
2340d7256d0eSJean-Mickael Guerin 		}
2341d7256d0eSJean-Mickael Guerin 
2342a2e27255SArnaldo Carvalho de Melo 		if (err)
2343a2e27255SArnaldo Carvalho de Melo 			break;
2344a2e27255SArnaldo Carvalho de Melo 		++datagrams;
2345a2e27255SArnaldo Carvalho de Melo 
234671c5c159SBrandon L Black 		/* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
234771c5c159SBrandon L Black 		if (flags & MSG_WAITFORONE)
234871c5c159SBrandon L Black 			flags |= MSG_DONTWAIT;
234971c5c159SBrandon L Black 
2350a2e27255SArnaldo Carvalho de Melo 		if (timeout) {
2351a2e27255SArnaldo Carvalho de Melo 			ktime_get_ts(timeout);
2352a2e27255SArnaldo Carvalho de Melo 			*timeout = timespec_sub(end_time, *timeout);
2353a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_sec < 0) {
2354a2e27255SArnaldo Carvalho de Melo 				timeout->tv_sec = timeout->tv_nsec = 0;
2355a2e27255SArnaldo Carvalho de Melo 				break;
2356a2e27255SArnaldo Carvalho de Melo 			}
2357a2e27255SArnaldo Carvalho de Melo 
2358a2e27255SArnaldo Carvalho de Melo 			/* Timeout, return less than vlen datagrams */
2359a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_nsec == 0 && timeout->tv_sec == 0)
2360a2e27255SArnaldo Carvalho de Melo 				break;
2361a2e27255SArnaldo Carvalho de Melo 		}
2362a2e27255SArnaldo Carvalho de Melo 
2363a2e27255SArnaldo Carvalho de Melo 		/* Out of band data, return right away */
2364a2e27255SArnaldo Carvalho de Melo 		if (msg_sys.msg_flags & MSG_OOB)
2365a2e27255SArnaldo Carvalho de Melo 			break;
2366a2e27255SArnaldo Carvalho de Melo 	}
2367a2e27255SArnaldo Carvalho de Melo 
2368a2e27255SArnaldo Carvalho de Melo out_put:
2369a2e27255SArnaldo Carvalho de Melo 	fput_light(sock->file, fput_needed);
2370a2e27255SArnaldo Carvalho de Melo 
2371a2e27255SArnaldo Carvalho de Melo 	if (err == 0)
2372a2e27255SArnaldo Carvalho de Melo 		return datagrams;
2373a2e27255SArnaldo Carvalho de Melo 
2374a2e27255SArnaldo Carvalho de Melo 	if (datagrams != 0) {
2375a2e27255SArnaldo Carvalho de Melo 		/*
2376a2e27255SArnaldo Carvalho de Melo 		 * We may return less entries than requested (vlen) if the
2377a2e27255SArnaldo Carvalho de Melo 		 * sock is non block and there aren't enough datagrams...
2378a2e27255SArnaldo Carvalho de Melo 		 */
2379a2e27255SArnaldo Carvalho de Melo 		if (err != -EAGAIN) {
2380a2e27255SArnaldo Carvalho de Melo 			/*
2381a2e27255SArnaldo Carvalho de Melo 			 * ... or  if recvmsg returns an error after we
2382a2e27255SArnaldo Carvalho de Melo 			 * received some datagrams, where we record the
2383a2e27255SArnaldo Carvalho de Melo 			 * error to return on the next call or if the
2384a2e27255SArnaldo Carvalho de Melo 			 * app asks about it using getsockopt(SO_ERROR).
2385a2e27255SArnaldo Carvalho de Melo 			 */
2386a2e27255SArnaldo Carvalho de Melo 			sock->sk->sk_err = -err;
2387a2e27255SArnaldo Carvalho de Melo 		}
2388a2e27255SArnaldo Carvalho de Melo 
2389a2e27255SArnaldo Carvalho de Melo 		return datagrams;
2390a2e27255SArnaldo Carvalho de Melo 	}
2391a2e27255SArnaldo Carvalho de Melo 
2392a2e27255SArnaldo Carvalho de Melo 	return err;
2393a2e27255SArnaldo Carvalho de Melo }
2394a2e27255SArnaldo Carvalho de Melo 
2395a2e27255SArnaldo Carvalho de Melo SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
2396a2e27255SArnaldo Carvalho de Melo 		unsigned int, vlen, unsigned int, flags,
2397a2e27255SArnaldo Carvalho de Melo 		struct timespec __user *, timeout)
2398a2e27255SArnaldo Carvalho de Melo {
2399a2e27255SArnaldo Carvalho de Melo 	int datagrams;
2400a2e27255SArnaldo Carvalho de Melo 	struct timespec timeout_sys;
2401a2e27255SArnaldo Carvalho de Melo 
2402a2e27255SArnaldo Carvalho de Melo 	if (!timeout)
2403a2e27255SArnaldo Carvalho de Melo 		return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL);
2404a2e27255SArnaldo Carvalho de Melo 
2405a2e27255SArnaldo Carvalho de Melo 	if (copy_from_user(&timeout_sys, timeout, sizeof(timeout_sys)))
2406a2e27255SArnaldo Carvalho de Melo 		return -EFAULT;
2407a2e27255SArnaldo Carvalho de Melo 
2408a2e27255SArnaldo Carvalho de Melo 	datagrams = __sys_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys);
2409a2e27255SArnaldo Carvalho de Melo 
2410a2e27255SArnaldo Carvalho de Melo 	if (datagrams > 0 &&
2411a2e27255SArnaldo Carvalho de Melo 	    copy_to_user(timeout, &timeout_sys, sizeof(timeout_sys)))
2412a2e27255SArnaldo Carvalho de Melo 		datagrams = -EFAULT;
2413a2e27255SArnaldo Carvalho de Melo 
2414a2e27255SArnaldo Carvalho de Melo 	return datagrams;
2415a2e27255SArnaldo Carvalho de Melo }
2416a2e27255SArnaldo Carvalho de Melo 
2417a2e27255SArnaldo Carvalho de Melo #ifdef __ARCH_WANT_SYS_SOCKETCALL
24181da177e4SLinus Torvalds /* Argument list sizes for sys_socketcall */
24191da177e4SLinus Torvalds #define AL(x) ((x) * sizeof(unsigned long))
2420228e548eSAnton Blanchard static const unsigned char nargs[21] = {
242189bddce5SStephen Hemminger 	AL(0), AL(3), AL(3), AL(3), AL(2), AL(3),
24221da177e4SLinus Torvalds 	AL(3), AL(3), AL(4), AL(4), AL(4), AL(6),
2423aaca0bdcSUlrich Drepper 	AL(6), AL(2), AL(5), AL(5), AL(3), AL(3),
2424228e548eSAnton Blanchard 	AL(4), AL(5), AL(4)
242589bddce5SStephen Hemminger };
242689bddce5SStephen Hemminger 
24271da177e4SLinus Torvalds #undef AL
24281da177e4SLinus Torvalds 
24291da177e4SLinus Torvalds /*
24301da177e4SLinus Torvalds  *	System call vectors.
24311da177e4SLinus Torvalds  *
24321da177e4SLinus Torvalds  *	Argument checking cleaned up. Saved 20% in size.
24331da177e4SLinus Torvalds  *  This function doesn't need to set the kernel lock because
24341da177e4SLinus Torvalds  *  it is set by the callees.
24351da177e4SLinus Torvalds  */
24361da177e4SLinus Torvalds 
24373e0fa65fSHeiko Carstens SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
24381da177e4SLinus Torvalds {
24391da177e4SLinus Torvalds 	unsigned long a[6];
24401da177e4SLinus Torvalds 	unsigned long a0, a1;
24411da177e4SLinus Torvalds 	int err;
244247379052SArjan van de Ven 	unsigned int len;
24431da177e4SLinus Torvalds 
2444228e548eSAnton Blanchard 	if (call < 1 || call > SYS_SENDMMSG)
24451da177e4SLinus Torvalds 		return -EINVAL;
24461da177e4SLinus Torvalds 
244747379052SArjan van de Ven 	len = nargs[call];
244847379052SArjan van de Ven 	if (len > sizeof(a))
244947379052SArjan van de Ven 		return -EINVAL;
245047379052SArjan van de Ven 
24511da177e4SLinus Torvalds 	/* copy_from_user should be SMP safe. */
245247379052SArjan van de Ven 	if (copy_from_user(a, args, len))
24531da177e4SLinus Torvalds 		return -EFAULT;
24541da177e4SLinus Torvalds 
2455f3298dc4SAl Viro 	audit_socketcall(nargs[call] / sizeof(unsigned long), a);
24563ec3b2fbSDavid Woodhouse 
24571da177e4SLinus Torvalds 	a0 = a[0];
24581da177e4SLinus Torvalds 	a1 = a[1];
24591da177e4SLinus Torvalds 
246089bddce5SStephen Hemminger 	switch (call) {
24611da177e4SLinus Torvalds 	case SYS_SOCKET:
24621da177e4SLinus Torvalds 		err = sys_socket(a0, a1, a[2]);
24631da177e4SLinus Torvalds 		break;
24641da177e4SLinus Torvalds 	case SYS_BIND:
24651da177e4SLinus Torvalds 		err = sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
24661da177e4SLinus Torvalds 		break;
24671da177e4SLinus Torvalds 	case SYS_CONNECT:
24681da177e4SLinus Torvalds 		err = sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
24691da177e4SLinus Torvalds 		break;
24701da177e4SLinus Torvalds 	case SYS_LISTEN:
24711da177e4SLinus Torvalds 		err = sys_listen(a0, a1);
24721da177e4SLinus Torvalds 		break;
24731da177e4SLinus Torvalds 	case SYS_ACCEPT:
2474de11defeSUlrich Drepper 		err = sys_accept4(a0, (struct sockaddr __user *)a1,
2475aaca0bdcSUlrich Drepper 				  (int __user *)a[2], 0);
24761da177e4SLinus Torvalds 		break;
24771da177e4SLinus Torvalds 	case SYS_GETSOCKNAME:
247889bddce5SStephen Hemminger 		err =
247989bddce5SStephen Hemminger 		    sys_getsockname(a0, (struct sockaddr __user *)a1,
248089bddce5SStephen Hemminger 				    (int __user *)a[2]);
24811da177e4SLinus Torvalds 		break;
24821da177e4SLinus Torvalds 	case SYS_GETPEERNAME:
248389bddce5SStephen Hemminger 		err =
248489bddce5SStephen Hemminger 		    sys_getpeername(a0, (struct sockaddr __user *)a1,
248589bddce5SStephen Hemminger 				    (int __user *)a[2]);
24861da177e4SLinus Torvalds 		break;
24871da177e4SLinus Torvalds 	case SYS_SOCKETPAIR:
24881da177e4SLinus Torvalds 		err = sys_socketpair(a0, a1, a[2], (int __user *)a[3]);
24891da177e4SLinus Torvalds 		break;
24901da177e4SLinus Torvalds 	case SYS_SEND:
24911da177e4SLinus Torvalds 		err = sys_send(a0, (void __user *)a1, a[2], a[3]);
24921da177e4SLinus Torvalds 		break;
24931da177e4SLinus Torvalds 	case SYS_SENDTO:
24941da177e4SLinus Torvalds 		err = sys_sendto(a0, (void __user *)a1, a[2], a[3],
24951da177e4SLinus Torvalds 				 (struct sockaddr __user *)a[4], a[5]);
24961da177e4SLinus Torvalds 		break;
24971da177e4SLinus Torvalds 	case SYS_RECV:
24981da177e4SLinus Torvalds 		err = sys_recv(a0, (void __user *)a1, a[2], a[3]);
24991da177e4SLinus Torvalds 		break;
25001da177e4SLinus Torvalds 	case SYS_RECVFROM:
25011da177e4SLinus Torvalds 		err = sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
250289bddce5SStephen Hemminger 				   (struct sockaddr __user *)a[4],
250389bddce5SStephen Hemminger 				   (int __user *)a[5]);
25041da177e4SLinus Torvalds 		break;
25051da177e4SLinus Torvalds 	case SYS_SHUTDOWN:
25061da177e4SLinus Torvalds 		err = sys_shutdown(a0, a1);
25071da177e4SLinus Torvalds 		break;
25081da177e4SLinus Torvalds 	case SYS_SETSOCKOPT:
25091da177e4SLinus Torvalds 		err = sys_setsockopt(a0, a1, a[2], (char __user *)a[3], a[4]);
25101da177e4SLinus Torvalds 		break;
25111da177e4SLinus Torvalds 	case SYS_GETSOCKOPT:
251289bddce5SStephen Hemminger 		err =
251389bddce5SStephen Hemminger 		    sys_getsockopt(a0, a1, a[2], (char __user *)a[3],
251489bddce5SStephen Hemminger 				   (int __user *)a[4]);
25151da177e4SLinus Torvalds 		break;
25161da177e4SLinus Torvalds 	case SYS_SENDMSG:
25171da177e4SLinus Torvalds 		err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]);
25181da177e4SLinus Torvalds 		break;
2519228e548eSAnton Blanchard 	case SYS_SENDMMSG:
2520228e548eSAnton Blanchard 		err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]);
2521228e548eSAnton Blanchard 		break;
25221da177e4SLinus Torvalds 	case SYS_RECVMSG:
25231da177e4SLinus Torvalds 		err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]);
25241da177e4SLinus Torvalds 		break;
2525a2e27255SArnaldo Carvalho de Melo 	case SYS_RECVMMSG:
2526a2e27255SArnaldo Carvalho de Melo 		err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3],
2527a2e27255SArnaldo Carvalho de Melo 				   (struct timespec __user *)a[4]);
2528a2e27255SArnaldo Carvalho de Melo 		break;
2529de11defeSUlrich Drepper 	case SYS_ACCEPT4:
2530de11defeSUlrich Drepper 		err = sys_accept4(a0, (struct sockaddr __user *)a1,
2531de11defeSUlrich Drepper 				  (int __user *)a[2], a[3]);
2532aaca0bdcSUlrich Drepper 		break;
25331da177e4SLinus Torvalds 	default:
25341da177e4SLinus Torvalds 		err = -EINVAL;
25351da177e4SLinus Torvalds 		break;
25361da177e4SLinus Torvalds 	}
25371da177e4SLinus Torvalds 	return err;
25381da177e4SLinus Torvalds }
25391da177e4SLinus Torvalds 
25401da177e4SLinus Torvalds #endif				/* __ARCH_WANT_SYS_SOCKETCALL */
25411da177e4SLinus Torvalds 
254255737fdaSStephen Hemminger /**
254355737fdaSStephen Hemminger  *	sock_register - add a socket protocol handler
254455737fdaSStephen Hemminger  *	@ops: description of protocol
254555737fdaSStephen Hemminger  *
25461da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
25471da177e4SLinus Torvalds  *	advertise its address family, and have it linked into the
254855737fdaSStephen Hemminger  *	socket interface. The value ops->family coresponds to the
254955737fdaSStephen Hemminger  *	socket system call protocol family.
25501da177e4SLinus Torvalds  */
2551f0fd27d4SStephen Hemminger int sock_register(const struct net_proto_family *ops)
25521da177e4SLinus Torvalds {
25531da177e4SLinus Torvalds 	int err;
25541da177e4SLinus Torvalds 
25551da177e4SLinus Torvalds 	if (ops->family >= NPROTO) {
255689bddce5SStephen Hemminger 		printk(KERN_CRIT "protocol %d >= NPROTO(%d)\n", ops->family,
255789bddce5SStephen Hemminger 		       NPROTO);
25581da177e4SLinus Torvalds 		return -ENOBUFS;
25591da177e4SLinus Torvalds 	}
256055737fdaSStephen Hemminger 
256155737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2562190683a9SEric Dumazet 	if (rcu_dereference_protected(net_families[ops->family],
2563190683a9SEric Dumazet 				      lockdep_is_held(&net_family_lock)))
25641da177e4SLinus Torvalds 		err = -EEXIST;
256555737fdaSStephen Hemminger 	else {
2566cf778b00SEric Dumazet 		rcu_assign_pointer(net_families[ops->family], ops);
25671da177e4SLinus Torvalds 		err = 0;
25681da177e4SLinus Torvalds 	}
256955737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
257055737fdaSStephen Hemminger 
257189bddce5SStephen Hemminger 	printk(KERN_INFO "NET: Registered protocol family %d\n", ops->family);
25721da177e4SLinus Torvalds 	return err;
25731da177e4SLinus Torvalds }
2574c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_register);
25751da177e4SLinus Torvalds 
257655737fdaSStephen Hemminger /**
257755737fdaSStephen Hemminger  *	sock_unregister - remove a protocol handler
257855737fdaSStephen Hemminger  *	@family: protocol family to remove
257955737fdaSStephen Hemminger  *
25801da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
25811da177e4SLinus Torvalds  *	remove its address family, and have it unlinked from the
258255737fdaSStephen Hemminger  *	new socket creation.
258355737fdaSStephen Hemminger  *
258455737fdaSStephen Hemminger  *	If protocol handler is a module, then it can use module reference
258555737fdaSStephen Hemminger  *	counts to protect against new references. If protocol handler is not
258655737fdaSStephen Hemminger  *	a module then it needs to provide its own protection in
258755737fdaSStephen Hemminger  *	the ops->create routine.
25881da177e4SLinus Torvalds  */
2589f0fd27d4SStephen Hemminger void sock_unregister(int family)
25901da177e4SLinus Torvalds {
2591f0fd27d4SStephen Hemminger 	BUG_ON(family < 0 || family >= NPROTO);
25921da177e4SLinus Torvalds 
259355737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2594a9b3cd7fSStephen Hemminger 	RCU_INIT_POINTER(net_families[family], NULL);
259555737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
259655737fdaSStephen Hemminger 
259755737fdaSStephen Hemminger 	synchronize_rcu();
259855737fdaSStephen Hemminger 
259989bddce5SStephen Hemminger 	printk(KERN_INFO "NET: Unregistered protocol family %d\n", family);
26001da177e4SLinus Torvalds }
2601c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_unregister);
26021da177e4SLinus Torvalds 
260377d76ea3SAndi Kleen static int __init sock_init(void)
26041da177e4SLinus Torvalds {
2605b3e19d92SNick Piggin 	int err;
26062ca794e5SEric W. Biederman 	/*
26072ca794e5SEric W. Biederman 	 *      Initialize the network sysctl infrastructure.
26082ca794e5SEric W. Biederman 	 */
26092ca794e5SEric W. Biederman 	err = net_sysctl_init();
26102ca794e5SEric W. Biederman 	if (err)
26112ca794e5SEric W. Biederman 		goto out;
2612b3e19d92SNick Piggin 
26131da177e4SLinus Torvalds 	/*
26141da177e4SLinus Torvalds 	 *      Initialize skbuff SLAB cache
26151da177e4SLinus Torvalds 	 */
26161da177e4SLinus Torvalds 	skb_init();
26171da177e4SLinus Torvalds 
26181da177e4SLinus Torvalds 	/*
26191da177e4SLinus Torvalds 	 *      Initialize the protocols module.
26201da177e4SLinus Torvalds 	 */
26211da177e4SLinus Torvalds 
26221da177e4SLinus Torvalds 	init_inodecache();
2623b3e19d92SNick Piggin 
2624b3e19d92SNick Piggin 	err = register_filesystem(&sock_fs_type);
2625b3e19d92SNick Piggin 	if (err)
2626b3e19d92SNick Piggin 		goto out_fs;
26271da177e4SLinus Torvalds 	sock_mnt = kern_mount(&sock_fs_type);
2628b3e19d92SNick Piggin 	if (IS_ERR(sock_mnt)) {
2629b3e19d92SNick Piggin 		err = PTR_ERR(sock_mnt);
2630b3e19d92SNick Piggin 		goto out_mount;
2631b3e19d92SNick Piggin 	}
263277d76ea3SAndi Kleen 
263377d76ea3SAndi Kleen 	/* The real protocol initialization is performed in later initcalls.
26341da177e4SLinus Torvalds 	 */
26351da177e4SLinus Torvalds 
26361da177e4SLinus Torvalds #ifdef CONFIG_NETFILTER
26371da177e4SLinus Torvalds 	netfilter_init();
26381da177e4SLinus Torvalds #endif
2639cbeb321aSDavid S. Miller 
2640c1f19b51SRichard Cochran #ifdef CONFIG_NETWORK_PHY_TIMESTAMPING
2641c1f19b51SRichard Cochran 	skb_timestamping_init();
2642c1f19b51SRichard Cochran #endif
2643c1f19b51SRichard Cochran 
2644b3e19d92SNick Piggin out:
2645b3e19d92SNick Piggin 	return err;
2646b3e19d92SNick Piggin 
2647b3e19d92SNick Piggin out_mount:
2648b3e19d92SNick Piggin 	unregister_filesystem(&sock_fs_type);
2649b3e19d92SNick Piggin out_fs:
2650b3e19d92SNick Piggin 	goto out;
26511da177e4SLinus Torvalds }
26521da177e4SLinus Torvalds 
265377d76ea3SAndi Kleen core_initcall(sock_init);	/* early initcall */
265477d76ea3SAndi Kleen 
26551da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS
26561da177e4SLinus Torvalds void socket_seq_show(struct seq_file *seq)
26571da177e4SLinus Torvalds {
26581da177e4SLinus Torvalds 	int cpu;
26591da177e4SLinus Torvalds 	int counter = 0;
26601da177e4SLinus Torvalds 
26616f912042SKAMEZAWA Hiroyuki 	for_each_possible_cpu(cpu)
26621da177e4SLinus Torvalds 	    counter += per_cpu(sockets_in_use, cpu);
26631da177e4SLinus Torvalds 
26641da177e4SLinus Torvalds 	/* It can be negative, by the way. 8) */
26651da177e4SLinus Torvalds 	if (counter < 0)
26661da177e4SLinus Torvalds 		counter = 0;
26671da177e4SLinus Torvalds 
26681da177e4SLinus Torvalds 	seq_printf(seq, "sockets: used %d\n", counter);
26691da177e4SLinus Torvalds }
26701da177e4SLinus Torvalds #endif				/* CONFIG_PROC_FS */
26711da177e4SLinus Torvalds 
267289bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
26736b96018bSArnd Bergmann static int do_siocgstamp(struct net *net, struct socket *sock,
2674644595f8SH. Peter Anvin 			 unsigned int cmd, void __user *up)
26757a229387SArnd Bergmann {
26767a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
26777a229387SArnd Bergmann 	struct timeval ktv;
26787a229387SArnd Bergmann 	int err;
26797a229387SArnd Bergmann 
26807a229387SArnd Bergmann 	set_fs(KERNEL_DS);
26816b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv);
26827a229387SArnd Bergmann 	set_fs(old_fs);
2683644595f8SH. Peter Anvin 	if (!err)
2684ed6fe9d6SMikulas Patocka 		err = compat_put_timeval(&ktv, up);
2685644595f8SH. Peter Anvin 
26867a229387SArnd Bergmann 	return err;
26877a229387SArnd Bergmann }
26887a229387SArnd Bergmann 
26896b96018bSArnd Bergmann static int do_siocgstampns(struct net *net, struct socket *sock,
2690644595f8SH. Peter Anvin 			   unsigned int cmd, void __user *up)
26917a229387SArnd Bergmann {
26927a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
26937a229387SArnd Bergmann 	struct timespec kts;
26947a229387SArnd Bergmann 	int err;
26957a229387SArnd Bergmann 
26967a229387SArnd Bergmann 	set_fs(KERNEL_DS);
26976b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts);
26987a229387SArnd Bergmann 	set_fs(old_fs);
2699644595f8SH. Peter Anvin 	if (!err)
2700ed6fe9d6SMikulas Patocka 		err = compat_put_timespec(&kts, up);
2701644595f8SH. Peter Anvin 
27027a229387SArnd Bergmann 	return err;
27037a229387SArnd Bergmann }
27047a229387SArnd Bergmann 
27056b96018bSArnd Bergmann static int dev_ifname32(struct net *net, struct compat_ifreq __user *uifr32)
27067a229387SArnd Bergmann {
27077a229387SArnd Bergmann 	struct ifreq __user *uifr;
27087a229387SArnd Bergmann 	int err;
27097a229387SArnd Bergmann 
27107a229387SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(struct ifreq));
27116b96018bSArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
27127a229387SArnd Bergmann 		return -EFAULT;
27137a229387SArnd Bergmann 
27146b96018bSArnd Bergmann 	err = dev_ioctl(net, SIOCGIFNAME, uifr);
27157a229387SArnd Bergmann 	if (err)
27167a229387SArnd Bergmann 		return err;
27177a229387SArnd Bergmann 
27186b96018bSArnd Bergmann 	if (copy_in_user(uifr32, uifr, sizeof(struct compat_ifreq)))
27197a229387SArnd Bergmann 		return -EFAULT;
27207a229387SArnd Bergmann 
27217a229387SArnd Bergmann 	return 0;
27227a229387SArnd Bergmann }
27237a229387SArnd Bergmann 
27246b96018bSArnd Bergmann static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32)
27257a229387SArnd Bergmann {
27266b96018bSArnd Bergmann 	struct compat_ifconf ifc32;
27277a229387SArnd Bergmann 	struct ifconf ifc;
27287a229387SArnd Bergmann 	struct ifconf __user *uifc;
27296b96018bSArnd Bergmann 	struct compat_ifreq __user *ifr32;
27307a229387SArnd Bergmann 	struct ifreq __user *ifr;
27317a229387SArnd Bergmann 	unsigned int i, j;
27327a229387SArnd Bergmann 	int err;
27337a229387SArnd Bergmann 
27346b96018bSArnd Bergmann 	if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf)))
27357a229387SArnd Bergmann 		return -EFAULT;
27367a229387SArnd Bergmann 
273743da5f2eSMathias Krause 	memset(&ifc, 0, sizeof(ifc));
27387a229387SArnd Bergmann 	if (ifc32.ifcbuf == 0) {
27397a229387SArnd Bergmann 		ifc32.ifc_len = 0;
27407a229387SArnd Bergmann 		ifc.ifc_len = 0;
27417a229387SArnd Bergmann 		ifc.ifc_req = NULL;
27427a229387SArnd Bergmann 		uifc = compat_alloc_user_space(sizeof(struct ifconf));
27437a229387SArnd Bergmann 	} else {
27446b96018bSArnd Bergmann 		size_t len = ((ifc32.ifc_len / sizeof(struct compat_ifreq)) + 1) *
27457a229387SArnd Bergmann 			sizeof(struct ifreq);
27467a229387SArnd Bergmann 		uifc = compat_alloc_user_space(sizeof(struct ifconf) + len);
27477a229387SArnd Bergmann 		ifc.ifc_len = len;
27487a229387SArnd Bergmann 		ifr = ifc.ifc_req = (void __user *)(uifc + 1);
27497a229387SArnd Bergmann 		ifr32 = compat_ptr(ifc32.ifcbuf);
27506b96018bSArnd Bergmann 		for (i = 0; i < ifc32.ifc_len; i += sizeof(struct compat_ifreq)) {
27516b96018bSArnd Bergmann 			if (copy_in_user(ifr, ifr32, sizeof(struct compat_ifreq)))
27527a229387SArnd Bergmann 				return -EFAULT;
27537a229387SArnd Bergmann 			ifr++;
27547a229387SArnd Bergmann 			ifr32++;
27557a229387SArnd Bergmann 		}
27567a229387SArnd Bergmann 	}
27577a229387SArnd Bergmann 	if (copy_to_user(uifc, &ifc, sizeof(struct ifconf)))
27587a229387SArnd Bergmann 		return -EFAULT;
27597a229387SArnd Bergmann 
27606b96018bSArnd Bergmann 	err = dev_ioctl(net, SIOCGIFCONF, uifc);
27617a229387SArnd Bergmann 	if (err)
27627a229387SArnd Bergmann 		return err;
27637a229387SArnd Bergmann 
27647a229387SArnd Bergmann 	if (copy_from_user(&ifc, uifc, sizeof(struct ifconf)))
27657a229387SArnd Bergmann 		return -EFAULT;
27667a229387SArnd Bergmann 
27677a229387SArnd Bergmann 	ifr = ifc.ifc_req;
27687a229387SArnd Bergmann 	ifr32 = compat_ptr(ifc32.ifcbuf);
27697a229387SArnd Bergmann 	for (i = 0, j = 0;
27706b96018bSArnd Bergmann 	     i + sizeof(struct compat_ifreq) <= ifc32.ifc_len && j < ifc.ifc_len;
27716b96018bSArnd Bergmann 	     i += sizeof(struct compat_ifreq), j += sizeof(struct ifreq)) {
27726b96018bSArnd Bergmann 		if (copy_in_user(ifr32, ifr, sizeof(struct compat_ifreq)))
27737a229387SArnd Bergmann 			return -EFAULT;
27747a229387SArnd Bergmann 		ifr32++;
27757a229387SArnd Bergmann 		ifr++;
27767a229387SArnd Bergmann 	}
27777a229387SArnd Bergmann 
27787a229387SArnd Bergmann 	if (ifc32.ifcbuf == 0) {
27797a229387SArnd Bergmann 		/* Translate from 64-bit structure multiple to
27807a229387SArnd Bergmann 		 * a 32-bit one.
27817a229387SArnd Bergmann 		 */
27827a229387SArnd Bergmann 		i = ifc.ifc_len;
27836b96018bSArnd Bergmann 		i = ((i / sizeof(struct ifreq)) * sizeof(struct compat_ifreq));
27847a229387SArnd Bergmann 		ifc32.ifc_len = i;
27857a229387SArnd Bergmann 	} else {
27867a229387SArnd Bergmann 		ifc32.ifc_len = i;
27877a229387SArnd Bergmann 	}
27886b96018bSArnd Bergmann 	if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf)))
27897a229387SArnd Bergmann 		return -EFAULT;
27907a229387SArnd Bergmann 
27917a229387SArnd Bergmann 	return 0;
27927a229387SArnd Bergmann }
27937a229387SArnd Bergmann 
27946b96018bSArnd Bergmann static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
27957a229387SArnd Bergmann {
27963a7da39dSBen Hutchings 	struct compat_ethtool_rxnfc __user *compat_rxnfc;
27973a7da39dSBen Hutchings 	bool convert_in = false, convert_out = false;
27983a7da39dSBen Hutchings 	size_t buf_size = ALIGN(sizeof(struct ifreq), 8);
27993a7da39dSBen Hutchings 	struct ethtool_rxnfc __user *rxnfc;
28007a229387SArnd Bergmann 	struct ifreq __user *ifr;
28013a7da39dSBen Hutchings 	u32 rule_cnt = 0, actual_rule_cnt;
28023a7da39dSBen Hutchings 	u32 ethcmd;
28037a229387SArnd Bergmann 	u32 data;
28043a7da39dSBen Hutchings 	int ret;
28057a229387SArnd Bergmann 
28067a229387SArnd Bergmann 	if (get_user(data, &ifr32->ifr_ifru.ifru_data))
28077a229387SArnd Bergmann 		return -EFAULT;
28087a229387SArnd Bergmann 
28093a7da39dSBen Hutchings 	compat_rxnfc = compat_ptr(data);
28103a7da39dSBen Hutchings 
28113a7da39dSBen Hutchings 	if (get_user(ethcmd, &compat_rxnfc->cmd))
28127a229387SArnd Bergmann 		return -EFAULT;
28137a229387SArnd Bergmann 
28143a7da39dSBen Hutchings 	/* Most ethtool structures are defined without padding.
28153a7da39dSBen Hutchings 	 * Unfortunately struct ethtool_rxnfc is an exception.
28163a7da39dSBen Hutchings 	 */
28173a7da39dSBen Hutchings 	switch (ethcmd) {
28183a7da39dSBen Hutchings 	default:
28193a7da39dSBen Hutchings 		break;
28203a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLALL:
28213a7da39dSBen Hutchings 		/* Buffer size is variable */
28223a7da39dSBen Hutchings 		if (get_user(rule_cnt, &compat_rxnfc->rule_cnt))
28233a7da39dSBen Hutchings 			return -EFAULT;
28243a7da39dSBen Hutchings 		if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32))
28253a7da39dSBen Hutchings 			return -ENOMEM;
28263a7da39dSBen Hutchings 		buf_size += rule_cnt * sizeof(u32);
28273a7da39dSBen Hutchings 		/* fall through */
28283a7da39dSBen Hutchings 	case ETHTOOL_GRXRINGS:
28293a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLCNT:
28303a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRULE:
283155664f32SBen Hutchings 	case ETHTOOL_SRXCLSRLINS:
28323a7da39dSBen Hutchings 		convert_out = true;
28333a7da39dSBen Hutchings 		/* fall through */
28343a7da39dSBen Hutchings 	case ETHTOOL_SRXCLSRLDEL:
28353a7da39dSBen Hutchings 		buf_size += sizeof(struct ethtool_rxnfc);
28363a7da39dSBen Hutchings 		convert_in = true;
28373a7da39dSBen Hutchings 		break;
28383a7da39dSBen Hutchings 	}
28393a7da39dSBen Hutchings 
28403a7da39dSBen Hutchings 	ifr = compat_alloc_user_space(buf_size);
28413a7da39dSBen Hutchings 	rxnfc = (void *)ifr + ALIGN(sizeof(struct ifreq), 8);
28423a7da39dSBen Hutchings 
28433a7da39dSBen Hutchings 	if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
28443a7da39dSBen Hutchings 		return -EFAULT;
28453a7da39dSBen Hutchings 
28463a7da39dSBen Hutchings 	if (put_user(convert_in ? rxnfc : compat_ptr(data),
28473a7da39dSBen Hutchings 		     &ifr->ifr_ifru.ifru_data))
28483a7da39dSBen Hutchings 		return -EFAULT;
28493a7da39dSBen Hutchings 
28503a7da39dSBen Hutchings 	if (convert_in) {
2851127fe533SAlexander Duyck 		/* We expect there to be holes between fs.m_ext and
28523a7da39dSBen Hutchings 		 * fs.ring_cookie and at the end of fs, but nowhere else.
28533a7da39dSBen Hutchings 		 */
2854127fe533SAlexander Duyck 		BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_ext) +
2855127fe533SAlexander Duyck 			     sizeof(compat_rxnfc->fs.m_ext) !=
2856127fe533SAlexander Duyck 			     offsetof(struct ethtool_rxnfc, fs.m_ext) +
2857127fe533SAlexander Duyck 			     sizeof(rxnfc->fs.m_ext));
28583a7da39dSBen Hutchings 		BUILD_BUG_ON(
28593a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.location) -
28603a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) !=
28613a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.location) -
28623a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.ring_cookie));
28633a7da39dSBen Hutchings 
28643a7da39dSBen Hutchings 		if (copy_in_user(rxnfc, compat_rxnfc,
2865127fe533SAlexander Duyck 				 (void *)(&rxnfc->fs.m_ext + 1) -
28663a7da39dSBen Hutchings 				 (void *)rxnfc) ||
28673a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->fs.ring_cookie,
28683a7da39dSBen Hutchings 				 &compat_rxnfc->fs.ring_cookie,
28693a7da39dSBen Hutchings 				 (void *)(&rxnfc->fs.location + 1) -
28703a7da39dSBen Hutchings 				 (void *)&rxnfc->fs.ring_cookie) ||
28713a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt,
28723a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
28733a7da39dSBen Hutchings 			return -EFAULT;
28743a7da39dSBen Hutchings 	}
28753a7da39dSBen Hutchings 
28763a7da39dSBen Hutchings 	ret = dev_ioctl(net, SIOCETHTOOL, ifr);
28773a7da39dSBen Hutchings 	if (ret)
28783a7da39dSBen Hutchings 		return ret;
28793a7da39dSBen Hutchings 
28803a7da39dSBen Hutchings 	if (convert_out) {
28813a7da39dSBen Hutchings 		if (copy_in_user(compat_rxnfc, rxnfc,
2882127fe533SAlexander Duyck 				 (const void *)(&rxnfc->fs.m_ext + 1) -
28833a7da39dSBen Hutchings 				 (const void *)rxnfc) ||
28843a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->fs.ring_cookie,
28853a7da39dSBen Hutchings 				 &rxnfc->fs.ring_cookie,
28863a7da39dSBen Hutchings 				 (const void *)(&rxnfc->fs.location + 1) -
28873a7da39dSBen Hutchings 				 (const void *)&rxnfc->fs.ring_cookie) ||
28883a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt,
28893a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
28903a7da39dSBen Hutchings 			return -EFAULT;
28913a7da39dSBen Hutchings 
28923a7da39dSBen Hutchings 		if (ethcmd == ETHTOOL_GRXCLSRLALL) {
28933a7da39dSBen Hutchings 			/* As an optimisation, we only copy the actual
28943a7da39dSBen Hutchings 			 * number of rules that the underlying
28953a7da39dSBen Hutchings 			 * function returned.  Since Mallory might
28963a7da39dSBen Hutchings 			 * change the rule count in user memory, we
28973a7da39dSBen Hutchings 			 * check that it is less than the rule count
28983a7da39dSBen Hutchings 			 * originally given (as the user buffer size),
28993a7da39dSBen Hutchings 			 * which has been range-checked.
29003a7da39dSBen Hutchings 			 */
29013a7da39dSBen Hutchings 			if (get_user(actual_rule_cnt, &rxnfc->rule_cnt))
29023a7da39dSBen Hutchings 				return -EFAULT;
29033a7da39dSBen Hutchings 			if (actual_rule_cnt < rule_cnt)
29043a7da39dSBen Hutchings 				rule_cnt = actual_rule_cnt;
29053a7da39dSBen Hutchings 			if (copy_in_user(&compat_rxnfc->rule_locs[0],
29063a7da39dSBen Hutchings 					 &rxnfc->rule_locs[0],
29073a7da39dSBen Hutchings 					 rule_cnt * sizeof(u32)))
29083a7da39dSBen Hutchings 				return -EFAULT;
29093a7da39dSBen Hutchings 		}
29103a7da39dSBen Hutchings 	}
29113a7da39dSBen Hutchings 
29123a7da39dSBen Hutchings 	return 0;
29137a229387SArnd Bergmann }
29147a229387SArnd Bergmann 
29157a50a240SArnd Bergmann static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32)
29167a50a240SArnd Bergmann {
29177a50a240SArnd Bergmann 	void __user *uptr;
29187a50a240SArnd Bergmann 	compat_uptr_t uptr32;
29197a50a240SArnd Bergmann 	struct ifreq __user *uifr;
29207a50a240SArnd Bergmann 
29217a50a240SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
29227a50a240SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
29237a50a240SArnd Bergmann 		return -EFAULT;
29247a50a240SArnd Bergmann 
29257a50a240SArnd Bergmann 	if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu))
29267a50a240SArnd Bergmann 		return -EFAULT;
29277a50a240SArnd Bergmann 
29287a50a240SArnd Bergmann 	uptr = compat_ptr(uptr32);
29297a50a240SArnd Bergmann 
29307a50a240SArnd Bergmann 	if (put_user(uptr, &uifr->ifr_settings.ifs_ifsu.raw_hdlc))
29317a50a240SArnd Bergmann 		return -EFAULT;
29327a50a240SArnd Bergmann 
29337a50a240SArnd Bergmann 	return dev_ioctl(net, SIOCWANDEV, uifr);
29347a50a240SArnd Bergmann }
29357a50a240SArnd Bergmann 
29366b96018bSArnd Bergmann static int bond_ioctl(struct net *net, unsigned int cmd,
29376b96018bSArnd Bergmann 			 struct compat_ifreq __user *ifr32)
29387a229387SArnd Bergmann {
29397a229387SArnd Bergmann 	struct ifreq kifr;
29407a229387SArnd Bergmann 	struct ifreq __user *uifr;
29417a229387SArnd Bergmann 	mm_segment_t old_fs;
29427a229387SArnd Bergmann 	int err;
29437a229387SArnd Bergmann 	u32 data;
29447a229387SArnd Bergmann 	void __user *datap;
29457a229387SArnd Bergmann 
29467a229387SArnd Bergmann 	switch (cmd) {
29477a229387SArnd Bergmann 	case SIOCBONDENSLAVE:
29487a229387SArnd Bergmann 	case SIOCBONDRELEASE:
29497a229387SArnd Bergmann 	case SIOCBONDSETHWADDR:
29507a229387SArnd Bergmann 	case SIOCBONDCHANGEACTIVE:
29516b96018bSArnd Bergmann 		if (copy_from_user(&kifr, ifr32, sizeof(struct compat_ifreq)))
29527a229387SArnd Bergmann 			return -EFAULT;
29537a229387SArnd Bergmann 
29547a229387SArnd Bergmann 		old_fs = get_fs();
29557a229387SArnd Bergmann 		set_fs(KERNEL_DS);
2956c3f52ae6Sstephen hemminger 		err = dev_ioctl(net, cmd,
2957c3f52ae6Sstephen hemminger 				(struct ifreq __user __force *) &kifr);
29587a229387SArnd Bergmann 		set_fs(old_fs);
29597a229387SArnd Bergmann 
29607a229387SArnd Bergmann 		return err;
29617a229387SArnd Bergmann 	case SIOCBONDSLAVEINFOQUERY:
29627a229387SArnd Bergmann 	case SIOCBONDINFOQUERY:
29637a229387SArnd Bergmann 		uifr = compat_alloc_user_space(sizeof(*uifr));
29647a229387SArnd Bergmann 		if (copy_in_user(&uifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
29657a229387SArnd Bergmann 			return -EFAULT;
29667a229387SArnd Bergmann 
29677a229387SArnd Bergmann 		if (get_user(data, &ifr32->ifr_ifru.ifru_data))
29687a229387SArnd Bergmann 			return -EFAULT;
29697a229387SArnd Bergmann 
29707a229387SArnd Bergmann 		datap = compat_ptr(data);
29717a229387SArnd Bergmann 		if (put_user(datap, &uifr->ifr_ifru.ifru_data))
29727a229387SArnd Bergmann 			return -EFAULT;
29737a229387SArnd Bergmann 
29746b96018bSArnd Bergmann 		return dev_ioctl(net, cmd, uifr);
29757a229387SArnd Bergmann 	default:
297607d106d0SLinus Torvalds 		return -ENOIOCTLCMD;
2977ccbd6a5aSJoe Perches 	}
29787a229387SArnd Bergmann }
29797a229387SArnd Bergmann 
29806b96018bSArnd Bergmann static int siocdevprivate_ioctl(struct net *net, unsigned int cmd,
29816b96018bSArnd Bergmann 				 struct compat_ifreq __user *u_ifreq32)
29827a229387SArnd Bergmann {
29837a229387SArnd Bergmann 	struct ifreq __user *u_ifreq64;
29847a229387SArnd Bergmann 	char tmp_buf[IFNAMSIZ];
29857a229387SArnd Bergmann 	void __user *data64;
29867a229387SArnd Bergmann 	u32 data32;
29877a229387SArnd Bergmann 
29887a229387SArnd Bergmann 	if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]),
29897a229387SArnd Bergmann 			   IFNAMSIZ))
29907a229387SArnd Bergmann 		return -EFAULT;
29917a229387SArnd Bergmann 	if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data))
29927a229387SArnd Bergmann 		return -EFAULT;
29937a229387SArnd Bergmann 	data64 = compat_ptr(data32);
29947a229387SArnd Bergmann 
29957a229387SArnd Bergmann 	u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
29967a229387SArnd Bergmann 
29977a229387SArnd Bergmann 	/* Don't check these user accesses, just let that get trapped
29987a229387SArnd Bergmann 	 * in the ioctl handler instead.
29997a229387SArnd Bergmann 	 */
30007a229387SArnd Bergmann 	if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0],
30017a229387SArnd Bergmann 			 IFNAMSIZ))
30027a229387SArnd Bergmann 		return -EFAULT;
30037a229387SArnd Bergmann 	if (__put_user(data64, &u_ifreq64->ifr_ifru.ifru_data))
30047a229387SArnd Bergmann 		return -EFAULT;
30057a229387SArnd Bergmann 
30066b96018bSArnd Bergmann 	return dev_ioctl(net, cmd, u_ifreq64);
30077a229387SArnd Bergmann }
30087a229387SArnd Bergmann 
30096b96018bSArnd Bergmann static int dev_ifsioc(struct net *net, struct socket *sock,
30106b96018bSArnd Bergmann 			 unsigned int cmd, struct compat_ifreq __user *uifr32)
30117a229387SArnd Bergmann {
3012a2116ed2SArnd Bergmann 	struct ifreq __user *uifr;
30137a229387SArnd Bergmann 	int err;
30147a229387SArnd Bergmann 
3015a2116ed2SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
3016a2116ed2SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(*uifr32)))
30177a229387SArnd Bergmann 		return -EFAULT;
3018a2116ed2SArnd Bergmann 
3019a2116ed2SArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr);
3020a2116ed2SArnd Bergmann 
30217a229387SArnd Bergmann 	if (!err) {
30227a229387SArnd Bergmann 		switch (cmd) {
30237a229387SArnd Bergmann 		case SIOCGIFFLAGS:
30247a229387SArnd Bergmann 		case SIOCGIFMETRIC:
30257a229387SArnd Bergmann 		case SIOCGIFMTU:
30267a229387SArnd Bergmann 		case SIOCGIFMEM:
30277a229387SArnd Bergmann 		case SIOCGIFHWADDR:
30287a229387SArnd Bergmann 		case SIOCGIFINDEX:
30297a229387SArnd Bergmann 		case SIOCGIFADDR:
30307a229387SArnd Bergmann 		case SIOCGIFBRDADDR:
30317a229387SArnd Bergmann 		case SIOCGIFDSTADDR:
30327a229387SArnd Bergmann 		case SIOCGIFNETMASK:
3033fab2532bSArnd Bergmann 		case SIOCGIFPFLAGS:
30347a229387SArnd Bergmann 		case SIOCGIFTXQLEN:
3035fab2532bSArnd Bergmann 		case SIOCGMIIPHY:
3036fab2532bSArnd Bergmann 		case SIOCGMIIREG:
3037a2116ed2SArnd Bergmann 			if (copy_in_user(uifr32, uifr, sizeof(*uifr32)))
3038a2116ed2SArnd Bergmann 				err = -EFAULT;
30397a229387SArnd Bergmann 			break;
3040a2116ed2SArnd Bergmann 		}
3041a2116ed2SArnd Bergmann 	}
3042a2116ed2SArnd Bergmann 	return err;
3043a2116ed2SArnd Bergmann }
3044a2116ed2SArnd Bergmann 
3045a2116ed2SArnd Bergmann static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
3046a2116ed2SArnd Bergmann 			struct compat_ifreq __user *uifr32)
3047a2116ed2SArnd Bergmann {
3048a2116ed2SArnd Bergmann 	struct ifreq ifr;
3049a2116ed2SArnd Bergmann 	struct compat_ifmap __user *uifmap32;
3050a2116ed2SArnd Bergmann 	mm_segment_t old_fs;
3051a2116ed2SArnd Bergmann 	int err;
3052a2116ed2SArnd Bergmann 
3053a2116ed2SArnd Bergmann 	uifmap32 = &uifr32->ifr_ifru.ifru_map;
3054a2116ed2SArnd Bergmann 	err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name));
3055a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
3056a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
3057a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
3058a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.irq, &uifmap32->irq);
3059a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.dma, &uifmap32->dma);
3060a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.port, &uifmap32->port);
3061a2116ed2SArnd Bergmann 	if (err)
3062a2116ed2SArnd Bergmann 		return -EFAULT;
3063a2116ed2SArnd Bergmann 
3064a2116ed2SArnd Bergmann 	old_fs = get_fs();
3065a2116ed2SArnd Bergmann 	set_fs(KERNEL_DS);
3066c3f52ae6Sstephen hemminger 	err = dev_ioctl(net, cmd, (void  __user __force *)&ifr);
3067a2116ed2SArnd Bergmann 	set_fs(old_fs);
3068a2116ed2SArnd Bergmann 
3069a2116ed2SArnd Bergmann 	if (cmd == SIOCGIFMAP && !err) {
30707a229387SArnd Bergmann 		err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name));
30717a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
30727a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
30737a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
30747a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.irq, &uifmap32->irq);
30757a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.dma, &uifmap32->dma);
30767a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.port, &uifmap32->port);
30777a229387SArnd Bergmann 		if (err)
30787a229387SArnd Bergmann 			err = -EFAULT;
30797a229387SArnd Bergmann 	}
30807a229387SArnd Bergmann 	return err;
30817a229387SArnd Bergmann }
30827a229387SArnd Bergmann 
3083a2116ed2SArnd Bergmann static int compat_siocshwtstamp(struct net *net, struct compat_ifreq __user *uifr32)
3084a2116ed2SArnd Bergmann {
3085a2116ed2SArnd Bergmann 	void __user *uptr;
3086a2116ed2SArnd Bergmann 	compat_uptr_t uptr32;
3087a2116ed2SArnd Bergmann 	struct ifreq __user *uifr;
3088a2116ed2SArnd Bergmann 
3089a2116ed2SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
3090a2116ed2SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
3091a2116ed2SArnd Bergmann 		return -EFAULT;
3092a2116ed2SArnd Bergmann 
3093a2116ed2SArnd Bergmann 	if (get_user(uptr32, &uifr32->ifr_data))
3094a2116ed2SArnd Bergmann 		return -EFAULT;
3095a2116ed2SArnd Bergmann 
3096a2116ed2SArnd Bergmann 	uptr = compat_ptr(uptr32);
3097a2116ed2SArnd Bergmann 
3098a2116ed2SArnd Bergmann 	if (put_user(uptr, &uifr->ifr_data))
3099a2116ed2SArnd Bergmann 		return -EFAULT;
3100a2116ed2SArnd Bergmann 
3101a2116ed2SArnd Bergmann 	return dev_ioctl(net, SIOCSHWTSTAMP, uifr);
3102a2116ed2SArnd Bergmann }
3103a2116ed2SArnd Bergmann 
31047a229387SArnd Bergmann struct rtentry32 {
31057a229387SArnd Bergmann 	u32		rt_pad1;
31067a229387SArnd Bergmann 	struct sockaddr rt_dst;         /* target address               */
31077a229387SArnd Bergmann 	struct sockaddr rt_gateway;     /* gateway addr (RTF_GATEWAY)   */
31087a229387SArnd Bergmann 	struct sockaddr rt_genmask;     /* target network mask (IP)     */
31097a229387SArnd Bergmann 	unsigned short	rt_flags;
31107a229387SArnd Bergmann 	short		rt_pad2;
31117a229387SArnd Bergmann 	u32		rt_pad3;
31127a229387SArnd Bergmann 	unsigned char	rt_tos;
31137a229387SArnd Bergmann 	unsigned char	rt_class;
31147a229387SArnd Bergmann 	short		rt_pad4;
31157a229387SArnd Bergmann 	short		rt_metric;      /* +1 for binary compatibility! */
31167a229387SArnd Bergmann 	/* char * */ u32 rt_dev;        /* forcing the device at add    */
31177a229387SArnd Bergmann 	u32		rt_mtu;         /* per route MTU/Window         */
31187a229387SArnd Bergmann 	u32		rt_window;      /* Window clamping              */
31197a229387SArnd Bergmann 	unsigned short  rt_irtt;        /* Initial RTT                  */
31207a229387SArnd Bergmann };
31217a229387SArnd Bergmann 
31227a229387SArnd Bergmann struct in6_rtmsg32 {
31237a229387SArnd Bergmann 	struct in6_addr		rtmsg_dst;
31247a229387SArnd Bergmann 	struct in6_addr		rtmsg_src;
31257a229387SArnd Bergmann 	struct in6_addr		rtmsg_gateway;
31267a229387SArnd Bergmann 	u32			rtmsg_type;
31277a229387SArnd Bergmann 	u16			rtmsg_dst_len;
31287a229387SArnd Bergmann 	u16			rtmsg_src_len;
31297a229387SArnd Bergmann 	u32			rtmsg_metric;
31307a229387SArnd Bergmann 	u32			rtmsg_info;
31317a229387SArnd Bergmann 	u32			rtmsg_flags;
31327a229387SArnd Bergmann 	s32			rtmsg_ifindex;
31337a229387SArnd Bergmann };
31347a229387SArnd Bergmann 
31356b96018bSArnd Bergmann static int routing_ioctl(struct net *net, struct socket *sock,
31366b96018bSArnd Bergmann 			 unsigned int cmd, void __user *argp)
31377a229387SArnd Bergmann {
31387a229387SArnd Bergmann 	int ret;
31397a229387SArnd Bergmann 	void *r = NULL;
31407a229387SArnd Bergmann 	struct in6_rtmsg r6;
31417a229387SArnd Bergmann 	struct rtentry r4;
31427a229387SArnd Bergmann 	char devname[16];
31437a229387SArnd Bergmann 	u32 rtdev;
31447a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
31457a229387SArnd Bergmann 
31466b96018bSArnd Bergmann 	if (sock && sock->sk && sock->sk->sk_family == AF_INET6) { /* ipv6 */
31476b96018bSArnd Bergmann 		struct in6_rtmsg32 __user *ur6 = argp;
31487a229387SArnd Bergmann 		ret = copy_from_user(&r6.rtmsg_dst, &(ur6->rtmsg_dst),
31497a229387SArnd Bergmann 			3 * sizeof(struct in6_addr));
31507a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_type, &(ur6->rtmsg_type));
31517a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len));
31527a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_src_len, &(ur6->rtmsg_src_len));
31537a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_metric, &(ur6->rtmsg_metric));
31547a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_info, &(ur6->rtmsg_info));
31557a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_flags, &(ur6->rtmsg_flags));
31567a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex));
31577a229387SArnd Bergmann 
31587a229387SArnd Bergmann 		r = (void *) &r6;
31597a229387SArnd Bergmann 	} else { /* ipv4 */
31606b96018bSArnd Bergmann 		struct rtentry32 __user *ur4 = argp;
31617a229387SArnd Bergmann 		ret = copy_from_user(&r4.rt_dst, &(ur4->rt_dst),
31627a229387SArnd Bergmann 					3 * sizeof(struct sockaddr));
31637a229387SArnd Bergmann 		ret |= __get_user(r4.rt_flags, &(ur4->rt_flags));
31647a229387SArnd Bergmann 		ret |= __get_user(r4.rt_metric, &(ur4->rt_metric));
31657a229387SArnd Bergmann 		ret |= __get_user(r4.rt_mtu, &(ur4->rt_mtu));
31667a229387SArnd Bergmann 		ret |= __get_user(r4.rt_window, &(ur4->rt_window));
31677a229387SArnd Bergmann 		ret |= __get_user(r4.rt_irtt, &(ur4->rt_irtt));
31687a229387SArnd Bergmann 		ret |= __get_user(rtdev, &(ur4->rt_dev));
31697a229387SArnd Bergmann 		if (rtdev) {
31707a229387SArnd Bergmann 			ret |= copy_from_user(devname, compat_ptr(rtdev), 15);
3171c3f52ae6Sstephen hemminger 			r4.rt_dev = (char __user __force *)devname;
3172c3f52ae6Sstephen hemminger 			devname[15] = 0;
31737a229387SArnd Bergmann 		} else
31747a229387SArnd Bergmann 			r4.rt_dev = NULL;
31757a229387SArnd Bergmann 
31767a229387SArnd Bergmann 		r = (void *) &r4;
31777a229387SArnd Bergmann 	}
31787a229387SArnd Bergmann 
31797a229387SArnd Bergmann 	if (ret) {
31807a229387SArnd Bergmann 		ret = -EFAULT;
31817a229387SArnd Bergmann 		goto out;
31827a229387SArnd Bergmann 	}
31837a229387SArnd Bergmann 
31847a229387SArnd Bergmann 	set_fs(KERNEL_DS);
31856b96018bSArnd Bergmann 	ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r);
31867a229387SArnd Bergmann 	set_fs(old_fs);
31877a229387SArnd Bergmann 
31887a229387SArnd Bergmann out:
31897a229387SArnd Bergmann 	return ret;
31907a229387SArnd Bergmann }
31917a229387SArnd Bergmann 
31927a229387SArnd Bergmann /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE
31937a229387SArnd Bergmann  * for some operations; this forces use of the newer bridge-utils that
319425985edcSLucas De Marchi  * use compatible ioctls
31957a229387SArnd Bergmann  */
31966b96018bSArnd Bergmann static int old_bridge_ioctl(compat_ulong_t __user *argp)
31977a229387SArnd Bergmann {
31986b96018bSArnd Bergmann 	compat_ulong_t tmp;
31997a229387SArnd Bergmann 
32006b96018bSArnd Bergmann 	if (get_user(tmp, argp))
32017a229387SArnd Bergmann 		return -EFAULT;
32027a229387SArnd Bergmann 	if (tmp == BRCTL_GET_VERSION)
32037a229387SArnd Bergmann 		return BRCTL_VERSION + 1;
32047a229387SArnd Bergmann 	return -EINVAL;
32057a229387SArnd Bergmann }
32067a229387SArnd Bergmann 
32076b96018bSArnd Bergmann static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
32086b96018bSArnd Bergmann 			 unsigned int cmd, unsigned long arg)
32096b96018bSArnd Bergmann {
32106b96018bSArnd Bergmann 	void __user *argp = compat_ptr(arg);
32116b96018bSArnd Bergmann 	struct sock *sk = sock->sk;
32126b96018bSArnd Bergmann 	struct net *net = sock_net(sk);
32137a229387SArnd Bergmann 
32146b96018bSArnd Bergmann 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
32156b96018bSArnd Bergmann 		return siocdevprivate_ioctl(net, cmd, argp);
32167a229387SArnd Bergmann 
32176b96018bSArnd Bergmann 	switch (cmd) {
32186b96018bSArnd Bergmann 	case SIOCSIFBR:
32196b96018bSArnd Bergmann 	case SIOCGIFBR:
32206b96018bSArnd Bergmann 		return old_bridge_ioctl(argp);
32216b96018bSArnd Bergmann 	case SIOCGIFNAME:
32226b96018bSArnd Bergmann 		return dev_ifname32(net, argp);
32236b96018bSArnd Bergmann 	case SIOCGIFCONF:
32246b96018bSArnd Bergmann 		return dev_ifconf(net, argp);
32256b96018bSArnd Bergmann 	case SIOCETHTOOL:
32266b96018bSArnd Bergmann 		return ethtool_ioctl(net, argp);
32277a50a240SArnd Bergmann 	case SIOCWANDEV:
32287a50a240SArnd Bergmann 		return compat_siocwandev(net, argp);
3229a2116ed2SArnd Bergmann 	case SIOCGIFMAP:
3230a2116ed2SArnd Bergmann 	case SIOCSIFMAP:
3231a2116ed2SArnd Bergmann 		return compat_sioc_ifmap(net, cmd, argp);
32326b96018bSArnd Bergmann 	case SIOCBONDENSLAVE:
32336b96018bSArnd Bergmann 	case SIOCBONDRELEASE:
32346b96018bSArnd Bergmann 	case SIOCBONDSETHWADDR:
32356b96018bSArnd Bergmann 	case SIOCBONDSLAVEINFOQUERY:
32366b96018bSArnd Bergmann 	case SIOCBONDINFOQUERY:
32376b96018bSArnd Bergmann 	case SIOCBONDCHANGEACTIVE:
32386b96018bSArnd Bergmann 		return bond_ioctl(net, cmd, argp);
32396b96018bSArnd Bergmann 	case SIOCADDRT:
32406b96018bSArnd Bergmann 	case SIOCDELRT:
32416b96018bSArnd Bergmann 		return routing_ioctl(net, sock, cmd, argp);
32426b96018bSArnd Bergmann 	case SIOCGSTAMP:
32436b96018bSArnd Bergmann 		return do_siocgstamp(net, sock, cmd, argp);
32446b96018bSArnd Bergmann 	case SIOCGSTAMPNS:
32456b96018bSArnd Bergmann 		return do_siocgstampns(net, sock, cmd, argp);
3246a2116ed2SArnd Bergmann 	case SIOCSHWTSTAMP:
3247a2116ed2SArnd Bergmann 		return compat_siocshwtstamp(net, argp);
32487a229387SArnd Bergmann 
32496b96018bSArnd Bergmann 	case FIOSETOWN:
32506b96018bSArnd Bergmann 	case SIOCSPGRP:
32516b96018bSArnd Bergmann 	case FIOGETOWN:
32526b96018bSArnd Bergmann 	case SIOCGPGRP:
32536b96018bSArnd Bergmann 	case SIOCBRADDBR:
32546b96018bSArnd Bergmann 	case SIOCBRDELBR:
32556b96018bSArnd Bergmann 	case SIOCGIFVLAN:
32566b96018bSArnd Bergmann 	case SIOCSIFVLAN:
32576b96018bSArnd Bergmann 	case SIOCADDDLCI:
32586b96018bSArnd Bergmann 	case SIOCDELDLCI:
32596b96018bSArnd Bergmann 		return sock_ioctl(file, cmd, arg);
32606b96018bSArnd Bergmann 
32616b96018bSArnd Bergmann 	case SIOCGIFFLAGS:
32626b96018bSArnd Bergmann 	case SIOCSIFFLAGS:
32636b96018bSArnd Bergmann 	case SIOCGIFMETRIC:
32646b96018bSArnd Bergmann 	case SIOCSIFMETRIC:
32656b96018bSArnd Bergmann 	case SIOCGIFMTU:
32666b96018bSArnd Bergmann 	case SIOCSIFMTU:
32676b96018bSArnd Bergmann 	case SIOCGIFMEM:
32686b96018bSArnd Bergmann 	case SIOCSIFMEM:
32696b96018bSArnd Bergmann 	case SIOCGIFHWADDR:
32706b96018bSArnd Bergmann 	case SIOCSIFHWADDR:
32716b96018bSArnd Bergmann 	case SIOCADDMULTI:
32726b96018bSArnd Bergmann 	case SIOCDELMULTI:
32736b96018bSArnd Bergmann 	case SIOCGIFINDEX:
32746b96018bSArnd Bergmann 	case SIOCGIFADDR:
32756b96018bSArnd Bergmann 	case SIOCSIFADDR:
32766b96018bSArnd Bergmann 	case SIOCSIFHWBROADCAST:
32776b96018bSArnd Bergmann 	case SIOCDIFADDR:
32786b96018bSArnd Bergmann 	case SIOCGIFBRDADDR:
32796b96018bSArnd Bergmann 	case SIOCSIFBRDADDR:
32806b96018bSArnd Bergmann 	case SIOCGIFDSTADDR:
32816b96018bSArnd Bergmann 	case SIOCSIFDSTADDR:
32826b96018bSArnd Bergmann 	case SIOCGIFNETMASK:
32836b96018bSArnd Bergmann 	case SIOCSIFNETMASK:
32846b96018bSArnd Bergmann 	case SIOCSIFPFLAGS:
32856b96018bSArnd Bergmann 	case SIOCGIFPFLAGS:
32866b96018bSArnd Bergmann 	case SIOCGIFTXQLEN:
32876b96018bSArnd Bergmann 	case SIOCSIFTXQLEN:
32886b96018bSArnd Bergmann 	case SIOCBRADDIF:
32896b96018bSArnd Bergmann 	case SIOCBRDELIF:
32909177efd3SArnd Bergmann 	case SIOCSIFNAME:
32919177efd3SArnd Bergmann 	case SIOCGMIIPHY:
32929177efd3SArnd Bergmann 	case SIOCGMIIREG:
32939177efd3SArnd Bergmann 	case SIOCSMIIREG:
32946b96018bSArnd Bergmann 		return dev_ifsioc(net, sock, cmd, argp);
32959177efd3SArnd Bergmann 
32966b96018bSArnd Bergmann 	case SIOCSARP:
32976b96018bSArnd Bergmann 	case SIOCGARP:
32986b96018bSArnd Bergmann 	case SIOCDARP:
32996b96018bSArnd Bergmann 	case SIOCATMARK:
33009177efd3SArnd Bergmann 		return sock_do_ioctl(net, sock, cmd, arg);
33019177efd3SArnd Bergmann 	}
33029177efd3SArnd Bergmann 
33036b96018bSArnd Bergmann 	return -ENOIOCTLCMD;
33046b96018bSArnd Bergmann }
33057a229387SArnd Bergmann 
330695c96174SEric Dumazet static long compat_sock_ioctl(struct file *file, unsigned int cmd,
330789bbfc95SShaun Pereira 			      unsigned long arg)
330889bbfc95SShaun Pereira {
330989bbfc95SShaun Pereira 	struct socket *sock = file->private_data;
331089bbfc95SShaun Pereira 	int ret = -ENOIOCTLCMD;
331187de87d5SDavid S. Miller 	struct sock *sk;
331287de87d5SDavid S. Miller 	struct net *net;
331387de87d5SDavid S. Miller 
331487de87d5SDavid S. Miller 	sk = sock->sk;
331587de87d5SDavid S. Miller 	net = sock_net(sk);
331689bbfc95SShaun Pereira 
331789bbfc95SShaun Pereira 	if (sock->ops->compat_ioctl)
331889bbfc95SShaun Pereira 		ret = sock->ops->compat_ioctl(sock, cmd, arg);
331989bbfc95SShaun Pereira 
332087de87d5SDavid S. Miller 	if (ret == -ENOIOCTLCMD &&
332187de87d5SDavid S. Miller 	    (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST))
332287de87d5SDavid S. Miller 		ret = compat_wext_handle_ioctl(net, cmd, arg);
332387de87d5SDavid S. Miller 
33246b96018bSArnd Bergmann 	if (ret == -ENOIOCTLCMD)
33256b96018bSArnd Bergmann 		ret = compat_sock_ioctl_trans(file, sock, cmd, arg);
33266b96018bSArnd Bergmann 
332789bbfc95SShaun Pereira 	return ret;
332889bbfc95SShaun Pereira }
332989bbfc95SShaun Pereira #endif
333089bbfc95SShaun Pereira 
3331ac5a488eSSridhar Samudrala int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
3332ac5a488eSSridhar Samudrala {
3333ac5a488eSSridhar Samudrala 	return sock->ops->bind(sock, addr, addrlen);
3334ac5a488eSSridhar Samudrala }
3335c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_bind);
3336ac5a488eSSridhar Samudrala 
3337ac5a488eSSridhar Samudrala int kernel_listen(struct socket *sock, int backlog)
3338ac5a488eSSridhar Samudrala {
3339ac5a488eSSridhar Samudrala 	return sock->ops->listen(sock, backlog);
3340ac5a488eSSridhar Samudrala }
3341c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_listen);
3342ac5a488eSSridhar Samudrala 
3343ac5a488eSSridhar Samudrala int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
3344ac5a488eSSridhar Samudrala {
3345ac5a488eSSridhar Samudrala 	struct sock *sk = sock->sk;
3346ac5a488eSSridhar Samudrala 	int err;
3347ac5a488eSSridhar Samudrala 
3348ac5a488eSSridhar Samudrala 	err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
3349ac5a488eSSridhar Samudrala 			       newsock);
3350ac5a488eSSridhar Samudrala 	if (err < 0)
3351ac5a488eSSridhar Samudrala 		goto done;
3352ac5a488eSSridhar Samudrala 
3353ac5a488eSSridhar Samudrala 	err = sock->ops->accept(sock, *newsock, flags);
3354ac5a488eSSridhar Samudrala 	if (err < 0) {
3355ac5a488eSSridhar Samudrala 		sock_release(*newsock);
3356fa8705b0STony Battersby 		*newsock = NULL;
3357ac5a488eSSridhar Samudrala 		goto done;
3358ac5a488eSSridhar Samudrala 	}
3359ac5a488eSSridhar Samudrala 
3360ac5a488eSSridhar Samudrala 	(*newsock)->ops = sock->ops;
33611b08534eSWei Yongjun 	__module_get((*newsock)->ops->owner);
3362ac5a488eSSridhar Samudrala 
3363ac5a488eSSridhar Samudrala done:
3364ac5a488eSSridhar Samudrala 	return err;
3365ac5a488eSSridhar Samudrala }
3366c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_accept);
3367ac5a488eSSridhar Samudrala 
3368ac5a488eSSridhar Samudrala int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
3369ac5a488eSSridhar Samudrala 		   int flags)
3370ac5a488eSSridhar Samudrala {
3371ac5a488eSSridhar Samudrala 	return sock->ops->connect(sock, addr, addrlen, flags);
3372ac5a488eSSridhar Samudrala }
3373c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_connect);
3374ac5a488eSSridhar Samudrala 
3375ac5a488eSSridhar Samudrala int kernel_getsockname(struct socket *sock, struct sockaddr *addr,
3376ac5a488eSSridhar Samudrala 			 int *addrlen)
3377ac5a488eSSridhar Samudrala {
3378ac5a488eSSridhar Samudrala 	return sock->ops->getname(sock, addr, addrlen, 0);
3379ac5a488eSSridhar Samudrala }
3380c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockname);
3381ac5a488eSSridhar Samudrala 
3382ac5a488eSSridhar Samudrala int kernel_getpeername(struct socket *sock, struct sockaddr *addr,
3383ac5a488eSSridhar Samudrala 			 int *addrlen)
3384ac5a488eSSridhar Samudrala {
3385ac5a488eSSridhar Samudrala 	return sock->ops->getname(sock, addr, addrlen, 1);
3386ac5a488eSSridhar Samudrala }
3387c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getpeername);
3388ac5a488eSSridhar Samudrala 
3389ac5a488eSSridhar Samudrala int kernel_getsockopt(struct socket *sock, int level, int optname,
3390ac5a488eSSridhar Samudrala 			char *optval, int *optlen)
3391ac5a488eSSridhar Samudrala {
3392ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3393fb8621bbSNamhyung Kim 	char __user *uoptval;
3394fb8621bbSNamhyung Kim 	int __user *uoptlen;
3395ac5a488eSSridhar Samudrala 	int err;
3396ac5a488eSSridhar Samudrala 
3397fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3398fb8621bbSNamhyung Kim 	uoptlen = (int __user __force *) optlen;
3399fb8621bbSNamhyung Kim 
3400ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3401ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3402fb8621bbSNamhyung Kim 		err = sock_getsockopt(sock, level, optname, uoptval, uoptlen);
3403ac5a488eSSridhar Samudrala 	else
3404fb8621bbSNamhyung Kim 		err = sock->ops->getsockopt(sock, level, optname, uoptval,
3405fb8621bbSNamhyung Kim 					    uoptlen);
3406ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3407ac5a488eSSridhar Samudrala 	return err;
3408ac5a488eSSridhar Samudrala }
3409c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockopt);
3410ac5a488eSSridhar Samudrala 
3411ac5a488eSSridhar Samudrala int kernel_setsockopt(struct socket *sock, int level, int optname,
3412b7058842SDavid S. Miller 			char *optval, unsigned int optlen)
3413ac5a488eSSridhar Samudrala {
3414ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3415fb8621bbSNamhyung Kim 	char __user *uoptval;
3416ac5a488eSSridhar Samudrala 	int err;
3417ac5a488eSSridhar Samudrala 
3418fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3419fb8621bbSNamhyung Kim 
3420ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3421ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3422fb8621bbSNamhyung Kim 		err = sock_setsockopt(sock, level, optname, uoptval, optlen);
3423ac5a488eSSridhar Samudrala 	else
3424fb8621bbSNamhyung Kim 		err = sock->ops->setsockopt(sock, level, optname, uoptval,
3425ac5a488eSSridhar Samudrala 					    optlen);
3426ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3427ac5a488eSSridhar Samudrala 	return err;
3428ac5a488eSSridhar Samudrala }
3429c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_setsockopt);
3430ac5a488eSSridhar Samudrala 
3431ac5a488eSSridhar Samudrala int kernel_sendpage(struct socket *sock, struct page *page, int offset,
3432ac5a488eSSridhar Samudrala 		    size_t size, int flags)
3433ac5a488eSSridhar Samudrala {
3434ac5a488eSSridhar Samudrala 	if (sock->ops->sendpage)
3435ac5a488eSSridhar Samudrala 		return sock->ops->sendpage(sock, page, offset, size, flags);
3436ac5a488eSSridhar Samudrala 
3437ac5a488eSSridhar Samudrala 	return sock_no_sendpage(sock, page, offset, size, flags);
3438ac5a488eSSridhar Samudrala }
3439c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendpage);
3440ac5a488eSSridhar Samudrala 
3441ac5a488eSSridhar Samudrala int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg)
3442ac5a488eSSridhar Samudrala {
3443ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3444ac5a488eSSridhar Samudrala 	int err;
3445ac5a488eSSridhar Samudrala 
3446ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3447ac5a488eSSridhar Samudrala 	err = sock->ops->ioctl(sock, cmd, arg);
3448ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3449ac5a488eSSridhar Samudrala 
3450ac5a488eSSridhar Samudrala 	return err;
3451ac5a488eSSridhar Samudrala }
3452c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sock_ioctl);
3453ac5a488eSSridhar Samudrala 
345491cf45f0STrond Myklebust int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
345591cf45f0STrond Myklebust {
345691cf45f0STrond Myklebust 	return sock->ops->shutdown(sock, how);
345791cf45f0STrond Myklebust }
345891cf45f0STrond Myklebust EXPORT_SYMBOL(kernel_sock_shutdown);
3459