Skip to content

Commit fad73a1

Browse files
iamkafaidavem330
authored andcommitted
bpf: Fix and simplifications on inline map lookup
Fix in verifier: For the same bpf_map_lookup_elem() instruction (i.e. "call 1"), a broken case is "a different type of map could be used for the same lookup instruction". For example, an array in one case and a hashmap in another. We have to resort to the old dynamic call behavior in this case. The fix is to check for collision on insn_aux->map_ptr. If there is collision, don't inline the map lookup. Please see the "do_reg_lookup()" in test_map_in_map_kern.c in the later patch for how-to trigger the above case. Simplifications on array_map_gen_lookup(): 1. Calculate elem_size from map->value_size. It removes the need for 'struct bpf_array' which makes the later map-in-map implementation easier. 2. Remove the 'elem_size == 1' test Fixes: 81ed18a ("bpf: add helper inlining infra and optimize map_array lookup") Signed-off-by: Martin KaFai Lau <[email protected]> Acked-by: Alexei Starovoitov <[email protected]> Acked-by: Daniel Borkmann <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent b4f0a66 commit fad73a1

File tree

2 files changed

+15
-9
lines changed

2 files changed

+15
-9
lines changed

kernel/bpf/arraymap.c

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -117,20 +117,17 @@ static void *array_map_lookup_elem(struct bpf_map *map, void *key)
117117
/* emit BPF instructions equivalent to C code of array_map_lookup_elem() */
118118
static u32 array_map_gen_lookup(struct bpf_map *map, struct bpf_insn *insn_buf)
119119
{
120-
struct bpf_array *array = container_of(map, struct bpf_array, map);
121120
struct bpf_insn *insn = insn_buf;
122-
u32 elem_size = array->elem_size;
121+
u32 elem_size = round_up(map->value_size, 8);
123122
const int ret = BPF_REG_0;
124123
const int map_ptr = BPF_REG_1;
125124
const int index = BPF_REG_2;
126125

127126
*insn++ = BPF_ALU64_IMM(BPF_ADD, map_ptr, offsetof(struct bpf_array, value));
128127
*insn++ = BPF_LDX_MEM(BPF_W, ret, index, 0);
129-
*insn++ = BPF_JMP_IMM(BPF_JGE, ret, array->map.max_entries,
130-
elem_size == 1 ? 2 : 3);
131-
if (elem_size == 1) {
132-
/* nop */
133-
} else if (is_power_of_2(elem_size)) {
128+
*insn++ = BPF_JMP_IMM(BPF_JGE, ret, map->max_entries, 3);
129+
130+
if (is_power_of_2(elem_size)) {
134131
*insn++ = BPF_ALU64_IMM(BPF_LSH, ret, ilog2(elem_size));
135132
} else {
136133
*insn++ = BPF_ALU64_IMM(BPF_MUL, ret, elem_size);

kernel/bpf/verifier.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@ struct bpf_verifier_stack_elem {
143143
#define BPF_COMPLEXITY_LIMIT_INSNS 65536
144144
#define BPF_COMPLEXITY_LIMIT_STACK 1024
145145

146+
#define BPF_MAP_PTR_POISON ((void *)0xeB9F + POISON_POINTER_DELTA)
147+
146148
struct bpf_call_arg_meta {
147149
struct bpf_map *map_ptr;
148150
bool raw_mode;
@@ -1357,6 +1359,8 @@ static int check_call(struct bpf_verifier_env *env, int func_id, int insn_idx)
13571359
} else if (fn->ret_type == RET_VOID) {
13581360
regs[BPF_REG_0].type = NOT_INIT;
13591361
} else if (fn->ret_type == RET_PTR_TO_MAP_VALUE_OR_NULL) {
1362+
struct bpf_insn_aux_data *insn_aux;
1363+
13601364
regs[BPF_REG_0].type = PTR_TO_MAP_VALUE_OR_NULL;
13611365
regs[BPF_REG_0].max_value = regs[BPF_REG_0].min_value = 0;
13621366
/* remember map_ptr, so that check_map_access()
@@ -1369,7 +1373,11 @@ static int check_call(struct bpf_verifier_env *env, int func_id, int insn_idx)
13691373
}
13701374
regs[BPF_REG_0].map_ptr = meta.map_ptr;
13711375
regs[BPF_REG_0].id = ++env->id_gen;
1372-
env->insn_aux_data[insn_idx].map_ptr = meta.map_ptr;
1376+
insn_aux = &env->insn_aux_data[insn_idx];
1377+
if (!insn_aux->map_ptr)
1378+
insn_aux->map_ptr = meta.map_ptr;
1379+
else if (insn_aux->map_ptr != meta.map_ptr)
1380+
insn_aux->map_ptr = BPF_MAP_PTR_POISON;
13731381
} else {
13741382
verbose("unknown return type %d of func %s#%d\n",
13751383
fn->ret_type, func_id_name(func_id), func_id);
@@ -3307,7 +3315,8 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env)
33073315

33083316
if (ebpf_jit_enabled() && insn->imm == BPF_FUNC_map_lookup_elem) {
33093317
map_ptr = env->insn_aux_data[i + delta].map_ptr;
3310-
if (!map_ptr->ops->map_gen_lookup)
3318+
if (map_ptr == BPF_MAP_PTR_POISON ||
3319+
!map_ptr->ops->map_gen_lookup)
33113320
goto patch_call_imm;
33123321

33133322
cnt = map_ptr->ops->map_gen_lookup(map_ptr, insn_buf);

0 commit comments

Comments
 (0)