When working with PCuABI, a user pointer is a capability carrying metadata such as access bounds and permissions. These are automatically enforced in hardware when a direct access is performed, which triggers a fault if either the bounds or permissions checks failed.
Whenever a futex key is accessed and an access fault occurs, the assumption is that the page containing the futex key must have faulted and the code proceeds to fix it up. Because no distinction is made between a capability fault and a page fault, an explicit capability check needs to be employed so we can fail early and avoid entering an infinite loop attempting to fixup a page fault.
Also, while get_futex_key looks like a valid candidate for an explicit capability check, that is not the case as the user space pointer is never dereferenced as it is instead directly accessed by the futex operations later on.
Signed-off-by: Luca Vizzarro Luca.Vizzarro@arm.com --- kernel/futex/core.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/kernel/futex/core.c b/kernel/futex/core.c index 4b79b5e2ad3b..8efd02515654 100644 --- a/kernel/futex/core.c +++ b/kernel/futex/core.c @@ -226,8 +226,6 @@ int get_futex_key(u32 __user *uaddr, bool fshared, union futex_key *key, struct address_space *mapping; int err, ro = 0;
- /* TODO [PCuABI] - capability checks for uaccess */ - /* * The futex address must be "naturally" aligned. */ @@ -413,7 +411,14 @@ int fault_in_user_writeable(u32 __user *uaddr) struct mm_struct *mm = current->mm; int ret;
- /* TODO [PCuABI] - capability checks for uaccess */ + /* + * When working in PCuABI, we may have reached this point because an + * atomic load/store failed as a consequence of a capability fault + * and not a page fault. To cover this case we should employ an explicit + * check, so that we can fail and return early. + */ + if (!check_user_ptr_rw(uaddr, sizeof(u32))) + return -EFAULT;
mmap_read_lock(mm); ret = fixup_user_fault(mm, user_ptr_addr(uaddr),