[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <bed5b512-6069-53cc-f128-05be05f89889@solarflare.com>
Date: Fri, 19 May 2017 21:00:13 +0100
From: Edward Cree <ecree@...arflare.com>
To: Alexei Starovoitov <ast@...com>,
David Miller <davem@...emloft.net>,
Daniel Borkmann <daniel@...earbox.net>
CC: <alexei.starovoitov@...il.com>, <netdev@...r.kernel.org>
Subject: Alignment in BPF verifier
Well, I've managed to get somewhat confused by reg->id.
In particular, I'm unsure which bpf_reg_types can have an id, and what
exactly it means. There seems to be some code that checks around map value
pointers, which seems strange as maps have fixed sizes (and the comments in
enum bpf_reg_type make it seem like id is a PTR_TO_PACKET thing) - is this
maybe because of map-of-maps support, can the contained maps have differing
element sizes? Or do we allow *(map_value + var + imm), if map_value + var
was appropriately bounds-checked?
Does the 'id' identify the variable that was added to an object pointer, or
the object itself? Or does it blur these and identify (what the comment in
enum bpf_reg_type calls) "skb->data + (u16) var"?
Here's what I'm thinking of doing:
struct bpf_reg_state {
enum bpf_reg_type type;
union {
/* valid when type == PTR_TO_PACKET */
u16 range;
/* valid when type == CONST_PTR_TO_MAP | PTR_TO_MAP_VALUE |
* PTR_TO_MAP_VALUE_OR_NULL
*/
struct bpf_map *map_ptr;
};
/* Used to find other pointers with the same variable base, so they
* can share range and align knowledge.
*/
u32 id;
u32 off; /* fixed part of pointer offset */
/* For scalar types (CONST_IMM | UNKNOWN_VALUE), this represents our
* knowledge of the actual value.
* For pointer types, this represents the variable part of the offset
* from the pointed-to object, and is shared with all bpf_reg_states
* with the same id as us.
*/
struct tnum align;
/* Used to determine if any memory access using this register will
* result in a bad access. These two fields must be last.
* See states_equal()
* These refer to the same value as align, not necessarily the actual
* contents of the register.
*/
s64 min_value;
u64 max_value;
};
Does that sound reasonable? (And does my added comment on min/max_value
accurately describe the current semantics, or will I need to change that
as well?)
-Ed
PS. I think this approach would also mean several of the bpf_reg_types can
be folded together:
* PTR_TO_MAP_VALUE and PTR_TO_MAP_VALUE_ADJ are the same
* FRAME_PTR is just a PTR_TO_STACK with known-zero offset
* CONST_IMM is similarly a special case of UNKNOWN_VALUE
Powered by blists - more mailing lists