~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/powerpc/kernel/signal.c

Version: ~ [ linux-5.3-rc5 ] ~ [ linux-5.2.9 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.67 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.139 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.189 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.189 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.72 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * Common signal handling code for both 32 and 64 bits
  3  *
  4  *    Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration
  5  *    Extracted from signal_32.c and signal_64.c
  6  *
  7  * This file is subject to the terms and conditions of the GNU General
  8  * Public License.  See the file README.legal in the main directory of
  9  * this archive for more details.
 10  */
 11 
 12 #include <linux/tracehook.h>
 13 #include <linux/signal.h>
 14 #include <linux/key.h>
 15 #include <asm/hw_breakpoint.h>
 16 #include <asm/uaccess.h>
 17 #include <asm/unistd.h>
 18 #include <asm/debug.h>
 19 
 20 #include "signal.h"
 21 
 22 /* Log an error when sending an unhandled signal to a process. Controlled
 23  * through debug.exception-trace sysctl.
 24  */
 25 
 26 int show_unhandled_signals = 0;
 27 
 28 /*
 29  * Allocate space for the signal frame
 30  */
 31 void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
 32                            size_t frame_size, int is_32)
 33 {
 34         unsigned long oldsp, newsp;
 35 
 36         /* Default to using normal stack */
 37         oldsp = get_clean_sp(regs, is_32);
 38 
 39         /* Check for alt stack */
 40         if ((ka->sa.sa_flags & SA_ONSTACK) &&
 41             current->sas_ss_size && !on_sig_stack(oldsp))
 42                 oldsp = (current->sas_ss_sp + current->sas_ss_size);
 43 
 44         /* Get aligned frame */
 45         newsp = (oldsp - frame_size) & ~0xFUL;
 46 
 47         /* Check access */
 48         if (!access_ok(VERIFY_WRITE, (void __user *)newsp, oldsp - newsp))
 49                 return NULL;
 50 
 51         return (void __user *)newsp;
 52 }
 53 
 54 
 55 /*
 56  * Restore the user process's signal mask
 57  */
 58 void restore_sigmask(sigset_t *set)
 59 {
 60         sigdelsetmask(set, ~_BLOCKABLE);
 61         set_current_blocked(set);
 62 }
 63 
 64 static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka,
 65                                   int has_handler)
 66 {
 67         unsigned long ret = regs->gpr[3];
 68         int restart = 1;
 69 
 70         /* syscall ? */
 71         if (TRAP(regs) != 0x0C00)
 72                 return;
 73 
 74         /* error signalled ? */
 75         if (!(regs->ccr & 0x10000000))
 76                 return;
 77 
 78         switch (ret) {
 79         case ERESTART_RESTARTBLOCK:
 80         case ERESTARTNOHAND:
 81                 /* ERESTARTNOHAND means that the syscall should only be
 82                  * restarted if there was no handler for the signal, and since
 83                  * we only get here if there is a handler, we dont restart.
 84                  */
 85                 restart = !has_handler;
 86                 break;
 87         case ERESTARTSYS:
 88                 /* ERESTARTSYS means to restart the syscall if there is no
 89                  * handler or the handler was registered with SA_RESTART
 90                  */
 91                 restart = !has_handler || (ka->sa.sa_flags & SA_RESTART) != 0;
 92                 break;
 93         case ERESTARTNOINTR:
 94                 /* ERESTARTNOINTR means that the syscall should be
 95                  * called again after the signal handler returns.
 96                  */
 97                 break;
 98         default:
 99                 return;
100         }
101         if (restart) {
102                 if (ret == ERESTART_RESTARTBLOCK)
103                         regs->gpr[0] = __NR_restart_syscall;
104                 else
105                         regs->gpr[3] = regs->orig_gpr3;
106                 regs->nip -= 4;
107                 regs->result = 0;
108         } else {
109                 regs->result = -EINTR;
110                 regs->gpr[3] = EINTR;
111                 regs->ccr |= 0x10000000;
112         }
113 }
114 
115 static int do_signal(struct pt_regs *regs)
116 {
117         sigset_t *oldset;
118         siginfo_t info;
119         int signr;
120         struct k_sigaction ka;
121         int ret;
122         int is32 = is_32bit_task();
123 
124         if (current_thread_info()->local_flags & _TLF_RESTORE_SIGMASK)
125                 oldset = &current->saved_sigmask;
126         else
127                 oldset = &current->blocked;
128 
129         signr = get_signal_to_deliver(&info, &ka, regs, NULL);
130 
131         /* Is there any syscall restart business here ? */
132         check_syscall_restart(regs, &ka, signr > 0);
133 
134         if (signr <= 0) {
135                 struct thread_info *ti = current_thread_info();
136                 /* No signal to deliver -- put the saved sigmask back */
137                 if (ti->local_flags & _TLF_RESTORE_SIGMASK) {
138                         ti->local_flags &= ~_TLF_RESTORE_SIGMASK;
139                         sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
140                 }
141                 regs->trap = 0;
142                 return 0;               /* no signals delivered */
143         }
144 
145 #ifndef CONFIG_PPC_ADV_DEBUG_REGS
146         /*
147          * Reenable the DABR before delivering the signal to
148          * user space. The DABR will have been cleared if it
149          * triggered inside the kernel.
150          */
151         if (current->thread.dabr)
152                 set_dabr(current->thread.dabr);
153 #endif
154         /* Re-enable the breakpoints for the signal stack */
155         thread_change_pc(current, regs);
156 
157         if (is32) {
158                 if (ka.sa.sa_flags & SA_SIGINFO)
159                         ret = handle_rt_signal32(signr, &ka, &info, oldset,
160                                         regs);
161                 else
162                         ret = handle_signal32(signr, &ka, &info, oldset,
163                                         regs);
164         } else {
165                 ret = handle_rt_signal64(signr, &ka, &info, oldset, regs);
166         }
167 
168         regs->trap = 0;
169         if (ret) {
170                 block_sigmask(&ka, signr);
171 
172                 /*
173                  * A signal was successfully delivered; the saved sigmask is in
174                  * its frame, and we can clear the TLF_RESTORE_SIGMASK flag.
175                  */
176                 current_thread_info()->local_flags &= ~_TLF_RESTORE_SIGMASK;
177 
178                 /*
179                  * Let tracing know that we've done the handler setup.
180                  */
181                 tracehook_signal_handler(signr, &info, &ka, regs,
182                                          test_thread_flag(TIF_SINGLESTEP));
183         }
184 
185         return ret;
186 }
187 
188 void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
189 {
190         if (thread_info_flags & _TIF_SIGPENDING)
191                 do_signal(regs);
192 
193         if (thread_info_flags & _TIF_NOTIFY_RESUME) {
194                 clear_thread_flag(TIF_NOTIFY_RESUME);
195                 tracehook_notify_resume(regs);
196                 if (current->replacement_session_keyring)
197                         key_replace_session_keyring();
198         }
199 }
200 
201 long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
202                 unsigned long r5, unsigned long r6, unsigned long r7,
203                 unsigned long r8, struct pt_regs *regs)
204 {
205         return do_sigaltstack(uss, uoss, regs->gpr[1]);
206 }
207 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp