um: fix stub location calculation
authorJohannes Berg <johannes.berg@intel.com>
Tue, 13 Jul 2021 21:47:10 +0000 (23:47 +0200)
committerRichard Weinberger <richard@nod.at>
Thu, 26 Aug 2021 20:28:03 +0000 (22:28 +0200)
In commit 9f0b4807a44f ("um: rework userspace stubs to not hard-code
stub location") I changed stub_segv_handler() to do a calculation with
a pointer to a stack variable to find the data page that we're using
for the stack and the rest of the data. This same commit was meant to
do it as well for stub_clone_handler(), but the change inadvertently
went into commit 84b2789d6115 ("um: separate child and parent errors
in clone stub") instead.

This was reported to not be compiled correctly by gcc 5, causing the
code to crash here. I'm not sure why, perhaps it's UB because the var
isn't initialized? In any case, this trick always seemed bad, so just
create a new inline function that does the calculation in assembly.

Reported-by: subashab@codeaurora.org
Fixes: 9f0b4807a44f ("um: rework userspace stubs to not hard-code stub location")
Fixes: 84b2789d6115 ("um: separate child and parent errors in clone stub")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Richard Weinberger <richard@nod.at>
arch/um/kernel/skas/clone.c
arch/x86/um/shared/sysdep/stub_32.h
arch/x86/um/shared/sysdep/stub_64.h
arch/x86/um/stub_segv.c

index 5afac0fef24ea0b5a0cc1da09106242231956fb0..ff5061f291674913e08c100fb21d31cd2d8bcd0a 100644 (file)
@@ -24,8 +24,7 @@
 void __attribute__ ((__section__ (".__syscall_stub")))
 stub_clone_handler(void)
 {
-       int stack;
-       struct stub_data *data = (void *) ((unsigned long)&stack & ~(UM_KERN_PAGE_SIZE - 1));
+       struct stub_data *data = get_stub_page();
        long err;
 
        err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD,
index b95db9daf0e821993677bb098c111e561269ed9d..4c6c2be0c899775b6480deb641ac01faf18d94f9 100644 (file)
@@ -101,4 +101,16 @@ static inline void remap_stack_and_trap(void)
                "memory");
 }
 
+static __always_inline void *get_stub_page(void)
+{
+       unsigned long ret;
+
+       asm volatile (
+               "movl %%esp,%0 ;"
+               "andl %1,%0"
+               : "=a" (ret)
+               : "g" (~(UM_KERN_PAGE_SIZE - 1)));
+
+       return (void *)ret;
+}
 #endif
index 6e2626b77a2e42c3f77549333655723794417965..e9c4b2b388039c86a9faec8d787a7a5c16bea72e 100644 (file)
@@ -108,4 +108,16 @@ static inline void remap_stack_and_trap(void)
                __syscall_clobber, "r10", "r8", "r9");
 }
 
+static __always_inline void *get_stub_page(void)
+{
+       unsigned long ret;
+
+       asm volatile (
+               "movq %%rsp,%0 ;"
+               "andq %1,%0"
+               : "=a" (ret)
+               : "g" (~(UM_KERN_PAGE_SIZE - 1)));
+
+       return (void *)ret;
+}
 #endif
index 21836eaf1725914ef24d0488bb5beb10b8491357..f7eefba034f96bf1e1379742ad0bf504dd0e88cb 100644 (file)
@@ -11,9 +11,8 @@
 void __attribute__ ((__section__ (".__syscall_stub")))
 stub_segv_handler(int sig, siginfo_t *info, void *p)
 {
-       int stack;
+       struct faultinfo *f = get_stub_page();
        ucontext_t *uc = p;
-       struct faultinfo *f = (void *)(((unsigned long)&stack) & ~(UM_KERN_PAGE_SIZE - 1));
 
        GET_FAULTINFO_FROM_MC(*f, &uc->uc_mcontext);
        trap_myself();