Skip to content

Commit

Permalink
arm64: Validate tagged addresses in access_ok() called from kernel th…
Browse files Browse the repository at this point in the history
…reads

__range_ok(), invoked from access_ok(), clears the tag of the user
address only if CONFIG_ARM64_TAGGED_ADDR_ABI is enabled and the thread
opted in to the relaxed ABI. The latter sets the TIF_TAGGED_ADDR thread
flag. In the case of asynchronous I/O (e.g. io_submit()), the
access_ok() may be called from a kernel thread. Since kernel threads
don't have TIF_TAGGED_ADDR set, access_ok() will fail for valid tagged
user addresses. Example from the ffs_user_copy_worker() thread:

	use_mm(io_data->mm);
	ret = ffs_copy_to_iter(io_data->buf, ret, &io_data->data);
	unuse_mm(io_data->mm);

Relax the __range_ok() check to always untag the user address if called
in the context of a kernel thread. The user pointers would have already
been checked via aio_setup_rw() -> import_{single_range,iovec}() at the
time of the asynchronous I/O request.

Fixes: 63f0c60 ("arm64: Introduce prctl() options to control the tagged user addresses ABI")
Cc: <stable@vger.kernel.org> # 5.4.x-
Cc: Will Deacon <will@kernel.org>
Reported-by: Evgenii Stepanov <eugenis@google.com>
Tested-by: Evgenii Stepanov <eugenis@google.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
  • Loading branch information
Catalin Marinas committed Dec 6, 2019
1 parent cba779d commit df325e0
Showing 1 changed file with 6 additions and 1 deletion.
7 changes: 6 additions & 1 deletion arch/arm64/include/asm/uaccess.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,13 @@ static inline unsigned long __range_ok(const void __user *addr, unsigned long si
{
unsigned long ret, limit = current_thread_info()->addr_limit;

/*
* Asynchronous I/O running in a kernel thread does not have the
* TIF_TAGGED_ADDR flag of the process owning the mm, so always untag
* the user address before checking.
*/
if (IS_ENABLED(CONFIG_ARM64_TAGGED_ADDR_ABI) &&
test_thread_flag(TIF_TAGGED_ADDR))
(current->flags & PF_KTHREAD || test_thread_flag(TIF_TAGGED_ADDR)))
addr = untagged_addr(addr);

__chk_user_ptr(addr);
Expand Down

0 comments on commit df325e0

Please sign in to comment.