Skip to content

Commit b34ffb0

Browse files
aspskMartin KaFai Lau
authored andcommitted
bpf: fix a memory leak in the LRU and LRU_PERCPU hash maps
The LRU and LRU_PERCPU maps allocate a new element on update before locking the target hash table bucket. Right after that the maps try to lock the bucket. If this fails, then maps return -EBUSY to the caller without releasing the allocated element. This makes the element untracked: it doesn't belong to either of free lists, and it doesn't belong to the hash table, so can't be re-used; this eventually leads to the permanent -ENOMEM on LRU map updates, which is unexpected. Fix this by returning the element to the local free list if bucket locking fails. Fixes: 20b6cc3 ("bpf: Avoid hashtab deadlock with map_locked") Signed-off-by: Anton Protopopov <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Martin KaFai Lau <[email protected]>
1 parent 0613d8c commit b34ffb0

File tree

1 file changed

+4
-2
lines changed

1 file changed

+4
-2
lines changed

kernel/bpf/hashtab.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1215,7 +1215,7 @@ static long htab_lru_map_update_elem(struct bpf_map *map, void *key, void *value
12151215

12161216
ret = htab_lock_bucket(htab, b, hash, &flags);
12171217
if (ret)
1218-
return ret;
1218+
goto err_lock_bucket;
12191219

12201220
l_old = lookup_elem_raw(head, hash, key, key_size);
12211221

@@ -1236,6 +1236,7 @@ static long htab_lru_map_update_elem(struct bpf_map *map, void *key, void *value
12361236
err:
12371237
htab_unlock_bucket(htab, b, hash, flags);
12381238

1239+
err_lock_bucket:
12391240
if (ret)
12401241
htab_lru_push_free(htab, l_new);
12411242
else if (l_old)
@@ -1338,7 +1339,7 @@ static long __htab_lru_percpu_map_update_elem(struct bpf_map *map, void *key,
13381339

13391340
ret = htab_lock_bucket(htab, b, hash, &flags);
13401341
if (ret)
1341-
return ret;
1342+
goto err_lock_bucket;
13421343

13431344
l_old = lookup_elem_raw(head, hash, key, key_size);
13441345

@@ -1361,6 +1362,7 @@ static long __htab_lru_percpu_map_update_elem(struct bpf_map *map, void *key,
13611362
ret = 0;
13621363
err:
13631364
htab_unlock_bucket(htab, b, hash, flags);
1365+
err_lock_bucket:
13641366
if (l_new)
13651367
bpf_lru_push_free(&htab->lru, &l_new->lru_node);
13661368
return ret;

0 commit comments

Comments
 (0)