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

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

Version: ~ [ linux-5.9-rc6 ] ~ [ linux-5.8.10 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.66 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.146 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.198 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.236 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.236 ] ~ [ 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.85 ] ~ [ 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-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 // SPDX-License-Identifier: GPL-2.0
  2 // Copyright (C) 2005-2017 Andes Technology Corporation
  3 
  4 #include <linux/errno.h>
  5 #include <linux/signal.h>
  6 #include <linux/ptrace.h>
  7 #include <linux/personality.h>
  8 #include <linux/freezer.h>
  9 #include <linux/tracehook.h>
 10 #include <linux/uaccess.h>
 11 
 12 #include <asm/cacheflush.h>
 13 #include <asm/ucontext.h>
 14 #include <asm/unistd.h>
 15 
 16 #include <asm/ptrace.h>
 17 #include <asm/vdso.h>
 18 
 19 struct rt_sigframe {
 20         struct siginfo info;
 21         struct ucontext uc;
 22 };
 23 
 24 static int restore_sigframe(struct pt_regs *regs,
 25                             struct rt_sigframe __user * sf)
 26 {
 27         sigset_t set;
 28         int err;
 29 
 30         err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
 31         if (err == 0) {
 32                 set_current_blocked(&set);
 33         }
 34 
 35         __get_user_error(regs->uregs[0], &sf->uc.uc_mcontext.nds32_r0, err);
 36         __get_user_error(regs->uregs[1], &sf->uc.uc_mcontext.nds32_r1, err);
 37         __get_user_error(regs->uregs[2], &sf->uc.uc_mcontext.nds32_r2, err);
 38         __get_user_error(regs->uregs[3], &sf->uc.uc_mcontext.nds32_r3, err);
 39         __get_user_error(regs->uregs[4], &sf->uc.uc_mcontext.nds32_r4, err);
 40         __get_user_error(regs->uregs[5], &sf->uc.uc_mcontext.nds32_r5, err);
 41         __get_user_error(regs->uregs[6], &sf->uc.uc_mcontext.nds32_r6, err);
 42         __get_user_error(regs->uregs[7], &sf->uc.uc_mcontext.nds32_r7, err);
 43         __get_user_error(regs->uregs[8], &sf->uc.uc_mcontext.nds32_r8, err);
 44         __get_user_error(regs->uregs[9], &sf->uc.uc_mcontext.nds32_r9, err);
 45         __get_user_error(regs->uregs[10], &sf->uc.uc_mcontext.nds32_r10, err);
 46         __get_user_error(regs->uregs[11], &sf->uc.uc_mcontext.nds32_r11, err);
 47         __get_user_error(regs->uregs[12], &sf->uc.uc_mcontext.nds32_r12, err);
 48         __get_user_error(regs->uregs[13], &sf->uc.uc_mcontext.nds32_r13, err);
 49         __get_user_error(regs->uregs[14], &sf->uc.uc_mcontext.nds32_r14, err);
 50         __get_user_error(regs->uregs[15], &sf->uc.uc_mcontext.nds32_r15, err);
 51         __get_user_error(regs->uregs[16], &sf->uc.uc_mcontext.nds32_r16, err);
 52         __get_user_error(regs->uregs[17], &sf->uc.uc_mcontext.nds32_r17, err);
 53         __get_user_error(regs->uregs[18], &sf->uc.uc_mcontext.nds32_r18, err);
 54         __get_user_error(regs->uregs[19], &sf->uc.uc_mcontext.nds32_r19, err);
 55         __get_user_error(regs->uregs[20], &sf->uc.uc_mcontext.nds32_r20, err);
 56         __get_user_error(regs->uregs[21], &sf->uc.uc_mcontext.nds32_r21, err);
 57         __get_user_error(regs->uregs[22], &sf->uc.uc_mcontext.nds32_r22, err);
 58         __get_user_error(regs->uregs[23], &sf->uc.uc_mcontext.nds32_r23, err);
 59         __get_user_error(regs->uregs[24], &sf->uc.uc_mcontext.nds32_r24, err);
 60         __get_user_error(regs->uregs[25], &sf->uc.uc_mcontext.nds32_r25, err);
 61 
 62         __get_user_error(regs->fp, &sf->uc.uc_mcontext.nds32_fp, err);
 63         __get_user_error(regs->gp, &sf->uc.uc_mcontext.nds32_gp, err);
 64         __get_user_error(regs->lp, &sf->uc.uc_mcontext.nds32_lp, err);
 65         __get_user_error(regs->sp, &sf->uc.uc_mcontext.nds32_sp, err);
 66         __get_user_error(regs->ipc, &sf->uc.uc_mcontext.nds32_ipc, err);
 67 #if defined(CONFIG_HWZOL)
 68         __get_user_error(regs->lc, &sf->uc.uc_mcontext.zol.nds32_lc, err);
 69         __get_user_error(regs->le, &sf->uc.uc_mcontext.zol.nds32_le, err);
 70         __get_user_error(regs->lb, &sf->uc.uc_mcontext.zol.nds32_lb, err);
 71 #endif
 72 
 73         /*
 74          * Avoid sys_rt_sigreturn() restarting.
 75          */
 76         forget_syscall(regs);
 77         return err;
 78 }
 79 
 80 asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
 81 {
 82         struct rt_sigframe __user *frame;
 83 
 84         /* Always make any pending restarted system calls return -EINTR */
 85         current->restart_block.fn = do_no_restart_syscall;
 86 
 87         /*
 88          * Since we stacked the signal on a 64-bit boundary,
 89          * then 'sp' should be two-word aligned here.  If it's
 90          * not, then the user is trying to mess with us.
 91          */
 92         if (regs->sp & 7)
 93                 goto badframe;
 94 
 95         frame = (struct rt_sigframe __user *)regs->sp;
 96 
 97         if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 98                 goto badframe;
 99 
100         if (restore_sigframe(regs, frame))
101                 goto badframe;
102 
103         if (restore_altstack(&frame->uc.uc_stack))
104                 goto badframe;
105 
106         return regs->uregs[0];
107 
108 badframe:
109         force_sig(SIGSEGV, current);
110         return 0;
111 }
112 
113 static int
114 setup_sigframe(struct rt_sigframe __user * sf, struct pt_regs *regs,
115                sigset_t * set)
116 {
117         int err = 0;
118 
119         __put_user_error(regs->uregs[0], &sf->uc.uc_mcontext.nds32_r0, err);
120         __put_user_error(regs->uregs[1], &sf->uc.uc_mcontext.nds32_r1, err);
121         __put_user_error(regs->uregs[2], &sf->uc.uc_mcontext.nds32_r2, err);
122         __put_user_error(regs->uregs[3], &sf->uc.uc_mcontext.nds32_r3, err);
123         __put_user_error(regs->uregs[4], &sf->uc.uc_mcontext.nds32_r4, err);
124         __put_user_error(regs->uregs[5], &sf->uc.uc_mcontext.nds32_r5, err);
125         __put_user_error(regs->uregs[6], &sf->uc.uc_mcontext.nds32_r6, err);
126         __put_user_error(regs->uregs[7], &sf->uc.uc_mcontext.nds32_r7, err);
127         __put_user_error(regs->uregs[8], &sf->uc.uc_mcontext.nds32_r8, err);
128         __put_user_error(regs->uregs[9], &sf->uc.uc_mcontext.nds32_r9, err);
129         __put_user_error(regs->uregs[10], &sf->uc.uc_mcontext.nds32_r10, err);
130         __put_user_error(regs->uregs[11], &sf->uc.uc_mcontext.nds32_r11, err);
131         __put_user_error(regs->uregs[12], &sf->uc.uc_mcontext.nds32_r12, err);
132         __put_user_error(regs->uregs[13], &sf->uc.uc_mcontext.nds32_r13, err);
133         __put_user_error(regs->uregs[14], &sf->uc.uc_mcontext.nds32_r14, err);
134         __put_user_error(regs->uregs[15], &sf->uc.uc_mcontext.nds32_r15, err);
135         __put_user_error(regs->uregs[16], &sf->uc.uc_mcontext.nds32_r16, err);
136         __put_user_error(regs->uregs[17], &sf->uc.uc_mcontext.nds32_r17, err);
137         __put_user_error(regs->uregs[18], &sf->uc.uc_mcontext.nds32_r18, err);
138         __put_user_error(regs->uregs[19], &sf->uc.uc_mcontext.nds32_r19, err);
139         __put_user_error(regs->uregs[20], &sf->uc.uc_mcontext.nds32_r20, err);
140 
141         __put_user_error(regs->uregs[21], &sf->uc.uc_mcontext.nds32_r21, err);
142         __put_user_error(regs->uregs[22], &sf->uc.uc_mcontext.nds32_r22, err);
143         __put_user_error(regs->uregs[23], &sf->uc.uc_mcontext.nds32_r23, err);
144         __put_user_error(regs->uregs[24], &sf->uc.uc_mcontext.nds32_r24, err);
145         __put_user_error(regs->uregs[25], &sf->uc.uc_mcontext.nds32_r25, err);
146         __put_user_error(regs->fp, &sf->uc.uc_mcontext.nds32_fp, err);
147         __put_user_error(regs->gp, &sf->uc.uc_mcontext.nds32_gp, err);
148         __put_user_error(regs->lp, &sf->uc.uc_mcontext.nds32_lp, err);
149         __put_user_error(regs->sp, &sf->uc.uc_mcontext.nds32_sp, err);
150         __put_user_error(regs->ipc, &sf->uc.uc_mcontext.nds32_ipc, err);
151 #if defined(CONFIG_HWZOL)
152         __put_user_error(regs->lc, &sf->uc.uc_mcontext.zol.nds32_lc, err);
153         __put_user_error(regs->le, &sf->uc.uc_mcontext.zol.nds32_le, err);
154         __put_user_error(regs->lb, &sf->uc.uc_mcontext.zol.nds32_lb, err);
155 #endif
156 
157         __put_user_error(current->thread.trap_no, &sf->uc.uc_mcontext.trap_no,
158                          err);
159         __put_user_error(current->thread.error_code,
160                          &sf->uc.uc_mcontext.error_code, err);
161         __put_user_error(current->thread.address,
162                          &sf->uc.uc_mcontext.fault_address, err);
163         __put_user_error(set->sig[0], &sf->uc.uc_mcontext.oldmask, err);
164 
165         err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set));
166 
167         return err;
168 }
169 
170 static inline void __user *get_sigframe(struct ksignal *ksig,
171                                         struct pt_regs *regs, int framesize)
172 {
173         unsigned long sp;
174 
175         /* Default to using normal stack */
176         sp = regs->sp;
177 
178         /*
179          * If we are on the alternate signal stack and would overflow it, don't.
180          * Return an always-bogus address instead so we will die with SIGSEGV.
181          */
182         if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize)))
183                 return (void __user __force *)(-1UL);
184 
185         /* This is the X/Open sanctioned signal stack switching. */
186         sp = (sigsp(sp, ksig) - framesize);
187 
188         /*
189          * nds32 mandates 8-byte alignment
190          */
191         sp &= ~0x7UL;
192 
193         return (void __user *)sp;
194 }
195 
196 static int
197 setup_return(struct pt_regs *regs, struct ksignal *ksig, void __user * frame)
198 {
199         unsigned long handler = (unsigned long)ksig->ka.sa.sa_handler;
200         unsigned long retcode;
201 
202         retcode = VDSO_SYMBOL(current->mm->context.vdso, rt_sigtramp);
203         regs->uregs[0] = ksig->sig;
204         regs->sp = (unsigned long)frame;
205         regs->lp = retcode;
206         regs->ipc = handler;
207 
208         return 0;
209 }
210 
211 static int
212 setup_rt_frame(struct ksignal *ksig, sigset_t * set, struct pt_regs *regs)
213 {
214         struct rt_sigframe __user *frame =
215             get_sigframe(ksig, regs, sizeof(*frame));
216         int err = 0;
217 
218         if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
219                 return -EFAULT;
220 
221         __put_user_error(0, &frame->uc.uc_flags, err);
222         __put_user_error(NULL, &frame->uc.uc_link, err);
223 
224         err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
225         err |= setup_sigframe(frame, regs, set);
226         if (err == 0) {
227                 setup_return(regs, ksig, frame);
228                 if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
229                         err |= copy_siginfo_to_user(&frame->info, &ksig->info);
230                         regs->uregs[1] = (unsigned long)&frame->info;
231                         regs->uregs[2] = (unsigned long)&frame->uc;
232                 }
233         }
234         return err;
235 }
236 
237 /*
238  * OK, we're invoking a handler
239  */
240 static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
241 {
242         int ret;
243         sigset_t *oldset = sigmask_to_save();
244 
245         if (in_syscall(regs)) {
246                 /* Avoid additional syscall restarting via ret_slow_syscall. */
247                 forget_syscall(regs);
248 
249                 switch (regs->uregs[0]) {
250                 case -ERESTART_RESTARTBLOCK:
251                 case -ERESTARTNOHAND:
252                         regs->uregs[0] = -EINTR;
253                         break;
254                 case -ERESTARTSYS:
255                         if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
256                                 regs->uregs[0] = -EINTR;
257                                 break;
258                         }
259                 case -ERESTARTNOINTR:
260                         regs->uregs[0] = regs->orig_r0;
261                         regs->ipc -= 4;
262                         break;
263                 }
264         }
265         /*
266          * Set up the stack frame
267          */
268         ret = setup_rt_frame(ksig, oldset, regs);
269 
270         signal_setup_done(ret, ksig, 0);
271 }
272 
273 /*
274  * Note that 'init' is a special process: it doesn't get signals it doesn't
275  * want to handle. Thus you cannot kill init even with a SIGKILL even by
276  * mistake.
277  *
278  * Note that we go through the signals twice: once to check the signals that
279  * the kernel can handle, and then we build all the user-level signal handling
280  * stack-frames in one go after that.
281  */
282 static void do_signal(struct pt_regs *regs)
283 {
284         struct ksignal ksig;
285 
286         if (get_signal(&ksig)) {
287                 handle_signal(&ksig, regs);
288                 return;
289         }
290 
291         /*
292          * If we were from a system call, check for system call restarting...
293          */
294         if (in_syscall(regs)) {
295                 /* Restart the system call - no handlers present */
296 
297                 /* Avoid additional syscall restarting via ret_slow_syscall. */
298                 forget_syscall(regs);
299 
300                 switch (regs->uregs[0]) {
301                 case -ERESTART_RESTARTBLOCK:
302                         regs->uregs[15] = __NR_restart_syscall;
303                 case -ERESTARTNOHAND:
304                 case -ERESTARTSYS:
305                 case -ERESTARTNOINTR:
306                         regs->uregs[0] = regs->orig_r0;
307                         regs->ipc -= 0x4;
308                         break;
309                 }
310         }
311         restore_saved_sigmask();
312 }
313 
314 asmlinkage void
315 do_notify_resume(struct pt_regs *regs, unsigned int thread_flags)
316 {
317         if (thread_flags & _TIF_SIGPENDING)
318                 do_signal(regs);
319 
320         if (thread_flags & _TIF_NOTIFY_RESUME) {
321                 clear_thread_flag(TIF_NOTIFY_RESUME);
322                 tracehook_notify_resume(regs);
323         }
324 }
325 

~ [ 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