mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-06-17 20:25:19 +00:00
bpf: don't trigger OOM killer under pressure with map alloc
This patch adds two helpers, bpf_map_area_alloc() and bpf_map_area_free(), that are to be used for map allocations. Using kmalloc() for very large allocations can cause excessive work within the page allocator, so i) fall back earlier to vmalloc() when the attempt is considered costly anyway, and even more importantly ii) don't trigger OOM killer with any of the allocators. Since this is based on a user space request, for example, when creating maps with element pre-allocation, we really want such requests to fail instead of killing other user space processes. Also, don't spam the kernel log with warnings should any of the allocations fail under pressure. Given that, we can make backend selection in bpf_map_area_alloc() generic, and convert all maps over to use this API for spots with potentially large allocation requests. Note, replacing the one kmalloc_array() is fine as overflow checks happen earlier in htab_map_alloc(), since it must also protect the multiplication for vmalloc() should kmalloc_array() fail. Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
9ed59592e3
commit
d407bd25a2
5 changed files with 52 additions and 36 deletions
|
@ -11,7 +11,6 @@
|
|||
*/
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/filter.h>
|
||||
|
@ -74,14 +73,10 @@ static struct bpf_map *array_map_alloc(union bpf_attr *attr)
|
|||
if (array_size >= U32_MAX - PAGE_SIZE)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
|
||||
/* allocate all map elements and zero-initialize them */
|
||||
array = kzalloc(array_size, GFP_USER | __GFP_NOWARN);
|
||||
if (!array) {
|
||||
array = vzalloc(array_size);
|
||||
if (!array)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
array = bpf_map_area_alloc(array_size);
|
||||
if (!array)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
/* copy mandatory map attributes */
|
||||
array->map.map_type = attr->map_type;
|
||||
|
@ -97,7 +92,7 @@ static struct bpf_map *array_map_alloc(union bpf_attr *attr)
|
|||
|
||||
if (array_size >= U32_MAX - PAGE_SIZE ||
|
||||
elem_size > PCPU_MIN_UNIT_SIZE || bpf_array_alloc_percpu(array)) {
|
||||
kvfree(array);
|
||||
bpf_map_area_free(array);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
out:
|
||||
|
@ -262,7 +257,7 @@ static void array_map_free(struct bpf_map *map)
|
|||
if (array->map.map_type == BPF_MAP_TYPE_PERCPU_ARRAY)
|
||||
bpf_array_free_percpu(array);
|
||||
|
||||
kvfree(array);
|
||||
bpf_map_area_free(array);
|
||||
}
|
||||
|
||||
static const struct bpf_map_ops array_ops = {
|
||||
|
@ -319,7 +314,8 @@ static void fd_array_map_free(struct bpf_map *map)
|
|||
/* make sure it's empty */
|
||||
for (i = 0; i < array->map.max_entries; i++)
|
||||
BUG_ON(array->ptrs[i] != NULL);
|
||||
kvfree(array);
|
||||
|
||||
bpf_map_area_free(array);
|
||||
}
|
||||
|
||||
static void *fd_array_map_lookup_elem(struct bpf_map *map, void *key)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue