From nobody Fri Sep 25 21:40:15 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D1D11395AF6; Tue, 8 Sep 2026 11:24:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788866694; cv=none; b=Ar6Byh9sZ16j58QPLIrNWROln5PH3mgqq+vbfJHcVrBV6HCbN7RFHd6yAQwVudFCrNnlxkSWBN1uySVRXsjmsglAO/D1+ErK5JN+mUPOKbJPZrgx8gh8D2gzH2EJeSianT6xAtY4F7K4IAfG9aNqql+2mVWZz/I9dY2ubgeQnq0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788866694; c=relaxed/simple; bh=QmSOJwju5TfiPg8slA7VLmMjfjzHO2fnrvsHpTcasuQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=B7jiT9QZO82xyBKKhIG/P0FBJeYeGhEnWZA+4YSD8b1pgmMScA8NNMWk18UDJsGDu4MgjYhxlFoDqKfLVIi2IVYxL+NfXF5t77qxTkm2bv535c1VR/vA5x3naezwlquBOhwzRA7ZmRWI0Kh5d6iK/T5SZX2tsNLaVVvaMVvIFQM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Kt/T3D8X; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Kt/T3D8X" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 485D01F00A3D; Tue, 8 Sep 2026 11:24:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1788866683; bh=SN9pBsYau6XqA12Xdl8N5Dmjue89SDbE0U+vn84I9OA=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=Kt/T3D8XZpEzIO2N4iiHbSPlr4ezP2rFGrKhB8FxNGJUjNIAUpTwD9HB2w4fSdRXB 3d+G27lYP0VS4+TljcJccGORudcFm1kPDdz4/OEvCSMQ06hhm/tILmG6tXjv+fSxQy zMCIcl9up+LoaF/s+i3mqtqISioFKy9/BCXkdOX0OrxdQ5lfZVcnYbTsAy7l10FKw/ DsKUhaVgrSL3QWN6+1haOn5hhpXGYybvQCKtSVfLx1qeHkhsUox0Tr1QG2JXGHkIYg UC6y/zN+LsXyYlH9dSgiyaqdJXFBbTQor3lMoBMTACgjNNtY5Gk5lqMhdnzWFhkCEo 7x8z0YQX9TC/Q== From: "Lorenzo Stoakes (ARM)" Date: Tue, 08 Sep 2026 12:23:38 +0100 Subject: [PATCH v2 1/6] mm: move drivers/char/mem.c to mm/char-mem.c Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260908-map-private-dev-zero-v2-1-acc7b5625305@kernel.org> References: <20260908-map-private-dev-zero-v2-0-acc7b5625305@kernel.org> In-Reply-To: <20260908-map-private-dev-zero-v2-0-acc7b5625305@kernel.org> To: Arnd Bergmann , Greg Kroah-Hartman , Andrew Morton , "Liam R. Howlett" , Vlastimil Babka , Jann Horn , Pedro Falcato , David Hildenbrand , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Hugh Dickins , Baolin Wang , "Matthew Wilcox (Oracle)" , Jan Kara Cc: linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-fsdevel@vger.kernel.org, linux-kselftest@vger.kernel.org, "Lorenzo Stoakes (ARM)" X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=3650; i=ljs@kernel.org; h=from:subject:message-id; bh=QmSOJwju5TfiPg8slA7VLmMjfjzHO2fnrvsHpTcasuQ=; b=owGbwMvMwCV2fu7ZrsZH9SKMp9WSGLLmfyjcdzyWeZOE6yTvbwKf+P1jDhiwHK17HsCu8FHw7 pSpHKH/OkpZGMS4GGTFFFmefxHfHyQSNq/zgr8bzBxWJpAhDFycAjCR+cGMDA1rKx8/uvU/ObR5 C9+U0lkqDLvK95be62aedsT4ueG2cysYGXrNlfuezn9pcvO5e9qxW+tsvDTsSzwdDZrzPZyFtWf fZwMA X-Developer-Key: i=ljs@kernel.org; a=openpgp; fpr=E7F417BF5214569E89D04F46CF9DCD8A81E27F14 The memory character driver implements several mm-specific features and is always compiled into the kernel, so move it to mm/ where it belongs. Among other things the driver implements /dev/mem which provides raw access to physical memory, and /dev/zero which either allows mapping of a shmem region (if mapped with MAP_SHARED) or, uniquely, anonymous memory (if mapped MAP_PRIVATE). This change lays the foundations to allow MAP_PRIVATE-/dev/zero to be mapped precisely the same as anonymous memory is mapped as currently it is an edge case within mm. Also update a couple of comments that reference 'drivers/char/mem.c' to reference 'mm/char-mem.c'. Acked-by: David Hildenbrand (Arm) Acked-by: Mike Rapoport (Microsoft) Signed-off-by: Lorenzo Stoakes (ARM) --- MAINTAINERS | 4 ++-- drivers/char/Makefile | 2 +- mm/Makefile | 3 ++- drivers/char/mem.c =3D> mm/char-mem.c | 2 +- mm/shmem.c | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 2133aec4a200..ebadf4cef076 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17272,7 +17272,7 @@ F: Documentation/ABI/testing/sysfs-kernel-mm-memory= -tiers F: Documentation/ABI/testing/sysfs-kernel-mm-numa F: Documentation/admin-guide/mm/ F: Documentation/mm/ -F: drivers/char/mem.c +F: mm/char-mem.c F: include/linux/cma.h F: include/linux/dmapool.h F: include/linux/ioremap.h @@ -17477,7 +17477,7 @@ L: linux-mm@kvack.org S: Maintained W: http://www.linux-mm.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm -F: drivers/char/mem.c +F: mm/char-mem.c F: include/trace/events/mmap.h F: fs/proc/task_mmu.c F: fs/proc/task_nommu.c diff --git a/drivers/char/Makefile b/drivers/char/Makefile index a46d7bf7c4c8..bb3bf66937b3 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -3,7 +3,7 @@ # Makefile for the kernel character device drivers. # =20 -obj-y +=3D mem.o random.o +obj-y +=3D random.o obj-$(CONFIG_TTY_PRINTK) +=3D ttyprintk.o obj-y +=3D misc.o obj-$(CONFIG_TEST_MISC_MINOR) +=3D misc_minor_kunit.o diff --git a/mm/Makefile b/mm/Makefile index e7245cb88c66..2a3ec53d62ee 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -55,7 +55,8 @@ obj-y :=3D filemap.o mempool.o oom_kill.o fadvise.o \ mm_init.o percpu.o slab_common.o \ compaction.o show_mem.o \ interval_tree.o list_lru.o workingset.o \ - debug.o gup.o mmap_lock.o vma_init.o $(mmu-y) + debug.o gup.o mmap_lock.o vma_init.o char-mem.o \ + $(mmu-y) =20 # Give 'page_alloc' its own module-parameter namespace page-alloc-y :=3D page_alloc.o diff --git a/drivers/char/mem.c b/mm/char-mem.c similarity index 99% rename from drivers/char/mem.c rename to mm/char-mem.c index 63253d1de5d7..d2e575545044 100644 --- a/drivers/char/mem.c +++ b/mm/char-mem.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * linux/drivers/char/mem.c + * mm/char-mem.c * * Copyright (C) 1991, 1992 Linus Torvalds * diff --git a/mm/shmem.c b/mm/shmem.c index 255d69ebceba..c92ed17dbc4a 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -2981,7 +2981,7 @@ unsigned long shmem_get_unmapped_area(struct file *fi= le, sb =3D file_inode(file)->i_sb; } else { /* - * Called directly from mm/mmap.c, or drivers/char/mem.c + * Called directly from mm/mmap.c, or mm/char-mem.c * for "/dev/zero", to create a shared anonymous object. */ if (IS_ERR(shm_mnt)) --=20 2.55.0 From nobody Fri Sep 25 21:40:15 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3A07251A743; Tue, 8 Sep 2026 11:24:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788866703; cv=none; b=rz8U2xYPmVffH3fnfLup6elXYlXErcd5ftiGW5+Jbc6I8YwLE98pvYgU3wSBy3zyownUHkfqCSvR7aqA7N90ojZm7nOJKMvkQsaDPBRBhJeJL1j5+h2IQZabbKCHYGZbHcfhXpOS9LU4JzuGL5BJ3vjD5sv5wlsYD9y46zIoVSk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788866703; c=relaxed/simple; bh=A0bJ64HW79psSPlOLCnw7EMt+8G8UJeBpFvBmWrksO0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=qkhK5YycPCvJyQJ3TL8eujAAa/LSREyo+5WYNes+acgRr6/r9qHk8QYuaW8+1uPFvVdgRGab6yL/tMgYdxO7AZd1EvDYEnYFMF5vUuv5SgKPs2JSkcm1kVb4vw9U5UunBjncEeE6IAhCo5rrRVCN/VX1ES7brCyD05X1cgu4avU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=J2vGBeCe; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="J2vGBeCe" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3BDD01F00A3E; Tue, 8 Sep 2026 11:24:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1788866689; bh=QpNjJERy5W0kZ4sRAK5DqssDq5giEzAZ8nJVAHeIm7A=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=J2vGBeCewZOhjQLLB49PJxkgMpsXWdqjwH7GKarj61WbzSCS1NNO2oOQt9HIjm5rp u4jBuYPhwsTKgB+LY7E6DrAtdeh0+kGQ3XDJWk7P0/J2tjJsGgcohsLg2gKViHhNlT HMFNoovZtWaYxqigrBGQwQWaruFMVFkX1H2eaxW0fwKlrWxRnCV4nN7oni97TZAioY TJLnyC7f2dfjBY0gWgs6vUpEXWkx3E/1Lw5j5O3IVuGxhkpAd11PqQ5sOuK9XCZAMg QITnixPPxa7aTS1r4Rlbke1xMxw/oZ1ABhd2RJT4b5lDuWyN1TlNRdT8lQKtXXYMWZ 0BYDV6/5X6ROQ== From: "Lorenzo Stoakes (ARM)" Date: Tue, 08 Sep 2026 12:23:39 +0100 Subject: [PATCH v2 2/6] mm: implement file_is_dev_zero() to uniquely identify /dev/zero Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260908-map-private-dev-zero-v2-2-acc7b5625305@kernel.org> References: <20260908-map-private-dev-zero-v2-0-acc7b5625305@kernel.org> In-Reply-To: <20260908-map-private-dev-zero-v2-0-acc7b5625305@kernel.org> To: Arnd Bergmann , Greg Kroah-Hartman , Andrew Morton , "Liam R. Howlett" , Vlastimil Babka , Jann Horn , Pedro Falcato , David Hildenbrand , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Hugh Dickins , Baolin Wang , "Matthew Wilcox (Oracle)" , Jan Kara Cc: linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-fsdevel@vger.kernel.org, linux-kselftest@vger.kernel.org, "Lorenzo Stoakes (ARM)" X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=2988; i=ljs@kernel.org; h=from:subject:message-id; bh=A0bJ64HW79psSPlOLCnw7EMt+8G8UJeBpFvBmWrksO0=; b=owGbwMvMwCV2fu7ZrsZH9SKMp9WSGLLmfyjcGSSo1Re24du3VUcC7M8aau83dRc+0TDx5cfHI VMDs27xdpSyMIhxMciKKbI8/yK+P0gkbF7nBX83mDmsTCBDGLg4BWAihUEM/+PWJrT9WRQRY19Q ZWlws69zynZdjsJ7BoFxXr+urndleM7w36O0/4+4w8YDU5d/DppydP6UKZdnc2258yTK5umRjr+ Nq3kB X-Developer-Key: i=ljs@kernel.org; a=openpgp; fpr=E7F417BF5214569E89D04F46CF9DCD8A81E27F14 To lay the foundation for a future change that converts MAP_PRIVATE-/dev/zero mappings to be truly anonymous, add the ability to uniquely identify these mappings. With the memory character device now part of mm/ this is trivially achievable through a file_is_dev_zero() predicate that simply tests that the file operation hooks are zero_fops. Also update userland VMA tests to expose file_is_dev_zero() and provide a stub zero_fops for testing. Acked-by: David Hildenbrand (Arm) Signed-off-by: Lorenzo Stoakes (ARM) --- mm/char-mem.c | 13 +++++++++++++ mm/internal.h | 3 +++ tools/testing/vma/include/dup.h | 7 +++++++ tools/testing/vma/shared.c | 9 +++++++++ 4 files changed, 32 insertions(+) diff --git a/mm/char-mem.c b/mm/char-mem.c index d2e575545044..e53e89e6ddd8 100644 --- a/mm/char-mem.c +++ b/mm/char-mem.c @@ -31,6 +31,8 @@ #include #include =20 +#include "internal.h" + #define DEVMEM_MINOR 1 #define DEVPORT_MINOR 4 =20 @@ -707,6 +709,17 @@ static const struct memdev { #endif }; =20 +/** + * file_is_dev_zero() - is the specified @file associated with the /dev/ze= ro + * driver? + * @file: File to test. + * Returns: true if it is, false otherwise. + */ +bool file_is_dev_zero(const struct file *file) +{ + return file && file->f_op =3D=3D &zero_fops; +} + static int memory_open(struct inode *inode, struct file *filp) { int minor; diff --git a/mm/internal.h b/mm/internal.h index e16f1250b25c..5d474e5f7709 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -1638,4 +1638,7 @@ static inline bool can_spin_trylock(void) return true; } =20 +/* char-mem.c */ +bool file_is_dev_zero(const struct file *file); + #endif /* __MM_INTERNAL_H */ diff --git a/tools/testing/vma/include/dup.h b/tools/testing/vma/include/du= p.h index 57046d8ac81d..0d1a2ac88922 100644 --- a/tools/testing/vma/include/dup.h +++ b/tools/testing/vma/include/dup.h @@ -1641,3 +1641,10 @@ static inline pgoff_t linear_anon_page_index(const s= truct vm_area_struct *vma, =20 return pgoff; } + +extern const struct file_operations zero_fops; + +static inline bool file_is_dev_zero(const struct file *file) +{ + return file && file->f_op =3D=3D &zero_fops; +} diff --git a/tools/testing/vma/shared.c b/tools/testing/vma/shared.c index 4a39c9d50489..8c4826499f40 100644 --- a/tools/testing/vma/shared.c +++ b/tools/testing/vma/shared.c @@ -12,6 +12,15 @@ const struct vm_operations_struct vma_dummy_vm_ops; struct anon_vma dummy_anon_vma; struct task_struct __current; =20 +static int mmap_zero_prepare(struct vm_area_desc *desc) +{ + return 0; +} + +const struct file_operations zero_fops =3D { + .mmap_prepare =3D mmap_zero_prepare, +}; + struct vm_area_struct *alloc_vma(struct mm_struct *mm, unsigned long start, unsigned long end, pgoff_t pgoff, vma_flags_t vma_flags) --=20 2.55.0 From nobody Fri Sep 25 21:40:15 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 41B2852ED38; Tue, 8 Sep 2026 11:24:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788866704; cv=none; b=giacjSkS57cKvdYor27Pslnuvs4cgx/1liGBOn/J33Z6TsaovkkiEDluqlEke2tdcF63dCs2L7sDRhH2OtnAieKhJRWioaZiXcxNn7OmuiyLU+gGwnaAs6J0zYDu4k0L5nHNI/j5COAuPyEQH2flObKgJQ3KmoFmYE1Xm/jCArQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788866704; c=relaxed/simple; bh=K4kKSpQaR4XCTcqNOsKhlctxc2n/RJkZ2c1LQ0Kbg9I=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=iqDeZdxthTZ+ByvVV+hQIqVs3tJShOt0+OrAl5TLhWgfrlUgcv2JToYyEnL4hnoLRqTz+W8x6fHKrxZc4jpSrNgteJ/PsA3+eSHnNyET9OZXeo4IM85GhUyrDG9aI2Z96HrrBSIwuQfhIfsqir7QpcZKtkIASkJhJTz3zAEiVUM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RA6OXMH7; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="RA6OXMH7" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 98E231F00A3F; Tue, 8 Sep 2026 11:24:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1788866694; bh=Sr9jsabfi8EcucrWWLeAxRfyM9FSn5Wtyl4+cNbIDm8=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=RA6OXMH77Zgvaug81fCjs6q8EFJrkbGmeb5ZTjWBjxCYmZgZ8iTsBWQli9NNSLlxI VA9VdFEgvov7JLmT1QlJk6DibaCmUI1gcg6hlnXFqhxznqkJ24BwmuOQ0rVhFXxXnf f510ZISKCnXtVnIpHmiv9lPnAaCpG5I9H+RxQSMb7Dwu949ia2SkyAH/qxp3hbWNy/ yRi966BwRmoku4PUIcg+v8K+NkJ1zLsDDdBnM/RFgWbMPcLsXOET7kSO7/1Tlz5GbN 9wt8xwfZvE+Y2kRVil6nc5rE4jqeJhy/Ul45Z6GvJwBngeBQeXWyuNoj4SHsvHCsLi bUAhZ8HJegA5w== From: "Lorenzo Stoakes (ARM)" Date: Tue, 08 Sep 2026 12:23:40 +0100 Subject: [PATCH v2 3/6] mm/vma: only permit MAP_PRIVATE /dev/zero to be mapped anonymous Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260908-map-private-dev-zero-v2-3-acc7b5625305@kernel.org> References: <20260908-map-private-dev-zero-v2-0-acc7b5625305@kernel.org> In-Reply-To: <20260908-map-private-dev-zero-v2-0-acc7b5625305@kernel.org> To: Arnd Bergmann , Greg Kroah-Hartman , Andrew Morton , "Liam R. Howlett" , Vlastimil Babka , Jann Horn , Pedro Falcato , David Hildenbrand , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Hugh Dickins , Baolin Wang , "Matthew Wilcox (Oracle)" , Jan Kara Cc: linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-fsdevel@vger.kernel.org, linux-kselftest@vger.kernel.org, "Lorenzo Stoakes (ARM)" X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=6758; i=ljs@kernel.org; h=from:subject:message-id; bh=K4kKSpQaR4XCTcqNOsKhlctxc2n/RJkZ2c1LQ0Kbg9I=; b=owGbwMvMwCV2fu7ZrsZH9SKMp9WSGLLmfyhce1aq6l3qAWex1cw/52hrmF+YdSzvbuuxBJ62A plnb8NEOkpZGMS4GGTFFFmefxHfHyQSNq/zgr8bzBxWJpAhDFycAjCRP9sZ/kqxlcwXi/dMeuN4 6sIhzZs8PNlG/V4bxdusvSPMt6ot/8/IsKXiQvjFou2VZZd/vugSuqSqEtg+d0K0fmTuiYUsgo+ NmQA= X-Developer-Key: i=ljs@kernel.org; a=openpgp; fpr=E7F417BF5214569E89D04F46CF9DCD8A81E27F14 In order to use mmap_prepare() with MAP_PRIVATE mappings of /dev/zero without the success_hook hack we explicitly permitted mmap_prepare handlers to set NULL vm_ops. However this is dangerous and we really only want to allow this for MAP_PRIVATE-mapped /dev/zero. Therefore use the newly introduced file_is_dev_zero() to uniquely identify MAP_PRIVATE-/dev/zero mappings and only permit this behaviour for them. Then, remove all ability for mmap_prepare or mmap hooks to set a VMA anonymous and update mmap_zero_prepare() to leave it to the core mmap code to do so. Note that this disallows nested MAP_PRIVATE-mappings of /dev/zero regions. Doing this would be broken in any case. We therefore do not need to update the mmap_prepare() compatibility layer to reflect these changes, as the mmap hook check suffices to disallow this behaviour. Now we're setting vma->vm_ops to NULL for an mmap_prepare-initialised MAP_PRIVATE-/dev/zero mapping, we have to avoid a subtle issue when updating user-defined fields via set_vma_user_defined_fields(). The default for vma->vm_ops for all mmap_prepare-initialised mappings is vma_dummy_vm_ops, so map->vm_ops will be set to this and setting vma->vm_ops to this will render the VMA mistakenly non-anon. In general, we should never be setting user-defined fields for an anonymous VMA, so explicitly check for this to avoid doing so for the one case where a mapping can be both mmap_prepare and anonymous. In the case of legacy ->mmap hooks some drivers may set vma->vm_ops NULL believing this is the equivalent of setting no VMA operations. Therefore update mmap_file() to correct this by setting dummy VMA operations if this occurs. An example of this is drm_gem_shmem_mmap() which deliberately clears vma->vm_ops before handing the VMA to dma-buf. Cases such as this will be updated when they are converted to mmap_prepare. Also, in order to avoid a single commit bisection hazard, add a temporary workaround to set the VMA anonymous only after vma->vm_file is assigned in __mmap_new_file_vma(). This is because vma_set_range() calls vma_set_pgoff() and assert_sane_pgoff() in turn, prior to the vma->vm_file being assigned. If we set the VMA anonymous early then this assert will fail. This is removed in the subsequent commit. Signed-off-by: Lorenzo Stoakes (ARM) Acked-by: David Hildenbrand (Arm) --- mm/char-mem.c | 6 +----- mm/internal.h | 17 ++++++++++------- mm/vma.c | 33 +++++++++++++++++++++++++-------- 3 files changed, 36 insertions(+), 20 deletions(-) diff --git a/mm/char-mem.c b/mm/char-mem.c index e53e89e6ddd8..c0b5fb019223 100644 --- a/mm/char-mem.c +++ b/mm/char-mem.c @@ -508,11 +508,7 @@ static int mmap_zero_prepare(struct vm_area_desc *desc) if (vma_desc_test(desc, VMA_SHARED_BIT)) return shmem_zero_setup_desc(desc); =20 - /* - * This is a highly unique situation where we mark a MAP_PRIVATE mapping - * of /dev/zero anonymous, despite it not being. - */ - vma_desc_set_anonymous(desc); + /* MAP_PRIVATE semantics are taken care of for us by core mm. */ return 0; } =20 diff --git a/mm/internal.h b/mm/internal.h index 5d474e5f7709..da14c56fb24e 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -226,15 +226,18 @@ static inline int mmap_file(struct file *file, struct= vm_area_struct *vma) { int err =3D vfs_mmap(file, vma); =20 - if (likely(!err)) - return 0; - /* - * OK, we tried to call the file hook for mmap(), but an error - * arose. The mapping is in an inconsistent state and we must not invoke - * any further hooks on it. + * Either we tried to call the file hook for mmap() and an error arose + * or a driver set vma->vm_ops =3D NULL intending there to be no VMA + * operations. + * + * In the former case the VMA is in an inconsistent state and we mustn't + * invoke any further hooks on it, in the latter case the hook actually + * wanted no further hooks to be invoked, so fix both by setting dummy + * VMA ops. */ - vma->vm_ops =3D &vma_dummy_vm_ops; + if (unlikely(err || !vma->vm_ops)) + vma->vm_ops =3D &vma_dummy_vm_ops; =20 return err; } diff --git a/mm/vma.c b/mm/vma.c index 35e7a64855fa..4b8d430d9619 100644 --- a/mm/vma.c +++ b/mm/vma.c @@ -2621,6 +2621,19 @@ static int __mmap_new_file_vma(struct mmap_state *ma= p, return 0; } =20 +static bool map_is_private(const struct mmap_state *map) +{ + return !vma_flags_test(&map->vma_flags, VMA_SHARED_BIT); +} + +static bool map_is_anon(const struct mmap_state *map) +{ + if (!map_is_private(map)) + return false; + + return !map->file || file_is_dev_zero(map->file); +} + /* * __mmap_new_vma() - Allocate a new VMA for the region, as merging was not * possible. @@ -2634,8 +2647,7 @@ static int __mmap_new_file_vma(struct mmap_state *map, static int __mmap_new_vma(struct mmap_state *map, struct vm_area_struct **= vmap, struct mmap_action *action) { - const bool is_anon =3D !map->file && - !vma_flags_test(&map->vma_flags, VMA_SHARED_BIT); + const bool is_anon =3D map_is_anon(map); struct vma_iterator *vmi =3D map->vmi; int error =3D 0; struct vm_area_struct *vma; @@ -2651,7 +2663,7 @@ static int __mmap_new_vma(struct mmap_state *map, str= uct vm_area_struct **vmap, =20 vma_iter_config(vmi, map->addr, map->end); =20 - if (is_anon) + if (is_anon && !map->file) vma_set_anonymous(vma); =20 vma_set_range(vma, map->addr, map->end, map->pgoff, map->anon_pgoff); @@ -2669,6 +2681,10 @@ static int __mmap_new_vma(struct mmap_state *map, st= ruct vm_area_struct **vmap, else if (!is_anon) error =3D shmem_zero_setup(vma); =20 + /* Temporary MAP_PRIVATE-/dev/zero workaround. */ + if (is_anon && map->file) + vma_set_anonymous(vma); + if (error) goto free_iter_vma; =20 @@ -2777,6 +2793,10 @@ static int call_mmap_prepare(struct mmap_state *map, if (err) return err; =20 + /* Hooks cannot mark themselves anonymous. */ + if (!desc->vm_ops) + return -EINVAL; + err =3D call_action_prepare(map, desc); if (err) return err; @@ -2799,10 +2819,7 @@ static int call_mmap_prepare(struct mmap_state *map, static void set_vma_user_defined_fields(struct vm_area_struct *vma, struct mmap_state *map) { - if (map->vm_ops) - vma->vm_ops =3D map->vm_ops; - else /* Only /dev/zero should do this. */ - vma_set_anonymous(vma); + vma->vm_ops =3D map->vm_ops; vma->vm_private_data =3D map->vm_private_data; } =20 @@ -2882,7 +2899,7 @@ static unsigned long __mmap_region(struct file *file,= unsigned long addr, allocated_new =3D true; } =20 - if (have_mmap_prepare) + if (have_mmap_prepare && !map_is_anon(&map)) set_vma_user_defined_fields(vma, &map); =20 __mmap_complete(&map, vma); --=20 2.55.0 From nobody Fri Sep 25 21:40:15 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5709E51476A; Tue, 8 Sep 2026 11:25:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788866710; cv=none; b=FE3pCy5T8XqHLpIBehurgXp+OKapxwAVDPn+tBdxPE07yY/bOncxwihFBBnb5s+pbkCetbdI1mDJ02C+dNdgcIdp8reMB6NDXTuhPJDxHVpzPKnMKLkj0VRovBnkloipSm8gPLgp8MNEaxzw6uEoKMACdF+pZtHMB4jMhDTY3ao= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788866710; c=relaxed/simple; bh=fzX9QdUHMfVqyUp8LMONbNp4Wr4hn8wKnpReBWJOVJ4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=RDLNzvi6giYK9pvzJCIKy0CtI3QOycZnHdoxBUNLZXGqtWu1Pg47gXlF4scPWNC2s4Aht6dBwBpksj1GouAHsNd+OiV71MSFtU7JV1KJil4QIUAPmr2oyVc5/ujY8YB56gRWz2iqaK7riP8f/+hzAoJAaKlC+KfK2M85gp7zxMc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Shx6TYO9; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Shx6TYO9" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8F5D41F00A3A; Tue, 8 Sep 2026 11:24:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1788866699; bh=yazDYPGF74/He2HfY4z5SarPY7lHKoZZ4RLl0CKyvnU=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=Shx6TYO9mvVknBiNeE1awVt5bACs63+IwluoLqEbILXwSV0GnAGg/zCQYguEZPV3/ YSG/XwVcfKeoUwCEbzJGinZmaoim/xwflGCpdp7rgDPfytGeAyyqYAlvDnCzqi8s71 6gfz67uNjCjekFJZdCUUlBETd6R6NHl2KzziwNV36s6E8G8vqsClpw1qGKheiWo3DH vdZ5VAhLQDMhTw5b+XwH9EF9gP1B7ZYV2M9SehZ9SEnMqNGfTdYxhYnCoDm8SGv8UI ejd8G/zNy67z0o4CVUdfw6j8OtfnbDI6SfkKCtp3qM/Nx/u+BNJ+IdLxGJniUCeuOt vyf/ZI0B/sPCw== From: "Lorenzo Stoakes (ARM)" Date: Tue, 08 Sep 2026 12:23:41 +0100 Subject: [PATCH v2 4/6] mm/vma: make MAP_PRIVATE-mapped /dev/zero mappings truly anonymous Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260908-map-private-dev-zero-v2-4-acc7b5625305@kernel.org> References: <20260908-map-private-dev-zero-v2-0-acc7b5625305@kernel.org> In-Reply-To: <20260908-map-private-dev-zero-v2-0-acc7b5625305@kernel.org> To: Arnd Bergmann , Greg Kroah-Hartman , Andrew Morton , "Liam R. Howlett" , Vlastimil Babka , Jann Horn , Pedro Falcato , David Hildenbrand , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Hugh Dickins , Baolin Wang , "Matthew Wilcox (Oracle)" , Jan Kara Cc: linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-fsdevel@vger.kernel.org, linux-kselftest@vger.kernel.org, "Lorenzo Stoakes (ARM)" X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=8751; i=ljs@kernel.org; h=from:subject:message-id; bh=fzX9QdUHMfVqyUp8LMONbNp4Wr4hn8wKnpReBWJOVJ4=; b=kA0DAAoWz53NioHifxQByyZiAGqf8HGhBHI1/4E1m+mlBR2WBnzPmZM3BFyoWgm5ixrBuXusp 4h1BAAWCgAdFiEE5/QXv1IUVp6J0E9Gz53NioHifxQFAmqf8HEACgkQz53NioHifxSYkQD/Zkkv vcbHKVb39aHTglqLTcA17mnJTgpVr4MM1HNCObMA/AvlmIqB6vU8C/V4+tHgRqUReLRpOOrMMc4 TBhcDWPkA X-Developer-Key: i=ljs@kernel.org; a=openpgp; fpr=E7F417BF5214569E89D04F46CF9DCD8A81E27F14 When mapping /dev/zero with MAP_PRIVATE, one ends up with strange VMAs originating from Linux's distant past. These have vma->vm_file set but NULL vma->vm_ops, meaning they satisfy vma_is_anonymous() but otherwise resemble a file-backed VMA. The introduction of anonymous page offsets and their subsequent use as indexes for MAP_PRIVATE-file-backed mappings mean the rmap does the right thing with these but we are left with inconsistencies. The vma_start_pgoff(vma) =3D=3D vma_start_anon_pgoff(vma) invariant is true= for all other anonymous VMAs, but not these. These VMAs are also observable as files in /proc//[maps, smaps, map_files] but otherwise behave like anonymous mappings. Therefore let's make these VMAs actually anonymous at mapping time which will activate the anonymous code path for mappings. This means we no longer have to account for this discrepancy anywhere and no longer have to think about these at all. This is user-observable, as MAP_PRIVATE-/dev/zero will no longer appear in procfs as a file-backed mapping, but the impact of this change should be low as likely nobody is relying upon this. However in any case, in using MAP_PRIVATE-/dev/zero they are explicitly asking anonymous memory, so no longer seeing these as file mappings is in fact correct. A previous commit gave us file_is_dev_zero() to positively identify these mappings, so we expressly only do so for these alone. Update assert_sane_pgoff(), the comment for vma_start_pgoff() and linear_anon_page_index() to reflect the change. We make this change in call_mmap_prepare() alone as /dev/zero has been converted to an mmap_prepare hook and we do not permit nested MAP_PRIVATE mapping of /dev/zero. We also remove the now defunct vma_desc_set_anonymous() and eliminate the temporary bisection hazard fix from the previous commit. Also update the VMA userland tests to reflect the change. Finally, update the procfs self tests proc-self-map-files-001 and proc-self-map-files-002 which both intend to map an arbitrary file MAP_PRIVATE then assert procfs state, but happen to choose /dev/zero. Fix them by updating these to /proc/self/exe which is guaranteed to be present if procfs is mounted. Signed-off-by: Lorenzo Stoakes (ARM) Acked-by: David Hildenbrand (Arm) --- include/linux/mm.h | 10 ++------ include/linux/pagemap.h | 3 +-- mm/vma.c | 28 ++++++++++++++----= ---- mm/vma.h | 3 --- .../selftests/proc/proc-self-map-files-001.c | 2 +- .../selftests/proc/proc-self-map-files-002.c | 2 +- tools/testing/vma/include/dup.h | 3 +-- 7 files changed, 24 insertions(+), 27 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 1b28e6fc8d5d..9238b7d52198 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1539,11 +1539,6 @@ static inline void vma_set_anonymous(struct vm_area_= struct *vma) vma->vm_ops =3D NULL; } =20 -static inline void vma_desc_set_anonymous(struct vm_area_desc *desc) -{ - desc->vm_ops =3D NULL; -} - static inline bool vma_is_anonymous(const struct vm_area_struct *vma) { return !vma->vm_ops; @@ -4405,9 +4400,8 @@ static inline unsigned long vma_pages(const struct vm= _area_struct *vma) * If @vma is a MAP_PRIVATE file-backed mapping, then this returns the * page offset within the file. * - * Edge cases: nommu does not abide by these, MAP_PRIVATE-/dev/zero satisf= ies - * vma_is_anonymous() but has file-backed page offset, and MAP_PRIVATE-pfn= map - * regions have their page offset set to the first PFN in the range. + * Edge cases: nommu does not abide by these and CoW MAP_PRIVATE-pfnmap re= gions + * have their page offset set to the first PFN in the range. * * Returns: The page offset of the start of @vma. */ diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 0adfa6605653..939f3a5e973f 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -1128,8 +1128,7 @@ static inline pgoff_t linear_anon_page_index(const st= ruct vm_area_struct *vma, const pgoff_t pgoff =3D __linear_anon_page_index(vma, address); =20 VM_WARN_ON_ONCE(!vma_is_cow_mapping(vma)); - /* Account for MAP_PRIVATE-/dev/zero which is only semi-anonymous. */ - if (vma_is_anonymous(vma) && !vma->vm_file) + if (vma_is_anonymous(vma)) VM_WARN_ON_ONCE(pgoff !=3D linear_page_index(vma, address)); =20 return pgoff; diff --git a/mm/vma.c b/mm/vma.c index 4b8d430d9619..6fdce4852ce6 100644 --- a/mm/vma.c +++ b/mm/vma.c @@ -2621,6 +2621,13 @@ static int __mmap_new_file_vma(struct mmap_state *ma= p, return 0; } =20 +static void map_set_anon(struct mmap_state *map) +{ + map->file =3D NULL; + map->vm_ops =3D NULL; + map->pgoff =3D map->addr >> PAGE_SHIFT; +} + static bool map_is_private(const struct mmap_state *map) { return !vma_flags_test(&map->vma_flags, VMA_SHARED_BIT); @@ -2628,10 +2635,7 @@ static bool map_is_private(const struct mmap_state *= map) =20 static bool map_is_anon(const struct mmap_state *map) { - if (!map_is_private(map)) - return false; - - return !map->file || file_is_dev_zero(map->file); + return map_is_private(map) && !map->file; } =20 /* @@ -2663,7 +2667,7 @@ static int __mmap_new_vma(struct mmap_state *map, str= uct vm_area_struct **vmap, =20 vma_iter_config(vmi, map->addr, map->end); =20 - if (is_anon && !map->file) + if (is_anon) vma_set_anonymous(vma); =20 vma_set_range(vma, map->addr, map->end, map->pgoff, map->anon_pgoff); @@ -2681,10 +2685,6 @@ static int __mmap_new_vma(struct mmap_state *map, st= ruct vm_area_struct **vmap, else if (!is_anon) error =3D shmem_zero_setup(vma); =20 - /* Temporary MAP_PRIVATE-/dev/zero workaround. */ - if (is_anon && map->file) - vma_set_anonymous(vma); - if (error) goto free_iter_vma; =20 @@ -2793,7 +2793,7 @@ static int call_mmap_prepare(struct mmap_state *map, if (err) return err; =20 - /* Hooks cannot mark themselves anonymous. */ + /* It's invalid for mmap_preprare hooks to clear vm_ops. */ if (!desc->vm_ops) return -EINVAL; =20 @@ -2813,6 +2813,14 @@ static int call_mmap_prepare(struct mmap_state *map, map->vm_ops =3D desc->vm_ops; map->vm_private_data =3D desc->private_data; =20 + /* + * MAP_PRIVATE-/dev/zero mappings are an ancient way of getting + * anonymous mappings. Rather than allowing these mappings to be odd + * outliers, simply make them truly anonymous. + */ + if (map_is_private(map) && file_is_dev_zero(map->file)) + map_set_anon(map); + return 0; } =20 diff --git a/mm/vma.h b/mm/vma.h index 024fabe63560..e97bd2dfa786 100644 --- a/mm/vma.h +++ b/mm/vma.h @@ -267,9 +267,6 @@ static inline void assert_sane_pgoff(struct vm_area_str= uct *vma, pgoff_t pgoff) */ if (!vma_is_anonymous(vma)) return; - /* MAP_PRIVATE-/dev/zero is anon, non-NULL vm_file, but has file pgoff. */ - if (vma->vm_file) - return; /* If faulted in, could have been remapped. */ if (vma->anon_vma) return; diff --git a/tools/testing/selftests/proc/proc-self-map-files-001.c b/tools= /testing/selftests/proc/proc-self-map-files-001.c index 4209c64283d6..bbca9f9e2743 100644 --- a/tools/testing/selftests/proc/proc-self-map-files-001.c +++ b/tools/testing/selftests/proc/proc-self-map-files-001.c @@ -51,7 +51,7 @@ int main(void) int fd; unsigned long a, b; =20 - fd =3D open("/dev/zero", O_RDONLY); + fd =3D open("/proc/self/exe", O_RDONLY); if (fd =3D=3D -1) return 1; =20 diff --git a/tools/testing/selftests/proc/proc-self-map-files-002.c b/tools= /testing/selftests/proc/proc-self-map-files-002.c index e6aa00a183bc..5786cdffbbf6 100644 --- a/tools/testing/selftests/proc/proc-self-map-files-002.c +++ b/tools/testing/selftests/proc/proc-self-map-files-002.c @@ -57,7 +57,7 @@ int main(void) int fd; unsigned long a, b; =20 - fd =3D open("/dev/zero", O_RDONLY); + fd =3D open("/proc/self/exe", O_RDONLY); if (fd =3D=3D -1) return 1; =20 diff --git a/tools/testing/vma/include/dup.h b/tools/testing/vma/include/du= p.h index 0d1a2ac88922..16c09dac59d9 100644 --- a/tools/testing/vma/include/dup.h +++ b/tools/testing/vma/include/dup.h @@ -1635,8 +1635,7 @@ static inline pgoff_t linear_anon_page_index(const st= ruct vm_area_struct *vma, const pgoff_t pgoff =3D __linear_anon_page_index(vma, address); =20 VM_WARN_ON_ONCE(!vma_is_cow_mapping(vma)); - /* Account for MAP_PRIVATE-/dev/zero which is only semi-anonymous. */ - if (vma_is_anonymous(vma) && !vma->vm_file) + if (vma_is_anonymous(vma)) VM_WARN_ON_ONCE(pgoff !=3D linear_page_index(vma, address)); =20 return pgoff; --=20 2.55.0 From nobody Fri Sep 25 21:40:15 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0475752B1F3; Tue, 8 Sep 2026 11:25:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788866718; cv=none; b=kSUsRwB0zS0G1QLAkrxhMEbhg10gZxbrd4WmUkGT3UJZkhXdLW2Jdfz1cUSVE5T37ntylUgVaZ/TChVZMshsjY3hXSppF1A4WO6YayvuUWYu6Zg136qR5lSsOOzvg5xuZsF+t+4AKsKkahCSfXuD7C/QhEnbQ8TOL9IDEBg640U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788866718; c=relaxed/simple; bh=MuW0MgECKFqsgKYanDvHZ2zzAEiQ7iCtWQ9chN/jOZY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=LlvPVHdLQSA/dtp4K3Je5ktZPOh4p79lAP0I5NUD31SL+38aHviqxtOOQ8Siy7Vy1kHJF/3jtv4ZLbribK/fYrpyx0baVc2iSVsnM2jtxmngU4lCXcAVc+PqhxaS1dDj/NgyErX6XNeprb4ws/ogStgEGUjzevNrxNOAkcZvGJg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=MCMynEAK; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="MCMynEAK" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 84AD51F00ACA; Tue, 8 Sep 2026 11:24:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1788866704; bh=7INaOtP/gm2Q0CwFqGyhMMm+FXe4/enBYyOAMoEMKqg=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=MCMynEAKWBBtZhM3TavPM2jvsMzLi/wfyDztSX3NadK30N7sH/KYNxbJTPna0++4M lE5/YW5SRBTlhkna4Lws5EybILgPvC0mz3bRN3o/XuXaHJSrijVmszq4RtwnMsPVBk tOxdnuRIffeKcofQSiJ2BFhlxP7re6LrwYSQqSruLSMCYgIi7gSFC1fU3mWxbSwn4C 2U+Gg1vY0dCzE7kFhijpKTkoX/Y/4vufVgfmUDopjMu7NmDgrK2ifxh9J+NzmNpcQz W22w2Kx727HvIXnbGmnxss/iKzUM2ixk4xg/yUsDdYwCClDW/MQzaRRQij+TWvnTyd xTbP10Rd5uwfA== From: "Lorenzo Stoakes (ARM)" Date: Tue, 08 Sep 2026 12:23:42 +0100 Subject: [PATCH v2 5/6] tools/testing/vma: add test to assert MAP_PRIVATE-/dev/zero is anon Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260908-map-private-dev-zero-v2-5-acc7b5625305@kernel.org> References: <20260908-map-private-dev-zero-v2-0-acc7b5625305@kernel.org> In-Reply-To: <20260908-map-private-dev-zero-v2-0-acc7b5625305@kernel.org> To: Arnd Bergmann , Greg Kroah-Hartman , Andrew Morton , "Liam R. Howlett" , Vlastimil Babka , Jann Horn , Pedro Falcato , David Hildenbrand , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Hugh Dickins , Baolin Wang , "Matthew Wilcox (Oracle)" , Jan Kara Cc: linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-fsdevel@vger.kernel.org, linux-kselftest@vger.kernel.org, "Lorenzo Stoakes (ARM)" X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=1881; i=ljs@kernel.org; h=from:subject:message-id; bh=MuW0MgECKFqsgKYanDvHZ2zzAEiQ7iCtWQ9chN/jOZY=; b=owGbwMvMwCV2fu7ZrsZH9SKMp9WSGLLmfyg80KuTMs9Z7srfjee93Bu2eq+dea5h49YnP6/36 a5/o1EQ3FHKwiDGxSArpsjy/Iv4/iCRsHmdF/zdYOawMoEMYeDiFICJyGQzMhzsOGP3+heLprbt OzWrS8qzdvEn8PpYXC9/MOmUscrVH5sY/udIy2aduTOvet7fSVJMds/c3ydt2yGZ4hOf4VAdVFu zjAEA X-Developer-Key: i=ljs@kernel.org; a=openpgp; fpr=E7F417BF5214569E89D04F46CF9DCD8A81E27F14 Now we've made MAP_PRIVATE-mapped /dev/zero mappings truly anonymous, add a VMA userland test to assert that this is the case and everything is as we would expect for an anonymous mapping. Acked-by: David Hildenbrand (Arm) Signed-off-by: Lorenzo Stoakes (ARM) --- tools/testing/vma/tests/mmap.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/tools/testing/vma/tests/mmap.c b/tools/testing/vma/tests/mmap.c index c85bc000d1cb..fa73faff2262 100644 --- a/tools/testing/vma/tests/mmap.c +++ b/tools/testing/vma/tests/mmap.c @@ -45,7 +45,44 @@ static bool test_mmap_region_basic(void) return true; } =20 +static bool test_pure_anon_dev_zero(void) +{ + const vma_flags_t vma_flags =3D mk_vma_flags(VMA_READ_BIT, VMA_WRITE_BIT, + VMA_MAYREAD_BIT, VMA_MAYWRITE_BIT); + struct file file =3D { + .f_op =3D &zero_fops, + }; + struct mm_struct mm =3D {}; + struct vm_area_struct *vma; + unsigned long addr; + VMA_ITERATOR(vmi, &mm, 0); + + current->mm =3D &mm; + + /* + * Map a MAP_PRIVATE-/dev/zero mapping at address 0x300000 with a page + * offset of 0x10, which we expect to be reset to the anonymous page + * offset. + */ + addr =3D __mmap_region(&file, 0x300000, 0x3000, vma_flags, 0x10, NULL); + ASSERT_EQ(addr, 0x300000); + + /* Assert that it truly is an anonymous mapping. */ + vma =3D vma_lookup(&mm, addr); + ASSERT_NE(vma, NULL); + ASSERT_TRUE(vma_is_anonymous(vma)); + ASSERT_EQ(vma->vm_file, NULL); + ASSERT_EQ(vma->vm_private_data, NULL); + /* Expect anonymous page offsets. */ + ASSERT_EQ(vma->vm_pgoff, 0x300); + ASSERT_EQ(vma_start_anon_pgoff(vma), 0x300); + + cleanup_mm(&mm, &vmi); + return true; +} + static void run_mmap_tests(int *num_tests, int *num_fail) { TEST(mmap_region_basic); + TEST(pure_anon_dev_zero); } --=20 2.55.0 From nobody Fri Sep 25 21:40:15 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 06CE44B04B9; Tue, 8 Sep 2026 11:25:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788866723; cv=none; b=lw5iBcZrQ+YxZZFsaCG68Bh7YMtF/z9OcKzRBbXI3gGCooPrylobmSLPu6wD7KbTWkiUeL3hJK98zKWlt0mc0j05KeBv1LnauhEj1vgyEqzrfzVleJA7CTIFe55CdBq0TTb4fqFmW6glBI6PFaAei9KkDfDp+yz6tTM7PZuurXo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788866723; c=relaxed/simple; bh=3png0c8or7nYdCZx23lmGIGRrVIeUt4V+p87b2uuFI8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=puwvB4UYN21P8aj2geEMouwsm6ykN6j/gCg+WH4u5Q1lS+F+pFIfabD5Za361rBknzYP+j/c0/EbE1xltU5ZjXbxE3U568bFkhqtnIyz5ep5PWOTQkDQ2Q5UVTRDof0NDlZOH4GKDPrqXs1zl3UT74uNrczG7NDvs8QT4sjQt38= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=XgmNxLy3; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="XgmNxLy3" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7C87C1F00A3D; Tue, 8 Sep 2026 11:25:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1788866708; bh=om0np5kv2o7p4ujdr2YodlAc5O6JiCLsFWeQl7Rh24s=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=XgmNxLy3XXo6zJi+ipSK9/Kxq68nxv16sLLPsIcI4SUgz9twJMZI81MQ1uLL0ZcxC sd97Rux856rODIB4DkQj/J3btopjnfJz8KZCP9qLUOFtDQ2gQaa0TKT3NTVC4GBxU1 sI9BHcnkMlIEvT3Uq5LYGLwZs7FIfAp4e0w3RWiA0yOxITZIYl1/1TqH1gLG9liSBj Kb076kSuPDadjILy/hzduDtUlggkJN6sLYAXYVTZWNmCw9NK5UL2hwjZJMzMYTiv8Z l53JivNcQ3Y6aIvGa6Ww9F6P4pV3Nj1kltUc3JU6Apyk2SY5pGVVxBG5oH77ddyBC0 RtU5Qgx16whFQ== From: "Lorenzo Stoakes (ARM)" Date: Tue, 08 Sep 2026 12:23:43 +0100 Subject: [PATCH v2 6/6] tools/testing/selftests/mm: add MAP_PRIVATE-/dev/zero merge tests Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260908-map-private-dev-zero-v2-6-acc7b5625305@kernel.org> References: <20260908-map-private-dev-zero-v2-0-acc7b5625305@kernel.org> In-Reply-To: <20260908-map-private-dev-zero-v2-0-acc7b5625305@kernel.org> To: Arnd Bergmann , Greg Kroah-Hartman , Andrew Morton , "Liam R. Howlett" , Vlastimil Babka , Jann Horn , Pedro Falcato , David Hildenbrand , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Hugh Dickins , Baolin Wang , "Matthew Wilcox (Oracle)" , Jan Kara Cc: linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-fsdevel@vger.kernel.org, linux-kselftest@vger.kernel.org, "Lorenzo Stoakes (ARM)" X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=4111; i=ljs@kernel.org; h=from:subject:message-id; bh=3png0c8or7nYdCZx23lmGIGRrVIeUt4V+p87b2uuFI8=; b=owGbwMvMwCV2fu7ZrsZH9SKMp9WSGLLmfyh8seHhftu6/WGcCu07NVd5JzsuVNKK1z46e9qze f6bWVjWd5SyMIhxMciKKbI8/yK+P0gkbF7nBX83mDmsTCBDGLg4BWAifVoM/3PfCx6wSxSaVbmk 7+bO4wwSV0UPetSq1M6ULVgWsuaT41aGfwpzf6lGe8wQfcrt4LPt3/Qizd8Nv+V/c+012bGWz6A mhwUA X-Developer-Key: i=ljs@kernel.org; a=openpgp; fpr=E7F417BF5214569E89D04F46CF9DCD8A81E27F14 Assert that MAP_PRIVATE-mapped /dev/zero mappings behave like they are anonymous. Test both unfaulted and faulted/unfaulted merges with page offset 0 which would not merge if the mappings were treated as if they were file-backed. With the recent change that makes them behave as pure anonymous mappings, the merges should succeed as their page offsets are equal to their anonymous page offsets. Signed-off-by: Lorenzo Stoakes (ARM) Acked-by: David Hildenbrand (Arm) --- tools/testing/selftests/mm/merge.c | 95 ++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 95 insertions(+) diff --git a/tools/testing/selftests/mm/merge.c b/tools/testing/selftests/m= m/merge.c index 52b8727b6628..7dd2933417c1 100644 --- a/tools/testing/selftests/mm/merge.c +++ b/tools/testing/selftests/mm/merge.c @@ -1362,6 +1362,101 @@ TEST_F(merge, anon_and_page_offset_mismatch_memfd) ASSERT_EQ(procmap->query.vma_end, (unsigned long)ptr + 5 * page_size); } =20 +TEST_F(merge, merge_map_private_dev_zero_unfaulted) +{ + struct procmap_fd *procmap =3D &self->procmap; + unsigned int page_size =3D self->page_size; + char *carveout =3D self->carveout; + char *ptr, *ptr2; + int fd_zero; + + if (access("/dev/zero", F_OK)) + SKIP(return, "No /dev/zero."); + fd_zero =3D open("/dev/zero", O_RDWR); + ASSERT_NE(fd_zero, -1); + + /* + * Map two MAP_PRIVATE-/dev/zero VMAs next to one another with offset 0 + * each. + * + * With these being made truly anonymous upon mapping, they will + * merge. If they were file-backed VMAs the page offsets would prevent + * the merge: + * + * |-----||------| |-------------| + * | ptr || ptr2 | -> | ptr | + * |-----||------| |-------------| + */ + ptr =3D mmap(carveout, 5 * page_size, PROT_READ | PROT_WRITE, + MAP_FIXED | MAP_PRIVATE, fd_zero, 0); + ptr2 =3D mmap(&carveout[5 * page_size], 5 * page_size, + PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, fd_zero, 0); + close(fd_zero); + ASSERT_NE(ptr, MAP_FAILED); + ASSERT_NE(ptr2, MAP_FAILED); + + /* Assert that they merged. */ + ASSERT_TRUE(find_vma_procmap(procmap, ptr)); + ASSERT_EQ(procmap->query.vma_start, (unsigned long)ptr); + ASSERT_EQ(procmap->query.vma_end, (unsigned long)ptr + 10 * page_size); +} + +TEST_F(merge, merge_map_private_dev_zero_faulted_unfaulted) +{ + struct procmap_fd *procmap =3D &self->procmap; + unsigned int page_size =3D self->page_size; + char *carveout =3D self->carveout; + char *ptr, *ptr2; + int fd_zero; + + if (access("/dev/zero", F_OK)) + SKIP(return, "No /dev/zero."); + fd_zero =3D open("/dev/zero", O_RDWR); + ASSERT_NE(fd_zero, -1); + + /* + * Map a MAP_PRIVATE mapping of /dev/zero with page offset 0, then fault + * it in: + * + * |-------------------------------| + * | faulted | + * |-------------------------------| + */ + ptr =3D mmap(carveout, 15 * page_size, PROT_READ | PROT_WRITE, + MAP_FIXED | MAP_PRIVATE, fd_zero, 0); + ASSERT_NE(ptr, MAP_FAILED); + memset(ptr, 'x', 15 * page_size); + + /* + * Unmap the middle: + * + * |---------| |---------| + * | faulted | | faulted | + * |---------| |---------| + */ + ASSERT_EQ(munmap(&ptr[5 * page_size], 5 * page_size), 0); + + /* + * Map in a new unfaulted mapping in the middle with page offset 0 - + * this should merge and would not if it were treated as a file rather + * than pure anon: + * + * |---------|-----------|---------| + * | faulted | unfaulted | faulted | + * |---------|-----------|---------| + */ + ptr2 =3D mmap(&carveout[5 * page_size], 5 * page_size, + PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, + fd_zero, 0); + close(fd_zero); + ASSERT_NE(ptr2, MAP_FAILED); + + /* Assert that they merged. */ + ASSERT_TRUE(find_vma_procmap(procmap, ptr)); + ASSERT_EQ(procmap->query.vma_start, (unsigned long)ptr); + ASSERT_EQ(procmap->query.vma_end, (unsigned long)ptr + 15 * page_size); +} + TEST_F(merge_with_fork, mremap_faulted_to_unfaulted_prev) { struct procmap_fd *procmap =3D &self->procmap; --=20 2.55.0