162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * NET4:	Implementation of BSD Unix domain sockets.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Authors:	Alan Cox, <alan@lxorguk.ukuu.org.uk>
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Fixes:
862306a36Sopenharmony_ci *		Linus Torvalds	:	Assorted bug cures.
962306a36Sopenharmony_ci *		Niibe Yutaka	:	async I/O support.
1062306a36Sopenharmony_ci *		Carsten Paeth	:	PF_UNIX check, address fixes.
1162306a36Sopenharmony_ci *		Alan Cox	:	Limit size of allocated blocks.
1262306a36Sopenharmony_ci *		Alan Cox	:	Fixed the stupid socketpair bug.
1362306a36Sopenharmony_ci *		Alan Cox	:	BSD compatibility fine tuning.
1462306a36Sopenharmony_ci *		Alan Cox	:	Fixed a bug in connect when interrupted.
1562306a36Sopenharmony_ci *		Alan Cox	:	Sorted out a proper draft version of
1662306a36Sopenharmony_ci *					file descriptor passing hacked up from
1762306a36Sopenharmony_ci *					Mike Shaver's work.
1862306a36Sopenharmony_ci *		Marty Leisner	:	Fixes to fd passing
1962306a36Sopenharmony_ci *		Nick Nevin	:	recvmsg bugfix.
2062306a36Sopenharmony_ci *		Alan Cox	:	Started proper garbage collector
2162306a36Sopenharmony_ci *		Heiko EiBfeldt	:	Missing verify_area check
2262306a36Sopenharmony_ci *		Alan Cox	:	Started POSIXisms
2362306a36Sopenharmony_ci *		Andreas Schwab	:	Replace inode by dentry for proper
2462306a36Sopenharmony_ci *					reference counting
2562306a36Sopenharmony_ci *		Kirk Petersen	:	Made this a module
2662306a36Sopenharmony_ci *	    Christoph Rohland	:	Elegant non-blocking accept/connect algorithm.
2762306a36Sopenharmony_ci *					Lots of bug fixes.
2862306a36Sopenharmony_ci *	     Alexey Kuznetosv	:	Repaired (I hope) bugs introduces
2962306a36Sopenharmony_ci *					by above two patches.
3062306a36Sopenharmony_ci *	     Andrea Arcangeli	:	If possible we block in connect(2)
3162306a36Sopenharmony_ci *					if the max backlog of the listen socket
3262306a36Sopenharmony_ci *					is been reached. This won't break
3362306a36Sopenharmony_ci *					old apps and it will avoid huge amount
3462306a36Sopenharmony_ci *					of socks hashed (this for unix_gc()
3562306a36Sopenharmony_ci *					performances reasons).
3662306a36Sopenharmony_ci *					Security fix that limits the max
3762306a36Sopenharmony_ci *					number of socks to 2*max_files and
3862306a36Sopenharmony_ci *					the number of skb queueable in the
3962306a36Sopenharmony_ci *					dgram receiver.
4062306a36Sopenharmony_ci *		Artur Skawina   :	Hash function optimizations
4162306a36Sopenharmony_ci *	     Alexey Kuznetsov   :	Full scale SMP. Lot of bugs are introduced 8)
4262306a36Sopenharmony_ci *	      Malcolm Beattie   :	Set peercred for socketpair
4362306a36Sopenharmony_ci *	     Michal Ostrowski   :       Module initialization cleanup.
4462306a36Sopenharmony_ci *	     Arnaldo C. Melo	:	Remove MOD_{INC,DEC}_USE_COUNT,
4562306a36Sopenharmony_ci *	     				the core infrastructure is doing that
4662306a36Sopenharmony_ci *	     				for all net proto families now (2.5.69+)
4762306a36Sopenharmony_ci *
4862306a36Sopenharmony_ci * Known differences from reference BSD that was tested:
4962306a36Sopenharmony_ci *
5062306a36Sopenharmony_ci *	[TO FIX]
5162306a36Sopenharmony_ci *	ECONNREFUSED is not returned from one end of a connected() socket to the
5262306a36Sopenharmony_ci *		other the moment one end closes.
5362306a36Sopenharmony_ci *	fstat() doesn't return st_dev=0, and give the blksize as high water mark
5462306a36Sopenharmony_ci *		and a fake inode identifier (nor the BSD first socket fstat twice bug).
5562306a36Sopenharmony_ci *	[NOT TO FIX]
5662306a36Sopenharmony_ci *	accept() returns a path name even if the connecting socket has closed
5762306a36Sopenharmony_ci *		in the meantime (BSD loses the path and gives up).
5862306a36Sopenharmony_ci *	accept() returns 0 length path for an unbound connector. BSD returns 16
5962306a36Sopenharmony_ci *		and a null first byte in the path (but not for gethost/peername - BSD bug ??)
6062306a36Sopenharmony_ci *	socketpair(...SOCK_RAW..) doesn't panic the kernel.
6162306a36Sopenharmony_ci *	BSD af_unix apparently has connect forgetting to block properly.
6262306a36Sopenharmony_ci *		(need to check this with the POSIX spec in detail)
6362306a36Sopenharmony_ci *
6462306a36Sopenharmony_ci * Differences from 2.0.0-11-... (ANK)
6562306a36Sopenharmony_ci *	Bug fixes and improvements.
6662306a36Sopenharmony_ci *		- client shutdown killed server socket.
6762306a36Sopenharmony_ci *		- removed all useless cli/sti pairs.
6862306a36Sopenharmony_ci *
6962306a36Sopenharmony_ci *	Semantic changes/extensions.
7062306a36Sopenharmony_ci *		- generic control message passing.
7162306a36Sopenharmony_ci *		- SCM_CREDENTIALS control message.
7262306a36Sopenharmony_ci *		- "Abstract" (not FS based) socket bindings.
7362306a36Sopenharmony_ci *		  Abstract names are sequences of bytes (not zero terminated)
7462306a36Sopenharmony_ci *		  started by 0, so that this name space does not intersect
7562306a36Sopenharmony_ci *		  with BSD names.
7662306a36Sopenharmony_ci */
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci#include <linux/module.h>
8162306a36Sopenharmony_ci#include <linux/kernel.h>
8262306a36Sopenharmony_ci#include <linux/signal.h>
8362306a36Sopenharmony_ci#include <linux/sched/signal.h>
8462306a36Sopenharmony_ci#include <linux/errno.h>
8562306a36Sopenharmony_ci#include <linux/string.h>
8662306a36Sopenharmony_ci#include <linux/stat.h>
8762306a36Sopenharmony_ci#include <linux/dcache.h>
8862306a36Sopenharmony_ci#include <linux/namei.h>
8962306a36Sopenharmony_ci#include <linux/socket.h>
9062306a36Sopenharmony_ci#include <linux/un.h>
9162306a36Sopenharmony_ci#include <linux/fcntl.h>
9262306a36Sopenharmony_ci#include <linux/filter.h>
9362306a36Sopenharmony_ci#include <linux/termios.h>
9462306a36Sopenharmony_ci#include <linux/sockios.h>
9562306a36Sopenharmony_ci#include <linux/net.h>
9662306a36Sopenharmony_ci#include <linux/in.h>
9762306a36Sopenharmony_ci#include <linux/fs.h>
9862306a36Sopenharmony_ci#include <linux/slab.h>
9962306a36Sopenharmony_ci#include <linux/uaccess.h>
10062306a36Sopenharmony_ci#include <linux/skbuff.h>
10162306a36Sopenharmony_ci#include <linux/netdevice.h>
10262306a36Sopenharmony_ci#include <net/net_namespace.h>
10362306a36Sopenharmony_ci#include <net/sock.h>
10462306a36Sopenharmony_ci#include <net/tcp_states.h>
10562306a36Sopenharmony_ci#include <net/af_unix.h>
10662306a36Sopenharmony_ci#include <linux/proc_fs.h>
10762306a36Sopenharmony_ci#include <linux/seq_file.h>
10862306a36Sopenharmony_ci#include <net/scm.h>
10962306a36Sopenharmony_ci#include <linux/init.h>
11062306a36Sopenharmony_ci#include <linux/poll.h>
11162306a36Sopenharmony_ci#include <linux/rtnetlink.h>
11262306a36Sopenharmony_ci#include <linux/mount.h>
11362306a36Sopenharmony_ci#include <net/checksum.h>
11462306a36Sopenharmony_ci#include <linux/security.h>
11562306a36Sopenharmony_ci#include <linux/splice.h>
11662306a36Sopenharmony_ci#include <linux/freezer.h>
11762306a36Sopenharmony_ci#include <linux/file.h>
11862306a36Sopenharmony_ci#include <linux/btf_ids.h>
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci#include "scm.h"
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_cistatic atomic_long_t unix_nr_socks;
12362306a36Sopenharmony_cistatic struct hlist_head bsd_socket_buckets[UNIX_HASH_SIZE / 2];
12462306a36Sopenharmony_cistatic spinlock_t bsd_socket_locks[UNIX_HASH_SIZE / 2];
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci/* SMP locking strategy:
12762306a36Sopenharmony_ci *    hash table is protected with spinlock.
12862306a36Sopenharmony_ci *    each socket state is protected by separate spinlock.
12962306a36Sopenharmony_ci */
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_cistatic unsigned int unix_unbound_hash(struct sock *sk)
13262306a36Sopenharmony_ci{
13362306a36Sopenharmony_ci	unsigned long hash = (unsigned long)sk;
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	hash ^= hash >> 16;
13662306a36Sopenharmony_ci	hash ^= hash >> 8;
13762306a36Sopenharmony_ci	hash ^= sk->sk_type;
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	return hash & UNIX_HASH_MOD;
14062306a36Sopenharmony_ci}
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_cistatic unsigned int unix_bsd_hash(struct inode *i)
14362306a36Sopenharmony_ci{
14462306a36Sopenharmony_ci	return i->i_ino & UNIX_HASH_MOD;
14562306a36Sopenharmony_ci}
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_cistatic unsigned int unix_abstract_hash(struct sockaddr_un *sunaddr,
14862306a36Sopenharmony_ci				       int addr_len, int type)
14962306a36Sopenharmony_ci{
15062306a36Sopenharmony_ci	__wsum csum = csum_partial(sunaddr, addr_len, 0);
15162306a36Sopenharmony_ci	unsigned int hash;
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	hash = (__force unsigned int)csum_fold(csum);
15462306a36Sopenharmony_ci	hash ^= hash >> 8;
15562306a36Sopenharmony_ci	hash ^= type;
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	return UNIX_HASH_MOD + 1 + (hash & UNIX_HASH_MOD);
15862306a36Sopenharmony_ci}
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_cistatic void unix_table_double_lock(struct net *net,
16162306a36Sopenharmony_ci				   unsigned int hash1, unsigned int hash2)
16262306a36Sopenharmony_ci{
16362306a36Sopenharmony_ci	if (hash1 == hash2) {
16462306a36Sopenharmony_ci		spin_lock(&net->unx.table.locks[hash1]);
16562306a36Sopenharmony_ci		return;
16662306a36Sopenharmony_ci	}
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	if (hash1 > hash2)
16962306a36Sopenharmony_ci		swap(hash1, hash2);
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	spin_lock(&net->unx.table.locks[hash1]);
17262306a36Sopenharmony_ci	spin_lock_nested(&net->unx.table.locks[hash2], SINGLE_DEPTH_NESTING);
17362306a36Sopenharmony_ci}
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_cistatic void unix_table_double_unlock(struct net *net,
17662306a36Sopenharmony_ci				     unsigned int hash1, unsigned int hash2)
17762306a36Sopenharmony_ci{
17862306a36Sopenharmony_ci	if (hash1 == hash2) {
17962306a36Sopenharmony_ci		spin_unlock(&net->unx.table.locks[hash1]);
18062306a36Sopenharmony_ci		return;
18162306a36Sopenharmony_ci	}
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci	spin_unlock(&net->unx.table.locks[hash1]);
18462306a36Sopenharmony_ci	spin_unlock(&net->unx.table.locks[hash2]);
18562306a36Sopenharmony_ci}
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci#ifdef CONFIG_SECURITY_NETWORK
18862306a36Sopenharmony_cistatic void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
18962306a36Sopenharmony_ci{
19062306a36Sopenharmony_ci	UNIXCB(skb).secid = scm->secid;
19162306a36Sopenharmony_ci}
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_cistatic inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
19462306a36Sopenharmony_ci{
19562306a36Sopenharmony_ci	scm->secid = UNIXCB(skb).secid;
19662306a36Sopenharmony_ci}
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_cistatic inline bool unix_secdata_eq(struct scm_cookie *scm, struct sk_buff *skb)
19962306a36Sopenharmony_ci{
20062306a36Sopenharmony_ci	return (scm->secid == UNIXCB(skb).secid);
20162306a36Sopenharmony_ci}
20262306a36Sopenharmony_ci#else
20362306a36Sopenharmony_cistatic inline void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
20462306a36Sopenharmony_ci{ }
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_cistatic inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
20762306a36Sopenharmony_ci{ }
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_cistatic inline bool unix_secdata_eq(struct scm_cookie *scm, struct sk_buff *skb)
21062306a36Sopenharmony_ci{
21162306a36Sopenharmony_ci	return true;
21262306a36Sopenharmony_ci}
21362306a36Sopenharmony_ci#endif /* CONFIG_SECURITY_NETWORK */
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_cistatic inline int unix_our_peer(struct sock *sk, struct sock *osk)
21662306a36Sopenharmony_ci{
21762306a36Sopenharmony_ci	return unix_peer(osk) == sk;
21862306a36Sopenharmony_ci}
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_cistatic inline int unix_may_send(struct sock *sk, struct sock *osk)
22162306a36Sopenharmony_ci{
22262306a36Sopenharmony_ci	return unix_peer(osk) == NULL || unix_our_peer(sk, osk);
22362306a36Sopenharmony_ci}
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_cistatic inline int unix_recvq_full(const struct sock *sk)
22662306a36Sopenharmony_ci{
22762306a36Sopenharmony_ci	return skb_queue_len(&sk->sk_receive_queue) > sk->sk_max_ack_backlog;
22862306a36Sopenharmony_ci}
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_cistatic inline int unix_recvq_full_lockless(const struct sock *sk)
23162306a36Sopenharmony_ci{
23262306a36Sopenharmony_ci	return skb_queue_len_lockless(&sk->sk_receive_queue) >
23362306a36Sopenharmony_ci		READ_ONCE(sk->sk_max_ack_backlog);
23462306a36Sopenharmony_ci}
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_cistruct sock *unix_peer_get(struct sock *s)
23762306a36Sopenharmony_ci{
23862306a36Sopenharmony_ci	struct sock *peer;
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci	unix_state_lock(s);
24162306a36Sopenharmony_ci	peer = unix_peer(s);
24262306a36Sopenharmony_ci	if (peer)
24362306a36Sopenharmony_ci		sock_hold(peer);
24462306a36Sopenharmony_ci	unix_state_unlock(s);
24562306a36Sopenharmony_ci	return peer;
24662306a36Sopenharmony_ci}
24762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(unix_peer_get);
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_cistatic struct unix_address *unix_create_addr(struct sockaddr_un *sunaddr,
25062306a36Sopenharmony_ci					     int addr_len)
25162306a36Sopenharmony_ci{
25262306a36Sopenharmony_ci	struct unix_address *addr;
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	addr = kmalloc(sizeof(*addr) + addr_len, GFP_KERNEL);
25562306a36Sopenharmony_ci	if (!addr)
25662306a36Sopenharmony_ci		return NULL;
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	refcount_set(&addr->refcnt, 1);
25962306a36Sopenharmony_ci	addr->len = addr_len;
26062306a36Sopenharmony_ci	memcpy(addr->name, sunaddr, addr_len);
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	return addr;
26362306a36Sopenharmony_ci}
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_cistatic inline void unix_release_addr(struct unix_address *addr)
26662306a36Sopenharmony_ci{
26762306a36Sopenharmony_ci	if (refcount_dec_and_test(&addr->refcnt))
26862306a36Sopenharmony_ci		kfree(addr);
26962306a36Sopenharmony_ci}
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci/*
27262306a36Sopenharmony_ci *	Check unix socket name:
27362306a36Sopenharmony_ci *		- should be not zero length.
27462306a36Sopenharmony_ci *	        - if started by not zero, should be NULL terminated (FS object)
27562306a36Sopenharmony_ci *		- if started by zero, it is abstract name.
27662306a36Sopenharmony_ci */
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_cistatic int unix_validate_addr(struct sockaddr_un *sunaddr, int addr_len)
27962306a36Sopenharmony_ci{
28062306a36Sopenharmony_ci	if (addr_len <= offsetof(struct sockaddr_un, sun_path) ||
28162306a36Sopenharmony_ci	    addr_len > sizeof(*sunaddr))
28262306a36Sopenharmony_ci		return -EINVAL;
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	if (sunaddr->sun_family != AF_UNIX)
28562306a36Sopenharmony_ci		return -EINVAL;
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	return 0;
28862306a36Sopenharmony_ci}
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_cistatic int unix_mkname_bsd(struct sockaddr_un *sunaddr, int addr_len)
29162306a36Sopenharmony_ci{
29262306a36Sopenharmony_ci	struct sockaddr_storage *addr = (struct sockaddr_storage *)sunaddr;
29362306a36Sopenharmony_ci	short offset = offsetof(struct sockaddr_storage, __data);
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci	BUILD_BUG_ON(offset != offsetof(struct sockaddr_un, sun_path));
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci	/* This may look like an off by one error but it is a bit more
29862306a36Sopenharmony_ci	 * subtle.  108 is the longest valid AF_UNIX path for a binding.
29962306a36Sopenharmony_ci	 * sun_path[108] doesn't as such exist.  However in kernel space
30062306a36Sopenharmony_ci	 * we are guaranteed that it is a valid memory location in our
30162306a36Sopenharmony_ci	 * kernel address buffer because syscall functions always pass
30262306a36Sopenharmony_ci	 * a pointer of struct sockaddr_storage which has a bigger buffer
30362306a36Sopenharmony_ci	 * than 108.  Also, we must terminate sun_path for strlen() in
30462306a36Sopenharmony_ci	 * getname_kernel().
30562306a36Sopenharmony_ci	 */
30662306a36Sopenharmony_ci	addr->__data[addr_len - offset] = 0;
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	/* Don't pass sunaddr->sun_path to strlen().  Otherwise, 108 will
30962306a36Sopenharmony_ci	 * cause panic if CONFIG_FORTIFY_SOURCE=y.  Let __fortify_strlen()
31062306a36Sopenharmony_ci	 * know the actual buffer.
31162306a36Sopenharmony_ci	 */
31262306a36Sopenharmony_ci	return strlen(addr->__data) + offset + 1;
31362306a36Sopenharmony_ci}
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_cistatic void __unix_remove_socket(struct sock *sk)
31662306a36Sopenharmony_ci{
31762306a36Sopenharmony_ci	sk_del_node_init(sk);
31862306a36Sopenharmony_ci}
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_cistatic void __unix_insert_socket(struct net *net, struct sock *sk)
32162306a36Sopenharmony_ci{
32262306a36Sopenharmony_ci	DEBUG_NET_WARN_ON_ONCE(!sk_unhashed(sk));
32362306a36Sopenharmony_ci	sk_add_node(sk, &net->unx.table.buckets[sk->sk_hash]);
32462306a36Sopenharmony_ci}
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_cistatic void __unix_set_addr_hash(struct net *net, struct sock *sk,
32762306a36Sopenharmony_ci				 struct unix_address *addr, unsigned int hash)
32862306a36Sopenharmony_ci{
32962306a36Sopenharmony_ci	__unix_remove_socket(sk);
33062306a36Sopenharmony_ci	smp_store_release(&unix_sk(sk)->addr, addr);
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci	sk->sk_hash = hash;
33362306a36Sopenharmony_ci	__unix_insert_socket(net, sk);
33462306a36Sopenharmony_ci}
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_cistatic void unix_remove_socket(struct net *net, struct sock *sk)
33762306a36Sopenharmony_ci{
33862306a36Sopenharmony_ci	spin_lock(&net->unx.table.locks[sk->sk_hash]);
33962306a36Sopenharmony_ci	__unix_remove_socket(sk);
34062306a36Sopenharmony_ci	spin_unlock(&net->unx.table.locks[sk->sk_hash]);
34162306a36Sopenharmony_ci}
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_cistatic void unix_insert_unbound_socket(struct net *net, struct sock *sk)
34462306a36Sopenharmony_ci{
34562306a36Sopenharmony_ci	spin_lock(&net->unx.table.locks[sk->sk_hash]);
34662306a36Sopenharmony_ci	__unix_insert_socket(net, sk);
34762306a36Sopenharmony_ci	spin_unlock(&net->unx.table.locks[sk->sk_hash]);
34862306a36Sopenharmony_ci}
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_cistatic void unix_insert_bsd_socket(struct sock *sk)
35162306a36Sopenharmony_ci{
35262306a36Sopenharmony_ci	spin_lock(&bsd_socket_locks[sk->sk_hash]);
35362306a36Sopenharmony_ci	sk_add_bind_node(sk, &bsd_socket_buckets[sk->sk_hash]);
35462306a36Sopenharmony_ci	spin_unlock(&bsd_socket_locks[sk->sk_hash]);
35562306a36Sopenharmony_ci}
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_cistatic void unix_remove_bsd_socket(struct sock *sk)
35862306a36Sopenharmony_ci{
35962306a36Sopenharmony_ci	if (!hlist_unhashed(&sk->sk_bind_node)) {
36062306a36Sopenharmony_ci		spin_lock(&bsd_socket_locks[sk->sk_hash]);
36162306a36Sopenharmony_ci		__sk_del_bind_node(sk);
36262306a36Sopenharmony_ci		spin_unlock(&bsd_socket_locks[sk->sk_hash]);
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci		sk_node_init(&sk->sk_bind_node);
36562306a36Sopenharmony_ci	}
36662306a36Sopenharmony_ci}
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_cistatic struct sock *__unix_find_socket_byname(struct net *net,
36962306a36Sopenharmony_ci					      struct sockaddr_un *sunname,
37062306a36Sopenharmony_ci					      int len, unsigned int hash)
37162306a36Sopenharmony_ci{
37262306a36Sopenharmony_ci	struct sock *s;
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci	sk_for_each(s, &net->unx.table.buckets[hash]) {
37562306a36Sopenharmony_ci		struct unix_sock *u = unix_sk(s);
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci		if (u->addr->len == len &&
37862306a36Sopenharmony_ci		    !memcmp(u->addr->name, sunname, len))
37962306a36Sopenharmony_ci			return s;
38062306a36Sopenharmony_ci	}
38162306a36Sopenharmony_ci	return NULL;
38262306a36Sopenharmony_ci}
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_cistatic inline struct sock *unix_find_socket_byname(struct net *net,
38562306a36Sopenharmony_ci						   struct sockaddr_un *sunname,
38662306a36Sopenharmony_ci						   int len, unsigned int hash)
38762306a36Sopenharmony_ci{
38862306a36Sopenharmony_ci	struct sock *s;
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci	spin_lock(&net->unx.table.locks[hash]);
39162306a36Sopenharmony_ci	s = __unix_find_socket_byname(net, sunname, len, hash);
39262306a36Sopenharmony_ci	if (s)
39362306a36Sopenharmony_ci		sock_hold(s);
39462306a36Sopenharmony_ci	spin_unlock(&net->unx.table.locks[hash]);
39562306a36Sopenharmony_ci	return s;
39662306a36Sopenharmony_ci}
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_cistatic struct sock *unix_find_socket_byinode(struct inode *i)
39962306a36Sopenharmony_ci{
40062306a36Sopenharmony_ci	unsigned int hash = unix_bsd_hash(i);
40162306a36Sopenharmony_ci	struct sock *s;
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ci	spin_lock(&bsd_socket_locks[hash]);
40462306a36Sopenharmony_ci	sk_for_each_bound(s, &bsd_socket_buckets[hash]) {
40562306a36Sopenharmony_ci		struct dentry *dentry = unix_sk(s)->path.dentry;
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ci		if (dentry && d_backing_inode(dentry) == i) {
40862306a36Sopenharmony_ci			sock_hold(s);
40962306a36Sopenharmony_ci			spin_unlock(&bsd_socket_locks[hash]);
41062306a36Sopenharmony_ci			return s;
41162306a36Sopenharmony_ci		}
41262306a36Sopenharmony_ci	}
41362306a36Sopenharmony_ci	spin_unlock(&bsd_socket_locks[hash]);
41462306a36Sopenharmony_ci	return NULL;
41562306a36Sopenharmony_ci}
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci/* Support code for asymmetrically connected dgram sockets
41862306a36Sopenharmony_ci *
41962306a36Sopenharmony_ci * If a datagram socket is connected to a socket not itself connected
42062306a36Sopenharmony_ci * to the first socket (eg, /dev/log), clients may only enqueue more
42162306a36Sopenharmony_ci * messages if the present receive queue of the server socket is not
42262306a36Sopenharmony_ci * "too large". This means there's a second writeability condition
42362306a36Sopenharmony_ci * poll and sendmsg need to test. The dgram recv code will do a wake
42462306a36Sopenharmony_ci * up on the peer_wait wait queue of a socket upon reception of a
42562306a36Sopenharmony_ci * datagram which needs to be propagated to sleeping would-be writers
42662306a36Sopenharmony_ci * since these might not have sent anything so far. This can't be
42762306a36Sopenharmony_ci * accomplished via poll_wait because the lifetime of the server
42862306a36Sopenharmony_ci * socket might be less than that of its clients if these break their
42962306a36Sopenharmony_ci * association with it or if the server socket is closed while clients
43062306a36Sopenharmony_ci * are still connected to it and there's no way to inform "a polling
43162306a36Sopenharmony_ci * implementation" that it should let go of a certain wait queue
43262306a36Sopenharmony_ci *
43362306a36Sopenharmony_ci * In order to propagate a wake up, a wait_queue_entry_t of the client
43462306a36Sopenharmony_ci * socket is enqueued on the peer_wait queue of the server socket
43562306a36Sopenharmony_ci * whose wake function does a wake_up on the ordinary client socket
43662306a36Sopenharmony_ci * wait queue. This connection is established whenever a write (or
43762306a36Sopenharmony_ci * poll for write) hit the flow control condition and broken when the
43862306a36Sopenharmony_ci * association to the server socket is dissolved or after a wake up
43962306a36Sopenharmony_ci * was relayed.
44062306a36Sopenharmony_ci */
44162306a36Sopenharmony_ci
44262306a36Sopenharmony_cistatic int unix_dgram_peer_wake_relay(wait_queue_entry_t *q, unsigned mode, int flags,
44362306a36Sopenharmony_ci				      void *key)
44462306a36Sopenharmony_ci{
44562306a36Sopenharmony_ci	struct unix_sock *u;
44662306a36Sopenharmony_ci	wait_queue_head_t *u_sleep;
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci	u = container_of(q, struct unix_sock, peer_wake);
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci	__remove_wait_queue(&unix_sk(u->peer_wake.private)->peer_wait,
45162306a36Sopenharmony_ci			    q);
45262306a36Sopenharmony_ci	u->peer_wake.private = NULL;
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	/* relaying can only happen while the wq still exists */
45562306a36Sopenharmony_ci	u_sleep = sk_sleep(&u->sk);
45662306a36Sopenharmony_ci	if (u_sleep)
45762306a36Sopenharmony_ci		wake_up_interruptible_poll(u_sleep, key_to_poll(key));
45862306a36Sopenharmony_ci
45962306a36Sopenharmony_ci	return 0;
46062306a36Sopenharmony_ci}
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_cistatic int unix_dgram_peer_wake_connect(struct sock *sk, struct sock *other)
46362306a36Sopenharmony_ci{
46462306a36Sopenharmony_ci	struct unix_sock *u, *u_other;
46562306a36Sopenharmony_ci	int rc;
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ci	u = unix_sk(sk);
46862306a36Sopenharmony_ci	u_other = unix_sk(other);
46962306a36Sopenharmony_ci	rc = 0;
47062306a36Sopenharmony_ci	spin_lock(&u_other->peer_wait.lock);
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci	if (!u->peer_wake.private) {
47362306a36Sopenharmony_ci		u->peer_wake.private = other;
47462306a36Sopenharmony_ci		__add_wait_queue(&u_other->peer_wait, &u->peer_wake);
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci		rc = 1;
47762306a36Sopenharmony_ci	}
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci	spin_unlock(&u_other->peer_wait.lock);
48062306a36Sopenharmony_ci	return rc;
48162306a36Sopenharmony_ci}
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_cistatic void unix_dgram_peer_wake_disconnect(struct sock *sk,
48462306a36Sopenharmony_ci					    struct sock *other)
48562306a36Sopenharmony_ci{
48662306a36Sopenharmony_ci	struct unix_sock *u, *u_other;
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_ci	u = unix_sk(sk);
48962306a36Sopenharmony_ci	u_other = unix_sk(other);
49062306a36Sopenharmony_ci	spin_lock(&u_other->peer_wait.lock);
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci	if (u->peer_wake.private == other) {
49362306a36Sopenharmony_ci		__remove_wait_queue(&u_other->peer_wait, &u->peer_wake);
49462306a36Sopenharmony_ci		u->peer_wake.private = NULL;
49562306a36Sopenharmony_ci	}
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_ci	spin_unlock(&u_other->peer_wait.lock);
49862306a36Sopenharmony_ci}
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_cistatic void unix_dgram_peer_wake_disconnect_wakeup(struct sock *sk,
50162306a36Sopenharmony_ci						   struct sock *other)
50262306a36Sopenharmony_ci{
50362306a36Sopenharmony_ci	unix_dgram_peer_wake_disconnect(sk, other);
50462306a36Sopenharmony_ci	wake_up_interruptible_poll(sk_sleep(sk),
50562306a36Sopenharmony_ci				   EPOLLOUT |
50662306a36Sopenharmony_ci				   EPOLLWRNORM |
50762306a36Sopenharmony_ci				   EPOLLWRBAND);
50862306a36Sopenharmony_ci}
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_ci/* preconditions:
51162306a36Sopenharmony_ci *	- unix_peer(sk) == other
51262306a36Sopenharmony_ci *	- association is stable
51362306a36Sopenharmony_ci */
51462306a36Sopenharmony_cistatic int unix_dgram_peer_wake_me(struct sock *sk, struct sock *other)
51562306a36Sopenharmony_ci{
51662306a36Sopenharmony_ci	int connected;
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_ci	connected = unix_dgram_peer_wake_connect(sk, other);
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci	/* If other is SOCK_DEAD, we want to make sure we signal
52162306a36Sopenharmony_ci	 * POLLOUT, such that a subsequent write() can get a
52262306a36Sopenharmony_ci	 * -ECONNREFUSED. Otherwise, if we haven't queued any skbs
52362306a36Sopenharmony_ci	 * to other and its full, we will hang waiting for POLLOUT.
52462306a36Sopenharmony_ci	 */
52562306a36Sopenharmony_ci	if (unix_recvq_full_lockless(other) && !sock_flag(other, SOCK_DEAD))
52662306a36Sopenharmony_ci		return 1;
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci	if (connected)
52962306a36Sopenharmony_ci		unix_dgram_peer_wake_disconnect(sk, other);
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_ci	return 0;
53262306a36Sopenharmony_ci}
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_cistatic int unix_writable(const struct sock *sk)
53562306a36Sopenharmony_ci{
53662306a36Sopenharmony_ci	return sk->sk_state != TCP_LISTEN &&
53762306a36Sopenharmony_ci	       (refcount_read(&sk->sk_wmem_alloc) << 2) <= sk->sk_sndbuf;
53862306a36Sopenharmony_ci}
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_cistatic void unix_write_space(struct sock *sk)
54162306a36Sopenharmony_ci{
54262306a36Sopenharmony_ci	struct socket_wq *wq;
54362306a36Sopenharmony_ci
54462306a36Sopenharmony_ci	rcu_read_lock();
54562306a36Sopenharmony_ci	if (unix_writable(sk)) {
54662306a36Sopenharmony_ci		wq = rcu_dereference(sk->sk_wq);
54762306a36Sopenharmony_ci		if (skwq_has_sleeper(wq))
54862306a36Sopenharmony_ci			wake_up_interruptible_sync_poll(&wq->wait,
54962306a36Sopenharmony_ci				EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND);
55062306a36Sopenharmony_ci		sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
55162306a36Sopenharmony_ci	}
55262306a36Sopenharmony_ci	rcu_read_unlock();
55362306a36Sopenharmony_ci}
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci/* When dgram socket disconnects (or changes its peer), we clear its receive
55662306a36Sopenharmony_ci * queue of packets arrived from previous peer. First, it allows to do
55762306a36Sopenharmony_ci * flow control based only on wmem_alloc; second, sk connected to peer
55862306a36Sopenharmony_ci * may receive messages only from that peer. */
55962306a36Sopenharmony_cistatic void unix_dgram_disconnected(struct sock *sk, struct sock *other)
56062306a36Sopenharmony_ci{
56162306a36Sopenharmony_ci	if (!skb_queue_empty(&sk->sk_receive_queue)) {
56262306a36Sopenharmony_ci		skb_queue_purge(&sk->sk_receive_queue);
56362306a36Sopenharmony_ci		wake_up_interruptible_all(&unix_sk(sk)->peer_wait);
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ci		/* If one link of bidirectional dgram pipe is disconnected,
56662306a36Sopenharmony_ci		 * we signal error. Messages are lost. Do not make this,
56762306a36Sopenharmony_ci		 * when peer was not connected to us.
56862306a36Sopenharmony_ci		 */
56962306a36Sopenharmony_ci		if (!sock_flag(other, SOCK_DEAD) && unix_peer(other) == sk) {
57062306a36Sopenharmony_ci			WRITE_ONCE(other->sk_err, ECONNRESET);
57162306a36Sopenharmony_ci			sk_error_report(other);
57262306a36Sopenharmony_ci		}
57362306a36Sopenharmony_ci	}
57462306a36Sopenharmony_ci	other->sk_state = TCP_CLOSE;
57562306a36Sopenharmony_ci}
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_cistatic void unix_sock_destructor(struct sock *sk)
57862306a36Sopenharmony_ci{
57962306a36Sopenharmony_ci	struct unix_sock *u = unix_sk(sk);
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_ci	skb_queue_purge(&sk->sk_receive_queue);
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_ci	DEBUG_NET_WARN_ON_ONCE(refcount_read(&sk->sk_wmem_alloc));
58462306a36Sopenharmony_ci	DEBUG_NET_WARN_ON_ONCE(!sk_unhashed(sk));
58562306a36Sopenharmony_ci	DEBUG_NET_WARN_ON_ONCE(sk->sk_socket);
58662306a36Sopenharmony_ci	if (!sock_flag(sk, SOCK_DEAD)) {
58762306a36Sopenharmony_ci		pr_info("Attempt to release alive unix socket: %p\n", sk);
58862306a36Sopenharmony_ci		return;
58962306a36Sopenharmony_ci	}
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci	if (u->addr)
59262306a36Sopenharmony_ci		unix_release_addr(u->addr);
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_ci	atomic_long_dec(&unix_nr_socks);
59562306a36Sopenharmony_ci	sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
59662306a36Sopenharmony_ci#ifdef UNIX_REFCNT_DEBUG
59762306a36Sopenharmony_ci	pr_debug("UNIX %p is destroyed, %ld are still alive.\n", sk,
59862306a36Sopenharmony_ci		atomic_long_read(&unix_nr_socks));
59962306a36Sopenharmony_ci#endif
60062306a36Sopenharmony_ci}
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_cistatic void unix_release_sock(struct sock *sk, int embrion)
60362306a36Sopenharmony_ci{
60462306a36Sopenharmony_ci	struct unix_sock *u = unix_sk(sk);
60562306a36Sopenharmony_ci	struct sock *skpair;
60662306a36Sopenharmony_ci	struct sk_buff *skb;
60762306a36Sopenharmony_ci	struct path path;
60862306a36Sopenharmony_ci	int state;
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_ci	unix_remove_socket(sock_net(sk), sk);
61162306a36Sopenharmony_ci	unix_remove_bsd_socket(sk);
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_ci	/* Clear state */
61462306a36Sopenharmony_ci	unix_state_lock(sk);
61562306a36Sopenharmony_ci	sock_orphan(sk);
61662306a36Sopenharmony_ci	WRITE_ONCE(sk->sk_shutdown, SHUTDOWN_MASK);
61762306a36Sopenharmony_ci	path	     = u->path;
61862306a36Sopenharmony_ci	u->path.dentry = NULL;
61962306a36Sopenharmony_ci	u->path.mnt = NULL;
62062306a36Sopenharmony_ci	state = sk->sk_state;
62162306a36Sopenharmony_ci	sk->sk_state = TCP_CLOSE;
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_ci	skpair = unix_peer(sk);
62462306a36Sopenharmony_ci	unix_peer(sk) = NULL;
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_ci	unix_state_unlock(sk);
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_AF_UNIX_OOB)
62962306a36Sopenharmony_ci	if (u->oob_skb) {
63062306a36Sopenharmony_ci		kfree_skb(u->oob_skb);
63162306a36Sopenharmony_ci		u->oob_skb = NULL;
63262306a36Sopenharmony_ci	}
63362306a36Sopenharmony_ci#endif
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_ci	wake_up_interruptible_all(&u->peer_wait);
63662306a36Sopenharmony_ci
63762306a36Sopenharmony_ci	if (skpair != NULL) {
63862306a36Sopenharmony_ci		if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) {
63962306a36Sopenharmony_ci			unix_state_lock(skpair);
64062306a36Sopenharmony_ci			/* No more writes */
64162306a36Sopenharmony_ci			WRITE_ONCE(skpair->sk_shutdown, SHUTDOWN_MASK);
64262306a36Sopenharmony_ci			if (!skb_queue_empty(&sk->sk_receive_queue) || embrion)
64362306a36Sopenharmony_ci				WRITE_ONCE(skpair->sk_err, ECONNRESET);
64462306a36Sopenharmony_ci			unix_state_unlock(skpair);
64562306a36Sopenharmony_ci			skpair->sk_state_change(skpair);
64662306a36Sopenharmony_ci			sk_wake_async(skpair, SOCK_WAKE_WAITD, POLL_HUP);
64762306a36Sopenharmony_ci		}
64862306a36Sopenharmony_ci
64962306a36Sopenharmony_ci		unix_dgram_peer_wake_disconnect(sk, skpair);
65062306a36Sopenharmony_ci		sock_put(skpair); /* It may now die */
65162306a36Sopenharmony_ci	}
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_ci	/* Try to flush out this socket. Throw out buffers at least */
65462306a36Sopenharmony_ci
65562306a36Sopenharmony_ci	while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
65662306a36Sopenharmony_ci		if (state == TCP_LISTEN)
65762306a36Sopenharmony_ci			unix_release_sock(skb->sk, 1);
65862306a36Sopenharmony_ci		/* passed fds are erased in the kfree_skb hook	      */
65962306a36Sopenharmony_ci		UNIXCB(skb).consumed = skb->len;
66062306a36Sopenharmony_ci		kfree_skb(skb);
66162306a36Sopenharmony_ci	}
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ci	if (path.dentry)
66462306a36Sopenharmony_ci		path_put(&path);
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ci	sock_put(sk);
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_ci	/* ---- Socket is dead now and most probably destroyed ---- */
66962306a36Sopenharmony_ci
67062306a36Sopenharmony_ci	/*
67162306a36Sopenharmony_ci	 * Fixme: BSD difference: In BSD all sockets connected to us get
67262306a36Sopenharmony_ci	 *	  ECONNRESET and we die on the spot. In Linux we behave
67362306a36Sopenharmony_ci	 *	  like files and pipes do and wait for the last
67462306a36Sopenharmony_ci	 *	  dereference.
67562306a36Sopenharmony_ci	 *
67662306a36Sopenharmony_ci	 * Can't we simply set sock->err?
67762306a36Sopenharmony_ci	 *
67862306a36Sopenharmony_ci	 *	  What the above comment does talk about? --ANK(980817)
67962306a36Sopenharmony_ci	 */
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_ci	if (READ_ONCE(unix_tot_inflight))
68262306a36Sopenharmony_ci		unix_gc();		/* Garbage collect fds */
68362306a36Sopenharmony_ci}
68462306a36Sopenharmony_ci
68562306a36Sopenharmony_cistatic void init_peercred(struct sock *sk)
68662306a36Sopenharmony_ci{
68762306a36Sopenharmony_ci	const struct cred *old_cred;
68862306a36Sopenharmony_ci	struct pid *old_pid;
68962306a36Sopenharmony_ci
69062306a36Sopenharmony_ci	spin_lock(&sk->sk_peer_lock);
69162306a36Sopenharmony_ci	old_pid = sk->sk_peer_pid;
69262306a36Sopenharmony_ci	old_cred = sk->sk_peer_cred;
69362306a36Sopenharmony_ci	sk->sk_peer_pid  = get_pid(task_tgid(current));
69462306a36Sopenharmony_ci	sk->sk_peer_cred = get_current_cred();
69562306a36Sopenharmony_ci	spin_unlock(&sk->sk_peer_lock);
69662306a36Sopenharmony_ci
69762306a36Sopenharmony_ci	put_pid(old_pid);
69862306a36Sopenharmony_ci	put_cred(old_cred);
69962306a36Sopenharmony_ci}
70062306a36Sopenharmony_ci
70162306a36Sopenharmony_cistatic void copy_peercred(struct sock *sk, struct sock *peersk)
70262306a36Sopenharmony_ci{
70362306a36Sopenharmony_ci	const struct cred *old_cred;
70462306a36Sopenharmony_ci	struct pid *old_pid;
70562306a36Sopenharmony_ci
70662306a36Sopenharmony_ci	if (sk < peersk) {
70762306a36Sopenharmony_ci		spin_lock(&sk->sk_peer_lock);
70862306a36Sopenharmony_ci		spin_lock_nested(&peersk->sk_peer_lock, SINGLE_DEPTH_NESTING);
70962306a36Sopenharmony_ci	} else {
71062306a36Sopenharmony_ci		spin_lock(&peersk->sk_peer_lock);
71162306a36Sopenharmony_ci		spin_lock_nested(&sk->sk_peer_lock, SINGLE_DEPTH_NESTING);
71262306a36Sopenharmony_ci	}
71362306a36Sopenharmony_ci	old_pid = sk->sk_peer_pid;
71462306a36Sopenharmony_ci	old_cred = sk->sk_peer_cred;
71562306a36Sopenharmony_ci	sk->sk_peer_pid  = get_pid(peersk->sk_peer_pid);
71662306a36Sopenharmony_ci	sk->sk_peer_cred = get_cred(peersk->sk_peer_cred);
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ci	spin_unlock(&sk->sk_peer_lock);
71962306a36Sopenharmony_ci	spin_unlock(&peersk->sk_peer_lock);
72062306a36Sopenharmony_ci
72162306a36Sopenharmony_ci	put_pid(old_pid);
72262306a36Sopenharmony_ci	put_cred(old_cred);
72362306a36Sopenharmony_ci}
72462306a36Sopenharmony_ci
72562306a36Sopenharmony_cistatic int unix_listen(struct socket *sock, int backlog)
72662306a36Sopenharmony_ci{
72762306a36Sopenharmony_ci	int err;
72862306a36Sopenharmony_ci	struct sock *sk = sock->sk;
72962306a36Sopenharmony_ci	struct unix_sock *u = unix_sk(sk);
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci	err = -EOPNOTSUPP;
73262306a36Sopenharmony_ci	if (sock->type != SOCK_STREAM && sock->type != SOCK_SEQPACKET)
73362306a36Sopenharmony_ci		goto out;	/* Only stream/seqpacket sockets accept */
73462306a36Sopenharmony_ci	err = -EINVAL;
73562306a36Sopenharmony_ci	if (!u->addr)
73662306a36Sopenharmony_ci		goto out;	/* No listens on an unbound socket */
73762306a36Sopenharmony_ci	unix_state_lock(sk);
73862306a36Sopenharmony_ci	if (sk->sk_state != TCP_CLOSE && sk->sk_state != TCP_LISTEN)
73962306a36Sopenharmony_ci		goto out_unlock;
74062306a36Sopenharmony_ci	if (backlog > sk->sk_max_ack_backlog)
74162306a36Sopenharmony_ci		wake_up_interruptible_all(&u->peer_wait);
74262306a36Sopenharmony_ci	sk->sk_max_ack_backlog	= backlog;
74362306a36Sopenharmony_ci	sk->sk_state		= TCP_LISTEN;
74462306a36Sopenharmony_ci	/* set credentials so connect can copy them */
74562306a36Sopenharmony_ci	init_peercred(sk);
74662306a36Sopenharmony_ci	err = 0;
74762306a36Sopenharmony_ci
74862306a36Sopenharmony_ciout_unlock:
74962306a36Sopenharmony_ci	unix_state_unlock(sk);
75062306a36Sopenharmony_ciout:
75162306a36Sopenharmony_ci	return err;
75262306a36Sopenharmony_ci}
75362306a36Sopenharmony_ci
75462306a36Sopenharmony_cistatic int unix_release(struct socket *);
75562306a36Sopenharmony_cistatic int unix_bind(struct socket *, struct sockaddr *, int);
75662306a36Sopenharmony_cistatic int unix_stream_connect(struct socket *, struct sockaddr *,
75762306a36Sopenharmony_ci			       int addr_len, int flags);
75862306a36Sopenharmony_cistatic int unix_socketpair(struct socket *, struct socket *);
75962306a36Sopenharmony_cistatic int unix_accept(struct socket *, struct socket *, int, bool);
76062306a36Sopenharmony_cistatic int unix_getname(struct socket *, struct sockaddr *, int);
76162306a36Sopenharmony_cistatic __poll_t unix_poll(struct file *, struct socket *, poll_table *);
76262306a36Sopenharmony_cistatic __poll_t unix_dgram_poll(struct file *, struct socket *,
76362306a36Sopenharmony_ci				    poll_table *);
76462306a36Sopenharmony_cistatic int unix_ioctl(struct socket *, unsigned int, unsigned long);
76562306a36Sopenharmony_ci#ifdef CONFIG_COMPAT
76662306a36Sopenharmony_cistatic int unix_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
76762306a36Sopenharmony_ci#endif
76862306a36Sopenharmony_cistatic int unix_shutdown(struct socket *, int);
76962306a36Sopenharmony_cistatic int unix_stream_sendmsg(struct socket *, struct msghdr *, size_t);
77062306a36Sopenharmony_cistatic int unix_stream_recvmsg(struct socket *, struct msghdr *, size_t, int);
77162306a36Sopenharmony_cistatic ssize_t unix_stream_splice_read(struct socket *,  loff_t *ppos,
77262306a36Sopenharmony_ci				       struct pipe_inode_info *, size_t size,
77362306a36Sopenharmony_ci				       unsigned int flags);
77462306a36Sopenharmony_cistatic int unix_dgram_sendmsg(struct socket *, struct msghdr *, size_t);
77562306a36Sopenharmony_cistatic int unix_dgram_recvmsg(struct socket *, struct msghdr *, size_t, int);
77662306a36Sopenharmony_cistatic int unix_read_skb(struct sock *sk, skb_read_actor_t recv_actor);
77762306a36Sopenharmony_cistatic int unix_stream_read_skb(struct sock *sk, skb_read_actor_t recv_actor);
77862306a36Sopenharmony_cistatic int unix_dgram_connect(struct socket *, struct sockaddr *,
77962306a36Sopenharmony_ci			      int, int);
78062306a36Sopenharmony_cistatic int unix_seqpacket_sendmsg(struct socket *, struct msghdr *, size_t);
78162306a36Sopenharmony_cistatic int unix_seqpacket_recvmsg(struct socket *, struct msghdr *, size_t,
78262306a36Sopenharmony_ci				  int);
78362306a36Sopenharmony_ci
78462306a36Sopenharmony_cistatic int unix_set_peek_off(struct sock *sk, int val)
78562306a36Sopenharmony_ci{
78662306a36Sopenharmony_ci	struct unix_sock *u = unix_sk(sk);
78762306a36Sopenharmony_ci
78862306a36Sopenharmony_ci	if (mutex_lock_interruptible(&u->iolock))
78962306a36Sopenharmony_ci		return -EINTR;
79062306a36Sopenharmony_ci
79162306a36Sopenharmony_ci	WRITE_ONCE(sk->sk_peek_off, val);
79262306a36Sopenharmony_ci	mutex_unlock(&u->iolock);
79362306a36Sopenharmony_ci
79462306a36Sopenharmony_ci	return 0;
79562306a36Sopenharmony_ci}
79662306a36Sopenharmony_ci
79762306a36Sopenharmony_ci#ifdef CONFIG_PROC_FS
79862306a36Sopenharmony_cistatic int unix_count_nr_fds(struct sock *sk)
79962306a36Sopenharmony_ci{
80062306a36Sopenharmony_ci	struct sk_buff *skb;
80162306a36Sopenharmony_ci	struct unix_sock *u;
80262306a36Sopenharmony_ci	int nr_fds = 0;
80362306a36Sopenharmony_ci
80462306a36Sopenharmony_ci	spin_lock(&sk->sk_receive_queue.lock);
80562306a36Sopenharmony_ci	skb = skb_peek(&sk->sk_receive_queue);
80662306a36Sopenharmony_ci	while (skb) {
80762306a36Sopenharmony_ci		u = unix_sk(skb->sk);
80862306a36Sopenharmony_ci		nr_fds += atomic_read(&u->scm_stat.nr_fds);
80962306a36Sopenharmony_ci		skb = skb_peek_next(skb, &sk->sk_receive_queue);
81062306a36Sopenharmony_ci	}
81162306a36Sopenharmony_ci	spin_unlock(&sk->sk_receive_queue.lock);
81262306a36Sopenharmony_ci
81362306a36Sopenharmony_ci	return nr_fds;
81462306a36Sopenharmony_ci}
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_cistatic void unix_show_fdinfo(struct seq_file *m, struct socket *sock)
81762306a36Sopenharmony_ci{
81862306a36Sopenharmony_ci	struct sock *sk = sock->sk;
81962306a36Sopenharmony_ci	unsigned char s_state;
82062306a36Sopenharmony_ci	struct unix_sock *u;
82162306a36Sopenharmony_ci	int nr_fds = 0;
82262306a36Sopenharmony_ci
82362306a36Sopenharmony_ci	if (sk) {
82462306a36Sopenharmony_ci		s_state = READ_ONCE(sk->sk_state);
82562306a36Sopenharmony_ci		u = unix_sk(sk);
82662306a36Sopenharmony_ci
82762306a36Sopenharmony_ci		/* SOCK_STREAM and SOCK_SEQPACKET sockets never change their
82862306a36Sopenharmony_ci		 * sk_state after switching to TCP_ESTABLISHED or TCP_LISTEN.
82962306a36Sopenharmony_ci		 * SOCK_DGRAM is ordinary. So, no lock is needed.
83062306a36Sopenharmony_ci		 */
83162306a36Sopenharmony_ci		if (sock->type == SOCK_DGRAM || s_state == TCP_ESTABLISHED)
83262306a36Sopenharmony_ci			nr_fds = atomic_read(&u->scm_stat.nr_fds);
83362306a36Sopenharmony_ci		else if (s_state == TCP_LISTEN)
83462306a36Sopenharmony_ci			nr_fds = unix_count_nr_fds(sk);
83562306a36Sopenharmony_ci
83662306a36Sopenharmony_ci		seq_printf(m, "scm_fds: %u\n", nr_fds);
83762306a36Sopenharmony_ci	}
83862306a36Sopenharmony_ci}
83962306a36Sopenharmony_ci#else
84062306a36Sopenharmony_ci#define unix_show_fdinfo NULL
84162306a36Sopenharmony_ci#endif
84262306a36Sopenharmony_ci
84362306a36Sopenharmony_cistatic const struct proto_ops unix_stream_ops = {
84462306a36Sopenharmony_ci	.family =	PF_UNIX,
84562306a36Sopenharmony_ci	.owner =	THIS_MODULE,
84662306a36Sopenharmony_ci	.release =	unix_release,
84762306a36Sopenharmony_ci	.bind =		unix_bind,
84862306a36Sopenharmony_ci	.connect =	unix_stream_connect,
84962306a36Sopenharmony_ci	.socketpair =	unix_socketpair,
85062306a36Sopenharmony_ci	.accept =	unix_accept,
85162306a36Sopenharmony_ci	.getname =	unix_getname,
85262306a36Sopenharmony_ci	.poll =		unix_poll,
85362306a36Sopenharmony_ci	.ioctl =	unix_ioctl,
85462306a36Sopenharmony_ci#ifdef CONFIG_COMPAT
85562306a36Sopenharmony_ci	.compat_ioctl =	unix_compat_ioctl,
85662306a36Sopenharmony_ci#endif
85762306a36Sopenharmony_ci	.listen =	unix_listen,
85862306a36Sopenharmony_ci	.shutdown =	unix_shutdown,
85962306a36Sopenharmony_ci	.sendmsg =	unix_stream_sendmsg,
86062306a36Sopenharmony_ci	.recvmsg =	unix_stream_recvmsg,
86162306a36Sopenharmony_ci	.read_skb =	unix_stream_read_skb,
86262306a36Sopenharmony_ci	.mmap =		sock_no_mmap,
86362306a36Sopenharmony_ci	.splice_read =	unix_stream_splice_read,
86462306a36Sopenharmony_ci	.set_peek_off =	unix_set_peek_off,
86562306a36Sopenharmony_ci	.show_fdinfo =	unix_show_fdinfo,
86662306a36Sopenharmony_ci};
86762306a36Sopenharmony_ci
86862306a36Sopenharmony_cistatic const struct proto_ops unix_dgram_ops = {
86962306a36Sopenharmony_ci	.family =	PF_UNIX,
87062306a36Sopenharmony_ci	.owner =	THIS_MODULE,
87162306a36Sopenharmony_ci	.release =	unix_release,
87262306a36Sopenharmony_ci	.bind =		unix_bind,
87362306a36Sopenharmony_ci	.connect =	unix_dgram_connect,
87462306a36Sopenharmony_ci	.socketpair =	unix_socketpair,
87562306a36Sopenharmony_ci	.accept =	sock_no_accept,
87662306a36Sopenharmony_ci	.getname =	unix_getname,
87762306a36Sopenharmony_ci	.poll =		unix_dgram_poll,
87862306a36Sopenharmony_ci	.ioctl =	unix_ioctl,
87962306a36Sopenharmony_ci#ifdef CONFIG_COMPAT
88062306a36Sopenharmony_ci	.compat_ioctl =	unix_compat_ioctl,
88162306a36Sopenharmony_ci#endif
88262306a36Sopenharmony_ci	.listen =	sock_no_listen,
88362306a36Sopenharmony_ci	.shutdown =	unix_shutdown,
88462306a36Sopenharmony_ci	.sendmsg =	unix_dgram_sendmsg,
88562306a36Sopenharmony_ci	.read_skb =	unix_read_skb,
88662306a36Sopenharmony_ci	.recvmsg =	unix_dgram_recvmsg,
88762306a36Sopenharmony_ci	.mmap =		sock_no_mmap,
88862306a36Sopenharmony_ci	.set_peek_off =	unix_set_peek_off,
88962306a36Sopenharmony_ci	.show_fdinfo =	unix_show_fdinfo,
89062306a36Sopenharmony_ci};
89162306a36Sopenharmony_ci
89262306a36Sopenharmony_cistatic const struct proto_ops unix_seqpacket_ops = {
89362306a36Sopenharmony_ci	.family =	PF_UNIX,
89462306a36Sopenharmony_ci	.owner =	THIS_MODULE,
89562306a36Sopenharmony_ci	.release =	unix_release,
89662306a36Sopenharmony_ci	.bind =		unix_bind,
89762306a36Sopenharmony_ci	.connect =	unix_stream_connect,
89862306a36Sopenharmony_ci	.socketpair =	unix_socketpair,
89962306a36Sopenharmony_ci	.accept =	unix_accept,
90062306a36Sopenharmony_ci	.getname =	unix_getname,
90162306a36Sopenharmony_ci	.poll =		unix_dgram_poll,
90262306a36Sopenharmony_ci	.ioctl =	unix_ioctl,
90362306a36Sopenharmony_ci#ifdef CONFIG_COMPAT
90462306a36Sopenharmony_ci	.compat_ioctl =	unix_compat_ioctl,
90562306a36Sopenharmony_ci#endif
90662306a36Sopenharmony_ci	.listen =	unix_listen,
90762306a36Sopenharmony_ci	.shutdown =	unix_shutdown,
90862306a36Sopenharmony_ci	.sendmsg =	unix_seqpacket_sendmsg,
90962306a36Sopenharmony_ci	.recvmsg =	unix_seqpacket_recvmsg,
91062306a36Sopenharmony_ci	.mmap =		sock_no_mmap,
91162306a36Sopenharmony_ci	.set_peek_off =	unix_set_peek_off,
91262306a36Sopenharmony_ci	.show_fdinfo =	unix_show_fdinfo,
91362306a36Sopenharmony_ci};
91462306a36Sopenharmony_ci
91562306a36Sopenharmony_cistatic void unix_close(struct sock *sk, long timeout)
91662306a36Sopenharmony_ci{
91762306a36Sopenharmony_ci	/* Nothing to do here, unix socket does not need a ->close().
91862306a36Sopenharmony_ci	 * This is merely for sockmap.
91962306a36Sopenharmony_ci	 */
92062306a36Sopenharmony_ci}
92162306a36Sopenharmony_ci
92262306a36Sopenharmony_cistatic void unix_unhash(struct sock *sk)
92362306a36Sopenharmony_ci{
92462306a36Sopenharmony_ci	/* Nothing to do here, unix socket does not need a ->unhash().
92562306a36Sopenharmony_ci	 * This is merely for sockmap.
92662306a36Sopenharmony_ci	 */
92762306a36Sopenharmony_ci}
92862306a36Sopenharmony_ci
92962306a36Sopenharmony_cistatic bool unix_bpf_bypass_getsockopt(int level, int optname)
93062306a36Sopenharmony_ci{
93162306a36Sopenharmony_ci	if (level == SOL_SOCKET) {
93262306a36Sopenharmony_ci		switch (optname) {
93362306a36Sopenharmony_ci		case SO_PEERPIDFD:
93462306a36Sopenharmony_ci			return true;
93562306a36Sopenharmony_ci		default:
93662306a36Sopenharmony_ci			return false;
93762306a36Sopenharmony_ci		}
93862306a36Sopenharmony_ci	}
93962306a36Sopenharmony_ci
94062306a36Sopenharmony_ci	return false;
94162306a36Sopenharmony_ci}
94262306a36Sopenharmony_ci
94362306a36Sopenharmony_cistruct proto unix_dgram_proto = {
94462306a36Sopenharmony_ci	.name			= "UNIX",
94562306a36Sopenharmony_ci	.owner			= THIS_MODULE,
94662306a36Sopenharmony_ci	.obj_size		= sizeof(struct unix_sock),
94762306a36Sopenharmony_ci	.close			= unix_close,
94862306a36Sopenharmony_ci	.bpf_bypass_getsockopt	= unix_bpf_bypass_getsockopt,
94962306a36Sopenharmony_ci#ifdef CONFIG_BPF_SYSCALL
95062306a36Sopenharmony_ci	.psock_update_sk_prot	= unix_dgram_bpf_update_proto,
95162306a36Sopenharmony_ci#endif
95262306a36Sopenharmony_ci};
95362306a36Sopenharmony_ci
95462306a36Sopenharmony_cistruct proto unix_stream_proto = {
95562306a36Sopenharmony_ci	.name			= "UNIX-STREAM",
95662306a36Sopenharmony_ci	.owner			= THIS_MODULE,
95762306a36Sopenharmony_ci	.obj_size		= sizeof(struct unix_sock),
95862306a36Sopenharmony_ci	.close			= unix_close,
95962306a36Sopenharmony_ci	.unhash			= unix_unhash,
96062306a36Sopenharmony_ci	.bpf_bypass_getsockopt	= unix_bpf_bypass_getsockopt,
96162306a36Sopenharmony_ci#ifdef CONFIG_BPF_SYSCALL
96262306a36Sopenharmony_ci	.psock_update_sk_prot	= unix_stream_bpf_update_proto,
96362306a36Sopenharmony_ci#endif
96462306a36Sopenharmony_ci};
96562306a36Sopenharmony_ci
96662306a36Sopenharmony_cistatic struct sock *unix_create1(struct net *net, struct socket *sock, int kern, int type)
96762306a36Sopenharmony_ci{
96862306a36Sopenharmony_ci	struct unix_sock *u;
96962306a36Sopenharmony_ci	struct sock *sk;
97062306a36Sopenharmony_ci	int err;
97162306a36Sopenharmony_ci
97262306a36Sopenharmony_ci	atomic_long_inc(&unix_nr_socks);
97362306a36Sopenharmony_ci	if (atomic_long_read(&unix_nr_socks) > 2 * get_max_files()) {
97462306a36Sopenharmony_ci		err = -ENFILE;
97562306a36Sopenharmony_ci		goto err;
97662306a36Sopenharmony_ci	}
97762306a36Sopenharmony_ci
97862306a36Sopenharmony_ci	if (type == SOCK_STREAM)
97962306a36Sopenharmony_ci		sk = sk_alloc(net, PF_UNIX, GFP_KERNEL, &unix_stream_proto, kern);
98062306a36Sopenharmony_ci	else /*dgram and  seqpacket */
98162306a36Sopenharmony_ci		sk = sk_alloc(net, PF_UNIX, GFP_KERNEL, &unix_dgram_proto, kern);
98262306a36Sopenharmony_ci
98362306a36Sopenharmony_ci	if (!sk) {
98462306a36Sopenharmony_ci		err = -ENOMEM;
98562306a36Sopenharmony_ci		goto err;
98662306a36Sopenharmony_ci	}
98762306a36Sopenharmony_ci
98862306a36Sopenharmony_ci	sock_init_data(sock, sk);
98962306a36Sopenharmony_ci
99062306a36Sopenharmony_ci	sk->sk_hash		= unix_unbound_hash(sk);
99162306a36Sopenharmony_ci	sk->sk_allocation	= GFP_KERNEL_ACCOUNT;
99262306a36Sopenharmony_ci	sk->sk_write_space	= unix_write_space;
99362306a36Sopenharmony_ci	sk->sk_max_ack_backlog	= net->unx.sysctl_max_dgram_qlen;
99462306a36Sopenharmony_ci	sk->sk_destruct		= unix_sock_destructor;
99562306a36Sopenharmony_ci	u	  = unix_sk(sk);
99662306a36Sopenharmony_ci	u->path.dentry = NULL;
99762306a36Sopenharmony_ci	u->path.mnt = NULL;
99862306a36Sopenharmony_ci	spin_lock_init(&u->lock);
99962306a36Sopenharmony_ci	atomic_long_set(&u->inflight, 0);
100062306a36Sopenharmony_ci	INIT_LIST_HEAD(&u->link);
100162306a36Sopenharmony_ci	mutex_init(&u->iolock); /* single task reading lock */
100262306a36Sopenharmony_ci	mutex_init(&u->bindlock); /* single task binding lock */
100362306a36Sopenharmony_ci	init_waitqueue_head(&u->peer_wait);
100462306a36Sopenharmony_ci	init_waitqueue_func_entry(&u->peer_wake, unix_dgram_peer_wake_relay);
100562306a36Sopenharmony_ci	memset(&u->scm_stat, 0, sizeof(struct scm_stat));
100662306a36Sopenharmony_ci	unix_insert_unbound_socket(net, sk);
100762306a36Sopenharmony_ci
100862306a36Sopenharmony_ci	sock_prot_inuse_add(net, sk->sk_prot, 1);
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_ci	return sk;
101162306a36Sopenharmony_ci
101262306a36Sopenharmony_cierr:
101362306a36Sopenharmony_ci	atomic_long_dec(&unix_nr_socks);
101462306a36Sopenharmony_ci	return ERR_PTR(err);
101562306a36Sopenharmony_ci}
101662306a36Sopenharmony_ci
101762306a36Sopenharmony_cistatic int unix_create(struct net *net, struct socket *sock, int protocol,
101862306a36Sopenharmony_ci		       int kern)
101962306a36Sopenharmony_ci{
102062306a36Sopenharmony_ci	struct sock *sk;
102162306a36Sopenharmony_ci
102262306a36Sopenharmony_ci	if (protocol && protocol != PF_UNIX)
102362306a36Sopenharmony_ci		return -EPROTONOSUPPORT;
102462306a36Sopenharmony_ci
102562306a36Sopenharmony_ci	sock->state = SS_UNCONNECTED;
102662306a36Sopenharmony_ci
102762306a36Sopenharmony_ci	switch (sock->type) {
102862306a36Sopenharmony_ci	case SOCK_STREAM:
102962306a36Sopenharmony_ci		sock->ops = &unix_stream_ops;
103062306a36Sopenharmony_ci		break;
103162306a36Sopenharmony_ci		/*
103262306a36Sopenharmony_ci		 *	Believe it or not BSD has AF_UNIX, SOCK_RAW though
103362306a36Sopenharmony_ci		 *	nothing uses it.
103462306a36Sopenharmony_ci		 */
103562306a36Sopenharmony_ci	case SOCK_RAW:
103662306a36Sopenharmony_ci		sock->type = SOCK_DGRAM;
103762306a36Sopenharmony_ci		fallthrough;
103862306a36Sopenharmony_ci	case SOCK_DGRAM:
103962306a36Sopenharmony_ci		sock->ops = &unix_dgram_ops;
104062306a36Sopenharmony_ci		break;
104162306a36Sopenharmony_ci	case SOCK_SEQPACKET:
104262306a36Sopenharmony_ci		sock->ops = &unix_seqpacket_ops;
104362306a36Sopenharmony_ci		break;
104462306a36Sopenharmony_ci	default:
104562306a36Sopenharmony_ci		return -ESOCKTNOSUPPORT;
104662306a36Sopenharmony_ci	}
104762306a36Sopenharmony_ci
104862306a36Sopenharmony_ci	sk = unix_create1(net, sock, kern, sock->type);
104962306a36Sopenharmony_ci	if (IS_ERR(sk))
105062306a36Sopenharmony_ci		return PTR_ERR(sk);
105162306a36Sopenharmony_ci
105262306a36Sopenharmony_ci	return 0;
105362306a36Sopenharmony_ci}
105462306a36Sopenharmony_ci
105562306a36Sopenharmony_cistatic int unix_release(struct socket *sock)
105662306a36Sopenharmony_ci{
105762306a36Sopenharmony_ci	struct sock *sk = sock->sk;
105862306a36Sopenharmony_ci
105962306a36Sopenharmony_ci	if (!sk)
106062306a36Sopenharmony_ci		return 0;
106162306a36Sopenharmony_ci
106262306a36Sopenharmony_ci	sk->sk_prot->close(sk, 0);
106362306a36Sopenharmony_ci	unix_release_sock(sk, 0);
106462306a36Sopenharmony_ci	sock->sk = NULL;
106562306a36Sopenharmony_ci
106662306a36Sopenharmony_ci	return 0;
106762306a36Sopenharmony_ci}
106862306a36Sopenharmony_ci
106962306a36Sopenharmony_cistatic struct sock *unix_find_bsd(struct sockaddr_un *sunaddr, int addr_len,
107062306a36Sopenharmony_ci				  int type)
107162306a36Sopenharmony_ci{
107262306a36Sopenharmony_ci	struct inode *inode;
107362306a36Sopenharmony_ci	struct path path;
107462306a36Sopenharmony_ci	struct sock *sk;
107562306a36Sopenharmony_ci	int err;
107662306a36Sopenharmony_ci
107762306a36Sopenharmony_ci	unix_mkname_bsd(sunaddr, addr_len);
107862306a36Sopenharmony_ci	err = kern_path(sunaddr->sun_path, LOOKUP_FOLLOW, &path);
107962306a36Sopenharmony_ci	if (err)
108062306a36Sopenharmony_ci		goto fail;
108162306a36Sopenharmony_ci
108262306a36Sopenharmony_ci	err = path_permission(&path, MAY_WRITE);
108362306a36Sopenharmony_ci	if (err)
108462306a36Sopenharmony_ci		goto path_put;
108562306a36Sopenharmony_ci
108662306a36Sopenharmony_ci	err = -ECONNREFUSED;
108762306a36Sopenharmony_ci	inode = d_backing_inode(path.dentry);
108862306a36Sopenharmony_ci	if (!S_ISSOCK(inode->i_mode))
108962306a36Sopenharmony_ci		goto path_put;
109062306a36Sopenharmony_ci
109162306a36Sopenharmony_ci	sk = unix_find_socket_byinode(inode);
109262306a36Sopenharmony_ci	if (!sk)
109362306a36Sopenharmony_ci		goto path_put;
109462306a36Sopenharmony_ci
109562306a36Sopenharmony_ci	err = -EPROTOTYPE;
109662306a36Sopenharmony_ci	if (sk->sk_type == type)
109762306a36Sopenharmony_ci		touch_atime(&path);
109862306a36Sopenharmony_ci	else
109962306a36Sopenharmony_ci		goto sock_put;
110062306a36Sopenharmony_ci
110162306a36Sopenharmony_ci	path_put(&path);
110262306a36Sopenharmony_ci
110362306a36Sopenharmony_ci	return sk;
110462306a36Sopenharmony_ci
110562306a36Sopenharmony_cisock_put:
110662306a36Sopenharmony_ci	sock_put(sk);
110762306a36Sopenharmony_cipath_put:
110862306a36Sopenharmony_ci	path_put(&path);
110962306a36Sopenharmony_cifail:
111062306a36Sopenharmony_ci	return ERR_PTR(err);
111162306a36Sopenharmony_ci}
111262306a36Sopenharmony_ci
111362306a36Sopenharmony_cistatic struct sock *unix_find_abstract(struct net *net,
111462306a36Sopenharmony_ci				       struct sockaddr_un *sunaddr,
111562306a36Sopenharmony_ci				       int addr_len, int type)
111662306a36Sopenharmony_ci{
111762306a36Sopenharmony_ci	unsigned int hash = unix_abstract_hash(sunaddr, addr_len, type);
111862306a36Sopenharmony_ci	struct dentry *dentry;
111962306a36Sopenharmony_ci	struct sock *sk;
112062306a36Sopenharmony_ci
112162306a36Sopenharmony_ci	sk = unix_find_socket_byname(net, sunaddr, addr_len, hash);
112262306a36Sopenharmony_ci	if (!sk)
112362306a36Sopenharmony_ci		return ERR_PTR(-ECONNREFUSED);
112462306a36Sopenharmony_ci
112562306a36Sopenharmony_ci	dentry = unix_sk(sk)->path.dentry;
112662306a36Sopenharmony_ci	if (dentry)
112762306a36Sopenharmony_ci		touch_atime(&unix_sk(sk)->path);
112862306a36Sopenharmony_ci
112962306a36Sopenharmony_ci	return sk;
113062306a36Sopenharmony_ci}
113162306a36Sopenharmony_ci
113262306a36Sopenharmony_cistatic struct sock *unix_find_other(struct net *net,
113362306a36Sopenharmony_ci				    struct sockaddr_un *sunaddr,
113462306a36Sopenharmony_ci				    int addr_len, int type)
113562306a36Sopenharmony_ci{
113662306a36Sopenharmony_ci	struct sock *sk;
113762306a36Sopenharmony_ci
113862306a36Sopenharmony_ci	if (sunaddr->sun_path[0])
113962306a36Sopenharmony_ci		sk = unix_find_bsd(sunaddr, addr_len, type);
114062306a36Sopenharmony_ci	else
114162306a36Sopenharmony_ci		sk = unix_find_abstract(net, sunaddr, addr_len, type);
114262306a36Sopenharmony_ci
114362306a36Sopenharmony_ci	return sk;
114462306a36Sopenharmony_ci}
114562306a36Sopenharmony_ci
114662306a36Sopenharmony_cistatic int unix_autobind(struct sock *sk)
114762306a36Sopenharmony_ci{
114862306a36Sopenharmony_ci	unsigned int new_hash, old_hash = sk->sk_hash;
114962306a36Sopenharmony_ci	struct unix_sock *u = unix_sk(sk);
115062306a36Sopenharmony_ci	struct net *net = sock_net(sk);
115162306a36Sopenharmony_ci	struct unix_address *addr;
115262306a36Sopenharmony_ci	u32 lastnum, ordernum;
115362306a36Sopenharmony_ci	int err;
115462306a36Sopenharmony_ci
115562306a36Sopenharmony_ci	err = mutex_lock_interruptible(&u->bindlock);
115662306a36Sopenharmony_ci	if (err)
115762306a36Sopenharmony_ci		return err;
115862306a36Sopenharmony_ci
115962306a36Sopenharmony_ci	if (u->addr)
116062306a36Sopenharmony_ci		goto out;
116162306a36Sopenharmony_ci
116262306a36Sopenharmony_ci	err = -ENOMEM;
116362306a36Sopenharmony_ci	addr = kzalloc(sizeof(*addr) +
116462306a36Sopenharmony_ci		       offsetof(struct sockaddr_un, sun_path) + 16, GFP_KERNEL);
116562306a36Sopenharmony_ci	if (!addr)
116662306a36Sopenharmony_ci		goto out;
116762306a36Sopenharmony_ci
116862306a36Sopenharmony_ci	addr->len = offsetof(struct sockaddr_un, sun_path) + 6;
116962306a36Sopenharmony_ci	addr->name->sun_family = AF_UNIX;
117062306a36Sopenharmony_ci	refcount_set(&addr->refcnt, 1);
117162306a36Sopenharmony_ci
117262306a36Sopenharmony_ci	ordernum = get_random_u32();
117362306a36Sopenharmony_ci	lastnum = ordernum & 0xFFFFF;
117462306a36Sopenharmony_ciretry:
117562306a36Sopenharmony_ci	ordernum = (ordernum + 1) & 0xFFFFF;
117662306a36Sopenharmony_ci	sprintf(addr->name->sun_path + 1, "%05x", ordernum);
117762306a36Sopenharmony_ci
117862306a36Sopenharmony_ci	new_hash = unix_abstract_hash(addr->name, addr->len, sk->sk_type);
117962306a36Sopenharmony_ci	unix_table_double_lock(net, old_hash, new_hash);
118062306a36Sopenharmony_ci
118162306a36Sopenharmony_ci	if (__unix_find_socket_byname(net, addr->name, addr->len, new_hash)) {
118262306a36Sopenharmony_ci		unix_table_double_unlock(net, old_hash, new_hash);
118362306a36Sopenharmony_ci
118462306a36Sopenharmony_ci		/* __unix_find_socket_byname() may take long time if many names
118562306a36Sopenharmony_ci		 * are already in use.
118662306a36Sopenharmony_ci		 */
118762306a36Sopenharmony_ci		cond_resched();
118862306a36Sopenharmony_ci
118962306a36Sopenharmony_ci		if (ordernum == lastnum) {
119062306a36Sopenharmony_ci			/* Give up if all names seems to be in use. */
119162306a36Sopenharmony_ci			err = -ENOSPC;
119262306a36Sopenharmony_ci			unix_release_addr(addr);
119362306a36Sopenharmony_ci			goto out;
119462306a36Sopenharmony_ci		}
119562306a36Sopenharmony_ci
119662306a36Sopenharmony_ci		goto retry;
119762306a36Sopenharmony_ci	}
119862306a36Sopenharmony_ci
119962306a36Sopenharmony_ci	__unix_set_addr_hash(net, sk, addr, new_hash);
120062306a36Sopenharmony_ci	unix_table_double_unlock(net, old_hash, new_hash);
120162306a36Sopenharmony_ci	err = 0;
120262306a36Sopenharmony_ci
120362306a36Sopenharmony_ciout:	mutex_unlock(&u->bindlock);
120462306a36Sopenharmony_ci	return err;
120562306a36Sopenharmony_ci}
120662306a36Sopenharmony_ci
120762306a36Sopenharmony_cistatic int unix_bind_bsd(struct sock *sk, struct sockaddr_un *sunaddr,
120862306a36Sopenharmony_ci			 int addr_len)
120962306a36Sopenharmony_ci{
121062306a36Sopenharmony_ci	umode_t mode = S_IFSOCK |
121162306a36Sopenharmony_ci	       (SOCK_INODE(sk->sk_socket)->i_mode & ~current_umask());
121262306a36Sopenharmony_ci	unsigned int new_hash, old_hash = sk->sk_hash;
121362306a36Sopenharmony_ci	struct unix_sock *u = unix_sk(sk);
121462306a36Sopenharmony_ci	struct net *net = sock_net(sk);
121562306a36Sopenharmony_ci	struct mnt_idmap *idmap;
121662306a36Sopenharmony_ci	struct unix_address *addr;
121762306a36Sopenharmony_ci	struct dentry *dentry;
121862306a36Sopenharmony_ci	struct path parent;
121962306a36Sopenharmony_ci	int err;
122062306a36Sopenharmony_ci
122162306a36Sopenharmony_ci	addr_len = unix_mkname_bsd(sunaddr, addr_len);
122262306a36Sopenharmony_ci	addr = unix_create_addr(sunaddr, addr_len);
122362306a36Sopenharmony_ci	if (!addr)
122462306a36Sopenharmony_ci		return -ENOMEM;
122562306a36Sopenharmony_ci
122662306a36Sopenharmony_ci	/*
122762306a36Sopenharmony_ci	 * Get the parent directory, calculate the hash for last
122862306a36Sopenharmony_ci	 * component.
122962306a36Sopenharmony_ci	 */
123062306a36Sopenharmony_ci	dentry = kern_path_create(AT_FDCWD, addr->name->sun_path, &parent, 0);
123162306a36Sopenharmony_ci	if (IS_ERR(dentry)) {
123262306a36Sopenharmony_ci		err = PTR_ERR(dentry);
123362306a36Sopenharmony_ci		goto out;
123462306a36Sopenharmony_ci	}
123562306a36Sopenharmony_ci
123662306a36Sopenharmony_ci	/*
123762306a36Sopenharmony_ci	 * All right, let's create it.
123862306a36Sopenharmony_ci	 */
123962306a36Sopenharmony_ci	idmap = mnt_idmap(parent.mnt);
124062306a36Sopenharmony_ci	err = security_path_mknod(&parent, dentry, mode, 0);
124162306a36Sopenharmony_ci	if (!err)
124262306a36Sopenharmony_ci		err = vfs_mknod(idmap, d_inode(parent.dentry), dentry, mode, 0);
124362306a36Sopenharmony_ci	if (err)
124462306a36Sopenharmony_ci		goto out_path;
124562306a36Sopenharmony_ci	err = mutex_lock_interruptible(&u->bindlock);
124662306a36Sopenharmony_ci	if (err)
124762306a36Sopenharmony_ci		goto out_unlink;
124862306a36Sopenharmony_ci	if (u->addr)
124962306a36Sopenharmony_ci		goto out_unlock;
125062306a36Sopenharmony_ci
125162306a36Sopenharmony_ci	new_hash = unix_bsd_hash(d_backing_inode(dentry));
125262306a36Sopenharmony_ci	unix_table_double_lock(net, old_hash, new_hash);
125362306a36Sopenharmony_ci	u->path.mnt = mntget(parent.mnt);
125462306a36Sopenharmony_ci	u->path.dentry = dget(dentry);
125562306a36Sopenharmony_ci	__unix_set_addr_hash(net, sk, addr, new_hash);
125662306a36Sopenharmony_ci	unix_table_double_unlock(net, old_hash, new_hash);
125762306a36Sopenharmony_ci	unix_insert_bsd_socket(sk);
125862306a36Sopenharmony_ci	mutex_unlock(&u->bindlock);
125962306a36Sopenharmony_ci	done_path_create(&parent, dentry);
126062306a36Sopenharmony_ci	return 0;
126162306a36Sopenharmony_ci
126262306a36Sopenharmony_ciout_unlock:
126362306a36Sopenharmony_ci	mutex_unlock(&u->bindlock);
126462306a36Sopenharmony_ci	err = -EINVAL;
126562306a36Sopenharmony_ciout_unlink:
126662306a36Sopenharmony_ci	/* failed after successful mknod?  unlink what we'd created... */
126762306a36Sopenharmony_ci	vfs_unlink(idmap, d_inode(parent.dentry), dentry, NULL);
126862306a36Sopenharmony_ciout_path:
126962306a36Sopenharmony_ci	done_path_create(&parent, dentry);
127062306a36Sopenharmony_ciout:
127162306a36Sopenharmony_ci	unix_release_addr(addr);
127262306a36Sopenharmony_ci	return err == -EEXIST ? -EADDRINUSE : err;
127362306a36Sopenharmony_ci}
127462306a36Sopenharmony_ci
127562306a36Sopenharmony_cistatic int unix_bind_abstract(struct sock *sk, struct sockaddr_un *sunaddr,
127662306a36Sopenharmony_ci			      int addr_len)
127762306a36Sopenharmony_ci{
127862306a36Sopenharmony_ci	unsigned int new_hash, old_hash = sk->sk_hash;
127962306a36Sopenharmony_ci	struct unix_sock *u = unix_sk(sk);
128062306a36Sopenharmony_ci	struct net *net = sock_net(sk);
128162306a36Sopenharmony_ci	struct unix_address *addr;
128262306a36Sopenharmony_ci	int err;
128362306a36Sopenharmony_ci
128462306a36Sopenharmony_ci	addr = unix_create_addr(sunaddr, addr_len);
128562306a36Sopenharmony_ci	if (!addr)
128662306a36Sopenharmony_ci		return -ENOMEM;
128762306a36Sopenharmony_ci
128862306a36Sopenharmony_ci	err = mutex_lock_interruptible(&u->bindlock);
128962306a36Sopenharmony_ci	if (err)
129062306a36Sopenharmony_ci		goto out;
129162306a36Sopenharmony_ci
129262306a36Sopenharmony_ci	if (u->addr) {
129362306a36Sopenharmony_ci		err = -EINVAL;
129462306a36Sopenharmony_ci		goto out_mutex;
129562306a36Sopenharmony_ci	}
129662306a36Sopenharmony_ci
129762306a36Sopenharmony_ci	new_hash = unix_abstract_hash(addr->name, addr->len, sk->sk_type);
129862306a36Sopenharmony_ci	unix_table_double_lock(net, old_hash, new_hash);
129962306a36Sopenharmony_ci
130062306a36Sopenharmony_ci	if (__unix_find_socket_byname(net, addr->name, addr->len, new_hash))
130162306a36Sopenharmony_ci		goto out_spin;
130262306a36Sopenharmony_ci
130362306a36Sopenharmony_ci	__unix_set_addr_hash(net, sk, addr, new_hash);
130462306a36Sopenharmony_ci	unix_table_double_unlock(net, old_hash, new_hash);
130562306a36Sopenharmony_ci	mutex_unlock(&u->bindlock);
130662306a36Sopenharmony_ci	return 0;
130762306a36Sopenharmony_ci
130862306a36Sopenharmony_ciout_spin:
130962306a36Sopenharmony_ci	unix_table_double_unlock(net, old_hash, new_hash);
131062306a36Sopenharmony_ci	err = -EADDRINUSE;
131162306a36Sopenharmony_ciout_mutex:
131262306a36Sopenharmony_ci	mutex_unlock(&u->bindlock);
131362306a36Sopenharmony_ciout:
131462306a36Sopenharmony_ci	unix_release_addr(addr);
131562306a36Sopenharmony_ci	return err;
131662306a36Sopenharmony_ci}
131762306a36Sopenharmony_ci
131862306a36Sopenharmony_cistatic int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
131962306a36Sopenharmony_ci{
132062306a36Sopenharmony_ci	struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr;
132162306a36Sopenharmony_ci	struct sock *sk = sock->sk;
132262306a36Sopenharmony_ci	int err;
132362306a36Sopenharmony_ci
132462306a36Sopenharmony_ci	if (addr_len == offsetof(struct sockaddr_un, sun_path) &&
132562306a36Sopenharmony_ci	    sunaddr->sun_family == AF_UNIX)
132662306a36Sopenharmony_ci		return unix_autobind(sk);
132762306a36Sopenharmony_ci
132862306a36Sopenharmony_ci	err = unix_validate_addr(sunaddr, addr_len);
132962306a36Sopenharmony_ci	if (err)
133062306a36Sopenharmony_ci		return err;
133162306a36Sopenharmony_ci
133262306a36Sopenharmony_ci	if (sunaddr->sun_path[0])
133362306a36Sopenharmony_ci		err = unix_bind_bsd(sk, sunaddr, addr_len);
133462306a36Sopenharmony_ci	else
133562306a36Sopenharmony_ci		err = unix_bind_abstract(sk, sunaddr, addr_len);
133662306a36Sopenharmony_ci
133762306a36Sopenharmony_ci	return err;
133862306a36Sopenharmony_ci}
133962306a36Sopenharmony_ci
134062306a36Sopenharmony_cistatic void unix_state_double_lock(struct sock *sk1, struct sock *sk2)
134162306a36Sopenharmony_ci{
134262306a36Sopenharmony_ci	if (unlikely(sk1 == sk2) || !sk2) {
134362306a36Sopenharmony_ci		unix_state_lock(sk1);
134462306a36Sopenharmony_ci		return;
134562306a36Sopenharmony_ci	}
134662306a36Sopenharmony_ci	if (sk1 > sk2)
134762306a36Sopenharmony_ci		swap(sk1, sk2);
134862306a36Sopenharmony_ci
134962306a36Sopenharmony_ci	unix_state_lock(sk1);
135062306a36Sopenharmony_ci	unix_state_lock_nested(sk2, U_LOCK_SECOND);
135162306a36Sopenharmony_ci}
135262306a36Sopenharmony_ci
135362306a36Sopenharmony_cistatic void unix_state_double_unlock(struct sock *sk1, struct sock *sk2)
135462306a36Sopenharmony_ci{
135562306a36Sopenharmony_ci	if (unlikely(sk1 == sk2) || !sk2) {
135662306a36Sopenharmony_ci		unix_state_unlock(sk1);
135762306a36Sopenharmony_ci		return;
135862306a36Sopenharmony_ci	}
135962306a36Sopenharmony_ci	unix_state_unlock(sk1);
136062306a36Sopenharmony_ci	unix_state_unlock(sk2);
136162306a36Sopenharmony_ci}
136262306a36Sopenharmony_ci
136362306a36Sopenharmony_cistatic int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
136462306a36Sopenharmony_ci			      int alen, int flags)
136562306a36Sopenharmony_ci{
136662306a36Sopenharmony_ci	struct sockaddr_un *sunaddr = (struct sockaddr_un *)addr;
136762306a36Sopenharmony_ci	struct sock *sk = sock->sk;
136862306a36Sopenharmony_ci	struct sock *other;
136962306a36Sopenharmony_ci	int err;
137062306a36Sopenharmony_ci
137162306a36Sopenharmony_ci	err = -EINVAL;
137262306a36Sopenharmony_ci	if (alen < offsetofend(struct sockaddr, sa_family))
137362306a36Sopenharmony_ci		goto out;
137462306a36Sopenharmony_ci
137562306a36Sopenharmony_ci	if (addr->sa_family != AF_UNSPEC) {
137662306a36Sopenharmony_ci		err = unix_validate_addr(sunaddr, alen);
137762306a36Sopenharmony_ci		if (err)
137862306a36Sopenharmony_ci			goto out;
137962306a36Sopenharmony_ci
138062306a36Sopenharmony_ci		if ((test_bit(SOCK_PASSCRED, &sock->flags) ||
138162306a36Sopenharmony_ci		     test_bit(SOCK_PASSPIDFD, &sock->flags)) &&
138262306a36Sopenharmony_ci		    !unix_sk(sk)->addr) {
138362306a36Sopenharmony_ci			err = unix_autobind(sk);
138462306a36Sopenharmony_ci			if (err)
138562306a36Sopenharmony_ci				goto out;
138662306a36Sopenharmony_ci		}
138762306a36Sopenharmony_ci
138862306a36Sopenharmony_cirestart:
138962306a36Sopenharmony_ci		other = unix_find_other(sock_net(sk), sunaddr, alen, sock->type);
139062306a36Sopenharmony_ci		if (IS_ERR(other)) {
139162306a36Sopenharmony_ci			err = PTR_ERR(other);
139262306a36Sopenharmony_ci			goto out;
139362306a36Sopenharmony_ci		}
139462306a36Sopenharmony_ci
139562306a36Sopenharmony_ci		unix_state_double_lock(sk, other);
139662306a36Sopenharmony_ci
139762306a36Sopenharmony_ci		/* Apparently VFS overslept socket death. Retry. */
139862306a36Sopenharmony_ci		if (sock_flag(other, SOCK_DEAD)) {
139962306a36Sopenharmony_ci			unix_state_double_unlock(sk, other);
140062306a36Sopenharmony_ci			sock_put(other);
140162306a36Sopenharmony_ci			goto restart;
140262306a36Sopenharmony_ci		}
140362306a36Sopenharmony_ci
140462306a36Sopenharmony_ci		err = -EPERM;
140562306a36Sopenharmony_ci		if (!unix_may_send(sk, other))
140662306a36Sopenharmony_ci			goto out_unlock;
140762306a36Sopenharmony_ci
140862306a36Sopenharmony_ci		err = security_unix_may_send(sk->sk_socket, other->sk_socket);
140962306a36Sopenharmony_ci		if (err)
141062306a36Sopenharmony_ci			goto out_unlock;
141162306a36Sopenharmony_ci
141262306a36Sopenharmony_ci		sk->sk_state = other->sk_state = TCP_ESTABLISHED;
141362306a36Sopenharmony_ci	} else {
141462306a36Sopenharmony_ci		/*
141562306a36Sopenharmony_ci		 *	1003.1g breaking connected state with AF_UNSPEC
141662306a36Sopenharmony_ci		 */
141762306a36Sopenharmony_ci		other = NULL;
141862306a36Sopenharmony_ci		unix_state_double_lock(sk, other);
141962306a36Sopenharmony_ci	}
142062306a36Sopenharmony_ci
142162306a36Sopenharmony_ci	/*
142262306a36Sopenharmony_ci	 * If it was connected, reconnect.
142362306a36Sopenharmony_ci	 */
142462306a36Sopenharmony_ci	if (unix_peer(sk)) {
142562306a36Sopenharmony_ci		struct sock *old_peer = unix_peer(sk);
142662306a36Sopenharmony_ci
142762306a36Sopenharmony_ci		unix_peer(sk) = other;
142862306a36Sopenharmony_ci		if (!other)
142962306a36Sopenharmony_ci			sk->sk_state = TCP_CLOSE;
143062306a36Sopenharmony_ci		unix_dgram_peer_wake_disconnect_wakeup(sk, old_peer);
143162306a36Sopenharmony_ci
143262306a36Sopenharmony_ci		unix_state_double_unlock(sk, other);
143362306a36Sopenharmony_ci
143462306a36Sopenharmony_ci		if (other != old_peer)
143562306a36Sopenharmony_ci			unix_dgram_disconnected(sk, old_peer);
143662306a36Sopenharmony_ci		sock_put(old_peer);
143762306a36Sopenharmony_ci	} else {
143862306a36Sopenharmony_ci		unix_peer(sk) = other;
143962306a36Sopenharmony_ci		unix_state_double_unlock(sk, other);
144062306a36Sopenharmony_ci	}
144162306a36Sopenharmony_ci
144262306a36Sopenharmony_ci	return 0;
144362306a36Sopenharmony_ci
144462306a36Sopenharmony_ciout_unlock:
144562306a36Sopenharmony_ci	unix_state_double_unlock(sk, other);
144662306a36Sopenharmony_ci	sock_put(other);
144762306a36Sopenharmony_ciout:
144862306a36Sopenharmony_ci	return err;
144962306a36Sopenharmony_ci}
145062306a36Sopenharmony_ci
145162306a36Sopenharmony_cistatic long unix_wait_for_peer(struct sock *other, long timeo)
145262306a36Sopenharmony_ci	__releases(&unix_sk(other)->lock)
145362306a36Sopenharmony_ci{
145462306a36Sopenharmony_ci	struct unix_sock *u = unix_sk(other);
145562306a36Sopenharmony_ci	int sched;
145662306a36Sopenharmony_ci	DEFINE_WAIT(wait);
145762306a36Sopenharmony_ci
145862306a36Sopenharmony_ci	prepare_to_wait_exclusive(&u->peer_wait, &wait, TASK_INTERRUPTIBLE);
145962306a36Sopenharmony_ci
146062306a36Sopenharmony_ci	sched = !sock_flag(other, SOCK_DEAD) &&
146162306a36Sopenharmony_ci		!(other->sk_shutdown & RCV_SHUTDOWN) &&
146262306a36Sopenharmony_ci		unix_recvq_full_lockless(other);
146362306a36Sopenharmony_ci
146462306a36Sopenharmony_ci	unix_state_unlock(other);
146562306a36Sopenharmony_ci
146662306a36Sopenharmony_ci	if (sched)
146762306a36Sopenharmony_ci		timeo = schedule_timeout(timeo);
146862306a36Sopenharmony_ci
146962306a36Sopenharmony_ci	finish_wait(&u->peer_wait, &wait);
147062306a36Sopenharmony_ci	return timeo;
147162306a36Sopenharmony_ci}
147262306a36Sopenharmony_ci
147362306a36Sopenharmony_cistatic int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
147462306a36Sopenharmony_ci			       int addr_len, int flags)
147562306a36Sopenharmony_ci{
147662306a36Sopenharmony_ci	struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr;
147762306a36Sopenharmony_ci	struct sock *sk = sock->sk, *newsk = NULL, *other = NULL;
147862306a36Sopenharmony_ci	struct unix_sock *u = unix_sk(sk), *newu, *otheru;
147962306a36Sopenharmony_ci	struct net *net = sock_net(sk);
148062306a36Sopenharmony_ci	struct sk_buff *skb = NULL;
148162306a36Sopenharmony_ci	long timeo;
148262306a36Sopenharmony_ci	int err;
148362306a36Sopenharmony_ci	int st;
148462306a36Sopenharmony_ci
148562306a36Sopenharmony_ci	err = unix_validate_addr(sunaddr, addr_len);
148662306a36Sopenharmony_ci	if (err)
148762306a36Sopenharmony_ci		goto out;
148862306a36Sopenharmony_ci
148962306a36Sopenharmony_ci	if ((test_bit(SOCK_PASSCRED, &sock->flags) ||
149062306a36Sopenharmony_ci	     test_bit(SOCK_PASSPIDFD, &sock->flags)) && !u->addr) {
149162306a36Sopenharmony_ci		err = unix_autobind(sk);
149262306a36Sopenharmony_ci		if (err)
149362306a36Sopenharmony_ci			goto out;
149462306a36Sopenharmony_ci	}
149562306a36Sopenharmony_ci
149662306a36Sopenharmony_ci	timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
149762306a36Sopenharmony_ci
149862306a36Sopenharmony_ci	/* First of all allocate resources.
149962306a36Sopenharmony_ci	   If we will make it after state is locked,
150062306a36Sopenharmony_ci	   we will have to recheck all again in any case.
150162306a36Sopenharmony_ci	 */
150262306a36Sopenharmony_ci
150362306a36Sopenharmony_ci	/* create new sock for complete connection */
150462306a36Sopenharmony_ci	newsk = unix_create1(net, NULL, 0, sock->type);
150562306a36Sopenharmony_ci	if (IS_ERR(newsk)) {
150662306a36Sopenharmony_ci		err = PTR_ERR(newsk);
150762306a36Sopenharmony_ci		newsk = NULL;
150862306a36Sopenharmony_ci		goto out;
150962306a36Sopenharmony_ci	}
151062306a36Sopenharmony_ci
151162306a36Sopenharmony_ci	err = -ENOMEM;
151262306a36Sopenharmony_ci
151362306a36Sopenharmony_ci	/* Allocate skb for sending to listening sock */
151462306a36Sopenharmony_ci	skb = sock_wmalloc(newsk, 1, 0, GFP_KERNEL);
151562306a36Sopenharmony_ci	if (skb == NULL)
151662306a36Sopenharmony_ci		goto out;
151762306a36Sopenharmony_ci
151862306a36Sopenharmony_cirestart:
151962306a36Sopenharmony_ci	/*  Find listening sock. */
152062306a36Sopenharmony_ci	other = unix_find_other(net, sunaddr, addr_len, sk->sk_type);
152162306a36Sopenharmony_ci	if (IS_ERR(other)) {
152262306a36Sopenharmony_ci		err = PTR_ERR(other);
152362306a36Sopenharmony_ci		other = NULL;
152462306a36Sopenharmony_ci		goto out;
152562306a36Sopenharmony_ci	}
152662306a36Sopenharmony_ci
152762306a36Sopenharmony_ci	/* Latch state of peer */
152862306a36Sopenharmony_ci	unix_state_lock(other);
152962306a36Sopenharmony_ci
153062306a36Sopenharmony_ci	/* Apparently VFS overslept socket death. Retry. */
153162306a36Sopenharmony_ci	if (sock_flag(other, SOCK_DEAD)) {
153262306a36Sopenharmony_ci		unix_state_unlock(other);
153362306a36Sopenharmony_ci		sock_put(other);
153462306a36Sopenharmony_ci		goto restart;
153562306a36Sopenharmony_ci	}
153662306a36Sopenharmony_ci
153762306a36Sopenharmony_ci	err = -ECONNREFUSED;
153862306a36Sopenharmony_ci	if (other->sk_state != TCP_LISTEN)
153962306a36Sopenharmony_ci		goto out_unlock;
154062306a36Sopenharmony_ci	if (other->sk_shutdown & RCV_SHUTDOWN)
154162306a36Sopenharmony_ci		goto out_unlock;
154262306a36Sopenharmony_ci
154362306a36Sopenharmony_ci	if (unix_recvq_full(other)) {
154462306a36Sopenharmony_ci		err = -EAGAIN;
154562306a36Sopenharmony_ci		if (!timeo)
154662306a36Sopenharmony_ci			goto out_unlock;
154762306a36Sopenharmony_ci
154862306a36Sopenharmony_ci		timeo = unix_wait_for_peer(other, timeo);
154962306a36Sopenharmony_ci
155062306a36Sopenharmony_ci		err = sock_intr_errno(timeo);
155162306a36Sopenharmony_ci		if (signal_pending(current))
155262306a36Sopenharmony_ci			goto out;
155362306a36Sopenharmony_ci		sock_put(other);
155462306a36Sopenharmony_ci		goto restart;
155562306a36Sopenharmony_ci	}
155662306a36Sopenharmony_ci
155762306a36Sopenharmony_ci	/* Latch our state.
155862306a36Sopenharmony_ci
155962306a36Sopenharmony_ci	   It is tricky place. We need to grab our state lock and cannot
156062306a36Sopenharmony_ci	   drop lock on peer. It is dangerous because deadlock is
156162306a36Sopenharmony_ci	   possible. Connect to self case and simultaneous
156262306a36Sopenharmony_ci	   attempt to connect are eliminated by checking socket
156362306a36Sopenharmony_ci	   state. other is TCP_LISTEN, if sk is TCP_LISTEN we
156462306a36Sopenharmony_ci	   check this before attempt to grab lock.
156562306a36Sopenharmony_ci
156662306a36Sopenharmony_ci	   Well, and we have to recheck the state after socket locked.
156762306a36Sopenharmony_ci	 */
156862306a36Sopenharmony_ci	st = sk->sk_state;
156962306a36Sopenharmony_ci
157062306a36Sopenharmony_ci	switch (st) {
157162306a36Sopenharmony_ci	case TCP_CLOSE:
157262306a36Sopenharmony_ci		/* This is ok... continue with connect */
157362306a36Sopenharmony_ci		break;
157462306a36Sopenharmony_ci	case TCP_ESTABLISHED:
157562306a36Sopenharmony_ci		/* Socket is already connected */
157662306a36Sopenharmony_ci		err = -EISCONN;
157762306a36Sopenharmony_ci		goto out_unlock;
157862306a36Sopenharmony_ci	default:
157962306a36Sopenharmony_ci		err = -EINVAL;
158062306a36Sopenharmony_ci		goto out_unlock;
158162306a36Sopenharmony_ci	}
158262306a36Sopenharmony_ci
158362306a36Sopenharmony_ci	unix_state_lock_nested(sk, U_LOCK_SECOND);
158462306a36Sopenharmony_ci
158562306a36Sopenharmony_ci	if (sk->sk_state != st) {
158662306a36Sopenharmony_ci		unix_state_unlock(sk);
158762306a36Sopenharmony_ci		unix_state_unlock(other);
158862306a36Sopenharmony_ci		sock_put(other);
158962306a36Sopenharmony_ci		goto restart;
159062306a36Sopenharmony_ci	}
159162306a36Sopenharmony_ci
159262306a36Sopenharmony_ci	err = security_unix_stream_connect(sk, other, newsk);
159362306a36Sopenharmony_ci	if (err) {
159462306a36Sopenharmony_ci		unix_state_unlock(sk);
159562306a36Sopenharmony_ci		goto out_unlock;
159662306a36Sopenharmony_ci	}
159762306a36Sopenharmony_ci
159862306a36Sopenharmony_ci	/* The way is open! Fastly set all the necessary fields... */
159962306a36Sopenharmony_ci
160062306a36Sopenharmony_ci	sock_hold(sk);
160162306a36Sopenharmony_ci	unix_peer(newsk)	= sk;
160262306a36Sopenharmony_ci	newsk->sk_state		= TCP_ESTABLISHED;
160362306a36Sopenharmony_ci	newsk->sk_type		= sk->sk_type;
160462306a36Sopenharmony_ci	init_peercred(newsk);
160562306a36Sopenharmony_ci	newu = unix_sk(newsk);
160662306a36Sopenharmony_ci	RCU_INIT_POINTER(newsk->sk_wq, &newu->peer_wq);
160762306a36Sopenharmony_ci	otheru = unix_sk(other);
160862306a36Sopenharmony_ci
160962306a36Sopenharmony_ci	/* copy address information from listening to new sock
161062306a36Sopenharmony_ci	 *
161162306a36Sopenharmony_ci	 * The contents of *(otheru->addr) and otheru->path
161262306a36Sopenharmony_ci	 * are seen fully set up here, since we have found
161362306a36Sopenharmony_ci	 * otheru in hash under its lock.  Insertion into the
161462306a36Sopenharmony_ci	 * hash chain we'd found it in had been done in an
161562306a36Sopenharmony_ci	 * earlier critical area protected by the chain's lock,
161662306a36Sopenharmony_ci	 * the same one where we'd set *(otheru->addr) contents,
161762306a36Sopenharmony_ci	 * as well as otheru->path and otheru->addr itself.
161862306a36Sopenharmony_ci	 *
161962306a36Sopenharmony_ci	 * Using smp_store_release() here to set newu->addr
162062306a36Sopenharmony_ci	 * is enough to make those stores, as well as stores
162162306a36Sopenharmony_ci	 * to newu->path visible to anyone who gets newu->addr
162262306a36Sopenharmony_ci	 * by smp_load_acquire().  IOW, the same warranties
162362306a36Sopenharmony_ci	 * as for unix_sock instances bound in unix_bind() or
162462306a36Sopenharmony_ci	 * in unix_autobind().
162562306a36Sopenharmony_ci	 */
162662306a36Sopenharmony_ci	if (otheru->path.dentry) {
162762306a36Sopenharmony_ci		path_get(&otheru->path);
162862306a36Sopenharmony_ci		newu->path = otheru->path;
162962306a36Sopenharmony_ci	}
163062306a36Sopenharmony_ci	refcount_inc(&otheru->addr->refcnt);
163162306a36Sopenharmony_ci	smp_store_release(&newu->addr, otheru->addr);
163262306a36Sopenharmony_ci
163362306a36Sopenharmony_ci	/* Set credentials */
163462306a36Sopenharmony_ci	copy_peercred(sk, other);
163562306a36Sopenharmony_ci
163662306a36Sopenharmony_ci	sock->state	= SS_CONNECTED;
163762306a36Sopenharmony_ci	sk->sk_state	= TCP_ESTABLISHED;
163862306a36Sopenharmony_ci	sock_hold(newsk);
163962306a36Sopenharmony_ci
164062306a36Sopenharmony_ci	smp_mb__after_atomic();	/* sock_hold() does an atomic_inc() */
164162306a36Sopenharmony_ci	unix_peer(sk)	= newsk;
164262306a36Sopenharmony_ci
164362306a36Sopenharmony_ci	unix_state_unlock(sk);
164462306a36Sopenharmony_ci
164562306a36Sopenharmony_ci	/* take ten and send info to listening sock */
164662306a36Sopenharmony_ci	spin_lock(&other->sk_receive_queue.lock);
164762306a36Sopenharmony_ci	__skb_queue_tail(&other->sk_receive_queue, skb);
164862306a36Sopenharmony_ci	spin_unlock(&other->sk_receive_queue.lock);
164962306a36Sopenharmony_ci	unix_state_unlock(other);
165062306a36Sopenharmony_ci	other->sk_data_ready(other);
165162306a36Sopenharmony_ci	sock_put(other);
165262306a36Sopenharmony_ci	return 0;
165362306a36Sopenharmony_ci
165462306a36Sopenharmony_ciout_unlock:
165562306a36Sopenharmony_ci	if (other)
165662306a36Sopenharmony_ci		unix_state_unlock(other);
165762306a36Sopenharmony_ci
165862306a36Sopenharmony_ciout:
165962306a36Sopenharmony_ci	kfree_skb(skb);
166062306a36Sopenharmony_ci	if (newsk)
166162306a36Sopenharmony_ci		unix_release_sock(newsk, 0);
166262306a36Sopenharmony_ci	if (other)
166362306a36Sopenharmony_ci		sock_put(other);
166462306a36Sopenharmony_ci	return err;
166562306a36Sopenharmony_ci}
166662306a36Sopenharmony_ci
166762306a36Sopenharmony_cistatic int unix_socketpair(struct socket *socka, struct socket *sockb)
166862306a36Sopenharmony_ci{
166962306a36Sopenharmony_ci	struct sock *ska = socka->sk, *skb = sockb->sk;
167062306a36Sopenharmony_ci
167162306a36Sopenharmony_ci	/* Join our sockets back to back */
167262306a36Sopenharmony_ci	sock_hold(ska);
167362306a36Sopenharmony_ci	sock_hold(skb);
167462306a36Sopenharmony_ci	unix_peer(ska) = skb;
167562306a36Sopenharmony_ci	unix_peer(skb) = ska;
167662306a36Sopenharmony_ci	init_peercred(ska);
167762306a36Sopenharmony_ci	init_peercred(skb);
167862306a36Sopenharmony_ci
167962306a36Sopenharmony_ci	ska->sk_state = TCP_ESTABLISHED;
168062306a36Sopenharmony_ci	skb->sk_state = TCP_ESTABLISHED;
168162306a36Sopenharmony_ci	socka->state  = SS_CONNECTED;
168262306a36Sopenharmony_ci	sockb->state  = SS_CONNECTED;
168362306a36Sopenharmony_ci	return 0;
168462306a36Sopenharmony_ci}
168562306a36Sopenharmony_ci
168662306a36Sopenharmony_cistatic void unix_sock_inherit_flags(const struct socket *old,
168762306a36Sopenharmony_ci				    struct socket *new)
168862306a36Sopenharmony_ci{
168962306a36Sopenharmony_ci	if (test_bit(SOCK_PASSCRED, &old->flags))
169062306a36Sopenharmony_ci		set_bit(SOCK_PASSCRED, &new->flags);
169162306a36Sopenharmony_ci	if (test_bit(SOCK_PASSPIDFD, &old->flags))
169262306a36Sopenharmony_ci		set_bit(SOCK_PASSPIDFD, &new->flags);
169362306a36Sopenharmony_ci	if (test_bit(SOCK_PASSSEC, &old->flags))
169462306a36Sopenharmony_ci		set_bit(SOCK_PASSSEC, &new->flags);
169562306a36Sopenharmony_ci}
169662306a36Sopenharmony_ci
169762306a36Sopenharmony_cistatic int unix_accept(struct socket *sock, struct socket *newsock, int flags,
169862306a36Sopenharmony_ci		       bool kern)
169962306a36Sopenharmony_ci{
170062306a36Sopenharmony_ci	struct sock *sk = sock->sk;
170162306a36Sopenharmony_ci	struct sock *tsk;
170262306a36Sopenharmony_ci	struct sk_buff *skb;
170362306a36Sopenharmony_ci	int err;
170462306a36Sopenharmony_ci
170562306a36Sopenharmony_ci	err = -EOPNOTSUPP;
170662306a36Sopenharmony_ci	if (sock->type != SOCK_STREAM && sock->type != SOCK_SEQPACKET)
170762306a36Sopenharmony_ci		goto out;
170862306a36Sopenharmony_ci
170962306a36Sopenharmony_ci	err = -EINVAL;
171062306a36Sopenharmony_ci	if (sk->sk_state != TCP_LISTEN)
171162306a36Sopenharmony_ci		goto out;
171262306a36Sopenharmony_ci
171362306a36Sopenharmony_ci	/* If socket state is TCP_LISTEN it cannot change (for now...),
171462306a36Sopenharmony_ci	 * so that no locks are necessary.
171562306a36Sopenharmony_ci	 */
171662306a36Sopenharmony_ci
171762306a36Sopenharmony_ci	skb = skb_recv_datagram(sk, (flags & O_NONBLOCK) ? MSG_DONTWAIT : 0,
171862306a36Sopenharmony_ci				&err);
171962306a36Sopenharmony_ci	if (!skb) {
172062306a36Sopenharmony_ci		/* This means receive shutdown. */
172162306a36Sopenharmony_ci		if (err == 0)
172262306a36Sopenharmony_ci			err = -EINVAL;
172362306a36Sopenharmony_ci		goto out;
172462306a36Sopenharmony_ci	}
172562306a36Sopenharmony_ci
172662306a36Sopenharmony_ci	tsk = skb->sk;
172762306a36Sopenharmony_ci	skb_free_datagram(sk, skb);
172862306a36Sopenharmony_ci	wake_up_interruptible(&unix_sk(sk)->peer_wait);
172962306a36Sopenharmony_ci
173062306a36Sopenharmony_ci	/* attach accepted sock to socket */
173162306a36Sopenharmony_ci	unix_state_lock(tsk);
173262306a36Sopenharmony_ci	newsock->state = SS_CONNECTED;
173362306a36Sopenharmony_ci	unix_sock_inherit_flags(sock, newsock);
173462306a36Sopenharmony_ci	sock_graft(tsk, newsock);
173562306a36Sopenharmony_ci	unix_state_unlock(tsk);
173662306a36Sopenharmony_ci	return 0;
173762306a36Sopenharmony_ci
173862306a36Sopenharmony_ciout:
173962306a36Sopenharmony_ci	return err;
174062306a36Sopenharmony_ci}
174162306a36Sopenharmony_ci
174262306a36Sopenharmony_ci
174362306a36Sopenharmony_cistatic int unix_getname(struct socket *sock, struct sockaddr *uaddr, int peer)
174462306a36Sopenharmony_ci{
174562306a36Sopenharmony_ci	struct sock *sk = sock->sk;
174662306a36Sopenharmony_ci	struct unix_address *addr;
174762306a36Sopenharmony_ci	DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, uaddr);
174862306a36Sopenharmony_ci	int err = 0;
174962306a36Sopenharmony_ci
175062306a36Sopenharmony_ci	if (peer) {
175162306a36Sopenharmony_ci		sk = unix_peer_get(sk);
175262306a36Sopenharmony_ci
175362306a36Sopenharmony_ci		err = -ENOTCONN;
175462306a36Sopenharmony_ci		if (!sk)
175562306a36Sopenharmony_ci			goto out;
175662306a36Sopenharmony_ci		err = 0;
175762306a36Sopenharmony_ci	} else {
175862306a36Sopenharmony_ci		sock_hold(sk);
175962306a36Sopenharmony_ci	}
176062306a36Sopenharmony_ci
176162306a36Sopenharmony_ci	addr = smp_load_acquire(&unix_sk(sk)->addr);
176262306a36Sopenharmony_ci	if (!addr) {
176362306a36Sopenharmony_ci		sunaddr->sun_family = AF_UNIX;
176462306a36Sopenharmony_ci		sunaddr->sun_path[0] = 0;
176562306a36Sopenharmony_ci		err = offsetof(struct sockaddr_un, sun_path);
176662306a36Sopenharmony_ci	} else {
176762306a36Sopenharmony_ci		err = addr->len;
176862306a36Sopenharmony_ci		memcpy(sunaddr, addr->name, addr->len);
176962306a36Sopenharmony_ci	}
177062306a36Sopenharmony_ci	sock_put(sk);
177162306a36Sopenharmony_ciout:
177262306a36Sopenharmony_ci	return err;
177362306a36Sopenharmony_ci}
177462306a36Sopenharmony_ci
177562306a36Sopenharmony_cistatic void unix_peek_fds(struct scm_cookie *scm, struct sk_buff *skb)
177662306a36Sopenharmony_ci{
177762306a36Sopenharmony_ci	scm->fp = scm_fp_dup(UNIXCB(skb).fp);
177862306a36Sopenharmony_ci
177962306a36Sopenharmony_ci	/*
178062306a36Sopenharmony_ci	 * Garbage collection of unix sockets starts by selecting a set of
178162306a36Sopenharmony_ci	 * candidate sockets which have reference only from being in flight
178262306a36Sopenharmony_ci	 * (total_refs == inflight_refs).  This condition is checked once during
178362306a36Sopenharmony_ci	 * the candidate collection phase, and candidates are marked as such, so
178462306a36Sopenharmony_ci	 * that non-candidates can later be ignored.  While inflight_refs is
178562306a36Sopenharmony_ci	 * protected by unix_gc_lock, total_refs (file count) is not, hence this
178662306a36Sopenharmony_ci	 * is an instantaneous decision.
178762306a36Sopenharmony_ci	 *
178862306a36Sopenharmony_ci	 * Once a candidate, however, the socket must not be reinstalled into a
178962306a36Sopenharmony_ci	 * file descriptor while the garbage collection is in progress.
179062306a36Sopenharmony_ci	 *
179162306a36Sopenharmony_ci	 * If the above conditions are met, then the directed graph of
179262306a36Sopenharmony_ci	 * candidates (*) does not change while unix_gc_lock is held.
179362306a36Sopenharmony_ci	 *
179462306a36Sopenharmony_ci	 * Any operations that changes the file count through file descriptors
179562306a36Sopenharmony_ci	 * (dup, close, sendmsg) does not change the graph since candidates are
179662306a36Sopenharmony_ci	 * not installed in fds.
179762306a36Sopenharmony_ci	 *
179862306a36Sopenharmony_ci	 * Dequeing a candidate via recvmsg would install it into an fd, but
179962306a36Sopenharmony_ci	 * that takes unix_gc_lock to decrement the inflight count, so it's
180062306a36Sopenharmony_ci	 * serialized with garbage collection.
180162306a36Sopenharmony_ci	 *
180262306a36Sopenharmony_ci	 * MSG_PEEK is special in that it does not change the inflight count,
180362306a36Sopenharmony_ci	 * yet does install the socket into an fd.  The following lock/unlock
180462306a36Sopenharmony_ci	 * pair is to ensure serialization with garbage collection.  It must be
180562306a36Sopenharmony_ci	 * done between incrementing the file count and installing the file into
180662306a36Sopenharmony_ci	 * an fd.
180762306a36Sopenharmony_ci	 *
180862306a36Sopenharmony_ci	 * If garbage collection starts after the barrier provided by the
180962306a36Sopenharmony_ci	 * lock/unlock, then it will see the elevated refcount and not mark this
181062306a36Sopenharmony_ci	 * as a candidate.  If a garbage collection is already in progress
181162306a36Sopenharmony_ci	 * before the file count was incremented, then the lock/unlock pair will
181262306a36Sopenharmony_ci	 * ensure that garbage collection is finished before progressing to
181362306a36Sopenharmony_ci	 * installing the fd.
181462306a36Sopenharmony_ci	 *
181562306a36Sopenharmony_ci	 * (*) A -> B where B is on the queue of A or B is on the queue of C
181662306a36Sopenharmony_ci	 * which is on the queue of listening socket A.
181762306a36Sopenharmony_ci	 */
181862306a36Sopenharmony_ci	spin_lock(&unix_gc_lock);
181962306a36Sopenharmony_ci	spin_unlock(&unix_gc_lock);
182062306a36Sopenharmony_ci}
182162306a36Sopenharmony_ci
182262306a36Sopenharmony_cistatic int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool send_fds)
182362306a36Sopenharmony_ci{
182462306a36Sopenharmony_ci	int err = 0;
182562306a36Sopenharmony_ci
182662306a36Sopenharmony_ci	UNIXCB(skb).pid  = get_pid(scm->pid);
182762306a36Sopenharmony_ci	UNIXCB(skb).uid = scm->creds.uid;
182862306a36Sopenharmony_ci	UNIXCB(skb).gid = scm->creds.gid;
182962306a36Sopenharmony_ci	UNIXCB(skb).fp = NULL;
183062306a36Sopenharmony_ci	unix_get_secdata(scm, skb);
183162306a36Sopenharmony_ci	if (scm->fp && send_fds)
183262306a36Sopenharmony_ci		err = unix_attach_fds(scm, skb);
183362306a36Sopenharmony_ci
183462306a36Sopenharmony_ci	skb->destructor = unix_destruct_scm;
183562306a36Sopenharmony_ci	return err;
183662306a36Sopenharmony_ci}
183762306a36Sopenharmony_ci
183862306a36Sopenharmony_cistatic bool unix_passcred_enabled(const struct socket *sock,
183962306a36Sopenharmony_ci				  const struct sock *other)
184062306a36Sopenharmony_ci{
184162306a36Sopenharmony_ci	return test_bit(SOCK_PASSCRED, &sock->flags) ||
184262306a36Sopenharmony_ci	       test_bit(SOCK_PASSPIDFD, &sock->flags) ||
184362306a36Sopenharmony_ci	       !other->sk_socket ||
184462306a36Sopenharmony_ci	       test_bit(SOCK_PASSCRED, &other->sk_socket->flags) ||
184562306a36Sopenharmony_ci	       test_bit(SOCK_PASSPIDFD, &other->sk_socket->flags);
184662306a36Sopenharmony_ci}
184762306a36Sopenharmony_ci
184862306a36Sopenharmony_ci/*
184962306a36Sopenharmony_ci * Some apps rely on write() giving SCM_CREDENTIALS
185062306a36Sopenharmony_ci * We include credentials if source or destination socket
185162306a36Sopenharmony_ci * asserted SOCK_PASSCRED.
185262306a36Sopenharmony_ci */
185362306a36Sopenharmony_cistatic void maybe_add_creds(struct sk_buff *skb, const struct socket *sock,
185462306a36Sopenharmony_ci			    const struct sock *other)
185562306a36Sopenharmony_ci{
185662306a36Sopenharmony_ci	if (UNIXCB(skb).pid)
185762306a36Sopenharmony_ci		return;
185862306a36Sopenharmony_ci	if (unix_passcred_enabled(sock, other)) {
185962306a36Sopenharmony_ci		UNIXCB(skb).pid  = get_pid(task_tgid(current));
186062306a36Sopenharmony_ci		current_uid_gid(&UNIXCB(skb).uid, &UNIXCB(skb).gid);
186162306a36Sopenharmony_ci	}
186262306a36Sopenharmony_ci}
186362306a36Sopenharmony_ci
186462306a36Sopenharmony_cistatic bool unix_skb_scm_eq(struct sk_buff *skb,
186562306a36Sopenharmony_ci			    struct scm_cookie *scm)
186662306a36Sopenharmony_ci{
186762306a36Sopenharmony_ci	return UNIXCB(skb).pid == scm->pid &&
186862306a36Sopenharmony_ci	       uid_eq(UNIXCB(skb).uid, scm->creds.uid) &&
186962306a36Sopenharmony_ci	       gid_eq(UNIXCB(skb).gid, scm->creds.gid) &&
187062306a36Sopenharmony_ci	       unix_secdata_eq(scm, skb);
187162306a36Sopenharmony_ci}
187262306a36Sopenharmony_ci
187362306a36Sopenharmony_cistatic void scm_stat_add(struct sock *sk, struct sk_buff *skb)
187462306a36Sopenharmony_ci{
187562306a36Sopenharmony_ci	struct scm_fp_list *fp = UNIXCB(skb).fp;
187662306a36Sopenharmony_ci	struct unix_sock *u = unix_sk(sk);
187762306a36Sopenharmony_ci
187862306a36Sopenharmony_ci	if (unlikely(fp && fp->count))
187962306a36Sopenharmony_ci		atomic_add(fp->count, &u->scm_stat.nr_fds);
188062306a36Sopenharmony_ci}
188162306a36Sopenharmony_ci
188262306a36Sopenharmony_cistatic void scm_stat_del(struct sock *sk, struct sk_buff *skb)
188362306a36Sopenharmony_ci{
188462306a36Sopenharmony_ci	struct scm_fp_list *fp = UNIXCB(skb).fp;
188562306a36Sopenharmony_ci	struct unix_sock *u = unix_sk(sk);
188662306a36Sopenharmony_ci
188762306a36Sopenharmony_ci	if (unlikely(fp && fp->count))
188862306a36Sopenharmony_ci		atomic_sub(fp->count, &u->scm_stat.nr_fds);
188962306a36Sopenharmony_ci}
189062306a36Sopenharmony_ci
189162306a36Sopenharmony_ci/*
189262306a36Sopenharmony_ci *	Send AF_UNIX data.
189362306a36Sopenharmony_ci */
189462306a36Sopenharmony_ci
189562306a36Sopenharmony_cistatic int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
189662306a36Sopenharmony_ci			      size_t len)
189762306a36Sopenharmony_ci{
189862306a36Sopenharmony_ci	DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, msg->msg_name);
189962306a36Sopenharmony_ci	struct sock *sk = sock->sk, *other = NULL;
190062306a36Sopenharmony_ci	struct unix_sock *u = unix_sk(sk);
190162306a36Sopenharmony_ci	struct scm_cookie scm;
190262306a36Sopenharmony_ci	struct sk_buff *skb;
190362306a36Sopenharmony_ci	int data_len = 0;
190462306a36Sopenharmony_ci	int sk_locked;
190562306a36Sopenharmony_ci	long timeo;
190662306a36Sopenharmony_ci	int err;
190762306a36Sopenharmony_ci
190862306a36Sopenharmony_ci	wait_for_unix_gc();
190962306a36Sopenharmony_ci	err = scm_send(sock, msg, &scm, false);
191062306a36Sopenharmony_ci	if (err < 0)
191162306a36Sopenharmony_ci		return err;
191262306a36Sopenharmony_ci
191362306a36Sopenharmony_ci	err = -EOPNOTSUPP;
191462306a36Sopenharmony_ci	if (msg->msg_flags&MSG_OOB)
191562306a36Sopenharmony_ci		goto out;
191662306a36Sopenharmony_ci
191762306a36Sopenharmony_ci	if (msg->msg_namelen) {
191862306a36Sopenharmony_ci		err = unix_validate_addr(sunaddr, msg->msg_namelen);
191962306a36Sopenharmony_ci		if (err)
192062306a36Sopenharmony_ci			goto out;
192162306a36Sopenharmony_ci	} else {
192262306a36Sopenharmony_ci		sunaddr = NULL;
192362306a36Sopenharmony_ci		err = -ENOTCONN;
192462306a36Sopenharmony_ci		other = unix_peer_get(sk);
192562306a36Sopenharmony_ci		if (!other)
192662306a36Sopenharmony_ci			goto out;
192762306a36Sopenharmony_ci	}
192862306a36Sopenharmony_ci
192962306a36Sopenharmony_ci	if ((test_bit(SOCK_PASSCRED, &sock->flags) ||
193062306a36Sopenharmony_ci	     test_bit(SOCK_PASSPIDFD, &sock->flags)) && !u->addr) {
193162306a36Sopenharmony_ci		err = unix_autobind(sk);
193262306a36Sopenharmony_ci		if (err)
193362306a36Sopenharmony_ci			goto out;
193462306a36Sopenharmony_ci	}
193562306a36Sopenharmony_ci
193662306a36Sopenharmony_ci	err = -EMSGSIZE;
193762306a36Sopenharmony_ci	if (len > sk->sk_sndbuf - 32)
193862306a36Sopenharmony_ci		goto out;
193962306a36Sopenharmony_ci
194062306a36Sopenharmony_ci	if (len > SKB_MAX_ALLOC) {
194162306a36Sopenharmony_ci		data_len = min_t(size_t,
194262306a36Sopenharmony_ci				 len - SKB_MAX_ALLOC,
194362306a36Sopenharmony_ci				 MAX_SKB_FRAGS * PAGE_SIZE);
194462306a36Sopenharmony_ci		data_len = PAGE_ALIGN(data_len);
194562306a36Sopenharmony_ci
194662306a36Sopenharmony_ci		BUILD_BUG_ON(SKB_MAX_ALLOC < PAGE_SIZE);
194762306a36Sopenharmony_ci	}
194862306a36Sopenharmony_ci
194962306a36Sopenharmony_ci	skb = sock_alloc_send_pskb(sk, len - data_len, data_len,
195062306a36Sopenharmony_ci				   msg->msg_flags & MSG_DONTWAIT, &err,
195162306a36Sopenharmony_ci				   PAGE_ALLOC_COSTLY_ORDER);
195262306a36Sopenharmony_ci	if (skb == NULL)
195362306a36Sopenharmony_ci		goto out;
195462306a36Sopenharmony_ci
195562306a36Sopenharmony_ci	err = unix_scm_to_skb(&scm, skb, true);
195662306a36Sopenharmony_ci	if (err < 0)
195762306a36Sopenharmony_ci		goto out_free;
195862306a36Sopenharmony_ci
195962306a36Sopenharmony_ci	skb_put(skb, len - data_len);
196062306a36Sopenharmony_ci	skb->data_len = data_len;
196162306a36Sopenharmony_ci	skb->len = len;
196262306a36Sopenharmony_ci	err = skb_copy_datagram_from_iter(skb, 0, &msg->msg_iter, len);
196362306a36Sopenharmony_ci	if (err)
196462306a36Sopenharmony_ci		goto out_free;
196562306a36Sopenharmony_ci
196662306a36Sopenharmony_ci	timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
196762306a36Sopenharmony_ci
196862306a36Sopenharmony_cirestart:
196962306a36Sopenharmony_ci	if (!other) {
197062306a36Sopenharmony_ci		err = -ECONNRESET;
197162306a36Sopenharmony_ci		if (sunaddr == NULL)
197262306a36Sopenharmony_ci			goto out_free;
197362306a36Sopenharmony_ci
197462306a36Sopenharmony_ci		other = unix_find_other(sock_net(sk), sunaddr, msg->msg_namelen,
197562306a36Sopenharmony_ci					sk->sk_type);
197662306a36Sopenharmony_ci		if (IS_ERR(other)) {
197762306a36Sopenharmony_ci			err = PTR_ERR(other);
197862306a36Sopenharmony_ci			other = NULL;
197962306a36Sopenharmony_ci			goto out_free;
198062306a36Sopenharmony_ci		}
198162306a36Sopenharmony_ci	}
198262306a36Sopenharmony_ci
198362306a36Sopenharmony_ci	if (sk_filter(other, skb) < 0) {
198462306a36Sopenharmony_ci		/* Toss the packet but do not return any error to the sender */
198562306a36Sopenharmony_ci		err = len;
198662306a36Sopenharmony_ci		goto out_free;
198762306a36Sopenharmony_ci	}
198862306a36Sopenharmony_ci
198962306a36Sopenharmony_ci	sk_locked = 0;
199062306a36Sopenharmony_ci	unix_state_lock(other);
199162306a36Sopenharmony_cirestart_locked:
199262306a36Sopenharmony_ci	err = -EPERM;
199362306a36Sopenharmony_ci	if (!unix_may_send(sk, other))
199462306a36Sopenharmony_ci		goto out_unlock;
199562306a36Sopenharmony_ci
199662306a36Sopenharmony_ci	if (unlikely(sock_flag(other, SOCK_DEAD))) {
199762306a36Sopenharmony_ci		/*
199862306a36Sopenharmony_ci		 *	Check with 1003.1g - what should
199962306a36Sopenharmony_ci		 *	datagram error
200062306a36Sopenharmony_ci		 */
200162306a36Sopenharmony_ci		unix_state_unlock(other);
200262306a36Sopenharmony_ci		sock_put(other);
200362306a36Sopenharmony_ci
200462306a36Sopenharmony_ci		if (!sk_locked)
200562306a36Sopenharmony_ci			unix_state_lock(sk);
200662306a36Sopenharmony_ci
200762306a36Sopenharmony_ci		err = 0;
200862306a36Sopenharmony_ci		if (sk->sk_type == SOCK_SEQPACKET) {
200962306a36Sopenharmony_ci			/* We are here only when racing with unix_release_sock()
201062306a36Sopenharmony_ci			 * is clearing @other. Never change state to TCP_CLOSE
201162306a36Sopenharmony_ci			 * unlike SOCK_DGRAM wants.
201262306a36Sopenharmony_ci			 */
201362306a36Sopenharmony_ci			unix_state_unlock(sk);
201462306a36Sopenharmony_ci			err = -EPIPE;
201562306a36Sopenharmony_ci		} else if (unix_peer(sk) == other) {
201662306a36Sopenharmony_ci			unix_peer(sk) = NULL;
201762306a36Sopenharmony_ci			unix_dgram_peer_wake_disconnect_wakeup(sk, other);
201862306a36Sopenharmony_ci
201962306a36Sopenharmony_ci			sk->sk_state = TCP_CLOSE;
202062306a36Sopenharmony_ci			unix_state_unlock(sk);
202162306a36Sopenharmony_ci
202262306a36Sopenharmony_ci			unix_dgram_disconnected(sk, other);
202362306a36Sopenharmony_ci			sock_put(other);
202462306a36Sopenharmony_ci			err = -ECONNREFUSED;
202562306a36Sopenharmony_ci		} else {
202662306a36Sopenharmony_ci			unix_state_unlock(sk);
202762306a36Sopenharmony_ci		}
202862306a36Sopenharmony_ci
202962306a36Sopenharmony_ci		other = NULL;
203062306a36Sopenharmony_ci		if (err)
203162306a36Sopenharmony_ci			goto out_free;
203262306a36Sopenharmony_ci		goto restart;
203362306a36Sopenharmony_ci	}
203462306a36Sopenharmony_ci
203562306a36Sopenharmony_ci	err = -EPIPE;
203662306a36Sopenharmony_ci	if (other->sk_shutdown & RCV_SHUTDOWN)
203762306a36Sopenharmony_ci		goto out_unlock;
203862306a36Sopenharmony_ci
203962306a36Sopenharmony_ci	if (sk->sk_type != SOCK_SEQPACKET) {
204062306a36Sopenharmony_ci		err = security_unix_may_send(sk->sk_socket, other->sk_socket);
204162306a36Sopenharmony_ci		if (err)
204262306a36Sopenharmony_ci			goto out_unlock;
204362306a36Sopenharmony_ci	}
204462306a36Sopenharmony_ci
204562306a36Sopenharmony_ci	/* other == sk && unix_peer(other) != sk if
204662306a36Sopenharmony_ci	 * - unix_peer(sk) == NULL, destination address bound to sk
204762306a36Sopenharmony_ci	 * - unix_peer(sk) == sk by time of get but disconnected before lock
204862306a36Sopenharmony_ci	 */
204962306a36Sopenharmony_ci	if (other != sk &&
205062306a36Sopenharmony_ci	    unlikely(unix_peer(other) != sk &&
205162306a36Sopenharmony_ci	    unix_recvq_full_lockless(other))) {
205262306a36Sopenharmony_ci		if (timeo) {
205362306a36Sopenharmony_ci			timeo = unix_wait_for_peer(other, timeo);
205462306a36Sopenharmony_ci
205562306a36Sopenharmony_ci			err = sock_intr_errno(timeo);
205662306a36Sopenharmony_ci			if (signal_pending(current))
205762306a36Sopenharmony_ci				goto out_free;
205862306a36Sopenharmony_ci
205962306a36Sopenharmony_ci			goto restart;
206062306a36Sopenharmony_ci		}
206162306a36Sopenharmony_ci
206262306a36Sopenharmony_ci		if (!sk_locked) {
206362306a36Sopenharmony_ci			unix_state_unlock(other);
206462306a36Sopenharmony_ci			unix_state_double_lock(sk, other);
206562306a36Sopenharmony_ci		}
206662306a36Sopenharmony_ci
206762306a36Sopenharmony_ci		if (unix_peer(sk) != other ||
206862306a36Sopenharmony_ci		    unix_dgram_peer_wake_me(sk, other)) {
206962306a36Sopenharmony_ci			err = -EAGAIN;
207062306a36Sopenharmony_ci			sk_locked = 1;
207162306a36Sopenharmony_ci			goto out_unlock;
207262306a36Sopenharmony_ci		}
207362306a36Sopenharmony_ci
207462306a36Sopenharmony_ci		if (!sk_locked) {
207562306a36Sopenharmony_ci			sk_locked = 1;
207662306a36Sopenharmony_ci			goto restart_locked;
207762306a36Sopenharmony_ci		}
207862306a36Sopenharmony_ci	}
207962306a36Sopenharmony_ci
208062306a36Sopenharmony_ci	if (unlikely(sk_locked))
208162306a36Sopenharmony_ci		unix_state_unlock(sk);
208262306a36Sopenharmony_ci
208362306a36Sopenharmony_ci	if (sock_flag(other, SOCK_RCVTSTAMP))
208462306a36Sopenharmony_ci		__net_timestamp(skb);
208562306a36Sopenharmony_ci	maybe_add_creds(skb, sock, other);
208662306a36Sopenharmony_ci	scm_stat_add(other, skb);
208762306a36Sopenharmony_ci	skb_queue_tail(&other->sk_receive_queue, skb);
208862306a36Sopenharmony_ci	unix_state_unlock(other);
208962306a36Sopenharmony_ci	other->sk_data_ready(other);
209062306a36Sopenharmony_ci	sock_put(other);
209162306a36Sopenharmony_ci	scm_destroy(&scm);
209262306a36Sopenharmony_ci	return len;
209362306a36Sopenharmony_ci
209462306a36Sopenharmony_ciout_unlock:
209562306a36Sopenharmony_ci	if (sk_locked)
209662306a36Sopenharmony_ci		unix_state_unlock(sk);
209762306a36Sopenharmony_ci	unix_state_unlock(other);
209862306a36Sopenharmony_ciout_free:
209962306a36Sopenharmony_ci	kfree_skb(skb);
210062306a36Sopenharmony_ciout:
210162306a36Sopenharmony_ci	if (other)
210262306a36Sopenharmony_ci		sock_put(other);
210362306a36Sopenharmony_ci	scm_destroy(&scm);
210462306a36Sopenharmony_ci	return err;
210562306a36Sopenharmony_ci}
210662306a36Sopenharmony_ci
210762306a36Sopenharmony_ci/* We use paged skbs for stream sockets, and limit occupancy to 32768
210862306a36Sopenharmony_ci * bytes, and a minimum of a full page.
210962306a36Sopenharmony_ci */
211062306a36Sopenharmony_ci#define UNIX_SKB_FRAGS_SZ (PAGE_SIZE << get_order(32768))
211162306a36Sopenharmony_ci
211262306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_AF_UNIX_OOB)
211362306a36Sopenharmony_cistatic int queue_oob(struct socket *sock, struct msghdr *msg, struct sock *other,
211462306a36Sopenharmony_ci		     struct scm_cookie *scm, bool fds_sent)
211562306a36Sopenharmony_ci{
211662306a36Sopenharmony_ci	struct unix_sock *ousk = unix_sk(other);
211762306a36Sopenharmony_ci	struct sk_buff *skb;
211862306a36Sopenharmony_ci	int err = 0;
211962306a36Sopenharmony_ci
212062306a36Sopenharmony_ci	skb = sock_alloc_send_skb(sock->sk, 1, msg->msg_flags & MSG_DONTWAIT, &err);
212162306a36Sopenharmony_ci
212262306a36Sopenharmony_ci	if (!skb)
212362306a36Sopenharmony_ci		return err;
212462306a36Sopenharmony_ci
212562306a36Sopenharmony_ci	err = unix_scm_to_skb(scm, skb, !fds_sent);
212662306a36Sopenharmony_ci	if (err < 0) {
212762306a36Sopenharmony_ci		kfree_skb(skb);
212862306a36Sopenharmony_ci		return err;
212962306a36Sopenharmony_ci	}
213062306a36Sopenharmony_ci	skb_put(skb, 1);
213162306a36Sopenharmony_ci	err = skb_copy_datagram_from_iter(skb, 0, &msg->msg_iter, 1);
213262306a36Sopenharmony_ci
213362306a36Sopenharmony_ci	if (err) {
213462306a36Sopenharmony_ci		kfree_skb(skb);
213562306a36Sopenharmony_ci		return err;
213662306a36Sopenharmony_ci	}
213762306a36Sopenharmony_ci
213862306a36Sopenharmony_ci	unix_state_lock(other);
213962306a36Sopenharmony_ci
214062306a36Sopenharmony_ci	if (sock_flag(other, SOCK_DEAD) ||
214162306a36Sopenharmony_ci	    (other->sk_shutdown & RCV_SHUTDOWN)) {
214262306a36Sopenharmony_ci		unix_state_unlock(other);
214362306a36Sopenharmony_ci		kfree_skb(skb);
214462306a36Sopenharmony_ci		return -EPIPE;
214562306a36Sopenharmony_ci	}
214662306a36Sopenharmony_ci
214762306a36Sopenharmony_ci	maybe_add_creds(skb, sock, other);
214862306a36Sopenharmony_ci	skb_get(skb);
214962306a36Sopenharmony_ci
215062306a36Sopenharmony_ci	if (ousk->oob_skb)
215162306a36Sopenharmony_ci		consume_skb(ousk->oob_skb);
215262306a36Sopenharmony_ci
215362306a36Sopenharmony_ci	WRITE_ONCE(ousk->oob_skb, skb);
215462306a36Sopenharmony_ci
215562306a36Sopenharmony_ci	scm_stat_add(other, skb);
215662306a36Sopenharmony_ci	skb_queue_tail(&other->sk_receive_queue, skb);
215762306a36Sopenharmony_ci	sk_send_sigurg(other);
215862306a36Sopenharmony_ci	unix_state_unlock(other);
215962306a36Sopenharmony_ci	other->sk_data_ready(other);
216062306a36Sopenharmony_ci
216162306a36Sopenharmony_ci	return err;
216262306a36Sopenharmony_ci}
216362306a36Sopenharmony_ci#endif
216462306a36Sopenharmony_ci
216562306a36Sopenharmony_cistatic int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
216662306a36Sopenharmony_ci			       size_t len)
216762306a36Sopenharmony_ci{
216862306a36Sopenharmony_ci	struct sock *sk = sock->sk;
216962306a36Sopenharmony_ci	struct sock *other = NULL;
217062306a36Sopenharmony_ci	int err, size;
217162306a36Sopenharmony_ci	struct sk_buff *skb;
217262306a36Sopenharmony_ci	int sent = 0;
217362306a36Sopenharmony_ci	struct scm_cookie scm;
217462306a36Sopenharmony_ci	bool fds_sent = false;
217562306a36Sopenharmony_ci	int data_len;
217662306a36Sopenharmony_ci
217762306a36Sopenharmony_ci	wait_for_unix_gc();
217862306a36Sopenharmony_ci	err = scm_send(sock, msg, &scm, false);
217962306a36Sopenharmony_ci	if (err < 0)
218062306a36Sopenharmony_ci		return err;
218162306a36Sopenharmony_ci
218262306a36Sopenharmony_ci	err = -EOPNOTSUPP;
218362306a36Sopenharmony_ci	if (msg->msg_flags & MSG_OOB) {
218462306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_AF_UNIX_OOB)
218562306a36Sopenharmony_ci		if (len)
218662306a36Sopenharmony_ci			len--;
218762306a36Sopenharmony_ci		else
218862306a36Sopenharmony_ci#endif
218962306a36Sopenharmony_ci			goto out_err;
219062306a36Sopenharmony_ci	}
219162306a36Sopenharmony_ci
219262306a36Sopenharmony_ci	if (msg->msg_namelen) {
219362306a36Sopenharmony_ci		err = sk->sk_state == TCP_ESTABLISHED ? -EISCONN : -EOPNOTSUPP;
219462306a36Sopenharmony_ci		goto out_err;
219562306a36Sopenharmony_ci	} else {
219662306a36Sopenharmony_ci		err = -ENOTCONN;
219762306a36Sopenharmony_ci		other = unix_peer(sk);
219862306a36Sopenharmony_ci		if (!other)
219962306a36Sopenharmony_ci			goto out_err;
220062306a36Sopenharmony_ci	}
220162306a36Sopenharmony_ci
220262306a36Sopenharmony_ci	if (sk->sk_shutdown & SEND_SHUTDOWN)
220362306a36Sopenharmony_ci		goto pipe_err;
220462306a36Sopenharmony_ci
220562306a36Sopenharmony_ci	while (sent < len) {
220662306a36Sopenharmony_ci		size = len - sent;
220762306a36Sopenharmony_ci
220862306a36Sopenharmony_ci		if (unlikely(msg->msg_flags & MSG_SPLICE_PAGES)) {
220962306a36Sopenharmony_ci			skb = sock_alloc_send_pskb(sk, 0, 0,
221062306a36Sopenharmony_ci						   msg->msg_flags & MSG_DONTWAIT,
221162306a36Sopenharmony_ci						   &err, 0);
221262306a36Sopenharmony_ci		} else {
221362306a36Sopenharmony_ci			/* Keep two messages in the pipe so it schedules better */
221462306a36Sopenharmony_ci			size = min_t(int, size, (sk->sk_sndbuf >> 1) - 64);
221562306a36Sopenharmony_ci
221662306a36Sopenharmony_ci			/* allow fallback to order-0 allocations */
221762306a36Sopenharmony_ci			size = min_t(int, size, SKB_MAX_HEAD(0) + UNIX_SKB_FRAGS_SZ);
221862306a36Sopenharmony_ci
221962306a36Sopenharmony_ci			data_len = max_t(int, 0, size - SKB_MAX_HEAD(0));
222062306a36Sopenharmony_ci
222162306a36Sopenharmony_ci			data_len = min_t(size_t, size, PAGE_ALIGN(data_len));
222262306a36Sopenharmony_ci
222362306a36Sopenharmony_ci			skb = sock_alloc_send_pskb(sk, size - data_len, data_len,
222462306a36Sopenharmony_ci						   msg->msg_flags & MSG_DONTWAIT, &err,
222562306a36Sopenharmony_ci						   get_order(UNIX_SKB_FRAGS_SZ));
222662306a36Sopenharmony_ci		}
222762306a36Sopenharmony_ci		if (!skb)
222862306a36Sopenharmony_ci			goto out_err;
222962306a36Sopenharmony_ci
223062306a36Sopenharmony_ci		/* Only send the fds in the first buffer */
223162306a36Sopenharmony_ci		err = unix_scm_to_skb(&scm, skb, !fds_sent);
223262306a36Sopenharmony_ci		if (err < 0) {
223362306a36Sopenharmony_ci			kfree_skb(skb);
223462306a36Sopenharmony_ci			goto out_err;
223562306a36Sopenharmony_ci		}
223662306a36Sopenharmony_ci		fds_sent = true;
223762306a36Sopenharmony_ci
223862306a36Sopenharmony_ci		if (unlikely(msg->msg_flags & MSG_SPLICE_PAGES)) {
223962306a36Sopenharmony_ci			err = skb_splice_from_iter(skb, &msg->msg_iter, size,
224062306a36Sopenharmony_ci						   sk->sk_allocation);
224162306a36Sopenharmony_ci			if (err < 0) {
224262306a36Sopenharmony_ci				kfree_skb(skb);
224362306a36Sopenharmony_ci				goto out_err;
224462306a36Sopenharmony_ci			}
224562306a36Sopenharmony_ci			size = err;
224662306a36Sopenharmony_ci			refcount_add(size, &sk->sk_wmem_alloc);
224762306a36Sopenharmony_ci		} else {
224862306a36Sopenharmony_ci			skb_put(skb, size - data_len);
224962306a36Sopenharmony_ci			skb->data_len = data_len;
225062306a36Sopenharmony_ci			skb->len = size;
225162306a36Sopenharmony_ci			err = skb_copy_datagram_from_iter(skb, 0, &msg->msg_iter, size);
225262306a36Sopenharmony_ci			if (err) {
225362306a36Sopenharmony_ci				kfree_skb(skb);
225462306a36Sopenharmony_ci				goto out_err;
225562306a36Sopenharmony_ci			}
225662306a36Sopenharmony_ci		}
225762306a36Sopenharmony_ci
225862306a36Sopenharmony_ci		unix_state_lock(other);
225962306a36Sopenharmony_ci
226062306a36Sopenharmony_ci		if (sock_flag(other, SOCK_DEAD) ||
226162306a36Sopenharmony_ci		    (other->sk_shutdown & RCV_SHUTDOWN))
226262306a36Sopenharmony_ci			goto pipe_err_free;
226362306a36Sopenharmony_ci
226462306a36Sopenharmony_ci		maybe_add_creds(skb, sock, other);
226562306a36Sopenharmony_ci		scm_stat_add(other, skb);
226662306a36Sopenharmony_ci		skb_queue_tail(&other->sk_receive_queue, skb);
226762306a36Sopenharmony_ci		unix_state_unlock(other);
226862306a36Sopenharmony_ci		other->sk_data_ready(other);
226962306a36Sopenharmony_ci		sent += size;
227062306a36Sopenharmony_ci	}
227162306a36Sopenharmony_ci
227262306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_AF_UNIX_OOB)
227362306a36Sopenharmony_ci	if (msg->msg_flags & MSG_OOB) {
227462306a36Sopenharmony_ci		err = queue_oob(sock, msg, other, &scm, fds_sent);
227562306a36Sopenharmony_ci		if (err)
227662306a36Sopenharmony_ci			goto out_err;
227762306a36Sopenharmony_ci		sent++;
227862306a36Sopenharmony_ci	}
227962306a36Sopenharmony_ci#endif
228062306a36Sopenharmony_ci
228162306a36Sopenharmony_ci	scm_destroy(&scm);
228262306a36Sopenharmony_ci
228362306a36Sopenharmony_ci	return sent;
228462306a36Sopenharmony_ci
228562306a36Sopenharmony_cipipe_err_free:
228662306a36Sopenharmony_ci	unix_state_unlock(other);
228762306a36Sopenharmony_ci	kfree_skb(skb);
228862306a36Sopenharmony_cipipe_err:
228962306a36Sopenharmony_ci	if (sent == 0 && !(msg->msg_flags&MSG_NOSIGNAL))
229062306a36Sopenharmony_ci		send_sig(SIGPIPE, current, 0);
229162306a36Sopenharmony_ci	err = -EPIPE;
229262306a36Sopenharmony_ciout_err:
229362306a36Sopenharmony_ci	scm_destroy(&scm);
229462306a36Sopenharmony_ci	return sent ? : err;
229562306a36Sopenharmony_ci}
229662306a36Sopenharmony_ci
229762306a36Sopenharmony_cistatic int unix_seqpacket_sendmsg(struct socket *sock, struct msghdr *msg,
229862306a36Sopenharmony_ci				  size_t len)
229962306a36Sopenharmony_ci{
230062306a36Sopenharmony_ci	int err;
230162306a36Sopenharmony_ci	struct sock *sk = sock->sk;
230262306a36Sopenharmony_ci
230362306a36Sopenharmony_ci	err = sock_error(sk);
230462306a36Sopenharmony_ci	if (err)
230562306a36Sopenharmony_ci		return err;
230662306a36Sopenharmony_ci
230762306a36Sopenharmony_ci	if (sk->sk_state != TCP_ESTABLISHED)
230862306a36Sopenharmony_ci		return -ENOTCONN;
230962306a36Sopenharmony_ci
231062306a36Sopenharmony_ci	if (msg->msg_namelen)
231162306a36Sopenharmony_ci		msg->msg_namelen = 0;
231262306a36Sopenharmony_ci
231362306a36Sopenharmony_ci	return unix_dgram_sendmsg(sock, msg, len);
231462306a36Sopenharmony_ci}
231562306a36Sopenharmony_ci
231662306a36Sopenharmony_cistatic int unix_seqpacket_recvmsg(struct socket *sock, struct msghdr *msg,
231762306a36Sopenharmony_ci				  size_t size, int flags)
231862306a36Sopenharmony_ci{
231962306a36Sopenharmony_ci	struct sock *sk = sock->sk;
232062306a36Sopenharmony_ci
232162306a36Sopenharmony_ci	if (sk->sk_state != TCP_ESTABLISHED)
232262306a36Sopenharmony_ci		return -ENOTCONN;
232362306a36Sopenharmony_ci
232462306a36Sopenharmony_ci	return unix_dgram_recvmsg(sock, msg, size, flags);
232562306a36Sopenharmony_ci}
232662306a36Sopenharmony_ci
232762306a36Sopenharmony_cistatic void unix_copy_addr(struct msghdr *msg, struct sock *sk)
232862306a36Sopenharmony_ci{
232962306a36Sopenharmony_ci	struct unix_address *addr = smp_load_acquire(&unix_sk(sk)->addr);
233062306a36Sopenharmony_ci
233162306a36Sopenharmony_ci	if (addr) {
233262306a36Sopenharmony_ci		msg->msg_namelen = addr->len;
233362306a36Sopenharmony_ci		memcpy(msg->msg_name, addr->name, addr->len);
233462306a36Sopenharmony_ci	}
233562306a36Sopenharmony_ci}
233662306a36Sopenharmony_ci
233762306a36Sopenharmony_ciint __unix_dgram_recvmsg(struct sock *sk, struct msghdr *msg, size_t size,
233862306a36Sopenharmony_ci			 int flags)
233962306a36Sopenharmony_ci{
234062306a36Sopenharmony_ci	struct scm_cookie scm;
234162306a36Sopenharmony_ci	struct socket *sock = sk->sk_socket;
234262306a36Sopenharmony_ci	struct unix_sock *u = unix_sk(sk);
234362306a36Sopenharmony_ci	struct sk_buff *skb, *last;
234462306a36Sopenharmony_ci	long timeo;
234562306a36Sopenharmony_ci	int skip;
234662306a36Sopenharmony_ci	int err;
234762306a36Sopenharmony_ci
234862306a36Sopenharmony_ci	err = -EOPNOTSUPP;
234962306a36Sopenharmony_ci	if (flags&MSG_OOB)
235062306a36Sopenharmony_ci		goto out;
235162306a36Sopenharmony_ci
235262306a36Sopenharmony_ci	timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
235362306a36Sopenharmony_ci
235462306a36Sopenharmony_ci	do {
235562306a36Sopenharmony_ci		mutex_lock(&u->iolock);
235662306a36Sopenharmony_ci
235762306a36Sopenharmony_ci		skip = sk_peek_offset(sk, flags);
235862306a36Sopenharmony_ci		skb = __skb_try_recv_datagram(sk, &sk->sk_receive_queue, flags,
235962306a36Sopenharmony_ci					      &skip, &err, &last);
236062306a36Sopenharmony_ci		if (skb) {
236162306a36Sopenharmony_ci			if (!(flags & MSG_PEEK))
236262306a36Sopenharmony_ci				scm_stat_del(sk, skb);
236362306a36Sopenharmony_ci			break;
236462306a36Sopenharmony_ci		}
236562306a36Sopenharmony_ci
236662306a36Sopenharmony_ci		mutex_unlock(&u->iolock);
236762306a36Sopenharmony_ci
236862306a36Sopenharmony_ci		if (err != -EAGAIN)
236962306a36Sopenharmony_ci			break;
237062306a36Sopenharmony_ci	} while (timeo &&
237162306a36Sopenharmony_ci		 !__skb_wait_for_more_packets(sk, &sk->sk_receive_queue,
237262306a36Sopenharmony_ci					      &err, &timeo, last));
237362306a36Sopenharmony_ci
237462306a36Sopenharmony_ci	if (!skb) { /* implies iolock unlocked */
237562306a36Sopenharmony_ci		unix_state_lock(sk);
237662306a36Sopenharmony_ci		/* Signal EOF on disconnected non-blocking SEQPACKET socket. */
237762306a36Sopenharmony_ci		if (sk->sk_type == SOCK_SEQPACKET && err == -EAGAIN &&
237862306a36Sopenharmony_ci		    (sk->sk_shutdown & RCV_SHUTDOWN))
237962306a36Sopenharmony_ci			err = 0;
238062306a36Sopenharmony_ci		unix_state_unlock(sk);
238162306a36Sopenharmony_ci		goto out;
238262306a36Sopenharmony_ci	}
238362306a36Sopenharmony_ci
238462306a36Sopenharmony_ci	if (wq_has_sleeper(&u->peer_wait))
238562306a36Sopenharmony_ci		wake_up_interruptible_sync_poll(&u->peer_wait,
238662306a36Sopenharmony_ci						EPOLLOUT | EPOLLWRNORM |
238762306a36Sopenharmony_ci						EPOLLWRBAND);
238862306a36Sopenharmony_ci
238962306a36Sopenharmony_ci	if (msg->msg_name)
239062306a36Sopenharmony_ci		unix_copy_addr(msg, skb->sk);
239162306a36Sopenharmony_ci
239262306a36Sopenharmony_ci	if (size > skb->len - skip)
239362306a36Sopenharmony_ci		size = skb->len - skip;
239462306a36Sopenharmony_ci	else if (size < skb->len - skip)
239562306a36Sopenharmony_ci		msg->msg_flags |= MSG_TRUNC;
239662306a36Sopenharmony_ci
239762306a36Sopenharmony_ci	err = skb_copy_datagram_msg(skb, skip, msg, size);
239862306a36Sopenharmony_ci	if (err)
239962306a36Sopenharmony_ci		goto out_free;
240062306a36Sopenharmony_ci
240162306a36Sopenharmony_ci	if (sock_flag(sk, SOCK_RCVTSTAMP))
240262306a36Sopenharmony_ci		__sock_recv_timestamp(msg, sk, skb);
240362306a36Sopenharmony_ci
240462306a36Sopenharmony_ci	memset(&scm, 0, sizeof(scm));
240562306a36Sopenharmony_ci
240662306a36Sopenharmony_ci	scm_set_cred(&scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid);
240762306a36Sopenharmony_ci	unix_set_secdata(&scm, skb);
240862306a36Sopenharmony_ci
240962306a36Sopenharmony_ci	if (!(flags & MSG_PEEK)) {
241062306a36Sopenharmony_ci		if (UNIXCB(skb).fp)
241162306a36Sopenharmony_ci			unix_detach_fds(&scm, skb);
241262306a36Sopenharmony_ci
241362306a36Sopenharmony_ci		sk_peek_offset_bwd(sk, skb->len);
241462306a36Sopenharmony_ci	} else {
241562306a36Sopenharmony_ci		/* It is questionable: on PEEK we could:
241662306a36Sopenharmony_ci		   - do not return fds - good, but too simple 8)
241762306a36Sopenharmony_ci		   - return fds, and do not return them on read (old strategy,
241862306a36Sopenharmony_ci		     apparently wrong)
241962306a36Sopenharmony_ci		   - clone fds (I chose it for now, it is the most universal
242062306a36Sopenharmony_ci		     solution)
242162306a36Sopenharmony_ci
242262306a36Sopenharmony_ci		   POSIX 1003.1g does not actually define this clearly
242362306a36Sopenharmony_ci		   at all. POSIX 1003.1g doesn't define a lot of things
242462306a36Sopenharmony_ci		   clearly however!
242562306a36Sopenharmony_ci
242662306a36Sopenharmony_ci		*/
242762306a36Sopenharmony_ci
242862306a36Sopenharmony_ci		sk_peek_offset_fwd(sk, size);
242962306a36Sopenharmony_ci
243062306a36Sopenharmony_ci		if (UNIXCB(skb).fp)
243162306a36Sopenharmony_ci			unix_peek_fds(&scm, skb);
243262306a36Sopenharmony_ci	}
243362306a36Sopenharmony_ci	err = (flags & MSG_TRUNC) ? skb->len - skip : size;
243462306a36Sopenharmony_ci
243562306a36Sopenharmony_ci	scm_recv_unix(sock, msg, &scm, flags);
243662306a36Sopenharmony_ci
243762306a36Sopenharmony_ciout_free:
243862306a36Sopenharmony_ci	skb_free_datagram(sk, skb);
243962306a36Sopenharmony_ci	mutex_unlock(&u->iolock);
244062306a36Sopenharmony_ciout:
244162306a36Sopenharmony_ci	return err;
244262306a36Sopenharmony_ci}
244362306a36Sopenharmony_ci
244462306a36Sopenharmony_cistatic int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
244562306a36Sopenharmony_ci			      int flags)
244662306a36Sopenharmony_ci{
244762306a36Sopenharmony_ci	struct sock *sk = sock->sk;
244862306a36Sopenharmony_ci
244962306a36Sopenharmony_ci#ifdef CONFIG_BPF_SYSCALL
245062306a36Sopenharmony_ci	const struct proto *prot = READ_ONCE(sk->sk_prot);
245162306a36Sopenharmony_ci
245262306a36Sopenharmony_ci	if (prot != &unix_dgram_proto)
245362306a36Sopenharmony_ci		return prot->recvmsg(sk, msg, size, flags, NULL);
245462306a36Sopenharmony_ci#endif
245562306a36Sopenharmony_ci	return __unix_dgram_recvmsg(sk, msg, size, flags);
245662306a36Sopenharmony_ci}
245762306a36Sopenharmony_ci
245862306a36Sopenharmony_cistatic int unix_read_skb(struct sock *sk, skb_read_actor_t recv_actor)
245962306a36Sopenharmony_ci{
246062306a36Sopenharmony_ci	struct unix_sock *u = unix_sk(sk);
246162306a36Sopenharmony_ci	struct sk_buff *skb;
246262306a36Sopenharmony_ci	int err;
246362306a36Sopenharmony_ci
246462306a36Sopenharmony_ci	mutex_lock(&u->iolock);
246562306a36Sopenharmony_ci	skb = skb_recv_datagram(sk, MSG_DONTWAIT, &err);
246662306a36Sopenharmony_ci	mutex_unlock(&u->iolock);
246762306a36Sopenharmony_ci	if (!skb)
246862306a36Sopenharmony_ci		return err;
246962306a36Sopenharmony_ci
247062306a36Sopenharmony_ci	return recv_actor(sk, skb);
247162306a36Sopenharmony_ci}
247262306a36Sopenharmony_ci
247362306a36Sopenharmony_ci/*
247462306a36Sopenharmony_ci *	Sleep until more data has arrived. But check for races..
247562306a36Sopenharmony_ci */
247662306a36Sopenharmony_cistatic long unix_stream_data_wait(struct sock *sk, long timeo,
247762306a36Sopenharmony_ci				  struct sk_buff *last, unsigned int last_len,
247862306a36Sopenharmony_ci				  bool freezable)
247962306a36Sopenharmony_ci{
248062306a36Sopenharmony_ci	unsigned int state = TASK_INTERRUPTIBLE | freezable * TASK_FREEZABLE;
248162306a36Sopenharmony_ci	struct sk_buff *tail;
248262306a36Sopenharmony_ci	DEFINE_WAIT(wait);
248362306a36Sopenharmony_ci
248462306a36Sopenharmony_ci	unix_state_lock(sk);
248562306a36Sopenharmony_ci
248662306a36Sopenharmony_ci	for (;;) {
248762306a36Sopenharmony_ci		prepare_to_wait(sk_sleep(sk), &wait, state);
248862306a36Sopenharmony_ci
248962306a36Sopenharmony_ci		tail = skb_peek_tail(&sk->sk_receive_queue);
249062306a36Sopenharmony_ci		if (tail != last ||
249162306a36Sopenharmony_ci		    (tail && tail->len != last_len) ||
249262306a36Sopenharmony_ci		    sk->sk_err ||
249362306a36Sopenharmony_ci		    (sk->sk_shutdown & RCV_SHUTDOWN) ||
249462306a36Sopenharmony_ci		    signal_pending(current) ||
249562306a36Sopenharmony_ci		    !timeo)
249662306a36Sopenharmony_ci			break;
249762306a36Sopenharmony_ci
249862306a36Sopenharmony_ci		sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
249962306a36Sopenharmony_ci		unix_state_unlock(sk);
250062306a36Sopenharmony_ci		timeo = schedule_timeout(timeo);
250162306a36Sopenharmony_ci		unix_state_lock(sk);
250262306a36Sopenharmony_ci
250362306a36Sopenharmony_ci		if (sock_flag(sk, SOCK_DEAD))
250462306a36Sopenharmony_ci			break;
250562306a36Sopenharmony_ci
250662306a36Sopenharmony_ci		sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
250762306a36Sopenharmony_ci	}
250862306a36Sopenharmony_ci
250962306a36Sopenharmony_ci	finish_wait(sk_sleep(sk), &wait);
251062306a36Sopenharmony_ci	unix_state_unlock(sk);
251162306a36Sopenharmony_ci	return timeo;
251262306a36Sopenharmony_ci}
251362306a36Sopenharmony_ci
251462306a36Sopenharmony_cistatic unsigned int unix_skb_len(const struct sk_buff *skb)
251562306a36Sopenharmony_ci{
251662306a36Sopenharmony_ci	return skb->len - UNIXCB(skb).consumed;
251762306a36Sopenharmony_ci}
251862306a36Sopenharmony_ci
251962306a36Sopenharmony_cistruct unix_stream_read_state {
252062306a36Sopenharmony_ci	int (*recv_actor)(struct sk_buff *, int, int,
252162306a36Sopenharmony_ci			  struct unix_stream_read_state *);
252262306a36Sopenharmony_ci	struct socket *socket;
252362306a36Sopenharmony_ci	struct msghdr *msg;
252462306a36Sopenharmony_ci	struct pipe_inode_info *pipe;
252562306a36Sopenharmony_ci	size_t size;
252662306a36Sopenharmony_ci	int flags;
252762306a36Sopenharmony_ci	unsigned int splice_flags;
252862306a36Sopenharmony_ci};
252962306a36Sopenharmony_ci
253062306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_AF_UNIX_OOB)
253162306a36Sopenharmony_cistatic int unix_stream_recv_urg(struct unix_stream_read_state *state)
253262306a36Sopenharmony_ci{
253362306a36Sopenharmony_ci	struct socket *sock = state->socket;
253462306a36Sopenharmony_ci	struct sock *sk = sock->sk;
253562306a36Sopenharmony_ci	struct unix_sock *u = unix_sk(sk);
253662306a36Sopenharmony_ci	int chunk = 1;
253762306a36Sopenharmony_ci	struct sk_buff *oob_skb;
253862306a36Sopenharmony_ci
253962306a36Sopenharmony_ci	mutex_lock(&u->iolock);
254062306a36Sopenharmony_ci	unix_state_lock(sk);
254162306a36Sopenharmony_ci
254262306a36Sopenharmony_ci	if (sock_flag(sk, SOCK_URGINLINE) || !u->oob_skb) {
254362306a36Sopenharmony_ci		unix_state_unlock(sk);
254462306a36Sopenharmony_ci		mutex_unlock(&u->iolock);
254562306a36Sopenharmony_ci		return -EINVAL;
254662306a36Sopenharmony_ci	}
254762306a36Sopenharmony_ci
254862306a36Sopenharmony_ci	oob_skb = u->oob_skb;
254962306a36Sopenharmony_ci
255062306a36Sopenharmony_ci	if (!(state->flags & MSG_PEEK))
255162306a36Sopenharmony_ci		WRITE_ONCE(u->oob_skb, NULL);
255262306a36Sopenharmony_ci	else
255362306a36Sopenharmony_ci		skb_get(oob_skb);
255462306a36Sopenharmony_ci	unix_state_unlock(sk);
255562306a36Sopenharmony_ci
255662306a36Sopenharmony_ci	chunk = state->recv_actor(oob_skb, 0, chunk, state);
255762306a36Sopenharmony_ci
255862306a36Sopenharmony_ci	if (!(state->flags & MSG_PEEK))
255962306a36Sopenharmony_ci		UNIXCB(oob_skb).consumed += 1;
256062306a36Sopenharmony_ci
256162306a36Sopenharmony_ci	consume_skb(oob_skb);
256262306a36Sopenharmony_ci
256362306a36Sopenharmony_ci	mutex_unlock(&u->iolock);
256462306a36Sopenharmony_ci
256562306a36Sopenharmony_ci	if (chunk < 0)
256662306a36Sopenharmony_ci		return -EFAULT;
256762306a36Sopenharmony_ci
256862306a36Sopenharmony_ci	state->msg->msg_flags |= MSG_OOB;
256962306a36Sopenharmony_ci	return 1;
257062306a36Sopenharmony_ci}
257162306a36Sopenharmony_ci
257262306a36Sopenharmony_cistatic struct sk_buff *manage_oob(struct sk_buff *skb, struct sock *sk,
257362306a36Sopenharmony_ci				  int flags, int copied)
257462306a36Sopenharmony_ci{
257562306a36Sopenharmony_ci	struct unix_sock *u = unix_sk(sk);
257662306a36Sopenharmony_ci
257762306a36Sopenharmony_ci	if (!unix_skb_len(skb) && !(flags & MSG_PEEK)) {
257862306a36Sopenharmony_ci		skb_unlink(skb, &sk->sk_receive_queue);
257962306a36Sopenharmony_ci		consume_skb(skb);
258062306a36Sopenharmony_ci		skb = NULL;
258162306a36Sopenharmony_ci	} else {
258262306a36Sopenharmony_ci		if (skb == u->oob_skb) {
258362306a36Sopenharmony_ci			if (copied) {
258462306a36Sopenharmony_ci				skb = NULL;
258562306a36Sopenharmony_ci			} else if (sock_flag(sk, SOCK_URGINLINE)) {
258662306a36Sopenharmony_ci				if (!(flags & MSG_PEEK)) {
258762306a36Sopenharmony_ci					WRITE_ONCE(u->oob_skb, NULL);
258862306a36Sopenharmony_ci					consume_skb(skb);
258962306a36Sopenharmony_ci				}
259062306a36Sopenharmony_ci			} else if (!(flags & MSG_PEEK)) {
259162306a36Sopenharmony_ci				skb_unlink(skb, &sk->sk_receive_queue);
259262306a36Sopenharmony_ci				consume_skb(skb);
259362306a36Sopenharmony_ci				skb = skb_peek(&sk->sk_receive_queue);
259462306a36Sopenharmony_ci			}
259562306a36Sopenharmony_ci		}
259662306a36Sopenharmony_ci	}
259762306a36Sopenharmony_ci	return skb;
259862306a36Sopenharmony_ci}
259962306a36Sopenharmony_ci#endif
260062306a36Sopenharmony_ci
260162306a36Sopenharmony_cistatic int unix_stream_read_skb(struct sock *sk, skb_read_actor_t recv_actor)
260262306a36Sopenharmony_ci{
260362306a36Sopenharmony_ci	if (unlikely(sk->sk_state != TCP_ESTABLISHED))
260462306a36Sopenharmony_ci		return -ENOTCONN;
260562306a36Sopenharmony_ci
260662306a36Sopenharmony_ci	return unix_read_skb(sk, recv_actor);
260762306a36Sopenharmony_ci}
260862306a36Sopenharmony_ci
260962306a36Sopenharmony_cistatic int unix_stream_read_generic(struct unix_stream_read_state *state,
261062306a36Sopenharmony_ci				    bool freezable)
261162306a36Sopenharmony_ci{
261262306a36Sopenharmony_ci	struct scm_cookie scm;
261362306a36Sopenharmony_ci	struct socket *sock = state->socket;
261462306a36Sopenharmony_ci	struct sock *sk = sock->sk;
261562306a36Sopenharmony_ci	struct unix_sock *u = unix_sk(sk);
261662306a36Sopenharmony_ci	int copied = 0;
261762306a36Sopenharmony_ci	int flags = state->flags;
261862306a36Sopenharmony_ci	int noblock = flags & MSG_DONTWAIT;
261962306a36Sopenharmony_ci	bool check_creds = false;
262062306a36Sopenharmony_ci	int target;
262162306a36Sopenharmony_ci	int err = 0;
262262306a36Sopenharmony_ci	long timeo;
262362306a36Sopenharmony_ci	int skip;
262462306a36Sopenharmony_ci	size_t size = state->size;
262562306a36Sopenharmony_ci	unsigned int last_len;
262662306a36Sopenharmony_ci
262762306a36Sopenharmony_ci	if (unlikely(sk->sk_state != TCP_ESTABLISHED)) {
262862306a36Sopenharmony_ci		err = -EINVAL;
262962306a36Sopenharmony_ci		goto out;
263062306a36Sopenharmony_ci	}
263162306a36Sopenharmony_ci
263262306a36Sopenharmony_ci	if (unlikely(flags & MSG_OOB)) {
263362306a36Sopenharmony_ci		err = -EOPNOTSUPP;
263462306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_AF_UNIX_OOB)
263562306a36Sopenharmony_ci		err = unix_stream_recv_urg(state);
263662306a36Sopenharmony_ci#endif
263762306a36Sopenharmony_ci		goto out;
263862306a36Sopenharmony_ci	}
263962306a36Sopenharmony_ci
264062306a36Sopenharmony_ci	target = sock_rcvlowat(sk, flags & MSG_WAITALL, size);
264162306a36Sopenharmony_ci	timeo = sock_rcvtimeo(sk, noblock);
264262306a36Sopenharmony_ci
264362306a36Sopenharmony_ci	memset(&scm, 0, sizeof(scm));
264462306a36Sopenharmony_ci
264562306a36Sopenharmony_ci	/* Lock the socket to prevent queue disordering
264662306a36Sopenharmony_ci	 * while sleeps in memcpy_tomsg
264762306a36Sopenharmony_ci	 */
264862306a36Sopenharmony_ci	mutex_lock(&u->iolock);
264962306a36Sopenharmony_ci
265062306a36Sopenharmony_ci	skip = max(sk_peek_offset(sk, flags), 0);
265162306a36Sopenharmony_ci
265262306a36Sopenharmony_ci	do {
265362306a36Sopenharmony_ci		int chunk;
265462306a36Sopenharmony_ci		bool drop_skb;
265562306a36Sopenharmony_ci		struct sk_buff *skb, *last;
265662306a36Sopenharmony_ci
265762306a36Sopenharmony_ciredo:
265862306a36Sopenharmony_ci		unix_state_lock(sk);
265962306a36Sopenharmony_ci		if (sock_flag(sk, SOCK_DEAD)) {
266062306a36Sopenharmony_ci			err = -ECONNRESET;
266162306a36Sopenharmony_ci			goto unlock;
266262306a36Sopenharmony_ci		}
266362306a36Sopenharmony_ci		last = skb = skb_peek(&sk->sk_receive_queue);
266462306a36Sopenharmony_ci		last_len = last ? last->len : 0;
266562306a36Sopenharmony_ci
266662306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_AF_UNIX_OOB)
266762306a36Sopenharmony_ci		if (skb) {
266862306a36Sopenharmony_ci			skb = manage_oob(skb, sk, flags, copied);
266962306a36Sopenharmony_ci			if (!skb) {
267062306a36Sopenharmony_ci				unix_state_unlock(sk);
267162306a36Sopenharmony_ci				if (copied)
267262306a36Sopenharmony_ci					break;
267362306a36Sopenharmony_ci				goto redo;
267462306a36Sopenharmony_ci			}
267562306a36Sopenharmony_ci		}
267662306a36Sopenharmony_ci#endif
267762306a36Sopenharmony_ciagain:
267862306a36Sopenharmony_ci		if (skb == NULL) {
267962306a36Sopenharmony_ci			if (copied >= target)
268062306a36Sopenharmony_ci				goto unlock;
268162306a36Sopenharmony_ci
268262306a36Sopenharmony_ci			/*
268362306a36Sopenharmony_ci			 *	POSIX 1003.1g mandates this order.
268462306a36Sopenharmony_ci			 */
268562306a36Sopenharmony_ci
268662306a36Sopenharmony_ci			err = sock_error(sk);
268762306a36Sopenharmony_ci			if (err)
268862306a36Sopenharmony_ci				goto unlock;
268962306a36Sopenharmony_ci			if (sk->sk_shutdown & RCV_SHUTDOWN)
269062306a36Sopenharmony_ci				goto unlock;
269162306a36Sopenharmony_ci
269262306a36Sopenharmony_ci			unix_state_unlock(sk);
269362306a36Sopenharmony_ci			if (!timeo) {
269462306a36Sopenharmony_ci				err = -EAGAIN;
269562306a36Sopenharmony_ci				break;
269662306a36Sopenharmony_ci			}
269762306a36Sopenharmony_ci
269862306a36Sopenharmony_ci			mutex_unlock(&u->iolock);
269962306a36Sopenharmony_ci
270062306a36Sopenharmony_ci			timeo = unix_stream_data_wait(sk, timeo, last,
270162306a36Sopenharmony_ci						      last_len, freezable);
270262306a36Sopenharmony_ci
270362306a36Sopenharmony_ci			if (signal_pending(current)) {
270462306a36Sopenharmony_ci				err = sock_intr_errno(timeo);
270562306a36Sopenharmony_ci				scm_destroy(&scm);
270662306a36Sopenharmony_ci				goto out;
270762306a36Sopenharmony_ci			}
270862306a36Sopenharmony_ci
270962306a36Sopenharmony_ci			mutex_lock(&u->iolock);
271062306a36Sopenharmony_ci			goto redo;
271162306a36Sopenharmony_ciunlock:
271262306a36Sopenharmony_ci			unix_state_unlock(sk);
271362306a36Sopenharmony_ci			break;
271462306a36Sopenharmony_ci		}
271562306a36Sopenharmony_ci
271662306a36Sopenharmony_ci		while (skip >= unix_skb_len(skb)) {
271762306a36Sopenharmony_ci			skip -= unix_skb_len(skb);
271862306a36Sopenharmony_ci			last = skb;
271962306a36Sopenharmony_ci			last_len = skb->len;
272062306a36Sopenharmony_ci			skb = skb_peek_next(skb, &sk->sk_receive_queue);
272162306a36Sopenharmony_ci			if (!skb)
272262306a36Sopenharmony_ci				goto again;
272362306a36Sopenharmony_ci		}
272462306a36Sopenharmony_ci
272562306a36Sopenharmony_ci		unix_state_unlock(sk);
272662306a36Sopenharmony_ci
272762306a36Sopenharmony_ci		if (check_creds) {
272862306a36Sopenharmony_ci			/* Never glue messages from different writers */
272962306a36Sopenharmony_ci			if (!unix_skb_scm_eq(skb, &scm))
273062306a36Sopenharmony_ci				break;
273162306a36Sopenharmony_ci		} else if (test_bit(SOCK_PASSCRED, &sock->flags) ||
273262306a36Sopenharmony_ci			   test_bit(SOCK_PASSPIDFD, &sock->flags)) {
273362306a36Sopenharmony_ci			/* Copy credentials */
273462306a36Sopenharmony_ci			scm_set_cred(&scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid);
273562306a36Sopenharmony_ci			unix_set_secdata(&scm, skb);
273662306a36Sopenharmony_ci			check_creds = true;
273762306a36Sopenharmony_ci		}
273862306a36Sopenharmony_ci
273962306a36Sopenharmony_ci		/* Copy address just once */
274062306a36Sopenharmony_ci		if (state->msg && state->msg->msg_name) {
274162306a36Sopenharmony_ci			DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr,
274262306a36Sopenharmony_ci					 state->msg->msg_name);
274362306a36Sopenharmony_ci			unix_copy_addr(state->msg, skb->sk);
274462306a36Sopenharmony_ci			sunaddr = NULL;
274562306a36Sopenharmony_ci		}
274662306a36Sopenharmony_ci
274762306a36Sopenharmony_ci		chunk = min_t(unsigned int, unix_skb_len(skb) - skip, size);
274862306a36Sopenharmony_ci		skb_get(skb);
274962306a36Sopenharmony_ci		chunk = state->recv_actor(skb, skip, chunk, state);
275062306a36Sopenharmony_ci		drop_skb = !unix_skb_len(skb);
275162306a36Sopenharmony_ci		/* skb is only safe to use if !drop_skb */
275262306a36Sopenharmony_ci		consume_skb(skb);
275362306a36Sopenharmony_ci		if (chunk < 0) {
275462306a36Sopenharmony_ci			if (copied == 0)
275562306a36Sopenharmony_ci				copied = -EFAULT;
275662306a36Sopenharmony_ci			break;
275762306a36Sopenharmony_ci		}
275862306a36Sopenharmony_ci		copied += chunk;
275962306a36Sopenharmony_ci		size -= chunk;
276062306a36Sopenharmony_ci
276162306a36Sopenharmony_ci		if (drop_skb) {
276262306a36Sopenharmony_ci			/* the skb was touched by a concurrent reader;
276362306a36Sopenharmony_ci			 * we should not expect anything from this skb
276462306a36Sopenharmony_ci			 * anymore and assume it invalid - we can be
276562306a36Sopenharmony_ci			 * sure it was dropped from the socket queue
276662306a36Sopenharmony_ci			 *
276762306a36Sopenharmony_ci			 * let's report a short read
276862306a36Sopenharmony_ci			 */
276962306a36Sopenharmony_ci			err = 0;
277062306a36Sopenharmony_ci			break;
277162306a36Sopenharmony_ci		}
277262306a36Sopenharmony_ci
277362306a36Sopenharmony_ci		/* Mark read part of skb as used */
277462306a36Sopenharmony_ci		if (!(flags & MSG_PEEK)) {
277562306a36Sopenharmony_ci			UNIXCB(skb).consumed += chunk;
277662306a36Sopenharmony_ci
277762306a36Sopenharmony_ci			sk_peek_offset_bwd(sk, chunk);
277862306a36Sopenharmony_ci
277962306a36Sopenharmony_ci			if (UNIXCB(skb).fp) {
278062306a36Sopenharmony_ci				scm_stat_del(sk, skb);
278162306a36Sopenharmony_ci				unix_detach_fds(&scm, skb);
278262306a36Sopenharmony_ci			}
278362306a36Sopenharmony_ci
278462306a36Sopenharmony_ci			if (unix_skb_len(skb))
278562306a36Sopenharmony_ci				break;
278662306a36Sopenharmony_ci
278762306a36Sopenharmony_ci			skb_unlink(skb, &sk->sk_receive_queue);
278862306a36Sopenharmony_ci			consume_skb(skb);
278962306a36Sopenharmony_ci
279062306a36Sopenharmony_ci			if (scm.fp)
279162306a36Sopenharmony_ci				break;
279262306a36Sopenharmony_ci		} else {
279362306a36Sopenharmony_ci			/* It is questionable, see note in unix_dgram_recvmsg.
279462306a36Sopenharmony_ci			 */
279562306a36Sopenharmony_ci			if (UNIXCB(skb).fp)
279662306a36Sopenharmony_ci				unix_peek_fds(&scm, skb);
279762306a36Sopenharmony_ci
279862306a36Sopenharmony_ci			sk_peek_offset_fwd(sk, chunk);
279962306a36Sopenharmony_ci
280062306a36Sopenharmony_ci			if (UNIXCB(skb).fp)
280162306a36Sopenharmony_ci				break;
280262306a36Sopenharmony_ci
280362306a36Sopenharmony_ci			skip = 0;
280462306a36Sopenharmony_ci			last = skb;
280562306a36Sopenharmony_ci			last_len = skb->len;
280662306a36Sopenharmony_ci			unix_state_lock(sk);
280762306a36Sopenharmony_ci			skb = skb_peek_next(skb, &sk->sk_receive_queue);
280862306a36Sopenharmony_ci			if (skb)
280962306a36Sopenharmony_ci				goto again;
281062306a36Sopenharmony_ci			unix_state_unlock(sk);
281162306a36Sopenharmony_ci			break;
281262306a36Sopenharmony_ci		}
281362306a36Sopenharmony_ci	} while (size);
281462306a36Sopenharmony_ci
281562306a36Sopenharmony_ci	mutex_unlock(&u->iolock);
281662306a36Sopenharmony_ci	if (state->msg)
281762306a36Sopenharmony_ci		scm_recv_unix(sock, state->msg, &scm, flags);
281862306a36Sopenharmony_ci	else
281962306a36Sopenharmony_ci		scm_destroy(&scm);
282062306a36Sopenharmony_ciout:
282162306a36Sopenharmony_ci	return copied ? : err;
282262306a36Sopenharmony_ci}
282362306a36Sopenharmony_ci
282462306a36Sopenharmony_cistatic int unix_stream_read_actor(struct sk_buff *skb,
282562306a36Sopenharmony_ci				  int skip, int chunk,
282662306a36Sopenharmony_ci				  struct unix_stream_read_state *state)
282762306a36Sopenharmony_ci{
282862306a36Sopenharmony_ci	int ret;
282962306a36Sopenharmony_ci
283062306a36Sopenharmony_ci	ret = skb_copy_datagram_msg(skb, UNIXCB(skb).consumed + skip,
283162306a36Sopenharmony_ci				    state->msg, chunk);
283262306a36Sopenharmony_ci	return ret ?: chunk;
283362306a36Sopenharmony_ci}
283462306a36Sopenharmony_ci
283562306a36Sopenharmony_ciint __unix_stream_recvmsg(struct sock *sk, struct msghdr *msg,
283662306a36Sopenharmony_ci			  size_t size, int flags)
283762306a36Sopenharmony_ci{
283862306a36Sopenharmony_ci	struct unix_stream_read_state state = {
283962306a36Sopenharmony_ci		.recv_actor = unix_stream_read_actor,
284062306a36Sopenharmony_ci		.socket = sk->sk_socket,
284162306a36Sopenharmony_ci		.msg = msg,
284262306a36Sopenharmony_ci		.size = size,
284362306a36Sopenharmony_ci		.flags = flags
284462306a36Sopenharmony_ci	};
284562306a36Sopenharmony_ci
284662306a36Sopenharmony_ci	return unix_stream_read_generic(&state, true);
284762306a36Sopenharmony_ci}
284862306a36Sopenharmony_ci
284962306a36Sopenharmony_cistatic int unix_stream_recvmsg(struct socket *sock, struct msghdr *msg,
285062306a36Sopenharmony_ci			       size_t size, int flags)
285162306a36Sopenharmony_ci{
285262306a36Sopenharmony_ci	struct unix_stream_read_state state = {
285362306a36Sopenharmony_ci		.recv_actor = unix_stream_read_actor,
285462306a36Sopenharmony_ci		.socket = sock,
285562306a36Sopenharmony_ci		.msg = msg,
285662306a36Sopenharmony_ci		.size = size,
285762306a36Sopenharmony_ci		.flags = flags
285862306a36Sopenharmony_ci	};
285962306a36Sopenharmony_ci
286062306a36Sopenharmony_ci#ifdef CONFIG_BPF_SYSCALL
286162306a36Sopenharmony_ci	struct sock *sk = sock->sk;
286262306a36Sopenharmony_ci	const struct proto *prot = READ_ONCE(sk->sk_prot);
286362306a36Sopenharmony_ci
286462306a36Sopenharmony_ci	if (prot != &unix_stream_proto)
286562306a36Sopenharmony_ci		return prot->recvmsg(sk, msg, size, flags, NULL);
286662306a36Sopenharmony_ci#endif
286762306a36Sopenharmony_ci	return unix_stream_read_generic(&state, true);
286862306a36Sopenharmony_ci}
286962306a36Sopenharmony_ci
287062306a36Sopenharmony_cistatic int unix_stream_splice_actor(struct sk_buff *skb,
287162306a36Sopenharmony_ci				    int skip, int chunk,
287262306a36Sopenharmony_ci				    struct unix_stream_read_state *state)
287362306a36Sopenharmony_ci{
287462306a36Sopenharmony_ci	return skb_splice_bits(skb, state->socket->sk,
287562306a36Sopenharmony_ci			       UNIXCB(skb).consumed + skip,
287662306a36Sopenharmony_ci			       state->pipe, chunk, state->splice_flags);
287762306a36Sopenharmony_ci}
287862306a36Sopenharmony_ci
287962306a36Sopenharmony_cistatic ssize_t unix_stream_splice_read(struct socket *sock,  loff_t *ppos,
288062306a36Sopenharmony_ci				       struct pipe_inode_info *pipe,
288162306a36Sopenharmony_ci				       size_t size, unsigned int flags)
288262306a36Sopenharmony_ci{
288362306a36Sopenharmony_ci	struct unix_stream_read_state state = {
288462306a36Sopenharmony_ci		.recv_actor = unix_stream_splice_actor,
288562306a36Sopenharmony_ci		.socket = sock,
288662306a36Sopenharmony_ci		.pipe = pipe,
288762306a36Sopenharmony_ci		.size = size,
288862306a36Sopenharmony_ci		.splice_flags = flags,
288962306a36Sopenharmony_ci	};
289062306a36Sopenharmony_ci
289162306a36Sopenharmony_ci	if (unlikely(*ppos))
289262306a36Sopenharmony_ci		return -ESPIPE;
289362306a36Sopenharmony_ci
289462306a36Sopenharmony_ci	if (sock->file->f_flags & O_NONBLOCK ||
289562306a36Sopenharmony_ci	    flags & SPLICE_F_NONBLOCK)
289662306a36Sopenharmony_ci		state.flags = MSG_DONTWAIT;
289762306a36Sopenharmony_ci
289862306a36Sopenharmony_ci	return unix_stream_read_generic(&state, false);
289962306a36Sopenharmony_ci}
290062306a36Sopenharmony_ci
290162306a36Sopenharmony_cistatic int unix_shutdown(struct socket *sock, int mode)
290262306a36Sopenharmony_ci{
290362306a36Sopenharmony_ci	struct sock *sk = sock->sk;
290462306a36Sopenharmony_ci	struct sock *other;
290562306a36Sopenharmony_ci
290662306a36Sopenharmony_ci	if (mode < SHUT_RD || mode > SHUT_RDWR)
290762306a36Sopenharmony_ci		return -EINVAL;
290862306a36Sopenharmony_ci	/* This maps:
290962306a36Sopenharmony_ci	 * SHUT_RD   (0) -> RCV_SHUTDOWN  (1)
291062306a36Sopenharmony_ci	 * SHUT_WR   (1) -> SEND_SHUTDOWN (2)
291162306a36Sopenharmony_ci	 * SHUT_RDWR (2) -> SHUTDOWN_MASK (3)
291262306a36Sopenharmony_ci	 */
291362306a36Sopenharmony_ci	++mode;
291462306a36Sopenharmony_ci
291562306a36Sopenharmony_ci	unix_state_lock(sk);
291662306a36Sopenharmony_ci	WRITE_ONCE(sk->sk_shutdown, sk->sk_shutdown | mode);
291762306a36Sopenharmony_ci	other = unix_peer(sk);
291862306a36Sopenharmony_ci	if (other)
291962306a36Sopenharmony_ci		sock_hold(other);
292062306a36Sopenharmony_ci	unix_state_unlock(sk);
292162306a36Sopenharmony_ci	sk->sk_state_change(sk);
292262306a36Sopenharmony_ci
292362306a36Sopenharmony_ci	if (other &&
292462306a36Sopenharmony_ci		(sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET)) {
292562306a36Sopenharmony_ci
292662306a36Sopenharmony_ci		int peer_mode = 0;
292762306a36Sopenharmony_ci		const struct proto *prot = READ_ONCE(other->sk_prot);
292862306a36Sopenharmony_ci
292962306a36Sopenharmony_ci		if (prot->unhash)
293062306a36Sopenharmony_ci			prot->unhash(other);
293162306a36Sopenharmony_ci		if (mode&RCV_SHUTDOWN)
293262306a36Sopenharmony_ci			peer_mode |= SEND_SHUTDOWN;
293362306a36Sopenharmony_ci		if (mode&SEND_SHUTDOWN)
293462306a36Sopenharmony_ci			peer_mode |= RCV_SHUTDOWN;
293562306a36Sopenharmony_ci		unix_state_lock(other);
293662306a36Sopenharmony_ci		WRITE_ONCE(other->sk_shutdown, other->sk_shutdown | peer_mode);
293762306a36Sopenharmony_ci		unix_state_unlock(other);
293862306a36Sopenharmony_ci		other->sk_state_change(other);
293962306a36Sopenharmony_ci		if (peer_mode == SHUTDOWN_MASK)
294062306a36Sopenharmony_ci			sk_wake_async(other, SOCK_WAKE_WAITD, POLL_HUP);
294162306a36Sopenharmony_ci		else if (peer_mode & RCV_SHUTDOWN)
294262306a36Sopenharmony_ci			sk_wake_async(other, SOCK_WAKE_WAITD, POLL_IN);
294362306a36Sopenharmony_ci	}
294462306a36Sopenharmony_ci	if (other)
294562306a36Sopenharmony_ci		sock_put(other);
294662306a36Sopenharmony_ci
294762306a36Sopenharmony_ci	return 0;
294862306a36Sopenharmony_ci}
294962306a36Sopenharmony_ci
295062306a36Sopenharmony_cilong unix_inq_len(struct sock *sk)
295162306a36Sopenharmony_ci{
295262306a36Sopenharmony_ci	struct sk_buff *skb;
295362306a36Sopenharmony_ci	long amount = 0;
295462306a36Sopenharmony_ci
295562306a36Sopenharmony_ci	if (sk->sk_state == TCP_LISTEN)
295662306a36Sopenharmony_ci		return -EINVAL;
295762306a36Sopenharmony_ci
295862306a36Sopenharmony_ci	spin_lock(&sk->sk_receive_queue.lock);
295962306a36Sopenharmony_ci	if (sk->sk_type == SOCK_STREAM ||
296062306a36Sopenharmony_ci	    sk->sk_type == SOCK_SEQPACKET) {
296162306a36Sopenharmony_ci		skb_queue_walk(&sk->sk_receive_queue, skb)
296262306a36Sopenharmony_ci			amount += unix_skb_len(skb);
296362306a36Sopenharmony_ci	} else {
296462306a36Sopenharmony_ci		skb = skb_peek(&sk->sk_receive_queue);
296562306a36Sopenharmony_ci		if (skb)
296662306a36Sopenharmony_ci			amount = skb->len;
296762306a36Sopenharmony_ci	}
296862306a36Sopenharmony_ci	spin_unlock(&sk->sk_receive_queue.lock);
296962306a36Sopenharmony_ci
297062306a36Sopenharmony_ci	return amount;
297162306a36Sopenharmony_ci}
297262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(unix_inq_len);
297362306a36Sopenharmony_ci
297462306a36Sopenharmony_cilong unix_outq_len(struct sock *sk)
297562306a36Sopenharmony_ci{
297662306a36Sopenharmony_ci	return sk_wmem_alloc_get(sk);
297762306a36Sopenharmony_ci}
297862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(unix_outq_len);
297962306a36Sopenharmony_ci
298062306a36Sopenharmony_cistatic int unix_open_file(struct sock *sk)
298162306a36Sopenharmony_ci{
298262306a36Sopenharmony_ci	struct path path;
298362306a36Sopenharmony_ci	struct file *f;
298462306a36Sopenharmony_ci	int fd;
298562306a36Sopenharmony_ci
298662306a36Sopenharmony_ci	if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
298762306a36Sopenharmony_ci		return -EPERM;
298862306a36Sopenharmony_ci
298962306a36Sopenharmony_ci	if (!smp_load_acquire(&unix_sk(sk)->addr))
299062306a36Sopenharmony_ci		return -ENOENT;
299162306a36Sopenharmony_ci
299262306a36Sopenharmony_ci	path = unix_sk(sk)->path;
299362306a36Sopenharmony_ci	if (!path.dentry)
299462306a36Sopenharmony_ci		return -ENOENT;
299562306a36Sopenharmony_ci
299662306a36Sopenharmony_ci	path_get(&path);
299762306a36Sopenharmony_ci
299862306a36Sopenharmony_ci	fd = get_unused_fd_flags(O_CLOEXEC);
299962306a36Sopenharmony_ci	if (fd < 0)
300062306a36Sopenharmony_ci		goto out;
300162306a36Sopenharmony_ci
300262306a36Sopenharmony_ci	f = dentry_open(&path, O_PATH, current_cred());
300362306a36Sopenharmony_ci	if (IS_ERR(f)) {
300462306a36Sopenharmony_ci		put_unused_fd(fd);
300562306a36Sopenharmony_ci		fd = PTR_ERR(f);
300662306a36Sopenharmony_ci		goto out;
300762306a36Sopenharmony_ci	}
300862306a36Sopenharmony_ci
300962306a36Sopenharmony_ci	fd_install(fd, f);
301062306a36Sopenharmony_ciout:
301162306a36Sopenharmony_ci	path_put(&path);
301262306a36Sopenharmony_ci
301362306a36Sopenharmony_ci	return fd;
301462306a36Sopenharmony_ci}
301562306a36Sopenharmony_ci
301662306a36Sopenharmony_cistatic int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
301762306a36Sopenharmony_ci{
301862306a36Sopenharmony_ci	struct sock *sk = sock->sk;
301962306a36Sopenharmony_ci	long amount = 0;
302062306a36Sopenharmony_ci	int err;
302162306a36Sopenharmony_ci
302262306a36Sopenharmony_ci	switch (cmd) {
302362306a36Sopenharmony_ci	case SIOCOUTQ:
302462306a36Sopenharmony_ci		amount = unix_outq_len(sk);
302562306a36Sopenharmony_ci		err = put_user(amount, (int __user *)arg);
302662306a36Sopenharmony_ci		break;
302762306a36Sopenharmony_ci	case SIOCINQ:
302862306a36Sopenharmony_ci		amount = unix_inq_len(sk);
302962306a36Sopenharmony_ci		if (amount < 0)
303062306a36Sopenharmony_ci			err = amount;
303162306a36Sopenharmony_ci		else
303262306a36Sopenharmony_ci			err = put_user(amount, (int __user *)arg);
303362306a36Sopenharmony_ci		break;
303462306a36Sopenharmony_ci	case SIOCUNIXFILE:
303562306a36Sopenharmony_ci		err = unix_open_file(sk);
303662306a36Sopenharmony_ci		break;
303762306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_AF_UNIX_OOB)
303862306a36Sopenharmony_ci	case SIOCATMARK:
303962306a36Sopenharmony_ci		{
304062306a36Sopenharmony_ci			struct sk_buff *skb;
304162306a36Sopenharmony_ci			int answ = 0;
304262306a36Sopenharmony_ci
304362306a36Sopenharmony_ci			skb = skb_peek(&sk->sk_receive_queue);
304462306a36Sopenharmony_ci			if (skb && skb == READ_ONCE(unix_sk(sk)->oob_skb))
304562306a36Sopenharmony_ci				answ = 1;
304662306a36Sopenharmony_ci			err = put_user(answ, (int __user *)arg);
304762306a36Sopenharmony_ci		}
304862306a36Sopenharmony_ci		break;
304962306a36Sopenharmony_ci#endif
305062306a36Sopenharmony_ci	default:
305162306a36Sopenharmony_ci		err = -ENOIOCTLCMD;
305262306a36Sopenharmony_ci		break;
305362306a36Sopenharmony_ci	}
305462306a36Sopenharmony_ci	return err;
305562306a36Sopenharmony_ci}
305662306a36Sopenharmony_ci
305762306a36Sopenharmony_ci#ifdef CONFIG_COMPAT
305862306a36Sopenharmony_cistatic int unix_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
305962306a36Sopenharmony_ci{
306062306a36Sopenharmony_ci	return unix_ioctl(sock, cmd, (unsigned long)compat_ptr(arg));
306162306a36Sopenharmony_ci}
306262306a36Sopenharmony_ci#endif
306362306a36Sopenharmony_ci
306462306a36Sopenharmony_cistatic __poll_t unix_poll(struct file *file, struct socket *sock, poll_table *wait)
306562306a36Sopenharmony_ci{
306662306a36Sopenharmony_ci	struct sock *sk = sock->sk;
306762306a36Sopenharmony_ci	__poll_t mask;
306862306a36Sopenharmony_ci	u8 shutdown;
306962306a36Sopenharmony_ci
307062306a36Sopenharmony_ci	sock_poll_wait(file, sock, wait);
307162306a36Sopenharmony_ci	mask = 0;
307262306a36Sopenharmony_ci	shutdown = READ_ONCE(sk->sk_shutdown);
307362306a36Sopenharmony_ci
307462306a36Sopenharmony_ci	/* exceptional events? */
307562306a36Sopenharmony_ci	if (READ_ONCE(sk->sk_err))
307662306a36Sopenharmony_ci		mask |= EPOLLERR;
307762306a36Sopenharmony_ci	if (shutdown == SHUTDOWN_MASK)
307862306a36Sopenharmony_ci		mask |= EPOLLHUP;
307962306a36Sopenharmony_ci	if (shutdown & RCV_SHUTDOWN)
308062306a36Sopenharmony_ci		mask |= EPOLLRDHUP | EPOLLIN | EPOLLRDNORM;
308162306a36Sopenharmony_ci
308262306a36Sopenharmony_ci	/* readable? */
308362306a36Sopenharmony_ci	if (!skb_queue_empty_lockless(&sk->sk_receive_queue))
308462306a36Sopenharmony_ci		mask |= EPOLLIN | EPOLLRDNORM;
308562306a36Sopenharmony_ci	if (sk_is_readable(sk))
308662306a36Sopenharmony_ci		mask |= EPOLLIN | EPOLLRDNORM;
308762306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_AF_UNIX_OOB)
308862306a36Sopenharmony_ci	if (READ_ONCE(unix_sk(sk)->oob_skb))
308962306a36Sopenharmony_ci		mask |= EPOLLPRI;
309062306a36Sopenharmony_ci#endif
309162306a36Sopenharmony_ci
309262306a36Sopenharmony_ci	/* Connection-based need to check for termination and startup */
309362306a36Sopenharmony_ci	if ((sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) &&
309462306a36Sopenharmony_ci	    sk->sk_state == TCP_CLOSE)
309562306a36Sopenharmony_ci		mask |= EPOLLHUP;
309662306a36Sopenharmony_ci
309762306a36Sopenharmony_ci	/*
309862306a36Sopenharmony_ci	 * we set writable also when the other side has shut down the
309962306a36Sopenharmony_ci	 * connection. This prevents stuck sockets.
310062306a36Sopenharmony_ci	 */
310162306a36Sopenharmony_ci	if (unix_writable(sk))
310262306a36Sopenharmony_ci		mask |= EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND;
310362306a36Sopenharmony_ci
310462306a36Sopenharmony_ci	return mask;
310562306a36Sopenharmony_ci}
310662306a36Sopenharmony_ci
310762306a36Sopenharmony_cistatic __poll_t unix_dgram_poll(struct file *file, struct socket *sock,
310862306a36Sopenharmony_ci				    poll_table *wait)
310962306a36Sopenharmony_ci{
311062306a36Sopenharmony_ci	struct sock *sk = sock->sk, *other;
311162306a36Sopenharmony_ci	unsigned int writable;
311262306a36Sopenharmony_ci	__poll_t mask;
311362306a36Sopenharmony_ci	u8 shutdown;
311462306a36Sopenharmony_ci
311562306a36Sopenharmony_ci	sock_poll_wait(file, sock, wait);
311662306a36Sopenharmony_ci	mask = 0;
311762306a36Sopenharmony_ci	shutdown = READ_ONCE(sk->sk_shutdown);
311862306a36Sopenharmony_ci
311962306a36Sopenharmony_ci	/* exceptional events? */
312062306a36Sopenharmony_ci	if (READ_ONCE(sk->sk_err) ||
312162306a36Sopenharmony_ci	    !skb_queue_empty_lockless(&sk->sk_error_queue))
312262306a36Sopenharmony_ci		mask |= EPOLLERR |
312362306a36Sopenharmony_ci			(sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? EPOLLPRI : 0);
312462306a36Sopenharmony_ci
312562306a36Sopenharmony_ci	if (shutdown & RCV_SHUTDOWN)
312662306a36Sopenharmony_ci		mask |= EPOLLRDHUP | EPOLLIN | EPOLLRDNORM;
312762306a36Sopenharmony_ci	if (shutdown == SHUTDOWN_MASK)
312862306a36Sopenharmony_ci		mask |= EPOLLHUP;
312962306a36Sopenharmony_ci
313062306a36Sopenharmony_ci	/* readable? */
313162306a36Sopenharmony_ci	if (!skb_queue_empty_lockless(&sk->sk_receive_queue))
313262306a36Sopenharmony_ci		mask |= EPOLLIN | EPOLLRDNORM;
313362306a36Sopenharmony_ci	if (sk_is_readable(sk))
313462306a36Sopenharmony_ci		mask |= EPOLLIN | EPOLLRDNORM;
313562306a36Sopenharmony_ci
313662306a36Sopenharmony_ci	/* Connection-based need to check for termination and startup */
313762306a36Sopenharmony_ci	if (sk->sk_type == SOCK_SEQPACKET) {
313862306a36Sopenharmony_ci		if (sk->sk_state == TCP_CLOSE)
313962306a36Sopenharmony_ci			mask |= EPOLLHUP;
314062306a36Sopenharmony_ci		/* connection hasn't started yet? */
314162306a36Sopenharmony_ci		if (sk->sk_state == TCP_SYN_SENT)
314262306a36Sopenharmony_ci			return mask;
314362306a36Sopenharmony_ci	}
314462306a36Sopenharmony_ci
314562306a36Sopenharmony_ci	/* No write status requested, avoid expensive OUT tests. */
314662306a36Sopenharmony_ci	if (!(poll_requested_events(wait) & (EPOLLWRBAND|EPOLLWRNORM|EPOLLOUT)))
314762306a36Sopenharmony_ci		return mask;
314862306a36Sopenharmony_ci
314962306a36Sopenharmony_ci	writable = unix_writable(sk);
315062306a36Sopenharmony_ci	if (writable) {
315162306a36Sopenharmony_ci		unix_state_lock(sk);
315262306a36Sopenharmony_ci
315362306a36Sopenharmony_ci		other = unix_peer(sk);
315462306a36Sopenharmony_ci		if (other && unix_peer(other) != sk &&
315562306a36Sopenharmony_ci		    unix_recvq_full_lockless(other) &&
315662306a36Sopenharmony_ci		    unix_dgram_peer_wake_me(sk, other))
315762306a36Sopenharmony_ci			writable = 0;
315862306a36Sopenharmony_ci
315962306a36Sopenharmony_ci		unix_state_unlock(sk);
316062306a36Sopenharmony_ci	}
316162306a36Sopenharmony_ci
316262306a36Sopenharmony_ci	if (writable)
316362306a36Sopenharmony_ci		mask |= EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND;
316462306a36Sopenharmony_ci	else
316562306a36Sopenharmony_ci		sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk);
316662306a36Sopenharmony_ci
316762306a36Sopenharmony_ci	return mask;
316862306a36Sopenharmony_ci}
316962306a36Sopenharmony_ci
317062306a36Sopenharmony_ci#ifdef CONFIG_PROC_FS
317162306a36Sopenharmony_ci
317262306a36Sopenharmony_ci#define BUCKET_SPACE (BITS_PER_LONG - (UNIX_HASH_BITS + 1) - 1)
317362306a36Sopenharmony_ci
317462306a36Sopenharmony_ci#define get_bucket(x) ((x) >> BUCKET_SPACE)
317562306a36Sopenharmony_ci#define get_offset(x) ((x) & ((1UL << BUCKET_SPACE) - 1))
317662306a36Sopenharmony_ci#define set_bucket_offset(b, o) ((b) << BUCKET_SPACE | (o))
317762306a36Sopenharmony_ci
317862306a36Sopenharmony_cistatic struct sock *unix_from_bucket(struct seq_file *seq, loff_t *pos)
317962306a36Sopenharmony_ci{
318062306a36Sopenharmony_ci	unsigned long offset = get_offset(*pos);
318162306a36Sopenharmony_ci	unsigned long bucket = get_bucket(*pos);
318262306a36Sopenharmony_ci	unsigned long count = 0;
318362306a36Sopenharmony_ci	struct sock *sk;
318462306a36Sopenharmony_ci
318562306a36Sopenharmony_ci	for (sk = sk_head(&seq_file_net(seq)->unx.table.buckets[bucket]);
318662306a36Sopenharmony_ci	     sk; sk = sk_next(sk)) {
318762306a36Sopenharmony_ci		if (++count == offset)
318862306a36Sopenharmony_ci			break;
318962306a36Sopenharmony_ci	}
319062306a36Sopenharmony_ci
319162306a36Sopenharmony_ci	return sk;
319262306a36Sopenharmony_ci}
319362306a36Sopenharmony_ci
319462306a36Sopenharmony_cistatic struct sock *unix_get_first(struct seq_file *seq, loff_t *pos)
319562306a36Sopenharmony_ci{
319662306a36Sopenharmony_ci	unsigned long bucket = get_bucket(*pos);
319762306a36Sopenharmony_ci	struct net *net = seq_file_net(seq);
319862306a36Sopenharmony_ci	struct sock *sk;
319962306a36Sopenharmony_ci
320062306a36Sopenharmony_ci	while (bucket < UNIX_HASH_SIZE) {
320162306a36Sopenharmony_ci		spin_lock(&net->unx.table.locks[bucket]);
320262306a36Sopenharmony_ci
320362306a36Sopenharmony_ci		sk = unix_from_bucket(seq, pos);
320462306a36Sopenharmony_ci		if (sk)
320562306a36Sopenharmony_ci			return sk;
320662306a36Sopenharmony_ci
320762306a36Sopenharmony_ci		spin_unlock(&net->unx.table.locks[bucket]);
320862306a36Sopenharmony_ci
320962306a36Sopenharmony_ci		*pos = set_bucket_offset(++bucket, 1);
321062306a36Sopenharmony_ci	}
321162306a36Sopenharmony_ci
321262306a36Sopenharmony_ci	return NULL;
321362306a36Sopenharmony_ci}
321462306a36Sopenharmony_ci
321562306a36Sopenharmony_cistatic struct sock *unix_get_next(struct seq_file *seq, struct sock *sk,
321662306a36Sopenharmony_ci				  loff_t *pos)
321762306a36Sopenharmony_ci{
321862306a36Sopenharmony_ci	unsigned long bucket = get_bucket(*pos);
321962306a36Sopenharmony_ci
322062306a36Sopenharmony_ci	sk = sk_next(sk);
322162306a36Sopenharmony_ci	if (sk)
322262306a36Sopenharmony_ci		return sk;
322362306a36Sopenharmony_ci
322462306a36Sopenharmony_ci
322562306a36Sopenharmony_ci	spin_unlock(&seq_file_net(seq)->unx.table.locks[bucket]);
322662306a36Sopenharmony_ci
322762306a36Sopenharmony_ci	*pos = set_bucket_offset(++bucket, 1);
322862306a36Sopenharmony_ci
322962306a36Sopenharmony_ci	return unix_get_first(seq, pos);
323062306a36Sopenharmony_ci}
323162306a36Sopenharmony_ci
323262306a36Sopenharmony_cistatic void *unix_seq_start(struct seq_file *seq, loff_t *pos)
323362306a36Sopenharmony_ci{
323462306a36Sopenharmony_ci	if (!*pos)
323562306a36Sopenharmony_ci		return SEQ_START_TOKEN;
323662306a36Sopenharmony_ci
323762306a36Sopenharmony_ci	return unix_get_first(seq, pos);
323862306a36Sopenharmony_ci}
323962306a36Sopenharmony_ci
324062306a36Sopenharmony_cistatic void *unix_seq_next(struct seq_file *seq, void *v, loff_t *pos)
324162306a36Sopenharmony_ci{
324262306a36Sopenharmony_ci	++*pos;
324362306a36Sopenharmony_ci
324462306a36Sopenharmony_ci	if (v == SEQ_START_TOKEN)
324562306a36Sopenharmony_ci		return unix_get_first(seq, pos);
324662306a36Sopenharmony_ci
324762306a36Sopenharmony_ci	return unix_get_next(seq, v, pos);
324862306a36Sopenharmony_ci}
324962306a36Sopenharmony_ci
325062306a36Sopenharmony_cistatic void unix_seq_stop(struct seq_file *seq, void *v)
325162306a36Sopenharmony_ci{
325262306a36Sopenharmony_ci	struct sock *sk = v;
325362306a36Sopenharmony_ci
325462306a36Sopenharmony_ci	if (sk)
325562306a36Sopenharmony_ci		spin_unlock(&seq_file_net(seq)->unx.table.locks[sk->sk_hash]);
325662306a36Sopenharmony_ci}
325762306a36Sopenharmony_ci
325862306a36Sopenharmony_cistatic int unix_seq_show(struct seq_file *seq, void *v)
325962306a36Sopenharmony_ci{
326062306a36Sopenharmony_ci
326162306a36Sopenharmony_ci	if (v == SEQ_START_TOKEN)
326262306a36Sopenharmony_ci		seq_puts(seq, "Num       RefCount Protocol Flags    Type St "
326362306a36Sopenharmony_ci			 "Inode Path\n");
326462306a36Sopenharmony_ci	else {
326562306a36Sopenharmony_ci		struct sock *s = v;
326662306a36Sopenharmony_ci		struct unix_sock *u = unix_sk(s);
326762306a36Sopenharmony_ci		unix_state_lock(s);
326862306a36Sopenharmony_ci
326962306a36Sopenharmony_ci		seq_printf(seq, "%pK: %08X %08X %08X %04X %02X %5lu",
327062306a36Sopenharmony_ci			s,
327162306a36Sopenharmony_ci			refcount_read(&s->sk_refcnt),
327262306a36Sopenharmony_ci			0,
327362306a36Sopenharmony_ci			s->sk_state == TCP_LISTEN ? __SO_ACCEPTCON : 0,
327462306a36Sopenharmony_ci			s->sk_type,
327562306a36Sopenharmony_ci			s->sk_socket ?
327662306a36Sopenharmony_ci			(s->sk_state == TCP_ESTABLISHED ? SS_CONNECTED : SS_UNCONNECTED) :
327762306a36Sopenharmony_ci			(s->sk_state == TCP_ESTABLISHED ? SS_CONNECTING : SS_DISCONNECTING),
327862306a36Sopenharmony_ci			sock_i_ino(s));
327962306a36Sopenharmony_ci
328062306a36Sopenharmony_ci		if (u->addr) {	// under a hash table lock here
328162306a36Sopenharmony_ci			int i, len;
328262306a36Sopenharmony_ci			seq_putc(seq, ' ');
328362306a36Sopenharmony_ci
328462306a36Sopenharmony_ci			i = 0;
328562306a36Sopenharmony_ci			len = u->addr->len -
328662306a36Sopenharmony_ci				offsetof(struct sockaddr_un, sun_path);
328762306a36Sopenharmony_ci			if (u->addr->name->sun_path[0]) {
328862306a36Sopenharmony_ci				len--;
328962306a36Sopenharmony_ci			} else {
329062306a36Sopenharmony_ci				seq_putc(seq, '@');
329162306a36Sopenharmony_ci				i++;
329262306a36Sopenharmony_ci			}
329362306a36Sopenharmony_ci			for ( ; i < len; i++)
329462306a36Sopenharmony_ci				seq_putc(seq, u->addr->name->sun_path[i] ?:
329562306a36Sopenharmony_ci					 '@');
329662306a36Sopenharmony_ci		}
329762306a36Sopenharmony_ci		unix_state_unlock(s);
329862306a36Sopenharmony_ci		seq_putc(seq, '\n');
329962306a36Sopenharmony_ci	}
330062306a36Sopenharmony_ci
330162306a36Sopenharmony_ci	return 0;
330262306a36Sopenharmony_ci}
330362306a36Sopenharmony_ci
330462306a36Sopenharmony_cistatic const struct seq_operations unix_seq_ops = {
330562306a36Sopenharmony_ci	.start  = unix_seq_start,
330662306a36Sopenharmony_ci	.next   = unix_seq_next,
330762306a36Sopenharmony_ci	.stop   = unix_seq_stop,
330862306a36Sopenharmony_ci	.show   = unix_seq_show,
330962306a36Sopenharmony_ci};
331062306a36Sopenharmony_ci
331162306a36Sopenharmony_ci#if IS_BUILTIN(CONFIG_UNIX) && defined(CONFIG_BPF_SYSCALL)
331262306a36Sopenharmony_cistruct bpf_unix_iter_state {
331362306a36Sopenharmony_ci	struct seq_net_private p;
331462306a36Sopenharmony_ci	unsigned int cur_sk;
331562306a36Sopenharmony_ci	unsigned int end_sk;
331662306a36Sopenharmony_ci	unsigned int max_sk;
331762306a36Sopenharmony_ci	struct sock **batch;
331862306a36Sopenharmony_ci	bool st_bucket_done;
331962306a36Sopenharmony_ci};
332062306a36Sopenharmony_ci
332162306a36Sopenharmony_cistruct bpf_iter__unix {
332262306a36Sopenharmony_ci	__bpf_md_ptr(struct bpf_iter_meta *, meta);
332362306a36Sopenharmony_ci	__bpf_md_ptr(struct unix_sock *, unix_sk);
332462306a36Sopenharmony_ci	uid_t uid __aligned(8);
332562306a36Sopenharmony_ci};
332662306a36Sopenharmony_ci
332762306a36Sopenharmony_cistatic int unix_prog_seq_show(struct bpf_prog *prog, struct bpf_iter_meta *meta,
332862306a36Sopenharmony_ci			      struct unix_sock *unix_sk, uid_t uid)
332962306a36Sopenharmony_ci{
333062306a36Sopenharmony_ci	struct bpf_iter__unix ctx;
333162306a36Sopenharmony_ci
333262306a36Sopenharmony_ci	meta->seq_num--;  /* skip SEQ_START_TOKEN */
333362306a36Sopenharmony_ci	ctx.meta = meta;
333462306a36Sopenharmony_ci	ctx.unix_sk = unix_sk;
333562306a36Sopenharmony_ci	ctx.uid = uid;
333662306a36Sopenharmony_ci	return bpf_iter_run_prog(prog, &ctx);
333762306a36Sopenharmony_ci}
333862306a36Sopenharmony_ci
333962306a36Sopenharmony_cistatic int bpf_iter_unix_hold_batch(struct seq_file *seq, struct sock *start_sk)
334062306a36Sopenharmony_ci
334162306a36Sopenharmony_ci{
334262306a36Sopenharmony_ci	struct bpf_unix_iter_state *iter = seq->private;
334362306a36Sopenharmony_ci	unsigned int expected = 1;
334462306a36Sopenharmony_ci	struct sock *sk;
334562306a36Sopenharmony_ci
334662306a36Sopenharmony_ci	sock_hold(start_sk);
334762306a36Sopenharmony_ci	iter->batch[iter->end_sk++] = start_sk;
334862306a36Sopenharmony_ci
334962306a36Sopenharmony_ci	for (sk = sk_next(start_sk); sk; sk = sk_next(sk)) {
335062306a36Sopenharmony_ci		if (iter->end_sk < iter->max_sk) {
335162306a36Sopenharmony_ci			sock_hold(sk);
335262306a36Sopenharmony_ci			iter->batch[iter->end_sk++] = sk;
335362306a36Sopenharmony_ci		}
335462306a36Sopenharmony_ci
335562306a36Sopenharmony_ci		expected++;
335662306a36Sopenharmony_ci	}
335762306a36Sopenharmony_ci
335862306a36Sopenharmony_ci	spin_unlock(&seq_file_net(seq)->unx.table.locks[start_sk->sk_hash]);
335962306a36Sopenharmony_ci
336062306a36Sopenharmony_ci	return expected;
336162306a36Sopenharmony_ci}
336262306a36Sopenharmony_ci
336362306a36Sopenharmony_cistatic void bpf_iter_unix_put_batch(struct bpf_unix_iter_state *iter)
336462306a36Sopenharmony_ci{
336562306a36Sopenharmony_ci	while (iter->cur_sk < iter->end_sk)
336662306a36Sopenharmony_ci		sock_put(iter->batch[iter->cur_sk++]);
336762306a36Sopenharmony_ci}
336862306a36Sopenharmony_ci
336962306a36Sopenharmony_cistatic int bpf_iter_unix_realloc_batch(struct bpf_unix_iter_state *iter,
337062306a36Sopenharmony_ci				       unsigned int new_batch_sz)
337162306a36Sopenharmony_ci{
337262306a36Sopenharmony_ci	struct sock **new_batch;
337362306a36Sopenharmony_ci
337462306a36Sopenharmony_ci	new_batch = kvmalloc(sizeof(*new_batch) * new_batch_sz,
337562306a36Sopenharmony_ci			     GFP_USER | __GFP_NOWARN);
337662306a36Sopenharmony_ci	if (!new_batch)
337762306a36Sopenharmony_ci		return -ENOMEM;
337862306a36Sopenharmony_ci
337962306a36Sopenharmony_ci	bpf_iter_unix_put_batch(iter);
338062306a36Sopenharmony_ci	kvfree(iter->batch);
338162306a36Sopenharmony_ci	iter->batch = new_batch;
338262306a36Sopenharmony_ci	iter->max_sk = new_batch_sz;
338362306a36Sopenharmony_ci
338462306a36Sopenharmony_ci	return 0;
338562306a36Sopenharmony_ci}
338662306a36Sopenharmony_ci
338762306a36Sopenharmony_cistatic struct sock *bpf_iter_unix_batch(struct seq_file *seq,
338862306a36Sopenharmony_ci					loff_t *pos)
338962306a36Sopenharmony_ci{
339062306a36Sopenharmony_ci	struct bpf_unix_iter_state *iter = seq->private;
339162306a36Sopenharmony_ci	unsigned int expected;
339262306a36Sopenharmony_ci	bool resized = false;
339362306a36Sopenharmony_ci	struct sock *sk;
339462306a36Sopenharmony_ci
339562306a36Sopenharmony_ci	if (iter->st_bucket_done)
339662306a36Sopenharmony_ci		*pos = set_bucket_offset(get_bucket(*pos) + 1, 1);
339762306a36Sopenharmony_ci
339862306a36Sopenharmony_ciagain:
339962306a36Sopenharmony_ci	/* Get a new batch */
340062306a36Sopenharmony_ci	iter->cur_sk = 0;
340162306a36Sopenharmony_ci	iter->end_sk = 0;
340262306a36Sopenharmony_ci
340362306a36Sopenharmony_ci	sk = unix_get_first(seq, pos);
340462306a36Sopenharmony_ci	if (!sk)
340562306a36Sopenharmony_ci		return NULL; /* Done */
340662306a36Sopenharmony_ci
340762306a36Sopenharmony_ci	expected = bpf_iter_unix_hold_batch(seq, sk);
340862306a36Sopenharmony_ci
340962306a36Sopenharmony_ci	if (iter->end_sk == expected) {
341062306a36Sopenharmony_ci		iter->st_bucket_done = true;
341162306a36Sopenharmony_ci		return sk;
341262306a36Sopenharmony_ci	}
341362306a36Sopenharmony_ci
341462306a36Sopenharmony_ci	if (!resized && !bpf_iter_unix_realloc_batch(iter, expected * 3 / 2)) {
341562306a36Sopenharmony_ci		resized = true;
341662306a36Sopenharmony_ci		goto again;
341762306a36Sopenharmony_ci	}
341862306a36Sopenharmony_ci
341962306a36Sopenharmony_ci	return sk;
342062306a36Sopenharmony_ci}
342162306a36Sopenharmony_ci
342262306a36Sopenharmony_cistatic void *bpf_iter_unix_seq_start(struct seq_file *seq, loff_t *pos)
342362306a36Sopenharmony_ci{
342462306a36Sopenharmony_ci	if (!*pos)
342562306a36Sopenharmony_ci		return SEQ_START_TOKEN;
342662306a36Sopenharmony_ci
342762306a36Sopenharmony_ci	/* bpf iter does not support lseek, so it always
342862306a36Sopenharmony_ci	 * continue from where it was stop()-ped.
342962306a36Sopenharmony_ci	 */
343062306a36Sopenharmony_ci	return bpf_iter_unix_batch(seq, pos);
343162306a36Sopenharmony_ci}
343262306a36Sopenharmony_ci
343362306a36Sopenharmony_cistatic void *bpf_iter_unix_seq_next(struct seq_file *seq, void *v, loff_t *pos)
343462306a36Sopenharmony_ci{
343562306a36Sopenharmony_ci	struct bpf_unix_iter_state *iter = seq->private;
343662306a36Sopenharmony_ci	struct sock *sk;
343762306a36Sopenharmony_ci
343862306a36Sopenharmony_ci	/* Whenever seq_next() is called, the iter->cur_sk is
343962306a36Sopenharmony_ci	 * done with seq_show(), so advance to the next sk in
344062306a36Sopenharmony_ci	 * the batch.
344162306a36Sopenharmony_ci	 */
344262306a36Sopenharmony_ci	if (iter->cur_sk < iter->end_sk)
344362306a36Sopenharmony_ci		sock_put(iter->batch[iter->cur_sk++]);
344462306a36Sopenharmony_ci
344562306a36Sopenharmony_ci	++*pos;
344662306a36Sopenharmony_ci
344762306a36Sopenharmony_ci	if (iter->cur_sk < iter->end_sk)
344862306a36Sopenharmony_ci		sk = iter->batch[iter->cur_sk];
344962306a36Sopenharmony_ci	else
345062306a36Sopenharmony_ci		sk = bpf_iter_unix_batch(seq, pos);
345162306a36Sopenharmony_ci
345262306a36Sopenharmony_ci	return sk;
345362306a36Sopenharmony_ci}
345462306a36Sopenharmony_ci
345562306a36Sopenharmony_cistatic int bpf_iter_unix_seq_show(struct seq_file *seq, void *v)
345662306a36Sopenharmony_ci{
345762306a36Sopenharmony_ci	struct bpf_iter_meta meta;
345862306a36Sopenharmony_ci	struct bpf_prog *prog;
345962306a36Sopenharmony_ci	struct sock *sk = v;
346062306a36Sopenharmony_ci	uid_t uid;
346162306a36Sopenharmony_ci	bool slow;
346262306a36Sopenharmony_ci	int ret;
346362306a36Sopenharmony_ci
346462306a36Sopenharmony_ci	if (v == SEQ_START_TOKEN)
346562306a36Sopenharmony_ci		return 0;
346662306a36Sopenharmony_ci
346762306a36Sopenharmony_ci	slow = lock_sock_fast(sk);
346862306a36Sopenharmony_ci
346962306a36Sopenharmony_ci	if (unlikely(sk_unhashed(sk))) {
347062306a36Sopenharmony_ci		ret = SEQ_SKIP;
347162306a36Sopenharmony_ci		goto unlock;
347262306a36Sopenharmony_ci	}
347362306a36Sopenharmony_ci
347462306a36Sopenharmony_ci	uid = from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk));
347562306a36Sopenharmony_ci	meta.seq = seq;
347662306a36Sopenharmony_ci	prog = bpf_iter_get_info(&meta, false);
347762306a36Sopenharmony_ci	ret = unix_prog_seq_show(prog, &meta, v, uid);
347862306a36Sopenharmony_ciunlock:
347962306a36Sopenharmony_ci	unlock_sock_fast(sk, slow);
348062306a36Sopenharmony_ci	return ret;
348162306a36Sopenharmony_ci}
348262306a36Sopenharmony_ci
348362306a36Sopenharmony_cistatic void bpf_iter_unix_seq_stop(struct seq_file *seq, void *v)
348462306a36Sopenharmony_ci{
348562306a36Sopenharmony_ci	struct bpf_unix_iter_state *iter = seq->private;
348662306a36Sopenharmony_ci	struct bpf_iter_meta meta;
348762306a36Sopenharmony_ci	struct bpf_prog *prog;
348862306a36Sopenharmony_ci
348962306a36Sopenharmony_ci	if (!v) {
349062306a36Sopenharmony_ci		meta.seq = seq;
349162306a36Sopenharmony_ci		prog = bpf_iter_get_info(&meta, true);
349262306a36Sopenharmony_ci		if (prog)
349362306a36Sopenharmony_ci			(void)unix_prog_seq_show(prog, &meta, v, 0);
349462306a36Sopenharmony_ci	}
349562306a36Sopenharmony_ci
349662306a36Sopenharmony_ci	if (iter->cur_sk < iter->end_sk)
349762306a36Sopenharmony_ci		bpf_iter_unix_put_batch(iter);
349862306a36Sopenharmony_ci}
349962306a36Sopenharmony_ci
350062306a36Sopenharmony_cistatic const struct seq_operations bpf_iter_unix_seq_ops = {
350162306a36Sopenharmony_ci	.start	= bpf_iter_unix_seq_start,
350262306a36Sopenharmony_ci	.next	= bpf_iter_unix_seq_next,
350362306a36Sopenharmony_ci	.stop	= bpf_iter_unix_seq_stop,
350462306a36Sopenharmony_ci	.show	= bpf_iter_unix_seq_show,
350562306a36Sopenharmony_ci};
350662306a36Sopenharmony_ci#endif
350762306a36Sopenharmony_ci#endif
350862306a36Sopenharmony_ci
350962306a36Sopenharmony_cistatic const struct net_proto_family unix_family_ops = {
351062306a36Sopenharmony_ci	.family = PF_UNIX,
351162306a36Sopenharmony_ci	.create = unix_create,
351262306a36Sopenharmony_ci	.owner	= THIS_MODULE,
351362306a36Sopenharmony_ci};
351462306a36Sopenharmony_ci
351562306a36Sopenharmony_ci
351662306a36Sopenharmony_cistatic int __net_init unix_net_init(struct net *net)
351762306a36Sopenharmony_ci{
351862306a36Sopenharmony_ci	int i;
351962306a36Sopenharmony_ci
352062306a36Sopenharmony_ci	net->unx.sysctl_max_dgram_qlen = 10;
352162306a36Sopenharmony_ci	if (unix_sysctl_register(net))
352262306a36Sopenharmony_ci		goto out;
352362306a36Sopenharmony_ci
352462306a36Sopenharmony_ci#ifdef CONFIG_PROC_FS
352562306a36Sopenharmony_ci	if (!proc_create_net("unix", 0, net->proc_net, &unix_seq_ops,
352662306a36Sopenharmony_ci			     sizeof(struct seq_net_private)))
352762306a36Sopenharmony_ci		goto err_sysctl;
352862306a36Sopenharmony_ci#endif
352962306a36Sopenharmony_ci
353062306a36Sopenharmony_ci	net->unx.table.locks = kvmalloc_array(UNIX_HASH_SIZE,
353162306a36Sopenharmony_ci					      sizeof(spinlock_t), GFP_KERNEL);
353262306a36Sopenharmony_ci	if (!net->unx.table.locks)
353362306a36Sopenharmony_ci		goto err_proc;
353462306a36Sopenharmony_ci
353562306a36Sopenharmony_ci	net->unx.table.buckets = kvmalloc_array(UNIX_HASH_SIZE,
353662306a36Sopenharmony_ci						sizeof(struct hlist_head),
353762306a36Sopenharmony_ci						GFP_KERNEL);
353862306a36Sopenharmony_ci	if (!net->unx.table.buckets)
353962306a36Sopenharmony_ci		goto free_locks;
354062306a36Sopenharmony_ci
354162306a36Sopenharmony_ci	for (i = 0; i < UNIX_HASH_SIZE; i++) {
354262306a36Sopenharmony_ci		spin_lock_init(&net->unx.table.locks[i]);
354362306a36Sopenharmony_ci		INIT_HLIST_HEAD(&net->unx.table.buckets[i]);
354462306a36Sopenharmony_ci	}
354562306a36Sopenharmony_ci
354662306a36Sopenharmony_ci	return 0;
354762306a36Sopenharmony_ci
354862306a36Sopenharmony_cifree_locks:
354962306a36Sopenharmony_ci	kvfree(net->unx.table.locks);
355062306a36Sopenharmony_cierr_proc:
355162306a36Sopenharmony_ci#ifdef CONFIG_PROC_FS
355262306a36Sopenharmony_ci	remove_proc_entry("unix", net->proc_net);
355362306a36Sopenharmony_cierr_sysctl:
355462306a36Sopenharmony_ci#endif
355562306a36Sopenharmony_ci	unix_sysctl_unregister(net);
355662306a36Sopenharmony_ciout:
355762306a36Sopenharmony_ci	return -ENOMEM;
355862306a36Sopenharmony_ci}
355962306a36Sopenharmony_ci
356062306a36Sopenharmony_cistatic void __net_exit unix_net_exit(struct net *net)
356162306a36Sopenharmony_ci{
356262306a36Sopenharmony_ci	kvfree(net->unx.table.buckets);
356362306a36Sopenharmony_ci	kvfree(net->unx.table.locks);
356462306a36Sopenharmony_ci	unix_sysctl_unregister(net);
356562306a36Sopenharmony_ci	remove_proc_entry("unix", net->proc_net);
356662306a36Sopenharmony_ci}
356762306a36Sopenharmony_ci
356862306a36Sopenharmony_cistatic struct pernet_operations unix_net_ops = {
356962306a36Sopenharmony_ci	.init = unix_net_init,
357062306a36Sopenharmony_ci	.exit = unix_net_exit,
357162306a36Sopenharmony_ci};
357262306a36Sopenharmony_ci
357362306a36Sopenharmony_ci#if IS_BUILTIN(CONFIG_UNIX) && defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_PROC_FS)
357462306a36Sopenharmony_ciDEFINE_BPF_ITER_FUNC(unix, struct bpf_iter_meta *meta,
357562306a36Sopenharmony_ci		     struct unix_sock *unix_sk, uid_t uid)
357662306a36Sopenharmony_ci
357762306a36Sopenharmony_ci#define INIT_BATCH_SZ 16
357862306a36Sopenharmony_ci
357962306a36Sopenharmony_cistatic int bpf_iter_init_unix(void *priv_data, struct bpf_iter_aux_info *aux)
358062306a36Sopenharmony_ci{
358162306a36Sopenharmony_ci	struct bpf_unix_iter_state *iter = priv_data;
358262306a36Sopenharmony_ci	int err;
358362306a36Sopenharmony_ci
358462306a36Sopenharmony_ci	err = bpf_iter_init_seq_net(priv_data, aux);
358562306a36Sopenharmony_ci	if (err)
358662306a36Sopenharmony_ci		return err;
358762306a36Sopenharmony_ci
358862306a36Sopenharmony_ci	err = bpf_iter_unix_realloc_batch(iter, INIT_BATCH_SZ);
358962306a36Sopenharmony_ci	if (err) {
359062306a36Sopenharmony_ci		bpf_iter_fini_seq_net(priv_data);
359162306a36Sopenharmony_ci		return err;
359262306a36Sopenharmony_ci	}
359362306a36Sopenharmony_ci
359462306a36Sopenharmony_ci	return 0;
359562306a36Sopenharmony_ci}
359662306a36Sopenharmony_ci
359762306a36Sopenharmony_cistatic void bpf_iter_fini_unix(void *priv_data)
359862306a36Sopenharmony_ci{
359962306a36Sopenharmony_ci	struct bpf_unix_iter_state *iter = priv_data;
360062306a36Sopenharmony_ci
360162306a36Sopenharmony_ci	bpf_iter_fini_seq_net(priv_data);
360262306a36Sopenharmony_ci	kvfree(iter->batch);
360362306a36Sopenharmony_ci}
360462306a36Sopenharmony_ci
360562306a36Sopenharmony_cistatic const struct bpf_iter_seq_info unix_seq_info = {
360662306a36Sopenharmony_ci	.seq_ops		= &bpf_iter_unix_seq_ops,
360762306a36Sopenharmony_ci	.init_seq_private	= bpf_iter_init_unix,
360862306a36Sopenharmony_ci	.fini_seq_private	= bpf_iter_fini_unix,
360962306a36Sopenharmony_ci	.seq_priv_size		= sizeof(struct bpf_unix_iter_state),
361062306a36Sopenharmony_ci};
361162306a36Sopenharmony_ci
361262306a36Sopenharmony_cistatic const struct bpf_func_proto *
361362306a36Sopenharmony_cibpf_iter_unix_get_func_proto(enum bpf_func_id func_id,
361462306a36Sopenharmony_ci			     const struct bpf_prog *prog)
361562306a36Sopenharmony_ci{
361662306a36Sopenharmony_ci	switch (func_id) {
361762306a36Sopenharmony_ci	case BPF_FUNC_setsockopt:
361862306a36Sopenharmony_ci		return &bpf_sk_setsockopt_proto;
361962306a36Sopenharmony_ci	case BPF_FUNC_getsockopt:
362062306a36Sopenharmony_ci		return &bpf_sk_getsockopt_proto;
362162306a36Sopenharmony_ci	default:
362262306a36Sopenharmony_ci		return NULL;
362362306a36Sopenharmony_ci	}
362462306a36Sopenharmony_ci}
362562306a36Sopenharmony_ci
362662306a36Sopenharmony_cistatic struct bpf_iter_reg unix_reg_info = {
362762306a36Sopenharmony_ci	.target			= "unix",
362862306a36Sopenharmony_ci	.ctx_arg_info_size	= 1,
362962306a36Sopenharmony_ci	.ctx_arg_info		= {
363062306a36Sopenharmony_ci		{ offsetof(struct bpf_iter__unix, unix_sk),
363162306a36Sopenharmony_ci		  PTR_TO_BTF_ID_OR_NULL },
363262306a36Sopenharmony_ci	},
363362306a36Sopenharmony_ci	.get_func_proto         = bpf_iter_unix_get_func_proto,
363462306a36Sopenharmony_ci	.seq_info		= &unix_seq_info,
363562306a36Sopenharmony_ci};
363662306a36Sopenharmony_ci
363762306a36Sopenharmony_cistatic void __init bpf_iter_register(void)
363862306a36Sopenharmony_ci{
363962306a36Sopenharmony_ci	unix_reg_info.ctx_arg_info[0].btf_id = btf_sock_ids[BTF_SOCK_TYPE_UNIX];
364062306a36Sopenharmony_ci	if (bpf_iter_reg_target(&unix_reg_info))
364162306a36Sopenharmony_ci		pr_warn("Warning: could not register bpf iterator unix\n");
364262306a36Sopenharmony_ci}
364362306a36Sopenharmony_ci#endif
364462306a36Sopenharmony_ci
364562306a36Sopenharmony_cistatic int __init af_unix_init(void)
364662306a36Sopenharmony_ci{
364762306a36Sopenharmony_ci	int i, rc = -1;
364862306a36Sopenharmony_ci
364962306a36Sopenharmony_ci	BUILD_BUG_ON(sizeof(struct unix_skb_parms) > sizeof_field(struct sk_buff, cb));
365062306a36Sopenharmony_ci
365162306a36Sopenharmony_ci	for (i = 0; i < UNIX_HASH_SIZE / 2; i++) {
365262306a36Sopenharmony_ci		spin_lock_init(&bsd_socket_locks[i]);
365362306a36Sopenharmony_ci		INIT_HLIST_HEAD(&bsd_socket_buckets[i]);
365462306a36Sopenharmony_ci	}
365562306a36Sopenharmony_ci
365662306a36Sopenharmony_ci	rc = proto_register(&unix_dgram_proto, 1);
365762306a36Sopenharmony_ci	if (rc != 0) {
365862306a36Sopenharmony_ci		pr_crit("%s: Cannot create unix_sock SLAB cache!\n", __func__);
365962306a36Sopenharmony_ci		goto out;
366062306a36Sopenharmony_ci	}
366162306a36Sopenharmony_ci
366262306a36Sopenharmony_ci	rc = proto_register(&unix_stream_proto, 1);
366362306a36Sopenharmony_ci	if (rc != 0) {
366462306a36Sopenharmony_ci		pr_crit("%s: Cannot create unix_sock SLAB cache!\n", __func__);
366562306a36Sopenharmony_ci		proto_unregister(&unix_dgram_proto);
366662306a36Sopenharmony_ci		goto out;
366762306a36Sopenharmony_ci	}
366862306a36Sopenharmony_ci
366962306a36Sopenharmony_ci	sock_register(&unix_family_ops);
367062306a36Sopenharmony_ci	register_pernet_subsys(&unix_net_ops);
367162306a36Sopenharmony_ci	unix_bpf_build_proto();
367262306a36Sopenharmony_ci
367362306a36Sopenharmony_ci#if IS_BUILTIN(CONFIG_UNIX) && defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_PROC_FS)
367462306a36Sopenharmony_ci	bpf_iter_register();
367562306a36Sopenharmony_ci#endif
367662306a36Sopenharmony_ci
367762306a36Sopenharmony_ciout:
367862306a36Sopenharmony_ci	return rc;
367962306a36Sopenharmony_ci}
368062306a36Sopenharmony_ci
368162306a36Sopenharmony_cistatic void __exit af_unix_exit(void)
368262306a36Sopenharmony_ci{
368362306a36Sopenharmony_ci	sock_unregister(PF_UNIX);
368462306a36Sopenharmony_ci	proto_unregister(&unix_dgram_proto);
368562306a36Sopenharmony_ci	proto_unregister(&unix_stream_proto);
368662306a36Sopenharmony_ci	unregister_pernet_subsys(&unix_net_ops);
368762306a36Sopenharmony_ci}
368862306a36Sopenharmony_ci
368962306a36Sopenharmony_ci/* Earlier than device_initcall() so that other drivers invoking
369062306a36Sopenharmony_ci   request_module() don't end up in a loop when modprobe tries
369162306a36Sopenharmony_ci   to use a UNIX socket. But later than subsys_initcall() because
369262306a36Sopenharmony_ci   we depend on stuff initialised there */
369362306a36Sopenharmony_cifs_initcall(af_unix_init);
369462306a36Sopenharmony_cimodule_exit(af_unix_exit);
369562306a36Sopenharmony_ci
369662306a36Sopenharmony_ciMODULE_LICENSE("GPL");
369762306a36Sopenharmony_ciMODULE_ALIAS_NETPROTO(PF_UNIX);
3698