mirror of
https://github.com/torvalds/linux.git
synced 2026-09-28 12:02:03 +02:00
selftests/bpf: Test CO-RE instruction poisoning restrictions
Add raw CO-RE relocations that fail to resolve their target enum value. Place each supported and unsupported instruction form in dead code. Unsupported targets must fail relocation with a diagnostic even when they are unreachable. Supported ALU immediates, memory accesses, and ldimm64 instructions must still be poisoned and removed as dead code, allowing the program to load. Check that both halves of ldimm64 are poisoned. Load every instruction stream without relocations first to ensure that rejection is caused by the relocation rather than the original program. Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> Acked-by: Eduard Zingerman <eddyz87@gmail.com> Link: https://patch.msgid.link/20260917233222.2542500-8-memxor@gmail.com Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
This commit is contained in:
parent
394ae39833
commit
3440505aca
|
|
@ -50,6 +50,28 @@ static int load_core_relo_insns(int btf_fd, struct bpf_insn *insns, int insn_cnt
|
|||
|
||||
static void test_early_core_relo(void)
|
||||
{
|
||||
static const char unrecognized[] = "trying to relocate unrecognized insn #2";
|
||||
static const struct {
|
||||
const char *name;
|
||||
struct bpf_insn insns[2];
|
||||
const char *err_msg;
|
||||
} tests[] = {
|
||||
{ "poison_exit", { BPF_EXIT_INSN() }, unrecognized },
|
||||
{ "poison_ja", { BPF_JMP_A(1) }, unrecognized },
|
||||
{ "poison_jmp", { BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1) }, unrecognized },
|
||||
{ "poison_jmp32", { BPF_JMP32_IMM(BPF_JEQ, BPF_REG_0, 0, 1) }, unrecognized },
|
||||
{ "poison_call", { BPF_EMIT_CALL(BPF_FUNC_get_prandom_u32) }, unrecognized },
|
||||
{ "poison_alu_reg", { BPF_MOV32_REG(BPF_REG_0, BPF_REG_1) }, unrecognized },
|
||||
{ "poison_alu64_reg", { BPF_MOV64_REG(BPF_REG_0, BPF_REG_1) }, unrecognized },
|
||||
{ "poison_ld_abs", { BPF_LD_ABS(BPF_W, 0) },
|
||||
"insn #2 (LDIMM64) has unexpected form" },
|
||||
{ "poison_alu_imm", { BPF_MOV32_IMM(BPF_REG_0, 0) } },
|
||||
{ "poison_alu64_imm", { BPF_MOV64_IMM(BPF_REG_0, 0) } },
|
||||
{ "poison_ldx", { BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 0) } },
|
||||
{ "poison_st", { BPF_ST_MEM(BPF_W, BPF_REG_10, -4, 0) } },
|
||||
{ "poison_stx", { BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -4) } },
|
||||
{ "poison_ldimm64", { BPF_LD_IMM64(BPF_REG_0, 0) } },
|
||||
};
|
||||
struct test_btf {
|
||||
struct btf_header hdr;
|
||||
__u32 types[18];
|
||||
|
|
@ -97,7 +119,7 @@ static void test_early_core_relo(void)
|
|||
};
|
||||
int access_str_off = 51; /* offset of "0" */
|
||||
int enum_id = 5;
|
||||
int btf_fd, prog_fd = -1;
|
||||
int btf_fd, prog_fd = -1, i;
|
||||
|
||||
btf_fd = bpf_btf_load(&raw_btf, sizeof(raw_btf), NULL);
|
||||
if (!ASSERT_GE(btf_fd, 0, "btf_load"))
|
||||
|
|
@ -136,6 +158,43 @@ static void test_early_core_relo(void)
|
|||
ASSERT_HAS_SUBSTR(log, "invalid bpf_ld_imm64 insn", "truncated_load_log");
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(tests); i++) {
|
||||
struct bpf_insn insns[] = {
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0),
|
||||
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
|
||||
tests[i].insns[0],
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0),
|
||||
BPF_EXIT_INSN(),
|
||||
};
|
||||
bool is_ldimm64 = insns[2].code == (BPF_LD | BPF_DW | BPF_IMM);
|
||||
|
||||
if (!test__start_subtest(tests[i].name))
|
||||
continue;
|
||||
if (is_ldimm64) {
|
||||
insns[1].off = 2;
|
||||
insns[3] = tests[i].insns[1];
|
||||
}
|
||||
prog_fd = load_core_relo_insns(btf_fd, insns, ARRAY_SIZE(insns), funcs, 1,
|
||||
enum_id, access_str_off, 2, false);
|
||||
if (!ASSERT_GE(prog_fd, 0, "control_load"))
|
||||
goto cleanup;
|
||||
close(prog_fd);
|
||||
prog_fd = load_core_relo_insns(btf_fd, insns, ARRAY_SIZE(insns), funcs, 1,
|
||||
enum_id, access_str_off, 2, true);
|
||||
if (!tests[i].err_msg) {
|
||||
ASSERT_GE(prog_fd, 0, "dead_poison_load");
|
||||
ASSERT_HAS_SUBSTR(log, "substituting insn #2", "poison_log");
|
||||
if (is_ldimm64)
|
||||
ASSERT_HAS_SUBSTR(log, "substituting insn #3", "poison_ldimm64_log");
|
||||
} else {
|
||||
ASSERT_LT(prog_fd, 0, "invalid_poison_load");
|
||||
ASSERT_HAS_SUBSTR(log, tests[i].err_msg, "invalid_poison_log");
|
||||
ASSERT_NULL(strstr(log, "substituting insn"), "invalid_poison_substitution");
|
||||
}
|
||||
close(prog_fd);
|
||||
prog_fd = -1;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (env.verbosity > VERBOSE_NORMAL && log[0]) {
|
||||
printf("-------- program load log start --------\n");
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user