/* Returns 1 if Data Execution Prevention is present and working */ static int AttemptToExecuteData() { int result; char *thunk_buffer = g_malloc(64); nacl_void_thunk thunk; /* d'b: small fixes */ if(thunk_buffer == NULL) return 0; thunk = GenerateThunk(thunk_buffer, 64); setup_signals(); if(0 == sigsetjmp(try_state, 1)) { thunk(); result = 0; } else { result = 1; } restore_signals(); g_free(thunk_buffer); return result; }
int main(int argc, char *argv[]) { int sockfd,r=0; if (argc != 3) { fprintf(stderr,"usage: %s server_hostname_or_ip port\n",argv[0]); return 1; } if(init_signals()==-1) { return 1; } sockfd=connect_to(argv[1],argv[2]); if(sockfd==INVALID_SOCKET) { return 1; } if(get_file(sockfd)==-1) { r=1; } if(close(sockfd)==-1) { perror("close"); r=1; } if(restore_signals()==-1) { r=1; } return r; }
int initialize_signals() { struct sigaction sa; for (size_t i = 0; i < sizeof(signals_used)/sizeof(signals_used[0]); i++) { if (!sd_is_handler_registered(signals_used[i].port_sig) && signals_used[i].signal != SIGSEGV) // Sigsegv is needed for port_memaccess continue; sigemptyset(&sa.sa_mask); sa.sa_flags = signals_used[i].flags; sa.sa_sigaction = &general_signal_handler; if (0 != sigaction(signals_used[i].signal, &sa, &old_actions[i])) { restore_signals(); return -1; } signals_used[i].set_up = true; } for (size_t j = 0; j < sizeof(signals_other)/sizeof(signals_other[0]); j++) { old_handlers[j] = signal(signals_other[j].signal, signals_other[j].handler); if (old_handlers[j] == SIG_ERR) { restore_signals(); return -1; } signals_other[j].set_up = true; } // Prepare gdb crash handler if (!init_gdb_crash_handler()) { restore_signals(); return -1; } return 0; } //initialize_signals
int thr_sigsetmask(int how, const sigset_t *set, sigset_t *oset) { ulwp_t *self = curthread; sigset_t saveset; if (set == NULL) { enter_critical(self); if (oset != NULL) *oset = self->ul_sigmask; exit_critical(self); } else { switch (how) { case SIG_BLOCK: case SIG_UNBLOCK: case SIG_SETMASK: break; default: return (EINVAL); } /* * The assignments to self->ul_sigmask must be protected from * signals. The nuances of this code are subtle. Be careful. */ block_all_signals(self); if (oset != NULL) saveset = self->ul_sigmask; switch (how) { case SIG_BLOCK: self->ul_sigmask.__sigbits[0] |= set->__sigbits[0]; self->ul_sigmask.__sigbits[1] |= set->__sigbits[1]; self->ul_sigmask.__sigbits[2] |= set->__sigbits[2]; self->ul_sigmask.__sigbits[3] |= set->__sigbits[3]; break; case SIG_UNBLOCK: self->ul_sigmask.__sigbits[0] &= ~set->__sigbits[0]; self->ul_sigmask.__sigbits[1] &= ~set->__sigbits[1]; self->ul_sigmask.__sigbits[2] &= ~set->__sigbits[2]; self->ul_sigmask.__sigbits[3] &= ~set->__sigbits[3]; break; case SIG_SETMASK: self->ul_sigmask.__sigbits[0] = set->__sigbits[0]; self->ul_sigmask.__sigbits[1] = set->__sigbits[1]; self->ul_sigmask.__sigbits[2] = set->__sigbits[2]; self->ul_sigmask.__sigbits[3] = set->__sigbits[3]; break; } delete_reserved_signals(&self->ul_sigmask); if (oset != NULL) *oset = saveset; restore_signals(self); } return (0); }
/* * Threads restoration via sigreturn. Note it's locked * routine and calls for unlock at the end. */ long __export_restore_thread(struct thread_restore_args *args) { struct rt_sigframe *rt_sigframe; k_rtsigset_t to_block; unsigned long new_sp; int my_pid = sys_gettid(); int ret; if (my_pid != args->pid) { pr_err("Thread pid mismatch %d/%d\n", my_pid, args->pid); goto core_restore_end; } /* All signals must be handled by thread leader */ ksigfillset(&to_block); ret = sys_sigprocmask(SIG_SETMASK, &to_block, NULL, sizeof(k_rtsigset_t)); if (ret) { pr_err("Unable to block signals %d", ret); goto core_restore_end; } rt_sigframe = (void *)args->mem_zone.rt_sigframe; if (restore_thread_common(rt_sigframe, args)) goto core_restore_end; ret = restore_creds(&args->ta->creds); if (ret) goto core_restore_end; ret = restore_dumpable_flag(&args->ta->mm); if (ret) goto core_restore_end; pr_info("%ld: Restored\n", sys_gettid()); restore_finish_stage(CR_STATE_RESTORE); if (restore_signals(args->siginfo, args->siginfo_nr, false)) goto core_restore_end; restore_finish_stage(CR_STATE_RESTORE_SIGCHLD); restore_pdeath_sig(args); restore_finish_stage(CR_STATE_RESTORE_CREDS); futex_dec_and_wake(&thread_inprogress); new_sp = (long)rt_sigframe + SIGFRAME_OFFSET; rst_sigreturn(new_sp); core_restore_end: pr_err("Restorer abnormal termination for %ld\n", sys_getpid()); futex_abort_and_wake(&task_entries->nr_in_progress); sys_exit_group(1); return -1; }
VALUE furnsh(int argc, VALUE *argv, VALUE self) { sigset_t old_mask = block_signals(); furnsh_c(StringValuePtr(argv[0])); restore_signals(old_mask); if(spice_error(SHORT)) return Qfalse; return Qtrue; }
static VALUE unload(VALUE self, VALUE kernel) { sigset_t old_mask = block_signals(); unload_c(StringValuePtr(kernel)); restore_signals(old_mask); if(spice_error(SPICE_ERROR_SHORT)) return Qfalse; return Qtrue; }
/** Initializes all ncurses' related stuff (windows, colors...). * There's no need to call 'engine_exit' */ bool engine_init() { /* signals during initialization */ block_signals(); engine_screen_init(80, 24); engine_windows_init(); engine_keymap(NULL); restore_signals(); register_signal_handler(); return true; }
void xmutex_unlock(struct xmutex * lock, sigset_t sigset) { TRACE(MUTEX, "thread %d:%d is unlocking %p\n", sys_getpid(), sys_gettid(), lock); /* atomic_dec(&lock->val) != 1 */ if (!atomic_dec_and_test(&lock->val)) { atomic_set(&lock->val, 0); futex_wake(&lock->val, 1); } restore_signals(sigset); TRACE(MUTEX, "thread %d:%d unlocked %p\n", sys_getpid(), sys_gettid(), lock); }
/* * Returns 1 if Data Execution Prevention is present and working. */ int NaClAttemptToExecuteData() { int result; char *thunk_buffer = malloc(64); nacl_void_thunk thunk = NaClGenerateThunk(thunk_buffer, 64); setup_signals(); if (0 == sigsetjmp(try_state, 1)) { thunk(); result = 0; } else { result = 1; } restore_signals(); return result; }
/* * Threads restoration via sigreturn. Note it's locked * routine and calls for unlock at the end. */ long __export_restore_thread(struct thread_restore_args *args) { struct rt_sigframe *rt_sigframe; unsigned long new_sp; int my_pid = sys_gettid(); int ret; if (my_pid != args->pid) { pr_err("Thread pid mismatch %d/%d\n", my_pid, args->pid); goto core_restore_end; } rt_sigframe = (void *)args->mem_zone.rt_sigframe + 8; if (restore_thread_common(rt_sigframe, args)) goto core_restore_end; mutex_unlock(&args->ta->rst_lock); ret = restore_creds(&args->ta->creds); if (ret) goto core_restore_end; pr_info("%ld: Restored\n", sys_gettid()); restore_finish_stage(CR_STATE_RESTORE); if (restore_signals(args->siginfo, args->siginfo_nr, false)) goto core_restore_end; restore_finish_stage(CR_STATE_RESTORE_SIGCHLD); restore_finish_stage(CR_STATE_RESTORE_CREDS); futex_dec_and_wake(&thread_inprogress); new_sp = (long)rt_sigframe + SIGFRAME_OFFSET; ARCH_RT_SIGRETURN(new_sp); core_restore_end: pr_err("Restorer abnormal termination for %ld\n", sys_getpid()); futex_abort_and_wake(&task_entries->nr_in_progress); sys_exit_group(1); return -1; }
int NaClAttemptToExecuteDataAtAddr(char *thunk_buffer, size_t size) { int result; MachExceptionHandlerData saved_handlers; nacl_void_thunk thunk = NaClGenerateThunk(thunk_buffer, size); setup_signals(); DisableMachExceptionHandler(&saved_handlers); if (0 == sigsetjmp(try_state, 1)) { thunk(); result = 0; } else { result = 1; } EnableMachExceptionHandler(&saved_handlers); restore_signals(); return result; }
int main(int argc, char* argv[]) { // parse options addpd::options options(argc, argv); // create server server s(options.port(), options.multicast()); // run server in background thread sigset_t sigmask = block_signals(); boost::thread t(boost::bind(&server::run, &s)); restore_signals(sigmask); // wait for signal to terminate wait_for_signal(); // stop the server s.stop(); t.join(); return 0; }
void shell_out(void){ char *comspec; #ifndef __TURBOC__ char key; int val; char *str; #endif /* __TURBOC__ */ save_screen(); clear_screen(); puts("[Entering DOS shell, type exit to return to game.]"); msdos_noraw(); ignore_signals(); if((comspec=getenv("COMSPEC")) ==NULL || spawnl(P_WAIT,comspec,comspec,(char *)NULL)<0){ puts("Sorry, there seems to be a problem with shell_out()"); printf("comspec = %s\n",comspec); flush(); puts("Hit a key to continue"); while(!kbhit()) ; } restore_signals(); restore_screen(); }
void julia_init(char *imageFile) { (void)uv_default_loop(); restore_signals(); //XXX: this needs to be early in load process jl_page_size = sysconf(_SC_PAGESIZE); jl_find_stack_bottom(); jl_dl_handle = jl_load_dynamic_library(NULL); #if defined(__linux__) int ncores = jl_cpu_cores(); if (ncores > 1) { cpu_set_t cpumask; CPU_ZERO(&cpumask); for(int i=0; i < ncores; i++) { CPU_SET(i, &cpumask); } sched_setaffinity(0, sizeof(cpu_set_t), &cpumask); } #endif #ifdef JL_GC_MARKSWEEP jl_gc_init(); jl_gc_disable(); #endif jl_init_frontend(); jl_init_types(); jl_init_tasks(jl_stack_lo, jl_stack_hi-jl_stack_lo); jl_init_codegen(); jl_an_empty_cell = (jl_value_t*)jl_alloc_cell_1d(0); jl_init_serializer(); if (!imageFile) { jl_main_module = jl_new_module(jl_symbol("Main")); jl_main_module->parent = jl_main_module; jl_core_module = jl_new_module(jl_symbol("Core")); jl_core_module->parent = jl_main_module; jl_set_const(jl_main_module, jl_symbol("Core"), (jl_value_t*)jl_core_module); jl_module_using(jl_main_module, jl_core_module); jl_current_module = jl_core_module; jl_init_intrinsic_functions(); jl_init_primitives(); jl_load("boot.jl"); jl_get_builtin_hooks(); jl_boot_file_loaded = 1; jl_init_box_caches(); } if (imageFile) { JL_TRY { jl_restore_system_image(imageFile); } JL_CATCH { JL_PRINTF(JL_STDERR, "error during init:\n"); jl_show(jl_stderr_obj(), jl_exception_in_transit); JL_PRINTF(JL_STDOUT, "\n"); jl_exit(1); } } // set module field of primitive types int i; void **table = jl_core_module->bindings.table; for(i=1; i < jl_core_module->bindings.size; i+=2) { if (table[i] != HT_NOTFOUND) { jl_binding_t *b = (jl_binding_t*)table[i]; if (b->value && jl_is_some_tag_type(b->value)) { jl_tag_type_t *tt = (jl_tag_type_t*)b->value; tt->name->module = jl_core_module; } } } // the Main module is the one which is always open, and set as the // current module for bare (non-module-wrapped) toplevel expressions. // it does "using Base" if Base is available. if (jl_base_module != NULL) jl_module_using(jl_main_module, jl_base_module); jl_current_module = jl_main_module; #ifndef __WIN32__ struct sigaction actf; memset(&actf, 0, sizeof(struct sigaction)); sigemptyset(&actf.sa_mask); actf.sa_handler = fpe_handler; actf.sa_flags = 0; if (sigaction(SIGFPE, &actf, NULL) < 0) { JL_PRINTF(JL_STDERR, "sigaction: %s\n", strerror(errno)); jl_exit(1); } stack_t ss; ss.ss_flags = 0; ss.ss_size = SIGSTKSZ; ss.ss_sp = malloc(ss.ss_size); if (sigaltstack(&ss, NULL) < 0) { JL_PRINTF(JL_STDERR, "sigaltstack: %s\n", strerror(errno)); jl_exit(1); } struct sigaction act; memset(&act, 0, sizeof(struct sigaction)); sigemptyset(&act.sa_mask); act.sa_sigaction = segv_handler; act.sa_flags = SA_ONSTACK | SA_SIGINFO; if (sigaction(SIGSEGV, &act, NULL) < 0) { JL_PRINTF(JL_STDERR, "sigaction: %s\n", strerror(errno)); jl_exit(1); } #endif atexit(jl_atexit_hook); #ifdef JL_GC_MARKSWEEP jl_gc_enable(); #endif }
/* * The main routine to restore task via sigreturn. * This one is very special, we never return there * but use sigreturn facility to restore core registers * and jump execution to some predefined ip read from * core file. */ long __export_restore_task(struct task_restore_core_args *args) { long ret = -1; VmaEntry *vma_entry; u64 va; unsigned long premmapped_end = args->premmapped_addr + args->premmapped_len; struct rt_sigframe *rt_sigframe; unsigned long new_sp; pid_t my_pid = sys_getpid(); rt_sigaction_t act; task_entries = args->task_entries; ksigfillset(&act.rt_sa_mask); act.rt_sa_handler = sigchld_handler; act.rt_sa_flags = SA_SIGINFO | SA_RESTORER | SA_RESTART; act.rt_sa_restorer = cr_restore_rt; sys_sigaction(SIGCHLD, &act, NULL, sizeof(k_rtsigset_t)); log_set_fd(args->logfd); log_set_loglevel(args->loglevel); cap_last_cap = args->cap_last_cap; pr_info("Switched to the restorer %d\n", my_pid); for (vma_entry = args->self_vmas; vma_entry->start != 0; vma_entry++) { unsigned long addr = vma_entry->start; unsigned long len; if (!vma_entry_is(vma_entry, VMA_AREA_REGULAR)) continue; pr_debug("Examine %"PRIx64"-%"PRIx64"\n", vma_entry->start, vma_entry->end); if (addr < args->premmapped_addr) { if (vma_entry->end >= args->premmapped_addr) len = args->premmapped_addr - addr; else len = vma_entry->end - vma_entry->start; if (sys_munmap((void *) addr, len)) { pr_err("munmap fail for %lx - %lx\n", addr, addr + len); goto core_restore_end; } } if (vma_entry->end >= TASK_SIZE) continue; if (vma_entry->end > premmapped_end) { if (vma_entry->start < premmapped_end) addr = premmapped_end; len = vma_entry->end - addr; if (sys_munmap((void *) addr, len)) { pr_err("munmap fail for %lx - %lx\n", addr, addr + len); goto core_restore_end; } } } sys_munmap(args->self_vmas, ((void *)(vma_entry + 1) - ((void *)args->self_vmas))); /* Shift private vma-s to the left */ for (vma_entry = args->tgt_vmas; vma_entry->start != 0; vma_entry++) { if (!vma_entry_is(vma_entry, VMA_AREA_REGULAR)) continue; if (!vma_priv(vma_entry)) continue; if (vma_entry->end >= TASK_SIZE) continue; if (vma_entry->start > vma_entry->shmid) break; if (vma_remap(vma_premmaped_start(vma_entry), vma_entry->start, vma_entry_len(vma_entry))) goto core_restore_end; } /* Shift private vma-s to the right */ for (vma_entry = args->tgt_vmas + args->nr_vmas -1; vma_entry >= args->tgt_vmas; vma_entry--) { if (!vma_entry_is(vma_entry, VMA_AREA_REGULAR)) continue; if (!vma_priv(vma_entry)) continue; if (vma_entry->start > TASK_SIZE) continue; if (vma_entry->start < vma_entry->shmid) break; if (vma_remap(vma_premmaped_start(vma_entry), vma_entry->start, vma_entry_len(vma_entry))) goto core_restore_end; } /* * OK, lets try to map new one. */ for (vma_entry = args->tgt_vmas; vma_entry->start != 0; vma_entry++) { if (!vma_entry_is(vma_entry, VMA_AREA_REGULAR)) continue; if (vma_priv(vma_entry)) continue; va = restore_mapping(vma_entry); if (va != vma_entry->start) { pr_err("Can't restore %"PRIx64" mapping with %"PRIx64"\n", vma_entry->start, va); goto core_restore_end; } } /* * Walk though all VMAs again to drop PROT_WRITE * if it was not there. */ for (vma_entry = args->tgt_vmas; vma_entry->start != 0; vma_entry++) { if (!(vma_entry_is(vma_entry, VMA_AREA_REGULAR))) continue; if (vma_entry_is(vma_entry, VMA_ANON_SHARED)) { struct shmem_info *entry; entry = find_shmem(args->shmems, vma_entry->shmid); if (entry && entry->pid == my_pid && entry->start == vma_entry->start) futex_set_and_wake(&entry->lock, 1); } if (vma_entry->prot & PROT_WRITE) continue; sys_mprotect(decode_pointer(vma_entry->start), vma_entry_len(vma_entry), vma_entry->prot); } /* * Finally restore madivse() bits */ for (vma_entry = args->tgt_vmas; vma_entry->start != 0; vma_entry++) { unsigned long i; if (!vma_entry->has_madv || !vma_entry->madv) continue; for (i = 0; i < sizeof(vma_entry->madv) * 8; i++) { if (vma_entry->madv & (1ul << i)) { ret = sys_madvise(vma_entry->start, vma_entry_len(vma_entry), i); if (ret) { pr_err("madvise(%"PRIx64", %"PRIu64", %ld) " "failed with %ld\n", vma_entry->start, vma_entry_len(vma_entry), i, ret); goto core_restore_end; } } } } sys_munmap(args->tgt_vmas, ((void *)(vma_entry + 1) - ((void *)args->tgt_vmas))); ret = sys_munmap(args->shmems, SHMEMS_SIZE); if (ret < 0) { pr_err("Can't unmap shmem %ld\n", ret); goto core_restore_end; } /* * Tune up the task fields. */ ret |= sys_prctl_safe(PR_SET_NAME, (long)args->comm, 0, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_CODE, (long)args->mm.mm_start_code, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_END_CODE, (long)args->mm.mm_end_code, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_DATA, (long)args->mm.mm_start_data, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_END_DATA, (long)args->mm.mm_end_data, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_STACK, (long)args->mm.mm_start_stack, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_BRK, (long)args->mm.mm_start_brk, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_BRK, (long)args->mm.mm_brk, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ARG_START, (long)args->mm.mm_arg_start, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ARG_END, (long)args->mm.mm_arg_end, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ENV_START, (long)args->mm.mm_env_start, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ENV_END, (long)args->mm.mm_env_end, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_AUXV, (long)args->mm_saved_auxv, args->mm_saved_auxv_size); if (ret) goto core_restore_end; /* * Because of requirements applied from kernel side * we need to restore /proc/pid/exe symlink late, * after old existing VMAs are superseded with * new ones from image file. */ ret = restore_self_exe_late(args); if (ret) goto core_restore_end; /* * We need to prepare a valid sigframe here, so * after sigreturn the kernel will pick up the * registers from the frame, set them up and * finally pass execution to the new IP. */ rt_sigframe = (void *)args->t->mem_zone.rt_sigframe + 8; if (restore_thread_common(rt_sigframe, args->t)) goto core_restore_end; /* * Threads restoration. This requires some more comments. This * restorer routine and thread restorer routine has the following * memory map, prepared by a caller code. * * | <-- low addresses high addresses --> | * +-------------------------------------------------------+-----------------------+ * | this proc body | own stack | heap | rt_sigframe space | thread restore zone | * +-------------------------------------------------------+-----------------------+ * * where each thread restore zone is the following * * | <-- low addresses high addresses --> | * +--------------------------------------------------------------------------+ * | thread restore proc | thread1 stack | thread1 heap | thread1 rt_sigframe | * +--------------------------------------------------------------------------+ */ if (args->nr_threads > 1) { struct thread_restore_args *thread_args = args->thread_args; long clone_flags = CLONE_VM | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM; long last_pid_len; long parent_tid; int i, fd; fd = sys_open(LAST_PID_PATH, O_RDWR, LAST_PID_PERM); if (fd < 0) { pr_err("Can't open last_pid %d\n", fd); goto core_restore_end; } ret = sys_flock(fd, LOCK_EX); if (ret) { pr_err("Can't lock last_pid %d\n", fd); goto core_restore_end; } for (i = 0; i < args->nr_threads; i++) { char last_pid_buf[16], *s; /* skip self */ if (thread_args[i].pid == args->t->pid) continue; mutex_lock(&args->rst_lock); new_sp = RESTORE_ALIGN_STACK((long)thread_args[i].mem_zone.stack, sizeof(thread_args[i].mem_zone.stack)); last_pid_len = vprint_num(last_pid_buf, sizeof(last_pid_buf), thread_args[i].pid - 1, &s); ret = sys_write(fd, s, last_pid_len); if (ret < 0) { pr_err("Can't set last_pid %ld/%s\n", ret, last_pid_buf); goto core_restore_end; } /* * To achieve functionality like libc's clone() * we need a pure assembly here, because clone()'ed * thread will run with own stack and we must not * have any additional instructions... oh, dear... */ RUN_CLONE_RESTORE_FN(ret, clone_flags, new_sp, parent_tid, thread_args, args->clone_restore_fn); } ret = sys_flock(fd, LOCK_UN); if (ret) { pr_err("Can't unlock last_pid %ld\n", ret); goto core_restore_end; } sys_close(fd); } restore_rlims(args); pr_info("%ld: Restored\n", sys_getpid()); futex_set(&zombies_inprogress, args->nr_zombies); restore_finish_stage(CR_STATE_RESTORE); futex_wait_while_gt(&zombies_inprogress, 0); sys_sigaction(SIGCHLD, &args->sigchld_act, NULL, sizeof(k_rtsigset_t)); ret = restore_signals(args->siginfo, args->siginfo_nr, true); if (ret) goto core_restore_end; ret = restore_signals(args->t->siginfo, args->t->siginfo_nr, false); if (ret) goto core_restore_end; restore_finish_stage(CR_STATE_RESTORE_SIGCHLD); if (args->siginfo_size) { ret = sys_munmap(args->siginfo, args->siginfo_size); if (ret < 0) { pr_err("Can't unmap signals %ld\n", ret); goto core_restore_failed; } } rst_tcp_socks_all(args->rst_tcp_socks, args->rst_tcp_socks_size); /* * Writing to last-pid is CAP_SYS_ADMIN protected, * turning off TCP repair is CAP_SYS_NED_ADMIN protected, * thus restore* creds _after_ all of the above. */ ret = restore_creds(&args->creds); futex_set_and_wake(&thread_inprogress, args->nr_threads); restore_finish_stage(CR_STATE_RESTORE_CREDS); if (ret) BUG(); /* Wait until children stop to use args->task_entries */ futex_wait_while_gt(&thread_inprogress, 1); log_set_fd(-1); /* * The code that prepared the itimers makes shure the * code below doesn't fail due to bad timing values. */ #define itimer_armed(args, i) \ (args->itimers[i].it_interval.tv_sec || \ args->itimers[i].it_interval.tv_usec) if (itimer_armed(args, 0)) sys_setitimer(ITIMER_REAL, &args->itimers[0], NULL); if (itimer_armed(args, 1)) sys_setitimer(ITIMER_VIRTUAL, &args->itimers[1], NULL); if (itimer_armed(args, 2)) sys_setitimer(ITIMER_PROF, &args->itimers[2], NULL); ret = sys_munmap(args->task_entries, TASK_ENTRIES_SIZE); if (ret < 0) { ret = ((long)__LINE__ << 16) | ((-ret) & 0xffff); goto core_restore_failed; } /* * Sigframe stack. */ new_sp = (long)rt_sigframe + SIGFRAME_OFFSET; /* * Prepare the stack and call for sigreturn, * pure assembly since we don't need any additional * code insns from gcc. */ ARCH_RT_SIGRETURN(new_sp); core_restore_end: futex_abort_and_wake(&task_entries->nr_in_progress); pr_err("Restorer fail %ld\n", sys_getpid()); sys_exit_group(1); return -1; core_restore_failed: ARCH_FAIL_CORE_RESTORE; return ret; }
/* * The main routine to restore task via sigreturn. * This one is very special, we never return there * but use sigreturn facility to restore core registers * and jump execution to some predefined ip read from * core file. */ long __export_restore_task(struct task_restore_args *args) { long ret = -1; int i; VmaEntry *vma_entry; unsigned long va; struct rt_sigframe *rt_sigframe; unsigned long new_sp; k_rtsigset_t to_block; pid_t my_pid = sys_getpid(); rt_sigaction_t act; bootstrap_start = args->bootstrap_start; bootstrap_len = args->bootstrap_len; #ifdef CONFIG_VDSO vdso_rt_size = args->vdso_rt_size; #endif task_entries = args->task_entries; helpers = args->helpers; n_helpers = args->n_helpers; *args->breakpoint = rst_sigreturn; ksigfillset(&act.rt_sa_mask); act.rt_sa_handler = sigchld_handler; act.rt_sa_flags = SA_SIGINFO | SA_RESTORER | SA_RESTART; act.rt_sa_restorer = cr_restore_rt; sys_sigaction(SIGCHLD, &act, NULL, sizeof(k_rtsigset_t)); log_set_fd(args->logfd); log_set_loglevel(args->loglevel); cap_last_cap = args->cap_last_cap; pr_info("Switched to the restorer %d\n", my_pid); #ifdef CONFIG_VDSO if (vdso_do_park(&args->vdso_sym_rt, args->vdso_rt_parked_at, vdso_rt_size)) goto core_restore_end; #endif if (unmap_old_vmas((void *)args->premmapped_addr, args->premmapped_len, bootstrap_start, bootstrap_len)) goto core_restore_end; /* Shift private vma-s to the left */ for (i = 0; i < args->nr_vmas; i++) { vma_entry = args->tgt_vmas + i; if (!vma_entry_is(vma_entry, VMA_AREA_REGULAR)) continue; if (!vma_priv(vma_entry)) continue; if (vma_entry->end >= TASK_SIZE) continue; if (vma_entry->start > vma_entry->shmid) break; if (vma_remap(vma_premmaped_start(vma_entry), vma_entry->start, vma_entry_len(vma_entry))) goto core_restore_end; } /* Shift private vma-s to the right */ for (i = args->nr_vmas - 1; i >= 0; i--) { vma_entry = args->tgt_vmas + i; if (!vma_entry_is(vma_entry, VMA_AREA_REGULAR)) continue; if (!vma_priv(vma_entry)) continue; if (vma_entry->start > TASK_SIZE) continue; if (vma_entry->start < vma_entry->shmid) break; if (vma_remap(vma_premmaped_start(vma_entry), vma_entry->start, vma_entry_len(vma_entry))) goto core_restore_end; } /* * OK, lets try to map new one. */ for (i = 0; i < args->nr_vmas; i++) { vma_entry = args->tgt_vmas + i; if (!vma_entry_is(vma_entry, VMA_AREA_REGULAR)) continue; if (vma_priv(vma_entry)) continue; va = restore_mapping(vma_entry); if (va != vma_entry->start) { pr_err("Can't restore %"PRIx64" mapping with %lx\n", vma_entry->start, va); goto core_restore_end; } } #ifdef CONFIG_VDSO /* * Proxify vDSO. */ for (i = 0; i < args->nr_vmas; i++) { if (vma_entry_is(&args->tgt_vmas[i], VMA_AREA_VDSO) || vma_entry_is(&args->tgt_vmas[i], VMA_AREA_VVAR)) { if (vdso_proxify("dumpee", &args->vdso_sym_rt, args->vdso_rt_parked_at, i, args->tgt_vmas, args->nr_vmas)) goto core_restore_end; break; } } #endif /* * Walk though all VMAs again to drop PROT_WRITE * if it was not there. */ for (i = 0; i < args->nr_vmas; i++) { vma_entry = args->tgt_vmas + i; if (!(vma_entry_is(vma_entry, VMA_AREA_REGULAR))) continue; if (vma_entry_is(vma_entry, VMA_ANON_SHARED)) { struct shmem_info *entry; entry = find_shmem(args->shmems, args->nr_shmems, vma_entry->shmid); if (entry && entry->pid == my_pid && entry->start == vma_entry->start) futex_set_and_wake(&entry->lock, 1); } if (vma_entry->prot & PROT_WRITE) continue; sys_mprotect(decode_pointer(vma_entry->start), vma_entry_len(vma_entry), vma_entry->prot); } /* * Finally restore madivse() bits */ for (i = 0; i < args->nr_vmas; i++) { unsigned long m; vma_entry = args->tgt_vmas + i; if (!vma_entry->has_madv || !vma_entry->madv) continue; for (m = 0; m < sizeof(vma_entry->madv) * 8; m++) { if (vma_entry->madv & (1ul << m)) { ret = sys_madvise(vma_entry->start, vma_entry_len(vma_entry), m); if (ret) { pr_err("madvise(%"PRIx64", %"PRIu64", %ld) " "failed with %ld\n", vma_entry->start, vma_entry_len(vma_entry), m, ret); goto core_restore_end; } } } } ret = 0; /* * Tune up the task fields. */ ret |= sys_prctl_safe(PR_SET_NAME, (long)args->comm, 0, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_CODE, (long)args->mm.mm_start_code, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_END_CODE, (long)args->mm.mm_end_code, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_DATA, (long)args->mm.mm_start_data, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_END_DATA, (long)args->mm.mm_end_data, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_STACK, (long)args->mm.mm_start_stack, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_BRK, (long)args->mm.mm_start_brk, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_BRK, (long)args->mm.mm_brk, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ARG_START, (long)args->mm.mm_arg_start, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ARG_END, (long)args->mm.mm_arg_end, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ENV_START, (long)args->mm.mm_env_start, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ENV_END, (long)args->mm.mm_env_end, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_AUXV, (long)args->mm_saved_auxv, args->mm_saved_auxv_size); if (ret) goto core_restore_end; /* * Because of requirements applied from kernel side * we need to restore /proc/pid/exe symlink late, * after old existing VMAs are superseded with * new ones from image file. */ ret = restore_self_exe_late(args); if (ret) goto core_restore_end; /* * We need to prepare a valid sigframe here, so * after sigreturn the kernel will pick up the * registers from the frame, set them up and * finally pass execution to the new IP. */ rt_sigframe = (void *)args->t->mem_zone.rt_sigframe; if (restore_thread_common(rt_sigframe, args->t)) goto core_restore_end; /* * Threads restoration. This requires some more comments. This * restorer routine and thread restorer routine has the following * memory map, prepared by a caller code. * * | <-- low addresses high addresses --> | * +-------------------------------------------------------+-----------------------+ * | this proc body | own stack | rt_sigframe space | thread restore zone | * +-------------------------------------------------------+-----------------------+ * * where each thread restore zone is the following * * | <-- low addresses high addresses --> | * +--------------------------------------------------------------------------+ * | thread restore proc | thread1 stack | thread1 rt_sigframe | * +--------------------------------------------------------------------------+ */ if (args->nr_threads > 1) { struct thread_restore_args *thread_args = args->thread_args; long clone_flags = CLONE_VM | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM; long last_pid_len; long parent_tid; int i, fd; fd = args->fd_last_pid; ret = sys_flock(fd, LOCK_EX); if (ret) { pr_err("Can't lock last_pid %d\n", fd); goto core_restore_end; } for (i = 0; i < args->nr_threads; i++) { char last_pid_buf[16], *s; /* skip self */ if (thread_args[i].pid == args->t->pid) continue; new_sp = restorer_stack(thread_args + i); last_pid_len = vprint_num(last_pid_buf, sizeof(last_pid_buf), thread_args[i].pid - 1, &s); sys_lseek(fd, 0, SEEK_SET); ret = sys_write(fd, s, last_pid_len); if (ret < 0) { pr_err("Can't set last_pid %ld/%s\n", ret, last_pid_buf); goto core_restore_end; } /* * To achieve functionality like libc's clone() * we need a pure assembly here, because clone()'ed * thread will run with own stack and we must not * have any additional instructions... oh, dear... */ RUN_CLONE_RESTORE_FN(ret, clone_flags, new_sp, parent_tid, thread_args, args->clone_restore_fn); } ret = sys_flock(fd, LOCK_UN); if (ret) { pr_err("Can't unlock last_pid %ld\n", ret); goto core_restore_end; } } sys_close(args->fd_last_pid); restore_rlims(args); ret = create_posix_timers(args); if (ret < 0) { pr_err("Can't restore posix timers %ld\n", ret); goto core_restore_end; } ret = timerfd_arm(args); if (ret < 0) { pr_err("Can't restore timerfd %ld\n", ret); goto core_restore_end; } pr_info("%ld: Restored\n", sys_getpid()); futex_set(&zombies_inprogress, args->nr_zombies); restore_finish_stage(CR_STATE_RESTORE); futex_wait_while_gt(&zombies_inprogress, 0); if (wait_helpers(args) < 0) goto core_restore_end; ksigfillset(&to_block); ret = sys_sigprocmask(SIG_SETMASK, &to_block, NULL, sizeof(k_rtsigset_t)); if (ret) { pr_err("Unable to block signals %ld", ret); goto core_restore_end; } sys_sigaction(SIGCHLD, &args->sigchld_act, NULL, sizeof(k_rtsigset_t)); ret = restore_signals(args->siginfo, args->siginfo_nr, true); if (ret) goto core_restore_end; ret = restore_signals(args->t->siginfo, args->t->siginfo_nr, false); if (ret) goto core_restore_end; restore_finish_stage(CR_STATE_RESTORE_SIGCHLD); rst_tcp_socks_all(args); /* * Writing to last-pid is CAP_SYS_ADMIN protected, * turning off TCP repair is CAP_SYS_NED_ADMIN protected, * thus restore* creds _after_ all of the above. */ ret = restore_creds(&args->creds); ret = ret || restore_dumpable_flag(&args->mm); ret = ret || restore_pdeath_sig(args->t); futex_set_and_wake(&thread_inprogress, args->nr_threads); restore_finish_stage(CR_STATE_RESTORE_CREDS); if (ret) BUG(); /* Wait until children stop to use args->task_entries */ futex_wait_while_gt(&thread_inprogress, 1); log_set_fd(-1); /* * The code that prepared the itimers makes shure the * code below doesn't fail due to bad timing values. */ #define itimer_armed(args, i) \ (args->itimers[i].it_interval.tv_sec || \ args->itimers[i].it_interval.tv_usec) if (itimer_armed(args, 0)) sys_setitimer(ITIMER_REAL, &args->itimers[0], NULL); if (itimer_armed(args, 1)) sys_setitimer(ITIMER_VIRTUAL, &args->itimers[1], NULL); if (itimer_armed(args, 2)) sys_setitimer(ITIMER_PROF, &args->itimers[2], NULL); restore_posix_timers(args); sys_munmap(args->rst_mem, args->rst_mem_size); /* * Sigframe stack. */ new_sp = (long)rt_sigframe + SIGFRAME_OFFSET; /* * Prepare the stack and call for sigreturn, * pure assembly since we don't need any additional * code insns from gcc. */ rst_sigreturn(new_sp); core_restore_end: futex_abort_and_wake(&task_entries->nr_in_progress); pr_err("Restorer fail %ld\n", sys_getpid()); sys_exit_group(1); return -1; }
int shutdown_signals() { cleanup_gdb_crash_handler(); restore_signals(); return 0; } //shutdown_signals