Commit 8b7f4cd3 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull bpf fixes from Alexei Starovoitov:

 - Fix u32/s32 bounds when ranges cross min/max boundary (Eduard
   Zingerman)

 - Fix precision backtracking with linked registers (Eduard Zingerman)

 - Fix linker flags detection for resolve_btfids (Ihor Solodrai)

 - Fix race in update_ftrace_direct_add/del (Jiri Olsa)

 - Fix UAF in bpf_trampoline_link_cgroup_shim (Lang Xu)

* tag 'bpf-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf:
  resolve_btfids: Fix linker flags detection
  selftests/bpf: add reproducer for spurious precision propagation through calls
  bpf: collect only live registers in linked regs
  Revert "selftests/bpf: Update reg_bound range refinement logic"
  selftests/bpf: test refining u32/s32 bounds when ranges cross min/max boundary
  bpf: Fix u32/s32 bounds when ranges cross min/max boundary
  bpf: Fix a UAF issue in bpf_trampoline_link_cgroup_shim
  ftrace: Add missing ftrace_lock to update_ftrace_direct_add/del
parents 03dcad79 b0dcdcb9
Loading
Loading
Loading
Loading
+1 −3
Original line number Diff line number Diff line
@@ -1002,10 +1002,8 @@ int bpf_trampoline_link_cgroup_shim(struct bpf_prog *prog,
	mutex_lock(&tr->mutex);

	shim_link = cgroup_shim_find(tr, bpf_func);
	if (shim_link) {
	if (shim_link && !IS_ERR(bpf_link_inc_not_zero(&shim_link->link.link))) {
		/* Reusing existing shim attached by the other program. */
		bpf_link_inc(&shim_link->link.link);

		mutex_unlock(&tr->mutex);
		bpf_trampoline_put(tr); /* bpf_trampoline_get above */
		return 0;
+34 −3
Original line number Diff line number Diff line
@@ -2511,6 +2511,30 @@ static void __reg32_deduce_bounds(struct bpf_reg_state *reg)
	if ((u32)reg->s32_min_value <= (u32)reg->s32_max_value) {
		reg->u32_min_value = max_t(u32, reg->s32_min_value, reg->u32_min_value);
		reg->u32_max_value = min_t(u32, reg->s32_max_value, reg->u32_max_value);
	} else {
		if (reg->u32_max_value < (u32)reg->s32_min_value) {
			/* See __reg64_deduce_bounds() for detailed explanation.
			 * Refine ranges in the following situation:
			 *
			 * 0                                                   U32_MAX
			 * |  [xxxxxxxxxxxxxx u32 range xxxxxxxxxxxxxx]              |
			 * |----------------------------|----------------------------|
			 * |xxxxx s32 range xxxxxxxxx]                       [xxxxxxx|
			 * 0                     S32_MAX S32_MIN                    -1
			 */
			reg->s32_min_value = (s32)reg->u32_min_value;
			reg->u32_max_value = min_t(u32, reg->u32_max_value, reg->s32_max_value);
		} else if ((u32)reg->s32_max_value < reg->u32_min_value) {
			/*
			 * 0                                                   U32_MAX
			 * |              [xxxxxxxxxxxxxx u32 range xxxxxxxxxxxxxx]  |
			 * |----------------------------|----------------------------|
			 * |xxxxxxxxx]                       [xxxxxxxxxxxx s32 range |
			 * 0                     S32_MAX S32_MIN                    -1
			 */
			reg->s32_max_value = (s32)reg->u32_max_value;
			reg->u32_min_value = max_t(u32, reg->u32_min_value, reg->s32_min_value);
		}
	}
}
@@ -17335,17 +17359,24 @@ static void __collect_linked_regs(struct linked_regs *reg_set, struct bpf_reg_st
 * in verifier state, save R in linked_regs if R->id == id.
 * If there are too many Rs sharing same id, reset id for leftover Rs.
 */
static void collect_linked_regs(struct bpf_verifier_state *vstate, u32 id,
static void collect_linked_regs(struct bpf_verifier_env *env,
				struct bpf_verifier_state *vstate,
				u32 id,
				struct linked_regs *linked_regs)
{
	struct bpf_insn_aux_data *aux = env->insn_aux_data;
	struct bpf_func_state *func;
	struct bpf_reg_state *reg;
	u16 live_regs;
	int i, j;
	id = id & ~BPF_ADD_CONST;
	for (i = vstate->curframe; i >= 0; i--) {
		live_regs = aux[frame_insn_idx(vstate, i)].live_regs_before;
		func = vstate->frame[i];
		for (j = 0; j < BPF_REG_FP; j++) {
			if (!(live_regs & BIT(j)))
				continue;
			reg = &func->regs[j];
			__collect_linked_regs(linked_regs, reg, id, i, j, true);
		}
@@ -17560,9 +17591,9 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
	 * if parent state is created.
	 */
	if (BPF_SRC(insn->code) == BPF_X && src_reg->type == SCALAR_VALUE && src_reg->id)
		collect_linked_regs(this_branch, src_reg->id, &linked_regs);
		collect_linked_regs(env, this_branch, src_reg->id, &linked_regs);
	if (dst_reg->type == SCALAR_VALUE && dst_reg->id)
		collect_linked_regs(this_branch, dst_reg->id, &linked_regs);
		collect_linked_regs(env, this_branch, dst_reg->id, &linked_regs);
	if (linked_regs.cnt > 1) {
		err = push_jmp_history(env, this_branch, 0, linked_regs_pack(&linked_regs));
		if (err)
+2 −0
Original line number Diff line number Diff line
@@ -6404,6 +6404,7 @@ int update_ftrace_direct_add(struct ftrace_ops *ops, struct ftrace_hash *hash)
			new_filter_hash = old_filter_hash;
		}
	} else {
		guard(mutex)(&ftrace_lock);
		err = ftrace_update_ops(ops, new_filter_hash, EMPTY_HASH);
		/*
		 * new_filter_hash is dup-ed, so we need to release it anyway,
@@ -6530,6 +6531,7 @@ int update_ftrace_direct_del(struct ftrace_ops *ops, struct ftrace_hash *hash)
			ops->func_hash->filter_hash = NULL;
		}
	} else {
		guard(mutex)(&ftrace_lock);
		err = ftrace_update_ops(ops, new_filter_hash, EMPTY_HASH);
		/*
		 * new_filter_hash is dup-ed, so we need to release it anyway,
+7 −2
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ RM ?= rm
HOSTCC  ?= gcc
HOSTLD  ?= ld
HOSTAR  ?= ar
HOSTPKG_CONFIG ?= pkg-config
CROSS_COMPILE =

OUTPUT ?= $(srctree)/tools/bpf/resolve_btfids/
@@ -63,10 +64,14 @@ $(BPFOBJ): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(LIBBPF_OU
		    $(abspath $@) install_headers

LIBELF_FLAGS := $(shell $(HOSTPKG_CONFIG) libelf --cflags 2>/dev/null)

ifneq ($(filter -static,$(EXTRA_LDFLAGS)),)
LIBELF_LIBS  := $(shell $(HOSTPKG_CONFIG) libelf --libs --static 2>/dev/null || echo -lelf -lzstd)
else
LIBELF_LIBS  := $(shell $(HOSTPKG_CONFIG) libelf --libs 2>/dev/null || echo -lelf)
endif

ZLIB_LIBS  := $(shell $(HOSTPKG_CONFIG) zlib --libs 2>/dev/null || echo -lz)
ZSTD_LIBS  := $(shell $(HOSTPKG_CONFIG) libzstd --libs 2>/dev/null || echo -lzstd)

HOSTCFLAGS_resolve_btfids += -g \
          -I$(srctree)/tools/include \
@@ -76,7 +81,7 @@ HOSTCFLAGS_resolve_btfids += -g \
          $(LIBELF_FLAGS) \
          -Wall -Werror

LIBS = $(LIBELF_LIBS) $(ZLIB_LIBS) $(ZSTD_LIBS)
LIBS = $(LIBELF_LIBS) $(ZLIB_LIBS)

export srctree OUTPUT HOSTCFLAGS_resolve_btfids Q HOSTCC HOSTLD HOSTAR
include $(srctree)/tools/build/Makefile.include
+1 −0
Original line number Diff line number Diff line
@@ -409,6 +409,7 @@ $(RESOLVE_BTFIDS): $(HOST_BPFOBJ) | $(HOST_BUILD_DIR)/resolve_btfids \
		CC="$(HOSTCC)" LD="$(HOSTLD)" AR="$(HOSTAR)" \
		LIBBPF_INCLUDE=$(HOST_INCLUDE_DIR) \
		EXTRA_LDFLAGS='$(SAN_LDFLAGS) $(EXTRA_LDFLAGS)' \
		HOSTPKG_CONFIG=$(PKG_CONFIG) \
		OUTPUT=$(HOST_BUILD_DIR)/resolve_btfids/ BPFOBJ=$(HOST_BPFOBJ)

# Get Clang's default includes on this system, as opposed to those seen by
Loading