Unverified Commit df8594ea authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!13277 CVE-2023-52920

Merge Pull Request from: @ci-robot 
 
PR sync from: Pu Lehui <pulehui@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/4ZPSZMHVCAS44XMMNPQ76P5EJQAUIIQ2/ 
Andrii Nakryiko (5):
  bpf: decouple prune and jump points
  bpf: encapsulate precision backtracking bookkeeping
  bpf: mostly decouple jump history management from is_state_visited()
  bpf: support non-r10 register spill/fill to/from stack in precision
    tracking
  bpf: handle fake register spill to stack with BPF_ST_MEM instruction


-- 
2.34.1
 
https://gitee.com/src-openeuler/kernel/issues/IB2AQ3 
 
Link:https://gitee.com/openeuler/kernel/pulls/13277

 

Reviewed-by: default avatarYe Weihua <yeweihua4@huawei.com>
Signed-off-by: default avatarYang Yingliang <yangyingliang@huawei.com>
parents 576c8cd1 1f240541
Loading
Loading
Loading
Loading
+42 −4
Original line number Diff line number Diff line
@@ -161,6 +161,10 @@ enum bpf_stack_slot_type {

#define BPF_REG_SIZE 8	/* size of eBPF register in bytes */

#define BPF_REGMASK_ARGS ((1 << BPF_REG_1) | (1 << BPF_REG_2) | \
			  (1 << BPF_REG_3) | (1 << BPF_REG_4) | \
			  (1 << BPF_REG_5))

struct bpf_stack_state {
	struct bpf_reg_state spilled_ptr;
	u8 slot_type[BPF_REG_SIZE];
@@ -206,9 +210,32 @@ struct bpf_func_state {
	struct bpf_stack_state *stack;
};

struct bpf_idx_pair {
	u32 prev_idx;
#define MAX_CALL_FRAMES 8

/* instruction history flags, used in bpf_jmp_history_entry.flags field */
enum {
	/* instruction references stack slot through PTR_TO_STACK register;
	 * we also store stack's frame number in lower 3 bits (MAX_CALL_FRAMES is 8)
	 * and accessed stack slot's index in next 6 bits (MAX_BPF_STACK is 512,
	 * 8 bytes per slot, so slot index (spi) is [0, 63])
	 */
	INSN_F_FRAMENO_MASK = 0x7, /* 3 bits */

	INSN_F_SPI_MASK = 0x3f, /* 6 bits */
	INSN_F_SPI_SHIFT = 3, /* shifted 3 bits to the left */

	INSN_F_STACK_ACCESS = BIT(9), /* we need 10 bits total */
};

static_assert(INSN_F_FRAMENO_MASK + 1 >= MAX_CALL_FRAMES);
static_assert(INSN_F_SPI_MASK + 1 >= MAX_BPF_STACK / 8);

struct bpf_jmp_history_entry {
	u32 idx;
	/* insn idx can't be bigger than 1 million */
	u32 prev_idx : 22;
	/* special flags, e.g., whether insn is doing register stack spill/load */
	u32 flags : 10;
};

struct bpf_id_pair {
@@ -218,7 +245,6 @@ struct bpf_id_pair {

/* Maximum number of register states that can exist at once */
#define BPF_ID_MAP_SIZE (MAX_BPF_REG + MAX_BPF_STACK / BPF_REG_SIZE)
#define MAX_CALL_FRAMES 8
struct bpf_verifier_state {
	/* call stack tracking */
	struct bpf_func_state *frame[MAX_CALL_FRAMES];
@@ -282,7 +308,7 @@ struct bpf_verifier_state {
	 * For most states jmp_history_cnt is [0-3].
	 * For loops can go up to ~40.
	 */
	struct bpf_idx_pair *jmp_history;
	struct bpf_jmp_history_entry *jmp_history;
	u32 jmp_history_cnt;
};

@@ -362,6 +388,7 @@ struct bpf_insn_aux_data {
	/* below fields are initialized once */
	unsigned int orig_idx; /* original instruction index */
	bool prune_point;
	bool jmp_point;
};

#define MAX_USED_MAPS 64 /* max number of maps accessed by one eBPF program */
@@ -414,6 +441,15 @@ struct bpf_subprog_info {
	bool has_ld_abs;
};

struct bpf_verifier_env;

struct backtrack_state {
	struct bpf_verifier_env *env;
	u32 frame;
	u32 reg_masks[MAX_CALL_FRAMES];
	u64 stack_masks[MAX_CALL_FRAMES];
};

/* single container for all structs
 * one verifier_env per bpf_check() call
 */
@@ -450,6 +486,8 @@ struct bpf_verifier_env {
		int *insn_stack;
		int cur_stack;
	} cfg;
	struct backtrack_state bt;
	struct bpf_jmp_history_entry *cur_hist_ent;
	u32 pass_cnt; /* number of times do_check() was called */
	u32 subprog_cnt;
	/* number of instructions analyzed by the verifier */
+324 −156

File changed.

Preview size limit exceeded, changes collapsed.

+19 −10
Original line number Diff line number Diff line
@@ -141,10 +141,11 @@
	.result = REJECT,
},
{
	"precise: ST insn causing spi > allocated_stack",
	"precise: ST zero to stack insn is supported",
	.insns = {
	BPF_MOV64_REG(BPF_REG_3, BPF_REG_10),
	BPF_JMP_IMM(BPF_JNE, BPF_REG_3, 123, 0),
	/* not a register spill, so we stop precision propagation for R4 here */
	BPF_ST_MEM(BPF_DW, BPF_REG_3, -8, 0),
	BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_10, -8),
	BPF_MOV64_IMM(BPF_REG_0, -1),
@@ -159,9 +160,10 @@
	last_idx 4 first_idx 2\
	regs=10 stack=0 before 4\
	regs=10 stack=0 before 3\
	regs=0 stack=1 before 2\
	last_idx 5 first_idx 5\
	parent didn't have regs=1 stack=0 marks",
	parent didn't have regs=1 stack=0 marks\
	last_idx 4 first_idx 2\
	regs=1 stack=0 before 4",
	.result = VERBOSE_ACCEPT,
	.retval = -1,
},
@@ -169,6 +171,8 @@
	"precise: STX insn causing spi > allocated_stack",
	.insns = {
	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
	/* make later reg spill more interesting by having somewhat known scalar */
	BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xff),
	BPF_MOV64_REG(BPF_REG_3, BPF_REG_10),
	BPF_JMP_IMM(BPF_JNE, BPF_REG_3, 123, 0),
	BPF_STX_MEM(BPF_DW, BPF_REG_3, BPF_REG_0, -8),
@@ -179,16 +183,21 @@
	},
	.prog_type = BPF_PROG_TYPE_XDP,
	.flags = BPF_F_TEST_STATE_FREQ,
	.errstr = "last_idx 6 first_idx 6\
	.errstr = "last_idx 7 first_idx 7\
	parent didn't have regs=10 stack=0 marks\
	last_idx 5 first_idx 3\
	last_idx 6 first_idx 4\
	regs=10 stack=0 before 6\
	regs=10 stack=0 before 5\
	regs=10 stack=0 before 4\
	regs=0 stack=1 before 3\
	last_idx 6 first_idx 6\
	regs=0 stack=1 before 4\
	parent didn't have regs=1 stack=0 marks\
	last_idx 3 first_idx 3\
	regs=1 stack=0 before 3\
	regs=1 stack=0 before 2\
	regs=1 stack=0 before 1\
	parent didn't have regs=1 stack=0 marks\
	last_idx 5 first_idx 3\
	regs=1 stack=0 before 5",
	last_idx 0 first_idx 0\
	regs=1 stack=0 before 0\
	last_idx 7 first_idx 7",
	.result = VERBOSE_ACCEPT,
	.retval = -1,
},