]> www.infradead.org Git - linux.git/commitdiff
um: make stub_exe _start() pure inline asm
authorJohannes Berg <johannes.berg@intel.com>
Tue, 22 Oct 2024 12:02:38 +0000 (14:02 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 23 Oct 2024 07:04:59 +0000 (09:04 +0200)
Since __attribute__((naked)) cannot be used with functions
containing C statements, just generate the few instructions
it needs in assembly directly.

While at it, fix the stack usage ("1 + 2*x - 1" is odd) and
document what it must do, and why it must adjust the stack.

Fixes: 8508a5e0e9db ("um: Fix misaligned stack in stub_exe")
Link: https://lore.kernel.org/linux-um/CABVgOSntH-uoOFMP5HwMXjx_f1osMnVdhgKRKm4uz6DFm2Lb8Q@mail.gmail.com/
Reviewed-by: David Gow <davidgow@google.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
arch/um/kernel/skas/stub_exe.c
arch/x86/um/shared/sysdep/stub_32.h
arch/x86/um/shared/sysdep/stub_64.h

index 722ce62674768c1c0445914ff632ce97697ee7e7..23c99b285e82e79a1b5808af48f5c0af294738b2 100644 (file)
@@ -81,11 +81,15 @@ noinline static void real_init(void)
 
 __attribute__((naked)) void _start(void)
 {
-       char *alloc;
-
-       /* Make enough space for the stub (including space for alignment) */
-       alloc = __builtin_alloca((1 + 2 * STUB_DATA_PAGES - 1) * UM_KERN_PAGE_SIZE);
-       asm volatile("" : "+r,m"(alloc) : : "memory");
-
-       real_init();
+       /*
+        * Since the stack after exec() starts at the top-most address,
+        * but that's exactly where we also want to map the stub data
+        * and code, this must:
+        *  - push the stack by 1 code and STUB_DATA_PAGES data pages
+        *  - call real_init()
+        * This way, real_init() can use the stack normally, while the
+        * original stack further down (higher address) will become
+        * inaccessible after the mmap() calls above.
+        */
+       stub_start(real_init);
 }
index 631a18d0ff441f09bea2f2fe4fb7d978bbcc7cbb..390988132c0a7a62e7a1a08e02940796a7e4759f 100644 (file)
@@ -123,4 +123,12 @@ static __always_inline void *get_stub_data(void)
 
        return (void *)ret;
 }
+
+#define stub_start(fn)                                                 \
+       asm volatile (                                                  \
+               "subl %0,%%esp ;"                                       \
+               "movl %1, %%eax ; "                                     \
+               "call *%%eax ;"                                         \
+               :: "i" ((1 + STUB_DATA_PAGES) * UM_KERN_PAGE_SIZE),     \
+                  "i" (&fn))
 #endif
index 17153dfd780a435fe2c6f25f94ff0a6edefbb0b9..294affbec74293026942450ddef3a5951f32bcde 100644 (file)
@@ -126,4 +126,12 @@ static __always_inline void *get_stub_data(void)
 
        return (void *)ret;
 }
+
+#define stub_start(fn)                                                 \
+       asm volatile (                                                  \
+               "subq %0,%%rsp ;"                                       \
+               "movq %1,%%rax ;"                                       \
+               "call *%%rax ;"                                         \
+               :: "i" ((1 + STUB_DATA_PAGES) * UM_KERN_PAGE_SIZE),     \
+                  "i" (&fn))
 #endif