/* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. * * Note that we go through the signals twice: once to check the signals that * the kernel can handle, and then we build all the user-level signal handling * stack-frames in one go after that. */ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) { struct k_sigaction ka; siginfo_t info; int signr; /* * We want the common case to go fast, which * is why we may in certain cases get here from * kernel mode. Just return without doing anything * if so. */ if (!user_mode(regs)) return 0; if (try_to_freeze()) goto no_signal; single_step_clear(current); signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { handle_signal(signr, &ka, &info, oldset, regs, syscall); single_step_set(current); return 1; } no_signal: /* * No signal to deliver to the process - restart the syscall. */ if (syscall) { if (regs->ARM_r0 == -ERESTART_RESTARTBLOCK) { regs->ARM_r0 = -EAGAIN; /* prevent multiple restarts */ if (thumb_mode(regs)) { regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE; regs->ARM_pc -= 2; } else { #if defined(CONFIG_AEABI) && !defined(CONFIG_OABI_COMPAT) regs->ARM_r7 = __NR_restart_syscall; regs->ARM_pc -= 4; #else u32 __user *usp; u32 swival = __NR_restart_syscall; regs->ARM_sp -= 12; usp = (u32 __user *)regs->ARM_sp; /* * Either we supports OABI only, or we have * EABI with the OABI compat layer enabled. * In the later case we don't know if user * space is EABI or not, and if not we must * not clobber r7. Always using the OABI * syscall solves that issue and works for * all those cases. */ swival = swival - __NR_SYSCALL_BASE + __NR_OABI_SYSCALL_BASE; put_user(regs->ARM_pc, &usp[0]); /* swi __NR_restart_syscall */ put_user(0xef000000 | swival, &usp[1]); /* ldr pc, [sp], #12 */ put_user(0xe49df00c, &usp[2]); flush_icache_range((unsigned long)usp, (unsigned long)(usp + 3)); regs->ARM_pc = regs->ARM_sp + 4; #endif } } if (regs->ARM_r0 == -ERESTARTNOHAND || regs->ARM_r0 == -ERESTARTSYS || regs->ARM_r0 == -ERESTARTNOINTR) { restart_syscall(regs); } } single_step_set(current); return 0; }
/* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. * * Note that we go through the signals twice: once to check the signals * that the kernel can handle, and then we build all the user-level signal * handling stack-frames in one go after that. */ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) { siginfo_t info; struct k_sigaction *ka; current->thread.esp0 = (unsigned long) regs; if (!oldset) oldset = ¤t->blocked; for (;;) { int signr; signr = get_signal_to_deliver(&info, regs, NULL); if (!signr) break; if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) { current->exit_code = signr; current->state = TASK_STOPPED; /* Did we come from a system call? */ if (regs->orig_er0 >= 0) { /* Restart the system call the same way as if the process were not traced. */ struct k_sigaction *ka = ¤t->sighand->action[signr-1]; int has_handler = (ka->sa.sa_handler != SIG_IGN && ka->sa.sa_handler != SIG_DFL); handle_restart(regs, ka, has_handler); } notify_parent(current, SIGCHLD); schedule(); /* We're back. Did the debugger cancel the sig? */ if (!(signr = current->exit_code)) { discard_frame: continue; } current->exit_code = 0; /* The debugger continued. Ignore SIGSTOP. */ if (signr == SIGSTOP) goto discard_frame; /* Update the siginfo structure. Is this good? */ if (signr != info.si_signo) { info.si_signo = signr; info.si_errno = 0; info.si_code = SI_USER; info.si_pid = current->parent->pid; info.si_uid = current->parent->uid; } /* If the (new) signal is now blocked, requeue it. */ if (sigismember(¤t->blocked, signr)) { send_sig_info(signr, &info, current); continue; } } ka = ¤t->sighand->action[signr-1]; if (ka->sa.sa_handler == SIG_IGN) { if (signr != SIGCHLD) continue; /* Check for SIGCHLD: it's special. */ while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0) /* nothing */; continue; } if (ka->sa.sa_handler == SIG_DFL) { int exit_code = signr; if (current->pid == 1) continue; switch (signr) { case SIGCONT: case SIGCHLD: case SIGWINCH: case SIGURG: continue; case SIGTSTP: case SIGTTIN: case SIGTTOU: if (is_orphaned_pgrp(process_group(current))) continue; /* FALLTHRU */ case SIGSTOP: { struct sighand_struct *sig; current->state = TASK_STOPPED; current->exit_code = signr; sig = current->parent->sighand; if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) notify_parent(current, SIGCHLD); schedule(); continue; } case SIGQUIT: case SIGILL: case SIGTRAP: case SIGIOT: case SIGFPE: case SIGSEGV: case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ: if (do_coredump(signr, exit_code, regs)) exit_code |= 0x80; /* FALLTHRU */ default: sigaddset(¤t->pending.signal, signr); recalc_sigpending(); current->flags |= PF_SIGNALED; do_exit(exit_code); /* NOTREACHED */ } } /* Whee! Actually deliver the signal. */ handle_signal(signr, ka, &info, oldset, regs); return 1; } /* Did we come from a system call? */ if (regs->orig_er0 >= 0) /* Restart the system call - no handlers present */ handle_restart(regs, NULL, 0); return 0; }
/* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. * * Note that we go through the signals twice: once to check the signals that * the kernel can handle, and then we build all the user-level signal handling * stack-frames in one go after that. */ static void do_signal(struct pt_regs *regs, unsigned int save_r0) { siginfo_t info; int signr; struct k_sigaction ka; sigset_t *oldset; /* * We want the common case to go fast, which * is why we may in certain cases get here from * kernel mode. Just return without doing anything * if so. */ if (!user_mode(regs)) return; if (try_to_freeze()) goto no_signal; if (current_thread_info()->status & TS_RESTORE_SIGMASK) oldset = ¤t->saved_sigmask; else oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { handle_syscall_restart(save_r0, regs, &ka.sa); /* Whee! Actually deliver the signal. */ if (handle_signal(signr, &ka, &info, oldset, regs, save_r0) == 0) { /* * A signal was successfully delivered; the saved * sigmask will have been stored in the signal frame, * and will be restored by sigreturn, so we can simply * clear the TS_RESTORE_SIGMASK flag */ current_thread_info()->status &= ~TS_RESTORE_SIGMASK; tracehook_signal_handler(signr, &info, &ka, regs, test_thread_flag(TIF_SINGLESTEP)); } return; } no_signal: /* Did we come from a system call? */ if (regs->tra >= 0) { /* Restart the system call - no handlers present */ if (regs->regs[0] == -ERESTARTNOHAND || regs->regs[0] == -ERESTARTSYS || regs->regs[0] == -ERESTARTNOINTR) { regs->regs[0] = save_r0; regs->pc -= instruction_size(ctrl_inw(regs->pc - 4)); } else if (regs->regs[0] == -ERESTART_RESTARTBLOCK) { regs->pc -= instruction_size(ctrl_inw(regs->pc - 4)); regs->regs[3] = __NR_restart_syscall; } } /* * If there's no signal to deliver, we just put the saved sigmask * back. */ if (current_thread_info()->status & TS_RESTORE_SIGMASK) { current_thread_info()->status &= ~TS_RESTORE_SIGMASK; sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); } }
void * decryption_func_dictionary(void *arg) { struct decryption_func_locals *dfargs; unsigned char *pwd, *key, *iv, *masterkey, *seckey, hash[32]; unsigned int pwd_len, masterkey_len1, masterkey_len2, seckey_len1, seckey_len2; int ret; EVP_CIPHER_CTX ctx; dfargs = (struct decryption_func_locals *) arg; sha256d(pubkey, pubkey_len, hash); key = (unsigned char *) malloc(EVP_CIPHER_key_length(cipher)); iv = (unsigned char *) malloc(EVP_CIPHER_iv_length(cipher)); masterkey = (unsigned char *) malloc(encrypted_masterkey_len + EVP_CIPHER_block_size(EVP_aes_256_cbc())); seckey = (unsigned char *) malloc(encrypted_seckey_len + EVP_CIPHER_block_size(EVP_aes_256_cbc())); if((key == NULL) || (iv == NULL) || (masterkey == NULL) || (seckey == NULL)) { fprintf(stderr, "Error: memory allocation failed.\n\n"); exit(EXIT_FAILURE); } do { ret = read_dictionary_line(&pwd, &pwd_len); if(ret == 0) break; /* Decrypt the master key with the password */ EVP_BytesToKey(cipher, digest, salt, pwd, pwd_len, rounds, key, iv); EVP_DecryptInit(&ctx, EVP_aes_256_cbc(), key, iv); EVP_DecryptUpdate(&ctx, masterkey, &masterkey_len1, encrypted_masterkey, encrypted_masterkey_len); ret = EVP_DecryptFinal(&ctx, masterkey + masterkey_len1, &masterkey_len2); dfargs->counter++; if(ret == 1) { /* Decrypt the secret key with the master key */ EVP_CIPHER_CTX_cleanup(&ctx); EVP_DecryptInit(&ctx, EVP_aes_256_cbc(), masterkey, hash); EVP_DecryptUpdate(&ctx, seckey, &seckey_len1, encrypted_seckey, encrypted_seckey_len); ret = EVP_DecryptFinal(&ctx, seckey + seckey_len1, &seckey_len2); if((ret == 1) && valid_seckey(seckey, seckey_len1 + seckey_len2, pubkey, pubkey_len)) { /* We have a positive result */ handle_signal(SIGUSR1); /* Print some stats */ pthread_mutex_lock(&found_password_lock); found_password = 1; printf("Password found: %s\n", pwd); stop = 1; pthread_mutex_unlock(&found_password_lock); } } EVP_CIPHER_CTX_cleanup(&ctx); free(pwd); } while(stop == 0); free(masterkey); free(seckey); free(iv); free(key); pthread_exit(NULL); }
ISC_APPFUNC_SCOPE isc_result_t isc__app_start(void) { isc_result_t result; int presult; sigset_t sset; char strbuf[ISC_STRERRORSIZE]; isc_g_appctx.common.impmagic = APPCTX_MAGIC; isc_g_appctx.common.magic = ISCAPI_APPCTX_MAGIC; isc_g_appctx.common.methods = &appmethods.methods; isc_g_appctx.mctx = NULL; /* The remaining members will be initialized in ctxstart() */ result = isc__app_ctxstart((isc_appctx_t *)&isc_g_appctx); if (result != ISC_R_SUCCESS) return (result); #ifndef HAVE_SIGWAIT /* * Install do-nothing handlers for SIGINT and SIGTERM. * * We install them now because BSDI 3.1 won't block * the default actions, regardless of what we do with * pthread_sigmask(). */ result = handle_signal(SIGINT, exit_action); if (result != ISC_R_SUCCESS) return (result); result = handle_signal(SIGTERM, exit_action); if (result != ISC_R_SUCCESS) return (result); #endif /* * Always ignore SIGPIPE. */ result = handle_signal(SIGPIPE, SIG_IGN); if (result != ISC_R_SUCCESS) return (result); /* * On Solaris 2, delivery of a signal whose action is SIG_IGN * will not cause sigwait() to return. We may have inherited * unexpected actions for SIGHUP, SIGINT, and SIGTERM from our parent * process (e.g, Solaris cron). Set an action of SIG_DFL to make * sure sigwait() works as expected. Only do this for SIGTERM and * SIGINT if we don't have sigwait(), since a different handler is * installed above. */ result = handle_signal(SIGHUP, SIG_DFL); if (result != ISC_R_SUCCESS) return (result); #ifdef HAVE_SIGWAIT result = handle_signal(SIGTERM, SIG_DFL); if (result != ISC_R_SUCCESS) return (result); result = handle_signal(SIGINT, SIG_DFL); if (result != ISC_R_SUCCESS) return (result); #endif #ifdef ISC_PLATFORM_USETHREADS /* * Block SIGHUP, SIGINT, SIGTERM. * * If isc_app_start() is called from the main thread before any other * threads have been created, then the pthread_sigmask() call below * will result in all threads having SIGHUP, SIGINT and SIGTERM * blocked by default, ensuring that only the thread that calls * sigwait() for them will get those signals. */ if (sigemptyset(&sset) != 0 || sigaddset(&sset, SIGHUP) != 0 || sigaddset(&sset, SIGINT) != 0 || sigaddset(&sset, SIGTERM) != 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_app_start() sigsetops: %s", strbuf); return (ISC_R_UNEXPECTED); } presult = pthread_sigmask(SIG_BLOCK, &sset, NULL); if (presult != 0) { isc__strerror(presult, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_app_start() pthread_sigmask: %s", strbuf); return (ISC_R_UNEXPECTED); } #else /* ISC_PLATFORM_USETHREADS */ /* * Unblock SIGHUP, SIGINT, SIGTERM. * * If we're not using threads, we need to make sure that SIGHUP, * SIGINT and SIGTERM are not inherited as blocked from the parent * process. */ if (sigemptyset(&sset) != 0 || sigaddset(&sset, SIGHUP) != 0 || sigaddset(&sset, SIGINT) != 0 || sigaddset(&sset, SIGTERM) != 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_app_start() sigsetops: %s", strbuf); return (ISC_R_UNEXPECTED); } presult = sigprocmask(SIG_UNBLOCK, &sset, NULL); if (presult != 0) { isc__strerror(presult, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_app_start() sigprocmask: %s", strbuf); return (ISC_R_UNEXPECTED); } #endif /* ISC_PLATFORM_USETHREADS */ return (ISC_R_SUCCESS); }
/* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. */ static void do_signal(void) { struct k_sigaction ka; siginfo_t info; sigset_t *oldset; int signr; /* * We want the common case to go fast, which * is why we may in certain cases get here from * kernel mode. Just return without doing anything * if so. */ if (!user_mode(__frame)) return; if (try_to_freeze()) goto no_signal; if (test_thread_flag(TIF_RESTORE_SIGMASK)) oldset = ¤t->saved_sigmask; else oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, &ka, __frame, NULL); if (signr > 0) { if (handle_signal(signr, &info, &ka, oldset) == 0) { /* a signal was successfully delivered; the saved * sigmask will have been stored in the signal frame, * and will be restored by sigreturn, so we can simply * clear the TIF_RESTORE_SIGMASK flag */ if (test_thread_flag(TIF_RESTORE_SIGMASK)) clear_thread_flag(TIF_RESTORE_SIGMASK); tracehook_signal_handler(signr, &info, &ka, __frame, test_thread_flag(TIF_SINGLESTEP)); } return; } no_signal: /* Did we come from a system call? */ if (__frame->syscallno != -1) { /* Restart the system call - no handlers present */ switch (__frame->gr8) { case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: __frame->gr8 = __frame->orig_gr8; __frame->pc -= 4; break; case -ERESTART_RESTARTBLOCK: __frame->gr7 = __NR_restart_syscall; __frame->pc -= 4; break; } __frame->syscallno = -1; } /* if there's no signal to deliver, we just put the saved sigmask * back */ if (test_thread_flag(TIF_RESTORE_SIGMASK)) { clear_thread_flag(TIF_RESTORE_SIGMASK); sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); } } /* end do_signal() */
int main(int argc, char *argv[]) { struct weston_launch wl; int i, c; char *tty = NULL; struct option opts[] = { { "user", required_argument, NULL, 'u' }, { "tty", required_argument, NULL, 't' }, { "verbose", no_argument, NULL, 'v' }, { "help", no_argument, NULL, 'h' }, { 0, 0, NULL, 0 } }; memset(&wl, 0, sizeof wl); while ((c = getopt_long(argc, argv, "u:t::vh", opts, &i)) != -1) { switch (c) { case 'u': wl.new_user = optarg; if (getuid() != 0) error(1, 0, "Permission denied. -u allowed for root only"); break; case 't': tty = optarg; break; case 'v': wl.verbose = 1; break; case 'h': help("weston-launch"); exit(EXIT_FAILURE); } } if ((argc - optind) > (MAX_ARGV_SIZE - 6)) error(1, E2BIG, "Too many arguments to pass to weston"); if (wl.new_user) wl.pw = getpwnam(wl.new_user); else wl.pw = getpwuid(getuid()); if (wl.pw == NULL) error(1, errno, "failed to get username"); if (!weston_launch_allowed(&wl)) error(1, 0, "Permission denied. You should either:\n" #ifdef HAVE_SYSTEMD_LOGIN " - run from an active and local (systemd) session.\n" #else " - enable systemd session support for weston-launch.\n" #endif " - or add yourself to the 'weston-launch' group."); if (setup_tty(&wl, tty) < 0) exit(EXIT_FAILURE); if (wl.new_user && setup_pam(&wl) < 0) exit(EXIT_FAILURE); if (setup_launcher_socket(&wl) < 0) exit(EXIT_FAILURE); if (setup_signals(&wl) < 0) exit(EXIT_FAILURE); wl.child = fork(); if (wl.child == -1) { error(1, errno, "fork failed"); exit(EXIT_FAILURE); } if (wl.child == 0) launch_compositor(&wl, argc - optind, argv + optind); close(wl.sock[1]); if (wl.tty != STDIN_FILENO) close(wl.tty); while (1) { struct pollfd fds[2]; int n; fds[0].fd = wl.sock[0]; fds[0].events = POLLIN; fds[1].fd = wl.signalfd; fds[1].events = POLLIN; n = poll(fds, 2, -1); if (n < 0) error(0, errno, "poll failed"); if (fds[0].revents & POLLIN) handle_socket_msg(&wl); if (fds[1].revents) handle_signal(&wl); } return 0; }
/* * Called from return-from-event code. */ static void do_signal(struct pt_regs *regs) { struct k_sigaction sigact; siginfo_t info; int signo; if (!user_mode(regs)) return; if (try_to_freeze()) goto no_signal; signo = get_signal_to_deliver(&info, &sigact, regs, NULL); if (signo > 0) { sigset_t *oldset; if (test_thread_flag(TIF_RESTORE_SIGMASK)) oldset = ¤t->saved_sigmask; else oldset = ¤t->blocked; if (handle_signal(signo, &info, &sigact, oldset, regs) == 0) { /* * Successful delivery case. The saved sigmask is * stored in the signal frame, and will be restored * by sigreturn. We can clear the TIF flag. */ clear_thread_flag(TIF_RESTORE_SIGMASK); tracehook_signal_handler(signo, &info, &sigact, regs, test_thread_flag(TIF_SINGLESTEP)); } return; } no_signal: /* * If we came from a system call, handle the restart. */ if (regs->syscall_nr >= 0) { switch (regs->r00) { case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: regs->r06 = regs->syscall_nr; break; case -ERESTART_RESTARTBLOCK: regs->r06 = __NR_restart_syscall; break; default: goto no_restart; } pt_set_elr(regs, pt_elr(regs) - 4); regs->r00 = regs->restart_r0; } no_restart: /* If there's no signal to deliver, put the saved sigmask back */ if (test_thread_flag(TIF_RESTORE_SIGMASK)) { clear_thread_flag(TIF_RESTORE_SIGMASK); sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); } }
static inline void handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs) { switch(regs->regs[0]) { case ERESTART_RESTARTBLOCK: case ERESTARTNOHAND: regs->regs[2] = EINTR; break; case ERESTARTSYS: if(!(ka->sa.sa_flags & SA_RESTART)) { regs->regs[2] = EINTR; break; } /* fallthrough */ case ERESTARTNOINTR: /* Userland will reload $v0. */ regs->regs[7] = regs->regs[26]; regs->cp0_epc -= 8; } regs->regs[0] = 0; /* Don't deal with this again. */ #ifdef CONFIG_TRAD_SIGNALS if (ka->sa.sa_flags & SA_SIGINFO) { #else if (1) { #endif #ifdef CONFIG_MIPS32_N32 if ((current->thread.mflags & MF_ABI_MASK) == MF_N32) setup_rt_frame_n32 (ka, regs, sig, oldset, info); else #endif setup_rt_frame(ka, regs, sig, oldset, info); } #ifdef CONFIG_TRAD_SIGNALS else setup_frame(ka, regs, sig, oldset); #endif if (!(ka->sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); sigaddset(¤t->blocked,sig); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); } } extern int do_signal32(sigset_t *oldset, struct pt_regs *regs); extern int do_irix_signal(sigset_t *oldset, struct pt_regs *regs); asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) { struct k_sigaction ka; siginfo_t info; int signr; #ifdef CONFIG_BINFMT_ELF32 if ((current->thread.mflags & MF_ABI_MASK) == MF_O32) { return do_signal32(oldset, regs); } #endif /* * We want the common case to go fast, which is why we may in certain * cases get here from kernel mode. Just return without doing anything * if so. */ if (!user_mode(regs)) return 1; if (current->flags & PF_FREEZE) { refrigerator(0); goto no_signal; } if (!oldset) oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { handle_signal(signr, &info, &ka, oldset, regs); return 1; } no_signal: /* * Who's code doesn't conform to the restartable syscall convention * dies here!!! The li instruction, a single machine instruction, * must directly be followed by the syscall instruction. */ if (regs->regs[0]) { if (regs->regs[2] == ERESTARTNOHAND || regs->regs[2] == ERESTARTSYS || regs->regs[2] == ERESTARTNOINTR) { regs->regs[7] = regs->regs[26]; regs->cp0_epc -= 8; } if (regs->regs[2] == ERESTART_RESTARTBLOCK) { regs->regs[2] = __NR_restart_syscall; regs->regs[7] = regs->regs[26]; regs->cp0_epc -= 4; } } return 0; } extern int do_irix_signal(sigset_t *oldset, struct pt_regs *regs); /* * notification of userspace execution resumption * - triggered by current->work.notify_resume */ asmlinkage void do_notify_resume(struct pt_regs *regs, sigset_t *oldset, __u32 thread_info_flags) { /* deal with pending signal delivery */ if (thread_info_flags & _TIF_SIGPENDING) { #ifdef CONFIG_BINFMT_ELF32 if (likely((current->thread.mflags & MF_ABI_MASK) == MF_O32)) { do_signal32(oldset, regs); return; } #endif #ifdef CONFIG_BINFMT_IRIX if (unlikely(current->personality != PER_LINUX)) { do_irix_signal(oldset, regs); return; } #endif do_signal(oldset, regs); } }
/* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. */ int do_signal(sigset_t *oldset, struct pt_regs *regs) { siginfo_t info; struct k_sigaction *ka; unsigned long frame, newsp; int signr, ret; if (!oldset) oldset = ¤t->blocked; newsp = frame = 0; signr = get_signal_to_deliver(&info, regs, NULL); ka = (signr == 0)? NULL: ¤t->sighand->action[signr-1]; if (TRAP(regs) == 0x0C00 /* System Call! */ && regs->ccr & 0x10000000 /* error signalled */ && ((ret = regs->gpr[3]) == ERESTARTSYS || ret == ERESTARTNOHAND || ret == ERESTARTNOINTR || ret == ERESTART_RESTARTBLOCK)) { if (signr > 0 && (ret == ERESTARTNOHAND || ret == ERESTART_RESTARTBLOCK || (ret == ERESTARTSYS && !(ka->sa.sa_flags & SA_RESTART)))) { /* make the system call return an EINTR error */ regs->result = -EINTR; regs->gpr[3] = EINTR; /* note that the cr0.SO bit is already set */ } else { regs->nip -= 4; /* Back up & retry system call */ regs->result = 0; regs->trap = 0; if (ret == ERESTART_RESTARTBLOCK) regs->gpr[0] = __NR_restart_syscall; else regs->gpr[3] = regs->orig_gpr3; } } if (signr == 0) return 0; /* no signals delivered */ if ((ka->sa.sa_flags & SA_ONSTACK) && current->sas_ss_size && !on_sig_stack(regs->gpr[1])) newsp = current->sas_ss_sp + current->sas_ss_size; else newsp = regs->gpr[1]; newsp &= ~0xfUL; /* Whee! Actually deliver the signal. */ if (ka->sa.sa_flags & SA_SIGINFO) handle_rt_signal(signr, ka, &info, oldset, regs, newsp); else handle_signal(signr, ka, &info, oldset, regs, newsp); if (ka->sa.sa_flags & SA_ONESHOT) ka->sa.sa_handler = SIG_DFL; if (!(ka->sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); sigaddset(¤t->blocked, signr); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); } return 1; }
/* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. */ int do_signal(struct pt_regs *regs, sigset_t *oldset) { siginfo_t info; int signr; struct k_sigaction ka; unsigned short inst; /* * We want the common case to go fast, which * is why we may in certain cases get here from * kernel mode. Just return without doing anything * if so. */ if (!user_mode(regs)) return 1; if (current->flags & PF_FREEZE) { refrigerator(0); goto no_signal; } if (!oldset) oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { /* Reenable any watchpoints before delivering the * signal to user space. The processor register will * have been cleared if the watchpoint triggered * inside the kernel. */ /* Whee! Actually deliver the signal. */ handle_signal(signr, &ka, &info, oldset, regs); return 1; } no_signal: /* Did we come from a system call? */ if (regs->syscall_nr >= 0) { /* Restart the system call - no handlers present */ if (regs->r0 == -ERESTARTNOHAND || regs->r0 == -ERESTARTSYS || regs->r0 == -ERESTARTNOINTR) { regs->r0 = regs->orig_r0; inst = *(unsigned short *)(regs->bpc - 2); if ((inst & 0xfff0) == 0x10f0) /* trap ? */ regs->bpc -= 2; else regs->bpc -= 4; } if (regs->r0 == -ERESTART_RESTARTBLOCK){ regs->r0 = regs->orig_r0; regs->r7 = __NR_restart_syscall; inst = *(unsigned short *)(regs->bpc - 2); if ((inst & 0xfff0) == 0x10f0) /* trap ? */ regs->bpc -= 2; else regs->bpc -= 4; } } return 0; }
/* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. */ static void do_signal(struct pt_regs *regs) { struct k_sigaction ka; siginfo_t info; int signr; sigset_t *oldset; #ifdef CONFIG_PREEMPT_RT /* * Fully-preemptible kernel does not need interrupts disabled: */ local_irq_enable(); preempt_check_resched(); #endif /* * We want the common case to go fast, which * is why we may in certain cases get here from * kernel mode. Just return without doing anything * if so. */ if (!user_mode(regs)) return; if (test_thread_flag(TIF_RESTORE_SIGMASK)) oldset = ¤t->saved_sigmask; else oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { /* Reenable any watchpoints before delivering the * signal to user space. The processor register will * have been cleared if the watchpoint triggered * inside the kernel. */ if (current->thread.debugreg7) set_debugreg(current->thread.debugreg7, 7); /* Whee! Actually deliver the signal. */ if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { /* a signal was successfully delivered; the saved * sigmask will have been stored in the signal frame, * and will be restored by sigreturn, so we can simply * clear the TIF_RESTORE_SIGMASK flag */ clear_thread_flag(TIF_RESTORE_SIGMASK); } return; } /* Did we come from a system call? */ if ((long)regs->orig_rax >= 0) { /* Restart the system call - no handlers present */ long res = regs->rax; switch (res) { case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: regs->rax = regs->orig_rax; regs->rip -= 2; break; case -ERESTART_RESTARTBLOCK: regs->rax = test_thread_flag(TIF_IA32) ? __NR_ia32_restart_syscall : __NR_restart_syscall; regs->rip -= 2; break; } } /* if there's no signal to deliver, we just put the saved sigmask back. */ if (test_thread_flag(TIF_RESTORE_SIGMASK)) { clear_thread_flag(TIF_RESTORE_SIGMASK); sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); } }
/* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. */ static void do_signal(struct pt_regs *regs) { struct k_sigaction ka; siginfo_t info; int signr; sigset_t *oldset; /* * We want the common case to go fast, which is why we may in certain * cases get here from kernel mode. Just return without doing anything * if so. * X86_32: vm86 regs switched out by assembly code before reaching * here, so testing against kernel CS suffices. */ if (!user_mode(regs)) return; if (current_thread_info()->status & TS_RESTORE_SIGMASK) oldset = ¤t->saved_sigmask; else oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { /* Re-enable any watchpoints before delivering the * signal to user space. The processor register will * have been cleared if the watchpoint triggered * inside the kernel. */ if (current->thread.debugreg7) set_debugreg(current->thread.debugreg7, 7); /* Whee! Actually deliver the signal. */ if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { /* * A signal was successfully delivered; the saved * sigmask will have been stored in the signal frame, * and will be restored by sigreturn, so we can simply * clear the TS_RESTORE_SIGMASK flag. */ current_thread_info()->status &= ~TS_RESTORE_SIGMASK; } return; } /* Did we come from a system call? */ if (current_syscall(regs) >= 0) { /* Restart the system call - no handlers present */ switch (current_syscall_ret(regs)) { case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: regs->ax = regs->orig_ax; regs->ip -= 2; break; case -ERESTART_RESTARTBLOCK: regs->ax = test_thread_flag(TIF_IA32) ? __NR_ia32_restart_syscall : __NR_restart_syscall; regs->ip -= 2; break; } } /* * If there's no signal to deliver, we just put the saved sigmask * back. */ if (current_thread_info()->status & TS_RESTORE_SIGMASK) { current_thread_info()->status &= ~TS_RESTORE_SIGMASK; sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); } }
/* * Notes for Meta. * We have moved from the old 2.4.9 SH way of using syscall_nr (in the stored * context) to passing in the syscall flag on the stack. * This is because having syscall_nr in our context does not fit with TBX, and * corrupted the stack. */ static int do_signal(struct pt_regs *regs, int syscall) { unsigned int retval = 0, continue_addr = 0, restart_addr = 0; int restart = 0; struct ksignal ksig; /* * By the end of rt_sigreturn the context describes the point that the * signal was taken (which may happen to be just before a syscall if * it's already been restarted). This should *never* be mistaken for a * system call in need of restarting. */ if (syscall == __NR_rt_sigreturn) syscall = -1; /* Did we come from a system call? */ if (syscall >= 0) { continue_addr = regs->REG_PC; restart_addr = continue_addr - 4; retval = regs->REG_RETVAL; /* * Prepare for system call restart. We do this here so that a * debugger will see the already changed PC. */ switch (retval) { case -ERESTART_RESTARTBLOCK: restart = -2; case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: ++restart; regs->REG_PC = restart_addr; break; } } /* * Get the signal to deliver. When running under ptrace, at this point * the debugger may change all our registers ... */ get_signal(&ksig); /* * Depending on the signal settings we may need to revert the decision * to restart the system call. But skip this if a debugger has chosen to * restart at a different PC. */ if (regs->REG_PC != restart_addr) restart = 0; if (ksig.sig > 0) { if (unlikely(restart)) { if (retval == -ERESTARTNOHAND || retval == -ERESTART_RESTARTBLOCK || (retval == -ERESTARTSYS && !(ksig.ka.sa.sa_flags & SA_RESTART))) { regs->REG_RETVAL = -EINTR; regs->REG_PC = continue_addr; } } /* Whee! Actually deliver the signal. */ handle_signal(&ksig, regs); return 0; } /* Handlerless -ERESTART_RESTARTBLOCK re-enters via restart_syscall */ if (unlikely(restart < 0)) regs->REG_SYSCALL = __NR_restart_syscall; /* * If there's no signal to deliver, we just put the saved sigmask back. */ restore_saved_sigmask(); return restart; }
/* Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. */ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, unsigned long orig_i0, int restart_syscall) { unsigned long signr; siginfo_t info; struct k_sigaction *ka; if (!oldset) oldset = ¤t->blocked; #ifdef CONFIG_SPARC32_COMPAT if (current->thread.flags & SPARC_FLAG_32BIT) { extern asmlinkage int do_signal32(sigset_t *, struct pt_regs *, unsigned long, int); return do_signal32(oldset, regs, orig_i0, restart_syscall); } #endif for (;;) { spin_lock_irq(¤t->sigmask_lock); signr = dequeue_signal(¤t->blocked, &info); spin_unlock_irq(¤t->sigmask_lock); if (!signr) break; if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) { current->exit_code = signr; current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); schedule(); if (!(signr = current->exit_code)) continue; current->exit_code = 0; if (signr == SIGSTOP) continue; /* Update the siginfo structure. Is this good? */ if (signr != info.si_signo) { info.si_signo = signr; info.si_errno = 0; info.si_code = SI_USER; info.si_pid = current->p_pptr->pid; info.si_uid = current->p_pptr->uid; } /* If the (new) signal is now blocked, requeue it. */ if (sigismember(¤t->blocked, signr)) { send_sig_info(signr, &info, current); continue; } } ka = ¤t->sig->action[signr-1]; if(ka->sa.sa_handler == SIG_IGN) { if(signr != SIGCHLD) continue; /* sys_wait4() grabs the master kernel lock, so * we need not do so, that sucker should be * threaded and would not be that difficult to * do anyways. */ while(sys_wait4(-1, NULL, WNOHANG, NULL) > 0) ; continue; } if(ka->sa.sa_handler == SIG_DFL) { unsigned long exit_code = signr; if(current->pid == 1) continue; switch(signr) { case SIGCONT: case SIGCHLD: case SIGWINCH: continue; case SIGTSTP: case SIGTTIN: case SIGTTOU: if (is_orphaned_pgrp(current->pgrp)) continue; case SIGSTOP: if (current->ptrace & PT_PTRACED) continue; current->state = TASK_STOPPED; current->exit_code = signr; if(!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) notify_parent(current, SIGCHLD); schedule(); continue; case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGSEGV: case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ: if (do_coredump(signr, regs)) exit_code |= 0x80; #ifdef DEBUG_SIGNALS /* Very useful to debug the dynamic linker */ printk ("Sig %d going...\n", (int)signr); show_regs (regs); #ifdef DEBUG_SIGNALS_TRACE { struct reg_window *rw = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS); unsigned long ins[8]; while(rw && !(((unsigned long) rw) & 0x3)) { copy_from_user(ins, &rw->ins[0], sizeof(ins)); printk("Caller[%016lx](%016lx,%016lx,%016lx,%016lx,%016lx,%016lx)\n", ins[7], ins[0], ins[1], ins[2], ins[3], ins[4], ins[5]); rw = (struct reg_window *)(unsigned long)(ins[6] + STACK_BIAS); } } #endif #ifdef DEBUG_SIGNALS_MAPS printk("Maps:\n"); read_maps(); #endif #endif /* fall through */ default: sigaddset(¤t->pending.signal, signr); recalc_sigpending(current); current->flags |= PF_SIGNALED; do_exit(exit_code); /* NOT REACHED */ } } if(restart_syscall) syscall_restart(orig_i0, regs, &ka->sa); handle_signal(signr, ka, &info, oldset, regs); return 1; } if(restart_syscall && (regs->u_regs[UREG_I0] == ERESTARTNOHAND || regs->u_regs[UREG_I0] == ERESTARTSYS || regs->u_regs[UREG_I0] == ERESTARTNOINTR)) { /* replay the system call when we are done */ regs->u_regs[UREG_I0] = orig_i0; regs->tpc -= 4; regs->tnpc -= 4; } return 0; }
/* Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. */ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) { struct k_sigaction ka; int restart_syscall; sigset_t *oldset; siginfo_t info; int signr; if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C)) restart_syscall = 1; else restart_syscall = 0; if (test_thread_flag(TIF_RESTORE_SIGMASK)) oldset = ¤t->saved_sigmask; else oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, &ka, regs, NULL); /* If the debugger messes with the program counter, it clears * the software "in syscall" bit, directing us to not perform * a syscall restart. */ if (restart_syscall && !pt_regs_is_syscall(regs)) restart_syscall = 0; if (signr > 0) { if (restart_syscall) syscall_restart(orig_i0, regs, &ka.sa); handle_signal(signr, &ka, &info, oldset, regs); /* a signal was successfully delivered; the saved * sigmask will have been stored in the signal frame, * and will be restored by sigreturn, so we can simply * clear the TIF_RESTORE_SIGMASK flag. */ if (test_thread_flag(TIF_RESTORE_SIGMASK)) clear_thread_flag(TIF_RESTORE_SIGMASK); tracehook_signal_handler(signr, &info, &ka, regs, 0); return; } if (restart_syscall && (regs->u_regs[UREG_I0] == ERESTARTNOHAND || regs->u_regs[UREG_I0] == ERESTARTSYS || regs->u_regs[UREG_I0] == ERESTARTNOINTR)) { /* replay the system call when we are done */ regs->u_regs[UREG_I0] = orig_i0; regs->pc -= 4; regs->npc -= 4; } if (restart_syscall && regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { regs->u_regs[UREG_G1] = __NR_restart_syscall; regs->pc -= 4; regs->npc -= 4; } /* if there's no signal to deliver, we just put the saved sigmask * back */ if (test_thread_flag(TIF_RESTORE_SIGMASK)) { clear_thread_flag(TIF_RESTORE_SIGMASK); sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); } }
/* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. * * Note that we go through the signals twice: once to check the signals that * the kernel can handle, and then we build all the user-level signal handling * stack-frames in one go after that. */ static int do_signal(struct pt_regs *regs, int syscall) { unsigned int retval = 0, continue_addr = 0, restart_addr = 0; struct ksignal ksig; int restart = 0; /* * If we were from a system call, check for system call restarting... */ if (syscall) { continue_addr = regs->ARM_pc; restart_addr = continue_addr - (thumb_mode(regs) ? 2 : 4); retval = regs->ARM_r0; /* * Prepare for system call restart. We do this here so that a * debugger will see the already changed PSW. */ switch (retval) { case -ERESTART_RESTARTBLOCK: restart -= 2; case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: restart++; regs->ARM_r0 = regs->ARM_ORIG_r0; regs->ARM_pc = restart_addr; break; } } /* * Get the signal to deliver. When running under ptrace, at this * point the debugger may change all our registers ... */ /* * Depending on the signal settings we may need to revert the * decision to restart the system call. But skip this if a * debugger has chosen to restart at a different PC. */ if (get_signal(&ksig)) { /* handler */ if (unlikely(restart) && regs->ARM_pc == restart_addr) { if (retval == -ERESTARTNOHAND || retval == -ERESTART_RESTARTBLOCK || (retval == -ERESTARTSYS && !(ksig.ka.sa.sa_flags & SA_RESTART))) { regs->ARM_r0 = -EINTR; regs->ARM_pc = continue_addr; } } handle_signal(&ksig, regs); } else { /* no handler */ restore_saved_sigmask(); if (unlikely(restart) && regs->ARM_pc == restart_addr) { regs->ARM_pc = continue_addr; return restart; } } return 0; }
asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs) { struct k_sigaction *ka; siginfo_t info; if (!oldset) oldset = ¤t->blocked; for (;;) { unsigned long signr; spin_lock_irq(¤t->sigmask_lock); signr = dequeue_signal(¤t->blocked, &info); spin_unlock_irq(¤t->sigmask_lock); if (!signr) break; if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) { /* Let the debugger run. */ current->exit_code = signr; current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); schedule(); /* We're back. Did the debugger cancel the sig? */ if (!(signr = current->exit_code)) continue; current->exit_code = 0; /* The debugger continued. Ignore SIGSTOP. */ if (signr == SIGSTOP) continue; /* Update the siginfo structure. Is this good? */ if (signr != info.si_signo) { info.si_signo = signr; info.si_errno = 0; info.si_code = SI_USER; info.si_pid = current->p_pptr->pid; info.si_uid = current->p_pptr->uid; } /* If the (new) signal is now blocked, requeue it. */ if (sigismember(¤t->blocked, signr)) { send_sig_info(signr, &info, current); continue; } } ka = ¤t->sig->action[signr-1]; if (ka->sa.sa_handler == SIG_IGN) { if (signr != SIGCHLD) continue; /* Check for SIGCHLD: it's special. */ while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0) /* nothing */; continue; } if (ka->sa.sa_handler == SIG_DFL) { int exit_code = signr; /* Init gets no signals it doesn't want. */ if (current->pid == 1) continue; switch (signr) { case SIGCONT: case SIGCHLD: case SIGWINCH: continue; case SIGTSTP: case SIGTTIN: case SIGTTOU: if (is_orphaned_pgrp(current->pgrp)) continue; /* FALLTHRU */ case SIGSTOP: current->state = TASK_STOPPED; current->exit_code = signr; if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) notify_parent(current, SIGCHLD); schedule(); continue; case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGSEGV: if (do_coredump(signr, regs)) exit_code |= 0x80; /* FALLTHRU */ default: sigaddset(¤t->pending.signal, signr); recalc_sigpending(current); current->flags |= PF_SIGNALED; do_exit(exit_code); /* NOTREACHED */ } } if (regs->regs[0]) syscall_restart(regs, ka); /* Whee! Actually deliver the signal. */ handle_signal(signr, ka, &info, oldset, regs); return 1; } /* * Who's code doesn't conform to the restartable syscall convention * dies here!!! The li instruction, a single machine instruction, * must directly be followed by the syscall instruction. */ if (regs->regs[0]) { if (regs->regs[2] == ERESTARTNOHAND || regs->regs[2] == ERESTARTSYS || regs->regs[2] == ERESTARTNOINTR) { regs->cp0_epc -= 8; } } return 0; }
/* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. * * Note that we go through the signals twice: once to check the signals that * the kernel can handle, and then we build all the user-level signal handling * stack-frames in one go after that. */ static void do_signal(struct pt_regs *regs, int syscall) { struct k_sigaction ka; siginfo_t info; int signr; /* * We want the common case to go fast, which * is why we may in certain cases get here from * kernel mode. Just return without doing anything * if so. */ if (!user_mode(regs)) return; if (try_to_freeze()) goto no_signal; single_step_clear(current); signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { sigset_t *oldset; if (test_thread_flag(TIF_RESTORE_SIGMASK)) oldset = ¤t->saved_sigmask; else oldset = ¤t->blocked; if (handle_signal(signr, &ka, &info, oldset, regs, syscall) == 0) { /* * A signal was successfully delivered; the saved * sigmask will have been stored in the signal frame, * and will be restored by sigreturn, so we can simply * clear the TIF_RESTORE_SIGMASK flag. */ if (test_thread_flag(TIF_RESTORE_SIGMASK)) clear_thread_flag(TIF_RESTORE_SIGMASK); } single_step_set(current); return; } no_signal: /* * No signal to deliver to the process - restart the syscall. */ if (syscall) { if (regs->ARM_r0 == -ERESTART_RESTARTBLOCK) { regs->ARM_r0 = -EAGAIN; /* prevent multiple restarts */ if (thumb_mode(regs)) { regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE; regs->ARM_pc -= 2; } else { #if defined(CONFIG_AEABI) && !defined(CONFIG_OABI_COMPAT) regs->ARM_r7 = __NR_restart_syscall; regs->ARM_pc -= 4; #else u32 __user *usp; regs->ARM_sp -= 4; usp = (u32 __user *)regs->ARM_sp; if (put_user(regs->ARM_pc, usp) == 0) { regs->ARM_pc = KERN_RESTART_CODE; } else { regs->ARM_sp += 4; force_sigsegv(0, current); } #endif } } if (regs->ARM_r0 == -ERESTARTNOHAND || regs->ARM_r0 == -ERESTARTSYS || regs->ARM_r0 == -ERESTARTNOINTR) { setup_syscall_restart(regs); } /* If there's no signal to deliver, we just put the saved sigmask * back. */ if (test_thread_flag(TIF_RESTORE_SIGMASK)) { clear_thread_flag(TIF_RESTORE_SIGMASK); sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); } } single_step_set(current); }
isc_result_t isc__app_ctxstart(isc_appctx_t *ctx0) { isc__appctx_t *ctx = (isc__appctx_t *)ctx0; isc_result_t result; int presult; sigset_t sset; char strbuf[ISC_STRERRORSIZE]; REQUIRE(VALID_APPCTX(ctx)); /* * Start an ISC library application. */ #ifdef NEED_PTHREAD_INIT /* * BSDI 3.1 seg faults in pthread_sigmask() if we don't do this. */ presult = pthread_init(); if (presult != 0) { isc__strerror(presult, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_app_start() pthread_init: %s", strbuf); return (ISC_R_UNEXPECTED); } #endif #ifdef ISC_PLATFORM_USETHREADS #ifdef HAVE_LINUXTHREADS main_thread = pthread_self(); #endif /* HAVE_LINUXTHREADS */ result = isc_mutex_init(&ctx->readylock); if (result != ISC_R_SUCCESS) return (result); result = isc_condition_init(&ctx->ready); if (result != ISC_R_SUCCESS) goto cleanup_rlock; result = isc_mutex_init(&ctx->lock); if (result != ISC_R_SUCCESS) goto cleanup_rcond; #else /* ISC_PLATFORM_USETHREADS */ result = isc_mutex_init(&ctx->lock); if (result != ISC_R_SUCCESS) goto cleanup; #endif /* ISC_PLATFORM_USETHREADS */ ISC_LIST_INIT(ctx->on_run); ctx->shutdown_requested = ISC_FALSE; ctx->running = ISC_FALSE; ctx->want_shutdown = ISC_FALSE; ctx->want_reload = ISC_FALSE; ctx->blocked = ISC_FALSE; #ifndef HAVE_SIGWAIT /* * Install do-nothing handlers for SIGINT and SIGTERM. * * We install them now because BSDI 3.1 won't block * the default actions, regardless of what we do with * pthread_sigmask(). */ result = handle_signal(SIGINT, exit_action); if (result != ISC_R_SUCCESS) goto cleanup; result = handle_signal(SIGTERM, exit_action); if (result != ISC_R_SUCCESS) goto cleanup; #endif /* * Always ignore SIGPIPE. */ result = handle_signal(SIGPIPE, SIG_IGN); if (result != ISC_R_SUCCESS) goto cleanup; /* * On Solaris 2, delivery of a signal whose action is SIG_IGN * will not cause sigwait() to return. We may have inherited * unexpected actions for SIGHUP, SIGINT, and SIGTERM from our parent * process (e.g, Solaris cron). Set an action of SIG_DFL to make * sure sigwait() works as expected. Only do this for SIGTERM and * SIGINT if we don't have sigwait(), since a different handler is * installed above. */ result = handle_signal(SIGHUP, SIG_DFL); if (result != ISC_R_SUCCESS) goto cleanup; #ifdef HAVE_SIGWAIT result = handle_signal(SIGTERM, SIG_DFL); if (result != ISC_R_SUCCESS) goto cleanup; result = handle_signal(SIGINT, SIG_DFL); if (result != ISC_R_SUCCESS) goto cleanup; #endif #ifdef ISC_PLATFORM_USETHREADS /* * Block SIGHUP, SIGINT, SIGTERM. * * If isc_app_start() is called from the main thread before any other * threads have been created, then the pthread_sigmask() call below * will result in all threads having SIGHUP, SIGINT and SIGTERM * blocked by default, ensuring that only the thread that calls * sigwait() for them will get those signals. */ if (sigemptyset(&sset) != 0 || sigaddset(&sset, SIGHUP) != 0 || sigaddset(&sset, SIGINT) != 0 || sigaddset(&sset, SIGTERM) != 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_app_start() sigsetops: %s", strbuf); result = ISC_R_UNEXPECTED; goto cleanup; } presult = pthread_sigmask(SIG_BLOCK, &sset, NULL); if (presult != 0) { isc__strerror(presult, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_app_start() pthread_sigmask: %s", strbuf); result = ISC_R_UNEXPECTED; goto cleanup; } #else /* ISC_PLATFORM_USETHREADS */ /* * Unblock SIGHUP, SIGINT, SIGTERM. * * If we're not using threads, we need to make sure that SIGHUP, * SIGINT and SIGTERM are not inherited as blocked from the parent * process. */ if (sigemptyset(&sset) != 0 || sigaddset(&sset, SIGHUP) != 0 || sigaddset(&sset, SIGINT) != 0 || sigaddset(&sset, SIGTERM) != 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_app_start() sigsetops: %s", strbuf); result = ISC_R_UNEXPECTED; goto cleanup; } presult = sigprocmask(SIG_UNBLOCK, &sset, NULL); if (presult != 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_app_start() sigprocmask: %s", strbuf); result = ISC_R_UNEXPECTED; goto cleanup; } #endif /* ISC_PLATFORM_USETHREADS */ return (ISC_R_SUCCESS); cleanup: #ifdef ISC_PLATFORM_USETHREADS cleanup_rcond: (void)isc_condition_destroy(&ctx->ready); cleanup_rlock: (void)isc_mutex_destroy(&ctx->readylock); #endif /* ISC_PLATFORM_USETHREADS */ return (result); }
/* The decryption_func_bruteforce thread function tests all the passwords of the form: * prefix + x + combination + suffix * where x is a character in the range charset[dfargs.index_start] -> charset[dfargs.index_end]. */ void * decryption_func_bruteforce(void *arg) { struct decryption_func_locals *dfargs; wchar_t *password; unsigned char *pwd, *key, *iv, *masterkey, *seckey, hash[32]; unsigned int password_len, pwd_len, index_start, index_end, len, i, j, k; unsigned int masterkey_len1, masterkey_len2, seckey_len1, seckey_len2; int ret; unsigned int *tab; EVP_CIPHER_CTX ctx; dfargs = (struct decryption_func_locals *) arg; index_start = dfargs->index_start; index_end = dfargs->index_end; sha256d(pubkey, pubkey_len, hash); key = (unsigned char *) malloc(EVP_CIPHER_key_length(cipher)); iv = (unsigned char *) malloc(EVP_CIPHER_iv_length(cipher)); masterkey = (unsigned char *) malloc(encrypted_masterkey_len + EVP_CIPHER_block_size(EVP_aes_256_cbc())); seckey = (unsigned char *) malloc(encrypted_seckey_len + EVP_CIPHER_block_size(EVP_aes_256_cbc())); if((key == NULL) || (iv == NULL) || (masterkey == NULL) || (seckey == NULL)) { fprintf(stderr, "Error: memory allocation failed.\n\n"); exit(EXIT_FAILURE); } /* For every possible length */ for(len = min_len - prefix_len - 1 - suffix_len; len + 1 <= max_len - prefix_len - suffix_len; len++) { /* For every first character in the range we were given */ for(k = index_start; k <= index_end; k++) { password_len = prefix_len + 1 + len + suffix_len; password = (wchar_t *) calloc(password_len + 1, sizeof(wchar_t)); tab = (unsigned int *) calloc(len + 1, sizeof(unsigned int)); if((password == NULL) || (tab == NULL)) { fprintf(stderr, "Error: memory allocation failed.\n\n"); exit(EXIT_FAILURE); } wcsncpy(password, prefix, prefix_len); password[prefix_len] = charset[k]; wcsncpy(password + prefix_len + 1 + len, suffix, suffix_len); password[password_len] = '\0'; for(i = 0; i <= len; i++) tab[i] = 0; /* Test all the combinations */ while((tab[len] == 0) && (stop == 0)) { for(i = 0; i < len; i++) password[prefix_len + 1 + i] = charset[tab[len - 1 - i]]; pwd_len = wcstombs(NULL, password, 0); pwd = (unsigned char *) malloc(pwd_len + 1); if(pwd == NULL) { fprintf(stderr, "Error: memory allocation failed.\n\n"); exit(EXIT_FAILURE); } wcstombs(pwd, password, pwd_len + 1); /* Decrypt the master key with the password */ EVP_BytesToKey(cipher, digest, salt, pwd, pwd_len, rounds, key, iv); EVP_DecryptInit(&ctx, EVP_aes_256_cbc(), key, iv); EVP_DecryptUpdate(&ctx, masterkey, &masterkey_len1, encrypted_masterkey, encrypted_masterkey_len); ret = EVP_DecryptFinal(&ctx, masterkey + masterkey_len1, &masterkey_len2); dfargs->counter++; if(ret == 1) { /* Decrypt the secret key with the master key */ EVP_CIPHER_CTX_cleanup(&ctx); EVP_DecryptInit(&ctx, EVP_aes_256_cbc(), masterkey, hash); EVP_DecryptUpdate(&ctx, seckey, &seckey_len1, encrypted_seckey, encrypted_seckey_len); ret = EVP_DecryptFinal(&ctx, seckey + seckey_len1, &seckey_len2); if((ret == 1) && valid_seckey(seckey, seckey_len1 + seckey_len2, pubkey, pubkey_len)) { /* We have a positive result */ handle_signal(SIGUSR1); /* Print some stats */ pthread_mutex_lock(&found_password_lock); found_password = 1; printf("Password found: %ls\n", password); stop = 1; pthread_mutex_unlock(&found_password_lock); } } EVP_CIPHER_CTX_cleanup(&ctx); free(pwd); if(len == 0) break; tab[0]++; if(tab[0] == charset_len) tab[0] = 0; j = 0; while((j < len) && (tab[j] == 0)) { j++; tab[j]++; if(tab[j] == charset_len) tab[j] = 0; } } free(tab); free(password); } } free(masterkey); free(seckey); free(iv); free(key); pthread_exit(NULL); }
isc_result_t isc__app_ctxrun(isc_appctx_t *ctx0) { isc__appctx_t *ctx = (isc__appctx_t *)ctx0; int result; isc_event_t *event, *next_event; isc_task_t *task; #ifdef ISC_PLATFORM_USETHREADS sigset_t sset; char strbuf[ISC_STRERRORSIZE]; #ifdef HAVE_SIGWAIT int sig; #endif /* HAVE_SIGWAIT */ #endif /* ISC_PLATFORM_USETHREADS */ REQUIRE(VALID_APPCTX(ctx)); #ifdef HAVE_LINUXTHREADS REQUIRE(main_thread == pthread_self()); #endif LOCK(&ctx->lock); if (!ctx->running) { ctx->running = ISC_TRUE; /* * Post any on-run events (in FIFO order). */ for (event = ISC_LIST_HEAD(ctx->on_run); event != NULL; event = next_event) { next_event = ISC_LIST_NEXT(event, ev_link); ISC_LIST_UNLINK(ctx->on_run, event, ev_link); task = event->ev_sender; event->ev_sender = NULL; isc_task_sendanddetach(&task, &event); } } UNLOCK(&ctx->lock); #ifndef ISC_PLATFORM_USETHREADS if (isc_bind9 && ctx == &isc_g_appctx) { result = handle_signal(SIGHUP, reload_action); if (result != ISC_R_SUCCESS) return (ISC_R_SUCCESS); } (void) isc__taskmgr_dispatch(ctx->taskmgr); result = evloop(ctx); return (result); #else /* ISC_PLATFORM_USETHREADS */ /* * BIND9 internal tools using multiple contexts do not * rely on signal. */ if (isc_bind9 && ctx != &isc_g_appctx) return (ISC_R_SUCCESS); /* * There is no danger if isc_app_shutdown() is called before we * wait for signals. Signals are blocked, so any such signal will * simply be made pending and we will get it when we call * sigwait(). */ while (!ctx->want_shutdown) { #ifdef HAVE_SIGWAIT if (isc_bind9) { /* * BIND9 internal; single context: * Wait for SIGHUP, SIGINT, or SIGTERM. */ if (sigemptyset(&sset) != 0 || sigaddset(&sset, SIGHUP) != 0 || sigaddset(&sset, SIGINT) != 0 || sigaddset(&sset, SIGTERM) != 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_app_run() sigsetops: %s", strbuf); return (ISC_R_UNEXPECTED); } #ifndef HAVE_UNIXWARE_SIGWAIT result = sigwait(&sset, &sig); if (result == 0) { if (sig == SIGINT || sig == SIGTERM) ctx->want_shutdown = ISC_TRUE; else if (sig == SIGHUP) ctx->want_reload = ISC_TRUE; } #else /* Using UnixWare sigwait semantics. */ sig = sigwait(&sset); if (sig >= 0) { if (sig == SIGINT || sig == SIGTERM) ctx->want_shutdown = ISC_TRUE; else if (sig == SIGHUP) ctx->want_reload = ISC_TRUE; } #endif /* HAVE_UNIXWARE_SIGWAIT */ } else { /* * External, or BIND9 using multiple contexts: * wait until woken up. */ LOCK(&ctx->readylock); if (ctx->want_shutdown) { /* shutdown() won the race. */ UNLOCK(&ctx->readylock); break; } if (!ctx->want_reload) WAIT(&ctx->ready, &ctx->readylock); UNLOCK(&ctx->readylock); } #else /* Don't have sigwait(). */ if (isc_bind9) { /* * BIND9 internal; single context: * Install a signal handler for SIGHUP, then wait for * all signals. */ result = handle_signal(SIGHUP, reload_action); if (result != ISC_R_SUCCESS) return (ISC_R_SUCCESS); if (sigemptyset(&sset) != 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_app_run() sigsetops: %s", strbuf); return (ISC_R_UNEXPECTED); } #ifdef HAVE_GPERFTOOLS_PROFILER if (sigaddset(&sset, SIGALRM) != 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_app_run() sigsetops: %s", strbuf); return (ISC_R_UNEXPECTED); } #endif (void)sigsuspend(&sset); } else { /* * External, or BIND9 using multiple contexts: * wait until woken up. */ LOCK(&ctx->readylock); if (ctx->want_shutdown) { /* shutdown() won the race. */ UNLOCK(&ctx->readylock); break; } if (!ctx->want_reload) WAIT(&ctx->ready, &ctx->readylock); UNLOCK(&ctx->readylock); } #endif /* HAVE_SIGWAIT */ if (ctx->want_reload) { ctx->want_reload = ISC_FALSE; return (ISC_R_RELOAD); } if (ctx->want_shutdown && ctx->blocked) exit(1); } return (ISC_R_SUCCESS); #endif /* ISC_PLATFORM_USETHREADS */ }
int main(int argc, char **argv) { pthread_t *decryption_threads; char *filename; int i, ret, c; setlocale(LC_ALL, ""); OpenSSL_add_all_algorithms(); /* Get options and parameters. */ opterr = 0; while((c = getopt(argc, argv, "b:e:f:hl:m:s:t:")) != -1) switch(c) { case 'b': prefix_len = mbstowcs(NULL, optarg, 0); if(prefix_len == (unsigned int) -1) { fprintf(stderr, "Error: invalid character in prefix.\n\n"); exit(EXIT_FAILURE); } prefix = (wchar_t *) calloc(prefix_len + 1, sizeof(wchar_t)); if(prefix == NULL) { fprintf(stderr, "Error: memory allocation failed.\n\n"); exit(EXIT_FAILURE); } mbstowcs(prefix, optarg, prefix_len + 1); break; case 'e': suffix_len = mbstowcs(NULL, optarg, 0); if(suffix_len == (unsigned int) -1) { fprintf(stderr, "Error: invalid character in suffix.\n\n"); exit(EXIT_FAILURE); } suffix = (wchar_t *) calloc(suffix_len + 1, sizeof(wchar_t)); if(suffix == NULL) { fprintf(stderr, "Error: memory allocation failed.\n\n"); exit(EXIT_FAILURE); } mbstowcs(suffix, optarg, suffix_len + 1); break; case 'f': dictionary = fopen(optarg, "r"); if(dictionary == NULL) { fprintf(stderr, "Error: can't open dictionary file.\n\n"); exit(EXIT_FAILURE); } break; case 'h': usage(argv[0]); exit(EXIT_FAILURE); break; case 'l': min_len = (unsigned int) atoi(optarg); break; case 'm': max_len = (unsigned int) atoi(optarg); break; case 's': charset_len = mbstowcs(NULL, optarg, 0); if(charset_len == 0) { fprintf(stderr, "Error: charset must have at least one character.\n\n"); exit(EXIT_FAILURE); } if(charset_len == (unsigned int) -1) { fprintf(stderr, "Error: invalid character in charset.\n\n"); exit(EXIT_FAILURE); } charset = (wchar_t *) calloc(charset_len + 1, sizeof(wchar_t)); if(charset == NULL) { fprintf(stderr, "Error: memory allocation failed.\n\n"); exit(EXIT_FAILURE); } mbstowcs(charset, optarg, charset_len + 1); break; case 't': nb_threads = (unsigned int) atoi(optarg); if(nb_threads == 0) nb_threads = 1; break; default: usage(argv[0]); switch(optopt) { case 'b': case 'e': case 'f': case 'l': case 'm': case 's': case 't': fprintf(stderr, "Error: missing argument for option: '-%c'.\n\n", optopt); break; default: fprintf(stderr, "Error: unknown option: '%c'.\n\n", optopt); break; } exit(EXIT_FAILURE); break; } if(optind >= argc) { usage(argv[0]); fprintf(stderr, "Error: missing wallet filename.\n\n"); exit(EXIT_FAILURE); } filename = argv[optind]; /* Check variables */ if(dictionary != NULL) { fprintf(stderr, "Warning: using dictionary mode, ignoring options -b, -e, -l, -m and -s.\n\n"); } else { if(prefix == NULL) { prefix_len = mbstowcs(NULL, "", 0); prefix = (wchar_t *) calloc(prefix_len + 1, sizeof(wchar_t)); if(prefix == NULL) { fprintf(stderr, "Error: memory allocation failed.\n\n"); exit(EXIT_FAILURE); } mbstowcs(prefix, "", prefix_len + 1); } if(suffix == NULL) { suffix_len = mbstowcs(NULL, "", 0); suffix = (wchar_t *) calloc(suffix_len + 1, sizeof(wchar_t)); if(suffix == NULL) { fprintf(stderr, "Error: memory allocation failed.\n\n"); exit(EXIT_FAILURE); } mbstowcs(suffix, "", suffix_len + 1); } if(charset == NULL) { charset_len = mbstowcs(NULL, default_charset, 0); charset = (wchar_t *) calloc(charset_len + 1, sizeof(wchar_t)); if(charset == NULL) { fprintf(stderr, "Error: memory allocation failed.\n\n"); exit(EXIT_FAILURE); } mbstowcs(charset, default_charset, charset_len + 1); } if(nb_threads > charset_len) { fprintf(stderr, "Warning: number of threads (%u) bigger than character set length (%u). Only using %u threads.\n\n", nb_threads, charset_len, charset_len); nb_threads = charset_len; } if(min_len < prefix_len + suffix_len + 1) { fprintf(stderr, "Warning: minimum length (%u) smaller than the length of specified password characters (%u). Setting minimum length to %u.\n\n", min_len, prefix_len + suffix_len, prefix_len + suffix_len + 1); min_len = prefix_len + suffix_len + 1; } if(max_len < min_len) { fprintf(stderr, "Warning: maximum length (%u) smaller than minimum length (%u). Setting maximum length to %u.\n\n", max_len, min_len, min_len); max_len = min_len; } } signal(SIGUSR1, handle_signal); /* Get data from the encrypted wallet */ ret = get_wallet_info(filename); if(ret == 0) { fprintf(stderr, "Error: couldn't find required info in wallet.\n\n"); exit(EXIT_FAILURE); } pthread_mutex_init(&found_password_lock, NULL); pthread_mutex_init(&dictionary_lock, NULL); /* Start decryption threads. */ decryption_threads = (pthread_t *) calloc(nb_threads, sizeof(pthread_t)); thread_locals = (struct decryption_func_locals *) calloc(nb_threads, sizeof(struct decryption_func_locals)); if((decryption_threads == NULL) || (thread_locals == NULL)) { fprintf(stderr, "Error: memory allocation failed.\n\n"); exit(EXIT_FAILURE); } for(i = 0; i < nb_threads; i++) { if(dictionary == NULL) { thread_locals[i].index_start = i * (charset_len / nb_threads); if(i == nb_threads - 1) thread_locals[i].index_end = charset_len - 1; else thread_locals[i].index_end = (i + 1) * (charset_len / nb_threads) - 1; ret = pthread_create(&decryption_threads[i], NULL, &decryption_func_bruteforce, &thread_locals[i]); } else { ret = pthread_create(&decryption_threads[i], NULL, &decryption_func_dictionary, &thread_locals[i]); } if(ret != 0) { perror("Error: decryption thread"); exit(EXIT_FAILURE); } } for(i = 0; i < nb_threads; i++) { pthread_join(decryption_threads[i], NULL); } if(found_password == 0) { handle_signal(SIGUSR1); /* Print some stats */ fprintf(stderr, "Password not found\n"); } free(thread_locals); free(decryption_threads); pthread_mutex_destroy(&found_password_lock); pthread_mutex_destroy(&dictionary_lock); free(encrypted_masterkey); free(encrypted_seckey); free(pubkey); EVP_cleanup(); exit(EXIT_SUCCESS); }
/* Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. */ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) { struct k_sigaction ka; int restart_syscall; sigset_t *oldset; siginfo_t info; int signr; /* It's a lot of work and synchronization to add a new ptrace * register for GDB to save and restore in order to get * orig_i0 correct for syscall restarts when debugging. * * Although it should be the case that most of the global * registers are volatile across a system call, glibc already * depends upon that fact that we preserve them. So we can't * just use any global register to save away the orig_i0 value. * * In particular %g2, %g3, %g4, and %g5 are all assumed to be * preserved across a system call trap by various pieces of * code in glibc. * * %g7 is used as the "thread register". %g6 is not used in * any fixed manner. %g6 is used as a scratch register and * a compiler temporary, but it's value is never used across * a system call. Therefore %g6 is usable for orig_i0 storage. */ if (pt_regs_is_syscall(regs) && (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) regs->u_regs[UREG_G6] = orig_i0; if (current_thread_info()->status & TS_RESTORE_SIGMASK) oldset = ¤t->saved_sigmask; else oldset = ¤t->blocked; #ifdef CONFIG_COMPAT if (test_thread_flag(TIF_32BIT)) { extern void do_signal32(sigset_t *, struct pt_regs *); do_signal32(oldset, regs); return; } #endif signr = get_signal_to_deliver(&info, &ka, regs, NULL); restart_syscall = 0; if (pt_regs_is_syscall(regs) && (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) { restart_syscall = 1; orig_i0 = regs->u_regs[UREG_G6]; } if (signr > 0) { if (restart_syscall) syscall_restart(orig_i0, regs, &ka.sa); if (handle_signal(signr, &ka, &info, oldset, regs) == 0) { /* A signal was successfully delivered; the saved * sigmask will have been stored in the signal frame, * and will be restored by sigreturn, so we can simply * clear the TS_RESTORE_SIGMASK flag. */ current_thread_info()->status &= ~TS_RESTORE_SIGMASK; } return; } if (restart_syscall && (regs->u_regs[UREG_I0] == ERESTARTNOHAND || regs->u_regs[UREG_I0] == ERESTARTSYS || regs->u_regs[UREG_I0] == ERESTARTNOINTR)) { /* replay the system call when we are done */ regs->u_regs[UREG_I0] = orig_i0; regs->tpc -= 4; regs->tnpc -= 4; pt_regs_clear_syscall(regs); } if (restart_syscall && regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { regs->u_regs[UREG_G1] = __NR_restart_syscall; regs->tpc -= 4; regs->tnpc -= 4; pt_regs_clear_syscall(regs); } /* If there's no signal to deliver, we just put the saved sigmask * back */ if (current_thread_info()->status & TS_RESTORE_SIGMASK) { current_thread_info()->status &= ~TS_RESTORE_SIGMASK; sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); } }
ISC_APPFUNC_SCOPE isc_result_t isc__app_ctxrun(isc_appctx_t *ctx0) { isc__appctx_t *ctx = (isc__appctx_t *)ctx0; int result; isc_event_t *event, *next_event; isc_task_t *task; #ifdef USE_THREADS_SINGLECTX sigset_t sset; char strbuf[ISC_STRERRORSIZE]; #ifdef HAVE_SIGWAIT int sig; #endif #endif /* USE_THREADS_SINGLECTX */ REQUIRE(VALID_APPCTX(ctx)); #ifdef HAVE_LINUXTHREADS REQUIRE(main_thread == pthread_self()); #endif LOCK(&ctx->lock); if (!ctx->running) { ctx->running = ISC_TRUE; /* * Post any on-run events (in FIFO order). */ for (event = ISC_LIST_HEAD(ctx->on_run); event != NULL; event = next_event) { next_event = ISC_LIST_NEXT(event, ev_link); ISC_LIST_UNLINK(ctx->on_run, event, ev_link); task = event->ev_sender; event->ev_sender = NULL; isc_task_sendanddetach(&task, &event); } } UNLOCK(&ctx->lock); #ifndef HAVE_SIGWAIT /* * Catch SIGHUP. * * We do this here to ensure that the signal handler is installed * (i.e. that it wasn't a "one-shot" handler). */ if (ctx == &isc_g_appctx) { result = handle_signal(SIGHUP, reload_action); if (result != ISC_R_SUCCESS) return (ISC_R_SUCCESS); } #endif #ifdef USE_THREADS_SINGLECTX /* * When we are using multiple contexts, we don't rely on signals. */ if (ctx != &isc_g_appctx) return (ISC_R_SUCCESS); /* * There is no danger if isc_app_shutdown() is called before we wait * for signals. Signals are blocked, so any such signal will simply * be made pending and we will get it when we call sigwait(). */ while (!ctx->want_shutdown) { #ifdef HAVE_SIGWAIT /* * Wait for SIGHUP, SIGINT, or SIGTERM. */ if (sigemptyset(&sset) != 0 || sigaddset(&sset, SIGHUP) != 0 || sigaddset(&sset, SIGINT) != 0 || sigaddset(&sset, SIGTERM) != 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_app_run() sigsetops: %s", strbuf); return (ISC_R_UNEXPECTED); } #ifndef HAVE_UNIXWARE_SIGWAIT result = sigwait(&sset, &sig); if (result == 0) { if (sig == SIGINT || sig == SIGTERM) ctx->want_shutdown = ISC_TRUE; else if (sig == SIGHUP) ctx->want_reload = ISC_TRUE; } #else /* Using UnixWare sigwait semantics. */ sig = sigwait(&sset); if (sig >= 0) { if (sig == SIGINT || sig == SIGTERM) ctx->want_shutdown = ISC_TRUE; else if (sig == SIGHUP) ctx->want_reload = ISC_TRUE; } #endif /* HAVE_UNIXWARE_SIGWAIT */ #else /* Don't have sigwait(). */ /* * Listen for all signals. */ if (sigemptyset(&sset) != 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_app_run() sigsetops: %s", strbuf); return (ISC_R_UNEXPECTED); } result = sigsuspend(&sset); #endif /* HAVE_SIGWAIT */ if (ctx->want_reload) { ctx->want_reload = ISC_FALSE; return (ISC_R_RELOAD); } if (ctx->want_shutdown && ctx->blocked) exit(1); } #else /* USE_THREADS_SINGLECTX */ (void)isc__taskmgr_dispatch(ctx->taskmgr); result = evloop(ctx); if (result != ISC_R_SUCCESS) return (result); #endif /* USE_THREADS_SINGLECTX */ return (ISC_R_SUCCESS); }
int main(int argc, char **argv) { int fd_count = 0; struct pollfd ufds[4]; int property_set_fd_init = 0; int signal_fd_init = 0; int keychord_fd_init = 0; bool is_charger = false; if (!strcmp(basename(argv[0]), "ueventd")) return ueventd_main(argc, argv); if (!strcmp(basename(argv[0]), "watchdogd")) return watchdogd_main(argc, argv); /* clear the umask */ umask(0); /* Get the basic filesystem setup we need put * together in the initramdisk on / and then we'll * let the rc file figure out the rest. */ mkdir("/dev", 0755); mkdir("/proc", 0755); mkdir("/sys", 0755); mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"); mkdir("/dev/pts", 0755); mkdir("/dev/socket", 0755); mount("devpts", "/dev/pts", "devpts", 0, NULL); mount("proc", "/proc", "proc", 0, NULL); mount("sysfs", "/sys", "sysfs", 0, NULL); /* indicate that booting is in progress to background fw loaders, etc */ close(open("/dev/.booting", O_WRONLY | O_CREAT, 0000)); /* We must have some place other than / to create the * device nodes for kmsg and null, otherwise we won't * be able to remount / read-only later on. * Now that tmpfs is mounted on /dev, we can actually * talk to the outside world. */ open_devnull_stdio(); klog_init(); property_init(); get_hardware_name(hardware, &revision); process_kernel_cmdline(); union selinux_callback cb; cb.func_log = log_callback; selinux_set_callback(SELINUX_CB_LOG, cb); cb.func_audit = audit_callback; selinux_set_callback(SELINUX_CB_AUDIT, cb); selinux_initialize(); /* These directories were necessarily created before initial policy load * and therefore need their security context restored to the proper value. * This must happen before /dev is populated by ueventd. */ restorecon("/dev"); restorecon("/dev/socket"); restorecon("/dev/__properties__"); restorecon_recursive("/sys"); is_charger = !strcmp(bootmode, "charger"); INFO("property init\n"); property_load_boot_defaults(); INFO("reading config file\n"); init_parse_config_file("/init.rc"); action_for_each_trigger("early-init", action_add_queue_tail); queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done"); queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng"); queue_builtin_action(keychord_init_action, "keychord_init"); queue_builtin_action(console_init_action, "console_init"); /* execute all the boot actions to get us started */ action_for_each_trigger("init", action_add_queue_tail); /* Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random * wasn't ready immediately after wait_for_coldboot_done */ queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng"); queue_builtin_action(property_service_init_action, "property_service_init"); queue_builtin_action(signal_init_action, "signal_init"); /* Don't mount filesystems or start core system services if in charger mode. */ if (is_charger) { action_for_each_trigger("charger", action_add_queue_tail); } else { action_for_each_trigger("late-init", action_add_queue_tail); } /* run all property triggers based on current state of the properties */ queue_builtin_action(queue_property_triggers_action, "queue_property_triggers"); #if BOOTCHART queue_builtin_action(bootchart_init_action, "bootchart_init"); #endif for(;;) { int nr, i, timeout = -1; execute_one_command(); restart_processes(); if (!property_set_fd_init && get_property_set_fd() > 0) { ufds[fd_count].fd = get_property_set_fd(); ufds[fd_count].events = POLLIN; ufds[fd_count].revents = 0; fd_count++; property_set_fd_init = 1; } if (!signal_fd_init && get_signal_fd() > 0) { ufds[fd_count].fd = get_signal_fd(); ufds[fd_count].events = POLLIN; ufds[fd_count].revents = 0; fd_count++; signal_fd_init = 1; } if (!keychord_fd_init && get_keychord_fd() > 0) { ufds[fd_count].fd = get_keychord_fd(); ufds[fd_count].events = POLLIN; ufds[fd_count].revents = 0; fd_count++; keychord_fd_init = 1; } if (process_needs_restart) { timeout = (process_needs_restart - gettime()) * 1000; if (timeout < 0) timeout = 0; } if (!action_queue_empty() || cur_action) timeout = 0; #if BOOTCHART if (bootchart_count > 0) { long long current_time; int elapsed_time, remaining_time; current_time = bootchart_gettime(); elapsed_time = current_time - bootchart_time; if (elapsed_time >= BOOTCHART_POLLING_MS) { /* count missed samples */ while (elapsed_time >= BOOTCHART_POLLING_MS) { elapsed_time -= BOOTCHART_POLLING_MS; bootchart_count--; } /* count may be negative, take a sample anyway */ bootchart_time = current_time; if (bootchart_step() < 0 || bootchart_count <= 0) { bootchart_finish(); bootchart_count = 0; } } if (bootchart_count > 0) { remaining_time = BOOTCHART_POLLING_MS - elapsed_time; if (timeout < 0 || timeout > remaining_time) timeout = remaining_time; } } #endif nr = poll(ufds, fd_count, timeout); if (nr <= 0) continue; for (i = 0; i < fd_count; i++) { if (ufds[i].revents & POLLIN) { if (ufds[i].fd == get_property_set_fd()) handle_property_set_fd(); else if (ufds[i].fd == get_keychord_fd()) handle_keychord(); else if (ufds[i].fd == get_signal_fd()) handle_signal(); } } } return 0; }
/* Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. */ static void do_signal(struct pt_regs *regs, unsigned long orig_i0, int restart_syscall) { siginfo_t info; struct signal_deliver_cookie cookie; struct k_sigaction ka; int signr; sigset_t *oldset; cookie.restart_syscall = restart_syscall; cookie.orig_i0 = orig_i0; if (test_thread_flag(TIF_RESTORE_SIGMASK)) oldset = ¤t->saved_sigmask; else oldset = ¤t->blocked; #ifdef CONFIG_SPARC32_COMPAT if (test_thread_flag(TIF_32BIT)) { extern void do_signal32(sigset_t *, struct pt_regs *, unsigned long, int); do_signal32(oldset, regs, orig_i0, cookie.restart_syscall); return; } #endif signr = get_signal_to_deliver(&info, &ka, regs, &cookie); if (signr > 0) { if (cookie.restart_syscall) syscall_restart(orig_i0, regs, &ka.sa); handle_signal(signr, &ka, &info, oldset, regs); /* a signal was successfully delivered; the saved * sigmask will have been stored in the signal frame, * and will be restored by sigreturn, so we can simply * clear the TIF_RESTORE_SIGMASK flag. */ if (test_thread_flag(TIF_RESTORE_SIGMASK)) clear_thread_flag(TIF_RESTORE_SIGMASK); return; } if (cookie.restart_syscall && (regs->u_regs[UREG_I0] == ERESTARTNOHAND || regs->u_regs[UREG_I0] == ERESTARTSYS || regs->u_regs[UREG_I0] == ERESTARTNOINTR)) { /* replay the system call when we are done */ regs->u_regs[UREG_I0] = cookie.orig_i0; regs->tpc -= 4; regs->tnpc -= 4; } if (cookie.restart_syscall && regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { regs->u_regs[UREG_G1] = __NR_restart_syscall; regs->tpc -= 4; regs->tnpc -= 4; } /* if there's no signal to deliver, we just put the saved sigmask * back */ if (test_thread_flag(TIF_RESTORE_SIGMASK)) { clear_thread_flag(TIF_RESTORE_SIGMASK); sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); } }
/* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. * * Note that we go through the signals twice: once to check the signals that * the kernel can handle, and then we build all the user-level signal handling * stack-frames in one go after that. */ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) { struct k_sigaction *ka; siginfo_t info; int single_stepping; /* * We want the common case to go fast, which * is why we may in certain cases get here from * kernel mode. Just return without doing anything * if so. */ if (!user_mode(regs)) return 0; if (!oldset) oldset = ¤t->blocked; single_stepping = ptrace_cancel_bpt(current); for (;;) { unsigned long signr; spin_lock_irq (¤t->sigmask_lock); signr = dequeue_signal(¤t->blocked, &info); spin_unlock_irq (¤t->sigmask_lock); if (!signr) break; if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) { /* Let the debugger run. */ current->exit_code = signr; current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); schedule(); single_stepping |= ptrace_cancel_bpt(current); /* We're back. Did the debugger cancel the sig? */ if (!(signr = current->exit_code)) continue; current->exit_code = 0; /* The debugger continued. Ignore SIGSTOP. */ if (signr == SIGSTOP) continue; /* Update the siginfo structure. Is this good? */ if (signr != info.si_signo) { info.si_signo = signr; info.si_errno = 0; info.si_code = SI_USER; info.si_pid = current->p_pptr->pid; info.si_uid = current->p_pptr->uid; } /* If the (new) signal is now blocked, requeue it. */ if (sigismember(¤t->blocked, signr)) { send_sig_info(signr, &info, current); continue; } } ka = ¤t->sig->action[signr-1]; if (ka->sa.sa_handler == SIG_IGN) { if (signr != SIGCHLD) continue; /* Check for SIGCHLD: it's special. */ while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0) /* nothing */; continue; } if (ka->sa.sa_handler == SIG_DFL) { int exit_code = signr; /* Init gets no signals it doesn't want. */ if (current->pid == 1) continue; switch (signr) { case SIGCONT: case SIGCHLD: case SIGWINCH: case SIGURG: continue; case SIGTSTP: case SIGTTIN: case SIGTTOU: if (is_orphaned_pgrp(current->pgrp)) continue; /* FALLTHRU */ case SIGSTOP: { struct signal_struct *sig; current->state = TASK_STOPPED; current->exit_code = signr; sig = current->p_pptr->sig; if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) notify_parent(current, SIGCHLD); schedule(); single_stepping |= ptrace_cancel_bpt(current); continue; } case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGSEGV: case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ: if (do_coredump(signr, regs)) exit_code |= 0x80; /* FALLTHRU */ default: sigaddset(¤t->pending.signal, signr); recalc_sigpending(current); current->flags |= PF_SIGNALED; do_exit(exit_code); /* NOTREACHED */ } } /* Are we from a system call? */ if (syscall) { switch (regs->ARM_r0) { case -ERESTARTNOHAND: regs->ARM_r0 = -EINTR; break; case -ERESTARTSYS: if (!(ka->sa.sa_flags & SA_RESTART)) { regs->ARM_r0 = -EINTR; break; } /* fallthrough */ case -ERESTARTNOINTR: regs->ARM_r0 = regs->ARM_ORIG_r0; regs->ARM_pc -= 4; } } /* Whee! Actually deliver the signal. */ handle_signal(signr, ka, &info, oldset, regs); if (single_stepping) ptrace_set_bpt(current); return 1; } if (syscall && (regs->ARM_r0 == -ERESTARTNOHAND || regs->ARM_r0 == -ERESTARTSYS || regs->ARM_r0 == -ERESTARTNOINTR)) { regs->ARM_r0 = regs->ARM_ORIG_r0; regs->ARM_pc -= 4; } if (single_stepping) ptrace_set_bpt(current); return 0; }
int main(int argc, char **argv) { int fd_count = 0; struct pollfd ufds[4]; char *tmpdev; char* debuggable; char tmp[32]; int property_set_fd_init = 0; int signal_fd_init = 0; int keychord_fd_init = 0; bool is_charger = false; if (!strcmp(basename(argv[0]), "ueventd")) return ueventd_main(argc, argv); if (!strcmp(basename(argv[0]), "watchdogd")) return watchdogd_main(argc, argv); /* clear the umask */ umask(0); /* Get the basic filesystem setup we need put * together in the initramdisk on / and then we'll * let the rc file figure out the rest. */ mkdir("/dev", 0755); mkdir("/proc", 0755); mkdir("/sys", 0755); mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"); mkdir("/dev/pts", 0755); mkdir("/dev/socket", 0755); mount("devpts", "/dev/pts", "devpts", 0, NULL); mount("proc", "/proc", "proc", 0, NULL); mount("sysfs", "/sys", "sysfs", 0, NULL); /* indicate that booting is in progress to background fw loaders, etc */ close(open("/dev/.booting", O_WRONLY | O_CREAT, 0000)); /* We must have some place other than / to create the * device nodes for kmsg and null, otherwise we won't * be able to remount / read-only later on. * Now that tmpfs is mounted on /dev, we can actually * talk to the outside world. */ open_devnull_stdio(); klog_init(); property_init(); get_hardware_name(hardware, &revision); process_kernel_cmdline(); union selinux_callback cb; cb.func_log = klog_write; selinux_set_callback(SELINUX_CB_LOG, cb); cb.func_audit = audit_callback; selinux_set_callback(SELINUX_CB_AUDIT, cb); INFO("loading selinux policy\n"); if (selinux_enabled) { if (selinux_android_load_policy() < 0) { selinux_enabled = 0; INFO("SELinux: Disabled due to failed policy load\n"); } else { selinux_init_all_handles(); } } else { INFO("SELinux: Disabled by command line option\n"); } /* These directories were necessarily created before initial policy load * and therefore need their security context restored to the proper value. * This must happen before /dev is populated by ueventd. */ restorecon("/dev"); restorecon("/dev/socket"); is_charger = !strcmp(bootmode, "charger"); INFO("property init\n"); if (!is_charger) property_load_boot_defaults(); INFO("reading config file\n"); init_parse_config_file("/init.rc"); action_for_each_trigger("early-init", action_add_queue_tail); queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done"); queue_builtin_action(keychord_init_action, "keychord_init"); queue_builtin_action(console_init_action, "console_init"); /* execute all the boot actions to get us started */ action_for_each_trigger("init", action_add_queue_tail); /* skip mounting filesystems in charger mode */ if (!is_charger) { action_for_each_trigger("early-fs", action_add_queue_tail); action_for_each_trigger("fs", action_add_queue_tail); action_for_each_trigger("post-fs", action_add_queue_tail); action_for_each_trigger("post-fs-data", action_add_queue_tail); } queue_builtin_action(property_service_init_action, "property_service_init"); queue_builtin_action(signal_init_action, "signal_init"); queue_builtin_action(check_startup_action, "check_startup"); if (is_charger) { action_for_each_trigger("charger", action_add_queue_tail); } else { action_for_each_trigger("early-boot", action_add_queue_tail); action_for_each_trigger("boot", action_add_queue_tail); } /* run all property triggers based on current state of the properties */ queue_builtin_action(queue_property_triggers_action, "queue_property_triggers"); #if BOOTCHART queue_builtin_action(bootchart_init_action, "bootchart_init"); #endif for(;;) { int nr, i, timeout = -1; execute_one_command(); restart_processes(); if (!property_set_fd_init && get_property_set_fd() > 0) { ufds[fd_count].fd = get_property_set_fd(); ufds[fd_count].events = POLLIN; ufds[fd_count].revents = 0; fd_count++; property_set_fd_init = 1; } if (!signal_fd_init && get_signal_fd() > 0) { ufds[fd_count].fd = get_signal_fd(); ufds[fd_count].events = POLLIN; ufds[fd_count].revents = 0; fd_count++; signal_fd_init = 1; } if (!keychord_fd_init && get_keychord_fd() > 0) { ufds[fd_count].fd = get_keychord_fd(); ufds[fd_count].events = POLLIN; ufds[fd_count].revents = 0; fd_count++; keychord_fd_init = 1; } if (process_needs_restart) { timeout = (process_needs_restart - gettime()) * 1000; if (timeout < 0) timeout = 0; } if (!action_queue_empty() || cur_action) timeout = 0; #if BOOTCHART if (bootchart_count > 0) { if (timeout < 0 || timeout > BOOTCHART_POLLING_MS) timeout = BOOTCHART_POLLING_MS; if (bootchart_step() < 0 || --bootchart_count == 0) { bootchart_finish(); bootchart_count = 0; } } #endif nr = poll(ufds, fd_count, timeout); if (nr <= 0) continue; for (i = 0; i < fd_count; i++) { if (ufds[i].revents == POLLIN) { if (ufds[i].fd == get_property_set_fd()) handle_property_set_fd(); else if (ufds[i].fd == get_keychord_fd()) handle_keychord(); else if (ufds[i].fd == get_signal_fd()) handle_signal(); } } } return 0; }
/* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. * * Note that we go through the signals twice: once to check the signals that * the kernel can handle, and then we build all the user-level signal handling * stack-frames in one go after that. * * "r0" and "r19" are the registers we need to restore for system call * restart. "r0" is also used as an indicator whether we can restart at * all (if we get here from anything but a syscall return, it will be 0) */ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, struct switch_stack * sw, unsigned long r0, unsigned long r19) { unsigned long single_stepping = ptrace_cancel_bpt(current); if (!oldset) oldset = ¤t->blocked; while (1) { unsigned long signr; struct k_sigaction *ka; siginfo_t info; spin_lock_irq(¤t->sigmask_lock); signr = dequeue_signal(¤t->blocked, &info); spin_unlock_irq(¤t->sigmask_lock); if (!signr) break; if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) { /* Let the debugger run. */ current->exit_code = signr; current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); schedule(); single_stepping |= ptrace_cancel_bpt(current); /* We're back. Did the debugger cancel the sig? */ if (!(signr = current->exit_code)) continue; current->exit_code = 0; /* The debugger continued. Ignore SIGSTOP. */ if (signr == SIGSTOP) continue; /* Update the siginfo structure. Is this good? */ if (signr != info.si_signo) { info.si_signo = signr; info.si_errno = 0; info.si_code = SI_USER; info.si_pid = current->p_pptr->pid; info.si_uid = current->p_pptr->uid; } /* If the (new) signal is now blocked, requeue it. */ if (sigismember(¤t->blocked, signr)) { send_sig_info(signr, &info, current); continue; } } ka = ¤t->sig->action[signr-1]; if (ka->sa.sa_handler == SIG_IGN) { if (signr != SIGCHLD) continue; /* Check for SIGCHLD: it's special. */ while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0) /* nothing */; continue; } if (ka->sa.sa_handler == SIG_DFL) { int exit_code = signr & 0x7f; /* Init gets no signals it doesn't want. */ if (current->pid == 1) continue; switch (signr) { case SIGCONT: case SIGCHLD: case SIGWINCH: continue; case SIGTSTP: case SIGTTIN: case SIGTTOU: if (is_orphaned_pgrp(current->pgrp)) continue; /* FALLTHRU */ case SIGSTOP: current->state = TASK_STOPPED; current->exit_code = signr; if (!(current->p_pptr->sig->action[SIGCHLD-1] .sa.sa_flags & SA_NOCLDSTOP)) notify_parent(current, SIGCHLD); schedule(); single_stepping |= ptrace_cancel_bpt(current); continue; case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGSEGV: case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ: if (do_coredump(signr, regs)) exit_code |= 0x80; /* FALLTHRU */ default: lock_kernel(); sigaddset(¤t->pending.signal, signr); current->flags |= PF_SIGNALED; do_exit(exit_code); /* NOTREACHED */ } continue; } /* Whee! Actually deliver the signal. */ if (r0) syscall_restart(r0, r19, regs, ka); handle_signal(signr, ka, &info, oldset, regs, sw); if (single_stepping) ptrace_set_bpt(current); /* re-set bpt */ return 1; } if (r0 && (regs->r0 == ERESTARTNOHAND || regs->r0 == ERESTARTSYS || regs->r0 == ERESTARTNOINTR)) { regs->r0 = r0; /* reset v0 and a3 and replay syscall */ regs->r19 = r19; regs->pc -= 4; } if (single_stepping) ptrace_set_bpt(current); /* re-set breakpoint */ return 0; }