Commit fe58e3dd6e119c6d41fd535429b0f1e83b5433d2

Authored by Andrii Nakryiko
Committed by Greg Kroah-Hartman
1 parent 43c390b751

bpf: Fix map leak in HASH_OF_MAPS map

[ Upstream commit 1d4e1eab456e1ee92a94987499b211db05f900ea ]

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: 8c290e60fa2a ("bpf: fix hashmap extra_elems logic")
Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Song Liu <songliubraving@fb.com>
Link: https://lore.kernel.org/bpf/20200729040913.2815687-1-andriin@fb.com
Signed-off-by: Sasha Levin <sashal@kernel.org>

Showing 1 changed file with 9 additions and 3 deletions Side-by-side Diff

kernel/bpf/hashtab.c
... ... @@ -675,16 +675,21 @@
675 675 preempt_enable();
676 676 }
677 677  
678   -static void free_htab_elem(struct bpf_htab *htab, struct htab_elem *l)
  678 +static void htab_put_fd_value(struct bpf_htab *htab, struct htab_elem *l)
679 679 {
680 680 struct bpf_map *map = &htab->map;
  681 + void *ptr;
681 682  
682 683 if (map->ops->map_fd_put_ptr) {
683   - void *ptr = fd_htab_map_get_ptr(map, l);
684   -
  684 + ptr = fd_htab_map_get_ptr(map, l);
685 685 map->ops->map_fd_put_ptr(ptr);
686 686 }
  687 +}
687 688  
  689 +static void free_htab_elem(struct bpf_htab *htab, struct htab_elem *l)
  690 +{
  691 + htab_put_fd_value(htab, l);
  692 +
688 693 if (htab_is_prealloc(htab)) {
689 694 __pcpu_freelist_push(&htab->freelist, &l->fnode);
690 695 } else {
... ... @@ -735,6 +740,7 @@
735 740 */
736 741 pl_new = this_cpu_ptr(htab->extra_elems);
737 742 l_new = *pl_new;
  743 + htab_put_fd_value(htab, old_elem);
738 744 *pl_new = old_elem;
739 745 } else {
740 746 struct pcpu_freelist_node *l;