1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#include <linux/sched.h>
17#include <linux/mm.h>
18#include <linux/smp.h>
19#include <linux/kernel.h>
20#include <linux/signal.h>
21#include <linux/errno.h>
22#include <linux/wait.h>
23#include <linux/ptrace.h>
24#include <linux/tracehook.h>
25#include <linux/unistd.h>
26#include <linux/stddef.h>
27#include <linux/compat.h>
28#include <linux/elf.h>
29#include <linux/tracehook.h>
30#include <asm/ucontext.h>
31#include <asm/rt_sigframe.h>
32#include <asm/uaccess.h>
33#include <asm/pgalloc.h>
34#include <asm/cacheflush.h>
35#include <asm/asm-offsets.h>
36
37#ifdef CONFIG_COMPAT
38#include "signal32.h"
39#endif
40
41#define DEBUG_SIG 0
42#define DEBUG_SIG_LEVEL 2
43
44#if DEBUG_SIG
45#define DBG(LEVEL, ...) \
46 ((DEBUG_SIG_LEVEL >= LEVEL) \
47 ? printk(__VA_ARGS__) : (void) 0)
48#else
49#define DBG(LEVEL, ...)
50#endif
51
52
53#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
54
55
56
57
58
59
60#define A(__x) ((unsigned long)(__x))
61
62
63
64
65#ifdef CONFIG_64BIT
66#include "sys32.h"
67#endif
68
69
70
71
72
73
74#define INSN_LDI_R25_0 0x34190000
75#define INSN_LDI_R25_1 0x34190002
76#define INSN_LDI_R20 0x3414015a
77#define INSN_BLE_SR2_R0 0xe4008200
78#define INSN_NOP 0x08000240
79
80#define INSN_DIE_HORRIBLY 0x68000ccc
81
82static long
83restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs)
84{
85 long err = 0;
86
87 err |= __copy_from_user(regs->gr, sc->sc_gr, sizeof(regs->gr));
88 err |= __copy_from_user(regs->fr, sc->sc_fr, sizeof(regs->fr));
89 err |= __copy_from_user(regs->iaoq, sc->sc_iaoq, sizeof(regs->iaoq));
90 err |= __copy_from_user(regs->iasq, sc->sc_iasq, sizeof(regs->iasq));
91 err |= __get_user(regs->sar, &sc->sc_sar);
92 DBG(2,"restore_sigcontext: iaoq is 0x%#lx / 0x%#lx\n",
93 regs->iaoq[0],regs->iaoq[1]);
94 DBG(2,"restore_sigcontext: r28 is %ld\n", regs->gr[28]);
95 return err;
96}
97
98void
99sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
100{
101 struct rt_sigframe __user *frame;
102 struct siginfo si;
103 sigset_t set;
104 unsigned long usp = (regs->gr[30] & ~(0x01UL));
105 unsigned long sigframe_size = PARISC_RT_SIGFRAME_SIZE;
106#ifdef CONFIG_64BIT
107 compat_sigset_t compat_set;
108 struct compat_rt_sigframe __user * compat_frame;
109
110 if (is_compat_task())
111 sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
112#endif
113
114
115
116 frame = (struct rt_sigframe __user *)
117 (usp - sigframe_size);
118 DBG(2,"sys_rt_sigreturn: frame is %p\n", frame);
119
120#ifdef CONFIG_64BIT
121 compat_frame = (struct compat_rt_sigframe __user *)frame;
122
123 if (is_compat_task()) {
124 DBG(2,"sys_rt_sigreturn: ELF32 process.\n");
125 if (__copy_from_user(&compat_set, &compat_frame->uc.uc_sigmask, sizeof(compat_set)))
126 goto give_sigsegv;
127 sigset_32to64(&set,&compat_set);
128 } else
129#endif
130 {
131 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
132 goto give_sigsegv;
133 }
134
135 sigdelsetmask(&set, ~_BLOCKABLE);
136 spin_lock_irq(¤t->sighand->siglock);
137 current->blocked = set;
138 recalc_sigpending();
139 spin_unlock_irq(¤t->sighand->siglock);
140
141
142#ifdef CONFIG_64BIT
143 if (is_compat_task()) {
144 DBG(1,"sys_rt_sigreturn: compat_frame->uc.uc_mcontext 0x%p\n",
145 &compat_frame->uc.uc_mcontext);
146
147 if (restore_sigcontext32(&compat_frame->uc.uc_mcontext,
148 &compat_frame->regs, regs))
149 goto give_sigsegv;
150 DBG(1,"sys_rt_sigreturn: usp %#08lx stack 0x%p\n",
151 usp, &compat_frame->uc.uc_stack);
152 if (do_sigaltstack32(&compat_frame->uc.uc_stack, NULL, usp) == -EFAULT)
153 goto give_sigsegv;
154 } else
155#endif
156 {
157 DBG(1,"sys_rt_sigreturn: frame->uc.uc_mcontext 0x%p\n",
158 &frame->uc.uc_mcontext);
159 if (restore_sigcontext(&frame->uc.uc_mcontext, regs))
160 goto give_sigsegv;
161 DBG(1,"sys_rt_sigreturn: usp %#08lx stack 0x%p\n",
162 usp, &frame->uc.uc_stack);
163 if (do_sigaltstack(&frame->uc.uc_stack, NULL, usp) == -EFAULT)
164 goto give_sigsegv;
165 }
166
167
168
169
170
171
172 if (in_syscall)
173 regs->gr[31] = regs->iaoq[0];
174#if DEBUG_SIG
175 DBG(1,"sys_rt_sigreturn: returning to %#lx, DUMPING REGS:\n", regs->iaoq[0]);
176 show_regs(regs);
177#endif
178 return;
179
180give_sigsegv:
181 DBG(1,"sys_rt_sigreturn: Sending SIGSEGV\n");
182 si.si_signo = SIGSEGV;
183 si.si_errno = 0;
184 si.si_code = SI_KERNEL;
185 si.si_pid = task_pid_vnr(current);
186 si.si_uid = current_uid();
187 si.si_addr = &frame->uc;
188 force_sig_info(SIGSEGV, &si, current);
189 return;
190}
191
192
193
194
195
196static inline void __user *
197get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
198{
199
200
201
202 DBG(1,"get_sigframe: ka = %#lx, sp = %#lx, frame_size = %#lx\n",
203 (unsigned long)ka, sp, frame_size);
204
205 if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
206 sp = current->sas_ss_sp;
207
208 DBG(1,"get_sigframe: Returning sp = %#lx\n", (unsigned long)sp);
209 return (void __user *) sp;
210}
211
212static long
213setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, int in_syscall)
214
215{
216 unsigned long flags = 0;
217 long err = 0;
218
219 if (on_sig_stack((unsigned long) sc))
220 flags |= PARISC_SC_FLAG_ONSTACK;
221 if (in_syscall) {
222 flags |= PARISC_SC_FLAG_IN_SYSCALL;
223
224 err |= __put_user(regs->gr[31], &sc->sc_iaoq[0]);
225 err |= __put_user(regs->gr[31]+4, &sc->sc_iaoq[1]);
226 err |= __put_user(regs->sr[3], &sc->sc_iasq[0]);
227 err |= __put_user(regs->sr[3], &sc->sc_iasq[1]);
228 DBG(1,"setup_sigcontext: iaoq %#lx / %#lx (in syscall)\n",
229 regs->gr[31], regs->gr[31]+4);
230 } else {
231 err |= __copy_to_user(sc->sc_iaoq, regs->iaoq, sizeof(regs->iaoq));
232 err |= __copy_to_user(sc->sc_iasq, regs->iasq, sizeof(regs->iasq));
233 DBG(1,"setup_sigcontext: iaoq %#lx / %#lx (not in syscall)\n",
234 regs->iaoq[0], regs->iaoq[1]);
235 }
236
237 err |= __put_user(flags, &sc->sc_flags);
238 err |= __copy_to_user(sc->sc_gr, regs->gr, sizeof(regs->gr));
239 err |= __copy_to_user(sc->sc_fr, regs->fr, sizeof(regs->fr));
240 err |= __put_user(regs->sar, &sc->sc_sar);
241 DBG(1,"setup_sigcontext: r28 is %ld\n", regs->gr[28]);
242
243 return err;
244}
245
246static long
247setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
248 sigset_t *set, struct pt_regs *regs, int in_syscall)
249{
250 struct rt_sigframe __user *frame;
251 unsigned long rp, usp;
252 unsigned long haddr, sigframe_size;
253 int err = 0;
254#ifdef CONFIG_64BIT
255 compat_int_t compat_val;
256 struct compat_rt_sigframe __user * compat_frame;
257 compat_sigset_t compat_set;
258#endif
259
260 usp = (regs->gr[30] & ~(0x01UL));
261
262 frame = get_sigframe(ka, usp, sizeof(*frame));
263
264 DBG(1,"SETUP_RT_FRAME: START\n");
265 DBG(1,"setup_rt_frame: frame %p info %p\n", frame, info);
266
267
268#ifdef CONFIG_64BIT
269
270 compat_frame = (struct compat_rt_sigframe __user *)frame;
271
272 if (is_compat_task()) {
273 DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &compat_frame->info);
274 err |= copy_siginfo_to_user32(&compat_frame->info, info);
275 DBG(1,"SETUP_RT_FRAME: 1\n");
276 compat_val = (compat_int_t)current->sas_ss_sp;
277 err |= __put_user(compat_val, &compat_frame->uc.uc_stack.ss_sp);
278 DBG(1,"SETUP_RT_FRAME: 2\n");
279 compat_val = (compat_int_t)current->sas_ss_size;
280 err |= __put_user(compat_val, &compat_frame->uc.uc_stack.ss_size);
281 DBG(1,"SETUP_RT_FRAME: 3\n");
282 compat_val = sas_ss_flags(regs->gr[30]);
283 err |= __put_user(compat_val, &compat_frame->uc.uc_stack.ss_flags);
284 DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &compat_frame->uc);
285 DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &compat_frame->uc.uc_mcontext);
286 err |= setup_sigcontext32(&compat_frame->uc.uc_mcontext,
287 &compat_frame->regs, regs, in_syscall);
288 sigset_64to32(&compat_set,set);
289 err |= __copy_to_user(&compat_frame->uc.uc_sigmask, &compat_set, sizeof(compat_set));
290 } else
291#endif
292 {
293 DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &frame->info);
294 err |= copy_siginfo_to_user(&frame->info, info);
295 err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
296 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
297 err |= __put_user(sas_ss_flags(regs->gr[30]),
298 &frame->uc.uc_stack.ss_flags);
299 DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &frame->uc);
300 DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &frame->uc.uc_mcontext);
301 err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, in_syscall);
302
303 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
304 }
305
306 if (err)
307 goto give_sigsegv;
308
309
310
311
312
313
314 err |= __put_user(in_syscall ? INSN_LDI_R25_1 : INSN_LDI_R25_0,
315 &frame->tramp[SIGRESTARTBLOCK_TRAMP+0]);
316 err |= __put_user(INSN_LDI_R20,
317 &frame->tramp[SIGRESTARTBLOCK_TRAMP+1]);
318 err |= __put_user(INSN_BLE_SR2_R0,
319 &frame->tramp[SIGRESTARTBLOCK_TRAMP+2]);
320 err |= __put_user(INSN_NOP, &frame->tramp[SIGRESTARTBLOCK_TRAMP+3]);
321
322#if DEBUG_SIG
323
324 {
325 int sid;
326 asm ("mfsp %%sr3,%0" : "=r" (sid));
327 DBG(1,"setup_rt_frame: Flushing 64 bytes at space %#x offset %p\n",
328 sid, frame->tramp);
329 }
330#endif
331
332 flush_user_dcache_range((unsigned long) &frame->tramp[0],
333 (unsigned long) &frame->tramp[TRAMP_SIZE]);
334 flush_user_icache_range((unsigned long) &frame->tramp[0],
335 (unsigned long) &frame->tramp[TRAMP_SIZE]);
336
337
338
339
340
341 rp = (unsigned long) &frame->tramp[SIGRESTARTBLOCK_TRAMP];
342
343 if (err)
344 goto give_sigsegv;
345
346 haddr = A(ka->sa.sa_handler);
347
348#ifdef CONFIG_64BIT
349 if (is_compat_task()) {
350#endif
351 if (haddr & PA_PLABEL_FDESC) {
352 Elf32_Fdesc fdesc;
353 Elf32_Fdesc __user *ufdesc = (Elf32_Fdesc __user *)A(haddr & ~3);
354
355 err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
356
357 if (err)
358 goto give_sigsegv;
359
360 haddr = fdesc.addr;
361 regs->gr[19] = fdesc.gp;
362 }
363#ifdef CONFIG_64BIT
364 } else {
365 Elf64_Fdesc fdesc;
366 Elf64_Fdesc __user *ufdesc = (Elf64_Fdesc __user *)A(haddr & ~3);
367
368 err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
369
370 if (err)
371 goto give_sigsegv;
372
373 haddr = fdesc.addr;
374 regs->gr[19] = fdesc.gp;
375 DBG(1,"setup_rt_frame: 64 bit signal, exe=%#lx, r19=%#lx, in_syscall=%d\n",
376 haddr, regs->gr[19], in_syscall);
377 }
378#endif
379
380
381
382 sigframe_size = PARISC_RT_SIGFRAME_SIZE;
383#ifdef CONFIG_64BIT
384 if (is_compat_task())
385 sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
386#endif
387 if (in_syscall) {
388 regs->gr[31] = haddr;
389#ifdef CONFIG_64BIT
390 if (!test_thread_flag(TIF_32BIT))
391 sigframe_size |= 1;
392#endif
393 } else {
394 unsigned long psw = USER_PSW;
395#ifdef CONFIG_64BIT
396 if (!test_thread_flag(TIF_32BIT))
397 psw |= PSW_W;
398#endif
399
400
401
402
403
404
405
406 if (pa_psw(current)->r) {
407 pa_psw(current)->r = 0;
408 psw |= PSW_R;
409 mtctl(-1, 0);
410 }
411
412 regs->gr[0] = psw;
413 regs->iaoq[0] = haddr | 3;
414 regs->iaoq[1] = regs->iaoq[0] + 4;
415 }
416
417 regs->gr[2] = rp;
418 regs->gr[26] = sig;
419
420#ifdef CONFIG_64BIT
421 if (is_compat_task()) {
422 regs->gr[25] = A(&compat_frame->info);
423 regs->gr[24] = A(&compat_frame->uc);
424 } else
425#endif
426 {
427 regs->gr[25] = A(&frame->info);
428 regs->gr[24] = A(&frame->uc);
429 }
430
431 DBG(1,"setup_rt_frame: making sigreturn frame: %#lx + %#lx = %#lx\n",
432 regs->gr[30], sigframe_size,
433 regs->gr[30] + sigframe_size);
434
435 regs->gr[30] = (A(frame) + sigframe_size);
436
437
438 DBG(1,"setup_rt_frame: sig deliver (%s,%d) frame=0x%p sp=%#lx iaoq=%#lx/%#lx rp=%#lx\n",
439 current->comm, current->pid, frame, regs->gr[30],
440 regs->iaoq[0], regs->iaoq[1], rp);
441
442 return 1;
443
444give_sigsegv:
445 DBG(1,"setup_rt_frame: sending SIGSEGV\n");
446 force_sigsegv(sig, current);
447 return 0;
448}
449
450
451
452
453
454static long
455handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
456 sigset_t *oldset, struct pt_regs *regs, int in_syscall)
457{
458 DBG(1,"handle_signal: sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p\n",
459 sig, ka, info, oldset, regs);
460
461
462 if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall))
463 return 0;
464
465 spin_lock_irq(¤t->sighand->siglock);
466 sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
467 if (!(ka->sa.sa_flags & SA_NODEFER))
468 sigaddset(¤t->blocked,sig);
469 recalc_sigpending();
470 spin_unlock_irq(¤t->sighand->siglock);
471
472 tracehook_signal_handler(sig, info, ka, regs, 0);
473
474 return 1;
475}
476
477static inline void
478syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
479{
480
481 switch (regs->gr[28]) {
482 case -ERESTART_RESTARTBLOCK:
483 current_thread_info()->restart_block.fn =
484 do_no_restart_syscall;
485 case -ERESTARTNOHAND:
486 DBG(1,"ERESTARTNOHAND: returning -EINTR\n");
487 regs->gr[28] = -EINTR;
488 break;
489
490 case -ERESTARTSYS:
491 if (!(ka->sa.sa_flags & SA_RESTART)) {
492 DBG(1,"ERESTARTSYS: putting -EINTR\n");
493 regs->gr[28] = -EINTR;
494 break;
495 }
496
497 case -ERESTARTNOINTR:
498
499
500
501 regs->gr[31] -= 8;
502
503 regs->gr[28] = regs->orig_r28;
504 break;
505 }
506}
507
508static inline void
509insert_restart_trampoline(struct pt_regs *regs)
510{
511 switch(regs->gr[28]) {
512 case -ERESTART_RESTARTBLOCK: {
513
514 unsigned int *usp = (unsigned int *)regs->gr[30];
515
516
517
518
519
520
521
522
523
524
525#ifdef CONFIG_64BIT
526 put_user(regs->gr[31] >> 32, &usp[0]);
527 put_user(regs->gr[31] & 0xffffffff, &usp[1]);
528 put_user(0x0fc010df, &usp[2]);
529#else
530 put_user(regs->gr[31], &usp[0]);
531 put_user(0x0fc0109f, &usp[2]);
532#endif
533 put_user(0xe0008200, &usp[3]);
534 put_user(0x34140000, &usp[4]);
535
536
537
538
539
540
541 flush_user_dcache_range(regs->gr[30], regs->gr[30] + 4);
542 flush_user_icache_range(regs->gr[30], regs->gr[30] + 4);
543
544 regs->gr[31] = regs->gr[30] + 8;
545
546 regs->gr[28] = regs->orig_r28;
547
548 return;
549 }
550 case -ERESTARTNOHAND:
551 case -ERESTARTSYS:
552 case -ERESTARTNOINTR: {
553
554
555
556
557
558 regs->gr[31] -= 8;
559
560 regs->gr[28] = regs->orig_r28;
561
562 return;
563 }
564 default:
565 break;
566 }
567}
568
569
570
571
572
573
574
575
576
577
578
579
580asmlinkage void
581do_signal(struct pt_regs *regs, long in_syscall)
582{
583 siginfo_t info;
584 struct k_sigaction ka;
585 int signr;
586 sigset_t *oldset;
587
588 DBG(1,"\ndo_signal: oldset=0x%p, regs=0x%p, sr7 %#lx, in_syscall=%d\n",
589 oldset, regs, regs->sr[7], in_syscall);
590
591
592
593
594
595
596 if (test_thread_flag(TIF_RESTORE_SIGMASK))
597 oldset = ¤t->saved_sigmask;
598 else
599 oldset = ¤t->blocked;
600
601 DBG(1,"do_signal: oldset %08lx / %08lx\n",
602 oldset->sig[0], oldset->sig[1]);
603
604
605
606 while (1) {
607
608 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
609 DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]);
610
611 if (signr <= 0)
612 break;
613
614
615 if (in_syscall)
616 syscall_restart(regs, &ka);
617
618
619
620
621 if (handle_signal(signr, &info, &ka, oldset,
622 regs, in_syscall)) {
623 DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
624 regs->gr[28]);
625 if (test_thread_flag(TIF_RESTORE_SIGMASK))
626 clear_thread_flag(TIF_RESTORE_SIGMASK);
627 return;
628 }
629 }
630
631
632
633 if (in_syscall)
634 insert_restart_trampoline(regs);
635
636 DBG(1,"do_signal: Exit (not delivered), regs->gr[28] = %ld\n",
637 regs->gr[28]);
638
639 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
640 clear_thread_flag(TIF_RESTORE_SIGMASK);
641 sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
642 }
643
644 return;
645}
646
647void do_notify_resume(struct pt_regs *regs, long in_syscall)
648{
649 if (test_thread_flag(TIF_SIGPENDING) ||
650 test_thread_flag(TIF_RESTORE_SIGMASK))
651 do_signal(regs, in_syscall);
652
653 if (test_thread_flag(TIF_NOTIFY_RESUME)) {
654 clear_thread_flag(TIF_NOTIFY_RESUME);
655 tracehook_notify_resume(regs);
656 if (current->replacement_session_keyring)
657 key_replace_session_keyring();
658 }
659}
660