xref: /openbmc/linux/net/socket.c (revision 4b936885)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * NET		An implementation of the SOCKET network access protocol.
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Version:	@(#)socket.c	1.1.93	18/02/95
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * Authors:	Orest Zborowski, <obz@Kodak.COM>
702c30a84SJesper Juhl  *		Ross Biro
81da177e4SLinus Torvalds  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
91da177e4SLinus Torvalds  *
101da177e4SLinus Torvalds  * Fixes:
111da177e4SLinus Torvalds  *		Anonymous	:	NOTSOCK/BADF cleanup. Error fix in
121da177e4SLinus Torvalds  *					shutdown()
131da177e4SLinus Torvalds  *		Alan Cox	:	verify_area() fixes
141da177e4SLinus Torvalds  *		Alan Cox	:	Removed DDI
151da177e4SLinus Torvalds  *		Jonathan Kamens	:	SOCK_DGRAM reconnect bug
161da177e4SLinus Torvalds  *		Alan Cox	:	Moved a load of checks to the very
171da177e4SLinus Torvalds  *					top level.
181da177e4SLinus Torvalds  *		Alan Cox	:	Move address structures to/from user
191da177e4SLinus Torvalds  *					mode above the protocol layers.
201da177e4SLinus Torvalds  *		Rob Janssen	:	Allow 0 length sends.
211da177e4SLinus Torvalds  *		Alan Cox	:	Asynchronous I/O support (cribbed from the
221da177e4SLinus Torvalds  *					tty drivers).
231da177e4SLinus Torvalds  *		Niibe Yutaka	:	Asynchronous I/O for writes (4.4BSD style)
241da177e4SLinus Torvalds  *		Jeff Uphoff	:	Made max number of sockets command-line
251da177e4SLinus Torvalds  *					configurable.
261da177e4SLinus Torvalds  *		Matti Aarnio	:	Made the number of sockets dynamic,
271da177e4SLinus Torvalds  *					to be allocated when needed, and mr.
281da177e4SLinus Torvalds  *					Uphoff's max is used as max to be
291da177e4SLinus Torvalds  *					allowed to allocate.
301da177e4SLinus Torvalds  *		Linus		:	Argh. removed all the socket allocation
311da177e4SLinus Torvalds  *					altogether: it's in the inode now.
321da177e4SLinus Torvalds  *		Alan Cox	:	Made sock_alloc()/sock_release() public
331da177e4SLinus Torvalds  *					for NetROM and future kernel nfsd type
341da177e4SLinus Torvalds  *					stuff.
351da177e4SLinus Torvalds  *		Alan Cox	:	sendmsg/recvmsg basics.
361da177e4SLinus Torvalds  *		Tom Dyas	:	Export net symbols.
371da177e4SLinus Torvalds  *		Marcin Dalecki	:	Fixed problems with CONFIG_NET="n".
381da177e4SLinus Torvalds  *		Alan Cox	:	Added thread locking to sys_* calls
391da177e4SLinus Torvalds  *					for sockets. May have errors at the
401da177e4SLinus Torvalds  *					moment.
411da177e4SLinus Torvalds  *		Kevin Buhr	:	Fixed the dumb errors in the above.
421da177e4SLinus Torvalds  *		Andi Kleen	:	Some small cleanups, optimizations,
431da177e4SLinus Torvalds  *					and fixed a copy_from_user() bug.
441da177e4SLinus Torvalds  *		Tigran Aivazian	:	sys_send(args) calls sys_sendto(args, NULL, 0)
451da177e4SLinus Torvalds  *		Tigran Aivazian	:	Made listen(2) backlog sanity checks
461da177e4SLinus Torvalds  *					protocol-independent
471da177e4SLinus Torvalds  *
481da177e4SLinus Torvalds  *
491da177e4SLinus Torvalds  *		This program is free software; you can redistribute it and/or
501da177e4SLinus Torvalds  *		modify it under the terms of the GNU General Public License
511da177e4SLinus Torvalds  *		as published by the Free Software Foundation; either version
521da177e4SLinus Torvalds  *		2 of the License, or (at your option) any later version.
531da177e4SLinus Torvalds  *
541da177e4SLinus Torvalds  *
551da177e4SLinus Torvalds  *	This module is effectively the top level interface to the BSD socket
561da177e4SLinus Torvalds  *	paradigm.
571da177e4SLinus Torvalds  *
581da177e4SLinus Torvalds  *	Based upon Swansea University Computer Society NET3.039
591da177e4SLinus Torvalds  */
601da177e4SLinus Torvalds 
611da177e4SLinus Torvalds #include <linux/mm.h>
621da177e4SLinus Torvalds #include <linux/socket.h>
631da177e4SLinus Torvalds #include <linux/file.h>
641da177e4SLinus Torvalds #include <linux/net.h>
651da177e4SLinus Torvalds #include <linux/interrupt.h>
66aaca0bdcSUlrich Drepper #include <linux/thread_info.h>
6755737fdaSStephen Hemminger #include <linux/rcupdate.h>
681da177e4SLinus Torvalds #include <linux/netdevice.h>
691da177e4SLinus Torvalds #include <linux/proc_fs.h>
701da177e4SLinus Torvalds #include <linux/seq_file.h>
714a3e2f71SArjan van de Ven #include <linux/mutex.h>
721da177e4SLinus Torvalds #include <linux/wanrouter.h>
731da177e4SLinus Torvalds #include <linux/if_bridge.h>
7420380731SArnaldo Carvalho de Melo #include <linux/if_frad.h>
7520380731SArnaldo Carvalho de Melo #include <linux/if_vlan.h>
761da177e4SLinus Torvalds #include <linux/init.h>
771da177e4SLinus Torvalds #include <linux/poll.h>
781da177e4SLinus Torvalds #include <linux/cache.h>
791da177e4SLinus Torvalds #include <linux/module.h>
801da177e4SLinus Torvalds #include <linux/highmem.h>
811da177e4SLinus Torvalds #include <linux/mount.h>
821da177e4SLinus Torvalds #include <linux/security.h>
831da177e4SLinus Torvalds #include <linux/syscalls.h>
841da177e4SLinus Torvalds #include <linux/compat.h>
851da177e4SLinus Torvalds #include <linux/kmod.h>
863ec3b2fbSDavid Woodhouse #include <linux/audit.h>
87d86b5e0eSAdrian Bunk #include <linux/wireless.h>
881b8d7ae4SEric W. Biederman #include <linux/nsproxy.h>
891fd7317dSNick Black #include <linux/magic.h>
905a0e3ad6STejun Heo #include <linux/slab.h>
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>
1076b96018bSArnd Bergmann 
1081da177e4SLinus Torvalds static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
109027445c3SBadari Pulavarty static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
110027445c3SBadari Pulavarty 			 unsigned long nr_segs, loff_t pos);
111027445c3SBadari Pulavarty static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
112027445c3SBadari Pulavarty 			  unsigned long nr_segs, loff_t pos);
1131da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma);
1141da177e4SLinus Torvalds 
1151da177e4SLinus Torvalds static int sock_close(struct inode *inode, struct file *file);
1161da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file,
1171da177e4SLinus Torvalds 			      struct poll_table_struct *wait);
11889bddce5SStephen Hemminger static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
11989bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
12089bbfc95SShaun Pereira static long compat_sock_ioctl(struct file *file,
12189bbfc95SShaun Pereira 			      unsigned int cmd, unsigned long arg);
12289bbfc95SShaun Pereira #endif
1231da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on);
1241da177e4SLinus Torvalds static ssize_t sock_sendpage(struct file *file, struct page *page,
1251da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more);
1269c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
1279c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
1289c55e01cSJens Axboe 				unsigned int flags);
1291da177e4SLinus Torvalds 
1301da177e4SLinus Torvalds /*
1311da177e4SLinus Torvalds  *	Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
1321da177e4SLinus Torvalds  *	in the operation structures but are done directly via the socketcall() multiplexor.
1331da177e4SLinus Torvalds  */
1341da177e4SLinus Torvalds 
135da7071d7SArjan van de Ven static const struct file_operations socket_file_ops = {
1361da177e4SLinus Torvalds 	.owner =	THIS_MODULE,
1371da177e4SLinus Torvalds 	.llseek =	no_llseek,
1381da177e4SLinus Torvalds 	.aio_read =	sock_aio_read,
1391da177e4SLinus Torvalds 	.aio_write =	sock_aio_write,
1401da177e4SLinus Torvalds 	.poll =		sock_poll,
1411da177e4SLinus Torvalds 	.unlocked_ioctl = sock_ioctl,
14289bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
14389bbfc95SShaun Pereira 	.compat_ioctl = compat_sock_ioctl,
14489bbfc95SShaun Pereira #endif
1451da177e4SLinus Torvalds 	.mmap =		sock_mmap,
1461da177e4SLinus Torvalds 	.open =		sock_no_open,	/* special open code to disallow open via /proc */
1471da177e4SLinus Torvalds 	.release =	sock_close,
1481da177e4SLinus Torvalds 	.fasync =	sock_fasync,
1495274f052SJens Axboe 	.sendpage =	sock_sendpage,
1505274f052SJens Axboe 	.splice_write = generic_splice_sendpage,
1519c55e01cSJens Axboe 	.splice_read =	sock_splice_read,
1521da177e4SLinus Torvalds };
1531da177e4SLinus Torvalds 
1541da177e4SLinus Torvalds /*
1551da177e4SLinus Torvalds  *	The protocol list. Each protocol is registered in here.
1561da177e4SLinus Torvalds  */
1571da177e4SLinus Torvalds 
1581da177e4SLinus Torvalds static DEFINE_SPINLOCK(net_family_lock);
159f0fd27d4SStephen Hemminger static const struct net_proto_family *net_families[NPROTO] __read_mostly;
1601da177e4SLinus Torvalds 
1611da177e4SLinus Torvalds /*
1621da177e4SLinus Torvalds  *	Statistics counters of the socket lists
1631da177e4SLinus Torvalds  */
1641da177e4SLinus Torvalds 
165c6d409cfSEric Dumazet static DEFINE_PER_CPU(int, sockets_in_use);
1661da177e4SLinus Torvalds 
1671da177e4SLinus Torvalds /*
16889bddce5SStephen Hemminger  * Support routines.
16989bddce5SStephen Hemminger  * Move socket addresses back and forth across the kernel/user
1701da177e4SLinus Torvalds  * divide and look after the messy bits.
1711da177e4SLinus Torvalds  */
1721da177e4SLinus Torvalds 
1731da177e4SLinus Torvalds /**
1741da177e4SLinus Torvalds  *	move_addr_to_kernel	-	copy a socket address into kernel space
1751da177e4SLinus Torvalds  *	@uaddr: Address in user space
1761da177e4SLinus Torvalds  *	@kaddr: Address in kernel space
1771da177e4SLinus Torvalds  *	@ulen: Length in user space
1781da177e4SLinus Torvalds  *
1791da177e4SLinus Torvalds  *	The address is copied into kernel space. If the provided address is
1801da177e4SLinus Torvalds  *	too long an error code of -EINVAL is returned. If the copy gives
1811da177e4SLinus Torvalds  *	invalid addresses -EFAULT is returned. On a success 0 is returned.
1821da177e4SLinus Torvalds  */
1831da177e4SLinus Torvalds 
184230b1839SYOSHIFUJI Hideaki int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr *kaddr)
1851da177e4SLinus Torvalds {
186230b1839SYOSHIFUJI Hideaki 	if (ulen < 0 || ulen > sizeof(struct sockaddr_storage))
1871da177e4SLinus Torvalds 		return -EINVAL;
1881da177e4SLinus Torvalds 	if (ulen == 0)
1891da177e4SLinus Torvalds 		return 0;
1901da177e4SLinus Torvalds 	if (copy_from_user(kaddr, uaddr, ulen))
1911da177e4SLinus Torvalds 		return -EFAULT;
1923ec3b2fbSDavid Woodhouse 	return audit_sockaddr(ulen, kaddr);
1931da177e4SLinus Torvalds }
1941da177e4SLinus Torvalds 
1951da177e4SLinus Torvalds /**
1961da177e4SLinus Torvalds  *	move_addr_to_user	-	copy an address to user space
1971da177e4SLinus Torvalds  *	@kaddr: kernel space address
1981da177e4SLinus Torvalds  *	@klen: length of address in kernel
1991da177e4SLinus Torvalds  *	@uaddr: user space address
2001da177e4SLinus Torvalds  *	@ulen: pointer to user length field
2011da177e4SLinus Torvalds  *
2021da177e4SLinus Torvalds  *	The value pointed to by ulen on entry is the buffer length available.
2031da177e4SLinus Torvalds  *	This is overwritten with the buffer space used. -EINVAL is returned
2041da177e4SLinus Torvalds  *	if an overlong buffer is specified or a negative buffer size. -EFAULT
2051da177e4SLinus Torvalds  *	is returned if either the buffer or the length field are not
2061da177e4SLinus Torvalds  *	accessible.
2071da177e4SLinus Torvalds  *	After copying the data up to the limit the user specifies, the true
2081da177e4SLinus Torvalds  *	length of the data is written over the length limit the user
2091da177e4SLinus Torvalds  *	specified. Zero is returned for a success.
2101da177e4SLinus Torvalds  */
2111da177e4SLinus Torvalds 
21211165f14Sstephen hemminger static int move_addr_to_user(struct sockaddr *kaddr, int klen,
21311165f14Sstephen hemminger 			     void __user *uaddr, int __user *ulen)
2141da177e4SLinus Torvalds {
2151da177e4SLinus Torvalds 	int err;
2161da177e4SLinus Torvalds 	int len;
2171da177e4SLinus Torvalds 
21889bddce5SStephen Hemminger 	err = get_user(len, ulen);
21989bddce5SStephen Hemminger 	if (err)
2201da177e4SLinus Torvalds 		return err;
2211da177e4SLinus Torvalds 	if (len > klen)
2221da177e4SLinus Torvalds 		len = klen;
223230b1839SYOSHIFUJI Hideaki 	if (len < 0 || len > sizeof(struct sockaddr_storage))
2241da177e4SLinus Torvalds 		return -EINVAL;
22589bddce5SStephen Hemminger 	if (len) {
226d6fe3945SSteve Grubb 		if (audit_sockaddr(klen, kaddr))
227d6fe3945SSteve Grubb 			return -ENOMEM;
2281da177e4SLinus Torvalds 		if (copy_to_user(uaddr, kaddr, len))
2291da177e4SLinus Torvalds 			return -EFAULT;
2301da177e4SLinus Torvalds 	}
2311da177e4SLinus Torvalds 	/*
2321da177e4SLinus Torvalds 	 *      "fromlen shall refer to the value before truncation.."
2331da177e4SLinus Torvalds 	 *                      1003.1g
2341da177e4SLinus Torvalds 	 */
2351da177e4SLinus Torvalds 	return __put_user(klen, ulen);
2361da177e4SLinus Torvalds }
2371da177e4SLinus Torvalds 
238e18b890bSChristoph Lameter static struct kmem_cache *sock_inode_cachep __read_mostly;
2391da177e4SLinus Torvalds 
2401da177e4SLinus Torvalds static struct inode *sock_alloc_inode(struct super_block *sb)
2411da177e4SLinus Torvalds {
2421da177e4SLinus Torvalds 	struct socket_alloc *ei;
24389bddce5SStephen Hemminger 
244e94b1766SChristoph Lameter 	ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL);
2451da177e4SLinus Torvalds 	if (!ei)
2461da177e4SLinus Torvalds 		return NULL;
24743815482SEric Dumazet 	ei->socket.wq = kmalloc(sizeof(struct socket_wq), GFP_KERNEL);
24843815482SEric Dumazet 	if (!ei->socket.wq) {
24943815482SEric Dumazet 		kmem_cache_free(sock_inode_cachep, ei);
25043815482SEric Dumazet 		return NULL;
25143815482SEric Dumazet 	}
25243815482SEric Dumazet 	init_waitqueue_head(&ei->socket.wq->wait);
25343815482SEric Dumazet 	ei->socket.wq->fasync_list = NULL;
2541da177e4SLinus Torvalds 
2551da177e4SLinus Torvalds 	ei->socket.state = SS_UNCONNECTED;
2561da177e4SLinus Torvalds 	ei->socket.flags = 0;
2571da177e4SLinus Torvalds 	ei->socket.ops = NULL;
2581da177e4SLinus Torvalds 	ei->socket.sk = NULL;
2591da177e4SLinus Torvalds 	ei->socket.file = NULL;
2601da177e4SLinus Torvalds 
2611da177e4SLinus Torvalds 	return &ei->vfs_inode;
2621da177e4SLinus Torvalds }
2631da177e4SLinus Torvalds 
26443815482SEric Dumazet 
26543815482SEric Dumazet 
266ff0c7d15SNick Piggin static void wq_free_rcu(struct rcu_head *head)
267ff0c7d15SNick Piggin {
268ff0c7d15SNick Piggin 	struct socket_wq *wq = container_of(head, struct socket_wq, rcu);
269ff0c7d15SNick Piggin 
270ff0c7d15SNick Piggin 	kfree(wq);
27143815482SEric Dumazet }
27243815482SEric Dumazet 
2731da177e4SLinus Torvalds static void sock_destroy_inode(struct inode *inode)
2741da177e4SLinus Torvalds {
275ff0c7d15SNick Piggin 	struct socket_alloc *ei;
276ff0c7d15SNick Piggin 
277ff0c7d15SNick Piggin 	ei = container_of(inode, struct socket_alloc, vfs_inode);
278ff0c7d15SNick Piggin 	call_rcu(&ei->socket.wq->rcu, wq_free_rcu);
279ff0c7d15SNick Piggin 	kmem_cache_free(sock_inode_cachep, ei);
2801da177e4SLinus Torvalds }
2811da177e4SLinus Torvalds 
28251cc5068SAlexey Dobriyan static void init_once(void *foo)
2831da177e4SLinus Torvalds {
2841da177e4SLinus Torvalds 	struct socket_alloc *ei = (struct socket_alloc *)foo;
2851da177e4SLinus Torvalds 
2861da177e4SLinus Torvalds 	inode_init_once(&ei->vfs_inode);
2871da177e4SLinus Torvalds }
2881da177e4SLinus Torvalds 
2891da177e4SLinus Torvalds static int init_inodecache(void)
2901da177e4SLinus Torvalds {
2911da177e4SLinus Torvalds 	sock_inode_cachep = kmem_cache_create("sock_inode_cache",
2921da177e4SLinus Torvalds 					      sizeof(struct socket_alloc),
29389bddce5SStephen Hemminger 					      0,
29489bddce5SStephen Hemminger 					      (SLAB_HWCACHE_ALIGN |
29589bddce5SStephen Hemminger 					       SLAB_RECLAIM_ACCOUNT |
296fffb60f9SPaul Jackson 					       SLAB_MEM_SPREAD),
29720c2df83SPaul Mundt 					      init_once);
2981da177e4SLinus Torvalds 	if (sock_inode_cachep == NULL)
2991da177e4SLinus Torvalds 		return -ENOMEM;
3001da177e4SLinus Torvalds 	return 0;
3011da177e4SLinus Torvalds }
3021da177e4SLinus Torvalds 
303b87221deSAlexey Dobriyan static const struct super_operations sockfs_ops = {
3041da177e4SLinus Torvalds 	.alloc_inode	= sock_alloc_inode,
3051da177e4SLinus Torvalds 	.destroy_inode	= sock_destroy_inode,
3061da177e4SLinus Torvalds 	.statfs		= simple_statfs,
3071da177e4SLinus Torvalds };
3081da177e4SLinus Torvalds 
30951139adaSAl Viro static struct dentry *sockfs_mount(struct file_system_type *fs_type,
31051139adaSAl Viro 			 int flags, const char *dev_name, void *data)
3111da177e4SLinus Torvalds {
31251139adaSAl Viro 	return mount_pseudo(fs_type, "socket:", &sockfs_ops, SOCKFS_MAGIC);
3131da177e4SLinus Torvalds }
3141da177e4SLinus Torvalds 
315ba89966cSEric Dumazet static struct vfsmount *sock_mnt __read_mostly;
3161da177e4SLinus Torvalds 
3171da177e4SLinus Torvalds static struct file_system_type sock_fs_type = {
3181da177e4SLinus Torvalds 	.name =		"sockfs",
31951139adaSAl Viro 	.mount =	sockfs_mount,
3201da177e4SLinus Torvalds 	.kill_sb =	kill_anon_super,
3211da177e4SLinus Torvalds };
32289bddce5SStephen Hemminger 
323c23fbb6bSEric Dumazet /*
324c23fbb6bSEric Dumazet  * sockfs_dname() is called from d_path().
325c23fbb6bSEric Dumazet  */
326c23fbb6bSEric Dumazet static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen)
327c23fbb6bSEric Dumazet {
328c23fbb6bSEric Dumazet 	return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]",
329c23fbb6bSEric Dumazet 				dentry->d_inode->i_ino);
330c23fbb6bSEric Dumazet }
331c23fbb6bSEric Dumazet 
3323ba13d17SAl Viro static const struct dentry_operations sockfs_dentry_operations = {
333c23fbb6bSEric Dumazet 	.d_dname  = sockfs_dname,
3341da177e4SLinus Torvalds };
3351da177e4SLinus Torvalds 
3361da177e4SLinus Torvalds /*
3371da177e4SLinus Torvalds  *	Obtains the first available file descriptor and sets it up for use.
3381da177e4SLinus Torvalds  *
33939d8c1b6SDavid S. Miller  *	These functions create file structures and maps them to fd space
34039d8c1b6SDavid S. Miller  *	of the current process. On success it returns file descriptor
3411da177e4SLinus Torvalds  *	and file struct implicitly stored in sock->file.
3421da177e4SLinus Torvalds  *	Note that another thread may close file descriptor before we return
3431da177e4SLinus Torvalds  *	from this function. We use the fact that now we do not refer
3441da177e4SLinus Torvalds  *	to socket after mapping. If one day we will need it, this
3451da177e4SLinus Torvalds  *	function will increment ref. count on file by 1.
3461da177e4SLinus Torvalds  *
3471da177e4SLinus Torvalds  *	In any case returned fd MAY BE not valid!
3481da177e4SLinus Torvalds  *	This race condition is unavoidable
3491da177e4SLinus Torvalds  *	with shared fd spaces, we cannot solve it inside kernel,
3501da177e4SLinus Torvalds  *	but we take care of internal coherence yet.
3511da177e4SLinus Torvalds  */
3521da177e4SLinus Torvalds 
3537cbe66b6SAl Viro static int sock_alloc_file(struct socket *sock, struct file **f, int flags)
3541da177e4SLinus Torvalds {
3557cbe66b6SAl Viro 	struct qstr name = { .name = "" };
3562c48b9c4SAl Viro 	struct path path;
3577cbe66b6SAl Viro 	struct file *file;
3581da177e4SLinus Torvalds 	int fd;
3591da177e4SLinus Torvalds 
360a677a039SUlrich Drepper 	fd = get_unused_fd_flags(flags);
3617cbe66b6SAl Viro 	if (unlikely(fd < 0))
3627cbe66b6SAl Viro 		return fd;
3631da177e4SLinus Torvalds 
3644b936885SNick Piggin 	path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name);
3652c48b9c4SAl Viro 	if (unlikely(!path.dentry)) {
3667cbe66b6SAl Viro 		put_unused_fd(fd);
36739d8c1b6SDavid S. Miller 		return -ENOMEM;
3687cbe66b6SAl Viro 	}
3692c48b9c4SAl Viro 	path.mnt = mntget(sock_mnt);
37039d8c1b6SDavid S. Miller 
371fb045adbSNick Piggin 	d_set_d_op(path.dentry, &sockfs_dentry_operations);
3722c48b9c4SAl Viro 	d_instantiate(path.dentry, SOCK_INODE(sock));
373cc3808f8SAl Viro 	SOCK_INODE(sock)->i_fop = &socket_file_ops;
374cc3808f8SAl Viro 
3752c48b9c4SAl Viro 	file = alloc_file(&path, FMODE_READ | FMODE_WRITE,
376cc3808f8SAl Viro 		  &socket_file_ops);
377cc3808f8SAl Viro 	if (unlikely(!file)) {
378cc3808f8SAl Viro 		/* drop dentry, keep inode */
3797de9c6eeSAl Viro 		ihold(path.dentry->d_inode);
3802c48b9c4SAl Viro 		path_put(&path);
381cc3808f8SAl Viro 		put_unused_fd(fd);
382cc3808f8SAl Viro 		return -ENFILE;
383cc3808f8SAl Viro 	}
3841da177e4SLinus Torvalds 
3851da177e4SLinus Torvalds 	sock->file = file;
38677d27200SUlrich Drepper 	file->f_flags = O_RDWR | (flags & O_NONBLOCK);
3871da177e4SLinus Torvalds 	file->f_pos = 0;
38807dc3f07SBenjamin LaHaise 	file->private_data = sock;
38939d8c1b6SDavid S. Miller 
3907cbe66b6SAl Viro 	*f = file;
3917cbe66b6SAl Viro 	return fd;
3921da177e4SLinus Torvalds }
3931da177e4SLinus Torvalds 
394a677a039SUlrich Drepper int sock_map_fd(struct socket *sock, int flags)
39539d8c1b6SDavid S. Miller {
39639d8c1b6SDavid S. Miller 	struct file *newfile;
3977cbe66b6SAl Viro 	int fd = sock_alloc_file(sock, &newfile, flags);
39839d8c1b6SDavid S. Miller 
3997cbe66b6SAl Viro 	if (likely(fd >= 0))
40039d8c1b6SDavid S. Miller 		fd_install(fd, newfile);
4017cbe66b6SAl Viro 
4021da177e4SLinus Torvalds 	return fd;
4031da177e4SLinus Torvalds }
404c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_map_fd);
4051da177e4SLinus Torvalds 
4066cb153caSBenjamin LaHaise static struct socket *sock_from_file(struct file *file, int *err)
4076cb153caSBenjamin LaHaise {
4086cb153caSBenjamin LaHaise 	if (file->f_op == &socket_file_ops)
4096cb153caSBenjamin LaHaise 		return file->private_data;	/* set in sock_map_fd */
4106cb153caSBenjamin LaHaise 
4116cb153caSBenjamin LaHaise 	*err = -ENOTSOCK;
4126cb153caSBenjamin LaHaise 	return NULL;
4136cb153caSBenjamin LaHaise }
4146cb153caSBenjamin LaHaise 
4151da177e4SLinus Torvalds /**
4161da177e4SLinus Torvalds  *	sockfd_lookup - Go from a file number to its socket slot
4171da177e4SLinus Torvalds  *	@fd: file handle
4181da177e4SLinus Torvalds  *	@err: pointer to an error code return
4191da177e4SLinus Torvalds  *
4201da177e4SLinus Torvalds  *	The file handle passed in is locked and the socket it is bound
4211da177e4SLinus Torvalds  *	too is returned. If an error occurs the err pointer is overwritten
4221da177e4SLinus Torvalds  *	with a negative errno code and NULL is returned. The function checks
4231da177e4SLinus Torvalds  *	for both invalid handles and passing a handle which is not a socket.
4241da177e4SLinus Torvalds  *
4251da177e4SLinus Torvalds  *	On a success the socket object pointer is returned.
4261da177e4SLinus Torvalds  */
4271da177e4SLinus Torvalds 
4281da177e4SLinus Torvalds struct socket *sockfd_lookup(int fd, int *err)
4291da177e4SLinus Torvalds {
4301da177e4SLinus Torvalds 	struct file *file;
4311da177e4SLinus Torvalds 	struct socket *sock;
4321da177e4SLinus Torvalds 
43389bddce5SStephen Hemminger 	file = fget(fd);
43489bddce5SStephen Hemminger 	if (!file) {
4351da177e4SLinus Torvalds 		*err = -EBADF;
4361da177e4SLinus Torvalds 		return NULL;
4371da177e4SLinus Torvalds 	}
43889bddce5SStephen Hemminger 
4396cb153caSBenjamin LaHaise 	sock = sock_from_file(file, err);
4406cb153caSBenjamin LaHaise 	if (!sock)
4411da177e4SLinus Torvalds 		fput(file);
4426cb153caSBenjamin LaHaise 	return sock;
4431da177e4SLinus Torvalds }
444c6d409cfSEric Dumazet EXPORT_SYMBOL(sockfd_lookup);
4451da177e4SLinus Torvalds 
4466cb153caSBenjamin LaHaise static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
4476cb153caSBenjamin LaHaise {
4486cb153caSBenjamin LaHaise 	struct file *file;
4496cb153caSBenjamin LaHaise 	struct socket *sock;
4506cb153caSBenjamin LaHaise 
4513672558cSHua Zhong 	*err = -EBADF;
4526cb153caSBenjamin LaHaise 	file = fget_light(fd, fput_needed);
4536cb153caSBenjamin LaHaise 	if (file) {
4546cb153caSBenjamin LaHaise 		sock = sock_from_file(file, err);
4556cb153caSBenjamin LaHaise 		if (sock)
4561da177e4SLinus Torvalds 			return sock;
4576cb153caSBenjamin LaHaise 		fput_light(file, *fput_needed);
4586cb153caSBenjamin LaHaise 	}
4596cb153caSBenjamin LaHaise 	return NULL;
4601da177e4SLinus Torvalds }
4611da177e4SLinus Torvalds 
4621da177e4SLinus Torvalds /**
4631da177e4SLinus Torvalds  *	sock_alloc	-	allocate a socket
4641da177e4SLinus Torvalds  *
4651da177e4SLinus Torvalds  *	Allocate a new inode and socket object. The two are bound together
4661da177e4SLinus Torvalds  *	and initialised. The socket is then returned. If we are out of inodes
4671da177e4SLinus Torvalds  *	NULL is returned.
4681da177e4SLinus Torvalds  */
4691da177e4SLinus Torvalds 
4701da177e4SLinus Torvalds static struct socket *sock_alloc(void)
4711da177e4SLinus Torvalds {
4721da177e4SLinus Torvalds 	struct inode *inode;
4731da177e4SLinus Torvalds 	struct socket *sock;
4741da177e4SLinus Torvalds 
4751da177e4SLinus Torvalds 	inode = new_inode(sock_mnt->mnt_sb);
4761da177e4SLinus Torvalds 	if (!inode)
4771da177e4SLinus Torvalds 		return NULL;
4781da177e4SLinus Torvalds 
4791da177e4SLinus Torvalds 	sock = SOCKET_I(inode);
4801da177e4SLinus Torvalds 
48129a020d3SEric Dumazet 	kmemcheck_annotate_bitfield(sock, type);
48285fe4025SChristoph Hellwig 	inode->i_ino = get_next_ino();
4831da177e4SLinus Torvalds 	inode->i_mode = S_IFSOCK | S_IRWXUGO;
4848192b0c4SDavid Howells 	inode->i_uid = current_fsuid();
4858192b0c4SDavid Howells 	inode->i_gid = current_fsgid();
4861da177e4SLinus Torvalds 
4874e69489aSEric Dumazet 	percpu_add(sockets_in_use, 1);
4881da177e4SLinus Torvalds 	return sock;
4891da177e4SLinus Torvalds }
4901da177e4SLinus Torvalds 
4911da177e4SLinus Torvalds /*
4921da177e4SLinus Torvalds  *	In theory you can't get an open on this inode, but /proc provides
4931da177e4SLinus Torvalds  *	a back door. Remember to keep it shut otherwise you'll let the
4941da177e4SLinus Torvalds  *	creepy crawlies in.
4951da177e4SLinus Torvalds  */
4961da177e4SLinus Torvalds 
4971da177e4SLinus Torvalds static int sock_no_open(struct inode *irrelevant, struct file *dontcare)
4981da177e4SLinus Torvalds {
4991da177e4SLinus Torvalds 	return -ENXIO;
5001da177e4SLinus Torvalds }
5011da177e4SLinus Torvalds 
5024b6f5d20SArjan van de Ven const struct file_operations bad_sock_fops = {
5031da177e4SLinus Torvalds 	.owner = THIS_MODULE,
5041da177e4SLinus Torvalds 	.open = sock_no_open,
5056038f373SArnd Bergmann 	.llseek = noop_llseek,
5061da177e4SLinus Torvalds };
5071da177e4SLinus Torvalds 
5081da177e4SLinus Torvalds /**
5091da177e4SLinus Torvalds  *	sock_release	-	close a socket
5101da177e4SLinus Torvalds  *	@sock: socket to close
5111da177e4SLinus Torvalds  *
5121da177e4SLinus Torvalds  *	The socket is released from the protocol stack if it has a release
5131da177e4SLinus Torvalds  *	callback, and the inode is then released if the socket is bound to
5141da177e4SLinus Torvalds  *	an inode not a file.
5151da177e4SLinus Torvalds  */
5161da177e4SLinus Torvalds 
5171da177e4SLinus Torvalds void sock_release(struct socket *sock)
5181da177e4SLinus Torvalds {
5191da177e4SLinus Torvalds 	if (sock->ops) {
5201da177e4SLinus Torvalds 		struct module *owner = sock->ops->owner;
5211da177e4SLinus Torvalds 
5221da177e4SLinus Torvalds 		sock->ops->release(sock);
5231da177e4SLinus Torvalds 		sock->ops = NULL;
5241da177e4SLinus Torvalds 		module_put(owner);
5251da177e4SLinus Torvalds 	}
5261da177e4SLinus Torvalds 
52743815482SEric Dumazet 	if (sock->wq->fasync_list)
5281da177e4SLinus Torvalds 		printk(KERN_ERR "sock_release: fasync list not empty!\n");
5291da177e4SLinus Torvalds 
5304e69489aSEric Dumazet 	percpu_sub(sockets_in_use, 1);
5311da177e4SLinus Torvalds 	if (!sock->file) {
5321da177e4SLinus Torvalds 		iput(SOCK_INODE(sock));
5331da177e4SLinus Torvalds 		return;
5341da177e4SLinus Torvalds 	}
5351da177e4SLinus Torvalds 	sock->file = NULL;
5361da177e4SLinus Torvalds }
537c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_release);
5381da177e4SLinus Torvalds 
5392244d07bSOliver Hartkopp int sock_tx_timestamp(struct sock *sk, __u8 *tx_flags)
54020d49473SPatrick Ohly {
5412244d07bSOliver Hartkopp 	*tx_flags = 0;
54220d49473SPatrick Ohly 	if (sock_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE))
5432244d07bSOliver Hartkopp 		*tx_flags |= SKBTX_HW_TSTAMP;
54420d49473SPatrick Ohly 	if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE))
5452244d07bSOliver Hartkopp 		*tx_flags |= SKBTX_SW_TSTAMP;
54620d49473SPatrick Ohly 	return 0;
54720d49473SPatrick Ohly }
54820d49473SPatrick Ohly EXPORT_SYMBOL(sock_tx_timestamp);
54920d49473SPatrick Ohly 
5501da177e4SLinus Torvalds static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock,
5511da177e4SLinus Torvalds 				 struct msghdr *msg, size_t size)
5521da177e4SLinus Torvalds {
5531da177e4SLinus Torvalds 	struct sock_iocb *si = kiocb_to_siocb(iocb);
5541da177e4SLinus Torvalds 	int err;
5551da177e4SLinus Torvalds 
556f8451725SHerbert Xu 	sock_update_classid(sock->sk);
557f8451725SHerbert Xu 
5581da177e4SLinus Torvalds 	si->sock = sock;
5591da177e4SLinus Torvalds 	si->scm = NULL;
5601da177e4SLinus Torvalds 	si->msg = msg;
5611da177e4SLinus Torvalds 	si->size = size;
5621da177e4SLinus Torvalds 
5631da177e4SLinus Torvalds 	err = security_socket_sendmsg(sock, msg, size);
5641da177e4SLinus Torvalds 	if (err)
5651da177e4SLinus Torvalds 		return err;
5661da177e4SLinus Torvalds 
5671da177e4SLinus Torvalds 	return sock->ops->sendmsg(iocb, sock, msg, size);
5681da177e4SLinus Torvalds }
5691da177e4SLinus Torvalds 
5701da177e4SLinus Torvalds int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
5711da177e4SLinus Torvalds {
5721da177e4SLinus Torvalds 	struct kiocb iocb;
5731da177e4SLinus Torvalds 	struct sock_iocb siocb;
5741da177e4SLinus Torvalds 	int ret;
5751da177e4SLinus Torvalds 
5761da177e4SLinus Torvalds 	init_sync_kiocb(&iocb, NULL);
5771da177e4SLinus Torvalds 	iocb.private = &siocb;
5781da177e4SLinus Torvalds 	ret = __sock_sendmsg(&iocb, sock, msg, size);
5791da177e4SLinus Torvalds 	if (-EIOCBQUEUED == ret)
5801da177e4SLinus Torvalds 		ret = wait_on_sync_kiocb(&iocb);
5811da177e4SLinus Torvalds 	return ret;
5821da177e4SLinus Torvalds }
583c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_sendmsg);
5841da177e4SLinus Torvalds 
5851da177e4SLinus Torvalds int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
5861da177e4SLinus Torvalds 		   struct kvec *vec, size_t num, size_t size)
5871da177e4SLinus Torvalds {
5881da177e4SLinus Torvalds 	mm_segment_t oldfs = get_fs();
5891da177e4SLinus Torvalds 	int result;
5901da177e4SLinus Torvalds 
5911da177e4SLinus Torvalds 	set_fs(KERNEL_DS);
5921da177e4SLinus Torvalds 	/*
5931da177e4SLinus Torvalds 	 * the following is safe, since for compiler definitions of kvec and
5941da177e4SLinus Torvalds 	 * iovec are identical, yielding the same in-core layout and alignment
5951da177e4SLinus Torvalds 	 */
59689bddce5SStephen Hemminger 	msg->msg_iov = (struct iovec *)vec;
5971da177e4SLinus Torvalds 	msg->msg_iovlen = num;
5981da177e4SLinus Torvalds 	result = sock_sendmsg(sock, msg, size);
5991da177e4SLinus Torvalds 	set_fs(oldfs);
6001da177e4SLinus Torvalds 	return result;
6011da177e4SLinus Torvalds }
602c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendmsg);
6031da177e4SLinus Torvalds 
60420d49473SPatrick Ohly static int ktime2ts(ktime_t kt, struct timespec *ts)
60520d49473SPatrick Ohly {
60620d49473SPatrick Ohly 	if (kt.tv64) {
60720d49473SPatrick Ohly 		*ts = ktime_to_timespec(kt);
60820d49473SPatrick Ohly 		return 1;
60920d49473SPatrick Ohly 	} else {
61020d49473SPatrick Ohly 		return 0;
61120d49473SPatrick Ohly 	}
61220d49473SPatrick Ohly }
61320d49473SPatrick Ohly 
61492f37fd2SEric Dumazet /*
61592f37fd2SEric Dumazet  * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
61692f37fd2SEric Dumazet  */
61792f37fd2SEric Dumazet void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
61892f37fd2SEric Dumazet 	struct sk_buff *skb)
61992f37fd2SEric Dumazet {
62020d49473SPatrick Ohly 	int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
62120d49473SPatrick Ohly 	struct timespec ts[3];
62220d49473SPatrick Ohly 	int empty = 1;
62320d49473SPatrick Ohly 	struct skb_shared_hwtstamps *shhwtstamps =
62420d49473SPatrick Ohly 		skb_hwtstamps(skb);
62592f37fd2SEric Dumazet 
62620d49473SPatrick Ohly 	/* Race occurred between timestamp enabling and packet
62720d49473SPatrick Ohly 	   receiving.  Fill in the current time for now. */
62820d49473SPatrick Ohly 	if (need_software_tstamp && skb->tstamp.tv64 == 0)
62920d49473SPatrick Ohly 		__net_timestamp(skb);
63020d49473SPatrick Ohly 
63120d49473SPatrick Ohly 	if (need_software_tstamp) {
63292f37fd2SEric Dumazet 		if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
63392f37fd2SEric Dumazet 			struct timeval tv;
63420d49473SPatrick Ohly 			skb_get_timestamp(skb, &tv);
63520d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP,
63620d49473SPatrick Ohly 				 sizeof(tv), &tv);
63792f37fd2SEric Dumazet 		} else {
638842509b8SHagen Paul Pfeifer 			skb_get_timestampns(skb, &ts[0]);
63920d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS,
640842509b8SHagen Paul Pfeifer 				 sizeof(ts[0]), &ts[0]);
64192f37fd2SEric Dumazet 		}
64292f37fd2SEric Dumazet 	}
64392f37fd2SEric Dumazet 
64420d49473SPatrick Ohly 
64520d49473SPatrick Ohly 	memset(ts, 0, sizeof(ts));
64620d49473SPatrick Ohly 	if (skb->tstamp.tv64 &&
64720d49473SPatrick Ohly 	    sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE)) {
64820d49473SPatrick Ohly 		skb_get_timestampns(skb, ts + 0);
64920d49473SPatrick Ohly 		empty = 0;
65020d49473SPatrick Ohly 	}
65120d49473SPatrick Ohly 	if (shhwtstamps) {
65220d49473SPatrick Ohly 		if (sock_flag(sk, SOCK_TIMESTAMPING_SYS_HARDWARE) &&
65320d49473SPatrick Ohly 		    ktime2ts(shhwtstamps->syststamp, ts + 1))
65420d49473SPatrick Ohly 			empty = 0;
65520d49473SPatrick Ohly 		if (sock_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE) &&
65620d49473SPatrick Ohly 		    ktime2ts(shhwtstamps->hwtstamp, ts + 2))
65720d49473SPatrick Ohly 			empty = 0;
65820d49473SPatrick Ohly 	}
65920d49473SPatrick Ohly 	if (!empty)
66020d49473SPatrick Ohly 		put_cmsg(msg, SOL_SOCKET,
66120d49473SPatrick Ohly 			 SCM_TIMESTAMPING, sizeof(ts), &ts);
66220d49473SPatrick Ohly }
6637c81fd8bSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
6647c81fd8bSArnaldo Carvalho de Melo 
66511165f14Sstephen hemminger static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk,
66611165f14Sstephen hemminger 				   struct sk_buff *skb)
6673b885787SNeil Horman {
6683b885787SNeil Horman 	if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && skb->dropcount)
6693b885787SNeil Horman 		put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL,
6703b885787SNeil Horman 			sizeof(__u32), &skb->dropcount);
6713b885787SNeil Horman }
6723b885787SNeil Horman 
673767dd033SEric Dumazet void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
6743b885787SNeil Horman 	struct sk_buff *skb)
6753b885787SNeil Horman {
6763b885787SNeil Horman 	sock_recv_timestamp(msg, sk, skb);
6773b885787SNeil Horman 	sock_recv_drops(msg, sk, skb);
6783b885787SNeil Horman }
679767dd033SEric Dumazet EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops);
6803b885787SNeil Horman 
681a2e27255SArnaldo Carvalho de Melo static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock,
6821da177e4SLinus Torvalds 				       struct msghdr *msg, size_t size, int flags)
6831da177e4SLinus Torvalds {
6841da177e4SLinus Torvalds 	struct sock_iocb *si = kiocb_to_siocb(iocb);
6851da177e4SLinus Torvalds 
686f8451725SHerbert Xu 	sock_update_classid(sock->sk);
687f8451725SHerbert Xu 
6881da177e4SLinus Torvalds 	si->sock = sock;
6891da177e4SLinus Torvalds 	si->scm = NULL;
6901da177e4SLinus Torvalds 	si->msg = msg;
6911da177e4SLinus Torvalds 	si->size = size;
6921da177e4SLinus Torvalds 	si->flags = flags;
6931da177e4SLinus Torvalds 
6941da177e4SLinus Torvalds 	return sock->ops->recvmsg(iocb, sock, msg, size, flags);
6951da177e4SLinus Torvalds }
6961da177e4SLinus Torvalds 
697a2e27255SArnaldo Carvalho de Melo static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock,
698a2e27255SArnaldo Carvalho de Melo 				 struct msghdr *msg, size_t size, int flags)
699a2e27255SArnaldo Carvalho de Melo {
700a2e27255SArnaldo Carvalho de Melo 	int err = security_socket_recvmsg(sock, msg, size, flags);
701a2e27255SArnaldo Carvalho de Melo 
702a2e27255SArnaldo Carvalho de Melo 	return err ?: __sock_recvmsg_nosec(iocb, sock, msg, size, flags);
703a2e27255SArnaldo Carvalho de Melo }
704a2e27255SArnaldo Carvalho de Melo 
7051da177e4SLinus Torvalds int sock_recvmsg(struct socket *sock, struct msghdr *msg,
7061da177e4SLinus Torvalds 		 size_t size, int flags)
7071da177e4SLinus Torvalds {
7081da177e4SLinus Torvalds 	struct kiocb iocb;
7091da177e4SLinus Torvalds 	struct sock_iocb siocb;
7101da177e4SLinus Torvalds 	int ret;
7111da177e4SLinus Torvalds 
7121da177e4SLinus Torvalds 	init_sync_kiocb(&iocb, NULL);
7131da177e4SLinus Torvalds 	iocb.private = &siocb;
7141da177e4SLinus Torvalds 	ret = __sock_recvmsg(&iocb, sock, msg, size, flags);
7151da177e4SLinus Torvalds 	if (-EIOCBQUEUED == ret)
7161da177e4SLinus Torvalds 		ret = wait_on_sync_kiocb(&iocb);
7171da177e4SLinus Torvalds 	return ret;
7181da177e4SLinus Torvalds }
719c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_recvmsg);
7201da177e4SLinus Torvalds 
721a2e27255SArnaldo Carvalho de Melo static int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
722a2e27255SArnaldo Carvalho de Melo 			      size_t size, int flags)
723a2e27255SArnaldo Carvalho de Melo {
724a2e27255SArnaldo Carvalho de Melo 	struct kiocb iocb;
725a2e27255SArnaldo Carvalho de Melo 	struct sock_iocb siocb;
726a2e27255SArnaldo Carvalho de Melo 	int ret;
727a2e27255SArnaldo Carvalho de Melo 
728a2e27255SArnaldo Carvalho de Melo 	init_sync_kiocb(&iocb, NULL);
729a2e27255SArnaldo Carvalho de Melo 	iocb.private = &siocb;
730a2e27255SArnaldo Carvalho de Melo 	ret = __sock_recvmsg_nosec(&iocb, sock, msg, size, flags);
731a2e27255SArnaldo Carvalho de Melo 	if (-EIOCBQUEUED == ret)
732a2e27255SArnaldo Carvalho de Melo 		ret = wait_on_sync_kiocb(&iocb);
733a2e27255SArnaldo Carvalho de Melo 	return ret;
734a2e27255SArnaldo Carvalho de Melo }
735a2e27255SArnaldo Carvalho de Melo 
736c1249c0aSMartin Lucina /**
737c1249c0aSMartin Lucina  * kernel_recvmsg - Receive a message from a socket (kernel space)
738c1249c0aSMartin Lucina  * @sock:       The socket to receive the message from
739c1249c0aSMartin Lucina  * @msg:        Received message
740c1249c0aSMartin Lucina  * @vec:        Input s/g array for message data
741c1249c0aSMartin Lucina  * @num:        Size of input s/g array
742c1249c0aSMartin Lucina  * @size:       Number of bytes to read
743c1249c0aSMartin Lucina  * @flags:      Message flags (MSG_DONTWAIT, etc...)
744c1249c0aSMartin Lucina  *
745c1249c0aSMartin Lucina  * On return the msg structure contains the scatter/gather array passed in the
746c1249c0aSMartin Lucina  * vec argument. The array is modified so that it consists of the unfilled
747c1249c0aSMartin Lucina  * portion of the original array.
748c1249c0aSMartin Lucina  *
749c1249c0aSMartin Lucina  * The returned value is the total number of bytes received, or an error.
750c1249c0aSMartin Lucina  */
7511da177e4SLinus Torvalds int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
75289bddce5SStephen Hemminger 		   struct kvec *vec, size_t num, size_t size, int flags)
7531da177e4SLinus Torvalds {
7541da177e4SLinus Torvalds 	mm_segment_t oldfs = get_fs();
7551da177e4SLinus Torvalds 	int result;
7561da177e4SLinus Torvalds 
7571da177e4SLinus Torvalds 	set_fs(KERNEL_DS);
7581da177e4SLinus Torvalds 	/*
7591da177e4SLinus Torvalds 	 * the following is safe, since for compiler definitions of kvec and
7601da177e4SLinus Torvalds 	 * iovec are identical, yielding the same in-core layout and alignment
7611da177e4SLinus Torvalds 	 */
76289bddce5SStephen Hemminger 	msg->msg_iov = (struct iovec *)vec, msg->msg_iovlen = num;
7631da177e4SLinus Torvalds 	result = sock_recvmsg(sock, msg, size, flags);
7641da177e4SLinus Torvalds 	set_fs(oldfs);
7651da177e4SLinus Torvalds 	return result;
7661da177e4SLinus Torvalds }
767c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_recvmsg);
7681da177e4SLinus Torvalds 
7691da177e4SLinus Torvalds static void sock_aio_dtor(struct kiocb *iocb)
7701da177e4SLinus Torvalds {
7711da177e4SLinus Torvalds 	kfree(iocb->private);
7721da177e4SLinus Torvalds }
7731da177e4SLinus Torvalds 
77420380731SArnaldo Carvalho de Melo static ssize_t sock_sendpage(struct file *file, struct page *page,
7751da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more)
7761da177e4SLinus Torvalds {
7771da177e4SLinus Torvalds 	struct socket *sock;
7781da177e4SLinus Torvalds 	int flags;
7791da177e4SLinus Torvalds 
780b69aee04SEric Dumazet 	sock = file->private_data;
7811da177e4SLinus Torvalds 
7821da177e4SLinus Torvalds 	flags = !(file->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT;
7831da177e4SLinus Torvalds 	if (more)
7841da177e4SLinus Torvalds 		flags |= MSG_MORE;
7851da177e4SLinus Torvalds 
786e6949583SLinus Torvalds 	return kernel_sendpage(sock, page, offset, size, flags);
7871da177e4SLinus Torvalds }
7881da177e4SLinus Torvalds 
7899c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
7909c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
7919c55e01cSJens Axboe 				unsigned int flags)
7929c55e01cSJens Axboe {
7939c55e01cSJens Axboe 	struct socket *sock = file->private_data;
7949c55e01cSJens Axboe 
795997b37daSRémi Denis-Courmont 	if (unlikely(!sock->ops->splice_read))
796997b37daSRémi Denis-Courmont 		return -EINVAL;
797997b37daSRémi Denis-Courmont 
798f8451725SHerbert Xu 	sock_update_classid(sock->sk);
799f8451725SHerbert Xu 
8009c55e01cSJens Axboe 	return sock->ops->splice_read(sock, ppos, pipe, len, flags);
8019c55e01cSJens Axboe }
8029c55e01cSJens Axboe 
803ce1d4d3eSChristoph Hellwig static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
80489bddce5SStephen Hemminger 					 struct sock_iocb *siocb)
805ce1d4d3eSChristoph Hellwig {
806ce1d4d3eSChristoph Hellwig 	if (!is_sync_kiocb(iocb)) {
807ce1d4d3eSChristoph Hellwig 		siocb = kmalloc(sizeof(*siocb), GFP_KERNEL);
808ce1d4d3eSChristoph Hellwig 		if (!siocb)
809ce1d4d3eSChristoph Hellwig 			return NULL;
810ce1d4d3eSChristoph Hellwig 		iocb->ki_dtor = sock_aio_dtor;
811ce1d4d3eSChristoph Hellwig 	}
812ce1d4d3eSChristoph Hellwig 
813ce1d4d3eSChristoph Hellwig 	siocb->kiocb = iocb;
814ce1d4d3eSChristoph Hellwig 	iocb->private = siocb;
815ce1d4d3eSChristoph Hellwig 	return siocb;
816ce1d4d3eSChristoph Hellwig }
817ce1d4d3eSChristoph Hellwig 
818ce1d4d3eSChristoph Hellwig static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb,
819027445c3SBadari Pulavarty 		struct file *file, const struct iovec *iov,
82089bddce5SStephen Hemminger 		unsigned long nr_segs)
821ce1d4d3eSChristoph Hellwig {
822ce1d4d3eSChristoph Hellwig 	struct socket *sock = file->private_data;
823ce1d4d3eSChristoph Hellwig 	size_t size = 0;
824ce1d4d3eSChristoph Hellwig 	int i;
825ce1d4d3eSChristoph Hellwig 
826ce1d4d3eSChristoph Hellwig 	for (i = 0; i < nr_segs; i++)
827ce1d4d3eSChristoph Hellwig 		size += iov[i].iov_len;
828ce1d4d3eSChristoph Hellwig 
829ce1d4d3eSChristoph Hellwig 	msg->msg_name = NULL;
830ce1d4d3eSChristoph Hellwig 	msg->msg_namelen = 0;
831ce1d4d3eSChristoph Hellwig 	msg->msg_control = NULL;
832ce1d4d3eSChristoph Hellwig 	msg->msg_controllen = 0;
833ce1d4d3eSChristoph Hellwig 	msg->msg_iov = (struct iovec *)iov;
834ce1d4d3eSChristoph Hellwig 	msg->msg_iovlen = nr_segs;
835ce1d4d3eSChristoph Hellwig 	msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
836ce1d4d3eSChristoph Hellwig 
837ce1d4d3eSChristoph Hellwig 	return __sock_recvmsg(iocb, sock, msg, size, msg->msg_flags);
838ce1d4d3eSChristoph Hellwig }
839ce1d4d3eSChristoph Hellwig 
840027445c3SBadari Pulavarty static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
841027445c3SBadari Pulavarty 				unsigned long nr_segs, loff_t pos)
842ce1d4d3eSChristoph Hellwig {
843ce1d4d3eSChristoph Hellwig 	struct sock_iocb siocb, *x;
844ce1d4d3eSChristoph Hellwig 
845ce1d4d3eSChristoph Hellwig 	if (pos != 0)
846ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
847027445c3SBadari Pulavarty 
848027445c3SBadari Pulavarty 	if (iocb->ki_left == 0)	/* Match SYS5 behaviour */
849ce1d4d3eSChristoph Hellwig 		return 0;
850ce1d4d3eSChristoph Hellwig 
851027445c3SBadari Pulavarty 
852027445c3SBadari Pulavarty 	x = alloc_sock_iocb(iocb, &siocb);
853ce1d4d3eSChristoph Hellwig 	if (!x)
854ce1d4d3eSChristoph Hellwig 		return -ENOMEM;
855027445c3SBadari Pulavarty 	return do_sock_read(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
856ce1d4d3eSChristoph Hellwig }
857ce1d4d3eSChristoph Hellwig 
858ce1d4d3eSChristoph Hellwig static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb,
859027445c3SBadari Pulavarty 			struct file *file, const struct iovec *iov,
86089bddce5SStephen Hemminger 			unsigned long nr_segs)
861ce1d4d3eSChristoph Hellwig {
862ce1d4d3eSChristoph Hellwig 	struct socket *sock = file->private_data;
863ce1d4d3eSChristoph Hellwig 	size_t size = 0;
864ce1d4d3eSChristoph Hellwig 	int i;
865ce1d4d3eSChristoph Hellwig 
866ce1d4d3eSChristoph Hellwig 	for (i = 0; i < nr_segs; i++)
867ce1d4d3eSChristoph Hellwig 		size += iov[i].iov_len;
868ce1d4d3eSChristoph Hellwig 
869ce1d4d3eSChristoph Hellwig 	msg->msg_name = NULL;
870ce1d4d3eSChristoph Hellwig 	msg->msg_namelen = 0;
871ce1d4d3eSChristoph Hellwig 	msg->msg_control = NULL;
872ce1d4d3eSChristoph Hellwig 	msg->msg_controllen = 0;
873ce1d4d3eSChristoph Hellwig 	msg->msg_iov = (struct iovec *)iov;
874ce1d4d3eSChristoph Hellwig 	msg->msg_iovlen = nr_segs;
875ce1d4d3eSChristoph Hellwig 	msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
876ce1d4d3eSChristoph Hellwig 	if (sock->type == SOCK_SEQPACKET)
877ce1d4d3eSChristoph Hellwig 		msg->msg_flags |= MSG_EOR;
878ce1d4d3eSChristoph Hellwig 
879ce1d4d3eSChristoph Hellwig 	return __sock_sendmsg(iocb, sock, msg, size);
880ce1d4d3eSChristoph Hellwig }
881ce1d4d3eSChristoph Hellwig 
882027445c3SBadari Pulavarty static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
883027445c3SBadari Pulavarty 			  unsigned long nr_segs, loff_t pos)
8841da177e4SLinus Torvalds {
885ce1d4d3eSChristoph Hellwig 	struct sock_iocb siocb, *x;
8861da177e4SLinus Torvalds 
887ce1d4d3eSChristoph Hellwig 	if (pos != 0)
888ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
889027445c3SBadari Pulavarty 
890027445c3SBadari Pulavarty 	x = alloc_sock_iocb(iocb, &siocb);
891ce1d4d3eSChristoph Hellwig 	if (!x)
892ce1d4d3eSChristoph Hellwig 		return -ENOMEM;
893ce1d4d3eSChristoph Hellwig 
894027445c3SBadari Pulavarty 	return do_sock_write(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
8951da177e4SLinus Torvalds }
8961da177e4SLinus Torvalds 
8971da177e4SLinus Torvalds /*
8981da177e4SLinus Torvalds  * Atomic setting of ioctl hooks to avoid race
8991da177e4SLinus Torvalds  * with module unload.
9001da177e4SLinus Torvalds  */
9011da177e4SLinus Torvalds 
9024a3e2f71SArjan van de Ven static DEFINE_MUTEX(br_ioctl_mutex);
903c6d409cfSEric Dumazet static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg);
9041da177e4SLinus Torvalds 
905881d966bSEric W. Biederman void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *))
9061da177e4SLinus Torvalds {
9074a3e2f71SArjan van de Ven 	mutex_lock(&br_ioctl_mutex);
9081da177e4SLinus Torvalds 	br_ioctl_hook = hook;
9094a3e2f71SArjan van de Ven 	mutex_unlock(&br_ioctl_mutex);
9101da177e4SLinus Torvalds }
9111da177e4SLinus Torvalds EXPORT_SYMBOL(brioctl_set);
9121da177e4SLinus Torvalds 
9134a3e2f71SArjan van de Ven static DEFINE_MUTEX(vlan_ioctl_mutex);
914881d966bSEric W. Biederman static int (*vlan_ioctl_hook) (struct net *, void __user *arg);
9151da177e4SLinus Torvalds 
916881d966bSEric W. Biederman void vlan_ioctl_set(int (*hook) (struct net *, void __user *))
9171da177e4SLinus Torvalds {
9184a3e2f71SArjan van de Ven 	mutex_lock(&vlan_ioctl_mutex);
9191da177e4SLinus Torvalds 	vlan_ioctl_hook = hook;
9204a3e2f71SArjan van de Ven 	mutex_unlock(&vlan_ioctl_mutex);
9211da177e4SLinus Torvalds }
9221da177e4SLinus Torvalds EXPORT_SYMBOL(vlan_ioctl_set);
9231da177e4SLinus Torvalds 
9244a3e2f71SArjan van de Ven static DEFINE_MUTEX(dlci_ioctl_mutex);
9251da177e4SLinus Torvalds static int (*dlci_ioctl_hook) (unsigned int, void __user *);
9261da177e4SLinus Torvalds 
9271da177e4SLinus Torvalds void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
9281da177e4SLinus Torvalds {
9294a3e2f71SArjan van de Ven 	mutex_lock(&dlci_ioctl_mutex);
9301da177e4SLinus Torvalds 	dlci_ioctl_hook = hook;
9314a3e2f71SArjan van de Ven 	mutex_unlock(&dlci_ioctl_mutex);
9321da177e4SLinus Torvalds }
9331da177e4SLinus Torvalds EXPORT_SYMBOL(dlci_ioctl_set);
9341da177e4SLinus Torvalds 
9356b96018bSArnd Bergmann static long sock_do_ioctl(struct net *net, struct socket *sock,
9366b96018bSArnd Bergmann 				 unsigned int cmd, unsigned long arg)
9376b96018bSArnd Bergmann {
9386b96018bSArnd Bergmann 	int err;
9396b96018bSArnd Bergmann 	void __user *argp = (void __user *)arg;
9406b96018bSArnd Bergmann 
9416b96018bSArnd Bergmann 	err = sock->ops->ioctl(sock, cmd, arg);
9426b96018bSArnd Bergmann 
9436b96018bSArnd Bergmann 	/*
9446b96018bSArnd Bergmann 	 * If this ioctl is unknown try to hand it down
9456b96018bSArnd Bergmann 	 * to the NIC driver.
9466b96018bSArnd Bergmann 	 */
9476b96018bSArnd Bergmann 	if (err == -ENOIOCTLCMD)
9486b96018bSArnd Bergmann 		err = dev_ioctl(net, cmd, argp);
9496b96018bSArnd Bergmann 
9506b96018bSArnd Bergmann 	return err;
9516b96018bSArnd Bergmann }
9526b96018bSArnd Bergmann 
9531da177e4SLinus Torvalds /*
9541da177e4SLinus Torvalds  *	With an ioctl, arg may well be a user mode pointer, but we don't know
9551da177e4SLinus Torvalds  *	what to do with it - that's up to the protocol still.
9561da177e4SLinus Torvalds  */
9571da177e4SLinus Torvalds 
9581da177e4SLinus Torvalds static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
9591da177e4SLinus Torvalds {
9601da177e4SLinus Torvalds 	struct socket *sock;
961881d966bSEric W. Biederman 	struct sock *sk;
9621da177e4SLinus Torvalds 	void __user *argp = (void __user *)arg;
9631da177e4SLinus Torvalds 	int pid, err;
964881d966bSEric W. Biederman 	struct net *net;
9651da177e4SLinus Torvalds 
966b69aee04SEric Dumazet 	sock = file->private_data;
967881d966bSEric W. Biederman 	sk = sock->sk;
9683b1e0a65SYOSHIFUJI Hideaki 	net = sock_net(sk);
9691da177e4SLinus Torvalds 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
970881d966bSEric W. Biederman 		err = dev_ioctl(net, cmd, argp);
9711da177e4SLinus Torvalds 	} else
9723d23e349SJohannes Berg #ifdef CONFIG_WEXT_CORE
9731da177e4SLinus Torvalds 	if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
974881d966bSEric W. Biederman 		err = dev_ioctl(net, cmd, argp);
9751da177e4SLinus Torvalds 	} else
9763d23e349SJohannes Berg #endif
9771da177e4SLinus Torvalds 		switch (cmd) {
9781da177e4SLinus Torvalds 		case FIOSETOWN:
9791da177e4SLinus Torvalds 		case SIOCSPGRP:
9801da177e4SLinus Torvalds 			err = -EFAULT;
9811da177e4SLinus Torvalds 			if (get_user(pid, (int __user *)argp))
9821da177e4SLinus Torvalds 				break;
9831da177e4SLinus Torvalds 			err = f_setown(sock->file, pid, 1);
9841da177e4SLinus Torvalds 			break;
9851da177e4SLinus Torvalds 		case FIOGETOWN:
9861da177e4SLinus Torvalds 		case SIOCGPGRP:
987609d7fa9SEric W. Biederman 			err = put_user(f_getown(sock->file),
98889bddce5SStephen Hemminger 				       (int __user *)argp);
9891da177e4SLinus Torvalds 			break;
9901da177e4SLinus Torvalds 		case SIOCGIFBR:
9911da177e4SLinus Torvalds 		case SIOCSIFBR:
9921da177e4SLinus Torvalds 		case SIOCBRADDBR:
9931da177e4SLinus Torvalds 		case SIOCBRDELBR:
9941da177e4SLinus Torvalds 			err = -ENOPKG;
9951da177e4SLinus Torvalds 			if (!br_ioctl_hook)
9961da177e4SLinus Torvalds 				request_module("bridge");
9971da177e4SLinus Torvalds 
9984a3e2f71SArjan van de Ven 			mutex_lock(&br_ioctl_mutex);
9991da177e4SLinus Torvalds 			if (br_ioctl_hook)
1000881d966bSEric W. Biederman 				err = br_ioctl_hook(net, cmd, argp);
10014a3e2f71SArjan van de Ven 			mutex_unlock(&br_ioctl_mutex);
10021da177e4SLinus Torvalds 			break;
10031da177e4SLinus Torvalds 		case SIOCGIFVLAN:
10041da177e4SLinus Torvalds 		case SIOCSIFVLAN:
10051da177e4SLinus Torvalds 			err = -ENOPKG;
10061da177e4SLinus Torvalds 			if (!vlan_ioctl_hook)
10071da177e4SLinus Torvalds 				request_module("8021q");
10081da177e4SLinus Torvalds 
10094a3e2f71SArjan van de Ven 			mutex_lock(&vlan_ioctl_mutex);
10101da177e4SLinus Torvalds 			if (vlan_ioctl_hook)
1011881d966bSEric W. Biederman 				err = vlan_ioctl_hook(net, argp);
10124a3e2f71SArjan van de Ven 			mutex_unlock(&vlan_ioctl_mutex);
10131da177e4SLinus Torvalds 			break;
10141da177e4SLinus Torvalds 		case SIOCADDDLCI:
10151da177e4SLinus Torvalds 		case SIOCDELDLCI:
10161da177e4SLinus Torvalds 			err = -ENOPKG;
10171da177e4SLinus Torvalds 			if (!dlci_ioctl_hook)
10181da177e4SLinus Torvalds 				request_module("dlci");
10191da177e4SLinus Torvalds 
10204a3e2f71SArjan van de Ven 			mutex_lock(&dlci_ioctl_mutex);
10217512cbf6SPavel Emelyanov 			if (dlci_ioctl_hook)
10221da177e4SLinus Torvalds 				err = dlci_ioctl_hook(cmd, argp);
10234a3e2f71SArjan van de Ven 			mutex_unlock(&dlci_ioctl_mutex);
10241da177e4SLinus Torvalds 			break;
10251da177e4SLinus Torvalds 		default:
10266b96018bSArnd Bergmann 			err = sock_do_ioctl(net, sock, cmd, arg);
10271da177e4SLinus Torvalds 			break;
10281da177e4SLinus Torvalds 		}
10291da177e4SLinus Torvalds 	return err;
10301da177e4SLinus Torvalds }
10311da177e4SLinus Torvalds 
10321da177e4SLinus Torvalds int sock_create_lite(int family, int type, int protocol, struct socket **res)
10331da177e4SLinus Torvalds {
10341da177e4SLinus Torvalds 	int err;
10351da177e4SLinus Torvalds 	struct socket *sock = NULL;
10361da177e4SLinus Torvalds 
10371da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, 1);
10381da177e4SLinus Torvalds 	if (err)
10391da177e4SLinus Torvalds 		goto out;
10401da177e4SLinus Torvalds 
10411da177e4SLinus Torvalds 	sock = sock_alloc();
10421da177e4SLinus Torvalds 	if (!sock) {
10431da177e4SLinus Torvalds 		err = -ENOMEM;
10441da177e4SLinus Torvalds 		goto out;
10451da177e4SLinus Torvalds 	}
10461da177e4SLinus Torvalds 
10471da177e4SLinus Torvalds 	sock->type = type;
10487420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, 1);
10497420ed23SVenkat Yekkirala 	if (err)
10507420ed23SVenkat Yekkirala 		goto out_release;
10517420ed23SVenkat Yekkirala 
10521da177e4SLinus Torvalds out:
10531da177e4SLinus Torvalds 	*res = sock;
10541da177e4SLinus Torvalds 	return err;
10557420ed23SVenkat Yekkirala out_release:
10567420ed23SVenkat Yekkirala 	sock_release(sock);
10577420ed23SVenkat Yekkirala 	sock = NULL;
10587420ed23SVenkat Yekkirala 	goto out;
10591da177e4SLinus Torvalds }
1060c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_lite);
10611da177e4SLinus Torvalds 
10621da177e4SLinus Torvalds /* No kernel lock held - perfect */
10631da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file, poll_table *wait)
10641da177e4SLinus Torvalds {
10651da177e4SLinus Torvalds 	struct socket *sock;
10661da177e4SLinus Torvalds 
10671da177e4SLinus Torvalds 	/*
10681da177e4SLinus Torvalds 	 *      We can't return errors to poll, so it's either yes or no.
10691da177e4SLinus Torvalds 	 */
1070b69aee04SEric Dumazet 	sock = file->private_data;
10711da177e4SLinus Torvalds 	return sock->ops->poll(file, sock, wait);
10721da177e4SLinus Torvalds }
10731da177e4SLinus Torvalds 
10741da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma)
10751da177e4SLinus Torvalds {
1076b69aee04SEric Dumazet 	struct socket *sock = file->private_data;
10771da177e4SLinus Torvalds 
10781da177e4SLinus Torvalds 	return sock->ops->mmap(file, sock, vma);
10791da177e4SLinus Torvalds }
10801da177e4SLinus Torvalds 
108120380731SArnaldo Carvalho de Melo static int sock_close(struct inode *inode, struct file *filp)
10821da177e4SLinus Torvalds {
10831da177e4SLinus Torvalds 	/*
10841da177e4SLinus Torvalds 	 *      It was possible the inode is NULL we were
10851da177e4SLinus Torvalds 	 *      closing an unfinished socket.
10861da177e4SLinus Torvalds 	 */
10871da177e4SLinus Torvalds 
108889bddce5SStephen Hemminger 	if (!inode) {
10891da177e4SLinus Torvalds 		printk(KERN_DEBUG "sock_close: NULL inode\n");
10901da177e4SLinus Torvalds 		return 0;
10911da177e4SLinus Torvalds 	}
10921da177e4SLinus Torvalds 	sock_release(SOCKET_I(inode));
10931da177e4SLinus Torvalds 	return 0;
10941da177e4SLinus Torvalds }
10951da177e4SLinus Torvalds 
10961da177e4SLinus Torvalds /*
10971da177e4SLinus Torvalds  *	Update the socket async list
10981da177e4SLinus Torvalds  *
10991da177e4SLinus Torvalds  *	Fasync_list locking strategy.
11001da177e4SLinus Torvalds  *
11011da177e4SLinus Torvalds  *	1. fasync_list is modified only under process context socket lock
11021da177e4SLinus Torvalds  *	   i.e. under semaphore.
11031da177e4SLinus Torvalds  *	2. fasync_list is used under read_lock(&sk->sk_callback_lock)
1104989a2979SEric Dumazet  *	   or under socket lock
11051da177e4SLinus Torvalds  */
11061da177e4SLinus Torvalds 
11071da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on)
11081da177e4SLinus Torvalds {
1109989a2979SEric Dumazet 	struct socket *sock = filp->private_data;
1110989a2979SEric Dumazet 	struct sock *sk = sock->sk;
11111da177e4SLinus Torvalds 
1112989a2979SEric Dumazet 	if (sk == NULL)
11131da177e4SLinus Torvalds 		return -EINVAL;
11141da177e4SLinus Torvalds 
11151da177e4SLinus Torvalds 	lock_sock(sk);
11161da177e4SLinus Torvalds 
111743815482SEric Dumazet 	fasync_helper(fd, filp, on, &sock->wq->fasync_list);
111876398425SJonathan Corbet 
111943815482SEric Dumazet 	if (!sock->wq->fasync_list)
1120bcdce719SEric Dumazet 		sock_reset_flag(sk, SOCK_FASYNC);
1121989a2979SEric Dumazet 	else
1122989a2979SEric Dumazet 		sock_set_flag(sk, SOCK_FASYNC);
11231da177e4SLinus Torvalds 
1124989a2979SEric Dumazet 	release_sock(sk);
11251da177e4SLinus Torvalds 	return 0;
11261da177e4SLinus Torvalds }
11271da177e4SLinus Torvalds 
112843815482SEric Dumazet /* This function may be called only under socket lock or callback_lock or rcu_lock */
11291da177e4SLinus Torvalds 
11301da177e4SLinus Torvalds int sock_wake_async(struct socket *sock, int how, int band)
11311da177e4SLinus Torvalds {
113243815482SEric Dumazet 	struct socket_wq *wq;
113343815482SEric Dumazet 
113443815482SEric Dumazet 	if (!sock)
11351da177e4SLinus Torvalds 		return -1;
113643815482SEric Dumazet 	rcu_read_lock();
113743815482SEric Dumazet 	wq = rcu_dereference(sock->wq);
113843815482SEric Dumazet 	if (!wq || !wq->fasync_list) {
113943815482SEric Dumazet 		rcu_read_unlock();
114043815482SEric Dumazet 		return -1;
114143815482SEric Dumazet 	}
114289bddce5SStephen Hemminger 	switch (how) {
11438d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_WAITD:
11441da177e4SLinus Torvalds 		if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
11451da177e4SLinus Torvalds 			break;
11461da177e4SLinus Torvalds 		goto call_kill;
11478d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_SPACE:
11481da177e4SLinus Torvalds 		if (!test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags))
11491da177e4SLinus Torvalds 			break;
11501da177e4SLinus Torvalds 		/* fall through */
11518d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_IO:
11521da177e4SLinus Torvalds call_kill:
115343815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGIO, band);
11541da177e4SLinus Torvalds 		break;
11558d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_URG:
115643815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGURG, band);
11571da177e4SLinus Torvalds 	}
115843815482SEric Dumazet 	rcu_read_unlock();
11591da177e4SLinus Torvalds 	return 0;
11601da177e4SLinus Torvalds }
1161c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_wake_async);
11621da177e4SLinus Torvalds 
1163721db93aSPavel Emelyanov int __sock_create(struct net *net, int family, int type, int protocol,
116489bddce5SStephen Hemminger 			 struct socket **res, int kern)
11651da177e4SLinus Torvalds {
11661da177e4SLinus Torvalds 	int err;
11671da177e4SLinus Torvalds 	struct socket *sock;
116855737fdaSStephen Hemminger 	const struct net_proto_family *pf;
11691da177e4SLinus Torvalds 
11701da177e4SLinus Torvalds 	/*
11711da177e4SLinus Torvalds 	 *      Check protocol is in range
11721da177e4SLinus Torvalds 	 */
11731da177e4SLinus Torvalds 	if (family < 0 || family >= NPROTO)
11741da177e4SLinus Torvalds 		return -EAFNOSUPPORT;
11751da177e4SLinus Torvalds 	if (type < 0 || type >= SOCK_MAX)
11761da177e4SLinus Torvalds 		return -EINVAL;
11771da177e4SLinus Torvalds 
11781da177e4SLinus Torvalds 	/* Compatibility.
11791da177e4SLinus Torvalds 
11801da177e4SLinus Torvalds 	   This uglymoron is moved from INET layer to here to avoid
11811da177e4SLinus Torvalds 	   deadlock in module load.
11821da177e4SLinus Torvalds 	 */
11831da177e4SLinus Torvalds 	if (family == PF_INET && type == SOCK_PACKET) {
11841da177e4SLinus Torvalds 		static int warned;
11851da177e4SLinus Torvalds 		if (!warned) {
11861da177e4SLinus Torvalds 			warned = 1;
118789bddce5SStephen Hemminger 			printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)\n",
118889bddce5SStephen Hemminger 			       current->comm);
11891da177e4SLinus Torvalds 		}
11901da177e4SLinus Torvalds 		family = PF_PACKET;
11911da177e4SLinus Torvalds 	}
11921da177e4SLinus Torvalds 
11931da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, kern);
11941da177e4SLinus Torvalds 	if (err)
11951da177e4SLinus Torvalds 		return err;
11961da177e4SLinus Torvalds 
119755737fdaSStephen Hemminger 	/*
119855737fdaSStephen Hemminger 	 *	Allocate the socket and allow the family to set things up. if
119955737fdaSStephen Hemminger 	 *	the protocol is 0, the family is instructed to select an appropriate
120055737fdaSStephen Hemminger 	 *	default.
120155737fdaSStephen Hemminger 	 */
120255737fdaSStephen Hemminger 	sock = sock_alloc();
120355737fdaSStephen Hemminger 	if (!sock) {
120455737fdaSStephen Hemminger 		if (net_ratelimit())
120555737fdaSStephen Hemminger 			printk(KERN_WARNING "socket: no more sockets\n");
120655737fdaSStephen Hemminger 		return -ENFILE;	/* Not exactly a match, but its the
120755737fdaSStephen Hemminger 				   closest posix thing */
120855737fdaSStephen Hemminger 	}
120955737fdaSStephen Hemminger 
121055737fdaSStephen Hemminger 	sock->type = type;
121155737fdaSStephen Hemminger 
121295a5afcaSJohannes Berg #ifdef CONFIG_MODULES
12131da177e4SLinus Torvalds 	/* Attempt to load a protocol module if the find failed.
12141da177e4SLinus Torvalds 	 *
12151da177e4SLinus Torvalds 	 * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
12161da177e4SLinus Torvalds 	 * requested real, full-featured networking support upon configuration.
12171da177e4SLinus Torvalds 	 * Otherwise module support will break!
12181da177e4SLinus Torvalds 	 */
121955737fdaSStephen Hemminger 	if (net_families[family] == NULL)
12201da177e4SLinus Torvalds 		request_module("net-pf-%d", family);
12211da177e4SLinus Torvalds #endif
12221da177e4SLinus Torvalds 
122355737fdaSStephen Hemminger 	rcu_read_lock();
122455737fdaSStephen Hemminger 	pf = rcu_dereference(net_families[family]);
12251da177e4SLinus Torvalds 	err = -EAFNOSUPPORT;
122655737fdaSStephen Hemminger 	if (!pf)
122755737fdaSStephen Hemminger 		goto out_release;
12281da177e4SLinus Torvalds 
12291da177e4SLinus Torvalds 	/*
12301da177e4SLinus Torvalds 	 * We will call the ->create function, that possibly is in a loadable
12311da177e4SLinus Torvalds 	 * module, so we have to bump that loadable module refcnt first.
12321da177e4SLinus Torvalds 	 */
123355737fdaSStephen Hemminger 	if (!try_module_get(pf->owner))
12341da177e4SLinus Torvalds 		goto out_release;
12351da177e4SLinus Torvalds 
123655737fdaSStephen Hemminger 	/* Now protected by module ref count */
123755737fdaSStephen Hemminger 	rcu_read_unlock();
123855737fdaSStephen Hemminger 
12393f378b68SEric Paris 	err = pf->create(net, sock, protocol, kern);
124055737fdaSStephen Hemminger 	if (err < 0)
12411da177e4SLinus Torvalds 		goto out_module_put;
1242a79af59eSFrank Filz 
12431da177e4SLinus Torvalds 	/*
12441da177e4SLinus Torvalds 	 * Now to bump the refcnt of the [loadable] module that owns this
12451da177e4SLinus Torvalds 	 * socket at sock_release time we decrement its refcnt.
12461da177e4SLinus Torvalds 	 */
124755737fdaSStephen Hemminger 	if (!try_module_get(sock->ops->owner))
124855737fdaSStephen Hemminger 		goto out_module_busy;
124955737fdaSStephen Hemminger 
12501da177e4SLinus Torvalds 	/*
12511da177e4SLinus Torvalds 	 * Now that we're done with the ->create function, the [loadable]
12521da177e4SLinus Torvalds 	 * module can have its refcnt decremented
12531da177e4SLinus Torvalds 	 */
125455737fdaSStephen Hemminger 	module_put(pf->owner);
12557420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, kern);
12567420ed23SVenkat Yekkirala 	if (err)
12573b185525SHerbert Xu 		goto out_sock_release;
125855737fdaSStephen Hemminger 	*res = sock;
12591da177e4SLinus Torvalds 
126055737fdaSStephen Hemminger 	return 0;
126155737fdaSStephen Hemminger 
126255737fdaSStephen Hemminger out_module_busy:
126355737fdaSStephen Hemminger 	err = -EAFNOSUPPORT;
12641da177e4SLinus Torvalds out_module_put:
126555737fdaSStephen Hemminger 	sock->ops = NULL;
126655737fdaSStephen Hemminger 	module_put(pf->owner);
126755737fdaSStephen Hemminger out_sock_release:
12681da177e4SLinus Torvalds 	sock_release(sock);
126955737fdaSStephen Hemminger 	return err;
127055737fdaSStephen Hemminger 
127155737fdaSStephen Hemminger out_release:
127255737fdaSStephen Hemminger 	rcu_read_unlock();
127355737fdaSStephen Hemminger 	goto out_sock_release;
12741da177e4SLinus Torvalds }
1275721db93aSPavel Emelyanov EXPORT_SYMBOL(__sock_create);
12761da177e4SLinus Torvalds 
12771da177e4SLinus Torvalds int sock_create(int family, int type, int protocol, struct socket **res)
12781da177e4SLinus Torvalds {
12791b8d7ae4SEric W. Biederman 	return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
12801da177e4SLinus Torvalds }
1281c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create);
12821da177e4SLinus Torvalds 
12831da177e4SLinus Torvalds int sock_create_kern(int family, int type, int protocol, struct socket **res)
12841da177e4SLinus Torvalds {
12851b8d7ae4SEric W. Biederman 	return __sock_create(&init_net, family, type, protocol, res, 1);
12861da177e4SLinus Torvalds }
1287c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_kern);
12881da177e4SLinus Torvalds 
12893e0fa65fSHeiko Carstens SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
12901da177e4SLinus Torvalds {
12911da177e4SLinus Torvalds 	int retval;
12921da177e4SLinus Torvalds 	struct socket *sock;
1293a677a039SUlrich Drepper 	int flags;
1294a677a039SUlrich Drepper 
1295e38b36f3SUlrich Drepper 	/* Check the SOCK_* constants for consistency.  */
1296e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
1297e38b36f3SUlrich Drepper 	BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
1298e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);
1299e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);
1300e38b36f3SUlrich Drepper 
1301a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
130277d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1303a677a039SUlrich Drepper 		return -EINVAL;
1304a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
13051da177e4SLinus Torvalds 
1306aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1307aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1308aaca0bdcSUlrich Drepper 
13091da177e4SLinus Torvalds 	retval = sock_create(family, type, protocol, &sock);
13101da177e4SLinus Torvalds 	if (retval < 0)
13111da177e4SLinus Torvalds 		goto out;
13121da177e4SLinus Torvalds 
131377d27200SUlrich Drepper 	retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
13141da177e4SLinus Torvalds 	if (retval < 0)
13151da177e4SLinus Torvalds 		goto out_release;
13161da177e4SLinus Torvalds 
13171da177e4SLinus Torvalds out:
13181da177e4SLinus Torvalds 	/* It may be already another descriptor 8) Not kernel problem. */
13191da177e4SLinus Torvalds 	return retval;
13201da177e4SLinus Torvalds 
13211da177e4SLinus Torvalds out_release:
13221da177e4SLinus Torvalds 	sock_release(sock);
13231da177e4SLinus Torvalds 	return retval;
13241da177e4SLinus Torvalds }
13251da177e4SLinus Torvalds 
13261da177e4SLinus Torvalds /*
13271da177e4SLinus Torvalds  *	Create a pair of connected sockets.
13281da177e4SLinus Torvalds  */
13291da177e4SLinus Torvalds 
13303e0fa65fSHeiko Carstens SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
13313e0fa65fSHeiko Carstens 		int __user *, usockvec)
13321da177e4SLinus Torvalds {
13331da177e4SLinus Torvalds 	struct socket *sock1, *sock2;
13341da177e4SLinus Torvalds 	int fd1, fd2, err;
1335db349509SAl Viro 	struct file *newfile1, *newfile2;
1336a677a039SUlrich Drepper 	int flags;
1337a677a039SUlrich Drepper 
1338a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
133977d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1340a677a039SUlrich Drepper 		return -EINVAL;
1341a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
13421da177e4SLinus Torvalds 
1343aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1344aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1345aaca0bdcSUlrich Drepper 
13461da177e4SLinus Torvalds 	/*
13471da177e4SLinus Torvalds 	 * Obtain the first socket and check if the underlying protocol
13481da177e4SLinus Torvalds 	 * supports the socketpair call.
13491da177e4SLinus Torvalds 	 */
13501da177e4SLinus Torvalds 
13511da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock1);
13521da177e4SLinus Torvalds 	if (err < 0)
13531da177e4SLinus Torvalds 		goto out;
13541da177e4SLinus Torvalds 
13551da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock2);
13561da177e4SLinus Torvalds 	if (err < 0)
13571da177e4SLinus Torvalds 		goto out_release_1;
13581da177e4SLinus Torvalds 
13591da177e4SLinus Torvalds 	err = sock1->ops->socketpair(sock1, sock2);
13601da177e4SLinus Torvalds 	if (err < 0)
13611da177e4SLinus Torvalds 		goto out_release_both;
13621da177e4SLinus Torvalds 
13637cbe66b6SAl Viro 	fd1 = sock_alloc_file(sock1, &newfile1, flags);
1364bf3c23d1SDavid S. Miller 	if (unlikely(fd1 < 0)) {
1365bf3c23d1SDavid S. Miller 		err = fd1;
13661da177e4SLinus Torvalds 		goto out_release_both;
1367bf3c23d1SDavid S. Miller 	}
13681da177e4SLinus Torvalds 
13697cbe66b6SAl Viro 	fd2 = sock_alloc_file(sock2, &newfile2, flags);
1370198de4d7SAl Viro 	if (unlikely(fd2 < 0)) {
1371198de4d7SAl Viro 		err = fd2;
1372198de4d7SAl Viro 		fput(newfile1);
1373198de4d7SAl Viro 		put_unused_fd(fd1);
1374198de4d7SAl Viro 		sock_release(sock2);
1375198de4d7SAl Viro 		goto out;
1376db349509SAl Viro 	}
1377db349509SAl Viro 
1378157cf649SAl Viro 	audit_fd_pair(fd1, fd2);
1379db349509SAl Viro 	fd_install(fd1, newfile1);
1380db349509SAl Viro 	fd_install(fd2, newfile2);
13811da177e4SLinus Torvalds 	/* fd1 and fd2 may be already another descriptors.
13821da177e4SLinus Torvalds 	 * Not kernel problem.
13831da177e4SLinus Torvalds 	 */
13841da177e4SLinus Torvalds 
13851da177e4SLinus Torvalds 	err = put_user(fd1, &usockvec[0]);
13861da177e4SLinus Torvalds 	if (!err)
13871da177e4SLinus Torvalds 		err = put_user(fd2, &usockvec[1]);
13881da177e4SLinus Torvalds 	if (!err)
13891da177e4SLinus Torvalds 		return 0;
13901da177e4SLinus Torvalds 
13911da177e4SLinus Torvalds 	sys_close(fd2);
13921da177e4SLinus Torvalds 	sys_close(fd1);
13931da177e4SLinus Torvalds 	return err;
13941da177e4SLinus Torvalds 
13951da177e4SLinus Torvalds out_release_both:
13961da177e4SLinus Torvalds 	sock_release(sock2);
13971da177e4SLinus Torvalds out_release_1:
13981da177e4SLinus Torvalds 	sock_release(sock1);
13991da177e4SLinus Torvalds out:
14001da177e4SLinus Torvalds 	return err;
14011da177e4SLinus Torvalds }
14021da177e4SLinus Torvalds 
14031da177e4SLinus Torvalds /*
14041da177e4SLinus Torvalds  *	Bind a name to a socket. Nothing much to do here since it's
14051da177e4SLinus Torvalds  *	the protocol's responsibility to handle the local address.
14061da177e4SLinus Torvalds  *
14071da177e4SLinus Torvalds  *	We move the socket address to kernel space before we call
14081da177e4SLinus Torvalds  *	the protocol layer (having also checked the address is ok).
14091da177e4SLinus Torvalds  */
14101da177e4SLinus Torvalds 
141120f37034SHeiko Carstens SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
14121da177e4SLinus Torvalds {
14131da177e4SLinus Torvalds 	struct socket *sock;
1414230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
14156cb153caSBenjamin LaHaise 	int err, fput_needed;
14161da177e4SLinus Torvalds 
141789bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
141889bddce5SStephen Hemminger 	if (sock) {
1419230b1839SYOSHIFUJI Hideaki 		err = move_addr_to_kernel(umyaddr, addrlen, (struct sockaddr *)&address);
142089bddce5SStephen Hemminger 		if (err >= 0) {
142189bddce5SStephen Hemminger 			err = security_socket_bind(sock,
1422230b1839SYOSHIFUJI Hideaki 						   (struct sockaddr *)&address,
142389bddce5SStephen Hemminger 						   addrlen);
14246cb153caSBenjamin LaHaise 			if (!err)
14256cb153caSBenjamin LaHaise 				err = sock->ops->bind(sock,
142689bddce5SStephen Hemminger 						      (struct sockaddr *)
1427230b1839SYOSHIFUJI Hideaki 						      &address, addrlen);
14281da177e4SLinus Torvalds 		}
14296cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
14301da177e4SLinus Torvalds 	}
14311da177e4SLinus Torvalds 	return err;
14321da177e4SLinus Torvalds }
14331da177e4SLinus Torvalds 
14341da177e4SLinus Torvalds /*
14351da177e4SLinus Torvalds  *	Perform a listen. Basically, we allow the protocol to do anything
14361da177e4SLinus Torvalds  *	necessary for a listen, and if that works, we mark the socket as
14371da177e4SLinus Torvalds  *	ready for listening.
14381da177e4SLinus Torvalds  */
14391da177e4SLinus Torvalds 
14403e0fa65fSHeiko Carstens SYSCALL_DEFINE2(listen, int, fd, int, backlog)
14411da177e4SLinus Torvalds {
14421da177e4SLinus Torvalds 	struct socket *sock;
14436cb153caSBenjamin LaHaise 	int err, fput_needed;
1444b8e1f9b5SPavel Emelyanov 	int somaxconn;
14451da177e4SLinus Torvalds 
144689bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
144789bddce5SStephen Hemminger 	if (sock) {
14488efa6e93SPavel Emelyanov 		somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
1449b8e1f9b5SPavel Emelyanov 		if ((unsigned)backlog > somaxconn)
1450b8e1f9b5SPavel Emelyanov 			backlog = somaxconn;
14511da177e4SLinus Torvalds 
14521da177e4SLinus Torvalds 		err = security_socket_listen(sock, backlog);
14536cb153caSBenjamin LaHaise 		if (!err)
14541da177e4SLinus Torvalds 			err = sock->ops->listen(sock, backlog);
14556cb153caSBenjamin LaHaise 
14566cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
14571da177e4SLinus Torvalds 	}
14581da177e4SLinus Torvalds 	return err;
14591da177e4SLinus Torvalds }
14601da177e4SLinus Torvalds 
14611da177e4SLinus Torvalds /*
14621da177e4SLinus Torvalds  *	For accept, we attempt to create a new socket, set up the link
14631da177e4SLinus Torvalds  *	with the client, wake up the client, then return the new
14641da177e4SLinus Torvalds  *	connected fd. We collect the address of the connector in kernel
14651da177e4SLinus Torvalds  *	space and move it to user at the very end. This is unclean because
14661da177e4SLinus Torvalds  *	we open the socket then return an error.
14671da177e4SLinus Torvalds  *
14681da177e4SLinus Torvalds  *	1003.1g adds the ability to recvmsg() to query connection pending
14691da177e4SLinus Torvalds  *	status to recvmsg. We need to add that support in a way thats
14701da177e4SLinus Torvalds  *	clean when we restucture accept also.
14711da177e4SLinus Torvalds  */
14721da177e4SLinus Torvalds 
147320f37034SHeiko Carstens SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
147420f37034SHeiko Carstens 		int __user *, upeer_addrlen, int, flags)
14751da177e4SLinus Torvalds {
14761da177e4SLinus Torvalds 	struct socket *sock, *newsock;
147739d8c1b6SDavid S. Miller 	struct file *newfile;
14786cb153caSBenjamin LaHaise 	int err, len, newfd, fput_needed;
1479230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
14801da177e4SLinus Torvalds 
148177d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1482aaca0bdcSUlrich Drepper 		return -EINVAL;
1483aaca0bdcSUlrich Drepper 
1484aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1485aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1486aaca0bdcSUlrich Drepper 
14876cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
14881da177e4SLinus Torvalds 	if (!sock)
14891da177e4SLinus Torvalds 		goto out;
14901da177e4SLinus Torvalds 
14911da177e4SLinus Torvalds 	err = -ENFILE;
1492c6d409cfSEric Dumazet 	newsock = sock_alloc();
1493c6d409cfSEric Dumazet 	if (!newsock)
14941da177e4SLinus Torvalds 		goto out_put;
14951da177e4SLinus Torvalds 
14961da177e4SLinus Torvalds 	newsock->type = sock->type;
14971da177e4SLinus Torvalds 	newsock->ops = sock->ops;
14981da177e4SLinus Torvalds 
14991da177e4SLinus Torvalds 	/*
15001da177e4SLinus Torvalds 	 * We don't need try_module_get here, as the listening socket (sock)
15011da177e4SLinus Torvalds 	 * has the protocol module (sock->ops->owner) held.
15021da177e4SLinus Torvalds 	 */
15031da177e4SLinus Torvalds 	__module_get(newsock->ops->owner);
15041da177e4SLinus Torvalds 
15057cbe66b6SAl Viro 	newfd = sock_alloc_file(newsock, &newfile, flags);
150639d8c1b6SDavid S. Miller 	if (unlikely(newfd < 0)) {
150739d8c1b6SDavid S. Miller 		err = newfd;
15089a1875e6SDavid S. Miller 		sock_release(newsock);
15099a1875e6SDavid S. Miller 		goto out_put;
151039d8c1b6SDavid S. Miller 	}
151139d8c1b6SDavid S. Miller 
1512a79af59eSFrank Filz 	err = security_socket_accept(sock, newsock);
1513a79af59eSFrank Filz 	if (err)
151439d8c1b6SDavid S. Miller 		goto out_fd;
1515a79af59eSFrank Filz 
15161da177e4SLinus Torvalds 	err = sock->ops->accept(sock, newsock, sock->file->f_flags);
15171da177e4SLinus Torvalds 	if (err < 0)
151839d8c1b6SDavid S. Miller 		goto out_fd;
15191da177e4SLinus Torvalds 
15201da177e4SLinus Torvalds 	if (upeer_sockaddr) {
1521230b1839SYOSHIFUJI Hideaki 		if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
152289bddce5SStephen Hemminger 					  &len, 2) < 0) {
15231da177e4SLinus Torvalds 			err = -ECONNABORTED;
152439d8c1b6SDavid S. Miller 			goto out_fd;
15251da177e4SLinus Torvalds 		}
1526230b1839SYOSHIFUJI Hideaki 		err = move_addr_to_user((struct sockaddr *)&address,
1527230b1839SYOSHIFUJI Hideaki 					len, upeer_sockaddr, upeer_addrlen);
15281da177e4SLinus Torvalds 		if (err < 0)
152939d8c1b6SDavid S. Miller 			goto out_fd;
15301da177e4SLinus Torvalds 	}
15311da177e4SLinus Torvalds 
15321da177e4SLinus Torvalds 	/* File flags are not inherited via accept() unlike another OSes. */
15331da177e4SLinus Torvalds 
153439d8c1b6SDavid S. Miller 	fd_install(newfd, newfile);
153539d8c1b6SDavid S. Miller 	err = newfd;
15361da177e4SLinus Torvalds 
15371da177e4SLinus Torvalds out_put:
15386cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
15391da177e4SLinus Torvalds out:
15401da177e4SLinus Torvalds 	return err;
154139d8c1b6SDavid S. Miller out_fd:
15429606a216SDavid S. Miller 	fput(newfile);
154339d8c1b6SDavid S. Miller 	put_unused_fd(newfd);
15441da177e4SLinus Torvalds 	goto out_put;
15451da177e4SLinus Torvalds }
15461da177e4SLinus Torvalds 
154720f37034SHeiko Carstens SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,
154820f37034SHeiko Carstens 		int __user *, upeer_addrlen)
1549aaca0bdcSUlrich Drepper {
1550de11defeSUlrich Drepper 	return sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0);
1551aaca0bdcSUlrich Drepper }
1552aaca0bdcSUlrich Drepper 
15531da177e4SLinus Torvalds /*
15541da177e4SLinus Torvalds  *	Attempt to connect to a socket with the server address.  The address
15551da177e4SLinus Torvalds  *	is in user space so we verify it is OK and move it to kernel space.
15561da177e4SLinus Torvalds  *
15571da177e4SLinus Torvalds  *	For 1003.1g we need to add clean support for a bind to AF_UNSPEC to
15581da177e4SLinus Torvalds  *	break bindings
15591da177e4SLinus Torvalds  *
15601da177e4SLinus Torvalds  *	NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and
15611da177e4SLinus Torvalds  *	other SEQPACKET protocols that take time to connect() as it doesn't
15621da177e4SLinus Torvalds  *	include the -EINPROGRESS status for such sockets.
15631da177e4SLinus Torvalds  */
15641da177e4SLinus Torvalds 
156520f37034SHeiko Carstens SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
156620f37034SHeiko Carstens 		int, addrlen)
15671da177e4SLinus Torvalds {
15681da177e4SLinus Torvalds 	struct socket *sock;
1569230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
15706cb153caSBenjamin LaHaise 	int err, fput_needed;
15711da177e4SLinus Torvalds 
15726cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
15731da177e4SLinus Torvalds 	if (!sock)
15741da177e4SLinus Torvalds 		goto out;
1575230b1839SYOSHIFUJI Hideaki 	err = move_addr_to_kernel(uservaddr, addrlen, (struct sockaddr *)&address);
15761da177e4SLinus Torvalds 	if (err < 0)
15771da177e4SLinus Torvalds 		goto out_put;
15781da177e4SLinus Torvalds 
157989bddce5SStephen Hemminger 	err =
1580230b1839SYOSHIFUJI Hideaki 	    security_socket_connect(sock, (struct sockaddr *)&address, addrlen);
15811da177e4SLinus Torvalds 	if (err)
15821da177e4SLinus Torvalds 		goto out_put;
15831da177e4SLinus Torvalds 
1584230b1839SYOSHIFUJI Hideaki 	err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,
15851da177e4SLinus Torvalds 				 sock->file->f_flags);
15861da177e4SLinus Torvalds out_put:
15876cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
15881da177e4SLinus Torvalds out:
15891da177e4SLinus Torvalds 	return err;
15901da177e4SLinus Torvalds }
15911da177e4SLinus Torvalds 
15921da177e4SLinus Torvalds /*
15931da177e4SLinus Torvalds  *	Get the local address ('name') of a socket object. Move the obtained
15941da177e4SLinus Torvalds  *	name to user space.
15951da177e4SLinus Torvalds  */
15961da177e4SLinus Torvalds 
159720f37034SHeiko Carstens SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
159820f37034SHeiko Carstens 		int __user *, usockaddr_len)
15991da177e4SLinus Torvalds {
16001da177e4SLinus Torvalds 	struct socket *sock;
1601230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16026cb153caSBenjamin LaHaise 	int len, err, fput_needed;
16031da177e4SLinus Torvalds 
16046cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
16051da177e4SLinus Torvalds 	if (!sock)
16061da177e4SLinus Torvalds 		goto out;
16071da177e4SLinus Torvalds 
16081da177e4SLinus Torvalds 	err = security_socket_getsockname(sock);
16091da177e4SLinus Torvalds 	if (err)
16101da177e4SLinus Torvalds 		goto out_put;
16111da177e4SLinus Torvalds 
1612230b1839SYOSHIFUJI Hideaki 	err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0);
16131da177e4SLinus Torvalds 	if (err)
16141da177e4SLinus Torvalds 		goto out_put;
1615230b1839SYOSHIFUJI Hideaki 	err = move_addr_to_user((struct sockaddr *)&address, len, usockaddr, usockaddr_len);
16161da177e4SLinus Torvalds 
16171da177e4SLinus Torvalds out_put:
16186cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
16191da177e4SLinus Torvalds out:
16201da177e4SLinus Torvalds 	return err;
16211da177e4SLinus Torvalds }
16221da177e4SLinus Torvalds 
16231da177e4SLinus Torvalds /*
16241da177e4SLinus Torvalds  *	Get the remote address ('name') of a socket object. Move the obtained
16251da177e4SLinus Torvalds  *	name to user space.
16261da177e4SLinus Torvalds  */
16271da177e4SLinus Torvalds 
162820f37034SHeiko Carstens SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
162920f37034SHeiko Carstens 		int __user *, usockaddr_len)
16301da177e4SLinus Torvalds {
16311da177e4SLinus Torvalds 	struct socket *sock;
1632230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16336cb153caSBenjamin LaHaise 	int len, err, fput_needed;
16341da177e4SLinus Torvalds 
163589bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
163689bddce5SStephen Hemminger 	if (sock != NULL) {
16371da177e4SLinus Torvalds 		err = security_socket_getpeername(sock);
16381da177e4SLinus Torvalds 		if (err) {
16396cb153caSBenjamin LaHaise 			fput_light(sock->file, fput_needed);
16401da177e4SLinus Torvalds 			return err;
16411da177e4SLinus Torvalds 		}
16421da177e4SLinus Torvalds 
164389bddce5SStephen Hemminger 		err =
1644230b1839SYOSHIFUJI Hideaki 		    sock->ops->getname(sock, (struct sockaddr *)&address, &len,
164589bddce5SStephen Hemminger 				       1);
16461da177e4SLinus Torvalds 		if (!err)
1647230b1839SYOSHIFUJI Hideaki 			err = move_addr_to_user((struct sockaddr *)&address, len, usockaddr,
164889bddce5SStephen Hemminger 						usockaddr_len);
16496cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
16501da177e4SLinus Torvalds 	}
16511da177e4SLinus Torvalds 	return err;
16521da177e4SLinus Torvalds }
16531da177e4SLinus Torvalds 
16541da177e4SLinus Torvalds /*
16551da177e4SLinus Torvalds  *	Send a datagram to a given address. We move the address into kernel
16561da177e4SLinus Torvalds  *	space and check the user space data area is readable before invoking
16571da177e4SLinus Torvalds  *	the protocol.
16581da177e4SLinus Torvalds  */
16591da177e4SLinus Torvalds 
16603e0fa65fSHeiko Carstens SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
16613e0fa65fSHeiko Carstens 		unsigned, flags, struct sockaddr __user *, addr,
16623e0fa65fSHeiko Carstens 		int, addr_len)
16631da177e4SLinus Torvalds {
16641da177e4SLinus Torvalds 	struct socket *sock;
1665230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16661da177e4SLinus Torvalds 	int err;
16671da177e4SLinus Torvalds 	struct msghdr msg;
16681da177e4SLinus Torvalds 	struct iovec iov;
16696cb153caSBenjamin LaHaise 	int fput_needed;
16701da177e4SLinus Torvalds 
1671253eacc0SLinus Torvalds 	if (len > INT_MAX)
1672253eacc0SLinus Torvalds 		len = INT_MAX;
1673de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1674de0fa95cSPavel Emelyanov 	if (!sock)
16754387ff75SDavid S. Miller 		goto out;
16766cb153caSBenjamin LaHaise 
16771da177e4SLinus Torvalds 	iov.iov_base = buff;
16781da177e4SLinus Torvalds 	iov.iov_len = len;
16791da177e4SLinus Torvalds 	msg.msg_name = NULL;
16801da177e4SLinus Torvalds 	msg.msg_iov = &iov;
16811da177e4SLinus Torvalds 	msg.msg_iovlen = 1;
16821da177e4SLinus Torvalds 	msg.msg_control = NULL;
16831da177e4SLinus Torvalds 	msg.msg_controllen = 0;
16841da177e4SLinus Torvalds 	msg.msg_namelen = 0;
16856cb153caSBenjamin LaHaise 	if (addr) {
1686230b1839SYOSHIFUJI Hideaki 		err = move_addr_to_kernel(addr, addr_len, (struct sockaddr *)&address);
16871da177e4SLinus Torvalds 		if (err < 0)
16881da177e4SLinus Torvalds 			goto out_put;
1689230b1839SYOSHIFUJI Hideaki 		msg.msg_name = (struct sockaddr *)&address;
16901da177e4SLinus Torvalds 		msg.msg_namelen = addr_len;
16911da177e4SLinus Torvalds 	}
16921da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
16931da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
16941da177e4SLinus Torvalds 	msg.msg_flags = flags;
16951da177e4SLinus Torvalds 	err = sock_sendmsg(sock, &msg, len);
16961da177e4SLinus Torvalds 
16971da177e4SLinus Torvalds out_put:
1698de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
16994387ff75SDavid S. Miller out:
17001da177e4SLinus Torvalds 	return err;
17011da177e4SLinus Torvalds }
17021da177e4SLinus Torvalds 
17031da177e4SLinus Torvalds /*
17041da177e4SLinus Torvalds  *	Send a datagram down a socket.
17051da177e4SLinus Torvalds  */
17061da177e4SLinus Torvalds 
17073e0fa65fSHeiko Carstens SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len,
17083e0fa65fSHeiko Carstens 		unsigned, flags)
17091da177e4SLinus Torvalds {
17101da177e4SLinus Torvalds 	return sys_sendto(fd, buff, len, flags, NULL, 0);
17111da177e4SLinus Torvalds }
17121da177e4SLinus Torvalds 
17131da177e4SLinus Torvalds /*
17141da177e4SLinus Torvalds  *	Receive a frame from the socket and optionally record the address of the
17151da177e4SLinus Torvalds  *	sender. We verify the buffers are writable and if needed move the
17161da177e4SLinus Torvalds  *	sender address from kernel to user space.
17171da177e4SLinus Torvalds  */
17181da177e4SLinus Torvalds 
17193e0fa65fSHeiko Carstens SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
17203e0fa65fSHeiko Carstens 		unsigned, flags, struct sockaddr __user *, addr,
17213e0fa65fSHeiko Carstens 		int __user *, addr_len)
17221da177e4SLinus Torvalds {
17231da177e4SLinus Torvalds 	struct socket *sock;
17241da177e4SLinus Torvalds 	struct iovec iov;
17251da177e4SLinus Torvalds 	struct msghdr msg;
1726230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
17271da177e4SLinus Torvalds 	int err, err2;
17286cb153caSBenjamin LaHaise 	int fput_needed;
17291da177e4SLinus Torvalds 
1730253eacc0SLinus Torvalds 	if (size > INT_MAX)
1731253eacc0SLinus Torvalds 		size = INT_MAX;
1732de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
17331da177e4SLinus Torvalds 	if (!sock)
1734de0fa95cSPavel Emelyanov 		goto out;
17351da177e4SLinus Torvalds 
17361da177e4SLinus Torvalds 	msg.msg_control = NULL;
17371da177e4SLinus Torvalds 	msg.msg_controllen = 0;
17381da177e4SLinus Torvalds 	msg.msg_iovlen = 1;
17391da177e4SLinus Torvalds 	msg.msg_iov = &iov;
17401da177e4SLinus Torvalds 	iov.iov_len = size;
17411da177e4SLinus Torvalds 	iov.iov_base = ubuf;
1742230b1839SYOSHIFUJI Hideaki 	msg.msg_name = (struct sockaddr *)&address;
1743230b1839SYOSHIFUJI Hideaki 	msg.msg_namelen = sizeof(address);
17441da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
17451da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
17461da177e4SLinus Torvalds 	err = sock_recvmsg(sock, &msg, size, flags);
17471da177e4SLinus Torvalds 
174889bddce5SStephen Hemminger 	if (err >= 0 && addr != NULL) {
1749230b1839SYOSHIFUJI Hideaki 		err2 = move_addr_to_user((struct sockaddr *)&address,
1750230b1839SYOSHIFUJI Hideaki 					 msg.msg_namelen, addr, addr_len);
17511da177e4SLinus Torvalds 		if (err2 < 0)
17521da177e4SLinus Torvalds 			err = err2;
17531da177e4SLinus Torvalds 	}
1754de0fa95cSPavel Emelyanov 
1755de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
17564387ff75SDavid S. Miller out:
17571da177e4SLinus Torvalds 	return err;
17581da177e4SLinus Torvalds }
17591da177e4SLinus Torvalds 
17601da177e4SLinus Torvalds /*
17611da177e4SLinus Torvalds  *	Receive a datagram from a socket.
17621da177e4SLinus Torvalds  */
17631da177e4SLinus Torvalds 
176489bddce5SStephen Hemminger asmlinkage long sys_recv(int fd, void __user *ubuf, size_t size,
176589bddce5SStephen Hemminger 			 unsigned flags)
17661da177e4SLinus Torvalds {
17671da177e4SLinus Torvalds 	return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL);
17681da177e4SLinus Torvalds }
17691da177e4SLinus Torvalds 
17701da177e4SLinus Torvalds /*
17711da177e4SLinus Torvalds  *	Set a socket option. Because we don't know the option lengths we have
17721da177e4SLinus Torvalds  *	to pass the user mode parameter for the protocols to sort out.
17731da177e4SLinus Torvalds  */
17741da177e4SLinus Torvalds 
177520f37034SHeiko Carstens SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
177620f37034SHeiko Carstens 		char __user *, optval, int, optlen)
17771da177e4SLinus Torvalds {
17786cb153caSBenjamin LaHaise 	int err, fput_needed;
17791da177e4SLinus Torvalds 	struct socket *sock;
17801da177e4SLinus Torvalds 
17811da177e4SLinus Torvalds 	if (optlen < 0)
17821da177e4SLinus Torvalds 		return -EINVAL;
17831da177e4SLinus Torvalds 
178489bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
178589bddce5SStephen Hemminger 	if (sock != NULL) {
17861da177e4SLinus Torvalds 		err = security_socket_setsockopt(sock, level, optname);
17876cb153caSBenjamin LaHaise 		if (err)
17886cb153caSBenjamin LaHaise 			goto out_put;
17891da177e4SLinus Torvalds 
17901da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
179189bddce5SStephen Hemminger 			err =
179289bddce5SStephen Hemminger 			    sock_setsockopt(sock, level, optname, optval,
179389bddce5SStephen Hemminger 					    optlen);
17941da177e4SLinus Torvalds 		else
179589bddce5SStephen Hemminger 			err =
179689bddce5SStephen Hemminger 			    sock->ops->setsockopt(sock, level, optname, optval,
179789bddce5SStephen Hemminger 						  optlen);
17986cb153caSBenjamin LaHaise out_put:
17996cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
18001da177e4SLinus Torvalds 	}
18011da177e4SLinus Torvalds 	return err;
18021da177e4SLinus Torvalds }
18031da177e4SLinus Torvalds 
18041da177e4SLinus Torvalds /*
18051da177e4SLinus Torvalds  *	Get a socket option. Because we don't know the option lengths we have
18061da177e4SLinus Torvalds  *	to pass a user mode parameter for the protocols to sort out.
18071da177e4SLinus Torvalds  */
18081da177e4SLinus Torvalds 
180920f37034SHeiko Carstens SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
181020f37034SHeiko Carstens 		char __user *, optval, int __user *, optlen)
18111da177e4SLinus Torvalds {
18126cb153caSBenjamin LaHaise 	int err, fput_needed;
18131da177e4SLinus Torvalds 	struct socket *sock;
18141da177e4SLinus Torvalds 
181589bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
181689bddce5SStephen Hemminger 	if (sock != NULL) {
18176cb153caSBenjamin LaHaise 		err = security_socket_getsockopt(sock, level, optname);
18186cb153caSBenjamin LaHaise 		if (err)
18196cb153caSBenjamin LaHaise 			goto out_put;
18201da177e4SLinus Torvalds 
18211da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
182289bddce5SStephen Hemminger 			err =
182389bddce5SStephen Hemminger 			    sock_getsockopt(sock, level, optname, optval,
182489bddce5SStephen Hemminger 					    optlen);
18251da177e4SLinus Torvalds 		else
182689bddce5SStephen Hemminger 			err =
182789bddce5SStephen Hemminger 			    sock->ops->getsockopt(sock, level, optname, optval,
182889bddce5SStephen Hemminger 						  optlen);
18296cb153caSBenjamin LaHaise out_put:
18306cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
18311da177e4SLinus Torvalds 	}
18321da177e4SLinus Torvalds 	return err;
18331da177e4SLinus Torvalds }
18341da177e4SLinus Torvalds 
18351da177e4SLinus Torvalds /*
18361da177e4SLinus Torvalds  *	Shutdown a socket.
18371da177e4SLinus Torvalds  */
18381da177e4SLinus Torvalds 
1839754fe8d2SHeiko Carstens SYSCALL_DEFINE2(shutdown, int, fd, int, how)
18401da177e4SLinus Torvalds {
18416cb153caSBenjamin LaHaise 	int err, fput_needed;
18421da177e4SLinus Torvalds 	struct socket *sock;
18431da177e4SLinus Torvalds 
184489bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
184589bddce5SStephen Hemminger 	if (sock != NULL) {
18461da177e4SLinus Torvalds 		err = security_socket_shutdown(sock, how);
18476cb153caSBenjamin LaHaise 		if (!err)
18481da177e4SLinus Torvalds 			err = sock->ops->shutdown(sock, how);
18496cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
18501da177e4SLinus Torvalds 	}
18511da177e4SLinus Torvalds 	return err;
18521da177e4SLinus Torvalds }
18531da177e4SLinus Torvalds 
18541da177e4SLinus Torvalds /* A couple of helpful macros for getting the address of the 32/64 bit
18551da177e4SLinus Torvalds  * fields which are the same type (int / unsigned) on our platforms.
18561da177e4SLinus Torvalds  */
18571da177e4SLinus Torvalds #define COMPAT_MSG(msg, member)	((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member)
18581da177e4SLinus Torvalds #define COMPAT_NAMELEN(msg)	COMPAT_MSG(msg, msg_namelen)
18591da177e4SLinus Torvalds #define COMPAT_FLAGS(msg)	COMPAT_MSG(msg, msg_flags)
18601da177e4SLinus Torvalds 
18611da177e4SLinus Torvalds /*
18621da177e4SLinus Torvalds  *	BSD sendmsg interface
18631da177e4SLinus Torvalds  */
18641da177e4SLinus Torvalds 
18653e0fa65fSHeiko Carstens SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned, flags)
18661da177e4SLinus Torvalds {
186789bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
186889bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
18691da177e4SLinus Torvalds 	struct socket *sock;
1870230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
18711da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
1872b9d717a7SAlex Williamson 	unsigned char ctl[sizeof(struct cmsghdr) + 20]
1873b9d717a7SAlex Williamson 	    __attribute__ ((aligned(sizeof(__kernel_size_t))));
1874b9d717a7SAlex Williamson 	/* 20 is size of ipv6_pktinfo */
18751da177e4SLinus Torvalds 	unsigned char *ctl_buf = ctl;
18761da177e4SLinus Torvalds 	struct msghdr msg_sys;
18771da177e4SLinus Torvalds 	int err, ctl_len, iov_size, total_len;
18786cb153caSBenjamin LaHaise 	int fput_needed;
18791da177e4SLinus Torvalds 
18801da177e4SLinus Torvalds 	err = -EFAULT;
18811da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
18821da177e4SLinus Torvalds 		if (get_compat_msghdr(&msg_sys, msg_compat))
18831da177e4SLinus Torvalds 			return -EFAULT;
1884c6d409cfSEric Dumazet 	} else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr)))
18851da177e4SLinus Torvalds 		return -EFAULT;
18861da177e4SLinus Torvalds 
18876cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
18881da177e4SLinus Torvalds 	if (!sock)
18891da177e4SLinus Torvalds 		goto out;
18901da177e4SLinus Torvalds 
18911da177e4SLinus Torvalds 	/* do not move before msg_sys is valid */
18921da177e4SLinus Torvalds 	err = -EMSGSIZE;
18931da177e4SLinus Torvalds 	if (msg_sys.msg_iovlen > UIO_MAXIOV)
18941da177e4SLinus Torvalds 		goto out_put;
18951da177e4SLinus Torvalds 
18961da177e4SLinus Torvalds 	/* Check whether to allocate the iovec area */
18971da177e4SLinus Torvalds 	err = -ENOMEM;
18981da177e4SLinus Torvalds 	iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);
18991da177e4SLinus Torvalds 	if (msg_sys.msg_iovlen > UIO_FASTIOV) {
19001da177e4SLinus Torvalds 		iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
19011da177e4SLinus Torvalds 		if (!iov)
19021da177e4SLinus Torvalds 			goto out_put;
19031da177e4SLinus Torvalds 	}
19041da177e4SLinus Torvalds 
19051da177e4SLinus Torvalds 	/* This will also move the address data into kernel space */
19061da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
1907230b1839SYOSHIFUJI Hideaki 		err = verify_compat_iovec(&msg_sys, iov,
1908230b1839SYOSHIFUJI Hideaki 					  (struct sockaddr *)&address,
1909230b1839SYOSHIFUJI Hideaki 					  VERIFY_READ);
19101da177e4SLinus Torvalds 	} else
1911230b1839SYOSHIFUJI Hideaki 		err = verify_iovec(&msg_sys, iov,
1912230b1839SYOSHIFUJI Hideaki 				   (struct sockaddr *)&address,
1913230b1839SYOSHIFUJI Hideaki 				   VERIFY_READ);
19141da177e4SLinus Torvalds 	if (err < 0)
19151da177e4SLinus Torvalds 		goto out_freeiov;
19161da177e4SLinus Torvalds 	total_len = err;
19171da177e4SLinus Torvalds 
19181da177e4SLinus Torvalds 	err = -ENOBUFS;
19191da177e4SLinus Torvalds 
19201da177e4SLinus Torvalds 	if (msg_sys.msg_controllen > INT_MAX)
19211da177e4SLinus Torvalds 		goto out_freeiov;
19221da177e4SLinus Torvalds 	ctl_len = msg_sys.msg_controllen;
19231da177e4SLinus Torvalds 	if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
192489bddce5SStephen Hemminger 		err =
192589bddce5SStephen Hemminger 		    cmsghdr_from_user_compat_to_kern(&msg_sys, sock->sk, ctl,
192689bddce5SStephen Hemminger 						     sizeof(ctl));
19271da177e4SLinus Torvalds 		if (err)
19281da177e4SLinus Torvalds 			goto out_freeiov;
19291da177e4SLinus Torvalds 		ctl_buf = msg_sys.msg_control;
19308920e8f9SAl Viro 		ctl_len = msg_sys.msg_controllen;
19311da177e4SLinus Torvalds 	} else if (ctl_len) {
193289bddce5SStephen Hemminger 		if (ctl_len > sizeof(ctl)) {
19331da177e4SLinus Torvalds 			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
19341da177e4SLinus Torvalds 			if (ctl_buf == NULL)
19351da177e4SLinus Torvalds 				goto out_freeiov;
19361da177e4SLinus Torvalds 		}
19371da177e4SLinus Torvalds 		err = -EFAULT;
19381da177e4SLinus Torvalds 		/*
19391da177e4SLinus Torvalds 		 * Careful! Before this, msg_sys.msg_control contains a user pointer.
19401da177e4SLinus Torvalds 		 * Afterwards, it will be a kernel pointer. Thus the compiler-assisted
19411da177e4SLinus Torvalds 		 * checking falls down on this.
19421da177e4SLinus Torvalds 		 */
1943fb8621bbSNamhyung Kim 		if (copy_from_user(ctl_buf,
1944fb8621bbSNamhyung Kim 				   (void __user __force *)msg_sys.msg_control,
194589bddce5SStephen Hemminger 				   ctl_len))
19461da177e4SLinus Torvalds 			goto out_freectl;
19471da177e4SLinus Torvalds 		msg_sys.msg_control = ctl_buf;
19481da177e4SLinus Torvalds 	}
19491da177e4SLinus Torvalds 	msg_sys.msg_flags = flags;
19501da177e4SLinus Torvalds 
19511da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
19521da177e4SLinus Torvalds 		msg_sys.msg_flags |= MSG_DONTWAIT;
19531da177e4SLinus Torvalds 	err = sock_sendmsg(sock, &msg_sys, total_len);
19541da177e4SLinus Torvalds 
19551da177e4SLinus Torvalds out_freectl:
19561da177e4SLinus Torvalds 	if (ctl_buf != ctl)
19571da177e4SLinus Torvalds 		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
19581da177e4SLinus Torvalds out_freeiov:
19591da177e4SLinus Torvalds 	if (iov != iovstack)
19601da177e4SLinus Torvalds 		sock_kfree_s(sock->sk, iov, iov_size);
19611da177e4SLinus Torvalds out_put:
19626cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
19631da177e4SLinus Torvalds out:
19641da177e4SLinus Torvalds 	return err;
19651da177e4SLinus Torvalds }
19661da177e4SLinus Torvalds 
1967a2e27255SArnaldo Carvalho de Melo static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
1968a2e27255SArnaldo Carvalho de Melo 			 struct msghdr *msg_sys, unsigned flags, int nosec)
19691da177e4SLinus Torvalds {
197089bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
197189bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
19721da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV];
19731da177e4SLinus Torvalds 	struct iovec *iov = iovstack;
19741da177e4SLinus Torvalds 	unsigned long cmsg_ptr;
19751da177e4SLinus Torvalds 	int err, iov_size, total_len, len;
19761da177e4SLinus Torvalds 
19771da177e4SLinus Torvalds 	/* kernel mode address */
1978230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage addr;
19791da177e4SLinus Torvalds 
19801da177e4SLinus Torvalds 	/* user mode address pointers */
19811da177e4SLinus Torvalds 	struct sockaddr __user *uaddr;
19821da177e4SLinus Torvalds 	int __user *uaddr_len;
19831da177e4SLinus Torvalds 
19841da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
1985a2e27255SArnaldo Carvalho de Melo 		if (get_compat_msghdr(msg_sys, msg_compat))
19861da177e4SLinus Torvalds 			return -EFAULT;
1987c6d409cfSEric Dumazet 	} else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr)))
19881da177e4SLinus Torvalds 		return -EFAULT;
19891da177e4SLinus Torvalds 
19901da177e4SLinus Torvalds 	err = -EMSGSIZE;
1991a2e27255SArnaldo Carvalho de Melo 	if (msg_sys->msg_iovlen > UIO_MAXIOV)
1992a2e27255SArnaldo Carvalho de Melo 		goto out;
19931da177e4SLinus Torvalds 
19941da177e4SLinus Torvalds 	/* Check whether to allocate the iovec area */
19951da177e4SLinus Torvalds 	err = -ENOMEM;
1996a2e27255SArnaldo Carvalho de Melo 	iov_size = msg_sys->msg_iovlen * sizeof(struct iovec);
1997a2e27255SArnaldo Carvalho de Melo 	if (msg_sys->msg_iovlen > UIO_FASTIOV) {
19981da177e4SLinus Torvalds 		iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
19991da177e4SLinus Torvalds 		if (!iov)
2000a2e27255SArnaldo Carvalho de Melo 			goto out;
20011da177e4SLinus Torvalds 	}
20021da177e4SLinus Torvalds 
20031da177e4SLinus Torvalds 	/*
20041da177e4SLinus Torvalds 	 *      Save the user-mode address (verify_iovec will change the
20051da177e4SLinus Torvalds 	 *      kernel msghdr to use the kernel address space)
20061da177e4SLinus Torvalds 	 */
20071da177e4SLinus Torvalds 
2008a2e27255SArnaldo Carvalho de Melo 	uaddr = (__force void __user *)msg_sys->msg_name;
20091da177e4SLinus Torvalds 	uaddr_len = COMPAT_NAMELEN(msg);
20101da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
2011a2e27255SArnaldo Carvalho de Melo 		err = verify_compat_iovec(msg_sys, iov,
2012230b1839SYOSHIFUJI Hideaki 					  (struct sockaddr *)&addr,
2013230b1839SYOSHIFUJI Hideaki 					  VERIFY_WRITE);
20141da177e4SLinus Torvalds 	} else
2015a2e27255SArnaldo Carvalho de Melo 		err = verify_iovec(msg_sys, iov,
2016230b1839SYOSHIFUJI Hideaki 				   (struct sockaddr *)&addr,
2017230b1839SYOSHIFUJI Hideaki 				   VERIFY_WRITE);
20181da177e4SLinus Torvalds 	if (err < 0)
20191da177e4SLinus Torvalds 		goto out_freeiov;
20201da177e4SLinus Torvalds 	total_len = err;
20211da177e4SLinus Torvalds 
2022a2e27255SArnaldo Carvalho de Melo 	cmsg_ptr = (unsigned long)msg_sys->msg_control;
2023a2e27255SArnaldo Carvalho de Melo 	msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
20241da177e4SLinus Torvalds 
20251da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
20261da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
2027a2e27255SArnaldo Carvalho de Melo 	err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys,
2028a2e27255SArnaldo Carvalho de Melo 							  total_len, flags);
20291da177e4SLinus Torvalds 	if (err < 0)
20301da177e4SLinus Torvalds 		goto out_freeiov;
20311da177e4SLinus Torvalds 	len = err;
20321da177e4SLinus Torvalds 
20331da177e4SLinus Torvalds 	if (uaddr != NULL) {
2034230b1839SYOSHIFUJI Hideaki 		err = move_addr_to_user((struct sockaddr *)&addr,
2035a2e27255SArnaldo Carvalho de Melo 					msg_sys->msg_namelen, uaddr,
203689bddce5SStephen Hemminger 					uaddr_len);
20371da177e4SLinus Torvalds 		if (err < 0)
20381da177e4SLinus Torvalds 			goto out_freeiov;
20391da177e4SLinus Torvalds 	}
2040a2e27255SArnaldo Carvalho de Melo 	err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
204137f7f421SDavid S. Miller 			 COMPAT_FLAGS(msg));
20421da177e4SLinus Torvalds 	if (err)
20431da177e4SLinus Torvalds 		goto out_freeiov;
20441da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags)
2045a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
20461da177e4SLinus Torvalds 				 &msg_compat->msg_controllen);
20471da177e4SLinus Torvalds 	else
2048a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
20491da177e4SLinus Torvalds 				 &msg->msg_controllen);
20501da177e4SLinus Torvalds 	if (err)
20511da177e4SLinus Torvalds 		goto out_freeiov;
20521da177e4SLinus Torvalds 	err = len;
20531da177e4SLinus Torvalds 
20541da177e4SLinus Torvalds out_freeiov:
20551da177e4SLinus Torvalds 	if (iov != iovstack)
20561da177e4SLinus Torvalds 		sock_kfree_s(sock->sk, iov, iov_size);
2057a2e27255SArnaldo Carvalho de Melo out:
2058a2e27255SArnaldo Carvalho de Melo 	return err;
2059a2e27255SArnaldo Carvalho de Melo }
2060a2e27255SArnaldo Carvalho de Melo 
2061a2e27255SArnaldo Carvalho de Melo /*
2062a2e27255SArnaldo Carvalho de Melo  *	BSD recvmsg interface
2063a2e27255SArnaldo Carvalho de Melo  */
2064a2e27255SArnaldo Carvalho de Melo 
2065a2e27255SArnaldo Carvalho de Melo SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg,
2066a2e27255SArnaldo Carvalho de Melo 		unsigned int, flags)
2067a2e27255SArnaldo Carvalho de Melo {
2068a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err;
2069a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
2070a2e27255SArnaldo Carvalho de Melo 	struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed);
2071a2e27255SArnaldo Carvalho de Melo 
2072a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2073a2e27255SArnaldo Carvalho de Melo 		goto out;
2074a2e27255SArnaldo Carvalho de Melo 
2075a2e27255SArnaldo Carvalho de Melo 	err = __sys_recvmsg(sock, msg, &msg_sys, flags, 0);
2076a2e27255SArnaldo Carvalho de Melo 
20776cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
20781da177e4SLinus Torvalds out:
20791da177e4SLinus Torvalds 	return err;
20801da177e4SLinus Torvalds }
20811da177e4SLinus Torvalds 
2082a2e27255SArnaldo Carvalho de Melo /*
2083a2e27255SArnaldo Carvalho de Melo  *     Linux recvmmsg interface
2084a2e27255SArnaldo Carvalho de Melo  */
20851da177e4SLinus Torvalds 
2086a2e27255SArnaldo Carvalho de Melo int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2087a2e27255SArnaldo Carvalho de Melo 		   unsigned int flags, struct timespec *timeout)
2088a2e27255SArnaldo Carvalho de Melo {
2089a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err, datagrams;
2090a2e27255SArnaldo Carvalho de Melo 	struct socket *sock;
2091a2e27255SArnaldo Carvalho de Melo 	struct mmsghdr __user *entry;
2092d7256d0eSJean-Mickael Guerin 	struct compat_mmsghdr __user *compat_entry;
2093a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
2094a2e27255SArnaldo Carvalho de Melo 	struct timespec end_time;
2095a2e27255SArnaldo Carvalho de Melo 
2096a2e27255SArnaldo Carvalho de Melo 	if (timeout &&
2097a2e27255SArnaldo Carvalho de Melo 	    poll_select_set_timeout(&end_time, timeout->tv_sec,
2098a2e27255SArnaldo Carvalho de Melo 				    timeout->tv_nsec))
2099a2e27255SArnaldo Carvalho de Melo 		return -EINVAL;
2100a2e27255SArnaldo Carvalho de Melo 
2101a2e27255SArnaldo Carvalho de Melo 	datagrams = 0;
2102a2e27255SArnaldo Carvalho de Melo 
2103a2e27255SArnaldo Carvalho de Melo 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2104a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2105a2e27255SArnaldo Carvalho de Melo 		return err;
2106a2e27255SArnaldo Carvalho de Melo 
2107a2e27255SArnaldo Carvalho de Melo 	err = sock_error(sock->sk);
2108a2e27255SArnaldo Carvalho de Melo 	if (err)
2109a2e27255SArnaldo Carvalho de Melo 		goto out_put;
2110a2e27255SArnaldo Carvalho de Melo 
2111a2e27255SArnaldo Carvalho de Melo 	entry = mmsg;
2112d7256d0eSJean-Mickael Guerin 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2113a2e27255SArnaldo Carvalho de Melo 
2114a2e27255SArnaldo Carvalho de Melo 	while (datagrams < vlen) {
2115a2e27255SArnaldo Carvalho de Melo 		/*
2116a2e27255SArnaldo Carvalho de Melo 		 * No need to ask LSM for more than the first datagram.
2117a2e27255SArnaldo Carvalho de Melo 		 */
2118d7256d0eSJean-Mickael Guerin 		if (MSG_CMSG_COMPAT & flags) {
2119d7256d0eSJean-Mickael Guerin 			err = __sys_recvmsg(sock, (struct msghdr __user *)compat_entry,
2120d7256d0eSJean-Mickael Guerin 					    &msg_sys, flags, datagrams);
2121d7256d0eSJean-Mickael Guerin 			if (err < 0)
2122d7256d0eSJean-Mickael Guerin 				break;
2123d7256d0eSJean-Mickael Guerin 			err = __put_user(err, &compat_entry->msg_len);
2124d7256d0eSJean-Mickael Guerin 			++compat_entry;
2125d7256d0eSJean-Mickael Guerin 		} else {
2126a2e27255SArnaldo Carvalho de Melo 			err = __sys_recvmsg(sock, (struct msghdr __user *)entry,
2127a2e27255SArnaldo Carvalho de Melo 					    &msg_sys, flags, datagrams);
2128a2e27255SArnaldo Carvalho de Melo 			if (err < 0)
2129a2e27255SArnaldo Carvalho de Melo 				break;
2130a2e27255SArnaldo Carvalho de Melo 			err = put_user(err, &entry->msg_len);
2131d7256d0eSJean-Mickael Guerin 			++entry;
2132d7256d0eSJean-Mickael Guerin 		}
2133d7256d0eSJean-Mickael Guerin 
2134a2e27255SArnaldo Carvalho de Melo 		if (err)
2135a2e27255SArnaldo Carvalho de Melo 			break;
2136a2e27255SArnaldo Carvalho de Melo 		++datagrams;
2137a2e27255SArnaldo Carvalho de Melo 
213871c5c159SBrandon L Black 		/* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
213971c5c159SBrandon L Black 		if (flags & MSG_WAITFORONE)
214071c5c159SBrandon L Black 			flags |= MSG_DONTWAIT;
214171c5c159SBrandon L Black 
2142a2e27255SArnaldo Carvalho de Melo 		if (timeout) {
2143a2e27255SArnaldo Carvalho de Melo 			ktime_get_ts(timeout);
2144a2e27255SArnaldo Carvalho de Melo 			*timeout = timespec_sub(end_time, *timeout);
2145a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_sec < 0) {
2146a2e27255SArnaldo Carvalho de Melo 				timeout->tv_sec = timeout->tv_nsec = 0;
2147a2e27255SArnaldo Carvalho de Melo 				break;
2148a2e27255SArnaldo Carvalho de Melo 			}
2149a2e27255SArnaldo Carvalho de Melo 
2150a2e27255SArnaldo Carvalho de Melo 			/* Timeout, return less than vlen datagrams */
2151a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_nsec == 0 && timeout->tv_sec == 0)
2152a2e27255SArnaldo Carvalho de Melo 				break;
2153a2e27255SArnaldo Carvalho de Melo 		}
2154a2e27255SArnaldo Carvalho de Melo 
2155a2e27255SArnaldo Carvalho de Melo 		/* Out of band data, return right away */
2156a2e27255SArnaldo Carvalho de Melo 		if (msg_sys.msg_flags & MSG_OOB)
2157a2e27255SArnaldo Carvalho de Melo 			break;
2158a2e27255SArnaldo Carvalho de Melo 	}
2159a2e27255SArnaldo Carvalho de Melo 
2160a2e27255SArnaldo Carvalho de Melo out_put:
2161a2e27255SArnaldo Carvalho de Melo 	fput_light(sock->file, fput_needed);
2162a2e27255SArnaldo Carvalho de Melo 
2163a2e27255SArnaldo Carvalho de Melo 	if (err == 0)
2164a2e27255SArnaldo Carvalho de Melo 		return datagrams;
2165a2e27255SArnaldo Carvalho de Melo 
2166a2e27255SArnaldo Carvalho de Melo 	if (datagrams != 0) {
2167a2e27255SArnaldo Carvalho de Melo 		/*
2168a2e27255SArnaldo Carvalho de Melo 		 * We may return less entries than requested (vlen) if the
2169a2e27255SArnaldo Carvalho de Melo 		 * sock is non block and there aren't enough datagrams...
2170a2e27255SArnaldo Carvalho de Melo 		 */
2171a2e27255SArnaldo Carvalho de Melo 		if (err != -EAGAIN) {
2172a2e27255SArnaldo Carvalho de Melo 			/*
2173a2e27255SArnaldo Carvalho de Melo 			 * ... or  if recvmsg returns an error after we
2174a2e27255SArnaldo Carvalho de Melo 			 * received some datagrams, where we record the
2175a2e27255SArnaldo Carvalho de Melo 			 * error to return on the next call or if the
2176a2e27255SArnaldo Carvalho de Melo 			 * app asks about it using getsockopt(SO_ERROR).
2177a2e27255SArnaldo Carvalho de Melo 			 */
2178a2e27255SArnaldo Carvalho de Melo 			sock->sk->sk_err = -err;
2179a2e27255SArnaldo Carvalho de Melo 		}
2180a2e27255SArnaldo Carvalho de Melo 
2181a2e27255SArnaldo Carvalho de Melo 		return datagrams;
2182a2e27255SArnaldo Carvalho de Melo 	}
2183a2e27255SArnaldo Carvalho de Melo 
2184a2e27255SArnaldo Carvalho de Melo 	return err;
2185a2e27255SArnaldo Carvalho de Melo }
2186a2e27255SArnaldo Carvalho de Melo 
2187a2e27255SArnaldo Carvalho de Melo SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
2188a2e27255SArnaldo Carvalho de Melo 		unsigned int, vlen, unsigned int, flags,
2189a2e27255SArnaldo Carvalho de Melo 		struct timespec __user *, timeout)
2190a2e27255SArnaldo Carvalho de Melo {
2191a2e27255SArnaldo Carvalho de Melo 	int datagrams;
2192a2e27255SArnaldo Carvalho de Melo 	struct timespec timeout_sys;
2193a2e27255SArnaldo Carvalho de Melo 
2194a2e27255SArnaldo Carvalho de Melo 	if (!timeout)
2195a2e27255SArnaldo Carvalho de Melo 		return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL);
2196a2e27255SArnaldo Carvalho de Melo 
2197a2e27255SArnaldo Carvalho de Melo 	if (copy_from_user(&timeout_sys, timeout, sizeof(timeout_sys)))
2198a2e27255SArnaldo Carvalho de Melo 		return -EFAULT;
2199a2e27255SArnaldo Carvalho de Melo 
2200a2e27255SArnaldo Carvalho de Melo 	datagrams = __sys_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys);
2201a2e27255SArnaldo Carvalho de Melo 
2202a2e27255SArnaldo Carvalho de Melo 	if (datagrams > 0 &&
2203a2e27255SArnaldo Carvalho de Melo 	    copy_to_user(timeout, &timeout_sys, sizeof(timeout_sys)))
2204a2e27255SArnaldo Carvalho de Melo 		datagrams = -EFAULT;
2205a2e27255SArnaldo Carvalho de Melo 
2206a2e27255SArnaldo Carvalho de Melo 	return datagrams;
2207a2e27255SArnaldo Carvalho de Melo }
2208a2e27255SArnaldo Carvalho de Melo 
2209a2e27255SArnaldo Carvalho de Melo #ifdef __ARCH_WANT_SYS_SOCKETCALL
22101da177e4SLinus Torvalds /* Argument list sizes for sys_socketcall */
22111da177e4SLinus Torvalds #define AL(x) ((x) * sizeof(unsigned long))
2212a2e27255SArnaldo Carvalho de Melo static const unsigned char nargs[20] = {
221389bddce5SStephen Hemminger 	AL(0), AL(3), AL(3), AL(3), AL(2), AL(3),
22141da177e4SLinus Torvalds 	AL(3), AL(3), AL(4), AL(4), AL(4), AL(6),
2215aaca0bdcSUlrich Drepper 	AL(6), AL(2), AL(5), AL(5), AL(3), AL(3),
2216a2e27255SArnaldo Carvalho de Melo 	AL(4), AL(5)
221789bddce5SStephen Hemminger };
221889bddce5SStephen Hemminger 
22191da177e4SLinus Torvalds #undef AL
22201da177e4SLinus Torvalds 
22211da177e4SLinus Torvalds /*
22221da177e4SLinus Torvalds  *	System call vectors.
22231da177e4SLinus Torvalds  *
22241da177e4SLinus Torvalds  *	Argument checking cleaned up. Saved 20% in size.
22251da177e4SLinus Torvalds  *  This function doesn't need to set the kernel lock because
22261da177e4SLinus Torvalds  *  it is set by the callees.
22271da177e4SLinus Torvalds  */
22281da177e4SLinus Torvalds 
22293e0fa65fSHeiko Carstens SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
22301da177e4SLinus Torvalds {
22311da177e4SLinus Torvalds 	unsigned long a[6];
22321da177e4SLinus Torvalds 	unsigned long a0, a1;
22331da177e4SLinus Torvalds 	int err;
223447379052SArjan van de Ven 	unsigned int len;
22351da177e4SLinus Torvalds 
2236a2e27255SArnaldo Carvalho de Melo 	if (call < 1 || call > SYS_RECVMMSG)
22371da177e4SLinus Torvalds 		return -EINVAL;
22381da177e4SLinus Torvalds 
223947379052SArjan van de Ven 	len = nargs[call];
224047379052SArjan van de Ven 	if (len > sizeof(a))
224147379052SArjan van de Ven 		return -EINVAL;
224247379052SArjan van de Ven 
22431da177e4SLinus Torvalds 	/* copy_from_user should be SMP safe. */
224447379052SArjan van de Ven 	if (copy_from_user(a, args, len))
22451da177e4SLinus Torvalds 		return -EFAULT;
22461da177e4SLinus Torvalds 
2247f3298dc4SAl Viro 	audit_socketcall(nargs[call] / sizeof(unsigned long), a);
22483ec3b2fbSDavid Woodhouse 
22491da177e4SLinus Torvalds 	a0 = a[0];
22501da177e4SLinus Torvalds 	a1 = a[1];
22511da177e4SLinus Torvalds 
225289bddce5SStephen Hemminger 	switch (call) {
22531da177e4SLinus Torvalds 	case SYS_SOCKET:
22541da177e4SLinus Torvalds 		err = sys_socket(a0, a1, a[2]);
22551da177e4SLinus Torvalds 		break;
22561da177e4SLinus Torvalds 	case SYS_BIND:
22571da177e4SLinus Torvalds 		err = sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
22581da177e4SLinus Torvalds 		break;
22591da177e4SLinus Torvalds 	case SYS_CONNECT:
22601da177e4SLinus Torvalds 		err = sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
22611da177e4SLinus Torvalds 		break;
22621da177e4SLinus Torvalds 	case SYS_LISTEN:
22631da177e4SLinus Torvalds 		err = sys_listen(a0, a1);
22641da177e4SLinus Torvalds 		break;
22651da177e4SLinus Torvalds 	case SYS_ACCEPT:
2266de11defeSUlrich Drepper 		err = sys_accept4(a0, (struct sockaddr __user *)a1,
2267aaca0bdcSUlrich Drepper 				  (int __user *)a[2], 0);
22681da177e4SLinus Torvalds 		break;
22691da177e4SLinus Torvalds 	case SYS_GETSOCKNAME:
227089bddce5SStephen Hemminger 		err =
227189bddce5SStephen Hemminger 		    sys_getsockname(a0, (struct sockaddr __user *)a1,
227289bddce5SStephen Hemminger 				    (int __user *)a[2]);
22731da177e4SLinus Torvalds 		break;
22741da177e4SLinus Torvalds 	case SYS_GETPEERNAME:
227589bddce5SStephen Hemminger 		err =
227689bddce5SStephen Hemminger 		    sys_getpeername(a0, (struct sockaddr __user *)a1,
227789bddce5SStephen Hemminger 				    (int __user *)a[2]);
22781da177e4SLinus Torvalds 		break;
22791da177e4SLinus Torvalds 	case SYS_SOCKETPAIR:
22801da177e4SLinus Torvalds 		err = sys_socketpair(a0, a1, a[2], (int __user *)a[3]);
22811da177e4SLinus Torvalds 		break;
22821da177e4SLinus Torvalds 	case SYS_SEND:
22831da177e4SLinus Torvalds 		err = sys_send(a0, (void __user *)a1, a[2], a[3]);
22841da177e4SLinus Torvalds 		break;
22851da177e4SLinus Torvalds 	case SYS_SENDTO:
22861da177e4SLinus Torvalds 		err = sys_sendto(a0, (void __user *)a1, a[2], a[3],
22871da177e4SLinus Torvalds 				 (struct sockaddr __user *)a[4], a[5]);
22881da177e4SLinus Torvalds 		break;
22891da177e4SLinus Torvalds 	case SYS_RECV:
22901da177e4SLinus Torvalds 		err = sys_recv(a0, (void __user *)a1, a[2], a[3]);
22911da177e4SLinus Torvalds 		break;
22921da177e4SLinus Torvalds 	case SYS_RECVFROM:
22931da177e4SLinus Torvalds 		err = sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
229489bddce5SStephen Hemminger 				   (struct sockaddr __user *)a[4],
229589bddce5SStephen Hemminger 				   (int __user *)a[5]);
22961da177e4SLinus Torvalds 		break;
22971da177e4SLinus Torvalds 	case SYS_SHUTDOWN:
22981da177e4SLinus Torvalds 		err = sys_shutdown(a0, a1);
22991da177e4SLinus Torvalds 		break;
23001da177e4SLinus Torvalds 	case SYS_SETSOCKOPT:
23011da177e4SLinus Torvalds 		err = sys_setsockopt(a0, a1, a[2], (char __user *)a[3], a[4]);
23021da177e4SLinus Torvalds 		break;
23031da177e4SLinus Torvalds 	case SYS_GETSOCKOPT:
230489bddce5SStephen Hemminger 		err =
230589bddce5SStephen Hemminger 		    sys_getsockopt(a0, a1, a[2], (char __user *)a[3],
230689bddce5SStephen Hemminger 				   (int __user *)a[4]);
23071da177e4SLinus Torvalds 		break;
23081da177e4SLinus Torvalds 	case SYS_SENDMSG:
23091da177e4SLinus Torvalds 		err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]);
23101da177e4SLinus Torvalds 		break;
23111da177e4SLinus Torvalds 	case SYS_RECVMSG:
23121da177e4SLinus Torvalds 		err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]);
23131da177e4SLinus Torvalds 		break;
2314a2e27255SArnaldo Carvalho de Melo 	case SYS_RECVMMSG:
2315a2e27255SArnaldo Carvalho de Melo 		err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3],
2316a2e27255SArnaldo Carvalho de Melo 				   (struct timespec __user *)a[4]);
2317a2e27255SArnaldo Carvalho de Melo 		break;
2318de11defeSUlrich Drepper 	case SYS_ACCEPT4:
2319de11defeSUlrich Drepper 		err = sys_accept4(a0, (struct sockaddr __user *)a1,
2320de11defeSUlrich Drepper 				  (int __user *)a[2], a[3]);
2321aaca0bdcSUlrich Drepper 		break;
23221da177e4SLinus Torvalds 	default:
23231da177e4SLinus Torvalds 		err = -EINVAL;
23241da177e4SLinus Torvalds 		break;
23251da177e4SLinus Torvalds 	}
23261da177e4SLinus Torvalds 	return err;
23271da177e4SLinus Torvalds }
23281da177e4SLinus Torvalds 
23291da177e4SLinus Torvalds #endif				/* __ARCH_WANT_SYS_SOCKETCALL */
23301da177e4SLinus Torvalds 
233155737fdaSStephen Hemminger /**
233255737fdaSStephen Hemminger  *	sock_register - add a socket protocol handler
233355737fdaSStephen Hemminger  *	@ops: description of protocol
233455737fdaSStephen Hemminger  *
23351da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
23361da177e4SLinus Torvalds  *	advertise its address family, and have it linked into the
233755737fdaSStephen Hemminger  *	socket interface. The value ops->family coresponds to the
233855737fdaSStephen Hemminger  *	socket system call protocol family.
23391da177e4SLinus Torvalds  */
2340f0fd27d4SStephen Hemminger int sock_register(const struct net_proto_family *ops)
23411da177e4SLinus Torvalds {
23421da177e4SLinus Torvalds 	int err;
23431da177e4SLinus Torvalds 
23441da177e4SLinus Torvalds 	if (ops->family >= NPROTO) {
234589bddce5SStephen Hemminger 		printk(KERN_CRIT "protocol %d >= NPROTO(%d)\n", ops->family,
234689bddce5SStephen Hemminger 		       NPROTO);
23471da177e4SLinus Torvalds 		return -ENOBUFS;
23481da177e4SLinus Torvalds 	}
234955737fdaSStephen Hemminger 
235055737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
235155737fdaSStephen Hemminger 	if (net_families[ops->family])
23521da177e4SLinus Torvalds 		err = -EEXIST;
235355737fdaSStephen Hemminger 	else {
23541da177e4SLinus Torvalds 		net_families[ops->family] = ops;
23551da177e4SLinus Torvalds 		err = 0;
23561da177e4SLinus Torvalds 	}
235755737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
235855737fdaSStephen Hemminger 
235989bddce5SStephen Hemminger 	printk(KERN_INFO "NET: Registered protocol family %d\n", ops->family);
23601da177e4SLinus Torvalds 	return err;
23611da177e4SLinus Torvalds }
2362c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_register);
23631da177e4SLinus Torvalds 
236455737fdaSStephen Hemminger /**
236555737fdaSStephen Hemminger  *	sock_unregister - remove a protocol handler
236655737fdaSStephen Hemminger  *	@family: protocol family to remove
236755737fdaSStephen Hemminger  *
23681da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
23691da177e4SLinus Torvalds  *	remove its address family, and have it unlinked from the
237055737fdaSStephen Hemminger  *	new socket creation.
237155737fdaSStephen Hemminger  *
237255737fdaSStephen Hemminger  *	If protocol handler is a module, then it can use module reference
237355737fdaSStephen Hemminger  *	counts to protect against new references. If protocol handler is not
237455737fdaSStephen Hemminger  *	a module then it needs to provide its own protection in
237555737fdaSStephen Hemminger  *	the ops->create routine.
23761da177e4SLinus Torvalds  */
2377f0fd27d4SStephen Hemminger void sock_unregister(int family)
23781da177e4SLinus Torvalds {
2379f0fd27d4SStephen Hemminger 	BUG_ON(family < 0 || family >= NPROTO);
23801da177e4SLinus Torvalds 
238155737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
23821da177e4SLinus Torvalds 	net_families[family] = NULL;
238355737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
238455737fdaSStephen Hemminger 
238555737fdaSStephen Hemminger 	synchronize_rcu();
238655737fdaSStephen Hemminger 
238789bddce5SStephen Hemminger 	printk(KERN_INFO "NET: Unregistered protocol family %d\n", family);
23881da177e4SLinus Torvalds }
2389c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_unregister);
23901da177e4SLinus Torvalds 
239177d76ea3SAndi Kleen static int __init sock_init(void)
23921da177e4SLinus Torvalds {
23931da177e4SLinus Torvalds 	/*
23941da177e4SLinus Torvalds 	 *      Initialize sock SLAB cache.
23951da177e4SLinus Torvalds 	 */
23961da177e4SLinus Torvalds 
23971da177e4SLinus Torvalds 	sk_init();
23981da177e4SLinus Torvalds 
23991da177e4SLinus Torvalds 	/*
24001da177e4SLinus Torvalds 	 *      Initialize skbuff SLAB cache
24011da177e4SLinus Torvalds 	 */
24021da177e4SLinus Torvalds 	skb_init();
24031da177e4SLinus Torvalds 
24041da177e4SLinus Torvalds 	/*
24051da177e4SLinus Torvalds 	 *      Initialize the protocols module.
24061da177e4SLinus Torvalds 	 */
24071da177e4SLinus Torvalds 
24081da177e4SLinus Torvalds 	init_inodecache();
24091da177e4SLinus Torvalds 	register_filesystem(&sock_fs_type);
24101da177e4SLinus Torvalds 	sock_mnt = kern_mount(&sock_fs_type);
241177d76ea3SAndi Kleen 
241277d76ea3SAndi Kleen 	/* The real protocol initialization is performed in later initcalls.
24131da177e4SLinus Torvalds 	 */
24141da177e4SLinus Torvalds 
24151da177e4SLinus Torvalds #ifdef CONFIG_NETFILTER
24161da177e4SLinus Torvalds 	netfilter_init();
24171da177e4SLinus Torvalds #endif
2418cbeb321aSDavid S. Miller 
2419c1f19b51SRichard Cochran #ifdef CONFIG_NETWORK_PHY_TIMESTAMPING
2420c1f19b51SRichard Cochran 	skb_timestamping_init();
2421c1f19b51SRichard Cochran #endif
2422c1f19b51SRichard Cochran 
2423cbeb321aSDavid S. Miller 	return 0;
24241da177e4SLinus Torvalds }
24251da177e4SLinus Torvalds 
242677d76ea3SAndi Kleen core_initcall(sock_init);	/* early initcall */
242777d76ea3SAndi Kleen 
24281da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS
24291da177e4SLinus Torvalds void socket_seq_show(struct seq_file *seq)
24301da177e4SLinus Torvalds {
24311da177e4SLinus Torvalds 	int cpu;
24321da177e4SLinus Torvalds 	int counter = 0;
24331da177e4SLinus Torvalds 
24346f912042SKAMEZAWA Hiroyuki 	for_each_possible_cpu(cpu)
24351da177e4SLinus Torvalds 	    counter += per_cpu(sockets_in_use, cpu);
24361da177e4SLinus Torvalds 
24371da177e4SLinus Torvalds 	/* It can be negative, by the way. 8) */
24381da177e4SLinus Torvalds 	if (counter < 0)
24391da177e4SLinus Torvalds 		counter = 0;
24401da177e4SLinus Torvalds 
24411da177e4SLinus Torvalds 	seq_printf(seq, "sockets: used %d\n", counter);
24421da177e4SLinus Torvalds }
24431da177e4SLinus Torvalds #endif				/* CONFIG_PROC_FS */
24441da177e4SLinus Torvalds 
244589bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
24466b96018bSArnd Bergmann static int do_siocgstamp(struct net *net, struct socket *sock,
24476b96018bSArnd Bergmann 			 unsigned int cmd, struct compat_timeval __user *up)
24487a229387SArnd Bergmann {
24497a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
24507a229387SArnd Bergmann 	struct timeval ktv;
24517a229387SArnd Bergmann 	int err;
24527a229387SArnd Bergmann 
24537a229387SArnd Bergmann 	set_fs(KERNEL_DS);
24546b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv);
24557a229387SArnd Bergmann 	set_fs(old_fs);
24567a229387SArnd Bergmann 	if (!err) {
24577a229387SArnd Bergmann 		err = put_user(ktv.tv_sec, &up->tv_sec);
24587a229387SArnd Bergmann 		err |= __put_user(ktv.tv_usec, &up->tv_usec);
24597a229387SArnd Bergmann 	}
24607a229387SArnd Bergmann 	return err;
24617a229387SArnd Bergmann }
24627a229387SArnd Bergmann 
24636b96018bSArnd Bergmann static int do_siocgstampns(struct net *net, struct socket *sock,
24646b96018bSArnd Bergmann 			 unsigned int cmd, struct compat_timespec __user *up)
24657a229387SArnd Bergmann {
24667a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
24677a229387SArnd Bergmann 	struct timespec kts;
24687a229387SArnd Bergmann 	int err;
24697a229387SArnd Bergmann 
24707a229387SArnd Bergmann 	set_fs(KERNEL_DS);
24716b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts);
24727a229387SArnd Bergmann 	set_fs(old_fs);
24737a229387SArnd Bergmann 	if (!err) {
24747a229387SArnd Bergmann 		err = put_user(kts.tv_sec, &up->tv_sec);
24757a229387SArnd Bergmann 		err |= __put_user(kts.tv_nsec, &up->tv_nsec);
24767a229387SArnd Bergmann 	}
24777a229387SArnd Bergmann 	return err;
24787a229387SArnd Bergmann }
24797a229387SArnd Bergmann 
24806b96018bSArnd Bergmann static int dev_ifname32(struct net *net, struct compat_ifreq __user *uifr32)
24817a229387SArnd Bergmann {
24827a229387SArnd Bergmann 	struct ifreq __user *uifr;
24837a229387SArnd Bergmann 	int err;
24847a229387SArnd Bergmann 
24857a229387SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(struct ifreq));
24866b96018bSArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
24877a229387SArnd Bergmann 		return -EFAULT;
24887a229387SArnd Bergmann 
24896b96018bSArnd Bergmann 	err = dev_ioctl(net, SIOCGIFNAME, uifr);
24907a229387SArnd Bergmann 	if (err)
24917a229387SArnd Bergmann 		return err;
24927a229387SArnd Bergmann 
24936b96018bSArnd Bergmann 	if (copy_in_user(uifr32, uifr, sizeof(struct compat_ifreq)))
24947a229387SArnd Bergmann 		return -EFAULT;
24957a229387SArnd Bergmann 
24967a229387SArnd Bergmann 	return 0;
24977a229387SArnd Bergmann }
24987a229387SArnd Bergmann 
24996b96018bSArnd Bergmann static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32)
25007a229387SArnd Bergmann {
25016b96018bSArnd Bergmann 	struct compat_ifconf ifc32;
25027a229387SArnd Bergmann 	struct ifconf ifc;
25037a229387SArnd Bergmann 	struct ifconf __user *uifc;
25046b96018bSArnd Bergmann 	struct compat_ifreq __user *ifr32;
25057a229387SArnd Bergmann 	struct ifreq __user *ifr;
25067a229387SArnd Bergmann 	unsigned int i, j;
25077a229387SArnd Bergmann 	int err;
25087a229387SArnd Bergmann 
25096b96018bSArnd Bergmann 	if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf)))
25107a229387SArnd Bergmann 		return -EFAULT;
25117a229387SArnd Bergmann 
25127a229387SArnd Bergmann 	if (ifc32.ifcbuf == 0) {
25137a229387SArnd Bergmann 		ifc32.ifc_len = 0;
25147a229387SArnd Bergmann 		ifc.ifc_len = 0;
25157a229387SArnd Bergmann 		ifc.ifc_req = NULL;
25167a229387SArnd Bergmann 		uifc = compat_alloc_user_space(sizeof(struct ifconf));
25177a229387SArnd Bergmann 	} else {
25186b96018bSArnd Bergmann 		size_t len = ((ifc32.ifc_len / sizeof(struct compat_ifreq)) + 1) *
25197a229387SArnd Bergmann 			sizeof(struct ifreq);
25207a229387SArnd Bergmann 		uifc = compat_alloc_user_space(sizeof(struct ifconf) + len);
25217a229387SArnd Bergmann 		ifc.ifc_len = len;
25227a229387SArnd Bergmann 		ifr = ifc.ifc_req = (void __user *)(uifc + 1);
25237a229387SArnd Bergmann 		ifr32 = compat_ptr(ifc32.ifcbuf);
25246b96018bSArnd Bergmann 		for (i = 0; i < ifc32.ifc_len; i += sizeof(struct compat_ifreq)) {
25256b96018bSArnd Bergmann 			if (copy_in_user(ifr, ifr32, sizeof(struct compat_ifreq)))
25267a229387SArnd Bergmann 				return -EFAULT;
25277a229387SArnd Bergmann 			ifr++;
25287a229387SArnd Bergmann 			ifr32++;
25297a229387SArnd Bergmann 		}
25307a229387SArnd Bergmann 	}
25317a229387SArnd Bergmann 	if (copy_to_user(uifc, &ifc, sizeof(struct ifconf)))
25327a229387SArnd Bergmann 		return -EFAULT;
25337a229387SArnd Bergmann 
25346b96018bSArnd Bergmann 	err = dev_ioctl(net, SIOCGIFCONF, uifc);
25357a229387SArnd Bergmann 	if (err)
25367a229387SArnd Bergmann 		return err;
25377a229387SArnd Bergmann 
25387a229387SArnd Bergmann 	if (copy_from_user(&ifc, uifc, sizeof(struct ifconf)))
25397a229387SArnd Bergmann 		return -EFAULT;
25407a229387SArnd Bergmann 
25417a229387SArnd Bergmann 	ifr = ifc.ifc_req;
25427a229387SArnd Bergmann 	ifr32 = compat_ptr(ifc32.ifcbuf);
25437a229387SArnd Bergmann 	for (i = 0, j = 0;
25446b96018bSArnd Bergmann 	     i + sizeof(struct compat_ifreq) <= ifc32.ifc_len && j < ifc.ifc_len;
25456b96018bSArnd Bergmann 	     i += sizeof(struct compat_ifreq), j += sizeof(struct ifreq)) {
25466b96018bSArnd Bergmann 		if (copy_in_user(ifr32, ifr, sizeof(struct compat_ifreq)))
25477a229387SArnd Bergmann 			return -EFAULT;
25487a229387SArnd Bergmann 		ifr32++;
25497a229387SArnd Bergmann 		ifr++;
25507a229387SArnd Bergmann 	}
25517a229387SArnd Bergmann 
25527a229387SArnd Bergmann 	if (ifc32.ifcbuf == 0) {
25537a229387SArnd Bergmann 		/* Translate from 64-bit structure multiple to
25547a229387SArnd Bergmann 		 * a 32-bit one.
25557a229387SArnd Bergmann 		 */
25567a229387SArnd Bergmann 		i = ifc.ifc_len;
25576b96018bSArnd Bergmann 		i = ((i / sizeof(struct ifreq)) * sizeof(struct compat_ifreq));
25587a229387SArnd Bergmann 		ifc32.ifc_len = i;
25597a229387SArnd Bergmann 	} else {
25607a229387SArnd Bergmann 		ifc32.ifc_len = i;
25617a229387SArnd Bergmann 	}
25626b96018bSArnd Bergmann 	if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf)))
25637a229387SArnd Bergmann 		return -EFAULT;
25647a229387SArnd Bergmann 
25657a229387SArnd Bergmann 	return 0;
25667a229387SArnd Bergmann }
25677a229387SArnd Bergmann 
25686b96018bSArnd Bergmann static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
25697a229387SArnd Bergmann {
25707a229387SArnd Bergmann 	struct ifreq __user *ifr;
25717a229387SArnd Bergmann 	u32 data;
25727a229387SArnd Bergmann 	void __user *datap;
25737a229387SArnd Bergmann 
25747a229387SArnd Bergmann 	ifr = compat_alloc_user_space(sizeof(*ifr));
25757a229387SArnd Bergmann 
25767a229387SArnd Bergmann 	if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
25777a229387SArnd Bergmann 		return -EFAULT;
25787a229387SArnd Bergmann 
25797a229387SArnd Bergmann 	if (get_user(data, &ifr32->ifr_ifru.ifru_data))
25807a229387SArnd Bergmann 		return -EFAULT;
25817a229387SArnd Bergmann 
25827a229387SArnd Bergmann 	datap = compat_ptr(data);
25837a229387SArnd Bergmann 	if (put_user(datap, &ifr->ifr_ifru.ifru_data))
25847a229387SArnd Bergmann 		return -EFAULT;
25857a229387SArnd Bergmann 
25866b96018bSArnd Bergmann 	return dev_ioctl(net, SIOCETHTOOL, ifr);
25877a229387SArnd Bergmann }
25887a229387SArnd Bergmann 
25897a50a240SArnd Bergmann static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32)
25907a50a240SArnd Bergmann {
25917a50a240SArnd Bergmann 	void __user *uptr;
25927a50a240SArnd Bergmann 	compat_uptr_t uptr32;
25937a50a240SArnd Bergmann 	struct ifreq __user *uifr;
25947a50a240SArnd Bergmann 
25957a50a240SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
25967a50a240SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
25977a50a240SArnd Bergmann 		return -EFAULT;
25987a50a240SArnd Bergmann 
25997a50a240SArnd Bergmann 	if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu))
26007a50a240SArnd Bergmann 		return -EFAULT;
26017a50a240SArnd Bergmann 
26027a50a240SArnd Bergmann 	uptr = compat_ptr(uptr32);
26037a50a240SArnd Bergmann 
26047a50a240SArnd Bergmann 	if (put_user(uptr, &uifr->ifr_settings.ifs_ifsu.raw_hdlc))
26057a50a240SArnd Bergmann 		return -EFAULT;
26067a50a240SArnd Bergmann 
26077a50a240SArnd Bergmann 	return dev_ioctl(net, SIOCWANDEV, uifr);
26087a50a240SArnd Bergmann }
26097a50a240SArnd Bergmann 
26106b96018bSArnd Bergmann static int bond_ioctl(struct net *net, unsigned int cmd,
26116b96018bSArnd Bergmann 			 struct compat_ifreq __user *ifr32)
26127a229387SArnd Bergmann {
26137a229387SArnd Bergmann 	struct ifreq kifr;
26147a229387SArnd Bergmann 	struct ifreq __user *uifr;
26157a229387SArnd Bergmann 	mm_segment_t old_fs;
26167a229387SArnd Bergmann 	int err;
26177a229387SArnd Bergmann 	u32 data;
26187a229387SArnd Bergmann 	void __user *datap;
26197a229387SArnd Bergmann 
26207a229387SArnd Bergmann 	switch (cmd) {
26217a229387SArnd Bergmann 	case SIOCBONDENSLAVE:
26227a229387SArnd Bergmann 	case SIOCBONDRELEASE:
26237a229387SArnd Bergmann 	case SIOCBONDSETHWADDR:
26247a229387SArnd Bergmann 	case SIOCBONDCHANGEACTIVE:
26256b96018bSArnd Bergmann 		if (copy_from_user(&kifr, ifr32, sizeof(struct compat_ifreq)))
26267a229387SArnd Bergmann 			return -EFAULT;
26277a229387SArnd Bergmann 
26287a229387SArnd Bergmann 		old_fs = get_fs();
26297a229387SArnd Bergmann 		set_fs(KERNEL_DS);
26306b96018bSArnd Bergmann 		err = dev_ioctl(net, cmd, &kifr);
26317a229387SArnd Bergmann 		set_fs(old_fs);
26327a229387SArnd Bergmann 
26337a229387SArnd Bergmann 		return err;
26347a229387SArnd Bergmann 	case SIOCBONDSLAVEINFOQUERY:
26357a229387SArnd Bergmann 	case SIOCBONDINFOQUERY:
26367a229387SArnd Bergmann 		uifr = compat_alloc_user_space(sizeof(*uifr));
26377a229387SArnd Bergmann 		if (copy_in_user(&uifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
26387a229387SArnd Bergmann 			return -EFAULT;
26397a229387SArnd Bergmann 
26407a229387SArnd Bergmann 		if (get_user(data, &ifr32->ifr_ifru.ifru_data))
26417a229387SArnd Bergmann 			return -EFAULT;
26427a229387SArnd Bergmann 
26437a229387SArnd Bergmann 		datap = compat_ptr(data);
26447a229387SArnd Bergmann 		if (put_user(datap, &uifr->ifr_ifru.ifru_data))
26457a229387SArnd Bergmann 			return -EFAULT;
26467a229387SArnd Bergmann 
26476b96018bSArnd Bergmann 		return dev_ioctl(net, cmd, uifr);
26487a229387SArnd Bergmann 	default:
26497a229387SArnd Bergmann 		return -EINVAL;
2650ccbd6a5aSJoe Perches 	}
26517a229387SArnd Bergmann }
26527a229387SArnd Bergmann 
26536b96018bSArnd Bergmann static int siocdevprivate_ioctl(struct net *net, unsigned int cmd,
26546b96018bSArnd Bergmann 				 struct compat_ifreq __user *u_ifreq32)
26557a229387SArnd Bergmann {
26567a229387SArnd Bergmann 	struct ifreq __user *u_ifreq64;
26577a229387SArnd Bergmann 	char tmp_buf[IFNAMSIZ];
26587a229387SArnd Bergmann 	void __user *data64;
26597a229387SArnd Bergmann 	u32 data32;
26607a229387SArnd Bergmann 
26617a229387SArnd Bergmann 	if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]),
26627a229387SArnd Bergmann 			   IFNAMSIZ))
26637a229387SArnd Bergmann 		return -EFAULT;
26647a229387SArnd Bergmann 	if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data))
26657a229387SArnd Bergmann 		return -EFAULT;
26667a229387SArnd Bergmann 	data64 = compat_ptr(data32);
26677a229387SArnd Bergmann 
26687a229387SArnd Bergmann 	u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
26697a229387SArnd Bergmann 
26707a229387SArnd Bergmann 	/* Don't check these user accesses, just let that get trapped
26717a229387SArnd Bergmann 	 * in the ioctl handler instead.
26727a229387SArnd Bergmann 	 */
26737a229387SArnd Bergmann 	if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0],
26747a229387SArnd Bergmann 			 IFNAMSIZ))
26757a229387SArnd Bergmann 		return -EFAULT;
26767a229387SArnd Bergmann 	if (__put_user(data64, &u_ifreq64->ifr_ifru.ifru_data))
26777a229387SArnd Bergmann 		return -EFAULT;
26787a229387SArnd Bergmann 
26796b96018bSArnd Bergmann 	return dev_ioctl(net, cmd, u_ifreq64);
26807a229387SArnd Bergmann }
26817a229387SArnd Bergmann 
26826b96018bSArnd Bergmann static int dev_ifsioc(struct net *net, struct socket *sock,
26836b96018bSArnd Bergmann 			 unsigned int cmd, struct compat_ifreq __user *uifr32)
26847a229387SArnd Bergmann {
2685a2116ed2SArnd Bergmann 	struct ifreq __user *uifr;
26867a229387SArnd Bergmann 	int err;
26877a229387SArnd Bergmann 
2688a2116ed2SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
2689a2116ed2SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(*uifr32)))
26907a229387SArnd Bergmann 		return -EFAULT;
2691a2116ed2SArnd Bergmann 
2692a2116ed2SArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr);
2693a2116ed2SArnd Bergmann 
26947a229387SArnd Bergmann 	if (!err) {
26957a229387SArnd Bergmann 		switch (cmd) {
26967a229387SArnd Bergmann 		case SIOCGIFFLAGS:
26977a229387SArnd Bergmann 		case SIOCGIFMETRIC:
26987a229387SArnd Bergmann 		case SIOCGIFMTU:
26997a229387SArnd Bergmann 		case SIOCGIFMEM:
27007a229387SArnd Bergmann 		case SIOCGIFHWADDR:
27017a229387SArnd Bergmann 		case SIOCGIFINDEX:
27027a229387SArnd Bergmann 		case SIOCGIFADDR:
27037a229387SArnd Bergmann 		case SIOCGIFBRDADDR:
27047a229387SArnd Bergmann 		case SIOCGIFDSTADDR:
27057a229387SArnd Bergmann 		case SIOCGIFNETMASK:
2706fab2532bSArnd Bergmann 		case SIOCGIFPFLAGS:
27077a229387SArnd Bergmann 		case SIOCGIFTXQLEN:
2708fab2532bSArnd Bergmann 		case SIOCGMIIPHY:
2709fab2532bSArnd Bergmann 		case SIOCGMIIREG:
2710a2116ed2SArnd Bergmann 			if (copy_in_user(uifr32, uifr, sizeof(*uifr32)))
2711a2116ed2SArnd Bergmann 				err = -EFAULT;
27127a229387SArnd Bergmann 			break;
2713a2116ed2SArnd Bergmann 		}
2714a2116ed2SArnd Bergmann 	}
2715a2116ed2SArnd Bergmann 	return err;
2716a2116ed2SArnd Bergmann }
2717a2116ed2SArnd Bergmann 
2718a2116ed2SArnd Bergmann static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
2719a2116ed2SArnd Bergmann 			struct compat_ifreq __user *uifr32)
2720a2116ed2SArnd Bergmann {
2721a2116ed2SArnd Bergmann 	struct ifreq ifr;
2722a2116ed2SArnd Bergmann 	struct compat_ifmap __user *uifmap32;
2723a2116ed2SArnd Bergmann 	mm_segment_t old_fs;
2724a2116ed2SArnd Bergmann 	int err;
2725a2116ed2SArnd Bergmann 
2726a2116ed2SArnd Bergmann 	uifmap32 = &uifr32->ifr_ifru.ifru_map;
2727a2116ed2SArnd Bergmann 	err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name));
2728a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
2729a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
2730a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
2731a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.irq, &uifmap32->irq);
2732a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.dma, &uifmap32->dma);
2733a2116ed2SArnd Bergmann 	err |= __get_user(ifr.ifr_map.port, &uifmap32->port);
2734a2116ed2SArnd Bergmann 	if (err)
2735a2116ed2SArnd Bergmann 		return -EFAULT;
2736a2116ed2SArnd Bergmann 
2737a2116ed2SArnd Bergmann 	old_fs = get_fs();
2738a2116ed2SArnd Bergmann 	set_fs(KERNEL_DS);
2739a2116ed2SArnd Bergmann 	err = dev_ioctl(net, cmd, (void __user *)&ifr);
2740a2116ed2SArnd Bergmann 	set_fs(old_fs);
2741a2116ed2SArnd Bergmann 
2742a2116ed2SArnd Bergmann 	if (cmd == SIOCGIFMAP && !err) {
27437a229387SArnd Bergmann 		err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name));
27447a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
27457a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
27467a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
27477a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.irq, &uifmap32->irq);
27487a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.dma, &uifmap32->dma);
27497a229387SArnd Bergmann 		err |= __put_user(ifr.ifr_map.port, &uifmap32->port);
27507a229387SArnd Bergmann 		if (err)
27517a229387SArnd Bergmann 			err = -EFAULT;
27527a229387SArnd Bergmann 	}
27537a229387SArnd Bergmann 	return err;
27547a229387SArnd Bergmann }
27557a229387SArnd Bergmann 
2756a2116ed2SArnd Bergmann static int compat_siocshwtstamp(struct net *net, struct compat_ifreq __user *uifr32)
2757a2116ed2SArnd Bergmann {
2758a2116ed2SArnd Bergmann 	void __user *uptr;
2759a2116ed2SArnd Bergmann 	compat_uptr_t uptr32;
2760a2116ed2SArnd Bergmann 	struct ifreq __user *uifr;
2761a2116ed2SArnd Bergmann 
2762a2116ed2SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
2763a2116ed2SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
2764a2116ed2SArnd Bergmann 		return -EFAULT;
2765a2116ed2SArnd Bergmann 
2766a2116ed2SArnd Bergmann 	if (get_user(uptr32, &uifr32->ifr_data))
2767a2116ed2SArnd Bergmann 		return -EFAULT;
2768a2116ed2SArnd Bergmann 
2769a2116ed2SArnd Bergmann 	uptr = compat_ptr(uptr32);
2770a2116ed2SArnd Bergmann 
2771a2116ed2SArnd Bergmann 	if (put_user(uptr, &uifr->ifr_data))
2772a2116ed2SArnd Bergmann 		return -EFAULT;
2773a2116ed2SArnd Bergmann 
2774a2116ed2SArnd Bergmann 	return dev_ioctl(net, SIOCSHWTSTAMP, uifr);
2775a2116ed2SArnd Bergmann }
2776a2116ed2SArnd Bergmann 
27777a229387SArnd Bergmann struct rtentry32 {
27787a229387SArnd Bergmann 	u32		rt_pad1;
27797a229387SArnd Bergmann 	struct sockaddr rt_dst;         /* target address               */
27807a229387SArnd Bergmann 	struct sockaddr rt_gateway;     /* gateway addr (RTF_GATEWAY)   */
27817a229387SArnd Bergmann 	struct sockaddr rt_genmask;     /* target network mask (IP)     */
27827a229387SArnd Bergmann 	unsigned short	rt_flags;
27837a229387SArnd Bergmann 	short		rt_pad2;
27847a229387SArnd Bergmann 	u32		rt_pad3;
27857a229387SArnd Bergmann 	unsigned char	rt_tos;
27867a229387SArnd Bergmann 	unsigned char	rt_class;
27877a229387SArnd Bergmann 	short		rt_pad4;
27887a229387SArnd Bergmann 	short		rt_metric;      /* +1 for binary compatibility! */
27897a229387SArnd Bergmann 	/* char * */ u32 rt_dev;        /* forcing the device at add    */
27907a229387SArnd Bergmann 	u32		rt_mtu;         /* per route MTU/Window         */
27917a229387SArnd Bergmann 	u32		rt_window;      /* Window clamping              */
27927a229387SArnd Bergmann 	unsigned short  rt_irtt;        /* Initial RTT                  */
27937a229387SArnd Bergmann };
27947a229387SArnd Bergmann 
27957a229387SArnd Bergmann struct in6_rtmsg32 {
27967a229387SArnd Bergmann 	struct in6_addr		rtmsg_dst;
27977a229387SArnd Bergmann 	struct in6_addr		rtmsg_src;
27987a229387SArnd Bergmann 	struct in6_addr		rtmsg_gateway;
27997a229387SArnd Bergmann 	u32			rtmsg_type;
28007a229387SArnd Bergmann 	u16			rtmsg_dst_len;
28017a229387SArnd Bergmann 	u16			rtmsg_src_len;
28027a229387SArnd Bergmann 	u32			rtmsg_metric;
28037a229387SArnd Bergmann 	u32			rtmsg_info;
28047a229387SArnd Bergmann 	u32			rtmsg_flags;
28057a229387SArnd Bergmann 	s32			rtmsg_ifindex;
28067a229387SArnd Bergmann };
28077a229387SArnd Bergmann 
28086b96018bSArnd Bergmann static int routing_ioctl(struct net *net, struct socket *sock,
28096b96018bSArnd Bergmann 			 unsigned int cmd, void __user *argp)
28107a229387SArnd Bergmann {
28117a229387SArnd Bergmann 	int ret;
28127a229387SArnd Bergmann 	void *r = NULL;
28137a229387SArnd Bergmann 	struct in6_rtmsg r6;
28147a229387SArnd Bergmann 	struct rtentry r4;
28157a229387SArnd Bergmann 	char devname[16];
28167a229387SArnd Bergmann 	u32 rtdev;
28177a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
28187a229387SArnd Bergmann 
28196b96018bSArnd Bergmann 	if (sock && sock->sk && sock->sk->sk_family == AF_INET6) { /* ipv6 */
28206b96018bSArnd Bergmann 		struct in6_rtmsg32 __user *ur6 = argp;
28217a229387SArnd Bergmann 		ret = copy_from_user(&r6.rtmsg_dst, &(ur6->rtmsg_dst),
28227a229387SArnd Bergmann 			3 * sizeof(struct in6_addr));
28237a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_type, &(ur6->rtmsg_type));
28247a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len));
28257a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_src_len, &(ur6->rtmsg_src_len));
28267a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_metric, &(ur6->rtmsg_metric));
28277a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_info, &(ur6->rtmsg_info));
28287a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_flags, &(ur6->rtmsg_flags));
28297a229387SArnd Bergmann 		ret |= __get_user(r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex));
28307a229387SArnd Bergmann 
28317a229387SArnd Bergmann 		r = (void *) &r6;
28327a229387SArnd Bergmann 	} else { /* ipv4 */
28336b96018bSArnd Bergmann 		struct rtentry32 __user *ur4 = argp;
28347a229387SArnd Bergmann 		ret = copy_from_user(&r4.rt_dst, &(ur4->rt_dst),
28357a229387SArnd Bergmann 					3 * sizeof(struct sockaddr));
28367a229387SArnd Bergmann 		ret |= __get_user(r4.rt_flags, &(ur4->rt_flags));
28377a229387SArnd Bergmann 		ret |= __get_user(r4.rt_metric, &(ur4->rt_metric));
28387a229387SArnd Bergmann 		ret |= __get_user(r4.rt_mtu, &(ur4->rt_mtu));
28397a229387SArnd Bergmann 		ret |= __get_user(r4.rt_window, &(ur4->rt_window));
28407a229387SArnd Bergmann 		ret |= __get_user(r4.rt_irtt, &(ur4->rt_irtt));
28417a229387SArnd Bergmann 		ret |= __get_user(rtdev, &(ur4->rt_dev));
28427a229387SArnd Bergmann 		if (rtdev) {
28437a229387SArnd Bergmann 			ret |= copy_from_user(devname, compat_ptr(rtdev), 15);
28447a229387SArnd Bergmann 			r4.rt_dev = devname; devname[15] = 0;
28457a229387SArnd Bergmann 		} else
28467a229387SArnd Bergmann 			r4.rt_dev = NULL;
28477a229387SArnd Bergmann 
28487a229387SArnd Bergmann 		r = (void *) &r4;
28497a229387SArnd Bergmann 	}
28507a229387SArnd Bergmann 
28517a229387SArnd Bergmann 	if (ret) {
28527a229387SArnd Bergmann 		ret = -EFAULT;
28537a229387SArnd Bergmann 		goto out;
28547a229387SArnd Bergmann 	}
28557a229387SArnd Bergmann 
28567a229387SArnd Bergmann 	set_fs(KERNEL_DS);
28576b96018bSArnd Bergmann 	ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r);
28587a229387SArnd Bergmann 	set_fs(old_fs);
28597a229387SArnd Bergmann 
28607a229387SArnd Bergmann out:
28617a229387SArnd Bergmann 	return ret;
28627a229387SArnd Bergmann }
28637a229387SArnd Bergmann 
28647a229387SArnd Bergmann /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE
28657a229387SArnd Bergmann  * for some operations; this forces use of the newer bridge-utils that
28667a229387SArnd Bergmann  * use compatiable ioctls
28677a229387SArnd Bergmann  */
28686b96018bSArnd Bergmann static int old_bridge_ioctl(compat_ulong_t __user *argp)
28697a229387SArnd Bergmann {
28706b96018bSArnd Bergmann 	compat_ulong_t tmp;
28717a229387SArnd Bergmann 
28726b96018bSArnd Bergmann 	if (get_user(tmp, argp))
28737a229387SArnd Bergmann 		return -EFAULT;
28747a229387SArnd Bergmann 	if (tmp == BRCTL_GET_VERSION)
28757a229387SArnd Bergmann 		return BRCTL_VERSION + 1;
28767a229387SArnd Bergmann 	return -EINVAL;
28777a229387SArnd Bergmann }
28787a229387SArnd Bergmann 
28796b96018bSArnd Bergmann static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
28806b96018bSArnd Bergmann 			 unsigned int cmd, unsigned long arg)
28816b96018bSArnd Bergmann {
28826b96018bSArnd Bergmann 	void __user *argp = compat_ptr(arg);
28836b96018bSArnd Bergmann 	struct sock *sk = sock->sk;
28846b96018bSArnd Bergmann 	struct net *net = sock_net(sk);
28857a229387SArnd Bergmann 
28866b96018bSArnd Bergmann 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
28876b96018bSArnd Bergmann 		return siocdevprivate_ioctl(net, cmd, argp);
28887a229387SArnd Bergmann 
28896b96018bSArnd Bergmann 	switch (cmd) {
28906b96018bSArnd Bergmann 	case SIOCSIFBR:
28916b96018bSArnd Bergmann 	case SIOCGIFBR:
28926b96018bSArnd Bergmann 		return old_bridge_ioctl(argp);
28936b96018bSArnd Bergmann 	case SIOCGIFNAME:
28946b96018bSArnd Bergmann 		return dev_ifname32(net, argp);
28956b96018bSArnd Bergmann 	case SIOCGIFCONF:
28966b96018bSArnd Bergmann 		return dev_ifconf(net, argp);
28976b96018bSArnd Bergmann 	case SIOCETHTOOL:
28986b96018bSArnd Bergmann 		return ethtool_ioctl(net, argp);
28997a50a240SArnd Bergmann 	case SIOCWANDEV:
29007a50a240SArnd Bergmann 		return compat_siocwandev(net, argp);
2901a2116ed2SArnd Bergmann 	case SIOCGIFMAP:
2902a2116ed2SArnd Bergmann 	case SIOCSIFMAP:
2903a2116ed2SArnd Bergmann 		return compat_sioc_ifmap(net, cmd, argp);
29046b96018bSArnd Bergmann 	case SIOCBONDENSLAVE:
29056b96018bSArnd Bergmann 	case SIOCBONDRELEASE:
29066b96018bSArnd Bergmann 	case SIOCBONDSETHWADDR:
29076b96018bSArnd Bergmann 	case SIOCBONDSLAVEINFOQUERY:
29086b96018bSArnd Bergmann 	case SIOCBONDINFOQUERY:
29096b96018bSArnd Bergmann 	case SIOCBONDCHANGEACTIVE:
29106b96018bSArnd Bergmann 		return bond_ioctl(net, cmd, argp);
29116b96018bSArnd Bergmann 	case SIOCADDRT:
29126b96018bSArnd Bergmann 	case SIOCDELRT:
29136b96018bSArnd Bergmann 		return routing_ioctl(net, sock, cmd, argp);
29146b96018bSArnd Bergmann 	case SIOCGSTAMP:
29156b96018bSArnd Bergmann 		return do_siocgstamp(net, sock, cmd, argp);
29166b96018bSArnd Bergmann 	case SIOCGSTAMPNS:
29176b96018bSArnd Bergmann 		return do_siocgstampns(net, sock, cmd, argp);
2918a2116ed2SArnd Bergmann 	case SIOCSHWTSTAMP:
2919a2116ed2SArnd Bergmann 		return compat_siocshwtstamp(net, argp);
29207a229387SArnd Bergmann 
29216b96018bSArnd Bergmann 	case FIOSETOWN:
29226b96018bSArnd Bergmann 	case SIOCSPGRP:
29236b96018bSArnd Bergmann 	case FIOGETOWN:
29246b96018bSArnd Bergmann 	case SIOCGPGRP:
29256b96018bSArnd Bergmann 	case SIOCBRADDBR:
29266b96018bSArnd Bergmann 	case SIOCBRDELBR:
29276b96018bSArnd Bergmann 	case SIOCGIFVLAN:
29286b96018bSArnd Bergmann 	case SIOCSIFVLAN:
29296b96018bSArnd Bergmann 	case SIOCADDDLCI:
29306b96018bSArnd Bergmann 	case SIOCDELDLCI:
29316b96018bSArnd Bergmann 		return sock_ioctl(file, cmd, arg);
29326b96018bSArnd Bergmann 
29336b96018bSArnd Bergmann 	case SIOCGIFFLAGS:
29346b96018bSArnd Bergmann 	case SIOCSIFFLAGS:
29356b96018bSArnd Bergmann 	case SIOCGIFMETRIC:
29366b96018bSArnd Bergmann 	case SIOCSIFMETRIC:
29376b96018bSArnd Bergmann 	case SIOCGIFMTU:
29386b96018bSArnd Bergmann 	case SIOCSIFMTU:
29396b96018bSArnd Bergmann 	case SIOCGIFMEM:
29406b96018bSArnd Bergmann 	case SIOCSIFMEM:
29416b96018bSArnd Bergmann 	case SIOCGIFHWADDR:
29426b96018bSArnd Bergmann 	case SIOCSIFHWADDR:
29436b96018bSArnd Bergmann 	case SIOCADDMULTI:
29446b96018bSArnd Bergmann 	case SIOCDELMULTI:
29456b96018bSArnd Bergmann 	case SIOCGIFINDEX:
29466b96018bSArnd Bergmann 	case SIOCGIFADDR:
29476b96018bSArnd Bergmann 	case SIOCSIFADDR:
29486b96018bSArnd Bergmann 	case SIOCSIFHWBROADCAST:
29496b96018bSArnd Bergmann 	case SIOCDIFADDR:
29506b96018bSArnd Bergmann 	case SIOCGIFBRDADDR:
29516b96018bSArnd Bergmann 	case SIOCSIFBRDADDR:
29526b96018bSArnd Bergmann 	case SIOCGIFDSTADDR:
29536b96018bSArnd Bergmann 	case SIOCSIFDSTADDR:
29546b96018bSArnd Bergmann 	case SIOCGIFNETMASK:
29556b96018bSArnd Bergmann 	case SIOCSIFNETMASK:
29566b96018bSArnd Bergmann 	case SIOCSIFPFLAGS:
29576b96018bSArnd Bergmann 	case SIOCGIFPFLAGS:
29586b96018bSArnd Bergmann 	case SIOCGIFTXQLEN:
29596b96018bSArnd Bergmann 	case SIOCSIFTXQLEN:
29606b96018bSArnd Bergmann 	case SIOCBRADDIF:
29616b96018bSArnd Bergmann 	case SIOCBRDELIF:
29629177efd3SArnd Bergmann 	case SIOCSIFNAME:
29639177efd3SArnd Bergmann 	case SIOCGMIIPHY:
29649177efd3SArnd Bergmann 	case SIOCGMIIREG:
29659177efd3SArnd Bergmann 	case SIOCSMIIREG:
29666b96018bSArnd Bergmann 		return dev_ifsioc(net, sock, cmd, argp);
29679177efd3SArnd Bergmann 
29686b96018bSArnd Bergmann 	case SIOCSARP:
29696b96018bSArnd Bergmann 	case SIOCGARP:
29706b96018bSArnd Bergmann 	case SIOCDARP:
29716b96018bSArnd Bergmann 	case SIOCATMARK:
29729177efd3SArnd Bergmann 		return sock_do_ioctl(net, sock, cmd, arg);
29739177efd3SArnd Bergmann 	}
29749177efd3SArnd Bergmann 
29759177efd3SArnd Bergmann 	/* Prevent warning from compat_sys_ioctl, these always
29769177efd3SArnd Bergmann 	 * result in -EINVAL in the native case anyway. */
29779177efd3SArnd Bergmann 	switch (cmd) {
29789177efd3SArnd Bergmann 	case SIOCRTMSG:
29799177efd3SArnd Bergmann 	case SIOCGIFCOUNT:
29806b96018bSArnd Bergmann 	case SIOCSRARP:
29816b96018bSArnd Bergmann 	case SIOCGRARP:
29826b96018bSArnd Bergmann 	case SIOCDRARP:
29839177efd3SArnd Bergmann 	case SIOCSIFLINK:
29849177efd3SArnd Bergmann 	case SIOCGIFSLAVE:
29859177efd3SArnd Bergmann 	case SIOCSIFSLAVE:
29869177efd3SArnd Bergmann 		return -EINVAL;
29876b96018bSArnd Bergmann 	}
29886b96018bSArnd Bergmann 
29896b96018bSArnd Bergmann 	return -ENOIOCTLCMD;
29906b96018bSArnd Bergmann }
29917a229387SArnd Bergmann 
299289bbfc95SShaun Pereira static long compat_sock_ioctl(struct file *file, unsigned cmd,
299389bbfc95SShaun Pereira 			      unsigned long arg)
299489bbfc95SShaun Pereira {
299589bbfc95SShaun Pereira 	struct socket *sock = file->private_data;
299689bbfc95SShaun Pereira 	int ret = -ENOIOCTLCMD;
299787de87d5SDavid S. Miller 	struct sock *sk;
299887de87d5SDavid S. Miller 	struct net *net;
299987de87d5SDavid S. Miller 
300087de87d5SDavid S. Miller 	sk = sock->sk;
300187de87d5SDavid S. Miller 	net = sock_net(sk);
300289bbfc95SShaun Pereira 
300389bbfc95SShaun Pereira 	if (sock->ops->compat_ioctl)
300489bbfc95SShaun Pereira 		ret = sock->ops->compat_ioctl(sock, cmd, arg);
300589bbfc95SShaun Pereira 
300687de87d5SDavid S. Miller 	if (ret == -ENOIOCTLCMD &&
300787de87d5SDavid S. Miller 	    (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST))
300887de87d5SDavid S. Miller 		ret = compat_wext_handle_ioctl(net, cmd, arg);
300987de87d5SDavid S. Miller 
30106b96018bSArnd Bergmann 	if (ret == -ENOIOCTLCMD)
30116b96018bSArnd Bergmann 		ret = compat_sock_ioctl_trans(file, sock, cmd, arg);
30126b96018bSArnd Bergmann 
301389bbfc95SShaun Pereira 	return ret;
301489bbfc95SShaun Pereira }
301589bbfc95SShaun Pereira #endif
301689bbfc95SShaun Pereira 
3017ac5a488eSSridhar Samudrala int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
3018ac5a488eSSridhar Samudrala {
3019ac5a488eSSridhar Samudrala 	return sock->ops->bind(sock, addr, addrlen);
3020ac5a488eSSridhar Samudrala }
3021c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_bind);
3022ac5a488eSSridhar Samudrala 
3023ac5a488eSSridhar Samudrala int kernel_listen(struct socket *sock, int backlog)
3024ac5a488eSSridhar Samudrala {
3025ac5a488eSSridhar Samudrala 	return sock->ops->listen(sock, backlog);
3026ac5a488eSSridhar Samudrala }
3027c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_listen);
3028ac5a488eSSridhar Samudrala 
3029ac5a488eSSridhar Samudrala int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
3030ac5a488eSSridhar Samudrala {
3031ac5a488eSSridhar Samudrala 	struct sock *sk = sock->sk;
3032ac5a488eSSridhar Samudrala 	int err;
3033ac5a488eSSridhar Samudrala 
3034ac5a488eSSridhar Samudrala 	err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
3035ac5a488eSSridhar Samudrala 			       newsock);
3036ac5a488eSSridhar Samudrala 	if (err < 0)
3037ac5a488eSSridhar Samudrala 		goto done;
3038ac5a488eSSridhar Samudrala 
3039ac5a488eSSridhar Samudrala 	err = sock->ops->accept(sock, *newsock, flags);
3040ac5a488eSSridhar Samudrala 	if (err < 0) {
3041ac5a488eSSridhar Samudrala 		sock_release(*newsock);
3042fa8705b0STony Battersby 		*newsock = NULL;
3043ac5a488eSSridhar Samudrala 		goto done;
3044ac5a488eSSridhar Samudrala 	}
3045ac5a488eSSridhar Samudrala 
3046ac5a488eSSridhar Samudrala 	(*newsock)->ops = sock->ops;
30471b08534eSWei Yongjun 	__module_get((*newsock)->ops->owner);
3048ac5a488eSSridhar Samudrala 
3049ac5a488eSSridhar Samudrala done:
3050ac5a488eSSridhar Samudrala 	return err;
3051ac5a488eSSridhar Samudrala }
3052c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_accept);
3053ac5a488eSSridhar Samudrala 
3054ac5a488eSSridhar Samudrala int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
3055ac5a488eSSridhar Samudrala 		   int flags)
3056ac5a488eSSridhar Samudrala {
3057ac5a488eSSridhar Samudrala 	return sock->ops->connect(sock, addr, addrlen, flags);
3058ac5a488eSSridhar Samudrala }
3059c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_connect);
3060ac5a488eSSridhar Samudrala 
3061ac5a488eSSridhar Samudrala int kernel_getsockname(struct socket *sock, struct sockaddr *addr,
3062ac5a488eSSridhar Samudrala 			 int *addrlen)
3063ac5a488eSSridhar Samudrala {
3064ac5a488eSSridhar Samudrala 	return sock->ops->getname(sock, addr, addrlen, 0);
3065ac5a488eSSridhar Samudrala }
3066c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockname);
3067ac5a488eSSridhar Samudrala 
3068ac5a488eSSridhar Samudrala int kernel_getpeername(struct socket *sock, struct sockaddr *addr,
3069ac5a488eSSridhar Samudrala 			 int *addrlen)
3070ac5a488eSSridhar Samudrala {
3071ac5a488eSSridhar Samudrala 	return sock->ops->getname(sock, addr, addrlen, 1);
3072ac5a488eSSridhar Samudrala }
3073c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getpeername);
3074ac5a488eSSridhar Samudrala 
3075ac5a488eSSridhar Samudrala int kernel_getsockopt(struct socket *sock, int level, int optname,
3076ac5a488eSSridhar Samudrala 			char *optval, int *optlen)
3077ac5a488eSSridhar Samudrala {
3078ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3079fb8621bbSNamhyung Kim 	char __user *uoptval;
3080fb8621bbSNamhyung Kim 	int __user *uoptlen;
3081ac5a488eSSridhar Samudrala 	int err;
3082ac5a488eSSridhar Samudrala 
3083fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3084fb8621bbSNamhyung Kim 	uoptlen = (int __user __force *) optlen;
3085fb8621bbSNamhyung Kim 
3086ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3087ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3088fb8621bbSNamhyung Kim 		err = sock_getsockopt(sock, level, optname, uoptval, uoptlen);
3089ac5a488eSSridhar Samudrala 	else
3090fb8621bbSNamhyung Kim 		err = sock->ops->getsockopt(sock, level, optname, uoptval,
3091fb8621bbSNamhyung Kim 					    uoptlen);
3092ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3093ac5a488eSSridhar Samudrala 	return err;
3094ac5a488eSSridhar Samudrala }
3095c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockopt);
3096ac5a488eSSridhar Samudrala 
3097ac5a488eSSridhar Samudrala int kernel_setsockopt(struct socket *sock, int level, int optname,
3098b7058842SDavid S. Miller 			char *optval, unsigned int optlen)
3099ac5a488eSSridhar Samudrala {
3100ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3101fb8621bbSNamhyung Kim 	char __user *uoptval;
3102ac5a488eSSridhar Samudrala 	int err;
3103ac5a488eSSridhar Samudrala 
3104fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3105fb8621bbSNamhyung Kim 
3106ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3107ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3108fb8621bbSNamhyung Kim 		err = sock_setsockopt(sock, level, optname, uoptval, optlen);
3109ac5a488eSSridhar Samudrala 	else
3110fb8621bbSNamhyung Kim 		err = sock->ops->setsockopt(sock, level, optname, uoptval,
3111ac5a488eSSridhar Samudrala 					    optlen);
3112ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3113ac5a488eSSridhar Samudrala 	return err;
3114ac5a488eSSridhar Samudrala }
3115c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_setsockopt);
3116ac5a488eSSridhar Samudrala 
3117ac5a488eSSridhar Samudrala int kernel_sendpage(struct socket *sock, struct page *page, int offset,
3118ac5a488eSSridhar Samudrala 		    size_t size, int flags)
3119ac5a488eSSridhar Samudrala {
3120f8451725SHerbert Xu 	sock_update_classid(sock->sk);
3121f8451725SHerbert Xu 
3122ac5a488eSSridhar Samudrala 	if (sock->ops->sendpage)
3123ac5a488eSSridhar Samudrala 		return sock->ops->sendpage(sock, page, offset, size, flags);
3124ac5a488eSSridhar Samudrala 
3125ac5a488eSSridhar Samudrala 	return sock_no_sendpage(sock, page, offset, size, flags);
3126ac5a488eSSridhar Samudrala }
3127c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendpage);
3128ac5a488eSSridhar Samudrala 
3129ac5a488eSSridhar Samudrala int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg)
3130ac5a488eSSridhar Samudrala {
3131ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3132ac5a488eSSridhar Samudrala 	int err;
3133ac5a488eSSridhar Samudrala 
3134ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3135ac5a488eSSridhar Samudrala 	err = sock->ops->ioctl(sock, cmd, arg);
3136ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3137ac5a488eSSridhar Samudrala 
3138ac5a488eSSridhar Samudrala 	return err;
3139ac5a488eSSridhar Samudrala }
3140c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sock_ioctl);
3141ac5a488eSSridhar Samudrala 
314291cf45f0STrond Myklebust int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
314391cf45f0STrond Myklebust {
314491cf45f0STrond Myklebust 	return sock->ops->shutdown(sock, how);
314591cf45f0STrond Myklebust }
314691cf45f0STrond Myklebust EXPORT_SYMBOL(kernel_sock_shutdown);
3147