aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/bpf
diff options
context:
space:
mode:
authorAlexei Starovoitov <ast@plumgrid.com>2015-04-15 19:19:33 -0400
committerDavid S. Miller <davem@davemloft.net>2015-04-16 14:08:49 -0400
commit725f9dcd58dedfea49ef958babf6c0bf6b7594a9 (patch)
tree01f711651a6d270186c12b2c6789e01792972e75 /kernel/bpf
parenta166151cbe33b53221c24259e4a7201064b3ba79 (diff)
bpf: fix two bugs in verification logic when accessing 'ctx' pointer
1. first bug is a silly mistake. It broke tracing examples and prevented simple bpf programs from loading. In the following code: if (insn->imm == 0 && BPF_SIZE(insn->code) == BPF_W) { } else if (...) { // this part should have been executed when // insn->code == BPF_W and insn->imm != 0 } Obviously it's not doing that. So simple instructions like: r2 = *(u64 *)(r1 + 8) will be rejected. Note the comments in the code around these branches were and still valid and indicate the true intent. Replace it with: if (BPF_SIZE(insn->code) != BPF_W) continue; if (insn->imm == 0) { } else if (...) { // now this code will be executed when // insn->code == BPF_W and insn->imm != 0 } 2. second bug is more subtle. If malicious code is using the same dest register as source register, the checks designed to prevent the same instruction to be used with different pointer types will fail to trigger, since we were assigning src_reg_type when it was already overwritten by check_mem_access(). The fix is trivial. Just move line: src_reg_type = regs[insn->src_reg].type; before check_mem_access(). Add new 'access skb fields bad4' test to check this case. Fixes: 9bac3d6d548e ("bpf: allow extended BPF programs access skb fields") Signed-off-by: Alexei Starovoitov <ast@plumgrid.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'kernel/bpf')
-rw-r--r--kernel/bpf/verifier.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 66bec36ec1ec..47dcd3aa6e23 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -1637,6 +1637,8 @@ static int do_check(struct verifier_env *env)
1637 if (err) 1637 if (err)
1638 return err; 1638 return err;
1639 1639
1640 src_reg_type = regs[insn->src_reg].type;
1641
1640 /* check that memory (src_reg + off) is readable, 1642 /* check that memory (src_reg + off) is readable,
1641 * the state of dst_reg will be updated by this func 1643 * the state of dst_reg will be updated by this func
1642 */ 1644 */
@@ -1646,9 +1648,12 @@ static int do_check(struct verifier_env *env)
1646 if (err) 1648 if (err)
1647 return err; 1649 return err;
1648 1650
1649 src_reg_type = regs[insn->src_reg].type; 1651 if (BPF_SIZE(insn->code) != BPF_W) {
1652 insn_idx++;
1653 continue;
1654 }
1650 1655
1651 if (insn->imm == 0 && BPF_SIZE(insn->code) == BPF_W) { 1656 if (insn->imm == 0) {
1652 /* saw a valid insn 1657 /* saw a valid insn
1653 * dst_reg = *(u32 *)(src_reg + off) 1658 * dst_reg = *(u32 *)(src_reg + off)
1654 * use reserved 'imm' field to mark this insn 1659 * use reserved 'imm' field to mark this insn