From nobody Mon Jun 15 15:06:14 2026 Received: from mail-dl1-f42.google.com (mail-dl1-f42.google.com [74.125.82.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A130126A0C7 for ; Sun, 12 Apr 2026 02:27:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775960853; cv=none; b=lBSylej0BIi8bWJ6INZo5SoLjpgFo++Lh63EwVOzwhxTzY9W0oyCXKCQPtZam9vdNmVOAOSz/GfgcCk9JrTSOVQGaib1nKjvGLl+Ul1a1BJOFhYQXTfIqgcNowCQA/V8Dxo2bHVmwWNCCOGwuIwFEN/cKtoquyVE5evK31nOwNo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775960853; c=relaxed/simple; bh=EVadKMzdyA05JwtqvG0eCVx3p4RsAmYyt8IXqFx0U7M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=QJGkxaEs9AzXHXXHe5A4nqdm6L5nXXb0Hg5wi0Vn5JckvtS+Xw8lFkfDNApYsH1Y7H+91Qh3lbi6hjVsZdqGKIs1Vqhvl9cUCz3dNv+6r4OqXvMFbFFLKKTqe3aRXSYsM9FOqliXfYByH6ILXgrGHHWcQIUdwUa6OmqeKPaOb5M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Ja/zMrUG; arc=none smtp.client-ip=74.125.82.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Ja/zMrUG" Received: by mail-dl1-f42.google.com with SMTP id a92af1059eb24-12c3d30564eso1541243c88.1 for ; Sat, 11 Apr 2026 19:27:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1775960852; x=1776565652; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=cRb3JIVlYGaiJeVlo7rnOgfaUPADTGIibb+C/7j3e0o=; b=Ja/zMrUGPAaJEV9INF4DkPX9Y5D4oWr67Wa2ZCMfxa0QgyIRc7a4YbK5wI39Fe4egX tuM6U0KTma6EFpJKfMQ9KbIVTS+CITNibiJjwmz/lmZrj2ZudDAAKRiosiONhSRUbUDo qWeJMpyN1d/dOiI48mO6b847Ai2KGHJCpYVTpKBW6wOg1k890ZM8r9gg8IjIM+aZQlyS QPIw+HeqZlvdNW+wJJWpHx0H6rK/CulhjCrL7L475T7PBdSGlxnHBrScOhq5BwEXfxQC mxsJC1CcTcznU8A01skckbNKaz+7BvbBFVAyPV0kncRHXAkAMsnZT4JHBn15JmivKgIX 400A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775960852; x=1776565652; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=cRb3JIVlYGaiJeVlo7rnOgfaUPADTGIibb+C/7j3e0o=; b=f7VbSsmsrBTiABsPxpZlU3kuL5WdO6YDiOuhD/E3rfj9VmeYGoXv7hkGNGE9mXv+bM 10DjEs7zGHhexUIqWtM+LJXeH7NUuGfGWmcYE5LVbysYRpmKPT8Swh5c7WcETUELGc+7 sg4GwaImnsnM6fdW1+UY7ui7DL7k2WozSW8TmldBjLhE6khLOBEurh2mloqkofQVbuME kt8XcHC+S19Ee6RB/VAZJPA1iUhv2sI/sDk7OzrlqWeiJB3D8lrCQDCYeYCm3wLyxS1X DRgzEN2dHtTzGa5r2ALRu1JNEh6Br5xgwQcE4yErB3Oi22ZcPK83n/SIRA62RzgDXJTt eY1A== X-Forwarded-Encrypted: i=1; AJvYcCVaGowPajxYhNrkAJ/pC8zxtWFAzObJ8UzN3Oq5ibb6CEofIwAfqFvqn0CZ8yylKgWrW1sO6c64GMJdm08=@vger.kernel.org X-Gm-Message-State: AOJu0YzOuD9SELN+G0+rwRmvcBNViTeCK2Akv5IpoogJMsEAFKlzFKED 8MLgI6Sm6k9iSGmCt0EbThdGkeQM+oWwjoEHp4uFKZ/ZrmFNWVDzVc41 X-Gm-Gg: AeBDieuEz0c0+QXs6qjug0vESrCtpsJvB4LQhhy3UqUcl8z8p4DB9lm7sHz+iLga8tT ag7WQQihwg8w33HbweYvOCxmbdBnbZDVbRoAdPGC9j58yjMANQMyJLNqNgqbNWUoZd0NgCaIwsx 0Y68rYYnoNrqfDsRPSfWe0fFPV/Sns4rltfwDaDOD6KmIFzzH8+yl1k6H7G0/lhwQm/o3BkYafn 62m+k5M7b1RQCYliLoRhTLeItb9smF1rj2mMdVMcRiQjEFgasDm44t0hCGLCGYc1X014xQCQwjO PVxOryN5UpqMEu4h3OFmtD3fclHJqB+15NZFfI7ajSrbkRGA8JZqcKzdSeAfg1FXHYBiCoGOp+D wSNLSexmuPIRFqIKns/c09C8I73hfEeuhnG2ex3zwg7t8rlEoQf6AlRXfowtlHUJvhpMvGLT6hk DXEdWtjq+9v2+2A0mOo6aehG2E2fhpM6O+PMiUq4f7uN9YgEP1TgJlECRWOrwMT+H6QkxVlYfFW SahZIPCmg== X-Received: by 2002:a05:7022:6282:b0:12a:796b:7cf1 with SMTP id a92af1059eb24-12c34edb8f8mr5438349c88.23.1775960851712; Sat, 11 Apr 2026 19:27:31 -0700 (PDT) Received: from efaec68ba852.tailc0aff1.ts.net ([206.206.192.132]) by smtp.gmail.com with ESMTPSA id a92af1059eb24-12c34352490sm8757860c88.0.2026.04.11.19.27.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 11 Apr 2026 19:27:31 -0700 (PDT) From: Weiming Shi To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko Cc: Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Barret Rhoden , Emil Tsalapatis , bpf@vger.kernel.org, linux-kernel@vger.kernel.org, Xiang Mei , Weiming Shi Subject: [PATCH bpf v4 1/2] bpf: Fix use-after-free of arena VMA on fork Date: Sat, 11 Apr 2026 19:27:14 -0700 Message-ID: <20260412022714.1955495-3-bestswngs@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260412022714.1955495-2-bestswngs@gmail.com> References: <20260412022714.1955495-2-bestswngs@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" arena_vm_open() only increments a refcount on the shared vma_list entry but never registers the new VMA or updates the stored vma pointer. When the original VMA is unmapped while a forked copy still exists, arena_vm_close() drops the refcount without freeing the vma_list entry. The entry's vma pointer now refers to a freed vm_area_struct. A subsequent bpf_arena_free_pages() call iterates vma_list and passes the dangling pointer to zap_page_range_single(), causing a use-after-free. The bug is reachable by any process with CAP_BPF and CAP_PERFMON that can create a BPF_MAP_TYPE_ARENA, mmap it, and fork. It triggers deterministically -- no race condition is involved. BUG: KASAN: slab-use-after-free in zap_page_range_single (mm/memory.c:2234) Call Trace: zap_page_range_single+0x101/0x110 mm/memory.c:2234 zap_pages+0x80/0xf0 kernel/bpf/arena.c:658 arena_free_pages+0x67a/0x860 kernel/bpf/arena.c:712 bpf_prog_test_run_syscall+0x3da net/bpf/test_run.c:1640 __sys_bpf+0x1662/0x50b0 kernel/bpf/syscall.c:6267 __x64_sys_bpf+0x73/0xb0 kernel/bpf/syscall.c:6360 do_syscall_64+0xf1/0x530 arch/x86/entry/syscall_64.c:63 entry_SYSCALL_64_after_hwframe+0x77 arch/x86/entry/entry_64.S:130 Fix this by tracking each child VMA separately. arena_vm_open() now clears the inherited vm_private_data and calls remember_vma() to register a fresh vma_list entry for the new VMA. If remember_vma() fails due to OOM, vm_private_data stays NULL and arena_vm_close() skips the cleanup for that VMA. The shared refcount is no longer needed and is removed. Also add arena_vm_may_split() returning -EINVAL to prevent VMA splitting, so that arena_vm_open() only needs to handle fork and the vma_list tracking stays simple. Fixes: b90d77e5fd78 ("bpf: Fix remap of arena.") Reported-by: Xiang Mei Signed-off-by: Weiming Shi --- kernel/bpf/arena.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/kernel/bpf/arena.c b/kernel/bpf/arena.c index f355cf1c1a16..3462c4463617 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 *ma= p) struct vma_list { struct vm_area_struct *vma; struct list_head head; - refcount_t mmap_count; }; =20 static int remember_vma(struct bpf_arena *arena, struct vm_area_struct *vm= a) @@ -327,7 +326,6 @@ static int remember_vma(struct bpf_arena *arena, struct= vm_area_struct *vma) vml =3D kmalloc_obj(*vml); if (!vml) return -ENOMEM; - refcount_set(&vml->mmap_count, 1); vma->vm_private_data =3D vml; vml->vma =3D vma; list_add(&vml->head, &arena->vma_list); @@ -336,9 +334,17 @@ static int remember_vma(struct bpf_arena *arena, struc= t vm_area_struct *vma) =20 static void arena_vm_open(struct vm_area_struct *vma) { - struct vma_list *vml =3D vma->vm_private_data; + struct bpf_map *map =3D vma->vm_file->private_data; + struct bpf_arena *arena =3D container_of(map, struct bpf_arena, map); =20 - refcount_inc(&vml->mmap_count); + /* + * vm_private_data points to the parent's vma_list entry after fork. + * Clear it and register this VMA separately. + */ + vma->vm_private_data =3D NULL; + guard(mutex)(&arena->lock); + /* OOM is silently ignored; arena_vm_close() handles NULL. */ + remember_vma(arena, vma); } =20 static void arena_vm_close(struct vm_area_struct *vma) @@ -347,10 +353,9 @@ static void arena_vm_close(struct vm_area_struct *vma) struct bpf_arena *arena =3D container_of(map, struct bpf_arena, map); struct vma_list *vml =3D vma->vm_private_data; =20 - 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 =3D NULL; kfree(vml); @@ -415,9 +420,15 @@ static vm_fault_t arena_vm_fault(struct vm_fault *vmf) return VM_FAULT_SIGSEGV; } =20 +static int arena_vm_may_split(struct vm_area_struct *vma, unsigned long ad= dr) +{ + return -EINVAL; +} + static const struct vm_operations_struct arena_vm_ops =3D { .open =3D arena_vm_open, .close =3D arena_vm_close, + .may_split =3D arena_vm_may_split, .fault =3D arena_vm_fault, }; =20 --=20 2.43.0 From nobody Mon Jun 15 15:06:14 2026 Received: from mail-dl1-f41.google.com (mail-dl1-f41.google.com [74.125.82.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D3E1C31E106 for ; Sun, 12 Apr 2026 02:27:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775960855; cv=none; b=Kk2pHdsVCbY0g3U08gbjCYqjfCnMvxnd3GCJmt7R6NThZBn+WoY6he+tLX5vGGDO9WDR4V22xSF9Zi8sliUHJjCfc0xuFC5Ntm3tXrLRdTIrbnOXP7YeN+1pS8S8bvLmrgajz/7hYHuUEPXPYFhmjCGHR00bpAn0kyz8J2PwI8o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775960855; c=relaxed/simple; bh=AAo390ls7O+/gBJECTw5jRwQRLXWQ3hPBdBKg6IolV4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=p3cA0MgE1aFdgUMdOOaXzOcxAm+CK9iQiJwTweEA0NFBAU3Ot5NISI9f/gUSJzEoRYuT8JtSk0fiO6KP5wwtmCG+iRVnwRETN5PsaJWguTa+sXvDm7zEvdJ+XlRFxsjmjRb+7ldG0Yxvz4nhQQvM6zToTq6Pix6dgMunimEItFw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=nNBjl3YW; arc=none smtp.client-ip=74.125.82.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="nNBjl3YW" Received: by mail-dl1-f41.google.com with SMTP id a92af1059eb24-1271257ae53so10742073c88.1 for ; Sat, 11 Apr 2026 19:27:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1775960853; x=1776565653; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=zcJawOFnHtEXmwU7Ts86h653zGkHF4K3zLulupg+ZRE=; b=nNBjl3YWut/7i64zvyTFb2vp4TZv+G3AcQXHtbHl3BelwVRE4MMJqiqXerE2Xr5SNo icTgQ90bUbog/e3pvTPWVYvKj0whMhV0pmDTZAD6q9UUB33a2/sTE/Bn83czQPkaG5Dk zOPENQbnsd8bX+Cxfqu/JfXlsDtc56VHpUkfPuLLmvM2clbXFlLbCwtFJzM5rYUMnPqL ilDSzUQUuN8/BbU2AlcWwdrueD0qyb/hwJVUCfZtBdTG3SZagdA1JoKjtpVbyJ24gmBI h4nGzWA1O7ww1JY379C4p95XrVH3BFIkZ7tMgAVMm3j1+rKEXj3BX4pgZdnfu4p7TRR5 vAmQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775960853; x=1776565653; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=zcJawOFnHtEXmwU7Ts86h653zGkHF4K3zLulupg+ZRE=; b=LGgCg3J7jys4t/tLOEJtYN/weqaUfLCdyBaZIn1pm1Prict4v/1/yACgiE25knACP0 8zyrV8HynaZtHe1aa9n04whvLUQNvTyvFSk6rMnNjmiywWdItf9xDHpZvFyktlVy6Qom CNvT2WFa6Zg5jMk+9dkEWQKjRahpowUN7wsZvSioAcspfiKDi/VkmtgDRWOeyQEifVXU ohEAcGIHwmkcOiEs9gmM2orbRlPrjQNjHRQT57vyQeGuLy2Ddsvm1mLLcJtjp4+bPipa em/wLGYtjjJDGt7z94ccXZLr8cnNu1VhyPbIfIdwQQZPeKerekzEGO4KHWqqWNTWFCVv YeIw== X-Forwarded-Encrypted: i=1; AJvYcCVdDIH5y3zABpywSEWX5AmZwMvirwG8zxgSG/0ytjaj486TLTh/xqdJb4BbiUvO439kG4G8LwrNa1fAMrs=@vger.kernel.org X-Gm-Message-State: AOJu0YxVbDrCwsiG3ZuAjzW5gDAtPiL8c5CBz43ubf0/yo+Dp1ggn3wD qLDrTskwG3j2KoI9AIXcm2VhhycryOmoOPrMd79/ncstOtSe7HelmE6q X-Gm-Gg: AeBDiesvom0dont6EzYV2xawtSnxmF1TXoajoWwRaXWuqbQ6tPD7U5pkQH9m8E0Jcw0 JoL3m9khbDY47/RkhXv5KkHwWeYfJcY7v0xH3mH79x7aoRjvv9ZYsqLWY1KHoBe1DSRgzvlyAuK SsV+6HKDNjwS99i63s5B/1UlFxcb81QGFtsfMS/ENtpyDn1jXjgpQ3O//IBaDMZeMP34M39Y1sN kBFpKDt9ohpfFsOgHXZIJ4VbNhrwt4kwSPTKfzLdrwwgdPKuY8DVp9D80gh3ZUuaebt/GYJeTCG TBkSsH7O+j3lWTO6th4B79Wte8riSA9uvFqAX+G0kGQhz2R17a9e6X431Cc0gOasVpePVN6I+F0 f1KjIrER2f3rOgIXnCGPYa0ZOziAcfoCcI4WDO3VVeU1SZPldjwMk78ZUk/MX1UAEoFrnAM5DWu LGueoFNXQtKiVWj50dtgozRjYw8osK+E92FRyW9rArrVQ4/uujHlFr8+dLtrWvBnyImHFAUJIzs fn4TPhQGg== X-Received: by 2002:a05:7022:517:b0:128:dab3:f528 with SMTP id a92af1059eb24-12c34e892c2mr4994180c88.8.1775960852898; Sat, 11 Apr 2026 19:27:32 -0700 (PDT) Received: from efaec68ba852.tailc0aff1.ts.net ([206.206.192.132]) by smtp.gmail.com with ESMTPSA id a92af1059eb24-12c34352490sm8757860c88.0.2026.04.11.19.27.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 11 Apr 2026 19:27:32 -0700 (PDT) From: Weiming Shi To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko Cc: Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Barret Rhoden , Emil Tsalapatis , bpf@vger.kernel.org, linux-kernel@vger.kernel.org, Xiang Mei , Weiming Shi Subject: [PATCH bpf v4 2/2] selftests/bpf: Add test for arena VMA use-after-free on fork Date: Sat, 11 Apr 2026 19:27:15 -0700 Message-ID: <20260412022714.1955495-4-bestswngs@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260412022714.1955495-2-bestswngs@gmail.com> References: <20260412022714.1955495-2-bestswngs@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a selftest that reproduces the arena VMA use-after-free fixed in the previous commit. The test creates an arena, mmaps it, allocates pages via BPF, forks, has the parent munmap the arena, then has the child call bpf_arena_free_pages. Without the fix this triggers a KASAN slab-use-after-free in zap_page_range_single. Note: the UAF occurs entirely in kernel space and is not observable from userspace, so this test relies on KASAN to detect the bug. Without KASAN the test passes regardless of whether the fix is applied. Signed-off-by: Weiming Shi --- .../selftests/bpf/prog_tests/arena_fork.c | 80 +++++++++++++++++++ .../testing/selftests/bpf/progs/arena_fork.c | 41 ++++++++++ 2 files changed, 121 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/arena_fork.c create mode 100644 tools/testing/selftests/bpf/progs/arena_fork.c diff --git a/tools/testing/selftests/bpf/prog_tests/arena_fork.c b/tools/te= sting/selftests/bpf/prog_tests/arena_fork.c new file mode 100644 index 000000000000..0235884c5906 --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/arena_fork.c @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2026 Meta Platforms, Inc. and affiliates. */ + +/* + * Test that forking a process with an arena mmap does not cause a + * use-after-free when the parent unmaps and the child frees arena pages. + */ +#include +#include +#include +#include + +#include "arena_fork.skel.h" + +void test_arena_fork(void) +{ + LIBBPF_OPTS(bpf_test_run_opts, opts); + struct bpf_map_info info =3D {}; + __u32 info_len =3D sizeof(info); + struct arena_fork *skel; + long page_size; + size_t arena_sz; + void *arena_addr; + int arena_fd, ret, status; + pid_t pid; + + page_size =3D sysconf(_SC_PAGESIZE); + if (!ASSERT_GT(page_size, 0, "page_size")) + return; + + skel =3D arena_fork__open_and_load(); + if (!ASSERT_OK_PTR(skel, "open_and_load")) + return; + + arena_fd =3D bpf_map__fd(skel->maps.arena); + + /* libbpf mmaps the arena via initial_value */ + arena_addr =3D bpf_map__initial_value(skel->maps.arena, &arena_sz); + if (!ASSERT_OK_PTR(arena_addr, "arena_mmap")) + goto out; + + /* Get real arena byte size for munmap */ + bpf_map_get_info_by_fd(arena_fd, &info, &info_len); + arena_sz =3D (size_t)info.max_entries * page_size; + + /* Allocate 4 pages in the arena via BPF */ + ret =3D bpf_prog_test_run_opts(bpf_program__fd(skel->progs.arena_alloc), + &opts); + if (!ASSERT_OK(ret, "alloc_run") || + !ASSERT_OK(opts.retval, "alloc_ret")) + goto out; + + /* Fault in a page so zap_pages has work to do */ + ((volatile char *)arena_addr)[0] =3D 'A'; + + /* Fork: child inherits the arena VMA */ + pid =3D fork(); + if (!ASSERT_GE(pid, 0, "fork")) + goto out; + + if (pid =3D=3D 0) { + /* Child: parent will unmap first, then we free pages. */ + LIBBPF_OPTS(bpf_test_run_opts, child_opts); + int free_fd =3D bpf_program__fd(skel->progs.arena_free); + + usleep(200000); /* let parent munmap first */ + + ret =3D bpf_prog_test_run_opts(free_fd, &child_opts); + _exit(ret || child_opts.retval); + } + + /* Parent: unmap the arena */ + munmap(arena_addr, arena_sz); + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status), "child_exited"); + ASSERT_EQ(WEXITSTATUS(status), 0, "child_exit_code"); +out: + arena_fork__destroy(skel); +} diff --git a/tools/testing/selftests/bpf/progs/arena_fork.c b/tools/testing= /selftests/bpf/progs/arena_fork.c new file mode 100644 index 000000000000..783c935a0af8 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/arena_fork.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2026 Meta Platforms, Inc. and affiliates. */ +#include +#include +#include "bpf_arena_common.h" + +struct { + __uint(type, BPF_MAP_TYPE_ARENA); + __uint(map_flags, BPF_F_MMAPABLE); + __uint(max_entries, 16); /* number of pages */ +#ifdef __TARGET_ARCH_arm64 + __ulong(map_extra, 0x1ull << 32); /* start of mmap() region */ +#else + __ulong(map_extra, 0x1ull << 44); /* start of mmap() region */ +#endif +} arena SEC(".maps"); + +void __arena *alloc_addr; + +SEC("syscall") +int arena_alloc(void *ctx) +{ + void __arena *p; + + p =3D bpf_arena_alloc_pages(&arena, NULL, 4, NUMA_NO_NODE, 0); + if (!p) + return 1; + alloc_addr =3D p; + return 0; +} + +SEC("syscall") +int arena_free(void *ctx) +{ + if (!alloc_addr) + return 1; + bpf_arena_free_pages(&arena, alloc_addr, 4); + return 0; +} + +char _license[] SEC("license") =3D "GPL"; --=20 2.43.0