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

 - Fix BPF builds due to -fms-extensions. selftests (Alexei
   Starovoitov), bpftool (Quentin Monnet).

 - Fix build of net/smc when CONFIG_BPF_SYSCALL=y, but CONFIG_BPF_JIT=n
   (Geert Uytterhoeven)

 - Fix livepatch/BPF interaction and support reliable unwinding through
   BPF stack frames (Josh Poimboeuf)

 - Do not audit capability check in arm64 JIT (Ondrej Mosnacek)

 - Fix truncated dmabuf BPF iterator reads (T.J. Mercier)

 - Fix verifier assumptions of bpf_d_path's output buffer (Shuran Liu)

 - Fix warnings in libbpf when built with -Wdiscarded-qualifiers under
   C23 (Mikhail Gavrilov)

* tag 'bpf-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf:
  selftests/bpf: add regression test for bpf_d_path()
  bpf: Fix verifier assumptions of bpf_d_path's output buffer
  selftests/bpf: Add test for truncated dmabuf_iter reads
  bpf: Fix truncated dmabuf iterator reads
  x86/unwind/orc: Support reliable unwinding through BPF stack frames
  bpf: Add bpf_has_frame_pointer()
  bpf, arm64: Do not audit capability check in do_jit()
  libbpf: Fix -Wdiscarded-qualifiers under C23
  bpftool: Fix build warnings due to MS extensions
  net: smc: SMC_HS_CTRL_BPF should depend on BPF_JIT
  selftests/bpf: Add -fms-extensions to bpf build flags
parents 64e68f8a 1d528e79
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1004,7 +1004,7 @@ static void __maybe_unused build_bhb_mitigation(struct jit_ctx *ctx)
	    arm64_get_spectre_v2_state() == SPECTRE_VULNERABLE)
		return;

	if (capable(CAP_SYS_ADMIN))
	if (ns_capable_noaudit(&init_user_ns, CAP_SYS_ADMIN))
		return;

	if (supports_clearbhb(SCOPE_SYSTEM)) {
+27 −12
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@
#include <linux/objtool.h>
#include <linux/module.h>
#include <linux/sort.h>
#include <linux/bpf.h>
#include <asm/ptrace.h>
#include <asm/stacktrace.h>
#include <asm/unwind.h>
@@ -172,6 +173,25 @@ static struct orc_entry *orc_ftrace_find(unsigned long ip)
}
#endif

/* Fake frame pointer entry -- used as a fallback for generated code */
static struct orc_entry orc_fp_entry = {
	.type		= ORC_TYPE_CALL,
	.sp_reg		= ORC_REG_BP,
	.sp_offset	= 16,
	.bp_reg		= ORC_REG_PREV_SP,
	.bp_offset	= -16,
};

static struct orc_entry *orc_bpf_find(unsigned long ip)
{
#ifdef CONFIG_BPF_JIT
	if (bpf_has_frame_pointer(ip))
		return &orc_fp_entry;
#endif

	return NULL;
}

/*
 * If we crash with IP==0, the last successfully executed instruction
 * was probably an indirect function call with a NULL function pointer,
@@ -186,15 +206,6 @@ static struct orc_entry null_orc_entry = {
	.type = ORC_TYPE_CALL
};

/* Fake frame pointer entry -- used as a fallback for generated code */
static struct orc_entry orc_fp_entry = {
	.type		= ORC_TYPE_CALL,
	.sp_reg		= ORC_REG_BP,
	.sp_offset	= 16,
	.bp_reg		= ORC_REG_PREV_SP,
	.bp_offset	= -16,
};

static struct orc_entry *orc_find(unsigned long ip)
{
	static struct orc_entry *orc;
@@ -238,6 +249,11 @@ static struct orc_entry *orc_find(unsigned long ip)
	if (orc)
		return orc;

	/* BPF lookup: */
	orc = orc_bpf_find(ip);
	if (orc)
		return orc;

	return orc_ftrace_find(ip);
}

@@ -495,9 +511,8 @@ bool unwind_next_frame(struct unwind_state *state)
	if (!orc) {
		/*
		 * As a fallback, try to assume this code uses a frame pointer.
		 * This is useful for generated code, like BPF, which ORC
		 * doesn't know about.  This is just a guess, so the rest of
		 * the unwind is no longer considered reliable.
		 * This is just a guess, so the rest of the unwind is no longer
		 * considered reliable.
		 */
		orc = &orc_fp_entry;
		state->error = true;
+12 −0
Original line number Diff line number Diff line
@@ -1678,6 +1678,9 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, u8 *rw_image
	emit_prologue(&prog, image, stack_depth,
		      bpf_prog_was_classic(bpf_prog), tail_call_reachable,
		      bpf_is_subprog(bpf_prog), bpf_prog->aux->exception_cb);

	bpf_prog->aux->ksym.fp_start = prog - temp;

	/* Exception callback will clobber callee regs for its own use, and
	 * restore the original callee regs from main prog's stack frame.
	 */
@@ -2736,6 +2739,8 @@ st: if (is_imm8(insn->off))
					pop_r12(&prog);
			}
			EMIT1(0xC9);         /* leave */
			bpf_prog->aux->ksym.fp_end = prog - temp;

			emit_return(&prog, image + addrs[i - 1] + (prog - temp));
			break;

@@ -3325,6 +3330,9 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
	}
	EMIT1(0x55);		 /* push rbp */
	EMIT3(0x48, 0x89, 0xE5); /* mov rbp, rsp */
	if (im)
		im->ksym.fp_start = prog - (u8 *)rw_image;

	if (!is_imm8(stack_size)) {
		/* sub rsp, stack_size */
		EMIT3_off32(0x48, 0x81, 0xEC, stack_size);
@@ -3462,7 +3470,11 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
		emit_ldx(&prog, BPF_DW, BPF_REG_0, BPF_REG_FP, -8);

	emit_ldx(&prog, BPF_DW, BPF_REG_6, BPF_REG_FP, -rbx_off);

	EMIT1(0xC9); /* leave */
	if (im)
		im->ksym.fp_end = prog - (u8 *)rw_image;

	if (flags & BPF_TRAMP_F_SKIP_FRAME) {
		/* skip our return address and return to parent */
		EMIT4(0x48, 0x83, 0xC4, 8); /* add rsp, 8 */
+3 −0
Original line number Diff line number Diff line
@@ -1283,6 +1283,8 @@ struct bpf_ksym {
	struct list_head	 lnode;
	struct latch_tree_node	 tnode;
	bool			 prog;
	u32			 fp_start;
	u32			 fp_end;
};

enum bpf_tramp_prog_type {
@@ -1511,6 +1513,7 @@ void bpf_image_ksym_add(struct bpf_ksym *ksym);
void bpf_image_ksym_del(struct bpf_ksym *ksym);
void bpf_ksym_add(struct bpf_ksym *ksym);
void bpf_ksym_del(struct bpf_ksym *ksym);
bool bpf_has_frame_pointer(unsigned long ip);
int bpf_jit_charge_modmem(u32 size);
void bpf_jit_uncharge_modmem(u32 size);
bool bpf_prog_has_trampoline(const struct bpf_prog *prog);
+16 −0
Original line number Diff line number Diff line
@@ -760,6 +760,22 @@ struct bpf_prog *bpf_prog_ksym_find(unsigned long addr)
	       NULL;
}

bool bpf_has_frame_pointer(unsigned long ip)
{
	struct bpf_ksym *ksym;
	unsigned long offset;

	guard(rcu)();

	ksym = bpf_ksym_find(ip);
	if (!ksym || !ksym->fp_start || !ksym->fp_end)
		return false;

	offset = ip - ksym->start;

	return offset >= ksym->fp_start && offset < ksym->fp_end;
}

const struct exception_table_entry *search_bpf_extables(unsigned long addr)
{
	const struct exception_table_entry *e = NULL;
Loading