Re: [PATCH] mips: vdso: conditionalize 32-bit time functions on COMPAT_32BIT_TIME

From: Paul Burton
Date: Tue Dec 31 2019 - 23:09:07 EST


Hi Jason,

On Tue, Dec 31, 2019 at 05:14:41PM +0100, Jason A. Donenfeld wrote:
> Here's a "one click" reproducer:
> https://data.zx2c4.com/mips-musl-libc-weird-crash-time32-compat.tar.xz
>
> Untar that and hit `make -j$(nproc)`, and you'll get a freshly built
> and crashing kernel+userland.

Thanks for the test case. It seems like the VDSO code isn't saving &
restoring $gp/$28, even though it's meant to be callee-saved in both the
n32 & n64 ABIs. With some digging I found that the below seems to
resolve the issue. Could you check whether it works for you?

I'm still not quite sure *why* this happens; perhaps GCC just decides it
doesn't need to save & restore $gp/$28 when it spots that it's being
"used" for __current_thread_info (even though that's never actually
referenced in the VDSO)?

Just moving the declaration of __current_thread_info inside the
current_thread_info() function seems to do the trick too, and is
probably a bit neater.

Thanks,
Paul

---
diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h
index 4993db40482c..ac33959bbb1f 100644
--- a/arch/mips/include/asm/thread_info.h
+++ b/arch/mips/include/asm/thread_info.h
@@ -50,7 +50,11 @@ struct thread_info {
}

/* How to get the thread information struct from C. */
+#ifdef __VDSO__
+register struct thread_info *__current_thread_info __asm__("$0");
+#else
register struct thread_info *__current_thread_info __asm__("$28");
+#endif

static inline struct thread_info *current_thread_info(void)
{