xref: /openbmc/linux/net/socket.c (revision 7b7fd0ac7dc1ffcaf24d9bca0f051b0168e43cd4)
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;
760d5e0bb03SMarc 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;
770d5e0bb03SMarc 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);
1572*563e6892SIgnat Korchagin 	if (err < 0) {
1573*563e6892SIgnat Korchagin 		/* ->create should release the allocated sock->sk object on error
1574*563e6892SIgnat Korchagin 		 * but it may leave the dangling pointer
1575*563e6892SIgnat Korchagin 		 */
1576*563e6892SIgnat Korchagin 		sock->sk = NULL;
15771da177e4SLinus Torvalds 		goto out_module_put;
1578*563e6892SIgnat Korchagin 	}
1579a79af59eSFrank Filz 
15801da177e4SLinus Torvalds 	/*
15811da177e4SLinus Torvalds 	 * Now to bump the refcnt of the [loadable] module that owns this
15821da177e4SLinus Torvalds 	 * socket at sock_release time we decrement its refcnt.
15831da177e4SLinus Torvalds 	 */
158455737fdaSStephen Hemminger 	if (!try_module_get(sock->ops->owner))
158555737fdaSStephen Hemminger 		goto out_module_busy;
158655737fdaSStephen Hemminger 
15871da177e4SLinus Torvalds 	/*
15881da177e4SLinus Torvalds 	 * Now that we're done with the ->create function, the [loadable]
15891da177e4SLinus Torvalds 	 * module can have its refcnt decremented
15901da177e4SLinus Torvalds 	 */
159155737fdaSStephen Hemminger 	module_put(pf->owner);
15927420ed23SVenkat Yekkirala 	err = security_socket_post_create(sock, family, type, protocol, kern);
15937420ed23SVenkat Yekkirala 	if (err)
15943b185525SHerbert Xu 		goto out_sock_release;
159555737fdaSStephen Hemminger 	*res = sock;
15961da177e4SLinus Torvalds 
159755737fdaSStephen Hemminger 	return 0;
159855737fdaSStephen Hemminger 
159955737fdaSStephen Hemminger out_module_busy:
160055737fdaSStephen Hemminger 	err = -EAFNOSUPPORT;
16011da177e4SLinus Torvalds out_module_put:
160255737fdaSStephen Hemminger 	sock->ops = NULL;
160355737fdaSStephen Hemminger 	module_put(pf->owner);
160455737fdaSStephen Hemminger out_sock_release:
16051da177e4SLinus Torvalds 	sock_release(sock);
160655737fdaSStephen Hemminger 	return err;
160755737fdaSStephen Hemminger 
160855737fdaSStephen Hemminger out_release:
160955737fdaSStephen Hemminger 	rcu_read_unlock();
161055737fdaSStephen Hemminger 	goto out_sock_release;
16111da177e4SLinus Torvalds }
1612721db93aSPavel Emelyanov EXPORT_SYMBOL(__sock_create);
16131da177e4SLinus Torvalds 
16148a3c245cSPedro Tammela /**
16158a3c245cSPedro Tammela  *	sock_create - creates a socket
16168a3c245cSPedro Tammela  *	@family: protocol family (AF_INET, ...)
16178a3c245cSPedro Tammela  *	@type: communication type (SOCK_STREAM, ...)
16188a3c245cSPedro Tammela  *	@protocol: protocol (0, ...)
16198a3c245cSPedro Tammela  *	@res: new socket
16208a3c245cSPedro Tammela  *
16218a3c245cSPedro Tammela  *	A wrapper around __sock_create().
16228a3c245cSPedro Tammela  *	Returns 0 or an error. This function internally uses GFP_KERNEL.
16238a3c245cSPedro Tammela  */
16248a3c245cSPedro Tammela 
sock_create(int family,int type,int protocol,struct socket ** res)16251da177e4SLinus Torvalds int sock_create(int family, int type, int protocol, struct socket **res)
16261da177e4SLinus Torvalds {
16271b8d7ae4SEric W. Biederman 	return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
16281da177e4SLinus Torvalds }
1629c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create);
16301da177e4SLinus Torvalds 
16318a3c245cSPedro Tammela /**
16328a3c245cSPedro Tammela  *	sock_create_kern - creates a socket (kernel space)
16338a3c245cSPedro Tammela  *	@net: net namespace
16348a3c245cSPedro Tammela  *	@family: protocol family (AF_INET, ...)
16358a3c245cSPedro Tammela  *	@type: communication type (SOCK_STREAM, ...)
16368a3c245cSPedro Tammela  *	@protocol: protocol (0, ...)
16378a3c245cSPedro Tammela  *	@res: new socket
16388a3c245cSPedro Tammela  *
16398a3c245cSPedro Tammela  *	A wrapper around __sock_create().
16408a3c245cSPedro Tammela  *	Returns 0 or an error. This function internally uses GFP_KERNEL.
16418a3c245cSPedro Tammela  */
16428a3c245cSPedro Tammela 
sock_create_kern(struct net * net,int family,int type,int protocol,struct socket ** res)1643eeb1bd5cSEric W. Biederman int sock_create_kern(struct net *net, int family, int type, int protocol, struct socket **res)
16441da177e4SLinus Torvalds {
1645eeb1bd5cSEric W. Biederman 	return __sock_create(net, family, type, protocol, res, 1);
16461da177e4SLinus Torvalds }
1647c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_create_kern);
16481da177e4SLinus Torvalds 
__sys_socket_create(int family,int type,int protocol)1649da214a47SJens Axboe static struct socket *__sys_socket_create(int family, int type, int protocol)
16501da177e4SLinus Torvalds {
16511da177e4SLinus Torvalds 	struct socket *sock;
1652da214a47SJens Axboe 	int retval;
1653a677a039SUlrich Drepper 
1654e38b36f3SUlrich Drepper 	/* Check the SOCK_* constants for consistency.  */
1655e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
1656e38b36f3SUlrich Drepper 	BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
1657e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);
1658e38b36f3SUlrich Drepper 	BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);
1659e38b36f3SUlrich Drepper 
1660da214a47SJens Axboe 	if ((type & ~SOCK_TYPE_MASK) & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1661da214a47SJens Axboe 		return ERR_PTR(-EINVAL);
1662a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
16631da177e4SLinus Torvalds 
16641da177e4SLinus Torvalds 	retval = sock_create(family, type, protocol, &sock);
16651da177e4SLinus Torvalds 	if (retval < 0)
1666da214a47SJens Axboe 		return ERR_PTR(retval);
1667da214a47SJens Axboe 
1668da214a47SJens Axboe 	return sock;
1669da214a47SJens Axboe }
1670da214a47SJens Axboe 
__sys_socket_file(int family,int type,int protocol)1671da214a47SJens Axboe struct file *__sys_socket_file(int family, int type, int protocol)
1672da214a47SJens Axboe {
1673da214a47SJens Axboe 	struct socket *sock;
1674da214a47SJens Axboe 	int flags;
1675da214a47SJens Axboe 
1676da214a47SJens Axboe 	sock = __sys_socket_create(family, type, protocol);
1677da214a47SJens Axboe 	if (IS_ERR(sock))
1678da214a47SJens Axboe 		return ERR_CAST(sock);
1679da214a47SJens Axboe 
1680da214a47SJens Axboe 	flags = type & ~SOCK_TYPE_MASK;
1681da214a47SJens Axboe 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1682da214a47SJens Axboe 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1683da214a47SJens Axboe 
1684649c15c7SThadeu Lima de Souza Cascardo 	return sock_alloc_file(sock, flags, NULL);
1685da214a47SJens Axboe }
1686da214a47SJens Axboe 
16870dd061a6SGeliang Tang /*	A hook for bpf progs to attach to and update socket protocol.
16880dd061a6SGeliang Tang  *
16890dd061a6SGeliang Tang  *	A static noinline declaration here could cause the compiler to
16900dd061a6SGeliang Tang  *	optimize away the function. A global noinline declaration will
16910dd061a6SGeliang Tang  *	keep the definition, but may optimize away the callsite.
16920dd061a6SGeliang Tang  *	Therefore, __weak is needed to ensure that the call is still
16930dd061a6SGeliang Tang  *	emitted, by telling the compiler that we don't know what the
16940dd061a6SGeliang Tang  *	function might eventually be.
16950dd061a6SGeliang Tang  *
16960dd061a6SGeliang Tang  *	__diag_* below are needed to dismiss the missing prototype warning.
16970dd061a6SGeliang Tang  */
16980dd061a6SGeliang Tang 
16990dd061a6SGeliang Tang __diag_push();
17000dd061a6SGeliang Tang __diag_ignore_all("-Wmissing-prototypes",
17010dd061a6SGeliang Tang 		  "A fmod_ret entry point for BPF programs");
17020dd061a6SGeliang Tang 
update_socket_protocol(int family,int type,int protocol)17030dd061a6SGeliang Tang __weak noinline int update_socket_protocol(int family, int type, int protocol)
17040dd061a6SGeliang Tang {
17050dd061a6SGeliang Tang 	return protocol;
17060dd061a6SGeliang Tang }
17070dd061a6SGeliang Tang 
17080dd061a6SGeliang Tang __diag_pop();
17090dd061a6SGeliang Tang 
__sys_socket(int family,int type,int protocol)1710da214a47SJens Axboe int __sys_socket(int family, int type, int protocol)
1711da214a47SJens Axboe {
1712da214a47SJens Axboe 	struct socket *sock;
1713da214a47SJens Axboe 	int flags;
1714da214a47SJens Axboe 
17150dd061a6SGeliang Tang 	sock = __sys_socket_create(family, type,
17160dd061a6SGeliang Tang 				   update_socket_protocol(family, type, protocol));
1717da214a47SJens Axboe 	if (IS_ERR(sock))
1718da214a47SJens Axboe 		return PTR_ERR(sock);
1719da214a47SJens Axboe 
1720da214a47SJens Axboe 	flags = type & ~SOCK_TYPE_MASK;
1721da214a47SJens Axboe 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1722da214a47SJens Axboe 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
17231da177e4SLinus Torvalds 
17248e1611e2SAl Viro 	return sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
17251da177e4SLinus Torvalds }
17261da177e4SLinus Torvalds 
SYSCALL_DEFINE3(socket,int,family,int,type,int,protocol)17279d6a15c3SDominik Brodowski SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
17289d6a15c3SDominik Brodowski {
17299d6a15c3SDominik Brodowski 	return __sys_socket(family, type, protocol);
17309d6a15c3SDominik Brodowski }
17319d6a15c3SDominik Brodowski 
17321da177e4SLinus Torvalds /*
17331da177e4SLinus Torvalds  *	Create a pair of connected sockets.
17341da177e4SLinus Torvalds  */
17351da177e4SLinus Torvalds 
__sys_socketpair(int family,int type,int protocol,int __user * usockvec)17366debc8d8SDominik Brodowski int __sys_socketpair(int family, int type, int protocol, int __user *usockvec)
17371da177e4SLinus Torvalds {
17381da177e4SLinus Torvalds 	struct socket *sock1, *sock2;
17391da177e4SLinus Torvalds 	int fd1, fd2, err;
1740db349509SAl Viro 	struct file *newfile1, *newfile2;
1741a677a039SUlrich Drepper 	int flags;
1742a677a039SUlrich Drepper 
1743a677a039SUlrich Drepper 	flags = type & ~SOCK_TYPE_MASK;
174477d27200SUlrich Drepper 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1745a677a039SUlrich Drepper 		return -EINVAL;
1746a677a039SUlrich Drepper 	type &= SOCK_TYPE_MASK;
17471da177e4SLinus Torvalds 
1748aaca0bdcSUlrich Drepper 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1749aaca0bdcSUlrich Drepper 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1750aaca0bdcSUlrich Drepper 
17511da177e4SLinus Torvalds 	/*
1752016a266bSAl Viro 	 * reserve descriptors and make sure we won't fail
1753016a266bSAl Viro 	 * to return them to userland.
1754016a266bSAl Viro 	 */
1755016a266bSAl Viro 	fd1 = get_unused_fd_flags(flags);
1756016a266bSAl Viro 	if (unlikely(fd1 < 0))
1757016a266bSAl Viro 		return fd1;
1758016a266bSAl Viro 
1759016a266bSAl Viro 	fd2 = get_unused_fd_flags(flags);
1760016a266bSAl Viro 	if (unlikely(fd2 < 0)) {
1761016a266bSAl Viro 		put_unused_fd(fd1);
1762016a266bSAl Viro 		return fd2;
1763016a266bSAl Viro 	}
1764016a266bSAl Viro 
1765016a266bSAl Viro 	err = put_user(fd1, &usockvec[0]);
1766016a266bSAl Viro 	if (err)
1767016a266bSAl Viro 		goto out;
1768016a266bSAl Viro 
1769016a266bSAl Viro 	err = put_user(fd2, &usockvec[1]);
1770016a266bSAl Viro 	if (err)
1771016a266bSAl Viro 		goto out;
1772016a266bSAl Viro 
1773016a266bSAl Viro 	/*
17741da177e4SLinus Torvalds 	 * Obtain the first socket and check if the underlying protocol
17751da177e4SLinus Torvalds 	 * supports the socketpair call.
17761da177e4SLinus Torvalds 	 */
17771da177e4SLinus Torvalds 
17781da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock1);
1779016a266bSAl Viro 	if (unlikely(err < 0))
17801da177e4SLinus Torvalds 		goto out;
17811da177e4SLinus Torvalds 
17821da177e4SLinus Torvalds 	err = sock_create(family, type, protocol, &sock2);
1783016a266bSAl Viro 	if (unlikely(err < 0)) {
1784016a266bSAl Viro 		sock_release(sock1);
1785016a266bSAl Viro 		goto out;
1786bf3c23d1SDavid S. Miller 	}
1787d73aa286SYann Droneaud 
1788d47cd945SDavid Herrmann 	err = security_socket_socketpair(sock1, sock2);
1789d47cd945SDavid Herrmann 	if (unlikely(err)) {
1790d47cd945SDavid Herrmann 		sock_release(sock2);
1791d47cd945SDavid Herrmann 		sock_release(sock1);
1792d47cd945SDavid Herrmann 		goto out;
1793d47cd945SDavid Herrmann 	}
1794d47cd945SDavid Herrmann 
17951ded5e5aSEric Dumazet 	err = READ_ONCE(sock1->ops)->socketpair(sock1, sock2);
1796016a266bSAl Viro 	if (unlikely(err < 0)) {
1797016a266bSAl Viro 		sock_release(sock2);
1798016a266bSAl Viro 		sock_release(sock1);
1799016a266bSAl Viro 		goto out;
180028407630SAl Viro 	}
180128407630SAl Viro 
1802aab174f0SLinus Torvalds 	newfile1 = sock_alloc_file(sock1, flags, NULL);
1803b5ffe634SViresh Kumar 	if (IS_ERR(newfile1)) {
180428407630SAl Viro 		err = PTR_ERR(newfile1);
1805016a266bSAl Viro 		sock_release(sock2);
1806016a266bSAl Viro 		goto out;
180728407630SAl Viro 	}
180828407630SAl Viro 
1809aab174f0SLinus Torvalds 	newfile2 = sock_alloc_file(sock2, flags, NULL);
181028407630SAl Viro 	if (IS_ERR(newfile2)) {
181128407630SAl Viro 		err = PTR_ERR(newfile2);
1812016a266bSAl Viro 		fput(newfile1);
1813016a266bSAl Viro 		goto out;
1814db349509SAl Viro 	}
1815db349509SAl Viro 
1816157cf649SAl Viro 	audit_fd_pair(fd1, fd2);
1817d73aa286SYann Droneaud 
1818db349509SAl Viro 	fd_install(fd1, newfile1);
1819db349509SAl Viro 	fd_install(fd2, newfile2);
18201da177e4SLinus Torvalds 	return 0;
18211da177e4SLinus Torvalds 
18221da177e4SLinus Torvalds out:
1823016a266bSAl Viro 	put_unused_fd(fd2);
1824016a266bSAl Viro 	put_unused_fd(fd1);
18251da177e4SLinus Torvalds 	return err;
18261da177e4SLinus Torvalds }
18271da177e4SLinus Torvalds 
SYSCALL_DEFINE4(socketpair,int,family,int,type,int,protocol,int __user *,usockvec)18286debc8d8SDominik Brodowski SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
18296debc8d8SDominik Brodowski 		int __user *, usockvec)
18306debc8d8SDominik Brodowski {
18316debc8d8SDominik Brodowski 	return __sys_socketpair(family, type, protocol, usockvec);
18326debc8d8SDominik Brodowski }
18336debc8d8SDominik Brodowski 
18341da177e4SLinus Torvalds /*
18351da177e4SLinus Torvalds  *	Bind a name to a socket. Nothing much to do here since it's
18361da177e4SLinus Torvalds  *	the protocol's responsibility to handle the local address.
18371da177e4SLinus Torvalds  *
18381da177e4SLinus Torvalds  *	We move the socket address to kernel space before we call
18391da177e4SLinus Torvalds  *	the protocol layer (having also checked the address is ok).
18401da177e4SLinus Torvalds  */
18411da177e4SLinus Torvalds 
__sys_bind(int fd,struct sockaddr __user * umyaddr,int addrlen)1842a87d35d8SDominik Brodowski int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)
18431da177e4SLinus Torvalds {
18441da177e4SLinus Torvalds 	struct socket *sock;
1845230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
18466cb153caSBenjamin LaHaise 	int err, fput_needed;
18471da177e4SLinus Torvalds 
184889bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
184989bddce5SStephen Hemminger 	if (sock) {
185043db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(umyaddr, addrlen, &address);
1851068b88ccSJakub Sitnicki 		if (!err) {
185289bddce5SStephen Hemminger 			err = security_socket_bind(sock,
1853230b1839SYOSHIFUJI Hideaki 						   (struct sockaddr *)&address,
185489bddce5SStephen Hemminger 						   addrlen);
18556cb153caSBenjamin LaHaise 			if (!err)
18561ded5e5aSEric Dumazet 				err = READ_ONCE(sock->ops)->bind(sock,
185789bddce5SStephen Hemminger 						      (struct sockaddr *)
1858230b1839SYOSHIFUJI Hideaki 						      &address, addrlen);
18591da177e4SLinus Torvalds 		}
18606cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
18611da177e4SLinus Torvalds 	}
18621da177e4SLinus Torvalds 	return err;
18631da177e4SLinus Torvalds }
18641da177e4SLinus Torvalds 
SYSCALL_DEFINE3(bind,int,fd,struct sockaddr __user *,umyaddr,int,addrlen)1865a87d35d8SDominik Brodowski SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
1866a87d35d8SDominik Brodowski {
1867a87d35d8SDominik Brodowski 	return __sys_bind(fd, umyaddr, addrlen);
1868a87d35d8SDominik Brodowski }
1869a87d35d8SDominik Brodowski 
18701da177e4SLinus Torvalds /*
18711da177e4SLinus Torvalds  *	Perform a listen. Basically, we allow the protocol to do anything
18721da177e4SLinus Torvalds  *	necessary for a listen, and if that works, we mark the socket as
18731da177e4SLinus Torvalds  *	ready for listening.
18741da177e4SLinus Torvalds  */
18751da177e4SLinus Torvalds 
__sys_listen(int fd,int backlog)187625e290eeSDominik Brodowski int __sys_listen(int fd, int backlog)
18771da177e4SLinus Torvalds {
18781da177e4SLinus Torvalds 	struct socket *sock;
18796cb153caSBenjamin LaHaise 	int err, fput_needed;
1880b8e1f9b5SPavel Emelyanov 	int somaxconn;
18811da177e4SLinus Torvalds 
188289bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
188389bddce5SStephen Hemminger 	if (sock) {
18843c9ba81dSKuniyuki Iwashima 		somaxconn = READ_ONCE(sock_net(sock->sk)->core.sysctl_somaxconn);
188595c96174SEric Dumazet 		if ((unsigned int)backlog > somaxconn)
1886b8e1f9b5SPavel Emelyanov 			backlog = somaxconn;
18871da177e4SLinus Torvalds 
18881da177e4SLinus Torvalds 		err = security_socket_listen(sock, backlog);
18896cb153caSBenjamin LaHaise 		if (!err)
18901ded5e5aSEric Dumazet 			err = READ_ONCE(sock->ops)->listen(sock, backlog);
18916cb153caSBenjamin LaHaise 
18926cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
18931da177e4SLinus Torvalds 	}
18941da177e4SLinus Torvalds 	return err;
18951da177e4SLinus Torvalds }
18961da177e4SLinus Torvalds 
SYSCALL_DEFINE2(listen,int,fd,int,backlog)189725e290eeSDominik Brodowski SYSCALL_DEFINE2(listen, int, fd, int, backlog)
189825e290eeSDominik Brodowski {
189925e290eeSDominik Brodowski 	return __sys_listen(fd, backlog);
190025e290eeSDominik Brodowski }
190125e290eeSDominik Brodowski 
do_accept(struct file * file,unsigned file_flags,struct sockaddr __user * upeer_sockaddr,int __user * upeer_addrlen,int flags)1902d32f89daSPavel Begunkov struct file *do_accept(struct file *file, unsigned file_flags,
1903de2ea4b6SJens Axboe 		       struct sockaddr __user *upeer_sockaddr,
1904d32f89daSPavel Begunkov 		       int __user *upeer_addrlen, int flags)
19051da177e4SLinus Torvalds {
19061da177e4SLinus Torvalds 	struct socket *sock, *newsock;
190739d8c1b6SDavid S. Miller 	struct file *newfile;
1908d32f89daSPavel Begunkov 	int err, len;
1909230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
19101ded5e5aSEric Dumazet 	const struct proto_ops *ops;
19111da177e4SLinus Torvalds 
1912dba4a925SFlorent Revest 	sock = sock_from_file(file);
1913d32f89daSPavel Begunkov 	if (!sock)
1914d32f89daSPavel Begunkov 		return ERR_PTR(-ENOTSOCK);
19151da177e4SLinus Torvalds 
1916c6d409cfSEric Dumazet 	newsock = sock_alloc();
1917c6d409cfSEric Dumazet 	if (!newsock)
1918d32f89daSPavel Begunkov 		return ERR_PTR(-ENFILE);
19191ded5e5aSEric Dumazet 	ops = READ_ONCE(sock->ops);
19201da177e4SLinus Torvalds 
19211da177e4SLinus Torvalds 	newsock->type = sock->type;
19221ded5e5aSEric Dumazet 	newsock->ops = ops;
19231da177e4SLinus Torvalds 
19241da177e4SLinus Torvalds 	/*
19251da177e4SLinus Torvalds 	 * We don't need try_module_get here, as the listening socket (sock)
19261da177e4SLinus Torvalds 	 * has the protocol module (sock->ops->owner) held.
19271da177e4SLinus Torvalds 	 */
19281ded5e5aSEric Dumazet 	__module_get(ops->owner);
19291da177e4SLinus Torvalds 
1930aab174f0SLinus Torvalds 	newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name);
1931d32f89daSPavel Begunkov 	if (IS_ERR(newfile))
1932d32f89daSPavel Begunkov 		return newfile;
193339d8c1b6SDavid S. Miller 
1934a79af59eSFrank Filz 	err = security_socket_accept(sock, newsock);
1935a79af59eSFrank Filz 	if (err)
193639d8c1b6SDavid S. Miller 		goto out_fd;
1937a79af59eSFrank Filz 
19381ded5e5aSEric Dumazet 	err = ops->accept(sock, newsock, sock->file->f_flags | file_flags,
1939de2ea4b6SJens Axboe 					false);
19401da177e4SLinus Torvalds 	if (err < 0)
194139d8c1b6SDavid S. Miller 		goto out_fd;
19421da177e4SLinus Torvalds 
19431da177e4SLinus Torvalds 	if (upeer_sockaddr) {
19441ded5e5aSEric Dumazet 		len = ops->getname(newsock, (struct sockaddr *)&address, 2);
19459b2c45d4SDenys Vlasenko 		if (len < 0) {
19461da177e4SLinus Torvalds 			err = -ECONNABORTED;
194739d8c1b6SDavid S. Miller 			goto out_fd;
19481da177e4SLinus Torvalds 		}
194943db362dSMaciej Żenczykowski 		err = move_addr_to_user(&address,
1950230b1839SYOSHIFUJI Hideaki 					len, upeer_sockaddr, upeer_addrlen);
19511da177e4SLinus Torvalds 		if (err < 0)
195239d8c1b6SDavid S. Miller 			goto out_fd;
19531da177e4SLinus Torvalds 	}
19541da177e4SLinus Torvalds 
19551da177e4SLinus Torvalds 	/* File flags are not inherited via accept() unlike another OSes. */
1956d32f89daSPavel Begunkov 	return newfile;
195739d8c1b6SDavid S. Miller out_fd:
19589606a216SDavid S. Miller 	fput(newfile);
1959d32f89daSPavel Begunkov 	return ERR_PTR(err);
1960d32f89daSPavel Begunkov }
1961de2ea4b6SJens Axboe 
__sys_accept4_file(struct file * file,struct sockaddr __user * upeer_sockaddr,int __user * upeer_addrlen,int flags)1962c0424532SYajun Deng static int __sys_accept4_file(struct file *file, struct sockaddr __user *upeer_sockaddr,
1963c0424532SYajun Deng 			      int __user *upeer_addrlen, int flags)
1964d32f89daSPavel Begunkov {
1965d32f89daSPavel Begunkov 	struct file *newfile;
1966d32f89daSPavel Begunkov 	int newfd;
1967d32f89daSPavel Begunkov 
1968d32f89daSPavel Begunkov 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1969d32f89daSPavel Begunkov 		return -EINVAL;
1970d32f89daSPavel Begunkov 
1971d32f89daSPavel Begunkov 	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
1972d32f89daSPavel Begunkov 		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
1973d32f89daSPavel Begunkov 
1974c0424532SYajun Deng 	newfd = get_unused_fd_flags(flags);
1975d32f89daSPavel Begunkov 	if (unlikely(newfd < 0))
1976d32f89daSPavel Begunkov 		return newfd;
1977d32f89daSPavel Begunkov 
1978c0424532SYajun Deng 	newfile = do_accept(file, 0, upeer_sockaddr, upeer_addrlen,
1979d32f89daSPavel Begunkov 			    flags);
1980d32f89daSPavel Begunkov 	if (IS_ERR(newfile)) {
1981d32f89daSPavel Begunkov 		put_unused_fd(newfd);
1982d32f89daSPavel Begunkov 		return PTR_ERR(newfile);
1983d32f89daSPavel Begunkov 	}
1984d32f89daSPavel Begunkov 	fd_install(newfd, newfile);
1985d32f89daSPavel Begunkov 	return newfd;
1986de2ea4b6SJens Axboe }
1987de2ea4b6SJens Axboe 
1988de2ea4b6SJens Axboe /*
1989de2ea4b6SJens Axboe  *	For accept, we attempt to create a new socket, set up the link
1990de2ea4b6SJens Axboe  *	with the client, wake up the client, then return the new
1991de2ea4b6SJens Axboe  *	connected fd. We collect the address of the connector in kernel
1992de2ea4b6SJens Axboe  *	space and move it to user at the very end. This is unclean because
1993de2ea4b6SJens Axboe  *	we open the socket then return an error.
1994de2ea4b6SJens Axboe  *
1995de2ea4b6SJens Axboe  *	1003.1g adds the ability to recvmsg() to query connection pending
1996de2ea4b6SJens Axboe  *	status to recvmsg. We need to add that support in a way thats
1997de2ea4b6SJens Axboe  *	clean when we restructure accept also.
1998de2ea4b6SJens Axboe  */
1999de2ea4b6SJens Axboe 
__sys_accept4(int fd,struct sockaddr __user * upeer_sockaddr,int __user * upeer_addrlen,int flags)2000de2ea4b6SJens Axboe int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
2001de2ea4b6SJens Axboe 		  int __user *upeer_addrlen, int flags)
2002de2ea4b6SJens Axboe {
2003de2ea4b6SJens Axboe 	int ret = -EBADF;
2004de2ea4b6SJens Axboe 	struct fd f;
2005de2ea4b6SJens Axboe 
2006de2ea4b6SJens Axboe 	f = fdget(fd);
2007de2ea4b6SJens Axboe 	if (f.file) {
2008c0424532SYajun Deng 		ret = __sys_accept4_file(f.file, upeer_sockaddr,
2009c0424532SYajun Deng 					 upeer_addrlen, flags);
20106b07edebSMiaohe Lin 		fdput(f);
2011de2ea4b6SJens Axboe 	}
2012de2ea4b6SJens Axboe 
2013de2ea4b6SJens Axboe 	return ret;
20141da177e4SLinus Torvalds }
20151da177e4SLinus Torvalds 
SYSCALL_DEFINE4(accept4,int,fd,struct sockaddr __user *,upeer_sockaddr,int __user *,upeer_addrlen,int,flags)20164541e805SDominik Brodowski SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
20174541e805SDominik Brodowski 		int __user *, upeer_addrlen, int, flags)
20184541e805SDominik Brodowski {
20194541e805SDominik Brodowski 	return __sys_accept4(fd, upeer_sockaddr, upeer_addrlen, flags);
20204541e805SDominik Brodowski }
20214541e805SDominik Brodowski 
SYSCALL_DEFINE3(accept,int,fd,struct sockaddr __user *,upeer_sockaddr,int __user *,upeer_addrlen)202220f37034SHeiko Carstens SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,
202320f37034SHeiko Carstens 		int __user *, upeer_addrlen)
2024aaca0bdcSUlrich Drepper {
20254541e805SDominik Brodowski 	return __sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0);
2026aaca0bdcSUlrich Drepper }
2027aaca0bdcSUlrich Drepper 
20281da177e4SLinus Torvalds /*
20291da177e4SLinus Torvalds  *	Attempt to connect to a socket with the server address.  The address
20301da177e4SLinus Torvalds  *	is in user space so we verify it is OK and move it to kernel space.
20311da177e4SLinus Torvalds  *
20321da177e4SLinus Torvalds  *	For 1003.1g we need to add clean support for a bind to AF_UNSPEC to
20331da177e4SLinus Torvalds  *	break bindings
20341da177e4SLinus Torvalds  *
20351da177e4SLinus Torvalds  *	NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and
20361da177e4SLinus Torvalds  *	other SEQPACKET protocols that take time to connect() as it doesn't
20371da177e4SLinus Torvalds  *	include the -EINPROGRESS status for such sockets.
20381da177e4SLinus Torvalds  */
20391da177e4SLinus Torvalds 
__sys_connect_file(struct file * file,struct sockaddr_storage * address,int addrlen,int file_flags)2040f499a021SJens Axboe int __sys_connect_file(struct file *file, struct sockaddr_storage *address,
2041bd3ded31SJens Axboe 		       int addrlen, int file_flags)
20421da177e4SLinus Torvalds {
20431da177e4SLinus Torvalds 	struct socket *sock;
2044bd3ded31SJens Axboe 	int err;
20451da177e4SLinus Torvalds 
2046dba4a925SFlorent Revest 	sock = sock_from_file(file);
2047dba4a925SFlorent Revest 	if (!sock) {
2048dba4a925SFlorent Revest 		err = -ENOTSOCK;
20491da177e4SLinus Torvalds 		goto out;
2050dba4a925SFlorent Revest 	}
20511da177e4SLinus Torvalds 
205289bddce5SStephen Hemminger 	err =
2053f499a021SJens Axboe 	    security_socket_connect(sock, (struct sockaddr *)address, addrlen);
20541da177e4SLinus Torvalds 	if (err)
2055bd3ded31SJens Axboe 		goto out;
20561da177e4SLinus Torvalds 
20571ded5e5aSEric Dumazet 	err = READ_ONCE(sock->ops)->connect(sock, (struct sockaddr *)address,
20581ded5e5aSEric Dumazet 				addrlen, sock->file->f_flags | file_flags);
20591da177e4SLinus Torvalds out:
20601da177e4SLinus Torvalds 	return err;
20611da177e4SLinus Torvalds }
20621da177e4SLinus Torvalds 
__sys_connect(int fd,struct sockaddr __user * uservaddr,int addrlen)2063bd3ded31SJens Axboe int __sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen)
2064bd3ded31SJens Axboe {
2065bd3ded31SJens Axboe 	int ret = -EBADF;
2066bd3ded31SJens Axboe 	struct fd f;
2067bd3ded31SJens Axboe 
2068bd3ded31SJens Axboe 	f = fdget(fd);
2069bd3ded31SJens Axboe 	if (f.file) {
2070f499a021SJens Axboe 		struct sockaddr_storage address;
2071f499a021SJens Axboe 
2072f499a021SJens Axboe 		ret = move_addr_to_kernel(uservaddr, addrlen, &address);
2073f499a021SJens Axboe 		if (!ret)
2074f499a021SJens Axboe 			ret = __sys_connect_file(f.file, &address, addrlen, 0);
20756b07edebSMiaohe Lin 		fdput(f);
2076bd3ded31SJens Axboe 	}
2077bd3ded31SJens Axboe 
2078bd3ded31SJens Axboe 	return ret;
2079bd3ded31SJens Axboe }
2080bd3ded31SJens Axboe 
SYSCALL_DEFINE3(connect,int,fd,struct sockaddr __user *,uservaddr,int,addrlen)20811387c2c2SDominik Brodowski SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
20821387c2c2SDominik Brodowski 		int, addrlen)
20831387c2c2SDominik Brodowski {
20841387c2c2SDominik Brodowski 	return __sys_connect(fd, uservaddr, addrlen);
20851387c2c2SDominik Brodowski }
20861387c2c2SDominik Brodowski 
20871da177e4SLinus Torvalds /*
20881da177e4SLinus Torvalds  *	Get the local address ('name') of a socket object. Move the obtained
20891da177e4SLinus Torvalds  *	name to user space.
20901da177e4SLinus Torvalds  */
20911da177e4SLinus Torvalds 
__sys_getsockname(int fd,struct sockaddr __user * usockaddr,int __user * usockaddr_len)20928882a107SDominik Brodowski int __sys_getsockname(int fd, struct sockaddr __user *usockaddr,
20938882a107SDominik Brodowski 		      int __user *usockaddr_len)
20941da177e4SLinus Torvalds {
20951da177e4SLinus Torvalds 	struct socket *sock;
2096230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
20979b2c45d4SDenys Vlasenko 	int err, fput_needed;
20981da177e4SLinus Torvalds 
20996cb153caSBenjamin LaHaise 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
21001da177e4SLinus Torvalds 	if (!sock)
21011da177e4SLinus Torvalds 		goto out;
21021da177e4SLinus Torvalds 
21031da177e4SLinus Torvalds 	err = security_socket_getsockname(sock);
21041da177e4SLinus Torvalds 	if (err)
21051da177e4SLinus Torvalds 		goto out_put;
21061da177e4SLinus Torvalds 
21071ded5e5aSEric Dumazet 	err = READ_ONCE(sock->ops)->getname(sock, (struct sockaddr *)&address, 0);
21089b2c45d4SDenys Vlasenko 	if (err < 0)
21091da177e4SLinus Torvalds 		goto out_put;
21109b2c45d4SDenys Vlasenko 	/* "err" is actually length in this case */
21119b2c45d4SDenys Vlasenko 	err = move_addr_to_user(&address, err, usockaddr, usockaddr_len);
21121da177e4SLinus Torvalds 
21131da177e4SLinus Torvalds out_put:
21146cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
21151da177e4SLinus Torvalds out:
21161da177e4SLinus Torvalds 	return err;
21171da177e4SLinus Torvalds }
21181da177e4SLinus Torvalds 
SYSCALL_DEFINE3(getsockname,int,fd,struct sockaddr __user *,usockaddr,int __user *,usockaddr_len)21198882a107SDominik Brodowski SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
21208882a107SDominik Brodowski 		int __user *, usockaddr_len)
21218882a107SDominik Brodowski {
21228882a107SDominik Brodowski 	return __sys_getsockname(fd, usockaddr, usockaddr_len);
21238882a107SDominik Brodowski }
21248882a107SDominik Brodowski 
21251da177e4SLinus Torvalds /*
21261da177e4SLinus Torvalds  *	Get the remote address ('name') of a socket object. Move the obtained
21271da177e4SLinus Torvalds  *	name to user space.
21281da177e4SLinus Torvalds  */
21291da177e4SLinus Torvalds 
__sys_getpeername(int fd,struct sockaddr __user * usockaddr,int __user * usockaddr_len)2130b21c8f83SDominik Brodowski int __sys_getpeername(int fd, struct sockaddr __user *usockaddr,
2131b21c8f83SDominik Brodowski 		      int __user *usockaddr_len)
21321da177e4SLinus Torvalds {
21331da177e4SLinus Torvalds 	struct socket *sock;
2134230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
21359b2c45d4SDenys Vlasenko 	int err, fput_needed;
21361da177e4SLinus Torvalds 
213789bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
213889bddce5SStephen Hemminger 	if (sock != NULL) {
21391ded5e5aSEric Dumazet 		const struct proto_ops *ops = READ_ONCE(sock->ops);
21401ded5e5aSEric Dumazet 
21411da177e4SLinus Torvalds 		err = security_socket_getpeername(sock);
21421da177e4SLinus Torvalds 		if (err) {
21436cb153caSBenjamin LaHaise 			fput_light(sock->file, fput_needed);
21441da177e4SLinus Torvalds 			return err;
21451da177e4SLinus Torvalds 		}
21461da177e4SLinus Torvalds 
21471ded5e5aSEric Dumazet 		err = ops->getname(sock, (struct sockaddr *)&address, 1);
21489b2c45d4SDenys Vlasenko 		if (err >= 0)
21499b2c45d4SDenys Vlasenko 			/* "err" is actually length in this case */
21509b2c45d4SDenys Vlasenko 			err = move_addr_to_user(&address, err, usockaddr,
215189bddce5SStephen Hemminger 						usockaddr_len);
21526cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
21531da177e4SLinus Torvalds 	}
21541da177e4SLinus Torvalds 	return err;
21551da177e4SLinus Torvalds }
21561da177e4SLinus Torvalds 
SYSCALL_DEFINE3(getpeername,int,fd,struct sockaddr __user *,usockaddr,int __user *,usockaddr_len)2157b21c8f83SDominik Brodowski SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
2158b21c8f83SDominik Brodowski 		int __user *, usockaddr_len)
2159b21c8f83SDominik Brodowski {
2160b21c8f83SDominik Brodowski 	return __sys_getpeername(fd, usockaddr, usockaddr_len);
2161b21c8f83SDominik Brodowski }
2162b21c8f83SDominik Brodowski 
21631da177e4SLinus Torvalds /*
21641da177e4SLinus Torvalds  *	Send a datagram to a given address. We move the address into kernel
21651da177e4SLinus Torvalds  *	space and check the user space data area is readable before invoking
21661da177e4SLinus Torvalds  *	the protocol.
21671da177e4SLinus Torvalds  */
__sys_sendto(int fd,void __user * buff,size_t len,unsigned int flags,struct sockaddr __user * addr,int addr_len)2168211b634bSDominik Brodowski int __sys_sendto(int fd, void __user *buff, size_t len, unsigned int flags,
2169211b634bSDominik Brodowski 		 struct sockaddr __user *addr,  int addr_len)
21701da177e4SLinus Torvalds {
21711da177e4SLinus Torvalds 	struct socket *sock;
2172230b1839SYOSHIFUJI Hideaki 	struct sockaddr_storage address;
21731da177e4SLinus Torvalds 	int err;
21741da177e4SLinus Torvalds 	struct msghdr msg;
21751da177e4SLinus Torvalds 	struct iovec iov;
21766cb153caSBenjamin LaHaise 	int fput_needed;
21771da177e4SLinus Torvalds 
2178de4eda9dSAl Viro 	err = import_single_range(ITER_SOURCE, buff, len, &iov, &msg.msg_iter);
2179602bd0e9SAl Viro 	if (unlikely(err))
2180602bd0e9SAl Viro 		return err;
2181de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2182de0fa95cSPavel Emelyanov 	if (!sock)
21834387ff75SDavid S. Miller 		goto out;
21846cb153caSBenjamin LaHaise 
21851da177e4SLinus Torvalds 	msg.msg_name = NULL;
21861da177e4SLinus Torvalds 	msg.msg_control = NULL;
21871da177e4SLinus Torvalds 	msg.msg_controllen = 0;
21881da177e4SLinus Torvalds 	msg.msg_namelen = 0;
21897c701d92SPavel Begunkov 	msg.msg_ubuf = NULL;
21906cb153caSBenjamin LaHaise 	if (addr) {
219143db362dSMaciej Żenczykowski 		err = move_addr_to_kernel(addr, addr_len, &address);
21921da177e4SLinus Torvalds 		if (err < 0)
21931da177e4SLinus Torvalds 			goto out_put;
2194230b1839SYOSHIFUJI Hideaki 		msg.msg_name = (struct sockaddr *)&address;
21951da177e4SLinus Torvalds 		msg.msg_namelen = addr_len;
21961da177e4SLinus Torvalds 	}
2197b841b901SDavid Howells 	flags &= ~MSG_INTERNAL_SENDMSG_FLAGS;
21981da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
21991da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
22001da177e4SLinus Torvalds 	msg.msg_flags = flags;
220186a7e0b6SJordan Rife 	err = __sock_sendmsg(sock, &msg);
22021da177e4SLinus Torvalds 
22031da177e4SLinus Torvalds out_put:
2204de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
22054387ff75SDavid S. Miller out:
22061da177e4SLinus Torvalds 	return err;
22071da177e4SLinus Torvalds }
22081da177e4SLinus Torvalds 
SYSCALL_DEFINE6(sendto,int,fd,void __user *,buff,size_t,len,unsigned int,flags,struct sockaddr __user *,addr,int,addr_len)2209211b634bSDominik Brodowski SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
2210211b634bSDominik Brodowski 		unsigned int, flags, struct sockaddr __user *, addr,
2211211b634bSDominik Brodowski 		int, addr_len)
2212211b634bSDominik Brodowski {
2213211b634bSDominik Brodowski 	return __sys_sendto(fd, buff, len, flags, addr, addr_len);
2214211b634bSDominik Brodowski }
2215211b634bSDominik Brodowski 
22161da177e4SLinus Torvalds /*
22171da177e4SLinus Torvalds  *	Send a datagram down a socket.
22181da177e4SLinus Torvalds  */
22191da177e4SLinus Torvalds 
SYSCALL_DEFINE4(send,int,fd,void __user *,buff,size_t,len,unsigned int,flags)22203e0fa65fSHeiko Carstens SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len,
222195c96174SEric Dumazet 		unsigned int, flags)
22221da177e4SLinus Torvalds {
2223211b634bSDominik Brodowski 	return __sys_sendto(fd, buff, len, flags, NULL, 0);
22241da177e4SLinus Torvalds }
22251da177e4SLinus Torvalds 
22261da177e4SLinus Torvalds /*
22271da177e4SLinus Torvalds  *	Receive a frame from the socket and optionally record the address of the
22281da177e4SLinus Torvalds  *	sender. We verify the buffers are writable and if needed move the
22291da177e4SLinus Torvalds  *	sender address from kernel to user space.
22301da177e4SLinus Torvalds  */
__sys_recvfrom(int fd,void __user * ubuf,size_t size,unsigned int flags,struct sockaddr __user * addr,int __user * addr_len)22317a09e1ebSDominik Brodowski int __sys_recvfrom(int fd, void __user *ubuf, size_t size, unsigned int flags,
22327a09e1ebSDominik Brodowski 		   struct sockaddr __user *addr, int __user *addr_len)
22331da177e4SLinus Torvalds {
22341228b34cSEric Dumazet 	struct sockaddr_storage address;
22351228b34cSEric Dumazet 	struct msghdr msg = {
22361228b34cSEric Dumazet 		/* Save some cycles and don't copy the address if not needed */
22371228b34cSEric Dumazet 		.msg_name = addr ? (struct sockaddr *)&address : NULL,
22381228b34cSEric Dumazet 	};
22391da177e4SLinus Torvalds 	struct socket *sock;
22401da177e4SLinus Torvalds 	struct iovec iov;
22411da177e4SLinus Torvalds 	int err, err2;
22426cb153caSBenjamin LaHaise 	int fput_needed;
22431da177e4SLinus Torvalds 
2244de4eda9dSAl Viro 	err = import_single_range(ITER_DEST, ubuf, size, &iov, &msg.msg_iter);
2245602bd0e9SAl Viro 	if (unlikely(err))
2246602bd0e9SAl Viro 		return err;
2247de0fa95cSPavel Emelyanov 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
22481da177e4SLinus Torvalds 	if (!sock)
2249de0fa95cSPavel Emelyanov 		goto out;
22501da177e4SLinus Torvalds 
22511da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
22521da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
22532da62906SAl Viro 	err = sock_recvmsg(sock, &msg, flags);
22541da177e4SLinus Torvalds 
225589bddce5SStephen Hemminger 	if (err >= 0 && addr != NULL) {
225643db362dSMaciej Żenczykowski 		err2 = move_addr_to_user(&address,
2257230b1839SYOSHIFUJI Hideaki 					 msg.msg_namelen, addr, addr_len);
22581da177e4SLinus Torvalds 		if (err2 < 0)
22591da177e4SLinus Torvalds 			err = err2;
22601da177e4SLinus Torvalds 	}
2261de0fa95cSPavel Emelyanov 
2262de0fa95cSPavel Emelyanov 	fput_light(sock->file, fput_needed);
22634387ff75SDavid S. Miller out:
22641da177e4SLinus Torvalds 	return err;
22651da177e4SLinus Torvalds }
22661da177e4SLinus Torvalds 
SYSCALL_DEFINE6(recvfrom,int,fd,void __user *,ubuf,size_t,size,unsigned int,flags,struct sockaddr __user *,addr,int __user *,addr_len)22677a09e1ebSDominik Brodowski SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
22687a09e1ebSDominik Brodowski 		unsigned int, flags, struct sockaddr __user *, addr,
22697a09e1ebSDominik Brodowski 		int __user *, addr_len)
22707a09e1ebSDominik Brodowski {
22717a09e1ebSDominik Brodowski 	return __sys_recvfrom(fd, ubuf, size, flags, addr, addr_len);
22727a09e1ebSDominik Brodowski }
22737a09e1ebSDominik Brodowski 
22741da177e4SLinus Torvalds /*
22751da177e4SLinus Torvalds  *	Receive a datagram from a socket.
22761da177e4SLinus Torvalds  */
22771da177e4SLinus Torvalds 
SYSCALL_DEFINE4(recv,int,fd,void __user *,ubuf,size_t,size,unsigned int,flags)2278b7c0ddf5SJan Glauber SYSCALL_DEFINE4(recv, int, fd, void __user *, ubuf, size_t, size,
2279b7c0ddf5SJan Glauber 		unsigned int, flags)
22801da177e4SLinus Torvalds {
22817a09e1ebSDominik Brodowski 	return __sys_recvfrom(fd, ubuf, size, flags, NULL, NULL);
22821da177e4SLinus Torvalds }
22831da177e4SLinus Torvalds 
sock_use_custom_sol_socket(const struct socket * sock)228483f0c10bSFlorian Westphal static bool sock_use_custom_sol_socket(const struct socket *sock)
228583f0c10bSFlorian Westphal {
2286a5ef058dSPaolo Abeni 	return test_bit(SOCK_CUSTOM_SOCKOPT, &sock->flags);
228783f0c10bSFlorian Westphal }
228883f0c10bSFlorian Westphal 
do_sock_setsockopt(struct socket * sock,bool compat,int level,int optname,sockptr_t optval,int optlen)2289e88c16a4SBreno Leitao int do_sock_setsockopt(struct socket *sock, bool compat, int level,
2290e88c16a4SBreno Leitao 		       int optname, sockptr_t optval, int optlen)
22911da177e4SLinus Torvalds {
22921ded5e5aSEric Dumazet 	const struct proto_ops *ops;
22930d01da6aSStanislav Fomichev 	char *kernel_optval = NULL;
2294e88c16a4SBreno Leitao 	int err;
22951da177e4SLinus Torvalds 
22961da177e4SLinus Torvalds 	if (optlen < 0)
22971da177e4SLinus Torvalds 		return -EINVAL;
22981da177e4SLinus Torvalds 
22991da177e4SLinus Torvalds 	err = security_socket_setsockopt(sock, level, optname);
23006cb153caSBenjamin LaHaise 	if (err)
23016cb153caSBenjamin LaHaise 		goto out_put;
23021da177e4SLinus Torvalds 
2303e88c16a4SBreno Leitao 	if (!compat)
23044a367299SChristoph Hellwig 		err = BPF_CGROUP_RUN_PROG_SETSOCKOPT(sock->sk, &level, &optname,
230509fba016SBreno Leitao 						     optval, &optlen,
230655db9c0eSChristoph Hellwig 						     &kernel_optval);
23074a367299SChristoph Hellwig 	if (err < 0)
23080d01da6aSStanislav Fomichev 		goto out_put;
23094a367299SChristoph Hellwig 	if (err > 0) {
23100d01da6aSStanislav Fomichev 		err = 0;
23110d01da6aSStanislav Fomichev 		goto out_put;
23120d01da6aSStanislav Fomichev 	}
23130d01da6aSStanislav Fomichev 
2314a7b75c5aSChristoph Hellwig 	if (kernel_optval)
2315a7b75c5aSChristoph Hellwig 		optval = KERNEL_SOCKPTR(kernel_optval);
23161ded5e5aSEric Dumazet 	ops = READ_ONCE(sock->ops);
231783f0c10bSFlorian Westphal 	if (level == SOL_SOCKET && !sock_use_custom_sol_socket(sock))
2318a7b75c5aSChristoph Hellwig 		err = sock_setsockopt(sock, level, optname, optval, optlen);
23191ded5e5aSEric Dumazet 	else if (unlikely(!ops->setsockopt))
2320a44d9e72SChristoph Hellwig 		err = -EOPNOTSUPP;
23211da177e4SLinus Torvalds 	else
23221ded5e5aSEric Dumazet 		err = ops->setsockopt(sock, level, optname, optval,
232389bddce5SStephen Hemminger 					    optlen);
23240d01da6aSStanislav Fomichev 	kfree(kernel_optval);
23256cb153caSBenjamin LaHaise out_put:
2326e88c16a4SBreno Leitao 	return err;
2327e88c16a4SBreno Leitao }
2328e88c16a4SBreno Leitao EXPORT_SYMBOL(do_sock_setsockopt);
2329e88c16a4SBreno Leitao 
2330e88c16a4SBreno Leitao /* Set a socket option. Because we don't know the option lengths we have
2331e88c16a4SBreno Leitao  * to pass the user mode parameter for the protocols to sort out.
2332e88c16a4SBreno Leitao  */
__sys_setsockopt(int fd,int level,int optname,char __user * user_optval,int optlen)2333e88c16a4SBreno Leitao int __sys_setsockopt(int fd, int level, int optname, char __user *user_optval,
2334e88c16a4SBreno Leitao 		     int optlen)
2335e88c16a4SBreno Leitao {
2336e88c16a4SBreno Leitao 	sockptr_t optval = USER_SOCKPTR(user_optval);
2337e88c16a4SBreno Leitao 	bool compat = in_compat_syscall();
2338e88c16a4SBreno Leitao 	int err, fput_needed;
2339e88c16a4SBreno Leitao 	struct socket *sock;
2340e88c16a4SBreno Leitao 
2341e88c16a4SBreno Leitao 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2342e88c16a4SBreno Leitao 	if (!sock)
2343e88c16a4SBreno Leitao 		return err;
2344e88c16a4SBreno Leitao 
2345e88c16a4SBreno Leitao 	err = do_sock_setsockopt(sock, compat, level, optname, optval, optlen);
2346e88c16a4SBreno Leitao 
23476cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
23481da177e4SLinus Torvalds 	return err;
23491da177e4SLinus Torvalds }
23501da177e4SLinus Torvalds 
SYSCALL_DEFINE5(setsockopt,int,fd,int,level,int,optname,char __user *,optval,int,optlen)2351cc36dca0SDominik Brodowski SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
2352cc36dca0SDominik Brodowski 		char __user *, optval, int, optlen)
2353cc36dca0SDominik Brodowski {
2354cc36dca0SDominik Brodowski 	return __sys_setsockopt(fd, level, optname, optval, optlen);
2355cc36dca0SDominik Brodowski }
2356cc36dca0SDominik Brodowski 
23579cacf81fSStanislav Fomichev INDIRECT_CALLABLE_DECLARE(bool tcp_bpf_bypass_getsockopt(int level,
23589cacf81fSStanislav Fomichev 							 int optname));
23599cacf81fSStanislav Fomichev 
do_sock_getsockopt(struct socket * sock,bool compat,int level,int optname,sockptr_t optval,sockptr_t optlen)23602174a3c3SBreno Leitao int do_sock_getsockopt(struct socket *sock, bool compat, int level,
23612174a3c3SBreno Leitao 		       int optname, sockptr_t optval, sockptr_t optlen)
23622174a3c3SBreno Leitao {
2363f8d6acb1STze-nan Wu 	int max_optlen __maybe_unused = 0;
23642174a3c3SBreno Leitao 	const struct proto_ops *ops;
23652174a3c3SBreno Leitao 	int err;
23662174a3c3SBreno Leitao 
23672174a3c3SBreno Leitao 	err = security_socket_getsockopt(sock, level, optname);
23682174a3c3SBreno Leitao 	if (err)
23692174a3c3SBreno Leitao 		return err;
23702174a3c3SBreno Leitao 
23712174a3c3SBreno Leitao 	if (!compat)
2372f8d6acb1STze-nan Wu 		copy_from_sockptr(&max_optlen, optlen, sizeof(int));
23732174a3c3SBreno Leitao 
23742174a3c3SBreno Leitao 	ops = READ_ONCE(sock->ops);
23752174a3c3SBreno Leitao 	if (level == SOL_SOCKET) {
23762174a3c3SBreno Leitao 		err = sk_getsockopt(sock->sk, level, optname, optval, optlen);
23772174a3c3SBreno Leitao 	} else if (unlikely(!ops->getsockopt)) {
23782174a3c3SBreno Leitao 		err = -EOPNOTSUPP;
23792174a3c3SBreno Leitao 	} else {
23802174a3c3SBreno Leitao 		if (WARN_ONCE(optval.is_kernel || optlen.is_kernel,
23812174a3c3SBreno Leitao 			      "Invalid argument type"))
23822174a3c3SBreno Leitao 			return -EOPNOTSUPP;
23832174a3c3SBreno Leitao 
23842174a3c3SBreno Leitao 		err = ops->getsockopt(sock, level, optname, optval.user,
23852174a3c3SBreno Leitao 				      optlen.user);
23862174a3c3SBreno Leitao 	}
23872174a3c3SBreno Leitao 
23882174a3c3SBreno Leitao 	if (!compat)
23892174a3c3SBreno Leitao 		err = BPF_CGROUP_RUN_PROG_GETSOCKOPT(sock->sk, level, optname,
23902174a3c3SBreno Leitao 						     optval, optlen, max_optlen,
23912174a3c3SBreno Leitao 						     err);
23922174a3c3SBreno Leitao 
23932174a3c3SBreno Leitao 	return err;
23942174a3c3SBreno Leitao }
23952174a3c3SBreno Leitao EXPORT_SYMBOL(do_sock_getsockopt);
23962174a3c3SBreno Leitao 
23971da177e4SLinus Torvalds /*
23981da177e4SLinus Torvalds  *	Get a socket option. Because we don't know the option lengths we have
23991da177e4SLinus Torvalds  *	to pass a user mode parameter for the protocols to sort out.
24001da177e4SLinus Torvalds  */
__sys_getsockopt(int fd,int level,int optname,char __user * optval,int __user * optlen)240155db9c0eSChristoph Hellwig int __sys_getsockopt(int fd, int level, int optname, char __user *optval,
240255db9c0eSChristoph Hellwig 		int __user *optlen)
24031da177e4SLinus Torvalds {
24046cb153caSBenjamin LaHaise 	int err, fput_needed;
24051da177e4SLinus Torvalds 	struct socket *sock;
24062174a3c3SBreno Leitao 	bool compat;
24071da177e4SLinus Torvalds 
240889bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2409d8a9b38fSChristoph Hellwig 	if (!sock)
2410d8a9b38fSChristoph Hellwig 		return err;
2411d8a9b38fSChristoph Hellwig 
24122174a3c3SBreno Leitao 	compat = in_compat_syscall();
24132174a3c3SBreno Leitao 	err = do_sock_getsockopt(sock, compat, level, optname,
24142174a3c3SBreno Leitao 				 USER_SOCKPTR(optval), USER_SOCKPTR(optlen));
24151da177e4SLinus Torvalds 
24166cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
24171da177e4SLinus Torvalds 	return err;
24181da177e4SLinus Torvalds }
24191da177e4SLinus Torvalds 
SYSCALL_DEFINE5(getsockopt,int,fd,int,level,int,optname,char __user *,optval,int __user *,optlen)242013a2d70eSDominik Brodowski SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
242113a2d70eSDominik Brodowski 		char __user *, optval, int __user *, optlen)
242213a2d70eSDominik Brodowski {
242313a2d70eSDominik Brodowski 	return __sys_getsockopt(fd, level, optname, optval, optlen);
242413a2d70eSDominik Brodowski }
242513a2d70eSDominik Brodowski 
24261da177e4SLinus Torvalds /*
24271da177e4SLinus Torvalds  *	Shutdown a socket.
24281da177e4SLinus Torvalds  */
24291da177e4SLinus Torvalds 
__sys_shutdown_sock(struct socket * sock,int how)2430b713c195SJens Axboe int __sys_shutdown_sock(struct socket *sock, int how)
2431b713c195SJens Axboe {
2432b713c195SJens Axboe 	int err;
2433b713c195SJens Axboe 
2434b713c195SJens Axboe 	err = security_socket_shutdown(sock, how);
2435b713c195SJens Axboe 	if (!err)
24361ded5e5aSEric Dumazet 		err = READ_ONCE(sock->ops)->shutdown(sock, how);
2437b713c195SJens Axboe 
2438b713c195SJens Axboe 	return err;
2439b713c195SJens Axboe }
2440b713c195SJens Axboe 
__sys_shutdown(int fd,int how)2441005a1aeaSDominik Brodowski int __sys_shutdown(int fd, int how)
24421da177e4SLinus Torvalds {
24436cb153caSBenjamin LaHaise 	int err, fput_needed;
24441da177e4SLinus Torvalds 	struct socket *sock;
24451da177e4SLinus Torvalds 
244689bddce5SStephen Hemminger 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
244789bddce5SStephen Hemminger 	if (sock != NULL) {
2448b713c195SJens Axboe 		err = __sys_shutdown_sock(sock, how);
24496cb153caSBenjamin LaHaise 		fput_light(sock->file, fput_needed);
24501da177e4SLinus Torvalds 	}
24511da177e4SLinus Torvalds 	return err;
24521da177e4SLinus Torvalds }
24531da177e4SLinus Torvalds 
SYSCALL_DEFINE2(shutdown,int,fd,int,how)2454005a1aeaSDominik Brodowski SYSCALL_DEFINE2(shutdown, int, fd, int, how)
2455005a1aeaSDominik Brodowski {
2456005a1aeaSDominik Brodowski 	return __sys_shutdown(fd, how);
2457005a1aeaSDominik Brodowski }
2458005a1aeaSDominik Brodowski 
24591da177e4SLinus Torvalds /* A couple of helpful macros for getting the address of the 32/64 bit
24601da177e4SLinus Torvalds  * fields which are the same type (int / unsigned) on our platforms.
24611da177e4SLinus Torvalds  */
24621da177e4SLinus Torvalds #define COMPAT_MSG(msg, member)	((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member)
24631da177e4SLinus Torvalds #define COMPAT_NAMELEN(msg)	COMPAT_MSG(msg, msg_namelen)
24641da177e4SLinus Torvalds #define COMPAT_FLAGS(msg)	COMPAT_MSG(msg, msg_flags)
24651da177e4SLinus Torvalds 
2466c71d8ebeSTetsuo Handa struct used_address {
2467c71d8ebeSTetsuo Handa 	struct sockaddr_storage name;
2468c71d8ebeSTetsuo Handa 	unsigned int name_len;
2469c71d8ebeSTetsuo Handa };
2470c71d8ebeSTetsuo Handa 
__copy_msghdr(struct msghdr * kmsg,struct user_msghdr * msg,struct sockaddr __user ** save_addr)24717fa875b8SDylan Yudaken int __copy_msghdr(struct msghdr *kmsg,
24727fa875b8SDylan Yudaken 		  struct user_msghdr *msg,
24737fa875b8SDylan Yudaken 		  struct sockaddr __user **save_addr)
24741661bf36SDan Carpenter {
247508adb7daSAl Viro 	ssize_t err;
247608adb7daSAl Viro 
24771f466e1fSChristoph Hellwig 	kmsg->msg_control_is_user = true;
24781228b34cSEric Dumazet 	kmsg->msg_get_inq = 0;
24797fa875b8SDylan Yudaken 	kmsg->msg_control_user = msg->msg_control;
24807fa875b8SDylan Yudaken 	kmsg->msg_controllen = msg->msg_controllen;
24817fa875b8SDylan Yudaken 	kmsg->msg_flags = msg->msg_flags;
2482ffb07550SAl Viro 
24837fa875b8SDylan Yudaken 	kmsg->msg_namelen = msg->msg_namelen;
24847fa875b8SDylan Yudaken 	if (!msg->msg_name)
24856a2a2b3aSAni Sinha 		kmsg->msg_namelen = 0;
24866a2a2b3aSAni Sinha 
2487dbb490b9SMatthew Leach 	if (kmsg->msg_namelen < 0)
2488dbb490b9SMatthew Leach 		return -EINVAL;
2489dbb490b9SMatthew Leach 
24901661bf36SDan Carpenter 	if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
2491db31c55aSDan Carpenter 		kmsg->msg_namelen = sizeof(struct sockaddr_storage);
249208adb7daSAl Viro 
249308adb7daSAl Viro 	if (save_addr)
24947fa875b8SDylan Yudaken 		*save_addr = msg->msg_name;
249508adb7daSAl Viro 
24967fa875b8SDylan Yudaken 	if (msg->msg_name && kmsg->msg_namelen) {
249708adb7daSAl Viro 		if (!save_addr) {
24987fa875b8SDylan Yudaken 			err = move_addr_to_kernel(msg->msg_name,
2499864d9664SPaolo Abeni 						  kmsg->msg_namelen,
250008adb7daSAl Viro 						  kmsg->msg_name);
250108adb7daSAl Viro 			if (err < 0)
250208adb7daSAl Viro 				return err;
250308adb7daSAl Viro 		}
250408adb7daSAl Viro 	} else {
250508adb7daSAl Viro 		kmsg->msg_name = NULL;
250608adb7daSAl Viro 		kmsg->msg_namelen = 0;
250708adb7daSAl Viro 	}
250808adb7daSAl Viro 
25097fa875b8SDylan Yudaken 	if (msg->msg_iovlen > UIO_MAXIOV)
251008adb7daSAl Viro 		return -EMSGSIZE;
251108adb7daSAl Viro 
25120345f931Stadeusz.struk@intel.com 	kmsg->msg_iocb = NULL;
25137c701d92SPavel Begunkov 	kmsg->msg_ubuf = NULL;
25140a384abfSJens Axboe 	return 0;
25150a384abfSJens Axboe }
25160a384abfSJens Axboe 
copy_msghdr_from_user(struct msghdr * kmsg,struct user_msghdr __user * umsg,struct sockaddr __user ** save_addr,struct iovec ** iov)25170a384abfSJens Axboe static int copy_msghdr_from_user(struct msghdr *kmsg,
25180a384abfSJens Axboe 				 struct user_msghdr __user *umsg,
25190a384abfSJens Axboe 				 struct sockaddr __user **save_addr,
25200a384abfSJens Axboe 				 struct iovec **iov)
25210a384abfSJens Axboe {
25220a384abfSJens Axboe 	struct user_msghdr msg;
25230a384abfSJens Axboe 	ssize_t err;
25240a384abfSJens Axboe 
25257fa875b8SDylan Yudaken 	if (copy_from_user(&msg, umsg, sizeof(*umsg)))
25267fa875b8SDylan Yudaken 		return -EFAULT;
25277fa875b8SDylan Yudaken 
25287fa875b8SDylan Yudaken 	err = __copy_msghdr(kmsg, &msg, save_addr);
25290a384abfSJens Axboe 	if (err)
25300a384abfSJens Axboe 		return err;
25310345f931Stadeusz.struk@intel.com 
2532de4eda9dSAl Viro 	err = import_iovec(save_addr ? ITER_DEST : ITER_SOURCE,
2533ffb07550SAl Viro 			    msg.msg_iov, msg.msg_iovlen,
2534da184284SAl Viro 			    UIO_FASTIOV, iov, &kmsg->msg_iter);
253587e5e6daSJens Axboe 	return err < 0 ? err : 0;
25361661bf36SDan Carpenter }
25371661bf36SDan Carpenter 
____sys_sendmsg(struct socket * sock,struct msghdr * msg_sys,unsigned int flags,struct used_address * used_address,unsigned int allowed_msghdr_flags)25384257c8caSJens Axboe static int ____sys_sendmsg(struct socket *sock, struct msghdr *msg_sys,
25394257c8caSJens Axboe 			   unsigned int flags, struct used_address *used_address,
254028a94d8fSTom Herbert 			   unsigned int allowed_msghdr_flags)
25411da177e4SLinus Torvalds {
2542b9d717a7SAlex Williamson 	unsigned char ctl[sizeof(struct cmsghdr) + 20]
2543846cc123SAmit Kushwaha 				__aligned(sizeof(__kernel_size_t));
2544b9d717a7SAlex Williamson 	/* 20 is size of ipv6_pktinfo */
25451da177e4SLinus Torvalds 	unsigned char *ctl_buf = ctl;
2546d8725c86SAl Viro 	int ctl_len;
254708adb7daSAl Viro 	ssize_t err;
25481da177e4SLinus Torvalds 
25491da177e4SLinus Torvalds 	err = -ENOBUFS;
25501da177e4SLinus Torvalds 
2551228e548eSAnton Blanchard 	if (msg_sys->msg_controllen > INT_MAX)
25524257c8caSJens Axboe 		goto out;
255328a94d8fSTom Herbert 	flags |= (msg_sys->msg_flags & allowed_msghdr_flags);
2554228e548eSAnton Blanchard 	ctl_len = msg_sys->msg_controllen;
25551da177e4SLinus Torvalds 	if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
255689bddce5SStephen Hemminger 		err =
2557228e548eSAnton Blanchard 		    cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl,
255889bddce5SStephen Hemminger 						     sizeof(ctl));
25591da177e4SLinus Torvalds 		if (err)
25604257c8caSJens Axboe 			goto out;
2561228e548eSAnton Blanchard 		ctl_buf = msg_sys->msg_control;
2562228e548eSAnton Blanchard 		ctl_len = msg_sys->msg_controllen;
25631da177e4SLinus Torvalds 	} else if (ctl_len) {
2564ac4340fcSDavid S. Miller 		BUILD_BUG_ON(sizeof(struct cmsghdr) !=
2565ac4340fcSDavid S. Miller 			     CMSG_ALIGN(sizeof(struct cmsghdr)));
256689bddce5SStephen Hemminger 		if (ctl_len > sizeof(ctl)) {
25671da177e4SLinus Torvalds 			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
25681da177e4SLinus Torvalds 			if (ctl_buf == NULL)
25694257c8caSJens Axboe 				goto out;
25701da177e4SLinus Torvalds 		}
25711da177e4SLinus Torvalds 		err = -EFAULT;
25721f466e1fSChristoph Hellwig 		if (copy_from_user(ctl_buf, msg_sys->msg_control_user, ctl_len))
25731da177e4SLinus Torvalds 			goto out_freectl;
2574228e548eSAnton Blanchard 		msg_sys->msg_control = ctl_buf;
25751f466e1fSChristoph Hellwig 		msg_sys->msg_control_is_user = false;
25761da177e4SLinus Torvalds 	}
2577b841b901SDavid Howells 	flags &= ~MSG_INTERNAL_SENDMSG_FLAGS;
2578228e548eSAnton Blanchard 	msg_sys->msg_flags = flags;
25791da177e4SLinus Torvalds 
25801da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
2581228e548eSAnton Blanchard 		msg_sys->msg_flags |= MSG_DONTWAIT;
2582c71d8ebeSTetsuo Handa 	/*
2583c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and current destination address is same as
2584c71d8ebeSTetsuo Handa 	 * previously succeeded address, omit asking LSM's decision.
2585c71d8ebeSTetsuo Handa 	 * used_address->name_len is initialized to UINT_MAX so that the first
2586c71d8ebeSTetsuo Handa 	 * destination address never matches.
2587c71d8ebeSTetsuo Handa 	 */
2588bc909d9dSMathieu Desnoyers 	if (used_address && msg_sys->msg_name &&
2589bc909d9dSMathieu Desnoyers 	    used_address->name_len == msg_sys->msg_namelen &&
2590bc909d9dSMathieu Desnoyers 	    !memcmp(&used_address->name, msg_sys->msg_name,
2591c71d8ebeSTetsuo Handa 		    used_address->name_len)) {
2592d8725c86SAl Viro 		err = sock_sendmsg_nosec(sock, msg_sys);
2593c71d8ebeSTetsuo Handa 		goto out_freectl;
2594c71d8ebeSTetsuo Handa 	}
259586a7e0b6SJordan Rife 	err = __sock_sendmsg(sock, msg_sys);
2596c71d8ebeSTetsuo Handa 	/*
2597c71d8ebeSTetsuo Handa 	 * If this is sendmmsg() and sending to current destination address was
2598c71d8ebeSTetsuo Handa 	 * successful, remember it.
2599c71d8ebeSTetsuo Handa 	 */
2600c71d8ebeSTetsuo Handa 	if (used_address && err >= 0) {
2601c71d8ebeSTetsuo Handa 		used_address->name_len = msg_sys->msg_namelen;
2602bc909d9dSMathieu Desnoyers 		if (msg_sys->msg_name)
2603bc909d9dSMathieu Desnoyers 			memcpy(&used_address->name, msg_sys->msg_name,
2604c71d8ebeSTetsuo Handa 			       used_address->name_len);
2605c71d8ebeSTetsuo Handa 	}
26061da177e4SLinus Torvalds 
26071da177e4SLinus Torvalds out_freectl:
26081da177e4SLinus Torvalds 	if (ctl_buf != ctl)
26091da177e4SLinus Torvalds 		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
26104257c8caSJens Axboe out:
26114257c8caSJens Axboe 	return err;
26124257c8caSJens Axboe }
26134257c8caSJens Axboe 
sendmsg_copy_msghdr(struct msghdr * msg,struct user_msghdr __user * umsg,unsigned flags,struct iovec ** iov)261403b1230cSJens Axboe int sendmsg_copy_msghdr(struct msghdr *msg,
26154257c8caSJens Axboe 			struct user_msghdr __user *umsg, unsigned flags,
26164257c8caSJens Axboe 			struct iovec **iov)
26174257c8caSJens Axboe {
26184257c8caSJens Axboe 	int err;
26194257c8caSJens Axboe 
26204257c8caSJens Axboe 	if (flags & MSG_CMSG_COMPAT) {
26214257c8caSJens Axboe 		struct compat_msghdr __user *msg_compat;
26224257c8caSJens Axboe 
26234257c8caSJens Axboe 		msg_compat = (struct compat_msghdr __user *) umsg;
26244257c8caSJens Axboe 		err = get_compat_msghdr(msg, msg_compat, NULL, iov);
26254257c8caSJens Axboe 	} else {
26264257c8caSJens Axboe 		err = copy_msghdr_from_user(msg, umsg, NULL, iov);
26274257c8caSJens Axboe 	}
26284257c8caSJens Axboe 	if (err < 0)
26294257c8caSJens Axboe 		return err;
26304257c8caSJens Axboe 
26314257c8caSJens Axboe 	return 0;
26324257c8caSJens Axboe }
26334257c8caSJens 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)26344257c8caSJens Axboe static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
26354257c8caSJens Axboe 			 struct msghdr *msg_sys, unsigned int flags,
26364257c8caSJens Axboe 			 struct used_address *used_address,
26374257c8caSJens Axboe 			 unsigned int allowed_msghdr_flags)
26384257c8caSJens Axboe {
26394257c8caSJens Axboe 	struct sockaddr_storage address;
26404257c8caSJens Axboe 	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
26414257c8caSJens Axboe 	ssize_t err;
26424257c8caSJens Axboe 
26434257c8caSJens Axboe 	msg_sys->msg_name = &address;
26444257c8caSJens Axboe 
26454257c8caSJens Axboe 	err = sendmsg_copy_msghdr(msg_sys, msg, flags, &iov);
26464257c8caSJens Axboe 	if (err < 0)
26474257c8caSJens Axboe 		return err;
26484257c8caSJens Axboe 
26494257c8caSJens Axboe 	err = ____sys_sendmsg(sock, msg_sys, flags, used_address,
26504257c8caSJens Axboe 				allowed_msghdr_flags);
2651a74e9106SEric Dumazet 	kfree(iov);
2652228e548eSAnton Blanchard 	return err;
2653228e548eSAnton Blanchard }
2654228e548eSAnton Blanchard 
2655228e548eSAnton Blanchard /*
2656228e548eSAnton Blanchard  *	BSD sendmsg interface
2657228e548eSAnton Blanchard  */
__sys_sendmsg_sock(struct socket * sock,struct msghdr * msg,unsigned int flags)265803b1230cSJens Axboe long __sys_sendmsg_sock(struct socket *sock, struct msghdr *msg,
26590fa03c62SJens Axboe 			unsigned int flags)
26600fa03c62SJens Axboe {
266103b1230cSJens Axboe 	return ____sys_sendmsg(sock, msg, flags, NULL, 0);
26620fa03c62SJens Axboe }
2663228e548eSAnton Blanchard 
__sys_sendmsg(int fd,struct user_msghdr __user * msg,unsigned int flags,bool forbid_cmsg_compat)2664e1834a32SDominik Brodowski long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned int flags,
2665e1834a32SDominik Brodowski 		   bool forbid_cmsg_compat)
2666228e548eSAnton Blanchard {
2667228e548eSAnton Blanchard 	int fput_needed, err;
2668228e548eSAnton Blanchard 	struct msghdr msg_sys;
26691be374a0SAndy Lutomirski 	struct socket *sock;
2670228e548eSAnton Blanchard 
2671e1834a32SDominik Brodowski 	if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT))
2672e1834a32SDominik Brodowski 		return -EINVAL;
2673e1834a32SDominik Brodowski 
26741be374a0SAndy Lutomirski 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2675228e548eSAnton Blanchard 	if (!sock)
2676228e548eSAnton Blanchard 		goto out;
2677228e548eSAnton Blanchard 
267828a94d8fSTom Herbert 	err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL, 0);
2679228e548eSAnton Blanchard 
26806cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
26811da177e4SLinus Torvalds out:
26821da177e4SLinus Torvalds 	return err;
26831da177e4SLinus Torvalds }
26841da177e4SLinus Torvalds 
SYSCALL_DEFINE3(sendmsg,int,fd,struct user_msghdr __user *,msg,unsigned int,flags)2685666547ffSAl Viro SYSCALL_DEFINE3(sendmsg, int, fd, struct user_msghdr __user *, msg, unsigned int, flags)
2686a7526eb5SAndy Lutomirski {
2687e1834a32SDominik Brodowski 	return __sys_sendmsg(fd, msg, flags, true);
2688a7526eb5SAndy Lutomirski }
2689a7526eb5SAndy Lutomirski 
2690228e548eSAnton Blanchard /*
2691228e548eSAnton Blanchard  *	Linux sendmmsg interface
2692228e548eSAnton Blanchard  */
2693228e548eSAnton Blanchard 
__sys_sendmmsg(int fd,struct mmsghdr __user * mmsg,unsigned int vlen,unsigned int flags,bool forbid_cmsg_compat)2694228e548eSAnton Blanchard int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2695e1834a32SDominik Brodowski 		   unsigned int flags, bool forbid_cmsg_compat)
2696228e548eSAnton Blanchard {
2697228e548eSAnton Blanchard 	int fput_needed, err, datagrams;
2698228e548eSAnton Blanchard 	struct socket *sock;
2699228e548eSAnton Blanchard 	struct mmsghdr __user *entry;
2700228e548eSAnton Blanchard 	struct compat_mmsghdr __user *compat_entry;
2701228e548eSAnton Blanchard 	struct msghdr msg_sys;
2702c71d8ebeSTetsuo Handa 	struct used_address used_address;
2703f092276dSTom Herbert 	unsigned int oflags = flags;
2704228e548eSAnton Blanchard 
2705e1834a32SDominik Brodowski 	if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT))
2706e1834a32SDominik Brodowski 		return -EINVAL;
2707e1834a32SDominik Brodowski 
270898382f41SAnton Blanchard 	if (vlen > UIO_MAXIOV)
270998382f41SAnton Blanchard 		vlen = UIO_MAXIOV;
2710228e548eSAnton Blanchard 
2711228e548eSAnton Blanchard 	datagrams = 0;
2712228e548eSAnton Blanchard 
2713228e548eSAnton Blanchard 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2714228e548eSAnton Blanchard 	if (!sock)
2715228e548eSAnton Blanchard 		return err;
2716228e548eSAnton Blanchard 
2717c71d8ebeSTetsuo Handa 	used_address.name_len = UINT_MAX;
2718228e548eSAnton Blanchard 	entry = mmsg;
2719228e548eSAnton Blanchard 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2720728ffb86SAnton Blanchard 	err = 0;
2721f092276dSTom Herbert 	flags |= MSG_BATCH;
2722228e548eSAnton Blanchard 
2723228e548eSAnton Blanchard 	while (datagrams < vlen) {
2724f092276dSTom Herbert 		if (datagrams == vlen - 1)
2725f092276dSTom Herbert 			flags = oflags;
2726f092276dSTom Herbert 
2727228e548eSAnton Blanchard 		if (MSG_CMSG_COMPAT & flags) {
2728666547ffSAl Viro 			err = ___sys_sendmsg(sock, (struct user_msghdr __user *)compat_entry,
272928a94d8fSTom Herbert 					     &msg_sys, flags, &used_address, MSG_EOR);
2730228e548eSAnton Blanchard 			if (err < 0)
2731228e548eSAnton Blanchard 				break;
2732228e548eSAnton Blanchard 			err = __put_user(err, &compat_entry->msg_len);
2733228e548eSAnton Blanchard 			++compat_entry;
2734228e548eSAnton Blanchard 		} else {
2735a7526eb5SAndy Lutomirski 			err = ___sys_sendmsg(sock,
2736666547ffSAl Viro 					     (struct user_msghdr __user *)entry,
273728a94d8fSTom Herbert 					     &msg_sys, flags, &used_address, MSG_EOR);
2738228e548eSAnton Blanchard 			if (err < 0)
2739228e548eSAnton Blanchard 				break;
2740228e548eSAnton Blanchard 			err = put_user(err, &entry->msg_len);
2741228e548eSAnton Blanchard 			++entry;
2742228e548eSAnton Blanchard 		}
2743228e548eSAnton Blanchard 
2744228e548eSAnton Blanchard 		if (err)
2745228e548eSAnton Blanchard 			break;
2746228e548eSAnton Blanchard 		++datagrams;
27473023898bSSoheil Hassas Yeganeh 		if (msg_data_left(&msg_sys))
27483023898bSSoheil Hassas Yeganeh 			break;
2749a78cb84cSEric Dumazet 		cond_resched();
2750228e548eSAnton Blanchard 	}
2751228e548eSAnton Blanchard 
2752228e548eSAnton Blanchard 	fput_light(sock->file, fput_needed);
2753228e548eSAnton Blanchard 
2754728ffb86SAnton Blanchard 	/* We only return an error if no datagrams were able to be sent */
2755728ffb86SAnton Blanchard 	if (datagrams != 0)
2756228e548eSAnton Blanchard 		return datagrams;
2757228e548eSAnton Blanchard 
2758228e548eSAnton Blanchard 	return err;
2759228e548eSAnton Blanchard }
2760228e548eSAnton Blanchard 
SYSCALL_DEFINE4(sendmmsg,int,fd,struct mmsghdr __user *,mmsg,unsigned int,vlen,unsigned int,flags)2761228e548eSAnton Blanchard SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
2762228e548eSAnton Blanchard 		unsigned int, vlen, unsigned int, flags)
2763228e548eSAnton Blanchard {
2764e1834a32SDominik Brodowski 	return __sys_sendmmsg(fd, mmsg, vlen, flags, true);
2765228e548eSAnton Blanchard }
2766228e548eSAnton Blanchard 
recvmsg_copy_msghdr(struct msghdr * msg,struct user_msghdr __user * umsg,unsigned flags,struct sockaddr __user ** uaddr,struct iovec ** iov)276703b1230cSJens Axboe int recvmsg_copy_msghdr(struct msghdr *msg,
27684257c8caSJens Axboe 			struct user_msghdr __user *umsg, unsigned flags,
27694257c8caSJens Axboe 			struct sockaddr __user **uaddr,
27704257c8caSJens Axboe 			struct iovec **iov)
27714257c8caSJens Axboe {
27724257c8caSJens Axboe 	ssize_t err;
27734257c8caSJens Axboe 
27744257c8caSJens Axboe 	if (MSG_CMSG_COMPAT & flags) {
27754257c8caSJens Axboe 		struct compat_msghdr __user *msg_compat;
27764257c8caSJens Axboe 
27774257c8caSJens Axboe 		msg_compat = (struct compat_msghdr __user *) umsg;
27784257c8caSJens Axboe 		err = get_compat_msghdr(msg, msg_compat, uaddr, iov);
27794257c8caSJens Axboe 	} else {
27804257c8caSJens Axboe 		err = copy_msghdr_from_user(msg, umsg, uaddr, iov);
27814257c8caSJens Axboe 	}
27824257c8caSJens Axboe 	if (err < 0)
27834257c8caSJens Axboe 		return err;
27844257c8caSJens Axboe 
27854257c8caSJens Axboe 	return 0;
27864257c8caSJens Axboe }
27874257c8caSJens Axboe 
____sys_recvmsg(struct socket * sock,struct msghdr * msg_sys,struct user_msghdr __user * msg,struct sockaddr __user * uaddr,unsigned int flags,int nosec)27884257c8caSJens Axboe static int ____sys_recvmsg(struct socket *sock, struct msghdr *msg_sys,
27894257c8caSJens Axboe 			   struct user_msghdr __user *msg,
27904257c8caSJens Axboe 			   struct sockaddr __user *uaddr,
27914257c8caSJens Axboe 			   unsigned int flags, int nosec)
27921da177e4SLinus Torvalds {
279389bddce5SStephen Hemminger 	struct compat_msghdr __user *msg_compat =
279489bddce5SStephen Hemminger 					(struct compat_msghdr __user *) msg;
27954257c8caSJens Axboe 	int __user *uaddr_len = COMPAT_NAMELEN(msg);
27964257c8caSJens Axboe 	struct sockaddr_storage addr;
27971da177e4SLinus Torvalds 	unsigned long cmsg_ptr;
27982da62906SAl Viro 	int len;
279908adb7daSAl Viro 	ssize_t err;
28001da177e4SLinus Torvalds 
280108adb7daSAl Viro 	msg_sys->msg_name = &addr;
2802a2e27255SArnaldo Carvalho de Melo 	cmsg_ptr = (unsigned long)msg_sys->msg_control;
2803a2e27255SArnaldo Carvalho de Melo 	msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
28041da177e4SLinus Torvalds 
2805f3d33426SHannes Frederic Sowa 	/* We assume all kernel code knows the size of sockaddr_storage */
2806f3d33426SHannes Frederic Sowa 	msg_sys->msg_namelen = 0;
2807f3d33426SHannes Frederic Sowa 
28081da177e4SLinus Torvalds 	if (sock->file->f_flags & O_NONBLOCK)
28091da177e4SLinus Torvalds 		flags |= MSG_DONTWAIT;
28101af66221SEric Dumazet 
28111af66221SEric Dumazet 	if (unlikely(nosec))
28121af66221SEric Dumazet 		err = sock_recvmsg_nosec(sock, msg_sys, flags);
28131af66221SEric Dumazet 	else
28141af66221SEric Dumazet 		err = sock_recvmsg(sock, msg_sys, flags);
28151af66221SEric Dumazet 
28161da177e4SLinus Torvalds 	if (err < 0)
28174257c8caSJens Axboe 		goto out;
28181da177e4SLinus Torvalds 	len = err;
28191da177e4SLinus Torvalds 
28201da177e4SLinus Torvalds 	if (uaddr != NULL) {
282143db362dSMaciej Żenczykowski 		err = move_addr_to_user(&addr,
2822a2e27255SArnaldo Carvalho de Melo 					msg_sys->msg_namelen, uaddr,
282389bddce5SStephen Hemminger 					uaddr_len);
28241da177e4SLinus Torvalds 		if (err < 0)
28254257c8caSJens Axboe 			goto out;
28261da177e4SLinus Torvalds 	}
2827a2e27255SArnaldo Carvalho de Melo 	err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
282837f7f421SDavid S. Miller 			 COMPAT_FLAGS(msg));
28291da177e4SLinus Torvalds 	if (err)
28304257c8caSJens Axboe 		goto out;
28311da177e4SLinus Torvalds 	if (MSG_CMSG_COMPAT & flags)
2832a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
28331da177e4SLinus Torvalds 				 &msg_compat->msg_controllen);
28341da177e4SLinus Torvalds 	else
2835a2e27255SArnaldo Carvalho de Melo 		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
28361da177e4SLinus Torvalds 				 &msg->msg_controllen);
28371da177e4SLinus Torvalds 	if (err)
28384257c8caSJens Axboe 		goto out;
28391da177e4SLinus Torvalds 	err = len;
28404257c8caSJens Axboe out:
28414257c8caSJens Axboe 	return err;
28424257c8caSJens Axboe }
28431da177e4SLinus Torvalds 
___sys_recvmsg(struct socket * sock,struct user_msghdr __user * msg,struct msghdr * msg_sys,unsigned int flags,int nosec)28444257c8caSJens Axboe static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg,
28454257c8caSJens Axboe 			 struct msghdr *msg_sys, unsigned int flags, int nosec)
28464257c8caSJens Axboe {
28474257c8caSJens Axboe 	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
28484257c8caSJens Axboe 	/* user mode address pointers */
28494257c8caSJens Axboe 	struct sockaddr __user *uaddr;
28504257c8caSJens Axboe 	ssize_t err;
28514257c8caSJens Axboe 
28524257c8caSJens Axboe 	err = recvmsg_copy_msghdr(msg_sys, msg, flags, &uaddr, &iov);
28534257c8caSJens Axboe 	if (err < 0)
28544257c8caSJens Axboe 		return err;
28554257c8caSJens Axboe 
28564257c8caSJens Axboe 	err = ____sys_recvmsg(sock, msg_sys, msg, uaddr, flags, nosec);
2857a74e9106SEric Dumazet 	kfree(iov);
2858a2e27255SArnaldo Carvalho de Melo 	return err;
2859a2e27255SArnaldo Carvalho de Melo }
2860a2e27255SArnaldo Carvalho de Melo 
2861a2e27255SArnaldo Carvalho de Melo /*
2862a2e27255SArnaldo Carvalho de Melo  *	BSD recvmsg interface
2863a2e27255SArnaldo Carvalho de Melo  */
2864a2e27255SArnaldo Carvalho de Melo 
__sys_recvmsg_sock(struct socket * sock,struct msghdr * msg,struct user_msghdr __user * umsg,struct sockaddr __user * uaddr,unsigned int flags)286503b1230cSJens Axboe long __sys_recvmsg_sock(struct socket *sock, struct msghdr *msg,
286603b1230cSJens Axboe 			struct user_msghdr __user *umsg,
286703b1230cSJens Axboe 			struct sockaddr __user *uaddr, unsigned int flags)
2868aa1fa28fSJens Axboe {
286903b1230cSJens Axboe 	return ____sys_recvmsg(sock, msg, umsg, uaddr, flags, 0);
2870aa1fa28fSJens Axboe }
2871aa1fa28fSJens Axboe 
__sys_recvmsg(int fd,struct user_msghdr __user * msg,unsigned int flags,bool forbid_cmsg_compat)2872e1834a32SDominik Brodowski long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned int flags,
2873e1834a32SDominik Brodowski 		   bool forbid_cmsg_compat)
2874a2e27255SArnaldo Carvalho de Melo {
2875a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err;
2876a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
28771be374a0SAndy Lutomirski 	struct socket *sock;
2878a2e27255SArnaldo Carvalho de Melo 
2879e1834a32SDominik Brodowski 	if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT))
2880e1834a32SDominik Brodowski 		return -EINVAL;
2881e1834a32SDominik Brodowski 
28821be374a0SAndy Lutomirski 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2883a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2884a2e27255SArnaldo Carvalho de Melo 		goto out;
2885a2e27255SArnaldo Carvalho de Melo 
2886a7526eb5SAndy Lutomirski 	err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0);
2887a2e27255SArnaldo Carvalho de Melo 
28886cb153caSBenjamin LaHaise 	fput_light(sock->file, fput_needed);
28891da177e4SLinus Torvalds out:
28901da177e4SLinus Torvalds 	return err;
28911da177e4SLinus Torvalds }
28921da177e4SLinus Torvalds 
SYSCALL_DEFINE3(recvmsg,int,fd,struct user_msghdr __user *,msg,unsigned int,flags)2893666547ffSAl Viro SYSCALL_DEFINE3(recvmsg, int, fd, struct user_msghdr __user *, msg,
2894a7526eb5SAndy Lutomirski 		unsigned int, flags)
2895a7526eb5SAndy Lutomirski {
2896e1834a32SDominik Brodowski 	return __sys_recvmsg(fd, msg, flags, true);
2897a7526eb5SAndy Lutomirski }
2898a7526eb5SAndy Lutomirski 
2899a2e27255SArnaldo Carvalho de Melo /*
2900a2e27255SArnaldo Carvalho de Melo  *     Linux recvmmsg interface
2901a2e27255SArnaldo Carvalho de Melo  */
29021da177e4SLinus Torvalds 
do_recvmmsg(int fd,struct mmsghdr __user * mmsg,unsigned int vlen,unsigned int flags,struct timespec64 * timeout)2903e11d4284SArnd Bergmann static int do_recvmmsg(int fd, struct mmsghdr __user *mmsg,
2904e11d4284SArnd Bergmann 			  unsigned int vlen, unsigned int flags,
2905e11d4284SArnd Bergmann 			  struct timespec64 *timeout)
2906a2e27255SArnaldo Carvalho de Melo {
2907a2e27255SArnaldo Carvalho de Melo 	int fput_needed, err, datagrams;
2908a2e27255SArnaldo Carvalho de Melo 	struct socket *sock;
2909a2e27255SArnaldo Carvalho de Melo 	struct mmsghdr __user *entry;
2910d7256d0eSJean-Mickael Guerin 	struct compat_mmsghdr __user *compat_entry;
2911a2e27255SArnaldo Carvalho de Melo 	struct msghdr msg_sys;
2912766b9f92SDeepa Dinamani 	struct timespec64 end_time;
2913766b9f92SDeepa Dinamani 	struct timespec64 timeout64;
2914a2e27255SArnaldo Carvalho de Melo 
2915a2e27255SArnaldo Carvalho de Melo 	if (timeout &&
2916a2e27255SArnaldo Carvalho de Melo 	    poll_select_set_timeout(&end_time, timeout->tv_sec,
2917a2e27255SArnaldo Carvalho de Melo 				    timeout->tv_nsec))
2918a2e27255SArnaldo Carvalho de Melo 		return -EINVAL;
2919a2e27255SArnaldo Carvalho de Melo 
2920a2e27255SArnaldo Carvalho de Melo 	datagrams = 0;
2921a2e27255SArnaldo Carvalho de Melo 
2922a2e27255SArnaldo Carvalho de Melo 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
2923a2e27255SArnaldo Carvalho de Melo 	if (!sock)
2924a2e27255SArnaldo Carvalho de Melo 		return err;
2925a2e27255SArnaldo Carvalho de Melo 
29267797dc41SSoheil Hassas Yeganeh 	if (likely(!(flags & MSG_ERRQUEUE))) {
2927a2e27255SArnaldo Carvalho de Melo 		err = sock_error(sock->sk);
2928e623a9e9SMaxime Jayat 		if (err) {
2929e623a9e9SMaxime Jayat 			datagrams = err;
2930a2e27255SArnaldo Carvalho de Melo 			goto out_put;
2931e623a9e9SMaxime Jayat 		}
29327797dc41SSoheil Hassas Yeganeh 	}
2933a2e27255SArnaldo Carvalho de Melo 
2934a2e27255SArnaldo Carvalho de Melo 	entry = mmsg;
2935d7256d0eSJean-Mickael Guerin 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
2936a2e27255SArnaldo Carvalho de Melo 
2937a2e27255SArnaldo Carvalho de Melo 	while (datagrams < vlen) {
2938a2e27255SArnaldo Carvalho de Melo 		/*
2939a2e27255SArnaldo Carvalho de Melo 		 * No need to ask LSM for more than the first datagram.
2940a2e27255SArnaldo Carvalho de Melo 		 */
2941d7256d0eSJean-Mickael Guerin 		if (MSG_CMSG_COMPAT & flags) {
2942666547ffSAl Viro 			err = ___sys_recvmsg(sock, (struct user_msghdr __user *)compat_entry,
2943b9eb8b87SAnton Blanchard 					     &msg_sys, flags & ~MSG_WAITFORONE,
2944b9eb8b87SAnton Blanchard 					     datagrams);
2945d7256d0eSJean-Mickael Guerin 			if (err < 0)
2946d7256d0eSJean-Mickael Guerin 				break;
2947d7256d0eSJean-Mickael Guerin 			err = __put_user(err, &compat_entry->msg_len);
2948d7256d0eSJean-Mickael Guerin 			++compat_entry;
2949d7256d0eSJean-Mickael Guerin 		} else {
2950a7526eb5SAndy Lutomirski 			err = ___sys_recvmsg(sock,
2951666547ffSAl Viro 					     (struct user_msghdr __user *)entry,
2952b9eb8b87SAnton Blanchard 					     &msg_sys, flags & ~MSG_WAITFORONE,
2953b9eb8b87SAnton Blanchard 					     datagrams);
2954a2e27255SArnaldo Carvalho de Melo 			if (err < 0)
2955a2e27255SArnaldo Carvalho de Melo 				break;
2956a2e27255SArnaldo Carvalho de Melo 			err = put_user(err, &entry->msg_len);
2957d7256d0eSJean-Mickael Guerin 			++entry;
2958d7256d0eSJean-Mickael Guerin 		}
2959d7256d0eSJean-Mickael Guerin 
2960a2e27255SArnaldo Carvalho de Melo 		if (err)
2961a2e27255SArnaldo Carvalho de Melo 			break;
2962a2e27255SArnaldo Carvalho de Melo 		++datagrams;
2963a2e27255SArnaldo Carvalho de Melo 
296471c5c159SBrandon L Black 		/* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
296571c5c159SBrandon L Black 		if (flags & MSG_WAITFORONE)
296671c5c159SBrandon L Black 			flags |= MSG_DONTWAIT;
296771c5c159SBrandon L Black 
2968a2e27255SArnaldo Carvalho de Melo 		if (timeout) {
2969766b9f92SDeepa Dinamani 			ktime_get_ts64(&timeout64);
2970c2e6c856SArnd Bergmann 			*timeout = timespec64_sub(end_time, timeout64);
2971a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_sec < 0) {
2972a2e27255SArnaldo Carvalho de Melo 				timeout->tv_sec = timeout->tv_nsec = 0;
2973a2e27255SArnaldo Carvalho de Melo 				break;
2974a2e27255SArnaldo Carvalho de Melo 			}
2975a2e27255SArnaldo Carvalho de Melo 
2976a2e27255SArnaldo Carvalho de Melo 			/* Timeout, return less than vlen datagrams */
2977a2e27255SArnaldo Carvalho de Melo 			if (timeout->tv_nsec == 0 && timeout->tv_sec == 0)
2978a2e27255SArnaldo Carvalho de Melo 				break;
2979a2e27255SArnaldo Carvalho de Melo 		}
2980a2e27255SArnaldo Carvalho de Melo 
2981a2e27255SArnaldo Carvalho de Melo 		/* Out of band data, return right away */
2982a2e27255SArnaldo Carvalho de Melo 		if (msg_sys.msg_flags & MSG_OOB)
2983a2e27255SArnaldo Carvalho de Melo 			break;
2984a78cb84cSEric Dumazet 		cond_resched();
2985a2e27255SArnaldo Carvalho de Melo 	}
2986a2e27255SArnaldo Carvalho de Melo 
2987a2e27255SArnaldo Carvalho de Melo 	if (err == 0)
298834b88a68SArnaldo Carvalho de Melo 		goto out_put;
2989a2e27255SArnaldo Carvalho de Melo 
299034b88a68SArnaldo Carvalho de Melo 	if (datagrams == 0) {
299134b88a68SArnaldo Carvalho de Melo 		datagrams = err;
299234b88a68SArnaldo Carvalho de Melo 		goto out_put;
299334b88a68SArnaldo Carvalho de Melo 	}
299434b88a68SArnaldo Carvalho de Melo 
2995a2e27255SArnaldo Carvalho de Melo 	/*
2996a2e27255SArnaldo Carvalho de Melo 	 * We may return less entries than requested (vlen) if the
2997a2e27255SArnaldo Carvalho de Melo 	 * sock is non block and there aren't enough datagrams...
2998a2e27255SArnaldo Carvalho de Melo 	 */
2999a2e27255SArnaldo Carvalho de Melo 	if (err != -EAGAIN) {
3000a2e27255SArnaldo Carvalho de Melo 		/*
3001a2e27255SArnaldo Carvalho de Melo 		 * ... or  if recvmsg returns an error after we
3002a2e27255SArnaldo Carvalho de Melo 		 * received some datagrams, where we record the
3003a2e27255SArnaldo Carvalho de Melo 		 * error to return on the next call or if the
3004a2e27255SArnaldo Carvalho de Melo 		 * app asks about it using getsockopt(SO_ERROR).
3005a2e27255SArnaldo Carvalho de Melo 		 */
3006e05a5f51SEric Dumazet 		WRITE_ONCE(sock->sk->sk_err, -err);
3007a2e27255SArnaldo Carvalho de Melo 	}
300834b88a68SArnaldo Carvalho de Melo out_put:
300934b88a68SArnaldo Carvalho de Melo 	fput_light(sock->file, fput_needed);
3010a2e27255SArnaldo Carvalho de Melo 
3011a2e27255SArnaldo Carvalho de Melo 	return datagrams;
3012a2e27255SArnaldo Carvalho de Melo }
3013a2e27255SArnaldo 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)3014e11d4284SArnd Bergmann int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg,
30151255e269SDominik Brodowski 		   unsigned int vlen, unsigned int flags,
3016e11d4284SArnd Bergmann 		   struct __kernel_timespec __user *timeout,
3017e11d4284SArnd Bergmann 		   struct old_timespec32 __user *timeout32)
3018a2e27255SArnaldo Carvalho de Melo {
3019a2e27255SArnaldo Carvalho de Melo 	int datagrams;
3020c2e6c856SArnd Bergmann 	struct timespec64 timeout_sys;
3021a2e27255SArnaldo Carvalho de Melo 
3022e11d4284SArnd Bergmann 	if (timeout && get_timespec64(&timeout_sys, timeout))
3023a2e27255SArnaldo Carvalho de Melo 		return -EFAULT;
3024a2e27255SArnaldo Carvalho de Melo 
3025e11d4284SArnd Bergmann 	if (timeout32 && get_old_timespec32(&timeout_sys, timeout32))
3026e11d4284SArnd Bergmann 		return -EFAULT;
3027a2e27255SArnaldo Carvalho de Melo 
3028e11d4284SArnd Bergmann 	if (!timeout && !timeout32)
3029e11d4284SArnd Bergmann 		return do_recvmmsg(fd, mmsg, vlen, flags, NULL);
3030e11d4284SArnd Bergmann 
3031e11d4284SArnd Bergmann 	datagrams = do_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys);
3032e11d4284SArnd Bergmann 
3033e11d4284SArnd Bergmann 	if (datagrams <= 0)
3034e11d4284SArnd Bergmann 		return datagrams;
3035e11d4284SArnd Bergmann 
3036e11d4284SArnd Bergmann 	if (timeout && put_timespec64(&timeout_sys, timeout))
3037e11d4284SArnd Bergmann 		datagrams = -EFAULT;
3038e11d4284SArnd Bergmann 
3039e11d4284SArnd Bergmann 	if (timeout32 && put_old_timespec32(&timeout_sys, timeout32))
3040a2e27255SArnaldo Carvalho de Melo 		datagrams = -EFAULT;
3041a2e27255SArnaldo Carvalho de Melo 
3042a2e27255SArnaldo Carvalho de Melo 	return datagrams;
3043a2e27255SArnaldo Carvalho de Melo }
3044a2e27255SArnaldo Carvalho de Melo 
SYSCALL_DEFINE5(recvmmsg,int,fd,struct mmsghdr __user *,mmsg,unsigned int,vlen,unsigned int,flags,struct __kernel_timespec __user *,timeout)30451255e269SDominik Brodowski SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
30461255e269SDominik Brodowski 		unsigned int, vlen, unsigned int, flags,
3047c2e6c856SArnd Bergmann 		struct __kernel_timespec __user *, timeout)
30481255e269SDominik Brodowski {
3049e11d4284SArnd Bergmann 	if (flags & MSG_CMSG_COMPAT)
3050e11d4284SArnd Bergmann 		return -EINVAL;
3051e11d4284SArnd Bergmann 
3052e11d4284SArnd Bergmann 	return __sys_recvmmsg(fd, mmsg, vlen, flags, timeout, NULL);
30531255e269SDominik Brodowski }
30541255e269SDominik Brodowski 
3055e11d4284SArnd 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)3056e11d4284SArnd Bergmann SYSCALL_DEFINE5(recvmmsg_time32, int, fd, struct mmsghdr __user *, mmsg,
3057e11d4284SArnd Bergmann 		unsigned int, vlen, unsigned int, flags,
3058e11d4284SArnd Bergmann 		struct old_timespec32 __user *, timeout)
3059e11d4284SArnd Bergmann {
3060e11d4284SArnd Bergmann 	if (flags & MSG_CMSG_COMPAT)
3061e11d4284SArnd Bergmann 		return -EINVAL;
3062e11d4284SArnd Bergmann 
3063e11d4284SArnd Bergmann 	return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL, timeout);
3064e11d4284SArnd Bergmann }
3065e11d4284SArnd Bergmann #endif
3066e11d4284SArnd Bergmann 
3067a2e27255SArnaldo Carvalho de Melo #ifdef __ARCH_WANT_SYS_SOCKETCALL
30681da177e4SLinus Torvalds /* Argument list sizes for sys_socketcall */
30691da177e4SLinus Torvalds #define AL(x) ((x) * sizeof(unsigned long))
3070228e548eSAnton Blanchard static const unsigned char nargs[21] = {
307189bddce5SStephen Hemminger 	AL(0), AL(3), AL(3), AL(3), AL(2), AL(3),
30721da177e4SLinus Torvalds 	AL(3), AL(3), AL(4), AL(4), AL(4), AL(6),
3073aaca0bdcSUlrich Drepper 	AL(6), AL(2), AL(5), AL(5), AL(3), AL(3),
3074228e548eSAnton Blanchard 	AL(4), AL(5), AL(4)
307589bddce5SStephen Hemminger };
307689bddce5SStephen Hemminger 
30771da177e4SLinus Torvalds #undef AL
30781da177e4SLinus Torvalds 
30791da177e4SLinus Torvalds /*
30801da177e4SLinus Torvalds  *	System call vectors.
30811da177e4SLinus Torvalds  *
30821da177e4SLinus Torvalds  *	Argument checking cleaned up. Saved 20% in size.
30831da177e4SLinus Torvalds  *  This function doesn't need to set the kernel lock because
30841da177e4SLinus Torvalds  *  it is set by the callees.
30851da177e4SLinus Torvalds  */
30861da177e4SLinus Torvalds 
SYSCALL_DEFINE2(socketcall,int,call,unsigned long __user *,args)30873e0fa65fSHeiko Carstens SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
30881da177e4SLinus Torvalds {
30892950fa9dSChen Gang 	unsigned long a[AUDITSC_ARGS];
30901da177e4SLinus Torvalds 	unsigned long a0, a1;
30911da177e4SLinus Torvalds 	int err;
309247379052SArjan van de Ven 	unsigned int len;
30931da177e4SLinus Torvalds 
3094228e548eSAnton Blanchard 	if (call < 1 || call > SYS_SENDMMSG)
30951da177e4SLinus Torvalds 		return -EINVAL;
3096c8e8cd57SJeremy Cline 	call = array_index_nospec(call, SYS_SENDMMSG + 1);
30971da177e4SLinus Torvalds 
309847379052SArjan van de Ven 	len = nargs[call];
309947379052SArjan van de Ven 	if (len > sizeof(a))
310047379052SArjan van de Ven 		return -EINVAL;
310147379052SArjan van de Ven 
31021da177e4SLinus Torvalds 	/* copy_from_user should be SMP safe. */
310347379052SArjan van de Ven 	if (copy_from_user(a, args, len))
31041da177e4SLinus Torvalds 		return -EFAULT;
31051da177e4SLinus Torvalds 
31062950fa9dSChen Gang 	err = audit_socketcall(nargs[call] / sizeof(unsigned long), a);
31072950fa9dSChen Gang 	if (err)
31082950fa9dSChen Gang 		return err;
31093ec3b2fbSDavid Woodhouse 
31101da177e4SLinus Torvalds 	a0 = a[0];
31111da177e4SLinus Torvalds 	a1 = a[1];
31121da177e4SLinus Torvalds 
311389bddce5SStephen Hemminger 	switch (call) {
31141da177e4SLinus Torvalds 	case SYS_SOCKET:
31159d6a15c3SDominik Brodowski 		err = __sys_socket(a0, a1, a[2]);
31161da177e4SLinus Torvalds 		break;
31171da177e4SLinus Torvalds 	case SYS_BIND:
3118a87d35d8SDominik Brodowski 		err = __sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
31191da177e4SLinus Torvalds 		break;
31201da177e4SLinus Torvalds 	case SYS_CONNECT:
31211387c2c2SDominik Brodowski 		err = __sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
31221da177e4SLinus Torvalds 		break;
31231da177e4SLinus Torvalds 	case SYS_LISTEN:
312425e290eeSDominik Brodowski 		err = __sys_listen(a0, a1);
31251da177e4SLinus Torvalds 		break;
31261da177e4SLinus Torvalds 	case SYS_ACCEPT:
31274541e805SDominik Brodowski 		err = __sys_accept4(a0, (struct sockaddr __user *)a1,
3128aaca0bdcSUlrich Drepper 				    (int __user *)a[2], 0);
31291da177e4SLinus Torvalds 		break;
31301da177e4SLinus Torvalds 	case SYS_GETSOCKNAME:
313189bddce5SStephen Hemminger 		err =
31328882a107SDominik Brodowski 		    __sys_getsockname(a0, (struct sockaddr __user *)a1,
313389bddce5SStephen Hemminger 				      (int __user *)a[2]);
31341da177e4SLinus Torvalds 		break;
31351da177e4SLinus Torvalds 	case SYS_GETPEERNAME:
313689bddce5SStephen Hemminger 		err =
3137b21c8f83SDominik Brodowski 		    __sys_getpeername(a0, (struct sockaddr __user *)a1,
313889bddce5SStephen Hemminger 				      (int __user *)a[2]);
31391da177e4SLinus Torvalds 		break;
31401da177e4SLinus Torvalds 	case SYS_SOCKETPAIR:
31416debc8d8SDominik Brodowski 		err = __sys_socketpair(a0, a1, a[2], (int __user *)a[3]);
31421da177e4SLinus Torvalds 		break;
31431da177e4SLinus Torvalds 	case SYS_SEND:
3144f3bf896bSDominik Brodowski 		err = __sys_sendto(a0, (void __user *)a1, a[2], a[3],
3145f3bf896bSDominik Brodowski 				   NULL, 0);
31461da177e4SLinus Torvalds 		break;
31471da177e4SLinus Torvalds 	case SYS_SENDTO:
3148211b634bSDominik Brodowski 		err = __sys_sendto(a0, (void __user *)a1, a[2], a[3],
31491da177e4SLinus Torvalds 				   (struct sockaddr __user *)a[4], a[5]);
31501da177e4SLinus Torvalds 		break;
31511da177e4SLinus Torvalds 	case SYS_RECV:
3152d27e9afcSDominik Brodowski 		err = __sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
3153d27e9afcSDominik Brodowski 				     NULL, NULL);
31541da177e4SLinus Torvalds 		break;
31551da177e4SLinus Torvalds 	case SYS_RECVFROM:
31567a09e1ebSDominik Brodowski 		err = __sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
315789bddce5SStephen Hemminger 				     (struct sockaddr __user *)a[4],
315889bddce5SStephen Hemminger 				     (int __user *)a[5]);
31591da177e4SLinus Torvalds 		break;
31601da177e4SLinus Torvalds 	case SYS_SHUTDOWN:
3161005a1aeaSDominik Brodowski 		err = __sys_shutdown(a0, a1);
31621da177e4SLinus Torvalds 		break;
31631da177e4SLinus Torvalds 	case SYS_SETSOCKOPT:
3164cc36dca0SDominik Brodowski 		err = __sys_setsockopt(a0, a1, a[2], (char __user *)a[3],
3165cc36dca0SDominik Brodowski 				       a[4]);
31661da177e4SLinus Torvalds 		break;
31671da177e4SLinus Torvalds 	case SYS_GETSOCKOPT:
316889bddce5SStephen Hemminger 		err =
316913a2d70eSDominik Brodowski 		    __sys_getsockopt(a0, a1, a[2], (char __user *)a[3],
317089bddce5SStephen Hemminger 				     (int __user *)a[4]);
31711da177e4SLinus Torvalds 		break;
31721da177e4SLinus Torvalds 	case SYS_SENDMSG:
3173e1834a32SDominik Brodowski 		err = __sys_sendmsg(a0, (struct user_msghdr __user *)a1,
3174e1834a32SDominik Brodowski 				    a[2], true);
31751da177e4SLinus Torvalds 		break;
3176228e548eSAnton Blanchard 	case SYS_SENDMMSG:
3177e1834a32SDominik Brodowski 		err = __sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2],
3178e1834a32SDominik Brodowski 				     a[3], true);
3179228e548eSAnton Blanchard 		break;
31801da177e4SLinus Torvalds 	case SYS_RECVMSG:
3181e1834a32SDominik Brodowski 		err = __sys_recvmsg(a0, (struct user_msghdr __user *)a1,
3182e1834a32SDominik Brodowski 				    a[2], true);
31831da177e4SLinus Torvalds 		break;
3184a2e27255SArnaldo Carvalho de Melo 	case SYS_RECVMMSG:
31853ca47e95SArnd Bergmann 		if (IS_ENABLED(CONFIG_64BIT))
3186e11d4284SArnd Bergmann 			err = __sys_recvmmsg(a0, (struct mmsghdr __user *)a1,
3187e11d4284SArnd Bergmann 					     a[2], a[3],
3188e11d4284SArnd Bergmann 					     (struct __kernel_timespec __user *)a[4],
3189e11d4284SArnd Bergmann 					     NULL);
3190e11d4284SArnd Bergmann 		else
3191e11d4284SArnd Bergmann 			err = __sys_recvmmsg(a0, (struct mmsghdr __user *)a1,
3192e11d4284SArnd Bergmann 					     a[2], a[3], NULL,
3193e11d4284SArnd Bergmann 					     (struct old_timespec32 __user *)a[4]);
3194a2e27255SArnaldo Carvalho de Melo 		break;
3195de11defeSUlrich Drepper 	case SYS_ACCEPT4:
31964541e805SDominik Brodowski 		err = __sys_accept4(a0, (struct sockaddr __user *)a1,
3197de11defeSUlrich Drepper 				    (int __user *)a[2], a[3]);
3198aaca0bdcSUlrich Drepper 		break;
31991da177e4SLinus Torvalds 	default:
32001da177e4SLinus Torvalds 		err = -EINVAL;
32011da177e4SLinus Torvalds 		break;
32021da177e4SLinus Torvalds 	}
32031da177e4SLinus Torvalds 	return err;
32041da177e4SLinus Torvalds }
32051da177e4SLinus Torvalds 
32061da177e4SLinus Torvalds #endif				/* __ARCH_WANT_SYS_SOCKETCALL */
32071da177e4SLinus Torvalds 
320855737fdaSStephen Hemminger /**
320955737fdaSStephen Hemminger  *	sock_register - add a socket protocol handler
321055737fdaSStephen Hemminger  *	@ops: description of protocol
321155737fdaSStephen Hemminger  *
32121da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
32131da177e4SLinus Torvalds  *	advertise its address family, and have it linked into the
3214e793c0f7SMasanari Iida  *	socket interface. The value ops->family corresponds to the
321555737fdaSStephen Hemminger  *	socket system call protocol family.
32161da177e4SLinus Torvalds  */
sock_register(const struct net_proto_family * ops)3217f0fd27d4SStephen Hemminger int sock_register(const struct net_proto_family *ops)
32181da177e4SLinus Torvalds {
32191da177e4SLinus Torvalds 	int err;
32201da177e4SLinus Torvalds 
32211da177e4SLinus Torvalds 	if (ops->family >= NPROTO) {
32223410f22eSYang Yingliang 		pr_crit("protocol %d >= NPROTO(%d)\n", ops->family, NPROTO);
32231da177e4SLinus Torvalds 		return -ENOBUFS;
32241da177e4SLinus Torvalds 	}
322555737fdaSStephen Hemminger 
322655737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
3227190683a9SEric Dumazet 	if (rcu_dereference_protected(net_families[ops->family],
3228190683a9SEric Dumazet 				      lockdep_is_held(&net_family_lock)))
32291da177e4SLinus Torvalds 		err = -EEXIST;
323055737fdaSStephen Hemminger 	else {
3231cf778b00SEric Dumazet 		rcu_assign_pointer(net_families[ops->family], ops);
32321da177e4SLinus Torvalds 		err = 0;
32331da177e4SLinus Torvalds 	}
323455737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
323555737fdaSStephen Hemminger 
3236fe0bdbdeSYejune Deng 	pr_info("NET: Registered %s protocol family\n", pf_family_names[ops->family]);
32371da177e4SLinus Torvalds 	return err;
32381da177e4SLinus Torvalds }
3239c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_register);
32401da177e4SLinus Torvalds 
324155737fdaSStephen Hemminger /**
324255737fdaSStephen Hemminger  *	sock_unregister - remove a protocol handler
324355737fdaSStephen Hemminger  *	@family: protocol family to remove
324455737fdaSStephen Hemminger  *
32451da177e4SLinus Torvalds  *	This function is called by a protocol handler that wants to
32461da177e4SLinus Torvalds  *	remove its address family, and have it unlinked from the
324755737fdaSStephen Hemminger  *	new socket creation.
324855737fdaSStephen Hemminger  *
324955737fdaSStephen Hemminger  *	If protocol handler is a module, then it can use module reference
325055737fdaSStephen Hemminger  *	counts to protect against new references. If protocol handler is not
325155737fdaSStephen Hemminger  *	a module then it needs to provide its own protection in
325255737fdaSStephen Hemminger  *	the ops->create routine.
32531da177e4SLinus Torvalds  */
sock_unregister(int family)3254f0fd27d4SStephen Hemminger void sock_unregister(int family)
32551da177e4SLinus Torvalds {
3256f0fd27d4SStephen Hemminger 	BUG_ON(family < 0 || family >= NPROTO);
32571da177e4SLinus Torvalds 
325855737fdaSStephen Hemminger 	spin_lock(&net_family_lock);
3259a9b3cd7fSStephen Hemminger 	RCU_INIT_POINTER(net_families[family], NULL);
326055737fdaSStephen Hemminger 	spin_unlock(&net_family_lock);
326155737fdaSStephen Hemminger 
326255737fdaSStephen Hemminger 	synchronize_rcu();
326355737fdaSStephen Hemminger 
3264fe0bdbdeSYejune Deng 	pr_info("NET: Unregistered %s protocol family\n", pf_family_names[family]);
32651da177e4SLinus Torvalds }
3266c6d409cfSEric Dumazet EXPORT_SYMBOL(sock_unregister);
32671da177e4SLinus Torvalds 
sock_is_registered(int family)3268bf2ae2e4SXin Long bool sock_is_registered(int family)
3269bf2ae2e4SXin Long {
327066b51b0aSJeremy Cline 	return family < NPROTO && rcu_access_pointer(net_families[family]);
3271bf2ae2e4SXin Long }
3272bf2ae2e4SXin Long 
sock_init(void)327377d76ea3SAndi Kleen static int __init sock_init(void)
32741da177e4SLinus Torvalds {
3275b3e19d92SNick Piggin 	int err;
32762ca794e5SEric W. Biederman 	/*
32772ca794e5SEric W. Biederman 	 *      Initialize the network sysctl infrastructure.
32782ca794e5SEric W. Biederman 	 */
32792ca794e5SEric W. Biederman 	err = net_sysctl_init();
32802ca794e5SEric W. Biederman 	if (err)
32812ca794e5SEric W. Biederman 		goto out;
3282b3e19d92SNick Piggin 
32831da177e4SLinus Torvalds 	/*
32841da177e4SLinus Torvalds 	 *      Initialize skbuff SLAB cache
32851da177e4SLinus Torvalds 	 */
32861da177e4SLinus Torvalds 	skb_init();
32871da177e4SLinus Torvalds 
32881da177e4SLinus Torvalds 	/*
32891da177e4SLinus Torvalds 	 *      Initialize the protocols module.
32901da177e4SLinus Torvalds 	 */
32911da177e4SLinus Torvalds 
32921da177e4SLinus Torvalds 	init_inodecache();
3293b3e19d92SNick Piggin 
3294b3e19d92SNick Piggin 	err = register_filesystem(&sock_fs_type);
3295b3e19d92SNick Piggin 	if (err)
329647260ba9SMiaohe Lin 		goto out;
32971da177e4SLinus Torvalds 	sock_mnt = kern_mount(&sock_fs_type);
3298b3e19d92SNick Piggin 	if (IS_ERR(sock_mnt)) {
3299b3e19d92SNick Piggin 		err = PTR_ERR(sock_mnt);
3300b3e19d92SNick Piggin 		goto out_mount;
3301b3e19d92SNick Piggin 	}
330277d76ea3SAndi Kleen 
330377d76ea3SAndi Kleen 	/* The real protocol initialization is performed in later initcalls.
33041da177e4SLinus Torvalds 	 */
33051da177e4SLinus Torvalds 
33061da177e4SLinus Torvalds #ifdef CONFIG_NETFILTER
33076d11cfdbSPablo Neira Ayuso 	err = netfilter_init();
33086d11cfdbSPablo Neira Ayuso 	if (err)
33096d11cfdbSPablo Neira Ayuso 		goto out;
33101da177e4SLinus Torvalds #endif
3311cbeb321aSDavid S. Miller 
3312408eccceSDaniel Borkmann 	ptp_classifier_init();
3313c1f19b51SRichard Cochran 
3314b3e19d92SNick Piggin out:
3315b3e19d92SNick Piggin 	return err;
3316b3e19d92SNick Piggin 
3317b3e19d92SNick Piggin out_mount:
3318b3e19d92SNick Piggin 	unregister_filesystem(&sock_fs_type);
3319b3e19d92SNick Piggin 	goto out;
33201da177e4SLinus Torvalds }
33211da177e4SLinus Torvalds 
332277d76ea3SAndi Kleen core_initcall(sock_init);	/* early initcall */
332377d76ea3SAndi Kleen 
33241da177e4SLinus Torvalds #ifdef CONFIG_PROC_FS
socket_seq_show(struct seq_file * seq)33251da177e4SLinus Torvalds void socket_seq_show(struct seq_file *seq)
33261da177e4SLinus Torvalds {
3327648845abSTonghao Zhang 	seq_printf(seq, "sockets: used %d\n",
3328648845abSTonghao Zhang 		   sock_inuse_get(seq->private));
33291da177e4SLinus Torvalds }
33301da177e4SLinus Torvalds #endif				/* CONFIG_PROC_FS */
33311da177e4SLinus Torvalds 
333229c49648SArnd Bergmann /* Handle the fact that while struct ifreq has the same *layout* on
333329c49648SArnd Bergmann  * 32/64 for everything but ifreq::ifru_ifmap and ifreq::ifru_data,
333429c49648SArnd Bergmann  * which are handled elsewhere, it still has different *size* due to
333529c49648SArnd Bergmann  * ifreq::ifru_ifmap (which is 16 bytes on 32 bit, 24 bytes on 64-bit,
333629c49648SArnd Bergmann  * resulting in struct ifreq being 32 and 40 bytes respectively).
333729c49648SArnd Bergmann  * As a result, if the struct happens to be at the end of a page and
333829c49648SArnd Bergmann  * the next page isn't readable/writable, we get a fault. To prevent
333929c49648SArnd Bergmann  * that, copy back and forth to the full size.
334029c49648SArnd Bergmann  */
get_user_ifreq(struct ifreq * ifr,void __user ** ifrdata,void __user * arg)334129c49648SArnd Bergmann int get_user_ifreq(struct ifreq *ifr, void __user **ifrdata, void __user *arg)
334229c49648SArnd Bergmann {
334329c49648SArnd Bergmann 	if (in_compat_syscall()) {
334429c49648SArnd Bergmann 		struct compat_ifreq *ifr32 = (struct compat_ifreq *)ifr;
334529c49648SArnd Bergmann 
334629c49648SArnd Bergmann 		memset(ifr, 0, sizeof(*ifr));
334729c49648SArnd Bergmann 		if (copy_from_user(ifr32, arg, sizeof(*ifr32)))
334829c49648SArnd Bergmann 			return -EFAULT;
334929c49648SArnd Bergmann 
335029c49648SArnd Bergmann 		if (ifrdata)
335129c49648SArnd Bergmann 			*ifrdata = compat_ptr(ifr32->ifr_data);
335229c49648SArnd Bergmann 
335329c49648SArnd Bergmann 		return 0;
335429c49648SArnd Bergmann 	}
335529c49648SArnd Bergmann 
335629c49648SArnd Bergmann 	if (copy_from_user(ifr, arg, sizeof(*ifr)))
335729c49648SArnd Bergmann 		return -EFAULT;
335829c49648SArnd Bergmann 
335929c49648SArnd Bergmann 	if (ifrdata)
336029c49648SArnd Bergmann 		*ifrdata = ifr->ifr_data;
336129c49648SArnd Bergmann 
336229c49648SArnd Bergmann 	return 0;
336329c49648SArnd Bergmann }
336429c49648SArnd Bergmann EXPORT_SYMBOL(get_user_ifreq);
336529c49648SArnd Bergmann 
put_user_ifreq(struct ifreq * ifr,void __user * arg)336629c49648SArnd Bergmann int put_user_ifreq(struct ifreq *ifr, void __user *arg)
336729c49648SArnd Bergmann {
336829c49648SArnd Bergmann 	size_t size = sizeof(*ifr);
336929c49648SArnd Bergmann 
337029c49648SArnd Bergmann 	if (in_compat_syscall())
337129c49648SArnd Bergmann 		size = sizeof(struct compat_ifreq);
337229c49648SArnd Bergmann 
337329c49648SArnd Bergmann 	if (copy_to_user(arg, ifr, size))
337429c49648SArnd Bergmann 		return -EFAULT;
337529c49648SArnd Bergmann 
337629c49648SArnd Bergmann 	return 0;
337729c49648SArnd Bergmann }
337829c49648SArnd Bergmann EXPORT_SYMBOL(put_user_ifreq);
337929c49648SArnd Bergmann 
338089bbfc95SShaun Pereira #ifdef CONFIG_COMPAT
compat_siocwandev(struct net * net,struct compat_ifreq __user * uifr32)33817a50a240SArnd Bergmann static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32)
33827a50a240SArnd Bergmann {
33837a50a240SArnd Bergmann 	compat_uptr_t uptr32;
338444c02a2cSAl Viro 	struct ifreq ifr;
338544c02a2cSAl Viro 	void __user *saved;
338644c02a2cSAl Viro 	int err;
33877a50a240SArnd Bergmann 
338829c49648SArnd Bergmann 	if (get_user_ifreq(&ifr, NULL, uifr32))
33897a50a240SArnd Bergmann 		return -EFAULT;
33907a50a240SArnd Bergmann 
33917a50a240SArnd Bergmann 	if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu))
33927a50a240SArnd Bergmann 		return -EFAULT;
33937a50a240SArnd Bergmann 
339444c02a2cSAl Viro 	saved = ifr.ifr_settings.ifs_ifsu.raw_hdlc;
339544c02a2cSAl Viro 	ifr.ifr_settings.ifs_ifsu.raw_hdlc = compat_ptr(uptr32);
33967a50a240SArnd Bergmann 
3397a554bf96SArnd Bergmann 	err = dev_ioctl(net, SIOCWANDEV, &ifr, NULL, NULL);
339844c02a2cSAl Viro 	if (!err) {
339944c02a2cSAl Viro 		ifr.ifr_settings.ifs_ifsu.raw_hdlc = saved;
340029c49648SArnd Bergmann 		if (put_user_ifreq(&ifr, uifr32))
340144c02a2cSAl Viro 			err = -EFAULT;
34027a50a240SArnd Bergmann 	}
34037a229387SArnd Bergmann 	return err;
34047a229387SArnd Bergmann }
34057a229387SArnd Bergmann 
3406590d4693SBen 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)3407590d4693SBen Hutchings static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd,
34086b96018bSArnd Bergmann 				 struct compat_ifreq __user *u_ifreq32)
34097a229387SArnd Bergmann {
341044c02a2cSAl Viro 	struct ifreq ifreq;
3411a554bf96SArnd Bergmann 	void __user *data;
34127a229387SArnd Bergmann 
3413d0efb162SPeter Collingbourne 	if (!is_socket_ioctl_cmd(cmd))
3414d0efb162SPeter Collingbourne 		return -ENOTTY;
3415a554bf96SArnd Bergmann 	if (get_user_ifreq(&ifreq, &data, u_ifreq32))
34167a229387SArnd Bergmann 		return -EFAULT;
3417a554bf96SArnd Bergmann 	ifreq.ifr_data = data;
34187a229387SArnd Bergmann 
3419a554bf96SArnd Bergmann 	return dev_ioctl(net, cmd, &ifreq, data, NULL);
34207a229387SArnd Bergmann }
34217a229387SArnd Bergmann 
compat_sock_ioctl_trans(struct file * file,struct socket * sock,unsigned int cmd,unsigned long arg)34226b96018bSArnd Bergmann static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
34236b96018bSArnd Bergmann 			 unsigned int cmd, unsigned long arg)
34246b96018bSArnd Bergmann {
34256b96018bSArnd Bergmann 	void __user *argp = compat_ptr(arg);
34266b96018bSArnd Bergmann 	struct sock *sk = sock->sk;
34276b96018bSArnd Bergmann 	struct net *net = sock_net(sk);
34281ded5e5aSEric Dumazet 	const struct proto_ops *ops;
34297a229387SArnd Bergmann 
34306b96018bSArnd Bergmann 	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
343188fc023fSArnd Bergmann 		return sock_ioctl(file, cmd, (unsigned long)argp);
34327a229387SArnd Bergmann 
34336b96018bSArnd Bergmann 	switch (cmd) {
34347a50a240SArnd Bergmann 	case SIOCWANDEV:
34357a50a240SArnd Bergmann 		return compat_siocwandev(net, argp);
34360768e170SArnd Bergmann 	case SIOCGSTAMP_OLD:
34370768e170SArnd Bergmann 	case SIOCGSTAMPNS_OLD:
34381ded5e5aSEric Dumazet 		ops = READ_ONCE(sock->ops);
34391ded5e5aSEric Dumazet 		if (!ops->gettstamp)
3440c7cbdbf2SArnd Bergmann 			return -ENOIOCTLCMD;
34411ded5e5aSEric Dumazet 		return ops->gettstamp(sock, argp, cmd == SIOCGSTAMP_OLD,
3442c7cbdbf2SArnd Bergmann 				      !COMPAT_USE_64BIT_TIME);
3443c7cbdbf2SArnd Bergmann 
3444dd98d289SArnd Bergmann 	case SIOCETHTOOL:
3445590d4693SBen Hutchings 	case SIOCBONDSLAVEINFOQUERY:
3446590d4693SBen Hutchings 	case SIOCBONDINFOQUERY:
3447a2116ed2SArnd Bergmann 	case SIOCSHWTSTAMP:
3448fd468c74SBen Hutchings 	case SIOCGHWTSTAMP:
3449590d4693SBen Hutchings 		return compat_ifr_data_ioctl(net, cmd, argp);
34507a229387SArnd Bergmann 
34516b96018bSArnd Bergmann 	case FIOSETOWN:
34526b96018bSArnd Bergmann 	case SIOCSPGRP:
34536b96018bSArnd Bergmann 	case FIOGETOWN:
34546b96018bSArnd Bergmann 	case SIOCGPGRP:
34556b96018bSArnd Bergmann 	case SIOCBRADDBR:
34566b96018bSArnd Bergmann 	case SIOCBRDELBR:
34576b96018bSArnd Bergmann 	case SIOCGIFVLAN:
34586b96018bSArnd Bergmann 	case SIOCSIFVLAN:
3459c62cce2cSAndrey Vagin 	case SIOCGSKNS:
34600768e170SArnd Bergmann 	case SIOCGSTAMP_NEW:
34610768e170SArnd Bergmann 	case SIOCGSTAMPNS_NEW:
3462876f0bf9SArnd Bergmann 	case SIOCGIFCONF:
3463fd3a4590SRemi Pommarel 	case SIOCSIFBR:
3464fd3a4590SRemi Pommarel 	case SIOCGIFBR:
34656b96018bSArnd Bergmann 		return sock_ioctl(file, cmd, arg);
34666b96018bSArnd Bergmann 
34676b96018bSArnd Bergmann 	case SIOCGIFFLAGS:
34686b96018bSArnd Bergmann 	case SIOCSIFFLAGS:
3469709566d7SArnd Bergmann 	case SIOCGIFMAP:
3470709566d7SArnd Bergmann 	case SIOCSIFMAP:
34716b96018bSArnd Bergmann 	case SIOCGIFMETRIC:
34726b96018bSArnd Bergmann 	case SIOCSIFMETRIC:
34736b96018bSArnd Bergmann 	case SIOCGIFMTU:
34746b96018bSArnd Bergmann 	case SIOCSIFMTU:
34756b96018bSArnd Bergmann 	case SIOCGIFMEM:
34766b96018bSArnd Bergmann 	case SIOCSIFMEM:
34776b96018bSArnd Bergmann 	case SIOCGIFHWADDR:
34786b96018bSArnd Bergmann 	case SIOCSIFHWADDR:
34796b96018bSArnd Bergmann 	case SIOCADDMULTI:
34806b96018bSArnd Bergmann 	case SIOCDELMULTI:
34816b96018bSArnd Bergmann 	case SIOCGIFINDEX:
34826b96018bSArnd Bergmann 	case SIOCGIFADDR:
34836b96018bSArnd Bergmann 	case SIOCSIFADDR:
34846b96018bSArnd Bergmann 	case SIOCSIFHWBROADCAST:
34856b96018bSArnd Bergmann 	case SIOCDIFADDR:
34866b96018bSArnd Bergmann 	case SIOCGIFBRDADDR:
34876b96018bSArnd Bergmann 	case SIOCSIFBRDADDR:
34886b96018bSArnd Bergmann 	case SIOCGIFDSTADDR:
34896b96018bSArnd Bergmann 	case SIOCSIFDSTADDR:
34906b96018bSArnd Bergmann 	case SIOCGIFNETMASK:
34916b96018bSArnd Bergmann 	case SIOCSIFNETMASK:
34926b96018bSArnd Bergmann 	case SIOCSIFPFLAGS:
34936b96018bSArnd Bergmann 	case SIOCGIFPFLAGS:
34946b96018bSArnd Bergmann 	case SIOCGIFTXQLEN:
34956b96018bSArnd Bergmann 	case SIOCSIFTXQLEN:
34966b96018bSArnd Bergmann 	case SIOCBRADDIF:
34976b96018bSArnd Bergmann 	case SIOCBRDELIF:
3498c6c9fee3SJohannes Berg 	case SIOCGIFNAME:
34999177efd3SArnd Bergmann 	case SIOCSIFNAME:
35009177efd3SArnd Bergmann 	case SIOCGMIIPHY:
35019177efd3SArnd Bergmann 	case SIOCGMIIREG:
35029177efd3SArnd Bergmann 	case SIOCSMIIREG:
3503f92d4fc9SAl Viro 	case SIOCBONDENSLAVE:
3504f92d4fc9SAl Viro 	case SIOCBONDRELEASE:
3505f92d4fc9SAl Viro 	case SIOCBONDSETHWADDR:
3506f92d4fc9SAl Viro 	case SIOCBONDCHANGEACTIVE:
35076b96018bSArnd Bergmann 	case SIOCSARP:
35086b96018bSArnd Bergmann 	case SIOCGARP:
35096b96018bSArnd Bergmann 	case SIOCDARP:
3510c7dc504eSArnd Bergmann 	case SIOCOUTQ:
35119d7bf41fSArnd Bergmann 	case SIOCOUTQNSD:
35126b96018bSArnd Bergmann 	case SIOCATMARK:
351363ff03abSJohannes Berg 		return sock_do_ioctl(net, sock, cmd, arg);
35149177efd3SArnd Bergmann 	}
35159177efd3SArnd Bergmann 
35166b96018bSArnd Bergmann 	return -ENOIOCTLCMD;
35176b96018bSArnd Bergmann }
35187a229387SArnd Bergmann 
compat_sock_ioctl(struct file * file,unsigned int cmd,unsigned long arg)351995c96174SEric Dumazet static long compat_sock_ioctl(struct file *file, unsigned int cmd,
352089bbfc95SShaun Pereira 			      unsigned long arg)
352189bbfc95SShaun Pereira {
352289bbfc95SShaun Pereira 	struct socket *sock = file->private_data;
35231ded5e5aSEric Dumazet 	const struct proto_ops *ops = READ_ONCE(sock->ops);
352489bbfc95SShaun Pereira 	int ret = -ENOIOCTLCMD;
352587de87d5SDavid S. Miller 	struct sock *sk;
352687de87d5SDavid S. Miller 	struct net *net;
352787de87d5SDavid S. Miller 
352887de87d5SDavid S. Miller 	sk = sock->sk;
352987de87d5SDavid S. Miller 	net = sock_net(sk);
353089bbfc95SShaun Pereira 
35311ded5e5aSEric Dumazet 	if (ops->compat_ioctl)
35321ded5e5aSEric Dumazet 		ret = ops->compat_ioctl(sock, cmd, arg);
353389bbfc95SShaun Pereira 
353487de87d5SDavid S. Miller 	if (ret == -ENOIOCTLCMD &&
353587de87d5SDavid S. Miller 	    (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST))
353687de87d5SDavid S. Miller 		ret = compat_wext_handle_ioctl(net, cmd, arg);
353787de87d5SDavid S. Miller 
35386b96018bSArnd Bergmann 	if (ret == -ENOIOCTLCMD)
35396b96018bSArnd Bergmann 		ret = compat_sock_ioctl_trans(file, sock, cmd, arg);
35406b96018bSArnd Bergmann 
354189bbfc95SShaun Pereira 	return ret;
354289bbfc95SShaun Pereira }
354389bbfc95SShaun Pereira #endif
354489bbfc95SShaun Pereira 
35458a3c245cSPedro Tammela /**
35468a3c245cSPedro Tammela  *	kernel_bind - bind an address to a socket (kernel space)
35478a3c245cSPedro Tammela  *	@sock: socket
35488a3c245cSPedro Tammela  *	@addr: address
35498a3c245cSPedro Tammela  *	@addrlen: length of address
35508a3c245cSPedro Tammela  *
35518a3c245cSPedro Tammela  *	Returns 0 or an error.
35528a3c245cSPedro Tammela  */
35538a3c245cSPedro Tammela 
kernel_bind(struct socket * sock,struct sockaddr * addr,int addrlen)3554ac5a488eSSridhar Samudrala int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
3555ac5a488eSSridhar Samudrala {
3556c889a99aSJordan Rife 	struct sockaddr_storage address;
3557c889a99aSJordan Rife 
3558c889a99aSJordan Rife 	memcpy(&address, addr, addrlen);
3559c889a99aSJordan Rife 
3560c889a99aSJordan Rife 	return READ_ONCE(sock->ops)->bind(sock, (struct sockaddr *)&address,
3561c889a99aSJordan Rife 					  addrlen);
3562ac5a488eSSridhar Samudrala }
3563c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_bind);
3564ac5a488eSSridhar Samudrala 
35658a3c245cSPedro Tammela /**
35668a3c245cSPedro Tammela  *	kernel_listen - move socket to listening state (kernel space)
35678a3c245cSPedro Tammela  *	@sock: socket
35688a3c245cSPedro Tammela  *	@backlog: pending connections queue size
35698a3c245cSPedro Tammela  *
35708a3c245cSPedro Tammela  *	Returns 0 or an error.
35718a3c245cSPedro Tammela  */
35728a3c245cSPedro Tammela 
kernel_listen(struct socket * sock,int backlog)3573ac5a488eSSridhar Samudrala int kernel_listen(struct socket *sock, int backlog)
3574ac5a488eSSridhar Samudrala {
35751ded5e5aSEric Dumazet 	return READ_ONCE(sock->ops)->listen(sock, backlog);
3576ac5a488eSSridhar Samudrala }
3577c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_listen);
3578ac5a488eSSridhar Samudrala 
35798a3c245cSPedro Tammela /**
35808a3c245cSPedro Tammela  *	kernel_accept - accept a connection (kernel space)
35818a3c245cSPedro Tammela  *	@sock: listening socket
35828a3c245cSPedro Tammela  *	@newsock: new connected socket
35838a3c245cSPedro Tammela  *	@flags: flags
35848a3c245cSPedro Tammela  *
35858a3c245cSPedro Tammela  *	@flags must be SOCK_CLOEXEC, SOCK_NONBLOCK or 0.
35868a3c245cSPedro Tammela  *	If it fails, @newsock is guaranteed to be %NULL.
35878a3c245cSPedro Tammela  *	Returns 0 or an error.
35888a3c245cSPedro Tammela  */
35898a3c245cSPedro Tammela 
kernel_accept(struct socket * sock,struct socket ** newsock,int flags)3590ac5a488eSSridhar Samudrala int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
3591ac5a488eSSridhar Samudrala {
3592ac5a488eSSridhar Samudrala 	struct sock *sk = sock->sk;
35931ded5e5aSEric Dumazet 	const struct proto_ops *ops = READ_ONCE(sock->ops);
3594ac5a488eSSridhar Samudrala 	int err;
3595ac5a488eSSridhar Samudrala 
3596ac5a488eSSridhar Samudrala 	err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
3597ac5a488eSSridhar Samudrala 			       newsock);
3598ac5a488eSSridhar Samudrala 	if (err < 0)
3599ac5a488eSSridhar Samudrala 		goto done;
3600ac5a488eSSridhar Samudrala 
36011ded5e5aSEric Dumazet 	err = ops->accept(sock, *newsock, flags, true);
3602ac5a488eSSridhar Samudrala 	if (err < 0) {
3603ac5a488eSSridhar Samudrala 		sock_release(*newsock);
3604fa8705b0STony Battersby 		*newsock = NULL;
3605ac5a488eSSridhar Samudrala 		goto done;
3606ac5a488eSSridhar Samudrala 	}
3607ac5a488eSSridhar Samudrala 
36081ded5e5aSEric Dumazet 	(*newsock)->ops = ops;
36091ded5e5aSEric Dumazet 	__module_get(ops->owner);
3610ac5a488eSSridhar Samudrala 
3611ac5a488eSSridhar Samudrala done:
3612ac5a488eSSridhar Samudrala 	return err;
3613ac5a488eSSridhar Samudrala }
3614c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_accept);
3615ac5a488eSSridhar Samudrala 
36168a3c245cSPedro Tammela /**
36178a3c245cSPedro Tammela  *	kernel_connect - connect a socket (kernel space)
36188a3c245cSPedro Tammela  *	@sock: socket
36198a3c245cSPedro Tammela  *	@addr: address
36208a3c245cSPedro Tammela  *	@addrlen: address length
36218a3c245cSPedro Tammela  *	@flags: flags (O_NONBLOCK, ...)
36228a3c245cSPedro Tammela  *
3623f1dcffccSLu Wei  *	For datagram sockets, @addr is the address to which datagrams are sent
36248a3c245cSPedro Tammela  *	by default, and the only address from which datagrams are received.
36258a3c245cSPedro Tammela  *	For stream sockets, attempts to connect to @addr.
36268a3c245cSPedro Tammela  *	Returns 0 or an error code.
36278a3c245cSPedro Tammela  */
36288a3c245cSPedro Tammela 
kernel_connect(struct socket * sock,struct sockaddr * addr,int addrlen,int flags)3629ac5a488eSSridhar Samudrala int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
3630ac5a488eSSridhar Samudrala 		   int flags)
3631ac5a488eSSridhar Samudrala {
36320bdf3993SJordan Rife 	struct sockaddr_storage address;
36330bdf3993SJordan Rife 
36340bdf3993SJordan Rife 	memcpy(&address, addr, addrlen);
36350bdf3993SJordan Rife 
36360bdf3993SJordan Rife 	return READ_ONCE(sock->ops)->connect(sock, (struct sockaddr *)&address,
36370bdf3993SJordan Rife 					     addrlen, flags);
3638ac5a488eSSridhar Samudrala }
3639c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_connect);
3640ac5a488eSSridhar Samudrala 
36418a3c245cSPedro Tammela /**
36428a3c245cSPedro Tammela  *	kernel_getsockname - get the address which the socket is bound (kernel space)
36438a3c245cSPedro Tammela  *	@sock: socket
36448a3c245cSPedro Tammela  *	@addr: address holder
36458a3c245cSPedro Tammela  *
36468a3c245cSPedro Tammela  * 	Fills the @addr pointer with the address which the socket is bound.
36470fc95decSAlex Maydanik  *	Returns the length of the address in bytes or an error code.
36488a3c245cSPedro Tammela  */
36498a3c245cSPedro Tammela 
kernel_getsockname(struct socket * sock,struct sockaddr * addr)36509b2c45d4SDenys Vlasenko int kernel_getsockname(struct socket *sock, struct sockaddr *addr)
3651ac5a488eSSridhar Samudrala {
36521ded5e5aSEric Dumazet 	return READ_ONCE(sock->ops)->getname(sock, addr, 0);
3653ac5a488eSSridhar Samudrala }
3654c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getsockname);
3655ac5a488eSSridhar Samudrala 
36568a3c245cSPedro Tammela /**
3657645f0897SMiaohe Lin  *	kernel_getpeername - get the address which the socket is connected (kernel space)
36588a3c245cSPedro Tammela  *	@sock: socket
36598a3c245cSPedro Tammela  *	@addr: address holder
36608a3c245cSPedro Tammela  *
36618a3c245cSPedro Tammela  * 	Fills the @addr pointer with the address which the socket is connected.
36620fc95decSAlex Maydanik  *	Returns the length of the address in bytes or an error code.
36638a3c245cSPedro Tammela  */
36648a3c245cSPedro Tammela 
kernel_getpeername(struct socket * sock,struct sockaddr * addr)36659b2c45d4SDenys Vlasenko int kernel_getpeername(struct socket *sock, struct sockaddr *addr)
3666ac5a488eSSridhar Samudrala {
36671ded5e5aSEric Dumazet 	return READ_ONCE(sock->ops)->getname(sock, addr, 1);
3668ac5a488eSSridhar Samudrala }
3669c6d409cfSEric Dumazet EXPORT_SYMBOL(kernel_getpeername);
3670ac5a488eSSridhar Samudrala 
36718a3c245cSPedro Tammela /**
3672645f0897SMiaohe Lin  *	kernel_sock_shutdown - shut down part of a full-duplex connection (kernel space)
36738a3c245cSPedro Tammela  *	@sock: socket
36748a3c245cSPedro Tammela  *	@how: connection part
36758a3c245cSPedro Tammela  *
36768a3c245cSPedro Tammela  *	Returns 0 or an error.
36778a3c245cSPedro Tammela  */
36788a3c245cSPedro Tammela 
kernel_sock_shutdown(struct socket * sock,enum sock_shutdown_cmd how)367991cf45f0STrond Myklebust int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
368091cf45f0STrond Myklebust {
36811ded5e5aSEric Dumazet 	return READ_ONCE(sock->ops)->shutdown(sock, how);
368291cf45f0STrond Myklebust }
368391cf45f0STrond Myklebust EXPORT_SYMBOL(kernel_sock_shutdown);
3684113c3075SR. Parameswaran 
36858a3c245cSPedro Tammela /**
36868a3c245cSPedro Tammela  *	kernel_sock_ip_overhead - returns the IP overhead imposed by a socket
36878a3c245cSPedro Tammela  *	@sk: socket
36888a3c245cSPedro Tammela  *
36898a3c245cSPedro Tammela  *	This routine returns the IP overhead imposed by a socket i.e.
3690113c3075SR. Parameswaran  *	the length of the underlying IP header, depending on whether
3691113c3075SR. Parameswaran  *	this is an IPv4 or IPv6 socket and the length from IP options turned
369257240d00SR. Parameswaran  *	on at the socket. Assumes that the caller has a lock on the socket.
3693113c3075SR. Parameswaran  */
36948a3c245cSPedro Tammela 
kernel_sock_ip_overhead(struct sock * sk)3695113c3075SR. Parameswaran u32 kernel_sock_ip_overhead(struct sock *sk)
3696113c3075SR. Parameswaran {
3697113c3075SR. Parameswaran 	struct inet_sock *inet;
3698113c3075SR. Parameswaran 	struct ip_options_rcu *opt;
3699113c3075SR. Parameswaran 	u32 overhead = 0;
3700113c3075SR. Parameswaran #if IS_ENABLED(CONFIG_IPV6)
3701113c3075SR. Parameswaran 	struct ipv6_pinfo *np;
3702113c3075SR. Parameswaran 	struct ipv6_txoptions *optv6 = NULL;
3703113c3075SR. Parameswaran #endif /* IS_ENABLED(CONFIG_IPV6) */
3704113c3075SR. Parameswaran 
3705113c3075SR. Parameswaran 	if (!sk)
3706113c3075SR. Parameswaran 		return overhead;
3707113c3075SR. Parameswaran 
3708113c3075SR. Parameswaran 	switch (sk->sk_family) {
3709113c3075SR. Parameswaran 	case AF_INET:
3710113c3075SR. Parameswaran 		inet = inet_sk(sk);
3711113c3075SR. Parameswaran 		overhead += sizeof(struct iphdr);
3712113c3075SR. Parameswaran 		opt = rcu_dereference_protected(inet->inet_opt,
3713614d79c0Sstephen hemminger 						sock_owned_by_user(sk));
3714113c3075SR. Parameswaran 		if (opt)
3715113c3075SR. Parameswaran 			overhead += opt->opt.optlen;
3716113c3075SR. Parameswaran 		return overhead;
3717113c3075SR. Parameswaran #if IS_ENABLED(CONFIG_IPV6)
3718113c3075SR. Parameswaran 	case AF_INET6:
3719113c3075SR. Parameswaran 		np = inet6_sk(sk);
3720113c3075SR. Parameswaran 		overhead += sizeof(struct ipv6hdr);
3721113c3075SR. Parameswaran 		if (np)
3722113c3075SR. Parameswaran 			optv6 = rcu_dereference_protected(np->opt,
3723614d79c0Sstephen hemminger 							  sock_owned_by_user(sk));
3724113c3075SR. Parameswaran 		if (optv6)
3725113c3075SR. Parameswaran 			overhead += (optv6->opt_flen + optv6->opt_nflen);
3726113c3075SR. Parameswaran 		return overhead;
3727113c3075SR. Parameswaran #endif /* IS_ENABLED(CONFIG_IPV6) */
3728113c3075SR. Parameswaran 	default: /* Returns 0 overhead if the socket is not ipv4 or ipv6 */
3729113c3075SR. Parameswaran 		return overhead;
3730113c3075SR. Parameswaran 	}
3731113c3075SR. Parameswaran }
3732113c3075SR. Parameswaran EXPORT_SYMBOL(kernel_sock_ip_overhead);
3733