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

 - Fix kCFI failures in JITed BPF code on arm64 (Sami Tolvanen, Puranjay
   Mohan, Mark Rutland, Maxwell Bland)

 - Disallow tail calls between BPF programs that use different cgroup
   local storage maps to prevent out-of-bounds access (Daniel Borkmann)

 - Fix unaligned access in flow_dissector and netfilter BPF programs
   (Paul Chaignon)

 - Avoid possible use of uninitialized mod_len in libbpf (Achill
   Gilgenast)

* tag 'bpf-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf:
  selftests/bpf: Test for unaligned flow_dissector ctx access
  bpf: Improve ctx access verifier error message
  bpf: Check netfilter ctx accesses are aligned
  bpf: Check flow_dissector ctx accesses are aligned
  arm64/cfi,bpf: Support kCFI + BPF on arm64
  cfi: Move BPF CFI types and helpers to generic code
  cfi: add C CFI type macro
  libbpf: Avoid possible use of uninitialized mod_len
  bpf: Fix oob access in cgroup local storage
  bpf: Move cgroup iterator helpers to bpf.h
  bpf: Move bpf map owner out of common struct
  bpf: Add cookie object to bpf maps
parents f4f346c3 d8d2d9d1
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_ARM64_CFI_H
#define _ASM_ARM64_CFI_H

#define __bpfcall

#endif /* _ASM_ARM64_CFI_H */
+27 −3
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@
#include <linux/arm-smccc.h>
#include <linux/bitfield.h>
#include <linux/bpf.h>
#include <linux/cfi.h>
#include <linux/filter.h>
#include <linux/memory.h>
#include <linux/printk.h>
@@ -114,6 +115,14 @@ static inline void emit(const u32 insn, struct jit_ctx *ctx)
	ctx->idx++;
}

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->idx++;
}

static inline void emit_a64_mov_i(const int is64, const int reg,
				  const s32 val, struct jit_ctx *ctx)
{
@@ -174,6 +183,12 @@ static inline void emit_bti(u32 insn, struct jit_ctx *ctx)
		emit(insn, ctx);
}

static inline void emit_kcfi(u32 hash, struct jit_ctx *ctx)
{
	if (IS_ENABLED(CONFIG_CFI_CLANG))
		emit_u32_data(hash, ctx);
}

/*
 * Kernel addresses in the vmalloc space use at most 48 bits, and the
 * remaining bits are guaranteed to be 0x1. So we can compose the address
@@ -503,7 +518,6 @@ static int build_prologue(struct jit_ctx *ctx, bool ebpf_from_cbpf)
	const u8 arena_vm_base = bpf2a64[ARENA_VM_START];
	const u8 priv_sp = bpf2a64[PRIVATE_SP];
	void __percpu *priv_stack_ptr;
	const int idx0 = ctx->idx;
	int cur_offset;

	/*
@@ -529,6 +543,9 @@ static int build_prologue(struct jit_ctx *ctx, bool ebpf_from_cbpf)
	 *
	 */

	emit_kcfi(is_main_prog ? cfi_bpf_hash : cfi_bpf_subprog_hash, ctx);
	const int idx0 = ctx->idx;

	/* bpf function may be invoked by 3 instruction types:
	 * 1. bl, attached via freplace to bpf prog via short jump
	 * 2. br, attached via freplace to bpf prog via long jump
@@ -2146,9 +2163,9 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
		jit_data->ro_header = ro_header;
	}

	prog->bpf_func = (void *)ctx.ro_image;
	prog->bpf_func = (void *)ctx.ro_image + cfi_get_offset();
	prog->jited = 1;
	prog->jited_len = prog_size;
	prog->jited_len = prog_size - cfi_get_offset();

	if (!prog->is_func || extra_pass) {
		int i;
@@ -2527,6 +2544,12 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
	/* return address locates above FP */
	retaddr_off = stack_size + 8;

	if (flags & BPF_TRAMP_F_INDIRECT) {
		/*
		 * Indirect call for bpf_struct_ops
		 */
		emit_kcfi(cfi_get_func_hash(func_addr), ctx);
	}
	/* bpf trampoline may be invoked by 3 instruction types:
	 * 1. bl, attached to bpf prog or kernel function via short jump
	 * 2. br, attached to bpf prog or kernel function via long jump
@@ -3045,6 +3068,7 @@ void bpf_jit_free(struct bpf_prog *prog)
					   sizeof(jit_data->header->size));
			kfree(jit_data);
		}
		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;
+0 −16
Original line number Diff line number Diff line
@@ -14,27 +14,11 @@ struct pt_regs;
#ifdef CONFIG_CFI_CLANG
enum bug_trap_type handle_cfi_failure(struct pt_regs *regs);
#define __bpfcall
static inline int cfi_get_offset(void)
{
	return 4;
}

#define cfi_get_offset cfi_get_offset
extern u32 cfi_bpf_hash;
extern u32 cfi_bpf_subprog_hash;
extern u32 cfi_get_func_hash(void *func);
#else
static inline enum bug_trap_type handle_cfi_failure(struct pt_regs *regs)
{
	return BUG_TRAP_TYPE_NONE;
}

#define cfi_bpf_hash 0U
#define cfi_bpf_subprog_hash 0U
static inline u32 cfi_get_func_hash(void *func)
{
	return 0;
}
#endif /* CONFIG_CFI_CLANG */

#endif /* _ASM_RISCV_CFI_H */
+0 −53
Original line number Diff line number Diff line
@@ -75,56 +75,3 @@ enum bug_trap_type handle_cfi_failure(struct pt_regs *regs)

	return report_cfi_failure(regs, regs->epc, &target, type);
}

#ifdef CONFIG_CFI_CLANG
struct bpf_insn;

/* Must match bpf_func_t / DEFINE_BPF_PROG_RUN() */
extern unsigned int __bpf_prog_runX(const void *ctx,
				    const struct bpf_insn *insn);

/*
 * Force a reference to the external symbol so the compiler generates
 * __kcfi_typid.
 */
__ADDRESSABLE(__bpf_prog_runX);

/* u32 __ro_after_init cfi_bpf_hash = __kcfi_typeid___bpf_prog_runX; */
asm (
"	.pushsection	.data..ro_after_init,\"aw\",@progbits	\n"
"	.type	cfi_bpf_hash,@object				\n"
"	.globl	cfi_bpf_hash					\n"
"	.p2align	2, 0x0					\n"
"cfi_bpf_hash:							\n"
"	.word	__kcfi_typeid___bpf_prog_runX			\n"
"	.size	cfi_bpf_hash, 4					\n"
"	.popsection						\n"
);

/* Must match bpf_callback_t */
extern u64 __bpf_callback_fn(u64, u64, u64, u64, u64);

__ADDRESSABLE(__bpf_callback_fn);

/* u32 __ro_after_init cfi_bpf_subprog_hash = __kcfi_typeid___bpf_callback_fn; */
asm (
"	.pushsection	.data..ro_after_init,\"aw\",@progbits	\n"
"	.type	cfi_bpf_subprog_hash,@object			\n"
"	.globl	cfi_bpf_subprog_hash				\n"
"	.p2align	2, 0x0					\n"
"cfi_bpf_subprog_hash:						\n"
"	.word	__kcfi_typeid___bpf_callback_fn			\n"
"	.size	cfi_bpf_subprog_hash, 4				\n"
"	.popsection						\n"
);

u32 cfi_get_func_hash(void *func)
{
	u32 hash;

	if (get_kernel_nofault(hash, func - cfi_get_offset()))
		return 0;

	return hash;
}
#endif
+2 −8
Original line number Diff line number Diff line
@@ -116,8 +116,6 @@ struct pt_regs;
#ifdef CONFIG_CFI_CLANG
enum bug_trap_type handle_cfi_failure(struct pt_regs *regs);
#define __bpfcall
extern u32 cfi_bpf_hash;
extern u32 cfi_bpf_subprog_hash;

static inline int cfi_get_offset(void)
{
@@ -135,6 +133,8 @@ static inline int cfi_get_offset(void)
#define cfi_get_offset cfi_get_offset

extern u32 cfi_get_func_hash(void *func);
#define cfi_get_func_hash cfi_get_func_hash

extern int cfi_get_func_arity(void *func);

#ifdef CONFIG_FINEIBT
@@ -153,12 +153,6 @@ static inline enum bug_trap_type handle_cfi_failure(struct pt_regs *regs)
{
	return BUG_TRAP_TYPE_NONE;
}
#define cfi_bpf_hash 0U
#define cfi_bpf_subprog_hash 0U
static inline u32 cfi_get_func_hash(void *func)
{
	return 0;
}
static inline int cfi_get_func_arity(void *func)
{
	return 0;
Loading