270 lines · 8.1 KB · C
RawDownload
#define BTF_TYPES \	.btf_strings = "\0int\0i\0ctx\0callback\0main\0", \	.btf_types = { \	/* 1: int   */ BTF_TYPE_INT_ENC(1, BTF_INT_SIGNED, 0, 32, 4), \	/* 2: int*  */ BTF_PTR_ENC(1), \	/* 3: void* */ BTF_PTR_ENC(0), \	/* 4: int __(void*) */ BTF_FUNC_PROTO_ENC(1, 1), \		BTF_FUNC_PROTO_ARG_ENC(7, 3), \	/* 5: int __(int, int*) */ BTF_FUNC_PROTO_ENC(1, 2), \		BTF_FUNC_PROTO_ARG_ENC(5, 1), \		BTF_FUNC_PROTO_ARG_ENC(7, 2), \	/* 6: main      */ BTF_FUNC_ENC(20, 4), \	/* 7: callback  */ BTF_FUNC_ENC(11, 5), \	BTF_END_RAW \	} #define MAIN_TYPE	6#define CALLBACK_TYPE	7 /* can't use BPF_CALL_REL, jit_subprogs adjusts IMM & OFF * fields for pseudo calls */#define PSEUDO_CALL_INSN() \	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_CALL, \		     INSN_OFF_MASK, INSN_IMM_MASK) /* can't use BPF_FUNC_loop constant, * do_mix_fixups adjusts the IMM field */#define HELPER_CALL_INSN() \	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, INSN_OFF_MASK, INSN_IMM_MASK) {	"inline simple bpf_loop call",	.insns = {	/* main */	/* force verifier state branching to verify logic on first and	 * subsequent bpf_loop insn processing steps	 */	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_jiffies64),	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 777, 2),	BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1),	BPF_JMP_IMM(BPF_JA, 0, 0, 1),	BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 2), 	BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 6),	BPF_RAW_INSN(0, 0, 0, 0, 0),	BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),	BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),	BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),	BPF_EXIT_INSN(),	/* callback */	BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),	BPF_EXIT_INSN(),	},	.expected_insns = { PSEUDO_CALL_INSN() },	.unexpected_insns = { HELPER_CALL_INSN() },	.prog_type = BPF_PROG_TYPE_TRACEPOINT,	.flags = F_NEEDS_JIT_ENABLED,	.result = ACCEPT,	.runs = 0,	.func_info = { { 0, MAIN_TYPE }, { 12, CALLBACK_TYPE } },	.func_info_cnt = 2,	BTF_TYPES},{	"don't inline bpf_loop call, flags non-zero",	.insns = {	/* main */	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_jiffies64),	BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_0),	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_jiffies64),	BPF_ALU64_REG(BPF_MOV, BPF_REG_7, BPF_REG_0),	BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 0, 9),	BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),	BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 0, 0),	BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1),	BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 7),	BPF_RAW_INSN(0, 0, 0, 0, 0),	BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),	BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),	BPF_EXIT_INSN(),	BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 1),	BPF_JMP_IMM(BPF_JA, 0, 0, -10),	/* callback */	BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),	BPF_EXIT_INSN(),	},	.expected_insns = { HELPER_CALL_INSN() },	.unexpected_insns = { PSEUDO_CALL_INSN() },	.prog_type = BPF_PROG_TYPE_TRACEPOINT,	.flags = F_NEEDS_JIT_ENABLED,	.result = ACCEPT,	.runs = 0,	.func_info = { { 0, MAIN_TYPE }, { 16, CALLBACK_TYPE } },	.func_info_cnt = 2,	BTF_TYPES},{	"don't inline bpf_loop call, callback non-constant",	.insns = {	/* main */	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_jiffies64),	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 777, 4), /* pick a random callback */ 	BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1),	BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 10),	BPF_RAW_INSN(0, 0, 0, 0, 0),	BPF_JMP_IMM(BPF_JA, 0, 0, 3), 	BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1),	BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 8),	BPF_RAW_INSN(0, 0, 0, 0, 0), 	BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),	BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),	BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),	BPF_EXIT_INSN(),	/* callback */	BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),	BPF_EXIT_INSN(),	/* callback #2 */	BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),	BPF_EXIT_INSN(),	},	.expected_insns = { HELPER_CALL_INSN() },	.unexpected_insns = { PSEUDO_CALL_INSN() },	.prog_type = BPF_PROG_TYPE_TRACEPOINT,	.flags = F_NEEDS_JIT_ENABLED,	.result = ACCEPT,	.runs = 0,	.func_info = {		{ 0, MAIN_TYPE },		{ 14, CALLBACK_TYPE },		{ 16, CALLBACK_TYPE }	},	.func_info_cnt = 3,	BTF_TYPES},{	"bpf_loop_inline and a dead func",	.insns = {	/* main */ 	/* A reference to callback #1 to make verifier count it as a func.	 * This reference is overwritten below and callback #1 is dead.	 */	BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 9),	BPF_RAW_INSN(0, 0, 0, 0, 0),	BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1),	BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 8),	BPF_RAW_INSN(0, 0, 0, 0, 0),	BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),	BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),	BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),	BPF_EXIT_INSN(),	/* callback */	BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),	BPF_EXIT_INSN(),	/* callback #2 */	BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),	BPF_EXIT_INSN(),	},	.expected_insns = { PSEUDO_CALL_INSN() },	.unexpected_insns = { HELPER_CALL_INSN() },	.prog_type = BPF_PROG_TYPE_TRACEPOINT,	.flags = F_NEEDS_JIT_ENABLED,	.result = ACCEPT,	.runs = 0,	.func_info = {		{ 0, MAIN_TYPE },		{ 10, CALLBACK_TYPE },		{ 12, CALLBACK_TYPE }	},	.func_info_cnt = 3,	BTF_TYPES},{	"bpf_loop_inline stack locations for loop vars",	.insns = {	/* main */	BPF_ST_MEM(BPF_W, BPF_REG_10, -12, 0x77),	/* bpf_loop call #1 */	BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1),	BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 22),	BPF_RAW_INSN(0, 0, 0, 0, 0),	BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),	BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),	/* bpf_loop call #2 */	BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 2),	BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 16),	BPF_RAW_INSN(0, 0, 0, 0, 0),	BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),	BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),	/* call func and exit */	BPF_CALL_REL(2),	BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),	BPF_EXIT_INSN(),	/* func */	BPF_ST_MEM(BPF_DW, BPF_REG_10, -32, 0x55),	BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 2),	BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 6),	BPF_RAW_INSN(0, 0, 0, 0, 0),	BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0),	BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0),	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop),	BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0),	BPF_EXIT_INSN(),	/* callback */	BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1),	BPF_EXIT_INSN(),	},	.expected_insns = {	BPF_ST_MEM(BPF_W, BPF_REG_10, -12, 0x77),	SKIP_INSNS(),	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_6, -40),	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_7, -32),	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_8, -24),	SKIP_INSNS(),	/* offsets are the same as in the first call */	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_6, -40),	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_7, -32),	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_8, -24),	SKIP_INSNS(),	BPF_ST_MEM(BPF_DW, BPF_REG_10, -32, 0x55),	SKIP_INSNS(),	/* offsets differ from main because of different offset	 * in BPF_ST_MEM instruction	 */	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_6, -56),	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_7, -48),	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_8, -40),	},	.unexpected_insns = { HELPER_CALL_INSN() },	.prog_type = BPF_PROG_TYPE_TRACEPOINT,	.flags = F_NEEDS_JIT_ENABLED,	.result = ACCEPT,	.func_info = {		{ 0, MAIN_TYPE },		{ 16, MAIN_TYPE },		{ 25, CALLBACK_TYPE },	},	.func_info_cnt = 3,	BTF_TYPES},{	"inline bpf_loop call in a big program",	.insns = {},	.fill_helper = bpf_fill_big_prog_with_loop_1,	.expected_insns = { PSEUDO_CALL_INSN() },	.unexpected_insns = { HELPER_CALL_INSN() },	.result = ACCEPT,	.prog_type = BPF_PROG_TYPE_TRACEPOINT,	.flags = F_NEEDS_JIT_ENABLED,	.func_info = { { 0, MAIN_TYPE }, { 16, CALLBACK_TYPE } },	.func_info_cnt = 2,	BTF_TYPES}, #undef HELPER_CALL_INSN#undef PSEUDO_CALL_INSN#undef CALLBACK_TYPE#undef MAIN_TYPE#undef BTF_TYPES