asmlinkage long compat_sys_wait4(compat_pid_t pid, compat_uint_t __user *stat_addr, int options, struct compat_rusage __user *ru) { if (!ru) { return sys_wait4(pid, stat_addr, options, NULL); } else { struct rusage r; int ret; unsigned int status; mm_segment_t old_fs = get_fs(); set_fs (KERNEL_DS); ret = sys_wait4(pid, (stat_addr ? (unsigned int __user *) &status : NULL), options, (struct rusage __user *) &r); set_fs (old_fs); if (ret > 0) { if (put_compat_rusage(&r, ru)) return -EFAULT; if (stat_addr && put_user(status, stat_addr)) return -EFAULT; } return ret; } }
COMPAT_SYSCALL_DEFINE4(wait4, compat_pid_t, pid, compat_uint_t __user *, stat_addr, int, options, struct compat_rusage __user *, ru) { if (!ru) { return sys_wait4(pid, stat_addr, options, NULL); } else { struct rusage r; int ret; unsigned int status; mm_segment_t old_fs = get_fs(); set_fs (KERNEL_DS); ret = sys_wait4(pid, (stat_addr ? (unsigned int __force_user *) &status : NULL), options, (struct rusage __force_user *) &r); set_fs (old_fs); if (ret > 0) { if (put_compat_rusage(&r, ru)) return -EFAULT; if (stat_addr && put_user(status, stat_addr)) return -EFAULT; } return ret; } }
/* Keventd can't block, but this (a child) can. */ static int wait_for_helper(void *data) { struct subprocess_info *sub_info = data; pid_t pid; struct k_sigaction sa; /* Install a handler: if SIGCLD isn't handled sys_wait4 won't * populate the status, but will return -ECHILD. */ sa.sa.sa_handler = SIG_IGN; sa.sa.sa_flags = 0; siginitset(&sa.sa.sa_mask, sigmask(SIGCHLD)); do_sigaction(SIGCHLD, &sa, (struct k_sigaction *)0); allow_signal(SIGCHLD); pid = kernel_thread(____call_usermodehelper, sub_info, SIGCHLD); if (pid < 0) { sub_info->retval = pid; } else { /* * Normally it is bogus to call wait4() from in-kernel because * wait4() wants to write the exit code to a userspace address. * But wait_for_helper() always runs as keventd, and put_user() * to a kernel address works OK for kernel threads, due to their * having an mm_segment_t which spans the entire address space. * * Thus the __user pointer cast is valid here. */ sys_wait4(pid, (int __user *) &sub_info->retval, 0, NULL); } complete(sub_info->complete); return 0; }
/* So stupid... */ asmlinkage int sunos_wait4(pid_t pid, unsigned int __user *stat_addr, int options, struct rusage __user*ru) { int ret; ret = sys_wait4((pid ? pid : -1), stat_addr, options, ru); return ret; }
int wyse_wait3(int *loc) { pid_t pid; int res; pid = sys_wait4(-1, loc, WNOHANG, 0); if (!loc) return pid; get_user(res, (unsigned long *)loc); if ((res & 0xff) == 0x7f) { int sig = (res >> 8) & 0xff; sig = current->exec_domain->signal_map[sig]; res = (res & (~0xff00)) | (sig << 8); put_user(res, (unsigned long *)loc); } else if (res && res == (res & 0xff)) {
static int wait_helpers(struct task_restore_args *task_args) { int i; for (i = 0; i < task_args->n_helpers; i++) { int status; pid_t pid = task_args->helpers[i]; /* Check that a helper completed. */ if (sys_wait4(pid, &status, 0, NULL) == -1) { /* It has been waited in sigchld_handler */ continue; } if (!WIFEXITED(status) || WEXITSTATUS(status)) { pr_err("%d exited with non-zero code (%d,%d)\n", pid, WEXITSTATUS(status), WTERMSIG(status)); return -1; } } return 0; }
/* Keventd can't block, but this (a child) can. */ static int wait_for_helper(void *data) { struct subprocess_info *sub_info = data; pid_t pid; /* If SIGCLD is ignored sys_wait4 won't populate the status. */ spin_lock_irq(¤t->sighand->siglock); current->sighand->action[SIGCHLD-1].sa.sa_handler = SIG_DFL; spin_unlock_irq(¤t->sighand->siglock); pid = kernel_thread(____call_usermodehelper, sub_info, SIGCHLD); if (pid < 0) { sub_info->retval = pid; } else { int ret = -ECHILD; /* * Normally it is bogus to call wait4() from in-kernel because * wait4() wants to write the exit code to a userspace address. * But wait_for_helper() always runs as keventd, and put_user() * to a kernel address works OK for kernel threads, due to their * having an mm_segment_t which spans the entire address space. * * Thus the __user pointer cast is valid here. */ sys_wait4(pid, (int __user *)&ret, 0, NULL); /* * If ret is 0, either ____call_usermodehelper failed and the * real error code is already in sub_info->retval or * sub_info->retval is 0 anyway, so don't mess with it then. */ if (ret) sub_info->retval = ret; } complete(sub_info->complete); return 0; }
/* * sys_waitpid() remains for compatibility. waitpid() should be * implemented by calling sys_wait4() from libc.a. */ asmlinkage long sys_waitpid(pid_t pid,unsigned int * stat_addr, int options) { return sys_wait4(pid, stat_addr, options, NULL); }
/* * This is the task which runs the usermode application */ static int ____call_usermodehelper(void *data) { struct subprocess_info *sub_info = data; int retval; BUG_ON(atomic_read(&sub_info->cred->usage) != 1); /* Unblock all signals */ spin_lock_irq(¤t->sighand->siglock); flush_signal_handlers(current, 1); sigemptyset(¤t->blocked); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); /* Install the credentials */ commit_creds(sub_info->cred); sub_info->cred = NULL; /* Install input pipe when needed */ if (sub_info->stdin) { struct files_struct *f = current->files; struct fdtable *fdt; /* no races because files should be private here */ sys_close(0); fd_install(0, sub_info->stdin); spin_lock(&f->file_lock); fdt = files_fdtable(f); FD_SET(0, fdt->open_fds); FD_CLR(0, fdt->close_on_exec); spin_unlock(&f->file_lock); /* and disallow core files too */ current->signal->rlim[RLIMIT_CORE] = (struct rlimit){0, 0}; } /* We can run anywhere, unlike our parent keventd(). */ set_cpus_allowed_ptr(current, cpu_all_mask); /* * Our parent is keventd, which runs with elevated scheduling priority. * Avoid propagating that into the userspace child. */ set_user_nice(current, 0); if (sub_info->init) { retval = sub_info->init(sub_info); if (retval) goto fail; } retval = kernel_execve(sub_info->path, sub_info->argv, sub_info->envp); /* Exec failed? */ fail: sub_info->retval = retval; return 0; } void call_usermodehelper_freeinfo(struct subprocess_info *info) { if (info->cleanup) (*info->cleanup)(info); if (info->cred) put_cred(info->cred); kfree(info); } EXPORT_SYMBOL(call_usermodehelper_freeinfo); static void umh_complete(struct subprocess_info *sub_info) { struct completion *comp = xchg(&sub_info->complete, NULL); /* * See call_usermodehelper_exec(). If xchg() returns NULL * we own sub_info, the UMH_KILLABLE caller has gone away. */ if (comp) complete(comp); else call_usermodehelper_freeinfo(sub_info); } /* Keventd can't block, but this (a child) can. */ static int wait_for_helper(void *data) { struct subprocess_info *sub_info = data; pid_t pid; /* Install a handler: if SIGCLD isn't handled sys_wait4 won't * populate the status, but will return -ECHILD. */ allow_signal(SIGCHLD); pid = kernel_thread(____call_usermodehelper, sub_info, SIGCHLD); if (pid < 0) { sub_info->retval = pid; } else { int ret; /* * Normally it is bogus to call wait4() from in-kernel because * wait4() wants to write the exit code to a userspace address. * But wait_for_helper() always runs as keventd, and put_user() * to a kernel address works OK for kernel threads, due to their * having an mm_segment_t which spans the entire address space. * * Thus the __user pointer cast is valid here. */ sys_wait4(pid, (int __user *)&ret, 0, NULL); /* * If ret is 0, either ____call_usermodehelper failed and the * real error code is already in sub_info->retval or * sub_info->retval is 0 anyway, so don't mess with it then. */ if (ret) sub_info->retval = ret; } if (sub_info->wait == UMH_NO_WAIT) call_usermodehelper_freeinfo(sub_info); else umh_complete(sub_info); return 0; } /* This is run by khelper thread */ static void __call_usermodehelper(struct work_struct *work) { struct subprocess_info *sub_info = container_of(work, struct subprocess_info, work); int wait = sub_info->wait & ~UMH_KILLABLE; pid_t pid; BUG_ON(atomic_read(&sub_info->cred->usage) != 1); /* CLONE_VFORK: wait until the usermode helper has execve'd * successfully We need the data structures to stay around * until that is done. */ if (wait == UMH_WAIT_PROC || wait == UMH_NO_WAIT) pid = kernel_thread(wait_for_helper, sub_info, CLONE_FS | CLONE_FILES | SIGCHLD); else pid = kernel_thread(____call_usermodehelper, sub_info, CLONE_VFORK | SIGCHLD); switch (wait) { case UMH_NO_WAIT: break; case UMH_WAIT_PROC: if (pid > 0) break; sub_info->retval = pid; /* FALLTHROUGH */ case UMH_WAIT_EXEC: umh_complete(sub_info); } } #ifdef CONFIG_PM_SLEEP /* * If set, call_usermodehelper_exec() will exit immediately returning -EBUSY * (used for preventing user land processes from being created after the user * land has been frozen during a system-wide hibernation or suspend operation). * Should always be manipulated under umhelper_sem acquired for write. */ static int usermodehelper_disabled; /* Number of helpers running */ static atomic_t running_helpers = ATOMIC_INIT(0); /* * Wait queue head used by usermodehelper_pm_callback() to wait for all running * helpers to finish. */ static DECLARE_WAIT_QUEUE_HEAD(running_helpers_waitq); /* * Time to wait for running_helpers to become zero before the setting of * usermodehelper_disabled in usermodehelper_pm_callback() fails */ #define RUNNING_HELPERS_TIMEOUT (5 * HZ) void read_lock_usermodehelper(void) { down_read(&umhelper_sem); }
static void __init handle_initrd(void) { int error; int pid; real_root_dev = new_encode_dev(ROOT_DEV); create_dev("/dev/root.old", Root_RAM0); /* mount initrd on rootfs' /root */ mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY); sys_mkdir("/old", 0700); root_fd = sys_open("/", 0, 0); old_fd = sys_open("/old", 0, 0); /* move initrd over / and chdir/chroot in initrd root */ sys_chdir("/root"); sys_mount(".", "/", NULL, MS_MOVE, NULL); sys_chroot("."); pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD); if (pid > 0) { while (pid != sys_wait4(-1, NULL, 0, NULL)) { try_to_freeze(); yield(); } } /* move initrd to rootfs' /old */ sys_fchdir(old_fd); sys_mount("/", ".", NULL, MS_MOVE, NULL); /* switch root and cwd back to / of rootfs */ sys_fchdir(root_fd); sys_chroot("."); sys_close(old_fd); sys_close(root_fd); if (new_decode_dev(real_root_dev) == Root_RAM0) { sys_chdir("/old"); return; } ROOT_DEV = new_decode_dev(real_root_dev); mount_root(); printk(KERN_NOTICE "Trying to move old root to /initrd ... "); error = sys_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL); if (!error) printk("okay\n"); else { int fd = sys_open("/dev/root.old", O_RDWR, 0); if (error == -ENOENT) printk("/initrd does not exist. Ignored.\n"); else printk("failed\n"); printk(KERN_NOTICE "Unmounting old root\n"); sys_umount("/old", MNT_DETACH); printk(KERN_NOTICE "Trying to free ramdisk memory ... "); if (fd < 0) { error = fd; } else { error = sys_ioctl(fd, BLKFLSBUF, 0); sys_close(fd); } printk(!error ? "okay\n" : "failed\n"); } }
int do_signal(sigset_t *oldset, struct pt_regs *regs) { siginfo_t info; struct k_sigaction *ka; unsigned long frame, newsp; /* * If the current thread is 32 bit - invoke the * 32 bit signal handling code */ if (current->thread.flags & PPC_FLAG_32BIT) return do_signal32(oldset, regs); if (!oldset) oldset = ¤t->blocked; newsp = frame = 0; for (;;) { unsigned long signr; PPCDBG(PPCDBG_SIGNAL, "do_signal - (pre) dequeueing signal - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm); spin_lock_irq(¤t->sigmask_lock); signr = dequeue_signal(¤t->blocked, &info); spin_unlock_irq(¤t->sigmask_lock); PPCDBG(PPCDBG_SIGNAL, "do_signal - (aft) dequeueing signal - signal=%lx - pid=%ld current=%lx comm=%s \n", signr, current->pid, current, current->comm); 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]; PPCDBG(PPCDBG_SIGNAL, "do_signal - ka=%p, action handler=%lx \n", ka, ka->sa.sa_handler); if (ka->sa.sa_handler == SIG_IGN) { PPCDBG(PPCDBG_SIGNAL, "do_signal - into SIG_IGN logic \n"); 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; PPCDBG(PPCDBG_SIGNAL, "do_signal - into SIG_DFL logic \n"); /* 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(); 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: sig_exit(signr, exit_code, &info); /* NOTREACHED */ } } if ( (ka->sa.sa_flags & SA_ONSTACK) && (! on_sig_stack(regs->gpr[1]))) newsp = (current->sas_ss_sp + current->sas_ss_size); else newsp = regs->gpr[1]; newsp = frame = newsp - sizeof(struct sigregs); /* Whee! Actually deliver the signal. */ PPCDBG(PPCDBG_SIGNAL, "do_signal - GOING TO RUN SIGNAL HANDLER - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm); handle_signal(signr, ka, &info, oldset, regs, &newsp, frame); PPCDBG(PPCDBG_SIGNAL, "do_signal - after running signal handler - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm); break; } if (regs->trap == 0x0C00 /* System Call! */ && ((int)regs->result == -ERESTARTNOHAND || (int)regs->result == -ERESTARTSYS || (int)regs->result == -ERESTARTNOINTR)) { PPCDBG(PPCDBG_SIGNAL, "do_signal - going to back up & retry system call \n"); regs->gpr[3] = regs->orig_gpr3; regs->nip -= 4; /* Back up & retry system call */ regs->result = 0; } if (newsp == frame) { PPCDBG(PPCDBG_SIGNAL, "do_signal - returning w/ no signal delivered \n"); return 0; /* no signals delivered */ } if (ka->sa.sa_flags & SA_SIGINFO) setup_rt_frame(regs, (struct sigregs *) frame, newsp); else setup_frame(regs, (struct sigregs *) frame, newsp); PPCDBG(PPCDBG_SIGNAL, "do_signal - returning a signal was delivered \n"); 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. * * 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: sig_exit(signr, exit_code, &info); /* 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: restart_syscall(regs); break; } } /* 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)) { restart_syscall(regs); } if (single_stepping) ptrace_set_bpt(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. */ 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) { /* Do the syscall restart before we let the debugger * look at the child registers. */ if (restart_syscall && (regs->u_regs[UREG_I0] == ERESTARTNOHAND || regs->u_regs[UREG_I0] == ERESTARTSYS || regs->u_regs[UREG_I0] == ERESTARTNOINTR)) { regs->u_regs[UREG_I0] = orig_i0; regs->tpc -= 4; regs->tnpc -= 4; restart_syscall = 0; } 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: case SIGURG: 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: sig_exit(signr, exit_code, &info); /* 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; }
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. * * "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; }
/** * Blocking wait for a child to exit. This is used when waiting for * cpp, gcc, etc. * * This is not used by the daemon-parent; it has its own * implementation in dcc_reap_kids(). They could be unified, but the * parent only waits when it thinks a child has exited; the child * waits all the time. **/ int dcc_collect_child(const char *what, pid_t pid, int *wait_status, int in_fd) { struct rusage ru; pid_t ret_pid; int ret; int wait_timeout_sec; fd_set fds,readfds; wait_timeout_sec = dcc_job_lifetime; FD_ZERO(&readfds); if (in_fd != timeout_null_fd){ FD_SET(in_fd,&readfds); } while (!dcc_job_lifetime || wait_timeout_sec-- >= 0) { /* If we're called with a socket, break out of the loop if the socket * disconnects. To do that, we need to block in select, not in * sys_wait4. (Only waitpid uses WNOHANG to mean don't block ever, * so I've modified sys_wait4 above to preferentially call waitpid.) */ int flags = (in_fd == timeout_null_fd) ? 0 : WNOHANG; ret_pid = sys_wait4(pid, wait_status, flags, &ru); if (ret_pid == -1) { if (errno == EINTR) { rs_trace("wait4 was interrupted; retrying"); } else { rs_log_error("sys_wait4(pid=%d) borked: %s", (int) pid, strerror(errno)); return EXIT_DISTCC_FAILED; } } else if (ret_pid != 0) { /* This is not the main user-visible message; that comes from * critique_status(). */ rs_trace("%s child %ld terminated with status %#x", what, (long) ret_pid, *wait_status); rs_log_info("%s times: user %lld.%06lds, system %lld.%06lds, " "%ld minflt, %ld majflt", what, ru.ru_utime.tv_sec, (long) ru.ru_utime.tv_usec, ru.ru_stime.tv_sec, (long) ru.ru_stime.tv_usec, ru.ru_minflt, ru.ru_majflt); return 0; } /* check timeout */ if (in_fd != timeout_null_fd) { struct timeval timeout; /* If client disconnects, the socket will become readable, * and a read should return -1 and set errno to EPIPE. */ fds = readfds; timeout.tv_sec = 1; timeout.tv_usec = 0; ret = select(in_fd+1,&fds,NULL,NULL,&timeout); if (ret == 1) { char buf; int nread = read(in_fd, &buf, 1); if ((nread == -1) && (errno == EWOULDBLOCK)) { /* spurious wakeup, ignore */ ; } else if (nread == 0) { rs_log_error("Client fd disconnected, killing job"); /* If killpg fails, it might means the child process is not * in a new group, so, just kill the child process */ if (killpg(pid,SIGTERM)!=0) kill(pid, SIGTERM); return EXIT_IO_ERROR; } else if (nread == 1) { rs_log_error("Bug! Read from fd succeeded when checking " "whether client disconnected!"); } else { rs_log_error("Bug! nread %d, errno %d checking whether " "client disconnected!", nread, errno); } } } else { poll(NULL, 0, 1000); } } /* If timeout, also kill the child process */ if (killpg(pid, SIGTERM) != 0) kill(pid, SIGTERM); rs_log_error("Compilation takes too long, timeout."); return EXIT_TIMEOUT; }
/* * 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; }
/** * kthread_create_ve - create a kthread. * @threadfn: the function to run until signal_pending(current). * @data: data ptr for @threadfn. * @namefmt: printf-style name for the thread. * * Description: This helper function creates and names a kernel * thread. The thread will be stopped: use wake_up_process() to start * it. See also kthread_run(), kthread_create_on_cpu(). * * When woken, the thread will run @threadfn() with @data as its * argument. @threadfn() can either call do_exit() directly if it is a * standalone thread for which noone will call kthread_stop(), or * return when 'kthread_should_stop()' is true (which means * kthread_stop() has been called). The return value should be zero * or a negative error number; it will be passed to kthread_stop(). * * Returns a task_struct or ERR_PTR(-ENOMEM). */ struct task_struct *kthread_create_ve(struct ve_struct *ve, int (*threadfn)(void *data), void *data, const char namefmt[], ...) { struct kthread_create_info create; struct ve_struct *old_ve; old_ve = set_exec_env(ve); create.threadfn = threadfn; create.data = data; init_completion(&create.done); spin_lock(&kthread_create_lock); list_add_tail(&create.list, &kthread_create_list); spin_unlock(&kthread_create_lock); wake_up_process(kthreadd_task); wait_for_completion(&create.done); if (!IS_ERR(create.result)) { struct sched_param param = { .sched_priority = 0 }; va_list args; va_start(args, namefmt); vsnprintf(create.result->comm, sizeof(create.result->comm), namefmt, args); va_end(args); /* * root may have changed our (kthreadd's) priority or CPU mask. * The kernel thread should not inherit these properties. */ sched_setscheduler_nocheck(create.result, SCHED_NORMAL, ¶m); set_cpus_allowed_ptr(create.result, cpu_all_mask); } set_exec_env(old_ve); return create.result; } EXPORT_SYMBOL(kthread_create_ve); /** * kthread_stop - stop a thread created by kthread_create(). * @k: thread created by kthread_create(). * * Sets kthread_should_stop() for @k to return true, wakes it, and * waits for it to exit. This can also be called after kthread_create() * instead of calling wake_up_process(): the thread will exit without * calling threadfn(). * * If threadfn() may call do_exit() itself, the caller must ensure * task_struct can't go away. * * Returns the result of threadfn(), or %-EINTR if wake_up_process() * was never called. */ int kthread_stop(struct task_struct *k) { struct kthread *kthread; int ret; trace_sched_kthread_stop(k); get_task_struct(k); kthread = to_kthread(k); barrier(); /* it might have exited */ if (k->vfork_done != NULL) { kthread->should_stop = 1; wake_up_process(k); wait_for_completion(&kthread->exited); } ret = k->exit_code; put_task_struct(k); trace_sched_kthread_stop_ret(ret); return ret; } EXPORT_SYMBOL(kthread_stop); int kthreadd(void *data) { struct task_struct *tsk = current; struct kthreadd_create_info *kcreate; struct kthread self; int rc; self.should_stop = 0; kcreate = (struct kthreadd_create_info *) data; if (kcreate) { daemonize("kthreadd/%d", get_exec_env()->veid); kcreate->result = current; set_fs(KERNEL_DS); init_completion(&self.exited); current->vfork_done = &self.exited; } else set_task_comm(tsk, "kthreadd"); /* Setup a clean context for our children to inherit. */ ignore_signals(tsk); set_cpus_allowed_ptr(tsk, cpu_all_mask); set_mems_allowed(node_states[N_HIGH_MEMORY]); current->flags |= PF_NOFREEZE | PF_FREEZER_NOSIG; if (kcreate) complete(&kcreate->done); for (;;) { set_current_state(TASK_INTERRUPTIBLE); if (list_empty(&kthread_create_list)) { if (self.should_stop) break; else schedule(); } __set_current_state(TASK_RUNNING); spin_lock(&kthread_create_lock); while (!list_empty(&kthread_create_list)) { struct kthread_create_info *create; create = list_entry(kthread_create_list.next, struct kthread_create_info, list); list_del_init(&create->list); spin_unlock(&kthread_create_lock); create_kthread(create); spin_lock(&kthread_create_lock); } spin_unlock(&kthread_create_lock); } do { clear_thread_flag(TIF_SIGPENDING); rc = sys_wait4(-1, NULL, __WALL, NULL); } while (rc != -ECHILD); do_exit(0); } int kthreadd_create() { struct kthreadd_create_info create; int ret; struct ve_struct *ve = get_exec_env(); BUG_ON(ve->_kthreadd_task); INIT_LIST_HEAD(&ve->_kthread_create_list); init_completion(&create.done); ret = kernel_thread(kthreadd, (void *) &create, CLONE_FS); if (ret < 0) { return ret; } wait_for_completion(&create.done); ve->_kthreadd_task = create.result; return 0; } EXPORT_SYMBOL(kthreadd_create); void kthreadd_stop(struct ve_struct *ve) { struct kthread *kthread; int ret; struct task_struct *k; if (!ve->_kthreadd_task) return; k = ve->_kthreadd_task; trace_sched_kthread_stop(k); get_task_struct(k); BUG_ON(!k->vfork_done); kthread = container_of(k->vfork_done, struct kthread, exited); kthread->should_stop = 1; wake_up_process(k); wait_for_completion(&kthread->exited); ret = k->exit_code; put_task_struct(k); trace_sched_kthread_stop_ret(ret); } EXPORT_SYMBOL(kthreadd_stop);
int do_signal(struct pt_regs *regs, sigset_t *oldset) { siginfo_t info; struct k_sigaction *ka; /* * 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 ((regs->xcs & 3) != 3) return 1; 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; /* We should probably find a better way to do this. */ if(ssmunch_multi) { int i; /* Here's a hack. If we get a signal that's not * one of the signals sent by ssmunch, then * we won't print a message, since the ssmunch'd * process is probably dead or mostly dead. * Mostly dead is not quite the same as dead; for more * information on this topic please see Miracle Max. */ for(i = 0; i < 32; i++) { if(ssmunch_multi&(1<<i)) break; } if(i == 32) goto no_ssmunch; /* HAHA! ^^^^ I used a goto! Now I'm a real * kernel h4x0r! */ printk("do_signal: multiple signals: "); for(i = 0; i < 32; i++) { if(ssmunch_multi&(1<<i)) printk("%d ", i); } printk("\n"); no_ssmunch: ssmunch_multi = 0; } if ((current->flags & PF_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: lock_kernel(); if (current->binfmt && current->binfmt->core_dump && current->binfmt->core_dump(signr, regs)) exit_code |= 0x80; unlock_kernel(); /* FALLTHRU */ default: lock_kernel(); sigaddset(¤t->signal, signr); recalc_sigpending(current); current->flags |= PF_SIGNALED; /* printk("do_signal: do_exit with %d\n", exit_code); */ do_exit(exit_code); /* NOTREACHED */ } } /* Whee! Actually deliver the signal. */ /* printk("do_signal: handle_signal with %d\n", signr); */ handle_signal(signr, ka, &info, oldset, regs); return 1; } /* Did we come from a system call? */ if (regs->orig_eax >= 0) { /* Restart the system call - no handlers present */ if (regs->eax == -ERESTARTNOHAND || regs->eax == -ERESTARTSYS || regs->eax == -ERESTARTNOINTR) { regs->eax = regs->orig_eax; regs->eip -= 2; } } return 0; }
asmlinkage int sunos_wait4(pid_t pid, unsigned int *stat_addr, int options, struct rusage *ru) { return sys_wait4((pid ? pid : -1), stat_addr, options, ru); }
/* * sys_waitpid() remains for compatibility. waitpid() should be * implemented by calling sys_wait4() from libc.a. */ int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options) { return sys_wait4(pid, stat_addr, options, NULL); }
static int get_signal_to_deliver(siginfo_t *info, struct pt_regs *regs) { for (;;) { unsigned long signr; struct k_sigaction *ka; 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? */ signr = current->exit_code; if (signr == 0) 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(); 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: sig_exit(signr, exit_code, info); /* NOTREACHED */ } } return signr; } 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. */ int do_signal(struct pt_regs *regs, sigset_t *oldset) { siginfo_t info; struct k_sigaction *ka; /* * 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 (!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: 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 */ } } /* Whee! Actually deliver the signal. */ handle_signal(signr, ka, &info, oldset, regs); return 1; } /* Did we come from a system call? */ if (PT_REGS_SYSCALL (regs)) { /* Restart the system call - no handlers present */ if (regs->gpr[GPR_RVAL] == -ERESTARTNOHAND || regs->gpr[GPR_RVAL] == -ERESTARTSYS || regs->gpr[GPR_RVAL] == -ERESTARTNOINTR) { regs->gpr[12] = PT_REGS_SYSCALL (regs); regs->pc -= 8; /* 4 + 8 for microblaze return offset wierdness */ } } 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. */ long ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) { struct signal_struct *sig; struct k_sigaction *ka; siginfo_t info; long restart = in_syscall; long errno = scr->pt.r8; /* * In the ia64_leave_kernel code path, 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(&scr->pt)) return 0; if (!oldset) oldset = ¤t->blocked; #ifdef CONFIG_IA32_SUPPORT if (IS_IA32_PROCESS(&scr->pt)) { if (in_syscall) { if (errno >= 0) restart = 0; else errno = -errno; } } else #endif if (scr->pt.r10 != -1) { /* * A system calls has to be restarted only if one of the error codes * ERESTARTNOHAND, ERESTARTSYS, or ERESTARTNOINTR is returned. If r10 * isn't -1 then r8 doesn't hold an error code and we don't need to * restart the syscall, so we can clear the "restart" flag here. */ restart = 0; } 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->thread.siginfo = &info; current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); schedule(); signr = current->exit_code; current->thread.siginfo = 0; /* We're back. Did the debugger cancel the sig? */ if (!signr) 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: 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(); 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, &scr->pt)) exit_code |= 0x80; /* FALLTHRU */ default: sig_exit(signr, exit_code, &info); /* NOTREACHED */ } } if (restart) { switch (errno) { case ERESTARTSYS: if ((ka->sa.sa_flags & SA_RESTART) == 0) { case ERESTARTNOHAND: #ifdef CONFIG_IA32_SUPPORT if (IS_IA32_PROCESS(&scr->pt)) scr->pt.r8 = -EINTR; else #endif scr->pt.r8 = EINTR; /* note: scr->pt.r10 is already -1 */ break; } case ERESTARTNOINTR: #ifdef CONFIG_IA32_SUPPORT if (IS_IA32_PROCESS(&scr->pt)) { scr->pt.r8 = scr->pt.r1; scr->pt.cr_iip -= 2; } else #endif ia64_decrement_ip(&scr->pt); } } /* Whee! Actually deliver the signal. If the delivery failed, we need to continue to iterate in this loop so we can deliver the SIGSEGV... */ if (handle_signal(signr, ka, &info, oldset, scr)) return 1; } /* Did we come from a system call? */ if (restart) { /* Restart the system call - no handlers present */ if (errno == ERESTARTNOHAND || errno == ERESTARTSYS || errno == ERESTARTNOINTR) { #ifdef CONFIG_IA32_SUPPORT if (IS_IA32_PROCESS(&scr->pt)) { scr->pt.r8 = scr->pt.r1; scr->pt.cr_iip -= 2; } else #endif /* * Note: the syscall number is in r15 which is * saved in pt_regs so all we need to do here * is adjust ip so that the "break" * instruction gets re-executed. */ ia64_decrement_ip(&scr->pt); } } return 0; }
static void __init handle_initrd(void) { int error; int pid; real_root_dev = new_encode_dev(ROOT_DEV); create_dev("/dev/root.old", Root_RAM0); /* mount initrd on rootfs' /root */ mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY); sys_mkdir((const char __user *)"/old", 0700); root_fd = sys_open((const char __user *)"/", 0, 0); old_fd = sys_open((const char __user *)"/old", 0, 0); /* move initrd over / and chdir/chroot in initrd root */ sys_chdir((const char __user *)"/root"); sys_mount((char __user *)".", (char __user *)"/", NULL, MS_MOVE, NULL); sys_chroot((const char __user *)"."); /* * In case that a resume from disk is carried out by linuxrc or one of * its children, we need to tell the freezer not to wait for us. */ current->flags |= PF_FREEZER_SKIP; pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD); if (pid > 0) while (pid != sys_wait4(-1, NULL, 0, NULL)) yield(); current->flags &= ~PF_FREEZER_SKIP; /* move initrd to rootfs' /old */ sys_fchdir(old_fd); sys_mount((char __user *)"/", (char __user *)".", NULL, MS_MOVE, NULL); /* switch root and cwd back to / of rootfs */ sys_fchdir(root_fd); sys_chroot((const char __user *)"."); sys_close(old_fd); sys_close(root_fd); if (new_decode_dev(real_root_dev) == Root_RAM0) { sys_chdir((const char __user *)"/old"); return; } ROOT_DEV = new_decode_dev(real_root_dev); mount_root(); printk(KERN_NOTICE "Trying to move old root to /initrd ... "); error = sys_mount((char __user *)"/old", (char __user *)"/root/initrd", NULL, MS_MOVE, NULL); if (!error) printk("okay\n"); else { int fd = sys_open((const char __user *)"/dev/root.old", O_RDWR, 0); if (error == -ENOENT) printk("/initrd does not exist. Ignored.\n"); else printk("failed\n"); printk(KERN_NOTICE "Unmounting old root\n"); sys_umount((char __user *)"/old", MNT_DETACH); printk(KERN_NOTICE "Trying to free ramdisk memory ... "); if (fd < 0) { error = fd; } else { error = sys_ioctl(fd, BLKFLSBUF, 0); sys_close(fd); } printk(!error ? "okay\n" : "failed\n"); } }
/* * This is the task which runs the usermode application */ static int ____call_usermodehelper(void *data) { struct subprocess_info *sub_info = data; int retval; /* Install input pipe when needed */ if (sub_info->stdin) { struct files_struct *f = current->files; struct fdtable *fdt; /* no races because files should be private here */ sys_close(0); fd_install(0, sub_info->stdin); spin_lock(&f->file_lock); fdt = files_fdtable(f); FD_SET(0, fdt->open_fds); FD_CLR(0, fdt->close_on_exec); spin_unlock(&f->file_lock); /* and disallow core files too */ current->signal->rlim[RLIMIT_CORE] = (struct rlimit){0, 0}; } /* We can run anywhere, unlike our parent keventd(). */ set_cpus_allowed(current, CPU_MASK_ALL); retval = __exec_usermodehelper(sub_info->path, sub_info->argv, sub_info->envp, sub_info->ring); /* Exec failed? */ sub_info->retval = retval; do_exit(0); } /* Keventd can't block, but this (a child) can. */ static int wait_for_helper(void *data) { struct subprocess_info *sub_info = data; pid_t pid; struct k_sigaction sa; /* Install a handler: if SIGCLD isn't handled sys_wait4 won't * populate the status, but will return -ECHILD. */ sa.sa.sa_handler = SIG_IGN; sa.sa.sa_flags = 0; siginitset(&sa.sa.sa_mask, sigmask(SIGCHLD)); do_sigaction(SIGCHLD, &sa, NULL); allow_signal(SIGCHLD); pid = kernel_thread(____call_usermodehelper, sub_info, SIGCHLD); if (pid < 0) { sub_info->retval = pid; } else { /* * Normally it is bogus to call wait4() from in-kernel because * wait4() wants to write the exit code to a userspace address. * But wait_for_helper() always runs as keventd, and put_user() * to a kernel address works OK for kernel threads, due to their * having an mm_segment_t which spans the entire address space. * * Thus the __user pointer cast is valid here. */ sys_wait4(pid, (int __user *) &sub_info->retval, 0, NULL); } complete(sub_info->complete); return 0; } /* This is run by khelper thread */ static void __call_usermodehelper(void *data) { struct subprocess_info *sub_info = data; pid_t pid; int wait = sub_info->wait; /* CLONE_VFORK: wait until the usermode helper has execve'd * successfully We need the data structures to stay around * until that is done. */ if (wait) pid = kernel_thread(wait_for_helper, sub_info, CLONE_FS | CLONE_FILES | SIGCHLD); else pid = kernel_thread(____call_usermodehelper, sub_info, CLONE_VFORK | SIGCHLD); if (pid < 0) { sub_info->retval = pid; complete(sub_info->complete); } else if (!wait) complete(sub_info->complete); } /** * call_usermodehelper_keys - start a usermode application * @path: pathname for the application * @argv: null-terminated argument list * @envp: null-terminated environment list * @session_keyring: session keyring for process (NULL for an empty keyring) * @wait: wait for the application to finish and return status. * * Runs a user-space application. The application is started * asynchronously if wait is not set, and runs as a child of keventd. * (ie. it runs with full root capabilities). * * Must be called from process context. Returns a negative error code * if program was not execed successfully, or 0. */ int call_usermodehelper_keys(char *path, char **argv, char **envp, struct key *session_keyring, int wait) { DECLARE_COMPLETION_ONSTACK(done); struct subprocess_info sub_info = { .complete = &done, .path = path, .argv = argv, .envp = envp, .ring = session_keyring, .wait = wait, .retval = 0, }; DECLARE_WORK(work, __call_usermodehelper, &sub_info); if (!khelper_wq) return -EBUSY; if (path[0] == '\0') return 0; queue_work(khelper_wq, &work); wait_for_completion(&done); return sub_info.retval; } EXPORT_SYMBOL(call_usermodehelper_keys); int call_usermodehelper_pipe(char *path, char **argv, char **envp, struct file **filp) { DECLARE_COMPLETION(done); struct subprocess_info sub_info = { .complete = &done, .path = path, .argv = argv, .envp = envp, .retval = 0, }; struct file *f; DECLARE_WORK(work, __call_usermodehelper, &sub_info); if (!khelper_wq) return -EBUSY; if (path[0] == '\0') return 0; f = create_write_pipe(); if (!f) return -ENOMEM; *filp = f; f = create_read_pipe(f); if (!f) { free_write_pipe(*filp); return -ENOMEM; } sub_info.stdin = f; queue_work(khelper_wq, &work); wait_for_completion(&done); return sub_info.retval; } EXPORT_SYMBOL(call_usermodehelper_pipe); void __init usermodehelper_init(void) { khelper_wq = create_singlethread_workqueue("khelper"); BUG_ON(!khelper_wq); }