Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(193)

Unified Diff: src/nonsfi/linux/irt_signal_handling.c

Issue 1300883003: Revert of Non-SFI mode: Add Linux asynchronous signal support (Closed) Base URL: https://chromium.googlesource.com/native_client/src/native_client.git@master
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/nonsfi/linux/irt_signal_handling.h ('k') | src/nonsfi/linux/linux_pthread_private.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/nonsfi/linux/irt_signal_handling.c
diff --git a/src/nonsfi/linux/irt_signal_handling.c b/src/nonsfi/linux/irt_signal_handling.c
deleted file mode 100644
index 9edd3754c84b3953d30b29561a23632b44eff2d5..0000000000000000000000000000000000000000
--- a/src/nonsfi/linux/irt_signal_handling.c
+++ /dev/null
@@ -1,513 +0,0 @@
-/*
- * Copyright (c) 2015 The Native Client Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include <errno.h>
-#include <pthread.h>
-#include <signal.h>
-#include <stdint.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "native_client/src/include/elf_constants.h"
-#include "native_client/src/include/nacl/nacl_exception.h"
-#include "native_client/src/include/nacl_macros.h"
-#include "native_client/src/nonsfi/linux/irt_signal_handling.h"
-#include "native_client/src/nonsfi/linux/linux_sys_private.h"
-#include "native_client/src/nonsfi/linux/linux_syscall_defines.h"
-#include "native_client/src/nonsfi/linux/linux_syscall_structs.h"
-#include "native_client/src/public/linux_syscalls/sys/syscall.h"
-#include "native_client/src/public/nonsfi/irt_signal_handling.h"
-#include "native_client/src/untrusted/irt/irt.h"
-
-typedef struct compat_sigaltstack {
- uint32_t ss_sp;
- int32_t ss_flags;
- uint32_t ss_size;
-} linux_stack_t;
-
-#if defined(__i386__)
-
-/* From linux/arch/x86/include/uapi/asm/sigcontext32.h */
-struct sigcontext_ia32 {
- uint16_t gs, __gsh;
- uint16_t fs, __fsh;
- uint16_t es, __esh;
- uint16_t ds, __dsh;
- uint32_t di;
- uint32_t si;
- uint32_t bp;
- uint32_t sp;
- uint32_t bx;
- uint32_t dx;
- uint32_t cx;
- uint32_t ax;
- uint32_t trapno;
- uint32_t err;
- uint32_t ip;
- uint16_t cs, __csh;
- uint32_t flags;
- uint32_t sp_at_signal;
- uint16_t ss, __ssh;
- uint32_t fpstate;
- uint32_t oldmask;
- uint32_t cr2;
-};
-
-typedef struct sigcontext_ia32 linux_mcontext_t;
-
-#elif defined(__arm__)
-
-/* From linux/arch/arm/include/uapi/asm/sigcontext.h */
-struct sigcontext_arm {
- uint32_t trap_no;
- uint32_t error_code;
- uint32_t oldmask;
- uint32_t arm_r0;
- uint32_t arm_r1;
- uint32_t arm_r2;
- uint32_t arm_r3;
- uint32_t arm_r4;
- uint32_t arm_r5;
- uint32_t arm_r6;
- uint32_t arm_r7;
- uint32_t arm_r8;
- uint32_t arm_r9;
- uint32_t arm_r10;
- uint32_t arm_r11; /* fp */
- uint32_t arm_r12; /* ip */
- uint32_t arm_sp;
- uint32_t arm_lr;
- uint32_t arm_pc;
- uint32_t arm_cpsr;
- uint32_t fault_address;
-};
-
-typedef struct sigcontext_arm linux_mcontext_t;
-
-#else
-#error "unsupported architecture"
-#endif
-
-/* From linux/arch/arm/include/asm/ucontext.h */
-struct linux_ucontext_t {
- uint32_t uc_flags;
- uint32_t uc_link;
- linux_stack_t uc_stack;
- linux_mcontext_t uc_mcontext;
- linux_sigset_t uc_sigmask;
- /* More data follows which we don't care about. */
-};
-
-/*
- * Crash signals to handle. The differences from SFI NaCl are that
- * NonSFI NaCl does not use NACL_THREAD_SUSPEND_SIGNAL (==SIGUSR1),
- */
-static const int kSignals[] = {
- LINUX_SIGSTKFLT,
- LINUX_SIGINT, LINUX_SIGQUIT, LINUX_SIGILL, LINUX_SIGTRAP, LINUX_SIGBUS,
- LINUX_SIGFPE, LINUX_SIGSEGV,
- /* Handle SIGABRT in case someone sends it asynchronously using kill(). */
- LINUX_SIGABRT,
-};
-
-static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
-static NaClExceptionHandler g_signal_handler_function_pointer = NULL;
-static NaClExceptionHandler g_exception_handler_function_pointer = NULL;
-static int g_signal_handler_initialized = 0;
-static int g_tgid = 0;
-static int g_main_tid;
-
-struct NonSfiExceptionFrame {
- struct NaClExceptionContext context;
- struct NaClExceptionPortableContext portable;
-};
-
-static void machine_context_to_register(const linux_mcontext_t *mctx,
- NaClUserRegisterState *dest) {
-#if defined(__i386__)
-#define COPY_REG(A) dest->e##A = mctx->A
- COPY_REG(ax);
- COPY_REG(cx);
- COPY_REG(dx);
- COPY_REG(bx);
- COPY_REG(bp);
- COPY_REG(si);
- COPY_REG(di);
-#undef COPY_REG
- dest->stack_ptr = mctx->sp;
- dest->prog_ctr = mctx->ip;
- dest->flags = mctx->flags;
-#elif defined(__arm__)
-#define COPY_REG(A) dest->A = mctx->arm_##A
- COPY_REG(r0);
- COPY_REG(r1);
- COPY_REG(r2);
- COPY_REG(r3);
- COPY_REG(r4);
- COPY_REG(r5);
- COPY_REG(r6);
- COPY_REG(r7);
- COPY_REG(r8);
- COPY_REG(r9);
- COPY_REG(r10);
- COPY_REG(r11);
- COPY_REG(r12);
-#undef COPY_REG
- dest->stack_ptr = mctx->arm_sp;
- dest->lr = mctx->arm_lr;
- dest->prog_ctr = mctx->arm_pc;
- dest->cpsr = mctx->arm_cpsr;
-#else
-# error Unsupported architecture
-#endif
-}
-
-static void nonsfi_exception_frame_from_signal_context(
- struct NonSfiExceptionFrame *frame,
- const void *raw_ctx) {
- const struct linux_ucontext_t *uctx = (struct linux_ucontext_t *) raw_ctx;
- const linux_mcontext_t *mctx = &uctx->uc_mcontext;
- frame->context.size = (((uintptr_t) (&frame->portable + 1))
- - (uintptr_t) &frame->context);
- frame->context.portable_context_offset = ((uintptr_t) &frame->portable
- - (uintptr_t) &frame->context);
- frame->context.portable_context_size = sizeof(frame->portable);
- frame->context.regs_size = sizeof(frame->context.regs);
-
- memset(frame->context.reserved, 0, sizeof(frame->context.reserved));
- machine_context_to_register(mctx, &frame->context.regs);
- frame->portable.prog_ctr = frame->context.regs.prog_ctr;
- frame->portable.stack_ptr = frame->context.regs.stack_ptr;
-
-#if defined(__i386__)
- frame->context.arch = EM_386;
- frame->portable.frame_ptr = frame->context.regs.ebp;
-#elif defined(__arm__)
- frame->context.arch = EM_ARM;
- /* R11 is frame pointer in ARM mode, R8 is frame pointer in thumb mode. */
- frame->portable.frame_ptr = frame->context.regs.r11;
-#else
-# error Unsupported architecture
-#endif
-}
-
-/* A replacement of sigreturn. It does not restore the signal mask. */
-static void __attribute__((noreturn))
-nonsfi_restore_context(const linux_mcontext_t *mctx) {
-
-#if defined(__i386__)
-
-#define OFFSET(name) \
- [name] "i" (offsetof(linux_mcontext_t, name))
-#define RESTORE_SEGMENT(name) \
- "mov %c[" #name "](%%eax), %%" #name "\n"
-#define RESTORE(name) \
- "movl %c[" #name "](%%eax), %%e" #name "\n"
-
- __asm__ __volatile__(
- /* Restore floating-point environment */
- "mov %c[fpstate](%%eax), %%ecx\n"
- "fldenv (%%ecx)\n"
-
- /* Restore all segment registers */
- RESTORE_SEGMENT(gs)
- RESTORE_SEGMENT(fs)
- RESTORE_SEGMENT(es)
- RESTORE_SEGMENT(ds)
-
- /*
- * Restore most of the other registers.
- */
- RESTORE(di)
- RESTORE(si)
- RESTORE(bp)
- RESTORE(bx)
-
- /*
- * Prepare the last registers. eip *must* be one slot above the original
- * stack, since that is the only way eip and esp can be simultaneously
- * restored. Here, we are using ecx as the pseudo stack pointer, and edx
- * as a scratch register. Once the stack is laid out the way we want it to
- * be, restore edx and eax last.
- */
- "mov %c[sp](%%eax), %%ecx\n"
- "mov %c[ip](%%eax), %%edx\n"
- "mov %%edx, -4(%%ecx)\n"
- "mov %c[flags](%%eax), %%edx\n"
- "mov %%edx, -8(%%ecx)\n"
- "mov %c[cx](%%eax), %%edx\n"
- "mov %%edx, -12(%%ecx)\n"
- RESTORE(dx)
- RESTORE(ax)
- "lea -12(%%ecx), %%esp\n"
-
- /*
- * Finally pop ecx off the stack, restore the processor flags, and return
- * to simultaneously restore esp and eip.
- */
- "pop %%ecx\n"
- "popf\n"
- "ret\n"
- :
- : "a" (mctx),
- OFFSET(gs),
- OFFSET(fs),
- OFFSET(es),
- OFFSET(ds),
- OFFSET(di),
- OFFSET(si),
- OFFSET(bp),
- OFFSET(sp),
- OFFSET(bx),
- OFFSET(dx),
- OFFSET(cx),
- OFFSET(ax),
- OFFSET(ip),
- OFFSET(flags),
- OFFSET(fpstate)
- );
-
-#undef OFFSET
-#undef RESTORE
-#undef RESTORE_SEGMENT
-
-#elif defined(__arm__)
-
-#define OFFSET(name) \
- [name] "I" (offsetof(linux_mcontext_t, arm_ ## name) - \
- offsetof(linux_mcontext_t, arm_r0))
-
- register uint32_t a14 __asm__("r14") = (uint32_t) &mctx->arm_r0;
-
- __asm__ __volatile__(
- /* Restore flags */
- "ldr r0, [r14, %[cpsr]]\n"
- "msr APSR_nzcvqg, r0\n"
-
- /*
- * Restore general-purpose registers.
- * This code does not use the simpler 'ldmia r14, {r0-pc}' since using
- * ldmia with either sp or with both lr and pc is deprecated.
- */
- "ldmia r14, {r0-r10}\n"
-
- /*
- * Copy r11, r12, lr, and pc just before the original sp.
- * r12 will work as a temporary sp. r11 will be the scratch register, and
- * will be restored just before moving sp.
- */
- "ldr r12, [r14, %[sp]]\n"
-
- "ldr r11, [r14, %[pc]]\n"
- "stmdb r12!, {r11}\n"
- "ldr r11, [r14, %[lr]]\n"
- "stmdb r12!, {r11}\n"
- "ldr r11, [r14, %[r12]]\n"
- "stmdb r12!, {r11}\n"
- "ldr r11, [r14, %[r11]]\n"
- "mov sp, r12\n"
-
- /*
- * Restore r12, lr, and pc. sp will point to the correct location once
- * we're done.
- */
- "pop {r12, lr}\n"
- "pop {pc}\n"
- :
- : "r" (a14),
- OFFSET(cpsr),
- OFFSET(r11),
- OFFSET(r12),
- OFFSET(sp),
- OFFSET(lr),
- OFFSET(pc)
- );
-
-#undef OFFSET
-
-#else
-# error Unsupported architecture
-#endif
-
- /* Should never reach this. */
- __builtin_trap();
-}
-
-static __attribute__((noreturn))
-void restore_context(void *raw_ctx) {
- const struct linux_ucontext_t *uctx = (struct linux_ucontext_t *) raw_ctx;
- const linux_mcontext_t *mctx = &uctx->uc_mcontext;
- nonsfi_restore_context(mctx);
-}
-
-/* Signal handlers, responsible for calling the registered handlers. */
-static void exception_catch(int sig, linux_siginfo_t *info, void *uc) {
- if (g_exception_handler_function_pointer) {
- struct NonSfiExceptionFrame exception_frame;
- nonsfi_exception_frame_from_signal_context(&exception_frame, uc);
- g_exception_handler_function_pointer(&exception_frame.context);
- }
- _exit(-sig);
-}
-
-static void signal_catch(int sig, linux_siginfo_t *info, void *uc) {
- if (g_signal_handler_function_pointer) {
- struct NonSfiExceptionFrame exception_frame;
- nonsfi_exception_frame_from_signal_context(&exception_frame, uc);
- g_signal_handler_function_pointer(&exception_frame.context);
- }
- restore_context(uc);
-}
-
-static void nonsfi_install_exception_handler_locked() {
- struct linux_sigaction sa;
- unsigned int a;
-
- memset(&sa, 0, sizeof(sa));
- sa.sa_sigaction = exception_catch;
- sa.sa_flags = LINUX_SA_SIGINFO | LINUX_SA_ONSTACK;
-
- /*
- * Reuse the sigemptyset/sigaddset for the first 32 bits of the
- * sigmask. Works on little endian systems only.
- */
- sigset_t *mask = (sigset_t*)&sa.sa_mask;
- sigemptyset(mask);
-
- /* Mask all signals we catch to prevent re-entry. */
- for (a = 0; a < NACL_ARRAY_SIZE(kSignals); a++) {
- sigaddset(mask, kSignals[a]);
- }
-
- /* Install all handlers. */
- for (a = 0; a < NACL_ARRAY_SIZE(kSignals); a++) {
- if (linux_sigaction(kSignals[a], &sa, NULL) != 0)
- abort();
- }
-}
-
-static void nonsfi_install_signal_handler_locked() {
- struct linux_sigaction sa;
-
- memset(&sa, 0, sizeof(sa));
- sa.sa_sigaction = signal_catch;
-
- /*
- * User signal handler can be recursively interrupted to avoid having
- * to allow sigreturn/sigprocmask.
- */
- sa.sa_flags = LINUX_SA_SIGINFO | LINUX_SA_NODEFER | LINUX_SA_RESTART;
- sigset_t *mask = (sigset_t*)&sa.sa_mask;
- sigemptyset(mask);
-
- /*
- * Install a single handler. Multiple signals can be multiplexed in
- * userspace.
- */
- if (linux_sigaction(LINUX_SIGUSR1, &sa, NULL) != 0)
- abort();
-}
-
-static void nonsfi_initialize_signal_handler_locked() {
- if (g_signal_handler_initialized)
- return;
- pid_t tgid = getpid();
- if (tgid == -1)
- abort();
- pid_t main_tid = syscall(__NR_gettid);
- if (main_tid == -1)
- abort();
- nonsfi_install_exception_handler_locked();
- nonsfi_install_signal_handler_locked();
- g_tgid = tgid;
- g_main_tid = main_tid;
- g_signal_handler_initialized = 1;
-}
-
-/*
- * Initialize signal handlers before entering sandbox.
- */
-void nonsfi_initialize_signal_handler() {
- if (pthread_mutex_lock(&g_mutex) != 0)
- abort();
- nonsfi_initialize_signal_handler_locked();
- if (pthread_mutex_unlock(&g_mutex) != 0)
- abort();
-}
-
-int nacl_exception_get_and_set_handler(NaClExceptionHandler handler,
- NaClExceptionHandler *old_handler) {
- if (pthread_mutex_lock(&g_mutex) != 0)
- abort();
- nonsfi_initialize_signal_handler_locked();
- if (old_handler)
- *old_handler = g_exception_handler_function_pointer;
- g_exception_handler_function_pointer = handler;
- if (pthread_mutex_unlock(&g_mutex) != 0)
- abort();
- return 0;
-}
-
-int nacl_exception_set_handler(NaClExceptionHandler handler) {
- return nacl_exception_get_and_set_handler(handler, NULL);
-}
-
-int nacl_exception_clear_flag(void) {
- /*
- * Unblock signals, useful for unit testing and continuing to
- * process after fatal signal.
- */
-
- /* Allocate the 8 bytes of signal mask. */
- linux_sigset_t mask;
-
- /*
- * sigemptyset will only clear first 4 bytes of sigset_t, and
- * compat_sigset_t has 8 bytes, clear with memset.
- */
- memset(&mask, 0, sizeof(mask));
-
- /*
- * Hack to be able to reuse sigset_t utilities from newlib for the
- * first lower 4 bytes of the signal, works because we are all
- * little endians.
- */
- sigset_t *maskptr = (sigset_t *) &mask;
- sigemptyset(maskptr);
- for (int a = 0; a < NACL_ARRAY_SIZE(kSignals); a++) {
- if (sigaddset(maskptr, kSignals[a]) != 0)
- abort();
- }
- if (linux_sigprocmask(LINUX_SIG_UNBLOCK, &mask, NULL) != 0)
- abort();
-
- return 0;
-}
-
-int nacl_exception_set_stack(void *p, size_t s) {
- /* Not implemented yet. */
- return ENOSYS;
-}
-
-int nacl_async_signal_set_handler(NaClIrtAsyncSignalHandler handler) {
- if (pthread_mutex_lock(&g_mutex) != 0)
- abort();
- nonsfi_initialize_signal_handler_locked();
- g_signal_handler_function_pointer = handler;
- if (pthread_mutex_unlock(&g_mutex) != 0)
- abort();
- return 0;
-}
-
-int nacl_async_signal_send_async_signal(nacl_irt_tid_t tid) {
- if (!g_signal_handler_initialized)
- return ESRCH;
- if (tid == 0)
- tid = g_main_tid;
- if (linux_tgkill(g_tgid, tid, LINUX_SIGUSR1) == -1)
- return errno;
- return 0;
-}
« no previous file with comments | « src/nonsfi/linux/irt_signal_handling.h ('k') | src/nonsfi/linux/linux_pthread_private.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698