]> git.ipfire.org Git - thirdparty/kernel/stable.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)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 18 Dec 2025 13:02:59 +0000 (14:02 +0100)
[ Upstream commit 6af6e49a76c9af7d42eb923703e7648cb2bf401a ]

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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
kernel/bpf/hashtab.c

index c2fcd0cd51e51b02b03b39ebfe0782d1a1b9fb5e..e7721f0776c722e07ef65a5451de1f39163a0ce0 100644 (file)
@@ -947,15 +947,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;
                }
        }