s390: current_stack_pointer shouldn't be a function
authorSven Schnelle <svens@linux.ibm.com>
Fri, 8 Apr 2022 12:51:26 +0000 (14:51 +0200)
committerHeiko Carstens <hca@linux.ibm.com>
Tue, 12 Apr 2022 09:56:08 +0000 (11:56 +0200)
s390 defines current_stack_pointer as function while all other
architectures use 'register unsigned long asm("<stackptr reg>").

This make codes like the following from check_stack_object() fail:

if (IS_ENABLED(CONFIG_STACK_GROWSUP)) {
if ((void *)current_stack_pointer < obj + len)
return BAD_STACK;
} else {
if (obj < (void *)current_stack_pointer)
return BAD_STACK;
}

because this would compare the address of current_stack_pointer() and
not the stackpointer value.

Reported-by: Karsten Graul <kgraul@linux.ibm.com>
Fixes: 2792d84e6da5 ("usercopy: Check valid lifetime via stack depth")
Cc: Kees Cook <keescook@chromium.org>
Cc: Vasily Gorbik <gor@linux.ibm.com>
Cc: Alexander Gordeev <agordeev@linux.ibm.com>
Signed-off-by: Sven Schnelle <svens@linux.ibm.com>
Reviewed-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
arch/s390/include/asm/entry-common.h
arch/s390/include/asm/processor.h
arch/s390/include/asm/stacktrace.h
arch/s390/lib/test_unwind.c

index eabab24..2f0a1ca 100644 (file)
@@ -58,7 +58,7 @@ static inline void arch_exit_to_user_mode_prepare(struct pt_regs *regs,
 
 static inline bool on_thread_stack(void)
 {
-       return !(((unsigned long)(current->stack) ^ current_stack_pointer()) & ~(THREAD_SIZE - 1));
+       return !(((unsigned long)(current->stack) ^ current_stack_pointer) & ~(THREAD_SIZE - 1));
 }
 
 #endif
index eee8d96..ff1e25d 100644 (file)
@@ -200,13 +200,7 @@ unsigned long __get_wchan(struct task_struct *p);
 /* Has task runtime instrumentation enabled ? */
 #define is_ri_task(tsk) (!!(tsk)->thread.ri_cb)
 
-static __always_inline unsigned long current_stack_pointer(void)
-{
-       unsigned long sp;
-
-       asm volatile("la %0,0(15)" : "=a" (sp));
-       return sp;
-}
+register unsigned long current_stack_pointer asm("r15");
 
 static __always_inline unsigned short stap(void)
 {
index 275f425..f850019 100644 (file)
@@ -46,7 +46,7 @@ struct stack_frame {
 };
 
 /*
- * Unlike current_stack_pointer() which simply returns current value of %r15
+ * Unlike current_stack_pointer which simply contains the current value of %r15
  * current_frame_address() returns function stack frame address, which matches
  * %r15 upon function invocation. It may differ from %r15 later if function
  * allocates stack for local variables or new stack frame to call other
index 9bb0673..5a053b3 100644 (file)
@@ -147,7 +147,7 @@ static __always_inline struct pt_regs fake_pt_regs(void)
        struct pt_regs regs;
 
        memset(&regs, 0, sizeof(regs));
-       regs.gprs[15] = current_stack_pointer();
+       regs.gprs[15] = current_stack_pointer;
 
        asm volatile(
                "basr   %[psw_addr],0\n"