/* * 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 in_syscall) { struct ksignal ksig; #ifdef DEBUG_SIG pr_info("do signal: %p %d\n", regs, in_syscall); pr_info("do signal2: %lx %lx %ld [%lx]\n", regs->pc, regs->r1, regs->r12, current_thread_info()->flags); #endif if (get_signal(&ksig)) { /* Whee! Actually deliver the signal. */ if (in_syscall) handle_restart(regs, &ksig.ka, 1); handle_signal(&ksig, regs); return; } if (in_syscall) handle_restart(regs, NULL, 0); /* * If there's no signal to deliver, we just put the saved sigmask * back. */ restore_saved_sigmask(); }
/* * 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 in_syscall) { siginfo_t info; int signr; struct k_sigaction ka; #ifdef DEBUG_SIG pr_info("do signal: %p %d\n", regs, in_syscall); pr_info("do signal2: %lx %lx %ld [%lx]\n", regs->pc, regs->r1, regs->r12, current_thread_info()->flags); #endif signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { /* Whee! Actually deliver the signal. */ if (in_syscall) handle_restart(regs, &ka, 1); handle_signal(signr, &ka, &info, regs); return; } if (in_syscall) handle_restart(regs, NULL, 0); /* * If there's no signal to deliver, we just put the saved sigmask * back. */ restore_saved_sigmask(); }
/* * OK, we're invoking a handler */ static int handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs) { int ret; /* are we from a system call? to see pt_regs->orig_p0 */ if (regs->orig_p0 >= 0) /* If so, check system call restarting.. */ handle_restart(regs, ka, 1); /* set up the stack frame */ ret = setup_rt_frame(sig, ka, info, oldset, regs); if (ret == 0) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); if (!(ka->sa.sa_flags & SA_NODEFER)) sigaddset(¤t->blocked, sig); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); } return ret; }
/* * 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) { 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 1; if (!oldset) oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { /* Whee! Actually deliver the signal. */ handle_signal(signr, &ka, &info, oldset, regs); return 1; } /* Did we come from a system call? */ if (regs->frame_type == -1) { /* Restart the system call - no handlers present */ handle_restart(regs, NULL, 0); } return 0; }
/* * OK, we're invoking a handler */ static void handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) { /* are we from a system call? */ if (regs->orig_er0 >= 0) /* If so, check system call restarting.. */ handle_restart(regs, ka, 1); /* set up the stack frame */ if (ka->sa.sa_flags & SA_SIGINFO) setup_rt_frame(sig, ka, info, oldset, regs); else setup_frame(sig, ka, oldset, regs); 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,sig); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); } }
/* * OK, we're invoking a handler */ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) { sigset_t *oldset = sigmask_to_save(); int ret; /* are we from a system call? */ if (regs->orig_er0 >= 0) handle_restart(regs, &ksig->ka); ret = setup_rt_frame(ksig, oldset, regs); signal_setup_done(ret, ksig, 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, int in_syscall) { siginfo_t info; int signr; struct k_sigaction ka; #ifdef DEBUG_SIG printk(KERN_INFO "do signal: %p %p %d\n", regs, oldset, in_syscall); printk(KERN_INFO "do signal2: %lx %lx %ld [%lx]\n", regs->pc, regs->r1, regs->r12, current_thread_info()->flags); #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 (kernel_mode(regs)) return 1; if (!oldset) oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { /* Whee! Actually deliver the signal. */ if (in_syscall) handle_restart(regs, &ka, 1); handle_signal(signr, &ka, &info, oldset, regs); return 1; } if (in_syscall) handle_restart(regs, NULL, 0); /* Did we come from a system call? */ 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 void do_signal(struct pt_regs *regs) { siginfo_t info; int signr; struct k_sigaction ka; sigset_t *oldset; current->thread.esp0 = (unsigned long)regs; 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, regs, NULL); if (signr > 0) { /* 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 */ if (test_thread_flag(TIF_RESTORE_SIGMASK)) clear_thread_flag(TIF_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->orig_p0 >= 0) /* Restart the system call - no handlers present */ handle_restart(regs, NULL, 0); /* 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); } }
/* * OK, we're invoking a handler */ static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka, struct pt_regs *regs) { /* are we from a system call? to see pt_regs->orig_p0 */ if (regs->orig_p0 >= 0) /* If so, check system call restarting.. */ handle_restart(regs, ka, 1); /* set up the stack frame */ if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0) force_sigsegv(sig, current); else signal_delivered(sig, info, ka, regs, test_thread_flag(TIF_SINGLESTEP)); }
/* * 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 ksignal ksig; current->thread.esp0 = (unsigned long) regs; if (get_signal(&ksig)) { /* Whee! Actually deliver the signal. */ handle_signal(&ksig, regs); return; } /* Did we come from a system call? */ if (regs->orig_er0 >= 0) handle_restart(regs, NULL); /* If there's no signal to deliver, we just restore the saved mask. */ restore_saved_sigmask(); }
/* * OK, we're invoking a handler */ static int handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs) { int ret; /* are we from a system call? to see pt_regs->orig_p0 */ if (regs->orig_p0 >= 0) /* If so, check system call restarting.. */ handle_restart(regs, ka, 1); /* set up the stack frame */ ret = setup_rt_frame(sig, ka, info, oldset, regs); if (ret == 0) block_sigmask(ka, sig); return ret; }
/* * 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 void do_signal(struct pt_regs *regs) { siginfo_t info; int signr; struct k_sigaction ka; current->thread.esp0 = (unsigned long)regs; signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { /* Whee! Actually deliver the signal. */ handle_signal(signr, &info, &ka, regs); return; } /* Did we come from a system call? */ if (regs->orig_p0 >= 0) /* Restart the system call - no handlers present */ handle_restart(regs, NULL, 0); /* if there's no signal to deliver, we just put the saved sigmask * back */ restore_saved_sigmask(); }
int do_test (int argc, char *argv[]) { pid_t pid; int status; /* We must have - one or four parameters left if called initially + path for ld.so optional + "--library-path" optional + the library path optional + the application name if --enable-hardcoded-path-in-tests is used, just + the application name */ if (restart) { if (argc != 1) { printf ("Wrong number of arguments (%d) in restart\n", argc); exit (EXIT_FAILURE); } return handle_restart (); } if (argc != 2 && argc != 5) { printf ("Wrong number of arguments (%d)\n", argc); exit (EXIT_FAILURE); } /* We want to test the `execvpe' function. To do this we restart the program with an additional parameter. */ pid = fork (); if (pid == 0) { /* This is the child. Construct the command line. */ /* We cast here to char* because the test itself does not modify neither the argument nor the environment list. */ char *envs[] = { (char*)(EXECVPE_KEY "=" EXECVPE_VALUE), NULL }; if (argc == 5) { char *args[] = { argv[1], argv[2], argv[3], argv[4], (char *) "--direct", (char *) "--restart", NULL }; execvpe (args[0], args, envs); } else { char *args[] = { argv[0], (char *) "--direct", (char *) "--restart", NULL }; execvpe (args[0], args, envs); } puts ("Cannot exec"); exit (EXIT_FAILURE); } else if (pid == (pid_t) -1) { puts ("Cannot fork"); return 1; } /* Wait for the child. */ if (waitpid (pid, &status, 0) != pid) { puts ("Wrong child"); return 1; } if (WTERMSIG (status) != 0) { puts ("Child terminated incorrectly"); return 1; } status = WEXITSTATUS (status); return status; }
int do_test (int argc, char *argv[]) { pid_t pid; int fd1; int fd2; int flags; int status; /* We must have - one or four parameters left if called initially + path for ld.so optional + "--library-path" optional + the library path optional + the application name - three parameters left if called through re-execution + file descriptor number which is supposed to be closed + the open file descriptor + the name of the closed desriptor */ if (restart) { if (argc != 4) error (EXIT_FAILURE, 0, "wrong number of arguments (%d)", argc); return handle_restart (argv[1], argv[2], argv[3]); } if (argc != 2 && argc != 5) error (EXIT_FAILURE, 0, "wrong number of arguments (%d)", argc); /* Prepare the test. We are creating two files: one which file descriptor will be marked with FD_CLOEXEC, another which is not. */ /* Open our test files. */ fd1 = mkstemp (name1); if (fd1 == -1) error (EXIT_FAILURE, errno, "cannot open test file `%s'", name1); fd2 = mkstemp (name2); if (fd2 == -1) error (EXIT_FAILURE, errno, "cannot open test file `%s'", name2); /* Set the bit. */ flags = fcntl (fd1, F_GETFD, 0); if (flags < 0) error (EXIT_FAILURE, errno, "cannot get flags"); flags |= FD_CLOEXEC; if (fcntl (fd1, F_SETFD, flags) < 0) error (EXIT_FAILURE, errno, "cannot set flags"); /* Write something in the files. */ if (write (fd1, fd1string, strlen (fd1string)) != strlen (fd1string)) error (EXIT_FAILURE, errno, "cannot write to first file"); if (write (fd2, fd2string, strlen (fd2string)) != strlen (fd2string)) error (EXIT_FAILURE, errno, "cannot write to second file"); /* We want to test the `exec' function. To do this we restart the program with an additional parameter. But first create another process. */ pid = fork (); if (pid == 0) { char fd1name[18]; char fd2name[18]; snprintf (fd1name, sizeof fd1name, "%d", fd1); snprintf (fd2name, sizeof fd2name, "%d", fd2); /* This is the child. Construct the command line. */ if (argc == 5) execl (argv[1], argv[1], argv[2], argv[3], argv[4], "--direct", "--restart", fd1name, fd2name, name1, NULL); else execl (argv[1], argv[1], "--direct", "--restart", fd1name, fd2name, name1, NULL); error (EXIT_FAILURE, errno, "cannot exec"); } else if (pid == (pid_t) -1) error (EXIT_FAILURE, errno, "cannot fork"); /* Wait for the child. */ if (waitpid (pid, &status, 0) != pid) error (EXIT_FAILURE, errno, "wrong child"); if (WTERMSIG (status) != 0) error (EXIT_FAILURE, 0, "Child terminated incorrectly"); status = WEXITSTATUS (status); /* Remove the test files. */ unlink (name1); unlink (name2); return status; }
int do_test (int argc, char *argv[]) { pid_t pid; int fd1; int fd2; int fd3; int fd4; int status; posix_spawn_file_actions_t actions; char fd1name[18]; char fd2name[18]; char fd3name[18]; char fd4name[18]; char *spargv[12]; /* We must have - four parameters left of called initially + path for ld.so + "--library-path" + the library path + the application name - five parameters left if called through re-execution + file descriptor number which is supposed to be closed + the open file descriptor + the newly opened file descriptor + thhe duped second descriptor + the name of the closed descriptor */ if (argc != (restart ? 6 : 5)) error (EXIT_FAILURE, 0, "wrong number of arguments (%d)", argc); if (restart) return handle_restart (argv[1], argv[2], argv[3], argv[4], argv[5]); /* Prepare the test. We are creating two files: one which file descriptor will be marked with FD_CLOEXEC, another which is not. */ /* Open our test files. */ fd1 = mkstemp (name1); if (fd1 == -1) error (EXIT_FAILURE, errno, "cannot open test file `%s'", name1); fd2 = mkstemp (name2); if (fd2 == -1) error (EXIT_FAILURE, errno, "cannot open test file `%s'", name2); fd3 = mkstemp (name3); if (fd3 == -1) error (EXIT_FAILURE, errno, "cannot open test file `%s'", name3); /* Write something in the files. */ if (write (fd1, fd1string, strlen (fd1string)) != strlen (fd1string)) error (EXIT_FAILURE, errno, "cannot write to first file"); if (write (fd2, fd2string, strlen (fd2string)) != strlen (fd2string)) error (EXIT_FAILURE, errno, "cannot write to second file"); if (write (fd3, fd3string, strlen (fd3string)) != strlen (fd3string)) error (EXIT_FAILURE, errno, "cannot write to third file"); /* Close the third file. It'll be opened by `spawn'. */ close (fd3); /* Tell `spawn' what to do. */ if (posix_spawn_file_actions_init (&actions) != 0) error (EXIT_FAILURE, errno, "posix_spawn_file_actions_init"); /* Close `fd1'. */ if (posix_spawn_file_actions_addclose (&actions, fd1) != 0) error (EXIT_FAILURE, errno, "posix_spawn_file_actions_addclose"); /* We want to open the third file. */ if (posix_spawn_file_actions_addopen (&actions, fd3, name3, O_RDONLY, 0666) != 0) error (EXIT_FAILURE, errno, "posix_spawn_file_actions_addopen"); /* We dup the second descriptor. */ fd4 = MAX (2, MAX (fd1, MAX (fd2, fd3))) + 1; if (posix_spawn_file_actions_adddup2 (&actions, fd2, fd4) != 0) error (EXIT_FAILURE, errno, "posix_spawn_file_actions_adddup2"); /* Now spawn the process. */ snprintf (fd1name, sizeof fd1name, "%d", fd1); snprintf (fd2name, sizeof fd2name, "%d", fd2); snprintf (fd3name, sizeof fd3name, "%d", fd3); snprintf (fd4name, sizeof fd4name, "%d", fd4); spargv[0] = argv[1]; spargv[1] = argv[2]; spargv[2] = argv[3]; spargv[3] = argv[4]; spargv[4] = (char *) "--direct"; spargv[5] = (char *) "--restart"; spargv[6] = fd1name; spargv[7] = fd2name; spargv[8] = fd3name; spargv[9] = fd4name; spargv[10] = name1; spargv[11] = NULL; if (posix_spawn (&pid, argv[1], &actions, NULL, spargv, environ) != 0) error (EXIT_FAILURE, errno, "posix_spawn"); /* Cleanup. */ if (posix_spawn_file_actions_destroy (&actions) != 0) error (EXIT_FAILURE, errno, "posix_spawn_file_actions_destroy"); /* Wait for the child. */ if (waitpid (pid, &status, 0) != pid) error (EXIT_FAILURE, errno, "wrong child"); if (WTERMSIG (status) != 0) error (EXIT_FAILURE, 0, "Child terminated incorrectly"); status = WEXITSTATUS (status); /* Remove the test files. */ unlink (name1); unlink (name2); unlink (name3); return status; }
/* * 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; }