mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Merge tag 'bpf-next-7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
Pull bpf updates from Alexei Starovoitov:
- Support associating BPF program with struct_ops (Amery Hung)
- Switch BPF local storage to rqspinlock and remove recursion detection
counters which were causing false positives (Amery Hung)
- Fix live registers marking for indirect jumps (Anton Protopopov)
- Introduce execution context detection BPF helpers (Changwoo Min)
- Improve verifier precision for 32bit sign extension pattern
(Cupertino Miranda)
- Optimize BTF type lookup by sorting vmlinux BTF and doing binary
search (Donglin Peng)
- Allow states pruning for misc/invalid slots in iterator loops (Eduard
Zingerman)
- In preparation for ASAN support in BPF arenas teach libbpf to move
global BPF variables to the end of the region and enable arena kfuncs
while holding locks (Emil Tsalapatis)
- Introduce support for implicit arguments in kfuncs and migrate a
number of them to new API. This is a prerequisite for cgroup
sub-schedulers in sched-ext (Ihor Solodrai)
- Fix incorrect copied_seq calculation in sockmap (Jiayuan Chen)
- Fix ORC stack unwind from kprobe_multi (Jiri Olsa)
- Speed up fentry attach by using single ftrace direct ops in BPF
trampolines (Jiri Olsa)
- Require frozen map for calculating map hash (KP Singh)
- Fix lock entry creation in TAS fallback in rqspinlock (Kumar
Kartikeya Dwivedi)
- Allow user space to select cpu in lookup/update operations on per-cpu
array and hash maps (Leon Hwang)
- Make kfuncs return trusted pointers by default (Matt Bobrowski)
- Introduce "fsession" support where single BPF program is executed
upon entry and exit from traced kernel function (Menglong Dong)
- Allow bpf_timer and bpf_wq use in all programs types (Mykyta
Yatsenko, Andrii Nakryiko, Kumar Kartikeya Dwivedi, Alexei
Starovoitov)
- Make KF_TRUSTED_ARGS the default for all kfuncs and clean up their
definition across the tree (Puranjay Mohan)
- Allow BPF arena calls from non-sleepable context (Puranjay Mohan)
- Improve register id comparison logic in the verifier and extend
linked registers with negative offsets (Puranjay Mohan)
- In preparation for BPF-OOM introduce kfuncs to access memcg events
(Roman Gushchin)
- Use CFI compatible destructor kfunc type (Sami Tolvanen)
- Add bitwise tracking for BPF_END in the verifier (Tianci Cao)
- Add range tracking for BPF_DIV and BPF_MOD in the verifier (Yazhou
Tang)
- Make BPF selftests work with 64k page size (Yonghong Song)
* tag 'bpf-next-7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next: (268 commits)
selftests/bpf: Fix outdated test on storage->smap
selftests/bpf: Choose another percpu variable in bpf for btf_dump test
selftests/bpf: Remove test_task_storage_map_stress_lookup
selftests/bpf: Update task_local_storage/task_storage_nodeadlock test
selftests/bpf: Update task_local_storage/recursion test
selftests/bpf: Update sk_storage_omem_uncharge test
bpf: Switch to bpf_selem_unlink_nofail in bpf_local_storage_{map_free, destroy}
bpf: Support lockless unlink when freeing map or local storage
bpf: Prepare for bpf_selem_unlink_nofail()
bpf: Remove unused percpu counter from bpf_local_storage_map_free
bpf: Remove cgroup local storage percpu counter
bpf: Remove task local storage percpu counter
bpf: Change local_storage->lock and b->lock to rqspinlock
bpf: Convert bpf_selem_unlink to failable
bpf: Convert bpf_selem_link_map to failable
bpf: Convert bpf_selem_unlink_map to failable
bpf: Select bpf_local_storage_map_bucket based on bpf_local_storage
selftests/xsk: fix number of Tx frags in invalid packet
selftests/xsk: properly handle batch ending in the middle of a packet
bpf: Prevent reentrance into call_rcu_tasks_trace()
...
This commit is contained in:
@@ -34,11 +34,12 @@ following types:
|
||||
- ``BPF_PROG_TYPE_LWT_IN``
|
||||
- ``BPF_PROG_TYPE_LWT_OUT``
|
||||
- ``BPF_PROG_TYPE_LWT_XMIT``
|
||||
- ``BPF_PROG_TYPE_LWT_SEG6LOCAL``
|
||||
- ``BPF_PROG_TYPE_FLOW_DISSECTOR``
|
||||
- ``BPF_PROG_TYPE_STRUCT_OPS``
|
||||
- ``BPF_PROG_TYPE_RAW_TRACEPOINT``
|
||||
- ``BPF_PROG_TYPE_SYSCALL``
|
||||
- ``BPF_PROG_TYPE_TRACING``
|
||||
- ``BPF_PROG_TYPE_NETFILTER``
|
||||
|
||||
When using the ``BPF_PROG_RUN`` command, userspace supplies an input context
|
||||
object and (for program types operating on network packets) a buffer containing
|
||||
|
||||
+238
-216
File diff suppressed because it is too large
Load Diff
@@ -38,7 +38,7 @@ bash 4.2 bash --version
|
||||
binutils 2.30 ld -v
|
||||
flex 2.5.35 flex --version
|
||||
bison 2.0 bison --version
|
||||
pahole 1.16 pahole --version
|
||||
pahole 1.22 pahole --version
|
||||
util-linux 2.10o mount --version
|
||||
kmod 13 depmod -V
|
||||
e2fsprogs 1.41.4 e2fsck -V
|
||||
@@ -143,7 +143,7 @@ pahole
|
||||
|
||||
Since Linux 5.2, if CONFIG_DEBUG_INFO_BTF is selected, the build system
|
||||
generates BTF (BPF Type Format) from DWARF in vmlinux, a bit later from kernel
|
||||
modules as well. This requires pahole v1.16 or later.
|
||||
modules as well. This requires pahole v1.22 or later.
|
||||
|
||||
It is found in the 'dwarves' or 'pahole' distro packages or from
|
||||
https://fedorapeople.org/~acme/dwarves/.
|
||||
|
||||
@@ -43,7 +43,6 @@ options should be enabled to use sched_ext:
|
||||
CONFIG_DEBUG_INFO_BTF=y
|
||||
CONFIG_BPF_JIT_ALWAYS_ON=y
|
||||
CONFIG_BPF_JIT_DEFAULT_ON=y
|
||||
CONFIG_PAHOLE_HAS_SPLIT_BTF=y
|
||||
CONFIG_PAHOLE_HAS_BTF_TAG=y
|
||||
|
||||
sched_ext is used only when the BPF scheduler is loaded and running.
|
||||
|
||||
+11
@@ -4772,6 +4772,7 @@ F: net/sched/act_bpf.c
|
||||
F: net/sched/cls_bpf.c
|
||||
F: samples/bpf/
|
||||
F: scripts/bpf_doc.py
|
||||
F: scripts/gen-btf.sh
|
||||
F: scripts/Makefile.btf
|
||||
F: scripts/pahole-version.sh
|
||||
F: tools/bpf/
|
||||
@@ -4804,6 +4805,15 @@ L: bpf@vger.kernel.org
|
||||
S: Maintained
|
||||
F: tools/lib/bpf/
|
||||
|
||||
BPF [MEMORY MANAGEMENT EXTENSIONS]
|
||||
M: Roman Gushchin <roman.gushchin@linux.dev>
|
||||
M: JP Kobryn <inwardvessel@gmail.com>
|
||||
M: Shakeel Butt <shakeel.butt@linux.dev>
|
||||
L: bpf@vger.kernel.org
|
||||
L: linux-mm@kvack.org
|
||||
S: Maintained
|
||||
F: mm/bpf_memcontrol.c
|
||||
|
||||
BPF [MISC]
|
||||
L: bpf@vger.kernel.org
|
||||
S: Odd Fixes
|
||||
@@ -4853,6 +4863,7 @@ S: Maintained
|
||||
F: Documentation/bpf/prog_lsm.rst
|
||||
F: include/linux/bpf_lsm.h
|
||||
F: kernel/bpf/bpf_lsm.c
|
||||
F: kernel/bpf/bpf_lsm_proto.c
|
||||
F: kernel/trace/bpf_trace.c
|
||||
F: security/bpf/
|
||||
|
||||
|
||||
@@ -708,11 +708,12 @@ endif
|
||||
|
||||
# The expansion should be delayed until arch/$(SRCARCH)/Makefile is included.
|
||||
# Some architectures define CROSS_COMPILE in arch/$(SRCARCH)/Makefile.
|
||||
# CC_VERSION_TEXT and RUSTC_VERSION_TEXT are referenced from Kconfig (so they
|
||||
# need export), and from include/config/auto.conf.cmd to detect the compiler
|
||||
# upgrade.
|
||||
# CC_VERSION_TEXT, RUSTC_VERSION_TEXT and PAHOLE_VERSION are referenced from
|
||||
# Kconfig (so they need export), and from include/config/auto.conf.cmd to
|
||||
# detect the version changes between builds.
|
||||
CC_VERSION_TEXT = $(subst $(pound),,$(shell LC_ALL=C $(CC) --version 2>/dev/null | head -n 1))
|
||||
RUSTC_VERSION_TEXT = $(subst $(pound),,$(shell $(RUSTC) --version 2>/dev/null))
|
||||
PAHOLE_VERSION = $(shell $(srctree)/scripts/pahole-version.sh $(PAHOLE))
|
||||
|
||||
ifneq ($(findstring clang,$(CC_VERSION_TEXT)),)
|
||||
include $(srctree)/scripts/Makefile.clang
|
||||
@@ -733,7 +734,7 @@ ifdef config-build
|
||||
# KBUILD_DEFCONFIG may point out an alternative default configuration
|
||||
# used for 'make defconfig'
|
||||
include $(srctree)/arch/$(SRCARCH)/Makefile
|
||||
export KBUILD_DEFCONFIG KBUILD_KCONFIG CC_VERSION_TEXT RUSTC_VERSION_TEXT
|
||||
export KBUILD_DEFCONFIG KBUILD_KCONFIG CC_VERSION_TEXT RUSTC_VERSION_TEXT PAHOLE_VERSION
|
||||
|
||||
config: outputmakefile scripts_basic FORCE
|
||||
$(Q)$(MAKE) $(build)=scripts/kconfig $@
|
||||
@@ -1928,12 +1929,18 @@ clean: private rm-files := Module.symvers modules.nsdeps compile_commands.json
|
||||
PHONY += prepare
|
||||
# now expand this into a simple variable to reduce the cost of shell evaluations
|
||||
prepare: CC_VERSION_TEXT := $(CC_VERSION_TEXT)
|
||||
prepare: PAHOLE_VERSION := $(PAHOLE_VERSION)
|
||||
prepare:
|
||||
@if [ "$(CC_VERSION_TEXT)" != "$(CONFIG_CC_VERSION_TEXT)" ]; then \
|
||||
echo >&2 "warning: the compiler differs from the one used to build the kernel"; \
|
||||
echo >&2 " The kernel was built by: $(CONFIG_CC_VERSION_TEXT)"; \
|
||||
echo >&2 " You are using: $(CC_VERSION_TEXT)"; \
|
||||
fi
|
||||
@if [ "$(PAHOLE_VERSION)" != "$(CONFIG_PAHOLE_VERSION)" ]; then \
|
||||
echo >&2 "warning: pahole version differs from the one used to build the kernel"; \
|
||||
echo >&2 " The kernel was built with: $(CONFIG_PAHOLE_VERSION)"; \
|
||||
echo >&2 " You are using: $(PAHOLE_VERSION)"; \
|
||||
fi
|
||||
|
||||
PHONY += help
|
||||
help:
|
||||
|
||||
@@ -118,7 +118,7 @@ static inline void emit(const u32 insn, struct jit_ctx *ctx)
|
||||
static inline void emit_u32_data(const u32 data, struct jit_ctx *ctx)
|
||||
{
|
||||
if (ctx->image != NULL && ctx->write)
|
||||
ctx->image[ctx->idx] = data;
|
||||
ctx->image[ctx->idx] = (__force __le32)data;
|
||||
|
||||
ctx->idx++;
|
||||
}
|
||||
@@ -2503,6 +2503,12 @@ static bool is_struct_ops_tramp(const struct bpf_tramp_links *fentry_links)
|
||||
fentry_links->links[0]->link.type == BPF_LINK_TYPE_STRUCT_OPS;
|
||||
}
|
||||
|
||||
static void store_func_meta(struct jit_ctx *ctx, u64 func_meta, int func_meta_off)
|
||||
{
|
||||
emit_a64_mov_i64(A64_R(10), func_meta, ctx);
|
||||
emit(A64_STR64I(A64_R(10), A64_SP, func_meta_off), ctx);
|
||||
}
|
||||
|
||||
/* Based on the x86's implementation of arch_prepare_bpf_trampoline().
|
||||
*
|
||||
* bpf prog and function entry before bpf trampoline hooked:
|
||||
@@ -2526,7 +2532,7 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
|
||||
int regs_off;
|
||||
int retval_off;
|
||||
int bargs_off;
|
||||
int nfuncargs_off;
|
||||
int func_meta_off;
|
||||
int ip_off;
|
||||
int run_ctx_off;
|
||||
int oargs_off;
|
||||
@@ -2537,6 +2543,9 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
|
||||
bool save_ret;
|
||||
__le32 **branches = NULL;
|
||||
bool is_struct_ops = is_struct_ops_tramp(fentry);
|
||||
int cookie_off, cookie_cnt, cookie_bargs_off;
|
||||
int fsession_cnt = bpf_fsession_cnt(tlinks);
|
||||
u64 func_meta;
|
||||
|
||||
/* trampoline stack layout:
|
||||
* [ parent ip ]
|
||||
@@ -2555,10 +2564,14 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
|
||||
* [ ... ]
|
||||
* SP + bargs_off [ arg reg 1 ] for bpf
|
||||
*
|
||||
* SP + nfuncargs_off [ arg regs count ]
|
||||
* SP + func_meta_off [ regs count, etc ]
|
||||
*
|
||||
* SP + ip_off [ traced function ] BPF_TRAMP_F_IP_ARG flag
|
||||
*
|
||||
* [ stack cookie N ]
|
||||
* [ ... ]
|
||||
* SP + cookie_off [ stack cookie 1 ]
|
||||
*
|
||||
* SP + run_ctx_off [ bpf_tramp_run_ctx ]
|
||||
*
|
||||
* [ stack arg N ]
|
||||
@@ -2575,13 +2588,18 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
|
||||
/* room for bpf_tramp_run_ctx */
|
||||
stack_size += round_up(sizeof(struct bpf_tramp_run_ctx), 8);
|
||||
|
||||
cookie_off = stack_size;
|
||||
/* room for session cookies */
|
||||
cookie_cnt = bpf_fsession_cookie_cnt(tlinks);
|
||||
stack_size += cookie_cnt * 8;
|
||||
|
||||
ip_off = stack_size;
|
||||
/* room for IP address argument */
|
||||
if (flags & BPF_TRAMP_F_IP_ARG)
|
||||
stack_size += 8;
|
||||
|
||||
nfuncargs_off = stack_size;
|
||||
/* room for args count */
|
||||
func_meta_off = stack_size;
|
||||
/* room for function metadata, such as regs count */
|
||||
stack_size += 8;
|
||||
|
||||
bargs_off = stack_size;
|
||||
@@ -2639,9 +2657,9 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
|
||||
emit(A64_STR64I(A64_R(10), A64_SP, ip_off), ctx);
|
||||
}
|
||||
|
||||
/* save arg regs count*/
|
||||
emit(A64_MOVZ(1, A64_R(10), nfuncargs, 0), ctx);
|
||||
emit(A64_STR64I(A64_R(10), A64_SP, nfuncargs_off), ctx);
|
||||
/* save function metadata */
|
||||
func_meta = nfuncargs;
|
||||
store_func_meta(ctx, func_meta, func_meta_off);
|
||||
|
||||
/* save args for bpf */
|
||||
save_args(ctx, bargs_off, oargs_off, m, a, false);
|
||||
@@ -2659,10 +2677,27 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
|
||||
emit_call((const u64)__bpf_tramp_enter, ctx);
|
||||
}
|
||||
|
||||
for (i = 0; i < fentry->nr_links; i++)
|
||||
if (fsession_cnt) {
|
||||
/* clear all the session cookies' value */
|
||||
emit(A64_MOVZ(1, A64_R(10), 0, 0), ctx);
|
||||
for (int i = 0; i < cookie_cnt; i++)
|
||||
emit(A64_STR64I(A64_R(10), A64_SP, cookie_off + 8 * i), ctx);
|
||||
/* clear the return value to make sure fentry always gets 0 */
|
||||
emit(A64_STR64I(A64_R(10), A64_SP, retval_off), ctx);
|
||||
}
|
||||
|
||||
cookie_bargs_off = (bargs_off - cookie_off) / 8;
|
||||
for (i = 0; i < fentry->nr_links; i++) {
|
||||
if (bpf_prog_calls_session_cookie(fentry->links[i])) {
|
||||
u64 meta = func_meta | (cookie_bargs_off << BPF_TRAMP_COOKIE_INDEX_SHIFT);
|
||||
|
||||
store_func_meta(ctx, meta, func_meta_off);
|
||||
cookie_bargs_off--;
|
||||
}
|
||||
invoke_bpf_prog(ctx, fentry->links[i], bargs_off,
|
||||
retval_off, run_ctx_off,
|
||||
flags & BPF_TRAMP_F_RET_FENTRY_RET);
|
||||
}
|
||||
|
||||
if (fmod_ret->nr_links) {
|
||||
branches = kcalloc(fmod_ret->nr_links, sizeof(__le32 *),
|
||||
@@ -2694,9 +2729,22 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
|
||||
*branches[i] = cpu_to_le32(A64_CBNZ(1, A64_R(10), offset));
|
||||
}
|
||||
|
||||
for (i = 0; i < fexit->nr_links; i++)
|
||||
/* set the "is_return" flag for fsession */
|
||||
func_meta |= (1ULL << BPF_TRAMP_IS_RETURN_SHIFT);
|
||||
if (fsession_cnt)
|
||||
store_func_meta(ctx, func_meta, func_meta_off);
|
||||
|
||||
cookie_bargs_off = (bargs_off - cookie_off) / 8;
|
||||
for (i = 0; i < fexit->nr_links; i++) {
|
||||
if (bpf_prog_calls_session_cookie(fexit->links[i])) {
|
||||
u64 meta = func_meta | (cookie_bargs_off << BPF_TRAMP_COOKIE_INDEX_SHIFT);
|
||||
|
||||
store_func_meta(ctx, meta, func_meta_off);
|
||||
cookie_bargs_off--;
|
||||
}
|
||||
invoke_bpf_prog(ctx, fexit->links[i], bargs_off, retval_off,
|
||||
run_ctx_off, false);
|
||||
}
|
||||
|
||||
if (flags & BPF_TRAMP_F_CALL_ORIG) {
|
||||
im->ip_epilogue = ctx->ro_image + ctx->idx;
|
||||
@@ -2746,6 +2794,11 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
|
||||
return ctx->idx;
|
||||
}
|
||||
|
||||
bool bpf_jit_supports_fsession(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
|
||||
struct bpf_tramp_links *tlinks, void *func_addr)
|
||||
{
|
||||
@@ -3132,7 +3185,7 @@ void bpf_jit_free(struct bpf_prog *prog)
|
||||
bpf_jit_binary_pack_finalize(jit_data->ro_header, jit_data->header);
|
||||
kfree(jit_data);
|
||||
}
|
||||
prog->bpf_func -= cfi_get_offset();
|
||||
prog->bpf_func = (void *)prog->bpf_func - cfi_get_offset();
|
||||
hdr = bpf_jit_binary_pack_hdr(prog);
|
||||
bpf_jit_binary_pack_free(hdr, NULL);
|
||||
priv_stack_ptr = prog->aux->priv_stack_ptr;
|
||||
|
||||
@@ -336,6 +336,7 @@ config X86
|
||||
select SCHED_SMT if SMP
|
||||
select ARCH_SUPPORTS_SCHED_CLUSTER if SMP
|
||||
select ARCH_SUPPORTS_SCHED_MC if SMP
|
||||
select HAVE_SINGLE_FTRACE_DIRECT_OPS if X86_64 && DYNAMIC_FTRACE_WITH_DIRECT_CALLS
|
||||
|
||||
config INSTRUCTION_DECODER
|
||||
def_bool y
|
||||
|
||||
@@ -57,7 +57,7 @@ arch_ftrace_get_regs(struct ftrace_regs *fregs)
|
||||
}
|
||||
|
||||
#define arch_ftrace_partial_regs(regs) do { \
|
||||
regs->flags &= ~X86_EFLAGS_FIXED; \
|
||||
regs->flags |= X86_EFLAGS_FIXED; \
|
||||
regs->cs = __KERNEL_CS; \
|
||||
} while (0)
|
||||
|
||||
|
||||
@@ -364,6 +364,9 @@ SYM_CODE_START(return_to_handler)
|
||||
UNWIND_HINT_UNDEFINED
|
||||
ANNOTATE_NOENDBR
|
||||
|
||||
/* Store original rsp for pt_regs.sp value. */
|
||||
movq %rsp, %rdi
|
||||
|
||||
/* Restore return_to_handler value that got eaten by previous ret instruction. */
|
||||
subq $8, %rsp
|
||||
UNWIND_HINT_FUNC
|
||||
@@ -374,7 +377,7 @@ SYM_CODE_START(return_to_handler)
|
||||
movq %rax, RAX(%rsp)
|
||||
movq %rdx, RDX(%rsp)
|
||||
movq %rbp, RBP(%rsp)
|
||||
movq %rsp, RSP(%rsp)
|
||||
movq %rdi, RSP(%rsp)
|
||||
movq %rsp, %rdi
|
||||
|
||||
call ftrace_return_to_handler
|
||||
|
||||
+63
-25
@@ -1300,12 +1300,23 @@ static void emit_st_r12(u8 **pprog, u32 size, u32 dst_reg, int off, int imm)
|
||||
emit_st_index(pprog, size, dst_reg, X86_REG_R12, off, imm);
|
||||
}
|
||||
|
||||
static void emit_store_stack_imm64(u8 **pprog, int reg, int stack_off, u64 imm64)
|
||||
{
|
||||
/*
|
||||
* mov reg, imm64
|
||||
* mov QWORD PTR [rbp + stack_off], reg
|
||||
*/
|
||||
emit_mov_imm64(pprog, reg, imm64 >> 32, (u32) imm64);
|
||||
emit_stx(pprog, BPF_DW, BPF_REG_FP, reg, stack_off);
|
||||
}
|
||||
|
||||
static int emit_atomic_rmw(u8 **pprog, u32 atomic_op,
|
||||
u32 dst_reg, u32 src_reg, s16 off, u8 bpf_size)
|
||||
{
|
||||
u8 *prog = *pprog;
|
||||
|
||||
EMIT1(0xF0); /* lock prefix */
|
||||
if (atomic_op != BPF_XCHG)
|
||||
EMIT1(0xF0); /* lock prefix */
|
||||
|
||||
maybe_emit_mod(&prog, dst_reg, src_reg, bpf_size == BPF_DW);
|
||||
|
||||
@@ -1347,7 +1358,9 @@ static int emit_atomic_rmw_index(u8 **pprog, u32 atomic_op, u32 size,
|
||||
{
|
||||
u8 *prog = *pprog;
|
||||
|
||||
EMIT1(0xF0); /* lock prefix */
|
||||
if (atomic_op != BPF_XCHG)
|
||||
EMIT1(0xF0); /* lock prefix */
|
||||
|
||||
switch (size) {
|
||||
case BPF_W:
|
||||
EMIT1(add_3mod(0x40, dst_reg, src_reg, index_reg));
|
||||
@@ -3081,13 +3094,19 @@ static int emit_cond_near_jump(u8 **pprog, void *func, void *ip, u8 jmp_cond)
|
||||
|
||||
static int invoke_bpf(const struct btf_func_model *m, u8 **pprog,
|
||||
struct bpf_tramp_links *tl, int stack_size,
|
||||
int run_ctx_off, bool save_ret,
|
||||
void *image, void *rw_image)
|
||||
int run_ctx_off, int func_meta_off, bool save_ret,
|
||||
void *image, void *rw_image, u64 func_meta,
|
||||
int cookie_off)
|
||||
{
|
||||
int i;
|
||||
int i, cur_cookie = (cookie_off - stack_size) / 8;
|
||||
u8 *prog = *pprog;
|
||||
|
||||
for (i = 0; i < tl->nr_links; i++) {
|
||||
if (tl->links[i]->link.prog->call_session_cookie) {
|
||||
emit_store_stack_imm64(&prog, BPF_REG_0, -func_meta_off,
|
||||
func_meta | (cur_cookie << BPF_TRAMP_COOKIE_INDEX_SHIFT));
|
||||
cur_cookie--;
|
||||
}
|
||||
if (invoke_bpf_prog(m, &prog, tl->links[i], stack_size,
|
||||
run_ctx_off, save_ret, image, rw_image))
|
||||
return -EINVAL;
|
||||
@@ -3205,12 +3224,14 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
|
||||
void *func_addr)
|
||||
{
|
||||
int i, ret, nr_regs = m->nr_args, stack_size = 0;
|
||||
int regs_off, nregs_off, ip_off, run_ctx_off, arg_stack_off, rbx_off;
|
||||
int regs_off, func_meta_off, ip_off, run_ctx_off, arg_stack_off, rbx_off;
|
||||
struct bpf_tramp_links *fentry = &tlinks[BPF_TRAMP_FENTRY];
|
||||
struct bpf_tramp_links *fexit = &tlinks[BPF_TRAMP_FEXIT];
|
||||
struct bpf_tramp_links *fmod_ret = &tlinks[BPF_TRAMP_MODIFY_RETURN];
|
||||
void *orig_call = func_addr;
|
||||
int cookie_off, cookie_cnt;
|
||||
u8 **branches = NULL;
|
||||
u64 func_meta;
|
||||
u8 *prog;
|
||||
bool save_ret;
|
||||
|
||||
@@ -3246,7 +3267,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
|
||||
* [ ... ]
|
||||
* RBP - regs_off [ reg_arg1 ] program's ctx pointer
|
||||
*
|
||||
* RBP - nregs_off [ regs count ] always
|
||||
* RBP - func_meta_off [ regs count, etc ] always
|
||||
*
|
||||
* RBP - ip_off [ traced function ] BPF_TRAMP_F_IP_ARG flag
|
||||
*
|
||||
@@ -3269,15 +3290,20 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
|
||||
stack_size += nr_regs * 8;
|
||||
regs_off = stack_size;
|
||||
|
||||
/* regs count */
|
||||
/* function matedata, such as regs count */
|
||||
stack_size += 8;
|
||||
nregs_off = stack_size;
|
||||
func_meta_off = stack_size;
|
||||
|
||||
if (flags & BPF_TRAMP_F_IP_ARG)
|
||||
stack_size += 8; /* room for IP address argument */
|
||||
|
||||
ip_off = stack_size;
|
||||
|
||||
cookie_cnt = bpf_fsession_cookie_cnt(tlinks);
|
||||
/* room for session cookies */
|
||||
stack_size += cookie_cnt * 8;
|
||||
cookie_off = stack_size;
|
||||
|
||||
stack_size += 8;
|
||||
rbx_off = stack_size;
|
||||
|
||||
@@ -3345,20 +3371,13 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
|
||||
/* mov QWORD PTR [rbp - rbx_off], rbx */
|
||||
emit_stx(&prog, BPF_DW, BPF_REG_FP, BPF_REG_6, -rbx_off);
|
||||
|
||||
/* Store number of argument registers of the traced function:
|
||||
* mov rax, nr_regs
|
||||
* mov QWORD PTR [rbp - nregs_off], rax
|
||||
*/
|
||||
emit_mov_imm64(&prog, BPF_REG_0, 0, (u32) nr_regs);
|
||||
emit_stx(&prog, BPF_DW, BPF_REG_FP, BPF_REG_0, -nregs_off);
|
||||
func_meta = nr_regs;
|
||||
/* Store number of argument registers of the traced function */
|
||||
emit_store_stack_imm64(&prog, BPF_REG_0, -func_meta_off, func_meta);
|
||||
|
||||
if (flags & BPF_TRAMP_F_IP_ARG) {
|
||||
/* Store IP address of the traced function:
|
||||
* movabsq rax, func_addr
|
||||
* mov QWORD PTR [rbp - ip_off], rax
|
||||
*/
|
||||
emit_mov_imm64(&prog, BPF_REG_0, (long) func_addr >> 32, (u32) (long) func_addr);
|
||||
emit_stx(&prog, BPF_DW, BPF_REG_FP, BPF_REG_0, -ip_off);
|
||||
/* Store IP address of the traced function */
|
||||
emit_store_stack_imm64(&prog, BPF_REG_0, -ip_off, (long)func_addr);
|
||||
}
|
||||
|
||||
save_args(m, &prog, regs_off, false, flags);
|
||||
@@ -3373,9 +3392,18 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
|
||||
}
|
||||
}
|
||||
|
||||
if (bpf_fsession_cnt(tlinks)) {
|
||||
/* clear all the session cookies' value */
|
||||
for (int i = 0; i < cookie_cnt; i++)
|
||||
emit_store_stack_imm64(&prog, BPF_REG_0, -cookie_off + 8 * i, 0);
|
||||
/* clear the return value to make sure fentry always get 0 */
|
||||
emit_store_stack_imm64(&prog, BPF_REG_0, -8, 0);
|
||||
}
|
||||
|
||||
if (fentry->nr_links) {
|
||||
if (invoke_bpf(m, &prog, fentry, regs_off, run_ctx_off,
|
||||
flags & BPF_TRAMP_F_RET_FENTRY_RET, image, rw_image))
|
||||
if (invoke_bpf(m, &prog, fentry, regs_off, run_ctx_off, func_meta_off,
|
||||
flags & BPF_TRAMP_F_RET_FENTRY_RET, image, rw_image,
|
||||
func_meta, cookie_off))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -3435,9 +3463,14 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
|
||||
}
|
||||
}
|
||||
|
||||
/* set the "is_return" flag for fsession */
|
||||
func_meta |= (1ULL << BPF_TRAMP_IS_RETURN_SHIFT);
|
||||
if (bpf_fsession_cnt(tlinks))
|
||||
emit_store_stack_imm64(&prog, BPF_REG_0, -func_meta_off, func_meta);
|
||||
|
||||
if (fexit->nr_links) {
|
||||
if (invoke_bpf(m, &prog, fexit, regs_off, run_ctx_off,
|
||||
false, image, rw_image)) {
|
||||
if (invoke_bpf(m, &prog, fexit, regs_off, run_ctx_off, func_meta_off,
|
||||
false, image, rw_image, func_meta, cookie_off)) {
|
||||
ret = -EINVAL;
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -4079,3 +4112,8 @@ bool bpf_jit_supports_timed_may_goto(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool bpf_jit_supports_fsession(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -295,9 +295,6 @@ hid_bpf_get_data(struct hid_bpf_ctx *ctx, unsigned int offset, const size_t rdwr
|
||||
{
|
||||
struct hid_bpf_ctx_kern *ctx_kern;
|
||||
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
|
||||
ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
|
||||
|
||||
if (rdwr_buf_size + offset > ctx->allocated_size)
|
||||
@@ -364,7 +361,7 @@ __hid_bpf_hw_check_params(struct hid_bpf_ctx *ctx, __u8 *buf, size_t *buf__sz,
|
||||
u32 report_len;
|
||||
|
||||
/* check arguments */
|
||||
if (!ctx || !hid_ops || !buf)
|
||||
if (!hid_ops)
|
||||
return -EINVAL;
|
||||
|
||||
switch (rtype) {
|
||||
|
||||
@@ -33,11 +33,9 @@ extern int hid_bpf_try_input_report(struct hid_bpf_ctx *ctx,
|
||||
/* bpf_wq implementation */
|
||||
extern int bpf_wq_init(struct bpf_wq *wq, void *p__map, unsigned int flags) __weak __ksym;
|
||||
extern int bpf_wq_start(struct bpf_wq *wq, unsigned int flags) __weak __ksym;
|
||||
extern int bpf_wq_set_callback_impl(struct bpf_wq *wq,
|
||||
int (callback_fn)(void *map, int *key, void *value),
|
||||
unsigned int flags__k, void *aux__ign) __ksym;
|
||||
#define bpf_wq_set_callback(wq, cb, flags) \
|
||||
bpf_wq_set_callback_impl(wq, cb, flags, NULL)
|
||||
extern int bpf_wq_set_callback(struct bpf_wq *wq,
|
||||
int (*callback_fn)(void *, int *, void *),
|
||||
unsigned int flags) __weak __ksym;
|
||||
|
||||
#define HID_MAX_DESCRIPTOR_SIZE 4096
|
||||
#define HID_IGNORE_EVENT -1
|
||||
|
||||
+9
-14
@@ -68,10 +68,7 @@ __bpf_kfunc void bpf_put_file(struct file *file)
|
||||
*
|
||||
* Resolve the pathname for the supplied *path* and store it in *buf*. This BPF
|
||||
* kfunc is the safer variant of the legacy bpf_d_path() helper and should be
|
||||
* used in place of bpf_d_path() whenever possible. It enforces KF_TRUSTED_ARGS
|
||||
* semantics, meaning that the supplied *path* must itself hold a valid
|
||||
* reference, or else the BPF program will be outright rejected by the BPF
|
||||
* verifier.
|
||||
* used in place of bpf_d_path() whenever possible.
|
||||
*
|
||||
* This BPF kfunc may only be called from BPF LSM programs.
|
||||
*
|
||||
@@ -359,14 +356,13 @@ __bpf_kfunc int bpf_cgroup_read_xattr(struct cgroup *cgroup, const char *name__s
|
||||
__bpf_kfunc_end_defs();
|
||||
|
||||
BTF_KFUNCS_START(bpf_fs_kfunc_set_ids)
|
||||
BTF_ID_FLAGS(func, bpf_get_task_exe_file,
|
||||
KF_ACQUIRE | KF_TRUSTED_ARGS | KF_RET_NULL)
|
||||
BTF_ID_FLAGS(func, bpf_get_task_exe_file, KF_ACQUIRE | KF_RET_NULL)
|
||||
BTF_ID_FLAGS(func, bpf_put_file, KF_RELEASE)
|
||||
BTF_ID_FLAGS(func, bpf_path_d_path, KF_TRUSTED_ARGS)
|
||||
BTF_ID_FLAGS(func, bpf_get_dentry_xattr, KF_SLEEPABLE | KF_TRUSTED_ARGS)
|
||||
BTF_ID_FLAGS(func, bpf_get_file_xattr, KF_SLEEPABLE | KF_TRUSTED_ARGS)
|
||||
BTF_ID_FLAGS(func, bpf_set_dentry_xattr, KF_SLEEPABLE | KF_TRUSTED_ARGS)
|
||||
BTF_ID_FLAGS(func, bpf_remove_dentry_xattr, KF_SLEEPABLE | KF_TRUSTED_ARGS)
|
||||
BTF_ID_FLAGS(func, bpf_path_d_path)
|
||||
BTF_ID_FLAGS(func, bpf_get_dentry_xattr, KF_SLEEPABLE)
|
||||
BTF_ID_FLAGS(func, bpf_get_file_xattr, KF_SLEEPABLE)
|
||||
BTF_ID_FLAGS(func, bpf_set_dentry_xattr, KF_SLEEPABLE)
|
||||
BTF_ID_FLAGS(func, bpf_remove_dentry_xattr, KF_SLEEPABLE)
|
||||
BTF_KFUNCS_END(bpf_fs_kfunc_set_ids)
|
||||
|
||||
static int bpf_fs_kfuncs_filter(const struct bpf_prog *prog, u32 kfunc_id)
|
||||
@@ -377,9 +373,8 @@ static int bpf_fs_kfuncs_filter(const struct bpf_prog *prog, u32 kfunc_id)
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
/* bpf_[set|remove]_dentry_xattr.* hooks have KF_TRUSTED_ARGS and
|
||||
* KF_SLEEPABLE, so they are only available to sleepable hooks with
|
||||
* dentry arguments.
|
||||
/* bpf_[set|remove]_dentry_xattr.* hooks have KF_SLEEPABLE, so they are only
|
||||
* available to sleepable hooks with dentry arguments.
|
||||
*
|
||||
* Setting and removing xattr requires exclusive lock on dentry->d_inode.
|
||||
* Some hooks already locked d_inode, while some hooks have not locked
|
||||
|
||||
+1
-1
@@ -162,7 +162,7 @@ __bpf_kfunc int bpf_get_fsverity_digest(struct file *file, struct bpf_dynptr *di
|
||||
__bpf_kfunc_end_defs();
|
||||
|
||||
BTF_KFUNCS_START(fsverity_set_ids)
|
||||
BTF_ID_FLAGS(func, bpf_get_fsverity_digest, KF_TRUSTED_ARGS)
|
||||
BTF_ID_FLAGS(func, bpf_get_fsverity_digest)
|
||||
BTF_KFUNCS_END(fsverity_set_ids)
|
||||
|
||||
static int bpf_get_fsverity_digest_filter(const struct bpf_prog *prog, u32 kfunc_id)
|
||||
|
||||
@@ -191,7 +191,7 @@ static __always_inline int res_spin_lock(rqspinlock_t *lock)
|
||||
|
||||
#else
|
||||
|
||||
#define res_spin_lock(lock) resilient_tas_spin_lock(lock)
|
||||
#define res_spin_lock(lock) ({ grab_held_lock_entry(lock); resilient_tas_spin_lock(lock); })
|
||||
|
||||
#endif /* CONFIG_QUEUED_SPINLOCKS */
|
||||
|
||||
|
||||
@@ -172,7 +172,7 @@ void bpf_cgroup_storage_link(struct bpf_cgroup_storage *storage,
|
||||
void bpf_cgroup_storage_unlink(struct bpf_cgroup_storage *storage);
|
||||
int bpf_cgroup_storage_assign(struct bpf_prog_aux *aux, struct bpf_map *map);
|
||||
|
||||
int bpf_percpu_cgroup_storage_copy(struct bpf_map *map, void *key, void *value);
|
||||
int bpf_percpu_cgroup_storage_copy(struct bpf_map *map, void *key, void *value, u64 flags);
|
||||
int bpf_percpu_cgroup_storage_update(struct bpf_map *map, void *key,
|
||||
void *value, u64 flags);
|
||||
|
||||
@@ -470,7 +470,7 @@ static inline struct bpf_cgroup_storage *bpf_cgroup_storage_alloc(
|
||||
static inline void bpf_cgroup_storage_free(
|
||||
struct bpf_cgroup_storage *storage) {}
|
||||
static inline int bpf_percpu_cgroup_storage_copy(struct bpf_map *map, void *key,
|
||||
void *value) {
|
||||
void *value, u64 flags) {
|
||||
return 0;
|
||||
}
|
||||
static inline int bpf_percpu_cgroup_storage_update(struct bpf_map *map,
|
||||
|
||||
+170
-8
@@ -287,6 +287,7 @@ struct bpf_map_owner {
|
||||
enum bpf_prog_type type;
|
||||
bool jited;
|
||||
bool xdp_has_frags;
|
||||
bool sleepable;
|
||||
u64 storage_cookie[MAX_BPF_CGROUP_STORAGE_TYPE];
|
||||
const struct btf_type *attach_func_proto;
|
||||
enum bpf_attach_type expected_attach_type;
|
||||
@@ -673,6 +674,22 @@ void bpf_map_free_internal_structs(struct bpf_map *map, void *obj);
|
||||
int bpf_dynptr_from_file_sleepable(struct file *file, u32 flags,
|
||||
struct bpf_dynptr *ptr__uninit);
|
||||
|
||||
#if defined(CONFIG_MMU) && defined(CONFIG_64BIT)
|
||||
void *bpf_arena_alloc_pages_non_sleepable(void *p__map, void *addr__ign, u32 page_cnt, int node_id,
|
||||
u64 flags);
|
||||
void bpf_arena_free_pages_non_sleepable(void *p__map, void *ptr__ign, u32 page_cnt);
|
||||
#else
|
||||
static inline void *bpf_arena_alloc_pages_non_sleepable(void *p__map, void *addr__ign, u32 page_cnt,
|
||||
int node_id, u64 flags)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void bpf_arena_free_pages_non_sleepable(void *p__map, void *ptr__ign, u32 page_cnt)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
extern const struct bpf_map_ops bpf_map_offload_ops;
|
||||
|
||||
/* bpf_type_flag contains a set of flags that are applicable to the values of
|
||||
@@ -737,7 +754,7 @@ enum bpf_type_flag {
|
||||
MEM_ALLOC = BIT(11 + BPF_BASE_TYPE_BITS),
|
||||
|
||||
/* PTR was passed from the kernel in a trusted context, and may be
|
||||
* passed to KF_TRUSTED_ARGS kfuncs or BPF helper functions.
|
||||
* passed to kfuncs or BPF helper functions.
|
||||
* Confusingly, this is _not_ the opposite of PTR_UNTRUSTED above.
|
||||
* PTR_UNTRUSTED refers to a kptr that was read directly from a map
|
||||
* without invoking bpf_kptr_xchg(). What we really need to know is
|
||||
@@ -1213,6 +1230,9 @@ enum {
|
||||
#endif
|
||||
};
|
||||
|
||||
#define BPF_TRAMP_COOKIE_INDEX_SHIFT 8
|
||||
#define BPF_TRAMP_IS_RETURN_SHIFT 63
|
||||
|
||||
struct bpf_tramp_links {
|
||||
struct bpf_tramp_link *links[BPF_MAX_TRAMP_LINKS];
|
||||
int nr_links;
|
||||
@@ -1293,6 +1313,7 @@ enum bpf_tramp_prog_type {
|
||||
BPF_TRAMP_MODIFY_RETURN,
|
||||
BPF_TRAMP_MAX,
|
||||
BPF_TRAMP_REPLACE, /* more than MAX */
|
||||
BPF_TRAMP_FSESSION,
|
||||
};
|
||||
|
||||
struct bpf_tramp_image {
|
||||
@@ -1309,14 +1330,17 @@ struct bpf_tramp_image {
|
||||
};
|
||||
|
||||
struct bpf_trampoline {
|
||||
/* hlist for trampoline_table */
|
||||
struct hlist_node hlist;
|
||||
/* hlist for trampoline_key_table */
|
||||
struct hlist_node hlist_key;
|
||||
/* hlist for trampoline_ip_table */
|
||||
struct hlist_node hlist_ip;
|
||||
struct ftrace_ops *fops;
|
||||
/* serializes access to fields of this trampoline */
|
||||
struct mutex mutex;
|
||||
refcount_t refcnt;
|
||||
u32 flags;
|
||||
u64 key;
|
||||
unsigned long ip;
|
||||
struct {
|
||||
struct btf_func_model model;
|
||||
void *addr;
|
||||
@@ -1418,7 +1442,7 @@ bool __bpf_dynptr_is_rdonly(const struct bpf_dynptr_kern *ptr);
|
||||
int __bpf_dynptr_write(const struct bpf_dynptr_kern *dst, u64 offset,
|
||||
void *src, u64 len, u64 flags);
|
||||
void *bpf_dynptr_slice_rdwr(const struct bpf_dynptr *p, u64 offset,
|
||||
void *buffer__opt, u64 buffer__szk);
|
||||
void *buffer__nullable, u64 buffer__szk);
|
||||
|
||||
static inline int bpf_dynptr_check_off_len(const struct bpf_dynptr_kern *ptr, u64 offset, u64 len)
|
||||
{
|
||||
@@ -1742,8 +1766,12 @@ struct bpf_prog_aux {
|
||||
struct rcu_head rcu;
|
||||
};
|
||||
struct bpf_stream stream[2];
|
||||
struct mutex st_ops_assoc_mutex;
|
||||
struct bpf_map __rcu *st_ops_assoc;
|
||||
};
|
||||
|
||||
#define BPF_NR_CONTEXTS 4 /* normal, softirq, hardirq, NMI */
|
||||
|
||||
struct bpf_prog {
|
||||
u16 pages; /* Number of allocated pages */
|
||||
u16 jited:1, /* Is our filter JIT'ed? */
|
||||
@@ -1759,6 +1787,7 @@ struct bpf_prog {
|
||||
enforce_expected_attach_type:1, /* Enforce expected_attach_type checking at attach time */
|
||||
call_get_stack:1, /* Do we call bpf_get_stack() or bpf_get_stackid() */
|
||||
call_get_func_ip:1, /* Do we call get_func_ip() */
|
||||
call_session_cookie:1, /* Do we call bpf_session_cookie() */
|
||||
tstamp_type_access:1, /* Accessed __sk_buff->tstamp_type */
|
||||
sleepable:1; /* BPF program is sleepable */
|
||||
enum bpf_prog_type type; /* Type of BPF program */
|
||||
@@ -1770,7 +1799,7 @@ struct bpf_prog {
|
||||
u8 tag[BPF_TAG_SIZE];
|
||||
};
|
||||
struct bpf_prog_stats __percpu *stats;
|
||||
int __percpu *active;
|
||||
u8 __percpu *active; /* u8[BPF_NR_CONTEXTS] for recursion protection */
|
||||
unsigned int (*bpf_func)(const void *ctx,
|
||||
const struct bpf_insn *insn);
|
||||
struct bpf_prog_aux *aux; /* Auxiliary fields */
|
||||
@@ -1855,6 +1884,11 @@ struct bpf_tracing_link {
|
||||
struct bpf_prog *tgt_prog;
|
||||
};
|
||||
|
||||
struct bpf_fsession_link {
|
||||
struct bpf_tracing_link link;
|
||||
struct bpf_tramp_link fexit;
|
||||
};
|
||||
|
||||
struct bpf_raw_tp_link {
|
||||
struct bpf_link link;
|
||||
struct bpf_raw_event_map *btp;
|
||||
@@ -2002,6 +2036,40 @@ struct bpf_struct_ops_common_value {
|
||||
enum bpf_struct_ops_state state;
|
||||
};
|
||||
|
||||
static inline bool bpf_prog_get_recursion_context(struct bpf_prog *prog)
|
||||
{
|
||||
#ifdef CONFIG_ARM64
|
||||
u8 rctx = interrupt_context_level();
|
||||
u8 *active = this_cpu_ptr(prog->active);
|
||||
u32 val;
|
||||
|
||||
preempt_disable();
|
||||
active[rctx]++;
|
||||
val = le32_to_cpu(*(__le32 *)active);
|
||||
preempt_enable();
|
||||
if (val != BIT(rctx * 8))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
#else
|
||||
return this_cpu_inc_return(*(int __percpu *)(prog->active)) == 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void bpf_prog_put_recursion_context(struct bpf_prog *prog)
|
||||
{
|
||||
#ifdef CONFIG_ARM64
|
||||
u8 rctx = interrupt_context_level();
|
||||
u8 *active = this_cpu_ptr(prog->active);
|
||||
|
||||
preempt_disable();
|
||||
active[rctx]--;
|
||||
preempt_enable();
|
||||
#else
|
||||
this_cpu_dec(*(int __percpu *)(prog->active));
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BPF_JIT) && defined(CONFIG_BPF_SYSCALL)
|
||||
/* This macro helps developer to register a struct_ops type and generate
|
||||
* type information correctly. Developers should use this macro to register
|
||||
@@ -2044,6 +2112,9 @@ static inline void bpf_module_put(const void *data, struct module *owner)
|
||||
module_put(owner);
|
||||
}
|
||||
int bpf_struct_ops_link_create(union bpf_attr *attr);
|
||||
int bpf_prog_assoc_struct_ops(struct bpf_prog *prog, struct bpf_map *map);
|
||||
void bpf_prog_disassoc_struct_ops(struct bpf_prog *prog);
|
||||
void *bpf_prog_get_assoc_struct_ops(const struct bpf_prog_aux *aux);
|
||||
u32 bpf_struct_ops_id(const void *kdata);
|
||||
|
||||
#ifdef CONFIG_NET
|
||||
@@ -2091,6 +2162,17 @@ static inline int bpf_struct_ops_link_create(union bpf_attr *attr)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
static inline int bpf_prog_assoc_struct_ops(struct bpf_prog *prog, struct bpf_map *map)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
static inline void bpf_prog_disassoc_struct_ops(struct bpf_prog *prog)
|
||||
{
|
||||
}
|
||||
static inline void *bpf_prog_get_assoc_struct_ops(const struct bpf_prog_aux *aux)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static inline void bpf_map_struct_ops_info_fill(struct bpf_map_info *info, struct bpf_map *map)
|
||||
{
|
||||
}
|
||||
@@ -2101,6 +2183,37 @@ static inline void bpf_struct_ops_desc_release(struct bpf_struct_ops_desc *st_op
|
||||
|
||||
#endif
|
||||
|
||||
static inline int bpf_fsession_cnt(struct bpf_tramp_links *links)
|
||||
{
|
||||
struct bpf_tramp_links fentries = links[BPF_TRAMP_FENTRY];
|
||||
int cnt = 0;
|
||||
|
||||
for (int i = 0; i < links[BPF_TRAMP_FENTRY].nr_links; i++) {
|
||||
if (fentries.links[i]->link.prog->expected_attach_type == BPF_TRACE_FSESSION)
|
||||
cnt++;
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
static inline bool bpf_prog_calls_session_cookie(struct bpf_tramp_link *link)
|
||||
{
|
||||
return link->link.prog->call_session_cookie;
|
||||
}
|
||||
|
||||
static inline int bpf_fsession_cookie_cnt(struct bpf_tramp_links *links)
|
||||
{
|
||||
struct bpf_tramp_links fentries = links[BPF_TRAMP_FENTRY];
|
||||
int cnt = 0;
|
||||
|
||||
for (int i = 0; i < links[BPF_TRAMP_FENTRY].nr_links; i++) {
|
||||
if (bpf_prog_calls_session_cookie(fentries.links[i]))
|
||||
cnt++;
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
int bpf_prog_ctx_arg_info_init(struct bpf_prog *prog,
|
||||
const struct bpf_ctx_arg_aux *info, u32 cnt);
|
||||
|
||||
@@ -2540,6 +2653,10 @@ struct bpf_prog *bpf_prog_get_curr_or_next(u32 *id);
|
||||
int bpf_map_alloc_pages(const struct bpf_map *map, int nid,
|
||||
unsigned long nr_pages, struct page **page_array);
|
||||
#ifdef CONFIG_MEMCG
|
||||
void bpf_map_memcg_enter(const struct bpf_map *map, struct mem_cgroup **old_memcg,
|
||||
struct mem_cgroup **new_memcg);
|
||||
void bpf_map_memcg_exit(struct mem_cgroup *old_memcg,
|
||||
struct mem_cgroup *memcg);
|
||||
void *bpf_map_kmalloc_node(const struct bpf_map *map, size_t size, gfp_t flags,
|
||||
int node);
|
||||
void *bpf_map_kmalloc_nolock(const struct bpf_map *map, size_t size, gfp_t flags,
|
||||
@@ -2564,6 +2681,17 @@ void __percpu *bpf_map_alloc_percpu(const struct bpf_map *map, size_t size,
|
||||
kvcalloc(_n, _size, _flags)
|
||||
#define bpf_map_alloc_percpu(_map, _size, _align, _flags) \
|
||||
__alloc_percpu_gfp(_size, _align, _flags)
|
||||
static inline void bpf_map_memcg_enter(const struct bpf_map *map, struct mem_cgroup **old_memcg,
|
||||
struct mem_cgroup **new_memcg)
|
||||
{
|
||||
*new_memcg = NULL;
|
||||
*old_memcg = NULL;
|
||||
}
|
||||
|
||||
static inline void bpf_map_memcg_exit(struct mem_cgroup *old_memcg,
|
||||
struct mem_cgroup *memcg)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int
|
||||
@@ -2764,8 +2892,8 @@ int map_set_for_each_callback_args(struct bpf_verifier_env *env,
|
||||
struct bpf_func_state *caller,
|
||||
struct bpf_func_state *callee);
|
||||
|
||||
int bpf_percpu_hash_copy(struct bpf_map *map, void *key, void *value);
|
||||
int bpf_percpu_array_copy(struct bpf_map *map, void *key, void *value);
|
||||
int bpf_percpu_hash_copy(struct bpf_map *map, void *key, void *value, u64 flags);
|
||||
int bpf_percpu_array_copy(struct bpf_map *map, void *key, void *value, u64 flags);
|
||||
int bpf_percpu_hash_update(struct bpf_map *map, void *key, void *value,
|
||||
u64 flags);
|
||||
int bpf_percpu_array_update(struct bpf_map *map, void *key, void *value,
|
||||
@@ -3243,6 +3371,11 @@ static inline void bpf_prog_report_arena_violation(bool write, unsigned long add
|
||||
}
|
||||
#endif /* CONFIG_BPF_SYSCALL */
|
||||
|
||||
static inline bool bpf_net_capable(void)
|
||||
{
|
||||
return capable(CAP_NET_ADMIN) || capable(CAP_SYS_ADMIN);
|
||||
}
|
||||
|
||||
static __always_inline int
|
||||
bpf_probe_read_kernel_common(void *dst, u32 size, const void *unsafe_ptr)
|
||||
{
|
||||
@@ -3832,14 +3965,43 @@ bpf_prog_update_insn_ptrs(struct bpf_prog *prog, u32 *offsets, void *image)
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline bool bpf_map_supports_cpu_flags(enum bpf_map_type map_type)
|
||||
{
|
||||
switch (map_type) {
|
||||
case BPF_MAP_TYPE_PERCPU_ARRAY:
|
||||
case BPF_MAP_TYPE_PERCPU_HASH:
|
||||
case BPF_MAP_TYPE_LRU_PERCPU_HASH:
|
||||
case BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int bpf_map_check_op_flags(struct bpf_map *map, u64 flags, u64 allowed_flags)
|
||||
{
|
||||
if (flags & ~allowed_flags)
|
||||
u32 cpu;
|
||||
|
||||
if ((u32)flags & ~allowed_flags)
|
||||
return -EINVAL;
|
||||
|
||||
if ((flags & BPF_F_LOCK) && !btf_record_has_field(map->record, BPF_SPIN_LOCK))
|
||||
return -EINVAL;
|
||||
|
||||
if (!(flags & BPF_F_CPU) && flags >> 32)
|
||||
return -EINVAL;
|
||||
|
||||
if (flags & (BPF_F_CPU | BPF_F_ALL_CPUS)) {
|
||||
if (!bpf_map_supports_cpu_flags(map->map_type))
|
||||
return -EINVAL;
|
||||
if ((flags & BPF_F_CPU) && (flags & BPF_F_ALL_CPUS))
|
||||
return -EINVAL;
|
||||
|
||||
cpu = flags >> 32;
|
||||
if ((flags & BPF_F_CPU) && cpu >= num_possible_cpus())
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,12 +15,13 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/bpf_mem_alloc.h>
|
||||
#include <uapi/linux/btf.h>
|
||||
#include <asm/rqspinlock.h>
|
||||
|
||||
#define BPF_LOCAL_STORAGE_CACHE_SIZE 16
|
||||
|
||||
struct bpf_local_storage_map_bucket {
|
||||
struct hlist_head list;
|
||||
raw_spinlock_t lock;
|
||||
rqspinlock_t lock;
|
||||
};
|
||||
|
||||
/* Thp map is not the primary owner of a bpf_local_storage_elem.
|
||||
@@ -67,6 +68,11 @@ struct bpf_local_storage_data {
|
||||
u8 data[] __aligned(8);
|
||||
};
|
||||
|
||||
#define SELEM_MAP_UNLINKED (1 << 0)
|
||||
#define SELEM_STORAGE_UNLINKED (1 << 1)
|
||||
#define SELEM_UNLINKED (SELEM_MAP_UNLINKED | SELEM_STORAGE_UNLINKED)
|
||||
#define SELEM_TOFREE (1 << 2)
|
||||
|
||||
/* Linked to bpf_local_storage and bpf_local_storage_map */
|
||||
struct bpf_local_storage_elem {
|
||||
struct hlist_node map_node; /* Linked to bpf_local_storage_map */
|
||||
@@ -79,7 +85,9 @@ struct bpf_local_storage_elem {
|
||||
* after raw_spin_unlock
|
||||
*/
|
||||
};
|
||||
/* 8 bytes hole */
|
||||
atomic_t state;
|
||||
bool use_kmalloc_nolock;
|
||||
/* 3 bytes hole */
|
||||
/* The data is stored in another cacheline to minimize
|
||||
* the number of cachelines access during a cache hit.
|
||||
*/
|
||||
@@ -88,13 +96,14 @@ struct bpf_local_storage_elem {
|
||||
|
||||
struct bpf_local_storage {
|
||||
struct bpf_local_storage_data __rcu *cache[BPF_LOCAL_STORAGE_CACHE_SIZE];
|
||||
struct bpf_local_storage_map __rcu *smap;
|
||||
struct hlist_head list; /* List of bpf_local_storage_elem */
|
||||
void *owner; /* The object that owns the above "list" of
|
||||
* bpf_local_storage_elem.
|
||||
*/
|
||||
struct rcu_head rcu;
|
||||
raw_spinlock_t lock; /* Protect adding/removing from the "list" */
|
||||
rqspinlock_t lock; /* Protect adding/removing from the "list" */
|
||||
u64 mem_charge; /* Copy of mem charged to owner. Protected by "lock" */
|
||||
refcount_t owner_refcnt;/* Used to pin owner when map_free is uncharging */
|
||||
bool use_kmalloc_nolock;
|
||||
};
|
||||
|
||||
@@ -162,11 +171,10 @@ bpf_local_storage_lookup(struct bpf_local_storage *local_storage,
|
||||
return SDATA(selem);
|
||||
}
|
||||
|
||||
void bpf_local_storage_destroy(struct bpf_local_storage *local_storage);
|
||||
u32 bpf_local_storage_destroy(struct bpf_local_storage *local_storage);
|
||||
|
||||
void bpf_local_storage_map_free(struct bpf_map *map,
|
||||
struct bpf_local_storage_cache *cache,
|
||||
int __percpu *busy_counter);
|
||||
struct bpf_local_storage_cache *cache);
|
||||
|
||||
int bpf_local_storage_map_check_btf(const struct bpf_map *map,
|
||||
const struct btf *btf,
|
||||
@@ -176,10 +184,11 @@ int bpf_local_storage_map_check_btf(const struct bpf_map *map,
|
||||
void bpf_selem_link_storage_nolock(struct bpf_local_storage *local_storage,
|
||||
struct bpf_local_storage_elem *selem);
|
||||
|
||||
void bpf_selem_unlink(struct bpf_local_storage_elem *selem, bool reuse_now);
|
||||
int bpf_selem_unlink(struct bpf_local_storage_elem *selem);
|
||||
|
||||
void bpf_selem_link_map(struct bpf_local_storage_map *smap,
|
||||
struct bpf_local_storage_elem *selem);
|
||||
int bpf_selem_link_map(struct bpf_local_storage_map *smap,
|
||||
struct bpf_local_storage *local_storage,
|
||||
struct bpf_local_storage_elem *selem);
|
||||
|
||||
struct bpf_local_storage_elem *
|
||||
bpf_selem_alloc(struct bpf_local_storage_map *smap, void *owner, void *value,
|
||||
|
||||
@@ -340,4 +340,14 @@ static inline bool bpf_mprog_supported(enum bpf_prog_type type)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool bpf_mprog_detach_empty(enum bpf_prog_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case BPF_PROG_TYPE_SCHED_CLS:
|
||||
return bpf_net_capable();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif /* __BPF_MPROG_H */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user