xref: /openbmc/linux/net/socket.c (revision 68c6beb3)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * NET		An implementation of the SOCKET network access protocol.
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Version:	@(#)socket.c	1.1.93	18/02/95
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * Authors:	Orest Zborowski, <obz@Kodak.COM>
702c30a84SJesper Juhl  *		Ross Biro
81da177e4SLinus Torvalds  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
91da177e4SLinus Torvalds  *
101da177e4SLinus Torvalds  * Fixes:
111da177e4SLinus Torvalds  *		Anonymous	:	NOTSOCK/BADF cleanup. Error fix in
121da177e4SLinus Torvalds  *					shutdown()
131da177e4SLinus Torvalds  *		Alan Cox	:	verify_area() fixes
141da177e4SLinus Torvalds  *		Alan Cox	:	Removed DDI
151da177e4SLinus Torvalds  *		Jonathan Kamens	:	SOCK_DGRAM reconnect bug
161da177e4SLinus Torvalds  *		Alan Cox	:	Moved a load of checks to the very
171da177e4SLinus Torvalds  *					top level.
181da177e4SLinus Torvalds  *		Alan Cox	:	Move address structures to/from user
191da177e4SLinus Torvalds  *					mode above the protocol layers.
201da177e4SLinus Torvalds  *		Rob Janssen	:	Allow 0 length sends.
211da177e4SLinus Torvalds  *		Alan Cox	:	Asynchronous I/O support (cribbed from the
221da177e4SLinus Torvalds  *					tty drivers).
231da177e4SLinus Torvalds  *		Niibe Yutaka	:	Asynchronous I/O for writes (4.4BSD style)
241da177e4SLinus Torvalds  *		Jeff Uphoff	:	Made max number of sockets command-line
251da177e4SLinus Torvalds  *					configurable.
261da177e4SLinus Torvalds  *		Matti Aarnio	:	Made the number of sockets dynamic,
271da177e4SLinus Torvalds  *					to be allocated when needed, and mr.
281da177e4SLinus Torvalds  *					Uphoff's max is used as max to be
291da177e4SLinus Torvalds  *					allowed to allocate.
301da177e4SLinus Torvalds  *		Linus		:	Argh. removed all the socket allocation
311da177e4SLinus Torvalds  *					altogether: it's in the inode now.
321da177e4SLinus Torvalds  *		Alan Cox	:	Made sock_alloc()/sock_release() public
331da177e4SLinus Torvalds  *					for NetROM and future kernel nfsd type
341da177e4SLinus Torvalds  *					stuff.
351da177e4SLinus Torvalds  *		Alan Cox	:	sendmsg/recvmsg basics.
361da177e4SLinus Torvalds  *		Tom Dyas	:	Export net symbols.
371da177e4SLinus Torvalds  *		Marcin Dalecki	:	Fixed problems with CONFIG_NET="n".
381da177e4SLinus Torvalds  *		Alan Cox	:	Added thread locking to sys_* calls
391da177e4SLinus Torvalds  *					for sockets. May have errors at the
401da177e4SLinus Torvalds  *					moment.
411da177e4SLinus Torvalds  *		Kevin Buhr	:	Fixed the dumb errors in the above.
421da177e4SLinus Torvalds  *		Andi Kleen	:	Some small cleanups, optimizations,
431da177e4SLinus Torvalds  *					and fixed a copy_from_user() bug.
441da177e4SLinus Torvalds  *		Tigran Aivazian	:	sys_send(args) calls sys_sendto(args, NULL, 0)
451da177e4SLinus Torvalds  *		Tigran Aivazian	:	Made listen(2) backlog sanity checks
461da177e4SLinus Torvalds  *					protocol-independent
471da177e4SLinus Torvalds  *
481da177e4SLinus Torvalds  *
491da177e4SLinus Torvalds  *		This program is free software; you can redistribute it and/or
501da177e4SLinus Torvalds  *		modify it under the terms of the GNU General Public License
511da177e4SLinus Torvalds  *		as published by the Free Software Foundation; either version
521da177e4SLinus Torvalds  *		2 of the License, or (at your option) any later version.
531da177e4SLinus Torvalds  *
541da177e4SLinus Torvalds  *
551da177e4SLinus Torvalds  *	This module is effectively the top level interface to the BSD socket
561da177e4SLinus Torvalds  *	paradigm.
571da177e4SLinus Torvalds  *
581da177e4SLinus Torvalds  *	Based upon Swansea University Computer Society NET3.039
591da177e4SLinus Torvalds  */
601da177e4SLinus Torvalds 
611da177e4SLinus Torvalds #include <linux/mm.h>
621da177e4SLinus Torvalds #include <linux/socket.h>
631da177e4SLinus Torvalds #include <linux/file.h>
641da177e4SLinus Torvalds #include <linux/net.h>
651da177e4SLinus Torvalds #include <linux/interrupt.h>
66aaca0bdcSUlrich Drepper #include <linux/thread_info.h>
6755737fdaSStephen Hemminger #include <linux/rcupdate.h>
681da177e4SLinus Torvalds #include <linux/netdevice.h>
691da177e4SLinus Torvalds #include <linux/proc_fs.h>
701da177e4SLinus Torvalds #include <linux/seq_file.h>
714a3e2f71SArjan van de Ven #include <linux/mutex.h>
721da177e4SLinus Torvalds #include <linux/if_bridge.h>
7320380731SArnaldo Carvalho de Melo #include <linux/if_frad.h>
7420380731SArnaldo Carvalho de Melo #include <linux/if_vlan.h>
751da177e4SLinus Torvalds #include <linux/init.h>
761da177e4SLinus Torvalds #include <linux/poll.h>
771da177e4SLinus Torvalds #include <linux/cache.h>
781da177e4SLinus Torvalds #include <linux/module.h>
791da177e4SLinus Torvalds #include <linux/highmem.h>
801da177e4SLinus Torvalds #include <linux/mount.h>
811da177e4SLinus Torvalds #include <linux/security.h>
821da177e4SLinus Torvalds #include <linux/syscalls.h>
831da177e4SLinus Torvalds #include <linux/compat.h>
841da177e4SLinus Torvalds #include <linux/kmod.h>
853ec3b2fbSDavid Woodhouse #include <linux/audit.h>
86d86b5e0eSAdrian Bunk #include <linux/wireless.h>
871b8d7ae4SEric W. Biederman #include <linux/nsproxy.h>
881fd7317dSNick Black #include <linux/magic.h>
895a0e3ad6STejun Heo #include <linux/slab.h>
90600e1779SMasatake YAMATO #include <linux/xattr.h>
911da177e4SLinus Torvalds 
921da177e4SLinus Torvalds #include <asm/uaccess.h>
931da177e4SLinus Torvalds #include <asm/unistd.h>
941da177e4SLinus Torvalds 
951da177e4SLinus Torvalds #include <net/compat.h>
9687de87d5SDavid S. Miller #include <net/wext.h>
97f8451725SHerbert Xu #include <net/cls_cgroup.h>
981da177e4SLinus Torvalds 
991da177e4SLinus Torvalds #include <net/sock.h>
1001da177e4SLinus Torvalds #include <linux/netfilter.h>
1011da177e4SLinus Torvalds 
1026b96018bSArnd Bergmann #include <linux/if_tun.h>
1036b96018bSArnd Bergmann #include <linux/ipv6_route.h>
1046b96018bSArnd Bergmann #include <linux/route.h>
1056b96018bSArnd Bergmann #include <linux/sockios.h>
1066b96018bSArnd Bergmann #include <linux/atalk.h>
107076bb0c8SEliezer Tamir #include <net/busy_poll.h>
10806021292SEliezer Tamir 
109e0d1095aSCong Wang #ifdef CONFIG_NET_RX_BUSY_POLL
11064b0dc51SEliezer Tamir unsigned int sysctl_net_busy_read __read_mostly;
11164b0dc51SEliezer Tamir unsigned int sysctl_net_busy_poll __read_mostly;
11206021292SEliezer Tamir #endif
1136b96018bSArnd Bergmann 
1141da177e4SLinus Torvalds static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
115027445c3SBadari Pulavarty static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
116027445c3SBadari Pulavarty 			 unsigned long nr_segs, loff_t pos);
117027445c3SBadari Pulavarty static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
118027445c3SBadari Pulavarty 			  unsigned long nr_segs, loff_t pos);
1191da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma);
1201da177e4SLinus Torvalds 
1211da177e4SLinus Torvalds static int sock_close(struct inode *inode, struct file *file);
1221da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file,
1231da177e4SLinus Torvalds 			      struct poll_table_struct *wait);
12489bddce5SStephen Hemminger static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
12589bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
12689bbfc95SShaun Pereira static long compat_sock_ioctl(struct file *file,
12789bbfc95SShaun Pereira 			      unsigned int cmd, unsigned long arg);
12889bbfc95SShaun Pereira #endif
1291da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on);
1301da177e4SLinus Torvalds static ssize_t sock_sendpage(struct file *file, struct page *page,
1311da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more);
1329c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
1339c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
1349c55e01cSJens Axboe 				unsigned int flags);
1351da177e4SLinus Torvalds 
1361da177e4SLinus Torvalds /*
1371da177e4SLinus Torvalds  *	Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
1381da177e4SLinus Torvalds  *	in the operation structures but are done directly via the socketcall() multiplexor.
1391da177e4SLinus Torvalds  */
1401da177e4SLinus Torvalds 
141da7071d7SArjan van de Ven static const struct file_operations socket_file_ops = {
1421da177e4SLinus Torvalds 	.owner =	THIS_MODULE,
1431da177e4SLinus Torvalds 	.llseek =	no_llseek,
1441da177e4SLinus Torvalds 	.aio_read =	sock_aio_read,
1451da177e4SLinus Torvalds 	.aio_write =	sock_aio_write,
1461da177e4SLinus Torvalds 	.poll =		sock_poll,
1471da177e4SLinus Torvalds 	.unlocked_ioctl = sock_ioctl,
14889bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
14989bbfc95SShaun Pereira 	.compat_ioctl = compat_sock_ioctl,
15089bbfc95SShaun Pereira #endif
1511da177e4SLinus Torvalds 	.mmap =		sock_mmap,
1521da177e4SLinus Torvalds 	.open =		sock_no_open,	/* special open code to disallow open via /proc */
1531da177e4SLinus Torvalds 	.release =	sock_close,
1541da177e4SLinus Torvalds 	.fasync =	sock_fasync,
1555274f052SJens Axboe 	.sendpage =	sock_sendpage,
1565274f052SJens Axboe 	.splice_write = generic_splice_sendpage,
1579c55e01cSJens Axboe 	.splice_read =	sock_splice_read,
1581da177e4SLinus Torvalds };
1591da177e4SLinus Torvalds 
1601da177e4SLinus Torvalds /*
1611da177e4SLinus Torvalds  *	The protocol list. Each protocol is registered in here.
1621da177e4SLinus Torvalds  */
1631da177e4SLinus Torvalds 
1641da177e4SLinus Torvalds static DEFINE_SPINLOCK(net_family_lock);
165190683a9SEric Dumazet static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly;
1661da177e4SLinus Torvalds 
1671da177e4SLinus Torvalds /*
1681da177e4SLinus Torvalds  *	Statistics counters of the socket lists
1691da177e4SLinus Torvalds  */
1701da177e4SLinus Torvalds 
171c6d409cfSEric Dumazet static DEFINE_PER_CPU(int, sockets_in_use);
1721da177e4SLinus Torvalds 
1731da177e4SLinus Torvalds /*
17489bddce5SStephen Hemminger  * Support routines.
17589bddce5SStephen Hemminger  * Move socket addresses back and forth across the kernel/user
1761da177e4SLinus Torvalds  * divide and look after the messy bits.
1771da177e4SLinus Torvalds  */
1781da177e4SLinus Torvalds 
1791da177e4SLinus Torvalds /**
1801da177e4SLinus Torvalds  *	move_addr_to_kernel	-	copy a socket address into kernel space
1811da177e4SLinus Torvalds  *	@uaddr: Address in user space
1821da177e4SLinus Torvalds  *	@kaddr: Address in kernel space
1831da177e4SLinus Torvalds  *	@ulen: Length in user space
1841da177e4SLinus Torvalds  *
1851da177e4SLinus Torvalds  *	The address is copied into kernel space. If the provided address is
1861da177e4SLinus Torvalds  *	too long an error code of -EINVAL is returned. If the copy gives
1871da177e4SLinus Torvalds  *	invalid addresses -EFAULT is returned. On a success 0 is returned.
1881da177e4SLinus Torvalds  */
1891da177e4SLinus Torvalds 
19043db362dSMaciej Żenczykowski int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr)
1911da177e4SLinus Torvalds {
192230b1839SYOSHIFUJI Hideaki 	if (ulen < 0 || ulen > sizeof(struct sockaddr_storage))
1931da177e4SLinus Torvalds 		return -EINVAL;
1941da177e4SLinus Torvalds 	if (ulen == 0)
1951da177e4SLinus Torvalds 		return 0;
1961da177e4SLinus Torvalds 	if (copy_from_user(kaddr, uaddr, ulen))
1971da177e4SLinus Torvalds 		return -EFAULT;
1983ec3b2fbSDavid Woodhouse 	return audit_sockaddr(ulen, kaddr);
1991da177e4SLinus Torvalds }
2001da177e4SLinus Torvalds 
2011da177e4SLinus Torvalds /**
2021da177e4SLinus Torvalds  *	move_addr_to_user	-	copy an address to user space
2031da177e4SLinus Torvalds  *	@kaddr: kernel space address
2041da177e4SLinus Torvalds  *	@klen: length of address in kernel
2051da177e4SLinus Torvalds  *	@uaddr: user space address
2061da177e4SLinus Torvalds  *	@ulen: pointer to user length field
2071da177e4SLinus Torvalds  *
2081da177e4SLinus Torvalds  *	The value pointed to by ulen on entry is the buffer length available.
2091da177e4SLinus Torvalds  *	This is overwritten with the buffer space used. -EINVAL is returned
2101da177e4SLinus Torvalds  *	if an overlong buffer is specified or a negative buffer size. -EFAULT
2111da177e4SLinus Torvalds  *	is returned if either the buffer or the length field are not
2121da177e4SLinus Torvalds  *	accessible.
2131da177e4SLinus Torvalds  *	After copying the data up to the limit the user specifies, the true
2141da177e4SLinus Torvalds  *	length of the data is written over the length limit the user
2151da177e4SLinus Torvalds  *	specified. Zero is returned for a success.
2161da177e4SLinus Torvalds  */
2171da177e4SLinus Torvalds 
21843db362dSMaciej Żenczykowski static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen,
21911165f14Sstephen hemminger 			     void __user *uaddr, int __user *ulen)
2201da177e4SLinus Torvalds {
2211da177e4SLinus Torvalds 	int err;
2221da177e4SLinus Torvalds 	int len;
2231da177e4SLinus Torvalds 
224*68c6beb3SHannes Frederic Sowa 	BUG_ON(klen > sizeof(struct sockaddr_storage));
22589bddce5SStephen Hemminger 	err = get_user(len, ulen);
22689bddce5SStephen Hemminger 	if (err)
2271da177e4SLinus Torvalds 		return err;
2281da177e4SLinus Torvalds 	if (len > klen)
2291da177e4SLinus Torvalds 		len = klen;
230*68c6beb3SHannes Frederic Sowa 	if (len < 0)
2311da177e4SLinus Torvalds 		return -EINVAL;
23289bddce5SStephen Hemminger 	if (len) {
233d6fe3945SSteve Grubb 		if (audit_sockaddr(klen, kaddr))
234d6fe3945SSteve Grubb 			return -ENOMEM;
2351da177e4SLinus Torvalds 		if (copy_to_user(uaddr, kaddr, len))
2361da177e4SLinus Torvalds 			return -EFAULT;
2371da177e4SLinus Torvalds 	}
2381da177e4SLinus Torvalds 	/*
2391da177e4SLinus Torvalds 	 *      "fromlen shall refer to the value before truncation.."
2401da177e4SLinus Torvalds 	 *                      1003.1g
2411da177e4SLinus Torvalds 	 */
2421da177e4SLinus Torvalds 	return __put_user(klen, ulen);
2431da177e4SLinus Torvalds }
2441da177e4SLinus Torvalds 
245e18b890bSChristoph Lameter static struct kmem_cache *sock_inode_cachep __read_mostly;
2461da177e4SLinus Torvalds 
2471da177e4SLinus Torvalds static struct inode *sock_alloc_inode(struct super_block *sb)
2481da177e4SLinus Torvalds {
2491da177e4SLinus Torvalds 	struct socket_alloc *ei;
250eaefd110SEric Dumazet 	struct socket_wq *wq;
25189bddce5SStephen Hemminger 
252e94b1766SChristoph Lameter 	ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL);
2531da177e4SLinus Torvalds 	if (!ei)
2541da177e4SLinus Torvalds 		return NULL;
255eaefd110SEric Dumazet 	wq = kmalloc(sizeof(*wq), GFP_KERNEL);
256eaefd110SEric Dumazet 	if (!wq) {
25743815482SEric Dumazet 		kmem_cache_free(sock_inode_cachep, ei);
25843815482SEric Dumazet 		return NULL;
25943815482SEric Dumazet 	}
260eaefd110SEric Dumazet 	init_waitqueue_head(&wq->wait);
261eaefd110SEric Dumazet 	wq->fasync_list = NULL;
262eaefd110SEric Dumazet 	RCU_INIT_POINTER(ei->socket.wq, wq);
2631da177e4SLinus Torvalds 
2641da177e4SLinus Torvalds 	ei->socket.state = SS_UNCONNECTED;
2651da177e4SLinus Torvalds 	ei->socket.flags = 0;
2661da177e4SLinus Torvalds 	ei->socket.ops = NULL;
2671da177e4SLinus Torvalds 	ei->socket.sk = NULL;
2681da177e4SLinus Torvalds 	ei->socket.file = NULL;
2691da177e4SLinus Torvalds 
2701da177e4SLinus Torvalds 	return &ei->vfs_inode;
2711da177e4SLinus Torvalds }
2721da177e4SLinus Torvalds 
2731da177e4SLinus Torvalds static void sock_destroy_inode(struct inode *inode)
2741da177e4SLinus Torvalds {
27543815482SEric Dumazet 	struct socket_alloc *ei;
276eaefd110SEric Dumazet 	struct socket_wq *wq;
27743815482SEric Dumazet 
27843815482SEric Dumazet 	ei = container_of(inode, struct socket_alloc, vfs_inode);
279eaefd110SEric Dumazet 	wq = rcu_dereference_protected(ei->socket.wq, 1);
28061845220SLai Jiangshan 	kfree_rcu(wq, rcu);
28143815482SEric Dumazet 	kmem_cache_free(sock_inode_cachep, ei);
2821da177e4SLinus Torvalds }
2831da177e4SLinus Torvalds 
28451cc5068SAlexey Dobriyan static void init_once(void *foo)
2851da177e4SLinus Torvalds {
2861da177e4SLinus Torvalds 	struct socket_alloc *ei = (struct socket_alloc *)foo;
2871da177e4SLinus Torvalds 
2881da177e4SLinus Torvalds 	inode_init_once(&ei->vfs_inode);
2891da177e4SLinus Torvalds }
2901da177e4SLinus Torvalds 
2911da177e4SLinus Torvalds static int init_inodecache(void)
2921da177e4SLinus Torvalds {
2931da177e4SLinus Torvalds 	sock_inode_cachep = kmem_cache_create("sock_inode_cache",
2941da177e4SLinus Torvalds 					      sizeof(struct socket_alloc),
29589bddce5SStephen Hemminger 					      0,
29689bddce5SStephen Hemminger 					      (SLAB_HWCACHE_ALIGN |
29789bddce5SStephen Hemminger 					       SLAB_RECLAIM_ACCOUNT |
298fffb60f9SPaul Jackson 					       SLAB_MEM_SPREAD),
29920c2df83SPaul Mundt 					      init_once);
3001da177e4SLinus Torvalds 	if (sock_inode_cachep == NULL)
3011da177e4SLinus Torvalds 		return -ENOMEM;
3021da177e4SLinus Torvalds 	return 0;
3031da177e4SLinus Torvalds }
3041da177e4SLinus Torvalds 
305b87221deSAlexey Dobriyan static const struct super_operations sockfs_ops = {
3061da177e4SLinus Torvalds 	.alloc_inode	= sock_alloc_inode,
3071da177e4SLinus Torvalds 	.destroy_inode	= sock_destroy_inode,
3081da177e4SLinus Torvalds 	.statfs		= simple_statfs,
3091da177e4SLinus Torvalds };
3101da177e4SLinus Torvalds 
311c23fbb6bSEric Dumazet /*
312c23fbb6bSEric Dumazet  * sockfs_dname() is called from d_path().
313c23fbb6bSEric Dumazet  */
314c23fbb6bSEric Dumazet static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen)
315c23fbb6bSEric Dumazet {
316c23fbb6bSEric Dumazet 	return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]",
317c23fbb6bSEric Dumazet 				dentry->d_inode->i_ino);
318c23fbb6bSEric Dumazet }
319c23fbb6bSEric Dumazet 
3203ba13d17SAl Viro static const struct dentry_operations sockfs_dentry_operations = {
321c23fbb6bSEric Dumazet 	.d_dname  = sockfs_dname,
3221da177e4SLinus Torvalds };
3231da177e4SLinus Torvalds 
324c74a1cbbSAl Viro static struct dentry *sockfs_mount(struct file_system_type *fs_type,
325c74a1cbbSAl Viro 			 int flags, const char *dev_name, void *data)
326c74a1cbbSAl Viro {
327c74a1cbbSAl Viro 	return mount_pseudo(fs_type, "socket:", &sockfs_ops,
328c74a1cbbSAl Viro 		&sockfs_dentry_operations, SOCKFS_MAGIC);
329c74a1cbbSAl Viro }
330c74a1cbbSAl Viro 
331c74a1cbbSAl Viro static struct vfsmount *sock_mnt __read_mostly;
332c74a1cbbSAl Viro 
333c74a1cbbSAl Viro static struct file_system_type sock_fs_type = {
334c74a1cbbSAl Viro 	.name =		"sockfs",
335c74a1cbbSAl Viro 	.mount =	sockfs_mount,
336c74a1cbbSAl Viro 	.kill_sb =	kill_anon_super,
337c74a1cbbSAl Viro };
338c74a1cbbSAl Viro 
3391da177e4SLinus Torvalds /*
3401da177e4SLinus Torvalds  *	Obtains the first available file descriptor and sets it up for use.
3411da177e4SLinus Torvalds  *
34239d8c1b6SDavid S. Miller  *	These functions create file structures and maps them to fd space
34339d8c1b6SDavid S. Miller  *	of the current process. On success it returns file descriptor
3441da177e4SLinus Torvalds  *	and file struct implicitly stored in sock->file.
3451da177e4SLinus Torvalds  *	Note that another thread may close file descriptor before we return
3461da177e4SLinus Torvalds  *	from this function. We use the fact that now we do not refer
3471da177e4SLinus Torvalds  *	to socket after mapping. If one day we will need it, this
3481da177e4SLinus Torvalds  *	function will increment ref. count on file by 1.
3491da177e4SLinus Torvalds  *
3501da177e4SLinus Torvalds  *	In any case returned fd MAY BE not valid!
3511da177e4SLinus Torvalds  *	This race condition is unavoidable
3521da177e4SLinus Torvalds  *	with shared fd spaces, we cannot solve it inside kernel,
3531da177e4SLinus Torvalds  *	but we take care of internal coherence yet.
3541da177e4SLinus Torvalds  */
3551da177e4SLinus Torvalds 
356aab174f0SLinus Torvalds struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)
3571da177e4SLinus Torvalds {
3587cbe66b6SAl Viro 	struct qstr name = { .name = "" };
3592c48b9c4SAl Viro 	struct path path;
3607cbe66b6SAl Viro 	struct file *file;
3611da177e4SLinus Torvalds 
362600e1779SMasatake YAMATO 	if (dname) {
363600e1779SMasatake YAMATO 		name.name = dname;
364600e1779SMasatake YAMATO 		name.len = strlen(name.name);
365600e1779SMasatake YAMATO 	} else if (sock->sk) {
366600e1779SMasatake YAMATO 		name.name = sock->sk->sk_prot_creator->name;
367600e1779SMasatake YAMATO 		name.len = strlen(name.name);
368600e1779SMasatake YAMATO 	}
3694b936885SNick Piggin 	path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name);
37028407630SAl Viro 	if (unlikely(!path.dentry))
37128407630SAl Viro 		return ERR_PTR(-ENOMEM);
3722c48b9c4SAl Viro 	path.mnt = mntget(sock_mnt);
37339d8c1b6SDavid S. Miller 
3742c48b9c4SAl Viro 	d_instantiate(path.dentry, SOCK_INODE(sock));
375cc3808f8SAl Viro 	SOCK_INODE(sock)->i_fop = &socket_file_ops;
376cc3808f8SAl Viro 
3772c48b9c4SAl Viro 	file = alloc_file(&path, FMODE_READ | FMODE_WRITE,
378cc3808f8SAl Viro 		  &socket_file_ops);
37939b65252SAnatol Pomozov 	if (unlikely(IS_ERR(file))) {
380cc3808f8SAl Viro 		/* drop dentry, keep inode */
3817de9c6eeSAl Viro 		ihold(path.dentry->d_inode);
3822c48b9c4SAl Viro 		path_put(&path);
38339b65252SAnatol Pomozov 		return file;
384cc3808f8SAl Viro 	}
3851da177e4SLinus Torvalds 
3861da177e4SLinus Torvalds 	sock->file = file;
38777d27200SUlrich Drepper 	file->f_flags = O_RDWR | (flags & O_NONBLOCK);
38807dc3f07SBenjamin LaHaise 	file->private_data = sock;
38928407630SAl Viro 	return file;
3901da177e4SLinus Torvalds }
39156b31d1cSAl Viro EXPORT_SYMBOL(sock_alloc_file);
3921da177e4SLinus Torvalds 
39356b31d1cSAl Viro static int sock_map_fd(struct socket *sock, int flags)
39439d8c1b6SDavid S. Miller {
39539d8c1b6SDavid S. Miller 	struct file *newfile;
39628407630SAl Viro 	int fd = get_unused_fd_flags(flags);
39728407630SAl Viro 	if (unlikely(fd < 0))
3981da177e4SLinus Torvalds 		return fd;
3991da177e4SLinus Torvalds 
400aab174f0SLinus Torvalds 	newfile = sock_alloc_file(sock, flags, NULL);
40128407630SAl Viro 	if (likely(!IS_ERR(newfile))) {
4021da177e4SLinus Torvalds 		fd_install(fd, newfile);
4031da177e4SLinus Torvalds 		return fd;
4041da177e4SLinus Torvalds 	}
40528407630SAl Viro 
40628407630SAl Viro 	put_unused_fd(fd);
40728407630SAl Viro 	return PTR_ERR(newfile);
4081da177e4SLinus Torvalds }
4091da177e4SLinus Torvalds 
410406a3c63SJohn Fastabend struct socket *sock_from_file(struct file *file, int *err)
4116cb153caSBenjamin LaHaise {
4126cb153caSBenjamin LaHaise 	if (file->f_op == &socket_file_ops)
4136cb153caSBenjamin LaHaise 		return file->private_data;	/* set in sock_map_fd */
4146cb153caSBenjamin LaHaise 
4156cb153caSBenjamin LaHaise 	*err = -ENOTSOCK;
4166cb153caSBenjamin LaHaise 	return NULL;
4176cb153caSBenjamin LaHaise }
418406a3c63SJohn Fastabend EXPORT_SYMBOL(sock_from_file);
4196cb153caSBenjamin LaHaise 
4201da177e4SLinus Torvalds /**
4211da177e4SLinus Torvalds  *	sockfd_lookup - Go from a file number to its socket slot
4221da177e4SLinus Torvalds  *	@fd: file handle
4231da177e4SLinus Torvalds  *	@err: pointer to an error code return
4241da177e4SLinus Torvalds  *
4251da177e4SLinus Torvalds  *	The file handle passed in is locked and the socket it is bound
4261da177e4SLinus Torvalds  *	too is returned. If an error occurs the err pointer is overwritten
4271da177e4SLinus Torvalds  *	with a negative errno code and NULL is returned. The function checks
4281da177e4SLinus Torvalds  *	for both invalid handles and passing a handle which is not a socket.
4291da177e4SLinus Torvalds  *
4301da177e4SLinus Torvalds  *	On a success the socket object pointer is returned.
4311da177e4SLinus Torvalds  */
4321da177e4SLinus Torvalds 
4331da177e4SLinus Torvalds struct socket *sockfd_lookup(int fd, int *err)
4341da177e4SLinus Torvalds {
4351da177e4SLinus Torvalds 	struct file *file;
4361da177e4SLinus Torvalds 	struct socket *sock;
4371da177e4SLinus Torvalds 
43889bddce5SStephen Hemminger 	file = fget(fd);
43989bddce5SStephen Hemminger 	if (!file) {
4401da177e4SLinus Torvalds 		*err = -EBADF;
4411da177e4SLinus Torvalds 		return NULL;
4421da177e4SLinus Torvalds 	}
44389bddce5SStephen Hemminger 
4446cb153caSBenjamin LaHaise 	sock = sock_from_file(file, err);
4456cb153caSBenjamin LaHaise 	if (!sock)
4461da177e4SLinus Torvalds 		fput(file);
4476cb153caSBenjamin LaHaise 	return sock;
4481da177e4SLinus Torvalds }
449c6d409cfSEric Dumazet EXPORT_SYMBOL(sockfd_lookup);
4501da177e4SLinus Torvalds 
4516cb153caSBenjamin LaHaise static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
4526cb153caSBenjamin LaHaise {
4536cb153caSBenjamin LaHaise 	struct file *file;
4546cb153caSBenjamin LaHaise 	struct socket *sock;
4556cb153caSBenjamin LaHaise 
4563672558cSHua Zhong 	*err = -EBADF;
4576cb153caSBenjamin LaHaise 	file = fget_light(fd, fput_needed);
4586cb153caSBenjamin LaHaise 	if (file) {
4596cb153caSBenjamin LaHaise 		sock = sock_from_file(file, err);
4606cb153caSBenjamin LaHaise 		if (sock)
4611da177e4SLinus Torvalds 			return sock;
4626cb153caSBenjamin LaHaise 		fput_light(file, *fput_needed);
4636cb153caSBenjamin LaHaise 	}
4646cb153caSBenjamin LaHaise 	return NULL;
4651da177e4SLinus Torvalds }
4661da177e4SLinus Torvalds 
467600e1779SMasatake YAMATO #define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname"
468600e1779SMasatake YAMATO #define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX)
469600e1779SMasatake YAMATO #define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1)
470600e1779SMasatake YAMATO static ssize_t sockfs_getxattr(struct dentry *dentry,
471600e1779SMasatake YAMATO 			       const char *name, void *value, size_t size)
472600e1779SMasatake YAMATO {
473600e1779SMasatake YAMATO 	const char *proto_name;
474600e1779SMasatake YAMATO 	size_t proto_size;
475600e1779SMasatake YAMATO 	int error;
476600e1779SMasatake YAMATO 
477600e1779SMasatake YAMATO 	error = -ENODATA;
478600e1779SMasatake YAMATO 	if (!strncmp(name, XATTR_NAME_SOCKPROTONAME, XATTR_NAME_SOCKPROTONAME_LEN)) {
479600e1779SMasatake YAMATO 		proto_name = dentry->d_name.name;
480600e1779SMasatake YAMATO 		proto_size = strlen(proto_name);
481600e1779SMasatake YAMATO 
482600e1779SMasatake YAMATO 		if (value) {
483600e1779SMasatake YAMATO 			error = -ERANGE;
484600e1779SMasatake YAMATO 			if (proto_size + 1 > size)
485600e1779SMasatake YAMATO 				goto out;
486600e1779SMasatake YAMATO 
487600e1779SMasatake YAMATO 			strncpy(value, proto_name, proto_size + 1);
488600e1779SMasatake YAMATO 		}
489600e1779SMasatake YAMATO 		error = proto_size + 1;
490600e1779SMasatake YAMATO 	}
491600e1779SMasatake YAMATO 
492600e1779SMasatake YAMATO out:
493600e1779SMasatake YAMATO 	return error;
494600e1779SMasatake YAMATO }
495600e1779SMasatake YAMATO 
496600e1779SMasatake YAMATO static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer,
497600e1779SMasatake YAMATO 				size_t size)
498600e1779SMasatake YAMATO {
499600e1779SMasatake YAMATO 	ssize_t len;
500600e1779SMasatake YAMATO 	ssize_t used = 0;
501600e1779SMasatake YAMATO 
502600e1779SMasatake YAMATO 	len = security_inode_listsecurity(dentry->d_inode, buffer, size);
503600e1779SMasatake YAMATO 	if (len < 0)
504600e1779SMasatake YAMATO 		return len;
505600e1779SMasatake YAMATO 	used += len;
506600e1779SMasatake YAMATO 	if (buffer) {
507600e1779SMasatake YAMATO 		if (size < used)
508600e1779SMasatake YAMATO 			return -ERANGE;
509600e1779SMasatake YAMATO 		buffer += len;
510600e1779SMasatake YAMATO 	}
511600e1779SMasatake YAMATO 
512600e1779SMasatake YAMATO 	len = (XATTR_NAME_SOCKPROTONAME_LEN + 1);
513600e1779SMasatake YAMATO 	used += len;
514600e1779SMasatake YAMATO 	if (buffer) {
515600e1779SMasatake YAMATO 		if (size < used)
516600e1779SMasatake YAMATO 			return -ERANGE;
517600e1779SMasatake YAMATO 		memcpy(buffer, XATTR_NAME_SOCKPROTONAME, len);
518600e1779SMasatake YAMATO 		buffer += len;
519600e1779SMasatake YAMATO 	}
520600e1779SMasatake YAMATO 
521600e1779SMasatake YAMATO 	return used;
522600e1779SMasatake YAMATO }
523600e1779SMasatake YAMATO 
524600e1779SMasatake YAMATO static const struct inode_operations sockfs_inode_ops = {
525600e1779SMasatake YAMATO 	.getxattr = sockfs_getxattr,
526600e1779SMasatake YAMATO 	.listxattr = sockfs_listxattr,
527600e1779SMasatake YAMATO };
528600e1779SMasatake YAMATO 
5291da177e4SLinus Torvalds /**
5301da177e4SLinus Torvalds  *	sock_alloc	-	allocate a socket
5311da177e4SLinus Torvalds  *
5321da177e4SLinus Torvalds  *	Allocate a new inode and socket object. The two are bound together
5331da177e4SLinus Torvalds  *	and initialised. The socket is then returned. If we are out of inodes
5341da177e4SLinus Torvalds  *	NULL is returned.
5351da177e4SLinus Torvalds  */
5361da177e4SLinus Torvalds 
5371da177e4SLinus Torvalds static struct socket *sock_alloc(void)
5381da177e4SLinus Torvalds {
5391da177e4SLinus Torvalds 	struct inode *inode;
5401da177e4SLinus Torvalds 	struct socket *sock;
5411da177e4SLinus Torvalds 
542a209dfc7SEric Dumazet 	inode = new_inode_pseudo(sock_mnt->mnt_sb);
5431da177e4SLinus Torvalds 	if (!inode)
5441da177e4SLinus Torvalds 		return NULL;
5451da177e4SLinus Torvalds 
5461da177e4SLinus Torvalds 	sock = SOCKET_I(inode);
5471da177e4SLinus Torvalds 
54829a020d3SEric Dumazet 	kmemcheck_annotate_bitfield(sock, type);
54985fe4025SChristoph Hellwig 	inode->i_ino = get_next_ino();
5501da177e4SLinus Torvalds 	inode->i_mode = S_IFSOCK | S_IRWXUGO;
5518192b0c4SDavid Howells 	inode->i_uid = current_fsuid();
5528192b0c4SDavid Howells 	inode->i_gid = current_fsgid();
553600e1779SMasatake YAMATO 	inode->i_op = &sockfs_inode_ops;
5541da177e4SLinus Torvalds 
55519e8d69cSAlex Shi 	this_cpu_add(sockets_in_use, 1);
5561da177e4SLinus Torvalds 	return sock;
5571da177e4SLinus Torvalds }
5581da177e4SLinus Torvalds 
5591da177e4SLinus Torvalds /*
5601da177e4SLinus Torvalds  *	In theory you can't get an open on this inode, but /proc provides
5611da177e4SLinus Torvalds  *	a back door. Remember to keep it shut otherwise you'll let the
5621da177e4SLinus Torvalds  *	creepy crawlies in.
5631da177e4SLinus Torvalds  */
5641da177e4SLinus Torvalds 
5651da177e4SLinus Torvalds static int sock_no_open(struct inode *irrelevant, struct file *dontcare)
5661da177e4SLinus Torvalds {
5671da177e4SLinus Torvalds 	return -ENXIO;
5681da177e4SLinus Torvalds }
5691da177e4SLinus Torvalds 
5704b6f5d20SArjan van de Ven const struct file_operations bad_sock_fops = {
5711da177e4SLinus Torvalds 	.owner = THIS_MODULE,
5721da177e4SLinus Torvalds 	.open = sock_no_open,
5736038f373SArnd Bergmann 	.llseek = noop_llseek,
5741da177e4SLinus Torvalds };
5751da177e4SLinus Torvalds 
5761da177e4SLinus Torvalds /**
5771da177e4SLinus Torvalds  *	sock_release	-	close a socket
5781da177e4SLinus Torvalds  *	@sock: socket to close
5791da177e4SLinus Torvalds  *
5801da177e4SLinus Torvalds  *	The socket is released from the protocol stack if it has a release
5811da177e4SLinus Torvalds  *	callback, and the inode is then released if the socket is bound to
5821da177e4SLinus Torvalds  *	an inode not a file.
5831da177e4SLinus Torvalds  */
5841da177e4SLinus Torvalds 
5851da177e4SLinus Torvalds void sock_release(struct socket *sock)
5861da177e4SLinus Torvalds {
5871da177e4SLinus Torvalds 	if (sock->ops) {
5881da177e4SLinus Torvalds 		struct module *owner = sock->ops->owner;
5891da177e4SLinus Torvalds 
5901da177e4SLinus Torvalds 		sock->ops->release(sock);
5911da177e4SLinus Torvalds 		sock->ops = NULL;
5921da177e4SLinus Torvalds 		module_put(owner);
5931da177e4SLinus Torvalds 	}
5941da177e4SLinus Torvalds 
595eaefd110SEric Dumazet 	if (rcu_dereference_protected(sock->wq, 1)->fasync_list)
5961da177e4SLinus Torvalds 		printk(KERN_ERR "sock_release: fasync list not empty!\n");
5971da177e4SLinus Torvalds 
598b09e786bSMikulas Patocka 	if (test_bit(SOCK_EXTERNALLY_ALLOCATED, &sock->flags))
599b09e786bSMikulas Patocka 		return;
600b09e786bSMikulas Patocka 
60119e8d69cSAlex Shi 	this_cpu_sub(sockets_in_use, 1);
6021da177e4SLinus Torvalds 	if (!sock->file) {
6031da177e4SLinus Torvalds 		iput(SOCK_INODE(sock));
6041da177e4SLinus Torvalds 		return;
6051da177e4SLinus Torvalds 	}
6061da177e4SLinus Torvalds 	sock->file = NULL;
6071da177e4SLinus Torvalds }
608c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_release);
6091da177e4SLinus Torvalds 
610bf84a010SDaniel Borkmann void sock_tx_timestamp(struct sock *sk, __u8 *tx_flags)
61120d49473SPatrick Ohly {
6122244d07bSOliver Hartkopp 	*tx_flags = 0;
61320d49473SPatrick Ohly 	if (sock_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE))
6142244d07bSOliver Hartkopp 		*tx_flags |= SKBTX_HW_TSTAMP;
61520d49473SPatrick Ohly 	if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE))
6162244d07bSOliver Hartkopp 		*tx_flags |= SKBTX_SW_TSTAMP;
6176e3e939fSJohannes Berg 	if (sock_flag(sk, SOCK_WIFI_STATUS))
6186e3e939fSJohannes Berg 		*tx_flags |= SKBTX_WIFI_STATUS;
61920d49473SPatrick Ohly }
62020d49473SPatrick Ohly EXPORT_SYMBOL(sock_tx_timestamp);
62120d49473SPatrick Ohly 
622228e548eSAnton Blanchard static inline int __sock_sendmsg_nosec(struct kiocb *iocb, struct socket *sock,
6231da177e4SLinus Torvalds 				       struct msghdr *msg, size_t size)
6241da177e4SLinus Torvalds {
6251da177e4SLinus Torvalds 	struct sock_iocb *si = kiocb_to_siocb(iocb);
6261da177e4SLinus Torvalds 
6271da177e4SLinus Torvalds 	si->sock = sock;
6281da177e4SLinus Torvalds 	si->scm = NULL;
6291da177e4SLinus Torvalds 	si->msg = msg;
6301da177e4SLinus Torvalds 	si->size = size;
6311da177e4SLinus Torvalds 
6321da177e4SLinus Torvalds 	return sock->ops->sendmsg(iocb, sock, msg, size);
6331da177e4SLinus Torvalds }
6341da177e4SLinus Torvalds 
635228e548eSAnton Blanchard static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock,
636228e548eSAnton Blanchard 				 struct msghdr *msg, size_t size)
637228e548eSAnton Blanchard {
638228e548eSAnton Blanchard 	int err = security_socket_sendmsg(sock, msg, size);
639228e548eSAnton Blanchard 
640228e548eSAnton Blanchard 	return err ?: __sock_sendmsg_nosec(iocb, sock, msg, size);
641228e548eSAnton Blanchard }
642228e548eSAnton Blanchard 
6431da177e4SLinus Torvalds int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
6441da177e4SLinus Torvalds {
6451da177e4SLinus Torvalds 	struct kiocb iocb;
6461da177e4SLinus Torvalds 	struct sock_iocb siocb;
6471da177e4SLinus Torvalds 	int ret;
6481da177e4SLinus Torvalds 
6491da177e4SLinus Torvalds 	init_sync_kiocb(&iocb, NULL);
6501da177e4SLinus Torvalds 	iocb.private = &siocb;
6511da177e4SLinus Torvalds 	ret = __sock_sendmsg(&iocb, sock, msg, size);
6521da177e4SLinus Torvalds 	if (-EIOCBQUEUED == ret)
6531da177e4SLinus Torvalds 		ret = wait_on_sync_kiocb(&iocb);
6541da177e4SLinus Torvalds 	return ret;
6551da177e4SLinus Torvalds }
656c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_sendmsg);
6571da177e4SLinus Torvalds 
658894dc24cSEric Dumazet static int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg, size_t size)
659228e548eSAnton Blanchard {
660228e548eSAnton Blanchard 	struct kiocb iocb;
661228e548eSAnton Blanchard 	struct sock_iocb siocb;
662228e548eSAnton Blanchard 	int ret;
663228e548eSAnton Blanchard 
664228e548eSAnton Blanchard 	init_sync_kiocb(&iocb, NULL);
665228e548eSAnton Blanchard 	iocb.private = &siocb;
666228e548eSAnton Blanchard 	ret = __sock_sendmsg_nosec(&iocb, sock, msg, size);
667228e548eSAnton Blanchard 	if (-EIOCBQUEUED == ret)
668228e548eSAnton Blanchard 		ret = wait_on_sync_kiocb(&iocb);
669228e548eSAnton Blanchard 	return ret;
670228e548eSAnton Blanchard }
671228e548eSAnton Blanchard 
6721da177e4SLinus Torvalds int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
6731da177e4SLinus Torvalds 		   struct kvec *vec, size_t num, size_t size)
6741da177e4SLinus Torvalds {
6751da177e4SLinus Torvalds 	mm_segment_t oldfs = get_fs();
6761da177e4SLinus Torvalds 	int result;
6771da177e4SLinus Torvalds 
6781da177e4SLinus Torvalds 	set_fs(KERNEL_DS);
6791da177e4SLinus Torvalds 	/*
6801da177e4SLinus Torvalds 	 * the following is safe, since for compiler definitions of kvec and
6811da177e4SLinus Torvalds 	 * iovec are identical, yielding the same in-core layout and alignment
6821da177e4SLinus Torvalds 	 */
68389bddce5SStephen Hemminger 	msg->msg_iov = (struct iovec *)vec;
6841da177e4SLinus Torvalds 	msg->msg_iovlen = num;
6851da177e4SLinus Torvalds 	result = sock_sendmsg(sock, msg, size);
6861da177e4SLinus Torvalds 	set_fs(oldfs);
6871da177e4SLinus Torvalds 	return result;
6881da177e4SLinus Torvalds }
689c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendmsg);
6901da177e4SLinus Torvalds 
69192f37fd2SEric Dumazet /*
69292f37fd2SEric Dumazet  * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
69392f37fd2SEric Dumazet  */
69492f37fd2SEric Dumazet void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
69592f37fd2SEric Dumazet 	struct sk_buff *skb)
69692f37fd2SEric Dumazet {
69720d49473SPatrick Ohly 	int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
69820d49473SPatrick Ohly 	struct timespec ts[3];
69920d49473SPatrick Ohly 	int empty = 1;
70020d49473SPatrick Ohly 	struct skb_shared_hwtstamps *shhwtstamps =
70120d49473SPatrick Ohly 		skb_hwtstamps(skb);
70292f37fd2SEric Dumazet 
70320d49473SPatrick Ohly 	/* Race occurred between timestamp enabling and packet
70420d49473SPatrick Ohly 	   receiving.  Fill in the current time for now. */
70520d49473SPatrick Ohly 	if (need_software_tstamp && skb->tstamp.tv64 == 0)
70620d49473SPatrick Ohly 		__net_timestamp(skb);
70720d49473SPatrick Ohly 
70820d49473SPatrick Ohly 	if (need_software_tstamp) {
70992f37fd2SEric Dumazet 		if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
71092f37fd2SEric Dumazet 			struct timeval tv;
71120d49473SPatrick Ohly 			skb_get_timestamp(skb, &tv);
71220d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP,
71320d49473SPatrick Ohly 				 sizeof(tv), &tv);
71492f37fd2SEric Dumazet 		} else {
715842509b8SHagen Paul Pfeifer 			skb_get_timestampns(skb, &ts[0]);
71620d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS,
717842509b8SHagen Paul Pfeifer 				 sizeof(ts[0]), &ts[0]);
71892f37fd2SEric Dumazet 		}
71992f37fd2SEric Dumazet 	}
72092f37fd2SEric Dumazet 
72120d49473SPatrick Ohly 
72220d49473SPatrick Ohly 	memset(ts, 0, sizeof(ts));
7236e94d1efSDaniel Borkmann 	if (sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE) &&
7246e94d1efSDaniel Borkmann 	    ktime_to_timespec_cond(skb->tstamp, ts + 0))
72520d49473SPatrick Ohly 		empty = 0;
72620d49473SPatrick Ohly 	if (shhwtstamps) {
72720d49473SPatrick Ohly 		if (sock_flag(sk, SOCK_TIMESTAMPING_SYS_HARDWARE) &&
7286e94d1efSDaniel Borkmann 		    ktime_to_timespec_cond(shhwtstamps->syststamp, ts + 1))
72920d49473SPatrick Ohly 			empty = 0;
73020d49473SPatrick Ohly 		if (sock_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE) &&
7316e94d1efSDaniel Borkmann 		    ktime_to_timespec_cond(shhwtstamps->hwtstamp, ts + 2))
73220d49473SPatrick Ohly 			empty = 0;
73320d49473SPatrick Ohly 	}
73420d49473SPatrick Ohly 	if (!empty)
73520d49473SPatrick Ohly 		put_cmsg(msg, SOL_SOCKET,
73620d49473SPatrick Ohly 			 SCM_TIMESTAMPING, sizeof(ts), &ts);
73720d49473SPatrick Ohly }
7387c81fd8bSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
7397c81fd8bSArnaldo Carvalho de Melo 
7406e3e939fSJohannes Berg void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
7416e3e939fSJohannes Berg 	struct sk_buff *skb)
7426e3e939fSJohannes Berg {
7436e3e939fSJohannes Berg 	int ack;
7446e3e939fSJohannes Berg 
7456e3e939fSJohannes Berg 	if (!sock_flag(sk, SOCK_WIFI_STATUS))
7466e3e939fSJohannes Berg 		return;
7476e3e939fSJohannes Berg 	if (!skb->wifi_acked_valid)
7486e3e939fSJohannes Berg 		return;
7496e3e939fSJohannes Berg 
7506e3e939fSJohannes Berg 	ack = skb->wifi_acked;
7516e3e939fSJohannes Berg 
7526e3e939fSJohannes Berg 	put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack);
7536e3e939fSJohannes Berg }
7546e3e939fSJohannes Berg EXPORT_SYMBOL_GPL(__sock_recv_wifi_status);
7556e3e939fSJohannes Berg 
75611165f14Sstephen hemminger static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk,
75711165f14Sstephen hemminger 				   struct sk_buff *skb)
7583b885787SNeil Horman {
7593b885787SNeil Horman 	if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && skb->dropcount)
7603b885787SNeil Horman 		put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL,
7613b885787SNeil Horman 			sizeof(__u32), &skb->dropcount);
7623b885787SNeil Horman }
7633b885787SNeil Horman 
764767dd033SEric Dumazet void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
7653b885787SNeil Horman 	struct sk_buff *skb)
7663b885787SNeil Horman {
7673b885787SNeil Horman 	sock_recv_timestamp(msg, sk, skb);
7683b885787SNeil Horman 	sock_recv_drops(msg, sk, skb);
7693b885787SNeil Horman }
770767dd033SEric Dumazet EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops);
7713b885787SNeil Horman 
772a2e27255SArnaldo Carvalho de Melo static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock,
7731da177e4SLinus Torvalds 				       struct msghdr *msg, size_t size, int flags)
7741da177e4SLinus Torvalds {
7751da177e4SLinus Torvalds 	struct sock_iocb *si = kiocb_to_siocb(iocb);
7761da177e4SLinus Torvalds 
7771da177e4SLinus Torvalds 	si->sock = sock;
7781da177e4SLinus Torvalds 	si->scm = NULL;
7791da177e4SLinus Torvalds 	si->msg = msg;
7801da177e4SLinus Torvalds 	si->size = size;
7811da177e4SLinus Torvalds 	si->flags = flags;
7821da177e4SLinus Torvalds 
7831da177e4SLinus Torvalds 	return sock->ops->recvmsg(iocb, sock, msg, size, flags);
7841da177e4SLinus Torvalds }
7851da177e4SLinus Torvalds 
786a2e27255SArnaldo Carvalho de Melo static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock,
787a2e27255SArnaldo Carvalho de Melo 				 struct msghdr *msg, size_t size, int flags)
788a2e27255SArnaldo Carvalho de Melo {
789a2e27255SArnaldo Carvalho de Melo 	int err = security_socket_recvmsg(sock, msg, size, flags);
790a2e27255SArnaldo Carvalho de Melo 
791a2e27255SArnaldo Carvalho de Melo 	return err ?: __sock_recvmsg_nosec(iocb, sock, msg, size, flags);
792a2e27255SArnaldo Carvalho de Melo }
793a2e27255SArnaldo Carvalho de Melo 
7941da177e4SLinus Torvalds int sock_recvmsg(struct socket *sock, struct msghdr *msg,
7951da177e4SLinus Torvalds 		 size_t size, int flags)
7961da177e4SLinus Torvalds {
7971da177e4SLinus Torvalds 	struct kiocb iocb;
7981da177e4SLinus Torvalds 	struct sock_iocb siocb;
7991da177e4SLinus Torvalds 	int ret;
8001da177e4SLinus Torvalds 
8011da177e4SLinus Torvalds 	init_sync_kiocb(&iocb, NULL);
8021da177e4SLinus Torvalds 	iocb.private = &siocb;
8031da177e4SLinus Torvalds 	ret = __sock_recvmsg(&iocb, sock, msg, size, flags);
8041da177e4SLinus Torvalds 	if (-EIOCBQUEUED == ret)
8051da177e4SLinus Torvalds 		ret = wait_on_sync_kiocb(&iocb);
8061da177e4SLinus Torvalds 	return ret;
8071da177e4SLinus Torvalds }
808c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_recvmsg);
8091da177e4SLinus Torvalds 
810a2e27255SArnaldo Carvalho de Melo static int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
811a2e27255SArnaldo Carvalho de Melo 			      size_t size, int flags)
812a2e27255SArnaldo Carvalho de Melo {
813a2e27255SArnaldo Carvalho de Melo 	struct kiocb iocb;
814a2e27255SArnaldo Carvalho de Melo 	struct sock_iocb siocb;
815a2e27255SArnaldo Carvalho de Melo 	int ret;
816a2e27255SArnaldo Carvalho de Melo 
817a2e27255SArnaldo Carvalho de Melo 	init_sync_kiocb(&iocb, NULL);
818a2e27255SArnaldo Carvalho de Melo 	iocb.private = &siocb;
819a2e27255SArnaldo Carvalho de Melo 	ret = __sock_recvmsg_nosec(&iocb, sock, msg, size, flags);
820a2e27255SArnaldo Carvalho de Melo 	if (-EIOCBQUEUED == ret)
821a2e27255SArnaldo Carvalho de Melo 		ret = wait_on_sync_kiocb(&iocb);
822a2e27255SArnaldo Carvalho de Melo 	return ret;
823a2e27255SArnaldo Carvalho de Melo }
824a2e27255SArnaldo Carvalho de Melo 
825c1249c0aSMartin Lucina /**
826c1249c0aSMartin Lucina  * kernel_recvmsg - Receive a message from a socket (kernel space)
827c1249c0aSMartin Lucina  * @sock:       The socket to receive the message from
828c1249c0aSMartin Lucina  * @msg:        Received message
829c1249c0aSMartin Lucina  * @vec:        Input s/g array for message data
830c1249c0aSMartin Lucina  * @num:        Size of input s/g array
831c1249c0aSMartin Lucina  * @size:       Number of bytes to read
832c1249c0aSMartin Lucina  * @flags:      Message flags (MSG_DONTWAIT, etc...)
833c1249c0aSMartin Lucina  *
834c1249c0aSMartin Lucina  * On return the msg structure contains the scatter/gather array passed in the
835c1249c0aSMartin Lucina  * vec argument. The array is modified so that it consists of the unfilled
836c1249c0aSMartin Lucina  * portion of the original array.
837c1249c0aSMartin Lucina  *
838c1249c0aSMartin Lucina  * The returned value is the total number of bytes received, or an error.
839c1249c0aSMartin Lucina  */
8401da177e4SLinus Torvalds int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
84189bddce5SStephen Hemminger 		   struct kvec *vec, size_t num, size_t size, int flags)
8421da177e4SLinus Torvalds {
8431da177e4SLinus Torvalds 	mm_segment_t oldfs = get_fs();
8441da177e4SLinus Torvalds 	int result;
8451da177e4SLinus Torvalds 
8461da177e4SLinus Torvalds 	set_fs(KERNEL_DS);
8471da177e4SLinus Torvalds 	/*
8481da177e4SLinus Torvalds 	 * the following is safe, since for compiler definitions of kvec and
8491da177e4SLinus Torvalds 	 * iovec are identical, yielding the same in-core layout and alignment
8501da177e4SLinus Torvalds 	 */
85189bddce5SStephen Hemminger 	msg->msg_iov = (struct iovec *)vec, msg->msg_iovlen = num;
8521da177e4SLinus Torvalds 	result = sock_recvmsg(sock, msg, size, flags);
8531da177e4SLinus Torvalds 	set_fs(oldfs);
8541da177e4SLinus Torvalds 	return result;
8551da177e4SLinus Torvalds }
856c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_recvmsg);
8571da177e4SLinus Torvalds 
85820380731SArnaldo Carvalho de Melo static ssize_t sock_sendpage(struct file *file, struct page *page,
8591da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more)
8601da177e4SLinus Torvalds {
8611da177e4SLinus Torvalds 	struct socket *sock;
8621da177e4SLinus Torvalds 	int flags;
8631da177e4SLinus Torvalds 
864b69aee04SEric Dumazet 	sock = file->private_data;
8651da177e4SLinus Torvalds 
86635f9c09fSEric Dumazet 	flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
86735f9c09fSEric Dumazet 	/* more is a combination of MSG_MORE and MSG_SENDPAGE_NOTLAST */
86835f9c09fSEric Dumazet 	flags |= more;
8691da177e4SLinus Torvalds 
870e6949583SLinus Torvalds 	return kernel_sendpage(sock, page, offset, size, flags);
8711da177e4SLinus Torvalds }
8721da177e4SLinus Torvalds 
8739c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
8749c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
8759c55e01cSJens Axboe 				unsigned int flags)
8769c55e01cSJens Axboe {
8779c55e01cSJens Axboe 	struct socket *sock = file->private_data;
8789c55e01cSJens Axboe 
879997b37daSRémi Denis-Courmont 	if (unlikely(!sock->ops->splice_read))
880997b37daSRémi Denis-Courmont 		return -EINVAL;
881997b37daSRémi Denis-Courmont 
8829c55e01cSJens Axboe 	return sock->ops->splice_read(sock, ppos, pipe, len, flags);
8839c55e01cSJens Axboe }
8849c55e01cSJens Axboe 
885ce1d4d3eSChristoph Hellwig static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
88689bddce5SStephen Hemminger 					 struct sock_iocb *siocb)
887ce1d4d3eSChristoph Hellwig {
888d29c445bSKent Overstreet 	if (!is_sync_kiocb(iocb))
889d29c445bSKent Overstreet 		BUG();
890ce1d4d3eSChristoph Hellwig 
891ce1d4d3eSChristoph Hellwig 	siocb->kiocb = iocb;
892ce1d4d3eSChristoph Hellwig 	iocb->private = siocb;
893ce1d4d3eSChristoph Hellwig 	return siocb;
894ce1d4d3eSChristoph Hellwig }
895ce1d4d3eSChristoph Hellwig 
896ce1d4d3eSChristoph Hellwig static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb,
897027445c3SBadari Pulavarty 		struct file *file, const struct iovec *iov,
89889bddce5SStephen Hemminger 		unsigned long nr_segs)
899ce1d4d3eSChristoph Hellwig {
900ce1d4d3eSChristoph Hellwig 	struct socket *sock = file->private_data;
901ce1d4d3eSChristoph Hellwig 	size_t size = 0;
902ce1d4d3eSChristoph Hellwig 	int i;
903ce1d4d3eSChristoph Hellwig 
904ce1d4d3eSChristoph Hellwig 	for (i = 0; i < nr_segs; i++)
905ce1d4d3eSChristoph Hellwig 		size += iov[i].iov_len;
906ce1d4d3eSChristoph Hellwig 
907ce1d4d3eSChristoph Hellwig 	msg->msg_name = NULL;
908ce1d4d3eSChristoph Hellwig 	msg->msg_namelen = 0;
909ce1d4d3eSChristoph Hellwig 	msg->msg_control = NULL;
910ce1d4d3eSChristoph Hellwig 	msg->msg_controllen = 0;
911ce1d4d3eSChristoph Hellwig 	msg->msg_iov = (struct iovec *)iov;
912ce1d4d3eSChristoph Hellwig 	msg->msg_iovlen = nr_segs;
913ce1d4d3eSChristoph Hellwig 	msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
914ce1d4d3eSChristoph Hellwig 
915ce1d4d3eSChristoph Hellwig 	return __sock_recvmsg(iocb, sock, msg, size, msg->msg_flags);
916ce1d4d3eSChristoph Hellwig }
917ce1d4d3eSChristoph Hellwig 
918027445c3SBadari Pulavarty static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
919027445c3SBadari Pulavarty 				unsigned long nr_segs, loff_t pos)
920ce1d4d3eSChristoph Hellwig {
921ce1d4d3eSChristoph Hellwig 	struct sock_iocb siocb, *x;
922ce1d4d3eSChristoph Hellwig 
923ce1d4d3eSChristoph Hellwig 	if (pos != 0)
924ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
925027445c3SBadari Pulavarty 
92673a7075eSKent Overstreet 	if (iocb->ki_nbytes == 0)	/* Match SYS5 behaviour */
927ce1d4d3eSChristoph Hellwig 		return 0;
928ce1d4d3eSChristoph Hellwig 
929027445c3SBadari Pulavarty 
930027445c3SBadari Pulavarty 	x = alloc_sock_iocb(iocb, &siocb);
931ce1d4d3eSChristoph Hellwig 	if (!x)
932ce1d4d3eSChristoph Hellwig 		return -ENOMEM;
933027445c3SBadari Pulavarty 	return do_sock_read(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
934ce1d4d3eSChristoph Hellwig }
935ce1d4d3eSChristoph Hellwig 
936ce1d4d3eSChristoph Hellwig static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb,
937027445c3SBadari Pulavarty 			struct file *file, const struct iovec *iov,
93889bddce5SStephen Hemminger 			unsigned long nr_segs)
939ce1d4d3eSChristoph Hellwig {
940ce1d4d3eSChristoph Hellwig 	struct socket *sock = file->private_data;
941ce1d4d3eSChristoph Hellwig 	size_t size = 0;
942ce1d4d3eSChristoph Hellwig 	int i;
943ce1d4d3eSChristoph Hellwig 
944ce1d4d3eSChristoph Hellwig 	for (i = 0; i < nr_segs; i++)
945ce1d4d3eSChristoph Hellwig 		size += iov[i].iov_len;
946ce1d4d3eSChristoph Hellwig 
947ce1d4d3eSChristoph Hellwig 	msg->msg_name = NULL;
948ce1d4d3eSChristoph Hellwig 	msg->msg_namelen = 0;
949ce1d4d3eSChristoph Hellwig 	msg->msg_control = NULL;
950ce1d4d3eSChristoph Hellwig 	msg->msg_controllen = 0;
951ce1d4d3eSChristoph Hellwig 	msg->msg_iov = (struct iovec *)iov;
952ce1d4d3eSChristoph Hellwig 	msg->msg_iovlen = nr_segs;
953ce1d4d3eSChristoph Hellwig 	msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
954ce1d4d3eSChristoph Hellwig 	if (sock->type == SOCK_SEQPACKET)
955ce1d4d3eSChristoph Hellwig 		msg->msg_flags |= MSG_EOR;
956ce1d4d3eSChristoph Hellwig 
957ce1d4d3eSChristoph Hellwig 	return __sock_sendmsg(iocb, sock, msg, size);
958ce1d4d3eSChristoph Hellwig }
959ce1d4d3eSChristoph Hellwig 
960027445c3SBadari Pulavarty static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
961027445c3SBadari Pulavarty 			  unsigned long nr_segs, loff_t pos)
9621da177e4SLinus Torvalds {
963ce1d4d3eSChristoph Hellwig 	struct sock_iocb siocb, *x;
9641da177e4SLinus Torvalds 
965ce1d4d3eSChristoph Hellwig 	if (pos != 0)
966ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
967027445c3SBadari Pulavarty 
968027445c3SBadari Pulavarty 	x = alloc_sock_iocb(iocb, &siocb);
969ce1d4d3eSChristoph Hellwig 	if (!x)
970ce1d4d3eSChristoph Hellwig 		return -ENOMEM;
971ce1d4d3eSChristoph Hellwig 
972027445c3SBadari Pulavarty 	return do_sock_write(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
9731da177e4SLinus Torvalds }
9741da177e4SLinus Torvalds 
9751da177e4SLinus Torvalds /*
9761da177e4SLinus Torvalds  * Atomic setting of ioctl hooks to avoid race
9771da177e4SLinus Torvalds  * with module unload.
9781da177e4SLinus Torvalds  */
9791da177e4SLinus Torvalds 
9804a3e2f71SArjan van de Ven static DEFINE_MUTEX(br_ioctl_mutex);
981c6d409cfSEric Dumazet static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg);
9821da177e4SLinus Torvalds 
983881d966bSEric W. Biederman void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *))
9841da177e4SLinus Torvalds {
9854a3e2f71SArjan van de Ven 	mutex_lock(&br_ioctl_mutex);
9861da177e4SLinus Torvalds 	br_ioctl_hook = hook;
9874a3e2f71SArjan van de Ven 	mutex_unlock(&br_ioctl_mutex);
9881da177e4SLinus Torvalds }
9891da177e4SLinus Torvalds EXPORT_SYMBOL(brioctl_set);
9901da177e4SLinus Torvalds 
9914a3e2f71SArjan van de Ven static DEFINE_MUTEX(vlan_ioctl_mutex);
992881d966bSEric W. Biederman static int (*vlan_ioctl_hook) (struct net *, void __user *arg);
9931da177e4SLinus Torvalds 
994881d966bSEric W. Biederman void vlan_ioctl_set(int (*hook) (struct net *, void __user *))
9951da177e4SLinus Torvalds {
9964a3e2f71SArjan van de Ven 	mutex_lock(&vlan_ioctl_mutex);
9971da177e4SLinus Torvalds 	vlan_ioctl_hook = hook;
9984a3e2f71SArjan van de Ven 	mutex_unlock(&vlan_ioctl_mutex);
9991da177e4SLinus Torvalds }
10001da177e4SLinus Torvalds EXPORT_SYMBOL(vlan_ioctl_set);
10011da177e4SLinus Torvalds 
10024a3e2f71SArjan van de Ven static DEFINE_MUTEX(dlci_ioctl_mutex);
10031da177e4SLinus Torvalds static int (*dlci_ioctl_hook) (unsigned int, void __user *);
10041da177e4SLinus Torvalds 
10051da177e4SLinus Torvalds void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
10061da177e4SLinus Torvalds {
10074a3e2f71SArjan van de Ven 	mutex_lock(&dlci_ioctl_mutex);
10081da177e4SLinus Torvalds 	dlci_ioctl_hook = hook;
10094a3e2f71SArjan van de Ven 	mutex_unlock(&dlci_ioctl_mutex);
10101da177e4SLinus Torvalds }
10111da177e4SLinus Torvalds EXPORT_SYMBOL(dlci_ioctl_set);
10121da177e4SLinus Torvalds 
10136b96018bSArnd Bergmann static long sock_do_ioctl(struct net *net, struct socket *sock,
10146b96018bSArnd Bergmann 				 unsigned int cmd, unsigned long arg)
10156b96018bSArnd Bergmann {
10166b96018bSArnd Bergmann 	int err;
10176b96018bSArnd Bergmann 	void __user *argp = (void __user *)arg;
10186b96018bSArnd Bergmann 
10196b96018bSArnd Bergmann 	err = sock->ops->ioctl(sock, cmd, arg);
10206b96018bSArnd Bergmann 
10216b96018bSArnd Bergmann 	/*
10226b96018bSArnd Bergmann 	 * If this ioctl is unknown try to hand it down
10236b96018bSArnd Bergmann 	 * to the NIC driver.
10246b96018bSArnd Bergmann 	 */
10256b96018bSArnd Bergmann 	if (err == -ENOIOCTLCMD)
10266b96018bSArnd Bergmann 		err = dev_ioctl(net, cmd, argp);
10276b96018bSArnd Bergmann 
10286b96018bSArnd Bergmann 	return err;
10296b96018bSArnd Bergmann }
10306b96018bSArnd Bergmann 
10311da177e4SLinus Torvalds /*
10321da177e4SLinus Torvalds  *	With an ioctl, arg may well be a user mode pointer, but we don't know
10331da177e4SLinus Torvalds  *	what to do with it - that's up to the protocol still.
10341da177e4SLinus Torvalds  */
10351da177e4SLinus Torvalds 
10361da177e4SLinus Torvalds static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
10371da177e4SLinus Torvalds {
10381da177e4SLinus Torvalds 	struct socket *sock;
1039881d966bSEric W. Biederman 	struct sock *sk;
10401da177e4SLinus Torvalds 	void __user *argp = (void __user *)arg;
10411da177e4SLinus Torvalds 	int pid, err;
1042881d966bSEric W. Biederman 	struct net *net;
10431da177e4SLinus Torvalds 
1044b69aee04SEric Dumazet 	sock = file->private_data;
1045881d966bSEric W. Biederman 	sk = sock->sk;
10463b1e0a65SYOSHIFUJI Hideaki 	net = sock_net(sk);
10471da177e4SLinus Torvalds 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
1048881d966bSEric W. Biederman 		err = dev_ioctl(net, cmd, argp);
10491da177e4SLinus Torvalds 	} else
10503d23e349SJohannes Berg #ifdef CONFIG_WEXT_CORE
10511da177e4SLinus Torvalds 	if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
1052881d966bSEric W. Biederman 		err = dev_ioctl(net, cmd, argp);
10531da177e4SLinus Torvalds 	} else
10543d23e349SJohannes Berg #endif
10551da177e4SLinus Torvalds 		switch (cmd) {
10561da177e4SLinus Torvalds 		case FIOSETOWN:
10571da177e4SLinus Torvalds 		case SIOCSPGRP:
10581da177e4SLinus Torvalds 			err = -EFAULT;
10591da177e4SLinus Torvalds 			if (get_user(pid, (int __user *)argp))
10601da177e4SLinus Torvalds 				break;
10611da177e4SLinus Torvalds 			err = f_setown(sock->file, pid, 1);
10621da177e4SLinus Torvalds 			break;
10631da177e4SLinus Torvalds 		case FIOGETOWN:
10641da177e4SLinus Torvalds 		case SIOCGPGRP:
1065609d7fa9SEric W. Biederman 			err = put_user(f_getown(sock->file),
106689bddce5SStephen Hemminger 				       (int __user *)argp);
10671da177e4SLinus Torvalds 			break;
10681da177e4SLinus Torvalds 		case SIOCGIFBR:
10691da177e4SLinus Torvalds 		case SIOCSIFBR:
10701da177e4SLinus Torvalds 		case SIOCBRADDBR:
10711da177e4SLinus Torvalds 		case SIOCBRDELBR:
10721da177e4SLinus Torvalds 			err = -ENOPKG;
10731da177e4SLinus Torvalds 			if (!br_ioctl_hook)
10741da177e4SLinus Torvalds 				request_module("bridge");
10751da177e4SLinus Torvalds 
10764a3e2f71SArjan van de Ven 			mutex_lock(&br_ioctl_mutex);
10771da177e4SLinus Torvalds 			if (br_ioctl_hook)
1078881d966bSEric W. Biederman 				err = br_ioctl_hook(net, cmd, argp);
10794a3e2f71SArjan van de Ven 			mutex_unlock(&br_ioctl_mutex);
10801da177e4SLinus Torvalds 			break;
10811da177e4SLinus Torvalds 		case SIOCGIFVLAN:
10821da177e4SLinus Torvalds 		case SIOCSIFVLAN:
10831da177e4SLinus Torvalds 			err = -ENOPKG;
10841da177e4SLinus Torvalds 			if (!vlan_ioctl_hook)
10851da177e4SLinus Torvalds 				request_module("8021q");
10861da177e4SLinus Torvalds 
10874a3e2f71SArjan van de Ven 			mutex_lock(&vlan_ioctl_mutex);
10881da177e4SLinus Torvalds 			if (vlan_ioctl_hook)
1089881d966bSEric W. Biederman 				err = vlan_ioctl_hook(net, argp);
10904a3e2f71SArjan van de Ven 			mutex_unlock(&vlan_ioctl_mutex);
10911da177e4SLinus Torvalds 			break;
10921da177e4SLinus Torvalds 		case SIOCADDDLCI:
10931da177e4SLinus Torvalds 		case SIOCDELDLCI:
10941da177e4SLinus Torvalds 			err = -ENOPKG;
10951da177e4SLinus Torvalds 			if (!dlci_ioctl_hook)
10961da177e4SLinus Torvalds 				request_module("dlci");
10971da177e4SLinus Torvalds 
10984a3e2f71SArjan van de Ven 			mutex_lock(&dlci_ioctl_mutex);
10997512cbf6SPavel Emelyanov 			if (dlci_ioctl_hook)
11001da177e4SLinus Torvalds 				err = dlci_ioctl_hook(cmd, argp);
11014a3e2f71SArjan van de Ven 			mutex_unlock(&dlci_ioctl_mutex);
11021da177e4SLinus Torvalds 			break;
11031da177e4SLinus Torvalds 		default:
11046b96018bSArnd Bergmann 			err = sock_do_ioctl(net, sock, cmd, arg);
11051da177e4SLinus Torvalds 			break;
11061da177e4SLinus Torvalds 		}
11071da177e4SLinus Torvalds 	return err;
11081da177e4SLinus Torvalds }
11091da177e4SLinus Torvalds 
11101da177e4SLinus Torvalds int sock_create_lite(int family, int type, int protocol, struct socket **res)
11111da177e4SLinus Torvalds {
11121da177e4SLinus Torvalds 	int err;
11131da177e4SLinus Torvalds 	struct socket *sock = NULL;
11141da177e4SLinus Torvalds 
11151da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, 1);
11161da177e4SLinus Torvalds 	if (err)
11171da177e4SLinus Torvalds 		goto out;
11181da177e4SLinus Torvalds 
11191da177e4SLinus Torvalds 	sock = sock_alloc();
11201da177e4SLinus Torvalds 	if (!sock) {
11211da177e4SLinus Torvalds 		err = -ENOMEM;
11221da177e4SLinus Torvalds 		goto out;
11231da177e4SLinus Torvalds 	}
11241da177e4SLinus Torvalds 
11251da177e4SLinus Torvalds 	sock->type = type;
11267420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, 1);
11277420ed23SVenkat Yekkirala 	if (err)
11287420ed23SVenkat Yekkirala 		goto out_release;
11297420ed23SVenkat Yekkirala 
11301da177e4SLinus Torvalds out:
11311da177e4SLinus Torvalds 	*res = sock;
11321da177e4SLinus Torvalds 	return err;
11337420ed23SVenkat Yekkirala out_release:
11347420ed23SVenkat Yekkirala 	sock_release(sock);
11357420ed23SVenkat Yekkirala 	sock = NULL;
11367420ed23SVenkat Yekkirala 	goto out;
11371da177e4SLinus Torvalds }
1138c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_lite);
11391da177e4SLinus Torvalds 
11401da177e4SLinus Torvalds /* No kernel lock held - perfect */
11411da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file, poll_table *wait)
11421da177e4SLinus Torvalds {
1143cbf55001SEliezer Tamir 	unsigned int busy_flag = 0;
11441da177e4SLinus Torvalds 	struct socket *sock;
11451da177e4SLinus Torvalds 
11461da177e4SLinus Torvalds 	/*
11471da177e4SLinus Torvalds 	 *      We can't return errors to poll, so it's either yes or no.
11481da177e4SLinus Torvalds 	 */
1149b69aee04SEric Dumazet 	sock = file->private_data;
11502d48d67fSEliezer Tamir 
1151cbf55001SEliezer Tamir 	if (sk_can_busy_loop(sock->sk)) {
11522d48d67fSEliezer Tamir 		/* this socket can poll_ll so tell the system call */
1153cbf55001SEliezer Tamir 		busy_flag = POLL_BUSY_LOOP;
11542d48d67fSEliezer Tamir 
11552d48d67fSEliezer Tamir 		/* once, only if requested by syscall */
1156cbf55001SEliezer Tamir 		if (wait && (wait->_key & POLL_BUSY_LOOP))
1157cbf55001SEliezer Tamir 			sk_busy_loop(sock->sk, 1);
11582d48d67fSEliezer Tamir 	}
11592d48d67fSEliezer Tamir 
1160cbf55001SEliezer Tamir 	return busy_flag | sock->ops->poll(file, sock, wait);
11611da177e4SLinus Torvalds }
11621da177e4SLinus Torvalds 
11631da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma)
11641da177e4SLinus Torvalds {
1165b69aee04SEric Dumazet 	struct socket *sock = file->private_data;
11661da177e4SLinus Torvalds 
11671da177e4SLinus Torvalds 	return sock->ops->mmap(file, sock, vma);
11681da177e4SLinus Torvalds }
11691da177e4SLinus Torvalds 
117020380731SArnaldo Carvalho de Melo static int sock_close(struct inode *inode, struct file *filp)
11711da177e4SLinus Torvalds {
11721da177e4SLinus Torvalds 	sock_release(SOCKET_I(inode));
11731da177e4SLinus Torvalds 	return 0;
11741da177e4SLinus Torvalds }
11751da177e4SLinus Torvalds 
11761da177e4SLinus Torvalds /*
11771da177e4SLinus Torvalds  *	Update the socket async list
11781da177e4SLinus Torvalds  *
11791da177e4SLinus Torvalds  *	Fasync_list locking strategy.
11801da177e4SLinus Torvalds  *
11811da177e4SLinus Torvalds  *	1. fasync_list is modified only under process context socket lock
11821da177e4SLinus Torvalds  *	   i.e. under semaphore.
11831da177e4SLinus Torvalds  *	2. fasync_list is used under read_lock(&sk->sk_callback_lock)
1184989a2979SEric Dumazet  *	   or under socket lock
11851da177e4SLinus Torvalds  */
11861da177e4SLinus Torvalds 
11871da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on)
11881da177e4SLinus Torvalds {
1189989a2979SEric Dumazet 	struct socket *sock = filp->private_data;
1190989a2979SEric Dumazet 	struct sock *sk = sock->sk;
1191eaefd110SEric Dumazet 	struct socket_wq *wq;
11921da177e4SLinus Torvalds 
1193989a2979SEric Dumazet 	if (sk == NULL)
11941da177e4SLinus Torvalds 		return -EINVAL;
11951da177e4SLinus Torvalds 
11961da177e4SLinus Torvalds 	lock_sock(sk);
1197eaefd110SEric Dumazet 	wq = rcu_dereference_protected(sock->wq, sock_owned_by_user(sk));
1198eaefd110SEric Dumazet 	fasync_helper(fd, filp, on, &wq->fasync_list);
11991da177e4SLinus Torvalds 
1200eaefd110SEric Dumazet 	if (!wq->fasync_list)
1201bcdce719SEric Dumazet 		sock_reset_flag(sk, SOCK_FASYNC);
1202989a2979SEric Dumazet 	else
1203989a2979SEric Dumazet 		sock_set_flag(sk, SOCK_FASYNC);
12041da177e4SLinus Torvalds 
1205989a2979SEric Dumazet 	release_sock(sk);
12061da177e4SLinus Torvalds 	return 0;
12071da177e4SLinus Torvalds }
12081da177e4SLinus Torvalds 
120943815482SEric Dumazet /* This function may be called only under socket lock or callback_lock or rcu_lock */
12101da177e4SLinus Torvalds 
12111da177e4SLinus Torvalds int sock_wake_async(struct socket *sock, int how, int band)
12121da177e4SLinus Torvalds {
121343815482SEric Dumazet 	struct socket_wq *wq;
121443815482SEric Dumazet 
121543815482SEric Dumazet 	if (!sock)
12161da177e4SLinus Torvalds 		return -1;
121743815482SEric Dumazet 	rcu_read_lock();
121843815482SEric Dumazet 	wq = rcu_dereference(sock->wq);
121943815482SEric Dumazet 	if (!wq || !wq->fasync_list) {
122043815482SEric Dumazet 		rcu_read_unlock();
122143815482SEric Dumazet 		return -1;
122243815482SEric Dumazet 	}
122389bddce5SStephen Hemminger 	switch (how) {
12248d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_WAITD:
12251da177e4SLinus Torvalds 		if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
12261da177e4SLinus Torvalds 			break;
12271da177e4SLinus Torvalds 		goto call_kill;
12288d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_SPACE:
12291da177e4SLinus Torvalds 		if (!test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags))
12301da177e4SLinus Torvalds 			break;
12311da177e4SLinus Torvalds 		/* fall through */
12328d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_IO:
12331da177e4SLinus Torvalds call_kill:
123443815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGIO, band);
12351da177e4SLinus Torvalds 		break;
12368d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_URG:
123743815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGURG, band);
12381da177e4SLinus Torvalds 	}
123943815482SEric Dumazet 	rcu_read_unlock();
12401da177e4SLinus Torvalds 	return 0;
12411da177e4SLinus Torvalds }
1242c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_wake_async);
12431da177e4SLinus Torvalds 
1244721db93aSPavel Emelyanov int __sock_create(struct net *net, int family, int type, int protocol,
124589bddce5SStephen Hemminger 			 struct socket **res, int kern)
12461da177e4SLinus Torvalds {
12471da177e4SLinus Torvalds 	int err;
12481da177e4SLinus Torvalds 	struct socket *sock;
124955737fdaSStephen Hemminger 	const struct net_proto_family *pf;
12501da177e4SLinus Torvalds 
12511da177e4SLinus Torvalds 	/*
12521da177e4SLinus Torvalds 	 *      Check protocol is in range
12531da177e4SLinus Torvalds 	 */
12541da177e4SLinus Torvalds 	if (family < 0 || family >= NPROTO)
12551da177e4SLinus Torvalds 		return -EAFNOSUPPORT;
12561da177e4SLinus Torvalds 	if (type < 0 || type >= SOCK_MAX)
12571da177e4SLinus Torvalds 		return -EINVAL;
12581da177e4SLinus Torvalds 
12591da177e4SLinus Torvalds 	/* Compatibility.
12601da177e4SLinus Torvalds 
12611da177e4SLinus Torvalds 	   This uglymoron is moved from INET layer to here to avoid
12621da177e4SLinus Torvalds 	   deadlock in module load.
12631da177e4SLinus Torvalds 	 */
12641da177e4SLinus Torvalds 	if (family == PF_INET && type == SOCK_PACKET) {
12651da177e4SLinus Torvalds 		static int warned;
12661da177e4SLinus Torvalds 		if (!warned) {
12671da177e4SLinus Torvalds 			warned = 1;
126889bddce5SStephen Hemminger 			printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)\n",
126989bddce5SStephen Hemminger 			       current->comm);
12701da177e4SLinus Torvalds 		}
12711da177e4SLinus Torvalds 		family = PF_PACKET;
12721da177e4SLinus Torvalds 	}
12731da177e4SLinus Torvalds 
12741da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, kern);
12751da177e4SLinus Torvalds 	if (err)
12761da177e4SLinus Torvalds 		return err;
12771da177e4SLinus Torvalds 
127855737fdaSStephen Hemminger 	/*
127955737fdaSStephen Hemminger 	 *	Allocate the socket and allow the family to set things up. if
128055737fdaSStephen Hemminger 	 *	the protocol is 0, the family is instructed to select an appropriate
128155737fdaSStephen Hemminger 	 *	default.
128255737fdaSStephen Hemminger 	 */
128355737fdaSStephen Hemminger 	sock = sock_alloc();
128455737fdaSStephen Hemminger 	if (!sock) {
1285e87cc472SJoe Perches 		net_warn_ratelimited("socket: no more sockets\n");
128655737fdaSStephen Hemminger 		return -ENFILE;	/* Not exactly a match, but its the
128755737fdaSStephen Hemminger 				   closest posix thing */
128855737fdaSStephen Hemminger 	}
128955737fdaSStephen Hemminger 
129055737fdaSStephen Hemminger 	sock->type = type;
129155737fdaSStephen Hemminger 
129295a5afcaSJohannes Berg #ifdef CONFIG_MODULES
12931da177e4SLinus Torvalds 	/* Attempt to load a protocol module if the find failed.
12941da177e4SLinus Torvalds 	 *
12951da177e4SLinus Torvalds 	 * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
12961da177e4SLinus Torvalds 	 * requested real, full-featured networking support upon configuration.
12971da177e4SLinus Torvalds 	 * Otherwise module support will break!
12981da177e4SLinus Torvalds 	 */
1299190683a9SEric Dumazet 	if (rcu_access_pointer(net_families[family]) == NULL)
13001da177e4SLinus Torvalds 		request_module("net-pf-%d", family);
13011da177e4SLinus Torvalds #endif
13021da177e4SLinus Torvalds 
130355737fdaSStephen Hemminger 	rcu_read_lock();
130455737fdaSStephen Hemminger 	pf = rcu_dereference(net_families[family]);
13051da177e4SLinus Torvalds 	err = -EAFNOSUPPORT;
130655737fdaSStephen Hemminger 	if (!pf)
130755737fdaSStephen Hemminger 		goto out_release;
13081da177e4SLinus Torvalds 
13091da177e4SLinus Torvalds 	/*
13101da177e4SLinus Torvalds 	 * We will call the ->create function, that possibly is in a loadable
13111da177e4SLinus Torvalds 	 * module, so we have to bump that loadable module refcnt first.
13121da177e4SLinus Torvalds 	 */
131355737fdaSStephen Hemminger 	if (!try_module_get(pf->owner))
13141da177e4SLinus Torvalds 		goto out_release;
13151da177e4SLinus Torvalds 
131655737fdaSStephen Hemminger 	/* Now protected by module ref count */
131755737fdaSStephen Hemminger 	rcu_read_unlock();
131855737fdaSStephen Hemminger 
13193f378b68SEric Paris 	err = pf->create(net, sock, protocol, kern);
132055737fdaSStephen Hemminger 	if (err < 0)
13211da177e4SLinus Torvalds 		goto out_module_put;
1322a79af59eSFrank Filz 
13231da177e4SLinus Torvalds 	/*
13241da177e4SLinus Torvalds 	 * Now to bump the refcnt of the [loadable] module that owns this
13251da177e4SLinus Torvalds 	 * socket at sock_release time we decrement its refcnt.
13261da177e4SLinus Torvalds 	 */
132755737fdaSStephen Hemminger 	if (!try_module_get(sock->ops->owner))
132855737fdaSStephen Hemminger 		goto out_module_busy;
132955737fdaSStephen Hemminger 
13301da177e4SLinus Torvalds 	/*
13311da177e4SLinus Torvalds 	 * Now that we're done with the ->create function, the [loadable]
13321da177e4SLinus Torvalds 	 * module can have its refcnt decremented
13331da177e4SLinus Torvalds 	 */
133455737fdaSStephen Hemminger 	module_put(pf->owner);
13357420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, kern);
13367420ed23SVenkat Yekkirala 	if (err)
13373b185525SHerbert Xu 		goto out_sock_release;
133855737fdaSStephen Hemminger 	*res = sock;
13391da177e4SLinus Torvalds 
134055737fdaSStephen Hemminger 	return 0;
134155737fdaSStephen Hemminger 
134255737fdaSStephen Hemminger out_module_busy:
134355737fdaSStephen Hemminger 	err = -EAFNOSUPPORT;
13441da177e4SLinus Torvalds out_module_put:
134555737fdaSStephen Hemminger 	sock->ops = NULL;
134655737fdaSStephen Hemminger 	module_put(pf->owner);
134755737fdaSStephen Hemminger out_sock_release:
13481da177e4SLinus Torvalds 	sock_release(sock);
134955737fdaSStephen Hemminger 	return err;
135055737fdaSStephen Hemminger 
135155737fdaSStephen Hemminger out_release:
135255737fdaSStephen Hemminger 	rcu_read_unlock();
135355737fdaSStephen Hemminger 	goto out_sock_release;
13541da177e4SLinus Torvalds }
1355721db93aSPavel Emelyanov EXPORT_SYMBOL(__sock_create);
13561da177e4SLinus Torvalds 
13571da177e4SLinus Torvalds int sock_create(int family, int type, int protocol, struct socket **res)
13581da177e4SLinus Torvalds {
13591b8d7ae4SEric W. Biederman 	return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
13601da177e4SLinus Torvalds }
1361c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create);
13621da177e4SLinus Torvalds 
13631da177e4SLinus Torvalds int sock_create_kern(int family, int type, int protocol, struct socket **res)
13641da177e4SLinus Torvalds {
13651b8d7ae4SEric W. Biederman 	return __sock_create(&init_net, family, type, protocol, res, 1);
13661da177e4SLinus Torvalds }
1367c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_kern);
13681da177e4SLinus Torvalds 
13693e0fa65fSHeiko Carstens SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
13701da177e4SLinus Torvalds {
13711da177e4SLinus Torvalds 	int retval;
13721da177e4SLinus Torvalds 	struct socket *sock;
1373a677a039SUlrich Drepper 	int flags;
1374a677a039SUlrich Drepper 
1375e38b36f3SUlrich Drepper 	/* Check the SOCK_* constants for consistency.  */
1376e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
1377e38b36f3SUlrich Drepper 	BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
1378e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);
1379e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);
1380e38b36f3SUlrich Drepper 
1381a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
138277d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1383a677a039SUlrich Drepper 		return -EINVAL;
1384a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
13851da177e4SLinus Torvalds 
1386aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1387aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1388aaca0bdcSUlrich Drepper 
13891da177e4SLinus Torvalds 	retval = sock_create(family, type, protocol, &sock);
13901da177e4SLinus Torvalds 	if (retval < 0)
13911da177e4SLinus Torvalds 		goto out;
13921da177e4SLinus Torvalds 
139377d27200SUlrich Drepper 	retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
13941da177e4SLinus Torvalds 	if (retval < 0)
13951da177e4SLinus Torvalds 		goto out_release;
13961da177e4SLinus Torvalds 
13971da177e4SLinus Torvalds out:
13981da177e4SLinus Torvalds 	/* It may be already another descriptor 8) Not kernel problem. */
13991da177e4SLinus Torvalds 	return retval;
14001da177e4SLinus Torvalds 
14011da177e4SLinus Torvalds out_release:
14021da177e4SLinus Torvalds 	sock_release(sock);
14031da177e4SLinus Torvalds 	return retval;
14041da177e4SLinus Torvalds }
14051da177e4SLinus Torvalds 
14061da177e4SLinus Torvalds /*
14071da177e4SLinus Torvalds  *	Create a pair of connected sockets.
14081da177e4SLinus Torvalds  */
14091da177e4SLinus Torvalds 
14103e0fa65fSHeiko Carstens SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
14113e0fa65fSHeiko Carstens 		int __user *, usockvec)
14121da177e4SLinus Torvalds {
14131da177e4SLinus Torvalds 	struct socket *sock1, *sock2;
14141da177e4SLinus Torvalds 	int fd1, fd2, err;
1415db349509SAl Viro 	struct file *newfile1, *newfile2;
1416a677a039SUlrich Drepper 	int flags;
1417a677a039SUlrich Drepper 
1418a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
141977d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1420a677a039SUlrich Drepper 		return -EINVAL;
1421a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
14221da177e4SLinus Torvalds 
1423aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1424aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1425aaca0bdcSUlrich Drepper 
14261da177e4SLinus Torvalds 	/*
14271da177e4SLinus Torvalds 	 * Obtain the first socket and check if the underlying protocol
14281da177e4SLinus Torvalds 	 * supports the socketpair call.
14291da177e4SLinus Torvalds 	 */
14301da177e4SLinus Torvalds 
14311da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock1);
14321da177e4SLinus Torvalds 	if (err < 0)
14331da177e4SLinus Torvalds 		goto out;
14341da177e4SLinus Torvalds 
14351da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock2);
14361da177e4SLinus Torvalds 	if (err < 0)
14371da177e4SLinus Torvalds 		goto out_release_1;
14381da177e4SLinus Torvalds 
14391da177e4SLinus Torvalds 	err = sock1->ops->socketpair(sock1, sock2);
14401da177e4SLinus Torvalds 	if (err < 0)
14411da177e4SLinus Torvalds 		goto out_release_both;
14421da177e4SLinus Torvalds 
144328407630SAl Viro 	fd1 = get_unused_fd_flags(flags);
1444bf3c23d1SDavid S. Miller 	if (unlikely(fd1 < 0)) {
1445bf3c23d1SDavid S. Miller 		err = fd1;
14461da177e4SLinus Torvalds 		goto out_release_both;
1447bf3c23d1SDavid S. Miller 	}
144828407630SAl Viro 	fd2 = get_unused_fd_flags(flags);
1449198de4d7SAl Viro 	if (unlikely(fd2 < 0)) {
1450198de4d7SAl Viro 		err = fd2;
145128407630SAl Viro 		put_unused_fd(fd1);
145228407630SAl Viro 		goto out_release_both;
145328407630SAl Viro 	}
145428407630SAl Viro 
1455aab174f0SLinus Torvalds 	newfile1 = sock_alloc_file(sock1, flags, NULL);
145628407630SAl Viro 	if (unlikely(IS_ERR(newfile1))) {
145728407630SAl Viro 		err = PTR_ERR(newfile1);
145828407630SAl Viro 		put_unused_fd(fd1);
145928407630SAl Viro 		put_unused_fd(fd2);
146028407630SAl Viro 		goto out_release_both;
146128407630SAl Viro 	}
146228407630SAl Viro 
1463aab174f0SLinus Torvalds 	newfile2 = sock_alloc_file(sock2, flags, NULL);
146428407630SAl Viro 	if (IS_ERR(newfile2)) {
146528407630SAl Viro 		err = PTR_ERR(newfile2);
1466198de4d7SAl Viro 		fput(newfile1);
1467198de4d7SAl Viro 		put_unused_fd(fd1);
146828407630SAl Viro 		put_unused_fd(fd2);
1469198de4d7SAl Viro 		sock_release(sock2);
1470198de4d7SAl Viro 		goto out;
1471db349509SAl Viro 	}
1472db349509SAl Viro 
1473157cf649SAl Viro 	audit_fd_pair(fd1, fd2);
1474db349509SAl Viro 	fd_install(fd1, newfile1);
1475db349509SAl Viro 	fd_install(fd2, newfile2);
14761da177e4SLinus Torvalds 	/* fd1 and fd2 may be already another descriptors.
14771da177e4SLinus Torvalds 	 * Not kernel problem.
14781da177e4SLinus Torvalds 	 */
14791da177e4SLinus Torvalds 
14801da177e4SLinus Torvalds 	err = put_user(fd1, &usockvec[0]);
14811da177e4SLinus Torvalds 	if (!err)
14821da177e4SLinus Torvalds 		err = put_user(fd2, &usockvec[1]);
14831da177e4SLinus Torvalds 	if (!err)
14841da177e4SLinus Torvalds 		return 0;
14851da177e4SLinus Torvalds 
14861da177e4SLinus Torvalds 	sys_close(fd2);
14871da177e4SLinus Torvalds 	sys_close(fd1);
14881da177e4SLinus Torvalds 	return err;
14891da177e4SLinus Torvalds 
14901da177e4SLinus Torvalds out_release_both:
14911da177e4SLinus Torvalds 	sock_release(sock2);
14921da177e4SLinus Torvalds out_release_1:
14931da177e4SLinus Torvalds 	sock_release(sock1);
14941da177e4SLinus Torvalds out:
14951da177e4SLinus Torvalds 	return err;
14961da177e4SLinus Torvalds }
14971da177e4SLinus Torvalds 
14981da177e4SLinus Torvalds /*
14991da177e4SLinus Torvalds  *	Bind a name to a socket. Nothing much to do here since it's
15001da177e4SLinus Torvalds  *	the protocol's responsibility to handle the local address.
15011da177e4SLinus Torvalds  *
15021da177e4SLinus Torvalds  *	We move the socket address to kernel space before we call
15031da177e4SLinus Torvalds  *	the protocol layer (having also checked the address is ok).
15041da177e4SLinus Torvalds  */
15051da177e4SLinus Torvalds 
150620f37034SHeiko Carstens SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
15071da177e4SLinus Torvalds {
15081da177e4SLinus Torvalds 	struct socket *sock;
1509230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
15106cb153caSBenjamin LaHaise 	int err, fput_needed;
15111da177e4SLinus Torvalds 
151289bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
151389bddce5SStephen Hemminger 	if (sock) {
151443db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(umyaddr, addrlen, &address);
151589bddce5SStephen Hemminger 		if (err >= 0) {
151689bddce5SStephen Hemminger 			err = security_socket_bind(sock,
1517230b1839SYOSHIFUJI Hideaki 						   (struct sockaddr *)&address,
151889bddce5SStephen Hemminger 						   addrlen);
15196cb153caSBenjamin LaHaise 			if (!err)
15206cb153caSBenjamin LaHaise 				err = sock->ops->bind(sock,
152189bddce5SStephen Hemminger 						      (struct sockaddr *)
1522230b1839SYOSHIFUJI Hideaki 						      &address, addrlen);
15231da177e4SLinus Torvalds 		}
15246cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
15251da177e4SLinus Torvalds 	}
15261da177e4SLinus Torvalds 	return err;
15271da177e4SLinus Torvalds }
15281da177e4SLinus Torvalds 
15291da177e4SLinus Torvalds /*
15301da177e4SLinus Torvalds  *	Perform a listen. Basically, we allow the protocol to do anything
15311da177e4SLinus Torvalds  *	necessary for a listen, and if that works, we mark the socket as
15321da177e4SLinus Torvalds  *	ready for listening.
15331da177e4SLinus Torvalds  */
15341da177e4SLinus Torvalds 
15353e0fa65fSHeiko Carstens SYSCALL_DEFINE2(listen, int, fd, int, backlog)
15361da177e4SLinus Torvalds {
15371da177e4SLinus Torvalds 	struct socket *sock;
15386cb153caSBenjamin LaHaise 	int err, fput_needed;
1539b8e1f9b5SPavel Emelyanov 	int somaxconn;
15401da177e4SLinus Torvalds 
154189bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
154289bddce5SStephen Hemminger 	if (sock) {
15438efa6e93SPavel Emelyanov 		somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
154495c96174SEric Dumazet 		if ((unsigned int)backlog > somaxconn)
1545b8e1f9b5SPavel Emelyanov 			backlog = somaxconn;
15461da177e4SLinus Torvalds 
15471da177e4SLinus Torvalds 		err = security_socket_listen(sock, backlog);
15486cb153caSBenjamin LaHaise 		if (!err)
15491da177e4SLinus Torvalds 			err = sock->ops->listen(sock, backlog);
15506cb153caSBenjamin LaHaise 
15516cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
15521da177e4SLinus Torvalds 	}
15531da177e4SLinus Torvalds 	return err;
15541da177e4SLinus Torvalds }
15551da177e4SLinus Torvalds 
15561da177e4SLinus Torvalds /*
15571da177e4SLinus Torvalds  *	For accept, we attempt to create a new socket, set up the link
15581da177e4SLinus Torvalds  *	with the client, wake up the client, then return the new
15591da177e4SLinus Torvalds  *	connected fd. We collect the address of the connector in kernel
15601da177e4SLinus Torvalds  *	space and move it to user at the very end. This is unclean because
15611da177e4SLinus Torvalds  *	we open the socket then return an error.
15621da177e4SLinus Torvalds  *
15631da177e4SLinus Torvalds  *	1003.1g adds the ability to recvmsg() to query connection pending
15641da177e4SLinus Torvalds  *	status to recvmsg. We need to add that support in a way thats
15651da177e4SLinus Torvalds  *	clean when we restucture accept also.
15661da177e4SLinus Torvalds  */
15671da177e4SLinus Torvalds 
156820f37034SHeiko Carstens SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
156920f37034SHeiko Carstens 		int __user *, upeer_addrlen, int, flags)
15701da177e4SLinus Torvalds {
15711da177e4SLinus Torvalds 	struct socket *sock, *newsock;
157239d8c1b6SDavid S. Miller 	struct file *newfile;
15736cb153caSBenjamin LaHaise 	int err, len, newfd, fput_needed;
1574230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
15751da177e4SLinus Torvalds 
157677d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1577aaca0bdcSUlrich Drepper 		return -EINVAL;
1578aaca0bdcSUlrich Drepper 
1579aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1580aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1581aaca0bdcSUlrich Drepper 
15826cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
15831da177e4SLinus Torvalds 	if (!sock)
15841da177e4SLinus Torvalds 		goto out;
15851da177e4SLinus Torvalds 
15861da177e4SLinus Torvalds 	err = -ENFILE;
1587c6d409cfSEric Dumazet 	newsock = sock_alloc();
1588c6d409cfSEric Dumazet 	if (!newsock)
15891da177e4SLinus Torvalds 		goto out_put;
15901da177e4SLinus Torvalds 
15911da177e4SLinus Torvalds 	newsock->type = sock->type;
15921da177e4SLinus Torvalds 	newsock->ops = sock->ops;
15931da177e4SLinus Torvalds 
15941da177e4SLinus Torvalds 	/*
15951da177e4SLinus Torvalds 	 * We don't need try_module_get here, as the listening socket (sock)
15961da177e4SLinus Torvalds 	 * has the protocol module (sock->ops->owner) held.
15971da177e4SLinus Torvalds 	 */
15981da177e4SLinus Torvalds 	__module_get(newsock->ops->owner);
15991da177e4SLinus Torvalds 
160028407630SAl Viro 	newfd = get_unused_fd_flags(flags);
160139d8c1b6SDavid S. Miller 	if (unlikely(newfd < 0)) {
160239d8c1b6SDavid S. Miller 		err = newfd;
16039a1875e6SDavid S. Miller 		sock_release(newsock);
16049a1875e6SDavid S. Miller 		goto out_put;
160539d8c1b6SDavid S. Miller 	}
1606aab174f0SLinus Torvalds 	newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name);
160728407630SAl Viro 	if (unlikely(IS_ERR(newfile))) {
160828407630SAl Viro 		err = PTR_ERR(newfile);
160928407630SAl Viro 		put_unused_fd(newfd);
161028407630SAl Viro 		sock_release(newsock);
161128407630SAl Viro 		goto out_put;
161228407630SAl Viro 	}
161339d8c1b6SDavid S. Miller 
1614a79af59eSFrank Filz 	err = security_socket_accept(sock, newsock);
1615a79af59eSFrank Filz 	if (err)
161639d8c1b6SDavid S. Miller 		goto out_fd;
1617a79af59eSFrank Filz 
16181da177e4SLinus Torvalds 	err = sock->ops->accept(sock, newsock, sock->file->f_flags);
16191da177e4SLinus Torvalds 	if (err < 0)
162039d8c1b6SDavid S. Miller 		goto out_fd;
16211da177e4SLinus Torvalds 
16221da177e4SLinus Torvalds 	if (upeer_sockaddr) {
1623230b1839SYOSHIFUJI Hideaki 		if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
162489bddce5SStephen Hemminger 					  &len, 2) < 0) {
16251da177e4SLinus Torvalds 			err = -ECONNABORTED;
162639d8c1b6SDavid S. Miller 			goto out_fd;
16271da177e4SLinus Torvalds 		}
162843db362dSMaciej Żenczykowski 		err = move_addr_to_user(&address,
1629230b1839SYOSHIFUJI Hideaki 					len, upeer_sockaddr, upeer_addrlen);
16301da177e4SLinus Torvalds 		if (err < 0)
163139d8c1b6SDavid S. Miller 			goto out_fd;
16321da177e4SLinus Torvalds 	}
16331da177e4SLinus Torvalds 
16341da177e4SLinus Torvalds 	/* File flags are not inherited via accept() unlike another OSes. */
16351da177e4SLinus Torvalds 
163639d8c1b6SDavid S. Miller 	fd_install(newfd, newfile);
163739d8c1b6SDavid S. Miller 	err = newfd;
16381da177e4SLinus Torvalds 
16391da177e4SLinus Torvalds out_put:
16406cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
16411da177e4SLinus Torvalds out:
16421da177e4SLinus Torvalds 	return err;
164339d8c1b6SDavid S. Miller out_fd:
16449606a216SDavid S. Miller 	fput(newfile);
164539d8c1b6SDavid S. Miller 	put_unused_fd(newfd);
16461da177e4SLinus Torvalds 	goto out_put;
16471da177e4SLinus Torvalds }
16481da177e4SLinus Torvalds 
164920f37034SHeiko Carstens SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,
165020f37034SHeiko Carstens 		int __user *, upeer_addrlen)
1651aaca0bdcSUlrich Drepper {
1652de11defeSUlrich Drepper 	return sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0);
1653aaca0bdcSUlrich Drepper }
1654aaca0bdcSUlrich Drepper 
16551da177e4SLinus Torvalds /*
16561da177e4SLinus Torvalds  *	Attempt to connect to a socket with the server address.  The address
16571da177e4SLinus Torvalds  *	is in user space so we verify it is OK and move it to kernel space.
16581da177e4SLinus Torvalds  *
16591da177e4SLinus Torvalds  *	For 1003.1g we need to add clean support for a bind to AF_UNSPEC to
16601da177e4SLinus Torvalds  *	break bindings
16611da177e4SLinus Torvalds  *
16621da177e4SLinus Torvalds  *	NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and
16631da177e4SLinus Torvalds  *	other SEQPACKET protocols that take time to connect() as it doesn't
16641da177e4SLinus Torvalds  *	include the -EINPROGRESS status for such sockets.
16651da177e4SLinus Torvalds  */
16661da177e4SLinus Torvalds 
166720f37034SHeiko Carstens SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
166820f37034SHeiko Carstens 		int, addrlen)
16691da177e4SLinus Torvalds {
16701da177e4SLinus Torvalds 	struct socket *sock;
1671230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16726cb153caSBenjamin LaHaise 	int err, fput_needed;
16731da177e4SLinus Torvalds 
16746cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
16751da177e4SLinus Torvalds 	if (!sock)
16761da177e4SLinus Torvalds 		goto out;
167743db362dSMaciej Żenczykowski 	err = move_addr_to_kernel(uservaddr, addrlen, &address);
16781da177e4SLinus Torvalds 	if (err < 0)
16791da177e4SLinus Torvalds 		goto out_put;
16801da177e4SLinus Torvalds 
168189bddce5SStephen Hemminger 	err =
1682230b1839SYOSHIFUJI Hideaki 	    security_socket_connect(sock, (struct sockaddr *)&address, addrlen);
16831da177e4SLinus Torvalds 	if (err)
16841da177e4SLinus Torvalds 		goto out_put;
16851da177e4SLinus Torvalds 
1686230b1839SYOSHIFUJI Hideaki 	err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,
16871da177e4SLinus Torvalds 				 sock->file->f_flags);
16881da177e4SLinus Torvalds out_put:
16896cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
16901da177e4SLinus Torvalds out:
16911da177e4SLinus Torvalds 	return err;
16921da177e4SLinus Torvalds }
16931da177e4SLinus Torvalds 
16941da177e4SLinus Torvalds /*
16951da177e4SLinus Torvalds  *	Get the local address ('name') of a socket object. Move the obtained
16961da177e4SLinus Torvalds  *	name to user space.
16971da177e4SLinus Torvalds  */
16981da177e4SLinus Torvalds 
169920f37034SHeiko Carstens SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
170020f37034SHeiko Carstens 		int __user *, usockaddr_len)
17011da177e4SLinus Torvalds {
17021da177e4SLinus Torvalds 	struct socket *sock;
1703230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
17046cb153caSBenjamin LaHaise 	int len, err, fput_needed;
17051da177e4SLinus Torvalds 
17066cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
17071da177e4SLinus Torvalds 	if (!sock)
17081da177e4SLinus Torvalds 		goto out;
17091da177e4SLinus Torvalds 
17101da177e4SLinus Torvalds 	err = security_socket_getsockname(sock);
17111da177e4SLinus Torvalds 	if (err)
17121da177e4SLinus Torvalds 		goto out_put;
17131da177e4SLinus Torvalds 
1714230b1839SYOSHIFUJI Hideaki 	err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0);
17151da177e4SLinus Torvalds 	if (err)
17161da177e4SLinus Torvalds 		goto out_put;
171743db362dSMaciej Żenczykowski 	err = move_addr_to_user(&address, len, usockaddr, usockaddr_len);
17181da177e4SLinus Torvalds 
17191da177e4SLinus Torvalds out_put:
17206cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
17211da177e4SLinus Torvalds out:
17221da177e4SLinus Torvalds 	return err;
17231da177e4SLinus Torvalds }
17241da177e4SLinus Torvalds 
17251da177e4SLinus Torvalds /*
17261da177e4SLinus Torvalds  *	Get the remote address ('name') of a socket object. Move the obtained
17271da177e4SLinus Torvalds  *	name to user space.
17281da177e4SLinus Torvalds  */
17291da177e4SLinus Torvalds 
173020f37034SHeiko Carstens SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
173120f37034SHeiko Carstens 		int __user *, usockaddr_len)
17321da177e4SLinus Torvalds {
17331da177e4SLinus Torvalds 	struct socket *sock;
1734230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
17356cb153caSBenjamin LaHaise 	int len, err, fput_needed;
17361da177e4SLinus Torvalds 
173789bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
173889bddce5SStephen Hemminger 	if (sock != NULL) {
17391da177e4SLinus Torvalds 		err = security_socket_getpeername(sock);
17401da177e4SLinus Torvalds 		if (err) {
17416cb153caSBenjamin LaHaise 			fput_light(sock->file, fput_needed);
17421da177e4SLinus Torvalds 			return err;
17431da177e4SLinus Torvalds 		}
17441da177e4SLinus Torvalds 
174589bddce5SStephen Hemminger 		err =
1746230b1839SYOSHIFUJI Hideaki 		    sock->ops->getname(sock, (struct sockaddr *)&address, &len,
174789bddce5SStephen Hemminger 				       1);
17481da177e4SLinus Torvalds 		if (!err)
174943db362dSMaciej Żenczykowski 			err = move_addr_to_user(&address, len, usockaddr,
175089bddce5SStephen Hemminger 						usockaddr_len);
17516cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
17521da177e4SLinus Torvalds 	}
17531da177e4SLinus Torvalds 	return err;
17541da177e4SLinus Torvalds }
17551da177e4SLinus Torvalds 
17561da177e4SLinus Torvalds /*
17571da177e4SLinus Torvalds  *	Send a datagram to a given address. We move the address into kernel
17581da177e4SLinus Torvalds  *	space and check the user space data area is readable before invoking
17591da177e4SLinus Torvalds  *	the protocol.
17601da177e4SLinus Torvalds  */
17611da177e4SLinus Torvalds 
17623e0fa65fSHeiko Carstens SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
176395c96174SEric Dumazet 		unsigned int, flags, struct sockaddr __user *, addr,
17643e0fa65fSHeiko Carstens 		int, addr_len)
17651da177e4SLinus Torvalds {
17661da177e4SLinus Torvalds 	struct socket *sock;
1767230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
17681da177e4SLinus Torvalds 	int err;
17691da177e4SLinus Torvalds 	struct msghdr msg;
17701da177e4SLinus Torvalds 	struct iovec iov;
17716cb153caSBenjamin LaHaise 	int fput_needed;
17721da177e4SLinus Torvalds 
1773253eacc0SLinus Torvalds 	if (len > INT_MAX)
1774253eacc0SLinus Torvalds 		len = INT_MAX;
1775de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1776de0fa95cSPavel Emelyanov 	if (!sock)
17774387ff75SDavid S. Miller 		goto out;
17786cb153caSBenjamin LaHaise 
17791da177e4SLinus Torvalds 	iov.iov_base = buff;
17801da177e4SLinus Torvalds 	iov.iov_len = len;
17811da177e4SLinus Torvalds 	msg.msg_name = NULL;
17821da177e4SLinus Torvalds 	msg.msg_iov = &iov;
17831da177e4SLinus Torvalds 	msg.msg_iovlen = 1;
17841da177e4SLinus Torvalds 	msg.msg_control = NULL;
17851da177e4SLinus Torvalds 	msg.msg_controllen = 0;
17861da177e4SLinus Torvalds 	msg.msg_namelen = 0;
17876cb153caSBenjamin LaHaise 	if (addr) {
178843db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(addr, addr_len, &address);
17891da177e4SLinus Torvalds 		if (err < 0)
17901da177e4SLinus Torvalds 			goto out_put;
1791230b1839SYOSHIFUJI Hideaki 		msg.msg_name = (struct sockaddr *)&address;
17921da177e4SLinus Torvalds 		msg.msg_namelen = addr_len;
17931da177e4SLinus Torvalds 	}
17941da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
17951da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
17961da177e4SLinus Torvalds 	msg.msg_flags = flags;
17971da177e4SLinus Torvalds 	err = sock_sendmsg(sock, &msg, len);
17981da177e4SLinus Torvalds 
17991da177e4SLinus Torvalds out_put:
1800de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
18014387ff75SDavid S. Miller out:
18021da177e4SLinus Torvalds 	return err;
18031da177e4SLinus Torvalds }
18041da177e4SLinus Torvalds 
18051da177e4SLinus Torvalds /*
18061da177e4SLinus Torvalds  *	Send a datagram down a socket.
18071da177e4SLinus Torvalds  */
18081da177e4SLinus Torvalds 
18093e0fa65fSHeiko Carstens SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len,
181095c96174SEric Dumazet 		unsigned int, flags)
18111da177e4SLinus Torvalds {
18121da177e4SLinus Torvalds 	return sys_sendto(fd, buff, len, flags, NULL, 0);
18131da177e4SLinus Torvalds }
18141da177e4SLinus Torvalds 
18151da177e4SLinus Torvalds /*
18161da177e4SLinus Torvalds  *	Receive a frame from the socket and optionally record the address of the
18171da177e4SLinus Torvalds  *	sender. We verify the buffers are writable and if needed move the
18181da177e4SLinus Torvalds  *	sender address from kernel to user space.
18191da177e4SLinus Torvalds  */
18201da177e4SLinus Torvalds 
18213e0fa65fSHeiko Carstens SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
182295c96174SEric Dumazet 		unsigned int, flags, struct sockaddr __user *, addr,
18233e0fa65fSHeiko Carstens 		int __user *, addr_len)
18241da177e4SLinus Torvalds {
18251da177e4SLinus Torvalds 	struct socket *sock;
18261da177e4SLinus Torvalds 	struct iovec iov;
18271da177e4SLinus Torvalds 	struct msghdr msg;
1828230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
18291da177e4SLinus Torvalds 	int err, err2;
18306cb153caSBenjamin LaHaise 	int fput_needed;
18311da177e4SLinus Torvalds 
1832253eacc0SLinus Torvalds 	if (size > INT_MAX)
1833253eacc0SLinus Torvalds 		size = INT_MAX;
1834de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
18351da177e4SLinus Torvalds 	if (!sock)
1836de0fa95cSPavel Emelyanov 		goto out;
18371da177e4SLinus Torvalds 
18381da177e4SLinus Torvalds 	msg.msg_control = NULL;
18391da177e4SLinus Torvalds 	msg.msg_controllen = 0;
18401da177e4SLinus Torvalds 	msg.msg_iovlen = 1;
18411da177e4SLinus Torvalds 	msg.msg_iov = &iov;
18421da177e4SLinus Torvalds 	iov.iov_len = size;
18431da177e4SLinus Torvalds 	iov.iov_base = ubuf;
1844f3d33426SHannes Frederic Sowa 	/* Save some cycles and don't copy the address if not needed */
1845f3d33426SHannes Frederic Sowa 	msg.msg_name = addr ? (struct sockaddr *)&address : NULL;
1846f3d33426SHannes Frederic Sowa 	/* We assume all kernel code knows the size of sockaddr_storage */
1847f3d33426SHannes Frederic Sowa 	msg.msg_namelen = 0;
18481da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
18491da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
18501da177e4SLinus Torvalds 	err = sock_recvmsg(sock, &msg, size, flags);
18511da177e4SLinus Torvalds 
185289bddce5SStephen Hemminger 	if (err >= 0 && addr != NULL) {
185343db362dSMaciej Żenczykowski 		err2 = move_addr_to_user(&address,
1854230b1839SYOSHIFUJI Hideaki 					 msg.msg_namelen, addr, addr_len);
18551da177e4SLinus Torvalds 		if (err2 < 0)
18561da177e4SLinus Torvalds 			err = err2;
18571da177e4SLinus Torvalds 	}
1858de0fa95cSPavel Emelyanov 
1859de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
18604387ff75SDavid S. Miller out:
18611da177e4SLinus Torvalds 	return err;
18621da177e4SLinus Torvalds }
18631da177e4SLinus Torvalds 
18641da177e4SLinus Torvalds /*
18651da177e4SLinus Torvalds  *	Receive a datagram from a socket.
18661da177e4SLinus Torvalds  */
18671da177e4SLinus Torvalds 
186889bddce5SStephen Hemminger asmlinkage long sys_recv(int fd, void __user *ubuf, size_t size,
186995c96174SEric Dumazet 			 unsigned int flags)
18701da177e4SLinus Torvalds {
18711da177e4SLinus Torvalds 	return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL);
18721da177e4SLinus Torvalds }
18731da177e4SLinus Torvalds 
18741da177e4SLinus Torvalds /*
18751da177e4SLinus Torvalds  *	Set a socket option. Because we don't know the option lengths we have
18761da177e4SLinus Torvalds  *	to pass the user mode parameter for the protocols to sort out.
18771da177e4SLinus Torvalds  */
18781da177e4SLinus Torvalds 
187920f37034SHeiko Carstens SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
188020f37034SHeiko Carstens 		char __user *, optval, int, optlen)
18811da177e4SLinus Torvalds {
18826cb153caSBenjamin LaHaise 	int err, fput_needed;
18831da177e4SLinus Torvalds 	struct socket *sock;
18841da177e4SLinus Torvalds 
18851da177e4SLinus Torvalds 	if (optlen < 0)
18861da177e4SLinus Torvalds 		return -EINVAL;
18871da177e4SLinus Torvalds 
188889bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
188989bddce5SStephen Hemminger 	if (sock != NULL) {
18901da177e4SLinus Torvalds 		err = security_socket_setsockopt(sock, level, optname);
18916cb153caSBenjamin LaHaise 		if (err)
18926cb153caSBenjamin LaHaise 			goto out_put;
18931da177e4SLinus Torvalds 
18941da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
189589bddce5SStephen Hemminger 			err =
189689bddce5SStephen Hemminger 			    sock_setsockopt(sock, level, optname, optval,
189789bddce5SStephen Hemminger 					    optlen);
18981da177e4SLinus Torvalds 		else
189989bddce5SStephen Hemminger 			err =
190089bddce5SStephen Hemminger 			    sock->ops->setsockopt(sock, level, optname, optval,
190189bddce5SStephen Hemminger 						  optlen);
19026cb153caSBenjamin LaHaise out_put:
19036cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
19041da177e4SLinus Torvalds 	}
19051da177e4SLinus Torvalds 	return err;
19061da177e4SLinus Torvalds }
19071da177e4SLinus Torvalds 
19081da177e4SLinus Torvalds /*
19091da177e4SLinus Torvalds  *	Get a socket option. Because we don't know the option lengths we have
19101da177e4SLinus Torvalds  *	to pass a user mode parameter for the protocols to sort out.
19111da177e4SLinus Torvalds  */
19121da177e4SLinus Torvalds 
191320f37034SHeiko Carstens SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
191420f37034SHeiko Carstens 		char __user *, optval, int __user *, optlen)
19151da177e4SLinus Torvalds {
19166cb153caSBenjamin LaHaise 	int err, fput_needed;
19171da177e4SLinus Torvalds 	struct socket *sock;
19181da177e4SLinus Torvalds 
191989bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
192089bddce5SStephen Hemminger 	if (sock != NULL) {
19216cb153caSBenjamin LaHaise 		err = security_socket_getsockopt(sock, level, optname);
19226cb153caSBenjamin LaHaise 		if (err)
19236cb153caSBenjamin LaHaise 			goto out_put;
19241da177e4SLinus Torvalds 
19251da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
192689bddce5SStephen Hemminger 			err =
192789bddce5SStephen Hemminger 			    sock_getsockopt(sock, level, optname, optval,
192889bddce5SStephen Hemminger 					    optlen);
19291da177e4SLinus Torvalds 		else
193089bddce5SStephen Hemminger 			err =
193189bddce5SStephen Hemminger 			    sock->ops->getsockopt(sock, level, optname, optval,
193289bddce5SStephen Hemminger 						  optlen);
19336cb153caSBenjamin LaHaise out_put:
19346cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
19351da177e4SLinus Torvalds 	}
19361da177e4SLinus Torvalds 	return err;
19371da177e4SLinus Torvalds }
19381da177e4SLinus Torvalds 
19391da177e4SLinus Torvalds /*
19401da177e4SLinus Torvalds  *	Shutdown a socket.
19411da177e4SLinus Torvalds  */
19421da177e4SLinus Torvalds 
1943754fe8d2SHeiko Carstens SYSCALL_DEFINE2(shutdown, int, fd, int, how)
19441da177e4SLinus Torvalds {
19456cb153caSBenjamin LaHaise 	int err, fput_needed;
19461da177e4SLinus Torvalds 	struct socket *sock;
19471da177e4SLinus Torvalds 
194889bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
194989bddce5SStephen Hemminger 	if (sock != NULL) {
19501da177e4SLinus Torvalds 		err = security_socket_shutdown(sock, how);
19516cb153caSBenjamin LaHaise 		if (!err)
19521da177e4SLinus Torvalds 			err = sock->ops->shutdown(sock, how);
19536cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
19541da177e4SLinus Torvalds 	}
19551da177e4SLinus Torvalds 	return err;
19561da177e4SLinus Torvalds }
19571da177e4SLinus Torvalds 
19581da177e4SLinus Torvalds /* A couple of helpful macros for getting the address of the 32/64 bit
19591da177e4SLinus Torvalds  * fields which are the same type (int / unsigned) on our platforms.
19601da177e4SLinus Torvalds  */
19611da177e4SLinus Torvalds #define COMPAT_MSG(msg, member)	((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member)
19621da177e4SLinus Torvalds #define COMPAT_NAMELEN(msg)	COMPAT_MSG(msg, msg_namelen)
19631da177e4SLinus Torvalds #define COMPAT_FLAGS(msg)	COMPAT_MSG(msg, msg_flags)
19641da177e4SLinus Torvalds 
1965c71d8ebeSTetsuo Handa struct used_address {
1966c71d8ebeSTetsuo Handa 	struct sockaddr_storage name;
1967c71d8ebeSTetsuo Handa 	unsigned int name_len;
1968c71d8ebeSTetsuo Handa };
1969c71d8ebeSTetsuo Handa 
19701661bf36SDan Carpenter static int copy_msghdr_from_user(struct msghdr *kmsg,
19711661bf36SDan Carpenter 				 struct msghdr __user *umsg)
19721661bf36SDan Carpenter {
19731661bf36SDan Carpenter 	if (copy_from_user(kmsg, umsg, sizeof(struct msghdr)))
19741661bf36SDan Carpenter 		return -EFAULT;
19751661bf36SDan Carpenter 	if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
19761661bf36SDan Carpenter 		return -EINVAL;
19771661bf36SDan Carpenter 	return 0;
19781661bf36SDan Carpenter }
19791661bf36SDan Carpenter 
1980a7526eb5SAndy Lutomirski static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
198195c96174SEric Dumazet 			 struct msghdr *msg_sys, unsigned int flags,
1982c71d8ebeSTetsuo Handa 			 struct used_address *used_address)
19831da177e4SLinus Torvalds {
198489bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
198589bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
1986230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
19871da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
1988b9d717a7SAlex Williamson 	unsigned char ctl[sizeof(struct cmsghdr) + 20]
1989b9d717a7SAlex Williamson 	    __attribute__ ((aligned(sizeof(__kernel_size_t))));
1990b9d717a7SAlex Williamson 	/* 20 is size of ipv6_pktinfo */
19911da177e4SLinus Torvalds 	unsigned char *ctl_buf = ctl;
1992a74e9106SEric Dumazet 	int err, ctl_len, total_len;
19931da177e4SLinus Torvalds 
19941da177e4SLinus Torvalds 	err = -EFAULT;
19951da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
1996228e548eSAnton Blanchard 		if (get_compat_msghdr(msg_sys, msg_compat))
19971da177e4SLinus Torvalds 			return -EFAULT;
19981661bf36SDan Carpenter 	} else {
19991661bf36SDan Carpenter 		err = copy_msghdr_from_user(msg_sys, msg);
20001661bf36SDan Carpenter 		if (err)
20011661bf36SDan Carpenter 			return err;
20021661bf36SDan Carpenter 	}
20031da177e4SLinus Torvalds 
2004a74e9106SEric Dumazet 	if (msg_sys->msg_iovlen > UIO_FASTIOV) {
20051da177e4SLinus Torvalds 		err = -EMSGSIZE;
2006228e548eSAnton Blanchard 		if (msg_sys->msg_iovlen > UIO_MAXIOV)
2007228e548eSAnton Blanchard 			goto out;
20081da177e4SLinus Torvalds 		err = -ENOMEM;
2009a74e9106SEric Dumazet 		iov = kmalloc(msg_sys->msg_iovlen * sizeof(struct iovec),
2010a74e9106SEric Dumazet 			      GFP_KERNEL);
20111da177e4SLinus Torvalds 		if (!iov)
2012228e548eSAnton Blanchard 			goto out;
20131da177e4SLinus Torvalds 	}
20141da177e4SLinus Torvalds 
20151da177e4SLinus Torvalds 	/* This will also move the address data into kernel space */
20161da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
201743db362dSMaciej Żenczykowski 		err = verify_compat_iovec(msg_sys, iov, &address, VERIFY_READ);
20181da177e4SLinus Torvalds 	} else
201943db362dSMaciej Żenczykowski 		err = verify_iovec(msg_sys, iov, &address, VERIFY_READ);
20201da177e4SLinus Torvalds 	if (err < 0)
20211da177e4SLinus Torvalds 		goto out_freeiov;
20221da177e4SLinus Torvalds 	total_len = err;
20231da177e4SLinus Torvalds 
20241da177e4SLinus Torvalds 	err = -ENOBUFS;
20251da177e4SLinus Torvalds 
2026228e548eSAnton Blanchard 	if (msg_sys->msg_controllen > INT_MAX)
20271da177e4SLinus Torvalds 		goto out_freeiov;
2028228e548eSAnton Blanchard 	ctl_len = msg_sys->msg_controllen;
20291da177e4SLinus Torvalds 	if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
203089bddce5SStephen Hemminger 		err =
2031228e548eSAnton Blanchard 		    cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl,
203289bddce5SStephen Hemminger 						     sizeof(ctl));
20331da177e4SLinus Torvalds 		if (err)
20341da177e4SLinus Torvalds 			goto out_freeiov;
2035228e548eSAnton Blanchard 		ctl_buf = msg_sys->msg_control;
2036228e548eSAnton Blanchard 		ctl_len = msg_sys->msg_controllen;
20371da177e4SLinus Torvalds 	} else if (ctl_len) {
203889bddce5SStephen Hemminger 		if (ctl_len > sizeof(ctl)) {
20391da177e4SLinus Torvalds 			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
20401da177e4SLinus Torvalds 			if (ctl_buf == NULL)
20411da177e4SLinus Torvalds 				goto out_freeiov;
20421da177e4SLinus Torvalds 		}
20431da177e4SLinus Torvalds 		err = -EFAULT;
20441da177e4SLinus Torvalds 		/*
2045228e548eSAnton Blanchard 		 * Careful! Before this, msg_sys->msg_control contains a user pointer.
20461da177e4SLinus Torvalds 		 * Afterwards, it will be a kernel pointer. Thus the compiler-assisted
20471da177e4SLinus Torvalds 		 * checking falls down on this.
20481da177e4SLinus Torvalds 		 */
2049fb8621bbSNamhyung Kim 		if (copy_from_user(ctl_buf,
2050228e548eSAnton Blanchard 				   (void __user __force *)msg_sys->msg_control,
205189bddce5SStephen Hemminger 				   ctl_len))
20521da177e4SLinus Torvalds 			goto out_freectl;
2053228e548eSAnton Blanchard 		msg_sys->msg_control = ctl_buf;
20541da177e4SLinus Torvalds 	}
2055228e548eSAnton Blanchard 	msg_sys->msg_flags = flags;
20561da177e4SLinus Torvalds 
20571da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
2058228e548eSAnton Blanchard 		msg_sys->msg_flags |= MSG_DONTWAIT;
2059c71d8ebeSTetsuo Handa 	/*
2060c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and current destination address is same as
2061c71d8ebeSTetsuo Handa 	 * previously succeeded address, omit asking LSM's decision.
2062c71d8ebeSTetsuo Handa 	 * used_address->name_len is initialized to UINT_MAX so that the first
2063c71d8ebeSTetsuo Handa 	 * destination address never matches.
2064c71d8ebeSTetsuo Handa 	 */
2065bc909d9dSMathieu Desnoyers 	if (used_address && msg_sys->msg_name &&
2066bc909d9dSMathieu Desnoyers 	    used_address->name_len == msg_sys->msg_namelen &&
2067bc909d9dSMathieu Desnoyers 	    !memcmp(&used_address->name, msg_sys->msg_name,
2068c71d8ebeSTetsuo Handa 		    used_address->name_len)) {
2069c71d8ebeSTetsuo Handa 		err = sock_sendmsg_nosec(sock, msg_sys, total_len);
2070c71d8ebeSTetsuo Handa 		goto out_freectl;
2071c71d8ebeSTetsuo Handa 	}
2072c71d8ebeSTetsuo Handa 	err = sock_sendmsg(sock, msg_sys, total_len);
2073c71d8ebeSTetsuo Handa 	/*
2074c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and sending to current destination address was
2075c71d8ebeSTetsuo Handa 	 * successful, remember it.
2076c71d8ebeSTetsuo Handa 	 */
2077c71d8ebeSTetsuo Handa 	if (used_address && err >= 0) {
2078c71d8ebeSTetsuo Handa 		used_address->name_len = msg_sys->msg_namelen;
2079bc909d9dSMathieu Desnoyers 		if (msg_sys->msg_name)
2080bc909d9dSMathieu Desnoyers 			memcpy(&used_address->name, msg_sys->msg_name,
2081c71d8ebeSTetsuo Handa 			       used_address->name_len);
2082c71d8ebeSTetsuo Handa 	}
20831da177e4SLinus Torvalds 
20841da177e4SLinus Torvalds out_freectl:
20851da177e4SLinus Torvalds 	if (ctl_buf != ctl)
20861da177e4SLinus Torvalds 		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
20871da177e4SLinus Torvalds out_freeiov:
20881da177e4SLinus Torvalds 	if (iov != iovstack)
2089a74e9106SEric Dumazet 		kfree(iov);
2090228e548eSAnton Blanchard out:
2091228e548eSAnton Blanchard 	return err;
2092228e548eSAnton Blanchard }
2093228e548eSAnton Blanchard 
2094228e548eSAnton Blanchard /*
2095228e548eSAnton Blanchard  *	BSD sendmsg interface
2096228e548eSAnton Blanchard  */
2097228e548eSAnton Blanchard 
2098a7526eb5SAndy Lutomirski long __sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
2099228e548eSAnton Blanchard {
2100228e548eSAnton Blanchard 	int fput_needed, err;
2101228e548eSAnton Blanchard 	struct msghdr msg_sys;
21021be374a0SAndy Lutomirski 	struct socket *sock;
2103228e548eSAnton Blanchard 
21041be374a0SAndy Lutomirski 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2105228e548eSAnton Blanchard 	if (!sock)
2106228e548eSAnton Blanchard 		goto out;
2107228e548eSAnton Blanchard 
2108a7526eb5SAndy Lutomirski 	err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL);
2109228e548eSAnton Blanchard 
21106cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
21111da177e4SLinus Torvalds out:
21121da177e4SLinus Torvalds 	return err;
21131da177e4SLinus Torvalds }
21141da177e4SLinus Torvalds 
2115a7526eb5SAndy Lutomirski SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned int, flags)
2116a7526eb5SAndy Lutomirski {
2117a7526eb5SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
2118a7526eb5SAndy Lutomirski 		return -EINVAL;
2119a7526eb5SAndy Lutomirski 	return __sys_sendmsg(fd, msg, flags);
2120a7526eb5SAndy Lutomirski }
2121a7526eb5SAndy Lutomirski 
2122228e548eSAnton Blanchard /*
2123228e548eSAnton Blanchard  *	Linux sendmmsg interface
2124228e548eSAnton Blanchard  */
2125228e548eSAnton Blanchard 
2126228e548eSAnton Blanchard int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2127228e548eSAnton Blanchard 		   unsigned int flags)
2128228e548eSAnton Blanchard {
2129228e548eSAnton Blanchard 	int fput_needed, err, datagrams;
2130228e548eSAnton Blanchard 	struct socket *sock;
2131228e548eSAnton Blanchard 	struct mmsghdr __user *entry;
2132228e548eSAnton Blanchard 	struct compat_mmsghdr __user *compat_entry;
2133228e548eSAnton Blanchard 	struct msghdr msg_sys;
2134c71d8ebeSTetsuo Handa 	struct used_address used_address;
2135228e548eSAnton Blanchard 
213698382f41SAnton Blanchard 	if (vlen > UIO_MAXIOV)
213798382f41SAnton Blanchard 		vlen = UIO_MAXIOV;
2138228e548eSAnton Blanchard 
2139228e548eSAnton Blanchard 	datagrams = 0;
2140228e548eSAnton Blanchard 
2141228e548eSAnton Blanchard 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2142228e548eSAnton Blanchard 	if (!sock)
2143228e548eSAnton Blanchard 		return err;
2144228e548eSAnton Blanchard 
2145c71d8ebeSTetsuo Handa 	used_address.name_len = UINT_MAX;
2146228e548eSAnton Blanchard 	entry = mmsg;
2147228e548eSAnton Blanchard 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2148728ffb86SAnton Blanchard 	err = 0;
2149228e548eSAnton Blanchard 
2150228e548eSAnton Blanchard 	while (datagrams < vlen) {
2151228e548eSAnton Blanchard 		if (MSG_CMSG_COMPAT & flags) {
2152a7526eb5SAndy Lutomirski 			err = ___sys_sendmsg(sock, (struct msghdr __user *)compat_entry,
2153c71d8ebeSTetsuo Handa 					     &msg_sys, flags, &used_address);
2154228e548eSAnton Blanchard 			if (err < 0)
2155228e548eSAnton Blanchard 				break;
2156228e548eSAnton Blanchard 			err = __put_user(err, &compat_entry->msg_len);
2157228e548eSAnton Blanchard 			++compat_entry;
2158228e548eSAnton Blanchard 		} else {
2159a7526eb5SAndy Lutomirski 			err = ___sys_sendmsg(sock,
2160a7526eb5SAndy Lutomirski 					     (struct msghdr __user *)entry,
2161c71d8ebeSTetsuo Handa 					     &msg_sys, flags, &used_address);
2162228e548eSAnton Blanchard 			if (err < 0)
2163228e548eSAnton Blanchard 				break;
2164228e548eSAnton Blanchard 			err = put_user(err, &entry->msg_len);
2165228e548eSAnton Blanchard 			++entry;
2166228e548eSAnton Blanchard 		}
2167228e548eSAnton Blanchard 
2168228e548eSAnton Blanchard 		if (err)
2169228e548eSAnton Blanchard 			break;
2170228e548eSAnton Blanchard 		++datagrams;
2171228e548eSAnton Blanchard 	}
2172228e548eSAnton Blanchard 
2173228e548eSAnton Blanchard 	fput_light(sock->file, fput_needed);
2174228e548eSAnton Blanchard 
2175728ffb86SAnton Blanchard 	/* We only return an error if no datagrams were able to be sent */
2176728ffb86SAnton Blanchard 	if (datagrams != 0)
2177228e548eSAnton Blanchard 		return datagrams;
2178228e548eSAnton Blanchard 
2179228e548eSAnton Blanchard 	return err;
2180228e548eSAnton Blanchard }
2181228e548eSAnton Blanchard 
2182228e548eSAnton Blanchard SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
2183228e548eSAnton Blanchard 		unsigned int, vlen, unsigned int, flags)
2184228e548eSAnton Blanchard {
21851be374a0SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
21861be374a0SAndy Lutomirski 		return -EINVAL;
2187228e548eSAnton Blanchard 	return __sys_sendmmsg(fd, mmsg, vlen, flags);
2188228e548eSAnton Blanchard }
2189228e548eSAnton Blanchard 
2190a7526eb5SAndy Lutomirski static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
219195c96174SEric Dumazet 			 struct msghdr *msg_sys, unsigned int flags, int nosec)
21921da177e4SLinus Torvalds {
219389bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
219489bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
21951da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV];
21961da177e4SLinus Torvalds 	struct iovec *iov = iovstack;
21971da177e4SLinus Torvalds 	unsigned long cmsg_ptr;
2198a74e9106SEric Dumazet 	int err, total_len, len;
21991da177e4SLinus Torvalds 
22001da177e4SLinus Torvalds 	/* kernel mode address */
2201230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage addr;
22021da177e4SLinus Torvalds 
22031da177e4SLinus Torvalds 	/* user mode address pointers */
22041da177e4SLinus Torvalds 	struct sockaddr __user *uaddr;
22051da177e4SLinus Torvalds 	int __user *uaddr_len;
22061da177e4SLinus Torvalds 
22071da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags) {
2208a2e27255SArnaldo Carvalho de Melo 		if (get_compat_msghdr(msg_sys, msg_compat))
22091da177e4SLinus Torvalds 			return -EFAULT;
22101661bf36SDan Carpenter 	} else {
22111661bf36SDan Carpenter 		err = copy_msghdr_from_user(msg_sys, msg);
22121661bf36SDan Carpenter 		if (err)
22131661bf36SDan Carpenter 			return err;
22141661bf36SDan Carpenter 	}
22151da177e4SLinus Torvalds 
2216a74e9106SEric Dumazet 	if (msg_sys->msg_iovlen > UIO_FASTIOV) {
22171da177e4SLinus Torvalds 		err = -EMSGSIZE;
2218a2e27255SArnaldo Carvalho de Melo 		if (msg_sys->msg_iovlen > UIO_MAXIOV)
2219a2e27255SArnaldo Carvalho de Melo 			goto out;
22201da177e4SLinus Torvalds 		err = -ENOMEM;
2221a74e9106SEric Dumazet 		iov = kmalloc(msg_sys->msg_iovlen * sizeof(struct iovec),
2222a74e9106SEric Dumazet 			      GFP_KERNEL);
22231da177e4SLinus Torvalds 		if (!iov)
2224a2e27255SArnaldo Carvalho de Melo 			goto out;
22251da177e4SLinus Torvalds 	}
22261da177e4SLinus Torvalds 
2227f3d33426SHannes Frederic Sowa 	/* Save the user-mode address (verify_iovec will change the
22281da177e4SLinus Torvalds 	 * kernel msghdr to use the kernel address space)
22291da177e4SLinus Torvalds 	 */
2230a2e27255SArnaldo Carvalho de Melo 	uaddr = (__force void __user *)msg_sys->msg_name;
22311da177e4SLinus Torvalds 	uaddr_len = COMPAT_NAMELEN(msg);
2232f3d33426SHannes Frederic Sowa 	if (MSG_CMSG_COMPAT & flags)
223343db362dSMaciej Żenczykowski 		err = verify_compat_iovec(msg_sys, iov, &addr, VERIFY_WRITE);
2234f3d33426SHannes Frederic Sowa 	else
223543db362dSMaciej Żenczykowski 		err = verify_iovec(msg_sys, iov, &addr, VERIFY_WRITE);
22361da177e4SLinus Torvalds 	if (err < 0)
22371da177e4SLinus Torvalds 		goto out_freeiov;
22381da177e4SLinus Torvalds 	total_len = err;
22391da177e4SLinus Torvalds 
2240a2e27255SArnaldo Carvalho de Melo 	cmsg_ptr = (unsigned long)msg_sys->msg_control;
2241a2e27255SArnaldo Carvalho de Melo 	msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
22421da177e4SLinus Torvalds 
2243f3d33426SHannes Frederic Sowa 	/* We assume all kernel code knows the size of sockaddr_storage */
2244f3d33426SHannes Frederic Sowa 	msg_sys->msg_namelen = 0;
2245f3d33426SHannes Frederic Sowa 
22461da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
22471da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
2248a2e27255SArnaldo Carvalho de Melo 	err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys,
2249a2e27255SArnaldo Carvalho de Melo 							  total_len, flags);
22501da177e4SLinus Torvalds 	if (err < 0)
22511da177e4SLinus Torvalds 		goto out_freeiov;
22521da177e4SLinus Torvalds 	len = err;
22531da177e4SLinus Torvalds 
22541da177e4SLinus Torvalds 	if (uaddr != NULL) {
225543db362dSMaciej Żenczykowski 		err = move_addr_to_user(&addr,
2256a2e27255SArnaldo Carvalho de Melo 					msg_sys->msg_namelen, uaddr,
225789bddce5SStephen Hemminger 					uaddr_len);
22581da177e4SLinus Torvalds 		if (err < 0)
22591da177e4SLinus Torvalds 			goto out_freeiov;
22601da177e4SLinus Torvalds 	}
2261a2e27255SArnaldo Carvalho de Melo 	err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
226237f7f421SDavid S. Miller 			 COMPAT_FLAGS(msg));
22631da177e4SLinus Torvalds 	if (err)
22641da177e4SLinus Torvalds 		goto out_freeiov;
22651da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags)
2266a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
22671da177e4SLinus Torvalds 				 &msg_compat->msg_controllen);
22681da177e4SLinus Torvalds 	else
2269a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
22701da177e4SLinus Torvalds 				 &msg->msg_controllen);
22711da177e4SLinus Torvalds 	if (err)
22721da177e4SLinus Torvalds 		goto out_freeiov;
22731da177e4SLinus Torvalds 	err = len;
22741da177e4SLinus Torvalds 
22751da177e4SLinus Torvalds out_freeiov:
22761da177e4SLinus Torvalds 	if (iov != iovstack)
2277a74e9106SEric Dumazet 		kfree(iov);
2278a2e27255SArnaldo Carvalho de Melo out:
2279a2e27255SArnaldo Carvalho de Melo 	return err;
2280a2e27255SArnaldo Carvalho de Melo }
2281a2e27255SArnaldo Carvalho de Melo 
2282a2e27255SArnaldo Carvalho de Melo /*
2283a2e27255SArnaldo Carvalho de Melo  *	BSD recvmsg interface
2284a2e27255SArnaldo Carvalho de Melo  */
2285a2e27255SArnaldo Carvalho de Melo 
2286a7526eb5SAndy Lutomirski long __sys_recvmsg(int fd, struct msghdr __user *msg, unsigned flags)
2287a2e27255SArnaldo Carvalho de Melo {
2288a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err;
2289a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
22901be374a0SAndy Lutomirski 	struct socket *sock;
2291a2e27255SArnaldo Carvalho de Melo 
22921be374a0SAndy Lutomirski 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2293a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2294a2e27255SArnaldo Carvalho de Melo 		goto out;
2295a2e27255SArnaldo Carvalho de Melo 
2296a7526eb5SAndy Lutomirski 	err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0);
2297a2e27255SArnaldo Carvalho de Melo 
22986cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
22991da177e4SLinus Torvalds out:
23001da177e4SLinus Torvalds 	return err;
23011da177e4SLinus Torvalds }
23021da177e4SLinus Torvalds 
2303a7526eb5SAndy Lutomirski SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg,
2304a7526eb5SAndy Lutomirski 		unsigned int, flags)
2305a7526eb5SAndy Lutomirski {
2306a7526eb5SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
2307a7526eb5SAndy Lutomirski 		return -EINVAL;
2308a7526eb5SAndy Lutomirski 	return __sys_recvmsg(fd, msg, flags);
2309a7526eb5SAndy Lutomirski }
2310a7526eb5SAndy Lutomirski 
2311a2e27255SArnaldo Carvalho de Melo /*
2312a2e27255SArnaldo Carvalho de Melo  *     Linux recvmmsg interface
2313a2e27255SArnaldo Carvalho de Melo  */
23141da177e4SLinus Torvalds 
2315a2e27255SArnaldo Carvalho de Melo int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2316a2e27255SArnaldo Carvalho de Melo 		   unsigned int flags, struct timespec *timeout)
2317a2e27255SArnaldo Carvalho de Melo {
2318a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err, datagrams;
2319a2e27255SArnaldo Carvalho de Melo 	struct socket *sock;
2320a2e27255SArnaldo Carvalho de Melo 	struct mmsghdr __user *entry;
2321d7256d0eSJean-Mickael Guerin 	struct compat_mmsghdr __user *compat_entry;
2322a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
2323a2e27255SArnaldo Carvalho de Melo 	struct timespec end_time;
2324a2e27255SArnaldo Carvalho de Melo 
2325a2e27255SArnaldo Carvalho de Melo 	if (timeout &&
2326a2e27255SArnaldo Carvalho de Melo 	    poll_select_set_timeout(&end_time, timeout->tv_sec,
2327a2e27255SArnaldo Carvalho de Melo 				    timeout->tv_nsec))
2328a2e27255SArnaldo Carvalho de Melo 		return -EINVAL;
2329a2e27255SArnaldo Carvalho de Melo 
2330a2e27255SArnaldo Carvalho de Melo 	datagrams = 0;
2331a2e27255SArnaldo Carvalho de Melo 
2332a2e27255SArnaldo Carvalho de Melo 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2333a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2334a2e27255SArnaldo Carvalho de Melo 		return err;
2335a2e27255SArnaldo Carvalho de Melo 
2336a2e27255SArnaldo Carvalho de Melo 	err = sock_error(sock->sk);
2337a2e27255SArnaldo Carvalho de Melo 	if (err)
2338a2e27255SArnaldo Carvalho de Melo 		goto out_put;
2339a2e27255SArnaldo Carvalho de Melo 
2340a2e27255SArnaldo Carvalho de Melo 	entry = mmsg;
2341d7256d0eSJean-Mickael Guerin 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2342a2e27255SArnaldo Carvalho de Melo 
2343a2e27255SArnaldo Carvalho de Melo 	while (datagrams < vlen) {
2344a2e27255SArnaldo Carvalho de Melo 		/*
2345a2e27255SArnaldo Carvalho de Melo 		 * No need to ask LSM for more than the first datagram.
2346a2e27255SArnaldo Carvalho de Melo 		 */
2347d7256d0eSJean-Mickael Guerin 		if (MSG_CMSG_COMPAT & flags) {
2348a7526eb5SAndy Lutomirski 			err = ___sys_recvmsg(sock, (struct msghdr __user *)compat_entry,
2349b9eb8b87SAnton Blanchard 					     &msg_sys, flags & ~MSG_WAITFORONE,
2350b9eb8b87SAnton Blanchard 					     datagrams);
2351d7256d0eSJean-Mickael Guerin 			if (err < 0)
2352d7256d0eSJean-Mickael Guerin 				break;
2353d7256d0eSJean-Mickael Guerin 			err = __put_user(err, &compat_entry->msg_len);
2354d7256d0eSJean-Mickael Guerin 			++compat_entry;
2355d7256d0eSJean-Mickael Guerin 		} else {
2356a7526eb5SAndy Lutomirski 			err = ___sys_recvmsg(sock,
2357a7526eb5SAndy Lutomirski 					     (struct msghdr __user *)entry,
2358b9eb8b87SAnton Blanchard 					     &msg_sys, flags & ~MSG_WAITFORONE,
2359b9eb8b87SAnton Blanchard 					     datagrams);
2360a2e27255SArnaldo Carvalho de Melo 			if (err < 0)
2361a2e27255SArnaldo Carvalho de Melo 				break;
2362a2e27255SArnaldo Carvalho de Melo 			err = put_user(err, &entry->msg_len);
2363d7256d0eSJean-Mickael Guerin 			++entry;
2364d7256d0eSJean-Mickael Guerin 		}
2365d7256d0eSJean-Mickael Guerin 
2366a2e27255SArnaldo Carvalho de Melo 		if (err)
2367a2e27255SArnaldo Carvalho de Melo 			break;
2368a2e27255SArnaldo Carvalho de Melo 		++datagrams;
2369a2e27255SArnaldo Carvalho de Melo 
237071c5c159SBrandon L Black 		/* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
237171c5c159SBrandon L Black 		if (flags & MSG_WAITFORONE)
237271c5c159SBrandon L Black 			flags |= MSG_DONTWAIT;
237371c5c159SBrandon L Black 
2374a2e27255SArnaldo Carvalho de Melo 		if (timeout) {
2375a2e27255SArnaldo Carvalho de Melo 			ktime_get_ts(timeout);
2376a2e27255SArnaldo Carvalho de Melo 			*timeout = timespec_sub(end_time, *timeout);
2377a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_sec < 0) {
2378a2e27255SArnaldo Carvalho de Melo 				timeout->tv_sec = timeout->tv_nsec = 0;
2379a2e27255SArnaldo Carvalho de Melo 				break;
2380a2e27255SArnaldo Carvalho de Melo 			}
2381a2e27255SArnaldo Carvalho de Melo 
2382a2e27255SArnaldo Carvalho de Melo 			/* Timeout, return less than vlen datagrams */
2383a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_nsec == 0 && timeout->tv_sec == 0)
2384a2e27255SArnaldo Carvalho de Melo 				break;
2385a2e27255SArnaldo Carvalho de Melo 		}
2386a2e27255SArnaldo Carvalho de Melo 
2387a2e27255SArnaldo Carvalho de Melo 		/* Out of band data, return right away */
2388a2e27255SArnaldo Carvalho de Melo 		if (msg_sys.msg_flags & MSG_OOB)
2389a2e27255SArnaldo Carvalho de Melo 			break;
2390a2e27255SArnaldo Carvalho de Melo 	}
2391a2e27255SArnaldo Carvalho de Melo 
2392a2e27255SArnaldo Carvalho de Melo out_put:
2393a2e27255SArnaldo Carvalho de Melo 	fput_light(sock->file, fput_needed);
2394a2e27255SArnaldo Carvalho de Melo 
2395a2e27255SArnaldo Carvalho de Melo 	if (err == 0)
2396a2e27255SArnaldo Carvalho de Melo 		return datagrams;
2397a2e27255SArnaldo Carvalho de Melo 
2398a2e27255SArnaldo Carvalho de Melo 	if (datagrams != 0) {
2399a2e27255SArnaldo Carvalho de Melo 		/*
2400a2e27255SArnaldo Carvalho de Melo 		 * We may return less entries than requested (vlen) if the
2401a2e27255SArnaldo Carvalho de Melo 		 * sock is non block and there aren't enough datagrams...
2402a2e27255SArnaldo Carvalho de Melo 		 */
2403a2e27255SArnaldo Carvalho de Melo 		if (err != -EAGAIN) {
2404a2e27255SArnaldo Carvalho de Melo 			/*
2405a2e27255SArnaldo Carvalho de Melo 			 * ... or  if recvmsg returns an error after we
2406a2e27255SArnaldo Carvalho de Melo 			 * received some datagrams, where we record the
2407a2e27255SArnaldo Carvalho de Melo 			 * error to return on the next call or if the
2408a2e27255SArnaldo Carvalho de Melo 			 * app asks about it using getsockopt(SO_ERROR).
2409a2e27255SArnaldo Carvalho de Melo 			 */
2410a2e27255SArnaldo Carvalho de Melo 			sock->sk->sk_err = -err;
2411a2e27255SArnaldo Carvalho de Melo 		}
2412a2e27255SArnaldo Carvalho de Melo 
2413a2e27255SArnaldo Carvalho de Melo 		return datagrams;
2414a2e27255SArnaldo Carvalho de Melo 	}
2415a2e27255SArnaldo Carvalho de Melo 
2416a2e27255SArnaldo Carvalho de Melo 	return err;
2417a2e27255SArnaldo Carvalho de Melo }
2418a2e27255SArnaldo Carvalho de Melo 
2419a2e27255SArnaldo Carvalho de Melo SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
2420a2e27255SArnaldo Carvalho de Melo 		unsigned int, vlen, unsigned int, flags,
2421a2e27255SArnaldo Carvalho de Melo 		struct timespec __user *, timeout)
2422a2e27255SArnaldo Carvalho de Melo {
2423a2e27255SArnaldo Carvalho de Melo 	int datagrams;
2424a2e27255SArnaldo Carvalho de Melo 	struct timespec timeout_sys;
2425a2e27255SArnaldo Carvalho de Melo 
24261be374a0SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
24271be374a0SAndy Lutomirski 		return -EINVAL;
24281be374a0SAndy Lutomirski 
2429a2e27255SArnaldo Carvalho de Melo 	if (!timeout)
2430a2e27255SArnaldo Carvalho de Melo 		return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL);
2431a2e27255SArnaldo Carvalho de Melo 
2432a2e27255SArnaldo Carvalho de Melo 	if (copy_from_user(&timeout_sys, timeout, sizeof(timeout_sys)))
2433a2e27255SArnaldo Carvalho de Melo 		return -EFAULT;
2434a2e27255SArnaldo Carvalho de Melo 
2435a2e27255SArnaldo Carvalho de Melo 	datagrams = __sys_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys);
2436a2e27255SArnaldo Carvalho de Melo 
2437a2e27255SArnaldo Carvalho de Melo 	if (datagrams > 0 &&
2438a2e27255SArnaldo Carvalho de Melo 	    copy_to_user(timeout, &timeout_sys, sizeof(timeout_sys)))
2439a2e27255SArnaldo Carvalho de Melo 		datagrams = -EFAULT;
2440a2e27255SArnaldo Carvalho de Melo 
2441a2e27255SArnaldo Carvalho de Melo 	return datagrams;
2442a2e27255SArnaldo Carvalho de Melo }
2443a2e27255SArnaldo Carvalho de Melo 
2444a2e27255SArnaldo Carvalho de Melo #ifdef __ARCH_WANT_SYS_SOCKETCALL
24451da177e4SLinus Torvalds /* Argument list sizes for sys_socketcall */
24461da177e4SLinus Torvalds #define AL(x) ((x) * sizeof(unsigned long))
2447228e548eSAnton Blanchard static const unsigned char nargs[21] = {
244889bddce5SStephen Hemminger 	AL(0), AL(3), AL(3), AL(3), AL(2), AL(3),
24491da177e4SLinus Torvalds 	AL(3), AL(3), AL(4), AL(4), AL(4), AL(6),
2450aaca0bdcSUlrich Drepper 	AL(6), AL(2), AL(5), AL(5), AL(3), AL(3),
2451228e548eSAnton Blanchard 	AL(4), AL(5), AL(4)
245289bddce5SStephen Hemminger };
245389bddce5SStephen Hemminger 
24541da177e4SLinus Torvalds #undef AL
24551da177e4SLinus Torvalds 
24561da177e4SLinus Torvalds /*
24571da177e4SLinus Torvalds  *	System call vectors.
24581da177e4SLinus Torvalds  *
24591da177e4SLinus Torvalds  *	Argument checking cleaned up. Saved 20% in size.
24601da177e4SLinus Torvalds  *  This function doesn't need to set the kernel lock because
24611da177e4SLinus Torvalds  *  it is set by the callees.
24621da177e4SLinus Torvalds  */
24631da177e4SLinus Torvalds 
24643e0fa65fSHeiko Carstens SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
24651da177e4SLinus Torvalds {
24662950fa9dSChen Gang 	unsigned long a[AUDITSC_ARGS];
24671da177e4SLinus Torvalds 	unsigned long a0, a1;
24681da177e4SLinus Torvalds 	int err;
246947379052SArjan van de Ven 	unsigned int len;
24701da177e4SLinus Torvalds 
2471228e548eSAnton Blanchard 	if (call < 1 || call > SYS_SENDMMSG)
24721da177e4SLinus Torvalds 		return -EINVAL;
24731da177e4SLinus Torvalds 
247447379052SArjan van de Ven 	len = nargs[call];
247547379052SArjan van de Ven 	if (len > sizeof(a))
247647379052SArjan van de Ven 		return -EINVAL;
247747379052SArjan van de Ven 
24781da177e4SLinus Torvalds 	/* copy_from_user should be SMP safe. */
247947379052SArjan van de Ven 	if (copy_from_user(a, args, len))
24801da177e4SLinus Torvalds 		return -EFAULT;
24811da177e4SLinus Torvalds 
24822950fa9dSChen Gang 	err = audit_socketcall(nargs[call] / sizeof(unsigned long), a);
24832950fa9dSChen Gang 	if (err)
24842950fa9dSChen Gang 		return err;
24853ec3b2fbSDavid Woodhouse 
24861da177e4SLinus Torvalds 	a0 = a[0];
24871da177e4SLinus Torvalds 	a1 = a[1];
24881da177e4SLinus Torvalds 
248989bddce5SStephen Hemminger 	switch (call) {
24901da177e4SLinus Torvalds 	case SYS_SOCKET:
24911da177e4SLinus Torvalds 		err = sys_socket(a0, a1, a[2]);
24921da177e4SLinus Torvalds 		break;
24931da177e4SLinus Torvalds 	case SYS_BIND:
24941da177e4SLinus Torvalds 		err = sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
24951da177e4SLinus Torvalds 		break;
24961da177e4SLinus Torvalds 	case SYS_CONNECT:
24971da177e4SLinus Torvalds 		err = sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
24981da177e4SLinus Torvalds 		break;
24991da177e4SLinus Torvalds 	case SYS_LISTEN:
25001da177e4SLinus Torvalds 		err = sys_listen(a0, a1);
25011da177e4SLinus Torvalds 		break;
25021da177e4SLinus Torvalds 	case SYS_ACCEPT:
2503de11defeSUlrich Drepper 		err = sys_accept4(a0, (struct sockaddr __user *)a1,
2504aaca0bdcSUlrich Drepper 				  (int __user *)a[2], 0);
25051da177e4SLinus Torvalds 		break;
25061da177e4SLinus Torvalds 	case SYS_GETSOCKNAME:
250789bddce5SStephen Hemminger 		err =
250889bddce5SStephen Hemminger 		    sys_getsockname(a0, (struct sockaddr __user *)a1,
250989bddce5SStephen Hemminger 				    (int __user *)a[2]);
25101da177e4SLinus Torvalds 		break;
25111da177e4SLinus Torvalds 	case SYS_GETPEERNAME:
251289bddce5SStephen Hemminger 		err =
251389bddce5SStephen Hemminger 		    sys_getpeername(a0, (struct sockaddr __user *)a1,
251489bddce5SStephen Hemminger 				    (int __user *)a[2]);
25151da177e4SLinus Torvalds 		break;
25161da177e4SLinus Torvalds 	case SYS_SOCKETPAIR:
25171da177e4SLinus Torvalds 		err = sys_socketpair(a0, a1, a[2], (int __user *)a[3]);
25181da177e4SLinus Torvalds 		break;
25191da177e4SLinus Torvalds 	case SYS_SEND:
25201da177e4SLinus Torvalds 		err = sys_send(a0, (void __user *)a1, a[2], a[3]);
25211da177e4SLinus Torvalds 		break;
25221da177e4SLinus Torvalds 	case SYS_SENDTO:
25231da177e4SLinus Torvalds 		err = sys_sendto(a0, (void __user *)a1, a[2], a[3],
25241da177e4SLinus Torvalds 				 (struct sockaddr __user *)a[4], a[5]);
25251da177e4SLinus Torvalds 		break;
25261da177e4SLinus Torvalds 	case SYS_RECV:
25271da177e4SLinus Torvalds 		err = sys_recv(a0, (void __user *)a1, a[2], a[3]);
25281da177e4SLinus Torvalds 		break;
25291da177e4SLinus Torvalds 	case SYS_RECVFROM:
25301da177e4SLinus Torvalds 		err = sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
253189bddce5SStephen Hemminger 				   (struct sockaddr __user *)a[4],
253289bddce5SStephen Hemminger 				   (int __user *)a[5]);
25331da177e4SLinus Torvalds 		break;
25341da177e4SLinus Torvalds 	case SYS_SHUTDOWN:
25351da177e4SLinus Torvalds 		err = sys_shutdown(a0, a1);
25361da177e4SLinus Torvalds 		break;
25371da177e4SLinus Torvalds 	case SYS_SETSOCKOPT:
25381da177e4SLinus Torvalds 		err = sys_setsockopt(a0, a1, a[2], (char __user *)a[3], a[4]);
25391da177e4SLinus Torvalds 		break;
25401da177e4SLinus Torvalds 	case SYS_GETSOCKOPT:
254189bddce5SStephen Hemminger 		err =
254289bddce5SStephen Hemminger 		    sys_getsockopt(a0, a1, a[2], (char __user *)a[3],
254389bddce5SStephen Hemminger 				   (int __user *)a[4]);
25441da177e4SLinus Torvalds 		break;
25451da177e4SLinus Torvalds 	case SYS_SENDMSG:
25461da177e4SLinus Torvalds 		err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]);
25471da177e4SLinus Torvalds 		break;
2548228e548eSAnton Blanchard 	case SYS_SENDMMSG:
2549228e548eSAnton Blanchard 		err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]);
2550228e548eSAnton Blanchard 		break;
25511da177e4SLinus Torvalds 	case SYS_RECVMSG:
25521da177e4SLinus Torvalds 		err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]);
25531da177e4SLinus Torvalds 		break;
2554a2e27255SArnaldo Carvalho de Melo 	case SYS_RECVMMSG:
2555a2e27255SArnaldo Carvalho de Melo 		err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3],
2556a2e27255SArnaldo Carvalho de Melo 				   (struct timespec __user *)a[4]);
2557a2e27255SArnaldo Carvalho de Melo 		break;
2558de11defeSUlrich Drepper 	case SYS_ACCEPT4:
2559de11defeSUlrich Drepper 		err = sys_accept4(a0, (struct sockaddr __user *)a1,
2560de11defeSUlrich Drepper 				  (int __user *)a[2], a[3]);
2561aaca0bdcSUlrich Drepper 		break;
25621da177e4SLinus Torvalds 	default:
25631da177e4SLinus Torvalds 		err = -EINVAL;
25641da177e4SLinus Torvalds 		break;
25651da177e4SLinus Torvalds 	}
25661da177e4SLinus Torvalds 	return err;
25671da177e4SLinus Torvalds }
25681da177e4SLinus Torvalds 
25691da177e4SLinus Torvalds #endif				/* __ARCH_WANT_SYS_SOCKETCALL */
25701da177e4SLinus Torvalds 
257155737fdaSStephen Hemminger /**
257255737fdaSStephen Hemminger  *	sock_register - add a socket protocol handler
257355737fdaSStephen Hemminger  *	@ops: description of protocol
257455737fdaSStephen Hemminger  *
25751da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
25761da177e4SLinus Torvalds  *	advertise its address family, and have it linked into the
257755737fdaSStephen Hemminger  *	socket interface. The value ops->family coresponds to the
257855737fdaSStephen Hemminger  *	socket system call protocol family.
25791da177e4SLinus Torvalds  */
2580f0fd27d4SStephen Hemminger int sock_register(const struct net_proto_family *ops)
25811da177e4SLinus Torvalds {
25821da177e4SLinus Torvalds 	int err;
25831da177e4SLinus Torvalds 
25841da177e4SLinus Torvalds 	if (ops->family >= NPROTO) {
258589bddce5SStephen Hemminger 		printk(KERN_CRIT "protocol %d >= NPROTO(%d)\n", ops->family,
258689bddce5SStephen Hemminger 		       NPROTO);
25871da177e4SLinus Torvalds 		return -ENOBUFS;
25881da177e4SLinus Torvalds 	}
258955737fdaSStephen Hemminger 
259055737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2591190683a9SEric Dumazet 	if (rcu_dereference_protected(net_families[ops->family],
2592190683a9SEric Dumazet 				      lockdep_is_held(&net_family_lock)))
25931da177e4SLinus Torvalds 		err = -EEXIST;
259455737fdaSStephen Hemminger 	else {
2595cf778b00SEric Dumazet 		rcu_assign_pointer(net_families[ops->family], ops);
25961da177e4SLinus Torvalds 		err = 0;
25971da177e4SLinus Torvalds 	}
259855737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
259955737fdaSStephen Hemminger 
260089bddce5SStephen Hemminger 	printk(KERN_INFO "NET: Registered protocol family %d\n", ops->family);
26011da177e4SLinus Torvalds 	return err;
26021da177e4SLinus Torvalds }
2603c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_register);
26041da177e4SLinus Torvalds 
260555737fdaSStephen Hemminger /**
260655737fdaSStephen Hemminger  *	sock_unregister - remove a protocol handler
260755737fdaSStephen Hemminger  *	@family: protocol family to remove
260855737fdaSStephen Hemminger  *
26091da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
26101da177e4SLinus Torvalds  *	remove its address family, and have it unlinked from the
261155737fdaSStephen Hemminger  *	new socket creation.
261255737fdaSStephen Hemminger  *
261355737fdaSStephen Hemminger  *	If protocol handler is a module, then it can use module reference
261455737fdaSStephen Hemminger  *	counts to protect against new references. If protocol handler is not
261555737fdaSStephen Hemminger  *	a module then it needs to provide its own protection in
261655737fdaSStephen Hemminger  *	the ops->create routine.
26171da177e4SLinus Torvalds  */
2618f0fd27d4SStephen Hemminger void sock_unregister(int family)
26191da177e4SLinus Torvalds {
2620f0fd27d4SStephen Hemminger 	BUG_ON(family < 0 || family >= NPROTO);
26211da177e4SLinus Torvalds 
262255737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2623a9b3cd7fSStephen Hemminger 	RCU_INIT_POINTER(net_families[family], NULL);
262455737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
262555737fdaSStephen Hemminger 
262655737fdaSStephen Hemminger 	synchronize_rcu();
262755737fdaSStephen Hemminger 
262889bddce5SStephen Hemminger 	printk(KERN_INFO "NET: Unregistered protocol family %d\n", family);
26291da177e4SLinus Torvalds }
2630c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_unregister);
26311da177e4SLinus Torvalds 
263277d76ea3SAndi Kleen static int __init sock_init(void)
26331da177e4SLinus Torvalds {
2634b3e19d92SNick Piggin 	int err;
26352ca794e5SEric W. Biederman 	/*
26362ca794e5SEric W. Biederman 	 *      Initialize the network sysctl infrastructure.
26372ca794e5SEric W. Biederman 	 */
26382ca794e5SEric W. Biederman 	err = net_sysctl_init();
26392ca794e5SEric W. Biederman 	if (err)
26402ca794e5SEric W. Biederman 		goto out;
2641b3e19d92SNick Piggin 
26421da177e4SLinus Torvalds 	/*
26431da177e4SLinus Torvalds 	 *      Initialize skbuff SLAB cache
26441da177e4SLinus Torvalds 	 */
26451da177e4SLinus Torvalds 	skb_init();
26461da177e4SLinus Torvalds 
26471da177e4SLinus Torvalds 	/*
26481da177e4SLinus Torvalds 	 *      Initialize the protocols module.
26491da177e4SLinus Torvalds 	 */
26501da177e4SLinus Torvalds 
26511da177e4SLinus Torvalds 	init_inodecache();
2652b3e19d92SNick Piggin 
2653b3e19d92SNick Piggin 	err = register_filesystem(&sock_fs_type);
2654b3e19d92SNick Piggin 	if (err)
2655b3e19d92SNick Piggin 		goto out_fs;
26561da177e4SLinus Torvalds 	sock_mnt = kern_mount(&sock_fs_type);
2657b3e19d92SNick Piggin 	if (IS_ERR(sock_mnt)) {
2658b3e19d92SNick Piggin 		err = PTR_ERR(sock_mnt);
2659b3e19d92SNick Piggin 		goto out_mount;
2660b3e19d92SNick Piggin 	}
266177d76ea3SAndi Kleen 
266277d76ea3SAndi Kleen 	/* The real protocol initialization is performed in later initcalls.
26631da177e4SLinus Torvalds 	 */
26641da177e4SLinus Torvalds 
26651da177e4SLinus Torvalds #ifdef CONFIG_NETFILTER
26666d11cfdbSPablo Neira Ayuso 	err = netfilter_init();
26676d11cfdbSPablo Neira Ayuso 	if (err)
26686d11cfdbSPablo Neira Ayuso 		goto out;
26691da177e4SLinus Torvalds #endif
2670cbeb321aSDavid S. Miller 
2671c1f19b51SRichard Cochran #ifdef CONFIG_NETWORK_PHY_TIMESTAMPING
2672c1f19b51SRichard Cochran 	skb_timestamping_init();
2673c1f19b51SRichard Cochran #endif
2674c1f19b51SRichard Cochran 
2675b3e19d92SNick Piggin out:
2676b3e19d92SNick Piggin 	return err;
2677b3e19d92SNick Piggin 
2678b3e19d92SNick Piggin out_mount:
2679b3e19d92SNick Piggin 	unregister_filesystem(&sock_fs_type);
2680b3e19d92SNick Piggin out_fs:
2681b3e19d92SNick Piggin 	goto out;
26821da177e4SLinus Torvalds }
26831da177e4SLinus Torvalds 
268477d76ea3SAndi Kleen core_initcall(sock_init);	/* early initcall */
268577d76ea3SAndi Kleen 
26861da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS
26871da177e4SLinus Torvalds void socket_seq_show(struct seq_file *seq)
26881da177e4SLinus Torvalds {
26891da177e4SLinus Torvalds 	int cpu;
26901da177e4SLinus Torvalds 	int counter = 0;
26911da177e4SLinus Torvalds 
26926f912042SKAMEZAWA Hiroyuki 	for_each_possible_cpu(cpu)
26931da177e4SLinus Torvalds 	    counter += per_cpu(sockets_in_use, cpu);
26941da177e4SLinus Torvalds 
26951da177e4SLinus Torvalds 	/* It can be negative, by the way. 8) */
26961da177e4SLinus Torvalds 	if (counter < 0)
26971da177e4SLinus Torvalds 		counter = 0;
26981da177e4SLinus Torvalds 
26991da177e4SLinus Torvalds 	seq_printf(seq, "sockets: used %d\n", counter);
27001da177e4SLinus Torvalds }
27011da177e4SLinus Torvalds #endif				/* CONFIG_PROC_FS */
27021da177e4SLinus Torvalds 
270389bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
27046b96018bSArnd Bergmann static int do_siocgstamp(struct net *net, struct socket *sock,
2705644595f8SH. Peter Anvin 			 unsigned int cmd, void __user *up)
27067a229387SArnd Bergmann {
27077a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
27087a229387SArnd Bergmann 	struct timeval ktv;
27097a229387SArnd Bergmann 	int err;
27107a229387SArnd Bergmann 
27117a229387SArnd Bergmann 	set_fs(KERNEL_DS);
27126b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv);
27137a229387SArnd Bergmann 	set_fs(old_fs);
2714644595f8SH. Peter Anvin 	if (!err)
2715ed6fe9d6SMikulas Patocka 		err = compat_put_timeval(&ktv, up);
2716644595f8SH. Peter Anvin 
27177a229387SArnd Bergmann 	return err;
27187a229387SArnd Bergmann }
27197a229387SArnd Bergmann 
27206b96018bSArnd Bergmann static int do_siocgstampns(struct net *net, struct socket *sock,
2721644595f8SH. Peter Anvin 			   unsigned int cmd, void __user *up)
27227a229387SArnd Bergmann {
27237a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
27247a229387SArnd Bergmann 	struct timespec kts;
27257a229387SArnd Bergmann 	int err;
27267a229387SArnd Bergmann 
27277a229387SArnd Bergmann 	set_fs(KERNEL_DS);
27286b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts);
27297a229387SArnd Bergmann 	set_fs(old_fs);
2730644595f8SH. Peter Anvin 	if (!err)
2731ed6fe9d6SMikulas Patocka 		err = compat_put_timespec(&kts, up);
2732644595f8SH. Peter Anvin 
27337a229387SArnd Bergmann 	return err;
27347a229387SArnd Bergmann }
27357a229387SArnd Bergmann 
27366b96018bSArnd Bergmann static int dev_ifname32(struct net *net, struct compat_ifreq __user *uifr32)
27377a229387SArnd Bergmann {
27387a229387SArnd Bergmann 	struct ifreq __user *uifr;
27397a229387SArnd Bergmann 	int err;
27407a229387SArnd Bergmann 
27417a229387SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(struct ifreq));
27426b96018bSArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
27437a229387SArnd Bergmann 		return -EFAULT;
27447a229387SArnd Bergmann 
27456b96018bSArnd Bergmann 	err = dev_ioctl(net, SIOCGIFNAME, uifr);
27467a229387SArnd Bergmann 	if (err)
27477a229387SArnd Bergmann 		return err;
27487a229387SArnd Bergmann 
27496b96018bSArnd Bergmann 	if (copy_in_user(uifr32, uifr, sizeof(struct compat_ifreq)))
27507a229387SArnd Bergmann 		return -EFAULT;
27517a229387SArnd Bergmann 
27527a229387SArnd Bergmann 	return 0;
27537a229387SArnd Bergmann }
27547a229387SArnd Bergmann 
27556b96018bSArnd Bergmann static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32)
27567a229387SArnd Bergmann {
27576b96018bSArnd Bergmann 	struct compat_ifconf ifc32;
27587a229387SArnd Bergmann 	struct ifconf ifc;
27597a229387SArnd Bergmann 	struct ifconf __user *uifc;
27606b96018bSArnd Bergmann 	struct compat_ifreq __user *ifr32;
27617a229387SArnd Bergmann 	struct ifreq __user *ifr;
27627a229387SArnd Bergmann 	unsigned int i, j;
27637a229387SArnd Bergmann 	int err;
27647a229387SArnd Bergmann 
27656b96018bSArnd Bergmann 	if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf)))
27667a229387SArnd Bergmann 		return -EFAULT;
27677a229387SArnd Bergmann 
276843da5f2eSMathias Krause 	memset(&ifc, 0, sizeof(ifc));
27697a229387SArnd Bergmann 	if (ifc32.ifcbuf == 0) {
27707a229387SArnd Bergmann 		ifc32.ifc_len = 0;
27717a229387SArnd Bergmann 		ifc.ifc_len = 0;
27727a229387SArnd Bergmann 		ifc.ifc_req = NULL;
27737a229387SArnd Bergmann 		uifc = compat_alloc_user_space(sizeof(struct ifconf));
27747a229387SArnd Bergmann 	} else {
27756b96018bSArnd Bergmann 		size_t len = ((ifc32.ifc_len / sizeof(struct compat_ifreq)) + 1) *
27767a229387SArnd Bergmann 			sizeof(struct ifreq);
27777a229387SArnd Bergmann 		uifc = compat_alloc_user_space(sizeof(struct ifconf) + len);
27787a229387SArnd Bergmann 		ifc.ifc_len = len;
27797a229387SArnd Bergmann 		ifr = ifc.ifc_req = (void __user *)(uifc + 1);
27807a229387SArnd Bergmann 		ifr32 = compat_ptr(ifc32.ifcbuf);
27816b96018bSArnd Bergmann 		for (i = 0; i < ifc32.ifc_len; i += sizeof(struct compat_ifreq)) {
27826b96018bSArnd Bergmann 			if (copy_in_user(ifr, ifr32, sizeof(struct compat_ifreq)))
27837a229387SArnd Bergmann 				return -EFAULT;
27847a229387SArnd Bergmann 			ifr++;
27857a229387SArnd Bergmann 			ifr32++;
27867a229387SArnd Bergmann 		}
27877a229387SArnd Bergmann 	}
27887a229387SArnd Bergmann 	if (copy_to_user(uifc, &ifc, sizeof(struct ifconf)))
27897a229387SArnd Bergmann 		return -EFAULT;
27907a229387SArnd Bergmann 
27916b96018bSArnd Bergmann 	err = dev_ioctl(net, SIOCGIFCONF, uifc);
27927a229387SArnd Bergmann 	if (err)
27937a229387SArnd Bergmann 		return err;
27947a229387SArnd Bergmann 
27957a229387SArnd Bergmann 	if (copy_from_user(&ifc, uifc, sizeof(struct ifconf)))
27967a229387SArnd Bergmann 		return -EFAULT;
27977a229387SArnd Bergmann 
27987a229387SArnd Bergmann 	ifr = ifc.ifc_req;
27997a229387SArnd Bergmann 	ifr32 = compat_ptr(ifc32.ifcbuf);
28007a229387SArnd Bergmann 	for (i = 0, j = 0;
28016b96018bSArnd Bergmann 	     i + sizeof(struct compat_ifreq) <= ifc32.ifc_len && j < ifc.ifc_len;
28026b96018bSArnd Bergmann 	     i += sizeof(struct compat_ifreq), j += sizeof(struct ifreq)) {
28036b96018bSArnd Bergmann 		if (copy_in_user(ifr32, ifr, sizeof(struct compat_ifreq)))
28047a229387SArnd Bergmann 			return -EFAULT;
28057a229387SArnd Bergmann 		ifr32++;
28067a229387SArnd Bergmann 		ifr++;
28077a229387SArnd Bergmann 	}
28087a229387SArnd Bergmann 
28097a229387SArnd Bergmann 	if (ifc32.ifcbuf == 0) {
28107a229387SArnd Bergmann 		/* Translate from 64-bit structure multiple to
28117a229387SArnd Bergmann 		 * a 32-bit one.
28127a229387SArnd Bergmann 		 */
28137a229387SArnd Bergmann 		i = ifc.ifc_len;
28146b96018bSArnd Bergmann 		i = ((i / sizeof(struct ifreq)) * sizeof(struct compat_ifreq));
28157a229387SArnd Bergmann 		ifc32.ifc_len = i;
28167a229387SArnd Bergmann 	} else {
28177a229387SArnd Bergmann 		ifc32.ifc_len = i;
28187a229387SArnd Bergmann 	}
28196b96018bSArnd Bergmann 	if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf)))
28207a229387SArnd Bergmann 		return -EFAULT;
28217a229387SArnd Bergmann 
28227a229387SArnd Bergmann 	return 0;
28237a229387SArnd Bergmann }
28247a229387SArnd Bergmann 
28256b96018bSArnd Bergmann static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
28267a229387SArnd Bergmann {
28273a7da39dSBen Hutchings 	struct compat_ethtool_rxnfc __user *compat_rxnfc;
28283a7da39dSBen Hutchings 	bool convert_in = false, convert_out = false;
28293a7da39dSBen Hutchings 	size_t buf_size = ALIGN(sizeof(struct ifreq), 8);
28303a7da39dSBen Hutchings 	struct ethtool_rxnfc __user *rxnfc;
28317a229387SArnd Bergmann 	struct ifreq __user *ifr;
28323a7da39dSBen Hutchings 	u32 rule_cnt = 0, actual_rule_cnt;
28333a7da39dSBen Hutchings 	u32 ethcmd;
28347a229387SArnd Bergmann 	u32 data;
28353a7da39dSBen Hutchings 	int ret;
28367a229387SArnd Bergmann 
28377a229387SArnd Bergmann 	if (get_user(data, &ifr32->ifr_ifru.ifru_data))
28387a229387SArnd Bergmann 		return -EFAULT;
28397a229387SArnd Bergmann 
28403a7da39dSBen Hutchings 	compat_rxnfc = compat_ptr(data);
28413a7da39dSBen Hutchings 
28423a7da39dSBen Hutchings 	if (get_user(ethcmd, &compat_rxnfc->cmd))
28437a229387SArnd Bergmann 		return -EFAULT;
28447a229387SArnd Bergmann 
28453a7da39dSBen Hutchings 	/* Most ethtool structures are defined without padding.
28463a7da39dSBen Hutchings 	 * Unfortunately struct ethtool_rxnfc is an exception.
28473a7da39dSBen Hutchings 	 */
28483a7da39dSBen Hutchings 	switch (ethcmd) {
28493a7da39dSBen Hutchings 	default:
28503a7da39dSBen Hutchings 		break;
28513a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLALL:
28523a7da39dSBen Hutchings 		/* Buffer size is variable */
28533a7da39dSBen Hutchings 		if (get_user(rule_cnt, &compat_rxnfc->rule_cnt))
28543a7da39dSBen Hutchings 			return -EFAULT;
28553a7da39dSBen Hutchings 		if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32))
28563a7da39dSBen Hutchings 			return -ENOMEM;
28573a7da39dSBen Hutchings 		buf_size += rule_cnt * sizeof(u32);
28583a7da39dSBen Hutchings 		/* fall through */
28593a7da39dSBen Hutchings 	case ETHTOOL_GRXRINGS:
28603a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLCNT:
28613a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRULE:
286255664f32SBen Hutchings 	case ETHTOOL_SRXCLSRLINS:
28633a7da39dSBen Hutchings 		convert_out = true;
28643a7da39dSBen Hutchings 		/* fall through */
28653a7da39dSBen Hutchings 	case ETHTOOL_SRXCLSRLDEL:
28663a7da39dSBen Hutchings 		buf_size += sizeof(struct ethtool_rxnfc);
28673a7da39dSBen Hutchings 		convert_in = true;
28683a7da39dSBen Hutchings 		break;
28693a7da39dSBen Hutchings 	}
28703a7da39dSBen Hutchings 
28713a7da39dSBen Hutchings 	ifr = compat_alloc_user_space(buf_size);
2872954b1244SStephen Hemminger 	rxnfc = (void __user *)ifr + ALIGN(sizeof(struct ifreq), 8);
28733a7da39dSBen Hutchings 
28743a7da39dSBen Hutchings 	if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
28753a7da39dSBen Hutchings 		return -EFAULT;
28763a7da39dSBen Hutchings 
28773a7da39dSBen Hutchings 	if (put_user(convert_in ? rxnfc : compat_ptr(data),
28783a7da39dSBen Hutchings 		     &ifr->ifr_ifru.ifru_data))
28793a7da39dSBen Hutchings 		return -EFAULT;
28803a7da39dSBen Hutchings 
28813a7da39dSBen Hutchings 	if (convert_in) {
2882127fe533SAlexander Duyck 		/* We expect there to be holes between fs.m_ext and
28833a7da39dSBen Hutchings 		 * fs.ring_cookie and at the end of fs, but nowhere else.
28843a7da39dSBen Hutchings 		 */
2885127fe533SAlexander Duyck 		BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_ext) +
2886127fe533SAlexander Duyck 			     sizeof(compat_rxnfc->fs.m_ext) !=
2887127fe533SAlexander Duyck 			     offsetof(struct ethtool_rxnfc, fs.m_ext) +
2888127fe533SAlexander Duyck 			     sizeof(rxnfc->fs.m_ext));
28893a7da39dSBen Hutchings 		BUILD_BUG_ON(
28903a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.location) -
28913a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) !=
28923a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.location) -
28933a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.ring_cookie));
28943a7da39dSBen Hutchings 
28953a7da39dSBen Hutchings 		if (copy_in_user(rxnfc, compat_rxnfc,
2896954b1244SStephen Hemminger 				 (void __user *)(&rxnfc->fs.m_ext + 1) -
2897954b1244SStephen Hemminger 				 (void __user *)rxnfc) ||
28983a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->fs.ring_cookie,
28993a7da39dSBen Hutchings 				 &compat_rxnfc->fs.ring_cookie,
2900954b1244SStephen Hemminger 				 (void __user *)(&rxnfc->fs.location + 1) -
2901954b1244SStephen Hemminger 				 (void __user *)&rxnfc->fs.ring_cookie) ||
29023a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt,
29033a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
29043a7da39dSBen Hutchings 			return -EFAULT;
29053a7da39dSBen Hutchings 	}
29063a7da39dSBen Hutchings 
29073a7da39dSBen Hutchings 	ret = dev_ioctl(net, SIOCETHTOOL, ifr);
29083a7da39dSBen Hutchings 	if (ret)
29093a7da39dSBen Hutchings 		return ret;
29103a7da39dSBen Hutchings 
29113a7da39dSBen Hutchings 	if (convert_out) {
29123a7da39dSBen Hutchings 		if (copy_in_user(compat_rxnfc, rxnfc,
2913954b1244SStephen Hemminger 				 (const void __user *)(&rxnfc->fs.m_ext + 1) -
2914954b1244SStephen Hemminger 				 (const void __user *)rxnfc) ||
29153a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->fs.ring_cookie,
29163a7da39dSBen Hutchings 				 &rxnfc->fs.ring_cookie,
2917954b1244SStephen Hemminger 				 (const void __user *)(&rxnfc->fs.location + 1) -
2918954b1244SStephen Hemminger 				 (const void __user *)&rxnfc->fs.ring_cookie) ||
29193a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt,
29203a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
29213a7da39dSBen Hutchings 			return -EFAULT;
29223a7da39dSBen Hutchings 
29233a7da39dSBen Hutchings 		if (ethcmd == ETHTOOL_GRXCLSRLALL) {
29243a7da39dSBen Hutchings 			/* As an optimisation, we only copy the actual
29253a7da39dSBen Hutchings 			 * number of rules that the underlying
29263a7da39dSBen Hutchings 			 * function returned.  Since Mallory might
29273a7da39dSBen Hutchings 			 * change the rule count in user memory, we
29283a7da39dSBen Hutchings 			 * check that it is less than the rule count
29293a7da39dSBen Hutchings 			 * originally given (as the user buffer size),
29303a7da39dSBen Hutchings 			 * which has been range-checked.
29313a7da39dSBen Hutchings 			 */
29323a7da39dSBen Hutchings 			if (get_user(actual_rule_cnt, &rxnfc->rule_cnt))
29333a7da39dSBen Hutchings 				return -EFAULT;
29343a7da39dSBen Hutchings 			if (actual_rule_cnt < rule_cnt)
29353a7da39dSBen Hutchings 				rule_cnt = actual_rule_cnt;
29363a7da39dSBen Hutchings 			if (copy_in_user(&compat_rxnfc->rule_locs[0],
29373a7da39dSBen Hutchings 					 &rxnfc->rule_locs[0],
29383a7da39dSBen Hutchings 					 rule_cnt * sizeof(u32)))
29393a7da39dSBen Hutchings 				return -EFAULT;
29403a7da39dSBen Hutchings 		}
29413a7da39dSBen Hutchings 	}
29423a7da39dSBen Hutchings 
29433a7da39dSBen Hutchings 	return 0;
29447a229387SArnd Bergmann }
29457a229387SArnd Bergmann 
29467a50a240SArnd Bergmann static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32)
29477a50a240SArnd Bergmann {
29487a50a240SArnd Bergmann 	void __user *uptr;
29497a50a240SArnd Bergmann 	compat_uptr_t uptr32;
29507a50a240SArnd Bergmann 	struct ifreq __user *uifr;
29517a50a240SArnd Bergmann 
29527a50a240SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
29537a50a240SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
29547a50a240SArnd Bergmann 		return -EFAULT;
29557a50a240SArnd Bergmann 
29567a50a240SArnd Bergmann 	if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu))
29577a50a240SArnd Bergmann 		return -EFAULT;
29587a50a240SArnd Bergmann 
29597a50a240SArnd Bergmann 	uptr = compat_ptr(uptr32);
29607a50a240SArnd Bergmann 
29617a50a240SArnd Bergmann 	if (put_user(uptr, &uifr->ifr_settings.ifs_ifsu.raw_hdlc))
29627a50a240SArnd Bergmann 		return -EFAULT;
29637a50a240SArnd Bergmann 
29647a50a240SArnd Bergmann 	return dev_ioctl(net, SIOCWANDEV, uifr);
29657a50a240SArnd Bergmann }
29667a50a240SArnd Bergmann 
29676b96018bSArnd Bergmann static int bond_ioctl(struct net *net, unsigned int cmd,
29686b96018bSArnd Bergmann 			 struct compat_ifreq __user *ifr32)
29697a229387SArnd Bergmann {
29707a229387SArnd Bergmann 	struct ifreq kifr;
29717a229387SArnd Bergmann 	struct ifreq __user *uifr;
29727a229387SArnd Bergmann 	mm_segment_t old_fs;
29737a229387SArnd Bergmann 	int err;
29747a229387SArnd Bergmann 	u32 data;
29757a229387SArnd Bergmann 	void __user *datap;
29767a229387SArnd Bergmann 
29777a229387SArnd Bergmann 	switch (cmd) {
29787a229387SArnd Bergmann 	case SIOCBONDENSLAVE:
29797a229387SArnd Bergmann 	case SIOCBONDRELEASE:
29807a229387SArnd Bergmann 	case SIOCBONDSETHWADDR:
29817a229387SArnd Bergmann 	case SIOCBONDCHANGEACTIVE:
29826b96018bSArnd Bergmann 		if (copy_from_user(&kifr, ifr32, sizeof(struct compat_ifreq)))
29837a229387SArnd Bergmann 			return -EFAULT;
29847a229387SArnd Bergmann 
29857a229387SArnd Bergmann 		old_fs = get_fs();
29867a229387SArnd Bergmann 		set_fs(KERNEL_DS);
2987c3f52ae6Sstephen hemminger 		err = dev_ioctl(net, cmd,
2988c3f52ae6Sstephen hemminger 				(struct ifreq __user __force *) &kifr);
29897a229387SArnd Bergmann 		set_fs(old_fs);
29907a229387SArnd Bergmann 
29917a229387SArnd Bergmann 		return err;
29927a229387SArnd Bergmann 	case SIOCBONDSLAVEINFOQUERY:
29937a229387SArnd Bergmann 	case SIOCBONDINFOQUERY:
29947a229387SArnd Bergmann 		uifr = compat_alloc_user_space(sizeof(*uifr));
29957a229387SArnd Bergmann 		if (copy_in_user(&uifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
29967a229387SArnd Bergmann 			return -EFAULT;
29977a229387SArnd Bergmann 
29987a229387SArnd Bergmann 		if (get_user(data, &ifr32->ifr_ifru.ifru_data))
29997a229387SArnd Bergmann 			return -EFAULT;
30007a229387SArnd Bergmann 
30017a229387SArnd Bergmann 		datap = compat_ptr(data);
30027a229387SArnd Bergmann 		if (put_user(datap, &uifr->ifr_ifru.ifru_data))
30037a229387SArnd Bergmann 			return -EFAULT;
30047a229387SArnd Bergmann 
30056b96018bSArnd Bergmann 		return dev_ioctl(net, cmd, uifr);
30067a229387SArnd Bergmann 	default:
300707d106d0SLinus Torvalds 		return -ENOIOCTLCMD;
3008ccbd6a5aSJoe Perches 	}
30097a229387SArnd Bergmann }
30107a229387SArnd Bergmann 
30116b96018bSArnd Bergmann static int siocdevprivate_ioctl(struct net *net, unsigned int cmd,
30126b96018bSArnd Bergmann 				 struct compat_ifreq __user *u_ifreq32)
30137a229387SArnd Bergmann {
30147a229387SArnd Bergmann 	struct ifreq __user *u_ifreq64;
30157a229387SArnd Bergmann 	char tmp_buf[IFNAMSIZ];
30167a229387SArnd Bergmann 	void __user *data64;
30177a229387SArnd Bergmann 	u32 data32;
30187a229387SArnd Bergmann 
30197a229387SArnd Bergmann 	if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]),
30207a229387SArnd Bergmann 			   IFNAMSIZ))
30217a229387SArnd Bergmann 		return -EFAULT;
30227a229387SArnd Bergmann 	if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data))
30237a229387SArnd Bergmann 		return -EFAULT;
30247a229387SArnd Bergmann 	data64 = compat_ptr(data32);
30257a229387SArnd Bergmann 
30267a229387SArnd Bergmann 	u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
30277a229387SArnd Bergmann 
30287a229387SArnd Bergmann 	/* Don't check these user accesses, just let that get trapped
30297a229387SArnd Bergmann 	 * in the ioctl handler instead.
30307a229387SArnd Bergmann 	 */
30317a229387SArnd Bergmann 	if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0],
30327a229387SArnd Bergmann 			 IFNAMSIZ))
30337a229387SArnd Bergmann 		return -EFAULT;
30347a229387SArnd Bergmann 	if (__put_user(data64, &u_ifreq64->ifr_ifru.ifru_data))
30357a229387SArnd Bergmann 		return -EFAULT;
30367a229387SArnd Bergmann 
30376b96018bSArnd Bergmann 	return dev_ioctl(net, cmd, u_ifreq64);
30387a229387SArnd Bergmann }
30397a229387SArnd Bergmann 
30406b96018bSArnd Bergmann static int dev_ifsioc(struct net *net, struct socket *sock,
30416b96018bSArnd Bergmann 			 unsigned int cmd, struct compat_ifreq __user *uifr32)
30427a229387SArnd Bergmann {
3043a2116ed2SArnd Bergmann 	struct ifreq __user *uifr;
30447a229387SArnd Bergmann 	int err;
30457a229387SArnd Bergmann 
3046a2116ed2SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
3047a2116ed2SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(*uifr32)))
30487a229387SArnd Bergmann 		return -EFAULT;
3049a2116ed2SArnd Bergmann 
3050a2116ed2SArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr);
3051a2116ed2SArnd Bergmann 
30527a229387SArnd Bergmann 	if (!err) {
30537a229387SArnd Bergmann 		switch (cmd) {
30547a229387SArnd Bergmann 		case SIOCGIFFLAGS:
30557a229387SArnd Bergmann 		case SIOCGIFMETRIC:
30567a229387SArnd Bergmann 		case SIOCGIFMTU:
30577a229387SArnd Bergmann 		case SIOCGIFMEM:
30587a229387SArnd Bergmann 		case SIOCGIFHWADDR:
30597a229387SArnd Bergmann 		case SIOCGIFINDEX:
30607a229387SArnd Bergmann 		case SIOCGIFADDR:
30617a229387SArnd Bergmann 		case SIOCGIFBRDADDR:
30627a229387SArnd Bergmann 		case SIOCGIFDSTADDR:
30637a229387SArnd Bergmann 		case SIOCGIFNETMASK:
3064fab2532bSArnd Bergmann 		case SIOCGIFPFLAGS:
30657a229387SArnd Bergmann 		case SIOCGIFTXQLEN:
3066fab2532bSArnd Bergmann 		case SIOCGMIIPHY:
3067fab2532bSArnd Bergmann 		case SIOCGMIIREG:
3068a2116ed2SArnd Bergmann 			if (copy_in_user(uifr32, uifr, sizeof(*uifr32)))
3069a2116ed2SArnd Bergmann 				err = -EFAULT;
30707a229387SArnd Bergmann 			break;
3071a2116ed2SArnd Bergmann 		}
3072a2116ed2SArnd Bergmann 	}
3073a2116ed2SArnd Bergmann 	return err;
3074a2116ed2SArnd Bergmann }
3075a2116ed2SArnd Bergmann 
3076a2116ed2SArnd Bergmann static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
3077a2116ed2SArnd Bergmann 			struct compat_ifreq __user *uifr32)
3078a2116ed2SArnd Bergmann {
3079a2116ed2SArnd Bergmann 	struct ifreq ifr;
3080a2116ed2SArnd Bergmann 	struct compat_ifmap __user *uifmap32;
3081a2116ed2SArnd Bergmann 	mm_segment_t old_fs;
3082a2116ed2SArnd Bergmann 	int err;
3083a2116ed2SArnd Bergmann 
3084a2116ed2SArnd Bergmann 	uifmap32 = &uifr32->ifr_ifru.ifru_map;
3085a2116ed2SArnd Bergmann 	err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name));
30863ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
30873ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
30883ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
30893ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.irq, &uifmap32->irq);
30903ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.dma, &uifmap32->dma);
30913ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.port, &uifmap32->port);
3092a2116ed2SArnd Bergmann 	if (err)
3093a2116ed2SArnd Bergmann 		return -EFAULT;
3094a2116ed2SArnd Bergmann 
3095a2116ed2SArnd Bergmann 	old_fs = get_fs();
3096a2116ed2SArnd Bergmann 	set_fs(KERNEL_DS);
3097c3f52ae6Sstephen hemminger 	err = dev_ioctl(net, cmd, (void  __user __force *)&ifr);
3098a2116ed2SArnd Bergmann 	set_fs(old_fs);
3099a2116ed2SArnd Bergmann 
3100a2116ed2SArnd Bergmann 	if (cmd == SIOCGIFMAP && !err) {
31017a229387SArnd Bergmann 		err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name));
31023ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
31033ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
31043ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
31053ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.irq, &uifmap32->irq);
31063ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.dma, &uifmap32->dma);
31073ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.port, &uifmap32->port);
31087a229387SArnd Bergmann 		if (err)
31097a229387SArnd Bergmann 			err = -EFAULT;
31107a229387SArnd Bergmann 	}
31117a229387SArnd Bergmann 	return err;
31127a229387SArnd Bergmann }
31137a229387SArnd Bergmann 
3114a2116ed2SArnd Bergmann static int compat_siocshwtstamp(struct net *net, struct compat_ifreq __user *uifr32)
3115a2116ed2SArnd Bergmann {
3116a2116ed2SArnd Bergmann 	void __user *uptr;
3117a2116ed2SArnd Bergmann 	compat_uptr_t uptr32;
3118a2116ed2SArnd Bergmann 	struct ifreq __user *uifr;
3119a2116ed2SArnd Bergmann 
3120a2116ed2SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
3121a2116ed2SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
3122a2116ed2SArnd Bergmann 		return -EFAULT;
3123a2116ed2SArnd Bergmann 
3124a2116ed2SArnd Bergmann 	if (get_user(uptr32, &uifr32->ifr_data))
3125a2116ed2SArnd Bergmann 		return -EFAULT;
3126a2116ed2SArnd Bergmann 
3127a2116ed2SArnd Bergmann 	uptr = compat_ptr(uptr32);
3128a2116ed2SArnd Bergmann 
3129a2116ed2SArnd Bergmann 	if (put_user(uptr, &uifr->ifr_data))
3130a2116ed2SArnd Bergmann 		return -EFAULT;
3131a2116ed2SArnd Bergmann 
3132a2116ed2SArnd Bergmann 	return dev_ioctl(net, SIOCSHWTSTAMP, uifr);
3133a2116ed2SArnd Bergmann }
3134a2116ed2SArnd Bergmann 
31357a229387SArnd Bergmann struct rtentry32 {
31367a229387SArnd Bergmann 	u32		rt_pad1;
31377a229387SArnd Bergmann 	struct sockaddr rt_dst;         /* target address               */
31387a229387SArnd Bergmann 	struct sockaddr rt_gateway;     /* gateway addr (RTF_GATEWAY)   */
31397a229387SArnd Bergmann 	struct sockaddr rt_genmask;     /* target network mask (IP)     */
31407a229387SArnd Bergmann 	unsigned short	rt_flags;
31417a229387SArnd Bergmann 	short		rt_pad2;
31427a229387SArnd Bergmann 	u32		rt_pad3;
31437a229387SArnd Bergmann 	unsigned char	rt_tos;
31447a229387SArnd Bergmann 	unsigned char	rt_class;
31457a229387SArnd Bergmann 	short		rt_pad4;
31467a229387SArnd Bergmann 	short		rt_metric;      /* +1 for binary compatibility! */
31477a229387SArnd Bergmann 	/* char * */ u32 rt_dev;        /* forcing the device at add    */
31487a229387SArnd Bergmann 	u32		rt_mtu;         /* per route MTU/Window         */
31497a229387SArnd Bergmann 	u32		rt_window;      /* Window clamping              */
31507a229387SArnd Bergmann 	unsigned short  rt_irtt;        /* Initial RTT                  */
31517a229387SArnd Bergmann };
31527a229387SArnd Bergmann 
31537a229387SArnd Bergmann struct in6_rtmsg32 {
31547a229387SArnd Bergmann 	struct in6_addr		rtmsg_dst;
31557a229387SArnd Bergmann 	struct in6_addr		rtmsg_src;
31567a229387SArnd Bergmann 	struct in6_addr		rtmsg_gateway;
31577a229387SArnd Bergmann 	u32			rtmsg_type;
31587a229387SArnd Bergmann 	u16			rtmsg_dst_len;
31597a229387SArnd Bergmann 	u16			rtmsg_src_len;
31607a229387SArnd Bergmann 	u32			rtmsg_metric;
31617a229387SArnd Bergmann 	u32			rtmsg_info;
31627a229387SArnd Bergmann 	u32			rtmsg_flags;
31637a229387SArnd Bergmann 	s32			rtmsg_ifindex;
31647a229387SArnd Bergmann };
31657a229387SArnd Bergmann 
31666b96018bSArnd Bergmann static int routing_ioctl(struct net *net, struct socket *sock,
31676b96018bSArnd Bergmann 			 unsigned int cmd, void __user *argp)
31687a229387SArnd Bergmann {
31697a229387SArnd Bergmann 	int ret;
31707a229387SArnd Bergmann 	void *r = NULL;
31717a229387SArnd Bergmann 	struct in6_rtmsg r6;
31727a229387SArnd Bergmann 	struct rtentry r4;
31737a229387SArnd Bergmann 	char devname[16];
31747a229387SArnd Bergmann 	u32 rtdev;
31757a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
31767a229387SArnd Bergmann 
31776b96018bSArnd Bergmann 	if (sock && sock->sk && sock->sk->sk_family == AF_INET6) { /* ipv6 */
31786b96018bSArnd Bergmann 		struct in6_rtmsg32 __user *ur6 = argp;
31797a229387SArnd Bergmann 		ret = copy_from_user(&r6.rtmsg_dst, &(ur6->rtmsg_dst),
31807a229387SArnd Bergmann 			3 * sizeof(struct in6_addr));
31813ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_type, &(ur6->rtmsg_type));
31823ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len));
31833ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_src_len, &(ur6->rtmsg_src_len));
31843ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_metric, &(ur6->rtmsg_metric));
31853ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_info, &(ur6->rtmsg_info));
31863ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_flags, &(ur6->rtmsg_flags));
31873ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex));
31887a229387SArnd Bergmann 
31897a229387SArnd Bergmann 		r = (void *) &r6;
31907a229387SArnd Bergmann 	} else { /* ipv4 */
31916b96018bSArnd Bergmann 		struct rtentry32 __user *ur4 = argp;
31927a229387SArnd Bergmann 		ret = copy_from_user(&r4.rt_dst, &(ur4->rt_dst),
31937a229387SArnd Bergmann 					3 * sizeof(struct sockaddr));
31943ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_flags, &(ur4->rt_flags));
31953ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_metric, &(ur4->rt_metric));
31963ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_mtu, &(ur4->rt_mtu));
31973ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_window, &(ur4->rt_window));
31983ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_irtt, &(ur4->rt_irtt));
31993ddc5b46SMathieu Desnoyers 		ret |= get_user(rtdev, &(ur4->rt_dev));
32007a229387SArnd Bergmann 		if (rtdev) {
32017a229387SArnd Bergmann 			ret |= copy_from_user(devname, compat_ptr(rtdev), 15);
3202c3f52ae6Sstephen hemminger 			r4.rt_dev = (char __user __force *)devname;
3203c3f52ae6Sstephen hemminger 			devname[15] = 0;
32047a229387SArnd Bergmann 		} else
32057a229387SArnd Bergmann 			r4.rt_dev = NULL;
32067a229387SArnd Bergmann 
32077a229387SArnd Bergmann 		r = (void *) &r4;
32087a229387SArnd Bergmann 	}
32097a229387SArnd Bergmann 
32107a229387SArnd Bergmann 	if (ret) {
32117a229387SArnd Bergmann 		ret = -EFAULT;
32127a229387SArnd Bergmann 		goto out;
32137a229387SArnd Bergmann 	}
32147a229387SArnd Bergmann 
32157a229387SArnd Bergmann 	set_fs(KERNEL_DS);
32166b96018bSArnd Bergmann 	ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r);
32177a229387SArnd Bergmann 	set_fs(old_fs);
32187a229387SArnd Bergmann 
32197a229387SArnd Bergmann out:
32207a229387SArnd Bergmann 	return ret;
32217a229387SArnd Bergmann }
32227a229387SArnd Bergmann 
32237a229387SArnd Bergmann /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE
32247a229387SArnd Bergmann  * for some operations; this forces use of the newer bridge-utils that
322525985edcSLucas De Marchi  * use compatible ioctls
32267a229387SArnd Bergmann  */
32276b96018bSArnd Bergmann static int old_bridge_ioctl(compat_ulong_t __user *argp)
32287a229387SArnd Bergmann {
32296b96018bSArnd Bergmann 	compat_ulong_t tmp;
32307a229387SArnd Bergmann 
32316b96018bSArnd Bergmann 	if (get_user(tmp, argp))
32327a229387SArnd Bergmann 		return -EFAULT;
32337a229387SArnd Bergmann 	if (tmp == BRCTL_GET_VERSION)
32347a229387SArnd Bergmann 		return BRCTL_VERSION + 1;
32357a229387SArnd Bergmann 	return -EINVAL;
32367a229387SArnd Bergmann }
32377a229387SArnd Bergmann 
32386b96018bSArnd Bergmann static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
32396b96018bSArnd Bergmann 			 unsigned int cmd, unsigned long arg)
32406b96018bSArnd Bergmann {
32416b96018bSArnd Bergmann 	void __user *argp = compat_ptr(arg);
32426b96018bSArnd Bergmann 	struct sock *sk = sock->sk;
32436b96018bSArnd Bergmann 	struct net *net = sock_net(sk);
32447a229387SArnd Bergmann 
32456b96018bSArnd Bergmann 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
32466b96018bSArnd Bergmann 		return siocdevprivate_ioctl(net, cmd, argp);
32477a229387SArnd Bergmann 
32486b96018bSArnd Bergmann 	switch (cmd) {
32496b96018bSArnd Bergmann 	case SIOCSIFBR:
32506b96018bSArnd Bergmann 	case SIOCGIFBR:
32516b96018bSArnd Bergmann 		return old_bridge_ioctl(argp);
32526b96018bSArnd Bergmann 	case SIOCGIFNAME:
32536b96018bSArnd Bergmann 		return dev_ifname32(net, argp);
32546b96018bSArnd Bergmann 	case SIOCGIFCONF:
32556b96018bSArnd Bergmann 		return dev_ifconf(net, argp);
32566b96018bSArnd Bergmann 	case SIOCETHTOOL:
32576b96018bSArnd Bergmann 		return ethtool_ioctl(net, argp);
32587a50a240SArnd Bergmann 	case SIOCWANDEV:
32597a50a240SArnd Bergmann 		return compat_siocwandev(net, argp);
3260a2116ed2SArnd Bergmann 	case SIOCGIFMAP:
3261a2116ed2SArnd Bergmann 	case SIOCSIFMAP:
3262a2116ed2SArnd Bergmann 		return compat_sioc_ifmap(net, cmd, argp);
32636b96018bSArnd Bergmann 	case SIOCBONDENSLAVE:
32646b96018bSArnd Bergmann 	case SIOCBONDRELEASE:
32656b96018bSArnd Bergmann 	case SIOCBONDSETHWADDR:
32666b96018bSArnd Bergmann 	case SIOCBONDSLAVEINFOQUERY:
32676b96018bSArnd Bergmann 	case SIOCBONDINFOQUERY:
32686b96018bSArnd Bergmann 	case SIOCBONDCHANGEACTIVE:
32696b96018bSArnd Bergmann 		return bond_ioctl(net, cmd, argp);
32706b96018bSArnd Bergmann 	case SIOCADDRT:
32716b96018bSArnd Bergmann 	case SIOCDELRT:
32726b96018bSArnd Bergmann 		return routing_ioctl(net, sock, cmd, argp);
32736b96018bSArnd Bergmann 	case SIOCGSTAMP:
32746b96018bSArnd Bergmann 		return do_siocgstamp(net, sock, cmd, argp);
32756b96018bSArnd Bergmann 	case SIOCGSTAMPNS:
32766b96018bSArnd Bergmann 		return do_siocgstampns(net, sock, cmd, argp);
3277a2116ed2SArnd Bergmann 	case SIOCSHWTSTAMP:
3278a2116ed2SArnd Bergmann 		return compat_siocshwtstamp(net, argp);
32797a229387SArnd Bergmann 
32806b96018bSArnd Bergmann 	case FIOSETOWN:
32816b96018bSArnd Bergmann 	case SIOCSPGRP:
32826b96018bSArnd Bergmann 	case FIOGETOWN:
32836b96018bSArnd Bergmann 	case SIOCGPGRP:
32846b96018bSArnd Bergmann 	case SIOCBRADDBR:
32856b96018bSArnd Bergmann 	case SIOCBRDELBR:
32866b96018bSArnd Bergmann 	case SIOCGIFVLAN:
32876b96018bSArnd Bergmann 	case SIOCSIFVLAN:
32886b96018bSArnd Bergmann 	case SIOCADDDLCI:
32896b96018bSArnd Bergmann 	case SIOCDELDLCI:
32906b96018bSArnd Bergmann 		return sock_ioctl(file, cmd, arg);
32916b96018bSArnd Bergmann 
32926b96018bSArnd Bergmann 	case SIOCGIFFLAGS:
32936b96018bSArnd Bergmann 	case SIOCSIFFLAGS:
32946b96018bSArnd Bergmann 	case SIOCGIFMETRIC:
32956b96018bSArnd Bergmann 	case SIOCSIFMETRIC:
32966b96018bSArnd Bergmann 	case SIOCGIFMTU:
32976b96018bSArnd Bergmann 	case SIOCSIFMTU:
32986b96018bSArnd Bergmann 	case SIOCGIFMEM:
32996b96018bSArnd Bergmann 	case SIOCSIFMEM:
33006b96018bSArnd Bergmann 	case SIOCGIFHWADDR:
33016b96018bSArnd Bergmann 	case SIOCSIFHWADDR:
33026b96018bSArnd Bergmann 	case SIOCADDMULTI:
33036b96018bSArnd Bergmann 	case SIOCDELMULTI:
33046b96018bSArnd Bergmann 	case SIOCGIFINDEX:
33056b96018bSArnd Bergmann 	case SIOCGIFADDR:
33066b96018bSArnd Bergmann 	case SIOCSIFADDR:
33076b96018bSArnd Bergmann 	case SIOCSIFHWBROADCAST:
33086b96018bSArnd Bergmann 	case SIOCDIFADDR:
33096b96018bSArnd Bergmann 	case SIOCGIFBRDADDR:
33106b96018bSArnd Bergmann 	case SIOCSIFBRDADDR:
33116b96018bSArnd Bergmann 	case SIOCGIFDSTADDR:
33126b96018bSArnd Bergmann 	case SIOCSIFDSTADDR:
33136b96018bSArnd Bergmann 	case SIOCGIFNETMASK:
33146b96018bSArnd Bergmann 	case SIOCSIFNETMASK:
33156b96018bSArnd Bergmann 	case SIOCSIFPFLAGS:
33166b96018bSArnd Bergmann 	case SIOCGIFPFLAGS:
33176b96018bSArnd Bergmann 	case SIOCGIFTXQLEN:
33186b96018bSArnd Bergmann 	case SIOCSIFTXQLEN:
33196b96018bSArnd Bergmann 	case SIOCBRADDIF:
33206b96018bSArnd Bergmann 	case SIOCBRDELIF:
33219177efd3SArnd Bergmann 	case SIOCSIFNAME:
33229177efd3SArnd Bergmann 	case SIOCGMIIPHY:
33239177efd3SArnd Bergmann 	case SIOCGMIIREG:
33249177efd3SArnd Bergmann 	case SIOCSMIIREG:
33256b96018bSArnd Bergmann 		return dev_ifsioc(net, sock, cmd, argp);
33269177efd3SArnd Bergmann 
33276b96018bSArnd Bergmann 	case SIOCSARP:
33286b96018bSArnd Bergmann 	case SIOCGARP:
33296b96018bSArnd Bergmann 	case SIOCDARP:
33306b96018bSArnd Bergmann 	case SIOCATMARK:
33319177efd3SArnd Bergmann 		return sock_do_ioctl(net, sock, cmd, arg);
33329177efd3SArnd Bergmann 	}
33339177efd3SArnd Bergmann 
33346b96018bSArnd Bergmann 	return -ENOIOCTLCMD;
33356b96018bSArnd Bergmann }
33367a229387SArnd Bergmann 
333795c96174SEric Dumazet static long compat_sock_ioctl(struct file *file, unsigned int cmd,
333889bbfc95SShaun Pereira 			      unsigned long arg)
333989bbfc95SShaun Pereira {
334089bbfc95SShaun Pereira 	struct socket *sock = file->private_data;
334189bbfc95SShaun Pereira 	int ret = -ENOIOCTLCMD;
334287de87d5SDavid S. Miller 	struct sock *sk;
334387de87d5SDavid S. Miller 	struct net *net;
334487de87d5SDavid S. Miller 
334587de87d5SDavid S. Miller 	sk = sock->sk;
334687de87d5SDavid S. Miller 	net = sock_net(sk);
334789bbfc95SShaun Pereira 
334889bbfc95SShaun Pereira 	if (sock->ops->compat_ioctl)
334989bbfc95SShaun Pereira 		ret = sock->ops->compat_ioctl(sock, cmd, arg);
335089bbfc95SShaun Pereira 
335187de87d5SDavid S. Miller 	if (ret == -ENOIOCTLCMD &&
335287de87d5SDavid S. Miller 	    (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST))
335387de87d5SDavid S. Miller 		ret = compat_wext_handle_ioctl(net, cmd, arg);
335487de87d5SDavid S. Miller 
33556b96018bSArnd Bergmann 	if (ret == -ENOIOCTLCMD)
33566b96018bSArnd Bergmann 		ret = compat_sock_ioctl_trans(file, sock, cmd, arg);
33576b96018bSArnd Bergmann 
335889bbfc95SShaun Pereira 	return ret;
335989bbfc95SShaun Pereira }
336089bbfc95SShaun Pereira #endif
336189bbfc95SShaun Pereira 
3362ac5a488eSSridhar Samudrala int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
3363ac5a488eSSridhar Samudrala {
3364ac5a488eSSridhar Samudrala 	return sock->ops->bind(sock, addr, addrlen);
3365ac5a488eSSridhar Samudrala }
3366c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_bind);
3367ac5a488eSSridhar Samudrala 
3368ac5a488eSSridhar Samudrala int kernel_listen(struct socket *sock, int backlog)
3369ac5a488eSSridhar Samudrala {
3370ac5a488eSSridhar Samudrala 	return sock->ops->listen(sock, backlog);
3371ac5a488eSSridhar Samudrala }
3372c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_listen);
3373ac5a488eSSridhar Samudrala 
3374ac5a488eSSridhar Samudrala int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
3375ac5a488eSSridhar Samudrala {
3376ac5a488eSSridhar Samudrala 	struct sock *sk = sock->sk;
3377ac5a488eSSridhar Samudrala 	int err;
3378ac5a488eSSridhar Samudrala 
3379ac5a488eSSridhar Samudrala 	err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
3380ac5a488eSSridhar Samudrala 			       newsock);
3381ac5a488eSSridhar Samudrala 	if (err < 0)
3382ac5a488eSSridhar Samudrala 		goto done;
3383ac5a488eSSridhar Samudrala 
3384ac5a488eSSridhar Samudrala 	err = sock->ops->accept(sock, *newsock, flags);
3385ac5a488eSSridhar Samudrala 	if (err < 0) {
3386ac5a488eSSridhar Samudrala 		sock_release(*newsock);
3387fa8705b0STony Battersby 		*newsock = NULL;
3388ac5a488eSSridhar Samudrala 		goto done;
3389ac5a488eSSridhar Samudrala 	}
3390ac5a488eSSridhar Samudrala 
3391ac5a488eSSridhar Samudrala 	(*newsock)->ops = sock->ops;
33921b08534eSWei Yongjun 	__module_get((*newsock)->ops->owner);
3393ac5a488eSSridhar Samudrala 
3394ac5a488eSSridhar Samudrala done:
3395ac5a488eSSridhar Samudrala 	return err;
3396ac5a488eSSridhar Samudrala }
3397c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_accept);
3398ac5a488eSSridhar Samudrala 
3399ac5a488eSSridhar Samudrala int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
3400ac5a488eSSridhar Samudrala 		   int flags)
3401ac5a488eSSridhar Samudrala {
3402ac5a488eSSridhar Samudrala 	return sock->ops->connect(sock, addr, addrlen, flags);
3403ac5a488eSSridhar Samudrala }
3404c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_connect);
3405ac5a488eSSridhar Samudrala 
3406ac5a488eSSridhar Samudrala int kernel_getsockname(struct socket *sock, struct sockaddr *addr,
3407ac5a488eSSridhar Samudrala 			 int *addrlen)
3408ac5a488eSSridhar Samudrala {
3409ac5a488eSSridhar Samudrala 	return sock->ops->getname(sock, addr, addrlen, 0);
3410ac5a488eSSridhar Samudrala }
3411c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockname);
3412ac5a488eSSridhar Samudrala 
3413ac5a488eSSridhar Samudrala int kernel_getpeername(struct socket *sock, struct sockaddr *addr,
3414ac5a488eSSridhar Samudrala 			 int *addrlen)
3415ac5a488eSSridhar Samudrala {
3416ac5a488eSSridhar Samudrala 	return sock->ops->getname(sock, addr, addrlen, 1);
3417ac5a488eSSridhar Samudrala }
3418c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getpeername);
3419ac5a488eSSridhar Samudrala 
3420ac5a488eSSridhar Samudrala int kernel_getsockopt(struct socket *sock, int level, int optname,
3421ac5a488eSSridhar Samudrala 			char *optval, int *optlen)
3422ac5a488eSSridhar Samudrala {
3423ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3424fb8621bbSNamhyung Kim 	char __user *uoptval;
3425fb8621bbSNamhyung Kim 	int __user *uoptlen;
3426ac5a488eSSridhar Samudrala 	int err;
3427ac5a488eSSridhar Samudrala 
3428fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3429fb8621bbSNamhyung Kim 	uoptlen = (int __user __force *) optlen;
3430fb8621bbSNamhyung Kim 
3431ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3432ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3433fb8621bbSNamhyung Kim 		err = sock_getsockopt(sock, level, optname, uoptval, uoptlen);
3434ac5a488eSSridhar Samudrala 	else
3435fb8621bbSNamhyung Kim 		err = sock->ops->getsockopt(sock, level, optname, uoptval,
3436fb8621bbSNamhyung Kim 					    uoptlen);
3437ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3438ac5a488eSSridhar Samudrala 	return err;
3439ac5a488eSSridhar Samudrala }
3440c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockopt);
3441ac5a488eSSridhar Samudrala 
3442ac5a488eSSridhar Samudrala int kernel_setsockopt(struct socket *sock, int level, int optname,
3443b7058842SDavid S. Miller 			char *optval, unsigned int optlen)
3444ac5a488eSSridhar Samudrala {
3445ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3446fb8621bbSNamhyung Kim 	char __user *uoptval;
3447ac5a488eSSridhar Samudrala 	int err;
3448ac5a488eSSridhar Samudrala 
3449fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3450fb8621bbSNamhyung Kim 
3451ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3452ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3453fb8621bbSNamhyung Kim 		err = sock_setsockopt(sock, level, optname, uoptval, optlen);
3454ac5a488eSSridhar Samudrala 	else
3455fb8621bbSNamhyung Kim 		err = sock->ops->setsockopt(sock, level, optname, uoptval,
3456ac5a488eSSridhar Samudrala 					    optlen);
3457ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3458ac5a488eSSridhar Samudrala 	return err;
3459ac5a488eSSridhar Samudrala }
3460c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_setsockopt);
3461ac5a488eSSridhar Samudrala 
3462ac5a488eSSridhar Samudrala int kernel_sendpage(struct socket *sock, struct page *page, int offset,
3463ac5a488eSSridhar Samudrala 		    size_t size, int flags)
3464ac5a488eSSridhar Samudrala {
3465ac5a488eSSridhar Samudrala 	if (sock->ops->sendpage)
3466ac5a488eSSridhar Samudrala 		return sock->ops->sendpage(sock, page, offset, size, flags);
3467ac5a488eSSridhar Samudrala 
3468ac5a488eSSridhar Samudrala 	return sock_no_sendpage(sock, page, offset, size, flags);
3469ac5a488eSSridhar Samudrala }
3470c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendpage);
3471ac5a488eSSridhar Samudrala 
3472ac5a488eSSridhar Samudrala int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg)
3473ac5a488eSSridhar Samudrala {
3474ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3475ac5a488eSSridhar Samudrala 	int err;
3476ac5a488eSSridhar Samudrala 
3477ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3478ac5a488eSSridhar Samudrala 	err = sock->ops->ioctl(sock, cmd, arg);
3479ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3480ac5a488eSSridhar Samudrala 
3481ac5a488eSSridhar Samudrala 	return err;
3482ac5a488eSSridhar Samudrala }
3483c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sock_ioctl);
3484ac5a488eSSridhar Samudrala 
348591cf45f0STrond Myklebust int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
348691cf45f0STrond Myklebust {
348791cf45f0STrond Myklebust 	return sock->ops->shutdown(sock, how);
348891cf45f0STrond Myklebust }
348991cf45f0STrond Myklebust EXPORT_SYMBOL(kernel_sock_shutdown);
3490