All of lore.kernel.org
 help / color / mirror / Atom feed
From: Daniel Hodges <git@danielhodges.dev>
To: bpf@vger.kernel.org
Cc: linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org,
	ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org,
	martin.lau@linux.dev, eddyz87@gmail.com, memxor@gmail.com,
	song@kernel.org, yonghong.song@linux.dev, jolsa@kernel.org,
	shuah@kernel.org, git@danielhodges.dev, brho@google.com,
	hodgesd@meta.com
Subject: [PATCH 1/2] bpf: arena: fix use-after-free in VMA tracking on fork
Date: Wed, 13 May 2026 15:13:21 -0400	[thread overview]
Message-ID: <20260513191322.21319-1-git@danielhodges.dev> (raw)

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


             reply	other threads:[~2026-05-13 19:16 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-13 19:13 Daniel Hodges [this message]
2026-05-13 19:13 ` [PATCH 2/2] selftests/bpf: Add test validating arena VMA tracking across fork Daniel Hodges
2026-05-14 11:57   ` sashiko-bot
2026-05-14 11:21 ` [PATCH 1/2] bpf: arena: fix use-after-free in VMA tracking on fork sashiko-bot
     [not found] <20260513180923.628644-1-hodgesd@meta.com>
2026-05-13 19:04 ` Alexei Starovoitov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260513191322.21319-1-git@danielhodges.dev \
    --to=git@danielhodges.dev \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=brho@google.com \
    --cc=daniel@iogearbox.net \
    --cc=eddyz87@gmail.com \
    --cc=hodgesd@meta.com \
    --cc=jolsa@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=martin.lau@linux.dev \
    --cc=memxor@gmail.com \
    --cc=shuah@kernel.org \
    --cc=song@kernel.org \
    --cc=yonghong.song@linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.