@@ -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__
@@ -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
@@ -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;
@@ -13,6 +13,10 @@
#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)
{
@@ -470,11 +470,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;
}