Re: [PATCH] arm64: mte: Do not service syscalls after async tag fault

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Dec 19, 2019 at 05:36:39PM -0800, Peter Collingbourne wrote:
> When entering the kernel after an async tag fault due to a syscall, rather
> than for another reason (e.g. preemption), we don't want to service the
> syscall as it may mask the tag fault. Rewind the PC to the svc instruction
> in order to give a userspace signal handler an opportunity to handle the
> fault and resume, and skip all other syscall processing.
> 
> Signed-off-by: Peter Collingbourne <pcc@xxxxxxxxxx>
> ---
[...]
>  arch/arm64/kernel/syscall.c | 22 +++++++++++++++++++---
>  1 file changed, 19 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/arm64/kernel/syscall.c b/arch/arm64/kernel/syscall.c
> index 9a9d98a443fc..49ea9bb47190 100644
> --- a/arch/arm64/kernel/syscall.c
> +++ b/arch/arm64/kernel/syscall.c
> @@ -95,13 +95,29 @@ static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr,
>  {
>  	unsigned long flags = current_thread_info()->flags;
>  
> -	regs->orig_x0 = regs->regs[0];
> -	regs->syscallno = scno;
> -
>  	cortex_a76_erratum_1463225_svc_handler();
>  	local_daif_restore(DAIF_PROCCTX);
>  	user_exit();
>  
> +#ifdef CONFIG_ARM64_MTE
> +	if (flags & _TIF_MTE_ASYNC_FAULT) {
> +		/*
> +		 * We entered the kernel after an async tag fault due to a
> +		 * syscall, rather than for another reason (e.g. preemption).
> +		 * In this case, we don't want to service the syscall as it may
> +		 * mask the tag fault. Rewind the PC to the svc instruction in
> +		 * order to give a userspace signal handler an opportunity to
> +		 * handle the fault and resume, and skip all other syscall
> +		 * processing.
> +		 */
> +		regs->pc -= 4;
> +		return;
> +	}
> +#endif
> +
> +	regs->orig_x0 = regs->regs[0];
> +	regs->syscallno = scno;

I'm slightly worried about the interaction with single-step, other
signals. It might be better if we just use the existing syscall
restarting mechanism. Untested diff below:

-------------------8<-------------------------------
diff --git a/arch/arm64/kernel/syscall.c b/arch/arm64/kernel/syscall.c
index a12c0c88d345..db25f5d6a07c 100644
--- a/arch/arm64/kernel/syscall.c
+++ b/arch/arm64/kernel/syscall.c
@@ -102,6 +102,16 @@ static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr,
 	local_daif_restore(DAIF_PROCCTX);
 	user_exit();
 
+	if (system_supports_mte() && (flags & _TIF_MTE_ASYNC_FAULT)) {
+		/*
+		 * Process the asynchronous tag check fault before the actual
+		 * syscall. do_notify_resume() will send a signal to userspace
+		 * before the syscall is restarted.
+		 */
+		regs->regs[0] = -ERESTARTNOINTR;
+		return;
+	}
+
 	if (has_syscall_work(flags)) {
 		/* set default errno for user-issued syscall(-1) */
 		if (scno == NO_SYSCALL)




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux