aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorDaniel Borkmann <daniel@iogearbox.net>2017-05-24 19:05:06 -0400
committerDavid S. Miller <davem@davemloft.net>2017-05-25 13:44:27 -0400
commita9789ef9afcb4fb0193f8dd94f2665ba3ad71e79 (patch)
treef2709d8120df7b4368ca173096b7260625965021 /kernel
parent1ad2f5838d345e1c102bd1cd27c4f4c1349b0dc8 (diff)
bpf: properly reset caller saved regs after helper call and ld_abs/ind
Currently, after performing helper calls, we clear all caller saved registers, that is r0 - r5 and fill r0 depending on struct bpf_func_proto specification. The way we reset these regs can affect pruning decisions in later paths, since we only reset register's imm to 0 and type to NOT_INIT. However, we leave out clearing of other variables such as id, min_value, max_value, etc, which can later on lead to pruning mismatches due to stale data. Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/bpf/verifier.c37
1 files changed, 16 insertions, 21 deletions
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index e37e06b1229d..339c8a1371de 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -463,19 +463,22 @@ static const int caller_saved[CALLER_SAVED_REGS] = {
463 BPF_REG_0, BPF_REG_1, BPF_REG_2, BPF_REG_3, BPF_REG_4, BPF_REG_5 463 BPF_REG_0, BPF_REG_1, BPF_REG_2, BPF_REG_3, BPF_REG_4, BPF_REG_5
464}; 464};
465 465
466static void mark_reg_not_init(struct bpf_reg_state *regs, u32 regno)
467{
468 BUG_ON(regno >= MAX_BPF_REG);
469
470 memset(&regs[regno], 0, sizeof(regs[regno]));
471 regs[regno].type = NOT_INIT;
472 regs[regno].min_value = BPF_REGISTER_MIN_RANGE;
473 regs[regno].max_value = BPF_REGISTER_MAX_RANGE;
474}
475
466static void init_reg_state(struct bpf_reg_state *regs) 476static void init_reg_state(struct bpf_reg_state *regs)
467{ 477{
468 int i; 478 int i;
469 479
470 for (i = 0; i < MAX_BPF_REG; i++) { 480 for (i = 0; i < MAX_BPF_REG; i++)
471 regs[i].type = NOT_INIT; 481 mark_reg_not_init(regs, i);
472 regs[i].imm = 0;
473 regs[i].min_value = BPF_REGISTER_MIN_RANGE;
474 regs[i].max_value = BPF_REGISTER_MAX_RANGE;
475 regs[i].min_align = 0;
476 regs[i].aux_off = 0;
477 regs[i].aux_off_align = 0;
478 }
479 482
480 /* frame pointer */ 483 /* frame pointer */
481 regs[BPF_REG_FP].type = FRAME_PTR; 484 regs[BPF_REG_FP].type = FRAME_PTR;
@@ -1346,7 +1349,6 @@ static int check_call(struct bpf_verifier_env *env, int func_id, int insn_idx)
1346 struct bpf_verifier_state *state = &env->cur_state; 1349 struct bpf_verifier_state *state = &env->cur_state;
1347 const struct bpf_func_proto *fn = NULL; 1350 const struct bpf_func_proto *fn = NULL;
1348 struct bpf_reg_state *regs = state->regs; 1351 struct bpf_reg_state *regs = state->regs;
1349 struct bpf_reg_state *reg;
1350 struct bpf_call_arg_meta meta; 1352 struct bpf_call_arg_meta meta;
1351 bool changes_data; 1353 bool changes_data;
1352 int i, err; 1354 int i, err;
@@ -1413,11 +1415,8 @@ static int check_call(struct bpf_verifier_env *env, int func_id, int insn_idx)
1413 } 1415 }
1414 1416
1415 /* reset caller saved regs */ 1417 /* reset caller saved regs */
1416 for (i = 0; i < CALLER_SAVED_REGS; i++) { 1418 for (i = 0; i < CALLER_SAVED_REGS; i++)
1417 reg = regs + caller_saved[i]; 1419 mark_reg_not_init(regs, caller_saved[i]);
1418 reg->type = NOT_INIT;
1419 reg->imm = 0;
1420 }
1421 1420
1422 /* update return register */ 1421 /* update return register */
1423 if (fn->ret_type == RET_INTEGER) { 1422 if (fn->ret_type == RET_INTEGER) {
@@ -2445,7 +2444,6 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
2445{ 2444{
2446 struct bpf_reg_state *regs = env->cur_state.regs; 2445 struct bpf_reg_state *regs = env->cur_state.regs;
2447 u8 mode = BPF_MODE(insn->code); 2446 u8 mode = BPF_MODE(insn->code);
2448 struct bpf_reg_state *reg;
2449 int i, err; 2447 int i, err;
2450 2448
2451 if (!may_access_skb(env->prog->type)) { 2449 if (!may_access_skb(env->prog->type)) {
@@ -2478,11 +2476,8 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
2478 } 2476 }
2479 2477
2480 /* reset caller saved regs to unreadable */ 2478 /* reset caller saved regs to unreadable */
2481 for (i = 0; i < CALLER_SAVED_REGS; i++) { 2479 for (i = 0; i < CALLER_SAVED_REGS; i++)
2482 reg = regs + caller_saved[i]; 2480 mark_reg_not_init(regs, caller_saved[i]);
2483 reg->type = NOT_INIT;
2484 reg->imm = 0;
2485 }
2486 2481
2487 /* mark destination R0 register as readable, since it contains 2482 /* mark destination R0 register as readable, since it contains
2488 * the value fetched from the packet 2483 * the value fetched from the packet