summaryrefslogtreecommitdiffstats
path: root/kernel/bpf/verifier.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/bpf/verifier.c')
-rw-r--r--kernel/bpf/verifier.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index a8d67d097b0d..f72f23b8fdab 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -653,6 +653,16 @@ static int check_map_access(struct verifier_env *env, u32 regno, int off,
653 653
654#define MAX_PACKET_OFF 0xffff 654#define MAX_PACKET_OFF 0xffff
655 655
656static bool may_write_pkt_data(enum bpf_prog_type type)
657{
658 switch (type) {
659 case BPF_PROG_TYPE_XDP:
660 return true;
661 default:
662 return false;
663 }
664}
665
656static int check_packet_access(struct verifier_env *env, u32 regno, int off, 666static int check_packet_access(struct verifier_env *env, u32 regno, int off,
657 int size) 667 int size)
658{ 668{
@@ -806,10 +816,15 @@ static int check_mem_access(struct verifier_env *env, u32 regno, int off,
806 err = check_stack_read(state, off, size, value_regno); 816 err = check_stack_read(state, off, size, value_regno);
807 } 817 }
808 } else if (state->regs[regno].type == PTR_TO_PACKET) { 818 } else if (state->regs[regno].type == PTR_TO_PACKET) {
809 if (t == BPF_WRITE) { 819 if (t == BPF_WRITE && !may_write_pkt_data(env->prog->type)) {
810 verbose("cannot write into packet\n"); 820 verbose("cannot write into packet\n");
811 return -EACCES; 821 return -EACCES;
812 } 822 }
823 if (t == BPF_WRITE && value_regno >= 0 &&
824 is_pointer_value(env, value_regno)) {
825 verbose("R%d leaks addr into packet\n", value_regno);
826 return -EACCES;
827 }
813 err = check_packet_access(env, regno, off, size); 828 err = check_packet_access(env, regno, off, size);
814 if (!err && t == BPF_READ && value_regno >= 0) 829 if (!err && t == BPF_READ && value_regno >= 0)
815 mark_reg_unknown_value(state->regs, value_regno); 830 mark_reg_unknown_value(state->regs, value_regno);