162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * INET		An implementation of the TCP/IP protocol suite for the LINUX
462306a36Sopenharmony_ci *		operating system.  INET is implemented using the  BSD Socket
562306a36Sopenharmony_ci *		interface as the means of communication with the user level.
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci *		Generic socket support routines. Memory allocators, socket lock/release
862306a36Sopenharmony_ci *		handler for protocols to use and generic option handler.
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci * Authors:	Ross Biro
1162306a36Sopenharmony_ci *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
1262306a36Sopenharmony_ci *		Florian La Roche, <flla@stud.uni-sb.de>
1362306a36Sopenharmony_ci *		Alan Cox, <A.Cox@swansea.ac.uk>
1462306a36Sopenharmony_ci *
1562306a36Sopenharmony_ci * Fixes:
1662306a36Sopenharmony_ci *		Alan Cox	: 	Numerous verify_area() problems
1762306a36Sopenharmony_ci *		Alan Cox	:	Connecting on a connecting socket
1862306a36Sopenharmony_ci *					now returns an error for tcp.
1962306a36Sopenharmony_ci *		Alan Cox	:	sock->protocol is set correctly.
2062306a36Sopenharmony_ci *					and is not sometimes left as 0.
2162306a36Sopenharmony_ci *		Alan Cox	:	connect handles icmp errors on a
2262306a36Sopenharmony_ci *					connect properly. Unfortunately there
2362306a36Sopenharmony_ci *					is a restart syscall nasty there. I
2462306a36Sopenharmony_ci *					can't match BSD without hacking the C
2562306a36Sopenharmony_ci *					library. Ideas urgently sought!
2662306a36Sopenharmony_ci *		Alan Cox	:	Disallow bind() to addresses that are
2762306a36Sopenharmony_ci *					not ours - especially broadcast ones!!
2862306a36Sopenharmony_ci *		Alan Cox	:	Socket 1024 _IS_ ok for users. (fencepost)
2962306a36Sopenharmony_ci *		Alan Cox	:	sock_wfree/sock_rfree don't destroy sockets,
3062306a36Sopenharmony_ci *					instead they leave that for the DESTROY timer.
3162306a36Sopenharmony_ci *		Alan Cox	:	Clean up error flag in accept
3262306a36Sopenharmony_ci *		Alan Cox	:	TCP ack handling is buggy, the DESTROY timer
3362306a36Sopenharmony_ci *					was buggy. Put a remove_sock() in the handler
3462306a36Sopenharmony_ci *					for memory when we hit 0. Also altered the timer
3562306a36Sopenharmony_ci *					code. The ACK stuff can wait and needs major
3662306a36Sopenharmony_ci *					TCP layer surgery.
3762306a36Sopenharmony_ci *		Alan Cox	:	Fixed TCP ack bug, removed remove sock
3862306a36Sopenharmony_ci *					and fixed timer/inet_bh race.
3962306a36Sopenharmony_ci *		Alan Cox	:	Added zapped flag for TCP
4062306a36Sopenharmony_ci *		Alan Cox	:	Move kfree_skb into skbuff.c and tidied up surplus code
4162306a36Sopenharmony_ci *		Alan Cox	:	for new sk_buff allocations wmalloc/rmalloc now call alloc_skb
4262306a36Sopenharmony_ci *		Alan Cox	:	kfree_s calls now are kfree_skbmem so we can track skb resources
4362306a36Sopenharmony_ci *		Alan Cox	:	Supports socket option broadcast now as does udp. Packet and raw need fixing.
4462306a36Sopenharmony_ci *		Alan Cox	:	Added RCVBUF,SNDBUF size setting. It suddenly occurred to me how easy it was so...
4562306a36Sopenharmony_ci *		Rick Sladkey	:	Relaxed UDP rules for matching packets.
4662306a36Sopenharmony_ci *		C.E.Hawkins	:	IFF_PROMISC/SIOCGHWADDR support
4762306a36Sopenharmony_ci *	Pauline Middelink	:	identd support
4862306a36Sopenharmony_ci *		Alan Cox	:	Fixed connect() taking signals I think.
4962306a36Sopenharmony_ci *		Alan Cox	:	SO_LINGER supported
5062306a36Sopenharmony_ci *		Alan Cox	:	Error reporting fixes
5162306a36Sopenharmony_ci *		Anonymous	:	inet_create tidied up (sk->reuse setting)
5262306a36Sopenharmony_ci *		Alan Cox	:	inet sockets don't set sk->type!
5362306a36Sopenharmony_ci *		Alan Cox	:	Split socket option code
5462306a36Sopenharmony_ci *		Alan Cox	:	Callbacks
5562306a36Sopenharmony_ci *		Alan Cox	:	Nagle flag for Charles & Johannes stuff
5662306a36Sopenharmony_ci *		Alex		:	Removed restriction on inet fioctl
5762306a36Sopenharmony_ci *		Alan Cox	:	Splitting INET from NET core
5862306a36Sopenharmony_ci *		Alan Cox	:	Fixed bogus SO_TYPE handling in getsockopt()
5962306a36Sopenharmony_ci *		Adam Caldwell	:	Missing return in SO_DONTROUTE/SO_DEBUG code
6062306a36Sopenharmony_ci *		Alan Cox	:	Split IP from generic code
6162306a36Sopenharmony_ci *		Alan Cox	:	New kfree_skbmem()
6262306a36Sopenharmony_ci *		Alan Cox	:	Make SO_DEBUG superuser only.
6362306a36Sopenharmony_ci *		Alan Cox	:	Allow anyone to clear SO_DEBUG
6462306a36Sopenharmony_ci *					(compatibility fix)
6562306a36Sopenharmony_ci *		Alan Cox	:	Added optimistic memory grabbing for AF_UNIX throughput.
6662306a36Sopenharmony_ci *		Alan Cox	:	Allocator for a socket is settable.
6762306a36Sopenharmony_ci *		Alan Cox	:	SO_ERROR includes soft errors.
6862306a36Sopenharmony_ci *		Alan Cox	:	Allow NULL arguments on some SO_ opts
6962306a36Sopenharmony_ci *		Alan Cox	: 	Generic socket allocation to make hooks
7062306a36Sopenharmony_ci *					easier (suggested by Craig Metz).
7162306a36Sopenharmony_ci *		Michael Pall	:	SO_ERROR returns positive errno again
7262306a36Sopenharmony_ci *              Steve Whitehouse:       Added default destructor to free
7362306a36Sopenharmony_ci *                                      protocol private data.
7462306a36Sopenharmony_ci *              Steve Whitehouse:       Added various other default routines
7562306a36Sopenharmony_ci *                                      common to several socket families.
7662306a36Sopenharmony_ci *              Chris Evans     :       Call suser() check last on F_SETOWN
7762306a36Sopenharmony_ci *		Jay Schulist	:	Added SO_ATTACH_FILTER and SO_DETACH_FILTER.
7862306a36Sopenharmony_ci *		Andi Kleen	:	Add sock_kmalloc()/sock_kfree_s()
7962306a36Sopenharmony_ci *		Andi Kleen	:	Fix write_space callback
8062306a36Sopenharmony_ci *		Chris Evans	:	Security fixes - signedness again
8162306a36Sopenharmony_ci *		Arnaldo C. Melo :       cleanups, use skb_queue_purge
8262306a36Sopenharmony_ci *
8362306a36Sopenharmony_ci * To Fix:
8462306a36Sopenharmony_ci */
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci#include <asm/unaligned.h>
8962306a36Sopenharmony_ci#include <linux/capability.h>
9062306a36Sopenharmony_ci#include <linux/errno.h>
9162306a36Sopenharmony_ci#include <linux/errqueue.h>
9262306a36Sopenharmony_ci#include <linux/types.h>
9362306a36Sopenharmony_ci#include <linux/socket.h>
9462306a36Sopenharmony_ci#include <linux/in.h>
9562306a36Sopenharmony_ci#include <linux/kernel.h>
9662306a36Sopenharmony_ci#include <linux/module.h>
9762306a36Sopenharmony_ci#include <linux/proc_fs.h>
9862306a36Sopenharmony_ci#include <linux/seq_file.h>
9962306a36Sopenharmony_ci#include <linux/sched.h>
10062306a36Sopenharmony_ci#include <linux/sched/mm.h>
10162306a36Sopenharmony_ci#include <linux/timer.h>
10262306a36Sopenharmony_ci#include <linux/string.h>
10362306a36Sopenharmony_ci#include <linux/sockios.h>
10462306a36Sopenharmony_ci#include <linux/net.h>
10562306a36Sopenharmony_ci#include <linux/mm.h>
10662306a36Sopenharmony_ci#include <linux/slab.h>
10762306a36Sopenharmony_ci#include <linux/interrupt.h>
10862306a36Sopenharmony_ci#include <linux/poll.h>
10962306a36Sopenharmony_ci#include <linux/tcp.h>
11062306a36Sopenharmony_ci#include <linux/udp.h>
11162306a36Sopenharmony_ci#include <linux/init.h>
11262306a36Sopenharmony_ci#include <linux/highmem.h>
11362306a36Sopenharmony_ci#include <linux/user_namespace.h>
11462306a36Sopenharmony_ci#include <linux/static_key.h>
11562306a36Sopenharmony_ci#include <linux/memcontrol.h>
11662306a36Sopenharmony_ci#include <linux/prefetch.h>
11762306a36Sopenharmony_ci#include <linux/compat.h>
11862306a36Sopenharmony_ci#include <linux/mroute.h>
11962306a36Sopenharmony_ci#include <linux/mroute6.h>
12062306a36Sopenharmony_ci#include <linux/icmpv6.h>
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci#include <linux/uaccess.h>
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci#include <linux/netdevice.h>
12562306a36Sopenharmony_ci#include <net/protocol.h>
12662306a36Sopenharmony_ci#include <linux/skbuff.h>
12762306a36Sopenharmony_ci#include <net/net_namespace.h>
12862306a36Sopenharmony_ci#include <net/request_sock.h>
12962306a36Sopenharmony_ci#include <net/sock.h>
13062306a36Sopenharmony_ci#include <linux/net_tstamp.h>
13162306a36Sopenharmony_ci#include <net/xfrm.h>
13262306a36Sopenharmony_ci#include <linux/ipsec.h>
13362306a36Sopenharmony_ci#include <net/cls_cgroup.h>
13462306a36Sopenharmony_ci#include <net/netprio_cgroup.h>
13562306a36Sopenharmony_ci#include <linux/sock_diag.h>
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci#include <linux/filter.h>
13862306a36Sopenharmony_ci#include <net/sock_reuseport.h>
13962306a36Sopenharmony_ci#include <net/bpf_sk_storage.h>
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci#include <trace/events/sock.h>
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci#include <net/tcp.h>
14462306a36Sopenharmony_ci#include <net/busy_poll.h>
14562306a36Sopenharmony_ci#include <net/phonet/phonet.h>
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci#include <linux/ethtool.h>
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci#include "dev.h"
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_cistatic DEFINE_MUTEX(proto_list_mutex);
15262306a36Sopenharmony_cistatic LIST_HEAD(proto_list);
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_cistatic void sock_def_write_space_wfree(struct sock *sk);
15562306a36Sopenharmony_cistatic void sock_def_write_space(struct sock *sk);
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci/**
15862306a36Sopenharmony_ci * sk_ns_capable - General socket capability test
15962306a36Sopenharmony_ci * @sk: Socket to use a capability on or through
16062306a36Sopenharmony_ci * @user_ns: The user namespace of the capability to use
16162306a36Sopenharmony_ci * @cap: The capability to use
16262306a36Sopenharmony_ci *
16362306a36Sopenharmony_ci * Test to see if the opener of the socket had when the socket was
16462306a36Sopenharmony_ci * created and the current process has the capability @cap in the user
16562306a36Sopenharmony_ci * namespace @user_ns.
16662306a36Sopenharmony_ci */
16762306a36Sopenharmony_cibool sk_ns_capable(const struct sock *sk,
16862306a36Sopenharmony_ci		   struct user_namespace *user_ns, int cap)
16962306a36Sopenharmony_ci{
17062306a36Sopenharmony_ci	return file_ns_capable(sk->sk_socket->file, user_ns, cap) &&
17162306a36Sopenharmony_ci		ns_capable(user_ns, cap);
17262306a36Sopenharmony_ci}
17362306a36Sopenharmony_ciEXPORT_SYMBOL(sk_ns_capable);
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci/**
17662306a36Sopenharmony_ci * sk_capable - Socket global capability test
17762306a36Sopenharmony_ci * @sk: Socket to use a capability on or through
17862306a36Sopenharmony_ci * @cap: The global capability to use
17962306a36Sopenharmony_ci *
18062306a36Sopenharmony_ci * Test to see if the opener of the socket had when the socket was
18162306a36Sopenharmony_ci * created and the current process has the capability @cap in all user
18262306a36Sopenharmony_ci * namespaces.
18362306a36Sopenharmony_ci */
18462306a36Sopenharmony_cibool sk_capable(const struct sock *sk, int cap)
18562306a36Sopenharmony_ci{
18662306a36Sopenharmony_ci	return sk_ns_capable(sk, &init_user_ns, cap);
18762306a36Sopenharmony_ci}
18862306a36Sopenharmony_ciEXPORT_SYMBOL(sk_capable);
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci/**
19162306a36Sopenharmony_ci * sk_net_capable - Network namespace socket capability test
19262306a36Sopenharmony_ci * @sk: Socket to use a capability on or through
19362306a36Sopenharmony_ci * @cap: The capability to use
19462306a36Sopenharmony_ci *
19562306a36Sopenharmony_ci * Test to see if the opener of the socket had when the socket was created
19662306a36Sopenharmony_ci * and the current process has the capability @cap over the network namespace
19762306a36Sopenharmony_ci * the socket is a member of.
19862306a36Sopenharmony_ci */
19962306a36Sopenharmony_cibool sk_net_capable(const struct sock *sk, int cap)
20062306a36Sopenharmony_ci{
20162306a36Sopenharmony_ci	return sk_ns_capable(sk, sock_net(sk)->user_ns, cap);
20262306a36Sopenharmony_ci}
20362306a36Sopenharmony_ciEXPORT_SYMBOL(sk_net_capable);
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci/*
20662306a36Sopenharmony_ci * Each address family might have different locking rules, so we have
20762306a36Sopenharmony_ci * one slock key per address family and separate keys for internal and
20862306a36Sopenharmony_ci * userspace sockets.
20962306a36Sopenharmony_ci */
21062306a36Sopenharmony_cistatic struct lock_class_key af_family_keys[AF_MAX];
21162306a36Sopenharmony_cistatic struct lock_class_key af_family_kern_keys[AF_MAX];
21262306a36Sopenharmony_cistatic struct lock_class_key af_family_slock_keys[AF_MAX];
21362306a36Sopenharmony_cistatic struct lock_class_key af_family_kern_slock_keys[AF_MAX];
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci/*
21662306a36Sopenharmony_ci * Make lock validator output more readable. (we pre-construct these
21762306a36Sopenharmony_ci * strings build-time, so that runtime initialization of socket
21862306a36Sopenharmony_ci * locks is fast):
21962306a36Sopenharmony_ci */
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci#define _sock_locks(x)						  \
22262306a36Sopenharmony_ci  x "AF_UNSPEC",	x "AF_UNIX"     ,	x "AF_INET"     , \
22362306a36Sopenharmony_ci  x "AF_AX25"  ,	x "AF_IPX"      ,	x "AF_APPLETALK", \
22462306a36Sopenharmony_ci  x "AF_NETROM",	x "AF_BRIDGE"   ,	x "AF_ATMPVC"   , \
22562306a36Sopenharmony_ci  x "AF_X25"   ,	x "AF_INET6"    ,	x "AF_ROSE"     , \
22662306a36Sopenharmony_ci  x "AF_DECnet",	x "AF_NETBEUI"  ,	x "AF_SECURITY" , \
22762306a36Sopenharmony_ci  x "AF_KEY"   ,	x "AF_NETLINK"  ,	x "AF_PACKET"   , \
22862306a36Sopenharmony_ci  x "AF_ASH"   ,	x "AF_ECONET"   ,	x "AF_ATMSVC"   , \
22962306a36Sopenharmony_ci  x "AF_RDS"   ,	x "AF_SNA"      ,	x "AF_IRDA"     , \
23062306a36Sopenharmony_ci  x "AF_PPPOX" ,	x "AF_WANPIPE"  ,	x "AF_LLC"      , \
23162306a36Sopenharmony_ci  x "27"       ,	x "28"          ,	x "AF_CAN"      , \
23262306a36Sopenharmony_ci  x "AF_TIPC"  ,	x "AF_BLUETOOTH",	x "IUCV"        , \
23362306a36Sopenharmony_ci  x "AF_RXRPC" ,	x "AF_ISDN"     ,	x "AF_PHONET"   , \
23462306a36Sopenharmony_ci  x "AF_IEEE802154",	x "AF_CAIF"	,	x "AF_ALG"      , \
23562306a36Sopenharmony_ci  x "AF_NFC"   ,	x "AF_VSOCK"    ,	x "AF_KCM"      , \
23662306a36Sopenharmony_ci  x "AF_QIPCRTR",	x "AF_SMC"	,	x "AF_XDP"	, \
23762306a36Sopenharmony_ci  x "AF_MCTP"  , \
23862306a36Sopenharmony_ci  x "AF_MAX"
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_cistatic const char *const af_family_key_strings[AF_MAX+1] = {
24162306a36Sopenharmony_ci	_sock_locks("sk_lock-")
24262306a36Sopenharmony_ci};
24362306a36Sopenharmony_cistatic const char *const af_family_slock_key_strings[AF_MAX+1] = {
24462306a36Sopenharmony_ci	_sock_locks("slock-")
24562306a36Sopenharmony_ci};
24662306a36Sopenharmony_cistatic const char *const af_family_clock_key_strings[AF_MAX+1] = {
24762306a36Sopenharmony_ci	_sock_locks("clock-")
24862306a36Sopenharmony_ci};
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_cistatic const char *const af_family_kern_key_strings[AF_MAX+1] = {
25162306a36Sopenharmony_ci	_sock_locks("k-sk_lock-")
25262306a36Sopenharmony_ci};
25362306a36Sopenharmony_cistatic const char *const af_family_kern_slock_key_strings[AF_MAX+1] = {
25462306a36Sopenharmony_ci	_sock_locks("k-slock-")
25562306a36Sopenharmony_ci};
25662306a36Sopenharmony_cistatic const char *const af_family_kern_clock_key_strings[AF_MAX+1] = {
25762306a36Sopenharmony_ci	_sock_locks("k-clock-")
25862306a36Sopenharmony_ci};
25962306a36Sopenharmony_cistatic const char *const af_family_rlock_key_strings[AF_MAX+1] = {
26062306a36Sopenharmony_ci	_sock_locks("rlock-")
26162306a36Sopenharmony_ci};
26262306a36Sopenharmony_cistatic const char *const af_family_wlock_key_strings[AF_MAX+1] = {
26362306a36Sopenharmony_ci	_sock_locks("wlock-")
26462306a36Sopenharmony_ci};
26562306a36Sopenharmony_cistatic const char *const af_family_elock_key_strings[AF_MAX+1] = {
26662306a36Sopenharmony_ci	_sock_locks("elock-")
26762306a36Sopenharmony_ci};
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci/*
27062306a36Sopenharmony_ci * sk_callback_lock and sk queues locking rules are per-address-family,
27162306a36Sopenharmony_ci * so split the lock classes by using a per-AF key:
27262306a36Sopenharmony_ci */
27362306a36Sopenharmony_cistatic struct lock_class_key af_callback_keys[AF_MAX];
27462306a36Sopenharmony_cistatic struct lock_class_key af_rlock_keys[AF_MAX];
27562306a36Sopenharmony_cistatic struct lock_class_key af_wlock_keys[AF_MAX];
27662306a36Sopenharmony_cistatic struct lock_class_key af_elock_keys[AF_MAX];
27762306a36Sopenharmony_cistatic struct lock_class_key af_kern_callback_keys[AF_MAX];
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ci/* Run time adjustable parameters. */
28062306a36Sopenharmony_ci__u32 sysctl_wmem_max __read_mostly = SK_WMEM_MAX;
28162306a36Sopenharmony_ciEXPORT_SYMBOL(sysctl_wmem_max);
28262306a36Sopenharmony_ci__u32 sysctl_rmem_max __read_mostly = SK_RMEM_MAX;
28362306a36Sopenharmony_ciEXPORT_SYMBOL(sysctl_rmem_max);
28462306a36Sopenharmony_ci__u32 sysctl_wmem_default __read_mostly = SK_WMEM_MAX;
28562306a36Sopenharmony_ci__u32 sysctl_rmem_default __read_mostly = SK_RMEM_MAX;
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci/* Maximal space eaten by iovec or ancillary data plus some space */
28862306a36Sopenharmony_ciint sysctl_optmem_max __read_mostly = sizeof(unsigned long)*(2*UIO_MAXIOV+512);
28962306a36Sopenharmony_ciEXPORT_SYMBOL(sysctl_optmem_max);
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ciint sysctl_tstamp_allow_data __read_mostly = 1;
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ciDEFINE_STATIC_KEY_FALSE(memalloc_socks_key);
29462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(memalloc_socks_key);
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci/**
29762306a36Sopenharmony_ci * sk_set_memalloc - sets %SOCK_MEMALLOC
29862306a36Sopenharmony_ci * @sk: socket to set it on
29962306a36Sopenharmony_ci *
30062306a36Sopenharmony_ci * Set %SOCK_MEMALLOC on a socket for access to emergency reserves.
30162306a36Sopenharmony_ci * It's the responsibility of the admin to adjust min_free_kbytes
30262306a36Sopenharmony_ci * to meet the requirements
30362306a36Sopenharmony_ci */
30462306a36Sopenharmony_civoid sk_set_memalloc(struct sock *sk)
30562306a36Sopenharmony_ci{
30662306a36Sopenharmony_ci	sock_set_flag(sk, SOCK_MEMALLOC);
30762306a36Sopenharmony_ci	sk->sk_allocation |= __GFP_MEMALLOC;
30862306a36Sopenharmony_ci	static_branch_inc(&memalloc_socks_key);
30962306a36Sopenharmony_ci}
31062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(sk_set_memalloc);
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_civoid sk_clear_memalloc(struct sock *sk)
31362306a36Sopenharmony_ci{
31462306a36Sopenharmony_ci	sock_reset_flag(sk, SOCK_MEMALLOC);
31562306a36Sopenharmony_ci	sk->sk_allocation &= ~__GFP_MEMALLOC;
31662306a36Sopenharmony_ci	static_branch_dec(&memalloc_socks_key);
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	/*
31962306a36Sopenharmony_ci	 * SOCK_MEMALLOC is allowed to ignore rmem limits to ensure forward
32062306a36Sopenharmony_ci	 * progress of swapping. SOCK_MEMALLOC may be cleared while
32162306a36Sopenharmony_ci	 * it has rmem allocations due to the last swapfile being deactivated
32262306a36Sopenharmony_ci	 * but there is a risk that the socket is unusable due to exceeding
32362306a36Sopenharmony_ci	 * the rmem limits. Reclaim the reserves and obey rmem limits again.
32462306a36Sopenharmony_ci	 */
32562306a36Sopenharmony_ci	sk_mem_reclaim(sk);
32662306a36Sopenharmony_ci}
32762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(sk_clear_memalloc);
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ciint __sk_backlog_rcv(struct sock *sk, struct sk_buff *skb)
33062306a36Sopenharmony_ci{
33162306a36Sopenharmony_ci	int ret;
33262306a36Sopenharmony_ci	unsigned int noreclaim_flag;
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	/* these should have been dropped before queueing */
33562306a36Sopenharmony_ci	BUG_ON(!sock_flag(sk, SOCK_MEMALLOC));
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci	noreclaim_flag = memalloc_noreclaim_save();
33862306a36Sopenharmony_ci	ret = INDIRECT_CALL_INET(sk->sk_backlog_rcv,
33962306a36Sopenharmony_ci				 tcp_v6_do_rcv,
34062306a36Sopenharmony_ci				 tcp_v4_do_rcv,
34162306a36Sopenharmony_ci				 sk, skb);
34262306a36Sopenharmony_ci	memalloc_noreclaim_restore(noreclaim_flag);
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	return ret;
34562306a36Sopenharmony_ci}
34662306a36Sopenharmony_ciEXPORT_SYMBOL(__sk_backlog_rcv);
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_civoid sk_error_report(struct sock *sk)
34962306a36Sopenharmony_ci{
35062306a36Sopenharmony_ci	sk->sk_error_report(sk);
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	switch (sk->sk_family) {
35362306a36Sopenharmony_ci	case AF_INET:
35462306a36Sopenharmony_ci		fallthrough;
35562306a36Sopenharmony_ci	case AF_INET6:
35662306a36Sopenharmony_ci		trace_inet_sk_error_report(sk);
35762306a36Sopenharmony_ci		break;
35862306a36Sopenharmony_ci	default:
35962306a36Sopenharmony_ci		break;
36062306a36Sopenharmony_ci	}
36162306a36Sopenharmony_ci}
36262306a36Sopenharmony_ciEXPORT_SYMBOL(sk_error_report);
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ciint sock_get_timeout(long timeo, void *optval, bool old_timeval)
36562306a36Sopenharmony_ci{
36662306a36Sopenharmony_ci	struct __kernel_sock_timeval tv;
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci	if (timeo == MAX_SCHEDULE_TIMEOUT) {
36962306a36Sopenharmony_ci		tv.tv_sec = 0;
37062306a36Sopenharmony_ci		tv.tv_usec = 0;
37162306a36Sopenharmony_ci	} else {
37262306a36Sopenharmony_ci		tv.tv_sec = timeo / HZ;
37362306a36Sopenharmony_ci		tv.tv_usec = ((timeo % HZ) * USEC_PER_SEC) / HZ;
37462306a36Sopenharmony_ci	}
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ci	if (old_timeval && in_compat_syscall() && !COMPAT_USE_64BIT_TIME) {
37762306a36Sopenharmony_ci		struct old_timeval32 tv32 = { tv.tv_sec, tv.tv_usec };
37862306a36Sopenharmony_ci		*(struct old_timeval32 *)optval = tv32;
37962306a36Sopenharmony_ci		return sizeof(tv32);
38062306a36Sopenharmony_ci	}
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci	if (old_timeval) {
38362306a36Sopenharmony_ci		struct __kernel_old_timeval old_tv;
38462306a36Sopenharmony_ci		old_tv.tv_sec = tv.tv_sec;
38562306a36Sopenharmony_ci		old_tv.tv_usec = tv.tv_usec;
38662306a36Sopenharmony_ci		*(struct __kernel_old_timeval *)optval = old_tv;
38762306a36Sopenharmony_ci		return sizeof(old_tv);
38862306a36Sopenharmony_ci	}
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci	*(struct __kernel_sock_timeval *)optval = tv;
39162306a36Sopenharmony_ci	return sizeof(tv);
39262306a36Sopenharmony_ci}
39362306a36Sopenharmony_ciEXPORT_SYMBOL(sock_get_timeout);
39462306a36Sopenharmony_ci
39562306a36Sopenharmony_ciint sock_copy_user_timeval(struct __kernel_sock_timeval *tv,
39662306a36Sopenharmony_ci			   sockptr_t optval, int optlen, bool old_timeval)
39762306a36Sopenharmony_ci{
39862306a36Sopenharmony_ci	if (old_timeval && in_compat_syscall() && !COMPAT_USE_64BIT_TIME) {
39962306a36Sopenharmony_ci		struct old_timeval32 tv32;
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci		if (optlen < sizeof(tv32))
40262306a36Sopenharmony_ci			return -EINVAL;
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci		if (copy_from_sockptr(&tv32, optval, sizeof(tv32)))
40562306a36Sopenharmony_ci			return -EFAULT;
40662306a36Sopenharmony_ci		tv->tv_sec = tv32.tv_sec;
40762306a36Sopenharmony_ci		tv->tv_usec = tv32.tv_usec;
40862306a36Sopenharmony_ci	} else if (old_timeval) {
40962306a36Sopenharmony_ci		struct __kernel_old_timeval old_tv;
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ci		if (optlen < sizeof(old_tv))
41262306a36Sopenharmony_ci			return -EINVAL;
41362306a36Sopenharmony_ci		if (copy_from_sockptr(&old_tv, optval, sizeof(old_tv)))
41462306a36Sopenharmony_ci			return -EFAULT;
41562306a36Sopenharmony_ci		tv->tv_sec = old_tv.tv_sec;
41662306a36Sopenharmony_ci		tv->tv_usec = old_tv.tv_usec;
41762306a36Sopenharmony_ci	} else {
41862306a36Sopenharmony_ci		if (optlen < sizeof(*tv))
41962306a36Sopenharmony_ci			return -EINVAL;
42062306a36Sopenharmony_ci		if (copy_from_sockptr(tv, optval, sizeof(*tv)))
42162306a36Sopenharmony_ci			return -EFAULT;
42262306a36Sopenharmony_ci	}
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_ci	return 0;
42562306a36Sopenharmony_ci}
42662306a36Sopenharmony_ciEXPORT_SYMBOL(sock_copy_user_timeval);
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_cistatic int sock_set_timeout(long *timeo_p, sockptr_t optval, int optlen,
42962306a36Sopenharmony_ci			    bool old_timeval)
43062306a36Sopenharmony_ci{
43162306a36Sopenharmony_ci	struct __kernel_sock_timeval tv;
43262306a36Sopenharmony_ci	int err = sock_copy_user_timeval(&tv, optval, optlen, old_timeval);
43362306a36Sopenharmony_ci	long val;
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci	if (err)
43662306a36Sopenharmony_ci		return err;
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_ci	if (tv.tv_usec < 0 || tv.tv_usec >= USEC_PER_SEC)
43962306a36Sopenharmony_ci		return -EDOM;
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci	if (tv.tv_sec < 0) {
44262306a36Sopenharmony_ci		static int warned __read_mostly;
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci		WRITE_ONCE(*timeo_p, 0);
44562306a36Sopenharmony_ci		if (warned < 10 && net_ratelimit()) {
44662306a36Sopenharmony_ci			warned++;
44762306a36Sopenharmony_ci			pr_info("%s: `%s' (pid %d) tries to set negative timeout\n",
44862306a36Sopenharmony_ci				__func__, current->comm, task_pid_nr(current));
44962306a36Sopenharmony_ci		}
45062306a36Sopenharmony_ci		return 0;
45162306a36Sopenharmony_ci	}
45262306a36Sopenharmony_ci	val = MAX_SCHEDULE_TIMEOUT;
45362306a36Sopenharmony_ci	if ((tv.tv_sec || tv.tv_usec) &&
45462306a36Sopenharmony_ci	    (tv.tv_sec < (MAX_SCHEDULE_TIMEOUT / HZ - 1)))
45562306a36Sopenharmony_ci		val = tv.tv_sec * HZ + DIV_ROUND_UP((unsigned long)tv.tv_usec,
45662306a36Sopenharmony_ci						    USEC_PER_SEC / HZ);
45762306a36Sopenharmony_ci	WRITE_ONCE(*timeo_p, val);
45862306a36Sopenharmony_ci	return 0;
45962306a36Sopenharmony_ci}
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_cistatic bool sock_needs_netstamp(const struct sock *sk)
46262306a36Sopenharmony_ci{
46362306a36Sopenharmony_ci	switch (sk->sk_family) {
46462306a36Sopenharmony_ci	case AF_UNSPEC:
46562306a36Sopenharmony_ci	case AF_UNIX:
46662306a36Sopenharmony_ci		return false;
46762306a36Sopenharmony_ci	default:
46862306a36Sopenharmony_ci		return true;
46962306a36Sopenharmony_ci	}
47062306a36Sopenharmony_ci}
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_cistatic void sock_disable_timestamp(struct sock *sk, unsigned long flags)
47362306a36Sopenharmony_ci{
47462306a36Sopenharmony_ci	if (sk->sk_flags & flags) {
47562306a36Sopenharmony_ci		sk->sk_flags &= ~flags;
47662306a36Sopenharmony_ci		if (sock_needs_netstamp(sk) &&
47762306a36Sopenharmony_ci		    !(sk->sk_flags & SK_FLAGS_TIMESTAMP))
47862306a36Sopenharmony_ci			net_disable_timestamp();
47962306a36Sopenharmony_ci	}
48062306a36Sopenharmony_ci}
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_ciint __sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
48462306a36Sopenharmony_ci{
48562306a36Sopenharmony_ci	unsigned long flags;
48662306a36Sopenharmony_ci	struct sk_buff_head *list = &sk->sk_receive_queue;
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_ci	if (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf) {
48962306a36Sopenharmony_ci		atomic_inc(&sk->sk_drops);
49062306a36Sopenharmony_ci		trace_sock_rcvqueue_full(sk, skb);
49162306a36Sopenharmony_ci		return -ENOMEM;
49262306a36Sopenharmony_ci	}
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci	if (!sk_rmem_schedule(sk, skb, skb->truesize)) {
49562306a36Sopenharmony_ci		atomic_inc(&sk->sk_drops);
49662306a36Sopenharmony_ci		return -ENOBUFS;
49762306a36Sopenharmony_ci	}
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci	skb->dev = NULL;
50062306a36Sopenharmony_ci	skb_set_owner_r(skb, sk);
50162306a36Sopenharmony_ci
50262306a36Sopenharmony_ci	/* we escape from rcu protected region, make sure we dont leak
50362306a36Sopenharmony_ci	 * a norefcounted dst
50462306a36Sopenharmony_ci	 */
50562306a36Sopenharmony_ci	skb_dst_force(skb);
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci	spin_lock_irqsave(&list->lock, flags);
50862306a36Sopenharmony_ci	sock_skb_set_dropcount(sk, skb);
50962306a36Sopenharmony_ci	__skb_queue_tail(list, skb);
51062306a36Sopenharmony_ci	spin_unlock_irqrestore(&list->lock, flags);
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_ci	if (!sock_flag(sk, SOCK_DEAD))
51362306a36Sopenharmony_ci		sk->sk_data_ready(sk);
51462306a36Sopenharmony_ci	return 0;
51562306a36Sopenharmony_ci}
51662306a36Sopenharmony_ciEXPORT_SYMBOL(__sock_queue_rcv_skb);
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_ciint sock_queue_rcv_skb_reason(struct sock *sk, struct sk_buff *skb,
51962306a36Sopenharmony_ci			      enum skb_drop_reason *reason)
52062306a36Sopenharmony_ci{
52162306a36Sopenharmony_ci	enum skb_drop_reason drop_reason;
52262306a36Sopenharmony_ci	int err;
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_ci	err = sk_filter(sk, skb);
52562306a36Sopenharmony_ci	if (err) {
52662306a36Sopenharmony_ci		drop_reason = SKB_DROP_REASON_SOCKET_FILTER;
52762306a36Sopenharmony_ci		goto out;
52862306a36Sopenharmony_ci	}
52962306a36Sopenharmony_ci	err = __sock_queue_rcv_skb(sk, skb);
53062306a36Sopenharmony_ci	switch (err) {
53162306a36Sopenharmony_ci	case -ENOMEM:
53262306a36Sopenharmony_ci		drop_reason = SKB_DROP_REASON_SOCKET_RCVBUFF;
53362306a36Sopenharmony_ci		break;
53462306a36Sopenharmony_ci	case -ENOBUFS:
53562306a36Sopenharmony_ci		drop_reason = SKB_DROP_REASON_PROTO_MEM;
53662306a36Sopenharmony_ci		break;
53762306a36Sopenharmony_ci	default:
53862306a36Sopenharmony_ci		drop_reason = SKB_NOT_DROPPED_YET;
53962306a36Sopenharmony_ci		break;
54062306a36Sopenharmony_ci	}
54162306a36Sopenharmony_ciout:
54262306a36Sopenharmony_ci	if (reason)
54362306a36Sopenharmony_ci		*reason = drop_reason;
54462306a36Sopenharmony_ci	return err;
54562306a36Sopenharmony_ci}
54662306a36Sopenharmony_ciEXPORT_SYMBOL(sock_queue_rcv_skb_reason);
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ciint __sk_receive_skb(struct sock *sk, struct sk_buff *skb,
54962306a36Sopenharmony_ci		     const int nested, unsigned int trim_cap, bool refcounted)
55062306a36Sopenharmony_ci{
55162306a36Sopenharmony_ci	int rc = NET_RX_SUCCESS;
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci	if (sk_filter_trim_cap(sk, skb, trim_cap))
55462306a36Sopenharmony_ci		goto discard_and_relse;
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_ci	skb->dev = NULL;
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_ci	if (sk_rcvqueues_full(sk, sk->sk_rcvbuf)) {
55962306a36Sopenharmony_ci		atomic_inc(&sk->sk_drops);
56062306a36Sopenharmony_ci		goto discard_and_relse;
56162306a36Sopenharmony_ci	}
56262306a36Sopenharmony_ci	if (nested)
56362306a36Sopenharmony_ci		bh_lock_sock_nested(sk);
56462306a36Sopenharmony_ci	else
56562306a36Sopenharmony_ci		bh_lock_sock(sk);
56662306a36Sopenharmony_ci	if (!sock_owned_by_user(sk)) {
56762306a36Sopenharmony_ci		/*
56862306a36Sopenharmony_ci		 * trylock + unlock semantics:
56962306a36Sopenharmony_ci		 */
57062306a36Sopenharmony_ci		mutex_acquire(&sk->sk_lock.dep_map, 0, 1, _RET_IP_);
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_ci		rc = sk_backlog_rcv(sk, skb);
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_ci		mutex_release(&sk->sk_lock.dep_map, _RET_IP_);
57562306a36Sopenharmony_ci	} else if (sk_add_backlog(sk, skb, READ_ONCE(sk->sk_rcvbuf))) {
57662306a36Sopenharmony_ci		bh_unlock_sock(sk);
57762306a36Sopenharmony_ci		atomic_inc(&sk->sk_drops);
57862306a36Sopenharmony_ci		goto discard_and_relse;
57962306a36Sopenharmony_ci	}
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_ci	bh_unlock_sock(sk);
58262306a36Sopenharmony_ciout:
58362306a36Sopenharmony_ci	if (refcounted)
58462306a36Sopenharmony_ci		sock_put(sk);
58562306a36Sopenharmony_ci	return rc;
58662306a36Sopenharmony_cidiscard_and_relse:
58762306a36Sopenharmony_ci	kfree_skb(skb);
58862306a36Sopenharmony_ci	goto out;
58962306a36Sopenharmony_ci}
59062306a36Sopenharmony_ciEXPORT_SYMBOL(__sk_receive_skb);
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_ciINDIRECT_CALLABLE_DECLARE(struct dst_entry *ip6_dst_check(struct dst_entry *,
59362306a36Sopenharmony_ci							  u32));
59462306a36Sopenharmony_ciINDIRECT_CALLABLE_DECLARE(struct dst_entry *ipv4_dst_check(struct dst_entry *,
59562306a36Sopenharmony_ci							   u32));
59662306a36Sopenharmony_cistruct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie)
59762306a36Sopenharmony_ci{
59862306a36Sopenharmony_ci	struct dst_entry *dst = __sk_dst_get(sk);
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci	if (dst && dst->obsolete &&
60162306a36Sopenharmony_ci	    INDIRECT_CALL_INET(dst->ops->check, ip6_dst_check, ipv4_dst_check,
60262306a36Sopenharmony_ci			       dst, cookie) == NULL) {
60362306a36Sopenharmony_ci		sk_tx_queue_clear(sk);
60462306a36Sopenharmony_ci		WRITE_ONCE(sk->sk_dst_pending_confirm, 0);
60562306a36Sopenharmony_ci		RCU_INIT_POINTER(sk->sk_dst_cache, NULL);
60662306a36Sopenharmony_ci		dst_release(dst);
60762306a36Sopenharmony_ci		return NULL;
60862306a36Sopenharmony_ci	}
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_ci	return dst;
61162306a36Sopenharmony_ci}
61262306a36Sopenharmony_ciEXPORT_SYMBOL(__sk_dst_check);
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_cistruct dst_entry *sk_dst_check(struct sock *sk, u32 cookie)
61562306a36Sopenharmony_ci{
61662306a36Sopenharmony_ci	struct dst_entry *dst = sk_dst_get(sk);
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_ci	if (dst && dst->obsolete &&
61962306a36Sopenharmony_ci	    INDIRECT_CALL_INET(dst->ops->check, ip6_dst_check, ipv4_dst_check,
62062306a36Sopenharmony_ci			       dst, cookie) == NULL) {
62162306a36Sopenharmony_ci		sk_dst_reset(sk);
62262306a36Sopenharmony_ci		dst_release(dst);
62362306a36Sopenharmony_ci		return NULL;
62462306a36Sopenharmony_ci	}
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_ci	return dst;
62762306a36Sopenharmony_ci}
62862306a36Sopenharmony_ciEXPORT_SYMBOL(sk_dst_check);
62962306a36Sopenharmony_ci
63062306a36Sopenharmony_cistatic int sock_bindtoindex_locked(struct sock *sk, int ifindex)
63162306a36Sopenharmony_ci{
63262306a36Sopenharmony_ci	int ret = -ENOPROTOOPT;
63362306a36Sopenharmony_ci#ifdef CONFIG_NETDEVICES
63462306a36Sopenharmony_ci	struct net *net = sock_net(sk);
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_ci	/* Sorry... */
63762306a36Sopenharmony_ci	ret = -EPERM;
63862306a36Sopenharmony_ci	if (sk->sk_bound_dev_if && !ns_capable(net->user_ns, CAP_NET_RAW))
63962306a36Sopenharmony_ci		goto out;
64062306a36Sopenharmony_ci
64162306a36Sopenharmony_ci	ret = -EINVAL;
64262306a36Sopenharmony_ci	if (ifindex < 0)
64362306a36Sopenharmony_ci		goto out;
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ci	/* Paired with all READ_ONCE() done locklessly. */
64662306a36Sopenharmony_ci	WRITE_ONCE(sk->sk_bound_dev_if, ifindex);
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci	if (sk->sk_prot->rehash)
64962306a36Sopenharmony_ci		sk->sk_prot->rehash(sk);
65062306a36Sopenharmony_ci	sk_dst_reset(sk);
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci	ret = 0;
65362306a36Sopenharmony_ci
65462306a36Sopenharmony_ciout:
65562306a36Sopenharmony_ci#endif
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ci	return ret;
65862306a36Sopenharmony_ci}
65962306a36Sopenharmony_ci
66062306a36Sopenharmony_ciint sock_bindtoindex(struct sock *sk, int ifindex, bool lock_sk)
66162306a36Sopenharmony_ci{
66262306a36Sopenharmony_ci	int ret;
66362306a36Sopenharmony_ci
66462306a36Sopenharmony_ci	if (lock_sk)
66562306a36Sopenharmony_ci		lock_sock(sk);
66662306a36Sopenharmony_ci	ret = sock_bindtoindex_locked(sk, ifindex);
66762306a36Sopenharmony_ci	if (lock_sk)
66862306a36Sopenharmony_ci		release_sock(sk);
66962306a36Sopenharmony_ci
67062306a36Sopenharmony_ci	return ret;
67162306a36Sopenharmony_ci}
67262306a36Sopenharmony_ciEXPORT_SYMBOL(sock_bindtoindex);
67362306a36Sopenharmony_ci
67462306a36Sopenharmony_cistatic int sock_setbindtodevice(struct sock *sk, sockptr_t optval, int optlen)
67562306a36Sopenharmony_ci{
67662306a36Sopenharmony_ci	int ret = -ENOPROTOOPT;
67762306a36Sopenharmony_ci#ifdef CONFIG_NETDEVICES
67862306a36Sopenharmony_ci	struct net *net = sock_net(sk);
67962306a36Sopenharmony_ci	char devname[IFNAMSIZ];
68062306a36Sopenharmony_ci	int index;
68162306a36Sopenharmony_ci
68262306a36Sopenharmony_ci	ret = -EINVAL;
68362306a36Sopenharmony_ci	if (optlen < 0)
68462306a36Sopenharmony_ci		goto out;
68562306a36Sopenharmony_ci
68662306a36Sopenharmony_ci	/* Bind this socket to a particular device like "eth0",
68762306a36Sopenharmony_ci	 * as specified in the passed interface name. If the
68862306a36Sopenharmony_ci	 * name is "" or the option length is zero the socket
68962306a36Sopenharmony_ci	 * is not bound.
69062306a36Sopenharmony_ci	 */
69162306a36Sopenharmony_ci	if (optlen > IFNAMSIZ - 1)
69262306a36Sopenharmony_ci		optlen = IFNAMSIZ - 1;
69362306a36Sopenharmony_ci	memset(devname, 0, sizeof(devname));
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_ci	ret = -EFAULT;
69662306a36Sopenharmony_ci	if (copy_from_sockptr(devname, optval, optlen))
69762306a36Sopenharmony_ci		goto out;
69862306a36Sopenharmony_ci
69962306a36Sopenharmony_ci	index = 0;
70062306a36Sopenharmony_ci	if (devname[0] != '\0') {
70162306a36Sopenharmony_ci		struct net_device *dev;
70262306a36Sopenharmony_ci
70362306a36Sopenharmony_ci		rcu_read_lock();
70462306a36Sopenharmony_ci		dev = dev_get_by_name_rcu(net, devname);
70562306a36Sopenharmony_ci		if (dev)
70662306a36Sopenharmony_ci			index = dev->ifindex;
70762306a36Sopenharmony_ci		rcu_read_unlock();
70862306a36Sopenharmony_ci		ret = -ENODEV;
70962306a36Sopenharmony_ci		if (!dev)
71062306a36Sopenharmony_ci			goto out;
71162306a36Sopenharmony_ci	}
71262306a36Sopenharmony_ci
71362306a36Sopenharmony_ci	sockopt_lock_sock(sk);
71462306a36Sopenharmony_ci	ret = sock_bindtoindex_locked(sk, index);
71562306a36Sopenharmony_ci	sockopt_release_sock(sk);
71662306a36Sopenharmony_ciout:
71762306a36Sopenharmony_ci#endif
71862306a36Sopenharmony_ci
71962306a36Sopenharmony_ci	return ret;
72062306a36Sopenharmony_ci}
72162306a36Sopenharmony_ci
72262306a36Sopenharmony_cistatic int sock_getbindtodevice(struct sock *sk, sockptr_t optval,
72362306a36Sopenharmony_ci				sockptr_t optlen, int len)
72462306a36Sopenharmony_ci{
72562306a36Sopenharmony_ci	int ret = -ENOPROTOOPT;
72662306a36Sopenharmony_ci#ifdef CONFIG_NETDEVICES
72762306a36Sopenharmony_ci	int bound_dev_if = READ_ONCE(sk->sk_bound_dev_if);
72862306a36Sopenharmony_ci	struct net *net = sock_net(sk);
72962306a36Sopenharmony_ci	char devname[IFNAMSIZ];
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci	if (bound_dev_if == 0) {
73262306a36Sopenharmony_ci		len = 0;
73362306a36Sopenharmony_ci		goto zero;
73462306a36Sopenharmony_ci	}
73562306a36Sopenharmony_ci
73662306a36Sopenharmony_ci	ret = -EINVAL;
73762306a36Sopenharmony_ci	if (len < IFNAMSIZ)
73862306a36Sopenharmony_ci		goto out;
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_ci	ret = netdev_get_name(net, devname, bound_dev_if);
74162306a36Sopenharmony_ci	if (ret)
74262306a36Sopenharmony_ci		goto out;
74362306a36Sopenharmony_ci
74462306a36Sopenharmony_ci	len = strlen(devname) + 1;
74562306a36Sopenharmony_ci
74662306a36Sopenharmony_ci	ret = -EFAULT;
74762306a36Sopenharmony_ci	if (copy_to_sockptr(optval, devname, len))
74862306a36Sopenharmony_ci		goto out;
74962306a36Sopenharmony_ci
75062306a36Sopenharmony_cizero:
75162306a36Sopenharmony_ci	ret = -EFAULT;
75262306a36Sopenharmony_ci	if (copy_to_sockptr(optlen, &len, sizeof(int)))
75362306a36Sopenharmony_ci		goto out;
75462306a36Sopenharmony_ci
75562306a36Sopenharmony_ci	ret = 0;
75662306a36Sopenharmony_ci
75762306a36Sopenharmony_ciout:
75862306a36Sopenharmony_ci#endif
75962306a36Sopenharmony_ci
76062306a36Sopenharmony_ci	return ret;
76162306a36Sopenharmony_ci}
76262306a36Sopenharmony_ci
76362306a36Sopenharmony_cibool sk_mc_loop(struct sock *sk)
76462306a36Sopenharmony_ci{
76562306a36Sopenharmony_ci	if (dev_recursion_level())
76662306a36Sopenharmony_ci		return false;
76762306a36Sopenharmony_ci	if (!sk)
76862306a36Sopenharmony_ci		return true;
76962306a36Sopenharmony_ci	/* IPV6_ADDRFORM can change sk->sk_family under us. */
77062306a36Sopenharmony_ci	switch (READ_ONCE(sk->sk_family)) {
77162306a36Sopenharmony_ci	case AF_INET:
77262306a36Sopenharmony_ci		return inet_test_bit(MC_LOOP, sk);
77362306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_IPV6)
77462306a36Sopenharmony_ci	case AF_INET6:
77562306a36Sopenharmony_ci		return inet6_sk(sk)->mc_loop;
77662306a36Sopenharmony_ci#endif
77762306a36Sopenharmony_ci	}
77862306a36Sopenharmony_ci	WARN_ON_ONCE(1);
77962306a36Sopenharmony_ci	return true;
78062306a36Sopenharmony_ci}
78162306a36Sopenharmony_ciEXPORT_SYMBOL(sk_mc_loop);
78262306a36Sopenharmony_ci
78362306a36Sopenharmony_civoid sock_set_reuseaddr(struct sock *sk)
78462306a36Sopenharmony_ci{
78562306a36Sopenharmony_ci	lock_sock(sk);
78662306a36Sopenharmony_ci	sk->sk_reuse = SK_CAN_REUSE;
78762306a36Sopenharmony_ci	release_sock(sk);
78862306a36Sopenharmony_ci}
78962306a36Sopenharmony_ciEXPORT_SYMBOL(sock_set_reuseaddr);
79062306a36Sopenharmony_ci
79162306a36Sopenharmony_civoid sock_set_reuseport(struct sock *sk)
79262306a36Sopenharmony_ci{
79362306a36Sopenharmony_ci	lock_sock(sk);
79462306a36Sopenharmony_ci	sk->sk_reuseport = true;
79562306a36Sopenharmony_ci	release_sock(sk);
79662306a36Sopenharmony_ci}
79762306a36Sopenharmony_ciEXPORT_SYMBOL(sock_set_reuseport);
79862306a36Sopenharmony_ci
79962306a36Sopenharmony_civoid sock_no_linger(struct sock *sk)
80062306a36Sopenharmony_ci{
80162306a36Sopenharmony_ci	lock_sock(sk);
80262306a36Sopenharmony_ci	WRITE_ONCE(sk->sk_lingertime, 0);
80362306a36Sopenharmony_ci	sock_set_flag(sk, SOCK_LINGER);
80462306a36Sopenharmony_ci	release_sock(sk);
80562306a36Sopenharmony_ci}
80662306a36Sopenharmony_ciEXPORT_SYMBOL(sock_no_linger);
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_civoid sock_set_priority(struct sock *sk, u32 priority)
80962306a36Sopenharmony_ci{
81062306a36Sopenharmony_ci	lock_sock(sk);
81162306a36Sopenharmony_ci	WRITE_ONCE(sk->sk_priority, priority);
81262306a36Sopenharmony_ci	release_sock(sk);
81362306a36Sopenharmony_ci}
81462306a36Sopenharmony_ciEXPORT_SYMBOL(sock_set_priority);
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_civoid sock_set_sndtimeo(struct sock *sk, s64 secs)
81762306a36Sopenharmony_ci{
81862306a36Sopenharmony_ci	lock_sock(sk);
81962306a36Sopenharmony_ci	if (secs && secs < MAX_SCHEDULE_TIMEOUT / HZ - 1)
82062306a36Sopenharmony_ci		WRITE_ONCE(sk->sk_sndtimeo, secs * HZ);
82162306a36Sopenharmony_ci	else
82262306a36Sopenharmony_ci		WRITE_ONCE(sk->sk_sndtimeo, MAX_SCHEDULE_TIMEOUT);
82362306a36Sopenharmony_ci	release_sock(sk);
82462306a36Sopenharmony_ci}
82562306a36Sopenharmony_ciEXPORT_SYMBOL(sock_set_sndtimeo);
82662306a36Sopenharmony_ci
82762306a36Sopenharmony_cistatic void __sock_set_timestamps(struct sock *sk, bool val, bool new, bool ns)
82862306a36Sopenharmony_ci{
82962306a36Sopenharmony_ci	if (val)  {
83062306a36Sopenharmony_ci		sock_valbool_flag(sk, SOCK_TSTAMP_NEW, new);
83162306a36Sopenharmony_ci		sock_valbool_flag(sk, SOCK_RCVTSTAMPNS, ns);
83262306a36Sopenharmony_ci		sock_set_flag(sk, SOCK_RCVTSTAMP);
83362306a36Sopenharmony_ci		sock_enable_timestamp(sk, SOCK_TIMESTAMP);
83462306a36Sopenharmony_ci	} else {
83562306a36Sopenharmony_ci		sock_reset_flag(sk, SOCK_RCVTSTAMP);
83662306a36Sopenharmony_ci		sock_reset_flag(sk, SOCK_RCVTSTAMPNS);
83762306a36Sopenharmony_ci	}
83862306a36Sopenharmony_ci}
83962306a36Sopenharmony_ci
84062306a36Sopenharmony_civoid sock_enable_timestamps(struct sock *sk)
84162306a36Sopenharmony_ci{
84262306a36Sopenharmony_ci	lock_sock(sk);
84362306a36Sopenharmony_ci	__sock_set_timestamps(sk, true, false, true);
84462306a36Sopenharmony_ci	release_sock(sk);
84562306a36Sopenharmony_ci}
84662306a36Sopenharmony_ciEXPORT_SYMBOL(sock_enable_timestamps);
84762306a36Sopenharmony_ci
84862306a36Sopenharmony_civoid sock_set_timestamp(struct sock *sk, int optname, bool valbool)
84962306a36Sopenharmony_ci{
85062306a36Sopenharmony_ci	switch (optname) {
85162306a36Sopenharmony_ci	case SO_TIMESTAMP_OLD:
85262306a36Sopenharmony_ci		__sock_set_timestamps(sk, valbool, false, false);
85362306a36Sopenharmony_ci		break;
85462306a36Sopenharmony_ci	case SO_TIMESTAMP_NEW:
85562306a36Sopenharmony_ci		__sock_set_timestamps(sk, valbool, true, false);
85662306a36Sopenharmony_ci		break;
85762306a36Sopenharmony_ci	case SO_TIMESTAMPNS_OLD:
85862306a36Sopenharmony_ci		__sock_set_timestamps(sk, valbool, false, true);
85962306a36Sopenharmony_ci		break;
86062306a36Sopenharmony_ci	case SO_TIMESTAMPNS_NEW:
86162306a36Sopenharmony_ci		__sock_set_timestamps(sk, valbool, true, true);
86262306a36Sopenharmony_ci		break;
86362306a36Sopenharmony_ci	}
86462306a36Sopenharmony_ci}
86562306a36Sopenharmony_ci
86662306a36Sopenharmony_cistatic int sock_timestamping_bind_phc(struct sock *sk, int phc_index)
86762306a36Sopenharmony_ci{
86862306a36Sopenharmony_ci	struct net *net = sock_net(sk);
86962306a36Sopenharmony_ci	struct net_device *dev = NULL;
87062306a36Sopenharmony_ci	bool match = false;
87162306a36Sopenharmony_ci	int *vclock_index;
87262306a36Sopenharmony_ci	int i, num;
87362306a36Sopenharmony_ci
87462306a36Sopenharmony_ci	if (sk->sk_bound_dev_if)
87562306a36Sopenharmony_ci		dev = dev_get_by_index(net, sk->sk_bound_dev_if);
87662306a36Sopenharmony_ci
87762306a36Sopenharmony_ci	if (!dev) {
87862306a36Sopenharmony_ci		pr_err("%s: sock not bind to device\n", __func__);
87962306a36Sopenharmony_ci		return -EOPNOTSUPP;
88062306a36Sopenharmony_ci	}
88162306a36Sopenharmony_ci
88262306a36Sopenharmony_ci	num = ethtool_get_phc_vclocks(dev, &vclock_index);
88362306a36Sopenharmony_ci	dev_put(dev);
88462306a36Sopenharmony_ci
88562306a36Sopenharmony_ci	for (i = 0; i < num; i++) {
88662306a36Sopenharmony_ci		if (*(vclock_index + i) == phc_index) {
88762306a36Sopenharmony_ci			match = true;
88862306a36Sopenharmony_ci			break;
88962306a36Sopenharmony_ci		}
89062306a36Sopenharmony_ci	}
89162306a36Sopenharmony_ci
89262306a36Sopenharmony_ci	if (num > 0)
89362306a36Sopenharmony_ci		kfree(vclock_index);
89462306a36Sopenharmony_ci
89562306a36Sopenharmony_ci	if (!match)
89662306a36Sopenharmony_ci		return -EINVAL;
89762306a36Sopenharmony_ci
89862306a36Sopenharmony_ci	WRITE_ONCE(sk->sk_bind_phc, phc_index);
89962306a36Sopenharmony_ci
90062306a36Sopenharmony_ci	return 0;
90162306a36Sopenharmony_ci}
90262306a36Sopenharmony_ci
90362306a36Sopenharmony_ciint sock_set_timestamping(struct sock *sk, int optname,
90462306a36Sopenharmony_ci			  struct so_timestamping timestamping)
90562306a36Sopenharmony_ci{
90662306a36Sopenharmony_ci	int val = timestamping.flags;
90762306a36Sopenharmony_ci	int ret;
90862306a36Sopenharmony_ci
90962306a36Sopenharmony_ci	if (val & ~SOF_TIMESTAMPING_MASK)
91062306a36Sopenharmony_ci		return -EINVAL;
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_ci	if (val & SOF_TIMESTAMPING_OPT_ID_TCP &&
91362306a36Sopenharmony_ci	    !(val & SOF_TIMESTAMPING_OPT_ID))
91462306a36Sopenharmony_ci		return -EINVAL;
91562306a36Sopenharmony_ci
91662306a36Sopenharmony_ci	if (val & SOF_TIMESTAMPING_OPT_ID &&
91762306a36Sopenharmony_ci	    !(sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID)) {
91862306a36Sopenharmony_ci		if (sk_is_tcp(sk)) {
91962306a36Sopenharmony_ci			if ((1 << sk->sk_state) &
92062306a36Sopenharmony_ci			    (TCPF_CLOSE | TCPF_LISTEN))
92162306a36Sopenharmony_ci				return -EINVAL;
92262306a36Sopenharmony_ci			if (val & SOF_TIMESTAMPING_OPT_ID_TCP)
92362306a36Sopenharmony_ci				atomic_set(&sk->sk_tskey, tcp_sk(sk)->write_seq);
92462306a36Sopenharmony_ci			else
92562306a36Sopenharmony_ci				atomic_set(&sk->sk_tskey, tcp_sk(sk)->snd_una);
92662306a36Sopenharmony_ci		} else {
92762306a36Sopenharmony_ci			atomic_set(&sk->sk_tskey, 0);
92862306a36Sopenharmony_ci		}
92962306a36Sopenharmony_ci	}
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_ci	if (val & SOF_TIMESTAMPING_OPT_STATS &&
93262306a36Sopenharmony_ci	    !(val & SOF_TIMESTAMPING_OPT_TSONLY))
93362306a36Sopenharmony_ci		return -EINVAL;
93462306a36Sopenharmony_ci
93562306a36Sopenharmony_ci	if (val & SOF_TIMESTAMPING_BIND_PHC) {
93662306a36Sopenharmony_ci		ret = sock_timestamping_bind_phc(sk, timestamping.bind_phc);
93762306a36Sopenharmony_ci		if (ret)
93862306a36Sopenharmony_ci			return ret;
93962306a36Sopenharmony_ci	}
94062306a36Sopenharmony_ci
94162306a36Sopenharmony_ci	WRITE_ONCE(sk->sk_tsflags, val);
94262306a36Sopenharmony_ci	sock_valbool_flag(sk, SOCK_TSTAMP_NEW, optname == SO_TIMESTAMPING_NEW);
94362306a36Sopenharmony_ci
94462306a36Sopenharmony_ci	if (val & SOF_TIMESTAMPING_RX_SOFTWARE)
94562306a36Sopenharmony_ci		sock_enable_timestamp(sk,
94662306a36Sopenharmony_ci				      SOCK_TIMESTAMPING_RX_SOFTWARE);
94762306a36Sopenharmony_ci	else
94862306a36Sopenharmony_ci		sock_disable_timestamp(sk,
94962306a36Sopenharmony_ci				       (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE));
95062306a36Sopenharmony_ci	return 0;
95162306a36Sopenharmony_ci}
95262306a36Sopenharmony_ci
95362306a36Sopenharmony_civoid sock_set_keepalive(struct sock *sk)
95462306a36Sopenharmony_ci{
95562306a36Sopenharmony_ci	lock_sock(sk);
95662306a36Sopenharmony_ci	if (sk->sk_prot->keepalive)
95762306a36Sopenharmony_ci		sk->sk_prot->keepalive(sk, true);
95862306a36Sopenharmony_ci	sock_valbool_flag(sk, SOCK_KEEPOPEN, true);
95962306a36Sopenharmony_ci	release_sock(sk);
96062306a36Sopenharmony_ci}
96162306a36Sopenharmony_ciEXPORT_SYMBOL(sock_set_keepalive);
96262306a36Sopenharmony_ci
96362306a36Sopenharmony_cistatic void __sock_set_rcvbuf(struct sock *sk, int val)
96462306a36Sopenharmony_ci{
96562306a36Sopenharmony_ci	/* Ensure val * 2 fits into an int, to prevent max_t() from treating it
96662306a36Sopenharmony_ci	 * as a negative value.
96762306a36Sopenharmony_ci	 */
96862306a36Sopenharmony_ci	val = min_t(int, val, INT_MAX / 2);
96962306a36Sopenharmony_ci	sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
97062306a36Sopenharmony_ci
97162306a36Sopenharmony_ci	/* We double it on the way in to account for "struct sk_buff" etc.
97262306a36Sopenharmony_ci	 * overhead.   Applications assume that the SO_RCVBUF setting they make
97362306a36Sopenharmony_ci	 * will allow that much actual data to be received on that socket.
97462306a36Sopenharmony_ci	 *
97562306a36Sopenharmony_ci	 * Applications are unaware that "struct sk_buff" and other overheads
97662306a36Sopenharmony_ci	 * allocate from the receive buffer during socket buffer allocation.
97762306a36Sopenharmony_ci	 *
97862306a36Sopenharmony_ci	 * And after considering the possible alternatives, returning the value
97962306a36Sopenharmony_ci	 * we actually used in getsockopt is the most desirable behavior.
98062306a36Sopenharmony_ci	 */
98162306a36Sopenharmony_ci	WRITE_ONCE(sk->sk_rcvbuf, max_t(int, val * 2, SOCK_MIN_RCVBUF));
98262306a36Sopenharmony_ci}
98362306a36Sopenharmony_ci
98462306a36Sopenharmony_civoid sock_set_rcvbuf(struct sock *sk, int val)
98562306a36Sopenharmony_ci{
98662306a36Sopenharmony_ci	lock_sock(sk);
98762306a36Sopenharmony_ci	__sock_set_rcvbuf(sk, val);
98862306a36Sopenharmony_ci	release_sock(sk);
98962306a36Sopenharmony_ci}
99062306a36Sopenharmony_ciEXPORT_SYMBOL(sock_set_rcvbuf);
99162306a36Sopenharmony_ci
99262306a36Sopenharmony_cistatic void __sock_set_mark(struct sock *sk, u32 val)
99362306a36Sopenharmony_ci{
99462306a36Sopenharmony_ci	if (val != sk->sk_mark) {
99562306a36Sopenharmony_ci		WRITE_ONCE(sk->sk_mark, val);
99662306a36Sopenharmony_ci		sk_dst_reset(sk);
99762306a36Sopenharmony_ci	}
99862306a36Sopenharmony_ci}
99962306a36Sopenharmony_ci
100062306a36Sopenharmony_civoid sock_set_mark(struct sock *sk, u32 val)
100162306a36Sopenharmony_ci{
100262306a36Sopenharmony_ci	lock_sock(sk);
100362306a36Sopenharmony_ci	__sock_set_mark(sk, val);
100462306a36Sopenharmony_ci	release_sock(sk);
100562306a36Sopenharmony_ci}
100662306a36Sopenharmony_ciEXPORT_SYMBOL(sock_set_mark);
100762306a36Sopenharmony_ci
100862306a36Sopenharmony_cistatic void sock_release_reserved_memory(struct sock *sk, int bytes)
100962306a36Sopenharmony_ci{
101062306a36Sopenharmony_ci	/* Round down bytes to multiple of pages */
101162306a36Sopenharmony_ci	bytes = round_down(bytes, PAGE_SIZE);
101262306a36Sopenharmony_ci
101362306a36Sopenharmony_ci	WARN_ON(bytes > sk->sk_reserved_mem);
101462306a36Sopenharmony_ci	WRITE_ONCE(sk->sk_reserved_mem, sk->sk_reserved_mem - bytes);
101562306a36Sopenharmony_ci	sk_mem_reclaim(sk);
101662306a36Sopenharmony_ci}
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_cistatic int sock_reserve_memory(struct sock *sk, int bytes)
101962306a36Sopenharmony_ci{
102062306a36Sopenharmony_ci	long allocated;
102162306a36Sopenharmony_ci	bool charged;
102262306a36Sopenharmony_ci	int pages;
102362306a36Sopenharmony_ci
102462306a36Sopenharmony_ci	if (!mem_cgroup_sockets_enabled || !sk->sk_memcg || !sk_has_account(sk))
102562306a36Sopenharmony_ci		return -EOPNOTSUPP;
102662306a36Sopenharmony_ci
102762306a36Sopenharmony_ci	if (!bytes)
102862306a36Sopenharmony_ci		return 0;
102962306a36Sopenharmony_ci
103062306a36Sopenharmony_ci	pages = sk_mem_pages(bytes);
103162306a36Sopenharmony_ci
103262306a36Sopenharmony_ci	/* pre-charge to memcg */
103362306a36Sopenharmony_ci	charged = mem_cgroup_charge_skmem(sk->sk_memcg, pages,
103462306a36Sopenharmony_ci					  GFP_KERNEL | __GFP_RETRY_MAYFAIL);
103562306a36Sopenharmony_ci	if (!charged)
103662306a36Sopenharmony_ci		return -ENOMEM;
103762306a36Sopenharmony_ci
103862306a36Sopenharmony_ci	/* pre-charge to forward_alloc */
103962306a36Sopenharmony_ci	sk_memory_allocated_add(sk, pages);
104062306a36Sopenharmony_ci	allocated = sk_memory_allocated(sk);
104162306a36Sopenharmony_ci	/* If the system goes into memory pressure with this
104262306a36Sopenharmony_ci	 * precharge, give up and return error.
104362306a36Sopenharmony_ci	 */
104462306a36Sopenharmony_ci	if (allocated > sk_prot_mem_limits(sk, 1)) {
104562306a36Sopenharmony_ci		sk_memory_allocated_sub(sk, pages);
104662306a36Sopenharmony_ci		mem_cgroup_uncharge_skmem(sk->sk_memcg, pages);
104762306a36Sopenharmony_ci		return -ENOMEM;
104862306a36Sopenharmony_ci	}
104962306a36Sopenharmony_ci	sk_forward_alloc_add(sk, pages << PAGE_SHIFT);
105062306a36Sopenharmony_ci
105162306a36Sopenharmony_ci	WRITE_ONCE(sk->sk_reserved_mem,
105262306a36Sopenharmony_ci		   sk->sk_reserved_mem + (pages << PAGE_SHIFT));
105362306a36Sopenharmony_ci
105462306a36Sopenharmony_ci	return 0;
105562306a36Sopenharmony_ci}
105662306a36Sopenharmony_ci
105762306a36Sopenharmony_civoid sockopt_lock_sock(struct sock *sk)
105862306a36Sopenharmony_ci{
105962306a36Sopenharmony_ci	/* When current->bpf_ctx is set, the setsockopt is called from
106062306a36Sopenharmony_ci	 * a bpf prog.  bpf has ensured the sk lock has been
106162306a36Sopenharmony_ci	 * acquired before calling setsockopt().
106262306a36Sopenharmony_ci	 */
106362306a36Sopenharmony_ci	if (has_current_bpf_ctx())
106462306a36Sopenharmony_ci		return;
106562306a36Sopenharmony_ci
106662306a36Sopenharmony_ci	lock_sock(sk);
106762306a36Sopenharmony_ci}
106862306a36Sopenharmony_ciEXPORT_SYMBOL(sockopt_lock_sock);
106962306a36Sopenharmony_ci
107062306a36Sopenharmony_civoid sockopt_release_sock(struct sock *sk)
107162306a36Sopenharmony_ci{
107262306a36Sopenharmony_ci	if (has_current_bpf_ctx())
107362306a36Sopenharmony_ci		return;
107462306a36Sopenharmony_ci
107562306a36Sopenharmony_ci	release_sock(sk);
107662306a36Sopenharmony_ci}
107762306a36Sopenharmony_ciEXPORT_SYMBOL(sockopt_release_sock);
107862306a36Sopenharmony_ci
107962306a36Sopenharmony_cibool sockopt_ns_capable(struct user_namespace *ns, int cap)
108062306a36Sopenharmony_ci{
108162306a36Sopenharmony_ci	return has_current_bpf_ctx() || ns_capable(ns, cap);
108262306a36Sopenharmony_ci}
108362306a36Sopenharmony_ciEXPORT_SYMBOL(sockopt_ns_capable);
108462306a36Sopenharmony_ci
108562306a36Sopenharmony_cibool sockopt_capable(int cap)
108662306a36Sopenharmony_ci{
108762306a36Sopenharmony_ci	return has_current_bpf_ctx() || capable(cap);
108862306a36Sopenharmony_ci}
108962306a36Sopenharmony_ciEXPORT_SYMBOL(sockopt_capable);
109062306a36Sopenharmony_ci
109162306a36Sopenharmony_ci/*
109262306a36Sopenharmony_ci *	This is meant for all protocols to use and covers goings on
109362306a36Sopenharmony_ci *	at the socket level. Everything here is generic.
109462306a36Sopenharmony_ci */
109562306a36Sopenharmony_ci
109662306a36Sopenharmony_ciint sk_setsockopt(struct sock *sk, int level, int optname,
109762306a36Sopenharmony_ci		  sockptr_t optval, unsigned int optlen)
109862306a36Sopenharmony_ci{
109962306a36Sopenharmony_ci	struct so_timestamping timestamping;
110062306a36Sopenharmony_ci	struct socket *sock = sk->sk_socket;
110162306a36Sopenharmony_ci	struct sock_txtime sk_txtime;
110262306a36Sopenharmony_ci	int val;
110362306a36Sopenharmony_ci	int valbool;
110462306a36Sopenharmony_ci	struct linger ling;
110562306a36Sopenharmony_ci	int ret = 0;
110662306a36Sopenharmony_ci
110762306a36Sopenharmony_ci	/*
110862306a36Sopenharmony_ci	 *	Options without arguments
110962306a36Sopenharmony_ci	 */
111062306a36Sopenharmony_ci
111162306a36Sopenharmony_ci	if (optname == SO_BINDTODEVICE)
111262306a36Sopenharmony_ci		return sock_setbindtodevice(sk, optval, optlen);
111362306a36Sopenharmony_ci
111462306a36Sopenharmony_ci	if (optlen < sizeof(int))
111562306a36Sopenharmony_ci		return -EINVAL;
111662306a36Sopenharmony_ci
111762306a36Sopenharmony_ci	if (copy_from_sockptr(&val, optval, sizeof(val)))
111862306a36Sopenharmony_ci		return -EFAULT;
111962306a36Sopenharmony_ci
112062306a36Sopenharmony_ci	valbool = val ? 1 : 0;
112162306a36Sopenharmony_ci
112262306a36Sopenharmony_ci	sockopt_lock_sock(sk);
112362306a36Sopenharmony_ci
112462306a36Sopenharmony_ci	switch (optname) {
112562306a36Sopenharmony_ci	case SO_DEBUG:
112662306a36Sopenharmony_ci		if (val && !sockopt_capable(CAP_NET_ADMIN))
112762306a36Sopenharmony_ci			ret = -EACCES;
112862306a36Sopenharmony_ci		else
112962306a36Sopenharmony_ci			sock_valbool_flag(sk, SOCK_DBG, valbool);
113062306a36Sopenharmony_ci		break;
113162306a36Sopenharmony_ci	case SO_REUSEADDR:
113262306a36Sopenharmony_ci		sk->sk_reuse = (valbool ? SK_CAN_REUSE : SK_NO_REUSE);
113362306a36Sopenharmony_ci		break;
113462306a36Sopenharmony_ci	case SO_REUSEPORT:
113562306a36Sopenharmony_ci		sk->sk_reuseport = valbool;
113662306a36Sopenharmony_ci		break;
113762306a36Sopenharmony_ci	case SO_TYPE:
113862306a36Sopenharmony_ci	case SO_PROTOCOL:
113962306a36Sopenharmony_ci	case SO_DOMAIN:
114062306a36Sopenharmony_ci	case SO_ERROR:
114162306a36Sopenharmony_ci		ret = -ENOPROTOOPT;
114262306a36Sopenharmony_ci		break;
114362306a36Sopenharmony_ci	case SO_DONTROUTE:
114462306a36Sopenharmony_ci		sock_valbool_flag(sk, SOCK_LOCALROUTE, valbool);
114562306a36Sopenharmony_ci		sk_dst_reset(sk);
114662306a36Sopenharmony_ci		break;
114762306a36Sopenharmony_ci	case SO_BROADCAST:
114862306a36Sopenharmony_ci		sock_valbool_flag(sk, SOCK_BROADCAST, valbool);
114962306a36Sopenharmony_ci		break;
115062306a36Sopenharmony_ci	case SO_SNDBUF:
115162306a36Sopenharmony_ci		/* Don't error on this BSD doesn't and if you think
115262306a36Sopenharmony_ci		 * about it this is right. Otherwise apps have to
115362306a36Sopenharmony_ci		 * play 'guess the biggest size' games. RCVBUF/SNDBUF
115462306a36Sopenharmony_ci		 * are treated in BSD as hints
115562306a36Sopenharmony_ci		 */
115662306a36Sopenharmony_ci		val = min_t(u32, val, READ_ONCE(sysctl_wmem_max));
115762306a36Sopenharmony_ciset_sndbuf:
115862306a36Sopenharmony_ci		/* Ensure val * 2 fits into an int, to prevent max_t()
115962306a36Sopenharmony_ci		 * from treating it as a negative value.
116062306a36Sopenharmony_ci		 */
116162306a36Sopenharmony_ci		val = min_t(int, val, INT_MAX / 2);
116262306a36Sopenharmony_ci		sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
116362306a36Sopenharmony_ci		WRITE_ONCE(sk->sk_sndbuf,
116462306a36Sopenharmony_ci			   max_t(int, val * 2, SOCK_MIN_SNDBUF));
116562306a36Sopenharmony_ci		/* Wake up sending tasks if we upped the value. */
116662306a36Sopenharmony_ci		sk->sk_write_space(sk);
116762306a36Sopenharmony_ci		break;
116862306a36Sopenharmony_ci
116962306a36Sopenharmony_ci	case SO_SNDBUFFORCE:
117062306a36Sopenharmony_ci		if (!sockopt_capable(CAP_NET_ADMIN)) {
117162306a36Sopenharmony_ci			ret = -EPERM;
117262306a36Sopenharmony_ci			break;
117362306a36Sopenharmony_ci		}
117462306a36Sopenharmony_ci
117562306a36Sopenharmony_ci		/* No negative values (to prevent underflow, as val will be
117662306a36Sopenharmony_ci		 * multiplied by 2).
117762306a36Sopenharmony_ci		 */
117862306a36Sopenharmony_ci		if (val < 0)
117962306a36Sopenharmony_ci			val = 0;
118062306a36Sopenharmony_ci		goto set_sndbuf;
118162306a36Sopenharmony_ci
118262306a36Sopenharmony_ci	case SO_RCVBUF:
118362306a36Sopenharmony_ci		/* Don't error on this BSD doesn't and if you think
118462306a36Sopenharmony_ci		 * about it this is right. Otherwise apps have to
118562306a36Sopenharmony_ci		 * play 'guess the biggest size' games. RCVBUF/SNDBUF
118662306a36Sopenharmony_ci		 * are treated in BSD as hints
118762306a36Sopenharmony_ci		 */
118862306a36Sopenharmony_ci		__sock_set_rcvbuf(sk, min_t(u32, val, READ_ONCE(sysctl_rmem_max)));
118962306a36Sopenharmony_ci		break;
119062306a36Sopenharmony_ci
119162306a36Sopenharmony_ci	case SO_RCVBUFFORCE:
119262306a36Sopenharmony_ci		if (!sockopt_capable(CAP_NET_ADMIN)) {
119362306a36Sopenharmony_ci			ret = -EPERM;
119462306a36Sopenharmony_ci			break;
119562306a36Sopenharmony_ci		}
119662306a36Sopenharmony_ci
119762306a36Sopenharmony_ci		/* No negative values (to prevent underflow, as val will be
119862306a36Sopenharmony_ci		 * multiplied by 2).
119962306a36Sopenharmony_ci		 */
120062306a36Sopenharmony_ci		__sock_set_rcvbuf(sk, max(val, 0));
120162306a36Sopenharmony_ci		break;
120262306a36Sopenharmony_ci
120362306a36Sopenharmony_ci	case SO_KEEPALIVE:
120462306a36Sopenharmony_ci		if (sk->sk_prot->keepalive)
120562306a36Sopenharmony_ci			sk->sk_prot->keepalive(sk, valbool);
120662306a36Sopenharmony_ci		sock_valbool_flag(sk, SOCK_KEEPOPEN, valbool);
120762306a36Sopenharmony_ci		break;
120862306a36Sopenharmony_ci
120962306a36Sopenharmony_ci	case SO_OOBINLINE:
121062306a36Sopenharmony_ci		sock_valbool_flag(sk, SOCK_URGINLINE, valbool);
121162306a36Sopenharmony_ci		break;
121262306a36Sopenharmony_ci
121362306a36Sopenharmony_ci	case SO_NO_CHECK:
121462306a36Sopenharmony_ci		sk->sk_no_check_tx = valbool;
121562306a36Sopenharmony_ci		break;
121662306a36Sopenharmony_ci
121762306a36Sopenharmony_ci	case SO_PRIORITY:
121862306a36Sopenharmony_ci		if ((val >= 0 && val <= 6) ||
121962306a36Sopenharmony_ci		    sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_RAW) ||
122062306a36Sopenharmony_ci		    sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
122162306a36Sopenharmony_ci			WRITE_ONCE(sk->sk_priority, val);
122262306a36Sopenharmony_ci		else
122362306a36Sopenharmony_ci			ret = -EPERM;
122462306a36Sopenharmony_ci		break;
122562306a36Sopenharmony_ci
122662306a36Sopenharmony_ci	case SO_LINGER:
122762306a36Sopenharmony_ci		if (optlen < sizeof(ling)) {
122862306a36Sopenharmony_ci			ret = -EINVAL;	/* 1003.1g */
122962306a36Sopenharmony_ci			break;
123062306a36Sopenharmony_ci		}
123162306a36Sopenharmony_ci		if (copy_from_sockptr(&ling, optval, sizeof(ling))) {
123262306a36Sopenharmony_ci			ret = -EFAULT;
123362306a36Sopenharmony_ci			break;
123462306a36Sopenharmony_ci		}
123562306a36Sopenharmony_ci		if (!ling.l_onoff) {
123662306a36Sopenharmony_ci			sock_reset_flag(sk, SOCK_LINGER);
123762306a36Sopenharmony_ci		} else {
123862306a36Sopenharmony_ci			unsigned long t_sec = ling.l_linger;
123962306a36Sopenharmony_ci
124062306a36Sopenharmony_ci			if (t_sec >= MAX_SCHEDULE_TIMEOUT / HZ)
124162306a36Sopenharmony_ci				WRITE_ONCE(sk->sk_lingertime, MAX_SCHEDULE_TIMEOUT);
124262306a36Sopenharmony_ci			else
124362306a36Sopenharmony_ci				WRITE_ONCE(sk->sk_lingertime, t_sec * HZ);
124462306a36Sopenharmony_ci			sock_set_flag(sk, SOCK_LINGER);
124562306a36Sopenharmony_ci		}
124662306a36Sopenharmony_ci		break;
124762306a36Sopenharmony_ci
124862306a36Sopenharmony_ci	case SO_BSDCOMPAT:
124962306a36Sopenharmony_ci		break;
125062306a36Sopenharmony_ci
125162306a36Sopenharmony_ci	case SO_PASSCRED:
125262306a36Sopenharmony_ci		assign_bit(SOCK_PASSCRED, &sock->flags, valbool);
125362306a36Sopenharmony_ci		break;
125462306a36Sopenharmony_ci
125562306a36Sopenharmony_ci	case SO_PASSPIDFD:
125662306a36Sopenharmony_ci		assign_bit(SOCK_PASSPIDFD, &sock->flags, valbool);
125762306a36Sopenharmony_ci		break;
125862306a36Sopenharmony_ci
125962306a36Sopenharmony_ci	case SO_TIMESTAMP_OLD:
126062306a36Sopenharmony_ci	case SO_TIMESTAMP_NEW:
126162306a36Sopenharmony_ci	case SO_TIMESTAMPNS_OLD:
126262306a36Sopenharmony_ci	case SO_TIMESTAMPNS_NEW:
126362306a36Sopenharmony_ci		sock_set_timestamp(sk, optname, valbool);
126462306a36Sopenharmony_ci		break;
126562306a36Sopenharmony_ci
126662306a36Sopenharmony_ci	case SO_TIMESTAMPING_NEW:
126762306a36Sopenharmony_ci	case SO_TIMESTAMPING_OLD:
126862306a36Sopenharmony_ci		if (optlen == sizeof(timestamping)) {
126962306a36Sopenharmony_ci			if (copy_from_sockptr(&timestamping, optval,
127062306a36Sopenharmony_ci					      sizeof(timestamping))) {
127162306a36Sopenharmony_ci				ret = -EFAULT;
127262306a36Sopenharmony_ci				break;
127362306a36Sopenharmony_ci			}
127462306a36Sopenharmony_ci		} else {
127562306a36Sopenharmony_ci			memset(&timestamping, 0, sizeof(timestamping));
127662306a36Sopenharmony_ci			timestamping.flags = val;
127762306a36Sopenharmony_ci		}
127862306a36Sopenharmony_ci		ret = sock_set_timestamping(sk, optname, timestamping);
127962306a36Sopenharmony_ci		break;
128062306a36Sopenharmony_ci
128162306a36Sopenharmony_ci	case SO_RCVLOWAT:
128262306a36Sopenharmony_ci		{
128362306a36Sopenharmony_ci		int (*set_rcvlowat)(struct sock *sk, int val) = NULL;
128462306a36Sopenharmony_ci
128562306a36Sopenharmony_ci		if (val < 0)
128662306a36Sopenharmony_ci			val = INT_MAX;
128762306a36Sopenharmony_ci		if (sock)
128862306a36Sopenharmony_ci			set_rcvlowat = READ_ONCE(sock->ops)->set_rcvlowat;
128962306a36Sopenharmony_ci		if (set_rcvlowat)
129062306a36Sopenharmony_ci			ret = set_rcvlowat(sk, val);
129162306a36Sopenharmony_ci		else
129262306a36Sopenharmony_ci			WRITE_ONCE(sk->sk_rcvlowat, val ? : 1);
129362306a36Sopenharmony_ci		break;
129462306a36Sopenharmony_ci		}
129562306a36Sopenharmony_ci	case SO_RCVTIMEO_OLD:
129662306a36Sopenharmony_ci	case SO_RCVTIMEO_NEW:
129762306a36Sopenharmony_ci		ret = sock_set_timeout(&sk->sk_rcvtimeo, optval,
129862306a36Sopenharmony_ci				       optlen, optname == SO_RCVTIMEO_OLD);
129962306a36Sopenharmony_ci		break;
130062306a36Sopenharmony_ci
130162306a36Sopenharmony_ci	case SO_SNDTIMEO_OLD:
130262306a36Sopenharmony_ci	case SO_SNDTIMEO_NEW:
130362306a36Sopenharmony_ci		ret = sock_set_timeout(&sk->sk_sndtimeo, optval,
130462306a36Sopenharmony_ci				       optlen, optname == SO_SNDTIMEO_OLD);
130562306a36Sopenharmony_ci		break;
130662306a36Sopenharmony_ci
130762306a36Sopenharmony_ci	case SO_ATTACH_FILTER: {
130862306a36Sopenharmony_ci		struct sock_fprog fprog;
130962306a36Sopenharmony_ci
131062306a36Sopenharmony_ci		ret = copy_bpf_fprog_from_user(&fprog, optval, optlen);
131162306a36Sopenharmony_ci		if (!ret)
131262306a36Sopenharmony_ci			ret = sk_attach_filter(&fprog, sk);
131362306a36Sopenharmony_ci		break;
131462306a36Sopenharmony_ci	}
131562306a36Sopenharmony_ci	case SO_ATTACH_BPF:
131662306a36Sopenharmony_ci		ret = -EINVAL;
131762306a36Sopenharmony_ci		if (optlen == sizeof(u32)) {
131862306a36Sopenharmony_ci			u32 ufd;
131962306a36Sopenharmony_ci
132062306a36Sopenharmony_ci			ret = -EFAULT;
132162306a36Sopenharmony_ci			if (copy_from_sockptr(&ufd, optval, sizeof(ufd)))
132262306a36Sopenharmony_ci				break;
132362306a36Sopenharmony_ci
132462306a36Sopenharmony_ci			ret = sk_attach_bpf(ufd, sk);
132562306a36Sopenharmony_ci		}
132662306a36Sopenharmony_ci		break;
132762306a36Sopenharmony_ci
132862306a36Sopenharmony_ci	case SO_ATTACH_REUSEPORT_CBPF: {
132962306a36Sopenharmony_ci		struct sock_fprog fprog;
133062306a36Sopenharmony_ci
133162306a36Sopenharmony_ci		ret = copy_bpf_fprog_from_user(&fprog, optval, optlen);
133262306a36Sopenharmony_ci		if (!ret)
133362306a36Sopenharmony_ci			ret = sk_reuseport_attach_filter(&fprog, sk);
133462306a36Sopenharmony_ci		break;
133562306a36Sopenharmony_ci	}
133662306a36Sopenharmony_ci	case SO_ATTACH_REUSEPORT_EBPF:
133762306a36Sopenharmony_ci		ret = -EINVAL;
133862306a36Sopenharmony_ci		if (optlen == sizeof(u32)) {
133962306a36Sopenharmony_ci			u32 ufd;
134062306a36Sopenharmony_ci
134162306a36Sopenharmony_ci			ret = -EFAULT;
134262306a36Sopenharmony_ci			if (copy_from_sockptr(&ufd, optval, sizeof(ufd)))
134362306a36Sopenharmony_ci				break;
134462306a36Sopenharmony_ci
134562306a36Sopenharmony_ci			ret = sk_reuseport_attach_bpf(ufd, sk);
134662306a36Sopenharmony_ci		}
134762306a36Sopenharmony_ci		break;
134862306a36Sopenharmony_ci
134962306a36Sopenharmony_ci	case SO_DETACH_REUSEPORT_BPF:
135062306a36Sopenharmony_ci		ret = reuseport_detach_prog(sk);
135162306a36Sopenharmony_ci		break;
135262306a36Sopenharmony_ci
135362306a36Sopenharmony_ci	case SO_DETACH_FILTER:
135462306a36Sopenharmony_ci		ret = sk_detach_filter(sk);
135562306a36Sopenharmony_ci		break;
135662306a36Sopenharmony_ci
135762306a36Sopenharmony_ci	case SO_LOCK_FILTER:
135862306a36Sopenharmony_ci		if (sock_flag(sk, SOCK_FILTER_LOCKED) && !valbool)
135962306a36Sopenharmony_ci			ret = -EPERM;
136062306a36Sopenharmony_ci		else
136162306a36Sopenharmony_ci			sock_valbool_flag(sk, SOCK_FILTER_LOCKED, valbool);
136262306a36Sopenharmony_ci		break;
136362306a36Sopenharmony_ci
136462306a36Sopenharmony_ci	case SO_PASSSEC:
136562306a36Sopenharmony_ci		assign_bit(SOCK_PASSSEC, &sock->flags, valbool);
136662306a36Sopenharmony_ci		break;
136762306a36Sopenharmony_ci	case SO_MARK:
136862306a36Sopenharmony_ci		if (!sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_RAW) &&
136962306a36Sopenharmony_ci		    !sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) {
137062306a36Sopenharmony_ci			ret = -EPERM;
137162306a36Sopenharmony_ci			break;
137262306a36Sopenharmony_ci		}
137362306a36Sopenharmony_ci
137462306a36Sopenharmony_ci		__sock_set_mark(sk, val);
137562306a36Sopenharmony_ci		break;
137662306a36Sopenharmony_ci	case SO_RCVMARK:
137762306a36Sopenharmony_ci		sock_valbool_flag(sk, SOCK_RCVMARK, valbool);
137862306a36Sopenharmony_ci		break;
137962306a36Sopenharmony_ci
138062306a36Sopenharmony_ci	case SO_RXQ_OVFL:
138162306a36Sopenharmony_ci		sock_valbool_flag(sk, SOCK_RXQ_OVFL, valbool);
138262306a36Sopenharmony_ci		break;
138362306a36Sopenharmony_ci
138462306a36Sopenharmony_ci	case SO_WIFI_STATUS:
138562306a36Sopenharmony_ci		sock_valbool_flag(sk, SOCK_WIFI_STATUS, valbool);
138662306a36Sopenharmony_ci		break;
138762306a36Sopenharmony_ci
138862306a36Sopenharmony_ci	case SO_PEEK_OFF:
138962306a36Sopenharmony_ci		{
139062306a36Sopenharmony_ci		int (*set_peek_off)(struct sock *sk, int val);
139162306a36Sopenharmony_ci
139262306a36Sopenharmony_ci		set_peek_off = READ_ONCE(sock->ops)->set_peek_off;
139362306a36Sopenharmony_ci		if (set_peek_off)
139462306a36Sopenharmony_ci			ret = set_peek_off(sk, val);
139562306a36Sopenharmony_ci		else
139662306a36Sopenharmony_ci			ret = -EOPNOTSUPP;
139762306a36Sopenharmony_ci		break;
139862306a36Sopenharmony_ci		}
139962306a36Sopenharmony_ci
140062306a36Sopenharmony_ci	case SO_NOFCS:
140162306a36Sopenharmony_ci		sock_valbool_flag(sk, SOCK_NOFCS, valbool);
140262306a36Sopenharmony_ci		break;
140362306a36Sopenharmony_ci
140462306a36Sopenharmony_ci	case SO_SELECT_ERR_QUEUE:
140562306a36Sopenharmony_ci		sock_valbool_flag(sk, SOCK_SELECT_ERR_QUEUE, valbool);
140662306a36Sopenharmony_ci		break;
140762306a36Sopenharmony_ci
140862306a36Sopenharmony_ci#ifdef CONFIG_NET_RX_BUSY_POLL
140962306a36Sopenharmony_ci	case SO_BUSY_POLL:
141062306a36Sopenharmony_ci		if (val < 0)
141162306a36Sopenharmony_ci			ret = -EINVAL;
141262306a36Sopenharmony_ci		else
141362306a36Sopenharmony_ci			WRITE_ONCE(sk->sk_ll_usec, val);
141462306a36Sopenharmony_ci		break;
141562306a36Sopenharmony_ci	case SO_PREFER_BUSY_POLL:
141662306a36Sopenharmony_ci		if (valbool && !sockopt_capable(CAP_NET_ADMIN))
141762306a36Sopenharmony_ci			ret = -EPERM;
141862306a36Sopenharmony_ci		else
141962306a36Sopenharmony_ci			WRITE_ONCE(sk->sk_prefer_busy_poll, valbool);
142062306a36Sopenharmony_ci		break;
142162306a36Sopenharmony_ci	case SO_BUSY_POLL_BUDGET:
142262306a36Sopenharmony_ci		if (val > READ_ONCE(sk->sk_busy_poll_budget) && !sockopt_capable(CAP_NET_ADMIN)) {
142362306a36Sopenharmony_ci			ret = -EPERM;
142462306a36Sopenharmony_ci		} else {
142562306a36Sopenharmony_ci			if (val < 0 || val > U16_MAX)
142662306a36Sopenharmony_ci				ret = -EINVAL;
142762306a36Sopenharmony_ci			else
142862306a36Sopenharmony_ci				WRITE_ONCE(sk->sk_busy_poll_budget, val);
142962306a36Sopenharmony_ci		}
143062306a36Sopenharmony_ci		break;
143162306a36Sopenharmony_ci#endif
143262306a36Sopenharmony_ci
143362306a36Sopenharmony_ci	case SO_MAX_PACING_RATE:
143462306a36Sopenharmony_ci		{
143562306a36Sopenharmony_ci		unsigned long ulval = (val == ~0U) ? ~0UL : (unsigned int)val;
143662306a36Sopenharmony_ci
143762306a36Sopenharmony_ci		if (sizeof(ulval) != sizeof(val) &&
143862306a36Sopenharmony_ci		    optlen >= sizeof(ulval) &&
143962306a36Sopenharmony_ci		    copy_from_sockptr(&ulval, optval, sizeof(ulval))) {
144062306a36Sopenharmony_ci			ret = -EFAULT;
144162306a36Sopenharmony_ci			break;
144262306a36Sopenharmony_ci		}
144362306a36Sopenharmony_ci		if (ulval != ~0UL)
144462306a36Sopenharmony_ci			cmpxchg(&sk->sk_pacing_status,
144562306a36Sopenharmony_ci				SK_PACING_NONE,
144662306a36Sopenharmony_ci				SK_PACING_NEEDED);
144762306a36Sopenharmony_ci		/* Pairs with READ_ONCE() from sk_getsockopt() */
144862306a36Sopenharmony_ci		WRITE_ONCE(sk->sk_max_pacing_rate, ulval);
144962306a36Sopenharmony_ci		sk->sk_pacing_rate = min(sk->sk_pacing_rate, ulval);
145062306a36Sopenharmony_ci		break;
145162306a36Sopenharmony_ci		}
145262306a36Sopenharmony_ci	case SO_INCOMING_CPU:
145362306a36Sopenharmony_ci		reuseport_update_incoming_cpu(sk, val);
145462306a36Sopenharmony_ci		break;
145562306a36Sopenharmony_ci
145662306a36Sopenharmony_ci	case SO_CNX_ADVICE:
145762306a36Sopenharmony_ci		if (val == 1)
145862306a36Sopenharmony_ci			dst_negative_advice(sk);
145962306a36Sopenharmony_ci		break;
146062306a36Sopenharmony_ci
146162306a36Sopenharmony_ci	case SO_ZEROCOPY:
146262306a36Sopenharmony_ci		if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6) {
146362306a36Sopenharmony_ci			if (!(sk_is_tcp(sk) ||
146462306a36Sopenharmony_ci			      (sk->sk_type == SOCK_DGRAM &&
146562306a36Sopenharmony_ci			       sk->sk_protocol == IPPROTO_UDP)))
146662306a36Sopenharmony_ci				ret = -EOPNOTSUPP;
146762306a36Sopenharmony_ci		} else if (sk->sk_family != PF_RDS) {
146862306a36Sopenharmony_ci			ret = -EOPNOTSUPP;
146962306a36Sopenharmony_ci		}
147062306a36Sopenharmony_ci		if (!ret) {
147162306a36Sopenharmony_ci			if (val < 0 || val > 1)
147262306a36Sopenharmony_ci				ret = -EINVAL;
147362306a36Sopenharmony_ci			else
147462306a36Sopenharmony_ci				sock_valbool_flag(sk, SOCK_ZEROCOPY, valbool);
147562306a36Sopenharmony_ci		}
147662306a36Sopenharmony_ci		break;
147762306a36Sopenharmony_ci
147862306a36Sopenharmony_ci	case SO_TXTIME:
147962306a36Sopenharmony_ci		if (optlen != sizeof(struct sock_txtime)) {
148062306a36Sopenharmony_ci			ret = -EINVAL;
148162306a36Sopenharmony_ci			break;
148262306a36Sopenharmony_ci		} else if (copy_from_sockptr(&sk_txtime, optval,
148362306a36Sopenharmony_ci			   sizeof(struct sock_txtime))) {
148462306a36Sopenharmony_ci			ret = -EFAULT;
148562306a36Sopenharmony_ci			break;
148662306a36Sopenharmony_ci		} else if (sk_txtime.flags & ~SOF_TXTIME_FLAGS_MASK) {
148762306a36Sopenharmony_ci			ret = -EINVAL;
148862306a36Sopenharmony_ci			break;
148962306a36Sopenharmony_ci		}
149062306a36Sopenharmony_ci		/* CLOCK_MONOTONIC is only used by sch_fq, and this packet
149162306a36Sopenharmony_ci		 * scheduler has enough safe guards.
149262306a36Sopenharmony_ci		 */
149362306a36Sopenharmony_ci		if (sk_txtime.clockid != CLOCK_MONOTONIC &&
149462306a36Sopenharmony_ci		    !sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) {
149562306a36Sopenharmony_ci			ret = -EPERM;
149662306a36Sopenharmony_ci			break;
149762306a36Sopenharmony_ci		}
149862306a36Sopenharmony_ci		sock_valbool_flag(sk, SOCK_TXTIME, true);
149962306a36Sopenharmony_ci		sk->sk_clockid = sk_txtime.clockid;
150062306a36Sopenharmony_ci		sk->sk_txtime_deadline_mode =
150162306a36Sopenharmony_ci			!!(sk_txtime.flags & SOF_TXTIME_DEADLINE_MODE);
150262306a36Sopenharmony_ci		sk->sk_txtime_report_errors =
150362306a36Sopenharmony_ci			!!(sk_txtime.flags & SOF_TXTIME_REPORT_ERRORS);
150462306a36Sopenharmony_ci		break;
150562306a36Sopenharmony_ci
150662306a36Sopenharmony_ci	case SO_BINDTOIFINDEX:
150762306a36Sopenharmony_ci		ret = sock_bindtoindex_locked(sk, val);
150862306a36Sopenharmony_ci		break;
150962306a36Sopenharmony_ci
151062306a36Sopenharmony_ci	case SO_BUF_LOCK:
151162306a36Sopenharmony_ci		if (val & ~SOCK_BUF_LOCK_MASK) {
151262306a36Sopenharmony_ci			ret = -EINVAL;
151362306a36Sopenharmony_ci			break;
151462306a36Sopenharmony_ci		}
151562306a36Sopenharmony_ci		sk->sk_userlocks = val | (sk->sk_userlocks &
151662306a36Sopenharmony_ci					  ~SOCK_BUF_LOCK_MASK);
151762306a36Sopenharmony_ci		break;
151862306a36Sopenharmony_ci
151962306a36Sopenharmony_ci	case SO_RESERVE_MEM:
152062306a36Sopenharmony_ci	{
152162306a36Sopenharmony_ci		int delta;
152262306a36Sopenharmony_ci
152362306a36Sopenharmony_ci		if (val < 0) {
152462306a36Sopenharmony_ci			ret = -EINVAL;
152562306a36Sopenharmony_ci			break;
152662306a36Sopenharmony_ci		}
152762306a36Sopenharmony_ci
152862306a36Sopenharmony_ci		delta = val - sk->sk_reserved_mem;
152962306a36Sopenharmony_ci		if (delta < 0)
153062306a36Sopenharmony_ci			sock_release_reserved_memory(sk, -delta);
153162306a36Sopenharmony_ci		else
153262306a36Sopenharmony_ci			ret = sock_reserve_memory(sk, delta);
153362306a36Sopenharmony_ci		break;
153462306a36Sopenharmony_ci	}
153562306a36Sopenharmony_ci
153662306a36Sopenharmony_ci	case SO_TXREHASH:
153762306a36Sopenharmony_ci		if (val < -1 || val > 1) {
153862306a36Sopenharmony_ci			ret = -EINVAL;
153962306a36Sopenharmony_ci			break;
154062306a36Sopenharmony_ci		}
154162306a36Sopenharmony_ci		if ((u8)val == SOCK_TXREHASH_DEFAULT)
154262306a36Sopenharmony_ci			val = READ_ONCE(sock_net(sk)->core.sysctl_txrehash);
154362306a36Sopenharmony_ci		/* Paired with READ_ONCE() in tcp_rtx_synack()
154462306a36Sopenharmony_ci		 * and sk_getsockopt().
154562306a36Sopenharmony_ci		 */
154662306a36Sopenharmony_ci		WRITE_ONCE(sk->sk_txrehash, (u8)val);
154762306a36Sopenharmony_ci		break;
154862306a36Sopenharmony_ci
154962306a36Sopenharmony_ci	default:
155062306a36Sopenharmony_ci		ret = -ENOPROTOOPT;
155162306a36Sopenharmony_ci		break;
155262306a36Sopenharmony_ci	}
155362306a36Sopenharmony_ci	sockopt_release_sock(sk);
155462306a36Sopenharmony_ci	return ret;
155562306a36Sopenharmony_ci}
155662306a36Sopenharmony_ci
155762306a36Sopenharmony_ciint sock_setsockopt(struct socket *sock, int level, int optname,
155862306a36Sopenharmony_ci		    sockptr_t optval, unsigned int optlen)
155962306a36Sopenharmony_ci{
156062306a36Sopenharmony_ci	return sk_setsockopt(sock->sk, level, optname,
156162306a36Sopenharmony_ci			     optval, optlen);
156262306a36Sopenharmony_ci}
156362306a36Sopenharmony_ciEXPORT_SYMBOL(sock_setsockopt);
156462306a36Sopenharmony_ci
156562306a36Sopenharmony_cistatic const struct cred *sk_get_peer_cred(struct sock *sk)
156662306a36Sopenharmony_ci{
156762306a36Sopenharmony_ci	const struct cred *cred;
156862306a36Sopenharmony_ci
156962306a36Sopenharmony_ci	spin_lock(&sk->sk_peer_lock);
157062306a36Sopenharmony_ci	cred = get_cred(sk->sk_peer_cred);
157162306a36Sopenharmony_ci	spin_unlock(&sk->sk_peer_lock);
157262306a36Sopenharmony_ci
157362306a36Sopenharmony_ci	return cred;
157462306a36Sopenharmony_ci}
157562306a36Sopenharmony_ci
157662306a36Sopenharmony_cistatic void cred_to_ucred(struct pid *pid, const struct cred *cred,
157762306a36Sopenharmony_ci			  struct ucred *ucred)
157862306a36Sopenharmony_ci{
157962306a36Sopenharmony_ci	ucred->pid = pid_vnr(pid);
158062306a36Sopenharmony_ci	ucred->uid = ucred->gid = -1;
158162306a36Sopenharmony_ci	if (cred) {
158262306a36Sopenharmony_ci		struct user_namespace *current_ns = current_user_ns();
158362306a36Sopenharmony_ci
158462306a36Sopenharmony_ci		ucred->uid = from_kuid_munged(current_ns, cred->euid);
158562306a36Sopenharmony_ci		ucred->gid = from_kgid_munged(current_ns, cred->egid);
158662306a36Sopenharmony_ci	}
158762306a36Sopenharmony_ci}
158862306a36Sopenharmony_ci
158962306a36Sopenharmony_cistatic int groups_to_user(sockptr_t dst, const struct group_info *src)
159062306a36Sopenharmony_ci{
159162306a36Sopenharmony_ci	struct user_namespace *user_ns = current_user_ns();
159262306a36Sopenharmony_ci	int i;
159362306a36Sopenharmony_ci
159462306a36Sopenharmony_ci	for (i = 0; i < src->ngroups; i++) {
159562306a36Sopenharmony_ci		gid_t gid = from_kgid_munged(user_ns, src->gid[i]);
159662306a36Sopenharmony_ci
159762306a36Sopenharmony_ci		if (copy_to_sockptr_offset(dst, i * sizeof(gid), &gid, sizeof(gid)))
159862306a36Sopenharmony_ci			return -EFAULT;
159962306a36Sopenharmony_ci	}
160062306a36Sopenharmony_ci
160162306a36Sopenharmony_ci	return 0;
160262306a36Sopenharmony_ci}
160362306a36Sopenharmony_ci
160462306a36Sopenharmony_ciint sk_getsockopt(struct sock *sk, int level, int optname,
160562306a36Sopenharmony_ci		  sockptr_t optval, sockptr_t optlen)
160662306a36Sopenharmony_ci{
160762306a36Sopenharmony_ci	struct socket *sock = sk->sk_socket;
160862306a36Sopenharmony_ci
160962306a36Sopenharmony_ci	union {
161062306a36Sopenharmony_ci		int val;
161162306a36Sopenharmony_ci		u64 val64;
161262306a36Sopenharmony_ci		unsigned long ulval;
161362306a36Sopenharmony_ci		struct linger ling;
161462306a36Sopenharmony_ci		struct old_timeval32 tm32;
161562306a36Sopenharmony_ci		struct __kernel_old_timeval tm;
161662306a36Sopenharmony_ci		struct  __kernel_sock_timeval stm;
161762306a36Sopenharmony_ci		struct sock_txtime txtime;
161862306a36Sopenharmony_ci		struct so_timestamping timestamping;
161962306a36Sopenharmony_ci	} v;
162062306a36Sopenharmony_ci
162162306a36Sopenharmony_ci	int lv = sizeof(int);
162262306a36Sopenharmony_ci	int len;
162362306a36Sopenharmony_ci
162462306a36Sopenharmony_ci	if (copy_from_sockptr(&len, optlen, sizeof(int)))
162562306a36Sopenharmony_ci		return -EFAULT;
162662306a36Sopenharmony_ci	if (len < 0)
162762306a36Sopenharmony_ci		return -EINVAL;
162862306a36Sopenharmony_ci
162962306a36Sopenharmony_ci	memset(&v, 0, sizeof(v));
163062306a36Sopenharmony_ci
163162306a36Sopenharmony_ci	switch (optname) {
163262306a36Sopenharmony_ci	case SO_DEBUG:
163362306a36Sopenharmony_ci		v.val = sock_flag(sk, SOCK_DBG);
163462306a36Sopenharmony_ci		break;
163562306a36Sopenharmony_ci
163662306a36Sopenharmony_ci	case SO_DONTROUTE:
163762306a36Sopenharmony_ci		v.val = sock_flag(sk, SOCK_LOCALROUTE);
163862306a36Sopenharmony_ci		break;
163962306a36Sopenharmony_ci
164062306a36Sopenharmony_ci	case SO_BROADCAST:
164162306a36Sopenharmony_ci		v.val = sock_flag(sk, SOCK_BROADCAST);
164262306a36Sopenharmony_ci		break;
164362306a36Sopenharmony_ci
164462306a36Sopenharmony_ci	case SO_SNDBUF:
164562306a36Sopenharmony_ci		v.val = READ_ONCE(sk->sk_sndbuf);
164662306a36Sopenharmony_ci		break;
164762306a36Sopenharmony_ci
164862306a36Sopenharmony_ci	case SO_RCVBUF:
164962306a36Sopenharmony_ci		v.val = READ_ONCE(sk->sk_rcvbuf);
165062306a36Sopenharmony_ci		break;
165162306a36Sopenharmony_ci
165262306a36Sopenharmony_ci	case SO_REUSEADDR:
165362306a36Sopenharmony_ci		v.val = sk->sk_reuse;
165462306a36Sopenharmony_ci		break;
165562306a36Sopenharmony_ci
165662306a36Sopenharmony_ci	case SO_REUSEPORT:
165762306a36Sopenharmony_ci		v.val = sk->sk_reuseport;
165862306a36Sopenharmony_ci		break;
165962306a36Sopenharmony_ci
166062306a36Sopenharmony_ci	case SO_KEEPALIVE:
166162306a36Sopenharmony_ci		v.val = sock_flag(sk, SOCK_KEEPOPEN);
166262306a36Sopenharmony_ci		break;
166362306a36Sopenharmony_ci
166462306a36Sopenharmony_ci	case SO_TYPE:
166562306a36Sopenharmony_ci		v.val = sk->sk_type;
166662306a36Sopenharmony_ci		break;
166762306a36Sopenharmony_ci
166862306a36Sopenharmony_ci	case SO_PROTOCOL:
166962306a36Sopenharmony_ci		v.val = sk->sk_protocol;
167062306a36Sopenharmony_ci		break;
167162306a36Sopenharmony_ci
167262306a36Sopenharmony_ci	case SO_DOMAIN:
167362306a36Sopenharmony_ci		v.val = sk->sk_family;
167462306a36Sopenharmony_ci		break;
167562306a36Sopenharmony_ci
167662306a36Sopenharmony_ci	case SO_ERROR:
167762306a36Sopenharmony_ci		v.val = -sock_error(sk);
167862306a36Sopenharmony_ci		if (v.val == 0)
167962306a36Sopenharmony_ci			v.val = xchg(&sk->sk_err_soft, 0);
168062306a36Sopenharmony_ci		break;
168162306a36Sopenharmony_ci
168262306a36Sopenharmony_ci	case SO_OOBINLINE:
168362306a36Sopenharmony_ci		v.val = sock_flag(sk, SOCK_URGINLINE);
168462306a36Sopenharmony_ci		break;
168562306a36Sopenharmony_ci
168662306a36Sopenharmony_ci	case SO_NO_CHECK:
168762306a36Sopenharmony_ci		v.val = sk->sk_no_check_tx;
168862306a36Sopenharmony_ci		break;
168962306a36Sopenharmony_ci
169062306a36Sopenharmony_ci	case SO_PRIORITY:
169162306a36Sopenharmony_ci		v.val = READ_ONCE(sk->sk_priority);
169262306a36Sopenharmony_ci		break;
169362306a36Sopenharmony_ci
169462306a36Sopenharmony_ci	case SO_LINGER:
169562306a36Sopenharmony_ci		lv		= sizeof(v.ling);
169662306a36Sopenharmony_ci		v.ling.l_onoff	= sock_flag(sk, SOCK_LINGER);
169762306a36Sopenharmony_ci		v.ling.l_linger	= READ_ONCE(sk->sk_lingertime) / HZ;
169862306a36Sopenharmony_ci		break;
169962306a36Sopenharmony_ci
170062306a36Sopenharmony_ci	case SO_BSDCOMPAT:
170162306a36Sopenharmony_ci		break;
170262306a36Sopenharmony_ci
170362306a36Sopenharmony_ci	case SO_TIMESTAMP_OLD:
170462306a36Sopenharmony_ci		v.val = sock_flag(sk, SOCK_RCVTSTAMP) &&
170562306a36Sopenharmony_ci				!sock_flag(sk, SOCK_TSTAMP_NEW) &&
170662306a36Sopenharmony_ci				!sock_flag(sk, SOCK_RCVTSTAMPNS);
170762306a36Sopenharmony_ci		break;
170862306a36Sopenharmony_ci
170962306a36Sopenharmony_ci	case SO_TIMESTAMPNS_OLD:
171062306a36Sopenharmony_ci		v.val = sock_flag(sk, SOCK_RCVTSTAMPNS) && !sock_flag(sk, SOCK_TSTAMP_NEW);
171162306a36Sopenharmony_ci		break;
171262306a36Sopenharmony_ci
171362306a36Sopenharmony_ci	case SO_TIMESTAMP_NEW:
171462306a36Sopenharmony_ci		v.val = sock_flag(sk, SOCK_RCVTSTAMP) && sock_flag(sk, SOCK_TSTAMP_NEW);
171562306a36Sopenharmony_ci		break;
171662306a36Sopenharmony_ci
171762306a36Sopenharmony_ci	case SO_TIMESTAMPNS_NEW:
171862306a36Sopenharmony_ci		v.val = sock_flag(sk, SOCK_RCVTSTAMPNS) && sock_flag(sk, SOCK_TSTAMP_NEW);
171962306a36Sopenharmony_ci		break;
172062306a36Sopenharmony_ci
172162306a36Sopenharmony_ci	case SO_TIMESTAMPING_OLD:
172262306a36Sopenharmony_ci	case SO_TIMESTAMPING_NEW:
172362306a36Sopenharmony_ci		lv = sizeof(v.timestamping);
172462306a36Sopenharmony_ci		/* For the later-added case SO_TIMESTAMPING_NEW: Be strict about only
172562306a36Sopenharmony_ci		 * returning the flags when they were set through the same option.
172662306a36Sopenharmony_ci		 * Don't change the beviour for the old case SO_TIMESTAMPING_OLD.
172762306a36Sopenharmony_ci		 */
172862306a36Sopenharmony_ci		if (optname == SO_TIMESTAMPING_OLD || sock_flag(sk, SOCK_TSTAMP_NEW)) {
172962306a36Sopenharmony_ci			v.timestamping.flags = READ_ONCE(sk->sk_tsflags);
173062306a36Sopenharmony_ci			v.timestamping.bind_phc = READ_ONCE(sk->sk_bind_phc);
173162306a36Sopenharmony_ci		}
173262306a36Sopenharmony_ci		break;
173362306a36Sopenharmony_ci
173462306a36Sopenharmony_ci	case SO_RCVTIMEO_OLD:
173562306a36Sopenharmony_ci	case SO_RCVTIMEO_NEW:
173662306a36Sopenharmony_ci		lv = sock_get_timeout(READ_ONCE(sk->sk_rcvtimeo), &v,
173762306a36Sopenharmony_ci				      SO_RCVTIMEO_OLD == optname);
173862306a36Sopenharmony_ci		break;
173962306a36Sopenharmony_ci
174062306a36Sopenharmony_ci	case SO_SNDTIMEO_OLD:
174162306a36Sopenharmony_ci	case SO_SNDTIMEO_NEW:
174262306a36Sopenharmony_ci		lv = sock_get_timeout(READ_ONCE(sk->sk_sndtimeo), &v,
174362306a36Sopenharmony_ci				      SO_SNDTIMEO_OLD == optname);
174462306a36Sopenharmony_ci		break;
174562306a36Sopenharmony_ci
174662306a36Sopenharmony_ci	case SO_RCVLOWAT:
174762306a36Sopenharmony_ci		v.val = READ_ONCE(sk->sk_rcvlowat);
174862306a36Sopenharmony_ci		break;
174962306a36Sopenharmony_ci
175062306a36Sopenharmony_ci	case SO_SNDLOWAT:
175162306a36Sopenharmony_ci		v.val = 1;
175262306a36Sopenharmony_ci		break;
175362306a36Sopenharmony_ci
175462306a36Sopenharmony_ci	case SO_PASSCRED:
175562306a36Sopenharmony_ci		v.val = !!test_bit(SOCK_PASSCRED, &sock->flags);
175662306a36Sopenharmony_ci		break;
175762306a36Sopenharmony_ci
175862306a36Sopenharmony_ci	case SO_PASSPIDFD:
175962306a36Sopenharmony_ci		v.val = !!test_bit(SOCK_PASSPIDFD, &sock->flags);
176062306a36Sopenharmony_ci		break;
176162306a36Sopenharmony_ci
176262306a36Sopenharmony_ci	case SO_PEERCRED:
176362306a36Sopenharmony_ci	{
176462306a36Sopenharmony_ci		struct ucred peercred;
176562306a36Sopenharmony_ci		if (len > sizeof(peercred))
176662306a36Sopenharmony_ci			len = sizeof(peercred);
176762306a36Sopenharmony_ci
176862306a36Sopenharmony_ci		spin_lock(&sk->sk_peer_lock);
176962306a36Sopenharmony_ci		cred_to_ucred(sk->sk_peer_pid, sk->sk_peer_cred, &peercred);
177062306a36Sopenharmony_ci		spin_unlock(&sk->sk_peer_lock);
177162306a36Sopenharmony_ci
177262306a36Sopenharmony_ci		if (copy_to_sockptr(optval, &peercred, len))
177362306a36Sopenharmony_ci			return -EFAULT;
177462306a36Sopenharmony_ci		goto lenout;
177562306a36Sopenharmony_ci	}
177662306a36Sopenharmony_ci
177762306a36Sopenharmony_ci	case SO_PEERPIDFD:
177862306a36Sopenharmony_ci	{
177962306a36Sopenharmony_ci		struct pid *peer_pid;
178062306a36Sopenharmony_ci		struct file *pidfd_file = NULL;
178162306a36Sopenharmony_ci		int pidfd;
178262306a36Sopenharmony_ci
178362306a36Sopenharmony_ci		if (len > sizeof(pidfd))
178462306a36Sopenharmony_ci			len = sizeof(pidfd);
178562306a36Sopenharmony_ci
178662306a36Sopenharmony_ci		spin_lock(&sk->sk_peer_lock);
178762306a36Sopenharmony_ci		peer_pid = get_pid(sk->sk_peer_pid);
178862306a36Sopenharmony_ci		spin_unlock(&sk->sk_peer_lock);
178962306a36Sopenharmony_ci
179062306a36Sopenharmony_ci		if (!peer_pid)
179162306a36Sopenharmony_ci			return -ENODATA;
179262306a36Sopenharmony_ci
179362306a36Sopenharmony_ci		pidfd = pidfd_prepare(peer_pid, 0, &pidfd_file);
179462306a36Sopenharmony_ci		put_pid(peer_pid);
179562306a36Sopenharmony_ci		if (pidfd < 0)
179662306a36Sopenharmony_ci			return pidfd;
179762306a36Sopenharmony_ci
179862306a36Sopenharmony_ci		if (copy_to_sockptr(optval, &pidfd, len) ||
179962306a36Sopenharmony_ci		    copy_to_sockptr(optlen, &len, sizeof(int))) {
180062306a36Sopenharmony_ci			put_unused_fd(pidfd);
180162306a36Sopenharmony_ci			fput(pidfd_file);
180262306a36Sopenharmony_ci
180362306a36Sopenharmony_ci			return -EFAULT;
180462306a36Sopenharmony_ci		}
180562306a36Sopenharmony_ci
180662306a36Sopenharmony_ci		fd_install(pidfd, pidfd_file);
180762306a36Sopenharmony_ci		return 0;
180862306a36Sopenharmony_ci	}
180962306a36Sopenharmony_ci
181062306a36Sopenharmony_ci	case SO_PEERGROUPS:
181162306a36Sopenharmony_ci	{
181262306a36Sopenharmony_ci		const struct cred *cred;
181362306a36Sopenharmony_ci		int ret, n;
181462306a36Sopenharmony_ci
181562306a36Sopenharmony_ci		cred = sk_get_peer_cred(sk);
181662306a36Sopenharmony_ci		if (!cred)
181762306a36Sopenharmony_ci			return -ENODATA;
181862306a36Sopenharmony_ci
181962306a36Sopenharmony_ci		n = cred->group_info->ngroups;
182062306a36Sopenharmony_ci		if (len < n * sizeof(gid_t)) {
182162306a36Sopenharmony_ci			len = n * sizeof(gid_t);
182262306a36Sopenharmony_ci			put_cred(cred);
182362306a36Sopenharmony_ci			return copy_to_sockptr(optlen, &len, sizeof(int)) ? -EFAULT : -ERANGE;
182462306a36Sopenharmony_ci		}
182562306a36Sopenharmony_ci		len = n * sizeof(gid_t);
182662306a36Sopenharmony_ci
182762306a36Sopenharmony_ci		ret = groups_to_user(optval, cred->group_info);
182862306a36Sopenharmony_ci		put_cred(cred);
182962306a36Sopenharmony_ci		if (ret)
183062306a36Sopenharmony_ci			return ret;
183162306a36Sopenharmony_ci		goto lenout;
183262306a36Sopenharmony_ci	}
183362306a36Sopenharmony_ci
183462306a36Sopenharmony_ci	case SO_PEERNAME:
183562306a36Sopenharmony_ci	{
183662306a36Sopenharmony_ci		struct sockaddr_storage address;
183762306a36Sopenharmony_ci
183862306a36Sopenharmony_ci		lv = READ_ONCE(sock->ops)->getname(sock, (struct sockaddr *)&address, 2);
183962306a36Sopenharmony_ci		if (lv < 0)
184062306a36Sopenharmony_ci			return -ENOTCONN;
184162306a36Sopenharmony_ci		if (lv < len)
184262306a36Sopenharmony_ci			return -EINVAL;
184362306a36Sopenharmony_ci		if (copy_to_sockptr(optval, &address, len))
184462306a36Sopenharmony_ci			return -EFAULT;
184562306a36Sopenharmony_ci		goto lenout;
184662306a36Sopenharmony_ci	}
184762306a36Sopenharmony_ci
184862306a36Sopenharmony_ci	/* Dubious BSD thing... Probably nobody even uses it, but
184962306a36Sopenharmony_ci	 * the UNIX standard wants it for whatever reason... -DaveM
185062306a36Sopenharmony_ci	 */
185162306a36Sopenharmony_ci	case SO_ACCEPTCONN:
185262306a36Sopenharmony_ci		v.val = sk->sk_state == TCP_LISTEN;
185362306a36Sopenharmony_ci		break;
185462306a36Sopenharmony_ci
185562306a36Sopenharmony_ci	case SO_PASSSEC:
185662306a36Sopenharmony_ci		v.val = !!test_bit(SOCK_PASSSEC, &sock->flags);
185762306a36Sopenharmony_ci		break;
185862306a36Sopenharmony_ci
185962306a36Sopenharmony_ci	case SO_PEERSEC:
186062306a36Sopenharmony_ci		return security_socket_getpeersec_stream(sock,
186162306a36Sopenharmony_ci							 optval, optlen, len);
186262306a36Sopenharmony_ci
186362306a36Sopenharmony_ci	case SO_MARK:
186462306a36Sopenharmony_ci		v.val = READ_ONCE(sk->sk_mark);
186562306a36Sopenharmony_ci		break;
186662306a36Sopenharmony_ci
186762306a36Sopenharmony_ci	case SO_RCVMARK:
186862306a36Sopenharmony_ci		v.val = sock_flag(sk, SOCK_RCVMARK);
186962306a36Sopenharmony_ci		break;
187062306a36Sopenharmony_ci
187162306a36Sopenharmony_ci	case SO_RXQ_OVFL:
187262306a36Sopenharmony_ci		v.val = sock_flag(sk, SOCK_RXQ_OVFL);
187362306a36Sopenharmony_ci		break;
187462306a36Sopenharmony_ci
187562306a36Sopenharmony_ci	case SO_WIFI_STATUS:
187662306a36Sopenharmony_ci		v.val = sock_flag(sk, SOCK_WIFI_STATUS);
187762306a36Sopenharmony_ci		break;
187862306a36Sopenharmony_ci
187962306a36Sopenharmony_ci	case SO_PEEK_OFF:
188062306a36Sopenharmony_ci		if (!READ_ONCE(sock->ops)->set_peek_off)
188162306a36Sopenharmony_ci			return -EOPNOTSUPP;
188262306a36Sopenharmony_ci
188362306a36Sopenharmony_ci		v.val = READ_ONCE(sk->sk_peek_off);
188462306a36Sopenharmony_ci		break;
188562306a36Sopenharmony_ci	case SO_NOFCS:
188662306a36Sopenharmony_ci		v.val = sock_flag(sk, SOCK_NOFCS);
188762306a36Sopenharmony_ci		break;
188862306a36Sopenharmony_ci
188962306a36Sopenharmony_ci	case SO_BINDTODEVICE:
189062306a36Sopenharmony_ci		return sock_getbindtodevice(sk, optval, optlen, len);
189162306a36Sopenharmony_ci
189262306a36Sopenharmony_ci	case SO_GET_FILTER:
189362306a36Sopenharmony_ci		len = sk_get_filter(sk, optval, len);
189462306a36Sopenharmony_ci		if (len < 0)
189562306a36Sopenharmony_ci			return len;
189662306a36Sopenharmony_ci
189762306a36Sopenharmony_ci		goto lenout;
189862306a36Sopenharmony_ci
189962306a36Sopenharmony_ci	case SO_LOCK_FILTER:
190062306a36Sopenharmony_ci		v.val = sock_flag(sk, SOCK_FILTER_LOCKED);
190162306a36Sopenharmony_ci		break;
190262306a36Sopenharmony_ci
190362306a36Sopenharmony_ci	case SO_BPF_EXTENSIONS:
190462306a36Sopenharmony_ci		v.val = bpf_tell_extensions();
190562306a36Sopenharmony_ci		break;
190662306a36Sopenharmony_ci
190762306a36Sopenharmony_ci	case SO_SELECT_ERR_QUEUE:
190862306a36Sopenharmony_ci		v.val = sock_flag(sk, SOCK_SELECT_ERR_QUEUE);
190962306a36Sopenharmony_ci		break;
191062306a36Sopenharmony_ci
191162306a36Sopenharmony_ci#ifdef CONFIG_NET_RX_BUSY_POLL
191262306a36Sopenharmony_ci	case SO_BUSY_POLL:
191362306a36Sopenharmony_ci		v.val = READ_ONCE(sk->sk_ll_usec);
191462306a36Sopenharmony_ci		break;
191562306a36Sopenharmony_ci	case SO_PREFER_BUSY_POLL:
191662306a36Sopenharmony_ci		v.val = READ_ONCE(sk->sk_prefer_busy_poll);
191762306a36Sopenharmony_ci		break;
191862306a36Sopenharmony_ci#endif
191962306a36Sopenharmony_ci
192062306a36Sopenharmony_ci	case SO_MAX_PACING_RATE:
192162306a36Sopenharmony_ci		/* The READ_ONCE() pair with the WRITE_ONCE() in sk_setsockopt() */
192262306a36Sopenharmony_ci		if (sizeof(v.ulval) != sizeof(v.val) && len >= sizeof(v.ulval)) {
192362306a36Sopenharmony_ci			lv = sizeof(v.ulval);
192462306a36Sopenharmony_ci			v.ulval = READ_ONCE(sk->sk_max_pacing_rate);
192562306a36Sopenharmony_ci		} else {
192662306a36Sopenharmony_ci			/* 32bit version */
192762306a36Sopenharmony_ci			v.val = min_t(unsigned long, ~0U,
192862306a36Sopenharmony_ci				      READ_ONCE(sk->sk_max_pacing_rate));
192962306a36Sopenharmony_ci		}
193062306a36Sopenharmony_ci		break;
193162306a36Sopenharmony_ci
193262306a36Sopenharmony_ci	case SO_INCOMING_CPU:
193362306a36Sopenharmony_ci		v.val = READ_ONCE(sk->sk_incoming_cpu);
193462306a36Sopenharmony_ci		break;
193562306a36Sopenharmony_ci
193662306a36Sopenharmony_ci	case SO_MEMINFO:
193762306a36Sopenharmony_ci	{
193862306a36Sopenharmony_ci		u32 meminfo[SK_MEMINFO_VARS];
193962306a36Sopenharmony_ci
194062306a36Sopenharmony_ci		sk_get_meminfo(sk, meminfo);
194162306a36Sopenharmony_ci
194262306a36Sopenharmony_ci		len = min_t(unsigned int, len, sizeof(meminfo));
194362306a36Sopenharmony_ci		if (copy_to_sockptr(optval, &meminfo, len))
194462306a36Sopenharmony_ci			return -EFAULT;
194562306a36Sopenharmony_ci
194662306a36Sopenharmony_ci		goto lenout;
194762306a36Sopenharmony_ci	}
194862306a36Sopenharmony_ci
194962306a36Sopenharmony_ci#ifdef CONFIG_NET_RX_BUSY_POLL
195062306a36Sopenharmony_ci	case SO_INCOMING_NAPI_ID:
195162306a36Sopenharmony_ci		v.val = READ_ONCE(sk->sk_napi_id);
195262306a36Sopenharmony_ci
195362306a36Sopenharmony_ci		/* aggregate non-NAPI IDs down to 0 */
195462306a36Sopenharmony_ci		if (v.val < MIN_NAPI_ID)
195562306a36Sopenharmony_ci			v.val = 0;
195662306a36Sopenharmony_ci
195762306a36Sopenharmony_ci		break;
195862306a36Sopenharmony_ci#endif
195962306a36Sopenharmony_ci
196062306a36Sopenharmony_ci	case SO_COOKIE:
196162306a36Sopenharmony_ci		lv = sizeof(u64);
196262306a36Sopenharmony_ci		if (len < lv)
196362306a36Sopenharmony_ci			return -EINVAL;
196462306a36Sopenharmony_ci		v.val64 = sock_gen_cookie(sk);
196562306a36Sopenharmony_ci		break;
196662306a36Sopenharmony_ci
196762306a36Sopenharmony_ci	case SO_ZEROCOPY:
196862306a36Sopenharmony_ci		v.val = sock_flag(sk, SOCK_ZEROCOPY);
196962306a36Sopenharmony_ci		break;
197062306a36Sopenharmony_ci
197162306a36Sopenharmony_ci	case SO_TXTIME:
197262306a36Sopenharmony_ci		lv = sizeof(v.txtime);
197362306a36Sopenharmony_ci		v.txtime.clockid = sk->sk_clockid;
197462306a36Sopenharmony_ci		v.txtime.flags |= sk->sk_txtime_deadline_mode ?
197562306a36Sopenharmony_ci				  SOF_TXTIME_DEADLINE_MODE : 0;
197662306a36Sopenharmony_ci		v.txtime.flags |= sk->sk_txtime_report_errors ?
197762306a36Sopenharmony_ci				  SOF_TXTIME_REPORT_ERRORS : 0;
197862306a36Sopenharmony_ci		break;
197962306a36Sopenharmony_ci
198062306a36Sopenharmony_ci	case SO_BINDTOIFINDEX:
198162306a36Sopenharmony_ci		v.val = READ_ONCE(sk->sk_bound_dev_if);
198262306a36Sopenharmony_ci		break;
198362306a36Sopenharmony_ci
198462306a36Sopenharmony_ci	case SO_NETNS_COOKIE:
198562306a36Sopenharmony_ci		lv = sizeof(u64);
198662306a36Sopenharmony_ci		if (len != lv)
198762306a36Sopenharmony_ci			return -EINVAL;
198862306a36Sopenharmony_ci		v.val64 = sock_net(sk)->net_cookie;
198962306a36Sopenharmony_ci		break;
199062306a36Sopenharmony_ci
199162306a36Sopenharmony_ci	case SO_BUF_LOCK:
199262306a36Sopenharmony_ci		v.val = sk->sk_userlocks & SOCK_BUF_LOCK_MASK;
199362306a36Sopenharmony_ci		break;
199462306a36Sopenharmony_ci
199562306a36Sopenharmony_ci	case SO_RESERVE_MEM:
199662306a36Sopenharmony_ci		v.val = READ_ONCE(sk->sk_reserved_mem);
199762306a36Sopenharmony_ci		break;
199862306a36Sopenharmony_ci
199962306a36Sopenharmony_ci	case SO_TXREHASH:
200062306a36Sopenharmony_ci		/* Paired with WRITE_ONCE() in sk_setsockopt() */
200162306a36Sopenharmony_ci		v.val = READ_ONCE(sk->sk_txrehash);
200262306a36Sopenharmony_ci		break;
200362306a36Sopenharmony_ci
200462306a36Sopenharmony_ci	default:
200562306a36Sopenharmony_ci		/* We implement the SO_SNDLOWAT etc to not be settable
200662306a36Sopenharmony_ci		 * (1003.1g 7).
200762306a36Sopenharmony_ci		 */
200862306a36Sopenharmony_ci		return -ENOPROTOOPT;
200962306a36Sopenharmony_ci	}
201062306a36Sopenharmony_ci
201162306a36Sopenharmony_ci	if (len > lv)
201262306a36Sopenharmony_ci		len = lv;
201362306a36Sopenharmony_ci	if (copy_to_sockptr(optval, &v, len))
201462306a36Sopenharmony_ci		return -EFAULT;
201562306a36Sopenharmony_cilenout:
201662306a36Sopenharmony_ci	if (copy_to_sockptr(optlen, &len, sizeof(int)))
201762306a36Sopenharmony_ci		return -EFAULT;
201862306a36Sopenharmony_ci	return 0;
201962306a36Sopenharmony_ci}
202062306a36Sopenharmony_ci
202162306a36Sopenharmony_ciint sock_getsockopt(struct socket *sock, int level, int optname,
202262306a36Sopenharmony_ci		    char __user *optval, int __user *optlen)
202362306a36Sopenharmony_ci{
202462306a36Sopenharmony_ci	return sk_getsockopt(sock->sk, level, optname,
202562306a36Sopenharmony_ci			     USER_SOCKPTR(optval),
202662306a36Sopenharmony_ci			     USER_SOCKPTR(optlen));
202762306a36Sopenharmony_ci}
202862306a36Sopenharmony_ci
202962306a36Sopenharmony_ci/*
203062306a36Sopenharmony_ci * Initialize an sk_lock.
203162306a36Sopenharmony_ci *
203262306a36Sopenharmony_ci * (We also register the sk_lock with the lock validator.)
203362306a36Sopenharmony_ci */
203462306a36Sopenharmony_cistatic inline void sock_lock_init(struct sock *sk)
203562306a36Sopenharmony_ci{
203662306a36Sopenharmony_ci	if (sk->sk_kern_sock)
203762306a36Sopenharmony_ci		sock_lock_init_class_and_name(
203862306a36Sopenharmony_ci			sk,
203962306a36Sopenharmony_ci			af_family_kern_slock_key_strings[sk->sk_family],
204062306a36Sopenharmony_ci			af_family_kern_slock_keys + sk->sk_family,
204162306a36Sopenharmony_ci			af_family_kern_key_strings[sk->sk_family],
204262306a36Sopenharmony_ci			af_family_kern_keys + sk->sk_family);
204362306a36Sopenharmony_ci	else
204462306a36Sopenharmony_ci		sock_lock_init_class_and_name(
204562306a36Sopenharmony_ci			sk,
204662306a36Sopenharmony_ci			af_family_slock_key_strings[sk->sk_family],
204762306a36Sopenharmony_ci			af_family_slock_keys + sk->sk_family,
204862306a36Sopenharmony_ci			af_family_key_strings[sk->sk_family],
204962306a36Sopenharmony_ci			af_family_keys + sk->sk_family);
205062306a36Sopenharmony_ci}
205162306a36Sopenharmony_ci
205262306a36Sopenharmony_ci/*
205362306a36Sopenharmony_ci * Copy all fields from osk to nsk but nsk->sk_refcnt must not change yet,
205462306a36Sopenharmony_ci * even temporarly, because of RCU lookups. sk_node should also be left as is.
205562306a36Sopenharmony_ci * We must not copy fields between sk_dontcopy_begin and sk_dontcopy_end
205662306a36Sopenharmony_ci */
205762306a36Sopenharmony_cistatic void sock_copy(struct sock *nsk, const struct sock *osk)
205862306a36Sopenharmony_ci{
205962306a36Sopenharmony_ci	const struct proto *prot = READ_ONCE(osk->sk_prot);
206062306a36Sopenharmony_ci#ifdef CONFIG_SECURITY_NETWORK
206162306a36Sopenharmony_ci	void *sptr = nsk->sk_security;
206262306a36Sopenharmony_ci#endif
206362306a36Sopenharmony_ci
206462306a36Sopenharmony_ci	/* If we move sk_tx_queue_mapping out of the private section,
206562306a36Sopenharmony_ci	 * we must check if sk_tx_queue_clear() is called after
206662306a36Sopenharmony_ci	 * sock_copy() in sk_clone_lock().
206762306a36Sopenharmony_ci	 */
206862306a36Sopenharmony_ci	BUILD_BUG_ON(offsetof(struct sock, sk_tx_queue_mapping) <
206962306a36Sopenharmony_ci		     offsetof(struct sock, sk_dontcopy_begin) ||
207062306a36Sopenharmony_ci		     offsetof(struct sock, sk_tx_queue_mapping) >=
207162306a36Sopenharmony_ci		     offsetof(struct sock, sk_dontcopy_end));
207262306a36Sopenharmony_ci
207362306a36Sopenharmony_ci	memcpy(nsk, osk, offsetof(struct sock, sk_dontcopy_begin));
207462306a36Sopenharmony_ci
207562306a36Sopenharmony_ci	memcpy(&nsk->sk_dontcopy_end, &osk->sk_dontcopy_end,
207662306a36Sopenharmony_ci	       prot->obj_size - offsetof(struct sock, sk_dontcopy_end));
207762306a36Sopenharmony_ci
207862306a36Sopenharmony_ci#ifdef CONFIG_SECURITY_NETWORK
207962306a36Sopenharmony_ci	nsk->sk_security = sptr;
208062306a36Sopenharmony_ci	security_sk_clone(osk, nsk);
208162306a36Sopenharmony_ci#endif
208262306a36Sopenharmony_ci}
208362306a36Sopenharmony_ci
208462306a36Sopenharmony_cistatic struct sock *sk_prot_alloc(struct proto *prot, gfp_t priority,
208562306a36Sopenharmony_ci		int family)
208662306a36Sopenharmony_ci{
208762306a36Sopenharmony_ci	struct sock *sk;
208862306a36Sopenharmony_ci	struct kmem_cache *slab;
208962306a36Sopenharmony_ci
209062306a36Sopenharmony_ci	slab = prot->slab;
209162306a36Sopenharmony_ci	if (slab != NULL) {
209262306a36Sopenharmony_ci		sk = kmem_cache_alloc(slab, priority & ~__GFP_ZERO);
209362306a36Sopenharmony_ci		if (!sk)
209462306a36Sopenharmony_ci			return sk;
209562306a36Sopenharmony_ci		if (want_init_on_alloc(priority))
209662306a36Sopenharmony_ci			sk_prot_clear_nulls(sk, prot->obj_size);
209762306a36Sopenharmony_ci	} else
209862306a36Sopenharmony_ci		sk = kmalloc(prot->obj_size, priority);
209962306a36Sopenharmony_ci
210062306a36Sopenharmony_ci	if (sk != NULL) {
210162306a36Sopenharmony_ci		if (security_sk_alloc(sk, family, priority))
210262306a36Sopenharmony_ci			goto out_free;
210362306a36Sopenharmony_ci
210462306a36Sopenharmony_ci		if (!try_module_get(prot->owner))
210562306a36Sopenharmony_ci			goto out_free_sec;
210662306a36Sopenharmony_ci	}
210762306a36Sopenharmony_ci
210862306a36Sopenharmony_ci	return sk;
210962306a36Sopenharmony_ci
211062306a36Sopenharmony_ciout_free_sec:
211162306a36Sopenharmony_ci	security_sk_free(sk);
211262306a36Sopenharmony_ciout_free:
211362306a36Sopenharmony_ci	if (slab != NULL)
211462306a36Sopenharmony_ci		kmem_cache_free(slab, sk);
211562306a36Sopenharmony_ci	else
211662306a36Sopenharmony_ci		kfree(sk);
211762306a36Sopenharmony_ci	return NULL;
211862306a36Sopenharmony_ci}
211962306a36Sopenharmony_ci
212062306a36Sopenharmony_cistatic void sk_prot_free(struct proto *prot, struct sock *sk)
212162306a36Sopenharmony_ci{
212262306a36Sopenharmony_ci	struct kmem_cache *slab;
212362306a36Sopenharmony_ci	struct module *owner;
212462306a36Sopenharmony_ci
212562306a36Sopenharmony_ci	owner = prot->owner;
212662306a36Sopenharmony_ci	slab = prot->slab;
212762306a36Sopenharmony_ci
212862306a36Sopenharmony_ci	cgroup_sk_free(&sk->sk_cgrp_data);
212962306a36Sopenharmony_ci	mem_cgroup_sk_free(sk);
213062306a36Sopenharmony_ci	security_sk_free(sk);
213162306a36Sopenharmony_ci	if (slab != NULL)
213262306a36Sopenharmony_ci		kmem_cache_free(slab, sk);
213362306a36Sopenharmony_ci	else
213462306a36Sopenharmony_ci		kfree(sk);
213562306a36Sopenharmony_ci	module_put(owner);
213662306a36Sopenharmony_ci}
213762306a36Sopenharmony_ci
213862306a36Sopenharmony_ci/**
213962306a36Sopenharmony_ci *	sk_alloc - All socket objects are allocated here
214062306a36Sopenharmony_ci *	@net: the applicable net namespace
214162306a36Sopenharmony_ci *	@family: protocol family
214262306a36Sopenharmony_ci *	@priority: for allocation (%GFP_KERNEL, %GFP_ATOMIC, etc)
214362306a36Sopenharmony_ci *	@prot: struct proto associated with this new sock instance
214462306a36Sopenharmony_ci *	@kern: is this to be a kernel socket?
214562306a36Sopenharmony_ci */
214662306a36Sopenharmony_cistruct sock *sk_alloc(struct net *net, int family, gfp_t priority,
214762306a36Sopenharmony_ci		      struct proto *prot, int kern)
214862306a36Sopenharmony_ci{
214962306a36Sopenharmony_ci	struct sock *sk;
215062306a36Sopenharmony_ci
215162306a36Sopenharmony_ci	sk = sk_prot_alloc(prot, priority | __GFP_ZERO, family);
215262306a36Sopenharmony_ci	if (sk) {
215362306a36Sopenharmony_ci		sk->sk_family = family;
215462306a36Sopenharmony_ci		/*
215562306a36Sopenharmony_ci		 * See comment in struct sock definition to understand
215662306a36Sopenharmony_ci		 * why we need sk_prot_creator -acme
215762306a36Sopenharmony_ci		 */
215862306a36Sopenharmony_ci		sk->sk_prot = sk->sk_prot_creator = prot;
215962306a36Sopenharmony_ci		sk->sk_kern_sock = kern;
216062306a36Sopenharmony_ci		sock_lock_init(sk);
216162306a36Sopenharmony_ci		sk->sk_net_refcnt = kern ? 0 : 1;
216262306a36Sopenharmony_ci		if (likely(sk->sk_net_refcnt)) {
216362306a36Sopenharmony_ci			get_net_track(net, &sk->ns_tracker, priority);
216462306a36Sopenharmony_ci			sock_inuse_add(net, 1);
216562306a36Sopenharmony_ci		} else {
216662306a36Sopenharmony_ci			__netns_tracker_alloc(net, &sk->ns_tracker,
216762306a36Sopenharmony_ci					      false, priority);
216862306a36Sopenharmony_ci		}
216962306a36Sopenharmony_ci
217062306a36Sopenharmony_ci		sock_net_set(sk, net);
217162306a36Sopenharmony_ci		refcount_set(&sk->sk_wmem_alloc, 1);
217262306a36Sopenharmony_ci
217362306a36Sopenharmony_ci		mem_cgroup_sk_alloc(sk);
217462306a36Sopenharmony_ci		cgroup_sk_alloc(&sk->sk_cgrp_data);
217562306a36Sopenharmony_ci		sock_update_classid(&sk->sk_cgrp_data);
217662306a36Sopenharmony_ci		sock_update_netprioidx(&sk->sk_cgrp_data);
217762306a36Sopenharmony_ci		sk_tx_queue_clear(sk);
217862306a36Sopenharmony_ci	}
217962306a36Sopenharmony_ci
218062306a36Sopenharmony_ci	return sk;
218162306a36Sopenharmony_ci}
218262306a36Sopenharmony_ciEXPORT_SYMBOL(sk_alloc);
218362306a36Sopenharmony_ci
218462306a36Sopenharmony_ci/* Sockets having SOCK_RCU_FREE will call this function after one RCU
218562306a36Sopenharmony_ci * grace period. This is the case for UDP sockets and TCP listeners.
218662306a36Sopenharmony_ci */
218762306a36Sopenharmony_cistatic void __sk_destruct(struct rcu_head *head)
218862306a36Sopenharmony_ci{
218962306a36Sopenharmony_ci	struct sock *sk = container_of(head, struct sock, sk_rcu);
219062306a36Sopenharmony_ci	struct sk_filter *filter;
219162306a36Sopenharmony_ci
219262306a36Sopenharmony_ci	if (sk->sk_destruct)
219362306a36Sopenharmony_ci		sk->sk_destruct(sk);
219462306a36Sopenharmony_ci
219562306a36Sopenharmony_ci	filter = rcu_dereference_check(sk->sk_filter,
219662306a36Sopenharmony_ci				       refcount_read(&sk->sk_wmem_alloc) == 0);
219762306a36Sopenharmony_ci	if (filter) {
219862306a36Sopenharmony_ci		sk_filter_uncharge(sk, filter);
219962306a36Sopenharmony_ci		RCU_INIT_POINTER(sk->sk_filter, NULL);
220062306a36Sopenharmony_ci	}
220162306a36Sopenharmony_ci
220262306a36Sopenharmony_ci	sock_disable_timestamp(sk, SK_FLAGS_TIMESTAMP);
220362306a36Sopenharmony_ci
220462306a36Sopenharmony_ci#ifdef CONFIG_BPF_SYSCALL
220562306a36Sopenharmony_ci	bpf_sk_storage_free(sk);
220662306a36Sopenharmony_ci#endif
220762306a36Sopenharmony_ci
220862306a36Sopenharmony_ci	if (atomic_read(&sk->sk_omem_alloc))
220962306a36Sopenharmony_ci		pr_debug("%s: optmem leakage (%d bytes) detected\n",
221062306a36Sopenharmony_ci			 __func__, atomic_read(&sk->sk_omem_alloc));
221162306a36Sopenharmony_ci
221262306a36Sopenharmony_ci	if (sk->sk_frag.page) {
221362306a36Sopenharmony_ci		put_page(sk->sk_frag.page);
221462306a36Sopenharmony_ci		sk->sk_frag.page = NULL;
221562306a36Sopenharmony_ci	}
221662306a36Sopenharmony_ci
221762306a36Sopenharmony_ci	/* We do not need to acquire sk->sk_peer_lock, we are the last user. */
221862306a36Sopenharmony_ci	put_cred(sk->sk_peer_cred);
221962306a36Sopenharmony_ci	put_pid(sk->sk_peer_pid);
222062306a36Sopenharmony_ci
222162306a36Sopenharmony_ci	if (likely(sk->sk_net_refcnt))
222262306a36Sopenharmony_ci		put_net_track(sock_net(sk), &sk->ns_tracker);
222362306a36Sopenharmony_ci	else
222462306a36Sopenharmony_ci		__netns_tracker_free(sock_net(sk), &sk->ns_tracker, false);
222562306a36Sopenharmony_ci
222662306a36Sopenharmony_ci	sk_prot_free(sk->sk_prot_creator, sk);
222762306a36Sopenharmony_ci}
222862306a36Sopenharmony_ci
222962306a36Sopenharmony_civoid sk_destruct(struct sock *sk)
223062306a36Sopenharmony_ci{
223162306a36Sopenharmony_ci	bool use_call_rcu = sock_flag(sk, SOCK_RCU_FREE);
223262306a36Sopenharmony_ci
223362306a36Sopenharmony_ci	if (rcu_access_pointer(sk->sk_reuseport_cb)) {
223462306a36Sopenharmony_ci		reuseport_detach_sock(sk);
223562306a36Sopenharmony_ci		use_call_rcu = true;
223662306a36Sopenharmony_ci	}
223762306a36Sopenharmony_ci
223862306a36Sopenharmony_ci	if (use_call_rcu)
223962306a36Sopenharmony_ci		call_rcu(&sk->sk_rcu, __sk_destruct);
224062306a36Sopenharmony_ci	else
224162306a36Sopenharmony_ci		__sk_destruct(&sk->sk_rcu);
224262306a36Sopenharmony_ci}
224362306a36Sopenharmony_ci
224462306a36Sopenharmony_cistatic void __sk_free(struct sock *sk)
224562306a36Sopenharmony_ci{
224662306a36Sopenharmony_ci	if (likely(sk->sk_net_refcnt))
224762306a36Sopenharmony_ci		sock_inuse_add(sock_net(sk), -1);
224862306a36Sopenharmony_ci
224962306a36Sopenharmony_ci	if (unlikely(sk->sk_net_refcnt && sock_diag_has_destroy_listeners(sk)))
225062306a36Sopenharmony_ci		sock_diag_broadcast_destroy(sk);
225162306a36Sopenharmony_ci	else
225262306a36Sopenharmony_ci		sk_destruct(sk);
225362306a36Sopenharmony_ci}
225462306a36Sopenharmony_ci
225562306a36Sopenharmony_civoid sk_free(struct sock *sk)
225662306a36Sopenharmony_ci{
225762306a36Sopenharmony_ci	/*
225862306a36Sopenharmony_ci	 * We subtract one from sk_wmem_alloc and can know if
225962306a36Sopenharmony_ci	 * some packets are still in some tx queue.
226062306a36Sopenharmony_ci	 * If not null, sock_wfree() will call __sk_free(sk) later
226162306a36Sopenharmony_ci	 */
226262306a36Sopenharmony_ci	if (refcount_dec_and_test(&sk->sk_wmem_alloc))
226362306a36Sopenharmony_ci		__sk_free(sk);
226462306a36Sopenharmony_ci}
226562306a36Sopenharmony_ciEXPORT_SYMBOL(sk_free);
226662306a36Sopenharmony_ci
226762306a36Sopenharmony_cistatic void sk_init_common(struct sock *sk)
226862306a36Sopenharmony_ci{
226962306a36Sopenharmony_ci	skb_queue_head_init(&sk->sk_receive_queue);
227062306a36Sopenharmony_ci	skb_queue_head_init(&sk->sk_write_queue);
227162306a36Sopenharmony_ci	skb_queue_head_init(&sk->sk_error_queue);
227262306a36Sopenharmony_ci
227362306a36Sopenharmony_ci	rwlock_init(&sk->sk_callback_lock);
227462306a36Sopenharmony_ci	lockdep_set_class_and_name(&sk->sk_receive_queue.lock,
227562306a36Sopenharmony_ci			af_rlock_keys + sk->sk_family,
227662306a36Sopenharmony_ci			af_family_rlock_key_strings[sk->sk_family]);
227762306a36Sopenharmony_ci	lockdep_set_class_and_name(&sk->sk_write_queue.lock,
227862306a36Sopenharmony_ci			af_wlock_keys + sk->sk_family,
227962306a36Sopenharmony_ci			af_family_wlock_key_strings[sk->sk_family]);
228062306a36Sopenharmony_ci	lockdep_set_class_and_name(&sk->sk_error_queue.lock,
228162306a36Sopenharmony_ci			af_elock_keys + sk->sk_family,
228262306a36Sopenharmony_ci			af_family_elock_key_strings[sk->sk_family]);
228362306a36Sopenharmony_ci	lockdep_set_class_and_name(&sk->sk_callback_lock,
228462306a36Sopenharmony_ci			af_callback_keys + sk->sk_family,
228562306a36Sopenharmony_ci			af_family_clock_key_strings[sk->sk_family]);
228662306a36Sopenharmony_ci}
228762306a36Sopenharmony_ci
228862306a36Sopenharmony_ci/**
228962306a36Sopenharmony_ci *	sk_clone_lock - clone a socket, and lock its clone
229062306a36Sopenharmony_ci *	@sk: the socket to clone
229162306a36Sopenharmony_ci *	@priority: for allocation (%GFP_KERNEL, %GFP_ATOMIC, etc)
229262306a36Sopenharmony_ci *
229362306a36Sopenharmony_ci *	Caller must unlock socket even in error path (bh_unlock_sock(newsk))
229462306a36Sopenharmony_ci */
229562306a36Sopenharmony_cistruct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
229662306a36Sopenharmony_ci{
229762306a36Sopenharmony_ci	struct proto *prot = READ_ONCE(sk->sk_prot);
229862306a36Sopenharmony_ci	struct sk_filter *filter;
229962306a36Sopenharmony_ci	bool is_charged = true;
230062306a36Sopenharmony_ci	struct sock *newsk;
230162306a36Sopenharmony_ci
230262306a36Sopenharmony_ci	newsk = sk_prot_alloc(prot, priority, sk->sk_family);
230362306a36Sopenharmony_ci	if (!newsk)
230462306a36Sopenharmony_ci		goto out;
230562306a36Sopenharmony_ci
230662306a36Sopenharmony_ci	sock_copy(newsk, sk);
230762306a36Sopenharmony_ci
230862306a36Sopenharmony_ci	newsk->sk_prot_creator = prot;
230962306a36Sopenharmony_ci
231062306a36Sopenharmony_ci	/* SANITY */
231162306a36Sopenharmony_ci	if (likely(newsk->sk_net_refcnt)) {
231262306a36Sopenharmony_ci		get_net_track(sock_net(newsk), &newsk->ns_tracker, priority);
231362306a36Sopenharmony_ci		sock_inuse_add(sock_net(newsk), 1);
231462306a36Sopenharmony_ci	} else {
231562306a36Sopenharmony_ci		/* Kernel sockets are not elevating the struct net refcount.
231662306a36Sopenharmony_ci		 * Instead, use a tracker to more easily detect if a layer
231762306a36Sopenharmony_ci		 * is not properly dismantling its kernel sockets at netns
231862306a36Sopenharmony_ci		 * destroy time.
231962306a36Sopenharmony_ci		 */
232062306a36Sopenharmony_ci		__netns_tracker_alloc(sock_net(newsk), &newsk->ns_tracker,
232162306a36Sopenharmony_ci				      false, priority);
232262306a36Sopenharmony_ci	}
232362306a36Sopenharmony_ci	sk_node_init(&newsk->sk_node);
232462306a36Sopenharmony_ci	sock_lock_init(newsk);
232562306a36Sopenharmony_ci	bh_lock_sock(newsk);
232662306a36Sopenharmony_ci	newsk->sk_backlog.head	= newsk->sk_backlog.tail = NULL;
232762306a36Sopenharmony_ci	newsk->sk_backlog.len = 0;
232862306a36Sopenharmony_ci
232962306a36Sopenharmony_ci	atomic_set(&newsk->sk_rmem_alloc, 0);
233062306a36Sopenharmony_ci
233162306a36Sopenharmony_ci	/* sk_wmem_alloc set to one (see sk_free() and sock_wfree()) */
233262306a36Sopenharmony_ci	refcount_set(&newsk->sk_wmem_alloc, 1);
233362306a36Sopenharmony_ci
233462306a36Sopenharmony_ci	atomic_set(&newsk->sk_omem_alloc, 0);
233562306a36Sopenharmony_ci	sk_init_common(newsk);
233662306a36Sopenharmony_ci
233762306a36Sopenharmony_ci	newsk->sk_dst_cache	= NULL;
233862306a36Sopenharmony_ci	newsk->sk_dst_pending_confirm = 0;
233962306a36Sopenharmony_ci	newsk->sk_wmem_queued	= 0;
234062306a36Sopenharmony_ci	newsk->sk_forward_alloc = 0;
234162306a36Sopenharmony_ci	newsk->sk_reserved_mem  = 0;
234262306a36Sopenharmony_ci	atomic_set(&newsk->sk_drops, 0);
234362306a36Sopenharmony_ci	newsk->sk_send_head	= NULL;
234462306a36Sopenharmony_ci	newsk->sk_userlocks	= sk->sk_userlocks & ~SOCK_BINDPORT_LOCK;
234562306a36Sopenharmony_ci	atomic_set(&newsk->sk_zckey, 0);
234662306a36Sopenharmony_ci
234762306a36Sopenharmony_ci	sock_reset_flag(newsk, SOCK_DONE);
234862306a36Sopenharmony_ci
234962306a36Sopenharmony_ci	/* sk->sk_memcg will be populated at accept() time */
235062306a36Sopenharmony_ci	newsk->sk_memcg = NULL;
235162306a36Sopenharmony_ci
235262306a36Sopenharmony_ci	cgroup_sk_clone(&newsk->sk_cgrp_data);
235362306a36Sopenharmony_ci
235462306a36Sopenharmony_ci	rcu_read_lock();
235562306a36Sopenharmony_ci	filter = rcu_dereference(sk->sk_filter);
235662306a36Sopenharmony_ci	if (filter != NULL)
235762306a36Sopenharmony_ci		/* though it's an empty new sock, the charging may fail
235862306a36Sopenharmony_ci		 * if sysctl_optmem_max was changed between creation of
235962306a36Sopenharmony_ci		 * original socket and cloning
236062306a36Sopenharmony_ci		 */
236162306a36Sopenharmony_ci		is_charged = sk_filter_charge(newsk, filter);
236262306a36Sopenharmony_ci	RCU_INIT_POINTER(newsk->sk_filter, filter);
236362306a36Sopenharmony_ci	rcu_read_unlock();
236462306a36Sopenharmony_ci
236562306a36Sopenharmony_ci	if (unlikely(!is_charged || xfrm_sk_clone_policy(newsk, sk))) {
236662306a36Sopenharmony_ci		/* We need to make sure that we don't uncharge the new
236762306a36Sopenharmony_ci		 * socket if we couldn't charge it in the first place
236862306a36Sopenharmony_ci		 * as otherwise we uncharge the parent's filter.
236962306a36Sopenharmony_ci		 */
237062306a36Sopenharmony_ci		if (!is_charged)
237162306a36Sopenharmony_ci			RCU_INIT_POINTER(newsk->sk_filter, NULL);
237262306a36Sopenharmony_ci		sk_free_unlock_clone(newsk);
237362306a36Sopenharmony_ci		newsk = NULL;
237462306a36Sopenharmony_ci		goto out;
237562306a36Sopenharmony_ci	}
237662306a36Sopenharmony_ci	RCU_INIT_POINTER(newsk->sk_reuseport_cb, NULL);
237762306a36Sopenharmony_ci
237862306a36Sopenharmony_ci	if (bpf_sk_storage_clone(sk, newsk)) {
237962306a36Sopenharmony_ci		sk_free_unlock_clone(newsk);
238062306a36Sopenharmony_ci		newsk = NULL;
238162306a36Sopenharmony_ci		goto out;
238262306a36Sopenharmony_ci	}
238362306a36Sopenharmony_ci
238462306a36Sopenharmony_ci	/* Clear sk_user_data if parent had the pointer tagged
238562306a36Sopenharmony_ci	 * as not suitable for copying when cloning.
238662306a36Sopenharmony_ci	 */
238762306a36Sopenharmony_ci	if (sk_user_data_is_nocopy(newsk))
238862306a36Sopenharmony_ci		newsk->sk_user_data = NULL;
238962306a36Sopenharmony_ci
239062306a36Sopenharmony_ci	newsk->sk_err	   = 0;
239162306a36Sopenharmony_ci	newsk->sk_err_soft = 0;
239262306a36Sopenharmony_ci	newsk->sk_priority = 0;
239362306a36Sopenharmony_ci	newsk->sk_incoming_cpu = raw_smp_processor_id();
239462306a36Sopenharmony_ci
239562306a36Sopenharmony_ci	/* Before updating sk_refcnt, we must commit prior changes to memory
239662306a36Sopenharmony_ci	 * (Documentation/RCU/rculist_nulls.rst for details)
239762306a36Sopenharmony_ci	 */
239862306a36Sopenharmony_ci	smp_wmb();
239962306a36Sopenharmony_ci	refcount_set(&newsk->sk_refcnt, 2);
240062306a36Sopenharmony_ci
240162306a36Sopenharmony_ci	sk_set_socket(newsk, NULL);
240262306a36Sopenharmony_ci	sk_tx_queue_clear(newsk);
240362306a36Sopenharmony_ci	RCU_INIT_POINTER(newsk->sk_wq, NULL);
240462306a36Sopenharmony_ci
240562306a36Sopenharmony_ci	if (newsk->sk_prot->sockets_allocated)
240662306a36Sopenharmony_ci		sk_sockets_allocated_inc(newsk);
240762306a36Sopenharmony_ci
240862306a36Sopenharmony_ci	if (sock_needs_netstamp(sk) && newsk->sk_flags & SK_FLAGS_TIMESTAMP)
240962306a36Sopenharmony_ci		net_enable_timestamp();
241062306a36Sopenharmony_ciout:
241162306a36Sopenharmony_ci	return newsk;
241262306a36Sopenharmony_ci}
241362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(sk_clone_lock);
241462306a36Sopenharmony_ci
241562306a36Sopenharmony_civoid sk_free_unlock_clone(struct sock *sk)
241662306a36Sopenharmony_ci{
241762306a36Sopenharmony_ci	/* It is still raw copy of parent, so invalidate
241862306a36Sopenharmony_ci	 * destructor and make plain sk_free() */
241962306a36Sopenharmony_ci	sk->sk_destruct = NULL;
242062306a36Sopenharmony_ci	bh_unlock_sock(sk);
242162306a36Sopenharmony_ci	sk_free(sk);
242262306a36Sopenharmony_ci}
242362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(sk_free_unlock_clone);
242462306a36Sopenharmony_ci
242562306a36Sopenharmony_cistatic u32 sk_dst_gso_max_size(struct sock *sk, struct dst_entry *dst)
242662306a36Sopenharmony_ci{
242762306a36Sopenharmony_ci	bool is_ipv6 = false;
242862306a36Sopenharmony_ci	u32 max_size;
242962306a36Sopenharmony_ci
243062306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_IPV6)
243162306a36Sopenharmony_ci	is_ipv6 = (sk->sk_family == AF_INET6 &&
243262306a36Sopenharmony_ci		   !ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr));
243362306a36Sopenharmony_ci#endif
243462306a36Sopenharmony_ci	/* pairs with the WRITE_ONCE() in netif_set_gso(_ipv4)_max_size() */
243562306a36Sopenharmony_ci	max_size = is_ipv6 ? READ_ONCE(dst->dev->gso_max_size) :
243662306a36Sopenharmony_ci			READ_ONCE(dst->dev->gso_ipv4_max_size);
243762306a36Sopenharmony_ci	if (max_size > GSO_LEGACY_MAX_SIZE && !sk_is_tcp(sk))
243862306a36Sopenharmony_ci		max_size = GSO_LEGACY_MAX_SIZE;
243962306a36Sopenharmony_ci
244062306a36Sopenharmony_ci	return max_size - (MAX_TCP_HEADER + 1);
244162306a36Sopenharmony_ci}
244262306a36Sopenharmony_ci
244362306a36Sopenharmony_civoid sk_setup_caps(struct sock *sk, struct dst_entry *dst)
244462306a36Sopenharmony_ci{
244562306a36Sopenharmony_ci	u32 max_segs = 1;
244662306a36Sopenharmony_ci
244762306a36Sopenharmony_ci	sk->sk_route_caps = dst->dev->features;
244862306a36Sopenharmony_ci	if (sk_is_tcp(sk))
244962306a36Sopenharmony_ci		sk->sk_route_caps |= NETIF_F_GSO;
245062306a36Sopenharmony_ci	if (sk->sk_route_caps & NETIF_F_GSO)
245162306a36Sopenharmony_ci		sk->sk_route_caps |= NETIF_F_GSO_SOFTWARE;
245262306a36Sopenharmony_ci	if (unlikely(sk->sk_gso_disabled))
245362306a36Sopenharmony_ci		sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
245462306a36Sopenharmony_ci	if (sk_can_gso(sk)) {
245562306a36Sopenharmony_ci		if (dst->header_len && !xfrm_dst_offload_ok(dst)) {
245662306a36Sopenharmony_ci			sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
245762306a36Sopenharmony_ci		} else {
245862306a36Sopenharmony_ci			sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM;
245962306a36Sopenharmony_ci			sk->sk_gso_max_size = sk_dst_gso_max_size(sk, dst);
246062306a36Sopenharmony_ci			/* pairs with the WRITE_ONCE() in netif_set_gso_max_segs() */
246162306a36Sopenharmony_ci			max_segs = max_t(u32, READ_ONCE(dst->dev->gso_max_segs), 1);
246262306a36Sopenharmony_ci		}
246362306a36Sopenharmony_ci	}
246462306a36Sopenharmony_ci	sk->sk_gso_max_segs = max_segs;
246562306a36Sopenharmony_ci	sk_dst_set(sk, dst);
246662306a36Sopenharmony_ci}
246762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(sk_setup_caps);
246862306a36Sopenharmony_ci
246962306a36Sopenharmony_ci/*
247062306a36Sopenharmony_ci *	Simple resource managers for sockets.
247162306a36Sopenharmony_ci */
247262306a36Sopenharmony_ci
247362306a36Sopenharmony_ci
247462306a36Sopenharmony_ci/*
247562306a36Sopenharmony_ci * Write buffer destructor automatically called from kfree_skb.
247662306a36Sopenharmony_ci */
247762306a36Sopenharmony_civoid sock_wfree(struct sk_buff *skb)
247862306a36Sopenharmony_ci{
247962306a36Sopenharmony_ci	struct sock *sk = skb->sk;
248062306a36Sopenharmony_ci	unsigned int len = skb->truesize;
248162306a36Sopenharmony_ci	bool free;
248262306a36Sopenharmony_ci
248362306a36Sopenharmony_ci	if (!sock_flag(sk, SOCK_USE_WRITE_QUEUE)) {
248462306a36Sopenharmony_ci		if (sock_flag(sk, SOCK_RCU_FREE) &&
248562306a36Sopenharmony_ci		    sk->sk_write_space == sock_def_write_space) {
248662306a36Sopenharmony_ci			rcu_read_lock();
248762306a36Sopenharmony_ci			free = refcount_sub_and_test(len, &sk->sk_wmem_alloc);
248862306a36Sopenharmony_ci			sock_def_write_space_wfree(sk);
248962306a36Sopenharmony_ci			rcu_read_unlock();
249062306a36Sopenharmony_ci			if (unlikely(free))
249162306a36Sopenharmony_ci				__sk_free(sk);
249262306a36Sopenharmony_ci			return;
249362306a36Sopenharmony_ci		}
249462306a36Sopenharmony_ci
249562306a36Sopenharmony_ci		/*
249662306a36Sopenharmony_ci		 * Keep a reference on sk_wmem_alloc, this will be released
249762306a36Sopenharmony_ci		 * after sk_write_space() call
249862306a36Sopenharmony_ci		 */
249962306a36Sopenharmony_ci		WARN_ON(refcount_sub_and_test(len - 1, &sk->sk_wmem_alloc));
250062306a36Sopenharmony_ci		sk->sk_write_space(sk);
250162306a36Sopenharmony_ci		len = 1;
250262306a36Sopenharmony_ci	}
250362306a36Sopenharmony_ci	/*
250462306a36Sopenharmony_ci	 * if sk_wmem_alloc reaches 0, we must finish what sk_free()
250562306a36Sopenharmony_ci	 * could not do because of in-flight packets
250662306a36Sopenharmony_ci	 */
250762306a36Sopenharmony_ci	if (refcount_sub_and_test(len, &sk->sk_wmem_alloc))
250862306a36Sopenharmony_ci		__sk_free(sk);
250962306a36Sopenharmony_ci}
251062306a36Sopenharmony_ciEXPORT_SYMBOL(sock_wfree);
251162306a36Sopenharmony_ci
251262306a36Sopenharmony_ci/* This variant of sock_wfree() is used by TCP,
251362306a36Sopenharmony_ci * since it sets SOCK_USE_WRITE_QUEUE.
251462306a36Sopenharmony_ci */
251562306a36Sopenharmony_civoid __sock_wfree(struct sk_buff *skb)
251662306a36Sopenharmony_ci{
251762306a36Sopenharmony_ci	struct sock *sk = skb->sk;
251862306a36Sopenharmony_ci
251962306a36Sopenharmony_ci	if (refcount_sub_and_test(skb->truesize, &sk->sk_wmem_alloc))
252062306a36Sopenharmony_ci		__sk_free(sk);
252162306a36Sopenharmony_ci}
252262306a36Sopenharmony_ci
252362306a36Sopenharmony_civoid skb_set_owner_w(struct sk_buff *skb, struct sock *sk)
252462306a36Sopenharmony_ci{
252562306a36Sopenharmony_ci	skb_orphan(skb);
252662306a36Sopenharmony_ci	skb->sk = sk;
252762306a36Sopenharmony_ci#ifdef CONFIG_INET
252862306a36Sopenharmony_ci	if (unlikely(!sk_fullsock(sk))) {
252962306a36Sopenharmony_ci		skb->destructor = sock_edemux;
253062306a36Sopenharmony_ci		sock_hold(sk);
253162306a36Sopenharmony_ci		return;
253262306a36Sopenharmony_ci	}
253362306a36Sopenharmony_ci#endif
253462306a36Sopenharmony_ci	skb->destructor = sock_wfree;
253562306a36Sopenharmony_ci	skb_set_hash_from_sk(skb, sk);
253662306a36Sopenharmony_ci	/*
253762306a36Sopenharmony_ci	 * We used to take a refcount on sk, but following operation
253862306a36Sopenharmony_ci	 * is enough to guarantee sk_free() wont free this sock until
253962306a36Sopenharmony_ci	 * all in-flight packets are completed
254062306a36Sopenharmony_ci	 */
254162306a36Sopenharmony_ci	refcount_add(skb->truesize, &sk->sk_wmem_alloc);
254262306a36Sopenharmony_ci}
254362306a36Sopenharmony_ciEXPORT_SYMBOL(skb_set_owner_w);
254462306a36Sopenharmony_ci
254562306a36Sopenharmony_cistatic bool can_skb_orphan_partial(const struct sk_buff *skb)
254662306a36Sopenharmony_ci{
254762306a36Sopenharmony_ci#ifdef CONFIG_TLS_DEVICE
254862306a36Sopenharmony_ci	/* Drivers depend on in-order delivery for crypto offload,
254962306a36Sopenharmony_ci	 * partial orphan breaks out-of-order-OK logic.
255062306a36Sopenharmony_ci	 */
255162306a36Sopenharmony_ci	if (skb->decrypted)
255262306a36Sopenharmony_ci		return false;
255362306a36Sopenharmony_ci#endif
255462306a36Sopenharmony_ci	return (skb->destructor == sock_wfree ||
255562306a36Sopenharmony_ci		(IS_ENABLED(CONFIG_INET) && skb->destructor == tcp_wfree));
255662306a36Sopenharmony_ci}
255762306a36Sopenharmony_ci
255862306a36Sopenharmony_ci/* This helper is used by netem, as it can hold packets in its
255962306a36Sopenharmony_ci * delay queue. We want to allow the owner socket to send more
256062306a36Sopenharmony_ci * packets, as if they were already TX completed by a typical driver.
256162306a36Sopenharmony_ci * But we also want to keep skb->sk set because some packet schedulers
256262306a36Sopenharmony_ci * rely on it (sch_fq for example).
256362306a36Sopenharmony_ci */
256462306a36Sopenharmony_civoid skb_orphan_partial(struct sk_buff *skb)
256562306a36Sopenharmony_ci{
256662306a36Sopenharmony_ci	if (skb_is_tcp_pure_ack(skb))
256762306a36Sopenharmony_ci		return;
256862306a36Sopenharmony_ci
256962306a36Sopenharmony_ci	if (can_skb_orphan_partial(skb) && skb_set_owner_sk_safe(skb, skb->sk))
257062306a36Sopenharmony_ci		return;
257162306a36Sopenharmony_ci
257262306a36Sopenharmony_ci	skb_orphan(skb);
257362306a36Sopenharmony_ci}
257462306a36Sopenharmony_ciEXPORT_SYMBOL(skb_orphan_partial);
257562306a36Sopenharmony_ci
257662306a36Sopenharmony_ci/*
257762306a36Sopenharmony_ci * Read buffer destructor automatically called from kfree_skb.
257862306a36Sopenharmony_ci */
257962306a36Sopenharmony_civoid sock_rfree(struct sk_buff *skb)
258062306a36Sopenharmony_ci{
258162306a36Sopenharmony_ci	struct sock *sk = skb->sk;
258262306a36Sopenharmony_ci	unsigned int len = skb->truesize;
258362306a36Sopenharmony_ci
258462306a36Sopenharmony_ci	atomic_sub(len, &sk->sk_rmem_alloc);
258562306a36Sopenharmony_ci	sk_mem_uncharge(sk, len);
258662306a36Sopenharmony_ci}
258762306a36Sopenharmony_ciEXPORT_SYMBOL(sock_rfree);
258862306a36Sopenharmony_ci
258962306a36Sopenharmony_ci/*
259062306a36Sopenharmony_ci * Buffer destructor for skbs that are not used directly in read or write
259162306a36Sopenharmony_ci * path, e.g. for error handler skbs. Automatically called from kfree_skb.
259262306a36Sopenharmony_ci */
259362306a36Sopenharmony_civoid sock_efree(struct sk_buff *skb)
259462306a36Sopenharmony_ci{
259562306a36Sopenharmony_ci	sock_put(skb->sk);
259662306a36Sopenharmony_ci}
259762306a36Sopenharmony_ciEXPORT_SYMBOL(sock_efree);
259862306a36Sopenharmony_ci
259962306a36Sopenharmony_ci/* Buffer destructor for prefetch/receive path where reference count may
260062306a36Sopenharmony_ci * not be held, e.g. for listen sockets.
260162306a36Sopenharmony_ci */
260262306a36Sopenharmony_ci#ifdef CONFIG_INET
260362306a36Sopenharmony_civoid sock_pfree(struct sk_buff *skb)
260462306a36Sopenharmony_ci{
260562306a36Sopenharmony_ci	if (sk_is_refcounted(skb->sk))
260662306a36Sopenharmony_ci		sock_gen_put(skb->sk);
260762306a36Sopenharmony_ci}
260862306a36Sopenharmony_ciEXPORT_SYMBOL(sock_pfree);
260962306a36Sopenharmony_ci#endif /* CONFIG_INET */
261062306a36Sopenharmony_ci
261162306a36Sopenharmony_cikuid_t sock_i_uid(struct sock *sk)
261262306a36Sopenharmony_ci{
261362306a36Sopenharmony_ci	kuid_t uid;
261462306a36Sopenharmony_ci
261562306a36Sopenharmony_ci	read_lock_bh(&sk->sk_callback_lock);
261662306a36Sopenharmony_ci	uid = sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_uid : GLOBAL_ROOT_UID;
261762306a36Sopenharmony_ci	read_unlock_bh(&sk->sk_callback_lock);
261862306a36Sopenharmony_ci	return uid;
261962306a36Sopenharmony_ci}
262062306a36Sopenharmony_ciEXPORT_SYMBOL(sock_i_uid);
262162306a36Sopenharmony_ci
262262306a36Sopenharmony_ciunsigned long __sock_i_ino(struct sock *sk)
262362306a36Sopenharmony_ci{
262462306a36Sopenharmony_ci	unsigned long ino;
262562306a36Sopenharmony_ci
262662306a36Sopenharmony_ci	read_lock(&sk->sk_callback_lock);
262762306a36Sopenharmony_ci	ino = sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_ino : 0;
262862306a36Sopenharmony_ci	read_unlock(&sk->sk_callback_lock);
262962306a36Sopenharmony_ci	return ino;
263062306a36Sopenharmony_ci}
263162306a36Sopenharmony_ciEXPORT_SYMBOL(__sock_i_ino);
263262306a36Sopenharmony_ci
263362306a36Sopenharmony_ciunsigned long sock_i_ino(struct sock *sk)
263462306a36Sopenharmony_ci{
263562306a36Sopenharmony_ci	unsigned long ino;
263662306a36Sopenharmony_ci
263762306a36Sopenharmony_ci	local_bh_disable();
263862306a36Sopenharmony_ci	ino = __sock_i_ino(sk);
263962306a36Sopenharmony_ci	local_bh_enable();
264062306a36Sopenharmony_ci	return ino;
264162306a36Sopenharmony_ci}
264262306a36Sopenharmony_ciEXPORT_SYMBOL(sock_i_ino);
264362306a36Sopenharmony_ci
264462306a36Sopenharmony_ci/*
264562306a36Sopenharmony_ci * Allocate a skb from the socket's send buffer.
264662306a36Sopenharmony_ci */
264762306a36Sopenharmony_cistruct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force,
264862306a36Sopenharmony_ci			     gfp_t priority)
264962306a36Sopenharmony_ci{
265062306a36Sopenharmony_ci	if (force ||
265162306a36Sopenharmony_ci	    refcount_read(&sk->sk_wmem_alloc) < READ_ONCE(sk->sk_sndbuf)) {
265262306a36Sopenharmony_ci		struct sk_buff *skb = alloc_skb(size, priority);
265362306a36Sopenharmony_ci
265462306a36Sopenharmony_ci		if (skb) {
265562306a36Sopenharmony_ci			skb_set_owner_w(skb, sk);
265662306a36Sopenharmony_ci			return skb;
265762306a36Sopenharmony_ci		}
265862306a36Sopenharmony_ci	}
265962306a36Sopenharmony_ci	return NULL;
266062306a36Sopenharmony_ci}
266162306a36Sopenharmony_ciEXPORT_SYMBOL(sock_wmalloc);
266262306a36Sopenharmony_ci
266362306a36Sopenharmony_cistatic void sock_ofree(struct sk_buff *skb)
266462306a36Sopenharmony_ci{
266562306a36Sopenharmony_ci	struct sock *sk = skb->sk;
266662306a36Sopenharmony_ci
266762306a36Sopenharmony_ci	atomic_sub(skb->truesize, &sk->sk_omem_alloc);
266862306a36Sopenharmony_ci}
266962306a36Sopenharmony_ci
267062306a36Sopenharmony_cistruct sk_buff *sock_omalloc(struct sock *sk, unsigned long size,
267162306a36Sopenharmony_ci			     gfp_t priority)
267262306a36Sopenharmony_ci{
267362306a36Sopenharmony_ci	struct sk_buff *skb;
267462306a36Sopenharmony_ci
267562306a36Sopenharmony_ci	/* small safe race: SKB_TRUESIZE may differ from final skb->truesize */
267662306a36Sopenharmony_ci	if (atomic_read(&sk->sk_omem_alloc) + SKB_TRUESIZE(size) >
267762306a36Sopenharmony_ci	    READ_ONCE(sysctl_optmem_max))
267862306a36Sopenharmony_ci		return NULL;
267962306a36Sopenharmony_ci
268062306a36Sopenharmony_ci	skb = alloc_skb(size, priority);
268162306a36Sopenharmony_ci	if (!skb)
268262306a36Sopenharmony_ci		return NULL;
268362306a36Sopenharmony_ci
268462306a36Sopenharmony_ci	atomic_add(skb->truesize, &sk->sk_omem_alloc);
268562306a36Sopenharmony_ci	skb->sk = sk;
268662306a36Sopenharmony_ci	skb->destructor = sock_ofree;
268762306a36Sopenharmony_ci	return skb;
268862306a36Sopenharmony_ci}
268962306a36Sopenharmony_ci
269062306a36Sopenharmony_ci/*
269162306a36Sopenharmony_ci * Allocate a memory block from the socket's option memory buffer.
269262306a36Sopenharmony_ci */
269362306a36Sopenharmony_civoid *sock_kmalloc(struct sock *sk, int size, gfp_t priority)
269462306a36Sopenharmony_ci{
269562306a36Sopenharmony_ci	int optmem_max = READ_ONCE(sysctl_optmem_max);
269662306a36Sopenharmony_ci
269762306a36Sopenharmony_ci	if ((unsigned int)size <= optmem_max &&
269862306a36Sopenharmony_ci	    atomic_read(&sk->sk_omem_alloc) + size < optmem_max) {
269962306a36Sopenharmony_ci		void *mem;
270062306a36Sopenharmony_ci		/* First do the add, to avoid the race if kmalloc
270162306a36Sopenharmony_ci		 * might sleep.
270262306a36Sopenharmony_ci		 */
270362306a36Sopenharmony_ci		atomic_add(size, &sk->sk_omem_alloc);
270462306a36Sopenharmony_ci		mem = kmalloc(size, priority);
270562306a36Sopenharmony_ci		if (mem)
270662306a36Sopenharmony_ci			return mem;
270762306a36Sopenharmony_ci		atomic_sub(size, &sk->sk_omem_alloc);
270862306a36Sopenharmony_ci	}
270962306a36Sopenharmony_ci	return NULL;
271062306a36Sopenharmony_ci}
271162306a36Sopenharmony_ciEXPORT_SYMBOL(sock_kmalloc);
271262306a36Sopenharmony_ci
271362306a36Sopenharmony_ci/* Free an option memory block. Note, we actually want the inline
271462306a36Sopenharmony_ci * here as this allows gcc to detect the nullify and fold away the
271562306a36Sopenharmony_ci * condition entirely.
271662306a36Sopenharmony_ci */
271762306a36Sopenharmony_cistatic inline void __sock_kfree_s(struct sock *sk, void *mem, int size,
271862306a36Sopenharmony_ci				  const bool nullify)
271962306a36Sopenharmony_ci{
272062306a36Sopenharmony_ci	if (WARN_ON_ONCE(!mem))
272162306a36Sopenharmony_ci		return;
272262306a36Sopenharmony_ci	if (nullify)
272362306a36Sopenharmony_ci		kfree_sensitive(mem);
272462306a36Sopenharmony_ci	else
272562306a36Sopenharmony_ci		kfree(mem);
272662306a36Sopenharmony_ci	atomic_sub(size, &sk->sk_omem_alloc);
272762306a36Sopenharmony_ci}
272862306a36Sopenharmony_ci
272962306a36Sopenharmony_civoid sock_kfree_s(struct sock *sk, void *mem, int size)
273062306a36Sopenharmony_ci{
273162306a36Sopenharmony_ci	__sock_kfree_s(sk, mem, size, false);
273262306a36Sopenharmony_ci}
273362306a36Sopenharmony_ciEXPORT_SYMBOL(sock_kfree_s);
273462306a36Sopenharmony_ci
273562306a36Sopenharmony_civoid sock_kzfree_s(struct sock *sk, void *mem, int size)
273662306a36Sopenharmony_ci{
273762306a36Sopenharmony_ci	__sock_kfree_s(sk, mem, size, true);
273862306a36Sopenharmony_ci}
273962306a36Sopenharmony_ciEXPORT_SYMBOL(sock_kzfree_s);
274062306a36Sopenharmony_ci
274162306a36Sopenharmony_ci/* It is almost wait_for_tcp_memory minus release_sock/lock_sock.
274262306a36Sopenharmony_ci   I think, these locks should be removed for datagram sockets.
274362306a36Sopenharmony_ci */
274462306a36Sopenharmony_cistatic long sock_wait_for_wmem(struct sock *sk, long timeo)
274562306a36Sopenharmony_ci{
274662306a36Sopenharmony_ci	DEFINE_WAIT(wait);
274762306a36Sopenharmony_ci
274862306a36Sopenharmony_ci	sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk);
274962306a36Sopenharmony_ci	for (;;) {
275062306a36Sopenharmony_ci		if (!timeo)
275162306a36Sopenharmony_ci			break;
275262306a36Sopenharmony_ci		if (signal_pending(current))
275362306a36Sopenharmony_ci			break;
275462306a36Sopenharmony_ci		set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
275562306a36Sopenharmony_ci		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
275662306a36Sopenharmony_ci		if (refcount_read(&sk->sk_wmem_alloc) < READ_ONCE(sk->sk_sndbuf))
275762306a36Sopenharmony_ci			break;
275862306a36Sopenharmony_ci		if (READ_ONCE(sk->sk_shutdown) & SEND_SHUTDOWN)
275962306a36Sopenharmony_ci			break;
276062306a36Sopenharmony_ci		if (READ_ONCE(sk->sk_err))
276162306a36Sopenharmony_ci			break;
276262306a36Sopenharmony_ci		timeo = schedule_timeout(timeo);
276362306a36Sopenharmony_ci	}
276462306a36Sopenharmony_ci	finish_wait(sk_sleep(sk), &wait);
276562306a36Sopenharmony_ci	return timeo;
276662306a36Sopenharmony_ci}
276762306a36Sopenharmony_ci
276862306a36Sopenharmony_ci
276962306a36Sopenharmony_ci/*
277062306a36Sopenharmony_ci *	Generic send/receive buffer handlers
277162306a36Sopenharmony_ci */
277262306a36Sopenharmony_ci
277362306a36Sopenharmony_cistruct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len,
277462306a36Sopenharmony_ci				     unsigned long data_len, int noblock,
277562306a36Sopenharmony_ci				     int *errcode, int max_page_order)
277662306a36Sopenharmony_ci{
277762306a36Sopenharmony_ci	struct sk_buff *skb;
277862306a36Sopenharmony_ci	long timeo;
277962306a36Sopenharmony_ci	int err;
278062306a36Sopenharmony_ci
278162306a36Sopenharmony_ci	timeo = sock_sndtimeo(sk, noblock);
278262306a36Sopenharmony_ci	for (;;) {
278362306a36Sopenharmony_ci		err = sock_error(sk);
278462306a36Sopenharmony_ci		if (err != 0)
278562306a36Sopenharmony_ci			goto failure;
278662306a36Sopenharmony_ci
278762306a36Sopenharmony_ci		err = -EPIPE;
278862306a36Sopenharmony_ci		if (READ_ONCE(sk->sk_shutdown) & SEND_SHUTDOWN)
278962306a36Sopenharmony_ci			goto failure;
279062306a36Sopenharmony_ci
279162306a36Sopenharmony_ci		if (sk_wmem_alloc_get(sk) < READ_ONCE(sk->sk_sndbuf))
279262306a36Sopenharmony_ci			break;
279362306a36Sopenharmony_ci
279462306a36Sopenharmony_ci		sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk);
279562306a36Sopenharmony_ci		set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
279662306a36Sopenharmony_ci		err = -EAGAIN;
279762306a36Sopenharmony_ci		if (!timeo)
279862306a36Sopenharmony_ci			goto failure;
279962306a36Sopenharmony_ci		if (signal_pending(current))
280062306a36Sopenharmony_ci			goto interrupted;
280162306a36Sopenharmony_ci		timeo = sock_wait_for_wmem(sk, timeo);
280262306a36Sopenharmony_ci	}
280362306a36Sopenharmony_ci	skb = alloc_skb_with_frags(header_len, data_len, max_page_order,
280462306a36Sopenharmony_ci				   errcode, sk->sk_allocation);
280562306a36Sopenharmony_ci	if (skb)
280662306a36Sopenharmony_ci		skb_set_owner_w(skb, sk);
280762306a36Sopenharmony_ci	return skb;
280862306a36Sopenharmony_ci
280962306a36Sopenharmony_ciinterrupted:
281062306a36Sopenharmony_ci	err = sock_intr_errno(timeo);
281162306a36Sopenharmony_cifailure:
281262306a36Sopenharmony_ci	*errcode = err;
281362306a36Sopenharmony_ci	return NULL;
281462306a36Sopenharmony_ci}
281562306a36Sopenharmony_ciEXPORT_SYMBOL(sock_alloc_send_pskb);
281662306a36Sopenharmony_ci
281762306a36Sopenharmony_ciint __sock_cmsg_send(struct sock *sk, struct cmsghdr *cmsg,
281862306a36Sopenharmony_ci		     struct sockcm_cookie *sockc)
281962306a36Sopenharmony_ci{
282062306a36Sopenharmony_ci	u32 tsflags;
282162306a36Sopenharmony_ci
282262306a36Sopenharmony_ci	switch (cmsg->cmsg_type) {
282362306a36Sopenharmony_ci	case SO_MARK:
282462306a36Sopenharmony_ci		if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_RAW) &&
282562306a36Sopenharmony_ci		    !ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
282662306a36Sopenharmony_ci			return -EPERM;
282762306a36Sopenharmony_ci		if (cmsg->cmsg_len != CMSG_LEN(sizeof(u32)))
282862306a36Sopenharmony_ci			return -EINVAL;
282962306a36Sopenharmony_ci		sockc->mark = *(u32 *)CMSG_DATA(cmsg);
283062306a36Sopenharmony_ci		break;
283162306a36Sopenharmony_ci	case SO_TIMESTAMPING_OLD:
283262306a36Sopenharmony_ci	case SO_TIMESTAMPING_NEW:
283362306a36Sopenharmony_ci		if (cmsg->cmsg_len != CMSG_LEN(sizeof(u32)))
283462306a36Sopenharmony_ci			return -EINVAL;
283562306a36Sopenharmony_ci
283662306a36Sopenharmony_ci		tsflags = *(u32 *)CMSG_DATA(cmsg);
283762306a36Sopenharmony_ci		if (tsflags & ~SOF_TIMESTAMPING_TX_RECORD_MASK)
283862306a36Sopenharmony_ci			return -EINVAL;
283962306a36Sopenharmony_ci
284062306a36Sopenharmony_ci		sockc->tsflags &= ~SOF_TIMESTAMPING_TX_RECORD_MASK;
284162306a36Sopenharmony_ci		sockc->tsflags |= tsflags;
284262306a36Sopenharmony_ci		break;
284362306a36Sopenharmony_ci	case SCM_TXTIME:
284462306a36Sopenharmony_ci		if (!sock_flag(sk, SOCK_TXTIME))
284562306a36Sopenharmony_ci			return -EINVAL;
284662306a36Sopenharmony_ci		if (cmsg->cmsg_len != CMSG_LEN(sizeof(u64)))
284762306a36Sopenharmony_ci			return -EINVAL;
284862306a36Sopenharmony_ci		sockc->transmit_time = get_unaligned((u64 *)CMSG_DATA(cmsg));
284962306a36Sopenharmony_ci		break;
285062306a36Sopenharmony_ci	/* SCM_RIGHTS and SCM_CREDENTIALS are semantically in SOL_UNIX. */
285162306a36Sopenharmony_ci	case SCM_RIGHTS:
285262306a36Sopenharmony_ci	case SCM_CREDENTIALS:
285362306a36Sopenharmony_ci		break;
285462306a36Sopenharmony_ci	default:
285562306a36Sopenharmony_ci		return -EINVAL;
285662306a36Sopenharmony_ci	}
285762306a36Sopenharmony_ci	return 0;
285862306a36Sopenharmony_ci}
285962306a36Sopenharmony_ciEXPORT_SYMBOL(__sock_cmsg_send);
286062306a36Sopenharmony_ci
286162306a36Sopenharmony_ciint sock_cmsg_send(struct sock *sk, struct msghdr *msg,
286262306a36Sopenharmony_ci		   struct sockcm_cookie *sockc)
286362306a36Sopenharmony_ci{
286462306a36Sopenharmony_ci	struct cmsghdr *cmsg;
286562306a36Sopenharmony_ci	int ret;
286662306a36Sopenharmony_ci
286762306a36Sopenharmony_ci	for_each_cmsghdr(cmsg, msg) {
286862306a36Sopenharmony_ci		if (!CMSG_OK(msg, cmsg))
286962306a36Sopenharmony_ci			return -EINVAL;
287062306a36Sopenharmony_ci		if (cmsg->cmsg_level != SOL_SOCKET)
287162306a36Sopenharmony_ci			continue;
287262306a36Sopenharmony_ci		ret = __sock_cmsg_send(sk, cmsg, sockc);
287362306a36Sopenharmony_ci		if (ret)
287462306a36Sopenharmony_ci			return ret;
287562306a36Sopenharmony_ci	}
287662306a36Sopenharmony_ci	return 0;
287762306a36Sopenharmony_ci}
287862306a36Sopenharmony_ciEXPORT_SYMBOL(sock_cmsg_send);
287962306a36Sopenharmony_ci
288062306a36Sopenharmony_cistatic void sk_enter_memory_pressure(struct sock *sk)
288162306a36Sopenharmony_ci{
288262306a36Sopenharmony_ci	if (!sk->sk_prot->enter_memory_pressure)
288362306a36Sopenharmony_ci		return;
288462306a36Sopenharmony_ci
288562306a36Sopenharmony_ci	sk->sk_prot->enter_memory_pressure(sk);
288662306a36Sopenharmony_ci}
288762306a36Sopenharmony_ci
288862306a36Sopenharmony_cistatic void sk_leave_memory_pressure(struct sock *sk)
288962306a36Sopenharmony_ci{
289062306a36Sopenharmony_ci	if (sk->sk_prot->leave_memory_pressure) {
289162306a36Sopenharmony_ci		INDIRECT_CALL_INET_1(sk->sk_prot->leave_memory_pressure,
289262306a36Sopenharmony_ci				     tcp_leave_memory_pressure, sk);
289362306a36Sopenharmony_ci	} else {
289462306a36Sopenharmony_ci		unsigned long *memory_pressure = sk->sk_prot->memory_pressure;
289562306a36Sopenharmony_ci
289662306a36Sopenharmony_ci		if (memory_pressure && READ_ONCE(*memory_pressure))
289762306a36Sopenharmony_ci			WRITE_ONCE(*memory_pressure, 0);
289862306a36Sopenharmony_ci	}
289962306a36Sopenharmony_ci}
290062306a36Sopenharmony_ci
290162306a36Sopenharmony_ciDEFINE_STATIC_KEY_FALSE(net_high_order_alloc_disable_key);
290262306a36Sopenharmony_ci
290362306a36Sopenharmony_ci/**
290462306a36Sopenharmony_ci * skb_page_frag_refill - check that a page_frag contains enough room
290562306a36Sopenharmony_ci * @sz: minimum size of the fragment we want to get
290662306a36Sopenharmony_ci * @pfrag: pointer to page_frag
290762306a36Sopenharmony_ci * @gfp: priority for memory allocation
290862306a36Sopenharmony_ci *
290962306a36Sopenharmony_ci * Note: While this allocator tries to use high order pages, there is
291062306a36Sopenharmony_ci * no guarantee that allocations succeed. Therefore, @sz MUST be
291162306a36Sopenharmony_ci * less or equal than PAGE_SIZE.
291262306a36Sopenharmony_ci */
291362306a36Sopenharmony_cibool skb_page_frag_refill(unsigned int sz, struct page_frag *pfrag, gfp_t gfp)
291462306a36Sopenharmony_ci{
291562306a36Sopenharmony_ci	if (pfrag->page) {
291662306a36Sopenharmony_ci		if (page_ref_count(pfrag->page) == 1) {
291762306a36Sopenharmony_ci			pfrag->offset = 0;
291862306a36Sopenharmony_ci			return true;
291962306a36Sopenharmony_ci		}
292062306a36Sopenharmony_ci		if (pfrag->offset + sz <= pfrag->size)
292162306a36Sopenharmony_ci			return true;
292262306a36Sopenharmony_ci		put_page(pfrag->page);
292362306a36Sopenharmony_ci	}
292462306a36Sopenharmony_ci
292562306a36Sopenharmony_ci	pfrag->offset = 0;
292662306a36Sopenharmony_ci	if (SKB_FRAG_PAGE_ORDER &&
292762306a36Sopenharmony_ci	    !static_branch_unlikely(&net_high_order_alloc_disable_key)) {
292862306a36Sopenharmony_ci		/* Avoid direct reclaim but allow kswapd to wake */
292962306a36Sopenharmony_ci		pfrag->page = alloc_pages((gfp & ~__GFP_DIRECT_RECLAIM) |
293062306a36Sopenharmony_ci					  __GFP_COMP | __GFP_NOWARN |
293162306a36Sopenharmony_ci					  __GFP_NORETRY,
293262306a36Sopenharmony_ci					  SKB_FRAG_PAGE_ORDER);
293362306a36Sopenharmony_ci		if (likely(pfrag->page)) {
293462306a36Sopenharmony_ci			pfrag->size = PAGE_SIZE << SKB_FRAG_PAGE_ORDER;
293562306a36Sopenharmony_ci			return true;
293662306a36Sopenharmony_ci		}
293762306a36Sopenharmony_ci	}
293862306a36Sopenharmony_ci	pfrag->page = alloc_page(gfp);
293962306a36Sopenharmony_ci	if (likely(pfrag->page)) {
294062306a36Sopenharmony_ci		pfrag->size = PAGE_SIZE;
294162306a36Sopenharmony_ci		return true;
294262306a36Sopenharmony_ci	}
294362306a36Sopenharmony_ci	return false;
294462306a36Sopenharmony_ci}
294562306a36Sopenharmony_ciEXPORT_SYMBOL(skb_page_frag_refill);
294662306a36Sopenharmony_ci
294762306a36Sopenharmony_cibool sk_page_frag_refill(struct sock *sk, struct page_frag *pfrag)
294862306a36Sopenharmony_ci{
294962306a36Sopenharmony_ci	if (likely(skb_page_frag_refill(32U, pfrag, sk->sk_allocation)))
295062306a36Sopenharmony_ci		return true;
295162306a36Sopenharmony_ci
295262306a36Sopenharmony_ci	sk_enter_memory_pressure(sk);
295362306a36Sopenharmony_ci	sk_stream_moderate_sndbuf(sk);
295462306a36Sopenharmony_ci	return false;
295562306a36Sopenharmony_ci}
295662306a36Sopenharmony_ciEXPORT_SYMBOL(sk_page_frag_refill);
295762306a36Sopenharmony_ci
295862306a36Sopenharmony_civoid __lock_sock(struct sock *sk)
295962306a36Sopenharmony_ci	__releases(&sk->sk_lock.slock)
296062306a36Sopenharmony_ci	__acquires(&sk->sk_lock.slock)
296162306a36Sopenharmony_ci{
296262306a36Sopenharmony_ci	DEFINE_WAIT(wait);
296362306a36Sopenharmony_ci
296462306a36Sopenharmony_ci	for (;;) {
296562306a36Sopenharmony_ci		prepare_to_wait_exclusive(&sk->sk_lock.wq, &wait,
296662306a36Sopenharmony_ci					TASK_UNINTERRUPTIBLE);
296762306a36Sopenharmony_ci		spin_unlock_bh(&sk->sk_lock.slock);
296862306a36Sopenharmony_ci		schedule();
296962306a36Sopenharmony_ci		spin_lock_bh(&sk->sk_lock.slock);
297062306a36Sopenharmony_ci		if (!sock_owned_by_user(sk))
297162306a36Sopenharmony_ci			break;
297262306a36Sopenharmony_ci	}
297362306a36Sopenharmony_ci	finish_wait(&sk->sk_lock.wq, &wait);
297462306a36Sopenharmony_ci}
297562306a36Sopenharmony_ci
297662306a36Sopenharmony_civoid __release_sock(struct sock *sk)
297762306a36Sopenharmony_ci	__releases(&sk->sk_lock.slock)
297862306a36Sopenharmony_ci	__acquires(&sk->sk_lock.slock)
297962306a36Sopenharmony_ci{
298062306a36Sopenharmony_ci	struct sk_buff *skb, *next;
298162306a36Sopenharmony_ci
298262306a36Sopenharmony_ci	while ((skb = sk->sk_backlog.head) != NULL) {
298362306a36Sopenharmony_ci		sk->sk_backlog.head = sk->sk_backlog.tail = NULL;
298462306a36Sopenharmony_ci
298562306a36Sopenharmony_ci		spin_unlock_bh(&sk->sk_lock.slock);
298662306a36Sopenharmony_ci
298762306a36Sopenharmony_ci		do {
298862306a36Sopenharmony_ci			next = skb->next;
298962306a36Sopenharmony_ci			prefetch(next);
299062306a36Sopenharmony_ci			DEBUG_NET_WARN_ON_ONCE(skb_dst_is_noref(skb));
299162306a36Sopenharmony_ci			skb_mark_not_on_list(skb);
299262306a36Sopenharmony_ci			sk_backlog_rcv(sk, skb);
299362306a36Sopenharmony_ci
299462306a36Sopenharmony_ci			cond_resched();
299562306a36Sopenharmony_ci
299662306a36Sopenharmony_ci			skb = next;
299762306a36Sopenharmony_ci		} while (skb != NULL);
299862306a36Sopenharmony_ci
299962306a36Sopenharmony_ci		spin_lock_bh(&sk->sk_lock.slock);
300062306a36Sopenharmony_ci	}
300162306a36Sopenharmony_ci
300262306a36Sopenharmony_ci	/*
300362306a36Sopenharmony_ci	 * Doing the zeroing here guarantee we can not loop forever
300462306a36Sopenharmony_ci	 * while a wild producer attempts to flood us.
300562306a36Sopenharmony_ci	 */
300662306a36Sopenharmony_ci	sk->sk_backlog.len = 0;
300762306a36Sopenharmony_ci}
300862306a36Sopenharmony_ci
300962306a36Sopenharmony_civoid __sk_flush_backlog(struct sock *sk)
301062306a36Sopenharmony_ci{
301162306a36Sopenharmony_ci	spin_lock_bh(&sk->sk_lock.slock);
301262306a36Sopenharmony_ci	__release_sock(sk);
301362306a36Sopenharmony_ci	spin_unlock_bh(&sk->sk_lock.slock);
301462306a36Sopenharmony_ci}
301562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(__sk_flush_backlog);
301662306a36Sopenharmony_ci
301762306a36Sopenharmony_ci/**
301862306a36Sopenharmony_ci * sk_wait_data - wait for data to arrive at sk_receive_queue
301962306a36Sopenharmony_ci * @sk:    sock to wait on
302062306a36Sopenharmony_ci * @timeo: for how long
302162306a36Sopenharmony_ci * @skb:   last skb seen on sk_receive_queue
302262306a36Sopenharmony_ci *
302362306a36Sopenharmony_ci * Now socket state including sk->sk_err is changed only under lock,
302462306a36Sopenharmony_ci * hence we may omit checks after joining wait queue.
302562306a36Sopenharmony_ci * We check receive queue before schedule() only as optimization;
302662306a36Sopenharmony_ci * it is very likely that release_sock() added new data.
302762306a36Sopenharmony_ci */
302862306a36Sopenharmony_ciint sk_wait_data(struct sock *sk, long *timeo, const struct sk_buff *skb)
302962306a36Sopenharmony_ci{
303062306a36Sopenharmony_ci	DEFINE_WAIT_FUNC(wait, woken_wake_function);
303162306a36Sopenharmony_ci	int rc;
303262306a36Sopenharmony_ci
303362306a36Sopenharmony_ci	add_wait_queue(sk_sleep(sk), &wait);
303462306a36Sopenharmony_ci	sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
303562306a36Sopenharmony_ci	rc = sk_wait_event(sk, timeo, skb_peek_tail(&sk->sk_receive_queue) != skb, &wait);
303662306a36Sopenharmony_ci	sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
303762306a36Sopenharmony_ci	remove_wait_queue(sk_sleep(sk), &wait);
303862306a36Sopenharmony_ci	return rc;
303962306a36Sopenharmony_ci}
304062306a36Sopenharmony_ciEXPORT_SYMBOL(sk_wait_data);
304162306a36Sopenharmony_ci
304262306a36Sopenharmony_ci/**
304362306a36Sopenharmony_ci *	__sk_mem_raise_allocated - increase memory_allocated
304462306a36Sopenharmony_ci *	@sk: socket
304562306a36Sopenharmony_ci *	@size: memory size to allocate
304662306a36Sopenharmony_ci *	@amt: pages to allocate
304762306a36Sopenharmony_ci *	@kind: allocation type
304862306a36Sopenharmony_ci *
304962306a36Sopenharmony_ci *	Similar to __sk_mem_schedule(), but does not update sk_forward_alloc
305062306a36Sopenharmony_ci */
305162306a36Sopenharmony_ciint __sk_mem_raise_allocated(struct sock *sk, int size, int amt, int kind)
305262306a36Sopenharmony_ci{
305362306a36Sopenharmony_ci	bool memcg_charge = mem_cgroup_sockets_enabled && sk->sk_memcg;
305462306a36Sopenharmony_ci	struct proto *prot = sk->sk_prot;
305562306a36Sopenharmony_ci	bool charged = true;
305662306a36Sopenharmony_ci	long allocated;
305762306a36Sopenharmony_ci
305862306a36Sopenharmony_ci	sk_memory_allocated_add(sk, amt);
305962306a36Sopenharmony_ci	allocated = sk_memory_allocated(sk);
306062306a36Sopenharmony_ci	if (memcg_charge &&
306162306a36Sopenharmony_ci	    !(charged = mem_cgroup_charge_skmem(sk->sk_memcg, amt,
306262306a36Sopenharmony_ci						gfp_memcg_charge())))
306362306a36Sopenharmony_ci		goto suppress_allocation;
306462306a36Sopenharmony_ci
306562306a36Sopenharmony_ci	/* Under limit. */
306662306a36Sopenharmony_ci	if (allocated <= sk_prot_mem_limits(sk, 0)) {
306762306a36Sopenharmony_ci		sk_leave_memory_pressure(sk);
306862306a36Sopenharmony_ci		return 1;
306962306a36Sopenharmony_ci	}
307062306a36Sopenharmony_ci
307162306a36Sopenharmony_ci	/* Under pressure. */
307262306a36Sopenharmony_ci	if (allocated > sk_prot_mem_limits(sk, 1))
307362306a36Sopenharmony_ci		sk_enter_memory_pressure(sk);
307462306a36Sopenharmony_ci
307562306a36Sopenharmony_ci	/* Over hard limit. */
307662306a36Sopenharmony_ci	if (allocated > sk_prot_mem_limits(sk, 2))
307762306a36Sopenharmony_ci		goto suppress_allocation;
307862306a36Sopenharmony_ci
307962306a36Sopenharmony_ci	/* guarantee minimum buffer size under pressure */
308062306a36Sopenharmony_ci	if (kind == SK_MEM_RECV) {
308162306a36Sopenharmony_ci		if (atomic_read(&sk->sk_rmem_alloc) < sk_get_rmem0(sk, prot))
308262306a36Sopenharmony_ci			return 1;
308362306a36Sopenharmony_ci
308462306a36Sopenharmony_ci	} else { /* SK_MEM_SEND */
308562306a36Sopenharmony_ci		int wmem0 = sk_get_wmem0(sk, prot);
308662306a36Sopenharmony_ci
308762306a36Sopenharmony_ci		if (sk->sk_type == SOCK_STREAM) {
308862306a36Sopenharmony_ci			if (sk->sk_wmem_queued < wmem0)
308962306a36Sopenharmony_ci				return 1;
309062306a36Sopenharmony_ci		} else if (refcount_read(&sk->sk_wmem_alloc) < wmem0) {
309162306a36Sopenharmony_ci				return 1;
309262306a36Sopenharmony_ci		}
309362306a36Sopenharmony_ci	}
309462306a36Sopenharmony_ci
309562306a36Sopenharmony_ci	if (sk_has_memory_pressure(sk)) {
309662306a36Sopenharmony_ci		u64 alloc;
309762306a36Sopenharmony_ci
309862306a36Sopenharmony_ci		if (!sk_under_memory_pressure(sk))
309962306a36Sopenharmony_ci			return 1;
310062306a36Sopenharmony_ci		alloc = sk_sockets_allocated_read_positive(sk);
310162306a36Sopenharmony_ci		if (sk_prot_mem_limits(sk, 2) > alloc *
310262306a36Sopenharmony_ci		    sk_mem_pages(sk->sk_wmem_queued +
310362306a36Sopenharmony_ci				 atomic_read(&sk->sk_rmem_alloc) +
310462306a36Sopenharmony_ci				 sk->sk_forward_alloc))
310562306a36Sopenharmony_ci			return 1;
310662306a36Sopenharmony_ci	}
310762306a36Sopenharmony_ci
310862306a36Sopenharmony_cisuppress_allocation:
310962306a36Sopenharmony_ci
311062306a36Sopenharmony_ci	if (kind == SK_MEM_SEND && sk->sk_type == SOCK_STREAM) {
311162306a36Sopenharmony_ci		sk_stream_moderate_sndbuf(sk);
311262306a36Sopenharmony_ci
311362306a36Sopenharmony_ci		/* Fail only if socket is _under_ its sndbuf.
311462306a36Sopenharmony_ci		 * In this case we cannot block, so that we have to fail.
311562306a36Sopenharmony_ci		 */
311662306a36Sopenharmony_ci		if (sk->sk_wmem_queued + size >= sk->sk_sndbuf) {
311762306a36Sopenharmony_ci			/* Force charge with __GFP_NOFAIL */
311862306a36Sopenharmony_ci			if (memcg_charge && !charged) {
311962306a36Sopenharmony_ci				mem_cgroup_charge_skmem(sk->sk_memcg, amt,
312062306a36Sopenharmony_ci					gfp_memcg_charge() | __GFP_NOFAIL);
312162306a36Sopenharmony_ci			}
312262306a36Sopenharmony_ci			return 1;
312362306a36Sopenharmony_ci		}
312462306a36Sopenharmony_ci	}
312562306a36Sopenharmony_ci
312662306a36Sopenharmony_ci	if (kind == SK_MEM_SEND || (kind == SK_MEM_RECV && charged))
312762306a36Sopenharmony_ci		trace_sock_exceed_buf_limit(sk, prot, allocated, kind);
312862306a36Sopenharmony_ci
312962306a36Sopenharmony_ci	sk_memory_allocated_sub(sk, amt);
313062306a36Sopenharmony_ci
313162306a36Sopenharmony_ci	if (memcg_charge && charged)
313262306a36Sopenharmony_ci		mem_cgroup_uncharge_skmem(sk->sk_memcg, amt);
313362306a36Sopenharmony_ci
313462306a36Sopenharmony_ci	return 0;
313562306a36Sopenharmony_ci}
313662306a36Sopenharmony_ci
313762306a36Sopenharmony_ci/**
313862306a36Sopenharmony_ci *	__sk_mem_schedule - increase sk_forward_alloc and memory_allocated
313962306a36Sopenharmony_ci *	@sk: socket
314062306a36Sopenharmony_ci *	@size: memory size to allocate
314162306a36Sopenharmony_ci *	@kind: allocation type
314262306a36Sopenharmony_ci *
314362306a36Sopenharmony_ci *	If kind is SK_MEM_SEND, it means wmem allocation. Otherwise it means
314462306a36Sopenharmony_ci *	rmem allocation. This function assumes that protocols which have
314562306a36Sopenharmony_ci *	memory_pressure use sk_wmem_queued as write buffer accounting.
314662306a36Sopenharmony_ci */
314762306a36Sopenharmony_ciint __sk_mem_schedule(struct sock *sk, int size, int kind)
314862306a36Sopenharmony_ci{
314962306a36Sopenharmony_ci	int ret, amt = sk_mem_pages(size);
315062306a36Sopenharmony_ci
315162306a36Sopenharmony_ci	sk_forward_alloc_add(sk, amt << PAGE_SHIFT);
315262306a36Sopenharmony_ci	ret = __sk_mem_raise_allocated(sk, size, amt, kind);
315362306a36Sopenharmony_ci	if (!ret)
315462306a36Sopenharmony_ci		sk_forward_alloc_add(sk, -(amt << PAGE_SHIFT));
315562306a36Sopenharmony_ci	return ret;
315662306a36Sopenharmony_ci}
315762306a36Sopenharmony_ciEXPORT_SYMBOL(__sk_mem_schedule);
315862306a36Sopenharmony_ci
315962306a36Sopenharmony_ci/**
316062306a36Sopenharmony_ci *	__sk_mem_reduce_allocated - reclaim memory_allocated
316162306a36Sopenharmony_ci *	@sk: socket
316262306a36Sopenharmony_ci *	@amount: number of quanta
316362306a36Sopenharmony_ci *
316462306a36Sopenharmony_ci *	Similar to __sk_mem_reclaim(), but does not update sk_forward_alloc
316562306a36Sopenharmony_ci */
316662306a36Sopenharmony_civoid __sk_mem_reduce_allocated(struct sock *sk, int amount)
316762306a36Sopenharmony_ci{
316862306a36Sopenharmony_ci	sk_memory_allocated_sub(sk, amount);
316962306a36Sopenharmony_ci
317062306a36Sopenharmony_ci	if (mem_cgroup_sockets_enabled && sk->sk_memcg)
317162306a36Sopenharmony_ci		mem_cgroup_uncharge_skmem(sk->sk_memcg, amount);
317262306a36Sopenharmony_ci
317362306a36Sopenharmony_ci	if (sk_under_global_memory_pressure(sk) &&
317462306a36Sopenharmony_ci	    (sk_memory_allocated(sk) < sk_prot_mem_limits(sk, 0)))
317562306a36Sopenharmony_ci		sk_leave_memory_pressure(sk);
317662306a36Sopenharmony_ci}
317762306a36Sopenharmony_ci
317862306a36Sopenharmony_ci/**
317962306a36Sopenharmony_ci *	__sk_mem_reclaim - reclaim sk_forward_alloc and memory_allocated
318062306a36Sopenharmony_ci *	@sk: socket
318162306a36Sopenharmony_ci *	@amount: number of bytes (rounded down to a PAGE_SIZE multiple)
318262306a36Sopenharmony_ci */
318362306a36Sopenharmony_civoid __sk_mem_reclaim(struct sock *sk, int amount)
318462306a36Sopenharmony_ci{
318562306a36Sopenharmony_ci	amount >>= PAGE_SHIFT;
318662306a36Sopenharmony_ci	sk_forward_alloc_add(sk, -(amount << PAGE_SHIFT));
318762306a36Sopenharmony_ci	__sk_mem_reduce_allocated(sk, amount);
318862306a36Sopenharmony_ci}
318962306a36Sopenharmony_ciEXPORT_SYMBOL(__sk_mem_reclaim);
319062306a36Sopenharmony_ci
319162306a36Sopenharmony_ciint sk_set_peek_off(struct sock *sk, int val)
319262306a36Sopenharmony_ci{
319362306a36Sopenharmony_ci	WRITE_ONCE(sk->sk_peek_off, val);
319462306a36Sopenharmony_ci	return 0;
319562306a36Sopenharmony_ci}
319662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(sk_set_peek_off);
319762306a36Sopenharmony_ci
319862306a36Sopenharmony_ci/*
319962306a36Sopenharmony_ci * Set of default routines for initialising struct proto_ops when
320062306a36Sopenharmony_ci * the protocol does not support a particular function. In certain
320162306a36Sopenharmony_ci * cases where it makes no sense for a protocol to have a "do nothing"
320262306a36Sopenharmony_ci * function, some default processing is provided.
320362306a36Sopenharmony_ci */
320462306a36Sopenharmony_ci
320562306a36Sopenharmony_ciint sock_no_bind(struct socket *sock, struct sockaddr *saddr, int len)
320662306a36Sopenharmony_ci{
320762306a36Sopenharmony_ci	return -EOPNOTSUPP;
320862306a36Sopenharmony_ci}
320962306a36Sopenharmony_ciEXPORT_SYMBOL(sock_no_bind);
321062306a36Sopenharmony_ci
321162306a36Sopenharmony_ciint sock_no_connect(struct socket *sock, struct sockaddr *saddr,
321262306a36Sopenharmony_ci		    int len, int flags)
321362306a36Sopenharmony_ci{
321462306a36Sopenharmony_ci	return -EOPNOTSUPP;
321562306a36Sopenharmony_ci}
321662306a36Sopenharmony_ciEXPORT_SYMBOL(sock_no_connect);
321762306a36Sopenharmony_ci
321862306a36Sopenharmony_ciint sock_no_socketpair(struct socket *sock1, struct socket *sock2)
321962306a36Sopenharmony_ci{
322062306a36Sopenharmony_ci	return -EOPNOTSUPP;
322162306a36Sopenharmony_ci}
322262306a36Sopenharmony_ciEXPORT_SYMBOL(sock_no_socketpair);
322362306a36Sopenharmony_ci
322462306a36Sopenharmony_ciint sock_no_accept(struct socket *sock, struct socket *newsock, int flags,
322562306a36Sopenharmony_ci		   bool kern)
322662306a36Sopenharmony_ci{
322762306a36Sopenharmony_ci	return -EOPNOTSUPP;
322862306a36Sopenharmony_ci}
322962306a36Sopenharmony_ciEXPORT_SYMBOL(sock_no_accept);
323062306a36Sopenharmony_ci
323162306a36Sopenharmony_ciint sock_no_getname(struct socket *sock, struct sockaddr *saddr,
323262306a36Sopenharmony_ci		    int peer)
323362306a36Sopenharmony_ci{
323462306a36Sopenharmony_ci	return -EOPNOTSUPP;
323562306a36Sopenharmony_ci}
323662306a36Sopenharmony_ciEXPORT_SYMBOL(sock_no_getname);
323762306a36Sopenharmony_ci
323862306a36Sopenharmony_ciint sock_no_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
323962306a36Sopenharmony_ci{
324062306a36Sopenharmony_ci	return -EOPNOTSUPP;
324162306a36Sopenharmony_ci}
324262306a36Sopenharmony_ciEXPORT_SYMBOL(sock_no_ioctl);
324362306a36Sopenharmony_ci
324462306a36Sopenharmony_ciint sock_no_listen(struct socket *sock, int backlog)
324562306a36Sopenharmony_ci{
324662306a36Sopenharmony_ci	return -EOPNOTSUPP;
324762306a36Sopenharmony_ci}
324862306a36Sopenharmony_ciEXPORT_SYMBOL(sock_no_listen);
324962306a36Sopenharmony_ci
325062306a36Sopenharmony_ciint sock_no_shutdown(struct socket *sock, int how)
325162306a36Sopenharmony_ci{
325262306a36Sopenharmony_ci	return -EOPNOTSUPP;
325362306a36Sopenharmony_ci}
325462306a36Sopenharmony_ciEXPORT_SYMBOL(sock_no_shutdown);
325562306a36Sopenharmony_ci
325662306a36Sopenharmony_ciint sock_no_sendmsg(struct socket *sock, struct msghdr *m, size_t len)
325762306a36Sopenharmony_ci{
325862306a36Sopenharmony_ci	return -EOPNOTSUPP;
325962306a36Sopenharmony_ci}
326062306a36Sopenharmony_ciEXPORT_SYMBOL(sock_no_sendmsg);
326162306a36Sopenharmony_ci
326262306a36Sopenharmony_ciint sock_no_sendmsg_locked(struct sock *sk, struct msghdr *m, size_t len)
326362306a36Sopenharmony_ci{
326462306a36Sopenharmony_ci	return -EOPNOTSUPP;
326562306a36Sopenharmony_ci}
326662306a36Sopenharmony_ciEXPORT_SYMBOL(sock_no_sendmsg_locked);
326762306a36Sopenharmony_ci
326862306a36Sopenharmony_ciint sock_no_recvmsg(struct socket *sock, struct msghdr *m, size_t len,
326962306a36Sopenharmony_ci		    int flags)
327062306a36Sopenharmony_ci{
327162306a36Sopenharmony_ci	return -EOPNOTSUPP;
327262306a36Sopenharmony_ci}
327362306a36Sopenharmony_ciEXPORT_SYMBOL(sock_no_recvmsg);
327462306a36Sopenharmony_ci
327562306a36Sopenharmony_ciint sock_no_mmap(struct file *file, struct socket *sock, struct vm_area_struct *vma)
327662306a36Sopenharmony_ci{
327762306a36Sopenharmony_ci	/* Mirror missing mmap method error code */
327862306a36Sopenharmony_ci	return -ENODEV;
327962306a36Sopenharmony_ci}
328062306a36Sopenharmony_ciEXPORT_SYMBOL(sock_no_mmap);
328162306a36Sopenharmony_ci
328262306a36Sopenharmony_ci/*
328362306a36Sopenharmony_ci * When a file is received (via SCM_RIGHTS, etc), we must bump the
328462306a36Sopenharmony_ci * various sock-based usage counts.
328562306a36Sopenharmony_ci */
328662306a36Sopenharmony_civoid __receive_sock(struct file *file)
328762306a36Sopenharmony_ci{
328862306a36Sopenharmony_ci	struct socket *sock;
328962306a36Sopenharmony_ci
329062306a36Sopenharmony_ci	sock = sock_from_file(file);
329162306a36Sopenharmony_ci	if (sock) {
329262306a36Sopenharmony_ci		sock_update_netprioidx(&sock->sk->sk_cgrp_data);
329362306a36Sopenharmony_ci		sock_update_classid(&sock->sk->sk_cgrp_data);
329462306a36Sopenharmony_ci	}
329562306a36Sopenharmony_ci}
329662306a36Sopenharmony_ci
329762306a36Sopenharmony_ci/*
329862306a36Sopenharmony_ci *	Default Socket Callbacks
329962306a36Sopenharmony_ci */
330062306a36Sopenharmony_ci
330162306a36Sopenharmony_cistatic void sock_def_wakeup(struct sock *sk)
330262306a36Sopenharmony_ci{
330362306a36Sopenharmony_ci	struct socket_wq *wq;
330462306a36Sopenharmony_ci
330562306a36Sopenharmony_ci	rcu_read_lock();
330662306a36Sopenharmony_ci	wq = rcu_dereference(sk->sk_wq);
330762306a36Sopenharmony_ci	if (skwq_has_sleeper(wq))
330862306a36Sopenharmony_ci		wake_up_interruptible_all(&wq->wait);
330962306a36Sopenharmony_ci	rcu_read_unlock();
331062306a36Sopenharmony_ci}
331162306a36Sopenharmony_ci
331262306a36Sopenharmony_cistatic void sock_def_error_report(struct sock *sk)
331362306a36Sopenharmony_ci{
331462306a36Sopenharmony_ci	struct socket_wq *wq;
331562306a36Sopenharmony_ci
331662306a36Sopenharmony_ci	rcu_read_lock();
331762306a36Sopenharmony_ci	wq = rcu_dereference(sk->sk_wq);
331862306a36Sopenharmony_ci	if (skwq_has_sleeper(wq))
331962306a36Sopenharmony_ci		wake_up_interruptible_poll(&wq->wait, EPOLLERR);
332062306a36Sopenharmony_ci	sk_wake_async(sk, SOCK_WAKE_IO, POLL_ERR);
332162306a36Sopenharmony_ci	rcu_read_unlock();
332262306a36Sopenharmony_ci}
332362306a36Sopenharmony_ci
332462306a36Sopenharmony_civoid sock_def_readable(struct sock *sk)
332562306a36Sopenharmony_ci{
332662306a36Sopenharmony_ci	struct socket_wq *wq;
332762306a36Sopenharmony_ci
332862306a36Sopenharmony_ci	trace_sk_data_ready(sk);
332962306a36Sopenharmony_ci
333062306a36Sopenharmony_ci	rcu_read_lock();
333162306a36Sopenharmony_ci	wq = rcu_dereference(sk->sk_wq);
333262306a36Sopenharmony_ci	if (skwq_has_sleeper(wq))
333362306a36Sopenharmony_ci		wake_up_interruptible_sync_poll(&wq->wait, EPOLLIN | EPOLLPRI |
333462306a36Sopenharmony_ci						EPOLLRDNORM | EPOLLRDBAND);
333562306a36Sopenharmony_ci	sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN);
333662306a36Sopenharmony_ci	rcu_read_unlock();
333762306a36Sopenharmony_ci}
333862306a36Sopenharmony_ci
333962306a36Sopenharmony_cistatic void sock_def_write_space(struct sock *sk)
334062306a36Sopenharmony_ci{
334162306a36Sopenharmony_ci	struct socket_wq *wq;
334262306a36Sopenharmony_ci
334362306a36Sopenharmony_ci	rcu_read_lock();
334462306a36Sopenharmony_ci
334562306a36Sopenharmony_ci	/* Do not wake up a writer until he can make "significant"
334662306a36Sopenharmony_ci	 * progress.  --DaveM
334762306a36Sopenharmony_ci	 */
334862306a36Sopenharmony_ci	if (sock_writeable(sk)) {
334962306a36Sopenharmony_ci		wq = rcu_dereference(sk->sk_wq);
335062306a36Sopenharmony_ci		if (skwq_has_sleeper(wq))
335162306a36Sopenharmony_ci			wake_up_interruptible_sync_poll(&wq->wait, EPOLLOUT |
335262306a36Sopenharmony_ci						EPOLLWRNORM | EPOLLWRBAND);
335362306a36Sopenharmony_ci
335462306a36Sopenharmony_ci		/* Should agree with poll, otherwise some programs break */
335562306a36Sopenharmony_ci		sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
335662306a36Sopenharmony_ci	}
335762306a36Sopenharmony_ci
335862306a36Sopenharmony_ci	rcu_read_unlock();
335962306a36Sopenharmony_ci}
336062306a36Sopenharmony_ci
336162306a36Sopenharmony_ci/* An optimised version of sock_def_write_space(), should only be called
336262306a36Sopenharmony_ci * for SOCK_RCU_FREE sockets under RCU read section and after putting
336362306a36Sopenharmony_ci * ->sk_wmem_alloc.
336462306a36Sopenharmony_ci */
336562306a36Sopenharmony_cistatic void sock_def_write_space_wfree(struct sock *sk)
336662306a36Sopenharmony_ci{
336762306a36Sopenharmony_ci	/* Do not wake up a writer until he can make "significant"
336862306a36Sopenharmony_ci	 * progress.  --DaveM
336962306a36Sopenharmony_ci	 */
337062306a36Sopenharmony_ci	if (sock_writeable(sk)) {
337162306a36Sopenharmony_ci		struct socket_wq *wq = rcu_dereference(sk->sk_wq);
337262306a36Sopenharmony_ci
337362306a36Sopenharmony_ci		/* rely on refcount_sub from sock_wfree() */
337462306a36Sopenharmony_ci		smp_mb__after_atomic();
337562306a36Sopenharmony_ci		if (wq && waitqueue_active(&wq->wait))
337662306a36Sopenharmony_ci			wake_up_interruptible_sync_poll(&wq->wait, EPOLLOUT |
337762306a36Sopenharmony_ci						EPOLLWRNORM | EPOLLWRBAND);
337862306a36Sopenharmony_ci
337962306a36Sopenharmony_ci		/* Should agree with poll, otherwise some programs break */
338062306a36Sopenharmony_ci		sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
338162306a36Sopenharmony_ci	}
338262306a36Sopenharmony_ci}
338362306a36Sopenharmony_ci
338462306a36Sopenharmony_cistatic void sock_def_destruct(struct sock *sk)
338562306a36Sopenharmony_ci{
338662306a36Sopenharmony_ci}
338762306a36Sopenharmony_ci
338862306a36Sopenharmony_civoid sk_send_sigurg(struct sock *sk)
338962306a36Sopenharmony_ci{
339062306a36Sopenharmony_ci	if (sk->sk_socket && sk->sk_socket->file)
339162306a36Sopenharmony_ci		if (send_sigurg(&sk->sk_socket->file->f_owner))
339262306a36Sopenharmony_ci			sk_wake_async(sk, SOCK_WAKE_URG, POLL_PRI);
339362306a36Sopenharmony_ci}
339462306a36Sopenharmony_ciEXPORT_SYMBOL(sk_send_sigurg);
339562306a36Sopenharmony_ci
339662306a36Sopenharmony_civoid sk_reset_timer(struct sock *sk, struct timer_list* timer,
339762306a36Sopenharmony_ci		    unsigned long expires)
339862306a36Sopenharmony_ci{
339962306a36Sopenharmony_ci	if (!mod_timer(timer, expires))
340062306a36Sopenharmony_ci		sock_hold(sk);
340162306a36Sopenharmony_ci}
340262306a36Sopenharmony_ciEXPORT_SYMBOL(sk_reset_timer);
340362306a36Sopenharmony_ci
340462306a36Sopenharmony_civoid sk_stop_timer(struct sock *sk, struct timer_list* timer)
340562306a36Sopenharmony_ci{
340662306a36Sopenharmony_ci	if (del_timer(timer))
340762306a36Sopenharmony_ci		__sock_put(sk);
340862306a36Sopenharmony_ci}
340962306a36Sopenharmony_ciEXPORT_SYMBOL(sk_stop_timer);
341062306a36Sopenharmony_ci
341162306a36Sopenharmony_civoid sk_stop_timer_sync(struct sock *sk, struct timer_list *timer)
341262306a36Sopenharmony_ci{
341362306a36Sopenharmony_ci	if (del_timer_sync(timer))
341462306a36Sopenharmony_ci		__sock_put(sk);
341562306a36Sopenharmony_ci}
341662306a36Sopenharmony_ciEXPORT_SYMBOL(sk_stop_timer_sync);
341762306a36Sopenharmony_ci
341862306a36Sopenharmony_civoid sock_init_data_uid(struct socket *sock, struct sock *sk, kuid_t uid)
341962306a36Sopenharmony_ci{
342062306a36Sopenharmony_ci	sk_init_common(sk);
342162306a36Sopenharmony_ci	sk->sk_send_head	=	NULL;
342262306a36Sopenharmony_ci
342362306a36Sopenharmony_ci	timer_setup(&sk->sk_timer, NULL, 0);
342462306a36Sopenharmony_ci
342562306a36Sopenharmony_ci	sk->sk_allocation	=	GFP_KERNEL;
342662306a36Sopenharmony_ci	sk->sk_rcvbuf		=	READ_ONCE(sysctl_rmem_default);
342762306a36Sopenharmony_ci	sk->sk_sndbuf		=	READ_ONCE(sysctl_wmem_default);
342862306a36Sopenharmony_ci	sk->sk_state		=	TCP_CLOSE;
342962306a36Sopenharmony_ci	sk->sk_use_task_frag	=	true;
343062306a36Sopenharmony_ci	sk_set_socket(sk, sock);
343162306a36Sopenharmony_ci
343262306a36Sopenharmony_ci	sock_set_flag(sk, SOCK_ZAPPED);
343362306a36Sopenharmony_ci
343462306a36Sopenharmony_ci	if (sock) {
343562306a36Sopenharmony_ci		sk->sk_type	=	sock->type;
343662306a36Sopenharmony_ci		RCU_INIT_POINTER(sk->sk_wq, &sock->wq);
343762306a36Sopenharmony_ci		sock->sk	=	sk;
343862306a36Sopenharmony_ci	} else {
343962306a36Sopenharmony_ci		RCU_INIT_POINTER(sk->sk_wq, NULL);
344062306a36Sopenharmony_ci	}
344162306a36Sopenharmony_ci	sk->sk_uid	=	uid;
344262306a36Sopenharmony_ci
344362306a36Sopenharmony_ci	rwlock_init(&sk->sk_callback_lock);
344462306a36Sopenharmony_ci	if (sk->sk_kern_sock)
344562306a36Sopenharmony_ci		lockdep_set_class_and_name(
344662306a36Sopenharmony_ci			&sk->sk_callback_lock,
344762306a36Sopenharmony_ci			af_kern_callback_keys + sk->sk_family,
344862306a36Sopenharmony_ci			af_family_kern_clock_key_strings[sk->sk_family]);
344962306a36Sopenharmony_ci	else
345062306a36Sopenharmony_ci		lockdep_set_class_and_name(
345162306a36Sopenharmony_ci			&sk->sk_callback_lock,
345262306a36Sopenharmony_ci			af_callback_keys + sk->sk_family,
345362306a36Sopenharmony_ci			af_family_clock_key_strings[sk->sk_family]);
345462306a36Sopenharmony_ci
345562306a36Sopenharmony_ci	sk->sk_state_change	=	sock_def_wakeup;
345662306a36Sopenharmony_ci	sk->sk_data_ready	=	sock_def_readable;
345762306a36Sopenharmony_ci	sk->sk_write_space	=	sock_def_write_space;
345862306a36Sopenharmony_ci	sk->sk_error_report	=	sock_def_error_report;
345962306a36Sopenharmony_ci	sk->sk_destruct		=	sock_def_destruct;
346062306a36Sopenharmony_ci
346162306a36Sopenharmony_ci	sk->sk_frag.page	=	NULL;
346262306a36Sopenharmony_ci	sk->sk_frag.offset	=	0;
346362306a36Sopenharmony_ci	sk->sk_peek_off		=	-1;
346462306a36Sopenharmony_ci
346562306a36Sopenharmony_ci	sk->sk_peer_pid 	=	NULL;
346662306a36Sopenharmony_ci	sk->sk_peer_cred	=	NULL;
346762306a36Sopenharmony_ci	spin_lock_init(&sk->sk_peer_lock);
346862306a36Sopenharmony_ci
346962306a36Sopenharmony_ci	sk->sk_write_pending	=	0;
347062306a36Sopenharmony_ci	sk->sk_rcvlowat		=	1;
347162306a36Sopenharmony_ci	sk->sk_rcvtimeo		=	MAX_SCHEDULE_TIMEOUT;
347262306a36Sopenharmony_ci	sk->sk_sndtimeo		=	MAX_SCHEDULE_TIMEOUT;
347362306a36Sopenharmony_ci
347462306a36Sopenharmony_ci	sk->sk_stamp = SK_DEFAULT_STAMP;
347562306a36Sopenharmony_ci#if BITS_PER_LONG==32
347662306a36Sopenharmony_ci	seqlock_init(&sk->sk_stamp_seq);
347762306a36Sopenharmony_ci#endif
347862306a36Sopenharmony_ci	atomic_set(&sk->sk_zckey, 0);
347962306a36Sopenharmony_ci
348062306a36Sopenharmony_ci#ifdef CONFIG_NET_RX_BUSY_POLL
348162306a36Sopenharmony_ci	sk->sk_napi_id		=	0;
348262306a36Sopenharmony_ci	sk->sk_ll_usec		=	READ_ONCE(sysctl_net_busy_read);
348362306a36Sopenharmony_ci#endif
348462306a36Sopenharmony_ci
348562306a36Sopenharmony_ci	sk->sk_max_pacing_rate = ~0UL;
348662306a36Sopenharmony_ci	sk->sk_pacing_rate = ~0UL;
348762306a36Sopenharmony_ci	WRITE_ONCE(sk->sk_pacing_shift, 10);
348862306a36Sopenharmony_ci	sk->sk_incoming_cpu = -1;
348962306a36Sopenharmony_ci
349062306a36Sopenharmony_ci	sk_rx_queue_clear(sk);
349162306a36Sopenharmony_ci	/*
349262306a36Sopenharmony_ci	 * Before updating sk_refcnt, we must commit prior changes to memory
349362306a36Sopenharmony_ci	 * (Documentation/RCU/rculist_nulls.rst for details)
349462306a36Sopenharmony_ci	 */
349562306a36Sopenharmony_ci	smp_wmb();
349662306a36Sopenharmony_ci	refcount_set(&sk->sk_refcnt, 1);
349762306a36Sopenharmony_ci	atomic_set(&sk->sk_drops, 0);
349862306a36Sopenharmony_ci}
349962306a36Sopenharmony_ciEXPORT_SYMBOL(sock_init_data_uid);
350062306a36Sopenharmony_ci
350162306a36Sopenharmony_civoid sock_init_data(struct socket *sock, struct sock *sk)
350262306a36Sopenharmony_ci{
350362306a36Sopenharmony_ci	kuid_t uid = sock ?
350462306a36Sopenharmony_ci		SOCK_INODE(sock)->i_uid :
350562306a36Sopenharmony_ci		make_kuid(sock_net(sk)->user_ns, 0);
350662306a36Sopenharmony_ci
350762306a36Sopenharmony_ci	sock_init_data_uid(sock, sk, uid);
350862306a36Sopenharmony_ci}
350962306a36Sopenharmony_ciEXPORT_SYMBOL(sock_init_data);
351062306a36Sopenharmony_ci
351162306a36Sopenharmony_civoid lock_sock_nested(struct sock *sk, int subclass)
351262306a36Sopenharmony_ci{
351362306a36Sopenharmony_ci	/* The sk_lock has mutex_lock() semantics here. */
351462306a36Sopenharmony_ci	mutex_acquire(&sk->sk_lock.dep_map, subclass, 0, _RET_IP_);
351562306a36Sopenharmony_ci
351662306a36Sopenharmony_ci	might_sleep();
351762306a36Sopenharmony_ci	spin_lock_bh(&sk->sk_lock.slock);
351862306a36Sopenharmony_ci	if (sock_owned_by_user_nocheck(sk))
351962306a36Sopenharmony_ci		__lock_sock(sk);
352062306a36Sopenharmony_ci	sk->sk_lock.owned = 1;
352162306a36Sopenharmony_ci	spin_unlock_bh(&sk->sk_lock.slock);
352262306a36Sopenharmony_ci}
352362306a36Sopenharmony_ciEXPORT_SYMBOL(lock_sock_nested);
352462306a36Sopenharmony_ci
352562306a36Sopenharmony_civoid release_sock(struct sock *sk)
352662306a36Sopenharmony_ci{
352762306a36Sopenharmony_ci	spin_lock_bh(&sk->sk_lock.slock);
352862306a36Sopenharmony_ci	if (sk->sk_backlog.tail)
352962306a36Sopenharmony_ci		__release_sock(sk);
353062306a36Sopenharmony_ci
353162306a36Sopenharmony_ci	/* Warning : release_cb() might need to release sk ownership,
353262306a36Sopenharmony_ci	 * ie call sock_release_ownership(sk) before us.
353362306a36Sopenharmony_ci	 */
353462306a36Sopenharmony_ci	if (sk->sk_prot->release_cb)
353562306a36Sopenharmony_ci		sk->sk_prot->release_cb(sk);
353662306a36Sopenharmony_ci
353762306a36Sopenharmony_ci	sock_release_ownership(sk);
353862306a36Sopenharmony_ci	if (waitqueue_active(&sk->sk_lock.wq))
353962306a36Sopenharmony_ci		wake_up(&sk->sk_lock.wq);
354062306a36Sopenharmony_ci	spin_unlock_bh(&sk->sk_lock.slock);
354162306a36Sopenharmony_ci}
354262306a36Sopenharmony_ciEXPORT_SYMBOL(release_sock);
354362306a36Sopenharmony_ci
354462306a36Sopenharmony_cibool __lock_sock_fast(struct sock *sk) __acquires(&sk->sk_lock.slock)
354562306a36Sopenharmony_ci{
354662306a36Sopenharmony_ci	might_sleep();
354762306a36Sopenharmony_ci	spin_lock_bh(&sk->sk_lock.slock);
354862306a36Sopenharmony_ci
354962306a36Sopenharmony_ci	if (!sock_owned_by_user_nocheck(sk)) {
355062306a36Sopenharmony_ci		/*
355162306a36Sopenharmony_ci		 * Fast path return with bottom halves disabled and
355262306a36Sopenharmony_ci		 * sock::sk_lock.slock held.
355362306a36Sopenharmony_ci		 *
355462306a36Sopenharmony_ci		 * The 'mutex' is not contended and holding
355562306a36Sopenharmony_ci		 * sock::sk_lock.slock prevents all other lockers to
355662306a36Sopenharmony_ci		 * proceed so the corresponding unlock_sock_fast() can
355762306a36Sopenharmony_ci		 * avoid the slow path of release_sock() completely and
355862306a36Sopenharmony_ci		 * just release slock.
355962306a36Sopenharmony_ci		 *
356062306a36Sopenharmony_ci		 * From a semantical POV this is equivalent to 'acquiring'
356162306a36Sopenharmony_ci		 * the 'mutex', hence the corresponding lockdep
356262306a36Sopenharmony_ci		 * mutex_release() has to happen in the fast path of
356362306a36Sopenharmony_ci		 * unlock_sock_fast().
356462306a36Sopenharmony_ci		 */
356562306a36Sopenharmony_ci		return false;
356662306a36Sopenharmony_ci	}
356762306a36Sopenharmony_ci
356862306a36Sopenharmony_ci	__lock_sock(sk);
356962306a36Sopenharmony_ci	sk->sk_lock.owned = 1;
357062306a36Sopenharmony_ci	__acquire(&sk->sk_lock.slock);
357162306a36Sopenharmony_ci	spin_unlock_bh(&sk->sk_lock.slock);
357262306a36Sopenharmony_ci	return true;
357362306a36Sopenharmony_ci}
357462306a36Sopenharmony_ciEXPORT_SYMBOL(__lock_sock_fast);
357562306a36Sopenharmony_ci
357662306a36Sopenharmony_ciint sock_gettstamp(struct socket *sock, void __user *userstamp,
357762306a36Sopenharmony_ci		   bool timeval, bool time32)
357862306a36Sopenharmony_ci{
357962306a36Sopenharmony_ci	struct sock *sk = sock->sk;
358062306a36Sopenharmony_ci	struct timespec64 ts;
358162306a36Sopenharmony_ci
358262306a36Sopenharmony_ci	sock_enable_timestamp(sk, SOCK_TIMESTAMP);
358362306a36Sopenharmony_ci	ts = ktime_to_timespec64(sock_read_timestamp(sk));
358462306a36Sopenharmony_ci	if (ts.tv_sec == -1)
358562306a36Sopenharmony_ci		return -ENOENT;
358662306a36Sopenharmony_ci	if (ts.tv_sec == 0) {
358762306a36Sopenharmony_ci		ktime_t kt = ktime_get_real();
358862306a36Sopenharmony_ci		sock_write_timestamp(sk, kt);
358962306a36Sopenharmony_ci		ts = ktime_to_timespec64(kt);
359062306a36Sopenharmony_ci	}
359162306a36Sopenharmony_ci
359262306a36Sopenharmony_ci	if (timeval)
359362306a36Sopenharmony_ci		ts.tv_nsec /= 1000;
359462306a36Sopenharmony_ci
359562306a36Sopenharmony_ci#ifdef CONFIG_COMPAT_32BIT_TIME
359662306a36Sopenharmony_ci	if (time32)
359762306a36Sopenharmony_ci		return put_old_timespec32(&ts, userstamp);
359862306a36Sopenharmony_ci#endif
359962306a36Sopenharmony_ci#ifdef CONFIG_SPARC64
360062306a36Sopenharmony_ci	/* beware of padding in sparc64 timeval */
360162306a36Sopenharmony_ci	if (timeval && !in_compat_syscall()) {
360262306a36Sopenharmony_ci		struct __kernel_old_timeval __user tv = {
360362306a36Sopenharmony_ci			.tv_sec = ts.tv_sec,
360462306a36Sopenharmony_ci			.tv_usec = ts.tv_nsec,
360562306a36Sopenharmony_ci		};
360662306a36Sopenharmony_ci		if (copy_to_user(userstamp, &tv, sizeof(tv)))
360762306a36Sopenharmony_ci			return -EFAULT;
360862306a36Sopenharmony_ci		return 0;
360962306a36Sopenharmony_ci	}
361062306a36Sopenharmony_ci#endif
361162306a36Sopenharmony_ci	return put_timespec64(&ts, userstamp);
361262306a36Sopenharmony_ci}
361362306a36Sopenharmony_ciEXPORT_SYMBOL(sock_gettstamp);
361462306a36Sopenharmony_ci
361562306a36Sopenharmony_civoid sock_enable_timestamp(struct sock *sk, enum sock_flags flag)
361662306a36Sopenharmony_ci{
361762306a36Sopenharmony_ci	if (!sock_flag(sk, flag)) {
361862306a36Sopenharmony_ci		unsigned long previous_flags = sk->sk_flags;
361962306a36Sopenharmony_ci
362062306a36Sopenharmony_ci		sock_set_flag(sk, flag);
362162306a36Sopenharmony_ci		/*
362262306a36Sopenharmony_ci		 * we just set one of the two flags which require net
362362306a36Sopenharmony_ci		 * time stamping, but time stamping might have been on
362462306a36Sopenharmony_ci		 * already because of the other one
362562306a36Sopenharmony_ci		 */
362662306a36Sopenharmony_ci		if (sock_needs_netstamp(sk) &&
362762306a36Sopenharmony_ci		    !(previous_flags & SK_FLAGS_TIMESTAMP))
362862306a36Sopenharmony_ci			net_enable_timestamp();
362962306a36Sopenharmony_ci	}
363062306a36Sopenharmony_ci}
363162306a36Sopenharmony_ci
363262306a36Sopenharmony_ciint sock_recv_errqueue(struct sock *sk, struct msghdr *msg, int len,
363362306a36Sopenharmony_ci		       int level, int type)
363462306a36Sopenharmony_ci{
363562306a36Sopenharmony_ci	struct sock_exterr_skb *serr;
363662306a36Sopenharmony_ci	struct sk_buff *skb;
363762306a36Sopenharmony_ci	int copied, err;
363862306a36Sopenharmony_ci
363962306a36Sopenharmony_ci	err = -EAGAIN;
364062306a36Sopenharmony_ci	skb = sock_dequeue_err_skb(sk);
364162306a36Sopenharmony_ci	if (skb == NULL)
364262306a36Sopenharmony_ci		goto out;
364362306a36Sopenharmony_ci
364462306a36Sopenharmony_ci	copied = skb->len;
364562306a36Sopenharmony_ci	if (copied > len) {
364662306a36Sopenharmony_ci		msg->msg_flags |= MSG_TRUNC;
364762306a36Sopenharmony_ci		copied = len;
364862306a36Sopenharmony_ci	}
364962306a36Sopenharmony_ci	err = skb_copy_datagram_msg(skb, 0, msg, copied);
365062306a36Sopenharmony_ci	if (err)
365162306a36Sopenharmony_ci		goto out_free_skb;
365262306a36Sopenharmony_ci
365362306a36Sopenharmony_ci	sock_recv_timestamp(msg, sk, skb);
365462306a36Sopenharmony_ci
365562306a36Sopenharmony_ci	serr = SKB_EXT_ERR(skb);
365662306a36Sopenharmony_ci	put_cmsg(msg, level, type, sizeof(serr->ee), &serr->ee);
365762306a36Sopenharmony_ci
365862306a36Sopenharmony_ci	msg->msg_flags |= MSG_ERRQUEUE;
365962306a36Sopenharmony_ci	err = copied;
366062306a36Sopenharmony_ci
366162306a36Sopenharmony_ciout_free_skb:
366262306a36Sopenharmony_ci	kfree_skb(skb);
366362306a36Sopenharmony_ciout:
366462306a36Sopenharmony_ci	return err;
366562306a36Sopenharmony_ci}
366662306a36Sopenharmony_ciEXPORT_SYMBOL(sock_recv_errqueue);
366762306a36Sopenharmony_ci
366862306a36Sopenharmony_ci/*
366962306a36Sopenharmony_ci *	Get a socket option on an socket.
367062306a36Sopenharmony_ci *
367162306a36Sopenharmony_ci *	FIX: POSIX 1003.1g is very ambiguous here. It states that
367262306a36Sopenharmony_ci *	asynchronous errors should be reported by getsockopt. We assume
367362306a36Sopenharmony_ci *	this means if you specify SO_ERROR (otherwise whats the point of it).
367462306a36Sopenharmony_ci */
367562306a36Sopenharmony_ciint sock_common_getsockopt(struct socket *sock, int level, int optname,
367662306a36Sopenharmony_ci			   char __user *optval, int __user *optlen)
367762306a36Sopenharmony_ci{
367862306a36Sopenharmony_ci	struct sock *sk = sock->sk;
367962306a36Sopenharmony_ci
368062306a36Sopenharmony_ci	/* IPV6_ADDRFORM can change sk->sk_prot under us. */
368162306a36Sopenharmony_ci	return READ_ONCE(sk->sk_prot)->getsockopt(sk, level, optname, optval, optlen);
368262306a36Sopenharmony_ci}
368362306a36Sopenharmony_ciEXPORT_SYMBOL(sock_common_getsockopt);
368462306a36Sopenharmony_ci
368562306a36Sopenharmony_ciint sock_common_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
368662306a36Sopenharmony_ci			int flags)
368762306a36Sopenharmony_ci{
368862306a36Sopenharmony_ci	struct sock *sk = sock->sk;
368962306a36Sopenharmony_ci	int addr_len = 0;
369062306a36Sopenharmony_ci	int err;
369162306a36Sopenharmony_ci
369262306a36Sopenharmony_ci	err = sk->sk_prot->recvmsg(sk, msg, size, flags, &addr_len);
369362306a36Sopenharmony_ci	if (err >= 0)
369462306a36Sopenharmony_ci		msg->msg_namelen = addr_len;
369562306a36Sopenharmony_ci	return err;
369662306a36Sopenharmony_ci}
369762306a36Sopenharmony_ciEXPORT_SYMBOL(sock_common_recvmsg);
369862306a36Sopenharmony_ci
369962306a36Sopenharmony_ci/*
370062306a36Sopenharmony_ci *	Set socket options on an inet socket.
370162306a36Sopenharmony_ci */
370262306a36Sopenharmony_ciint sock_common_setsockopt(struct socket *sock, int level, int optname,
370362306a36Sopenharmony_ci			   sockptr_t optval, unsigned int optlen)
370462306a36Sopenharmony_ci{
370562306a36Sopenharmony_ci	struct sock *sk = sock->sk;
370662306a36Sopenharmony_ci
370762306a36Sopenharmony_ci	/* IPV6_ADDRFORM can change sk->sk_prot under us. */
370862306a36Sopenharmony_ci	return READ_ONCE(sk->sk_prot)->setsockopt(sk, level, optname, optval, optlen);
370962306a36Sopenharmony_ci}
371062306a36Sopenharmony_ciEXPORT_SYMBOL(sock_common_setsockopt);
371162306a36Sopenharmony_ci
371262306a36Sopenharmony_civoid sk_common_release(struct sock *sk)
371362306a36Sopenharmony_ci{
371462306a36Sopenharmony_ci	if (sk->sk_prot->destroy)
371562306a36Sopenharmony_ci		sk->sk_prot->destroy(sk);
371662306a36Sopenharmony_ci
371762306a36Sopenharmony_ci	/*
371862306a36Sopenharmony_ci	 * Observation: when sk_common_release is called, processes have
371962306a36Sopenharmony_ci	 * no access to socket. But net still has.
372062306a36Sopenharmony_ci	 * Step one, detach it from networking:
372162306a36Sopenharmony_ci	 *
372262306a36Sopenharmony_ci	 * A. Remove from hash tables.
372362306a36Sopenharmony_ci	 */
372462306a36Sopenharmony_ci
372562306a36Sopenharmony_ci	sk->sk_prot->unhash(sk);
372662306a36Sopenharmony_ci
372762306a36Sopenharmony_ci	/*
372862306a36Sopenharmony_ci	 * In this point socket cannot receive new packets, but it is possible
372962306a36Sopenharmony_ci	 * that some packets are in flight because some CPU runs receiver and
373062306a36Sopenharmony_ci	 * did hash table lookup before we unhashed socket. They will achieve
373162306a36Sopenharmony_ci	 * receive queue and will be purged by socket destructor.
373262306a36Sopenharmony_ci	 *
373362306a36Sopenharmony_ci	 * Also we still have packets pending on receive queue and probably,
373462306a36Sopenharmony_ci	 * our own packets waiting in device queues. sock_destroy will drain
373562306a36Sopenharmony_ci	 * receive queue, but transmitted packets will delay socket destruction
373662306a36Sopenharmony_ci	 * until the last reference will be released.
373762306a36Sopenharmony_ci	 */
373862306a36Sopenharmony_ci
373962306a36Sopenharmony_ci	sock_orphan(sk);
374062306a36Sopenharmony_ci
374162306a36Sopenharmony_ci	xfrm_sk_free_policy(sk);
374262306a36Sopenharmony_ci
374362306a36Sopenharmony_ci	sock_put(sk);
374462306a36Sopenharmony_ci}
374562306a36Sopenharmony_ciEXPORT_SYMBOL(sk_common_release);
374662306a36Sopenharmony_ci
374762306a36Sopenharmony_civoid sk_get_meminfo(const struct sock *sk, u32 *mem)
374862306a36Sopenharmony_ci{
374962306a36Sopenharmony_ci	memset(mem, 0, sizeof(*mem) * SK_MEMINFO_VARS);
375062306a36Sopenharmony_ci
375162306a36Sopenharmony_ci	mem[SK_MEMINFO_RMEM_ALLOC] = sk_rmem_alloc_get(sk);
375262306a36Sopenharmony_ci	mem[SK_MEMINFO_RCVBUF] = READ_ONCE(sk->sk_rcvbuf);
375362306a36Sopenharmony_ci	mem[SK_MEMINFO_WMEM_ALLOC] = sk_wmem_alloc_get(sk);
375462306a36Sopenharmony_ci	mem[SK_MEMINFO_SNDBUF] = READ_ONCE(sk->sk_sndbuf);
375562306a36Sopenharmony_ci	mem[SK_MEMINFO_FWD_ALLOC] = sk_forward_alloc_get(sk);
375662306a36Sopenharmony_ci	mem[SK_MEMINFO_WMEM_QUEUED] = READ_ONCE(sk->sk_wmem_queued);
375762306a36Sopenharmony_ci	mem[SK_MEMINFO_OPTMEM] = atomic_read(&sk->sk_omem_alloc);
375862306a36Sopenharmony_ci	mem[SK_MEMINFO_BACKLOG] = READ_ONCE(sk->sk_backlog.len);
375962306a36Sopenharmony_ci	mem[SK_MEMINFO_DROPS] = atomic_read(&sk->sk_drops);
376062306a36Sopenharmony_ci}
376162306a36Sopenharmony_ci
376262306a36Sopenharmony_ci#ifdef CONFIG_PROC_FS
376362306a36Sopenharmony_cistatic DECLARE_BITMAP(proto_inuse_idx, PROTO_INUSE_NR);
376462306a36Sopenharmony_ci
376562306a36Sopenharmony_ciint sock_prot_inuse_get(struct net *net, struct proto *prot)
376662306a36Sopenharmony_ci{
376762306a36Sopenharmony_ci	int cpu, idx = prot->inuse_idx;
376862306a36Sopenharmony_ci	int res = 0;
376962306a36Sopenharmony_ci
377062306a36Sopenharmony_ci	for_each_possible_cpu(cpu)
377162306a36Sopenharmony_ci		res += per_cpu_ptr(net->core.prot_inuse, cpu)->val[idx];
377262306a36Sopenharmony_ci
377362306a36Sopenharmony_ci	return res >= 0 ? res : 0;
377462306a36Sopenharmony_ci}
377562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(sock_prot_inuse_get);
377662306a36Sopenharmony_ci
377762306a36Sopenharmony_ciint sock_inuse_get(struct net *net)
377862306a36Sopenharmony_ci{
377962306a36Sopenharmony_ci	int cpu, res = 0;
378062306a36Sopenharmony_ci
378162306a36Sopenharmony_ci	for_each_possible_cpu(cpu)
378262306a36Sopenharmony_ci		res += per_cpu_ptr(net->core.prot_inuse, cpu)->all;
378362306a36Sopenharmony_ci
378462306a36Sopenharmony_ci	return res;
378562306a36Sopenharmony_ci}
378662306a36Sopenharmony_ci
378762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(sock_inuse_get);
378862306a36Sopenharmony_ci
378962306a36Sopenharmony_cistatic int __net_init sock_inuse_init_net(struct net *net)
379062306a36Sopenharmony_ci{
379162306a36Sopenharmony_ci	net->core.prot_inuse = alloc_percpu(struct prot_inuse);
379262306a36Sopenharmony_ci	if (net->core.prot_inuse == NULL)
379362306a36Sopenharmony_ci		return -ENOMEM;
379462306a36Sopenharmony_ci	return 0;
379562306a36Sopenharmony_ci}
379662306a36Sopenharmony_ci
379762306a36Sopenharmony_cistatic void __net_exit sock_inuse_exit_net(struct net *net)
379862306a36Sopenharmony_ci{
379962306a36Sopenharmony_ci	free_percpu(net->core.prot_inuse);
380062306a36Sopenharmony_ci}
380162306a36Sopenharmony_ci
380262306a36Sopenharmony_cistatic struct pernet_operations net_inuse_ops = {
380362306a36Sopenharmony_ci	.init = sock_inuse_init_net,
380462306a36Sopenharmony_ci	.exit = sock_inuse_exit_net,
380562306a36Sopenharmony_ci};
380662306a36Sopenharmony_ci
380762306a36Sopenharmony_cistatic __init int net_inuse_init(void)
380862306a36Sopenharmony_ci{
380962306a36Sopenharmony_ci	if (register_pernet_subsys(&net_inuse_ops))
381062306a36Sopenharmony_ci		panic("Cannot initialize net inuse counters");
381162306a36Sopenharmony_ci
381262306a36Sopenharmony_ci	return 0;
381362306a36Sopenharmony_ci}
381462306a36Sopenharmony_ci
381562306a36Sopenharmony_cicore_initcall(net_inuse_init);
381662306a36Sopenharmony_ci
381762306a36Sopenharmony_cistatic int assign_proto_idx(struct proto *prot)
381862306a36Sopenharmony_ci{
381962306a36Sopenharmony_ci	prot->inuse_idx = find_first_zero_bit(proto_inuse_idx, PROTO_INUSE_NR);
382062306a36Sopenharmony_ci
382162306a36Sopenharmony_ci	if (unlikely(prot->inuse_idx == PROTO_INUSE_NR - 1)) {
382262306a36Sopenharmony_ci		pr_err("PROTO_INUSE_NR exhausted\n");
382362306a36Sopenharmony_ci		return -ENOSPC;
382462306a36Sopenharmony_ci	}
382562306a36Sopenharmony_ci
382662306a36Sopenharmony_ci	set_bit(prot->inuse_idx, proto_inuse_idx);
382762306a36Sopenharmony_ci	return 0;
382862306a36Sopenharmony_ci}
382962306a36Sopenharmony_ci
383062306a36Sopenharmony_cistatic void release_proto_idx(struct proto *prot)
383162306a36Sopenharmony_ci{
383262306a36Sopenharmony_ci	if (prot->inuse_idx != PROTO_INUSE_NR - 1)
383362306a36Sopenharmony_ci		clear_bit(prot->inuse_idx, proto_inuse_idx);
383462306a36Sopenharmony_ci}
383562306a36Sopenharmony_ci#else
383662306a36Sopenharmony_cistatic inline int assign_proto_idx(struct proto *prot)
383762306a36Sopenharmony_ci{
383862306a36Sopenharmony_ci	return 0;
383962306a36Sopenharmony_ci}
384062306a36Sopenharmony_ci
384162306a36Sopenharmony_cistatic inline void release_proto_idx(struct proto *prot)
384262306a36Sopenharmony_ci{
384362306a36Sopenharmony_ci}
384462306a36Sopenharmony_ci
384562306a36Sopenharmony_ci#endif
384662306a36Sopenharmony_ci
384762306a36Sopenharmony_cistatic void tw_prot_cleanup(struct timewait_sock_ops *twsk_prot)
384862306a36Sopenharmony_ci{
384962306a36Sopenharmony_ci	if (!twsk_prot)
385062306a36Sopenharmony_ci		return;
385162306a36Sopenharmony_ci	kfree(twsk_prot->twsk_slab_name);
385262306a36Sopenharmony_ci	twsk_prot->twsk_slab_name = NULL;
385362306a36Sopenharmony_ci	kmem_cache_destroy(twsk_prot->twsk_slab);
385462306a36Sopenharmony_ci	twsk_prot->twsk_slab = NULL;
385562306a36Sopenharmony_ci}
385662306a36Sopenharmony_ci
385762306a36Sopenharmony_cistatic int tw_prot_init(const struct proto *prot)
385862306a36Sopenharmony_ci{
385962306a36Sopenharmony_ci	struct timewait_sock_ops *twsk_prot = prot->twsk_prot;
386062306a36Sopenharmony_ci
386162306a36Sopenharmony_ci	if (!twsk_prot)
386262306a36Sopenharmony_ci		return 0;
386362306a36Sopenharmony_ci
386462306a36Sopenharmony_ci	twsk_prot->twsk_slab_name = kasprintf(GFP_KERNEL, "tw_sock_%s",
386562306a36Sopenharmony_ci					      prot->name);
386662306a36Sopenharmony_ci	if (!twsk_prot->twsk_slab_name)
386762306a36Sopenharmony_ci		return -ENOMEM;
386862306a36Sopenharmony_ci
386962306a36Sopenharmony_ci	twsk_prot->twsk_slab =
387062306a36Sopenharmony_ci		kmem_cache_create(twsk_prot->twsk_slab_name,
387162306a36Sopenharmony_ci				  twsk_prot->twsk_obj_size, 0,
387262306a36Sopenharmony_ci				  SLAB_ACCOUNT | prot->slab_flags,
387362306a36Sopenharmony_ci				  NULL);
387462306a36Sopenharmony_ci	if (!twsk_prot->twsk_slab) {
387562306a36Sopenharmony_ci		pr_crit("%s: Can't create timewait sock SLAB cache!\n",
387662306a36Sopenharmony_ci			prot->name);
387762306a36Sopenharmony_ci		return -ENOMEM;
387862306a36Sopenharmony_ci	}
387962306a36Sopenharmony_ci
388062306a36Sopenharmony_ci	return 0;
388162306a36Sopenharmony_ci}
388262306a36Sopenharmony_ci
388362306a36Sopenharmony_cistatic void req_prot_cleanup(struct request_sock_ops *rsk_prot)
388462306a36Sopenharmony_ci{
388562306a36Sopenharmony_ci	if (!rsk_prot)
388662306a36Sopenharmony_ci		return;
388762306a36Sopenharmony_ci	kfree(rsk_prot->slab_name);
388862306a36Sopenharmony_ci	rsk_prot->slab_name = NULL;
388962306a36Sopenharmony_ci	kmem_cache_destroy(rsk_prot->slab);
389062306a36Sopenharmony_ci	rsk_prot->slab = NULL;
389162306a36Sopenharmony_ci}
389262306a36Sopenharmony_ci
389362306a36Sopenharmony_cistatic int req_prot_init(const struct proto *prot)
389462306a36Sopenharmony_ci{
389562306a36Sopenharmony_ci	struct request_sock_ops *rsk_prot = prot->rsk_prot;
389662306a36Sopenharmony_ci
389762306a36Sopenharmony_ci	if (!rsk_prot)
389862306a36Sopenharmony_ci		return 0;
389962306a36Sopenharmony_ci
390062306a36Sopenharmony_ci	rsk_prot->slab_name = kasprintf(GFP_KERNEL, "request_sock_%s",
390162306a36Sopenharmony_ci					prot->name);
390262306a36Sopenharmony_ci	if (!rsk_prot->slab_name)
390362306a36Sopenharmony_ci		return -ENOMEM;
390462306a36Sopenharmony_ci
390562306a36Sopenharmony_ci	rsk_prot->slab = kmem_cache_create(rsk_prot->slab_name,
390662306a36Sopenharmony_ci					   rsk_prot->obj_size, 0,
390762306a36Sopenharmony_ci					   SLAB_ACCOUNT | prot->slab_flags,
390862306a36Sopenharmony_ci					   NULL);
390962306a36Sopenharmony_ci
391062306a36Sopenharmony_ci	if (!rsk_prot->slab) {
391162306a36Sopenharmony_ci		pr_crit("%s: Can't create request sock SLAB cache!\n",
391262306a36Sopenharmony_ci			prot->name);
391362306a36Sopenharmony_ci		return -ENOMEM;
391462306a36Sopenharmony_ci	}
391562306a36Sopenharmony_ci	return 0;
391662306a36Sopenharmony_ci}
391762306a36Sopenharmony_ci
391862306a36Sopenharmony_ciint proto_register(struct proto *prot, int alloc_slab)
391962306a36Sopenharmony_ci{
392062306a36Sopenharmony_ci	int ret = -ENOBUFS;
392162306a36Sopenharmony_ci
392262306a36Sopenharmony_ci	if (prot->memory_allocated && !prot->sysctl_mem) {
392362306a36Sopenharmony_ci		pr_err("%s: missing sysctl_mem\n", prot->name);
392462306a36Sopenharmony_ci		return -EINVAL;
392562306a36Sopenharmony_ci	}
392662306a36Sopenharmony_ci	if (prot->memory_allocated && !prot->per_cpu_fw_alloc) {
392762306a36Sopenharmony_ci		pr_err("%s: missing per_cpu_fw_alloc\n", prot->name);
392862306a36Sopenharmony_ci		return -EINVAL;
392962306a36Sopenharmony_ci	}
393062306a36Sopenharmony_ci	if (alloc_slab) {
393162306a36Sopenharmony_ci		prot->slab = kmem_cache_create_usercopy(prot->name,
393262306a36Sopenharmony_ci					prot->obj_size, 0,
393362306a36Sopenharmony_ci					SLAB_HWCACHE_ALIGN | SLAB_ACCOUNT |
393462306a36Sopenharmony_ci					prot->slab_flags,
393562306a36Sopenharmony_ci					prot->useroffset, prot->usersize,
393662306a36Sopenharmony_ci					NULL);
393762306a36Sopenharmony_ci
393862306a36Sopenharmony_ci		if (prot->slab == NULL) {
393962306a36Sopenharmony_ci			pr_crit("%s: Can't create sock SLAB cache!\n",
394062306a36Sopenharmony_ci				prot->name);
394162306a36Sopenharmony_ci			goto out;
394262306a36Sopenharmony_ci		}
394362306a36Sopenharmony_ci
394462306a36Sopenharmony_ci		if (req_prot_init(prot))
394562306a36Sopenharmony_ci			goto out_free_request_sock_slab;
394662306a36Sopenharmony_ci
394762306a36Sopenharmony_ci		if (tw_prot_init(prot))
394862306a36Sopenharmony_ci			goto out_free_timewait_sock_slab;
394962306a36Sopenharmony_ci	}
395062306a36Sopenharmony_ci
395162306a36Sopenharmony_ci	mutex_lock(&proto_list_mutex);
395262306a36Sopenharmony_ci	ret = assign_proto_idx(prot);
395362306a36Sopenharmony_ci	if (ret) {
395462306a36Sopenharmony_ci		mutex_unlock(&proto_list_mutex);
395562306a36Sopenharmony_ci		goto out_free_timewait_sock_slab;
395662306a36Sopenharmony_ci	}
395762306a36Sopenharmony_ci	list_add(&prot->node, &proto_list);
395862306a36Sopenharmony_ci	mutex_unlock(&proto_list_mutex);
395962306a36Sopenharmony_ci	return ret;
396062306a36Sopenharmony_ci
396162306a36Sopenharmony_ciout_free_timewait_sock_slab:
396262306a36Sopenharmony_ci	if (alloc_slab)
396362306a36Sopenharmony_ci		tw_prot_cleanup(prot->twsk_prot);
396462306a36Sopenharmony_ciout_free_request_sock_slab:
396562306a36Sopenharmony_ci	if (alloc_slab) {
396662306a36Sopenharmony_ci		req_prot_cleanup(prot->rsk_prot);
396762306a36Sopenharmony_ci
396862306a36Sopenharmony_ci		kmem_cache_destroy(prot->slab);
396962306a36Sopenharmony_ci		prot->slab = NULL;
397062306a36Sopenharmony_ci	}
397162306a36Sopenharmony_ciout:
397262306a36Sopenharmony_ci	return ret;
397362306a36Sopenharmony_ci}
397462306a36Sopenharmony_ciEXPORT_SYMBOL(proto_register);
397562306a36Sopenharmony_ci
397662306a36Sopenharmony_civoid proto_unregister(struct proto *prot)
397762306a36Sopenharmony_ci{
397862306a36Sopenharmony_ci	mutex_lock(&proto_list_mutex);
397962306a36Sopenharmony_ci	release_proto_idx(prot);
398062306a36Sopenharmony_ci	list_del(&prot->node);
398162306a36Sopenharmony_ci	mutex_unlock(&proto_list_mutex);
398262306a36Sopenharmony_ci
398362306a36Sopenharmony_ci	kmem_cache_destroy(prot->slab);
398462306a36Sopenharmony_ci	prot->slab = NULL;
398562306a36Sopenharmony_ci
398662306a36Sopenharmony_ci	req_prot_cleanup(prot->rsk_prot);
398762306a36Sopenharmony_ci	tw_prot_cleanup(prot->twsk_prot);
398862306a36Sopenharmony_ci}
398962306a36Sopenharmony_ciEXPORT_SYMBOL(proto_unregister);
399062306a36Sopenharmony_ci
399162306a36Sopenharmony_ciint sock_load_diag_module(int family, int protocol)
399262306a36Sopenharmony_ci{
399362306a36Sopenharmony_ci	if (!protocol) {
399462306a36Sopenharmony_ci		if (!sock_is_registered(family))
399562306a36Sopenharmony_ci			return -ENOENT;
399662306a36Sopenharmony_ci
399762306a36Sopenharmony_ci		return request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK,
399862306a36Sopenharmony_ci				      NETLINK_SOCK_DIAG, family);
399962306a36Sopenharmony_ci	}
400062306a36Sopenharmony_ci
400162306a36Sopenharmony_ci#ifdef CONFIG_INET
400262306a36Sopenharmony_ci	if (family == AF_INET &&
400362306a36Sopenharmony_ci	    protocol != IPPROTO_RAW &&
400462306a36Sopenharmony_ci	    protocol < MAX_INET_PROTOS &&
400562306a36Sopenharmony_ci	    !rcu_access_pointer(inet_protos[protocol]))
400662306a36Sopenharmony_ci		return -ENOENT;
400762306a36Sopenharmony_ci#endif
400862306a36Sopenharmony_ci
400962306a36Sopenharmony_ci	return request_module("net-pf-%d-proto-%d-type-%d-%d", PF_NETLINK,
401062306a36Sopenharmony_ci			      NETLINK_SOCK_DIAG, family, protocol);
401162306a36Sopenharmony_ci}
401262306a36Sopenharmony_ciEXPORT_SYMBOL(sock_load_diag_module);
401362306a36Sopenharmony_ci
401462306a36Sopenharmony_ci#ifdef CONFIG_PROC_FS
401562306a36Sopenharmony_cistatic void *proto_seq_start(struct seq_file *seq, loff_t *pos)
401662306a36Sopenharmony_ci	__acquires(proto_list_mutex)
401762306a36Sopenharmony_ci{
401862306a36Sopenharmony_ci	mutex_lock(&proto_list_mutex);
401962306a36Sopenharmony_ci	return seq_list_start_head(&proto_list, *pos);
402062306a36Sopenharmony_ci}
402162306a36Sopenharmony_ci
402262306a36Sopenharmony_cistatic void *proto_seq_next(struct seq_file *seq, void *v, loff_t *pos)
402362306a36Sopenharmony_ci{
402462306a36Sopenharmony_ci	return seq_list_next(v, &proto_list, pos);
402562306a36Sopenharmony_ci}
402662306a36Sopenharmony_ci
402762306a36Sopenharmony_cistatic void proto_seq_stop(struct seq_file *seq, void *v)
402862306a36Sopenharmony_ci	__releases(proto_list_mutex)
402962306a36Sopenharmony_ci{
403062306a36Sopenharmony_ci	mutex_unlock(&proto_list_mutex);
403162306a36Sopenharmony_ci}
403262306a36Sopenharmony_ci
403362306a36Sopenharmony_cistatic char proto_method_implemented(const void *method)
403462306a36Sopenharmony_ci{
403562306a36Sopenharmony_ci	return method == NULL ? 'n' : 'y';
403662306a36Sopenharmony_ci}
403762306a36Sopenharmony_cistatic long sock_prot_memory_allocated(struct proto *proto)
403862306a36Sopenharmony_ci{
403962306a36Sopenharmony_ci	return proto->memory_allocated != NULL ? proto_memory_allocated(proto) : -1L;
404062306a36Sopenharmony_ci}
404162306a36Sopenharmony_ci
404262306a36Sopenharmony_cistatic const char *sock_prot_memory_pressure(struct proto *proto)
404362306a36Sopenharmony_ci{
404462306a36Sopenharmony_ci	return proto->memory_pressure != NULL ?
404562306a36Sopenharmony_ci	proto_memory_pressure(proto) ? "yes" : "no" : "NI";
404662306a36Sopenharmony_ci}
404762306a36Sopenharmony_ci
404862306a36Sopenharmony_cistatic void proto_seq_printf(struct seq_file *seq, struct proto *proto)
404962306a36Sopenharmony_ci{
405062306a36Sopenharmony_ci
405162306a36Sopenharmony_ci	seq_printf(seq, "%-9s %4u %6d  %6ld   %-3s %6u   %-3s  %-10s "
405262306a36Sopenharmony_ci			"%2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c\n",
405362306a36Sopenharmony_ci		   proto->name,
405462306a36Sopenharmony_ci		   proto->obj_size,
405562306a36Sopenharmony_ci		   sock_prot_inuse_get(seq_file_net(seq), proto),
405662306a36Sopenharmony_ci		   sock_prot_memory_allocated(proto),
405762306a36Sopenharmony_ci		   sock_prot_memory_pressure(proto),
405862306a36Sopenharmony_ci		   proto->max_header,
405962306a36Sopenharmony_ci		   proto->slab == NULL ? "no" : "yes",
406062306a36Sopenharmony_ci		   module_name(proto->owner),
406162306a36Sopenharmony_ci		   proto_method_implemented(proto->close),
406262306a36Sopenharmony_ci		   proto_method_implemented(proto->connect),
406362306a36Sopenharmony_ci		   proto_method_implemented(proto->disconnect),
406462306a36Sopenharmony_ci		   proto_method_implemented(proto->accept),
406562306a36Sopenharmony_ci		   proto_method_implemented(proto->ioctl),
406662306a36Sopenharmony_ci		   proto_method_implemented(proto->init),
406762306a36Sopenharmony_ci		   proto_method_implemented(proto->destroy),
406862306a36Sopenharmony_ci		   proto_method_implemented(proto->shutdown),
406962306a36Sopenharmony_ci		   proto_method_implemented(proto->setsockopt),
407062306a36Sopenharmony_ci		   proto_method_implemented(proto->getsockopt),
407162306a36Sopenharmony_ci		   proto_method_implemented(proto->sendmsg),
407262306a36Sopenharmony_ci		   proto_method_implemented(proto->recvmsg),
407362306a36Sopenharmony_ci		   proto_method_implemented(proto->bind),
407462306a36Sopenharmony_ci		   proto_method_implemented(proto->backlog_rcv),
407562306a36Sopenharmony_ci		   proto_method_implemented(proto->hash),
407662306a36Sopenharmony_ci		   proto_method_implemented(proto->unhash),
407762306a36Sopenharmony_ci		   proto_method_implemented(proto->get_port),
407862306a36Sopenharmony_ci		   proto_method_implemented(proto->enter_memory_pressure));
407962306a36Sopenharmony_ci}
408062306a36Sopenharmony_ci
408162306a36Sopenharmony_cistatic int proto_seq_show(struct seq_file *seq, void *v)
408262306a36Sopenharmony_ci{
408362306a36Sopenharmony_ci	if (v == &proto_list)
408462306a36Sopenharmony_ci		seq_printf(seq, "%-9s %-4s %-8s %-6s %-5s %-7s %-4s %-10s %s",
408562306a36Sopenharmony_ci			   "protocol",
408662306a36Sopenharmony_ci			   "size",
408762306a36Sopenharmony_ci			   "sockets",
408862306a36Sopenharmony_ci			   "memory",
408962306a36Sopenharmony_ci			   "press",
409062306a36Sopenharmony_ci			   "maxhdr",
409162306a36Sopenharmony_ci			   "slab",
409262306a36Sopenharmony_ci			   "module",
409362306a36Sopenharmony_ci			   "cl co di ac io in de sh ss gs se re bi br ha uh gp em\n");
409462306a36Sopenharmony_ci	else
409562306a36Sopenharmony_ci		proto_seq_printf(seq, list_entry(v, struct proto, node));
409662306a36Sopenharmony_ci	return 0;
409762306a36Sopenharmony_ci}
409862306a36Sopenharmony_ci
409962306a36Sopenharmony_cistatic const struct seq_operations proto_seq_ops = {
410062306a36Sopenharmony_ci	.start  = proto_seq_start,
410162306a36Sopenharmony_ci	.next   = proto_seq_next,
410262306a36Sopenharmony_ci	.stop   = proto_seq_stop,
410362306a36Sopenharmony_ci	.show   = proto_seq_show,
410462306a36Sopenharmony_ci};
410562306a36Sopenharmony_ci
410662306a36Sopenharmony_cistatic __net_init int proto_init_net(struct net *net)
410762306a36Sopenharmony_ci{
410862306a36Sopenharmony_ci	if (!proc_create_net("protocols", 0444, net->proc_net, &proto_seq_ops,
410962306a36Sopenharmony_ci			sizeof(struct seq_net_private)))
411062306a36Sopenharmony_ci		return -ENOMEM;
411162306a36Sopenharmony_ci
411262306a36Sopenharmony_ci	return 0;
411362306a36Sopenharmony_ci}
411462306a36Sopenharmony_ci
411562306a36Sopenharmony_cistatic __net_exit void proto_exit_net(struct net *net)
411662306a36Sopenharmony_ci{
411762306a36Sopenharmony_ci	remove_proc_entry("protocols", net->proc_net);
411862306a36Sopenharmony_ci}
411962306a36Sopenharmony_ci
412062306a36Sopenharmony_ci
412162306a36Sopenharmony_cistatic __net_initdata struct pernet_operations proto_net_ops = {
412262306a36Sopenharmony_ci	.init = proto_init_net,
412362306a36Sopenharmony_ci	.exit = proto_exit_net,
412462306a36Sopenharmony_ci};
412562306a36Sopenharmony_ci
412662306a36Sopenharmony_cistatic int __init proto_init(void)
412762306a36Sopenharmony_ci{
412862306a36Sopenharmony_ci	return register_pernet_subsys(&proto_net_ops);
412962306a36Sopenharmony_ci}
413062306a36Sopenharmony_ci
413162306a36Sopenharmony_cisubsys_initcall(proto_init);
413262306a36Sopenharmony_ci
413362306a36Sopenharmony_ci#endif /* PROC_FS */
413462306a36Sopenharmony_ci
413562306a36Sopenharmony_ci#ifdef CONFIG_NET_RX_BUSY_POLL
413662306a36Sopenharmony_cibool sk_busy_loop_end(void *p, unsigned long start_time)
413762306a36Sopenharmony_ci{
413862306a36Sopenharmony_ci	struct sock *sk = p;
413962306a36Sopenharmony_ci
414062306a36Sopenharmony_ci	if (!skb_queue_empty_lockless(&sk->sk_receive_queue))
414162306a36Sopenharmony_ci		return true;
414262306a36Sopenharmony_ci
414362306a36Sopenharmony_ci	if (sk_is_udp(sk) &&
414462306a36Sopenharmony_ci	    !skb_queue_empty_lockless(&udp_sk(sk)->reader_queue))
414562306a36Sopenharmony_ci		return true;
414662306a36Sopenharmony_ci
414762306a36Sopenharmony_ci	return sk_busy_loop_timeout(sk, start_time);
414862306a36Sopenharmony_ci}
414962306a36Sopenharmony_ciEXPORT_SYMBOL(sk_busy_loop_end);
415062306a36Sopenharmony_ci#endif /* CONFIG_NET_RX_BUSY_POLL */
415162306a36Sopenharmony_ci
415262306a36Sopenharmony_ciint sock_bind_add(struct sock *sk, struct sockaddr *addr, int addr_len)
415362306a36Sopenharmony_ci{
415462306a36Sopenharmony_ci	if (!sk->sk_prot->bind_add)
415562306a36Sopenharmony_ci		return -EOPNOTSUPP;
415662306a36Sopenharmony_ci	return sk->sk_prot->bind_add(sk, addr, addr_len);
415762306a36Sopenharmony_ci}
415862306a36Sopenharmony_ciEXPORT_SYMBOL(sock_bind_add);
415962306a36Sopenharmony_ci
416062306a36Sopenharmony_ci/* Copy 'size' bytes from userspace and return `size` back to userspace */
416162306a36Sopenharmony_ciint sock_ioctl_inout(struct sock *sk, unsigned int cmd,
416262306a36Sopenharmony_ci		     void __user *arg, void *karg, size_t size)
416362306a36Sopenharmony_ci{
416462306a36Sopenharmony_ci	int ret;
416562306a36Sopenharmony_ci
416662306a36Sopenharmony_ci	if (copy_from_user(karg, arg, size))
416762306a36Sopenharmony_ci		return -EFAULT;
416862306a36Sopenharmony_ci
416962306a36Sopenharmony_ci	ret = READ_ONCE(sk->sk_prot)->ioctl(sk, cmd, karg);
417062306a36Sopenharmony_ci	if (ret)
417162306a36Sopenharmony_ci		return ret;
417262306a36Sopenharmony_ci
417362306a36Sopenharmony_ci	if (copy_to_user(arg, karg, size))
417462306a36Sopenharmony_ci		return -EFAULT;
417562306a36Sopenharmony_ci
417662306a36Sopenharmony_ci	return 0;
417762306a36Sopenharmony_ci}
417862306a36Sopenharmony_ciEXPORT_SYMBOL(sock_ioctl_inout);
417962306a36Sopenharmony_ci
418062306a36Sopenharmony_ci/* This is the most common ioctl prep function, where the result (4 bytes) is
418162306a36Sopenharmony_ci * copied back to userspace if the ioctl() returns successfully. No input is
418262306a36Sopenharmony_ci * copied from userspace as input argument.
418362306a36Sopenharmony_ci */
418462306a36Sopenharmony_cistatic int sock_ioctl_out(struct sock *sk, unsigned int cmd, void __user *arg)
418562306a36Sopenharmony_ci{
418662306a36Sopenharmony_ci	int ret, karg = 0;
418762306a36Sopenharmony_ci
418862306a36Sopenharmony_ci	ret = READ_ONCE(sk->sk_prot)->ioctl(sk, cmd, &karg);
418962306a36Sopenharmony_ci	if (ret)
419062306a36Sopenharmony_ci		return ret;
419162306a36Sopenharmony_ci
419262306a36Sopenharmony_ci	return put_user(karg, (int __user *)arg);
419362306a36Sopenharmony_ci}
419462306a36Sopenharmony_ci
419562306a36Sopenharmony_ci/* A wrapper around sock ioctls, which copies the data from userspace
419662306a36Sopenharmony_ci * (depending on the protocol/ioctl), and copies back the result to userspace.
419762306a36Sopenharmony_ci * The main motivation for this function is to pass kernel memory to the
419862306a36Sopenharmony_ci * protocol ioctl callbacks, instead of userspace memory.
419962306a36Sopenharmony_ci */
420062306a36Sopenharmony_ciint sk_ioctl(struct sock *sk, unsigned int cmd, void __user *arg)
420162306a36Sopenharmony_ci{
420262306a36Sopenharmony_ci	int rc = 1;
420362306a36Sopenharmony_ci
420462306a36Sopenharmony_ci	if (sk->sk_type == SOCK_RAW && sk->sk_family == AF_INET)
420562306a36Sopenharmony_ci		rc = ipmr_sk_ioctl(sk, cmd, arg);
420662306a36Sopenharmony_ci	else if (sk->sk_type == SOCK_RAW && sk->sk_family == AF_INET6)
420762306a36Sopenharmony_ci		rc = ip6mr_sk_ioctl(sk, cmd, arg);
420862306a36Sopenharmony_ci	else if (sk_is_phonet(sk))
420962306a36Sopenharmony_ci		rc = phonet_sk_ioctl(sk, cmd, arg);
421062306a36Sopenharmony_ci
421162306a36Sopenharmony_ci	/* If ioctl was processed, returns its value */
421262306a36Sopenharmony_ci	if (rc <= 0)
421362306a36Sopenharmony_ci		return rc;
421462306a36Sopenharmony_ci
421562306a36Sopenharmony_ci	/* Otherwise call the default handler */
421662306a36Sopenharmony_ci	return sock_ioctl_out(sk, cmd, arg);
421762306a36Sopenharmony_ci}
421862306a36Sopenharmony_ciEXPORT_SYMBOL(sk_ioctl);
4219