Commit b6f7756d authored by David S. Miller's avatar David S. Miller

[SIGNAL]: Allow more platforms to use generic get_signal_to_deliver.

The few platforms that cannot use the generic
get_signal_to_deliver implementation cannot do
so because they do special things for ptraced
children.  This can be easily avoided and thus
all of the signal handling code duplication can
be eliminated.

This is the first part, which adds a platform hook
right before the parent of the ptraced child is woken.
Data can be passed in via a cookie argument.

The next part will be dealing with platforms
that need to muck with breakpoints in the child
in this same code block.
parent 89ed8e6a
...@@ -619,7 +619,7 @@ do_signal(sigset_t *oldset, struct pt_regs * regs, struct switch_stack * sw, ...@@ -619,7 +619,7 @@ do_signal(sigset_t *oldset, struct pt_regs * regs, struct switch_stack * sw,
if (!oldset) if (!oldset)
oldset = &current->blocked; oldset = &current->blocked;
signr = get_signal_to_deliver(&info, regs); signr = get_signal_to_deliver(&info, regs, NULL);
if (signr > 0) { if (signr > 0) {
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
......
...@@ -560,7 +560,7 @@ int do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs) ...@@ -560,7 +560,7 @@ int do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs)
if (!oldset) if (!oldset)
oldset = &current->blocked; oldset = &current->blocked;
signr = get_signal_to_deliver(&info, regs); signr = get_signal_to_deliver(&info, regs, NULL);
if (signr > 0) { if (signr > 0) {
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal(canrestart, signr, &info, oldset, regs); handle_signal(canrestart, signr, &info, oldset, regs);
......
...@@ -582,7 +582,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) ...@@ -582,7 +582,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
if (!oldset) if (!oldset)
oldset = &current->blocked; oldset = &current->blocked;
signr = get_signal_to_deliver(&info, regs); signr = get_signal_to_deliver(&info, regs, NULL);
if (signr > 0) { if (signr > 0) {
/* Reenable any watchpoints before delivering the /* Reenable any watchpoints before delivering the
* signal to user space. The processor register will * signal to user space. The processor register will
......
...@@ -517,7 +517,7 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) ...@@ -517,7 +517,7 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
restart = 0; restart = 0;
while (1) { while (1) {
int signr = get_signal_to_deliver(&info, &scr->pt); int signr = get_signal_to_deliver(&info, &scr->pt, NULL);
if (signr <= 0) if (signr <= 0)
break; break;
......
...@@ -768,7 +768,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) ...@@ -768,7 +768,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
for (;;) { for (;;) {
int signr; int signr;
signr = get_signal_to_deliver(&info, regs); signr = get_signal_to_deliver(&info, regs, NULL);
if (!signr) if (!signr)
break; break;
......
...@@ -544,7 +544,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) ...@@ -544,7 +544,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
if (!oldset) if (!oldset)
oldset = &current->blocked; oldset = &current->blocked;
signr = get_signal_to_deliver(&info, regs); signr = get_signal_to_deliver(&info, regs, NULL);
if (signr > 0) { if (signr > 0) {
if (regs->regs[0]) if (regs->regs[0])
syscall_restart(regs, ka); syscall_restart(regs, ka);
......
...@@ -602,7 +602,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) ...@@ -602,7 +602,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
if (!oldset) if (!oldset)
oldset = &current->blocked; oldset = &current->blocked;
signr = get_signal_to_deliver(&info, regs); signr = get_signal_to_deliver(&info, regs, NULL);
if (signr > 0) { if (signr > 0) {
if (regs->regs[0]) if (regs->regs[0])
syscall_restart(regs, ka); syscall_restart(regs, ka);
......
...@@ -676,7 +676,7 @@ asmlinkage int do_signal32(sigset_t *oldset, struct pt_regs *regs) ...@@ -676,7 +676,7 @@ asmlinkage int do_signal32(sigset_t *oldset, struct pt_regs *regs)
if (!oldset) if (!oldset)
oldset = &current->blocked; oldset = &current->blocked;
signr = get_signal_to_deliver(&info, regs); signr = get_signal_to_deliver(&info, regs, NULL);
if (signr > 0) { if (signr > 0) {
if (regs->regs[0]) if (regs->regs[0])
syscall_restart(regs, ka); syscall_restart(regs, ka);
......
...@@ -484,7 +484,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) ...@@ -484,7 +484,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
newsp = frame = 0; newsp = frame = 0;
signr = get_signal_to_deliver(&info, regs); signr = get_signal_to_deliver(&info, regs, NULL);
if (signr > 0) { if (signr > 0) {
ka = &current->sig->action[signr-1]; ka = &current->sig->action[signr-1];
if ( (ka->sa.sa_flags & SA_ONSTACK) if ( (ka->sa.sa_flags & SA_ONSTACK)
......
...@@ -551,7 +551,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) ...@@ -551,7 +551,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
newsp = frame = 0; newsp = frame = 0;
signr = get_signal_to_deliver(&info, regs); signr = get_signal_to_deliver(&info, regs, NULL);
if (signr > 0) { if (signr > 0) {
ka = &current->sighand->action[signr-1]; ka = &current->sighand->action[signr-1];
if ((ka->sa.sa_flags & SA_ONSTACK) if ((ka->sa.sa_flags & SA_ONSTACK)
......
...@@ -1063,7 +1063,7 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs) ...@@ -1063,7 +1063,7 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
newsp = frame = 0; newsp = frame = 0;
signr = get_signal_to_deliver(&info, regs); signr = get_signal_to_deliver(&info, regs, NULL);
if (signr > 0) { if (signr > 0) {
ka = &current->sighand->action[signr-1]; ka = &current->sighand->action[signr-1];
if ((ka->sa.sa_flags & SA_ONSTACK) if ((ka->sa.sa_flags & SA_ONSTACK)
......
...@@ -461,7 +461,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) ...@@ -461,7 +461,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
if (!oldset) if (!oldset)
oldset = &current->blocked; oldset = &current->blocked;
signr = get_signal_to_deliver(&info, regs); signr = get_signal_to_deliver(&info, regs, NULL);
if (signr > 0) { if (signr > 0) {
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal(signr, &info, oldset, regs); handle_signal(signr, &info, oldset, regs);
......
...@@ -461,7 +461,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) ...@@ -461,7 +461,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
} }
#endif #endif
signr = get_signal_to_deliver(&info, regs); signr = get_signal_to_deliver(&info, regs, NULL);
if (signr > 0) { if (signr > 0) {
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal(signr, &info, oldset, regs); handle_signal(signr, &info, oldset, regs);
......
...@@ -622,7 +622,7 @@ int do_signal32(struct pt_regs *regs, sigset_t *oldset) ...@@ -622,7 +622,7 @@ int do_signal32(struct pt_regs *regs, sigset_t *oldset)
if (!oldset) if (!oldset)
oldset = &current->blocked; oldset = &current->blocked;
signr = get_signal_to_deliver(&info, regs); signr = get_signal_to_deliver(&info, regs, NULL);
if (signr > 0) { if (signr > 0) {
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal32(signr, &info, oldset, regs); handle_signal32(signr, &info, oldset, regs);
......
...@@ -556,7 +556,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) ...@@ -556,7 +556,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
if (!oldset) if (!oldset)
oldset = &current->blocked; oldset = &current->blocked;
signr = get_signal_to_deliver(&info, regs); signr = get_signal_to_deliver(&info, regs, NULL);
if (signr > 0) { if (signr > 0) {
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal(signr, &info, oldset, regs); handle_signal(signr, &info, oldset, regs);
......
...@@ -1045,8 +1045,9 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, ...@@ -1045,8 +1045,9 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
unsigned long orig_i0, int restart_syscall) unsigned long orig_i0, int restart_syscall)
{ {
struct k_sigaction *ka;
siginfo_t info; siginfo_t info;
struct sparc_deliver_cookie cookie;
int signr;
/* /*
* XXX Disable svr4 signal handling until solaris emulation works. * XXX Disable svr4 signal handling until solaris emulation works.
...@@ -1059,142 +1060,32 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, ...@@ -1059,142 +1060,32 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
int svr4_signal = current->personality == PER_SVR4; int svr4_signal = current->personality == PER_SVR4;
#endif #endif
cookie.restart_syscall = restart_syscall;
cookie.orig_i0 = orig_i0;
if (!oldset) if (!oldset)
oldset = &current->blocked; oldset = &current->blocked;
for (;;) { signr = get_signal_to_deliver(&info, regs, &cookie);
sigset_t *mask = &current->blocked; if (signr > 0) {
unsigned long signr = 0; struct k_sigaction *ka;
spin_lock_irq(&current->sighand->siglock); ka = &current->sighand->action[signr-1];
signr = dequeue_signal(mask, &info); if (cookie.restart_syscall)
spin_unlock_irq(&current->sighand->siglock); syscall_restart(cookie.orig_i0, regs, &ka->sa);
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)) {
/* replay the system call when we are done */
regs->u_regs[UREG_I0] = orig_i0;
regs->pc -= 4;
regs->npc -= 4;
restart_syscall = 0;
}
if (restart_syscall &&
regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
regs->u_regs[UREG_G1] = __NR_restart_syscall;
regs->pc -= 4;
regs->npc -= 4;
restart_syscall = 0;
}
current->exit_code = signr;
set_current_state(TASK_STOPPED);
/* This happens to be SMP safe so no need to
* grab master kernel lock even in this case.
*/
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->parent->pid;
info.si_uid = current->parent->uid;
}
/* If the (new) signal is now blocked, requeue it. */
if (sigismember(&current->blocked, signr)) {
send_sig_info(signr, &info, current);
continue;
}
}
ka = &current->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:
/* The operations performed by
* is_orphaned_pgrp() are protected by
* the tasklist_lock.
*/
if (is_orphaned_pgrp(current->pgrp))
continue;
case SIGSTOP: {
struct signal_struct *sig;
set_current_state(TASK_STOPPED);
current->exit_code = signr;
sig = current->parent->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, exit_code, regs))
exit_code |= 0x80;
/* FALLTHRU */
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, svr4_signal); handle_signal(signr, ka, &info, oldset, regs, svr4_signal);
return 1; return 1;
} }
if (restart_syscall && if (cookie.restart_syscall &&
(regs->u_regs[UREG_I0] == ERESTARTNOHAND || (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
regs->u_regs[UREG_I0] == ERESTARTSYS || regs->u_regs[UREG_I0] == ERESTARTSYS ||
regs->u_regs[UREG_I0] == ERESTARTNOINTR)) { regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
/* replay the system call when we are done */ /* replay the system call when we are done */
regs->u_regs[UREG_I0] = orig_i0; regs->u_regs[UREG_I0] = cookie.orig_i0;
regs->pc -= 4; regs->pc -= 4;
regs->npc -= 4; regs->npc -= 4;
} }
if (restart_syscall && if (cookie.restart_syscall &&
regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
regs->u_regs[UREG_G1] = __NR_restart_syscall; regs->u_regs[UREG_G1] = __NR_restart_syscall;
regs->pc -= 4; regs->pc -= 4;
......
...@@ -603,8 +603,12 @@ static int do_signal(sigset_t *oldset, struct pt_regs * regs, ...@@ -603,8 +603,12 @@ static int do_signal(sigset_t *oldset, struct pt_regs * regs,
unsigned long orig_i0, int restart_syscall) unsigned long orig_i0, int restart_syscall)
{ {
siginfo_t info; siginfo_t info;
struct k_sigaction *ka; struct signal_deliver_cookie cookie;
int signr;
cookie.restart_syscall = restart_syscall;
cookie.orig_i0 = orig_i0;
if (!oldset) if (!oldset)
oldset = &current->blocked; oldset = &current->blocked;
...@@ -612,135 +616,31 @@ static int do_signal(sigset_t *oldset, struct pt_regs * regs, ...@@ -612,135 +616,31 @@ static int do_signal(sigset_t *oldset, struct pt_regs * regs,
if (test_thread_flag(TIF_32BIT)) { if (test_thread_flag(TIF_32BIT)) {
extern int do_signal32(sigset_t *, struct pt_regs *, extern int do_signal32(sigset_t *, struct pt_regs *,
unsigned long, int); unsigned long, int);
return do_signal32(oldset, regs, orig_i0, restart_syscall); return do_signal32(oldset, regs, orig_i0,
cookie.restart_syscall);
} }
#endif #endif
for (;;) {
sigset_t *mask = &current->blocked;
unsigned long signr = 0;
spin_lock_irq(&current->sighand->siglock); signr = get_signal_to_deliver(&info, regs, &cookie);
signr = dequeue_signal(mask, &info); if (signr > 0) {
spin_unlock_irq(&current->sighand->siglock); struct k_sigaction *ka;
if (!signr) ka = &current->sighand->action[signr-1];
break; if (cookie.restart_syscall)
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)) {
/* replay the system call when we are done */
regs->u_regs[UREG_I0] = orig_i0;
regs->tpc -= 4;
regs->tnpc -= 4;
restart_syscall = 0;
}
if (restart_syscall &&
regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
regs->u_regs[UREG_G1] = __NR_restart_syscall;
regs->tpc -= 4;
regs->tnpc -= 4;
restart_syscall = 0;
}
current->exit_code = signr;
set_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->parent->pid;
info.si_uid = current->parent->uid;
}
/* If the (new) signal is now blocked, requeue it. */
if (sigismember(&current->blocked, signr)) {
send_sig_info(signr, &info, current);
continue;
}
}
ka = &current->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: {
struct signal_struct *sig;
set_current_state(TASK_STOPPED);
current->exit_code = signr;
sig = current->parent->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, exit_code, regs))
exit_code |= 0x80;
/* FALLTHRU */
default:
sig_exit(signr, exit_code, &info);
/* NOT REACHED */
}
}
if (restart_syscall)
syscall_restart(orig_i0, regs, &ka->sa); syscall_restart(orig_i0, regs, &ka->sa);
handle_signal(signr, ka, &info, oldset, regs); handle_signal(signr, ka, &info, oldset, regs);
return 1; return 1;
} }
if (restart_syscall && if (cookie.restart_syscall &&
(regs->u_regs[UREG_I0] == ERESTARTNOHAND || (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
regs->u_regs[UREG_I0] == ERESTARTSYS || regs->u_regs[UREG_I0] == ERESTARTSYS ||
regs->u_regs[UREG_I0] == ERESTARTNOINTR)) { regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
/* replay the system call when we are done */ /* replay the system call when we are done */
regs->u_regs[UREG_I0] = orig_i0; regs->u_regs[UREG_I0] = cookie.orig_i0;
regs->tpc -= 4; regs->tpc -= 4;
regs->tnpc -= 4; regs->tnpc -= 4;
} }
if (restart_syscall && if (cookie.restart_syscall &&
regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
regs->u_regs[UREG_G1] = __NR_restart_syscall; regs->u_regs[UREG_G1] = __NR_restart_syscall;
regs->tpc -= 4; regs->tpc -= 4;
......
...@@ -1279,136 +1279,34 @@ static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs ...@@ -1279,136 +1279,34 @@ static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs
int do_signal32(sigset_t *oldset, struct pt_regs * regs, int do_signal32(sigset_t *oldset, struct pt_regs * regs,
unsigned long orig_i0, int restart_syscall) unsigned long orig_i0, int restart_syscall)
{ {
struct k_sigaction *ka;
siginfo_t info; siginfo_t info;
struct signal_deliver_cookie cookie;
int signr;
int svr4_signal = current->personality == PER_SVR4; int svr4_signal = current->personality == PER_SVR4;
for (;;) { cookie.restart_syscall = restart_syscall;
sigset_t *mask = &current->blocked; cookie.orig_i0 = orig_i0;
unsigned long signr = 0;
spin_lock_irq(&current->sighand->siglock);
signr = dequeue_signal(mask, &info);
spin_unlock_irq(&current->sighand->siglock);
if (!signr)
break;
if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) { signr = get_signal_to_deliver(&info, regs, &cookie);
/* Do the syscall restart before we let the debugger if (signr > 0) {
* look at the child registers. struct k_sigaction *ka;
*/
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;
restart_syscall = 0;
}
if (restart_syscall &&
regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
regs->u_regs[UREG_G1] = __NR_restart_syscall;
regs->tpc -= 4;
regs->tnpc -= 4;
restart_syscall = 0;
}
current->exit_code = signr;
set_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->parent->pid;
info.si_uid = current->parent->uid;
}
/* If the (new) signal is now blocked, requeue it. */ ka = &current->sighand->action[signr-1];
if (sigismember(&current->blocked, signr)) { if (cookie.restart_syscall)
send_sig_info(signr, &info, current);
continue;
}
}
ka = &current->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: {
struct signal_struct *sig;
set_current_state(TASK_STOPPED);
current->exit_code = signr;
sig = current->parent->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, exit_code, regs))
exit_code |= 0x80;
/* FALLTHRU */
default:
sig_exit(signr, exit_code, &info);
/* NOT REACHED */
}
}
if (restart_syscall)
syscall_restart32(orig_i0, regs, &ka->sa); syscall_restart32(orig_i0, regs, &ka->sa);
handle_signal32(signr, ka, &info, oldset, regs, svr4_signal); handle_signal32(signr, ka, &info, oldset, regs, svr4_signal);
return 1; return 1;
} }
if (restart_syscall && if (cookie.restart_syscall &&
(regs->u_regs[UREG_I0] == ERESTARTNOHAND || (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
regs->u_regs[UREG_I0] == ERESTARTSYS || regs->u_regs[UREG_I0] == ERESTARTSYS ||
regs->u_regs[UREG_I0] == ERESTARTNOINTR)) { regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
/* replay the system call when we are done */ /* replay the system call when we are done */
regs->u_regs[UREG_I0] = orig_i0; regs->u_regs[UREG_I0] = cookie.orig_i0;
regs->tpc -= 4; regs->tpc -= 4;
regs->tnpc -= 4; regs->tnpc -= 4;
} }
if (restart_syscall && if (cookie.restart_syscall &&
regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
regs->u_regs[UREG_G1] = __NR_restart_syscall; regs->u_regs[UREG_G1] = __NR_restart_syscall;
regs->tpc -= 4; regs->tpc -= 4;
......
...@@ -136,7 +136,7 @@ static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset, int error) ...@@ -136,7 +136,7 @@ static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset, int error)
if (!oldset) if (!oldset)
oldset = &current->blocked; oldset = &current->blocked;
sig = get_signal_to_deliver(&info, regs); sig = get_signal_to_deliver(&info, regs, NULL);
if(sig == 0) if(sig == 0)
return(0); return(0);
......
...@@ -506,7 +506,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) ...@@ -506,7 +506,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
if (!oldset) if (!oldset)
oldset = &current->blocked; oldset = &current->blocked;
signr = get_signal_to_deliver(&info, regs); signr = get_signal_to_deliver(&info, regs, NULL);
if (signr > 0) { if (signr > 0) {
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal(signr, &info, oldset, regs); handle_signal(signr, &info, oldset, regs);
......
...@@ -437,7 +437,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) ...@@ -437,7 +437,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
if (!oldset) if (!oldset)
oldset = &current->blocked; oldset = &current->blocked;
signr = get_signal_to_deliver(&info, regs); signr = get_signal_to_deliver(&info, regs, NULL);
if (signr > 0) { if (signr > 0) {
/* Reenable any watchpoints before delivering the /* Reenable any watchpoints before delivering the
* signal to user space. The processor register will * signal to user space. The processor register will
......
...@@ -186,6 +186,7 @@ struct sigstack { ...@@ -186,6 +186,7 @@ struct sigstack {
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <asm/sigcontext.h> #include <asm/sigcontext.h>
#define ptrace_signal_deliver(regs, cookie) do { } while (0)
#define HAVE_ARCH_SYS_PAUSE #define HAVE_ARCH_SYS_PAUSE
#endif #endif
......
...@@ -181,6 +181,7 @@ typedef struct sigaltstack { ...@@ -181,6 +181,7 @@ typedef struct sigaltstack {
/* here we could define asm-optimized sigaddset, sigdelset etc. operations. /* here we could define asm-optimized sigaddset, sigdelset etc. operations.
* if we don't, generic ones are used from linux/signal.h * if we don't, generic ones are used from linux/signal.h
*/ */
#define ptrace_signal_deliver(regs, cookie) do { } while (0)
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
...@@ -217,6 +217,7 @@ static __inline__ int sigfindinword(unsigned long word) ...@@ -217,6 +217,7 @@ static __inline__ int sigfindinword(unsigned long word)
struct pt_regs; struct pt_regs;
extern int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset)); extern int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset));
#define ptrace_signal_deliver(regs, cookie) do { } while (0)
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
...@@ -166,6 +166,7 @@ struct k_sigaction { ...@@ -166,6 +166,7 @@ struct k_sigaction {
# include <asm/sigcontext.h> # include <asm/sigcontext.h>
#define ptrace_signal_deliver(regs, cookie) do { } while (0)
#define HAVE_ARCH_SYS_PAUSE #define HAVE_ARCH_SYS_PAUSE
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
...@@ -176,6 +176,8 @@ typedef struct sigaltstack { ...@@ -176,6 +176,8 @@ typedef struct sigaltstack {
#include <asm/sigcontext.h> #include <asm/sigcontext.h>
#undef __HAVE_ARCH_SIG_BITOPS #undef __HAVE_ARCH_SIG_BITOPS
#define ptrace_signal_deliver(regs, cookie) do { } while (0)
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* _M68KNOMMU_SIGNAL_H */ #endif /* _M68KNOMMU_SIGNAL_H */
...@@ -169,6 +169,8 @@ typedef struct sigaltstack { ...@@ -169,6 +169,8 @@ typedef struct sigaltstack {
#define _BRK_THREADBP 11 /* For threads, user bp (used by debuggers) */ #define _BRK_THREADBP 11 /* For threads, user bp (used by debuggers) */
#define BRK_MULOVF 1023 /* Multiply overflow */ #define BRK_MULOVF 1023 /* Multiply overflow */
#define ptrace_signal_deliver(regs, cookie) do { } while (0)
#endif /* defined (__KERNEL__) */ #endif /* defined (__KERNEL__) */
#endif /* _ASM_SIGNAL_H */ #endif /* _ASM_SIGNAL_H */
...@@ -168,6 +168,9 @@ typedef struct sigaltstack { ...@@ -168,6 +168,9 @@ typedef struct sigaltstack {
#define BRK_NORLD 10 /* No rld found - not used by Linux/MIPS */ #define BRK_NORLD 10 /* No rld found - not used by Linux/MIPS */
#define _BRK_THREADBP 11 /* For threads, user bp (used by debuggers) */ #define _BRK_THREADBP 11 /* For threads, user bp (used by debuggers) */
#define BRK_MULOVF 1023 /* Multiply overflow */ #define BRK_MULOVF 1023 /* Multiply overflow */
#define ptrace_signal_deliver(regs, cookie) do { } while (0)
#endif /* defined (__KERNEL__) || defined (__USE_MISC) */ #endif /* defined (__KERNEL__) || defined (__USE_MISC) */
#endif /* !defined (_ASM_SIGNAL_H) */ #endif /* !defined (_ASM_SIGNAL_H) */
...@@ -150,6 +150,7 @@ typedef struct sigaltstack { ...@@ -150,6 +150,7 @@ typedef struct sigaltstack {
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <asm/sigcontext.h> #include <asm/sigcontext.h>
#define ptrace_signal_deliver(regs, cookie) do { } while (0)
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif #endif
...@@ -143,4 +143,6 @@ typedef struct sigaltstack { ...@@ -143,4 +143,6 @@ typedef struct sigaltstack {
size_t ss_size; size_t ss_size;
} stack_t; } stack_t;
#define ptrace_signal_deliver(regs, cookie) do { } while (0)
#endif /* _ASMPPC64_SIGNAL_H */ #endif /* _ASMPPC64_SIGNAL_H */
...@@ -175,6 +175,8 @@ struct sigaction { ...@@ -175,6 +175,8 @@ struct sigaction {
#define sa_handler _u._sa_handler #define sa_handler _u._sa_handler
#define sa_sigaction _u._sa_sigaction #define sa_sigaction _u._sa_sigaction
#define ptrace_signal_deliver(regs, cookie) do { } while (0)
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
typedef struct sigaltstack { typedef struct sigaltstack {
......
...@@ -175,6 +175,8 @@ struct sigaction { ...@@ -175,6 +175,8 @@ struct sigaction {
#define sa_handler _u._sa_handler #define sa_handler _u._sa_handler
#define sa_sigaction _u._sa_sigaction #define sa_sigaction _u._sa_sigaction
#define ptrace_signal_deliver(regs, cookie) do { } while (0)
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
typedef struct sigaltstack { typedef struct sigaltstack {
......
...@@ -165,6 +165,8 @@ typedef struct sigaltstack { ...@@ -165,6 +165,8 @@ typedef struct sigaltstack {
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <asm/sigcontext.h> #include <asm/sigcontext.h>
#define ptrace_signal_deliver(regs, cookie) do { } while (0)
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* __ASM_SH_SIGNAL_H */ #endif /* __ASM_SH_SIGNAL_H */
...@@ -216,7 +216,32 @@ typedef struct sigaltstack { ...@@ -216,7 +216,32 @@ typedef struct sigaltstack {
size_t ss_size; size_t ss_size;
} stack_t; } stack_t;
#define HAVE_ARCH_GET_SIGNAL_TO_DELIVER struct sparc_deliver_cookie {
int restart_syscall;
unsigned long orig_i0;
};
#define ptrace_signal_deliver(REGS, COOKIE) \
do { struct sparc_deliver_cookie *cp = (COOKIE); \
if (cp->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] = cp->orig_i0; \
regs->pc -= 4; \
regs->npc -= 4; \
cp->restart_syscall = 0; \
} \
if (cp->restart_syscall && \
regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { \
regs->u_regs[UREG_G1] = __NR_restart_syscall; \
regs->pc -= 4; \
regs->npc -= 4; \
cp->restart_syscall = 0; \
} \
} while (0)
#endif /* !(__ASSEMBLY__) */ #endif /* !(__ASSEMBLY__) */
......
...@@ -245,7 +245,32 @@ typedef struct sigaltstack32 { ...@@ -245,7 +245,32 @@ typedef struct sigaltstack32 {
compat_size_t ss_size; compat_size_t ss_size;
} stack_t32; } stack_t32;
#define HAVE_ARCH_GET_SIGNAL_TO_DELIVER struct signal_deliver_cookie {
int restart_syscall;
unsigned long orig_i0;
};
#define ptrace_signal_deliver(REGS, COOKIE) \
do { struct signal_deliver_cookie *cp = (COOKIE); \
if (cp->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] = cp->orig_i0; \
regs->tpc -= 4; \
regs->tnpc -= 4; \
cp->restart_syscall = 0; \
} \
if (cp->restart_syscall && \
regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { \
regs->u_regs[UREG_G1] = __NR_restart_syscall; \
regs->tpc -= 4; \
regs->tnpc -= 4; \
cp->restart_syscall = 0; \
} \
} while (0)
#define HAVE_ARCH_SYS_PAUSE #define HAVE_ARCH_SYS_PAUSE
#endif #endif
......
...@@ -188,6 +188,8 @@ typedef struct sigaltstack { ...@@ -188,6 +188,8 @@ typedef struct sigaltstack {
#include <asm/sigcontext.h> #include <asm/sigcontext.h>
#undef __HAVE_ARCH_SIG_BITOPS #undef __HAVE_ARCH_SIG_BITOPS
#define ptrace_signal_deliver(regs, cookie) do { } while (0)
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* __V850_SIGNAL_H__ */ #endif /* __V850_SIGNAL_H__ */
...@@ -200,6 +200,9 @@ extern __inline__ int sigfindinword(unsigned long word) ...@@ -200,6 +200,9 @@ extern __inline__ int sigfindinword(unsigned long word)
} }
#endif #endif
#endif #endif
#define ptrace_signal_deliver(regs, cookie) do { } while (0)
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif #endif
...@@ -208,7 +208,7 @@ extern int sigprocmask(int, sigset_t *, sigset_t *); ...@@ -208,7 +208,7 @@ extern int sigprocmask(int, sigset_t *, sigset_t *);
#ifndef HAVE_ARCH_GET_SIGNAL_TO_DELIVER #ifndef HAVE_ARCH_GET_SIGNAL_TO_DELIVER
struct pt_regs; struct pt_regs;
extern int get_signal_to_deliver(siginfo_t *info, struct pt_regs *regs); extern int get_signal_to_deliver(siginfo_t *info, struct pt_regs *regs, void *cookie);
#endif #endif
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
...@@ -1393,7 +1393,7 @@ do_signal_stop(int signr) ...@@ -1393,7 +1393,7 @@ do_signal_stop(int signr)
#ifndef HAVE_ARCH_GET_SIGNAL_TO_DELIVER #ifndef HAVE_ARCH_GET_SIGNAL_TO_DELIVER
int get_signal_to_deliver(siginfo_t *info, struct pt_regs *regs) int get_signal_to_deliver(siginfo_t *info, struct pt_regs *regs, void *cookie)
{ {
sigset_t *mask = &current->blocked; sigset_t *mask = &current->blocked;
...@@ -1431,6 +1431,8 @@ int get_signal_to_deliver(siginfo_t *info, struct pt_regs *regs) ...@@ -1431,6 +1431,8 @@ int get_signal_to_deliver(siginfo_t *info, struct pt_regs *regs)
break; break;
if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) { if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
ptrace_signal_deliver(regs, cookie);
/* /*
* If there is a group stop in progress, * If there is a group stop in progress,
* we must participate in the bookkeeping. * we must participate in the bookkeeping.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment