]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
um: Create signal stack memory assignment in stub_data
authorBenjamin Berg <benjamin@sipsolutions.net>
Wed, 3 Jul 2024 13:45:26 +0000 (15:45 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 3 Jul 2024 15:09:48 +0000 (17:09 +0200)
When we switch to use seccomp, we need both the signal stack and other
data (i.e. syscall information) to co-exist in the stub data. To
facilitate this, start by defining separate memory areas for the stack
and syscall data.

This moves the signal stack onto a new page as the memory area is not
sufficient to hold both signal stack and syscall information.

Only change the signal stack setup for now, as the syscall code will be
reworked later.

Signed-off-by: Benjamin Berg <benjamin@sipsolutions.net>
Link: https://patch.msgid.link/20240703134536.1161108-3-benjamin@sipsolutions.net
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
arch/um/include/shared/as-layout.h
arch/um/include/shared/skas/stub-data.h
arch/um/kernel/skas/clone.c
arch/um/kernel/skas/mmu.c
arch/um/os-Linux/skas/process.c

index c22f46a757dcffccaf032f29b3178dfe9f8c703d..06292fca5a4da5afba0864fa73d888b39bff8039 100644 (file)
@@ -23,7 +23,7 @@
 #define STUB_START stub_start
 #define STUB_CODE STUB_START
 #define STUB_DATA (STUB_CODE + UM_KERN_PAGE_SIZE)
-#define STUB_DATA_PAGES 1 /* must be a power of two */
+#define STUB_DATA_PAGES 2 /* must be a power of two */
 #define STUB_END (STUB_DATA + STUB_DATA_PAGES * UM_KERN_PAGE_SIZE)
 
 #ifndef __ASSEMBLY__
index 5e3ade3fb38b3af9d6dc371c96c169a3db72f150..779d2a3bac5d9057f71c5a8cc39c4ddedad26557 100644 (file)
@@ -8,10 +8,19 @@
 #ifndef __STUB_DATA_H
 #define __STUB_DATA_H
 
+#include <linux/compiler_types.h>
+#include <as-layout.h>
+
 struct stub_data {
        unsigned long offset;
        int fd;
        long parent_err, child_err;
+
+       /* 128 leaves enough room for additional fields in the struct */
+       unsigned char syscall_data[UM_KERN_PAGE_SIZE - 128] __aligned(16);
+
+       /* Stack for our signal handlers and for calling into . */
+       unsigned char sigstack[UM_KERN_PAGE_SIZE] __aligned(UM_KERN_PAGE_SIZE);
 };
 
 #endif
index 62435187dda4840183f5e6bc42277340ba3afd30..906f7454887c4f49a40ee903a6405f6e8f2920be 100644 (file)
@@ -27,9 +27,11 @@ stub_clone_handler(void)
        struct stub_data *data = get_stub_data();
        long err;
 
+       /* syscall data as a temporary stack area (bottom half). */
        err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD,
-                           (unsigned long)data +
-                               STUB_DATA_PAGES * UM_KERN_PAGE_SIZE / 2);
+                           (unsigned long) data->syscall_data +
+                                           sizeof(data->syscall_data) / 2 -
+                                           sizeof(void *));
        if (err) {
                data->parent_err = err;
                goto done;
index aeed1c2aaf3c76b14c1303d149910665836db3a0..681839cdd795a13a030ebebc2d6396e37823e4f4 100644 (file)
 #include <as-layout.h>
 #include <os.h>
 #include <skas.h>
+#include <stub-data.h>
+
+/* Ensure the stub_data struct covers the allocated area */
+static_assert(sizeof(struct stub_data) == STUB_DATA_PAGES * UM_KERN_PAGE_SIZE);
 
 int init_new_context(struct task_struct *task, struct mm_struct *mm)
 {
index 45885deb6cae8cbd3a21a9cb21d748a73a52690e..56403a1b006a378acd87eb149073589493138da6 100644 (file)
@@ -474,11 +474,12 @@ static int __init init_thread_regs(void)
        thread_regs[REGS_IP_INDEX] = STUB_CODE +
                                (unsigned long) stub_clone_handler -
                                (unsigned long) __syscall_stub_start;
-       thread_regs[REGS_SP_INDEX] = STUB_DATA + STUB_DATA_PAGES * UM_KERN_PAGE_SIZE -
-               sizeof(void *);
-#ifdef __SIGNAL_FRAMESIZE
-       thread_regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE;
-#endif
+
+       /* syscall data as a temporary stack area (top half). */
+       thread_regs[REGS_SP_INDEX] = STUB_DATA +
+                                    offsetof(struct stub_data, syscall_data) +
+                                    sizeof(((struct stub_data *) 0)->syscall_data) -
+                                    sizeof(void *);
        return 0;
 }