Skip to content

Commit 463b771

Browse files
Gregory PriceKAGA-KOKO
authored andcommitted
syscall_user_dispatch: Untag selector address before access_ok()
To support checkpoint/restart, ptrace must be able to set the selector of the tracee. The selector is a user pointer that may be subject to memory tagging extensions on some architectures (namely ARM MTE). access_ok() clears memory tags for tagged addresses if the current task has memory tagging enabled. This obviously fails when ptrace modifies the selector of a tracee when tracer and tracee do not have the same memory tagging enabled state. Solve this by untagging the selector address before handing it to access_ok(), like other ptrace functions which modify tracee pointers do. Obviously a tracer can set an invalid selector address for the tracee, but that's independent of tagging and a general capability of the tracer. Suggested-by: Catalin Marinas <[email protected]> Signed-off-by: Gregory Price <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Reviewed-by: Catalin Marinas <[email protected]> Acked-by: Oleg Nesterov <[email protected]> Link: https://lore.kernel.org/all/[email protected]/ Link: https://lore.kernel.org/r/[email protected]
1 parent 4336068 commit 463b771

File tree

1 file changed

+10
-1
lines changed

1 file changed

+10
-1
lines changed

kernel/entry/syscall_user_dispatch.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,16 @@ static int task_set_syscall_user_dispatch(struct task_struct *task, unsigned lon
8787
if (offset && offset + len <= offset)
8888
return -EINVAL;
8989

90-
if (selector && !access_ok(selector, sizeof(*selector)))
90+
/*
91+
* access_ok() will clear memory tags for tagged addresses
92+
* if current has memory tagging enabled.
93+
94+
* To enable a tracer to set a tracees selector the
95+
* selector address must be untagged for access_ok(),
96+
* otherwise an untagged tracer will always fail to set a
97+
* tagged tracees selector.
98+
*/
99+
if (selector && !access_ok(untagged_addr(selector), sizeof(*selector)))
91100
return -EFAULT;
92101

93102
break;

0 commit comments

Comments
 (0)