Skip to content

Commit 4846113

Browse files
Josef Bacikdavem330
authored andcommitted
bpf: allow access into map value arrays
Suppose you have a map array value that is something like this struct foo { unsigned iter; int array[SOME_CONSTANT]; }; You can easily insert this into an array, but you cannot modify the contents of foo->array[] after the fact. This is because we have no way to verify we won't go off the end of the array at verification time. This patch provides a start for this work. We accomplish this by keeping track of a minimum and maximum value a register could be while we're checking the code. Then at the time we try to do an access into a MAP_VALUE we verify that the maximum offset into that region is a valid access into that memory region. So in practice, code such as this unsigned index = 0; if (foo->iter >= SOME_CONSTANT) foo->iter = index; else index = foo->iter++; foo->array[index] = bar; would be allowed, as we can verify that index will always be between 0 and SOME_CONSTANT-1. If you wish to use signed values you'll have to have an extra check to make sure the index isn't less than 0, or do something like index %= SOME_CONSTANT. Signed-off-by: Josef Bacik <[email protected]> Acked-by: Alexei Starovoitov <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 7836667 commit 4846113

File tree

5 files changed

+577
-22
lines changed

5 files changed

+577
-22
lines changed

include/linux/bpf.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,13 @@ enum bpf_reg_type {
139139
*/
140140
PTR_TO_PACKET,
141141
PTR_TO_PACKET_END, /* skb->data + headlen */
142+
143+
/* PTR_TO_MAP_VALUE_ADJ is used for doing pointer math inside of a map
144+
* elem value. We only allow this if we can statically verify that
145+
* access from this register are going to fall within the size of the
146+
* map element.
147+
*/
148+
PTR_TO_MAP_VALUE_ADJ,
142149
};
143150

144151
struct bpf_prog;

include/linux/bpf_verifier.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,19 @@
1010
#include <linux/bpf.h> /* for enum bpf_reg_type */
1111
#include <linux/filter.h> /* for MAX_BPF_STACK */
1212

13+
/* Just some arbitrary values so we can safely do math without overflowing and
14+
* are obviously wrong for any sort of memory access.
15+
*/
16+
#define BPF_REGISTER_MAX_RANGE (1024 * 1024 * 1024)
17+
#define BPF_REGISTER_MIN_RANGE -(1024 * 1024 * 1024)
18+
1319
struct bpf_reg_state {
1420
enum bpf_reg_type type;
21+
/*
22+
* Used to determine if any memory access using this register will
23+
* result in a bad access.
24+
*/
25+
u64 min_value, max_value;
1526
union {
1627
/* valid when type == CONST_IMM | PTR_TO_STACK | UNKNOWN_VALUE */
1728
s64 imm;
@@ -81,6 +92,7 @@ struct bpf_verifier_env {
8192
u32 id_gen; /* used to generate unique reg IDs */
8293
bool allow_ptr_leaks;
8394
bool seen_direct_write;
95+
bool varlen_map_value_access;
8496
struct bpf_insn_aux_data *insn_aux_data; /* array of per-insn state */
8597
};
8698

0 commit comments

Comments
 (0)