Commit 1d4e1eab authored by Andrii Nakryiko's avatar Andrii Nakryiko Committed by Daniel Borkmann

bpf: Fix map leak in HASH_OF_MAPS map

Fix HASH_OF_MAPS bug of not putting inner map pointer on bpf_map_elem_update()
operation. This is due to per-cpu extra_elems optimization, which bypassed
free_htab_elem() logic doing proper clean ups. Make sure that inner map is put
properly in optimized case as well.

Fixes: 8c290e60 ("bpf: fix hashmap extra_elems logic")
Signed-off-by: default avatarAndrii Nakryiko <andriin@fb.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Acked-by: default avatarSong Liu <songliubraving@fb.com>
Link: https://lore.kernel.org/bpf/20200729040913.2815687-1-andriin@fb.com
parent 5b801dfb
...@@ -779,15 +779,20 @@ static void htab_elem_free_rcu(struct rcu_head *head) ...@@ -779,15 +779,20 @@ static void htab_elem_free_rcu(struct rcu_head *head)
htab_elem_free(htab, l); htab_elem_free(htab, l);
} }
static void free_htab_elem(struct bpf_htab *htab, struct htab_elem *l) static void htab_put_fd_value(struct bpf_htab *htab, struct htab_elem *l)
{ {
struct bpf_map *map = &htab->map; struct bpf_map *map = &htab->map;
void *ptr;
if (map->ops->map_fd_put_ptr) { if (map->ops->map_fd_put_ptr) {
void *ptr = fd_htab_map_get_ptr(map, l); ptr = fd_htab_map_get_ptr(map, l);
map->ops->map_fd_put_ptr(ptr); map->ops->map_fd_put_ptr(ptr);
} }
}
static void free_htab_elem(struct bpf_htab *htab, struct htab_elem *l)
{
htab_put_fd_value(htab, l);
if (htab_is_prealloc(htab)) { if (htab_is_prealloc(htab)) {
__pcpu_freelist_push(&htab->freelist, &l->fnode); __pcpu_freelist_push(&htab->freelist, &l->fnode);
...@@ -839,6 +844,7 @@ static struct htab_elem *alloc_htab_elem(struct bpf_htab *htab, void *key, ...@@ -839,6 +844,7 @@ static struct htab_elem *alloc_htab_elem(struct bpf_htab *htab, void *key,
*/ */
pl_new = this_cpu_ptr(htab->extra_elems); pl_new = this_cpu_ptr(htab->extra_elems);
l_new = *pl_new; l_new = *pl_new;
htab_put_fd_value(htab, old_elem);
*pl_new = old_elem; *pl_new = old_elem;
} else { } else {
struct pcpu_freelist_node *l; struct pcpu_freelist_node *l;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment