|
@@ -315,8 +315,8 @@ save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-static void setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
|
|
|
- int signo, sigset_t *oldset)
|
|
|
+static int setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
|
|
|
+ int signo, sigset_t *oldset)
|
|
|
{
|
|
|
struct signal_frame __user *sf;
|
|
|
int sigframe_size, err;
|
|
@@ -384,16 +384,19 @@ static void setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
|
|
|
/* Flush instruction space. */
|
|
|
flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
|
|
|
}
|
|
|
- return;
|
|
|
+ return 0;
|
|
|
|
|
|
sigill_and_return:
|
|
|
do_exit(SIGILL);
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
sigsegv:
|
|
|
force_sigsegv(signo, current);
|
|
|
+ return -EFAULT;
|
|
|
}
|
|
|
|
|
|
-static void setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
|
|
|
- int signo, sigset_t *oldset, siginfo_t *info)
|
|
|
+static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
|
|
|
+ int signo, sigset_t *oldset, siginfo_t *info)
|
|
|
{
|
|
|
struct rt_signal_frame __user *sf;
|
|
|
int sigframe_size;
|
|
@@ -466,22 +469,30 @@ static void setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
|
|
|
/* Flush instruction space. */
|
|
|
flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
|
|
|
}
|
|
|
- return;
|
|
|
+ return 0;
|
|
|
|
|
|
sigill:
|
|
|
do_exit(SIGILL);
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
sigsegv:
|
|
|
force_sigsegv(signo, current);
|
|
|
+ return -EFAULT;
|
|
|
}
|
|
|
|
|
|
-static inline void
|
|
|
+static inline int
|
|
|
handle_signal(unsigned long signr, struct k_sigaction *ka,
|
|
|
siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
|
|
|
{
|
|
|
+ int err;
|
|
|
+
|
|
|
if (ka->sa.sa_flags & SA_SIGINFO)
|
|
|
- setup_rt_frame(ka, regs, signr, oldset, info);
|
|
|
+ err = setup_rt_frame(ka, regs, signr, oldset, info);
|
|
|
else
|
|
|
- setup_frame(ka, regs, signr, oldset);
|
|
|
+ err = setup_frame(ka, regs, signr, oldset);
|
|
|
+
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
|
|
|
spin_lock_irq(¤t->sighand->siglock);
|
|
|
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
|
@@ -489,6 +500,10 @@ handle_signal(unsigned long signr, struct k_sigaction *ka,
|
|
|
sigaddset(¤t->blocked, signr);
|
|
|
recalc_sigpending();
|
|
|
spin_unlock_irq(¤t->sighand->siglock);
|
|
|
+
|
|
|
+ tracehook_signal_handler(signr, info, ka, regs, 0);
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
|
|
@@ -546,17 +561,15 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
|
|
|
if (signr > 0) {
|
|
|
if (restart_syscall)
|
|
|
syscall_restart(orig_i0, regs, &ka.sa);
|
|
|
- handle_signal(signr, &ka, &info, oldset, regs);
|
|
|
-
|
|
|
- /* a signal was successfully delivered; the saved
|
|
|
- * sigmask will have been stored in the signal frame,
|
|
|
- * and will be restored by sigreturn, so we can simply
|
|
|
- * clear the TIF_RESTORE_SIGMASK flag.
|
|
|
- */
|
|
|
- if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
|
|
- clear_thread_flag(TIF_RESTORE_SIGMASK);
|
|
|
-
|
|
|
- tracehook_signal_handler(signr, &info, &ka, regs, 0);
|
|
|
+ if (handle_signal(signr, &ka, &info, oldset, regs) == 0) {
|
|
|
+ /* a signal was successfully delivered; the saved
|
|
|
+ * sigmask will have been stored in the signal frame,
|
|
|
+ * and will be restored by sigreturn, so we can simply
|
|
|
+ * clear the TIF_RESTORE_SIGMASK flag.
|
|
|
+ */
|
|
|
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
|
|
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
|
|
|
+ }
|
|
|
return;
|
|
|
}
|
|
|
if (restart_syscall &&
|