aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Gartrell <agartrell@fb.com>2015-07-23 17:24:40 -0400
committerDavid S. Miller <davem@davemloft.net>2015-07-27 03:54:10 -0400
commit24b4d2abd0bd628f396dada3e915d395cbf459eb (patch)
treeff4993b4c6f7c86b2f325d93d5c944446e5d5c61
parent6ecfdd28c8a6504349ca8501316b1ed3f639ce44 (diff)
ebpf: Allow dereferences of PTR_TO_STACK registers
mov %rsp, %r1 ; r1 = rsp add $-8, %r1 ; r1 = rsp - 8 store_q $123, -8(%rsp) ; *(u64*)r1 = 123 <- valid store_q $123, (%r1) ; *(u64*)r1 = 123 <- previously invalid mov $0, %r0 exit ; Always need to exit And we'd get the following error: 0: (bf) r1 = r10 1: (07) r1 += -8 2: (7a) *(u64 *)(r10 -8) = 999 3: (7a) *(u64 *)(r1 +0) = 999 R1 invalid mem access 'fp' Unable to load program We already know that a register is a stack address and the appropriate offset, so we should be able to validate those references as well. Signed-off-by: Alex Gartrell <agartrell@fb.com> Acked-by: Alexei Starovoitov <ast@plumgrid.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--kernel/bpf/verifier.c6
-rw-r--r--samples/bpf/test_verifier.c59
2 files changed, 64 insertions, 1 deletions
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 039d866fd36a..cd307df98cb3 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -648,6 +648,9 @@ static int check_mem_access(struct verifier_env *env, u32 regno, int off,
648 struct verifier_state *state = &env->cur_state; 648 struct verifier_state *state = &env->cur_state;
649 int size, err = 0; 649 int size, err = 0;
650 650
651 if (state->regs[regno].type == PTR_TO_STACK)
652 off += state->regs[regno].imm;
653
651 size = bpf_size_to_bytes(bpf_size); 654 size = bpf_size_to_bytes(bpf_size);
652 if (size < 0) 655 if (size < 0)
653 return size; 656 return size;
@@ -667,7 +670,8 @@ static int check_mem_access(struct verifier_env *env, u32 regno, int off,
667 if (!err && t == BPF_READ && value_regno >= 0) 670 if (!err && t == BPF_READ && value_regno >= 0)
668 mark_reg_unknown_value(state->regs, value_regno); 671 mark_reg_unknown_value(state->regs, value_regno);
669 672
670 } else if (state->regs[regno].type == FRAME_PTR) { 673 } else if (state->regs[regno].type == FRAME_PTR ||
674 state->regs[regno].type == PTR_TO_STACK) {
671 if (off >= 0 || off < -MAX_BPF_STACK) { 675 if (off >= 0 || off < -MAX_BPF_STACK) {
672 verbose("invalid stack off=%d size=%d\n", off, size); 676 verbose("invalid stack off=%d size=%d\n", off, size);
673 return -EACCES; 677 return -EACCES;
diff --git a/samples/bpf/test_verifier.c b/samples/bpf/test_verifier.c
index 693605997abc..ee0f110c9c54 100644
--- a/samples/bpf/test_verifier.c
+++ b/samples/bpf/test_verifier.c
@@ -822,6 +822,65 @@ static struct bpf_test tests[] = {
822 .result = ACCEPT, 822 .result = ACCEPT,
823 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 823 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
824 }, 824 },
825 {
826 "PTR_TO_STACK store/load",
827 .insns = {
828 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
829 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -10),
830 BPF_ST_MEM(BPF_DW, BPF_REG_1, 2, 0xfaceb00c),
831 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 2),
832 BPF_EXIT_INSN(),
833 },
834 .result = ACCEPT,
835 },
836 {
837 "PTR_TO_STACK store/load - bad alignment on off",
838 .insns = {
839 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
840 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8),
841 BPF_ST_MEM(BPF_DW, BPF_REG_1, 2, 0xfaceb00c),
842 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 2),
843 BPF_EXIT_INSN(),
844 },
845 .result = REJECT,
846 .errstr = "misaligned access off -6 size 8",
847 },
848 {
849 "PTR_TO_STACK store/load - bad alignment on reg",
850 .insns = {
851 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
852 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -10),
853 BPF_ST_MEM(BPF_DW, BPF_REG_1, 8, 0xfaceb00c),
854 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 8),
855 BPF_EXIT_INSN(),
856 },
857 .result = REJECT,
858 .errstr = "misaligned access off -2 size 8",
859 },
860 {
861 "PTR_TO_STACK store/load - out of bounds low",
862 .insns = {
863 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
864 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -80000),
865 BPF_ST_MEM(BPF_DW, BPF_REG_1, 8, 0xfaceb00c),
866 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 8),
867 BPF_EXIT_INSN(),
868 },
869 .result = REJECT,
870 .errstr = "invalid stack off=-79992 size=8",
871 },
872 {
873 "PTR_TO_STACK store/load - out of bounds high",
874 .insns = {
875 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
876 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8),
877 BPF_ST_MEM(BPF_DW, BPF_REG_1, 8, 0xfaceb00c),
878 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 8),
879 BPF_EXIT_INSN(),
880 },
881 .result = REJECT,
882 .errstr = "invalid stack off=0 size=8",
883 },
825}; 884};
826 885
827static int probe_filter_length(struct bpf_insn *fp) 886static int probe_filter_length(struct bpf_insn *fp)