xref: /openbmc/linux/net/socket.c (revision d5e0bb03)
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, <obz@Kodak.COM>
802c30a84SJesper Juhl  *		Ross Biro
91da177e4SLinus Torvalds  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
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>
918e9fad0eSBreno Leitao #include <linux/io_uring.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 
113e0d1095aSCong Wang #ifdef CONFIG_NET_RX_BUSY_POLL
11464b0dc51SEliezer Tamir unsigned int sysctl_net_busy_read __read_mostly;
11564b0dc51SEliezer Tamir unsigned int sysctl_net_busy_poll __read_mostly;
11606021292SEliezer Tamir #endif
1176b96018bSArnd Bergmann 
1188ae5e030SAl Viro static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to);
1198ae5e030SAl Viro static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from);
1201da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma);
1211da177e4SLinus Torvalds 
1221da177e4SLinus Torvalds static int sock_close(struct inode *inode, struct file *file);
123a11e1d43SLinus Torvalds static __poll_t sock_poll(struct file *file,
124a11e1d43SLinus Torvalds 			      struct poll_table_struct *wait);
12589bddce5SStephen Hemminger static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
12689bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
12789bbfc95SShaun Pereira static long compat_sock_ioctl(struct file *file,
12889bbfc95SShaun Pereira 			      unsigned int cmd, unsigned long arg);
12989bbfc95SShaun Pereira #endif
1301da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on);
1319c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
1329c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
1339c55e01cSJens Axboe 				unsigned int flags);
1342bfc6685SDavid Howells static void sock_splice_eof(struct file *file);
135542d3065SArnd Bergmann 
136542d3065SArnd Bergmann #ifdef CONFIG_PROC_FS
sock_show_fdinfo(struct seq_file * m,struct file * f)137542d3065SArnd Bergmann static void sock_show_fdinfo(struct seq_file *m, struct file *f)
138542d3065SArnd Bergmann {
139542d3065SArnd Bergmann 	struct socket *sock = f->private_data;
1401ded5e5aSEric Dumazet 	const struct proto_ops *ops = READ_ONCE(sock->ops);
141542d3065SArnd Bergmann 
1421ded5e5aSEric Dumazet 	if (ops->show_fdinfo)
1431ded5e5aSEric Dumazet 		ops->show_fdinfo(m, sock);
144542d3065SArnd Bergmann }
145542d3065SArnd Bergmann #else
146542d3065SArnd Bergmann #define sock_show_fdinfo NULL
147542d3065SArnd Bergmann #endif
1481da177e4SLinus Torvalds 
1491da177e4SLinus Torvalds /*
1501da177e4SLinus Torvalds  *	Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
1511da177e4SLinus Torvalds  *	in the operation structures but are done directly via the socketcall() multiplexor.
1521da177e4SLinus Torvalds  */
1531da177e4SLinus Torvalds 
154da7071d7SArjan van de Ven static const struct file_operations socket_file_ops = {
1551da177e4SLinus Torvalds 	.owner =	THIS_MODULE,
1561da177e4SLinus Torvalds 	.llseek =	no_llseek,
1578ae5e030SAl Viro 	.read_iter =	sock_read_iter,
1588ae5e030SAl Viro 	.write_iter =	sock_write_iter,
1591da177e4SLinus Torvalds 	.poll =		sock_poll,
1601da177e4SLinus Torvalds 	.unlocked_ioctl = sock_ioctl,
16189bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
16289bbfc95SShaun Pereira 	.compat_ioctl = compat_sock_ioctl,
16389bbfc95SShaun Pereira #endif
1648e9fad0eSBreno Leitao 	.uring_cmd =    io_uring_cmd_sock,
1651da177e4SLinus Torvalds 	.mmap =		sock_mmap,
1661da177e4SLinus Torvalds 	.release =	sock_close,
1671da177e4SLinus Torvalds 	.fasync =	sock_fasync,
1682dc334f1SDavid Howells 	.splice_write = splice_to_socket,
1699c55e01cSJens Axboe 	.splice_read =	sock_splice_read,
1702bfc6685SDavid Howells 	.splice_eof =	sock_splice_eof,
171b4653342SKirill Tkhai 	.show_fdinfo =	sock_show_fdinfo,
1721da177e4SLinus Torvalds };
1731da177e4SLinus Torvalds 
174fe0bdbdeSYejune Deng static const char * const pf_family_names[] = {
175fe0bdbdeSYejune Deng 	[PF_UNSPEC]	= "PF_UNSPEC",
176fe0bdbdeSYejune Deng 	[PF_UNIX]	= "PF_UNIX/PF_LOCAL",
177fe0bdbdeSYejune Deng 	[PF_INET]	= "PF_INET",
178fe0bdbdeSYejune Deng 	[PF_AX25]	= "PF_AX25",
179fe0bdbdeSYejune Deng 	[PF_IPX]	= "PF_IPX",
180fe0bdbdeSYejune Deng 	[PF_APPLETALK]	= "PF_APPLETALK",
181fe0bdbdeSYejune Deng 	[PF_NETROM]	= "PF_NETROM",
182fe0bdbdeSYejune Deng 	[PF_BRIDGE]	= "PF_BRIDGE",
183fe0bdbdeSYejune Deng 	[PF_ATMPVC]	= "PF_ATMPVC",
184fe0bdbdeSYejune Deng 	[PF_X25]	= "PF_X25",
185fe0bdbdeSYejune Deng 	[PF_INET6]	= "PF_INET6",
186fe0bdbdeSYejune Deng 	[PF_ROSE]	= "PF_ROSE",
187fe0bdbdeSYejune Deng 	[PF_DECnet]	= "PF_DECnet",
188fe0bdbdeSYejune Deng 	[PF_NETBEUI]	= "PF_NETBEUI",
189fe0bdbdeSYejune Deng 	[PF_SECURITY]	= "PF_SECURITY",
190fe0bdbdeSYejune Deng 	[PF_KEY]	= "PF_KEY",
191fe0bdbdeSYejune Deng 	[PF_NETLINK]	= "PF_NETLINK/PF_ROUTE",
192fe0bdbdeSYejune Deng 	[PF_PACKET]	= "PF_PACKET",
193fe0bdbdeSYejune Deng 	[PF_ASH]	= "PF_ASH",
194fe0bdbdeSYejune Deng 	[PF_ECONET]	= "PF_ECONET",
195fe0bdbdeSYejune Deng 	[PF_ATMSVC]	= "PF_ATMSVC",
196fe0bdbdeSYejune Deng 	[PF_RDS]	= "PF_RDS",
197fe0bdbdeSYejune Deng 	[PF_SNA]	= "PF_SNA",
198fe0bdbdeSYejune Deng 	[PF_IRDA]	= "PF_IRDA",
199fe0bdbdeSYejune Deng 	[PF_PPPOX]	= "PF_PPPOX",
200fe0bdbdeSYejune Deng 	[PF_WANPIPE]	= "PF_WANPIPE",
201fe0bdbdeSYejune Deng 	[PF_LLC]	= "PF_LLC",
202fe0bdbdeSYejune Deng 	[PF_IB]		= "PF_IB",
203fe0bdbdeSYejune Deng 	[PF_MPLS]	= "PF_MPLS",
204fe0bdbdeSYejune Deng 	[PF_CAN]	= "PF_CAN",
205fe0bdbdeSYejune Deng 	[PF_TIPC]	= "PF_TIPC",
206fe0bdbdeSYejune Deng 	[PF_BLUETOOTH]	= "PF_BLUETOOTH",
207fe0bdbdeSYejune Deng 	[PF_IUCV]	= "PF_IUCV",
208fe0bdbdeSYejune Deng 	[PF_RXRPC]	= "PF_RXRPC",
209fe0bdbdeSYejune Deng 	[PF_ISDN]	= "PF_ISDN",
210fe0bdbdeSYejune Deng 	[PF_PHONET]	= "PF_PHONET",
211fe0bdbdeSYejune Deng 	[PF_IEEE802154]	= "PF_IEEE802154",
212fe0bdbdeSYejune Deng 	[PF_CAIF]	= "PF_CAIF",
213fe0bdbdeSYejune Deng 	[PF_ALG]	= "PF_ALG",
214fe0bdbdeSYejune Deng 	[PF_NFC]	= "PF_NFC",
215fe0bdbdeSYejune Deng 	[PF_VSOCK]	= "PF_VSOCK",
216fe0bdbdeSYejune Deng 	[PF_KCM]	= "PF_KCM",
217fe0bdbdeSYejune Deng 	[PF_QIPCRTR]	= "PF_QIPCRTR",
218fe0bdbdeSYejune Deng 	[PF_SMC]	= "PF_SMC",
219fe0bdbdeSYejune Deng 	[PF_XDP]	= "PF_XDP",
220bc49d816SJeremy Kerr 	[PF_MCTP]	= "PF_MCTP",
221fe0bdbdeSYejune Deng };
222fe0bdbdeSYejune Deng 
2231da177e4SLinus Torvalds /*
2241da177e4SLinus Torvalds  *	The protocol list. Each protocol is registered in here.
2251da177e4SLinus Torvalds  */
2261da177e4SLinus Torvalds 
2271da177e4SLinus Torvalds static DEFINE_SPINLOCK(net_family_lock);
228190683a9SEric Dumazet static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly;
2291da177e4SLinus Torvalds 
2301da177e4SLinus Torvalds /*
23189bddce5SStephen Hemminger  * Support routines.
23289bddce5SStephen Hemminger  * Move socket addresses back and forth across the kernel/user
2331da177e4SLinus Torvalds  * divide and look after the messy bits.
2341da177e4SLinus Torvalds  */
2351da177e4SLinus Torvalds 
2361da177e4SLinus Torvalds /**
2371da177e4SLinus Torvalds  *	move_addr_to_kernel	-	copy a socket address into kernel space
2381da177e4SLinus Torvalds  *	@uaddr: Address in user space
2391da177e4SLinus Torvalds  *	@kaddr: Address in kernel space
2401da177e4SLinus Torvalds  *	@ulen: Length in user space
2411da177e4SLinus Torvalds  *
2421da177e4SLinus Torvalds  *	The address is copied into kernel space. If the provided address is
2431da177e4SLinus Torvalds  *	too long an error code of -EINVAL is returned. If the copy gives
2441da177e4SLinus Torvalds  *	invalid addresses -EFAULT is returned. On a success 0 is returned.
2451da177e4SLinus Torvalds  */
2461da177e4SLinus Torvalds 
move_addr_to_kernel(void __user * uaddr,int ulen,struct sockaddr_storage * kaddr)24743db362dSMaciej Żenczykowski int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr)
2481da177e4SLinus Torvalds {
249230b1839SYOSHIFUJI Hideaki 	if (ulen < 0 || ulen > sizeof(struct sockaddr_storage))
2501da177e4SLinus Torvalds 		return -EINVAL;
2511da177e4SLinus Torvalds 	if (ulen == 0)
2521da177e4SLinus Torvalds 		return 0;
2531da177e4SLinus Torvalds 	if (copy_from_user(kaddr, uaddr, ulen))
2541da177e4SLinus Torvalds 		return -EFAULT;
2553ec3b2fbSDavid Woodhouse 	return audit_sockaddr(ulen, kaddr);
2561da177e4SLinus Torvalds }
2571da177e4SLinus Torvalds 
2581da177e4SLinus Torvalds /**
2591da177e4SLinus Torvalds  *	move_addr_to_user	-	copy an address to user space
2601da177e4SLinus Torvalds  *	@kaddr: kernel space address
2611da177e4SLinus Torvalds  *	@klen: length of address in kernel
2621da177e4SLinus Torvalds  *	@uaddr: user space address
2631da177e4SLinus Torvalds  *	@ulen: pointer to user length field
2641da177e4SLinus Torvalds  *
2651da177e4SLinus Torvalds  *	The value pointed to by ulen on entry is the buffer length available.
2661da177e4SLinus Torvalds  *	This is overwritten with the buffer space used. -EINVAL is returned
2671da177e4SLinus Torvalds  *	if an overlong buffer is specified or a negative buffer size. -EFAULT
2681da177e4SLinus Torvalds  *	is returned if either the buffer or the length field are not
2691da177e4SLinus Torvalds  *	accessible.
2701da177e4SLinus Torvalds  *	After copying the data up to the limit the user specifies, the true
2711da177e4SLinus Torvalds  *	length of the data is written over the length limit the user
2721da177e4SLinus Torvalds  *	specified. Zero is returned for a success.
2731da177e4SLinus Torvalds  */
2741da177e4SLinus Torvalds 
move_addr_to_user(struct sockaddr_storage * kaddr,int klen,void __user * uaddr,int __user * ulen)27543db362dSMaciej Żenczykowski static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen,
27611165f14Sstephen hemminger 			     void __user *uaddr, int __user *ulen)
2771da177e4SLinus Torvalds {
2781da177e4SLinus Torvalds 	int err;
2791da177e4SLinus Torvalds 	int len;
2801da177e4SLinus Torvalds 
28168c6beb3SHannes Frederic Sowa 	BUG_ON(klen > sizeof(struct sockaddr_storage));
28289bddce5SStephen Hemminger 	err = get_user(len, ulen);
28389bddce5SStephen Hemminger 	if (err)
2841da177e4SLinus Torvalds 		return err;
2851da177e4SLinus Torvalds 	if (len > klen)
2861da177e4SLinus Torvalds 		len = klen;
28768c6beb3SHannes Frederic Sowa 	if (len < 0)
2881da177e4SLinus Torvalds 		return -EINVAL;
28989bddce5SStephen Hemminger 	if (len) {
290d6fe3945SSteve Grubb 		if (audit_sockaddr(klen, kaddr))
291d6fe3945SSteve Grubb 			return -ENOMEM;
2921da177e4SLinus Torvalds 		if (copy_to_user(uaddr, kaddr, len))
2931da177e4SLinus Torvalds 			return -EFAULT;
2941da177e4SLinus Torvalds 	}
2951da177e4SLinus Torvalds 	/*
2961da177e4SLinus Torvalds 	 *      "fromlen shall refer to the value before truncation.."
2971da177e4SLinus Torvalds 	 *                      1003.1g
2981da177e4SLinus Torvalds 	 */
2991da177e4SLinus Torvalds 	return __put_user(klen, ulen);
3001da177e4SLinus Torvalds }
3011da177e4SLinus Torvalds 
30208009a76SAlexey Dobriyan static struct kmem_cache *sock_inode_cachep __ro_after_init;
3031da177e4SLinus Torvalds 
sock_alloc_inode(struct super_block * sb)3041da177e4SLinus Torvalds static struct inode *sock_alloc_inode(struct super_block *sb)
3051da177e4SLinus Torvalds {
3061da177e4SLinus Torvalds 	struct socket_alloc *ei;
30789bddce5SStephen Hemminger 
308fd60b288SMuchun Song 	ei = alloc_inode_sb(sb, sock_inode_cachep, GFP_KERNEL);
3091da177e4SLinus Torvalds 	if (!ei)
3101da177e4SLinus Torvalds 		return NULL;
311333f7909SAl Viro 	init_waitqueue_head(&ei->socket.wq.wait);
312333f7909SAl Viro 	ei->socket.wq.fasync_list = NULL;
313333f7909SAl Viro 	ei->socket.wq.flags = 0;
3141da177e4SLinus Torvalds 
3151da177e4SLinus Torvalds 	ei->socket.state = SS_UNCONNECTED;
3161da177e4SLinus Torvalds 	ei->socket.flags = 0;
3171da177e4SLinus Torvalds 	ei->socket.ops = NULL;
3181da177e4SLinus Torvalds 	ei->socket.sk = NULL;
3191da177e4SLinus Torvalds 	ei->socket.file = NULL;
3201da177e4SLinus Torvalds 
3211da177e4SLinus Torvalds 	return &ei->vfs_inode;
3221da177e4SLinus Torvalds }
3231da177e4SLinus Torvalds 
sock_free_inode(struct inode * inode)3246d7855c5SAl Viro static void sock_free_inode(struct inode *inode)
3251da177e4SLinus Torvalds {
32643815482SEric Dumazet 	struct socket_alloc *ei;
32743815482SEric Dumazet 
32843815482SEric Dumazet 	ei = container_of(inode, struct socket_alloc, vfs_inode);
32943815482SEric Dumazet 	kmem_cache_free(sock_inode_cachep, ei);
3301da177e4SLinus Torvalds }
3311da177e4SLinus Torvalds 
init_once(void * foo)33251cc5068SAlexey Dobriyan static void init_once(void *foo)
3331da177e4SLinus Torvalds {
3341da177e4SLinus Torvalds 	struct socket_alloc *ei = (struct socket_alloc *)foo;
3351da177e4SLinus Torvalds 
3361da177e4SLinus Torvalds 	inode_init_once(&ei->vfs_inode);
3371da177e4SLinus Torvalds }
3381da177e4SLinus Torvalds 
init_inodecache(void)3391e911632Syuan linyu static void init_inodecache(void)
3401da177e4SLinus Torvalds {
3411da177e4SLinus Torvalds 	sock_inode_cachep = kmem_cache_create("sock_inode_cache",
3421da177e4SLinus Torvalds 					      sizeof(struct socket_alloc),
34389bddce5SStephen Hemminger 					      0,
34489bddce5SStephen Hemminger 					      (SLAB_HWCACHE_ALIGN |
34589bddce5SStephen Hemminger 					       SLAB_RECLAIM_ACCOUNT |
3465d097056SVladimir Davydov 					       SLAB_MEM_SPREAD | SLAB_ACCOUNT),
34720c2df83SPaul Mundt 					      init_once);
3481e911632Syuan linyu 	BUG_ON(sock_inode_cachep == NULL);
3491da177e4SLinus Torvalds }
3501da177e4SLinus Torvalds 
351b87221deSAlexey Dobriyan static const struct super_operations sockfs_ops = {
3521da177e4SLinus Torvalds 	.alloc_inode	= sock_alloc_inode,
3536d7855c5SAl Viro 	.free_inode	= sock_free_inode,
3541da177e4SLinus Torvalds 	.statfs		= simple_statfs,
3551da177e4SLinus Torvalds };
3561da177e4SLinus Torvalds 
357c23fbb6bSEric Dumazet /*
358c23fbb6bSEric Dumazet  * sockfs_dname() is called from d_path().
359c23fbb6bSEric Dumazet  */
sockfs_dname(struct dentry * dentry,char * buffer,int buflen)360c23fbb6bSEric Dumazet static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen)
361c23fbb6bSEric Dumazet {
3620f60d288SAl Viro 	return dynamic_dname(buffer, buflen, "socket:[%lu]",
363c5ef6035SDavid Howells 				d_inode(dentry)->i_ino);
364c23fbb6bSEric Dumazet }
365c23fbb6bSEric Dumazet 
3663ba13d17SAl Viro static const struct dentry_operations sockfs_dentry_operations = {
367c23fbb6bSEric Dumazet 	.d_dname  = sockfs_dname,
3681da177e4SLinus Torvalds };
3691da177e4SLinus Torvalds 
sockfs_xattr_get(const struct xattr_handler * handler,struct dentry * dentry,struct inode * inode,const char * suffix,void * value,size_t size)370bba0bd31SAndreas Gruenbacher static int sockfs_xattr_get(const struct xattr_handler *handler,
371bba0bd31SAndreas Gruenbacher 			    struct dentry *dentry, struct inode *inode,
372bba0bd31SAndreas Gruenbacher 			    const char *suffix, void *value, size_t size)
373bba0bd31SAndreas Gruenbacher {
374bba0bd31SAndreas Gruenbacher 	if (value) {
375bba0bd31SAndreas Gruenbacher 		if (dentry->d_name.len + 1 > size)
376bba0bd31SAndreas Gruenbacher 			return -ERANGE;
377bba0bd31SAndreas Gruenbacher 		memcpy(value, dentry->d_name.name, dentry->d_name.len + 1);
378bba0bd31SAndreas Gruenbacher 	}
379bba0bd31SAndreas Gruenbacher 	return dentry->d_name.len + 1;
380bba0bd31SAndreas Gruenbacher }
381bba0bd31SAndreas Gruenbacher 
382bba0bd31SAndreas Gruenbacher #define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname"
383bba0bd31SAndreas Gruenbacher #define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX)
384bba0bd31SAndreas Gruenbacher #define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1)
385bba0bd31SAndreas Gruenbacher 
386bba0bd31SAndreas Gruenbacher static const struct xattr_handler sockfs_xattr_handler = {
387bba0bd31SAndreas Gruenbacher 	.name = XATTR_NAME_SOCKPROTONAME,
388bba0bd31SAndreas Gruenbacher 	.get = sockfs_xattr_get,
389bba0bd31SAndreas Gruenbacher };
390bba0bd31SAndreas 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)3914a590153SAndreas Gruenbacher static int sockfs_security_xattr_set(const struct xattr_handler *handler,
39239f60c1cSChristian Brauner 				     struct mnt_idmap *idmap,
3934a590153SAndreas Gruenbacher 				     struct dentry *dentry, struct inode *inode,
3944a590153SAndreas Gruenbacher 				     const char *suffix, const void *value,
3954a590153SAndreas Gruenbacher 				     size_t size, int flags)
3964a590153SAndreas Gruenbacher {
3974a590153SAndreas Gruenbacher 	/* Handled by LSM. */
3984a590153SAndreas Gruenbacher 	return -EAGAIN;
3994a590153SAndreas Gruenbacher }
4004a590153SAndreas Gruenbacher 
4014a590153SAndreas Gruenbacher static const struct xattr_handler sockfs_security_xattr_handler = {
4024a590153SAndreas Gruenbacher 	.prefix = XATTR_SECURITY_PREFIX,
4034a590153SAndreas Gruenbacher 	.set = sockfs_security_xattr_set,
4044a590153SAndreas Gruenbacher };
4054a590153SAndreas Gruenbacher 
406bba0bd31SAndreas Gruenbacher static const struct xattr_handler *sockfs_xattr_handlers[] = {
407bba0bd31SAndreas Gruenbacher 	&sockfs_xattr_handler,
4084a590153SAndreas Gruenbacher 	&sockfs_security_xattr_handler,
409bba0bd31SAndreas Gruenbacher 	NULL
410bba0bd31SAndreas Gruenbacher };
411bba0bd31SAndreas Gruenbacher 
sockfs_init_fs_context(struct fs_context * fc)412fba9be49SDavid Howells static int sockfs_init_fs_context(struct fs_context *fc)
413c74a1cbbSAl Viro {
414fba9be49SDavid Howells 	struct pseudo_fs_context *ctx = init_pseudo(fc, SOCKFS_MAGIC);
415fba9be49SDavid Howells 	if (!ctx)
416fba9be49SDavid Howells 		return -ENOMEM;
417fba9be49SDavid Howells 	ctx->ops = &sockfs_ops;
418fba9be49SDavid Howells 	ctx->dops = &sockfs_dentry_operations;
419fba9be49SDavid Howells 	ctx->xattr = sockfs_xattr_handlers;
420fba9be49SDavid Howells 	return 0;
421c74a1cbbSAl Viro }
422c74a1cbbSAl Viro 
423c74a1cbbSAl Viro static struct vfsmount *sock_mnt __read_mostly;
424c74a1cbbSAl Viro 
425c74a1cbbSAl Viro static struct file_system_type sock_fs_type = {
426c74a1cbbSAl Viro 	.name =		"sockfs",
427fba9be49SDavid Howells 	.init_fs_context = sockfs_init_fs_context,
428c74a1cbbSAl Viro 	.kill_sb =	kill_anon_super,
429c74a1cbbSAl Viro };
430c74a1cbbSAl Viro 
4311da177e4SLinus Torvalds /*
4321da177e4SLinus Torvalds  *	Obtains the first available file descriptor and sets it up for use.
4331da177e4SLinus Torvalds  *
43439d8c1b6SDavid S. Miller  *	These functions create file structures and maps them to fd space
43539d8c1b6SDavid S. Miller  *	of the current process. On success it returns file descriptor
4361da177e4SLinus Torvalds  *	and file struct implicitly stored in sock->file.
4371da177e4SLinus Torvalds  *	Note that another thread may close file descriptor before we return
4381da177e4SLinus Torvalds  *	from this function. We use the fact that now we do not refer
4391da177e4SLinus Torvalds  *	to socket after mapping. If one day we will need it, this
4401da177e4SLinus Torvalds  *	function will increment ref. count on file by 1.
4411da177e4SLinus Torvalds  *
4421da177e4SLinus Torvalds  *	In any case returned fd MAY BE not valid!
4431da177e4SLinus Torvalds  *	This race condition is unavoidable
4441da177e4SLinus Torvalds  *	with shared fd spaces, we cannot solve it inside kernel,
4451da177e4SLinus Torvalds  *	but we take care of internal coherence yet.
4461da177e4SLinus Torvalds  */
4471da177e4SLinus Torvalds 
4488a3c245cSPedro Tammela /**
4498a3c245cSPedro Tammela  *	sock_alloc_file - Bind a &socket to a &file
4508a3c245cSPedro Tammela  *	@sock: socket
4518a3c245cSPedro Tammela  *	@flags: file status flags
4528a3c245cSPedro Tammela  *	@dname: protocol name
4538a3c245cSPedro Tammela  *
4548a3c245cSPedro Tammela  *	Returns the &file bound with @sock, implicitly storing it
4558a3c245cSPedro Tammela  *	in sock->file. If dname is %NULL, sets to "".
456649c15c7SThadeu Lima de Souza Cascardo  *
457649c15c7SThadeu Lima de Souza Cascardo  *	On failure @sock is released, and an ERR pointer is returned.
458649c15c7SThadeu Lima de Souza Cascardo  *
4598a3c245cSPedro Tammela  *	This function uses GFP_KERNEL internally.
4608a3c245cSPedro Tammela  */
4618a3c245cSPedro Tammela 
sock_alloc_file(struct socket * sock,int flags,const char * dname)462aab174f0SLinus Torvalds struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)
4631da177e4SLinus Torvalds {
4647cbe66b6SAl Viro 	struct file *file;
4651da177e4SLinus Torvalds 
466d93aa9d8SAl Viro 	if (!dname)
467d93aa9d8SAl Viro 		dname = sock->sk ? sock->sk->sk_prot_creator->name : "";
46839d8c1b6SDavid S. Miller 
469d93aa9d8SAl Viro 	file = alloc_file_pseudo(SOCK_INODE(sock), sock_mnt, dname,
470d93aa9d8SAl Viro 				O_RDWR | (flags & O_NONBLOCK),
471cc3808f8SAl Viro 				&socket_file_ops);
472b5ffe634SViresh Kumar 	if (IS_ERR(file)) {
4738e1611e2SAl Viro 		sock_release(sock);
47439b65252SAnatol Pomozov 		return file;
475cc3808f8SAl Viro 	}
4761da177e4SLinus Torvalds 
477fe34db06SJens Axboe 	file->f_mode |= FMODE_NOWAIT;
4781da177e4SLinus Torvalds 	sock->file = file;
47907dc3f07SBenjamin LaHaise 	file->private_data = sock;
480d8e464ecSLinus Torvalds 	stream_open(SOCK_INODE(sock), file);
48128407630SAl Viro 	return file;
4821da177e4SLinus Torvalds }
48356b31d1cSAl Viro EXPORT_SYMBOL(sock_alloc_file);
4841da177e4SLinus Torvalds 
sock_map_fd(struct socket * sock,int flags)48556b31d1cSAl Viro static int sock_map_fd(struct socket *sock, int flags)
48639d8c1b6SDavid S. Miller {
48739d8c1b6SDavid S. Miller 	struct file *newfile;
48828407630SAl Viro 	int fd = get_unused_fd_flags(flags);
489ce4bb04cSAl Viro 	if (unlikely(fd < 0)) {
490ce4bb04cSAl Viro 		sock_release(sock);
4911da177e4SLinus Torvalds 		return fd;
492ce4bb04cSAl Viro 	}
4931da177e4SLinus Torvalds 
494aab174f0SLinus Torvalds 	newfile = sock_alloc_file(sock, flags, NULL);
4954546e44cSEnrico Weigelt 	if (!IS_ERR(newfile)) {
4961da177e4SLinus Torvalds 		fd_install(fd, newfile);
4971da177e4SLinus Torvalds 		return fd;
4981da177e4SLinus Torvalds 	}
49928407630SAl Viro 
50028407630SAl Viro 	put_unused_fd(fd);
50128407630SAl Viro 	return PTR_ERR(newfile);
5021da177e4SLinus Torvalds }
5031da177e4SLinus Torvalds 
5048a3c245cSPedro Tammela /**
5058a3c245cSPedro Tammela  *	sock_from_file - Return the &socket bounded to @file.
5068a3c245cSPedro Tammela  *	@file: file
5078a3c245cSPedro Tammela  *
508dba4a925SFlorent Revest  *	On failure returns %NULL.
5098a3c245cSPedro Tammela  */
5108a3c245cSPedro Tammela 
sock_from_file(struct file * file)511dba4a925SFlorent Revest struct socket *sock_from_file(struct file *file)
5126cb153caSBenjamin LaHaise {
5136cb153caSBenjamin LaHaise 	if (file->f_op == &socket_file_ops)
514da214a47SJens Axboe 		return file->private_data;	/* set in sock_alloc_file */
5156cb153caSBenjamin LaHaise 
5166cb153caSBenjamin LaHaise 	return NULL;
5176cb153caSBenjamin LaHaise }
518406a3c63SJohn Fastabend EXPORT_SYMBOL(sock_from_file);
5196cb153caSBenjamin LaHaise 
5201da177e4SLinus Torvalds /**
5211da177e4SLinus Torvalds  *	sockfd_lookup - Go from a file number to its socket slot
5221da177e4SLinus Torvalds  *	@fd: file handle
5231da177e4SLinus Torvalds  *	@err: pointer to an error code return
5241da177e4SLinus Torvalds  *
5251da177e4SLinus Torvalds  *	The file handle passed in is locked and the socket it is bound
526241c4667SRosen, Rami  *	to is returned. If an error occurs the err pointer is overwritten
5271da177e4SLinus Torvalds  *	with a negative errno code and NULL is returned. The function checks
5281da177e4SLinus Torvalds  *	for both invalid handles and passing a handle which is not a socket.
5291da177e4SLinus Torvalds  *
5301da177e4SLinus Torvalds  *	On a success the socket object pointer is returned.
5311da177e4SLinus Torvalds  */
5321da177e4SLinus Torvalds 
sockfd_lookup(int fd,int * err)5331da177e4SLinus Torvalds struct socket *sockfd_lookup(int fd, int *err)
5341da177e4SLinus Torvalds {
5351da177e4SLinus Torvalds 	struct file *file;
5361da177e4SLinus Torvalds 	struct socket *sock;
5371da177e4SLinus Torvalds 
53889bddce5SStephen Hemminger 	file = fget(fd);
53989bddce5SStephen Hemminger 	if (!file) {
5401da177e4SLinus Torvalds 		*err = -EBADF;
5411da177e4SLinus Torvalds 		return NULL;
5421da177e4SLinus Torvalds 	}
54389bddce5SStephen Hemminger 
544dba4a925SFlorent Revest 	sock = sock_from_file(file);
545dba4a925SFlorent Revest 	if (!sock) {
546dba4a925SFlorent Revest 		*err = -ENOTSOCK;
5471da177e4SLinus Torvalds 		fput(file);
548dba4a925SFlorent Revest 	}
5496cb153caSBenjamin LaHaise 	return sock;
5501da177e4SLinus Torvalds }
551c6d409cfSEric Dumazet EXPORT_SYMBOL(sockfd_lookup);
5521da177e4SLinus Torvalds 
sockfd_lookup_light(int fd,int * err,int * fput_needed)5536cb153caSBenjamin LaHaise static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
5546cb153caSBenjamin LaHaise {
55500e188efSAl Viro 	struct fd f = fdget(fd);
5566cb153caSBenjamin LaHaise 	struct socket *sock;
5576cb153caSBenjamin LaHaise 
5583672558cSHua Zhong 	*err = -EBADF;
55900e188efSAl Viro 	if (f.file) {
560dba4a925SFlorent Revest 		sock = sock_from_file(f.file);
56100e188efSAl Viro 		if (likely(sock)) {
562ce787a5aSMiaohe Lin 			*fput_needed = f.flags & FDPUT_FPUT;
5631da177e4SLinus Torvalds 			return sock;
56400e188efSAl Viro 		}
565dba4a925SFlorent Revest 		*err = -ENOTSOCK;
56600e188efSAl Viro 		fdput(f);
5676cb153caSBenjamin LaHaise 	}
5686cb153caSBenjamin LaHaise 	return NULL;
5691da177e4SLinus Torvalds }
5701da177e4SLinus Torvalds 
sockfs_listxattr(struct dentry * dentry,char * buffer,size_t size)571600e1779SMasatake YAMATO static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer,
572600e1779SMasatake YAMATO 				size_t size)
573600e1779SMasatake YAMATO {
574600e1779SMasatake YAMATO 	ssize_t len;
575600e1779SMasatake YAMATO 	ssize_t used = 0;
576600e1779SMasatake YAMATO 
577c5ef6035SDavid Howells 	len = security_inode_listsecurity(d_inode(dentry), buffer, size);
578600e1779SMasatake YAMATO 	if (len < 0)
579600e1779SMasatake YAMATO 		return len;
580600e1779SMasatake YAMATO 	used += len;
581600e1779SMasatake YAMATO 	if (buffer) {
582600e1779SMasatake YAMATO 		if (size < used)
583600e1779SMasatake YAMATO 			return -ERANGE;
584600e1779SMasatake YAMATO 		buffer += len;
585600e1779SMasatake YAMATO 	}
586600e1779SMasatake YAMATO 
587600e1779SMasatake YAMATO 	len = (XATTR_NAME_SOCKPROTONAME_LEN + 1);
588600e1779SMasatake YAMATO 	used += len;
589600e1779SMasatake YAMATO 	if (buffer) {
590600e1779SMasatake YAMATO 		if (size < used)
591600e1779SMasatake YAMATO 			return -ERANGE;
592600e1779SMasatake YAMATO 		memcpy(buffer, XATTR_NAME_SOCKPROTONAME, len);
593600e1779SMasatake YAMATO 		buffer += len;
594600e1779SMasatake YAMATO 	}
595600e1779SMasatake YAMATO 
596600e1779SMasatake YAMATO 	return used;
597600e1779SMasatake YAMATO }
598600e1779SMasatake YAMATO 
sockfs_setattr(struct mnt_idmap * idmap,struct dentry * dentry,struct iattr * iattr)599c1632a0fSChristian Brauner static int sockfs_setattr(struct mnt_idmap *idmap,
600549c7297SChristian Brauner 			  struct dentry *dentry, struct iattr *iattr)
60186741ec2SLorenzo Colitti {
602c1632a0fSChristian Brauner 	int err = simple_setattr(&nop_mnt_idmap, dentry, iattr);
60386741ec2SLorenzo Colitti 
604e1a3a60aSEric Biggers 	if (!err && (iattr->ia_valid & ATTR_UID)) {
60586741ec2SLorenzo Colitti 		struct socket *sock = SOCKET_I(d_inode(dentry));
60686741ec2SLorenzo Colitti 
6076d8c50dcSCong Wang 		if (sock->sk)
60886741ec2SLorenzo Colitti 			sock->sk->sk_uid = iattr->ia_uid;
6096d8c50dcSCong Wang 		else
6106d8c50dcSCong Wang 			err = -ENOENT;
61186741ec2SLorenzo Colitti 	}
61286741ec2SLorenzo Colitti 
61386741ec2SLorenzo Colitti 	return err;
61486741ec2SLorenzo Colitti }
61586741ec2SLorenzo Colitti 
616600e1779SMasatake YAMATO static const struct inode_operations sockfs_inode_ops = {
617600e1779SMasatake YAMATO 	.listxattr = sockfs_listxattr,
61886741ec2SLorenzo Colitti 	.setattr = sockfs_setattr,
619600e1779SMasatake YAMATO };
620600e1779SMasatake YAMATO 
6211da177e4SLinus Torvalds /**
6221da177e4SLinus Torvalds  *	sock_alloc - allocate a socket
6231da177e4SLinus Torvalds  *
6241da177e4SLinus Torvalds  *	Allocate a new inode and socket object. The two are bound together
6251da177e4SLinus Torvalds  *	and initialised. The socket is then returned. If we are out of inodes
6268a3c245cSPedro Tammela  *	NULL is returned. This functions uses GFP_KERNEL internally.
6271da177e4SLinus Torvalds  */
6281da177e4SLinus Torvalds 
sock_alloc(void)629f4a00aacSTom Herbert struct socket *sock_alloc(void)
6301da177e4SLinus Torvalds {
6311da177e4SLinus Torvalds 	struct inode *inode;
6321da177e4SLinus Torvalds 	struct socket *sock;
6331da177e4SLinus Torvalds 
634a209dfc7SEric Dumazet 	inode = new_inode_pseudo(sock_mnt->mnt_sb);
6351da177e4SLinus Torvalds 	if (!inode)
6361da177e4SLinus Torvalds 		return NULL;
6371da177e4SLinus Torvalds 
6381da177e4SLinus Torvalds 	sock = SOCKET_I(inode);
6391da177e4SLinus Torvalds 
64085fe4025SChristoph Hellwig 	inode->i_ino = get_next_ino();
6411da177e4SLinus Torvalds 	inode->i_mode = S_IFSOCK | S_IRWXUGO;
6428192b0c4SDavid Howells 	inode->i_uid = current_fsuid();
6438192b0c4SDavid Howells 	inode->i_gid = current_fsgid();
644600e1779SMasatake YAMATO 	inode->i_op = &sockfs_inode_ops;
6451da177e4SLinus Torvalds 
6461da177e4SLinus Torvalds 	return sock;
6471da177e4SLinus Torvalds }
648f4a00aacSTom Herbert EXPORT_SYMBOL(sock_alloc);
6491da177e4SLinus Torvalds 
__sock_release(struct socket * sock,struct inode * inode)6506d8c50dcSCong Wang static void __sock_release(struct socket *sock, struct inode *inode)
6511da177e4SLinus Torvalds {
6521ded5e5aSEric Dumazet 	const struct proto_ops *ops = READ_ONCE(sock->ops);
6531ded5e5aSEric Dumazet 
6541ded5e5aSEric Dumazet 	if (ops) {
6551ded5e5aSEric Dumazet 		struct module *owner = ops->owner;
6561da177e4SLinus Torvalds 
6576d8c50dcSCong Wang 		if (inode)
6586d8c50dcSCong Wang 			inode_lock(inode);
6591ded5e5aSEric Dumazet 		ops->release(sock);
660ff7b11aaSEric Biggers 		sock->sk = NULL;
6616d8c50dcSCong Wang 		if (inode)
6626d8c50dcSCong Wang 			inode_unlock(inode);
6631da177e4SLinus Torvalds 		sock->ops = NULL;
6641da177e4SLinus Torvalds 		module_put(owner);
6651da177e4SLinus Torvalds 	}
6661da177e4SLinus Torvalds 
667333f7909SAl Viro 	if (sock->wq.fasync_list)
6683410f22eSYang Yingliang 		pr_err("%s: fasync list not empty!\n", __func__);
6691da177e4SLinus Torvalds 
6701da177e4SLinus Torvalds 	if (!sock->file) {
6711da177e4SLinus Torvalds 		iput(SOCK_INODE(sock));
6721da177e4SLinus Torvalds 		return;
6731da177e4SLinus Torvalds 	}
6741da177e4SLinus Torvalds 	sock->file = NULL;
6751da177e4SLinus Torvalds }
6766d8c50dcSCong Wang 
6779a8ad9acSAndrew Lunn /**
6789a8ad9acSAndrew Lunn  *	sock_release - close a socket
6799a8ad9acSAndrew Lunn  *	@sock: socket to close
6809a8ad9acSAndrew Lunn  *
6819a8ad9acSAndrew Lunn  *	The socket is released from the protocol stack if it has a release
6829a8ad9acSAndrew Lunn  *	callback, and the inode is then released if the socket is bound to
6839a8ad9acSAndrew Lunn  *	an inode not a file.
6849a8ad9acSAndrew Lunn  */
sock_release(struct socket * sock)6856d8c50dcSCong Wang void sock_release(struct socket *sock)
6866d8c50dcSCong Wang {
6876d8c50dcSCong Wang 	__sock_release(sock, NULL);
6886d8c50dcSCong Wang }
689c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_release);
6901da177e4SLinus Torvalds 
__sock_tx_timestamp(__u16 tsflags,__u8 * tx_flags)691c14ac945SSoheil Hassas Yeganeh void __sock_tx_timestamp(__u16 tsflags, __u8 *tx_flags)
69220d49473SPatrick Ohly {
693140c55d4SEric Dumazet 	u8 flags = *tx_flags;
694140c55d4SEric Dumazet 
69551eb7492SGerhard Engleder 	if (tsflags & SOF_TIMESTAMPING_TX_HARDWARE) {
696140c55d4SEric Dumazet 		flags |= SKBTX_HW_TSTAMP;
697140c55d4SEric Dumazet 
69851eb7492SGerhard Engleder 		/* PTP hardware clocks can provide a free running cycle counter
69951eb7492SGerhard Engleder 		 * as a time base for virtual clocks. Tell driver to use the
70051eb7492SGerhard Engleder 		 * free running cycle counter for timestamp if socket is bound
70151eb7492SGerhard Engleder 		 * to virtual clock.
70251eb7492SGerhard Engleder 		 */
70351eb7492SGerhard Engleder 		if (tsflags & SOF_TIMESTAMPING_BIND_PHC)
70451eb7492SGerhard Engleder 			flags |= SKBTX_HW_TSTAMP_USE_CYCLES;
70551eb7492SGerhard Engleder 	}
70651eb7492SGerhard Engleder 
707c14ac945SSoheil Hassas Yeganeh 	if (tsflags & SOF_TIMESTAMPING_TX_SOFTWARE)
708140c55d4SEric Dumazet 		flags |= SKBTX_SW_TSTAMP;
709140c55d4SEric Dumazet 
710c14ac945SSoheil Hassas Yeganeh 	if (tsflags & SOF_TIMESTAMPING_TX_SCHED)
711140c55d4SEric Dumazet 		flags |= SKBTX_SCHED_TSTAMP;
712140c55d4SEric Dumazet 
713140c55d4SEric Dumazet 	*tx_flags = flags;
71420d49473SPatrick Ohly }
71567cc0d40SWillem de Bruijn EXPORT_SYMBOL(__sock_tx_timestamp);
71620d49473SPatrick Ohly 
7178c3c447bSPaolo Abeni INDIRECT_CALLABLE_DECLARE(int inet_sendmsg(struct socket *, struct msghdr *,
7188c3c447bSPaolo Abeni 					   size_t));
719a648a592SPaolo Abeni INDIRECT_CALLABLE_DECLARE(int inet6_sendmsg(struct socket *, struct msghdr *,
720a648a592SPaolo Abeni 					    size_t));
7216e6eda44SYunhui Cui 
call_trace_sock_send_length(struct sock * sk,int ret,int flags)7226e6eda44SYunhui Cui static noinline void call_trace_sock_send_length(struct sock *sk, int ret,
7236e6eda44SYunhui Cui 						 int flags)
7246e6eda44SYunhui Cui {
7256e6eda44SYunhui Cui 	trace_sock_send_length(sk, ret, 0);
7266e6eda44SYunhui Cui }
7276e6eda44SYunhui Cui 
sock_sendmsg_nosec(struct socket * sock,struct msghdr * msg)728d8725c86SAl Viro static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg)
7291da177e4SLinus Torvalds {
7301ded5e5aSEric Dumazet 	int ret = INDIRECT_CALL_INET(READ_ONCE(sock->ops)->sendmsg, inet6_sendmsg,
731a648a592SPaolo Abeni 				     inet_sendmsg, sock, msg,
732a648a592SPaolo Abeni 				     msg_data_left(msg));
733d8725c86SAl Viro 	BUG_ON(ret == -EIOCBQUEUED);
7346e6eda44SYunhui Cui 
7356e6eda44SYunhui Cui 	if (trace_sock_send_length_enabled())
7366e6eda44SYunhui Cui 		call_trace_sock_send_length(sock->sk, ret, 0);
737d8725c86SAl Viro 	return ret;
7381da177e4SLinus Torvalds }
7390cf00c6fSGu Zheng 
__sock_sendmsg(struct socket * sock,struct msghdr * msg)74086a7e0b6SJordan Rife static int __sock_sendmsg(struct socket *sock, struct msghdr *msg)
74186a7e0b6SJordan Rife {
74286a7e0b6SJordan Rife 	int err = security_socket_sendmsg(sock, msg,
74386a7e0b6SJordan Rife 					  msg_data_left(msg));
74486a7e0b6SJordan Rife 
74586a7e0b6SJordan Rife 	return err ?: sock_sendmsg_nosec(sock, msg);
74686a7e0b6SJordan Rife }
74786a7e0b6SJordan Rife 
74885806af0SRandy Dunlap /**
74985806af0SRandy Dunlap  *	sock_sendmsg - send a message through @sock
75085806af0SRandy Dunlap  *	@sock: socket
75185806af0SRandy Dunlap  *	@msg: message to send
75285806af0SRandy Dunlap  *
75385806af0SRandy Dunlap  *	Sends @msg through @sock, passing through LSM.
75485806af0SRandy Dunlap  *	Returns the number of bytes sent, or an error code.
75585806af0SRandy Dunlap  */
sock_sendmsg(struct socket * sock,struct msghdr * msg)756d8725c86SAl Viro int sock_sendmsg(struct socket *sock, struct msghdr *msg)
7570cf00c6fSGu Zheng {
75886a7e0b6SJordan Rife 	struct sockaddr_storage *save_addr = (struct sockaddr_storage *)msg->msg_name;
75986a7e0b6SJordan Rife 	struct sockaddr_storage address;
760*d5e0bb03SMarc Dionne 	int save_len = msg->msg_namelen;
76186a7e0b6SJordan Rife 	int ret;
7621b784140SYing Xue 
76386a7e0b6SJordan Rife 	if (msg->msg_name) {
76486a7e0b6SJordan Rife 		memcpy(&address, msg->msg_name, msg->msg_namelen);
76586a7e0b6SJordan Rife 		msg->msg_name = &address;
76686a7e0b6SJordan Rife 	}
76786a7e0b6SJordan Rife 
76886a7e0b6SJordan Rife 	ret = __sock_sendmsg(sock, msg);
76986a7e0b6SJordan Rife 	msg->msg_name = save_addr;
770*d5e0bb03SMarc Dionne 	msg->msg_namelen = save_len;
77186a7e0b6SJordan Rife 
77286a7e0b6SJordan Rife 	return ret;
7730cf00c6fSGu Zheng }
774c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_sendmsg);
7751da177e4SLinus Torvalds 
7768a3c245cSPedro Tammela /**
7778a3c245cSPedro Tammela  *	kernel_sendmsg - send a message through @sock (kernel-space)
7788a3c245cSPedro Tammela  *	@sock: socket
7798a3c245cSPedro Tammela  *	@msg: message header
7808a3c245cSPedro Tammela  *	@vec: kernel vec
7818a3c245cSPedro Tammela  *	@num: vec array length
7828a3c245cSPedro Tammela  *	@size: total message data size
7838a3c245cSPedro Tammela  *
7848a3c245cSPedro Tammela  *	Builds the message data with @vec and sends it through @sock.
7858a3c245cSPedro Tammela  *	Returns the number of bytes sent, or an error code.
7868a3c245cSPedro Tammela  */
7878a3c245cSPedro Tammela 
kernel_sendmsg(struct socket * sock,struct msghdr * msg,struct kvec * vec,size_t num,size_t size)7881da177e4SLinus Torvalds int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
7891da177e4SLinus Torvalds 		   struct kvec *vec, size_t num, size_t size)
7901da177e4SLinus Torvalds {
791de4eda9dSAl Viro 	iov_iter_kvec(&msg->msg_iter, ITER_SOURCE, vec, num, size);
792d8725c86SAl Viro 	return sock_sendmsg(sock, msg);
7931da177e4SLinus Torvalds }
794c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_sendmsg);
7951da177e4SLinus Torvalds 
7968a3c245cSPedro Tammela /**
7978a3c245cSPedro Tammela  *	kernel_sendmsg_locked - send a message through @sock (kernel-space)
7988a3c245cSPedro Tammela  *	@sk: sock
7998a3c245cSPedro Tammela  *	@msg: message header
8008a3c245cSPedro Tammela  *	@vec: output s/g array
8018a3c245cSPedro Tammela  *	@num: output s/g array length
8028a3c245cSPedro Tammela  *	@size: total message data size
8038a3c245cSPedro Tammela  *
8048a3c245cSPedro Tammela  *	Builds the message data with @vec and sends it through @sock.
8058a3c245cSPedro Tammela  *	Returns the number of bytes sent, or an error code.
8068a3c245cSPedro Tammela  *	Caller must hold @sk.
8078a3c245cSPedro Tammela  */
8088a3c245cSPedro Tammela 
kernel_sendmsg_locked(struct sock * sk,struct msghdr * msg,struct kvec * vec,size_t num,size_t size)809306b13ebSTom Herbert int kernel_sendmsg_locked(struct sock *sk, struct msghdr *msg,
810306b13ebSTom Herbert 			  struct kvec *vec, size_t num, size_t size)
811306b13ebSTom Herbert {
812306b13ebSTom Herbert 	struct socket *sock = sk->sk_socket;
8131ded5e5aSEric Dumazet 	const struct proto_ops *ops = READ_ONCE(sock->ops);
814306b13ebSTom Herbert 
8151ded5e5aSEric Dumazet 	if (!ops->sendmsg_locked)
816db5980d8SJohn Fastabend 		return sock_no_sendmsg_locked(sk, msg, size);
817306b13ebSTom Herbert 
818de4eda9dSAl Viro 	iov_iter_kvec(&msg->msg_iter, ITER_SOURCE, vec, num, size);
819306b13ebSTom Herbert 
8201ded5e5aSEric Dumazet 	return ops->sendmsg_locked(sk, msg, msg_data_left(msg));
821306b13ebSTom Herbert }
822306b13ebSTom Herbert EXPORT_SYMBOL(kernel_sendmsg_locked);
823306b13ebSTom Herbert 
skb_is_err_queue(const struct sk_buff * skb)8248605330aSSoheil Hassas Yeganeh static bool skb_is_err_queue(const struct sk_buff *skb)
8258605330aSSoheil Hassas Yeganeh {
8268605330aSSoheil Hassas Yeganeh 	/* pkt_type of skbs enqueued on the error queue are set to
8278605330aSSoheil Hassas Yeganeh 	 * PACKET_OUTGOING in skb_set_err_queue(). This is only safe to do
8288605330aSSoheil Hassas Yeganeh 	 * in recvmsg, since skbs received on a local socket will never
8298605330aSSoheil Hassas Yeganeh 	 * have a pkt_type of PACKET_OUTGOING.
8308605330aSSoheil Hassas Yeganeh 	 */
8318605330aSSoheil Hassas Yeganeh 	return skb->pkt_type == PACKET_OUTGOING;
8328605330aSSoheil Hassas Yeganeh }
8338605330aSSoheil Hassas Yeganeh 
834b50a5c70SMiroslav Lichvar /* On transmit, software and hardware timestamps are returned independently.
835b50a5c70SMiroslav Lichvar  * As the two skb clones share the hardware timestamp, which may be updated
836b50a5c70SMiroslav Lichvar  * before the software timestamp is received, a hardware TX timestamp may be
837b50a5c70SMiroslav Lichvar  * returned only if there is no software TX timestamp. Ignore false software
838b50a5c70SMiroslav Lichvar  * timestamps, which may be made in the __sock_recv_timestamp() call when the
8397f1bc6e9SDeepa Dinamani  * option SO_TIMESTAMP_OLD(NS) is enabled on the socket, even when the skb has a
840b50a5c70SMiroslav Lichvar  * hardware timestamp.
841b50a5c70SMiroslav Lichvar  */
skb_is_swtx_tstamp(const struct sk_buff * skb,int false_tstamp)842b50a5c70SMiroslav Lichvar static bool skb_is_swtx_tstamp(const struct sk_buff *skb, int false_tstamp)
843b50a5c70SMiroslav Lichvar {
844b50a5c70SMiroslav Lichvar 	return skb->tstamp && !false_tstamp && skb_is_err_queue(skb);
845b50a5c70SMiroslav Lichvar }
846b50a5c70SMiroslav Lichvar 
get_timestamp(struct sock * sk,struct sk_buff * skb,int * if_index)84797dc7cd9SGerhard Engleder static ktime_t get_timestamp(struct sock *sk, struct sk_buff *skb, int *if_index)
84897dc7cd9SGerhard Engleder {
849e3390b30SEric Dumazet 	bool cycles = READ_ONCE(sk->sk_tsflags) & SOF_TIMESTAMPING_BIND_PHC;
85097dc7cd9SGerhard Engleder 	struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
85197dc7cd9SGerhard Engleder 	struct net_device *orig_dev;
85297dc7cd9SGerhard Engleder 	ktime_t hwtstamp;
85397dc7cd9SGerhard Engleder 
85497dc7cd9SGerhard Engleder 	rcu_read_lock();
85597dc7cd9SGerhard Engleder 	orig_dev = dev_get_by_napi_id(skb_napi_id(skb));
85697dc7cd9SGerhard Engleder 	if (orig_dev) {
85797dc7cd9SGerhard Engleder 		*if_index = orig_dev->ifindex;
85897dc7cd9SGerhard Engleder 		hwtstamp = netdev_get_tstamp(orig_dev, shhwtstamps, cycles);
85997dc7cd9SGerhard Engleder 	} else {
86097dc7cd9SGerhard Engleder 		hwtstamp = shhwtstamps->hwtstamp;
86197dc7cd9SGerhard Engleder 	}
86297dc7cd9SGerhard Engleder 	rcu_read_unlock();
86397dc7cd9SGerhard Engleder 
86497dc7cd9SGerhard Engleder 	return hwtstamp;
86597dc7cd9SGerhard Engleder }
86697dc7cd9SGerhard Engleder 
put_ts_pktinfo(struct msghdr * msg,struct sk_buff * skb,int if_index)86797dc7cd9SGerhard Engleder static void put_ts_pktinfo(struct msghdr *msg, struct sk_buff *skb,
86897dc7cd9SGerhard Engleder 			   int if_index)
869aad9c8c4SMiroslav Lichvar {
870aad9c8c4SMiroslav Lichvar 	struct scm_ts_pktinfo ts_pktinfo;
871aad9c8c4SMiroslav Lichvar 	struct net_device *orig_dev;
872aad9c8c4SMiroslav Lichvar 
873aad9c8c4SMiroslav Lichvar 	if (!skb_mac_header_was_set(skb))
874aad9c8c4SMiroslav Lichvar 		return;
875aad9c8c4SMiroslav Lichvar 
876aad9c8c4SMiroslav Lichvar 	memset(&ts_pktinfo, 0, sizeof(ts_pktinfo));
877aad9c8c4SMiroslav Lichvar 
87897dc7cd9SGerhard Engleder 	if (!if_index) {
879aad9c8c4SMiroslav Lichvar 		rcu_read_lock();
880aad9c8c4SMiroslav Lichvar 		orig_dev = dev_get_by_napi_id(skb_napi_id(skb));
881aad9c8c4SMiroslav Lichvar 		if (orig_dev)
88297dc7cd9SGerhard Engleder 			if_index = orig_dev->ifindex;
883aad9c8c4SMiroslav Lichvar 		rcu_read_unlock();
88497dc7cd9SGerhard Engleder 	}
88597dc7cd9SGerhard Engleder 	ts_pktinfo.if_index = if_index;
886aad9c8c4SMiroslav Lichvar 
887aad9c8c4SMiroslav Lichvar 	ts_pktinfo.pkt_length = skb->len - skb_mac_offset(skb);
888aad9c8c4SMiroslav Lichvar 	put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_PKTINFO,
889aad9c8c4SMiroslav Lichvar 		 sizeof(ts_pktinfo), &ts_pktinfo);
890aad9c8c4SMiroslav Lichvar }
891aad9c8c4SMiroslav Lichvar 
89292f37fd2SEric Dumazet /*
89392f37fd2SEric Dumazet  * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
89492f37fd2SEric Dumazet  */
__sock_recv_timestamp(struct msghdr * msg,struct sock * sk,struct sk_buff * skb)89592f37fd2SEric Dumazet void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
89692f37fd2SEric Dumazet 	struct sk_buff *skb)
89792f37fd2SEric Dumazet {
89820d49473SPatrick Ohly 	int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
899887feae3SDeepa Dinamani 	int new_tstamp = sock_flag(sk, SOCK_TSTAMP_NEW);
9009718475eSDeepa Dinamani 	struct scm_timestamping_internal tss;
901b50a5c70SMiroslav Lichvar 	int empty = 1, false_tstamp = 0;
90220d49473SPatrick Ohly 	struct skb_shared_hwtstamps *shhwtstamps =
90320d49473SPatrick Ohly 		skb_hwtstamps(skb);
90497dc7cd9SGerhard Engleder 	int if_index;
905007747a9SMiroslav Lichvar 	ktime_t hwtstamp;
906e3390b30SEric Dumazet 	u32 tsflags;
90792f37fd2SEric Dumazet 
90820d49473SPatrick Ohly 	/* Race occurred between timestamp enabling and packet
90920d49473SPatrick Ohly 	   receiving.  Fill in the current time for now. */
910b50a5c70SMiroslav Lichvar 	if (need_software_tstamp && skb->tstamp == 0) {
91120d49473SPatrick Ohly 		__net_timestamp(skb);
912b50a5c70SMiroslav Lichvar 		false_tstamp = 1;
913b50a5c70SMiroslav Lichvar 	}
91420d49473SPatrick Ohly 
91520d49473SPatrick Ohly 	if (need_software_tstamp) {
91692f37fd2SEric Dumazet 		if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
917887feae3SDeepa Dinamani 			if (new_tstamp) {
918887feae3SDeepa Dinamani 				struct __kernel_sock_timeval tv;
919887feae3SDeepa Dinamani 
920887feae3SDeepa Dinamani 				skb_get_new_timestamp(skb, &tv);
921887feae3SDeepa Dinamani 				put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_NEW,
922887feae3SDeepa Dinamani 					 sizeof(tv), &tv);
923887feae3SDeepa Dinamani 			} else {
92413c6ee2aSDeepa Dinamani 				struct __kernel_old_timeval tv;
925887feae3SDeepa Dinamani 
92620d49473SPatrick Ohly 				skb_get_timestamp(skb, &tv);
9277f1bc6e9SDeepa Dinamani 				put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_OLD,
92820d49473SPatrick Ohly 					 sizeof(tv), &tv);
929887feae3SDeepa Dinamani 			}
930887feae3SDeepa Dinamani 		} else {
931887feae3SDeepa Dinamani 			if (new_tstamp) {
932887feae3SDeepa Dinamani 				struct __kernel_timespec ts;
933887feae3SDeepa Dinamani 
934887feae3SDeepa Dinamani 				skb_get_new_timestampns(skb, &ts);
935887feae3SDeepa Dinamani 				put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_NEW,
936887feae3SDeepa Dinamani 					 sizeof(ts), &ts);
93792f37fd2SEric Dumazet 			} else {
938df1b4ba9SArnd Bergmann 				struct __kernel_old_timespec ts;
939887feae3SDeepa Dinamani 
940f24b9be5SWillem de Bruijn 				skb_get_timestampns(skb, &ts);
9417f1bc6e9SDeepa Dinamani 				put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_OLD,
942f24b9be5SWillem de Bruijn 					 sizeof(ts), &ts);
94392f37fd2SEric Dumazet 			}
94492f37fd2SEric Dumazet 		}
945887feae3SDeepa Dinamani 	}
94692f37fd2SEric Dumazet 
947f24b9be5SWillem de Bruijn 	memset(&tss, 0, sizeof(tss));
948e3390b30SEric Dumazet 	tsflags = READ_ONCE(sk->sk_tsflags);
949e3390b30SEric Dumazet 	if ((tsflags & SOF_TIMESTAMPING_SOFTWARE) &&
9509718475eSDeepa Dinamani 	    ktime_to_timespec64_cond(skb->tstamp, tss.ts + 0))
95120d49473SPatrick Ohly 		empty = 0;
9524d276eb6SWillem de Bruijn 	if (shhwtstamps &&
953e3390b30SEric Dumazet 	    (tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
954d7c08826SYangbo Lu 	    !skb_is_swtx_tstamp(skb, false_tstamp)) {
95597dc7cd9SGerhard Engleder 		if_index = 0;
95697dc7cd9SGerhard Engleder 		if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP_NETDEV)
95797dc7cd9SGerhard Engleder 			hwtstamp = get_timestamp(sk, skb, &if_index);
958007747a9SMiroslav Lichvar 		else
959007747a9SMiroslav Lichvar 			hwtstamp = shhwtstamps->hwtstamp;
960d7c08826SYangbo Lu 
961e3390b30SEric Dumazet 		if (tsflags & SOF_TIMESTAMPING_BIND_PHC)
96297dc7cd9SGerhard Engleder 			hwtstamp = ptp_convert_timestamp(&hwtstamp,
963251cd405SEric Dumazet 							 READ_ONCE(sk->sk_bind_phc));
96497dc7cd9SGerhard Engleder 
965007747a9SMiroslav Lichvar 		if (ktime_to_timespec64_cond(hwtstamp, tss.ts + 2)) {
96620d49473SPatrick Ohly 			empty = 0;
967d7c08826SYangbo Lu 
968e3390b30SEric Dumazet 			if ((tsflags & SOF_TIMESTAMPING_OPT_PKTINFO) &&
969aad9c8c4SMiroslav Lichvar 			    !skb_is_err_queue(skb))
97097dc7cd9SGerhard Engleder 				put_ts_pktinfo(msg, skb, if_index);
971aad9c8c4SMiroslav Lichvar 		}
972d7c08826SYangbo Lu 	}
9731c885808SFrancis Yan 	if (!empty) {
9749718475eSDeepa Dinamani 		if (sock_flag(sk, SOCK_TSTAMP_NEW))
9759718475eSDeepa Dinamani 			put_cmsg_scm_timestamping64(msg, &tss);
9769718475eSDeepa Dinamani 		else
9779718475eSDeepa Dinamani 			put_cmsg_scm_timestamping(msg, &tss);
9781c885808SFrancis Yan 
9798605330aSSoheil Hassas Yeganeh 		if (skb_is_err_queue(skb) && skb->len &&
9804ef1b286SSoheil Hassas Yeganeh 		    SKB_EXT_ERR(skb)->opt_stats)
9811c885808SFrancis Yan 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_OPT_STATS,
9821c885808SFrancis Yan 				 skb->len, skb->data);
9831c885808SFrancis Yan 	}
98420d49473SPatrick Ohly }
9857c81fd8bSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
9867c81fd8bSArnaldo Carvalho de Melo 
987eb6fba75SJakub Kicinski #ifdef CONFIG_WIRELESS
__sock_recv_wifi_status(struct msghdr * msg,struct sock * sk,struct sk_buff * skb)9886e3e939fSJohannes Berg void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
9896e3e939fSJohannes Berg 	struct sk_buff *skb)
9906e3e939fSJohannes Berg {
9916e3e939fSJohannes Berg 	int ack;
9926e3e939fSJohannes Berg 
9936e3e939fSJohannes Berg 	if (!sock_flag(sk, SOCK_WIFI_STATUS))
9946e3e939fSJohannes Berg 		return;
9956e3e939fSJohannes Berg 	if (!skb->wifi_acked_valid)
9966e3e939fSJohannes Berg 		return;
9976e3e939fSJohannes Berg 
9986e3e939fSJohannes Berg 	ack = skb->wifi_acked;
9996e3e939fSJohannes Berg 
10006e3e939fSJohannes Berg 	put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack);
10016e3e939fSJohannes Berg }
10026e3e939fSJohannes Berg EXPORT_SYMBOL_GPL(__sock_recv_wifi_status);
1003eb6fba75SJakub Kicinski #endif
10046e3e939fSJohannes Berg 
sock_recv_drops(struct msghdr * msg,struct sock * sk,struct sk_buff * skb)100511165f14Sstephen hemminger static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk,
100611165f14Sstephen hemminger 				   struct sk_buff *skb)
10073b885787SNeil Horman {
1008744d5a3eSEyal Birger 	if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && SOCK_SKB_CB(skb)->dropcount)
10093b885787SNeil Horman 		put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL,
1010744d5a3eSEyal Birger 			sizeof(__u32), &SOCK_SKB_CB(skb)->dropcount);
10113b885787SNeil Horman }
10123b885787SNeil Horman 
sock_recv_mark(struct msghdr * msg,struct sock * sk,struct sk_buff * skb)10136fd1d51cSErin MacNeil static void sock_recv_mark(struct msghdr *msg, struct sock *sk,
10146fd1d51cSErin MacNeil 			   struct sk_buff *skb)
10156fd1d51cSErin MacNeil {
10162558b803SEric Dumazet 	if (sock_flag(sk, SOCK_RCVMARK) && skb) {
10172558b803SEric Dumazet 		/* We must use a bounce buffer for CONFIG_HARDENED_USERCOPY=y */
10182558b803SEric Dumazet 		__u32 mark = skb->mark;
10192558b803SEric Dumazet 
10202558b803SEric Dumazet 		put_cmsg(msg, SOL_SOCKET, SO_MARK, sizeof(__u32), &mark);
10212558b803SEric Dumazet 	}
10226fd1d51cSErin MacNeil }
10236fd1d51cSErin MacNeil 
__sock_recv_cmsgs(struct msghdr * msg,struct sock * sk,struct sk_buff * skb)10246fd1d51cSErin MacNeil void __sock_recv_cmsgs(struct msghdr *msg, struct sock *sk,
10253b885787SNeil Horman 		       struct sk_buff *skb)
10263b885787SNeil Horman {
10273b885787SNeil Horman 	sock_recv_timestamp(msg, sk, skb);
10283b885787SNeil Horman 	sock_recv_drops(msg, sk, skb);
10296fd1d51cSErin MacNeil 	sock_recv_mark(msg, sk, skb);
10303b885787SNeil Horman }
10316fd1d51cSErin MacNeil EXPORT_SYMBOL_GPL(__sock_recv_cmsgs);
10323b885787SNeil Horman 
10338c3c447bSPaolo Abeni INDIRECT_CALLABLE_DECLARE(int inet_recvmsg(struct socket *, struct msghdr *,
10348c3c447bSPaolo Abeni 					   size_t, int));
1035a648a592SPaolo Abeni INDIRECT_CALLABLE_DECLARE(int inet6_recvmsg(struct socket *, struct msghdr *,
1036a648a592SPaolo Abeni 					    size_t, int));
10376e6eda44SYunhui Cui 
call_trace_sock_recv_length(struct sock * sk,int ret,int flags)10386e6eda44SYunhui Cui static noinline void call_trace_sock_recv_length(struct sock *sk, int ret, int flags)
10396e6eda44SYunhui Cui {
10406e6eda44SYunhui Cui 	trace_sock_recv_length(sk, ret, flags);
10416e6eda44SYunhui Cui }
10426e6eda44SYunhui Cui 
sock_recvmsg_nosec(struct socket * sock,struct msghdr * msg,int flags)10431b784140SYing Xue static inline int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
10441b784140SYing Xue 				     int flags)
1045a2e27255SArnaldo Carvalho de Melo {
10461ded5e5aSEric Dumazet 	int ret = INDIRECT_CALL_INET(READ_ONCE(sock->ops)->recvmsg,
10471ded5e5aSEric Dumazet 				     inet6_recvmsg,
10486e6eda44SYunhui Cui 				     inet_recvmsg, sock, msg,
10496e6eda44SYunhui Cui 				     msg_data_left(msg), flags);
10506e6eda44SYunhui Cui 	if (trace_sock_recv_length_enabled())
10516e6eda44SYunhui Cui 		call_trace_sock_recv_length(sock->sk, ret, flags);
10526e6eda44SYunhui Cui 	return ret;
10532da62906SAl Viro }
1054a2e27255SArnaldo Carvalho de Melo 
105585806af0SRandy Dunlap /**
105685806af0SRandy Dunlap  *	sock_recvmsg - receive a message from @sock
105785806af0SRandy Dunlap  *	@sock: socket
105885806af0SRandy Dunlap  *	@msg: message to receive
105985806af0SRandy Dunlap  *	@flags: message flags
106085806af0SRandy Dunlap  *
106185806af0SRandy Dunlap  *	Receives @msg from @sock, passing through LSM. Returns the total number
106285806af0SRandy Dunlap  *	of bytes received, or an error.
106385806af0SRandy Dunlap  */
sock_recvmsg(struct socket * sock,struct msghdr * msg,int flags)10642da62906SAl Viro int sock_recvmsg(struct socket *sock, struct msghdr *msg, int flags)
10652da62906SAl Viro {
10662da62906SAl Viro 	int err = security_socket_recvmsg(sock, msg, msg_data_left(msg), flags);
10672da62906SAl Viro 
10682da62906SAl Viro 	return err ?: sock_recvmsg_nosec(sock, msg, flags);
10691da177e4SLinus Torvalds }
1070c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_recvmsg);
10711da177e4SLinus Torvalds 
1072c1249c0aSMartin Lucina /**
1073c1249c0aSMartin Lucina  *	kernel_recvmsg - Receive a message from a socket (kernel space)
1074c1249c0aSMartin Lucina  *	@sock: The socket to receive the message from
1075c1249c0aSMartin Lucina  *	@msg: Received message
1076c1249c0aSMartin Lucina  *	@vec: Input s/g array for message data
1077c1249c0aSMartin Lucina  *	@num: Size of input s/g array
1078c1249c0aSMartin Lucina  *	@size: Number of bytes to read
1079c1249c0aSMartin Lucina  *	@flags: Message flags (MSG_DONTWAIT, etc...)
1080c1249c0aSMartin Lucina  *
1081c1249c0aSMartin Lucina  *	On return the msg structure contains the scatter/gather array passed in the
1082c1249c0aSMartin Lucina  *	vec argument. The array is modified so that it consists of the unfilled
1083c1249c0aSMartin Lucina  *	portion of the original array.
1084c1249c0aSMartin Lucina  *
1085c1249c0aSMartin Lucina  *	The returned value is the total number of bytes received, or an error.
1086c1249c0aSMartin Lucina  */
10878a3c245cSPedro Tammela 
kernel_recvmsg(struct socket * sock,struct msghdr * msg,struct kvec * vec,size_t num,size_t size,int flags)10881da177e4SLinus Torvalds int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
108989bddce5SStephen Hemminger 		   struct kvec *vec, size_t num, size_t size, int flags)
10901da177e4SLinus Torvalds {
10911f466e1fSChristoph Hellwig 	msg->msg_control_is_user = false;
1092de4eda9dSAl Viro 	iov_iter_kvec(&msg->msg_iter, ITER_DEST, vec, num, size);
10931f466e1fSChristoph Hellwig 	return sock_recvmsg(sock, msg, flags);
10941da177e4SLinus Torvalds }
1095c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_recvmsg);
10961da177e4SLinus Torvalds 
sock_splice_read(struct file * file,loff_t * ppos,struct pipe_inode_info * pipe,size_t len,unsigned int flags)10979c55e01cSJens Axboe static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
10989c55e01cSJens Axboe 				struct pipe_inode_info *pipe, size_t len,
10999c55e01cSJens Axboe 				unsigned int flags)
11009c55e01cSJens Axboe {
11019c55e01cSJens Axboe 	struct socket *sock = file->private_data;
11021ded5e5aSEric Dumazet 	const struct proto_ops *ops;
11039c55e01cSJens Axboe 
11041ded5e5aSEric Dumazet 	ops = READ_ONCE(sock->ops);
11051ded5e5aSEric Dumazet 	if (unlikely(!ops->splice_read))
110667178fd0SDavid Howells 		return copy_splice_read(file, ppos, pipe, len, flags);
1107997b37daSRémi Denis-Courmont 
11081ded5e5aSEric Dumazet 	return ops->splice_read(sock, ppos, pipe, len, flags);
11099c55e01cSJens Axboe }
11109c55e01cSJens Axboe 
sock_splice_eof(struct file * file)11112bfc6685SDavid Howells static void sock_splice_eof(struct file *file)
11122bfc6685SDavid Howells {
11132bfc6685SDavid Howells 	struct socket *sock = file->private_data;
11141ded5e5aSEric Dumazet 	const struct proto_ops *ops;
11152bfc6685SDavid Howells 
11161ded5e5aSEric Dumazet 	ops = READ_ONCE(sock->ops);
11171ded5e5aSEric Dumazet 	if (ops->splice_eof)
11181ded5e5aSEric Dumazet 		ops->splice_eof(sock);
11192bfc6685SDavid Howells }
11202bfc6685SDavid Howells 
sock_read_iter(struct kiocb * iocb,struct iov_iter * to)11218ae5e030SAl Viro static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to)
1122ce1d4d3eSChristoph Hellwig {
11236d652330SAl Viro 	struct file *file = iocb->ki_filp;
11246d652330SAl Viro 	struct socket *sock = file->private_data;
11250345f931Stadeusz.struk@intel.com 	struct msghdr msg = {.msg_iter = *to,
11260345f931Stadeusz.struk@intel.com 			     .msg_iocb = iocb};
11278ae5e030SAl Viro 	ssize_t res;
1128ce1d4d3eSChristoph Hellwig 
1129ebfcd895SJens Axboe 	if (file->f_flags & O_NONBLOCK || (iocb->ki_flags & IOCB_NOWAIT))
11308ae5e030SAl Viro 		msg.msg_flags = MSG_DONTWAIT;
11318ae5e030SAl Viro 
11328ae5e030SAl Viro 	if (iocb->ki_pos != 0)
1133ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
1134027445c3SBadari Pulavarty 
113566ee59afSChristoph Hellwig 	if (!iov_iter_count(to))	/* Match SYS5 behaviour */
1136ce1d4d3eSChristoph Hellwig 		return 0;
1137ce1d4d3eSChristoph Hellwig 
11382da62906SAl Viro 	res = sock_recvmsg(sock, &msg, msg.msg_flags);
11398ae5e030SAl Viro 	*to = msg.msg_iter;
11408ae5e030SAl Viro 	return res;
1141ce1d4d3eSChristoph Hellwig }
1142ce1d4d3eSChristoph Hellwig 
sock_write_iter(struct kiocb * iocb,struct iov_iter * from)11438ae5e030SAl Viro static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from)
11441da177e4SLinus Torvalds {
11456d652330SAl Viro 	struct file *file = iocb->ki_filp;
11466d652330SAl Viro 	struct socket *sock = file->private_data;
11470345f931Stadeusz.struk@intel.com 	struct msghdr msg = {.msg_iter = *from,
11480345f931Stadeusz.struk@intel.com 			     .msg_iocb = iocb};
11498ae5e030SAl Viro 	ssize_t res;
11501da177e4SLinus Torvalds 
11518ae5e030SAl Viro 	if (iocb->ki_pos != 0)
1152ce1d4d3eSChristoph Hellwig 		return -ESPIPE;
1153027445c3SBadari Pulavarty 
1154ebfcd895SJens Axboe 	if (file->f_flags & O_NONBLOCK || (iocb->ki_flags & IOCB_NOWAIT))
11558ae5e030SAl Viro 		msg.msg_flags = MSG_DONTWAIT;
11568ae5e030SAl Viro 
11576d652330SAl Viro 	if (sock->type == SOCK_SEQPACKET)
11586d652330SAl Viro 		msg.msg_flags |= MSG_EOR;
11596d652330SAl Viro 
116086a7e0b6SJordan Rife 	res = __sock_sendmsg(sock, &msg);
11618ae5e030SAl Viro 	*from = msg.msg_iter;
11628ae5e030SAl Viro 	return res;
11631da177e4SLinus Torvalds }
11641da177e4SLinus Torvalds 
11651da177e4SLinus Torvalds /*
11661da177e4SLinus Torvalds  * Atomic setting of ioctl hooks to avoid race
11671da177e4SLinus Torvalds  * with module unload.
11681da177e4SLinus Torvalds  */
11691da177e4SLinus Torvalds 
11704a3e2f71SArjan van de Ven static DEFINE_MUTEX(br_ioctl_mutex);
1171ad2f99aeSArnd Bergmann static int (*br_ioctl_hook)(struct net *net, struct net_bridge *br,
1172ad2f99aeSArnd Bergmann 			    unsigned int cmd, struct ifreq *ifr,
1173ad2f99aeSArnd Bergmann 			    void __user *uarg);
11741da177e4SLinus Torvalds 
brioctl_set(int (* hook)(struct net * net,struct net_bridge * br,unsigned int cmd,struct ifreq * ifr,void __user * uarg))1175ad2f99aeSArnd Bergmann void brioctl_set(int (*hook)(struct net *net, struct net_bridge *br,
1176ad2f99aeSArnd Bergmann 			     unsigned int cmd, struct ifreq *ifr,
1177ad2f99aeSArnd Bergmann 			     void __user *uarg))
11781da177e4SLinus Torvalds {
11794a3e2f71SArjan van de Ven 	mutex_lock(&br_ioctl_mutex);
11801da177e4SLinus Torvalds 	br_ioctl_hook = hook;
11814a3e2f71SArjan van de Ven 	mutex_unlock(&br_ioctl_mutex);
11821da177e4SLinus Torvalds }
11831da177e4SLinus Torvalds EXPORT_SYMBOL(brioctl_set);
11841da177e4SLinus Torvalds 
br_ioctl_call(struct net * net,struct net_bridge * br,unsigned int cmd,struct ifreq * ifr,void __user * uarg)1185ad2f99aeSArnd Bergmann int br_ioctl_call(struct net *net, struct net_bridge *br, unsigned int cmd,
1186ad2f99aeSArnd Bergmann 		  struct ifreq *ifr, void __user *uarg)
1187ad2f99aeSArnd Bergmann {
1188ad2f99aeSArnd Bergmann 	int err = -ENOPKG;
1189ad2f99aeSArnd Bergmann 
1190ad2f99aeSArnd Bergmann 	if (!br_ioctl_hook)
1191ad2f99aeSArnd Bergmann 		request_module("bridge");
1192ad2f99aeSArnd Bergmann 
1193ad2f99aeSArnd Bergmann 	mutex_lock(&br_ioctl_mutex);
1194ad2f99aeSArnd Bergmann 	if (br_ioctl_hook)
1195ad2f99aeSArnd Bergmann 		err = br_ioctl_hook(net, br, cmd, ifr, uarg);
1196ad2f99aeSArnd Bergmann 	mutex_unlock(&br_ioctl_mutex);
1197ad2f99aeSArnd Bergmann 
1198ad2f99aeSArnd Bergmann 	return err;
1199ad2f99aeSArnd Bergmann }
1200ad2f99aeSArnd Bergmann 
12014a3e2f71SArjan van de Ven static DEFINE_MUTEX(vlan_ioctl_mutex);
1202881d966bSEric W. Biederman static int (*vlan_ioctl_hook) (struct net *, void __user *arg);
12031da177e4SLinus Torvalds 
vlan_ioctl_set(int (* hook)(struct net *,void __user *))1204881d966bSEric W. Biederman void vlan_ioctl_set(int (*hook) (struct net *, void __user *))
12051da177e4SLinus Torvalds {
12064a3e2f71SArjan van de Ven 	mutex_lock(&vlan_ioctl_mutex);
12071da177e4SLinus Torvalds 	vlan_ioctl_hook = hook;
12084a3e2f71SArjan van de Ven 	mutex_unlock(&vlan_ioctl_mutex);
12091da177e4SLinus Torvalds }
12101da177e4SLinus Torvalds EXPORT_SYMBOL(vlan_ioctl_set);
12111da177e4SLinus Torvalds 
sock_do_ioctl(struct net * net,struct socket * sock,unsigned int cmd,unsigned long arg)12126b96018bSArnd Bergmann static long sock_do_ioctl(struct net *net, struct socket *sock,
121363ff03abSJohannes Berg 			  unsigned int cmd, unsigned long arg)
12146b96018bSArnd Bergmann {
12151ded5e5aSEric Dumazet 	const struct proto_ops *ops = READ_ONCE(sock->ops);
1216876f0bf9SArnd Bergmann 	struct ifreq ifr;
1217876f0bf9SArnd Bergmann 	bool need_copyout;
12186b96018bSArnd Bergmann 	int err;
12196b96018bSArnd Bergmann 	void __user *argp = (void __user *)arg;
1220a554bf96SArnd Bergmann 	void __user *data;
12216b96018bSArnd Bergmann 
12221ded5e5aSEric Dumazet 	err = ops->ioctl(sock, cmd, arg);
12236b96018bSArnd Bergmann 
12246b96018bSArnd Bergmann 	/*
12256b96018bSArnd Bergmann 	 * If this ioctl is unknown try to hand it down
12266b96018bSArnd Bergmann 	 * to the NIC driver.
12276b96018bSArnd Bergmann 	 */
122836fd633eSAl Viro 	if (err != -ENOIOCTLCMD)
12296b96018bSArnd Bergmann 		return err;
12306b96018bSArnd Bergmann 
123129ce8f97SJakub Kicinski 	if (!is_socket_ioctl_cmd(cmd))
123229ce8f97SJakub Kicinski 		return -ENOTTY;
123329ce8f97SJakub Kicinski 
1234a554bf96SArnd Bergmann 	if (get_user_ifreq(&ifr, &data, argp))
123536fd633eSAl Viro 		return -EFAULT;
1236a554bf96SArnd Bergmann 	err = dev_ioctl(net, cmd, &ifr, data, &need_copyout);
123744c02a2cSAl Viro 	if (!err && need_copyout)
1238a554bf96SArnd Bergmann 		if (put_user_ifreq(&ifr, argp))
123944c02a2cSAl Viro 			return -EFAULT;
1240876f0bf9SArnd Bergmann 
12416b96018bSArnd Bergmann 	return err;
12426b96018bSArnd Bergmann }
12436b96018bSArnd Bergmann 
12441da177e4SLinus Torvalds /*
12451da177e4SLinus Torvalds  *	With an ioctl, arg may well be a user mode pointer, but we don't know
12461da177e4SLinus Torvalds  *	what to do with it - that's up to the protocol still.
12471da177e4SLinus Torvalds  */
12481da177e4SLinus Torvalds 
sock_ioctl(struct file * file,unsigned cmd,unsigned long arg)12491da177e4SLinus Torvalds static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
12501da177e4SLinus Torvalds {
12511ded5e5aSEric Dumazet 	const struct proto_ops  *ops;
12521da177e4SLinus Torvalds 	struct socket *sock;
1253881d966bSEric W. Biederman 	struct sock *sk;
12541da177e4SLinus Torvalds 	void __user *argp = (void __user *)arg;
12551da177e4SLinus Torvalds 	int pid, err;
1256881d966bSEric W. Biederman 	struct net *net;
12571da177e4SLinus Torvalds 
1258b69aee04SEric Dumazet 	sock = file->private_data;
12591ded5e5aSEric Dumazet 	ops = READ_ONCE(sock->ops);
1260881d966bSEric W. Biederman 	sk = sock->sk;
12613b1e0a65SYOSHIFUJI Hideaki 	net = sock_net(sk);
126244c02a2cSAl Viro 	if (unlikely(cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))) {
126344c02a2cSAl Viro 		struct ifreq ifr;
1264a554bf96SArnd Bergmann 		void __user *data;
126544c02a2cSAl Viro 		bool need_copyout;
1266a554bf96SArnd Bergmann 		if (get_user_ifreq(&ifr, &data, argp))
126744c02a2cSAl Viro 			return -EFAULT;
1268a554bf96SArnd Bergmann 		err = dev_ioctl(net, cmd, &ifr, data, &need_copyout);
126944c02a2cSAl Viro 		if (!err && need_copyout)
1270a554bf96SArnd Bergmann 			if (put_user_ifreq(&ifr, argp))
127144c02a2cSAl Viro 				return -EFAULT;
12721da177e4SLinus Torvalds 	} else
12733d23e349SJohannes Berg #ifdef CONFIG_WEXT_CORE
12741da177e4SLinus Torvalds 	if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
1275b1b0c245SAl Viro 		err = wext_handle_ioctl(net, cmd, argp);
12761da177e4SLinus Torvalds 	} else
12773d23e349SJohannes Berg #endif
12781da177e4SLinus Torvalds 		switch (cmd) {
12791da177e4SLinus Torvalds 		case FIOSETOWN:
12801da177e4SLinus Torvalds 		case SIOCSPGRP:
12811da177e4SLinus Torvalds 			err = -EFAULT;
12821da177e4SLinus Torvalds 			if (get_user(pid, (int __user *)argp))
12831da177e4SLinus Torvalds 				break;
1284393cc3f5SJiri Slaby 			err = f_setown(sock->file, pid, 1);
12851da177e4SLinus Torvalds 			break;
12861da177e4SLinus Torvalds 		case FIOGETOWN:
12871da177e4SLinus Torvalds 		case SIOCGPGRP:
1288609d7fa9SEric W. Biederman 			err = put_user(f_getown(sock->file),
128989bddce5SStephen Hemminger 				       (int __user *)argp);
12901da177e4SLinus Torvalds 			break;
12911da177e4SLinus Torvalds 		case SIOCGIFBR:
12921da177e4SLinus Torvalds 		case SIOCSIFBR:
12931da177e4SLinus Torvalds 		case SIOCBRADDBR:
12941da177e4SLinus Torvalds 		case SIOCBRDELBR:
1295ad2f99aeSArnd Bergmann 			err = br_ioctl_call(net, NULL, cmd, NULL, argp);
12961da177e4SLinus Torvalds 			break;
12971da177e4SLinus Torvalds 		case SIOCGIFVLAN:
12981da177e4SLinus Torvalds 		case SIOCSIFVLAN:
12991da177e4SLinus Torvalds 			err = -ENOPKG;
13001da177e4SLinus Torvalds 			if (!vlan_ioctl_hook)
13011da177e4SLinus Torvalds 				request_module("8021q");
13021da177e4SLinus Torvalds 
13034a3e2f71SArjan van de Ven 			mutex_lock(&vlan_ioctl_mutex);
13041da177e4SLinus Torvalds 			if (vlan_ioctl_hook)
1305881d966bSEric W. Biederman 				err = vlan_ioctl_hook(net, argp);
13064a3e2f71SArjan van de Ven 			mutex_unlock(&vlan_ioctl_mutex);
13071da177e4SLinus Torvalds 			break;
1308c62cce2cSAndrey Vagin 		case SIOCGSKNS:
1309c62cce2cSAndrey Vagin 			err = -EPERM;
1310c62cce2cSAndrey Vagin 			if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
1311c62cce2cSAndrey Vagin 				break;
1312c62cce2cSAndrey Vagin 
1313c62cce2cSAndrey Vagin 			err = open_related_ns(&net->ns, get_net_ns);
1314c62cce2cSAndrey Vagin 			break;
13150768e170SArnd Bergmann 		case SIOCGSTAMP_OLD:
13160768e170SArnd Bergmann 		case SIOCGSTAMPNS_OLD:
13171ded5e5aSEric Dumazet 			if (!ops->gettstamp) {
1318c7cbdbf2SArnd Bergmann 				err = -ENOIOCTLCMD;
1319c7cbdbf2SArnd Bergmann 				break;
1320c7cbdbf2SArnd Bergmann 			}
13211ded5e5aSEric Dumazet 			err = ops->gettstamp(sock, argp,
13220768e170SArnd Bergmann 					     cmd == SIOCGSTAMP_OLD,
13230768e170SArnd Bergmann 					     !IS_ENABLED(CONFIG_64BIT));
132460747828SGustavo A. R. Silva 			break;
13250768e170SArnd Bergmann 		case SIOCGSTAMP_NEW:
13260768e170SArnd Bergmann 		case SIOCGSTAMPNS_NEW:
13271ded5e5aSEric Dumazet 			if (!ops->gettstamp) {
13280768e170SArnd Bergmann 				err = -ENOIOCTLCMD;
13290768e170SArnd Bergmann 				break;
13300768e170SArnd Bergmann 			}
13311ded5e5aSEric Dumazet 			err = ops->gettstamp(sock, argp,
13320768e170SArnd Bergmann 					     cmd == SIOCGSTAMP_NEW,
13330768e170SArnd Bergmann 					     false);
1334c7cbdbf2SArnd Bergmann 			break;
1335876f0bf9SArnd Bergmann 
1336876f0bf9SArnd Bergmann 		case SIOCGIFCONF:
1337876f0bf9SArnd Bergmann 			err = dev_ifconf(net, argp);
1338876f0bf9SArnd Bergmann 			break;
1339876f0bf9SArnd Bergmann 
13401da177e4SLinus Torvalds 		default:
134163ff03abSJohannes Berg 			err = sock_do_ioctl(net, sock, cmd, arg);
13421da177e4SLinus Torvalds 			break;
13431da177e4SLinus Torvalds 		}
13441da177e4SLinus Torvalds 	return err;
13451da177e4SLinus Torvalds }
13461da177e4SLinus Torvalds 
13478a3c245cSPedro Tammela /**
13488a3c245cSPedro Tammela  *	sock_create_lite - creates a socket
13498a3c245cSPedro Tammela  *	@family: protocol family (AF_INET, ...)
13508a3c245cSPedro Tammela  *	@type: communication type (SOCK_STREAM, ...)
13518a3c245cSPedro Tammela  *	@protocol: protocol (0, ...)
13528a3c245cSPedro Tammela  *	@res: new socket
13538a3c245cSPedro Tammela  *
13548a3c245cSPedro Tammela  *	Creates a new socket and assigns it to @res, passing through LSM.
13558a3c245cSPedro Tammela  *	The new socket initialization is not complete, see kernel_accept().
13568a3c245cSPedro Tammela  *	Returns 0 or an error. On failure @res is set to %NULL.
13578a3c245cSPedro Tammela  *	This function internally uses GFP_KERNEL.
13588a3c245cSPedro Tammela  */
13598a3c245cSPedro Tammela 
sock_create_lite(int family,int type,int protocol,struct socket ** res)13601da177e4SLinus Torvalds int sock_create_lite(int family, int type, int protocol, struct socket **res)
13611da177e4SLinus Torvalds {
13621da177e4SLinus Torvalds 	int err;
13631da177e4SLinus Torvalds 	struct socket *sock = NULL;
13641da177e4SLinus Torvalds 
13651da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, 1);
13661da177e4SLinus Torvalds 	if (err)
13671da177e4SLinus Torvalds 		goto out;
13681da177e4SLinus Torvalds 
13691da177e4SLinus Torvalds 	sock = sock_alloc();
13701da177e4SLinus Torvalds 	if (!sock) {
13711da177e4SLinus Torvalds 		err = -ENOMEM;
13721da177e4SLinus Torvalds 		goto out;
13731da177e4SLinus Torvalds 	}
13741da177e4SLinus Torvalds 
13751da177e4SLinus Torvalds 	sock->type = type;
13767420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, 1);
13777420ed23SVenkat Yekkirala 	if (err)
13787420ed23SVenkat Yekkirala 		goto out_release;
13797420ed23SVenkat Yekkirala 
13801da177e4SLinus Torvalds out:
13811da177e4SLinus Torvalds 	*res = sock;
13821da177e4SLinus Torvalds 	return err;
13837420ed23SVenkat Yekkirala out_release:
13847420ed23SVenkat Yekkirala 	sock_release(sock);
13857420ed23SVenkat Yekkirala 	sock = NULL;
13867420ed23SVenkat Yekkirala 	goto out;
13871da177e4SLinus Torvalds }
1388c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_lite);
13891da177e4SLinus Torvalds 
13901da177e4SLinus Torvalds /* No kernel lock held - perfect */
sock_poll(struct file * file,poll_table * wait)1391ade994f4SAl Viro static __poll_t sock_poll(struct file *file, poll_table *wait)
13921da177e4SLinus Torvalds {
13933cafb376SChristoph Hellwig 	struct socket *sock = file->private_data;
13941ded5e5aSEric Dumazet 	const struct proto_ops *ops = READ_ONCE(sock->ops);
1395a331de3bSChristoph Hellwig 	__poll_t events = poll_requested_events(wait), flag = 0;
13961da177e4SLinus Torvalds 
13971ded5e5aSEric Dumazet 	if (!ops->poll)
1398e88958e6SChristoph Hellwig 		return 0;
1399f641f13bSChristoph Hellwig 
1400a331de3bSChristoph Hellwig 	if (sk_can_busy_loop(sock->sk)) {
1401f641f13bSChristoph Hellwig 		/* poll once if requested by the syscall */
1402a331de3bSChristoph Hellwig 		if (events & POLL_BUSY_LOOP)
1403f641f13bSChristoph Hellwig 			sk_busy_loop(sock->sk, 1);
1404a331de3bSChristoph Hellwig 
1405a331de3bSChristoph Hellwig 		/* if this socket can poll_ll, tell the system call */
1406a331de3bSChristoph Hellwig 		flag = POLL_BUSY_LOOP;
1407a331de3bSChristoph Hellwig 	}
1408a331de3bSChristoph Hellwig 
14091ded5e5aSEric Dumazet 	return ops->poll(file, sock, wait) | flag;
14101da177e4SLinus Torvalds }
14111da177e4SLinus Torvalds 
sock_mmap(struct file * file,struct vm_area_struct * vma)14121da177e4SLinus Torvalds static int sock_mmap(struct file *file, struct vm_area_struct *vma)
14131da177e4SLinus Torvalds {
1414b69aee04SEric Dumazet 	struct socket *sock = file->private_data;
14151da177e4SLinus Torvalds 
14161ded5e5aSEric Dumazet 	return READ_ONCE(sock->ops)->mmap(file, sock, vma);
14171da177e4SLinus Torvalds }
14181da177e4SLinus Torvalds 
sock_close(struct inode * inode,struct file * filp)141920380731SArnaldo Carvalho de Melo static int sock_close(struct inode *inode, struct file *filp)
14201da177e4SLinus Torvalds {
14216d8c50dcSCong Wang 	__sock_release(SOCKET_I(inode), inode);
14221da177e4SLinus Torvalds 	return 0;
14231da177e4SLinus Torvalds }
14241da177e4SLinus Torvalds 
14251da177e4SLinus Torvalds /*
14261da177e4SLinus Torvalds  *	Update the socket async list
14271da177e4SLinus Torvalds  *
14281da177e4SLinus Torvalds  *	Fasync_list locking strategy.
14291da177e4SLinus Torvalds  *
14301da177e4SLinus Torvalds  *	1. fasync_list is modified only under process context socket lock
14311da177e4SLinus Torvalds  *	   i.e. under semaphore.
14321da177e4SLinus Torvalds  *	2. fasync_list is used under read_lock(&sk->sk_callback_lock)
1433989a2979SEric Dumazet  *	   or under socket lock
14341da177e4SLinus Torvalds  */
14351da177e4SLinus Torvalds 
sock_fasync(int fd,struct file * filp,int on)14361da177e4SLinus Torvalds static int sock_fasync(int fd, struct file *filp, int on)
14371da177e4SLinus Torvalds {
1438989a2979SEric Dumazet 	struct socket *sock = filp->private_data;
1439989a2979SEric Dumazet 	struct sock *sk = sock->sk;
1440333f7909SAl Viro 	struct socket_wq *wq = &sock->wq;
14411da177e4SLinus Torvalds 
1442989a2979SEric Dumazet 	if (sk == NULL)
14431da177e4SLinus Torvalds 		return -EINVAL;
14441da177e4SLinus Torvalds 
14451da177e4SLinus Torvalds 	lock_sock(sk);
1446eaefd110SEric Dumazet 	fasync_helper(fd, filp, on, &wq->fasync_list);
14471da177e4SLinus Torvalds 
1448eaefd110SEric Dumazet 	if (!wq->fasync_list)
1449bcdce719SEric Dumazet 		sock_reset_flag(sk, SOCK_FASYNC);
1450989a2979SEric Dumazet 	else
1451989a2979SEric Dumazet 		sock_set_flag(sk, SOCK_FASYNC);
14521da177e4SLinus Torvalds 
1453989a2979SEric Dumazet 	release_sock(sk);
14541da177e4SLinus Torvalds 	return 0;
14551da177e4SLinus Torvalds }
14561da177e4SLinus Torvalds 
1457ceb5d58bSEric Dumazet /* This function may be called only under rcu_lock */
14581da177e4SLinus Torvalds 
sock_wake_async(struct socket_wq * wq,int how,int band)1459ceb5d58bSEric Dumazet int sock_wake_async(struct socket_wq *wq, int how, int band)
14601da177e4SLinus Torvalds {
1461ceb5d58bSEric Dumazet 	if (!wq || !wq->fasync_list)
1462ceb5d58bSEric Dumazet 		return -1;
146343815482SEric Dumazet 
146489bddce5SStephen Hemminger 	switch (how) {
14658d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_WAITD:
1466ceb5d58bSEric Dumazet 		if (test_bit(SOCKWQ_ASYNC_WAITDATA, &wq->flags))
14671da177e4SLinus Torvalds 			break;
14681da177e4SLinus Torvalds 		goto call_kill;
14698d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_SPACE:
1470ceb5d58bSEric Dumazet 		if (!test_and_clear_bit(SOCKWQ_ASYNC_NOSPACE, &wq->flags))
14711da177e4SLinus Torvalds 			break;
14727c7ab580SMiaohe Lin 		fallthrough;
14738d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_IO:
14741da177e4SLinus Torvalds call_kill:
147543815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGIO, band);
14761da177e4SLinus Torvalds 		break;
14778d8ad9d7SPavel Emelyanov 	case SOCK_WAKE_URG:
147843815482SEric Dumazet 		kill_fasync(&wq->fasync_list, SIGURG, band);
14791da177e4SLinus Torvalds 	}
1480ceb5d58bSEric Dumazet 
14811da177e4SLinus Torvalds 	return 0;
14821da177e4SLinus Torvalds }
1483c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_wake_async);
14841da177e4SLinus Torvalds 
14858a3c245cSPedro Tammela /**
14868a3c245cSPedro Tammela  *	__sock_create - creates a socket
14878a3c245cSPedro Tammela  *	@net: net namespace
14888a3c245cSPedro Tammela  *	@family: protocol family (AF_INET, ...)
14898a3c245cSPedro Tammela  *	@type: communication type (SOCK_STREAM, ...)
14908a3c245cSPedro Tammela  *	@protocol: protocol (0, ...)
14918a3c245cSPedro Tammela  *	@res: new socket
14928a3c245cSPedro Tammela  *	@kern: boolean for kernel space sockets
14938a3c245cSPedro Tammela  *
14948a3c245cSPedro Tammela  *	Creates a new socket and assigns it to @res, passing through LSM.
14958a3c245cSPedro Tammela  *	Returns 0 or an error. On failure @res is set to %NULL. @kern must
14968a3c245cSPedro Tammela  *	be set to true if the socket resides in kernel space.
14978a3c245cSPedro Tammela  *	This function internally uses GFP_KERNEL.
14988a3c245cSPedro Tammela  */
14998a3c245cSPedro Tammela 
__sock_create(struct net * net,int family,int type,int protocol,struct socket ** res,int kern)1500721db93aSPavel Emelyanov int __sock_create(struct net *net, int family, int type, int protocol,
150189bddce5SStephen Hemminger 			 struct socket **res, int kern)
15021da177e4SLinus Torvalds {
15031da177e4SLinus Torvalds 	int err;
15041da177e4SLinus Torvalds 	struct socket *sock;
150555737fdaSStephen Hemminger 	const struct net_proto_family *pf;
15061da177e4SLinus Torvalds 
15071da177e4SLinus Torvalds 	/*
15081da177e4SLinus Torvalds 	 *      Check protocol is in range
15091da177e4SLinus Torvalds 	 */
15101da177e4SLinus Torvalds 	if (family < 0 || family >= NPROTO)
15111da177e4SLinus Torvalds 		return -EAFNOSUPPORT;
15121da177e4SLinus Torvalds 	if (type < 0 || type >= SOCK_MAX)
15131da177e4SLinus Torvalds 		return -EINVAL;
15141da177e4SLinus Torvalds 
15151da177e4SLinus Torvalds 	/* Compatibility.
15161da177e4SLinus Torvalds 
15171da177e4SLinus Torvalds 	   This uglymoron is moved from INET layer to here to avoid
15181da177e4SLinus Torvalds 	   deadlock in module load.
15191da177e4SLinus Torvalds 	 */
15201da177e4SLinus Torvalds 	if (family == PF_INET && type == SOCK_PACKET) {
1521f3c98690Sliping.zhang 		pr_info_once("%s uses obsolete (PF_INET,SOCK_PACKET)\n",
152289bddce5SStephen Hemminger 			     current->comm);
15231da177e4SLinus Torvalds 		family = PF_PACKET;
15241da177e4SLinus Torvalds 	}
15251da177e4SLinus Torvalds 
15261da177e4SLinus Torvalds 	err = security_socket_create(family, type, protocol, kern);
15271da177e4SLinus Torvalds 	if (err)
15281da177e4SLinus Torvalds 		return err;
15291da177e4SLinus Torvalds 
153055737fdaSStephen Hemminger 	/*
153155737fdaSStephen Hemminger 	 *	Allocate the socket and allow the family to set things up. if
153255737fdaSStephen Hemminger 	 *	the protocol is 0, the family is instructed to select an appropriate
153355737fdaSStephen Hemminger 	 *	default.
153455737fdaSStephen Hemminger 	 */
153555737fdaSStephen Hemminger 	sock = sock_alloc();
153655737fdaSStephen Hemminger 	if (!sock) {
1537e87cc472SJoe Perches 		net_warn_ratelimited("socket: no more sockets\n");
153855737fdaSStephen Hemminger 		return -ENFILE;	/* Not exactly a match, but its the
153955737fdaSStephen Hemminger 				   closest posix thing */
154055737fdaSStephen Hemminger 	}
154155737fdaSStephen Hemminger 
154255737fdaSStephen Hemminger 	sock->type = type;
154355737fdaSStephen Hemminger 
154495a5afcaSJohannes Berg #ifdef CONFIG_MODULES
15451da177e4SLinus Torvalds 	/* Attempt to load a protocol module if the find failed.
15461da177e4SLinus Torvalds 	 *
15471da177e4SLinus Torvalds 	 * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
15481da177e4SLinus Torvalds 	 * requested real, full-featured networking support upon configuration.
15491da177e4SLinus Torvalds 	 * Otherwise module support will break!
15501da177e4SLinus Torvalds 	 */
1551190683a9SEric Dumazet 	if (rcu_access_pointer(net_families[family]) == NULL)
15521da177e4SLinus Torvalds 		request_module("net-pf-%d", family);
15531da177e4SLinus Torvalds #endif
15541da177e4SLinus Torvalds 
155555737fdaSStephen Hemminger 	rcu_read_lock();
155655737fdaSStephen Hemminger 	pf = rcu_dereference(net_families[family]);
15571da177e4SLinus Torvalds 	err = -EAFNOSUPPORT;
155855737fdaSStephen Hemminger 	if (!pf)
155955737fdaSStephen Hemminger 		goto out_release;
15601da177e4SLinus Torvalds 
15611da177e4SLinus Torvalds 	/*
15621da177e4SLinus Torvalds 	 * We will call the ->create function, that possibly is in a loadable
15631da177e4SLinus Torvalds 	 * module, so we have to bump that loadable module refcnt first.
15641da177e4SLinus Torvalds 	 */
156555737fdaSStephen Hemminger 	if (!try_module_get(pf->owner))
15661da177e4SLinus Torvalds 		goto out_release;
15671da177e4SLinus Torvalds 
156855737fdaSStephen Hemminger 	/* Now protected by module ref count */
156955737fdaSStephen Hemminger 	rcu_read_unlock();
157055737fdaSStephen Hemminger 
15713f378b68SEric Paris 	err = pf->create(net, sock, protocol, kern);
157255737fdaSStephen Hemminger 	if (err < 0)
15731da177e4SLinus Torvalds 		goto out_module_put;
1574a79af59eSFrank Filz 
15751da177e4SLinus Torvalds 	/*
15761da177e4SLinus Torvalds 	 * Now to bump the refcnt of the [loadable] module that owns this
15771da177e4SLinus Torvalds 	 * socket at sock_release time we decrement its refcnt.
15781da177e4SLinus Torvalds 	 */
157955737fdaSStephen Hemminger 	if (!try_module_get(sock->ops->owner))
158055737fdaSStephen Hemminger 		goto out_module_busy;
158155737fdaSStephen Hemminger 
15821da177e4SLinus Torvalds 	/*
15831da177e4SLinus Torvalds 	 * Now that we're done with the ->create function, the [loadable]
15841da177e4SLinus Torvalds 	 * module can have its refcnt decremented
15851da177e4SLinus Torvalds 	 */
158655737fdaSStephen Hemminger 	module_put(pf->owner);
15877420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, kern);
15887420ed23SVenkat Yekkirala 	if (err)
15893b185525SHerbert Xu 		goto out_sock_release;
159055737fdaSStephen Hemminger 	*res = sock;
15911da177e4SLinus Torvalds 
159255737fdaSStephen Hemminger 	return 0;
159355737fdaSStephen Hemminger 
159455737fdaSStephen Hemminger out_module_busy:
159555737fdaSStephen Hemminger 	err = -EAFNOSUPPORT;
15961da177e4SLinus Torvalds out_module_put:
159755737fdaSStephen Hemminger 	sock->ops = NULL;
159855737fdaSStephen Hemminger 	module_put(pf->owner);
159955737fdaSStephen Hemminger out_sock_release:
16001da177e4SLinus Torvalds 	sock_release(sock);
160155737fdaSStephen Hemminger 	return err;
160255737fdaSStephen Hemminger 
160355737fdaSStephen Hemminger out_release:
160455737fdaSStephen Hemminger 	rcu_read_unlock();
160555737fdaSStephen Hemminger 	goto out_sock_release;
16061da177e4SLinus Torvalds }
1607721db93aSPavel Emelyanov EXPORT_SYMBOL(__sock_create);
16081da177e4SLinus Torvalds 
16098a3c245cSPedro Tammela /**
16108a3c245cSPedro Tammela  *	sock_create - creates a socket
16118a3c245cSPedro Tammela  *	@family: protocol family (AF_INET, ...)
16128a3c245cSPedro Tammela  *	@type: communication type (SOCK_STREAM, ...)
16138a3c245cSPedro Tammela  *	@protocol: protocol (0, ...)
16148a3c245cSPedro Tammela  *	@res: new socket
16158a3c245cSPedro Tammela  *
16168a3c245cSPedro Tammela  *	A wrapper around __sock_create().
16178a3c245cSPedro Tammela  *	Returns 0 or an error. This function internally uses GFP_KERNEL.
16188a3c245cSPedro Tammela  */
16198a3c245cSPedro Tammela 
sock_create(int family,int type,int protocol,struct socket ** res)16201da177e4SLinus Torvalds int sock_create(int family, int type, int protocol, struct socket **res)
16211da177e4SLinus Torvalds {
16221b8d7ae4SEric W. Biederman 	return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
16231da177e4SLinus Torvalds }
1624c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create);
16251da177e4SLinus Torvalds 
16268a3c245cSPedro Tammela /**
16278a3c245cSPedro Tammela  *	sock_create_kern - creates a socket (kernel space)
16288a3c245cSPedro Tammela  *	@net: net namespace
16298a3c245cSPedro Tammela  *	@family: protocol family (AF_INET, ...)
16308a3c245cSPedro Tammela  *	@type: communication type (SOCK_STREAM, ...)
16318a3c245cSPedro Tammela  *	@protocol: protocol (0, ...)
16328a3c245cSPedro Tammela  *	@res: new socket
16338a3c245cSPedro Tammela  *
16348a3c245cSPedro Tammela  *	A wrapper around __sock_create().
16358a3c245cSPedro Tammela  *	Returns 0 or an error. This function internally uses GFP_KERNEL.
16368a3c245cSPedro Tammela  */
16378a3c245cSPedro Tammela 
sock_create_kern(struct net * net,int family,int type,int protocol,struct socket ** res)1638eeb1bd5cSEric W. Biederman int sock_create_kern(struct net *net, int family, int type, int protocol, struct socket **res)
16391da177e4SLinus Torvalds {
1640eeb1bd5cSEric W. Biederman 	return __sock_create(net, family, type, protocol, res, 1);
16411da177e4SLinus Torvalds }
1642c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_kern);
16431da177e4SLinus Torvalds 
__sys_socket_create(int family,int type,int protocol)1644da214a47SJens Axboe static struct socket *__sys_socket_create(int family, int type, int protocol)
16451da177e4SLinus Torvalds {
16461da177e4SLinus Torvalds 	struct socket *sock;
1647da214a47SJens Axboe 	int retval;
1648a677a039SUlrich Drepper 
1649e38b36f3SUlrich Drepper 	/* Check the SOCK_* constants for consistency.  */
1650e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
1651e38b36f3SUlrich Drepper 	BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
1652e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);
1653e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);
1654e38b36f3SUlrich Drepper 
1655da214a47SJens Axboe 	if ((type & ~SOCK_TYPE_MASK) & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1656da214a47SJens Axboe 		return ERR_PTR(-EINVAL);
1657a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
16581da177e4SLinus Torvalds 
16591da177e4SLinus Torvalds 	retval = sock_create(family, type, protocol, &sock);
16601da177e4SLinus Torvalds 	if (retval < 0)
1661da214a47SJens Axboe 		return ERR_PTR(retval);
1662da214a47SJens Axboe 
1663da214a47SJens Axboe 	return sock;
1664da214a47SJens Axboe }
1665da214a47SJens Axboe 
__sys_socket_file(int family,int type,int protocol)1666da214a47SJens Axboe struct file *__sys_socket_file(int family, int type, int protocol)
1667da214a47SJens Axboe {
1668da214a47SJens Axboe 	struct socket *sock;
1669da214a47SJens Axboe 	int flags;
1670da214a47SJens Axboe 
1671da214a47SJens Axboe 	sock = __sys_socket_create(family, type, protocol);
1672da214a47SJens Axboe 	if (IS_ERR(sock))
1673da214a47SJens Axboe 		return ERR_CAST(sock);
1674da214a47SJens Axboe 
1675da214a47SJens Axboe 	flags = type & ~SOCK_TYPE_MASK;
1676da214a47SJens Axboe 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1677da214a47SJens Axboe 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1678da214a47SJens Axboe 
1679649c15c7SThadeu Lima de Souza Cascardo 	return sock_alloc_file(sock, flags, NULL);
1680da214a47SJens Axboe }
1681da214a47SJens Axboe 
16820dd061a6SGeliang Tang /*	A hook for bpf progs to attach to and update socket protocol.
16830dd061a6SGeliang Tang  *
16840dd061a6SGeliang Tang  *	A static noinline declaration here could cause the compiler to
16850dd061a6SGeliang Tang  *	optimize away the function. A global noinline declaration will
16860dd061a6SGeliang Tang  *	keep the definition, but may optimize away the callsite.
16870dd061a6SGeliang Tang  *	Therefore, __weak is needed to ensure that the call is still
16880dd061a6SGeliang Tang  *	emitted, by telling the compiler that we don't know what the
16890dd061a6SGeliang Tang  *	function might eventually be.
16900dd061a6SGeliang Tang  *
16910dd061a6SGeliang Tang  *	__diag_* below are needed to dismiss the missing prototype warning.
16920dd061a6SGeliang Tang  */
16930dd061a6SGeliang Tang 
16940dd061a6SGeliang Tang __diag_push();
16950dd061a6SGeliang Tang __diag_ignore_all("-Wmissing-prototypes",
16960dd061a6SGeliang Tang 		  "A fmod_ret entry point for BPF programs");
16970dd061a6SGeliang Tang 
update_socket_protocol(int family,int type,int protocol)16980dd061a6SGeliang Tang __weak noinline int update_socket_protocol(int family, int type, int protocol)
16990dd061a6SGeliang Tang {
17000dd061a6SGeliang Tang 	return protocol;
17010dd061a6SGeliang Tang }
17020dd061a6SGeliang Tang 
17030dd061a6SGeliang Tang __diag_pop();
17040dd061a6SGeliang Tang 
__sys_socket(int family,int type,int protocol)1705da214a47SJens Axboe int __sys_socket(int family, int type, int protocol)
1706da214a47SJens Axboe {
1707da214a47SJens Axboe 	struct socket *sock;
1708da214a47SJens Axboe 	int flags;
1709da214a47SJens Axboe 
17100dd061a6SGeliang Tang 	sock = __sys_socket_create(family, type,
17110dd061a6SGeliang Tang 				   update_socket_protocol(family, type, protocol));
1712da214a47SJens Axboe 	if (IS_ERR(sock))
1713da214a47SJens Axboe 		return PTR_ERR(sock);
1714da214a47SJens Axboe 
1715da214a47SJens Axboe 	flags = type & ~SOCK_TYPE_MASK;
1716da214a47SJens Axboe 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1717da214a47SJens Axboe 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
17181da177e4SLinus Torvalds 
17198e1611e2SAl Viro 	return sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
17201da177e4SLinus Torvalds }
17211da177e4SLinus Torvalds 
SYSCALL_DEFINE3(socket,int,family,int,type,int,protocol)17229d6a15c3SDominik Brodowski SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
17239d6a15c3SDominik Brodowski {
17249d6a15c3SDominik Brodowski 	return __sys_socket(family, type, protocol);
17259d6a15c3SDominik Brodowski }
17269d6a15c3SDominik Brodowski 
17271da177e4SLinus Torvalds /*
17281da177e4SLinus Torvalds  *	Create a pair of connected sockets.
17291da177e4SLinus Torvalds  */
17301da177e4SLinus Torvalds 
__sys_socketpair(int family,int type,int protocol,int __user * usockvec)17316debc8d8SDominik Brodowski int __sys_socketpair(int family, int type, int protocol, int __user *usockvec)
17321da177e4SLinus Torvalds {
17331da177e4SLinus Torvalds 	struct socket *sock1, *sock2;
17341da177e4SLinus Torvalds 	int fd1, fd2, err;
1735db349509SAl Viro 	struct file *newfile1, *newfile2;
1736a677a039SUlrich Drepper 	int flags;
1737a677a039SUlrich Drepper 
1738a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
173977d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1740a677a039SUlrich Drepper 		return -EINVAL;
1741a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
17421da177e4SLinus Torvalds 
1743aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1744aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1745aaca0bdcSUlrich Drepper 
17461da177e4SLinus Torvalds 	/*
1747016a266bSAl Viro 	 * reserve descriptors and make sure we won't fail
1748016a266bSAl Viro 	 * to return them to userland.
1749016a266bSAl Viro 	 */
1750016a266bSAl Viro 	fd1 = get_unused_fd_flags(flags);
1751016a266bSAl Viro 	if (unlikely(fd1 < 0))
1752016a266bSAl Viro 		return fd1;
1753016a266bSAl Viro 
1754016a266bSAl Viro 	fd2 = get_unused_fd_flags(flags);
1755016a266bSAl Viro 	if (unlikely(fd2 < 0)) {
1756016a266bSAl Viro 		put_unused_fd(fd1);
1757016a266bSAl Viro 		return fd2;
1758016a266bSAl Viro 	}
1759016a266bSAl Viro 
1760016a266bSAl Viro 	err = put_user(fd1, &usockvec[0]);
1761016a266bSAl Viro 	if (err)
1762016a266bSAl Viro 		goto out;
1763016a266bSAl Viro 
1764016a266bSAl Viro 	err = put_user(fd2, &usockvec[1]);
1765016a266bSAl Viro 	if (err)
1766016a266bSAl Viro 		goto out;
1767016a266bSAl Viro 
1768016a266bSAl Viro 	/*
17691da177e4SLinus Torvalds 	 * Obtain the first socket and check if the underlying protocol
17701da177e4SLinus Torvalds 	 * supports the socketpair call.
17711da177e4SLinus Torvalds 	 */
17721da177e4SLinus Torvalds 
17731da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock1);
1774016a266bSAl Viro 	if (unlikely(err < 0))
17751da177e4SLinus Torvalds 		goto out;
17761da177e4SLinus Torvalds 
17771da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock2);
1778016a266bSAl Viro 	if (unlikely(err < 0)) {
1779016a266bSAl Viro 		sock_release(sock1);
1780016a266bSAl Viro 		goto out;
1781bf3c23d1SDavid S. Miller 	}
1782d73aa286SYann Droneaud 
1783d47cd945SDavid Herrmann 	err = security_socket_socketpair(sock1, sock2);
1784d47cd945SDavid Herrmann 	if (unlikely(err)) {
1785d47cd945SDavid Herrmann 		sock_release(sock2);
1786d47cd945SDavid Herrmann 		sock_release(sock1);
1787d47cd945SDavid Herrmann 		goto out;
1788d47cd945SDavid Herrmann 	}
1789d47cd945SDavid Herrmann 
17901ded5e5aSEric Dumazet 	err = READ_ONCE(sock1->ops)->socketpair(sock1, sock2);
1791016a266bSAl Viro 	if (unlikely(err < 0)) {
1792016a266bSAl Viro 		sock_release(sock2);
1793016a266bSAl Viro 		sock_release(sock1);
1794016a266bSAl Viro 		goto out;
179528407630SAl Viro 	}
179628407630SAl Viro 
1797aab174f0SLinus Torvalds 	newfile1 = sock_alloc_file(sock1, flags, NULL);
1798b5ffe634SViresh Kumar 	if (IS_ERR(newfile1)) {
179928407630SAl Viro 		err = PTR_ERR(newfile1);
1800016a266bSAl Viro 		sock_release(sock2);
1801016a266bSAl Viro 		goto out;
180228407630SAl Viro 	}
180328407630SAl Viro 
1804aab174f0SLinus Torvalds 	newfile2 = sock_alloc_file(sock2, flags, NULL);
180528407630SAl Viro 	if (IS_ERR(newfile2)) {
180628407630SAl Viro 		err = PTR_ERR(newfile2);
1807016a266bSAl Viro 		fput(newfile1);
1808016a266bSAl Viro 		goto out;
1809db349509SAl Viro 	}
1810db349509SAl Viro 
1811157cf649SAl Viro 	audit_fd_pair(fd1, fd2);
1812d73aa286SYann Droneaud 
1813db349509SAl Viro 	fd_install(fd1, newfile1);
1814db349509SAl Viro 	fd_install(fd2, newfile2);
18151da177e4SLinus Torvalds 	return 0;
18161da177e4SLinus Torvalds 
18171da177e4SLinus Torvalds out:
1818016a266bSAl Viro 	put_unused_fd(fd2);
1819016a266bSAl Viro 	put_unused_fd(fd1);
18201da177e4SLinus Torvalds 	return err;
18211da177e4SLinus Torvalds }
18221da177e4SLinus Torvalds 
SYSCALL_DEFINE4(socketpair,int,family,int,type,int,protocol,int __user *,usockvec)18236debc8d8SDominik Brodowski SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
18246debc8d8SDominik Brodowski 		int __user *, usockvec)
18256debc8d8SDominik Brodowski {
18266debc8d8SDominik Brodowski 	return __sys_socketpair(family, type, protocol, usockvec);
18276debc8d8SDominik Brodowski }
18286debc8d8SDominik Brodowski 
18291da177e4SLinus Torvalds /*
18301da177e4SLinus Torvalds  *	Bind a name to a socket. Nothing much to do here since it's
18311da177e4SLinus Torvalds  *	the protocol's responsibility to handle the local address.
18321da177e4SLinus Torvalds  *
18331da177e4SLinus Torvalds  *	We move the socket address to kernel space before we call
18341da177e4SLinus Torvalds  *	the protocol layer (having also checked the address is ok).
18351da177e4SLinus Torvalds  */
18361da177e4SLinus Torvalds 
__sys_bind(int fd,struct sockaddr __user * umyaddr,int addrlen)1837a87d35d8SDominik Brodowski int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)
18381da177e4SLinus Torvalds {
18391da177e4SLinus Torvalds 	struct socket *sock;
1840230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
18416cb153caSBenjamin LaHaise 	int err, fput_needed;
18421da177e4SLinus Torvalds 
184389bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
184489bddce5SStephen Hemminger 	if (sock) {
184543db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(umyaddr, addrlen, &address);
1846068b88ccSJakub Sitnicki 		if (!err) {
184789bddce5SStephen Hemminger 			err = security_socket_bind(sock,
1848230b1839SYOSHIFUJI Hideaki 						   (struct sockaddr *)&address,
184989bddce5SStephen Hemminger 						   addrlen);
18506cb153caSBenjamin LaHaise 			if (!err)
18511ded5e5aSEric Dumazet 				err = READ_ONCE(sock->ops)->bind(sock,
185289bddce5SStephen Hemminger 						      (struct sockaddr *)
1853230b1839SYOSHIFUJI Hideaki 						      &address, addrlen);
18541da177e4SLinus Torvalds 		}
18556cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
18561da177e4SLinus Torvalds 	}
18571da177e4SLinus Torvalds 	return err;
18581da177e4SLinus Torvalds }
18591da177e4SLinus Torvalds 
SYSCALL_DEFINE3(bind,int,fd,struct sockaddr __user *,umyaddr,int,addrlen)1860a87d35d8SDominik Brodowski SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
1861a87d35d8SDominik Brodowski {
1862a87d35d8SDominik Brodowski 	return __sys_bind(fd, umyaddr, addrlen);
1863a87d35d8SDominik Brodowski }
1864a87d35d8SDominik Brodowski 
18651da177e4SLinus Torvalds /*
18661da177e4SLinus Torvalds  *	Perform a listen. Basically, we allow the protocol to do anything
18671da177e4SLinus Torvalds  *	necessary for a listen, and if that works, we mark the socket as
18681da177e4SLinus Torvalds  *	ready for listening.
18691da177e4SLinus Torvalds  */
18701da177e4SLinus Torvalds 
__sys_listen(int fd,int backlog)187125e290eeSDominik Brodowski int __sys_listen(int fd, int backlog)
18721da177e4SLinus Torvalds {
18731da177e4SLinus Torvalds 	struct socket *sock;
18746cb153caSBenjamin LaHaise 	int err, fput_needed;
1875b8e1f9b5SPavel Emelyanov 	int somaxconn;
18761da177e4SLinus Torvalds 
187789bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
187889bddce5SStephen Hemminger 	if (sock) {
18793c9ba81dSKuniyuki Iwashima 		somaxconn = READ_ONCE(sock_net(sock->sk)->core.sysctl_somaxconn);
188095c96174SEric Dumazet 		if ((unsigned int)backlog > somaxconn)
1881b8e1f9b5SPavel Emelyanov 			backlog = somaxconn;
18821da177e4SLinus Torvalds 
18831da177e4SLinus Torvalds 		err = security_socket_listen(sock, backlog);
18846cb153caSBenjamin LaHaise 		if (!err)
18851ded5e5aSEric Dumazet 			err = READ_ONCE(sock->ops)->listen(sock, backlog);
18866cb153caSBenjamin LaHaise 
18876cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
18881da177e4SLinus Torvalds 	}
18891da177e4SLinus Torvalds 	return err;
18901da177e4SLinus Torvalds }
18911da177e4SLinus Torvalds 
SYSCALL_DEFINE2(listen,int,fd,int,backlog)189225e290eeSDominik Brodowski SYSCALL_DEFINE2(listen, int, fd, int, backlog)
189325e290eeSDominik Brodowski {
189425e290eeSDominik Brodowski 	return __sys_listen(fd, backlog);
189525e290eeSDominik Brodowski }
189625e290eeSDominik Brodowski 
do_accept(struct file * file,unsigned file_flags,struct sockaddr __user * upeer_sockaddr,int __user * upeer_addrlen,int flags)1897d32f89daSPavel Begunkov struct file *do_accept(struct file *file, unsigned file_flags,
1898de2ea4b6SJens Axboe 		       struct sockaddr __user *upeer_sockaddr,
1899d32f89daSPavel Begunkov 		       int __user *upeer_addrlen, int flags)
19001da177e4SLinus Torvalds {
19011da177e4SLinus Torvalds 	struct socket *sock, *newsock;
190239d8c1b6SDavid S. Miller 	struct file *newfile;
1903d32f89daSPavel Begunkov 	int err, len;
1904230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
19051ded5e5aSEric Dumazet 	const struct proto_ops *ops;
19061da177e4SLinus Torvalds 
1907dba4a925SFlorent Revest 	sock = sock_from_file(file);
1908d32f89daSPavel Begunkov 	if (!sock)
1909d32f89daSPavel Begunkov 		return ERR_PTR(-ENOTSOCK);
19101da177e4SLinus Torvalds 
1911c6d409cfSEric Dumazet 	newsock = sock_alloc();
1912c6d409cfSEric Dumazet 	if (!newsock)
1913d32f89daSPavel Begunkov 		return ERR_PTR(-ENFILE);
19141ded5e5aSEric Dumazet 	ops = READ_ONCE(sock->ops);
19151da177e4SLinus Torvalds 
19161da177e4SLinus Torvalds 	newsock->type = sock->type;
19171ded5e5aSEric Dumazet 	newsock->ops = ops;
19181da177e4SLinus Torvalds 
19191da177e4SLinus Torvalds 	/*
19201da177e4SLinus Torvalds 	 * We don't need try_module_get here, as the listening socket (sock)
19211da177e4SLinus Torvalds 	 * has the protocol module (sock->ops->owner) held.
19221da177e4SLinus Torvalds 	 */
19231ded5e5aSEric Dumazet 	__module_get(ops->owner);
19241da177e4SLinus Torvalds 
1925aab174f0SLinus Torvalds 	newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name);
1926d32f89daSPavel Begunkov 	if (IS_ERR(newfile))
1927d32f89daSPavel Begunkov 		return newfile;
192839d8c1b6SDavid S. Miller 
1929a79af59eSFrank Filz 	err = security_socket_accept(sock, newsock);
1930a79af59eSFrank Filz 	if (err)
193139d8c1b6SDavid S. Miller 		goto out_fd;
1932a79af59eSFrank Filz 
19331ded5e5aSEric Dumazet 	err = ops->accept(sock, newsock, sock->file->f_flags | file_flags,
1934de2ea4b6SJens Axboe 					false);
19351da177e4SLinus Torvalds 	if (err < 0)
193639d8c1b6SDavid S. Miller 		goto out_fd;
19371da177e4SLinus Torvalds 
19381da177e4SLinus Torvalds 	if (upeer_sockaddr) {
19391ded5e5aSEric Dumazet 		len = ops->getname(newsock, (struct sockaddr *)&address, 2);
19409b2c45d4SDenys Vlasenko 		if (len < 0) {
19411da177e4SLinus Torvalds 			err = -ECONNABORTED;
194239d8c1b6SDavid S. Miller 			goto out_fd;
19431da177e4SLinus Torvalds 		}
194443db362dSMaciej Żenczykowski 		err = move_addr_to_user(&address,
1945230b1839SYOSHIFUJI Hideaki 					len, upeer_sockaddr, upeer_addrlen);
19461da177e4SLinus Torvalds 		if (err < 0)
194739d8c1b6SDavid S. Miller 			goto out_fd;
19481da177e4SLinus Torvalds 	}
19491da177e4SLinus Torvalds 
19501da177e4SLinus Torvalds 	/* File flags are not inherited via accept() unlike another OSes. */
1951d32f89daSPavel Begunkov 	return newfile;
195239d8c1b6SDavid S. Miller out_fd:
19539606a216SDavid S. Miller 	fput(newfile);
1954d32f89daSPavel Begunkov 	return ERR_PTR(err);
1955d32f89daSPavel Begunkov }
1956de2ea4b6SJens Axboe 
__sys_accept4_file(struct file * file,struct sockaddr __user * upeer_sockaddr,int __user * upeer_addrlen,int flags)1957c0424532SYajun Deng static int __sys_accept4_file(struct file *file, struct sockaddr __user *upeer_sockaddr,
1958c0424532SYajun Deng 			      int __user *upeer_addrlen, int flags)
1959d32f89daSPavel Begunkov {
1960d32f89daSPavel Begunkov 	struct file *newfile;
1961d32f89daSPavel Begunkov 	int newfd;
1962d32f89daSPavel Begunkov 
1963d32f89daSPavel Begunkov 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1964d32f89daSPavel Begunkov 		return -EINVAL;
1965d32f89daSPavel Begunkov 
1966d32f89daSPavel Begunkov 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1967d32f89daSPavel Begunkov 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1968d32f89daSPavel Begunkov 
1969c0424532SYajun Deng 	newfd = get_unused_fd_flags(flags);
1970d32f89daSPavel Begunkov 	if (unlikely(newfd < 0))
1971d32f89daSPavel Begunkov 		return newfd;
1972d32f89daSPavel Begunkov 
1973c0424532SYajun Deng 	newfile = do_accept(file, 0, upeer_sockaddr, upeer_addrlen,
1974d32f89daSPavel Begunkov 			    flags);
1975d32f89daSPavel Begunkov 	if (IS_ERR(newfile)) {
1976d32f89daSPavel Begunkov 		put_unused_fd(newfd);
1977d32f89daSPavel Begunkov 		return PTR_ERR(newfile);
1978d32f89daSPavel Begunkov 	}
1979d32f89daSPavel Begunkov 	fd_install(newfd, newfile);
1980d32f89daSPavel Begunkov 	return newfd;
1981de2ea4b6SJens Axboe }
1982de2ea4b6SJens Axboe 
1983de2ea4b6SJens Axboe /*
1984de2ea4b6SJens Axboe  *	For accept, we attempt to create a new socket, set up the link
1985de2ea4b6SJens Axboe  *	with the client, wake up the client, then return the new
1986de2ea4b6SJens Axboe  *	connected fd. We collect the address of the connector in kernel
1987de2ea4b6SJens Axboe  *	space and move it to user at the very end. This is unclean because
1988de2ea4b6SJens Axboe  *	we open the socket then return an error.
1989de2ea4b6SJens Axboe  *
1990de2ea4b6SJens Axboe  *	1003.1g adds the ability to recvmsg() to query connection pending
1991de2ea4b6SJens Axboe  *	status to recvmsg. We need to add that support in a way thats
1992de2ea4b6SJens Axboe  *	clean when we restructure accept also.
1993de2ea4b6SJens Axboe  */
1994de2ea4b6SJens Axboe 
__sys_accept4(int fd,struct sockaddr __user * upeer_sockaddr,int __user * upeer_addrlen,int flags)1995de2ea4b6SJens Axboe int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
1996de2ea4b6SJens Axboe 		  int __user *upeer_addrlen, int flags)
1997de2ea4b6SJens Axboe {
1998de2ea4b6SJens Axboe 	int ret = -EBADF;
1999de2ea4b6SJens Axboe 	struct fd f;
2000de2ea4b6SJens Axboe 
2001de2ea4b6SJens Axboe 	f = fdget(fd);
2002de2ea4b6SJens Axboe 	if (f.file) {
2003c0424532SYajun Deng 		ret = __sys_accept4_file(f.file, upeer_sockaddr,
2004c0424532SYajun Deng 					 upeer_addrlen, flags);
20056b07edebSMiaohe Lin 		fdput(f);
2006de2ea4b6SJens Axboe 	}
2007de2ea4b6SJens Axboe 
2008de2ea4b6SJens Axboe 	return ret;
20091da177e4SLinus Torvalds }
20101da177e4SLinus Torvalds 
SYSCALL_DEFINE4(accept4,int,fd,struct sockaddr __user *,upeer_sockaddr,int __user *,upeer_addrlen,int,flags)20114541e805SDominik Brodowski SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
20124541e805SDominik Brodowski 		int __user *, upeer_addrlen, int, flags)
20134541e805SDominik Brodowski {
20144541e805SDominik Brodowski 	return __sys_accept4(fd, upeer_sockaddr, upeer_addrlen, flags);
20154541e805SDominik Brodowski }
20164541e805SDominik Brodowski 
SYSCALL_DEFINE3(accept,int,fd,struct sockaddr __user *,upeer_sockaddr,int __user *,upeer_addrlen)201720f37034SHeiko Carstens SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,
201820f37034SHeiko Carstens 		int __user *, upeer_addrlen)
2019aaca0bdcSUlrich Drepper {
20204541e805SDominik Brodowski 	return __sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0);
2021aaca0bdcSUlrich Drepper }
2022aaca0bdcSUlrich Drepper 
20231da177e4SLinus Torvalds /*
20241da177e4SLinus Torvalds  *	Attempt to connect to a socket with the server address.  The address
20251da177e4SLinus Torvalds  *	is in user space so we verify it is OK and move it to kernel space.
20261da177e4SLinus Torvalds  *
20271da177e4SLinus Torvalds  *	For 1003.1g we need to add clean support for a bind to AF_UNSPEC to
20281da177e4SLinus Torvalds  *	break bindings
20291da177e4SLinus Torvalds  *
20301da177e4SLinus Torvalds  *	NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and
20311da177e4SLinus Torvalds  *	other SEQPACKET protocols that take time to connect() as it doesn't
20321da177e4SLinus Torvalds  *	include the -EINPROGRESS status for such sockets.
20331da177e4SLinus Torvalds  */
20341da177e4SLinus Torvalds 
__sys_connect_file(struct file * file,struct sockaddr_storage * address,int addrlen,int file_flags)2035f499a021SJens Axboe int __sys_connect_file(struct file *file, struct sockaddr_storage *address,
2036bd3ded31SJens Axboe 		       int addrlen, int file_flags)
20371da177e4SLinus Torvalds {
20381da177e4SLinus Torvalds 	struct socket *sock;
2039bd3ded31SJens Axboe 	int err;
20401da177e4SLinus Torvalds 
2041dba4a925SFlorent Revest 	sock = sock_from_file(file);
2042dba4a925SFlorent Revest 	if (!sock) {
2043dba4a925SFlorent Revest 		err = -ENOTSOCK;
20441da177e4SLinus Torvalds 		goto out;
2045dba4a925SFlorent Revest 	}
20461da177e4SLinus Torvalds 
204789bddce5SStephen Hemminger 	err =
2048f499a021SJens Axboe 	    security_socket_connect(sock, (struct sockaddr *)address, addrlen);
20491da177e4SLinus Torvalds 	if (err)
2050bd3ded31SJens Axboe 		goto out;
20511da177e4SLinus Torvalds 
20521ded5e5aSEric Dumazet 	err = READ_ONCE(sock->ops)->connect(sock, (struct sockaddr *)address,
20531ded5e5aSEric Dumazet 				addrlen, sock->file->f_flags | file_flags);
20541da177e4SLinus Torvalds out:
20551da177e4SLinus Torvalds 	return err;
20561da177e4SLinus Torvalds }
20571da177e4SLinus Torvalds 
__sys_connect(int fd,struct sockaddr __user * uservaddr,int addrlen)2058bd3ded31SJens Axboe int __sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen)
2059bd3ded31SJens Axboe {
2060bd3ded31SJens Axboe 	int ret = -EBADF;
2061bd3ded31SJens Axboe 	struct fd f;
2062bd3ded31SJens Axboe 
2063bd3ded31SJens Axboe 	f = fdget(fd);
2064bd3ded31SJens Axboe 	if (f.file) {
2065f499a021SJens Axboe 		struct sockaddr_storage address;
2066f499a021SJens Axboe 
2067f499a021SJens Axboe 		ret = move_addr_to_kernel(uservaddr, addrlen, &address);
2068f499a021SJens Axboe 		if (!ret)
2069f499a021SJens Axboe 			ret = __sys_connect_file(f.file, &address, addrlen, 0);
20706b07edebSMiaohe Lin 		fdput(f);
2071bd3ded31SJens Axboe 	}
2072bd3ded31SJens Axboe 
2073bd3ded31SJens Axboe 	return ret;
2074bd3ded31SJens Axboe }
2075bd3ded31SJens Axboe 
SYSCALL_DEFINE3(connect,int,fd,struct sockaddr __user *,uservaddr,int,addrlen)20761387c2c2SDominik Brodowski SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
20771387c2c2SDominik Brodowski 		int, addrlen)
20781387c2c2SDominik Brodowski {
20791387c2c2SDominik Brodowski 	return __sys_connect(fd, uservaddr, addrlen);
20801387c2c2SDominik Brodowski }
20811387c2c2SDominik Brodowski 
20821da177e4SLinus Torvalds /*
20831da177e4SLinus Torvalds  *	Get the local address ('name') of a socket object. Move the obtained
20841da177e4SLinus Torvalds  *	name to user space.
20851da177e4SLinus Torvalds  */
20861da177e4SLinus Torvalds 
__sys_getsockname(int fd,struct sockaddr __user * usockaddr,int __user * usockaddr_len)20878882a107SDominik Brodowski int __sys_getsockname(int fd, struct sockaddr __user *usockaddr,
20888882a107SDominik Brodowski 		      int __user *usockaddr_len)
20891da177e4SLinus Torvalds {
20901da177e4SLinus Torvalds 	struct socket *sock;
2091230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
20929b2c45d4SDenys Vlasenko 	int err, fput_needed;
20931da177e4SLinus Torvalds 
20946cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
20951da177e4SLinus Torvalds 	if (!sock)
20961da177e4SLinus Torvalds 		goto out;
20971da177e4SLinus Torvalds 
20981da177e4SLinus Torvalds 	err = security_socket_getsockname(sock);
20991da177e4SLinus Torvalds 	if (err)
21001da177e4SLinus Torvalds 		goto out_put;
21011da177e4SLinus Torvalds 
21021ded5e5aSEric Dumazet 	err = READ_ONCE(sock->ops)->getname(sock, (struct sockaddr *)&address, 0);
21039b2c45d4SDenys Vlasenko 	if (err < 0)
21041da177e4SLinus Torvalds 		goto out_put;
21059b2c45d4SDenys Vlasenko 	/* "err" is actually length in this case */
21069b2c45d4SDenys Vlasenko 	err = move_addr_to_user(&address, err, usockaddr, usockaddr_len);
21071da177e4SLinus Torvalds 
21081da177e4SLinus Torvalds out_put:
21096cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
21101da177e4SLinus Torvalds out:
21111da177e4SLinus Torvalds 	return err;
21121da177e4SLinus Torvalds }
21131da177e4SLinus Torvalds 
SYSCALL_DEFINE3(getsockname,int,fd,struct sockaddr __user *,usockaddr,int __user *,usockaddr_len)21148882a107SDominik Brodowski SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
21158882a107SDominik Brodowski 		int __user *, usockaddr_len)
21168882a107SDominik Brodowski {
21178882a107SDominik Brodowski 	return __sys_getsockname(fd, usockaddr, usockaddr_len);
21188882a107SDominik Brodowski }
21198882a107SDominik Brodowski 
21201da177e4SLinus Torvalds /*
21211da177e4SLinus Torvalds  *	Get the remote address ('name') of a socket object. Move the obtained
21221da177e4SLinus Torvalds  *	name to user space.
21231da177e4SLinus Torvalds  */
21241da177e4SLinus Torvalds 
__sys_getpeername(int fd,struct sockaddr __user * usockaddr,int __user * usockaddr_len)2125b21c8f83SDominik Brodowski int __sys_getpeername(int fd, struct sockaddr __user *usockaddr,
2126b21c8f83SDominik Brodowski 		      int __user *usockaddr_len)
21271da177e4SLinus Torvalds {
21281da177e4SLinus Torvalds 	struct socket *sock;
2129230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
21309b2c45d4SDenys Vlasenko 	int err, fput_needed;
21311da177e4SLinus Torvalds 
213289bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
213389bddce5SStephen Hemminger 	if (sock != NULL) {
21341ded5e5aSEric Dumazet 		const struct proto_ops *ops = READ_ONCE(sock->ops);
21351ded5e5aSEric Dumazet 
21361da177e4SLinus Torvalds 		err = security_socket_getpeername(sock);
21371da177e4SLinus Torvalds 		if (err) {
21386cb153caSBenjamin LaHaise 			fput_light(sock->file, fput_needed);
21391da177e4SLinus Torvalds 			return err;
21401da177e4SLinus Torvalds 		}
21411da177e4SLinus Torvalds 
21421ded5e5aSEric Dumazet 		err = ops->getname(sock, (struct sockaddr *)&address, 1);
21439b2c45d4SDenys Vlasenko 		if (err >= 0)
21449b2c45d4SDenys Vlasenko 			/* "err" is actually length in this case */
21459b2c45d4SDenys Vlasenko 			err = move_addr_to_user(&address, err, usockaddr,
214689bddce5SStephen Hemminger 						usockaddr_len);
21476cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
21481da177e4SLinus Torvalds 	}
21491da177e4SLinus Torvalds 	return err;
21501da177e4SLinus Torvalds }
21511da177e4SLinus Torvalds 
SYSCALL_DEFINE3(getpeername,int,fd,struct sockaddr __user *,usockaddr,int __user *,usockaddr_len)2152b21c8f83SDominik Brodowski SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
2153b21c8f83SDominik Brodowski 		int __user *, usockaddr_len)
2154b21c8f83SDominik Brodowski {
2155b21c8f83SDominik Brodowski 	return __sys_getpeername(fd, usockaddr, usockaddr_len);
2156b21c8f83SDominik Brodowski }
2157b21c8f83SDominik Brodowski 
21581da177e4SLinus Torvalds /*
21591da177e4SLinus Torvalds  *	Send a datagram to a given address. We move the address into kernel
21601da177e4SLinus Torvalds  *	space and check the user space data area is readable before invoking
21611da177e4SLinus Torvalds  *	the protocol.
21621da177e4SLinus Torvalds  */
__sys_sendto(int fd,void __user * buff,size_t len,unsigned int flags,struct sockaddr __user * addr,int addr_len)2163211b634bSDominik Brodowski int __sys_sendto(int fd, void __user *buff, size_t len, unsigned int flags,
2164211b634bSDominik Brodowski 		 struct sockaddr __user *addr,  int addr_len)
21651da177e4SLinus Torvalds {
21661da177e4SLinus Torvalds 	struct socket *sock;
2167230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
21681da177e4SLinus Torvalds 	int err;
21691da177e4SLinus Torvalds 	struct msghdr msg;
21701da177e4SLinus Torvalds 	struct iovec iov;
21716cb153caSBenjamin LaHaise 	int fput_needed;
21721da177e4SLinus Torvalds 
2173de4eda9dSAl Viro 	err = import_single_range(ITER_SOURCE, buff, len, &iov, &msg.msg_iter);
2174602bd0e9SAl Viro 	if (unlikely(err))
2175602bd0e9SAl Viro 		return err;
2176de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2177de0fa95cSPavel Emelyanov 	if (!sock)
21784387ff75SDavid S. Miller 		goto out;
21796cb153caSBenjamin LaHaise 
21801da177e4SLinus Torvalds 	msg.msg_name = NULL;
21811da177e4SLinus Torvalds 	msg.msg_control = NULL;
21821da177e4SLinus Torvalds 	msg.msg_controllen = 0;
21831da177e4SLinus Torvalds 	msg.msg_namelen = 0;
21847c701d92SPavel Begunkov 	msg.msg_ubuf = NULL;
21856cb153caSBenjamin LaHaise 	if (addr) {
218643db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(addr, addr_len, &address);
21871da177e4SLinus Torvalds 		if (err < 0)
21881da177e4SLinus Torvalds 			goto out_put;
2189230b1839SYOSHIFUJI Hideaki 		msg.msg_name = (struct sockaddr *)&address;
21901da177e4SLinus Torvalds 		msg.msg_namelen = addr_len;
21911da177e4SLinus Torvalds 	}
2192b841b901SDavid Howells 	flags &= ~MSG_INTERNAL_SENDMSG_FLAGS;
21931da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
21941da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
21951da177e4SLinus Torvalds 	msg.msg_flags = flags;
219686a7e0b6SJordan Rife 	err = __sock_sendmsg(sock, &msg);
21971da177e4SLinus Torvalds 
21981da177e4SLinus Torvalds out_put:
2199de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
22004387ff75SDavid S. Miller out:
22011da177e4SLinus Torvalds 	return err;
22021da177e4SLinus Torvalds }
22031da177e4SLinus Torvalds 
SYSCALL_DEFINE6(sendto,int,fd,void __user *,buff,size_t,len,unsigned int,flags,struct sockaddr __user *,addr,int,addr_len)2204211b634bSDominik Brodowski SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
2205211b634bSDominik Brodowski 		unsigned int, flags, struct sockaddr __user *, addr,
2206211b634bSDominik Brodowski 		int, addr_len)
2207211b634bSDominik Brodowski {
2208211b634bSDominik Brodowski 	return __sys_sendto(fd, buff, len, flags, addr, addr_len);
2209211b634bSDominik Brodowski }
2210211b634bSDominik Brodowski 
22111da177e4SLinus Torvalds /*
22121da177e4SLinus Torvalds  *	Send a datagram down a socket.
22131da177e4SLinus Torvalds  */
22141da177e4SLinus Torvalds 
SYSCALL_DEFINE4(send,int,fd,void __user *,buff,size_t,len,unsigned int,flags)22153e0fa65fSHeiko Carstens SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len,
221695c96174SEric Dumazet 		unsigned int, flags)
22171da177e4SLinus Torvalds {
2218211b634bSDominik Brodowski 	return __sys_sendto(fd, buff, len, flags, NULL, 0);
22191da177e4SLinus Torvalds }
22201da177e4SLinus Torvalds 
22211da177e4SLinus Torvalds /*
22221da177e4SLinus Torvalds  *	Receive a frame from the socket and optionally record the address of the
22231da177e4SLinus Torvalds  *	sender. We verify the buffers are writable and if needed move the
22241da177e4SLinus Torvalds  *	sender address from kernel to user space.
22251da177e4SLinus Torvalds  */
__sys_recvfrom(int fd,void __user * ubuf,size_t size,unsigned int flags,struct sockaddr __user * addr,int __user * addr_len)22267a09e1ebSDominik Brodowski int __sys_recvfrom(int fd, void __user *ubuf, size_t size, unsigned int flags,
22277a09e1ebSDominik Brodowski 		   struct sockaddr __user *addr, int __user *addr_len)
22281da177e4SLinus Torvalds {
22291228b34cSEric Dumazet 	struct sockaddr_storage address;
22301228b34cSEric Dumazet 	struct msghdr msg = {
22311228b34cSEric Dumazet 		/* Save some cycles and don't copy the address if not needed */
22321228b34cSEric Dumazet 		.msg_name = addr ? (struct sockaddr *)&address : NULL,
22331228b34cSEric Dumazet 	};
22341da177e4SLinus Torvalds 	struct socket *sock;
22351da177e4SLinus Torvalds 	struct iovec iov;
22361da177e4SLinus Torvalds 	int err, err2;
22376cb153caSBenjamin LaHaise 	int fput_needed;
22381da177e4SLinus Torvalds 
2239de4eda9dSAl Viro 	err = import_single_range(ITER_DEST, ubuf, size, &iov, &msg.msg_iter);
2240602bd0e9SAl Viro 	if (unlikely(err))
2241602bd0e9SAl Viro 		return err;
2242de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
22431da177e4SLinus Torvalds 	if (!sock)
2244de0fa95cSPavel Emelyanov 		goto out;
22451da177e4SLinus Torvalds 
22461da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
22471da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
22482da62906SAl Viro 	err = sock_recvmsg(sock, &msg, flags);
22491da177e4SLinus Torvalds 
225089bddce5SStephen Hemminger 	if (err >= 0 && addr != NULL) {
225143db362dSMaciej Żenczykowski 		err2 = move_addr_to_user(&address,
2252230b1839SYOSHIFUJI Hideaki 					 msg.msg_namelen, addr, addr_len);
22531da177e4SLinus Torvalds 		if (err2 < 0)
22541da177e4SLinus Torvalds 			err = err2;
22551da177e4SLinus Torvalds 	}
2256de0fa95cSPavel Emelyanov 
2257de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
22584387ff75SDavid S. Miller out:
22591da177e4SLinus Torvalds 	return err;
22601da177e4SLinus Torvalds }
22611da177e4SLinus Torvalds 
SYSCALL_DEFINE6(recvfrom,int,fd,void __user *,ubuf,size_t,size,unsigned int,flags,struct sockaddr __user *,addr,int __user *,addr_len)22627a09e1ebSDominik Brodowski SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
22637a09e1ebSDominik Brodowski 		unsigned int, flags, struct sockaddr __user *, addr,
22647a09e1ebSDominik Brodowski 		int __user *, addr_len)
22657a09e1ebSDominik Brodowski {
22667a09e1ebSDominik Brodowski 	return __sys_recvfrom(fd, ubuf, size, flags, addr, addr_len);
22677a09e1ebSDominik Brodowski }
22687a09e1ebSDominik Brodowski 
22691da177e4SLinus Torvalds /*
22701da177e4SLinus Torvalds  *	Receive a datagram from a socket.
22711da177e4SLinus Torvalds  */
22721da177e4SLinus Torvalds 
SYSCALL_DEFINE4(recv,int,fd,void __user *,ubuf,size_t,size,unsigned int,flags)2273b7c0ddf5SJan Glauber SYSCALL_DEFINE4(recv, int, fd, void __user *, ubuf, size_t, size,
2274b7c0ddf5SJan Glauber 		unsigned int, flags)
22751da177e4SLinus Torvalds {
22767a09e1ebSDominik Brodowski 	return __sys_recvfrom(fd, ubuf, size, flags, NULL, NULL);
22771da177e4SLinus Torvalds }
22781da177e4SLinus Torvalds 
sock_use_custom_sol_socket(const struct socket * sock)227983f0c10bSFlorian Westphal static bool sock_use_custom_sol_socket(const struct socket *sock)
228083f0c10bSFlorian Westphal {
2281a5ef058dSPaolo Abeni 	return test_bit(SOCK_CUSTOM_SOCKOPT, &sock->flags);
228283f0c10bSFlorian Westphal }
228383f0c10bSFlorian Westphal 
22841da177e4SLinus Torvalds /*
22851da177e4SLinus Torvalds  *	Set a socket option. Because we don't know the option lengths we have
22861da177e4SLinus Torvalds  *	to pass the user mode parameter for the protocols to sort out.
22871da177e4SLinus Torvalds  */
__sys_setsockopt(int fd,int level,int optname,char __user * user_optval,int optlen)2288a7b75c5aSChristoph Hellwig int __sys_setsockopt(int fd, int level, int optname, char __user *user_optval,
228955db9c0eSChristoph Hellwig 		int optlen)
22901da177e4SLinus Torvalds {
2291519a8a6cSChristoph Hellwig 	sockptr_t optval = USER_SOCKPTR(user_optval);
22921ded5e5aSEric Dumazet 	const struct proto_ops *ops;
22930d01da6aSStanislav Fomichev 	char *kernel_optval = NULL;
22946cb153caSBenjamin LaHaise 	int err, fput_needed;
22951da177e4SLinus Torvalds 	struct socket *sock;
22961da177e4SLinus Torvalds 
22971da177e4SLinus Torvalds 	if (optlen < 0)
22981da177e4SLinus Torvalds 		return -EINVAL;
22991da177e4SLinus Torvalds 
230089bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
23014a367299SChristoph Hellwig 	if (!sock)
23024a367299SChristoph Hellwig 		return err;
23034a367299SChristoph Hellwig 
23041da177e4SLinus Torvalds 	err = security_socket_setsockopt(sock, level, optname);
23056cb153caSBenjamin LaHaise 	if (err)
23066cb153caSBenjamin LaHaise 		goto out_put;
23071da177e4SLinus Torvalds 
230855db9c0eSChristoph Hellwig 	if (!in_compat_syscall())
23094a367299SChristoph Hellwig 		err = BPF_CGROUP_RUN_PROG_SETSOCKOPT(sock->sk, &level, &optname,
2310a7b75c5aSChristoph Hellwig 						     user_optval, &optlen,
231155db9c0eSChristoph Hellwig 						     &kernel_optval);
23124a367299SChristoph Hellwig 	if (err < 0)
23130d01da6aSStanislav Fomichev 		goto out_put;
23144a367299SChristoph Hellwig 	if (err > 0) {
23150d01da6aSStanislav Fomichev 		err = 0;
23160d01da6aSStanislav Fomichev 		goto out_put;
23170d01da6aSStanislav Fomichev 	}
23180d01da6aSStanislav Fomichev 
2319a7b75c5aSChristoph Hellwig 	if (kernel_optval)
2320a7b75c5aSChristoph Hellwig 		optval = KERNEL_SOCKPTR(kernel_optval);
23211ded5e5aSEric Dumazet 	ops = READ_ONCE(sock->ops);
232283f0c10bSFlorian Westphal 	if (level == SOL_SOCKET && !sock_use_custom_sol_socket(sock))
2323a7b75c5aSChristoph Hellwig 		err = sock_setsockopt(sock, level, optname, optval, optlen);
23241ded5e5aSEric Dumazet 	else if (unlikely(!ops->setsockopt))
2325a44d9e72SChristoph Hellwig 		err = -EOPNOTSUPP;
23261da177e4SLinus Torvalds 	else
23271ded5e5aSEric Dumazet 		err = ops->setsockopt(sock, level, optname, optval,
232889bddce5SStephen Hemminger 					    optlen);
23290d01da6aSStanislav Fomichev 	kfree(kernel_optval);
23306cb153caSBenjamin LaHaise out_put:
23316cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
23321da177e4SLinus Torvalds 	return err;
23331da177e4SLinus Torvalds }
23341da177e4SLinus Torvalds 
SYSCALL_DEFINE5(setsockopt,int,fd,int,level,int,optname,char __user *,optval,int,optlen)2335cc36dca0SDominik Brodowski SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
2336cc36dca0SDominik Brodowski 		char __user *, optval, int, optlen)
2337cc36dca0SDominik Brodowski {
2338cc36dca0SDominik Brodowski 	return __sys_setsockopt(fd, level, optname, optval, optlen);
2339cc36dca0SDominik Brodowski }
2340cc36dca0SDominik Brodowski 
23419cacf81fSStanislav Fomichev INDIRECT_CALLABLE_DECLARE(bool tcp_bpf_bypass_getsockopt(int level,
23429cacf81fSStanislav Fomichev 							 int optname));
23439cacf81fSStanislav Fomichev 
23441da177e4SLinus Torvalds /*
23451da177e4SLinus Torvalds  *	Get a socket option. Because we don't know the option lengths we have
23461da177e4SLinus Torvalds  *	to pass a user mode parameter for the protocols to sort out.
23471da177e4SLinus Torvalds  */
__sys_getsockopt(int fd,int level,int optname,char __user * optval,int __user * optlen)234855db9c0eSChristoph Hellwig int __sys_getsockopt(int fd, int level, int optname, char __user *optval,
234955db9c0eSChristoph Hellwig 		int __user *optlen)
23501da177e4SLinus Torvalds {
2351ad4bf5f2SVincenzo Palazzo 	int max_optlen __maybe_unused;
23521ded5e5aSEric Dumazet 	const struct proto_ops *ops;
23536cb153caSBenjamin LaHaise 	int err, fput_needed;
23541da177e4SLinus Torvalds 	struct socket *sock;
23551da177e4SLinus Torvalds 
235689bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2357d8a9b38fSChristoph Hellwig 	if (!sock)
2358d8a9b38fSChristoph Hellwig 		return err;
2359d8a9b38fSChristoph Hellwig 
23606cb153caSBenjamin LaHaise 	err = security_socket_getsockopt(sock, level, optname);
23616cb153caSBenjamin LaHaise 	if (err)
23626cb153caSBenjamin LaHaise 		goto out_put;
23631da177e4SLinus Torvalds 
236455db9c0eSChristoph Hellwig 	if (!in_compat_syscall())
23650d01da6aSStanislav Fomichev 		max_optlen = BPF_CGROUP_GETSOCKOPT_MAX_OPTLEN(optlen);
23660d01da6aSStanislav Fomichev 
23671ded5e5aSEric Dumazet 	ops = READ_ONCE(sock->ops);
23681da177e4SLinus Torvalds 	if (level == SOL_SOCKET)
2369d8a9b38fSChristoph Hellwig 		err = sock_getsockopt(sock, level, optname, optval, optlen);
23701ded5e5aSEric Dumazet 	else if (unlikely(!ops->getsockopt))
2371a44d9e72SChristoph Hellwig 		err = -EOPNOTSUPP;
23721da177e4SLinus Torvalds 	else
23731ded5e5aSEric Dumazet 		err = ops->getsockopt(sock, level, optname, optval,
237489bddce5SStephen Hemminger 					    optlen);
23750d01da6aSStanislav Fomichev 
237655db9c0eSChristoph Hellwig 	if (!in_compat_syscall())
237755db9c0eSChristoph Hellwig 		err = BPF_CGROUP_RUN_PROG_GETSOCKOPT(sock->sk, level, optname,
237855db9c0eSChristoph Hellwig 						     optval, optlen, max_optlen,
237955db9c0eSChristoph Hellwig 						     err);
23806cb153caSBenjamin LaHaise out_put:
23816cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
23821da177e4SLinus Torvalds 	return err;
23831da177e4SLinus Torvalds }
23841da177e4SLinus Torvalds 
SYSCALL_DEFINE5(getsockopt,int,fd,int,level,int,optname,char __user *,optval,int __user *,optlen)238513a2d70eSDominik Brodowski SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
238613a2d70eSDominik Brodowski 		char __user *, optval, int __user *, optlen)
238713a2d70eSDominik Brodowski {
238813a2d70eSDominik Brodowski 	return __sys_getsockopt(fd, level, optname, optval, optlen);
238913a2d70eSDominik Brodowski }
239013a2d70eSDominik Brodowski 
23911da177e4SLinus Torvalds /*
23921da177e4SLinus Torvalds  *	Shutdown a socket.
23931da177e4SLinus Torvalds  */
23941da177e4SLinus Torvalds 
__sys_shutdown_sock(struct socket * sock,int how)2395b713c195SJens Axboe int __sys_shutdown_sock(struct socket *sock, int how)
2396b713c195SJens Axboe {
2397b713c195SJens Axboe 	int err;
2398b713c195SJens Axboe 
2399b713c195SJens Axboe 	err = security_socket_shutdown(sock, how);
2400b713c195SJens Axboe 	if (!err)
24011ded5e5aSEric Dumazet 		err = READ_ONCE(sock->ops)->shutdown(sock, how);
2402b713c195SJens Axboe 
2403b713c195SJens Axboe 	return err;
2404b713c195SJens Axboe }
2405b713c195SJens Axboe 
__sys_shutdown(int fd,int how)2406005a1aeaSDominik Brodowski int __sys_shutdown(int fd, int how)
24071da177e4SLinus Torvalds {
24086cb153caSBenjamin LaHaise 	int err, fput_needed;
24091da177e4SLinus Torvalds 	struct socket *sock;
24101da177e4SLinus Torvalds 
241189bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
241289bddce5SStephen Hemminger 	if (sock != NULL) {
2413b713c195SJens Axboe 		err = __sys_shutdown_sock(sock, how);
24146cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
24151da177e4SLinus Torvalds 	}
24161da177e4SLinus Torvalds 	return err;
24171da177e4SLinus Torvalds }
24181da177e4SLinus Torvalds 
SYSCALL_DEFINE2(shutdown,int,fd,int,how)2419005a1aeaSDominik Brodowski SYSCALL_DEFINE2(shutdown, int, fd, int, how)
2420005a1aeaSDominik Brodowski {
2421005a1aeaSDominik Brodowski 	return __sys_shutdown(fd, how);
2422005a1aeaSDominik Brodowski }
2423005a1aeaSDominik Brodowski 
24241da177e4SLinus Torvalds /* A couple of helpful macros for getting the address of the 32/64 bit
24251da177e4SLinus Torvalds  * fields which are the same type (int / unsigned) on our platforms.
24261da177e4SLinus Torvalds  */
24271da177e4SLinus Torvalds #define COMPAT_MSG(msg, member)	((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member)
24281da177e4SLinus Torvalds #define COMPAT_NAMELEN(msg)	COMPAT_MSG(msg, msg_namelen)
24291da177e4SLinus Torvalds #define COMPAT_FLAGS(msg)	COMPAT_MSG(msg, msg_flags)
24301da177e4SLinus Torvalds 
2431c71d8ebeSTetsuo Handa struct used_address {
2432c71d8ebeSTetsuo Handa 	struct sockaddr_storage name;
2433c71d8ebeSTetsuo Handa 	unsigned int name_len;
2434c71d8ebeSTetsuo Handa };
2435c71d8ebeSTetsuo Handa 
__copy_msghdr(struct msghdr * kmsg,struct user_msghdr * msg,struct sockaddr __user ** save_addr)24367fa875b8SDylan Yudaken int __copy_msghdr(struct msghdr *kmsg,
24377fa875b8SDylan Yudaken 		  struct user_msghdr *msg,
24387fa875b8SDylan Yudaken 		  struct sockaddr __user **save_addr)
24391661bf36SDan Carpenter {
244008adb7daSAl Viro 	ssize_t err;
244108adb7daSAl Viro 
24421f466e1fSChristoph Hellwig 	kmsg->msg_control_is_user = true;
24431228b34cSEric Dumazet 	kmsg->msg_get_inq = 0;
24447fa875b8SDylan Yudaken 	kmsg->msg_control_user = msg->msg_control;
24457fa875b8SDylan Yudaken 	kmsg->msg_controllen = msg->msg_controllen;
24467fa875b8SDylan Yudaken 	kmsg->msg_flags = msg->msg_flags;
2447ffb07550SAl Viro 
24487fa875b8SDylan Yudaken 	kmsg->msg_namelen = msg->msg_namelen;
24497fa875b8SDylan Yudaken 	if (!msg->msg_name)
24506a2a2b3aSAni Sinha 		kmsg->msg_namelen = 0;
24516a2a2b3aSAni Sinha 
2452dbb490b9SMatthew Leach 	if (kmsg->msg_namelen < 0)
2453dbb490b9SMatthew Leach 		return -EINVAL;
2454dbb490b9SMatthew Leach 
24551661bf36SDan Carpenter 	if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
2456db31c55aSDan Carpenter 		kmsg->msg_namelen = sizeof(struct sockaddr_storage);
245708adb7daSAl Viro 
245808adb7daSAl Viro 	if (save_addr)
24597fa875b8SDylan Yudaken 		*save_addr = msg->msg_name;
246008adb7daSAl Viro 
24617fa875b8SDylan Yudaken 	if (msg->msg_name && kmsg->msg_namelen) {
246208adb7daSAl Viro 		if (!save_addr) {
24637fa875b8SDylan Yudaken 			err = move_addr_to_kernel(msg->msg_name,
2464864d9664SPaolo Abeni 						  kmsg->msg_namelen,
246508adb7daSAl Viro 						  kmsg->msg_name);
246608adb7daSAl Viro 			if (err < 0)
246708adb7daSAl Viro 				return err;
246808adb7daSAl Viro 		}
246908adb7daSAl Viro 	} else {
247008adb7daSAl Viro 		kmsg->msg_name = NULL;
247108adb7daSAl Viro 		kmsg->msg_namelen = 0;
247208adb7daSAl Viro 	}
247308adb7daSAl Viro 
24747fa875b8SDylan Yudaken 	if (msg->msg_iovlen > UIO_MAXIOV)
247508adb7daSAl Viro 		return -EMSGSIZE;
247608adb7daSAl Viro 
24770345f931Stadeusz.struk@intel.com 	kmsg->msg_iocb = NULL;
24787c701d92SPavel Begunkov 	kmsg->msg_ubuf = NULL;
24790a384abfSJens Axboe 	return 0;
24800a384abfSJens Axboe }
24810a384abfSJens Axboe 
copy_msghdr_from_user(struct msghdr * kmsg,struct user_msghdr __user * umsg,struct sockaddr __user ** save_addr,struct iovec ** iov)24820a384abfSJens Axboe static int copy_msghdr_from_user(struct msghdr *kmsg,
24830a384abfSJens Axboe 				 struct user_msghdr __user *umsg,
24840a384abfSJens Axboe 				 struct sockaddr __user **save_addr,
24850a384abfSJens Axboe 				 struct iovec **iov)
24860a384abfSJens Axboe {
24870a384abfSJens Axboe 	struct user_msghdr msg;
24880a384abfSJens Axboe 	ssize_t err;
24890a384abfSJens Axboe 
24907fa875b8SDylan Yudaken 	if (copy_from_user(&msg, umsg, sizeof(*umsg)))
24917fa875b8SDylan Yudaken 		return -EFAULT;
24927fa875b8SDylan Yudaken 
24937fa875b8SDylan Yudaken 	err = __copy_msghdr(kmsg, &msg, save_addr);
24940a384abfSJens Axboe 	if (err)
24950a384abfSJens Axboe 		return err;
24960345f931Stadeusz.struk@intel.com 
2497de4eda9dSAl Viro 	err = import_iovec(save_addr ? ITER_DEST : ITER_SOURCE,
2498ffb07550SAl Viro 			    msg.msg_iov, msg.msg_iovlen,
2499da184284SAl Viro 			    UIO_FASTIOV, iov, &kmsg->msg_iter);
250087e5e6daSJens Axboe 	return err < 0 ? err : 0;
25011661bf36SDan Carpenter }
25021661bf36SDan Carpenter 
____sys_sendmsg(struct socket * sock,struct msghdr * msg_sys,unsigned int flags,struct used_address * used_address,unsigned int allowed_msghdr_flags)25034257c8caSJens Axboe static int ____sys_sendmsg(struct socket *sock, struct msghdr *msg_sys,
25044257c8caSJens Axboe 			   unsigned int flags, struct used_address *used_address,
250528a94d8fSTom Herbert 			   unsigned int allowed_msghdr_flags)
25061da177e4SLinus Torvalds {
2507b9d717a7SAlex Williamson 	unsigned char ctl[sizeof(struct cmsghdr) + 20]
2508846cc123SAmit Kushwaha 				__aligned(sizeof(__kernel_size_t));
2509b9d717a7SAlex Williamson 	/* 20 is size of ipv6_pktinfo */
25101da177e4SLinus Torvalds 	unsigned char *ctl_buf = ctl;
2511d8725c86SAl Viro 	int ctl_len;
251208adb7daSAl Viro 	ssize_t err;
25131da177e4SLinus Torvalds 
25141da177e4SLinus Torvalds 	err = -ENOBUFS;
25151da177e4SLinus Torvalds 
2516228e548eSAnton Blanchard 	if (msg_sys->msg_controllen > INT_MAX)
25174257c8caSJens Axboe 		goto out;
251828a94d8fSTom Herbert 	flags |= (msg_sys->msg_flags & allowed_msghdr_flags);
2519228e548eSAnton Blanchard 	ctl_len = msg_sys->msg_controllen;
25201da177e4SLinus Torvalds 	if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
252189bddce5SStephen Hemminger 		err =
2522228e548eSAnton Blanchard 		    cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl,
252389bddce5SStephen Hemminger 						     sizeof(ctl));
25241da177e4SLinus Torvalds 		if (err)
25254257c8caSJens Axboe 			goto out;
2526228e548eSAnton Blanchard 		ctl_buf = msg_sys->msg_control;
2527228e548eSAnton Blanchard 		ctl_len = msg_sys->msg_controllen;
25281da177e4SLinus Torvalds 	} else if (ctl_len) {
2529ac4340fcSDavid S. Miller 		BUILD_BUG_ON(sizeof(struct cmsghdr) !=
2530ac4340fcSDavid S. Miller 			     CMSG_ALIGN(sizeof(struct cmsghdr)));
253189bddce5SStephen Hemminger 		if (ctl_len > sizeof(ctl)) {
25321da177e4SLinus Torvalds 			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
25331da177e4SLinus Torvalds 			if (ctl_buf == NULL)
25344257c8caSJens Axboe 				goto out;
25351da177e4SLinus Torvalds 		}
25361da177e4SLinus Torvalds 		err = -EFAULT;
25371f466e1fSChristoph Hellwig 		if (copy_from_user(ctl_buf, msg_sys->msg_control_user, ctl_len))
25381da177e4SLinus Torvalds 			goto out_freectl;
2539228e548eSAnton Blanchard 		msg_sys->msg_control = ctl_buf;
25401f466e1fSChristoph Hellwig 		msg_sys->msg_control_is_user = false;
25411da177e4SLinus Torvalds 	}
2542b841b901SDavid Howells 	flags &= ~MSG_INTERNAL_SENDMSG_FLAGS;
2543228e548eSAnton Blanchard 	msg_sys->msg_flags = flags;
25441da177e4SLinus Torvalds 
25451da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
2546228e548eSAnton Blanchard 		msg_sys->msg_flags |= MSG_DONTWAIT;
2547c71d8ebeSTetsuo Handa 	/*
2548c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and current destination address is same as
2549c71d8ebeSTetsuo Handa 	 * previously succeeded address, omit asking LSM's decision.
2550c71d8ebeSTetsuo Handa 	 * used_address->name_len is initialized to UINT_MAX so that the first
2551c71d8ebeSTetsuo Handa 	 * destination address never matches.
2552c71d8ebeSTetsuo Handa 	 */
2553bc909d9dSMathieu Desnoyers 	if (used_address && msg_sys->msg_name &&
2554bc909d9dSMathieu Desnoyers 	    used_address->name_len == msg_sys->msg_namelen &&
2555bc909d9dSMathieu Desnoyers 	    !memcmp(&used_address->name, msg_sys->msg_name,
2556c71d8ebeSTetsuo Handa 		    used_address->name_len)) {
2557d8725c86SAl Viro 		err = sock_sendmsg_nosec(sock, msg_sys);
2558c71d8ebeSTetsuo Handa 		goto out_freectl;
2559c71d8ebeSTetsuo Handa 	}
256086a7e0b6SJordan Rife 	err = __sock_sendmsg(sock, msg_sys);
2561c71d8ebeSTetsuo Handa 	/*
2562c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and sending to current destination address was
2563c71d8ebeSTetsuo Handa 	 * successful, remember it.
2564c71d8ebeSTetsuo Handa 	 */
2565c71d8ebeSTetsuo Handa 	if (used_address && err >= 0) {
2566c71d8ebeSTetsuo Handa 		used_address->name_len = msg_sys->msg_namelen;
2567bc909d9dSMathieu Desnoyers 		if (msg_sys->msg_name)
2568bc909d9dSMathieu Desnoyers 			memcpy(&used_address->name, msg_sys->msg_name,
2569c71d8ebeSTetsuo Handa 			       used_address->name_len);
2570c71d8ebeSTetsuo Handa 	}
25711da177e4SLinus Torvalds 
25721da177e4SLinus Torvalds out_freectl:
25731da177e4SLinus Torvalds 	if (ctl_buf != ctl)
25741da177e4SLinus Torvalds 		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
25754257c8caSJens Axboe out:
25764257c8caSJens Axboe 	return err;
25774257c8caSJens Axboe }
25784257c8caSJens Axboe 
sendmsg_copy_msghdr(struct msghdr * msg,struct user_msghdr __user * umsg,unsigned flags,struct iovec ** iov)257903b1230cSJens Axboe int sendmsg_copy_msghdr(struct msghdr *msg,
25804257c8caSJens Axboe 			struct user_msghdr __user *umsg, unsigned flags,
25814257c8caSJens Axboe 			struct iovec **iov)
25824257c8caSJens Axboe {
25834257c8caSJens Axboe 	int err;
25844257c8caSJens Axboe 
25854257c8caSJens Axboe 	if (flags & MSG_CMSG_COMPAT) {
25864257c8caSJens Axboe 		struct compat_msghdr __user *msg_compat;
25874257c8caSJens Axboe 
25884257c8caSJens Axboe 		msg_compat = (struct compat_msghdr __user *) umsg;
25894257c8caSJens Axboe 		err = get_compat_msghdr(msg, msg_compat, NULL, iov);
25904257c8caSJens Axboe 	} else {
25914257c8caSJens Axboe 		err = copy_msghdr_from_user(msg, umsg, NULL, iov);
25924257c8caSJens Axboe 	}
25934257c8caSJens Axboe 	if (err < 0)
25944257c8caSJens Axboe 		return err;
25954257c8caSJens Axboe 
25964257c8caSJens Axboe 	return 0;
25974257c8caSJens Axboe }
25984257c8caSJens 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)25994257c8caSJens Axboe static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
26004257c8caSJens Axboe 			 struct msghdr *msg_sys, unsigned int flags,
26014257c8caSJens Axboe 			 struct used_address *used_address,
26024257c8caSJens Axboe 			 unsigned int allowed_msghdr_flags)
26034257c8caSJens Axboe {
26044257c8caSJens Axboe 	struct sockaddr_storage address;
26054257c8caSJens Axboe 	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
26064257c8caSJens Axboe 	ssize_t err;
26074257c8caSJens Axboe 
26084257c8caSJens Axboe 	msg_sys->msg_name = &address;
26094257c8caSJens Axboe 
26104257c8caSJens Axboe 	err = sendmsg_copy_msghdr(msg_sys, msg, flags, &iov);
26114257c8caSJens Axboe 	if (err < 0)
26124257c8caSJens Axboe 		return err;
26134257c8caSJens Axboe 
26144257c8caSJens Axboe 	err = ____sys_sendmsg(sock, msg_sys, flags, used_address,
26154257c8caSJens Axboe 				allowed_msghdr_flags);
2616a74e9106SEric Dumazet 	kfree(iov);
2617228e548eSAnton Blanchard 	return err;
2618228e548eSAnton Blanchard }
2619228e548eSAnton Blanchard 
2620228e548eSAnton Blanchard /*
2621228e548eSAnton Blanchard  *	BSD sendmsg interface
2622228e548eSAnton Blanchard  */
__sys_sendmsg_sock(struct socket * sock,struct msghdr * msg,unsigned int flags)262303b1230cSJens Axboe long __sys_sendmsg_sock(struct socket *sock, struct msghdr *msg,
26240fa03c62SJens Axboe 			unsigned int flags)
26250fa03c62SJens Axboe {
262603b1230cSJens Axboe 	return ____sys_sendmsg(sock, msg, flags, NULL, 0);
26270fa03c62SJens Axboe }
2628228e548eSAnton Blanchard 
__sys_sendmsg(int fd,struct user_msghdr __user * msg,unsigned int flags,bool forbid_cmsg_compat)2629e1834a32SDominik Brodowski long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned int flags,
2630e1834a32SDominik Brodowski 		   bool forbid_cmsg_compat)
2631228e548eSAnton Blanchard {
2632228e548eSAnton Blanchard 	int fput_needed, err;
2633228e548eSAnton Blanchard 	struct msghdr msg_sys;
26341be374a0SAndy Lutomirski 	struct socket *sock;
2635228e548eSAnton Blanchard 
2636e1834a32SDominik Brodowski 	if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT))
2637e1834a32SDominik Brodowski 		return -EINVAL;
2638e1834a32SDominik Brodowski 
26391be374a0SAndy Lutomirski 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2640228e548eSAnton Blanchard 	if (!sock)
2641228e548eSAnton Blanchard 		goto out;
2642228e548eSAnton Blanchard 
264328a94d8fSTom Herbert 	err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL, 0);
2644228e548eSAnton Blanchard 
26456cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
26461da177e4SLinus Torvalds out:
26471da177e4SLinus Torvalds 	return err;
26481da177e4SLinus Torvalds }
26491da177e4SLinus Torvalds 
SYSCALL_DEFINE3(sendmsg,int,fd,struct user_msghdr __user *,msg,unsigned int,flags)2650666547ffSAl Viro SYSCALL_DEFINE3(sendmsg, int, fd, struct user_msghdr __user *, msg, unsigned int, flags)
2651a7526eb5SAndy Lutomirski {
2652e1834a32SDominik Brodowski 	return __sys_sendmsg(fd, msg, flags, true);
2653a7526eb5SAndy Lutomirski }
2654a7526eb5SAndy Lutomirski 
2655228e548eSAnton Blanchard /*
2656228e548eSAnton Blanchard  *	Linux sendmmsg interface
2657228e548eSAnton Blanchard  */
2658228e548eSAnton Blanchard 
__sys_sendmmsg(int fd,struct mmsghdr __user * mmsg,unsigned int vlen,unsigned int flags,bool forbid_cmsg_compat)2659228e548eSAnton Blanchard int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2660e1834a32SDominik Brodowski 		   unsigned int flags, bool forbid_cmsg_compat)
2661228e548eSAnton Blanchard {
2662228e548eSAnton Blanchard 	int fput_needed, err, datagrams;
2663228e548eSAnton Blanchard 	struct socket *sock;
2664228e548eSAnton Blanchard 	struct mmsghdr __user *entry;
2665228e548eSAnton Blanchard 	struct compat_mmsghdr __user *compat_entry;
2666228e548eSAnton Blanchard 	struct msghdr msg_sys;
2667c71d8ebeSTetsuo Handa 	struct used_address used_address;
2668f092276dSTom Herbert 	unsigned int oflags = flags;
2669228e548eSAnton Blanchard 
2670e1834a32SDominik Brodowski 	if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT))
2671e1834a32SDominik Brodowski 		return -EINVAL;
2672e1834a32SDominik Brodowski 
267398382f41SAnton Blanchard 	if (vlen > UIO_MAXIOV)
267498382f41SAnton Blanchard 		vlen = UIO_MAXIOV;
2675228e548eSAnton Blanchard 
2676228e548eSAnton Blanchard 	datagrams = 0;
2677228e548eSAnton Blanchard 
2678228e548eSAnton Blanchard 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2679228e548eSAnton Blanchard 	if (!sock)
2680228e548eSAnton Blanchard 		return err;
2681228e548eSAnton Blanchard 
2682c71d8ebeSTetsuo Handa 	used_address.name_len = UINT_MAX;
2683228e548eSAnton Blanchard 	entry = mmsg;
2684228e548eSAnton Blanchard 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2685728ffb86SAnton Blanchard 	err = 0;
2686f092276dSTom Herbert 	flags |= MSG_BATCH;
2687228e548eSAnton Blanchard 
2688228e548eSAnton Blanchard 	while (datagrams < vlen) {
2689f092276dSTom Herbert 		if (datagrams == vlen - 1)
2690f092276dSTom Herbert 			flags = oflags;
2691f092276dSTom Herbert 
2692228e548eSAnton Blanchard 		if (MSG_CMSG_COMPAT & flags) {
2693666547ffSAl Viro 			err = ___sys_sendmsg(sock, (struct user_msghdr __user *)compat_entry,
269428a94d8fSTom Herbert 					     &msg_sys, flags, &used_address, MSG_EOR);
2695228e548eSAnton Blanchard 			if (err < 0)
2696228e548eSAnton Blanchard 				break;
2697228e548eSAnton Blanchard 			err = __put_user(err, &compat_entry->msg_len);
2698228e548eSAnton Blanchard 			++compat_entry;
2699228e548eSAnton Blanchard 		} else {
2700a7526eb5SAndy Lutomirski 			err = ___sys_sendmsg(sock,
2701666547ffSAl Viro 					     (struct user_msghdr __user *)entry,
270228a94d8fSTom Herbert 					     &msg_sys, flags, &used_address, MSG_EOR);
2703228e548eSAnton Blanchard 			if (err < 0)
2704228e548eSAnton Blanchard 				break;
2705228e548eSAnton Blanchard 			err = put_user(err, &entry->msg_len);
2706228e548eSAnton Blanchard 			++entry;
2707228e548eSAnton Blanchard 		}
2708228e548eSAnton Blanchard 
2709228e548eSAnton Blanchard 		if (err)
2710228e548eSAnton Blanchard 			break;
2711228e548eSAnton Blanchard 		++datagrams;
27123023898bSSoheil Hassas Yeganeh 		if (msg_data_left(&msg_sys))
27133023898bSSoheil Hassas Yeganeh 			break;
2714a78cb84cSEric Dumazet 		cond_resched();
2715228e548eSAnton Blanchard 	}
2716228e548eSAnton Blanchard 
2717228e548eSAnton Blanchard 	fput_light(sock->file, fput_needed);
2718228e548eSAnton Blanchard 
2719728ffb86SAnton Blanchard 	/* We only return an error if no datagrams were able to be sent */
2720728ffb86SAnton Blanchard 	if (datagrams != 0)
2721228e548eSAnton Blanchard 		return datagrams;
2722228e548eSAnton Blanchard 
2723228e548eSAnton Blanchard 	return err;
2724228e548eSAnton Blanchard }
2725228e548eSAnton Blanchard 
SYSCALL_DEFINE4(sendmmsg,int,fd,struct mmsghdr __user *,mmsg,unsigned int,vlen,unsigned int,flags)2726228e548eSAnton Blanchard SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
2727228e548eSAnton Blanchard 		unsigned int, vlen, unsigned int, flags)
2728228e548eSAnton Blanchard {
2729e1834a32SDominik Brodowski 	return __sys_sendmmsg(fd, mmsg, vlen, flags, true);
2730228e548eSAnton Blanchard }
2731228e548eSAnton Blanchard 
recvmsg_copy_msghdr(struct msghdr * msg,struct user_msghdr __user * umsg,unsigned flags,struct sockaddr __user ** uaddr,struct iovec ** iov)273203b1230cSJens Axboe int recvmsg_copy_msghdr(struct msghdr *msg,
27334257c8caSJens Axboe 			struct user_msghdr __user *umsg, unsigned flags,
27344257c8caSJens Axboe 			struct sockaddr __user **uaddr,
27354257c8caSJens Axboe 			struct iovec **iov)
27364257c8caSJens Axboe {
27374257c8caSJens Axboe 	ssize_t err;
27384257c8caSJens Axboe 
27394257c8caSJens Axboe 	if (MSG_CMSG_COMPAT & flags) {
27404257c8caSJens Axboe 		struct compat_msghdr __user *msg_compat;
27414257c8caSJens Axboe 
27424257c8caSJens Axboe 		msg_compat = (struct compat_msghdr __user *) umsg;
27434257c8caSJens Axboe 		err = get_compat_msghdr(msg, msg_compat, uaddr, iov);
27444257c8caSJens Axboe 	} else {
27454257c8caSJens Axboe 		err = copy_msghdr_from_user(msg, umsg, uaddr, iov);
27464257c8caSJens Axboe 	}
27474257c8caSJens Axboe 	if (err < 0)
27484257c8caSJens Axboe 		return err;
27494257c8caSJens Axboe 
27504257c8caSJens Axboe 	return 0;
27514257c8caSJens Axboe }
27524257c8caSJens Axboe 
____sys_recvmsg(struct socket * sock,struct msghdr * msg_sys,struct user_msghdr __user * msg,struct sockaddr __user * uaddr,unsigned int flags,int nosec)27534257c8caSJens Axboe static int ____sys_recvmsg(struct socket *sock, struct msghdr *msg_sys,
27544257c8caSJens Axboe 			   struct user_msghdr __user *msg,
27554257c8caSJens Axboe 			   struct sockaddr __user *uaddr,
27564257c8caSJens Axboe 			   unsigned int flags, int nosec)
27571da177e4SLinus Torvalds {
275889bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
275989bddce5SStephen Hemminger 					(struct compat_msghdr __user *) msg;
27604257c8caSJens Axboe 	int __user *uaddr_len = COMPAT_NAMELEN(msg);
27614257c8caSJens Axboe 	struct sockaddr_storage addr;
27621da177e4SLinus Torvalds 	unsigned long cmsg_ptr;
27632da62906SAl Viro 	int len;
276408adb7daSAl Viro 	ssize_t err;
27651da177e4SLinus Torvalds 
276608adb7daSAl Viro 	msg_sys->msg_name = &addr;
2767a2e27255SArnaldo Carvalho de Melo 	cmsg_ptr = (unsigned long)msg_sys->msg_control;
2768a2e27255SArnaldo Carvalho de Melo 	msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
27691da177e4SLinus Torvalds 
2770f3d33426SHannes Frederic Sowa 	/* We assume all kernel code knows the size of sockaddr_storage */
2771f3d33426SHannes Frederic Sowa 	msg_sys->msg_namelen = 0;
2772f3d33426SHannes Frederic Sowa 
27731da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
27741da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
27751af66221SEric Dumazet 
27761af66221SEric Dumazet 	if (unlikely(nosec))
27771af66221SEric Dumazet 		err = sock_recvmsg_nosec(sock, msg_sys, flags);
27781af66221SEric Dumazet 	else
27791af66221SEric Dumazet 		err = sock_recvmsg(sock, msg_sys, flags);
27801af66221SEric Dumazet 
27811da177e4SLinus Torvalds 	if (err < 0)
27824257c8caSJens Axboe 		goto out;
27831da177e4SLinus Torvalds 	len = err;
27841da177e4SLinus Torvalds 
27851da177e4SLinus Torvalds 	if (uaddr != NULL) {
278643db362dSMaciej Żenczykowski 		err = move_addr_to_user(&addr,
2787a2e27255SArnaldo Carvalho de Melo 					msg_sys->msg_namelen, uaddr,
278889bddce5SStephen Hemminger 					uaddr_len);
27891da177e4SLinus Torvalds 		if (err < 0)
27904257c8caSJens Axboe 			goto out;
27911da177e4SLinus Torvalds 	}
2792a2e27255SArnaldo Carvalho de Melo 	err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
279337f7f421SDavid S. Miller 			 COMPAT_FLAGS(msg));
27941da177e4SLinus Torvalds 	if (err)
27954257c8caSJens Axboe 		goto out;
27961da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags)
2797a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
27981da177e4SLinus Torvalds 				 &msg_compat->msg_controllen);
27991da177e4SLinus Torvalds 	else
2800a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
28011da177e4SLinus Torvalds 				 &msg->msg_controllen);
28021da177e4SLinus Torvalds 	if (err)
28034257c8caSJens Axboe 		goto out;
28041da177e4SLinus Torvalds 	err = len;
28054257c8caSJens Axboe out:
28064257c8caSJens Axboe 	return err;
28074257c8caSJens Axboe }
28081da177e4SLinus Torvalds 
___sys_recvmsg(struct socket * sock,struct user_msghdr __user * msg,struct msghdr * msg_sys,unsigned int flags,int nosec)28094257c8caSJens Axboe static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg,
28104257c8caSJens Axboe 			 struct msghdr *msg_sys, unsigned int flags, int nosec)
28114257c8caSJens Axboe {
28124257c8caSJens Axboe 	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
28134257c8caSJens Axboe 	/* user mode address pointers */
28144257c8caSJens Axboe 	struct sockaddr __user *uaddr;
28154257c8caSJens Axboe 	ssize_t err;
28164257c8caSJens Axboe 
28174257c8caSJens Axboe 	err = recvmsg_copy_msghdr(msg_sys, msg, flags, &uaddr, &iov);
28184257c8caSJens Axboe 	if (err < 0)
28194257c8caSJens Axboe 		return err;
28204257c8caSJens Axboe 
28214257c8caSJens Axboe 	err = ____sys_recvmsg(sock, msg_sys, msg, uaddr, flags, nosec);
2822a74e9106SEric Dumazet 	kfree(iov);
2823a2e27255SArnaldo Carvalho de Melo 	return err;
2824a2e27255SArnaldo Carvalho de Melo }
2825a2e27255SArnaldo Carvalho de Melo 
2826a2e27255SArnaldo Carvalho de Melo /*
2827a2e27255SArnaldo Carvalho de Melo  *	BSD recvmsg interface
2828a2e27255SArnaldo Carvalho de Melo  */
2829a2e27255SArnaldo Carvalho de Melo 
__sys_recvmsg_sock(struct socket * sock,struct msghdr * msg,struct user_msghdr __user * umsg,struct sockaddr __user * uaddr,unsigned int flags)283003b1230cSJens Axboe long __sys_recvmsg_sock(struct socket *sock, struct msghdr *msg,
283103b1230cSJens Axboe 			struct user_msghdr __user *umsg,
283203b1230cSJens Axboe 			struct sockaddr __user *uaddr, unsigned int flags)
2833aa1fa28fSJens Axboe {
283403b1230cSJens Axboe 	return ____sys_recvmsg(sock, msg, umsg, uaddr, flags, 0);
2835aa1fa28fSJens Axboe }
2836aa1fa28fSJens Axboe 
__sys_recvmsg(int fd,struct user_msghdr __user * msg,unsigned int flags,bool forbid_cmsg_compat)2837e1834a32SDominik Brodowski long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned int flags,
2838e1834a32SDominik Brodowski 		   bool forbid_cmsg_compat)
2839a2e27255SArnaldo Carvalho de Melo {
2840a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err;
2841a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
28421be374a0SAndy Lutomirski 	struct socket *sock;
2843a2e27255SArnaldo Carvalho de Melo 
2844e1834a32SDominik Brodowski 	if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT))
2845e1834a32SDominik Brodowski 		return -EINVAL;
2846e1834a32SDominik Brodowski 
28471be374a0SAndy Lutomirski 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2848a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2849a2e27255SArnaldo Carvalho de Melo 		goto out;
2850a2e27255SArnaldo Carvalho de Melo 
2851a7526eb5SAndy Lutomirski 	err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0);
2852a2e27255SArnaldo Carvalho de Melo 
28536cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
28541da177e4SLinus Torvalds out:
28551da177e4SLinus Torvalds 	return err;
28561da177e4SLinus Torvalds }
28571da177e4SLinus Torvalds 
SYSCALL_DEFINE3(recvmsg,int,fd,struct user_msghdr __user *,msg,unsigned int,flags)2858666547ffSAl Viro SYSCALL_DEFINE3(recvmsg, int, fd, struct user_msghdr __user *, msg,
2859a7526eb5SAndy Lutomirski 		unsigned int, flags)
2860a7526eb5SAndy Lutomirski {
2861e1834a32SDominik Brodowski 	return __sys_recvmsg(fd, msg, flags, true);
2862a7526eb5SAndy Lutomirski }
2863a7526eb5SAndy Lutomirski 
2864a2e27255SArnaldo Carvalho de Melo /*
2865a2e27255SArnaldo Carvalho de Melo  *     Linux recvmmsg interface
2866a2e27255SArnaldo Carvalho de Melo  */
28671da177e4SLinus Torvalds 
do_recvmmsg(int fd,struct mmsghdr __user * mmsg,unsigned int vlen,unsigned int flags,struct timespec64 * timeout)2868e11d4284SArnd Bergmann static int do_recvmmsg(int fd, struct mmsghdr __user *mmsg,
2869e11d4284SArnd Bergmann 			  unsigned int vlen, unsigned int flags,
2870e11d4284SArnd Bergmann 			  struct timespec64 *timeout)
2871a2e27255SArnaldo Carvalho de Melo {
2872a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err, datagrams;
2873a2e27255SArnaldo Carvalho de Melo 	struct socket *sock;
2874a2e27255SArnaldo Carvalho de Melo 	struct mmsghdr __user *entry;
2875d7256d0eSJean-Mickael Guerin 	struct compat_mmsghdr __user *compat_entry;
2876a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
2877766b9f92SDeepa Dinamani 	struct timespec64 end_time;
2878766b9f92SDeepa Dinamani 	struct timespec64 timeout64;
2879a2e27255SArnaldo Carvalho de Melo 
2880a2e27255SArnaldo Carvalho de Melo 	if (timeout &&
2881a2e27255SArnaldo Carvalho de Melo 	    poll_select_set_timeout(&end_time, timeout->tv_sec,
2882a2e27255SArnaldo Carvalho de Melo 				    timeout->tv_nsec))
2883a2e27255SArnaldo Carvalho de Melo 		return -EINVAL;
2884a2e27255SArnaldo Carvalho de Melo 
2885a2e27255SArnaldo Carvalho de Melo 	datagrams = 0;
2886a2e27255SArnaldo Carvalho de Melo 
2887a2e27255SArnaldo Carvalho de Melo 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2888a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2889a2e27255SArnaldo Carvalho de Melo 		return err;
2890a2e27255SArnaldo Carvalho de Melo 
28917797dc41SSoheil Hassas Yeganeh 	if (likely(!(flags & MSG_ERRQUEUE))) {
2892a2e27255SArnaldo Carvalho de Melo 		err = sock_error(sock->sk);
2893e623a9e9SMaxime Jayat 		if (err) {
2894e623a9e9SMaxime Jayat 			datagrams = err;
2895a2e27255SArnaldo Carvalho de Melo 			goto out_put;
2896e623a9e9SMaxime Jayat 		}
28977797dc41SSoheil Hassas Yeganeh 	}
2898a2e27255SArnaldo Carvalho de Melo 
2899a2e27255SArnaldo Carvalho de Melo 	entry = mmsg;
2900d7256d0eSJean-Mickael Guerin 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2901a2e27255SArnaldo Carvalho de Melo 
2902a2e27255SArnaldo Carvalho de Melo 	while (datagrams < vlen) {
2903a2e27255SArnaldo Carvalho de Melo 		/*
2904a2e27255SArnaldo Carvalho de Melo 		 * No need to ask LSM for more than the first datagram.
2905a2e27255SArnaldo Carvalho de Melo 		 */
2906d7256d0eSJean-Mickael Guerin 		if (MSG_CMSG_COMPAT & flags) {
2907666547ffSAl Viro 			err = ___sys_recvmsg(sock, (struct user_msghdr __user *)compat_entry,
2908b9eb8b87SAnton Blanchard 					     &msg_sys, flags & ~MSG_WAITFORONE,
2909b9eb8b87SAnton Blanchard 					     datagrams);
2910d7256d0eSJean-Mickael Guerin 			if (err < 0)
2911d7256d0eSJean-Mickael Guerin 				break;
2912d7256d0eSJean-Mickael Guerin 			err = __put_user(err, &compat_entry->msg_len);
2913d7256d0eSJean-Mickael Guerin 			++compat_entry;
2914d7256d0eSJean-Mickael Guerin 		} else {
2915a7526eb5SAndy Lutomirski 			err = ___sys_recvmsg(sock,
2916666547ffSAl Viro 					     (struct user_msghdr __user *)entry,
2917b9eb8b87SAnton Blanchard 					     &msg_sys, flags & ~MSG_WAITFORONE,
2918b9eb8b87SAnton Blanchard 					     datagrams);
2919a2e27255SArnaldo Carvalho de Melo 			if (err < 0)
2920a2e27255SArnaldo Carvalho de Melo 				break;
2921a2e27255SArnaldo Carvalho de Melo 			err = put_user(err, &entry->msg_len);
2922d7256d0eSJean-Mickael Guerin 			++entry;
2923d7256d0eSJean-Mickael Guerin 		}
2924d7256d0eSJean-Mickael Guerin 
2925a2e27255SArnaldo Carvalho de Melo 		if (err)
2926a2e27255SArnaldo Carvalho de Melo 			break;
2927a2e27255SArnaldo Carvalho de Melo 		++datagrams;
2928a2e27255SArnaldo Carvalho de Melo 
292971c5c159SBrandon L Black 		/* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
293071c5c159SBrandon L Black 		if (flags & MSG_WAITFORONE)
293171c5c159SBrandon L Black 			flags |= MSG_DONTWAIT;
293271c5c159SBrandon L Black 
2933a2e27255SArnaldo Carvalho de Melo 		if (timeout) {
2934766b9f92SDeepa Dinamani 			ktime_get_ts64(&timeout64);
2935c2e6c856SArnd Bergmann 			*timeout = timespec64_sub(end_time, timeout64);
2936a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_sec < 0) {
2937a2e27255SArnaldo Carvalho de Melo 				timeout->tv_sec = timeout->tv_nsec = 0;
2938a2e27255SArnaldo Carvalho de Melo 				break;
2939a2e27255SArnaldo Carvalho de Melo 			}
2940a2e27255SArnaldo Carvalho de Melo 
2941a2e27255SArnaldo Carvalho de Melo 			/* Timeout, return less than vlen datagrams */
2942a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_nsec == 0 && timeout->tv_sec == 0)
2943a2e27255SArnaldo Carvalho de Melo 				break;
2944a2e27255SArnaldo Carvalho de Melo 		}
2945a2e27255SArnaldo Carvalho de Melo 
2946a2e27255SArnaldo Carvalho de Melo 		/* Out of band data, return right away */
2947a2e27255SArnaldo Carvalho de Melo 		if (msg_sys.msg_flags & MSG_OOB)
2948a2e27255SArnaldo Carvalho de Melo 			break;
2949a78cb84cSEric Dumazet 		cond_resched();
2950a2e27255SArnaldo Carvalho de Melo 	}
2951a2e27255SArnaldo Carvalho de Melo 
2952a2e27255SArnaldo Carvalho de Melo 	if (err == 0)
295334b88a68SArnaldo Carvalho de Melo 		goto out_put;
2954a2e27255SArnaldo Carvalho de Melo 
295534b88a68SArnaldo Carvalho de Melo 	if (datagrams == 0) {
295634b88a68SArnaldo Carvalho de Melo 		datagrams = err;
295734b88a68SArnaldo Carvalho de Melo 		goto out_put;
295834b88a68SArnaldo Carvalho de Melo 	}
295934b88a68SArnaldo Carvalho de Melo 
2960a2e27255SArnaldo Carvalho de Melo 	/*
2961a2e27255SArnaldo Carvalho de Melo 	 * We may return less entries than requested (vlen) if the
2962a2e27255SArnaldo Carvalho de Melo 	 * sock is non block and there aren't enough datagrams...
2963a2e27255SArnaldo Carvalho de Melo 	 */
2964a2e27255SArnaldo Carvalho de Melo 	if (err != -EAGAIN) {
2965a2e27255SArnaldo Carvalho de Melo 		/*
2966a2e27255SArnaldo Carvalho de Melo 		 * ... or  if recvmsg returns an error after we
2967a2e27255SArnaldo Carvalho de Melo 		 * received some datagrams, where we record the
2968a2e27255SArnaldo Carvalho de Melo 		 * error to return on the next call or if the
2969a2e27255SArnaldo Carvalho de Melo 		 * app asks about it using getsockopt(SO_ERROR).
2970a2e27255SArnaldo Carvalho de Melo 		 */
2971e05a5f51SEric Dumazet 		WRITE_ONCE(sock->sk->sk_err, -err);
2972a2e27255SArnaldo Carvalho de Melo 	}
297334b88a68SArnaldo Carvalho de Melo out_put:
297434b88a68SArnaldo Carvalho de Melo 	fput_light(sock->file, fput_needed);
2975a2e27255SArnaldo Carvalho de Melo 
2976a2e27255SArnaldo Carvalho de Melo 	return datagrams;
2977a2e27255SArnaldo Carvalho de Melo }
2978a2e27255SArnaldo 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)2979e11d4284SArnd Bergmann int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg,
29801255e269SDominik Brodowski 		   unsigned int vlen, unsigned int flags,
2981e11d4284SArnd Bergmann 		   struct __kernel_timespec __user *timeout,
2982e11d4284SArnd Bergmann 		   struct old_timespec32 __user *timeout32)
2983a2e27255SArnaldo Carvalho de Melo {
2984a2e27255SArnaldo Carvalho de Melo 	int datagrams;
2985c2e6c856SArnd Bergmann 	struct timespec64 timeout_sys;
2986a2e27255SArnaldo Carvalho de Melo 
2987e11d4284SArnd Bergmann 	if (timeout && get_timespec64(&timeout_sys, timeout))
2988a2e27255SArnaldo Carvalho de Melo 		return -EFAULT;
2989a2e27255SArnaldo Carvalho de Melo 
2990e11d4284SArnd Bergmann 	if (timeout32 && get_old_timespec32(&timeout_sys, timeout32))
2991e11d4284SArnd Bergmann 		return -EFAULT;
2992a2e27255SArnaldo Carvalho de Melo 
2993e11d4284SArnd Bergmann 	if (!timeout && !timeout32)
2994e11d4284SArnd Bergmann 		return do_recvmmsg(fd, mmsg, vlen, flags, NULL);
2995e11d4284SArnd Bergmann 
2996e11d4284SArnd Bergmann 	datagrams = do_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys);
2997e11d4284SArnd Bergmann 
2998e11d4284SArnd Bergmann 	if (datagrams <= 0)
2999e11d4284SArnd Bergmann 		return datagrams;
3000e11d4284SArnd Bergmann 
3001e11d4284SArnd Bergmann 	if (timeout && put_timespec64(&timeout_sys, timeout))
3002e11d4284SArnd Bergmann 		datagrams = -EFAULT;
3003e11d4284SArnd Bergmann 
3004e11d4284SArnd Bergmann 	if (timeout32 && put_old_timespec32(&timeout_sys, timeout32))
3005a2e27255SArnaldo Carvalho de Melo 		datagrams = -EFAULT;
3006a2e27255SArnaldo Carvalho de Melo 
3007a2e27255SArnaldo Carvalho de Melo 	return datagrams;
3008a2e27255SArnaldo Carvalho de Melo }
3009a2e27255SArnaldo Carvalho de Melo 
SYSCALL_DEFINE5(recvmmsg,int,fd,struct mmsghdr __user *,mmsg,unsigned int,vlen,unsigned int,flags,struct __kernel_timespec __user *,timeout)30101255e269SDominik Brodowski SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
30111255e269SDominik Brodowski 		unsigned int, vlen, unsigned int, flags,
3012c2e6c856SArnd Bergmann 		struct __kernel_timespec __user *, timeout)
30131255e269SDominik Brodowski {
3014e11d4284SArnd Bergmann 	if (flags & MSG_CMSG_COMPAT)
3015e11d4284SArnd Bergmann 		return -EINVAL;
3016e11d4284SArnd Bergmann 
3017e11d4284SArnd Bergmann 	return __sys_recvmmsg(fd, mmsg, vlen, flags, timeout, NULL);
30181255e269SDominik Brodowski }
30191255e269SDominik Brodowski 
3020e11d4284SArnd Bergmann #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)3021e11d4284SArnd Bergmann SYSCALL_DEFINE5(recvmmsg_time32, int, fd, struct mmsghdr __user *, mmsg,
3022e11d4284SArnd Bergmann 		unsigned int, vlen, unsigned int, flags,
3023e11d4284SArnd Bergmann 		struct old_timespec32 __user *, timeout)
3024e11d4284SArnd Bergmann {
3025e11d4284SArnd Bergmann 	if (flags & MSG_CMSG_COMPAT)
3026e11d4284SArnd Bergmann 		return -EINVAL;
3027e11d4284SArnd Bergmann 
3028e11d4284SArnd Bergmann 	return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL, timeout);
3029e11d4284SArnd Bergmann }
3030e11d4284SArnd Bergmann #endif
3031e11d4284SArnd Bergmann 
3032a2e27255SArnaldo Carvalho de Melo #ifdef __ARCH_WANT_SYS_SOCKETCALL
30331da177e4SLinus Torvalds /* Argument list sizes for sys_socketcall */
30341da177e4SLinus Torvalds #define AL(x) ((x) * sizeof(unsigned long))
3035228e548eSAnton Blanchard static const unsigned char nargs[21] = {
303689bddce5SStephen Hemminger 	AL(0), AL(3), AL(3), AL(3), AL(2), AL(3),
30371da177e4SLinus Torvalds 	AL(3), AL(3), AL(4), AL(4), AL(4), AL(6),
3038aaca0bdcSUlrich Drepper 	AL(6), AL(2), AL(5), AL(5), AL(3), AL(3),
3039228e548eSAnton Blanchard 	AL(4), AL(5), AL(4)
304089bddce5SStephen Hemminger };
304189bddce5SStephen Hemminger 
30421da177e4SLinus Torvalds #undef AL
30431da177e4SLinus Torvalds 
30441da177e4SLinus Torvalds /*
30451da177e4SLinus Torvalds  *	System call vectors.
30461da177e4SLinus Torvalds  *
30471da177e4SLinus Torvalds  *	Argument checking cleaned up. Saved 20% in size.
30481da177e4SLinus Torvalds  *  This function doesn't need to set the kernel lock because
30491da177e4SLinus Torvalds  *  it is set by the callees.
30501da177e4SLinus Torvalds  */
30511da177e4SLinus Torvalds 
SYSCALL_DEFINE2(socketcall,int,call,unsigned long __user *,args)30523e0fa65fSHeiko Carstens SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
30531da177e4SLinus Torvalds {
30542950fa9dSChen Gang 	unsigned long a[AUDITSC_ARGS];
30551da177e4SLinus Torvalds 	unsigned long a0, a1;
30561da177e4SLinus Torvalds 	int err;
305747379052SArjan van de Ven 	unsigned int len;
30581da177e4SLinus Torvalds 
3059228e548eSAnton Blanchard 	if (call < 1 || call > SYS_SENDMMSG)
30601da177e4SLinus Torvalds 		return -EINVAL;
3061c8e8cd57SJeremy Cline 	call = array_index_nospec(call, SYS_SENDMMSG + 1);
30621da177e4SLinus Torvalds 
306347379052SArjan van de Ven 	len = nargs[call];
306447379052SArjan van de Ven 	if (len > sizeof(a))
306547379052SArjan van de Ven 		return -EINVAL;
306647379052SArjan van de Ven 
30671da177e4SLinus Torvalds 	/* copy_from_user should be SMP safe. */
306847379052SArjan van de Ven 	if (copy_from_user(a, args, len))
30691da177e4SLinus Torvalds 		return -EFAULT;
30701da177e4SLinus Torvalds 
30712950fa9dSChen Gang 	err = audit_socketcall(nargs[call] / sizeof(unsigned long), a);
30722950fa9dSChen Gang 	if (err)
30732950fa9dSChen Gang 		return err;
30743ec3b2fbSDavid Woodhouse 
30751da177e4SLinus Torvalds 	a0 = a[0];
30761da177e4SLinus Torvalds 	a1 = a[1];
30771da177e4SLinus Torvalds 
307889bddce5SStephen Hemminger 	switch (call) {
30791da177e4SLinus Torvalds 	case SYS_SOCKET:
30809d6a15c3SDominik Brodowski 		err = __sys_socket(a0, a1, a[2]);
30811da177e4SLinus Torvalds 		break;
30821da177e4SLinus Torvalds 	case SYS_BIND:
3083a87d35d8SDominik Brodowski 		err = __sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
30841da177e4SLinus Torvalds 		break;
30851da177e4SLinus Torvalds 	case SYS_CONNECT:
30861387c2c2SDominik Brodowski 		err = __sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
30871da177e4SLinus Torvalds 		break;
30881da177e4SLinus Torvalds 	case SYS_LISTEN:
308925e290eeSDominik Brodowski 		err = __sys_listen(a0, a1);
30901da177e4SLinus Torvalds 		break;
30911da177e4SLinus Torvalds 	case SYS_ACCEPT:
30924541e805SDominik Brodowski 		err = __sys_accept4(a0, (struct sockaddr __user *)a1,
3093aaca0bdcSUlrich Drepper 				    (int __user *)a[2], 0);
30941da177e4SLinus Torvalds 		break;
30951da177e4SLinus Torvalds 	case SYS_GETSOCKNAME:
309689bddce5SStephen Hemminger 		err =
30978882a107SDominik Brodowski 		    __sys_getsockname(a0, (struct sockaddr __user *)a1,
309889bddce5SStephen Hemminger 				      (int __user *)a[2]);
30991da177e4SLinus Torvalds 		break;
31001da177e4SLinus Torvalds 	case SYS_GETPEERNAME:
310189bddce5SStephen Hemminger 		err =
3102b21c8f83SDominik Brodowski 		    __sys_getpeername(a0, (struct sockaddr __user *)a1,
310389bddce5SStephen Hemminger 				      (int __user *)a[2]);
31041da177e4SLinus Torvalds 		break;
31051da177e4SLinus Torvalds 	case SYS_SOCKETPAIR:
31066debc8d8SDominik Brodowski 		err = __sys_socketpair(a0, a1, a[2], (int __user *)a[3]);
31071da177e4SLinus Torvalds 		break;
31081da177e4SLinus Torvalds 	case SYS_SEND:
3109f3bf896bSDominik Brodowski 		err = __sys_sendto(a0, (void __user *)a1, a[2], a[3],
3110f3bf896bSDominik Brodowski 				   NULL, 0);
31111da177e4SLinus Torvalds 		break;
31121da177e4SLinus Torvalds 	case SYS_SENDTO:
3113211b634bSDominik Brodowski 		err = __sys_sendto(a0, (void __user *)a1, a[2], a[3],
31141da177e4SLinus Torvalds 				   (struct sockaddr __user *)a[4], a[5]);
31151da177e4SLinus Torvalds 		break;
31161da177e4SLinus Torvalds 	case SYS_RECV:
3117d27e9afcSDominik Brodowski 		err = __sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
3118d27e9afcSDominik Brodowski 				     NULL, NULL);
31191da177e4SLinus Torvalds 		break;
31201da177e4SLinus Torvalds 	case SYS_RECVFROM:
31217a09e1ebSDominik Brodowski 		err = __sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
312289bddce5SStephen Hemminger 				     (struct sockaddr __user *)a[4],
312389bddce5SStephen Hemminger 				     (int __user *)a[5]);
31241da177e4SLinus Torvalds 		break;
31251da177e4SLinus Torvalds 	case SYS_SHUTDOWN:
3126005a1aeaSDominik Brodowski 		err = __sys_shutdown(a0, a1);
31271da177e4SLinus Torvalds 		break;
31281da177e4SLinus Torvalds 	case SYS_SETSOCKOPT:
3129cc36dca0SDominik Brodowski 		err = __sys_setsockopt(a0, a1, a[2], (char __user *)a[3],
3130cc36dca0SDominik Brodowski 				       a[4]);
31311da177e4SLinus Torvalds 		break;
31321da177e4SLinus Torvalds 	case SYS_GETSOCKOPT:
313389bddce5SStephen Hemminger 		err =
313413a2d70eSDominik Brodowski 		    __sys_getsockopt(a0, a1, a[2], (char __user *)a[3],
313589bddce5SStephen Hemminger 				     (int __user *)a[4]);
31361da177e4SLinus Torvalds 		break;
31371da177e4SLinus Torvalds 	case SYS_SENDMSG:
3138e1834a32SDominik Brodowski 		err = __sys_sendmsg(a0, (struct user_msghdr __user *)a1,
3139e1834a32SDominik Brodowski 				    a[2], true);
31401da177e4SLinus Torvalds 		break;
3141228e548eSAnton Blanchard 	case SYS_SENDMMSG:
3142e1834a32SDominik Brodowski 		err = __sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2],
3143e1834a32SDominik Brodowski 				     a[3], true);
3144228e548eSAnton Blanchard 		break;
31451da177e4SLinus Torvalds 	case SYS_RECVMSG:
3146e1834a32SDominik Brodowski 		err = __sys_recvmsg(a0, (struct user_msghdr __user *)a1,
3147e1834a32SDominik Brodowski 				    a[2], true);
31481da177e4SLinus Torvalds 		break;
3149a2e27255SArnaldo Carvalho de Melo 	case SYS_RECVMMSG:
31503ca47e95SArnd Bergmann 		if (IS_ENABLED(CONFIG_64BIT))
3151e11d4284SArnd Bergmann 			err = __sys_recvmmsg(a0, (struct mmsghdr __user *)a1,
3152e11d4284SArnd Bergmann 					     a[2], a[3],
3153e11d4284SArnd Bergmann 					     (struct __kernel_timespec __user *)a[4],
3154e11d4284SArnd Bergmann 					     NULL);
3155e11d4284SArnd Bergmann 		else
3156e11d4284SArnd Bergmann 			err = __sys_recvmmsg(a0, (struct mmsghdr __user *)a1,
3157e11d4284SArnd Bergmann 					     a[2], a[3], NULL,
3158e11d4284SArnd Bergmann 					     (struct old_timespec32 __user *)a[4]);
3159a2e27255SArnaldo Carvalho de Melo 		break;
3160de11defeSUlrich Drepper 	case SYS_ACCEPT4:
31614541e805SDominik Brodowski 		err = __sys_accept4(a0, (struct sockaddr __user *)a1,
3162de11defeSUlrich Drepper 				    (int __user *)a[2], a[3]);
3163aaca0bdcSUlrich Drepper 		break;
31641da177e4SLinus Torvalds 	default:
31651da177e4SLinus Torvalds 		err = -EINVAL;
31661da177e4SLinus Torvalds 		break;
31671da177e4SLinus Torvalds 	}
31681da177e4SLinus Torvalds 	return err;
31691da177e4SLinus Torvalds }
31701da177e4SLinus Torvalds 
31711da177e4SLinus Torvalds #endif				/* __ARCH_WANT_SYS_SOCKETCALL */
31721da177e4SLinus Torvalds 
317355737fdaSStephen Hemminger /**
317455737fdaSStephen Hemminger  *	sock_register - add a socket protocol handler
317555737fdaSStephen Hemminger  *	@ops: description of protocol
317655737fdaSStephen Hemminger  *
31771da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
31781da177e4SLinus Torvalds  *	advertise its address family, and have it linked into the
3179e793c0f7SMasanari Iida  *	socket interface. The value ops->family corresponds to the
318055737fdaSStephen Hemminger  *	socket system call protocol family.
31811da177e4SLinus Torvalds  */
sock_register(const struct net_proto_family * ops)3182f0fd27d4SStephen Hemminger int sock_register(const struct net_proto_family *ops)
31831da177e4SLinus Torvalds {
31841da177e4SLinus Torvalds 	int err;
31851da177e4SLinus Torvalds 
31861da177e4SLinus Torvalds 	if (ops->family >= NPROTO) {
31873410f22eSYang Yingliang 		pr_crit("protocol %d >= NPROTO(%d)\n", ops->family, NPROTO);
31881da177e4SLinus Torvalds 		return -ENOBUFS;
31891da177e4SLinus Torvalds 	}
319055737fdaSStephen Hemminger 
319155737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
3192190683a9SEric Dumazet 	if (rcu_dereference_protected(net_families[ops->family],
3193190683a9SEric Dumazet 				      lockdep_is_held(&net_family_lock)))
31941da177e4SLinus Torvalds 		err = -EEXIST;
319555737fdaSStephen Hemminger 	else {
3196cf778b00SEric Dumazet 		rcu_assign_pointer(net_families[ops->family], ops);
31971da177e4SLinus Torvalds 		err = 0;
31981da177e4SLinus Torvalds 	}
319955737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
320055737fdaSStephen Hemminger 
3201fe0bdbdeSYejune Deng 	pr_info("NET: Registered %s protocol family\n", pf_family_names[ops->family]);
32021da177e4SLinus Torvalds 	return err;
32031da177e4SLinus Torvalds }
3204c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_register);
32051da177e4SLinus Torvalds 
320655737fdaSStephen Hemminger /**
320755737fdaSStephen Hemminger  *	sock_unregister - remove a protocol handler
320855737fdaSStephen Hemminger  *	@family: protocol family to remove
320955737fdaSStephen Hemminger  *
32101da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
32111da177e4SLinus Torvalds  *	remove its address family, and have it unlinked from the
321255737fdaSStephen Hemminger  *	new socket creation.
321355737fdaSStephen Hemminger  *
321455737fdaSStephen Hemminger  *	If protocol handler is a module, then it can use module reference
321555737fdaSStephen Hemminger  *	counts to protect against new references. If protocol handler is not
321655737fdaSStephen Hemminger  *	a module then it needs to provide its own protection in
321755737fdaSStephen Hemminger  *	the ops->create routine.
32181da177e4SLinus Torvalds  */
sock_unregister(int family)3219f0fd27d4SStephen Hemminger void sock_unregister(int family)
32201da177e4SLinus Torvalds {
3221f0fd27d4SStephen Hemminger 	BUG_ON(family < 0 || family >= NPROTO);
32221da177e4SLinus Torvalds 
322355737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
3224a9b3cd7fSStephen Hemminger 	RCU_INIT_POINTER(net_families[family], NULL);
322555737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
322655737fdaSStephen Hemminger 
322755737fdaSStephen Hemminger 	synchronize_rcu();
322855737fdaSStephen Hemminger 
3229fe0bdbdeSYejune Deng 	pr_info("NET: Unregistered %s protocol family\n", pf_family_names[family]);
32301da177e4SLinus Torvalds }
3231c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_unregister);
32321da177e4SLinus Torvalds 
sock_is_registered(int family)3233bf2ae2e4SXin Long bool sock_is_registered(int family)
3234bf2ae2e4SXin Long {
323566b51b0aSJeremy Cline 	return family < NPROTO && rcu_access_pointer(net_families[family]);
3236bf2ae2e4SXin Long }
3237bf2ae2e4SXin Long 
sock_init(void)323877d76ea3SAndi Kleen static int __init sock_init(void)
32391da177e4SLinus Torvalds {
3240b3e19d92SNick Piggin 	int err;
32412ca794e5SEric W. Biederman 	/*
32422ca794e5SEric W. Biederman 	 *      Initialize the network sysctl infrastructure.
32432ca794e5SEric W. Biederman 	 */
32442ca794e5SEric W. Biederman 	err = net_sysctl_init();
32452ca794e5SEric W. Biederman 	if (err)
32462ca794e5SEric W. Biederman 		goto out;
3247b3e19d92SNick Piggin 
32481da177e4SLinus Torvalds 	/*
32491da177e4SLinus Torvalds 	 *      Initialize skbuff SLAB cache
32501da177e4SLinus Torvalds 	 */
32511da177e4SLinus Torvalds 	skb_init();
32521da177e4SLinus Torvalds 
32531da177e4SLinus Torvalds 	/*
32541da177e4SLinus Torvalds 	 *      Initialize the protocols module.
32551da177e4SLinus Torvalds 	 */
32561da177e4SLinus Torvalds 
32571da177e4SLinus Torvalds 	init_inodecache();
3258b3e19d92SNick Piggin 
3259b3e19d92SNick Piggin 	err = register_filesystem(&sock_fs_type);
3260b3e19d92SNick Piggin 	if (err)
326147260ba9SMiaohe Lin 		goto out;
32621da177e4SLinus Torvalds 	sock_mnt = kern_mount(&sock_fs_type);
3263b3e19d92SNick Piggin 	if (IS_ERR(sock_mnt)) {
3264b3e19d92SNick Piggin 		err = PTR_ERR(sock_mnt);
3265b3e19d92SNick Piggin 		goto out_mount;
3266b3e19d92SNick Piggin 	}
326777d76ea3SAndi Kleen 
326877d76ea3SAndi Kleen 	/* The real protocol initialization is performed in later initcalls.
32691da177e4SLinus Torvalds 	 */
32701da177e4SLinus Torvalds 
32711da177e4SLinus Torvalds #ifdef CONFIG_NETFILTER
32726d11cfdbSPablo Neira Ayuso 	err = netfilter_init();
32736d11cfdbSPablo Neira Ayuso 	if (err)
32746d11cfdbSPablo Neira Ayuso 		goto out;
32751da177e4SLinus Torvalds #endif
3276cbeb321aSDavid S. Miller 
3277408eccceSDaniel Borkmann 	ptp_classifier_init();
3278c1f19b51SRichard Cochran 
3279b3e19d92SNick Piggin out:
3280b3e19d92SNick Piggin 	return err;
3281b3e19d92SNick Piggin 
3282b3e19d92SNick Piggin out_mount:
3283b3e19d92SNick Piggin 	unregister_filesystem(&sock_fs_type);
3284b3e19d92SNick Piggin 	goto out;
32851da177e4SLinus Torvalds }
32861da177e4SLinus Torvalds 
328777d76ea3SAndi Kleen core_initcall(sock_init);	/* early initcall */
328877d76ea3SAndi Kleen 
32891da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS
socket_seq_show(struct seq_file * seq)32901da177e4SLinus Torvalds void socket_seq_show(struct seq_file *seq)
32911da177e4SLinus Torvalds {
3292648845abSTonghao Zhang 	seq_printf(seq, "sockets: used %d\n",
3293648845abSTonghao Zhang 		   sock_inuse_get(seq->private));
32941da177e4SLinus Torvalds }
32951da177e4SLinus Torvalds #endif				/* CONFIG_PROC_FS */
32961da177e4SLinus Torvalds 
329729c49648SArnd Bergmann /* Handle the fact that while struct ifreq has the same *layout* on
329829c49648SArnd Bergmann  * 32/64 for everything but ifreq::ifru_ifmap and ifreq::ifru_data,
329929c49648SArnd Bergmann  * which are handled elsewhere, it still has different *size* due to
330029c49648SArnd Bergmann  * ifreq::ifru_ifmap (which is 16 bytes on 32 bit, 24 bytes on 64-bit,
330129c49648SArnd Bergmann  * resulting in struct ifreq being 32 and 40 bytes respectively).
330229c49648SArnd Bergmann  * As a result, if the struct happens to be at the end of a page and
330329c49648SArnd Bergmann  * the next page isn't readable/writable, we get a fault. To prevent
330429c49648SArnd Bergmann  * that, copy back and forth to the full size.
330529c49648SArnd Bergmann  */
get_user_ifreq(struct ifreq * ifr,void __user ** ifrdata,void __user * arg)330629c49648SArnd Bergmann int get_user_ifreq(struct ifreq *ifr, void __user **ifrdata, void __user *arg)
330729c49648SArnd Bergmann {
330829c49648SArnd Bergmann 	if (in_compat_syscall()) {
330929c49648SArnd Bergmann 		struct compat_ifreq *ifr32 = (struct compat_ifreq *)ifr;
331029c49648SArnd Bergmann 
331129c49648SArnd Bergmann 		memset(ifr, 0, sizeof(*ifr));
331229c49648SArnd Bergmann 		if (copy_from_user(ifr32, arg, sizeof(*ifr32)))
331329c49648SArnd Bergmann 			return -EFAULT;
331429c49648SArnd Bergmann 
331529c49648SArnd Bergmann 		if (ifrdata)
331629c49648SArnd Bergmann 			*ifrdata = compat_ptr(ifr32->ifr_data);
331729c49648SArnd Bergmann 
331829c49648SArnd Bergmann 		return 0;
331929c49648SArnd Bergmann 	}
332029c49648SArnd Bergmann 
332129c49648SArnd Bergmann 	if (copy_from_user(ifr, arg, sizeof(*ifr)))
332229c49648SArnd Bergmann 		return -EFAULT;
332329c49648SArnd Bergmann 
332429c49648SArnd Bergmann 	if (ifrdata)
332529c49648SArnd Bergmann 		*ifrdata = ifr->ifr_data;
332629c49648SArnd Bergmann 
332729c49648SArnd Bergmann 	return 0;
332829c49648SArnd Bergmann }
332929c49648SArnd Bergmann EXPORT_SYMBOL(get_user_ifreq);
333029c49648SArnd Bergmann 
put_user_ifreq(struct ifreq * ifr,void __user * arg)333129c49648SArnd Bergmann int put_user_ifreq(struct ifreq *ifr, void __user *arg)
333229c49648SArnd Bergmann {
333329c49648SArnd Bergmann 	size_t size = sizeof(*ifr);
333429c49648SArnd Bergmann 
333529c49648SArnd Bergmann 	if (in_compat_syscall())
333629c49648SArnd Bergmann 		size = sizeof(struct compat_ifreq);
333729c49648SArnd Bergmann 
333829c49648SArnd Bergmann 	if (copy_to_user(arg, ifr, size))
333929c49648SArnd Bergmann 		return -EFAULT;
334029c49648SArnd Bergmann 
334129c49648SArnd Bergmann 	return 0;
334229c49648SArnd Bergmann }
334329c49648SArnd Bergmann EXPORT_SYMBOL(put_user_ifreq);
334429c49648SArnd Bergmann 
334589bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
compat_siocwandev(struct net * net,struct compat_ifreq __user * uifr32)33467a50a240SArnd Bergmann static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32)
33477a50a240SArnd Bergmann {
33487a50a240SArnd Bergmann 	compat_uptr_t uptr32;
334944c02a2cSAl Viro 	struct ifreq ifr;
335044c02a2cSAl Viro 	void __user *saved;
335144c02a2cSAl Viro 	int err;
33527a50a240SArnd Bergmann 
335329c49648SArnd Bergmann 	if (get_user_ifreq(&ifr, NULL, uifr32))
33547a50a240SArnd Bergmann 		return -EFAULT;
33557a50a240SArnd Bergmann 
33567a50a240SArnd Bergmann 	if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu))
33577a50a240SArnd Bergmann 		return -EFAULT;
33587a50a240SArnd Bergmann 
335944c02a2cSAl Viro 	saved = ifr.ifr_settings.ifs_ifsu.raw_hdlc;
336044c02a2cSAl Viro 	ifr.ifr_settings.ifs_ifsu.raw_hdlc = compat_ptr(uptr32);
33617a50a240SArnd Bergmann 
3362a554bf96SArnd Bergmann 	err = dev_ioctl(net, SIOCWANDEV, &ifr, NULL, NULL);
336344c02a2cSAl Viro 	if (!err) {
336444c02a2cSAl Viro 		ifr.ifr_settings.ifs_ifsu.raw_hdlc = saved;
336529c49648SArnd Bergmann 		if (put_user_ifreq(&ifr, uifr32))
336644c02a2cSAl Viro 			err = -EFAULT;
33677a50a240SArnd Bergmann 	}
33687a229387SArnd Bergmann 	return err;
33697a229387SArnd Bergmann }
33707a229387SArnd Bergmann 
3371590d4693SBen Hutchings /* 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)3372590d4693SBen Hutchings static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd,
33736b96018bSArnd Bergmann 				 struct compat_ifreq __user *u_ifreq32)
33747a229387SArnd Bergmann {
337544c02a2cSAl Viro 	struct ifreq ifreq;
3376a554bf96SArnd Bergmann 	void __user *data;
33777a229387SArnd Bergmann 
3378d0efb162SPeter Collingbourne 	if (!is_socket_ioctl_cmd(cmd))
3379d0efb162SPeter Collingbourne 		return -ENOTTY;
3380a554bf96SArnd Bergmann 	if (get_user_ifreq(&ifreq, &data, u_ifreq32))
33817a229387SArnd Bergmann 		return -EFAULT;
3382a554bf96SArnd Bergmann 	ifreq.ifr_data = data;
33837a229387SArnd Bergmann 
3384a554bf96SArnd Bergmann 	return dev_ioctl(net, cmd, &ifreq, data, NULL);
33857a229387SArnd Bergmann }
33867a229387SArnd Bergmann 
compat_sock_ioctl_trans(struct file * file,struct socket * sock,unsigned int cmd,unsigned long arg)33876b96018bSArnd Bergmann static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
33886b96018bSArnd Bergmann 			 unsigned int cmd, unsigned long arg)
33896b96018bSArnd Bergmann {
33906b96018bSArnd Bergmann 	void __user *argp = compat_ptr(arg);
33916b96018bSArnd Bergmann 	struct sock *sk = sock->sk;
33926b96018bSArnd Bergmann 	struct net *net = sock_net(sk);
33931ded5e5aSEric Dumazet 	const struct proto_ops *ops;
33947a229387SArnd Bergmann 
33956b96018bSArnd Bergmann 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
339688fc023fSArnd Bergmann 		return sock_ioctl(file, cmd, (unsigned long)argp);
33977a229387SArnd Bergmann 
33986b96018bSArnd Bergmann 	switch (cmd) {
33997a50a240SArnd Bergmann 	case SIOCWANDEV:
34007a50a240SArnd Bergmann 		return compat_siocwandev(net, argp);
34010768e170SArnd Bergmann 	case SIOCGSTAMP_OLD:
34020768e170SArnd Bergmann 	case SIOCGSTAMPNS_OLD:
34031ded5e5aSEric Dumazet 		ops = READ_ONCE(sock->ops);
34041ded5e5aSEric Dumazet 		if (!ops->gettstamp)
3405c7cbdbf2SArnd Bergmann 			return -ENOIOCTLCMD;
34061ded5e5aSEric Dumazet 		return ops->gettstamp(sock, argp, cmd == SIOCGSTAMP_OLD,
3407c7cbdbf2SArnd Bergmann 				      !COMPAT_USE_64BIT_TIME);
3408c7cbdbf2SArnd Bergmann 
3409dd98d289SArnd Bergmann 	case SIOCETHTOOL:
3410590d4693SBen Hutchings 	case SIOCBONDSLAVEINFOQUERY:
3411590d4693SBen Hutchings 	case SIOCBONDINFOQUERY:
3412a2116ed2SArnd Bergmann 	case SIOCSHWTSTAMP:
3413fd468c74SBen Hutchings 	case SIOCGHWTSTAMP:
3414590d4693SBen Hutchings 		return compat_ifr_data_ioctl(net, cmd, argp);
34157a229387SArnd Bergmann 
34166b96018bSArnd Bergmann 	case FIOSETOWN:
34176b96018bSArnd Bergmann 	case SIOCSPGRP:
34186b96018bSArnd Bergmann 	case FIOGETOWN:
34196b96018bSArnd Bergmann 	case SIOCGPGRP:
34206b96018bSArnd Bergmann 	case SIOCBRADDBR:
34216b96018bSArnd Bergmann 	case SIOCBRDELBR:
34226b96018bSArnd Bergmann 	case SIOCGIFVLAN:
34236b96018bSArnd Bergmann 	case SIOCSIFVLAN:
3424c62cce2cSAndrey Vagin 	case SIOCGSKNS:
34250768e170SArnd Bergmann 	case SIOCGSTAMP_NEW:
34260768e170SArnd Bergmann 	case SIOCGSTAMPNS_NEW:
3427876f0bf9SArnd Bergmann 	case SIOCGIFCONF:
3428fd3a4590SRemi Pommarel 	case SIOCSIFBR:
3429fd3a4590SRemi Pommarel 	case SIOCGIFBR:
34306b96018bSArnd Bergmann 		return sock_ioctl(file, cmd, arg);
34316b96018bSArnd Bergmann 
34326b96018bSArnd Bergmann 	case SIOCGIFFLAGS:
34336b96018bSArnd Bergmann 	case SIOCSIFFLAGS:
3434709566d7SArnd Bergmann 	case SIOCGIFMAP:
3435709566d7SArnd Bergmann 	case SIOCSIFMAP:
34366b96018bSArnd Bergmann 	case SIOCGIFMETRIC:
34376b96018bSArnd Bergmann 	case SIOCSIFMETRIC:
34386b96018bSArnd Bergmann 	case SIOCGIFMTU:
34396b96018bSArnd Bergmann 	case SIOCSIFMTU:
34406b96018bSArnd Bergmann 	case SIOCGIFMEM:
34416b96018bSArnd Bergmann 	case SIOCSIFMEM:
34426b96018bSArnd Bergmann 	case SIOCGIFHWADDR:
34436b96018bSArnd Bergmann 	case SIOCSIFHWADDR:
34446b96018bSArnd Bergmann 	case SIOCADDMULTI:
34456b96018bSArnd Bergmann 	case SIOCDELMULTI:
34466b96018bSArnd Bergmann 	case SIOCGIFINDEX:
34476b96018bSArnd Bergmann 	case SIOCGIFADDR:
34486b96018bSArnd Bergmann 	case SIOCSIFADDR:
34496b96018bSArnd Bergmann 	case SIOCSIFHWBROADCAST:
34506b96018bSArnd Bergmann 	case SIOCDIFADDR:
34516b96018bSArnd Bergmann 	case SIOCGIFBRDADDR:
34526b96018bSArnd Bergmann 	case SIOCSIFBRDADDR:
34536b96018bSArnd Bergmann 	case SIOCGIFDSTADDR:
34546b96018bSArnd Bergmann 	case SIOCSIFDSTADDR:
34556b96018bSArnd Bergmann 	case SIOCGIFNETMASK:
34566b96018bSArnd Bergmann 	case SIOCSIFNETMASK:
34576b96018bSArnd Bergmann 	case SIOCSIFPFLAGS:
34586b96018bSArnd Bergmann 	case SIOCGIFPFLAGS:
34596b96018bSArnd Bergmann 	case SIOCGIFTXQLEN:
34606b96018bSArnd Bergmann 	case SIOCSIFTXQLEN:
34616b96018bSArnd Bergmann 	case SIOCBRADDIF:
34626b96018bSArnd Bergmann 	case SIOCBRDELIF:
3463c6c9fee3SJohannes Berg 	case SIOCGIFNAME:
34649177efd3SArnd Bergmann 	case SIOCSIFNAME:
34659177efd3SArnd Bergmann 	case SIOCGMIIPHY:
34669177efd3SArnd Bergmann 	case SIOCGMIIREG:
34679177efd3SArnd Bergmann 	case SIOCSMIIREG:
3468f92d4fc9SAl Viro 	case SIOCBONDENSLAVE:
3469f92d4fc9SAl Viro 	case SIOCBONDRELEASE:
3470f92d4fc9SAl Viro 	case SIOCBONDSETHWADDR:
3471f92d4fc9SAl Viro 	case SIOCBONDCHANGEACTIVE:
34726b96018bSArnd Bergmann 	case SIOCSARP:
34736b96018bSArnd Bergmann 	case SIOCGARP:
34746b96018bSArnd Bergmann 	case SIOCDARP:
3475c7dc504eSArnd Bergmann 	case SIOCOUTQ:
34769d7bf41fSArnd Bergmann 	case SIOCOUTQNSD:
34776b96018bSArnd Bergmann 	case SIOCATMARK:
347863ff03abSJohannes Berg 		return sock_do_ioctl(net, sock, cmd, arg);
34799177efd3SArnd Bergmann 	}
34809177efd3SArnd Bergmann 
34816b96018bSArnd Bergmann 	return -ENOIOCTLCMD;
34826b96018bSArnd Bergmann }
34837a229387SArnd Bergmann 
compat_sock_ioctl(struct file * file,unsigned int cmd,unsigned long arg)348495c96174SEric Dumazet static long compat_sock_ioctl(struct file *file, unsigned int cmd,
348589bbfc95SShaun Pereira 			      unsigned long arg)
348689bbfc95SShaun Pereira {
348789bbfc95SShaun Pereira 	struct socket *sock = file->private_data;
34881ded5e5aSEric Dumazet 	const struct proto_ops *ops = READ_ONCE(sock->ops);
348989bbfc95SShaun Pereira 	int ret = -ENOIOCTLCMD;
349087de87d5SDavid S. Miller 	struct sock *sk;
349187de87d5SDavid S. Miller 	struct net *net;
349287de87d5SDavid S. Miller 
349387de87d5SDavid S. Miller 	sk = sock->sk;
349487de87d5SDavid S. Miller 	net = sock_net(sk);
349589bbfc95SShaun Pereira 
34961ded5e5aSEric Dumazet 	if (ops->compat_ioctl)
34971ded5e5aSEric Dumazet 		ret = ops->compat_ioctl(sock, cmd, arg);
349889bbfc95SShaun Pereira 
349987de87d5SDavid S. Miller 	if (ret == -ENOIOCTLCMD &&
350087de87d5SDavid S. Miller 	    (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST))
350187de87d5SDavid S. Miller 		ret = compat_wext_handle_ioctl(net, cmd, arg);
350287de87d5SDavid S. Miller 
35036b96018bSArnd Bergmann 	if (ret == -ENOIOCTLCMD)
35046b96018bSArnd Bergmann 		ret = compat_sock_ioctl_trans(file, sock, cmd, arg);
35056b96018bSArnd Bergmann 
350689bbfc95SShaun Pereira 	return ret;
350789bbfc95SShaun Pereira }
350889bbfc95SShaun Pereira #endif
350989bbfc95SShaun Pereira 
35108a3c245cSPedro Tammela /**
35118a3c245cSPedro Tammela  *	kernel_bind - bind an address to a socket (kernel space)
35128a3c245cSPedro Tammela  *	@sock: socket
35138a3c245cSPedro Tammela  *	@addr: address
35148a3c245cSPedro Tammela  *	@addrlen: length of address
35158a3c245cSPedro Tammela  *
35168a3c245cSPedro Tammela  *	Returns 0 or an error.
35178a3c245cSPedro Tammela  */
35188a3c245cSPedro Tammela 
kernel_bind(struct socket * sock,struct sockaddr * addr,int addrlen)3519ac5a488eSSridhar Samudrala int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
3520ac5a488eSSridhar Samudrala {
3521c889a99aSJordan Rife 	struct sockaddr_storage address;
3522c889a99aSJordan Rife 
3523c889a99aSJordan Rife 	memcpy(&address, addr, addrlen);
3524c889a99aSJordan Rife 
3525c889a99aSJordan Rife 	return READ_ONCE(sock->ops)->bind(sock, (struct sockaddr *)&address,
3526c889a99aSJordan Rife 					  addrlen);
3527ac5a488eSSridhar Samudrala }
3528c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_bind);
3529ac5a488eSSridhar Samudrala 
35308a3c245cSPedro Tammela /**
35318a3c245cSPedro Tammela  *	kernel_listen - move socket to listening state (kernel space)
35328a3c245cSPedro Tammela  *	@sock: socket
35338a3c245cSPedro Tammela  *	@backlog: pending connections queue size
35348a3c245cSPedro Tammela  *
35358a3c245cSPedro Tammela  *	Returns 0 or an error.
35368a3c245cSPedro Tammela  */
35378a3c245cSPedro Tammela 
kernel_listen(struct socket * sock,int backlog)3538ac5a488eSSridhar Samudrala int kernel_listen(struct socket *sock, int backlog)
3539ac5a488eSSridhar Samudrala {
35401ded5e5aSEric Dumazet 	return READ_ONCE(sock->ops)->listen(sock, backlog);
3541ac5a488eSSridhar Samudrala }
3542c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_listen);
3543ac5a488eSSridhar Samudrala 
35448a3c245cSPedro Tammela /**
35458a3c245cSPedro Tammela  *	kernel_accept - accept a connection (kernel space)
35468a3c245cSPedro Tammela  *	@sock: listening socket
35478a3c245cSPedro Tammela  *	@newsock: new connected socket
35488a3c245cSPedro Tammela  *	@flags: flags
35498a3c245cSPedro Tammela  *
35508a3c245cSPedro Tammela  *	@flags must be SOCK_CLOEXEC, SOCK_NONBLOCK or 0.
35518a3c245cSPedro Tammela  *	If it fails, @newsock is guaranteed to be %NULL.
35528a3c245cSPedro Tammela  *	Returns 0 or an error.
35538a3c245cSPedro Tammela  */
35548a3c245cSPedro Tammela 
kernel_accept(struct socket * sock,struct socket ** newsock,int flags)3555ac5a488eSSridhar Samudrala int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
3556ac5a488eSSridhar Samudrala {
3557ac5a488eSSridhar Samudrala 	struct sock *sk = sock->sk;
35581ded5e5aSEric Dumazet 	const struct proto_ops *ops = READ_ONCE(sock->ops);
3559ac5a488eSSridhar Samudrala 	int err;
3560ac5a488eSSridhar Samudrala 
3561ac5a488eSSridhar Samudrala 	err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
3562ac5a488eSSridhar Samudrala 			       newsock);
3563ac5a488eSSridhar Samudrala 	if (err < 0)
3564ac5a488eSSridhar Samudrala 		goto done;
3565ac5a488eSSridhar Samudrala 
35661ded5e5aSEric Dumazet 	err = ops->accept(sock, *newsock, flags, true);
3567ac5a488eSSridhar Samudrala 	if (err < 0) {
3568ac5a488eSSridhar Samudrala 		sock_release(*newsock);
3569fa8705b0STony Battersby 		*newsock = NULL;
3570ac5a488eSSridhar Samudrala 		goto done;
3571ac5a488eSSridhar Samudrala 	}
3572ac5a488eSSridhar Samudrala 
35731ded5e5aSEric Dumazet 	(*newsock)->ops = ops;
35741ded5e5aSEric Dumazet 	__module_get(ops->owner);
3575ac5a488eSSridhar Samudrala 
3576ac5a488eSSridhar Samudrala done:
3577ac5a488eSSridhar Samudrala 	return err;
3578ac5a488eSSridhar Samudrala }
3579c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_accept);
3580ac5a488eSSridhar Samudrala 
35818a3c245cSPedro Tammela /**
35828a3c245cSPedro Tammela  *	kernel_connect - connect a socket (kernel space)
35838a3c245cSPedro Tammela  *	@sock: socket
35848a3c245cSPedro Tammela  *	@addr: address
35858a3c245cSPedro Tammela  *	@addrlen: address length
35868a3c245cSPedro Tammela  *	@flags: flags (O_NONBLOCK, ...)
35878a3c245cSPedro Tammela  *
3588f1dcffccSLu Wei  *	For datagram sockets, @addr is the address to which datagrams are sent
35898a3c245cSPedro Tammela  *	by default, and the only address from which datagrams are received.
35908a3c245cSPedro Tammela  *	For stream sockets, attempts to connect to @addr.
35918a3c245cSPedro Tammela  *	Returns 0 or an error code.
35928a3c245cSPedro Tammela  */
35938a3c245cSPedro Tammela 
kernel_connect(struct socket * sock,struct sockaddr * addr,int addrlen,int flags)3594ac5a488eSSridhar Samudrala int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
3595ac5a488eSSridhar Samudrala 		   int flags)
3596ac5a488eSSridhar Samudrala {
35970bdf3993SJordan Rife 	struct sockaddr_storage address;
35980bdf3993SJordan Rife 
35990bdf3993SJordan Rife 	memcpy(&address, addr, addrlen);
36000bdf3993SJordan Rife 
36010bdf3993SJordan Rife 	return READ_ONCE(sock->ops)->connect(sock, (struct sockaddr *)&address,
36020bdf3993SJordan Rife 					     addrlen, flags);
3603ac5a488eSSridhar Samudrala }
3604c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_connect);
3605ac5a488eSSridhar Samudrala 
36068a3c245cSPedro Tammela /**
36078a3c245cSPedro Tammela  *	kernel_getsockname - get the address which the socket is bound (kernel space)
36088a3c245cSPedro Tammela  *	@sock: socket
36098a3c245cSPedro Tammela  *	@addr: address holder
36108a3c245cSPedro Tammela  *
36118a3c245cSPedro Tammela  * 	Fills the @addr pointer with the address which the socket is bound.
36120fc95decSAlex Maydanik  *	Returns the length of the address in bytes or an error code.
36138a3c245cSPedro Tammela  */
36148a3c245cSPedro Tammela 
kernel_getsockname(struct socket * sock,struct sockaddr * addr)36159b2c45d4SDenys Vlasenko int kernel_getsockname(struct socket *sock, struct sockaddr *addr)
3616ac5a488eSSridhar Samudrala {
36171ded5e5aSEric Dumazet 	return READ_ONCE(sock->ops)->getname(sock, addr, 0);
3618ac5a488eSSridhar Samudrala }
3619c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockname);
3620ac5a488eSSridhar Samudrala 
36218a3c245cSPedro Tammela /**
3622645f0897SMiaohe Lin  *	kernel_getpeername - get the address which the socket is connected (kernel space)
36238a3c245cSPedro Tammela  *	@sock: socket
36248a3c245cSPedro Tammela  *	@addr: address holder
36258a3c245cSPedro Tammela  *
36268a3c245cSPedro Tammela  * 	Fills the @addr pointer with the address which the socket is connected.
36270fc95decSAlex Maydanik  *	Returns the length of the address in bytes or an error code.
36288a3c245cSPedro Tammela  */
36298a3c245cSPedro Tammela 
kernel_getpeername(struct socket * sock,struct sockaddr * addr)36309b2c45d4SDenys Vlasenko int kernel_getpeername(struct socket *sock, struct sockaddr *addr)
3631ac5a488eSSridhar Samudrala {
36321ded5e5aSEric Dumazet 	return READ_ONCE(sock->ops)->getname(sock, addr, 1);
3633ac5a488eSSridhar Samudrala }
3634c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getpeername);
3635ac5a488eSSridhar Samudrala 
36368a3c245cSPedro Tammela /**
3637645f0897SMiaohe Lin  *	kernel_sock_shutdown - shut down part of a full-duplex connection (kernel space)
36388a3c245cSPedro Tammela  *	@sock: socket
36398a3c245cSPedro Tammela  *	@how: connection part
36408a3c245cSPedro Tammela  *
36418a3c245cSPedro Tammela  *	Returns 0 or an error.
36428a3c245cSPedro Tammela  */
36438a3c245cSPedro Tammela 
kernel_sock_shutdown(struct socket * sock,enum sock_shutdown_cmd how)364491cf45f0STrond Myklebust int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
364591cf45f0STrond Myklebust {
36461ded5e5aSEric Dumazet 	return READ_ONCE(sock->ops)->shutdown(sock, how);
364791cf45f0STrond Myklebust }
364891cf45f0STrond Myklebust EXPORT_SYMBOL(kernel_sock_shutdown);
3649113c3075SR. Parameswaran 
36508a3c245cSPedro Tammela /**
36518a3c245cSPedro Tammela  *	kernel_sock_ip_overhead - returns the IP overhead imposed by a socket
36528a3c245cSPedro Tammela  *	@sk: socket
36538a3c245cSPedro Tammela  *
36548a3c245cSPedro Tammela  *	This routine returns the IP overhead imposed by a socket i.e.
3655113c3075SR. Parameswaran  *	the length of the underlying IP header, depending on whether
3656113c3075SR. Parameswaran  *	this is an IPv4 or IPv6 socket and the length from IP options turned
365757240d00SR. Parameswaran  *	on at the socket. Assumes that the caller has a lock on the socket.
3658113c3075SR. Parameswaran  */
36598a3c245cSPedro Tammela 
kernel_sock_ip_overhead(struct sock * sk)3660113c3075SR. Parameswaran u32 kernel_sock_ip_overhead(struct sock *sk)
3661113c3075SR. Parameswaran {
3662113c3075SR. Parameswaran 	struct inet_sock *inet;
3663113c3075SR. Parameswaran 	struct ip_options_rcu *opt;
3664113c3075SR. Parameswaran 	u32 overhead = 0;
3665113c3075SR. Parameswaran #if IS_ENABLED(CONFIG_IPV6)
3666113c3075SR. Parameswaran 	struct ipv6_pinfo *np;
3667113c3075SR. Parameswaran 	struct ipv6_txoptions *optv6 = NULL;
3668113c3075SR. Parameswaran #endif /* IS_ENABLED(CONFIG_IPV6) */
3669113c3075SR. Parameswaran 
3670113c3075SR. Parameswaran 	if (!sk)
3671113c3075SR. Parameswaran 		return overhead;
3672113c3075SR. Parameswaran 
3673113c3075SR. Parameswaran 	switch (sk->sk_family) {
3674113c3075SR. Parameswaran 	case AF_INET:
3675113c3075SR. Parameswaran 		inet = inet_sk(sk);
3676113c3075SR. Parameswaran 		overhead += sizeof(struct iphdr);
3677113c3075SR. Parameswaran 		opt = rcu_dereference_protected(inet->inet_opt,
3678614d79c0Sstephen hemminger 						sock_owned_by_user(sk));
3679113c3075SR. Parameswaran 		if (opt)
3680113c3075SR. Parameswaran 			overhead += opt->opt.optlen;
3681113c3075SR. Parameswaran 		return overhead;
3682113c3075SR. Parameswaran #if IS_ENABLED(CONFIG_IPV6)
3683113c3075SR. Parameswaran 	case AF_INET6:
3684113c3075SR. Parameswaran 		np = inet6_sk(sk);
3685113c3075SR. Parameswaran 		overhead += sizeof(struct ipv6hdr);
3686113c3075SR. Parameswaran 		if (np)
3687113c3075SR. Parameswaran 			optv6 = rcu_dereference_protected(np->opt,
3688614d79c0Sstephen hemminger 							  sock_owned_by_user(sk));
3689113c3075SR. Parameswaran 		if (optv6)
3690113c3075SR. Parameswaran 			overhead += (optv6->opt_flen + optv6->opt_nflen);
3691113c3075SR. Parameswaran 		return overhead;
3692113c3075SR. Parameswaran #endif /* IS_ENABLED(CONFIG_IPV6) */
3693113c3075SR. Parameswaran 	default: /* Returns 0 overhead if the socket is not ipv4 or ipv6 */
3694113c3075SR. Parameswaran 		return overhead;
3695113c3075SR. Parameswaran 	}
3696113c3075SR. Parameswaran }
3697113c3075SR. Parameswaran EXPORT_SYMBOL(kernel_sock_ip_overhead);
3698