aboutsummaryrefslogtreecommitdiffstats
path: root/tools/testing
diff options
context:
space:
mode:
authorDaniel Borkmann <daniel@iogearbox.net>2018-06-07 11:40:03 -0400
committerAlexei Starovoitov <ast@kernel.org>2018-06-07 15:37:17 -0400
commit58990d1ff3f7896ee341030e9a7c2e4002570683 (patch)
treecfc70cdd8cca1754404ad25757737141a73e4263 /tools/testing
parent1c8c5a9d38f607c0b6fd12c91cbe1a4418762a21 (diff)
bpf: reject passing modified ctx to helper functions
As commit 28e33f9d78ee ("bpf: disallow arithmetic operations on context pointer") already describes, f1174f77b50c ("bpf/verifier: rework value tracking") removed the specific white-listed cases we had previously where we would allow for pointer arithmetic in order to further generalize it, and allow e.g. context access via modified registers. While the dereferencing of modified context pointers had been forbidden through 28e33f9d78ee, syzkaller did recently manage to trigger several KASAN splats for slab out of bounds access and use after frees by simply passing a modified context pointer to a helper function which would then do the bad access since verifier allowed it in adjust_ptr_min_max_vals(). Rejecting arithmetic on ctx pointer in adjust_ptr_min_max_vals() generally could break existing programs as there's a valid use case in tracing in combination with passing the ctx to helpers as bpf_probe_read(), where the register then becomes unknown at verification time due to adding a non-constant offset to it. An access sequence may look like the following: offset = args->filename; /* field __data_loc filename */ bpf_probe_read(&dst, len, (char *)args + offset); // args is ctx There are two options: i) we could special case the ctx and as soon as we add a constant or bounded offset to it (hence ctx type wouldn't change) we could turn the ctx into an unknown scalar, or ii) we generalize the sanity test for ctx member access into a small helper and assert it on the ctx register that was passed as a function argument. Fwiw, latter is more obvious and less complex at the same time, and one case that may potentially be legitimate in future for ctx member access at least would be for ctx to carry a const offset. Therefore, fix follows approach from ii) and adds test cases to BPF kselftests. Fixes: f1174f77b50c ("bpf/verifier: rework value tracking") Reported-by: syzbot+3d0b2441dbb71751615e@syzkaller.appspotmail.com Reported-by: syzbot+c8504affd4fdd0c1b626@syzkaller.appspotmail.com Reported-by: syzbot+e5190cb881d8660fb1a3@syzkaller.appspotmail.com Reported-by: syzbot+efae31b384d5badbd620@syzkaller.appspotmail.com Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Alexei Starovoitov <ast@kernel.org> Acked-by: Yonghong Song <yhs@fb.com> Acked-by: Edward Cree <ecree@solarflare.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'tools/testing')
-rw-r--r--tools/testing/selftests/bpf/test_verifier.c58
1 files changed, 57 insertions, 1 deletions
diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c
index 7cb1d74057ce..2ecd27b670d7 100644
--- a/tools/testing/selftests/bpf/test_verifier.c
+++ b/tools/testing/selftests/bpf/test_verifier.c
@@ -8647,7 +8647,7 @@ static struct bpf_test tests[] = {
8647 offsetof(struct __sk_buff, mark)), 8647 offsetof(struct __sk_buff, mark)),
8648 BPF_EXIT_INSN(), 8648 BPF_EXIT_INSN(),
8649 }, 8649 },
8650 .errstr = "dereference of modified ctx ptr R1 off=68+8, ctx+const is allowed, ctx+const+const is not", 8650 .errstr = "dereference of modified ctx ptr",
8651 .result = REJECT, 8651 .result = REJECT,
8652 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 8652 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
8653 }, 8653 },
@@ -12258,6 +12258,62 @@ static struct bpf_test tests[] = {
12258 .result = ACCEPT, 12258 .result = ACCEPT,
12259 .retval = 5, 12259 .retval = 5,
12260 }, 12260 },
12261 {
12262 "pass unmodified ctx pointer to helper",
12263 .insns = {
12264 BPF_MOV64_IMM(BPF_REG_2, 0),
12265 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
12266 BPF_FUNC_csum_update),
12267 BPF_MOV64_IMM(BPF_REG_0, 0),
12268 BPF_EXIT_INSN(),
12269 },
12270 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
12271 .result = ACCEPT,
12272 },
12273 {
12274 "pass modified ctx pointer to helper, 1",
12275 .insns = {
12276 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -612),
12277 BPF_MOV64_IMM(BPF_REG_2, 0),
12278 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
12279 BPF_FUNC_csum_update),
12280 BPF_MOV64_IMM(BPF_REG_0, 0),
12281 BPF_EXIT_INSN(),
12282 },
12283 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
12284 .result = REJECT,
12285 .errstr = "dereference of modified ctx ptr",
12286 },
12287 {
12288 "pass modified ctx pointer to helper, 2",
12289 .insns = {
12290 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -612),
12291 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
12292 BPF_FUNC_get_socket_cookie),
12293 BPF_MOV64_IMM(BPF_REG_0, 0),
12294 BPF_EXIT_INSN(),
12295 },
12296 .result_unpriv = REJECT,
12297 .result = REJECT,
12298 .errstr_unpriv = "dereference of modified ctx ptr",
12299 .errstr = "dereference of modified ctx ptr",
12300 },
12301 {
12302 "pass modified ctx pointer to helper, 3",
12303 .insns = {
12304 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, 0),
12305 BPF_ALU64_IMM(BPF_AND, BPF_REG_3, 4),
12306 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
12307 BPF_MOV64_IMM(BPF_REG_2, 0),
12308 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
12309 BPF_FUNC_csum_update),
12310 BPF_MOV64_IMM(BPF_REG_0, 0),
12311 BPF_EXIT_INSN(),
12312 },
12313 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
12314 .result = REJECT,
12315 .errstr = "variable ctx access var_off=(0x0; 0x4)",
12316 },
12261}; 12317};
12262 12318
12263static int probe_filter_length(const struct bpf_insn *fp) 12319static int probe_filter_length(const struct bpf_insn *fp)