Commit d0d106a2 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull bpf updates from Alexei Starovoitov:
 "A smaller than usual release cycle.

  The main changes are:

   - Prepare selftest to run with GCC-BPF backend (Ihor Solodrai)

     In addition to LLVM-BPF runs the BPF CI now runs GCC-BPF in compile
     only mode. Half of the tests are failing, since support for
     btf_decl_tag is still WIP, but this is a great milestone.

   - Convert various samples/bpf to selftests/bpf/test_progs format
     (Alexis Lothoré and Bastien Curutchet)

   - Teach verifier to recognize that array lookup with constant
     in-range index will always succeed (Daniel Xu)

   - Cleanup migrate disable scope in BPF maps (Hou Tao)

   - Fix bpf_timer destroy path in PREEMPT_RT (Hou Tao)

   - Always use bpf_mem_alloc in bpf_local_storage in PREEMPT_RT (Martin
     KaFai Lau)

   - Refactor verifier lock support (Kumar Kartikeya Dwivedi)

     This is a prerequisite for upcoming resilient spin lock.

   - Remove excessive 'may_goto +0' instructions in the verifier that
     LLVM leaves when unrolls the loops (Yonghong Song)

   - Remove unhelpful bpf_probe_write_user() warning message (Marco
     Elver)

   - Add fd_array_cnt attribute for prog_load command (Anton Protopopov)

     This is a prerequisite for upcoming support for static_branch"

* tag 'bpf-next-6.14' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next: (125 commits)
  selftests/bpf: Add some tests related to 'may_goto 0' insns
  bpf: Remove 'may_goto 0' instruction in opt_remove_nops()
  bpf: Allow 'may_goto 0' instruction in verifier
  selftests/bpf: Add test case for the freeing of bpf_timer
  bpf: Cancel the running bpf_timer through kworker for PREEMPT_RT
  bpf: Free element after unlock in __htab_map_lookup_and_delete_elem()
  bpf: Bail out early in __htab_map_lookup_and_delete_elem()
  bpf: Free special fields after unlock in htab_lru_map_delete_node()
  tools: Sync if_xdp.h uapi tooling header
  libbpf: Work around kernel inconsistently stripping '.llvm.' suffix
  bpf: selftests: verifier: Add nullness elision tests
  bpf: verifier: Support eliding map lookup nullness
  bpf: verifier: Refactor helper access type tracking
  bpf: tcp: Mark bpf_load_hdr_opt() arg2 as read-write
  bpf: verifier: Add missing newline on verbose() call
  selftests/bpf: Add distilled BTF test about marking BTF_IS_EMBEDDED
  libbpf: Fix incorrect traversal end type ID when marking BTF_IS_EMBEDDED
  libbpf: Fix return zero when elf_begin failed
  selftests/bpf: Fix btf leak on new btf alloc failure in btf_distill test
  veristat: Load struct_ops programs only once
  ...
parents 754916d4 3f3c2f0c
Loading
Loading
Loading
Loading
+24 −24
Original line number Diff line number Diff line
@@ -267,6 +267,19 @@ static bool is_addsub_imm(u32 imm)
	return !(imm & ~0xfff) || !(imm & ~0xfff000);
}

static inline void emit_a64_add_i(const bool is64, const int dst, const int src,
				  const int tmp, const s32 imm, struct jit_ctx *ctx)
{
	if (is_addsub_imm(imm)) {
		emit(A64_ADD_I(is64, dst, src, imm), ctx);
	} else if (is_addsub_imm(-imm)) {
		emit(A64_SUB_I(is64, dst, src, -imm), ctx);
	} else {
		emit_a64_mov_i(is64, tmp, imm, ctx);
		emit(A64_ADD(is64, dst, src, tmp), ctx);
	}
}

/*
 * There are 3 types of AArch64 LDR/STR (immediate) instruction:
 * Post-index, Pre-index, Unsigned offset.
@@ -648,17 +661,14 @@ static int emit_lse_atomic(const struct bpf_insn *insn, struct jit_ctx *ctx)
	const s16 off = insn->off;
	u8 reg = dst;

	if (off || arena) {
	if (off) {
			emit_a64_mov_i(1, tmp, off, ctx);
			emit(A64_ADD(1, tmp, tmp, dst), ctx);
		emit_a64_add_i(1, tmp, reg, tmp, off, ctx);
		reg = tmp;
	}
	if (arena) {
		emit(A64_ADD(1, tmp, reg, arena_vm_base), ctx);
		reg = tmp;
	}
	}

	switch (insn->imm) {
	/* lock *(u32/u64 *)(dst_reg + off) <op>= src_reg */
@@ -723,7 +733,7 @@ static int emit_ll_sc_atomic(const struct bpf_insn *insn, struct jit_ctx *ctx)
	const s32 imm = insn->imm;
	const s16 off = insn->off;
	const bool isdw = BPF_SIZE(code) == BPF_DW;
	u8 reg;
	u8 reg = dst;
	s32 jmp_offset;

	if (BPF_MODE(code) == BPF_PROBE_ATOMIC) {
@@ -732,11 +742,8 @@ static int emit_ll_sc_atomic(const struct bpf_insn *insn, struct jit_ctx *ctx)
		return -EINVAL;
	}

	if (!off) {
		reg = dst;
	} else {
		emit_a64_mov_i(1, tmp, off, ctx);
		emit(A64_ADD(1, tmp, tmp, dst), ctx);
	if (off) {
		emit_a64_add_i(1, tmp, reg, tmp, off, ctx);
		reg = tmp;
	}

@@ -1146,14 +1153,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
	/* dst = dst OP imm */
	case BPF_ALU | BPF_ADD | BPF_K:
	case BPF_ALU64 | BPF_ADD | BPF_K:
		if (is_addsub_imm(imm)) {
			emit(A64_ADD_I(is64, dst, dst, imm), ctx);
		} else if (is_addsub_imm(-imm)) {
			emit(A64_SUB_I(is64, dst, dst, -imm), ctx);
		} else {
			emit_a64_mov_i(is64, tmp, imm, ctx);
			emit(A64_ADD(is64, dst, dst, tmp), ctx);
		}
		emit_a64_add_i(is64, dst, dst, tmp, imm, ctx);
		break;
	case BPF_ALU | BPF_SUB | BPF_K:
	case BPF_ALU64 | BPF_SUB | BPF_K:
+17 −0
Original line number Diff line number Diff line
@@ -2299,6 +2299,14 @@ void __bpf_obj_drop_impl(void *p, const struct btf_record *rec, bool percpu);
struct bpf_map *bpf_map_get(u32 ufd);
struct bpf_map *bpf_map_get_with_uref(u32 ufd);

/*
 * The __bpf_map_get() and __btf_get_by_fd() functions parse a file
 * descriptor and return a corresponding map or btf object.
 * Their names are double underscored to emphasize the fact that they
 * do not increase refcnt. To also increase refcnt use corresponding
 * bpf_map_get() and btf_get_by_fd() functions.
 */

static inline struct bpf_map *__bpf_map_get(struct fd f)
{
	if (fd_empty(f))
@@ -2308,6 +2316,15 @@ static inline struct bpf_map *__bpf_map_get(struct fd f)
	return fd_file(f)->private_data;
}

static inline struct btf *__btf_get_by_fd(struct fd f)
{
	if (fd_empty(f))
		return ERR_PTR(-EBADF);
	if (unlikely(fd_file(f)->f_op != &btf_fops))
		return ERR_PTR(-EINVAL);
	return fd_file(f)->private_data;
}

void bpf_map_inc(struct bpf_map *map);
void bpf_map_inc_with_uref(struct bpf_map *map);
struct bpf_map *__bpf_map_inc_not_zero(struct bpf_map *map, bool uref);
+16 −10
Original line number Diff line number Diff line
@@ -233,6 +233,7 @@ enum bpf_stack_slot_type {
	 */
	STACK_DYNPTR,
	STACK_ITER,
	STACK_IRQ_FLAG,
};

#define BPF_REG_SIZE 8	/* size of eBPF register in bytes */
@@ -254,8 +255,9 @@ struct bpf_reference_state {
	 * default to pointer reference on zero initialization of a state.
	 */
	enum ref_state_type {
		REF_TYPE_PTR = 0,
		REF_TYPE_LOCK,
		REF_TYPE_PTR	= 1,
		REF_TYPE_IRQ	= 2,
		REF_TYPE_LOCK	= 3,
	} type;
	/* Track each reference created with a unique id, even if the same
	 * instruction creates the reference multiple times (eg, via CALL).
@@ -315,9 +317,6 @@ struct bpf_func_state {
	u32 callback_depth;

	/* The following fields should be last. See copy_func_state() */
	int acquired_refs;
	int active_locks;
	struct bpf_reference_state *refs;
	/* The state of the stack. Each element of the array describes BPF_REG_SIZE
	 * (i.e. 8) bytes worth of stack memory.
	 * stack[0] represents bytes [*(r10-8)..*(r10-1)]
@@ -370,6 +369,8 @@ struct bpf_verifier_state {
	/* call stack tracking */
	struct bpf_func_state *frame[MAX_CALL_FRAMES];
	struct bpf_verifier_state *parent;
	/* Acquired reference states */
	struct bpf_reference_state *refs;
	/*
	 * 'branches' field is the number of branches left to explore:
	 * 0 - all possible paths from this state reached bpf_exit or
@@ -419,9 +420,13 @@ struct bpf_verifier_state {
	u32 insn_idx;
	u32 curframe;

	bool speculative;
	u32 acquired_refs;
	u32 active_locks;
	u32 active_preempt_locks;
	u32 active_irq_id;
	bool active_rcu_lock;
	u32 active_preempt_lock;

	bool speculative;
	/* If this state was ever pointed-to by other state's loop_entry field
	 * this flag would be set to true. Used to avoid freeing such states
	 * while they are still in use.
@@ -980,8 +985,9 @@ const char *dynptr_type_str(enum bpf_dynptr_type type);
const char *iter_type_str(const struct btf *btf, u32 btf_id);
const char *iter_state_str(enum bpf_iter_state state);

void print_verifier_state(struct bpf_verifier_env *env,
			  const struct bpf_func_state *state, bool print_all);
void print_insn_state(struct bpf_verifier_env *env, const struct bpf_func_state *state);
void print_verifier_state(struct bpf_verifier_env *env, const struct bpf_verifier_state *vstate,
			  u32 frameno, bool print_all);
void print_insn_state(struct bpf_verifier_env *env, const struct bpf_verifier_state *vstate,
		      u32 frameno);

#endif /* _LINUX_BPF_VERIFIER_H */
+5 −0
Original line number Diff line number Diff line
@@ -353,6 +353,11 @@ static inline bool btf_type_is_scalar(const struct btf_type *t)
	return btf_type_is_int(t) || btf_type_is_enum(t);
}

static inline bool btf_type_is_fwd(const struct btf_type *t)
{
	return BTF_INFO_KIND(t->info) == BTF_KIND_FWD;
}

static inline bool btf_type_is_typedef(const struct btf_type *t)
{
	return BTF_INFO_KIND(t->info) == BTF_KIND_TYPEDEF;
+10 −0
Original line number Diff line number Diff line
@@ -1573,6 +1573,16 @@ union bpf_attr {
		 * If provided, prog_flags should have BPF_F_TOKEN_FD flag set.
		 */
		__s32		prog_token_fd;
		/* The fd_array_cnt can be used to pass the length of the
		 * fd_array array. In this case all the [map] file descriptors
		 * passed in this array will be bound to the program, even if
		 * the maps are not referenced directly. The functionality is
		 * similar to the BPF_PROG_BIND_MAP syscall, but maps can be
		 * used by the verifier during the program load. If provided,
		 * then the fd_array[0,...,fd_array_cnt-1] is expected to be
		 * continuous.
		 */
		__u32		fd_array_cnt;
	};

	struct { /* anonymous struct used by BPF_OBJ_* commands */
Loading