diff options
| author | David S. Miller <davem@davemloft.net> | 2017-08-24 01:38:08 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2017-08-24 01:38:08 -0400 |
| commit | 81152518e985e2db22f22ca89b12169851644af6 (patch) | |
| tree | 180afe2c34f0bd7901b27138d06c6ede1d1456c5 /kernel/bpf | |
| parent | 60890e046081aef61980dbc812ac5100ad078a87 (diff) | |
| parent | 8e9cd9ce90d48369b2c5ddd79fe3d4a4cb1ccb56 (diff) | |
Merge branch 'bpf-verifier-fixes'
Edward Cree says:
====================
bpf: verifier fixes
Fix a couple of bugs introduced in my recent verifier patches.
Patch #2 does slightly increase the insn count on bpf_lxc.o, but only by
about a hundred insns (i.e. 0.2%).
v2: added test for write-marks bug (patch #1); reworded comment on
propagate_liveness() for clarity.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'kernel/bpf')
| -rw-r--r-- | kernel/bpf/verifier.c | 78 |
1 files changed, 46 insertions, 32 deletions
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index e42c096ba20d..d690c7dd1f1a 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c | |||
| @@ -832,11 +832,6 @@ static int check_map_access(struct bpf_verifier_env *env, u32 regno, | |||
| 832 | */ | 832 | */ |
| 833 | if (log_level) | 833 | if (log_level) |
| 834 | print_verifier_state(state); | 834 | print_verifier_state(state); |
| 835 | /* If the offset is variable, we will need to be stricter in state | ||
| 836 | * pruning from now on. | ||
| 837 | */ | ||
| 838 | if (!tnum_is_const(reg->var_off)) | ||
| 839 | env->varlen_map_value_access = true; | ||
| 840 | /* The minimum value is only important with signed | 835 | /* The minimum value is only important with signed |
| 841 | * comparisons where we can't assume the floor of a | 836 | * comparisons where we can't assume the floor of a |
| 842 | * value is 0. If we are using signed variables for our | 837 | * value is 0. If we are using signed variables for our |
| @@ -3247,9 +3242,8 @@ static bool check_ids(u32 old_id, u32 cur_id, struct idpair *idmap) | |||
| 3247 | } | 3242 | } |
| 3248 | 3243 | ||
| 3249 | /* Returns true if (rold safe implies rcur safe) */ | 3244 | /* Returns true if (rold safe implies rcur safe) */ |
| 3250 | static bool regsafe(struct bpf_reg_state *rold, | 3245 | static bool regsafe(struct bpf_reg_state *rold, struct bpf_reg_state *rcur, |
| 3251 | struct bpf_reg_state *rcur, | 3246 | struct idpair *idmap) |
| 3252 | bool varlen_map_access, struct idpair *idmap) | ||
| 3253 | { | 3247 | { |
| 3254 | if (!(rold->live & REG_LIVE_READ)) | 3248 | if (!(rold->live & REG_LIVE_READ)) |
| 3255 | /* explored state didn't use this */ | 3249 | /* explored state didn't use this */ |
| @@ -3281,22 +3275,14 @@ static bool regsafe(struct bpf_reg_state *rold, | |||
| 3281 | tnum_is_unknown(rold->var_off); | 3275 | tnum_is_unknown(rold->var_off); |
| 3282 | } | 3276 | } |
| 3283 | case PTR_TO_MAP_VALUE: | 3277 | case PTR_TO_MAP_VALUE: |
| 3284 | if (varlen_map_access) { | 3278 | /* If the new min/max/var_off satisfy the old ones and |
| 3285 | /* If the new min/max/var_off satisfy the old ones and | 3279 | * everything else matches, we are OK. |
| 3286 | * everything else matches, we are OK. | 3280 | * We don't care about the 'id' value, because nothing |
| 3287 | * We don't care about the 'id' value, because nothing | 3281 | * uses it for PTR_TO_MAP_VALUE (only for ..._OR_NULL) |
| 3288 | * uses it for PTR_TO_MAP_VALUE (only for ..._OR_NULL) | 3282 | */ |
| 3289 | */ | 3283 | return memcmp(rold, rcur, offsetof(struct bpf_reg_state, id)) == 0 && |
| 3290 | return memcmp(rold, rcur, offsetof(struct bpf_reg_state, id)) == 0 && | 3284 | range_within(rold, rcur) && |
| 3291 | range_within(rold, rcur) && | 3285 | tnum_in(rold->var_off, rcur->var_off); |
| 3292 | tnum_in(rold->var_off, rcur->var_off); | ||
| 3293 | } else { | ||
| 3294 | /* If the ranges/var_off were not the same, but | ||
| 3295 | * everything else was and we didn't do a variable | ||
| 3296 | * access into a map then we are a-ok. | ||
| 3297 | */ | ||
| 3298 | return memcmp(rold, rcur, offsetof(struct bpf_reg_state, id)) == 0; | ||
| 3299 | } | ||
| 3300 | case PTR_TO_MAP_VALUE_OR_NULL: | 3286 | case PTR_TO_MAP_VALUE_OR_NULL: |
| 3301 | /* a PTR_TO_MAP_VALUE could be safe to use as a | 3287 | /* a PTR_TO_MAP_VALUE could be safe to use as a |
| 3302 | * PTR_TO_MAP_VALUE_OR_NULL into the same map. | 3288 | * PTR_TO_MAP_VALUE_OR_NULL into the same map. |
| @@ -3380,7 +3366,6 @@ static bool states_equal(struct bpf_verifier_env *env, | |||
| 3380 | struct bpf_verifier_state *old, | 3366 | struct bpf_verifier_state *old, |
| 3381 | struct bpf_verifier_state *cur) | 3367 | struct bpf_verifier_state *cur) |
| 3382 | { | 3368 | { |
| 3383 | bool varlen_map_access = env->varlen_map_value_access; | ||
| 3384 | struct idpair *idmap; | 3369 | struct idpair *idmap; |
| 3385 | bool ret = false; | 3370 | bool ret = false; |
| 3386 | int i; | 3371 | int i; |
| @@ -3391,8 +3376,7 @@ static bool states_equal(struct bpf_verifier_env *env, | |||
| 3391 | return false; | 3376 | return false; |
| 3392 | 3377 | ||
| 3393 | for (i = 0; i < MAX_BPF_REG; i++) { | 3378 | for (i = 0; i < MAX_BPF_REG; i++) { |
| 3394 | if (!regsafe(&old->regs[i], &cur->regs[i], varlen_map_access, | 3379 | if (!regsafe(&old->regs[i], &cur->regs[i], idmap)) |
| 3395 | idmap)) | ||
| 3396 | goto out_free; | 3380 | goto out_free; |
| 3397 | } | 3381 | } |
| 3398 | 3382 | ||
| @@ -3412,7 +3396,7 @@ static bool states_equal(struct bpf_verifier_env *env, | |||
| 3412 | continue; | 3396 | continue; |
| 3413 | if (!regsafe(&old->spilled_regs[i / BPF_REG_SIZE], | 3397 | if (!regsafe(&old->spilled_regs[i / BPF_REG_SIZE], |
| 3414 | &cur->spilled_regs[i / BPF_REG_SIZE], | 3398 | &cur->spilled_regs[i / BPF_REG_SIZE], |
| 3415 | varlen_map_access, idmap)) | 3399 | idmap)) |
| 3416 | /* when explored and current stack slot are both storing | 3400 | /* when explored and current stack slot are both storing |
| 3417 | * spilled registers, check that stored pointers types | 3401 | * spilled registers, check that stored pointers types |
| 3418 | * are the same as well. | 3402 | * are the same as well. |
| @@ -3433,9 +3417,16 @@ out_free: | |||
| 3433 | return ret; | 3417 | return ret; |
| 3434 | } | 3418 | } |
| 3435 | 3419 | ||
| 3420 | /* A write screens off any subsequent reads; but write marks come from the | ||
| 3421 | * straight-line code between a state and its parent. When we arrive at a | ||
| 3422 | * jump target (in the first iteration of the propagate_liveness() loop), | ||
| 3423 | * we didn't arrive by the straight-line code, so read marks in state must | ||
| 3424 | * propagate to parent regardless of state's write marks. | ||
| 3425 | */ | ||
| 3436 | static bool do_propagate_liveness(const struct bpf_verifier_state *state, | 3426 | static bool do_propagate_liveness(const struct bpf_verifier_state *state, |
| 3437 | struct bpf_verifier_state *parent) | 3427 | struct bpf_verifier_state *parent) |
| 3438 | { | 3428 | { |
| 3429 | bool writes = parent == state->parent; /* Observe write marks */ | ||
| 3439 | bool touched = false; /* any changes made? */ | 3430 | bool touched = false; /* any changes made? */ |
| 3440 | int i; | 3431 | int i; |
| 3441 | 3432 | ||
| @@ -3447,7 +3438,9 @@ static bool do_propagate_liveness(const struct bpf_verifier_state *state, | |||
| 3447 | for (i = 0; i < BPF_REG_FP; i++) { | 3438 | for (i = 0; i < BPF_REG_FP; i++) { |
| 3448 | if (parent->regs[i].live & REG_LIVE_READ) | 3439 | if (parent->regs[i].live & REG_LIVE_READ) |
| 3449 | continue; | 3440 | continue; |
| 3450 | if (state->regs[i].live == REG_LIVE_READ) { | 3441 | if (writes && (state->regs[i].live & REG_LIVE_WRITTEN)) |
| 3442 | continue; | ||
| 3443 | if (state->regs[i].live & REG_LIVE_READ) { | ||
| 3451 | parent->regs[i].live |= REG_LIVE_READ; | 3444 | parent->regs[i].live |= REG_LIVE_READ; |
| 3452 | touched = true; | 3445 | touched = true; |
| 3453 | } | 3446 | } |
| @@ -3460,7 +3453,9 @@ static bool do_propagate_liveness(const struct bpf_verifier_state *state, | |||
| 3460 | continue; | 3453 | continue; |
| 3461 | if (parent->spilled_regs[i].live & REG_LIVE_READ) | 3454 | if (parent->spilled_regs[i].live & REG_LIVE_READ) |
| 3462 | continue; | 3455 | continue; |
| 3463 | if (state->spilled_regs[i].live == REG_LIVE_READ) { | 3456 | if (writes && (state->spilled_regs[i].live & REG_LIVE_WRITTEN)) |
| 3457 | continue; | ||
| 3458 | if (state->spilled_regs[i].live & REG_LIVE_READ) { | ||
| 3464 | parent->spilled_regs[i].live |= REG_LIVE_READ; | 3459 | parent->spilled_regs[i].live |= REG_LIVE_READ; |
| 3465 | touched = true; | 3460 | touched = true; |
| 3466 | } | 3461 | } |
| @@ -3468,6 +3463,15 @@ static bool do_propagate_liveness(const struct bpf_verifier_state *state, | |||
| 3468 | return touched; | 3463 | return touched; |
| 3469 | } | 3464 | } |
| 3470 | 3465 | ||
| 3466 | /* "parent" is "a state from which we reach the current state", but initially | ||
| 3467 | * it is not the state->parent (i.e. "the state whose straight-line code leads | ||
| 3468 | * to the current state"), instead it is the state that happened to arrive at | ||
| 3469 | * a (prunable) equivalent of the current state. See comment above | ||
| 3470 | * do_propagate_liveness() for consequences of this. | ||
| 3471 | * This function is just a more efficient way of calling mark_reg_read() or | ||
| 3472 | * mark_stack_slot_read() on each reg in "parent" that is read in "state", | ||
| 3473 | * though it requires that parent != state->parent in the call arguments. | ||
| 3474 | */ | ||
| 3471 | static void propagate_liveness(const struct bpf_verifier_state *state, | 3475 | static void propagate_liveness(const struct bpf_verifier_state *state, |
| 3472 | struct bpf_verifier_state *parent) | 3476 | struct bpf_verifier_state *parent) |
| 3473 | { | 3477 | { |
| @@ -3496,6 +3500,12 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx) | |||
| 3496 | /* reached equivalent register/stack state, | 3500 | /* reached equivalent register/stack state, |
| 3497 | * prune the search. | 3501 | * prune the search. |
| 3498 | * Registers read by the continuation are read by us. | 3502 | * Registers read by the continuation are read by us. |
| 3503 | * If we have any write marks in env->cur_state, they | ||
| 3504 | * will prevent corresponding reads in the continuation | ||
| 3505 | * from reaching our parent (an explored_state). Our | ||
| 3506 | * own state will get the read marks recorded, but | ||
| 3507 | * they'll be immediately forgotten as we're pruning | ||
| 3508 | * this state and will pop a new one. | ||
| 3499 | */ | 3509 | */ |
| 3500 | propagate_liveness(&sl->state, &env->cur_state); | 3510 | propagate_liveness(&sl->state, &env->cur_state); |
| 3501 | return 1; | 3511 | return 1; |
| @@ -3519,7 +3529,12 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx) | |||
| 3519 | env->explored_states[insn_idx] = new_sl; | 3529 | env->explored_states[insn_idx] = new_sl; |
| 3520 | /* connect new state to parentage chain */ | 3530 | /* connect new state to parentage chain */ |
| 3521 | env->cur_state.parent = &new_sl->state; | 3531 | env->cur_state.parent = &new_sl->state; |
| 3522 | /* clear liveness marks in current state */ | 3532 | /* clear write marks in current state: the writes we did are not writes |
| 3533 | * our child did, so they don't screen off its reads from us. | ||
| 3534 | * (There are no read marks in current state, because reads always mark | ||
| 3535 | * their parent and current state never has children yet. Only | ||
| 3536 | * explored_states can get read marks.) | ||
| 3537 | */ | ||
| 3523 | for (i = 0; i < BPF_REG_FP; i++) | 3538 | for (i = 0; i < BPF_REG_FP; i++) |
| 3524 | env->cur_state.regs[i].live = REG_LIVE_NONE; | 3539 | env->cur_state.regs[i].live = REG_LIVE_NONE; |
| 3525 | for (i = 0; i < MAX_BPF_STACK / BPF_REG_SIZE; i++) | 3540 | for (i = 0; i < MAX_BPF_STACK / BPF_REG_SIZE; i++) |
| @@ -3550,7 +3565,6 @@ static int do_check(struct bpf_verifier_env *env) | |||
| 3550 | init_reg_state(regs); | 3565 | init_reg_state(regs); |
| 3551 | state->parent = NULL; | 3566 | state->parent = NULL; |
| 3552 | insn_idx = 0; | 3567 | insn_idx = 0; |
| 3553 | env->varlen_map_value_access = false; | ||
| 3554 | for (;;) { | 3568 | for (;;) { |
| 3555 | struct bpf_insn *insn; | 3569 | struct bpf_insn *insn; |
| 3556 | u8 class; | 3570 | u8 class; |
