Use the recently introduced PCuABI reservation interfaces to verify the address range for shmat syscall.
Signed-off-by: Amit Daniel Kachhap amitdaniel.kachhap@arm.com --- include/linux/shm.h | 4 ++-- ipc/shm.c | 27 ++++++++++++++++----------- 2 files changed, 18 insertions(+), 13 deletions(-)
diff --git a/include/linux/shm.h b/include/linux/shm.h index d8e69aed3d32..bf5b2e5cbd0c 100644 --- a/include/linux/shm.h +++ b/include/linux/shm.h @@ -14,7 +14,7 @@ struct sysv_shm { struct list_head shm_clist; };
-long do_shmat(int shmid, char __user *shmaddr, int shmflg, unsigned long *addr, +long do_shmat(int shmid, char __user *shmaddr, int shmflg, user_uintptr_t *user_ptr, unsigned long shmlba); bool is_file_shm_hugepages(struct file *file); void exit_shm(struct task_struct *task); @@ -25,7 +25,7 @@ struct sysv_shm { };
static inline long do_shmat(int shmid, char __user *shmaddr, - int shmflg, unsigned long *addr, + int shmflg, user_uintptr_t *user_ptr, unsigned long shmlba) { return -ENOSYS; diff --git a/ipc/shm.c b/ipc/shm.c index 7bb7c4bbc383..231b68d6c281 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -44,6 +44,7 @@ #include <linux/mount.h> #include <linux/ipc_namespace.h> #include <linux/rhashtable.h> +#include <linux/cap_addr_mgmt.h>
#include <linux/uaccess.h>
@@ -1519,14 +1520,13 @@ COMPAT_SYSCALL_DEFINE3(old_shmctl, int, shmid, int, cmd, void __user *, uptr) * Fix shmaddr, allocate descriptor, map shm, add attach descriptor to lists. * * NOTE! Despite the name, this is NOT a direct system call entrypoint. The - * "raddr" thing points to kernel space, and there has to be a wrapper around + * "ruser_ptr" thing points to kernel space, and there has to be a wrapper around * this. */ long do_shmat(int shmid, char __user *shmaddr, int shmflg, - ulong *raddr, unsigned long shmlba) + user_uintptr_t *ruser_ptr, unsigned long shmlba) { struct shmid_kernel *shp; - /* TODO [PCuABI] - capability checks for address space management */ unsigned long addr = user_ptr_addr(shmaddr); unsigned long size; struct file *file, *base; @@ -1538,6 +1538,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, struct shm_file_data *sfd; int f_flags; unsigned long populate = 0; + user_uintptr_t user_ptr = (user_uintptr_t)shmaddr;
err = -EINVAL; if (shmid < 0) @@ -1666,11 +1667,16 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, goto invalid; }
- addr = do_mmap(file, addr, size, prot, flags, 0, 0, &populate, NULL); - *raddr = addr; + user_ptr = (user_uintptr_t)user_ptr_set_addr(shmaddr, addr); + err = check_pcuabi_params(user_ptr, size, MAP_FIXED, false, false, true); + if (err) + goto invalid; + + user_ptr = do_mmap(file, user_ptr, size, prot, flags, 0, 0, &populate, NULL); + *ruser_ptr = user_ptr; err = 0; - if (IS_ERR_VALUE(addr)) - err = (long)addr; + if (IS_ERR_VALUE(user_ptr)) + err = (long)user_ptr; invalid: mmap_write_unlock(current->mm); if (populate) @@ -1699,15 +1705,14 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg,
SYSCALL_DEFINE3(__retptr__(shmat), int, shmid, char __user *, shmaddr, int, shmflg) { - unsigned long ret; + user_uintptr_t ret; long err;
err = do_shmat(shmid, shmaddr, shmflg, &ret, SHMLBA); if (err) return err; force_successful_syscall_return(); - /* TODO [PCuABI] - derive proper capability */ - return (user_uintptr_t)uaddr_to_user_ptr_safe(ret); + return ret; }
#ifdef CONFIG_COMPAT @@ -1718,7 +1723,7 @@ SYSCALL_DEFINE3(__retptr__(shmat), int, shmid, char __user *, shmaddr, int, shmf
COMPAT_SYSCALL_DEFINE3(shmat, int, shmid, compat_uptr_t, shmaddr, int, shmflg) { - unsigned long ret; + user_uintptr_t ret; long err;
err = do_shmat(shmid, compat_ptr(shmaddr), shmflg, &ret, COMPAT_SHMLBA);