summaryrefslogtreecommitdiff
path: root/tools/testing
diff options
context:
space:
mode:
authorLorenzo Stoakes (ARM) <ljs@kernel.org>2026-07-20 15:38:38 +0100
committerAndrew Morton <akpm@linux-foundation.org>2026-07-26 22:50:24 -0700
commit2b1e950447ae74ccca4e349f03e1bb7a32991fa2 (patch)
tree14b1f2c38a80aa4065b4edb654b05da78665819a /tools/testing
parentc2f917154d1010f642716dd09dab0851ec96c9e2 (diff)
downloadlinux-next-2b1e950447ae74ccca4e349f03e1bb7a32991fa2.tar.gz
linux-next-2b1e950447ae74ccca4e349f03e1bb7a32991fa2.zip
mm/vma: only permit MAP_PRIVATE /dev/zero to be mapped anonymous
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. Make it possible to explicitly identify /dev/zero by setting a global DEVZERO_MINOR device minor number then explicitly check for this in mmap code for a MAP_PRIVATE mapping and only set the VMA anonymous if we have positively identified it. 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 mark the VMA anonymous. 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. 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. Also update the VMA userland tests to reflect the change. Link: https://lore.kernel.org/20260720-b4-scalable-cow-virt-pgoff-v2-12-2d549757a76f@kernel.org Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org> Cc: Alistair Popple <apopple@nvidia.com> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Baolin Wang <baolin.wang@linux.alibaba.com> Cc: Barry Song <baohua@kernel.org> Cc: Byungchul Park <byungchul@sk.com> Cc: Chengming Zhou <chengming.zhou@linux.dev> Cc: David Hildenbrand <david@kernel.org> Cc: Dev Jain <dev.jain@arm.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Gregory Price <gourry@gourry.net> Cc: Harry Yoo <harry@kernel.org> Cc: "Huang, Ying" <ying.huang@linux.alibaba.com> Cc: Jan Kara <jack@suse.cz> Cc: Jann Horn <jannh@google.com> Cc: Joshua Hahn <joshua.hahnjy@gmail.com> Cc: Kees Cook <kees@kernel.org> Cc: Lance Yang <lance.yang@linux.dev> Cc: Liam R. Howlett <liam@infradead.org> Cc: Matthew Brost <matthew.brost@intel.com> Cc: Matthew Wilcox (Oracle) <willy@infradead.org> Cc: Miaohe Lin <linmiaohe@huawei.com> Cc: Michal Hocko <mhocko@suse.com> Cc: Mike Rapoport <rppt@kernel.org> Cc: Naoya Horiguchi <nao.horiguchi@gmail.com> Cc: Nico Pache <npache@redhat.com> Cc: Pedro Falcato <pfalcato@suse.de> Cc: Peter Xu <peterx@redhat.com> Cc: Rakie Kim <rakie.kim@sk.com> Cc: Rik van Riel <riel@surriel.com> Cc: Ryan Roberts <ryan.roberts@arm.com> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Vlastimil Babka <vbabka@kernel.org> Cc: xu xin <xu.xin16@zte.com.cn> Cc: Zi Yan <ziy@nvidia.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Diffstat (limited to 'tools/testing')
-rw-r--r--tools/testing/vma/include/dup.h36
1 files changed, 36 insertions, 0 deletions
diff --git a/tools/testing/vma/include/dup.h b/tools/testing/vma/include/dup.h
index a4a0e2b40504..a5b673b06ee6 100644
--- a/tools/testing/vma/include/dup.h
+++ b/tools/testing/vma/include/dup.h
@@ -15,6 +15,20 @@ struct task_struct *get_current(void);
#define MMF_HAS_MDWE 28
#define current get_current()
+#define MINORBITS 20
+#define MINORMASK ((1U << MINORBITS) - 1)
+
+#define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS))
+#define MINOR(dev) ((unsigned int) ((dev) & MINORMASK))
+
+#define S_IFMT 00170000
+#define S_IFCHR 0020000
+
+#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+
+#define MEM_MAJOR 1
+#define DEVZERO_MINOR 5
+
/*
* Define the task command name length as enum, then it can be visible to
* BPF programs.
@@ -23,6 +37,8 @@ enum {
TASK_COMM_LEN = 16,
};
+typedef unsigned short umode_t;
+
/* PARTIALLY implemented types. */
struct mm_struct {
struct maple_tree mm_mt;
@@ -45,6 +61,10 @@ struct address_space {
unsigned long flags;
atomic_t i_mmap_writable;
};
+struct inode {
+ umode_t i_mode;
+ dev_t i_rdev;
+};
struct file_operations {
int (*mmap)(struct file *, struct vm_area_struct *);
int (*mmap_prepare)(struct vm_area_desc *);
@@ -52,6 +72,7 @@ struct file_operations {
struct file {
struct address_space *f_mapping;
const struct file_operations *f_op;
+ struct inode *f_inode;
};
struct anon_vma_chain {
struct anon_vma *anon_vma;
@@ -1633,3 +1654,18 @@ static inline pgoff_t linear_virt_page_index(const struct vm_area_struct *vma,
return pgoff;
}
+
+static inline struct inode *file_inode(const struct file *f)
+{
+ return f->f_inode;
+}
+
+static inline unsigned iminor(const struct inode *inode)
+{
+ return MINOR(inode->i_rdev);
+}
+
+static inline unsigned imajor(const struct inode *inode)
+{
+ return MAJOR(inode->i_rdev);
+}