xref: /openbmc/linux/net/socket.c (revision f3d33426)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * NET		An implementation of the SOCKET network access protocol.
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Version:	@(#)socket.c	1.1.93	18/02/95
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * Authors:	Orest Zborowski, <obz@Kodak.COM>
702c30a84SJesper Juhl  *		Ross Biro
81da177e4SLinus Torvalds  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
91da177e4SLinus Torvalds  *
101da177e4SLinus Torvalds  * Fixes:
111da177e4SLinus Torvalds  *		Anonymous	:	NOTSOCK/BADF cleanup. Error fix in
121da177e4SLinus Torvalds  *					shutdown()
131da177e4SLinus Torvalds  *		Alan Cox	:	verify_area() fixes
141da177e4SLinus Torvalds  *		Alan Cox	:	Removed DDI
151da177e4SLinus Torvalds  *		Jonathan Kamens	:	SOCK_DGRAM reconnect bug
161da177e4SLinus Torvalds  *		Alan Cox	:	Moved a load of checks to the very
171da177e4SLinus Torvalds  *					top level.
181da177e4SLinus Torvalds  *		Alan Cox	:	Move address structures to/from user
191da177e4SLinus Torvalds  *					mode above the protocol layers.
201da177e4SLinus Torvalds  *		Rob Janssen	:	Allow 0 length sends.
211da177e4SLinus Torvalds  *		Alan Cox	:	Asynchronous I/O support (cribbed from the
221da177e4SLinus Torvalds  *					tty drivers).
231da177e4SLinus Torvalds  *		Niibe Yutaka	:	Asynchronous I/O for writes (4.4BSD style)
241da177e4SLinus Torvalds  *		Jeff Uphoff	:	Made max number of sockets command-line
251da177e4SLinus Torvalds  *					configurable.
261da177e4SLinus Torvalds  *		Matti Aarnio	:	Made the number of sockets dynamic,
271da177e4SLinus Torvalds  *					to be allocated when needed, and mr.
281da177e4SLinus Torvalds  *					Uphoff's max is used as max to be
291da177e4SLinus Torvalds  *					allowed to allocate.
301da177e4SLinus Torvalds  *		Linus		:	Argh. removed all the socket allocation
311da177e4SLinus Torvalds  *					altogether: it's in the inode now.
321da177e4SLinus Torvalds  *		Alan Cox	:	Made sock_alloc()/sock_release() public
331da177e4SLinus Torvalds  *					for NetROM and future kernel nfsd type
341da177e4SLinus Torvalds  *					stuff.
351da177e4SLinus Torvalds  *		Alan Cox	:	sendmsg/recvmsg basics.
361da177e4SLinus Torvalds  *		Tom Dyas	:	Export net symbols.
371da177e4SLinus Torvalds  *		Marcin Dalecki	:	Fixed problems with CONFIG_NET="n".
381da177e4SLinus Torvalds  *		Alan Cox	:	Added thread locking to sys_* calls
391da177e4SLinus Torvalds  *					for sockets. May have errors at the
401da177e4SLinus Torvalds  *					moment.
411da177e4SLinus Torvalds  *		Kevin Buhr	:	Fixed the dumb errors in the above.
421da177e4SLinus Torvalds  *		Andi Kleen	:	Some small cleanups, optimizations,
431da177e4SLinus Torvalds  *					and fixed a copy_from_user() bug.
441da177e4SLinus Torvalds  *		Tigran Aivazian	:	sys_send(args) calls sys_sendto(args, NULL, 0)
451da177e4SLinus Torvalds  *		Tigran Aivazian	:	Made listen(2) backlog sanity checks
461da177e4SLinus Torvalds  *					protocol-independent
471da177e4SLinus Torvalds  *
481da177e4SLinus Torvalds  *
491da177e4SLinus Torvalds  *		This program is free software; you can redistribute it and/or
501da177e4SLinus Torvalds  *		modify it under the terms of the GNU General Public License
511da177e4SLinus Torvalds  *		as published by the Free Software Foundation; either version
521da177e4SLinus Torvalds  *		2 of the License, or (at your option) any later version.
531da177e4SLinus Torvalds  *
541da177e4SLinus Torvalds  *
551da177e4SLinus Torvalds  *	This module is effectively the top level interface to the BSD socket
561da177e4SLinus Torvalds  *	paradigm.
571da177e4SLinus Torvalds  *
581da177e4SLinus Torvalds  *	Based upon Swansea University Computer Society NET3.039
591da177e4SLinus Torvalds  */
601da177e4SLinus Torvalds 
611da177e4SLinus Torvalds #include <linux/mm.h>
621da177e4SLinus Torvalds #include <linux/socket.h>
631da177e4SLinus Torvalds #include <linux/file.h>
641da177e4SLinus Torvalds #include <linux/net.h>
651da177e4SLinus Torvalds #include <linux/interrupt.h>
66aaca0bdcSUlrich Drepper #include <linux/thread_info.h>
6755737fdaSStephen Hemminger #include <linux/rcupdate.h>
681da177e4SLinus Torvalds #include <linux/netdevice.h>
691da177e4SLinus Torvalds #include <linux/proc_fs.h>
701da177e4SLinus Torvalds #include <linux/seq_file.h>
714a3e2f71SArjan van de Ven #include <linux/mutex.h>
721da177e4SLinus Torvalds #include <linux/if_bridge.h>
7320380731SArnaldo Carvalho de Melo #include <linux/if_frad.h>
7420380731SArnaldo Carvalho de Melo #include <linux/if_vlan.h>
751da177e4SLinus Torvalds #include <linux/init.h>
761da177e4SLinus Torvalds #include <linux/poll.h>
771da177e4SLinus Torvalds #include <linux/cache.h>
781da177e4SLinus Torvalds #include <linux/module.h>
791da177e4SLinus Torvalds #include <linux/highmem.h>
801da177e4SLinus Torvalds #include <linux/mount.h>
811da177e4SLinus Torvalds #include <linux/security.h>
821da177e4SLinus Torvalds #include <linux/syscalls.h>
831da177e4SLinus Torvalds #include <linux/compat.h>
841da177e4SLinus Torvalds #include <linux/kmod.h>
853ec3b2fbSDavid Woodhouse #include <linux/audit.h>
86d86b5e0eSAdrian Bunk #include <linux/wireless.h>
871b8d7ae4SEric W. Biederman #include <linux/nsproxy.h>
881fd7317dSNick Black #include <linux/magic.h>
895a0e3ad6STejun Heo #include <linux/slab.h>
90600e1779SMasatake YAMATO #include <linux/xattr.h>
911da177e4SLinus Torvalds 
921da177e4SLinus Torvalds #include <asm/uaccess.h>
931da177e4SLinus Torvalds #include <asm/unistd.h>
941da177e4SLinus Torvalds 
951da177e4SLinus Torvalds #include <net/compat.h>
9687de87d5SDavid S. Miller #include <net/wext.h>
97f8451725SHerbert Xu #include <net/cls_cgroup.h>
981da177e4SLinus Torvalds 
991da177e4SLinus Torvalds #include <net/sock.h>
1001da177e4SLinus Torvalds #include <linux/netfilter.h>
1011da177e4SLinus Torvalds 
1026b96018bSArnd Bergmann #include <linux/if_tun.h>
1036b96018bSArnd Bergmann #include <linux/ipv6_route.h>
1046b96018bSArnd Bergmann #include <linux/route.h>
1056b96018bSArnd Bergmann #include <linux/sockios.h>
1066b96018bSArnd Bergmann #include <linux/atalk.h>
107076bb0c8SEliezer Tamir #include <net/busy_poll.h>
10806021292SEliezer Tamir 
109e0d1095aSCong Wang #ifdef CONFIG_NET_RX_BUSY_POLL
11064b0dc51SEliezer Tamir unsigned int sysctl_net_busy_read __read_mostly;
11164b0dc51SEliezer Tamir unsigned int sysctl_net_busy_poll __read_mostly;
11206021292SEliezer Tamir #endif
1136b96018bSArnd Bergmann 
1141da177e4SLinus Torvalds static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
115027445c3SBadari Pulavarty static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
116027445c3SBadari Pulavarty 			 unsigned long nr_segs, loff_t pos);
117027445c3SBadari Pulavarty static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
118027445c3SBadari Pulavarty 			  unsigned long nr_segs, loff_t pos);
1191da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma);
1201da177e4SLinus Torvalds 
1211da177e4SLinus Torvalds static int sock_close(struct inode *inode, struct file *file);
1221da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file,
1231da177e4SLinus Torvalds 			      struct poll_table_struct *wait);
12489bddce5SStephen Hemminger static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
12589bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
12689bbfc95SShaun Pereira static long compat_sock_ioctl(struct file *file,
12789bbfc95SShaun Pereira 			      unsigned int cmd, unsigned long arg);
12889bbfc95SShaun Pereira #endif
1291da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on);
1301da177e4SLinus Torvalds static ssize_t sock_sendpage(struct file *file, struct page *page,
1311da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more);
1329c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
1339c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
1349c55e01cSJens Axboe 				unsigned int flags);
1351da177e4SLinus Torvalds 
1361da177e4SLinus Torvalds /*
1371da177e4SLinus Torvalds  *	Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
1381da177e4SLinus Torvalds  *	in the operation structures but are done directly via the socketcall() multiplexor.
1391da177e4SLinus Torvalds  */
1401da177e4SLinus Torvalds 
141da7071d7SArjan van de Ven static const struct file_operations socket_file_ops = {
1421da177e4SLinus Torvalds 	.owner =	THIS_MODULE,
1431da177e4SLinus Torvalds 	.llseek =	no_llseek,
1441da177e4SLinus Torvalds 	.aio_read =	sock_aio_read,
1451da177e4SLinus Torvalds 	.aio_write =	sock_aio_write,
1461da177e4SLinus Torvalds 	.poll =		sock_poll,
1471da177e4SLinus Torvalds 	.unlocked_ioctl = sock_ioctl,
14889bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
14989bbfc95SShaun Pereira 	.compat_ioctl = compat_sock_ioctl,
15089bbfc95SShaun Pereira #endif
1511da177e4SLinus Torvalds 	.mmap =		sock_mmap,
1521da177e4SLinus Torvalds 	.open =		sock_no_open,	/* special open code to disallow open via /proc */
1531da177e4SLinus Torvalds 	.release =	sock_close,
1541da177e4SLinus Torvalds 	.fasync =	sock_fasync,
1555274f052SJens Axboe 	.sendpage =	sock_sendpage,
1565274f052SJens Axboe 	.splice_write = generic_splice_sendpage,
1579c55e01cSJens Axboe 	.splice_read =	sock_splice_read,
1581da177e4SLinus Torvalds };
1591da177e4SLinus Torvalds 
1601da177e4SLinus Torvalds /*
1611da177e4SLinus Torvalds  *	The protocol list. Each protocol is registered in here.
1621da177e4SLinus Torvalds  */
1631da177e4SLinus Torvalds 
1641da177e4SLinus Torvalds static DEFINE_SPINLOCK(net_family_lock);
165190683a9SEric Dumazet static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly;
1661da177e4SLinus Torvalds 
1671da177e4SLinus Torvalds /*
1681da177e4SLinus Torvalds  *	Statistics counters of the socket lists
1691da177e4SLinus Torvalds  */
1701da177e4SLinus Torvalds 
171c6d409cfSEric Dumazet static DEFINE_PER_CPU(int, sockets_in_use);
1721da177e4SLinus Torvalds 
1731da177e4SLinus Torvalds /*
17489bddce5SStephen Hemminger  * Support routines.
17589bddce5SStephen Hemminger  * Move socket addresses back and forth across the kernel/user
1761da177e4SLinus Torvalds  * divide and look after the messy bits.
1771da177e4SLinus Torvalds  */
1781da177e4SLinus Torvalds 
1791da177e4SLinus Torvalds /**
1801da177e4SLinus Torvalds  *	move_addr_to_kernel	-	copy a socket address into kernel space
1811da177e4SLinus Torvalds  *	@uaddr: Address in user space
1821da177e4SLinus Torvalds  *	@kaddr: Address in kernel space
1831da177e4SLinus Torvalds  *	@ulen: Length in user space
1841da177e4SLinus Torvalds  *
1851da177e4SLinus Torvalds  *	The address is copied into kernel space. If the provided address is
1861da177e4SLinus Torvalds  *	too long an error code of -EINVAL is returned. If the copy gives
1871da177e4SLinus Torvalds  *	invalid addresses -EFAULT is returned. On a success 0 is returned.
1881da177e4SLinus Torvalds  */
1891da177e4SLinus Torvalds 
19043db362dSMaciej Żenczykowski int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr)
1911da177e4SLinus Torvalds {
192230b1839SYOSHIFUJI Hideaki 	if (ulen < 0 || ulen > sizeof(struct sockaddr_storage))
1931da177e4SLinus Torvalds 		return -EINVAL;
1941da177e4SLinus Torvalds 	if (ulen == 0)
1951da177e4SLinus Torvalds 		return 0;
1961da177e4SLinus Torvalds 	if (copy_from_user(kaddr, uaddr, ulen))
1971da177e4SLinus Torvalds 		return -EFAULT;
1983ec3b2fbSDavid Woodhouse 	return audit_sockaddr(ulen, kaddr);
1991da177e4SLinus Torvalds }
2001da177e4SLinus Torvalds 
2011da177e4SLinus Torvalds /**
2021da177e4SLinus Torvalds  *	move_addr_to_user	-	copy an address to user space
2031da177e4SLinus Torvalds  *	@kaddr: kernel space address
2041da177e4SLinus Torvalds  *	@klen: length of address in kernel
2051da177e4SLinus Torvalds  *	@uaddr: user space address
2061da177e4SLinus Torvalds  *	@ulen: pointer to user length field
2071da177e4SLinus Torvalds  *
2081da177e4SLinus Torvalds  *	The value pointed to by ulen on entry is the buffer length available.
2091da177e4SLinus Torvalds  *	This is overwritten with the buffer space used. -EINVAL is returned
2101da177e4SLinus Torvalds  *	if an overlong buffer is specified or a negative buffer size. -EFAULT
2111da177e4SLinus Torvalds  *	is returned if either the buffer or the length field are not
2121da177e4SLinus Torvalds  *	accessible.
2131da177e4SLinus Torvalds  *	After copying the data up to the limit the user specifies, the true
2141da177e4SLinus Torvalds  *	length of the data is written over the length limit the user
2151da177e4SLinus Torvalds  *	specified. Zero is returned for a success.
2161da177e4SLinus Torvalds  */
2171da177e4SLinus Torvalds 
21843db362dSMaciej Żenczykowski static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen,
21911165f14Sstephen hemminger 			     void __user *uaddr, int __user *ulen)
2201da177e4SLinus Torvalds {
2211da177e4SLinus Torvalds 	int err;
2221da177e4SLinus Torvalds 	int len;
2231da177e4SLinus Torvalds 
22489bddce5SStephen Hemminger 	err = get_user(len, ulen);
22589bddce5SStephen Hemminger 	if (err)
2261da177e4SLinus Torvalds 		return err;
2271da177e4SLinus Torvalds 	if (len > klen)
2281da177e4SLinus Torvalds 		len = klen;
229230b1839SYOSHIFUJI Hideaki 	if (len < 0 || len > sizeof(struct sockaddr_storage))
2301da177e4SLinus Torvalds 		return -EINVAL;
23189bddce5SStephen Hemminger 	if (len) {
232d6fe3945SSteve Grubb 		if (audit_sockaddr(klen, kaddr))
233d6fe3945SSteve Grubb 			return -ENOMEM;
2341da177e4SLinus Torvalds 		if (copy_to_user(uaddr, kaddr, len))
2351da177e4SLinus Torvalds 			return -EFAULT;
2361da177e4SLinus Torvalds 	}
2371da177e4SLinus Torvalds 	/*
2381da177e4SLinus Torvalds 	 *      "fromlen shall refer to the value before truncation.."
2391da177e4SLinus Torvalds 	 *                      1003.1g
2401da177e4SLinus Torvalds 	 */
2411da177e4SLinus Torvalds 	return __put_user(klen, ulen);
2421da177e4SLinus Torvalds }
2431da177e4SLinus Torvalds 
244e18b890bSChristoph Lameter static struct kmem_cache *sock_inode_cachep __read_mostly;
2451da177e4SLinus Torvalds 
2461da177e4SLinus Torvalds static struct inode *sock_alloc_inode(struct super_block *sb)
2471da177e4SLinus Torvalds {
2481da177e4SLinus Torvalds 	struct socket_alloc *ei;
249eaefd110SEric Dumazet 	struct socket_wq *wq;
25089bddce5SStephen Hemminger 
251e94b1766SChristoph Lameter 	ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL);
2521da177e4SLinus Torvalds 	if (!ei)
2531da177e4SLinus Torvalds 		return NULL;
254eaefd110SEric Dumazet 	wq = kmalloc(sizeof(*wq), GFP_KERNEL);
255eaefd110SEric Dumazet 	if (!wq) {
25643815482SEric Dumazet 		kmem_cache_free(sock_inode_cachep, ei);
25743815482SEric Dumazet 		return NULL;
25843815482SEric Dumazet 	}
259eaefd110SEric Dumazet 	init_waitqueue_head(&wq->wait);
260eaefd110SEric Dumazet 	wq->fasync_list = NULL;
261eaefd110SEric Dumazet 	RCU_INIT_POINTER(ei->socket.wq, wq);
2621da177e4SLinus Torvalds 
2631da177e4SLinus Torvalds 	ei->socket.state = SS_UNCONNECTED;
2641da177e4SLinus Torvalds 	ei->socket.flags = 0;
2651da177e4SLinus Torvalds 	ei->socket.ops = NULL;
2661da177e4SLinus Torvalds 	ei->socket.sk = NULL;
2671da177e4SLinus Torvalds 	ei->socket.file = NULL;
2681da177e4SLinus Torvalds 
2691da177e4SLinus Torvalds 	return &ei->vfs_inode;
2701da177e4SLinus Torvalds }
2711da177e4SLinus Torvalds 
2721da177e4SLinus Torvalds static void sock_destroy_inode(struct inode *inode)
2731da177e4SLinus Torvalds {
27443815482SEric Dumazet 	struct socket_alloc *ei;
275eaefd110SEric Dumazet 	struct socket_wq *wq;
27643815482SEric Dumazet 
27743815482SEric Dumazet 	ei = container_of(inode, struct socket_alloc, vfs_inode);
278eaefd110SEric Dumazet 	wq = rcu_dereference_protected(ei->socket.wq, 1);
27961845220SLai Jiangshan 	kfree_rcu(wq, rcu);
28043815482SEric Dumazet 	kmem_cache_free(sock_inode_cachep, ei);
2811da177e4SLinus Torvalds }
2821da177e4SLinus Torvalds 
28351cc5068SAlexey Dobriyan static void init_once(void *foo)
2841da177e4SLinus Torvalds {
2851da177e4SLinus Torvalds 	struct socket_alloc *ei = (struct socket_alloc *)foo;
2861da177e4SLinus Torvalds 
2871da177e4SLinus Torvalds 	inode_init_once(&ei->vfs_inode);
2881da177e4SLinus Torvalds }
2891da177e4SLinus Torvalds 
2901da177e4SLinus Torvalds static int init_inodecache(void)
2911da177e4SLinus Torvalds {
2921da177e4SLinus Torvalds 	sock_inode_cachep = kmem_cache_create("sock_inode_cache",
2931da177e4SLinus Torvalds 					      sizeof(struct socket_alloc),
29489bddce5SStephen Hemminger 					      0,
29589bddce5SStephen Hemminger 					      (SLAB_HWCACHE_ALIGN |
29689bddce5SStephen Hemminger 					       SLAB_RECLAIM_ACCOUNT |
297fffb60f9SPaul Jackson 					       SLAB_MEM_SPREAD),
29820c2df83SPaul Mundt 					      init_once);
2991da177e4SLinus Torvalds 	if (sock_inode_cachep == NULL)
3001da177e4SLinus Torvalds 		return -ENOMEM;
3011da177e4SLinus Torvalds 	return 0;
3021da177e4SLinus Torvalds }
3031da177e4SLinus Torvalds 
304b87221deSAlexey Dobriyan static const struct super_operations sockfs_ops = {
3051da177e4SLinus Torvalds 	.alloc_inode	= sock_alloc_inode,
3061da177e4SLinus Torvalds 	.destroy_inode	= sock_destroy_inode,
3071da177e4SLinus Torvalds 	.statfs		= simple_statfs,
3081da177e4SLinus Torvalds };
3091da177e4SLinus Torvalds 
310c23fbb6bSEric Dumazet /*
311c23fbb6bSEric Dumazet  * sockfs_dname() is called from d_path().
312c23fbb6bSEric Dumazet  */
313c23fbb6bSEric Dumazet static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen)
314c23fbb6bSEric Dumazet {
315c23fbb6bSEric Dumazet 	return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]",
316c23fbb6bSEric Dumazet 				dentry->d_inode->i_ino);
317c23fbb6bSEric Dumazet }
318c23fbb6bSEric Dumazet 
3193ba13d17SAl Viro static const struct dentry_operations sockfs_dentry_operations = {
320c23fbb6bSEric Dumazet 	.d_dname  = sockfs_dname,
3211da177e4SLinus Torvalds };
3221da177e4SLinus Torvalds 
323c74a1cbbSAl Viro static struct dentry *sockfs_mount(struct file_system_type *fs_type,
324c74a1cbbSAl Viro 			 int flags, const char *dev_name, void *data)
325c74a1cbbSAl Viro {
326c74a1cbbSAl Viro 	return mount_pseudo(fs_type, "socket:", &sockfs_ops,
327c74a1cbbSAl Viro 		&sockfs_dentry_operations, SOCKFS_MAGIC);
328c74a1cbbSAl Viro }
329c74a1cbbSAl Viro 
330c74a1cbbSAl Viro static struct vfsmount *sock_mnt __read_mostly;
331c74a1cbbSAl Viro 
332c74a1cbbSAl Viro static struct file_system_type sock_fs_type = {
333c74a1cbbSAl Viro 	.name =		"sockfs",
334c74a1cbbSAl Viro 	.mount =	sockfs_mount,
335c74a1cbbSAl Viro 	.kill_sb =	kill_anon_super,
336c74a1cbbSAl Viro };
337c74a1cbbSAl Viro 
3381da177e4SLinus Torvalds /*
3391da177e4SLinus Torvalds  *	Obtains the first available file descriptor and sets it up for use.
3401da177e4SLinus Torvalds  *
34139d8c1b6SDavid S. Miller  *	These functions create file structures and maps them to fd space
34239d8c1b6SDavid S. Miller  *	of the current process. On success it returns file descriptor
3431da177e4SLinus Torvalds  *	and file struct implicitly stored in sock->file.
3441da177e4SLinus Torvalds  *	Note that another thread may close file descriptor before we return
3451da177e4SLinus Torvalds  *	from this function. We use the fact that now we do not refer
3461da177e4SLinus Torvalds  *	to socket after mapping. If one day we will need it, this
3471da177e4SLinus Torvalds  *	function will increment ref. count on file by 1.
3481da177e4SLinus Torvalds  *
3491da177e4SLinus Torvalds  *	In any case returned fd MAY BE not valid!
3501da177e4SLinus Torvalds  *	This race condition is unavoidable
3511da177e4SLinus Torvalds  *	with shared fd spaces, we cannot solve it inside kernel,
3521da177e4SLinus Torvalds  *	but we take care of internal coherence yet.
3531da177e4SLinus Torvalds  */
3541da177e4SLinus Torvalds 
355aab174f0SLinus Torvalds struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)
3561da177e4SLinus Torvalds {
3577cbe66b6SAl Viro 	struct qstr name = { .name = "" };
3582c48b9c4SAl Viro 	struct path path;
3597cbe66b6SAl Viro 	struct file *file;
3601da177e4SLinus Torvalds 
361600e1779SMasatake YAMATO 	if (dname) {
362600e1779SMasatake YAMATO 		name.name = dname;
363600e1779SMasatake YAMATO 		name.len = strlen(name.name);
364600e1779SMasatake YAMATO 	} else if (sock->sk) {
365600e1779SMasatake YAMATO 		name.name = sock->sk->sk_prot_creator->name;
366600e1779SMasatake YAMATO 		name.len = strlen(name.name);
367600e1779SMasatake YAMATO 	}
3684b936885SNick Piggin 	path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name);
36928407630SAl Viro 	if (unlikely(!path.dentry))
37028407630SAl Viro 		return ERR_PTR(-ENOMEM);
3712c48b9c4SAl Viro 	path.mnt = mntget(sock_mnt);
37239d8c1b6SDavid S. Miller 
3732c48b9c4SAl Viro 	d_instantiate(path.dentry, SOCK_INODE(sock));
374cc3808f8SAl Viro 	SOCK_INODE(sock)->i_fop = &socket_file_ops;
375cc3808f8SAl Viro 
3762c48b9c4SAl Viro 	file = alloc_file(&path, FMODE_READ | FMODE_WRITE,
377cc3808f8SAl Viro 		  &socket_file_ops);
37839b65252SAnatol Pomozov 	if (unlikely(IS_ERR(file))) {
379cc3808f8SAl Viro 		/* drop dentry, keep inode */
3807de9c6eeSAl Viro 		ihold(path.dentry->d_inode);
3812c48b9c4SAl Viro 		path_put(&path);
38239b65252SAnatol Pomozov 		return file;
383cc3808f8SAl Viro 	}
3841da177e4SLinus Torvalds 
3851da177e4SLinus Torvalds 	sock->file = file;
38677d27200SUlrich Drepper 	file->f_flags = O_RDWR | (flags & O_NONBLOCK);
38707dc3f07SBenjamin LaHaise 	file->private_data = sock;
38828407630SAl Viro 	return file;
3891da177e4SLinus Torvalds }
39056b31d1cSAl Viro EXPORT_SYMBOL(sock_alloc_file);
3911da177e4SLinus Torvalds 
39256b31d1cSAl Viro static int sock_map_fd(struct socket *sock, int flags)
39339d8c1b6SDavid S. Miller {
39439d8c1b6SDavid S. Miller 	struct file *newfile;
39528407630SAl Viro 	int fd = get_unused_fd_flags(flags);
39628407630SAl Viro 	if (unlikely(fd < 0))
3971da177e4SLinus Torvalds 		return fd;
3981da177e4SLinus Torvalds 
399aab174f0SLinus Torvalds 	newfile = sock_alloc_file(sock, flags, NULL);
40028407630SAl Viro 	if (likely(!IS_ERR(newfile))) {
4011da177e4SLinus Torvalds 		fd_install(fd, newfile);
4021da177e4SLinus Torvalds 		return fd;
4031da177e4SLinus Torvalds 	}
40428407630SAl Viro 
40528407630SAl Viro 	put_unused_fd(fd);
40628407630SAl Viro 	return PTR_ERR(newfile);
4071da177e4SLinus Torvalds }
4081da177e4SLinus Torvalds 
409406a3c63SJohn Fastabend struct socket *sock_from_file(struct file *file, int *err)
4106cb153caSBenjamin LaHaise {
4116cb153caSBenjamin LaHaise 	if (file->f_op == &socket_file_ops)
4126cb153caSBenjamin LaHaise 		return file->private_data;	/* set in sock_map_fd */
4136cb153caSBenjamin LaHaise 
4146cb153caSBenjamin LaHaise 	*err = -ENOTSOCK;
4156cb153caSBenjamin LaHaise 	return NULL;
4166cb153caSBenjamin LaHaise }
417406a3c63SJohn Fastabend EXPORT_SYMBOL(sock_from_file);
4186cb153caSBenjamin LaHaise 
4191da177e4SLinus Torvalds /**
4201da177e4SLinus Torvalds  *	sockfd_lookup - Go from a file number to its socket slot
4211da177e4SLinus Torvalds  *	@fd: file handle
4221da177e4SLinus Torvalds  *	@err: pointer to an error code return
4231da177e4SLinus Torvalds  *
4241da177e4SLinus Torvalds  *	The file handle passed in is locked and the socket it is bound
4251da177e4SLinus Torvalds  *	too is returned. If an error occurs the err pointer is overwritten
4261da177e4SLinus Torvalds  *	with a negative errno code and NULL is returned. The function checks
4271da177e4SLinus Torvalds  *	for both invalid handles and passing a handle which is not a socket.
4281da177e4SLinus Torvalds  *
4291da177e4SLinus Torvalds  *	On a success the socket object pointer is returned.
4301da177e4SLinus Torvalds  */
4311da177e4SLinus Torvalds 
4321da177e4SLinus Torvalds struct socket *sockfd_lookup(int fd, int *err)
4331da177e4SLinus Torvalds {
4341da177e4SLinus Torvalds 	struct file *file;
4351da177e4SLinus Torvalds 	struct socket *sock;
4361da177e4SLinus Torvalds 
43789bddce5SStephen Hemminger 	file = fget(fd);
43889bddce5SStephen Hemminger 	if (!file) {
4391da177e4SLinus Torvalds 		*err = -EBADF;
4401da177e4SLinus Torvalds 		return NULL;
4411da177e4SLinus Torvalds 	}
44289bddce5SStephen Hemminger 
4436cb153caSBenjamin LaHaise 	sock = sock_from_file(file, err);
4446cb153caSBenjamin LaHaise 	if (!sock)
4451da177e4SLinus Torvalds 		fput(file);
4466cb153caSBenjamin LaHaise 	return sock;
4471da177e4SLinus Torvalds }
448c6d409cfSEric Dumazet EXPORT_SYMBOL(sockfd_lookup);
4491da177e4SLinus Torvalds 
4506cb153caSBenjamin LaHaise static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
4516cb153caSBenjamin LaHaise {
4526cb153caSBenjamin LaHaise 	struct file *file;
4536cb153caSBenjamin LaHaise 	struct socket *sock;
4546cb153caSBenjamin LaHaise 
4553672558cSHua Zhong 	*err = -EBADF;
4566cb153caSBenjamin LaHaise 	file = fget_light(fd, fput_needed);
4576cb153caSBenjamin LaHaise 	if (file) {
4586cb153caSBenjamin LaHaise 		sock = sock_from_file(file, err);
4596cb153caSBenjamin LaHaise 		if (sock)
4601da177e4SLinus Torvalds 			return sock;
4616cb153caSBenjamin LaHaise 		fput_light(file, *fput_needed);
4626cb153caSBenjamin LaHaise 	}
4636cb153caSBenjamin LaHaise 	return NULL;
4641da177e4SLinus Torvalds }
4651da177e4SLinus Torvalds 
466600e1779SMasatake YAMATO #define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname"
467600e1779SMasatake YAMATO #define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX)
468600e1779SMasatake YAMATO #define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1)
469600e1779SMasatake YAMATO static ssize_t sockfs_getxattr(struct dentry *dentry,
470600e1779SMasatake YAMATO 			       const char *name, void *value, size_t size)
471600e1779SMasatake YAMATO {
472600e1779SMasatake YAMATO 	const char *proto_name;
473600e1779SMasatake YAMATO 	size_t proto_size;
474600e1779SMasatake YAMATO 	int error;
475600e1779SMasatake YAMATO 
476600e1779SMasatake YAMATO 	error = -ENODATA;
477600e1779SMasatake YAMATO 	if (!strncmp(name, XATTR_NAME_SOCKPROTONAME, XATTR_NAME_SOCKPROTONAME_LEN)) {
478600e1779SMasatake YAMATO 		proto_name = dentry->d_name.name;
479600e1779SMasatake YAMATO 		proto_size = strlen(proto_name);
480600e1779SMasatake YAMATO 
481600e1779SMasatake YAMATO 		if (value) {
482600e1779SMasatake YAMATO 			error = -ERANGE;
483600e1779SMasatake YAMATO 			if (proto_size + 1 > size)
484600e1779SMasatake YAMATO 				goto out;
485600e1779SMasatake YAMATO 
486600e1779SMasatake YAMATO 			strncpy(value, proto_name, proto_size + 1);
487600e1779SMasatake YAMATO 		}
488600e1779SMasatake YAMATO 		error = proto_size + 1;
489600e1779SMasatake YAMATO 	}
490600e1779SMasatake YAMATO 
491600e1779SMasatake YAMATO out:
492600e1779SMasatake YAMATO 	return error;
493600e1779SMasatake YAMATO }
494600e1779SMasatake YAMATO 
495600e1779SMasatake YAMATO static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer,
496600e1779SMasatake YAMATO 				size_t size)
497600e1779SMasatake YAMATO {
498600e1779SMasatake YAMATO 	ssize_t len;
499600e1779SMasatake YAMATO 	ssize_t used = 0;
500600e1779SMasatake YAMATO 
501600e1779SMasatake YAMATO 	len = security_inode_listsecurity(dentry->d_inode, buffer, size);
502600e1779SMasatake YAMATO 	if (len < 0)
503600e1779SMasatake YAMATO 		return len;
504600e1779SMasatake YAMATO 	used += len;
505600e1779SMasatake YAMATO 	if (buffer) {
506600e1779SMasatake YAMATO 		if (size < used)
507600e1779SMasatake YAMATO 			return -ERANGE;
508600e1779SMasatake YAMATO 		buffer += len;
509600e1779SMasatake YAMATO 	}
510600e1779SMasatake YAMATO 
511600e1779SMasatake YAMATO 	len = (XATTR_NAME_SOCKPROTONAME_LEN + 1);
512600e1779SMasatake YAMATO 	used += len;
513600e1779SMasatake YAMATO 	if (buffer) {
514600e1779SMasatake YAMATO 		if (size < used)
515600e1779SMasatake YAMATO 			return -ERANGE;
516600e1779SMasatake YAMATO 		memcpy(buffer, XATTR_NAME_SOCKPROTONAME, len);
517600e1779SMasatake YAMATO 		buffer += len;
518600e1779SMasatake YAMATO 	}
519600e1779SMasatake YAMATO 
520600e1779SMasatake YAMATO 	return used;
521600e1779SMasatake YAMATO }
522600e1779SMasatake YAMATO 
523600e1779SMasatake YAMATO static const struct inode_operations sockfs_inode_ops = {
524600e1779SMasatake YAMATO 	.getxattr = sockfs_getxattr,
525600e1779SMasatake YAMATO 	.listxattr = sockfs_listxattr,
526600e1779SMasatake YAMATO };
527600e1779SMasatake YAMATO 
5281da177e4SLinus Torvalds /**
5291da177e4SLinus Torvalds  *	sock_alloc	-	allocate a socket
5301da177e4SLinus Torvalds  *
5311da177e4SLinus Torvalds  *	Allocate a new inode and socket object. The two are bound together
5321da177e4SLinus Torvalds  *	and initialised. The socket is then returned. If we are out of inodes
5331da177e4SLinus Torvalds  *	NULL is returned.
5341da177e4SLinus Torvalds  */
5351da177e4SLinus Torvalds 
5361da177e4SLinus Torvalds static struct socket *sock_alloc(void)
5371da177e4SLinus Torvalds {
5381da177e4SLinus Torvalds 	struct inode *inode;
5391da177e4SLinus Torvalds 	struct socket *sock;
5401da177e4SLinus Torvalds 
541a209dfc7SEric Dumazet 	inode = new_inode_pseudo(sock_mnt->mnt_sb);
5421da177e4SLinus Torvalds 	if (!inode)
5431da177e4SLinus Torvalds 		return NULL;
5441da177e4SLinus Torvalds 
5451da177e4SLinus Torvalds 	sock = SOCKET_I(inode);
5461da177e4SLinus Torvalds 
54729a020d3SEric Dumazet 	kmemcheck_annotate_bitfield(sock, type);
54885fe4025SChristoph Hellwig 	inode->i_ino = get_next_ino();
5491da177e4SLinus Torvalds 	inode->i_mode = S_IFSOCK | S_IRWXUGO;
5508192b0c4SDavid Howells 	inode->i_uid = current_fsuid();
5518192b0c4SDavid Howells 	inode->i_gid = current_fsgid();
552600e1779SMasatake YAMATO 	inode->i_op = &sockfs_inode_ops;
5531da177e4SLinus Torvalds 
55419e8d69cSAlex Shi 	this_cpu_add(sockets_in_use, 1);
5551da177e4SLinus Torvalds 	return sock;
5561da177e4SLinus Torvalds }
5571da177e4SLinus Torvalds 
5581da177e4SLinus Torvalds /*
5591da177e4SLinus Torvalds  *	In theory you can't get an open on this inode, but /proc provides
5601da177e4SLinus Torvalds  *	a back door. Remember to keep it shut otherwise you'll let the
5611da177e4SLinus Torvalds  *	creepy crawlies in.
5621da177e4SLinus Torvalds  */
5631da177e4SLinus Torvalds 
5641da177e4SLinus Torvalds static int sock_no_open(struct inode *irrelevant, struct file *dontcare)
5651da177e4SLinus Torvalds {
5661da177e4SLinus Torvalds 	return -ENXIO;
5671da177e4SLinus Torvalds }
5681da177e4SLinus Torvalds 
5694b6f5d20SArjan van de Ven const struct file_operations bad_sock_fops = {
5701da177e4SLinus Torvalds 	.owner = THIS_MODULE,
5711da177e4SLinus Torvalds 	.open = sock_no_open,
5726038f373SArnd Bergmann 	.llseek = noop_llseek,
5731da177e4SLinus Torvalds };
5741da177e4SLinus Torvalds 
5751da177e4SLinus Torvalds /**
5761da177e4SLinus Torvalds  *	sock_release	-	close a socket
5771da177e4SLinus Torvalds  *	@sock: socket to close
5781da177e4SLinus Torvalds  *
5791da177e4SLinus Torvalds  *	The socket is released from the protocol stack if it has a release
5801da177e4SLinus Torvalds  *	callback, and the inode is then released if the socket is bound to
5811da177e4SLinus Torvalds  *	an inode not a file.
5821da177e4SLinus Torvalds  */
5831da177e4SLinus Torvalds 
5841da177e4SLinus Torvalds void sock_release(struct socket *sock)
5851da177e4SLinus Torvalds {
5861da177e4SLinus Torvalds 	if (sock->ops) {
5871da177e4SLinus Torvalds 		struct module *owner = sock->ops->owner;
5881da177e4SLinus Torvalds 
5891da177e4SLinus Torvalds 		sock->ops->release(sock);
5901da177e4SLinus Torvalds 		sock->ops = NULL;
5911da177e4SLinus Torvalds 		module_put(owner);
5921da177e4SLinus Torvalds 	}
5931da177e4SLinus Torvalds 
594eaefd110SEric Dumazet 	if (rcu_dereference_protected(sock->wq, 1)->fasync_list)
5951da177e4SLinus Torvalds 		printk(KERN_ERR "sock_release: fasync list not empty!\n");
5961da177e4SLinus Torvalds 
597b09e786bSMikulas Patocka 	if (test_bit(SOCK_EXTERNALLY_ALLOCATED, &sock->flags))
598b09e786bSMikulas Patocka 		return;
599b09e786bSMikulas Patocka 
60019e8d69cSAlex Shi 	this_cpu_sub(sockets_in_use, 1);
6011da177e4SLinus Torvalds 	if (!sock->file) {
6021da177e4SLinus Torvalds 		iput(SOCK_INODE(sock));
6031da177e4SLinus Torvalds 		return;
6041da177e4SLinus Torvalds 	}
6051da177e4SLinus Torvalds 	sock->file = NULL;
6061da177e4SLinus Torvalds }
607c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_release);
6081da177e4SLinus Torvalds 
609bf84a010SDaniel Borkmann void sock_tx_timestamp(struct sock *sk, __u8 *tx_flags)
61020d49473SPatrick Ohly {
6112244d07bSOliver Hartkopp 	*tx_flags = 0;
61220d49473SPatrick Ohly 	if (sock_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE))
6132244d07bSOliver Hartkopp 		*tx_flags |= SKBTX_HW_TSTAMP;
61420d49473SPatrick Ohly 	if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE))
6152244d07bSOliver Hartkopp 		*tx_flags |= SKBTX_SW_TSTAMP;
6166e3e939fSJohannes Berg 	if (sock_flag(sk, SOCK_WIFI_STATUS))
6176e3e939fSJohannes Berg 		*tx_flags |= SKBTX_WIFI_STATUS;
61820d49473SPatrick Ohly }
61920d49473SPatrick Ohly EXPORT_SYMBOL(sock_tx_timestamp);
62020d49473SPatrick Ohly 
621228e548eSAnton Blanchard static inline int __sock_sendmsg_nosec(struct kiocb *iocb, struct socket *sock,
6221da177e4SLinus Torvalds 				       struct msghdr *msg, size_t size)
6231da177e4SLinus Torvalds {
6241da177e4SLinus Torvalds 	struct sock_iocb *si = kiocb_to_siocb(iocb);
6251da177e4SLinus Torvalds 
6261da177e4SLinus Torvalds 	si->sock = sock;
6271da177e4SLinus Torvalds 	si->scm = NULL;
6281da177e4SLinus Torvalds 	si->msg = msg;
6291da177e4SLinus Torvalds 	si->size = size;
6301da177e4SLinus Torvalds 
6311da177e4SLinus Torvalds 	return sock->ops->sendmsg(iocb, sock, msg, size);
6321da177e4SLinus Torvalds }
6331da177e4SLinus Torvalds 
634228e548eSAnton Blanchard static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock,
635228e548eSAnton Blanchard 				 struct msghdr *msg, size_t size)
636228e548eSAnton Blanchard {
637228e548eSAnton Blanchard 	int err = security_socket_sendmsg(sock, msg, size);
638228e548eSAnton Blanchard 
639228e548eSAnton Blanchard 	return err ?: __sock_sendmsg_nosec(iocb, sock, msg, size);
640228e548eSAnton Blanchard }
641228e548eSAnton Blanchard 
6421da177e4SLinus Torvalds int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
6431da177e4SLinus Torvalds {
6441da177e4SLinus Torvalds 	struct kiocb iocb;
6451da177e4SLinus Torvalds 	struct sock_iocb siocb;
6461da177e4SLinus Torvalds 	int ret;
6471da177e4SLinus Torvalds 
6481da177e4SLinus Torvalds 	init_sync_kiocb(&iocb, NULL);
6491da177e4SLinus Torvalds 	iocb.private = &siocb;
6501da177e4SLinus Torvalds 	ret = __sock_sendmsg(&iocb, sock, msg, size);
6511da177e4SLinus Torvalds 	if (-EIOCBQUEUED == ret)
6521da177e4SLinus Torvalds 		ret = wait_on_sync_kiocb(&iocb);
6531da177e4SLinus Torvalds 	return ret;
6541da177e4SLinus Torvalds }
655c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_sendmsg);
6561da177e4SLinus Torvalds 
657894dc24cSEric Dumazet static int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg, size_t size)
658228e548eSAnton Blanchard {
659228e548eSAnton Blanchard 	struct kiocb iocb;
660228e548eSAnton Blanchard 	struct sock_iocb siocb;
661228e548eSAnton Blanchard 	int ret;
662228e548eSAnton Blanchard 
663228e548eSAnton Blanchard 	init_sync_kiocb(&iocb, NULL);
664228e548eSAnton Blanchard 	iocb.private = &siocb;
665228e548eSAnton Blanchard 	ret = __sock_sendmsg_nosec(&iocb, sock, msg, size);
666228e548eSAnton Blanchard 	if (-EIOCBQUEUED == ret)
667228e548eSAnton Blanchard 		ret = wait_on_sync_kiocb(&iocb);
668228e548eSAnton Blanchard 	return ret;
669228e548eSAnton Blanchard }
670228e548eSAnton Blanchard 
6711da177e4SLinus Torvalds int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
6721da177e4SLinus Torvalds 		   struct kvec *vec, size_t num, size_t size)
6731da177e4SLinus Torvalds {
6741da177e4SLinus Torvalds 	mm_segment_t oldfs = get_fs();
6751da177e4SLinus Torvalds 	int result;
6761da177e4SLinus Torvalds 
6771da177e4SLinus Torvalds 	set_fs(KERNEL_DS);
6781da177e4SLinus Torvalds 	/*
6791da177e4SLinus Torvalds 	 * the following is safe, since for compiler definitions of kvec and
6801da177e4SLinus Torvalds 	 * iovec are identical, yielding the same in-core layout and alignment
6811da177e4SLinus Torvalds 	 */
68289bddce5SStephen Hemminger 	msg->msg_iov = (struct iovec *)vec;
6831da177e4SLinus Torvalds 	msg->msg_iovlen = num;
6841da177e4SLinus Torvalds 	result = sock_sendmsg(sock, msg, size);
6851da177e4SLinus Torvalds 	set_fs(oldfs);
6861da177e4SLinus Torvalds 	return result;
6871da177e4SLinus Torvalds }
688c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendmsg);
6891da177e4SLinus Torvalds 
69092f37fd2SEric Dumazet /*
69192f37fd2SEric Dumazet  * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
69292f37fd2SEric Dumazet  */
69392f37fd2SEric Dumazet void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
69492f37fd2SEric Dumazet 	struct sk_buff *skb)
69592f37fd2SEric Dumazet {
69620d49473SPatrick Ohly 	int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
69720d49473SPatrick Ohly 	struct timespec ts[3];
69820d49473SPatrick Ohly 	int empty = 1;
69920d49473SPatrick Ohly 	struct skb_shared_hwtstamps *shhwtstamps =
70020d49473SPatrick Ohly 		skb_hwtstamps(skb);
70192f37fd2SEric Dumazet 
70220d49473SPatrick Ohly 	/* Race occurred between timestamp enabling and packet
70320d49473SPatrick Ohly 	   receiving.  Fill in the current time for now. */
70420d49473SPatrick Ohly 	if (need_software_tstamp && skb->tstamp.tv64 == 0)
70520d49473SPatrick Ohly 		__net_timestamp(skb);
70620d49473SPatrick Ohly 
70720d49473SPatrick Ohly 	if (need_software_tstamp) {
70892f37fd2SEric Dumazet 		if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
70992f37fd2SEric Dumazet 			struct timeval tv;
71020d49473SPatrick Ohly 			skb_get_timestamp(skb, &tv);
71120d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP,
71220d49473SPatrick Ohly 				 sizeof(tv), &tv);
71392f37fd2SEric Dumazet 		} else {
714842509b8SHagen Paul Pfeifer 			skb_get_timestampns(skb, &ts[0]);
71520d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS,
716842509b8SHagen Paul Pfeifer 				 sizeof(ts[0]), &ts[0]);
71792f37fd2SEric Dumazet 		}
71892f37fd2SEric Dumazet 	}
71992f37fd2SEric Dumazet 
72020d49473SPatrick Ohly 
72120d49473SPatrick Ohly 	memset(ts, 0, sizeof(ts));
7226e94d1efSDaniel Borkmann 	if (sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE) &&
7236e94d1efSDaniel Borkmann 	    ktime_to_timespec_cond(skb->tstamp, ts + 0))
72420d49473SPatrick Ohly 		empty = 0;
72520d49473SPatrick Ohly 	if (shhwtstamps) {
72620d49473SPatrick Ohly 		if (sock_flag(sk, SOCK_TIMESTAMPING_SYS_HARDWARE) &&
7276e94d1efSDaniel Borkmann 		    ktime_to_timespec_cond(shhwtstamps->syststamp, ts + 1))
72820d49473SPatrick Ohly 			empty = 0;
72920d49473SPatrick Ohly 		if (sock_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE) &&
7306e94d1efSDaniel Borkmann 		    ktime_to_timespec_cond(shhwtstamps->hwtstamp, ts + 2))
73120d49473SPatrick Ohly 			empty = 0;
73220d49473SPatrick Ohly 	}
73320d49473SPatrick Ohly 	if (!empty)
73420d49473SPatrick Ohly 		put_cmsg(msg, SOL_SOCKET,
73520d49473SPatrick Ohly 			 SCM_TIMESTAMPING, sizeof(ts), &ts);
73620d49473SPatrick Ohly }
7377c81fd8bSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
7387c81fd8bSArnaldo Carvalho de Melo 
7396e3e939fSJohannes Berg void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
7406e3e939fSJohannes Berg 	struct sk_buff *skb)
7416e3e939fSJohannes Berg {
7426e3e939fSJohannes Berg 	int ack;
7436e3e939fSJohannes Berg 
7446e3e939fSJohannes Berg 	if (!sock_flag(sk, SOCK_WIFI_STATUS))
7456e3e939fSJohannes Berg 		return;
7466e3e939fSJohannes Berg 	if (!skb->wifi_acked_valid)
7476e3e939fSJohannes Berg 		return;
7486e3e939fSJohannes Berg 
7496e3e939fSJohannes Berg 	ack = skb->wifi_acked;
7506e3e939fSJohannes Berg 
7516e3e939fSJohannes Berg 	put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack);
7526e3e939fSJohannes Berg }
7536e3e939fSJohannes Berg EXPORT_SYMBOL_GPL(__sock_recv_wifi_status);
7546e3e939fSJohannes Berg 
75511165f14Sstephen hemminger static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk,
75611165f14Sstephen hemminger 				   struct sk_buff *skb)
7573b885787SNeil Horman {
7583b885787SNeil Horman 	if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && skb->dropcount)
7593b885787SNeil Horman 		put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL,
7603b885787SNeil Horman 			sizeof(__u32), &skb->dropcount);
7613b885787SNeil Horman }
7623b885787SNeil Horman 
763767dd033SEric Dumazet void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
7643b885787SNeil Horman 	struct sk_buff *skb)
7653b885787SNeil Horman {
7663b885787SNeil Horman 	sock_recv_timestamp(msg, sk, skb);
7673b885787SNeil Horman 	sock_recv_drops(msg, sk, skb);
7683b885787SNeil Horman }
769767dd033SEric Dumazet EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops);
7703b885787SNeil Horman 
771a2e27255SArnaldo Carvalho de Melo static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock,
7721da177e4SLinus Torvalds 				       struct msghdr *msg, size_t size, int flags)
7731da177e4SLinus Torvalds {
7741da177e4SLinus Torvalds 	struct sock_iocb *si = kiocb_to_siocb(iocb);
7751da177e4SLinus Torvalds 
7761da177e4SLinus Torvalds 	si->sock = sock;
7771da177e4SLinus Torvalds 	si->scm = NULL;
7781da177e4SLinus Torvalds 	si->msg = msg;
7791da177e4SLinus Torvalds 	si->size = size;
7801da177e4SLinus Torvalds 	si->flags = flags;
7811da177e4SLinus Torvalds 
7821da177e4SLinus Torvalds 	return sock->ops->recvmsg(iocb, sock, msg, size, flags);
7831da177e4SLinus Torvalds }
7841da177e4SLinus Torvalds 
785a2e27255SArnaldo Carvalho de Melo static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock,
786a2e27255SArnaldo Carvalho de Melo 				 struct msghdr *msg, size_t size, int flags)
787a2e27255SArnaldo Carvalho de Melo {
788a2e27255SArnaldo Carvalho de Melo 	int err = security_socket_recvmsg(sock, msg, size, flags);
789a2e27255SArnaldo Carvalho de Melo 
790a2e27255SArnaldo Carvalho de Melo 	return err ?: __sock_recvmsg_nosec(iocb, sock, msg, size, flags);
791a2e27255SArnaldo Carvalho de Melo }
792a2e27255SArnaldo Carvalho de Melo 
7931da177e4SLinus Torvalds int sock_recvmsg(struct socket *sock, struct msghdr *msg,
7941da177e4SLinus Torvalds 		 size_t size, int flags)
7951da177e4SLinus Torvalds {
7961da177e4SLinus Torvalds 	struct kiocb iocb;
7971da177e4SLinus Torvalds 	struct sock_iocb siocb;
7981da177e4SLinus Torvalds 	int ret;
7991da177e4SLinus Torvalds 
8001da177e4SLinus Torvalds 	init_sync_kiocb(&iocb, NULL);
8011da177e4SLinus Torvalds 	iocb.private = &siocb;
8021da177e4SLinus Torvalds 	ret = __sock_recvmsg(&iocb, sock, msg, size, flags);
8031da177e4SLinus Torvalds 	if (-EIOCBQUEUED == ret)
8041da177e4SLinus Torvalds 		ret = wait_on_sync_kiocb(&iocb);
8051da177e4SLinus Torvalds 	return ret;
8061da177e4SLinus Torvalds }
807c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_recvmsg);
8081da177e4SLinus Torvalds 
809a2e27255SArnaldo Carvalho de Melo static int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
810a2e27255SArnaldo Carvalho de Melo 			      size_t size, int flags)
811a2e27255SArnaldo Carvalho de Melo {
812a2e27255SArnaldo Carvalho de Melo 	struct kiocb iocb;
813a2e27255SArnaldo Carvalho de Melo 	struct sock_iocb siocb;
814a2e27255SArnaldo Carvalho de Melo 	int ret;
815a2e27255SArnaldo Carvalho de Melo 
816a2e27255SArnaldo Carvalho de Melo 	init_sync_kiocb(&iocb, NULL);
817a2e27255SArnaldo Carvalho de Melo 	iocb.private = &siocb;
818a2e27255SArnaldo Carvalho de Melo 	ret = __sock_recvmsg_nosec(&iocb, sock, msg, size, flags);
819a2e27255SArnaldo Carvalho de Melo 	if (-EIOCBQUEUED == ret)
820a2e27255SArnaldo Carvalho de Melo 		ret = wait_on_sync_kiocb(&iocb);
821a2e27255SArnaldo Carvalho de Melo 	return ret;
822a2e27255SArnaldo Carvalho de Melo }
823a2e27255SArnaldo Carvalho de Melo 
824c1249c0aSMartin Lucina /**
825c1249c0aSMartin Lucina  * kernel_recvmsg - Receive a message from a socket (kernel space)
826c1249c0aSMartin Lucina  * @sock:       The socket to receive the message from
827c1249c0aSMartin Lucina  * @msg:        Received message
828c1249c0aSMartin Lucina  * @vec:        Input s/g array for message data
829c1249c0aSMartin Lucina  * @num:        Size of input s/g array
830c1249c0aSMartin Lucina  * @size:       Number of bytes to read
831c1249c0aSMartin Lucina  * @flags:      Message flags (MSG_DONTWAIT, etc...)
832c1249c0aSMartin Lucina  *
833c1249c0aSMartin Lucina  * On return the msg structure contains the scatter/gather array passed in the
834c1249c0aSMartin Lucina  * vec argument. The array is modified so that it consists of the unfilled
835c1249c0aSMartin Lucina  * portion of the original array.
836c1249c0aSMartin Lucina  *
837c1249c0aSMartin Lucina  * The returned value is the total number of bytes received, or an error.
838c1249c0aSMartin Lucina  */
8391da177e4SLinus Torvalds int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
84089bddce5SStephen Hemminger 		   struct kvec *vec, size_t num, size_t size, int flags)
8411da177e4SLinus Torvalds {
8421da177e4SLinus Torvalds 	mm_segment_t oldfs = get_fs();
8431da177e4SLinus Torvalds 	int result;
8441da177e4SLinus Torvalds 
8451da177e4SLinus Torvalds 	set_fs(KERNEL_DS);
8461da177e4SLinus Torvalds 	/*
8471da177e4SLinus Torvalds 	 * the following is safe, since for compiler definitions of kvec and
8481da177e4SLinus Torvalds 	 * iovec are identical, yielding the same in-core layout and alignment
8491da177e4SLinus Torvalds 	 */
85089bddce5SStephen Hemminger 	msg->msg_iov = (struct iovec *)vec, msg->msg_iovlen = num;
8511da177e4SLinus Torvalds 	result = sock_recvmsg(sock, msg, size, flags);
8521da177e4SLinus Torvalds 	set_fs(oldfs);
8531da177e4SLinus Torvalds 	return result;
8541da177e4SLinus Torvalds }
855c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_recvmsg);
8561da177e4SLinus Torvalds 
85720380731SArnaldo Carvalho de Melo static ssize_t sock_sendpage(struct file *file, struct page *page,
8581da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more)
8591da177e4SLinus Torvalds {
8601da177e4SLinus Torvalds 	struct socket *sock;
8611da177e4SLinus Torvalds 	int flags;
8621da177e4SLinus Torvalds 
863b69aee04SEric Dumazet 	sock = file->private_data;
8641da177e4SLinus Torvalds 
86535f9c09fSEric Dumazet 	flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
86635f9c09fSEric Dumazet 	/* more is a combination of MSG_MORE and MSG_SENDPAGE_NOTLAST */
86735f9c09fSEric Dumazet 	flags |= more;
8681da177e4SLinus Torvalds 
869e6949583SLinus Torvalds 	return kernel_sendpage(sock, page, offset, size, flags);
8701da177e4SLinus Torvalds }
8711da177e4SLinus Torvalds 
8729c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
8739c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
8749c55e01cSJens Axboe 				unsigned int flags)
8759c55e01cSJens Axboe {
8769c55e01cSJens Axboe 	struct socket *sock = file->private_data;
8779c55e01cSJens Axboe 
878997b37daSRémi Denis-Courmont 	if (unlikely(!sock->ops->splice_read))
879997b37daSRémi Denis-Courmont 		return -EINVAL;
880997b37daSRémi Denis-Courmont 
8819c55e01cSJens Axboe 	return sock->ops->splice_read(sock, ppos, pipe, len, flags);
8829c55e01cSJens Axboe }
8839c55e01cSJens Axboe 
884ce1d4d3eSChristoph Hellwig static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
88589bddce5SStephen Hemminger 					 struct sock_iocb *siocb)
886ce1d4d3eSChristoph Hellwig {
887d29c445bSKent Overstreet 	if (!is_sync_kiocb(iocb))
888d29c445bSKent Overstreet 		BUG();
889ce1d4d3eSChristoph Hellwig 
890ce1d4d3eSChristoph Hellwig 	siocb->kiocb = iocb;
891ce1d4d3eSChristoph Hellwig 	iocb->private = siocb;
892ce1d4d3eSChristoph Hellwig 	return siocb;
893ce1d4d3eSChristoph Hellwig }
894ce1d4d3eSChristoph Hellwig 
895ce1d4d3eSChristoph Hellwig static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb,
896027445c3SBadari Pulavarty 		struct file *file, const struct iovec *iov,
89789bddce5SStephen Hemminger 		unsigned long nr_segs)
898ce1d4d3eSChristoph Hellwig {
899ce1d4d3eSChristoph Hellwig 	struct socket *sock = file->private_data;
900ce1d4d3eSChristoph Hellwig 	size_t size = 0;
901ce1d4d3eSChristoph Hellwig 	int i;
902ce1d4d3eSChristoph Hellwig 
903ce1d4d3eSChristoph Hellwig 	for (i = 0; i < nr_segs; i++)
904ce1d4d3eSChristoph Hellwig 		size += iov[i].iov_len;
905ce1d4d3eSChristoph Hellwig 
906ce1d4d3eSChristoph Hellwig 	msg->msg_name = NULL;
907ce1d4d3eSChristoph Hellwig 	msg->msg_namelen = 0;
908ce1d4d3eSChristoph Hellwig 	msg->msg_control = NULL;
909ce1d4d3eSChristoph Hellwig 	msg->msg_controllen = 0;
910ce1d4d3eSChristoph Hellwig 	msg->msg_iov = (struct iovec *)iov;
911ce1d4d3eSChristoph Hellwig 	msg->msg_iovlen = nr_segs;
912ce1d4d3eSChristoph Hellwig 	msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
913ce1d4d3eSChristoph Hellwig 
914ce1d4d3eSChristoph Hellwig 	return __sock_recvmsg(iocb, sock, msg, size, msg->msg_flags);
915ce1d4d3eSChristoph Hellwig }
916ce1d4d3eSChristoph Hellwig 
917027445c3SBadari Pulavarty static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
918027445c3SBadari Pulavarty 				unsigned long nr_segs, loff_t pos)
919ce1d4d3eSChristoph Hellwig {
920ce1d4d3eSChristoph Hellwig 	struct sock_iocb siocb, *x;
921ce1d4d3eSChristoph Hellwig 
922ce1d4d3eSChristoph Hellwig 	if (pos != 0)
923ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
924027445c3SBadari Pulavarty 
92573a7075eSKent Overstreet 	if (iocb->ki_nbytes == 0)	/* Match SYS5 behaviour */
926ce1d4d3eSChristoph Hellwig 		return 0;
927ce1d4d3eSChristoph Hellwig 
928027445c3SBadari Pulavarty 
929027445c3SBadari Pulavarty 	x = alloc_sock_iocb(iocb, &siocb);
930ce1d4d3eSChristoph Hellwig 	if (!x)
931ce1d4d3eSChristoph Hellwig 		return -ENOMEM;
932027445c3SBadari Pulavarty 	return do_sock_read(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
933ce1d4d3eSChristoph Hellwig }
934ce1d4d3eSChristoph Hellwig 
935ce1d4d3eSChristoph Hellwig static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb,
936027445c3SBadari Pulavarty 			struct file *file, const struct iovec *iov,
93789bddce5SStephen Hemminger 			unsigned long nr_segs)
938ce1d4d3eSChristoph Hellwig {
939ce1d4d3eSChristoph Hellwig 	struct socket *sock = file->private_data;
940ce1d4d3eSChristoph Hellwig 	size_t size = 0;
941ce1d4d3eSChristoph Hellwig 	int i;
942ce1d4d3eSChristoph Hellwig 
943ce1d4d3eSChristoph Hellwig 	for (i = 0; i < nr_segs; i++)
944ce1d4d3eSChristoph Hellwig 		size += iov[i].iov_len;
945ce1d4d3eSChristoph Hellwig 
946ce1d4d3eSChristoph Hellwig 	msg->msg_name = NULL;
947ce1d4d3eSChristoph Hellwig 	msg->msg_namelen = 0;
948ce1d4d3eSChristoph Hellwig 	msg->msg_control = NULL;
949ce1d4d3eSChristoph Hellwig 	msg->msg_controllen = 0;
950ce1d4d3eSChristoph Hellwig 	msg->msg_iov = (struct iovec *)iov;
951ce1d4d3eSChristoph Hellwig 	msg->msg_iovlen = nr_segs;
952ce1d4d3eSChristoph Hellwig 	msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
953ce1d4d3eSChristoph Hellwig 	if (sock->type == SOCK_SEQPACKET)
954ce1d4d3eSChristoph Hellwig 		msg->msg_flags |= MSG_EOR;
955ce1d4d3eSChristoph Hellwig 
956ce1d4d3eSChristoph Hellwig 	return __sock_sendmsg(iocb, sock, msg, size);
957ce1d4d3eSChristoph Hellwig }
958ce1d4d3eSChristoph Hellwig 
959027445c3SBadari Pulavarty static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
960027445c3SBadari Pulavarty 			  unsigned long nr_segs, loff_t pos)
9611da177e4SLinus Torvalds {
962ce1d4d3eSChristoph Hellwig 	struct sock_iocb siocb, *x;
9631da177e4SLinus Torvalds 
964ce1d4d3eSChristoph Hellwig 	if (pos != 0)
965ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
966027445c3SBadari Pulavarty 
967027445c3SBadari Pulavarty 	x = alloc_sock_iocb(iocb, &siocb);
968ce1d4d3eSChristoph Hellwig 	if (!x)
969ce1d4d3eSChristoph Hellwig 		return -ENOMEM;
970ce1d4d3eSChristoph Hellwig 
971027445c3SBadari Pulavarty 	return do_sock_write(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
9721da177e4SLinus Torvalds }
9731da177e4SLinus Torvalds 
9741da177e4SLinus Torvalds /*
9751da177e4SLinus Torvalds  * Atomic setting of ioctl hooks to avoid race
9761da177e4SLinus Torvalds  * with module unload.
9771da177e4SLinus Torvalds  */
9781da177e4SLinus Torvalds 
9794a3e2f71SArjan van de Ven static DEFINE_MUTEX(br_ioctl_mutex);
980c6d409cfSEric Dumazet static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg);
9811da177e4SLinus Torvalds 
982881d966bSEric W. Biederman void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *))
9831da177e4SLinus Torvalds {
9844a3e2f71SArjan van de Ven 	mutex_lock(&br_ioctl_mutex);
9851da177e4SLinus Torvalds 	br_ioctl_hook = hook;
9864a3e2f71SArjan van de Ven 	mutex_unlock(&br_ioctl_mutex);
9871da177e4SLinus Torvalds }
9881da177e4SLinus Torvalds EXPORT_SYMBOL(brioctl_set);
9891da177e4SLinus Torvalds 
9904a3e2f71SArjan van de Ven static DEFINE_MUTEX(vlan_ioctl_mutex);
991881d966bSEric W. Biederman static int (*vlan_ioctl_hook) (struct net *, void __user *arg);
9921da177e4SLinus Torvalds 
993881d966bSEric W. Biederman void vlan_ioctl_set(int (*hook) (struct net *, void __user *))
9941da177e4SLinus Torvalds {
9954a3e2f71SArjan van de Ven 	mutex_lock(&vlan_ioctl_mutex);
9961da177e4SLinus Torvalds 	vlan_ioctl_hook = hook;
9974a3e2f71SArjan van de Ven 	mutex_unlock(&vlan_ioctl_mutex);
9981da177e4SLinus Torvalds }
9991da177e4SLinus Torvalds EXPORT_SYMBOL(vlan_ioctl_set);
10001da177e4SLinus Torvalds 
10014a3e2f71SArjan van de Ven static DEFINE_MUTEX(dlci_ioctl_mutex);
10021da177e4SLinus Torvalds static int (*dlci_ioctl_hook) (unsigned int, void __user *);
10031da177e4SLinus Torvalds 
10041da177e4SLinus Torvalds void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
10051da177e4SLinus Torvalds {
10064a3e2f71SArjan van de Ven 	mutex_lock(&dlci_ioctl_mutex);
10071da177e4SLinus Torvalds 	dlci_ioctl_hook = hook;
10084a3e2f71SArjan van de Ven 	mutex_unlock(&dlci_ioctl_mutex);
10091da177e4SLinus Torvalds }
10101da177e4SLinus Torvalds EXPORT_SYMBOL(dlci_ioctl_set);
10111da177e4SLinus Torvalds 
10126b96018bSArnd Bergmann static long sock_do_ioctl(struct net *net, struct socket *sock,
10136b96018bSArnd Bergmann 				 unsigned int cmd, unsigned long arg)
10146b96018bSArnd Bergmann {
10156b96018bSArnd Bergmann 	int err;
10166b96018bSArnd Bergmann 	void __user *argp = (void __user *)arg;
10176b96018bSArnd Bergmann 
10186b96018bSArnd Bergmann 	err = sock->ops->ioctl(sock, cmd, arg);
10196b96018bSArnd Bergmann 
10206b96018bSArnd Bergmann 	/*
10216b96018bSArnd Bergmann 	 * If this ioctl is unknown try to hand it down
10226b96018bSArnd Bergmann 	 * to the NIC driver.
10236b96018bSArnd Bergmann 	 */
10246b96018bSArnd Bergmann 	if (err == -ENOIOCTLCMD)
10256b96018bSArnd Bergmann 		err = dev_ioctl(net, cmd, argp);
10266b96018bSArnd Bergmann 
10276b96018bSArnd Bergmann 	return err;
10286b96018bSArnd Bergmann }
10296b96018bSArnd Bergmann 
10301da177e4SLinus Torvalds /*
10311da177e4SLinus Torvalds  *	With an ioctl, arg may well be a user mode pointer, but we don't know
10321da177e4SLinus Torvalds  *	what to do with it - that's up to the protocol still.
10331da177e4SLinus Torvalds  */
10341da177e4SLinus Torvalds 
10351da177e4SLinus Torvalds static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
10361da177e4SLinus Torvalds {
10371da177e4SLinus Torvalds 	struct socket *sock;
1038881d966bSEric W. Biederman 	struct sock *sk;
10391da177e4SLinus Torvalds 	void __user *argp = (void __user *)arg;
10401da177e4SLinus Torvalds 	int pid, err;
1041881d966bSEric W. Biederman 	struct net *net;
10421da177e4SLinus Torvalds 
1043b69aee04SEric Dumazet 	sock = file->private_data;
1044881d966bSEric W. Biederman 	sk = sock->sk;
10453b1e0a65SYOSHIFUJI Hideaki 	net = sock_net(sk);
10461da177e4SLinus Torvalds 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
1047881d966bSEric W. Biederman 		err = dev_ioctl(net, cmd, argp);
10481da177e4SLinus Torvalds 	} else
10493d23e349SJohannes Berg #ifdef CONFIG_WEXT_CORE
10501da177e4SLinus Torvalds 	if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
1051881d966bSEric W. Biederman 		err = dev_ioctl(net, cmd, argp);
10521da177e4SLinus Torvalds 	} else
10533d23e349SJohannes Berg #endif
10541da177e4SLinus Torvalds 		switch (cmd) {
10551da177e4SLinus Torvalds 		case FIOSETOWN:
10561da177e4SLinus Torvalds 		case SIOCSPGRP:
10571da177e4SLinus Torvalds 			err = -EFAULT;
10581da177e4SLinus Torvalds 			if (get_user(pid, (int __user *)argp))
10591da177e4SLinus Torvalds 				break;
10601da177e4SLinus Torvalds 			err = f_setown(sock->file, pid, 1);
10611da177e4SLinus Torvalds 			break;
10621da177e4SLinus Torvalds 		case FIOGETOWN:
10631da177e4SLinus Torvalds 		case SIOCGPGRP:
1064609d7fa9SEric W. Biederman 			err = put_user(f_getown(sock->file),
106589bddce5SStephen Hemminger 				       (int __user *)argp);
10661da177e4SLinus Torvalds 			break;
10671da177e4SLinus Torvalds 		case SIOCGIFBR:
10681da177e4SLinus Torvalds 		case SIOCSIFBR:
10691da177e4SLinus Torvalds 		case SIOCBRADDBR:
10701da177e4SLinus Torvalds 		case SIOCBRDELBR:
10711da177e4SLinus Torvalds 			err = -ENOPKG;
10721da177e4SLinus Torvalds 			if (!br_ioctl_hook)
10731da177e4SLinus Torvalds 				request_module("bridge");
10741da177e4SLinus Torvalds 
10754a3e2f71SArjan van de Ven 			mutex_lock(&br_ioctl_mutex);
10761da177e4SLinus Torvalds 			if (br_ioctl_hook)
1077881d966bSEric W. Biederman 				err = br_ioctl_hook(net, cmd, argp);
10784a3e2f71SArjan van de Ven 			mutex_unlock(&br_ioctl_mutex);
10791da177e4SLinus Torvalds 			break;
10801da177e4SLinus Torvalds 		case SIOCGIFVLAN:
10811da177e4SLinus Torvalds 		case SIOCSIFVLAN:
10821da177e4SLinus Torvalds 			err = -ENOPKG;
10831da177e4SLinus Torvalds 			if (!vlan_ioctl_hook)
10841da177e4SLinus Torvalds 				request_module("8021q");
10851da177e4SLinus Torvalds 
10864a3e2f71SArjan van de Ven 			mutex_lock(&vlan_ioctl_mutex);
10871da177e4SLinus Torvalds 			if (vlan_ioctl_hook)
1088881d966bSEric W. Biederman 				err = vlan_ioctl_hook(net, argp);
10894a3e2f71SArjan van de Ven 			mutex_unlock(&vlan_ioctl_mutex);
10901da177e4SLinus Torvalds 			break;
10911da177e4SLinus Torvalds 		case SIOCADDDLCI:
10921da177e4SLinus Torvalds 		case SIOCDELDLCI:
10931da177e4SLinus Torvalds 			err = -ENOPKG;
10941da177e4SLinus Torvalds 			if (!dlci_ioctl_hook)
10951da177e4SLinus Torvalds 				request_module("dlci");
10961da177e4SLinus Torvalds 
10974a3e2f71SArjan van de Ven 			mutex_lock(&dlci_ioctl_mutex);
10987512cbf6SPavel Emelyanov 			if (dlci_ioctl_hook)
10991da177e4SLinus Torvalds 				err = dlci_ioctl_hook(cmd, argp);
11004a3e2f71SArjan van de Ven 			mutex_unlock(&dlci_ioctl_mutex);
11011da177e4SLinus Torvalds 			break;
11021da177e4SLinus Torvalds 		default:
11036b96018bSArnd Bergmann 			err = sock_do_ioctl(net, sock, cmd, arg);
11041da177e4SLinus Torvalds 			break;
11051da177e4SLinus Torvalds 		}
11061da177e4SLinus Torvalds 	return err;
11071da177e4SLinus Torvalds }
11081da177e4SLinus Torvalds 
11091da177e4SLinus Torvalds int sock_create_lite(int family, int type, int protocol, struct socket **res)
11101da177e4SLinus Torvalds {
11111da177e4SLinus Torvalds 	int err;
11121da177e4SLinus Torvalds 	struct socket *sock = NULL;
11131da177e4SLinus Torvalds 
11141da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, 1);
11151da177e4SLinus Torvalds 	if (err)
11161da177e4SLinus Torvalds 		goto out;
11171da177e4SLinus Torvalds 
11181da177e4SLinus Torvalds 	sock = sock_alloc();
11191da177e4SLinus Torvalds 	if (!sock) {
11201da177e4SLinus Torvalds 		err = -ENOMEM;
11211da177e4SLinus Torvalds 		goto out;
11221da177e4SLinus Torvalds 	}
11231da177e4SLinus Torvalds 
11241da177e4SLinus Torvalds 	sock->type = type;
11257420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, 1);
11267420ed23SVenkat Yekkirala 	if (err)
11277420ed23SVenkat Yekkirala 		goto out_release;
11287420ed23SVenkat Yekkirala 
11291da177e4SLinus Torvalds out:
11301da177e4SLinus Torvalds 	*res = sock;
11311da177e4SLinus Torvalds 	return err;
11327420ed23SVenkat Yekkirala out_release:
11337420ed23SVenkat Yekkirala 	sock_release(sock);
11347420ed23SVenkat Yekkirala 	sock = NULL;
11357420ed23SVenkat Yekkirala 	goto out;
11361da177e4SLinus Torvalds }
1137c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_lite);
11381da177e4SLinus Torvalds 
11391da177e4SLinus Torvalds /* No kernel lock held - perfect */
11401da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file, poll_table *wait)
11411da177e4SLinus Torvalds {
1142cbf55001SEliezer Tamir 	unsigned int busy_flag = 0;
11431da177e4SLinus Torvalds 	struct socket *sock;
11441da177e4SLinus Torvalds 
11451da177e4SLinus Torvalds 	/*
11461da177e4SLinus Torvalds 	 *      We can't return errors to poll, so it's either yes or no.
11471da177e4SLinus Torvalds 	 */
1148b69aee04SEric Dumazet 	sock = file->private_data;
11492d48d67fSEliezer Tamir 
1150cbf55001SEliezer Tamir 	if (sk_can_busy_loop(sock->sk)) {
11512d48d67fSEliezer Tamir 		/* this socket can poll_ll so tell the system call */
1152cbf55001SEliezer Tamir 		busy_flag = POLL_BUSY_LOOP;
11532d48d67fSEliezer Tamir 
11542d48d67fSEliezer Tamir 		/* once, only if requested by syscall */
1155cbf55001SEliezer Tamir 		if (wait && (wait->_key & POLL_BUSY_LOOP))
1156cbf55001SEliezer Tamir 			sk_busy_loop(sock->sk, 1);
11572d48d67fSEliezer Tamir 	}
11582d48d67fSEliezer Tamir 
1159cbf55001SEliezer Tamir 	return busy_flag | sock->ops->poll(file, sock, wait);
11601da177e4SLinus Torvalds }
11611da177e4SLinus Torvalds 
11621da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma)
11631da177e4SLinus Torvalds {
1164b69aee04SEric Dumazet 	struct socket *sock = file->private_data;
11651da177e4SLinus Torvalds 
11661da177e4SLinus Torvalds 	return sock->ops->mmap(file, sock, vma);
11671da177e4SLinus Torvalds }
11681da177e4SLinus Torvalds 
116920380731SArnaldo Carvalho de Melo static int sock_close(struct inode *inode, struct file *filp)
11701da177e4SLinus Torvalds {
11711da177e4SLinus Torvalds 	sock_release(SOCKET_I(inode));
11721da177e4SLinus Torvalds 	return 0;
11731da177e4SLinus Torvalds }
11741da177e4SLinus Torvalds 
11751da177e4SLinus Torvalds /*
11761da177e4SLinus Torvalds  *	Update the socket async list
11771da177e4SLinus Torvalds  *
11781da177e4SLinus Torvalds  *	Fasync_list locking strategy.
11791da177e4SLinus Torvalds  *
11801da177e4SLinus Torvalds  *	1. fasync_list is modified only under process context socket lock
11811da177e4SLinus Torvalds  *	   i.e. under semaphore.
11821da177e4SLinus Torvalds  *	2. fasync_list is used under read_lock(&sk->sk_callback_lock)
1183989a2979SEric Dumazet  *	   or under socket lock
11841da177e4SLinus Torvalds  */
11851da177e4SLinus Torvalds 
11861da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on)
11871da177e4SLinus Torvalds {
1188989a2979SEric Dumazet 	struct socket *sock = filp->private_data;
1189989a2979SEric Dumazet 	struct sock *sk = sock->sk;
1190eaefd110SEric Dumazet 	struct socket_wq *wq;
11911da177e4SLinus Torvalds 
1192989a2979SEric Dumazet 	if (sk == NULL)
11931da177e4SLinus Torvalds 		return -EINVAL;
11941da177e4SLinus Torvalds 
11951da177e4SLinus Torvalds 	lock_sock(sk);
1196eaefd110SEric Dumazet 	wq = rcu_dereference_protected(sock->wq, sock_owned_by_user(sk));
1197eaefd110SEric Dumazet 	fasync_helper(fd, filp, on, &wq->fasync_list);
11981da177e4SLinus Torvalds 
1199eaefd110SEric Dumazet 	if (!wq->fasync_list)
1200bcdce719SEric Dumazet 		sock_reset_flag(sk, SOCK_FASYNC);
1201989a2979SEric Dumazet 	else
1202989a2979SEric Dumazet 		sock_set_flag(sk, SOCK_FASYNC);
12031da177e4SLinus Torvalds 
1204989a2979SEric Dumazet 	release_sock(sk);
12051da177e4SLinus Torvalds 	return 0;
12061da177e4SLinus Torvalds }
12071da177e4SLinus Torvalds 
120843815482SEric Dumazet /* This function may be called only under socket lock or callback_lock or rcu_lock */
12091da177e4SLinus Torvalds 
12101da177e4SLinus Torvalds int sock_wake_async(struct socket *sock, int how, int band)
12111da177e4SLinus Torvalds {
121243815482SEric Dumazet 	struct socket_wq *wq;
121343815482SEric Dumazet 
121443815482SEric Dumazet 	if (!sock)
12151da177e4SLinus Torvalds 		return -1;
121643815482SEric Dumazet 	rcu_read_lock();
121743815482SEric Dumazet 	wq = rcu_dereference(sock->wq);
121843815482SEric Dumazet 	if (!wq || !wq->fasync_list) {
121943815482SEric Dumazet 		rcu_read_unlock();
122043815482SEric Dumazet 		return -1;
122143815482SEric Dumazet 	}
122289bddce5SStephen Hemminger 	switch (how) {
12238d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_WAITD:
12241da177e4SLinus Torvalds 		if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
12251da177e4SLinus Torvalds 			break;
12261da177e4SLinus Torvalds 		goto call_kill;
12278d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_SPACE:
12281da177e4SLinus Torvalds 		if (!test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags))
12291da177e4SLinus Torvalds 			break;
12301da177e4SLinus Torvalds 		/* fall through */
12318d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_IO:
12321da177e4SLinus Torvalds call_kill:
123343815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGIO, band);
12341da177e4SLinus Torvalds 		break;
12358d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_URG:
123643815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGURG, band);
12371da177e4SLinus Torvalds 	}
123843815482SEric Dumazet 	rcu_read_unlock();
12391da177e4SLinus Torvalds 	return 0;
12401da177e4SLinus Torvalds }
1241c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_wake_async);
12421da177e4SLinus Torvalds 
1243721db93aSPavel Emelyanov int __sock_create(struct net *net, int family, int type, int protocol,
124489bddce5SStephen Hemminger 			 struct socket **res, int kern)
12451da177e4SLinus Torvalds {
12461da177e4SLinus Torvalds 	int err;
12471da177e4SLinus Torvalds 	struct socket *sock;
124855737fdaSStephen Hemminger 	const struct net_proto_family *pf;
12491da177e4SLinus Torvalds 
12501da177e4SLinus Torvalds 	/*
12511da177e4SLinus Torvalds 	 *      Check protocol is in range
12521da177e4SLinus Torvalds 	 */
12531da177e4SLinus Torvalds 	if (family < 0 || family >= NPROTO)
12541da177e4SLinus Torvalds 		return -EAFNOSUPPORT;
12551da177e4SLinus Torvalds 	if (type < 0 || type >= SOCK_MAX)
12561da177e4SLinus Torvalds 		return -EINVAL;
12571da177e4SLinus Torvalds 
12581da177e4SLinus Torvalds 	/* Compatibility.
12591da177e4SLinus Torvalds 
12601da177e4SLinus Torvalds 	   This uglymoron is moved from INET layer to here to avoid
12611da177e4SLinus Torvalds 	   deadlock in module load.
12621da177e4SLinus Torvalds 	 */
12631da177e4SLinus Torvalds 	if (family == PF_INET && type == SOCK_PACKET) {
12641da177e4SLinus Torvalds 		static int warned;
12651da177e4SLinus Torvalds 		if (!warned) {
12661da177e4SLinus Torvalds 			warned = 1;
126789bddce5SStephen Hemminger 			printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)\n",
126889bddce5SStephen Hemminger 			       current->comm);
12691da177e4SLinus Torvalds 		}
12701da177e4SLinus Torvalds 		family = PF_PACKET;
12711da177e4SLinus Torvalds 	}
12721da177e4SLinus Torvalds 
12731da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, kern);
12741da177e4SLinus Torvalds 	if (err)
12751da177e4SLinus Torvalds 		return err;
12761da177e4SLinus Torvalds 
127755737fdaSStephen Hemminger 	/*
127855737fdaSStephen Hemminger 	 *	Allocate the socket and allow the family to set things up. if
127955737fdaSStephen Hemminger 	 *	the protocol is 0, the family is instructed to select an appropriate
128055737fdaSStephen Hemminger 	 *	default.
128155737fdaSStephen Hemminger 	 */
128255737fdaSStephen Hemminger 	sock = sock_alloc();
128355737fdaSStephen Hemminger 	if (!sock) {
1284e87cc472SJoe Perches 		net_warn_ratelimited("socket: no more sockets\n");
128555737fdaSStephen Hemminger 		return -ENFILE;	/* Not exactly a match, but its the
128655737fdaSStephen Hemminger 				   closest posix thing */
128755737fdaSStephen Hemminger 	}
128855737fdaSStephen Hemminger 
128955737fdaSStephen Hemminger 	sock->type = type;
129055737fdaSStephen Hemminger 
129195a5afcaSJohannes Berg #ifdef CONFIG_MODULES
12921da177e4SLinus Torvalds 	/* Attempt to load a protocol module if the find failed.
12931da177e4SLinus Torvalds 	 *
12941da177e4SLinus Torvalds 	 * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
12951da177e4SLinus Torvalds 	 * requested real, full-featured networking support upon configuration.
12961da177e4SLinus Torvalds 	 * Otherwise module support will break!
12971da177e4SLinus Torvalds 	 */
1298190683a9SEric Dumazet 	if (rcu_access_pointer(net_families[family]) == NULL)
12991da177e4SLinus Torvalds 		request_module("net-pf-%d", family);
13001da177e4SLinus Torvalds #endif
13011da177e4SLinus Torvalds 
130255737fdaSStephen Hemminger 	rcu_read_lock();
130355737fdaSStephen Hemminger 	pf = rcu_dereference(net_families[family]);
13041da177e4SLinus Torvalds 	err = -EAFNOSUPPORT;
130555737fdaSStephen Hemminger 	if (!pf)
130655737fdaSStephen Hemminger 		goto out_release;
13071da177e4SLinus Torvalds 
13081da177e4SLinus Torvalds 	/*
13091da177e4SLinus Torvalds 	 * We will call the ->create function, that possibly is in a loadable
13101da177e4SLinus Torvalds 	 * module, so we have to bump that loadable module refcnt first.
13111da177e4SLinus Torvalds 	 */
131255737fdaSStephen Hemminger 	if (!try_module_get(pf->owner))
13131da177e4SLinus Torvalds 		goto out_release;
13141da177e4SLinus Torvalds 
131555737fdaSStephen Hemminger 	/* Now protected by module ref count */
131655737fdaSStephen Hemminger 	rcu_read_unlock();
131755737fdaSStephen Hemminger 
13183f378b68SEric Paris 	err = pf->create(net, sock, protocol, kern);
131955737fdaSStephen Hemminger 	if (err < 0)
13201da177e4SLinus Torvalds 		goto out_module_put;
1321a79af59eSFrank Filz 
13221da177e4SLinus Torvalds 	/*
13231da177e4SLinus Torvalds 	 * Now to bump the refcnt of the [loadable] module that owns this
13241da177e4SLinus Torvalds 	 * socket at sock_release time we decrement its refcnt.
13251da177e4SLinus Torvalds 	 */
132655737fdaSStephen Hemminger 	if (!try_module_get(sock->ops->owner))
132755737fdaSStephen Hemminger 		goto out_module_busy;
132855737fdaSStephen Hemminger 
13291da177e4SLinus Torvalds 	/*
13301da177e4SLinus Torvalds 	 * Now that we're done with the ->create function, the [loadable]
13311da177e4SLinus Torvalds 	 * module can have its refcnt decremented
13321da177e4SLinus Torvalds 	 */
133355737fdaSStephen Hemminger 	module_put(pf->owner);
13347420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, kern);
13357420ed23SVenkat Yekkirala 	if (err)
13363b185525SHerbert Xu 		goto out_sock_release;
133755737fdaSStephen Hemminger 	*res = sock;
13381da177e4SLinus Torvalds 
133955737fdaSStephen Hemminger 	return 0;
134055737fdaSStephen Hemminger 
134155737fdaSStephen Hemminger out_module_busy:
134255737fdaSStephen Hemminger 	err = -EAFNOSUPPORT;
13431da177e4SLinus Torvalds out_module_put:
134455737fdaSStephen Hemminger 	sock->ops = NULL;
134555737fdaSStephen Hemminger 	module_put(pf->owner);
134655737fdaSStephen Hemminger out_sock_release:
13471da177e4SLinus Torvalds 	sock_release(sock);
134855737fdaSStephen Hemminger 	return err;
134955737fdaSStephen Hemminger 
135055737fdaSStephen Hemminger out_release:
135155737fdaSStephen Hemminger 	rcu_read_unlock();
135255737fdaSStephen Hemminger 	goto out_sock_release;
13531da177e4SLinus Torvalds }
1354721db93aSPavel Emelyanov EXPORT_SYMBOL(__sock_create);
13551da177e4SLinus Torvalds 
13561da177e4SLinus Torvalds int sock_create(int family, int type, int protocol, struct socket **res)
13571da177e4SLinus Torvalds {
13581b8d7ae4SEric W. Biederman 	return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
13591da177e4SLinus Torvalds }
1360c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create);
13611da177e4SLinus Torvalds 
13621da177e4SLinus Torvalds int sock_create_kern(int family, int type, int protocol, struct socket **res)
13631da177e4SLinus Torvalds {
13641b8d7ae4SEric W. Biederman 	return __sock_create(&init_net, family, type, protocol, res, 1);
13651da177e4SLinus Torvalds }
1366c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_kern);
13671da177e4SLinus Torvalds 
13683e0fa65fSHeiko Carstens SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
13691da177e4SLinus Torvalds {
13701da177e4SLinus Torvalds 	int retval;
13711da177e4SLinus Torvalds 	struct socket *sock;
1372a677a039SUlrich Drepper 	int flags;
1373a677a039SUlrich Drepper 
1374e38b36f3SUlrich Drepper 	/* Check the SOCK_* constants for consistency.  */
1375e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
1376e38b36f3SUlrich Drepper 	BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
1377e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);
1378e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);
1379e38b36f3SUlrich Drepper 
1380a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
138177d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1382a677a039SUlrich Drepper 		return -EINVAL;
1383a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
13841da177e4SLinus Torvalds 
1385aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1386aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1387aaca0bdcSUlrich Drepper 
13881da177e4SLinus Torvalds 	retval = sock_create(family, type, protocol, &sock);
13891da177e4SLinus Torvalds 	if (retval < 0)
13901da177e4SLinus Torvalds 		goto out;
13911da177e4SLinus Torvalds 
139277d27200SUlrich Drepper 	retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
13931da177e4SLinus Torvalds 	if (retval < 0)
13941da177e4SLinus Torvalds 		goto out_release;
13951da177e4SLinus Torvalds 
13961da177e4SLinus Torvalds out:
13971da177e4SLinus Torvalds 	/* It may be already another descriptor 8) Not kernel problem. */
13981da177e4SLinus Torvalds 	return retval;
13991da177e4SLinus Torvalds 
14001da177e4SLinus Torvalds out_release:
14011da177e4SLinus Torvalds 	sock_release(sock);
14021da177e4SLinus Torvalds 	return retval;
14031da177e4SLinus Torvalds }
14041da177e4SLinus Torvalds 
14051da177e4SLinus Torvalds /*
14061da177e4SLinus Torvalds  *	Create a pair of connected sockets.
14071da177e4SLinus Torvalds  */
14081da177e4SLinus Torvalds 
14093e0fa65fSHeiko Carstens SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
14103e0fa65fSHeiko Carstens 		int __user *, usockvec)
14111da177e4SLinus Torvalds {
14121da177e4SLinus Torvalds 	struct socket *sock1, *sock2;
14131da177e4SLinus Torvalds 	int fd1, fd2, err;
1414db349509SAl Viro 	struct file *newfile1, *newfile2;
1415a677a039SUlrich Drepper 	int flags;
1416a677a039SUlrich Drepper 
1417a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
141877d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1419a677a039SUlrich Drepper 		return -EINVAL;
1420a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
14211da177e4SLinus Torvalds 
1422aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1423aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1424aaca0bdcSUlrich Drepper 
14251da177e4SLinus Torvalds 	/*
14261da177e4SLinus Torvalds 	 * Obtain the first socket and check if the underlying protocol
14271da177e4SLinus Torvalds 	 * supports the socketpair call.
14281da177e4SLinus Torvalds 	 */
14291da177e4SLinus Torvalds 
14301da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock1);
14311da177e4SLinus Torvalds 	if (err < 0)
14321da177e4SLinus Torvalds 		goto out;
14331da177e4SLinus Torvalds 
14341da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock2);
14351da177e4SLinus Torvalds 	if (err < 0)
14361da177e4SLinus Torvalds 		goto out_release_1;
14371da177e4SLinus Torvalds 
14381da177e4SLinus Torvalds 	err = sock1->ops->socketpair(sock1, sock2);
14391da177e4SLinus Torvalds 	if (err < 0)
14401da177e4SLinus Torvalds 		goto out_release_both;
14411da177e4SLinus Torvalds 
144228407630SAl Viro 	fd1 = get_unused_fd_flags(flags);
1443bf3c23d1SDavid S. Miller 	if (unlikely(fd1 < 0)) {
1444bf3c23d1SDavid S. Miller 		err = fd1;
14451da177e4SLinus Torvalds 		goto out_release_both;
1446bf3c23d1SDavid S. Miller 	}
144728407630SAl Viro 	fd2 = get_unused_fd_flags(flags);
1448198de4d7SAl Viro 	if (unlikely(fd2 < 0)) {
1449198de4d7SAl Viro 		err = fd2;
145028407630SAl Viro 		put_unused_fd(fd1);
145128407630SAl Viro 		goto out_release_both;
145228407630SAl Viro 	}
145328407630SAl Viro 
1454aab174f0SLinus Torvalds 	newfile1 = sock_alloc_file(sock1, flags, NULL);
145528407630SAl Viro 	if (unlikely(IS_ERR(newfile1))) {
145628407630SAl Viro 		err = PTR_ERR(newfile1);
145728407630SAl Viro 		put_unused_fd(fd1);
145828407630SAl Viro 		put_unused_fd(fd2);
145928407630SAl Viro 		goto out_release_both;
146028407630SAl Viro 	}
146128407630SAl Viro 
1462aab174f0SLinus Torvalds 	newfile2 = sock_alloc_file(sock2, flags, NULL);
146328407630SAl Viro 	if (IS_ERR(newfile2)) {
146428407630SAl Viro 		err = PTR_ERR(newfile2);
1465198de4d7SAl Viro 		fput(newfile1);
1466198de4d7SAl Viro 		put_unused_fd(fd1);
146728407630SAl Viro 		put_unused_fd(fd2);
1468198de4d7SAl Viro 		sock_release(sock2);
1469198de4d7SAl Viro 		goto out;
1470db349509SAl Viro 	}
1471db349509SAl Viro 
1472157cf649SAl Viro 	audit_fd_pair(fd1, fd2);
1473db349509SAl Viro 	fd_install(fd1, newfile1);
1474db349509SAl Viro 	fd_install(fd2, newfile2);
14751da177e4SLinus Torvalds 	/* fd1 and fd2 may be already another descriptors.
14761da177e4SLinus Torvalds 	 * Not kernel problem.
14771da177e4SLinus Torvalds 	 */
14781da177e4SLinus Torvalds 
14791da177e4SLinus Torvalds 	err = put_user(fd1, &usockvec[0]);
14801da177e4SLinus Torvalds 	if (!err)
14811da177e4SLinus Torvalds 		err = put_user(fd2, &usockvec[1]);
14821da177e4SLinus Torvalds 	if (!err)
14831da177e4SLinus Torvalds 		return 0;
14841da177e4SLinus Torvalds 
14851da177e4SLinus Torvalds 	sys_close(fd2);
14861da177e4SLinus Torvalds 	sys_close(fd1);
14871da177e4SLinus Torvalds 	return err;
14881da177e4SLinus Torvalds 
14891da177e4SLinus Torvalds out_release_both:
14901da177e4SLinus Torvalds 	sock_release(sock2);
14911da177e4SLinus Torvalds out_release_1:
14921da177e4SLinus Torvalds 	sock_release(sock1);
14931da177e4SLinus Torvalds out:
14941da177e4SLinus Torvalds 	return err;
14951da177e4SLinus Torvalds }
14961da177e4SLinus Torvalds 
14971da177e4SLinus Torvalds /*
14981da177e4SLinus Torvalds  *	Bind a name to a socket. Nothing much to do here since it's
14991da177e4SLinus Torvalds  *	the protocol's responsibility to handle the local address.
15001da177e4SLinus Torvalds  *
15011da177e4SLinus Torvalds  *	We move the socket address to kernel space before we call
15021da177e4SLinus Torvalds  *	the protocol layer (having also checked the address is ok).
15031da177e4SLinus Torvalds  */
15041da177e4SLinus Torvalds 
150520f37034SHeiko Carstens SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
15061da177e4SLinus Torvalds {
15071da177e4SLinus Torvalds 	struct socket *sock;
1508230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
15096cb153caSBenjamin LaHaise 	int err, fput_needed;
15101da177e4SLinus Torvalds 
151189bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
151289bddce5SStephen Hemminger 	if (sock) {
151343db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(umyaddr, addrlen, &address);
151489bddce5SStephen Hemminger 		if (err >= 0) {
151589bddce5SStephen Hemminger 			err = security_socket_bind(sock,
1516230b1839SYOSHIFUJI Hideaki 						   (struct sockaddr *)&address,
151789bddce5SStephen Hemminger 						   addrlen);
15186cb153caSBenjamin LaHaise 			if (!err)
15196cb153caSBenjamin LaHaise 				err = sock->ops->bind(sock,
152089bddce5SStephen Hemminger 						      (struct sockaddr *)
1521230b1839SYOSHIFUJI Hideaki 						      &address, addrlen);
15221da177e4SLinus Torvalds 		}
15236cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
15241da177e4SLinus Torvalds 	}
15251da177e4SLinus Torvalds 	return err;
15261da177e4SLinus Torvalds }
15271da177e4SLinus Torvalds 
15281da177e4SLinus Torvalds /*
15291da177e4SLinus Torvalds  *	Perform a listen. Basically, we allow the protocol to do anything
15301da177e4SLinus Torvalds  *	necessary for a listen, and if that works, we mark the socket as
15311da177e4SLinus Torvalds  *	ready for listening.
15321da177e4SLinus Torvalds  */
15331da177e4SLinus Torvalds 
15343e0fa65fSHeiko Carstens SYSCALL_DEFINE2(listen, int, fd, int, backlog)
15351da177e4SLinus Torvalds {
15361da177e4SLinus Torvalds 	struct socket *sock;
15376cb153caSBenjamin LaHaise 	int err, fput_needed;
1538b8e1f9b5SPavel Emelyanov 	int somaxconn;
15391da177e4SLinus Torvalds 
154089bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
154189bddce5SStephen Hemminger 	if (sock) {
15428efa6e93SPavel Emelyanov 		somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
154395c96174SEric Dumazet 		if ((unsigned int)backlog > somaxconn)
1544b8e1f9b5SPavel Emelyanov 			backlog = somaxconn;
15451da177e4SLinus Torvalds 
15461da177e4SLinus Torvalds 		err = security_socket_listen(sock, backlog);
15476cb153caSBenjamin LaHaise 		if (!err)
15481da177e4SLinus Torvalds 			err = sock->ops->listen(sock, backlog);
15496cb153caSBenjamin LaHaise 
15506cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
15511da177e4SLinus Torvalds 	}
15521da177e4SLinus Torvalds 	return err;
15531da177e4SLinus Torvalds }
15541da177e4SLinus Torvalds 
15551da177e4SLinus Torvalds /*
15561da177e4SLinus Torvalds  *	For accept, we attempt to create a new socket, set up the link
15571da177e4SLinus Torvalds  *	with the client, wake up the client, then return the new
15581da177e4SLinus Torvalds  *	connected fd. We collect the address of the connector in kernel
15591da177e4SLinus Torvalds  *	space and move it to user at the very end. This is unclean because
15601da177e4SLinus Torvalds  *	we open the socket then return an error.
15611da177e4SLinus Torvalds  *
15621da177e4SLinus Torvalds  *	1003.1g adds the ability to recvmsg() to query connection pending
15631da177e4SLinus Torvalds  *	status to recvmsg. We need to add that support in a way thats
15641da177e4SLinus Torvalds  *	clean when we restucture accept also.
15651da177e4SLinus Torvalds  */
15661da177e4SLinus Torvalds 
156720f37034SHeiko Carstens SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
156820f37034SHeiko Carstens 		int __user *, upeer_addrlen, int, flags)
15691da177e4SLinus Torvalds {
15701da177e4SLinus Torvalds 	struct socket *sock, *newsock;
157139d8c1b6SDavid S. Miller 	struct file *newfile;
15726cb153caSBenjamin LaHaise 	int err, len, newfd, fput_needed;
1573230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
15741da177e4SLinus Torvalds 
157577d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1576aaca0bdcSUlrich Drepper 		return -EINVAL;
1577aaca0bdcSUlrich Drepper 
1578aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1579aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1580aaca0bdcSUlrich Drepper 
15816cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
15821da177e4SLinus Torvalds 	if (!sock)
15831da177e4SLinus Torvalds 		goto out;
15841da177e4SLinus Torvalds 
15851da177e4SLinus Torvalds 	err = -ENFILE;
1586c6d409cfSEric Dumazet 	newsock = sock_alloc();
1587c6d409cfSEric Dumazet 	if (!newsock)
15881da177e4SLinus Torvalds 		goto out_put;
15891da177e4SLinus Torvalds 
15901da177e4SLinus Torvalds 	newsock->type = sock->type;
15911da177e4SLinus Torvalds 	newsock->ops = sock->ops;
15921da177e4SLinus Torvalds 
15931da177e4SLinus Torvalds 	/*
15941da177e4SLinus Torvalds 	 * We don't need try_module_get here, as the listening socket (sock)
15951da177e4SLinus Torvalds 	 * has the protocol module (sock->ops->owner) held.
15961da177e4SLinus Torvalds 	 */
15971da177e4SLinus Torvalds 	__module_get(newsock->ops->owner);
15981da177e4SLinus Torvalds 
159928407630SAl Viro 	newfd = get_unused_fd_flags(flags);
160039d8c1b6SDavid S. Miller 	if (unlikely(newfd < 0)) {
160139d8c1b6SDavid S. Miller 		err = newfd;
16029a1875e6SDavid S. Miller 		sock_release(newsock);
16039a1875e6SDavid S. Miller 		goto out_put;
160439d8c1b6SDavid S. Miller 	}
1605aab174f0SLinus Torvalds 	newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name);
160628407630SAl Viro 	if (unlikely(IS_ERR(newfile))) {
160728407630SAl Viro 		err = PTR_ERR(newfile);
160828407630SAl Viro 		put_unused_fd(newfd);
160928407630SAl Viro 		sock_release(newsock);
161028407630SAl Viro 		goto out_put;
161128407630SAl Viro 	}
161239d8c1b6SDavid S. Miller 
1613a79af59eSFrank Filz 	err = security_socket_accept(sock, newsock);
1614a79af59eSFrank Filz 	if (err)
161539d8c1b6SDavid S. Miller 		goto out_fd;
1616a79af59eSFrank Filz 
16171da177e4SLinus Torvalds 	err = sock->ops->accept(sock, newsock, sock->file->f_flags);
16181da177e4SLinus Torvalds 	if (err < 0)
161939d8c1b6SDavid S. Miller 		goto out_fd;
16201da177e4SLinus Torvalds 
16211da177e4SLinus Torvalds 	if (upeer_sockaddr) {
1622230b1839SYOSHIFUJI Hideaki 		if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
162389bddce5SStephen Hemminger 					  &len, 2) < 0) {
16241da177e4SLinus Torvalds 			err = -ECONNABORTED;
162539d8c1b6SDavid S. Miller 			goto out_fd;
16261da177e4SLinus Torvalds 		}
162743db362dSMaciej Żenczykowski 		err = move_addr_to_user(&address,
1628230b1839SYOSHIFUJI Hideaki 					len, upeer_sockaddr, upeer_addrlen);
16291da177e4SLinus Torvalds 		if (err < 0)
163039d8c1b6SDavid S. Miller 			goto out_fd;
16311da177e4SLinus Torvalds 	}
16321da177e4SLinus Torvalds 
16331da177e4SLinus Torvalds 	/* File flags are not inherited via accept() unlike another OSes. */
16341da177e4SLinus Torvalds 
163539d8c1b6SDavid S. Miller 	fd_install(newfd, newfile);
163639d8c1b6SDavid S. Miller 	err = newfd;
16371da177e4SLinus Torvalds 
16381da177e4SLinus Torvalds out_put:
16396cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
16401da177e4SLinus Torvalds out:
16411da177e4SLinus Torvalds 	return err;
164239d8c1b6SDavid S. Miller out_fd:
16439606a216SDavid S. Miller 	fput(newfile);
164439d8c1b6SDavid S. Miller 	put_unused_fd(newfd);
16451da177e4SLinus Torvalds 	goto out_put;
16461da177e4SLinus Torvalds }
16471da177e4SLinus Torvalds 
164820f37034SHeiko Carstens SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,
164920f37034SHeiko Carstens 		int __user *, upeer_addrlen)
1650aaca0bdcSUlrich Drepper {
1651de11defeSUlrich Drepper 	return sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0);
1652aaca0bdcSUlrich Drepper }
1653aaca0bdcSUlrich Drepper 
16541da177e4SLinus Torvalds /*
16551da177e4SLinus Torvalds  *	Attempt to connect to a socket with the server address.  The address
16561da177e4SLinus Torvalds  *	is in user space so we verify it is OK and move it to kernel space.
16571da177e4SLinus Torvalds  *
16581da177e4SLinus Torvalds  *	For 1003.1g we need to add clean support for a bind to AF_UNSPEC to
16591da177e4SLinus Torvalds  *	break bindings
16601da177e4SLinus Torvalds  *
16611da177e4SLinus Torvalds  *	NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and
16621da177e4SLinus Torvalds  *	other SEQPACKET protocols that take time to connect() as it doesn't
16631da177e4SLinus Torvalds  *	include the -EINPROGRESS status for such sockets.
16641da177e4SLinus Torvalds  */
16651da177e4SLinus Torvalds 
166620f37034SHeiko Carstens SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
166720f37034SHeiko Carstens 		int, addrlen)
16681da177e4SLinus Torvalds {
16691da177e4SLinus Torvalds 	struct socket *sock;
1670230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16716cb153caSBenjamin LaHaise 	int err, fput_needed;
16721da177e4SLinus Torvalds 
16736cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
16741da177e4SLinus Torvalds 	if (!sock)
16751da177e4SLinus Torvalds 		goto out;
167643db362dSMaciej Żenczykowski 	err = move_addr_to_kernel(uservaddr, addrlen, &address);
16771da177e4SLinus Torvalds 	if (err < 0)
16781da177e4SLinus Torvalds 		goto out_put;
16791da177e4SLinus Torvalds 
168089bddce5SStephen Hemminger 	err =
1681230b1839SYOSHIFUJI Hideaki 	    security_socket_connect(sock, (struct sockaddr *)&address, addrlen);
16821da177e4SLinus Torvalds 	if (err)
16831da177e4SLinus Torvalds 		goto out_put;
16841da177e4SLinus Torvalds 
1685230b1839SYOSHIFUJI Hideaki 	err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,
16861da177e4SLinus Torvalds 				 sock->file->f_flags);
16871da177e4SLinus Torvalds out_put:
16886cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
16891da177e4SLinus Torvalds out:
16901da177e4SLinus Torvalds 	return err;
16911da177e4SLinus Torvalds }
16921da177e4SLinus Torvalds 
16931da177e4SLinus Torvalds /*
16941da177e4SLinus Torvalds  *	Get the local address ('name') of a socket object. Move the obtained
16951da177e4SLinus Torvalds  *	name to user space.
16961da177e4SLinus Torvalds  */
16971da177e4SLinus Torvalds 
169820f37034SHeiko Carstens SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
169920f37034SHeiko Carstens 		int __user *, usockaddr_len)
17001da177e4SLinus Torvalds {
17011da177e4SLinus Torvalds 	struct socket *sock;
1702230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
17036cb153caSBenjamin LaHaise 	int len, err, fput_needed;
17041da177e4SLinus Torvalds 
17056cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
17061da177e4SLinus Torvalds 	if (!sock)
17071da177e4SLinus Torvalds 		goto out;
17081da177e4SLinus Torvalds 
17091da177e4SLinus Torvalds 	err = security_socket_getsockname(sock);
17101da177e4SLinus Torvalds 	if (err)
17111da177e4SLinus Torvalds 		goto out_put;
17121da177e4SLinus Torvalds 
1713230b1839SYOSHIFUJI Hideaki 	err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0);
17141da177e4SLinus Torvalds 	if (err)
17151da177e4SLinus Torvalds 		goto out_put;
171643db362dSMaciej Żenczykowski 	err = move_addr_to_user(&address, len, usockaddr, usockaddr_len);
17171da177e4SLinus Torvalds 
17181da177e4SLinus Torvalds out_put:
17196cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
17201da177e4SLinus Torvalds out:
17211da177e4SLinus Torvalds 	return err;
17221da177e4SLinus Torvalds }
17231da177e4SLinus Torvalds 
17241da177e4SLinus Torvalds /*
17251da177e4SLinus Torvalds  *	Get the remote address ('name') of a socket object. Move the obtained
17261da177e4SLinus Torvalds  *	name to user space.
17271da177e4SLinus Torvalds  */
17281da177e4SLinus Torvalds 
172920f37034SHeiko Carstens SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
173020f37034SHeiko Carstens 		int __user *, usockaddr_len)
17311da177e4SLinus Torvalds {
17321da177e4SLinus Torvalds 	struct socket *sock;
1733230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
17346cb153caSBenjamin LaHaise 	int len, err, fput_needed;
17351da177e4SLinus Torvalds 
173689bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
173789bddce5SStephen Hemminger 	if (sock != NULL) {
17381da177e4SLinus Torvalds 		err = security_socket_getpeername(sock);
17391da177e4SLinus Torvalds 		if (err) {
17406cb153caSBenjamin LaHaise 			fput_light(sock->file, fput_needed);
17411da177e4SLinus Torvalds 			return err;
17421da177e4SLinus Torvalds 		}
17431da177e4SLinus Torvalds 
174489bddce5SStephen Hemminger 		err =
1745230b1839SYOSHIFUJI Hideaki 		    sock->ops->getname(sock, (struct sockaddr *)&address, &len,
174689bddce5SStephen Hemminger 				       1);
17471da177e4SLinus Torvalds 		if (!err)
174843db362dSMaciej Żenczykowski 			err = move_addr_to_user(&address, len, usockaddr,
174989bddce5SStephen Hemminger 						usockaddr_len);
17506cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
17511da177e4SLinus Torvalds 	}
17521da177e4SLinus Torvalds 	return err;
17531da177e4SLinus Torvalds }
17541da177e4SLinus Torvalds 
17551da177e4SLinus Torvalds /*
17561da177e4SLinus Torvalds  *	Send a datagram to a given address. We move the address into kernel
17571da177e4SLinus Torvalds  *	space and check the user space data area is readable before invoking
17581da177e4SLinus Torvalds  *	the protocol.
17591da177e4SLinus Torvalds  */
17601da177e4SLinus Torvalds 
17613e0fa65fSHeiko Carstens SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
176295c96174SEric Dumazet 		unsigned int, flags, struct sockaddr __user *, addr,
17633e0fa65fSHeiko Carstens 		int, addr_len)
17641da177e4SLinus Torvalds {
17651da177e4SLinus Torvalds 	struct socket *sock;
1766230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
17671da177e4SLinus Torvalds 	int err;
17681da177e4SLinus Torvalds 	struct msghdr msg;
17691da177e4SLinus Torvalds 	struct iovec iov;
17706cb153caSBenjamin LaHaise 	int fput_needed;
17711da177e4SLinus Torvalds 
1772253eacc0SLinus Torvalds 	if (len > INT_MAX)
1773253eacc0SLinus Torvalds 		len = INT_MAX;
1774de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1775de0fa95cSPavel Emelyanov 	if (!sock)
17764387ff75SDavid S. Miller 		goto out;
17776cb153caSBenjamin LaHaise 
17781da177e4SLinus Torvalds 	iov.iov_base = buff;
17791da177e4SLinus Torvalds 	iov.iov_len = len;
17801da177e4SLinus Torvalds 	msg.msg_name = NULL;
17811da177e4SLinus Torvalds 	msg.msg_iov = &iov;
17821da177e4SLinus Torvalds 	msg.msg_iovlen = 1;
17831da177e4SLinus Torvalds 	msg.msg_control = NULL;
17841da177e4SLinus Torvalds 	msg.msg_controllen = 0;
17851da177e4SLinus Torvalds 	msg.msg_namelen = 0;
17866cb153caSBenjamin LaHaise 	if (addr) {
178743db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(addr, addr_len, &address);
17881da177e4SLinus Torvalds 		if (err < 0)
17891da177e4SLinus Torvalds 			goto out_put;
1790230b1839SYOSHIFUJI Hideaki 		msg.msg_name = (struct sockaddr *)&address;
17911da177e4SLinus Torvalds 		msg.msg_namelen = addr_len;
17921da177e4SLinus Torvalds 	}
17931da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
17941da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
17951da177e4SLinus Torvalds 	msg.msg_flags = flags;
17961da177e4SLinus Torvalds 	err = sock_sendmsg(sock, &msg, len);
17971da177e4SLinus Torvalds 
17981da177e4SLinus Torvalds out_put:
1799de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
18004387ff75SDavid S. Miller out:
18011da177e4SLinus Torvalds 	return err;
18021da177e4SLinus Torvalds }
18031da177e4SLinus Torvalds 
18041da177e4SLinus Torvalds /*
18051da177e4SLinus Torvalds  *	Send a datagram down a socket.
18061da177e4SLinus Torvalds  */
18071da177e4SLinus Torvalds 
18083e0fa65fSHeiko Carstens SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len,
180995c96174SEric Dumazet 		unsigned int, flags)
18101da177e4SLinus Torvalds {
18111da177e4SLinus Torvalds 	return sys_sendto(fd, buff, len, flags, NULL, 0);
18121da177e4SLinus Torvalds }
18131da177e4SLinus Torvalds 
18141da177e4SLinus Torvalds /*
18151da177e4SLinus Torvalds  *	Receive a frame from the socket and optionally record the address of the
18161da177e4SLinus Torvalds  *	sender. We verify the buffers are writable and if needed move the
18171da177e4SLinus Torvalds  *	sender address from kernel to user space.
18181da177e4SLinus Torvalds  */
18191da177e4SLinus Torvalds 
18203e0fa65fSHeiko Carstens SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
182195c96174SEric Dumazet 		unsigned int, flags, struct sockaddr __user *, addr,
18223e0fa65fSHeiko Carstens 		int __user *, addr_len)
18231da177e4SLinus Torvalds {
18241da177e4SLinus Torvalds 	struct socket *sock;
18251da177e4SLinus Torvalds 	struct iovec iov;
18261da177e4SLinus Torvalds 	struct msghdr msg;
1827230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
18281da177e4SLinus Torvalds 	int err, err2;
18296cb153caSBenjamin LaHaise 	int fput_needed;
18301da177e4SLinus Torvalds 
1831253eacc0SLinus Torvalds 	if (size > INT_MAX)
1832253eacc0SLinus Torvalds 		size = INT_MAX;
1833de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
18341da177e4SLinus Torvalds 	if (!sock)
1835de0fa95cSPavel Emelyanov 		goto out;
18361da177e4SLinus Torvalds 
18371da177e4SLinus Torvalds 	msg.msg_control = NULL;
18381da177e4SLinus Torvalds 	msg.msg_controllen = 0;
18391da177e4SLinus Torvalds 	msg.msg_iovlen = 1;
18401da177e4SLinus Torvalds 	msg.msg_iov = &iov;
18411da177e4SLinus Torvalds 	iov.iov_len = size;
18421da177e4SLinus Torvalds 	iov.iov_base = ubuf;
1843*f3d33426SHannes Frederic Sowa 	/* Save some cycles and don't copy the address if not needed */
1844*f3d33426SHannes Frederic Sowa 	msg.msg_name = addr ? (struct sockaddr *)&address : NULL;
1845*f3d33426SHannes Frederic Sowa 	/* We assume all kernel code knows the size of sockaddr_storage */
1846*f3d33426SHannes Frederic Sowa 	msg.msg_namelen = 0;
18471da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
18481da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
18491da177e4SLinus Torvalds 	err = sock_recvmsg(sock, &msg, size, flags);
18501da177e4SLinus Torvalds 
185189bddce5SStephen Hemminger 	if (err >= 0 && addr != NULL) {
185243db362dSMaciej Żenczykowski 		err2 = move_addr_to_user(&address,
1853230b1839SYOSHIFUJI Hideaki 					 msg.msg_namelen, addr, addr_len);
18541da177e4SLinus Torvalds 		if (err2 < 0)
18551da177e4SLinus Torvalds 			err = err2;
18561da177e4SLinus Torvalds 	}
1857de0fa95cSPavel Emelyanov 
1858de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
18594387ff75SDavid S. Miller out:
18601da177e4SLinus Torvalds 	return err;
18611da177e4SLinus Torvalds }
18621da177e4SLinus Torvalds 
18631da177e4SLinus Torvalds /*
18641da177e4SLinus Torvalds  *	Receive a datagram from a socket.
18651da177e4SLinus Torvalds  */
18661da177e4SLinus Torvalds 
186789bddce5SStephen Hemminger asmlinkage long sys_recv(int fd, void __user *ubuf, size_t size,
186895c96174SEric Dumazet 			 unsigned int flags)
18691da177e4SLinus Torvalds {
18701da177e4SLinus Torvalds 	return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL);
18711da177e4SLinus Torvalds }
18721da177e4SLinus Torvalds 
18731da177e4SLinus Torvalds /*
18741da177e4SLinus Torvalds  *	Set a socket option. Because we don't know the option lengths we have
18751da177e4SLinus Torvalds  *	to pass the user mode parameter for the protocols to sort out.
18761da177e4SLinus Torvalds  */
18771da177e4SLinus Torvalds 
187820f37034SHeiko Carstens SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
187920f37034SHeiko Carstens 		char __user *, optval, int, optlen)
18801da177e4SLinus Torvalds {
18816cb153caSBenjamin LaHaise 	int err, fput_needed;
18821da177e4SLinus Torvalds 	struct socket *sock;
18831da177e4SLinus Torvalds 
18841da177e4SLinus Torvalds 	if (optlen < 0)
18851da177e4SLinus Torvalds 		return -EINVAL;
18861da177e4SLinus Torvalds 
188789bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
188889bddce5SStephen Hemminger 	if (sock != NULL) {
18891da177e4SLinus Torvalds 		err = security_socket_setsockopt(sock, level, optname);
18906cb153caSBenjamin LaHaise 		if (err)
18916cb153caSBenjamin LaHaise 			goto out_put;
18921da177e4SLinus Torvalds 
18931da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
189489bddce5SStephen Hemminger 			err =
189589bddce5SStephen Hemminger 			    sock_setsockopt(sock, level, optname, optval,
189689bddce5SStephen Hemminger 					    optlen);
18971da177e4SLinus Torvalds 		else
189889bddce5SStephen Hemminger 			err =
189989bddce5SStephen Hemminger 			    sock->ops->setsockopt(sock, level, optname, optval,
190089bddce5SStephen Hemminger 						  optlen);
19016cb153caSBenjamin LaHaise out_put:
19026cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
19031da177e4SLinus Torvalds 	}
19041da177e4SLinus Torvalds 	return err;
19051da177e4SLinus Torvalds }
19061da177e4SLinus Torvalds 
19071da177e4SLinus Torvalds /*
19081da177e4SLinus Torvalds  *	Get a socket option. Because we don't know the option lengths we have
19091da177e4SLinus Torvalds  *	to pass a user mode parameter for the protocols to sort out.
19101da177e4SLinus Torvalds  */
19111da177e4SLinus Torvalds 
191220f37034SHeiko Carstens SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
191320f37034SHeiko Carstens 		char __user *, optval, int __user *, optlen)
19141da177e4SLinus Torvalds {
19156cb153caSBenjamin LaHaise 	int err, fput_needed;
19161da177e4SLinus Torvalds 	struct socket *sock;
19171da177e4SLinus Torvalds 
191889bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
191989bddce5SStephen Hemminger 	if (sock != NULL) {
19206cb153caSBenjamin LaHaise 		err = security_socket_getsockopt(sock, level, optname);
19216cb153caSBenjamin LaHaise 		if (err)
19226cb153caSBenjamin LaHaise 			goto out_put;
19231da177e4SLinus Torvalds 
19241da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
192589bddce5SStephen Hemminger 			err =
192689bddce5SStephen Hemminger 			    sock_getsockopt(sock, level, optname, optval,
192789bddce5SStephen Hemminger 					    optlen);
19281da177e4SLinus Torvalds 		else
192989bddce5SStephen Hemminger 			err =
193089bddce5SStephen Hemminger 			    sock->ops->getsockopt(sock, level, optname, optval,
193189bddce5SStephen Hemminger 						  optlen);
19326cb153caSBenjamin LaHaise out_put:
19336cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
19341da177e4SLinus Torvalds 	}
19351da177e4SLinus Torvalds 	return err;
19361da177e4SLinus Torvalds }
19371da177e4SLinus Torvalds 
19381da177e4SLinus Torvalds /*
19391da177e4SLinus Torvalds  *	Shutdown a socket.
19401da177e4SLinus Torvalds  */
19411da177e4SLinus Torvalds 
1942754fe8d2SHeiko Carstens SYSCALL_DEFINE2(shutdown, int, fd, int, how)
19431da177e4SLinus Torvalds {
19446cb153caSBenjamin LaHaise 	int err, fput_needed;
19451da177e4SLinus Torvalds 	struct socket *sock;
19461da177e4SLinus Torvalds 
194789bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
194889bddce5SStephen Hemminger 	if (sock != NULL) {
19491da177e4SLinus Torvalds 		err = security_socket_shutdown(sock, how);
19506cb153caSBenjamin LaHaise 		if (!err)
19511da177e4SLinus Torvalds 			err = sock->ops->shutdown(sock, how);
19526cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
19531da177e4SLinus Torvalds 	}
19541da177e4SLinus Torvalds 	return err;
19551da177e4SLinus Torvalds }
19561da177e4SLinus Torvalds 
19571da177e4SLinus Torvalds /* A couple of helpful macros for getting the address of the 32/64 bit
19581da177e4SLinus Torvalds  * fields which are the same type (int / unsigned) on our platforms.
19591da177e4SLinus Torvalds  */
19601da177e4SLinus Torvalds #define COMPAT_MSG(msg, member)	((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member)
19611da177e4SLinus Torvalds #define COMPAT_NAMELEN(msg)	COMPAT_MSG(msg, msg_namelen)
19621da177e4SLinus Torvalds #define COMPAT_FLAGS(msg)	COMPAT_MSG(msg, msg_flags)
19631da177e4SLinus Torvalds 
1964c71d8ebeSTetsuo Handa struct used_address {
1965c71d8ebeSTetsuo Handa 	struct sockaddr_storage name;
1966c71d8ebeSTetsuo Handa 	unsigned int name_len;
1967c71d8ebeSTetsuo Handa };
1968c71d8ebeSTetsuo Handa 
19691661bf36SDan Carpenter static int copy_msghdr_from_user(struct msghdr *kmsg,
19701661bf36SDan Carpenter 				 struct msghdr __user *umsg)
19711661bf36SDan Carpenter {
19721661bf36SDan Carpenter 	if (copy_from_user(kmsg, umsg, sizeof(struct msghdr)))
19731661bf36SDan Carpenter 		return -EFAULT;
19741661bf36SDan Carpenter 	if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
19751661bf36SDan Carpenter 		return -EINVAL;
19761661bf36SDan Carpenter 	return 0;
19771661bf36SDan Carpenter }
19781661bf36SDan Carpenter 
1979a7526eb5SAndy Lutomirski static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
198095c96174SEric Dumazet 			 struct msghdr *msg_sys, unsigned int flags,
1981c71d8ebeSTetsuo Handa 			 struct used_address *used_address)
19821da177e4SLinus Torvalds {
198389bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
198489bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
1985230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
19861da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
1987b9d717a7SAlex Williamson 	unsigned char ctl[sizeof(struct cmsghdr) + 20]
1988b9d717a7SAlex Williamson 	    __attribute__ ((aligned(sizeof(__kernel_size_t))));
1989b9d717a7SAlex Williamson 	/* 20 is size of ipv6_pktinfo */
19901da177e4SLinus Torvalds 	unsigned char *ctl_buf = ctl;
1991a74e9106SEric Dumazet 	int err, ctl_len, total_len;
19921da177e4SLinus Torvalds 
19931da177e4SLinus Torvalds 	err = -EFAULT;
19941da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
1995228e548eSAnton Blanchard 		if (get_compat_msghdr(msg_sys, msg_compat))
19961da177e4SLinus Torvalds 			return -EFAULT;
19971661bf36SDan Carpenter 	} else {
19981661bf36SDan Carpenter 		err = copy_msghdr_from_user(msg_sys, msg);
19991661bf36SDan Carpenter 		if (err)
20001661bf36SDan Carpenter 			return err;
20011661bf36SDan Carpenter 	}
20021da177e4SLinus Torvalds 
2003a74e9106SEric Dumazet 	if (msg_sys->msg_iovlen > UIO_FASTIOV) {
20041da177e4SLinus Torvalds 		err = -EMSGSIZE;
2005228e548eSAnton Blanchard 		if (msg_sys->msg_iovlen > UIO_MAXIOV)
2006228e548eSAnton Blanchard 			goto out;
20071da177e4SLinus Torvalds 		err = -ENOMEM;
2008a74e9106SEric Dumazet 		iov = kmalloc(msg_sys->msg_iovlen * sizeof(struct iovec),
2009a74e9106SEric Dumazet 			      GFP_KERNEL);
20101da177e4SLinus Torvalds 		if (!iov)
2011228e548eSAnton Blanchard 			goto out;
20121da177e4SLinus Torvalds 	}
20131da177e4SLinus Torvalds 
20141da177e4SLinus Torvalds 	/* This will also move the address data into kernel space */
20151da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
201643db362dSMaciej Żenczykowski 		err = verify_compat_iovec(msg_sys, iov, &address, VERIFY_READ);
20171da177e4SLinus Torvalds 	} else
201843db362dSMaciej Żenczykowski 		err = verify_iovec(msg_sys, iov, &address, VERIFY_READ);
20191da177e4SLinus Torvalds 	if (err < 0)
20201da177e4SLinus Torvalds 		goto out_freeiov;
20211da177e4SLinus Torvalds 	total_len = err;
20221da177e4SLinus Torvalds 
20231da177e4SLinus Torvalds 	err = -ENOBUFS;
20241da177e4SLinus Torvalds 
2025228e548eSAnton Blanchard 	if (msg_sys->msg_controllen > INT_MAX)
20261da177e4SLinus Torvalds 		goto out_freeiov;
2027228e548eSAnton Blanchard 	ctl_len = msg_sys->msg_controllen;
20281da177e4SLinus Torvalds 	if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
202989bddce5SStephen Hemminger 		err =
2030228e548eSAnton Blanchard 		    cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl,
203189bddce5SStephen Hemminger 						     sizeof(ctl));
20321da177e4SLinus Torvalds 		if (err)
20331da177e4SLinus Torvalds 			goto out_freeiov;
2034228e548eSAnton Blanchard 		ctl_buf = msg_sys->msg_control;
2035228e548eSAnton Blanchard 		ctl_len = msg_sys->msg_controllen;
20361da177e4SLinus Torvalds 	} else if (ctl_len) {
203789bddce5SStephen Hemminger 		if (ctl_len > sizeof(ctl)) {
20381da177e4SLinus Torvalds 			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
20391da177e4SLinus Torvalds 			if (ctl_buf == NULL)
20401da177e4SLinus Torvalds 				goto out_freeiov;
20411da177e4SLinus Torvalds 		}
20421da177e4SLinus Torvalds 		err = -EFAULT;
20431da177e4SLinus Torvalds 		/*
2044228e548eSAnton Blanchard 		 * Careful! Before this, msg_sys->msg_control contains a user pointer.
20451da177e4SLinus Torvalds 		 * Afterwards, it will be a kernel pointer. Thus the compiler-assisted
20461da177e4SLinus Torvalds 		 * checking falls down on this.
20471da177e4SLinus Torvalds 		 */
2048fb8621bbSNamhyung Kim 		if (copy_from_user(ctl_buf,
2049228e548eSAnton Blanchard 				   (void __user __force *)msg_sys->msg_control,
205089bddce5SStephen Hemminger 				   ctl_len))
20511da177e4SLinus Torvalds 			goto out_freectl;
2052228e548eSAnton Blanchard 		msg_sys->msg_control = ctl_buf;
20531da177e4SLinus Torvalds 	}
2054228e548eSAnton Blanchard 	msg_sys->msg_flags = flags;
20551da177e4SLinus Torvalds 
20561da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
2057228e548eSAnton Blanchard 		msg_sys->msg_flags |= MSG_DONTWAIT;
2058c71d8ebeSTetsuo Handa 	/*
2059c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and current destination address is same as
2060c71d8ebeSTetsuo Handa 	 * previously succeeded address, omit asking LSM's decision.
2061c71d8ebeSTetsuo Handa 	 * used_address->name_len is initialized to UINT_MAX so that the first
2062c71d8ebeSTetsuo Handa 	 * destination address never matches.
2063c71d8ebeSTetsuo Handa 	 */
2064bc909d9dSMathieu Desnoyers 	if (used_address && msg_sys->msg_name &&
2065bc909d9dSMathieu Desnoyers 	    used_address->name_len == msg_sys->msg_namelen &&
2066bc909d9dSMathieu Desnoyers 	    !memcmp(&used_address->name, msg_sys->msg_name,
2067c71d8ebeSTetsuo Handa 		    used_address->name_len)) {
2068c71d8ebeSTetsuo Handa 		err = sock_sendmsg_nosec(sock, msg_sys, total_len);
2069c71d8ebeSTetsuo Handa 		goto out_freectl;
2070c71d8ebeSTetsuo Handa 	}
2071c71d8ebeSTetsuo Handa 	err = sock_sendmsg(sock, msg_sys, total_len);
2072c71d8ebeSTetsuo Handa 	/*
2073c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and sending to current destination address was
2074c71d8ebeSTetsuo Handa 	 * successful, remember it.
2075c71d8ebeSTetsuo Handa 	 */
2076c71d8ebeSTetsuo Handa 	if (used_address && err >= 0) {
2077c71d8ebeSTetsuo Handa 		used_address->name_len = msg_sys->msg_namelen;
2078bc909d9dSMathieu Desnoyers 		if (msg_sys->msg_name)
2079bc909d9dSMathieu Desnoyers 			memcpy(&used_address->name, msg_sys->msg_name,
2080c71d8ebeSTetsuo Handa 			       used_address->name_len);
2081c71d8ebeSTetsuo Handa 	}
20821da177e4SLinus Torvalds 
20831da177e4SLinus Torvalds out_freectl:
20841da177e4SLinus Torvalds 	if (ctl_buf != ctl)
20851da177e4SLinus Torvalds 		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
20861da177e4SLinus Torvalds out_freeiov:
20871da177e4SLinus Torvalds 	if (iov != iovstack)
2088a74e9106SEric Dumazet 		kfree(iov);
2089228e548eSAnton Blanchard out:
2090228e548eSAnton Blanchard 	return err;
2091228e548eSAnton Blanchard }
2092228e548eSAnton Blanchard 
2093228e548eSAnton Blanchard /*
2094228e548eSAnton Blanchard  *	BSD sendmsg interface
2095228e548eSAnton Blanchard  */
2096228e548eSAnton Blanchard 
2097a7526eb5SAndy Lutomirski long __sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
2098228e548eSAnton Blanchard {
2099228e548eSAnton Blanchard 	int fput_needed, err;
2100228e548eSAnton Blanchard 	struct msghdr msg_sys;
21011be374a0SAndy Lutomirski 	struct socket *sock;
2102228e548eSAnton Blanchard 
21031be374a0SAndy Lutomirski 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2104228e548eSAnton Blanchard 	if (!sock)
2105228e548eSAnton Blanchard 		goto out;
2106228e548eSAnton Blanchard 
2107a7526eb5SAndy Lutomirski 	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 
2114a7526eb5SAndy Lutomirski SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned int, flags)
2115a7526eb5SAndy Lutomirski {
2116a7526eb5SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
2117a7526eb5SAndy Lutomirski 		return -EINVAL;
2118a7526eb5SAndy Lutomirski 	return __sys_sendmsg(fd, msg, flags);
2119a7526eb5SAndy Lutomirski }
2120a7526eb5SAndy Lutomirski 
2121228e548eSAnton Blanchard /*
2122228e548eSAnton Blanchard  *	Linux sendmmsg interface
2123228e548eSAnton Blanchard  */
2124228e548eSAnton Blanchard 
2125228e548eSAnton Blanchard int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2126228e548eSAnton Blanchard 		   unsigned int flags)
2127228e548eSAnton Blanchard {
2128228e548eSAnton Blanchard 	int fput_needed, err, datagrams;
2129228e548eSAnton Blanchard 	struct socket *sock;
2130228e548eSAnton Blanchard 	struct mmsghdr __user *entry;
2131228e548eSAnton Blanchard 	struct compat_mmsghdr __user *compat_entry;
2132228e548eSAnton Blanchard 	struct msghdr msg_sys;
2133c71d8ebeSTetsuo Handa 	struct used_address used_address;
2134228e548eSAnton Blanchard 
213598382f41SAnton Blanchard 	if (vlen > UIO_MAXIOV)
213698382f41SAnton Blanchard 		vlen = UIO_MAXIOV;
2137228e548eSAnton Blanchard 
2138228e548eSAnton Blanchard 	datagrams = 0;
2139228e548eSAnton Blanchard 
2140228e548eSAnton Blanchard 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2141228e548eSAnton Blanchard 	if (!sock)
2142228e548eSAnton Blanchard 		return err;
2143228e548eSAnton Blanchard 
2144c71d8ebeSTetsuo Handa 	used_address.name_len = UINT_MAX;
2145228e548eSAnton Blanchard 	entry = mmsg;
2146228e548eSAnton Blanchard 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2147728ffb86SAnton Blanchard 	err = 0;
2148228e548eSAnton Blanchard 
2149228e548eSAnton Blanchard 	while (datagrams < vlen) {
2150228e548eSAnton Blanchard 		if (MSG_CMSG_COMPAT & flags) {
2151a7526eb5SAndy Lutomirski 			err = ___sys_sendmsg(sock, (struct msghdr __user *)compat_entry,
2152c71d8ebeSTetsuo Handa 					     &msg_sys, flags, &used_address);
2153228e548eSAnton Blanchard 			if (err < 0)
2154228e548eSAnton Blanchard 				break;
2155228e548eSAnton Blanchard 			err = __put_user(err, &compat_entry->msg_len);
2156228e548eSAnton Blanchard 			++compat_entry;
2157228e548eSAnton Blanchard 		} else {
2158a7526eb5SAndy Lutomirski 			err = ___sys_sendmsg(sock,
2159a7526eb5SAndy Lutomirski 					     (struct msghdr __user *)entry,
2160c71d8ebeSTetsuo Handa 					     &msg_sys, flags, &used_address);
2161228e548eSAnton Blanchard 			if (err < 0)
2162228e548eSAnton Blanchard 				break;
2163228e548eSAnton Blanchard 			err = put_user(err, &entry->msg_len);
2164228e548eSAnton Blanchard 			++entry;
2165228e548eSAnton Blanchard 		}
2166228e548eSAnton Blanchard 
2167228e548eSAnton Blanchard 		if (err)
2168228e548eSAnton Blanchard 			break;
2169228e548eSAnton Blanchard 		++datagrams;
2170228e548eSAnton Blanchard 	}
2171228e548eSAnton Blanchard 
2172228e548eSAnton Blanchard 	fput_light(sock->file, fput_needed);
2173228e548eSAnton Blanchard 
2174728ffb86SAnton Blanchard 	/* We only return an error if no datagrams were able to be sent */
2175728ffb86SAnton Blanchard 	if (datagrams != 0)
2176228e548eSAnton Blanchard 		return datagrams;
2177228e548eSAnton Blanchard 
2178228e548eSAnton Blanchard 	return err;
2179228e548eSAnton Blanchard }
2180228e548eSAnton Blanchard 
2181228e548eSAnton Blanchard SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
2182228e548eSAnton Blanchard 		unsigned int, vlen, unsigned int, flags)
2183228e548eSAnton Blanchard {
21841be374a0SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
21851be374a0SAndy Lutomirski 		return -EINVAL;
2186228e548eSAnton Blanchard 	return __sys_sendmmsg(fd, mmsg, vlen, flags);
2187228e548eSAnton Blanchard }
2188228e548eSAnton Blanchard 
2189a7526eb5SAndy Lutomirski static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
219095c96174SEric Dumazet 			 struct msghdr *msg_sys, unsigned int flags, int nosec)
21911da177e4SLinus Torvalds {
219289bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
219389bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
21941da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV];
21951da177e4SLinus Torvalds 	struct iovec *iov = iovstack;
21961da177e4SLinus Torvalds 	unsigned long cmsg_ptr;
2197a74e9106SEric Dumazet 	int err, total_len, len;
21981da177e4SLinus Torvalds 
21991da177e4SLinus Torvalds 	/* kernel mode address */
2200230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage addr;
22011da177e4SLinus Torvalds 
22021da177e4SLinus Torvalds 	/* user mode address pointers */
22031da177e4SLinus Torvalds 	struct sockaddr __user *uaddr;
22041da177e4SLinus Torvalds 	int __user *uaddr_len;
22051da177e4SLinus Torvalds 
22061da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
2207a2e27255SArnaldo Carvalho de Melo 		if (get_compat_msghdr(msg_sys, msg_compat))
22081da177e4SLinus Torvalds 			return -EFAULT;
22091661bf36SDan Carpenter 	} else {
22101661bf36SDan Carpenter 		err = copy_msghdr_from_user(msg_sys, msg);
22111661bf36SDan Carpenter 		if (err)
22121661bf36SDan Carpenter 			return err;
22131661bf36SDan Carpenter 	}
22141da177e4SLinus Torvalds 
2215a74e9106SEric Dumazet 	if (msg_sys->msg_iovlen > UIO_FASTIOV) {
22161da177e4SLinus Torvalds 		err = -EMSGSIZE;
2217a2e27255SArnaldo Carvalho de Melo 		if (msg_sys->msg_iovlen > UIO_MAXIOV)
2218a2e27255SArnaldo Carvalho de Melo 			goto out;
22191da177e4SLinus Torvalds 		err = -ENOMEM;
2220a74e9106SEric Dumazet 		iov = kmalloc(msg_sys->msg_iovlen * sizeof(struct iovec),
2221a74e9106SEric Dumazet 			      GFP_KERNEL);
22221da177e4SLinus Torvalds 		if (!iov)
2223a2e27255SArnaldo Carvalho de Melo 			goto out;
22241da177e4SLinus Torvalds 	}
22251da177e4SLinus Torvalds 
2226*f3d33426SHannes Frederic Sowa 	/* Save the user-mode address (verify_iovec will change the
22271da177e4SLinus Torvalds 	 * kernel msghdr to use the kernel address space)
22281da177e4SLinus Torvalds 	 */
2229a2e27255SArnaldo Carvalho de Melo 	uaddr = (__force void __user *)msg_sys->msg_name;
22301da177e4SLinus Torvalds 	uaddr_len = COMPAT_NAMELEN(msg);
2231*f3d33426SHannes Frederic Sowa 	if (MSG_CMSG_COMPAT & flags)
223243db362dSMaciej Żenczykowski 		err = verify_compat_iovec(msg_sys, iov, &addr, VERIFY_WRITE);
2233*f3d33426SHannes Frederic Sowa 	else
223443db362dSMaciej Żenczykowski 		err = verify_iovec(msg_sys, iov, &addr, VERIFY_WRITE);
22351da177e4SLinus Torvalds 	if (err < 0)
22361da177e4SLinus Torvalds 		goto out_freeiov;
22371da177e4SLinus Torvalds 	total_len = err;
22381da177e4SLinus Torvalds 
2239a2e27255SArnaldo Carvalho de Melo 	cmsg_ptr = (unsigned long)msg_sys->msg_control;
2240a2e27255SArnaldo Carvalho de Melo 	msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
22411da177e4SLinus Torvalds 
2242*f3d33426SHannes Frederic Sowa 	/* We assume all kernel code knows the size of sockaddr_storage */
2243*f3d33426SHannes Frederic Sowa 	msg_sys->msg_namelen = 0;
2244*f3d33426SHannes Frederic Sowa 
22451da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
22461da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
2247a2e27255SArnaldo Carvalho de Melo 	err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys,
2248a2e27255SArnaldo Carvalho de Melo 							  total_len, flags);
22491da177e4SLinus Torvalds 	if (err < 0)
22501da177e4SLinus Torvalds 		goto out_freeiov;
22511da177e4SLinus Torvalds 	len = err;
22521da177e4SLinus Torvalds 
22531da177e4SLinus Torvalds 	if (uaddr != NULL) {
225443db362dSMaciej Żenczykowski 		err = move_addr_to_user(&addr,
2255a2e27255SArnaldo Carvalho de Melo 					msg_sys->msg_namelen, uaddr,
225689bddce5SStephen Hemminger 					uaddr_len);
22571da177e4SLinus Torvalds 		if (err < 0)
22581da177e4SLinus Torvalds 			goto out_freeiov;
22591da177e4SLinus Torvalds 	}
2260a2e27255SArnaldo Carvalho de Melo 	err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
226137f7f421SDavid S. Miller 			 COMPAT_FLAGS(msg));
22621da177e4SLinus Torvalds 	if (err)
22631da177e4SLinus Torvalds 		goto out_freeiov;
22641da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags)
2265a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
22661da177e4SLinus Torvalds 				 &msg_compat->msg_controllen);
22671da177e4SLinus Torvalds 	else
2268a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
22691da177e4SLinus Torvalds 				 &msg->msg_controllen);
22701da177e4SLinus Torvalds 	if (err)
22711da177e4SLinus Torvalds 		goto out_freeiov;
22721da177e4SLinus Torvalds 	err = len;
22731da177e4SLinus Torvalds 
22741da177e4SLinus Torvalds out_freeiov:
22751da177e4SLinus Torvalds 	if (iov != iovstack)
2276a74e9106SEric Dumazet 		kfree(iov);
2277a2e27255SArnaldo Carvalho de Melo out:
2278a2e27255SArnaldo Carvalho de Melo 	return err;
2279a2e27255SArnaldo Carvalho de Melo }
2280a2e27255SArnaldo Carvalho de Melo 
2281a2e27255SArnaldo Carvalho de Melo /*
2282a2e27255SArnaldo Carvalho de Melo  *	BSD recvmsg interface
2283a2e27255SArnaldo Carvalho de Melo  */
2284a2e27255SArnaldo Carvalho de Melo 
2285a7526eb5SAndy Lutomirski long __sys_recvmsg(int fd, struct msghdr __user *msg, unsigned flags)
2286a2e27255SArnaldo Carvalho de Melo {
2287a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err;
2288a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
22891be374a0SAndy Lutomirski 	struct socket *sock;
2290a2e27255SArnaldo Carvalho de Melo 
22911be374a0SAndy Lutomirski 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2292a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2293a2e27255SArnaldo Carvalho de Melo 		goto out;
2294a2e27255SArnaldo Carvalho de Melo 
2295a7526eb5SAndy Lutomirski 	err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0);
2296a2e27255SArnaldo Carvalho de Melo 
22976cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
22981da177e4SLinus Torvalds out:
22991da177e4SLinus Torvalds 	return err;
23001da177e4SLinus Torvalds }
23011da177e4SLinus Torvalds 
2302a7526eb5SAndy Lutomirski SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg,
2303a7526eb5SAndy Lutomirski 		unsigned int, flags)
2304a7526eb5SAndy Lutomirski {
2305a7526eb5SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
2306a7526eb5SAndy Lutomirski 		return -EINVAL;
2307a7526eb5SAndy Lutomirski 	return __sys_recvmsg(fd, msg, flags);
2308a7526eb5SAndy Lutomirski }
2309a7526eb5SAndy Lutomirski 
2310a2e27255SArnaldo Carvalho de Melo /*
2311a2e27255SArnaldo Carvalho de Melo  *     Linux recvmmsg interface
2312a2e27255SArnaldo Carvalho de Melo  */
23131da177e4SLinus Torvalds 
2314a2e27255SArnaldo Carvalho de Melo int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2315a2e27255SArnaldo Carvalho de Melo 		   unsigned int flags, struct timespec *timeout)
2316a2e27255SArnaldo Carvalho de Melo {
2317a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err, datagrams;
2318a2e27255SArnaldo Carvalho de Melo 	struct socket *sock;
2319a2e27255SArnaldo Carvalho de Melo 	struct mmsghdr __user *entry;
2320d7256d0eSJean-Mickael Guerin 	struct compat_mmsghdr __user *compat_entry;
2321a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
2322a2e27255SArnaldo Carvalho de Melo 	struct timespec end_time;
2323a2e27255SArnaldo Carvalho de Melo 
2324a2e27255SArnaldo Carvalho de Melo 	if (timeout &&
2325a2e27255SArnaldo Carvalho de Melo 	    poll_select_set_timeout(&end_time, timeout->tv_sec,
2326a2e27255SArnaldo Carvalho de Melo 				    timeout->tv_nsec))
2327a2e27255SArnaldo Carvalho de Melo 		return -EINVAL;
2328a2e27255SArnaldo Carvalho de Melo 
2329a2e27255SArnaldo Carvalho de Melo 	datagrams = 0;
2330a2e27255SArnaldo Carvalho de Melo 
2331a2e27255SArnaldo Carvalho de Melo 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2332a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2333a2e27255SArnaldo Carvalho de Melo 		return err;
2334a2e27255SArnaldo Carvalho de Melo 
2335a2e27255SArnaldo Carvalho de Melo 	err = sock_error(sock->sk);
2336a2e27255SArnaldo Carvalho de Melo 	if (err)
2337a2e27255SArnaldo Carvalho de Melo 		goto out_put;
2338a2e27255SArnaldo Carvalho de Melo 
2339a2e27255SArnaldo Carvalho de Melo 	entry = mmsg;
2340d7256d0eSJean-Mickael Guerin 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2341a2e27255SArnaldo Carvalho de Melo 
2342a2e27255SArnaldo Carvalho de Melo 	while (datagrams < vlen) {
2343a2e27255SArnaldo Carvalho de Melo 		/*
2344a2e27255SArnaldo Carvalho de Melo 		 * No need to ask LSM for more than the first datagram.
2345a2e27255SArnaldo Carvalho de Melo 		 */
2346d7256d0eSJean-Mickael Guerin 		if (MSG_CMSG_COMPAT & flags) {
2347a7526eb5SAndy Lutomirski 			err = ___sys_recvmsg(sock, (struct msghdr __user *)compat_entry,
2348b9eb8b87SAnton Blanchard 					     &msg_sys, flags & ~MSG_WAITFORONE,
2349b9eb8b87SAnton Blanchard 					     datagrams);
2350d7256d0eSJean-Mickael Guerin 			if (err < 0)
2351d7256d0eSJean-Mickael Guerin 				break;
2352d7256d0eSJean-Mickael Guerin 			err = __put_user(err, &compat_entry->msg_len);
2353d7256d0eSJean-Mickael Guerin 			++compat_entry;
2354d7256d0eSJean-Mickael Guerin 		} else {
2355a7526eb5SAndy Lutomirski 			err = ___sys_recvmsg(sock,
2356a7526eb5SAndy Lutomirski 					     (struct msghdr __user *)entry,
2357b9eb8b87SAnton Blanchard 					     &msg_sys, flags & ~MSG_WAITFORONE,
2358b9eb8b87SAnton Blanchard 					     datagrams);
2359a2e27255SArnaldo Carvalho de Melo 			if (err < 0)
2360a2e27255SArnaldo Carvalho de Melo 				break;
2361a2e27255SArnaldo Carvalho de Melo 			err = put_user(err, &entry->msg_len);
2362d7256d0eSJean-Mickael Guerin 			++entry;
2363d7256d0eSJean-Mickael Guerin 		}
2364d7256d0eSJean-Mickael Guerin 
2365a2e27255SArnaldo Carvalho de Melo 		if (err)
2366a2e27255SArnaldo Carvalho de Melo 			break;
2367a2e27255SArnaldo Carvalho de Melo 		++datagrams;
2368a2e27255SArnaldo Carvalho de Melo 
236971c5c159SBrandon L Black 		/* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
237071c5c159SBrandon L Black 		if (flags & MSG_WAITFORONE)
237171c5c159SBrandon L Black 			flags |= MSG_DONTWAIT;
237271c5c159SBrandon L Black 
2373a2e27255SArnaldo Carvalho de Melo 		if (timeout) {
2374a2e27255SArnaldo Carvalho de Melo 			ktime_get_ts(timeout);
2375a2e27255SArnaldo Carvalho de Melo 			*timeout = timespec_sub(end_time, *timeout);
2376a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_sec < 0) {
2377a2e27255SArnaldo Carvalho de Melo 				timeout->tv_sec = timeout->tv_nsec = 0;
2378a2e27255SArnaldo Carvalho de Melo 				break;
2379a2e27255SArnaldo Carvalho de Melo 			}
2380a2e27255SArnaldo Carvalho de Melo 
2381a2e27255SArnaldo Carvalho de Melo 			/* Timeout, return less than vlen datagrams */
2382a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_nsec == 0 && timeout->tv_sec == 0)
2383a2e27255SArnaldo Carvalho de Melo 				break;
2384a2e27255SArnaldo Carvalho de Melo 		}
2385a2e27255SArnaldo Carvalho de Melo 
2386a2e27255SArnaldo Carvalho de Melo 		/* Out of band data, return right away */
2387a2e27255SArnaldo Carvalho de Melo 		if (msg_sys.msg_flags & MSG_OOB)
2388a2e27255SArnaldo Carvalho de Melo 			break;
2389a2e27255SArnaldo Carvalho de Melo 	}
2390a2e27255SArnaldo Carvalho de Melo 
2391a2e27255SArnaldo Carvalho de Melo out_put:
2392a2e27255SArnaldo Carvalho de Melo 	fput_light(sock->file, fput_needed);
2393a2e27255SArnaldo Carvalho de Melo 
2394a2e27255SArnaldo Carvalho de Melo 	if (err == 0)
2395a2e27255SArnaldo Carvalho de Melo 		return datagrams;
2396a2e27255SArnaldo Carvalho de Melo 
2397a2e27255SArnaldo Carvalho de Melo 	if (datagrams != 0) {
2398a2e27255SArnaldo Carvalho de Melo 		/*
2399a2e27255SArnaldo Carvalho de Melo 		 * We may return less entries than requested (vlen) if the
2400a2e27255SArnaldo Carvalho de Melo 		 * sock is non block and there aren't enough datagrams...
2401a2e27255SArnaldo Carvalho de Melo 		 */
2402a2e27255SArnaldo Carvalho de Melo 		if (err != -EAGAIN) {
2403a2e27255SArnaldo Carvalho de Melo 			/*
2404a2e27255SArnaldo Carvalho de Melo 			 * ... or  if recvmsg returns an error after we
2405a2e27255SArnaldo Carvalho de Melo 			 * received some datagrams, where we record the
2406a2e27255SArnaldo Carvalho de Melo 			 * error to return on the next call or if the
2407a2e27255SArnaldo Carvalho de Melo 			 * app asks about it using getsockopt(SO_ERROR).
2408a2e27255SArnaldo Carvalho de Melo 			 */
2409a2e27255SArnaldo Carvalho de Melo 			sock->sk->sk_err = -err;
2410a2e27255SArnaldo Carvalho de Melo 		}
2411a2e27255SArnaldo Carvalho de Melo 
2412a2e27255SArnaldo Carvalho de Melo 		return datagrams;
2413a2e27255SArnaldo Carvalho de Melo 	}
2414a2e27255SArnaldo Carvalho de Melo 
2415a2e27255SArnaldo Carvalho de Melo 	return err;
2416a2e27255SArnaldo Carvalho de Melo }
2417a2e27255SArnaldo Carvalho de Melo 
2418a2e27255SArnaldo Carvalho de Melo SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
2419a2e27255SArnaldo Carvalho de Melo 		unsigned int, vlen, unsigned int, flags,
2420a2e27255SArnaldo Carvalho de Melo 		struct timespec __user *, timeout)
2421a2e27255SArnaldo Carvalho de Melo {
2422a2e27255SArnaldo Carvalho de Melo 	int datagrams;
2423a2e27255SArnaldo Carvalho de Melo 	struct timespec timeout_sys;
2424a2e27255SArnaldo Carvalho de Melo 
24251be374a0SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
24261be374a0SAndy Lutomirski 		return -EINVAL;
24271be374a0SAndy Lutomirski 
2428a2e27255SArnaldo Carvalho de Melo 	if (!timeout)
2429a2e27255SArnaldo Carvalho de Melo 		return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL);
2430a2e27255SArnaldo Carvalho de Melo 
2431a2e27255SArnaldo Carvalho de Melo 	if (copy_from_user(&timeout_sys, timeout, sizeof(timeout_sys)))
2432a2e27255SArnaldo Carvalho de Melo 		return -EFAULT;
2433a2e27255SArnaldo Carvalho de Melo 
2434a2e27255SArnaldo Carvalho de Melo 	datagrams = __sys_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys);
2435a2e27255SArnaldo Carvalho de Melo 
2436a2e27255SArnaldo Carvalho de Melo 	if (datagrams > 0 &&
2437a2e27255SArnaldo Carvalho de Melo 	    copy_to_user(timeout, &timeout_sys, sizeof(timeout_sys)))
2438a2e27255SArnaldo Carvalho de Melo 		datagrams = -EFAULT;
2439a2e27255SArnaldo Carvalho de Melo 
2440a2e27255SArnaldo Carvalho de Melo 	return datagrams;
2441a2e27255SArnaldo Carvalho de Melo }
2442a2e27255SArnaldo Carvalho de Melo 
2443a2e27255SArnaldo Carvalho de Melo #ifdef __ARCH_WANT_SYS_SOCKETCALL
24441da177e4SLinus Torvalds /* Argument list sizes for sys_socketcall */
24451da177e4SLinus Torvalds #define AL(x) ((x) * sizeof(unsigned long))
2446228e548eSAnton Blanchard static const unsigned char nargs[21] = {
244789bddce5SStephen Hemminger 	AL(0), AL(3), AL(3), AL(3), AL(2), AL(3),
24481da177e4SLinus Torvalds 	AL(3), AL(3), AL(4), AL(4), AL(4), AL(6),
2449aaca0bdcSUlrich Drepper 	AL(6), AL(2), AL(5), AL(5), AL(3), AL(3),
2450228e548eSAnton Blanchard 	AL(4), AL(5), AL(4)
245189bddce5SStephen Hemminger };
245289bddce5SStephen Hemminger 
24531da177e4SLinus Torvalds #undef AL
24541da177e4SLinus Torvalds 
24551da177e4SLinus Torvalds /*
24561da177e4SLinus Torvalds  *	System call vectors.
24571da177e4SLinus Torvalds  *
24581da177e4SLinus Torvalds  *	Argument checking cleaned up. Saved 20% in size.
24591da177e4SLinus Torvalds  *  This function doesn't need to set the kernel lock because
24601da177e4SLinus Torvalds  *  it is set by the callees.
24611da177e4SLinus Torvalds  */
24621da177e4SLinus Torvalds 
24633e0fa65fSHeiko Carstens SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
24641da177e4SLinus Torvalds {
24652950fa9dSChen Gang 	unsigned long a[AUDITSC_ARGS];
24661da177e4SLinus Torvalds 	unsigned long a0, a1;
24671da177e4SLinus Torvalds 	int err;
246847379052SArjan van de Ven 	unsigned int len;
24691da177e4SLinus Torvalds 
2470228e548eSAnton Blanchard 	if (call < 1 || call > SYS_SENDMMSG)
24711da177e4SLinus Torvalds 		return -EINVAL;
24721da177e4SLinus Torvalds 
247347379052SArjan van de Ven 	len = nargs[call];
247447379052SArjan van de Ven 	if (len > sizeof(a))
247547379052SArjan van de Ven 		return -EINVAL;
247647379052SArjan van de Ven 
24771da177e4SLinus Torvalds 	/* copy_from_user should be SMP safe. */
247847379052SArjan van de Ven 	if (copy_from_user(a, args, len))
24791da177e4SLinus Torvalds 		return -EFAULT;
24801da177e4SLinus Torvalds 
24812950fa9dSChen Gang 	err = audit_socketcall(nargs[call] / sizeof(unsigned long), a);
24822950fa9dSChen Gang 	if (err)
24832950fa9dSChen Gang 		return err;
24843ec3b2fbSDavid Woodhouse 
24851da177e4SLinus Torvalds 	a0 = a[0];
24861da177e4SLinus Torvalds 	a1 = a[1];
24871da177e4SLinus Torvalds 
248889bddce5SStephen Hemminger 	switch (call) {
24891da177e4SLinus Torvalds 	case SYS_SOCKET:
24901da177e4SLinus Torvalds 		err = sys_socket(a0, a1, a[2]);
24911da177e4SLinus Torvalds 		break;
24921da177e4SLinus Torvalds 	case SYS_BIND:
24931da177e4SLinus Torvalds 		err = sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
24941da177e4SLinus Torvalds 		break;
24951da177e4SLinus Torvalds 	case SYS_CONNECT:
24961da177e4SLinus Torvalds 		err = sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
24971da177e4SLinus Torvalds 		break;
24981da177e4SLinus Torvalds 	case SYS_LISTEN:
24991da177e4SLinus Torvalds 		err = sys_listen(a0, a1);
25001da177e4SLinus Torvalds 		break;
25011da177e4SLinus Torvalds 	case SYS_ACCEPT:
2502de11defeSUlrich Drepper 		err = sys_accept4(a0, (struct sockaddr __user *)a1,
2503aaca0bdcSUlrich Drepper 				  (int __user *)a[2], 0);
25041da177e4SLinus Torvalds 		break;
25051da177e4SLinus Torvalds 	case SYS_GETSOCKNAME:
250689bddce5SStephen Hemminger 		err =
250789bddce5SStephen Hemminger 		    sys_getsockname(a0, (struct sockaddr __user *)a1,
250889bddce5SStephen Hemminger 				    (int __user *)a[2]);
25091da177e4SLinus Torvalds 		break;
25101da177e4SLinus Torvalds 	case SYS_GETPEERNAME:
251189bddce5SStephen Hemminger 		err =
251289bddce5SStephen Hemminger 		    sys_getpeername(a0, (struct sockaddr __user *)a1,
251389bddce5SStephen Hemminger 				    (int __user *)a[2]);
25141da177e4SLinus Torvalds 		break;
25151da177e4SLinus Torvalds 	case SYS_SOCKETPAIR:
25161da177e4SLinus Torvalds 		err = sys_socketpair(a0, a1, a[2], (int __user *)a[3]);
25171da177e4SLinus Torvalds 		break;
25181da177e4SLinus Torvalds 	case SYS_SEND:
25191da177e4SLinus Torvalds 		err = sys_send(a0, (void __user *)a1, a[2], a[3]);
25201da177e4SLinus Torvalds 		break;
25211da177e4SLinus Torvalds 	case SYS_SENDTO:
25221da177e4SLinus Torvalds 		err = sys_sendto(a0, (void __user *)a1, a[2], a[3],
25231da177e4SLinus Torvalds 				 (struct sockaddr __user *)a[4], a[5]);
25241da177e4SLinus Torvalds 		break;
25251da177e4SLinus Torvalds 	case SYS_RECV:
25261da177e4SLinus Torvalds 		err = sys_recv(a0, (void __user *)a1, a[2], a[3]);
25271da177e4SLinus Torvalds 		break;
25281da177e4SLinus Torvalds 	case SYS_RECVFROM:
25291da177e4SLinus Torvalds 		err = sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
253089bddce5SStephen Hemminger 				   (struct sockaddr __user *)a[4],
253189bddce5SStephen Hemminger 				   (int __user *)a[5]);
25321da177e4SLinus Torvalds 		break;
25331da177e4SLinus Torvalds 	case SYS_SHUTDOWN:
25341da177e4SLinus Torvalds 		err = sys_shutdown(a0, a1);
25351da177e4SLinus Torvalds 		break;
25361da177e4SLinus Torvalds 	case SYS_SETSOCKOPT:
25371da177e4SLinus Torvalds 		err = sys_setsockopt(a0, a1, a[2], (char __user *)a[3], a[4]);
25381da177e4SLinus Torvalds 		break;
25391da177e4SLinus Torvalds 	case SYS_GETSOCKOPT:
254089bddce5SStephen Hemminger 		err =
254189bddce5SStephen Hemminger 		    sys_getsockopt(a0, a1, a[2], (char __user *)a[3],
254289bddce5SStephen Hemminger 				   (int __user *)a[4]);
25431da177e4SLinus Torvalds 		break;
25441da177e4SLinus Torvalds 	case SYS_SENDMSG:
25451da177e4SLinus Torvalds 		err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]);
25461da177e4SLinus Torvalds 		break;
2547228e548eSAnton Blanchard 	case SYS_SENDMMSG:
2548228e548eSAnton Blanchard 		err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]);
2549228e548eSAnton Blanchard 		break;
25501da177e4SLinus Torvalds 	case SYS_RECVMSG:
25511da177e4SLinus Torvalds 		err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]);
25521da177e4SLinus Torvalds 		break;
2553a2e27255SArnaldo Carvalho de Melo 	case SYS_RECVMMSG:
2554a2e27255SArnaldo Carvalho de Melo 		err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3],
2555a2e27255SArnaldo Carvalho de Melo 				   (struct timespec __user *)a[4]);
2556a2e27255SArnaldo Carvalho de Melo 		break;
2557de11defeSUlrich Drepper 	case SYS_ACCEPT4:
2558de11defeSUlrich Drepper 		err = sys_accept4(a0, (struct sockaddr __user *)a1,
2559de11defeSUlrich Drepper 				  (int __user *)a[2], a[3]);
2560aaca0bdcSUlrich Drepper 		break;
25611da177e4SLinus Torvalds 	default:
25621da177e4SLinus Torvalds 		err = -EINVAL;
25631da177e4SLinus Torvalds 		break;
25641da177e4SLinus Torvalds 	}
25651da177e4SLinus Torvalds 	return err;
25661da177e4SLinus Torvalds }
25671da177e4SLinus Torvalds 
25681da177e4SLinus Torvalds #endif				/* __ARCH_WANT_SYS_SOCKETCALL */
25691da177e4SLinus Torvalds 
257055737fdaSStephen Hemminger /**
257155737fdaSStephen Hemminger  *	sock_register - add a socket protocol handler
257255737fdaSStephen Hemminger  *	@ops: description of protocol
257355737fdaSStephen Hemminger  *
25741da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
25751da177e4SLinus Torvalds  *	advertise its address family, and have it linked into the
257655737fdaSStephen Hemminger  *	socket interface. The value ops->family coresponds to the
257755737fdaSStephen Hemminger  *	socket system call protocol family.
25781da177e4SLinus Torvalds  */
2579f0fd27d4SStephen Hemminger int sock_register(const struct net_proto_family *ops)
25801da177e4SLinus Torvalds {
25811da177e4SLinus Torvalds 	int err;
25821da177e4SLinus Torvalds 
25831da177e4SLinus Torvalds 	if (ops->family >= NPROTO) {
258489bddce5SStephen Hemminger 		printk(KERN_CRIT "protocol %d >= NPROTO(%d)\n", ops->family,
258589bddce5SStephen Hemminger 		       NPROTO);
25861da177e4SLinus Torvalds 		return -ENOBUFS;
25871da177e4SLinus Torvalds 	}
258855737fdaSStephen Hemminger 
258955737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2590190683a9SEric Dumazet 	if (rcu_dereference_protected(net_families[ops->family],
2591190683a9SEric Dumazet 				      lockdep_is_held(&net_family_lock)))
25921da177e4SLinus Torvalds 		err = -EEXIST;
259355737fdaSStephen Hemminger 	else {
2594cf778b00SEric Dumazet 		rcu_assign_pointer(net_families[ops->family], ops);
25951da177e4SLinus Torvalds 		err = 0;
25961da177e4SLinus Torvalds 	}
259755737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
259855737fdaSStephen Hemminger 
259989bddce5SStephen Hemminger 	printk(KERN_INFO "NET: Registered protocol family %d\n", ops->family);
26001da177e4SLinus Torvalds 	return err;
26011da177e4SLinus Torvalds }
2602c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_register);
26031da177e4SLinus Torvalds 
260455737fdaSStephen Hemminger /**
260555737fdaSStephen Hemminger  *	sock_unregister - remove a protocol handler
260655737fdaSStephen Hemminger  *	@family: protocol family to remove
260755737fdaSStephen Hemminger  *
26081da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
26091da177e4SLinus Torvalds  *	remove its address family, and have it unlinked from the
261055737fdaSStephen Hemminger  *	new socket creation.
261155737fdaSStephen Hemminger  *
261255737fdaSStephen Hemminger  *	If protocol handler is a module, then it can use module reference
261355737fdaSStephen Hemminger  *	counts to protect against new references. If protocol handler is not
261455737fdaSStephen Hemminger  *	a module then it needs to provide its own protection in
261555737fdaSStephen Hemminger  *	the ops->create routine.
26161da177e4SLinus Torvalds  */
2617f0fd27d4SStephen Hemminger void sock_unregister(int family)
26181da177e4SLinus Torvalds {
2619f0fd27d4SStephen Hemminger 	BUG_ON(family < 0 || family >= NPROTO);
26201da177e4SLinus Torvalds 
262155737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2622a9b3cd7fSStephen Hemminger 	RCU_INIT_POINTER(net_families[family], NULL);
262355737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
262455737fdaSStephen Hemminger 
262555737fdaSStephen Hemminger 	synchronize_rcu();
262655737fdaSStephen Hemminger 
262789bddce5SStephen Hemminger 	printk(KERN_INFO "NET: Unregistered protocol family %d\n", family);
26281da177e4SLinus Torvalds }
2629c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_unregister);
26301da177e4SLinus Torvalds 
263177d76ea3SAndi Kleen static int __init sock_init(void)
26321da177e4SLinus Torvalds {
2633b3e19d92SNick Piggin 	int err;
26342ca794e5SEric W. Biederman 	/*
26352ca794e5SEric W. Biederman 	 *      Initialize the network sysctl infrastructure.
26362ca794e5SEric W. Biederman 	 */
26372ca794e5SEric W. Biederman 	err = net_sysctl_init();
26382ca794e5SEric W. Biederman 	if (err)
26392ca794e5SEric W. Biederman 		goto out;
2640b3e19d92SNick Piggin 
26411da177e4SLinus Torvalds 	/*
26421da177e4SLinus Torvalds 	 *      Initialize skbuff SLAB cache
26431da177e4SLinus Torvalds 	 */
26441da177e4SLinus Torvalds 	skb_init();
26451da177e4SLinus Torvalds 
26461da177e4SLinus Torvalds 	/*
26471da177e4SLinus Torvalds 	 *      Initialize the protocols module.
26481da177e4SLinus Torvalds 	 */
26491da177e4SLinus Torvalds 
26501da177e4SLinus Torvalds 	init_inodecache();
2651b3e19d92SNick Piggin 
2652b3e19d92SNick Piggin 	err = register_filesystem(&sock_fs_type);
2653b3e19d92SNick Piggin 	if (err)
2654b3e19d92SNick Piggin 		goto out_fs;
26551da177e4SLinus Torvalds 	sock_mnt = kern_mount(&sock_fs_type);
2656b3e19d92SNick Piggin 	if (IS_ERR(sock_mnt)) {
2657b3e19d92SNick Piggin 		err = PTR_ERR(sock_mnt);
2658b3e19d92SNick Piggin 		goto out_mount;
2659b3e19d92SNick Piggin 	}
266077d76ea3SAndi Kleen 
266177d76ea3SAndi Kleen 	/* The real protocol initialization is performed in later initcalls.
26621da177e4SLinus Torvalds 	 */
26631da177e4SLinus Torvalds 
26641da177e4SLinus Torvalds #ifdef CONFIG_NETFILTER
26656d11cfdbSPablo Neira Ayuso 	err = netfilter_init();
26666d11cfdbSPablo Neira Ayuso 	if (err)
26676d11cfdbSPablo Neira Ayuso 		goto out;
26681da177e4SLinus Torvalds #endif
2669cbeb321aSDavid S. Miller 
2670c1f19b51SRichard Cochran #ifdef CONFIG_NETWORK_PHY_TIMESTAMPING
2671c1f19b51SRichard Cochran 	skb_timestamping_init();
2672c1f19b51SRichard Cochran #endif
2673c1f19b51SRichard Cochran 
2674b3e19d92SNick Piggin out:
2675b3e19d92SNick Piggin 	return err;
2676b3e19d92SNick Piggin 
2677b3e19d92SNick Piggin out_mount:
2678b3e19d92SNick Piggin 	unregister_filesystem(&sock_fs_type);
2679b3e19d92SNick Piggin out_fs:
2680b3e19d92SNick Piggin 	goto out;
26811da177e4SLinus Torvalds }
26821da177e4SLinus Torvalds 
268377d76ea3SAndi Kleen core_initcall(sock_init);	/* early initcall */
268477d76ea3SAndi Kleen 
26851da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS
26861da177e4SLinus Torvalds void socket_seq_show(struct seq_file *seq)
26871da177e4SLinus Torvalds {
26881da177e4SLinus Torvalds 	int cpu;
26891da177e4SLinus Torvalds 	int counter = 0;
26901da177e4SLinus Torvalds 
26916f912042SKAMEZAWA Hiroyuki 	for_each_possible_cpu(cpu)
26921da177e4SLinus Torvalds 	    counter += per_cpu(sockets_in_use, cpu);
26931da177e4SLinus Torvalds 
26941da177e4SLinus Torvalds 	/* It can be negative, by the way. 8) */
26951da177e4SLinus Torvalds 	if (counter < 0)
26961da177e4SLinus Torvalds 		counter = 0;
26971da177e4SLinus Torvalds 
26981da177e4SLinus Torvalds 	seq_printf(seq, "sockets: used %d\n", counter);
26991da177e4SLinus Torvalds }
27001da177e4SLinus Torvalds #endif				/* CONFIG_PROC_FS */
27011da177e4SLinus Torvalds 
270289bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
27036b96018bSArnd Bergmann static int do_siocgstamp(struct net *net, struct socket *sock,
2704644595f8SH. Peter Anvin 			 unsigned int cmd, void __user *up)
27057a229387SArnd Bergmann {
27067a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
27077a229387SArnd Bergmann 	struct timeval ktv;
27087a229387SArnd Bergmann 	int err;
27097a229387SArnd Bergmann 
27107a229387SArnd Bergmann 	set_fs(KERNEL_DS);
27116b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv);
27127a229387SArnd Bergmann 	set_fs(old_fs);
2713644595f8SH. Peter Anvin 	if (!err)
2714ed6fe9d6SMikulas Patocka 		err = compat_put_timeval(&ktv, up);
2715644595f8SH. Peter Anvin 
27167a229387SArnd Bergmann 	return err;
27177a229387SArnd Bergmann }
27187a229387SArnd Bergmann 
27196b96018bSArnd Bergmann static int do_siocgstampns(struct net *net, struct socket *sock,
2720644595f8SH. Peter Anvin 			   unsigned int cmd, void __user *up)
27217a229387SArnd Bergmann {
27227a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
27237a229387SArnd Bergmann 	struct timespec kts;
27247a229387SArnd Bergmann 	int err;
27257a229387SArnd Bergmann 
27267a229387SArnd Bergmann 	set_fs(KERNEL_DS);
27276b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts);
27287a229387SArnd Bergmann 	set_fs(old_fs);
2729644595f8SH. Peter Anvin 	if (!err)
2730ed6fe9d6SMikulas Patocka 		err = compat_put_timespec(&kts, up);
2731644595f8SH. Peter Anvin 
27327a229387SArnd Bergmann 	return err;
27337a229387SArnd Bergmann }
27347a229387SArnd Bergmann 
27356b96018bSArnd Bergmann static int dev_ifname32(struct net *net, struct compat_ifreq __user *uifr32)
27367a229387SArnd Bergmann {
27377a229387SArnd Bergmann 	struct ifreq __user *uifr;
27387a229387SArnd Bergmann 	int err;
27397a229387SArnd Bergmann 
27407a229387SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(struct ifreq));
27416b96018bSArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
27427a229387SArnd Bergmann 		return -EFAULT;
27437a229387SArnd Bergmann 
27446b96018bSArnd Bergmann 	err = dev_ioctl(net, SIOCGIFNAME, uifr);
27457a229387SArnd Bergmann 	if (err)
27467a229387SArnd Bergmann 		return err;
27477a229387SArnd Bergmann 
27486b96018bSArnd Bergmann 	if (copy_in_user(uifr32, uifr, sizeof(struct compat_ifreq)))
27497a229387SArnd Bergmann 		return -EFAULT;
27507a229387SArnd Bergmann 
27517a229387SArnd Bergmann 	return 0;
27527a229387SArnd Bergmann }
27537a229387SArnd Bergmann 
27546b96018bSArnd Bergmann static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32)
27557a229387SArnd Bergmann {
27566b96018bSArnd Bergmann 	struct compat_ifconf ifc32;
27577a229387SArnd Bergmann 	struct ifconf ifc;
27587a229387SArnd Bergmann 	struct ifconf __user *uifc;
27596b96018bSArnd Bergmann 	struct compat_ifreq __user *ifr32;
27607a229387SArnd Bergmann 	struct ifreq __user *ifr;
27617a229387SArnd Bergmann 	unsigned int i, j;
27627a229387SArnd Bergmann 	int err;
27637a229387SArnd Bergmann 
27646b96018bSArnd Bergmann 	if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf)))
27657a229387SArnd Bergmann 		return -EFAULT;
27667a229387SArnd Bergmann 
276743da5f2eSMathias Krause 	memset(&ifc, 0, sizeof(ifc));
27687a229387SArnd Bergmann 	if (ifc32.ifcbuf == 0) {
27697a229387SArnd Bergmann 		ifc32.ifc_len = 0;
27707a229387SArnd Bergmann 		ifc.ifc_len = 0;
27717a229387SArnd Bergmann 		ifc.ifc_req = NULL;
27727a229387SArnd Bergmann 		uifc = compat_alloc_user_space(sizeof(struct ifconf));
27737a229387SArnd Bergmann 	} else {
27746b96018bSArnd Bergmann 		size_t len = ((ifc32.ifc_len / sizeof(struct compat_ifreq)) + 1) *
27757a229387SArnd Bergmann 			sizeof(struct ifreq);
27767a229387SArnd Bergmann 		uifc = compat_alloc_user_space(sizeof(struct ifconf) + len);
27777a229387SArnd Bergmann 		ifc.ifc_len = len;
27787a229387SArnd Bergmann 		ifr = ifc.ifc_req = (void __user *)(uifc + 1);
27797a229387SArnd Bergmann 		ifr32 = compat_ptr(ifc32.ifcbuf);
27806b96018bSArnd Bergmann 		for (i = 0; i < ifc32.ifc_len; i += sizeof(struct compat_ifreq)) {
27816b96018bSArnd Bergmann 			if (copy_in_user(ifr, ifr32, sizeof(struct compat_ifreq)))
27827a229387SArnd Bergmann 				return -EFAULT;
27837a229387SArnd Bergmann 			ifr++;
27847a229387SArnd Bergmann 			ifr32++;
27857a229387SArnd Bergmann 		}
27867a229387SArnd Bergmann 	}
27877a229387SArnd Bergmann 	if (copy_to_user(uifc, &ifc, sizeof(struct ifconf)))
27887a229387SArnd Bergmann 		return -EFAULT;
27897a229387SArnd Bergmann 
27906b96018bSArnd Bergmann 	err = dev_ioctl(net, SIOCGIFCONF, uifc);
27917a229387SArnd Bergmann 	if (err)
27927a229387SArnd Bergmann 		return err;
27937a229387SArnd Bergmann 
27947a229387SArnd Bergmann 	if (copy_from_user(&ifc, uifc, sizeof(struct ifconf)))
27957a229387SArnd Bergmann 		return -EFAULT;
27967a229387SArnd Bergmann 
27977a229387SArnd Bergmann 	ifr = ifc.ifc_req;
27987a229387SArnd Bergmann 	ifr32 = compat_ptr(ifc32.ifcbuf);
27997a229387SArnd Bergmann 	for (i = 0, j = 0;
28006b96018bSArnd Bergmann 	     i + sizeof(struct compat_ifreq) <= ifc32.ifc_len && j < ifc.ifc_len;
28016b96018bSArnd Bergmann 	     i += sizeof(struct compat_ifreq), j += sizeof(struct ifreq)) {
28026b96018bSArnd Bergmann 		if (copy_in_user(ifr32, ifr, sizeof(struct compat_ifreq)))
28037a229387SArnd Bergmann 			return -EFAULT;
28047a229387SArnd Bergmann 		ifr32++;
28057a229387SArnd Bergmann 		ifr++;
28067a229387SArnd Bergmann 	}
28077a229387SArnd Bergmann 
28087a229387SArnd Bergmann 	if (ifc32.ifcbuf == 0) {
28097a229387SArnd Bergmann 		/* Translate from 64-bit structure multiple to
28107a229387SArnd Bergmann 		 * a 32-bit one.
28117a229387SArnd Bergmann 		 */
28127a229387SArnd Bergmann 		i = ifc.ifc_len;
28136b96018bSArnd Bergmann 		i = ((i / sizeof(struct ifreq)) * sizeof(struct compat_ifreq));
28147a229387SArnd Bergmann 		ifc32.ifc_len = i;
28157a229387SArnd Bergmann 	} else {
28167a229387SArnd Bergmann 		ifc32.ifc_len = i;
28177a229387SArnd Bergmann 	}
28186b96018bSArnd Bergmann 	if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf)))
28197a229387SArnd Bergmann 		return -EFAULT;
28207a229387SArnd Bergmann 
28217a229387SArnd Bergmann 	return 0;
28227a229387SArnd Bergmann }
28237a229387SArnd Bergmann 
28246b96018bSArnd Bergmann static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
28257a229387SArnd Bergmann {
28263a7da39dSBen Hutchings 	struct compat_ethtool_rxnfc __user *compat_rxnfc;
28273a7da39dSBen Hutchings 	bool convert_in = false, convert_out = false;
28283a7da39dSBen Hutchings 	size_t buf_size = ALIGN(sizeof(struct ifreq), 8);
28293a7da39dSBen Hutchings 	struct ethtool_rxnfc __user *rxnfc;
28307a229387SArnd Bergmann 	struct ifreq __user *ifr;
28313a7da39dSBen Hutchings 	u32 rule_cnt = 0, actual_rule_cnt;
28323a7da39dSBen Hutchings 	u32 ethcmd;
28337a229387SArnd Bergmann 	u32 data;
28343a7da39dSBen Hutchings 	int ret;
28357a229387SArnd Bergmann 
28367a229387SArnd Bergmann 	if (get_user(data, &ifr32->ifr_ifru.ifru_data))
28377a229387SArnd Bergmann 		return -EFAULT;
28387a229387SArnd Bergmann 
28393a7da39dSBen Hutchings 	compat_rxnfc = compat_ptr(data);
28403a7da39dSBen Hutchings 
28413a7da39dSBen Hutchings 	if (get_user(ethcmd, &compat_rxnfc->cmd))
28427a229387SArnd Bergmann 		return -EFAULT;
28437a229387SArnd Bergmann 
28443a7da39dSBen Hutchings 	/* Most ethtool structures are defined without padding.
28453a7da39dSBen Hutchings 	 * Unfortunately struct ethtool_rxnfc is an exception.
28463a7da39dSBen Hutchings 	 */
28473a7da39dSBen Hutchings 	switch (ethcmd) {
28483a7da39dSBen Hutchings 	default:
28493a7da39dSBen Hutchings 		break;
28503a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLALL:
28513a7da39dSBen Hutchings 		/* Buffer size is variable */
28523a7da39dSBen Hutchings 		if (get_user(rule_cnt, &compat_rxnfc->rule_cnt))
28533a7da39dSBen Hutchings 			return -EFAULT;
28543a7da39dSBen Hutchings 		if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32))
28553a7da39dSBen Hutchings 			return -ENOMEM;
28563a7da39dSBen Hutchings 		buf_size += rule_cnt * sizeof(u32);
28573a7da39dSBen Hutchings 		/* fall through */
28583a7da39dSBen Hutchings 	case ETHTOOL_GRXRINGS:
28593a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLCNT:
28603a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRULE:
286155664f32SBen Hutchings 	case ETHTOOL_SRXCLSRLINS:
28623a7da39dSBen Hutchings 		convert_out = true;
28633a7da39dSBen Hutchings 		/* fall through */
28643a7da39dSBen Hutchings 	case ETHTOOL_SRXCLSRLDEL:
28653a7da39dSBen Hutchings 		buf_size += sizeof(struct ethtool_rxnfc);
28663a7da39dSBen Hutchings 		convert_in = true;
28673a7da39dSBen Hutchings 		break;
28683a7da39dSBen Hutchings 	}
28693a7da39dSBen Hutchings 
28703a7da39dSBen Hutchings 	ifr = compat_alloc_user_space(buf_size);
2871954b1244SStephen Hemminger 	rxnfc = (void __user *)ifr + ALIGN(sizeof(struct ifreq), 8);
28723a7da39dSBen Hutchings 
28733a7da39dSBen Hutchings 	if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
28743a7da39dSBen Hutchings 		return -EFAULT;
28753a7da39dSBen Hutchings 
28763a7da39dSBen Hutchings 	if (put_user(convert_in ? rxnfc : compat_ptr(data),
28773a7da39dSBen Hutchings 		     &ifr->ifr_ifru.ifru_data))
28783a7da39dSBen Hutchings 		return -EFAULT;
28793a7da39dSBen Hutchings 
28803a7da39dSBen Hutchings 	if (convert_in) {
2881127fe533SAlexander Duyck 		/* We expect there to be holes between fs.m_ext and
28823a7da39dSBen Hutchings 		 * fs.ring_cookie and at the end of fs, but nowhere else.
28833a7da39dSBen Hutchings 		 */
2884127fe533SAlexander Duyck 		BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_ext) +
2885127fe533SAlexander Duyck 			     sizeof(compat_rxnfc->fs.m_ext) !=
2886127fe533SAlexander Duyck 			     offsetof(struct ethtool_rxnfc, fs.m_ext) +
2887127fe533SAlexander Duyck 			     sizeof(rxnfc->fs.m_ext));
28883a7da39dSBen Hutchings 		BUILD_BUG_ON(
28893a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.location) -
28903a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) !=
28913a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.location) -
28923a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.ring_cookie));
28933a7da39dSBen Hutchings 
28943a7da39dSBen Hutchings 		if (copy_in_user(rxnfc, compat_rxnfc,
2895954b1244SStephen Hemminger 				 (void __user *)(&rxnfc->fs.m_ext + 1) -
2896954b1244SStephen Hemminger 				 (void __user *)rxnfc) ||
28973a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->fs.ring_cookie,
28983a7da39dSBen Hutchings 				 &compat_rxnfc->fs.ring_cookie,
2899954b1244SStephen Hemminger 				 (void __user *)(&rxnfc->fs.location + 1) -
2900954b1244SStephen Hemminger 				 (void __user *)&rxnfc->fs.ring_cookie) ||
29013a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt,
29023a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
29033a7da39dSBen Hutchings 			return -EFAULT;
29043a7da39dSBen Hutchings 	}
29053a7da39dSBen Hutchings 
29063a7da39dSBen Hutchings 	ret = dev_ioctl(net, SIOCETHTOOL, ifr);
29073a7da39dSBen Hutchings 	if (ret)
29083a7da39dSBen Hutchings 		return ret;
29093a7da39dSBen Hutchings 
29103a7da39dSBen Hutchings 	if (convert_out) {
29113a7da39dSBen Hutchings 		if (copy_in_user(compat_rxnfc, rxnfc,
2912954b1244SStephen Hemminger 				 (const void __user *)(&rxnfc->fs.m_ext + 1) -
2913954b1244SStephen Hemminger 				 (const void __user *)rxnfc) ||
29143a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->fs.ring_cookie,
29153a7da39dSBen Hutchings 				 &rxnfc->fs.ring_cookie,
2916954b1244SStephen Hemminger 				 (const void __user *)(&rxnfc->fs.location + 1) -
2917954b1244SStephen Hemminger 				 (const void __user *)&rxnfc->fs.ring_cookie) ||
29183a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt,
29193a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
29203a7da39dSBen Hutchings 			return -EFAULT;
29213a7da39dSBen Hutchings 
29223a7da39dSBen Hutchings 		if (ethcmd == ETHTOOL_GRXCLSRLALL) {
29233a7da39dSBen Hutchings 			/* As an optimisation, we only copy the actual
29243a7da39dSBen Hutchings 			 * number of rules that the underlying
29253a7da39dSBen Hutchings 			 * function returned.  Since Mallory might
29263a7da39dSBen Hutchings 			 * change the rule count in user memory, we
29273a7da39dSBen Hutchings 			 * check that it is less than the rule count
29283a7da39dSBen Hutchings 			 * originally given (as the user buffer size),
29293a7da39dSBen Hutchings 			 * which has been range-checked.
29303a7da39dSBen Hutchings 			 */
29313a7da39dSBen Hutchings 			if (get_user(actual_rule_cnt, &rxnfc->rule_cnt))
29323a7da39dSBen Hutchings 				return -EFAULT;
29333a7da39dSBen Hutchings 			if (actual_rule_cnt < rule_cnt)
29343a7da39dSBen Hutchings 				rule_cnt = actual_rule_cnt;
29353a7da39dSBen Hutchings 			if (copy_in_user(&compat_rxnfc->rule_locs[0],
29363a7da39dSBen Hutchings 					 &rxnfc->rule_locs[0],
29373a7da39dSBen Hutchings 					 rule_cnt * sizeof(u32)))
29383a7da39dSBen Hutchings 				return -EFAULT;
29393a7da39dSBen Hutchings 		}
29403a7da39dSBen Hutchings 	}
29413a7da39dSBen Hutchings 
29423a7da39dSBen Hutchings 	return 0;
29437a229387SArnd Bergmann }
29447a229387SArnd Bergmann 
29457a50a240SArnd Bergmann static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32)
29467a50a240SArnd Bergmann {
29477a50a240SArnd Bergmann 	void __user *uptr;
29487a50a240SArnd Bergmann 	compat_uptr_t uptr32;
29497a50a240SArnd Bergmann 	struct ifreq __user *uifr;
29507a50a240SArnd Bergmann 
29517a50a240SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
29527a50a240SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
29537a50a240SArnd Bergmann 		return -EFAULT;
29547a50a240SArnd Bergmann 
29557a50a240SArnd Bergmann 	if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu))
29567a50a240SArnd Bergmann 		return -EFAULT;
29577a50a240SArnd Bergmann 
29587a50a240SArnd Bergmann 	uptr = compat_ptr(uptr32);
29597a50a240SArnd Bergmann 
29607a50a240SArnd Bergmann 	if (put_user(uptr, &uifr->ifr_settings.ifs_ifsu.raw_hdlc))
29617a50a240SArnd Bergmann 		return -EFAULT;
29627a50a240SArnd Bergmann 
29637a50a240SArnd Bergmann 	return dev_ioctl(net, SIOCWANDEV, uifr);
29647a50a240SArnd Bergmann }
29657a50a240SArnd Bergmann 
29666b96018bSArnd Bergmann static int bond_ioctl(struct net *net, unsigned int cmd,
29676b96018bSArnd Bergmann 			 struct compat_ifreq __user *ifr32)
29687a229387SArnd Bergmann {
29697a229387SArnd Bergmann 	struct ifreq kifr;
29707a229387SArnd Bergmann 	struct ifreq __user *uifr;
29717a229387SArnd Bergmann 	mm_segment_t old_fs;
29727a229387SArnd Bergmann 	int err;
29737a229387SArnd Bergmann 	u32 data;
29747a229387SArnd Bergmann 	void __user *datap;
29757a229387SArnd Bergmann 
29767a229387SArnd Bergmann 	switch (cmd) {
29777a229387SArnd Bergmann 	case SIOCBONDENSLAVE:
29787a229387SArnd Bergmann 	case SIOCBONDRELEASE:
29797a229387SArnd Bergmann 	case SIOCBONDSETHWADDR:
29807a229387SArnd Bergmann 	case SIOCBONDCHANGEACTIVE:
29816b96018bSArnd Bergmann 		if (copy_from_user(&kifr, ifr32, sizeof(struct compat_ifreq)))
29827a229387SArnd Bergmann 			return -EFAULT;
29837a229387SArnd Bergmann 
29847a229387SArnd Bergmann 		old_fs = get_fs();
29857a229387SArnd Bergmann 		set_fs(KERNEL_DS);
2986c3f52ae6Sstephen hemminger 		err = dev_ioctl(net, cmd,
2987c3f52ae6Sstephen hemminger 				(struct ifreq __user __force *) &kifr);
29887a229387SArnd Bergmann 		set_fs(old_fs);
29897a229387SArnd Bergmann 
29907a229387SArnd Bergmann 		return err;
29917a229387SArnd Bergmann 	case SIOCBONDSLAVEINFOQUERY:
29927a229387SArnd Bergmann 	case SIOCBONDINFOQUERY:
29937a229387SArnd Bergmann 		uifr = compat_alloc_user_space(sizeof(*uifr));
29947a229387SArnd Bergmann 		if (copy_in_user(&uifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
29957a229387SArnd Bergmann 			return -EFAULT;
29967a229387SArnd Bergmann 
29977a229387SArnd Bergmann 		if (get_user(data, &ifr32->ifr_ifru.ifru_data))
29987a229387SArnd Bergmann 			return -EFAULT;
29997a229387SArnd Bergmann 
30007a229387SArnd Bergmann 		datap = compat_ptr(data);
30017a229387SArnd Bergmann 		if (put_user(datap, &uifr->ifr_ifru.ifru_data))
30027a229387SArnd Bergmann 			return -EFAULT;
30037a229387SArnd Bergmann 
30046b96018bSArnd Bergmann 		return dev_ioctl(net, cmd, uifr);
30057a229387SArnd Bergmann 	default:
300607d106d0SLinus Torvalds 		return -ENOIOCTLCMD;
3007ccbd6a5aSJoe Perches 	}
30087a229387SArnd Bergmann }
30097a229387SArnd Bergmann 
30106b96018bSArnd Bergmann static int siocdevprivate_ioctl(struct net *net, unsigned int cmd,
30116b96018bSArnd Bergmann 				 struct compat_ifreq __user *u_ifreq32)
30127a229387SArnd Bergmann {
30137a229387SArnd Bergmann 	struct ifreq __user *u_ifreq64;
30147a229387SArnd Bergmann 	char tmp_buf[IFNAMSIZ];
30157a229387SArnd Bergmann 	void __user *data64;
30167a229387SArnd Bergmann 	u32 data32;
30177a229387SArnd Bergmann 
30187a229387SArnd Bergmann 	if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]),
30197a229387SArnd Bergmann 			   IFNAMSIZ))
30207a229387SArnd Bergmann 		return -EFAULT;
30217a229387SArnd Bergmann 	if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data))
30227a229387SArnd Bergmann 		return -EFAULT;
30237a229387SArnd Bergmann 	data64 = compat_ptr(data32);
30247a229387SArnd Bergmann 
30257a229387SArnd Bergmann 	u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
30267a229387SArnd Bergmann 
30277a229387SArnd Bergmann 	/* Don't check these user accesses, just let that get trapped
30287a229387SArnd Bergmann 	 * in the ioctl handler instead.
30297a229387SArnd Bergmann 	 */
30307a229387SArnd Bergmann 	if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0],
30317a229387SArnd Bergmann 			 IFNAMSIZ))
30327a229387SArnd Bergmann 		return -EFAULT;
30337a229387SArnd Bergmann 	if (__put_user(data64, &u_ifreq64->ifr_ifru.ifru_data))
30347a229387SArnd Bergmann 		return -EFAULT;
30357a229387SArnd Bergmann 
30366b96018bSArnd Bergmann 	return dev_ioctl(net, cmd, u_ifreq64);
30377a229387SArnd Bergmann }
30387a229387SArnd Bergmann 
30396b96018bSArnd Bergmann static int dev_ifsioc(struct net *net, struct socket *sock,
30406b96018bSArnd Bergmann 			 unsigned int cmd, struct compat_ifreq __user *uifr32)
30417a229387SArnd Bergmann {
3042a2116ed2SArnd Bergmann 	struct ifreq __user *uifr;
30437a229387SArnd Bergmann 	int err;
30447a229387SArnd Bergmann 
3045a2116ed2SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
3046a2116ed2SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(*uifr32)))
30477a229387SArnd Bergmann 		return -EFAULT;
3048a2116ed2SArnd Bergmann 
3049a2116ed2SArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr);
3050a2116ed2SArnd Bergmann 
30517a229387SArnd Bergmann 	if (!err) {
30527a229387SArnd Bergmann 		switch (cmd) {
30537a229387SArnd Bergmann 		case SIOCGIFFLAGS:
30547a229387SArnd Bergmann 		case SIOCGIFMETRIC:
30557a229387SArnd Bergmann 		case SIOCGIFMTU:
30567a229387SArnd Bergmann 		case SIOCGIFMEM:
30577a229387SArnd Bergmann 		case SIOCGIFHWADDR:
30587a229387SArnd Bergmann 		case SIOCGIFINDEX:
30597a229387SArnd Bergmann 		case SIOCGIFADDR:
30607a229387SArnd Bergmann 		case SIOCGIFBRDADDR:
30617a229387SArnd Bergmann 		case SIOCGIFDSTADDR:
30627a229387SArnd Bergmann 		case SIOCGIFNETMASK:
3063fab2532bSArnd Bergmann 		case SIOCGIFPFLAGS:
30647a229387SArnd Bergmann 		case SIOCGIFTXQLEN:
3065fab2532bSArnd Bergmann 		case SIOCGMIIPHY:
3066fab2532bSArnd Bergmann 		case SIOCGMIIREG:
3067a2116ed2SArnd Bergmann 			if (copy_in_user(uifr32, uifr, sizeof(*uifr32)))
3068a2116ed2SArnd Bergmann 				err = -EFAULT;
30697a229387SArnd Bergmann 			break;
3070a2116ed2SArnd Bergmann 		}
3071a2116ed2SArnd Bergmann 	}
3072a2116ed2SArnd Bergmann 	return err;
3073a2116ed2SArnd Bergmann }
3074a2116ed2SArnd Bergmann 
3075a2116ed2SArnd Bergmann static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
3076a2116ed2SArnd Bergmann 			struct compat_ifreq __user *uifr32)
3077a2116ed2SArnd Bergmann {
3078a2116ed2SArnd Bergmann 	struct ifreq ifr;
3079a2116ed2SArnd Bergmann 	struct compat_ifmap __user *uifmap32;
3080a2116ed2SArnd Bergmann 	mm_segment_t old_fs;
3081a2116ed2SArnd Bergmann 	int err;
3082a2116ed2SArnd Bergmann 
3083a2116ed2SArnd Bergmann 	uifmap32 = &uifr32->ifr_ifru.ifru_map;
3084a2116ed2SArnd Bergmann 	err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name));
30853ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
30863ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
30873ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
30883ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.irq, &uifmap32->irq);
30893ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.dma, &uifmap32->dma);
30903ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.port, &uifmap32->port);
3091a2116ed2SArnd Bergmann 	if (err)
3092a2116ed2SArnd Bergmann 		return -EFAULT;
3093a2116ed2SArnd Bergmann 
3094a2116ed2SArnd Bergmann 	old_fs = get_fs();
3095a2116ed2SArnd Bergmann 	set_fs(KERNEL_DS);
3096c3f52ae6Sstephen hemminger 	err = dev_ioctl(net, cmd, (void  __user __force *)&ifr);
3097a2116ed2SArnd Bergmann 	set_fs(old_fs);
3098a2116ed2SArnd Bergmann 
3099a2116ed2SArnd Bergmann 	if (cmd == SIOCGIFMAP && !err) {
31007a229387SArnd Bergmann 		err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name));
31013ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
31023ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
31033ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
31043ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.irq, &uifmap32->irq);
31053ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.dma, &uifmap32->dma);
31063ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.port, &uifmap32->port);
31077a229387SArnd Bergmann 		if (err)
31087a229387SArnd Bergmann 			err = -EFAULT;
31097a229387SArnd Bergmann 	}
31107a229387SArnd Bergmann 	return err;
31117a229387SArnd Bergmann }
31127a229387SArnd Bergmann 
3113a2116ed2SArnd Bergmann static int compat_siocshwtstamp(struct net *net, struct compat_ifreq __user *uifr32)
3114a2116ed2SArnd Bergmann {
3115a2116ed2SArnd Bergmann 	void __user *uptr;
3116a2116ed2SArnd Bergmann 	compat_uptr_t uptr32;
3117a2116ed2SArnd Bergmann 	struct ifreq __user *uifr;
3118a2116ed2SArnd Bergmann 
3119a2116ed2SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
3120a2116ed2SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
3121a2116ed2SArnd Bergmann 		return -EFAULT;
3122a2116ed2SArnd Bergmann 
3123a2116ed2SArnd Bergmann 	if (get_user(uptr32, &uifr32->ifr_data))
3124a2116ed2SArnd Bergmann 		return -EFAULT;
3125a2116ed2SArnd Bergmann 
3126a2116ed2SArnd Bergmann 	uptr = compat_ptr(uptr32);
3127a2116ed2SArnd Bergmann 
3128a2116ed2SArnd Bergmann 	if (put_user(uptr, &uifr->ifr_data))
3129a2116ed2SArnd Bergmann 		return -EFAULT;
3130a2116ed2SArnd Bergmann 
3131a2116ed2SArnd Bergmann 	return dev_ioctl(net, SIOCSHWTSTAMP, uifr);
3132a2116ed2SArnd Bergmann }
3133a2116ed2SArnd Bergmann 
31347a229387SArnd Bergmann struct rtentry32 {
31357a229387SArnd Bergmann 	u32		rt_pad1;
31367a229387SArnd Bergmann 	struct sockaddr rt_dst;         /* target address               */
31377a229387SArnd Bergmann 	struct sockaddr rt_gateway;     /* gateway addr (RTF_GATEWAY)   */
31387a229387SArnd Bergmann 	struct sockaddr rt_genmask;     /* target network mask (IP)     */
31397a229387SArnd Bergmann 	unsigned short	rt_flags;
31407a229387SArnd Bergmann 	short		rt_pad2;
31417a229387SArnd Bergmann 	u32		rt_pad3;
31427a229387SArnd Bergmann 	unsigned char	rt_tos;
31437a229387SArnd Bergmann 	unsigned char	rt_class;
31447a229387SArnd Bergmann 	short		rt_pad4;
31457a229387SArnd Bergmann 	short		rt_metric;      /* +1 for binary compatibility! */
31467a229387SArnd Bergmann 	/* char * */ u32 rt_dev;        /* forcing the device at add    */
31477a229387SArnd Bergmann 	u32		rt_mtu;         /* per route MTU/Window         */
31487a229387SArnd Bergmann 	u32		rt_window;      /* Window clamping              */
31497a229387SArnd Bergmann 	unsigned short  rt_irtt;        /* Initial RTT                  */
31507a229387SArnd Bergmann };
31517a229387SArnd Bergmann 
31527a229387SArnd Bergmann struct in6_rtmsg32 {
31537a229387SArnd Bergmann 	struct in6_addr		rtmsg_dst;
31547a229387SArnd Bergmann 	struct in6_addr		rtmsg_src;
31557a229387SArnd Bergmann 	struct in6_addr		rtmsg_gateway;
31567a229387SArnd Bergmann 	u32			rtmsg_type;
31577a229387SArnd Bergmann 	u16			rtmsg_dst_len;
31587a229387SArnd Bergmann 	u16			rtmsg_src_len;
31597a229387SArnd Bergmann 	u32			rtmsg_metric;
31607a229387SArnd Bergmann 	u32			rtmsg_info;
31617a229387SArnd Bergmann 	u32			rtmsg_flags;
31627a229387SArnd Bergmann 	s32			rtmsg_ifindex;
31637a229387SArnd Bergmann };
31647a229387SArnd Bergmann 
31656b96018bSArnd Bergmann static int routing_ioctl(struct net *net, struct socket *sock,
31666b96018bSArnd Bergmann 			 unsigned int cmd, void __user *argp)
31677a229387SArnd Bergmann {
31687a229387SArnd Bergmann 	int ret;
31697a229387SArnd Bergmann 	void *r = NULL;
31707a229387SArnd Bergmann 	struct in6_rtmsg r6;
31717a229387SArnd Bergmann 	struct rtentry r4;
31727a229387SArnd Bergmann 	char devname[16];
31737a229387SArnd Bergmann 	u32 rtdev;
31747a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
31757a229387SArnd Bergmann 
31766b96018bSArnd Bergmann 	if (sock && sock->sk && sock->sk->sk_family == AF_INET6) { /* ipv6 */
31776b96018bSArnd Bergmann 		struct in6_rtmsg32 __user *ur6 = argp;
31787a229387SArnd Bergmann 		ret = copy_from_user(&r6.rtmsg_dst, &(ur6->rtmsg_dst),
31797a229387SArnd Bergmann 			3 * sizeof(struct in6_addr));
31803ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_type, &(ur6->rtmsg_type));
31813ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len));
31823ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_src_len, &(ur6->rtmsg_src_len));
31833ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_metric, &(ur6->rtmsg_metric));
31843ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_info, &(ur6->rtmsg_info));
31853ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_flags, &(ur6->rtmsg_flags));
31863ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex));
31877a229387SArnd Bergmann 
31887a229387SArnd Bergmann 		r = (void *) &r6;
31897a229387SArnd Bergmann 	} else { /* ipv4 */
31906b96018bSArnd Bergmann 		struct rtentry32 __user *ur4 = argp;
31917a229387SArnd Bergmann 		ret = copy_from_user(&r4.rt_dst, &(ur4->rt_dst),
31927a229387SArnd Bergmann 					3 * sizeof(struct sockaddr));
31933ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_flags, &(ur4->rt_flags));
31943ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_metric, &(ur4->rt_metric));
31953ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_mtu, &(ur4->rt_mtu));
31963ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_window, &(ur4->rt_window));
31973ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_irtt, &(ur4->rt_irtt));
31983ddc5b46SMathieu Desnoyers 		ret |= get_user(rtdev, &(ur4->rt_dev));
31997a229387SArnd Bergmann 		if (rtdev) {
32007a229387SArnd Bergmann 			ret |= copy_from_user(devname, compat_ptr(rtdev), 15);
3201c3f52ae6Sstephen hemminger 			r4.rt_dev = (char __user __force *)devname;
3202c3f52ae6Sstephen hemminger 			devname[15] = 0;
32037a229387SArnd Bergmann 		} else
32047a229387SArnd Bergmann 			r4.rt_dev = NULL;
32057a229387SArnd Bergmann 
32067a229387SArnd Bergmann 		r = (void *) &r4;
32077a229387SArnd Bergmann 	}
32087a229387SArnd Bergmann 
32097a229387SArnd Bergmann 	if (ret) {
32107a229387SArnd Bergmann 		ret = -EFAULT;
32117a229387SArnd Bergmann 		goto out;
32127a229387SArnd Bergmann 	}
32137a229387SArnd Bergmann 
32147a229387SArnd Bergmann 	set_fs(KERNEL_DS);
32156b96018bSArnd Bergmann 	ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r);
32167a229387SArnd Bergmann 	set_fs(old_fs);
32177a229387SArnd Bergmann 
32187a229387SArnd Bergmann out:
32197a229387SArnd Bergmann 	return ret;
32207a229387SArnd Bergmann }
32217a229387SArnd Bergmann 
32227a229387SArnd Bergmann /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE
32237a229387SArnd Bergmann  * for some operations; this forces use of the newer bridge-utils that
322425985edcSLucas De Marchi  * use compatible ioctls
32257a229387SArnd Bergmann  */
32266b96018bSArnd Bergmann static int old_bridge_ioctl(compat_ulong_t __user *argp)
32277a229387SArnd Bergmann {
32286b96018bSArnd Bergmann 	compat_ulong_t tmp;
32297a229387SArnd Bergmann 
32306b96018bSArnd Bergmann 	if (get_user(tmp, argp))
32317a229387SArnd Bergmann 		return -EFAULT;
32327a229387SArnd Bergmann 	if (tmp == BRCTL_GET_VERSION)
32337a229387SArnd Bergmann 		return BRCTL_VERSION + 1;
32347a229387SArnd Bergmann 	return -EINVAL;
32357a229387SArnd Bergmann }
32367a229387SArnd Bergmann 
32376b96018bSArnd Bergmann static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
32386b96018bSArnd Bergmann 			 unsigned int cmd, unsigned long arg)
32396b96018bSArnd Bergmann {
32406b96018bSArnd Bergmann 	void __user *argp = compat_ptr(arg);
32416b96018bSArnd Bergmann 	struct sock *sk = sock->sk;
32426b96018bSArnd Bergmann 	struct net *net = sock_net(sk);
32437a229387SArnd Bergmann 
32446b96018bSArnd Bergmann 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
32456b96018bSArnd Bergmann 		return siocdevprivate_ioctl(net, cmd, argp);
32467a229387SArnd Bergmann 
32476b96018bSArnd Bergmann 	switch (cmd) {
32486b96018bSArnd Bergmann 	case SIOCSIFBR:
32496b96018bSArnd Bergmann 	case SIOCGIFBR:
32506b96018bSArnd Bergmann 		return old_bridge_ioctl(argp);
32516b96018bSArnd Bergmann 	case SIOCGIFNAME:
32526b96018bSArnd Bergmann 		return dev_ifname32(net, argp);
32536b96018bSArnd Bergmann 	case SIOCGIFCONF:
32546b96018bSArnd Bergmann 		return dev_ifconf(net, argp);
32556b96018bSArnd Bergmann 	case SIOCETHTOOL:
32566b96018bSArnd Bergmann 		return ethtool_ioctl(net, argp);
32577a50a240SArnd Bergmann 	case SIOCWANDEV:
32587a50a240SArnd Bergmann 		return compat_siocwandev(net, argp);
3259a2116ed2SArnd Bergmann 	case SIOCGIFMAP:
3260a2116ed2SArnd Bergmann 	case SIOCSIFMAP:
3261a2116ed2SArnd Bergmann 		return compat_sioc_ifmap(net, cmd, argp);
32626b96018bSArnd Bergmann 	case SIOCBONDENSLAVE:
32636b96018bSArnd Bergmann 	case SIOCBONDRELEASE:
32646b96018bSArnd Bergmann 	case SIOCBONDSETHWADDR:
32656b96018bSArnd Bergmann 	case SIOCBONDSLAVEINFOQUERY:
32666b96018bSArnd Bergmann 	case SIOCBONDINFOQUERY:
32676b96018bSArnd Bergmann 	case SIOCBONDCHANGEACTIVE:
32686b96018bSArnd Bergmann 		return bond_ioctl(net, cmd, argp);
32696b96018bSArnd Bergmann 	case SIOCADDRT:
32706b96018bSArnd Bergmann 	case SIOCDELRT:
32716b96018bSArnd Bergmann 		return routing_ioctl(net, sock, cmd, argp);
32726b96018bSArnd Bergmann 	case SIOCGSTAMP:
32736b96018bSArnd Bergmann 		return do_siocgstamp(net, sock, cmd, argp);
32746b96018bSArnd Bergmann 	case SIOCGSTAMPNS:
32756b96018bSArnd Bergmann 		return do_siocgstampns(net, sock, cmd, argp);
3276a2116ed2SArnd Bergmann 	case SIOCSHWTSTAMP:
3277a2116ed2SArnd Bergmann 		return compat_siocshwtstamp(net, argp);
32787a229387SArnd Bergmann 
32796b96018bSArnd Bergmann 	case FIOSETOWN:
32806b96018bSArnd Bergmann 	case SIOCSPGRP:
32816b96018bSArnd Bergmann 	case FIOGETOWN:
32826b96018bSArnd Bergmann 	case SIOCGPGRP:
32836b96018bSArnd Bergmann 	case SIOCBRADDBR:
32846b96018bSArnd Bergmann 	case SIOCBRDELBR:
32856b96018bSArnd Bergmann 	case SIOCGIFVLAN:
32866b96018bSArnd Bergmann 	case SIOCSIFVLAN:
32876b96018bSArnd Bergmann 	case SIOCADDDLCI:
32886b96018bSArnd Bergmann 	case SIOCDELDLCI:
32896b96018bSArnd Bergmann 		return sock_ioctl(file, cmd, arg);
32906b96018bSArnd Bergmann 
32916b96018bSArnd Bergmann 	case SIOCGIFFLAGS:
32926b96018bSArnd Bergmann 	case SIOCSIFFLAGS:
32936b96018bSArnd Bergmann 	case SIOCGIFMETRIC:
32946b96018bSArnd Bergmann 	case SIOCSIFMETRIC:
32956b96018bSArnd Bergmann 	case SIOCGIFMTU:
32966b96018bSArnd Bergmann 	case SIOCSIFMTU:
32976b96018bSArnd Bergmann 	case SIOCGIFMEM:
32986b96018bSArnd Bergmann 	case SIOCSIFMEM:
32996b96018bSArnd Bergmann 	case SIOCGIFHWADDR:
33006b96018bSArnd Bergmann 	case SIOCSIFHWADDR:
33016b96018bSArnd Bergmann 	case SIOCADDMULTI:
33026b96018bSArnd Bergmann 	case SIOCDELMULTI:
33036b96018bSArnd Bergmann 	case SIOCGIFINDEX:
33046b96018bSArnd Bergmann 	case SIOCGIFADDR:
33056b96018bSArnd Bergmann 	case SIOCSIFADDR:
33066b96018bSArnd Bergmann 	case SIOCSIFHWBROADCAST:
33076b96018bSArnd Bergmann 	case SIOCDIFADDR:
33086b96018bSArnd Bergmann 	case SIOCGIFBRDADDR:
33096b96018bSArnd Bergmann 	case SIOCSIFBRDADDR:
33106b96018bSArnd Bergmann 	case SIOCGIFDSTADDR:
33116b96018bSArnd Bergmann 	case SIOCSIFDSTADDR:
33126b96018bSArnd Bergmann 	case SIOCGIFNETMASK:
33136b96018bSArnd Bergmann 	case SIOCSIFNETMASK:
33146b96018bSArnd Bergmann 	case SIOCSIFPFLAGS:
33156b96018bSArnd Bergmann 	case SIOCGIFPFLAGS:
33166b96018bSArnd Bergmann 	case SIOCGIFTXQLEN:
33176b96018bSArnd Bergmann 	case SIOCSIFTXQLEN:
33186b96018bSArnd Bergmann 	case SIOCBRADDIF:
33196b96018bSArnd Bergmann 	case SIOCBRDELIF:
33209177efd3SArnd Bergmann 	case SIOCSIFNAME:
33219177efd3SArnd Bergmann 	case SIOCGMIIPHY:
33229177efd3SArnd Bergmann 	case SIOCGMIIREG:
33239177efd3SArnd Bergmann 	case SIOCSMIIREG:
33246b96018bSArnd Bergmann 		return dev_ifsioc(net, sock, cmd, argp);
33259177efd3SArnd Bergmann 
33266b96018bSArnd Bergmann 	case SIOCSARP:
33276b96018bSArnd Bergmann 	case SIOCGARP:
33286b96018bSArnd Bergmann 	case SIOCDARP:
33296b96018bSArnd Bergmann 	case SIOCATMARK:
33309177efd3SArnd Bergmann 		return sock_do_ioctl(net, sock, cmd, arg);
33319177efd3SArnd Bergmann 	}
33329177efd3SArnd Bergmann 
33336b96018bSArnd Bergmann 	return -ENOIOCTLCMD;
33346b96018bSArnd Bergmann }
33357a229387SArnd Bergmann 
333695c96174SEric Dumazet static long compat_sock_ioctl(struct file *file, unsigned int cmd,
333789bbfc95SShaun Pereira 			      unsigned long arg)
333889bbfc95SShaun Pereira {
333989bbfc95SShaun Pereira 	struct socket *sock = file->private_data;
334089bbfc95SShaun Pereira 	int ret = -ENOIOCTLCMD;
334187de87d5SDavid S. Miller 	struct sock *sk;
334287de87d5SDavid S. Miller 	struct net *net;
334387de87d5SDavid S. Miller 
334487de87d5SDavid S. Miller 	sk = sock->sk;
334587de87d5SDavid S. Miller 	net = sock_net(sk);
334689bbfc95SShaun Pereira 
334789bbfc95SShaun Pereira 	if (sock->ops->compat_ioctl)
334889bbfc95SShaun Pereira 		ret = sock->ops->compat_ioctl(sock, cmd, arg);
334989bbfc95SShaun Pereira 
335087de87d5SDavid S. Miller 	if (ret == -ENOIOCTLCMD &&
335187de87d5SDavid S. Miller 	    (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST))
335287de87d5SDavid S. Miller 		ret = compat_wext_handle_ioctl(net, cmd, arg);
335387de87d5SDavid S. Miller 
33546b96018bSArnd Bergmann 	if (ret == -ENOIOCTLCMD)
33556b96018bSArnd Bergmann 		ret = compat_sock_ioctl_trans(file, sock, cmd, arg);
33566b96018bSArnd Bergmann 
335789bbfc95SShaun Pereira 	return ret;
335889bbfc95SShaun Pereira }
335989bbfc95SShaun Pereira #endif
336089bbfc95SShaun Pereira 
3361ac5a488eSSridhar Samudrala int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
3362ac5a488eSSridhar Samudrala {
3363ac5a488eSSridhar Samudrala 	return sock->ops->bind(sock, addr, addrlen);
3364ac5a488eSSridhar Samudrala }
3365c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_bind);
3366ac5a488eSSridhar Samudrala 
3367ac5a488eSSridhar Samudrala int kernel_listen(struct socket *sock, int backlog)
3368ac5a488eSSridhar Samudrala {
3369ac5a488eSSridhar Samudrala 	return sock->ops->listen(sock, backlog);
3370ac5a488eSSridhar Samudrala }
3371c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_listen);
3372ac5a488eSSridhar Samudrala 
3373ac5a488eSSridhar Samudrala int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
3374ac5a488eSSridhar Samudrala {
3375ac5a488eSSridhar Samudrala 	struct sock *sk = sock->sk;
3376ac5a488eSSridhar Samudrala 	int err;
3377ac5a488eSSridhar Samudrala 
3378ac5a488eSSridhar Samudrala 	err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
3379ac5a488eSSridhar Samudrala 			       newsock);
3380ac5a488eSSridhar Samudrala 	if (err < 0)
3381ac5a488eSSridhar Samudrala 		goto done;
3382ac5a488eSSridhar Samudrala 
3383ac5a488eSSridhar Samudrala 	err = sock->ops->accept(sock, *newsock, flags);
3384ac5a488eSSridhar Samudrala 	if (err < 0) {
3385ac5a488eSSridhar Samudrala 		sock_release(*newsock);
3386fa8705b0STony Battersby 		*newsock = NULL;
3387ac5a488eSSridhar Samudrala 		goto done;
3388ac5a488eSSridhar Samudrala 	}
3389ac5a488eSSridhar Samudrala 
3390ac5a488eSSridhar Samudrala 	(*newsock)->ops = sock->ops;
33911b08534eSWei Yongjun 	__module_get((*newsock)->ops->owner);
3392ac5a488eSSridhar Samudrala 
3393ac5a488eSSridhar Samudrala done:
3394ac5a488eSSridhar Samudrala 	return err;
3395ac5a488eSSridhar Samudrala }
3396c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_accept);
3397ac5a488eSSridhar Samudrala 
3398ac5a488eSSridhar Samudrala int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
3399ac5a488eSSridhar Samudrala 		   int flags)
3400ac5a488eSSridhar Samudrala {
3401ac5a488eSSridhar Samudrala 	return sock->ops->connect(sock, addr, addrlen, flags);
3402ac5a488eSSridhar Samudrala }
3403c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_connect);
3404ac5a488eSSridhar Samudrala 
3405ac5a488eSSridhar Samudrala int kernel_getsockname(struct socket *sock, struct sockaddr *addr,
3406ac5a488eSSridhar Samudrala 			 int *addrlen)
3407ac5a488eSSridhar Samudrala {
3408ac5a488eSSridhar Samudrala 	return sock->ops->getname(sock, addr, addrlen, 0);
3409ac5a488eSSridhar Samudrala }
3410c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockname);
3411ac5a488eSSridhar Samudrala 
3412ac5a488eSSridhar Samudrala int kernel_getpeername(struct socket *sock, struct sockaddr *addr,
3413ac5a488eSSridhar Samudrala 			 int *addrlen)
3414ac5a488eSSridhar Samudrala {
3415ac5a488eSSridhar Samudrala 	return sock->ops->getname(sock, addr, addrlen, 1);
3416ac5a488eSSridhar Samudrala }
3417c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getpeername);
3418ac5a488eSSridhar Samudrala 
3419ac5a488eSSridhar Samudrala int kernel_getsockopt(struct socket *sock, int level, int optname,
3420ac5a488eSSridhar Samudrala 			char *optval, int *optlen)
3421ac5a488eSSridhar Samudrala {
3422ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3423fb8621bbSNamhyung Kim 	char __user *uoptval;
3424fb8621bbSNamhyung Kim 	int __user *uoptlen;
3425ac5a488eSSridhar Samudrala 	int err;
3426ac5a488eSSridhar Samudrala 
3427fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3428fb8621bbSNamhyung Kim 	uoptlen = (int __user __force *) optlen;
3429fb8621bbSNamhyung Kim 
3430ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3431ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3432fb8621bbSNamhyung Kim 		err = sock_getsockopt(sock, level, optname, uoptval, uoptlen);
3433ac5a488eSSridhar Samudrala 	else
3434fb8621bbSNamhyung Kim 		err = sock->ops->getsockopt(sock, level, optname, uoptval,
3435fb8621bbSNamhyung Kim 					    uoptlen);
3436ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3437ac5a488eSSridhar Samudrala 	return err;
3438ac5a488eSSridhar Samudrala }
3439c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockopt);
3440ac5a488eSSridhar Samudrala 
3441ac5a488eSSridhar Samudrala int kernel_setsockopt(struct socket *sock, int level, int optname,
3442b7058842SDavid S. Miller 			char *optval, unsigned int optlen)
3443ac5a488eSSridhar Samudrala {
3444ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3445fb8621bbSNamhyung Kim 	char __user *uoptval;
3446ac5a488eSSridhar Samudrala 	int err;
3447ac5a488eSSridhar Samudrala 
3448fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3449fb8621bbSNamhyung Kim 
3450ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3451ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3452fb8621bbSNamhyung Kim 		err = sock_setsockopt(sock, level, optname, uoptval, optlen);
3453ac5a488eSSridhar Samudrala 	else
3454fb8621bbSNamhyung Kim 		err = sock->ops->setsockopt(sock, level, optname, uoptval,
3455ac5a488eSSridhar Samudrala 					    optlen);
3456ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3457ac5a488eSSridhar Samudrala 	return err;
3458ac5a488eSSridhar Samudrala }
3459c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_setsockopt);
3460ac5a488eSSridhar Samudrala 
3461ac5a488eSSridhar Samudrala int kernel_sendpage(struct socket *sock, struct page *page, int offset,
3462ac5a488eSSridhar Samudrala 		    size_t size, int flags)
3463ac5a488eSSridhar Samudrala {
3464ac5a488eSSridhar Samudrala 	if (sock->ops->sendpage)
3465ac5a488eSSridhar Samudrala 		return sock->ops->sendpage(sock, page, offset, size, flags);
3466ac5a488eSSridhar Samudrala 
3467ac5a488eSSridhar Samudrala 	return sock_no_sendpage(sock, page, offset, size, flags);
3468ac5a488eSSridhar Samudrala }
3469c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendpage);
3470ac5a488eSSridhar Samudrala 
3471ac5a488eSSridhar Samudrala int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg)
3472ac5a488eSSridhar Samudrala {
3473ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3474ac5a488eSSridhar Samudrala 	int err;
3475ac5a488eSSridhar Samudrala 
3476ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3477ac5a488eSSridhar Samudrala 	err = sock->ops->ioctl(sock, cmd, arg);
3478ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3479ac5a488eSSridhar Samudrala 
3480ac5a488eSSridhar Samudrala 	return err;
3481ac5a488eSSridhar Samudrala }
3482c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sock_ioctl);
3483ac5a488eSSridhar Samudrala 
348491cf45f0STrond Myklebust int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
348591cf45f0STrond Myklebust {
348691cf45f0STrond Myklebust 	return sock->ops->shutdown(sock, how);
348791cf45f0STrond Myklebust }
348891cf45f0STrond Myklebust EXPORT_SYMBOL(kernel_sock_shutdown);
3489