aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Borkmann <daniel@iogearbox.net>2017-05-07 18:04:09 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-05-14 08:00:21 -0400
commitced0a31e667fbf618591f0a76a8213018407cde0 (patch)
tree5ca491dbf4b5faded37c2447259cc314cffb6f2a
parente37aab9c63b87dd4ece0b570d3886f7c6c03b549 (diff)
bpf: don't let ldimm64 leak map addresses on unprivileged
[ Upstream commit 0d0e57697f162da4aa218b5feafe614fb666db07 ] The patch fixes two things at once: 1) It checks the env->allow_ptr_leaks and only prints the map address to the log if we have the privileges to do so, otherwise it just dumps 0 as we would when kptr_restrict is enabled on %pK. Given the latter is off by default and not every distro sets it, I don't want to rely on this, hence the 0 by default for unprivileged. 2) Printing of ldimm64 in the verifier log is currently broken in that we don't print the full immediate, but only the 32 bit part of the first insn part for ldimm64. Thus, fix this up as well; it's okay to access, since we verified all ldimm64 earlier already (including just constants) through replace_map_fd_with_map_ptr(). Fixes: 1be7f75d1668 ("bpf: enable non-root eBPF programs") Fixes: cbd357008604 ("bpf: verifier (add ability to receive verification log)") Reported-by: Jann Horn <jannh@google.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--kernel/bpf/verifier.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 64fcab1d8cd9..44c17f47d94c 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -279,7 +279,8 @@ static const char *const bpf_jmp_string[16] = {
279 [BPF_EXIT >> 4] = "exit", 279 [BPF_EXIT >> 4] = "exit",
280}; 280};
281 281
282static void print_bpf_insn(struct bpf_insn *insn) 282static void print_bpf_insn(const struct bpf_verifier_env *env,
283 const struct bpf_insn *insn)
283{ 284{
284 u8 class = BPF_CLASS(insn->code); 285 u8 class = BPF_CLASS(insn->code);
285 286
@@ -343,9 +344,19 @@ static void print_bpf_insn(struct bpf_insn *insn)
343 insn->code, 344 insn->code,
344 bpf_ldst_string[BPF_SIZE(insn->code) >> 3], 345 bpf_ldst_string[BPF_SIZE(insn->code) >> 3],
345 insn->src_reg, insn->imm); 346 insn->src_reg, insn->imm);
346 } else if (BPF_MODE(insn->code) == BPF_IMM) { 347 } else if (BPF_MODE(insn->code) == BPF_IMM &&
347 verbose("(%02x) r%d = 0x%x\n", 348 BPF_SIZE(insn->code) == BPF_DW) {
348 insn->code, insn->dst_reg, insn->imm); 349 /* At this point, we already made sure that the second
350 * part of the ldimm64 insn is accessible.
351 */
352 u64 imm = ((u64)(insn + 1)->imm << 32) | (u32)insn->imm;
353 bool map_ptr = insn->src_reg == BPF_PSEUDO_MAP_FD;
354
355 if (map_ptr && !env->allow_ptr_leaks)
356 imm = 0;
357
358 verbose("(%02x) r%d = 0x%llx\n", insn->code,
359 insn->dst_reg, (unsigned long long)imm);
349 } else { 360 } else {
350 verbose("BUG_ld_%02x\n", insn->code); 361 verbose("BUG_ld_%02x\n", insn->code);
351 return; 362 return;
@@ -2674,7 +2685,7 @@ static int do_check(struct bpf_verifier_env *env)
2674 2685
2675 if (log_level) { 2686 if (log_level) {
2676 verbose("%d: ", insn_idx); 2687 verbose("%d: ", insn_idx);
2677 print_bpf_insn(insn); 2688 print_bpf_insn(env, insn);
2678 } 2689 }
2679 2690
2680 err = ext_analyzer_insn_hook(env, insn_idx, prev_insn_idx); 2691 err = ext_analyzer_insn_hook(env, insn_idx, prev_insn_idx);