-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEZH8oZUiU471FcZm+ONu9yGCSaT4FAmW64xYACgkQONu9yGCS aT7kVA/+KKlE3UFuGmV1ZmiHagHF+oRZKSk9m97F5zgfAcEHAcTnnuikzvJHuepU 4hPMsH+tTXafOJLh81bv7IH3RhHtvmQZPQyWUw7ysY9ms/7CZxjkuirxLWI3evUG lre7OiApyOPkxERBfA5f9r2D1ufXC742xcAdaXrn+GSZd4nuId5f0IbHmfdNv/MV zTt6+0qRU3TMpsUdqp0rIm/0KUXtopCDFf2fI/lIImAvN2onuiqDy+TC0FJ0ErTQ C3wTEi1j9u6l3AO51OYm57TbKj/KmVOcQdcQyskHGHbB+7nS9z29LXQyorRUKqkv KTs739kgG8GH0ZegTwPVPCx5t1SBzy8fuzI2c2MMVfNCT6rWJVS7brzeb7zDLuRT 9pSr9MnoQNYMhJ3IlPvgPHKwvpP4t2el7Z8noVTRXHDjrkC238gloHwvH78/b2ao bXO3DRKTzB4Vv/Q8YUPFmj5fhPqz5lnK6idr4r72JSlzfjxtYoPAKwYihDGxmeLN mWikAPepLqoGg/P2ztKhV/fL9TVhJB+d2YM5op/b+pUxZtYdiJODefFF1ebBbF34 sRG12htP7GV/MTkxC7Yu0h3vS3HWVHugHMBIXXUnqlOANMUbyAMEQW+xkdS/W5bd QnowcQr+DT1A5b9P1bYXB7efNiHENxo/jvuJTrzZmLioy1MPqeE= =219k -----END PGP SIGNATURE----- Merge 6.1.76 into android-6.1 Changes in 6.1.76 usb: dwc3: gadget: Refactor EP0 forced stall/restart into a separate API usb: dwc3: gadget: Queue PM runtime idle on disconnect event usb: dwc3: gadget: Handle EP0 request dequeuing properly Revert "nSVM: Check for reserved encodings of TLB_CONTROL in nested VMCB" iio: adc: ad7091r: Set alert bit in config register iio: adc: ad7091r: Allow users to configure device events ext4: allow for the last group to be marked as trimmed arm64: properly install vmlinuz.efi OPP: Pass rounded rate to _set_opp() btrfs: sysfs: validate scrub_speed_max value crypto: api - Disallow identical driver names PM: hibernate: Enforce ordering during image compression/decompression hwrng: core - Fix page fault dead lock on mmap-ed hwrng crypto: s390/aes - Fix buffer overread in CTR mode s390/vfio-ap: unpin pages on gisc registration failure PM / devfreq: Fix buffer overflow in trans_stat_show media: imx355: Enable runtime PM before registering async sub-device rpmsg: virtio: Free driver_override when rpmsg_remove() media: ov9734: Enable runtime PM before registering async sub-device s390/vfio-ap: always filter entire AP matrix s390/vfio-ap: loop over the shadow APCB when filtering guest's AP configuration s390/vfio-ap: let on_scan_complete() callback filter matrix and update guest's APCB mips: Fix max_mapnr being uninitialized on early stages bus: mhi: host: Add alignment check for event ring read pointer bus: mhi: host: Drop chan lock before queuing buffers bus: mhi: host: Add spinlock to protect WP access when queueing TREs parisc/firmware: Fix F-extend for PDC addresses parisc/power: Fix power soft-off button emulation on qemu async: Split async_schedule_node_domain() async: Introduce async_schedule_dev_nocall() iio: adc: ad7091r: Enable internal vref if external vref is not supplied dmaengine: fix NULL pointer in channel unregistration function scsi: ufs: core: Remove the ufshcd_hba_exit() call from ufshcd_async_scan() arm64: dts: qcom: sc7180: fix USB wakeup interrupt types arm64: dts: qcom: sdm845: fix USB wakeup interrupt types arm64: dts: qcom: sm8150: fix USB wakeup interrupt types arm64: dts: qcom: sc7280: fix usb_1 wakeup interrupt types arm64: dts: qcom: sdm845: fix USB DP/DM HS PHY interrupts arm64: dts: qcom: sm8150: fix USB DP/DM HS PHY interrupts lsm: new security_file_ioctl_compat() hook docs: kernel_abi.py: fix command injection scripts/get_abi: fix source path leak media: videobuf2-dma-sg: fix vmap callback mmc: core: Use mrq.sbc in close-ended ffu mmc: mmc_spi: remove custom DMA mapped buffers media: mtk-jpeg: Fix use after free bug due to error path handling in mtk_jpeg_dec_device_run arm64: Rename ARM64_WORKAROUND_2966298 rtc: cmos: Use ACPI alarm for non-Intel x86 systems too rtc: Adjust failure return code for cmos_set_alarm() rtc: mc146818-lib: Adjust failure return code for mc146818_get_time() rtc: Add support for configuring the UIP timeout for RTC reads rtc: Extend timeout for waiting for UIP to clear to 1s nouveau/vmm: don't set addr on the fail path to avoid warning ubifs: ubifs_symlink: Fix memleak of inode->i_link in error path mm/rmap: fix misplaced parenthesis of a likely() mm/sparsemem: fix race in accessing memory_section->usage rename(): fix the locking of subdirectories serial: sc16is7xx: improve regmap debugfs by using one regmap per port serial: sc16is7xx: remove wasteful static buffer in sc16is7xx_regmap_name() serial: sc16is7xx: remove global regmap from struct sc16is7xx_port serial: sc16is7xx: remove unused line structure member serial: sc16is7xx: change EFR lock to operate on each channels serial: sc16is7xx: convert from _raw_ to _noinc_ regmap functions for FIFO serial: sc16is7xx: fix invalid sc16is7xx_lines bitfield in case of probe error serial: sc16is7xx: remove obsolete loop in sc16is7xx_port_irq() serial: sc16is7xx: improve do/while loop in sc16is7xx_irq() LoongArch/smp: Call rcutree_report_cpu_starting() earlier mm: page_alloc: unreserve highatomic page blocks before oom ksmbd: set v2 lease version on lease upgrade ksmbd: fix potential circular locking issue in smb2_set_ea() ksmbd: don't increment epoch if current state and request state are same ksmbd: send lease break notification on FILE_RENAME_INFORMATION ksmbd: Add missing set_freezable() for freezable kthread Revert "drm/amd: Enable PCIe PME from D3" drm/amd/display: pbn_div need be updated for hotplug event wifi: mac80211: fix potential sta-link leak net/smc: fix illegal rmb_desc access in SMC-D connection dump tcp: make sure init the accept_queue's spinlocks once bnxt_en: Wait for FLR to complete during probe vlan: skip nested type that is not IFLA_VLAN_QOS_MAPPING llc: make llc_ui_sendmsg() more robust against bonding changes llc: Drop support for ETH_P_TR_802_2. udp: fix busy polling net: fix removing a namespace with conflicting altnames tun: fix missing dropped counter in tun_xdp_act tun: add missing rx stats accounting in tun_xdp_act net: micrel: Fix PTP frame parsing for lan8814 net/rds: Fix UBSAN: array-index-out-of-bounds in rds_cmsg_recv netfs, fscache: Prevent Oops in fscache_put_cache() tracing: Ensure visibility when inserting an element into tracing_map afs: Hide silly-rename files from userspace tcp: Add memory barrier to tcp_push() netlink: fix potential sleeping issue in mqueue_flush_file ipv6: init the accept_queue's spinlocks in inet6_create net/mlx5: DR, Use the right GVMI number for drop action net/mlx5: DR, Can't go to uplink vport on RX rule net/mlx5: Use mlx5 device constant for selecting CQ period mode for ASO net/mlx5e: Allow software parsing when IPsec crypto is enabled net/mlx5e: fix a double-free in arfs_create_groups net/mlx5e: fix a potential double-free in fs_any_create_groups rcu: Defer RCU kthreads wakeup when CPU is dying netfilter: nft_limit: reject configurations that cause integer overflow btrfs: fix infinite directory reads btrfs: set last dir index to the current last index when opening dir btrfs: refresh dir last index during a rewinddir(3) call btrfs: fix race between reading a directory and adding entries to it netfilter: nf_tables: restrict anonymous set and map names to 16 bytes netfilter: nf_tables: validate NFPROTO_* family net: stmmac: Wait a bit for the reset to take effect net: mvpp2: clear BM pool before initialization selftests: netdevsim: fix the udp_tunnel_nic test fjes: fix memleaks in fjes_hw_setup net: fec: fix the unhandled context fault from smmu nbd: always initialize struct msghdr completely btrfs: avoid copying BTRFS_ROOT_SUBVOL_DEAD flag to snapshot of subvolume being deleted btrfs: ref-verify: free ref cache before clearing mount opt btrfs: tree-checker: fix inline ref size in error messages btrfs: don't warn if discard range is not aligned to sector btrfs: defrag: reject unknown flags of btrfs_ioctl_defrag_range_args btrfs: don't abort filesystem when attempting to snapshot deleted subvolume rbd: don't move requests to the running list on errors exec: Fix error handling in begin_new_exec() wifi: iwlwifi: fix a memory corruption hv_netvsc: Calculate correct ring size when PAGE_SIZE is not 4 Kbytes netfilter: nft_chain_filter: handle NETDEV_UNREGISTER for inet/ingress basechain netfilter: nf_tables: reject QUEUE/DROP verdict parameters platform/x86: p2sb: Allow p2sb_bar() calls during PCI device probe ksmbd: fix global oob in ksmbd_nl_policy firmware: arm_scmi: Check mailbox/SMT channel for consistency xfs: read only mounts with fsopen mount API are busted gpiolib: acpi: Ignore touchpad wakeup on GPD G1619-04 cpufreq: intel_pstate: Refine computation of P-state for given frequency drm: Don't unref the same fb many times by mistake due to deadlock handling drm/bridge: nxp-ptn3460: fix i2c_master_send() error checking drm/tidss: Fix atomic_flush check drm/amd/display: Disable PSR-SU on Parade 0803 TCON again platform/x86: intel-uncore-freq: Fix types in sysfs callbacks drm/bridge: nxp-ptn3460: simplify some error checking drm/amd/display: Port DENTIST hang and TDR fixes to OTG disable W/A drm/amdgpu/pm: Fix the power source flag error erofs: get rid of the remaining kmap_atomic() erofs: fix lz4 inplace decompression media: ov13b10: Support device probe in non-zero ACPI D state media: ov13b10: Enable runtime PM before registering async sub-device bus: mhi: ep: Do not allocate event ring element on stack PM: core: Remove unnecessary (void *) conversions PM: sleep: Fix possible deadlocks in core system-wide PM code thermal: intel: hfi: Refactor enabling code into helper functions thermal: intel: hfi: Disable an HFI instance when all its CPUs go offline thermal: intel: hfi: Add syscore callbacks for system-wide PM fs/pipe: move check to pipe_has_watch_queue() pipe: wakeup wr_wait after setting max_usage ARM: dts: qcom: sdx55: fix USB wakeup interrupt types ARM: dts: samsung: exynos4210-i9100: Unconditionally enable LDO12 ARM: dts: qcom: sdx55: fix pdc '#interrupt-cells' ARM: dts: qcom: sdx55: fix USB DP/DM HS PHY interrupts ARM: dts: qcom: sdx55: fix USB SS wakeup dlm: use kernel_connect() and kernel_bind() serial: core: Provide port lock wrappers serial: sc16is7xx: Use port lock wrappers serial: sc16is7xx: fix unconditional activation of THRI interrupt btrfs: zoned: factor out prepare_allocation_zoned() btrfs: zoned: optimize hint byte for zoned allocator drm/panel-edp: drm/panel-edp: Fix AUO B116XAK01 name and timing Revert "powerpc/64s: Increase default stack size to 32KB" drm/bridge: parade-ps8640: Wait for HPD when doing an AUX transfer drm: panel-simple: add missing bus flags for Tianma tm070jvhg[30/33] drm/bridge: sii902x: Use devm_regulator_bulk_get_enable() drm/bridge: sii902x: Fix probing race issue drm/bridge: sii902x: Fix audio codec unregistration drm/bridge: parade-ps8640: Ensure bridge is suspended in .post_disable() drm/bridge: parade-ps8640: Make sure we drop the AUX mutex in the error case drm/exynos: fix accidental on-stack copy of exynos_drm_plane drm/exynos: gsc: minor fix for loop iteration in gsc_runtime_resume gpio: eic-sprd: Clear interrupt after set the interrupt type block: Move checking GENHD_FL_NO_PART to bdev_add_partition() drm/bridge: anx7625: Ensure bridge is suspended in disable() spi: bcm-qspi: fix SFDP BFPT read by usig mspi read spi: fix finalize message on error return MIPS: lantiq: register smp_ops on non-smp platforms cxl/region:Fix overflow issue in alloc_hpa() mips: Call lose_fpu(0) before initializing fcr31 in mips_set_personality_nan tick/sched: Preserve number of idle sleeps across CPU hotplug events x86/entry/ia32: Ensure s32 is sign extended to s64 serial: core: fix kernel-doc for uart_port_unlock_irqrestore() net/mlx5e: Handle hardware IPsec limits events Linux 6.1.76 Change-Id: I4725561e2ca5df042a1fe307af701e7d5e2d06c8 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
553 lines
13 KiB
C
553 lines
13 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/* Copyright (c) 2017 - 2018 Covalent IO, Inc. http://covalent.io */
|
|
|
|
#ifndef _LINUX_SKMSG_H
|
|
#define _LINUX_SKMSG_H
|
|
|
|
#include <linux/bpf.h>
|
|
#include <linux/filter.h>
|
|
#include <linux/scatterlist.h>
|
|
#include <linux/skbuff.h>
|
|
|
|
#include <net/sock.h>
|
|
#include <net/tcp.h>
|
|
#include <net/strparser.h>
|
|
|
|
#define MAX_MSG_FRAGS MAX_SKB_FRAGS
|
|
#define NR_MSG_FRAG_IDS (MAX_MSG_FRAGS + 1)
|
|
|
|
enum __sk_action {
|
|
__SK_DROP = 0,
|
|
__SK_PASS,
|
|
__SK_REDIRECT,
|
|
__SK_NONE,
|
|
};
|
|
|
|
struct sk_msg_sg {
|
|
u32 start;
|
|
u32 curr;
|
|
u32 end;
|
|
u32 size;
|
|
u32 copybreak;
|
|
DECLARE_BITMAP(copy, MAX_MSG_FRAGS + 2);
|
|
/* The extra two elements:
|
|
* 1) used for chaining the front and sections when the list becomes
|
|
* partitioned (e.g. end < start). The crypto APIs require the
|
|
* chaining;
|
|
* 2) to chain tailer SG entries after the message.
|
|
*/
|
|
struct scatterlist data[MAX_MSG_FRAGS + 2];
|
|
};
|
|
|
|
/* UAPI in filter.c depends on struct sk_msg_sg being first element. */
|
|
struct sk_msg {
|
|
struct sk_msg_sg sg;
|
|
void *data;
|
|
void *data_end;
|
|
u32 apply_bytes;
|
|
u32 cork_bytes;
|
|
u32 flags;
|
|
struct sk_buff *skb;
|
|
struct sock *sk_redir;
|
|
struct sock *sk;
|
|
struct list_head list;
|
|
};
|
|
|
|
struct sk_psock_progs {
|
|
struct bpf_prog *msg_parser;
|
|
struct bpf_prog *stream_parser;
|
|
struct bpf_prog *stream_verdict;
|
|
struct bpf_prog *skb_verdict;
|
|
};
|
|
|
|
enum sk_psock_state_bits {
|
|
SK_PSOCK_TX_ENABLED,
|
|
SK_PSOCK_RX_STRP_ENABLED,
|
|
};
|
|
|
|
struct sk_psock_link {
|
|
struct list_head list;
|
|
struct bpf_map *map;
|
|
void *link_raw;
|
|
};
|
|
|
|
struct sk_psock_work_state {
|
|
u32 len;
|
|
u32 off;
|
|
};
|
|
|
|
struct sk_psock {
|
|
struct sock *sk;
|
|
struct sock *sk_redir;
|
|
u32 apply_bytes;
|
|
u32 cork_bytes;
|
|
u32 eval;
|
|
bool redir_ingress; /* undefined if sk_redir is null */
|
|
struct sk_msg *cork;
|
|
struct sk_psock_progs progs;
|
|
#if IS_ENABLED(CONFIG_BPF_STREAM_PARSER)
|
|
struct strparser strp;
|
|
#endif
|
|
struct sk_buff_head ingress_skb;
|
|
struct list_head ingress_msg;
|
|
spinlock_t ingress_lock;
|
|
unsigned long state;
|
|
struct list_head link;
|
|
spinlock_t link_lock;
|
|
refcount_t refcnt;
|
|
void (*saved_unhash)(struct sock *sk);
|
|
void (*saved_destroy)(struct sock *sk);
|
|
void (*saved_close)(struct sock *sk, long timeout);
|
|
void (*saved_write_space)(struct sock *sk);
|
|
void (*saved_data_ready)(struct sock *sk);
|
|
int (*psock_update_sk_prot)(struct sock *sk, struct sk_psock *psock,
|
|
bool restore);
|
|
struct proto *sk_proto;
|
|
struct mutex work_mutex;
|
|
struct sk_psock_work_state work_state;
|
|
struct delayed_work work;
|
|
struct rcu_work rwork;
|
|
};
|
|
|
|
int sk_msg_alloc(struct sock *sk, struct sk_msg *msg, int len,
|
|
int elem_first_coalesce);
|
|
int sk_msg_clone(struct sock *sk, struct sk_msg *dst, struct sk_msg *src,
|
|
u32 off, u32 len);
|
|
void sk_msg_trim(struct sock *sk, struct sk_msg *msg, int len);
|
|
int sk_msg_free(struct sock *sk, struct sk_msg *msg);
|
|
int sk_msg_free_nocharge(struct sock *sk, struct sk_msg *msg);
|
|
void sk_msg_free_partial(struct sock *sk, struct sk_msg *msg, u32 bytes);
|
|
void sk_msg_free_partial_nocharge(struct sock *sk, struct sk_msg *msg,
|
|
u32 bytes);
|
|
|
|
void sk_msg_return(struct sock *sk, struct sk_msg *msg, int bytes);
|
|
void sk_msg_return_zero(struct sock *sk, struct sk_msg *msg, int bytes);
|
|
|
|
int sk_msg_zerocopy_from_iter(struct sock *sk, struct iov_iter *from,
|
|
struct sk_msg *msg, u32 bytes);
|
|
int sk_msg_memcopy_from_iter(struct sock *sk, struct iov_iter *from,
|
|
struct sk_msg *msg, u32 bytes);
|
|
int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,
|
|
int len, int flags);
|
|
bool sk_msg_is_readable(struct sock *sk);
|
|
|
|
static inline void sk_msg_check_to_free(struct sk_msg *msg, u32 i, u32 bytes)
|
|
{
|
|
WARN_ON(i == msg->sg.end && bytes);
|
|
}
|
|
|
|
static inline void sk_msg_apply_bytes(struct sk_psock *psock, u32 bytes)
|
|
{
|
|
if (psock->apply_bytes) {
|
|
if (psock->apply_bytes < bytes)
|
|
psock->apply_bytes = 0;
|
|
else
|
|
psock->apply_bytes -= bytes;
|
|
}
|
|
}
|
|
|
|
static inline u32 sk_msg_iter_dist(u32 start, u32 end)
|
|
{
|
|
return end >= start ? end - start : end + (NR_MSG_FRAG_IDS - start);
|
|
}
|
|
|
|
#define sk_msg_iter_var_prev(var) \
|
|
do { \
|
|
if (var == 0) \
|
|
var = NR_MSG_FRAG_IDS - 1; \
|
|
else \
|
|
var--; \
|
|
} while (0)
|
|
|
|
#define sk_msg_iter_var_next(var) \
|
|
do { \
|
|
var++; \
|
|
if (var == NR_MSG_FRAG_IDS) \
|
|
var = 0; \
|
|
} while (0)
|
|
|
|
#define sk_msg_iter_prev(msg, which) \
|
|
sk_msg_iter_var_prev(msg->sg.which)
|
|
|
|
#define sk_msg_iter_next(msg, which) \
|
|
sk_msg_iter_var_next(msg->sg.which)
|
|
|
|
static inline void sk_msg_init(struct sk_msg *msg)
|
|
{
|
|
BUILD_BUG_ON(ARRAY_SIZE(msg->sg.data) - 1 != NR_MSG_FRAG_IDS);
|
|
memset(msg, 0, sizeof(*msg));
|
|
sg_init_marker(msg->sg.data, NR_MSG_FRAG_IDS);
|
|
}
|
|
|
|
static inline void sk_msg_xfer(struct sk_msg *dst, struct sk_msg *src,
|
|
int which, u32 size)
|
|
{
|
|
dst->sg.data[which] = src->sg.data[which];
|
|
dst->sg.data[which].length = size;
|
|
dst->sg.size += size;
|
|
src->sg.size -= size;
|
|
src->sg.data[which].length -= size;
|
|
src->sg.data[which].offset += size;
|
|
}
|
|
|
|
static inline void sk_msg_xfer_full(struct sk_msg *dst, struct sk_msg *src)
|
|
{
|
|
memcpy(dst, src, sizeof(*src));
|
|
sk_msg_init(src);
|
|
}
|
|
|
|
static inline bool sk_msg_full(const struct sk_msg *msg)
|
|
{
|
|
return sk_msg_iter_dist(msg->sg.start, msg->sg.end) == MAX_MSG_FRAGS;
|
|
}
|
|
|
|
static inline u32 sk_msg_elem_used(const struct sk_msg *msg)
|
|
{
|
|
return sk_msg_iter_dist(msg->sg.start, msg->sg.end);
|
|
}
|
|
|
|
static inline struct scatterlist *sk_msg_elem(struct sk_msg *msg, int which)
|
|
{
|
|
return &msg->sg.data[which];
|
|
}
|
|
|
|
static inline struct scatterlist sk_msg_elem_cpy(struct sk_msg *msg, int which)
|
|
{
|
|
return msg->sg.data[which];
|
|
}
|
|
|
|
static inline struct page *sk_msg_page(struct sk_msg *msg, int which)
|
|
{
|
|
return sg_page(sk_msg_elem(msg, which));
|
|
}
|
|
|
|
static inline bool sk_msg_to_ingress(const struct sk_msg *msg)
|
|
{
|
|
return msg->flags & BPF_F_INGRESS;
|
|
}
|
|
|
|
static inline void sk_msg_compute_data_pointers(struct sk_msg *msg)
|
|
{
|
|
struct scatterlist *sge = sk_msg_elem(msg, msg->sg.start);
|
|
|
|
if (test_bit(msg->sg.start, msg->sg.copy)) {
|
|
msg->data = NULL;
|
|
msg->data_end = NULL;
|
|
} else {
|
|
msg->data = sg_virt(sge);
|
|
msg->data_end = msg->data + sge->length;
|
|
}
|
|
}
|
|
|
|
static inline void sk_msg_page_add(struct sk_msg *msg, struct page *page,
|
|
u32 len, u32 offset)
|
|
{
|
|
struct scatterlist *sge;
|
|
|
|
get_page(page);
|
|
sge = sk_msg_elem(msg, msg->sg.end);
|
|
sg_set_page(sge, page, len, offset);
|
|
sg_unmark_end(sge);
|
|
|
|
__set_bit(msg->sg.end, msg->sg.copy);
|
|
msg->sg.size += len;
|
|
sk_msg_iter_next(msg, end);
|
|
}
|
|
|
|
static inline void sk_msg_sg_copy(struct sk_msg *msg, u32 i, bool copy_state)
|
|
{
|
|
do {
|
|
if (copy_state)
|
|
__set_bit(i, msg->sg.copy);
|
|
else
|
|
__clear_bit(i, msg->sg.copy);
|
|
sk_msg_iter_var_next(i);
|
|
if (i == msg->sg.end)
|
|
break;
|
|
} while (1);
|
|
}
|
|
|
|
static inline void sk_msg_sg_copy_set(struct sk_msg *msg, u32 start)
|
|
{
|
|
sk_msg_sg_copy(msg, start, true);
|
|
}
|
|
|
|
static inline void sk_msg_sg_copy_clear(struct sk_msg *msg, u32 start)
|
|
{
|
|
sk_msg_sg_copy(msg, start, false);
|
|
}
|
|
|
|
static inline struct sk_psock *sk_psock(const struct sock *sk)
|
|
{
|
|
return __rcu_dereference_sk_user_data_with_flags(sk,
|
|
SK_USER_DATA_PSOCK);
|
|
}
|
|
|
|
static inline void sk_psock_set_state(struct sk_psock *psock,
|
|
enum sk_psock_state_bits bit)
|
|
{
|
|
set_bit(bit, &psock->state);
|
|
}
|
|
|
|
static inline void sk_psock_clear_state(struct sk_psock *psock,
|
|
enum sk_psock_state_bits bit)
|
|
{
|
|
clear_bit(bit, &psock->state);
|
|
}
|
|
|
|
static inline bool sk_psock_test_state(const struct sk_psock *psock,
|
|
enum sk_psock_state_bits bit)
|
|
{
|
|
return test_bit(bit, &psock->state);
|
|
}
|
|
|
|
static inline void sock_drop(struct sock *sk, struct sk_buff *skb)
|
|
{
|
|
sk_drops_add(sk, skb);
|
|
kfree_skb(skb);
|
|
}
|
|
|
|
static inline void sk_psock_queue_msg(struct sk_psock *psock,
|
|
struct sk_msg *msg)
|
|
{
|
|
spin_lock_bh(&psock->ingress_lock);
|
|
if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED))
|
|
list_add_tail(&msg->list, &psock->ingress_msg);
|
|
else {
|
|
sk_msg_free(psock->sk, msg);
|
|
kfree(msg);
|
|
}
|
|
spin_unlock_bh(&psock->ingress_lock);
|
|
}
|
|
|
|
static inline struct sk_msg *sk_psock_dequeue_msg(struct sk_psock *psock)
|
|
{
|
|
struct sk_msg *msg;
|
|
|
|
spin_lock_bh(&psock->ingress_lock);
|
|
msg = list_first_entry_or_null(&psock->ingress_msg, struct sk_msg, list);
|
|
if (msg)
|
|
list_del(&msg->list);
|
|
spin_unlock_bh(&psock->ingress_lock);
|
|
return msg;
|
|
}
|
|
|
|
static inline struct sk_msg *sk_psock_peek_msg(struct sk_psock *psock)
|
|
{
|
|
struct sk_msg *msg;
|
|
|
|
spin_lock_bh(&psock->ingress_lock);
|
|
msg = list_first_entry_or_null(&psock->ingress_msg, struct sk_msg, list);
|
|
spin_unlock_bh(&psock->ingress_lock);
|
|
return msg;
|
|
}
|
|
|
|
static inline struct sk_msg *sk_psock_next_msg(struct sk_psock *psock,
|
|
struct sk_msg *msg)
|
|
{
|
|
struct sk_msg *ret;
|
|
|
|
spin_lock_bh(&psock->ingress_lock);
|
|
if (list_is_last(&msg->list, &psock->ingress_msg))
|
|
ret = NULL;
|
|
else
|
|
ret = list_next_entry(msg, list);
|
|
spin_unlock_bh(&psock->ingress_lock);
|
|
return ret;
|
|
}
|
|
|
|
static inline bool sk_psock_queue_empty(const struct sk_psock *psock)
|
|
{
|
|
return psock ? list_empty(&psock->ingress_msg) : true;
|
|
}
|
|
|
|
static inline void kfree_sk_msg(struct sk_msg *msg)
|
|
{
|
|
if (msg->skb)
|
|
consume_skb(msg->skb);
|
|
kfree(msg);
|
|
}
|
|
|
|
static inline void sk_psock_report_error(struct sk_psock *psock, int err)
|
|
{
|
|
struct sock *sk = psock->sk;
|
|
|
|
sk->sk_err = err;
|
|
sk_error_report(sk);
|
|
}
|
|
|
|
struct sk_psock *sk_psock_init(struct sock *sk, int node);
|
|
void sk_psock_stop(struct sk_psock *psock);
|
|
|
|
#if IS_ENABLED(CONFIG_BPF_STREAM_PARSER)
|
|
int sk_psock_init_strp(struct sock *sk, struct sk_psock *psock);
|
|
void sk_psock_start_strp(struct sock *sk, struct sk_psock *psock);
|
|
void sk_psock_stop_strp(struct sock *sk, struct sk_psock *psock);
|
|
#else
|
|
static inline int sk_psock_init_strp(struct sock *sk, struct sk_psock *psock)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline void sk_psock_start_strp(struct sock *sk, struct sk_psock *psock)
|
|
{
|
|
}
|
|
|
|
static inline void sk_psock_stop_strp(struct sock *sk, struct sk_psock *psock)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
void sk_psock_start_verdict(struct sock *sk, struct sk_psock *psock);
|
|
void sk_psock_stop_verdict(struct sock *sk, struct sk_psock *psock);
|
|
|
|
int sk_psock_msg_verdict(struct sock *sk, struct sk_psock *psock,
|
|
struct sk_msg *msg);
|
|
|
|
static inline struct sk_psock_link *sk_psock_init_link(void)
|
|
{
|
|
return kzalloc(sizeof(struct sk_psock_link),
|
|
GFP_ATOMIC | __GFP_NOWARN);
|
|
}
|
|
|
|
static inline void sk_psock_free_link(struct sk_psock_link *link)
|
|
{
|
|
kfree(link);
|
|
}
|
|
|
|
struct sk_psock_link *sk_psock_link_pop(struct sk_psock *psock);
|
|
|
|
static inline void sk_psock_cork_free(struct sk_psock *psock)
|
|
{
|
|
if (psock->cork) {
|
|
sk_msg_free(psock->sk, psock->cork);
|
|
kfree(psock->cork);
|
|
psock->cork = NULL;
|
|
}
|
|
}
|
|
|
|
static inline void sk_psock_restore_proto(struct sock *sk,
|
|
struct sk_psock *psock)
|
|
{
|
|
if (psock->psock_update_sk_prot)
|
|
psock->psock_update_sk_prot(sk, psock, true);
|
|
}
|
|
|
|
static inline struct sk_psock *sk_psock_get(struct sock *sk)
|
|
{
|
|
struct sk_psock *psock;
|
|
|
|
rcu_read_lock();
|
|
psock = sk_psock(sk);
|
|
if (psock && !refcount_inc_not_zero(&psock->refcnt))
|
|
psock = NULL;
|
|
rcu_read_unlock();
|
|
return psock;
|
|
}
|
|
|
|
void sk_psock_drop(struct sock *sk, struct sk_psock *psock);
|
|
|
|
static inline void sk_psock_put(struct sock *sk, struct sk_psock *psock)
|
|
{
|
|
if (refcount_dec_and_test(&psock->refcnt))
|
|
sk_psock_drop(sk, psock);
|
|
}
|
|
|
|
static inline void sk_psock_data_ready(struct sock *sk, struct sk_psock *psock)
|
|
{
|
|
if (psock->saved_data_ready)
|
|
psock->saved_data_ready(sk);
|
|
else
|
|
sk->sk_data_ready(sk);
|
|
}
|
|
|
|
static inline void psock_set_prog(struct bpf_prog **pprog,
|
|
struct bpf_prog *prog)
|
|
{
|
|
prog = xchg(pprog, prog);
|
|
if (prog)
|
|
bpf_prog_put(prog);
|
|
}
|
|
|
|
static inline int psock_replace_prog(struct bpf_prog **pprog,
|
|
struct bpf_prog *prog,
|
|
struct bpf_prog *old)
|
|
{
|
|
if (cmpxchg(pprog, old, prog) != old)
|
|
return -ENOENT;
|
|
|
|
if (old)
|
|
bpf_prog_put(old);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static inline void psock_progs_drop(struct sk_psock_progs *progs)
|
|
{
|
|
psock_set_prog(&progs->msg_parser, NULL);
|
|
psock_set_prog(&progs->stream_parser, NULL);
|
|
psock_set_prog(&progs->stream_verdict, NULL);
|
|
psock_set_prog(&progs->skb_verdict, NULL);
|
|
}
|
|
|
|
int sk_psock_tls_strp_read(struct sk_psock *psock, struct sk_buff *skb);
|
|
|
|
static inline bool sk_psock_strp_enabled(struct sk_psock *psock)
|
|
{
|
|
if (!psock)
|
|
return false;
|
|
return !!psock->saved_data_ready;
|
|
}
|
|
|
|
#if IS_ENABLED(CONFIG_NET_SOCK_MSG)
|
|
|
|
#define BPF_F_STRPARSER (1UL << 1)
|
|
|
|
/* We only have two bits so far. */
|
|
#define BPF_F_PTR_MASK ~(BPF_F_INGRESS | BPF_F_STRPARSER)
|
|
|
|
static inline bool skb_bpf_strparser(const struct sk_buff *skb)
|
|
{
|
|
unsigned long sk_redir = skb->_sk_redir;
|
|
|
|
return sk_redir & BPF_F_STRPARSER;
|
|
}
|
|
|
|
static inline void skb_bpf_set_strparser(struct sk_buff *skb)
|
|
{
|
|
skb->_sk_redir |= BPF_F_STRPARSER;
|
|
}
|
|
|
|
static inline bool skb_bpf_ingress(const struct sk_buff *skb)
|
|
{
|
|
unsigned long sk_redir = skb->_sk_redir;
|
|
|
|
return sk_redir & BPF_F_INGRESS;
|
|
}
|
|
|
|
static inline void skb_bpf_set_ingress(struct sk_buff *skb)
|
|
{
|
|
skb->_sk_redir |= BPF_F_INGRESS;
|
|
}
|
|
|
|
static inline void skb_bpf_set_redir(struct sk_buff *skb, struct sock *sk_redir,
|
|
bool ingress)
|
|
{
|
|
skb->_sk_redir = (unsigned long)sk_redir;
|
|
if (ingress)
|
|
skb->_sk_redir |= BPF_F_INGRESS;
|
|
}
|
|
|
|
static inline struct sock *skb_bpf_redirect_fetch(const struct sk_buff *skb)
|
|
{
|
|
unsigned long sk_redir = skb->_sk_redir;
|
|
|
|
return (struct sock *)(sk_redir & BPF_F_PTR_MASK);
|
|
}
|
|
|
|
static inline void skb_bpf_redirect_clear(struct sk_buff *skb)
|
|
{
|
|
skb->_sk_redir = 0;
|
|
}
|
|
#endif /* CONFIG_NET_SOCK_MSG */
|
|
#endif /* _LINUX_SKMSG_H */
|