Skip to content

Commit 2a02759

Browse files
Alexei Starovoitovborkmann
authored andcommitted
bpf: Add support for BTF pointers to interpreter
Pointer to BTF object is a pointer to kernel object or NULL. The memory access in the interpreter has to be done via probe_kernel_read to avoid page faults. Signed-off-by: Alexei Starovoitov <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Acked-by: Andrii Nakryiko <[email protected]> Acked-by: Martin KaFai Lau <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent ac4414b commit 2a02759

File tree

3 files changed

+30
-0
lines changed

3 files changed

+30
-0
lines changed

include/linux/filter.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ struct ctl_table_header;
6565
/* unused opcode to mark special call to bpf_tail_call() helper */
6666
#define BPF_TAIL_CALL 0xf0
6767

68+
/* unused opcode to mark special load instruction. Same as BPF_ABS */
69+
#define BPF_PROBE_MEM 0x20
70+
6871
/* unused opcode to mark call to interpreter with arguments */
6972
#define BPF_CALL_ARGS 0xe0
7073

kernel/bpf/core.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1291,6 +1291,11 @@ bool bpf_opcode_in_insntable(u8 code)
12911291
}
12921292

12931293
#ifndef CONFIG_BPF_JIT_ALWAYS_ON
1294+
u64 __weak bpf_probe_read(void * dst, u32 size, const void * unsafe_ptr)
1295+
{
1296+
memset(dst, 0, size);
1297+
return -EFAULT;
1298+
}
12941299
/**
12951300
* __bpf_prog_run - run eBPF program on a given context
12961301
* @regs: is the array of MAX_BPF_EXT_REG eBPF pseudo-registers
@@ -1310,6 +1315,10 @@ static u64 __no_fgcse ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn, u6
13101315
/* Non-UAPI available opcodes. */
13111316
[BPF_JMP | BPF_CALL_ARGS] = &&JMP_CALL_ARGS,
13121317
[BPF_JMP | BPF_TAIL_CALL] = &&JMP_TAIL_CALL,
1318+
[BPF_LDX | BPF_PROBE_MEM | BPF_B] = &&LDX_PROBE_MEM_B,
1319+
[BPF_LDX | BPF_PROBE_MEM | BPF_H] = &&LDX_PROBE_MEM_H,
1320+
[BPF_LDX | BPF_PROBE_MEM | BPF_W] = &&LDX_PROBE_MEM_W,
1321+
[BPF_LDX | BPF_PROBE_MEM | BPF_DW] = &&LDX_PROBE_MEM_DW,
13131322
};
13141323
#undef BPF_INSN_3_LBL
13151324
#undef BPF_INSN_2_LBL
@@ -1542,6 +1551,16 @@ static u64 __no_fgcse ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn, u6
15421551
LDST(W, u32)
15431552
LDST(DW, u64)
15441553
#undef LDST
1554+
#define LDX_PROBE(SIZEOP, SIZE) \
1555+
LDX_PROBE_MEM_##SIZEOP: \
1556+
bpf_probe_read(&DST, SIZE, (const void *)(long) SRC); \
1557+
CONT;
1558+
LDX_PROBE(B, 1)
1559+
LDX_PROBE(H, 2)
1560+
LDX_PROBE(W, 4)
1561+
LDX_PROBE(DW, 8)
1562+
#undef LDX_PROBE
1563+
15451564
STX_XADD_W: /* lock xadd *(u32 *)(dst_reg + off16) += src_reg */
15461565
atomic_add((u32) SRC, (atomic_t *)(unsigned long)
15471566
(DST + insn->off));

kernel/bpf/verifier.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7581,6 +7581,7 @@ static bool reg_type_mismatch_ok(enum bpf_reg_type type)
75817581
case PTR_TO_TCP_SOCK:
75827582
case PTR_TO_TCP_SOCK_OR_NULL:
75837583
case PTR_TO_XDP_SOCK:
7584+
case PTR_TO_BTF_ID:
75847585
return false;
75857586
default:
75867587
return true;
@@ -8722,6 +8723,13 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
87228723
case PTR_TO_XDP_SOCK:
87238724
convert_ctx_access = bpf_xdp_sock_convert_ctx_access;
87248725
break;
8726+
case PTR_TO_BTF_ID:
8727+
if (type == BPF_WRITE) {
8728+
verbose(env, "Writes through BTF pointers are not allowed\n");
8729+
return -EINVAL;
8730+
}
8731+
insn->code = BPF_LDX | BPF_PROBE_MEM | BPF_SIZE((insn)->code);
8732+
continue;
87258733
default:
87268734
continue;
87278735
}

0 commit comments

Comments
 (0)