um: Rework syscall handling

Rework syscall handling to be platform independent. Also create a clean
split between queueing of syscalls and flushing them out, removing the
need to keep state in the code that triggers the syscalls.

The code adds syscall_data_len to the global mm_id structure. This will
be used later to allow surrounding code to track whether syscalls still
need to run and if errors occurred.

Signed-off-by: Benjamin Berg <benjamin@sipsolutions.net>
Link: https://patch.msgid.link/20240703134536.1161108-5-benjamin@sipsolutions.net
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Benjamin Berg 2024-07-03 15:45:28 +02:00 committed by Johannes Berg
parent 542dc79f6e
commit 76ed9158e1
16 changed files with 271 additions and 294 deletions

View File

@ -272,19 +272,15 @@ extern long long os_persistent_clock_emulation(void);
extern long long os_nsecs(void);
/* skas/mem.c */
extern long run_syscall_stub(struct mm_id * mm_idp,
int syscall, unsigned long *args, long expected,
void **addr, int done);
extern long syscall_stub_data(struct mm_id * mm_idp,
unsigned long *data, int data_count,
void **addr, void **stub_addr);
extern int map(struct mm_id * mm_idp, unsigned long virt,
unsigned long len, int prot, int phys_fd,
unsigned long long offset, int done, void **data);
extern int unmap(struct mm_id * mm_idp, unsigned long addr, unsigned long len,
int done, void **data);
extern int protect(struct mm_id * mm_idp, unsigned long addr,
unsigned long len, unsigned int prot, int done, void **data);
int syscall_stub_flush(struct mm_id *mm_idp);
struct stub_syscall *syscall_stub_alloc(struct mm_id *mm_idp);
void map(struct mm_id *mm_idp, unsigned long virt,
unsigned long len, int prot, int phys_fd,
unsigned long long offset);
void unmap(struct mm_id *mm_idp, unsigned long addr, unsigned long len);
void protect(struct mm_id *mm_idp, unsigned long addr,
unsigned long len, unsigned int prot);
/* skas/process.c */
extern int is_skas_winch(int pid, int fd, void *data);

View File

@ -13,6 +13,7 @@ struct mm_id {
} u;
unsigned long stack;
int kill;
int syscall_data_len;
};
void __switch_mm(struct mm_id *mm_idp);

View File

@ -10,14 +10,45 @@
#include <linux/compiler_types.h>
#include <as-layout.h>
#include <sysdep/tls.h>
#define STUB_NEXT_SYSCALL(s) \
((struct stub_syscall *) (((unsigned long) s) + (s)->cmd_len))
enum stub_syscall_type {
STUB_SYSCALL_UNSET = 0,
STUB_SYSCALL_MMAP,
STUB_SYSCALL_MUNMAP,
STUB_SYSCALL_MPROTECT,
STUB_SYSCALL_LDT,
};
struct stub_syscall {
union {
struct {
unsigned long addr;
unsigned long length;
unsigned long offset;
int fd;
int prot;
} mem;
struct {
user_desc_t desc;
int func;
} ldt;
};
enum stub_syscall_type syscall;
};
struct stub_data {
unsigned long offset;
int fd;
long parent_err, child_err;
long err, child_err;
int syscall_data_len;
/* 128 leaves enough room for additional fields in the struct */
unsigned char syscall_data[UM_KERN_PAGE_SIZE - 128] __aligned(16);
struct stub_syscall syscall_data[(UM_KERN_PAGE_SIZE - 128) / sizeof(struct stub_syscall)] __aligned(16);
/* Stack for our signal handlers and for calling into . */
unsigned char sigstack[UM_KERN_PAGE_SIZE] __aligned(UM_KERN_PAGE_SIZE);

View File

@ -42,11 +42,19 @@ extern void panic(const char *fmt, ...)
#define printk(...) _printk(__VA_ARGS__)
extern int _printk(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
extern void print_hex_dump(const char *level, const char *prefix_str,
int prefix_type, int rowsize, int groupsize,
const void *buf, size_t len, _Bool ascii);
#else
static inline int printk(const char *fmt, ...)
{
return 0;
}
static inline void print_hex_dump(const char *level, const char *prefix_str,
int prefix_type, int rowsize, int groupsize,
const void *buf, size_t len, _Bool ascii)
{
}
#endif
extern int in_aton(char *str);

View File

@ -22,15 +22,11 @@
void flush_thread(void)
{
void *data = NULL;
int ret;
arch_flush_thread(&current->thread.arch);
ret = unmap(&current->mm->context.id, 0, TASK_SIZE, 1, &data);
if (ret) {
printk(KERN_ERR "%s - clearing address space failed, err = %d\n",
__func__, ret);
unmap(&current->mm->context.id, 0, TASK_SIZE);
if (syscall_stub_flush(&current->mm->context.id) < 0) {
printk(KERN_ERR "%s - clearing address space failed", __func__);
force_sig(SIGKILL);
}
get_safe_registers(current_pt_regs()->regs.gp,

View File

@ -3,14 +3,15 @@
# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
#
obj-y := clone.o mmu.o process.o syscall.o uaccess.o
obj-y := clone.o stub.o mmu.o process.o syscall.o uaccess.o
# clone.o is in the stub, so it can't be built with profiling
# clone.o and stub.o are in the stub, so it can't be built with profiling
# GCC hardened also auto-enables -fpic, but we need %ebx so it can't work ->
# disable it
CFLAGS_clone.o := $(CFLAGS_NO_HARDENING)
UNPROFILE_OBJS := clone.o
CFLAGS_stub.o := $(CFLAGS_NO_HARDENING)
UNPROFILE_OBJS := clone.o stub.o
KCOV_INSTRUMENT := n

View File

@ -33,7 +33,7 @@ stub_clone_handler(void)
sizeof(data->syscall_data) / 2 -
sizeof(void *));
if (err) {
data->parent_err = err;
data->err = err;
goto done;
}

View File

@ -0,0 +1,80 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2021 Benjamin Berg <benjamin@sipsolutions.net>
*/
#include <sysdep/stub.h>
static __always_inline int syscall_handler(struct stub_data *d)
{
int i;
unsigned long res;
for (i = 0; i < d->syscall_data_len; i++) {
struct stub_syscall *sc = &d->syscall_data[i];
switch (sc->syscall) {
case STUB_SYSCALL_MMAP:
res = stub_syscall6(STUB_MMAP_NR,
sc->mem.addr, sc->mem.length,
sc->mem.prot,
MAP_SHARED | MAP_FIXED,
sc->mem.fd, sc->mem.offset);
if (res != sc->mem.addr) {
d->err = res;
d->syscall_data_len = i;
return -1;
}
break;
case STUB_SYSCALL_MUNMAP:
res = stub_syscall2(__NR_munmap,
sc->mem.addr, sc->mem.length);
if (res) {
d->err = res;
d->syscall_data_len = i;
return -1;
}
break;
case STUB_SYSCALL_MPROTECT:
res = stub_syscall3(__NR_mprotect,
sc->mem.addr, sc->mem.length,
sc->mem.prot);
if (res) {
d->err = res;
d->syscall_data_len = i;
return -1;
}
break;
case STUB_SYSCALL_LDT:
res = stub_syscall3(__NR_modify_ldt, sc->ldt.func,
(unsigned long) &sc->ldt.desc,
sizeof(sc->ldt.desc));
/* We only write, so the expected result is zero */
if (res) {
d->err = res;
d->syscall_data_len = i;
return -1;
}
break;
default:
d->err = -95; /* EOPNOTSUPP */
d->syscall_data_len = i;
return -1;
}
}
d->err = 0;
d->syscall_data_len = 0;
return 0;
}
void __section(".__syscall_stub")
stub_syscall_handler(void)
{
struct stub_data *d = get_stub_data();
syscall_handler(d);
trap_myself();
}

View File

@ -71,21 +71,19 @@ static int do_ops(struct host_vm_change *hvc, int end,
switch (op->type) {
case MMAP:
if (hvc->userspace)
ret = map(&hvc->mm->context.id, op->u.mmap.addr,
op->u.mmap.len, op->u.mmap.prot,
op->u.mmap.fd,
op->u.mmap.offset, finished,
&hvc->data);
map(&hvc->mm->context.id, op->u.mmap.addr,
op->u.mmap.len, op->u.mmap.prot,
op->u.mmap.fd,
op->u.mmap.offset);
else
map_memory(op->u.mmap.addr, op->u.mmap.offset,
op->u.mmap.len, 1, 1, 1);
break;
case MUNMAP:
if (hvc->userspace)
ret = unmap(&hvc->mm->context.id,
op->u.munmap.addr,
op->u.munmap.len, finished,
&hvc->data);
unmap(&hvc->mm->context.id,
op->u.munmap.addr,
op->u.munmap.len);
else
ret = os_unmap_memory(
(void *) op->u.munmap.addr,
@ -94,11 +92,10 @@ static int do_ops(struct host_vm_change *hvc, int end,
break;
case MPROTECT:
if (hvc->userspace)
ret = protect(&hvc->mm->context.id,
op->u.mprotect.addr,
op->u.mprotect.len,
op->u.mprotect.prot,
finished, &hvc->data);
protect(&hvc->mm->context.id,
op->u.mprotect.addr,
op->u.mprotect.len,
op->u.mprotect.prot);
else
ret = os_protect_memory(
(void *) op->u.mprotect.addr,
@ -113,6 +110,9 @@ static int do_ops(struct host_vm_change *hvc, int end,
}
}
if (hvc->userspace && finished)
ret = syscall_stub_flush(&hvc->mm->context.id);
if (ret == -ENOMEM)
report_enomem();
@ -461,7 +461,6 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
pmd_t *pmd;
pte_t *pte;
struct mm_struct *mm = vma->vm_mm;
void *flush = NULL;
int r, w, x, prot, err = 0;
struct mm_id *mm_id;
@ -504,14 +503,13 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
int fd;
fd = phys_mapping(pte_val(*pte) & PAGE_MASK, &offset);
err = map(mm_id, address, PAGE_SIZE, prot, fd, offset,
1, &flush);
}
else err = unmap(mm_id, address, PAGE_SIZE, 1, &flush);
}
else if (pte_newprot(*pte))
err = protect(mm_id, address, PAGE_SIZE, prot, 1, &flush);
map(mm_id, address, PAGE_SIZE, prot, fd, offset);
} else
unmap(mm_id, address, PAGE_SIZE);
} else if (pte_newprot(*pte))
protect(mm_id, address, PAGE_SIZE, prot);
err = syscall_stub_flush(mm_id);
if (err) {
if (err == -ENOMEM)
report_enomem();

View File

@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2021 Benjamin Berg <benjamin@sipsolutions.net>
* Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
*/
@ -19,7 +20,7 @@
#include <sysdep/stub.h>
#include "../internal.h"
extern char batch_syscall_stub[], __syscall_stub_start[];
extern char __syscall_stub_start[];
static inline unsigned long *check_init_stack(struct mm_id * mm_idp,
unsigned long *stack)
@ -36,22 +37,24 @@ static unsigned long syscall_regs[MAX_REG_NR];
static int __init init_syscall_regs(void)
{
get_safe_registers(syscall_regs, NULL);
syscall_regs[REGS_IP_INDEX] = STUB_CODE +
((unsigned long) batch_syscall_stub -
((unsigned long) stub_syscall_handler -
(unsigned long) __syscall_stub_start);
syscall_regs[REGS_SP_INDEX] = STUB_DATA;
syscall_regs[REGS_SP_INDEX] = STUB_DATA +
offsetof(struct stub_data, sigstack) +
sizeof(((struct stub_data *) 0)->sigstack) -
sizeof(void *);
return 0;
}
__initcall(init_syscall_regs);
static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr)
static inline long do_syscall_stub(struct mm_id *mm_idp)
{
struct stub_data *proc_data = (void *)mm_idp->stack;
int n, i;
long ret, offset;
unsigned long * data;
unsigned long * syscall;
int err, pid = mm_idp->u.pid;
n = ptrace_setregs(pid, syscall_regs);
@ -63,6 +66,9 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr)
__func__, -n);
}
/* Inform process how much we have filled in. */
proc_data->syscall_data_len = mm_idp->syscall_data_len;
err = ptrace(PTRACE_CONT, pid, 0, 0);
if (err)
panic("Failed to continue stub, pid = %d, errno = %d\n", pid,
@ -71,135 +77,113 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr)
wait_stub_done(pid);
/*
* When the stub stops, we find the following values on the
* beginning of the stack:
* (long )return_value
* (long )offset to failed sycall-data (0, if no error)
* proc_data->err will be non-zero if there was an (unexpected) error.
* In that case, syscall_data_len points to the last executed syscall,
* otherwise it will be zero (but we do not need to rely on that).
*/
ret = *((unsigned long *) mm_idp->stack);
offset = *((unsigned long *) mm_idp->stack + 1);
if (offset) {
data = (unsigned long *)(mm_idp->stack + offset - STUB_DATA);
printk(UM_KERN_ERR "%s : ret = %ld, offset = %ld, data = %p\n",
__func__, ret, offset, data);
syscall = (unsigned long *)((unsigned long)data + data[0]);
printk(UM_KERN_ERR "%s: syscall %ld failed, return value = 0x%lx, expected return value = 0x%lx\n",
__func__, syscall[0], ret, syscall[7]);
printk(UM_KERN_ERR " syscall parameters: 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n",
syscall[1], syscall[2], syscall[3],
syscall[4], syscall[5], syscall[6]);
for (n = 1; n < data[0]/sizeof(long); n++) {
if (n == 1)
printk(UM_KERN_ERR " additional syscall data:");
if (n % 4 == 1)
printk("\n" UM_KERN_ERR " ");
printk(" 0x%lx", data[n]);
}
if (n > 1)
printk("\n");
if (proc_data->err < 0) {
struct stub_syscall *sc;
if (proc_data->syscall_data_len < 0 ||
proc_data->syscall_data_len >= ARRAY_SIZE(proc_data->syscall_data))
panic("Syscall data was corrupted by stub (len is: %d, expected maximum: %d)!",
proc_data->syscall_data_len,
mm_idp->syscall_data_len);
sc = &proc_data->syscall_data[proc_data->syscall_data_len];
printk(UM_KERN_ERR "%s : length = %d, last offset = %d",
__func__, mm_idp->syscall_data_len,
proc_data->syscall_data_len);
printk(UM_KERN_ERR "%s : stub syscall type %d failed, return value = 0x%lx\n",
__func__, sc->syscall, proc_data->err);
print_hex_dump(UM_KERN_ERR,
" syscall data: ", 0,
16, 4, sc, sizeof(*sc), 0);
mm_idp->syscall_data_len = proc_data->err;
} else {
mm_idp->syscall_data_len = 0;
}
else ret = 0;
*addr = check_init_stack(mm_idp, NULL);
return ret;
return mm_idp->syscall_data_len;
}
long run_syscall_stub(struct mm_id * mm_idp, int syscall,
unsigned long *args, long expected, void **addr,
int done)
int syscall_stub_flush(struct mm_id *mm_idp)
{
unsigned long *stack = check_init_stack(mm_idp, *addr);
int res;
*stack += sizeof(long);
stack += *stack / sizeof(long);
*stack++ = syscall;
*stack++ = args[0];
*stack++ = args[1];
*stack++ = args[2];
*stack++ = args[3];
*stack++ = args[4];
*stack++ = args[5];
*stack++ = expected;
*stack = 0;
if (!done && ((((unsigned long) stack) & ~UM_KERN_PAGE_MASK) <
UM_KERN_PAGE_SIZE - 10 * sizeof(long))) {
*addr = stack;
if (mm_idp->syscall_data_len == 0)
return 0;
/* If an error happened already, report it and reset the state. */
if (mm_idp->syscall_data_len < 0) {
res = mm_idp->syscall_data_len;
mm_idp->syscall_data_len = 0;
return res;
}
return do_syscall_stub(mm_idp, addr);
res = do_syscall_stub(mm_idp);
mm_idp->syscall_data_len = 0;
return res;
}
long syscall_stub_data(struct mm_id * mm_idp,
unsigned long *data, int data_count,
void **addr, void **stub_addr)
struct stub_syscall *syscall_stub_alloc(struct mm_id *mm_idp)
{
unsigned long *stack;
int ret = 0;
struct stub_syscall *sc;
struct stub_data *proc_data = (struct stub_data *) mm_idp->stack;
/*
* If *addr still is uninitialized, it *must* contain NULL.
* Thus in this case do_syscall_stub correctly won't be called.
*/
if ((((unsigned long) *addr) & ~UM_KERN_PAGE_MASK) >=
UM_KERN_PAGE_SIZE - (10 + data_count) * sizeof(long)) {
ret = do_syscall_stub(mm_idp, addr);
/* in case of error, don't overwrite data on stack */
if (ret)
return ret;
if (mm_idp->syscall_data_len > 0 &&
mm_idp->syscall_data_len == ARRAY_SIZE(proc_data->syscall_data))
do_syscall_stub(mm_idp);
if (mm_idp->syscall_data_len < 0) {
/* Return dummy to retain error state. */
sc = &proc_data->syscall_data[0];
} else {
sc = &proc_data->syscall_data[mm_idp->syscall_data_len];
mm_idp->syscall_data_len += 1;
}
memset(sc, 0, sizeof(*sc));
stack = check_init_stack(mm_idp, *addr);
*addr = stack;
*stack = data_count * sizeof(long);
memcpy(stack + 1, data, data_count * sizeof(long));
*stub_addr = (void *)(((unsigned long)(stack + 1) &
~UM_KERN_PAGE_MASK) + STUB_DATA);
return 0;
return sc;
}
int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, int prot,
int phys_fd, unsigned long long offset, int done, void **data)
void map(struct mm_id *mm_idp, unsigned long virt, unsigned long len, int prot,
int phys_fd, unsigned long long offset)
{
int ret;
unsigned long args[] = { virt, len, prot,
MAP_SHARED | MAP_FIXED, phys_fd,
MMAP_OFFSET(offset) };
struct stub_syscall *sc;
ret = run_syscall_stub(mm_idp, STUB_MMAP_NR, args, virt,
data, done);
return ret;
sc = syscall_stub_alloc(mm_idp);
sc->syscall = STUB_SYSCALL_MMAP;
sc->mem.addr = virt;
sc->mem.length = len;
sc->mem.prot = prot;
sc->mem.fd = phys_fd;
sc->mem.offset = MMAP_OFFSET(offset);
}
int unmap(struct mm_id * mm_idp, unsigned long addr, unsigned long len,
int done, void **data)
void unmap(struct mm_id *mm_idp, unsigned long addr, unsigned long len)
{
int ret;
unsigned long args[] = { (unsigned long) addr, len, 0, 0, 0,
0 };
struct stub_syscall *sc;
ret = run_syscall_stub(mm_idp, __NR_munmap, args, 0,
data, done);
return ret;
sc = syscall_stub_alloc(mm_idp);
sc->syscall = STUB_SYSCALL_MUNMAP;
sc->mem.addr = addr;
sc->mem.length = len;
}
int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len,
unsigned int prot, int done, void **data)
void protect(struct mm_id *mm_idp, unsigned long addr, unsigned long len,
unsigned int prot)
{
int ret;
unsigned long args[] = { addr, len, prot, 0, 0, 0 };
struct stub_syscall *sc;
ret = run_syscall_stub(mm_idp, __NR_mprotect, args, 0,
data, done);
return ret;
sc = syscall_stub_alloc(mm_idp);
sc->syscall = STUB_SYSCALL_MPROTECT;
sc->mem.addr = addr;
sc->mem.length = len;
sc->mem.prot = prot;
}

View File

@ -501,7 +501,7 @@ int copy_context_skas0(unsigned long new_stack, int pid)
*data = ((struct stub_data) {
.offset = MMAP_OFFSET(new_offset),
.fd = new_fd,
.parent_err = -ESRCH,
.err = -ESRCH,
.child_err = 0,
});
@ -538,7 +538,7 @@ int copy_context_skas0(unsigned long new_stack, int pid)
wait_stub_done(pid);
pid = data->parent_err;
pid = data->err;
if (pid < 0) {
printk(UM_KERN_ERR "%s - stub-parent reports error %d\n",
__func__, -pid);

View File

@ -11,7 +11,7 @@ endif
obj-y = bugs_$(BITS).o delay.o fault.o ldt.o \
ptrace_$(BITS).o ptrace_user.o setjmp_$(BITS).o signal.o \
stub_$(BITS).o stub_segv.o \
stub_segv.o \
sys_call_table_$(BITS).o sysrq_$(BITS).o tls_$(BITS).o \
mem_$(BITS).o subarch.o os-Linux/

View File

@ -12,33 +12,22 @@
#include <os.h>
#include <skas.h>
#include <sysdep/tls.h>
#include <stub-data.h>
static inline int modify_ldt (int func, void *ptr, unsigned long bytecount)
{
return syscall(__NR_modify_ldt, func, ptr, bytecount);
}
static long write_ldt_entry(struct mm_id *mm_idp, int func,
struct user_desc *desc, void **addr, int done)
static void write_ldt_entry(struct mm_id *mm_idp, int func,
struct user_desc *desc)
{
long res;
void *stub_addr;
struct stub_syscall *sc;
BUILD_BUG_ON(sizeof(*desc) % sizeof(long));
res = syscall_stub_data(mm_idp, (unsigned long *)desc,
sizeof(*desc) / sizeof(long),
addr, &stub_addr);
if (!res) {
unsigned long args[] = { func,
(unsigned long)stub_addr,
sizeof(*desc),
0, 0, 0 };
res = run_syscall_stub(mm_idp, __NR_modify_ldt, args,
0, addr, done);
}
return res;
sc = syscall_stub_alloc(mm_idp);
sc->syscall = STUB_SYSCALL_LDT;
sc->ldt.func = func;
memcpy(&sc->ldt.desc, desc, sizeof(*desc));
}
/*
@ -127,7 +116,6 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
int i, err;
struct user_desc ldt_info;
struct ldt_entry entry0, *ldt_p;
void *addr = NULL;
err = -EINVAL;
if (bytecount != sizeof(ldt_info))
@ -148,7 +136,8 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
mutex_lock(&ldt->lock);
err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1);
write_ldt_entry(mm_idp, func, &ldt_info);
err = syscall_stub_flush(mm_idp);
if (err)
goto out_unlock;
@ -166,7 +155,8 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
err = -ENOMEM;
/* Undo the change in host */
memset(&ldt_info, 0, sizeof(ldt_info));
write_ldt_entry(mm_idp, 1, &ldt_info, &addr, 1);
write_ldt_entry(mm_idp, 1, &ldt_info);
err = syscall_stub_flush(mm_idp);
goto out_unlock;
}
if (i == 0) {
@ -303,7 +293,6 @@ long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm)
short * num_p;
int i;
long page, err=0;
void *addr = NULL;
mutex_init(&new_mm->arch.ldt.lock);
@ -318,11 +307,9 @@ long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm)
ldt_get_host_info();
for (num_p=host_ldt_entries; *num_p != -1; num_p++) {
desc.entry_number = *num_p;
err = write_ldt_entry(&new_mm->id, 1, &desc,
&addr, *(num_p + 1) == -1);
if (err)
break;
write_ldt_entry(&new_mm->id, 1, &desc);
}
err = syscall_stub_flush(&new_mm->id);
new_mm->arch.ldt.entry_count = 0;
goto out;

View File

@ -12,4 +12,5 @@
#endif
extern void stub_segv_handler(int, siginfo_t *, void *);
extern void stub_syscall_handler(void);
extern void stub_clone_handler(void);

View File

@ -1,56 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <as-layout.h>
.section .__syscall_stub, "ax"
.globl batch_syscall_stub
batch_syscall_stub:
/* %esp comes in as "top of page" */
mov %esp, %ecx
/* %esp has pointer to first operation */
add $8, %esp
again:
/* load length of additional data */
mov 0x0(%esp), %eax
/* if(length == 0) : end of list */
/* write possible 0 to header */
mov %eax, 0x4(%ecx)
cmpl $0, %eax
jz done
/* save current pointer */
mov %esp, 0x4(%ecx)
/* skip additional data */
add %eax, %esp
/* load syscall-# */
pop %eax
/* load syscall params */
pop %ebx
pop %ecx
pop %edx
pop %esi
pop %edi
pop %ebp
/* execute syscall */
int $0x80
/* restore top of page pointer in %ecx */
mov %esp, %ecx
andl $(~UM_KERN_PAGE_SIZE) + 1, %ecx
/* check return value */
pop %ebx
cmp %ebx, %eax
je again
done:
/* save return value */
mov %eax, (%ecx)
/* stop */
int3

View File

@ -1,50 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <as-layout.h>
.section .__syscall_stub, "ax"
.globl batch_syscall_stub
batch_syscall_stub:
/* %rsp has the pointer to first operation */
mov %rsp, %rbx
add $0x10, %rsp
again:
/* load length of additional data */
mov 0x0(%rsp), %rax
/* if(length == 0) : end of list */
/* write possible 0 to header */
mov %rax, 8(%rbx)
cmp $0, %rax
jz done
/* save current pointer */
mov %rsp, 8(%rbx)
/* skip additional data */
add %rax, %rsp
/* load syscall-# */
pop %rax
/* load syscall params */
pop %rdi
pop %rsi
pop %rdx
pop %r10
pop %r8
pop %r9
/* execute syscall */
syscall
/* check return value */
pop %rcx
cmp %rcx, %rax
je again
done:
/* save return value */
mov %rax, (%rbx)
/* stop */
int3