18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * NET		An implementation of the SOCKET network access protocol.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Version:	@(#)socket.c	1.1.93	18/02/95
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Authors:	Orest Zborowski, <obz@Kodak.COM>
88c2ecf20Sopenharmony_ci *		Ross Biro
98c2ecf20Sopenharmony_ci *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci * Fixes:
128c2ecf20Sopenharmony_ci *		Anonymous	:	NOTSOCK/BADF cleanup. Error fix in
138c2ecf20Sopenharmony_ci *					shutdown()
148c2ecf20Sopenharmony_ci *		Alan Cox	:	verify_area() fixes
158c2ecf20Sopenharmony_ci *		Alan Cox	:	Removed DDI
168c2ecf20Sopenharmony_ci *		Jonathan Kamens	:	SOCK_DGRAM reconnect bug
178c2ecf20Sopenharmony_ci *		Alan Cox	:	Moved a load of checks to the very
188c2ecf20Sopenharmony_ci *					top level.
198c2ecf20Sopenharmony_ci *		Alan Cox	:	Move address structures to/from user
208c2ecf20Sopenharmony_ci *					mode above the protocol layers.
218c2ecf20Sopenharmony_ci *		Rob Janssen	:	Allow 0 length sends.
228c2ecf20Sopenharmony_ci *		Alan Cox	:	Asynchronous I/O support (cribbed from the
238c2ecf20Sopenharmony_ci *					tty drivers).
248c2ecf20Sopenharmony_ci *		Niibe Yutaka	:	Asynchronous I/O for writes (4.4BSD style)
258c2ecf20Sopenharmony_ci *		Jeff Uphoff	:	Made max number of sockets command-line
268c2ecf20Sopenharmony_ci *					configurable.
278c2ecf20Sopenharmony_ci *		Matti Aarnio	:	Made the number of sockets dynamic,
288c2ecf20Sopenharmony_ci *					to be allocated when needed, and mr.
298c2ecf20Sopenharmony_ci *					Uphoff's max is used as max to be
308c2ecf20Sopenharmony_ci *					allowed to allocate.
318c2ecf20Sopenharmony_ci *		Linus		:	Argh. removed all the socket allocation
328c2ecf20Sopenharmony_ci *					altogether: it's in the inode now.
338c2ecf20Sopenharmony_ci *		Alan Cox	:	Made sock_alloc()/sock_release() public
348c2ecf20Sopenharmony_ci *					for NetROM and future kernel nfsd type
358c2ecf20Sopenharmony_ci *					stuff.
368c2ecf20Sopenharmony_ci *		Alan Cox	:	sendmsg/recvmsg basics.
378c2ecf20Sopenharmony_ci *		Tom Dyas	:	Export net symbols.
388c2ecf20Sopenharmony_ci *		Marcin Dalecki	:	Fixed problems with CONFIG_NET="n".
398c2ecf20Sopenharmony_ci *		Alan Cox	:	Added thread locking to sys_* calls
408c2ecf20Sopenharmony_ci *					for sockets. May have errors at the
418c2ecf20Sopenharmony_ci *					moment.
428c2ecf20Sopenharmony_ci *		Kevin Buhr	:	Fixed the dumb errors in the above.
438c2ecf20Sopenharmony_ci *		Andi Kleen	:	Some small cleanups, optimizations,
448c2ecf20Sopenharmony_ci *					and fixed a copy_from_user() bug.
458c2ecf20Sopenharmony_ci *		Tigran Aivazian	:	sys_send(args) calls sys_sendto(args, NULL, 0)
468c2ecf20Sopenharmony_ci *		Tigran Aivazian	:	Made listen(2) backlog sanity checks
478c2ecf20Sopenharmony_ci *					protocol-independent
488c2ecf20Sopenharmony_ci *
498c2ecf20Sopenharmony_ci *	This module is effectively the top level interface to the BSD socket
508c2ecf20Sopenharmony_ci *	paradigm.
518c2ecf20Sopenharmony_ci *
528c2ecf20Sopenharmony_ci *	Based upon Swansea University Computer Society NET3.039
538c2ecf20Sopenharmony_ci */
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci#include <linux/mm.h>
568c2ecf20Sopenharmony_ci#include <linux/socket.h>
578c2ecf20Sopenharmony_ci#include <linux/file.h>
588c2ecf20Sopenharmony_ci#include <linux/net.h>
598c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
608c2ecf20Sopenharmony_ci#include <linux/thread_info.h>
618c2ecf20Sopenharmony_ci#include <linux/rcupdate.h>
628c2ecf20Sopenharmony_ci#include <linux/netdevice.h>
638c2ecf20Sopenharmony_ci#include <linux/proc_fs.h>
648c2ecf20Sopenharmony_ci#include <linux/seq_file.h>
658c2ecf20Sopenharmony_ci#include <linux/mutex.h>
668c2ecf20Sopenharmony_ci#include <linux/if_bridge.h>
678c2ecf20Sopenharmony_ci#include <linux/if_frad.h>
688c2ecf20Sopenharmony_ci#include <linux/if_vlan.h>
698c2ecf20Sopenharmony_ci#include <linux/ptp_classify.h>
708c2ecf20Sopenharmony_ci#include <linux/init.h>
718c2ecf20Sopenharmony_ci#include <linux/poll.h>
728c2ecf20Sopenharmony_ci#include <linux/cache.h>
738c2ecf20Sopenharmony_ci#include <linux/module.h>
748c2ecf20Sopenharmony_ci#include <linux/highmem.h>
758c2ecf20Sopenharmony_ci#include <linux/mount.h>
768c2ecf20Sopenharmony_ci#include <linux/pseudo_fs.h>
778c2ecf20Sopenharmony_ci#include <linux/security.h>
788c2ecf20Sopenharmony_ci#include <linux/syscalls.h>
798c2ecf20Sopenharmony_ci#include <linux/compat.h>
808c2ecf20Sopenharmony_ci#include <linux/kmod.h>
818c2ecf20Sopenharmony_ci#include <linux/audit.h>
828c2ecf20Sopenharmony_ci#include <linux/wireless.h>
838c2ecf20Sopenharmony_ci#include <linux/nsproxy.h>
848c2ecf20Sopenharmony_ci#include <linux/magic.h>
858c2ecf20Sopenharmony_ci#include <linux/slab.h>
868c2ecf20Sopenharmony_ci#include <linux/xattr.h>
878c2ecf20Sopenharmony_ci#include <linux/nospec.h>
888c2ecf20Sopenharmony_ci#include <linux/indirect_call_wrapper.h>
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci#include <linux/uaccess.h>
918c2ecf20Sopenharmony_ci#include <asm/unistd.h>
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci#include <net/compat.h>
948c2ecf20Sopenharmony_ci#include <net/wext.h>
958c2ecf20Sopenharmony_ci#include <net/cls_cgroup.h>
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci#include <net/sock.h>
988c2ecf20Sopenharmony_ci#include <linux/netfilter.h>
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci#include <linux/if_tun.h>
1018c2ecf20Sopenharmony_ci#include <linux/ipv6_route.h>
1028c2ecf20Sopenharmony_ci#include <linux/route.h>
1038c2ecf20Sopenharmony_ci#include <linux/termios.h>
1048c2ecf20Sopenharmony_ci#include <linux/sockios.h>
1058c2ecf20Sopenharmony_ci#include <net/busy_poll.h>
1068c2ecf20Sopenharmony_ci#include <linux/errqueue.h>
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci#ifdef CONFIG_NET_RX_BUSY_POLL
1098c2ecf20Sopenharmony_ciunsigned int sysctl_net_busy_read __read_mostly;
1108c2ecf20Sopenharmony_ciunsigned int sysctl_net_busy_poll __read_mostly;
1118c2ecf20Sopenharmony_ci#endif
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_cistatic ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to);
1148c2ecf20Sopenharmony_cistatic ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from);
1158c2ecf20Sopenharmony_cistatic int sock_mmap(struct file *file, struct vm_area_struct *vma);
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_cistatic int sock_close(struct inode *inode, struct file *file);
1188c2ecf20Sopenharmony_cistatic __poll_t sock_poll(struct file *file,
1198c2ecf20Sopenharmony_ci			      struct poll_table_struct *wait);
1208c2ecf20Sopenharmony_cistatic long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
1218c2ecf20Sopenharmony_ci#ifdef CONFIG_COMPAT
1228c2ecf20Sopenharmony_cistatic long compat_sock_ioctl(struct file *file,
1238c2ecf20Sopenharmony_ci			      unsigned int cmd, unsigned long arg);
1248c2ecf20Sopenharmony_ci#endif
1258c2ecf20Sopenharmony_cistatic int sock_fasync(int fd, struct file *filp, int on);
1268c2ecf20Sopenharmony_cistatic ssize_t sock_sendpage(struct file *file, struct page *page,
1278c2ecf20Sopenharmony_ci			     int offset, size_t size, loff_t *ppos, int more);
1288c2ecf20Sopenharmony_cistatic ssize_t sock_splice_read(struct file *file, loff_t *ppos,
1298c2ecf20Sopenharmony_ci				struct pipe_inode_info *pipe, size_t len,
1308c2ecf20Sopenharmony_ci				unsigned int flags);
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci#ifdef CONFIG_PROC_FS
1338c2ecf20Sopenharmony_cistatic void sock_show_fdinfo(struct seq_file *m, struct file *f)
1348c2ecf20Sopenharmony_ci{
1358c2ecf20Sopenharmony_ci	struct socket *sock = f->private_data;
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	if (sock->ops->show_fdinfo)
1388c2ecf20Sopenharmony_ci		sock->ops->show_fdinfo(m, sock);
1398c2ecf20Sopenharmony_ci}
1408c2ecf20Sopenharmony_ci#else
1418c2ecf20Sopenharmony_ci#define sock_show_fdinfo NULL
1428c2ecf20Sopenharmony_ci#endif
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci/*
1458c2ecf20Sopenharmony_ci *	Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
1468c2ecf20Sopenharmony_ci *	in the operation structures but are done directly via the socketcall() multiplexor.
1478c2ecf20Sopenharmony_ci */
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_cistatic const struct file_operations socket_file_ops = {
1508c2ecf20Sopenharmony_ci	.owner =	THIS_MODULE,
1518c2ecf20Sopenharmony_ci	.llseek =	no_llseek,
1528c2ecf20Sopenharmony_ci	.read_iter =	sock_read_iter,
1538c2ecf20Sopenharmony_ci	.write_iter =	sock_write_iter,
1548c2ecf20Sopenharmony_ci	.poll =		sock_poll,
1558c2ecf20Sopenharmony_ci	.unlocked_ioctl = sock_ioctl,
1568c2ecf20Sopenharmony_ci#ifdef CONFIG_COMPAT
1578c2ecf20Sopenharmony_ci	.compat_ioctl = compat_sock_ioctl,
1588c2ecf20Sopenharmony_ci#endif
1598c2ecf20Sopenharmony_ci	.mmap =		sock_mmap,
1608c2ecf20Sopenharmony_ci	.release =	sock_close,
1618c2ecf20Sopenharmony_ci	.fasync =	sock_fasync,
1628c2ecf20Sopenharmony_ci	.sendpage =	sock_sendpage,
1638c2ecf20Sopenharmony_ci	.splice_write = generic_splice_sendpage,
1648c2ecf20Sopenharmony_ci	.splice_read =	sock_splice_read,
1658c2ecf20Sopenharmony_ci	.show_fdinfo =	sock_show_fdinfo,
1668c2ecf20Sopenharmony_ci};
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci/*
1698c2ecf20Sopenharmony_ci *	The protocol list. Each protocol is registered in here.
1708c2ecf20Sopenharmony_ci */
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_cistatic DEFINE_SPINLOCK(net_family_lock);
1738c2ecf20Sopenharmony_cistatic const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly;
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci/*
1768c2ecf20Sopenharmony_ci * Support routines.
1778c2ecf20Sopenharmony_ci * Move socket addresses back and forth across the kernel/user
1788c2ecf20Sopenharmony_ci * divide and look after the messy bits.
1798c2ecf20Sopenharmony_ci */
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci/**
1828c2ecf20Sopenharmony_ci *	move_addr_to_kernel	-	copy a socket address into kernel space
1838c2ecf20Sopenharmony_ci *	@uaddr: Address in user space
1848c2ecf20Sopenharmony_ci *	@kaddr: Address in kernel space
1858c2ecf20Sopenharmony_ci *	@ulen: Length in user space
1868c2ecf20Sopenharmony_ci *
1878c2ecf20Sopenharmony_ci *	The address is copied into kernel space. If the provided address is
1888c2ecf20Sopenharmony_ci *	too long an error code of -EINVAL is returned. If the copy gives
1898c2ecf20Sopenharmony_ci *	invalid addresses -EFAULT is returned. On a success 0 is returned.
1908c2ecf20Sopenharmony_ci */
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ciint move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr)
1938c2ecf20Sopenharmony_ci{
1948c2ecf20Sopenharmony_ci	if (ulen < 0 || ulen > sizeof(struct sockaddr_storage))
1958c2ecf20Sopenharmony_ci		return -EINVAL;
1968c2ecf20Sopenharmony_ci	if (ulen == 0)
1978c2ecf20Sopenharmony_ci		return 0;
1988c2ecf20Sopenharmony_ci	if (copy_from_user(kaddr, uaddr, ulen))
1998c2ecf20Sopenharmony_ci		return -EFAULT;
2008c2ecf20Sopenharmony_ci	return audit_sockaddr(ulen, kaddr);
2018c2ecf20Sopenharmony_ci}
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci/**
2048c2ecf20Sopenharmony_ci *	move_addr_to_user	-	copy an address to user space
2058c2ecf20Sopenharmony_ci *	@kaddr: kernel space address
2068c2ecf20Sopenharmony_ci *	@klen: length of address in kernel
2078c2ecf20Sopenharmony_ci *	@uaddr: user space address
2088c2ecf20Sopenharmony_ci *	@ulen: pointer to user length field
2098c2ecf20Sopenharmony_ci *
2108c2ecf20Sopenharmony_ci *	The value pointed to by ulen on entry is the buffer length available.
2118c2ecf20Sopenharmony_ci *	This is overwritten with the buffer space used. -EINVAL is returned
2128c2ecf20Sopenharmony_ci *	if an overlong buffer is specified or a negative buffer size. -EFAULT
2138c2ecf20Sopenharmony_ci *	is returned if either the buffer or the length field are not
2148c2ecf20Sopenharmony_ci *	accessible.
2158c2ecf20Sopenharmony_ci *	After copying the data up to the limit the user specifies, the true
2168c2ecf20Sopenharmony_ci *	length of the data is written over the length limit the user
2178c2ecf20Sopenharmony_ci *	specified. Zero is returned for a success.
2188c2ecf20Sopenharmony_ci */
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_cistatic int move_addr_to_user(struct sockaddr_storage *kaddr, int klen,
2218c2ecf20Sopenharmony_ci			     void __user *uaddr, int __user *ulen)
2228c2ecf20Sopenharmony_ci{
2238c2ecf20Sopenharmony_ci	int err;
2248c2ecf20Sopenharmony_ci	int len;
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	BUG_ON(klen > sizeof(struct sockaddr_storage));
2278c2ecf20Sopenharmony_ci	err = get_user(len, ulen);
2288c2ecf20Sopenharmony_ci	if (err)
2298c2ecf20Sopenharmony_ci		return err;
2308c2ecf20Sopenharmony_ci	if (len > klen)
2318c2ecf20Sopenharmony_ci		len = klen;
2328c2ecf20Sopenharmony_ci	if (len < 0)
2338c2ecf20Sopenharmony_ci		return -EINVAL;
2348c2ecf20Sopenharmony_ci	if (len) {
2358c2ecf20Sopenharmony_ci		if (audit_sockaddr(klen, kaddr))
2368c2ecf20Sopenharmony_ci			return -ENOMEM;
2378c2ecf20Sopenharmony_ci		if (copy_to_user(uaddr, kaddr, len))
2388c2ecf20Sopenharmony_ci			return -EFAULT;
2398c2ecf20Sopenharmony_ci	}
2408c2ecf20Sopenharmony_ci	/*
2418c2ecf20Sopenharmony_ci	 *      "fromlen shall refer to the value before truncation.."
2428c2ecf20Sopenharmony_ci	 *                      1003.1g
2438c2ecf20Sopenharmony_ci	 */
2448c2ecf20Sopenharmony_ci	return __put_user(klen, ulen);
2458c2ecf20Sopenharmony_ci}
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_cistatic struct kmem_cache *sock_inode_cachep __ro_after_init;
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_cistatic struct inode *sock_alloc_inode(struct super_block *sb)
2508c2ecf20Sopenharmony_ci{
2518c2ecf20Sopenharmony_ci	struct socket_alloc *ei;
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL);
2548c2ecf20Sopenharmony_ci	if (!ei)
2558c2ecf20Sopenharmony_ci		return NULL;
2568c2ecf20Sopenharmony_ci	init_waitqueue_head(&ei->socket.wq.wait);
2578c2ecf20Sopenharmony_ci	ei->socket.wq.fasync_list = NULL;
2588c2ecf20Sopenharmony_ci	ei->socket.wq.flags = 0;
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci	ei->socket.state = SS_UNCONNECTED;
2618c2ecf20Sopenharmony_ci	ei->socket.flags = 0;
2628c2ecf20Sopenharmony_ci	ei->socket.ops = NULL;
2638c2ecf20Sopenharmony_ci	ei->socket.sk = NULL;
2648c2ecf20Sopenharmony_ci	ei->socket.file = NULL;
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	return &ei->vfs_inode;
2678c2ecf20Sopenharmony_ci}
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_cistatic void sock_free_inode(struct inode *inode)
2708c2ecf20Sopenharmony_ci{
2718c2ecf20Sopenharmony_ci	struct socket_alloc *ei;
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	ei = container_of(inode, struct socket_alloc, vfs_inode);
2748c2ecf20Sopenharmony_ci	kmem_cache_free(sock_inode_cachep, ei);
2758c2ecf20Sopenharmony_ci}
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_cistatic void init_once(void *foo)
2788c2ecf20Sopenharmony_ci{
2798c2ecf20Sopenharmony_ci	struct socket_alloc *ei = (struct socket_alloc *)foo;
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci	inode_init_once(&ei->vfs_inode);
2828c2ecf20Sopenharmony_ci}
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_cistatic void init_inodecache(void)
2858c2ecf20Sopenharmony_ci{
2868c2ecf20Sopenharmony_ci	sock_inode_cachep = kmem_cache_create("sock_inode_cache",
2878c2ecf20Sopenharmony_ci					      sizeof(struct socket_alloc),
2888c2ecf20Sopenharmony_ci					      0,
2898c2ecf20Sopenharmony_ci					      (SLAB_HWCACHE_ALIGN |
2908c2ecf20Sopenharmony_ci					       SLAB_RECLAIM_ACCOUNT |
2918c2ecf20Sopenharmony_ci					       SLAB_MEM_SPREAD | SLAB_ACCOUNT),
2928c2ecf20Sopenharmony_ci					      init_once);
2938c2ecf20Sopenharmony_ci	BUG_ON(sock_inode_cachep == NULL);
2948c2ecf20Sopenharmony_ci}
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_cistatic const struct super_operations sockfs_ops = {
2978c2ecf20Sopenharmony_ci	.alloc_inode	= sock_alloc_inode,
2988c2ecf20Sopenharmony_ci	.free_inode	= sock_free_inode,
2998c2ecf20Sopenharmony_ci	.statfs		= simple_statfs,
3008c2ecf20Sopenharmony_ci};
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci/*
3038c2ecf20Sopenharmony_ci * sockfs_dname() is called from d_path().
3048c2ecf20Sopenharmony_ci */
3058c2ecf20Sopenharmony_cistatic char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen)
3068c2ecf20Sopenharmony_ci{
3078c2ecf20Sopenharmony_ci	return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]",
3088c2ecf20Sopenharmony_ci				d_inode(dentry)->i_ino);
3098c2ecf20Sopenharmony_ci}
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_cistatic const struct dentry_operations sockfs_dentry_operations = {
3128c2ecf20Sopenharmony_ci	.d_dname  = sockfs_dname,
3138c2ecf20Sopenharmony_ci};
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_cistatic int sockfs_xattr_get(const struct xattr_handler *handler,
3168c2ecf20Sopenharmony_ci			    struct dentry *dentry, struct inode *inode,
3178c2ecf20Sopenharmony_ci			    const char *suffix, void *value, size_t size)
3188c2ecf20Sopenharmony_ci{
3198c2ecf20Sopenharmony_ci	if (value) {
3208c2ecf20Sopenharmony_ci		if (dentry->d_name.len + 1 > size)
3218c2ecf20Sopenharmony_ci			return -ERANGE;
3228c2ecf20Sopenharmony_ci		memcpy(value, dentry->d_name.name, dentry->d_name.len + 1);
3238c2ecf20Sopenharmony_ci	}
3248c2ecf20Sopenharmony_ci	return dentry->d_name.len + 1;
3258c2ecf20Sopenharmony_ci}
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci#define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname"
3288c2ecf20Sopenharmony_ci#define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX)
3298c2ecf20Sopenharmony_ci#define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1)
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_cistatic const struct xattr_handler sockfs_xattr_handler = {
3328c2ecf20Sopenharmony_ci	.name = XATTR_NAME_SOCKPROTONAME,
3338c2ecf20Sopenharmony_ci	.get = sockfs_xattr_get,
3348c2ecf20Sopenharmony_ci};
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_cistatic int sockfs_security_xattr_set(const struct xattr_handler *handler,
3378c2ecf20Sopenharmony_ci				     struct dentry *dentry, struct inode *inode,
3388c2ecf20Sopenharmony_ci				     const char *suffix, const void *value,
3398c2ecf20Sopenharmony_ci				     size_t size, int flags)
3408c2ecf20Sopenharmony_ci{
3418c2ecf20Sopenharmony_ci	/* Handled by LSM. */
3428c2ecf20Sopenharmony_ci	return -EAGAIN;
3438c2ecf20Sopenharmony_ci}
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_cistatic const struct xattr_handler sockfs_security_xattr_handler = {
3468c2ecf20Sopenharmony_ci	.prefix = XATTR_SECURITY_PREFIX,
3478c2ecf20Sopenharmony_ci	.set = sockfs_security_xattr_set,
3488c2ecf20Sopenharmony_ci};
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_cistatic const struct xattr_handler *sockfs_xattr_handlers[] = {
3518c2ecf20Sopenharmony_ci	&sockfs_xattr_handler,
3528c2ecf20Sopenharmony_ci	&sockfs_security_xattr_handler,
3538c2ecf20Sopenharmony_ci	NULL
3548c2ecf20Sopenharmony_ci};
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_cistatic int sockfs_init_fs_context(struct fs_context *fc)
3578c2ecf20Sopenharmony_ci{
3588c2ecf20Sopenharmony_ci	struct pseudo_fs_context *ctx = init_pseudo(fc, SOCKFS_MAGIC);
3598c2ecf20Sopenharmony_ci	if (!ctx)
3608c2ecf20Sopenharmony_ci		return -ENOMEM;
3618c2ecf20Sopenharmony_ci	ctx->ops = &sockfs_ops;
3628c2ecf20Sopenharmony_ci	ctx->dops = &sockfs_dentry_operations;
3638c2ecf20Sopenharmony_ci	ctx->xattr = sockfs_xattr_handlers;
3648c2ecf20Sopenharmony_ci	return 0;
3658c2ecf20Sopenharmony_ci}
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_cistatic struct vfsmount *sock_mnt __read_mostly;
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_cistatic struct file_system_type sock_fs_type = {
3708c2ecf20Sopenharmony_ci	.name =		"sockfs",
3718c2ecf20Sopenharmony_ci	.init_fs_context = sockfs_init_fs_context,
3728c2ecf20Sopenharmony_ci	.kill_sb =	kill_anon_super,
3738c2ecf20Sopenharmony_ci};
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_ci/*
3768c2ecf20Sopenharmony_ci *	Obtains the first available file descriptor and sets it up for use.
3778c2ecf20Sopenharmony_ci *
3788c2ecf20Sopenharmony_ci *	These functions create file structures and maps them to fd space
3798c2ecf20Sopenharmony_ci *	of the current process. On success it returns file descriptor
3808c2ecf20Sopenharmony_ci *	and file struct implicitly stored in sock->file.
3818c2ecf20Sopenharmony_ci *	Note that another thread may close file descriptor before we return
3828c2ecf20Sopenharmony_ci *	from this function. We use the fact that now we do not refer
3838c2ecf20Sopenharmony_ci *	to socket after mapping. If one day we will need it, this
3848c2ecf20Sopenharmony_ci *	function will increment ref. count on file by 1.
3858c2ecf20Sopenharmony_ci *
3868c2ecf20Sopenharmony_ci *	In any case returned fd MAY BE not valid!
3878c2ecf20Sopenharmony_ci *	This race condition is unavoidable
3888c2ecf20Sopenharmony_ci *	with shared fd spaces, we cannot solve it inside kernel,
3898c2ecf20Sopenharmony_ci *	but we take care of internal coherence yet.
3908c2ecf20Sopenharmony_ci */
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci/**
3938c2ecf20Sopenharmony_ci *	sock_alloc_file - Bind a &socket to a &file
3948c2ecf20Sopenharmony_ci *	@sock: socket
3958c2ecf20Sopenharmony_ci *	@flags: file status flags
3968c2ecf20Sopenharmony_ci *	@dname: protocol name
3978c2ecf20Sopenharmony_ci *
3988c2ecf20Sopenharmony_ci *	Returns the &file bound with @sock, implicitly storing it
3998c2ecf20Sopenharmony_ci *	in sock->file. If dname is %NULL, sets to "".
4008c2ecf20Sopenharmony_ci *	On failure the return is a ERR pointer (see linux/err.h).
4018c2ecf20Sopenharmony_ci *	This function uses GFP_KERNEL internally.
4028c2ecf20Sopenharmony_ci */
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_cistruct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)
4058c2ecf20Sopenharmony_ci{
4068c2ecf20Sopenharmony_ci	struct file *file;
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_ci	if (!dname)
4098c2ecf20Sopenharmony_ci		dname = sock->sk ? sock->sk->sk_prot_creator->name : "";
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	file = alloc_file_pseudo(SOCK_INODE(sock), sock_mnt, dname,
4128c2ecf20Sopenharmony_ci				O_RDWR | (flags & O_NONBLOCK),
4138c2ecf20Sopenharmony_ci				&socket_file_ops);
4148c2ecf20Sopenharmony_ci	if (IS_ERR(file)) {
4158c2ecf20Sopenharmony_ci		sock_release(sock);
4168c2ecf20Sopenharmony_ci		return file;
4178c2ecf20Sopenharmony_ci	}
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	sock->file = file;
4208c2ecf20Sopenharmony_ci	file->private_data = sock;
4218c2ecf20Sopenharmony_ci	stream_open(SOCK_INODE(sock), file);
4228c2ecf20Sopenharmony_ci	return file;
4238c2ecf20Sopenharmony_ci}
4248c2ecf20Sopenharmony_ciEXPORT_SYMBOL(sock_alloc_file);
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_cistatic int sock_map_fd(struct socket *sock, int flags)
4278c2ecf20Sopenharmony_ci{
4288c2ecf20Sopenharmony_ci	struct file *newfile;
4298c2ecf20Sopenharmony_ci	int fd = get_unused_fd_flags(flags);
4308c2ecf20Sopenharmony_ci	if (unlikely(fd < 0)) {
4318c2ecf20Sopenharmony_ci		sock_release(sock);
4328c2ecf20Sopenharmony_ci		return fd;
4338c2ecf20Sopenharmony_ci	}
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	newfile = sock_alloc_file(sock, flags, NULL);
4368c2ecf20Sopenharmony_ci	if (!IS_ERR(newfile)) {
4378c2ecf20Sopenharmony_ci		fd_install(fd, newfile);
4388c2ecf20Sopenharmony_ci		return fd;
4398c2ecf20Sopenharmony_ci	}
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci	put_unused_fd(fd);
4428c2ecf20Sopenharmony_ci	return PTR_ERR(newfile);
4438c2ecf20Sopenharmony_ci}
4448c2ecf20Sopenharmony_ci
4458c2ecf20Sopenharmony_ci/**
4468c2ecf20Sopenharmony_ci *	sock_from_file - Return the &socket bounded to @file.
4478c2ecf20Sopenharmony_ci *	@file: file
4488c2ecf20Sopenharmony_ci *	@err: pointer to an error code return
4498c2ecf20Sopenharmony_ci *
4508c2ecf20Sopenharmony_ci *	On failure returns %NULL and assigns -ENOTSOCK to @err.
4518c2ecf20Sopenharmony_ci */
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_cistruct socket *sock_from_file(struct file *file, int *err)
4548c2ecf20Sopenharmony_ci{
4558c2ecf20Sopenharmony_ci	if (file->f_op == &socket_file_ops)
4568c2ecf20Sopenharmony_ci		return file->private_data;	/* set in sock_map_fd */
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_ci	*err = -ENOTSOCK;
4598c2ecf20Sopenharmony_ci	return NULL;
4608c2ecf20Sopenharmony_ci}
4618c2ecf20Sopenharmony_ciEXPORT_SYMBOL(sock_from_file);
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_ci/**
4648c2ecf20Sopenharmony_ci *	sockfd_lookup - Go from a file number to its socket slot
4658c2ecf20Sopenharmony_ci *	@fd: file handle
4668c2ecf20Sopenharmony_ci *	@err: pointer to an error code return
4678c2ecf20Sopenharmony_ci *
4688c2ecf20Sopenharmony_ci *	The file handle passed in is locked and the socket it is bound
4698c2ecf20Sopenharmony_ci *	to is returned. If an error occurs the err pointer is overwritten
4708c2ecf20Sopenharmony_ci *	with a negative errno code and NULL is returned. The function checks
4718c2ecf20Sopenharmony_ci *	for both invalid handles and passing a handle which is not a socket.
4728c2ecf20Sopenharmony_ci *
4738c2ecf20Sopenharmony_ci *	On a success the socket object pointer is returned.
4748c2ecf20Sopenharmony_ci */
4758c2ecf20Sopenharmony_ci
4768c2ecf20Sopenharmony_cistruct socket *sockfd_lookup(int fd, int *err)
4778c2ecf20Sopenharmony_ci{
4788c2ecf20Sopenharmony_ci	struct file *file;
4798c2ecf20Sopenharmony_ci	struct socket *sock;
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_ci	file = fget(fd);
4828c2ecf20Sopenharmony_ci	if (!file) {
4838c2ecf20Sopenharmony_ci		*err = -EBADF;
4848c2ecf20Sopenharmony_ci		return NULL;
4858c2ecf20Sopenharmony_ci	}
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ci	sock = sock_from_file(file, err);
4888c2ecf20Sopenharmony_ci	if (!sock)
4898c2ecf20Sopenharmony_ci		fput(file);
4908c2ecf20Sopenharmony_ci	return sock;
4918c2ecf20Sopenharmony_ci}
4928c2ecf20Sopenharmony_ciEXPORT_SYMBOL(sockfd_lookup);
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_cistatic struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
4958c2ecf20Sopenharmony_ci{
4968c2ecf20Sopenharmony_ci	struct fd f = fdget(fd);
4978c2ecf20Sopenharmony_ci	struct socket *sock;
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci	*err = -EBADF;
5008c2ecf20Sopenharmony_ci	if (f.file) {
5018c2ecf20Sopenharmony_ci		sock = sock_from_file(f.file, err);
5028c2ecf20Sopenharmony_ci		if (likely(sock)) {
5038c2ecf20Sopenharmony_ci			*fput_needed = f.flags & FDPUT_FPUT;
5048c2ecf20Sopenharmony_ci			return sock;
5058c2ecf20Sopenharmony_ci		}
5068c2ecf20Sopenharmony_ci		fdput(f);
5078c2ecf20Sopenharmony_ci	}
5088c2ecf20Sopenharmony_ci	return NULL;
5098c2ecf20Sopenharmony_ci}
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_cistatic ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer,
5128c2ecf20Sopenharmony_ci				size_t size)
5138c2ecf20Sopenharmony_ci{
5148c2ecf20Sopenharmony_ci	ssize_t len;
5158c2ecf20Sopenharmony_ci	ssize_t used = 0;
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci	len = security_inode_listsecurity(d_inode(dentry), buffer, size);
5188c2ecf20Sopenharmony_ci	if (len < 0)
5198c2ecf20Sopenharmony_ci		return len;
5208c2ecf20Sopenharmony_ci	used += len;
5218c2ecf20Sopenharmony_ci	if (buffer) {
5228c2ecf20Sopenharmony_ci		if (size < used)
5238c2ecf20Sopenharmony_ci			return -ERANGE;
5248c2ecf20Sopenharmony_ci		buffer += len;
5258c2ecf20Sopenharmony_ci	}
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ci	len = (XATTR_NAME_SOCKPROTONAME_LEN + 1);
5288c2ecf20Sopenharmony_ci	used += len;
5298c2ecf20Sopenharmony_ci	if (buffer) {
5308c2ecf20Sopenharmony_ci		if (size < used)
5318c2ecf20Sopenharmony_ci			return -ERANGE;
5328c2ecf20Sopenharmony_ci		memcpy(buffer, XATTR_NAME_SOCKPROTONAME, len);
5338c2ecf20Sopenharmony_ci		buffer += len;
5348c2ecf20Sopenharmony_ci	}
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci	return used;
5378c2ecf20Sopenharmony_ci}
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_cistatic int sockfs_setattr(struct dentry *dentry, struct iattr *iattr)
5408c2ecf20Sopenharmony_ci{
5418c2ecf20Sopenharmony_ci	int err = simple_setattr(dentry, iattr);
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci	if (!err && (iattr->ia_valid & ATTR_UID)) {
5448c2ecf20Sopenharmony_ci		struct socket *sock = SOCKET_I(d_inode(dentry));
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_ci		if (sock->sk)
5478c2ecf20Sopenharmony_ci			sock->sk->sk_uid = iattr->ia_uid;
5488c2ecf20Sopenharmony_ci		else
5498c2ecf20Sopenharmony_ci			err = -ENOENT;
5508c2ecf20Sopenharmony_ci	}
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci	return err;
5538c2ecf20Sopenharmony_ci}
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_cistatic const struct inode_operations sockfs_inode_ops = {
5568c2ecf20Sopenharmony_ci	.listxattr = sockfs_listxattr,
5578c2ecf20Sopenharmony_ci	.setattr = sockfs_setattr,
5588c2ecf20Sopenharmony_ci};
5598c2ecf20Sopenharmony_ci
5608c2ecf20Sopenharmony_ci/**
5618c2ecf20Sopenharmony_ci *	sock_alloc - allocate a socket
5628c2ecf20Sopenharmony_ci *
5638c2ecf20Sopenharmony_ci *	Allocate a new inode and socket object. The two are bound together
5648c2ecf20Sopenharmony_ci *	and initialised. The socket is then returned. If we are out of inodes
5658c2ecf20Sopenharmony_ci *	NULL is returned. This functions uses GFP_KERNEL internally.
5668c2ecf20Sopenharmony_ci */
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_cistruct socket *sock_alloc(void)
5698c2ecf20Sopenharmony_ci{
5708c2ecf20Sopenharmony_ci	struct inode *inode;
5718c2ecf20Sopenharmony_ci	struct socket *sock;
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci	inode = new_inode_pseudo(sock_mnt->mnt_sb);
5748c2ecf20Sopenharmony_ci	if (!inode)
5758c2ecf20Sopenharmony_ci		return NULL;
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_ci	sock = SOCKET_I(inode);
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci	inode->i_ino = get_next_ino();
5808c2ecf20Sopenharmony_ci	inode->i_mode = S_IFSOCK | S_IRWXUGO;
5818c2ecf20Sopenharmony_ci	inode->i_uid = current_fsuid();
5828c2ecf20Sopenharmony_ci	inode->i_gid = current_fsgid();
5838c2ecf20Sopenharmony_ci	inode->i_op = &sockfs_inode_ops;
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_ci	return sock;
5868c2ecf20Sopenharmony_ci}
5878c2ecf20Sopenharmony_ciEXPORT_SYMBOL(sock_alloc);
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_cistatic void __sock_release(struct socket *sock, struct inode *inode)
5908c2ecf20Sopenharmony_ci{
5918c2ecf20Sopenharmony_ci	if (sock->ops) {
5928c2ecf20Sopenharmony_ci		struct module *owner = sock->ops->owner;
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_ci		if (inode)
5958c2ecf20Sopenharmony_ci			inode_lock(inode);
5968c2ecf20Sopenharmony_ci		sock->ops->release(sock);
5978c2ecf20Sopenharmony_ci		sock->sk = NULL;
5988c2ecf20Sopenharmony_ci		if (inode)
5998c2ecf20Sopenharmony_ci			inode_unlock(inode);
6008c2ecf20Sopenharmony_ci		sock->ops = NULL;
6018c2ecf20Sopenharmony_ci		module_put(owner);
6028c2ecf20Sopenharmony_ci	}
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci	if (sock->wq.fasync_list)
6058c2ecf20Sopenharmony_ci		pr_err("%s: fasync list not empty!\n", __func__);
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_ci	if (!sock->file) {
6088c2ecf20Sopenharmony_ci		iput(SOCK_INODE(sock));
6098c2ecf20Sopenharmony_ci		return;
6108c2ecf20Sopenharmony_ci	}
6118c2ecf20Sopenharmony_ci	sock->file = NULL;
6128c2ecf20Sopenharmony_ci}
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci/**
6158c2ecf20Sopenharmony_ci *	sock_release - close a socket
6168c2ecf20Sopenharmony_ci *	@sock: socket to close
6178c2ecf20Sopenharmony_ci *
6188c2ecf20Sopenharmony_ci *	The socket is released from the protocol stack if it has a release
6198c2ecf20Sopenharmony_ci *	callback, and the inode is then released if the socket is bound to
6208c2ecf20Sopenharmony_ci *	an inode not a file.
6218c2ecf20Sopenharmony_ci */
6228c2ecf20Sopenharmony_civoid sock_release(struct socket *sock)
6238c2ecf20Sopenharmony_ci{
6248c2ecf20Sopenharmony_ci	__sock_release(sock, NULL);
6258c2ecf20Sopenharmony_ci}
6268c2ecf20Sopenharmony_ciEXPORT_SYMBOL(sock_release);
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_civoid __sock_tx_timestamp(__u16 tsflags, __u8 *tx_flags)
6298c2ecf20Sopenharmony_ci{
6308c2ecf20Sopenharmony_ci	u8 flags = *tx_flags;
6318c2ecf20Sopenharmony_ci
6328c2ecf20Sopenharmony_ci	if (tsflags & SOF_TIMESTAMPING_TX_HARDWARE)
6338c2ecf20Sopenharmony_ci		flags |= SKBTX_HW_TSTAMP;
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_ci	if (tsflags & SOF_TIMESTAMPING_TX_SOFTWARE)
6368c2ecf20Sopenharmony_ci		flags |= SKBTX_SW_TSTAMP;
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_ci	if (tsflags & SOF_TIMESTAMPING_TX_SCHED)
6398c2ecf20Sopenharmony_ci		flags |= SKBTX_SCHED_TSTAMP;
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ci	*tx_flags = flags;
6428c2ecf20Sopenharmony_ci}
6438c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__sock_tx_timestamp);
6448c2ecf20Sopenharmony_ci
6458c2ecf20Sopenharmony_ciINDIRECT_CALLABLE_DECLARE(int inet_sendmsg(struct socket *, struct msghdr *,
6468c2ecf20Sopenharmony_ci					   size_t));
6478c2ecf20Sopenharmony_ciINDIRECT_CALLABLE_DECLARE(int inet6_sendmsg(struct socket *, struct msghdr *,
6488c2ecf20Sopenharmony_ci					    size_t));
6498c2ecf20Sopenharmony_cistatic inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg)
6508c2ecf20Sopenharmony_ci{
6518c2ecf20Sopenharmony_ci	int ret = INDIRECT_CALL_INET(sock->ops->sendmsg, inet6_sendmsg,
6528c2ecf20Sopenharmony_ci				     inet_sendmsg, sock, msg,
6538c2ecf20Sopenharmony_ci				     msg_data_left(msg));
6548c2ecf20Sopenharmony_ci	BUG_ON(ret == -EIOCBQUEUED);
6558c2ecf20Sopenharmony_ci	return ret;
6568c2ecf20Sopenharmony_ci}
6578c2ecf20Sopenharmony_ci
6588c2ecf20Sopenharmony_cistatic int __sock_sendmsg(struct socket *sock, struct msghdr *msg)
6598c2ecf20Sopenharmony_ci{
6608c2ecf20Sopenharmony_ci	int err = security_socket_sendmsg(sock, msg,
6618c2ecf20Sopenharmony_ci					  msg_data_left(msg));
6628c2ecf20Sopenharmony_ci
6638c2ecf20Sopenharmony_ci	return err ?: sock_sendmsg_nosec(sock, msg);
6648c2ecf20Sopenharmony_ci}
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci/**
6678c2ecf20Sopenharmony_ci *	sock_sendmsg - send a message through @sock
6688c2ecf20Sopenharmony_ci *	@sock: socket
6698c2ecf20Sopenharmony_ci *	@msg: message to send
6708c2ecf20Sopenharmony_ci *
6718c2ecf20Sopenharmony_ci *	Sends @msg through @sock, passing through LSM.
6728c2ecf20Sopenharmony_ci *	Returns the number of bytes sent, or an error code.
6738c2ecf20Sopenharmony_ci */
6748c2ecf20Sopenharmony_ciint sock_sendmsg(struct socket *sock, struct msghdr *msg)
6758c2ecf20Sopenharmony_ci{
6768c2ecf20Sopenharmony_ci	struct sockaddr_storage *save_addr = (struct sockaddr_storage *)msg->msg_name;
6778c2ecf20Sopenharmony_ci	struct sockaddr_storage address;
6788c2ecf20Sopenharmony_ci	int save_len = msg->msg_namelen;
6798c2ecf20Sopenharmony_ci	int ret;
6808c2ecf20Sopenharmony_ci
6818c2ecf20Sopenharmony_ci	if (msg->msg_name) {
6828c2ecf20Sopenharmony_ci		memcpy(&address, msg->msg_name, msg->msg_namelen);
6838c2ecf20Sopenharmony_ci		msg->msg_name = &address;
6848c2ecf20Sopenharmony_ci	}
6858c2ecf20Sopenharmony_ci
6868c2ecf20Sopenharmony_ci	ret = __sock_sendmsg(sock, msg);
6878c2ecf20Sopenharmony_ci	msg->msg_name = save_addr;
6888c2ecf20Sopenharmony_ci	msg->msg_namelen = save_len;
6898c2ecf20Sopenharmony_ci
6908c2ecf20Sopenharmony_ci	return ret;
6918c2ecf20Sopenharmony_ci}
6928c2ecf20Sopenharmony_ciEXPORT_SYMBOL(sock_sendmsg);
6938c2ecf20Sopenharmony_ci
6948c2ecf20Sopenharmony_ci/**
6958c2ecf20Sopenharmony_ci *	kernel_sendmsg - send a message through @sock (kernel-space)
6968c2ecf20Sopenharmony_ci *	@sock: socket
6978c2ecf20Sopenharmony_ci *	@msg: message header
6988c2ecf20Sopenharmony_ci *	@vec: kernel vec
6998c2ecf20Sopenharmony_ci *	@num: vec array length
7008c2ecf20Sopenharmony_ci *	@size: total message data size
7018c2ecf20Sopenharmony_ci *
7028c2ecf20Sopenharmony_ci *	Builds the message data with @vec and sends it through @sock.
7038c2ecf20Sopenharmony_ci *	Returns the number of bytes sent, or an error code.
7048c2ecf20Sopenharmony_ci */
7058c2ecf20Sopenharmony_ci
7068c2ecf20Sopenharmony_ciint kernel_sendmsg(struct socket *sock, struct msghdr *msg,
7078c2ecf20Sopenharmony_ci		   struct kvec *vec, size_t num, size_t size)
7088c2ecf20Sopenharmony_ci{
7098c2ecf20Sopenharmony_ci	iov_iter_kvec(&msg->msg_iter, WRITE, vec, num, size);
7108c2ecf20Sopenharmony_ci	return sock_sendmsg(sock, msg);
7118c2ecf20Sopenharmony_ci}
7128c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kernel_sendmsg);
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_ci/**
7158c2ecf20Sopenharmony_ci *	kernel_sendmsg_locked - send a message through @sock (kernel-space)
7168c2ecf20Sopenharmony_ci *	@sk: sock
7178c2ecf20Sopenharmony_ci *	@msg: message header
7188c2ecf20Sopenharmony_ci *	@vec: output s/g array
7198c2ecf20Sopenharmony_ci *	@num: output s/g array length
7208c2ecf20Sopenharmony_ci *	@size: total message data size
7218c2ecf20Sopenharmony_ci *
7228c2ecf20Sopenharmony_ci *	Builds the message data with @vec and sends it through @sock.
7238c2ecf20Sopenharmony_ci *	Returns the number of bytes sent, or an error code.
7248c2ecf20Sopenharmony_ci *	Caller must hold @sk.
7258c2ecf20Sopenharmony_ci */
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_ciint kernel_sendmsg_locked(struct sock *sk, struct msghdr *msg,
7288c2ecf20Sopenharmony_ci			  struct kvec *vec, size_t num, size_t size)
7298c2ecf20Sopenharmony_ci{
7308c2ecf20Sopenharmony_ci	struct socket *sock = sk->sk_socket;
7318c2ecf20Sopenharmony_ci
7328c2ecf20Sopenharmony_ci	if (!sock->ops->sendmsg_locked)
7338c2ecf20Sopenharmony_ci		return sock_no_sendmsg_locked(sk, msg, size);
7348c2ecf20Sopenharmony_ci
7358c2ecf20Sopenharmony_ci	iov_iter_kvec(&msg->msg_iter, WRITE, vec, num, size);
7368c2ecf20Sopenharmony_ci
7378c2ecf20Sopenharmony_ci	return sock->ops->sendmsg_locked(sk, msg, msg_data_left(msg));
7388c2ecf20Sopenharmony_ci}
7398c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kernel_sendmsg_locked);
7408c2ecf20Sopenharmony_ci
7418c2ecf20Sopenharmony_cistatic bool skb_is_err_queue(const struct sk_buff *skb)
7428c2ecf20Sopenharmony_ci{
7438c2ecf20Sopenharmony_ci	/* pkt_type of skbs enqueued on the error queue are set to
7448c2ecf20Sopenharmony_ci	 * PACKET_OUTGOING in skb_set_err_queue(). This is only safe to do
7458c2ecf20Sopenharmony_ci	 * in recvmsg, since skbs received on a local socket will never
7468c2ecf20Sopenharmony_ci	 * have a pkt_type of PACKET_OUTGOING.
7478c2ecf20Sopenharmony_ci	 */
7488c2ecf20Sopenharmony_ci	return skb->pkt_type == PACKET_OUTGOING;
7498c2ecf20Sopenharmony_ci}
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_ci/* On transmit, software and hardware timestamps are returned independently.
7528c2ecf20Sopenharmony_ci * As the two skb clones share the hardware timestamp, which may be updated
7538c2ecf20Sopenharmony_ci * before the software timestamp is received, a hardware TX timestamp may be
7548c2ecf20Sopenharmony_ci * returned only if there is no software TX timestamp. Ignore false software
7558c2ecf20Sopenharmony_ci * timestamps, which may be made in the __sock_recv_timestamp() call when the
7568c2ecf20Sopenharmony_ci * option SO_TIMESTAMP_OLD(NS) is enabled on the socket, even when the skb has a
7578c2ecf20Sopenharmony_ci * hardware timestamp.
7588c2ecf20Sopenharmony_ci */
7598c2ecf20Sopenharmony_cistatic bool skb_is_swtx_tstamp(const struct sk_buff *skb, int false_tstamp)
7608c2ecf20Sopenharmony_ci{
7618c2ecf20Sopenharmony_ci	return skb->tstamp && !false_tstamp && skb_is_err_queue(skb);
7628c2ecf20Sopenharmony_ci}
7638c2ecf20Sopenharmony_ci
7648c2ecf20Sopenharmony_cistatic void put_ts_pktinfo(struct msghdr *msg, struct sk_buff *skb)
7658c2ecf20Sopenharmony_ci{
7668c2ecf20Sopenharmony_ci	struct scm_ts_pktinfo ts_pktinfo;
7678c2ecf20Sopenharmony_ci	struct net_device *orig_dev;
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_ci	if (!skb_mac_header_was_set(skb))
7708c2ecf20Sopenharmony_ci		return;
7718c2ecf20Sopenharmony_ci
7728c2ecf20Sopenharmony_ci	memset(&ts_pktinfo, 0, sizeof(ts_pktinfo));
7738c2ecf20Sopenharmony_ci
7748c2ecf20Sopenharmony_ci	rcu_read_lock();
7758c2ecf20Sopenharmony_ci	orig_dev = dev_get_by_napi_id(skb_napi_id(skb));
7768c2ecf20Sopenharmony_ci	if (orig_dev)
7778c2ecf20Sopenharmony_ci		ts_pktinfo.if_index = orig_dev->ifindex;
7788c2ecf20Sopenharmony_ci	rcu_read_unlock();
7798c2ecf20Sopenharmony_ci
7808c2ecf20Sopenharmony_ci	ts_pktinfo.pkt_length = skb->len - skb_mac_offset(skb);
7818c2ecf20Sopenharmony_ci	put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_PKTINFO,
7828c2ecf20Sopenharmony_ci		 sizeof(ts_pktinfo), &ts_pktinfo);
7838c2ecf20Sopenharmony_ci}
7848c2ecf20Sopenharmony_ci
7858c2ecf20Sopenharmony_ci/*
7868c2ecf20Sopenharmony_ci * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
7878c2ecf20Sopenharmony_ci */
7888c2ecf20Sopenharmony_civoid __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
7898c2ecf20Sopenharmony_ci	struct sk_buff *skb)
7908c2ecf20Sopenharmony_ci{
7918c2ecf20Sopenharmony_ci	int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
7928c2ecf20Sopenharmony_ci	int new_tstamp = sock_flag(sk, SOCK_TSTAMP_NEW);
7938c2ecf20Sopenharmony_ci	struct scm_timestamping_internal tss;
7948c2ecf20Sopenharmony_ci
7958c2ecf20Sopenharmony_ci	int empty = 1, false_tstamp = 0;
7968c2ecf20Sopenharmony_ci	struct skb_shared_hwtstamps *shhwtstamps =
7978c2ecf20Sopenharmony_ci		skb_hwtstamps(skb);
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_ci	/* Race occurred between timestamp enabling and packet
8008c2ecf20Sopenharmony_ci	   receiving.  Fill in the current time for now. */
8018c2ecf20Sopenharmony_ci	if (need_software_tstamp && skb->tstamp == 0) {
8028c2ecf20Sopenharmony_ci		__net_timestamp(skb);
8038c2ecf20Sopenharmony_ci		false_tstamp = 1;
8048c2ecf20Sopenharmony_ci	}
8058c2ecf20Sopenharmony_ci
8068c2ecf20Sopenharmony_ci	if (need_software_tstamp) {
8078c2ecf20Sopenharmony_ci		if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
8088c2ecf20Sopenharmony_ci			if (new_tstamp) {
8098c2ecf20Sopenharmony_ci				struct __kernel_sock_timeval tv;
8108c2ecf20Sopenharmony_ci
8118c2ecf20Sopenharmony_ci				skb_get_new_timestamp(skb, &tv);
8128c2ecf20Sopenharmony_ci				put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_NEW,
8138c2ecf20Sopenharmony_ci					 sizeof(tv), &tv);
8148c2ecf20Sopenharmony_ci			} else {
8158c2ecf20Sopenharmony_ci				struct __kernel_old_timeval tv;
8168c2ecf20Sopenharmony_ci
8178c2ecf20Sopenharmony_ci				skb_get_timestamp(skb, &tv);
8188c2ecf20Sopenharmony_ci				put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_OLD,
8198c2ecf20Sopenharmony_ci					 sizeof(tv), &tv);
8208c2ecf20Sopenharmony_ci			}
8218c2ecf20Sopenharmony_ci		} else {
8228c2ecf20Sopenharmony_ci			if (new_tstamp) {
8238c2ecf20Sopenharmony_ci				struct __kernel_timespec ts;
8248c2ecf20Sopenharmony_ci
8258c2ecf20Sopenharmony_ci				skb_get_new_timestampns(skb, &ts);
8268c2ecf20Sopenharmony_ci				put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_NEW,
8278c2ecf20Sopenharmony_ci					 sizeof(ts), &ts);
8288c2ecf20Sopenharmony_ci			} else {
8298c2ecf20Sopenharmony_ci				struct __kernel_old_timespec ts;
8308c2ecf20Sopenharmony_ci
8318c2ecf20Sopenharmony_ci				skb_get_timestampns(skb, &ts);
8328c2ecf20Sopenharmony_ci				put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_OLD,
8338c2ecf20Sopenharmony_ci					 sizeof(ts), &ts);
8348c2ecf20Sopenharmony_ci			}
8358c2ecf20Sopenharmony_ci		}
8368c2ecf20Sopenharmony_ci	}
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ci	memset(&tss, 0, sizeof(tss));
8398c2ecf20Sopenharmony_ci	if ((sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE) &&
8408c2ecf20Sopenharmony_ci	    ktime_to_timespec64_cond(skb->tstamp, tss.ts + 0))
8418c2ecf20Sopenharmony_ci		empty = 0;
8428c2ecf20Sopenharmony_ci	if (shhwtstamps &&
8438c2ecf20Sopenharmony_ci	    (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
8448c2ecf20Sopenharmony_ci	    !skb_is_swtx_tstamp(skb, false_tstamp) &&
8458c2ecf20Sopenharmony_ci	    ktime_to_timespec64_cond(shhwtstamps->hwtstamp, tss.ts + 2)) {
8468c2ecf20Sopenharmony_ci		empty = 0;
8478c2ecf20Sopenharmony_ci		if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_PKTINFO) &&
8488c2ecf20Sopenharmony_ci		    !skb_is_err_queue(skb))
8498c2ecf20Sopenharmony_ci			put_ts_pktinfo(msg, skb);
8508c2ecf20Sopenharmony_ci	}
8518c2ecf20Sopenharmony_ci	if (!empty) {
8528c2ecf20Sopenharmony_ci		if (sock_flag(sk, SOCK_TSTAMP_NEW))
8538c2ecf20Sopenharmony_ci			put_cmsg_scm_timestamping64(msg, &tss);
8548c2ecf20Sopenharmony_ci		else
8558c2ecf20Sopenharmony_ci			put_cmsg_scm_timestamping(msg, &tss);
8568c2ecf20Sopenharmony_ci
8578c2ecf20Sopenharmony_ci		if (skb_is_err_queue(skb) && skb->len &&
8588c2ecf20Sopenharmony_ci		    SKB_EXT_ERR(skb)->opt_stats)
8598c2ecf20Sopenharmony_ci			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_OPT_STATS,
8608c2ecf20Sopenharmony_ci				 skb->len, skb->data);
8618c2ecf20Sopenharmony_ci	}
8628c2ecf20Sopenharmony_ci}
8638c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(__sock_recv_timestamp);
8648c2ecf20Sopenharmony_ci
8658c2ecf20Sopenharmony_civoid __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
8668c2ecf20Sopenharmony_ci	struct sk_buff *skb)
8678c2ecf20Sopenharmony_ci{
8688c2ecf20Sopenharmony_ci	int ack;
8698c2ecf20Sopenharmony_ci
8708c2ecf20Sopenharmony_ci	if (!sock_flag(sk, SOCK_WIFI_STATUS))
8718c2ecf20Sopenharmony_ci		return;
8728c2ecf20Sopenharmony_ci	if (!skb->wifi_acked_valid)
8738c2ecf20Sopenharmony_ci		return;
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_ci	ack = skb->wifi_acked;
8768c2ecf20Sopenharmony_ci
8778c2ecf20Sopenharmony_ci	put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack);
8788c2ecf20Sopenharmony_ci}
8798c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(__sock_recv_wifi_status);
8808c2ecf20Sopenharmony_ci
8818c2ecf20Sopenharmony_cistatic inline void sock_recv_drops(struct msghdr *msg, struct sock *sk,
8828c2ecf20Sopenharmony_ci				   struct sk_buff *skb)
8838c2ecf20Sopenharmony_ci{
8848c2ecf20Sopenharmony_ci	if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && SOCK_SKB_CB(skb)->dropcount)
8858c2ecf20Sopenharmony_ci		put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL,
8868c2ecf20Sopenharmony_ci			sizeof(__u32), &SOCK_SKB_CB(skb)->dropcount);
8878c2ecf20Sopenharmony_ci}
8888c2ecf20Sopenharmony_ci
8898c2ecf20Sopenharmony_civoid __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
8908c2ecf20Sopenharmony_ci	struct sk_buff *skb)
8918c2ecf20Sopenharmony_ci{
8928c2ecf20Sopenharmony_ci	sock_recv_timestamp(msg, sk, skb);
8938c2ecf20Sopenharmony_ci	sock_recv_drops(msg, sk, skb);
8948c2ecf20Sopenharmony_ci}
8958c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops);
8968c2ecf20Sopenharmony_ci
8978c2ecf20Sopenharmony_ciINDIRECT_CALLABLE_DECLARE(int inet_recvmsg(struct socket *, struct msghdr *,
8988c2ecf20Sopenharmony_ci					   size_t, int));
8998c2ecf20Sopenharmony_ciINDIRECT_CALLABLE_DECLARE(int inet6_recvmsg(struct socket *, struct msghdr *,
9008c2ecf20Sopenharmony_ci					    size_t, int));
9018c2ecf20Sopenharmony_cistatic inline int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
9028c2ecf20Sopenharmony_ci				     int flags)
9038c2ecf20Sopenharmony_ci{
9048c2ecf20Sopenharmony_ci	return INDIRECT_CALL_INET(sock->ops->recvmsg, inet6_recvmsg,
9058c2ecf20Sopenharmony_ci				  inet_recvmsg, sock, msg, msg_data_left(msg),
9068c2ecf20Sopenharmony_ci				  flags);
9078c2ecf20Sopenharmony_ci}
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_ci/**
9108c2ecf20Sopenharmony_ci *	sock_recvmsg - receive a message from @sock
9118c2ecf20Sopenharmony_ci *	@sock: socket
9128c2ecf20Sopenharmony_ci *	@msg: message to receive
9138c2ecf20Sopenharmony_ci *	@flags: message flags
9148c2ecf20Sopenharmony_ci *
9158c2ecf20Sopenharmony_ci *	Receives @msg from @sock, passing through LSM. Returns the total number
9168c2ecf20Sopenharmony_ci *	of bytes received, or an error.
9178c2ecf20Sopenharmony_ci */
9188c2ecf20Sopenharmony_ciint sock_recvmsg(struct socket *sock, struct msghdr *msg, int flags)
9198c2ecf20Sopenharmony_ci{
9208c2ecf20Sopenharmony_ci	int err = security_socket_recvmsg(sock, msg, msg_data_left(msg), flags);
9218c2ecf20Sopenharmony_ci
9228c2ecf20Sopenharmony_ci	return err ?: sock_recvmsg_nosec(sock, msg, flags);
9238c2ecf20Sopenharmony_ci}
9248c2ecf20Sopenharmony_ciEXPORT_SYMBOL(sock_recvmsg);
9258c2ecf20Sopenharmony_ci
9268c2ecf20Sopenharmony_ci/**
9278c2ecf20Sopenharmony_ci *	kernel_recvmsg - Receive a message from a socket (kernel space)
9288c2ecf20Sopenharmony_ci *	@sock: The socket to receive the message from
9298c2ecf20Sopenharmony_ci *	@msg: Received message
9308c2ecf20Sopenharmony_ci *	@vec: Input s/g array for message data
9318c2ecf20Sopenharmony_ci *	@num: Size of input s/g array
9328c2ecf20Sopenharmony_ci *	@size: Number of bytes to read
9338c2ecf20Sopenharmony_ci *	@flags: Message flags (MSG_DONTWAIT, etc...)
9348c2ecf20Sopenharmony_ci *
9358c2ecf20Sopenharmony_ci *	On return the msg structure contains the scatter/gather array passed in the
9368c2ecf20Sopenharmony_ci *	vec argument. The array is modified so that it consists of the unfilled
9378c2ecf20Sopenharmony_ci *	portion of the original array.
9388c2ecf20Sopenharmony_ci *
9398c2ecf20Sopenharmony_ci *	The returned value is the total number of bytes received, or an error.
9408c2ecf20Sopenharmony_ci */
9418c2ecf20Sopenharmony_ci
9428c2ecf20Sopenharmony_ciint kernel_recvmsg(struct socket *sock, struct msghdr *msg,
9438c2ecf20Sopenharmony_ci		   struct kvec *vec, size_t num, size_t size, int flags)
9448c2ecf20Sopenharmony_ci{
9458c2ecf20Sopenharmony_ci	msg->msg_control_is_user = false;
9468c2ecf20Sopenharmony_ci	iov_iter_kvec(&msg->msg_iter, READ, vec, num, size);
9478c2ecf20Sopenharmony_ci	return sock_recvmsg(sock, msg, flags);
9488c2ecf20Sopenharmony_ci}
9498c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kernel_recvmsg);
9508c2ecf20Sopenharmony_ci
9518c2ecf20Sopenharmony_cistatic ssize_t sock_sendpage(struct file *file, struct page *page,
9528c2ecf20Sopenharmony_ci			     int offset, size_t size, loff_t *ppos, int more)
9538c2ecf20Sopenharmony_ci{
9548c2ecf20Sopenharmony_ci	struct socket *sock;
9558c2ecf20Sopenharmony_ci	int flags;
9568c2ecf20Sopenharmony_ci
9578c2ecf20Sopenharmony_ci	sock = file->private_data;
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_ci	flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
9608c2ecf20Sopenharmony_ci	/* more is a combination of MSG_MORE and MSG_SENDPAGE_NOTLAST */
9618c2ecf20Sopenharmony_ci	flags |= more;
9628c2ecf20Sopenharmony_ci
9638c2ecf20Sopenharmony_ci	return kernel_sendpage(sock, page, offset, size, flags);
9648c2ecf20Sopenharmony_ci}
9658c2ecf20Sopenharmony_ci
9668c2ecf20Sopenharmony_cistatic ssize_t sock_splice_read(struct file *file, loff_t *ppos,
9678c2ecf20Sopenharmony_ci				struct pipe_inode_info *pipe, size_t len,
9688c2ecf20Sopenharmony_ci				unsigned int flags)
9698c2ecf20Sopenharmony_ci{
9708c2ecf20Sopenharmony_ci	struct socket *sock = file->private_data;
9718c2ecf20Sopenharmony_ci
9728c2ecf20Sopenharmony_ci	if (unlikely(!sock->ops->splice_read))
9738c2ecf20Sopenharmony_ci		return generic_file_splice_read(file, ppos, pipe, len, flags);
9748c2ecf20Sopenharmony_ci
9758c2ecf20Sopenharmony_ci	return sock->ops->splice_read(sock, ppos, pipe, len, flags);
9768c2ecf20Sopenharmony_ci}
9778c2ecf20Sopenharmony_ci
9788c2ecf20Sopenharmony_cistatic ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to)
9798c2ecf20Sopenharmony_ci{
9808c2ecf20Sopenharmony_ci	struct file *file = iocb->ki_filp;
9818c2ecf20Sopenharmony_ci	struct socket *sock = file->private_data;
9828c2ecf20Sopenharmony_ci	struct msghdr msg = {.msg_iter = *to,
9838c2ecf20Sopenharmony_ci			     .msg_iocb = iocb};
9848c2ecf20Sopenharmony_ci	ssize_t res;
9858c2ecf20Sopenharmony_ci
9868c2ecf20Sopenharmony_ci	if (file->f_flags & O_NONBLOCK || (iocb->ki_flags & IOCB_NOWAIT))
9878c2ecf20Sopenharmony_ci		msg.msg_flags = MSG_DONTWAIT;
9888c2ecf20Sopenharmony_ci
9898c2ecf20Sopenharmony_ci	if (iocb->ki_pos != 0)
9908c2ecf20Sopenharmony_ci		return -ESPIPE;
9918c2ecf20Sopenharmony_ci
9928c2ecf20Sopenharmony_ci	if (!iov_iter_count(to))	/* Match SYS5 behaviour */
9938c2ecf20Sopenharmony_ci		return 0;
9948c2ecf20Sopenharmony_ci
9958c2ecf20Sopenharmony_ci	res = sock_recvmsg(sock, &msg, msg.msg_flags);
9968c2ecf20Sopenharmony_ci	*to = msg.msg_iter;
9978c2ecf20Sopenharmony_ci	return res;
9988c2ecf20Sopenharmony_ci}
9998c2ecf20Sopenharmony_ci
10008c2ecf20Sopenharmony_cistatic ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from)
10018c2ecf20Sopenharmony_ci{
10028c2ecf20Sopenharmony_ci	struct file *file = iocb->ki_filp;
10038c2ecf20Sopenharmony_ci	struct socket *sock = file->private_data;
10048c2ecf20Sopenharmony_ci	struct msghdr msg = {.msg_iter = *from,
10058c2ecf20Sopenharmony_ci			     .msg_iocb = iocb};
10068c2ecf20Sopenharmony_ci	ssize_t res;
10078c2ecf20Sopenharmony_ci
10088c2ecf20Sopenharmony_ci	if (iocb->ki_pos != 0)
10098c2ecf20Sopenharmony_ci		return -ESPIPE;
10108c2ecf20Sopenharmony_ci
10118c2ecf20Sopenharmony_ci	if (file->f_flags & O_NONBLOCK || (iocb->ki_flags & IOCB_NOWAIT))
10128c2ecf20Sopenharmony_ci		msg.msg_flags = MSG_DONTWAIT;
10138c2ecf20Sopenharmony_ci
10148c2ecf20Sopenharmony_ci	if (sock->type == SOCK_SEQPACKET)
10158c2ecf20Sopenharmony_ci		msg.msg_flags |= MSG_EOR;
10168c2ecf20Sopenharmony_ci
10178c2ecf20Sopenharmony_ci	res = __sock_sendmsg(sock, &msg);
10188c2ecf20Sopenharmony_ci	*from = msg.msg_iter;
10198c2ecf20Sopenharmony_ci	return res;
10208c2ecf20Sopenharmony_ci}
10218c2ecf20Sopenharmony_ci
10228c2ecf20Sopenharmony_ci/*
10238c2ecf20Sopenharmony_ci * Atomic setting of ioctl hooks to avoid race
10248c2ecf20Sopenharmony_ci * with module unload.
10258c2ecf20Sopenharmony_ci */
10268c2ecf20Sopenharmony_ci
10278c2ecf20Sopenharmony_cistatic DEFINE_MUTEX(br_ioctl_mutex);
10288c2ecf20Sopenharmony_cistatic int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg);
10298c2ecf20Sopenharmony_ci
10308c2ecf20Sopenharmony_civoid brioctl_set(int (*hook) (struct net *, unsigned int, void __user *))
10318c2ecf20Sopenharmony_ci{
10328c2ecf20Sopenharmony_ci	mutex_lock(&br_ioctl_mutex);
10338c2ecf20Sopenharmony_ci	br_ioctl_hook = hook;
10348c2ecf20Sopenharmony_ci	mutex_unlock(&br_ioctl_mutex);
10358c2ecf20Sopenharmony_ci}
10368c2ecf20Sopenharmony_ciEXPORT_SYMBOL(brioctl_set);
10378c2ecf20Sopenharmony_ci
10388c2ecf20Sopenharmony_cistatic DEFINE_MUTEX(vlan_ioctl_mutex);
10398c2ecf20Sopenharmony_cistatic int (*vlan_ioctl_hook) (struct net *, void __user *arg);
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_civoid vlan_ioctl_set(int (*hook) (struct net *, void __user *))
10428c2ecf20Sopenharmony_ci{
10438c2ecf20Sopenharmony_ci	mutex_lock(&vlan_ioctl_mutex);
10448c2ecf20Sopenharmony_ci	vlan_ioctl_hook = hook;
10458c2ecf20Sopenharmony_ci	mutex_unlock(&vlan_ioctl_mutex);
10468c2ecf20Sopenharmony_ci}
10478c2ecf20Sopenharmony_ciEXPORT_SYMBOL(vlan_ioctl_set);
10488c2ecf20Sopenharmony_ci
10498c2ecf20Sopenharmony_cistatic DEFINE_MUTEX(dlci_ioctl_mutex);
10508c2ecf20Sopenharmony_cistatic int (*dlci_ioctl_hook) (unsigned int, void __user *);
10518c2ecf20Sopenharmony_ci
10528c2ecf20Sopenharmony_civoid dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
10538c2ecf20Sopenharmony_ci{
10548c2ecf20Sopenharmony_ci	mutex_lock(&dlci_ioctl_mutex);
10558c2ecf20Sopenharmony_ci	dlci_ioctl_hook = hook;
10568c2ecf20Sopenharmony_ci	mutex_unlock(&dlci_ioctl_mutex);
10578c2ecf20Sopenharmony_ci}
10588c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dlci_ioctl_set);
10598c2ecf20Sopenharmony_ci
10608c2ecf20Sopenharmony_cistatic long sock_do_ioctl(struct net *net, struct socket *sock,
10618c2ecf20Sopenharmony_ci			  unsigned int cmd, unsigned long arg)
10628c2ecf20Sopenharmony_ci{
10638c2ecf20Sopenharmony_ci	int err;
10648c2ecf20Sopenharmony_ci	void __user *argp = (void __user *)arg;
10658c2ecf20Sopenharmony_ci
10668c2ecf20Sopenharmony_ci	err = sock->ops->ioctl(sock, cmd, arg);
10678c2ecf20Sopenharmony_ci
10688c2ecf20Sopenharmony_ci	/*
10698c2ecf20Sopenharmony_ci	 * If this ioctl is unknown try to hand it down
10708c2ecf20Sopenharmony_ci	 * to the NIC driver.
10718c2ecf20Sopenharmony_ci	 */
10728c2ecf20Sopenharmony_ci	if (err != -ENOIOCTLCMD)
10738c2ecf20Sopenharmony_ci		return err;
10748c2ecf20Sopenharmony_ci
10758c2ecf20Sopenharmony_ci	if (cmd == SIOCGIFCONF) {
10768c2ecf20Sopenharmony_ci		struct ifconf ifc;
10778c2ecf20Sopenharmony_ci		if (copy_from_user(&ifc, argp, sizeof(struct ifconf)))
10788c2ecf20Sopenharmony_ci			return -EFAULT;
10798c2ecf20Sopenharmony_ci		rtnl_lock();
10808c2ecf20Sopenharmony_ci		err = dev_ifconf(net, &ifc, sizeof(struct ifreq));
10818c2ecf20Sopenharmony_ci		rtnl_unlock();
10828c2ecf20Sopenharmony_ci		if (!err && copy_to_user(argp, &ifc, sizeof(struct ifconf)))
10838c2ecf20Sopenharmony_ci			err = -EFAULT;
10848c2ecf20Sopenharmony_ci	} else if (is_socket_ioctl_cmd(cmd)) {
10858c2ecf20Sopenharmony_ci		struct ifreq ifr;
10868c2ecf20Sopenharmony_ci		bool need_copyout;
10878c2ecf20Sopenharmony_ci		if (copy_from_user(&ifr, argp, sizeof(struct ifreq)))
10888c2ecf20Sopenharmony_ci			return -EFAULT;
10898c2ecf20Sopenharmony_ci		err = dev_ioctl(net, cmd, &ifr, &need_copyout);
10908c2ecf20Sopenharmony_ci		if (!err && need_copyout)
10918c2ecf20Sopenharmony_ci			if (copy_to_user(argp, &ifr, sizeof(struct ifreq)))
10928c2ecf20Sopenharmony_ci				return -EFAULT;
10938c2ecf20Sopenharmony_ci	} else {
10948c2ecf20Sopenharmony_ci		err = -ENOTTY;
10958c2ecf20Sopenharmony_ci	}
10968c2ecf20Sopenharmony_ci	return err;
10978c2ecf20Sopenharmony_ci}
10988c2ecf20Sopenharmony_ci
10998c2ecf20Sopenharmony_ci/*
11008c2ecf20Sopenharmony_ci *	With an ioctl, arg may well be a user mode pointer, but we don't know
11018c2ecf20Sopenharmony_ci *	what to do with it - that's up to the protocol still.
11028c2ecf20Sopenharmony_ci */
11038c2ecf20Sopenharmony_ci
11048c2ecf20Sopenharmony_cistatic long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
11058c2ecf20Sopenharmony_ci{
11068c2ecf20Sopenharmony_ci	struct socket *sock;
11078c2ecf20Sopenharmony_ci	struct sock *sk;
11088c2ecf20Sopenharmony_ci	void __user *argp = (void __user *)arg;
11098c2ecf20Sopenharmony_ci	int pid, err;
11108c2ecf20Sopenharmony_ci	struct net *net;
11118c2ecf20Sopenharmony_ci
11128c2ecf20Sopenharmony_ci	sock = file->private_data;
11138c2ecf20Sopenharmony_ci	sk = sock->sk;
11148c2ecf20Sopenharmony_ci	net = sock_net(sk);
11158c2ecf20Sopenharmony_ci	if (unlikely(cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))) {
11168c2ecf20Sopenharmony_ci		struct ifreq ifr;
11178c2ecf20Sopenharmony_ci		bool need_copyout;
11188c2ecf20Sopenharmony_ci		if (copy_from_user(&ifr, argp, sizeof(struct ifreq)))
11198c2ecf20Sopenharmony_ci			return -EFAULT;
11208c2ecf20Sopenharmony_ci		err = dev_ioctl(net, cmd, &ifr, &need_copyout);
11218c2ecf20Sopenharmony_ci		if (!err && need_copyout)
11228c2ecf20Sopenharmony_ci			if (copy_to_user(argp, &ifr, sizeof(struct ifreq)))
11238c2ecf20Sopenharmony_ci				return -EFAULT;
11248c2ecf20Sopenharmony_ci	} else
11258c2ecf20Sopenharmony_ci#ifdef CONFIG_WEXT_CORE
11268c2ecf20Sopenharmony_ci	if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
11278c2ecf20Sopenharmony_ci		err = wext_handle_ioctl(net, cmd, argp);
11288c2ecf20Sopenharmony_ci	} else
11298c2ecf20Sopenharmony_ci#endif
11308c2ecf20Sopenharmony_ci		switch (cmd) {
11318c2ecf20Sopenharmony_ci		case FIOSETOWN:
11328c2ecf20Sopenharmony_ci		case SIOCSPGRP:
11338c2ecf20Sopenharmony_ci			err = -EFAULT;
11348c2ecf20Sopenharmony_ci			if (get_user(pid, (int __user *)argp))
11358c2ecf20Sopenharmony_ci				break;
11368c2ecf20Sopenharmony_ci			err = f_setown(sock->file, pid, 1);
11378c2ecf20Sopenharmony_ci			break;
11388c2ecf20Sopenharmony_ci		case FIOGETOWN:
11398c2ecf20Sopenharmony_ci		case SIOCGPGRP:
11408c2ecf20Sopenharmony_ci			err = put_user(f_getown(sock->file),
11418c2ecf20Sopenharmony_ci				       (int __user *)argp);
11428c2ecf20Sopenharmony_ci			break;
11438c2ecf20Sopenharmony_ci		case SIOCGIFBR:
11448c2ecf20Sopenharmony_ci		case SIOCSIFBR:
11458c2ecf20Sopenharmony_ci		case SIOCBRADDBR:
11468c2ecf20Sopenharmony_ci		case SIOCBRDELBR:
11478c2ecf20Sopenharmony_ci			err = -ENOPKG;
11488c2ecf20Sopenharmony_ci			if (!br_ioctl_hook)
11498c2ecf20Sopenharmony_ci				request_module("bridge");
11508c2ecf20Sopenharmony_ci
11518c2ecf20Sopenharmony_ci			mutex_lock(&br_ioctl_mutex);
11528c2ecf20Sopenharmony_ci			if (br_ioctl_hook)
11538c2ecf20Sopenharmony_ci				err = br_ioctl_hook(net, cmd, argp);
11548c2ecf20Sopenharmony_ci			mutex_unlock(&br_ioctl_mutex);
11558c2ecf20Sopenharmony_ci			break;
11568c2ecf20Sopenharmony_ci		case SIOCGIFVLAN:
11578c2ecf20Sopenharmony_ci		case SIOCSIFVLAN:
11588c2ecf20Sopenharmony_ci			err = -ENOPKG;
11598c2ecf20Sopenharmony_ci			if (!vlan_ioctl_hook)
11608c2ecf20Sopenharmony_ci				request_module("8021q");
11618c2ecf20Sopenharmony_ci
11628c2ecf20Sopenharmony_ci			mutex_lock(&vlan_ioctl_mutex);
11638c2ecf20Sopenharmony_ci			if (vlan_ioctl_hook)
11648c2ecf20Sopenharmony_ci				err = vlan_ioctl_hook(net, argp);
11658c2ecf20Sopenharmony_ci			mutex_unlock(&vlan_ioctl_mutex);
11668c2ecf20Sopenharmony_ci			break;
11678c2ecf20Sopenharmony_ci		case SIOCADDDLCI:
11688c2ecf20Sopenharmony_ci		case SIOCDELDLCI:
11698c2ecf20Sopenharmony_ci			err = -ENOPKG;
11708c2ecf20Sopenharmony_ci			if (!dlci_ioctl_hook)
11718c2ecf20Sopenharmony_ci				request_module("dlci");
11728c2ecf20Sopenharmony_ci
11738c2ecf20Sopenharmony_ci			mutex_lock(&dlci_ioctl_mutex);
11748c2ecf20Sopenharmony_ci			if (dlci_ioctl_hook)
11758c2ecf20Sopenharmony_ci				err = dlci_ioctl_hook(cmd, argp);
11768c2ecf20Sopenharmony_ci			mutex_unlock(&dlci_ioctl_mutex);
11778c2ecf20Sopenharmony_ci			break;
11788c2ecf20Sopenharmony_ci		case SIOCGSKNS:
11798c2ecf20Sopenharmony_ci			err = -EPERM;
11808c2ecf20Sopenharmony_ci			if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
11818c2ecf20Sopenharmony_ci				break;
11828c2ecf20Sopenharmony_ci
11838c2ecf20Sopenharmony_ci			err = open_related_ns(&net->ns, get_net_ns);
11848c2ecf20Sopenharmony_ci			break;
11858c2ecf20Sopenharmony_ci		case SIOCGSTAMP_OLD:
11868c2ecf20Sopenharmony_ci		case SIOCGSTAMPNS_OLD:
11878c2ecf20Sopenharmony_ci			if (!sock->ops->gettstamp) {
11888c2ecf20Sopenharmony_ci				err = -ENOIOCTLCMD;
11898c2ecf20Sopenharmony_ci				break;
11908c2ecf20Sopenharmony_ci			}
11918c2ecf20Sopenharmony_ci			err = sock->ops->gettstamp(sock, argp,
11928c2ecf20Sopenharmony_ci						   cmd == SIOCGSTAMP_OLD,
11938c2ecf20Sopenharmony_ci						   !IS_ENABLED(CONFIG_64BIT));
11948c2ecf20Sopenharmony_ci			break;
11958c2ecf20Sopenharmony_ci		case SIOCGSTAMP_NEW:
11968c2ecf20Sopenharmony_ci		case SIOCGSTAMPNS_NEW:
11978c2ecf20Sopenharmony_ci			if (!sock->ops->gettstamp) {
11988c2ecf20Sopenharmony_ci				err = -ENOIOCTLCMD;
11998c2ecf20Sopenharmony_ci				break;
12008c2ecf20Sopenharmony_ci			}
12018c2ecf20Sopenharmony_ci			err = sock->ops->gettstamp(sock, argp,
12028c2ecf20Sopenharmony_ci						   cmd == SIOCGSTAMP_NEW,
12038c2ecf20Sopenharmony_ci						   false);
12048c2ecf20Sopenharmony_ci			break;
12058c2ecf20Sopenharmony_ci		default:
12068c2ecf20Sopenharmony_ci			err = sock_do_ioctl(net, sock, cmd, arg);
12078c2ecf20Sopenharmony_ci			break;
12088c2ecf20Sopenharmony_ci		}
12098c2ecf20Sopenharmony_ci	return err;
12108c2ecf20Sopenharmony_ci}
12118c2ecf20Sopenharmony_ci
12128c2ecf20Sopenharmony_ci/**
12138c2ecf20Sopenharmony_ci *	sock_create_lite - creates a socket
12148c2ecf20Sopenharmony_ci *	@family: protocol family (AF_INET, ...)
12158c2ecf20Sopenharmony_ci *	@type: communication type (SOCK_STREAM, ...)
12168c2ecf20Sopenharmony_ci *	@protocol: protocol (0, ...)
12178c2ecf20Sopenharmony_ci *	@res: new socket
12188c2ecf20Sopenharmony_ci *
12198c2ecf20Sopenharmony_ci *	Creates a new socket and assigns it to @res, passing through LSM.
12208c2ecf20Sopenharmony_ci *	The new socket initialization is not complete, see kernel_accept().
12218c2ecf20Sopenharmony_ci *	Returns 0 or an error. On failure @res is set to %NULL.
12228c2ecf20Sopenharmony_ci *	This function internally uses GFP_KERNEL.
12238c2ecf20Sopenharmony_ci */
12248c2ecf20Sopenharmony_ci
12258c2ecf20Sopenharmony_ciint sock_create_lite(int family, int type, int protocol, struct socket **res)
12268c2ecf20Sopenharmony_ci{
12278c2ecf20Sopenharmony_ci	int err;
12288c2ecf20Sopenharmony_ci	struct socket *sock = NULL;
12298c2ecf20Sopenharmony_ci
12308c2ecf20Sopenharmony_ci	err = security_socket_create(family, type, protocol, 1);
12318c2ecf20Sopenharmony_ci	if (err)
12328c2ecf20Sopenharmony_ci		goto out;
12338c2ecf20Sopenharmony_ci
12348c2ecf20Sopenharmony_ci	sock = sock_alloc();
12358c2ecf20Sopenharmony_ci	if (!sock) {
12368c2ecf20Sopenharmony_ci		err = -ENOMEM;
12378c2ecf20Sopenharmony_ci		goto out;
12388c2ecf20Sopenharmony_ci	}
12398c2ecf20Sopenharmony_ci
12408c2ecf20Sopenharmony_ci	sock->type = type;
12418c2ecf20Sopenharmony_ci	err = security_socket_post_create(sock, family, type, protocol, 1);
12428c2ecf20Sopenharmony_ci	if (err)
12438c2ecf20Sopenharmony_ci		goto out_release;
12448c2ecf20Sopenharmony_ci
12458c2ecf20Sopenharmony_ciout:
12468c2ecf20Sopenharmony_ci	*res = sock;
12478c2ecf20Sopenharmony_ci	return err;
12488c2ecf20Sopenharmony_ciout_release:
12498c2ecf20Sopenharmony_ci	sock_release(sock);
12508c2ecf20Sopenharmony_ci	sock = NULL;
12518c2ecf20Sopenharmony_ci	goto out;
12528c2ecf20Sopenharmony_ci}
12538c2ecf20Sopenharmony_ciEXPORT_SYMBOL(sock_create_lite);
12548c2ecf20Sopenharmony_ci
12558c2ecf20Sopenharmony_ci/* No kernel lock held - perfect */
12568c2ecf20Sopenharmony_cistatic __poll_t sock_poll(struct file *file, poll_table *wait)
12578c2ecf20Sopenharmony_ci{
12588c2ecf20Sopenharmony_ci	struct socket *sock = file->private_data;
12598c2ecf20Sopenharmony_ci	__poll_t events = poll_requested_events(wait), flag = 0;
12608c2ecf20Sopenharmony_ci
12618c2ecf20Sopenharmony_ci	if (!sock->ops->poll)
12628c2ecf20Sopenharmony_ci		return 0;
12638c2ecf20Sopenharmony_ci
12648c2ecf20Sopenharmony_ci	if (sk_can_busy_loop(sock->sk)) {
12658c2ecf20Sopenharmony_ci		/* poll once if requested by the syscall */
12668c2ecf20Sopenharmony_ci		if (events & POLL_BUSY_LOOP)
12678c2ecf20Sopenharmony_ci			sk_busy_loop(sock->sk, 1);
12688c2ecf20Sopenharmony_ci
12698c2ecf20Sopenharmony_ci		/* if this socket can poll_ll, tell the system call */
12708c2ecf20Sopenharmony_ci		flag = POLL_BUSY_LOOP;
12718c2ecf20Sopenharmony_ci	}
12728c2ecf20Sopenharmony_ci
12738c2ecf20Sopenharmony_ci	return sock->ops->poll(file, sock, wait) | flag;
12748c2ecf20Sopenharmony_ci}
12758c2ecf20Sopenharmony_ci
12768c2ecf20Sopenharmony_cistatic int sock_mmap(struct file *file, struct vm_area_struct *vma)
12778c2ecf20Sopenharmony_ci{
12788c2ecf20Sopenharmony_ci	struct socket *sock = file->private_data;
12798c2ecf20Sopenharmony_ci
12808c2ecf20Sopenharmony_ci	return sock->ops->mmap(file, sock, vma);
12818c2ecf20Sopenharmony_ci}
12828c2ecf20Sopenharmony_ci
12838c2ecf20Sopenharmony_cistatic int sock_close(struct inode *inode, struct file *filp)
12848c2ecf20Sopenharmony_ci{
12858c2ecf20Sopenharmony_ci	__sock_release(SOCKET_I(inode), inode);
12868c2ecf20Sopenharmony_ci	return 0;
12878c2ecf20Sopenharmony_ci}
12888c2ecf20Sopenharmony_ci
12898c2ecf20Sopenharmony_ci/*
12908c2ecf20Sopenharmony_ci *	Update the socket async list
12918c2ecf20Sopenharmony_ci *
12928c2ecf20Sopenharmony_ci *	Fasync_list locking strategy.
12938c2ecf20Sopenharmony_ci *
12948c2ecf20Sopenharmony_ci *	1. fasync_list is modified only under process context socket lock
12958c2ecf20Sopenharmony_ci *	   i.e. under semaphore.
12968c2ecf20Sopenharmony_ci *	2. fasync_list is used under read_lock(&sk->sk_callback_lock)
12978c2ecf20Sopenharmony_ci *	   or under socket lock
12988c2ecf20Sopenharmony_ci */
12998c2ecf20Sopenharmony_ci
13008c2ecf20Sopenharmony_cistatic int sock_fasync(int fd, struct file *filp, int on)
13018c2ecf20Sopenharmony_ci{
13028c2ecf20Sopenharmony_ci	struct socket *sock = filp->private_data;
13038c2ecf20Sopenharmony_ci	struct sock *sk = sock->sk;
13048c2ecf20Sopenharmony_ci	struct socket_wq *wq = &sock->wq;
13058c2ecf20Sopenharmony_ci
13068c2ecf20Sopenharmony_ci	if (sk == NULL)
13078c2ecf20Sopenharmony_ci		return -EINVAL;
13088c2ecf20Sopenharmony_ci
13098c2ecf20Sopenharmony_ci	lock_sock(sk);
13108c2ecf20Sopenharmony_ci	fasync_helper(fd, filp, on, &wq->fasync_list);
13118c2ecf20Sopenharmony_ci
13128c2ecf20Sopenharmony_ci	if (!wq->fasync_list)
13138c2ecf20Sopenharmony_ci		sock_reset_flag(sk, SOCK_FASYNC);
13148c2ecf20Sopenharmony_ci	else
13158c2ecf20Sopenharmony_ci		sock_set_flag(sk, SOCK_FASYNC);
13168c2ecf20Sopenharmony_ci
13178c2ecf20Sopenharmony_ci	release_sock(sk);
13188c2ecf20Sopenharmony_ci	return 0;
13198c2ecf20Sopenharmony_ci}
13208c2ecf20Sopenharmony_ci
13218c2ecf20Sopenharmony_ci/* This function may be called only under rcu_lock */
13228c2ecf20Sopenharmony_ci
13238c2ecf20Sopenharmony_ciint sock_wake_async(struct socket_wq *wq, int how, int band)
13248c2ecf20Sopenharmony_ci{
13258c2ecf20Sopenharmony_ci	if (!wq || !wq->fasync_list)
13268c2ecf20Sopenharmony_ci		return -1;
13278c2ecf20Sopenharmony_ci
13288c2ecf20Sopenharmony_ci	switch (how) {
13298c2ecf20Sopenharmony_ci	case SOCK_WAKE_WAITD:
13308c2ecf20Sopenharmony_ci		if (test_bit(SOCKWQ_ASYNC_WAITDATA, &wq->flags))
13318c2ecf20Sopenharmony_ci			break;
13328c2ecf20Sopenharmony_ci		goto call_kill;
13338c2ecf20Sopenharmony_ci	case SOCK_WAKE_SPACE:
13348c2ecf20Sopenharmony_ci		if (!test_and_clear_bit(SOCKWQ_ASYNC_NOSPACE, &wq->flags))
13358c2ecf20Sopenharmony_ci			break;
13368c2ecf20Sopenharmony_ci		fallthrough;
13378c2ecf20Sopenharmony_ci	case SOCK_WAKE_IO:
13388c2ecf20Sopenharmony_cicall_kill:
13398c2ecf20Sopenharmony_ci		kill_fasync(&wq->fasync_list, SIGIO, band);
13408c2ecf20Sopenharmony_ci		break;
13418c2ecf20Sopenharmony_ci	case SOCK_WAKE_URG:
13428c2ecf20Sopenharmony_ci		kill_fasync(&wq->fasync_list, SIGURG, band);
13438c2ecf20Sopenharmony_ci	}
13448c2ecf20Sopenharmony_ci
13458c2ecf20Sopenharmony_ci	return 0;
13468c2ecf20Sopenharmony_ci}
13478c2ecf20Sopenharmony_ciEXPORT_SYMBOL(sock_wake_async);
13488c2ecf20Sopenharmony_ci
13498c2ecf20Sopenharmony_ci/**
13508c2ecf20Sopenharmony_ci *	__sock_create - creates a socket
13518c2ecf20Sopenharmony_ci *	@net: net namespace
13528c2ecf20Sopenharmony_ci *	@family: protocol family (AF_INET, ...)
13538c2ecf20Sopenharmony_ci *	@type: communication type (SOCK_STREAM, ...)
13548c2ecf20Sopenharmony_ci *	@protocol: protocol (0, ...)
13558c2ecf20Sopenharmony_ci *	@res: new socket
13568c2ecf20Sopenharmony_ci *	@kern: boolean for kernel space sockets
13578c2ecf20Sopenharmony_ci *
13588c2ecf20Sopenharmony_ci *	Creates a new socket and assigns it to @res, passing through LSM.
13598c2ecf20Sopenharmony_ci *	Returns 0 or an error. On failure @res is set to %NULL. @kern must
13608c2ecf20Sopenharmony_ci *	be set to true if the socket resides in kernel space.
13618c2ecf20Sopenharmony_ci *	This function internally uses GFP_KERNEL.
13628c2ecf20Sopenharmony_ci */
13638c2ecf20Sopenharmony_ci
13648c2ecf20Sopenharmony_ciint __sock_create(struct net *net, int family, int type, int protocol,
13658c2ecf20Sopenharmony_ci			 struct socket **res, int kern)
13668c2ecf20Sopenharmony_ci{
13678c2ecf20Sopenharmony_ci	int err;
13688c2ecf20Sopenharmony_ci	struct socket *sock;
13698c2ecf20Sopenharmony_ci	const struct net_proto_family *pf;
13708c2ecf20Sopenharmony_ci
13718c2ecf20Sopenharmony_ci	/*
13728c2ecf20Sopenharmony_ci	 *      Check protocol is in range
13738c2ecf20Sopenharmony_ci	 */
13748c2ecf20Sopenharmony_ci	if (family < 0 || family >= NPROTO)
13758c2ecf20Sopenharmony_ci		return -EAFNOSUPPORT;
13768c2ecf20Sopenharmony_ci	if (type < 0 || type >= SOCK_MAX)
13778c2ecf20Sopenharmony_ci		return -EINVAL;
13788c2ecf20Sopenharmony_ci
13798c2ecf20Sopenharmony_ci	/* Compatibility.
13808c2ecf20Sopenharmony_ci
13818c2ecf20Sopenharmony_ci	   This uglymoron is moved from INET layer to here to avoid
13828c2ecf20Sopenharmony_ci	   deadlock in module load.
13838c2ecf20Sopenharmony_ci	 */
13848c2ecf20Sopenharmony_ci	if (family == PF_INET && type == SOCK_PACKET) {
13858c2ecf20Sopenharmony_ci		pr_info_once("%s uses obsolete (PF_INET,SOCK_PACKET)\n",
13868c2ecf20Sopenharmony_ci			     current->comm);
13878c2ecf20Sopenharmony_ci		family = PF_PACKET;
13888c2ecf20Sopenharmony_ci	}
13898c2ecf20Sopenharmony_ci
13908c2ecf20Sopenharmony_ci	err = security_socket_create(family, type, protocol, kern);
13918c2ecf20Sopenharmony_ci	if (err)
13928c2ecf20Sopenharmony_ci		return err;
13938c2ecf20Sopenharmony_ci
13948c2ecf20Sopenharmony_ci	/*
13958c2ecf20Sopenharmony_ci	 *	Allocate the socket and allow the family to set things up. if
13968c2ecf20Sopenharmony_ci	 *	the protocol is 0, the family is instructed to select an appropriate
13978c2ecf20Sopenharmony_ci	 *	default.
13988c2ecf20Sopenharmony_ci	 */
13998c2ecf20Sopenharmony_ci	sock = sock_alloc();
14008c2ecf20Sopenharmony_ci	if (!sock) {
14018c2ecf20Sopenharmony_ci		net_warn_ratelimited("socket: no more sockets\n");
14028c2ecf20Sopenharmony_ci		return -ENFILE;	/* Not exactly a match, but its the
14038c2ecf20Sopenharmony_ci				   closest posix thing */
14048c2ecf20Sopenharmony_ci	}
14058c2ecf20Sopenharmony_ci
14068c2ecf20Sopenharmony_ci	sock->type = type;
14078c2ecf20Sopenharmony_ci
14088c2ecf20Sopenharmony_ci#ifdef CONFIG_MODULES
14098c2ecf20Sopenharmony_ci	/* Attempt to load a protocol module if the find failed.
14108c2ecf20Sopenharmony_ci	 *
14118c2ecf20Sopenharmony_ci	 * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
14128c2ecf20Sopenharmony_ci	 * requested real, full-featured networking support upon configuration.
14138c2ecf20Sopenharmony_ci	 * Otherwise module support will break!
14148c2ecf20Sopenharmony_ci	 */
14158c2ecf20Sopenharmony_ci	if (rcu_access_pointer(net_families[family]) == NULL)
14168c2ecf20Sopenharmony_ci		request_module("net-pf-%d", family);
14178c2ecf20Sopenharmony_ci#endif
14188c2ecf20Sopenharmony_ci
14198c2ecf20Sopenharmony_ci	rcu_read_lock();
14208c2ecf20Sopenharmony_ci	pf = rcu_dereference(net_families[family]);
14218c2ecf20Sopenharmony_ci	err = -EAFNOSUPPORT;
14228c2ecf20Sopenharmony_ci	if (!pf)
14238c2ecf20Sopenharmony_ci		goto out_release;
14248c2ecf20Sopenharmony_ci
14258c2ecf20Sopenharmony_ci	/*
14268c2ecf20Sopenharmony_ci	 * We will call the ->create function, that possibly is in a loadable
14278c2ecf20Sopenharmony_ci	 * module, so we have to bump that loadable module refcnt first.
14288c2ecf20Sopenharmony_ci	 */
14298c2ecf20Sopenharmony_ci	if (!try_module_get(pf->owner))
14308c2ecf20Sopenharmony_ci		goto out_release;
14318c2ecf20Sopenharmony_ci
14328c2ecf20Sopenharmony_ci	/* Now protected by module ref count */
14338c2ecf20Sopenharmony_ci	rcu_read_unlock();
14348c2ecf20Sopenharmony_ci
14358c2ecf20Sopenharmony_ci	err = pf->create(net, sock, protocol, kern);
14368c2ecf20Sopenharmony_ci	if (err < 0)
14378c2ecf20Sopenharmony_ci		goto out_module_put;
14388c2ecf20Sopenharmony_ci
14398c2ecf20Sopenharmony_ci	/*
14408c2ecf20Sopenharmony_ci	 * Now to bump the refcnt of the [loadable] module that owns this
14418c2ecf20Sopenharmony_ci	 * socket at sock_release time we decrement its refcnt.
14428c2ecf20Sopenharmony_ci	 */
14438c2ecf20Sopenharmony_ci	if (!try_module_get(sock->ops->owner))
14448c2ecf20Sopenharmony_ci		goto out_module_busy;
14458c2ecf20Sopenharmony_ci
14468c2ecf20Sopenharmony_ci	/*
14478c2ecf20Sopenharmony_ci	 * Now that we're done with the ->create function, the [loadable]
14488c2ecf20Sopenharmony_ci	 * module can have its refcnt decremented
14498c2ecf20Sopenharmony_ci	 */
14508c2ecf20Sopenharmony_ci	module_put(pf->owner);
14518c2ecf20Sopenharmony_ci	err = security_socket_post_create(sock, family, type, protocol, kern);
14528c2ecf20Sopenharmony_ci	if (err)
14538c2ecf20Sopenharmony_ci		goto out_sock_release;
14548c2ecf20Sopenharmony_ci	*res = sock;
14558c2ecf20Sopenharmony_ci
14568c2ecf20Sopenharmony_ci	return 0;
14578c2ecf20Sopenharmony_ci
14588c2ecf20Sopenharmony_ciout_module_busy:
14598c2ecf20Sopenharmony_ci	err = -EAFNOSUPPORT;
14608c2ecf20Sopenharmony_ciout_module_put:
14618c2ecf20Sopenharmony_ci	sock->ops = NULL;
14628c2ecf20Sopenharmony_ci	module_put(pf->owner);
14638c2ecf20Sopenharmony_ciout_sock_release:
14648c2ecf20Sopenharmony_ci	sock_release(sock);
14658c2ecf20Sopenharmony_ci	return err;
14668c2ecf20Sopenharmony_ci
14678c2ecf20Sopenharmony_ciout_release:
14688c2ecf20Sopenharmony_ci	rcu_read_unlock();
14698c2ecf20Sopenharmony_ci	goto out_sock_release;
14708c2ecf20Sopenharmony_ci}
14718c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__sock_create);
14728c2ecf20Sopenharmony_ci
14738c2ecf20Sopenharmony_ci/**
14748c2ecf20Sopenharmony_ci *	sock_create - creates a socket
14758c2ecf20Sopenharmony_ci *	@family: protocol family (AF_INET, ...)
14768c2ecf20Sopenharmony_ci *	@type: communication type (SOCK_STREAM, ...)
14778c2ecf20Sopenharmony_ci *	@protocol: protocol (0, ...)
14788c2ecf20Sopenharmony_ci *	@res: new socket
14798c2ecf20Sopenharmony_ci *
14808c2ecf20Sopenharmony_ci *	A wrapper around __sock_create().
14818c2ecf20Sopenharmony_ci *	Returns 0 or an error. This function internally uses GFP_KERNEL.
14828c2ecf20Sopenharmony_ci */
14838c2ecf20Sopenharmony_ci
14848c2ecf20Sopenharmony_ciint sock_create(int family, int type, int protocol, struct socket **res)
14858c2ecf20Sopenharmony_ci{
14868c2ecf20Sopenharmony_ci	return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
14878c2ecf20Sopenharmony_ci}
14888c2ecf20Sopenharmony_ciEXPORT_SYMBOL(sock_create);
14898c2ecf20Sopenharmony_ci
14908c2ecf20Sopenharmony_ci/**
14918c2ecf20Sopenharmony_ci *	sock_create_kern - creates a socket (kernel space)
14928c2ecf20Sopenharmony_ci *	@net: net namespace
14938c2ecf20Sopenharmony_ci *	@family: protocol family (AF_INET, ...)
14948c2ecf20Sopenharmony_ci *	@type: communication type (SOCK_STREAM, ...)
14958c2ecf20Sopenharmony_ci *	@protocol: protocol (0, ...)
14968c2ecf20Sopenharmony_ci *	@res: new socket
14978c2ecf20Sopenharmony_ci *
14988c2ecf20Sopenharmony_ci *	A wrapper around __sock_create().
14998c2ecf20Sopenharmony_ci *	Returns 0 or an error. This function internally uses GFP_KERNEL.
15008c2ecf20Sopenharmony_ci */
15018c2ecf20Sopenharmony_ci
15028c2ecf20Sopenharmony_ciint sock_create_kern(struct net *net, int family, int type, int protocol, struct socket **res)
15038c2ecf20Sopenharmony_ci{
15048c2ecf20Sopenharmony_ci	return __sock_create(net, family, type, protocol, res, 1);
15058c2ecf20Sopenharmony_ci}
15068c2ecf20Sopenharmony_ciEXPORT_SYMBOL(sock_create_kern);
15078c2ecf20Sopenharmony_ci
15088c2ecf20Sopenharmony_ciint __sys_socket(int family, int type, int protocol)
15098c2ecf20Sopenharmony_ci{
15108c2ecf20Sopenharmony_ci	int retval;
15118c2ecf20Sopenharmony_ci	struct socket *sock;
15128c2ecf20Sopenharmony_ci	int flags;
15138c2ecf20Sopenharmony_ci
15148c2ecf20Sopenharmony_ci	/* Check the SOCK_* constants for consistency.  */
15158c2ecf20Sopenharmony_ci	BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
15168c2ecf20Sopenharmony_ci	BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
15178c2ecf20Sopenharmony_ci	BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);
15188c2ecf20Sopenharmony_ci	BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);
15198c2ecf20Sopenharmony_ci
15208c2ecf20Sopenharmony_ci	flags = type & ~SOCK_TYPE_MASK;
15218c2ecf20Sopenharmony_ci	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
15228c2ecf20Sopenharmony_ci		return -EINVAL;
15238c2ecf20Sopenharmony_ci	type &= SOCK_TYPE_MASK;
15248c2ecf20Sopenharmony_ci
15258c2ecf20Sopenharmony_ci	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
15268c2ecf20Sopenharmony_ci		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
15278c2ecf20Sopenharmony_ci
15288c2ecf20Sopenharmony_ci	retval = sock_create(family, type, protocol, &sock);
15298c2ecf20Sopenharmony_ci	if (retval < 0)
15308c2ecf20Sopenharmony_ci		return retval;
15318c2ecf20Sopenharmony_ci
15328c2ecf20Sopenharmony_ci	return sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
15338c2ecf20Sopenharmony_ci}
15348c2ecf20Sopenharmony_ci
15358c2ecf20Sopenharmony_ciSYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
15368c2ecf20Sopenharmony_ci{
15378c2ecf20Sopenharmony_ci	return __sys_socket(family, type, protocol);
15388c2ecf20Sopenharmony_ci}
15398c2ecf20Sopenharmony_ci
15408c2ecf20Sopenharmony_ci/*
15418c2ecf20Sopenharmony_ci *	Create a pair of connected sockets.
15428c2ecf20Sopenharmony_ci */
15438c2ecf20Sopenharmony_ci
15448c2ecf20Sopenharmony_ciint __sys_socketpair(int family, int type, int protocol, int __user *usockvec)
15458c2ecf20Sopenharmony_ci{
15468c2ecf20Sopenharmony_ci	struct socket *sock1, *sock2;
15478c2ecf20Sopenharmony_ci	int fd1, fd2, err;
15488c2ecf20Sopenharmony_ci	struct file *newfile1, *newfile2;
15498c2ecf20Sopenharmony_ci	int flags;
15508c2ecf20Sopenharmony_ci
15518c2ecf20Sopenharmony_ci	flags = type & ~SOCK_TYPE_MASK;
15528c2ecf20Sopenharmony_ci	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
15538c2ecf20Sopenharmony_ci		return -EINVAL;
15548c2ecf20Sopenharmony_ci	type &= SOCK_TYPE_MASK;
15558c2ecf20Sopenharmony_ci
15568c2ecf20Sopenharmony_ci	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
15578c2ecf20Sopenharmony_ci		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
15588c2ecf20Sopenharmony_ci
15598c2ecf20Sopenharmony_ci	/*
15608c2ecf20Sopenharmony_ci	 * reserve descriptors and make sure we won't fail
15618c2ecf20Sopenharmony_ci	 * to return them to userland.
15628c2ecf20Sopenharmony_ci	 */
15638c2ecf20Sopenharmony_ci	fd1 = get_unused_fd_flags(flags);
15648c2ecf20Sopenharmony_ci	if (unlikely(fd1 < 0))
15658c2ecf20Sopenharmony_ci		return fd1;
15668c2ecf20Sopenharmony_ci
15678c2ecf20Sopenharmony_ci	fd2 = get_unused_fd_flags(flags);
15688c2ecf20Sopenharmony_ci	if (unlikely(fd2 < 0)) {
15698c2ecf20Sopenharmony_ci		put_unused_fd(fd1);
15708c2ecf20Sopenharmony_ci		return fd2;
15718c2ecf20Sopenharmony_ci	}
15728c2ecf20Sopenharmony_ci
15738c2ecf20Sopenharmony_ci	err = put_user(fd1, &usockvec[0]);
15748c2ecf20Sopenharmony_ci	if (err)
15758c2ecf20Sopenharmony_ci		goto out;
15768c2ecf20Sopenharmony_ci
15778c2ecf20Sopenharmony_ci	err = put_user(fd2, &usockvec[1]);
15788c2ecf20Sopenharmony_ci	if (err)
15798c2ecf20Sopenharmony_ci		goto out;
15808c2ecf20Sopenharmony_ci
15818c2ecf20Sopenharmony_ci	/*
15828c2ecf20Sopenharmony_ci	 * Obtain the first socket and check if the underlying protocol
15838c2ecf20Sopenharmony_ci	 * supports the socketpair call.
15848c2ecf20Sopenharmony_ci	 */
15858c2ecf20Sopenharmony_ci
15868c2ecf20Sopenharmony_ci	err = sock_create(family, type, protocol, &sock1);
15878c2ecf20Sopenharmony_ci	if (unlikely(err < 0))
15888c2ecf20Sopenharmony_ci		goto out;
15898c2ecf20Sopenharmony_ci
15908c2ecf20Sopenharmony_ci	err = sock_create(family, type, protocol, &sock2);
15918c2ecf20Sopenharmony_ci	if (unlikely(err < 0)) {
15928c2ecf20Sopenharmony_ci		sock_release(sock1);
15938c2ecf20Sopenharmony_ci		goto out;
15948c2ecf20Sopenharmony_ci	}
15958c2ecf20Sopenharmony_ci
15968c2ecf20Sopenharmony_ci	err = security_socket_socketpair(sock1, sock2);
15978c2ecf20Sopenharmony_ci	if (unlikely(err)) {
15988c2ecf20Sopenharmony_ci		sock_release(sock2);
15998c2ecf20Sopenharmony_ci		sock_release(sock1);
16008c2ecf20Sopenharmony_ci		goto out;
16018c2ecf20Sopenharmony_ci	}
16028c2ecf20Sopenharmony_ci
16038c2ecf20Sopenharmony_ci	err = sock1->ops->socketpair(sock1, sock2);
16048c2ecf20Sopenharmony_ci	if (unlikely(err < 0)) {
16058c2ecf20Sopenharmony_ci		sock_release(sock2);
16068c2ecf20Sopenharmony_ci		sock_release(sock1);
16078c2ecf20Sopenharmony_ci		goto out;
16088c2ecf20Sopenharmony_ci	}
16098c2ecf20Sopenharmony_ci
16108c2ecf20Sopenharmony_ci	newfile1 = sock_alloc_file(sock1, flags, NULL);
16118c2ecf20Sopenharmony_ci	if (IS_ERR(newfile1)) {
16128c2ecf20Sopenharmony_ci		err = PTR_ERR(newfile1);
16138c2ecf20Sopenharmony_ci		sock_release(sock2);
16148c2ecf20Sopenharmony_ci		goto out;
16158c2ecf20Sopenharmony_ci	}
16168c2ecf20Sopenharmony_ci
16178c2ecf20Sopenharmony_ci	newfile2 = sock_alloc_file(sock2, flags, NULL);
16188c2ecf20Sopenharmony_ci	if (IS_ERR(newfile2)) {
16198c2ecf20Sopenharmony_ci		err = PTR_ERR(newfile2);
16208c2ecf20Sopenharmony_ci		fput(newfile1);
16218c2ecf20Sopenharmony_ci		goto out;
16228c2ecf20Sopenharmony_ci	}
16238c2ecf20Sopenharmony_ci
16248c2ecf20Sopenharmony_ci	audit_fd_pair(fd1, fd2);
16258c2ecf20Sopenharmony_ci
16268c2ecf20Sopenharmony_ci	fd_install(fd1, newfile1);
16278c2ecf20Sopenharmony_ci	fd_install(fd2, newfile2);
16288c2ecf20Sopenharmony_ci	return 0;
16298c2ecf20Sopenharmony_ci
16308c2ecf20Sopenharmony_ciout:
16318c2ecf20Sopenharmony_ci	put_unused_fd(fd2);
16328c2ecf20Sopenharmony_ci	put_unused_fd(fd1);
16338c2ecf20Sopenharmony_ci	return err;
16348c2ecf20Sopenharmony_ci}
16358c2ecf20Sopenharmony_ci
16368c2ecf20Sopenharmony_ciSYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
16378c2ecf20Sopenharmony_ci		int __user *, usockvec)
16388c2ecf20Sopenharmony_ci{
16398c2ecf20Sopenharmony_ci	return __sys_socketpair(family, type, protocol, usockvec);
16408c2ecf20Sopenharmony_ci}
16418c2ecf20Sopenharmony_ci
16428c2ecf20Sopenharmony_ci/*
16438c2ecf20Sopenharmony_ci *	Bind a name to a socket. Nothing much to do here since it's
16448c2ecf20Sopenharmony_ci *	the protocol's responsibility to handle the local address.
16458c2ecf20Sopenharmony_ci *
16468c2ecf20Sopenharmony_ci *	We move the socket address to kernel space before we call
16478c2ecf20Sopenharmony_ci *	the protocol layer (having also checked the address is ok).
16488c2ecf20Sopenharmony_ci */
16498c2ecf20Sopenharmony_ci
16508c2ecf20Sopenharmony_ciint __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)
16518c2ecf20Sopenharmony_ci{
16528c2ecf20Sopenharmony_ci	struct socket *sock;
16538c2ecf20Sopenharmony_ci	struct sockaddr_storage address;
16548c2ecf20Sopenharmony_ci	int err, fput_needed;
16558c2ecf20Sopenharmony_ci
16568c2ecf20Sopenharmony_ci	sock = sockfd_lookup_light(fd, &err, &fput_needed);
16578c2ecf20Sopenharmony_ci	if (sock) {
16588c2ecf20Sopenharmony_ci		err = move_addr_to_kernel(umyaddr, addrlen, &address);
16598c2ecf20Sopenharmony_ci		if (!err) {
16608c2ecf20Sopenharmony_ci			err = security_socket_bind(sock,
16618c2ecf20Sopenharmony_ci						   (struct sockaddr *)&address,
16628c2ecf20Sopenharmony_ci						   addrlen);
16638c2ecf20Sopenharmony_ci			if (!err)
16648c2ecf20Sopenharmony_ci				err = sock->ops->bind(sock,
16658c2ecf20Sopenharmony_ci						      (struct sockaddr *)
16668c2ecf20Sopenharmony_ci						      &address, addrlen);
16678c2ecf20Sopenharmony_ci		}
16688c2ecf20Sopenharmony_ci		fput_light(sock->file, fput_needed);
16698c2ecf20Sopenharmony_ci	}
16708c2ecf20Sopenharmony_ci	return err;
16718c2ecf20Sopenharmony_ci}
16728c2ecf20Sopenharmony_ci
16738c2ecf20Sopenharmony_ciSYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
16748c2ecf20Sopenharmony_ci{
16758c2ecf20Sopenharmony_ci	return __sys_bind(fd, umyaddr, addrlen);
16768c2ecf20Sopenharmony_ci}
16778c2ecf20Sopenharmony_ci
16788c2ecf20Sopenharmony_ci/*
16798c2ecf20Sopenharmony_ci *	Perform a listen. Basically, we allow the protocol to do anything
16808c2ecf20Sopenharmony_ci *	necessary for a listen, and if that works, we mark the socket as
16818c2ecf20Sopenharmony_ci *	ready for listening.
16828c2ecf20Sopenharmony_ci */
16838c2ecf20Sopenharmony_ci
16848c2ecf20Sopenharmony_ciint __sys_listen(int fd, int backlog)
16858c2ecf20Sopenharmony_ci{
16868c2ecf20Sopenharmony_ci	struct socket *sock;
16878c2ecf20Sopenharmony_ci	int err, fput_needed;
16888c2ecf20Sopenharmony_ci	int somaxconn;
16898c2ecf20Sopenharmony_ci
16908c2ecf20Sopenharmony_ci	sock = sockfd_lookup_light(fd, &err, &fput_needed);
16918c2ecf20Sopenharmony_ci	if (sock) {
16928c2ecf20Sopenharmony_ci		somaxconn = READ_ONCE(sock_net(sock->sk)->core.sysctl_somaxconn);
16938c2ecf20Sopenharmony_ci		if ((unsigned int)backlog > somaxconn)
16948c2ecf20Sopenharmony_ci			backlog = somaxconn;
16958c2ecf20Sopenharmony_ci
16968c2ecf20Sopenharmony_ci		err = security_socket_listen(sock, backlog);
16978c2ecf20Sopenharmony_ci		if (!err)
16988c2ecf20Sopenharmony_ci			err = sock->ops->listen(sock, backlog);
16998c2ecf20Sopenharmony_ci
17008c2ecf20Sopenharmony_ci		fput_light(sock->file, fput_needed);
17018c2ecf20Sopenharmony_ci	}
17028c2ecf20Sopenharmony_ci	return err;
17038c2ecf20Sopenharmony_ci}
17048c2ecf20Sopenharmony_ci
17058c2ecf20Sopenharmony_ciSYSCALL_DEFINE2(listen, int, fd, int, backlog)
17068c2ecf20Sopenharmony_ci{
17078c2ecf20Sopenharmony_ci	return __sys_listen(fd, backlog);
17088c2ecf20Sopenharmony_ci}
17098c2ecf20Sopenharmony_ci
17108c2ecf20Sopenharmony_cistruct file *do_accept(struct file *file, unsigned file_flags,
17118c2ecf20Sopenharmony_ci		       struct sockaddr __user *upeer_sockaddr,
17128c2ecf20Sopenharmony_ci		       int __user *upeer_addrlen, int flags)
17138c2ecf20Sopenharmony_ci{
17148c2ecf20Sopenharmony_ci	struct socket *sock, *newsock;
17158c2ecf20Sopenharmony_ci	struct file *newfile;
17168c2ecf20Sopenharmony_ci	int err, len;
17178c2ecf20Sopenharmony_ci	struct sockaddr_storage address;
17188c2ecf20Sopenharmony_ci
17198c2ecf20Sopenharmony_ci	sock = sock_from_file(file, &err);
17208c2ecf20Sopenharmony_ci	if (!sock)
17218c2ecf20Sopenharmony_ci		return ERR_PTR(err);
17228c2ecf20Sopenharmony_ci
17238c2ecf20Sopenharmony_ci	newsock = sock_alloc();
17248c2ecf20Sopenharmony_ci	if (!newsock)
17258c2ecf20Sopenharmony_ci		return ERR_PTR(-ENFILE);
17268c2ecf20Sopenharmony_ci
17278c2ecf20Sopenharmony_ci	newsock->type = sock->type;
17288c2ecf20Sopenharmony_ci	newsock->ops = sock->ops;
17298c2ecf20Sopenharmony_ci
17308c2ecf20Sopenharmony_ci	/*
17318c2ecf20Sopenharmony_ci	 * We don't need try_module_get here, as the listening socket (sock)
17328c2ecf20Sopenharmony_ci	 * has the protocol module (sock->ops->owner) held.
17338c2ecf20Sopenharmony_ci	 */
17348c2ecf20Sopenharmony_ci	__module_get(newsock->ops->owner);
17358c2ecf20Sopenharmony_ci
17368c2ecf20Sopenharmony_ci	newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name);
17378c2ecf20Sopenharmony_ci	if (IS_ERR(newfile))
17388c2ecf20Sopenharmony_ci		return newfile;
17398c2ecf20Sopenharmony_ci
17408c2ecf20Sopenharmony_ci	err = security_socket_accept(sock, newsock);
17418c2ecf20Sopenharmony_ci	if (err)
17428c2ecf20Sopenharmony_ci		goto out_fd;
17438c2ecf20Sopenharmony_ci
17448c2ecf20Sopenharmony_ci	err = sock->ops->accept(sock, newsock, sock->file->f_flags | file_flags,
17458c2ecf20Sopenharmony_ci					false);
17468c2ecf20Sopenharmony_ci	if (err < 0)
17478c2ecf20Sopenharmony_ci		goto out_fd;
17488c2ecf20Sopenharmony_ci
17498c2ecf20Sopenharmony_ci	if (upeer_sockaddr) {
17508c2ecf20Sopenharmony_ci		len = newsock->ops->getname(newsock,
17518c2ecf20Sopenharmony_ci					(struct sockaddr *)&address, 2);
17528c2ecf20Sopenharmony_ci		if (len < 0) {
17538c2ecf20Sopenharmony_ci			err = -ECONNABORTED;
17548c2ecf20Sopenharmony_ci			goto out_fd;
17558c2ecf20Sopenharmony_ci		}
17568c2ecf20Sopenharmony_ci		err = move_addr_to_user(&address,
17578c2ecf20Sopenharmony_ci					len, upeer_sockaddr, upeer_addrlen);
17588c2ecf20Sopenharmony_ci		if (err < 0)
17598c2ecf20Sopenharmony_ci			goto out_fd;
17608c2ecf20Sopenharmony_ci	}
17618c2ecf20Sopenharmony_ci
17628c2ecf20Sopenharmony_ci	/* File flags are not inherited via accept() unlike another OSes. */
17638c2ecf20Sopenharmony_ci	return newfile;
17648c2ecf20Sopenharmony_ciout_fd:
17658c2ecf20Sopenharmony_ci	fput(newfile);
17668c2ecf20Sopenharmony_ci	return ERR_PTR(err);
17678c2ecf20Sopenharmony_ci}
17688c2ecf20Sopenharmony_ci
17698c2ecf20Sopenharmony_ciint __sys_accept4_file(struct file *file, unsigned file_flags,
17708c2ecf20Sopenharmony_ci		       struct sockaddr __user *upeer_sockaddr,
17718c2ecf20Sopenharmony_ci		       int __user *upeer_addrlen, int flags,
17728c2ecf20Sopenharmony_ci		       unsigned long nofile)
17738c2ecf20Sopenharmony_ci{
17748c2ecf20Sopenharmony_ci	struct file *newfile;
17758c2ecf20Sopenharmony_ci	int newfd;
17768c2ecf20Sopenharmony_ci
17778c2ecf20Sopenharmony_ci	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
17788c2ecf20Sopenharmony_ci		return -EINVAL;
17798c2ecf20Sopenharmony_ci
17808c2ecf20Sopenharmony_ci	if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
17818c2ecf20Sopenharmony_ci		flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
17828c2ecf20Sopenharmony_ci
17838c2ecf20Sopenharmony_ci	newfd = __get_unused_fd_flags(flags, nofile);
17848c2ecf20Sopenharmony_ci	if (unlikely(newfd < 0))
17858c2ecf20Sopenharmony_ci		return newfd;
17868c2ecf20Sopenharmony_ci
17878c2ecf20Sopenharmony_ci	newfile = do_accept(file, file_flags, upeer_sockaddr, upeer_addrlen,
17888c2ecf20Sopenharmony_ci			    flags);
17898c2ecf20Sopenharmony_ci	if (IS_ERR(newfile)) {
17908c2ecf20Sopenharmony_ci		put_unused_fd(newfd);
17918c2ecf20Sopenharmony_ci		return PTR_ERR(newfile);
17928c2ecf20Sopenharmony_ci	}
17938c2ecf20Sopenharmony_ci	fd_install(newfd, newfile);
17948c2ecf20Sopenharmony_ci	return newfd;
17958c2ecf20Sopenharmony_ci}
17968c2ecf20Sopenharmony_ci
17978c2ecf20Sopenharmony_ci/*
17988c2ecf20Sopenharmony_ci *	For accept, we attempt to create a new socket, set up the link
17998c2ecf20Sopenharmony_ci *	with the client, wake up the client, then return the new
18008c2ecf20Sopenharmony_ci *	connected fd. We collect the address of the connector in kernel
18018c2ecf20Sopenharmony_ci *	space and move it to user at the very end. This is unclean because
18028c2ecf20Sopenharmony_ci *	we open the socket then return an error.
18038c2ecf20Sopenharmony_ci *
18048c2ecf20Sopenharmony_ci *	1003.1g adds the ability to recvmsg() to query connection pending
18058c2ecf20Sopenharmony_ci *	status to recvmsg. We need to add that support in a way thats
18068c2ecf20Sopenharmony_ci *	clean when we restructure accept also.
18078c2ecf20Sopenharmony_ci */
18088c2ecf20Sopenharmony_ci
18098c2ecf20Sopenharmony_ciint __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
18108c2ecf20Sopenharmony_ci		  int __user *upeer_addrlen, int flags)
18118c2ecf20Sopenharmony_ci{
18128c2ecf20Sopenharmony_ci	int ret = -EBADF;
18138c2ecf20Sopenharmony_ci	struct fd f;
18148c2ecf20Sopenharmony_ci
18158c2ecf20Sopenharmony_ci	f = fdget(fd);
18168c2ecf20Sopenharmony_ci	if (f.file) {
18178c2ecf20Sopenharmony_ci		ret = __sys_accept4_file(f.file, 0, upeer_sockaddr,
18188c2ecf20Sopenharmony_ci						upeer_addrlen, flags,
18198c2ecf20Sopenharmony_ci						rlimit(RLIMIT_NOFILE));
18208c2ecf20Sopenharmony_ci		fdput(f);
18218c2ecf20Sopenharmony_ci	}
18228c2ecf20Sopenharmony_ci
18238c2ecf20Sopenharmony_ci	return ret;
18248c2ecf20Sopenharmony_ci}
18258c2ecf20Sopenharmony_ci
18268c2ecf20Sopenharmony_ciSYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
18278c2ecf20Sopenharmony_ci		int __user *, upeer_addrlen, int, flags)
18288c2ecf20Sopenharmony_ci{
18298c2ecf20Sopenharmony_ci	return __sys_accept4(fd, upeer_sockaddr, upeer_addrlen, flags);
18308c2ecf20Sopenharmony_ci}
18318c2ecf20Sopenharmony_ci
18328c2ecf20Sopenharmony_ciSYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,
18338c2ecf20Sopenharmony_ci		int __user *, upeer_addrlen)
18348c2ecf20Sopenharmony_ci{
18358c2ecf20Sopenharmony_ci	return __sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0);
18368c2ecf20Sopenharmony_ci}
18378c2ecf20Sopenharmony_ci
18388c2ecf20Sopenharmony_ci/*
18398c2ecf20Sopenharmony_ci *	Attempt to connect to a socket with the server address.  The address
18408c2ecf20Sopenharmony_ci *	is in user space so we verify it is OK and move it to kernel space.
18418c2ecf20Sopenharmony_ci *
18428c2ecf20Sopenharmony_ci *	For 1003.1g we need to add clean support for a bind to AF_UNSPEC to
18438c2ecf20Sopenharmony_ci *	break bindings
18448c2ecf20Sopenharmony_ci *
18458c2ecf20Sopenharmony_ci *	NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and
18468c2ecf20Sopenharmony_ci *	other SEQPACKET protocols that take time to connect() as it doesn't
18478c2ecf20Sopenharmony_ci *	include the -EINPROGRESS status for such sockets.
18488c2ecf20Sopenharmony_ci */
18498c2ecf20Sopenharmony_ci
18508c2ecf20Sopenharmony_ciint __sys_connect_file(struct file *file, struct sockaddr_storage *address,
18518c2ecf20Sopenharmony_ci		       int addrlen, int file_flags)
18528c2ecf20Sopenharmony_ci{
18538c2ecf20Sopenharmony_ci	struct socket *sock;
18548c2ecf20Sopenharmony_ci	int err;
18558c2ecf20Sopenharmony_ci
18568c2ecf20Sopenharmony_ci	sock = sock_from_file(file, &err);
18578c2ecf20Sopenharmony_ci	if (!sock)
18588c2ecf20Sopenharmony_ci		goto out;
18598c2ecf20Sopenharmony_ci
18608c2ecf20Sopenharmony_ci	err =
18618c2ecf20Sopenharmony_ci	    security_socket_connect(sock, (struct sockaddr *)address, addrlen);
18628c2ecf20Sopenharmony_ci	if (err)
18638c2ecf20Sopenharmony_ci		goto out;
18648c2ecf20Sopenharmony_ci
18658c2ecf20Sopenharmony_ci	err = sock->ops->connect(sock, (struct sockaddr *)address, addrlen,
18668c2ecf20Sopenharmony_ci				 sock->file->f_flags | file_flags);
18678c2ecf20Sopenharmony_ciout:
18688c2ecf20Sopenharmony_ci	return err;
18698c2ecf20Sopenharmony_ci}
18708c2ecf20Sopenharmony_ci
18718c2ecf20Sopenharmony_ciint __sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen)
18728c2ecf20Sopenharmony_ci{
18738c2ecf20Sopenharmony_ci	int ret = -EBADF;
18748c2ecf20Sopenharmony_ci	struct fd f;
18758c2ecf20Sopenharmony_ci
18768c2ecf20Sopenharmony_ci	f = fdget(fd);
18778c2ecf20Sopenharmony_ci	if (f.file) {
18788c2ecf20Sopenharmony_ci		struct sockaddr_storage address;
18798c2ecf20Sopenharmony_ci
18808c2ecf20Sopenharmony_ci		ret = move_addr_to_kernel(uservaddr, addrlen, &address);
18818c2ecf20Sopenharmony_ci		if (!ret)
18828c2ecf20Sopenharmony_ci			ret = __sys_connect_file(f.file, &address, addrlen, 0);
18838c2ecf20Sopenharmony_ci		fdput(f);
18848c2ecf20Sopenharmony_ci	}
18858c2ecf20Sopenharmony_ci
18868c2ecf20Sopenharmony_ci	return ret;
18878c2ecf20Sopenharmony_ci}
18888c2ecf20Sopenharmony_ci
18898c2ecf20Sopenharmony_ciSYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
18908c2ecf20Sopenharmony_ci		int, addrlen)
18918c2ecf20Sopenharmony_ci{
18928c2ecf20Sopenharmony_ci	return __sys_connect(fd, uservaddr, addrlen);
18938c2ecf20Sopenharmony_ci}
18948c2ecf20Sopenharmony_ci
18958c2ecf20Sopenharmony_ci/*
18968c2ecf20Sopenharmony_ci *	Get the local address ('name') of a socket object. Move the obtained
18978c2ecf20Sopenharmony_ci *	name to user space.
18988c2ecf20Sopenharmony_ci */
18998c2ecf20Sopenharmony_ci
19008c2ecf20Sopenharmony_ciint __sys_getsockname(int fd, struct sockaddr __user *usockaddr,
19018c2ecf20Sopenharmony_ci		      int __user *usockaddr_len)
19028c2ecf20Sopenharmony_ci{
19038c2ecf20Sopenharmony_ci	struct socket *sock;
19048c2ecf20Sopenharmony_ci	struct sockaddr_storage address;
19058c2ecf20Sopenharmony_ci	int err, fput_needed;
19068c2ecf20Sopenharmony_ci
19078c2ecf20Sopenharmony_ci	sock = sockfd_lookup_light(fd, &err, &fput_needed);
19088c2ecf20Sopenharmony_ci	if (!sock)
19098c2ecf20Sopenharmony_ci		goto out;
19108c2ecf20Sopenharmony_ci
19118c2ecf20Sopenharmony_ci	err = security_socket_getsockname(sock);
19128c2ecf20Sopenharmony_ci	if (err)
19138c2ecf20Sopenharmony_ci		goto out_put;
19148c2ecf20Sopenharmony_ci
19158c2ecf20Sopenharmony_ci	err = sock->ops->getname(sock, (struct sockaddr *)&address, 0);
19168c2ecf20Sopenharmony_ci	if (err < 0)
19178c2ecf20Sopenharmony_ci		goto out_put;
19188c2ecf20Sopenharmony_ci        /* "err" is actually length in this case */
19198c2ecf20Sopenharmony_ci	err = move_addr_to_user(&address, err, usockaddr, usockaddr_len);
19208c2ecf20Sopenharmony_ci
19218c2ecf20Sopenharmony_ciout_put:
19228c2ecf20Sopenharmony_ci	fput_light(sock->file, fput_needed);
19238c2ecf20Sopenharmony_ciout:
19248c2ecf20Sopenharmony_ci	return err;
19258c2ecf20Sopenharmony_ci}
19268c2ecf20Sopenharmony_ci
19278c2ecf20Sopenharmony_ciSYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
19288c2ecf20Sopenharmony_ci		int __user *, usockaddr_len)
19298c2ecf20Sopenharmony_ci{
19308c2ecf20Sopenharmony_ci	return __sys_getsockname(fd, usockaddr, usockaddr_len);
19318c2ecf20Sopenharmony_ci}
19328c2ecf20Sopenharmony_ci
19338c2ecf20Sopenharmony_ci/*
19348c2ecf20Sopenharmony_ci *	Get the remote address ('name') of a socket object. Move the obtained
19358c2ecf20Sopenharmony_ci *	name to user space.
19368c2ecf20Sopenharmony_ci */
19378c2ecf20Sopenharmony_ci
19388c2ecf20Sopenharmony_ciint __sys_getpeername(int fd, struct sockaddr __user *usockaddr,
19398c2ecf20Sopenharmony_ci		      int __user *usockaddr_len)
19408c2ecf20Sopenharmony_ci{
19418c2ecf20Sopenharmony_ci	struct socket *sock;
19428c2ecf20Sopenharmony_ci	struct sockaddr_storage address;
19438c2ecf20Sopenharmony_ci	int err, fput_needed;
19448c2ecf20Sopenharmony_ci
19458c2ecf20Sopenharmony_ci	sock = sockfd_lookup_light(fd, &err, &fput_needed);
19468c2ecf20Sopenharmony_ci	if (sock != NULL) {
19478c2ecf20Sopenharmony_ci		err = security_socket_getpeername(sock);
19488c2ecf20Sopenharmony_ci		if (err) {
19498c2ecf20Sopenharmony_ci			fput_light(sock->file, fput_needed);
19508c2ecf20Sopenharmony_ci			return err;
19518c2ecf20Sopenharmony_ci		}
19528c2ecf20Sopenharmony_ci
19538c2ecf20Sopenharmony_ci		err = sock->ops->getname(sock, (struct sockaddr *)&address, 1);
19548c2ecf20Sopenharmony_ci		if (err >= 0)
19558c2ecf20Sopenharmony_ci			/* "err" is actually length in this case */
19568c2ecf20Sopenharmony_ci			err = move_addr_to_user(&address, err, usockaddr,
19578c2ecf20Sopenharmony_ci						usockaddr_len);
19588c2ecf20Sopenharmony_ci		fput_light(sock->file, fput_needed);
19598c2ecf20Sopenharmony_ci	}
19608c2ecf20Sopenharmony_ci	return err;
19618c2ecf20Sopenharmony_ci}
19628c2ecf20Sopenharmony_ci
19638c2ecf20Sopenharmony_ciSYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
19648c2ecf20Sopenharmony_ci		int __user *, usockaddr_len)
19658c2ecf20Sopenharmony_ci{
19668c2ecf20Sopenharmony_ci	return __sys_getpeername(fd, usockaddr, usockaddr_len);
19678c2ecf20Sopenharmony_ci}
19688c2ecf20Sopenharmony_ci
19698c2ecf20Sopenharmony_ci/*
19708c2ecf20Sopenharmony_ci *	Send a datagram to a given address. We move the address into kernel
19718c2ecf20Sopenharmony_ci *	space and check the user space data area is readable before invoking
19728c2ecf20Sopenharmony_ci *	the protocol.
19738c2ecf20Sopenharmony_ci */
19748c2ecf20Sopenharmony_ciint __sys_sendto(int fd, void __user *buff, size_t len, unsigned int flags,
19758c2ecf20Sopenharmony_ci		 struct sockaddr __user *addr,  int addr_len)
19768c2ecf20Sopenharmony_ci{
19778c2ecf20Sopenharmony_ci	struct socket *sock;
19788c2ecf20Sopenharmony_ci	struct sockaddr_storage address;
19798c2ecf20Sopenharmony_ci	int err;
19808c2ecf20Sopenharmony_ci	struct msghdr msg;
19818c2ecf20Sopenharmony_ci	struct iovec iov;
19828c2ecf20Sopenharmony_ci	int fput_needed;
19838c2ecf20Sopenharmony_ci
19848c2ecf20Sopenharmony_ci	err = import_single_range(WRITE, buff, len, &iov, &msg.msg_iter);
19858c2ecf20Sopenharmony_ci	if (unlikely(err))
19868c2ecf20Sopenharmony_ci		return err;
19878c2ecf20Sopenharmony_ci	sock = sockfd_lookup_light(fd, &err, &fput_needed);
19888c2ecf20Sopenharmony_ci	if (!sock)
19898c2ecf20Sopenharmony_ci		goto out;
19908c2ecf20Sopenharmony_ci
19918c2ecf20Sopenharmony_ci	msg.msg_name = NULL;
19928c2ecf20Sopenharmony_ci	msg.msg_control = NULL;
19938c2ecf20Sopenharmony_ci	msg.msg_controllen = 0;
19948c2ecf20Sopenharmony_ci	msg.msg_namelen = 0;
19958c2ecf20Sopenharmony_ci	if (addr) {
19968c2ecf20Sopenharmony_ci		err = move_addr_to_kernel(addr, addr_len, &address);
19978c2ecf20Sopenharmony_ci		if (err < 0)
19988c2ecf20Sopenharmony_ci			goto out_put;
19998c2ecf20Sopenharmony_ci		msg.msg_name = (struct sockaddr *)&address;
20008c2ecf20Sopenharmony_ci		msg.msg_namelen = addr_len;
20018c2ecf20Sopenharmony_ci	}
20028c2ecf20Sopenharmony_ci	if (sock->file->f_flags & O_NONBLOCK)
20038c2ecf20Sopenharmony_ci		flags |= MSG_DONTWAIT;
20048c2ecf20Sopenharmony_ci	msg.msg_flags = flags;
20058c2ecf20Sopenharmony_ci	err = __sock_sendmsg(sock, &msg);
20068c2ecf20Sopenharmony_ci
20078c2ecf20Sopenharmony_ciout_put:
20088c2ecf20Sopenharmony_ci	fput_light(sock->file, fput_needed);
20098c2ecf20Sopenharmony_ciout:
20108c2ecf20Sopenharmony_ci	return err;
20118c2ecf20Sopenharmony_ci}
20128c2ecf20Sopenharmony_ci
20138c2ecf20Sopenharmony_ciSYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
20148c2ecf20Sopenharmony_ci		unsigned int, flags, struct sockaddr __user *, addr,
20158c2ecf20Sopenharmony_ci		int, addr_len)
20168c2ecf20Sopenharmony_ci{
20178c2ecf20Sopenharmony_ci	return __sys_sendto(fd, buff, len, flags, addr, addr_len);
20188c2ecf20Sopenharmony_ci}
20198c2ecf20Sopenharmony_ci
20208c2ecf20Sopenharmony_ci/*
20218c2ecf20Sopenharmony_ci *	Send a datagram down a socket.
20228c2ecf20Sopenharmony_ci */
20238c2ecf20Sopenharmony_ci
20248c2ecf20Sopenharmony_ciSYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len,
20258c2ecf20Sopenharmony_ci		unsigned int, flags)
20268c2ecf20Sopenharmony_ci{
20278c2ecf20Sopenharmony_ci	return __sys_sendto(fd, buff, len, flags, NULL, 0);
20288c2ecf20Sopenharmony_ci}
20298c2ecf20Sopenharmony_ci
20308c2ecf20Sopenharmony_ci/*
20318c2ecf20Sopenharmony_ci *	Receive a frame from the socket and optionally record the address of the
20328c2ecf20Sopenharmony_ci *	sender. We verify the buffers are writable and if needed move the
20338c2ecf20Sopenharmony_ci *	sender address from kernel to user space.
20348c2ecf20Sopenharmony_ci */
20358c2ecf20Sopenharmony_ciint __sys_recvfrom(int fd, void __user *ubuf, size_t size, unsigned int flags,
20368c2ecf20Sopenharmony_ci		   struct sockaddr __user *addr, int __user *addr_len)
20378c2ecf20Sopenharmony_ci{
20388c2ecf20Sopenharmony_ci	struct socket *sock;
20398c2ecf20Sopenharmony_ci	struct iovec iov;
20408c2ecf20Sopenharmony_ci	struct msghdr msg;
20418c2ecf20Sopenharmony_ci	struct sockaddr_storage address;
20428c2ecf20Sopenharmony_ci	int err, err2;
20438c2ecf20Sopenharmony_ci	int fput_needed;
20448c2ecf20Sopenharmony_ci
20458c2ecf20Sopenharmony_ci	err = import_single_range(READ, ubuf, size, &iov, &msg.msg_iter);
20468c2ecf20Sopenharmony_ci	if (unlikely(err))
20478c2ecf20Sopenharmony_ci		return err;
20488c2ecf20Sopenharmony_ci	sock = sockfd_lookup_light(fd, &err, &fput_needed);
20498c2ecf20Sopenharmony_ci	if (!sock)
20508c2ecf20Sopenharmony_ci		goto out;
20518c2ecf20Sopenharmony_ci
20528c2ecf20Sopenharmony_ci	msg.msg_control = NULL;
20538c2ecf20Sopenharmony_ci	msg.msg_controllen = 0;
20548c2ecf20Sopenharmony_ci	/* Save some cycles and don't copy the address if not needed */
20558c2ecf20Sopenharmony_ci	msg.msg_name = addr ? (struct sockaddr *)&address : NULL;
20568c2ecf20Sopenharmony_ci	/* We assume all kernel code knows the size of sockaddr_storage */
20578c2ecf20Sopenharmony_ci	msg.msg_namelen = 0;
20588c2ecf20Sopenharmony_ci	msg.msg_iocb = NULL;
20598c2ecf20Sopenharmony_ci	msg.msg_flags = 0;
20608c2ecf20Sopenharmony_ci	if (sock->file->f_flags & O_NONBLOCK)
20618c2ecf20Sopenharmony_ci		flags |= MSG_DONTWAIT;
20628c2ecf20Sopenharmony_ci	err = sock_recvmsg(sock, &msg, flags);
20638c2ecf20Sopenharmony_ci
20648c2ecf20Sopenharmony_ci	if (err >= 0 && addr != NULL) {
20658c2ecf20Sopenharmony_ci		err2 = move_addr_to_user(&address,
20668c2ecf20Sopenharmony_ci					 msg.msg_namelen, addr, addr_len);
20678c2ecf20Sopenharmony_ci		if (err2 < 0)
20688c2ecf20Sopenharmony_ci			err = err2;
20698c2ecf20Sopenharmony_ci	}
20708c2ecf20Sopenharmony_ci
20718c2ecf20Sopenharmony_ci	fput_light(sock->file, fput_needed);
20728c2ecf20Sopenharmony_ciout:
20738c2ecf20Sopenharmony_ci	return err;
20748c2ecf20Sopenharmony_ci}
20758c2ecf20Sopenharmony_ci
20768c2ecf20Sopenharmony_ciSYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
20778c2ecf20Sopenharmony_ci		unsigned int, flags, struct sockaddr __user *, addr,
20788c2ecf20Sopenharmony_ci		int __user *, addr_len)
20798c2ecf20Sopenharmony_ci{
20808c2ecf20Sopenharmony_ci	return __sys_recvfrom(fd, ubuf, size, flags, addr, addr_len);
20818c2ecf20Sopenharmony_ci}
20828c2ecf20Sopenharmony_ci
20838c2ecf20Sopenharmony_ci/*
20848c2ecf20Sopenharmony_ci *	Receive a datagram from a socket.
20858c2ecf20Sopenharmony_ci */
20868c2ecf20Sopenharmony_ci
20878c2ecf20Sopenharmony_ciSYSCALL_DEFINE4(recv, int, fd, void __user *, ubuf, size_t, size,
20888c2ecf20Sopenharmony_ci		unsigned int, flags)
20898c2ecf20Sopenharmony_ci{
20908c2ecf20Sopenharmony_ci	return __sys_recvfrom(fd, ubuf, size, flags, NULL, NULL);
20918c2ecf20Sopenharmony_ci}
20928c2ecf20Sopenharmony_ci
20938c2ecf20Sopenharmony_cistatic bool sock_use_custom_sol_socket(const struct socket *sock)
20948c2ecf20Sopenharmony_ci{
20958c2ecf20Sopenharmony_ci	const struct sock *sk = sock->sk;
20968c2ecf20Sopenharmony_ci
20978c2ecf20Sopenharmony_ci	/* Use sock->ops->setsockopt() for MPTCP */
20988c2ecf20Sopenharmony_ci	return IS_ENABLED(CONFIG_MPTCP) &&
20998c2ecf20Sopenharmony_ci	       sk->sk_protocol == IPPROTO_MPTCP &&
21008c2ecf20Sopenharmony_ci	       sk->sk_type == SOCK_STREAM &&
21018c2ecf20Sopenharmony_ci	       (sk->sk_family == AF_INET || sk->sk_family == AF_INET6);
21028c2ecf20Sopenharmony_ci}
21038c2ecf20Sopenharmony_ci
21048c2ecf20Sopenharmony_ci/*
21058c2ecf20Sopenharmony_ci *	Set a socket option. Because we don't know the option lengths we have
21068c2ecf20Sopenharmony_ci *	to pass the user mode parameter for the protocols to sort out.
21078c2ecf20Sopenharmony_ci */
21088c2ecf20Sopenharmony_ciint __sys_setsockopt(int fd, int level, int optname, char __user *user_optval,
21098c2ecf20Sopenharmony_ci		int optlen)
21108c2ecf20Sopenharmony_ci{
21118c2ecf20Sopenharmony_ci	sockptr_t optval = USER_SOCKPTR(user_optval);
21128c2ecf20Sopenharmony_ci	char *kernel_optval = NULL;
21138c2ecf20Sopenharmony_ci	int err, fput_needed;
21148c2ecf20Sopenharmony_ci	struct socket *sock;
21158c2ecf20Sopenharmony_ci
21168c2ecf20Sopenharmony_ci	if (optlen < 0)
21178c2ecf20Sopenharmony_ci		return -EINVAL;
21188c2ecf20Sopenharmony_ci
21198c2ecf20Sopenharmony_ci	sock = sockfd_lookup_light(fd, &err, &fput_needed);
21208c2ecf20Sopenharmony_ci	if (!sock)
21218c2ecf20Sopenharmony_ci		return err;
21228c2ecf20Sopenharmony_ci
21238c2ecf20Sopenharmony_ci	err = security_socket_setsockopt(sock, level, optname);
21248c2ecf20Sopenharmony_ci	if (err)
21258c2ecf20Sopenharmony_ci		goto out_put;
21268c2ecf20Sopenharmony_ci
21278c2ecf20Sopenharmony_ci	if (!in_compat_syscall())
21288c2ecf20Sopenharmony_ci		err = BPF_CGROUP_RUN_PROG_SETSOCKOPT(sock->sk, &level, &optname,
21298c2ecf20Sopenharmony_ci						     user_optval, &optlen,
21308c2ecf20Sopenharmony_ci						     &kernel_optval);
21318c2ecf20Sopenharmony_ci	if (err < 0)
21328c2ecf20Sopenharmony_ci		goto out_put;
21338c2ecf20Sopenharmony_ci	if (err > 0) {
21348c2ecf20Sopenharmony_ci		err = 0;
21358c2ecf20Sopenharmony_ci		goto out_put;
21368c2ecf20Sopenharmony_ci	}
21378c2ecf20Sopenharmony_ci
21388c2ecf20Sopenharmony_ci	if (kernel_optval)
21398c2ecf20Sopenharmony_ci		optval = KERNEL_SOCKPTR(kernel_optval);
21408c2ecf20Sopenharmony_ci	if (level == SOL_SOCKET && !sock_use_custom_sol_socket(sock))
21418c2ecf20Sopenharmony_ci		err = sock_setsockopt(sock, level, optname, optval, optlen);
21428c2ecf20Sopenharmony_ci	else if (unlikely(!sock->ops->setsockopt))
21438c2ecf20Sopenharmony_ci		err = -EOPNOTSUPP;
21448c2ecf20Sopenharmony_ci	else
21458c2ecf20Sopenharmony_ci		err = sock->ops->setsockopt(sock, level, optname, optval,
21468c2ecf20Sopenharmony_ci					    optlen);
21478c2ecf20Sopenharmony_ci	kfree(kernel_optval);
21488c2ecf20Sopenharmony_ciout_put:
21498c2ecf20Sopenharmony_ci	fput_light(sock->file, fput_needed);
21508c2ecf20Sopenharmony_ci	return err;
21518c2ecf20Sopenharmony_ci}
21528c2ecf20Sopenharmony_ci
21538c2ecf20Sopenharmony_ciSYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
21548c2ecf20Sopenharmony_ci		char __user *, optval, int, optlen)
21558c2ecf20Sopenharmony_ci{
21568c2ecf20Sopenharmony_ci	return __sys_setsockopt(fd, level, optname, optval, optlen);
21578c2ecf20Sopenharmony_ci}
21588c2ecf20Sopenharmony_ci
21598c2ecf20Sopenharmony_ciINDIRECT_CALLABLE_DECLARE(bool tcp_bpf_bypass_getsockopt(int level,
21608c2ecf20Sopenharmony_ci							 int optname));
21618c2ecf20Sopenharmony_ci
21628c2ecf20Sopenharmony_ci/*
21638c2ecf20Sopenharmony_ci *	Get a socket option. Because we don't know the option lengths we have
21648c2ecf20Sopenharmony_ci *	to pass a user mode parameter for the protocols to sort out.
21658c2ecf20Sopenharmony_ci */
21668c2ecf20Sopenharmony_ciint __sys_getsockopt(int fd, int level, int optname, char __user *optval,
21678c2ecf20Sopenharmony_ci		int __user *optlen)
21688c2ecf20Sopenharmony_ci{
21698c2ecf20Sopenharmony_ci	int err, fput_needed;
21708c2ecf20Sopenharmony_ci	struct socket *sock;
21718c2ecf20Sopenharmony_ci	int max_optlen;
21728c2ecf20Sopenharmony_ci
21738c2ecf20Sopenharmony_ci	sock = sockfd_lookup_light(fd, &err, &fput_needed);
21748c2ecf20Sopenharmony_ci	if (!sock)
21758c2ecf20Sopenharmony_ci		return err;
21768c2ecf20Sopenharmony_ci
21778c2ecf20Sopenharmony_ci	err = security_socket_getsockopt(sock, level, optname);
21788c2ecf20Sopenharmony_ci	if (err)
21798c2ecf20Sopenharmony_ci		goto out_put;
21808c2ecf20Sopenharmony_ci
21818c2ecf20Sopenharmony_ci	if (!in_compat_syscall())
21828c2ecf20Sopenharmony_ci		max_optlen = BPF_CGROUP_GETSOCKOPT_MAX_OPTLEN(optlen);
21838c2ecf20Sopenharmony_ci
21848c2ecf20Sopenharmony_ci	if (level == SOL_SOCKET)
21858c2ecf20Sopenharmony_ci		err = sock_getsockopt(sock, level, optname, optval, optlen);
21868c2ecf20Sopenharmony_ci	else if (unlikely(!sock->ops->getsockopt))
21878c2ecf20Sopenharmony_ci		err = -EOPNOTSUPP;
21888c2ecf20Sopenharmony_ci	else
21898c2ecf20Sopenharmony_ci		err = sock->ops->getsockopt(sock, level, optname, optval,
21908c2ecf20Sopenharmony_ci					    optlen);
21918c2ecf20Sopenharmony_ci
21928c2ecf20Sopenharmony_ci	if (!in_compat_syscall())
21938c2ecf20Sopenharmony_ci		err = BPF_CGROUP_RUN_PROG_GETSOCKOPT(sock->sk, level, optname,
21948c2ecf20Sopenharmony_ci						     optval, optlen, max_optlen,
21958c2ecf20Sopenharmony_ci						     err);
21968c2ecf20Sopenharmony_ciout_put:
21978c2ecf20Sopenharmony_ci	fput_light(sock->file, fput_needed);
21988c2ecf20Sopenharmony_ci	return err;
21998c2ecf20Sopenharmony_ci}
22008c2ecf20Sopenharmony_ci
22018c2ecf20Sopenharmony_ciSYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
22028c2ecf20Sopenharmony_ci		char __user *, optval, int __user *, optlen)
22038c2ecf20Sopenharmony_ci{
22048c2ecf20Sopenharmony_ci	return __sys_getsockopt(fd, level, optname, optval, optlen);
22058c2ecf20Sopenharmony_ci}
22068c2ecf20Sopenharmony_ci
22078c2ecf20Sopenharmony_ci/*
22088c2ecf20Sopenharmony_ci *	Shutdown a socket.
22098c2ecf20Sopenharmony_ci */
22108c2ecf20Sopenharmony_ci
22118c2ecf20Sopenharmony_ciint __sys_shutdown_sock(struct socket *sock, int how)
22128c2ecf20Sopenharmony_ci{
22138c2ecf20Sopenharmony_ci	int err;
22148c2ecf20Sopenharmony_ci
22158c2ecf20Sopenharmony_ci	err = security_socket_shutdown(sock, how);
22168c2ecf20Sopenharmony_ci	if (!err)
22178c2ecf20Sopenharmony_ci		err = sock->ops->shutdown(sock, how);
22188c2ecf20Sopenharmony_ci
22198c2ecf20Sopenharmony_ci	return err;
22208c2ecf20Sopenharmony_ci}
22218c2ecf20Sopenharmony_ci
22228c2ecf20Sopenharmony_ciint __sys_shutdown(int fd, int how)
22238c2ecf20Sopenharmony_ci{
22248c2ecf20Sopenharmony_ci	int err, fput_needed;
22258c2ecf20Sopenharmony_ci	struct socket *sock;
22268c2ecf20Sopenharmony_ci
22278c2ecf20Sopenharmony_ci	sock = sockfd_lookup_light(fd, &err, &fput_needed);
22288c2ecf20Sopenharmony_ci	if (sock != NULL) {
22298c2ecf20Sopenharmony_ci		err = __sys_shutdown_sock(sock, how);
22308c2ecf20Sopenharmony_ci		fput_light(sock->file, fput_needed);
22318c2ecf20Sopenharmony_ci	}
22328c2ecf20Sopenharmony_ci	return err;
22338c2ecf20Sopenharmony_ci}
22348c2ecf20Sopenharmony_ci
22358c2ecf20Sopenharmony_ciSYSCALL_DEFINE2(shutdown, int, fd, int, how)
22368c2ecf20Sopenharmony_ci{
22378c2ecf20Sopenharmony_ci	return __sys_shutdown(fd, how);
22388c2ecf20Sopenharmony_ci}
22398c2ecf20Sopenharmony_ci
22408c2ecf20Sopenharmony_ci/* A couple of helpful macros for getting the address of the 32/64 bit
22418c2ecf20Sopenharmony_ci * fields which are the same type (int / unsigned) on our platforms.
22428c2ecf20Sopenharmony_ci */
22438c2ecf20Sopenharmony_ci#define COMPAT_MSG(msg, member)	((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member)
22448c2ecf20Sopenharmony_ci#define COMPAT_NAMELEN(msg)	COMPAT_MSG(msg, msg_namelen)
22458c2ecf20Sopenharmony_ci#define COMPAT_FLAGS(msg)	COMPAT_MSG(msg, msg_flags)
22468c2ecf20Sopenharmony_ci
22478c2ecf20Sopenharmony_cistruct used_address {
22488c2ecf20Sopenharmony_ci	struct sockaddr_storage name;
22498c2ecf20Sopenharmony_ci	unsigned int name_len;
22508c2ecf20Sopenharmony_ci};
22518c2ecf20Sopenharmony_ci
22528c2ecf20Sopenharmony_ciint __copy_msghdr_from_user(struct msghdr *kmsg,
22538c2ecf20Sopenharmony_ci			    struct user_msghdr __user *umsg,
22548c2ecf20Sopenharmony_ci			    struct sockaddr __user **save_addr,
22558c2ecf20Sopenharmony_ci			    struct iovec __user **uiov, size_t *nsegs)
22568c2ecf20Sopenharmony_ci{
22578c2ecf20Sopenharmony_ci	struct user_msghdr msg;
22588c2ecf20Sopenharmony_ci	ssize_t err;
22598c2ecf20Sopenharmony_ci
22608c2ecf20Sopenharmony_ci	if (copy_from_user(&msg, umsg, sizeof(*umsg)))
22618c2ecf20Sopenharmony_ci		return -EFAULT;
22628c2ecf20Sopenharmony_ci
22638c2ecf20Sopenharmony_ci	kmsg->msg_control_is_user = true;
22648c2ecf20Sopenharmony_ci	kmsg->msg_control_user = msg.msg_control;
22658c2ecf20Sopenharmony_ci	kmsg->msg_controllen = msg.msg_controllen;
22668c2ecf20Sopenharmony_ci	kmsg->msg_flags = msg.msg_flags;
22678c2ecf20Sopenharmony_ci
22688c2ecf20Sopenharmony_ci	kmsg->msg_namelen = msg.msg_namelen;
22698c2ecf20Sopenharmony_ci	if (!msg.msg_name)
22708c2ecf20Sopenharmony_ci		kmsg->msg_namelen = 0;
22718c2ecf20Sopenharmony_ci
22728c2ecf20Sopenharmony_ci	if (kmsg->msg_namelen < 0)
22738c2ecf20Sopenharmony_ci		return -EINVAL;
22748c2ecf20Sopenharmony_ci
22758c2ecf20Sopenharmony_ci	if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
22768c2ecf20Sopenharmony_ci		kmsg->msg_namelen = sizeof(struct sockaddr_storage);
22778c2ecf20Sopenharmony_ci
22788c2ecf20Sopenharmony_ci	if (save_addr)
22798c2ecf20Sopenharmony_ci		*save_addr = msg.msg_name;
22808c2ecf20Sopenharmony_ci
22818c2ecf20Sopenharmony_ci	if (msg.msg_name && kmsg->msg_namelen) {
22828c2ecf20Sopenharmony_ci		if (!save_addr) {
22838c2ecf20Sopenharmony_ci			err = move_addr_to_kernel(msg.msg_name,
22848c2ecf20Sopenharmony_ci						  kmsg->msg_namelen,
22858c2ecf20Sopenharmony_ci						  kmsg->msg_name);
22868c2ecf20Sopenharmony_ci			if (err < 0)
22878c2ecf20Sopenharmony_ci				return err;
22888c2ecf20Sopenharmony_ci		}
22898c2ecf20Sopenharmony_ci	} else {
22908c2ecf20Sopenharmony_ci		kmsg->msg_name = NULL;
22918c2ecf20Sopenharmony_ci		kmsg->msg_namelen = 0;
22928c2ecf20Sopenharmony_ci	}
22938c2ecf20Sopenharmony_ci
22948c2ecf20Sopenharmony_ci	if (msg.msg_iovlen > UIO_MAXIOV)
22958c2ecf20Sopenharmony_ci		return -EMSGSIZE;
22968c2ecf20Sopenharmony_ci
22978c2ecf20Sopenharmony_ci	kmsg->msg_iocb = NULL;
22988c2ecf20Sopenharmony_ci	*uiov = msg.msg_iov;
22998c2ecf20Sopenharmony_ci	*nsegs = msg.msg_iovlen;
23008c2ecf20Sopenharmony_ci	return 0;
23018c2ecf20Sopenharmony_ci}
23028c2ecf20Sopenharmony_ci
23038c2ecf20Sopenharmony_cistatic int copy_msghdr_from_user(struct msghdr *kmsg,
23048c2ecf20Sopenharmony_ci				 struct user_msghdr __user *umsg,
23058c2ecf20Sopenharmony_ci				 struct sockaddr __user **save_addr,
23068c2ecf20Sopenharmony_ci				 struct iovec **iov)
23078c2ecf20Sopenharmony_ci{
23088c2ecf20Sopenharmony_ci	struct user_msghdr msg;
23098c2ecf20Sopenharmony_ci	ssize_t err;
23108c2ecf20Sopenharmony_ci
23118c2ecf20Sopenharmony_ci	err = __copy_msghdr_from_user(kmsg, umsg, save_addr, &msg.msg_iov,
23128c2ecf20Sopenharmony_ci					&msg.msg_iovlen);
23138c2ecf20Sopenharmony_ci	if (err)
23148c2ecf20Sopenharmony_ci		return err;
23158c2ecf20Sopenharmony_ci
23168c2ecf20Sopenharmony_ci	err = import_iovec(save_addr ? READ : WRITE,
23178c2ecf20Sopenharmony_ci			    msg.msg_iov, msg.msg_iovlen,
23188c2ecf20Sopenharmony_ci			    UIO_FASTIOV, iov, &kmsg->msg_iter);
23198c2ecf20Sopenharmony_ci	return err < 0 ? err : 0;
23208c2ecf20Sopenharmony_ci}
23218c2ecf20Sopenharmony_ci
23228c2ecf20Sopenharmony_cistatic int ____sys_sendmsg(struct socket *sock, struct msghdr *msg_sys,
23238c2ecf20Sopenharmony_ci			   unsigned int flags, struct used_address *used_address,
23248c2ecf20Sopenharmony_ci			   unsigned int allowed_msghdr_flags)
23258c2ecf20Sopenharmony_ci{
23268c2ecf20Sopenharmony_ci	unsigned char ctl[sizeof(struct cmsghdr) + 20]
23278c2ecf20Sopenharmony_ci				__aligned(sizeof(__kernel_size_t));
23288c2ecf20Sopenharmony_ci	/* 20 is size of ipv6_pktinfo */
23298c2ecf20Sopenharmony_ci	unsigned char *ctl_buf = ctl;
23308c2ecf20Sopenharmony_ci	int ctl_len;
23318c2ecf20Sopenharmony_ci	ssize_t err;
23328c2ecf20Sopenharmony_ci
23338c2ecf20Sopenharmony_ci	err = -ENOBUFS;
23348c2ecf20Sopenharmony_ci
23358c2ecf20Sopenharmony_ci	if (msg_sys->msg_controllen > INT_MAX)
23368c2ecf20Sopenharmony_ci		goto out;
23378c2ecf20Sopenharmony_ci	flags |= (msg_sys->msg_flags & allowed_msghdr_flags);
23388c2ecf20Sopenharmony_ci	ctl_len = msg_sys->msg_controllen;
23398c2ecf20Sopenharmony_ci	if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
23408c2ecf20Sopenharmony_ci		err =
23418c2ecf20Sopenharmony_ci		    cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl,
23428c2ecf20Sopenharmony_ci						     sizeof(ctl));
23438c2ecf20Sopenharmony_ci		if (err)
23448c2ecf20Sopenharmony_ci			goto out;
23458c2ecf20Sopenharmony_ci		ctl_buf = msg_sys->msg_control;
23468c2ecf20Sopenharmony_ci		ctl_len = msg_sys->msg_controllen;
23478c2ecf20Sopenharmony_ci	} else if (ctl_len) {
23488c2ecf20Sopenharmony_ci		BUILD_BUG_ON(sizeof(struct cmsghdr) !=
23498c2ecf20Sopenharmony_ci			     CMSG_ALIGN(sizeof(struct cmsghdr)));
23508c2ecf20Sopenharmony_ci		if (ctl_len > sizeof(ctl)) {
23518c2ecf20Sopenharmony_ci			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
23528c2ecf20Sopenharmony_ci			if (ctl_buf == NULL)
23538c2ecf20Sopenharmony_ci				goto out;
23548c2ecf20Sopenharmony_ci		}
23558c2ecf20Sopenharmony_ci		err = -EFAULT;
23568c2ecf20Sopenharmony_ci		if (copy_from_user(ctl_buf, msg_sys->msg_control_user, ctl_len))
23578c2ecf20Sopenharmony_ci			goto out_freectl;
23588c2ecf20Sopenharmony_ci		msg_sys->msg_control = ctl_buf;
23598c2ecf20Sopenharmony_ci		msg_sys->msg_control_is_user = false;
23608c2ecf20Sopenharmony_ci	}
23618c2ecf20Sopenharmony_ci	msg_sys->msg_flags = flags;
23628c2ecf20Sopenharmony_ci
23638c2ecf20Sopenharmony_ci	if (sock->file->f_flags & O_NONBLOCK)
23648c2ecf20Sopenharmony_ci		msg_sys->msg_flags |= MSG_DONTWAIT;
23658c2ecf20Sopenharmony_ci	/*
23668c2ecf20Sopenharmony_ci	 * If this is sendmmsg() and current destination address is same as
23678c2ecf20Sopenharmony_ci	 * previously succeeded address, omit asking LSM's decision.
23688c2ecf20Sopenharmony_ci	 * used_address->name_len is initialized to UINT_MAX so that the first
23698c2ecf20Sopenharmony_ci	 * destination address never matches.
23708c2ecf20Sopenharmony_ci	 */
23718c2ecf20Sopenharmony_ci	if (used_address && msg_sys->msg_name &&
23728c2ecf20Sopenharmony_ci	    used_address->name_len == msg_sys->msg_namelen &&
23738c2ecf20Sopenharmony_ci	    !memcmp(&used_address->name, msg_sys->msg_name,
23748c2ecf20Sopenharmony_ci		    used_address->name_len)) {
23758c2ecf20Sopenharmony_ci		err = sock_sendmsg_nosec(sock, msg_sys);
23768c2ecf20Sopenharmony_ci		goto out_freectl;
23778c2ecf20Sopenharmony_ci	}
23788c2ecf20Sopenharmony_ci	err = __sock_sendmsg(sock, msg_sys);
23798c2ecf20Sopenharmony_ci	/*
23808c2ecf20Sopenharmony_ci	 * If this is sendmmsg() and sending to current destination address was
23818c2ecf20Sopenharmony_ci	 * successful, remember it.
23828c2ecf20Sopenharmony_ci	 */
23838c2ecf20Sopenharmony_ci	if (used_address && err >= 0) {
23848c2ecf20Sopenharmony_ci		used_address->name_len = msg_sys->msg_namelen;
23858c2ecf20Sopenharmony_ci		if (msg_sys->msg_name)
23868c2ecf20Sopenharmony_ci			memcpy(&used_address->name, msg_sys->msg_name,
23878c2ecf20Sopenharmony_ci			       used_address->name_len);
23888c2ecf20Sopenharmony_ci	}
23898c2ecf20Sopenharmony_ci
23908c2ecf20Sopenharmony_ciout_freectl:
23918c2ecf20Sopenharmony_ci	if (ctl_buf != ctl)
23928c2ecf20Sopenharmony_ci		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
23938c2ecf20Sopenharmony_ciout:
23948c2ecf20Sopenharmony_ci	return err;
23958c2ecf20Sopenharmony_ci}
23968c2ecf20Sopenharmony_ci
23978c2ecf20Sopenharmony_ciint sendmsg_copy_msghdr(struct msghdr *msg,
23988c2ecf20Sopenharmony_ci			struct user_msghdr __user *umsg, unsigned flags,
23998c2ecf20Sopenharmony_ci			struct iovec **iov)
24008c2ecf20Sopenharmony_ci{
24018c2ecf20Sopenharmony_ci	int err;
24028c2ecf20Sopenharmony_ci
24038c2ecf20Sopenharmony_ci	if (flags & MSG_CMSG_COMPAT) {
24048c2ecf20Sopenharmony_ci		struct compat_msghdr __user *msg_compat;
24058c2ecf20Sopenharmony_ci
24068c2ecf20Sopenharmony_ci		msg_compat = (struct compat_msghdr __user *) umsg;
24078c2ecf20Sopenharmony_ci		err = get_compat_msghdr(msg, msg_compat, NULL, iov);
24088c2ecf20Sopenharmony_ci	} else {
24098c2ecf20Sopenharmony_ci		err = copy_msghdr_from_user(msg, umsg, NULL, iov);
24108c2ecf20Sopenharmony_ci	}
24118c2ecf20Sopenharmony_ci	if (err < 0)
24128c2ecf20Sopenharmony_ci		return err;
24138c2ecf20Sopenharmony_ci
24148c2ecf20Sopenharmony_ci	return 0;
24158c2ecf20Sopenharmony_ci}
24168c2ecf20Sopenharmony_ci
24178c2ecf20Sopenharmony_cistatic int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
24188c2ecf20Sopenharmony_ci			 struct msghdr *msg_sys, unsigned int flags,
24198c2ecf20Sopenharmony_ci			 struct used_address *used_address,
24208c2ecf20Sopenharmony_ci			 unsigned int allowed_msghdr_flags)
24218c2ecf20Sopenharmony_ci{
24228c2ecf20Sopenharmony_ci	struct sockaddr_storage address;
24238c2ecf20Sopenharmony_ci	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
24248c2ecf20Sopenharmony_ci	ssize_t err;
24258c2ecf20Sopenharmony_ci
24268c2ecf20Sopenharmony_ci	msg_sys->msg_name = &address;
24278c2ecf20Sopenharmony_ci
24288c2ecf20Sopenharmony_ci	err = sendmsg_copy_msghdr(msg_sys, msg, flags, &iov);
24298c2ecf20Sopenharmony_ci	if (err < 0)
24308c2ecf20Sopenharmony_ci		return err;
24318c2ecf20Sopenharmony_ci
24328c2ecf20Sopenharmony_ci	err = ____sys_sendmsg(sock, msg_sys, flags, used_address,
24338c2ecf20Sopenharmony_ci				allowed_msghdr_flags);
24348c2ecf20Sopenharmony_ci	kfree(iov);
24358c2ecf20Sopenharmony_ci	return err;
24368c2ecf20Sopenharmony_ci}
24378c2ecf20Sopenharmony_ci
24388c2ecf20Sopenharmony_ci/*
24398c2ecf20Sopenharmony_ci *	BSD sendmsg interface
24408c2ecf20Sopenharmony_ci */
24418c2ecf20Sopenharmony_cilong __sys_sendmsg_sock(struct socket *sock, struct msghdr *msg,
24428c2ecf20Sopenharmony_ci			unsigned int flags)
24438c2ecf20Sopenharmony_ci{
24448c2ecf20Sopenharmony_ci	return ____sys_sendmsg(sock, msg, flags, NULL, 0);
24458c2ecf20Sopenharmony_ci}
24468c2ecf20Sopenharmony_ci
24478c2ecf20Sopenharmony_cilong __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned int flags,
24488c2ecf20Sopenharmony_ci		   bool forbid_cmsg_compat)
24498c2ecf20Sopenharmony_ci{
24508c2ecf20Sopenharmony_ci	int fput_needed, err;
24518c2ecf20Sopenharmony_ci	struct msghdr msg_sys;
24528c2ecf20Sopenharmony_ci	struct socket *sock;
24538c2ecf20Sopenharmony_ci
24548c2ecf20Sopenharmony_ci	if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT))
24558c2ecf20Sopenharmony_ci		return -EINVAL;
24568c2ecf20Sopenharmony_ci
24578c2ecf20Sopenharmony_ci	sock = sockfd_lookup_light(fd, &err, &fput_needed);
24588c2ecf20Sopenharmony_ci	if (!sock)
24598c2ecf20Sopenharmony_ci		goto out;
24608c2ecf20Sopenharmony_ci
24618c2ecf20Sopenharmony_ci	err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL, 0);
24628c2ecf20Sopenharmony_ci
24638c2ecf20Sopenharmony_ci	fput_light(sock->file, fput_needed);
24648c2ecf20Sopenharmony_ciout:
24658c2ecf20Sopenharmony_ci	return err;
24668c2ecf20Sopenharmony_ci}
24678c2ecf20Sopenharmony_ci
24688c2ecf20Sopenharmony_ciSYSCALL_DEFINE3(sendmsg, int, fd, struct user_msghdr __user *, msg, unsigned int, flags)
24698c2ecf20Sopenharmony_ci{
24708c2ecf20Sopenharmony_ci	return __sys_sendmsg(fd, msg, flags, true);
24718c2ecf20Sopenharmony_ci}
24728c2ecf20Sopenharmony_ci
24738c2ecf20Sopenharmony_ci/*
24748c2ecf20Sopenharmony_ci *	Linux sendmmsg interface
24758c2ecf20Sopenharmony_ci */
24768c2ecf20Sopenharmony_ci
24778c2ecf20Sopenharmony_ciint __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
24788c2ecf20Sopenharmony_ci		   unsigned int flags, bool forbid_cmsg_compat)
24798c2ecf20Sopenharmony_ci{
24808c2ecf20Sopenharmony_ci	int fput_needed, err, datagrams;
24818c2ecf20Sopenharmony_ci	struct socket *sock;
24828c2ecf20Sopenharmony_ci	struct mmsghdr __user *entry;
24838c2ecf20Sopenharmony_ci	struct compat_mmsghdr __user *compat_entry;
24848c2ecf20Sopenharmony_ci	struct msghdr msg_sys;
24858c2ecf20Sopenharmony_ci	struct used_address used_address;
24868c2ecf20Sopenharmony_ci	unsigned int oflags = flags;
24878c2ecf20Sopenharmony_ci
24888c2ecf20Sopenharmony_ci	if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT))
24898c2ecf20Sopenharmony_ci		return -EINVAL;
24908c2ecf20Sopenharmony_ci
24918c2ecf20Sopenharmony_ci	if (vlen > UIO_MAXIOV)
24928c2ecf20Sopenharmony_ci		vlen = UIO_MAXIOV;
24938c2ecf20Sopenharmony_ci
24948c2ecf20Sopenharmony_ci	datagrams = 0;
24958c2ecf20Sopenharmony_ci
24968c2ecf20Sopenharmony_ci	sock = sockfd_lookup_light(fd, &err, &fput_needed);
24978c2ecf20Sopenharmony_ci	if (!sock)
24988c2ecf20Sopenharmony_ci		return err;
24998c2ecf20Sopenharmony_ci
25008c2ecf20Sopenharmony_ci	used_address.name_len = UINT_MAX;
25018c2ecf20Sopenharmony_ci	entry = mmsg;
25028c2ecf20Sopenharmony_ci	compat_entry = (struct compat_mmsghdr __user *)mmsg;
25038c2ecf20Sopenharmony_ci	err = 0;
25048c2ecf20Sopenharmony_ci	flags |= MSG_BATCH;
25058c2ecf20Sopenharmony_ci
25068c2ecf20Sopenharmony_ci	while (datagrams < vlen) {
25078c2ecf20Sopenharmony_ci		if (datagrams == vlen - 1)
25088c2ecf20Sopenharmony_ci			flags = oflags;
25098c2ecf20Sopenharmony_ci
25108c2ecf20Sopenharmony_ci		if (MSG_CMSG_COMPAT & flags) {
25118c2ecf20Sopenharmony_ci			err = ___sys_sendmsg(sock, (struct user_msghdr __user *)compat_entry,
25128c2ecf20Sopenharmony_ci					     &msg_sys, flags, &used_address, MSG_EOR);
25138c2ecf20Sopenharmony_ci			if (err < 0)
25148c2ecf20Sopenharmony_ci				break;
25158c2ecf20Sopenharmony_ci			err = __put_user(err, &compat_entry->msg_len);
25168c2ecf20Sopenharmony_ci			++compat_entry;
25178c2ecf20Sopenharmony_ci		} else {
25188c2ecf20Sopenharmony_ci			err = ___sys_sendmsg(sock,
25198c2ecf20Sopenharmony_ci					     (struct user_msghdr __user *)entry,
25208c2ecf20Sopenharmony_ci					     &msg_sys, flags, &used_address, MSG_EOR);
25218c2ecf20Sopenharmony_ci			if (err < 0)
25228c2ecf20Sopenharmony_ci				break;
25238c2ecf20Sopenharmony_ci			err = put_user(err, &entry->msg_len);
25248c2ecf20Sopenharmony_ci			++entry;
25258c2ecf20Sopenharmony_ci		}
25268c2ecf20Sopenharmony_ci
25278c2ecf20Sopenharmony_ci		if (err)
25288c2ecf20Sopenharmony_ci			break;
25298c2ecf20Sopenharmony_ci		++datagrams;
25308c2ecf20Sopenharmony_ci		if (msg_data_left(&msg_sys))
25318c2ecf20Sopenharmony_ci			break;
25328c2ecf20Sopenharmony_ci		cond_resched();
25338c2ecf20Sopenharmony_ci	}
25348c2ecf20Sopenharmony_ci
25358c2ecf20Sopenharmony_ci	fput_light(sock->file, fput_needed);
25368c2ecf20Sopenharmony_ci
25378c2ecf20Sopenharmony_ci	/* We only return an error if no datagrams were able to be sent */
25388c2ecf20Sopenharmony_ci	if (datagrams != 0)
25398c2ecf20Sopenharmony_ci		return datagrams;
25408c2ecf20Sopenharmony_ci
25418c2ecf20Sopenharmony_ci	return err;
25428c2ecf20Sopenharmony_ci}
25438c2ecf20Sopenharmony_ci
25448c2ecf20Sopenharmony_ciSYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
25458c2ecf20Sopenharmony_ci		unsigned int, vlen, unsigned int, flags)
25468c2ecf20Sopenharmony_ci{
25478c2ecf20Sopenharmony_ci	return __sys_sendmmsg(fd, mmsg, vlen, flags, true);
25488c2ecf20Sopenharmony_ci}
25498c2ecf20Sopenharmony_ci
25508c2ecf20Sopenharmony_ciint recvmsg_copy_msghdr(struct msghdr *msg,
25518c2ecf20Sopenharmony_ci			struct user_msghdr __user *umsg, unsigned flags,
25528c2ecf20Sopenharmony_ci			struct sockaddr __user **uaddr,
25538c2ecf20Sopenharmony_ci			struct iovec **iov)
25548c2ecf20Sopenharmony_ci{
25558c2ecf20Sopenharmony_ci	ssize_t err;
25568c2ecf20Sopenharmony_ci
25578c2ecf20Sopenharmony_ci	if (MSG_CMSG_COMPAT & flags) {
25588c2ecf20Sopenharmony_ci		struct compat_msghdr __user *msg_compat;
25598c2ecf20Sopenharmony_ci
25608c2ecf20Sopenharmony_ci		msg_compat = (struct compat_msghdr __user *) umsg;
25618c2ecf20Sopenharmony_ci		err = get_compat_msghdr(msg, msg_compat, uaddr, iov);
25628c2ecf20Sopenharmony_ci	} else {
25638c2ecf20Sopenharmony_ci		err = copy_msghdr_from_user(msg, umsg, uaddr, iov);
25648c2ecf20Sopenharmony_ci	}
25658c2ecf20Sopenharmony_ci	if (err < 0)
25668c2ecf20Sopenharmony_ci		return err;
25678c2ecf20Sopenharmony_ci
25688c2ecf20Sopenharmony_ci	return 0;
25698c2ecf20Sopenharmony_ci}
25708c2ecf20Sopenharmony_ci
25718c2ecf20Sopenharmony_cistatic int ____sys_recvmsg(struct socket *sock, struct msghdr *msg_sys,
25728c2ecf20Sopenharmony_ci			   struct user_msghdr __user *msg,
25738c2ecf20Sopenharmony_ci			   struct sockaddr __user *uaddr,
25748c2ecf20Sopenharmony_ci			   unsigned int flags, int nosec)
25758c2ecf20Sopenharmony_ci{
25768c2ecf20Sopenharmony_ci	struct compat_msghdr __user *msg_compat =
25778c2ecf20Sopenharmony_ci					(struct compat_msghdr __user *) msg;
25788c2ecf20Sopenharmony_ci	int __user *uaddr_len = COMPAT_NAMELEN(msg);
25798c2ecf20Sopenharmony_ci	struct sockaddr_storage addr;
25808c2ecf20Sopenharmony_ci	unsigned long cmsg_ptr;
25818c2ecf20Sopenharmony_ci	int len;
25828c2ecf20Sopenharmony_ci	ssize_t err;
25838c2ecf20Sopenharmony_ci
25848c2ecf20Sopenharmony_ci	msg_sys->msg_name = &addr;
25858c2ecf20Sopenharmony_ci	cmsg_ptr = (unsigned long)msg_sys->msg_control;
25868c2ecf20Sopenharmony_ci	msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
25878c2ecf20Sopenharmony_ci
25888c2ecf20Sopenharmony_ci	/* We assume all kernel code knows the size of sockaddr_storage */
25898c2ecf20Sopenharmony_ci	msg_sys->msg_namelen = 0;
25908c2ecf20Sopenharmony_ci
25918c2ecf20Sopenharmony_ci	if (sock->file->f_flags & O_NONBLOCK)
25928c2ecf20Sopenharmony_ci		flags |= MSG_DONTWAIT;
25938c2ecf20Sopenharmony_ci
25948c2ecf20Sopenharmony_ci	if (unlikely(nosec))
25958c2ecf20Sopenharmony_ci		err = sock_recvmsg_nosec(sock, msg_sys, flags);
25968c2ecf20Sopenharmony_ci	else
25978c2ecf20Sopenharmony_ci		err = sock_recvmsg(sock, msg_sys, flags);
25988c2ecf20Sopenharmony_ci
25998c2ecf20Sopenharmony_ci	if (err < 0)
26008c2ecf20Sopenharmony_ci		goto out;
26018c2ecf20Sopenharmony_ci	len = err;
26028c2ecf20Sopenharmony_ci
26038c2ecf20Sopenharmony_ci	if (uaddr != NULL) {
26048c2ecf20Sopenharmony_ci		err = move_addr_to_user(&addr,
26058c2ecf20Sopenharmony_ci					msg_sys->msg_namelen, uaddr,
26068c2ecf20Sopenharmony_ci					uaddr_len);
26078c2ecf20Sopenharmony_ci		if (err < 0)
26088c2ecf20Sopenharmony_ci			goto out;
26098c2ecf20Sopenharmony_ci	}
26108c2ecf20Sopenharmony_ci	err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
26118c2ecf20Sopenharmony_ci			 COMPAT_FLAGS(msg));
26128c2ecf20Sopenharmony_ci	if (err)
26138c2ecf20Sopenharmony_ci		goto out;
26148c2ecf20Sopenharmony_ci	if (MSG_CMSG_COMPAT & flags)
26158c2ecf20Sopenharmony_ci		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
26168c2ecf20Sopenharmony_ci				 &msg_compat->msg_controllen);
26178c2ecf20Sopenharmony_ci	else
26188c2ecf20Sopenharmony_ci		err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
26198c2ecf20Sopenharmony_ci				 &msg->msg_controllen);
26208c2ecf20Sopenharmony_ci	if (err)
26218c2ecf20Sopenharmony_ci		goto out;
26228c2ecf20Sopenharmony_ci	err = len;
26238c2ecf20Sopenharmony_ciout:
26248c2ecf20Sopenharmony_ci	return err;
26258c2ecf20Sopenharmony_ci}
26268c2ecf20Sopenharmony_ci
26278c2ecf20Sopenharmony_cistatic int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg,
26288c2ecf20Sopenharmony_ci			 struct msghdr *msg_sys, unsigned int flags, int nosec)
26298c2ecf20Sopenharmony_ci{
26308c2ecf20Sopenharmony_ci	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
26318c2ecf20Sopenharmony_ci	/* user mode address pointers */
26328c2ecf20Sopenharmony_ci	struct sockaddr __user *uaddr;
26338c2ecf20Sopenharmony_ci	ssize_t err;
26348c2ecf20Sopenharmony_ci
26358c2ecf20Sopenharmony_ci	err = recvmsg_copy_msghdr(msg_sys, msg, flags, &uaddr, &iov);
26368c2ecf20Sopenharmony_ci	if (err < 0)
26378c2ecf20Sopenharmony_ci		return err;
26388c2ecf20Sopenharmony_ci
26398c2ecf20Sopenharmony_ci	err = ____sys_recvmsg(sock, msg_sys, msg, uaddr, flags, nosec);
26408c2ecf20Sopenharmony_ci	kfree(iov);
26418c2ecf20Sopenharmony_ci	return err;
26428c2ecf20Sopenharmony_ci}
26438c2ecf20Sopenharmony_ci
26448c2ecf20Sopenharmony_ci/*
26458c2ecf20Sopenharmony_ci *	BSD recvmsg interface
26468c2ecf20Sopenharmony_ci */
26478c2ecf20Sopenharmony_ci
26488c2ecf20Sopenharmony_cilong __sys_recvmsg_sock(struct socket *sock, struct msghdr *msg,
26498c2ecf20Sopenharmony_ci			struct user_msghdr __user *umsg,
26508c2ecf20Sopenharmony_ci			struct sockaddr __user *uaddr, unsigned int flags)
26518c2ecf20Sopenharmony_ci{
26528c2ecf20Sopenharmony_ci	return ____sys_recvmsg(sock, msg, umsg, uaddr, flags, 0);
26538c2ecf20Sopenharmony_ci}
26548c2ecf20Sopenharmony_ci
26558c2ecf20Sopenharmony_cilong __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned int flags,
26568c2ecf20Sopenharmony_ci		   bool forbid_cmsg_compat)
26578c2ecf20Sopenharmony_ci{
26588c2ecf20Sopenharmony_ci	int fput_needed, err;
26598c2ecf20Sopenharmony_ci	struct msghdr msg_sys;
26608c2ecf20Sopenharmony_ci	struct socket *sock;
26618c2ecf20Sopenharmony_ci
26628c2ecf20Sopenharmony_ci	if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT))
26638c2ecf20Sopenharmony_ci		return -EINVAL;
26648c2ecf20Sopenharmony_ci
26658c2ecf20Sopenharmony_ci	sock = sockfd_lookup_light(fd, &err, &fput_needed);
26668c2ecf20Sopenharmony_ci	if (!sock)
26678c2ecf20Sopenharmony_ci		goto out;
26688c2ecf20Sopenharmony_ci
26698c2ecf20Sopenharmony_ci	err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0);
26708c2ecf20Sopenharmony_ci
26718c2ecf20Sopenharmony_ci	fput_light(sock->file, fput_needed);
26728c2ecf20Sopenharmony_ciout:
26738c2ecf20Sopenharmony_ci	return err;
26748c2ecf20Sopenharmony_ci}
26758c2ecf20Sopenharmony_ci
26768c2ecf20Sopenharmony_ciSYSCALL_DEFINE3(recvmsg, int, fd, struct user_msghdr __user *, msg,
26778c2ecf20Sopenharmony_ci		unsigned int, flags)
26788c2ecf20Sopenharmony_ci{
26798c2ecf20Sopenharmony_ci	return __sys_recvmsg(fd, msg, flags, true);
26808c2ecf20Sopenharmony_ci}
26818c2ecf20Sopenharmony_ci
26828c2ecf20Sopenharmony_ci/*
26838c2ecf20Sopenharmony_ci *     Linux recvmmsg interface
26848c2ecf20Sopenharmony_ci */
26858c2ecf20Sopenharmony_ci
26868c2ecf20Sopenharmony_cistatic int do_recvmmsg(int fd, struct mmsghdr __user *mmsg,
26878c2ecf20Sopenharmony_ci			  unsigned int vlen, unsigned int flags,
26888c2ecf20Sopenharmony_ci			  struct timespec64 *timeout)
26898c2ecf20Sopenharmony_ci{
26908c2ecf20Sopenharmony_ci	int fput_needed, err, datagrams;
26918c2ecf20Sopenharmony_ci	struct socket *sock;
26928c2ecf20Sopenharmony_ci	struct mmsghdr __user *entry;
26938c2ecf20Sopenharmony_ci	struct compat_mmsghdr __user *compat_entry;
26948c2ecf20Sopenharmony_ci	struct msghdr msg_sys;
26958c2ecf20Sopenharmony_ci	struct timespec64 end_time;
26968c2ecf20Sopenharmony_ci	struct timespec64 timeout64;
26978c2ecf20Sopenharmony_ci
26988c2ecf20Sopenharmony_ci	if (timeout &&
26998c2ecf20Sopenharmony_ci	    poll_select_set_timeout(&end_time, timeout->tv_sec,
27008c2ecf20Sopenharmony_ci				    timeout->tv_nsec))
27018c2ecf20Sopenharmony_ci		return -EINVAL;
27028c2ecf20Sopenharmony_ci
27038c2ecf20Sopenharmony_ci	datagrams = 0;
27048c2ecf20Sopenharmony_ci
27058c2ecf20Sopenharmony_ci	sock = sockfd_lookup_light(fd, &err, &fput_needed);
27068c2ecf20Sopenharmony_ci	if (!sock)
27078c2ecf20Sopenharmony_ci		return err;
27088c2ecf20Sopenharmony_ci
27098c2ecf20Sopenharmony_ci	if (likely(!(flags & MSG_ERRQUEUE))) {
27108c2ecf20Sopenharmony_ci		err = sock_error(sock->sk);
27118c2ecf20Sopenharmony_ci		if (err) {
27128c2ecf20Sopenharmony_ci			datagrams = err;
27138c2ecf20Sopenharmony_ci			goto out_put;
27148c2ecf20Sopenharmony_ci		}
27158c2ecf20Sopenharmony_ci	}
27168c2ecf20Sopenharmony_ci
27178c2ecf20Sopenharmony_ci	entry = mmsg;
27188c2ecf20Sopenharmony_ci	compat_entry = (struct compat_mmsghdr __user *)mmsg;
27198c2ecf20Sopenharmony_ci
27208c2ecf20Sopenharmony_ci	while (datagrams < vlen) {
27218c2ecf20Sopenharmony_ci		/*
27228c2ecf20Sopenharmony_ci		 * No need to ask LSM for more than the first datagram.
27238c2ecf20Sopenharmony_ci		 */
27248c2ecf20Sopenharmony_ci		if (MSG_CMSG_COMPAT & flags) {
27258c2ecf20Sopenharmony_ci			err = ___sys_recvmsg(sock, (struct user_msghdr __user *)compat_entry,
27268c2ecf20Sopenharmony_ci					     &msg_sys, flags & ~MSG_WAITFORONE,
27278c2ecf20Sopenharmony_ci					     datagrams);
27288c2ecf20Sopenharmony_ci			if (err < 0)
27298c2ecf20Sopenharmony_ci				break;
27308c2ecf20Sopenharmony_ci			err = __put_user(err, &compat_entry->msg_len);
27318c2ecf20Sopenharmony_ci			++compat_entry;
27328c2ecf20Sopenharmony_ci		} else {
27338c2ecf20Sopenharmony_ci			err = ___sys_recvmsg(sock,
27348c2ecf20Sopenharmony_ci					     (struct user_msghdr __user *)entry,
27358c2ecf20Sopenharmony_ci					     &msg_sys, flags & ~MSG_WAITFORONE,
27368c2ecf20Sopenharmony_ci					     datagrams);
27378c2ecf20Sopenharmony_ci			if (err < 0)
27388c2ecf20Sopenharmony_ci				break;
27398c2ecf20Sopenharmony_ci			err = put_user(err, &entry->msg_len);
27408c2ecf20Sopenharmony_ci			++entry;
27418c2ecf20Sopenharmony_ci		}
27428c2ecf20Sopenharmony_ci
27438c2ecf20Sopenharmony_ci		if (err)
27448c2ecf20Sopenharmony_ci			break;
27458c2ecf20Sopenharmony_ci		++datagrams;
27468c2ecf20Sopenharmony_ci
27478c2ecf20Sopenharmony_ci		/* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
27488c2ecf20Sopenharmony_ci		if (flags & MSG_WAITFORONE)
27498c2ecf20Sopenharmony_ci			flags |= MSG_DONTWAIT;
27508c2ecf20Sopenharmony_ci
27518c2ecf20Sopenharmony_ci		if (timeout) {
27528c2ecf20Sopenharmony_ci			ktime_get_ts64(&timeout64);
27538c2ecf20Sopenharmony_ci			*timeout = timespec64_sub(end_time, timeout64);
27548c2ecf20Sopenharmony_ci			if (timeout->tv_sec < 0) {
27558c2ecf20Sopenharmony_ci				timeout->tv_sec = timeout->tv_nsec = 0;
27568c2ecf20Sopenharmony_ci				break;
27578c2ecf20Sopenharmony_ci			}
27588c2ecf20Sopenharmony_ci
27598c2ecf20Sopenharmony_ci			/* Timeout, return less than vlen datagrams */
27608c2ecf20Sopenharmony_ci			if (timeout->tv_nsec == 0 && timeout->tv_sec == 0)
27618c2ecf20Sopenharmony_ci				break;
27628c2ecf20Sopenharmony_ci		}
27638c2ecf20Sopenharmony_ci
27648c2ecf20Sopenharmony_ci		/* Out of band data, return right away */
27658c2ecf20Sopenharmony_ci		if (msg_sys.msg_flags & MSG_OOB)
27668c2ecf20Sopenharmony_ci			break;
27678c2ecf20Sopenharmony_ci		cond_resched();
27688c2ecf20Sopenharmony_ci	}
27698c2ecf20Sopenharmony_ci
27708c2ecf20Sopenharmony_ci	if (err == 0)
27718c2ecf20Sopenharmony_ci		goto out_put;
27728c2ecf20Sopenharmony_ci
27738c2ecf20Sopenharmony_ci	if (datagrams == 0) {
27748c2ecf20Sopenharmony_ci		datagrams = err;
27758c2ecf20Sopenharmony_ci		goto out_put;
27768c2ecf20Sopenharmony_ci	}
27778c2ecf20Sopenharmony_ci
27788c2ecf20Sopenharmony_ci	/*
27798c2ecf20Sopenharmony_ci	 * We may return less entries than requested (vlen) if the
27808c2ecf20Sopenharmony_ci	 * sock is non block and there aren't enough datagrams...
27818c2ecf20Sopenharmony_ci	 */
27828c2ecf20Sopenharmony_ci	if (err != -EAGAIN) {
27838c2ecf20Sopenharmony_ci		/*
27848c2ecf20Sopenharmony_ci		 * ... or  if recvmsg returns an error after we
27858c2ecf20Sopenharmony_ci		 * received some datagrams, where we record the
27868c2ecf20Sopenharmony_ci		 * error to return on the next call or if the
27878c2ecf20Sopenharmony_ci		 * app asks about it using getsockopt(SO_ERROR).
27888c2ecf20Sopenharmony_ci		 */
27898c2ecf20Sopenharmony_ci		WRITE_ONCE(sock->sk->sk_err, -err);
27908c2ecf20Sopenharmony_ci	}
27918c2ecf20Sopenharmony_ciout_put:
27928c2ecf20Sopenharmony_ci	fput_light(sock->file, fput_needed);
27938c2ecf20Sopenharmony_ci
27948c2ecf20Sopenharmony_ci	return datagrams;
27958c2ecf20Sopenharmony_ci}
27968c2ecf20Sopenharmony_ci
27978c2ecf20Sopenharmony_ciint __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg,
27988c2ecf20Sopenharmony_ci		   unsigned int vlen, unsigned int flags,
27998c2ecf20Sopenharmony_ci		   struct __kernel_timespec __user *timeout,
28008c2ecf20Sopenharmony_ci		   struct old_timespec32 __user *timeout32)
28018c2ecf20Sopenharmony_ci{
28028c2ecf20Sopenharmony_ci	int datagrams;
28038c2ecf20Sopenharmony_ci	struct timespec64 timeout_sys;
28048c2ecf20Sopenharmony_ci
28058c2ecf20Sopenharmony_ci	if (timeout && get_timespec64(&timeout_sys, timeout))
28068c2ecf20Sopenharmony_ci		return -EFAULT;
28078c2ecf20Sopenharmony_ci
28088c2ecf20Sopenharmony_ci	if (timeout32 && get_old_timespec32(&timeout_sys, timeout32))
28098c2ecf20Sopenharmony_ci		return -EFAULT;
28108c2ecf20Sopenharmony_ci
28118c2ecf20Sopenharmony_ci	if (!timeout && !timeout32)
28128c2ecf20Sopenharmony_ci		return do_recvmmsg(fd, mmsg, vlen, flags, NULL);
28138c2ecf20Sopenharmony_ci
28148c2ecf20Sopenharmony_ci	datagrams = do_recvmmsg(fd, mmsg, vlen, flags, &timeout_sys);
28158c2ecf20Sopenharmony_ci
28168c2ecf20Sopenharmony_ci	if (datagrams <= 0)
28178c2ecf20Sopenharmony_ci		return datagrams;
28188c2ecf20Sopenharmony_ci
28198c2ecf20Sopenharmony_ci	if (timeout && put_timespec64(&timeout_sys, timeout))
28208c2ecf20Sopenharmony_ci		datagrams = -EFAULT;
28218c2ecf20Sopenharmony_ci
28228c2ecf20Sopenharmony_ci	if (timeout32 && put_old_timespec32(&timeout_sys, timeout32))
28238c2ecf20Sopenharmony_ci		datagrams = -EFAULT;
28248c2ecf20Sopenharmony_ci
28258c2ecf20Sopenharmony_ci	return datagrams;
28268c2ecf20Sopenharmony_ci}
28278c2ecf20Sopenharmony_ci
28288c2ecf20Sopenharmony_ciSYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
28298c2ecf20Sopenharmony_ci		unsigned int, vlen, unsigned int, flags,
28308c2ecf20Sopenharmony_ci		struct __kernel_timespec __user *, timeout)
28318c2ecf20Sopenharmony_ci{
28328c2ecf20Sopenharmony_ci	if (flags & MSG_CMSG_COMPAT)
28338c2ecf20Sopenharmony_ci		return -EINVAL;
28348c2ecf20Sopenharmony_ci
28358c2ecf20Sopenharmony_ci	return __sys_recvmmsg(fd, mmsg, vlen, flags, timeout, NULL);
28368c2ecf20Sopenharmony_ci}
28378c2ecf20Sopenharmony_ci
28388c2ecf20Sopenharmony_ci#ifdef CONFIG_COMPAT_32BIT_TIME
28398c2ecf20Sopenharmony_ciSYSCALL_DEFINE5(recvmmsg_time32, int, fd, struct mmsghdr __user *, mmsg,
28408c2ecf20Sopenharmony_ci		unsigned int, vlen, unsigned int, flags,
28418c2ecf20Sopenharmony_ci		struct old_timespec32 __user *, timeout)
28428c2ecf20Sopenharmony_ci{
28438c2ecf20Sopenharmony_ci	if (flags & MSG_CMSG_COMPAT)
28448c2ecf20Sopenharmony_ci		return -EINVAL;
28458c2ecf20Sopenharmony_ci
28468c2ecf20Sopenharmony_ci	return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL, timeout);
28478c2ecf20Sopenharmony_ci}
28488c2ecf20Sopenharmony_ci#endif
28498c2ecf20Sopenharmony_ci
28508c2ecf20Sopenharmony_ci#ifdef __ARCH_WANT_SYS_SOCKETCALL
28518c2ecf20Sopenharmony_ci/* Argument list sizes for sys_socketcall */
28528c2ecf20Sopenharmony_ci#define AL(x) ((x) * sizeof(unsigned long))
28538c2ecf20Sopenharmony_cistatic const unsigned char nargs[21] = {
28548c2ecf20Sopenharmony_ci	AL(0), AL(3), AL(3), AL(3), AL(2), AL(3),
28558c2ecf20Sopenharmony_ci	AL(3), AL(3), AL(4), AL(4), AL(4), AL(6),
28568c2ecf20Sopenharmony_ci	AL(6), AL(2), AL(5), AL(5), AL(3), AL(3),
28578c2ecf20Sopenharmony_ci	AL(4), AL(5), AL(4)
28588c2ecf20Sopenharmony_ci};
28598c2ecf20Sopenharmony_ci
28608c2ecf20Sopenharmony_ci#undef AL
28618c2ecf20Sopenharmony_ci
28628c2ecf20Sopenharmony_ci/*
28638c2ecf20Sopenharmony_ci *	System call vectors.
28648c2ecf20Sopenharmony_ci *
28658c2ecf20Sopenharmony_ci *	Argument checking cleaned up. Saved 20% in size.
28668c2ecf20Sopenharmony_ci *  This function doesn't need to set the kernel lock because
28678c2ecf20Sopenharmony_ci *  it is set by the callees.
28688c2ecf20Sopenharmony_ci */
28698c2ecf20Sopenharmony_ci
28708c2ecf20Sopenharmony_ciSYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
28718c2ecf20Sopenharmony_ci{
28728c2ecf20Sopenharmony_ci	unsigned long a[AUDITSC_ARGS];
28738c2ecf20Sopenharmony_ci	unsigned long a0, a1;
28748c2ecf20Sopenharmony_ci	int err;
28758c2ecf20Sopenharmony_ci	unsigned int len;
28768c2ecf20Sopenharmony_ci
28778c2ecf20Sopenharmony_ci	if (call < 1 || call > SYS_SENDMMSG)
28788c2ecf20Sopenharmony_ci		return -EINVAL;
28798c2ecf20Sopenharmony_ci	call = array_index_nospec(call, SYS_SENDMMSG + 1);
28808c2ecf20Sopenharmony_ci
28818c2ecf20Sopenharmony_ci	len = nargs[call];
28828c2ecf20Sopenharmony_ci	if (len > sizeof(a))
28838c2ecf20Sopenharmony_ci		return -EINVAL;
28848c2ecf20Sopenharmony_ci
28858c2ecf20Sopenharmony_ci	/* copy_from_user should be SMP safe. */
28868c2ecf20Sopenharmony_ci	if (copy_from_user(a, args, len))
28878c2ecf20Sopenharmony_ci		return -EFAULT;
28888c2ecf20Sopenharmony_ci
28898c2ecf20Sopenharmony_ci	err = audit_socketcall(nargs[call] / sizeof(unsigned long), a);
28908c2ecf20Sopenharmony_ci	if (err)
28918c2ecf20Sopenharmony_ci		return err;
28928c2ecf20Sopenharmony_ci
28938c2ecf20Sopenharmony_ci	a0 = a[0];
28948c2ecf20Sopenharmony_ci	a1 = a[1];
28958c2ecf20Sopenharmony_ci
28968c2ecf20Sopenharmony_ci	switch (call) {
28978c2ecf20Sopenharmony_ci	case SYS_SOCKET:
28988c2ecf20Sopenharmony_ci		err = __sys_socket(a0, a1, a[2]);
28998c2ecf20Sopenharmony_ci		break;
29008c2ecf20Sopenharmony_ci	case SYS_BIND:
29018c2ecf20Sopenharmony_ci		err = __sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
29028c2ecf20Sopenharmony_ci		break;
29038c2ecf20Sopenharmony_ci	case SYS_CONNECT:
29048c2ecf20Sopenharmony_ci		err = __sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
29058c2ecf20Sopenharmony_ci		break;
29068c2ecf20Sopenharmony_ci	case SYS_LISTEN:
29078c2ecf20Sopenharmony_ci		err = __sys_listen(a0, a1);
29088c2ecf20Sopenharmony_ci		break;
29098c2ecf20Sopenharmony_ci	case SYS_ACCEPT:
29108c2ecf20Sopenharmony_ci		err = __sys_accept4(a0, (struct sockaddr __user *)a1,
29118c2ecf20Sopenharmony_ci				    (int __user *)a[2], 0);
29128c2ecf20Sopenharmony_ci		break;
29138c2ecf20Sopenharmony_ci	case SYS_GETSOCKNAME:
29148c2ecf20Sopenharmony_ci		err =
29158c2ecf20Sopenharmony_ci		    __sys_getsockname(a0, (struct sockaddr __user *)a1,
29168c2ecf20Sopenharmony_ci				      (int __user *)a[2]);
29178c2ecf20Sopenharmony_ci		break;
29188c2ecf20Sopenharmony_ci	case SYS_GETPEERNAME:
29198c2ecf20Sopenharmony_ci		err =
29208c2ecf20Sopenharmony_ci		    __sys_getpeername(a0, (struct sockaddr __user *)a1,
29218c2ecf20Sopenharmony_ci				      (int __user *)a[2]);
29228c2ecf20Sopenharmony_ci		break;
29238c2ecf20Sopenharmony_ci	case SYS_SOCKETPAIR:
29248c2ecf20Sopenharmony_ci		err = __sys_socketpair(a0, a1, a[2], (int __user *)a[3]);
29258c2ecf20Sopenharmony_ci		break;
29268c2ecf20Sopenharmony_ci	case SYS_SEND:
29278c2ecf20Sopenharmony_ci		err = __sys_sendto(a0, (void __user *)a1, a[2], a[3],
29288c2ecf20Sopenharmony_ci				   NULL, 0);
29298c2ecf20Sopenharmony_ci		break;
29308c2ecf20Sopenharmony_ci	case SYS_SENDTO:
29318c2ecf20Sopenharmony_ci		err = __sys_sendto(a0, (void __user *)a1, a[2], a[3],
29328c2ecf20Sopenharmony_ci				   (struct sockaddr __user *)a[4], a[5]);
29338c2ecf20Sopenharmony_ci		break;
29348c2ecf20Sopenharmony_ci	case SYS_RECV:
29358c2ecf20Sopenharmony_ci		err = __sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
29368c2ecf20Sopenharmony_ci				     NULL, NULL);
29378c2ecf20Sopenharmony_ci		break;
29388c2ecf20Sopenharmony_ci	case SYS_RECVFROM:
29398c2ecf20Sopenharmony_ci		err = __sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
29408c2ecf20Sopenharmony_ci				     (struct sockaddr __user *)a[4],
29418c2ecf20Sopenharmony_ci				     (int __user *)a[5]);
29428c2ecf20Sopenharmony_ci		break;
29438c2ecf20Sopenharmony_ci	case SYS_SHUTDOWN:
29448c2ecf20Sopenharmony_ci		err = __sys_shutdown(a0, a1);
29458c2ecf20Sopenharmony_ci		break;
29468c2ecf20Sopenharmony_ci	case SYS_SETSOCKOPT:
29478c2ecf20Sopenharmony_ci		err = __sys_setsockopt(a0, a1, a[2], (char __user *)a[3],
29488c2ecf20Sopenharmony_ci				       a[4]);
29498c2ecf20Sopenharmony_ci		break;
29508c2ecf20Sopenharmony_ci	case SYS_GETSOCKOPT:
29518c2ecf20Sopenharmony_ci		err =
29528c2ecf20Sopenharmony_ci		    __sys_getsockopt(a0, a1, a[2], (char __user *)a[3],
29538c2ecf20Sopenharmony_ci				     (int __user *)a[4]);
29548c2ecf20Sopenharmony_ci		break;
29558c2ecf20Sopenharmony_ci	case SYS_SENDMSG:
29568c2ecf20Sopenharmony_ci		err = __sys_sendmsg(a0, (struct user_msghdr __user *)a1,
29578c2ecf20Sopenharmony_ci				    a[2], true);
29588c2ecf20Sopenharmony_ci		break;
29598c2ecf20Sopenharmony_ci	case SYS_SENDMMSG:
29608c2ecf20Sopenharmony_ci		err = __sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2],
29618c2ecf20Sopenharmony_ci				     a[3], true);
29628c2ecf20Sopenharmony_ci		break;
29638c2ecf20Sopenharmony_ci	case SYS_RECVMSG:
29648c2ecf20Sopenharmony_ci		err = __sys_recvmsg(a0, (struct user_msghdr __user *)a1,
29658c2ecf20Sopenharmony_ci				    a[2], true);
29668c2ecf20Sopenharmony_ci		break;
29678c2ecf20Sopenharmony_ci	case SYS_RECVMMSG:
29688c2ecf20Sopenharmony_ci		if (IS_ENABLED(CONFIG_64BIT))
29698c2ecf20Sopenharmony_ci			err = __sys_recvmmsg(a0, (struct mmsghdr __user *)a1,
29708c2ecf20Sopenharmony_ci					     a[2], a[3],
29718c2ecf20Sopenharmony_ci					     (struct __kernel_timespec __user *)a[4],
29728c2ecf20Sopenharmony_ci					     NULL);
29738c2ecf20Sopenharmony_ci		else
29748c2ecf20Sopenharmony_ci			err = __sys_recvmmsg(a0, (struct mmsghdr __user *)a1,
29758c2ecf20Sopenharmony_ci					     a[2], a[3], NULL,
29768c2ecf20Sopenharmony_ci					     (struct old_timespec32 __user *)a[4]);
29778c2ecf20Sopenharmony_ci		break;
29788c2ecf20Sopenharmony_ci	case SYS_ACCEPT4:
29798c2ecf20Sopenharmony_ci		err = __sys_accept4(a0, (struct sockaddr __user *)a1,
29808c2ecf20Sopenharmony_ci				    (int __user *)a[2], a[3]);
29818c2ecf20Sopenharmony_ci		break;
29828c2ecf20Sopenharmony_ci	default:
29838c2ecf20Sopenharmony_ci		err = -EINVAL;
29848c2ecf20Sopenharmony_ci		break;
29858c2ecf20Sopenharmony_ci	}
29868c2ecf20Sopenharmony_ci	return err;
29878c2ecf20Sopenharmony_ci}
29888c2ecf20Sopenharmony_ci
29898c2ecf20Sopenharmony_ci#endif				/* __ARCH_WANT_SYS_SOCKETCALL */
29908c2ecf20Sopenharmony_ci
29918c2ecf20Sopenharmony_ci/**
29928c2ecf20Sopenharmony_ci *	sock_register - add a socket protocol handler
29938c2ecf20Sopenharmony_ci *	@ops: description of protocol
29948c2ecf20Sopenharmony_ci *
29958c2ecf20Sopenharmony_ci *	This function is called by a protocol handler that wants to
29968c2ecf20Sopenharmony_ci *	advertise its address family, and have it linked into the
29978c2ecf20Sopenharmony_ci *	socket interface. The value ops->family corresponds to the
29988c2ecf20Sopenharmony_ci *	socket system call protocol family.
29998c2ecf20Sopenharmony_ci */
30008c2ecf20Sopenharmony_ciint sock_register(const struct net_proto_family *ops)
30018c2ecf20Sopenharmony_ci{
30028c2ecf20Sopenharmony_ci	int err;
30038c2ecf20Sopenharmony_ci
30048c2ecf20Sopenharmony_ci	if (ops->family >= NPROTO) {
30058c2ecf20Sopenharmony_ci		pr_crit("protocol %d >= NPROTO(%d)\n", ops->family, NPROTO);
30068c2ecf20Sopenharmony_ci		return -ENOBUFS;
30078c2ecf20Sopenharmony_ci	}
30088c2ecf20Sopenharmony_ci
30098c2ecf20Sopenharmony_ci	spin_lock(&net_family_lock);
30108c2ecf20Sopenharmony_ci	if (rcu_dereference_protected(net_families[ops->family],
30118c2ecf20Sopenharmony_ci				      lockdep_is_held(&net_family_lock)))
30128c2ecf20Sopenharmony_ci		err = -EEXIST;
30138c2ecf20Sopenharmony_ci	else {
30148c2ecf20Sopenharmony_ci		rcu_assign_pointer(net_families[ops->family], ops);
30158c2ecf20Sopenharmony_ci		err = 0;
30168c2ecf20Sopenharmony_ci	}
30178c2ecf20Sopenharmony_ci	spin_unlock(&net_family_lock);
30188c2ecf20Sopenharmony_ci
30198c2ecf20Sopenharmony_ci	pr_info("NET: Registered protocol family %d\n", ops->family);
30208c2ecf20Sopenharmony_ci	return err;
30218c2ecf20Sopenharmony_ci}
30228c2ecf20Sopenharmony_ciEXPORT_SYMBOL(sock_register);
30238c2ecf20Sopenharmony_ci
30248c2ecf20Sopenharmony_ci/**
30258c2ecf20Sopenharmony_ci *	sock_unregister - remove a protocol handler
30268c2ecf20Sopenharmony_ci *	@family: protocol family to remove
30278c2ecf20Sopenharmony_ci *
30288c2ecf20Sopenharmony_ci *	This function is called by a protocol handler that wants to
30298c2ecf20Sopenharmony_ci *	remove its address family, and have it unlinked from the
30308c2ecf20Sopenharmony_ci *	new socket creation.
30318c2ecf20Sopenharmony_ci *
30328c2ecf20Sopenharmony_ci *	If protocol handler is a module, then it can use module reference
30338c2ecf20Sopenharmony_ci *	counts to protect against new references. If protocol handler is not
30348c2ecf20Sopenharmony_ci *	a module then it needs to provide its own protection in
30358c2ecf20Sopenharmony_ci *	the ops->create routine.
30368c2ecf20Sopenharmony_ci */
30378c2ecf20Sopenharmony_civoid sock_unregister(int family)
30388c2ecf20Sopenharmony_ci{
30398c2ecf20Sopenharmony_ci	BUG_ON(family < 0 || family >= NPROTO);
30408c2ecf20Sopenharmony_ci
30418c2ecf20Sopenharmony_ci	spin_lock(&net_family_lock);
30428c2ecf20Sopenharmony_ci	RCU_INIT_POINTER(net_families[family], NULL);
30438c2ecf20Sopenharmony_ci	spin_unlock(&net_family_lock);
30448c2ecf20Sopenharmony_ci
30458c2ecf20Sopenharmony_ci	synchronize_rcu();
30468c2ecf20Sopenharmony_ci
30478c2ecf20Sopenharmony_ci	pr_info("NET: Unregistered protocol family %d\n", family);
30488c2ecf20Sopenharmony_ci}
30498c2ecf20Sopenharmony_ciEXPORT_SYMBOL(sock_unregister);
30508c2ecf20Sopenharmony_ci
30518c2ecf20Sopenharmony_cibool sock_is_registered(int family)
30528c2ecf20Sopenharmony_ci{
30538c2ecf20Sopenharmony_ci	return family < NPROTO && rcu_access_pointer(net_families[family]);
30548c2ecf20Sopenharmony_ci}
30558c2ecf20Sopenharmony_ci
30568c2ecf20Sopenharmony_cistatic int __init sock_init(void)
30578c2ecf20Sopenharmony_ci{
30588c2ecf20Sopenharmony_ci	int err;
30598c2ecf20Sopenharmony_ci	/*
30608c2ecf20Sopenharmony_ci	 *      Initialize the network sysctl infrastructure.
30618c2ecf20Sopenharmony_ci	 */
30628c2ecf20Sopenharmony_ci	err = net_sysctl_init();
30638c2ecf20Sopenharmony_ci	if (err)
30648c2ecf20Sopenharmony_ci		goto out;
30658c2ecf20Sopenharmony_ci
30668c2ecf20Sopenharmony_ci	/*
30678c2ecf20Sopenharmony_ci	 *      Initialize skbuff SLAB cache
30688c2ecf20Sopenharmony_ci	 */
30698c2ecf20Sopenharmony_ci	skb_init();
30708c2ecf20Sopenharmony_ci
30718c2ecf20Sopenharmony_ci	/*
30728c2ecf20Sopenharmony_ci	 *      Initialize the protocols module.
30738c2ecf20Sopenharmony_ci	 */
30748c2ecf20Sopenharmony_ci
30758c2ecf20Sopenharmony_ci	init_inodecache();
30768c2ecf20Sopenharmony_ci
30778c2ecf20Sopenharmony_ci	err = register_filesystem(&sock_fs_type);
30788c2ecf20Sopenharmony_ci	if (err)
30798c2ecf20Sopenharmony_ci		goto out;
30808c2ecf20Sopenharmony_ci	sock_mnt = kern_mount(&sock_fs_type);
30818c2ecf20Sopenharmony_ci	if (IS_ERR(sock_mnt)) {
30828c2ecf20Sopenharmony_ci		err = PTR_ERR(sock_mnt);
30838c2ecf20Sopenharmony_ci		goto out_mount;
30848c2ecf20Sopenharmony_ci	}
30858c2ecf20Sopenharmony_ci
30868c2ecf20Sopenharmony_ci	/* The real protocol initialization is performed in later initcalls.
30878c2ecf20Sopenharmony_ci	 */
30888c2ecf20Sopenharmony_ci
30898c2ecf20Sopenharmony_ci#ifdef CONFIG_NETFILTER
30908c2ecf20Sopenharmony_ci	err = netfilter_init();
30918c2ecf20Sopenharmony_ci	if (err)
30928c2ecf20Sopenharmony_ci		goto out;
30938c2ecf20Sopenharmony_ci#endif
30948c2ecf20Sopenharmony_ci
30958c2ecf20Sopenharmony_ci	ptp_classifier_init();
30968c2ecf20Sopenharmony_ci
30978c2ecf20Sopenharmony_ciout:
30988c2ecf20Sopenharmony_ci	return err;
30998c2ecf20Sopenharmony_ci
31008c2ecf20Sopenharmony_ciout_mount:
31018c2ecf20Sopenharmony_ci	unregister_filesystem(&sock_fs_type);
31028c2ecf20Sopenharmony_ci	goto out;
31038c2ecf20Sopenharmony_ci}
31048c2ecf20Sopenharmony_ci
31058c2ecf20Sopenharmony_cicore_initcall(sock_init);	/* early initcall */
31068c2ecf20Sopenharmony_ci
31078c2ecf20Sopenharmony_ci#ifdef CONFIG_PROC_FS
31088c2ecf20Sopenharmony_civoid socket_seq_show(struct seq_file *seq)
31098c2ecf20Sopenharmony_ci{
31108c2ecf20Sopenharmony_ci	seq_printf(seq, "sockets: used %d\n",
31118c2ecf20Sopenharmony_ci		   sock_inuse_get(seq->private));
31128c2ecf20Sopenharmony_ci}
31138c2ecf20Sopenharmony_ci#endif				/* CONFIG_PROC_FS */
31148c2ecf20Sopenharmony_ci
31158c2ecf20Sopenharmony_ci#ifdef CONFIG_COMPAT
31168c2ecf20Sopenharmony_cistatic int compat_dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32)
31178c2ecf20Sopenharmony_ci{
31188c2ecf20Sopenharmony_ci	struct compat_ifconf ifc32;
31198c2ecf20Sopenharmony_ci	struct ifconf ifc;
31208c2ecf20Sopenharmony_ci	int err;
31218c2ecf20Sopenharmony_ci
31228c2ecf20Sopenharmony_ci	if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf)))
31238c2ecf20Sopenharmony_ci		return -EFAULT;
31248c2ecf20Sopenharmony_ci
31258c2ecf20Sopenharmony_ci	ifc.ifc_len = ifc32.ifc_len;
31268c2ecf20Sopenharmony_ci	ifc.ifc_req = compat_ptr(ifc32.ifcbuf);
31278c2ecf20Sopenharmony_ci
31288c2ecf20Sopenharmony_ci	rtnl_lock();
31298c2ecf20Sopenharmony_ci	err = dev_ifconf(net, &ifc, sizeof(struct compat_ifreq));
31308c2ecf20Sopenharmony_ci	rtnl_unlock();
31318c2ecf20Sopenharmony_ci	if (err)
31328c2ecf20Sopenharmony_ci		return err;
31338c2ecf20Sopenharmony_ci
31348c2ecf20Sopenharmony_ci	ifc32.ifc_len = ifc.ifc_len;
31358c2ecf20Sopenharmony_ci	if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf)))
31368c2ecf20Sopenharmony_ci		return -EFAULT;
31378c2ecf20Sopenharmony_ci
31388c2ecf20Sopenharmony_ci	return 0;
31398c2ecf20Sopenharmony_ci}
31408c2ecf20Sopenharmony_ci
31418c2ecf20Sopenharmony_cistatic int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32)
31428c2ecf20Sopenharmony_ci{
31438c2ecf20Sopenharmony_ci	compat_uptr_t uptr32;
31448c2ecf20Sopenharmony_ci	struct ifreq ifr;
31458c2ecf20Sopenharmony_ci	void __user *saved;
31468c2ecf20Sopenharmony_ci	int err;
31478c2ecf20Sopenharmony_ci
31488c2ecf20Sopenharmony_ci	if (copy_from_user(&ifr, uifr32, sizeof(struct compat_ifreq)))
31498c2ecf20Sopenharmony_ci		return -EFAULT;
31508c2ecf20Sopenharmony_ci
31518c2ecf20Sopenharmony_ci	if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu))
31528c2ecf20Sopenharmony_ci		return -EFAULT;
31538c2ecf20Sopenharmony_ci
31548c2ecf20Sopenharmony_ci	saved = ifr.ifr_settings.ifs_ifsu.raw_hdlc;
31558c2ecf20Sopenharmony_ci	ifr.ifr_settings.ifs_ifsu.raw_hdlc = compat_ptr(uptr32);
31568c2ecf20Sopenharmony_ci
31578c2ecf20Sopenharmony_ci	err = dev_ioctl(net, SIOCWANDEV, &ifr, NULL);
31588c2ecf20Sopenharmony_ci	if (!err) {
31598c2ecf20Sopenharmony_ci		ifr.ifr_settings.ifs_ifsu.raw_hdlc = saved;
31608c2ecf20Sopenharmony_ci		if (copy_to_user(uifr32, &ifr, sizeof(struct compat_ifreq)))
31618c2ecf20Sopenharmony_ci			err = -EFAULT;
31628c2ecf20Sopenharmony_ci	}
31638c2ecf20Sopenharmony_ci	return err;
31648c2ecf20Sopenharmony_ci}
31658c2ecf20Sopenharmony_ci
31668c2ecf20Sopenharmony_ci/* Handle ioctls that use ifreq::ifr_data and just need struct ifreq converted */
31678c2ecf20Sopenharmony_cistatic int compat_ifr_data_ioctl(struct net *net, unsigned int cmd,
31688c2ecf20Sopenharmony_ci				 struct compat_ifreq __user *u_ifreq32)
31698c2ecf20Sopenharmony_ci{
31708c2ecf20Sopenharmony_ci	struct ifreq ifreq;
31718c2ecf20Sopenharmony_ci	u32 data32;
31728c2ecf20Sopenharmony_ci
31738c2ecf20Sopenharmony_ci	if (!is_socket_ioctl_cmd(cmd))
31748c2ecf20Sopenharmony_ci		return -ENOTTY;
31758c2ecf20Sopenharmony_ci	if (copy_from_user(ifreq.ifr_name, u_ifreq32->ifr_name, IFNAMSIZ))
31768c2ecf20Sopenharmony_ci		return -EFAULT;
31778c2ecf20Sopenharmony_ci	if (get_user(data32, &u_ifreq32->ifr_data))
31788c2ecf20Sopenharmony_ci		return -EFAULT;
31798c2ecf20Sopenharmony_ci	ifreq.ifr_data = compat_ptr(data32);
31808c2ecf20Sopenharmony_ci
31818c2ecf20Sopenharmony_ci	return dev_ioctl(net, cmd, &ifreq, NULL);
31828c2ecf20Sopenharmony_ci}
31838c2ecf20Sopenharmony_ci
31848c2ecf20Sopenharmony_cistatic int compat_ifreq_ioctl(struct net *net, struct socket *sock,
31858c2ecf20Sopenharmony_ci			      unsigned int cmd,
31868c2ecf20Sopenharmony_ci			      struct compat_ifreq __user *uifr32)
31878c2ecf20Sopenharmony_ci{
31888c2ecf20Sopenharmony_ci	struct ifreq __user *uifr;
31898c2ecf20Sopenharmony_ci	int err;
31908c2ecf20Sopenharmony_ci
31918c2ecf20Sopenharmony_ci	/* Handle the fact that while struct ifreq has the same *layout* on
31928c2ecf20Sopenharmony_ci	 * 32/64 for everything but ifreq::ifru_ifmap and ifreq::ifru_data,
31938c2ecf20Sopenharmony_ci	 * which are handled elsewhere, it still has different *size* due to
31948c2ecf20Sopenharmony_ci	 * ifreq::ifru_ifmap (which is 16 bytes on 32 bit, 24 bytes on 64-bit,
31958c2ecf20Sopenharmony_ci	 * resulting in struct ifreq being 32 and 40 bytes respectively).
31968c2ecf20Sopenharmony_ci	 * As a result, if the struct happens to be at the end of a page and
31978c2ecf20Sopenharmony_ci	 * the next page isn't readable/writable, we get a fault. To prevent
31988c2ecf20Sopenharmony_ci	 * that, copy back and forth to the full size.
31998c2ecf20Sopenharmony_ci	 */
32008c2ecf20Sopenharmony_ci
32018c2ecf20Sopenharmony_ci	uifr = compat_alloc_user_space(sizeof(*uifr));
32028c2ecf20Sopenharmony_ci	if (copy_in_user(uifr, uifr32, sizeof(*uifr32)))
32038c2ecf20Sopenharmony_ci		return -EFAULT;
32048c2ecf20Sopenharmony_ci
32058c2ecf20Sopenharmony_ci	err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr);
32068c2ecf20Sopenharmony_ci
32078c2ecf20Sopenharmony_ci	if (!err) {
32088c2ecf20Sopenharmony_ci		switch (cmd) {
32098c2ecf20Sopenharmony_ci		case SIOCGIFFLAGS:
32108c2ecf20Sopenharmony_ci		case SIOCGIFMETRIC:
32118c2ecf20Sopenharmony_ci		case SIOCGIFMTU:
32128c2ecf20Sopenharmony_ci		case SIOCGIFMEM:
32138c2ecf20Sopenharmony_ci		case SIOCGIFHWADDR:
32148c2ecf20Sopenharmony_ci		case SIOCGIFINDEX:
32158c2ecf20Sopenharmony_ci		case SIOCGIFADDR:
32168c2ecf20Sopenharmony_ci		case SIOCGIFBRDADDR:
32178c2ecf20Sopenharmony_ci		case SIOCGIFDSTADDR:
32188c2ecf20Sopenharmony_ci		case SIOCGIFNETMASK:
32198c2ecf20Sopenharmony_ci		case SIOCGIFPFLAGS:
32208c2ecf20Sopenharmony_ci		case SIOCGIFTXQLEN:
32218c2ecf20Sopenharmony_ci		case SIOCGMIIPHY:
32228c2ecf20Sopenharmony_ci		case SIOCGMIIREG:
32238c2ecf20Sopenharmony_ci		case SIOCGIFNAME:
32248c2ecf20Sopenharmony_ci			if (copy_in_user(uifr32, uifr, sizeof(*uifr32)))
32258c2ecf20Sopenharmony_ci				err = -EFAULT;
32268c2ecf20Sopenharmony_ci			break;
32278c2ecf20Sopenharmony_ci		}
32288c2ecf20Sopenharmony_ci	}
32298c2ecf20Sopenharmony_ci	return err;
32308c2ecf20Sopenharmony_ci}
32318c2ecf20Sopenharmony_ci
32328c2ecf20Sopenharmony_cistatic int compat_sioc_ifmap(struct net *net, unsigned int cmd,
32338c2ecf20Sopenharmony_ci			struct compat_ifreq __user *uifr32)
32348c2ecf20Sopenharmony_ci{
32358c2ecf20Sopenharmony_ci	struct ifreq ifr;
32368c2ecf20Sopenharmony_ci	struct compat_ifmap __user *uifmap32;
32378c2ecf20Sopenharmony_ci	int err;
32388c2ecf20Sopenharmony_ci
32398c2ecf20Sopenharmony_ci	uifmap32 = &uifr32->ifr_ifru.ifru_map;
32408c2ecf20Sopenharmony_ci	err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name));
32418c2ecf20Sopenharmony_ci	err |= get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
32428c2ecf20Sopenharmony_ci	err |= get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
32438c2ecf20Sopenharmony_ci	err |= get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
32448c2ecf20Sopenharmony_ci	err |= get_user(ifr.ifr_map.irq, &uifmap32->irq);
32458c2ecf20Sopenharmony_ci	err |= get_user(ifr.ifr_map.dma, &uifmap32->dma);
32468c2ecf20Sopenharmony_ci	err |= get_user(ifr.ifr_map.port, &uifmap32->port);
32478c2ecf20Sopenharmony_ci	if (err)
32488c2ecf20Sopenharmony_ci		return -EFAULT;
32498c2ecf20Sopenharmony_ci
32508c2ecf20Sopenharmony_ci	err = dev_ioctl(net, cmd, &ifr, NULL);
32518c2ecf20Sopenharmony_ci
32528c2ecf20Sopenharmony_ci	if (cmd == SIOCGIFMAP && !err) {
32538c2ecf20Sopenharmony_ci		err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name));
32548c2ecf20Sopenharmony_ci		err |= put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
32558c2ecf20Sopenharmony_ci		err |= put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
32568c2ecf20Sopenharmony_ci		err |= put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
32578c2ecf20Sopenharmony_ci		err |= put_user(ifr.ifr_map.irq, &uifmap32->irq);
32588c2ecf20Sopenharmony_ci		err |= put_user(ifr.ifr_map.dma, &uifmap32->dma);
32598c2ecf20Sopenharmony_ci		err |= put_user(ifr.ifr_map.port, &uifmap32->port);
32608c2ecf20Sopenharmony_ci		if (err)
32618c2ecf20Sopenharmony_ci			err = -EFAULT;
32628c2ecf20Sopenharmony_ci	}
32638c2ecf20Sopenharmony_ci	return err;
32648c2ecf20Sopenharmony_ci}
32658c2ecf20Sopenharmony_ci
32668c2ecf20Sopenharmony_ci/* Since old style bridge ioctl's endup using SIOCDEVPRIVATE
32678c2ecf20Sopenharmony_ci * for some operations; this forces use of the newer bridge-utils that
32688c2ecf20Sopenharmony_ci * use compatible ioctls
32698c2ecf20Sopenharmony_ci */
32708c2ecf20Sopenharmony_cistatic int old_bridge_ioctl(compat_ulong_t __user *argp)
32718c2ecf20Sopenharmony_ci{
32728c2ecf20Sopenharmony_ci	compat_ulong_t tmp;
32738c2ecf20Sopenharmony_ci
32748c2ecf20Sopenharmony_ci	if (get_user(tmp, argp))
32758c2ecf20Sopenharmony_ci		return -EFAULT;
32768c2ecf20Sopenharmony_ci	if (tmp == BRCTL_GET_VERSION)
32778c2ecf20Sopenharmony_ci		return BRCTL_VERSION + 1;
32788c2ecf20Sopenharmony_ci	return -EINVAL;
32798c2ecf20Sopenharmony_ci}
32808c2ecf20Sopenharmony_ci
32818c2ecf20Sopenharmony_cistatic int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
32828c2ecf20Sopenharmony_ci			 unsigned int cmd, unsigned long arg)
32838c2ecf20Sopenharmony_ci{
32848c2ecf20Sopenharmony_ci	void __user *argp = compat_ptr(arg);
32858c2ecf20Sopenharmony_ci	struct sock *sk = sock->sk;
32868c2ecf20Sopenharmony_ci	struct net *net = sock_net(sk);
32878c2ecf20Sopenharmony_ci
32888c2ecf20Sopenharmony_ci	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
32898c2ecf20Sopenharmony_ci		return compat_ifr_data_ioctl(net, cmd, argp);
32908c2ecf20Sopenharmony_ci
32918c2ecf20Sopenharmony_ci	switch (cmd) {
32928c2ecf20Sopenharmony_ci	case SIOCSIFBR:
32938c2ecf20Sopenharmony_ci	case SIOCGIFBR:
32948c2ecf20Sopenharmony_ci		return old_bridge_ioctl(argp);
32958c2ecf20Sopenharmony_ci	case SIOCGIFCONF:
32968c2ecf20Sopenharmony_ci		return compat_dev_ifconf(net, argp);
32978c2ecf20Sopenharmony_ci	case SIOCWANDEV:
32988c2ecf20Sopenharmony_ci		return compat_siocwandev(net, argp);
32998c2ecf20Sopenharmony_ci	case SIOCGIFMAP:
33008c2ecf20Sopenharmony_ci	case SIOCSIFMAP:
33018c2ecf20Sopenharmony_ci		return compat_sioc_ifmap(net, cmd, argp);
33028c2ecf20Sopenharmony_ci	case SIOCGSTAMP_OLD:
33038c2ecf20Sopenharmony_ci	case SIOCGSTAMPNS_OLD:
33048c2ecf20Sopenharmony_ci		if (!sock->ops->gettstamp)
33058c2ecf20Sopenharmony_ci			return -ENOIOCTLCMD;
33068c2ecf20Sopenharmony_ci		return sock->ops->gettstamp(sock, argp, cmd == SIOCGSTAMP_OLD,
33078c2ecf20Sopenharmony_ci					    !COMPAT_USE_64BIT_TIME);
33088c2ecf20Sopenharmony_ci
33098c2ecf20Sopenharmony_ci	case SIOCETHTOOL:
33108c2ecf20Sopenharmony_ci	case SIOCBONDSLAVEINFOQUERY:
33118c2ecf20Sopenharmony_ci	case SIOCBONDINFOQUERY:
33128c2ecf20Sopenharmony_ci	case SIOCSHWTSTAMP:
33138c2ecf20Sopenharmony_ci	case SIOCGHWTSTAMP:
33148c2ecf20Sopenharmony_ci		return compat_ifr_data_ioctl(net, cmd, argp);
33158c2ecf20Sopenharmony_ci
33168c2ecf20Sopenharmony_ci	case FIOSETOWN:
33178c2ecf20Sopenharmony_ci	case SIOCSPGRP:
33188c2ecf20Sopenharmony_ci	case FIOGETOWN:
33198c2ecf20Sopenharmony_ci	case SIOCGPGRP:
33208c2ecf20Sopenharmony_ci	case SIOCBRADDBR:
33218c2ecf20Sopenharmony_ci	case SIOCBRDELBR:
33228c2ecf20Sopenharmony_ci	case SIOCGIFVLAN:
33238c2ecf20Sopenharmony_ci	case SIOCSIFVLAN:
33248c2ecf20Sopenharmony_ci	case SIOCADDDLCI:
33258c2ecf20Sopenharmony_ci	case SIOCDELDLCI:
33268c2ecf20Sopenharmony_ci	case SIOCGSKNS:
33278c2ecf20Sopenharmony_ci	case SIOCGSTAMP_NEW:
33288c2ecf20Sopenharmony_ci	case SIOCGSTAMPNS_NEW:
33298c2ecf20Sopenharmony_ci		return sock_ioctl(file, cmd, arg);
33308c2ecf20Sopenharmony_ci
33318c2ecf20Sopenharmony_ci	case SIOCGIFFLAGS:
33328c2ecf20Sopenharmony_ci	case SIOCSIFFLAGS:
33338c2ecf20Sopenharmony_ci	case SIOCGIFMETRIC:
33348c2ecf20Sopenharmony_ci	case SIOCSIFMETRIC:
33358c2ecf20Sopenharmony_ci	case SIOCGIFMTU:
33368c2ecf20Sopenharmony_ci	case SIOCSIFMTU:
33378c2ecf20Sopenharmony_ci	case SIOCGIFMEM:
33388c2ecf20Sopenharmony_ci	case SIOCSIFMEM:
33398c2ecf20Sopenharmony_ci	case SIOCGIFHWADDR:
33408c2ecf20Sopenharmony_ci	case SIOCSIFHWADDR:
33418c2ecf20Sopenharmony_ci	case SIOCADDMULTI:
33428c2ecf20Sopenharmony_ci	case SIOCDELMULTI:
33438c2ecf20Sopenharmony_ci	case SIOCGIFINDEX:
33448c2ecf20Sopenharmony_ci	case SIOCGIFADDR:
33458c2ecf20Sopenharmony_ci	case SIOCSIFADDR:
33468c2ecf20Sopenharmony_ci	case SIOCSIFHWBROADCAST:
33478c2ecf20Sopenharmony_ci	case SIOCDIFADDR:
33488c2ecf20Sopenharmony_ci	case SIOCGIFBRDADDR:
33498c2ecf20Sopenharmony_ci	case SIOCSIFBRDADDR:
33508c2ecf20Sopenharmony_ci	case SIOCGIFDSTADDR:
33518c2ecf20Sopenharmony_ci	case SIOCSIFDSTADDR:
33528c2ecf20Sopenharmony_ci	case SIOCGIFNETMASK:
33538c2ecf20Sopenharmony_ci	case SIOCSIFNETMASK:
33548c2ecf20Sopenharmony_ci	case SIOCSIFPFLAGS:
33558c2ecf20Sopenharmony_ci	case SIOCGIFPFLAGS:
33568c2ecf20Sopenharmony_ci	case SIOCGIFTXQLEN:
33578c2ecf20Sopenharmony_ci	case SIOCSIFTXQLEN:
33588c2ecf20Sopenharmony_ci	case SIOCBRADDIF:
33598c2ecf20Sopenharmony_ci	case SIOCBRDELIF:
33608c2ecf20Sopenharmony_ci	case SIOCGIFNAME:
33618c2ecf20Sopenharmony_ci	case SIOCSIFNAME:
33628c2ecf20Sopenharmony_ci	case SIOCGMIIPHY:
33638c2ecf20Sopenharmony_ci	case SIOCGMIIREG:
33648c2ecf20Sopenharmony_ci	case SIOCSMIIREG:
33658c2ecf20Sopenharmony_ci	case SIOCBONDENSLAVE:
33668c2ecf20Sopenharmony_ci	case SIOCBONDRELEASE:
33678c2ecf20Sopenharmony_ci	case SIOCBONDSETHWADDR:
33688c2ecf20Sopenharmony_ci	case SIOCBONDCHANGEACTIVE:
33698c2ecf20Sopenharmony_ci		return compat_ifreq_ioctl(net, sock, cmd, argp);
33708c2ecf20Sopenharmony_ci
33718c2ecf20Sopenharmony_ci	case SIOCSARP:
33728c2ecf20Sopenharmony_ci	case SIOCGARP:
33738c2ecf20Sopenharmony_ci	case SIOCDARP:
33748c2ecf20Sopenharmony_ci	case SIOCOUTQ:
33758c2ecf20Sopenharmony_ci	case SIOCOUTQNSD:
33768c2ecf20Sopenharmony_ci	case SIOCATMARK:
33778c2ecf20Sopenharmony_ci		return sock_do_ioctl(net, sock, cmd, arg);
33788c2ecf20Sopenharmony_ci	}
33798c2ecf20Sopenharmony_ci
33808c2ecf20Sopenharmony_ci	return -ENOIOCTLCMD;
33818c2ecf20Sopenharmony_ci}
33828c2ecf20Sopenharmony_ci
33838c2ecf20Sopenharmony_cistatic long compat_sock_ioctl(struct file *file, unsigned int cmd,
33848c2ecf20Sopenharmony_ci			      unsigned long arg)
33858c2ecf20Sopenharmony_ci{
33868c2ecf20Sopenharmony_ci	struct socket *sock = file->private_data;
33878c2ecf20Sopenharmony_ci	int ret = -ENOIOCTLCMD;
33888c2ecf20Sopenharmony_ci	struct sock *sk;
33898c2ecf20Sopenharmony_ci	struct net *net;
33908c2ecf20Sopenharmony_ci
33918c2ecf20Sopenharmony_ci	sk = sock->sk;
33928c2ecf20Sopenharmony_ci	net = sock_net(sk);
33938c2ecf20Sopenharmony_ci
33948c2ecf20Sopenharmony_ci	if (sock->ops->compat_ioctl)
33958c2ecf20Sopenharmony_ci		ret = sock->ops->compat_ioctl(sock, cmd, arg);
33968c2ecf20Sopenharmony_ci
33978c2ecf20Sopenharmony_ci	if (ret == -ENOIOCTLCMD &&
33988c2ecf20Sopenharmony_ci	    (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST))
33998c2ecf20Sopenharmony_ci		ret = compat_wext_handle_ioctl(net, cmd, arg);
34008c2ecf20Sopenharmony_ci
34018c2ecf20Sopenharmony_ci	if (ret == -ENOIOCTLCMD)
34028c2ecf20Sopenharmony_ci		ret = compat_sock_ioctl_trans(file, sock, cmd, arg);
34038c2ecf20Sopenharmony_ci
34048c2ecf20Sopenharmony_ci	return ret;
34058c2ecf20Sopenharmony_ci}
34068c2ecf20Sopenharmony_ci#endif
34078c2ecf20Sopenharmony_ci
34088c2ecf20Sopenharmony_ci/**
34098c2ecf20Sopenharmony_ci *	kernel_bind - bind an address to a socket (kernel space)
34108c2ecf20Sopenharmony_ci *	@sock: socket
34118c2ecf20Sopenharmony_ci *	@addr: address
34128c2ecf20Sopenharmony_ci *	@addrlen: length of address
34138c2ecf20Sopenharmony_ci *
34148c2ecf20Sopenharmony_ci *	Returns 0 or an error.
34158c2ecf20Sopenharmony_ci */
34168c2ecf20Sopenharmony_ci
34178c2ecf20Sopenharmony_ciint kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
34188c2ecf20Sopenharmony_ci{
34198c2ecf20Sopenharmony_ci	struct sockaddr_storage address;
34208c2ecf20Sopenharmony_ci
34218c2ecf20Sopenharmony_ci	memcpy(&address, addr, addrlen);
34228c2ecf20Sopenharmony_ci
34238c2ecf20Sopenharmony_ci	return sock->ops->bind(sock, (struct sockaddr *)&address, addrlen);
34248c2ecf20Sopenharmony_ci}
34258c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kernel_bind);
34268c2ecf20Sopenharmony_ci
34278c2ecf20Sopenharmony_ci/**
34288c2ecf20Sopenharmony_ci *	kernel_listen - move socket to listening state (kernel space)
34298c2ecf20Sopenharmony_ci *	@sock: socket
34308c2ecf20Sopenharmony_ci *	@backlog: pending connections queue size
34318c2ecf20Sopenharmony_ci *
34328c2ecf20Sopenharmony_ci *	Returns 0 or an error.
34338c2ecf20Sopenharmony_ci */
34348c2ecf20Sopenharmony_ci
34358c2ecf20Sopenharmony_ciint kernel_listen(struct socket *sock, int backlog)
34368c2ecf20Sopenharmony_ci{
34378c2ecf20Sopenharmony_ci	return sock->ops->listen(sock, backlog);
34388c2ecf20Sopenharmony_ci}
34398c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kernel_listen);
34408c2ecf20Sopenharmony_ci
34418c2ecf20Sopenharmony_ci/**
34428c2ecf20Sopenharmony_ci *	kernel_accept - accept a connection (kernel space)
34438c2ecf20Sopenharmony_ci *	@sock: listening socket
34448c2ecf20Sopenharmony_ci *	@newsock: new connected socket
34458c2ecf20Sopenharmony_ci *	@flags: flags
34468c2ecf20Sopenharmony_ci *
34478c2ecf20Sopenharmony_ci *	@flags must be SOCK_CLOEXEC, SOCK_NONBLOCK or 0.
34488c2ecf20Sopenharmony_ci *	If it fails, @newsock is guaranteed to be %NULL.
34498c2ecf20Sopenharmony_ci *	Returns 0 or an error.
34508c2ecf20Sopenharmony_ci */
34518c2ecf20Sopenharmony_ci
34528c2ecf20Sopenharmony_ciint kernel_accept(struct socket *sock, struct socket **newsock, int flags)
34538c2ecf20Sopenharmony_ci{
34548c2ecf20Sopenharmony_ci	struct sock *sk = sock->sk;
34558c2ecf20Sopenharmony_ci	int err;
34568c2ecf20Sopenharmony_ci
34578c2ecf20Sopenharmony_ci	err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
34588c2ecf20Sopenharmony_ci			       newsock);
34598c2ecf20Sopenharmony_ci	if (err < 0)
34608c2ecf20Sopenharmony_ci		goto done;
34618c2ecf20Sopenharmony_ci
34628c2ecf20Sopenharmony_ci	err = sock->ops->accept(sock, *newsock, flags, true);
34638c2ecf20Sopenharmony_ci	if (err < 0) {
34648c2ecf20Sopenharmony_ci		sock_release(*newsock);
34658c2ecf20Sopenharmony_ci		*newsock = NULL;
34668c2ecf20Sopenharmony_ci		goto done;
34678c2ecf20Sopenharmony_ci	}
34688c2ecf20Sopenharmony_ci
34698c2ecf20Sopenharmony_ci	(*newsock)->ops = sock->ops;
34708c2ecf20Sopenharmony_ci	__module_get((*newsock)->ops->owner);
34718c2ecf20Sopenharmony_ci
34728c2ecf20Sopenharmony_cidone:
34738c2ecf20Sopenharmony_ci	return err;
34748c2ecf20Sopenharmony_ci}
34758c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kernel_accept);
34768c2ecf20Sopenharmony_ci
34778c2ecf20Sopenharmony_ci/**
34788c2ecf20Sopenharmony_ci *	kernel_connect - connect a socket (kernel space)
34798c2ecf20Sopenharmony_ci *	@sock: socket
34808c2ecf20Sopenharmony_ci *	@addr: address
34818c2ecf20Sopenharmony_ci *	@addrlen: address length
34828c2ecf20Sopenharmony_ci *	@flags: flags (O_NONBLOCK, ...)
34838c2ecf20Sopenharmony_ci *
34848c2ecf20Sopenharmony_ci *	For datagram sockets, @addr is the addres to which datagrams are sent
34858c2ecf20Sopenharmony_ci *	by default, and the only address from which datagrams are received.
34868c2ecf20Sopenharmony_ci *	For stream sockets, attempts to connect to @addr.
34878c2ecf20Sopenharmony_ci *	Returns 0 or an error code.
34888c2ecf20Sopenharmony_ci */
34898c2ecf20Sopenharmony_ci
34908c2ecf20Sopenharmony_ciint kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
34918c2ecf20Sopenharmony_ci		   int flags)
34928c2ecf20Sopenharmony_ci{
34938c2ecf20Sopenharmony_ci	struct sockaddr_storage address;
34948c2ecf20Sopenharmony_ci
34958c2ecf20Sopenharmony_ci	memcpy(&address, addr, addrlen);
34968c2ecf20Sopenharmony_ci
34978c2ecf20Sopenharmony_ci	return sock->ops->connect(sock, (struct sockaddr *)&address, addrlen, flags);
34988c2ecf20Sopenharmony_ci}
34998c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kernel_connect);
35008c2ecf20Sopenharmony_ci
35018c2ecf20Sopenharmony_ci/**
35028c2ecf20Sopenharmony_ci *	kernel_getsockname - get the address which the socket is bound (kernel space)
35038c2ecf20Sopenharmony_ci *	@sock: socket
35048c2ecf20Sopenharmony_ci *	@addr: address holder
35058c2ecf20Sopenharmony_ci *
35068c2ecf20Sopenharmony_ci * 	Fills the @addr pointer with the address which the socket is bound.
35078c2ecf20Sopenharmony_ci *	Returns 0 or an error code.
35088c2ecf20Sopenharmony_ci */
35098c2ecf20Sopenharmony_ci
35108c2ecf20Sopenharmony_ciint kernel_getsockname(struct socket *sock, struct sockaddr *addr)
35118c2ecf20Sopenharmony_ci{
35128c2ecf20Sopenharmony_ci	return sock->ops->getname(sock, addr, 0);
35138c2ecf20Sopenharmony_ci}
35148c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kernel_getsockname);
35158c2ecf20Sopenharmony_ci
35168c2ecf20Sopenharmony_ci/**
35178c2ecf20Sopenharmony_ci *	kernel_getpeername - get the address which the socket is connected (kernel space)
35188c2ecf20Sopenharmony_ci *	@sock: socket
35198c2ecf20Sopenharmony_ci *	@addr: address holder
35208c2ecf20Sopenharmony_ci *
35218c2ecf20Sopenharmony_ci * 	Fills the @addr pointer with the address which the socket is connected.
35228c2ecf20Sopenharmony_ci *	Returns 0 or an error code.
35238c2ecf20Sopenharmony_ci */
35248c2ecf20Sopenharmony_ci
35258c2ecf20Sopenharmony_ciint kernel_getpeername(struct socket *sock, struct sockaddr *addr)
35268c2ecf20Sopenharmony_ci{
35278c2ecf20Sopenharmony_ci	return sock->ops->getname(sock, addr, 1);
35288c2ecf20Sopenharmony_ci}
35298c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kernel_getpeername);
35308c2ecf20Sopenharmony_ci
35318c2ecf20Sopenharmony_ci/**
35328c2ecf20Sopenharmony_ci *	kernel_sendpage - send a &page through a socket (kernel space)
35338c2ecf20Sopenharmony_ci *	@sock: socket
35348c2ecf20Sopenharmony_ci *	@page: page
35358c2ecf20Sopenharmony_ci *	@offset: page offset
35368c2ecf20Sopenharmony_ci *	@size: total size in bytes
35378c2ecf20Sopenharmony_ci *	@flags: flags (MSG_DONTWAIT, ...)
35388c2ecf20Sopenharmony_ci *
35398c2ecf20Sopenharmony_ci *	Returns the total amount sent in bytes or an error.
35408c2ecf20Sopenharmony_ci */
35418c2ecf20Sopenharmony_ci
35428c2ecf20Sopenharmony_ciint kernel_sendpage(struct socket *sock, struct page *page, int offset,
35438c2ecf20Sopenharmony_ci		    size_t size, int flags)
35448c2ecf20Sopenharmony_ci{
35458c2ecf20Sopenharmony_ci	if (sock->ops->sendpage) {
35468c2ecf20Sopenharmony_ci		/* Warn in case the improper page to zero-copy send */
35478c2ecf20Sopenharmony_ci		WARN_ONCE(!sendpage_ok(page), "improper page for zero-copy send");
35488c2ecf20Sopenharmony_ci		return sock->ops->sendpage(sock, page, offset, size, flags);
35498c2ecf20Sopenharmony_ci	}
35508c2ecf20Sopenharmony_ci	return sock_no_sendpage(sock, page, offset, size, flags);
35518c2ecf20Sopenharmony_ci}
35528c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kernel_sendpage);
35538c2ecf20Sopenharmony_ci
35548c2ecf20Sopenharmony_ci/**
35558c2ecf20Sopenharmony_ci *	kernel_sendpage_locked - send a &page through the locked sock (kernel space)
35568c2ecf20Sopenharmony_ci *	@sk: sock
35578c2ecf20Sopenharmony_ci *	@page: page
35588c2ecf20Sopenharmony_ci *	@offset: page offset
35598c2ecf20Sopenharmony_ci *	@size: total size in bytes
35608c2ecf20Sopenharmony_ci *	@flags: flags (MSG_DONTWAIT, ...)
35618c2ecf20Sopenharmony_ci *
35628c2ecf20Sopenharmony_ci *	Returns the total amount sent in bytes or an error.
35638c2ecf20Sopenharmony_ci *	Caller must hold @sk.
35648c2ecf20Sopenharmony_ci */
35658c2ecf20Sopenharmony_ci
35668c2ecf20Sopenharmony_ciint kernel_sendpage_locked(struct sock *sk, struct page *page, int offset,
35678c2ecf20Sopenharmony_ci			   size_t size, int flags)
35688c2ecf20Sopenharmony_ci{
35698c2ecf20Sopenharmony_ci	struct socket *sock = sk->sk_socket;
35708c2ecf20Sopenharmony_ci
35718c2ecf20Sopenharmony_ci	if (sock->ops->sendpage_locked)
35728c2ecf20Sopenharmony_ci		return sock->ops->sendpage_locked(sk, page, offset, size,
35738c2ecf20Sopenharmony_ci						  flags);
35748c2ecf20Sopenharmony_ci
35758c2ecf20Sopenharmony_ci	return sock_no_sendpage_locked(sk, page, offset, size, flags);
35768c2ecf20Sopenharmony_ci}
35778c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kernel_sendpage_locked);
35788c2ecf20Sopenharmony_ci
35798c2ecf20Sopenharmony_ci/**
35808c2ecf20Sopenharmony_ci *	kernel_sock_shutdown - shut down part of a full-duplex connection (kernel space)
35818c2ecf20Sopenharmony_ci *	@sock: socket
35828c2ecf20Sopenharmony_ci *	@how: connection part
35838c2ecf20Sopenharmony_ci *
35848c2ecf20Sopenharmony_ci *	Returns 0 or an error.
35858c2ecf20Sopenharmony_ci */
35868c2ecf20Sopenharmony_ci
35878c2ecf20Sopenharmony_ciint kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
35888c2ecf20Sopenharmony_ci{
35898c2ecf20Sopenharmony_ci	return sock->ops->shutdown(sock, how);
35908c2ecf20Sopenharmony_ci}
35918c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kernel_sock_shutdown);
35928c2ecf20Sopenharmony_ci
35938c2ecf20Sopenharmony_ci/**
35948c2ecf20Sopenharmony_ci *	kernel_sock_ip_overhead - returns the IP overhead imposed by a socket
35958c2ecf20Sopenharmony_ci *	@sk: socket
35968c2ecf20Sopenharmony_ci *
35978c2ecf20Sopenharmony_ci *	This routine returns the IP overhead imposed by a socket i.e.
35988c2ecf20Sopenharmony_ci *	the length of the underlying IP header, depending on whether
35998c2ecf20Sopenharmony_ci *	this is an IPv4 or IPv6 socket and the length from IP options turned
36008c2ecf20Sopenharmony_ci *	on at the socket. Assumes that the caller has a lock on the socket.
36018c2ecf20Sopenharmony_ci */
36028c2ecf20Sopenharmony_ci
36038c2ecf20Sopenharmony_ciu32 kernel_sock_ip_overhead(struct sock *sk)
36048c2ecf20Sopenharmony_ci{
36058c2ecf20Sopenharmony_ci	struct inet_sock *inet;
36068c2ecf20Sopenharmony_ci	struct ip_options_rcu *opt;
36078c2ecf20Sopenharmony_ci	u32 overhead = 0;
36088c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_IPV6)
36098c2ecf20Sopenharmony_ci	struct ipv6_pinfo *np;
36108c2ecf20Sopenharmony_ci	struct ipv6_txoptions *optv6 = NULL;
36118c2ecf20Sopenharmony_ci#endif /* IS_ENABLED(CONFIG_IPV6) */
36128c2ecf20Sopenharmony_ci
36138c2ecf20Sopenharmony_ci	if (!sk)
36148c2ecf20Sopenharmony_ci		return overhead;
36158c2ecf20Sopenharmony_ci
36168c2ecf20Sopenharmony_ci	switch (sk->sk_family) {
36178c2ecf20Sopenharmony_ci	case AF_INET:
36188c2ecf20Sopenharmony_ci		inet = inet_sk(sk);
36198c2ecf20Sopenharmony_ci		overhead += sizeof(struct iphdr);
36208c2ecf20Sopenharmony_ci		opt = rcu_dereference_protected(inet->inet_opt,
36218c2ecf20Sopenharmony_ci						sock_owned_by_user(sk));
36228c2ecf20Sopenharmony_ci		if (opt)
36238c2ecf20Sopenharmony_ci			overhead += opt->opt.optlen;
36248c2ecf20Sopenharmony_ci		return overhead;
36258c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_IPV6)
36268c2ecf20Sopenharmony_ci	case AF_INET6:
36278c2ecf20Sopenharmony_ci		np = inet6_sk(sk);
36288c2ecf20Sopenharmony_ci		overhead += sizeof(struct ipv6hdr);
36298c2ecf20Sopenharmony_ci		if (np)
36308c2ecf20Sopenharmony_ci			optv6 = rcu_dereference_protected(np->opt,
36318c2ecf20Sopenharmony_ci							  sock_owned_by_user(sk));
36328c2ecf20Sopenharmony_ci		if (optv6)
36338c2ecf20Sopenharmony_ci			overhead += (optv6->opt_flen + optv6->opt_nflen);
36348c2ecf20Sopenharmony_ci		return overhead;
36358c2ecf20Sopenharmony_ci#endif /* IS_ENABLED(CONFIG_IPV6) */
36368c2ecf20Sopenharmony_ci	default: /* Returns 0 overhead if the socket is not ipv4 or ipv6 */
36378c2ecf20Sopenharmony_ci		return overhead;
36388c2ecf20Sopenharmony_ci	}
36398c2ecf20Sopenharmony_ci}
36408c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kernel_sock_ip_overhead);
3641