mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-29 09:16:33 +00:00
mm/nommu: factor out check for NOMMU shared mappings into is_nommu_shared_mapping()
Patch series "mm/nommu: don't use VM_MAYSHARE for MAP_PRIVATE mappings". Trying to reduce the confusion around VM_SHARED and VM_MAYSHARE first requires !CONFIG_MMU to stop using VM_MAYSHARE for MAP_PRIVATE mappings. CONFIG_MMU only sets VM_MAYSHARE for MAP_SHARED mappings. This paves the way for further VM_MAYSHARE and VM_SHARED cleanups: for example, renaming VM_MAYSHARED to VM_MAP_SHARED to make it cleaner what is actually means. Let's first get the weird case out of the way and not use VM_MAYSHARE in MAP_PRIVATE mappings, using a new VM_MAYOVERLAY flag instead. This patch (of 3): We want to stop using VM_MAYSHARE in private mappings to pave the way for clarifying the semantics of VM_MAYSHARE vs. VM_SHARED and reduce the confusion. While CONFIG_MMU uses VM_MAYSHARE to represent MAP_SHARED, !CONFIG_MMU also sets VM_MAYSHARE for selected R/O private file mappings that are an effective overlay of a file mapping. Let's factor out all relevant VM_MAYSHARE checks in !CONFIG_MMU code into is_nommu_shared_mapping() first. Note that whenever VM_SHARED is set, VM_MAYSHARE must be set as well (unless there is a serious BUG). So there is not need to test for VM_SHARED manually. No functional change intended. Link: https://lkml.kernel.org/r/20230102160856.500584-1-david@redhat.com Link: https://lkml.kernel.org/r/20230102160856.500584-2-david@redhat.com Signed-off-by: David Hildenbrand <david@redhat.com> Cc: Arnd Bergmann <arnd@arndb.de> Cc: David Hildenbrand <david@redhat.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Jens Axboe <axboe@kernel.dk> Cc: Nicolas Pitre <nico@fluxnic.net> Cc: Pavel Begunkov <asml.silence@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
da0618c146
commit
fc4f4be9b5
@ -343,7 +343,7 @@ static unsigned zero_mmap_capabilities(struct file *file)
|
||||
/* can't do an in-place private mapping if there's no MMU */
|
||||
static inline int private_mapping_ok(struct vm_area_struct *vma)
|
||||
{
|
||||
return vma->vm_flags & VM_MAYSHARE;
|
||||
return is_nommu_shared_mapping(vma->vm_flags);
|
||||
}
|
||||
#else
|
||||
|
||||
|
@ -437,7 +437,7 @@ static int cramfs_physmem_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
|
||||
static int cramfs_physmem_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
{
|
||||
return vma->vm_flags & (VM_SHARED | VM_MAYSHARE) ? 0 : -ENOSYS;
|
||||
return is_nommu_shared_mapping(vma->vm_flags) ? 0 : -ENOSYS;
|
||||
}
|
||||
|
||||
static unsigned long cramfs_physmem_get_unmapped_area(struct file *file,
|
||||
|
@ -38,7 +38,7 @@ void task_mem(struct seq_file *m, struct mm_struct *mm)
|
||||
}
|
||||
|
||||
if (atomic_read(&mm->mm_count) > 1 ||
|
||||
vma->vm_flags & VM_MAYSHARE) {
|
||||
is_nommu_shared_mapping(vma->vm_flags)) {
|
||||
sbytes += size;
|
||||
} else {
|
||||
bytes += size;
|
||||
|
@ -264,7 +264,7 @@ static unsigned long ramfs_nommu_get_unmapped_area(struct file *file,
|
||||
*/
|
||||
static int ramfs_nommu_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
{
|
||||
if (!(vma->vm_flags & (VM_SHARED | VM_MAYSHARE)))
|
||||
if (!is_nommu_shared_mapping(vma->vm_flags))
|
||||
return -ENOSYS;
|
||||
|
||||
file_accessed(file);
|
||||
|
@ -63,7 +63,7 @@ static unsigned long romfs_get_unmapped_area(struct file *file,
|
||||
*/
|
||||
static int romfs_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
{
|
||||
return vma->vm_flags & (VM_SHARED | VM_MAYSHARE) ? 0 : -ENOSYS;
|
||||
return is_nommu_shared_mapping(vma->vm_flags) ? 0 : -ENOSYS;
|
||||
}
|
||||
|
||||
static unsigned romfs_mmap_capabilities(struct file *file)
|
||||
|
@ -1347,6 +1347,21 @@ static inline bool is_cow_mapping(vm_flags_t flags)
|
||||
return (flags & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_MMU
|
||||
static inline bool is_nommu_shared_mapping(vm_flags_t flags)
|
||||
{
|
||||
/*
|
||||
* NOMMU shared mappings are ordinary MAP_SHARED mappings and selected
|
||||
* R/O MAP_PRIVATE file mappings that are an effective R/O overlay of
|
||||
* a file mapping. R/O MAP_PRIVATE mappings might still modify
|
||||
* underlying memory if ptrace is active, so this is only possible if
|
||||
* ptrace does not apply. Note that there is no mprotect() to upgrade
|
||||
* write permissions later.
|
||||
*/
|
||||
return flags & VM_MAYSHARE;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SPARSEMEM) && !defined(CONFIG_SPARSEMEM_VMEMMAP)
|
||||
#define SECTION_IN_PAGE_FLAGS
|
||||
#endif
|
||||
|
@ -3206,7 +3206,7 @@ static __cold int io_uring_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
|
||||
static int io_uring_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
{
|
||||
return vma->vm_flags & (VM_SHARED | VM_MAYSHARE) ? 0 : -EINVAL;
|
||||
return is_nommu_shared_mapping(vma->vm_flags) ? 0 : -EINVAL;
|
||||
}
|
||||
|
||||
static unsigned int io_uring_nommu_mmap_capabilities(struct file *file)
|
||||
|
11
mm/nommu.c
11
mm/nommu.c
@ -958,9 +958,10 @@ static int do_mmap_private(struct vm_area_struct *vma,
|
||||
*/
|
||||
if (capabilities & NOMMU_MAP_DIRECT) {
|
||||
ret = call_mmap(vma->vm_file, vma);
|
||||
/* shouldn't return success if we're not sharing */
|
||||
if (WARN_ON_ONCE(!is_nommu_shared_mapping(vma->vm_flags)))
|
||||
ret = -ENOSYS;
|
||||
if (ret == 0) {
|
||||
/* shouldn't return success if we're not sharing */
|
||||
BUG_ON(!(vma->vm_flags & VM_MAYSHARE));
|
||||
vma->vm_region->vm_top = vma->vm_region->vm_end;
|
||||
return 0;
|
||||
}
|
||||
@ -1106,7 +1107,7 @@ unsigned long do_mmap(struct file *file,
|
||||
* these cases, sharing is handled in the driver or filesystem rather
|
||||
* than here
|
||||
*/
|
||||
if (vm_flags & VM_MAYSHARE) {
|
||||
if (is_nommu_shared_mapping(vm_flags)) {
|
||||
struct vm_region *pregion;
|
||||
unsigned long pglen, rpglen, pgend, rpgend, start;
|
||||
|
||||
@ -1116,7 +1117,7 @@ unsigned long do_mmap(struct file *file,
|
||||
for (rb = rb_first(&nommu_region_tree); rb; rb = rb_next(rb)) {
|
||||
pregion = rb_entry(rb, struct vm_region, vm_rb);
|
||||
|
||||
if (!(pregion->vm_flags & VM_MAYSHARE))
|
||||
if (!is_nommu_shared_mapping(pregion->vm_flags))
|
||||
continue;
|
||||
|
||||
/* search for overlapping mappings on the same file */
|
||||
@ -1600,7 +1601,7 @@ static unsigned long do_mremap(unsigned long addr,
|
||||
if (vma->vm_end != vma->vm_start + old_len)
|
||||
return (unsigned long) -EFAULT;
|
||||
|
||||
if (vma->vm_flags & VM_MAYSHARE)
|
||||
if (is_nommu_shared_mapping(vma->vm_flags))
|
||||
return (unsigned long) -EPERM;
|
||||
|
||||
if (new_len > vma->vm_region->vm_end - vma->vm_region->vm_start)
|
||||
|
Loading…
Reference in New Issue
Block a user