Revert "mm: resolve faulty mmap_region() error path behaviour"

This reverts commit bdc136e2b0.

[surenb: preserved trace_android_vh_mmap_region() during the revert]

Bug: 409148564
Bug: 408888654
Change-Id: I6d8dddc0dba935da6bd956d70bee76b4c1f77286
Signed-off-by: Suren Baghdasaryan <surenb@google.com>
This commit is contained in:
Suren Baghdasaryan
2025-04-18 19:57:38 +00:00
committed by Todd Kjos
parent a3b47b4bc7
commit 8a34ab3c95

115
mm/mmap.c
View File

@@ -2703,14 +2703,14 @@ int do_munmap(struct mm_struct *mm, unsigned long start, size_t len,
return do_vmi_munmap(&vmi, mm, start, len, uf, false);
}
static unsigned long __mmap_region(struct file *file, unsigned long addr,
unsigned long mmap_region(struct file *file, unsigned long addr,
unsigned long len, vm_flags_t vm_flags, unsigned long pgoff,
struct list_head *uf)
{
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma = NULL;
struct vm_area_struct *next, *prev, *merge;
pgoff_t pglen = PHYS_PFN(len);
pgoff_t pglen = len >> PAGE_SHIFT;
unsigned long charged = 0;
unsigned long end = addr + len;
unsigned long merge_start = addr, merge_end = end;
@@ -2810,26 +2810,25 @@ cannot_expand:
vma->vm_page_prot = vm_get_page_prot(vm_flags);
vma->vm_pgoff = pgoff;
if (vma_iter_prealloc(&vmi, vma)) {
error = -ENOMEM;
goto free_vma;
}
if (file) {
if (vm_flags & VM_SHARED) {
error = mapping_map_writable(file->f_mapping);
if (error)
goto free_vma;
}
vma->vm_file = get_file(file);
error = mmap_file(file, vma);
if (error)
goto unmap_and_free_file_vma;
goto unmap_and_free_vma;
/* Drivers cannot alter the address of the VMA. */
WARN_ON_ONCE(addr != vma->vm_start);
/*
* Drivers should not permit writability when previously it was
* disallowed.
* Expansion is handled above, merging is handled below.
* Drivers should not alter the address of the VMA.
*/
VM_WARN_ON_ONCE(vm_flags != vma->vm_flags &&
!(vm_flags & VM_MAYWRITE) &&
(vma->vm_flags & VM_MAYWRITE));
error = -EINVAL;
if (WARN_ON((addr != vma->vm_start)))
goto close_and_free_vma;
vma_iter_config(&vmi, addr, end);
/*
@@ -2841,7 +2840,6 @@ cannot_expand:
vma->vm_end, vma->vm_flags, NULL,
vma->vm_file, vma->vm_pgoff, NULL,
NULL_VM_UFFD_CTX, NULL);
if (merge) {
/*
* ->mmap() can change vma->vm_file and fput
@@ -2855,7 +2853,7 @@ cannot_expand:
vma = merge;
/* Update vm_flags to pick up the change. */
vm_flags = vma->vm_flags;
goto file_expanded;
goto unmap_writable;
}
}
@@ -2863,15 +2861,24 @@ cannot_expand:
} else if (vm_flags & VM_SHARED) {
error = shmem_zero_setup(vma);
if (error)
goto free_iter_vma;
goto free_vma;
} else {
vma_set_anonymous(vma);
}
#ifdef CONFIG_SPARC64
/* TODO: Fix SPARC ADI! */
WARN_ON_ONCE(!arch_validate_flags(vm_flags));
#endif
if (map_deny_write_exec(vma->vm_flags, vma->vm_flags)) {
error = -EACCES;
goto close_and_free_vma;
}
/* Allow architectures to sanity-check the vm_flags */
error = -EINVAL;
if (!arch_validate_flags(vma->vm_flags))
goto close_and_free_vma;
error = -ENOMEM;
if (vma_iter_prealloc(&vmi, vma))
goto close_and_free_vma;
/* Lock the VMA since it is modified after insertion into VMA tree */
vma_start_write(vma);
@@ -2894,7 +2901,10 @@ cannot_expand:
*/
khugepaged_enter_vma(vma, vma->vm_flags);
file_expanded:
/* Once vma denies write, undo our temporary denial count */
unmap_writable:
if (file && vm_flags & VM_SHARED)
mapping_unmap_writable(file->f_mapping);
file = vma->vm_file;
ksm_add_vma(vma);
expanded:
@@ -2926,60 +2936,33 @@ expanded:
trace_android_vh_mmap_region(vma, addr);
validate_mm(mm);
return addr;
unmap_and_free_file_vma:
fput(vma->vm_file);
vma->vm_file = NULL;
close_and_free_vma:
vma_close(vma);
vma_iter_set(&vmi, vma->vm_end);
/* Undo any partial mapping done by a device driver. */
unmap_region(mm, &vmi.mas, vma, prev, next, vma->vm_start,
vma->vm_end, vma->vm_end, true);
free_iter_vma:
vma_iter_free(&vmi);
if (file || vma->vm_file) {
unmap_and_free_vma:
fput(vma->vm_file);
vma->vm_file = NULL;
vma_iter_set(&vmi, vma->vm_end);
/* Undo any partial mapping done by a device driver. */
unmap_region(mm, &vmi.mas, vma, prev, next, vma->vm_start,
vma->vm_end, vma->vm_end, true);
}
if (file && (vm_flags & VM_SHARED))
mapping_unmap_writable(file->f_mapping);
free_vma:
vm_area_free(vma);
unacct_error:
if (charged)
vm_unacct_memory(charged);
validate_mm(mm);
return error;
}
unsigned long mmap_region(struct file *file, unsigned long addr,
unsigned long len, vm_flags_t vm_flags, unsigned long pgoff,
struct list_head *uf)
{
unsigned long ret;
bool writable_file_mapping = false;
/* Check to see if MDWE is applicable. */
if (map_deny_write_exec(vm_flags, vm_flags))
return -EACCES;
/* Allow architectures to sanity-check the vm_flags. */
if (!arch_validate_flags(vm_flags))
return -EINVAL;
/* Map writable and ensure this isn't a sealed memfd. */
if (file && (vm_flags & VM_SHARED)) {
int error = mapping_map_writable(file->f_mapping);
if (error)
return error;
writable_file_mapping = true;
}
ret = __mmap_region(file, addr, len, vm_flags, pgoff, uf);
/* Clear our write mapping regardless of error. */
if (writable_file_mapping)
mapping_unmap_writable(file->f_mapping);
validate_mm(current->mm);
return ret;
}
static int __vm_munmap(unsigned long start, size_t len, bool unlock)
{
int ret;