Re: [PATCH RFC 1/2] arm64: vdso: Prepare for robust futex unlock support

From: Thomas Weißschuh

Date: Wed Apr 22 2026 - 09:22:44 EST


On 2026-04-22 15:02:45+0200, Thomas Weißschuh wrote:
> On 2026-04-17 11:56:10-0300, André Almeida wrote:
> > There will be a VDSO function to unlock non-contended robust futexes in
> > user space. The unlock sequence is racy vs. clearing the list_pending_op
> > pointer in the task's robust list head. To plug this race the kernel needs
> > to know the critical section window so it can clear the pointer when the
> > task is interrupted within that race window. The window is determined by
> > labels in the inline assembly.
> >
> > Signed-off-by: André Almeida <andrealmeid@xxxxxxxxxx>
> > ---
> > RFC: Those symbols can't be found by the linker after patch 2/2, it fails with:
> >
> > ld: arch/arm64/kernel/vdso.o: in function `vdso_futex_robust_unlock_update_ips':
> > arch/arm64/kernel/vdso.c:72:(.text+0x200): undefined reference to `__futex_list64_try_unlock_cs_success'
> > ld: arch/arm64/kernel/vdso.o: relocation R_AARCH64_ADR_PREL_PG_HI21 against symbol `__futex_list64_try_unlock_cs_success' which may bind externally can not be used when making a shared object; recompile with -fPIC
> > arch/arm64/kernel/vdso.c:72:(.text+0x200): dangerous relocation: unsupported relocation
>
> arch/arm64/kernel/vdso.o is a kernel object.
> __futex_list64_try_unlock_cs_success is a vDSO symbol.
> They live in wholly different objects, which are never linked together.
> Look at VDSO_SYMBOL() to get the offset of the vDSO symbol in kernel code.
>
> (...)

The diff below shows the idea. Compat code is not fixed, and I didn't
even try to run it. Also please use CONFIG_COMPAT_VDSO over plain
CONFIG_COMPAT.

diff --git a/arch/arm64/include/asm/vdso.h b/arch/arm64/include/asm/vdso.h
index 182fde1df3dd..232b46969088 100644
--- a/arch/arm64/include/asm/vdso.h
+++ b/arch/arm64/include/asm/vdso.h
@@ -18,10 +18,6 @@

extern char vdso_start[], vdso_end[];
extern char vdso32_start[], vdso32_end[];
-extern char __futex_list64_try_unlock_cs_success[], __futex_list64_try_unlock_cs_end[];
-#ifdef CONFIG_COMPAT
-extern char __futex_list32_try_unlock_cs_success[], __futex_list32_try_unlock_cs_end[];
-#endif

#endif /* !__ASSEMBLER__ */

diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index 42a82e73a774..45eb1aa627a2 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -64,21 +64,17 @@ static void vdso_futex_robust_unlock_update_ips(enum vdso_abi abi, struct mm_str
unsigned long vdso = (unsigned long) mm->context.vdso;
struct futex_mm_data *fd = &mm->futex;

- /*
- * RFC: won't compile due to undefined reference to `__futex_list64_try_unlock_cs_...`
-
if (abi == VDSO_ABI_AA64) {
- futex_set_vdso_cs_range(fd, 0, vdso, (uintptr_t) __futex_list64_try_unlock_cs_success,
- (uintptr_t) __futex_list64_try_unlock_cs_end, false);
+ futex_set_vdso_cs_range(fd, 0, vdso, (uintptr_t)VDSO_SYMBOL(vdso, futex_list64_try_unlock_cs_success),
+ (uintptr_t)VDSO_SYMBOL(vdso, futex_list64_try_unlock_cs_end), false);
}

-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_COMPAT_VDSO
if (abi == VDSO_ABI_AA32) {
futex_set_vdso_cs_range(fd, 1, vdso, (uintptr_t) __futex_list32_try_unlock_cs_success,
(uintptr_t) __futex_list32_try_unlock_cs_end, true);
}
#endif
- */
}
#else
static inline void vdso_futex_robust_unlock_update_ips(enum vdso_abi abi, struct mm_struct *mm) { }
diff --git a/arch/arm64/kernel/vdso/vdso.lds.S b/arch/arm64/kernel/vdso/vdso.lds.S
index 33ce58516580..a17e6eab9d3f 100644
--- a/arch/arm64/kernel/vdso/vdso.lds.S
+++ b/arch/arm64/kernel/vdso/vdso.lds.S
@@ -116,3 +116,5 @@ VERSION
* Make the sigreturn code visible to the kernel.
*/
VDSO_sigtramp = __kernel_rt_sigreturn;
+VDSO_futex_list64_try_unlock_cs_success = __futex_list64_try_unlock_cs_success;
+VDSO_futex_list64_try_unlock_cs_end = __futex_list64_try_unlock_cs_end;