]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
bpf: Free special fields when update [lru_,]percpu_hash maps
authorLeon Hwang <leon.hwang@linux.dev>
Wed, 5 Nov 2025 15:14:06 +0000 (23:14 +0800)
committerAlexei Starovoitov <ast@kernel.org>
Thu, 13 Nov 2025 17:14:15 +0000 (09:14 -0800)
As [lru_,]percpu_hash maps support BPF_KPTR_{REF,PERCPU}, missing
calls to 'bpf_obj_free_fields()' in 'pcpu_copy_value()' could cause the
memory referenced by BPF_KPTR_{REF,PERCPU} fields to be held until the
map gets freed.

Fix this by calling 'bpf_obj_free_fields()' after
'copy_map_value[,_long]()' in 'pcpu_copy_value()'.

Fixes: 65334e64a493 ("bpf: Support kptrs in percpu hashmap and percpu LRU hashmap")
Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
Acked-by: Yonghong Song <yonghong.song@linux.dev>
Link: https://lore.kernel.org/r/20251105151407.12723-2-leon.hwang@linux.dev
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
kernel/bpf/hashtab.c

index f876f09355f0d35d572ed18d3b2ce2e36d57fdb1..c8a9b27f8663bbc12559626ac995ce74911bcba9 100644 (file)
@@ -934,15 +934,21 @@ static void free_htab_elem(struct bpf_htab *htab, struct htab_elem *l)
 static void pcpu_copy_value(struct bpf_htab *htab, void __percpu *pptr,
                            void *value, bool onallcpus)
 {
+       void *ptr;
+
        if (!onallcpus) {
                /* copy true value_size bytes */
-               copy_map_value(&htab->map, this_cpu_ptr(pptr), value);
+               ptr = this_cpu_ptr(pptr);
+               copy_map_value(&htab->map, ptr, value);
+               bpf_obj_free_fields(htab->map.record, ptr);
        } else {
                u32 size = round_up(htab->map.value_size, 8);
                int off = 0, cpu;
 
                for_each_possible_cpu(cpu) {
-                       copy_map_value_long(&htab->map, per_cpu_ptr(pptr, cpu), value + off);
+                       ptr = per_cpu_ptr(pptr, cpu);
+                       copy_map_value_long(&htab->map, ptr, value + off);
+                       bpf_obj_free_fields(htab->map.record, ptr);
                        off += size;
                }
        }