[PATCH v17 15/15] arm64: vdso: Expose sigreturn address on vdso to the kernel

Jinjie Ruan ruanjinjie at huawei.com
Tue Jul 21 01:18:58 PDT 2026


Syscall User Dispatch (SUD) must not intercept the signal trampoline
code, otherwise returning from a signal with a locked selector may
cause infinite recursion into the signal handler.

Provide an arm64 implementation of arch_syscall_is_vdso_sigreturn()
to exclude these sigreturn syscalls from dispatch.

For native 64-bit tasks, check whether the current PC matches the 'svc #0'
instruction inside the vDSO sigreturn trampoline (defined in
arch/arm64/kernel/vdso/sigreturn.S as below).

	SYM_CODE_START(__kernel_rt_sigreturn)
		mov     x8, #__NR_rt_sigreturn
		svc     #0
	SYM_CODE_END(__kernel_rt_sigreturn)

For COMPAT tasks, verify that the instruction falls within the dedicated
'sigpage' range, since compat signal handlers use this architecture-
specific page (not the vDSO) for their return trampoline. This prevents
SUD from incorrectly dispatching syscalls issued during signal return.

Suggested-by: Thomas Weißschuh <thomas.weissschuh at linutronix.de>
Suggested-by: Kevin Brodsky <kevin.brodsky at arm.com>
Suggested-by: kemal <kmal at cock.li>
Signed-off-by: Jinjie Ruan <ruanjinjie at huawei.com>
---
 arch/arm64/Kconfig                 |  1 +
 arch/arm64/include/asm/elf.h       |  1 +
 arch/arm64/kernel/vdso.c           | 16 ++++++++++++++++
 arch/arm64/kernel/vdso/sigreturn.S |  1 +
 arch/arm64/kernel/vdso/vdso.lds.S  |  1 +
 5 files changed, 20 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index aea686dce3d5..a41d2b593899 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -86,6 +86,7 @@ config ARM64
 	select ARCH_SUPPORTS_SCHED_SMT
 	select ARCH_SUPPORTS_SCHED_CLUSTER
 	select ARCH_SUPPORTS_SCHED_MC
+	select ARCH_SUPPORTS_SYSCALL_USER_DISPATCH
 	select ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH
 	select ARCH_WANT_COMPAT_IPC_PARSE_VERSION if COMPAT
 	select ARCH_WANT_DEFAULT_BPF_JIT
diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
index d2779d604c7b..a8b232c5c6d9 100644
--- a/arch/arm64/include/asm/elf.h
+++ b/arch/arm64/include/asm/elf.h
@@ -293,6 +293,7 @@ static inline int arch_check_elf(void *ehdr, bool has_interp,
 	return 0;
 }
 
+extern bool arch_syscall_is_vdso_sigreturn(struct pt_regs *regs);
 #endif /* !__ASSEMBLER__ */
 
 #endif
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index 592dd8668de4..37cdc7c72e15 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -343,3 +343,19 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 
 	return ret;
 }
+
+bool arch_syscall_is_vdso_sigreturn(struct pt_regs *regs)
+{
+	unsigned long landing_pad;
+
+#ifdef CONFIG_COMPAT
+	if (is_compat_task()) {
+		unsigned long sigpage = (unsigned long)current->mm->context.sigpage;
+
+		return regs->pc >= sigpage && regs->pc < (sigpage + PAGE_SIZE);
+	}
+#endif
+	landing_pad = (unsigned long)VDSO_SYMBOL(current->mm->context.vdso, sigreturn_landing_pad);
+
+	return regs->pc == landing_pad;
+}
diff --git a/arch/arm64/kernel/vdso/sigreturn.S b/arch/arm64/kernel/vdso/sigreturn.S
index 0e18729abc3b..8d2d413ff45e 100644
--- a/arch/arm64/kernel/vdso/sigreturn.S
+++ b/arch/arm64/kernel/vdso/sigreturn.S
@@ -73,6 +73,7 @@ SYM_CODE_START(__kernel_rt_sigreturn)
 	mov	x8, #__NR_rt_sigreturn
 //	PLEASE DO NOT MODIFY
 	svc	#0
+	SYM_INNER_LABEL(__sigreturn_landing_pad, SYM_L_GLOBAL)
 //	PLEASE DO NOT MODIFY
 //	.cfi_endproc
 SYM_CODE_END(__kernel_rt_sigreturn)
diff --git a/arch/arm64/kernel/vdso/vdso.lds.S b/arch/arm64/kernel/vdso/vdso.lds.S
index 52314be29191..da61d6fc6fe9 100644
--- a/arch/arm64/kernel/vdso/vdso.lds.S
+++ b/arch/arm64/kernel/vdso/vdso.lds.S
@@ -112,3 +112,4 @@ VERSION
  * Make the sigreturn code visible to the kernel.
  */
 VDSO_sigtramp		= __kernel_rt_sigreturn;
+VDSO_sigreturn_landing_pad	= __sigreturn_landing_pad;
-- 
2.34.1




More information about the linux-arm-kernel mailing list