Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions core/arch/arm64/regs.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,8 @@ lfi_ctx_regs_init(struct LFIContext *ctx)
ctx->ctxreg[CTXREG_CTX_OFFSET / 8] = (uint64_t) ctx;
#endif
}

EXPORT void
lfi_ctx_thread_regs_init(struct LFIContext* ctx)
{
}
5 changes: 5 additions & 0 deletions core/arch/riscv64/regs.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,8 @@ lfi_ctx_regs_init(struct LFIContext *ctx)
ctx->regs.ra = ctx->box->base;
ctx->regs.retaddr = ctx->box->retaddr;
}

EXPORT void
lfi_ctx_thread_regs_init(struct LFIContext* ctx)
{
}
4 changes: 4 additions & 0 deletions core/arch/x64/arch_callback.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

#include <stdint.h>

#ifdef LARGE_SANDBOX
#define MAXCALLBACKS 40960
#else
#define MAXCALLBACKS 4096
#endif

// A CallbackEntry is what gets inserted into the sandbox when a new callback
// is registered. It consists of 16 bytes of code, which performs the callback
Expand Down
8 changes: 7 additions & 1 deletion core/arch/x64/callback.S
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
1:

#ifdef ENABLE_SEGUE
# ifndef SEGUE_SINGLE_SANDBOX
# ifndef SINGLE_SANDBOX
wrgsbase %REG_BASE
# endif
#endif
Expand Down Expand Up @@ -132,8 +132,14 @@

// NOTE: This pop instruction could fault.
popq %r11
#ifdef LARGE_SANDBOX
andq %REG_MASK, %r11
andq $0xffffffffffffffe0, %r11
addq %REG_BASE, %r11
#else
andl $0xffffffe0, %r11d
addq %REG_BASE, %r11
#endif
jmpq *%r11
.endm

Expand Down
13 changes: 13 additions & 0 deletions core/arch/x64/regs.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,23 @@ lfi_ctx_regs_init(struct LFIContext *ctx)
ctx->regs.pkey = ctx->box->pkey;
ctx->regs.fcw = 0x37f;
ctx->regs.mxcsr = 0x1f80;
#ifdef LARGE_SANDBOX
ctx->regs.REG_MASK = ctx->box->size - 1;
ctx->regs._tp = 0;
#else
#ifdef CTXREG
ctx->regs.r15 = (uint64_t) ctx->ctxreg;
ctx->ctxreg[CTXREG_CTX_OFFSET / 8] = (uint64_t) ctx;
#else
ctx->regs.r15 = 0x00000000ffffffff;
#endif
#endif
}

EXPORT void
lfi_ctx_thread_regs_init(struct LFIContext* ctx)
{
#if defined(LARGE_SANDBOX) && defined(SINGLE_SANDBOX)
__asm__ __volatile__("wrgsbase %0" : : "r"(ctx->regs._tp));
#endif
}
2 changes: 1 addition & 1 deletion core/arch/x64/runtime.S
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ lfi_syscall_entry:
// NOTE: consider removing this entirely if we can assume that syscall
// execution never modifies %gs (i.e., never calls into another sandbox).
#ifdef ENABLE_SEGUE
# ifndef SEGUE_SINGLE_SANDBOX
# ifndef SINGLE_SANDBOX
wrgsbase %REG_BASE
# endif
#endif
Expand Down
124 changes: 123 additions & 1 deletion core/arch/x64/trampoline.S
Original file line number Diff line number Diff line change
Expand Up @@ -210,22 +210,144 @@ lfi_trampoline_direct:
movq REGS_BASE(%r11), %REG_BASE
// also write base to %gs
#ifdef ENABLE_SEGUE
# ifndef SEGUE_SINGLE_SANDBOX
# ifndef SINGLE_SANDBOX
wrgsbase %REG_BASE
# endif
#endif

#ifdef LARGE_SANDBOX
// load sandbox mask
movq REGS_MASK(%r11), %REG_MASK
#endif

// load address of the lfi_retfn function that will make the return rtcall
movq REGS_RETADDR(%r11), %r11
// align stack
andq $0xfffffffffffffff0, %rsp
// push this as the return address onto the sandbox stack
pushq %r11

// load address of the target function
movq %r12, %r11
// apply mask just to be safe
#ifdef LARGE_SANDBOX
andq %r15, %r11
andq $0xffffffffffffffe0, %r11
#else
andl $0xffffffe0, %r11d
#endif
addq %REG_BASE, %r11

// set the sandbox thread control block by saving the old value of
// %fs:TLS_SLOT_LFI into the context and setting it to point to the context
// itself
get_ctx %r12
movq (%r13), %r13
movq %r12, REGS_HOST_TP(%r13)
write_ctx %r13

#ifndef STORES_ONLY
fldcw REGS_FCW(%r13)
ldmxcsr REGS_MXCSR(%r13)
#endif

#ifdef HAVE_PKU
movq %rcx, %rbx
movq %rdx, %rbp
pku_box_access REGS_PKEY(%r13)
movq %rbp, %rdx
movq %rbx, %rcx
#endif

#ifndef STORES_ONLY
// Zero non-argument registers for full LFI.
zero_regs
#endif

// this function should return via a runtime call
jmpq *%r11
int3

// Direct trampoline that doesn't involve a thread-local lookup. Instead the
// info usually passed via the lfi_invoke_info thread-local are passed via
// the stack:
// (%rsp+24): n_stack (unused)
// (%rsp+16): lfiptr target
// (%rsp+8): struct LFIContext *box
// (%rsp): struct LFIContext **ctxp
.global lfi_trampoline_stack_args
.p2align 4
lfi_trampoline_stack_args:
// ctxp
popq %r11
// box
popq %r10

// save callee-saved registers
xchgq %r15, (%rsp)
// xchgq %r14, -8(%rsp) not included yet
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rbp

// Put arguments where we expect them.
movq %r15, %r12 // target
movq %r11, %r13 // ctxp
movq %r14, %r15 // n_stack
movq %r10, %r14 // box

lazy_ctx_clone

// dummy push to keep the stack aligned
pushq %rbp
// push sandbox rsp
pushq REGS_RSP(%r11)

// save current host stack
movq %rsp, REGS_HOST_SP(%r11)
// load sandbox rsp
movq REGS_RSP(%r11), %rsp
// load sandbox base
movq REGS_BASE(%r11), %REG_BASE
// also write base to %gs
#ifdef ENABLE_SEGUE
# ifndef SINGLE_SANDBOX
wrgsbase %REG_BASE
# endif
#endif

#ifdef LARGE_SANDBOX
// load sandbox mask
movq REGS_MASK(%r11), %REG_MASK
#endif

// save application stack pointer to copy arguments below
movq REGS_HOST_SP(%r11), %r10
// load address of the lfi_retfn function that will make the return rtcall
movq REGS_RETADDR(%r11), %r11
// align stack
andq $0xfffffffffffffff0, %rsp

// copy stack arguments
pushq 96(%r10)
pushq 88(%r10)
pushq 80(%r10)
pushq 72(%r10)

// push this as the return address onto the sandbox stack
pushq %r11

// load address of the target function
movq %r12, %r11
// apply mask just to be safe
#ifdef LARGE_SANDBOX
andq %r15, %r11
andq $0xffffffffffffffe0, %r11
#else
andl $0xffffffe0, %r11d
#endif
addq %REG_BASE, %r11

// set the sandbox thread control block by saving the old value of
Expand Down
6 changes: 5 additions & 1 deletion core/arch_asm.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,13 @@
#define REGS_XMM(n) (REGS_XMM0 + 16 * n)

#define REGS_BASE REGS_R14

#define REG_BASE r14

#ifdef LARGE_SANDBOX
#define REGS_MASK REGS_R15
#define REG_MASK r15
#endif

#define CTX_ABORT_CALLBACK 448
#define CTX_ABORT_STATUS 456

Expand Down
2 changes: 1 addition & 1 deletion core/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ lfi_new(struct LFIOptions opts, size_t nsandboxes)
}

struct BoxMapOptions bm_opts = (struct BoxMapOptions) {
.chunksize = gb(4),
.chunksize = opts.boxsize,
.guardsize = REGION_GUARD,
};
struct BoxMap *bm = boxmap_new(bm_opts);
Expand Down
5 changes: 5 additions & 0 deletions core/include/lfi_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,11 @@ lfi_ctx_set_tp(struct LFIContext *ctx, uint64_t tp);
void
lfi_ctx_regs_init(struct LFIContext *ctx);

// Used to set sandbox context registers that can be set once per-thread
// rather than having to be set on each transition.
void
lfi_ctx_thread_regs_init(struct LFIContext* ctx);

// Causes the sandbox context to exit with a given exit code.
void
lfi_ctx_exit(struct LFIContext *ctx, int code);
Expand Down
3 changes: 3 additions & 0 deletions linux/linux.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ struct SysInfo {
typedef int linux_clockid_t;
typedef int64_t linux_time_t;

// First TID, to avoid using low TID numbers.
#define BASE_TID 10000

#define LINUX_EPERM 1
#define LINUX_ENOENT 2
#define LINUX_ENXIO 6
Expand Down
2 changes: 1 addition & 1 deletion linux/sys.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ syshandle(struct LFILinuxThread *t, uintptr_t sysno, uintptr_t a0, uintptr_t a1,
// clang-format off
switch (sysno) {
SYS(getpid,
0)
BASE_TID)
SYS(write,
sys_write(t, a0, a1, a2))
SYS(writev,
Expand Down
1 change: 1 addition & 0 deletions linux/sys/sys_arch_prctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ sys_arch_prctl(struct LFILinuxThread *t, int code, lfiptr addr)
return -LINUX_ENOSYS;
#else
lfi_ctx_set_tp(t->ctx, addr);
lfi_ctx_thread_regs_init(t->ctx);
return 0;
#endif
default:
Expand Down
8 changes: 8 additions & 0 deletions linux/sys/sys_clone.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ threadspawn_fake(struct LFILinuxThread *t)
#error "invalid arch"
#endif

lfi_ctx_thread_regs_init(t->ctx);
int code = lfi_ctx_run(t->ctx, entry);
assert(code == 0);
}
Expand Down Expand Up @@ -90,6 +91,7 @@ threadspawn(void *arg)
pthread_cond_signal(&t->cond_ready);
unlock(&t->lk_ready);

lfi_ctx_thread_regs_init(t->ctx);
lfi_ctx_run(t->ctx, entry);

end:
Expand Down Expand Up @@ -152,6 +154,8 @@ spawn(struct LFILinuxThread *p, uint64_t flags, uint64_t stack, uint64_t ptidp,
struct LFIRegs *regs = lfi_ctx_regs(p2->ctx);
if (flags & LINUX_CLONE_SETTLS) {
lfi_ctx_set_tp(p2->ctx, tls);
} else {
lfi_ctx_set_tp(p2->ctx, 0);
}
if (flags & LINUX_CLONE_CHILD_CLEARTID) {
p2->ctidp = ctidp;
Expand Down Expand Up @@ -184,6 +188,10 @@ spawn(struct LFILinuxThread *p, uint64_t flags, uint64_t stack, uint64_t ptidp,
threadspawn_fake(p2);
lfi_invoke_info = old;
new_ctx = p2->ctx;

// threadspawn_fake may have clobbered context specific per-thread
// registers.
lfi_ctx_thread_regs_init(p->ctx);
} else {
pthread_t *thread = malloc(sizeof(pthread_t));
pthread_attr_t attr;
Expand Down
2 changes: 0 additions & 2 deletions linux/thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ host_getauxval(unsigned long type)
}
#endif

// First TID, to avoid using low TID numbers.
#define BASE_TID 10000
// Maximum number of argv arguments.
#define ARGV_MAX 1024
// Maxmimum number of envp arguments.
Expand Down
3 changes: 3 additions & 0 deletions linux/trampoline.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,15 @@ lfi_linux_clone_cb(struct LFIBox *box)

// Invoke thread_create in clone_ctx and return the resulting new_ctx.
LOCK_WITH_DEFER(&proc->lk_clone, lk_clone);
lfi_ctx_thread_regs_init(proc->clone_ctx);
lfiptr pt = LFI_INVOKE(box, &proc->clone_ctx, proc->libsyms.thread_create,
lfiptr, (void) );

struct LFILinuxThread *thread = lfi_ctx_data(new_ctx);
thread->box_pthread = pt;
pthread_setspecific(thread_key, new_ctx);

lfi_ctx_thread_regs_init(new_ctx);
return new_ctx;
}

Expand All @@ -102,6 +104,7 @@ thread_destructor(void *p)
thread->box_pthread);

LOCK_WITH_DEFER(&proc->lk_clone, lk_clone);
lfi_ctx_thread_regs_init(proc->clone_ctx);
LFI_INVOKE(proc->box, &proc->clone_ctx, proc->libsyms.free, void, (lfiptr),
thread->box_pthread);

Expand Down
7 changes: 5 additions & 2 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,11 @@ endif
if get_option('enable_segue')
defines += '-DENABLE_SEGUE'
endif
if get_option('segue_single_sandbox')
defines += '-DSEGUE_SINGLE_SANDBOX'
if get_option('single_sandbox')
defines += '-DSINGLE_SANDBOX'
endif
if get_option('large_sandbox')
defines += '-DLARGE_SANDBOX'
endif
if get_option('sys_minimal')
defines += '-DSYS_MINIMAL'
Expand Down
7 changes: 6 additions & 1 deletion meson_options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,16 @@ option('enable_segue',
value: true,
description: 'use %gs for the sandbox base (x86-64 only)')

option('segue_single_sandbox',
option('single_sandbox',
type: 'boolean',
value: false,
description: 'assume that %gs is never modified by the host, and there is only one sandbox (x86-64 only)')

option('large_sandbox',
type: 'boolean',
value: false,
description: 'allow creation of sandboxes with sizes larger than 4GB (x86-64 only)')

option('enable_pku',
type: 'boolean',
value: false,
Expand Down
Loading
Loading