[PATCH] ARM: Fix potential register clobbering in __get_user_check

Tal Well talwell02 at gmail.com
Sat Jun 13 05:27:07 PDT 2026


This can happen due to local variable registers being call-clobbered by
uaccess_save_and_enable or uaccess_restore, which can happen if they
become slightly more complicated than they are (for example contain any
memory access while KASAN is enabled).
In that case, the first user access will fail while trying to execute
the init process and the kernel will panic.

While this is not strictly a bug given r0, r1 and r2 remain unused in
the uaccess functions, even something as simple as making them noinline
breaks this assumption and there's no reason to rely on it.

This is similar to the issue fixed by commit df909df0770779f1a556
("ARM: 9132/1: Fix __get_user_check failure with ARM KASAN images"),
but that only handled clobbering of r0 by the uaccess_restore function.

Signed-off-by: Tal Well <talwell02 at gmail.com>
---
 arch/arm/include/asm/uaccess.h | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h
index d6ae80b5df36..290ce8710773 100644
--- a/arch/arm/include/asm/uaccess.h
+++ b/arch/arm/include/asm/uaccess.h
@@ -180,12 +180,13 @@ extern int __get_user_64t_4(void *);
 
 #define __get_user_check(x, p)						\
 	({								\
-		unsigned long __limit = TASK_SIZE - 1; \
+		unsigned long __limit = TASK_SIZE - 1;			\
+		unsigned int __ua_flags = uaccess_save_and_enable();	\
 		register typeof(*(p)) __user *__p asm("r0") = (p);	\
 		register __inttype(x) __r2 asm("r2");			\
 		register unsigned long __l asm("r1") = __limit;		\
 		register int __e asm("r0");				\
-		unsigned int __ua_flags = uaccess_save_and_enable();	\
+		__inttype(x) __tmp_r2;					\
 		int __tmp_e;						\
 		switch (sizeof(*(__p))) {				\
 		case 1:							\
@@ -214,9 +215,10 @@ extern int __get_user_64t_4(void *);
 			break;						\
 		default: __e = __get_user_bad(); break;			\
 		}							\
+		__tmp_r2 = __r2;					\
 		__tmp_e = __e;						\
 		uaccess_restore(__ua_flags);				\
-		x = (typeof(*(p))) __r2;				\
+		x = (typeof(*(p))) __tmp_r2;				\
 		__tmp_e;						\
 	})
 

base-commit: 062871f1371b2e02a272ff5279c6479aff0a37ef
-- 
2.39.5




More information about the linux-arm-kernel mailing list