diff options
author | Alexei Starovoitov <ast@fb.com> | 2016-06-15 21:25:38 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-06-16 02:37:54 -0400 |
commit | 19de99f70b87fcc3338da52a89c439b088cbff71 (patch) | |
tree | 43b5ff80043ee9ea62e09fe568502c9d68a188ee /include/linux/bpf.h | |
parent | e582615ad33dbd39623084a02e95567b116e1eea (diff) |
bpf: fix matching of data/data_end in verifier
The ctx structure passed into bpf programs is different depending on bpf
program type. The verifier incorrectly marked ctx->data and ctx->data_end
access based on ctx offset only. That caused loads in tracing programs
int bpf_prog(struct pt_regs *ctx) { .. ctx->ax .. }
to be incorrectly marked as PTR_TO_PACKET which later caused verifier
to reject the program that was actually valid in tracing context.
Fix this by doing program type specific matching of ctx offsets.
Fixes: 969bf05eb3ce ("bpf: direct packet access")
Reported-by: Sasha Goldshtein <goldshtn@gmail.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/linux/bpf.h')
-rw-r--r-- | include/linux/bpf.h | 28 |
1 files changed, 27 insertions, 1 deletions
diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 8ee27b8afe81..8269cafc6eb1 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h | |||
@@ -111,6 +111,31 @@ enum bpf_access_type { | |||
111 | BPF_WRITE = 2 | 111 | BPF_WRITE = 2 |
112 | }; | 112 | }; |
113 | 113 | ||
114 | /* types of values stored in eBPF registers */ | ||
115 | enum bpf_reg_type { | ||
116 | NOT_INIT = 0, /* nothing was written into register */ | ||
117 | UNKNOWN_VALUE, /* reg doesn't contain a valid pointer */ | ||
118 | PTR_TO_CTX, /* reg points to bpf_context */ | ||
119 | CONST_PTR_TO_MAP, /* reg points to struct bpf_map */ | ||
120 | PTR_TO_MAP_VALUE, /* reg points to map element value */ | ||
121 | PTR_TO_MAP_VALUE_OR_NULL,/* points to map elem value or NULL */ | ||
122 | FRAME_PTR, /* reg == frame_pointer */ | ||
123 | PTR_TO_STACK, /* reg == frame_pointer + imm */ | ||
124 | CONST_IMM, /* constant integer value */ | ||
125 | |||
126 | /* PTR_TO_PACKET represents: | ||
127 | * skb->data | ||
128 | * skb->data + imm | ||
129 | * skb->data + (u16) var | ||
130 | * skb->data + (u16) var + imm | ||
131 | * if (range > 0) then [ptr, ptr + range - off) is safe to access | ||
132 | * if (id > 0) means that some 'var' was added | ||
133 | * if (off > 0) menas that 'imm' was added | ||
134 | */ | ||
135 | PTR_TO_PACKET, | ||
136 | PTR_TO_PACKET_END, /* skb->data + headlen */ | ||
137 | }; | ||
138 | |||
114 | struct bpf_prog; | 139 | struct bpf_prog; |
115 | 140 | ||
116 | struct bpf_verifier_ops { | 141 | struct bpf_verifier_ops { |
@@ -120,7 +145,8 @@ struct bpf_verifier_ops { | |||
120 | /* return true if 'size' wide access at offset 'off' within bpf_context | 145 | /* return true if 'size' wide access at offset 'off' within bpf_context |
121 | * with 'type' (read or write) is allowed | 146 | * with 'type' (read or write) is allowed |
122 | */ | 147 | */ |
123 | bool (*is_valid_access)(int off, int size, enum bpf_access_type type); | 148 | bool (*is_valid_access)(int off, int size, enum bpf_access_type type, |
149 | enum bpf_reg_type *reg_type); | ||
124 | 150 | ||
125 | u32 (*convert_ctx_access)(enum bpf_access_type type, int dst_reg, | 151 | u32 (*convert_ctx_access)(enum bpf_access_type type, int dst_reg, |
126 | int src_reg, int ctx_off, | 152 | int src_reg, int ctx_off, |