From: Yves-Alexis Perez Date: Sat, 20 Jan 2018 13:52:32 +0000 (+0100) Subject: bpf: Avoid ABI change in 4.9.77 X-Git-Tag: archive/raspbian/4.9.80-2+rpi1~8^2~3 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=87a2d201db06099181e2a81b285ab8e268b2e407;p=linux-4.9.git bpf: Avoid ABI change in 4.9.77 Commit a9bfac14cde2 "bpf: prevent out-of-bounds speculation" added one member each to struct bpf_map and struct bpf_array (which is effectively a sub-type of bpf_map). Changing the size of struct bpf_array is an ABI change, since the array contents immediately follows the structure. However, bpf_map::work is not used (or even initialised) until after the map's refcount drops to zero. We can therefore move the new members into a union with it. Based on the patch against 4.14.14 by Ben Hutchings Gbp-Pq: Topic debian Gbp-Pq: Name bpf-avoid-abi-change-in-4.9.77.patch --- diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 75ffd3b2149e..e28c535d0a53 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -43,10 +43,20 @@ struct bpf_map { u32 max_entries; u32 map_flags; u32 pages; - bool unpriv_array; + struct user_struct *user; const struct bpf_map_ops *ops; +#ifdef __GENKSYMS__ struct work_struct work; +#else + union { + struct work_struct work; + struct { + bool unpriv_array; + u32 index_mask; + }; + }; +#endif atomic_t usercnt; }; @@ -190,7 +200,6 @@ struct bpf_prog_aux { struct bpf_array { struct bpf_map map; u32 elem_size; - u32 index_mask; /* 'ownership' of prog_array is claimed by the first program that * is going to use this map or by the first program which FD is stored * in the map to make sure that all callers and callees have the same diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c index 9a1e6ed7babc..e949abb8bdd4 100644 --- a/kernel/bpf/arraymap.c +++ b/kernel/bpf/arraymap.c @@ -99,7 +99,7 @@ static struct bpf_map *array_map_alloc(union bpf_attr *attr) array = bpf_map_area_alloc(array_size); if (!array) return ERR_PTR(-ENOMEM); - array->index_mask = index_mask; + array->map.index_mask = index_mask; array->map.unpriv_array = unpriv; /* copy mandatory map attributes */ @@ -134,7 +134,7 @@ static void *array_map_lookup_elem(struct bpf_map *map, void *key) if (unlikely(index >= array->map.max_entries)) return NULL; - return array->value + array->elem_size * (index & array->index_mask); + return array->value + array->elem_size * (index & array->map.index_mask); } /* Called from eBPF program */ @@ -146,7 +146,7 @@ static void *percpu_array_map_lookup_elem(struct bpf_map *map, void *key) if (unlikely(index >= array->map.max_entries)) return NULL; - return this_cpu_ptr(array->pptrs[index & array->index_mask]); + return this_cpu_ptr(array->pptrs[index & array->map.index_mask]); } int bpf_percpu_array_copy(struct bpf_map *map, void *key, void *value) @@ -166,7 +166,7 @@ int bpf_percpu_array_copy(struct bpf_map *map, void *key, void *value) */ size = round_up(map->value_size, 8); rcu_read_lock(); - pptr = array->pptrs[index & array->index_mask]; + pptr = array->pptrs[index & array->map.index_mask]; for_each_possible_cpu(cpu) { bpf_long_memcpy(value + off, per_cpu_ptr(pptr, cpu), size); off += size; @@ -214,11 +214,11 @@ static int array_map_update_elem(struct bpf_map *map, void *key, void *value, return -EEXIST; if (array->map.map_type == BPF_MAP_TYPE_PERCPU_ARRAY) - memcpy(this_cpu_ptr(array->pptrs[index & array->index_mask]), + memcpy(this_cpu_ptr(array->pptrs[index & array->map.index_mask]), value, map->value_size); else memcpy(array->value + - array->elem_size * (index & array->index_mask), + array->elem_size * (index & array->map.index_mask), value, map->value_size); return 0; } @@ -252,7 +252,7 @@ int bpf_percpu_array_update(struct bpf_map *map, void *key, void *value, */ size = round_up(map->value_size, 8); rcu_read_lock(); - pptr = array->pptrs[index & array->index_mask]; + pptr = array->pptrs[index & array->map.index_mask]; for_each_possible_cpu(cpu) { bpf_long_memcpy(per_cpu_ptr(pptr, cpu), value + off, size); off += size; diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 076e4a0ff95e..f23dfac066b8 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -3456,9 +3456,7 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env) insn_buf[0] = BPF_JMP_IMM(BPF_JGE, BPF_REG_3, map_ptr->max_entries, 2); insn_buf[1] = BPF_ALU32_IMM(BPF_AND, BPF_REG_3, - container_of(map_ptr, - struct bpf_array, - map)->index_mask); + map_ptr->index_mask); insn_buf[2] = *insn; cnt = 3; new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);