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