]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.9.28/bpf-don-t-let-ldimm64-leak-map-addresses-on-unprivileged.patch
5.1-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.9.28 / bpf-don-t-let-ldimm64-leak-map-addresses-on-unprivileged.patch
1 From foo@baz Thu May 11 11:08:24 CEST 2017
2 From: Daniel Borkmann <daniel@iogearbox.net>
3 Date: Mon, 8 May 2017 00:04:09 +0200
4 Subject: bpf: don't let ldimm64 leak map addresses on unprivileged
5
6 From: Daniel Borkmann <daniel@iogearbox.net>
7
8
9 [ Upstream commit 0d0e57697f162da4aa218b5feafe614fb666db07 ]
10
11 The patch fixes two things at once:
12
13 1) It checks the env->allow_ptr_leaks and only prints the map address to
14 the log if we have the privileges to do so, otherwise it just dumps 0
15 as we would when kptr_restrict is enabled on %pK. Given the latter is
16 off by default and not every distro sets it, I don't want to rely on
17 this, hence the 0 by default for unprivileged.
18
19 2) Printing of ldimm64 in the verifier log is currently broken in that
20 we don't print the full immediate, but only the 32 bit part of the
21 first insn part for ldimm64. Thus, fix this up as well; it's okay to
22 access, since we verified all ldimm64 earlier already (including just
23 constants) through replace_map_fd_with_map_ptr().
24
25 Fixes: 1be7f75d1668 ("bpf: enable non-root eBPF programs")
26 Fixes: cbd357008604 ("bpf: verifier (add ability to receive verification log)")
27 Reported-by: Jann Horn <jannh@google.com>
28 Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
29 Acked-by: Alexei Starovoitov <ast@kernel.org>
30 Signed-off-by: David S. Miller <davem@davemloft.net>
31 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
32 ---
33 kernel/bpf/verifier.c | 21 ++++++++++++++++-----
34 1 file changed, 16 insertions(+), 5 deletions(-)
35
36 --- a/kernel/bpf/verifier.c
37 +++ b/kernel/bpf/verifier.c
38 @@ -279,7 +279,8 @@ static const char *const bpf_jmp_string[
39 [BPF_EXIT >> 4] = "exit",
40 };
41
42 -static void print_bpf_insn(struct bpf_insn *insn)
43 +static void print_bpf_insn(const struct bpf_verifier_env *env,
44 + const struct bpf_insn *insn)
45 {
46 u8 class = BPF_CLASS(insn->code);
47
48 @@ -343,9 +344,19 @@ static void print_bpf_insn(struct bpf_in
49 insn->code,
50 bpf_ldst_string[BPF_SIZE(insn->code) >> 3],
51 insn->src_reg, insn->imm);
52 - } else if (BPF_MODE(insn->code) == BPF_IMM) {
53 - verbose("(%02x) r%d = 0x%x\n",
54 - insn->code, insn->dst_reg, insn->imm);
55 + } else if (BPF_MODE(insn->code) == BPF_IMM &&
56 + BPF_SIZE(insn->code) == BPF_DW) {
57 + /* At this point, we already made sure that the second
58 + * part of the ldimm64 insn is accessible.
59 + */
60 + u64 imm = ((u64)(insn + 1)->imm << 32) | (u32)insn->imm;
61 + bool map_ptr = insn->src_reg == BPF_PSEUDO_MAP_FD;
62 +
63 + if (map_ptr && !env->allow_ptr_leaks)
64 + imm = 0;
65 +
66 + verbose("(%02x) r%d = 0x%llx\n", insn->code,
67 + insn->dst_reg, (unsigned long long)imm);
68 } else {
69 verbose("BUG_ld_%02x\n", insn->code);
70 return;
71 @@ -2674,7 +2685,7 @@ static int do_check(struct bpf_verifier_
72
73 if (log_level) {
74 verbose("%d: ", insn_idx);
75 - print_bpf_insn(insn);
76 + print_bpf_insn(env, insn);
77 }
78
79 err = ext_analyzer_insn_hook(env, insn_idx, prev_insn_idx);