On 15/04/2024 15:21, Amit Daniel Kachhap wrote:
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);
do_mmap() returns an address. I suppose we need to use the same logic as in ksys_mmap_pgoff() to return a capability.
Kevin
- *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);