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_BLE_SR2_R0,
295 &frame->tramp[SIGRESTARTBLOCK_TRAMP+1]);
296 err |= __put_user(INSN_LDI_R20,
297 &frame->tramp[SIGRESTARTBLOCK_TRAMP+2]);
298
299 start = (unsigned long) &frame->tramp[SIGRESTARTBLOCK_TRAMP+0];
300 end = (unsigned long) &frame->tramp[SIGRESTARTBLOCK_TRAMP+3];
301 flush_user_dcache_range_asm(start, end);
302 flush_user_icache_range_asm(start, end);
303
304
305
306
307
308 rp = (unsigned long) &frame->tramp[SIGRESTARTBLOCK_TRAMP];
309
310 if (err)
311 return -EFAULT;
312
313 haddr = A(ksig->ka.sa.sa_handler);
314
315#ifdef CONFIG_64BIT
316 if (is_compat_task()) {
317#endif
318 if (haddr & PA_PLABEL_FDESC) {
319 Elf32_Fdesc fdesc;
320 Elf32_Fdesc __user *ufdesc = (Elf32_Fdesc __user *)A(haddr & ~3);
321
322 err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
323
324 if (err)
325 return -EFAULT;
326
327 haddr = fdesc.addr;
328 regs->gr[19] = fdesc.gp;
329 }
330#ifdef CONFIG_64BIT
331 } else {
332 Elf64_Fdesc fdesc;
333 Elf64_Fdesc __user *ufdesc = (Elf64_Fdesc __user *)A(haddr & ~3);
334
335 err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
336
337 if (err)
338 return -EFAULT;
339
340 haddr = fdesc.addr;
341 regs->gr[19] = fdesc.gp;
342 DBG(1,"setup_rt_frame: 64 bit signal, exe=%#lx, r19=%#lx, in_syscall=%d\n",
343 haddr, regs->gr[19], in_syscall);
344 }
345#endif
346
347
348
349 if (in_syscall) {
350 regs->gr[31] = haddr;
351#ifdef CONFIG_64BIT
352 if (!test_thread_flag(TIF_32BIT))
353 sigframe_size |= 1;
354#endif
355 } else {
356 unsigned long psw = USER_PSW;
357#ifdef CONFIG_64BIT
358 if (!test_thread_flag(TIF_32BIT))
359 psw |= PSW_W;
360#endif
361
362
363
364
365
366
367
368 if (pa_psw(current)->r) {
369 pa_psw(current)->r = 0;
370 psw |= PSW_R;
371 mtctl(-1, 0);
372 }
373
374 regs->gr[0] = psw;
375 regs->iaoq[0] = haddr | 3;
376 regs->iaoq[1] = regs->iaoq[0] + 4;
377 }
378
379 regs->gr[2] = rp;
380 regs->gr[26] = ksig->sig;
381
382#ifdef CONFIG_64BIT
383 if (is_compat_task()) {
384 regs->gr[25] = A(&compat_frame->info);
385 regs->gr[24] = A(&compat_frame->uc);
386 } else
387#endif
388 {
389 regs->gr[25] = A(&frame->info);
390 regs->gr[24] = A(&frame->uc);
391 }
392
393 DBG(1,"setup_rt_frame: making sigreturn frame: %#lx + %#lx = %#lx\n",
394 regs->gr[30], sigframe_size,
395 regs->gr[30] + sigframe_size);
396
397 regs->gr[30] = (A(frame) + sigframe_size);
398
399
400 DBG(1,"setup_rt_frame: sig deliver (%s,%d) frame=0x%p sp=%#lx iaoq=%#lx/%#lx rp=%#lx\n",
401 current->comm, current->pid, frame, regs->gr[30],
402 regs->iaoq[0], regs->iaoq[1], rp);
403
404 return 0;
405}
406
407
408
409
410
411static void
412handle_signal(struct ksignal *ksig, struct pt_regs *regs, int in_syscall)
413{
414 int ret;
415 sigset_t *oldset = sigmask_to_save();
416
417 DBG(1,"handle_signal: sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p\n",
418 ksig->sig, ksig->ka, ksig->info, oldset, regs);
419
420
421 ret = setup_rt_frame(ksig, oldset, regs, in_syscall);
422
423 signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP) ||
424 test_thread_flag(TIF_BLOCKSTEP));
425
426 DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
427 regs->gr[28]);
428}
429
430
431
432
433
434
435static void check_syscallno_in_delay_branch(struct pt_regs *regs)
436{
437 u32 opcode, source_reg;
438 u32 __user *uaddr;
439 int err;
440
441
442
443
444
445
446
447
448
449
450
451
452 regs->gr[31] -= 8;
453
454
455 uaddr = (unsigned int *) ((regs->gr[31] & ~3) + 4);
456 err = get_user(opcode, uaddr);
457 if (err)
458 return;
459
460
461 if ((opcode & 0xffff0000) == 0x34140000)
462 return;
463
464
465 if (opcode == INSN_NOP)
466 return;
467
468
469 if ((opcode & 0xffe0ffff) == 0x08000254) {
470 source_reg = (opcode >> 16) & 31;
471 regs->gr[source_reg] = regs->gr[20];
472 return;
473 }
474
475 pr_warn("syscall restart: %s (pid %d): unexpected opcode 0x%08x\n",
476 current->comm, task_pid_nr(current), opcode);
477}
478
479static inline void
480syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
481{
482 if (regs->orig_r28)
483 return;
484 regs->orig_r28 = 1;
485
486 switch (regs->gr[28]) {
487 case -ERESTART_RESTARTBLOCK:
488 case -ERESTARTNOHAND:
489 DBG(1,"ERESTARTNOHAND: returning -EINTR\n");
490 regs->gr[28] = -EINTR;
491 break;
492 case -ERESTARTSYS:
493 if (!(ka->sa.sa_flags & SA_RESTART)) {
494 DBG(1,"ERESTARTSYS: putting -EINTR\n");
495 regs->gr[28] = -EINTR;
496 break;
497 }
498 fallthrough;
499 case -ERESTARTNOINTR:
500 check_syscallno_in_delay_branch(regs);
501 break;
502 }
503}
504
505static inline void
506insert_restart_trampoline(struct pt_regs *regs)
507{
508 if (regs->orig_r28)
509 return;
510 regs->orig_r28 = 1;
511 switch(regs->gr[28]) {
512 case -ERESTART_RESTARTBLOCK: {
513
514 unsigned int *usp = (unsigned int *)regs->gr[30];
515 unsigned long start = (unsigned long) &usp[2];
516 unsigned long end = (unsigned long) &usp[5];
517 long err = 0;
518
519
520 if (A(&usp[0]) >= user_addr_max() - 5 * sizeof(int))
521 return;
522
523
524
525
526
527
528
529
530
531
532#ifdef CONFIG_64BIT
533 err |= put_user(regs->gr[31] >> 32, &usp[0]);
534 err |= put_user(regs->gr[31] & 0xffffffff, &usp[1]);
535 err |= put_user(0x0fc010df, &usp[2]);
536#else
537 err |= put_user(regs->gr[31], &usp[0]);
538 err |= put_user(0x0fc0109f, &usp[2]);
539#endif
540 err |= put_user(0xe0008200, &usp[3]);
541 err |= put_user(0x34140000, &usp[4]);
542
543 WARN_ON(err);
544
545
546 flush_user_dcache_range_asm(start, end);
547 flush_user_icache_range_asm(start, end);
548
549 regs->gr[31] = regs->gr[30] + 8;
550 return;
551 }
552 case -ERESTARTNOHAND:
553 case -ERESTARTSYS:
554 case -ERESTARTNOINTR:
555 check_syscallno_in_delay_branch(regs);
556 return;
557 default:
558 break;
559 }
560}
561
562
563
564
565
566
567
568
569asmlinkage void
570do_signal(struct pt_regs *regs, long in_syscall)
571{
572 struct ksignal ksig;
573
574 DBG(1,"\ndo_signal: regs=0x%p, sr7 %#lx, in_syscall=%d\n",
575 regs, regs->sr[7], in_syscall);
576
577 if (get_signal(&ksig)) {
578 DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]);
579
580 if (in_syscall)
581 syscall_restart(regs, &ksig.ka);
582
583 handle_signal(&ksig, regs, in_syscall);
584 return;
585 }
586
587
588 if (in_syscall)
589 insert_restart_trampoline(regs);
590
591 DBG(1,"do_signal: Exit (not delivered), regs->gr[28] = %ld\n",
592 regs->gr[28]);
593
594 restore_saved_sigmask();
595}
596
597void do_notify_resume(struct pt_regs *regs, long in_syscall)
598{
599 if (test_thread_flag(TIF_SIGPENDING) ||
600 test_thread_flag(TIF_NOTIFY_SIGNAL))
601 do_signal(regs, in_syscall);
602
603 if (test_thread_flag(TIF_NOTIFY_RESUME))
604 tracehook_notify_resume(regs);
605}
606