From: Amit Daniel Kachhap amitdaniel.kachhap@arm.com
Check that the permissions of the new user pointer does not exceed the permission of old user pointer for the mremap syscall.
Signed-off-by: Amit Daniel Kachhap amitdaniel.kachhap@arm.com --- mm/mremap.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
diff --git a/mm/mremap.c b/mm/mremap.c index 78858a167242..6e9598a0d73c 100644 --- a/mm/mremap.c +++ b/mm/mremap.c @@ -996,6 +996,20 @@ static int vma_expandable(struct vm_area_struct *vma, unsigned long delta) return 1; }
+static int check_mremap_user_ptr_perms(user_uintptr_t user_ptr, user_uintptr_t new_user_ptr, + unsigned long flags) +{ +#ifdef CONFIG_CHERI_PURECAP_UABI + if (!reserv_is_supported(current->mm) || !(flags & MREMAP_FIXED)) + return 0; + + if ((cheri_perms_get(user_ptr) | cheri_perms_get(new_user_ptr)) + != cheri_perms_get(user_ptr)) + return -EINVAL; +#endif + return 0; +} + /* * Expand (or shrink) an existing mapping, potentially moving it at the * same time (controlled by the MREMAP_MAYMOVE flag and available VM space) @@ -1074,6 +1088,9 @@ SYSCALL_DEFINE5(__retptr__(mremap), user_uintptr_t, user_ptr, unsigned long, old goto out; } ret = check_pcuabi_map_ptr_arg(new_user_ptr, new_len, flags & MREMAP_FIXED, true); + if (ret) + goto out; + ret = check_mremap_user_ptr_perms(user_ptr, new_user_ptr, flags); if (ret) goto out;