linux/net/unix/af_unix.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * NET4:	Implementation of BSD Unix domain sockets.
 *
 * Authors:	Alan Cox, <[email protected]>
 *
 * Fixes:
 *		Linus Torvalds	:	Assorted bug cures.
 *		Niibe Yutaka	:	async I/O support.
 *		Carsten Paeth	:	PF_UNIX check, address fixes.
 *		Alan Cox	:	Limit size of allocated blocks.
 *		Alan Cox	:	Fixed the stupid socketpair bug.
 *		Alan Cox	:	BSD compatibility fine tuning.
 *		Alan Cox	:	Fixed a bug in connect when interrupted.
 *		Alan Cox	:	Sorted out a proper draft version of
 *					file descriptor passing hacked up from
 *					Mike Shaver's work.
 *		Marty Leisner	:	Fixes to fd passing
 *		Nick Nevin	:	recvmsg bugfix.
 *		Alan Cox	:	Started proper garbage collector
 *		Heiko EiBfeldt	:	Missing verify_area check
 *		Alan Cox	:	Started POSIXisms
 *		Andreas Schwab	:	Replace inode by dentry for proper
 *					reference counting
 *		Kirk Petersen	:	Made this a module
 *	    Christoph Rohland	:	Elegant non-blocking accept/connect algorithm.
 *					Lots of bug fixes.
 *	     Alexey Kuznetosv	:	Repaired (I hope) bugs introduces
 *					by above two patches.
 *	     Andrea Arcangeli	:	If possible we block in connect(2)
 *					if the max backlog of the listen socket
 *					is been reached. This won't break
 *					old apps and it will avoid huge amount
 *					of socks hashed (this for unix_gc()
 *					performances reasons).
 *					Security fix that limits the max
 *					number of socks to 2*max_files and
 *					the number of skb queueable in the
 *					dgram receiver.
 *		Artur Skawina   :	Hash function optimizations
 *	     Alexey Kuznetsov   :	Full scale SMP. Lot of bugs are introduced 8)
 *	      Malcolm Beattie   :	Set peercred for socketpair
 *	     Michal Ostrowski   :       Module initialization cleanup.
 *	     Arnaldo C. Melo	:	Remove MOD_{INC,DEC}_USE_COUNT,
 *	     				the core infrastructure is doing that
 *	     				for all net proto families now (2.5.69+)
 *
 * Known differences from reference BSD that was tested:
 *
 *	[TO FIX]
 *	ECONNREFUSED is not returned from one end of a connected() socket to the
 *		other the moment one end closes.
 *	fstat() doesn't return st_dev=0, and give the blksize as high water mark
 *		and a fake inode identifier (nor the BSD first socket fstat twice bug).
 *	[NOT TO FIX]
 *	accept() returns a path name even if the connecting socket has closed
 *		in the meantime (BSD loses the path and gives up).
 *	accept() returns 0 length path for an unbound connector. BSD returns 16
 *		and a null first byte in the path (but not for gethost/peername - BSD bug ??)
 *	socketpair(...SOCK_RAW..) doesn't panic the kernel.
 *	BSD af_unix apparently has connect forgetting to block properly.
 *		(need to check this with the POSIX spec in detail)
 *
 * Differences from 2.0.0-11-... (ANK)
 *	Bug fixes and improvements.
 *		- client shutdown killed server socket.
 *		- removed all useless cli/sti pairs.
 *
 *	Semantic changes/extensions.
 *		- generic control message passing.
 *		- SCM_CREDENTIALS control message.
 *		- "Abstract" (not FS based) socket bindings.
 *		  Abstract names are sequences of bytes (not zero terminated)
 *		  started by 0, so that this name space does not intersect
 *		  with BSD names.
 */

#define pr_fmt(fmt)

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/sched/signal.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/dcache.h>
#include <linux/namei.h>
#include <linux/socket.h>
#include <linux/un.h>
#include <linux/fcntl.h>
#include <linux/filter.h>
#include <linux/termios.h>
#include <linux/sockios.h>
#include <linux/net.h>
#include <linux/in.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <net/net_namespace.h>
#include <net/sock.h>
#include <net/tcp_states.h>
#include <net/af_unix.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <net/scm.h>
#include <linux/init.h>
#include <linux/poll.h>
#include <linux/rtnetlink.h>
#include <linux/mount.h>
#include <net/checksum.h>
#include <linux/security.h>
#include <linux/splice.h>
#include <linux/freezer.h>
#include <linux/file.h>
#include <linux/btf_ids.h>
#include <linux/bpf-cgroup.h>

static atomic_long_t unix_nr_socks;
static struct hlist_head bsd_socket_buckets[UNIX_HASH_SIZE / 2];
static spinlock_t bsd_socket_locks[UNIX_HASH_SIZE / 2];

/* SMP locking strategy:
 *    hash table is protected with spinlock.
 *    each socket state is protected by separate spinlock.
 */
#ifdef CONFIG_PROVE_LOCKING
#define cmp_ptr(l, r)

static int unix_table_lock_cmp_fn(const struct lockdep_map *a,
				  const struct lockdep_map *b)
{}

static int unix_state_lock_cmp_fn(const struct lockdep_map *_a,
				  const struct lockdep_map *_b)
{}

static int unix_recvq_lock_cmp_fn(const struct lockdep_map *_a,
				  const struct lockdep_map *_b)
{}
#endif

static unsigned int unix_unbound_hash(struct sock *sk)
{}

static unsigned int unix_bsd_hash(struct inode *i)
{}

static unsigned int unix_abstract_hash(struct sockaddr_un *sunaddr,
				       int addr_len, int type)
{}

static void unix_table_double_lock(struct net *net,
				   unsigned int hash1, unsigned int hash2)
{}

static void unix_table_double_unlock(struct net *net,
				     unsigned int hash1, unsigned int hash2)
{}

#ifdef CONFIG_SECURITY_NETWORK
static void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
{}

static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
{}

static inline bool unix_secdata_eq(struct scm_cookie *scm, struct sk_buff *skb)
{}
#else
static inline void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
{ }

static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
{ }

static inline bool unix_secdata_eq(struct scm_cookie *scm, struct sk_buff *skb)
{
	return true;
}
#endif /* CONFIG_SECURITY_NETWORK */

static inline int unix_our_peer(struct sock *sk, struct sock *osk)
{}

static inline int unix_may_send(struct sock *sk, struct sock *osk)
{}

static inline int unix_recvq_full_lockless(const struct sock *sk)
{}

struct sock *unix_peer_get(struct sock *s)
{}
EXPORT_SYMBOL_GPL();

static struct unix_address *unix_create_addr(struct sockaddr_un *sunaddr,
					     int addr_len)
{}

static inline void unix_release_addr(struct unix_address *addr)
{}

/*
 *	Check unix socket name:
 *		- should be not zero length.
 *	        - if started by not zero, should be NULL terminated (FS object)
 *		- if started by zero, it is abstract name.
 */

static int unix_validate_addr(struct sockaddr_un *sunaddr, int addr_len)
{}

static int unix_mkname_bsd(struct sockaddr_un *sunaddr, int addr_len)
{}

static void __unix_remove_socket(struct sock *sk)
{}

static void __unix_insert_socket(struct net *net, struct sock *sk)
{}

static void __unix_set_addr_hash(struct net *net, struct sock *sk,
				 struct unix_address *addr, unsigned int hash)
{}

static void unix_remove_socket(struct net *net, struct sock *sk)
{}

static void unix_insert_unbound_socket(struct net *net, struct sock *sk)
{}

static void unix_insert_bsd_socket(struct sock *sk)
{}

static void unix_remove_bsd_socket(struct sock *sk)
{}

static struct sock *__unix_find_socket_byname(struct net *net,
					      struct sockaddr_un *sunname,
					      int len, unsigned int hash)
{}

static inline struct sock *unix_find_socket_byname(struct net *net,
						   struct sockaddr_un *sunname,
						   int len, unsigned int hash)
{}

static struct sock *unix_find_socket_byinode(struct inode *i)
{}

/* Support code for asymmetrically connected dgram sockets
 *
 * If a datagram socket is connected to a socket not itself connected
 * to the first socket (eg, /dev/log), clients may only enqueue more
 * messages if the present receive queue of the server socket is not
 * "too large". This means there's a second writeability condition
 * poll and sendmsg need to test. The dgram recv code will do a wake
 * up on the peer_wait wait queue of a socket upon reception of a
 * datagram which needs to be propagated to sleeping would-be writers
 * since these might not have sent anything so far. This can't be
 * accomplished via poll_wait because the lifetime of the server
 * socket might be less than that of its clients if these break their
 * association with it or if the server socket is closed while clients
 * are still connected to it and there's no way to inform "a polling
 * implementation" that it should let go of a certain wait queue
 *
 * In order to propagate a wake up, a wait_queue_entry_t of the client
 * socket is enqueued on the peer_wait queue of the server socket
 * whose wake function does a wake_up on the ordinary client socket
 * wait queue. This connection is established whenever a write (or
 * poll for write) hit the flow control condition and broken when the
 * association to the server socket is dissolved or after a wake up
 * was relayed.
 */

static int unix_dgram_peer_wake_relay(wait_queue_entry_t *q, unsigned mode, int flags,
				      void *key)
{}

static int unix_dgram_peer_wake_connect(struct sock *sk, struct sock *other)
{}

static void unix_dgram_peer_wake_disconnect(struct sock *sk,
					    struct sock *other)
{}

static void unix_dgram_peer_wake_disconnect_wakeup(struct sock *sk,
						   struct sock *other)
{}

/* preconditions:
 *	- unix_peer(sk) == other
 *	- association is stable
 */
static int unix_dgram_peer_wake_me(struct sock *sk, struct sock *other)
{}

static int unix_writable(const struct sock *sk, unsigned char state)
{}

static void unix_write_space(struct sock *sk)
{}

/* When dgram socket disconnects (or changes its peer), we clear its receive
 * queue of packets arrived from previous peer. First, it allows to do
 * flow control based only on wmem_alloc; second, sk connected to peer
 * may receive messages only from that peer. */
static void unix_dgram_disconnected(struct sock *sk, struct sock *other)
{}

static void unix_sock_destructor(struct sock *sk)
{}

static void unix_release_sock(struct sock *sk, int embrion)
{}

static void init_peercred(struct sock *sk)
{}

static void update_peercred(struct sock *sk)
{}

static void copy_peercred(struct sock *sk, struct sock *peersk)
{}

static int unix_listen(struct socket *sock, int backlog)
{}

static int unix_release(struct socket *);
static int unix_bind(struct socket *, struct sockaddr *, int);
static int unix_stream_connect(struct socket *, struct sockaddr *,
			       int addr_len, int flags);
static int unix_socketpair(struct socket *, struct socket *);
static int unix_accept(struct socket *, struct socket *, struct proto_accept_arg *arg);
static int unix_getname(struct socket *, struct sockaddr *, int);
static __poll_t unix_poll(struct file *, struct socket *, poll_table *);
static __poll_t unix_dgram_poll(struct file *, struct socket *,
				    poll_table *);
static int unix_ioctl(struct socket *, unsigned int, unsigned long);
#ifdef CONFIG_COMPAT
static int unix_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
#endif
static int unix_shutdown(struct socket *, int);
static int unix_stream_sendmsg(struct socket *, struct msghdr *, size_t);
static int unix_stream_recvmsg(struct socket *, struct msghdr *, size_t, int);
static ssize_t unix_stream_splice_read(struct socket *,  loff_t *ppos,
				       struct pipe_inode_info *, size_t size,
				       unsigned int flags);
static int unix_dgram_sendmsg(struct socket *, struct msghdr *, size_t);
static int unix_dgram_recvmsg(struct socket *, struct msghdr *, size_t, int);
static int unix_read_skb(struct sock *sk, skb_read_actor_t recv_actor);
static int unix_stream_read_skb(struct sock *sk, skb_read_actor_t recv_actor);
static int unix_dgram_connect(struct socket *, struct sockaddr *,
			      int, int);
static int unix_seqpacket_sendmsg(struct socket *, struct msghdr *, size_t);
static int unix_seqpacket_recvmsg(struct socket *, struct msghdr *, size_t,
				  int);

#ifdef CONFIG_PROC_FS
static int unix_count_nr_fds(struct sock *sk)
{}

static void unix_show_fdinfo(struct seq_file *m, struct socket *sock)
{}
#else
#define unix_show_fdinfo
#endif

static const struct proto_ops unix_stream_ops =;

static const struct proto_ops unix_dgram_ops =;

static const struct proto_ops unix_seqpacket_ops =;

static void unix_close(struct sock *sk, long timeout)
{}

static void unix_unhash(struct sock *sk)
{}

static bool unix_bpf_bypass_getsockopt(int level, int optname)
{}

struct proto unix_dgram_proto =;

struct proto unix_stream_proto =;

static struct sock *unix_create1(struct net *net, struct socket *sock, int kern, int type)
{}

static int unix_create(struct net *net, struct socket *sock, int protocol,
		       int kern)
{}

static int unix_release(struct socket *sock)
{}

static struct sock *unix_find_bsd(struct sockaddr_un *sunaddr, int addr_len,
				  int type)
{}

static struct sock *unix_find_abstract(struct net *net,
				       struct sockaddr_un *sunaddr,
				       int addr_len, int type)
{}

static struct sock *unix_find_other(struct net *net,
				    struct sockaddr_un *sunaddr,
				    int addr_len, int type)
{}

static int unix_autobind(struct sock *sk)
{}

static int unix_bind_bsd(struct sock *sk, struct sockaddr_un *sunaddr,
			 int addr_len)
{}

static int unix_bind_abstract(struct sock *sk, struct sockaddr_un *sunaddr,
			      int addr_len)
{}

static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
{}

static void unix_state_double_lock(struct sock *sk1, struct sock *sk2)
{}

static void unix_state_double_unlock(struct sock *sk1, struct sock *sk2)
{}

static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
			      int alen, int flags)
{}

static long unix_wait_for_peer(struct sock *other, long timeo)
	__releases(&unix_sk(other)->lock)
{}

static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
			       int addr_len, int flags)
{}

static int unix_socketpair(struct socket *socka, struct socket *sockb)
{}

static void unix_sock_inherit_flags(const struct socket *old,
				    struct socket *new)
{}

static int unix_accept(struct socket *sock, struct socket *newsock,
		       struct proto_accept_arg *arg)
{}


static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int peer)
{}

/* The "user->unix_inflight" variable is protected by the garbage
 * collection lock, and we just read it locklessly here. If you go
 * over the limit, there might be a tiny race in actually noticing
 * it across threads. Tough.
 */
static inline bool too_many_unix_fds(struct task_struct *p)
{}

static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
{}

static void unix_detach_fds(struct scm_cookie *scm, struct sk_buff *skb)
{}

static void unix_peek_fds(struct scm_cookie *scm, struct sk_buff *skb)
{}

static void unix_destruct_scm(struct sk_buff *skb)
{}

static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool send_fds)
{}

static bool unix_passcred_enabled(const struct socket *sock,
				  const struct sock *other)
{}

/*
 * Some apps rely on write() giving SCM_CREDENTIALS
 * We include credentials if source or destination socket
 * asserted SOCK_PASSCRED.
 */
static void maybe_add_creds(struct sk_buff *skb, const struct socket *sock,
			    const struct sock *other)
{}

static bool unix_skb_scm_eq(struct sk_buff *skb,
			    struct scm_cookie *scm)
{}

static void scm_stat_add(struct sock *sk, struct sk_buff *skb)
{}

static void scm_stat_del(struct sock *sk, struct sk_buff *skb)
{}

/*
 *	Send AF_UNIX data.
 */

static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
			      size_t len)
{}

/* We use paged skbs for stream sockets, and limit occupancy to 32768
 * bytes, and a minimum of a full page.
 */
#define UNIX_SKB_FRAGS_SZ

#if IS_ENABLED(CONFIG_AF_UNIX_OOB)
static int queue_oob(struct socket *sock, struct msghdr *msg, struct sock *other,
		     struct scm_cookie *scm, bool fds_sent)
{}
#endif

static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
			       size_t len)
{}

static int unix_seqpacket_sendmsg(struct socket *sock, struct msghdr *msg,
				  size_t len)
{}

static int unix_seqpacket_recvmsg(struct socket *sock, struct msghdr *msg,
				  size_t size, int flags)
{}

static void unix_copy_addr(struct msghdr *msg, struct sock *sk)
{}

int __unix_dgram_recvmsg(struct sock *sk, struct msghdr *msg, size_t size,
			 int flags)
{}

static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
			      int flags)
{}

static int unix_read_skb(struct sock *sk, skb_read_actor_t recv_actor)
{}

/*
 *	Sleep until more data has arrived. But check for races..
 */
static long unix_stream_data_wait(struct sock *sk, long timeo,
				  struct sk_buff *last, unsigned int last_len,
				  bool freezable)
{}

static unsigned int unix_skb_len(const struct sk_buff *skb)
{}

struct unix_stream_read_state {};

#if IS_ENABLED(CONFIG_AF_UNIX_OOB)
static int unix_stream_recv_urg(struct unix_stream_read_state *state)
{}

static struct sk_buff *manage_oob(struct sk_buff *skb, struct sock *sk,
				  int flags, int copied)
{}
#endif

static int unix_stream_read_skb(struct sock *sk, skb_read_actor_t recv_actor)
{}

static int unix_stream_read_generic(struct unix_stream_read_state *state,
				    bool freezable)
{}

static int unix_stream_read_actor(struct sk_buff *skb,
				  int skip, int chunk,
				  struct unix_stream_read_state *state)
{}

int __unix_stream_recvmsg(struct sock *sk, struct msghdr *msg,
			  size_t size, int flags)
{}

static int unix_stream_recvmsg(struct socket *sock, struct msghdr *msg,
			       size_t size, int flags)
{}

static int unix_stream_splice_actor(struct sk_buff *skb,
				    int skip, int chunk,
				    struct unix_stream_read_state *state)
{}

static ssize_t unix_stream_splice_read(struct socket *sock,  loff_t *ppos,
				       struct pipe_inode_info *pipe,
				       size_t size, unsigned int flags)
{}

static int unix_shutdown(struct socket *sock, int mode)
{}

long unix_inq_len(struct sock *sk)
{}
EXPORT_SYMBOL_GPL();

long unix_outq_len(struct sock *sk)
{}
EXPORT_SYMBOL_GPL();

static int unix_open_file(struct sock *sk)
{}

static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{}

#ifdef CONFIG_COMPAT
static int unix_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{}
#endif

static __poll_t unix_poll(struct file *file, struct socket *sock, poll_table *wait)
{}

static __poll_t unix_dgram_poll(struct file *file, struct socket *sock,
				    poll_table *wait)
{}

#ifdef CONFIG_PROC_FS

#define BUCKET_SPACE

#define get_bucket(x)
#define get_offset(x)
#define set_bucket_offset(b, o)

static struct sock *unix_from_bucket(struct seq_file *seq, loff_t *pos)
{}

static struct sock *unix_get_first(struct seq_file *seq, loff_t *pos)
{}

static struct sock *unix_get_next(struct seq_file *seq, struct sock *sk,
				  loff_t *pos)
{}

static void *unix_seq_start(struct seq_file *seq, loff_t *pos)
{}

static void *unix_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{}

static void unix_seq_stop(struct seq_file *seq, void *v)
{}

static int unix_seq_show(struct seq_file *seq, void *v)
{}

static const struct seq_operations unix_seq_ops =;

#ifdef CONFIG_BPF_SYSCALL
struct bpf_unix_iter_state {};

struct bpf_iter__unix {};

static int unix_prog_seq_show(struct bpf_prog *prog, struct bpf_iter_meta *meta,
			      struct unix_sock *unix_sk, uid_t uid)
{}

static int bpf_iter_unix_hold_batch(struct seq_file *seq, struct sock *start_sk)

{}

static void bpf_iter_unix_put_batch(struct bpf_unix_iter_state *iter)
{}

static int bpf_iter_unix_realloc_batch(struct bpf_unix_iter_state *iter,
				       unsigned int new_batch_sz)
{}

static struct sock *bpf_iter_unix_batch(struct seq_file *seq,
					loff_t *pos)
{}

static void *bpf_iter_unix_seq_start(struct seq_file *seq, loff_t *pos)
{}

static void *bpf_iter_unix_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{}

static int bpf_iter_unix_seq_show(struct seq_file *seq, void *v)
{}

static void bpf_iter_unix_seq_stop(struct seq_file *seq, void *v)
{}

static const struct seq_operations bpf_iter_unix_seq_ops =;
#endif
#endif

static const struct net_proto_family unix_family_ops =;


static int __net_init unix_net_init(struct net *net)
{}

static void __net_exit unix_net_exit(struct net *net)
{}

static struct pernet_operations unix_net_ops =;

#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_PROC_FS)
DEFINE_BPF_ITER_FUNC(unix, struct bpf_iter_meta *meta,
		     struct unix_sock *unix_sk, uid_t uid)

#define INIT_BATCH_SZ

static int bpf_iter_init_unix(void *priv_data, struct bpf_iter_aux_info *aux)
{}

static void bpf_iter_fini_unix(void *priv_data)
{}

static const struct bpf_iter_seq_info unix_seq_info =;

static const struct bpf_func_proto *
bpf_iter_unix_get_func_proto(enum bpf_func_id func_id,
			     const struct bpf_prog *prog)
{}

static struct bpf_iter_reg unix_reg_info =;

static void __init bpf_iter_register(void)
{}
#endif

static int __init af_unix_init(void)
{}

/* Later than subsys_initcall() because we depend on stuff initialised there */
fs_initcall(af_unix_init);