diff --git a/pkg/sentry/platform/systrap/sysmsg/sighandler_amd64.c b/pkg/sentry/platform/systrap/sysmsg/sighandler_amd64.c index 3c847db53..3215f7674 100644 --- a/pkg/sentry/platform/systrap/sysmsg/sighandler_amd64.c +++ b/pkg/sentry/platform/systrap/sysmsg/sighandler_amd64.c @@ -160,6 +160,7 @@ static void set_fsbase(uint64_t fsbase) { struct thread_context *switch_context_amd64( struct sysmsg *sysmsg, struct thread_context *ctx, enum thread_state new_thread_state, enum context_state new_context_state) { + struct thread_context *old_ctx = sysmsg->context; for (;;) { // TODO(b/271631387): Once stub code globals can be used between objects @@ -189,6 +190,9 @@ struct thread_context *switch_context_amd64( break; } } + if (old_ctx != ctx || ctx->last_thread_id != sysmsg->thread_id) { + ctx->fpstate_changed = 1; + } return ctx; } @@ -366,6 +370,20 @@ void __syshandler() { } } +void __export_start(struct sysmsg *sysmsg, void *_ucontext) { +#if defined(__x86_64__) + asm volatile("movq %%gs:0, %0\n" : "=r"(sysmsg) : :); + if (sysmsg->self != sysmsg) { + panic(0xdeaddead); + } +#endif + + struct thread_context *ctx = switch_context_amd64( + sysmsg, NULL, THREAD_STATE_EVENT, CONTEXT_STATE_INVALID); + + restore_state(sysmsg, ctx, _ucontext); +} + // asm_restore_state is implemented in syshandler_amd64.S void asm_restore_state(); diff --git a/pkg/sentry/platform/systrap/sysmsg/sighandler_arm64.c b/pkg/sentry/platform/systrap/sysmsg/sighandler_arm64.c index ad44e944b..f65e7ca8a 100644 --- a/pkg/sentry/platform/systrap/sysmsg/sighandler_arm64.c +++ b/pkg/sentry/platform/systrap/sysmsg/sighandler_arm64.c @@ -91,6 +91,10 @@ static void ptregs_to_gregs(ucontext_t *ucontext, ucontext->uc_mcontext.pstate = ptregs->pstate; } +void __export_start(struct sysmsg *sysmsg, void *_ucontext) { + panic(0x11111111); +} + void __export_sighandler(int signo, siginfo_t *siginfo, void *_ucontext) { ucontext_t *ucontext = _ucontext; void *sp = sysmsg_sp(); @@ -98,16 +102,18 @@ void __export_sighandler(int signo, siginfo_t *siginfo, void *_ucontext) { if (sysmsg != sysmsg->self) panic(0xdeaddead); int32_t thread_state = __atomic_load_n(&sysmsg->state, __ATOMIC_ACQUIRE); + + uint32_t ctx_state = CONTEXT_STATE_INVALID; + struct thread_context *ctx = NULL, *old_ctx = NULL; if (__export_context_decoupling_exp && thread_state == THREAD_STATE_INITIALIZING) { // Find a new context and exit to restore it. - __export_start(sysmsg, _ucontext); - return; + goto init; } - struct thread_context *ctx = sysmsg->context; + ctx = sysmsg->context; + old_ctx = sysmsg->context; - uint32_t ctx_state = CONTEXT_STATE_INVALID; ctx->signo = signo; gregs_to_ptregs(ucontext, &ctx->ptregs); @@ -154,6 +160,7 @@ void __export_sighandler(int signo, siginfo_t *siginfo, void *_ucontext) { return; } +init: for (;;) { if (__export_context_decoupling_exp) { ctx = switch_context(sysmsg, ctx, ctx_state); @@ -174,6 +181,10 @@ void __export_sighandler(int signo, siginfo_t *siginfo, void *_ucontext) { break; } } + + if (old_ctx != ctx || ctx->last_thread_id != sysmsg->thread_id) { + ctx->fpstate_changed = 1; + } restore_state(sysmsg, ctx, _ucontext); } diff --git a/pkg/sentry/platform/systrap/sysmsg/sysmsg_lib.c b/pkg/sentry/platform/systrap/sysmsg/sysmsg_lib.c index 88120c370..9eb282ec4 100644 --- a/pkg/sentry/platform/systrap/sysmsg/sysmsg_lib.c +++ b/pkg/sentry/platform/systrap/sysmsg/sysmsg_lib.c @@ -259,41 +259,20 @@ struct thread_context *switch_context(struct sysmsg *sysmsg, enum context_state new_context_state) { struct context_queue *queue = __export_context_queue_addr; - __atomic_sub_fetch(&queue->num_active_contexts, 1, __ATOMIC_ACQ_REL); - __atomic_store_n(&ctx->thread_id, INVALID_THREAD_ID, __ATOMIC_RELEASE); - __atomic_store_n(&ctx->last_thread_id, sysmsg->thread_id, __ATOMIC_RELEASE); - __atomic_store_n(&ctx->state, new_context_state, __ATOMIC_RELEASE); - if (__atomic_load_n(&ctx->sentry_fast_path, __ATOMIC_ACQUIRE) == 0) { - int ret = sys_futex(&ctx->state, FUTEX_WAKE, 1, NULL, NULL, 0); - if (ret < 0) { - panic(ret); + if (ctx) { + __atomic_sub_fetch(&queue->num_active_contexts, 1, __ATOMIC_ACQ_REL); + __atomic_store_n(&ctx->thread_id, INVALID_THREAD_ID, __ATOMIC_RELEASE); + __atomic_store_n(&ctx->last_thread_id, sysmsg->thread_id, __ATOMIC_RELEASE); + __atomic_store_n(&ctx->state, new_context_state, __ATOMIC_RELEASE); + if (__atomic_load_n(&ctx->sentry_fast_path, __ATOMIC_ACQUIRE) == 0) { + int ret = sys_futex(&ctx->state, FUTEX_WAKE, 1, NULL, NULL, 0); + if (ret < 0) { + panic(ret); + } } } - struct thread_context *old_ctx = sysmsg->context; - - ctx = get_context(sysmsg); - - if (old_ctx != ctx || ctx->last_thread_id != sysmsg->thread_id) { - ctx->fpstate_changed = 1; - } - - return ctx; -} - -void __export_start(struct sysmsg *sysmsg, void *_ucontext) { -#if defined(__x86_64__) - asm volatile("movq %%gs:0, %0\n" : "=r"(sysmsg) : :); - if (sysmsg->self != sysmsg) { - panic(0xdeaddead); - } -#endif - - struct thread_context *ctx = get_context(sysmsg); - __atomic_store_n(&ctx->fpstate_changed, 1, __ATOMIC_RELEASE); - __atomic_store_n(&ctx->thread_id, sysmsg->thread_id, __ATOMIC_RELEASE); - - restore_state(sysmsg, ctx, _ucontext); + return get_context(sysmsg); } int wait_state(struct sysmsg *sysmsg, enum thread_state new_thread_state) {