xref: /linux-6.15/net/socket.c (revision 983e0e4e)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * NET		An implementation of the SOCKET network access protocol.
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  * Version:	@(#)socket.c	1.1.93	18/02/95
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  * Authors:	Orest Zborowski, <[email protected]>
802c30a84SJesper Juhl  *		Ross Biro
91da177e4SLinus Torvalds  *		Fred N. van Kempen, <[email protected]>
101da177e4SLinus Torvalds  *
111da177e4SLinus Torvalds  * Fixes:
121da177e4SLinus Torvalds  *		Anonymous	:	NOTSOCK/BADF cleanup. Error fix in
131da177e4SLinus Torvalds  *					shutdown()
141da177e4SLinus Torvalds  *		Alan Cox	:	verify_area() fixes
151da177e4SLinus Torvalds  *		Alan Cox	:	Removed DDI
161da177e4SLinus Torvalds  *		Jonathan Kamens	:	SOCK_DGRAM reconnect bug
171da177e4SLinus Torvalds  *		Alan Cox	:	Moved a load of checks to the very
181da177e4SLinus Torvalds  *					top level.
191da177e4SLinus Torvalds  *		Alan Cox	:	Move address structures to/from user
201da177e4SLinus Torvalds  *					mode above the protocol layers.
211da177e4SLinus Torvalds  *		Rob Janssen	:	Allow 0 length sends.
221da177e4SLinus Torvalds  *		Alan Cox	:	Asynchronous I/O support (cribbed from the
231da177e4SLinus Torvalds  *					tty drivers).
241da177e4SLinus Torvalds  *		Niibe Yutaka	:	Asynchronous I/O for writes (4.4BSD style)
251da177e4SLinus Torvalds  *		Jeff Uphoff	:	Made max number of sockets command-line
261da177e4SLinus Torvalds  *					configurable.
271da177e4SLinus Torvalds  *		Matti Aarnio	:	Made the number of sockets dynamic,
281da177e4SLinus Torvalds  *					to be allocated when needed, and mr.
291da177e4SLinus Torvalds  *					Uphoff's max is used as max to be
301da177e4SLinus Torvalds  *					allowed to allocate.
311da177e4SLinus Torvalds  *		Linus		:	Argh. removed all the socket allocation
321da177e4SLinus Torvalds  *					altogether: it's in the inode now.
331da177e4SLinus Torvalds  *		Alan Cox	:	Made sock_alloc()/sock_release() public
341da177e4SLinus Torvalds  *					for NetROM and future kernel nfsd type
351da177e4SLinus Torvalds  *					stuff.
361da177e4SLinus Torvalds  *		Alan Cox	:	sendmsg/recvmsg basics.
371da177e4SLinus Torvalds  *		Tom Dyas	:	Export net symbols.
381da177e4SLinus Torvalds  *		Marcin Dalecki	:	Fixed problems with CONFIG_NET="n".
391da177e4SLinus Torvalds  *		Alan Cox	:	Added thread locking to sys_* calls
401da177e4SLinus Torvalds  *					for sockets. May have errors at the
411da177e4SLinus Torvalds  *					moment.
421da177e4SLinus Torvalds  *		Kevin Buhr	:	Fixed the dumb errors in the above.
431da177e4SLinus Torvalds  *		Andi Kleen	:	Some small cleanups, optimizations,
441da177e4SLinus Torvalds  *					and fixed a copy_from_user() bug.
451da177e4SLinus Torvalds  *		Tigran Aivazian	:	sys_send(args) calls sys_sendto(args, NULL, 0)
461da177e4SLinus Torvalds  *		Tigran Aivazian	:	Made listen(2) backlog sanity checks
471da177e4SLinus Torvalds  *					protocol-independent
481da177e4SLinus Torvalds  *
491da177e4SLinus Torvalds  *	This module is effectively the top level interface to the BSD socket
501da177e4SLinus Torvalds  *	paradigm.
511da177e4SLinus Torvalds  *
521da177e4SLinus Torvalds  *	Based upon Swansea University Computer Society NET3.039
531da177e4SLinus Torvalds  */
541da177e4SLinus Torvalds 
55aef2fedaSJakub Kicinski #include <linux/bpf-cgroup.h>
56cc69837fSJakub Kicinski #include <linux/ethtool.h>
571da177e4SLinus Torvalds #include <linux/mm.h>
581da177e4SLinus Torvalds #include <linux/socket.h>
591da177e4SLinus Torvalds #include <linux/file.h>
602dc334f1SDavid Howells #include <linux/splice.h>
611da177e4SLinus Torvalds #include <linux/net.h>
621da177e4SLinus Torvalds #include <linux/interrupt.h>
63aaca0bdcSUlrich Drepper #include <linux/thread_info.h>
6455737fdaSStephen Hemminger #include <linux/rcupdate.h>
651da177e4SLinus Torvalds #include <linux/netdevice.h>
661da177e4SLinus Torvalds #include <linux/proc_fs.h>
671da177e4SLinus Torvalds #include <linux/seq_file.h>
684a3e2f71SArjan van de Ven #include <linux/mutex.h>
691da177e4SLinus Torvalds #include <linux/if_bridge.h>
7020380731SArnaldo Carvalho de Melo #include <linux/if_vlan.h>
71408eccceSDaniel Borkmann #include <linux/ptp_classify.h>
721da177e4SLinus Torvalds #include <linux/init.h>
731da177e4SLinus Torvalds #include <linux/poll.h>
741da177e4SLinus Torvalds #include <linux/cache.h>
751da177e4SLinus Torvalds #include <linux/module.h>
761da177e4SLinus Torvalds #include <linux/highmem.h>
771da177e4SLinus Torvalds #include <linux/mount.h>
78fba9be49SDavid Howells #include <linux/pseudo_fs.h>
791da177e4SLinus Torvalds #include <linux/security.h>
801da177e4SLinus Torvalds #include <linux/syscalls.h>
811da177e4SLinus Torvalds #include <linux/compat.h>
821da177e4SLinus Torvalds #include <linux/kmod.h>
833ec3b2fbSDavid Woodhouse #include <linux/audit.h>
84d86b5e0eSAdrian Bunk #include <linux/wireless.h>
851b8d7ae4SEric W. Biederman #include <linux/nsproxy.h>
861fd7317dSNick Black #include <linux/magic.h>
875a0e3ad6STejun Heo #include <linux/slab.h>
88600e1779SMasatake YAMATO #include <linux/xattr.h>
89c8e8cd57SJeremy Cline #include <linux/nospec.h>
908c3c447bSPaolo Abeni #include <linux/indirect_call_wrapper.h>
918c9a6f54SPavel Begunkov #include <linux/io_uring/net.h>
921da177e4SLinus Torvalds 
937c0f6ba6SLinus Torvalds #include <linux/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>
106c7dc504eSArnd Bergmann #include <linux/termios.h>
1076b96018bSArnd Bergmann #include <linux/sockios.h>
108076bb0c8SEliezer Tamir #include <net/busy_poll.h>
109f24b9be5SWillem de Bruijn #include <linux/errqueue.h>
110d7c08826SYangbo Lu #include <linux/ptp_clock_kernel.h>
1116e6eda44SYunhui Cui #include <trace/events/sock.h>
11206021292SEliezer Tamir 
11321520e74SJakub Kicinski #include "core/dev.h"
11421520e74SJakub Kicinski 
115e0d1095aSCong Wang #ifdef CONFIG_NET_RX_BUSY_POLL
11664b0dc51SEliezer Tamir unsigned int sysctl_net_busy_read __read_mostly;
11764b0dc51SEliezer Tamir unsigned int sysctl_net_busy_poll __read_mostly;
11806021292SEliezer Tamir #endif
1196b96018bSArnd Bergmann 
1208ae5e030SAl Viro static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to);
1218ae5e030SAl Viro static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from);
1221da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma);
1231da177e4SLinus Torvalds 
1241da177e4SLinus Torvalds static int sock_close(struct inode *inode, struct file *file);
125a11e1d43SLinus Torvalds static __poll_t sock_poll(struct file *file,
126a11e1d43SLinus Torvalds 			      struct poll_table_struct *wait);
12789bddce5SStephen Hemminger static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
12889bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
12989bbfc95SShaun Pereira static long compat_sock_ioctl(struct file *file,
13089bbfc95SShaun Pereira 			      unsigned int cmd, unsigned long arg);
13189bbfc95SShaun Pereira #endif
1321da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on);
1339c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
1349c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
1359c55e01cSJens Axboe 				unsigned int flags);
1362bfc6685SDavid Howells static void sock_splice_eof(struct file *file);
137542d3065SArnd Bergmann 
138542d3065SArnd Bergmann #ifdef CONFIG_PROC_FS
sock_show_fdinfo(struct seq_file * m,struct file * f)139542d3065SArnd Bergmann static void sock_show_fdinfo(struct seq_file *m, struct file *f)
140542d3065SArnd Bergmann {
141542d3065SArnd Bergmann 	struct socket *sock = f->private_data;
1421ded5e5aSEric Dumazet 	const struct proto_ops *ops = READ_ONCE(sock->ops);
143542d3065SArnd Bergmann 
1441ded5e5aSEric Dumazet 	if (ops->show_fdinfo)
1451ded5e5aSEric Dumazet 		ops->show_fdinfo(m, sock);
146542d3065SArnd Bergmann }
147542d3065SArnd Bergmann #else
148542d3065SArnd Bergmann #define sock_show_fdinfo NULL
149542d3065SArnd Bergmann #endif
1501da177e4SLinus Torvalds 
1511da177e4SLinus Torvalds /*
1521da177e4SLinus Torvalds  *	Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
1531da177e4SLinus Torvalds  *	in the operation structures but are done directly via the socketcall() multiplexor.
1541da177e4SLinus Torvalds  */
1551da177e4SLinus Torvalds 
156da7071d7SArjan van de Ven static const struct file_operations socket_file_ops = {
1571da177e4SLinus Torvalds 	.owner =	THIS_MODULE,
1588ae5e030SAl Viro 	.read_iter =	sock_read_iter,
1598ae5e030SAl Viro 	.write_iter =	sock_write_iter,
1601da177e4SLinus Torvalds 	.poll =		sock_poll,
1611da177e4SLinus Torvalds 	.unlocked_ioctl = sock_ioctl,
16289bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
16389bbfc95SShaun Pereira 	.compat_ioctl = compat_sock_ioctl,
16489bbfc95SShaun Pereira #endif
1658e9fad0eSBreno Leitao 	.uring_cmd =    io_uring_cmd_sock,
1661da177e4SLinus Torvalds 	.mmap =		sock_mmap,
1671da177e4SLinus Torvalds 	.release =	sock_close,
1681da177e4SLinus Torvalds 	.fasync =	sock_fasync,
1692dc334f1SDavid Howells 	.splice_write = splice_to_socket,
1709c55e01cSJens Axboe 	.splice_read =	sock_splice_read,
1712bfc6685SDavid Howells 	.splice_eof =	sock_splice_eof,
172b4653342SKirill Tkhai 	.show_fdinfo =	sock_show_fdinfo,
1731da177e4SLinus Torvalds };
1741da177e4SLinus Torvalds 
175fe0bdbdeSYejune Deng static const char * const pf_family_names[] = {
176fe0bdbdeSYejune Deng 	[PF_UNSPEC]	= "PF_UNSPEC",
177fe0bdbdeSYejune Deng 	[PF_UNIX]	= "PF_UNIX/PF_LOCAL",
178fe0bdbdeSYejune Deng 	[PF_INET]	= "PF_INET",
179fe0bdbdeSYejune Deng 	[PF_AX25]	= "PF_AX25",
180fe0bdbdeSYejune Deng 	[PF_IPX]	= "PF_IPX",
181fe0bdbdeSYejune Deng 	[PF_APPLETALK]	= "PF_APPLETALK",
182fe0bdbdeSYejune Deng 	[PF_NETROM]	= "PF_NETROM",
183fe0bdbdeSYejune Deng 	[PF_BRIDGE]	= "PF_BRIDGE",
184fe0bdbdeSYejune Deng 	[PF_ATMPVC]	= "PF_ATMPVC",
185fe0bdbdeSYejune Deng 	[PF_X25]	= "PF_X25",
186fe0bdbdeSYejune Deng 	[PF_INET6]	= "PF_INET6",
187fe0bdbdeSYejune Deng 	[PF_ROSE]	= "PF_ROSE",
188fe0bdbdeSYejune Deng 	[PF_DECnet]	= "PF_DECnet",
189fe0bdbdeSYejune Deng 	[PF_NETBEUI]	= "PF_NETBEUI",
190fe0bdbdeSYejune Deng 	[PF_SECURITY]	= "PF_SECURITY",
191fe0bdbdeSYejune Deng 	[PF_KEY]	= "PF_KEY",
192fe0bdbdeSYejune Deng 	[PF_NETLINK]	= "PF_NETLINK/PF_ROUTE",
193fe0bdbdeSYejune Deng 	[PF_PACKET]	= "PF_PACKET",
194fe0bdbdeSYejune Deng 	[PF_ASH]	= "PF_ASH",
195fe0bdbdeSYejune Deng 	[PF_ECONET]	= "PF_ECONET",
196fe0bdbdeSYejune Deng 	[PF_ATMSVC]	= "PF_ATMSVC",
197fe0bdbdeSYejune Deng 	[PF_RDS]	= "PF_RDS",
198fe0bdbdeSYejune Deng 	[PF_SNA]	= "PF_SNA",
199fe0bdbdeSYejune Deng 	[PF_IRDA]	= "PF_IRDA",
200fe0bdbdeSYejune Deng 	[PF_PPPOX]	= "PF_PPPOX",
201fe0bdbdeSYejune Deng 	[PF_WANPIPE]	= "PF_WANPIPE",
202fe0bdbdeSYejune Deng 	[PF_LLC]	= "PF_LLC",
203fe0bdbdeSYejune Deng 	[PF_IB]		= "PF_IB",
204fe0bdbdeSYejune Deng 	[PF_MPLS]	= "PF_MPLS",
205fe0bdbdeSYejune Deng 	[PF_CAN]	= "PF_CAN",
206fe0bdbdeSYejune Deng 	[PF_TIPC]	= "PF_TIPC",
207fe0bdbdeSYejune Deng 	[PF_BLUETOOTH]	= "PF_BLUETOOTH",
208fe0bdbdeSYejune Deng 	[PF_IUCV]	= "PF_IUCV",
209fe0bdbdeSYejune Deng 	[PF_RXRPC]	= "PF_RXRPC",
210fe0bdbdeSYejune Deng 	[PF_ISDN]	= "PF_ISDN",
211fe0bdbdeSYejune Deng 	[PF_PHONET]	= "PF_PHONET",
212fe0bdbdeSYejune Deng 	[PF_IEEE802154]	= "PF_IEEE802154",
213fe0bdbdeSYejune Deng 	[PF_CAIF]	= "PF_CAIF",
214fe0bdbdeSYejune Deng 	[PF_ALG]	= "PF_ALG",
215fe0bdbdeSYejune Deng 	[PF_NFC]	= "PF_NFC",
216fe0bdbdeSYejune Deng 	[PF_VSOCK]	= "PF_VSOCK",
217fe0bdbdeSYejune Deng 	[PF_KCM]	= "PF_KCM",
218fe0bdbdeSYejune Deng 	[PF_QIPCRTR]	= "PF_QIPCRTR",
219fe0bdbdeSYejune Deng 	[PF_SMC]	= "PF_SMC",
220fe0bdbdeSYejune Deng 	[PF_XDP]	= "PF_XDP",
221bc49d816SJeremy Kerr 	[PF_MCTP]	= "PF_MCTP",
222fe0bdbdeSYejune Deng };
223fe0bdbdeSYejune Deng 
2241da177e4SLinus Torvalds /*
2251da177e4SLinus Torvalds  *	The protocol list. Each protocol is registered in here.
2261da177e4SLinus Torvalds  */
2271da177e4SLinus Torvalds 
2281da177e4SLinus Torvalds static DEFINE_SPINLOCK(net_family_lock);
229190683a9SEric Dumazet static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly;
2301da177e4SLinus Torvalds 
2311da177e4SLinus Torvalds /*
23289bddce5SStephen Hemminger  * Support routines.
23389bddce5SStephen Hemminger  * Move socket addresses back and forth across the kernel/user
2341da177e4SLinus Torvalds  * divide and look after the messy bits.
2351da177e4SLinus Torvalds  */
2361da177e4SLinus Torvalds 
2371da177e4SLinus Torvalds /**
2381da177e4SLinus Torvalds  *	move_addr_to_kernel	-	copy a socket address into kernel space
2391da177e4SLinus Torvalds  *	@uaddr: Address in user space
2401da177e4SLinus Torvalds  *	@kaddr: Address in kernel space
2411da177e4SLinus Torvalds  *	@ulen: Length in user space
2421da177e4SLinus Torvalds  *
2431da177e4SLinus Torvalds  *	The address is copied into kernel space. If the provided address is
2441da177e4SLinus Torvalds  *	too long an error code of -EINVAL is returned. If the copy gives
2451da177e4SLinus Torvalds  *	invalid addresses -EFAULT is returned. On a success 0 is returned.
2461da177e4SLinus Torvalds  */
2471da177e4SLinus Torvalds 
move_addr_to_kernel(void __user * uaddr,int ulen,struct sockaddr_storage * kaddr)24843db362dSMaciej Żenczykowski int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr)
2491da177e4SLinus Torvalds {
250230b1839SYOSHIFUJI Hideaki 	if (ulen < 0 || ulen > sizeof(struct sockaddr_storage))
2511da177e4SLinus Torvalds 		return -EINVAL;
2521da177e4SLinus Torvalds 	if (ulen == 0)
2531da177e4SLinus Torvalds 		return 0;
2541da177e4SLinus Torvalds 	if (copy_from_user(kaddr, uaddr, ulen))
2551da177e4SLinus Torvalds 		return -EFAULT;
2563ec3b2fbSDavid Woodhouse 	return audit_sockaddr(ulen, kaddr);
2571da177e4SLinus Torvalds }
2581da177e4SLinus Torvalds 
2591da177e4SLinus Torvalds /**
2601da177e4SLinus Torvalds  *	move_addr_to_user	-	copy an address to user space
2611da177e4SLinus Torvalds  *	@kaddr: kernel space address
2621da177e4SLinus Torvalds  *	@klen: length of address in kernel
2631da177e4SLinus Torvalds  *	@uaddr: user space address
2641da177e4SLinus Torvalds  *	@ulen: pointer to user length field
2651da177e4SLinus Torvalds  *
2661da177e4SLinus Torvalds  *	The value pointed to by ulen on entry is the buffer length available.
2671da177e4SLinus Torvalds  *	This is overwritten with the buffer space used. -EINVAL is returned
2681da177e4SLinus Torvalds  *	if an overlong buffer is specified or a negative buffer size. -EFAULT
2691da177e4SLinus Torvalds  *	is returned if either the buffer or the length field are not
2701da177e4SLinus Torvalds  *	accessible.
2711da177e4SLinus Torvalds  *	After copying the data up to the limit the user specifies, the true
2721da177e4SLinus Torvalds  *	length of the data is written over the length limit the user
2731da177e4SLinus Torvalds  *	specified. Zero is returned for a success.
2741da177e4SLinus Torvalds  */
2751da177e4SLinus Torvalds 
move_addr_to_user(struct sockaddr_storage * kaddr,int klen,void __user * uaddr,int __user * ulen)27643db362dSMaciej Żenczykowski static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen,
27711165f14Sstephen hemminger 			     void __user *uaddr, int __user *ulen)
2781da177e4SLinus Torvalds {
2791da177e4SLinus Torvalds 	int err;
2801da177e4SLinus Torvalds 	int len;
2811da177e4SLinus Torvalds 
28268c6beb3SHannes Frederic Sowa 	BUG_ON(klen > sizeof(struct sockaddr_storage));
28389bddce5SStephen Hemminger 	err = get_user(len, ulen);
28489bddce5SStephen Hemminger 	if (err)
2851da177e4SLinus Torvalds 		return err;
2861da177e4SLinus Torvalds 	if (len > klen)
2871da177e4SLinus Torvalds 		len = klen;
28868c6beb3SHannes Frederic Sowa 	if (len < 0)
2891da177e4SLinus Torvalds 		return -EINVAL;
29089bddce5SStephen Hemminger 	if (len) {
291d6fe3945SSteve Grubb 		if (audit_sockaddr(klen, kaddr))
292d6fe3945SSteve Grubb 			return -ENOMEM;
2931da177e4SLinus Torvalds 		if (copy_to_user(uaddr, kaddr, len))
2941da177e4SLinus Torvalds 			return -EFAULT;
2951da177e4SLinus Torvalds 	}
2961da177e4SLinus Torvalds 	/*
2971da177e4SLinus Torvalds 	 *      "fromlen shall refer to the value before truncation.."
2981da177e4SLinus Torvalds 	 *                      1003.1g
2991da177e4SLinus Torvalds 	 */
3001da177e4SLinus Torvalds 	return __put_user(klen, ulen);
3011da177e4SLinus Torvalds }
3021da177e4SLinus Torvalds 
30308009a76SAlexey Dobriyan static struct kmem_cache *sock_inode_cachep __ro_after_init;
3041da177e4SLinus Torvalds 
sock_alloc_inode(struct super_block * sb)3051da177e4SLinus Torvalds static struct inode *sock_alloc_inode(struct super_block *sb)
3061da177e4SLinus Torvalds {
3071da177e4SLinus Torvalds 	struct socket_alloc *ei;
30889bddce5SStephen Hemminger 
309fd60b288SMuchun Song 	ei = alloc_inode_sb(sb, sock_inode_cachep, GFP_KERNEL);
3101da177e4SLinus Torvalds 	if (!ei)
3111da177e4SLinus Torvalds 		return NULL;
312333f7909SAl Viro 	init_waitqueue_head(&ei->socket.wq.wait);
313333f7909SAl Viro 	ei->socket.wq.fasync_list = NULL;
314333f7909SAl Viro 	ei->socket.wq.flags = 0;
3151da177e4SLinus Torvalds 
3161da177e4SLinus Torvalds 	ei->socket.state = SS_UNCONNECTED;
3171da177e4SLinus Torvalds 	ei->socket.flags = 0;
3181da177e4SLinus Torvalds 	ei->socket.ops = NULL;
3191da177e4SLinus Torvalds 	ei->socket.sk = NULL;
3201da177e4SLinus Torvalds 	ei->socket.file = NULL;
3211da177e4SLinus Torvalds 
3221da177e4SLinus Torvalds 	return &ei->vfs_inode;
3231da177e4SLinus Torvalds }
3241da177e4SLinus Torvalds 
sock_free_inode(struct inode * inode)3256d7855c5SAl Viro static void sock_free_inode(struct inode *inode)
3261da177e4SLinus Torvalds {
32743815482SEric Dumazet 	struct socket_alloc *ei;
32843815482SEric Dumazet 
32943815482SEric Dumazet 	ei = container_of(inode, struct socket_alloc, vfs_inode);
33043815482SEric Dumazet 	kmem_cache_free(sock_inode_cachep, ei);
3311da177e4SLinus Torvalds }
3321da177e4SLinus Torvalds 
init_once(void * foo)33351cc5068SAlexey Dobriyan static void init_once(void *foo)
3341da177e4SLinus Torvalds {
3351da177e4SLinus Torvalds 	struct socket_alloc *ei = (struct socket_alloc *)foo;
3361da177e4SLinus Torvalds 
3371da177e4SLinus Torvalds 	inode_init_once(&ei->vfs_inode);
3381da177e4SLinus Torvalds }
3391da177e4SLinus Torvalds 
init_inodecache(void)3401e911632Syuan linyu static void init_inodecache(void)
3411da177e4SLinus Torvalds {
3421da177e4SLinus Torvalds 	sock_inode_cachep = kmem_cache_create("sock_inode_cache",
3431da177e4SLinus Torvalds 					      sizeof(struct socket_alloc),
34489bddce5SStephen Hemminger 					      0,
34589bddce5SStephen Hemminger 					      (SLAB_HWCACHE_ALIGN |
34689bddce5SStephen Hemminger 					       SLAB_RECLAIM_ACCOUNT |
347d4f01c5eSChengming Zhou 					       SLAB_ACCOUNT),
34820c2df83SPaul Mundt 					      init_once);
3491e911632Syuan linyu 	BUG_ON(sock_inode_cachep == NULL);
3501da177e4SLinus Torvalds }
3511da177e4SLinus Torvalds 
352b87221deSAlexey Dobriyan static const struct super_operations sockfs_ops = {
3531da177e4SLinus Torvalds 	.alloc_inode	= sock_alloc_inode,
3546d7855c5SAl Viro 	.free_inode	= sock_free_inode,
3551da177e4SLinus Torvalds 	.statfs		= simple_statfs,
3561da177e4SLinus Torvalds };
3571da177e4SLinus Torvalds 
358c23fbb6bSEric Dumazet /*
359c23fbb6bSEric Dumazet  * sockfs_dname() is called from d_path().
360c23fbb6bSEric Dumazet  */
sockfs_dname(struct dentry * dentry,char * buffer,int buflen)361c23fbb6bSEric Dumazet static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen)
362c23fbb6bSEric Dumazet {
3630f60d288SAl Viro 	return dynamic_dname(buffer, buflen, "socket:[%lu]",
364c5ef6035SDavid Howells 				d_inode(dentry)->i_ino);
365c23fbb6bSEric Dumazet }
366c23fbb6bSEric Dumazet 
3673ba13d17SAl Viro static const struct dentry_operations sockfs_dentry_operations = {
368c23fbb6bSEric Dumazet 	.d_dname  = sockfs_dname,
3691da177e4SLinus Torvalds };
3701da177e4SLinus Torvalds 
sockfs_xattr_get(const struct xattr_handler * handler,struct dentry * dentry,struct inode * inode,const char * suffix,void * value,size_t size)371bba0bd31SAndreas Gruenbacher static int sockfs_xattr_get(const struct xattr_handler *handler,
372bba0bd31SAndreas Gruenbacher 			    struct dentry *dentry, struct inode *inode,
373bba0bd31SAndreas Gruenbacher 			    const char *suffix, void *value, size_t size)
374bba0bd31SAndreas Gruenbacher {
375bba0bd31SAndreas Gruenbacher 	if (value) {
376bba0bd31SAndreas Gruenbacher 		if (dentry->d_name.len + 1 > size)
377bba0bd31SAndreas Gruenbacher 			return -ERANGE;
378bba0bd31SAndreas Gruenbacher 		memcpy(value, dentry->d_name.name, dentry->d_name.len + 1);
379bba0bd31SAndreas Gruenbacher 	}
380bba0bd31SAndreas Gruenbacher 	return dentry->d_name.len + 1;
381bba0bd31SAndreas Gruenbacher }
382bba0bd31SAndreas Gruenbacher 
383bba0bd31SAndreas Gruenbacher #define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname"
384bba0bd31SAndreas Gruenbacher #define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX)
385bba0bd31SAndreas Gruenbacher #define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1)
386bba0bd31SAndreas Gruenbacher 
387bba0bd31SAndreas Gruenbacher static const struct xattr_handler sockfs_xattr_handler = {
388bba0bd31SAndreas Gruenbacher 	.name = XATTR_NAME_SOCKPROTONAME,
389bba0bd31SAndreas Gruenbacher 	.get = sockfs_xattr_get,
390bba0bd31SAndreas Gruenbacher };
391bba0bd31SAndreas Gruenbacher 
sockfs_security_xattr_set(const struct xattr_handler * handler,struct mnt_idmap * idmap,struct dentry * dentry,struct inode * inode,const char * suffix,const void * value,size_t size,int flags)3924a590153SAndreas Gruenbacher static int sockfs_security_xattr_set(const struct xattr_handler *handler,
39339f60c1cSChristian Brauner 				     struct mnt_idmap *idmap,
3944a590153SAndreas Gruenbacher 				     struct dentry *dentry, struct inode *inode,
3954a590153SAndreas Gruenbacher 				     const char *suffix, const void *value,
3964a590153SAndreas Gruenbacher 				     size_t size, int flags)
3974a590153SAndreas Gruenbacher {
3984a590153SAndreas Gruenbacher 	/* Handled by LSM. */
3994a590153SAndreas Gruenbacher 	return -EAGAIN;
4004a590153SAndreas Gruenbacher }
4014a590153SAndreas Gruenbacher 
4024a590153SAndreas Gruenbacher static const struct xattr_handler sockfs_security_xattr_handler = {
4034a590153SAndreas Gruenbacher 	.prefix = XATTR_SECURITY_PREFIX,
4044a590153SAndreas Gruenbacher 	.set = sockfs_security_xattr_set,
4054a590153SAndreas Gruenbacher };
4064a590153SAndreas Gruenbacher 
407295d3c44SWedson Almeida Filho static const struct xattr_handler * const sockfs_xattr_handlers[] = {
408bba0bd31SAndreas Gruenbacher 	&sockfs_xattr_handler,
4094a590153SAndreas Gruenbacher 	&sockfs_security_xattr_handler,
410bba0bd31SAndreas Gruenbacher 	NULL
411bba0bd31SAndreas Gruenbacher };
412bba0bd31SAndreas Gruenbacher 
sockfs_init_fs_context(struct fs_context * fc)413fba9be49SDavid Howells static int sockfs_init_fs_context(struct fs_context *fc)
414c74a1cbbSAl Viro {
415fba9be49SDavid Howells 	struct pseudo_fs_context *ctx = init_pseudo(fc, SOCKFS_MAGIC);
416fba9be49SDavid Howells 	if (!ctx)
417fba9be49SDavid Howells 		return -ENOMEM;
418fba9be49SDavid Howells 	ctx->ops = &sockfs_ops;
419fba9be49SDavid Howells 	ctx->dops = &sockfs_dentry_operations;
420fba9be49SDavid Howells 	ctx->xattr = sockfs_xattr_handlers;
421fba9be49SDavid Howells 	return 0;
422c74a1cbbSAl Viro }
423c74a1cbbSAl Viro 
424c74a1cbbSAl Viro static struct vfsmount *sock_mnt __read_mostly;
425c74a1cbbSAl Viro 
426c74a1cbbSAl Viro static struct file_system_type sock_fs_type = {
427c74a1cbbSAl Viro 	.name =		"sockfs",
428fba9be49SDavid Howells 	.init_fs_context = sockfs_init_fs_context,
429c74a1cbbSAl Viro 	.kill_sb =	kill_anon_super,
430c74a1cbbSAl Viro };
431c74a1cbbSAl Viro 
4321da177e4SLinus Torvalds /*
4331da177e4SLinus Torvalds  *	Obtains the first available file descriptor and sets it up for use.
4341da177e4SLinus Torvalds  *
43539d8c1b6SDavid S. Miller  *	These functions create file structures and maps them to fd space
43639d8c1b6SDavid S. Miller  *	of the current process. On success it returns file descriptor
4371da177e4SLinus Torvalds  *	and file struct implicitly stored in sock->file.
4381da177e4SLinus Torvalds  *	Note that another thread may close file descriptor before we return
4391da177e4SLinus Torvalds  *	from this function. We use the fact that now we do not refer
4401da177e4SLinus Torvalds  *	to socket after mapping. If one day we will need it, this
4411da177e4SLinus Torvalds  *	function will increment ref. count on file by 1.
4421da177e4SLinus Torvalds  *
4431da177e4SLinus Torvalds  *	In any case returned fd MAY BE not valid!
4441da177e4SLinus Torvalds  *	This race condition is unavoidable
4451da177e4SLinus Torvalds  *	with shared fd spaces, we cannot solve it inside kernel,
4461da177e4SLinus Torvalds  *	but we take care of internal coherence yet.
4471da177e4SLinus Torvalds  */
4481da177e4SLinus Torvalds 
4498a3c245cSPedro Tammela /**
4508a3c245cSPedro Tammela  *	sock_alloc_file - Bind a &socket to a &file
4518a3c245cSPedro Tammela  *	@sock: socket
4528a3c245cSPedro Tammela  *	@flags: file status flags
4538a3c245cSPedro Tammela  *	@dname: protocol name
4548a3c245cSPedro Tammela  *
4558a3c245cSPedro Tammela  *	Returns the &file bound with @sock, implicitly storing it
4568a3c245cSPedro Tammela  *	in sock->file. If dname is %NULL, sets to "".
457649c15c7SThadeu Lima de Souza Cascardo  *
458649c15c7SThadeu Lima de Souza Cascardo  *	On failure @sock is released, and an ERR pointer is returned.
459649c15c7SThadeu Lima de Souza Cascardo  *
4608a3c245cSPedro Tammela  *	This function uses GFP_KERNEL internally.
4618a3c245cSPedro Tammela  */
4628a3c245cSPedro Tammela 
sock_alloc_file(struct socket * sock,int flags,const char * dname)463aab174f0SLinus Torvalds struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)
4641da177e4SLinus Torvalds {
4657cbe66b6SAl Viro 	struct file *file;
4661da177e4SLinus Torvalds 
467d93aa9d8SAl Viro 	if (!dname)
468d93aa9d8SAl Viro 		dname = sock->sk ? sock->sk->sk_prot_creator->name : "";
46939d8c1b6SDavid S. Miller 
470d93aa9d8SAl Viro 	file = alloc_file_pseudo(SOCK_INODE(sock), sock_mnt, dname,
471d93aa9d8SAl Viro 				O_RDWR | (flags & O_NONBLOCK),
472cc3808f8SAl Viro 				&socket_file_ops);
473b5ffe634SViresh Kumar 	if (IS_ERR(file)) {
4748e1611e2SAl Viro 		sock_release(sock);
47539b65252SAnatol Pomozov 		return file;
476cc3808f8SAl Viro 	}
4771da177e4SLinus Torvalds 
478fe34db06SJens Axboe 	file->f_mode |= FMODE_NOWAIT;
4791da177e4SLinus Torvalds 	sock->file = file;
48007dc3f07SBenjamin LaHaise 	file->private_data = sock;
481d8e464ecSLinus Torvalds 	stream_open(SOCK_INODE(sock), file);
4822a42754bSAmir Goldstein 	/*
4832a42754bSAmir Goldstein 	 * Disable permission and pre-content events, but enable legacy
4842a42754bSAmir Goldstein 	 * inotify events for legacy users.
4852a42754bSAmir Goldstein 	 */
4862a42754bSAmir Goldstein 	file_set_fsnotify_mode(file, FMODE_NONOTIFY_PERM);
48728407630SAl Viro 	return file;
4881da177e4SLinus Torvalds }
48956b31d1cSAl Viro EXPORT_SYMBOL(sock_alloc_file);
4901da177e4SLinus Torvalds 
sock_map_fd(struct socket * sock,int flags)49156b31d1cSAl Viro static int sock_map_fd(struct socket *sock, int flags)
49239d8c1b6SDavid S. Miller {
49339d8c1b6SDavid S. Miller 	struct file *newfile;
49428407630SAl Viro 	int fd = get_unused_fd_flags(flags);
495ce4bb04cSAl Viro 	if (unlikely(fd < 0)) {
496ce4bb04cSAl Viro 		sock_release(sock);
4971da177e4SLinus Torvalds 		return fd;
498ce4bb04cSAl Viro 	}
4991da177e4SLinus Torvalds 
500aab174f0SLinus Torvalds 	newfile = sock_alloc_file(sock, flags, NULL);
5014546e44cSEnrico Weigelt 	if (!IS_ERR(newfile)) {
5021da177e4SLinus Torvalds 		fd_install(fd, newfile);
5031da177e4SLinus Torvalds 		return fd;
5041da177e4SLinus Torvalds 	}
50528407630SAl Viro 
50628407630SAl Viro 	put_unused_fd(fd);
50728407630SAl Viro 	return PTR_ERR(newfile);
5081da177e4SLinus Torvalds }
5091da177e4SLinus Torvalds 
5108a3c245cSPedro Tammela /**
5118a3c245cSPedro Tammela  *	sock_from_file - Return the &socket bounded to @file.
5128a3c245cSPedro Tammela  *	@file: file
5138a3c245cSPedro Tammela  *
514dba4a925SFlorent Revest  *	On failure returns %NULL.
5158a3c245cSPedro Tammela  */
5168a3c245cSPedro Tammela 
sock_from_file(struct file * file)517dba4a925SFlorent Revest struct socket *sock_from_file(struct file *file)
5186cb153caSBenjamin LaHaise {
51953c0a58bSAl Viro 	if (likely(file->f_op == &socket_file_ops))
520da214a47SJens Axboe 		return file->private_data;	/* set in sock_alloc_file */
5216cb153caSBenjamin LaHaise 
5226cb153caSBenjamin LaHaise 	return NULL;
5236cb153caSBenjamin LaHaise }
524406a3c63SJohn Fastabend EXPORT_SYMBOL(sock_from_file);
5256cb153caSBenjamin LaHaise 
5261da177e4SLinus Torvalds /**
5271da177e4SLinus Torvalds  *	sockfd_lookup - Go from a file number to its socket slot
5281da177e4SLinus Torvalds  *	@fd: file handle
5291da177e4SLinus Torvalds  *	@err: pointer to an error code return
5301da177e4SLinus Torvalds  *
5311da177e4SLinus Torvalds  *	The file handle passed in is locked and the socket it is bound
532241c4667SRosen, Rami  *	to is returned. If an error occurs the err pointer is overwritten
5331da177e4SLinus Torvalds  *	with a negative errno code and NULL is returned. The function checks
5341da177e4SLinus Torvalds  *	for both invalid handles and passing a handle which is not a socket.
5351da177e4SLinus Torvalds  *
5361da177e4SLinus Torvalds  *	On a success the socket object pointer is returned.
5371da177e4SLinus Torvalds  */
5381da177e4SLinus Torvalds 
sockfd_lookup(int fd,int * err)5391da177e4SLinus Torvalds struct socket *sockfd_lookup(int fd, int *err)
5401da177e4SLinus Torvalds {
5411da177e4SLinus Torvalds 	struct file *file;
5421da177e4SLinus Torvalds 	struct socket *sock;
5431da177e4SLinus Torvalds 
54489bddce5SStephen Hemminger 	file = fget(fd);
54589bddce5SStephen Hemminger 	if (!file) {
5461da177e4SLinus Torvalds 		*err = -EBADF;
5471da177e4SLinus Torvalds 		return NULL;
5481da177e4SLinus Torvalds 	}
54989bddce5SStephen Hemminger 
550dba4a925SFlorent Revest 	sock = sock_from_file(file);
551dba4a925SFlorent Revest 	if (!sock) {
552dba4a925SFlorent Revest 		*err = -ENOTSOCK;
5531da177e4SLinus Torvalds 		fput(file);
554dba4a925SFlorent Revest 	}
5556cb153caSBenjamin LaHaise 	return sock;
5561da177e4SLinus Torvalds }
557c6d409cfSEric Dumazet EXPORT_SYMBOL(sockfd_lookup);
5581da177e4SLinus Torvalds 
sockfs_listxattr(struct dentry * dentry,char * buffer,size_t size)559600e1779SMasatake YAMATO static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer,
560600e1779SMasatake YAMATO 				size_t size)
561600e1779SMasatake YAMATO {
562600e1779SMasatake YAMATO 	ssize_t len;
563600e1779SMasatake YAMATO 	ssize_t used = 0;
564600e1779SMasatake YAMATO 
565c5ef6035SDavid Howells 	len = security_inode_listsecurity(d_inode(dentry), buffer, size);
566600e1779SMasatake YAMATO 	if (len < 0)
567600e1779SMasatake YAMATO 		return len;
568600e1779SMasatake YAMATO 	used += len;
569600e1779SMasatake YAMATO 	if (buffer) {
570600e1779SMasatake YAMATO 		if (size < used)
571600e1779SMasatake YAMATO 			return -ERANGE;
572600e1779SMasatake YAMATO 		buffer += len;
573600e1779SMasatake YAMATO 	}
574600e1779SMasatake YAMATO 
575600e1779SMasatake YAMATO 	len = (XATTR_NAME_SOCKPROTONAME_LEN + 1);
576600e1779SMasatake YAMATO 	used += len;
577600e1779SMasatake YAMATO 	if (buffer) {
578600e1779SMasatake YAMATO 		if (size < used)
579600e1779SMasatake YAMATO 			return -ERANGE;
580600e1779SMasatake YAMATO 		memcpy(buffer, XATTR_NAME_SOCKPROTONAME, len);
581600e1779SMasatake YAMATO 		buffer += len;
582600e1779SMasatake YAMATO 	}
583600e1779SMasatake YAMATO 
584600e1779SMasatake YAMATO 	return used;
585600e1779SMasatake YAMATO }
586600e1779SMasatake YAMATO 
sockfs_setattr(struct mnt_idmap * idmap,struct dentry * dentry,struct iattr * iattr)587c1632a0fSChristian Brauner static int sockfs_setattr(struct mnt_idmap *idmap,
588549c7297SChristian Brauner 			  struct dentry *dentry, struct iattr *iattr)
58986741ec2SLorenzo Colitti {
590c1632a0fSChristian Brauner 	int err = simple_setattr(&nop_mnt_idmap, dentry, iattr);
59186741ec2SLorenzo Colitti 
592e1a3a60aSEric Biggers 	if (!err && (iattr->ia_valid & ATTR_UID)) {
59386741ec2SLorenzo Colitti 		struct socket *sock = SOCKET_I(d_inode(dentry));
59486741ec2SLorenzo Colitti 
5956d8c50dcSCong Wang 		if (sock->sk)
59686741ec2SLorenzo Colitti 			sock->sk->sk_uid = iattr->ia_uid;
5976d8c50dcSCong Wang 		else
5986d8c50dcSCong Wang 			err = -ENOENT;
59986741ec2SLorenzo Colitti 	}
60086741ec2SLorenzo Colitti 
60186741ec2SLorenzo Colitti 	return err;
60286741ec2SLorenzo Colitti }
60386741ec2SLorenzo Colitti 
604600e1779SMasatake YAMATO static const struct inode_operations sockfs_inode_ops = {
605600e1779SMasatake YAMATO 	.listxattr = sockfs_listxattr,
60686741ec2SLorenzo Colitti 	.setattr = sockfs_setattr,
607600e1779SMasatake YAMATO };
608600e1779SMasatake YAMATO 
6091da177e4SLinus Torvalds /**
6101da177e4SLinus Torvalds  *	sock_alloc - allocate a socket
6111da177e4SLinus Torvalds  *
6121da177e4SLinus Torvalds  *	Allocate a new inode and socket object. The two are bound together
6131da177e4SLinus Torvalds  *	and initialised. The socket is then returned. If we are out of inodes
6148a3c245cSPedro Tammela  *	NULL is returned. This functions uses GFP_KERNEL internally.
6151da177e4SLinus Torvalds  */
6161da177e4SLinus Torvalds 
sock_alloc(void)617f4a00aacSTom Herbert struct socket *sock_alloc(void)
6181da177e4SLinus Torvalds {
6191da177e4SLinus Torvalds 	struct inode *inode;
6201da177e4SLinus Torvalds 	struct socket *sock;
6211da177e4SLinus Torvalds 
622a209dfc7SEric Dumazet 	inode = new_inode_pseudo(sock_mnt->mnt_sb);
6231da177e4SLinus Torvalds 	if (!inode)
6241da177e4SLinus Torvalds 		return NULL;
6251da177e4SLinus Torvalds 
6261da177e4SLinus Torvalds 	sock = SOCKET_I(inode);
6271da177e4SLinus Torvalds 
62885fe4025SChristoph Hellwig 	inode->i_ino = get_next_ino();
6291da177e4SLinus Torvalds 	inode->i_mode = S_IFSOCK | S_IRWXUGO;
6308192b0c4SDavid Howells 	inode->i_uid = current_fsuid();
6318192b0c4SDavid Howells 	inode->i_gid = current_fsgid();
632600e1779SMasatake YAMATO 	inode->i_op = &sockfs_inode_ops;
6331da177e4SLinus Torvalds 
6341da177e4SLinus Torvalds 	return sock;
6351da177e4SLinus Torvalds }
636f4a00aacSTom Herbert EXPORT_SYMBOL(sock_alloc);
6371da177e4SLinus Torvalds 
__sock_release(struct socket * sock,struct inode * inode)6386d8c50dcSCong Wang static void __sock_release(struct socket *sock, struct inode *inode)
6391da177e4SLinus Torvalds {
6401ded5e5aSEric Dumazet 	const struct proto_ops *ops = READ_ONCE(sock->ops);
6411ded5e5aSEric Dumazet 
6421ded5e5aSEric Dumazet 	if (ops) {
6431ded5e5aSEric Dumazet 		struct module *owner = ops->owner;
6441da177e4SLinus Torvalds 
6456d8c50dcSCong Wang 		if (inode)
6466d8c50dcSCong Wang 			inode_lock(inode);
6471ded5e5aSEric Dumazet 		ops->release(sock);
648ff7b11aaSEric Biggers 		sock->sk = NULL;
6496d8c50dcSCong Wang 		if (inode)
6506d8c50dcSCong Wang 			inode_unlock(inode);
6511da177e4SLinus Torvalds 		sock->ops = NULL;
6521da177e4SLinus Torvalds 		module_put(owner);
6531da177e4SLinus Torvalds 	}
6541da177e4SLinus Torvalds 
655333f7909SAl Viro 	if (sock->wq.fasync_list)
6563410f22eSYang Yingliang 		pr_err("%s: fasync list not empty!\n", __func__);
6571da177e4SLinus Torvalds 
6581da177e4SLinus Torvalds 	if (!sock->file) {
6591da177e4SLinus Torvalds 		iput(SOCK_INODE(sock));
6601da177e4SLinus Torvalds 		return;
6611da177e4SLinus Torvalds 	}
6621da177e4SLinus Torvalds 	sock->file = NULL;
6631da177e4SLinus Torvalds }
6646d8c50dcSCong Wang 
6659a8ad9acSAndrew Lunn /**
6669a8ad9acSAndrew Lunn  *	sock_release - close a socket
6679a8ad9acSAndrew Lunn  *	@sock: socket to close
6689a8ad9acSAndrew Lunn  *
6699a8ad9acSAndrew Lunn  *	The socket is released from the protocol stack if it has a release
6709a8ad9acSAndrew Lunn  *	callback, and the inode is then released if the socket is bound to
6719a8ad9acSAndrew Lunn  *	an inode not a file.
6729a8ad9acSAndrew Lunn  */
sock_release(struct socket * sock)6736d8c50dcSCong Wang void sock_release(struct socket *sock)
6746d8c50dcSCong Wang {
6756d8c50dcSCong Wang 	__sock_release(sock, NULL);
6766d8c50dcSCong Wang }
677c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_release);
6781da177e4SLinus Torvalds 
__sock_tx_timestamp(__u32 tsflags,__u8 * tx_flags)679822b5bc6SVadim Fedorenko void __sock_tx_timestamp(__u32 tsflags, __u8 *tx_flags)
68020d49473SPatrick Ohly {
681140c55d4SEric Dumazet 	u8 flags = *tx_flags;
682140c55d4SEric Dumazet 
683e6116fc6SWillem de Bruijn 	if (tsflags & SOF_TIMESTAMPING_TX_HARDWARE)
6842deaf7f4SJason Xing 		flags |= SKBTX_HW_TSTAMP_NOBPF;
685140c55d4SEric Dumazet 
686c14ac945SSoheil Hassas Yeganeh 	if (tsflags & SOF_TIMESTAMPING_TX_SOFTWARE)
687140c55d4SEric Dumazet 		flags |= SKBTX_SW_TSTAMP;
688140c55d4SEric Dumazet 
689c14ac945SSoheil Hassas Yeganeh 	if (tsflags & SOF_TIMESTAMPING_TX_SCHED)
690140c55d4SEric Dumazet 		flags |= SKBTX_SCHED_TSTAMP;
691140c55d4SEric Dumazet 
692*983e0e4eSPauli Virtanen 	if (tsflags & SOF_TIMESTAMPING_TX_COMPLETION)
693*983e0e4eSPauli Virtanen 		flags |= SKBTX_COMPLETION_TSTAMP;
694*983e0e4eSPauli Virtanen 
695140c55d4SEric Dumazet 	*tx_flags = flags;
69620d49473SPatrick Ohly }
69767cc0d40SWillem de Bruijn EXPORT_SYMBOL(__sock_tx_timestamp);
69820d49473SPatrick Ohly 
6998c3c447bSPaolo Abeni INDIRECT_CALLABLE_DECLARE(int inet_sendmsg(struct socket *, struct msghdr *,
7008c3c447bSPaolo Abeni 					   size_t));
701a648a592SPaolo Abeni INDIRECT_CALLABLE_DECLARE(int inet6_sendmsg(struct socket *, struct msghdr *,
702a648a592SPaolo Abeni 					    size_t));
7036e6eda44SYunhui Cui 
call_trace_sock_send_length(struct sock * sk,int ret,int flags)7046e6eda44SYunhui Cui static noinline void call_trace_sock_send_length(struct sock *sk, int ret,
7056e6eda44SYunhui Cui 						 int flags)
7066e6eda44SYunhui Cui {
7076e6eda44SYunhui Cui 	trace_sock_send_length(sk, ret, 0);
7086e6eda44SYunhui Cui }
7096e6eda44SYunhui Cui 
sock_sendmsg_nosec(struct socket * sock,struct msghdr * msg)710d8725c86SAl Viro static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg)
7111da177e4SLinus Torvalds {
7121ded5e5aSEric Dumazet 	int ret = INDIRECT_CALL_INET(READ_ONCE(sock->ops)->sendmsg, inet6_sendmsg,
713a648a592SPaolo Abeni 				     inet_sendmsg, sock, msg,
714a648a592SPaolo Abeni 				     msg_data_left(msg));
715d8725c86SAl Viro 	BUG_ON(ret == -EIOCBQUEUED);
7166e6eda44SYunhui Cui 
7176e6eda44SYunhui Cui 	if (trace_sock_send_length_enabled())
7186e6eda44SYunhui Cui 		call_trace_sock_send_length(sock->sk, ret, 0);
719d8725c86SAl Viro 	return ret;
7201da177e4SLinus Torvalds }
7210cf00c6fSGu Zheng 
__sock_sendmsg(struct socket * sock,struct msghdr * msg)72286a7e0b6SJordan Rife static int __sock_sendmsg(struct socket *sock, struct msghdr *msg)
72386a7e0b6SJordan Rife {
72486a7e0b6SJordan Rife 	int err = security_socket_sendmsg(sock, msg,
72586a7e0b6SJordan Rife 					  msg_data_left(msg));
72686a7e0b6SJordan Rife 
72786a7e0b6SJordan Rife 	return err ?: sock_sendmsg_nosec(sock, msg);
72886a7e0b6SJordan Rife }
72986a7e0b6SJordan Rife 
73085806af0SRandy Dunlap /**
73185806af0SRandy Dunlap  *	sock_sendmsg - send a message through @sock
73285806af0SRandy Dunlap  *	@sock: socket
73385806af0SRandy Dunlap  *	@msg: message to send
73485806af0SRandy Dunlap  *
73585806af0SRandy Dunlap  *	Sends @msg through @sock, passing through LSM.
73685806af0SRandy Dunlap  *	Returns the number of bytes sent, or an error code.
73785806af0SRandy Dunlap  */
sock_sendmsg(struct socket * sock,struct msghdr * msg)738d8725c86SAl Viro int sock_sendmsg(struct socket *sock, struct msghdr *msg)
7390cf00c6fSGu Zheng {
74086a7e0b6SJordan Rife 	struct sockaddr_storage *save_addr = (struct sockaddr_storage *)msg->msg_name;
74186a7e0b6SJordan Rife 	struct sockaddr_storage address;
74201b2885dSMarc Dionne 	int save_len = msg->msg_namelen;
74386a7e0b6SJordan Rife 	int ret;
7441b784140SYing Xue 
74586a7e0b6SJordan Rife 	if (msg->msg_name) {
74686a7e0b6SJordan Rife 		memcpy(&address, msg->msg_name, msg->msg_namelen);
74786a7e0b6SJordan Rife 		msg->msg_name = &address;
74886a7e0b6SJordan Rife 	}
74986a7e0b6SJordan Rife 
75086a7e0b6SJordan Rife 	ret = __sock_sendmsg(sock, msg);
75186a7e0b6SJordan Rife 	msg->msg_name = save_addr;
75201b2885dSMarc Dionne 	msg->msg_namelen = save_len;
75386a7e0b6SJordan Rife 
75486a7e0b6SJordan Rife 	return ret;
7550cf00c6fSGu Zheng }
756c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_sendmsg);
7571da177e4SLinus Torvalds 
7588a3c245cSPedro Tammela /**
7598a3c245cSPedro Tammela  *	kernel_sendmsg - send a message through @sock (kernel-space)
7608a3c245cSPedro Tammela  *	@sock: socket
7618a3c245cSPedro Tammela  *	@msg: message header
7628a3c245cSPedro Tammela  *	@vec: kernel vec
7638a3c245cSPedro Tammela  *	@num: vec array length
7648a3c245cSPedro Tammela  *	@size: total message data size
7658a3c245cSPedro Tammela  *
7668a3c245cSPedro Tammela  *	Builds the message data with @vec and sends it through @sock.
7678a3c245cSPedro Tammela  *	Returns the number of bytes sent, or an error code.
7688a3c245cSPedro Tammela  */
7698a3c245cSPedro Tammela 
kernel_sendmsg(struct socket * sock,struct msghdr * msg,struct kvec * vec,size_t num,size_t size)7701da177e4SLinus Torvalds int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
7711da177e4SLinus Torvalds 		   struct kvec *vec, size_t num, size_t size)
7721da177e4SLinus Torvalds {
773de4eda9dSAl Viro 	iov_iter_kvec(&msg->msg_iter, ITER_SOURCE, vec, num, size);
774d8725c86SAl Viro 	return sock_sendmsg(sock, msg);
7751da177e4SLinus Torvalds }
776c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendmsg);
7771da177e4SLinus Torvalds 
skb_is_err_queue(const struct sk_buff * skb)7788605330aSSoheil Hassas Yeganeh static bool skb_is_err_queue(const struct sk_buff *skb)
7798605330aSSoheil Hassas Yeganeh {
7808605330aSSoheil Hassas Yeganeh 	/* pkt_type of skbs enqueued on the error queue are set to
7818605330aSSoheil Hassas Yeganeh 	 * PACKET_OUTGOING in skb_set_err_queue(). This is only safe to do
7828605330aSSoheil Hassas Yeganeh 	 * in recvmsg, since skbs received on a local socket will never
7838605330aSSoheil Hassas Yeganeh 	 * have a pkt_type of PACKET_OUTGOING.
7848605330aSSoheil Hassas Yeganeh 	 */
7858605330aSSoheil Hassas Yeganeh 	return skb->pkt_type == PACKET_OUTGOING;
7868605330aSSoheil Hassas Yeganeh }
7878605330aSSoheil Hassas Yeganeh 
788b50a5c70SMiroslav Lichvar /* On transmit, software and hardware timestamps are returned independently.
789b50a5c70SMiroslav Lichvar  * As the two skb clones share the hardware timestamp, which may be updated
790b50a5c70SMiroslav Lichvar  * before the software timestamp is received, a hardware TX timestamp may be
791b50a5c70SMiroslav Lichvar  * returned only if there is no software TX timestamp. Ignore false software
792b50a5c70SMiroslav Lichvar  * timestamps, which may be made in the __sock_recv_timestamp() call when the
7937f1bc6e9SDeepa Dinamani  * option SO_TIMESTAMP_OLD(NS) is enabled on the socket, even when the skb has a
794b50a5c70SMiroslav Lichvar  * hardware timestamp.
795b50a5c70SMiroslav Lichvar  */
skb_is_swtx_tstamp(const struct sk_buff * skb,int false_tstamp)796b50a5c70SMiroslav Lichvar static bool skb_is_swtx_tstamp(const struct sk_buff *skb, int false_tstamp)
797b50a5c70SMiroslav Lichvar {
798b50a5c70SMiroslav Lichvar 	return skb->tstamp && !false_tstamp && skb_is_err_queue(skb);
799b50a5c70SMiroslav Lichvar }
800b50a5c70SMiroslav Lichvar 
get_timestamp(struct sock * sk,struct sk_buff * skb,int * if_index)80197dc7cd9SGerhard Engleder static ktime_t get_timestamp(struct sock *sk, struct sk_buff *skb, int *if_index)
80297dc7cd9SGerhard Engleder {
803e3390b30SEric Dumazet 	bool cycles = READ_ONCE(sk->sk_tsflags) & SOF_TIMESTAMPING_BIND_PHC;
80497dc7cd9SGerhard Engleder 	struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
80597dc7cd9SGerhard Engleder 	struct net_device *orig_dev;
80697dc7cd9SGerhard Engleder 	ktime_t hwtstamp;
80797dc7cd9SGerhard Engleder 
80897dc7cd9SGerhard Engleder 	rcu_read_lock();
80997dc7cd9SGerhard Engleder 	orig_dev = dev_get_by_napi_id(skb_napi_id(skb));
81097dc7cd9SGerhard Engleder 	if (orig_dev) {
81197dc7cd9SGerhard Engleder 		*if_index = orig_dev->ifindex;
81297dc7cd9SGerhard Engleder 		hwtstamp = netdev_get_tstamp(orig_dev, shhwtstamps, cycles);
81397dc7cd9SGerhard Engleder 	} else {
81497dc7cd9SGerhard Engleder 		hwtstamp = shhwtstamps->hwtstamp;
81597dc7cd9SGerhard Engleder 	}
81697dc7cd9SGerhard Engleder 	rcu_read_unlock();
81797dc7cd9SGerhard Engleder 
81897dc7cd9SGerhard Engleder 	return hwtstamp;
81997dc7cd9SGerhard Engleder }
82097dc7cd9SGerhard Engleder 
put_ts_pktinfo(struct msghdr * msg,struct sk_buff * skb,int if_index)82197dc7cd9SGerhard Engleder static void put_ts_pktinfo(struct msghdr *msg, struct sk_buff *skb,
82297dc7cd9SGerhard Engleder 			   int if_index)
823aad9c8c4SMiroslav Lichvar {
824aad9c8c4SMiroslav Lichvar 	struct scm_ts_pktinfo ts_pktinfo;
825aad9c8c4SMiroslav Lichvar 	struct net_device *orig_dev;
826aad9c8c4SMiroslav Lichvar 
827aad9c8c4SMiroslav Lichvar 	if (!skb_mac_header_was_set(skb))
828aad9c8c4SMiroslav Lichvar 		return;
829aad9c8c4SMiroslav Lichvar 
830aad9c8c4SMiroslav Lichvar 	memset(&ts_pktinfo, 0, sizeof(ts_pktinfo));
831aad9c8c4SMiroslav Lichvar 
83297dc7cd9SGerhard Engleder 	if (!if_index) {
833aad9c8c4SMiroslav Lichvar 		rcu_read_lock();
834aad9c8c4SMiroslav Lichvar 		orig_dev = dev_get_by_napi_id(skb_napi_id(skb));
835aad9c8c4SMiroslav Lichvar 		if (orig_dev)
83697dc7cd9SGerhard Engleder 			if_index = orig_dev->ifindex;
837aad9c8c4SMiroslav Lichvar 		rcu_read_unlock();
83897dc7cd9SGerhard Engleder 	}
83997dc7cd9SGerhard Engleder 	ts_pktinfo.if_index = if_index;
840aad9c8c4SMiroslav Lichvar 
841aad9c8c4SMiroslav Lichvar 	ts_pktinfo.pkt_length = skb->len - skb_mac_offset(skb);
842aad9c8c4SMiroslav Lichvar 	put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_PKTINFO,
843aad9c8c4SMiroslav Lichvar 		 sizeof(ts_pktinfo), &ts_pktinfo);
844aad9c8c4SMiroslav Lichvar }
845aad9c8c4SMiroslav Lichvar 
84692f37fd2SEric Dumazet /*
84792f37fd2SEric Dumazet  * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
84892f37fd2SEric Dumazet  */
__sock_recv_timestamp(struct msghdr * msg,struct sock * sk,struct sk_buff * skb)84992f37fd2SEric Dumazet void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
85092f37fd2SEric Dumazet 	struct sk_buff *skb)
85192f37fd2SEric Dumazet {
85220d49473SPatrick Ohly 	int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
853887feae3SDeepa Dinamani 	int new_tstamp = sock_flag(sk, SOCK_TSTAMP_NEW);
8549718475eSDeepa Dinamani 	struct scm_timestamping_internal tss;
855b50a5c70SMiroslav Lichvar 	int empty = 1, false_tstamp = 0;
85620d49473SPatrick Ohly 	struct skb_shared_hwtstamps *shhwtstamps =
85720d49473SPatrick Ohly 		skb_hwtstamps(skb);
85897dc7cd9SGerhard Engleder 	int if_index;
859007747a9SMiroslav Lichvar 	ktime_t hwtstamp;
860e3390b30SEric Dumazet 	u32 tsflags;
86192f37fd2SEric Dumazet 
86220d49473SPatrick Ohly 	/* Race occurred between timestamp enabling and packet
86320d49473SPatrick Ohly 	   receiving.  Fill in the current time for now. */
864b50a5c70SMiroslav Lichvar 	if (need_software_tstamp && skb->tstamp == 0) {
86520d49473SPatrick Ohly 		__net_timestamp(skb);
866b50a5c70SMiroslav Lichvar 		false_tstamp = 1;
867b50a5c70SMiroslav Lichvar 	}
86820d49473SPatrick Ohly 
86920d49473SPatrick Ohly 	if (need_software_tstamp) {
87092f37fd2SEric Dumazet 		if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
871887feae3SDeepa Dinamani 			if (new_tstamp) {
872887feae3SDeepa Dinamani 				struct __kernel_sock_timeval tv;
873887feae3SDeepa Dinamani 
874887feae3SDeepa Dinamani 				skb_get_new_timestamp(skb, &tv);
875887feae3SDeepa Dinamani 				put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_NEW,
876887feae3SDeepa Dinamani 					 sizeof(tv), &tv);
877887feae3SDeepa Dinamani 			} else {
87813c6ee2aSDeepa Dinamani 				struct __kernel_old_timeval tv;
879887feae3SDeepa Dinamani 
88020d49473SPatrick Ohly 				skb_get_timestamp(skb, &tv);
8817f1bc6e9SDeepa Dinamani 				put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_OLD,
88220d49473SPatrick Ohly 					 sizeof(tv), &tv);
883887feae3SDeepa Dinamani 			}
884887feae3SDeepa Dinamani 		} else {
885887feae3SDeepa Dinamani 			if (new_tstamp) {
886887feae3SDeepa Dinamani 				struct __kernel_timespec ts;
887887feae3SDeepa Dinamani 
888887feae3SDeepa Dinamani 				skb_get_new_timestampns(skb, &ts);
889887feae3SDeepa Dinamani 				put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_NEW,
890887feae3SDeepa Dinamani 					 sizeof(ts), &ts);
89192f37fd2SEric Dumazet 			} else {
892df1b4ba9SArnd Bergmann 				struct __kernel_old_timespec ts;
893887feae3SDeepa Dinamani 
894f24b9be5SWillem de Bruijn 				skb_get_timestampns(skb, &ts);
8957f1bc6e9SDeepa Dinamani 				put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_OLD,
896f24b9be5SWillem de Bruijn 					 sizeof(ts), &ts);
89792f37fd2SEric Dumazet 			}
89892f37fd2SEric Dumazet 		}
899887feae3SDeepa Dinamani 	}
90092f37fd2SEric Dumazet 
901f24b9be5SWillem de Bruijn 	memset(&tss, 0, sizeof(tss));
902e3390b30SEric Dumazet 	tsflags = READ_ONCE(sk->sk_tsflags);
903be8e9eb3SJason Xing 	if ((tsflags & SOF_TIMESTAMPING_SOFTWARE &&
904be8e9eb3SJason Xing 	     (tsflags & SOF_TIMESTAMPING_RX_SOFTWARE ||
905be8e9eb3SJason Xing 	      skb_is_err_queue(skb) ||
906be8e9eb3SJason Xing 	      !(tsflags & SOF_TIMESTAMPING_OPT_RX_FILTER))) &&
9079718475eSDeepa Dinamani 	    ktime_to_timespec64_cond(skb->tstamp, tss.ts + 0))
90820d49473SPatrick Ohly 		empty = 0;
9094d276eb6SWillem de Bruijn 	if (shhwtstamps &&
910be8e9eb3SJason Xing 	    (tsflags & SOF_TIMESTAMPING_RAW_HARDWARE &&
911be8e9eb3SJason Xing 	     (tsflags & SOF_TIMESTAMPING_RX_HARDWARE ||
912be8e9eb3SJason Xing 	      skb_is_err_queue(skb) ||
913be8e9eb3SJason Xing 	      !(tsflags & SOF_TIMESTAMPING_OPT_RX_FILTER))) &&
914d7c08826SYangbo Lu 	    !skb_is_swtx_tstamp(skb, false_tstamp)) {
91597dc7cd9SGerhard Engleder 		if_index = 0;
91697dc7cd9SGerhard Engleder 		if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP_NETDEV)
91797dc7cd9SGerhard Engleder 			hwtstamp = get_timestamp(sk, skb, &if_index);
918007747a9SMiroslav Lichvar 		else
919007747a9SMiroslav Lichvar 			hwtstamp = shhwtstamps->hwtstamp;
920d7c08826SYangbo Lu 
921e3390b30SEric Dumazet 		if (tsflags & SOF_TIMESTAMPING_BIND_PHC)
92297dc7cd9SGerhard Engleder 			hwtstamp = ptp_convert_timestamp(&hwtstamp,
923251cd405SEric Dumazet 							 READ_ONCE(sk->sk_bind_phc));
92497dc7cd9SGerhard Engleder 
925007747a9SMiroslav Lichvar 		if (ktime_to_timespec64_cond(hwtstamp, tss.ts + 2)) {
92620d49473SPatrick Ohly 			empty = 0;
927d7c08826SYangbo Lu 
928e3390b30SEric Dumazet 			if ((tsflags & SOF_TIMESTAMPING_OPT_PKTINFO) &&
929aad9c8c4SMiroslav Lichvar 			    !skb_is_err_queue(skb))
93097dc7cd9SGerhard Engleder 				put_ts_pktinfo(msg, skb, if_index);
931aad9c8c4SMiroslav Lichvar 		}
932d7c08826SYangbo Lu 	}
9331c885808SFrancis Yan 	if (!empty) {
9349718475eSDeepa Dinamani 		if (sock_flag(sk, SOCK_TSTAMP_NEW))
9359718475eSDeepa Dinamani 			put_cmsg_scm_timestamping64(msg, &tss);
9369718475eSDeepa Dinamani 		else
9379718475eSDeepa Dinamani 			put_cmsg_scm_timestamping(msg, &tss);
9381c885808SFrancis Yan 
9398605330aSSoheil Hassas Yeganeh 		if (skb_is_err_queue(skb) && skb->len &&
9404ef1b286SSoheil Hassas Yeganeh 		    SKB_EXT_ERR(skb)->opt_stats)
9411c885808SFrancis Yan 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_OPT_STATS,
9421c885808SFrancis Yan 				 skb->len, skb->data);
9431c885808SFrancis Yan 	}
94420d49473SPatrick Ohly }
9457c81fd8bSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
9467c81fd8bSArnaldo Carvalho de Melo 
947eb6fba75SJakub Kicinski #ifdef CONFIG_WIRELESS
__sock_recv_wifi_status(struct msghdr * msg,struct sock * sk,struct sk_buff * skb)9486e3e939fSJohannes Berg void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
9496e3e939fSJohannes Berg 	struct sk_buff *skb)
9506e3e939fSJohannes Berg {
9516e3e939fSJohannes Berg 	int ack;
9526e3e939fSJohannes Berg 
9536e3e939fSJohannes Berg 	if (!sock_flag(sk, SOCK_WIFI_STATUS))
9546e3e939fSJohannes Berg 		return;
9556e3e939fSJohannes Berg 	if (!skb->wifi_acked_valid)
9566e3e939fSJohannes Berg 		return;
9576e3e939fSJohannes Berg 
9586e3e939fSJohannes Berg 	ack = skb->wifi_acked;
9596e3e939fSJohannes Berg 
9606e3e939fSJohannes Berg 	put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack);
9616e3e939fSJohannes Berg }
9626e3e939fSJohannes Berg EXPORT_SYMBOL_GPL(__sock_recv_wifi_status);
963eb6fba75SJakub Kicinski #endif
9646e3e939fSJohannes Berg 
sock_recv_drops(struct msghdr * msg,struct sock * sk,struct sk_buff * skb)96511165f14Sstephen hemminger static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk,
96611165f14Sstephen hemminger 				   struct sk_buff *skb)
9673b885787SNeil Horman {
968744d5a3eSEyal Birger 	if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && SOCK_SKB_CB(skb)->dropcount)
9693b885787SNeil Horman 		put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL,
970744d5a3eSEyal Birger 			sizeof(__u32), &SOCK_SKB_CB(skb)->dropcount);
9713b885787SNeil Horman }
9723b885787SNeil Horman 
sock_recv_mark(struct msghdr * msg,struct sock * sk,struct sk_buff * skb)9736fd1d51cSErin MacNeil static void sock_recv_mark(struct msghdr *msg, struct sock *sk,
9746fd1d51cSErin MacNeil 			   struct sk_buff *skb)
9756fd1d51cSErin MacNeil {
9762558b803SEric Dumazet 	if (sock_flag(sk, SOCK_RCVMARK) && skb) {
9772558b803SEric Dumazet 		/* We must use a bounce buffer for CONFIG_HARDENED_USERCOPY=y */
9782558b803SEric Dumazet 		__u32 mark = skb->mark;
9792558b803SEric Dumazet 
9802558b803SEric Dumazet 		put_cmsg(msg, SOL_SOCKET, SO_MARK, sizeof(__u32), &mark);
9812558b803SEric Dumazet 	}
9826fd1d51cSErin MacNeil }
9836fd1d51cSErin MacNeil 
sock_recv_priority(struct msghdr * msg,struct sock * sk,struct sk_buff * skb)984e45469e5SAnna Emese Nyiri static void sock_recv_priority(struct msghdr *msg, struct sock *sk,
985e45469e5SAnna Emese Nyiri 			       struct sk_buff *skb)
986e45469e5SAnna Emese Nyiri {
987e45469e5SAnna Emese Nyiri 	if (sock_flag(sk, SOCK_RCVPRIORITY) && skb) {
988e45469e5SAnna Emese Nyiri 		__u32 priority = skb->priority;
989e45469e5SAnna Emese Nyiri 
990e45469e5SAnna Emese Nyiri 		put_cmsg(msg, SOL_SOCKET, SO_PRIORITY, sizeof(__u32), &priority);
991e45469e5SAnna Emese Nyiri 	}
992e45469e5SAnna Emese Nyiri }
993e45469e5SAnna Emese Nyiri 
__sock_recv_cmsgs(struct msghdr * msg,struct sock * sk,struct sk_buff * skb)9946fd1d51cSErin MacNeil void __sock_recv_cmsgs(struct msghdr *msg, struct sock *sk,
9953b885787SNeil Horman 		       struct sk_buff *skb)
9963b885787SNeil Horman {
9973b885787SNeil Horman 	sock_recv_timestamp(msg, sk, skb);
9983b885787SNeil Horman 	sock_recv_drops(msg, sk, skb);
9996fd1d51cSErin MacNeil 	sock_recv_mark(msg, sk, skb);
1000e45469e5SAnna Emese Nyiri 	sock_recv_priority(msg, sk, skb);
10013b885787SNeil Horman }
10026fd1d51cSErin MacNeil EXPORT_SYMBOL_GPL(__sock_recv_cmsgs);
10033b885787SNeil Horman 
10048c3c447bSPaolo Abeni INDIRECT_CALLABLE_DECLARE(int inet_recvmsg(struct socket *, struct msghdr *,
10058c3c447bSPaolo Abeni 					   size_t, int));
1006a648a592SPaolo Abeni INDIRECT_CALLABLE_DECLARE(int inet6_recvmsg(struct socket *, struct msghdr *,
1007a648a592SPaolo Abeni 					    size_t, int));
10086e6eda44SYunhui Cui 
call_trace_sock_recv_length(struct sock * sk,int ret,int flags)10096e6eda44SYunhui Cui static noinline void call_trace_sock_recv_length(struct sock *sk, int ret, int flags)
10106e6eda44SYunhui Cui {
10116e6eda44SYunhui Cui 	trace_sock_recv_length(sk, ret, flags);
10126e6eda44SYunhui Cui }
10136e6eda44SYunhui Cui 
sock_recvmsg_nosec(struct socket * sock,struct msghdr * msg,int flags)10141b784140SYing Xue static inline int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
10151b784140SYing Xue 				     int flags)
1016a2e27255SArnaldo Carvalho de Melo {
10171ded5e5aSEric Dumazet 	int ret = INDIRECT_CALL_INET(READ_ONCE(sock->ops)->recvmsg,
10181ded5e5aSEric Dumazet 				     inet6_recvmsg,
10196e6eda44SYunhui Cui 				     inet_recvmsg, sock, msg,
10206e6eda44SYunhui Cui 				     msg_data_left(msg), flags);
10216e6eda44SYunhui Cui 	if (trace_sock_recv_length_enabled())
10226e6eda44SYunhui Cui 		call_trace_sock_recv_length(sock->sk, ret, flags);
10236e6eda44SYunhui Cui 	return ret;
10242da62906SAl Viro }
1025a2e27255SArnaldo Carvalho de Melo 
102685806af0SRandy Dunlap /**
102785806af0SRandy Dunlap  *	sock_recvmsg - receive a message from @sock
102885806af0SRandy Dunlap  *	@sock: socket
102985806af0SRandy Dunlap  *	@msg: message to receive
103085806af0SRandy Dunlap  *	@flags: message flags
103185806af0SRandy Dunlap  *
103285806af0SRandy Dunlap  *	Receives @msg from @sock, passing through LSM. Returns the total number
103385806af0SRandy Dunlap  *	of bytes received, or an error.
103485806af0SRandy Dunlap  */
sock_recvmsg(struct socket * sock,struct msghdr * msg,int flags)10352da62906SAl Viro int sock_recvmsg(struct socket *sock, struct msghdr *msg, int flags)
10362da62906SAl Viro {
10372da62906SAl Viro 	int err = security_socket_recvmsg(sock, msg, msg_data_left(msg), flags);
10382da62906SAl Viro 
10392da62906SAl Viro 	return err ?: sock_recvmsg_nosec(sock, msg, flags);
10401da177e4SLinus Torvalds }
1041c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_recvmsg);
10421da177e4SLinus Torvalds 
1043c1249c0aSMartin Lucina /**
1044c1249c0aSMartin Lucina  *	kernel_recvmsg - Receive a message from a socket (kernel space)
1045c1249c0aSMartin Lucina  *	@sock: The socket to receive the message from
1046c1249c0aSMartin Lucina  *	@msg: Received message
1047c1249c0aSMartin Lucina  *	@vec: Input s/g array for message data
1048c1249c0aSMartin Lucina  *	@num: Size of input s/g array
1049c1249c0aSMartin Lucina  *	@size: Number of bytes to read
1050c1249c0aSMartin Lucina  *	@flags: Message flags (MSG_DONTWAIT, etc...)
1051c1249c0aSMartin Lucina  *
1052c1249c0aSMartin Lucina  *	On return the msg structure contains the scatter/gather array passed in the
1053c1249c0aSMartin Lucina  *	vec argument. The array is modified so that it consists of the unfilled
1054c1249c0aSMartin Lucina  *	portion of the original array.
1055c1249c0aSMartin Lucina  *
1056c1249c0aSMartin Lucina  *	The returned value is the total number of bytes received, or an error.
1057c1249c0aSMartin Lucina  */
10588a3c245cSPedro Tammela 
kernel_recvmsg(struct socket * sock,struct msghdr * msg,struct kvec * vec,size_t num,size_t size,int flags)10591da177e4SLinus Torvalds int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
106089bddce5SStephen Hemminger 		   struct kvec *vec, size_t num, size_t size, int flags)
10611da177e4SLinus Torvalds {
10621f466e1fSChristoph Hellwig 	msg->msg_control_is_user = false;
1063de4eda9dSAl Viro 	iov_iter_kvec(&msg->msg_iter, ITER_DEST, vec, num, size);
10641f466e1fSChristoph Hellwig 	return sock_recvmsg(sock, msg, flags);
10651da177e4SLinus Torvalds }
1066c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_recvmsg);
10671da177e4SLinus Torvalds 
sock_splice_read(struct file * file,loff_t * ppos,struct pipe_inode_info * pipe,size_t len,unsigned int flags)10689c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
10699c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
10709c55e01cSJens Axboe 				unsigned int flags)
10719c55e01cSJens Axboe {
10729c55e01cSJens Axboe 	struct socket *sock = file->private_data;
10731ded5e5aSEric Dumazet 	const struct proto_ops *ops;
10749c55e01cSJens Axboe 
10751ded5e5aSEric Dumazet 	ops = READ_ONCE(sock->ops);
10761ded5e5aSEric Dumazet 	if (unlikely(!ops->splice_read))
107767178fd0SDavid Howells 		return copy_splice_read(file, ppos, pipe, len, flags);
1078997b37daSRémi Denis-Courmont 
10791ded5e5aSEric Dumazet 	return ops->splice_read(sock, ppos, pipe, len, flags);
10809c55e01cSJens Axboe }
10819c55e01cSJens Axboe 
sock_splice_eof(struct file * file)10822bfc6685SDavid Howells static void sock_splice_eof(struct file *file)
10832bfc6685SDavid Howells {
10842bfc6685SDavid Howells 	struct socket *sock = file->private_data;
10851ded5e5aSEric Dumazet 	const struct proto_ops *ops;
10862bfc6685SDavid Howells 
10871ded5e5aSEric Dumazet 	ops = READ_ONCE(sock->ops);
10881ded5e5aSEric Dumazet 	if (ops->splice_eof)
10891ded5e5aSEric Dumazet 		ops->splice_eof(sock);
10902bfc6685SDavid Howells }
10912bfc6685SDavid Howells 
sock_read_iter(struct kiocb * iocb,struct iov_iter * to)10928ae5e030SAl Viro static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to)
1093ce1d4d3eSChristoph Hellwig {
10946d652330SAl Viro 	struct file *file = iocb->ki_filp;
10956d652330SAl Viro 	struct socket *sock = file->private_data;
10960345f931S[email protected] 	struct msghdr msg = {.msg_iter = *to,
10970345f931S[email protected] 			     .msg_iocb = iocb};
10988ae5e030SAl Viro 	ssize_t res;
1099ce1d4d3eSChristoph Hellwig 
1100ebfcd895SJens Axboe 	if (file->f_flags & O_NONBLOCK || (iocb->ki_flags & IOCB_NOWAIT))
11018ae5e030SAl Viro 		msg.msg_flags = MSG_DONTWAIT;
11028ae5e030SAl Viro 
11038ae5e030SAl Viro 	if (iocb->ki_pos != 0)
1104ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
1105027445c3SBadari Pulavarty 
110666ee59afSChristoph Hellwig 	if (!iov_iter_count(to))	/* Match SYS5 behaviour */
1107ce1d4d3eSChristoph Hellwig 		return 0;
1108ce1d4d3eSChristoph Hellwig 
11092da62906SAl Viro 	res = sock_recvmsg(sock, &msg, msg.msg_flags);
11108ae5e030SAl Viro 	*to = msg.msg_iter;
11118ae5e030SAl Viro 	return res;
1112ce1d4d3eSChristoph Hellwig }
1113ce1d4d3eSChristoph Hellwig 
sock_write_iter(struct kiocb * iocb,struct iov_iter * from)11148ae5e030SAl Viro static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from)
11151da177e4SLinus Torvalds {
11166d652330SAl Viro 	struct file *file = iocb->ki_filp;
11176d652330SAl Viro 	struct socket *sock = file->private_data;
11180345f931S[email protected] 	struct msghdr msg = {.msg_iter = *from,
11190345f931S[email protected] 			     .msg_iocb = iocb};
11208ae5e030SAl Viro 	ssize_t res;
11211da177e4SLinus Torvalds 
11228ae5e030SAl Viro 	if (iocb->ki_pos != 0)
1123ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
1124027445c3SBadari Pulavarty 
1125ebfcd895SJens Axboe 	if (file->f_flags & O_NONBLOCK || (iocb->ki_flags & IOCB_NOWAIT))
11268ae5e030SAl Viro 		msg.msg_flags = MSG_DONTWAIT;
11278ae5e030SAl Viro 
11286d652330SAl Viro 	if (sock->type == SOCK_SEQPACKET)
11296d652330SAl Viro 		msg.msg_flags |= MSG_EOR;
11306d652330SAl Viro 
113186a7e0b6SJordan Rife 	res = __sock_sendmsg(sock, &msg);
11328ae5e030SAl Viro 	*from = msg.msg_iter;
11338ae5e030SAl Viro 	return res;
11341da177e4SLinus Torvalds }
11351da177e4SLinus Torvalds 
11361da177e4SLinus Torvalds /*
11371da177e4SLinus Torvalds  * Atomic setting of ioctl hooks to avoid race
11381da177e4SLinus Torvalds  * with module unload.
11391da177e4SLinus Torvalds  */
11401da177e4SLinus Torvalds 
11414a3e2f71SArjan van de Ven static DEFINE_MUTEX(br_ioctl_mutex);
1142ad2f99aeSArnd Bergmann static int (*br_ioctl_hook)(struct net *net, unsigned int cmd,
1143ad2f99aeSArnd Bergmann 			    void __user *uarg);
1144ad2f99aeSArnd Bergmann 
brioctl_set(int (* hook)(struct net * net,unsigned int cmd,void __user * uarg))11451da177e4SLinus Torvalds void brioctl_set(int (*hook)(struct net *net, unsigned int cmd,
1146ad2f99aeSArnd Bergmann 			     void __user *uarg))
1147ad2f99aeSArnd Bergmann {
1148ad2f99aeSArnd Bergmann 	mutex_lock(&br_ioctl_mutex);
11491da177e4SLinus Torvalds 	br_ioctl_hook = hook;
11504a3e2f71SArjan van de Ven 	mutex_unlock(&br_ioctl_mutex);
11511da177e4SLinus Torvalds }
11524a3e2f71SArjan van de Ven EXPORT_SYMBOL(brioctl_set);
11531da177e4SLinus Torvalds 
br_ioctl_call(struct net * net,unsigned int cmd,void __user * uarg)11541da177e4SLinus Torvalds int br_ioctl_call(struct net *net, unsigned int cmd, void __user *uarg)
11551da177e4SLinus Torvalds {
1156ad2f99aeSArnd Bergmann 	int err = -ENOPKG;
1157ad2f99aeSArnd Bergmann 
1158ad2f99aeSArnd Bergmann 	if (!br_ioctl_hook)
1159ad2f99aeSArnd Bergmann 		request_module("bridge");
1160ad2f99aeSArnd Bergmann 
1161ad2f99aeSArnd Bergmann 	mutex_lock(&br_ioctl_mutex);
1162ad2f99aeSArnd Bergmann 	if (br_ioctl_hook)
1163ad2f99aeSArnd Bergmann 		err = br_ioctl_hook(net, cmd, uarg);
1164ad2f99aeSArnd Bergmann 	mutex_unlock(&br_ioctl_mutex);
1165ad2f99aeSArnd Bergmann 
1166ad2f99aeSArnd Bergmann 	return err;
1167ad2f99aeSArnd Bergmann }
1168ad2f99aeSArnd Bergmann 
1169ad2f99aeSArnd Bergmann static DEFINE_MUTEX(vlan_ioctl_mutex);
1170ad2f99aeSArnd Bergmann static int (*vlan_ioctl_hook) (struct net *, void __user *arg);
1171ad2f99aeSArnd Bergmann 
vlan_ioctl_set(int (* hook)(struct net *,void __user *))11724a3e2f71SArjan van de Ven void vlan_ioctl_set(int (*hook) (struct net *, void __user *))
1173881d966bSEric W. Biederman {
11741da177e4SLinus Torvalds 	mutex_lock(&vlan_ioctl_mutex);
1175881d966bSEric W. Biederman 	vlan_ioctl_hook = hook;
11761da177e4SLinus Torvalds 	mutex_unlock(&vlan_ioctl_mutex);
11774a3e2f71SArjan van de Ven }
11781da177e4SLinus Torvalds EXPORT_SYMBOL(vlan_ioctl_set);
11794a3e2f71SArjan van de Ven 
sock_do_ioctl(struct net * net,struct socket * sock,unsigned int cmd,unsigned long arg)11801da177e4SLinus Torvalds static long sock_do_ioctl(struct net *net, struct socket *sock,
11811da177e4SLinus Torvalds 			  unsigned int cmd, unsigned long arg)
11821da177e4SLinus Torvalds {
11836b96018bSArnd Bergmann 	const struct proto_ops *ops = READ_ONCE(sock->ops);
118463ff03abSJohannes Berg 	struct ifreq ifr;
11856b96018bSArnd Bergmann 	bool need_copyout;
11861ded5e5aSEric Dumazet 	int err;
1187876f0bf9SArnd Bergmann 	void __user *argp = (void __user *)arg;
1188876f0bf9SArnd Bergmann 	void __user *data;
11896b96018bSArnd Bergmann 
11906b96018bSArnd Bergmann 	err = ops->ioctl(sock, cmd, arg);
1191a554bf96SArnd Bergmann 
11926b96018bSArnd Bergmann 	/*
11931ded5e5aSEric Dumazet 	 * If this ioctl is unknown try to hand it down
11946b96018bSArnd Bergmann 	 * to the NIC driver.
11956b96018bSArnd Bergmann 	 */
11966b96018bSArnd Bergmann 	if (err != -ENOIOCTLCMD)
11976b96018bSArnd Bergmann 		return err;
11986b96018bSArnd Bergmann 
119936fd633eSAl Viro 	if (!is_socket_ioctl_cmd(cmd))
12006b96018bSArnd Bergmann 		return -ENOTTY;
12016b96018bSArnd Bergmann 
120229ce8f97SJakub Kicinski 	if (get_user_ifreq(&ifr, &data, argp))
120329ce8f97SJakub Kicinski 		return -EFAULT;
120429ce8f97SJakub Kicinski 	err = dev_ioctl(net, cmd, &ifr, data, &need_copyout);
1205a554bf96SArnd Bergmann 	if (!err && need_copyout)
120636fd633eSAl Viro 		if (put_user_ifreq(&ifr, argp))
1207a554bf96SArnd Bergmann 			return -EFAULT;
120844c02a2cSAl Viro 
1209a554bf96SArnd Bergmann 	return err;
121044c02a2cSAl Viro }
1211876f0bf9SArnd Bergmann 
12126b96018bSArnd Bergmann /*
12136b96018bSArnd Bergmann  *	With an ioctl, arg may well be a user mode pointer, but we don't know
12146b96018bSArnd Bergmann  *	what to do with it - that's up to the protocol still.
12151da177e4SLinus Torvalds  */
12161da177e4SLinus Torvalds 
sock_ioctl(struct file * file,unsigned cmd,unsigned long arg)12171da177e4SLinus Torvalds static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
12181da177e4SLinus Torvalds {
12191da177e4SLinus Torvalds 	const struct proto_ops  *ops;
12201da177e4SLinus Torvalds 	struct socket *sock;
12211da177e4SLinus Torvalds 	struct sock *sk;
12221ded5e5aSEric Dumazet 	void __user *argp = (void __user *)arg;
12231da177e4SLinus Torvalds 	int pid, err;
1224881d966bSEric W. Biederman 	struct net *net;
12251da177e4SLinus Torvalds 
12261da177e4SLinus Torvalds 	sock = file->private_data;
1227881d966bSEric W. Biederman 	ops = READ_ONCE(sock->ops);
12281da177e4SLinus Torvalds 	sk = sock->sk;
1229b69aee04SEric Dumazet 	net = sock_net(sk);
12301ded5e5aSEric Dumazet 	if (unlikely(cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))) {
1231881d966bSEric W. Biederman 		struct ifreq ifr;
12323b1e0a65SYOSHIFUJI Hideaki 		void __user *data;
123344c02a2cSAl Viro 		bool need_copyout;
123444c02a2cSAl Viro 		if (get_user_ifreq(&ifr, &data, argp))
1235a554bf96SArnd Bergmann 			return -EFAULT;
123644c02a2cSAl Viro 		err = dev_ioctl(net, cmd, &ifr, data, &need_copyout);
1237a554bf96SArnd Bergmann 		if (!err && need_copyout)
123844c02a2cSAl Viro 			if (put_user_ifreq(&ifr, argp))
1239a554bf96SArnd Bergmann 				return -EFAULT;
124044c02a2cSAl Viro 	} else
1241a554bf96SArnd Bergmann #ifdef CONFIG_WEXT_CORE
124244c02a2cSAl Viro 	if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
12431da177e4SLinus Torvalds 		err = wext_handle_ioctl(net, cmd, argp);
12443d23e349SJohannes Berg 	} else
12451da177e4SLinus Torvalds #endif
1246b1b0c245SAl Viro 		switch (cmd) {
12471da177e4SLinus Torvalds 		case FIOSETOWN:
12483d23e349SJohannes Berg 		case SIOCSPGRP:
12491da177e4SLinus Torvalds 			err = -EFAULT;
12501da177e4SLinus Torvalds 			if (get_user(pid, (int __user *)argp))
12511da177e4SLinus Torvalds 				break;
12521da177e4SLinus Torvalds 			err = f_setown(sock->file, pid, 1);
12531da177e4SLinus Torvalds 			break;
12541da177e4SLinus Torvalds 		case FIOGETOWN:
1255393cc3f5SJiri Slaby 		case SIOCGPGRP:
12561da177e4SLinus Torvalds 			err = put_user(f_getown(sock->file),
12571da177e4SLinus Torvalds 				       (int __user *)argp);
12581da177e4SLinus Torvalds 			break;
1259609d7fa9SEric W. Biederman 		case SIOCGIFBR:
126089bddce5SStephen Hemminger 		case SIOCSIFBR:
12611da177e4SLinus Torvalds 		case SIOCBRADDBR:
12621da177e4SLinus Torvalds 		case SIOCBRDELBR:
12631da177e4SLinus Torvalds 		case SIOCBRADDIF:
12641da177e4SLinus Torvalds 		case SIOCBRDELIF:
12651da177e4SLinus Torvalds 			err = br_ioctl_call(net, cmd, argp);
1266ad2f99aeSArnd Bergmann 			break;
12671da177e4SLinus Torvalds 		case SIOCGIFVLAN:
12681da177e4SLinus Torvalds 		case SIOCSIFVLAN:
12691da177e4SLinus Torvalds 			err = -ENOPKG;
12701da177e4SLinus Torvalds 			if (!vlan_ioctl_hook)
12711da177e4SLinus Torvalds 				request_module("8021q");
12721da177e4SLinus Torvalds 
12731da177e4SLinus Torvalds 			mutex_lock(&vlan_ioctl_mutex);
12744a3e2f71SArjan van de Ven 			if (vlan_ioctl_hook)
12751da177e4SLinus Torvalds 				err = vlan_ioctl_hook(net, argp);
1276881d966bSEric W. Biederman 			mutex_unlock(&vlan_ioctl_mutex);
12774a3e2f71SArjan van de Ven 			break;
12781da177e4SLinus Torvalds 		case SIOCGSKNS:
1279c62cce2cSAndrey Vagin 			err = -EPERM;
1280c62cce2cSAndrey Vagin 			if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
1281c62cce2cSAndrey Vagin 				break;
1282c62cce2cSAndrey Vagin 
1283c62cce2cSAndrey Vagin 			err = open_related_ns(&net->ns, get_net_ns);
1284c62cce2cSAndrey Vagin 			break;
1285c62cce2cSAndrey Vagin 		case SIOCGSTAMP_OLD:
12860768e170SArnd Bergmann 		case SIOCGSTAMPNS_OLD:
12870768e170SArnd Bergmann 			if (!ops->gettstamp) {
12881ded5e5aSEric Dumazet 				err = -ENOIOCTLCMD;
1289c7cbdbf2SArnd Bergmann 				break;
1290c7cbdbf2SArnd Bergmann 			}
1291c7cbdbf2SArnd Bergmann 			err = ops->gettstamp(sock, argp,
12921ded5e5aSEric Dumazet 					     cmd == SIOCGSTAMP_OLD,
12930768e170SArnd Bergmann 					     !IS_ENABLED(CONFIG_64BIT));
12940768e170SArnd Bergmann 			break;
129560747828SGustavo A. R. Silva 		case SIOCGSTAMP_NEW:
12960768e170SArnd Bergmann 		case SIOCGSTAMPNS_NEW:
12970768e170SArnd Bergmann 			if (!ops->gettstamp) {
12981ded5e5aSEric Dumazet 				err = -ENOIOCTLCMD;
12990768e170SArnd Bergmann 				break;
13000768e170SArnd Bergmann 			}
13010768e170SArnd Bergmann 			err = ops->gettstamp(sock, argp,
13021ded5e5aSEric Dumazet 					     cmd == SIOCGSTAMP_NEW,
13030768e170SArnd Bergmann 					     false);
13040768e170SArnd Bergmann 			break;
1305c7cbdbf2SArnd Bergmann 
1306876f0bf9SArnd Bergmann 		case SIOCGIFCONF:
1307876f0bf9SArnd Bergmann 			err = dev_ifconf(net, argp);
1308876f0bf9SArnd Bergmann 			break;
1309876f0bf9SArnd Bergmann 
1310876f0bf9SArnd Bergmann 		default:
13111da177e4SLinus Torvalds 			err = sock_do_ioctl(net, sock, cmd, arg);
131263ff03abSJohannes Berg 			break;
13131da177e4SLinus Torvalds 		}
13141da177e4SLinus Torvalds 	return err;
13151da177e4SLinus Torvalds }
13161da177e4SLinus Torvalds 
13171da177e4SLinus Torvalds /**
13188a3c245cSPedro Tammela  *	sock_create_lite - creates a socket
13198a3c245cSPedro Tammela  *	@family: protocol family (AF_INET, ...)
13208a3c245cSPedro Tammela  *	@type: communication type (SOCK_STREAM, ...)
13218a3c245cSPedro Tammela  *	@protocol: protocol (0, ...)
13228a3c245cSPedro Tammela  *	@res: new socket
13238a3c245cSPedro Tammela  *
13248a3c245cSPedro Tammela  *	Creates a new socket and assigns it to @res, passing through LSM.
13258a3c245cSPedro Tammela  *	The new socket initialization is not complete, see kernel_accept().
13268a3c245cSPedro Tammela  *	Returns 0 or an error. On failure @res is set to %NULL.
13278a3c245cSPedro Tammela  *	This function internally uses GFP_KERNEL.
13288a3c245cSPedro Tammela  */
13298a3c245cSPedro Tammela 
sock_create_lite(int family,int type,int protocol,struct socket ** res)13308a3c245cSPedro Tammela int sock_create_lite(int family, int type, int protocol, struct socket **res)
13311da177e4SLinus Torvalds {
13321da177e4SLinus Torvalds 	int err;
13331da177e4SLinus Torvalds 	struct socket *sock = NULL;
13341da177e4SLinus Torvalds 
13351da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, 1);
13361da177e4SLinus Torvalds 	if (err)
13371da177e4SLinus Torvalds 		goto out;
13381da177e4SLinus Torvalds 
13391da177e4SLinus Torvalds 	sock = sock_alloc();
13401da177e4SLinus Torvalds 	if (!sock) {
13411da177e4SLinus Torvalds 		err = -ENOMEM;
13421da177e4SLinus Torvalds 		goto out;
13431da177e4SLinus Torvalds 	}
13441da177e4SLinus Torvalds 
13451da177e4SLinus Torvalds 	sock->type = type;
13461da177e4SLinus Torvalds 	err = security_socket_post_create(sock, family, type, protocol, 1);
13477420ed23SVenkat Yekkirala 	if (err)
13487420ed23SVenkat Yekkirala 		goto out_release;
13497420ed23SVenkat Yekkirala 
13507420ed23SVenkat Yekkirala out:
13511da177e4SLinus Torvalds 	*res = sock;
13521da177e4SLinus Torvalds 	return err;
13531da177e4SLinus Torvalds out_release:
13547420ed23SVenkat Yekkirala 	sock_release(sock);
13557420ed23SVenkat Yekkirala 	sock = NULL;
13567420ed23SVenkat Yekkirala 	goto out;
13577420ed23SVenkat Yekkirala }
13581da177e4SLinus Torvalds EXPORT_SYMBOL(sock_create_lite);
1359c6d409cfSEric Dumazet 
13601da177e4SLinus Torvalds /* No kernel lock held - perfect */
sock_poll(struct file * file,poll_table * wait)13611da177e4SLinus Torvalds static __poll_t sock_poll(struct file *file, poll_table *wait)
1362ade994f4SAl Viro {
13631da177e4SLinus Torvalds 	struct socket *sock = file->private_data;
13643cafb376SChristoph Hellwig 	const struct proto_ops *ops = READ_ONCE(sock->ops);
13651ded5e5aSEric Dumazet 	__poll_t events = poll_requested_events(wait), flag = 0;
1366a331de3bSChristoph Hellwig 
13671da177e4SLinus Torvalds 	if (!ops->poll)
13681ded5e5aSEric Dumazet 		return 0;
1369e88958e6SChristoph Hellwig 
1370f641f13bSChristoph Hellwig 	if (sk_can_busy_loop(sock->sk)) {
1371a331de3bSChristoph Hellwig 		/* poll once if requested by the syscall */
1372f641f13bSChristoph Hellwig 		if (events & POLL_BUSY_LOOP)
1373a331de3bSChristoph Hellwig 			sk_busy_loop(sock->sk, 1);
1374f641f13bSChristoph Hellwig 
1375a331de3bSChristoph Hellwig 		/* if this socket can poll_ll, tell the system call */
1376a331de3bSChristoph Hellwig 		flag = POLL_BUSY_LOOP;
1377a331de3bSChristoph Hellwig 	}
1378a331de3bSChristoph Hellwig 
1379a331de3bSChristoph Hellwig 	return ops->poll(file, sock, wait) | flag;
13801ded5e5aSEric Dumazet }
13811da177e4SLinus Torvalds 
sock_mmap(struct file * file,struct vm_area_struct * vma)13821da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma)
13831da177e4SLinus Torvalds {
13841da177e4SLinus Torvalds 	struct socket *sock = file->private_data;
1385b69aee04SEric Dumazet 
13861da177e4SLinus Torvalds 	return READ_ONCE(sock->ops)->mmap(file, sock, vma);
13871ded5e5aSEric Dumazet }
13881da177e4SLinus Torvalds 
sock_close(struct inode * inode,struct file * filp)13891da177e4SLinus Torvalds static int sock_close(struct inode *inode, struct file *filp)
139020380731SArnaldo Carvalho de Melo {
13911da177e4SLinus Torvalds 	__sock_release(SOCKET_I(inode), inode);
13926d8c50dcSCong Wang 	return 0;
13931da177e4SLinus Torvalds }
13941da177e4SLinus Torvalds 
13951da177e4SLinus Torvalds /*
13961da177e4SLinus Torvalds  *	Update the socket async list
13971da177e4SLinus Torvalds  *
13981da177e4SLinus Torvalds  *	Fasync_list locking strategy.
13991da177e4SLinus Torvalds  *
14001da177e4SLinus Torvalds  *	1. fasync_list is modified only under process context socket lock
14011da177e4SLinus Torvalds  *	   i.e. under semaphore.
14021da177e4SLinus Torvalds  *	2. fasync_list is used under read_lock(&sk->sk_callback_lock)
14031da177e4SLinus Torvalds  *	   or under socket lock
1404989a2979SEric Dumazet  */
14051da177e4SLinus Torvalds 
sock_fasync(int fd,struct file * filp,int on)14061da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on)
14071da177e4SLinus Torvalds {
14081da177e4SLinus Torvalds 	struct socket *sock = filp->private_data;
1409989a2979SEric Dumazet 	struct sock *sk = sock->sk;
1410989a2979SEric Dumazet 	struct socket_wq *wq = &sock->wq;
1411333f7909SAl Viro 
14121da177e4SLinus Torvalds 	if (sk == NULL)
1413989a2979SEric Dumazet 		return -EINVAL;
14141da177e4SLinus Torvalds 
14151da177e4SLinus Torvalds 	lock_sock(sk);
14161da177e4SLinus Torvalds 	fasync_helper(fd, filp, on, &wq->fasync_list);
1417eaefd110SEric Dumazet 
14181da177e4SLinus Torvalds 	if (!wq->fasync_list)
1419eaefd110SEric Dumazet 		sock_reset_flag(sk, SOCK_FASYNC);
1420bcdce719SEric Dumazet 	else
1421989a2979SEric Dumazet 		sock_set_flag(sk, SOCK_FASYNC);
1422989a2979SEric Dumazet 
14231da177e4SLinus Torvalds 	release_sock(sk);
1424989a2979SEric Dumazet 	return 0;
14251da177e4SLinus Torvalds }
14261da177e4SLinus Torvalds 
14271da177e4SLinus Torvalds /* This function may be called only under rcu_lock */
1428ceb5d58bSEric Dumazet 
sock_wake_async(struct socket_wq * wq,int how,int band)14291da177e4SLinus Torvalds int sock_wake_async(struct socket_wq *wq, int how, int band)
1430ceb5d58bSEric Dumazet {
14311da177e4SLinus Torvalds 	if (!wq || !wq->fasync_list)
1432ceb5d58bSEric Dumazet 		return -1;
1433ceb5d58bSEric Dumazet 
143443815482SEric Dumazet 	switch (how) {
143589bddce5SStephen Hemminger 	case SOCK_WAKE_WAITD:
14368d8ad9d7SPavel Emelyanov 		if (test_bit(SOCKWQ_ASYNC_WAITDATA, &wq->flags))
1437ceb5d58bSEric Dumazet 			break;
14381da177e4SLinus Torvalds 		goto call_kill;
14391da177e4SLinus Torvalds 	case SOCK_WAKE_SPACE:
14408d8ad9d7SPavel Emelyanov 		if (!test_and_clear_bit(SOCKWQ_ASYNC_NOSPACE, &wq->flags))
1441ceb5d58bSEric Dumazet 			break;
14421da177e4SLinus Torvalds 		fallthrough;
14437c7ab580SMiaohe Lin 	case SOCK_WAKE_IO:
14448d8ad9d7SPavel Emelyanov call_kill:
14451da177e4SLinus Torvalds 		kill_fasync(&wq->fasync_list, SIGIO, band);
144643815482SEric Dumazet 		break;
14471da177e4SLinus Torvalds 	case SOCK_WAKE_URG:
14488d8ad9d7SPavel Emelyanov 		kill_fasync(&wq->fasync_list, SIGURG, band);
144943815482SEric Dumazet 	}
14501da177e4SLinus Torvalds 
1451ceb5d58bSEric Dumazet 	return 0;
14521da177e4SLinus Torvalds }
14531da177e4SLinus Torvalds EXPORT_SYMBOL(sock_wake_async);
1454c6d409cfSEric Dumazet 
14551da177e4SLinus Torvalds /**
14568a3c245cSPedro Tammela  *	__sock_create - creates a socket
14578a3c245cSPedro Tammela  *	@net: net namespace
14588a3c245cSPedro Tammela  *	@family: protocol family (AF_INET, ...)
14598a3c245cSPedro Tammela  *	@type: communication type (SOCK_STREAM, ...)
14608a3c245cSPedro Tammela  *	@protocol: protocol (0, ...)
14618a3c245cSPedro Tammela  *	@res: new socket
14628a3c245cSPedro Tammela  *	@kern: boolean for kernel space sockets
14638a3c245cSPedro Tammela  *
14648a3c245cSPedro Tammela  *	Creates a new socket and assigns it to @res, passing through LSM.
14658a3c245cSPedro Tammela  *	Returns 0 or an error. On failure @res is set to %NULL. @kern must
14668a3c245cSPedro Tammela  *	be set to true if the socket resides in kernel space.
14678a3c245cSPedro Tammela  *	This function internally uses GFP_KERNEL.
14688a3c245cSPedro Tammela  */
14698a3c245cSPedro Tammela 
__sock_create(struct net * net,int family,int type,int protocol,struct socket ** res,int kern)14708a3c245cSPedro Tammela int __sock_create(struct net *net, int family, int type, int protocol,
1471721db93aSPavel Emelyanov 			 struct socket **res, int kern)
147289bddce5SStephen Hemminger {
14731da177e4SLinus Torvalds 	int err;
14741da177e4SLinus Torvalds 	struct socket *sock;
14751da177e4SLinus Torvalds 	const struct net_proto_family *pf;
147655737fdaSStephen Hemminger 
14771da177e4SLinus Torvalds 	/*
14781da177e4SLinus Torvalds 	 *      Check protocol is in range
14791da177e4SLinus Torvalds 	 */
14801da177e4SLinus Torvalds 	if (family < 0 || family >= NPROTO)
14811da177e4SLinus Torvalds 		return -EAFNOSUPPORT;
14821da177e4SLinus Torvalds 	if (type < 0 || type >= SOCK_MAX)
14831da177e4SLinus Torvalds 		return -EINVAL;
14841da177e4SLinus Torvalds 
14851da177e4SLinus Torvalds 	/* Compatibility.
14861da177e4SLinus Torvalds 
14871da177e4SLinus Torvalds 	   This uglymoron is moved from INET layer to here to avoid
14881da177e4SLinus Torvalds 	   deadlock in module load.
14891da177e4SLinus Torvalds 	 */
14901da177e4SLinus Torvalds 	if (family == PF_INET && type == SOCK_PACKET) {
14911da177e4SLinus Torvalds 		pr_info_once("%s uses obsolete (PF_INET,SOCK_PACKET)\n",
1492f3c98690Sliping.zhang 			     current->comm);
149389bddce5SStephen Hemminger 		family = PF_PACKET;
14941da177e4SLinus Torvalds 	}
14951da177e4SLinus Torvalds 
14961da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, kern);
14971da177e4SLinus Torvalds 	if (err)
14981da177e4SLinus Torvalds 		return err;
14991da177e4SLinus Torvalds 
15001da177e4SLinus Torvalds 	/*
150155737fdaSStephen Hemminger 	 *	Allocate the socket and allow the family to set things up. if
150255737fdaSStephen Hemminger 	 *	the protocol is 0, the family is instructed to select an appropriate
150355737fdaSStephen Hemminger 	 *	default.
150455737fdaSStephen Hemminger 	 */
150555737fdaSStephen Hemminger 	sock = sock_alloc();
150655737fdaSStephen Hemminger 	if (!sock) {
150755737fdaSStephen Hemminger 		net_warn_ratelimited("socket: no more sockets\n");
1508e87cc472SJoe Perches 		return -ENFILE;	/* Not exactly a match, but its the
150955737fdaSStephen Hemminger 				   closest posix thing */
151055737fdaSStephen Hemminger 	}
151155737fdaSStephen Hemminger 
151255737fdaSStephen Hemminger 	sock->type = type;
151355737fdaSStephen Hemminger 
151455737fdaSStephen Hemminger #ifdef CONFIG_MODULES
151595a5afcaSJohannes Berg 	/* Attempt to load a protocol module if the find failed.
15161da177e4SLinus Torvalds 	 *
15171da177e4SLinus Torvalds 	 * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
15181da177e4SLinus Torvalds 	 * requested real, full-featured networking support upon configuration.
15191da177e4SLinus Torvalds 	 * Otherwise module support will break!
15201da177e4SLinus Torvalds 	 */
15211da177e4SLinus Torvalds 	if (rcu_access_pointer(net_families[family]) == NULL)
1522190683a9SEric Dumazet 		request_module("net-pf-%d", family);
15231da177e4SLinus Torvalds #endif
15241da177e4SLinus Torvalds 
15251da177e4SLinus Torvalds 	rcu_read_lock();
152655737fdaSStephen Hemminger 	pf = rcu_dereference(net_families[family]);
152755737fdaSStephen Hemminger 	err = -EAFNOSUPPORT;
15281da177e4SLinus Torvalds 	if (!pf)
152955737fdaSStephen Hemminger 		goto out_release;
153055737fdaSStephen Hemminger 
15311da177e4SLinus Torvalds 	/*
15321da177e4SLinus Torvalds 	 * We will call the ->create function, that possibly is in a loadable
15331da177e4SLinus Torvalds 	 * module, so we have to bump that loadable module refcnt first.
15341da177e4SLinus Torvalds 	 */
15351da177e4SLinus Torvalds 	if (!try_module_get(pf->owner))
153655737fdaSStephen Hemminger 		goto out_release;
15371da177e4SLinus Torvalds 
15381da177e4SLinus Torvalds 	/* Now protected by module ref count */
153955737fdaSStephen Hemminger 	rcu_read_unlock();
154055737fdaSStephen Hemminger 
154155737fdaSStephen Hemminger 	err = pf->create(net, sock, protocol, kern);
15423f378b68SEric Paris 	if (err < 0) {
154363108314SIgnat Korchagin 		/* ->create should release the allocated sock->sk object on error
154463108314SIgnat Korchagin 		 * and make sure sock->sk is set to NULL to avoid use-after-free
154548156296SIgnat Korchagin 		 */
154663108314SIgnat Korchagin 		DEBUG_NET_WARN_ONCE(sock->sk,
15474bbd360aSKuniyuki Iwashima 				    "%ps must clear sock->sk on failure, family: %d, type: %d, protocol: %d\n",
15484bbd360aSKuniyuki Iwashima 				    pf->create, family, type, protocol);
15494bbd360aSKuniyuki Iwashima 		goto out_module_put;
15501da177e4SLinus Torvalds 	}
155163108314SIgnat Korchagin 
1552a79af59eSFrank Filz 	/*
15531da177e4SLinus Torvalds 	 * Now to bump the refcnt of the [loadable] module that owns this
15541da177e4SLinus Torvalds 	 * socket at sock_release time we decrement its refcnt.
15551da177e4SLinus Torvalds 	 */
15561da177e4SLinus Torvalds 	if (!try_module_get(sock->ops->owner))
155755737fdaSStephen Hemminger 		goto out_module_busy;
155855737fdaSStephen Hemminger 
155955737fdaSStephen Hemminger 	/*
15601da177e4SLinus Torvalds 	 * Now that we're done with the ->create function, the [loadable]
15611da177e4SLinus Torvalds 	 * module can have its refcnt decremented
15621da177e4SLinus Torvalds 	 */
15631da177e4SLinus Torvalds 	module_put(pf->owner);
156455737fdaSStephen Hemminger 	err = security_socket_post_create(sock, family, type, protocol, kern);
15657420ed23SVenkat Yekkirala 	if (err)
15667420ed23SVenkat Yekkirala 		goto out_sock_release;
15673b185525SHerbert Xu 	*res = sock;
156855737fdaSStephen Hemminger 
15691da177e4SLinus Torvalds 	return 0;
157055737fdaSStephen Hemminger 
157155737fdaSStephen Hemminger out_module_busy:
157255737fdaSStephen Hemminger 	err = -EAFNOSUPPORT;
157355737fdaSStephen Hemminger out_module_put:
15741da177e4SLinus Torvalds 	sock->ops = NULL;
157555737fdaSStephen Hemminger 	module_put(pf->owner);
157655737fdaSStephen Hemminger out_sock_release:
157755737fdaSStephen Hemminger 	sock_release(sock);
15781da177e4SLinus Torvalds 	return err;
157955737fdaSStephen Hemminger 
158055737fdaSStephen Hemminger out_release:
158155737fdaSStephen Hemminger 	rcu_read_unlock();
158255737fdaSStephen Hemminger 	goto out_sock_release;
158355737fdaSStephen Hemminger }
15841da177e4SLinus Torvalds EXPORT_SYMBOL(__sock_create);
1585721db93aSPavel Emelyanov 
15861da177e4SLinus Torvalds /**
15878a3c245cSPedro Tammela  *	sock_create - creates a socket
15888a3c245cSPedro Tammela  *	@family: protocol family (AF_INET, ...)
15898a3c245cSPedro Tammela  *	@type: communication type (SOCK_STREAM, ...)
15908a3c245cSPedro Tammela  *	@protocol: protocol (0, ...)
15918a3c245cSPedro Tammela  *	@res: new socket
15928a3c245cSPedro Tammela  *
15938a3c245cSPedro Tammela  *	A wrapper around __sock_create().
15948a3c245cSPedro Tammela  *	Returns 0 or an error. This function internally uses GFP_KERNEL.
15958a3c245cSPedro Tammela  */
15968a3c245cSPedro Tammela 
sock_create(int family,int type,int protocol,struct socket ** res)15978a3c245cSPedro Tammela int sock_create(int family, int type, int protocol, struct socket **res)
15981da177e4SLinus Torvalds {
15991da177e4SLinus Torvalds 	return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
16001b8d7ae4SEric W. Biederman }
16011da177e4SLinus Torvalds EXPORT_SYMBOL(sock_create);
1602c6d409cfSEric Dumazet 
16031da177e4SLinus Torvalds /**
16048a3c245cSPedro Tammela  *	sock_create_kern - creates a socket (kernel space)
16058a3c245cSPedro Tammela  *	@net: net namespace
16068a3c245cSPedro Tammela  *	@family: protocol family (AF_INET, ...)
16078a3c245cSPedro Tammela  *	@type: communication type (SOCK_STREAM, ...)
16088a3c245cSPedro Tammela  *	@protocol: protocol (0, ...)
16098a3c245cSPedro Tammela  *	@res: new socket
16108a3c245cSPedro Tammela  *
16118a3c245cSPedro Tammela  *	A wrapper around __sock_create().
16128a3c245cSPedro Tammela  *	Returns 0 or an error. This function internally uses GFP_KERNEL.
16138a3c245cSPedro Tammela  */
16148a3c245cSPedro Tammela 
sock_create_kern(struct net * net,int family,int type,int protocol,struct socket ** res)16158a3c245cSPedro Tammela int sock_create_kern(struct net *net, int family, int type, int protocol, struct socket **res)
1616eeb1bd5cSEric W. Biederman {
16171da177e4SLinus Torvalds 	return __sock_create(net, family, type, protocol, res, 1);
1618eeb1bd5cSEric W. Biederman }
16191da177e4SLinus Torvalds EXPORT_SYMBOL(sock_create_kern);
1620c6d409cfSEric Dumazet 
__sys_socket_create(int family,int type,int protocol)16211da177e4SLinus Torvalds static struct socket *__sys_socket_create(int family, int type, int protocol)
1622da214a47SJens Axboe {
16231da177e4SLinus Torvalds 	struct socket *sock;
16241da177e4SLinus Torvalds 	int retval;
1625da214a47SJens Axboe 
1626a677a039SUlrich Drepper 	/* Check the SOCK_* constants for consistency.  */
1627e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
1628e38b36f3SUlrich Drepper 	BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
1629e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);
1630e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);
1631e38b36f3SUlrich Drepper 
1632e38b36f3SUlrich Drepper 	if ((type & ~SOCK_TYPE_MASK) & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1633da214a47SJens Axboe 		return ERR_PTR(-EINVAL);
1634da214a47SJens Axboe 	type &= SOCK_TYPE_MASK;
1635a677a039SUlrich Drepper 
16361da177e4SLinus Torvalds 	retval = sock_create(family, type, protocol, &sock);
16371da177e4SLinus Torvalds 	if (retval < 0)
16381da177e4SLinus Torvalds 		return ERR_PTR(retval);
1639da214a47SJens Axboe 
1640da214a47SJens Axboe 	return sock;
1641da214a47SJens Axboe }
1642da214a47SJens Axboe 
__sys_socket_file(int family,int type,int protocol)1643da214a47SJens Axboe struct file *__sys_socket_file(int family, int type, int protocol)
1644da214a47SJens Axboe {
1645da214a47SJens Axboe 	struct socket *sock;
1646da214a47SJens Axboe 	int flags;
1647da214a47SJens Axboe 
1648da214a47SJens Axboe 	sock = __sys_socket_create(family, type, protocol);
1649da214a47SJens Axboe 	if (IS_ERR(sock))
1650da214a47SJens Axboe 		return ERR_CAST(sock);
1651da214a47SJens Axboe 
1652da214a47SJens Axboe 	flags = type & ~SOCK_TYPE_MASK;
1653da214a47SJens Axboe 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1654da214a47SJens Axboe 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1655da214a47SJens Axboe 
1656da214a47SJens Axboe 	return sock_alloc_file(sock, flags, NULL);
1657649c15c7SThadeu Lima de Souza Cascardo }
1658da214a47SJens Axboe 
1659da214a47SJens Axboe /*	A hook for bpf progs to attach to and update socket protocol.
16600dd061a6SGeliang Tang  *
16610dd061a6SGeliang Tang  *	A static noinline declaration here could cause the compiler to
16620dd061a6SGeliang Tang  *	optimize away the function. A global noinline declaration will
16630dd061a6SGeliang Tang  *	keep the definition, but may optimize away the callsite.
16640dd061a6SGeliang Tang  *	Therefore, __weak is needed to ensure that the call is still
16650dd061a6SGeliang Tang  *	emitted, by telling the compiler that we don't know what the
16660dd061a6SGeliang Tang  *	function might eventually be.
16670dd061a6SGeliang Tang  */
16680dd061a6SGeliang Tang 
16690dd061a6SGeliang Tang __bpf_hook_start();
167015fb6f2bSDave Marchevsky 
update_socket_protocol(int family,int type,int protocol)16710dd061a6SGeliang Tang __weak noinline int update_socket_protocol(int family, int type, int protocol)
16720dd061a6SGeliang Tang {
16730dd061a6SGeliang Tang 	return protocol;
16740dd061a6SGeliang Tang }
16750dd061a6SGeliang Tang 
16760dd061a6SGeliang Tang __bpf_hook_end();
167715fb6f2bSDave Marchevsky 
__sys_socket(int family,int type,int protocol)16780dd061a6SGeliang Tang int __sys_socket(int family, int type, int protocol)
1679da214a47SJens Axboe {
1680da214a47SJens Axboe 	struct socket *sock;
1681da214a47SJens Axboe 	int flags;
1682da214a47SJens Axboe 
1683da214a47SJens Axboe 	sock = __sys_socket_create(family, type,
16840dd061a6SGeliang Tang 				   update_socket_protocol(family, type, protocol));
16850dd061a6SGeliang Tang 	if (IS_ERR(sock))
1686da214a47SJens Axboe 		return PTR_ERR(sock);
1687da214a47SJens Axboe 
1688da214a47SJens Axboe 	flags = type & ~SOCK_TYPE_MASK;
1689da214a47SJens Axboe 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1690da214a47SJens Axboe 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1691da214a47SJens Axboe 
16921da177e4SLinus Torvalds 	return sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
16938e1611e2SAl Viro }
16941da177e4SLinus Torvalds 
SYSCALL_DEFINE3(socket,int,family,int,type,int,protocol)16951da177e4SLinus Torvalds SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
16969d6a15c3SDominik Brodowski {
16979d6a15c3SDominik Brodowski 	return __sys_socket(family, type, protocol);
16989d6a15c3SDominik Brodowski }
16999d6a15c3SDominik Brodowski 
17009d6a15c3SDominik Brodowski /*
17011da177e4SLinus Torvalds  *	Create a pair of connected sockets.
17021da177e4SLinus Torvalds  */
17031da177e4SLinus Torvalds 
__sys_socketpair(int family,int type,int protocol,int __user * usockvec)17041da177e4SLinus Torvalds int __sys_socketpair(int family, int type, int protocol, int __user *usockvec)
17056debc8d8SDominik Brodowski {
17061da177e4SLinus Torvalds 	struct socket *sock1, *sock2;
17071da177e4SLinus Torvalds 	int fd1, fd2, err;
17081da177e4SLinus Torvalds 	struct file *newfile1, *newfile2;
1709db349509SAl Viro 	int flags;
1710a677a039SUlrich Drepper 
1711a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
1712a677a039SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
171377d27200SUlrich Drepper 		return -EINVAL;
1714a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
1715a677a039SUlrich Drepper 
17161da177e4SLinus Torvalds 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1717aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1718aaca0bdcSUlrich Drepper 
1719aaca0bdcSUlrich Drepper 	/*
17201da177e4SLinus Torvalds 	 * reserve descriptors and make sure we won't fail
1721016a266bSAl Viro 	 * to return them to userland.
1722016a266bSAl Viro 	 */
1723016a266bSAl Viro 	fd1 = get_unused_fd_flags(flags);
1724016a266bSAl Viro 	if (unlikely(fd1 < 0))
1725016a266bSAl Viro 		return fd1;
1726016a266bSAl Viro 
1727016a266bSAl Viro 	fd2 = get_unused_fd_flags(flags);
1728016a266bSAl Viro 	if (unlikely(fd2 < 0)) {
1729016a266bSAl Viro 		put_unused_fd(fd1);
1730016a266bSAl Viro 		return fd2;
1731016a266bSAl Viro 	}
1732016a266bSAl Viro 
1733016a266bSAl Viro 	err = put_user(fd1, &usockvec[0]);
1734016a266bSAl Viro 	if (err)
1735016a266bSAl Viro 		goto out;
1736016a266bSAl Viro 
1737016a266bSAl Viro 	err = put_user(fd2, &usockvec[1]);
1738016a266bSAl Viro 	if (err)
1739016a266bSAl Viro 		goto out;
1740016a266bSAl Viro 
1741016a266bSAl Viro 	/*
1742016a266bSAl Viro 	 * Obtain the first socket and check if the underlying protocol
17431da177e4SLinus Torvalds 	 * supports the socketpair call.
17441da177e4SLinus Torvalds 	 */
17451da177e4SLinus Torvalds 
17461da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock1);
17471da177e4SLinus Torvalds 	if (unlikely(err < 0))
1748016a266bSAl Viro 		goto out;
17491da177e4SLinus Torvalds 
17501da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock2);
17511da177e4SLinus Torvalds 	if (unlikely(err < 0)) {
1752016a266bSAl Viro 		sock_release(sock1);
1753016a266bSAl Viro 		goto out;
1754016a266bSAl Viro 	}
1755bf3c23d1SDavid S. Miller 
1756d73aa286SYann Droneaud 	err = security_socket_socketpair(sock1, sock2);
1757d47cd945SDavid Herrmann 	if (unlikely(err)) {
1758d47cd945SDavid Herrmann 		sock_release(sock2);
1759d47cd945SDavid Herrmann 		sock_release(sock1);
1760d47cd945SDavid Herrmann 		goto out;
1761d47cd945SDavid Herrmann 	}
1762d47cd945SDavid Herrmann 
1763d47cd945SDavid Herrmann 	err = READ_ONCE(sock1->ops)->socketpair(sock1, sock2);
17641ded5e5aSEric Dumazet 	if (unlikely(err < 0)) {
1765016a266bSAl Viro 		sock_release(sock2);
1766016a266bSAl Viro 		sock_release(sock1);
1767016a266bSAl Viro 		goto out;
1768016a266bSAl Viro 	}
176928407630SAl Viro 
177028407630SAl Viro 	newfile1 = sock_alloc_file(sock1, flags, NULL);
1771aab174f0SLinus Torvalds 	if (IS_ERR(newfile1)) {
1772b5ffe634SViresh Kumar 		err = PTR_ERR(newfile1);
177328407630SAl Viro 		sock_release(sock2);
1774016a266bSAl Viro 		goto out;
1775016a266bSAl Viro 	}
177628407630SAl Viro 
177728407630SAl Viro 	newfile2 = sock_alloc_file(sock2, flags, NULL);
1778aab174f0SLinus Torvalds 	if (IS_ERR(newfile2)) {
177928407630SAl Viro 		err = PTR_ERR(newfile2);
178028407630SAl Viro 		fput(newfile1);
1781016a266bSAl Viro 		goto out;
1782016a266bSAl Viro 	}
1783db349509SAl Viro 
1784db349509SAl Viro 	audit_fd_pair(fd1, fd2);
1785157cf649SAl Viro 
1786d73aa286SYann Droneaud 	fd_install(fd1, newfile1);
1787db349509SAl Viro 	fd_install(fd2, newfile2);
1788db349509SAl Viro 	return 0;
17891da177e4SLinus Torvalds 
17901da177e4SLinus Torvalds out:
17911da177e4SLinus Torvalds 	put_unused_fd(fd2);
1792016a266bSAl Viro 	put_unused_fd(fd1);
1793016a266bSAl Viro 	return err;
17941da177e4SLinus Torvalds }
17951da177e4SLinus Torvalds 
SYSCALL_DEFINE4(socketpair,int,family,int,type,int,protocol,int __user *,usockvec)17961da177e4SLinus Torvalds SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
17976debc8d8SDominik Brodowski 		int __user *, usockvec)
17986debc8d8SDominik Brodowski {
17996debc8d8SDominik Brodowski 	return __sys_socketpair(family, type, protocol, usockvec);
18006debc8d8SDominik Brodowski }
18016debc8d8SDominik Brodowski 
__sys_bind_socket(struct socket * sock,struct sockaddr_storage * address,int addrlen)18026debc8d8SDominik Brodowski int __sys_bind_socket(struct socket *sock, struct sockaddr_storage *address,
1803dc2e7797SGabriel Krisman Bertazi 		      int addrlen)
1804dc2e7797SGabriel Krisman Bertazi {
1805dc2e7797SGabriel Krisman Bertazi 	int err;
1806dc2e7797SGabriel Krisman Bertazi 
1807dc2e7797SGabriel Krisman Bertazi 	err = security_socket_bind(sock, (struct sockaddr *)address,
1808dc2e7797SGabriel Krisman Bertazi 				   addrlen);
1809dc2e7797SGabriel Krisman Bertazi 	if (!err)
1810dc2e7797SGabriel Krisman Bertazi 		err = READ_ONCE(sock->ops)->bind(sock,
1811dc2e7797SGabriel Krisman Bertazi 						 (struct sockaddr *)address,
1812dc2e7797SGabriel Krisman Bertazi 						 addrlen);
1813dc2e7797SGabriel Krisman Bertazi 	return err;
1814dc2e7797SGabriel Krisman Bertazi }
1815dc2e7797SGabriel Krisman Bertazi 
1816dc2e7797SGabriel Krisman Bertazi /*
18171da177e4SLinus Torvalds  *	Bind a name to a socket. Nothing much to do here since it's
18181da177e4SLinus Torvalds  *	the protocol's responsibility to handle the local address.
18191da177e4SLinus Torvalds  *
18201da177e4SLinus Torvalds  *	We move the socket address to kernel space before we call
18211da177e4SLinus Torvalds  *	the protocol layer (having also checked the address is ok).
18221da177e4SLinus Torvalds  */
18231da177e4SLinus Torvalds 
__sys_bind(int fd,struct sockaddr __user * umyaddr,int addrlen)18241da177e4SLinus Torvalds int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)
1825a87d35d8SDominik Brodowski {
18261da177e4SLinus Torvalds 	struct socket *sock;
18271da177e4SLinus Torvalds 	struct sockaddr_storage address;
1828230b1839SYOSHIFUJI Hideaki 	CLASS(fd, f)(fd);
182953c0a58bSAl Viro 	int err;
183053c0a58bSAl Viro 
18311da177e4SLinus Torvalds 	if (fd_empty(f))
183253c0a58bSAl Viro 		return -EBADF;
183353c0a58bSAl Viro 	sock = sock_from_file(fd_file(f));
183453c0a58bSAl Viro 	if (unlikely(!sock))
183553c0a58bSAl Viro 		return -ENOTSOCK;
183653c0a58bSAl Viro 
183753c0a58bSAl Viro 	err = move_addr_to_kernel(umyaddr, addrlen, &address);
183843db362dSMaciej Żenczykowski 	if (unlikely(err))
183953c0a58bSAl Viro 		return err;
18401da177e4SLinus Torvalds 
184153c0a58bSAl Viro 	return __sys_bind_socket(sock, &address, addrlen);
184253c0a58bSAl Viro }
18431da177e4SLinus Torvalds 
SYSCALL_DEFINE3(bind,int,fd,struct sockaddr __user *,umyaddr,int,addrlen)18441da177e4SLinus Torvalds SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
1845a87d35d8SDominik Brodowski {
1846a87d35d8SDominik Brodowski 	return __sys_bind(fd, umyaddr, addrlen);
1847a87d35d8SDominik Brodowski }
1848a87d35d8SDominik Brodowski 
1849a87d35d8SDominik Brodowski /*
18501da177e4SLinus Torvalds  *	Perform a listen. Basically, we allow the protocol to do anything
18511da177e4SLinus Torvalds  *	necessary for a listen, and if that works, we mark the socket as
18521da177e4SLinus Torvalds  *	ready for listening.
18531da177e4SLinus Torvalds  */
__sys_listen_socket(struct socket * sock,int backlog)18541da177e4SLinus Torvalds int __sys_listen_socket(struct socket *sock, int backlog)
1855bb6aaf73SGabriel Krisman Bertazi {
18561da177e4SLinus Torvalds 	int somaxconn, err;
1857bb6aaf73SGabriel Krisman Bertazi 
18581da177e4SLinus Torvalds 	somaxconn = READ_ONCE(sock_net(sock->sk)->core.sysctl_somaxconn);
18593c9ba81dSKuniyuki Iwashima 	if ((unsigned int)backlog > somaxconn)
186095c96174SEric Dumazet 		backlog = somaxconn;
1861b8e1f9b5SPavel Emelyanov 
18621da177e4SLinus Torvalds 	err = security_socket_listen(sock, backlog);
18631da177e4SLinus Torvalds 	if (!err)
18646cb153caSBenjamin LaHaise 		err = READ_ONCE(sock->ops)->listen(sock, backlog);
18651ded5e5aSEric Dumazet 	return err;
1866bb6aaf73SGabriel Krisman Bertazi }
1867bb6aaf73SGabriel Krisman Bertazi 
__sys_listen(int fd,int backlog)18686cb153caSBenjamin LaHaise int __sys_listen(int fd, int backlog)
1869bb6aaf73SGabriel Krisman Bertazi {
1870bb6aaf73SGabriel Krisman Bertazi 	CLASS(fd, f)(fd);
187153c0a58bSAl Viro 	struct socket *sock;
1872bb6aaf73SGabriel Krisman Bertazi 
1873bb6aaf73SGabriel Krisman Bertazi 	if (fd_empty(f))
187453c0a58bSAl Viro 		return -EBADF;
187553c0a58bSAl Viro 	sock = sock_from_file(fd_file(f));
187653c0a58bSAl Viro 	if (unlikely(!sock))
187753c0a58bSAl Viro 		return -ENOTSOCK;
187853c0a58bSAl Viro 
187953c0a58bSAl Viro 	return __sys_listen_socket(sock, backlog);
188053c0a58bSAl Viro }
18811da177e4SLinus Torvalds 
SYSCALL_DEFINE2(listen,int,fd,int,backlog)18821da177e4SLinus Torvalds SYSCALL_DEFINE2(listen, int, fd, int, backlog)
188325e290eeSDominik Brodowski {
188425e290eeSDominik Brodowski 	return __sys_listen(fd, backlog);
188525e290eeSDominik Brodowski }
188625e290eeSDominik Brodowski 
do_accept(struct file * file,struct proto_accept_arg * arg,struct sockaddr __user * upeer_sockaddr,int __user * upeer_addrlen,int flags)188725e290eeSDominik Brodowski struct file *do_accept(struct file *file, struct proto_accept_arg *arg,
18880645fbe7SJens Axboe 		       struct sockaddr __user *upeer_sockaddr,
1889de2ea4b6SJens Axboe 		       int __user *upeer_addrlen, int flags)
1890d32f89daSPavel Begunkov {
18911da177e4SLinus Torvalds 	struct socket *sock, *newsock;
18921da177e4SLinus Torvalds 	struct file *newfile;
189339d8c1b6SDavid S. Miller 	int err, len;
1894d32f89daSPavel Begunkov 	struct sockaddr_storage address;
1895230b1839SYOSHIFUJI Hideaki 	const struct proto_ops *ops;
18961ded5e5aSEric Dumazet 
18971da177e4SLinus Torvalds 	sock = sock_from_file(file);
1898dba4a925SFlorent Revest 	if (!sock)
1899d32f89daSPavel Begunkov 		return ERR_PTR(-ENOTSOCK);
1900d32f89daSPavel Begunkov 
19011da177e4SLinus Torvalds 	newsock = sock_alloc();
1902c6d409cfSEric Dumazet 	if (!newsock)
1903c6d409cfSEric Dumazet 		return ERR_PTR(-ENFILE);
1904d32f89daSPavel Begunkov 	ops = READ_ONCE(sock->ops);
19051ded5e5aSEric Dumazet 
19061da177e4SLinus Torvalds 	newsock->type = sock->type;
19071da177e4SLinus Torvalds 	newsock->ops = ops;
19081ded5e5aSEric Dumazet 
19091da177e4SLinus Torvalds 	/*
19101da177e4SLinus Torvalds 	 * We don't need try_module_get here, as the listening socket (sock)
19111da177e4SLinus Torvalds 	 * has the protocol module (sock->ops->owner) held.
19121da177e4SLinus Torvalds 	 */
19131da177e4SLinus Torvalds 	__module_get(ops->owner);
19141ded5e5aSEric Dumazet 
19151da177e4SLinus Torvalds 	newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name);
1916aab174f0SLinus Torvalds 	if (IS_ERR(newfile))
1917d32f89daSPavel Begunkov 		return newfile;
1918d32f89daSPavel Begunkov 
191939d8c1b6SDavid S. Miller 	err = security_socket_accept(sock, newsock);
1920a79af59eSFrank Filz 	if (err)
1921a79af59eSFrank Filz 		goto out_fd;
192239d8c1b6SDavid S. Miller 
1923a79af59eSFrank Filz 	arg->flags |= sock->file->f_flags;
19240645fbe7SJens Axboe 	err = ops->accept(sock, newsock, arg);
19250645fbe7SJens Axboe 	if (err < 0)
19261da177e4SLinus Torvalds 		goto out_fd;
192739d8c1b6SDavid S. Miller 
19281da177e4SLinus Torvalds 	if (upeer_sockaddr) {
19291da177e4SLinus Torvalds 		len = ops->getname(newsock, (struct sockaddr *)&address, 2);
19301ded5e5aSEric Dumazet 		if (len < 0) {
19319b2c45d4SDenys Vlasenko 			err = -ECONNABORTED;
19321da177e4SLinus Torvalds 			goto out_fd;
193339d8c1b6SDavid S. Miller 		}
19341da177e4SLinus Torvalds 		err = move_addr_to_user(&address,
193543db362dSMaciej Żenczykowski 					len, upeer_sockaddr, upeer_addrlen);
1936230b1839SYOSHIFUJI Hideaki 		if (err < 0)
19371da177e4SLinus Torvalds 			goto out_fd;
193839d8c1b6SDavid S. Miller 	}
19391da177e4SLinus Torvalds 
19401da177e4SLinus Torvalds 	/* File flags are not inherited via accept() unlike another OSes. */
19411da177e4SLinus Torvalds 	return newfile;
1942d32f89daSPavel Begunkov out_fd:
194339d8c1b6SDavid S. Miller 	fput(newfile);
19449606a216SDavid S. Miller 	return ERR_PTR(err);
1945d32f89daSPavel Begunkov }
1946d32f89daSPavel Begunkov 
__sys_accept4_file(struct file * file,struct sockaddr __user * upeer_sockaddr,int __user * upeer_addrlen,int flags)1947de2ea4b6SJens Axboe static int __sys_accept4_file(struct file *file, struct sockaddr __user *upeer_sockaddr,
1948c0424532SYajun Deng 			      int __user *upeer_addrlen, int flags)
1949c0424532SYajun Deng {
1950d32f89daSPavel Begunkov 	struct proto_accept_arg arg = { };
19510645fbe7SJens Axboe 	struct file *newfile;
1952d32f89daSPavel Begunkov 	int newfd;
1953d32f89daSPavel Begunkov 
1954d32f89daSPavel Begunkov 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1955d32f89daSPavel Begunkov 		return -EINVAL;
1956d32f89daSPavel Begunkov 
1957d32f89daSPavel Begunkov 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1958d32f89daSPavel Begunkov 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1959d32f89daSPavel Begunkov 
1960d32f89daSPavel Begunkov 	newfd = get_unused_fd_flags(flags);
1961c0424532SYajun Deng 	if (unlikely(newfd < 0))
1962d32f89daSPavel Begunkov 		return newfd;
1963d32f89daSPavel Begunkov 
1964d32f89daSPavel Begunkov 	newfile = do_accept(file, &arg, upeer_sockaddr, upeer_addrlen,
19650645fbe7SJens Axboe 			    flags);
1966d32f89daSPavel Begunkov 	if (IS_ERR(newfile)) {
1967d32f89daSPavel Begunkov 		put_unused_fd(newfd);
1968d32f89daSPavel Begunkov 		return PTR_ERR(newfile);
1969d32f89daSPavel Begunkov 	}
1970d32f89daSPavel Begunkov 	fd_install(newfd, newfile);
1971d32f89daSPavel Begunkov 	return newfd;
1972d32f89daSPavel Begunkov }
1973de2ea4b6SJens Axboe 
1974de2ea4b6SJens Axboe /*
1975de2ea4b6SJens Axboe  *	For accept, we attempt to create a new socket, set up the link
1976de2ea4b6SJens Axboe  *	with the client, wake up the client, then return the new
1977de2ea4b6SJens Axboe  *	connected fd. We collect the address of the connector in kernel
1978de2ea4b6SJens Axboe  *	space and move it to user at the very end. This is unclean because
1979de2ea4b6SJens Axboe  *	we open the socket then return an error.
1980de2ea4b6SJens Axboe  *
1981de2ea4b6SJens Axboe  *	1003.1g adds the ability to recvmsg() to query connection pending
1982de2ea4b6SJens Axboe  *	status to recvmsg. We need to add that support in a way thats
1983de2ea4b6SJens Axboe  *	clean when we restructure accept also.
1984de2ea4b6SJens Axboe  */
1985de2ea4b6SJens Axboe 
__sys_accept4(int fd,struct sockaddr __user * upeer_sockaddr,int __user * upeer_addrlen,int flags)1986de2ea4b6SJens Axboe int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
1987de2ea4b6SJens Axboe 		  int __user *upeer_addrlen, int flags)
1988de2ea4b6SJens Axboe {
1989de2ea4b6SJens Axboe 	CLASS(fd, f)(fd);
199053c0a58bSAl Viro 
1991de2ea4b6SJens Axboe 	if (fd_empty(f))
199253c0a58bSAl Viro 		return -EBADF;
199353c0a58bSAl Viro 	return __sys_accept4_file(fd_file(f), upeer_sockaddr,
199453c0a58bSAl Viro 					 upeer_addrlen, flags);
1995c0424532SYajun Deng }
19961da177e4SLinus Torvalds 
SYSCALL_DEFINE4(accept4,int,fd,struct sockaddr __user *,upeer_sockaddr,int __user *,upeer_addrlen,int,flags)19971da177e4SLinus Torvalds SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
19984541e805SDominik Brodowski 		int __user *, upeer_addrlen, int, flags)
19994541e805SDominik Brodowski {
20004541e805SDominik Brodowski 	return __sys_accept4(fd, upeer_sockaddr, upeer_addrlen, flags);
20014541e805SDominik Brodowski }
20024541e805SDominik Brodowski 
SYSCALL_DEFINE3(accept,int,fd,struct sockaddr __user *,upeer_sockaddr,int __user *,upeer_addrlen)20034541e805SDominik Brodowski SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,
200420f37034SHeiko Carstens 		int __user *, upeer_addrlen)
200520f37034SHeiko Carstens {
2006aaca0bdcSUlrich Drepper 	return __sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0);
20074541e805SDominik Brodowski }
2008aaca0bdcSUlrich Drepper 
2009aaca0bdcSUlrich Drepper /*
20101da177e4SLinus Torvalds  *	Attempt to connect to a socket with the server address.  The address
20111da177e4SLinus Torvalds  *	is in user space so we verify it is OK and move it to kernel space.
20121da177e4SLinus Torvalds  *
20131da177e4SLinus Torvalds  *	For 1003.1g we need to add clean support for a bind to AF_UNSPEC to
20141da177e4SLinus Torvalds  *	break bindings
20151da177e4SLinus Torvalds  *
20161da177e4SLinus Torvalds  *	NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and
20171da177e4SLinus Torvalds  *	other SEQPACKET protocols that take time to connect() as it doesn't
20181da177e4SLinus Torvalds  *	include the -EINPROGRESS status for such sockets.
20191da177e4SLinus Torvalds  */
20201da177e4SLinus Torvalds 
__sys_connect_file(struct file * file,struct sockaddr_storage * address,int addrlen,int file_flags)20211da177e4SLinus Torvalds int __sys_connect_file(struct file *file, struct sockaddr_storage *address,
2022f499a021SJens Axboe 		       int addrlen, int file_flags)
2023bd3ded31SJens Axboe {
20241da177e4SLinus Torvalds 	struct socket *sock;
20251da177e4SLinus Torvalds 	int err;
2026bd3ded31SJens Axboe 
20271da177e4SLinus Torvalds 	sock = sock_from_file(file);
2028dba4a925SFlorent Revest 	if (!sock) {
2029dba4a925SFlorent Revest 		err = -ENOTSOCK;
2030dba4a925SFlorent Revest 		goto out;
20311da177e4SLinus Torvalds 	}
2032dba4a925SFlorent Revest 
20331da177e4SLinus Torvalds 	err =
203489bddce5SStephen Hemminger 	    security_socket_connect(sock, (struct sockaddr *)address, addrlen);
2035f499a021SJens Axboe 	if (err)
20361da177e4SLinus Torvalds 		goto out;
2037bd3ded31SJens Axboe 
20381da177e4SLinus Torvalds 	err = READ_ONCE(sock->ops)->connect(sock, (struct sockaddr *)address,
20391ded5e5aSEric Dumazet 				addrlen, sock->file->f_flags | file_flags);
20401ded5e5aSEric Dumazet out:
20411da177e4SLinus Torvalds 	return err;
20421da177e4SLinus Torvalds }
20431da177e4SLinus Torvalds 
__sys_connect(int fd,struct sockaddr __user * uservaddr,int addrlen)20441da177e4SLinus Torvalds int __sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen)
2045bd3ded31SJens Axboe {
2046bd3ded31SJens Axboe 	struct sockaddr_storage address;
2047f499a021SJens Axboe 	CLASS(fd, f)(fd);
204853c0a58bSAl Viro 	int ret;
204953c0a58bSAl Viro 
205053c0a58bSAl Viro 	if (fd_empty(f))
205153c0a58bSAl Viro 		return -EBADF;
205253c0a58bSAl Viro 
2053f499a021SJens Axboe 	ret = move_addr_to_kernel(uservaddr, addrlen, &address);
2054f499a021SJens Axboe 	if (ret)
205553c0a58bSAl Viro 		return ret;
2056bd3ded31SJens Axboe 
205753c0a58bSAl Viro 	return __sys_connect_file(fd_file(f), &address, addrlen, 0);
205853c0a58bSAl Viro }
2059bd3ded31SJens Axboe 
SYSCALL_DEFINE3(connect,int,fd,struct sockaddr __user *,uservaddr,int,addrlen)2060bd3ded31SJens Axboe SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
20611387c2c2SDominik Brodowski 		int, addrlen)
20621387c2c2SDominik Brodowski {
20631387c2c2SDominik Brodowski 	return __sys_connect(fd, uservaddr, addrlen);
20641387c2c2SDominik Brodowski }
20651387c2c2SDominik Brodowski 
20661387c2c2SDominik Brodowski /*
20671da177e4SLinus Torvalds  *	Get the local address ('name') of a socket object. Move the obtained
20681da177e4SLinus Torvalds  *	name to user space.
20691da177e4SLinus Torvalds  */
20701da177e4SLinus Torvalds 
__sys_getsockname(int fd,struct sockaddr __user * usockaddr,int __user * usockaddr_len)20711da177e4SLinus Torvalds int __sys_getsockname(int fd, struct sockaddr __user *usockaddr,
20728882a107SDominik Brodowski 		      int __user *usockaddr_len)
20738882a107SDominik Brodowski {
20741da177e4SLinus Torvalds 	struct socket *sock;
20751da177e4SLinus Torvalds 	struct sockaddr_storage address;
2076230b1839SYOSHIFUJI Hideaki 	CLASS(fd, f)(fd);
207753c0a58bSAl Viro 	int err;
207853c0a58bSAl Viro 
20791da177e4SLinus Torvalds 	if (fd_empty(f))
208053c0a58bSAl Viro 		return -EBADF;
208153c0a58bSAl Viro 	sock = sock_from_file(fd_file(f));
208253c0a58bSAl Viro 	if (unlikely(!sock))
208353c0a58bSAl Viro 		return -ENOTSOCK;
208453c0a58bSAl Viro 
20851da177e4SLinus Torvalds 	err = security_socket_getsockname(sock);
20861da177e4SLinus Torvalds 	if (err)
20871da177e4SLinus Torvalds 		return err;
208853c0a58bSAl Viro 
20891da177e4SLinus Torvalds 	err = READ_ONCE(sock->ops)->getname(sock, (struct sockaddr *)&address, 0);
20901ded5e5aSEric Dumazet 	if (err < 0)
20919b2c45d4SDenys Vlasenko 		return err;
20921da177e4SLinus Torvalds 
209353c0a58bSAl Viro 	/* "err" is actually length in this case */
209453c0a58bSAl Viro 	return move_addr_to_user(&address, err, usockaddr, usockaddr_len);
209553c0a58bSAl Viro }
20961da177e4SLinus Torvalds 
SYSCALL_DEFINE3(getsockname,int,fd,struct sockaddr __user *,usockaddr,int __user *,usockaddr_len)20971da177e4SLinus Torvalds SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
20988882a107SDominik Brodowski 		int __user *, usockaddr_len)
20998882a107SDominik Brodowski {
21008882a107SDominik Brodowski 	return __sys_getsockname(fd, usockaddr, usockaddr_len);
21018882a107SDominik Brodowski }
21028882a107SDominik Brodowski 
21038882a107SDominik Brodowski /*
21041da177e4SLinus Torvalds  *	Get the remote address ('name') of a socket object. Move the obtained
21051da177e4SLinus Torvalds  *	name to user space.
21061da177e4SLinus Torvalds  */
21071da177e4SLinus Torvalds 
__sys_getpeername(int fd,struct sockaddr __user * usockaddr,int __user * usockaddr_len)21081da177e4SLinus Torvalds int __sys_getpeername(int fd, struct sockaddr __user *usockaddr,
2109b21c8f83SDominik Brodowski 		      int __user *usockaddr_len)
2110b21c8f83SDominik Brodowski {
21111da177e4SLinus Torvalds 	struct socket *sock;
21121da177e4SLinus Torvalds 	struct sockaddr_storage address;
2113230b1839SYOSHIFUJI Hideaki 	CLASS(fd, f)(fd);
211453c0a58bSAl Viro 	int err;
211553c0a58bSAl Viro 
21161da177e4SLinus Torvalds 	if (fd_empty(f))
211753c0a58bSAl Viro 		return -EBADF;
211853c0a58bSAl Viro 	sock = sock_from_file(fd_file(f));
211953c0a58bSAl Viro 	if (unlikely(!sock))
212053c0a58bSAl Viro 		return -ENOTSOCK;
212153c0a58bSAl Viro 
21221ded5e5aSEric Dumazet 	err = security_socket_getpeername(sock);
21231da177e4SLinus Torvalds 	if (err)
212453c0a58bSAl Viro 		return err;
21251da177e4SLinus Torvalds 
21261da177e4SLinus Torvalds 	err = READ_ONCE(sock->ops)->getname(sock, (struct sockaddr *)&address, 1);
212753c0a58bSAl Viro 	if (err < 0)
212853c0a58bSAl Viro 		return err;
21291da177e4SLinus Torvalds 
213053c0a58bSAl Viro 	/* "err" is actually length in this case */
213153c0a58bSAl Viro 	return move_addr_to_user(&address, err, usockaddr, usockaddr_len);
213253c0a58bSAl Viro }
21331da177e4SLinus Torvalds 
SYSCALL_DEFINE3(getpeername,int,fd,struct sockaddr __user *,usockaddr,int __user *,usockaddr_len)21341da177e4SLinus Torvalds SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
2135b21c8f83SDominik Brodowski 		int __user *, usockaddr_len)
2136b21c8f83SDominik Brodowski {
2137b21c8f83SDominik Brodowski 	return __sys_getpeername(fd, usockaddr, usockaddr_len);
2138b21c8f83SDominik Brodowski }
2139b21c8f83SDominik Brodowski 
2140b21c8f83SDominik Brodowski /*
21411da177e4SLinus Torvalds  *	Send a datagram to a given address. We move the address into kernel
21421da177e4SLinus Torvalds  *	space and check the user space data area is readable before invoking
21431da177e4SLinus Torvalds  *	the protocol.
21441da177e4SLinus Torvalds  */
__sys_sendto(int fd,void __user * buff,size_t len,unsigned int flags,struct sockaddr __user * addr,int addr_len)21451da177e4SLinus Torvalds int __sys_sendto(int fd, void __user *buff, size_t len, unsigned int flags,
2146211b634bSDominik Brodowski 		 struct sockaddr __user *addr,  int addr_len)
2147211b634bSDominik Brodowski {
21481da177e4SLinus Torvalds 	struct socket *sock;
21491da177e4SLinus Torvalds 	struct sockaddr_storage address;
2150230b1839SYOSHIFUJI Hideaki 	int err;
21511da177e4SLinus Torvalds 	struct msghdr msg;
21521da177e4SLinus Torvalds 
21531da177e4SLinus Torvalds 	err = import_ubuf(ITER_SOURCE, buff, len, &msg.msg_iter);
21549fd7874cSJens Axboe 	if (unlikely(err))
2155602bd0e9SAl Viro 		return err;
2156602bd0e9SAl Viro 
215753c0a58bSAl Viro 	CLASS(fd, f)(fd);
215853c0a58bSAl Viro 	if (fd_empty(f))
215953c0a58bSAl Viro 		return -EBADF;
216053c0a58bSAl Viro 	sock = sock_from_file(fd_file(f));
216153c0a58bSAl Viro 	if (unlikely(!sock))
216253c0a58bSAl Viro 		return -ENOTSOCK;
216353c0a58bSAl Viro 
21646cb153caSBenjamin LaHaise 	msg.msg_name = NULL;
21651da177e4SLinus Torvalds 	msg.msg_control = NULL;
21661da177e4SLinus Torvalds 	msg.msg_controllen = 0;
21671da177e4SLinus Torvalds 	msg.msg_namelen = 0;
21681da177e4SLinus Torvalds 	msg.msg_ubuf = NULL;
21697c701d92SPavel Begunkov 	if (addr) {
21706cb153caSBenjamin LaHaise 		err = move_addr_to_kernel(addr, addr_len, &address);
217143db362dSMaciej Żenczykowski 		if (err < 0)
21721da177e4SLinus Torvalds 			return err;
217353c0a58bSAl Viro 		msg.msg_name = (struct sockaddr *)&address;
2174230b1839SYOSHIFUJI Hideaki 		msg.msg_namelen = addr_len;
21751da177e4SLinus Torvalds 	}
21761da177e4SLinus Torvalds 	flags &= ~MSG_INTERNAL_SENDMSG_FLAGS;
2177b841b901SDavid Howells 	if (sock->file->f_flags & O_NONBLOCK)
21781da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
21791da177e4SLinus Torvalds 	msg.msg_flags = flags;
21801da177e4SLinus Torvalds 	return __sock_sendmsg(sock, &msg);
218153c0a58bSAl Viro }
21821da177e4SLinus Torvalds 
SYSCALL_DEFINE6(sendto,int,fd,void __user *,buff,size_t,len,unsigned int,flags,struct sockaddr __user *,addr,int,addr_len)21831da177e4SLinus Torvalds SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
2184211b634bSDominik Brodowski 		unsigned int, flags, struct sockaddr __user *, addr,
2185211b634bSDominik Brodowski 		int, addr_len)
2186211b634bSDominik Brodowski {
2187211b634bSDominik Brodowski 	return __sys_sendto(fd, buff, len, flags, addr, addr_len);
2188211b634bSDominik Brodowski }
2189211b634bSDominik Brodowski 
2190211b634bSDominik Brodowski /*
21911da177e4SLinus Torvalds  *	Send a datagram down a socket.
21921da177e4SLinus Torvalds  */
21931da177e4SLinus Torvalds 
SYSCALL_DEFINE4(send,int,fd,void __user *,buff,size_t,len,unsigned int,flags)21941da177e4SLinus Torvalds SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len,
21953e0fa65fSHeiko Carstens 		unsigned int, flags)
219695c96174SEric Dumazet {
21971da177e4SLinus Torvalds 	return __sys_sendto(fd, buff, len, flags, NULL, 0);
2198211b634bSDominik Brodowski }
21991da177e4SLinus Torvalds 
22001da177e4SLinus Torvalds /*
22011da177e4SLinus Torvalds  *	Receive a frame from the socket and optionally record the address of the
22021da177e4SLinus Torvalds  *	sender. We verify the buffers are writable and if needed move the
22031da177e4SLinus Torvalds  *	sender address from kernel to user space.
22041da177e4SLinus Torvalds  */
__sys_recvfrom(int fd,void __user * ubuf,size_t size,unsigned int flags,struct sockaddr __user * addr,int __user * addr_len)22051da177e4SLinus Torvalds int __sys_recvfrom(int fd, void __user *ubuf, size_t size, unsigned int flags,
22067a09e1ebSDominik Brodowski 		   struct sockaddr __user *addr, int __user *addr_len)
22077a09e1ebSDominik Brodowski {
22081da177e4SLinus Torvalds 	struct sockaddr_storage address;
22091228b34cSEric Dumazet 	struct msghdr msg = {
22101228b34cSEric Dumazet 		/* Save some cycles and don't copy the address if not needed */
22111228b34cSEric Dumazet 		.msg_name = addr ? (struct sockaddr *)&address : NULL,
22121228b34cSEric Dumazet 	};
22131228b34cSEric Dumazet 	struct socket *sock;
22141da177e4SLinus Torvalds 	int err, err2;
22151da177e4SLinus Torvalds 
22161da177e4SLinus Torvalds 	err = import_ubuf(ITER_DEST, ubuf, size, &msg.msg_iter);
22179fd7874cSJens Axboe 	if (unlikely(err))
2218602bd0e9SAl Viro 		return err;
2219602bd0e9SAl Viro 
222053c0a58bSAl Viro 	CLASS(fd, f)(fd);
222153c0a58bSAl Viro 
222253c0a58bSAl Viro 	if (fd_empty(f))
222353c0a58bSAl Viro 		return -EBADF;
222453c0a58bSAl Viro 	sock = sock_from_file(fd_file(f));
222553c0a58bSAl Viro 	if (unlikely(!sock))
222653c0a58bSAl Viro 		return -ENOTSOCK;
222753c0a58bSAl Viro 
22281da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
22291da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
22301da177e4SLinus Torvalds 	err = sock_recvmsg(sock, &msg, flags);
22312da62906SAl Viro 
22321da177e4SLinus Torvalds 	if (err >= 0 && addr != NULL) {
223389bddce5SStephen Hemminger 		err2 = move_addr_to_user(&address,
223443db362dSMaciej Żenczykowski 					 msg.msg_namelen, addr, addr_len);
2235230b1839SYOSHIFUJI Hideaki 		if (err2 < 0)
22361da177e4SLinus Torvalds 			err = err2;
22371da177e4SLinus Torvalds 	}
22381da177e4SLinus Torvalds 	return err;
22391da177e4SLinus Torvalds }
22401da177e4SLinus Torvalds 
SYSCALL_DEFINE6(recvfrom,int,fd,void __user *,ubuf,size_t,size,unsigned int,flags,struct sockaddr __user *,addr,int __user *,addr_len)22411da177e4SLinus Torvalds SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
22427a09e1ebSDominik Brodowski 		unsigned int, flags, struct sockaddr __user *, addr,
22437a09e1ebSDominik Brodowski 		int __user *, addr_len)
22447a09e1ebSDominik Brodowski {
22457a09e1ebSDominik Brodowski 	return __sys_recvfrom(fd, ubuf, size, flags, addr, addr_len);
22467a09e1ebSDominik Brodowski }
22477a09e1ebSDominik Brodowski 
22487a09e1ebSDominik Brodowski /*
22491da177e4SLinus Torvalds  *	Receive a datagram from a socket.
22501da177e4SLinus Torvalds  */
22511da177e4SLinus Torvalds 
SYSCALL_DEFINE4(recv,int,fd,void __user *,ubuf,size_t,size,unsigned int,flags)22521da177e4SLinus Torvalds SYSCALL_DEFINE4(recv, int, fd, void __user *, ubuf, size_t, size,
2253b7c0ddf5SJan Glauber 		unsigned int, flags)
2254b7c0ddf5SJan Glauber {
22551da177e4SLinus Torvalds 	return __sys_recvfrom(fd, ubuf, size, flags, NULL, NULL);
22567a09e1ebSDominik Brodowski }
22571da177e4SLinus Torvalds 
sock_use_custom_sol_socket(const struct socket * sock)22581da177e4SLinus Torvalds static bool sock_use_custom_sol_socket(const struct socket *sock)
225983f0c10bSFlorian Westphal {
226083f0c10bSFlorian Westphal 	return test_bit(SOCK_CUSTOM_SOCKOPT, &sock->flags);
2261a5ef058dSPaolo Abeni }
226283f0c10bSFlorian Westphal 
do_sock_setsockopt(struct socket * sock,bool compat,int level,int optname,sockptr_t optval,int optlen)226383f0c10bSFlorian Westphal int do_sock_setsockopt(struct socket *sock, bool compat, int level,
22641406245cSBreno Leitao 		       int optname, sockptr_t optval, int optlen)
22651406245cSBreno Leitao {
22661da177e4SLinus Torvalds 	const struct proto_ops *ops;
22671ded5e5aSEric Dumazet 	char *kernel_optval = NULL;
22680d01da6aSStanislav Fomichev 	int err;
22691406245cSBreno Leitao 
22701da177e4SLinus Torvalds 	if (optlen < 0)
22711da177e4SLinus Torvalds 		return -EINVAL;
22721da177e4SLinus Torvalds 
22731da177e4SLinus Torvalds 	err = security_socket_setsockopt(sock, level, optname);
22741da177e4SLinus Torvalds 	if (err)
22756cb153caSBenjamin LaHaise 		goto out_put;
22766cb153caSBenjamin LaHaise 
22771da177e4SLinus Torvalds 	if (!compat)
22781406245cSBreno Leitao 		err = BPF_CGROUP_RUN_PROG_SETSOCKOPT(sock->sk, &level, &optname,
22794a367299SChristoph Hellwig 						     optval, &optlen,
22803f31e0d1SBreno Leitao 						     &kernel_optval);
228155db9c0eSChristoph Hellwig 	if (err < 0)
22824a367299SChristoph Hellwig 		goto out_put;
22830d01da6aSStanislav Fomichev 	if (err > 0) {
22844a367299SChristoph Hellwig 		err = 0;
22850d01da6aSStanislav Fomichev 		goto out_put;
22860d01da6aSStanislav Fomichev 	}
22870d01da6aSStanislav Fomichev 
22880d01da6aSStanislav Fomichev 	if (kernel_optval)
2289a7b75c5aSChristoph Hellwig 		optval = KERNEL_SOCKPTR(kernel_optval);
2290a7b75c5aSChristoph Hellwig 	ops = READ_ONCE(sock->ops);
22911ded5e5aSEric Dumazet 	if (level == SOL_SOCKET && !sock_use_custom_sol_socket(sock))
229283f0c10bSFlorian Westphal 		err = sock_setsockopt(sock, level, optname, optval, optlen);
2293a7b75c5aSChristoph Hellwig 	else if (unlikely(!ops->setsockopt))
22941ded5e5aSEric Dumazet 		err = -EOPNOTSUPP;
2295a44d9e72SChristoph Hellwig 	else
22961da177e4SLinus Torvalds 		err = ops->setsockopt(sock, level, optname, optval,
22971ded5e5aSEric Dumazet 					    optlen);
229889bddce5SStephen Hemminger 	kfree(kernel_optval);
22990d01da6aSStanislav Fomichev out_put:
23006cb153caSBenjamin LaHaise 	return err;
23011406245cSBreno Leitao }
23021406245cSBreno Leitao EXPORT_SYMBOL(do_sock_setsockopt);
23031406245cSBreno Leitao 
23041406245cSBreno Leitao /* Set a socket option. Because we don't know the option lengths we have
23051406245cSBreno Leitao  * to pass the user mode parameter for the protocols to sort out.
23061406245cSBreno Leitao  */
__sys_setsockopt(int fd,int level,int optname,char __user * user_optval,int optlen)23071406245cSBreno Leitao int __sys_setsockopt(int fd, int level, int optname, char __user *user_optval,
23081406245cSBreno Leitao 		     int optlen)
23091406245cSBreno Leitao {
23101406245cSBreno Leitao 	sockptr_t optval = USER_SOCKPTR(user_optval);
23111406245cSBreno Leitao 	bool compat = in_compat_syscall();
23121406245cSBreno Leitao 	struct socket *sock;
23131406245cSBreno Leitao 	CLASS(fd, f)(fd);
231453c0a58bSAl Viro 
23151406245cSBreno Leitao 	if (fd_empty(f))
231653c0a58bSAl Viro 		return -EBADF;
231753c0a58bSAl Viro 	sock = sock_from_file(fd_file(f));
231853c0a58bSAl Viro 	if (unlikely(!sock))
231953c0a58bSAl Viro 		return -ENOTSOCK;
232053c0a58bSAl Viro 
23211406245cSBreno Leitao 	return do_sock_setsockopt(sock, compat, level, optname, optval, optlen);
232253c0a58bSAl Viro }
23231da177e4SLinus Torvalds 
SYSCALL_DEFINE5(setsockopt,int,fd,int,level,int,optname,char __user *,optval,int,optlen)23241da177e4SLinus Torvalds SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
2325cc36dca0SDominik Brodowski 		char __user *, optval, int, optlen)
2326cc36dca0SDominik Brodowski {
2327cc36dca0SDominik Brodowski 	return __sys_setsockopt(fd, level, optname, optval, optlen);
2328cc36dca0SDominik Brodowski }
2329cc36dca0SDominik Brodowski 
2330cc36dca0SDominik Brodowski INDIRECT_CALLABLE_DECLARE(bool tcp_bpf_bypass_getsockopt(int level,
23319cacf81fSStanislav Fomichev 							 int optname));
23329cacf81fSStanislav Fomichev 
do_sock_getsockopt(struct socket * sock,bool compat,int level,int optname,sockptr_t optval,sockptr_t optlen)23339cacf81fSStanislav Fomichev int do_sock_getsockopt(struct socket *sock, bool compat, int level,
23340b05b0cdSBreno Leitao 		       int optname, sockptr_t optval, sockptr_t optlen)
23350b05b0cdSBreno Leitao {
23360b05b0cdSBreno Leitao 	int max_optlen __maybe_unused = 0;
233733f339a1STze-nan Wu 	const struct proto_ops *ops;
23380b05b0cdSBreno Leitao 	int err;
23390b05b0cdSBreno Leitao 
23400b05b0cdSBreno Leitao 	err = security_socket_getsockopt(sock, level, optname);
23410b05b0cdSBreno Leitao 	if (err)
23420b05b0cdSBreno Leitao 		return err;
23430b05b0cdSBreno Leitao 
23440b05b0cdSBreno Leitao 	if (!compat)
23450b05b0cdSBreno Leitao 		copy_from_sockptr(&max_optlen, optlen, sizeof(int));
234633f339a1STze-nan Wu 
23470b05b0cdSBreno Leitao 	ops = READ_ONCE(sock->ops);
23480b05b0cdSBreno Leitao 	if (level == SOL_SOCKET) {
23490b05b0cdSBreno Leitao 		err = sk_getsockopt(sock->sk, level, optname, optval, optlen);
23500b05b0cdSBreno Leitao 	} else if (unlikely(!ops->getsockopt)) {
23510b05b0cdSBreno Leitao 		err = -EOPNOTSUPP;
23520b05b0cdSBreno Leitao 	} else {
23530b05b0cdSBreno Leitao 		if (WARN_ONCE(optval.is_kernel || optlen.is_kernel,
23540b05b0cdSBreno Leitao 			      "Invalid argument type"))
23550b05b0cdSBreno Leitao 			return -EOPNOTSUPP;
23560b05b0cdSBreno Leitao 
23570b05b0cdSBreno Leitao 		err = ops->getsockopt(sock, level, optname, optval.user,
23580b05b0cdSBreno Leitao 				      optlen.user);
23590b05b0cdSBreno Leitao 	}
23600b05b0cdSBreno Leitao 
23610b05b0cdSBreno Leitao 	if (!compat)
23620b05b0cdSBreno Leitao 		err = BPF_CGROUP_RUN_PROG_GETSOCKOPT(sock->sk, level, optname,
23630b05b0cdSBreno Leitao 						     optval, optlen, max_optlen,
23640b05b0cdSBreno Leitao 						     err);
23650b05b0cdSBreno Leitao 
23660b05b0cdSBreno Leitao 	return err;
23670b05b0cdSBreno Leitao }
23680b05b0cdSBreno Leitao EXPORT_SYMBOL(do_sock_getsockopt);
23690b05b0cdSBreno Leitao 
23700b05b0cdSBreno Leitao /*
23711da177e4SLinus Torvalds  *	Get a socket option. Because we don't know the option lengths we have
23721da177e4SLinus Torvalds  *	to pass a user mode parameter for the protocols to sort out.
23731da177e4SLinus Torvalds  */
__sys_getsockopt(int fd,int level,int optname,char __user * optval,int __user * optlen)23741da177e4SLinus Torvalds int __sys_getsockopt(int fd, int level, int optname, char __user *optval,
237555db9c0eSChristoph Hellwig 		int __user *optlen)
237655db9c0eSChristoph Hellwig {
23771da177e4SLinus Torvalds 	struct socket *sock;
23781da177e4SLinus Torvalds 	CLASS(fd, f)(fd);
237953c0a58bSAl Viro 
23801da177e4SLinus Torvalds 	if (fd_empty(f))
238153c0a58bSAl Viro 		return -EBADF;
238253c0a58bSAl Viro 	sock = sock_from_file(fd_file(f));
238353c0a58bSAl Viro 	if (unlikely(!sock))
238453c0a58bSAl Viro 		return -ENOTSOCK;
238553c0a58bSAl Viro 
2386d8a9b38fSChristoph Hellwig 	return do_sock_getsockopt(sock, in_compat_syscall(), level, optname,
238753c0a58bSAl Viro 				 USER_SOCKPTR(optval), USER_SOCKPTR(optlen));
23880b05b0cdSBreno Leitao }
23891da177e4SLinus Torvalds 
SYSCALL_DEFINE5(getsockopt,int,fd,int,level,int,optname,char __user *,optval,int __user *,optlen)23901da177e4SLinus Torvalds SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
239113a2d70eSDominik Brodowski 		char __user *, optval, int __user *, optlen)
239213a2d70eSDominik Brodowski {
239313a2d70eSDominik Brodowski 	return __sys_getsockopt(fd, level, optname, optval, optlen);
239413a2d70eSDominik Brodowski }
239513a2d70eSDominik Brodowski 
239613a2d70eSDominik Brodowski /*
23971da177e4SLinus Torvalds  *	Shutdown a socket.
23981da177e4SLinus Torvalds  */
23991da177e4SLinus Torvalds 
__sys_shutdown_sock(struct socket * sock,int how)24001da177e4SLinus Torvalds int __sys_shutdown_sock(struct socket *sock, int how)
2401b713c195SJens Axboe {
2402b713c195SJens Axboe 	int err;
2403b713c195SJens Axboe 
2404b713c195SJens Axboe 	err = security_socket_shutdown(sock, how);
2405b713c195SJens Axboe 	if (!err)
2406b713c195SJens Axboe 		err = READ_ONCE(sock->ops)->shutdown(sock, how);
24071ded5e5aSEric Dumazet 
2408b713c195SJens Axboe 	return err;
2409b713c195SJens Axboe }
2410b713c195SJens Axboe 
__sys_shutdown(int fd,int how)2411b713c195SJens Axboe int __sys_shutdown(int fd, int how)
2412005a1aeaSDominik Brodowski {
24131da177e4SLinus Torvalds 	struct socket *sock;
24141da177e4SLinus Torvalds 	CLASS(fd, f)(fd);
241553c0a58bSAl Viro 
24161da177e4SLinus Torvalds 	if (fd_empty(f))
241753c0a58bSAl Viro 		return -EBADF;
241853c0a58bSAl Viro 	sock = sock_from_file(fd_file(f));
241953c0a58bSAl Viro 	if (unlikely(!sock))
242053c0a58bSAl Viro 		return -ENOTSOCK;
242153c0a58bSAl Viro 
242253c0a58bSAl Viro 	return __sys_shutdown_sock(sock, how);
242353c0a58bSAl Viro }
24241da177e4SLinus Torvalds 
SYSCALL_DEFINE2(shutdown,int,fd,int,how)24251da177e4SLinus Torvalds SYSCALL_DEFINE2(shutdown, int, fd, int, how)
2426005a1aeaSDominik Brodowski {
2427005a1aeaSDominik Brodowski 	return __sys_shutdown(fd, how);
2428005a1aeaSDominik Brodowski }
2429005a1aeaSDominik Brodowski 
2430005a1aeaSDominik Brodowski /* A couple of helpful macros for getting the address of the 32/64 bit
24311da177e4SLinus Torvalds  * fields which are the same type (int / unsigned) on our platforms.
24321da177e4SLinus Torvalds  */
24331da177e4SLinus Torvalds #define COMPAT_MSG(msg, member)	((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member)
24341da177e4SLinus Torvalds #define COMPAT_NAMELEN(msg)	COMPAT_MSG(msg, msg_namelen)
24351da177e4SLinus Torvalds #define COMPAT_FLAGS(msg)	COMPAT_MSG(msg, msg_flags)
24361da177e4SLinus Torvalds 
24371da177e4SLinus Torvalds struct used_address {
2438c71d8ebeSTetsuo Handa 	struct sockaddr_storage name;
2439c71d8ebeSTetsuo Handa 	unsigned int name_len;
2440c71d8ebeSTetsuo Handa };
2441c71d8ebeSTetsuo Handa 
__copy_msghdr(struct msghdr * kmsg,struct user_msghdr * msg,struct sockaddr __user ** save_addr)2442c71d8ebeSTetsuo Handa int __copy_msghdr(struct msghdr *kmsg,
24437fa875b8SDylan Yudaken 		  struct user_msghdr *msg,
24447fa875b8SDylan Yudaken 		  struct sockaddr __user **save_addr)
24457fa875b8SDylan Yudaken {
24461661bf36SDan Carpenter 	ssize_t err;
244708adb7daSAl Viro 
244808adb7daSAl Viro 	kmsg->msg_control_is_user = true;
24491f466e1fSChristoph Hellwig 	kmsg->msg_get_inq = 0;
24501228b34cSEric Dumazet 	kmsg->msg_control_user = msg->msg_control;
24517fa875b8SDylan Yudaken 	kmsg->msg_controllen = msg->msg_controllen;
24527fa875b8SDylan Yudaken 	kmsg->msg_flags = msg->msg_flags;
24537fa875b8SDylan Yudaken 
2454ffb07550SAl Viro 	kmsg->msg_namelen = msg->msg_namelen;
24557fa875b8SDylan Yudaken 	if (!msg->msg_name)
24567fa875b8SDylan Yudaken 		kmsg->msg_namelen = 0;
24576a2a2b3aSAni Sinha 
24586a2a2b3aSAni Sinha 	if (kmsg->msg_namelen < 0)
2459dbb490b9SMatthew Leach 		return -EINVAL;
2460dbb490b9SMatthew Leach 
2461dbb490b9SMatthew Leach 	if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
24621661bf36SDan Carpenter 		kmsg->msg_namelen = sizeof(struct sockaddr_storage);
2463db31c55aSDan Carpenter 
246408adb7daSAl Viro 	if (save_addr)
246508adb7daSAl Viro 		*save_addr = msg->msg_name;
24667fa875b8SDylan Yudaken 
246708adb7daSAl Viro 	if (msg->msg_name && kmsg->msg_namelen) {
24687fa875b8SDylan Yudaken 		if (!save_addr) {
246908adb7daSAl Viro 			err = move_addr_to_kernel(msg->msg_name,
24707fa875b8SDylan Yudaken 						  kmsg->msg_namelen,
2471864d9664SPaolo Abeni 						  kmsg->msg_name);
247208adb7daSAl Viro 			if (err < 0)
247308adb7daSAl Viro 				return err;
247408adb7daSAl Viro 		}
247508adb7daSAl Viro 	} else {
247608adb7daSAl Viro 		kmsg->msg_name = NULL;
247708adb7daSAl Viro 		kmsg->msg_namelen = 0;
247808adb7daSAl Viro 	}
247908adb7daSAl Viro 
248008adb7daSAl Viro 	if (msg->msg_iovlen > UIO_MAXIOV)
24817fa875b8SDylan Yudaken 		return -EMSGSIZE;
248208adb7daSAl Viro 
248308adb7daSAl Viro 	kmsg->msg_iocb = NULL;
24840345f931S[email protected] 	kmsg->msg_ubuf = NULL;
24857c701d92SPavel Begunkov 	return 0;
24860a384abfSJens Axboe }
24870a384abfSJens Axboe 
copy_msghdr_from_user(struct msghdr * kmsg,struct user_msghdr __user * umsg,struct sockaddr __user ** save_addr,struct iovec ** iov)24880a384abfSJens Axboe static int copy_msghdr_from_user(struct msghdr *kmsg,
24890a384abfSJens Axboe 				 struct user_msghdr __user *umsg,
24900a384abfSJens Axboe 				 struct sockaddr __user **save_addr,
24910a384abfSJens Axboe 				 struct iovec **iov)
24920a384abfSJens Axboe {
24930a384abfSJens Axboe 	struct user_msghdr msg;
24940a384abfSJens Axboe 	ssize_t err;
24950a384abfSJens Axboe 
24960a384abfSJens Axboe 	if (copy_from_user(&msg, umsg, sizeof(*umsg)))
24977fa875b8SDylan Yudaken 		return -EFAULT;
24987fa875b8SDylan Yudaken 
24997fa875b8SDylan Yudaken 	err = __copy_msghdr(kmsg, &msg, save_addr);
25007fa875b8SDylan Yudaken 	if (err)
25010a384abfSJens Axboe 		return err;
25020a384abfSJens Axboe 
25030345f931S[email protected] 	err = import_iovec(save_addr ? ITER_DEST : ITER_SOURCE,
2504de4eda9dSAl Viro 			    msg.msg_iov, msg.msg_iovlen,
2505ffb07550SAl Viro 			    UIO_FASTIOV, iov, &kmsg->msg_iter);
2506da184284SAl Viro 	return err < 0 ? err : 0;
250787e5e6daSJens Axboe }
25081661bf36SDan Carpenter 
____sys_sendmsg(struct socket * sock,struct msghdr * msg_sys,unsigned int flags,struct used_address * used_address,unsigned int allowed_msghdr_flags)25091661bf36SDan Carpenter static int ____sys_sendmsg(struct socket *sock, struct msghdr *msg_sys,
25104257c8caSJens Axboe 			   unsigned int flags, struct used_address *used_address,
25114257c8caSJens Axboe 			   unsigned int allowed_msghdr_flags)
251228a94d8fSTom Herbert {
25131da177e4SLinus Torvalds 	unsigned char ctl[sizeof(struct cmsghdr) + 20]
2514b9d717a7SAlex Williamson 				__aligned(sizeof(__kernel_size_t));
2515846cc123SAmit Kushwaha 	/* 20 is size of ipv6_pktinfo */
2516b9d717a7SAlex Williamson 	unsigned char *ctl_buf = ctl;
25171da177e4SLinus Torvalds 	int ctl_len;
2518d8725c86SAl Viro 	ssize_t err;
251908adb7daSAl Viro 
25201da177e4SLinus Torvalds 	err = -ENOBUFS;
25211da177e4SLinus Torvalds 
25221da177e4SLinus Torvalds 	if (msg_sys->msg_controllen > INT_MAX)
2523228e548eSAnton Blanchard 		goto out;
25244257c8caSJens Axboe 	flags |= (msg_sys->msg_flags & allowed_msghdr_flags);
252528a94d8fSTom Herbert 	ctl_len = msg_sys->msg_controllen;
2526228e548eSAnton Blanchard 	if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
25271da177e4SLinus Torvalds 		err =
252889bddce5SStephen Hemminger 		    cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl,
2529228e548eSAnton Blanchard 						     sizeof(ctl));
253089bddce5SStephen Hemminger 		if (err)
25311da177e4SLinus Torvalds 			goto out;
25324257c8caSJens Axboe 		ctl_buf = msg_sys->msg_control;
2533228e548eSAnton Blanchard 		ctl_len = msg_sys->msg_controllen;
2534228e548eSAnton Blanchard 	} else if (ctl_len) {
25351da177e4SLinus Torvalds 		BUILD_BUG_ON(sizeof(struct cmsghdr) !=
2536ac4340fcSDavid S. Miller 			     CMSG_ALIGN(sizeof(struct cmsghdr)));
2537ac4340fcSDavid S. Miller 		if (ctl_len > sizeof(ctl)) {
253889bddce5SStephen Hemminger 			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
25391da177e4SLinus Torvalds 			if (ctl_buf == NULL)
25401da177e4SLinus Torvalds 				goto out;
25414257c8caSJens Axboe 		}
25421da177e4SLinus Torvalds 		err = -EFAULT;
25431da177e4SLinus Torvalds 		if (copy_from_user(ctl_buf, msg_sys->msg_control_user, ctl_len))
25441f466e1fSChristoph Hellwig 			goto out_freectl;
25451da177e4SLinus Torvalds 		msg_sys->msg_control = ctl_buf;
2546228e548eSAnton Blanchard 		msg_sys->msg_control_is_user = false;
25471f466e1fSChristoph Hellwig 	}
25481da177e4SLinus Torvalds 	flags &= ~MSG_INTERNAL_SENDMSG_FLAGS;
2549b841b901SDavid Howells 	msg_sys->msg_flags = flags;
2550228e548eSAnton Blanchard 
25511da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
25521da177e4SLinus Torvalds 		msg_sys->msg_flags |= MSG_DONTWAIT;
2553228e548eSAnton Blanchard 	/*
2554c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and current destination address is same as
2555c71d8ebeSTetsuo Handa 	 * previously succeeded address, omit asking LSM's decision.
2556c71d8ebeSTetsuo Handa 	 * used_address->name_len is initialized to UINT_MAX so that the first
2557c71d8ebeSTetsuo Handa 	 * destination address never matches.
2558c71d8ebeSTetsuo Handa 	 */
2559c71d8ebeSTetsuo Handa 	if (used_address && msg_sys->msg_name &&
2560bc909d9dSMathieu Desnoyers 	    used_address->name_len == msg_sys->msg_namelen &&
2561bc909d9dSMathieu Desnoyers 	    !memcmp(&used_address->name, msg_sys->msg_name,
2562bc909d9dSMathieu Desnoyers 		    used_address->name_len)) {
2563c71d8ebeSTetsuo Handa 		err = sock_sendmsg_nosec(sock, msg_sys);
2564d8725c86SAl Viro 		goto out_freectl;
2565c71d8ebeSTetsuo Handa 	}
2566c71d8ebeSTetsuo Handa 	err = __sock_sendmsg(sock, msg_sys);
256786a7e0b6SJordan Rife 	/*
2568c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and sending to current destination address was
2569c71d8ebeSTetsuo Handa 	 * successful, remember it.
2570c71d8ebeSTetsuo Handa 	 */
2571c71d8ebeSTetsuo Handa 	if (used_address && err >= 0) {
2572c71d8ebeSTetsuo Handa 		used_address->name_len = msg_sys->msg_namelen;
2573c71d8ebeSTetsuo Handa 		if (msg_sys->msg_name)
2574bc909d9dSMathieu Desnoyers 			memcpy(&used_address->name, msg_sys->msg_name,
2575bc909d9dSMathieu Desnoyers 			       used_address->name_len);
2576c71d8ebeSTetsuo Handa 	}
2577c71d8ebeSTetsuo Handa 
25781da177e4SLinus Torvalds out_freectl:
25791da177e4SLinus Torvalds 	if (ctl_buf != ctl)
25801da177e4SLinus Torvalds 		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
25811da177e4SLinus Torvalds out:
25824257c8caSJens Axboe 	return err;
25834257c8caSJens Axboe }
25844257c8caSJens Axboe 
sendmsg_copy_msghdr(struct msghdr * msg,struct user_msghdr __user * umsg,unsigned flags,struct iovec ** iov)25854257c8caSJens Axboe static int sendmsg_copy_msghdr(struct msghdr *msg,
2586e54e09c0SJens Axboe 			       struct user_msghdr __user *umsg, unsigned flags,
25874257c8caSJens Axboe 			       struct iovec **iov)
25884257c8caSJens Axboe {
25894257c8caSJens Axboe 	int err;
25904257c8caSJens Axboe 
25914257c8caSJens Axboe 	if (flags & MSG_CMSG_COMPAT) {
25924257c8caSJens Axboe 		struct compat_msghdr __user *msg_compat;
25934257c8caSJens Axboe 
25944257c8caSJens Axboe 		msg_compat = (struct compat_msghdr __user *) umsg;
25954257c8caSJens Axboe 		err = get_compat_msghdr(msg, msg_compat, NULL, iov);
25964257c8caSJens Axboe 	} else {
25974257c8caSJens Axboe 		err = copy_msghdr_from_user(msg, umsg, NULL, iov);
25984257c8caSJens Axboe 	}
25994257c8caSJens Axboe 	if (err < 0)
26004257c8caSJens Axboe 		return err;
26014257c8caSJens Axboe 
26024257c8caSJens Axboe 	return 0;
26034257c8caSJens Axboe }
26044257c8caSJens Axboe 
___sys_sendmsg(struct socket * sock,struct user_msghdr __user * msg,struct msghdr * msg_sys,unsigned int flags,struct used_address * used_address,unsigned int allowed_msghdr_flags)26054257c8caSJens Axboe static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
26064257c8caSJens Axboe 			 struct msghdr *msg_sys, unsigned int flags,
26074257c8caSJens Axboe 			 struct used_address *used_address,
26084257c8caSJens Axboe 			 unsigned int allowed_msghdr_flags)
26094257c8caSJens Axboe {
26104257c8caSJens Axboe 	struct sockaddr_storage address;
26114257c8caSJens Axboe 	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
26124257c8caSJens Axboe 	ssize_t err;
26134257c8caSJens Axboe 
26144257c8caSJens Axboe 	msg_sys->msg_name = &address;
26154257c8caSJens Axboe 
26164257c8caSJens Axboe 	err = sendmsg_copy_msghdr(msg_sys, msg, flags, &iov);
26174257c8caSJens Axboe 	if (err < 0)
26184257c8caSJens Axboe 		return err;
26194257c8caSJens Axboe 
26204257c8caSJens Axboe 	err = ____sys_sendmsg(sock, msg_sys, flags, used_address,
26214257c8caSJens Axboe 				allowed_msghdr_flags);
26224257c8caSJens Axboe 	kfree(iov);
2623a74e9106SEric Dumazet 	return err;
2624228e548eSAnton Blanchard }
2625228e548eSAnton Blanchard 
2626228e548eSAnton Blanchard /*
2627228e548eSAnton Blanchard  *	BSD sendmsg interface
2628228e548eSAnton Blanchard  */
__sys_sendmsg_sock(struct socket * sock,struct msghdr * msg,unsigned int flags)2629228e548eSAnton Blanchard long __sys_sendmsg_sock(struct socket *sock, struct msghdr *msg,
263003b1230cSJens Axboe 			unsigned int flags)
26310fa03c62SJens Axboe {
26320fa03c62SJens Axboe 	return ____sys_sendmsg(sock, msg, flags, NULL, 0);
263303b1230cSJens Axboe }
26340fa03c62SJens Axboe 
__sys_sendmsg(int fd,struct user_msghdr __user * msg,unsigned int flags,bool forbid_cmsg_compat)2635228e548eSAnton Blanchard long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned int flags,
2636e1834a32SDominik Brodowski 		   bool forbid_cmsg_compat)
2637e1834a32SDominik Brodowski {
2638228e548eSAnton Blanchard 	struct msghdr msg_sys;
2639228e548eSAnton Blanchard 	struct socket *sock;
26401be374a0SAndy Lutomirski 
2641228e548eSAnton Blanchard 	if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT))
2642e1834a32SDominik Brodowski 		return -EINVAL;
2643e1834a32SDominik Brodowski 
2644e1834a32SDominik Brodowski 	CLASS(fd, f)(fd);
264553c0a58bSAl Viro 
2646228e548eSAnton Blanchard 	if (fd_empty(f))
264753c0a58bSAl Viro 		return -EBADF;
264853c0a58bSAl Viro 	sock = sock_from_file(fd_file(f));
264953c0a58bSAl Viro 	if (unlikely(!sock))
265053c0a58bSAl Viro 		return -ENOTSOCK;
265153c0a58bSAl Viro 
2652228e548eSAnton Blanchard 	return ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL, 0);
265353c0a58bSAl Viro }
26541da177e4SLinus Torvalds 
SYSCALL_DEFINE3(sendmsg,int,fd,struct user_msghdr __user *,msg,unsigned int,flags)26551da177e4SLinus Torvalds SYSCALL_DEFINE3(sendmsg, int, fd, struct user_msghdr __user *, msg, unsigned int, flags)
2656666547ffSAl Viro {
2657a7526eb5SAndy Lutomirski 	return __sys_sendmsg(fd, msg, flags, true);
2658e1834a32SDominik Brodowski }
2659a7526eb5SAndy Lutomirski 
2660a7526eb5SAndy Lutomirski /*
2661228e548eSAnton Blanchard  *	Linux sendmmsg interface
2662228e548eSAnton Blanchard  */
2663228e548eSAnton Blanchard 
__sys_sendmmsg(int fd,struct mmsghdr __user * mmsg,unsigned int vlen,unsigned int flags,bool forbid_cmsg_compat)2664228e548eSAnton Blanchard int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2665228e548eSAnton Blanchard 		   unsigned int flags, bool forbid_cmsg_compat)
2666e1834a32SDominik Brodowski {
2667228e548eSAnton Blanchard 	int err, datagrams;
266853c0a58bSAl Viro 	struct socket *sock;
2669228e548eSAnton Blanchard 	struct mmsghdr __user *entry;
2670228e548eSAnton Blanchard 	struct compat_mmsghdr __user *compat_entry;
2671228e548eSAnton Blanchard 	struct msghdr msg_sys;
2672228e548eSAnton Blanchard 	struct used_address used_address;
2673c71d8ebeSTetsuo Handa 	unsigned int oflags = flags;
2674f092276dSTom Herbert 
2675228e548eSAnton Blanchard 	if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT))
2676e1834a32SDominik Brodowski 		return -EINVAL;
2677e1834a32SDominik Brodowski 
2678e1834a32SDominik Brodowski 	if (vlen > UIO_MAXIOV)
267998382f41SAnton Blanchard 		vlen = UIO_MAXIOV;
268098382f41SAnton Blanchard 
2681228e548eSAnton Blanchard 	datagrams = 0;
2682228e548eSAnton Blanchard 
2683228e548eSAnton Blanchard 	CLASS(fd, f)(fd);
268453c0a58bSAl Viro 
268553c0a58bSAl Viro 	if (fd_empty(f))
268653c0a58bSAl Viro 		return -EBADF;
268753c0a58bSAl Viro 	sock = sock_from_file(fd_file(f));
268853c0a58bSAl Viro 	if (unlikely(!sock))
268953c0a58bSAl Viro 		return -ENOTSOCK;
269053c0a58bSAl Viro 
2691228e548eSAnton Blanchard 	used_address.name_len = UINT_MAX;
2692c71d8ebeSTetsuo Handa 	entry = mmsg;
2693228e548eSAnton Blanchard 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2694228e548eSAnton Blanchard 	err = 0;
2695728ffb86SAnton Blanchard 	flags |= MSG_BATCH;
2696f092276dSTom Herbert 
2697228e548eSAnton Blanchard 	while (datagrams < vlen) {
2698228e548eSAnton Blanchard 		if (datagrams == vlen - 1)
2699f092276dSTom Herbert 			flags = oflags;
2700f092276dSTom Herbert 
2701f092276dSTom Herbert 		if (MSG_CMSG_COMPAT & flags) {
2702228e548eSAnton Blanchard 			err = ___sys_sendmsg(sock, (struct user_msghdr __user *)compat_entry,
2703666547ffSAl Viro 					     &msg_sys, flags, &used_address, MSG_EOR);
270428a94d8fSTom Herbert 			if (err < 0)
2705228e548eSAnton Blanchard 				break;
2706228e548eSAnton Blanchard 			err = __put_user(err, &compat_entry->msg_len);
2707228e548eSAnton Blanchard 			++compat_entry;
2708228e548eSAnton Blanchard 		} else {
2709228e548eSAnton Blanchard 			err = ___sys_sendmsg(sock,
2710a7526eb5SAndy Lutomirski 					     (struct user_msghdr __user *)entry,
2711666547ffSAl Viro 					     &msg_sys, flags, &used_address, MSG_EOR);
271228a94d8fSTom Herbert 			if (err < 0)
2713228e548eSAnton Blanchard 				break;
2714228e548eSAnton Blanchard 			err = put_user(err, &entry->msg_len);
2715228e548eSAnton Blanchard 			++entry;
2716228e548eSAnton Blanchard 		}
2717228e548eSAnton Blanchard 
2718228e548eSAnton Blanchard 		if (err)
2719228e548eSAnton Blanchard 			break;
2720228e548eSAnton Blanchard 		++datagrams;
2721228e548eSAnton Blanchard 		if (msg_data_left(&msg_sys))
27223023898bSSoheil Hassas Yeganeh 			break;
27233023898bSSoheil Hassas Yeganeh 		cond_resched();
2724a78cb84cSEric Dumazet 	}
2725228e548eSAnton Blanchard 
2726228e548eSAnton Blanchard 	/* We only return an error if no datagrams were able to be sent */
2727728ffb86SAnton Blanchard 	if (datagrams != 0)
2728728ffb86SAnton Blanchard 		return datagrams;
2729228e548eSAnton Blanchard 
2730228e548eSAnton Blanchard 	return err;
2731228e548eSAnton Blanchard }
2732228e548eSAnton Blanchard 
SYSCALL_DEFINE4(sendmmsg,int,fd,struct mmsghdr __user *,mmsg,unsigned int,vlen,unsigned int,flags)2733228e548eSAnton Blanchard SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
2734228e548eSAnton Blanchard 		unsigned int, vlen, unsigned int, flags)
2735228e548eSAnton Blanchard {
2736228e548eSAnton Blanchard 	return __sys_sendmmsg(fd, mmsg, vlen, flags, true);
2737e1834a32SDominik Brodowski }
2738228e548eSAnton Blanchard 
recvmsg_copy_msghdr(struct msghdr * msg,struct user_msghdr __user * umsg,unsigned flags,struct sockaddr __user ** uaddr,struct iovec ** iov)2739228e548eSAnton Blanchard static int recvmsg_copy_msghdr(struct msghdr *msg,
2740e54e09c0SJens Axboe 			       struct user_msghdr __user *umsg, unsigned flags,
27414257c8caSJens Axboe 			       struct sockaddr __user **uaddr,
27424257c8caSJens Axboe 			       struct iovec **iov)
27434257c8caSJens Axboe {
27444257c8caSJens Axboe 	ssize_t err;
27454257c8caSJens Axboe 
27464257c8caSJens Axboe 	if (MSG_CMSG_COMPAT & flags) {
27474257c8caSJens Axboe 		struct compat_msghdr __user *msg_compat;
27484257c8caSJens Axboe 
27494257c8caSJens Axboe 		msg_compat = (struct compat_msghdr __user *) umsg;
27504257c8caSJens Axboe 		err = get_compat_msghdr(msg, msg_compat, uaddr, iov);
27514257c8caSJens Axboe 	} else {
27524257c8caSJens Axboe 		err = copy_msghdr_from_user(msg, umsg, uaddr, iov);
27534257c8caSJens Axboe 	}
27544257c8caSJens Axboe 	if (err < 0)
27554257c8caSJens Axboe 		return err;
27564257c8caSJens Axboe 
27574257c8caSJens Axboe 	return 0;
27584257c8caSJens Axboe }
27594257c8caSJens Axboe 
____sys_recvmsg(struct socket * sock,struct msghdr * msg_sys,struct user_msghdr __user * msg,struct sockaddr __user * uaddr,unsigned int flags,int nosec)27604257c8caSJens Axboe static int ____sys_recvmsg(struct socket *sock, struct msghdr *msg_sys,
27614257c8caSJens Axboe 			   struct user_msghdr __user *msg,
27624257c8caSJens Axboe 			   struct sockaddr __user *uaddr,
27634257c8caSJens Axboe 			   unsigned int flags, int nosec)
27644257c8caSJens Axboe {
27651da177e4SLinus Torvalds 	struct compat_msghdr __user *msg_compat =
276689bddce5SStephen Hemminger 					(struct compat_msghdr __user *) msg;
276789bddce5SStephen Hemminger 	int __user *uaddr_len = COMPAT_NAMELEN(msg);
27684257c8caSJens Axboe 	struct sockaddr_storage addr;
27694257c8caSJens Axboe 	unsigned long cmsg_ptr;
27701da177e4SLinus Torvalds 	int len;
27712da62906SAl Viro 	ssize_t err;
277208adb7daSAl Viro 
27731da177e4SLinus Torvalds 	msg_sys->msg_name = &addr;
277408adb7daSAl Viro 	cmsg_ptr = (unsigned long)msg_sys->msg_control;
2775a2e27255SArnaldo Carvalho de Melo 	msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
2776a2e27255SArnaldo Carvalho de Melo 
27771da177e4SLinus Torvalds 	/* We assume all kernel code knows the size of sockaddr_storage */
2778f3d33426SHannes Frederic Sowa 	msg_sys->msg_namelen = 0;
2779f3d33426SHannes Frederic Sowa 
2780f3d33426SHannes Frederic Sowa 	if (sock->file->f_flags & O_NONBLOCK)
27811da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
27821da177e4SLinus Torvalds 
27831af66221SEric Dumazet 	if (unlikely(nosec))
27841af66221SEric Dumazet 		err = sock_recvmsg_nosec(sock, msg_sys, flags);
27851af66221SEric Dumazet 	else
27861af66221SEric Dumazet 		err = sock_recvmsg(sock, msg_sys, flags);
27871af66221SEric Dumazet 
27881af66221SEric Dumazet 	if (err < 0)
27891da177e4SLinus Torvalds 		goto out;
27904257c8caSJens Axboe 	len = err;
27911da177e4SLinus Torvalds 
27921da177e4SLinus Torvalds 	if (uaddr != NULL) {
27931da177e4SLinus Torvalds 		err = move_addr_to_user(&addr,
279443db362dSMaciej Żenczykowski 					msg_sys->msg_namelen, uaddr,
2795a2e27255SArnaldo Carvalho de Melo 					uaddr_len);
279689bddce5SStephen Hemminger 		if (err < 0)
27971da177e4SLinus Torvalds 			goto out;
27984257c8caSJens Axboe 	}
27991da177e4SLinus Torvalds 	err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
2800a2e27255SArnaldo Carvalho de Melo 			 COMPAT_FLAGS(msg));
280137f7f421SDavid S. Miller 	if (err)
28021da177e4SLinus Torvalds 		goto out;
28034257c8caSJens Axboe 	if (MSG_CMSG_COMPAT & flags)
28041da177e4SLinus Torvalds 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
2805a2e27255SArnaldo Carvalho de Melo 				 &msg_compat->msg_controllen);
28061da177e4SLinus Torvalds 	else
28071da177e4SLinus Torvalds 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
2808a2e27255SArnaldo Carvalho de Melo 				 &msg->msg_controllen);
28091da177e4SLinus Torvalds 	if (err)
28101da177e4SLinus Torvalds 		goto out;
28114257c8caSJens Axboe 	err = len;
28121da177e4SLinus Torvalds out:
28134257c8caSJens Axboe 	return err;
28144257c8caSJens Axboe }
28154257c8caSJens Axboe 
___sys_recvmsg(struct socket * sock,struct user_msghdr __user * msg,struct msghdr * msg_sys,unsigned int flags,int nosec)28161da177e4SLinus Torvalds static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg,
28174257c8caSJens Axboe 			 struct msghdr *msg_sys, unsigned int flags, int nosec)
28184257c8caSJens Axboe {
28194257c8caSJens Axboe 	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
28204257c8caSJens Axboe 	/* user mode address pointers */
28214257c8caSJens Axboe 	struct sockaddr __user *uaddr;
28224257c8caSJens Axboe 	ssize_t err;
28234257c8caSJens Axboe 
28244257c8caSJens Axboe 	err = recvmsg_copy_msghdr(msg_sys, msg, flags, &uaddr, &iov);
28254257c8caSJens Axboe 	if (err < 0)
28264257c8caSJens Axboe 		return err;
28274257c8caSJens Axboe 
28284257c8caSJens Axboe 	err = ____sys_recvmsg(sock, msg_sys, msg, uaddr, flags, nosec);
28294257c8caSJens Axboe 	kfree(iov);
2830a74e9106SEric Dumazet 	return err;
2831a2e27255SArnaldo Carvalho de Melo }
2832a2e27255SArnaldo Carvalho de Melo 
2833a2e27255SArnaldo Carvalho de Melo /*
2834a2e27255SArnaldo Carvalho de Melo  *	BSD recvmsg interface
2835a2e27255SArnaldo Carvalho de Melo  */
2836a2e27255SArnaldo Carvalho de Melo 
__sys_recvmsg_sock(struct socket * sock,struct msghdr * msg,struct user_msghdr __user * umsg,struct sockaddr __user * uaddr,unsigned int flags)2837a2e27255SArnaldo Carvalho de Melo long __sys_recvmsg_sock(struct socket *sock, struct msghdr *msg,
283803b1230cSJens Axboe 			struct user_msghdr __user *umsg,
283903b1230cSJens Axboe 			struct sockaddr __user *uaddr, unsigned int flags)
284003b1230cSJens Axboe {
2841aa1fa28fSJens Axboe 	return ____sys_recvmsg(sock, msg, umsg, uaddr, flags, 0);
284203b1230cSJens Axboe }
2843aa1fa28fSJens Axboe 
__sys_recvmsg(int fd,struct user_msghdr __user * msg,unsigned int flags,bool forbid_cmsg_compat)2844aa1fa28fSJens Axboe long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned int flags,
2845e1834a32SDominik Brodowski 		   bool forbid_cmsg_compat)
2846e1834a32SDominik Brodowski {
2847a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
2848a2e27255SArnaldo Carvalho de Melo 	struct socket *sock;
28491be374a0SAndy Lutomirski 
2850a2e27255SArnaldo Carvalho de Melo 	if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT))
2851e1834a32SDominik Brodowski 		return -EINVAL;
2852e1834a32SDominik Brodowski 
2853e1834a32SDominik Brodowski 	CLASS(fd, f)(fd);
285453c0a58bSAl Viro 
2855a2e27255SArnaldo Carvalho de Melo 	if (fd_empty(f))
285653c0a58bSAl Viro 		return -EBADF;
285753c0a58bSAl Viro 	sock = sock_from_file(fd_file(f));
285853c0a58bSAl Viro 	if (unlikely(!sock))
285953c0a58bSAl Viro 		return -ENOTSOCK;
286053c0a58bSAl Viro 
2861a2e27255SArnaldo Carvalho de Melo 	return ___sys_recvmsg(sock, msg, &msg_sys, flags, 0);
286253c0a58bSAl Viro }
28631da177e4SLinus Torvalds 
SYSCALL_DEFINE3(recvmsg,int,fd,struct user_msghdr __user *,msg,unsigned int,flags)28641da177e4SLinus Torvalds SYSCALL_DEFINE3(recvmsg, int, fd, struct user_msghdr __user *, msg,
2865666547ffSAl Viro 		unsigned int, flags)
2866a7526eb5SAndy Lutomirski {
2867a7526eb5SAndy Lutomirski 	return __sys_recvmsg(fd, msg, flags, true);
2868e1834a32SDominik Brodowski }
2869a7526eb5SAndy Lutomirski 
2870a7526eb5SAndy Lutomirski /*
2871a2e27255SArnaldo Carvalho de Melo  *     Linux recvmmsg interface
2872a2e27255SArnaldo Carvalho de Melo  */
2873a2e27255SArnaldo Carvalho de Melo 
do_recvmmsg(int fd,struct mmsghdr __user * mmsg,unsigned int vlen,unsigned int flags,struct timespec64 * timeout)28741da177e4SLinus Torvalds static int do_recvmmsg(int fd, struct mmsghdr __user *mmsg,
2875e11d4284SArnd Bergmann 			  unsigned int vlen, unsigned int flags,
2876e11d4284SArnd Bergmann 			  struct timespec64 *timeout)
2877e11d4284SArnd Bergmann {
2878a2e27255SArnaldo Carvalho de Melo 	int err = 0, datagrams;
287953c0a58bSAl Viro 	struct socket *sock;
2880a2e27255SArnaldo Carvalho de Melo 	struct mmsghdr __user *entry;
2881a2e27255SArnaldo Carvalho de Melo 	struct compat_mmsghdr __user *compat_entry;
2882d7256d0eSJean-Mickael Guerin 	struct msghdr msg_sys;
2883a2e27255SArnaldo Carvalho de Melo 	struct timespec64 end_time;
2884766b9f92SDeepa Dinamani 	struct timespec64 timeout64;
2885766b9f92SDeepa Dinamani 
2886a2e27255SArnaldo Carvalho de Melo 	if (timeout &&
2887a2e27255SArnaldo Carvalho de Melo 	    poll_select_set_timeout(&end_time, timeout->tv_sec,
2888a2e27255SArnaldo Carvalho de Melo 				    timeout->tv_nsec))
2889a2e27255SArnaldo Carvalho de Melo 		return -EINVAL;
2890a2e27255SArnaldo Carvalho de Melo 
2891a2e27255SArnaldo Carvalho de Melo 	datagrams = 0;
2892a2e27255SArnaldo Carvalho de Melo 
2893a2e27255SArnaldo Carvalho de Melo 	CLASS(fd, f)(fd);
289453c0a58bSAl Viro 
289553c0a58bSAl Viro 	if (fd_empty(f))
289653c0a58bSAl Viro 		return -EBADF;
289753c0a58bSAl Viro 	sock = sock_from_file(fd_file(f));
289853c0a58bSAl Viro 	if (unlikely(!sock))
289953c0a58bSAl Viro 		return -ENOTSOCK;
290053c0a58bSAl Viro 
2901a2e27255SArnaldo Carvalho de Melo 	if (likely(!(flags & MSG_ERRQUEUE))) {
29027797dc41SSoheil Hassas Yeganeh 		err = sock_error(sock->sk);
2903a2e27255SArnaldo Carvalho de Melo 		if (err)
290453c0a58bSAl Viro 			return err;
290553c0a58bSAl Viro 	}
29067797dc41SSoheil Hassas Yeganeh 
2907a2e27255SArnaldo Carvalho de Melo 	entry = mmsg;
2908a2e27255SArnaldo Carvalho de Melo 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2909d7256d0eSJean-Mickael Guerin 
2910a2e27255SArnaldo Carvalho de Melo 	while (datagrams < vlen) {
2911a2e27255SArnaldo Carvalho de Melo 		/*
2912a2e27255SArnaldo Carvalho de Melo 		 * No need to ask LSM for more than the first datagram.
2913a2e27255SArnaldo Carvalho de Melo 		 */
2914a2e27255SArnaldo Carvalho de Melo 		if (MSG_CMSG_COMPAT & flags) {
2915d7256d0eSJean-Mickael Guerin 			err = ___sys_recvmsg(sock, (struct user_msghdr __user *)compat_entry,
2916666547ffSAl Viro 					     &msg_sys, flags & ~MSG_WAITFORONE,
2917b9eb8b87SAnton Blanchard 					     datagrams);
2918b9eb8b87SAnton Blanchard 			if (err < 0)
2919d7256d0eSJean-Mickael Guerin 				break;
2920d7256d0eSJean-Mickael Guerin 			err = __put_user(err, &compat_entry->msg_len);
2921d7256d0eSJean-Mickael Guerin 			++compat_entry;
2922d7256d0eSJean-Mickael Guerin 		} else {
2923d7256d0eSJean-Mickael Guerin 			err = ___sys_recvmsg(sock,
2924a7526eb5SAndy Lutomirski 					     (struct user_msghdr __user *)entry,
2925666547ffSAl Viro 					     &msg_sys, flags & ~MSG_WAITFORONE,
2926b9eb8b87SAnton Blanchard 					     datagrams);
2927b9eb8b87SAnton Blanchard 			if (err < 0)
2928a2e27255SArnaldo Carvalho de Melo 				break;
2929a2e27255SArnaldo Carvalho de Melo 			err = put_user(err, &entry->msg_len);
2930a2e27255SArnaldo Carvalho de Melo 			++entry;
2931d7256d0eSJean-Mickael Guerin 		}
2932d7256d0eSJean-Mickael Guerin 
2933d7256d0eSJean-Mickael Guerin 		if (err)
2934a2e27255SArnaldo Carvalho de Melo 			break;
2935a2e27255SArnaldo Carvalho de Melo 		++datagrams;
2936a2e27255SArnaldo Carvalho de Melo 
2937a2e27255SArnaldo Carvalho de Melo 		/* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
293871c5c159SBrandon L Black 		if (flags & MSG_WAITFORONE)
293971c5c159SBrandon L Black 			flags |= MSG_DONTWAIT;
294071c5c159SBrandon L Black 
294171c5c159SBrandon L Black 		if (timeout) {
2942a2e27255SArnaldo Carvalho de Melo 			ktime_get_ts64(&timeout64);
2943766b9f92SDeepa Dinamani 			*timeout = timespec64_sub(end_time, timeout64);
2944c2e6c856SArnd Bergmann 			if (timeout->tv_sec < 0) {
2945a2e27255SArnaldo Carvalho de Melo 				timeout->tv_sec = timeout->tv_nsec = 0;
2946a2e27255SArnaldo Carvalho de Melo 				break;
2947a2e27255SArnaldo Carvalho de Melo 			}
2948a2e27255SArnaldo Carvalho de Melo 
2949a2e27255SArnaldo Carvalho de Melo 			/* Timeout, return less than vlen datagrams */
2950a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_nsec == 0 && timeout->tv_sec == 0)
2951a2e27255SArnaldo Carvalho de Melo 				break;
2952a2e27255SArnaldo Carvalho de Melo 		}
2953a2e27255SArnaldo Carvalho de Melo 
2954a2e27255SArnaldo Carvalho de Melo 		/* Out of band data, return right away */
2955a2e27255SArnaldo Carvalho de Melo 		if (msg_sys.msg_flags & MSG_OOB)
2956a2e27255SArnaldo Carvalho de Melo 			break;
2957a2e27255SArnaldo Carvalho de Melo 		cond_resched();
2958a78cb84cSEric Dumazet 	}
2959a2e27255SArnaldo Carvalho de Melo 
2960a2e27255SArnaldo Carvalho de Melo 	if (err == 0)
2961a2e27255SArnaldo Carvalho de Melo 		return datagrams;
296253c0a58bSAl Viro 
2963a2e27255SArnaldo Carvalho de Melo 	if (datagrams == 0)
296453c0a58bSAl Viro 		return err;
296553c0a58bSAl Viro 
296634b88a68SArnaldo Carvalho de Melo 	/*
2967a2e27255SArnaldo Carvalho de Melo 	 * We may return less entries than requested (vlen) if the
2968a2e27255SArnaldo Carvalho de Melo 	 * sock is non block and there aren't enough datagrams...
2969a2e27255SArnaldo Carvalho de Melo 	 */
2970a2e27255SArnaldo Carvalho de Melo 	if (err != -EAGAIN) {
2971a2e27255SArnaldo Carvalho de Melo 		/*
2972a2e27255SArnaldo Carvalho de Melo 		 * ... or  if recvmsg returns an error after we
2973a2e27255SArnaldo Carvalho de Melo 		 * received some datagrams, where we record the
2974a2e27255SArnaldo Carvalho de Melo 		 * error to return on the next call or if the
2975a2e27255SArnaldo Carvalho de Melo 		 * app asks about it using getsockopt(SO_ERROR).
2976a2e27255SArnaldo Carvalho de Melo 		 */
2977a2e27255SArnaldo Carvalho de Melo 		WRITE_ONCE(sock->sk->sk_err, -err);
2978e05a5f51SEric Dumazet 	}
2979a2e27255SArnaldo Carvalho de Melo 	return datagrams;
2980a2e27255SArnaldo Carvalho de Melo }
2981a2e27255SArnaldo Carvalho de Melo 
__sys_recvmmsg(int fd,struct mmsghdr __user * mmsg,unsigned int vlen,unsigned int flags,struct __kernel_timespec __user * timeout,struct old_timespec32 __user * timeout32)2982a2e27255SArnaldo Carvalho de Melo int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg,
2983e11d4284SArnd Bergmann 		   unsigned int vlen, unsigned int flags,
29841255e269SDominik Brodowski 		   struct __kernel_timespec __user *timeout,
2985e11d4284SArnd Bergmann 		   struct old_timespec32 __user *timeout32)
2986e11d4284SArnd Bergmann {
2987a2e27255SArnaldo Carvalho de Melo 	int datagrams;
2988a2e27255SArnaldo Carvalho de Melo 	struct timespec64 timeout_sys;
2989c2e6c856SArnd Bergmann 
2990a2e27255SArnaldo Carvalho de Melo 	if (timeout && get_timespec64(&timeout_sys, timeout))
2991e11d4284SArnd Bergmann 		return -EFAULT;
2992a2e27255SArnaldo Carvalho de Melo 
2993a2e27255SArnaldo Carvalho de Melo 	if (timeout32 && get_old_timespec32(&timeout_sys, timeout32))
2994e11d4284SArnd Bergmann 		return -EFAULT;
2995e11d4284SArnd Bergmann 
2996a2e27255SArnaldo Carvalho de Melo 	if (!timeout && !timeout32)
2997e11d4284SArnd Bergmann 		return do_recvmmsg(fd, mmsg, vlen, flags, NULL);
2998e11d4284SArnd Bergmann 
2999e11d4284SArnd Bergmann 	datagrams = do_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys);
3000e11d4284SArnd Bergmann 
3001e11d4284SArnd Bergmann 	if (datagrams <= 0)
3002e11d4284SArnd Bergmann 		return datagrams;
3003e11d4284SArnd Bergmann 
3004e11d4284SArnd Bergmann 	if (timeout && put_timespec64(&timeout_sys, timeout))
3005e11d4284SArnd Bergmann 		datagrams = -EFAULT;
3006e11d4284SArnd Bergmann 
3007e11d4284SArnd Bergmann 	if (timeout32 && put_old_timespec32(&timeout_sys, timeout32))
3008e11d4284SArnd Bergmann 		datagrams = -EFAULT;
3009a2e27255SArnaldo Carvalho de Melo 
3010a2e27255SArnaldo Carvalho de Melo 	return datagrams;
3011a2e27255SArnaldo Carvalho de Melo }
3012a2e27255SArnaldo Carvalho de Melo 
SYSCALL_DEFINE5(recvmmsg,int,fd,struct mmsghdr __user *,mmsg,unsigned int,vlen,unsigned int,flags,struct __kernel_timespec __user *,timeout)3013a2e27255SArnaldo Carvalho de Melo SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
30141255e269SDominik Brodowski 		unsigned int, vlen, unsigned int, flags,
30151255e269SDominik Brodowski 		struct __kernel_timespec __user *, timeout)
3016c2e6c856SArnd Bergmann {
30171255e269SDominik Brodowski 	if (flags & MSG_CMSG_COMPAT)
3018e11d4284SArnd Bergmann 		return -EINVAL;
3019e11d4284SArnd Bergmann 
3020e11d4284SArnd Bergmann 	return __sys_recvmmsg(fd, mmsg, vlen, flags, timeout, NULL);
3021e11d4284SArnd Bergmann }
30221255e269SDominik Brodowski 
30231255e269SDominik Brodowski #ifdef CONFIG_COMPAT_32BIT_TIME
SYSCALL_DEFINE5(recvmmsg_time32,int,fd,struct mmsghdr __user *,mmsg,unsigned int,vlen,unsigned int,flags,struct old_timespec32 __user *,timeout)3024e11d4284SArnd Bergmann SYSCALL_DEFINE5(recvmmsg_time32, int, fd, struct mmsghdr __user *, mmsg,
3025e11d4284SArnd Bergmann 		unsigned int, vlen, unsigned int, flags,
3026e11d4284SArnd Bergmann 		struct old_timespec32 __user *, timeout)
3027e11d4284SArnd Bergmann {
3028e11d4284SArnd Bergmann 	if (flags & MSG_CMSG_COMPAT)
3029e11d4284SArnd Bergmann 		return -EINVAL;
3030e11d4284SArnd Bergmann 
3031e11d4284SArnd Bergmann 	return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL, timeout);
3032e11d4284SArnd Bergmann }
3033e11d4284SArnd Bergmann #endif
3034e11d4284SArnd Bergmann 
3035e11d4284SArnd Bergmann #ifdef __ARCH_WANT_SYS_SOCKETCALL
3036a2e27255SArnaldo Carvalho de Melo /* Argument list sizes for sys_socketcall */
30371da177e4SLinus Torvalds #define AL(x) ((x) * sizeof(unsigned long))
30381da177e4SLinus Torvalds static const unsigned char nargs[21] = {
3039228e548eSAnton Blanchard 	AL(0), AL(3), AL(3), AL(3), AL(2), AL(3),
304089bddce5SStephen Hemminger 	AL(3), AL(3), AL(4), AL(4), AL(4), AL(6),
30411da177e4SLinus Torvalds 	AL(6), AL(2), AL(5), AL(5), AL(3), AL(3),
3042aaca0bdcSUlrich Drepper 	AL(4), AL(5), AL(4)
3043228e548eSAnton Blanchard };
304489bddce5SStephen Hemminger 
304589bddce5SStephen Hemminger #undef AL
30461da177e4SLinus Torvalds 
30471da177e4SLinus Torvalds /*
30481da177e4SLinus Torvalds  *	System call vectors.
30491da177e4SLinus Torvalds  *
30501da177e4SLinus Torvalds  *	Argument checking cleaned up. Saved 20% in size.
30511da177e4SLinus Torvalds  *  This function doesn't need to set the kernel lock because
30521da177e4SLinus Torvalds  *  it is set by the callees.
30531da177e4SLinus Torvalds  */
30541da177e4SLinus Torvalds 
SYSCALL_DEFINE2(socketcall,int,call,unsigned long __user *,args)30551da177e4SLinus Torvalds SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
30563e0fa65fSHeiko Carstens {
30571da177e4SLinus Torvalds 	unsigned long a[AUDITSC_ARGS];
30582950fa9dSChen Gang 	unsigned long a0, a1;
30591da177e4SLinus Torvalds 	int err;
30601da177e4SLinus Torvalds 	unsigned int len;
306147379052SArjan van de Ven 
30621da177e4SLinus Torvalds 	if (call < 1 || call > SYS_SENDMMSG)
3063228e548eSAnton Blanchard 		return -EINVAL;
30641da177e4SLinus Torvalds 	call = array_index_nospec(call, SYS_SENDMMSG + 1);
3065c8e8cd57SJeremy Cline 
30661da177e4SLinus Torvalds 	len = nargs[call];
306747379052SArjan van de Ven 	if (len > sizeof(a))
306847379052SArjan van de Ven 		return -EINVAL;
306947379052SArjan van de Ven 
307047379052SArjan van de Ven 	/* copy_from_user should be SMP safe. */
30711da177e4SLinus Torvalds 	if (copy_from_user(a, args, len))
307247379052SArjan van de Ven 		return -EFAULT;
30731da177e4SLinus Torvalds 
30741da177e4SLinus Torvalds 	err = audit_socketcall(nargs[call] / sizeof(unsigned long), a);
30752950fa9dSChen Gang 	if (err)
30762950fa9dSChen Gang 		return err;
30772950fa9dSChen Gang 
30783ec3b2fbSDavid Woodhouse 	a0 = a[0];
30791da177e4SLinus Torvalds 	a1 = a[1];
30801da177e4SLinus Torvalds 
30811da177e4SLinus Torvalds 	switch (call) {
308289bddce5SStephen Hemminger 	case SYS_SOCKET:
30831da177e4SLinus Torvalds 		err = __sys_socket(a0, a1, a[2]);
30849d6a15c3SDominik Brodowski 		break;
30851da177e4SLinus Torvalds 	case SYS_BIND:
30861da177e4SLinus Torvalds 		err = __sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
3087a87d35d8SDominik Brodowski 		break;
30881da177e4SLinus Torvalds 	case SYS_CONNECT:
30891da177e4SLinus Torvalds 		err = __sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
30901387c2c2SDominik Brodowski 		break;
30911da177e4SLinus Torvalds 	case SYS_LISTEN:
30921da177e4SLinus Torvalds 		err = __sys_listen(a0, a1);
309325e290eeSDominik Brodowski 		break;
30941da177e4SLinus Torvalds 	case SYS_ACCEPT:
30951da177e4SLinus Torvalds 		err = __sys_accept4(a0, (struct sockaddr __user *)a1,
30964541e805SDominik Brodowski 				    (int __user *)a[2], 0);
3097aaca0bdcSUlrich Drepper 		break;
30981da177e4SLinus Torvalds 	case SYS_GETSOCKNAME:
30991da177e4SLinus Torvalds 		err =
310089bddce5SStephen Hemminger 		    __sys_getsockname(a0, (struct sockaddr __user *)a1,
31018882a107SDominik Brodowski 				      (int __user *)a[2]);
310289bddce5SStephen Hemminger 		break;
31031da177e4SLinus Torvalds 	case SYS_GETPEERNAME:
31041da177e4SLinus Torvalds 		err =
310589bddce5SStephen Hemminger 		    __sys_getpeername(a0, (struct sockaddr __user *)a1,
3106b21c8f83SDominik Brodowski 				      (int __user *)a[2]);
310789bddce5SStephen Hemminger 		break;
31081da177e4SLinus Torvalds 	case SYS_SOCKETPAIR:
31091da177e4SLinus Torvalds 		err = __sys_socketpair(a0, a1, a[2], (int __user *)a[3]);
31106debc8d8SDominik Brodowski 		break;
31111da177e4SLinus Torvalds 	case SYS_SEND:
31121da177e4SLinus Torvalds 		err = __sys_sendto(a0, (void __user *)a1, a[2], a[3],
3113f3bf896bSDominik Brodowski 				   NULL, 0);
3114f3bf896bSDominik Brodowski 		break;
31151da177e4SLinus Torvalds 	case SYS_SENDTO:
31161da177e4SLinus Torvalds 		err = __sys_sendto(a0, (void __user *)a1, a[2], a[3],
3117211b634bSDominik Brodowski 				   (struct sockaddr __user *)a[4], a[5]);
31181da177e4SLinus Torvalds 		break;
31191da177e4SLinus Torvalds 	case SYS_RECV:
31201da177e4SLinus Torvalds 		err = __sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
3121d27e9afcSDominik Brodowski 				     NULL, NULL);
3122d27e9afcSDominik Brodowski 		break;
31231da177e4SLinus Torvalds 	case SYS_RECVFROM:
31241da177e4SLinus Torvalds 		err = __sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
31257a09e1ebSDominik Brodowski 				     (struct sockaddr __user *)a[4],
312689bddce5SStephen Hemminger 				     (int __user *)a[5]);
312789bddce5SStephen Hemminger 		break;
31281da177e4SLinus Torvalds 	case SYS_SHUTDOWN:
31291da177e4SLinus Torvalds 		err = __sys_shutdown(a0, a1);
3130005a1aeaSDominik Brodowski 		break;
31311da177e4SLinus Torvalds 	case SYS_SETSOCKOPT:
31321da177e4SLinus Torvalds 		err = __sys_setsockopt(a0, a1, a[2], (char __user *)a[3],
3133cc36dca0SDominik Brodowski 				       a[4]);
3134cc36dca0SDominik Brodowski 		break;
31351da177e4SLinus Torvalds 	case SYS_GETSOCKOPT:
31361da177e4SLinus Torvalds 		err =
313789bddce5SStephen Hemminger 		    __sys_getsockopt(a0, a1, a[2], (char __user *)a[3],
313813a2d70eSDominik Brodowski 				     (int __user *)a[4]);
313989bddce5SStephen Hemminger 		break;
31401da177e4SLinus Torvalds 	case SYS_SENDMSG:
31411da177e4SLinus Torvalds 		err = __sys_sendmsg(a0, (struct user_msghdr __user *)a1,
3142e1834a32SDominik Brodowski 				    a[2], true);
3143e1834a32SDominik Brodowski 		break;
31441da177e4SLinus Torvalds 	case SYS_SENDMMSG:
3145228e548eSAnton Blanchard 		err = __sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2],
3146e1834a32SDominik Brodowski 				     a[3], true);
3147e1834a32SDominik Brodowski 		break;
3148228e548eSAnton Blanchard 	case SYS_RECVMSG:
31491da177e4SLinus Torvalds 		err = __sys_recvmsg(a0, (struct user_msghdr __user *)a1,
3150e1834a32SDominik Brodowski 				    a[2], true);
3151e1834a32SDominik Brodowski 		break;
31521da177e4SLinus Torvalds 	case SYS_RECVMMSG:
3153a2e27255SArnaldo Carvalho de Melo 		if (IS_ENABLED(CONFIG_64BIT))
31543ca47e95SArnd Bergmann 			err = __sys_recvmmsg(a0, (struct mmsghdr __user *)a1,
3155e11d4284SArnd Bergmann 					     a[2], a[3],
3156e11d4284SArnd Bergmann 					     (struct __kernel_timespec __user *)a[4],
3157e11d4284SArnd Bergmann 					     NULL);
3158e11d4284SArnd Bergmann 		else
3159e11d4284SArnd Bergmann 			err = __sys_recvmmsg(a0, (struct mmsghdr __user *)a1,
3160e11d4284SArnd Bergmann 					     a[2], a[3], NULL,
3161e11d4284SArnd Bergmann 					     (struct old_timespec32 __user *)a[4]);
3162e11d4284SArnd Bergmann 		break;
3163a2e27255SArnaldo Carvalho de Melo 	case SYS_ACCEPT4:
3164de11defeSUlrich Drepper 		err = __sys_accept4(a0, (struct sockaddr __user *)a1,
31654541e805SDominik Brodowski 				    (int __user *)a[2], a[3]);
3166de11defeSUlrich Drepper 		break;
3167aaca0bdcSUlrich Drepper 	default:
31681da177e4SLinus Torvalds 		err = -EINVAL;
31691da177e4SLinus Torvalds 		break;
31701da177e4SLinus Torvalds 	}
31711da177e4SLinus Torvalds 	return err;
31721da177e4SLinus Torvalds }
31731da177e4SLinus Torvalds 
31741da177e4SLinus Torvalds #endif				/* __ARCH_WANT_SYS_SOCKETCALL */
31751da177e4SLinus Torvalds 
31761da177e4SLinus Torvalds /**
317755737fdaSStephen Hemminger  *	sock_register - add a socket protocol handler
317855737fdaSStephen Hemminger  *	@ops: description of protocol
317955737fdaSStephen Hemminger  *
318055737fdaSStephen Hemminger  *	This function is called by a protocol handler that wants to
31811da177e4SLinus Torvalds  *	advertise its address family, and have it linked into the
31821da177e4SLinus Torvalds  *	socket interface. The value ops->family corresponds to the
3183e793c0f7SMasanari Iida  *	socket system call protocol family.
318455737fdaSStephen Hemminger  */
sock_register(const struct net_proto_family * ops)31851da177e4SLinus Torvalds int sock_register(const struct net_proto_family *ops)
3186f0fd27d4SStephen Hemminger {
31871da177e4SLinus Torvalds 	int err;
31881da177e4SLinus Torvalds 
31891da177e4SLinus Torvalds 	if (ops->family >= NPROTO) {
31901da177e4SLinus Torvalds 		pr_crit("protocol %d >= NPROTO(%d)\n", ops->family, NPROTO);
31913410f22eSYang Yingliang 		return -ENOBUFS;
31921da177e4SLinus Torvalds 	}
31931da177e4SLinus Torvalds 
319455737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
319555737fdaSStephen Hemminger 	if (rcu_dereference_protected(net_families[ops->family],
3196190683a9SEric Dumazet 				      lockdep_is_held(&net_family_lock)))
3197190683a9SEric Dumazet 		err = -EEXIST;
31981da177e4SLinus Torvalds 	else {
319955737fdaSStephen Hemminger 		rcu_assign_pointer(net_families[ops->family], ops);
3200cf778b00SEric Dumazet 		err = 0;
32011da177e4SLinus Torvalds 	}
32021da177e4SLinus Torvalds 	spin_unlock(&net_family_lock);
320355737fdaSStephen Hemminger 
320455737fdaSStephen Hemminger 	pr_info("NET: Registered %s protocol family\n", pf_family_names[ops->family]);
3205fe0bdbdeSYejune Deng 	return err;
32061da177e4SLinus Torvalds }
32071da177e4SLinus Torvalds EXPORT_SYMBOL(sock_register);
3208c6d409cfSEric Dumazet 
32091da177e4SLinus Torvalds /**
321055737fdaSStephen Hemminger  *	sock_unregister - remove a protocol handler
321155737fdaSStephen Hemminger  *	@family: protocol family to remove
321255737fdaSStephen Hemminger  *
321355737fdaSStephen Hemminger  *	This function is called by a protocol handler that wants to
32141da177e4SLinus Torvalds  *	remove its address family, and have it unlinked from the
32151da177e4SLinus Torvalds  *	new socket creation.
321655737fdaSStephen Hemminger  *
321755737fdaSStephen Hemminger  *	If protocol handler is a module, then it can use module reference
321855737fdaSStephen Hemminger  *	counts to protect against new references. If protocol handler is not
321955737fdaSStephen Hemminger  *	a module then it needs to provide its own protection in
322055737fdaSStephen Hemminger  *	the ops->create routine.
322155737fdaSStephen Hemminger  */
sock_unregister(int family)32221da177e4SLinus Torvalds void sock_unregister(int family)
3223f0fd27d4SStephen Hemminger {
32241da177e4SLinus Torvalds 	BUG_ON(family < 0 || family >= NPROTO);
3225f0fd27d4SStephen Hemminger 
32261da177e4SLinus Torvalds 	spin_lock(&net_family_lock);
322755737fdaSStephen Hemminger 	RCU_INIT_POINTER(net_families[family], NULL);
3228a9b3cd7fSStephen Hemminger 	spin_unlock(&net_family_lock);
322955737fdaSStephen Hemminger 
323055737fdaSStephen Hemminger 	synchronize_rcu();
323155737fdaSStephen Hemminger 
323255737fdaSStephen Hemminger 	pr_info("NET: Unregistered %s protocol family\n", pf_family_names[family]);
3233fe0bdbdeSYejune Deng }
32341da177e4SLinus Torvalds EXPORT_SYMBOL(sock_unregister);
3235c6d409cfSEric Dumazet 
sock_is_registered(int family)32361da177e4SLinus Torvalds bool sock_is_registered(int family)
3237bf2ae2e4SXin Long {
3238bf2ae2e4SXin Long 	return family < NPROTO && rcu_access_pointer(net_families[family]);
323966b51b0aSJeremy Cline }
3240bf2ae2e4SXin Long 
sock_init(void)3241bf2ae2e4SXin Long static int __init sock_init(void)
324277d76ea3SAndi Kleen {
32431da177e4SLinus Torvalds 	int err;
3244b3e19d92SNick Piggin 	/*
32452ca794e5SEric W. Biederman 	 *      Initialize the network sysctl infrastructure.
32462ca794e5SEric W. Biederman 	 */
32472ca794e5SEric W. Biederman 	err = net_sysctl_init();
32482ca794e5SEric W. Biederman 	if (err)
32492ca794e5SEric W. Biederman 		goto out;
32502ca794e5SEric W. Biederman 
3251b3e19d92SNick Piggin 	/*
32521da177e4SLinus Torvalds 	 *      Initialize skbuff SLAB cache
32531da177e4SLinus Torvalds 	 */
32541da177e4SLinus Torvalds 	skb_init();
32551da177e4SLinus Torvalds 
32561da177e4SLinus Torvalds 	/*
32571da177e4SLinus Torvalds 	 *      Initialize the protocols module.
32581da177e4SLinus Torvalds 	 */
32591da177e4SLinus Torvalds 
32601da177e4SLinus Torvalds 	init_inodecache();
32611da177e4SLinus Torvalds 
3262b3e19d92SNick Piggin 	err = register_filesystem(&sock_fs_type);
3263b3e19d92SNick Piggin 	if (err)
3264b3e19d92SNick Piggin 		goto out;
326547260ba9SMiaohe Lin 	sock_mnt = kern_mount(&sock_fs_type);
32661da177e4SLinus Torvalds 	if (IS_ERR(sock_mnt)) {
3267b3e19d92SNick Piggin 		err = PTR_ERR(sock_mnt);
3268b3e19d92SNick Piggin 		goto out_mount;
3269b3e19d92SNick Piggin 	}
3270b3e19d92SNick Piggin 
327177d76ea3SAndi Kleen 	/* The real protocol initialization is performed in later initcalls.
327277d76ea3SAndi Kleen 	 */
32731da177e4SLinus Torvalds 
32741da177e4SLinus Torvalds #ifdef CONFIG_NETFILTER
32751da177e4SLinus Torvalds 	err = netfilter_init();
32766d11cfdbSPablo Neira Ayuso 	if (err)
32776d11cfdbSPablo Neira Ayuso 		goto out;
32786d11cfdbSPablo Neira Ayuso #endif
32791da177e4SLinus Torvalds 
3280cbeb321aSDavid S. Miller 	ptp_classifier_init();
3281408eccceSDaniel Borkmann 
3282c1f19b51SRichard Cochran out:
3283b3e19d92SNick Piggin 	return err;
3284b3e19d92SNick Piggin 
3285b3e19d92SNick Piggin out_mount:
3286b3e19d92SNick Piggin 	unregister_filesystem(&sock_fs_type);
3287b3e19d92SNick Piggin 	goto out;
3288b3e19d92SNick Piggin }
32891da177e4SLinus Torvalds 
32901da177e4SLinus Torvalds core_initcall(sock_init);	/* early initcall */
329177d76ea3SAndi Kleen 
329277d76ea3SAndi Kleen #ifdef CONFIG_PROC_FS
socket_seq_show(struct seq_file * seq)32931da177e4SLinus Torvalds void socket_seq_show(struct seq_file *seq)
32941da177e4SLinus Torvalds {
32951da177e4SLinus Torvalds 	seq_printf(seq, "sockets: used %d\n",
3296648845abSTonghao Zhang 		   sock_inuse_get(seq->private));
3297648845abSTonghao Zhang }
32981da177e4SLinus Torvalds #endif				/* CONFIG_PROC_FS */
32991da177e4SLinus Torvalds 
33001da177e4SLinus Torvalds /* Handle the fact that while struct ifreq has the same *layout* on
330129c49648SArnd Bergmann  * 32/64 for everything but ifreq::ifru_ifmap and ifreq::ifru_data,
330229c49648SArnd Bergmann  * which are handled elsewhere, it still has different *size* due to
330329c49648SArnd Bergmann  * ifreq::ifru_ifmap (which is 16 bytes on 32 bit, 24 bytes on 64-bit,
330429c49648SArnd Bergmann  * resulting in struct ifreq being 32 and 40 bytes respectively).
330529c49648SArnd Bergmann  * As a result, if the struct happens to be at the end of a page and
330629c49648SArnd Bergmann  * the next page isn't readable/writable, we get a fault. To prevent
330729c49648SArnd Bergmann  * that, copy back and forth to the full size.
330829c49648SArnd Bergmann  */
get_user_ifreq(struct ifreq * ifr,void __user ** ifrdata,void __user * arg)330929c49648SArnd Bergmann int get_user_ifreq(struct ifreq *ifr, void __user **ifrdata, void __user *arg)
331029c49648SArnd Bergmann {
331129c49648SArnd Bergmann 	if (in_compat_syscall()) {
331229c49648SArnd Bergmann 		struct compat_ifreq *ifr32 = (struct compat_ifreq *)ifr;
331329c49648SArnd Bergmann 
331429c49648SArnd Bergmann 		memset(ifr, 0, sizeof(*ifr));
331529c49648SArnd Bergmann 		if (copy_from_user(ifr32, arg, sizeof(*ifr32)))
331629c49648SArnd Bergmann 			return -EFAULT;
331729c49648SArnd Bergmann 
331829c49648SArnd Bergmann 		if (ifrdata)
331929c49648SArnd Bergmann 			*ifrdata = compat_ptr(ifr32->ifr_data);
332029c49648SArnd Bergmann 
332129c49648SArnd Bergmann 		return 0;
332229c49648SArnd Bergmann 	}
332329c49648SArnd Bergmann 
332429c49648SArnd Bergmann 	if (copy_from_user(ifr, arg, sizeof(*ifr)))
332529c49648SArnd Bergmann 		return -EFAULT;
332629c49648SArnd Bergmann 
332729c49648SArnd Bergmann 	if (ifrdata)
332829c49648SArnd Bergmann 		*ifrdata = ifr->ifr_data;
332929c49648SArnd Bergmann 
333029c49648SArnd Bergmann 	return 0;
333129c49648SArnd Bergmann }
333229c49648SArnd Bergmann EXPORT_SYMBOL(get_user_ifreq);
333329c49648SArnd Bergmann 
put_user_ifreq(struct ifreq * ifr,void __user * arg)333429c49648SArnd Bergmann int put_user_ifreq(struct ifreq *ifr, void __user *arg)
333529c49648SArnd Bergmann {
333629c49648SArnd Bergmann 	size_t size = sizeof(*ifr);
333729c49648SArnd Bergmann 
333829c49648SArnd Bergmann 	if (in_compat_syscall())
333929c49648SArnd Bergmann 		size = sizeof(struct compat_ifreq);
334029c49648SArnd Bergmann 
334129c49648SArnd Bergmann 	if (copy_to_user(arg, ifr, size))
334229c49648SArnd Bergmann 		return -EFAULT;
334329c49648SArnd Bergmann 
334429c49648SArnd Bergmann 	return 0;
334529c49648SArnd Bergmann }
334629c49648SArnd Bergmann EXPORT_SYMBOL(put_user_ifreq);
334729c49648SArnd Bergmann 
334829c49648SArnd Bergmann #ifdef CONFIG_COMPAT
compat_siocwandev(struct net * net,struct compat_ifreq __user * uifr32)334989bbfc95SShaun Pereira static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32)
33507a50a240SArnd Bergmann {
33517a50a240SArnd Bergmann 	compat_uptr_t uptr32;
33527a50a240SArnd Bergmann 	struct ifreq ifr;
335344c02a2cSAl Viro 	void __user *saved;
335444c02a2cSAl Viro 	int err;
335544c02a2cSAl Viro 
33567a50a240SArnd Bergmann 	if (get_user_ifreq(&ifr, NULL, uifr32))
335729c49648SArnd Bergmann 		return -EFAULT;
33587a50a240SArnd Bergmann 
33597a50a240SArnd Bergmann 	if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu))
33607a50a240SArnd Bergmann 		return -EFAULT;
33617a50a240SArnd Bergmann 
33627a50a240SArnd Bergmann 	saved = ifr.ifr_settings.ifs_ifsu.raw_hdlc;
336344c02a2cSAl Viro 	ifr.ifr_settings.ifs_ifsu.raw_hdlc = compat_ptr(uptr32);
336444c02a2cSAl Viro 
33657a50a240SArnd Bergmann 	err = dev_ioctl(net, SIOCWANDEV, &ifr, NULL, NULL);
3366a554bf96SArnd Bergmann 	if (!err) {
336744c02a2cSAl Viro 		ifr.ifr_settings.ifs_ifsu.raw_hdlc = saved;
336844c02a2cSAl Viro 		if (put_user_ifreq(&ifr, uifr32))
336929c49648SArnd Bergmann 			err = -EFAULT;
337044c02a2cSAl Viro 	}
33717a50a240SArnd Bergmann 	return err;
33727a229387SArnd Bergmann }
33737a229387SArnd Bergmann 
33747a229387SArnd Bergmann /* Handle ioctls that use ifreq::ifr_data and just need struct ifreq converted */
compat_ifr_data_ioctl(struct net * net,unsigned int cmd,struct compat_ifreq __user * u_ifreq32)3375590d4693SBen Hutchings static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd,
3376590d4693SBen Hutchings 				 struct compat_ifreq __user *u_ifreq32)
33776b96018bSArnd Bergmann {
33787a229387SArnd Bergmann 	struct ifreq ifreq;
337944c02a2cSAl Viro 	void __user *data;
3380a554bf96SArnd Bergmann 
33817a229387SArnd Bergmann 	if (!is_socket_ioctl_cmd(cmd))
3382d0efb162SPeter Collingbourne 		return -ENOTTY;
3383d0efb162SPeter Collingbourne 	if (get_user_ifreq(&ifreq, &data, u_ifreq32))
3384a554bf96SArnd Bergmann 		return -EFAULT;
33857a229387SArnd Bergmann 	ifreq.ifr_data = data;
3386a554bf96SArnd Bergmann 
33877a229387SArnd Bergmann 	return dev_ioctl(net, cmd, &ifreq, data, NULL);
3388a554bf96SArnd Bergmann }
33897a229387SArnd Bergmann 
compat_sock_ioctl_trans(struct file * file,struct socket * sock,unsigned int cmd,unsigned long arg)33907a229387SArnd Bergmann static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
33916b96018bSArnd Bergmann 			 unsigned int cmd, unsigned long arg)
33926b96018bSArnd Bergmann {
33936b96018bSArnd Bergmann 	void __user *argp = compat_ptr(arg);
33946b96018bSArnd Bergmann 	struct sock *sk = sock->sk;
33956b96018bSArnd Bergmann 	struct net *net = sock_net(sk);
33966b96018bSArnd Bergmann 	const struct proto_ops *ops;
33971ded5e5aSEric Dumazet 
33987a229387SArnd Bergmann 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
33996b96018bSArnd Bergmann 		return sock_ioctl(file, cmd, (unsigned long)argp);
340088fc023fSArnd Bergmann 
34017a229387SArnd Bergmann 	switch (cmd) {
34026b96018bSArnd Bergmann 	case SIOCWANDEV:
34037a50a240SArnd Bergmann 		return compat_siocwandev(net, argp);
34047a50a240SArnd Bergmann 	case SIOCGSTAMP_OLD:
34050768e170SArnd Bergmann 	case SIOCGSTAMPNS_OLD:
34060768e170SArnd Bergmann 		ops = READ_ONCE(sock->ops);
34071ded5e5aSEric Dumazet 		if (!ops->gettstamp)
34081ded5e5aSEric Dumazet 			return -ENOIOCTLCMD;
3409c7cbdbf2SArnd Bergmann 		return ops->gettstamp(sock, argp, cmd == SIOCGSTAMP_OLD,
34101ded5e5aSEric Dumazet 				      !COMPAT_USE_64BIT_TIME);
3411c7cbdbf2SArnd Bergmann 
3412c7cbdbf2SArnd Bergmann 	case SIOCETHTOOL:
3413dd98d289SArnd Bergmann 	case SIOCBONDSLAVEINFOQUERY:
3414590d4693SBen Hutchings 	case SIOCBONDINFOQUERY:
3415590d4693SBen Hutchings 	case SIOCSHWTSTAMP:
3416a2116ed2SArnd Bergmann 	case SIOCGHWTSTAMP:
3417fd468c74SBen Hutchings 		return compat_ifr_data_ioctl(net, cmd, argp);
3418590d4693SBen Hutchings 
34197a229387SArnd Bergmann 	case FIOSETOWN:
34206b96018bSArnd Bergmann 	case SIOCSPGRP:
34216b96018bSArnd Bergmann 	case FIOGETOWN:
34226b96018bSArnd Bergmann 	case SIOCGPGRP:
34236b96018bSArnd Bergmann 	case SIOCBRADDBR:
34246b96018bSArnd Bergmann 	case SIOCBRDELBR:
34256b96018bSArnd Bergmann 	case SIOCBRADDIF:
34266b96018bSArnd Bergmann 	case SIOCBRDELIF:
34276b96018bSArnd Bergmann 	case SIOCGIFVLAN:
3428c62cce2cSAndrey Vagin 	case SIOCSIFVLAN:
34290768e170SArnd Bergmann 	case SIOCGSKNS:
34300768e170SArnd Bergmann 	case SIOCGSTAMP_NEW:
3431876f0bf9SArnd Bergmann 	case SIOCGSTAMPNS_NEW:
3432fd3a4590SRemi Pommarel 	case SIOCGIFCONF:
3433fd3a4590SRemi Pommarel 	case SIOCSIFBR:
34346b96018bSArnd Bergmann 	case SIOCGIFBR:
34356b96018bSArnd Bergmann 		return sock_ioctl(file, cmd, arg);
34366b96018bSArnd Bergmann 
34376b96018bSArnd Bergmann 	case SIOCGIFFLAGS:
3438709566d7SArnd Bergmann 	case SIOCSIFFLAGS:
3439709566d7SArnd Bergmann 	case SIOCGIFMAP:
34406b96018bSArnd Bergmann 	case SIOCSIFMAP:
34416b96018bSArnd Bergmann 	case SIOCGIFMETRIC:
34426b96018bSArnd Bergmann 	case SIOCSIFMETRIC:
34436b96018bSArnd Bergmann 	case SIOCGIFMTU:
34446b96018bSArnd Bergmann 	case SIOCSIFMTU:
34456b96018bSArnd Bergmann 	case SIOCGIFMEM:
34466b96018bSArnd Bergmann 	case SIOCSIFMEM:
34476b96018bSArnd Bergmann 	case SIOCGIFHWADDR:
34486b96018bSArnd Bergmann 	case SIOCSIFHWADDR:
34496b96018bSArnd Bergmann 	case SIOCADDMULTI:
34506b96018bSArnd Bergmann 	case SIOCDELMULTI:
34516b96018bSArnd Bergmann 	case SIOCGIFINDEX:
34526b96018bSArnd Bergmann 	case SIOCGIFADDR:
34536b96018bSArnd Bergmann 	case SIOCSIFADDR:
34546b96018bSArnd Bergmann 	case SIOCSIFHWBROADCAST:
34556b96018bSArnd Bergmann 	case SIOCDIFADDR:
34566b96018bSArnd Bergmann 	case SIOCGIFBRDADDR:
34576b96018bSArnd Bergmann 	case SIOCSIFBRDADDR:
34586b96018bSArnd Bergmann 	case SIOCGIFDSTADDR:
34596b96018bSArnd Bergmann 	case SIOCSIFDSTADDR:
34606b96018bSArnd Bergmann 	case SIOCGIFNETMASK:
34616b96018bSArnd Bergmann 	case SIOCSIFNETMASK:
34626b96018bSArnd Bergmann 	case SIOCSIFPFLAGS:
34636b96018bSArnd Bergmann 	case SIOCGIFPFLAGS:
34646b96018bSArnd Bergmann 	case SIOCGIFTXQLEN:
34656b96018bSArnd Bergmann 	case SIOCSIFTXQLEN:
34666b96018bSArnd Bergmann 	case SIOCGIFNAME:
3467c6c9fee3SJohannes Berg 	case SIOCSIFNAME:
34689177efd3SArnd Bergmann 	case SIOCGMIIPHY:
34699177efd3SArnd Bergmann 	case SIOCGMIIREG:
34709177efd3SArnd Bergmann 	case SIOCSMIIREG:
34719177efd3SArnd Bergmann 	case SIOCBONDENSLAVE:
3472f92d4fc9SAl Viro 	case SIOCBONDRELEASE:
3473f92d4fc9SAl Viro 	case SIOCBONDSETHWADDR:
3474f92d4fc9SAl Viro 	case SIOCBONDCHANGEACTIVE:
3475f92d4fc9SAl Viro 	case SIOCSARP:
34766b96018bSArnd Bergmann 	case SIOCGARP:
34776b96018bSArnd Bergmann 	case SIOCDARP:
34786b96018bSArnd Bergmann 	case SIOCOUTQ:
3479c7dc504eSArnd Bergmann 	case SIOCOUTQNSD:
34809d7bf41fSArnd Bergmann 	case SIOCATMARK:
34816b96018bSArnd Bergmann 		return sock_do_ioctl(net, sock, cmd, arg);
348263ff03abSJohannes Berg 	}
34839177efd3SArnd Bergmann 
34849177efd3SArnd Bergmann 	return -ENOIOCTLCMD;
34856b96018bSArnd Bergmann }
34866b96018bSArnd Bergmann 
compat_sock_ioctl(struct file * file,unsigned int cmd,unsigned long arg)34877a229387SArnd Bergmann static long compat_sock_ioctl(struct file *file, unsigned int cmd,
348895c96174SEric Dumazet 			      unsigned long arg)
348989bbfc95SShaun Pereira {
349089bbfc95SShaun Pereira 	struct socket *sock = file->private_data;
349189bbfc95SShaun Pereira 	const struct proto_ops *ops = READ_ONCE(sock->ops);
34921ded5e5aSEric Dumazet 	int ret = -ENOIOCTLCMD;
349389bbfc95SShaun Pereira 	struct sock *sk;
349487de87d5SDavid S. Miller 	struct net *net;
349587de87d5SDavid S. Miller 
349687de87d5SDavid S. Miller 	sk = sock->sk;
349787de87d5SDavid S. Miller 	net = sock_net(sk);
349887de87d5SDavid S. Miller 
349989bbfc95SShaun Pereira 	if (ops->compat_ioctl)
35001ded5e5aSEric Dumazet 		ret = ops->compat_ioctl(sock, cmd, arg);
35011ded5e5aSEric Dumazet 
350289bbfc95SShaun Pereira 	if (ret == -ENOIOCTLCMD &&
350387de87d5SDavid S. Miller 	    (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST))
350487de87d5SDavid S. Miller 		ret = compat_wext_handle_ioctl(net, cmd, arg);
350587de87d5SDavid S. Miller 
350687de87d5SDavid S. Miller 	if (ret == -ENOIOCTLCMD)
35076b96018bSArnd Bergmann 		ret = compat_sock_ioctl_trans(file, sock, cmd, arg);
35086b96018bSArnd Bergmann 
35096b96018bSArnd Bergmann 	return ret;
351089bbfc95SShaun Pereira }
351189bbfc95SShaun Pereira #endif
351289bbfc95SShaun Pereira 
351389bbfc95SShaun Pereira /**
35148a3c245cSPedro Tammela  *	kernel_bind - bind an address to a socket (kernel space)
35158a3c245cSPedro Tammela  *	@sock: socket
35168a3c245cSPedro Tammela  *	@addr: address
35178a3c245cSPedro Tammela  *	@addrlen: length of address
35188a3c245cSPedro Tammela  *
35198a3c245cSPedro Tammela  *	Returns 0 or an error.
35208a3c245cSPedro Tammela  */
35218a3c245cSPedro Tammela 
kernel_bind(struct socket * sock,struct sockaddr * addr,int addrlen)35228a3c245cSPedro Tammela int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
3523ac5a488eSSridhar Samudrala {
3524ac5a488eSSridhar Samudrala 	struct sockaddr_storage address;
3525c889a99aSJordan Rife 
3526c889a99aSJordan Rife 	memcpy(&address, addr, addrlen);
3527c889a99aSJordan Rife 
3528c889a99aSJordan Rife 	return READ_ONCE(sock->ops)->bind(sock, (struct sockaddr *)&address,
3529c889a99aSJordan Rife 					  addrlen);
3530c889a99aSJordan Rife }
3531ac5a488eSSridhar Samudrala EXPORT_SYMBOL(kernel_bind);
3532c6d409cfSEric Dumazet 
3533ac5a488eSSridhar Samudrala /**
35348a3c245cSPedro Tammela  *	kernel_listen - move socket to listening state (kernel space)
35358a3c245cSPedro Tammela  *	@sock: socket
35368a3c245cSPedro Tammela  *	@backlog: pending connections queue size
35378a3c245cSPedro Tammela  *
35388a3c245cSPedro Tammela  *	Returns 0 or an error.
35398a3c245cSPedro Tammela  */
35408a3c245cSPedro Tammela 
kernel_listen(struct socket * sock,int backlog)35418a3c245cSPedro Tammela int kernel_listen(struct socket *sock, int backlog)
3542ac5a488eSSridhar Samudrala {
3543ac5a488eSSridhar Samudrala 	return READ_ONCE(sock->ops)->listen(sock, backlog);
35441ded5e5aSEric Dumazet }
3545ac5a488eSSridhar Samudrala EXPORT_SYMBOL(kernel_listen);
3546c6d409cfSEric Dumazet 
3547ac5a488eSSridhar Samudrala /**
35488a3c245cSPedro Tammela  *	kernel_accept - accept a connection (kernel space)
35498a3c245cSPedro Tammela  *	@sock: listening socket
35508a3c245cSPedro Tammela  *	@newsock: new connected socket
35518a3c245cSPedro Tammela  *	@flags: flags
35528a3c245cSPedro Tammela  *
35538a3c245cSPedro Tammela  *	@flags must be SOCK_CLOEXEC, SOCK_NONBLOCK or 0.
35548a3c245cSPedro Tammela  *	If it fails, @newsock is guaranteed to be %NULL.
35558a3c245cSPedro Tammela  *	Returns 0 or an error.
35568a3c245cSPedro Tammela  */
35578a3c245cSPedro Tammela 
kernel_accept(struct socket * sock,struct socket ** newsock,int flags)35588a3c245cSPedro Tammela int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
3559ac5a488eSSridhar Samudrala {
3560ac5a488eSSridhar Samudrala 	struct sock *sk = sock->sk;
3561ac5a488eSSridhar Samudrala 	const struct proto_ops *ops = READ_ONCE(sock->ops);
35621ded5e5aSEric Dumazet 	struct proto_accept_arg arg = {
356392ef0fd5SJens Axboe 		.flags = flags,
356492ef0fd5SJens Axboe 		.kern = true,
356592ef0fd5SJens Axboe 	};
356692ef0fd5SJens Axboe 	int err;
3567ac5a488eSSridhar Samudrala 
3568ac5a488eSSridhar Samudrala 	err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
3569ac5a488eSSridhar Samudrala 			       newsock);
3570ac5a488eSSridhar Samudrala 	if (err < 0)
3571ac5a488eSSridhar Samudrala 		goto done;
3572ac5a488eSSridhar Samudrala 
3573ac5a488eSSridhar Samudrala 	err = ops->accept(sock, *newsock, &arg);
357492ef0fd5SJens Axboe 	if (err < 0) {
3575ac5a488eSSridhar Samudrala 		sock_release(*newsock);
3576ac5a488eSSridhar Samudrala 		*newsock = NULL;
3577fa8705b0STony Battersby 		goto done;
3578ac5a488eSSridhar Samudrala 	}
3579ac5a488eSSridhar Samudrala 
3580ac5a488eSSridhar Samudrala 	(*newsock)->ops = ops;
35811ded5e5aSEric Dumazet 	__module_get(ops->owner);
35821ded5e5aSEric Dumazet 
3583ac5a488eSSridhar Samudrala done:
3584ac5a488eSSridhar Samudrala 	return err;
3585ac5a488eSSridhar Samudrala }
3586ac5a488eSSridhar Samudrala EXPORT_SYMBOL(kernel_accept);
3587c6d409cfSEric Dumazet 
3588ac5a488eSSridhar Samudrala /**
35898a3c245cSPedro Tammela  *	kernel_connect - connect a socket (kernel space)
35908a3c245cSPedro Tammela  *	@sock: socket
35918a3c245cSPedro Tammela  *	@addr: address
35928a3c245cSPedro Tammela  *	@addrlen: address length
35938a3c245cSPedro Tammela  *	@flags: flags (O_NONBLOCK, ...)
35948a3c245cSPedro Tammela  *
35958a3c245cSPedro Tammela  *	For datagram sockets, @addr is the address to which datagrams are sent
3596f1dcffccSLu Wei  *	by default, and the only address from which datagrams are received.
35978a3c245cSPedro Tammela  *	For stream sockets, attempts to connect to @addr.
35988a3c245cSPedro Tammela  *	Returns 0 or an error code.
35998a3c245cSPedro Tammela  */
36008a3c245cSPedro Tammela 
kernel_connect(struct socket * sock,struct sockaddr * addr,int addrlen,int flags)36018a3c245cSPedro Tammela int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
3602ac5a488eSSridhar Samudrala 		   int flags)
3603ac5a488eSSridhar Samudrala {
3604ac5a488eSSridhar Samudrala 	struct sockaddr_storage address;
36050bdf3993SJordan Rife 
36060bdf3993SJordan Rife 	memcpy(&address, addr, addrlen);
36070bdf3993SJordan Rife 
36080bdf3993SJordan Rife 	return READ_ONCE(sock->ops)->connect(sock, (struct sockaddr *)&address,
36090bdf3993SJordan Rife 					     addrlen, flags);
36100bdf3993SJordan Rife }
3611ac5a488eSSridhar Samudrala EXPORT_SYMBOL(kernel_connect);
3612c6d409cfSEric Dumazet 
3613ac5a488eSSridhar Samudrala /**
36148a3c245cSPedro Tammela  *	kernel_getsockname - get the address which the socket is bound (kernel space)
36158a3c245cSPedro Tammela  *	@sock: socket
36168a3c245cSPedro Tammela  *	@addr: address holder
36178a3c245cSPedro Tammela  *
36188a3c245cSPedro Tammela  * 	Fills the @addr pointer with the address which the socket is bound.
36198a3c245cSPedro Tammela  *	Returns the length of the address in bytes or an error code.
36200fc95decSAlex Maydanik  */
36218a3c245cSPedro Tammela 
kernel_getsockname(struct socket * sock,struct sockaddr * addr)36228a3c245cSPedro Tammela int kernel_getsockname(struct socket *sock, struct sockaddr *addr)
36239b2c45d4SDenys Vlasenko {
3624ac5a488eSSridhar Samudrala 	return READ_ONCE(sock->ops)->getname(sock, addr, 0);
36251ded5e5aSEric Dumazet }
3626ac5a488eSSridhar Samudrala EXPORT_SYMBOL(kernel_getsockname);
3627c6d409cfSEric Dumazet 
3628ac5a488eSSridhar Samudrala /**
36298a3c245cSPedro Tammela  *	kernel_getpeername - get the address which the socket is connected (kernel space)
3630645f0897SMiaohe Lin  *	@sock: socket
36318a3c245cSPedro Tammela  *	@addr: address holder
36328a3c245cSPedro Tammela  *
36338a3c245cSPedro Tammela  * 	Fills the @addr pointer with the address which the socket is connected.
36348a3c245cSPedro Tammela  *	Returns the length of the address in bytes or an error code.
36350fc95decSAlex Maydanik  */
36368a3c245cSPedro Tammela 
kernel_getpeername(struct socket * sock,struct sockaddr * addr)36378a3c245cSPedro Tammela int kernel_getpeername(struct socket *sock, struct sockaddr *addr)
36389b2c45d4SDenys Vlasenko {
3639ac5a488eSSridhar Samudrala 	return READ_ONCE(sock->ops)->getname(sock, addr, 1);
36401ded5e5aSEric Dumazet }
3641ac5a488eSSridhar Samudrala EXPORT_SYMBOL(kernel_getpeername);
3642c6d409cfSEric Dumazet 
3643ac5a488eSSridhar Samudrala /**
36448a3c245cSPedro Tammela  *	kernel_sock_shutdown - shut down part of a full-duplex connection (kernel space)
3645645f0897SMiaohe Lin  *	@sock: socket
36468a3c245cSPedro Tammela  *	@how: connection part
36478a3c245cSPedro Tammela  *
36488a3c245cSPedro Tammela  *	Returns 0 or an error.
36498a3c245cSPedro Tammela  */
36508a3c245cSPedro Tammela 
kernel_sock_shutdown(struct socket * sock,enum sock_shutdown_cmd how)36518a3c245cSPedro Tammela int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
365291cf45f0STrond Myklebust {
365391cf45f0STrond Myklebust 	return READ_ONCE(sock->ops)->shutdown(sock, how);
36541ded5e5aSEric Dumazet }
365591cf45f0STrond Myklebust EXPORT_SYMBOL(kernel_sock_shutdown);
365691cf45f0STrond Myklebust 
3657113c3075SR. Parameswaran /**
36588a3c245cSPedro Tammela  *	kernel_sock_ip_overhead - returns the IP overhead imposed by a socket
36598a3c245cSPedro Tammela  *	@sk: socket
36608a3c245cSPedro Tammela  *
36618a3c245cSPedro Tammela  *	This routine returns the IP overhead imposed by a socket i.e.
36628a3c245cSPedro Tammela  *	the length of the underlying IP header, depending on whether
3663113c3075SR. Parameswaran  *	this is an IPv4 or IPv6 socket and the length from IP options turned
3664113c3075SR. Parameswaran  *	on at the socket. Assumes that the caller has a lock on the socket.
366557240d00SR. Parameswaran  */
3666113c3075SR. Parameswaran 
kernel_sock_ip_overhead(struct sock * sk)36678a3c245cSPedro Tammela u32 kernel_sock_ip_overhead(struct sock *sk)
3668113c3075SR. Parameswaran {
3669113c3075SR. Parameswaran 	struct inet_sock *inet;
3670113c3075SR. Parameswaran 	struct ip_options_rcu *opt;
3671113c3075SR. Parameswaran 	u32 overhead = 0;
3672113c3075SR. Parameswaran #if IS_ENABLED(CONFIG_IPV6)
3673113c3075SR. Parameswaran 	struct ipv6_pinfo *np;
3674113c3075SR. Parameswaran 	struct ipv6_txoptions *optv6 = NULL;
3675113c3075SR. Parameswaran #endif /* IS_ENABLED(CONFIG_IPV6) */
3676113c3075SR. Parameswaran 
3677113c3075SR. Parameswaran 	if (!sk)
3678113c3075SR. Parameswaran 		return overhead;
3679113c3075SR. Parameswaran 
3680113c3075SR. Parameswaran 	switch (sk->sk_family) {
3681113c3075SR. Parameswaran 	case AF_INET:
3682113c3075SR. Parameswaran 		inet = inet_sk(sk);
3683113c3075SR. Parameswaran 		overhead += sizeof(struct iphdr);
3684113c3075SR. Parameswaran 		opt = rcu_dereference_protected(inet->inet_opt,
3685113c3075SR. Parameswaran 						sock_owned_by_user(sk));
3686614d79c0Sstephen hemminger 		if (opt)
3687113c3075SR. Parameswaran 			overhead += opt->opt.optlen;
3688113c3075SR. Parameswaran 		return overhead;
3689113c3075SR. Parameswaran #if IS_ENABLED(CONFIG_IPV6)
3690113c3075SR. Parameswaran 	case AF_INET6:
3691113c3075SR. Parameswaran 		np = inet6_sk(sk);
3692113c3075SR. Parameswaran 		overhead += sizeof(struct ipv6hdr);
3693113c3075SR. Parameswaran 		if (np)
3694113c3075SR. Parameswaran 			optv6 = rcu_dereference_protected(np->opt,
3695113c3075SR. Parameswaran 							  sock_owned_by_user(sk));
3696614d79c0Sstephen hemminger 		if (optv6)
3697113c3075SR. Parameswaran 			overhead += (optv6->opt_flen + optv6->opt_nflen);
3698113c3075SR. Parameswaran 		return overhead;
3699113c3075SR. Parameswaran #endif /* IS_ENABLED(CONFIG_IPV6) */
3700113c3075SR. Parameswaran 	default: /* Returns 0 overhead if the socket is not ipv4 or ipv6 */
3701113c3075SR. Parameswaran 		return overhead;
3702113c3075SR. Parameswaran 	}
3703113c3075SR. Parameswaran }
3704113c3075SR. Parameswaran EXPORT_SYMBOL(kernel_sock_ip_overhead);
3705113c3075SR. Parameswaran