xref: /openbmc/linux/net/socket.c (revision 130ed5d1)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * NET		An implementation of the SOCKET network access protocol.
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Version:	@(#)socket.c	1.1.93	18/02/95
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * Authors:	Orest Zborowski, <obz@Kodak.COM>
702c30a84SJesper Juhl  *		Ross Biro
81da177e4SLinus Torvalds  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
91da177e4SLinus Torvalds  *
101da177e4SLinus Torvalds  * Fixes:
111da177e4SLinus Torvalds  *		Anonymous	:	NOTSOCK/BADF cleanup. Error fix in
121da177e4SLinus Torvalds  *					shutdown()
131da177e4SLinus Torvalds  *		Alan Cox	:	verify_area() fixes
141da177e4SLinus Torvalds  *		Alan Cox	:	Removed DDI
151da177e4SLinus Torvalds  *		Jonathan Kamens	:	SOCK_DGRAM reconnect bug
161da177e4SLinus Torvalds  *		Alan Cox	:	Moved a load of checks to the very
171da177e4SLinus Torvalds  *					top level.
181da177e4SLinus Torvalds  *		Alan Cox	:	Move address structures to/from user
191da177e4SLinus Torvalds  *					mode above the protocol layers.
201da177e4SLinus Torvalds  *		Rob Janssen	:	Allow 0 length sends.
211da177e4SLinus Torvalds  *		Alan Cox	:	Asynchronous I/O support (cribbed from the
221da177e4SLinus Torvalds  *					tty drivers).
231da177e4SLinus Torvalds  *		Niibe Yutaka	:	Asynchronous I/O for writes (4.4BSD style)
241da177e4SLinus Torvalds  *		Jeff Uphoff	:	Made max number of sockets command-line
251da177e4SLinus Torvalds  *					configurable.
261da177e4SLinus Torvalds  *		Matti Aarnio	:	Made the number of sockets dynamic,
271da177e4SLinus Torvalds  *					to be allocated when needed, and mr.
281da177e4SLinus Torvalds  *					Uphoff's max is used as max to be
291da177e4SLinus Torvalds  *					allowed to allocate.
301da177e4SLinus Torvalds  *		Linus		:	Argh. removed all the socket allocation
311da177e4SLinus Torvalds  *					altogether: it's in the inode now.
321da177e4SLinus Torvalds  *		Alan Cox	:	Made sock_alloc()/sock_release() public
331da177e4SLinus Torvalds  *					for NetROM and future kernel nfsd type
341da177e4SLinus Torvalds  *					stuff.
351da177e4SLinus Torvalds  *		Alan Cox	:	sendmsg/recvmsg basics.
361da177e4SLinus Torvalds  *		Tom Dyas	:	Export net symbols.
371da177e4SLinus Torvalds  *		Marcin Dalecki	:	Fixed problems with CONFIG_NET="n".
381da177e4SLinus Torvalds  *		Alan Cox	:	Added thread locking to sys_* calls
391da177e4SLinus Torvalds  *					for sockets. May have errors at the
401da177e4SLinus Torvalds  *					moment.
411da177e4SLinus Torvalds  *		Kevin Buhr	:	Fixed the dumb errors in the above.
421da177e4SLinus Torvalds  *		Andi Kleen	:	Some small cleanups, optimizations,
431da177e4SLinus Torvalds  *					and fixed a copy_from_user() bug.
441da177e4SLinus Torvalds  *		Tigran Aivazian	:	sys_send(args) calls sys_sendto(args, NULL, 0)
451da177e4SLinus Torvalds  *		Tigran Aivazian	:	Made listen(2) backlog sanity checks
461da177e4SLinus Torvalds  *					protocol-independent
471da177e4SLinus Torvalds  *
481da177e4SLinus Torvalds  *
491da177e4SLinus Torvalds  *		This program is free software; you can redistribute it and/or
501da177e4SLinus Torvalds  *		modify it under the terms of the GNU General Public License
511da177e4SLinus Torvalds  *		as published by the Free Software Foundation; either version
521da177e4SLinus Torvalds  *		2 of the License, or (at your option) any later version.
531da177e4SLinus Torvalds  *
541da177e4SLinus Torvalds  *
551da177e4SLinus Torvalds  *	This module is effectively the top level interface to the BSD socket
561da177e4SLinus Torvalds  *	paradigm.
571da177e4SLinus Torvalds  *
581da177e4SLinus Torvalds  *	Based upon Swansea University Computer Society NET3.039
591da177e4SLinus Torvalds  */
601da177e4SLinus Torvalds 
611da177e4SLinus Torvalds #include <linux/mm.h>
621da177e4SLinus Torvalds #include <linux/socket.h>
631da177e4SLinus Torvalds #include <linux/file.h>
641da177e4SLinus Torvalds #include <linux/net.h>
651da177e4SLinus Torvalds #include <linux/interrupt.h>
66aaca0bdcSUlrich Drepper #include <linux/thread_info.h>
6755737fdaSStephen Hemminger #include <linux/rcupdate.h>
681da177e4SLinus Torvalds #include <linux/netdevice.h>
691da177e4SLinus Torvalds #include <linux/proc_fs.h>
701da177e4SLinus Torvalds #include <linux/seq_file.h>
714a3e2f71SArjan van de Ven #include <linux/mutex.h>
721da177e4SLinus Torvalds #include <linux/if_bridge.h>
7320380731SArnaldo Carvalho de Melo #include <linux/if_frad.h>
7420380731SArnaldo Carvalho de Melo #include <linux/if_vlan.h>
75408eccceSDaniel Borkmann #include <linux/ptp_classify.h>
761da177e4SLinus Torvalds #include <linux/init.h>
771da177e4SLinus Torvalds #include <linux/poll.h>
781da177e4SLinus Torvalds #include <linux/cache.h>
791da177e4SLinus Torvalds #include <linux/module.h>
801da177e4SLinus Torvalds #include <linux/highmem.h>
811da177e4SLinus Torvalds #include <linux/mount.h>
821da177e4SLinus Torvalds #include <linux/security.h>
831da177e4SLinus Torvalds #include <linux/syscalls.h>
841da177e4SLinus Torvalds #include <linux/compat.h>
851da177e4SLinus Torvalds #include <linux/kmod.h>
863ec3b2fbSDavid Woodhouse #include <linux/audit.h>
87d86b5e0eSAdrian Bunk #include <linux/wireless.h>
881b8d7ae4SEric W. Biederman #include <linux/nsproxy.h>
891fd7317dSNick Black #include <linux/magic.h>
905a0e3ad6STejun Heo #include <linux/slab.h>
91600e1779SMasatake YAMATO #include <linux/xattr.h>
921da177e4SLinus Torvalds 
931da177e4SLinus Torvalds #include <asm/uaccess.h>
941da177e4SLinus Torvalds #include <asm/unistd.h>
951da177e4SLinus Torvalds 
961da177e4SLinus Torvalds #include <net/compat.h>
9787de87d5SDavid S. Miller #include <net/wext.h>
98f8451725SHerbert Xu #include <net/cls_cgroup.h>
991da177e4SLinus Torvalds 
1001da177e4SLinus Torvalds #include <net/sock.h>
1011da177e4SLinus Torvalds #include <linux/netfilter.h>
1021da177e4SLinus Torvalds 
1036b96018bSArnd Bergmann #include <linux/if_tun.h>
1046b96018bSArnd Bergmann #include <linux/ipv6_route.h>
1056b96018bSArnd Bergmann #include <linux/route.h>
1066b96018bSArnd Bergmann #include <linux/sockios.h>
1076b96018bSArnd Bergmann #include <linux/atalk.h>
108076bb0c8SEliezer Tamir #include <net/busy_poll.h>
109f24b9be5SWillem de Bruijn #include <linux/errqueue.h>
11006021292SEliezer Tamir 
111e0d1095aSCong Wang #ifdef CONFIG_NET_RX_BUSY_POLL
11264b0dc51SEliezer Tamir unsigned int sysctl_net_busy_read __read_mostly;
11364b0dc51SEliezer Tamir unsigned int sysctl_net_busy_poll __read_mostly;
11406021292SEliezer Tamir #endif
1156b96018bSArnd Bergmann 
1168ae5e030SAl Viro static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to);
1178ae5e030SAl Viro static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from);
1181da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma);
1191da177e4SLinus Torvalds 
1201da177e4SLinus Torvalds static int sock_close(struct inode *inode, struct file *file);
1211da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file,
1221da177e4SLinus Torvalds 			      struct poll_table_struct *wait);
12389bddce5SStephen Hemminger static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
12489bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
12589bbfc95SShaun Pereira static long compat_sock_ioctl(struct file *file,
12689bbfc95SShaun Pereira 			      unsigned int cmd, unsigned long arg);
12789bbfc95SShaun Pereira #endif
1281da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on);
1291da177e4SLinus Torvalds static ssize_t sock_sendpage(struct file *file, struct page *page,
1301da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more);
1319c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
1329c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
1339c55e01cSJens Axboe 				unsigned int flags);
1341da177e4SLinus Torvalds 
1351da177e4SLinus Torvalds /*
1361da177e4SLinus Torvalds  *	Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
1371da177e4SLinus Torvalds  *	in the operation structures but are done directly via the socketcall() multiplexor.
1381da177e4SLinus Torvalds  */
1391da177e4SLinus Torvalds 
140da7071d7SArjan van de Ven static const struct file_operations socket_file_ops = {
1411da177e4SLinus Torvalds 	.owner =	THIS_MODULE,
1421da177e4SLinus Torvalds 	.llseek =	no_llseek,
1438ae5e030SAl Viro 	.read_iter =	sock_read_iter,
1448ae5e030SAl Viro 	.write_iter =	sock_write_iter,
1451da177e4SLinus Torvalds 	.poll =		sock_poll,
1461da177e4SLinus Torvalds 	.unlocked_ioctl = sock_ioctl,
14789bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
14889bbfc95SShaun Pereira 	.compat_ioctl = compat_sock_ioctl,
14989bbfc95SShaun Pereira #endif
1501da177e4SLinus Torvalds 	.mmap =		sock_mmap,
1511da177e4SLinus Torvalds 	.release =	sock_close,
1521da177e4SLinus Torvalds 	.fasync =	sock_fasync,
1535274f052SJens Axboe 	.sendpage =	sock_sendpage,
1545274f052SJens Axboe 	.splice_write = generic_splice_sendpage,
1559c55e01cSJens Axboe 	.splice_read =	sock_splice_read,
1561da177e4SLinus Torvalds };
1571da177e4SLinus Torvalds 
1581da177e4SLinus Torvalds /*
1591da177e4SLinus Torvalds  *	The protocol list. Each protocol is registered in here.
1601da177e4SLinus Torvalds  */
1611da177e4SLinus Torvalds 
1621da177e4SLinus Torvalds static DEFINE_SPINLOCK(net_family_lock);
163190683a9SEric Dumazet static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly;
1641da177e4SLinus Torvalds 
1651da177e4SLinus Torvalds /*
1661da177e4SLinus Torvalds  *	Statistics counters of the socket lists
1671da177e4SLinus Torvalds  */
1681da177e4SLinus Torvalds 
169c6d409cfSEric Dumazet static DEFINE_PER_CPU(int, sockets_in_use);
1701da177e4SLinus Torvalds 
1711da177e4SLinus Torvalds /*
17289bddce5SStephen Hemminger  * Support routines.
17389bddce5SStephen Hemminger  * Move socket addresses back and forth across the kernel/user
1741da177e4SLinus Torvalds  * divide and look after the messy bits.
1751da177e4SLinus Torvalds  */
1761da177e4SLinus Torvalds 
1771da177e4SLinus Torvalds /**
1781da177e4SLinus Torvalds  *	move_addr_to_kernel	-	copy a socket address into kernel space
1791da177e4SLinus Torvalds  *	@uaddr: Address in user space
1801da177e4SLinus Torvalds  *	@kaddr: Address in kernel space
1811da177e4SLinus Torvalds  *	@ulen: Length in user space
1821da177e4SLinus Torvalds  *
1831da177e4SLinus Torvalds  *	The address is copied into kernel space. If the provided address is
1841da177e4SLinus Torvalds  *	too long an error code of -EINVAL is returned. If the copy gives
1851da177e4SLinus Torvalds  *	invalid addresses -EFAULT is returned. On a success 0 is returned.
1861da177e4SLinus Torvalds  */
1871da177e4SLinus Torvalds 
18843db362dSMaciej Żenczykowski int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr)
1891da177e4SLinus Torvalds {
190230b1839SYOSHIFUJI Hideaki 	if (ulen < 0 || ulen > sizeof(struct sockaddr_storage))
1911da177e4SLinus Torvalds 		return -EINVAL;
1921da177e4SLinus Torvalds 	if (ulen == 0)
1931da177e4SLinus Torvalds 		return 0;
1941da177e4SLinus Torvalds 	if (copy_from_user(kaddr, uaddr, ulen))
1951da177e4SLinus Torvalds 		return -EFAULT;
1963ec3b2fbSDavid Woodhouse 	return audit_sockaddr(ulen, kaddr);
1971da177e4SLinus Torvalds }
1981da177e4SLinus Torvalds 
1991da177e4SLinus Torvalds /**
2001da177e4SLinus Torvalds  *	move_addr_to_user	-	copy an address to user space
2011da177e4SLinus Torvalds  *	@kaddr: kernel space address
2021da177e4SLinus Torvalds  *	@klen: length of address in kernel
2031da177e4SLinus Torvalds  *	@uaddr: user space address
2041da177e4SLinus Torvalds  *	@ulen: pointer to user length field
2051da177e4SLinus Torvalds  *
2061da177e4SLinus Torvalds  *	The value pointed to by ulen on entry is the buffer length available.
2071da177e4SLinus Torvalds  *	This is overwritten with the buffer space used. -EINVAL is returned
2081da177e4SLinus Torvalds  *	if an overlong buffer is specified or a negative buffer size. -EFAULT
2091da177e4SLinus Torvalds  *	is returned if either the buffer or the length field are not
2101da177e4SLinus Torvalds  *	accessible.
2111da177e4SLinus Torvalds  *	After copying the data up to the limit the user specifies, the true
2121da177e4SLinus Torvalds  *	length of the data is written over the length limit the user
2131da177e4SLinus Torvalds  *	specified. Zero is returned for a success.
2141da177e4SLinus Torvalds  */
2151da177e4SLinus Torvalds 
21643db362dSMaciej Żenczykowski static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen,
21711165f14Sstephen hemminger 			     void __user *uaddr, int __user *ulen)
2181da177e4SLinus Torvalds {
2191da177e4SLinus Torvalds 	int err;
2201da177e4SLinus Torvalds 	int len;
2211da177e4SLinus Torvalds 
22268c6beb3SHannes Frederic Sowa 	BUG_ON(klen > sizeof(struct sockaddr_storage));
22389bddce5SStephen Hemminger 	err = get_user(len, ulen);
22489bddce5SStephen Hemminger 	if (err)
2251da177e4SLinus Torvalds 		return err;
2261da177e4SLinus Torvalds 	if (len > klen)
2271da177e4SLinus Torvalds 		len = klen;
22868c6beb3SHannes Frederic Sowa 	if (len < 0)
2291da177e4SLinus Torvalds 		return -EINVAL;
23089bddce5SStephen Hemminger 	if (len) {
231d6fe3945SSteve Grubb 		if (audit_sockaddr(klen, kaddr))
232d6fe3945SSteve Grubb 			return -ENOMEM;
2331da177e4SLinus Torvalds 		if (copy_to_user(uaddr, kaddr, len))
2341da177e4SLinus Torvalds 			return -EFAULT;
2351da177e4SLinus Torvalds 	}
2361da177e4SLinus Torvalds 	/*
2371da177e4SLinus Torvalds 	 *      "fromlen shall refer to the value before truncation.."
2381da177e4SLinus Torvalds 	 *                      1003.1g
2391da177e4SLinus Torvalds 	 */
2401da177e4SLinus Torvalds 	return __put_user(klen, ulen);
2411da177e4SLinus Torvalds }
2421da177e4SLinus Torvalds 
243e18b890bSChristoph Lameter static struct kmem_cache *sock_inode_cachep __read_mostly;
2441da177e4SLinus Torvalds 
2451da177e4SLinus Torvalds static struct inode *sock_alloc_inode(struct super_block *sb)
2461da177e4SLinus Torvalds {
2471da177e4SLinus Torvalds 	struct socket_alloc *ei;
248eaefd110SEric Dumazet 	struct socket_wq *wq;
24989bddce5SStephen Hemminger 
250e94b1766SChristoph Lameter 	ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL);
2511da177e4SLinus Torvalds 	if (!ei)
2521da177e4SLinus Torvalds 		return NULL;
253eaefd110SEric Dumazet 	wq = kmalloc(sizeof(*wq), GFP_KERNEL);
254eaefd110SEric Dumazet 	if (!wq) {
25543815482SEric Dumazet 		kmem_cache_free(sock_inode_cachep, ei);
25643815482SEric Dumazet 		return NULL;
25743815482SEric Dumazet 	}
258eaefd110SEric Dumazet 	init_waitqueue_head(&wq->wait);
259eaefd110SEric Dumazet 	wq->fasync_list = NULL;
260eaefd110SEric Dumazet 	RCU_INIT_POINTER(ei->socket.wq, wq);
2611da177e4SLinus Torvalds 
2621da177e4SLinus Torvalds 	ei->socket.state = SS_UNCONNECTED;
2631da177e4SLinus Torvalds 	ei->socket.flags = 0;
2641da177e4SLinus Torvalds 	ei->socket.ops = NULL;
2651da177e4SLinus Torvalds 	ei->socket.sk = NULL;
2661da177e4SLinus Torvalds 	ei->socket.file = NULL;
2671da177e4SLinus Torvalds 
2681da177e4SLinus Torvalds 	return &ei->vfs_inode;
2691da177e4SLinus Torvalds }
2701da177e4SLinus Torvalds 
2711da177e4SLinus Torvalds static void sock_destroy_inode(struct inode *inode)
2721da177e4SLinus Torvalds {
27343815482SEric Dumazet 	struct socket_alloc *ei;
274eaefd110SEric Dumazet 	struct socket_wq *wq;
27543815482SEric Dumazet 
27643815482SEric Dumazet 	ei = container_of(inode, struct socket_alloc, vfs_inode);
277eaefd110SEric Dumazet 	wq = rcu_dereference_protected(ei->socket.wq, 1);
27861845220SLai Jiangshan 	kfree_rcu(wq, rcu);
27943815482SEric Dumazet 	kmem_cache_free(sock_inode_cachep, ei);
2801da177e4SLinus Torvalds }
2811da177e4SLinus Torvalds 
28251cc5068SAlexey Dobriyan static void init_once(void *foo)
2831da177e4SLinus Torvalds {
2841da177e4SLinus Torvalds 	struct socket_alloc *ei = (struct socket_alloc *)foo;
2851da177e4SLinus Torvalds 
2861da177e4SLinus Torvalds 	inode_init_once(&ei->vfs_inode);
2871da177e4SLinus Torvalds }
2881da177e4SLinus Torvalds 
2891da177e4SLinus Torvalds static int init_inodecache(void)
2901da177e4SLinus Torvalds {
2911da177e4SLinus Torvalds 	sock_inode_cachep = kmem_cache_create("sock_inode_cache",
2921da177e4SLinus Torvalds 					      sizeof(struct socket_alloc),
29389bddce5SStephen Hemminger 					      0,
29489bddce5SStephen Hemminger 					      (SLAB_HWCACHE_ALIGN |
29589bddce5SStephen Hemminger 					       SLAB_RECLAIM_ACCOUNT |
296fffb60f9SPaul Jackson 					       SLAB_MEM_SPREAD),
29720c2df83SPaul Mundt 					      init_once);
2981da177e4SLinus Torvalds 	if (sock_inode_cachep == NULL)
2991da177e4SLinus Torvalds 		return -ENOMEM;
3001da177e4SLinus Torvalds 	return 0;
3011da177e4SLinus Torvalds }
3021da177e4SLinus Torvalds 
303b87221deSAlexey Dobriyan static const struct super_operations sockfs_ops = {
3041da177e4SLinus Torvalds 	.alloc_inode	= sock_alloc_inode,
3051da177e4SLinus Torvalds 	.destroy_inode	= sock_destroy_inode,
3061da177e4SLinus Torvalds 	.statfs		= simple_statfs,
3071da177e4SLinus Torvalds };
3081da177e4SLinus Torvalds 
309c23fbb6bSEric Dumazet /*
310c23fbb6bSEric Dumazet  * sockfs_dname() is called from d_path().
311c23fbb6bSEric Dumazet  */
312c23fbb6bSEric Dumazet static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen)
313c23fbb6bSEric Dumazet {
314c23fbb6bSEric Dumazet 	return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]",
315c5ef6035SDavid Howells 				d_inode(dentry)->i_ino);
316c23fbb6bSEric Dumazet }
317c23fbb6bSEric Dumazet 
3183ba13d17SAl Viro static const struct dentry_operations sockfs_dentry_operations = {
319c23fbb6bSEric Dumazet 	.d_dname  = sockfs_dname,
3201da177e4SLinus Torvalds };
3211da177e4SLinus Torvalds 
322c74a1cbbSAl Viro static struct dentry *sockfs_mount(struct file_system_type *fs_type,
323c74a1cbbSAl Viro 			 int flags, const char *dev_name, void *data)
324c74a1cbbSAl Viro {
325c74a1cbbSAl Viro 	return mount_pseudo(fs_type, "socket:", &sockfs_ops,
326c74a1cbbSAl Viro 		&sockfs_dentry_operations, SOCKFS_MAGIC);
327c74a1cbbSAl Viro }
328c74a1cbbSAl Viro 
329c74a1cbbSAl Viro static struct vfsmount *sock_mnt __read_mostly;
330c74a1cbbSAl Viro 
331c74a1cbbSAl Viro static struct file_system_type sock_fs_type = {
332c74a1cbbSAl Viro 	.name =		"sockfs",
333c74a1cbbSAl Viro 	.mount =	sockfs_mount,
334c74a1cbbSAl Viro 	.kill_sb =	kill_anon_super,
335c74a1cbbSAl Viro };
336c74a1cbbSAl Viro 
3371da177e4SLinus Torvalds /*
3381da177e4SLinus Torvalds  *	Obtains the first available file descriptor and sets it up for use.
3391da177e4SLinus Torvalds  *
34039d8c1b6SDavid S. Miller  *	These functions create file structures and maps them to fd space
34139d8c1b6SDavid S. Miller  *	of the current process. On success it returns file descriptor
3421da177e4SLinus Torvalds  *	and file struct implicitly stored in sock->file.
3431da177e4SLinus Torvalds  *	Note that another thread may close file descriptor before we return
3441da177e4SLinus Torvalds  *	from this function. We use the fact that now we do not refer
3451da177e4SLinus Torvalds  *	to socket after mapping. If one day we will need it, this
3461da177e4SLinus Torvalds  *	function will increment ref. count on file by 1.
3471da177e4SLinus Torvalds  *
3481da177e4SLinus Torvalds  *	In any case returned fd MAY BE not valid!
3491da177e4SLinus Torvalds  *	This race condition is unavoidable
3501da177e4SLinus Torvalds  *	with shared fd spaces, we cannot solve it inside kernel,
3511da177e4SLinus Torvalds  *	but we take care of internal coherence yet.
3521da177e4SLinus Torvalds  */
3531da177e4SLinus Torvalds 
354aab174f0SLinus Torvalds struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)
3551da177e4SLinus Torvalds {
3567cbe66b6SAl Viro 	struct qstr name = { .name = "" };
3572c48b9c4SAl Viro 	struct path path;
3587cbe66b6SAl Viro 	struct file *file;
3591da177e4SLinus Torvalds 
360600e1779SMasatake YAMATO 	if (dname) {
361600e1779SMasatake YAMATO 		name.name = dname;
362600e1779SMasatake YAMATO 		name.len = strlen(name.name);
363600e1779SMasatake YAMATO 	} else if (sock->sk) {
364600e1779SMasatake YAMATO 		name.name = sock->sk->sk_prot_creator->name;
365600e1779SMasatake YAMATO 		name.len = strlen(name.name);
366600e1779SMasatake YAMATO 	}
3674b936885SNick Piggin 	path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name);
36828407630SAl Viro 	if (unlikely(!path.dentry))
36928407630SAl Viro 		return ERR_PTR(-ENOMEM);
3702c48b9c4SAl Viro 	path.mnt = mntget(sock_mnt);
37139d8c1b6SDavid S. Miller 
3722c48b9c4SAl Viro 	d_instantiate(path.dentry, SOCK_INODE(sock));
373cc3808f8SAl Viro 
3742c48b9c4SAl Viro 	file = alloc_file(&path, FMODE_READ | FMODE_WRITE,
375cc3808f8SAl Viro 		  &socket_file_ops);
376b5ffe634SViresh Kumar 	if (IS_ERR(file)) {
377cc3808f8SAl Viro 		/* drop dentry, keep inode */
378c5ef6035SDavid Howells 		ihold(d_inode(path.dentry));
3792c48b9c4SAl Viro 		path_put(&path);
38039b65252SAnatol Pomozov 		return file;
381cc3808f8SAl Viro 	}
3821da177e4SLinus Torvalds 
3831da177e4SLinus Torvalds 	sock->file = file;
38477d27200SUlrich Drepper 	file->f_flags = O_RDWR | (flags & O_NONBLOCK);
38507dc3f07SBenjamin LaHaise 	file->private_data = sock;
38628407630SAl Viro 	return file;
3871da177e4SLinus Torvalds }
38856b31d1cSAl Viro EXPORT_SYMBOL(sock_alloc_file);
3891da177e4SLinus Torvalds 
39056b31d1cSAl Viro static int sock_map_fd(struct socket *sock, int flags)
39139d8c1b6SDavid S. Miller {
39239d8c1b6SDavid S. Miller 	struct file *newfile;
39328407630SAl Viro 	int fd = get_unused_fd_flags(flags);
39428407630SAl Viro 	if (unlikely(fd < 0))
3951da177e4SLinus Torvalds 		return fd;
3961da177e4SLinus Torvalds 
397aab174f0SLinus Torvalds 	newfile = sock_alloc_file(sock, flags, NULL);
39828407630SAl Viro 	if (likely(!IS_ERR(newfile))) {
3991da177e4SLinus Torvalds 		fd_install(fd, newfile);
4001da177e4SLinus Torvalds 		return fd;
4011da177e4SLinus Torvalds 	}
40228407630SAl Viro 
40328407630SAl Viro 	put_unused_fd(fd);
40428407630SAl Viro 	return PTR_ERR(newfile);
4051da177e4SLinus Torvalds }
4061da177e4SLinus Torvalds 
407406a3c63SJohn Fastabend struct socket *sock_from_file(struct file *file, int *err)
4086cb153caSBenjamin LaHaise {
4096cb153caSBenjamin LaHaise 	if (file->f_op == &socket_file_ops)
4106cb153caSBenjamin LaHaise 		return file->private_data;	/* set in sock_map_fd */
4116cb153caSBenjamin LaHaise 
4126cb153caSBenjamin LaHaise 	*err = -ENOTSOCK;
4136cb153caSBenjamin LaHaise 	return NULL;
4146cb153caSBenjamin LaHaise }
415406a3c63SJohn Fastabend EXPORT_SYMBOL(sock_from_file);
4166cb153caSBenjamin LaHaise 
4171da177e4SLinus Torvalds /**
4181da177e4SLinus Torvalds  *	sockfd_lookup - Go from a file number to its socket slot
4191da177e4SLinus Torvalds  *	@fd: file handle
4201da177e4SLinus Torvalds  *	@err: pointer to an error code return
4211da177e4SLinus Torvalds  *
4221da177e4SLinus Torvalds  *	The file handle passed in is locked and the socket it is bound
4231da177e4SLinus Torvalds  *	too is returned. If an error occurs the err pointer is overwritten
4241da177e4SLinus Torvalds  *	with a negative errno code and NULL is returned. The function checks
4251da177e4SLinus Torvalds  *	for both invalid handles and passing a handle which is not a socket.
4261da177e4SLinus Torvalds  *
4271da177e4SLinus Torvalds  *	On a success the socket object pointer is returned.
4281da177e4SLinus Torvalds  */
4291da177e4SLinus Torvalds 
4301da177e4SLinus Torvalds struct socket *sockfd_lookup(int fd, int *err)
4311da177e4SLinus Torvalds {
4321da177e4SLinus Torvalds 	struct file *file;
4331da177e4SLinus Torvalds 	struct socket *sock;
4341da177e4SLinus Torvalds 
43589bddce5SStephen Hemminger 	file = fget(fd);
43689bddce5SStephen Hemminger 	if (!file) {
4371da177e4SLinus Torvalds 		*err = -EBADF;
4381da177e4SLinus Torvalds 		return NULL;
4391da177e4SLinus Torvalds 	}
44089bddce5SStephen Hemminger 
4416cb153caSBenjamin LaHaise 	sock = sock_from_file(file, err);
4426cb153caSBenjamin LaHaise 	if (!sock)
4431da177e4SLinus Torvalds 		fput(file);
4446cb153caSBenjamin LaHaise 	return sock;
4451da177e4SLinus Torvalds }
446c6d409cfSEric Dumazet EXPORT_SYMBOL(sockfd_lookup);
4471da177e4SLinus Torvalds 
4486cb153caSBenjamin LaHaise static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
4496cb153caSBenjamin LaHaise {
45000e188efSAl Viro 	struct fd f = fdget(fd);
4516cb153caSBenjamin LaHaise 	struct socket *sock;
4526cb153caSBenjamin LaHaise 
4533672558cSHua Zhong 	*err = -EBADF;
45400e188efSAl Viro 	if (f.file) {
45500e188efSAl Viro 		sock = sock_from_file(f.file, err);
45600e188efSAl Viro 		if (likely(sock)) {
45700e188efSAl Viro 			*fput_needed = f.flags;
4581da177e4SLinus Torvalds 			return sock;
45900e188efSAl Viro 		}
46000e188efSAl Viro 		fdput(f);
4616cb153caSBenjamin LaHaise 	}
4626cb153caSBenjamin LaHaise 	return NULL;
4631da177e4SLinus Torvalds }
4641da177e4SLinus Torvalds 
465600e1779SMasatake YAMATO #define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname"
466600e1779SMasatake YAMATO #define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX)
467600e1779SMasatake YAMATO #define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1)
468600e1779SMasatake YAMATO static ssize_t sockfs_getxattr(struct dentry *dentry,
469600e1779SMasatake YAMATO 			       const char *name, void *value, size_t size)
470600e1779SMasatake YAMATO {
471600e1779SMasatake YAMATO 	const char *proto_name;
472600e1779SMasatake YAMATO 	size_t proto_size;
473600e1779SMasatake YAMATO 	int error;
474600e1779SMasatake YAMATO 
475600e1779SMasatake YAMATO 	error = -ENODATA;
476600e1779SMasatake YAMATO 	if (!strncmp(name, XATTR_NAME_SOCKPROTONAME, XATTR_NAME_SOCKPROTONAME_LEN)) {
477600e1779SMasatake YAMATO 		proto_name = dentry->d_name.name;
478600e1779SMasatake YAMATO 		proto_size = strlen(proto_name);
479600e1779SMasatake YAMATO 
480600e1779SMasatake YAMATO 		if (value) {
481600e1779SMasatake YAMATO 			error = -ERANGE;
482600e1779SMasatake YAMATO 			if (proto_size + 1 > size)
483600e1779SMasatake YAMATO 				goto out;
484600e1779SMasatake YAMATO 
485600e1779SMasatake YAMATO 			strncpy(value, proto_name, proto_size + 1);
486600e1779SMasatake YAMATO 		}
487600e1779SMasatake YAMATO 		error = proto_size + 1;
488600e1779SMasatake YAMATO 	}
489600e1779SMasatake YAMATO 
490600e1779SMasatake YAMATO out:
491600e1779SMasatake YAMATO 	return error;
492600e1779SMasatake YAMATO }
493600e1779SMasatake YAMATO 
494600e1779SMasatake YAMATO static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer,
495600e1779SMasatake YAMATO 				size_t size)
496600e1779SMasatake YAMATO {
497600e1779SMasatake YAMATO 	ssize_t len;
498600e1779SMasatake YAMATO 	ssize_t used = 0;
499600e1779SMasatake YAMATO 
500c5ef6035SDavid Howells 	len = security_inode_listsecurity(d_inode(dentry), buffer, size);
501600e1779SMasatake YAMATO 	if (len < 0)
502600e1779SMasatake YAMATO 		return len;
503600e1779SMasatake YAMATO 	used += len;
504600e1779SMasatake YAMATO 	if (buffer) {
505600e1779SMasatake YAMATO 		if (size < used)
506600e1779SMasatake YAMATO 			return -ERANGE;
507600e1779SMasatake YAMATO 		buffer += len;
508600e1779SMasatake YAMATO 	}
509600e1779SMasatake YAMATO 
510600e1779SMasatake YAMATO 	len = (XATTR_NAME_SOCKPROTONAME_LEN + 1);
511600e1779SMasatake YAMATO 	used += len;
512600e1779SMasatake YAMATO 	if (buffer) {
513600e1779SMasatake YAMATO 		if (size < used)
514600e1779SMasatake YAMATO 			return -ERANGE;
515600e1779SMasatake YAMATO 		memcpy(buffer, XATTR_NAME_SOCKPROTONAME, len);
516600e1779SMasatake YAMATO 		buffer += len;
517600e1779SMasatake YAMATO 	}
518600e1779SMasatake YAMATO 
519600e1779SMasatake YAMATO 	return used;
520600e1779SMasatake YAMATO }
521600e1779SMasatake YAMATO 
522600e1779SMasatake YAMATO static const struct inode_operations sockfs_inode_ops = {
523600e1779SMasatake YAMATO 	.getxattr = sockfs_getxattr,
524600e1779SMasatake YAMATO 	.listxattr = sockfs_listxattr,
525600e1779SMasatake YAMATO };
526600e1779SMasatake YAMATO 
5271da177e4SLinus Torvalds /**
5281da177e4SLinus Torvalds  *	sock_alloc	-	allocate a socket
5291da177e4SLinus Torvalds  *
5301da177e4SLinus Torvalds  *	Allocate a new inode and socket object. The two are bound together
5311da177e4SLinus Torvalds  *	and initialised. The socket is then returned. If we are out of inodes
5321da177e4SLinus Torvalds  *	NULL is returned.
5331da177e4SLinus Torvalds  */
5341da177e4SLinus Torvalds 
5351da177e4SLinus Torvalds static struct socket *sock_alloc(void)
5361da177e4SLinus Torvalds {
5371da177e4SLinus Torvalds 	struct inode *inode;
5381da177e4SLinus Torvalds 	struct socket *sock;
5391da177e4SLinus Torvalds 
540a209dfc7SEric Dumazet 	inode = new_inode_pseudo(sock_mnt->mnt_sb);
5411da177e4SLinus Torvalds 	if (!inode)
5421da177e4SLinus Torvalds 		return NULL;
5431da177e4SLinus Torvalds 
5441da177e4SLinus Torvalds 	sock = SOCKET_I(inode);
5451da177e4SLinus Torvalds 
54629a020d3SEric Dumazet 	kmemcheck_annotate_bitfield(sock, type);
54785fe4025SChristoph Hellwig 	inode->i_ino = get_next_ino();
5481da177e4SLinus Torvalds 	inode->i_mode = S_IFSOCK | S_IRWXUGO;
5498192b0c4SDavid Howells 	inode->i_uid = current_fsuid();
5508192b0c4SDavid Howells 	inode->i_gid = current_fsgid();
551600e1779SMasatake YAMATO 	inode->i_op = &sockfs_inode_ops;
5521da177e4SLinus Torvalds 
55319e8d69cSAlex Shi 	this_cpu_add(sockets_in_use, 1);
5541da177e4SLinus Torvalds 	return sock;
5551da177e4SLinus Torvalds }
5561da177e4SLinus Torvalds 
5571da177e4SLinus Torvalds /**
5581da177e4SLinus Torvalds  *	sock_release	-	close a socket
5591da177e4SLinus Torvalds  *	@sock: socket to close
5601da177e4SLinus Torvalds  *
5611da177e4SLinus Torvalds  *	The socket is released from the protocol stack if it has a release
5621da177e4SLinus Torvalds  *	callback, and the inode is then released if the socket is bound to
5631da177e4SLinus Torvalds  *	an inode not a file.
5641da177e4SLinus Torvalds  */
5651da177e4SLinus Torvalds 
5661da177e4SLinus Torvalds void sock_release(struct socket *sock)
5671da177e4SLinus Torvalds {
5681da177e4SLinus Torvalds 	if (sock->ops) {
5691da177e4SLinus Torvalds 		struct module *owner = sock->ops->owner;
5701da177e4SLinus Torvalds 
5711da177e4SLinus Torvalds 		sock->ops->release(sock);
5721da177e4SLinus Torvalds 		sock->ops = NULL;
5731da177e4SLinus Torvalds 		module_put(owner);
5741da177e4SLinus Torvalds 	}
5751da177e4SLinus Torvalds 
576eaefd110SEric Dumazet 	if (rcu_dereference_protected(sock->wq, 1)->fasync_list)
5773410f22eSYang Yingliang 		pr_err("%s: fasync list not empty!\n", __func__);
5781da177e4SLinus Torvalds 
57919e8d69cSAlex Shi 	this_cpu_sub(sockets_in_use, 1);
5801da177e4SLinus Torvalds 	if (!sock->file) {
5811da177e4SLinus Torvalds 		iput(SOCK_INODE(sock));
5821da177e4SLinus Torvalds 		return;
5831da177e4SLinus Torvalds 	}
5841da177e4SLinus Torvalds 	sock->file = NULL;
5851da177e4SLinus Torvalds }
586c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_release);
5871da177e4SLinus Torvalds 
58867cc0d40SWillem de Bruijn void __sock_tx_timestamp(const struct sock *sk, __u8 *tx_flags)
58920d49473SPatrick Ohly {
590140c55d4SEric Dumazet 	u8 flags = *tx_flags;
591140c55d4SEric Dumazet 
592b9f40e21SWillem de Bruijn 	if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_HARDWARE)
593140c55d4SEric Dumazet 		flags |= SKBTX_HW_TSTAMP;
594140c55d4SEric Dumazet 
595b9f40e21SWillem de Bruijn 	if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_SOFTWARE)
596140c55d4SEric Dumazet 		flags |= SKBTX_SW_TSTAMP;
597140c55d4SEric Dumazet 
598e7fd2885SWillem de Bruijn 	if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_SCHED)
599140c55d4SEric Dumazet 		flags |= SKBTX_SCHED_TSTAMP;
600140c55d4SEric Dumazet 
601e1c8a607SWillem de Bruijn 	if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_ACK)
602140c55d4SEric Dumazet 		flags |= SKBTX_ACK_TSTAMP;
603e7fd2885SWillem de Bruijn 
604140c55d4SEric Dumazet 	*tx_flags = flags;
60520d49473SPatrick Ohly }
60667cc0d40SWillem de Bruijn EXPORT_SYMBOL(__sock_tx_timestamp);
60720d49473SPatrick Ohly 
608d8725c86SAl Viro static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg)
6091da177e4SLinus Torvalds {
61001e97e65SAl Viro 	int ret = sock->ops->sendmsg(sock, msg, msg_data_left(msg));
611d8725c86SAl Viro 	BUG_ON(ret == -EIOCBQUEUED);
612d8725c86SAl Viro 	return ret;
6131da177e4SLinus Torvalds }
6140cf00c6fSGu Zheng 
615d8725c86SAl Viro int sock_sendmsg(struct socket *sock, struct msghdr *msg)
6160cf00c6fSGu Zheng {
617d8725c86SAl Viro 	int err = security_socket_sendmsg(sock, msg,
61801e97e65SAl Viro 					  msg_data_left(msg));
6191b784140SYing Xue 
620d8725c86SAl Viro 	return err ?: sock_sendmsg_nosec(sock, msg);
6210cf00c6fSGu Zheng }
622c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_sendmsg);
6231da177e4SLinus Torvalds 
6241da177e4SLinus Torvalds int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
6251da177e4SLinus Torvalds 		   struct kvec *vec, size_t num, size_t size)
6261da177e4SLinus Torvalds {
6276aa24814SAl Viro 	iov_iter_kvec(&msg->msg_iter, WRITE | ITER_KVEC, vec, num, size);
628d8725c86SAl Viro 	return sock_sendmsg(sock, msg);
6291da177e4SLinus Torvalds }
630c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendmsg);
6311da177e4SLinus Torvalds 
63292f37fd2SEric Dumazet /*
63392f37fd2SEric Dumazet  * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
63492f37fd2SEric Dumazet  */
63592f37fd2SEric Dumazet void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
63692f37fd2SEric Dumazet 	struct sk_buff *skb)
63792f37fd2SEric Dumazet {
63820d49473SPatrick Ohly 	int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
639f24b9be5SWillem de Bruijn 	struct scm_timestamping tss;
64020d49473SPatrick Ohly 	int empty = 1;
64120d49473SPatrick Ohly 	struct skb_shared_hwtstamps *shhwtstamps =
64220d49473SPatrick Ohly 		skb_hwtstamps(skb);
64392f37fd2SEric Dumazet 
64420d49473SPatrick Ohly 	/* Race occurred between timestamp enabling and packet
64520d49473SPatrick Ohly 	   receiving.  Fill in the current time for now. */
64620d49473SPatrick Ohly 	if (need_software_tstamp && skb->tstamp.tv64 == 0)
64720d49473SPatrick Ohly 		__net_timestamp(skb);
64820d49473SPatrick Ohly 
64920d49473SPatrick Ohly 	if (need_software_tstamp) {
65092f37fd2SEric Dumazet 		if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
65192f37fd2SEric Dumazet 			struct timeval tv;
65220d49473SPatrick Ohly 			skb_get_timestamp(skb, &tv);
65320d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP,
65420d49473SPatrick Ohly 				 sizeof(tv), &tv);
65592f37fd2SEric Dumazet 		} else {
656f24b9be5SWillem de Bruijn 			struct timespec ts;
657f24b9be5SWillem de Bruijn 			skb_get_timestampns(skb, &ts);
65820d49473SPatrick Ohly 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS,
659f24b9be5SWillem de Bruijn 				 sizeof(ts), &ts);
66092f37fd2SEric Dumazet 		}
66192f37fd2SEric Dumazet 	}
66292f37fd2SEric Dumazet 
663f24b9be5SWillem de Bruijn 	memset(&tss, 0, sizeof(tss));
664c199105dSWillem de Bruijn 	if ((sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE) &&
665f24b9be5SWillem de Bruijn 	    ktime_to_timespec_cond(skb->tstamp, tss.ts + 0))
66620d49473SPatrick Ohly 		empty = 0;
6674d276eb6SWillem de Bruijn 	if (shhwtstamps &&
668b9f40e21SWillem de Bruijn 	    (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
669f24b9be5SWillem de Bruijn 	    ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2))
67020d49473SPatrick Ohly 		empty = 0;
67120d49473SPatrick Ohly 	if (!empty)
67220d49473SPatrick Ohly 		put_cmsg(msg, SOL_SOCKET,
673f24b9be5SWillem de Bruijn 			 SCM_TIMESTAMPING, sizeof(tss), &tss);
67420d49473SPatrick Ohly }
6757c81fd8bSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
6767c81fd8bSArnaldo Carvalho de Melo 
6776e3e939fSJohannes Berg void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
6786e3e939fSJohannes Berg 	struct sk_buff *skb)
6796e3e939fSJohannes Berg {
6806e3e939fSJohannes Berg 	int ack;
6816e3e939fSJohannes Berg 
6826e3e939fSJohannes Berg 	if (!sock_flag(sk, SOCK_WIFI_STATUS))
6836e3e939fSJohannes Berg 		return;
6846e3e939fSJohannes Berg 	if (!skb->wifi_acked_valid)
6856e3e939fSJohannes Berg 		return;
6866e3e939fSJohannes Berg 
6876e3e939fSJohannes Berg 	ack = skb->wifi_acked;
6886e3e939fSJohannes Berg 
6896e3e939fSJohannes Berg 	put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack);
6906e3e939fSJohannes Berg }
6916e3e939fSJohannes Berg EXPORT_SYMBOL_GPL(__sock_recv_wifi_status);
6926e3e939fSJohannes Berg 
69311165f14Sstephen hemminger static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk,
69411165f14Sstephen hemminger 				   struct sk_buff *skb)
6953b885787SNeil Horman {
696744d5a3eSEyal Birger 	if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && SOCK_SKB_CB(skb)->dropcount)
6973b885787SNeil Horman 		put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL,
698744d5a3eSEyal Birger 			sizeof(__u32), &SOCK_SKB_CB(skb)->dropcount);
6993b885787SNeil Horman }
7003b885787SNeil Horman 
701767dd033SEric Dumazet void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
7023b885787SNeil Horman 	struct sk_buff *skb)
7033b885787SNeil Horman {
7043b885787SNeil Horman 	sock_recv_timestamp(msg, sk, skb);
7053b885787SNeil Horman 	sock_recv_drops(msg, sk, skb);
7063b885787SNeil Horman }
707767dd033SEric Dumazet EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops);
7083b885787SNeil Horman 
7091b784140SYing Xue static inline int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
7101b784140SYing Xue 				     size_t size, int flags)
7111da177e4SLinus Torvalds {
7121b784140SYing Xue 	return sock->ops->recvmsg(sock, msg, size, flags);
7131da177e4SLinus Torvalds }
7141da177e4SLinus Torvalds 
7151b784140SYing Xue int sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
7161b784140SYing Xue 		 int flags)
717a2e27255SArnaldo Carvalho de Melo {
718a2e27255SArnaldo Carvalho de Melo 	int err = security_socket_recvmsg(sock, msg, size, flags);
719a2e27255SArnaldo Carvalho de Melo 
7201b784140SYing Xue 	return err ?: sock_recvmsg_nosec(sock, msg, size, flags);
7211da177e4SLinus Torvalds }
722c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_recvmsg);
7231da177e4SLinus Torvalds 
724c1249c0aSMartin Lucina /**
725c1249c0aSMartin Lucina  * kernel_recvmsg - Receive a message from a socket (kernel space)
726c1249c0aSMartin Lucina  * @sock:       The socket to receive the message from
727c1249c0aSMartin Lucina  * @msg:        Received message
728c1249c0aSMartin Lucina  * @vec:        Input s/g array for message data
729c1249c0aSMartin Lucina  * @num:        Size of input s/g array
730c1249c0aSMartin Lucina  * @size:       Number of bytes to read
731c1249c0aSMartin Lucina  * @flags:      Message flags (MSG_DONTWAIT, etc...)
732c1249c0aSMartin Lucina  *
733c1249c0aSMartin Lucina  * On return the msg structure contains the scatter/gather array passed in the
734c1249c0aSMartin Lucina  * vec argument. The array is modified so that it consists of the unfilled
735c1249c0aSMartin Lucina  * portion of the original array.
736c1249c0aSMartin Lucina  *
737c1249c0aSMartin Lucina  * The returned value is the total number of bytes received, or an error.
738c1249c0aSMartin Lucina  */
7391da177e4SLinus Torvalds int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
74089bddce5SStephen Hemminger 		   struct kvec *vec, size_t num, size_t size, int flags)
7411da177e4SLinus Torvalds {
7421da177e4SLinus Torvalds 	mm_segment_t oldfs = get_fs();
7431da177e4SLinus Torvalds 	int result;
7441da177e4SLinus Torvalds 
7456aa24814SAl Viro 	iov_iter_kvec(&msg->msg_iter, READ | ITER_KVEC, vec, num, size);
7461da177e4SLinus Torvalds 	set_fs(KERNEL_DS);
7471da177e4SLinus Torvalds 	result = sock_recvmsg(sock, msg, size, flags);
7481da177e4SLinus Torvalds 	set_fs(oldfs);
7491da177e4SLinus Torvalds 	return result;
7501da177e4SLinus Torvalds }
751c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_recvmsg);
7521da177e4SLinus Torvalds 
75320380731SArnaldo Carvalho de Melo static ssize_t sock_sendpage(struct file *file, struct page *page,
7541da177e4SLinus Torvalds 			     int offset, size_t size, loff_t *ppos, int more)
7551da177e4SLinus Torvalds {
7561da177e4SLinus Torvalds 	struct socket *sock;
7571da177e4SLinus Torvalds 	int flags;
7581da177e4SLinus Torvalds 
759b69aee04SEric Dumazet 	sock = file->private_data;
7601da177e4SLinus Torvalds 
76135f9c09fSEric Dumazet 	flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
76235f9c09fSEric Dumazet 	/* more is a combination of MSG_MORE and MSG_SENDPAGE_NOTLAST */
76335f9c09fSEric Dumazet 	flags |= more;
7641da177e4SLinus Torvalds 
765e6949583SLinus Torvalds 	return kernel_sendpage(sock, page, offset, size, flags);
7661da177e4SLinus Torvalds }
7671da177e4SLinus Torvalds 
7689c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
7699c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
7709c55e01cSJens Axboe 				unsigned int flags)
7719c55e01cSJens Axboe {
7729c55e01cSJens Axboe 	struct socket *sock = file->private_data;
7739c55e01cSJens Axboe 
774997b37daSRémi Denis-Courmont 	if (unlikely(!sock->ops->splice_read))
775997b37daSRémi Denis-Courmont 		return -EINVAL;
776997b37daSRémi Denis-Courmont 
7779c55e01cSJens Axboe 	return sock->ops->splice_read(sock, ppos, pipe, len, flags);
7789c55e01cSJens Axboe }
7799c55e01cSJens Axboe 
7808ae5e030SAl Viro static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to)
781ce1d4d3eSChristoph Hellwig {
7826d652330SAl Viro 	struct file *file = iocb->ki_filp;
7836d652330SAl Viro 	struct socket *sock = file->private_data;
7840345f931Stadeusz.struk@intel.com 	struct msghdr msg = {.msg_iter = *to,
7850345f931Stadeusz.struk@intel.com 			     .msg_iocb = iocb};
7868ae5e030SAl Viro 	ssize_t res;
787ce1d4d3eSChristoph Hellwig 
7888ae5e030SAl Viro 	if (file->f_flags & O_NONBLOCK)
7898ae5e030SAl Viro 		msg.msg_flags = MSG_DONTWAIT;
7908ae5e030SAl Viro 
7918ae5e030SAl Viro 	if (iocb->ki_pos != 0)
792ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
793027445c3SBadari Pulavarty 
79466ee59afSChristoph Hellwig 	if (!iov_iter_count(to))	/* Match SYS5 behaviour */
795ce1d4d3eSChristoph Hellwig 		return 0;
796ce1d4d3eSChristoph Hellwig 
797237dae88SAl Viro 	res = sock_recvmsg(sock, &msg, iov_iter_count(to), msg.msg_flags);
7988ae5e030SAl Viro 	*to = msg.msg_iter;
7998ae5e030SAl Viro 	return res;
800ce1d4d3eSChristoph Hellwig }
801ce1d4d3eSChristoph Hellwig 
8028ae5e030SAl Viro static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from)
8031da177e4SLinus Torvalds {
8046d652330SAl Viro 	struct file *file = iocb->ki_filp;
8056d652330SAl Viro 	struct socket *sock = file->private_data;
8060345f931Stadeusz.struk@intel.com 	struct msghdr msg = {.msg_iter = *from,
8070345f931Stadeusz.struk@intel.com 			     .msg_iocb = iocb};
8088ae5e030SAl Viro 	ssize_t res;
8091da177e4SLinus Torvalds 
8108ae5e030SAl Viro 	if (iocb->ki_pos != 0)
811ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
812027445c3SBadari Pulavarty 
8138ae5e030SAl Viro 	if (file->f_flags & O_NONBLOCK)
8148ae5e030SAl Viro 		msg.msg_flags = MSG_DONTWAIT;
8158ae5e030SAl Viro 
8166d652330SAl Viro 	if (sock->type == SOCK_SEQPACKET)
8176d652330SAl Viro 		msg.msg_flags |= MSG_EOR;
8186d652330SAl Viro 
819d8725c86SAl Viro 	res = sock_sendmsg(sock, &msg);
8208ae5e030SAl Viro 	*from = msg.msg_iter;
8218ae5e030SAl Viro 	return res;
8221da177e4SLinus Torvalds }
8231da177e4SLinus Torvalds 
8241da177e4SLinus Torvalds /*
8251da177e4SLinus Torvalds  * Atomic setting of ioctl hooks to avoid race
8261da177e4SLinus Torvalds  * with module unload.
8271da177e4SLinus Torvalds  */
8281da177e4SLinus Torvalds 
8294a3e2f71SArjan van de Ven static DEFINE_MUTEX(br_ioctl_mutex);
830c6d409cfSEric Dumazet static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg);
8311da177e4SLinus Torvalds 
832881d966bSEric W. Biederman void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *))
8331da177e4SLinus Torvalds {
8344a3e2f71SArjan van de Ven 	mutex_lock(&br_ioctl_mutex);
8351da177e4SLinus Torvalds 	br_ioctl_hook = hook;
8364a3e2f71SArjan van de Ven 	mutex_unlock(&br_ioctl_mutex);
8371da177e4SLinus Torvalds }
8381da177e4SLinus Torvalds EXPORT_SYMBOL(brioctl_set);
8391da177e4SLinus Torvalds 
8404a3e2f71SArjan van de Ven static DEFINE_MUTEX(vlan_ioctl_mutex);
841881d966bSEric W. Biederman static int (*vlan_ioctl_hook) (struct net *, void __user *arg);
8421da177e4SLinus Torvalds 
843881d966bSEric W. Biederman void vlan_ioctl_set(int (*hook) (struct net *, void __user *))
8441da177e4SLinus Torvalds {
8454a3e2f71SArjan van de Ven 	mutex_lock(&vlan_ioctl_mutex);
8461da177e4SLinus Torvalds 	vlan_ioctl_hook = hook;
8474a3e2f71SArjan van de Ven 	mutex_unlock(&vlan_ioctl_mutex);
8481da177e4SLinus Torvalds }
8491da177e4SLinus Torvalds EXPORT_SYMBOL(vlan_ioctl_set);
8501da177e4SLinus Torvalds 
8514a3e2f71SArjan van de Ven static DEFINE_MUTEX(dlci_ioctl_mutex);
8521da177e4SLinus Torvalds static int (*dlci_ioctl_hook) (unsigned int, void __user *);
8531da177e4SLinus Torvalds 
8541da177e4SLinus Torvalds void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
8551da177e4SLinus Torvalds {
8564a3e2f71SArjan van de Ven 	mutex_lock(&dlci_ioctl_mutex);
8571da177e4SLinus Torvalds 	dlci_ioctl_hook = hook;
8584a3e2f71SArjan van de Ven 	mutex_unlock(&dlci_ioctl_mutex);
8591da177e4SLinus Torvalds }
8601da177e4SLinus Torvalds EXPORT_SYMBOL(dlci_ioctl_set);
8611da177e4SLinus Torvalds 
8626b96018bSArnd Bergmann static long sock_do_ioctl(struct net *net, struct socket *sock,
8636b96018bSArnd Bergmann 				 unsigned int cmd, unsigned long arg)
8646b96018bSArnd Bergmann {
8656b96018bSArnd Bergmann 	int err;
8666b96018bSArnd Bergmann 	void __user *argp = (void __user *)arg;
8676b96018bSArnd Bergmann 
8686b96018bSArnd Bergmann 	err = sock->ops->ioctl(sock, cmd, arg);
8696b96018bSArnd Bergmann 
8706b96018bSArnd Bergmann 	/*
8716b96018bSArnd Bergmann 	 * If this ioctl is unknown try to hand it down
8726b96018bSArnd Bergmann 	 * to the NIC driver.
8736b96018bSArnd Bergmann 	 */
8746b96018bSArnd Bergmann 	if (err == -ENOIOCTLCMD)
8756b96018bSArnd Bergmann 		err = dev_ioctl(net, cmd, argp);
8766b96018bSArnd Bergmann 
8776b96018bSArnd Bergmann 	return err;
8786b96018bSArnd Bergmann }
8796b96018bSArnd Bergmann 
8801da177e4SLinus Torvalds /*
8811da177e4SLinus Torvalds  *	With an ioctl, arg may well be a user mode pointer, but we don't know
8821da177e4SLinus Torvalds  *	what to do with it - that's up to the protocol still.
8831da177e4SLinus Torvalds  */
8841da177e4SLinus Torvalds 
8851da177e4SLinus Torvalds static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
8861da177e4SLinus Torvalds {
8871da177e4SLinus Torvalds 	struct socket *sock;
888881d966bSEric W. Biederman 	struct sock *sk;
8891da177e4SLinus Torvalds 	void __user *argp = (void __user *)arg;
8901da177e4SLinus Torvalds 	int pid, err;
891881d966bSEric W. Biederman 	struct net *net;
8921da177e4SLinus Torvalds 
893b69aee04SEric Dumazet 	sock = file->private_data;
894881d966bSEric W. Biederman 	sk = sock->sk;
8953b1e0a65SYOSHIFUJI Hideaki 	net = sock_net(sk);
8961da177e4SLinus Torvalds 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
897881d966bSEric W. Biederman 		err = dev_ioctl(net, cmd, argp);
8981da177e4SLinus Torvalds 	} else
8993d23e349SJohannes Berg #ifdef CONFIG_WEXT_CORE
9001da177e4SLinus Torvalds 	if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
901881d966bSEric W. Biederman 		err = dev_ioctl(net, cmd, argp);
9021da177e4SLinus Torvalds 	} else
9033d23e349SJohannes Berg #endif
9041da177e4SLinus Torvalds 		switch (cmd) {
9051da177e4SLinus Torvalds 		case FIOSETOWN:
9061da177e4SLinus Torvalds 		case SIOCSPGRP:
9071da177e4SLinus Torvalds 			err = -EFAULT;
9081da177e4SLinus Torvalds 			if (get_user(pid, (int __user *)argp))
9091da177e4SLinus Torvalds 				break;
910e0b93eddSJeff Layton 			f_setown(sock->file, pid, 1);
911e0b93eddSJeff Layton 			err = 0;
9121da177e4SLinus Torvalds 			break;
9131da177e4SLinus Torvalds 		case FIOGETOWN:
9141da177e4SLinus Torvalds 		case SIOCGPGRP:
915609d7fa9SEric W. Biederman 			err = put_user(f_getown(sock->file),
91689bddce5SStephen Hemminger 				       (int __user *)argp);
9171da177e4SLinus Torvalds 			break;
9181da177e4SLinus Torvalds 		case SIOCGIFBR:
9191da177e4SLinus Torvalds 		case SIOCSIFBR:
9201da177e4SLinus Torvalds 		case SIOCBRADDBR:
9211da177e4SLinus Torvalds 		case SIOCBRDELBR:
9221da177e4SLinus Torvalds 			err = -ENOPKG;
9231da177e4SLinus Torvalds 			if (!br_ioctl_hook)
9241da177e4SLinus Torvalds 				request_module("bridge");
9251da177e4SLinus Torvalds 
9264a3e2f71SArjan van de Ven 			mutex_lock(&br_ioctl_mutex);
9271da177e4SLinus Torvalds 			if (br_ioctl_hook)
928881d966bSEric W. Biederman 				err = br_ioctl_hook(net, cmd, argp);
9294a3e2f71SArjan van de Ven 			mutex_unlock(&br_ioctl_mutex);
9301da177e4SLinus Torvalds 			break;
9311da177e4SLinus Torvalds 		case SIOCGIFVLAN:
9321da177e4SLinus Torvalds 		case SIOCSIFVLAN:
9331da177e4SLinus Torvalds 			err = -ENOPKG;
9341da177e4SLinus Torvalds 			if (!vlan_ioctl_hook)
9351da177e4SLinus Torvalds 				request_module("8021q");
9361da177e4SLinus Torvalds 
9374a3e2f71SArjan van de Ven 			mutex_lock(&vlan_ioctl_mutex);
9381da177e4SLinus Torvalds 			if (vlan_ioctl_hook)
939881d966bSEric W. Biederman 				err = vlan_ioctl_hook(net, argp);
9404a3e2f71SArjan van de Ven 			mutex_unlock(&vlan_ioctl_mutex);
9411da177e4SLinus Torvalds 			break;
9421da177e4SLinus Torvalds 		case SIOCADDDLCI:
9431da177e4SLinus Torvalds 		case SIOCDELDLCI:
9441da177e4SLinus Torvalds 			err = -ENOPKG;
9451da177e4SLinus Torvalds 			if (!dlci_ioctl_hook)
9461da177e4SLinus Torvalds 				request_module("dlci");
9471da177e4SLinus Torvalds 
9484a3e2f71SArjan van de Ven 			mutex_lock(&dlci_ioctl_mutex);
9497512cbf6SPavel Emelyanov 			if (dlci_ioctl_hook)
9501da177e4SLinus Torvalds 				err = dlci_ioctl_hook(cmd, argp);
9514a3e2f71SArjan van de Ven 			mutex_unlock(&dlci_ioctl_mutex);
9521da177e4SLinus Torvalds 			break;
9531da177e4SLinus Torvalds 		default:
9546b96018bSArnd Bergmann 			err = sock_do_ioctl(net, sock, cmd, arg);
9551da177e4SLinus Torvalds 			break;
9561da177e4SLinus Torvalds 		}
9571da177e4SLinus Torvalds 	return err;
9581da177e4SLinus Torvalds }
9591da177e4SLinus Torvalds 
9601da177e4SLinus Torvalds int sock_create_lite(int family, int type, int protocol, struct socket **res)
9611da177e4SLinus Torvalds {
9621da177e4SLinus Torvalds 	int err;
9631da177e4SLinus Torvalds 	struct socket *sock = NULL;
9641da177e4SLinus Torvalds 
9651da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, 1);
9661da177e4SLinus Torvalds 	if (err)
9671da177e4SLinus Torvalds 		goto out;
9681da177e4SLinus Torvalds 
9691da177e4SLinus Torvalds 	sock = sock_alloc();
9701da177e4SLinus Torvalds 	if (!sock) {
9711da177e4SLinus Torvalds 		err = -ENOMEM;
9721da177e4SLinus Torvalds 		goto out;
9731da177e4SLinus Torvalds 	}
9741da177e4SLinus Torvalds 
9751da177e4SLinus Torvalds 	sock->type = type;
9767420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, 1);
9777420ed23SVenkat Yekkirala 	if (err)
9787420ed23SVenkat Yekkirala 		goto out_release;
9797420ed23SVenkat Yekkirala 
9801da177e4SLinus Torvalds out:
9811da177e4SLinus Torvalds 	*res = sock;
9821da177e4SLinus Torvalds 	return err;
9837420ed23SVenkat Yekkirala out_release:
9847420ed23SVenkat Yekkirala 	sock_release(sock);
9857420ed23SVenkat Yekkirala 	sock = NULL;
9867420ed23SVenkat Yekkirala 	goto out;
9871da177e4SLinus Torvalds }
988c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_lite);
9891da177e4SLinus Torvalds 
9901da177e4SLinus Torvalds /* No kernel lock held - perfect */
9911da177e4SLinus Torvalds static unsigned int sock_poll(struct file *file, poll_table *wait)
9921da177e4SLinus Torvalds {
993cbf55001SEliezer Tamir 	unsigned int busy_flag = 0;
9941da177e4SLinus Torvalds 	struct socket *sock;
9951da177e4SLinus Torvalds 
9961da177e4SLinus Torvalds 	/*
9971da177e4SLinus Torvalds 	 *      We can't return errors to poll, so it's either yes or no.
9981da177e4SLinus Torvalds 	 */
999b69aee04SEric Dumazet 	sock = file->private_data;
10002d48d67fSEliezer Tamir 
1001cbf55001SEliezer Tamir 	if (sk_can_busy_loop(sock->sk)) {
10022d48d67fSEliezer Tamir 		/* this socket can poll_ll so tell the system call */
1003cbf55001SEliezer Tamir 		busy_flag = POLL_BUSY_LOOP;
10042d48d67fSEliezer Tamir 
10052d48d67fSEliezer Tamir 		/* once, only if requested by syscall */
1006cbf55001SEliezer Tamir 		if (wait && (wait->_key & POLL_BUSY_LOOP))
1007cbf55001SEliezer Tamir 			sk_busy_loop(sock->sk, 1);
10082d48d67fSEliezer Tamir 	}
10092d48d67fSEliezer Tamir 
1010cbf55001SEliezer Tamir 	return busy_flag | sock->ops->poll(file, sock, wait);
10111da177e4SLinus Torvalds }
10121da177e4SLinus Torvalds 
10131da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma)
10141da177e4SLinus Torvalds {
1015b69aee04SEric Dumazet 	struct socket *sock = file->private_data;
10161da177e4SLinus Torvalds 
10171da177e4SLinus Torvalds 	return sock->ops->mmap(file, sock, vma);
10181da177e4SLinus Torvalds }
10191da177e4SLinus Torvalds 
102020380731SArnaldo Carvalho de Melo static int sock_close(struct inode *inode, struct file *filp)
10211da177e4SLinus Torvalds {
10221da177e4SLinus Torvalds 	sock_release(SOCKET_I(inode));
10231da177e4SLinus Torvalds 	return 0;
10241da177e4SLinus Torvalds }
10251da177e4SLinus Torvalds 
10261da177e4SLinus Torvalds /*
10271da177e4SLinus Torvalds  *	Update the socket async list
10281da177e4SLinus Torvalds  *
10291da177e4SLinus Torvalds  *	Fasync_list locking strategy.
10301da177e4SLinus Torvalds  *
10311da177e4SLinus Torvalds  *	1. fasync_list is modified only under process context socket lock
10321da177e4SLinus Torvalds  *	   i.e. under semaphore.
10331da177e4SLinus Torvalds  *	2. fasync_list is used under read_lock(&sk->sk_callback_lock)
1034989a2979SEric Dumazet  *	   or under socket lock
10351da177e4SLinus Torvalds  */
10361da177e4SLinus Torvalds 
10371da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on)
10381da177e4SLinus Torvalds {
1039989a2979SEric Dumazet 	struct socket *sock = filp->private_data;
1040989a2979SEric Dumazet 	struct sock *sk = sock->sk;
1041eaefd110SEric Dumazet 	struct socket_wq *wq;
10421da177e4SLinus Torvalds 
1043989a2979SEric Dumazet 	if (sk == NULL)
10441da177e4SLinus Torvalds 		return -EINVAL;
10451da177e4SLinus Torvalds 
10461da177e4SLinus Torvalds 	lock_sock(sk);
1047eaefd110SEric Dumazet 	wq = rcu_dereference_protected(sock->wq, sock_owned_by_user(sk));
1048eaefd110SEric Dumazet 	fasync_helper(fd, filp, on, &wq->fasync_list);
10491da177e4SLinus Torvalds 
1050eaefd110SEric Dumazet 	if (!wq->fasync_list)
1051bcdce719SEric Dumazet 		sock_reset_flag(sk, SOCK_FASYNC);
1052989a2979SEric Dumazet 	else
1053989a2979SEric Dumazet 		sock_set_flag(sk, SOCK_FASYNC);
10541da177e4SLinus Torvalds 
1055989a2979SEric Dumazet 	release_sock(sk);
10561da177e4SLinus Torvalds 	return 0;
10571da177e4SLinus Torvalds }
10581da177e4SLinus Torvalds 
1059ceb5d58bSEric Dumazet /* This function may be called only under rcu_lock */
10601da177e4SLinus Torvalds 
1061ceb5d58bSEric Dumazet int sock_wake_async(struct socket_wq *wq, int how, int band)
10621da177e4SLinus Torvalds {
1063ceb5d58bSEric Dumazet 	if (!wq || !wq->fasync_list)
1064ceb5d58bSEric Dumazet 		return -1;
106543815482SEric Dumazet 
106689bddce5SStephen Hemminger 	switch (how) {
10678d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_WAITD:
1068ceb5d58bSEric Dumazet 		if (test_bit(SOCKWQ_ASYNC_WAITDATA, &wq->flags))
10691da177e4SLinus Torvalds 			break;
10701da177e4SLinus Torvalds 		goto call_kill;
10718d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_SPACE:
1072ceb5d58bSEric Dumazet 		if (!test_and_clear_bit(SOCKWQ_ASYNC_NOSPACE, &wq->flags))
10731da177e4SLinus Torvalds 			break;
10741da177e4SLinus Torvalds 		/* fall through */
10758d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_IO:
10761da177e4SLinus Torvalds call_kill:
107743815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGIO, band);
10781da177e4SLinus Torvalds 		break;
10798d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_URG:
108043815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGURG, band);
10811da177e4SLinus Torvalds 	}
1082ceb5d58bSEric Dumazet 
10831da177e4SLinus Torvalds 	return 0;
10841da177e4SLinus Torvalds }
1085c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_wake_async);
10861da177e4SLinus Torvalds 
1087721db93aSPavel Emelyanov int __sock_create(struct net *net, int family, int type, int protocol,
108889bddce5SStephen Hemminger 			 struct socket **res, int kern)
10891da177e4SLinus Torvalds {
10901da177e4SLinus Torvalds 	int err;
10911da177e4SLinus Torvalds 	struct socket *sock;
109255737fdaSStephen Hemminger 	const struct net_proto_family *pf;
10931da177e4SLinus Torvalds 
10941da177e4SLinus Torvalds 	/*
10951da177e4SLinus Torvalds 	 *      Check protocol is in range
10961da177e4SLinus Torvalds 	 */
10971da177e4SLinus Torvalds 	if (family < 0 || family >= NPROTO)
10981da177e4SLinus Torvalds 		return -EAFNOSUPPORT;
10991da177e4SLinus Torvalds 	if (type < 0 || type >= SOCK_MAX)
11001da177e4SLinus Torvalds 		return -EINVAL;
11011da177e4SLinus Torvalds 
11021da177e4SLinus Torvalds 	/* Compatibility.
11031da177e4SLinus Torvalds 
11041da177e4SLinus Torvalds 	   This uglymoron is moved from INET layer to here to avoid
11051da177e4SLinus Torvalds 	   deadlock in module load.
11061da177e4SLinus Torvalds 	 */
11071da177e4SLinus Torvalds 	if (family == PF_INET && type == SOCK_PACKET) {
11081da177e4SLinus Torvalds 		static int warned;
11091da177e4SLinus Torvalds 		if (!warned) {
11101da177e4SLinus Torvalds 			warned = 1;
11113410f22eSYang Yingliang 			pr_info("%s uses obsolete (PF_INET,SOCK_PACKET)\n",
111289bddce5SStephen Hemminger 				current->comm);
11131da177e4SLinus Torvalds 		}
11141da177e4SLinus Torvalds 		family = PF_PACKET;
11151da177e4SLinus Torvalds 	}
11161da177e4SLinus Torvalds 
11171da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, kern);
11181da177e4SLinus Torvalds 	if (err)
11191da177e4SLinus Torvalds 		return err;
11201da177e4SLinus Torvalds 
112155737fdaSStephen Hemminger 	/*
112255737fdaSStephen Hemminger 	 *	Allocate the socket and allow the family to set things up. if
112355737fdaSStephen Hemminger 	 *	the protocol is 0, the family is instructed to select an appropriate
112455737fdaSStephen Hemminger 	 *	default.
112555737fdaSStephen Hemminger 	 */
112655737fdaSStephen Hemminger 	sock = sock_alloc();
112755737fdaSStephen Hemminger 	if (!sock) {
1128e87cc472SJoe Perches 		net_warn_ratelimited("socket: no more sockets\n");
112955737fdaSStephen Hemminger 		return -ENFILE;	/* Not exactly a match, but its the
113055737fdaSStephen Hemminger 				   closest posix thing */
113155737fdaSStephen Hemminger 	}
113255737fdaSStephen Hemminger 
113355737fdaSStephen Hemminger 	sock->type = type;
113455737fdaSStephen Hemminger 
113595a5afcaSJohannes Berg #ifdef CONFIG_MODULES
11361da177e4SLinus Torvalds 	/* Attempt to load a protocol module if the find failed.
11371da177e4SLinus Torvalds 	 *
11381da177e4SLinus Torvalds 	 * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
11391da177e4SLinus Torvalds 	 * requested real, full-featured networking support upon configuration.
11401da177e4SLinus Torvalds 	 * Otherwise module support will break!
11411da177e4SLinus Torvalds 	 */
1142190683a9SEric Dumazet 	if (rcu_access_pointer(net_families[family]) == NULL)
11431da177e4SLinus Torvalds 		request_module("net-pf-%d", family);
11441da177e4SLinus Torvalds #endif
11451da177e4SLinus Torvalds 
114655737fdaSStephen Hemminger 	rcu_read_lock();
114755737fdaSStephen Hemminger 	pf = rcu_dereference(net_families[family]);
11481da177e4SLinus Torvalds 	err = -EAFNOSUPPORT;
114955737fdaSStephen Hemminger 	if (!pf)
115055737fdaSStephen Hemminger 		goto out_release;
11511da177e4SLinus Torvalds 
11521da177e4SLinus Torvalds 	/*
11531da177e4SLinus Torvalds 	 * We will call the ->create function, that possibly is in a loadable
11541da177e4SLinus Torvalds 	 * module, so we have to bump that loadable module refcnt first.
11551da177e4SLinus Torvalds 	 */
115655737fdaSStephen Hemminger 	if (!try_module_get(pf->owner))
11571da177e4SLinus Torvalds 		goto out_release;
11581da177e4SLinus Torvalds 
115955737fdaSStephen Hemminger 	/* Now protected by module ref count */
116055737fdaSStephen Hemminger 	rcu_read_unlock();
116155737fdaSStephen Hemminger 
11623f378b68SEric Paris 	err = pf->create(net, sock, protocol, kern);
116355737fdaSStephen Hemminger 	if (err < 0)
11641da177e4SLinus Torvalds 		goto out_module_put;
1165a79af59eSFrank Filz 
11661da177e4SLinus Torvalds 	/*
11671da177e4SLinus Torvalds 	 * Now to bump the refcnt of the [loadable] module that owns this
11681da177e4SLinus Torvalds 	 * socket at sock_release time we decrement its refcnt.
11691da177e4SLinus Torvalds 	 */
117055737fdaSStephen Hemminger 	if (!try_module_get(sock->ops->owner))
117155737fdaSStephen Hemminger 		goto out_module_busy;
117255737fdaSStephen Hemminger 
11731da177e4SLinus Torvalds 	/*
11741da177e4SLinus Torvalds 	 * Now that we're done with the ->create function, the [loadable]
11751da177e4SLinus Torvalds 	 * module can have its refcnt decremented
11761da177e4SLinus Torvalds 	 */
117755737fdaSStephen Hemminger 	module_put(pf->owner);
11787420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, kern);
11797420ed23SVenkat Yekkirala 	if (err)
11803b185525SHerbert Xu 		goto out_sock_release;
118155737fdaSStephen Hemminger 	*res = sock;
11821da177e4SLinus Torvalds 
118355737fdaSStephen Hemminger 	return 0;
118455737fdaSStephen Hemminger 
118555737fdaSStephen Hemminger out_module_busy:
118655737fdaSStephen Hemminger 	err = -EAFNOSUPPORT;
11871da177e4SLinus Torvalds out_module_put:
118855737fdaSStephen Hemminger 	sock->ops = NULL;
118955737fdaSStephen Hemminger 	module_put(pf->owner);
119055737fdaSStephen Hemminger out_sock_release:
11911da177e4SLinus Torvalds 	sock_release(sock);
119255737fdaSStephen Hemminger 	return err;
119355737fdaSStephen Hemminger 
119455737fdaSStephen Hemminger out_release:
119555737fdaSStephen Hemminger 	rcu_read_unlock();
119655737fdaSStephen Hemminger 	goto out_sock_release;
11971da177e4SLinus Torvalds }
1198721db93aSPavel Emelyanov EXPORT_SYMBOL(__sock_create);
11991da177e4SLinus Torvalds 
12001da177e4SLinus Torvalds int sock_create(int family, int type, int protocol, struct socket **res)
12011da177e4SLinus Torvalds {
12021b8d7ae4SEric W. Biederman 	return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
12031da177e4SLinus Torvalds }
1204c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create);
12051da177e4SLinus Torvalds 
1206eeb1bd5cSEric W. Biederman int sock_create_kern(struct net *net, int family, int type, int protocol, struct socket **res)
12071da177e4SLinus Torvalds {
1208eeb1bd5cSEric W. Biederman 	return __sock_create(net, family, type, protocol, res, 1);
12091da177e4SLinus Torvalds }
1210c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_kern);
12111da177e4SLinus Torvalds 
12123e0fa65fSHeiko Carstens SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
12131da177e4SLinus Torvalds {
12141da177e4SLinus Torvalds 	int retval;
12151da177e4SLinus Torvalds 	struct socket *sock;
1216a677a039SUlrich Drepper 	int flags;
1217a677a039SUlrich Drepper 
1218e38b36f3SUlrich Drepper 	/* Check the SOCK_* constants for consistency.  */
1219e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
1220e38b36f3SUlrich Drepper 	BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
1221e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);
1222e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);
1223e38b36f3SUlrich Drepper 
1224a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
122577d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1226a677a039SUlrich Drepper 		return -EINVAL;
1227a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
12281da177e4SLinus Torvalds 
1229aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1230aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1231aaca0bdcSUlrich Drepper 
12321da177e4SLinus Torvalds 	retval = sock_create(family, type, protocol, &sock);
12331da177e4SLinus Torvalds 	if (retval < 0)
12341da177e4SLinus Torvalds 		goto out;
12351da177e4SLinus Torvalds 
123677d27200SUlrich Drepper 	retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
12371da177e4SLinus Torvalds 	if (retval < 0)
12381da177e4SLinus Torvalds 		goto out_release;
12391da177e4SLinus Torvalds 
12401da177e4SLinus Torvalds out:
12411da177e4SLinus Torvalds 	/* It may be already another descriptor 8) Not kernel problem. */
12421da177e4SLinus Torvalds 	return retval;
12431da177e4SLinus Torvalds 
12441da177e4SLinus Torvalds out_release:
12451da177e4SLinus Torvalds 	sock_release(sock);
12461da177e4SLinus Torvalds 	return retval;
12471da177e4SLinus Torvalds }
12481da177e4SLinus Torvalds 
12491da177e4SLinus Torvalds /*
12501da177e4SLinus Torvalds  *	Create a pair of connected sockets.
12511da177e4SLinus Torvalds  */
12521da177e4SLinus Torvalds 
12533e0fa65fSHeiko Carstens SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
12543e0fa65fSHeiko Carstens 		int __user *, usockvec)
12551da177e4SLinus Torvalds {
12561da177e4SLinus Torvalds 	struct socket *sock1, *sock2;
12571da177e4SLinus Torvalds 	int fd1, fd2, err;
1258db349509SAl Viro 	struct file *newfile1, *newfile2;
1259a677a039SUlrich Drepper 	int flags;
1260a677a039SUlrich Drepper 
1261a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
126277d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1263a677a039SUlrich Drepper 		return -EINVAL;
1264a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
12651da177e4SLinus Torvalds 
1266aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1267aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1268aaca0bdcSUlrich Drepper 
12691da177e4SLinus Torvalds 	/*
12701da177e4SLinus Torvalds 	 * Obtain the first socket and check if the underlying protocol
12711da177e4SLinus Torvalds 	 * supports the socketpair call.
12721da177e4SLinus Torvalds 	 */
12731da177e4SLinus Torvalds 
12741da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock1);
12751da177e4SLinus Torvalds 	if (err < 0)
12761da177e4SLinus Torvalds 		goto out;
12771da177e4SLinus Torvalds 
12781da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock2);
12791da177e4SLinus Torvalds 	if (err < 0)
12801da177e4SLinus Torvalds 		goto out_release_1;
12811da177e4SLinus Torvalds 
12821da177e4SLinus Torvalds 	err = sock1->ops->socketpair(sock1, sock2);
12831da177e4SLinus Torvalds 	if (err < 0)
12841da177e4SLinus Torvalds 		goto out_release_both;
12851da177e4SLinus Torvalds 
128628407630SAl Viro 	fd1 = get_unused_fd_flags(flags);
1287bf3c23d1SDavid S. Miller 	if (unlikely(fd1 < 0)) {
1288bf3c23d1SDavid S. Miller 		err = fd1;
12891da177e4SLinus Torvalds 		goto out_release_both;
1290bf3c23d1SDavid S. Miller 	}
1291d73aa286SYann Droneaud 
129228407630SAl Viro 	fd2 = get_unused_fd_flags(flags);
1293198de4d7SAl Viro 	if (unlikely(fd2 < 0)) {
1294198de4d7SAl Viro 		err = fd2;
1295d73aa286SYann Droneaud 		goto out_put_unused_1;
129628407630SAl Viro 	}
129728407630SAl Viro 
1298aab174f0SLinus Torvalds 	newfile1 = sock_alloc_file(sock1, flags, NULL);
1299b5ffe634SViresh Kumar 	if (IS_ERR(newfile1)) {
130028407630SAl Viro 		err = PTR_ERR(newfile1);
1301d73aa286SYann Droneaud 		goto out_put_unused_both;
130228407630SAl Viro 	}
130328407630SAl Viro 
1304aab174f0SLinus Torvalds 	newfile2 = sock_alloc_file(sock2, flags, NULL);
130528407630SAl Viro 	if (IS_ERR(newfile2)) {
130628407630SAl Viro 		err = PTR_ERR(newfile2);
1307d73aa286SYann Droneaud 		goto out_fput_1;
1308db349509SAl Viro 	}
1309db349509SAl Viro 
1310d73aa286SYann Droneaud 	err = put_user(fd1, &usockvec[0]);
1311d73aa286SYann Droneaud 	if (err)
1312d73aa286SYann Droneaud 		goto out_fput_both;
1313d73aa286SYann Droneaud 
1314d73aa286SYann Droneaud 	err = put_user(fd2, &usockvec[1]);
1315d73aa286SYann Droneaud 	if (err)
1316d73aa286SYann Droneaud 		goto out_fput_both;
1317d73aa286SYann Droneaud 
1318157cf649SAl Viro 	audit_fd_pair(fd1, fd2);
1319d73aa286SYann Droneaud 
1320db349509SAl Viro 	fd_install(fd1, newfile1);
1321db349509SAl Viro 	fd_install(fd2, newfile2);
13221da177e4SLinus Torvalds 	/* fd1 and fd2 may be already another descriptors.
13231da177e4SLinus Torvalds 	 * Not kernel problem.
13241da177e4SLinus Torvalds 	 */
13251da177e4SLinus Torvalds 
13261da177e4SLinus Torvalds 	return 0;
13271da177e4SLinus Torvalds 
1328d73aa286SYann Droneaud out_fput_both:
1329d73aa286SYann Droneaud 	fput(newfile2);
1330d73aa286SYann Droneaud 	fput(newfile1);
1331d73aa286SYann Droneaud 	put_unused_fd(fd2);
1332d73aa286SYann Droneaud 	put_unused_fd(fd1);
1333d73aa286SYann Droneaud 	goto out;
13341da177e4SLinus Torvalds 
1335d73aa286SYann Droneaud out_fput_1:
1336d73aa286SYann Droneaud 	fput(newfile1);
1337d73aa286SYann Droneaud 	put_unused_fd(fd2);
1338d73aa286SYann Droneaud 	put_unused_fd(fd1);
1339d73aa286SYann Droneaud 	sock_release(sock2);
1340d73aa286SYann Droneaud 	goto out;
1341d73aa286SYann Droneaud 
1342d73aa286SYann Droneaud out_put_unused_both:
1343d73aa286SYann Droneaud 	put_unused_fd(fd2);
1344d73aa286SYann Droneaud out_put_unused_1:
1345d73aa286SYann Droneaud 	put_unused_fd(fd1);
13461da177e4SLinus Torvalds out_release_both:
13471da177e4SLinus Torvalds 	sock_release(sock2);
13481da177e4SLinus Torvalds out_release_1:
13491da177e4SLinus Torvalds 	sock_release(sock1);
13501da177e4SLinus Torvalds out:
13511da177e4SLinus Torvalds 	return err;
13521da177e4SLinus Torvalds }
13531da177e4SLinus Torvalds 
13541da177e4SLinus Torvalds /*
13551da177e4SLinus Torvalds  *	Bind a name to a socket. Nothing much to do here since it's
13561da177e4SLinus Torvalds  *	the protocol's responsibility to handle the local address.
13571da177e4SLinus Torvalds  *
13581da177e4SLinus Torvalds  *	We move the socket address to kernel space before we call
13591da177e4SLinus Torvalds  *	the protocol layer (having also checked the address is ok).
13601da177e4SLinus Torvalds  */
13611da177e4SLinus Torvalds 
136220f37034SHeiko Carstens SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
13631da177e4SLinus Torvalds {
13641da177e4SLinus Torvalds 	struct socket *sock;
1365230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
13666cb153caSBenjamin LaHaise 	int err, fput_needed;
13671da177e4SLinus Torvalds 
136889bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
136989bddce5SStephen Hemminger 	if (sock) {
137043db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(umyaddr, addrlen, &address);
137189bddce5SStephen Hemminger 		if (err >= 0) {
137289bddce5SStephen Hemminger 			err = security_socket_bind(sock,
1373230b1839SYOSHIFUJI Hideaki 						   (struct sockaddr *)&address,
137489bddce5SStephen Hemminger 						   addrlen);
13756cb153caSBenjamin LaHaise 			if (!err)
13766cb153caSBenjamin LaHaise 				err = sock->ops->bind(sock,
137789bddce5SStephen Hemminger 						      (struct sockaddr *)
1378230b1839SYOSHIFUJI Hideaki 						      &address, addrlen);
13791da177e4SLinus Torvalds 		}
13806cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
13811da177e4SLinus Torvalds 	}
13821da177e4SLinus Torvalds 	return err;
13831da177e4SLinus Torvalds }
13841da177e4SLinus Torvalds 
13851da177e4SLinus Torvalds /*
13861da177e4SLinus Torvalds  *	Perform a listen. Basically, we allow the protocol to do anything
13871da177e4SLinus Torvalds  *	necessary for a listen, and if that works, we mark the socket as
13881da177e4SLinus Torvalds  *	ready for listening.
13891da177e4SLinus Torvalds  */
13901da177e4SLinus Torvalds 
13913e0fa65fSHeiko Carstens SYSCALL_DEFINE2(listen, int, fd, int, backlog)
13921da177e4SLinus Torvalds {
13931da177e4SLinus Torvalds 	struct socket *sock;
13946cb153caSBenjamin LaHaise 	int err, fput_needed;
1395b8e1f9b5SPavel Emelyanov 	int somaxconn;
13961da177e4SLinus Torvalds 
139789bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
139889bddce5SStephen Hemminger 	if (sock) {
13998efa6e93SPavel Emelyanov 		somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
140095c96174SEric Dumazet 		if ((unsigned int)backlog > somaxconn)
1401b8e1f9b5SPavel Emelyanov 			backlog = somaxconn;
14021da177e4SLinus Torvalds 
14031da177e4SLinus Torvalds 		err = security_socket_listen(sock, backlog);
14046cb153caSBenjamin LaHaise 		if (!err)
14051da177e4SLinus Torvalds 			err = sock->ops->listen(sock, backlog);
14066cb153caSBenjamin LaHaise 
14076cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
14081da177e4SLinus Torvalds 	}
14091da177e4SLinus Torvalds 	return err;
14101da177e4SLinus Torvalds }
14111da177e4SLinus Torvalds 
14121da177e4SLinus Torvalds /*
14131da177e4SLinus Torvalds  *	For accept, we attempt to create a new socket, set up the link
14141da177e4SLinus Torvalds  *	with the client, wake up the client, then return the new
14151da177e4SLinus Torvalds  *	connected fd. We collect the address of the connector in kernel
14161da177e4SLinus Torvalds  *	space and move it to user at the very end. This is unclean because
14171da177e4SLinus Torvalds  *	we open the socket then return an error.
14181da177e4SLinus Torvalds  *
14191da177e4SLinus Torvalds  *	1003.1g adds the ability to recvmsg() to query connection pending
14201da177e4SLinus Torvalds  *	status to recvmsg. We need to add that support in a way thats
14211da177e4SLinus Torvalds  *	clean when we restucture accept also.
14221da177e4SLinus Torvalds  */
14231da177e4SLinus Torvalds 
142420f37034SHeiko Carstens SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
142520f37034SHeiko Carstens 		int __user *, upeer_addrlen, int, flags)
14261da177e4SLinus Torvalds {
14271da177e4SLinus Torvalds 	struct socket *sock, *newsock;
142839d8c1b6SDavid S. Miller 	struct file *newfile;
14296cb153caSBenjamin LaHaise 	int err, len, newfd, fput_needed;
1430230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
14311da177e4SLinus Torvalds 
143277d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1433aaca0bdcSUlrich Drepper 		return -EINVAL;
1434aaca0bdcSUlrich Drepper 
1435aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1436aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1437aaca0bdcSUlrich Drepper 
14386cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
14391da177e4SLinus Torvalds 	if (!sock)
14401da177e4SLinus Torvalds 		goto out;
14411da177e4SLinus Torvalds 
14421da177e4SLinus Torvalds 	err = -ENFILE;
1443c6d409cfSEric Dumazet 	newsock = sock_alloc();
1444c6d409cfSEric Dumazet 	if (!newsock)
14451da177e4SLinus Torvalds 		goto out_put;
14461da177e4SLinus Torvalds 
14471da177e4SLinus Torvalds 	newsock->type = sock->type;
14481da177e4SLinus Torvalds 	newsock->ops = sock->ops;
14491da177e4SLinus Torvalds 
14501da177e4SLinus Torvalds 	/*
14511da177e4SLinus Torvalds 	 * We don't need try_module_get here, as the listening socket (sock)
14521da177e4SLinus Torvalds 	 * has the protocol module (sock->ops->owner) held.
14531da177e4SLinus Torvalds 	 */
14541da177e4SLinus Torvalds 	__module_get(newsock->ops->owner);
14551da177e4SLinus Torvalds 
145628407630SAl Viro 	newfd = get_unused_fd_flags(flags);
145739d8c1b6SDavid S. Miller 	if (unlikely(newfd < 0)) {
145839d8c1b6SDavid S. Miller 		err = newfd;
14599a1875e6SDavid S. Miller 		sock_release(newsock);
14609a1875e6SDavid S. Miller 		goto out_put;
146139d8c1b6SDavid S. Miller 	}
1462aab174f0SLinus Torvalds 	newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name);
1463b5ffe634SViresh Kumar 	if (IS_ERR(newfile)) {
146428407630SAl Viro 		err = PTR_ERR(newfile);
146528407630SAl Viro 		put_unused_fd(newfd);
146628407630SAl Viro 		sock_release(newsock);
146728407630SAl Viro 		goto out_put;
146828407630SAl Viro 	}
146939d8c1b6SDavid S. Miller 
1470a79af59eSFrank Filz 	err = security_socket_accept(sock, newsock);
1471a79af59eSFrank Filz 	if (err)
147239d8c1b6SDavid S. Miller 		goto out_fd;
1473a79af59eSFrank Filz 
14741da177e4SLinus Torvalds 	err = sock->ops->accept(sock, newsock, sock->file->f_flags);
14751da177e4SLinus Torvalds 	if (err < 0)
147639d8c1b6SDavid S. Miller 		goto out_fd;
14771da177e4SLinus Torvalds 
14781da177e4SLinus Torvalds 	if (upeer_sockaddr) {
1479230b1839SYOSHIFUJI Hideaki 		if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
148089bddce5SStephen Hemminger 					  &len, 2) < 0) {
14811da177e4SLinus Torvalds 			err = -ECONNABORTED;
148239d8c1b6SDavid S. Miller 			goto out_fd;
14831da177e4SLinus Torvalds 		}
148443db362dSMaciej Żenczykowski 		err = move_addr_to_user(&address,
1485230b1839SYOSHIFUJI Hideaki 					len, upeer_sockaddr, upeer_addrlen);
14861da177e4SLinus Torvalds 		if (err < 0)
148739d8c1b6SDavid S. Miller 			goto out_fd;
14881da177e4SLinus Torvalds 	}
14891da177e4SLinus Torvalds 
14901da177e4SLinus Torvalds 	/* File flags are not inherited via accept() unlike another OSes. */
14911da177e4SLinus Torvalds 
149239d8c1b6SDavid S. Miller 	fd_install(newfd, newfile);
149339d8c1b6SDavid S. Miller 	err = newfd;
14941da177e4SLinus Torvalds 
14951da177e4SLinus Torvalds out_put:
14966cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
14971da177e4SLinus Torvalds out:
14981da177e4SLinus Torvalds 	return err;
149939d8c1b6SDavid S. Miller out_fd:
15009606a216SDavid S. Miller 	fput(newfile);
150139d8c1b6SDavid S. Miller 	put_unused_fd(newfd);
15021da177e4SLinus Torvalds 	goto out_put;
15031da177e4SLinus Torvalds }
15041da177e4SLinus Torvalds 
150520f37034SHeiko Carstens SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,
150620f37034SHeiko Carstens 		int __user *, upeer_addrlen)
1507aaca0bdcSUlrich Drepper {
1508de11defeSUlrich Drepper 	return sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0);
1509aaca0bdcSUlrich Drepper }
1510aaca0bdcSUlrich Drepper 
15111da177e4SLinus Torvalds /*
15121da177e4SLinus Torvalds  *	Attempt to connect to a socket with the server address.  The address
15131da177e4SLinus Torvalds  *	is in user space so we verify it is OK and move it to kernel space.
15141da177e4SLinus Torvalds  *
15151da177e4SLinus Torvalds  *	For 1003.1g we need to add clean support for a bind to AF_UNSPEC to
15161da177e4SLinus Torvalds  *	break bindings
15171da177e4SLinus Torvalds  *
15181da177e4SLinus Torvalds  *	NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and
15191da177e4SLinus Torvalds  *	other SEQPACKET protocols that take time to connect() as it doesn't
15201da177e4SLinus Torvalds  *	include the -EINPROGRESS status for such sockets.
15211da177e4SLinus Torvalds  */
15221da177e4SLinus Torvalds 
152320f37034SHeiko Carstens SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
152420f37034SHeiko Carstens 		int, addrlen)
15251da177e4SLinus Torvalds {
15261da177e4SLinus Torvalds 	struct socket *sock;
1527230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
15286cb153caSBenjamin LaHaise 	int err, fput_needed;
15291da177e4SLinus Torvalds 
15306cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
15311da177e4SLinus Torvalds 	if (!sock)
15321da177e4SLinus Torvalds 		goto out;
153343db362dSMaciej Żenczykowski 	err = move_addr_to_kernel(uservaddr, addrlen, &address);
15341da177e4SLinus Torvalds 	if (err < 0)
15351da177e4SLinus Torvalds 		goto out_put;
15361da177e4SLinus Torvalds 
153789bddce5SStephen Hemminger 	err =
1538230b1839SYOSHIFUJI Hideaki 	    security_socket_connect(sock, (struct sockaddr *)&address, addrlen);
15391da177e4SLinus Torvalds 	if (err)
15401da177e4SLinus Torvalds 		goto out_put;
15411da177e4SLinus Torvalds 
1542230b1839SYOSHIFUJI Hideaki 	err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,
15431da177e4SLinus Torvalds 				 sock->file->f_flags);
15441da177e4SLinus Torvalds out_put:
15456cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
15461da177e4SLinus Torvalds out:
15471da177e4SLinus Torvalds 	return err;
15481da177e4SLinus Torvalds }
15491da177e4SLinus Torvalds 
15501da177e4SLinus Torvalds /*
15511da177e4SLinus Torvalds  *	Get the local address ('name') of a socket object. Move the obtained
15521da177e4SLinus Torvalds  *	name to user space.
15531da177e4SLinus Torvalds  */
15541da177e4SLinus Torvalds 
155520f37034SHeiko Carstens SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
155620f37034SHeiko Carstens 		int __user *, usockaddr_len)
15571da177e4SLinus Torvalds {
15581da177e4SLinus Torvalds 	struct socket *sock;
1559230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
15606cb153caSBenjamin LaHaise 	int len, err, fput_needed;
15611da177e4SLinus Torvalds 
15626cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
15631da177e4SLinus Torvalds 	if (!sock)
15641da177e4SLinus Torvalds 		goto out;
15651da177e4SLinus Torvalds 
15661da177e4SLinus Torvalds 	err = security_socket_getsockname(sock);
15671da177e4SLinus Torvalds 	if (err)
15681da177e4SLinus Torvalds 		goto out_put;
15691da177e4SLinus Torvalds 
1570230b1839SYOSHIFUJI Hideaki 	err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0);
15711da177e4SLinus Torvalds 	if (err)
15721da177e4SLinus Torvalds 		goto out_put;
157343db362dSMaciej Żenczykowski 	err = move_addr_to_user(&address, len, usockaddr, usockaddr_len);
15741da177e4SLinus Torvalds 
15751da177e4SLinus Torvalds out_put:
15766cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
15771da177e4SLinus Torvalds out:
15781da177e4SLinus Torvalds 	return err;
15791da177e4SLinus Torvalds }
15801da177e4SLinus Torvalds 
15811da177e4SLinus Torvalds /*
15821da177e4SLinus Torvalds  *	Get the remote address ('name') of a socket object. Move the obtained
15831da177e4SLinus Torvalds  *	name to user space.
15841da177e4SLinus Torvalds  */
15851da177e4SLinus Torvalds 
158620f37034SHeiko Carstens SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
158720f37034SHeiko Carstens 		int __user *, usockaddr_len)
15881da177e4SLinus Torvalds {
15891da177e4SLinus Torvalds 	struct socket *sock;
1590230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
15916cb153caSBenjamin LaHaise 	int len, err, fput_needed;
15921da177e4SLinus Torvalds 
159389bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
159489bddce5SStephen Hemminger 	if (sock != NULL) {
15951da177e4SLinus Torvalds 		err = security_socket_getpeername(sock);
15961da177e4SLinus Torvalds 		if (err) {
15976cb153caSBenjamin LaHaise 			fput_light(sock->file, fput_needed);
15981da177e4SLinus Torvalds 			return err;
15991da177e4SLinus Torvalds 		}
16001da177e4SLinus Torvalds 
160189bddce5SStephen Hemminger 		err =
1602230b1839SYOSHIFUJI Hideaki 		    sock->ops->getname(sock, (struct sockaddr *)&address, &len,
160389bddce5SStephen Hemminger 				       1);
16041da177e4SLinus Torvalds 		if (!err)
160543db362dSMaciej Żenczykowski 			err = move_addr_to_user(&address, len, usockaddr,
160689bddce5SStephen Hemminger 						usockaddr_len);
16076cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
16081da177e4SLinus Torvalds 	}
16091da177e4SLinus Torvalds 	return err;
16101da177e4SLinus Torvalds }
16111da177e4SLinus Torvalds 
16121da177e4SLinus Torvalds /*
16131da177e4SLinus Torvalds  *	Send a datagram to a given address. We move the address into kernel
16141da177e4SLinus Torvalds  *	space and check the user space data area is readable before invoking
16151da177e4SLinus Torvalds  *	the protocol.
16161da177e4SLinus Torvalds  */
16171da177e4SLinus Torvalds 
16183e0fa65fSHeiko Carstens SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
161995c96174SEric Dumazet 		unsigned int, flags, struct sockaddr __user *, addr,
16203e0fa65fSHeiko Carstens 		int, addr_len)
16211da177e4SLinus Torvalds {
16221da177e4SLinus Torvalds 	struct socket *sock;
1623230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16241da177e4SLinus Torvalds 	int err;
16251da177e4SLinus Torvalds 	struct msghdr msg;
16261da177e4SLinus Torvalds 	struct iovec iov;
16276cb153caSBenjamin LaHaise 	int fput_needed;
16281da177e4SLinus Torvalds 
1629602bd0e9SAl Viro 	err = import_single_range(WRITE, buff, len, &iov, &msg.msg_iter);
1630602bd0e9SAl Viro 	if (unlikely(err))
1631602bd0e9SAl Viro 		return err;
1632de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1633de0fa95cSPavel Emelyanov 	if (!sock)
16344387ff75SDavid S. Miller 		goto out;
16356cb153caSBenjamin LaHaise 
16361da177e4SLinus Torvalds 	msg.msg_name = NULL;
16371da177e4SLinus Torvalds 	msg.msg_control = NULL;
16381da177e4SLinus Torvalds 	msg.msg_controllen = 0;
16391da177e4SLinus Torvalds 	msg.msg_namelen = 0;
16406cb153caSBenjamin LaHaise 	if (addr) {
164143db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(addr, addr_len, &address);
16421da177e4SLinus Torvalds 		if (err < 0)
16431da177e4SLinus Torvalds 			goto out_put;
1644230b1839SYOSHIFUJI Hideaki 		msg.msg_name = (struct sockaddr *)&address;
16451da177e4SLinus Torvalds 		msg.msg_namelen = addr_len;
16461da177e4SLinus Torvalds 	}
16471da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
16481da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
16491da177e4SLinus Torvalds 	msg.msg_flags = flags;
1650d8725c86SAl Viro 	err = sock_sendmsg(sock, &msg);
16511da177e4SLinus Torvalds 
16521da177e4SLinus Torvalds out_put:
1653de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
16544387ff75SDavid S. Miller out:
16551da177e4SLinus Torvalds 	return err;
16561da177e4SLinus Torvalds }
16571da177e4SLinus Torvalds 
16581da177e4SLinus Torvalds /*
16591da177e4SLinus Torvalds  *	Send a datagram down a socket.
16601da177e4SLinus Torvalds  */
16611da177e4SLinus Torvalds 
16623e0fa65fSHeiko Carstens SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len,
166395c96174SEric Dumazet 		unsigned int, flags)
16641da177e4SLinus Torvalds {
16651da177e4SLinus Torvalds 	return sys_sendto(fd, buff, len, flags, NULL, 0);
16661da177e4SLinus Torvalds }
16671da177e4SLinus Torvalds 
16681da177e4SLinus Torvalds /*
16691da177e4SLinus Torvalds  *	Receive a frame from the socket and optionally record the address of the
16701da177e4SLinus Torvalds  *	sender. We verify the buffers are writable and if needed move the
16711da177e4SLinus Torvalds  *	sender address from kernel to user space.
16721da177e4SLinus Torvalds  */
16731da177e4SLinus Torvalds 
16743e0fa65fSHeiko Carstens SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
167595c96174SEric Dumazet 		unsigned int, flags, struct sockaddr __user *, addr,
16763e0fa65fSHeiko Carstens 		int __user *, addr_len)
16771da177e4SLinus Torvalds {
16781da177e4SLinus Torvalds 	struct socket *sock;
16791da177e4SLinus Torvalds 	struct iovec iov;
16801da177e4SLinus Torvalds 	struct msghdr msg;
1681230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
16821da177e4SLinus Torvalds 	int err, err2;
16836cb153caSBenjamin LaHaise 	int fput_needed;
16841da177e4SLinus Torvalds 
1685602bd0e9SAl Viro 	err = import_single_range(READ, ubuf, size, &iov, &msg.msg_iter);
1686602bd0e9SAl Viro 	if (unlikely(err))
1687602bd0e9SAl Viro 		return err;
1688de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
16891da177e4SLinus Torvalds 	if (!sock)
1690de0fa95cSPavel Emelyanov 		goto out;
16911da177e4SLinus Torvalds 
16921da177e4SLinus Torvalds 	msg.msg_control = NULL;
16931da177e4SLinus Torvalds 	msg.msg_controllen = 0;
1694f3d33426SHannes Frederic Sowa 	/* Save some cycles and don't copy the address if not needed */
1695f3d33426SHannes Frederic Sowa 	msg.msg_name = addr ? (struct sockaddr *)&address : NULL;
1696f3d33426SHannes Frederic Sowa 	/* We assume all kernel code knows the size of sockaddr_storage */
1697f3d33426SHannes Frederic Sowa 	msg.msg_namelen = 0;
1698130ed5d1Stadeusz.struk@intel.com 	msg.msg_iocb = NULL;
16991da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
17001da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
1701602bd0e9SAl Viro 	err = sock_recvmsg(sock, &msg, iov_iter_count(&msg.msg_iter), flags);
17021da177e4SLinus Torvalds 
170389bddce5SStephen Hemminger 	if (err >= 0 && addr != NULL) {
170443db362dSMaciej Żenczykowski 		err2 = move_addr_to_user(&address,
1705230b1839SYOSHIFUJI Hideaki 					 msg.msg_namelen, addr, addr_len);
17061da177e4SLinus Torvalds 		if (err2 < 0)
17071da177e4SLinus Torvalds 			err = err2;
17081da177e4SLinus Torvalds 	}
1709de0fa95cSPavel Emelyanov 
1710de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
17114387ff75SDavid S. Miller out:
17121da177e4SLinus Torvalds 	return err;
17131da177e4SLinus Torvalds }
17141da177e4SLinus Torvalds 
17151da177e4SLinus Torvalds /*
17161da177e4SLinus Torvalds  *	Receive a datagram from a socket.
17171da177e4SLinus Torvalds  */
17181da177e4SLinus Torvalds 
1719b7c0ddf5SJan Glauber SYSCALL_DEFINE4(recv, int, fd, void __user *, ubuf, size_t, size,
1720b7c0ddf5SJan Glauber 		unsigned int, flags)
17211da177e4SLinus Torvalds {
17221da177e4SLinus Torvalds 	return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL);
17231da177e4SLinus Torvalds }
17241da177e4SLinus Torvalds 
17251da177e4SLinus Torvalds /*
17261da177e4SLinus Torvalds  *	Set a socket option. Because we don't know the option lengths we have
17271da177e4SLinus Torvalds  *	to pass the user mode parameter for the protocols to sort out.
17281da177e4SLinus Torvalds  */
17291da177e4SLinus Torvalds 
173020f37034SHeiko Carstens SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
173120f37034SHeiko Carstens 		char __user *, optval, int, optlen)
17321da177e4SLinus Torvalds {
17336cb153caSBenjamin LaHaise 	int err, fput_needed;
17341da177e4SLinus Torvalds 	struct socket *sock;
17351da177e4SLinus Torvalds 
17361da177e4SLinus Torvalds 	if (optlen < 0)
17371da177e4SLinus Torvalds 		return -EINVAL;
17381da177e4SLinus Torvalds 
173989bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
174089bddce5SStephen Hemminger 	if (sock != NULL) {
17411da177e4SLinus Torvalds 		err = security_socket_setsockopt(sock, level, optname);
17426cb153caSBenjamin LaHaise 		if (err)
17436cb153caSBenjamin LaHaise 			goto out_put;
17441da177e4SLinus Torvalds 
17451da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
174689bddce5SStephen Hemminger 			err =
174789bddce5SStephen Hemminger 			    sock_setsockopt(sock, level, optname, optval,
174889bddce5SStephen Hemminger 					    optlen);
17491da177e4SLinus Torvalds 		else
175089bddce5SStephen Hemminger 			err =
175189bddce5SStephen Hemminger 			    sock->ops->setsockopt(sock, level, optname, optval,
175289bddce5SStephen Hemminger 						  optlen);
17536cb153caSBenjamin LaHaise out_put:
17546cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
17551da177e4SLinus Torvalds 	}
17561da177e4SLinus Torvalds 	return err;
17571da177e4SLinus Torvalds }
17581da177e4SLinus Torvalds 
17591da177e4SLinus Torvalds /*
17601da177e4SLinus Torvalds  *	Get a socket option. Because we don't know the option lengths we have
17611da177e4SLinus Torvalds  *	to pass a user mode parameter for the protocols to sort out.
17621da177e4SLinus Torvalds  */
17631da177e4SLinus Torvalds 
176420f37034SHeiko Carstens SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
176520f37034SHeiko Carstens 		char __user *, optval, int __user *, optlen)
17661da177e4SLinus Torvalds {
17676cb153caSBenjamin LaHaise 	int err, fput_needed;
17681da177e4SLinus Torvalds 	struct socket *sock;
17691da177e4SLinus Torvalds 
177089bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
177189bddce5SStephen Hemminger 	if (sock != NULL) {
17726cb153caSBenjamin LaHaise 		err = security_socket_getsockopt(sock, level, optname);
17736cb153caSBenjamin LaHaise 		if (err)
17746cb153caSBenjamin LaHaise 			goto out_put;
17751da177e4SLinus Torvalds 
17761da177e4SLinus Torvalds 		if (level == SOL_SOCKET)
177789bddce5SStephen Hemminger 			err =
177889bddce5SStephen Hemminger 			    sock_getsockopt(sock, level, optname, optval,
177989bddce5SStephen Hemminger 					    optlen);
17801da177e4SLinus Torvalds 		else
178189bddce5SStephen Hemminger 			err =
178289bddce5SStephen Hemminger 			    sock->ops->getsockopt(sock, level, optname, optval,
178389bddce5SStephen Hemminger 						  optlen);
17846cb153caSBenjamin LaHaise out_put:
17856cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
17861da177e4SLinus Torvalds 	}
17871da177e4SLinus Torvalds 	return err;
17881da177e4SLinus Torvalds }
17891da177e4SLinus Torvalds 
17901da177e4SLinus Torvalds /*
17911da177e4SLinus Torvalds  *	Shutdown a socket.
17921da177e4SLinus Torvalds  */
17931da177e4SLinus Torvalds 
1794754fe8d2SHeiko Carstens SYSCALL_DEFINE2(shutdown, int, fd, int, how)
17951da177e4SLinus Torvalds {
17966cb153caSBenjamin LaHaise 	int err, fput_needed;
17971da177e4SLinus Torvalds 	struct socket *sock;
17981da177e4SLinus Torvalds 
179989bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
180089bddce5SStephen Hemminger 	if (sock != NULL) {
18011da177e4SLinus Torvalds 		err = security_socket_shutdown(sock, how);
18026cb153caSBenjamin LaHaise 		if (!err)
18031da177e4SLinus Torvalds 			err = sock->ops->shutdown(sock, how);
18046cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
18051da177e4SLinus Torvalds 	}
18061da177e4SLinus Torvalds 	return err;
18071da177e4SLinus Torvalds }
18081da177e4SLinus Torvalds 
18091da177e4SLinus Torvalds /* A couple of helpful macros for getting the address of the 32/64 bit
18101da177e4SLinus Torvalds  * fields which are the same type (int / unsigned) on our platforms.
18111da177e4SLinus Torvalds  */
18121da177e4SLinus Torvalds #define COMPAT_MSG(msg, member)	((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member)
18131da177e4SLinus Torvalds #define COMPAT_NAMELEN(msg)	COMPAT_MSG(msg, msg_namelen)
18141da177e4SLinus Torvalds #define COMPAT_FLAGS(msg)	COMPAT_MSG(msg, msg_flags)
18151da177e4SLinus Torvalds 
1816c71d8ebeSTetsuo Handa struct used_address {
1817c71d8ebeSTetsuo Handa 	struct sockaddr_storage name;
1818c71d8ebeSTetsuo Handa 	unsigned int name_len;
1819c71d8ebeSTetsuo Handa };
1820c71d8ebeSTetsuo Handa 
1821da184284SAl Viro static int copy_msghdr_from_user(struct msghdr *kmsg,
182208adb7daSAl Viro 				 struct user_msghdr __user *umsg,
182308adb7daSAl Viro 				 struct sockaddr __user **save_addr,
182408adb7daSAl Viro 				 struct iovec **iov)
18251661bf36SDan Carpenter {
182608adb7daSAl Viro 	struct sockaddr __user *uaddr;
182708adb7daSAl Viro 	struct iovec __user *uiov;
1828c0371da6SAl Viro 	size_t nr_segs;
182908adb7daSAl Viro 	ssize_t err;
183008adb7daSAl Viro 
183108adb7daSAl Viro 	if (!access_ok(VERIFY_READ, umsg, sizeof(*umsg)) ||
183208adb7daSAl Viro 	    __get_user(uaddr, &umsg->msg_name) ||
183308adb7daSAl Viro 	    __get_user(kmsg->msg_namelen, &umsg->msg_namelen) ||
183408adb7daSAl Viro 	    __get_user(uiov, &umsg->msg_iov) ||
1835c0371da6SAl Viro 	    __get_user(nr_segs, &umsg->msg_iovlen) ||
183608adb7daSAl Viro 	    __get_user(kmsg->msg_control, &umsg->msg_control) ||
183708adb7daSAl Viro 	    __get_user(kmsg->msg_controllen, &umsg->msg_controllen) ||
183808adb7daSAl Viro 	    __get_user(kmsg->msg_flags, &umsg->msg_flags))
18391661bf36SDan Carpenter 		return -EFAULT;
1840dbb490b9SMatthew Leach 
184108adb7daSAl Viro 	if (!uaddr)
18426a2a2b3aSAni Sinha 		kmsg->msg_namelen = 0;
18436a2a2b3aSAni Sinha 
1844dbb490b9SMatthew Leach 	if (kmsg->msg_namelen < 0)
1845dbb490b9SMatthew Leach 		return -EINVAL;
1846dbb490b9SMatthew Leach 
18471661bf36SDan Carpenter 	if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
1848db31c55aSDan Carpenter 		kmsg->msg_namelen = sizeof(struct sockaddr_storage);
184908adb7daSAl Viro 
185008adb7daSAl Viro 	if (save_addr)
185108adb7daSAl Viro 		*save_addr = uaddr;
185208adb7daSAl Viro 
185308adb7daSAl Viro 	if (uaddr && kmsg->msg_namelen) {
185408adb7daSAl Viro 		if (!save_addr) {
185508adb7daSAl Viro 			err = move_addr_to_kernel(uaddr, kmsg->msg_namelen,
185608adb7daSAl Viro 						  kmsg->msg_name);
185708adb7daSAl Viro 			if (err < 0)
185808adb7daSAl Viro 				return err;
185908adb7daSAl Viro 		}
186008adb7daSAl Viro 	} else {
186108adb7daSAl Viro 		kmsg->msg_name = NULL;
186208adb7daSAl Viro 		kmsg->msg_namelen = 0;
186308adb7daSAl Viro 	}
186408adb7daSAl Viro 
1865c0371da6SAl Viro 	if (nr_segs > UIO_MAXIOV)
186608adb7daSAl Viro 		return -EMSGSIZE;
186708adb7daSAl Viro 
18680345f931Stadeusz.struk@intel.com 	kmsg->msg_iocb = NULL;
18690345f931Stadeusz.struk@intel.com 
1870da184284SAl Viro 	return import_iovec(save_addr ? READ : WRITE, uiov, nr_segs,
1871da184284SAl Viro 			    UIO_FASTIOV, iov, &kmsg->msg_iter);
18721661bf36SDan Carpenter }
18731661bf36SDan Carpenter 
1874666547ffSAl Viro static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
187595c96174SEric Dumazet 			 struct msghdr *msg_sys, unsigned int flags,
1876c71d8ebeSTetsuo Handa 			 struct used_address *used_address)
18771da177e4SLinus Torvalds {
187889bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
187989bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
1880230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
18811da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
1882b9d717a7SAlex Williamson 	unsigned char ctl[sizeof(struct cmsghdr) + 20]
1883b9d717a7SAlex Williamson 	    __attribute__ ((aligned(sizeof(__kernel_size_t))));
1884b9d717a7SAlex Williamson 	/* 20 is size of ipv6_pktinfo */
18851da177e4SLinus Torvalds 	unsigned char *ctl_buf = ctl;
1886d8725c86SAl Viro 	int ctl_len;
188708adb7daSAl Viro 	ssize_t err;
18881da177e4SLinus Torvalds 
188908adb7daSAl Viro 	msg_sys->msg_name = &address;
18901da177e4SLinus Torvalds 
189108449320SAl Viro 	if (MSG_CMSG_COMPAT & flags)
189208adb7daSAl Viro 		err = get_compat_msghdr(msg_sys, msg_compat, NULL, &iov);
189308449320SAl Viro 	else
189408adb7daSAl Viro 		err = copy_msghdr_from_user(msg_sys, msg, NULL, &iov);
18951da177e4SLinus Torvalds 	if (err < 0)
1896da184284SAl Viro 		return err;
18971da177e4SLinus Torvalds 
18981da177e4SLinus Torvalds 	err = -ENOBUFS;
18991da177e4SLinus Torvalds 
1900228e548eSAnton Blanchard 	if (msg_sys->msg_controllen > INT_MAX)
19011da177e4SLinus Torvalds 		goto out_freeiov;
1902228e548eSAnton Blanchard 	ctl_len = msg_sys->msg_controllen;
19031da177e4SLinus Torvalds 	if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
190489bddce5SStephen Hemminger 		err =
1905228e548eSAnton Blanchard 		    cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl,
190689bddce5SStephen Hemminger 						     sizeof(ctl));
19071da177e4SLinus Torvalds 		if (err)
19081da177e4SLinus Torvalds 			goto out_freeiov;
1909228e548eSAnton Blanchard 		ctl_buf = msg_sys->msg_control;
1910228e548eSAnton Blanchard 		ctl_len = msg_sys->msg_controllen;
19111da177e4SLinus Torvalds 	} else if (ctl_len) {
191289bddce5SStephen Hemminger 		if (ctl_len > sizeof(ctl)) {
19131da177e4SLinus Torvalds 			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
19141da177e4SLinus Torvalds 			if (ctl_buf == NULL)
19151da177e4SLinus Torvalds 				goto out_freeiov;
19161da177e4SLinus Torvalds 		}
19171da177e4SLinus Torvalds 		err = -EFAULT;
19181da177e4SLinus Torvalds 		/*
1919228e548eSAnton Blanchard 		 * Careful! Before this, msg_sys->msg_control contains a user pointer.
19201da177e4SLinus Torvalds 		 * Afterwards, it will be a kernel pointer. Thus the compiler-assisted
19211da177e4SLinus Torvalds 		 * checking falls down on this.
19221da177e4SLinus Torvalds 		 */
1923fb8621bbSNamhyung Kim 		if (copy_from_user(ctl_buf,
1924228e548eSAnton Blanchard 				   (void __user __force *)msg_sys->msg_control,
192589bddce5SStephen Hemminger 				   ctl_len))
19261da177e4SLinus Torvalds 			goto out_freectl;
1927228e548eSAnton Blanchard 		msg_sys->msg_control = ctl_buf;
19281da177e4SLinus Torvalds 	}
1929228e548eSAnton Blanchard 	msg_sys->msg_flags = flags;
19301da177e4SLinus Torvalds 
19311da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
1932228e548eSAnton Blanchard 		msg_sys->msg_flags |= MSG_DONTWAIT;
1933c71d8ebeSTetsuo Handa 	/*
1934c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and current destination address is same as
1935c71d8ebeSTetsuo Handa 	 * previously succeeded address, omit asking LSM's decision.
1936c71d8ebeSTetsuo Handa 	 * used_address->name_len is initialized to UINT_MAX so that the first
1937c71d8ebeSTetsuo Handa 	 * destination address never matches.
1938c71d8ebeSTetsuo Handa 	 */
1939bc909d9dSMathieu Desnoyers 	if (used_address && msg_sys->msg_name &&
1940bc909d9dSMathieu Desnoyers 	    used_address->name_len == msg_sys->msg_namelen &&
1941bc909d9dSMathieu Desnoyers 	    !memcmp(&used_address->name, msg_sys->msg_name,
1942c71d8ebeSTetsuo Handa 		    used_address->name_len)) {
1943d8725c86SAl Viro 		err = sock_sendmsg_nosec(sock, msg_sys);
1944c71d8ebeSTetsuo Handa 		goto out_freectl;
1945c71d8ebeSTetsuo Handa 	}
1946d8725c86SAl Viro 	err = sock_sendmsg(sock, msg_sys);
1947c71d8ebeSTetsuo Handa 	/*
1948c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and sending to current destination address was
1949c71d8ebeSTetsuo Handa 	 * successful, remember it.
1950c71d8ebeSTetsuo Handa 	 */
1951c71d8ebeSTetsuo Handa 	if (used_address && err >= 0) {
1952c71d8ebeSTetsuo Handa 		used_address->name_len = msg_sys->msg_namelen;
1953bc909d9dSMathieu Desnoyers 		if (msg_sys->msg_name)
1954bc909d9dSMathieu Desnoyers 			memcpy(&used_address->name, msg_sys->msg_name,
1955c71d8ebeSTetsuo Handa 			       used_address->name_len);
1956c71d8ebeSTetsuo Handa 	}
19571da177e4SLinus Torvalds 
19581da177e4SLinus Torvalds out_freectl:
19591da177e4SLinus Torvalds 	if (ctl_buf != ctl)
19601da177e4SLinus Torvalds 		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
19611da177e4SLinus Torvalds out_freeiov:
1962a74e9106SEric Dumazet 	kfree(iov);
1963228e548eSAnton Blanchard 	return err;
1964228e548eSAnton Blanchard }
1965228e548eSAnton Blanchard 
1966228e548eSAnton Blanchard /*
1967228e548eSAnton Blanchard  *	BSD sendmsg interface
1968228e548eSAnton Blanchard  */
1969228e548eSAnton Blanchard 
1970666547ffSAl Viro long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned flags)
1971228e548eSAnton Blanchard {
1972228e548eSAnton Blanchard 	int fput_needed, err;
1973228e548eSAnton Blanchard 	struct msghdr msg_sys;
19741be374a0SAndy Lutomirski 	struct socket *sock;
1975228e548eSAnton Blanchard 
19761be374a0SAndy Lutomirski 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
1977228e548eSAnton Blanchard 	if (!sock)
1978228e548eSAnton Blanchard 		goto out;
1979228e548eSAnton Blanchard 
1980a7526eb5SAndy Lutomirski 	err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL);
1981228e548eSAnton Blanchard 
19826cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
19831da177e4SLinus Torvalds out:
19841da177e4SLinus Torvalds 	return err;
19851da177e4SLinus Torvalds }
19861da177e4SLinus Torvalds 
1987666547ffSAl Viro SYSCALL_DEFINE3(sendmsg, int, fd, struct user_msghdr __user *, msg, unsigned int, flags)
1988a7526eb5SAndy Lutomirski {
1989a7526eb5SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
1990a7526eb5SAndy Lutomirski 		return -EINVAL;
1991a7526eb5SAndy Lutomirski 	return __sys_sendmsg(fd, msg, flags);
1992a7526eb5SAndy Lutomirski }
1993a7526eb5SAndy Lutomirski 
1994228e548eSAnton Blanchard /*
1995228e548eSAnton Blanchard  *	Linux sendmmsg interface
1996228e548eSAnton Blanchard  */
1997228e548eSAnton Blanchard 
1998228e548eSAnton Blanchard int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
1999228e548eSAnton Blanchard 		   unsigned int flags)
2000228e548eSAnton Blanchard {
2001228e548eSAnton Blanchard 	int fput_needed, err, datagrams;
2002228e548eSAnton Blanchard 	struct socket *sock;
2003228e548eSAnton Blanchard 	struct mmsghdr __user *entry;
2004228e548eSAnton Blanchard 	struct compat_mmsghdr __user *compat_entry;
2005228e548eSAnton Blanchard 	struct msghdr msg_sys;
2006c71d8ebeSTetsuo Handa 	struct used_address used_address;
2007228e548eSAnton Blanchard 
200898382f41SAnton Blanchard 	if (vlen > UIO_MAXIOV)
200998382f41SAnton Blanchard 		vlen = UIO_MAXIOV;
2010228e548eSAnton Blanchard 
2011228e548eSAnton Blanchard 	datagrams = 0;
2012228e548eSAnton Blanchard 
2013228e548eSAnton Blanchard 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2014228e548eSAnton Blanchard 	if (!sock)
2015228e548eSAnton Blanchard 		return err;
2016228e548eSAnton Blanchard 
2017c71d8ebeSTetsuo Handa 	used_address.name_len = UINT_MAX;
2018228e548eSAnton Blanchard 	entry = mmsg;
2019228e548eSAnton Blanchard 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2020728ffb86SAnton Blanchard 	err = 0;
2021228e548eSAnton Blanchard 
2022228e548eSAnton Blanchard 	while (datagrams < vlen) {
2023228e548eSAnton Blanchard 		if (MSG_CMSG_COMPAT & flags) {
2024666547ffSAl Viro 			err = ___sys_sendmsg(sock, (struct user_msghdr __user *)compat_entry,
2025c71d8ebeSTetsuo Handa 					     &msg_sys, flags, &used_address);
2026228e548eSAnton Blanchard 			if (err < 0)
2027228e548eSAnton Blanchard 				break;
2028228e548eSAnton Blanchard 			err = __put_user(err, &compat_entry->msg_len);
2029228e548eSAnton Blanchard 			++compat_entry;
2030228e548eSAnton Blanchard 		} else {
2031a7526eb5SAndy Lutomirski 			err = ___sys_sendmsg(sock,
2032666547ffSAl Viro 					     (struct user_msghdr __user *)entry,
2033c71d8ebeSTetsuo Handa 					     &msg_sys, flags, &used_address);
2034228e548eSAnton Blanchard 			if (err < 0)
2035228e548eSAnton Blanchard 				break;
2036228e548eSAnton Blanchard 			err = put_user(err, &entry->msg_len);
2037228e548eSAnton Blanchard 			++entry;
2038228e548eSAnton Blanchard 		}
2039228e548eSAnton Blanchard 
2040228e548eSAnton Blanchard 		if (err)
2041228e548eSAnton Blanchard 			break;
2042228e548eSAnton Blanchard 		++datagrams;
2043228e548eSAnton Blanchard 	}
2044228e548eSAnton Blanchard 
2045228e548eSAnton Blanchard 	fput_light(sock->file, fput_needed);
2046228e548eSAnton Blanchard 
2047728ffb86SAnton Blanchard 	/* We only return an error if no datagrams were able to be sent */
2048728ffb86SAnton Blanchard 	if (datagrams != 0)
2049228e548eSAnton Blanchard 		return datagrams;
2050228e548eSAnton Blanchard 
2051228e548eSAnton Blanchard 	return err;
2052228e548eSAnton Blanchard }
2053228e548eSAnton Blanchard 
2054228e548eSAnton Blanchard SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
2055228e548eSAnton Blanchard 		unsigned int, vlen, unsigned int, flags)
2056228e548eSAnton Blanchard {
20571be374a0SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
20581be374a0SAndy Lutomirski 		return -EINVAL;
2059228e548eSAnton Blanchard 	return __sys_sendmmsg(fd, mmsg, vlen, flags);
2060228e548eSAnton Blanchard }
2061228e548eSAnton Blanchard 
2062666547ffSAl Viro static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg,
206395c96174SEric Dumazet 			 struct msghdr *msg_sys, unsigned int flags, int nosec)
20641da177e4SLinus Torvalds {
206589bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
206689bddce5SStephen Hemminger 	    (struct compat_msghdr __user *)msg;
20671da177e4SLinus Torvalds 	struct iovec iovstack[UIO_FASTIOV];
20681da177e4SLinus Torvalds 	struct iovec *iov = iovstack;
20691da177e4SLinus Torvalds 	unsigned long cmsg_ptr;
207008adb7daSAl Viro 	int total_len, len;
207108adb7daSAl Viro 	ssize_t err;
20721da177e4SLinus Torvalds 
20731da177e4SLinus Torvalds 	/* kernel mode address */
2074230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage addr;
20751da177e4SLinus Torvalds 
20761da177e4SLinus Torvalds 	/* user mode address pointers */
20771da177e4SLinus Torvalds 	struct sockaddr __user *uaddr;
207808adb7daSAl Viro 	int __user *uaddr_len = COMPAT_NAMELEN(msg);
20791da177e4SLinus Torvalds 
208008adb7daSAl Viro 	msg_sys->msg_name = &addr;
20811da177e4SLinus Torvalds 
2082f3d33426SHannes Frederic Sowa 	if (MSG_CMSG_COMPAT & flags)
208308adb7daSAl Viro 		err = get_compat_msghdr(msg_sys, msg_compat, &uaddr, &iov);
2084f3d33426SHannes Frederic Sowa 	else
208508adb7daSAl Viro 		err = copy_msghdr_from_user(msg_sys, msg, &uaddr, &iov);
20861da177e4SLinus Torvalds 	if (err < 0)
2087da184284SAl Viro 		return err;
2088da184284SAl Viro 	total_len = iov_iter_count(&msg_sys->msg_iter);
20891da177e4SLinus Torvalds 
2090a2e27255SArnaldo Carvalho de Melo 	cmsg_ptr = (unsigned long)msg_sys->msg_control;
2091a2e27255SArnaldo Carvalho de Melo 	msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
20921da177e4SLinus Torvalds 
2093f3d33426SHannes Frederic Sowa 	/* We assume all kernel code knows the size of sockaddr_storage */
2094f3d33426SHannes Frederic Sowa 	msg_sys->msg_namelen = 0;
2095f3d33426SHannes Frederic Sowa 
20961da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
20971da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
2098a2e27255SArnaldo Carvalho de Melo 	err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys,
2099a2e27255SArnaldo Carvalho de Melo 							  total_len, flags);
21001da177e4SLinus Torvalds 	if (err < 0)
21011da177e4SLinus Torvalds 		goto out_freeiov;
21021da177e4SLinus Torvalds 	len = err;
21031da177e4SLinus Torvalds 
21041da177e4SLinus Torvalds 	if (uaddr != NULL) {
210543db362dSMaciej Żenczykowski 		err = move_addr_to_user(&addr,
2106a2e27255SArnaldo Carvalho de Melo 					msg_sys->msg_namelen, uaddr,
210789bddce5SStephen Hemminger 					uaddr_len);
21081da177e4SLinus Torvalds 		if (err < 0)
21091da177e4SLinus Torvalds 			goto out_freeiov;
21101da177e4SLinus Torvalds 	}
2111a2e27255SArnaldo Carvalho de Melo 	err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
211237f7f421SDavid S. Miller 			 COMPAT_FLAGS(msg));
21131da177e4SLinus Torvalds 	if (err)
21141da177e4SLinus Torvalds 		goto out_freeiov;
21151da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags)
2116a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
21171da177e4SLinus Torvalds 				 &msg_compat->msg_controllen);
21181da177e4SLinus Torvalds 	else
2119a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
21201da177e4SLinus Torvalds 				 &msg->msg_controllen);
21211da177e4SLinus Torvalds 	if (err)
21221da177e4SLinus Torvalds 		goto out_freeiov;
21231da177e4SLinus Torvalds 	err = len;
21241da177e4SLinus Torvalds 
21251da177e4SLinus Torvalds out_freeiov:
2126a74e9106SEric Dumazet 	kfree(iov);
2127a2e27255SArnaldo Carvalho de Melo 	return err;
2128a2e27255SArnaldo Carvalho de Melo }
2129a2e27255SArnaldo Carvalho de Melo 
2130a2e27255SArnaldo Carvalho de Melo /*
2131a2e27255SArnaldo Carvalho de Melo  *	BSD recvmsg interface
2132a2e27255SArnaldo Carvalho de Melo  */
2133a2e27255SArnaldo Carvalho de Melo 
2134666547ffSAl Viro long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned flags)
2135a2e27255SArnaldo Carvalho de Melo {
2136a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err;
2137a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
21381be374a0SAndy Lutomirski 	struct socket *sock;
2139a2e27255SArnaldo Carvalho de Melo 
21401be374a0SAndy Lutomirski 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2141a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2142a2e27255SArnaldo Carvalho de Melo 		goto out;
2143a2e27255SArnaldo Carvalho de Melo 
2144a7526eb5SAndy Lutomirski 	err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0);
2145a2e27255SArnaldo Carvalho de Melo 
21466cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
21471da177e4SLinus Torvalds out:
21481da177e4SLinus Torvalds 	return err;
21491da177e4SLinus Torvalds }
21501da177e4SLinus Torvalds 
2151666547ffSAl Viro SYSCALL_DEFINE3(recvmsg, int, fd, struct user_msghdr __user *, msg,
2152a7526eb5SAndy Lutomirski 		unsigned int, flags)
2153a7526eb5SAndy Lutomirski {
2154a7526eb5SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
2155a7526eb5SAndy Lutomirski 		return -EINVAL;
2156a7526eb5SAndy Lutomirski 	return __sys_recvmsg(fd, msg, flags);
2157a7526eb5SAndy Lutomirski }
2158a7526eb5SAndy Lutomirski 
2159a2e27255SArnaldo Carvalho de Melo /*
2160a2e27255SArnaldo Carvalho de Melo  *     Linux recvmmsg interface
2161a2e27255SArnaldo Carvalho de Melo  */
21621da177e4SLinus Torvalds 
2163a2e27255SArnaldo Carvalho de Melo int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2164a2e27255SArnaldo Carvalho de Melo 		   unsigned int flags, struct timespec *timeout)
2165a2e27255SArnaldo Carvalho de Melo {
2166a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err, datagrams;
2167a2e27255SArnaldo Carvalho de Melo 	struct socket *sock;
2168a2e27255SArnaldo Carvalho de Melo 	struct mmsghdr __user *entry;
2169d7256d0eSJean-Mickael Guerin 	struct compat_mmsghdr __user *compat_entry;
2170a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
2171a2e27255SArnaldo Carvalho de Melo 	struct timespec end_time;
2172a2e27255SArnaldo Carvalho de Melo 
2173a2e27255SArnaldo Carvalho de Melo 	if (timeout &&
2174a2e27255SArnaldo Carvalho de Melo 	    poll_select_set_timeout(&end_time, timeout->tv_sec,
2175a2e27255SArnaldo Carvalho de Melo 				    timeout->tv_nsec))
2176a2e27255SArnaldo Carvalho de Melo 		return -EINVAL;
2177a2e27255SArnaldo Carvalho de Melo 
2178a2e27255SArnaldo Carvalho de Melo 	datagrams = 0;
2179a2e27255SArnaldo Carvalho de Melo 
2180a2e27255SArnaldo Carvalho de Melo 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2181a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2182a2e27255SArnaldo Carvalho de Melo 		return err;
2183a2e27255SArnaldo Carvalho de Melo 
2184a2e27255SArnaldo Carvalho de Melo 	err = sock_error(sock->sk);
2185a2e27255SArnaldo Carvalho de Melo 	if (err)
2186a2e27255SArnaldo Carvalho de Melo 		goto out_put;
2187a2e27255SArnaldo Carvalho de Melo 
2188a2e27255SArnaldo Carvalho de Melo 	entry = mmsg;
2189d7256d0eSJean-Mickael Guerin 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2190a2e27255SArnaldo Carvalho de Melo 
2191a2e27255SArnaldo Carvalho de Melo 	while (datagrams < vlen) {
2192a2e27255SArnaldo Carvalho de Melo 		/*
2193a2e27255SArnaldo Carvalho de Melo 		 * No need to ask LSM for more than the first datagram.
2194a2e27255SArnaldo Carvalho de Melo 		 */
2195d7256d0eSJean-Mickael Guerin 		if (MSG_CMSG_COMPAT & flags) {
2196666547ffSAl Viro 			err = ___sys_recvmsg(sock, (struct user_msghdr __user *)compat_entry,
2197b9eb8b87SAnton Blanchard 					     &msg_sys, flags & ~MSG_WAITFORONE,
2198b9eb8b87SAnton Blanchard 					     datagrams);
2199d7256d0eSJean-Mickael Guerin 			if (err < 0)
2200d7256d0eSJean-Mickael Guerin 				break;
2201d7256d0eSJean-Mickael Guerin 			err = __put_user(err, &compat_entry->msg_len);
2202d7256d0eSJean-Mickael Guerin 			++compat_entry;
2203d7256d0eSJean-Mickael Guerin 		} else {
2204a7526eb5SAndy Lutomirski 			err = ___sys_recvmsg(sock,
2205666547ffSAl Viro 					     (struct user_msghdr __user *)entry,
2206b9eb8b87SAnton Blanchard 					     &msg_sys, flags & ~MSG_WAITFORONE,
2207b9eb8b87SAnton Blanchard 					     datagrams);
2208a2e27255SArnaldo Carvalho de Melo 			if (err < 0)
2209a2e27255SArnaldo Carvalho de Melo 				break;
2210a2e27255SArnaldo Carvalho de Melo 			err = put_user(err, &entry->msg_len);
2211d7256d0eSJean-Mickael Guerin 			++entry;
2212d7256d0eSJean-Mickael Guerin 		}
2213d7256d0eSJean-Mickael Guerin 
2214a2e27255SArnaldo Carvalho de Melo 		if (err)
2215a2e27255SArnaldo Carvalho de Melo 			break;
2216a2e27255SArnaldo Carvalho de Melo 		++datagrams;
2217a2e27255SArnaldo Carvalho de Melo 
221871c5c159SBrandon L Black 		/* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
221971c5c159SBrandon L Black 		if (flags & MSG_WAITFORONE)
222071c5c159SBrandon L Black 			flags |= MSG_DONTWAIT;
222171c5c159SBrandon L Black 
2222a2e27255SArnaldo Carvalho de Melo 		if (timeout) {
2223a2e27255SArnaldo Carvalho de Melo 			ktime_get_ts(timeout);
2224a2e27255SArnaldo Carvalho de Melo 			*timeout = timespec_sub(end_time, *timeout);
2225a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_sec < 0) {
2226a2e27255SArnaldo Carvalho de Melo 				timeout->tv_sec = timeout->tv_nsec = 0;
2227a2e27255SArnaldo Carvalho de Melo 				break;
2228a2e27255SArnaldo Carvalho de Melo 			}
2229a2e27255SArnaldo Carvalho de Melo 
2230a2e27255SArnaldo Carvalho de Melo 			/* Timeout, return less than vlen datagrams */
2231a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_nsec == 0 && timeout->tv_sec == 0)
2232a2e27255SArnaldo Carvalho de Melo 				break;
2233a2e27255SArnaldo Carvalho de Melo 		}
2234a2e27255SArnaldo Carvalho de Melo 
2235a2e27255SArnaldo Carvalho de Melo 		/* Out of band data, return right away */
2236a2e27255SArnaldo Carvalho de Melo 		if (msg_sys.msg_flags & MSG_OOB)
2237a2e27255SArnaldo Carvalho de Melo 			break;
2238a2e27255SArnaldo Carvalho de Melo 	}
2239a2e27255SArnaldo Carvalho de Melo 
2240a2e27255SArnaldo Carvalho de Melo out_put:
2241a2e27255SArnaldo Carvalho de Melo 	fput_light(sock->file, fput_needed);
2242a2e27255SArnaldo Carvalho de Melo 
2243a2e27255SArnaldo Carvalho de Melo 	if (err == 0)
2244a2e27255SArnaldo Carvalho de Melo 		return datagrams;
2245a2e27255SArnaldo Carvalho de Melo 
2246a2e27255SArnaldo Carvalho de Melo 	if (datagrams != 0) {
2247a2e27255SArnaldo Carvalho de Melo 		/*
2248a2e27255SArnaldo Carvalho de Melo 		 * We may return less entries than requested (vlen) if the
2249a2e27255SArnaldo Carvalho de Melo 		 * sock is non block and there aren't enough datagrams...
2250a2e27255SArnaldo Carvalho de Melo 		 */
2251a2e27255SArnaldo Carvalho de Melo 		if (err != -EAGAIN) {
2252a2e27255SArnaldo Carvalho de Melo 			/*
2253a2e27255SArnaldo Carvalho de Melo 			 * ... or  if recvmsg returns an error after we
2254a2e27255SArnaldo Carvalho de Melo 			 * received some datagrams, where we record the
2255a2e27255SArnaldo Carvalho de Melo 			 * error to return on the next call or if the
2256a2e27255SArnaldo Carvalho de Melo 			 * app asks about it using getsockopt(SO_ERROR).
2257a2e27255SArnaldo Carvalho de Melo 			 */
2258a2e27255SArnaldo Carvalho de Melo 			sock->sk->sk_err = -err;
2259a2e27255SArnaldo Carvalho de Melo 		}
2260a2e27255SArnaldo Carvalho de Melo 
2261a2e27255SArnaldo Carvalho de Melo 		return datagrams;
2262a2e27255SArnaldo Carvalho de Melo 	}
2263a2e27255SArnaldo Carvalho de Melo 
2264a2e27255SArnaldo Carvalho de Melo 	return err;
2265a2e27255SArnaldo Carvalho de Melo }
2266a2e27255SArnaldo Carvalho de Melo 
2267a2e27255SArnaldo Carvalho de Melo SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
2268a2e27255SArnaldo Carvalho de Melo 		unsigned int, vlen, unsigned int, flags,
2269a2e27255SArnaldo Carvalho de Melo 		struct timespec __user *, timeout)
2270a2e27255SArnaldo Carvalho de Melo {
2271a2e27255SArnaldo Carvalho de Melo 	int datagrams;
2272a2e27255SArnaldo Carvalho de Melo 	struct timespec timeout_sys;
2273a2e27255SArnaldo Carvalho de Melo 
22741be374a0SAndy Lutomirski 	if (flags & MSG_CMSG_COMPAT)
22751be374a0SAndy Lutomirski 		return -EINVAL;
22761be374a0SAndy Lutomirski 
2277a2e27255SArnaldo Carvalho de Melo 	if (!timeout)
2278a2e27255SArnaldo Carvalho de Melo 		return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL);
2279a2e27255SArnaldo Carvalho de Melo 
2280a2e27255SArnaldo Carvalho de Melo 	if (copy_from_user(&timeout_sys, timeout, sizeof(timeout_sys)))
2281a2e27255SArnaldo Carvalho de Melo 		return -EFAULT;
2282a2e27255SArnaldo Carvalho de Melo 
2283a2e27255SArnaldo Carvalho de Melo 	datagrams = __sys_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys);
2284a2e27255SArnaldo Carvalho de Melo 
2285a2e27255SArnaldo Carvalho de Melo 	if (datagrams > 0 &&
2286a2e27255SArnaldo Carvalho de Melo 	    copy_to_user(timeout, &timeout_sys, sizeof(timeout_sys)))
2287a2e27255SArnaldo Carvalho de Melo 		datagrams = -EFAULT;
2288a2e27255SArnaldo Carvalho de Melo 
2289a2e27255SArnaldo Carvalho de Melo 	return datagrams;
2290a2e27255SArnaldo Carvalho de Melo }
2291a2e27255SArnaldo Carvalho de Melo 
2292a2e27255SArnaldo Carvalho de Melo #ifdef __ARCH_WANT_SYS_SOCKETCALL
22931da177e4SLinus Torvalds /* Argument list sizes for sys_socketcall */
22941da177e4SLinus Torvalds #define AL(x) ((x) * sizeof(unsigned long))
2295228e548eSAnton Blanchard static const unsigned char nargs[21] = {
229689bddce5SStephen Hemminger 	AL(0), AL(3), AL(3), AL(3), AL(2), AL(3),
22971da177e4SLinus Torvalds 	AL(3), AL(3), AL(4), AL(4), AL(4), AL(6),
2298aaca0bdcSUlrich Drepper 	AL(6), AL(2), AL(5), AL(5), AL(3), AL(3),
2299228e548eSAnton Blanchard 	AL(4), AL(5), AL(4)
230089bddce5SStephen Hemminger };
230189bddce5SStephen Hemminger 
23021da177e4SLinus Torvalds #undef AL
23031da177e4SLinus Torvalds 
23041da177e4SLinus Torvalds /*
23051da177e4SLinus Torvalds  *	System call vectors.
23061da177e4SLinus Torvalds  *
23071da177e4SLinus Torvalds  *	Argument checking cleaned up. Saved 20% in size.
23081da177e4SLinus Torvalds  *  This function doesn't need to set the kernel lock because
23091da177e4SLinus Torvalds  *  it is set by the callees.
23101da177e4SLinus Torvalds  */
23111da177e4SLinus Torvalds 
23123e0fa65fSHeiko Carstens SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
23131da177e4SLinus Torvalds {
23142950fa9dSChen Gang 	unsigned long a[AUDITSC_ARGS];
23151da177e4SLinus Torvalds 	unsigned long a0, a1;
23161da177e4SLinus Torvalds 	int err;
231747379052SArjan van de Ven 	unsigned int len;
23181da177e4SLinus Torvalds 
2319228e548eSAnton Blanchard 	if (call < 1 || call > SYS_SENDMMSG)
23201da177e4SLinus Torvalds 		return -EINVAL;
23211da177e4SLinus Torvalds 
232247379052SArjan van de Ven 	len = nargs[call];
232347379052SArjan van de Ven 	if (len > sizeof(a))
232447379052SArjan van de Ven 		return -EINVAL;
232547379052SArjan van de Ven 
23261da177e4SLinus Torvalds 	/* copy_from_user should be SMP safe. */
232747379052SArjan van de Ven 	if (copy_from_user(a, args, len))
23281da177e4SLinus Torvalds 		return -EFAULT;
23291da177e4SLinus Torvalds 
23302950fa9dSChen Gang 	err = audit_socketcall(nargs[call] / sizeof(unsigned long), a);
23312950fa9dSChen Gang 	if (err)
23322950fa9dSChen Gang 		return err;
23333ec3b2fbSDavid Woodhouse 
23341da177e4SLinus Torvalds 	a0 = a[0];
23351da177e4SLinus Torvalds 	a1 = a[1];
23361da177e4SLinus Torvalds 
233789bddce5SStephen Hemminger 	switch (call) {
23381da177e4SLinus Torvalds 	case SYS_SOCKET:
23391da177e4SLinus Torvalds 		err = sys_socket(a0, a1, a[2]);
23401da177e4SLinus Torvalds 		break;
23411da177e4SLinus Torvalds 	case SYS_BIND:
23421da177e4SLinus Torvalds 		err = sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
23431da177e4SLinus Torvalds 		break;
23441da177e4SLinus Torvalds 	case SYS_CONNECT:
23451da177e4SLinus Torvalds 		err = sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
23461da177e4SLinus Torvalds 		break;
23471da177e4SLinus Torvalds 	case SYS_LISTEN:
23481da177e4SLinus Torvalds 		err = sys_listen(a0, a1);
23491da177e4SLinus Torvalds 		break;
23501da177e4SLinus Torvalds 	case SYS_ACCEPT:
2351de11defeSUlrich Drepper 		err = sys_accept4(a0, (struct sockaddr __user *)a1,
2352aaca0bdcSUlrich Drepper 				  (int __user *)a[2], 0);
23531da177e4SLinus Torvalds 		break;
23541da177e4SLinus Torvalds 	case SYS_GETSOCKNAME:
235589bddce5SStephen Hemminger 		err =
235689bddce5SStephen Hemminger 		    sys_getsockname(a0, (struct sockaddr __user *)a1,
235789bddce5SStephen Hemminger 				    (int __user *)a[2]);
23581da177e4SLinus Torvalds 		break;
23591da177e4SLinus Torvalds 	case SYS_GETPEERNAME:
236089bddce5SStephen Hemminger 		err =
236189bddce5SStephen Hemminger 		    sys_getpeername(a0, (struct sockaddr __user *)a1,
236289bddce5SStephen Hemminger 				    (int __user *)a[2]);
23631da177e4SLinus Torvalds 		break;
23641da177e4SLinus Torvalds 	case SYS_SOCKETPAIR:
23651da177e4SLinus Torvalds 		err = sys_socketpair(a0, a1, a[2], (int __user *)a[3]);
23661da177e4SLinus Torvalds 		break;
23671da177e4SLinus Torvalds 	case SYS_SEND:
23681da177e4SLinus Torvalds 		err = sys_send(a0, (void __user *)a1, a[2], a[3]);
23691da177e4SLinus Torvalds 		break;
23701da177e4SLinus Torvalds 	case SYS_SENDTO:
23711da177e4SLinus Torvalds 		err = sys_sendto(a0, (void __user *)a1, a[2], a[3],
23721da177e4SLinus Torvalds 				 (struct sockaddr __user *)a[4], a[5]);
23731da177e4SLinus Torvalds 		break;
23741da177e4SLinus Torvalds 	case SYS_RECV:
23751da177e4SLinus Torvalds 		err = sys_recv(a0, (void __user *)a1, a[2], a[3]);
23761da177e4SLinus Torvalds 		break;
23771da177e4SLinus Torvalds 	case SYS_RECVFROM:
23781da177e4SLinus Torvalds 		err = sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
237989bddce5SStephen Hemminger 				   (struct sockaddr __user *)a[4],
238089bddce5SStephen Hemminger 				   (int __user *)a[5]);
23811da177e4SLinus Torvalds 		break;
23821da177e4SLinus Torvalds 	case SYS_SHUTDOWN:
23831da177e4SLinus Torvalds 		err = sys_shutdown(a0, a1);
23841da177e4SLinus Torvalds 		break;
23851da177e4SLinus Torvalds 	case SYS_SETSOCKOPT:
23861da177e4SLinus Torvalds 		err = sys_setsockopt(a0, a1, a[2], (char __user *)a[3], a[4]);
23871da177e4SLinus Torvalds 		break;
23881da177e4SLinus Torvalds 	case SYS_GETSOCKOPT:
238989bddce5SStephen Hemminger 		err =
239089bddce5SStephen Hemminger 		    sys_getsockopt(a0, a1, a[2], (char __user *)a[3],
239189bddce5SStephen Hemminger 				   (int __user *)a[4]);
23921da177e4SLinus Torvalds 		break;
23931da177e4SLinus Torvalds 	case SYS_SENDMSG:
2394666547ffSAl Viro 		err = sys_sendmsg(a0, (struct user_msghdr __user *)a1, a[2]);
23951da177e4SLinus Torvalds 		break;
2396228e548eSAnton Blanchard 	case SYS_SENDMMSG:
2397228e548eSAnton Blanchard 		err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]);
2398228e548eSAnton Blanchard 		break;
23991da177e4SLinus Torvalds 	case SYS_RECVMSG:
2400666547ffSAl Viro 		err = sys_recvmsg(a0, (struct user_msghdr __user *)a1, a[2]);
24011da177e4SLinus Torvalds 		break;
2402a2e27255SArnaldo Carvalho de Melo 	case SYS_RECVMMSG:
2403a2e27255SArnaldo Carvalho de Melo 		err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3],
2404a2e27255SArnaldo Carvalho de Melo 				   (struct timespec __user *)a[4]);
2405a2e27255SArnaldo Carvalho de Melo 		break;
2406de11defeSUlrich Drepper 	case SYS_ACCEPT4:
2407de11defeSUlrich Drepper 		err = sys_accept4(a0, (struct sockaddr __user *)a1,
2408de11defeSUlrich Drepper 				  (int __user *)a[2], a[3]);
2409aaca0bdcSUlrich Drepper 		break;
24101da177e4SLinus Torvalds 	default:
24111da177e4SLinus Torvalds 		err = -EINVAL;
24121da177e4SLinus Torvalds 		break;
24131da177e4SLinus Torvalds 	}
24141da177e4SLinus Torvalds 	return err;
24151da177e4SLinus Torvalds }
24161da177e4SLinus Torvalds 
24171da177e4SLinus Torvalds #endif				/* __ARCH_WANT_SYS_SOCKETCALL */
24181da177e4SLinus Torvalds 
241955737fdaSStephen Hemminger /**
242055737fdaSStephen Hemminger  *	sock_register - add a socket protocol handler
242155737fdaSStephen Hemminger  *	@ops: description of protocol
242255737fdaSStephen Hemminger  *
24231da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
24241da177e4SLinus Torvalds  *	advertise its address family, and have it linked into the
2425e793c0f7SMasanari Iida  *	socket interface. The value ops->family corresponds to the
242655737fdaSStephen Hemminger  *	socket system call protocol family.
24271da177e4SLinus Torvalds  */
2428f0fd27d4SStephen Hemminger int sock_register(const struct net_proto_family *ops)
24291da177e4SLinus Torvalds {
24301da177e4SLinus Torvalds 	int err;
24311da177e4SLinus Torvalds 
24321da177e4SLinus Torvalds 	if (ops->family >= NPROTO) {
24333410f22eSYang Yingliang 		pr_crit("protocol %d >= NPROTO(%d)\n", ops->family, NPROTO);
24341da177e4SLinus Torvalds 		return -ENOBUFS;
24351da177e4SLinus Torvalds 	}
243655737fdaSStephen Hemminger 
243755737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2438190683a9SEric Dumazet 	if (rcu_dereference_protected(net_families[ops->family],
2439190683a9SEric Dumazet 				      lockdep_is_held(&net_family_lock)))
24401da177e4SLinus Torvalds 		err = -EEXIST;
244155737fdaSStephen Hemminger 	else {
2442cf778b00SEric Dumazet 		rcu_assign_pointer(net_families[ops->family], ops);
24431da177e4SLinus Torvalds 		err = 0;
24441da177e4SLinus Torvalds 	}
244555737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
244655737fdaSStephen Hemminger 
24473410f22eSYang Yingliang 	pr_info("NET: Registered protocol family %d\n", ops->family);
24481da177e4SLinus Torvalds 	return err;
24491da177e4SLinus Torvalds }
2450c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_register);
24511da177e4SLinus Torvalds 
245255737fdaSStephen Hemminger /**
245355737fdaSStephen Hemminger  *	sock_unregister - remove a protocol handler
245455737fdaSStephen Hemminger  *	@family: protocol family to remove
245555737fdaSStephen Hemminger  *
24561da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
24571da177e4SLinus Torvalds  *	remove its address family, and have it unlinked from the
245855737fdaSStephen Hemminger  *	new socket creation.
245955737fdaSStephen Hemminger  *
246055737fdaSStephen Hemminger  *	If protocol handler is a module, then it can use module reference
246155737fdaSStephen Hemminger  *	counts to protect against new references. If protocol handler is not
246255737fdaSStephen Hemminger  *	a module then it needs to provide its own protection in
246355737fdaSStephen Hemminger  *	the ops->create routine.
24641da177e4SLinus Torvalds  */
2465f0fd27d4SStephen Hemminger void sock_unregister(int family)
24661da177e4SLinus Torvalds {
2467f0fd27d4SStephen Hemminger 	BUG_ON(family < 0 || family >= NPROTO);
24681da177e4SLinus Torvalds 
246955737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
2470a9b3cd7fSStephen Hemminger 	RCU_INIT_POINTER(net_families[family], NULL);
247155737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
247255737fdaSStephen Hemminger 
247355737fdaSStephen Hemminger 	synchronize_rcu();
247455737fdaSStephen Hemminger 
24753410f22eSYang Yingliang 	pr_info("NET: Unregistered protocol family %d\n", family);
24761da177e4SLinus Torvalds }
2477c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_unregister);
24781da177e4SLinus Torvalds 
247977d76ea3SAndi Kleen static int __init sock_init(void)
24801da177e4SLinus Torvalds {
2481b3e19d92SNick Piggin 	int err;
24822ca794e5SEric W. Biederman 	/*
24832ca794e5SEric W. Biederman 	 *      Initialize the network sysctl infrastructure.
24842ca794e5SEric W. Biederman 	 */
24852ca794e5SEric W. Biederman 	err = net_sysctl_init();
24862ca794e5SEric W. Biederman 	if (err)
24872ca794e5SEric W. Biederman 		goto out;
2488b3e19d92SNick Piggin 
24891da177e4SLinus Torvalds 	/*
24901da177e4SLinus Torvalds 	 *      Initialize skbuff SLAB cache
24911da177e4SLinus Torvalds 	 */
24921da177e4SLinus Torvalds 	skb_init();
24931da177e4SLinus Torvalds 
24941da177e4SLinus Torvalds 	/*
24951da177e4SLinus Torvalds 	 *      Initialize the protocols module.
24961da177e4SLinus Torvalds 	 */
24971da177e4SLinus Torvalds 
24981da177e4SLinus Torvalds 	init_inodecache();
2499b3e19d92SNick Piggin 
2500b3e19d92SNick Piggin 	err = register_filesystem(&sock_fs_type);
2501b3e19d92SNick Piggin 	if (err)
2502b3e19d92SNick Piggin 		goto out_fs;
25031da177e4SLinus Torvalds 	sock_mnt = kern_mount(&sock_fs_type);
2504b3e19d92SNick Piggin 	if (IS_ERR(sock_mnt)) {
2505b3e19d92SNick Piggin 		err = PTR_ERR(sock_mnt);
2506b3e19d92SNick Piggin 		goto out_mount;
2507b3e19d92SNick Piggin 	}
250877d76ea3SAndi Kleen 
250977d76ea3SAndi Kleen 	/* The real protocol initialization is performed in later initcalls.
25101da177e4SLinus Torvalds 	 */
25111da177e4SLinus Torvalds 
25121da177e4SLinus Torvalds #ifdef CONFIG_NETFILTER
25136d11cfdbSPablo Neira Ayuso 	err = netfilter_init();
25146d11cfdbSPablo Neira Ayuso 	if (err)
25156d11cfdbSPablo Neira Ayuso 		goto out;
25161da177e4SLinus Torvalds #endif
2517cbeb321aSDavid S. Miller 
2518408eccceSDaniel Borkmann 	ptp_classifier_init();
2519c1f19b51SRichard Cochran 
2520b3e19d92SNick Piggin out:
2521b3e19d92SNick Piggin 	return err;
2522b3e19d92SNick Piggin 
2523b3e19d92SNick Piggin out_mount:
2524b3e19d92SNick Piggin 	unregister_filesystem(&sock_fs_type);
2525b3e19d92SNick Piggin out_fs:
2526b3e19d92SNick Piggin 	goto out;
25271da177e4SLinus Torvalds }
25281da177e4SLinus Torvalds 
252977d76ea3SAndi Kleen core_initcall(sock_init);	/* early initcall */
253077d76ea3SAndi Kleen 
25311da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS
25321da177e4SLinus Torvalds void socket_seq_show(struct seq_file *seq)
25331da177e4SLinus Torvalds {
25341da177e4SLinus Torvalds 	int cpu;
25351da177e4SLinus Torvalds 	int counter = 0;
25361da177e4SLinus Torvalds 
25376f912042SKAMEZAWA Hiroyuki 	for_each_possible_cpu(cpu)
25381da177e4SLinus Torvalds 	    counter += per_cpu(sockets_in_use, cpu);
25391da177e4SLinus Torvalds 
25401da177e4SLinus Torvalds 	/* It can be negative, by the way. 8) */
25411da177e4SLinus Torvalds 	if (counter < 0)
25421da177e4SLinus Torvalds 		counter = 0;
25431da177e4SLinus Torvalds 
25441da177e4SLinus Torvalds 	seq_printf(seq, "sockets: used %d\n", counter);
25451da177e4SLinus Torvalds }
25461da177e4SLinus Torvalds #endif				/* CONFIG_PROC_FS */
25471da177e4SLinus Torvalds 
254889bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
25496b96018bSArnd Bergmann static int do_siocgstamp(struct net *net, struct socket *sock,
2550644595f8SH. Peter Anvin 			 unsigned int cmd, void __user *up)
25517a229387SArnd Bergmann {
25527a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
25537a229387SArnd Bergmann 	struct timeval ktv;
25547a229387SArnd Bergmann 	int err;
25557a229387SArnd Bergmann 
25567a229387SArnd Bergmann 	set_fs(KERNEL_DS);
25576b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv);
25587a229387SArnd Bergmann 	set_fs(old_fs);
2559644595f8SH. Peter Anvin 	if (!err)
2560ed6fe9d6SMikulas Patocka 		err = compat_put_timeval(&ktv, up);
2561644595f8SH. Peter Anvin 
25627a229387SArnd Bergmann 	return err;
25637a229387SArnd Bergmann }
25647a229387SArnd Bergmann 
25656b96018bSArnd Bergmann static int do_siocgstampns(struct net *net, struct socket *sock,
2566644595f8SH. Peter Anvin 			   unsigned int cmd, void __user *up)
25677a229387SArnd Bergmann {
25687a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
25697a229387SArnd Bergmann 	struct timespec kts;
25707a229387SArnd Bergmann 	int err;
25717a229387SArnd Bergmann 
25727a229387SArnd Bergmann 	set_fs(KERNEL_DS);
25736b96018bSArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts);
25747a229387SArnd Bergmann 	set_fs(old_fs);
2575644595f8SH. Peter Anvin 	if (!err)
2576ed6fe9d6SMikulas Patocka 		err = compat_put_timespec(&kts, up);
2577644595f8SH. Peter Anvin 
25787a229387SArnd Bergmann 	return err;
25797a229387SArnd Bergmann }
25807a229387SArnd Bergmann 
25816b96018bSArnd Bergmann static int dev_ifname32(struct net *net, struct compat_ifreq __user *uifr32)
25827a229387SArnd Bergmann {
25837a229387SArnd Bergmann 	struct ifreq __user *uifr;
25847a229387SArnd Bergmann 	int err;
25857a229387SArnd Bergmann 
25867a229387SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(struct ifreq));
25876b96018bSArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
25887a229387SArnd Bergmann 		return -EFAULT;
25897a229387SArnd Bergmann 
25906b96018bSArnd Bergmann 	err = dev_ioctl(net, SIOCGIFNAME, uifr);
25917a229387SArnd Bergmann 	if (err)
25927a229387SArnd Bergmann 		return err;
25937a229387SArnd Bergmann 
25946b96018bSArnd Bergmann 	if (copy_in_user(uifr32, uifr, sizeof(struct compat_ifreq)))
25957a229387SArnd Bergmann 		return -EFAULT;
25967a229387SArnd Bergmann 
25977a229387SArnd Bergmann 	return 0;
25987a229387SArnd Bergmann }
25997a229387SArnd Bergmann 
26006b96018bSArnd Bergmann static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32)
26017a229387SArnd Bergmann {
26026b96018bSArnd Bergmann 	struct compat_ifconf ifc32;
26037a229387SArnd Bergmann 	struct ifconf ifc;
26047a229387SArnd Bergmann 	struct ifconf __user *uifc;
26056b96018bSArnd Bergmann 	struct compat_ifreq __user *ifr32;
26067a229387SArnd Bergmann 	struct ifreq __user *ifr;
26077a229387SArnd Bergmann 	unsigned int i, j;
26087a229387SArnd Bergmann 	int err;
26097a229387SArnd Bergmann 
26106b96018bSArnd Bergmann 	if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf)))
26117a229387SArnd Bergmann 		return -EFAULT;
26127a229387SArnd Bergmann 
261343da5f2eSMathias Krause 	memset(&ifc, 0, sizeof(ifc));
26147a229387SArnd Bergmann 	if (ifc32.ifcbuf == 0) {
26157a229387SArnd Bergmann 		ifc32.ifc_len = 0;
26167a229387SArnd Bergmann 		ifc.ifc_len = 0;
26177a229387SArnd Bergmann 		ifc.ifc_req = NULL;
26187a229387SArnd Bergmann 		uifc = compat_alloc_user_space(sizeof(struct ifconf));
26197a229387SArnd Bergmann 	} else {
26206b96018bSArnd Bergmann 		size_t len = ((ifc32.ifc_len / sizeof(struct compat_ifreq)) + 1) *
26217a229387SArnd Bergmann 			sizeof(struct ifreq);
26227a229387SArnd Bergmann 		uifc = compat_alloc_user_space(sizeof(struct ifconf) + len);
26237a229387SArnd Bergmann 		ifc.ifc_len = len;
26247a229387SArnd Bergmann 		ifr = ifc.ifc_req = (void __user *)(uifc + 1);
26257a229387SArnd Bergmann 		ifr32 = compat_ptr(ifc32.ifcbuf);
26266b96018bSArnd Bergmann 		for (i = 0; i < ifc32.ifc_len; i += sizeof(struct compat_ifreq)) {
26276b96018bSArnd Bergmann 			if (copy_in_user(ifr, ifr32, sizeof(struct compat_ifreq)))
26287a229387SArnd Bergmann 				return -EFAULT;
26297a229387SArnd Bergmann 			ifr++;
26307a229387SArnd Bergmann 			ifr32++;
26317a229387SArnd Bergmann 		}
26327a229387SArnd Bergmann 	}
26337a229387SArnd Bergmann 	if (copy_to_user(uifc, &ifc, sizeof(struct ifconf)))
26347a229387SArnd Bergmann 		return -EFAULT;
26357a229387SArnd Bergmann 
26366b96018bSArnd Bergmann 	err = dev_ioctl(net, SIOCGIFCONF, uifc);
26377a229387SArnd Bergmann 	if (err)
26387a229387SArnd Bergmann 		return err;
26397a229387SArnd Bergmann 
26407a229387SArnd Bergmann 	if (copy_from_user(&ifc, uifc, sizeof(struct ifconf)))
26417a229387SArnd Bergmann 		return -EFAULT;
26427a229387SArnd Bergmann 
26437a229387SArnd Bergmann 	ifr = ifc.ifc_req;
26447a229387SArnd Bergmann 	ifr32 = compat_ptr(ifc32.ifcbuf);
26457a229387SArnd Bergmann 	for (i = 0, j = 0;
26466b96018bSArnd Bergmann 	     i + sizeof(struct compat_ifreq) <= ifc32.ifc_len && j < ifc.ifc_len;
26476b96018bSArnd Bergmann 	     i += sizeof(struct compat_ifreq), j += sizeof(struct ifreq)) {
26486b96018bSArnd Bergmann 		if (copy_in_user(ifr32, ifr, sizeof(struct compat_ifreq)))
26497a229387SArnd Bergmann 			return -EFAULT;
26507a229387SArnd Bergmann 		ifr32++;
26517a229387SArnd Bergmann 		ifr++;
26527a229387SArnd Bergmann 	}
26537a229387SArnd Bergmann 
26547a229387SArnd Bergmann 	if (ifc32.ifcbuf == 0) {
26557a229387SArnd Bergmann 		/* Translate from 64-bit structure multiple to
26567a229387SArnd Bergmann 		 * a 32-bit one.
26577a229387SArnd Bergmann 		 */
26587a229387SArnd Bergmann 		i = ifc.ifc_len;
26596b96018bSArnd Bergmann 		i = ((i / sizeof(struct ifreq)) * sizeof(struct compat_ifreq));
26607a229387SArnd Bergmann 		ifc32.ifc_len = i;
26617a229387SArnd Bergmann 	} else {
26627a229387SArnd Bergmann 		ifc32.ifc_len = i;
26637a229387SArnd Bergmann 	}
26646b96018bSArnd Bergmann 	if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf)))
26657a229387SArnd Bergmann 		return -EFAULT;
26667a229387SArnd Bergmann 
26677a229387SArnd Bergmann 	return 0;
26687a229387SArnd Bergmann }
26697a229387SArnd Bergmann 
26706b96018bSArnd Bergmann static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
26717a229387SArnd Bergmann {
26723a7da39dSBen Hutchings 	struct compat_ethtool_rxnfc __user *compat_rxnfc;
26733a7da39dSBen Hutchings 	bool convert_in = false, convert_out = false;
26743a7da39dSBen Hutchings 	size_t buf_size = ALIGN(sizeof(struct ifreq), 8);
26753a7da39dSBen Hutchings 	struct ethtool_rxnfc __user *rxnfc;
26767a229387SArnd Bergmann 	struct ifreq __user *ifr;
26773a7da39dSBen Hutchings 	u32 rule_cnt = 0, actual_rule_cnt;
26783a7da39dSBen Hutchings 	u32 ethcmd;
26797a229387SArnd Bergmann 	u32 data;
26803a7da39dSBen Hutchings 	int ret;
26817a229387SArnd Bergmann 
26827a229387SArnd Bergmann 	if (get_user(data, &ifr32->ifr_ifru.ifru_data))
26837a229387SArnd Bergmann 		return -EFAULT;
26847a229387SArnd Bergmann 
26853a7da39dSBen Hutchings 	compat_rxnfc = compat_ptr(data);
26863a7da39dSBen Hutchings 
26873a7da39dSBen Hutchings 	if (get_user(ethcmd, &compat_rxnfc->cmd))
26887a229387SArnd Bergmann 		return -EFAULT;
26897a229387SArnd Bergmann 
26903a7da39dSBen Hutchings 	/* Most ethtool structures are defined without padding.
26913a7da39dSBen Hutchings 	 * Unfortunately struct ethtool_rxnfc is an exception.
26923a7da39dSBen Hutchings 	 */
26933a7da39dSBen Hutchings 	switch (ethcmd) {
26943a7da39dSBen Hutchings 	default:
26953a7da39dSBen Hutchings 		break;
26963a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLALL:
26973a7da39dSBen Hutchings 		/* Buffer size is variable */
26983a7da39dSBen Hutchings 		if (get_user(rule_cnt, &compat_rxnfc->rule_cnt))
26993a7da39dSBen Hutchings 			return -EFAULT;
27003a7da39dSBen Hutchings 		if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32))
27013a7da39dSBen Hutchings 			return -ENOMEM;
27023a7da39dSBen Hutchings 		buf_size += rule_cnt * sizeof(u32);
27033a7da39dSBen Hutchings 		/* fall through */
27043a7da39dSBen Hutchings 	case ETHTOOL_GRXRINGS:
27053a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRLCNT:
27063a7da39dSBen Hutchings 	case ETHTOOL_GRXCLSRULE:
270755664f32SBen Hutchings 	case ETHTOOL_SRXCLSRLINS:
27083a7da39dSBen Hutchings 		convert_out = true;
27093a7da39dSBen Hutchings 		/* fall through */
27103a7da39dSBen Hutchings 	case ETHTOOL_SRXCLSRLDEL:
27113a7da39dSBen Hutchings 		buf_size += sizeof(struct ethtool_rxnfc);
27123a7da39dSBen Hutchings 		convert_in = true;
27133a7da39dSBen Hutchings 		break;
27143a7da39dSBen Hutchings 	}
27153a7da39dSBen Hutchings 
27163a7da39dSBen Hutchings 	ifr = compat_alloc_user_space(buf_size);
2717954b1244SStephen Hemminger 	rxnfc = (void __user *)ifr + ALIGN(sizeof(struct ifreq), 8);
27183a7da39dSBen Hutchings 
27193a7da39dSBen Hutchings 	if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
27203a7da39dSBen Hutchings 		return -EFAULT;
27213a7da39dSBen Hutchings 
27223a7da39dSBen Hutchings 	if (put_user(convert_in ? rxnfc : compat_ptr(data),
27233a7da39dSBen Hutchings 		     &ifr->ifr_ifru.ifru_data))
27243a7da39dSBen Hutchings 		return -EFAULT;
27253a7da39dSBen Hutchings 
27263a7da39dSBen Hutchings 	if (convert_in) {
2727127fe533SAlexander Duyck 		/* We expect there to be holes between fs.m_ext and
27283a7da39dSBen Hutchings 		 * fs.ring_cookie and at the end of fs, but nowhere else.
27293a7da39dSBen Hutchings 		 */
2730127fe533SAlexander Duyck 		BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_ext) +
2731127fe533SAlexander Duyck 			     sizeof(compat_rxnfc->fs.m_ext) !=
2732127fe533SAlexander Duyck 			     offsetof(struct ethtool_rxnfc, fs.m_ext) +
2733127fe533SAlexander Duyck 			     sizeof(rxnfc->fs.m_ext));
27343a7da39dSBen Hutchings 		BUILD_BUG_ON(
27353a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.location) -
27363a7da39dSBen Hutchings 			offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) !=
27373a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.location) -
27383a7da39dSBen Hutchings 			offsetof(struct ethtool_rxnfc, fs.ring_cookie));
27393a7da39dSBen Hutchings 
27403a7da39dSBen Hutchings 		if (copy_in_user(rxnfc, compat_rxnfc,
2741954b1244SStephen Hemminger 				 (void __user *)(&rxnfc->fs.m_ext + 1) -
2742954b1244SStephen Hemminger 				 (void __user *)rxnfc) ||
27433a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->fs.ring_cookie,
27443a7da39dSBen Hutchings 				 &compat_rxnfc->fs.ring_cookie,
2745954b1244SStephen Hemminger 				 (void __user *)(&rxnfc->fs.location + 1) -
2746954b1244SStephen Hemminger 				 (void __user *)&rxnfc->fs.ring_cookie) ||
27473a7da39dSBen Hutchings 		    copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt,
27483a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
27493a7da39dSBen Hutchings 			return -EFAULT;
27503a7da39dSBen Hutchings 	}
27513a7da39dSBen Hutchings 
27523a7da39dSBen Hutchings 	ret = dev_ioctl(net, SIOCETHTOOL, ifr);
27533a7da39dSBen Hutchings 	if (ret)
27543a7da39dSBen Hutchings 		return ret;
27553a7da39dSBen Hutchings 
27563a7da39dSBen Hutchings 	if (convert_out) {
27573a7da39dSBen Hutchings 		if (copy_in_user(compat_rxnfc, rxnfc,
2758954b1244SStephen Hemminger 				 (const void __user *)(&rxnfc->fs.m_ext + 1) -
2759954b1244SStephen Hemminger 				 (const void __user *)rxnfc) ||
27603a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->fs.ring_cookie,
27613a7da39dSBen Hutchings 				 &rxnfc->fs.ring_cookie,
2762954b1244SStephen Hemminger 				 (const void __user *)(&rxnfc->fs.location + 1) -
2763954b1244SStephen Hemminger 				 (const void __user *)&rxnfc->fs.ring_cookie) ||
27643a7da39dSBen Hutchings 		    copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt,
27653a7da39dSBen Hutchings 				 sizeof(rxnfc->rule_cnt)))
27663a7da39dSBen Hutchings 			return -EFAULT;
27673a7da39dSBen Hutchings 
27683a7da39dSBen Hutchings 		if (ethcmd == ETHTOOL_GRXCLSRLALL) {
27693a7da39dSBen Hutchings 			/* As an optimisation, we only copy the actual
27703a7da39dSBen Hutchings 			 * number of rules that the underlying
27713a7da39dSBen Hutchings 			 * function returned.  Since Mallory might
27723a7da39dSBen Hutchings 			 * change the rule count in user memory, we
27733a7da39dSBen Hutchings 			 * check that it is less than the rule count
27743a7da39dSBen Hutchings 			 * originally given (as the user buffer size),
27753a7da39dSBen Hutchings 			 * which has been range-checked.
27763a7da39dSBen Hutchings 			 */
27773a7da39dSBen Hutchings 			if (get_user(actual_rule_cnt, &rxnfc->rule_cnt))
27783a7da39dSBen Hutchings 				return -EFAULT;
27793a7da39dSBen Hutchings 			if (actual_rule_cnt < rule_cnt)
27803a7da39dSBen Hutchings 				rule_cnt = actual_rule_cnt;
27813a7da39dSBen Hutchings 			if (copy_in_user(&compat_rxnfc->rule_locs[0],
27823a7da39dSBen Hutchings 					 &rxnfc->rule_locs[0],
27833a7da39dSBen Hutchings 					 rule_cnt * sizeof(u32)))
27843a7da39dSBen Hutchings 				return -EFAULT;
27853a7da39dSBen Hutchings 		}
27863a7da39dSBen Hutchings 	}
27873a7da39dSBen Hutchings 
27883a7da39dSBen Hutchings 	return 0;
27897a229387SArnd Bergmann }
27907a229387SArnd Bergmann 
27917a50a240SArnd Bergmann static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32)
27927a50a240SArnd Bergmann {
27937a50a240SArnd Bergmann 	void __user *uptr;
27947a50a240SArnd Bergmann 	compat_uptr_t uptr32;
27957a50a240SArnd Bergmann 	struct ifreq __user *uifr;
27967a50a240SArnd Bergmann 
27977a50a240SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
27987a50a240SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
27997a50a240SArnd Bergmann 		return -EFAULT;
28007a50a240SArnd Bergmann 
28017a50a240SArnd Bergmann 	if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu))
28027a50a240SArnd Bergmann 		return -EFAULT;
28037a50a240SArnd Bergmann 
28047a50a240SArnd Bergmann 	uptr = compat_ptr(uptr32);
28057a50a240SArnd Bergmann 
28067a50a240SArnd Bergmann 	if (put_user(uptr, &uifr->ifr_settings.ifs_ifsu.raw_hdlc))
28077a50a240SArnd Bergmann 		return -EFAULT;
28087a50a240SArnd Bergmann 
28097a50a240SArnd Bergmann 	return dev_ioctl(net, SIOCWANDEV, uifr);
28107a50a240SArnd Bergmann }
28117a50a240SArnd Bergmann 
28126b96018bSArnd Bergmann static int bond_ioctl(struct net *net, unsigned int cmd,
28136b96018bSArnd Bergmann 			 struct compat_ifreq __user *ifr32)
28147a229387SArnd Bergmann {
28157a229387SArnd Bergmann 	struct ifreq kifr;
28167a229387SArnd Bergmann 	mm_segment_t old_fs;
28177a229387SArnd Bergmann 	int err;
28187a229387SArnd Bergmann 
28197a229387SArnd Bergmann 	switch (cmd) {
28207a229387SArnd Bergmann 	case SIOCBONDENSLAVE:
28217a229387SArnd Bergmann 	case SIOCBONDRELEASE:
28227a229387SArnd Bergmann 	case SIOCBONDSETHWADDR:
28237a229387SArnd Bergmann 	case SIOCBONDCHANGEACTIVE:
28246b96018bSArnd Bergmann 		if (copy_from_user(&kifr, ifr32, sizeof(struct compat_ifreq)))
28257a229387SArnd Bergmann 			return -EFAULT;
28267a229387SArnd Bergmann 
28277a229387SArnd Bergmann 		old_fs = get_fs();
28287a229387SArnd Bergmann 		set_fs(KERNEL_DS);
2829c3f52ae6Sstephen hemminger 		err = dev_ioctl(net, cmd,
2830c3f52ae6Sstephen hemminger 				(struct ifreq __user __force *) &kifr);
28317a229387SArnd Bergmann 		set_fs(old_fs);
28327a229387SArnd Bergmann 
28337a229387SArnd Bergmann 		return err;
28347a229387SArnd Bergmann 	default:
283507d106d0SLinus Torvalds 		return -ENOIOCTLCMD;
2836ccbd6a5aSJoe Perches 	}
28377a229387SArnd Bergmann }
28387a229387SArnd Bergmann 
2839590d4693SBen Hutchings /* Handle ioctls that use ifreq::ifr_data and just need struct ifreq converted */
2840590d4693SBen Hutchings static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd,
28416b96018bSArnd Bergmann 				 struct compat_ifreq __user *u_ifreq32)
28427a229387SArnd Bergmann {
28437a229387SArnd Bergmann 	struct ifreq __user *u_ifreq64;
28447a229387SArnd Bergmann 	char tmp_buf[IFNAMSIZ];
28457a229387SArnd Bergmann 	void __user *data64;
28467a229387SArnd Bergmann 	u32 data32;
28477a229387SArnd Bergmann 
28487a229387SArnd Bergmann 	if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]),
28497a229387SArnd Bergmann 			   IFNAMSIZ))
28507a229387SArnd Bergmann 		return -EFAULT;
2851417c3522SBen Hutchings 	if (get_user(data32, &u_ifreq32->ifr_ifru.ifru_data))
28527a229387SArnd Bergmann 		return -EFAULT;
28537a229387SArnd Bergmann 	data64 = compat_ptr(data32);
28547a229387SArnd Bergmann 
28557a229387SArnd Bergmann 	u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
28567a229387SArnd Bergmann 
28577a229387SArnd Bergmann 	if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0],
28587a229387SArnd Bergmann 			 IFNAMSIZ))
28597a229387SArnd Bergmann 		return -EFAULT;
2860417c3522SBen Hutchings 	if (put_user(data64, &u_ifreq64->ifr_ifru.ifru_data))
28617a229387SArnd Bergmann 		return -EFAULT;
28627a229387SArnd Bergmann 
28636b96018bSArnd Bergmann 	return dev_ioctl(net, cmd, u_ifreq64);
28647a229387SArnd Bergmann }
28657a229387SArnd Bergmann 
28666b96018bSArnd Bergmann static int dev_ifsioc(struct net *net, struct socket *sock,
28676b96018bSArnd Bergmann 			 unsigned int cmd, struct compat_ifreq __user *uifr32)
28687a229387SArnd Bergmann {
2869a2116ed2SArnd Bergmann 	struct ifreq __user *uifr;
28707a229387SArnd Bergmann 	int err;
28717a229387SArnd Bergmann 
2872a2116ed2SArnd Bergmann 	uifr = compat_alloc_user_space(sizeof(*uifr));
2873a2116ed2SArnd Bergmann 	if (copy_in_user(uifr, uifr32, sizeof(*uifr32)))
28747a229387SArnd Bergmann 		return -EFAULT;
2875a2116ed2SArnd Bergmann 
2876a2116ed2SArnd Bergmann 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr);
2877a2116ed2SArnd Bergmann 
28787a229387SArnd Bergmann 	if (!err) {
28797a229387SArnd Bergmann 		switch (cmd) {
28807a229387SArnd Bergmann 		case SIOCGIFFLAGS:
28817a229387SArnd Bergmann 		case SIOCGIFMETRIC:
28827a229387SArnd Bergmann 		case SIOCGIFMTU:
28837a229387SArnd Bergmann 		case SIOCGIFMEM:
28847a229387SArnd Bergmann 		case SIOCGIFHWADDR:
28857a229387SArnd Bergmann 		case SIOCGIFINDEX:
28867a229387SArnd Bergmann 		case SIOCGIFADDR:
28877a229387SArnd Bergmann 		case SIOCGIFBRDADDR:
28887a229387SArnd Bergmann 		case SIOCGIFDSTADDR:
28897a229387SArnd Bergmann 		case SIOCGIFNETMASK:
2890fab2532bSArnd Bergmann 		case SIOCGIFPFLAGS:
28917a229387SArnd Bergmann 		case SIOCGIFTXQLEN:
2892fab2532bSArnd Bergmann 		case SIOCGMIIPHY:
2893fab2532bSArnd Bergmann 		case SIOCGMIIREG:
2894a2116ed2SArnd Bergmann 			if (copy_in_user(uifr32, uifr, sizeof(*uifr32)))
2895a2116ed2SArnd Bergmann 				err = -EFAULT;
28967a229387SArnd Bergmann 			break;
2897a2116ed2SArnd Bergmann 		}
2898a2116ed2SArnd Bergmann 	}
2899a2116ed2SArnd Bergmann 	return err;
2900a2116ed2SArnd Bergmann }
2901a2116ed2SArnd Bergmann 
2902a2116ed2SArnd Bergmann static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
2903a2116ed2SArnd Bergmann 			struct compat_ifreq __user *uifr32)
2904a2116ed2SArnd Bergmann {
2905a2116ed2SArnd Bergmann 	struct ifreq ifr;
2906a2116ed2SArnd Bergmann 	struct compat_ifmap __user *uifmap32;
2907a2116ed2SArnd Bergmann 	mm_segment_t old_fs;
2908a2116ed2SArnd Bergmann 	int err;
2909a2116ed2SArnd Bergmann 
2910a2116ed2SArnd Bergmann 	uifmap32 = &uifr32->ifr_ifru.ifru_map;
2911a2116ed2SArnd Bergmann 	err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name));
29123ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
29133ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
29143ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
29153ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.irq, &uifmap32->irq);
29163ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.dma, &uifmap32->dma);
29173ddc5b46SMathieu Desnoyers 	err |= get_user(ifr.ifr_map.port, &uifmap32->port);
2918a2116ed2SArnd Bergmann 	if (err)
2919a2116ed2SArnd Bergmann 		return -EFAULT;
2920a2116ed2SArnd Bergmann 
2921a2116ed2SArnd Bergmann 	old_fs = get_fs();
2922a2116ed2SArnd Bergmann 	set_fs(KERNEL_DS);
2923c3f52ae6Sstephen hemminger 	err = dev_ioctl(net, cmd, (void  __user __force *)&ifr);
2924a2116ed2SArnd Bergmann 	set_fs(old_fs);
2925a2116ed2SArnd Bergmann 
2926a2116ed2SArnd Bergmann 	if (cmd == SIOCGIFMAP && !err) {
29277a229387SArnd Bergmann 		err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name));
29283ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
29293ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
29303ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
29313ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.irq, &uifmap32->irq);
29323ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.dma, &uifmap32->dma);
29333ddc5b46SMathieu Desnoyers 		err |= put_user(ifr.ifr_map.port, &uifmap32->port);
29347a229387SArnd Bergmann 		if (err)
29357a229387SArnd Bergmann 			err = -EFAULT;
29367a229387SArnd Bergmann 	}
29377a229387SArnd Bergmann 	return err;
29387a229387SArnd Bergmann }
29397a229387SArnd Bergmann 
29407a229387SArnd Bergmann struct rtentry32 {
29417a229387SArnd Bergmann 	u32		rt_pad1;
29427a229387SArnd Bergmann 	struct sockaddr rt_dst;         /* target address               */
29437a229387SArnd Bergmann 	struct sockaddr rt_gateway;     /* gateway addr (RTF_GATEWAY)   */
29447a229387SArnd Bergmann 	struct sockaddr rt_genmask;     /* target network mask (IP)     */
29457a229387SArnd Bergmann 	unsigned short	rt_flags;
29467a229387SArnd Bergmann 	short		rt_pad2;
29477a229387SArnd Bergmann 	u32		rt_pad3;
29487a229387SArnd Bergmann 	unsigned char	rt_tos;
29497a229387SArnd Bergmann 	unsigned char	rt_class;
29507a229387SArnd Bergmann 	short		rt_pad4;
29517a229387SArnd Bergmann 	short		rt_metric;      /* +1 for binary compatibility! */
29527a229387SArnd Bergmann 	/* char * */ u32 rt_dev;        /* forcing the device at add    */
29537a229387SArnd Bergmann 	u32		rt_mtu;         /* per route MTU/Window         */
29547a229387SArnd Bergmann 	u32		rt_window;      /* Window clamping              */
29557a229387SArnd Bergmann 	unsigned short  rt_irtt;        /* Initial RTT                  */
29567a229387SArnd Bergmann };
29577a229387SArnd Bergmann 
29587a229387SArnd Bergmann struct in6_rtmsg32 {
29597a229387SArnd Bergmann 	struct in6_addr		rtmsg_dst;
29607a229387SArnd Bergmann 	struct in6_addr		rtmsg_src;
29617a229387SArnd Bergmann 	struct in6_addr		rtmsg_gateway;
29627a229387SArnd Bergmann 	u32			rtmsg_type;
29637a229387SArnd Bergmann 	u16			rtmsg_dst_len;
29647a229387SArnd Bergmann 	u16			rtmsg_src_len;
29657a229387SArnd Bergmann 	u32			rtmsg_metric;
29667a229387SArnd Bergmann 	u32			rtmsg_info;
29677a229387SArnd Bergmann 	u32			rtmsg_flags;
29687a229387SArnd Bergmann 	s32			rtmsg_ifindex;
29697a229387SArnd Bergmann };
29707a229387SArnd Bergmann 
29716b96018bSArnd Bergmann static int routing_ioctl(struct net *net, struct socket *sock,
29726b96018bSArnd Bergmann 			 unsigned int cmd, void __user *argp)
29737a229387SArnd Bergmann {
29747a229387SArnd Bergmann 	int ret;
29757a229387SArnd Bergmann 	void *r = NULL;
29767a229387SArnd Bergmann 	struct in6_rtmsg r6;
29777a229387SArnd Bergmann 	struct rtentry r4;
29787a229387SArnd Bergmann 	char devname[16];
29797a229387SArnd Bergmann 	u32 rtdev;
29807a229387SArnd Bergmann 	mm_segment_t old_fs = get_fs();
29817a229387SArnd Bergmann 
29826b96018bSArnd Bergmann 	if (sock && sock->sk && sock->sk->sk_family == AF_INET6) { /* ipv6 */
29836b96018bSArnd Bergmann 		struct in6_rtmsg32 __user *ur6 = argp;
29847a229387SArnd Bergmann 		ret = copy_from_user(&r6.rtmsg_dst, &(ur6->rtmsg_dst),
29857a229387SArnd Bergmann 			3 * sizeof(struct in6_addr));
29863ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_type, &(ur6->rtmsg_type));
29873ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len));
29883ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_src_len, &(ur6->rtmsg_src_len));
29893ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_metric, &(ur6->rtmsg_metric));
29903ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_info, &(ur6->rtmsg_info));
29913ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_flags, &(ur6->rtmsg_flags));
29923ddc5b46SMathieu Desnoyers 		ret |= get_user(r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex));
29937a229387SArnd Bergmann 
29947a229387SArnd Bergmann 		r = (void *) &r6;
29957a229387SArnd Bergmann 	} else { /* ipv4 */
29966b96018bSArnd Bergmann 		struct rtentry32 __user *ur4 = argp;
29977a229387SArnd Bergmann 		ret = copy_from_user(&r4.rt_dst, &(ur4->rt_dst),
29987a229387SArnd Bergmann 					3 * sizeof(struct sockaddr));
29993ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_flags, &(ur4->rt_flags));
30003ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_metric, &(ur4->rt_metric));
30013ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_mtu, &(ur4->rt_mtu));
30023ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_window, &(ur4->rt_window));
30033ddc5b46SMathieu Desnoyers 		ret |= get_user(r4.rt_irtt, &(ur4->rt_irtt));
30043ddc5b46SMathieu Desnoyers 		ret |= get_user(rtdev, &(ur4->rt_dev));
30057a229387SArnd Bergmann 		if (rtdev) {
30067a229387SArnd Bergmann 			ret |= copy_from_user(devname, compat_ptr(rtdev), 15);
3007c3f52ae6Sstephen hemminger 			r4.rt_dev = (char __user __force *)devname;
3008c3f52ae6Sstephen hemminger 			devname[15] = 0;
30097a229387SArnd Bergmann 		} else
30107a229387SArnd Bergmann 			r4.rt_dev = NULL;
30117a229387SArnd Bergmann 
30127a229387SArnd Bergmann 		r = (void *) &r4;
30137a229387SArnd Bergmann 	}
30147a229387SArnd Bergmann 
30157a229387SArnd Bergmann 	if (ret) {
30167a229387SArnd Bergmann 		ret = -EFAULT;
30177a229387SArnd Bergmann 		goto out;
30187a229387SArnd Bergmann 	}
30197a229387SArnd Bergmann 
30207a229387SArnd Bergmann 	set_fs(KERNEL_DS);
30216b96018bSArnd Bergmann 	ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r);
30227a229387SArnd Bergmann 	set_fs(old_fs);
30237a229387SArnd Bergmann 
30247a229387SArnd Bergmann out:
30257a229387SArnd Bergmann 	return ret;
30267a229387SArnd Bergmann }
30277a229387SArnd Bergmann 
30287a229387SArnd Bergmann /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE
30297a229387SArnd Bergmann  * for some operations; this forces use of the newer bridge-utils that
303025985edcSLucas De Marchi  * use compatible ioctls
30317a229387SArnd Bergmann  */
30326b96018bSArnd Bergmann static int old_bridge_ioctl(compat_ulong_t __user *argp)
30337a229387SArnd Bergmann {
30346b96018bSArnd Bergmann 	compat_ulong_t tmp;
30357a229387SArnd Bergmann 
30366b96018bSArnd Bergmann 	if (get_user(tmp, argp))
30377a229387SArnd Bergmann 		return -EFAULT;
30387a229387SArnd Bergmann 	if (tmp == BRCTL_GET_VERSION)
30397a229387SArnd Bergmann 		return BRCTL_VERSION + 1;
30407a229387SArnd Bergmann 	return -EINVAL;
30417a229387SArnd Bergmann }
30427a229387SArnd Bergmann 
30436b96018bSArnd Bergmann static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
30446b96018bSArnd Bergmann 			 unsigned int cmd, unsigned long arg)
30456b96018bSArnd Bergmann {
30466b96018bSArnd Bergmann 	void __user *argp = compat_ptr(arg);
30476b96018bSArnd Bergmann 	struct sock *sk = sock->sk;
30486b96018bSArnd Bergmann 	struct net *net = sock_net(sk);
30497a229387SArnd Bergmann 
30506b96018bSArnd Bergmann 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
3051590d4693SBen Hutchings 		return compat_ifr_data_ioctl(net, cmd, argp);
30527a229387SArnd Bergmann 
30536b96018bSArnd Bergmann 	switch (cmd) {
30546b96018bSArnd Bergmann 	case SIOCSIFBR:
30556b96018bSArnd Bergmann 	case SIOCGIFBR:
30566b96018bSArnd Bergmann 		return old_bridge_ioctl(argp);
30576b96018bSArnd Bergmann 	case SIOCGIFNAME:
30586b96018bSArnd Bergmann 		return dev_ifname32(net, argp);
30596b96018bSArnd Bergmann 	case SIOCGIFCONF:
30606b96018bSArnd Bergmann 		return dev_ifconf(net, argp);
30616b96018bSArnd Bergmann 	case SIOCETHTOOL:
30626b96018bSArnd Bergmann 		return ethtool_ioctl(net, argp);
30637a50a240SArnd Bergmann 	case SIOCWANDEV:
30647a50a240SArnd Bergmann 		return compat_siocwandev(net, argp);
3065a2116ed2SArnd Bergmann 	case SIOCGIFMAP:
3066a2116ed2SArnd Bergmann 	case SIOCSIFMAP:
3067a2116ed2SArnd Bergmann 		return compat_sioc_ifmap(net, cmd, argp);
30686b96018bSArnd Bergmann 	case SIOCBONDENSLAVE:
30696b96018bSArnd Bergmann 	case SIOCBONDRELEASE:
30706b96018bSArnd Bergmann 	case SIOCBONDSETHWADDR:
30716b96018bSArnd Bergmann 	case SIOCBONDCHANGEACTIVE:
30726b96018bSArnd Bergmann 		return bond_ioctl(net, cmd, argp);
30736b96018bSArnd Bergmann 	case SIOCADDRT:
30746b96018bSArnd Bergmann 	case SIOCDELRT:
30756b96018bSArnd Bergmann 		return routing_ioctl(net, sock, cmd, argp);
30766b96018bSArnd Bergmann 	case SIOCGSTAMP:
30776b96018bSArnd Bergmann 		return do_siocgstamp(net, sock, cmd, argp);
30786b96018bSArnd Bergmann 	case SIOCGSTAMPNS:
30796b96018bSArnd Bergmann 		return do_siocgstampns(net, sock, cmd, argp);
3080590d4693SBen Hutchings 	case SIOCBONDSLAVEINFOQUERY:
3081590d4693SBen Hutchings 	case SIOCBONDINFOQUERY:
3082a2116ed2SArnd Bergmann 	case SIOCSHWTSTAMP:
3083fd468c74SBen Hutchings 	case SIOCGHWTSTAMP:
3084590d4693SBen Hutchings 		return compat_ifr_data_ioctl(net, cmd, argp);
30857a229387SArnd Bergmann 
30866b96018bSArnd Bergmann 	case FIOSETOWN:
30876b96018bSArnd Bergmann 	case SIOCSPGRP:
30886b96018bSArnd Bergmann 	case FIOGETOWN:
30896b96018bSArnd Bergmann 	case SIOCGPGRP:
30906b96018bSArnd Bergmann 	case SIOCBRADDBR:
30916b96018bSArnd Bergmann 	case SIOCBRDELBR:
30926b96018bSArnd Bergmann 	case SIOCGIFVLAN:
30936b96018bSArnd Bergmann 	case SIOCSIFVLAN:
30946b96018bSArnd Bergmann 	case SIOCADDDLCI:
30956b96018bSArnd Bergmann 	case SIOCDELDLCI:
30966b96018bSArnd Bergmann 		return sock_ioctl(file, cmd, arg);
30976b96018bSArnd Bergmann 
30986b96018bSArnd Bergmann 	case SIOCGIFFLAGS:
30996b96018bSArnd Bergmann 	case SIOCSIFFLAGS:
31006b96018bSArnd Bergmann 	case SIOCGIFMETRIC:
31016b96018bSArnd Bergmann 	case SIOCSIFMETRIC:
31026b96018bSArnd Bergmann 	case SIOCGIFMTU:
31036b96018bSArnd Bergmann 	case SIOCSIFMTU:
31046b96018bSArnd Bergmann 	case SIOCGIFMEM:
31056b96018bSArnd Bergmann 	case SIOCSIFMEM:
31066b96018bSArnd Bergmann 	case SIOCGIFHWADDR:
31076b96018bSArnd Bergmann 	case SIOCSIFHWADDR:
31086b96018bSArnd Bergmann 	case SIOCADDMULTI:
31096b96018bSArnd Bergmann 	case SIOCDELMULTI:
31106b96018bSArnd Bergmann 	case SIOCGIFINDEX:
31116b96018bSArnd Bergmann 	case SIOCGIFADDR:
31126b96018bSArnd Bergmann 	case SIOCSIFADDR:
31136b96018bSArnd Bergmann 	case SIOCSIFHWBROADCAST:
31146b96018bSArnd Bergmann 	case SIOCDIFADDR:
31156b96018bSArnd Bergmann 	case SIOCGIFBRDADDR:
31166b96018bSArnd Bergmann 	case SIOCSIFBRDADDR:
31176b96018bSArnd Bergmann 	case SIOCGIFDSTADDR:
31186b96018bSArnd Bergmann 	case SIOCSIFDSTADDR:
31196b96018bSArnd Bergmann 	case SIOCGIFNETMASK:
31206b96018bSArnd Bergmann 	case SIOCSIFNETMASK:
31216b96018bSArnd Bergmann 	case SIOCSIFPFLAGS:
31226b96018bSArnd Bergmann 	case SIOCGIFPFLAGS:
31236b96018bSArnd Bergmann 	case SIOCGIFTXQLEN:
31246b96018bSArnd Bergmann 	case SIOCSIFTXQLEN:
31256b96018bSArnd Bergmann 	case SIOCBRADDIF:
31266b96018bSArnd Bergmann 	case SIOCBRDELIF:
31279177efd3SArnd Bergmann 	case SIOCSIFNAME:
31289177efd3SArnd Bergmann 	case SIOCGMIIPHY:
31299177efd3SArnd Bergmann 	case SIOCGMIIREG:
31309177efd3SArnd Bergmann 	case SIOCSMIIREG:
31316b96018bSArnd Bergmann 		return dev_ifsioc(net, sock, cmd, argp);
31329177efd3SArnd Bergmann 
31336b96018bSArnd Bergmann 	case SIOCSARP:
31346b96018bSArnd Bergmann 	case SIOCGARP:
31356b96018bSArnd Bergmann 	case SIOCDARP:
31366b96018bSArnd Bergmann 	case SIOCATMARK:
31379177efd3SArnd Bergmann 		return sock_do_ioctl(net, sock, cmd, arg);
31389177efd3SArnd Bergmann 	}
31399177efd3SArnd Bergmann 
31406b96018bSArnd Bergmann 	return -ENOIOCTLCMD;
31416b96018bSArnd Bergmann }
31427a229387SArnd Bergmann 
314395c96174SEric Dumazet static long compat_sock_ioctl(struct file *file, unsigned int cmd,
314489bbfc95SShaun Pereira 			      unsigned long arg)
314589bbfc95SShaun Pereira {
314689bbfc95SShaun Pereira 	struct socket *sock = file->private_data;
314789bbfc95SShaun Pereira 	int ret = -ENOIOCTLCMD;
314887de87d5SDavid S. Miller 	struct sock *sk;
314987de87d5SDavid S. Miller 	struct net *net;
315087de87d5SDavid S. Miller 
315187de87d5SDavid S. Miller 	sk = sock->sk;
315287de87d5SDavid S. Miller 	net = sock_net(sk);
315389bbfc95SShaun Pereira 
315489bbfc95SShaun Pereira 	if (sock->ops->compat_ioctl)
315589bbfc95SShaun Pereira 		ret = sock->ops->compat_ioctl(sock, cmd, arg);
315689bbfc95SShaun Pereira 
315787de87d5SDavid S. Miller 	if (ret == -ENOIOCTLCMD &&
315887de87d5SDavid S. Miller 	    (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST))
315987de87d5SDavid S. Miller 		ret = compat_wext_handle_ioctl(net, cmd, arg);
316087de87d5SDavid S. Miller 
31616b96018bSArnd Bergmann 	if (ret == -ENOIOCTLCMD)
31626b96018bSArnd Bergmann 		ret = compat_sock_ioctl_trans(file, sock, cmd, arg);
31636b96018bSArnd Bergmann 
316489bbfc95SShaun Pereira 	return ret;
316589bbfc95SShaun Pereira }
316689bbfc95SShaun Pereira #endif
316789bbfc95SShaun Pereira 
3168ac5a488eSSridhar Samudrala int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
3169ac5a488eSSridhar Samudrala {
3170ac5a488eSSridhar Samudrala 	return sock->ops->bind(sock, addr, addrlen);
3171ac5a488eSSridhar Samudrala }
3172c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_bind);
3173ac5a488eSSridhar Samudrala 
3174ac5a488eSSridhar Samudrala int kernel_listen(struct socket *sock, int backlog)
3175ac5a488eSSridhar Samudrala {
3176ac5a488eSSridhar Samudrala 	return sock->ops->listen(sock, backlog);
3177ac5a488eSSridhar Samudrala }
3178c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_listen);
3179ac5a488eSSridhar Samudrala 
3180ac5a488eSSridhar Samudrala int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
3181ac5a488eSSridhar Samudrala {
3182ac5a488eSSridhar Samudrala 	struct sock *sk = sock->sk;
3183ac5a488eSSridhar Samudrala 	int err;
3184ac5a488eSSridhar Samudrala 
3185ac5a488eSSridhar Samudrala 	err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
3186ac5a488eSSridhar Samudrala 			       newsock);
3187ac5a488eSSridhar Samudrala 	if (err < 0)
3188ac5a488eSSridhar Samudrala 		goto done;
3189ac5a488eSSridhar Samudrala 
3190ac5a488eSSridhar Samudrala 	err = sock->ops->accept(sock, *newsock, flags);
3191ac5a488eSSridhar Samudrala 	if (err < 0) {
3192ac5a488eSSridhar Samudrala 		sock_release(*newsock);
3193fa8705b0STony Battersby 		*newsock = NULL;
3194ac5a488eSSridhar Samudrala 		goto done;
3195ac5a488eSSridhar Samudrala 	}
3196ac5a488eSSridhar Samudrala 
3197ac5a488eSSridhar Samudrala 	(*newsock)->ops = sock->ops;
31981b08534eSWei Yongjun 	__module_get((*newsock)->ops->owner);
3199ac5a488eSSridhar Samudrala 
3200ac5a488eSSridhar Samudrala done:
3201ac5a488eSSridhar Samudrala 	return err;
3202ac5a488eSSridhar Samudrala }
3203c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_accept);
3204ac5a488eSSridhar Samudrala 
3205ac5a488eSSridhar Samudrala int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
3206ac5a488eSSridhar Samudrala 		   int flags)
3207ac5a488eSSridhar Samudrala {
3208ac5a488eSSridhar Samudrala 	return sock->ops->connect(sock, addr, addrlen, flags);
3209ac5a488eSSridhar Samudrala }
3210c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_connect);
3211ac5a488eSSridhar Samudrala 
3212ac5a488eSSridhar Samudrala int kernel_getsockname(struct socket *sock, struct sockaddr *addr,
3213ac5a488eSSridhar Samudrala 			 int *addrlen)
3214ac5a488eSSridhar Samudrala {
3215ac5a488eSSridhar Samudrala 	return sock->ops->getname(sock, addr, addrlen, 0);
3216ac5a488eSSridhar Samudrala }
3217c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockname);
3218ac5a488eSSridhar Samudrala 
3219ac5a488eSSridhar Samudrala int kernel_getpeername(struct socket *sock, struct sockaddr *addr,
3220ac5a488eSSridhar Samudrala 			 int *addrlen)
3221ac5a488eSSridhar Samudrala {
3222ac5a488eSSridhar Samudrala 	return sock->ops->getname(sock, addr, addrlen, 1);
3223ac5a488eSSridhar Samudrala }
3224c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getpeername);
3225ac5a488eSSridhar Samudrala 
3226ac5a488eSSridhar Samudrala int kernel_getsockopt(struct socket *sock, int level, int optname,
3227ac5a488eSSridhar Samudrala 			char *optval, int *optlen)
3228ac5a488eSSridhar Samudrala {
3229ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3230fb8621bbSNamhyung Kim 	char __user *uoptval;
3231fb8621bbSNamhyung Kim 	int __user *uoptlen;
3232ac5a488eSSridhar Samudrala 	int err;
3233ac5a488eSSridhar Samudrala 
3234fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3235fb8621bbSNamhyung Kim 	uoptlen = (int __user __force *) optlen;
3236fb8621bbSNamhyung Kim 
3237ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3238ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3239fb8621bbSNamhyung Kim 		err = sock_getsockopt(sock, level, optname, uoptval, uoptlen);
3240ac5a488eSSridhar Samudrala 	else
3241fb8621bbSNamhyung Kim 		err = sock->ops->getsockopt(sock, level, optname, uoptval,
3242fb8621bbSNamhyung Kim 					    uoptlen);
3243ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3244ac5a488eSSridhar Samudrala 	return err;
3245ac5a488eSSridhar Samudrala }
3246c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockopt);
3247ac5a488eSSridhar Samudrala 
3248ac5a488eSSridhar Samudrala int kernel_setsockopt(struct socket *sock, int level, int optname,
3249b7058842SDavid S. Miller 			char *optval, unsigned int optlen)
3250ac5a488eSSridhar Samudrala {
3251ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3252fb8621bbSNamhyung Kim 	char __user *uoptval;
3253ac5a488eSSridhar Samudrala 	int err;
3254ac5a488eSSridhar Samudrala 
3255fb8621bbSNamhyung Kim 	uoptval = (char __user __force *) optval;
3256fb8621bbSNamhyung Kim 
3257ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3258ac5a488eSSridhar Samudrala 	if (level == SOL_SOCKET)
3259fb8621bbSNamhyung Kim 		err = sock_setsockopt(sock, level, optname, uoptval, optlen);
3260ac5a488eSSridhar Samudrala 	else
3261fb8621bbSNamhyung Kim 		err = sock->ops->setsockopt(sock, level, optname, uoptval,
3262ac5a488eSSridhar Samudrala 					    optlen);
3263ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3264ac5a488eSSridhar Samudrala 	return err;
3265ac5a488eSSridhar Samudrala }
3266c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_setsockopt);
3267ac5a488eSSridhar Samudrala 
3268ac5a488eSSridhar Samudrala int kernel_sendpage(struct socket *sock, struct page *page, int offset,
3269ac5a488eSSridhar Samudrala 		    size_t size, int flags)
3270ac5a488eSSridhar Samudrala {
3271ac5a488eSSridhar Samudrala 	if (sock->ops->sendpage)
3272ac5a488eSSridhar Samudrala 		return sock->ops->sendpage(sock, page, offset, size, flags);
3273ac5a488eSSridhar Samudrala 
3274ac5a488eSSridhar Samudrala 	return sock_no_sendpage(sock, page, offset, size, flags);
3275ac5a488eSSridhar Samudrala }
3276c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendpage);
3277ac5a488eSSridhar Samudrala 
3278ac5a488eSSridhar Samudrala int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg)
3279ac5a488eSSridhar Samudrala {
3280ac5a488eSSridhar Samudrala 	mm_segment_t oldfs = get_fs();
3281ac5a488eSSridhar Samudrala 	int err;
3282ac5a488eSSridhar Samudrala 
3283ac5a488eSSridhar Samudrala 	set_fs(KERNEL_DS);
3284ac5a488eSSridhar Samudrala 	err = sock->ops->ioctl(sock, cmd, arg);
3285ac5a488eSSridhar Samudrala 	set_fs(oldfs);
3286ac5a488eSSridhar Samudrala 
3287ac5a488eSSridhar Samudrala 	return err;
3288ac5a488eSSridhar Samudrala }
3289c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sock_ioctl);
3290ac5a488eSSridhar Samudrala 
329191cf45f0STrond Myklebust int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
329291cf45f0STrond Myklebust {
329391cf45f0STrond Myklebust 	return sock->ops->shutdown(sock, how);
329491cf45f0STrond Myklebust }
329591cf45f0STrond Myklebust EXPORT_SYMBOL(kernel_sock_shutdown);
3296