Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mm: consistently use current->mm in mm_get_unmapped_area()

mm_get_unmapped_area() is a wrapper around arch_get_unmapped_area() /
arch_get_unmapped_area_topdown(), both of which search current->mm for
some free space. Neither take an mm_struct - they implicitly operate on
current->mm.

But the wrapper takes an mm_struct and uses it to decide whether to search
bottom up or top down. All callers pass in current->mm for this, so
everything is working consistently. But it feels like an accident waiting
to happen; eventually someone will call that function with a different mm,
expecting to find free space in it, but what gets returned is free space
in the current mm.

So let's simplify by removing the parameter and have the wrapper use
current->mm to decide which end to start at. Now everything is consistent
and self-documenting.

Link: https://lkml.kernel.org/r/20251003155306.2147572-1-ryan.roberts@arm.com
Signed-off-by: Ryan Roberts <ryan.roberts@arm.com>
Acked-by: David Hildenbrand <david@redhat.com>
Reviewed-by: Oscar Salvador <osalvador@suse.de>
Reviewed-by: Dev Jain <dev.jain@arm.com>
Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com>
Reviewed-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>
Cc: Liam Howlett <liam.howlett@oracle.com>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Ryan Roberts and committed by
Andrew Morton
9ac09bb9 0fdaa13e

+29 -37
+3 -3
arch/sparc/kernel/sys_sparc_64.c
··· 241 241 242 242 if (flags & MAP_FIXED) { 243 243 /* Ok, don't mess with it. */ 244 - return mm_get_unmapped_area(current->mm, NULL, orig_addr, len, pgoff, flags); 244 + return mm_get_unmapped_area(NULL, orig_addr, len, pgoff, flags); 245 245 } 246 246 flags &= ~MAP_SHARED; 247 247 ··· 254 254 align_goal = (64UL * 1024); 255 255 256 256 do { 257 - addr = mm_get_unmapped_area(current->mm, NULL, orig_addr, 257 + addr = mm_get_unmapped_area(NULL, orig_addr, 258 258 len + (align_goal - PAGE_SIZE), pgoff, flags); 259 259 if (!(addr & ~PAGE_MASK)) { 260 260 addr = (addr + (align_goal - 1UL)) & ~(align_goal - 1UL); ··· 273 273 * be obtained. 274 274 */ 275 275 if (addr & ~PAGE_MASK) 276 - addr = mm_get_unmapped_area(current->mm, NULL, orig_addr, len, pgoff, flags); 276 + addr = mm_get_unmapped_area(NULL, orig_addr, len, pgoff, flags); 277 277 278 278 return addr; 279 279 }
+1 -1
arch/x86/kernel/cpu/sgx/driver.c
··· 113 113 if (flags & MAP_FIXED) 114 114 return addr; 115 115 116 - return mm_get_unmapped_area(current->mm, file, addr, len, pgoff, flags); 116 + return mm_get_unmapped_area(file, addr, len, pgoff, flags); 117 117 } 118 118 119 119 #ifdef CONFIG_COMPAT
+1 -1
drivers/char/mem.c
··· 542 542 #ifdef CONFIG_TRANSPARENT_HUGEPAGE 543 543 return thp_get_unmapped_area(file, addr, len, pgoff, flags); 544 544 #else 545 - return mm_get_unmapped_area(current->mm, file, addr, len, pgoff, flags); 545 + return mm_get_unmapped_area(file, addr, len, pgoff, flags); 546 546 #endif 547 547 } 548 548 #endif /* CONFIG_MMU */
+2 -3
drivers/dax/device.c
··· 330 330 if ((off + len_align) < off) 331 331 goto out; 332 332 333 - addr_align = mm_get_unmapped_area(current->mm, filp, addr, len_align, 334 - pgoff, flags); 333 + addr_align = mm_get_unmapped_area(filp, addr, len_align, pgoff, flags); 335 334 if (!IS_ERR_VALUE(addr_align)) { 336 335 addr_align += (off - addr_align) & (align - 1); 337 336 return addr_align; 338 337 } 339 338 out: 340 - return mm_get_unmapped_area(current->mm, filp, addr, len, pgoff, flags); 339 + return mm_get_unmapped_area(filp, addr, len, pgoff, flags); 341 340 } 342 341 343 342 static const struct address_space_operations dev_dax_aops = {
+1 -2
fs/hugetlbfs/inode.c
··· 184 184 if (addr) 185 185 addr0 = ALIGN(addr, huge_page_size(h)); 186 186 187 - return mm_get_unmapped_area_vmflags(current->mm, file, addr0, len, pgoff, 188 - flags, 0); 187 + return mm_get_unmapped_area_vmflags(file, addr0, len, pgoff, flags, 0); 189 188 } 190 189 191 190 /*
+1 -1
fs/proc/inode.c
··· 443 443 return pde->proc_ops->proc_get_unmapped_area(file, orig_addr, len, pgoff, flags); 444 444 445 445 #ifdef CONFIG_MMU 446 - return mm_get_unmapped_area(current->mm, file, orig_addr, len, pgoff, flags); 446 + return mm_get_unmapped_area(file, orig_addr, len, pgoff, flags); 447 447 #endif 448 448 449 449 return orig_addr;
+1 -1
fs/ramfs/file-mmu.c
··· 35 35 unsigned long addr, unsigned long len, unsigned long pgoff, 36 36 unsigned long flags) 37 37 { 38 - return mm_get_unmapped_area(current->mm, file, addr, len, pgoff, flags); 38 + return mm_get_unmapped_area(file, addr, len, pgoff, flags); 39 39 } 40 40 41 41 const struct file_operations ramfs_file_operations = {
+4 -5
include/linux/sched/mm.h
··· 189 189 unsigned long len, unsigned long pgoff, 190 190 unsigned long flags, vm_flags_t); 191 191 192 - unsigned long mm_get_unmapped_area(struct mm_struct *mm, struct file *filp, 193 - unsigned long addr, unsigned long len, 194 - unsigned long pgoff, unsigned long flags); 192 + unsigned long mm_get_unmapped_area(struct file *filp, unsigned long addr, 193 + unsigned long len, unsigned long pgoff, 194 + unsigned long flags); 195 195 196 - unsigned long mm_get_unmapped_area_vmflags(struct mm_struct *mm, 197 - struct file *filp, 196 + unsigned long mm_get_unmapped_area_vmflags(struct file *filp, 198 197 unsigned long addr, 199 198 unsigned long len, 200 199 unsigned long pgoff,
+1 -1
io_uring/memmap.c
··· 387 387 #else 388 388 addr = 0UL; 389 389 #endif 390 - return mm_get_unmapped_area(current->mm, filp, addr, len, pgoff, flags); 390 + return mm_get_unmapped_area(filp, addr, len, pgoff, flags); 391 391 } 392 392 393 393 #else /* !CONFIG_MMU */
+1 -1
kernel/bpf/arena.c
··· 334 334 return -EINVAL; 335 335 } 336 336 337 - ret = mm_get_unmapped_area(current->mm, filp, addr, len * 2, 0, flags); 337 + ret = mm_get_unmapped_area(filp, addr, len * 2, 0, flags); 338 338 if (IS_ERR_VALUE(ret)) 339 339 return ret; 340 340 if ((ret >> 32) == ((ret + len - 1) >> 32))
+1 -1
kernel/bpf/syscall.c
··· 1162 1162 if (map->ops->map_get_unmapped_area) 1163 1163 return map->ops->map_get_unmapped_area(filp, addr, len, pgoff, flags); 1164 1164 #ifdef CONFIG_MMU 1165 - return mm_get_unmapped_area(current->mm, filp, addr, len, pgoff, flags); 1165 + return mm_get_unmapped_area(filp, addr, len, pgoff, flags); 1166 1166 #else 1167 1167 return addr; 1168 1168 #endif
+2 -2
mm/huge_memory.c
··· 1127 1127 if (len_pad < len || (off + len_pad) < off) 1128 1128 return 0; 1129 1129 1130 - ret = mm_get_unmapped_area_vmflags(current->mm, filp, addr, len_pad, 1130 + ret = mm_get_unmapped_area_vmflags(filp, addr, len_pad, 1131 1131 off >> PAGE_SHIFT, flags, vm_flags); 1132 1132 1133 1133 /* ··· 1164 1164 if (ret) 1165 1165 return ret; 1166 1166 1167 - return mm_get_unmapped_area_vmflags(current->mm, filp, addr, len, pgoff, flags, 1167 + return mm_get_unmapped_area_vmflags(filp, addr, len, pgoff, flags, 1168 1168 vm_flags); 1169 1169 } 1170 1170
+7 -10
mm/mmap.c
··· 797 797 } 798 798 #endif 799 799 800 - unsigned long mm_get_unmapped_area_vmflags(struct mm_struct *mm, struct file *filp, 801 - unsigned long addr, unsigned long len, 802 - unsigned long pgoff, unsigned long flags, 803 - vm_flags_t vm_flags) 800 + unsigned long mm_get_unmapped_area_vmflags(struct file *filp, unsigned long addr, 801 + unsigned long len, unsigned long pgoff, 802 + unsigned long flags, vm_flags_t vm_flags) 804 803 { 805 - if (mm_flags_test(MMF_TOPDOWN, mm)) 804 + if (mm_flags_test(MMF_TOPDOWN, current->mm)) 806 805 return arch_get_unmapped_area_topdown(filp, addr, len, pgoff, 807 806 flags, vm_flags); 808 807 return arch_get_unmapped_area(filp, addr, len, pgoff, flags, vm_flags); ··· 847 848 addr = thp_get_unmapped_area_vmflags(file, addr, len, 848 849 pgoff, flags, vm_flags); 849 850 } else { 850 - addr = mm_get_unmapped_area_vmflags(current->mm, file, addr, len, 851 + addr = mm_get_unmapped_area_vmflags(file, addr, len, 851 852 pgoff, flags, vm_flags); 852 853 } 853 854 if (IS_ERR_VALUE(addr)) ··· 863 864 } 864 865 865 866 unsigned long 866 - mm_get_unmapped_area(struct mm_struct *mm, struct file *file, 867 - unsigned long addr, unsigned long len, 867 + mm_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, 868 868 unsigned long pgoff, unsigned long flags) 869 869 { 870 - return mm_get_unmapped_area_vmflags(mm, file, addr, len, 871 - pgoff, flags, 0); 870 + return mm_get_unmapped_area_vmflags(file, addr, len, pgoff, flags, 0); 872 871 } 873 872 EXPORT_SYMBOL(mm_get_unmapped_area); 874 873
+3 -5
mm/shmem.c
··· 2759 2759 if (len > TASK_SIZE) 2760 2760 return -ENOMEM; 2761 2761 2762 - addr = mm_get_unmapped_area(current->mm, file, uaddr, len, pgoff, 2763 - flags); 2762 + addr = mm_get_unmapped_area(file, uaddr, len, pgoff, flags); 2764 2763 2765 2764 if (!IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE)) 2766 2765 return addr; ··· 2837 2838 if (inflated_len < len) 2838 2839 return addr; 2839 2840 2840 - inflated_addr = mm_get_unmapped_area(current->mm, NULL, uaddr, 2841 - inflated_len, 0, flags); 2841 + inflated_addr = mm_get_unmapped_area(NULL, uaddr, inflated_len, 0, flags); 2842 2842 if (IS_ERR_VALUE(inflated_addr)) 2843 2843 return addr; 2844 2844 if (inflated_addr & ~PAGE_MASK) ··· 5773 5775 unsigned long addr, unsigned long len, 5774 5776 unsigned long pgoff, unsigned long flags) 5775 5777 { 5776 - return mm_get_unmapped_area(current->mm, file, addr, len, pgoff, flags); 5778 + return mm_get_unmapped_area(file, addr, len, pgoff, flags); 5777 5779 } 5778 5780 #endif 5779 5781