The address argument in struct file_operations.get_unmapped_area() function is unsigned long. However, PCuABI requirements need full capability details to be passed to this generic function get_unmapped_area(). This will help to implement the different PCuABI constraints in the low-level handler generic_get_unmapped_area*.
Note that this is a non-functional change for non-purecap cases which still pass the argument as unsigned long. Also, this commit is not exhaustive at the moment.
Signed-off-by: Amit Daniel Kachhap amitdaniel.kachhap@arm.com --- drivers/char/mem.c | 2 +- fs/hugetlbfs/inode.c | 2 +- fs/proc/inode.c | 4 ++-- fs/ramfs/file-mmu.c | 2 +- include/linux/fs.h | 2 +- include/linux/huge_mm.h | 2 +- include/linux/mm.h | 2 +- include/linux/mm_types.h | 2 +- include/linux/proc_fs.h | 2 +- include/linux/sched/mm.h | 8 ++++---- include/linux/shmem_fs.h | 2 +- io_uring/io_uring.c | 2 +- ipc/shm.c | 2 +- mm/huge_memory.c | 2 +- mm/mmap.c | 17 ++++++++++------- mm/shmem.c | 4 ++-- 16 files changed, 30 insertions(+), 27 deletions(-)
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index f494d31f2b98..332a1276b9fc 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -548,7 +548,7 @@ static int mmap_zero(struct file *file, struct vm_area_struct *vma) }
static unsigned long get_unmapped_area_zero(struct file *file, - unsigned long addr, unsigned long len, + user_uintptr_t addr, unsigned long len, unsigned long pgoff, unsigned long flags) { #ifdef CONFIG_MMU diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index ecfdfb2529a3..63457f1f9b60 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -274,7 +274,7 @@ generic_hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
#ifndef HAVE_ARCH_HUGETLB_UNMAPPED_AREA static unsigned long -hugetlb_get_unmapped_area(struct file *file, unsigned long addr, +hugetlb_get_unmapped_area(struct file *file, user_uintptr_t addr, unsigned long len, unsigned long pgoff, unsigned long flags) { diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 8bc77efd6244..abe54ba79759 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -453,7 +453,7 @@ static int proc_reg_mmap(struct file *file, struct vm_area_struct *vma) }
static unsigned long -pde_get_unmapped_area(struct proc_dir_entry *pde, struct file *file, unsigned long orig_addr, +pde_get_unmapped_area(struct proc_dir_entry *pde, struct file *file, user_uintptr_t orig_addr, unsigned long len, unsigned long pgoff, unsigned long flags) { @@ -470,7 +470,7 @@ pde_get_unmapped_area(struct proc_dir_entry *pde, struct file *file, unsigned lo }
static unsigned long -proc_reg_get_unmapped_area(struct file *file, unsigned long orig_addr, +proc_reg_get_unmapped_area(struct file *file, user_uintptr_t orig_addr, unsigned long len, unsigned long pgoff, unsigned long flags) { diff --git a/fs/ramfs/file-mmu.c b/fs/ramfs/file-mmu.c index 12af0490322f..deec4fac8a13 100644 --- a/fs/ramfs/file-mmu.c +++ b/fs/ramfs/file-mmu.c @@ -32,7 +32,7 @@ #include "internal.h"
static unsigned long ramfs_mmu_get_unmapped_area(struct file *file, - unsigned long addr, unsigned long len, unsigned long pgoff, + user_uintptr_t addr, unsigned long len, unsigned long pgoff, unsigned long flags) { return current->mm->get_unmapped_area(file, addr, len, pgoff, flags); diff --git a/include/linux/fs.h b/include/linux/fs.h index 8f2952e298a8..affd05163686 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1794,7 +1794,7 @@ struct file_operations { int (*fasync) (int, struct file *, int); int (*lock) (struct file *, int, struct file_lock *); ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); - unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); + unsigned long (*get_unmapped_area)(struct file *, user_uintptr_t, unsigned long, unsigned long, unsigned long); int (*check_flags)(int); int (*flock) (struct file *, int, struct file_lock *); ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h index 20284387b841..a322bf196ac7 100644 --- a/include/linux/huge_mm.h +++ b/include/linux/huge_mm.h @@ -140,7 +140,7 @@ bool hugepage_vma_check(struct vm_area_struct *vma, unsigned long vm_flags, (transparent_hugepage_flags & \ (1<<TRANSPARENT_HUGEPAGE_USE_ZERO_PAGE_FLAG))
-unsigned long thp_get_unmapped_area(struct file *filp, unsigned long addr, +unsigned long thp_get_unmapped_area(struct file *filp, user_uintptr_t addr, unsigned long len, unsigned long pgoff, unsigned long flags);
void prep_transhuge_page(struct page *page); diff --git a/include/linux/mm.h b/include/linux/mm.h index c1f4996a957f..a4b7381b4977 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -3135,7 +3135,7 @@ extern int install_special_mapping(struct mm_struct *mm, unsigned long randomize_stack_top(unsigned long stack_top); unsigned long randomize_page(unsigned long start, unsigned long range);
-extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); +extern unsigned long get_unmapped_area(struct file *, user_uintptr_t, unsigned long, unsigned long, unsigned long);
extern unsigned long mmap_region(struct file *file, unsigned long addr, unsigned long len, vm_flags_t vm_flags, unsigned long pgoff, diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 38bad6b201ca..487389d5a33e 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -591,7 +591,7 @@ struct mm_struct { struct maple_tree mm_mt; #ifdef CONFIG_MMU unsigned long (*get_unmapped_area) (struct file *filp, - unsigned long addr, unsigned long len, + user_uintptr_t addr, unsigned long len, unsigned long pgoff, unsigned long flags); #endif unsigned long mmap_base; /* base of mmap area */ diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 6a2cabec118d..cbe40e5ad8d0 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -41,7 +41,7 @@ struct proc_ops { long (*proc_compat_ioctl)(struct file *, unsigned int, unsigned long); #endif int (*proc_mmap)(struct file *, struct vm_area_struct *); - unsigned long (*proc_get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); + unsigned long (*proc_get_unmapped_area)(struct file *, user_uintptr_t, unsigned long, unsigned long, unsigned long); } __randomize_layout;
/* definitions for hide_pid field */ diff --git a/include/linux/sched/mm.h b/include/linux/sched/mm.h index 8d89c8c4fac1..3385ac9cd298 100644 --- a/include/linux/sched/mm.h +++ b/include/linux/sched/mm.h @@ -179,19 +179,19 @@ static inline void mm_update_next_owner(struct mm_struct *mm) extern void arch_pick_mmap_layout(struct mm_struct *mm, struct rlimit *rlim_stack); extern unsigned long -arch_get_unmapped_area(struct file *, unsigned long, unsigned long, +arch_get_unmapped_area(struct file *, user_uintptr_t, unsigned long, unsigned long, unsigned long); extern unsigned long -arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr, +arch_get_unmapped_area_topdown(struct file *filp, user_uintptr_t addr, unsigned long len, unsigned long pgoff, unsigned long flags);
unsigned long -generic_get_unmapped_area(struct file *filp, unsigned long addr, +generic_get_unmapped_area(struct file *filp, user_uintptr_t addr, unsigned long len, unsigned long pgoff, unsigned long flags); unsigned long -generic_get_unmapped_area_topdown(struct file *filp, unsigned long addr, +generic_get_unmapped_area_topdown(struct file *filp, user_uintptr_t addr, unsigned long len, unsigned long pgoff, unsigned long flags); #else diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h index 9029abd29b1c..233617830711 100644 --- a/include/linux/shmem_fs.h +++ b/include/linux/shmem_fs.h @@ -73,7 +73,7 @@ extern struct file *shmem_kernel_file_setup(const char *name, loff_t size, extern struct file *shmem_file_setup_with_mnt(struct vfsmount *mnt, const char *name, loff_t size, unsigned long flags); extern int shmem_zero_setup(struct vm_area_struct *); -extern unsigned long shmem_get_unmapped_area(struct file *, unsigned long addr, +extern unsigned long shmem_get_unmapped_area(struct file *, user_uintptr_t addr, unsigned long len, unsigned long pgoff, unsigned long flags); extern int shmem_lock(struct file *file, int lock, struct ucounts *ucounts); #ifdef CONFIG_SHMEM diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c index 37c3a1a6cc76..5c9c9e768788 100644 --- a/io_uring/io_uring.c +++ b/io_uring/io_uring.c @@ -3468,7 +3468,7 @@ static __cold int io_uring_mmap(struct file *file, struct vm_area_struct *vma) }
static unsigned long io_uring_mmu_get_unmapped_area(struct file *filp, - unsigned long addr, unsigned long len, + user_uintptr_t addr, unsigned long len, unsigned long pgoff, unsigned long flags) { const unsigned long mmap_end = arch_get_mmap_end(addr, len, flags); diff --git a/ipc/shm.c b/ipc/shm.c index 16b75e8bcda1..447b8dcd95df 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -647,7 +647,7 @@ static long shm_fallocate(struct file *file, int mode, loff_t offset, }
static unsigned long shm_get_unmapped_area(struct file *file, - unsigned long addr, unsigned long len, unsigned long pgoff, + user_uintptr_t addr, unsigned long len, unsigned long pgoff, unsigned long flags) { struct shm_file_data *sfd = shm_file_data(file); diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 624671aaa60d..e67b474efac7 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -634,7 +634,7 @@ static unsigned long __thp_get_unmapped_area(struct file *filp, return ret; }
-unsigned long thp_get_unmapped_area(struct file *filp, unsigned long addr, +unsigned long thp_get_unmapped_area(struct file *filp, user_uintptr_t addr, unsigned long len, unsigned long pgoff, unsigned long flags) { unsigned long ret; diff --git a/mm/mmap.c b/mm/mmap.c index bc422cc4a14b..7f2246cbc969 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1679,13 +1679,14 @@ unsigned long vm_unmapped_area(struct vm_unmapped_area_info *info) * This function "knows" that -ENOMEM has the bits set. */ unsigned long -generic_get_unmapped_area(struct file *filp, unsigned long addr, +generic_get_unmapped_area(struct file *filp, user_uintptr_t user_ptr, unsigned long len, unsigned long pgoff, unsigned long flags) { struct mm_struct *mm = current->mm; struct vm_area_struct *vma, *prev; struct vm_unmapped_area_info info; + unsigned long addr = (ptraddr_t)user_ptr; const unsigned long mmap_end = arch_get_mmap_end(addr, len, flags);
if (len > mmap_end - mmap_min_addr) @@ -1714,7 +1715,7 @@ generic_get_unmapped_area(struct file *filp, unsigned long addr,
#ifndef HAVE_ARCH_UNMAPPED_AREA unsigned long -arch_get_unmapped_area(struct file *filp, unsigned long addr, +arch_get_unmapped_area(struct file *filp, user_uintptr_t addr, unsigned long len, unsigned long pgoff, unsigned long flags) { @@ -1727,13 +1728,14 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, * stack's low limit (the base): */ unsigned long -generic_get_unmapped_area_topdown(struct file *filp, unsigned long addr, +generic_get_unmapped_area_topdown(struct file *filp, user_uintptr_t user_ptr, unsigned long len, unsigned long pgoff, unsigned long flags) { struct vm_area_struct *vma, *prev; struct mm_struct *mm = current->mm; struct vm_unmapped_area_info info; + unsigned long addr = (ptraddr_t)user_ptr; const unsigned long mmap_end = arch_get_mmap_end(addr, len, flags);
/* requested length too big for entire address space */ @@ -1780,7 +1782,7 @@ generic_get_unmapped_area_topdown(struct file *filp, unsigned long addr,
#ifndef HAVE_ARCH_UNMAPPED_AREA_TOPDOWN unsigned long -arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr, +arch_get_unmapped_area_topdown(struct file *filp, user_uintptr_t addr, unsigned long len, unsigned long pgoff, unsigned long flags) { @@ -1789,12 +1791,13 @@ arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr, #endif
unsigned long -get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, +get_unmapped_area(struct file *file, user_uintptr_t user_ptr, unsigned long len, unsigned long pgoff, unsigned long flags) { - unsigned long (*get_area)(struct file *, unsigned long, + unsigned long (*get_area)(struct file *, user_uintptr_t, unsigned long, unsigned long, unsigned long);
+ unsigned long addr = (ptraddr_t)user_ptr; unsigned long error = arch_mmap_check(addr, len, flags); if (error) return error; @@ -1817,7 +1820,7 @@ get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, get_area = shmem_get_unmapped_area; }
- addr = get_area(file, addr, len, pgoff, flags); + addr = get_area(file, user_ptr, len, pgoff, flags); if (IS_ERR_VALUE(addr)) return addr;
diff --git a/mm/shmem.c b/mm/shmem.c index e40a08c5c6d7..36c0b00c1982 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -2170,11 +2170,11 @@ static vm_fault_t shmem_fault(struct vm_fault *vmf) }
unsigned long shmem_get_unmapped_area(struct file *file, - unsigned long uaddr, unsigned long len, + user_uintptr_t uaddr, unsigned long len, unsigned long pgoff, unsigned long flags) { unsigned long (*get_area)(struct file *, - unsigned long, unsigned long, unsigned long, unsigned long); + user_uintptr_t, unsigned long, unsigned long, unsigned long); unsigned long addr; unsigned long offset; unsigned long inflated_len;