xref: /kernel/linux/linux-5.10/net/unix/af_unix.c (revision 8c2ecf20)
18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * NET4:	Implementation of BSD Unix domain sockets.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Authors:	Alan Cox, <alan@lxorguk.ukuu.org.uk>
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Fixes:
88c2ecf20Sopenharmony_ci *		Linus Torvalds	:	Assorted bug cures.
98c2ecf20Sopenharmony_ci *		Niibe Yutaka	:	async I/O support.
108c2ecf20Sopenharmony_ci *		Carsten Paeth	:	PF_UNIX check, address fixes.
118c2ecf20Sopenharmony_ci *		Alan Cox	:	Limit size of allocated blocks.
128c2ecf20Sopenharmony_ci *		Alan Cox	:	Fixed the stupid socketpair bug.
138c2ecf20Sopenharmony_ci *		Alan Cox	:	BSD compatibility fine tuning.
148c2ecf20Sopenharmony_ci *		Alan Cox	:	Fixed a bug in connect when interrupted.
158c2ecf20Sopenharmony_ci *		Alan Cox	:	Sorted out a proper draft version of
168c2ecf20Sopenharmony_ci *					file descriptor passing hacked up from
178c2ecf20Sopenharmony_ci *					Mike Shaver's work.
188c2ecf20Sopenharmony_ci *		Marty Leisner	:	Fixes to fd passing
198c2ecf20Sopenharmony_ci *		Nick Nevin	:	recvmsg bugfix.
208c2ecf20Sopenharmony_ci *		Alan Cox	:	Started proper garbage collector
218c2ecf20Sopenharmony_ci *		Heiko EiBfeldt	:	Missing verify_area check
228c2ecf20Sopenharmony_ci *		Alan Cox	:	Started POSIXisms
238c2ecf20Sopenharmony_ci *		Andreas Schwab	:	Replace inode by dentry for proper
248c2ecf20Sopenharmony_ci *					reference counting
258c2ecf20Sopenharmony_ci *		Kirk Petersen	:	Made this a module
268c2ecf20Sopenharmony_ci *	    Christoph Rohland	:	Elegant non-blocking accept/connect algorithm.
278c2ecf20Sopenharmony_ci *					Lots of bug fixes.
288c2ecf20Sopenharmony_ci *	     Alexey Kuznetosv	:	Repaired (I hope) bugs introduces
298c2ecf20Sopenharmony_ci *					by above two patches.
308c2ecf20Sopenharmony_ci *	     Andrea Arcangeli	:	If possible we block in connect(2)
318c2ecf20Sopenharmony_ci *					if the max backlog of the listen socket
328c2ecf20Sopenharmony_ci *					is been reached. This won't break
338c2ecf20Sopenharmony_ci *					old apps and it will avoid huge amount
348c2ecf20Sopenharmony_ci *					of socks hashed (this for unix_gc()
358c2ecf20Sopenharmony_ci *					performances reasons).
368c2ecf20Sopenharmony_ci *					Security fix that limits the max
378c2ecf20Sopenharmony_ci *					number of socks to 2*max_files and
388c2ecf20Sopenharmony_ci *					the number of skb queueable in the
398c2ecf20Sopenharmony_ci *					dgram receiver.
408c2ecf20Sopenharmony_ci *		Artur Skawina   :	Hash function optimizations
418c2ecf20Sopenharmony_ci *	     Alexey Kuznetsov   :	Full scale SMP. Lot of bugs are introduced 8)
428c2ecf20Sopenharmony_ci *	      Malcolm Beattie   :	Set peercred for socketpair
438c2ecf20Sopenharmony_ci *	     Michal Ostrowski   :       Module initialization cleanup.
448c2ecf20Sopenharmony_ci *	     Arnaldo C. Melo	:	Remove MOD_{INC,DEC}_USE_COUNT,
458c2ecf20Sopenharmony_ci *	     				the core infrastructure is doing that
468c2ecf20Sopenharmony_ci *	     				for all net proto families now (2.5.69+)
478c2ecf20Sopenharmony_ci *
488c2ecf20Sopenharmony_ci * Known differences from reference BSD that was tested:
498c2ecf20Sopenharmony_ci *
508c2ecf20Sopenharmony_ci *	[TO FIX]
518c2ecf20Sopenharmony_ci *	ECONNREFUSED is not returned from one end of a connected() socket to the
528c2ecf20Sopenharmony_ci *		other the moment one end closes.
538c2ecf20Sopenharmony_ci *	fstat() doesn't return st_dev=0, and give the blksize as high water mark
548c2ecf20Sopenharmony_ci *		and a fake inode identifier (nor the BSD first socket fstat twice bug).
558c2ecf20Sopenharmony_ci *	[NOT TO FIX]
568c2ecf20Sopenharmony_ci *	accept() returns a path name even if the connecting socket has closed
578c2ecf20Sopenharmony_ci *		in the meantime (BSD loses the path and gives up).
588c2ecf20Sopenharmony_ci *	accept() returns 0 length path for an unbound connector. BSD returns 16
598c2ecf20Sopenharmony_ci *		and a null first byte in the path (but not for gethost/peername - BSD bug ??)
608c2ecf20Sopenharmony_ci *	socketpair(...SOCK_RAW..) doesn't panic the kernel.
618c2ecf20Sopenharmony_ci *	BSD af_unix apparently has connect forgetting to block properly.
628c2ecf20Sopenharmony_ci *		(need to check this with the POSIX spec in detail)
638c2ecf20Sopenharmony_ci *
648c2ecf20Sopenharmony_ci * Differences from 2.0.0-11-... (ANK)
658c2ecf20Sopenharmony_ci *	Bug fixes and improvements.
668c2ecf20Sopenharmony_ci *		- client shutdown killed server socket.
678c2ecf20Sopenharmony_ci *		- removed all useless cli/sti pairs.
688c2ecf20Sopenharmony_ci *
698c2ecf20Sopenharmony_ci *	Semantic changes/extensions.
708c2ecf20Sopenharmony_ci *		- generic control message passing.
718c2ecf20Sopenharmony_ci *		- SCM_CREDENTIALS control message.
728c2ecf20Sopenharmony_ci *		- "Abstract" (not FS based) socket bindings.
738c2ecf20Sopenharmony_ci *		  Abstract names are sequences of bytes (not zero terminated)
748c2ecf20Sopenharmony_ci *		  started by 0, so that this name space does not intersect
758c2ecf20Sopenharmony_ci *		  with BSD names.
768c2ecf20Sopenharmony_ci */
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci#include <linux/module.h>
818c2ecf20Sopenharmony_ci#include <linux/kernel.h>
828c2ecf20Sopenharmony_ci#include <linux/signal.h>
838c2ecf20Sopenharmony_ci#include <linux/sched/signal.h>
848c2ecf20Sopenharmony_ci#include <linux/errno.h>
858c2ecf20Sopenharmony_ci#include <linux/string.h>
868c2ecf20Sopenharmony_ci#include <linux/stat.h>
878c2ecf20Sopenharmony_ci#include <linux/dcache.h>
888c2ecf20Sopenharmony_ci#include <linux/namei.h>
898c2ecf20Sopenharmony_ci#include <linux/socket.h>
908c2ecf20Sopenharmony_ci#include <linux/un.h>
918c2ecf20Sopenharmony_ci#include <linux/fcntl.h>
928c2ecf20Sopenharmony_ci#include <linux/termios.h>
938c2ecf20Sopenharmony_ci#include <linux/sockios.h>
948c2ecf20Sopenharmony_ci#include <linux/net.h>
958c2ecf20Sopenharmony_ci#include <linux/in.h>
968c2ecf20Sopenharmony_ci#include <linux/fs.h>
978c2ecf20Sopenharmony_ci#include <linux/slab.h>
988c2ecf20Sopenharmony_ci#include <linux/uaccess.h>
998c2ecf20Sopenharmony_ci#include <linux/skbuff.h>
1008c2ecf20Sopenharmony_ci#include <linux/netdevice.h>
1018c2ecf20Sopenharmony_ci#include <net/net_namespace.h>
1028c2ecf20Sopenharmony_ci#include <net/sock.h>
1038c2ecf20Sopenharmony_ci#include <net/tcp_states.h>
1048c2ecf20Sopenharmony_ci#include <net/af_unix.h>
1058c2ecf20Sopenharmony_ci#include <linux/proc_fs.h>
1068c2ecf20Sopenharmony_ci#include <linux/seq_file.h>
1078c2ecf20Sopenharmony_ci#include <net/scm.h>
1088c2ecf20Sopenharmony_ci#include <linux/init.h>
1098c2ecf20Sopenharmony_ci#include <linux/poll.h>
1108c2ecf20Sopenharmony_ci#include <linux/rtnetlink.h>
1118c2ecf20Sopenharmony_ci#include <linux/mount.h>
1128c2ecf20Sopenharmony_ci#include <net/checksum.h>
1138c2ecf20Sopenharmony_ci#include <linux/security.h>
1148c2ecf20Sopenharmony_ci#include <linux/freezer.h>
1158c2ecf20Sopenharmony_ci#include <linux/file.h>
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci#include "scm.h"
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_cistruct hlist_head unix_socket_table[2 * UNIX_HASH_SIZE];
1208c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(unix_socket_table);
1218c2ecf20Sopenharmony_ciDEFINE_SPINLOCK(unix_table_lock);
1228c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(unix_table_lock);
1238c2ecf20Sopenharmony_cistatic atomic_long_t unix_nr_socks;
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_cistatic struct hlist_head *unix_sockets_unbound(void *addr)
1278c2ecf20Sopenharmony_ci{
1288c2ecf20Sopenharmony_ci	unsigned long hash = (unsigned long)addr;
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci	hash ^= hash >> 16;
1318c2ecf20Sopenharmony_ci	hash ^= hash >> 8;
1328c2ecf20Sopenharmony_ci	hash %= UNIX_HASH_SIZE;
1338c2ecf20Sopenharmony_ci	return &unix_socket_table[UNIX_HASH_SIZE + hash];
1348c2ecf20Sopenharmony_ci}
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci#define UNIX_ABSTRACT(sk)	(unix_sk(sk)->addr->hash < UNIX_HASH_SIZE)
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci#ifdef CONFIG_SECURITY_NETWORK
1398c2ecf20Sopenharmony_cistatic void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
1408c2ecf20Sopenharmony_ci{
1418c2ecf20Sopenharmony_ci	UNIXCB(skb).secid = scm->secid;
1428c2ecf20Sopenharmony_ci}
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_cistatic inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
1458c2ecf20Sopenharmony_ci{
1468c2ecf20Sopenharmony_ci	scm->secid = UNIXCB(skb).secid;
1478c2ecf20Sopenharmony_ci}
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_cistatic inline bool unix_secdata_eq(struct scm_cookie *scm, struct sk_buff *skb)
1508c2ecf20Sopenharmony_ci{
1518c2ecf20Sopenharmony_ci	return (scm->secid == UNIXCB(skb).secid);
1528c2ecf20Sopenharmony_ci}
1538c2ecf20Sopenharmony_ci#else
1548c2ecf20Sopenharmony_cistatic inline void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
1558c2ecf20Sopenharmony_ci{ }
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_cistatic inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
1588c2ecf20Sopenharmony_ci{ }
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_cistatic inline bool unix_secdata_eq(struct scm_cookie *scm, struct sk_buff *skb)
1618c2ecf20Sopenharmony_ci{
1628c2ecf20Sopenharmony_ci	return true;
1638c2ecf20Sopenharmony_ci}
1648c2ecf20Sopenharmony_ci#endif /* CONFIG_SECURITY_NETWORK */
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci/*
1678c2ecf20Sopenharmony_ci *  SMP locking strategy:
1688c2ecf20Sopenharmony_ci *    hash table is protected with spinlock unix_table_lock
1698c2ecf20Sopenharmony_ci *    each socket state is protected by separate spin lock.
1708c2ecf20Sopenharmony_ci */
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_cistatic inline unsigned int unix_hash_fold(__wsum n)
1738c2ecf20Sopenharmony_ci{
1748c2ecf20Sopenharmony_ci	unsigned int hash = (__force unsigned int)csum_fold(n);
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	hash ^= hash>>8;
1778c2ecf20Sopenharmony_ci	return hash&(UNIX_HASH_SIZE-1);
1788c2ecf20Sopenharmony_ci}
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci#define unix_peer(sk) (unix_sk(sk)->peer)
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_cistatic inline int unix_our_peer(struct sock *sk, struct sock *osk)
1838c2ecf20Sopenharmony_ci{
1848c2ecf20Sopenharmony_ci	return unix_peer(osk) == sk;
1858c2ecf20Sopenharmony_ci}
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_cistatic inline int unix_may_send(struct sock *sk, struct sock *osk)
1888c2ecf20Sopenharmony_ci{
1898c2ecf20Sopenharmony_ci	return unix_peer(osk) == NULL || unix_our_peer(sk, osk);
1908c2ecf20Sopenharmony_ci}
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_cistatic inline int unix_recvq_full(const struct sock *sk)
1938c2ecf20Sopenharmony_ci{
1948c2ecf20Sopenharmony_ci	return skb_queue_len(&sk->sk_receive_queue) > sk->sk_max_ack_backlog;
1958c2ecf20Sopenharmony_ci}
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_cistatic inline int unix_recvq_full_lockless(const struct sock *sk)
1988c2ecf20Sopenharmony_ci{
1998c2ecf20Sopenharmony_ci	return skb_queue_len_lockless(&sk->sk_receive_queue) >
2008c2ecf20Sopenharmony_ci		READ_ONCE(sk->sk_max_ack_backlog);
2018c2ecf20Sopenharmony_ci}
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_cistruct sock *unix_peer_get(struct sock *s)
2048c2ecf20Sopenharmony_ci{
2058c2ecf20Sopenharmony_ci	struct sock *peer;
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	unix_state_lock(s);
2088c2ecf20Sopenharmony_ci	peer = unix_peer(s);
2098c2ecf20Sopenharmony_ci	if (peer)
2108c2ecf20Sopenharmony_ci		sock_hold(peer);
2118c2ecf20Sopenharmony_ci	unix_state_unlock(s);
2128c2ecf20Sopenharmony_ci	return peer;
2138c2ecf20Sopenharmony_ci}
2148c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(unix_peer_get);
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_cistatic inline void unix_release_addr(struct unix_address *addr)
2178c2ecf20Sopenharmony_ci{
2188c2ecf20Sopenharmony_ci	if (refcount_dec_and_test(&addr->refcnt))
2198c2ecf20Sopenharmony_ci		kfree(addr);
2208c2ecf20Sopenharmony_ci}
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci/*
2238c2ecf20Sopenharmony_ci *	Check unix socket name:
2248c2ecf20Sopenharmony_ci *		- should be not zero length.
2258c2ecf20Sopenharmony_ci *	        - if started by not zero, should be NULL terminated (FS object)
2268c2ecf20Sopenharmony_ci *		- if started by zero, it is abstract name.
2278c2ecf20Sopenharmony_ci */
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_cistatic int unix_mkname(struct sockaddr_un *sunaddr, int len, unsigned int *hashp)
2308c2ecf20Sopenharmony_ci{
2318c2ecf20Sopenharmony_ci	*hashp = 0;
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	if (len <= sizeof(short) || len > sizeof(*sunaddr))
2348c2ecf20Sopenharmony_ci		return -EINVAL;
2358c2ecf20Sopenharmony_ci	if (!sunaddr || sunaddr->sun_family != AF_UNIX)
2368c2ecf20Sopenharmony_ci		return -EINVAL;
2378c2ecf20Sopenharmony_ci	if (sunaddr->sun_path[0]) {
2388c2ecf20Sopenharmony_ci		/*
2398c2ecf20Sopenharmony_ci		 * This may look like an off by one error but it is a bit more
2408c2ecf20Sopenharmony_ci		 * subtle. 108 is the longest valid AF_UNIX path for a binding.
2418c2ecf20Sopenharmony_ci		 * sun_path[108] doesn't as such exist.  However in kernel space
2428c2ecf20Sopenharmony_ci		 * we are guaranteed that it is a valid memory location in our
2438c2ecf20Sopenharmony_ci		 * kernel address buffer.
2448c2ecf20Sopenharmony_ci		 */
2458c2ecf20Sopenharmony_ci		((char *)sunaddr)[len] = 0;
2468c2ecf20Sopenharmony_ci		len = strlen(sunaddr->sun_path)+1+sizeof(short);
2478c2ecf20Sopenharmony_ci		return len;
2488c2ecf20Sopenharmony_ci	}
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	*hashp = unix_hash_fold(csum_partial(sunaddr, len, 0));
2518c2ecf20Sopenharmony_ci	return len;
2528c2ecf20Sopenharmony_ci}
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_cistatic void __unix_remove_socket(struct sock *sk)
2558c2ecf20Sopenharmony_ci{
2568c2ecf20Sopenharmony_ci	sk_del_node_init(sk);
2578c2ecf20Sopenharmony_ci}
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_cistatic void __unix_insert_socket(struct hlist_head *list, struct sock *sk)
2608c2ecf20Sopenharmony_ci{
2618c2ecf20Sopenharmony_ci	WARN_ON(!sk_unhashed(sk));
2628c2ecf20Sopenharmony_ci	sk_add_node(sk, list);
2638c2ecf20Sopenharmony_ci}
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_cistatic inline void unix_remove_socket(struct sock *sk)
2668c2ecf20Sopenharmony_ci{
2678c2ecf20Sopenharmony_ci	spin_lock(&unix_table_lock);
2688c2ecf20Sopenharmony_ci	__unix_remove_socket(sk);
2698c2ecf20Sopenharmony_ci	spin_unlock(&unix_table_lock);
2708c2ecf20Sopenharmony_ci}
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_cistatic inline void unix_insert_socket(struct hlist_head *list, struct sock *sk)
2738c2ecf20Sopenharmony_ci{
2748c2ecf20Sopenharmony_ci	spin_lock(&unix_table_lock);
2758c2ecf20Sopenharmony_ci	__unix_insert_socket(list, sk);
2768c2ecf20Sopenharmony_ci	spin_unlock(&unix_table_lock);
2778c2ecf20Sopenharmony_ci}
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_cistatic struct sock *__unix_find_socket_byname(struct net *net,
2808c2ecf20Sopenharmony_ci					      struct sockaddr_un *sunname,
2818c2ecf20Sopenharmony_ci					      int len, int type, unsigned int hash)
2828c2ecf20Sopenharmony_ci{
2838c2ecf20Sopenharmony_ci	struct sock *s;
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci	sk_for_each(s, &unix_socket_table[hash ^ type]) {
2868c2ecf20Sopenharmony_ci		struct unix_sock *u = unix_sk(s);
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci		if (!net_eq(sock_net(s), net))
2898c2ecf20Sopenharmony_ci			continue;
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci		if (u->addr->len == len &&
2928c2ecf20Sopenharmony_ci		    !memcmp(u->addr->name, sunname, len))
2938c2ecf20Sopenharmony_ci			return s;
2948c2ecf20Sopenharmony_ci	}
2958c2ecf20Sopenharmony_ci	return NULL;
2968c2ecf20Sopenharmony_ci}
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_cistatic inline struct sock *unix_find_socket_byname(struct net *net,
2998c2ecf20Sopenharmony_ci						   struct sockaddr_un *sunname,
3008c2ecf20Sopenharmony_ci						   int len, int type,
3018c2ecf20Sopenharmony_ci						   unsigned int hash)
3028c2ecf20Sopenharmony_ci{
3038c2ecf20Sopenharmony_ci	struct sock *s;
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	spin_lock(&unix_table_lock);
3068c2ecf20Sopenharmony_ci	s = __unix_find_socket_byname(net, sunname, len, type, hash);
3078c2ecf20Sopenharmony_ci	if (s)
3088c2ecf20Sopenharmony_ci		sock_hold(s);
3098c2ecf20Sopenharmony_ci	spin_unlock(&unix_table_lock);
3108c2ecf20Sopenharmony_ci	return s;
3118c2ecf20Sopenharmony_ci}
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_cistatic struct sock *unix_find_socket_byinode(struct inode *i)
3148c2ecf20Sopenharmony_ci{
3158c2ecf20Sopenharmony_ci	struct sock *s;
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	spin_lock(&unix_table_lock);
3188c2ecf20Sopenharmony_ci	sk_for_each(s,
3198c2ecf20Sopenharmony_ci		    &unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) {
3208c2ecf20Sopenharmony_ci		struct dentry *dentry = unix_sk(s)->path.dentry;
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci		if (dentry && d_backing_inode(dentry) == i) {
3238c2ecf20Sopenharmony_ci			sock_hold(s);
3248c2ecf20Sopenharmony_ci			goto found;
3258c2ecf20Sopenharmony_ci		}
3268c2ecf20Sopenharmony_ci	}
3278c2ecf20Sopenharmony_ci	s = NULL;
3288c2ecf20Sopenharmony_cifound:
3298c2ecf20Sopenharmony_ci	spin_unlock(&unix_table_lock);
3308c2ecf20Sopenharmony_ci	return s;
3318c2ecf20Sopenharmony_ci}
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci/* Support code for asymmetrically connected dgram sockets
3348c2ecf20Sopenharmony_ci *
3358c2ecf20Sopenharmony_ci * If a datagram socket is connected to a socket not itself connected
3368c2ecf20Sopenharmony_ci * to the first socket (eg, /dev/log), clients may only enqueue more
3378c2ecf20Sopenharmony_ci * messages if the present receive queue of the server socket is not
3388c2ecf20Sopenharmony_ci * "too large". This means there's a second writeability condition
3398c2ecf20Sopenharmony_ci * poll and sendmsg need to test. The dgram recv code will do a wake
3408c2ecf20Sopenharmony_ci * up on the peer_wait wait queue of a socket upon reception of a
3418c2ecf20Sopenharmony_ci * datagram which needs to be propagated to sleeping would-be writers
3428c2ecf20Sopenharmony_ci * since these might not have sent anything so far. This can't be
3438c2ecf20Sopenharmony_ci * accomplished via poll_wait because the lifetime of the server
3448c2ecf20Sopenharmony_ci * socket might be less than that of its clients if these break their
3458c2ecf20Sopenharmony_ci * association with it or if the server socket is closed while clients
3468c2ecf20Sopenharmony_ci * are still connected to it and there's no way to inform "a polling
3478c2ecf20Sopenharmony_ci * implementation" that it should let go of a certain wait queue
3488c2ecf20Sopenharmony_ci *
3498c2ecf20Sopenharmony_ci * In order to propagate a wake up, a wait_queue_entry_t of the client
3508c2ecf20Sopenharmony_ci * socket is enqueued on the peer_wait queue of the server socket
3518c2ecf20Sopenharmony_ci * whose wake function does a wake_up on the ordinary client socket
3528c2ecf20Sopenharmony_ci * wait queue. This connection is established whenever a write (or
3538c2ecf20Sopenharmony_ci * poll for write) hit the flow control condition and broken when the
3548c2ecf20Sopenharmony_ci * association to the server socket is dissolved or after a wake up
3558c2ecf20Sopenharmony_ci * was relayed.
3568c2ecf20Sopenharmony_ci */
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_cistatic int unix_dgram_peer_wake_relay(wait_queue_entry_t *q, unsigned mode, int flags,
3598c2ecf20Sopenharmony_ci				      void *key)
3608c2ecf20Sopenharmony_ci{
3618c2ecf20Sopenharmony_ci	struct unix_sock *u;
3628c2ecf20Sopenharmony_ci	wait_queue_head_t *u_sleep;
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	u = container_of(q, struct unix_sock, peer_wake);
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci	__remove_wait_queue(&unix_sk(u->peer_wake.private)->peer_wait,
3678c2ecf20Sopenharmony_ci			    q);
3688c2ecf20Sopenharmony_ci	u->peer_wake.private = NULL;
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_ci	/* relaying can only happen while the wq still exists */
3718c2ecf20Sopenharmony_ci	u_sleep = sk_sleep(&u->sk);
3728c2ecf20Sopenharmony_ci	if (u_sleep)
3738c2ecf20Sopenharmony_ci		wake_up_interruptible_poll(u_sleep, key_to_poll(key));
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_ci	return 0;
3768c2ecf20Sopenharmony_ci}
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_cistatic int unix_dgram_peer_wake_connect(struct sock *sk, struct sock *other)
3798c2ecf20Sopenharmony_ci{
3808c2ecf20Sopenharmony_ci	struct unix_sock *u, *u_other;
3818c2ecf20Sopenharmony_ci	int rc;
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci	u = unix_sk(sk);
3848c2ecf20Sopenharmony_ci	u_other = unix_sk(other);
3858c2ecf20Sopenharmony_ci	rc = 0;
3868c2ecf20Sopenharmony_ci	spin_lock(&u_other->peer_wait.lock);
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_ci	if (!u->peer_wake.private) {
3898c2ecf20Sopenharmony_ci		u->peer_wake.private = other;
3908c2ecf20Sopenharmony_ci		__add_wait_queue(&u_other->peer_wait, &u->peer_wake);
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci		rc = 1;
3938c2ecf20Sopenharmony_ci	}
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci	spin_unlock(&u_other->peer_wait.lock);
3968c2ecf20Sopenharmony_ci	return rc;
3978c2ecf20Sopenharmony_ci}
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_cistatic void unix_dgram_peer_wake_disconnect(struct sock *sk,
4008c2ecf20Sopenharmony_ci					    struct sock *other)
4018c2ecf20Sopenharmony_ci{
4028c2ecf20Sopenharmony_ci	struct unix_sock *u, *u_other;
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci	u = unix_sk(sk);
4058c2ecf20Sopenharmony_ci	u_other = unix_sk(other);
4068c2ecf20Sopenharmony_ci	spin_lock(&u_other->peer_wait.lock);
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_ci	if (u->peer_wake.private == other) {
4098c2ecf20Sopenharmony_ci		__remove_wait_queue(&u_other->peer_wait, &u->peer_wake);
4108c2ecf20Sopenharmony_ci		u->peer_wake.private = NULL;
4118c2ecf20Sopenharmony_ci	}
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci	spin_unlock(&u_other->peer_wait.lock);
4148c2ecf20Sopenharmony_ci}
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_cistatic void unix_dgram_peer_wake_disconnect_wakeup(struct sock *sk,
4178c2ecf20Sopenharmony_ci						   struct sock *other)
4188c2ecf20Sopenharmony_ci{
4198c2ecf20Sopenharmony_ci	unix_dgram_peer_wake_disconnect(sk, other);
4208c2ecf20Sopenharmony_ci	wake_up_interruptible_poll(sk_sleep(sk),
4218c2ecf20Sopenharmony_ci				   EPOLLOUT |
4228c2ecf20Sopenharmony_ci				   EPOLLWRNORM |
4238c2ecf20Sopenharmony_ci				   EPOLLWRBAND);
4248c2ecf20Sopenharmony_ci}
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci/* preconditions:
4278c2ecf20Sopenharmony_ci *	- unix_peer(sk) == other
4288c2ecf20Sopenharmony_ci *	- association is stable
4298c2ecf20Sopenharmony_ci */
4308c2ecf20Sopenharmony_cistatic int unix_dgram_peer_wake_me(struct sock *sk, struct sock *other)
4318c2ecf20Sopenharmony_ci{
4328c2ecf20Sopenharmony_ci	int connected;
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ci	connected = unix_dgram_peer_wake_connect(sk, other);
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci	/* If other is SOCK_DEAD, we want to make sure we signal
4378c2ecf20Sopenharmony_ci	 * POLLOUT, such that a subsequent write() can get a
4388c2ecf20Sopenharmony_ci	 * -ECONNREFUSED. Otherwise, if we haven't queued any skbs
4398c2ecf20Sopenharmony_ci	 * to other and its full, we will hang waiting for POLLOUT.
4408c2ecf20Sopenharmony_ci	 */
4418c2ecf20Sopenharmony_ci	if (unix_recvq_full_lockless(other) && !sock_flag(other, SOCK_DEAD))
4428c2ecf20Sopenharmony_ci		return 1;
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	if (connected)
4458c2ecf20Sopenharmony_ci		unix_dgram_peer_wake_disconnect(sk, other);
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ci	return 0;
4488c2ecf20Sopenharmony_ci}
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_cistatic int unix_writable(const struct sock *sk)
4518c2ecf20Sopenharmony_ci{
4528c2ecf20Sopenharmony_ci	return sk->sk_state != TCP_LISTEN &&
4538c2ecf20Sopenharmony_ci	       (refcount_read(&sk->sk_wmem_alloc) << 2) <= sk->sk_sndbuf;
4548c2ecf20Sopenharmony_ci}
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_cistatic void unix_write_space(struct sock *sk)
4578c2ecf20Sopenharmony_ci{
4588c2ecf20Sopenharmony_ci	struct socket_wq *wq;
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_ci	rcu_read_lock();
4618c2ecf20Sopenharmony_ci	if (unix_writable(sk)) {
4628c2ecf20Sopenharmony_ci		wq = rcu_dereference(sk->sk_wq);
4638c2ecf20Sopenharmony_ci		if (skwq_has_sleeper(wq))
4648c2ecf20Sopenharmony_ci			wake_up_interruptible_sync_poll(&wq->wait,
4658c2ecf20Sopenharmony_ci				EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND);
4668c2ecf20Sopenharmony_ci		sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
4678c2ecf20Sopenharmony_ci	}
4688c2ecf20Sopenharmony_ci	rcu_read_unlock();
4698c2ecf20Sopenharmony_ci}
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci/* When dgram socket disconnects (or changes its peer), we clear its receive
4728c2ecf20Sopenharmony_ci * queue of packets arrived from previous peer. First, it allows to do
4738c2ecf20Sopenharmony_ci * flow control based only on wmem_alloc; second, sk connected to peer
4748c2ecf20Sopenharmony_ci * may receive messages only from that peer. */
4758c2ecf20Sopenharmony_cistatic void unix_dgram_disconnected(struct sock *sk, struct sock *other)
4768c2ecf20Sopenharmony_ci{
4778c2ecf20Sopenharmony_ci	if (!skb_queue_empty(&sk->sk_receive_queue)) {
4788c2ecf20Sopenharmony_ci		skb_queue_purge(&sk->sk_receive_queue);
4798c2ecf20Sopenharmony_ci		wake_up_interruptible_all(&unix_sk(sk)->peer_wait);
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_ci		/* If one link of bidirectional dgram pipe is disconnected,
4828c2ecf20Sopenharmony_ci		 * we signal error. Messages are lost. Do not make this,
4838c2ecf20Sopenharmony_ci		 * when peer was not connected to us.
4848c2ecf20Sopenharmony_ci		 */
4858c2ecf20Sopenharmony_ci		if (!sock_flag(other, SOCK_DEAD) && unix_peer(other) == sk) {
4868c2ecf20Sopenharmony_ci			other->sk_err = ECONNRESET;
4878c2ecf20Sopenharmony_ci			other->sk_error_report(other);
4888c2ecf20Sopenharmony_ci		}
4898c2ecf20Sopenharmony_ci	}
4908c2ecf20Sopenharmony_ci}
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_cistatic void unix_sock_destructor(struct sock *sk)
4938c2ecf20Sopenharmony_ci{
4948c2ecf20Sopenharmony_ci	struct unix_sock *u = unix_sk(sk);
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	skb_queue_purge(&sk->sk_receive_queue);
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci	WARN_ON(refcount_read(&sk->sk_wmem_alloc));
4998c2ecf20Sopenharmony_ci	WARN_ON(!sk_unhashed(sk));
5008c2ecf20Sopenharmony_ci	WARN_ON(sk->sk_socket);
5018c2ecf20Sopenharmony_ci	if (!sock_flag(sk, SOCK_DEAD)) {
5028c2ecf20Sopenharmony_ci		pr_info("Attempt to release alive unix socket: %p\n", sk);
5038c2ecf20Sopenharmony_ci		return;
5048c2ecf20Sopenharmony_ci	}
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci	if (u->addr)
5078c2ecf20Sopenharmony_ci		unix_release_addr(u->addr);
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci	atomic_long_dec(&unix_nr_socks);
5108c2ecf20Sopenharmony_ci	local_bh_disable();
5118c2ecf20Sopenharmony_ci	sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
5128c2ecf20Sopenharmony_ci	local_bh_enable();
5138c2ecf20Sopenharmony_ci#ifdef UNIX_REFCNT_DEBUG
5148c2ecf20Sopenharmony_ci	pr_debug("UNIX %p is destroyed, %ld are still alive.\n", sk,
5158c2ecf20Sopenharmony_ci		atomic_long_read(&unix_nr_socks));
5168c2ecf20Sopenharmony_ci#endif
5178c2ecf20Sopenharmony_ci}
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_cistatic void unix_release_sock(struct sock *sk, int embrion)
5208c2ecf20Sopenharmony_ci{
5218c2ecf20Sopenharmony_ci	struct unix_sock *u = unix_sk(sk);
5228c2ecf20Sopenharmony_ci	struct path path;
5238c2ecf20Sopenharmony_ci	struct sock *skpair;
5248c2ecf20Sopenharmony_ci	struct sk_buff *skb;
5258c2ecf20Sopenharmony_ci	int state;
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ci	unix_remove_socket(sk);
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci	/* Clear state */
5308c2ecf20Sopenharmony_ci	unix_state_lock(sk);
5318c2ecf20Sopenharmony_ci	sock_orphan(sk);
5328c2ecf20Sopenharmony_ci	WRITE_ONCE(sk->sk_shutdown, SHUTDOWN_MASK);
5338c2ecf20Sopenharmony_ci	path	     = u->path;
5348c2ecf20Sopenharmony_ci	u->path.dentry = NULL;
5358c2ecf20Sopenharmony_ci	u->path.mnt = NULL;
5368c2ecf20Sopenharmony_ci	state = sk->sk_state;
5378c2ecf20Sopenharmony_ci	sk->sk_state = TCP_CLOSE;
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_ci	skpair = unix_peer(sk);
5408c2ecf20Sopenharmony_ci	unix_peer(sk) = NULL;
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_ci	unix_state_unlock(sk);
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_ci	wake_up_interruptible_all(&u->peer_wait);
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_ci	if (skpair != NULL) {
5478c2ecf20Sopenharmony_ci		if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) {
5488c2ecf20Sopenharmony_ci			unix_state_lock(skpair);
5498c2ecf20Sopenharmony_ci			/* No more writes */
5508c2ecf20Sopenharmony_ci			WRITE_ONCE(skpair->sk_shutdown, SHUTDOWN_MASK);
5518c2ecf20Sopenharmony_ci			if (!skb_queue_empty(&sk->sk_receive_queue) || embrion)
5528c2ecf20Sopenharmony_ci				skpair->sk_err = ECONNRESET;
5538c2ecf20Sopenharmony_ci			unix_state_unlock(skpair);
5548c2ecf20Sopenharmony_ci			skpair->sk_state_change(skpair);
5558c2ecf20Sopenharmony_ci			sk_wake_async(skpair, SOCK_WAKE_WAITD, POLL_HUP);
5568c2ecf20Sopenharmony_ci		}
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci		unix_dgram_peer_wake_disconnect(sk, skpair);
5598c2ecf20Sopenharmony_ci		sock_put(skpair); /* It may now die */
5608c2ecf20Sopenharmony_ci	}
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci	/* Try to flush out this socket. Throw out buffers at least */
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci	while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
5658c2ecf20Sopenharmony_ci		if (state == TCP_LISTEN)
5668c2ecf20Sopenharmony_ci			unix_release_sock(skb->sk, 1);
5678c2ecf20Sopenharmony_ci		/* passed fds are erased in the kfree_skb hook	      */
5688c2ecf20Sopenharmony_ci		UNIXCB(skb).consumed = skb->len;
5698c2ecf20Sopenharmony_ci		kfree_skb(skb);
5708c2ecf20Sopenharmony_ci	}
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ci	if (path.dentry)
5738c2ecf20Sopenharmony_ci		path_put(&path);
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_ci	sock_put(sk);
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_ci	/* ---- Socket is dead now and most probably destroyed ---- */
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci	/*
5808c2ecf20Sopenharmony_ci	 * Fixme: BSD difference: In BSD all sockets connected to us get
5818c2ecf20Sopenharmony_ci	 *	  ECONNRESET and we die on the spot. In Linux we behave
5828c2ecf20Sopenharmony_ci	 *	  like files and pipes do and wait for the last
5838c2ecf20Sopenharmony_ci	 *	  dereference.
5848c2ecf20Sopenharmony_ci	 *
5858c2ecf20Sopenharmony_ci	 * Can't we simply set sock->err?
5868c2ecf20Sopenharmony_ci	 *
5878c2ecf20Sopenharmony_ci	 *	  What the above comment does talk about? --ANK(980817)
5888c2ecf20Sopenharmony_ci	 */
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci	if (READ_ONCE(unix_tot_inflight))
5918c2ecf20Sopenharmony_ci		unix_gc();		/* Garbage collect fds */
5928c2ecf20Sopenharmony_ci}
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_cistatic void init_peercred(struct sock *sk)
5958c2ecf20Sopenharmony_ci{
5968c2ecf20Sopenharmony_ci	const struct cred *old_cred;
5978c2ecf20Sopenharmony_ci	struct pid *old_pid;
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci	spin_lock(&sk->sk_peer_lock);
6008c2ecf20Sopenharmony_ci	old_pid = sk->sk_peer_pid;
6018c2ecf20Sopenharmony_ci	old_cred = sk->sk_peer_cred;
6028c2ecf20Sopenharmony_ci	sk->sk_peer_pid  = get_pid(task_tgid(current));
6038c2ecf20Sopenharmony_ci	sk->sk_peer_cred = get_current_cred();
6048c2ecf20Sopenharmony_ci	spin_unlock(&sk->sk_peer_lock);
6058c2ecf20Sopenharmony_ci
6068c2ecf20Sopenharmony_ci	put_pid(old_pid);
6078c2ecf20Sopenharmony_ci	put_cred(old_cred);
6088c2ecf20Sopenharmony_ci}
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_cistatic void copy_peercred(struct sock *sk, struct sock *peersk)
6118c2ecf20Sopenharmony_ci{
6128c2ecf20Sopenharmony_ci	const struct cred *old_cred;
6138c2ecf20Sopenharmony_ci	struct pid *old_pid;
6148c2ecf20Sopenharmony_ci
6158c2ecf20Sopenharmony_ci	if (sk < peersk) {
6168c2ecf20Sopenharmony_ci		spin_lock(&sk->sk_peer_lock);
6178c2ecf20Sopenharmony_ci		spin_lock_nested(&peersk->sk_peer_lock, SINGLE_DEPTH_NESTING);
6188c2ecf20Sopenharmony_ci	} else {
6198c2ecf20Sopenharmony_ci		spin_lock(&peersk->sk_peer_lock);
6208c2ecf20Sopenharmony_ci		spin_lock_nested(&sk->sk_peer_lock, SINGLE_DEPTH_NESTING);
6218c2ecf20Sopenharmony_ci	}
6228c2ecf20Sopenharmony_ci	old_pid = sk->sk_peer_pid;
6238c2ecf20Sopenharmony_ci	old_cred = sk->sk_peer_cred;
6248c2ecf20Sopenharmony_ci	sk->sk_peer_pid  = get_pid(peersk->sk_peer_pid);
6258c2ecf20Sopenharmony_ci	sk->sk_peer_cred = get_cred(peersk->sk_peer_cred);
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_ci	spin_unlock(&sk->sk_peer_lock);
6288c2ecf20Sopenharmony_ci	spin_unlock(&peersk->sk_peer_lock);
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ci	put_pid(old_pid);
6318c2ecf20Sopenharmony_ci	put_cred(old_cred);
6328c2ecf20Sopenharmony_ci}
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_cistatic int unix_listen(struct socket *sock, int backlog)
6358c2ecf20Sopenharmony_ci{
6368c2ecf20Sopenharmony_ci	int err;
6378c2ecf20Sopenharmony_ci	struct sock *sk = sock->sk;
6388c2ecf20Sopenharmony_ci	struct unix_sock *u = unix_sk(sk);
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_ci	err = -EOPNOTSUPP;
6418c2ecf20Sopenharmony_ci	if (sock->type != SOCK_STREAM && sock->type != SOCK_SEQPACKET)
6428c2ecf20Sopenharmony_ci		goto out;	/* Only stream/seqpacket sockets accept */
6438c2ecf20Sopenharmony_ci	err = -EINVAL;
6448c2ecf20Sopenharmony_ci	if (!u->addr)
6458c2ecf20Sopenharmony_ci		goto out;	/* No listens on an unbound socket */
6468c2ecf20Sopenharmony_ci	unix_state_lock(sk);
6478c2ecf20Sopenharmony_ci	if (sk->sk_state != TCP_CLOSE && sk->sk_state != TCP_LISTEN)
6488c2ecf20Sopenharmony_ci		goto out_unlock;
6498c2ecf20Sopenharmony_ci	if (backlog > sk->sk_max_ack_backlog)
6508c2ecf20Sopenharmony_ci		wake_up_interruptible_all(&u->peer_wait);
6518c2ecf20Sopenharmony_ci	sk->sk_max_ack_backlog	= backlog;
6528c2ecf20Sopenharmony_ci	sk->sk_state		= TCP_LISTEN;
6538c2ecf20Sopenharmony_ci	/* set credentials so connect can copy them */
6548c2ecf20Sopenharmony_ci	init_peercred(sk);
6558c2ecf20Sopenharmony_ci	err = 0;
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_ciout_unlock:
6588c2ecf20Sopenharmony_ci	unix_state_unlock(sk);
6598c2ecf20Sopenharmony_ciout:
6608c2ecf20Sopenharmony_ci	return err;
6618c2ecf20Sopenharmony_ci}
6628c2ecf20Sopenharmony_ci
6638c2ecf20Sopenharmony_cistatic int unix_release(struct socket *);
6648c2ecf20Sopenharmony_cistatic int unix_bind(struct socket *, struct sockaddr *, int);
6658c2ecf20Sopenharmony_cistatic int unix_stream_connect(struct socket *, struct sockaddr *,
6668c2ecf20Sopenharmony_ci			       int addr_len, int flags);
6678c2ecf20Sopenharmony_cistatic int unix_socketpair(struct socket *, struct socket *);
6688c2ecf20Sopenharmony_cistatic int unix_accept(struct socket *, struct socket *, int, bool);
6698c2ecf20Sopenharmony_cistatic int unix_getname(struct socket *, struct sockaddr *, int);
6708c2ecf20Sopenharmony_cistatic __poll_t unix_poll(struct file *, struct socket *, poll_table *);
6718c2ecf20Sopenharmony_cistatic __poll_t unix_dgram_poll(struct file *, struct socket *,
6728c2ecf20Sopenharmony_ci				    poll_table *);
6738c2ecf20Sopenharmony_cistatic int unix_ioctl(struct socket *, unsigned int, unsigned long);
6748c2ecf20Sopenharmony_ci#ifdef CONFIG_COMPAT
6758c2ecf20Sopenharmony_cistatic int unix_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
6768c2ecf20Sopenharmony_ci#endif
6778c2ecf20Sopenharmony_cistatic int unix_shutdown(struct socket *, int);
6788c2ecf20Sopenharmony_cistatic int unix_stream_sendmsg(struct socket *, struct msghdr *, size_t);
6798c2ecf20Sopenharmony_cistatic int unix_stream_recvmsg(struct socket *, struct msghdr *, size_t, int);
6808c2ecf20Sopenharmony_cistatic ssize_t unix_stream_sendpage(struct socket *, struct page *, int offset,
6818c2ecf20Sopenharmony_ci				    size_t size, int flags);
6828c2ecf20Sopenharmony_cistatic ssize_t unix_stream_splice_read(struct socket *,  loff_t *ppos,
6838c2ecf20Sopenharmony_ci				       struct pipe_inode_info *, size_t size,
6848c2ecf20Sopenharmony_ci				       unsigned int flags);
6858c2ecf20Sopenharmony_cistatic int unix_dgram_sendmsg(struct socket *, struct msghdr *, size_t);
6868c2ecf20Sopenharmony_cistatic int unix_dgram_recvmsg(struct socket *, struct msghdr *, size_t, int);
6878c2ecf20Sopenharmony_cistatic int unix_dgram_connect(struct socket *, struct sockaddr *,
6888c2ecf20Sopenharmony_ci			      int, int);
6898c2ecf20Sopenharmony_cistatic int unix_seqpacket_sendmsg(struct socket *, struct msghdr *, size_t);
6908c2ecf20Sopenharmony_cistatic int unix_seqpacket_recvmsg(struct socket *, struct msghdr *, size_t,
6918c2ecf20Sopenharmony_ci				  int);
6928c2ecf20Sopenharmony_ci
6938c2ecf20Sopenharmony_cistatic int unix_set_peek_off(struct sock *sk, int val)
6948c2ecf20Sopenharmony_ci{
6958c2ecf20Sopenharmony_ci	struct unix_sock *u = unix_sk(sk);
6968c2ecf20Sopenharmony_ci
6978c2ecf20Sopenharmony_ci	if (mutex_lock_interruptible(&u->iolock))
6988c2ecf20Sopenharmony_ci		return -EINTR;
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_ci	WRITE_ONCE(sk->sk_peek_off, val);
7018c2ecf20Sopenharmony_ci	mutex_unlock(&u->iolock);
7028c2ecf20Sopenharmony_ci
7038c2ecf20Sopenharmony_ci	return 0;
7048c2ecf20Sopenharmony_ci}
7058c2ecf20Sopenharmony_ci
7068c2ecf20Sopenharmony_ci#ifdef CONFIG_PROC_FS
7078c2ecf20Sopenharmony_cistatic void unix_show_fdinfo(struct seq_file *m, struct socket *sock)
7088c2ecf20Sopenharmony_ci{
7098c2ecf20Sopenharmony_ci	struct sock *sk = sock->sk;
7108c2ecf20Sopenharmony_ci	struct unix_sock *u;
7118c2ecf20Sopenharmony_ci
7128c2ecf20Sopenharmony_ci	if (sk) {
7138c2ecf20Sopenharmony_ci		u = unix_sk(sock->sk);
7148c2ecf20Sopenharmony_ci		seq_printf(m, "scm_fds: %u\n",
7158c2ecf20Sopenharmony_ci			   atomic_read(&u->scm_stat.nr_fds));
7168c2ecf20Sopenharmony_ci	}
7178c2ecf20Sopenharmony_ci}
7188c2ecf20Sopenharmony_ci#else
7198c2ecf20Sopenharmony_ci#define unix_show_fdinfo NULL
7208c2ecf20Sopenharmony_ci#endif
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_cistatic const struct proto_ops unix_stream_ops = {
7238c2ecf20Sopenharmony_ci	.family =	PF_UNIX,
7248c2ecf20Sopenharmony_ci	.owner =	THIS_MODULE,
7258c2ecf20Sopenharmony_ci	.release =	unix_release,
7268c2ecf20Sopenharmony_ci	.bind =		unix_bind,
7278c2ecf20Sopenharmony_ci	.connect =	unix_stream_connect,
7288c2ecf20Sopenharmony_ci	.socketpair =	unix_socketpair,
7298c2ecf20Sopenharmony_ci	.accept =	unix_accept,
7308c2ecf20Sopenharmony_ci	.getname =	unix_getname,
7318c2ecf20Sopenharmony_ci	.poll =		unix_poll,
7328c2ecf20Sopenharmony_ci	.ioctl =	unix_ioctl,
7338c2ecf20Sopenharmony_ci#ifdef CONFIG_COMPAT
7348c2ecf20Sopenharmony_ci	.compat_ioctl =	unix_compat_ioctl,
7358c2ecf20Sopenharmony_ci#endif
7368c2ecf20Sopenharmony_ci	.listen =	unix_listen,
7378c2ecf20Sopenharmony_ci	.shutdown =	unix_shutdown,
7388c2ecf20Sopenharmony_ci	.sendmsg =	unix_stream_sendmsg,
7398c2ecf20Sopenharmony_ci	.recvmsg =	unix_stream_recvmsg,
7408c2ecf20Sopenharmony_ci	.mmap =		sock_no_mmap,
7418c2ecf20Sopenharmony_ci	.sendpage =	unix_stream_sendpage,
7428c2ecf20Sopenharmony_ci	.splice_read =	unix_stream_splice_read,
7438c2ecf20Sopenharmony_ci	.set_peek_off =	unix_set_peek_off,
7448c2ecf20Sopenharmony_ci	.show_fdinfo =	unix_show_fdinfo,
7458c2ecf20Sopenharmony_ci};
7468c2ecf20Sopenharmony_ci
7478c2ecf20Sopenharmony_cistatic const struct proto_ops unix_dgram_ops = {
7488c2ecf20Sopenharmony_ci	.family =	PF_UNIX,
7498c2ecf20Sopenharmony_ci	.owner =	THIS_MODULE,
7508c2ecf20Sopenharmony_ci	.release =	unix_release,
7518c2ecf20Sopenharmony_ci	.bind =		unix_bind,
7528c2ecf20Sopenharmony_ci	.connect =	unix_dgram_connect,
7538c2ecf20Sopenharmony_ci	.socketpair =	unix_socketpair,
7548c2ecf20Sopenharmony_ci	.accept =	sock_no_accept,
7558c2ecf20Sopenharmony_ci	.getname =	unix_getname,
7568c2ecf20Sopenharmony_ci	.poll =		unix_dgram_poll,
7578c2ecf20Sopenharmony_ci	.ioctl =	unix_ioctl,
7588c2ecf20Sopenharmony_ci#ifdef CONFIG_COMPAT
7598c2ecf20Sopenharmony_ci	.compat_ioctl =	unix_compat_ioctl,
7608c2ecf20Sopenharmony_ci#endif
7618c2ecf20Sopenharmony_ci	.listen =	sock_no_listen,
7628c2ecf20Sopenharmony_ci	.shutdown =	unix_shutdown,
7638c2ecf20Sopenharmony_ci	.sendmsg =	unix_dgram_sendmsg,
7648c2ecf20Sopenharmony_ci	.recvmsg =	unix_dgram_recvmsg,
7658c2ecf20Sopenharmony_ci	.mmap =		sock_no_mmap,
7668c2ecf20Sopenharmony_ci	.sendpage =	sock_no_sendpage,
7678c2ecf20Sopenharmony_ci	.set_peek_off =	unix_set_peek_off,
7688c2ecf20Sopenharmony_ci	.show_fdinfo =	unix_show_fdinfo,
7698c2ecf20Sopenharmony_ci};
7708c2ecf20Sopenharmony_ci
7718c2ecf20Sopenharmony_cistatic const struct proto_ops unix_seqpacket_ops = {
7728c2ecf20Sopenharmony_ci	.family =	PF_UNIX,
7738c2ecf20Sopenharmony_ci	.owner =	THIS_MODULE,
7748c2ecf20Sopenharmony_ci	.release =	unix_release,
7758c2ecf20Sopenharmony_ci	.bind =		unix_bind,
7768c2ecf20Sopenharmony_ci	.connect =	unix_stream_connect,
7778c2ecf20Sopenharmony_ci	.socketpair =	unix_socketpair,
7788c2ecf20Sopenharmony_ci	.accept =	unix_accept,
7798c2ecf20Sopenharmony_ci	.getname =	unix_getname,
7808c2ecf20Sopenharmony_ci	.poll =		unix_dgram_poll,
7818c2ecf20Sopenharmony_ci	.ioctl =	unix_ioctl,
7828c2ecf20Sopenharmony_ci#ifdef CONFIG_COMPAT
7838c2ecf20Sopenharmony_ci	.compat_ioctl =	unix_compat_ioctl,
7848c2ecf20Sopenharmony_ci#endif
7858c2ecf20Sopenharmony_ci	.listen =	unix_listen,
7868c2ecf20Sopenharmony_ci	.shutdown =	unix_shutdown,
7878c2ecf20Sopenharmony_ci	.sendmsg =	unix_seqpacket_sendmsg,
7888c2ecf20Sopenharmony_ci	.recvmsg =	unix_seqpacket_recvmsg,
7898c2ecf20Sopenharmony_ci	.mmap =		sock_no_mmap,
7908c2ecf20Sopenharmony_ci	.sendpage =	sock_no_sendpage,
7918c2ecf20Sopenharmony_ci	.set_peek_off =	unix_set_peek_off,
7928c2ecf20Sopenharmony_ci	.show_fdinfo =	unix_show_fdinfo,
7938c2ecf20Sopenharmony_ci};
7948c2ecf20Sopenharmony_ci
7958c2ecf20Sopenharmony_cistatic struct proto unix_proto = {
7968c2ecf20Sopenharmony_ci	.name			= "UNIX",
7978c2ecf20Sopenharmony_ci	.owner			= THIS_MODULE,
7988c2ecf20Sopenharmony_ci	.obj_size		= sizeof(struct unix_sock),
7998c2ecf20Sopenharmony_ci};
8008c2ecf20Sopenharmony_ci
8018c2ecf20Sopenharmony_cistatic struct sock *unix_create1(struct net *net, struct socket *sock, int kern)
8028c2ecf20Sopenharmony_ci{
8038c2ecf20Sopenharmony_ci	struct sock *sk = NULL;
8048c2ecf20Sopenharmony_ci	struct unix_sock *u;
8058c2ecf20Sopenharmony_ci
8068c2ecf20Sopenharmony_ci	atomic_long_inc(&unix_nr_socks);
8078c2ecf20Sopenharmony_ci	if (atomic_long_read(&unix_nr_socks) > 2 * get_max_files())
8088c2ecf20Sopenharmony_ci		goto out;
8098c2ecf20Sopenharmony_ci
8108c2ecf20Sopenharmony_ci	sk = sk_alloc(net, PF_UNIX, GFP_KERNEL, &unix_proto, kern);
8118c2ecf20Sopenharmony_ci	if (!sk)
8128c2ecf20Sopenharmony_ci		goto out;
8138c2ecf20Sopenharmony_ci
8148c2ecf20Sopenharmony_ci	sock_init_data(sock, sk);
8158c2ecf20Sopenharmony_ci
8168c2ecf20Sopenharmony_ci	sk->sk_allocation	= GFP_KERNEL_ACCOUNT;
8178c2ecf20Sopenharmony_ci	sk->sk_write_space	= unix_write_space;
8188c2ecf20Sopenharmony_ci	sk->sk_max_ack_backlog	= net->unx.sysctl_max_dgram_qlen;
8198c2ecf20Sopenharmony_ci	sk->sk_destruct		= unix_sock_destructor;
8208c2ecf20Sopenharmony_ci	u	  = unix_sk(sk);
8218c2ecf20Sopenharmony_ci	u->path.dentry = NULL;
8228c2ecf20Sopenharmony_ci	u->path.mnt = NULL;
8238c2ecf20Sopenharmony_ci	spin_lock_init(&u->lock);
8248c2ecf20Sopenharmony_ci	atomic_long_set(&u->inflight, 0);
8258c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&u->link);
8268c2ecf20Sopenharmony_ci	mutex_init(&u->iolock); /* single task reading lock */
8278c2ecf20Sopenharmony_ci	mutex_init(&u->bindlock); /* single task binding lock */
8288c2ecf20Sopenharmony_ci	init_waitqueue_head(&u->peer_wait);
8298c2ecf20Sopenharmony_ci	init_waitqueue_func_entry(&u->peer_wake, unix_dgram_peer_wake_relay);
8308c2ecf20Sopenharmony_ci	memset(&u->scm_stat, 0, sizeof(struct scm_stat));
8318c2ecf20Sopenharmony_ci	unix_insert_socket(unix_sockets_unbound(sk), sk);
8328c2ecf20Sopenharmony_ciout:
8338c2ecf20Sopenharmony_ci	if (sk == NULL)
8348c2ecf20Sopenharmony_ci		atomic_long_dec(&unix_nr_socks);
8358c2ecf20Sopenharmony_ci	else {
8368c2ecf20Sopenharmony_ci		local_bh_disable();
8378c2ecf20Sopenharmony_ci		sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
8388c2ecf20Sopenharmony_ci		local_bh_enable();
8398c2ecf20Sopenharmony_ci	}
8408c2ecf20Sopenharmony_ci	return sk;
8418c2ecf20Sopenharmony_ci}
8428c2ecf20Sopenharmony_ci
8438c2ecf20Sopenharmony_cistatic int unix_create(struct net *net, struct socket *sock, int protocol,
8448c2ecf20Sopenharmony_ci		       int kern)
8458c2ecf20Sopenharmony_ci{
8468c2ecf20Sopenharmony_ci	if (protocol && protocol != PF_UNIX)
8478c2ecf20Sopenharmony_ci		return -EPROTONOSUPPORT;
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci	sock->state = SS_UNCONNECTED;
8508c2ecf20Sopenharmony_ci
8518c2ecf20Sopenharmony_ci	switch (sock->type) {
8528c2ecf20Sopenharmony_ci	case SOCK_STREAM:
8538c2ecf20Sopenharmony_ci		sock->ops = &unix_stream_ops;
8548c2ecf20Sopenharmony_ci		break;
8558c2ecf20Sopenharmony_ci		/*
8568c2ecf20Sopenharmony_ci		 *	Believe it or not BSD has AF_UNIX, SOCK_RAW though
8578c2ecf20Sopenharmony_ci		 *	nothing uses it.
8588c2ecf20Sopenharmony_ci		 */
8598c2ecf20Sopenharmony_ci	case SOCK_RAW:
8608c2ecf20Sopenharmony_ci		sock->type = SOCK_DGRAM;
8618c2ecf20Sopenharmony_ci		fallthrough;
8628c2ecf20Sopenharmony_ci	case SOCK_DGRAM:
8638c2ecf20Sopenharmony_ci		sock->ops = &unix_dgram_ops;
8648c2ecf20Sopenharmony_ci		break;
8658c2ecf20Sopenharmony_ci	case SOCK_SEQPACKET:
8668c2ecf20Sopenharmony_ci		sock->ops = &unix_seqpacket_ops;
8678c2ecf20Sopenharmony_ci		break;
8688c2ecf20Sopenharmony_ci	default:
8698c2ecf20Sopenharmony_ci		return -ESOCKTNOSUPPORT;
8708c2ecf20Sopenharmony_ci	}
8718c2ecf20Sopenharmony_ci
8728c2ecf20Sopenharmony_ci	return unix_create1(net, sock, kern) ? 0 : -ENOMEM;
8738c2ecf20Sopenharmony_ci}
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_cistatic int unix_release(struct socket *sock)
8768c2ecf20Sopenharmony_ci{
8778c2ecf20Sopenharmony_ci	struct sock *sk = sock->sk;
8788c2ecf20Sopenharmony_ci
8798c2ecf20Sopenharmony_ci	if (!sk)
8808c2ecf20Sopenharmony_ci		return 0;
8818c2ecf20Sopenharmony_ci
8828c2ecf20Sopenharmony_ci	unix_release_sock(sk, 0);
8838c2ecf20Sopenharmony_ci	sock->sk = NULL;
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_ci	return 0;
8868c2ecf20Sopenharmony_ci}
8878c2ecf20Sopenharmony_ci
8888c2ecf20Sopenharmony_cistatic int unix_autobind(struct socket *sock)
8898c2ecf20Sopenharmony_ci{
8908c2ecf20Sopenharmony_ci	struct sock *sk = sock->sk;
8918c2ecf20Sopenharmony_ci	struct net *net = sock_net(sk);
8928c2ecf20Sopenharmony_ci	struct unix_sock *u = unix_sk(sk);
8938c2ecf20Sopenharmony_ci	static u32 ordernum = 1;
8948c2ecf20Sopenharmony_ci	struct unix_address *addr;
8958c2ecf20Sopenharmony_ci	int err;
8968c2ecf20Sopenharmony_ci	unsigned int retries = 0;
8978c2ecf20Sopenharmony_ci
8988c2ecf20Sopenharmony_ci	err = mutex_lock_interruptible(&u->bindlock);
8998c2ecf20Sopenharmony_ci	if (err)
9008c2ecf20Sopenharmony_ci		return err;
9018c2ecf20Sopenharmony_ci
9028c2ecf20Sopenharmony_ci	if (u->addr)
9038c2ecf20Sopenharmony_ci		goto out;
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_ci	err = -ENOMEM;
9068c2ecf20Sopenharmony_ci	addr = kzalloc(sizeof(*addr) + sizeof(short) + 16, GFP_KERNEL);
9078c2ecf20Sopenharmony_ci	if (!addr)
9088c2ecf20Sopenharmony_ci		goto out;
9098c2ecf20Sopenharmony_ci
9108c2ecf20Sopenharmony_ci	addr->name->sun_family = AF_UNIX;
9118c2ecf20Sopenharmony_ci	refcount_set(&addr->refcnt, 1);
9128c2ecf20Sopenharmony_ci
9138c2ecf20Sopenharmony_ciretry:
9148c2ecf20Sopenharmony_ci	addr->len = sprintf(addr->name->sun_path+1, "%05x", ordernum) + 1 + sizeof(short);
9158c2ecf20Sopenharmony_ci	addr->hash = unix_hash_fold(csum_partial(addr->name, addr->len, 0));
9168c2ecf20Sopenharmony_ci
9178c2ecf20Sopenharmony_ci	spin_lock(&unix_table_lock);
9188c2ecf20Sopenharmony_ci	ordernum = (ordernum+1)&0xFFFFF;
9198c2ecf20Sopenharmony_ci
9208c2ecf20Sopenharmony_ci	if (__unix_find_socket_byname(net, addr->name, addr->len, sock->type,
9218c2ecf20Sopenharmony_ci				      addr->hash)) {
9228c2ecf20Sopenharmony_ci		spin_unlock(&unix_table_lock);
9238c2ecf20Sopenharmony_ci		/*
9248c2ecf20Sopenharmony_ci		 * __unix_find_socket_byname() may take long time if many names
9258c2ecf20Sopenharmony_ci		 * are already in use.
9268c2ecf20Sopenharmony_ci		 */
9278c2ecf20Sopenharmony_ci		cond_resched();
9288c2ecf20Sopenharmony_ci		/* Give up if all names seems to be in use. */
9298c2ecf20Sopenharmony_ci		if (retries++ == 0xFFFFF) {
9308c2ecf20Sopenharmony_ci			err = -ENOSPC;
9318c2ecf20Sopenharmony_ci			kfree(addr);
9328c2ecf20Sopenharmony_ci			goto out;
9338c2ecf20Sopenharmony_ci		}
9348c2ecf20Sopenharmony_ci		goto retry;
9358c2ecf20Sopenharmony_ci	}
9368c2ecf20Sopenharmony_ci	addr->hash ^= sk->sk_type;
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_ci	__unix_remove_socket(sk);
9398c2ecf20Sopenharmony_ci	smp_store_release(&u->addr, addr);
9408c2ecf20Sopenharmony_ci	__unix_insert_socket(&unix_socket_table[addr->hash], sk);
9418c2ecf20Sopenharmony_ci	spin_unlock(&unix_table_lock);
9428c2ecf20Sopenharmony_ci	err = 0;
9438c2ecf20Sopenharmony_ci
9448c2ecf20Sopenharmony_ciout:	mutex_unlock(&u->bindlock);
9458c2ecf20Sopenharmony_ci	return err;
9468c2ecf20Sopenharmony_ci}
9478c2ecf20Sopenharmony_ci
9488c2ecf20Sopenharmony_cistatic struct sock *unix_find_other(struct net *net,
9498c2ecf20Sopenharmony_ci				    struct sockaddr_un *sunname, int len,
9508c2ecf20Sopenharmony_ci				    int type, unsigned int hash, int *error)
9518c2ecf20Sopenharmony_ci{
9528c2ecf20Sopenharmony_ci	struct sock *u;
9538c2ecf20Sopenharmony_ci	struct path path;
9548c2ecf20Sopenharmony_ci	int err = 0;
9558c2ecf20Sopenharmony_ci
9568c2ecf20Sopenharmony_ci	if (sunname->sun_path[0]) {
9578c2ecf20Sopenharmony_ci		struct inode *inode;
9588c2ecf20Sopenharmony_ci		err = kern_path(sunname->sun_path, LOOKUP_FOLLOW, &path);
9598c2ecf20Sopenharmony_ci		if (err)
9608c2ecf20Sopenharmony_ci			goto fail;
9618c2ecf20Sopenharmony_ci		inode = d_backing_inode(path.dentry);
9628c2ecf20Sopenharmony_ci		err = inode_permission(inode, MAY_WRITE);
9638c2ecf20Sopenharmony_ci		if (err)
9648c2ecf20Sopenharmony_ci			goto put_fail;
9658c2ecf20Sopenharmony_ci
9668c2ecf20Sopenharmony_ci		err = -ECONNREFUSED;
9678c2ecf20Sopenharmony_ci		if (!S_ISSOCK(inode->i_mode))
9688c2ecf20Sopenharmony_ci			goto put_fail;
9698c2ecf20Sopenharmony_ci		u = unix_find_socket_byinode(inode);
9708c2ecf20Sopenharmony_ci		if (!u)
9718c2ecf20Sopenharmony_ci			goto put_fail;
9728c2ecf20Sopenharmony_ci
9738c2ecf20Sopenharmony_ci		if (u->sk_type == type)
9748c2ecf20Sopenharmony_ci			touch_atime(&path);
9758c2ecf20Sopenharmony_ci
9768c2ecf20Sopenharmony_ci		path_put(&path);
9778c2ecf20Sopenharmony_ci
9788c2ecf20Sopenharmony_ci		err = -EPROTOTYPE;
9798c2ecf20Sopenharmony_ci		if (u->sk_type != type) {
9808c2ecf20Sopenharmony_ci			sock_put(u);
9818c2ecf20Sopenharmony_ci			goto fail;
9828c2ecf20Sopenharmony_ci		}
9838c2ecf20Sopenharmony_ci	} else {
9848c2ecf20Sopenharmony_ci		err = -ECONNREFUSED;
9858c2ecf20Sopenharmony_ci		u = unix_find_socket_byname(net, sunname, len, type, hash);
9868c2ecf20Sopenharmony_ci		if (u) {
9878c2ecf20Sopenharmony_ci			struct dentry *dentry;
9888c2ecf20Sopenharmony_ci			dentry = unix_sk(u)->path.dentry;
9898c2ecf20Sopenharmony_ci			if (dentry)
9908c2ecf20Sopenharmony_ci				touch_atime(&unix_sk(u)->path);
9918c2ecf20Sopenharmony_ci		} else
9928c2ecf20Sopenharmony_ci			goto fail;
9938c2ecf20Sopenharmony_ci	}
9948c2ecf20Sopenharmony_ci	return u;
9958c2ecf20Sopenharmony_ci
9968c2ecf20Sopenharmony_ciput_fail:
9978c2ecf20Sopenharmony_ci	path_put(&path);
9988c2ecf20Sopenharmony_cifail:
9998c2ecf20Sopenharmony_ci	*error = err;
10008c2ecf20Sopenharmony_ci	return NULL;
10018c2ecf20Sopenharmony_ci}
10028c2ecf20Sopenharmony_ci
10038c2ecf20Sopenharmony_cistatic int unix_mknod(const char *sun_path, umode_t mode, struct path *res)
10048c2ecf20Sopenharmony_ci{
10058c2ecf20Sopenharmony_ci	struct dentry *dentry;
10068c2ecf20Sopenharmony_ci	struct path path;
10078c2ecf20Sopenharmony_ci	int err = 0;
10088c2ecf20Sopenharmony_ci	/*
10098c2ecf20Sopenharmony_ci	 * Get the parent directory, calculate the hash for last
10108c2ecf20Sopenharmony_ci	 * component.
10118c2ecf20Sopenharmony_ci	 */
10128c2ecf20Sopenharmony_ci	dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0);
10138c2ecf20Sopenharmony_ci	err = PTR_ERR(dentry);
10148c2ecf20Sopenharmony_ci	if (IS_ERR(dentry))
10158c2ecf20Sopenharmony_ci		return err;
10168c2ecf20Sopenharmony_ci
10178c2ecf20Sopenharmony_ci	/*
10188c2ecf20Sopenharmony_ci	 * All right, let's create it.
10198c2ecf20Sopenharmony_ci	 */
10208c2ecf20Sopenharmony_ci	err = security_path_mknod(&path, dentry, mode, 0);
10218c2ecf20Sopenharmony_ci	if (!err) {
10228c2ecf20Sopenharmony_ci		err = vfs_mknod(d_inode(path.dentry), dentry, mode, 0);
10238c2ecf20Sopenharmony_ci		if (!err) {
10248c2ecf20Sopenharmony_ci			res->mnt = mntget(path.mnt);
10258c2ecf20Sopenharmony_ci			res->dentry = dget(dentry);
10268c2ecf20Sopenharmony_ci		}
10278c2ecf20Sopenharmony_ci	}
10288c2ecf20Sopenharmony_ci	done_path_create(&path, dentry);
10298c2ecf20Sopenharmony_ci	return err;
10308c2ecf20Sopenharmony_ci}
10318c2ecf20Sopenharmony_ci
10328c2ecf20Sopenharmony_cistatic int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
10338c2ecf20Sopenharmony_ci{
10348c2ecf20Sopenharmony_ci	struct sock *sk = sock->sk;
10358c2ecf20Sopenharmony_ci	struct net *net = sock_net(sk);
10368c2ecf20Sopenharmony_ci	struct unix_sock *u = unix_sk(sk);
10378c2ecf20Sopenharmony_ci	struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr;
10388c2ecf20Sopenharmony_ci	char *sun_path = sunaddr->sun_path;
10398c2ecf20Sopenharmony_ci	int err;
10408c2ecf20Sopenharmony_ci	unsigned int hash;
10418c2ecf20Sopenharmony_ci	struct unix_address *addr;
10428c2ecf20Sopenharmony_ci	struct hlist_head *list;
10438c2ecf20Sopenharmony_ci	struct path path = { };
10448c2ecf20Sopenharmony_ci
10458c2ecf20Sopenharmony_ci	err = -EINVAL;
10468c2ecf20Sopenharmony_ci	if (addr_len < offsetofend(struct sockaddr_un, sun_family) ||
10478c2ecf20Sopenharmony_ci	    sunaddr->sun_family != AF_UNIX)
10488c2ecf20Sopenharmony_ci		goto out;
10498c2ecf20Sopenharmony_ci
10508c2ecf20Sopenharmony_ci	if (addr_len == sizeof(short)) {
10518c2ecf20Sopenharmony_ci		err = unix_autobind(sock);
10528c2ecf20Sopenharmony_ci		goto out;
10538c2ecf20Sopenharmony_ci	}
10548c2ecf20Sopenharmony_ci
10558c2ecf20Sopenharmony_ci	err = unix_mkname(sunaddr, addr_len, &hash);
10568c2ecf20Sopenharmony_ci	if (err < 0)
10578c2ecf20Sopenharmony_ci		goto out;
10588c2ecf20Sopenharmony_ci	addr_len = err;
10598c2ecf20Sopenharmony_ci
10608c2ecf20Sopenharmony_ci	if (sun_path[0]) {
10618c2ecf20Sopenharmony_ci		umode_t mode = S_IFSOCK |
10628c2ecf20Sopenharmony_ci		       (SOCK_INODE(sock)->i_mode & ~current_umask());
10638c2ecf20Sopenharmony_ci		err = unix_mknod(sun_path, mode, &path);
10648c2ecf20Sopenharmony_ci		if (err) {
10658c2ecf20Sopenharmony_ci			if (err == -EEXIST)
10668c2ecf20Sopenharmony_ci				err = -EADDRINUSE;
10678c2ecf20Sopenharmony_ci			goto out;
10688c2ecf20Sopenharmony_ci		}
10698c2ecf20Sopenharmony_ci	}
10708c2ecf20Sopenharmony_ci
10718c2ecf20Sopenharmony_ci	err = mutex_lock_interruptible(&u->bindlock);
10728c2ecf20Sopenharmony_ci	if (err)
10738c2ecf20Sopenharmony_ci		goto out_put;
10748c2ecf20Sopenharmony_ci
10758c2ecf20Sopenharmony_ci	err = -EINVAL;
10768c2ecf20Sopenharmony_ci	if (u->addr)
10778c2ecf20Sopenharmony_ci		goto out_up;
10788c2ecf20Sopenharmony_ci
10798c2ecf20Sopenharmony_ci	err = -ENOMEM;
10808c2ecf20Sopenharmony_ci	addr = kmalloc(sizeof(*addr)+addr_len, GFP_KERNEL);
10818c2ecf20Sopenharmony_ci	if (!addr)
10828c2ecf20Sopenharmony_ci		goto out_up;
10838c2ecf20Sopenharmony_ci
10848c2ecf20Sopenharmony_ci	memcpy(addr->name, sunaddr, addr_len);
10858c2ecf20Sopenharmony_ci	addr->len = addr_len;
10868c2ecf20Sopenharmony_ci	addr->hash = hash ^ sk->sk_type;
10878c2ecf20Sopenharmony_ci	refcount_set(&addr->refcnt, 1);
10888c2ecf20Sopenharmony_ci
10898c2ecf20Sopenharmony_ci	if (sun_path[0]) {
10908c2ecf20Sopenharmony_ci		addr->hash = UNIX_HASH_SIZE;
10918c2ecf20Sopenharmony_ci		hash = d_backing_inode(path.dentry)->i_ino & (UNIX_HASH_SIZE - 1);
10928c2ecf20Sopenharmony_ci		spin_lock(&unix_table_lock);
10938c2ecf20Sopenharmony_ci		u->path = path;
10948c2ecf20Sopenharmony_ci		list = &unix_socket_table[hash];
10958c2ecf20Sopenharmony_ci	} else {
10968c2ecf20Sopenharmony_ci		spin_lock(&unix_table_lock);
10978c2ecf20Sopenharmony_ci		err = -EADDRINUSE;
10988c2ecf20Sopenharmony_ci		if (__unix_find_socket_byname(net, sunaddr, addr_len,
10998c2ecf20Sopenharmony_ci					      sk->sk_type, hash)) {
11008c2ecf20Sopenharmony_ci			unix_release_addr(addr);
11018c2ecf20Sopenharmony_ci			goto out_unlock;
11028c2ecf20Sopenharmony_ci		}
11038c2ecf20Sopenharmony_ci
11048c2ecf20Sopenharmony_ci		list = &unix_socket_table[addr->hash];
11058c2ecf20Sopenharmony_ci	}
11068c2ecf20Sopenharmony_ci
11078c2ecf20Sopenharmony_ci	err = 0;
11088c2ecf20Sopenharmony_ci	__unix_remove_socket(sk);
11098c2ecf20Sopenharmony_ci	smp_store_release(&u->addr, addr);
11108c2ecf20Sopenharmony_ci	__unix_insert_socket(list, sk);
11118c2ecf20Sopenharmony_ci
11128c2ecf20Sopenharmony_ciout_unlock:
11138c2ecf20Sopenharmony_ci	spin_unlock(&unix_table_lock);
11148c2ecf20Sopenharmony_ciout_up:
11158c2ecf20Sopenharmony_ci	mutex_unlock(&u->bindlock);
11168c2ecf20Sopenharmony_ciout_put:
11178c2ecf20Sopenharmony_ci	if (err)
11188c2ecf20Sopenharmony_ci		path_put(&path);
11198c2ecf20Sopenharmony_ciout:
11208c2ecf20Sopenharmony_ci	return err;
11218c2ecf20Sopenharmony_ci}
11228c2ecf20Sopenharmony_ci
11238c2ecf20Sopenharmony_cistatic void unix_state_double_lock(struct sock *sk1, struct sock *sk2)
11248c2ecf20Sopenharmony_ci{
11258c2ecf20Sopenharmony_ci	if (unlikely(sk1 == sk2) || !sk2) {
11268c2ecf20Sopenharmony_ci		unix_state_lock(sk1);
11278c2ecf20Sopenharmony_ci		return;
11288c2ecf20Sopenharmony_ci	}
11298c2ecf20Sopenharmony_ci	if (sk1 > sk2)
11308c2ecf20Sopenharmony_ci		swap(sk1, sk2);
11318c2ecf20Sopenharmony_ci
11328c2ecf20Sopenharmony_ci	unix_state_lock(sk1);
11338c2ecf20Sopenharmony_ci	unix_state_lock_nested(sk2, U_LOCK_SECOND);
11348c2ecf20Sopenharmony_ci}
11358c2ecf20Sopenharmony_ci
11368c2ecf20Sopenharmony_cistatic void unix_state_double_unlock(struct sock *sk1, struct sock *sk2)
11378c2ecf20Sopenharmony_ci{
11388c2ecf20Sopenharmony_ci	if (unlikely(sk1 == sk2) || !sk2) {
11398c2ecf20Sopenharmony_ci		unix_state_unlock(sk1);
11408c2ecf20Sopenharmony_ci		return;
11418c2ecf20Sopenharmony_ci	}
11428c2ecf20Sopenharmony_ci	unix_state_unlock(sk1);
11438c2ecf20Sopenharmony_ci	unix_state_unlock(sk2);
11448c2ecf20Sopenharmony_ci}
11458c2ecf20Sopenharmony_ci
11468c2ecf20Sopenharmony_cistatic int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
11478c2ecf20Sopenharmony_ci			      int alen, int flags)
11488c2ecf20Sopenharmony_ci{
11498c2ecf20Sopenharmony_ci	struct sock *sk = sock->sk;
11508c2ecf20Sopenharmony_ci	struct net *net = sock_net(sk);
11518c2ecf20Sopenharmony_ci	struct sockaddr_un *sunaddr = (struct sockaddr_un *)addr;
11528c2ecf20Sopenharmony_ci	struct sock *other;
11538c2ecf20Sopenharmony_ci	unsigned int hash;
11548c2ecf20Sopenharmony_ci	int err;
11558c2ecf20Sopenharmony_ci
11568c2ecf20Sopenharmony_ci	err = -EINVAL;
11578c2ecf20Sopenharmony_ci	if (alen < offsetofend(struct sockaddr, sa_family))
11588c2ecf20Sopenharmony_ci		goto out;
11598c2ecf20Sopenharmony_ci
11608c2ecf20Sopenharmony_ci	if (addr->sa_family != AF_UNSPEC) {
11618c2ecf20Sopenharmony_ci		err = unix_mkname(sunaddr, alen, &hash);
11628c2ecf20Sopenharmony_ci		if (err < 0)
11638c2ecf20Sopenharmony_ci			goto out;
11648c2ecf20Sopenharmony_ci		alen = err;
11658c2ecf20Sopenharmony_ci
11668c2ecf20Sopenharmony_ci		if (test_bit(SOCK_PASSCRED, &sock->flags) &&
11678c2ecf20Sopenharmony_ci		    !unix_sk(sk)->addr && (err = unix_autobind(sock)) != 0)
11688c2ecf20Sopenharmony_ci			goto out;
11698c2ecf20Sopenharmony_ci
11708c2ecf20Sopenharmony_cirestart:
11718c2ecf20Sopenharmony_ci		other = unix_find_other(net, sunaddr, alen, sock->type, hash, &err);
11728c2ecf20Sopenharmony_ci		if (!other)
11738c2ecf20Sopenharmony_ci			goto out;
11748c2ecf20Sopenharmony_ci
11758c2ecf20Sopenharmony_ci		unix_state_double_lock(sk, other);
11768c2ecf20Sopenharmony_ci
11778c2ecf20Sopenharmony_ci		/* Apparently VFS overslept socket death. Retry. */
11788c2ecf20Sopenharmony_ci		if (sock_flag(other, SOCK_DEAD)) {
11798c2ecf20Sopenharmony_ci			unix_state_double_unlock(sk, other);
11808c2ecf20Sopenharmony_ci			sock_put(other);
11818c2ecf20Sopenharmony_ci			goto restart;
11828c2ecf20Sopenharmony_ci		}
11838c2ecf20Sopenharmony_ci
11848c2ecf20Sopenharmony_ci		err = -EPERM;
11858c2ecf20Sopenharmony_ci		if (!unix_may_send(sk, other))
11868c2ecf20Sopenharmony_ci			goto out_unlock;
11878c2ecf20Sopenharmony_ci
11888c2ecf20Sopenharmony_ci		err = security_unix_may_send(sk->sk_socket, other->sk_socket);
11898c2ecf20Sopenharmony_ci		if (err)
11908c2ecf20Sopenharmony_ci			goto out_unlock;
11918c2ecf20Sopenharmony_ci
11928c2ecf20Sopenharmony_ci	} else {
11938c2ecf20Sopenharmony_ci		/*
11948c2ecf20Sopenharmony_ci		 *	1003.1g breaking connected state with AF_UNSPEC
11958c2ecf20Sopenharmony_ci		 */
11968c2ecf20Sopenharmony_ci		other = NULL;
11978c2ecf20Sopenharmony_ci		unix_state_double_lock(sk, other);
11988c2ecf20Sopenharmony_ci	}
11998c2ecf20Sopenharmony_ci
12008c2ecf20Sopenharmony_ci	/*
12018c2ecf20Sopenharmony_ci	 * If it was connected, reconnect.
12028c2ecf20Sopenharmony_ci	 */
12038c2ecf20Sopenharmony_ci	if (unix_peer(sk)) {
12048c2ecf20Sopenharmony_ci		struct sock *old_peer = unix_peer(sk);
12058c2ecf20Sopenharmony_ci		unix_peer(sk) = other;
12068c2ecf20Sopenharmony_ci		unix_dgram_peer_wake_disconnect_wakeup(sk, old_peer);
12078c2ecf20Sopenharmony_ci
12088c2ecf20Sopenharmony_ci		unix_state_double_unlock(sk, other);
12098c2ecf20Sopenharmony_ci
12108c2ecf20Sopenharmony_ci		if (other != old_peer)
12118c2ecf20Sopenharmony_ci			unix_dgram_disconnected(sk, old_peer);
12128c2ecf20Sopenharmony_ci		sock_put(old_peer);
12138c2ecf20Sopenharmony_ci	} else {
12148c2ecf20Sopenharmony_ci		unix_peer(sk) = other;
12158c2ecf20Sopenharmony_ci		unix_state_double_unlock(sk, other);
12168c2ecf20Sopenharmony_ci	}
12178c2ecf20Sopenharmony_ci	return 0;
12188c2ecf20Sopenharmony_ci
12198c2ecf20Sopenharmony_ciout_unlock:
12208c2ecf20Sopenharmony_ci	unix_state_double_unlock(sk, other);
12218c2ecf20Sopenharmony_ci	sock_put(other);
12228c2ecf20Sopenharmony_ciout:
12238c2ecf20Sopenharmony_ci	return err;
12248c2ecf20Sopenharmony_ci}
12258c2ecf20Sopenharmony_ci
12268c2ecf20Sopenharmony_cistatic long unix_wait_for_peer(struct sock *other, long timeo)
12278c2ecf20Sopenharmony_ci	__releases(&unix_sk(other)->lock)
12288c2ecf20Sopenharmony_ci{
12298c2ecf20Sopenharmony_ci	struct unix_sock *u = unix_sk(other);
12308c2ecf20Sopenharmony_ci	int sched;
12318c2ecf20Sopenharmony_ci	DEFINE_WAIT(wait);
12328c2ecf20Sopenharmony_ci
12338c2ecf20Sopenharmony_ci	prepare_to_wait_exclusive(&u->peer_wait, &wait, TASK_INTERRUPTIBLE);
12348c2ecf20Sopenharmony_ci
12358c2ecf20Sopenharmony_ci	sched = !sock_flag(other, SOCK_DEAD) &&
12368c2ecf20Sopenharmony_ci		!(other->sk_shutdown & RCV_SHUTDOWN) &&
12378c2ecf20Sopenharmony_ci		unix_recvq_full_lockless(other);
12388c2ecf20Sopenharmony_ci
12398c2ecf20Sopenharmony_ci	unix_state_unlock(other);
12408c2ecf20Sopenharmony_ci
12418c2ecf20Sopenharmony_ci	if (sched)
12428c2ecf20Sopenharmony_ci		timeo = schedule_timeout(timeo);
12438c2ecf20Sopenharmony_ci
12448c2ecf20Sopenharmony_ci	finish_wait(&u->peer_wait, &wait);
12458c2ecf20Sopenharmony_ci	return timeo;
12468c2ecf20Sopenharmony_ci}
12478c2ecf20Sopenharmony_ci
12488c2ecf20Sopenharmony_cistatic int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
12498c2ecf20Sopenharmony_ci			       int addr_len, int flags)
12508c2ecf20Sopenharmony_ci{
12518c2ecf20Sopenharmony_ci	struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr;
12528c2ecf20Sopenharmony_ci	struct sock *sk = sock->sk;
12538c2ecf20Sopenharmony_ci	struct net *net = sock_net(sk);
12548c2ecf20Sopenharmony_ci	struct unix_sock *u = unix_sk(sk), *newu, *otheru;
12558c2ecf20Sopenharmony_ci	struct sock *newsk = NULL;
12568c2ecf20Sopenharmony_ci	struct sock *other = NULL;
12578c2ecf20Sopenharmony_ci	struct sk_buff *skb = NULL;
12588c2ecf20Sopenharmony_ci	unsigned int hash;
12598c2ecf20Sopenharmony_ci	int st;
12608c2ecf20Sopenharmony_ci	int err;
12618c2ecf20Sopenharmony_ci	long timeo;
12628c2ecf20Sopenharmony_ci
12638c2ecf20Sopenharmony_ci	err = unix_mkname(sunaddr, addr_len, &hash);
12648c2ecf20Sopenharmony_ci	if (err < 0)
12658c2ecf20Sopenharmony_ci		goto out;
12668c2ecf20Sopenharmony_ci	addr_len = err;
12678c2ecf20Sopenharmony_ci
12688c2ecf20Sopenharmony_ci	if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr &&
12698c2ecf20Sopenharmony_ci	    (err = unix_autobind(sock)) != 0)
12708c2ecf20Sopenharmony_ci		goto out;
12718c2ecf20Sopenharmony_ci
12728c2ecf20Sopenharmony_ci	timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
12738c2ecf20Sopenharmony_ci
12748c2ecf20Sopenharmony_ci	/* First of all allocate resources.
12758c2ecf20Sopenharmony_ci	   If we will make it after state is locked,
12768c2ecf20Sopenharmony_ci	   we will have to recheck all again in any case.
12778c2ecf20Sopenharmony_ci	 */
12788c2ecf20Sopenharmony_ci
12798c2ecf20Sopenharmony_ci	err = -ENOMEM;
12808c2ecf20Sopenharmony_ci
12818c2ecf20Sopenharmony_ci	/* create new sock for complete connection */
12828c2ecf20Sopenharmony_ci	newsk = unix_create1(sock_net(sk), NULL, 0);
12838c2ecf20Sopenharmony_ci	if (newsk == NULL)
12848c2ecf20Sopenharmony_ci		goto out;
12858c2ecf20Sopenharmony_ci
12868c2ecf20Sopenharmony_ci	/* Allocate skb for sending to listening sock */
12878c2ecf20Sopenharmony_ci	skb = sock_wmalloc(newsk, 1, 0, GFP_KERNEL);
12888c2ecf20Sopenharmony_ci	if (skb == NULL)
12898c2ecf20Sopenharmony_ci		goto out;
12908c2ecf20Sopenharmony_ci
12918c2ecf20Sopenharmony_cirestart:
12928c2ecf20Sopenharmony_ci	/*  Find listening sock. */
12938c2ecf20Sopenharmony_ci	other = unix_find_other(net, sunaddr, addr_len, sk->sk_type, hash, &err);
12948c2ecf20Sopenharmony_ci	if (!other)
12958c2ecf20Sopenharmony_ci		goto out;
12968c2ecf20Sopenharmony_ci
12978c2ecf20Sopenharmony_ci	/* Latch state of peer */
12988c2ecf20Sopenharmony_ci	unix_state_lock(other);
12998c2ecf20Sopenharmony_ci
13008c2ecf20Sopenharmony_ci	/* Apparently VFS overslept socket death. Retry. */
13018c2ecf20Sopenharmony_ci	if (sock_flag(other, SOCK_DEAD)) {
13028c2ecf20Sopenharmony_ci		unix_state_unlock(other);
13038c2ecf20Sopenharmony_ci		sock_put(other);
13048c2ecf20Sopenharmony_ci		goto restart;
13058c2ecf20Sopenharmony_ci	}
13068c2ecf20Sopenharmony_ci
13078c2ecf20Sopenharmony_ci	err = -ECONNREFUSED;
13088c2ecf20Sopenharmony_ci	if (other->sk_state != TCP_LISTEN)
13098c2ecf20Sopenharmony_ci		goto out_unlock;
13108c2ecf20Sopenharmony_ci	if (other->sk_shutdown & RCV_SHUTDOWN)
13118c2ecf20Sopenharmony_ci		goto out_unlock;
13128c2ecf20Sopenharmony_ci
13138c2ecf20Sopenharmony_ci	if (unix_recvq_full(other)) {
13148c2ecf20Sopenharmony_ci		err = -EAGAIN;
13158c2ecf20Sopenharmony_ci		if (!timeo)
13168c2ecf20Sopenharmony_ci			goto out_unlock;
13178c2ecf20Sopenharmony_ci
13188c2ecf20Sopenharmony_ci		timeo = unix_wait_for_peer(other, timeo);
13198c2ecf20Sopenharmony_ci
13208c2ecf20Sopenharmony_ci		err = sock_intr_errno(timeo);
13218c2ecf20Sopenharmony_ci		if (signal_pending(current))
13228c2ecf20Sopenharmony_ci			goto out;
13238c2ecf20Sopenharmony_ci		sock_put(other);
13248c2ecf20Sopenharmony_ci		goto restart;
13258c2ecf20Sopenharmony_ci	}
13268c2ecf20Sopenharmony_ci
13278c2ecf20Sopenharmony_ci	/* Latch our state.
13288c2ecf20Sopenharmony_ci
13298c2ecf20Sopenharmony_ci	   It is tricky place. We need to grab our state lock and cannot
13308c2ecf20Sopenharmony_ci	   drop lock on peer. It is dangerous because deadlock is
13318c2ecf20Sopenharmony_ci	   possible. Connect to self case and simultaneous
13328c2ecf20Sopenharmony_ci	   attempt to connect are eliminated by checking socket
13338c2ecf20Sopenharmony_ci	   state. other is TCP_LISTEN, if sk is TCP_LISTEN we
13348c2ecf20Sopenharmony_ci	   check this before attempt to grab lock.
13358c2ecf20Sopenharmony_ci
13368c2ecf20Sopenharmony_ci	   Well, and we have to recheck the state after socket locked.
13378c2ecf20Sopenharmony_ci	 */
13388c2ecf20Sopenharmony_ci	st = sk->sk_state;
13398c2ecf20Sopenharmony_ci
13408c2ecf20Sopenharmony_ci	switch (st) {
13418c2ecf20Sopenharmony_ci	case TCP_CLOSE:
13428c2ecf20Sopenharmony_ci		/* This is ok... continue with connect */
13438c2ecf20Sopenharmony_ci		break;
13448c2ecf20Sopenharmony_ci	case TCP_ESTABLISHED:
13458c2ecf20Sopenharmony_ci		/* Socket is already connected */
13468c2ecf20Sopenharmony_ci		err = -EISCONN;
13478c2ecf20Sopenharmony_ci		goto out_unlock;
13488c2ecf20Sopenharmony_ci	default:
13498c2ecf20Sopenharmony_ci		err = -EINVAL;
13508c2ecf20Sopenharmony_ci		goto out_unlock;
13518c2ecf20Sopenharmony_ci	}
13528c2ecf20Sopenharmony_ci
13538c2ecf20Sopenharmony_ci	unix_state_lock_nested(sk, U_LOCK_SECOND);
13548c2ecf20Sopenharmony_ci
13558c2ecf20Sopenharmony_ci	if (sk->sk_state != st) {
13568c2ecf20Sopenharmony_ci		unix_state_unlock(sk);
13578c2ecf20Sopenharmony_ci		unix_state_unlock(other);
13588c2ecf20Sopenharmony_ci		sock_put(other);
13598c2ecf20Sopenharmony_ci		goto restart;
13608c2ecf20Sopenharmony_ci	}
13618c2ecf20Sopenharmony_ci
13628c2ecf20Sopenharmony_ci	err = security_unix_stream_connect(sk, other, newsk);
13638c2ecf20Sopenharmony_ci	if (err) {
13648c2ecf20Sopenharmony_ci		unix_state_unlock(sk);
13658c2ecf20Sopenharmony_ci		goto out_unlock;
13668c2ecf20Sopenharmony_ci	}
13678c2ecf20Sopenharmony_ci
13688c2ecf20Sopenharmony_ci	/* The way is open! Fastly set all the necessary fields... */
13698c2ecf20Sopenharmony_ci
13708c2ecf20Sopenharmony_ci	sock_hold(sk);
13718c2ecf20Sopenharmony_ci	unix_peer(newsk)	= sk;
13728c2ecf20Sopenharmony_ci	newsk->sk_state		= TCP_ESTABLISHED;
13738c2ecf20Sopenharmony_ci	newsk->sk_type		= sk->sk_type;
13748c2ecf20Sopenharmony_ci	init_peercred(newsk);
13758c2ecf20Sopenharmony_ci	newu = unix_sk(newsk);
13768c2ecf20Sopenharmony_ci	RCU_INIT_POINTER(newsk->sk_wq, &newu->peer_wq);
13778c2ecf20Sopenharmony_ci	otheru = unix_sk(other);
13788c2ecf20Sopenharmony_ci
13798c2ecf20Sopenharmony_ci	/* copy address information from listening to new sock
13808c2ecf20Sopenharmony_ci	 *
13818c2ecf20Sopenharmony_ci	 * The contents of *(otheru->addr) and otheru->path
13828c2ecf20Sopenharmony_ci	 * are seen fully set up here, since we have found
13838c2ecf20Sopenharmony_ci	 * otheru in hash under unix_table_lock.  Insertion
13848c2ecf20Sopenharmony_ci	 * into the hash chain we'd found it in had been done
13858c2ecf20Sopenharmony_ci	 * in an earlier critical area protected by unix_table_lock,
13868c2ecf20Sopenharmony_ci	 * the same one where we'd set *(otheru->addr) contents,
13878c2ecf20Sopenharmony_ci	 * as well as otheru->path and otheru->addr itself.
13888c2ecf20Sopenharmony_ci	 *
13898c2ecf20Sopenharmony_ci	 * Using smp_store_release() here to set newu->addr
13908c2ecf20Sopenharmony_ci	 * is enough to make those stores, as well as stores
13918c2ecf20Sopenharmony_ci	 * to newu->path visible to anyone who gets newu->addr
13928c2ecf20Sopenharmony_ci	 * by smp_load_acquire().  IOW, the same warranties
13938c2ecf20Sopenharmony_ci	 * as for unix_sock instances bound in unix_bind() or
13948c2ecf20Sopenharmony_ci	 * in unix_autobind().
13958c2ecf20Sopenharmony_ci	 */
13968c2ecf20Sopenharmony_ci	if (otheru->path.dentry) {
13978c2ecf20Sopenharmony_ci		path_get(&otheru->path);
13988c2ecf20Sopenharmony_ci		newu->path = otheru->path;
13998c2ecf20Sopenharmony_ci	}
14008c2ecf20Sopenharmony_ci	refcount_inc(&otheru->addr->refcnt);
14018c2ecf20Sopenharmony_ci	smp_store_release(&newu->addr, otheru->addr);
14028c2ecf20Sopenharmony_ci
14038c2ecf20Sopenharmony_ci	/* Set credentials */
14048c2ecf20Sopenharmony_ci	copy_peercred(sk, other);
14058c2ecf20Sopenharmony_ci
14068c2ecf20Sopenharmony_ci	sock->state	= SS_CONNECTED;
14078c2ecf20Sopenharmony_ci	sk->sk_state	= TCP_ESTABLISHED;
14088c2ecf20Sopenharmony_ci	sock_hold(newsk);
14098c2ecf20Sopenharmony_ci
14108c2ecf20Sopenharmony_ci	smp_mb__after_atomic();	/* sock_hold() does an atomic_inc() */
14118c2ecf20Sopenharmony_ci	unix_peer(sk)	= newsk;
14128c2ecf20Sopenharmony_ci
14138c2ecf20Sopenharmony_ci	unix_state_unlock(sk);
14148c2ecf20Sopenharmony_ci
14158c2ecf20Sopenharmony_ci	/* take ten and and send info to listening sock */
14168c2ecf20Sopenharmony_ci	spin_lock(&other->sk_receive_queue.lock);
14178c2ecf20Sopenharmony_ci	__skb_queue_tail(&other->sk_receive_queue, skb);
14188c2ecf20Sopenharmony_ci	spin_unlock(&other->sk_receive_queue.lock);
14198c2ecf20Sopenharmony_ci	unix_state_unlock(other);
14208c2ecf20Sopenharmony_ci	other->sk_data_ready(other);
14218c2ecf20Sopenharmony_ci	sock_put(other);
14228c2ecf20Sopenharmony_ci	return 0;
14238c2ecf20Sopenharmony_ci
14248c2ecf20Sopenharmony_ciout_unlock:
14258c2ecf20Sopenharmony_ci	if (other)
14268c2ecf20Sopenharmony_ci		unix_state_unlock(other);
14278c2ecf20Sopenharmony_ci
14288c2ecf20Sopenharmony_ciout:
14298c2ecf20Sopenharmony_ci	kfree_skb(skb);
14308c2ecf20Sopenharmony_ci	if (newsk)
14318c2ecf20Sopenharmony_ci		unix_release_sock(newsk, 0);
14328c2ecf20Sopenharmony_ci	if (other)
14338c2ecf20Sopenharmony_ci		sock_put(other);
14348c2ecf20Sopenharmony_ci	return err;
14358c2ecf20Sopenharmony_ci}
14368c2ecf20Sopenharmony_ci
14378c2ecf20Sopenharmony_cistatic int unix_socketpair(struct socket *socka, struct socket *sockb)
14388c2ecf20Sopenharmony_ci{
14398c2ecf20Sopenharmony_ci	struct sock *ska = socka->sk, *skb = sockb->sk;
14408c2ecf20Sopenharmony_ci
14418c2ecf20Sopenharmony_ci	/* Join our sockets back to back */
14428c2ecf20Sopenharmony_ci	sock_hold(ska);
14438c2ecf20Sopenharmony_ci	sock_hold(skb);
14448c2ecf20Sopenharmony_ci	unix_peer(ska) = skb;
14458c2ecf20Sopenharmony_ci	unix_peer(skb) = ska;
14468c2ecf20Sopenharmony_ci	init_peercred(ska);
14478c2ecf20Sopenharmony_ci	init_peercred(skb);
14488c2ecf20Sopenharmony_ci
14498c2ecf20Sopenharmony_ci	if (ska->sk_type != SOCK_DGRAM) {
14508c2ecf20Sopenharmony_ci		ska->sk_state = TCP_ESTABLISHED;
14518c2ecf20Sopenharmony_ci		skb->sk_state = TCP_ESTABLISHED;
14528c2ecf20Sopenharmony_ci		socka->state  = SS_CONNECTED;
14538c2ecf20Sopenharmony_ci		sockb->state  = SS_CONNECTED;
14548c2ecf20Sopenharmony_ci	}
14558c2ecf20Sopenharmony_ci	return 0;
14568c2ecf20Sopenharmony_ci}
14578c2ecf20Sopenharmony_ci
14588c2ecf20Sopenharmony_cistatic void unix_sock_inherit_flags(const struct socket *old,
14598c2ecf20Sopenharmony_ci				    struct socket *new)
14608c2ecf20Sopenharmony_ci{
14618c2ecf20Sopenharmony_ci	if (test_bit(SOCK_PASSCRED, &old->flags))
14628c2ecf20Sopenharmony_ci		set_bit(SOCK_PASSCRED, &new->flags);
14638c2ecf20Sopenharmony_ci	if (test_bit(SOCK_PASSSEC, &old->flags))
14648c2ecf20Sopenharmony_ci		set_bit(SOCK_PASSSEC, &new->flags);
14658c2ecf20Sopenharmony_ci}
14668c2ecf20Sopenharmony_ci
14678c2ecf20Sopenharmony_cistatic int unix_accept(struct socket *sock, struct socket *newsock, int flags,
14688c2ecf20Sopenharmony_ci		       bool kern)
14698c2ecf20Sopenharmony_ci{
14708c2ecf20Sopenharmony_ci	struct sock *sk = sock->sk;
14718c2ecf20Sopenharmony_ci	struct sock *tsk;
14728c2ecf20Sopenharmony_ci	struct sk_buff *skb;
14738c2ecf20Sopenharmony_ci	int err;
14748c2ecf20Sopenharmony_ci
14758c2ecf20Sopenharmony_ci	err = -EOPNOTSUPP;
14768c2ecf20Sopenharmony_ci	if (sock->type != SOCK_STREAM && sock->type != SOCK_SEQPACKET)
14778c2ecf20Sopenharmony_ci		goto out;
14788c2ecf20Sopenharmony_ci
14798c2ecf20Sopenharmony_ci	err = -EINVAL;
14808c2ecf20Sopenharmony_ci	if (sk->sk_state != TCP_LISTEN)
14818c2ecf20Sopenharmony_ci		goto out;
14828c2ecf20Sopenharmony_ci
14838c2ecf20Sopenharmony_ci	/* If socket state is TCP_LISTEN it cannot change (for now...),
14848c2ecf20Sopenharmony_ci	 * so that no locks are necessary.
14858c2ecf20Sopenharmony_ci	 */
14868c2ecf20Sopenharmony_ci
14878c2ecf20Sopenharmony_ci	skb = skb_recv_datagram(sk, 0, flags&O_NONBLOCK, &err);
14888c2ecf20Sopenharmony_ci	if (!skb) {
14898c2ecf20Sopenharmony_ci		/* This means receive shutdown. */
14908c2ecf20Sopenharmony_ci		if (err == 0)
14918c2ecf20Sopenharmony_ci			err = -EINVAL;
14928c2ecf20Sopenharmony_ci		goto out;
14938c2ecf20Sopenharmony_ci	}
14948c2ecf20Sopenharmony_ci
14958c2ecf20Sopenharmony_ci	tsk = skb->sk;
14968c2ecf20Sopenharmony_ci	skb_free_datagram(sk, skb);
14978c2ecf20Sopenharmony_ci	wake_up_interruptible(&unix_sk(sk)->peer_wait);
14988c2ecf20Sopenharmony_ci
14998c2ecf20Sopenharmony_ci	/* attach accepted sock to socket */
15008c2ecf20Sopenharmony_ci	unix_state_lock(tsk);
15018c2ecf20Sopenharmony_ci	newsock->state = SS_CONNECTED;
15028c2ecf20Sopenharmony_ci	unix_sock_inherit_flags(sock, newsock);
15038c2ecf20Sopenharmony_ci	sock_graft(tsk, newsock);
15048c2ecf20Sopenharmony_ci	unix_state_unlock(tsk);
15058c2ecf20Sopenharmony_ci	return 0;
15068c2ecf20Sopenharmony_ci
15078c2ecf20Sopenharmony_ciout:
15088c2ecf20Sopenharmony_ci	return err;
15098c2ecf20Sopenharmony_ci}
15108c2ecf20Sopenharmony_ci
15118c2ecf20Sopenharmony_ci
15128c2ecf20Sopenharmony_cistatic int unix_getname(struct socket *sock, struct sockaddr *uaddr, int peer)
15138c2ecf20Sopenharmony_ci{
15148c2ecf20Sopenharmony_ci	struct sock *sk = sock->sk;
15158c2ecf20Sopenharmony_ci	struct unix_address *addr;
15168c2ecf20Sopenharmony_ci	DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, uaddr);
15178c2ecf20Sopenharmony_ci	int err = 0;
15188c2ecf20Sopenharmony_ci
15198c2ecf20Sopenharmony_ci	if (peer) {
15208c2ecf20Sopenharmony_ci		sk = unix_peer_get(sk);
15218c2ecf20Sopenharmony_ci
15228c2ecf20Sopenharmony_ci		err = -ENOTCONN;
15238c2ecf20Sopenharmony_ci		if (!sk)
15248c2ecf20Sopenharmony_ci			goto out;
15258c2ecf20Sopenharmony_ci		err = 0;
15268c2ecf20Sopenharmony_ci	} else {
15278c2ecf20Sopenharmony_ci		sock_hold(sk);
15288c2ecf20Sopenharmony_ci	}
15298c2ecf20Sopenharmony_ci
15308c2ecf20Sopenharmony_ci	addr = smp_load_acquire(&unix_sk(sk)->addr);
15318c2ecf20Sopenharmony_ci	if (!addr) {
15328c2ecf20Sopenharmony_ci		sunaddr->sun_family = AF_UNIX;
15338c2ecf20Sopenharmony_ci		sunaddr->sun_path[0] = 0;
15348c2ecf20Sopenharmony_ci		err = sizeof(short);
15358c2ecf20Sopenharmony_ci	} else {
15368c2ecf20Sopenharmony_ci		err = addr->len;
15378c2ecf20Sopenharmony_ci		memcpy(sunaddr, addr->name, addr->len);
15388c2ecf20Sopenharmony_ci	}
15398c2ecf20Sopenharmony_ci	sock_put(sk);
15408c2ecf20Sopenharmony_ciout:
15418c2ecf20Sopenharmony_ci	return err;
15428c2ecf20Sopenharmony_ci}
15438c2ecf20Sopenharmony_ci
15448c2ecf20Sopenharmony_cistatic void unix_peek_fds(struct scm_cookie *scm, struct sk_buff *skb)
15458c2ecf20Sopenharmony_ci{
15468c2ecf20Sopenharmony_ci	scm->fp = scm_fp_dup(UNIXCB(skb).fp);
15478c2ecf20Sopenharmony_ci
15488c2ecf20Sopenharmony_ci	/*
15498c2ecf20Sopenharmony_ci	 * Garbage collection of unix sockets starts by selecting a set of
15508c2ecf20Sopenharmony_ci	 * candidate sockets which have reference only from being in flight
15518c2ecf20Sopenharmony_ci	 * (total_refs == inflight_refs).  This condition is checked once during
15528c2ecf20Sopenharmony_ci	 * the candidate collection phase, and candidates are marked as such, so
15538c2ecf20Sopenharmony_ci	 * that non-candidates can later be ignored.  While inflight_refs is
15548c2ecf20Sopenharmony_ci	 * protected by unix_gc_lock, total_refs (file count) is not, hence this
15558c2ecf20Sopenharmony_ci	 * is an instantaneous decision.
15568c2ecf20Sopenharmony_ci	 *
15578c2ecf20Sopenharmony_ci	 * Once a candidate, however, the socket must not be reinstalled into a
15588c2ecf20Sopenharmony_ci	 * file descriptor while the garbage collection is in progress.
15598c2ecf20Sopenharmony_ci	 *
15608c2ecf20Sopenharmony_ci	 * If the above conditions are met, then the directed graph of
15618c2ecf20Sopenharmony_ci	 * candidates (*) does not change while unix_gc_lock is held.
15628c2ecf20Sopenharmony_ci	 *
15638c2ecf20Sopenharmony_ci	 * Any operations that changes the file count through file descriptors
15648c2ecf20Sopenharmony_ci	 * (dup, close, sendmsg) does not change the graph since candidates are
15658c2ecf20Sopenharmony_ci	 * not installed in fds.
15668c2ecf20Sopenharmony_ci	 *
15678c2ecf20Sopenharmony_ci	 * Dequeing a candidate via recvmsg would install it into an fd, but
15688c2ecf20Sopenharmony_ci	 * that takes unix_gc_lock to decrement the inflight count, so it's
15698c2ecf20Sopenharmony_ci	 * serialized with garbage collection.
15708c2ecf20Sopenharmony_ci	 *
15718c2ecf20Sopenharmony_ci	 * MSG_PEEK is special in that it does not change the inflight count,
15728c2ecf20Sopenharmony_ci	 * yet does install the socket into an fd.  The following lock/unlock
15738c2ecf20Sopenharmony_ci	 * pair is to ensure serialization with garbage collection.  It must be
15748c2ecf20Sopenharmony_ci	 * done between incrementing the file count and installing the file into
15758c2ecf20Sopenharmony_ci	 * an fd.
15768c2ecf20Sopenharmony_ci	 *
15778c2ecf20Sopenharmony_ci	 * If garbage collection starts after the barrier provided by the
15788c2ecf20Sopenharmony_ci	 * lock/unlock, then it will see the elevated refcount and not mark this
15798c2ecf20Sopenharmony_ci	 * as a candidate.  If a garbage collection is already in progress
15808c2ecf20Sopenharmony_ci	 * before the file count was incremented, then the lock/unlock pair will
15818c2ecf20Sopenharmony_ci	 * ensure that garbage collection is finished before progressing to
15828c2ecf20Sopenharmony_ci	 * installing the fd.
15838c2ecf20Sopenharmony_ci	 *
15848c2ecf20Sopenharmony_ci	 * (*) A -> B where B is on the queue of A or B is on the queue of C
15858c2ecf20Sopenharmony_ci	 * which is on the queue of listening socket A.
15868c2ecf20Sopenharmony_ci	 */
15878c2ecf20Sopenharmony_ci	spin_lock(&unix_gc_lock);
15888c2ecf20Sopenharmony_ci	spin_unlock(&unix_gc_lock);
15898c2ecf20Sopenharmony_ci}
15908c2ecf20Sopenharmony_ci
15918c2ecf20Sopenharmony_cistatic int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool send_fds)
15928c2ecf20Sopenharmony_ci{
15938c2ecf20Sopenharmony_ci	int err = 0;
15948c2ecf20Sopenharmony_ci
15958c2ecf20Sopenharmony_ci	UNIXCB(skb).pid  = get_pid(scm->pid);
15968c2ecf20Sopenharmony_ci	UNIXCB(skb).uid = scm->creds.uid;
15978c2ecf20Sopenharmony_ci	UNIXCB(skb).gid = scm->creds.gid;
15988c2ecf20Sopenharmony_ci	UNIXCB(skb).fp = NULL;
15998c2ecf20Sopenharmony_ci	unix_get_secdata(scm, skb);
16008c2ecf20Sopenharmony_ci	if (scm->fp && send_fds)
16018c2ecf20Sopenharmony_ci		err = unix_attach_fds(scm, skb);
16028c2ecf20Sopenharmony_ci
16038c2ecf20Sopenharmony_ci	skb->destructor = unix_destruct_scm;
16048c2ecf20Sopenharmony_ci	return err;
16058c2ecf20Sopenharmony_ci}
16068c2ecf20Sopenharmony_ci
16078c2ecf20Sopenharmony_cistatic bool unix_passcred_enabled(const struct socket *sock,
16088c2ecf20Sopenharmony_ci				  const struct sock *other)
16098c2ecf20Sopenharmony_ci{
16108c2ecf20Sopenharmony_ci	return test_bit(SOCK_PASSCRED, &sock->flags) ||
16118c2ecf20Sopenharmony_ci	       !other->sk_socket ||
16128c2ecf20Sopenharmony_ci	       test_bit(SOCK_PASSCRED, &other->sk_socket->flags);
16138c2ecf20Sopenharmony_ci}
16148c2ecf20Sopenharmony_ci
16158c2ecf20Sopenharmony_ci/*
16168c2ecf20Sopenharmony_ci * Some apps rely on write() giving SCM_CREDENTIALS
16178c2ecf20Sopenharmony_ci * We include credentials if source or destination socket
16188c2ecf20Sopenharmony_ci * asserted SOCK_PASSCRED.
16198c2ecf20Sopenharmony_ci */
16208c2ecf20Sopenharmony_cistatic void maybe_add_creds(struct sk_buff *skb, const struct socket *sock,
16218c2ecf20Sopenharmony_ci			    const struct sock *other)
16228c2ecf20Sopenharmony_ci{
16238c2ecf20Sopenharmony_ci	if (UNIXCB(skb).pid)
16248c2ecf20Sopenharmony_ci		return;
16258c2ecf20Sopenharmony_ci	if (unix_passcred_enabled(sock, other)) {
16268c2ecf20Sopenharmony_ci		UNIXCB(skb).pid  = get_pid(task_tgid(current));
16278c2ecf20Sopenharmony_ci		current_uid_gid(&UNIXCB(skb).uid, &UNIXCB(skb).gid);
16288c2ecf20Sopenharmony_ci	}
16298c2ecf20Sopenharmony_ci}
16308c2ecf20Sopenharmony_ci
16318c2ecf20Sopenharmony_cistatic int maybe_init_creds(struct scm_cookie *scm,
16328c2ecf20Sopenharmony_ci			    struct socket *socket,
16338c2ecf20Sopenharmony_ci			    const struct sock *other)
16348c2ecf20Sopenharmony_ci{
16358c2ecf20Sopenharmony_ci	int err;
16368c2ecf20Sopenharmony_ci	struct msghdr msg = { .msg_controllen = 0 };
16378c2ecf20Sopenharmony_ci
16388c2ecf20Sopenharmony_ci	err = scm_send(socket, &msg, scm, false);
16398c2ecf20Sopenharmony_ci	if (err)
16408c2ecf20Sopenharmony_ci		return err;
16418c2ecf20Sopenharmony_ci
16428c2ecf20Sopenharmony_ci	if (unix_passcred_enabled(socket, other)) {
16438c2ecf20Sopenharmony_ci		scm->pid = get_pid(task_tgid(current));
16448c2ecf20Sopenharmony_ci		current_uid_gid(&scm->creds.uid, &scm->creds.gid);
16458c2ecf20Sopenharmony_ci	}
16468c2ecf20Sopenharmony_ci	return err;
16478c2ecf20Sopenharmony_ci}
16488c2ecf20Sopenharmony_ci
16498c2ecf20Sopenharmony_cistatic bool unix_skb_scm_eq(struct sk_buff *skb,
16508c2ecf20Sopenharmony_ci			    struct scm_cookie *scm)
16518c2ecf20Sopenharmony_ci{
16528c2ecf20Sopenharmony_ci	const struct unix_skb_parms *u = &UNIXCB(skb);
16538c2ecf20Sopenharmony_ci
16548c2ecf20Sopenharmony_ci	return u->pid == scm->pid &&
16558c2ecf20Sopenharmony_ci	       uid_eq(u->uid, scm->creds.uid) &&
16568c2ecf20Sopenharmony_ci	       gid_eq(u->gid, scm->creds.gid) &&
16578c2ecf20Sopenharmony_ci	       unix_secdata_eq(scm, skb);
16588c2ecf20Sopenharmony_ci}
16598c2ecf20Sopenharmony_ci
16608c2ecf20Sopenharmony_cistatic void scm_stat_add(struct sock *sk, struct sk_buff *skb)
16618c2ecf20Sopenharmony_ci{
16628c2ecf20Sopenharmony_ci	struct scm_fp_list *fp = UNIXCB(skb).fp;
16638c2ecf20Sopenharmony_ci	struct unix_sock *u = unix_sk(sk);
16648c2ecf20Sopenharmony_ci
16658c2ecf20Sopenharmony_ci	if (unlikely(fp && fp->count))
16668c2ecf20Sopenharmony_ci		atomic_add(fp->count, &u->scm_stat.nr_fds);
16678c2ecf20Sopenharmony_ci}
16688c2ecf20Sopenharmony_ci
16698c2ecf20Sopenharmony_cistatic void scm_stat_del(struct sock *sk, struct sk_buff *skb)
16708c2ecf20Sopenharmony_ci{
16718c2ecf20Sopenharmony_ci	struct scm_fp_list *fp = UNIXCB(skb).fp;
16728c2ecf20Sopenharmony_ci	struct unix_sock *u = unix_sk(sk);
16738c2ecf20Sopenharmony_ci
16748c2ecf20Sopenharmony_ci	if (unlikely(fp && fp->count))
16758c2ecf20Sopenharmony_ci		atomic_sub(fp->count, &u->scm_stat.nr_fds);
16768c2ecf20Sopenharmony_ci}
16778c2ecf20Sopenharmony_ci
16788c2ecf20Sopenharmony_ci/*
16798c2ecf20Sopenharmony_ci *	Send AF_UNIX data.
16808c2ecf20Sopenharmony_ci */
16818c2ecf20Sopenharmony_ci
16828c2ecf20Sopenharmony_cistatic int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
16838c2ecf20Sopenharmony_ci			      size_t len)
16848c2ecf20Sopenharmony_ci{
16858c2ecf20Sopenharmony_ci	struct sock *sk = sock->sk;
16868c2ecf20Sopenharmony_ci	struct net *net = sock_net(sk);
16878c2ecf20Sopenharmony_ci	struct unix_sock *u = unix_sk(sk);
16888c2ecf20Sopenharmony_ci	DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, msg->msg_name);
16898c2ecf20Sopenharmony_ci	struct sock *other = NULL;
16908c2ecf20Sopenharmony_ci	int namelen = 0; /* fake GCC */
16918c2ecf20Sopenharmony_ci	int err;
16928c2ecf20Sopenharmony_ci	unsigned int hash;
16938c2ecf20Sopenharmony_ci	struct sk_buff *skb;
16948c2ecf20Sopenharmony_ci	long timeo;
16958c2ecf20Sopenharmony_ci	struct scm_cookie scm;
16968c2ecf20Sopenharmony_ci	int data_len = 0;
16978c2ecf20Sopenharmony_ci	int sk_locked;
16988c2ecf20Sopenharmony_ci
16998c2ecf20Sopenharmony_ci	wait_for_unix_gc();
17008c2ecf20Sopenharmony_ci	err = scm_send(sock, msg, &scm, false);
17018c2ecf20Sopenharmony_ci	if (err < 0)
17028c2ecf20Sopenharmony_ci		return err;
17038c2ecf20Sopenharmony_ci
17048c2ecf20Sopenharmony_ci	err = -EOPNOTSUPP;
17058c2ecf20Sopenharmony_ci	if (msg->msg_flags&MSG_OOB)
17068c2ecf20Sopenharmony_ci		goto out;
17078c2ecf20Sopenharmony_ci
17088c2ecf20Sopenharmony_ci	if (msg->msg_namelen) {
17098c2ecf20Sopenharmony_ci		err = unix_mkname(sunaddr, msg->msg_namelen, &hash);
17108c2ecf20Sopenharmony_ci		if (err < 0)
17118c2ecf20Sopenharmony_ci			goto out;
17128c2ecf20Sopenharmony_ci		namelen = err;
17138c2ecf20Sopenharmony_ci	} else {
17148c2ecf20Sopenharmony_ci		sunaddr = NULL;
17158c2ecf20Sopenharmony_ci		err = -ENOTCONN;
17168c2ecf20Sopenharmony_ci		other = unix_peer_get(sk);
17178c2ecf20Sopenharmony_ci		if (!other)
17188c2ecf20Sopenharmony_ci			goto out;
17198c2ecf20Sopenharmony_ci	}
17208c2ecf20Sopenharmony_ci
17218c2ecf20Sopenharmony_ci	if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr
17228c2ecf20Sopenharmony_ci	    && (err = unix_autobind(sock)) != 0)
17238c2ecf20Sopenharmony_ci		goto out;
17248c2ecf20Sopenharmony_ci
17258c2ecf20Sopenharmony_ci	err = -EMSGSIZE;
17268c2ecf20Sopenharmony_ci	if (len > sk->sk_sndbuf - 32)
17278c2ecf20Sopenharmony_ci		goto out;
17288c2ecf20Sopenharmony_ci
17298c2ecf20Sopenharmony_ci	if (len > SKB_MAX_ALLOC) {
17308c2ecf20Sopenharmony_ci		data_len = min_t(size_t,
17318c2ecf20Sopenharmony_ci				 len - SKB_MAX_ALLOC,
17328c2ecf20Sopenharmony_ci				 MAX_SKB_FRAGS * PAGE_SIZE);
17338c2ecf20Sopenharmony_ci		data_len = PAGE_ALIGN(data_len);
17348c2ecf20Sopenharmony_ci
17358c2ecf20Sopenharmony_ci		BUILD_BUG_ON(SKB_MAX_ALLOC < PAGE_SIZE);
17368c2ecf20Sopenharmony_ci	}
17378c2ecf20Sopenharmony_ci
17388c2ecf20Sopenharmony_ci	skb = sock_alloc_send_pskb(sk, len - data_len, data_len,
17398c2ecf20Sopenharmony_ci				   msg->msg_flags & MSG_DONTWAIT, &err,
17408c2ecf20Sopenharmony_ci				   PAGE_ALLOC_COSTLY_ORDER);
17418c2ecf20Sopenharmony_ci	if (skb == NULL)
17428c2ecf20Sopenharmony_ci		goto out;
17438c2ecf20Sopenharmony_ci
17448c2ecf20Sopenharmony_ci	err = unix_scm_to_skb(&scm, skb, true);
17458c2ecf20Sopenharmony_ci	if (err < 0)
17468c2ecf20Sopenharmony_ci		goto out_free;
17478c2ecf20Sopenharmony_ci
17488c2ecf20Sopenharmony_ci	skb_put(skb, len - data_len);
17498c2ecf20Sopenharmony_ci	skb->data_len = data_len;
17508c2ecf20Sopenharmony_ci	skb->len = len;
17518c2ecf20Sopenharmony_ci	err = skb_copy_datagram_from_iter(skb, 0, &msg->msg_iter, len);
17528c2ecf20Sopenharmony_ci	if (err)
17538c2ecf20Sopenharmony_ci		goto out_free;
17548c2ecf20Sopenharmony_ci
17558c2ecf20Sopenharmony_ci	timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
17568c2ecf20Sopenharmony_ci
17578c2ecf20Sopenharmony_cirestart:
17588c2ecf20Sopenharmony_ci	if (!other) {
17598c2ecf20Sopenharmony_ci		err = -ECONNRESET;
17608c2ecf20Sopenharmony_ci		if (sunaddr == NULL)
17618c2ecf20Sopenharmony_ci			goto out_free;
17628c2ecf20Sopenharmony_ci
17638c2ecf20Sopenharmony_ci		other = unix_find_other(net, sunaddr, namelen, sk->sk_type,
17648c2ecf20Sopenharmony_ci					hash, &err);
17658c2ecf20Sopenharmony_ci		if (other == NULL)
17668c2ecf20Sopenharmony_ci			goto out_free;
17678c2ecf20Sopenharmony_ci	}
17688c2ecf20Sopenharmony_ci
17698c2ecf20Sopenharmony_ci	if (sk_filter(other, skb) < 0) {
17708c2ecf20Sopenharmony_ci		/* Toss the packet but do not return any error to the sender */
17718c2ecf20Sopenharmony_ci		err = len;
17728c2ecf20Sopenharmony_ci		goto out_free;
17738c2ecf20Sopenharmony_ci	}
17748c2ecf20Sopenharmony_ci
17758c2ecf20Sopenharmony_ci	sk_locked = 0;
17768c2ecf20Sopenharmony_ci	unix_state_lock(other);
17778c2ecf20Sopenharmony_cirestart_locked:
17788c2ecf20Sopenharmony_ci	err = -EPERM;
17798c2ecf20Sopenharmony_ci	if (!unix_may_send(sk, other))
17808c2ecf20Sopenharmony_ci		goto out_unlock;
17818c2ecf20Sopenharmony_ci
17828c2ecf20Sopenharmony_ci	if (unlikely(sock_flag(other, SOCK_DEAD))) {
17838c2ecf20Sopenharmony_ci		/*
17848c2ecf20Sopenharmony_ci		 *	Check with 1003.1g - what should
17858c2ecf20Sopenharmony_ci		 *	datagram error
17868c2ecf20Sopenharmony_ci		 */
17878c2ecf20Sopenharmony_ci		unix_state_unlock(other);
17888c2ecf20Sopenharmony_ci		sock_put(other);
17898c2ecf20Sopenharmony_ci
17908c2ecf20Sopenharmony_ci		if (!sk_locked)
17918c2ecf20Sopenharmony_ci			unix_state_lock(sk);
17928c2ecf20Sopenharmony_ci
17938c2ecf20Sopenharmony_ci		err = 0;
17948c2ecf20Sopenharmony_ci		if (unix_peer(sk) == other) {
17958c2ecf20Sopenharmony_ci			unix_peer(sk) = NULL;
17968c2ecf20Sopenharmony_ci			unix_dgram_peer_wake_disconnect_wakeup(sk, other);
17978c2ecf20Sopenharmony_ci
17988c2ecf20Sopenharmony_ci			unix_state_unlock(sk);
17998c2ecf20Sopenharmony_ci
18008c2ecf20Sopenharmony_ci			unix_dgram_disconnected(sk, other);
18018c2ecf20Sopenharmony_ci			sock_put(other);
18028c2ecf20Sopenharmony_ci			err = -ECONNREFUSED;
18038c2ecf20Sopenharmony_ci		} else {
18048c2ecf20Sopenharmony_ci			unix_state_unlock(sk);
18058c2ecf20Sopenharmony_ci		}
18068c2ecf20Sopenharmony_ci
18078c2ecf20Sopenharmony_ci		other = NULL;
18088c2ecf20Sopenharmony_ci		if (err)
18098c2ecf20Sopenharmony_ci			goto out_free;
18108c2ecf20Sopenharmony_ci		goto restart;
18118c2ecf20Sopenharmony_ci	}
18128c2ecf20Sopenharmony_ci
18138c2ecf20Sopenharmony_ci	err = -EPIPE;
18148c2ecf20Sopenharmony_ci	if (other->sk_shutdown & RCV_SHUTDOWN)
18158c2ecf20Sopenharmony_ci		goto out_unlock;
18168c2ecf20Sopenharmony_ci
18178c2ecf20Sopenharmony_ci	if (sk->sk_type != SOCK_SEQPACKET) {
18188c2ecf20Sopenharmony_ci		err = security_unix_may_send(sk->sk_socket, other->sk_socket);
18198c2ecf20Sopenharmony_ci		if (err)
18208c2ecf20Sopenharmony_ci			goto out_unlock;
18218c2ecf20Sopenharmony_ci	}
18228c2ecf20Sopenharmony_ci
18238c2ecf20Sopenharmony_ci	/* other == sk && unix_peer(other) != sk if
18248c2ecf20Sopenharmony_ci	 * - unix_peer(sk) == NULL, destination address bound to sk
18258c2ecf20Sopenharmony_ci	 * - unix_peer(sk) == sk by time of get but disconnected before lock
18268c2ecf20Sopenharmony_ci	 */
18278c2ecf20Sopenharmony_ci	if (other != sk &&
18288c2ecf20Sopenharmony_ci	    unlikely(unix_peer(other) != sk &&
18298c2ecf20Sopenharmony_ci	    unix_recvq_full_lockless(other))) {
18308c2ecf20Sopenharmony_ci		if (timeo) {
18318c2ecf20Sopenharmony_ci			timeo = unix_wait_for_peer(other, timeo);
18328c2ecf20Sopenharmony_ci
18338c2ecf20Sopenharmony_ci			err = sock_intr_errno(timeo);
18348c2ecf20Sopenharmony_ci			if (signal_pending(current))
18358c2ecf20Sopenharmony_ci				goto out_free;
18368c2ecf20Sopenharmony_ci
18378c2ecf20Sopenharmony_ci			goto restart;
18388c2ecf20Sopenharmony_ci		}
18398c2ecf20Sopenharmony_ci
18408c2ecf20Sopenharmony_ci		if (!sk_locked) {
18418c2ecf20Sopenharmony_ci			unix_state_unlock(other);
18428c2ecf20Sopenharmony_ci			unix_state_double_lock(sk, other);
18438c2ecf20Sopenharmony_ci		}
18448c2ecf20Sopenharmony_ci
18458c2ecf20Sopenharmony_ci		if (unix_peer(sk) != other ||
18468c2ecf20Sopenharmony_ci		    unix_dgram_peer_wake_me(sk, other)) {
18478c2ecf20Sopenharmony_ci			err = -EAGAIN;
18488c2ecf20Sopenharmony_ci			sk_locked = 1;
18498c2ecf20Sopenharmony_ci			goto out_unlock;
18508c2ecf20Sopenharmony_ci		}
18518c2ecf20Sopenharmony_ci
18528c2ecf20Sopenharmony_ci		if (!sk_locked) {
18538c2ecf20Sopenharmony_ci			sk_locked = 1;
18548c2ecf20Sopenharmony_ci			goto restart_locked;
18558c2ecf20Sopenharmony_ci		}
18568c2ecf20Sopenharmony_ci	}
18578c2ecf20Sopenharmony_ci
18588c2ecf20Sopenharmony_ci	if (unlikely(sk_locked))
18598c2ecf20Sopenharmony_ci		unix_state_unlock(sk);
18608c2ecf20Sopenharmony_ci
18618c2ecf20Sopenharmony_ci	if (sock_flag(other, SOCK_RCVTSTAMP))
18628c2ecf20Sopenharmony_ci		__net_timestamp(skb);
18638c2ecf20Sopenharmony_ci	maybe_add_creds(skb, sock, other);
18648c2ecf20Sopenharmony_ci	scm_stat_add(other, skb);
18658c2ecf20Sopenharmony_ci	skb_queue_tail(&other->sk_receive_queue, skb);
18668c2ecf20Sopenharmony_ci	unix_state_unlock(other);
18678c2ecf20Sopenharmony_ci	other->sk_data_ready(other);
18688c2ecf20Sopenharmony_ci	sock_put(other);
18698c2ecf20Sopenharmony_ci	scm_destroy(&scm);
18708c2ecf20Sopenharmony_ci	return len;
18718c2ecf20Sopenharmony_ci
18728c2ecf20Sopenharmony_ciout_unlock:
18738c2ecf20Sopenharmony_ci	if (sk_locked)
18748c2ecf20Sopenharmony_ci		unix_state_unlock(sk);
18758c2ecf20Sopenharmony_ci	unix_state_unlock(other);
18768c2ecf20Sopenharmony_ciout_free:
18778c2ecf20Sopenharmony_ci	kfree_skb(skb);
18788c2ecf20Sopenharmony_ciout:
18798c2ecf20Sopenharmony_ci	if (other)
18808c2ecf20Sopenharmony_ci		sock_put(other);
18818c2ecf20Sopenharmony_ci	scm_destroy(&scm);
18828c2ecf20Sopenharmony_ci	return err;
18838c2ecf20Sopenharmony_ci}
18848c2ecf20Sopenharmony_ci
18858c2ecf20Sopenharmony_ci/* We use paged skbs for stream sockets, and limit occupancy to 32768
18868c2ecf20Sopenharmony_ci * bytes, and a minimum of a full page.
18878c2ecf20Sopenharmony_ci */
18888c2ecf20Sopenharmony_ci#define UNIX_SKB_FRAGS_SZ (PAGE_SIZE << get_order(32768))
18898c2ecf20Sopenharmony_ci
18908c2ecf20Sopenharmony_cistatic int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
18918c2ecf20Sopenharmony_ci			       size_t len)
18928c2ecf20Sopenharmony_ci{
18938c2ecf20Sopenharmony_ci	struct sock *sk = sock->sk;
18948c2ecf20Sopenharmony_ci	struct sock *other = NULL;
18958c2ecf20Sopenharmony_ci	int err, size;
18968c2ecf20Sopenharmony_ci	struct sk_buff *skb;
18978c2ecf20Sopenharmony_ci	int sent = 0;
18988c2ecf20Sopenharmony_ci	struct scm_cookie scm;
18998c2ecf20Sopenharmony_ci	bool fds_sent = false;
19008c2ecf20Sopenharmony_ci	int data_len;
19018c2ecf20Sopenharmony_ci
19028c2ecf20Sopenharmony_ci	wait_for_unix_gc();
19038c2ecf20Sopenharmony_ci	err = scm_send(sock, msg, &scm, false);
19048c2ecf20Sopenharmony_ci	if (err < 0)
19058c2ecf20Sopenharmony_ci		return err;
19068c2ecf20Sopenharmony_ci
19078c2ecf20Sopenharmony_ci	err = -EOPNOTSUPP;
19088c2ecf20Sopenharmony_ci	if (msg->msg_flags&MSG_OOB)
19098c2ecf20Sopenharmony_ci		goto out_err;
19108c2ecf20Sopenharmony_ci
19118c2ecf20Sopenharmony_ci	if (msg->msg_namelen) {
19128c2ecf20Sopenharmony_ci		err = sk->sk_state == TCP_ESTABLISHED ? -EISCONN : -EOPNOTSUPP;
19138c2ecf20Sopenharmony_ci		goto out_err;
19148c2ecf20Sopenharmony_ci	} else {
19158c2ecf20Sopenharmony_ci		err = -ENOTCONN;
19168c2ecf20Sopenharmony_ci		other = unix_peer(sk);
19178c2ecf20Sopenharmony_ci		if (!other)
19188c2ecf20Sopenharmony_ci			goto out_err;
19198c2ecf20Sopenharmony_ci	}
19208c2ecf20Sopenharmony_ci
19218c2ecf20Sopenharmony_ci	if (READ_ONCE(sk->sk_shutdown) & SEND_SHUTDOWN)
19228c2ecf20Sopenharmony_ci		goto pipe_err;
19238c2ecf20Sopenharmony_ci
19248c2ecf20Sopenharmony_ci	while (sent < len) {
19258c2ecf20Sopenharmony_ci		size = len - sent;
19268c2ecf20Sopenharmony_ci
19278c2ecf20Sopenharmony_ci		/* Keep two messages in the pipe so it schedules better */
19288c2ecf20Sopenharmony_ci		size = min_t(int, size, (sk->sk_sndbuf >> 1) - 64);
19298c2ecf20Sopenharmony_ci
19308c2ecf20Sopenharmony_ci		/* allow fallback to order-0 allocations */
19318c2ecf20Sopenharmony_ci		size = min_t(int, size, SKB_MAX_HEAD(0) + UNIX_SKB_FRAGS_SZ);
19328c2ecf20Sopenharmony_ci
19338c2ecf20Sopenharmony_ci		data_len = max_t(int, 0, size - SKB_MAX_HEAD(0));
19348c2ecf20Sopenharmony_ci
19358c2ecf20Sopenharmony_ci		data_len = min_t(size_t, size, PAGE_ALIGN(data_len));
19368c2ecf20Sopenharmony_ci
19378c2ecf20Sopenharmony_ci		skb = sock_alloc_send_pskb(sk, size - data_len, data_len,
19388c2ecf20Sopenharmony_ci					   msg->msg_flags & MSG_DONTWAIT, &err,
19398c2ecf20Sopenharmony_ci					   get_order(UNIX_SKB_FRAGS_SZ));
19408c2ecf20Sopenharmony_ci		if (!skb)
19418c2ecf20Sopenharmony_ci			goto out_err;
19428c2ecf20Sopenharmony_ci
19438c2ecf20Sopenharmony_ci		/* Only send the fds in the first buffer */
19448c2ecf20Sopenharmony_ci		err = unix_scm_to_skb(&scm, skb, !fds_sent);
19458c2ecf20Sopenharmony_ci		if (err < 0) {
19468c2ecf20Sopenharmony_ci			kfree_skb(skb);
19478c2ecf20Sopenharmony_ci			goto out_err;
19488c2ecf20Sopenharmony_ci		}
19498c2ecf20Sopenharmony_ci		fds_sent = true;
19508c2ecf20Sopenharmony_ci
19518c2ecf20Sopenharmony_ci		skb_put(skb, size - data_len);
19528c2ecf20Sopenharmony_ci		skb->data_len = data_len;
19538c2ecf20Sopenharmony_ci		skb->len = size;
19548c2ecf20Sopenharmony_ci		err = skb_copy_datagram_from_iter(skb, 0, &msg->msg_iter, size);
19558c2ecf20Sopenharmony_ci		if (err) {
19568c2ecf20Sopenharmony_ci			kfree_skb(skb);
19578c2ecf20Sopenharmony_ci			goto out_err;
19588c2ecf20Sopenharmony_ci		}
19598c2ecf20Sopenharmony_ci
19608c2ecf20Sopenharmony_ci		unix_state_lock(other);
19618c2ecf20Sopenharmony_ci
19628c2ecf20Sopenharmony_ci		if (sock_flag(other, SOCK_DEAD) ||
19638c2ecf20Sopenharmony_ci		    (other->sk_shutdown & RCV_SHUTDOWN))
19648c2ecf20Sopenharmony_ci			goto pipe_err_free;
19658c2ecf20Sopenharmony_ci
19668c2ecf20Sopenharmony_ci		maybe_add_creds(skb, sock, other);
19678c2ecf20Sopenharmony_ci		scm_stat_add(other, skb);
19688c2ecf20Sopenharmony_ci		skb_queue_tail(&other->sk_receive_queue, skb);
19698c2ecf20Sopenharmony_ci		unix_state_unlock(other);
19708c2ecf20Sopenharmony_ci		other->sk_data_ready(other);
19718c2ecf20Sopenharmony_ci		sent += size;
19728c2ecf20Sopenharmony_ci	}
19738c2ecf20Sopenharmony_ci
19748c2ecf20Sopenharmony_ci	scm_destroy(&scm);
19758c2ecf20Sopenharmony_ci
19768c2ecf20Sopenharmony_ci	return sent;
19778c2ecf20Sopenharmony_ci
19788c2ecf20Sopenharmony_cipipe_err_free:
19798c2ecf20Sopenharmony_ci	unix_state_unlock(other);
19808c2ecf20Sopenharmony_ci	kfree_skb(skb);
19818c2ecf20Sopenharmony_cipipe_err:
19828c2ecf20Sopenharmony_ci	if (sent == 0 && !(msg->msg_flags&MSG_NOSIGNAL))
19838c2ecf20Sopenharmony_ci		send_sig(SIGPIPE, current, 0);
19848c2ecf20Sopenharmony_ci	err = -EPIPE;
19858c2ecf20Sopenharmony_ciout_err:
19868c2ecf20Sopenharmony_ci	scm_destroy(&scm);
19878c2ecf20Sopenharmony_ci	return sent ? : err;
19888c2ecf20Sopenharmony_ci}
19898c2ecf20Sopenharmony_ci
19908c2ecf20Sopenharmony_cistatic ssize_t unix_stream_sendpage(struct socket *socket, struct page *page,
19918c2ecf20Sopenharmony_ci				    int offset, size_t size, int flags)
19928c2ecf20Sopenharmony_ci{
19938c2ecf20Sopenharmony_ci	int err;
19948c2ecf20Sopenharmony_ci	bool send_sigpipe = false;
19958c2ecf20Sopenharmony_ci	bool init_scm = true;
19968c2ecf20Sopenharmony_ci	struct scm_cookie scm;
19978c2ecf20Sopenharmony_ci	struct sock *other, *sk = socket->sk;
19988c2ecf20Sopenharmony_ci	struct sk_buff *skb, *newskb = NULL, *tail = NULL;
19998c2ecf20Sopenharmony_ci
20008c2ecf20Sopenharmony_ci	if (flags & MSG_OOB)
20018c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
20028c2ecf20Sopenharmony_ci
20038c2ecf20Sopenharmony_ci	other = unix_peer(sk);
20048c2ecf20Sopenharmony_ci	if (!other || sk->sk_state != TCP_ESTABLISHED)
20058c2ecf20Sopenharmony_ci		return -ENOTCONN;
20068c2ecf20Sopenharmony_ci
20078c2ecf20Sopenharmony_ci	if (false) {
20088c2ecf20Sopenharmony_cialloc_skb:
20098c2ecf20Sopenharmony_ci		spin_unlock(&other->sk_receive_queue.lock);
20108c2ecf20Sopenharmony_ci		unix_state_unlock(other);
20118c2ecf20Sopenharmony_ci		mutex_unlock(&unix_sk(other)->iolock);
20128c2ecf20Sopenharmony_ci		newskb = sock_alloc_send_pskb(sk, 0, 0, flags & MSG_DONTWAIT,
20138c2ecf20Sopenharmony_ci					      &err, 0);
20148c2ecf20Sopenharmony_ci		if (!newskb)
20158c2ecf20Sopenharmony_ci			goto err;
20168c2ecf20Sopenharmony_ci	}
20178c2ecf20Sopenharmony_ci
20188c2ecf20Sopenharmony_ci	/* we must acquire iolock as we modify already present
20198c2ecf20Sopenharmony_ci	 * skbs in the sk_receive_queue and mess with skb->len
20208c2ecf20Sopenharmony_ci	 */
20218c2ecf20Sopenharmony_ci	err = mutex_lock_interruptible(&unix_sk(other)->iolock);
20228c2ecf20Sopenharmony_ci	if (err) {
20238c2ecf20Sopenharmony_ci		err = flags & MSG_DONTWAIT ? -EAGAIN : -ERESTARTSYS;
20248c2ecf20Sopenharmony_ci		goto err;
20258c2ecf20Sopenharmony_ci	}
20268c2ecf20Sopenharmony_ci
20278c2ecf20Sopenharmony_ci	if (sk->sk_shutdown & SEND_SHUTDOWN) {
20288c2ecf20Sopenharmony_ci		err = -EPIPE;
20298c2ecf20Sopenharmony_ci		send_sigpipe = true;
20308c2ecf20Sopenharmony_ci		goto err_unlock;
20318c2ecf20Sopenharmony_ci	}
20328c2ecf20Sopenharmony_ci
20338c2ecf20Sopenharmony_ci	unix_state_lock(other);
20348c2ecf20Sopenharmony_ci
20358c2ecf20Sopenharmony_ci	if (sock_flag(other, SOCK_DEAD) ||
20368c2ecf20Sopenharmony_ci	    other->sk_shutdown & RCV_SHUTDOWN) {
20378c2ecf20Sopenharmony_ci		err = -EPIPE;
20388c2ecf20Sopenharmony_ci		send_sigpipe = true;
20398c2ecf20Sopenharmony_ci		goto err_state_unlock;
20408c2ecf20Sopenharmony_ci	}
20418c2ecf20Sopenharmony_ci
20428c2ecf20Sopenharmony_ci	if (init_scm) {
20438c2ecf20Sopenharmony_ci		err = maybe_init_creds(&scm, socket, other);
20448c2ecf20Sopenharmony_ci		if (err)
20458c2ecf20Sopenharmony_ci			goto err_state_unlock;
20468c2ecf20Sopenharmony_ci		init_scm = false;
20478c2ecf20Sopenharmony_ci	}
20488c2ecf20Sopenharmony_ci
20498c2ecf20Sopenharmony_ci	spin_lock(&other->sk_receive_queue.lock);
20508c2ecf20Sopenharmony_ci	skb = skb_peek_tail(&other->sk_receive_queue);
20518c2ecf20Sopenharmony_ci	if (tail && tail == skb) {
20528c2ecf20Sopenharmony_ci		skb = newskb;
20538c2ecf20Sopenharmony_ci	} else if (!skb || !unix_skb_scm_eq(skb, &scm)) {
20548c2ecf20Sopenharmony_ci		if (newskb) {
20558c2ecf20Sopenharmony_ci			skb = newskb;
20568c2ecf20Sopenharmony_ci		} else {
20578c2ecf20Sopenharmony_ci			tail = skb;
20588c2ecf20Sopenharmony_ci			goto alloc_skb;
20598c2ecf20Sopenharmony_ci		}
20608c2ecf20Sopenharmony_ci	} else if (newskb) {
20618c2ecf20Sopenharmony_ci		/* this is fast path, we don't necessarily need to
20628c2ecf20Sopenharmony_ci		 * call to kfree_skb even though with newskb == NULL
20638c2ecf20Sopenharmony_ci		 * this - does no harm
20648c2ecf20Sopenharmony_ci		 */
20658c2ecf20Sopenharmony_ci		consume_skb(newskb);
20668c2ecf20Sopenharmony_ci		newskb = NULL;
20678c2ecf20Sopenharmony_ci	}
20688c2ecf20Sopenharmony_ci
20698c2ecf20Sopenharmony_ci	if (skb_append_pagefrags(skb, page, offset, size)) {
20708c2ecf20Sopenharmony_ci		tail = skb;
20718c2ecf20Sopenharmony_ci		goto alloc_skb;
20728c2ecf20Sopenharmony_ci	}
20738c2ecf20Sopenharmony_ci
20748c2ecf20Sopenharmony_ci	skb->len += size;
20758c2ecf20Sopenharmony_ci	skb->data_len += size;
20768c2ecf20Sopenharmony_ci	skb->truesize += size;
20778c2ecf20Sopenharmony_ci	refcount_add(size, &sk->sk_wmem_alloc);
20788c2ecf20Sopenharmony_ci
20798c2ecf20Sopenharmony_ci	if (newskb) {
20808c2ecf20Sopenharmony_ci		unix_scm_to_skb(&scm, skb, false);
20818c2ecf20Sopenharmony_ci		__skb_queue_tail(&other->sk_receive_queue, newskb);
20828c2ecf20Sopenharmony_ci	}
20838c2ecf20Sopenharmony_ci
20848c2ecf20Sopenharmony_ci	spin_unlock(&other->sk_receive_queue.lock);
20858c2ecf20Sopenharmony_ci	unix_state_unlock(other);
20868c2ecf20Sopenharmony_ci	mutex_unlock(&unix_sk(other)->iolock);
20878c2ecf20Sopenharmony_ci
20888c2ecf20Sopenharmony_ci	other->sk_data_ready(other);
20898c2ecf20Sopenharmony_ci	scm_destroy(&scm);
20908c2ecf20Sopenharmony_ci	return size;
20918c2ecf20Sopenharmony_ci
20928c2ecf20Sopenharmony_cierr_state_unlock:
20938c2ecf20Sopenharmony_ci	unix_state_unlock(other);
20948c2ecf20Sopenharmony_cierr_unlock:
20958c2ecf20Sopenharmony_ci	mutex_unlock(&unix_sk(other)->iolock);
20968c2ecf20Sopenharmony_cierr:
20978c2ecf20Sopenharmony_ci	kfree_skb(newskb);
20988c2ecf20Sopenharmony_ci	if (send_sigpipe && !(flags & MSG_NOSIGNAL))
20998c2ecf20Sopenharmony_ci		send_sig(SIGPIPE, current, 0);
21008c2ecf20Sopenharmony_ci	if (!init_scm)
21018c2ecf20Sopenharmony_ci		scm_destroy(&scm);
21028c2ecf20Sopenharmony_ci	return err;
21038c2ecf20Sopenharmony_ci}
21048c2ecf20Sopenharmony_ci
21058c2ecf20Sopenharmony_cistatic int unix_seqpacket_sendmsg(struct socket *sock, struct msghdr *msg,
21068c2ecf20Sopenharmony_ci				  size_t len)
21078c2ecf20Sopenharmony_ci{
21088c2ecf20Sopenharmony_ci	int err;
21098c2ecf20Sopenharmony_ci	struct sock *sk = sock->sk;
21108c2ecf20Sopenharmony_ci
21118c2ecf20Sopenharmony_ci	err = sock_error(sk);
21128c2ecf20Sopenharmony_ci	if (err)
21138c2ecf20Sopenharmony_ci		return err;
21148c2ecf20Sopenharmony_ci
21158c2ecf20Sopenharmony_ci	if (sk->sk_state != TCP_ESTABLISHED)
21168c2ecf20Sopenharmony_ci		return -ENOTCONN;
21178c2ecf20Sopenharmony_ci
21188c2ecf20Sopenharmony_ci	if (msg->msg_namelen)
21198c2ecf20Sopenharmony_ci		msg->msg_namelen = 0;
21208c2ecf20Sopenharmony_ci
21218c2ecf20Sopenharmony_ci	return unix_dgram_sendmsg(sock, msg, len);
21228c2ecf20Sopenharmony_ci}
21238c2ecf20Sopenharmony_ci
21248c2ecf20Sopenharmony_cistatic int unix_seqpacket_recvmsg(struct socket *sock, struct msghdr *msg,
21258c2ecf20Sopenharmony_ci				  size_t size, int flags)
21268c2ecf20Sopenharmony_ci{
21278c2ecf20Sopenharmony_ci	struct sock *sk = sock->sk;
21288c2ecf20Sopenharmony_ci
21298c2ecf20Sopenharmony_ci	if (sk->sk_state != TCP_ESTABLISHED)
21308c2ecf20Sopenharmony_ci		return -ENOTCONN;
21318c2ecf20Sopenharmony_ci
21328c2ecf20Sopenharmony_ci	return unix_dgram_recvmsg(sock, msg, size, flags);
21338c2ecf20Sopenharmony_ci}
21348c2ecf20Sopenharmony_ci
21358c2ecf20Sopenharmony_cistatic void unix_copy_addr(struct msghdr *msg, struct sock *sk)
21368c2ecf20Sopenharmony_ci{
21378c2ecf20Sopenharmony_ci	struct unix_address *addr = smp_load_acquire(&unix_sk(sk)->addr);
21388c2ecf20Sopenharmony_ci
21398c2ecf20Sopenharmony_ci	if (addr) {
21408c2ecf20Sopenharmony_ci		msg->msg_namelen = addr->len;
21418c2ecf20Sopenharmony_ci		memcpy(msg->msg_name, addr->name, addr->len);
21428c2ecf20Sopenharmony_ci	}
21438c2ecf20Sopenharmony_ci}
21448c2ecf20Sopenharmony_ci
21458c2ecf20Sopenharmony_cistatic int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg,
21468c2ecf20Sopenharmony_ci			      size_t size, int flags)
21478c2ecf20Sopenharmony_ci{
21488c2ecf20Sopenharmony_ci	struct scm_cookie scm;
21498c2ecf20Sopenharmony_ci	struct sock *sk = sock->sk;
21508c2ecf20Sopenharmony_ci	struct unix_sock *u = unix_sk(sk);
21518c2ecf20Sopenharmony_ci	struct sk_buff *skb, *last;
21528c2ecf20Sopenharmony_ci	long timeo;
21538c2ecf20Sopenharmony_ci	int skip;
21548c2ecf20Sopenharmony_ci	int err;
21558c2ecf20Sopenharmony_ci
21568c2ecf20Sopenharmony_ci	err = -EOPNOTSUPP;
21578c2ecf20Sopenharmony_ci	if (flags&MSG_OOB)
21588c2ecf20Sopenharmony_ci		goto out;
21598c2ecf20Sopenharmony_ci
21608c2ecf20Sopenharmony_ci	timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
21618c2ecf20Sopenharmony_ci
21628c2ecf20Sopenharmony_ci	do {
21638c2ecf20Sopenharmony_ci		mutex_lock(&u->iolock);
21648c2ecf20Sopenharmony_ci
21658c2ecf20Sopenharmony_ci		skip = sk_peek_offset(sk, flags);
21668c2ecf20Sopenharmony_ci		skb = __skb_try_recv_datagram(sk, &sk->sk_receive_queue, flags,
21678c2ecf20Sopenharmony_ci					      &skip, &err, &last);
21688c2ecf20Sopenharmony_ci		if (skb) {
21698c2ecf20Sopenharmony_ci			if (!(flags & MSG_PEEK))
21708c2ecf20Sopenharmony_ci				scm_stat_del(sk, skb);
21718c2ecf20Sopenharmony_ci			break;
21728c2ecf20Sopenharmony_ci		}
21738c2ecf20Sopenharmony_ci
21748c2ecf20Sopenharmony_ci		mutex_unlock(&u->iolock);
21758c2ecf20Sopenharmony_ci
21768c2ecf20Sopenharmony_ci		if (err != -EAGAIN)
21778c2ecf20Sopenharmony_ci			break;
21788c2ecf20Sopenharmony_ci	} while (timeo &&
21798c2ecf20Sopenharmony_ci		 !__skb_wait_for_more_packets(sk, &sk->sk_receive_queue,
21808c2ecf20Sopenharmony_ci					      &err, &timeo, last));
21818c2ecf20Sopenharmony_ci
21828c2ecf20Sopenharmony_ci	if (!skb) { /* implies iolock unlocked */
21838c2ecf20Sopenharmony_ci		unix_state_lock(sk);
21848c2ecf20Sopenharmony_ci		/* Signal EOF on disconnected non-blocking SEQPACKET socket. */
21858c2ecf20Sopenharmony_ci		if (sk->sk_type == SOCK_SEQPACKET && err == -EAGAIN &&
21868c2ecf20Sopenharmony_ci		    (sk->sk_shutdown & RCV_SHUTDOWN))
21878c2ecf20Sopenharmony_ci			err = 0;
21888c2ecf20Sopenharmony_ci		unix_state_unlock(sk);
21898c2ecf20Sopenharmony_ci		goto out;
21908c2ecf20Sopenharmony_ci	}
21918c2ecf20Sopenharmony_ci
21928c2ecf20Sopenharmony_ci	if (wq_has_sleeper(&u->peer_wait))
21938c2ecf20Sopenharmony_ci		wake_up_interruptible_sync_poll(&u->peer_wait,
21948c2ecf20Sopenharmony_ci						EPOLLOUT | EPOLLWRNORM |
21958c2ecf20Sopenharmony_ci						EPOLLWRBAND);
21968c2ecf20Sopenharmony_ci
21978c2ecf20Sopenharmony_ci	if (msg->msg_name)
21988c2ecf20Sopenharmony_ci		unix_copy_addr(msg, skb->sk);
21998c2ecf20Sopenharmony_ci
22008c2ecf20Sopenharmony_ci	if (size > skb->len - skip)
22018c2ecf20Sopenharmony_ci		size = skb->len - skip;
22028c2ecf20Sopenharmony_ci	else if (size < skb->len - skip)
22038c2ecf20Sopenharmony_ci		msg->msg_flags |= MSG_TRUNC;
22048c2ecf20Sopenharmony_ci
22058c2ecf20Sopenharmony_ci	err = skb_copy_datagram_msg(skb, skip, msg, size);
22068c2ecf20Sopenharmony_ci	if (err)
22078c2ecf20Sopenharmony_ci		goto out_free;
22088c2ecf20Sopenharmony_ci
22098c2ecf20Sopenharmony_ci	if (sock_flag(sk, SOCK_RCVTSTAMP))
22108c2ecf20Sopenharmony_ci		__sock_recv_timestamp(msg, sk, skb);
22118c2ecf20Sopenharmony_ci
22128c2ecf20Sopenharmony_ci	memset(&scm, 0, sizeof(scm));
22138c2ecf20Sopenharmony_ci
22148c2ecf20Sopenharmony_ci	scm_set_cred(&scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid);
22158c2ecf20Sopenharmony_ci	unix_set_secdata(&scm, skb);
22168c2ecf20Sopenharmony_ci
22178c2ecf20Sopenharmony_ci	if (!(flags & MSG_PEEK)) {
22188c2ecf20Sopenharmony_ci		if (UNIXCB(skb).fp)
22198c2ecf20Sopenharmony_ci			unix_detach_fds(&scm, skb);
22208c2ecf20Sopenharmony_ci
22218c2ecf20Sopenharmony_ci		sk_peek_offset_bwd(sk, skb->len);
22228c2ecf20Sopenharmony_ci	} else {
22238c2ecf20Sopenharmony_ci		/* It is questionable: on PEEK we could:
22248c2ecf20Sopenharmony_ci		   - do not return fds - good, but too simple 8)
22258c2ecf20Sopenharmony_ci		   - return fds, and do not return them on read (old strategy,
22268c2ecf20Sopenharmony_ci		     apparently wrong)
22278c2ecf20Sopenharmony_ci		   - clone fds (I chose it for now, it is the most universal
22288c2ecf20Sopenharmony_ci		     solution)
22298c2ecf20Sopenharmony_ci
22308c2ecf20Sopenharmony_ci		   POSIX 1003.1g does not actually define this clearly
22318c2ecf20Sopenharmony_ci		   at all. POSIX 1003.1g doesn't define a lot of things
22328c2ecf20Sopenharmony_ci		   clearly however!
22338c2ecf20Sopenharmony_ci
22348c2ecf20Sopenharmony_ci		*/
22358c2ecf20Sopenharmony_ci
22368c2ecf20Sopenharmony_ci		sk_peek_offset_fwd(sk, size);
22378c2ecf20Sopenharmony_ci
22388c2ecf20Sopenharmony_ci		if (UNIXCB(skb).fp)
22398c2ecf20Sopenharmony_ci			unix_peek_fds(&scm, skb);
22408c2ecf20Sopenharmony_ci	}
22418c2ecf20Sopenharmony_ci	err = (flags & MSG_TRUNC) ? skb->len - skip : size;
22428c2ecf20Sopenharmony_ci
22438c2ecf20Sopenharmony_ci	scm_recv(sock, msg, &scm, flags);
22448c2ecf20Sopenharmony_ci
22458c2ecf20Sopenharmony_ciout_free:
22468c2ecf20Sopenharmony_ci	skb_free_datagram(sk, skb);
22478c2ecf20Sopenharmony_ci	mutex_unlock(&u->iolock);
22488c2ecf20Sopenharmony_ciout:
22498c2ecf20Sopenharmony_ci	return err;
22508c2ecf20Sopenharmony_ci}
22518c2ecf20Sopenharmony_ci
22528c2ecf20Sopenharmony_ci/*
22538c2ecf20Sopenharmony_ci *	Sleep until more data has arrived. But check for races..
22548c2ecf20Sopenharmony_ci */
22558c2ecf20Sopenharmony_cistatic long unix_stream_data_wait(struct sock *sk, long timeo,
22568c2ecf20Sopenharmony_ci				  struct sk_buff *last, unsigned int last_len,
22578c2ecf20Sopenharmony_ci				  bool freezable)
22588c2ecf20Sopenharmony_ci{
22598c2ecf20Sopenharmony_ci	struct sk_buff *tail;
22608c2ecf20Sopenharmony_ci	DEFINE_WAIT(wait);
22618c2ecf20Sopenharmony_ci
22628c2ecf20Sopenharmony_ci	unix_state_lock(sk);
22638c2ecf20Sopenharmony_ci
22648c2ecf20Sopenharmony_ci	for (;;) {
22658c2ecf20Sopenharmony_ci		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
22668c2ecf20Sopenharmony_ci
22678c2ecf20Sopenharmony_ci		tail = skb_peek_tail(&sk->sk_receive_queue);
22688c2ecf20Sopenharmony_ci		if (tail != last ||
22698c2ecf20Sopenharmony_ci		    (tail && tail->len != last_len) ||
22708c2ecf20Sopenharmony_ci		    sk->sk_err ||
22718c2ecf20Sopenharmony_ci		    (sk->sk_shutdown & RCV_SHUTDOWN) ||
22728c2ecf20Sopenharmony_ci		    signal_pending(current) ||
22738c2ecf20Sopenharmony_ci		    !timeo)
22748c2ecf20Sopenharmony_ci			break;
22758c2ecf20Sopenharmony_ci
22768c2ecf20Sopenharmony_ci		sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
22778c2ecf20Sopenharmony_ci		unix_state_unlock(sk);
22788c2ecf20Sopenharmony_ci		if (freezable)
22798c2ecf20Sopenharmony_ci			timeo = freezable_schedule_timeout(timeo);
22808c2ecf20Sopenharmony_ci		else
22818c2ecf20Sopenharmony_ci			timeo = schedule_timeout(timeo);
22828c2ecf20Sopenharmony_ci		unix_state_lock(sk);
22838c2ecf20Sopenharmony_ci
22848c2ecf20Sopenharmony_ci		if (sock_flag(sk, SOCK_DEAD))
22858c2ecf20Sopenharmony_ci			break;
22868c2ecf20Sopenharmony_ci
22878c2ecf20Sopenharmony_ci		sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
22888c2ecf20Sopenharmony_ci	}
22898c2ecf20Sopenharmony_ci
22908c2ecf20Sopenharmony_ci	finish_wait(sk_sleep(sk), &wait);
22918c2ecf20Sopenharmony_ci	unix_state_unlock(sk);
22928c2ecf20Sopenharmony_ci	return timeo;
22938c2ecf20Sopenharmony_ci}
22948c2ecf20Sopenharmony_ci
22958c2ecf20Sopenharmony_cistatic unsigned int unix_skb_len(const struct sk_buff *skb)
22968c2ecf20Sopenharmony_ci{
22978c2ecf20Sopenharmony_ci	return skb->len - UNIXCB(skb).consumed;
22988c2ecf20Sopenharmony_ci}
22998c2ecf20Sopenharmony_ci
23008c2ecf20Sopenharmony_cistruct unix_stream_read_state {
23018c2ecf20Sopenharmony_ci	int (*recv_actor)(struct sk_buff *, int, int,
23028c2ecf20Sopenharmony_ci			  struct unix_stream_read_state *);
23038c2ecf20Sopenharmony_ci	struct socket *socket;
23048c2ecf20Sopenharmony_ci	struct msghdr *msg;
23058c2ecf20Sopenharmony_ci	struct pipe_inode_info *pipe;
23068c2ecf20Sopenharmony_ci	size_t size;
23078c2ecf20Sopenharmony_ci	int flags;
23088c2ecf20Sopenharmony_ci	unsigned int splice_flags;
23098c2ecf20Sopenharmony_ci};
23108c2ecf20Sopenharmony_ci
23118c2ecf20Sopenharmony_cistatic int unix_stream_read_generic(struct unix_stream_read_state *state,
23128c2ecf20Sopenharmony_ci				    bool freezable)
23138c2ecf20Sopenharmony_ci{
23148c2ecf20Sopenharmony_ci	struct scm_cookie scm;
23158c2ecf20Sopenharmony_ci	struct socket *sock = state->socket;
23168c2ecf20Sopenharmony_ci	struct sock *sk = sock->sk;
23178c2ecf20Sopenharmony_ci	struct unix_sock *u = unix_sk(sk);
23188c2ecf20Sopenharmony_ci	int copied = 0;
23198c2ecf20Sopenharmony_ci	int flags = state->flags;
23208c2ecf20Sopenharmony_ci	int noblock = flags & MSG_DONTWAIT;
23218c2ecf20Sopenharmony_ci	bool check_creds = false;
23228c2ecf20Sopenharmony_ci	int target;
23238c2ecf20Sopenharmony_ci	int err = 0;
23248c2ecf20Sopenharmony_ci	long timeo;
23258c2ecf20Sopenharmony_ci	int skip;
23268c2ecf20Sopenharmony_ci	size_t size = state->size;
23278c2ecf20Sopenharmony_ci	unsigned int last_len;
23288c2ecf20Sopenharmony_ci
23298c2ecf20Sopenharmony_ci	if (unlikely(sk->sk_state != TCP_ESTABLISHED)) {
23308c2ecf20Sopenharmony_ci		err = -EINVAL;
23318c2ecf20Sopenharmony_ci		goto out;
23328c2ecf20Sopenharmony_ci	}
23338c2ecf20Sopenharmony_ci
23348c2ecf20Sopenharmony_ci	if (unlikely(flags & MSG_OOB)) {
23358c2ecf20Sopenharmony_ci		err = -EOPNOTSUPP;
23368c2ecf20Sopenharmony_ci		goto out;
23378c2ecf20Sopenharmony_ci	}
23388c2ecf20Sopenharmony_ci
23398c2ecf20Sopenharmony_ci	target = sock_rcvlowat(sk, flags & MSG_WAITALL, size);
23408c2ecf20Sopenharmony_ci	timeo = sock_rcvtimeo(sk, noblock);
23418c2ecf20Sopenharmony_ci
23428c2ecf20Sopenharmony_ci	memset(&scm, 0, sizeof(scm));
23438c2ecf20Sopenharmony_ci
23448c2ecf20Sopenharmony_ci	/* Lock the socket to prevent queue disordering
23458c2ecf20Sopenharmony_ci	 * while sleeps in memcpy_tomsg
23468c2ecf20Sopenharmony_ci	 */
23478c2ecf20Sopenharmony_ci	mutex_lock(&u->iolock);
23488c2ecf20Sopenharmony_ci
23498c2ecf20Sopenharmony_ci	skip = max(sk_peek_offset(sk, flags), 0);
23508c2ecf20Sopenharmony_ci
23518c2ecf20Sopenharmony_ci	do {
23528c2ecf20Sopenharmony_ci		int chunk;
23538c2ecf20Sopenharmony_ci		bool drop_skb;
23548c2ecf20Sopenharmony_ci		struct sk_buff *skb, *last;
23558c2ecf20Sopenharmony_ci
23568c2ecf20Sopenharmony_ciredo:
23578c2ecf20Sopenharmony_ci		unix_state_lock(sk);
23588c2ecf20Sopenharmony_ci		if (sock_flag(sk, SOCK_DEAD)) {
23598c2ecf20Sopenharmony_ci			err = -ECONNRESET;
23608c2ecf20Sopenharmony_ci			goto unlock;
23618c2ecf20Sopenharmony_ci		}
23628c2ecf20Sopenharmony_ci		last = skb = skb_peek(&sk->sk_receive_queue);
23638c2ecf20Sopenharmony_ci		last_len = last ? last->len : 0;
23648c2ecf20Sopenharmony_ciagain:
23658c2ecf20Sopenharmony_ci		if (skb == NULL) {
23668c2ecf20Sopenharmony_ci			if (copied >= target)
23678c2ecf20Sopenharmony_ci				goto unlock;
23688c2ecf20Sopenharmony_ci
23698c2ecf20Sopenharmony_ci			/*
23708c2ecf20Sopenharmony_ci			 *	POSIX 1003.1g mandates this order.
23718c2ecf20Sopenharmony_ci			 */
23728c2ecf20Sopenharmony_ci
23738c2ecf20Sopenharmony_ci			err = sock_error(sk);
23748c2ecf20Sopenharmony_ci			if (err)
23758c2ecf20Sopenharmony_ci				goto unlock;
23768c2ecf20Sopenharmony_ci			if (sk->sk_shutdown & RCV_SHUTDOWN)
23778c2ecf20Sopenharmony_ci				goto unlock;
23788c2ecf20Sopenharmony_ci
23798c2ecf20Sopenharmony_ci			unix_state_unlock(sk);
23808c2ecf20Sopenharmony_ci			if (!timeo) {
23818c2ecf20Sopenharmony_ci				err = -EAGAIN;
23828c2ecf20Sopenharmony_ci				break;
23838c2ecf20Sopenharmony_ci			}
23848c2ecf20Sopenharmony_ci
23858c2ecf20Sopenharmony_ci			mutex_unlock(&u->iolock);
23868c2ecf20Sopenharmony_ci
23878c2ecf20Sopenharmony_ci			timeo = unix_stream_data_wait(sk, timeo, last,
23888c2ecf20Sopenharmony_ci						      last_len, freezable);
23898c2ecf20Sopenharmony_ci
23908c2ecf20Sopenharmony_ci			if (signal_pending(current)) {
23918c2ecf20Sopenharmony_ci				err = sock_intr_errno(timeo);
23928c2ecf20Sopenharmony_ci				scm_destroy(&scm);
23938c2ecf20Sopenharmony_ci				goto out;
23948c2ecf20Sopenharmony_ci			}
23958c2ecf20Sopenharmony_ci
23968c2ecf20Sopenharmony_ci			mutex_lock(&u->iolock);
23978c2ecf20Sopenharmony_ci			goto redo;
23988c2ecf20Sopenharmony_ciunlock:
23998c2ecf20Sopenharmony_ci			unix_state_unlock(sk);
24008c2ecf20Sopenharmony_ci			break;
24018c2ecf20Sopenharmony_ci		}
24028c2ecf20Sopenharmony_ci
24038c2ecf20Sopenharmony_ci		while (skip >= unix_skb_len(skb)) {
24048c2ecf20Sopenharmony_ci			skip -= unix_skb_len(skb);
24058c2ecf20Sopenharmony_ci			last = skb;
24068c2ecf20Sopenharmony_ci			last_len = skb->len;
24078c2ecf20Sopenharmony_ci			skb = skb_peek_next(skb, &sk->sk_receive_queue);
24088c2ecf20Sopenharmony_ci			if (!skb)
24098c2ecf20Sopenharmony_ci				goto again;
24108c2ecf20Sopenharmony_ci		}
24118c2ecf20Sopenharmony_ci
24128c2ecf20Sopenharmony_ci		unix_state_unlock(sk);
24138c2ecf20Sopenharmony_ci
24148c2ecf20Sopenharmony_ci		if (check_creds) {
24158c2ecf20Sopenharmony_ci			/* Never glue messages from different writers */
24168c2ecf20Sopenharmony_ci			if (!unix_skb_scm_eq(skb, &scm))
24178c2ecf20Sopenharmony_ci				break;
24188c2ecf20Sopenharmony_ci		} else if (test_bit(SOCK_PASSCRED, &sock->flags)) {
24198c2ecf20Sopenharmony_ci			/* Copy credentials */
24208c2ecf20Sopenharmony_ci			scm_set_cred(&scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid);
24218c2ecf20Sopenharmony_ci			unix_set_secdata(&scm, skb);
24228c2ecf20Sopenharmony_ci			check_creds = true;
24238c2ecf20Sopenharmony_ci		}
24248c2ecf20Sopenharmony_ci
24258c2ecf20Sopenharmony_ci		/* Copy address just once */
24268c2ecf20Sopenharmony_ci		if (state->msg && state->msg->msg_name) {
24278c2ecf20Sopenharmony_ci			DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr,
24288c2ecf20Sopenharmony_ci					 state->msg->msg_name);
24298c2ecf20Sopenharmony_ci			unix_copy_addr(state->msg, skb->sk);
24308c2ecf20Sopenharmony_ci			sunaddr = NULL;
24318c2ecf20Sopenharmony_ci		}
24328c2ecf20Sopenharmony_ci
24338c2ecf20Sopenharmony_ci		chunk = min_t(unsigned int, unix_skb_len(skb) - skip, size);
24348c2ecf20Sopenharmony_ci		skb_get(skb);
24358c2ecf20Sopenharmony_ci		chunk = state->recv_actor(skb, skip, chunk, state);
24368c2ecf20Sopenharmony_ci		drop_skb = !unix_skb_len(skb);
24378c2ecf20Sopenharmony_ci		/* skb is only safe to use if !drop_skb */
24388c2ecf20Sopenharmony_ci		consume_skb(skb);
24398c2ecf20Sopenharmony_ci		if (chunk < 0) {
24408c2ecf20Sopenharmony_ci			if (copied == 0)
24418c2ecf20Sopenharmony_ci				copied = -EFAULT;
24428c2ecf20Sopenharmony_ci			break;
24438c2ecf20Sopenharmony_ci		}
24448c2ecf20Sopenharmony_ci		copied += chunk;
24458c2ecf20Sopenharmony_ci		size -= chunk;
24468c2ecf20Sopenharmony_ci
24478c2ecf20Sopenharmony_ci		if (drop_skb) {
24488c2ecf20Sopenharmony_ci			/* the skb was touched by a concurrent reader;
24498c2ecf20Sopenharmony_ci			 * we should not expect anything from this skb
24508c2ecf20Sopenharmony_ci			 * anymore and assume it invalid - we can be
24518c2ecf20Sopenharmony_ci			 * sure it was dropped from the socket queue
24528c2ecf20Sopenharmony_ci			 *
24538c2ecf20Sopenharmony_ci			 * let's report a short read
24548c2ecf20Sopenharmony_ci			 */
24558c2ecf20Sopenharmony_ci			err = 0;
24568c2ecf20Sopenharmony_ci			break;
24578c2ecf20Sopenharmony_ci		}
24588c2ecf20Sopenharmony_ci
24598c2ecf20Sopenharmony_ci		/* Mark read part of skb as used */
24608c2ecf20Sopenharmony_ci		if (!(flags & MSG_PEEK)) {
24618c2ecf20Sopenharmony_ci			UNIXCB(skb).consumed += chunk;
24628c2ecf20Sopenharmony_ci
24638c2ecf20Sopenharmony_ci			sk_peek_offset_bwd(sk, chunk);
24648c2ecf20Sopenharmony_ci
24658c2ecf20Sopenharmony_ci			if (UNIXCB(skb).fp) {
24668c2ecf20Sopenharmony_ci				scm_stat_del(sk, skb);
24678c2ecf20Sopenharmony_ci				unix_detach_fds(&scm, skb);
24688c2ecf20Sopenharmony_ci			}
24698c2ecf20Sopenharmony_ci
24708c2ecf20Sopenharmony_ci			if (unix_skb_len(skb))
24718c2ecf20Sopenharmony_ci				break;
24728c2ecf20Sopenharmony_ci
24738c2ecf20Sopenharmony_ci			skb_unlink(skb, &sk->sk_receive_queue);
24748c2ecf20Sopenharmony_ci			consume_skb(skb);
24758c2ecf20Sopenharmony_ci
24768c2ecf20Sopenharmony_ci			if (scm.fp)
24778c2ecf20Sopenharmony_ci				break;
24788c2ecf20Sopenharmony_ci		} else {
24798c2ecf20Sopenharmony_ci			/* It is questionable, see note in unix_dgram_recvmsg.
24808c2ecf20Sopenharmony_ci			 */
24818c2ecf20Sopenharmony_ci			if (UNIXCB(skb).fp)
24828c2ecf20Sopenharmony_ci				unix_peek_fds(&scm, skb);
24838c2ecf20Sopenharmony_ci
24848c2ecf20Sopenharmony_ci			sk_peek_offset_fwd(sk, chunk);
24858c2ecf20Sopenharmony_ci
24868c2ecf20Sopenharmony_ci			if (UNIXCB(skb).fp)
24878c2ecf20Sopenharmony_ci				break;
24888c2ecf20Sopenharmony_ci
24898c2ecf20Sopenharmony_ci			skip = 0;
24908c2ecf20Sopenharmony_ci			last = skb;
24918c2ecf20Sopenharmony_ci			last_len = skb->len;
24928c2ecf20Sopenharmony_ci			unix_state_lock(sk);
24938c2ecf20Sopenharmony_ci			skb = skb_peek_next(skb, &sk->sk_receive_queue);
24948c2ecf20Sopenharmony_ci			if (skb)
24958c2ecf20Sopenharmony_ci				goto again;
24968c2ecf20Sopenharmony_ci			unix_state_unlock(sk);
24978c2ecf20Sopenharmony_ci			break;
24988c2ecf20Sopenharmony_ci		}
24998c2ecf20Sopenharmony_ci	} while (size);
25008c2ecf20Sopenharmony_ci
25018c2ecf20Sopenharmony_ci	mutex_unlock(&u->iolock);
25028c2ecf20Sopenharmony_ci	if (state->msg)
25038c2ecf20Sopenharmony_ci		scm_recv(sock, state->msg, &scm, flags);
25048c2ecf20Sopenharmony_ci	else
25058c2ecf20Sopenharmony_ci		scm_destroy(&scm);
25068c2ecf20Sopenharmony_ciout:
25078c2ecf20Sopenharmony_ci	return copied ? : err;
25088c2ecf20Sopenharmony_ci}
25098c2ecf20Sopenharmony_ci
25108c2ecf20Sopenharmony_cistatic int unix_stream_read_actor(struct sk_buff *skb,
25118c2ecf20Sopenharmony_ci				  int skip, int chunk,
25128c2ecf20Sopenharmony_ci				  struct unix_stream_read_state *state)
25138c2ecf20Sopenharmony_ci{
25148c2ecf20Sopenharmony_ci	int ret;
25158c2ecf20Sopenharmony_ci
25168c2ecf20Sopenharmony_ci	ret = skb_copy_datagram_msg(skb, UNIXCB(skb).consumed + skip,
25178c2ecf20Sopenharmony_ci				    state->msg, chunk);
25188c2ecf20Sopenharmony_ci	return ret ?: chunk;
25198c2ecf20Sopenharmony_ci}
25208c2ecf20Sopenharmony_ci
25218c2ecf20Sopenharmony_cistatic int unix_stream_recvmsg(struct socket *sock, struct msghdr *msg,
25228c2ecf20Sopenharmony_ci			       size_t size, int flags)
25238c2ecf20Sopenharmony_ci{
25248c2ecf20Sopenharmony_ci	struct unix_stream_read_state state = {
25258c2ecf20Sopenharmony_ci		.recv_actor = unix_stream_read_actor,
25268c2ecf20Sopenharmony_ci		.socket = sock,
25278c2ecf20Sopenharmony_ci		.msg = msg,
25288c2ecf20Sopenharmony_ci		.size = size,
25298c2ecf20Sopenharmony_ci		.flags = flags
25308c2ecf20Sopenharmony_ci	};
25318c2ecf20Sopenharmony_ci
25328c2ecf20Sopenharmony_ci	return unix_stream_read_generic(&state, true);
25338c2ecf20Sopenharmony_ci}
25348c2ecf20Sopenharmony_ci
25358c2ecf20Sopenharmony_cistatic int unix_stream_splice_actor(struct sk_buff *skb,
25368c2ecf20Sopenharmony_ci				    int skip, int chunk,
25378c2ecf20Sopenharmony_ci				    struct unix_stream_read_state *state)
25388c2ecf20Sopenharmony_ci{
25398c2ecf20Sopenharmony_ci	return skb_splice_bits(skb, state->socket->sk,
25408c2ecf20Sopenharmony_ci			       UNIXCB(skb).consumed + skip,
25418c2ecf20Sopenharmony_ci			       state->pipe, chunk, state->splice_flags);
25428c2ecf20Sopenharmony_ci}
25438c2ecf20Sopenharmony_ci
25448c2ecf20Sopenharmony_cistatic ssize_t unix_stream_splice_read(struct socket *sock,  loff_t *ppos,
25458c2ecf20Sopenharmony_ci				       struct pipe_inode_info *pipe,
25468c2ecf20Sopenharmony_ci				       size_t size, unsigned int flags)
25478c2ecf20Sopenharmony_ci{
25488c2ecf20Sopenharmony_ci	struct unix_stream_read_state state = {
25498c2ecf20Sopenharmony_ci		.recv_actor = unix_stream_splice_actor,
25508c2ecf20Sopenharmony_ci		.socket = sock,
25518c2ecf20Sopenharmony_ci		.pipe = pipe,
25528c2ecf20Sopenharmony_ci		.size = size,
25538c2ecf20Sopenharmony_ci		.splice_flags = flags,
25548c2ecf20Sopenharmony_ci	};
25558c2ecf20Sopenharmony_ci
25568c2ecf20Sopenharmony_ci	if (unlikely(*ppos))
25578c2ecf20Sopenharmony_ci		return -ESPIPE;
25588c2ecf20Sopenharmony_ci
25598c2ecf20Sopenharmony_ci	if (sock->file->f_flags & O_NONBLOCK ||
25608c2ecf20Sopenharmony_ci	    flags & SPLICE_F_NONBLOCK)
25618c2ecf20Sopenharmony_ci		state.flags = MSG_DONTWAIT;
25628c2ecf20Sopenharmony_ci
25638c2ecf20Sopenharmony_ci	return unix_stream_read_generic(&state, false);
25648c2ecf20Sopenharmony_ci}
25658c2ecf20Sopenharmony_ci
25668c2ecf20Sopenharmony_cistatic int unix_shutdown(struct socket *sock, int mode)
25678c2ecf20Sopenharmony_ci{
25688c2ecf20Sopenharmony_ci	struct sock *sk = sock->sk;
25698c2ecf20Sopenharmony_ci	struct sock *other;
25708c2ecf20Sopenharmony_ci
25718c2ecf20Sopenharmony_ci	if (mode < SHUT_RD || mode > SHUT_RDWR)
25728c2ecf20Sopenharmony_ci		return -EINVAL;
25738c2ecf20Sopenharmony_ci	/* This maps:
25748c2ecf20Sopenharmony_ci	 * SHUT_RD   (0) -> RCV_SHUTDOWN  (1)
25758c2ecf20Sopenharmony_ci	 * SHUT_WR   (1) -> SEND_SHUTDOWN (2)
25768c2ecf20Sopenharmony_ci	 * SHUT_RDWR (2) -> SHUTDOWN_MASK (3)
25778c2ecf20Sopenharmony_ci	 */
25788c2ecf20Sopenharmony_ci	++mode;
25798c2ecf20Sopenharmony_ci
25808c2ecf20Sopenharmony_ci	unix_state_lock(sk);
25818c2ecf20Sopenharmony_ci	WRITE_ONCE(sk->sk_shutdown, sk->sk_shutdown | mode);
25828c2ecf20Sopenharmony_ci	other = unix_peer(sk);
25838c2ecf20Sopenharmony_ci	if (other)
25848c2ecf20Sopenharmony_ci		sock_hold(other);
25858c2ecf20Sopenharmony_ci	unix_state_unlock(sk);
25868c2ecf20Sopenharmony_ci	sk->sk_state_change(sk);
25878c2ecf20Sopenharmony_ci
25888c2ecf20Sopenharmony_ci	if (other &&
25898c2ecf20Sopenharmony_ci		(sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET)) {
25908c2ecf20Sopenharmony_ci
25918c2ecf20Sopenharmony_ci		int peer_mode = 0;
25928c2ecf20Sopenharmony_ci
25938c2ecf20Sopenharmony_ci		if (mode&RCV_SHUTDOWN)
25948c2ecf20Sopenharmony_ci			peer_mode |= SEND_SHUTDOWN;
25958c2ecf20Sopenharmony_ci		if (mode&SEND_SHUTDOWN)
25968c2ecf20Sopenharmony_ci			peer_mode |= RCV_SHUTDOWN;
25978c2ecf20Sopenharmony_ci		unix_state_lock(other);
25988c2ecf20Sopenharmony_ci		WRITE_ONCE(other->sk_shutdown, other->sk_shutdown | peer_mode);
25998c2ecf20Sopenharmony_ci		unix_state_unlock(other);
26008c2ecf20Sopenharmony_ci		other->sk_state_change(other);
26018c2ecf20Sopenharmony_ci		if (peer_mode == SHUTDOWN_MASK)
26028c2ecf20Sopenharmony_ci			sk_wake_async(other, SOCK_WAKE_WAITD, POLL_HUP);
26038c2ecf20Sopenharmony_ci		else if (peer_mode & RCV_SHUTDOWN)
26048c2ecf20Sopenharmony_ci			sk_wake_async(other, SOCK_WAKE_WAITD, POLL_IN);
26058c2ecf20Sopenharmony_ci	}
26068c2ecf20Sopenharmony_ci	if (other)
26078c2ecf20Sopenharmony_ci		sock_put(other);
26088c2ecf20Sopenharmony_ci
26098c2ecf20Sopenharmony_ci	return 0;
26108c2ecf20Sopenharmony_ci}
26118c2ecf20Sopenharmony_ci
26128c2ecf20Sopenharmony_cilong unix_inq_len(struct sock *sk)
26138c2ecf20Sopenharmony_ci{
26148c2ecf20Sopenharmony_ci	struct sk_buff *skb;
26158c2ecf20Sopenharmony_ci	long amount = 0;
26168c2ecf20Sopenharmony_ci
26178c2ecf20Sopenharmony_ci	if (sk->sk_state == TCP_LISTEN)
26188c2ecf20Sopenharmony_ci		return -EINVAL;
26198c2ecf20Sopenharmony_ci
26208c2ecf20Sopenharmony_ci	spin_lock(&sk->sk_receive_queue.lock);
26218c2ecf20Sopenharmony_ci	if (sk->sk_type == SOCK_STREAM ||
26228c2ecf20Sopenharmony_ci	    sk->sk_type == SOCK_SEQPACKET) {
26238c2ecf20Sopenharmony_ci		skb_queue_walk(&sk->sk_receive_queue, skb)
26248c2ecf20Sopenharmony_ci			amount += unix_skb_len(skb);
26258c2ecf20Sopenharmony_ci	} else {
26268c2ecf20Sopenharmony_ci		skb = skb_peek(&sk->sk_receive_queue);
26278c2ecf20Sopenharmony_ci		if (skb)
26288c2ecf20Sopenharmony_ci			amount = skb->len;
26298c2ecf20Sopenharmony_ci	}
26308c2ecf20Sopenharmony_ci	spin_unlock(&sk->sk_receive_queue.lock);
26318c2ecf20Sopenharmony_ci
26328c2ecf20Sopenharmony_ci	return amount;
26338c2ecf20Sopenharmony_ci}
26348c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(unix_inq_len);
26358c2ecf20Sopenharmony_ci
26368c2ecf20Sopenharmony_cilong unix_outq_len(struct sock *sk)
26378c2ecf20Sopenharmony_ci{
26388c2ecf20Sopenharmony_ci	return sk_wmem_alloc_get(sk);
26398c2ecf20Sopenharmony_ci}
26408c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(unix_outq_len);
26418c2ecf20Sopenharmony_ci
26428c2ecf20Sopenharmony_cistatic int unix_open_file(struct sock *sk)
26438c2ecf20Sopenharmony_ci{
26448c2ecf20Sopenharmony_ci	struct path path;
26458c2ecf20Sopenharmony_ci	struct file *f;
26468c2ecf20Sopenharmony_ci	int fd;
26478c2ecf20Sopenharmony_ci
26488c2ecf20Sopenharmony_ci	if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
26498c2ecf20Sopenharmony_ci		return -EPERM;
26508c2ecf20Sopenharmony_ci
26518c2ecf20Sopenharmony_ci	if (!smp_load_acquire(&unix_sk(sk)->addr))
26528c2ecf20Sopenharmony_ci		return -ENOENT;
26538c2ecf20Sopenharmony_ci
26548c2ecf20Sopenharmony_ci	path = unix_sk(sk)->path;
26558c2ecf20Sopenharmony_ci	if (!path.dentry)
26568c2ecf20Sopenharmony_ci		return -ENOENT;
26578c2ecf20Sopenharmony_ci
26588c2ecf20Sopenharmony_ci	path_get(&path);
26598c2ecf20Sopenharmony_ci
26608c2ecf20Sopenharmony_ci	fd = get_unused_fd_flags(O_CLOEXEC);
26618c2ecf20Sopenharmony_ci	if (fd < 0)
26628c2ecf20Sopenharmony_ci		goto out;
26638c2ecf20Sopenharmony_ci
26648c2ecf20Sopenharmony_ci	f = dentry_open(&path, O_PATH, current_cred());
26658c2ecf20Sopenharmony_ci	if (IS_ERR(f)) {
26668c2ecf20Sopenharmony_ci		put_unused_fd(fd);
26678c2ecf20Sopenharmony_ci		fd = PTR_ERR(f);
26688c2ecf20Sopenharmony_ci		goto out;
26698c2ecf20Sopenharmony_ci	}
26708c2ecf20Sopenharmony_ci
26718c2ecf20Sopenharmony_ci	fd_install(fd, f);
26728c2ecf20Sopenharmony_ciout:
26738c2ecf20Sopenharmony_ci	path_put(&path);
26748c2ecf20Sopenharmony_ci
26758c2ecf20Sopenharmony_ci	return fd;
26768c2ecf20Sopenharmony_ci}
26778c2ecf20Sopenharmony_ci
26788c2ecf20Sopenharmony_cistatic int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
26798c2ecf20Sopenharmony_ci{
26808c2ecf20Sopenharmony_ci	struct sock *sk = sock->sk;
26818c2ecf20Sopenharmony_ci	long amount = 0;
26828c2ecf20Sopenharmony_ci	int err;
26838c2ecf20Sopenharmony_ci
26848c2ecf20Sopenharmony_ci	switch (cmd) {
26858c2ecf20Sopenharmony_ci	case SIOCOUTQ:
26868c2ecf20Sopenharmony_ci		amount = unix_outq_len(sk);
26878c2ecf20Sopenharmony_ci		err = put_user(amount, (int __user *)arg);
26888c2ecf20Sopenharmony_ci		break;
26898c2ecf20Sopenharmony_ci	case SIOCINQ:
26908c2ecf20Sopenharmony_ci		amount = unix_inq_len(sk);
26918c2ecf20Sopenharmony_ci		if (amount < 0)
26928c2ecf20Sopenharmony_ci			err = amount;
26938c2ecf20Sopenharmony_ci		else
26948c2ecf20Sopenharmony_ci			err = put_user(amount, (int __user *)arg);
26958c2ecf20Sopenharmony_ci		break;
26968c2ecf20Sopenharmony_ci	case SIOCUNIXFILE:
26978c2ecf20Sopenharmony_ci		err = unix_open_file(sk);
26988c2ecf20Sopenharmony_ci		break;
26998c2ecf20Sopenharmony_ci	default:
27008c2ecf20Sopenharmony_ci		err = -ENOIOCTLCMD;
27018c2ecf20Sopenharmony_ci		break;
27028c2ecf20Sopenharmony_ci	}
27038c2ecf20Sopenharmony_ci	return err;
27048c2ecf20Sopenharmony_ci}
27058c2ecf20Sopenharmony_ci
27068c2ecf20Sopenharmony_ci#ifdef CONFIG_COMPAT
27078c2ecf20Sopenharmony_cistatic int unix_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
27088c2ecf20Sopenharmony_ci{
27098c2ecf20Sopenharmony_ci	return unix_ioctl(sock, cmd, (unsigned long)compat_ptr(arg));
27108c2ecf20Sopenharmony_ci}
27118c2ecf20Sopenharmony_ci#endif
27128c2ecf20Sopenharmony_ci
27138c2ecf20Sopenharmony_cistatic __poll_t unix_poll(struct file *file, struct socket *sock, poll_table *wait)
27148c2ecf20Sopenharmony_ci{
27158c2ecf20Sopenharmony_ci	struct sock *sk = sock->sk;
27168c2ecf20Sopenharmony_ci	__poll_t mask;
27178c2ecf20Sopenharmony_ci	u8 shutdown;
27188c2ecf20Sopenharmony_ci
27198c2ecf20Sopenharmony_ci	sock_poll_wait(file, sock, wait);
27208c2ecf20Sopenharmony_ci	mask = 0;
27218c2ecf20Sopenharmony_ci	shutdown = READ_ONCE(sk->sk_shutdown);
27228c2ecf20Sopenharmony_ci
27238c2ecf20Sopenharmony_ci	/* exceptional events? */
27248c2ecf20Sopenharmony_ci	if (sk->sk_err)
27258c2ecf20Sopenharmony_ci		mask |= EPOLLERR;
27268c2ecf20Sopenharmony_ci	if (shutdown == SHUTDOWN_MASK)
27278c2ecf20Sopenharmony_ci		mask |= EPOLLHUP;
27288c2ecf20Sopenharmony_ci	if (shutdown & RCV_SHUTDOWN)
27298c2ecf20Sopenharmony_ci		mask |= EPOLLRDHUP | EPOLLIN | EPOLLRDNORM;
27308c2ecf20Sopenharmony_ci
27318c2ecf20Sopenharmony_ci	/* readable? */
27328c2ecf20Sopenharmony_ci	if (!skb_queue_empty_lockless(&sk->sk_receive_queue))
27338c2ecf20Sopenharmony_ci		mask |= EPOLLIN | EPOLLRDNORM;
27348c2ecf20Sopenharmony_ci
27358c2ecf20Sopenharmony_ci	/* Connection-based need to check for termination and startup */
27368c2ecf20Sopenharmony_ci	if ((sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) &&
27378c2ecf20Sopenharmony_ci	    sk->sk_state == TCP_CLOSE)
27388c2ecf20Sopenharmony_ci		mask |= EPOLLHUP;
27398c2ecf20Sopenharmony_ci
27408c2ecf20Sopenharmony_ci	/*
27418c2ecf20Sopenharmony_ci	 * we set writable also when the other side has shut down the
27428c2ecf20Sopenharmony_ci	 * connection. This prevents stuck sockets.
27438c2ecf20Sopenharmony_ci	 */
27448c2ecf20Sopenharmony_ci	if (unix_writable(sk))
27458c2ecf20Sopenharmony_ci		mask |= EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND;
27468c2ecf20Sopenharmony_ci
27478c2ecf20Sopenharmony_ci	return mask;
27488c2ecf20Sopenharmony_ci}
27498c2ecf20Sopenharmony_ci
27508c2ecf20Sopenharmony_cistatic __poll_t unix_dgram_poll(struct file *file, struct socket *sock,
27518c2ecf20Sopenharmony_ci				    poll_table *wait)
27528c2ecf20Sopenharmony_ci{
27538c2ecf20Sopenharmony_ci	struct sock *sk = sock->sk, *other;
27548c2ecf20Sopenharmony_ci	unsigned int writable;
27558c2ecf20Sopenharmony_ci	__poll_t mask;
27568c2ecf20Sopenharmony_ci	u8 shutdown;
27578c2ecf20Sopenharmony_ci
27588c2ecf20Sopenharmony_ci	sock_poll_wait(file, sock, wait);
27598c2ecf20Sopenharmony_ci	mask = 0;
27608c2ecf20Sopenharmony_ci	shutdown = READ_ONCE(sk->sk_shutdown);
27618c2ecf20Sopenharmony_ci
27628c2ecf20Sopenharmony_ci	/* exceptional events? */
27638c2ecf20Sopenharmony_ci	if (sk->sk_err || !skb_queue_empty_lockless(&sk->sk_error_queue))
27648c2ecf20Sopenharmony_ci		mask |= EPOLLERR |
27658c2ecf20Sopenharmony_ci			(sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? EPOLLPRI : 0);
27668c2ecf20Sopenharmony_ci
27678c2ecf20Sopenharmony_ci	if (shutdown & RCV_SHUTDOWN)
27688c2ecf20Sopenharmony_ci		mask |= EPOLLRDHUP | EPOLLIN | EPOLLRDNORM;
27698c2ecf20Sopenharmony_ci	if (shutdown == SHUTDOWN_MASK)
27708c2ecf20Sopenharmony_ci		mask |= EPOLLHUP;
27718c2ecf20Sopenharmony_ci
27728c2ecf20Sopenharmony_ci	/* readable? */
27738c2ecf20Sopenharmony_ci	if (!skb_queue_empty_lockless(&sk->sk_receive_queue))
27748c2ecf20Sopenharmony_ci		mask |= EPOLLIN | EPOLLRDNORM;
27758c2ecf20Sopenharmony_ci
27768c2ecf20Sopenharmony_ci	/* Connection-based need to check for termination and startup */
27778c2ecf20Sopenharmony_ci	if (sk->sk_type == SOCK_SEQPACKET) {
27788c2ecf20Sopenharmony_ci		if (sk->sk_state == TCP_CLOSE)
27798c2ecf20Sopenharmony_ci			mask |= EPOLLHUP;
27808c2ecf20Sopenharmony_ci		/* connection hasn't started yet? */
27818c2ecf20Sopenharmony_ci		if (sk->sk_state == TCP_SYN_SENT)
27828c2ecf20Sopenharmony_ci			return mask;
27838c2ecf20Sopenharmony_ci	}
27848c2ecf20Sopenharmony_ci
27858c2ecf20Sopenharmony_ci	/* No write status requested, avoid expensive OUT tests. */
27868c2ecf20Sopenharmony_ci	if (!(poll_requested_events(wait) & (EPOLLWRBAND|EPOLLWRNORM|EPOLLOUT)))
27878c2ecf20Sopenharmony_ci		return mask;
27888c2ecf20Sopenharmony_ci
27898c2ecf20Sopenharmony_ci	writable = unix_writable(sk);
27908c2ecf20Sopenharmony_ci	if (writable) {
27918c2ecf20Sopenharmony_ci		unix_state_lock(sk);
27928c2ecf20Sopenharmony_ci
27938c2ecf20Sopenharmony_ci		other = unix_peer(sk);
27948c2ecf20Sopenharmony_ci		if (other && unix_peer(other) != sk &&
27958c2ecf20Sopenharmony_ci		    unix_recvq_full_lockless(other) &&
27968c2ecf20Sopenharmony_ci		    unix_dgram_peer_wake_me(sk, other))
27978c2ecf20Sopenharmony_ci			writable = 0;
27988c2ecf20Sopenharmony_ci
27998c2ecf20Sopenharmony_ci		unix_state_unlock(sk);
28008c2ecf20Sopenharmony_ci	}
28018c2ecf20Sopenharmony_ci
28028c2ecf20Sopenharmony_ci	if (writable)
28038c2ecf20Sopenharmony_ci		mask |= EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND;
28048c2ecf20Sopenharmony_ci	else
28058c2ecf20Sopenharmony_ci		sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk);
28068c2ecf20Sopenharmony_ci
28078c2ecf20Sopenharmony_ci	return mask;
28088c2ecf20Sopenharmony_ci}
28098c2ecf20Sopenharmony_ci
28108c2ecf20Sopenharmony_ci#ifdef CONFIG_PROC_FS
28118c2ecf20Sopenharmony_ci
28128c2ecf20Sopenharmony_ci#define BUCKET_SPACE (BITS_PER_LONG - (UNIX_HASH_BITS + 1) - 1)
28138c2ecf20Sopenharmony_ci
28148c2ecf20Sopenharmony_ci#define get_bucket(x) ((x) >> BUCKET_SPACE)
28158c2ecf20Sopenharmony_ci#define get_offset(x) ((x) & ((1L << BUCKET_SPACE) - 1))
28168c2ecf20Sopenharmony_ci#define set_bucket_offset(b, o) ((b) << BUCKET_SPACE | (o))
28178c2ecf20Sopenharmony_ci
28188c2ecf20Sopenharmony_cistatic struct sock *unix_from_bucket(struct seq_file *seq, loff_t *pos)
28198c2ecf20Sopenharmony_ci{
28208c2ecf20Sopenharmony_ci	unsigned long offset = get_offset(*pos);
28218c2ecf20Sopenharmony_ci	unsigned long bucket = get_bucket(*pos);
28228c2ecf20Sopenharmony_ci	struct sock *sk;
28238c2ecf20Sopenharmony_ci	unsigned long count = 0;
28248c2ecf20Sopenharmony_ci
28258c2ecf20Sopenharmony_ci	for (sk = sk_head(&unix_socket_table[bucket]); sk; sk = sk_next(sk)) {
28268c2ecf20Sopenharmony_ci		if (sock_net(sk) != seq_file_net(seq))
28278c2ecf20Sopenharmony_ci			continue;
28288c2ecf20Sopenharmony_ci		if (++count == offset)
28298c2ecf20Sopenharmony_ci			break;
28308c2ecf20Sopenharmony_ci	}
28318c2ecf20Sopenharmony_ci
28328c2ecf20Sopenharmony_ci	return sk;
28338c2ecf20Sopenharmony_ci}
28348c2ecf20Sopenharmony_ci
28358c2ecf20Sopenharmony_cistatic struct sock *unix_next_socket(struct seq_file *seq,
28368c2ecf20Sopenharmony_ci				     struct sock *sk,
28378c2ecf20Sopenharmony_ci				     loff_t *pos)
28388c2ecf20Sopenharmony_ci{
28398c2ecf20Sopenharmony_ci	unsigned long bucket;
28408c2ecf20Sopenharmony_ci
28418c2ecf20Sopenharmony_ci	while (sk > (struct sock *)SEQ_START_TOKEN) {
28428c2ecf20Sopenharmony_ci		sk = sk_next(sk);
28438c2ecf20Sopenharmony_ci		if (!sk)
28448c2ecf20Sopenharmony_ci			goto next_bucket;
28458c2ecf20Sopenharmony_ci		if (sock_net(sk) == seq_file_net(seq))
28468c2ecf20Sopenharmony_ci			return sk;
28478c2ecf20Sopenharmony_ci	}
28488c2ecf20Sopenharmony_ci
28498c2ecf20Sopenharmony_ci	do {
28508c2ecf20Sopenharmony_ci		sk = unix_from_bucket(seq, pos);
28518c2ecf20Sopenharmony_ci		if (sk)
28528c2ecf20Sopenharmony_ci			return sk;
28538c2ecf20Sopenharmony_ci
28548c2ecf20Sopenharmony_cinext_bucket:
28558c2ecf20Sopenharmony_ci		bucket = get_bucket(*pos) + 1;
28568c2ecf20Sopenharmony_ci		*pos = set_bucket_offset(bucket, 1);
28578c2ecf20Sopenharmony_ci	} while (bucket < ARRAY_SIZE(unix_socket_table));
28588c2ecf20Sopenharmony_ci
28598c2ecf20Sopenharmony_ci	return NULL;
28608c2ecf20Sopenharmony_ci}
28618c2ecf20Sopenharmony_ci
28628c2ecf20Sopenharmony_cistatic void *unix_seq_start(struct seq_file *seq, loff_t *pos)
28638c2ecf20Sopenharmony_ci	__acquires(unix_table_lock)
28648c2ecf20Sopenharmony_ci{
28658c2ecf20Sopenharmony_ci	spin_lock(&unix_table_lock);
28668c2ecf20Sopenharmony_ci
28678c2ecf20Sopenharmony_ci	if (!*pos)
28688c2ecf20Sopenharmony_ci		return SEQ_START_TOKEN;
28698c2ecf20Sopenharmony_ci
28708c2ecf20Sopenharmony_ci	if (get_bucket(*pos) >= ARRAY_SIZE(unix_socket_table))
28718c2ecf20Sopenharmony_ci		return NULL;
28728c2ecf20Sopenharmony_ci
28738c2ecf20Sopenharmony_ci	return unix_next_socket(seq, NULL, pos);
28748c2ecf20Sopenharmony_ci}
28758c2ecf20Sopenharmony_ci
28768c2ecf20Sopenharmony_cistatic void *unix_seq_next(struct seq_file *seq, void *v, loff_t *pos)
28778c2ecf20Sopenharmony_ci{
28788c2ecf20Sopenharmony_ci	++*pos;
28798c2ecf20Sopenharmony_ci	return unix_next_socket(seq, v, pos);
28808c2ecf20Sopenharmony_ci}
28818c2ecf20Sopenharmony_ci
28828c2ecf20Sopenharmony_cistatic void unix_seq_stop(struct seq_file *seq, void *v)
28838c2ecf20Sopenharmony_ci	__releases(unix_table_lock)
28848c2ecf20Sopenharmony_ci{
28858c2ecf20Sopenharmony_ci	spin_unlock(&unix_table_lock);
28868c2ecf20Sopenharmony_ci}
28878c2ecf20Sopenharmony_ci
28888c2ecf20Sopenharmony_cistatic int unix_seq_show(struct seq_file *seq, void *v)
28898c2ecf20Sopenharmony_ci{
28908c2ecf20Sopenharmony_ci
28918c2ecf20Sopenharmony_ci	if (v == SEQ_START_TOKEN)
28928c2ecf20Sopenharmony_ci		seq_puts(seq, "Num       RefCount Protocol Flags    Type St "
28938c2ecf20Sopenharmony_ci			 "Inode Path\n");
28948c2ecf20Sopenharmony_ci	else {
28958c2ecf20Sopenharmony_ci		struct sock *s = v;
28968c2ecf20Sopenharmony_ci		struct unix_sock *u = unix_sk(s);
28978c2ecf20Sopenharmony_ci		unix_state_lock(s);
28988c2ecf20Sopenharmony_ci
28998c2ecf20Sopenharmony_ci		seq_printf(seq, "%pK: %08X %08X %08X %04X %02X %5lu",
29008c2ecf20Sopenharmony_ci			s,
29018c2ecf20Sopenharmony_ci			refcount_read(&s->sk_refcnt),
29028c2ecf20Sopenharmony_ci			0,
29038c2ecf20Sopenharmony_ci			s->sk_state == TCP_LISTEN ? __SO_ACCEPTCON : 0,
29048c2ecf20Sopenharmony_ci			s->sk_type,
29058c2ecf20Sopenharmony_ci			s->sk_socket ?
29068c2ecf20Sopenharmony_ci			(s->sk_state == TCP_ESTABLISHED ? SS_CONNECTED : SS_UNCONNECTED) :
29078c2ecf20Sopenharmony_ci			(s->sk_state == TCP_ESTABLISHED ? SS_CONNECTING : SS_DISCONNECTING),
29088c2ecf20Sopenharmony_ci			sock_i_ino(s));
29098c2ecf20Sopenharmony_ci
29108c2ecf20Sopenharmony_ci		if (u->addr) {	// under unix_table_lock here
29118c2ecf20Sopenharmony_ci			int i, len;
29128c2ecf20Sopenharmony_ci			seq_putc(seq, ' ');
29138c2ecf20Sopenharmony_ci
29148c2ecf20Sopenharmony_ci			i = 0;
29158c2ecf20Sopenharmony_ci			len = u->addr->len - sizeof(short);
29168c2ecf20Sopenharmony_ci			if (!UNIX_ABSTRACT(s))
29178c2ecf20Sopenharmony_ci				len--;
29188c2ecf20Sopenharmony_ci			else {
29198c2ecf20Sopenharmony_ci				seq_putc(seq, '@');
29208c2ecf20Sopenharmony_ci				i++;
29218c2ecf20Sopenharmony_ci			}
29228c2ecf20Sopenharmony_ci			for ( ; i < len; i++)
29238c2ecf20Sopenharmony_ci				seq_putc(seq, u->addr->name->sun_path[i] ?:
29248c2ecf20Sopenharmony_ci					 '@');
29258c2ecf20Sopenharmony_ci		}
29268c2ecf20Sopenharmony_ci		unix_state_unlock(s);
29278c2ecf20Sopenharmony_ci		seq_putc(seq, '\n');
29288c2ecf20Sopenharmony_ci	}
29298c2ecf20Sopenharmony_ci
29308c2ecf20Sopenharmony_ci	return 0;
29318c2ecf20Sopenharmony_ci}
29328c2ecf20Sopenharmony_ci
29338c2ecf20Sopenharmony_cistatic const struct seq_operations unix_seq_ops = {
29348c2ecf20Sopenharmony_ci	.start  = unix_seq_start,
29358c2ecf20Sopenharmony_ci	.next   = unix_seq_next,
29368c2ecf20Sopenharmony_ci	.stop   = unix_seq_stop,
29378c2ecf20Sopenharmony_ci	.show   = unix_seq_show,
29388c2ecf20Sopenharmony_ci};
29398c2ecf20Sopenharmony_ci#endif
29408c2ecf20Sopenharmony_ci
29418c2ecf20Sopenharmony_cistatic const struct net_proto_family unix_family_ops = {
29428c2ecf20Sopenharmony_ci	.family = PF_UNIX,
29438c2ecf20Sopenharmony_ci	.create = unix_create,
29448c2ecf20Sopenharmony_ci	.owner	= THIS_MODULE,
29458c2ecf20Sopenharmony_ci};
29468c2ecf20Sopenharmony_ci
29478c2ecf20Sopenharmony_ci
29488c2ecf20Sopenharmony_cistatic int __net_init unix_net_init(struct net *net)
29498c2ecf20Sopenharmony_ci{
29508c2ecf20Sopenharmony_ci	int error = -ENOMEM;
29518c2ecf20Sopenharmony_ci
29528c2ecf20Sopenharmony_ci	net->unx.sysctl_max_dgram_qlen = 10;
29538c2ecf20Sopenharmony_ci	if (unix_sysctl_register(net))
29548c2ecf20Sopenharmony_ci		goto out;
29558c2ecf20Sopenharmony_ci
29568c2ecf20Sopenharmony_ci#ifdef CONFIG_PROC_FS
29578c2ecf20Sopenharmony_ci	if (!proc_create_net("unix", 0, net->proc_net, &unix_seq_ops,
29588c2ecf20Sopenharmony_ci			sizeof(struct seq_net_private))) {
29598c2ecf20Sopenharmony_ci		unix_sysctl_unregister(net);
29608c2ecf20Sopenharmony_ci		goto out;
29618c2ecf20Sopenharmony_ci	}
29628c2ecf20Sopenharmony_ci#endif
29638c2ecf20Sopenharmony_ci	error = 0;
29648c2ecf20Sopenharmony_ciout:
29658c2ecf20Sopenharmony_ci	return error;
29668c2ecf20Sopenharmony_ci}
29678c2ecf20Sopenharmony_ci
29688c2ecf20Sopenharmony_cistatic void __net_exit unix_net_exit(struct net *net)
29698c2ecf20Sopenharmony_ci{
29708c2ecf20Sopenharmony_ci	unix_sysctl_unregister(net);
29718c2ecf20Sopenharmony_ci	remove_proc_entry("unix", net->proc_net);
29728c2ecf20Sopenharmony_ci}
29738c2ecf20Sopenharmony_ci
29748c2ecf20Sopenharmony_cistatic struct pernet_operations unix_net_ops = {
29758c2ecf20Sopenharmony_ci	.init = unix_net_init,
29768c2ecf20Sopenharmony_ci	.exit = unix_net_exit,
29778c2ecf20Sopenharmony_ci};
29788c2ecf20Sopenharmony_ci
29798c2ecf20Sopenharmony_cistatic int __init af_unix_init(void)
29808c2ecf20Sopenharmony_ci{
29818c2ecf20Sopenharmony_ci	int rc = -1;
29828c2ecf20Sopenharmony_ci
29838c2ecf20Sopenharmony_ci	BUILD_BUG_ON(sizeof(struct unix_skb_parms) > sizeof_field(struct sk_buff, cb));
29848c2ecf20Sopenharmony_ci
29858c2ecf20Sopenharmony_ci	rc = proto_register(&unix_proto, 1);
29868c2ecf20Sopenharmony_ci	if (rc != 0) {
29878c2ecf20Sopenharmony_ci		pr_crit("%s: Cannot create unix_sock SLAB cache!\n", __func__);
29888c2ecf20Sopenharmony_ci		goto out;
29898c2ecf20Sopenharmony_ci	}
29908c2ecf20Sopenharmony_ci
29918c2ecf20Sopenharmony_ci	sock_register(&unix_family_ops);
29928c2ecf20Sopenharmony_ci	register_pernet_subsys(&unix_net_ops);
29938c2ecf20Sopenharmony_ciout:
29948c2ecf20Sopenharmony_ci	return rc;
29958c2ecf20Sopenharmony_ci}
29968c2ecf20Sopenharmony_ci
29978c2ecf20Sopenharmony_cistatic void __exit af_unix_exit(void)
29988c2ecf20Sopenharmony_ci{
29998c2ecf20Sopenharmony_ci	sock_unregister(PF_UNIX);
30008c2ecf20Sopenharmony_ci	proto_unregister(&unix_proto);
30018c2ecf20Sopenharmony_ci	unregister_pernet_subsys(&unix_net_ops);
30028c2ecf20Sopenharmony_ci}
30038c2ecf20Sopenharmony_ci
30048c2ecf20Sopenharmony_ci/* Earlier than device_initcall() so that other drivers invoking
30058c2ecf20Sopenharmony_ci   request_module() don't end up in a loop when modprobe tries
30068c2ecf20Sopenharmony_ci   to use a UNIX socket. But later than subsys_initcall() because
30078c2ecf20Sopenharmony_ci   we depend on stuff initialised there */
30088c2ecf20Sopenharmony_cifs_initcall(af_unix_init);
30098c2ecf20Sopenharmony_cimodule_exit(af_unix_exit);
30108c2ecf20Sopenharmony_ci
30118c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
30128c2ecf20Sopenharmony_ciMODULE_ALIAS_NETPROTO(PF_UNIX);
3013