The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH 1/2] bpf: arena: fix use-after-free in VMA tracking on fork
@ 2026-05-13 19:13 Daniel Hodges
  2026-05-13 19:13 ` [PATCH 2/2] selftests/bpf: Add test validating arena VMA tracking across fork Daniel Hodges
  0 siblings, 1 reply; 2+ messages in thread
From: Daniel Hodges @ 2026-05-13 19:13 UTC (permalink / raw)
  To: bpf
  Cc: linux-kselftest, linux-kernel, ast, daniel, andrii, martin.lau,
	eddyz87, memxor, song, yonghong.song, jolsa, shuah, git, brho,
	hodgesd

arena_vm_open() only increments a refcount on the existing vma_list
entry without creating a new entry for the child's VMA. After fork,
vml->vma still points to the parent's VMA. When the parent unmaps
(arena_vm_close decrements refcount but doesn't remove the entry),
vml->vma becomes a dangling pointer. A subsequent bpf_arena_free_pages
call reaches zap_pages() which dereferences the freed VMA via
zap_vma_range(vml->vma, ...), causing a use-after-free:

  BUG: KASAN: slab-use-after-free in zap_vma_range+0xf2/0x100
  Read of size 8 at addr ff11000113ec9b10 by task test_progs/198
  Call Trace:
   zap_vma_range+0xf2/0x100
   arena_free_pages+0x6de/0x970
   bpf_prog_a2b540a82b1066f3_arena_free+0x8b/0xb6
   bpf_prog_test_run_syscall+0x3d3/0x8a0

The same issue is triggered by __split_vma (partial munmap) and
copy_vma (mremap), both of which call vm_ops->open.

Fix this by giving each VMA its own vma_list entry instead of sharing
one with a refcount. arena_vm_open now allocates a new entry for the
new VMA, and arena_vm_close always removes and frees its own entry.
If the allocation fails in arena_vm_open, vm_private_data is set to
NULL and arena_vm_close handles this gracefully, meaning the VMA
simply won't be zapped during arena page frees.

Fixes: 317460317a02 ("bpf: Introduce bpf_arena.")
Signed-off-by: Daniel Hodges <git@danielhodges.dev>
Assisted-by: Claude-Code:claude-opus-4-6
---
 kernel/bpf/arena.c | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/kernel/bpf/arena.c b/kernel/bpf/arena.c
index 49a8f7b1beef..a3c46100dd12 100644
--- a/kernel/bpf/arena.c
+++ b/kernel/bpf/arena.c
@@ -317,7 +317,6 @@ static u64 arena_map_mem_usage(const struct bpf_map *map)
 struct vma_list {
 	struct vm_area_struct *vma;
 	struct list_head head;
-	refcount_t mmap_count;
 };
 
 static int remember_vma(struct bpf_arena *arena, struct vm_area_struct *vma)
@@ -327,7 +326,6 @@ static int remember_vma(struct bpf_arena *arena, struct vm_area_struct *vma)
 	vml = kmalloc_obj(*vml);
 	if (!vml)
 		return -ENOMEM;
-	refcount_set(&vml->mmap_count, 1);
 	vma->vm_private_data = vml;
 	vml->vma = vma;
 	list_add(&vml->head, &arena->vma_list);
@@ -336,9 +334,19 @@ static int remember_vma(struct bpf_arena *arena, struct vm_area_struct *vma)
 
 static void arena_vm_open(struct vm_area_struct *vma)
 {
-	struct vma_list *vml = vma->vm_private_data;
+	struct bpf_map *map = vma->vm_file->private_data;
+	struct bpf_arena *arena = container_of(map, struct bpf_arena, map);
+	struct vma_list *vml;
 
-	refcount_inc(&vml->mmap_count);
+	vml = kmalloc_obj(*vml);
+	if (!vml) {
+		vma->vm_private_data = NULL;
+		return;
+	}
+	vml->vma = vma;
+	vma->vm_private_data = vml;
+	guard(mutex)(&arena->lock);
+	list_add(&vml->head, &arena->vma_list);
 }
 
 static int arena_vm_may_split(struct vm_area_struct *vma, unsigned long addr)
@@ -357,10 +365,9 @@ static void arena_vm_close(struct vm_area_struct *vma)
 	struct bpf_arena *arena = container_of(map, struct bpf_arena, map);
 	struct vma_list *vml = vma->vm_private_data;
 
-	if (!refcount_dec_and_test(&vml->mmap_count))
+	if (!vml)
 		return;
 	guard(mutex)(&arena->lock);
-	/* update link list under lock */
 	list_del(&vml->head);
 	vma->vm_private_data = NULL;
 	kfree(vml);
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-05-13 19:16 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-13 19:13 [PATCH 1/2] bpf: arena: fix use-after-free in VMA tracking on fork Daniel Hodges
2026-05-13 19:13 ` [PATCH 2/2] selftests/bpf: Add test validating arena VMA tracking across fork Daniel Hodges

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox