diff options
Diffstat (limited to 'kernel/bpf/verifier.c')
-rw-r--r-- | kernel/bpf/verifier.c | 41 |
1 files changed, 7 insertions, 34 deletions
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 668e07903c8f..eec9f90ba030 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c | |||
@@ -126,31 +126,6 @@ | |||
126 | * are set to NOT_INIT to indicate that they are no longer readable. | 126 | * are set to NOT_INIT to indicate that they are no longer readable. |
127 | */ | 127 | */ |
128 | 128 | ||
129 | /* types of values stored in eBPF registers */ | ||
130 | enum bpf_reg_type { | ||
131 | NOT_INIT = 0, /* nothing was written into register */ | ||
132 | UNKNOWN_VALUE, /* reg doesn't contain a valid pointer */ | ||
133 | PTR_TO_CTX, /* reg points to bpf_context */ | ||
134 | CONST_PTR_TO_MAP, /* reg points to struct bpf_map */ | ||
135 | PTR_TO_MAP_VALUE, /* reg points to map element value */ | ||
136 | PTR_TO_MAP_VALUE_OR_NULL,/* points to map elem value or NULL */ | ||
137 | FRAME_PTR, /* reg == frame_pointer */ | ||
138 | PTR_TO_STACK, /* reg == frame_pointer + imm */ | ||
139 | CONST_IMM, /* constant integer value */ | ||
140 | |||
141 | /* PTR_TO_PACKET represents: | ||
142 | * skb->data | ||
143 | * skb->data + imm | ||
144 | * skb->data + (u16) var | ||
145 | * skb->data + (u16) var + imm | ||
146 | * if (range > 0) then [ptr, ptr + range - off) is safe to access | ||
147 | * if (id > 0) means that some 'var' was added | ||
148 | * if (off > 0) menas that 'imm' was added | ||
149 | */ | ||
150 | PTR_TO_PACKET, | ||
151 | PTR_TO_PACKET_END, /* skb->data + headlen */ | ||
152 | }; | ||
153 | |||
154 | struct reg_state { | 129 | struct reg_state { |
155 | enum bpf_reg_type type; | 130 | enum bpf_reg_type type; |
156 | union { | 131 | union { |
@@ -695,10 +670,10 @@ static int check_packet_access(struct verifier_env *env, u32 regno, int off, | |||
695 | 670 | ||
696 | /* check access to 'struct bpf_context' fields */ | 671 | /* check access to 'struct bpf_context' fields */ |
697 | static int check_ctx_access(struct verifier_env *env, int off, int size, | 672 | static int check_ctx_access(struct verifier_env *env, int off, int size, |
698 | enum bpf_access_type t) | 673 | enum bpf_access_type t, enum bpf_reg_type *reg_type) |
699 | { | 674 | { |
700 | if (env->prog->aux->ops->is_valid_access && | 675 | if (env->prog->aux->ops->is_valid_access && |
701 | env->prog->aux->ops->is_valid_access(off, size, t)) { | 676 | env->prog->aux->ops->is_valid_access(off, size, t, reg_type)) { |
702 | /* remember the offset of last byte accessed in ctx */ | 677 | /* remember the offset of last byte accessed in ctx */ |
703 | if (env->prog->aux->max_ctx_offset < off + size) | 678 | if (env->prog->aux->max_ctx_offset < off + size) |
704 | env->prog->aux->max_ctx_offset = off + size; | 679 | env->prog->aux->max_ctx_offset = off + size; |
@@ -798,21 +773,19 @@ static int check_mem_access(struct verifier_env *env, u32 regno, int off, | |||
798 | mark_reg_unknown_value(state->regs, value_regno); | 773 | mark_reg_unknown_value(state->regs, value_regno); |
799 | 774 | ||
800 | } else if (reg->type == PTR_TO_CTX) { | 775 | } else if (reg->type == PTR_TO_CTX) { |
776 | enum bpf_reg_type reg_type = UNKNOWN_VALUE; | ||
777 | |||
801 | if (t == BPF_WRITE && value_regno >= 0 && | 778 | if (t == BPF_WRITE && value_regno >= 0 && |
802 | is_pointer_value(env, value_regno)) { | 779 | is_pointer_value(env, value_regno)) { |
803 | verbose("R%d leaks addr into ctx\n", value_regno); | 780 | verbose("R%d leaks addr into ctx\n", value_regno); |
804 | return -EACCES; | 781 | return -EACCES; |
805 | } | 782 | } |
806 | err = check_ctx_access(env, off, size, t); | 783 | err = check_ctx_access(env, off, size, t, ®_type); |
807 | if (!err && t == BPF_READ && value_regno >= 0) { | 784 | if (!err && t == BPF_READ && value_regno >= 0) { |
808 | mark_reg_unknown_value(state->regs, value_regno); | 785 | mark_reg_unknown_value(state->regs, value_regno); |
809 | if (off == offsetof(struct __sk_buff, data) && | 786 | if (env->allow_ptr_leaks) |
810 | env->allow_ptr_leaks) | ||
811 | /* note that reg.[id|off|range] == 0 */ | 787 | /* note that reg.[id|off|range] == 0 */ |
812 | state->regs[value_regno].type = PTR_TO_PACKET; | 788 | state->regs[value_regno].type = reg_type; |
813 | else if (off == offsetof(struct __sk_buff, data_end) && | ||
814 | env->allow_ptr_leaks) | ||
815 | state->regs[value_regno].type = PTR_TO_PACKET_END; | ||
816 | } | 789 | } |
817 | 790 | ||
818 | } else if (reg->type == FRAME_PTR || reg->type == PTR_TO_STACK) { | 791 | } else if (reg->type == FRAME_PTR || reg->type == PTR_TO_STACK) { |