aboutsummaryrefslogtreecommitdiffstats
path: root/samples
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 /samples
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 'samples')
-rw-r--r--samples/bpf/test_verifier.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/samples/bpf/test_verifier.c b/samples/bpf/test_verifier.c
index 9ab645698ffb..12f3780af73f 100644
--- a/samples/bpf/test_verifier.c
+++ b/samples/bpf/test_verifier.c
@@ -721,6 +721,28 @@ static struct bpf_test tests[] = {
721 .errstr = "different pointers", 721 .errstr = "different pointers",
722 .result = REJECT, 722 .result = REJECT,
723 }, 723 },
724 {
725 "access skb fields bad4",
726 .insns = {
727 BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 3),
728 BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_1,
729 offsetof(struct __sk_buff, len)),
730 BPF_MOV64_IMM(BPF_REG_0, 0),
731 BPF_EXIT_INSN(),
732 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
733 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
734 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
735 BPF_LD_MAP_FD(BPF_REG_1, 0),
736 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
737 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
738 BPF_EXIT_INSN(),
739 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
740 BPF_JMP_IMM(BPF_JA, 0, 0, -13),
741 },
742 .fixup = {7},
743 .errstr = "different pointers",
744 .result = REJECT,
745 },
724}; 746};
725 747
726static int probe_filter_length(struct bpf_insn *fp) 748static int probe_filter_length(struct bpf_insn *fp)