Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

parisc: Add ARCH_TRACEHOOK and regset support

By adding TRACEHOOK support we now get a clean user interface to access
registers via PTRACE_GETREGS, PTRACE_SETREGS, PTRACE_GETFPREGS and
PTRACE_SETFPREGS.

The user-visible regset struct user_regs_struct and user_fp_struct are
modelled similiar to x86 and can be accessed via PTRACE_GETREGSET.

Signed-off-by: Helge Deller <deller@gmx.de>

+410 -3
+1
arch/parisc/Kconfig
··· 32 32 select HAVE_DEBUG_STACKOVERFLOW 33 33 select HAVE_ARCH_AUDITSYSCALL 34 34 select HAVE_ARCH_SECCOMP_FILTER 35 + select HAVE_ARCH_TRACEHOOK 35 36 select ARCH_NO_COHERENT_DMA_MMAP 36 37 select CPU_NO_EFFICIENT_FFS 37 38
+48
arch/parisc/include/uapi/asm/ptrace.h
··· 13 13 * N.B. gdb/strace care about the size and offsets within this 14 14 * structure. If you change things, you may break object compatibility 15 15 * for those applications. 16 + * 17 + * Please do NOT use this structure for future programs, but use 18 + * user_regs_struct (see below) instead. 19 + * 20 + * It can be accessed through PTRACE_PEEKUSR/PTRACE_POKEUSR only. 16 21 */ 17 22 18 23 struct pt_regs { ··· 38 33 unsigned long ipsw; /* CR22 */ 39 34 }; 40 35 36 + /** 37 + * struct user_regs_struct - User general purpose registers 38 + * 39 + * This is the user-visible general purpose register state structure 40 + * which is used to define the elf_gregset_t. 41 + * 42 + * It can be accessed through PTRACE_GETREGSET with NT_PRSTATUS 43 + * and through PTRACE_GETREGS. 44 + */ 45 + struct user_regs_struct { 46 + unsigned long gr[32]; /* PSW is in gr[0] */ 47 + unsigned long sr[8]; 48 + unsigned long iaoq[2]; 49 + unsigned long iasq[2]; 50 + unsigned long sar; /* CR11 */ 51 + unsigned long iir; /* CR19 */ 52 + unsigned long isr; /* CR20 */ 53 + unsigned long ior; /* CR21 */ 54 + unsigned long ipsw; /* CR22 */ 55 + unsigned long cr0; 56 + unsigned long cr24, cr25, cr26, cr27, cr28, cr29, cr30, cr31; 57 + unsigned long cr8, cr9, cr12, cr13, cr10, cr15; 58 + unsigned long _pad[80-64]; /* pad to ELF_NGREG (80) */ 59 + }; 60 + 61 + /** 62 + * struct user_fp_struct - User floating point registers 63 + * 64 + * This is the user-visible floating point register state structure. 65 + * It uses the same layout and size as elf_fpregset_t. 66 + * 67 + * It can be accessed through PTRACE_GETREGSET with NT_PRFPREG 68 + * and through PTRACE_GETFPREGS. 69 + */ 70 + struct user_fp_struct { 71 + __u64 fr[32]; 72 + }; 73 + 74 + 41 75 /* 42 76 * The numbers chosen here are somewhat arbitrary but absolutely MUST 43 77 * not overlap with any of the number assigned in <linux/ptrace.h>. ··· 87 43 */ 88 44 #define PTRACE_SINGLEBLOCK 12 /* resume execution until next branch */ 89 45 46 + #define PTRACE_GETREGS 18 47 + #define PTRACE_SETREGS 19 48 + #define PTRACE_GETFPREGS 14 49 + #define PTRACE_SETFPREGS 15 90 50 91 51 #endif /* _UAPI_PARISC_PTRACE_H */
+354 -2
arch/parisc/kernel/ptrace.c
··· 4 4 * Copyright (C) 2000 Hewlett-Packard Co, Linuxcare Inc. 5 5 * Copyright (C) 2000 Matthew Wilcox <matthew@wil.cx> 6 6 * Copyright (C) 2000 David Huggins-Daines <dhd@debian.org> 7 - * Copyright (C) 2008 Helge Deller <deller@gmx.de> 7 + * Copyright (C) 2008-2016 Helge Deller <deller@gmx.de> 8 8 */ 9 9 10 10 #include <linux/kernel.h> 11 11 #include <linux/sched.h> 12 12 #include <linux/mm.h> 13 13 #include <linux/smp.h> 14 + #include <linux/elf.h> 14 15 #include <linux/errno.h> 15 16 #include <linux/ptrace.h> 16 17 #include <linux/tracehook.h> 17 18 #include <linux/user.h> 18 19 #include <linux/personality.h> 20 + #include <linux/regset.h> 19 21 #include <linux/security.h> 20 22 #include <linux/seccomp.h> 21 23 #include <linux/compat.h> ··· 34 32 35 33 #define CREATE_TRACE_POINTS 36 34 #include <trace/events/syscalls.h> 35 + 36 + /* 37 + * These are our native regset flavors. 38 + */ 39 + enum parisc_regset { 40 + REGSET_GENERAL, 41 + REGSET_FP 42 + }; 37 43 38 44 /* 39 45 * Called by kernel/ptrace.c when detaching.. ··· 127 117 long arch_ptrace(struct task_struct *child, long request, 128 118 unsigned long addr, unsigned long data) 129 119 { 120 + unsigned long __user *datap = (unsigned long __user *)data; 130 121 unsigned long tmp; 131 122 long ret = -EIO; 132 123 ··· 140 129 addr >= sizeof(struct pt_regs)) 141 130 break; 142 131 tmp = *(unsigned long *) ((char *) task_regs(child) + addr); 143 - ret = put_user(tmp, (unsigned long __user *) data); 132 + ret = put_user(tmp, datap); 144 133 break; 145 134 146 135 /* Write the word at location addr in the USER area. This will need ··· 178 167 ret = 0; 179 168 } 180 169 break; 170 + 171 + case PTRACE_GETREGS: /* Get all gp regs from the child. */ 172 + return copy_regset_to_user(child, 173 + task_user_regset_view(current), 174 + REGSET_GENERAL, 175 + 0, sizeof(struct user_regs_struct), 176 + datap); 177 + 178 + case PTRACE_SETREGS: /* Set all gp regs in the child. */ 179 + return copy_regset_from_user(child, 180 + task_user_regset_view(current), 181 + REGSET_GENERAL, 182 + 0, sizeof(struct user_regs_struct), 183 + datap); 184 + 185 + case PTRACE_GETFPREGS: /* Get the child FPU state. */ 186 + return copy_regset_to_user(child, 187 + task_user_regset_view(current), 188 + REGSET_FP, 189 + 0, sizeof(struct user_fp_struct), 190 + datap); 191 + 192 + case PTRACE_SETFPREGS: /* Set the child FPU state. */ 193 + return copy_regset_from_user(child, 194 + task_user_regset_view(current), 195 + REGSET_FP, 196 + 0, sizeof(struct user_fp_struct), 197 + datap); 181 198 182 199 default: 183 200 ret = ptrace_request(child, request, addr, data); ··· 364 325 365 326 if (stepping || test_thread_flag(TIF_SYSCALL_TRACE)) 366 327 tracehook_report_syscall_exit(regs, stepping); 328 + } 329 + 330 + 331 + /* 332 + * regset functions. 333 + */ 334 + 335 + static int fpr_get(struct task_struct *target, 336 + const struct user_regset *regset, 337 + unsigned int pos, unsigned int count, 338 + void *kbuf, void __user *ubuf) 339 + { 340 + struct pt_regs *regs = task_regs(target); 341 + __u64 *k = kbuf; 342 + __u64 __user *u = ubuf; 343 + __u64 reg; 344 + 345 + pos /= sizeof(reg); 346 + count /= sizeof(reg); 347 + 348 + if (kbuf) 349 + for (; count > 0 && pos < ELF_NFPREG; --count) 350 + *k++ = regs->fr[pos++]; 351 + else 352 + for (; count > 0 && pos < ELF_NFPREG; --count) 353 + if (__put_user(regs->fr[pos++], u++)) 354 + return -EFAULT; 355 + 356 + kbuf = k; 357 + ubuf = u; 358 + pos *= sizeof(reg); 359 + count *= sizeof(reg); 360 + return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 361 + ELF_NFPREG * sizeof(reg), -1); 362 + } 363 + 364 + static int fpr_set(struct task_struct *target, 365 + const struct user_regset *regset, 366 + unsigned int pos, unsigned int count, 367 + const void *kbuf, const void __user *ubuf) 368 + { 369 + struct pt_regs *regs = task_regs(target); 370 + const __u64 *k = kbuf; 371 + const __u64 __user *u = ubuf; 372 + __u64 reg; 373 + 374 + pos /= sizeof(reg); 375 + count /= sizeof(reg); 376 + 377 + if (kbuf) 378 + for (; count > 0 && pos < ELF_NFPREG; --count) 379 + regs->fr[pos++] = *k++; 380 + else 381 + for (; count > 0 && pos < ELF_NFPREG; --count) { 382 + if (__get_user(reg, u++)) 383 + return -EFAULT; 384 + regs->fr[pos++] = reg; 385 + } 386 + 387 + kbuf = k; 388 + ubuf = u; 389 + pos *= sizeof(reg); 390 + count *= sizeof(reg); 391 + return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 392 + ELF_NFPREG * sizeof(reg), -1); 393 + } 394 + 395 + #define RI(reg) (offsetof(struct user_regs_struct,reg) / sizeof(long)) 396 + 397 + static unsigned long get_reg(struct pt_regs *regs, int num) 398 + { 399 + switch (num) { 400 + case RI(gr[0]) ... RI(gr[31]): return regs->gr[num - RI(gr[0])]; 401 + case RI(sr[0]) ... RI(sr[7]): return regs->sr[num - RI(sr[0])]; 402 + case RI(iasq[0]): return regs->iasq[0]; 403 + case RI(iasq[1]): return regs->iasq[1]; 404 + case RI(iaoq[0]): return regs->iaoq[0]; 405 + case RI(iaoq[1]): return regs->iaoq[1]; 406 + case RI(sar): return regs->sar; 407 + case RI(iir): return regs->iir; 408 + case RI(isr): return regs->isr; 409 + case RI(ior): return regs->ior; 410 + case RI(ipsw): return regs->ipsw; 411 + case RI(cr27): return regs->cr27; 412 + case RI(cr0): return mfctl(0); 413 + case RI(cr24): return mfctl(24); 414 + case RI(cr25): return mfctl(25); 415 + case RI(cr26): return mfctl(26); 416 + case RI(cr28): return mfctl(28); 417 + case RI(cr29): return mfctl(29); 418 + case RI(cr30): return mfctl(30); 419 + case RI(cr31): return mfctl(31); 420 + case RI(cr8): return mfctl(8); 421 + case RI(cr9): return mfctl(9); 422 + case RI(cr12): return mfctl(12); 423 + case RI(cr13): return mfctl(13); 424 + case RI(cr10): return mfctl(10); 425 + case RI(cr15): return mfctl(15); 426 + default: return 0; 427 + } 428 + } 429 + 430 + static void set_reg(struct pt_regs *regs, int num, unsigned long val) 431 + { 432 + switch (num) { 433 + case RI(gr[0]): /* 434 + * PSW is in gr[0]. 435 + * Allow writing to Nullify, Divide-step-correction, 436 + * and carry/borrow bits. 437 + * BEWARE, if you set N, and then single step, it won't 438 + * stop on the nullified instruction. 439 + */ 440 + val &= USER_PSW_BITS; 441 + regs->gr[0] &= ~USER_PSW_BITS; 442 + regs->gr[0] |= val; 443 + return; 444 + case RI(gr[1]) ... RI(gr[31]): 445 + regs->gr[num - RI(gr[0])] = val; 446 + return; 447 + case RI(iaoq[0]): 448 + case RI(iaoq[1]): 449 + regs->iaoq[num - RI(iaoq[0])] = val; 450 + return; 451 + case RI(sar): regs->sar = val; 452 + return; 453 + default: return; 454 + #if 0 455 + /* do not allow to change any of the following registers (yet) */ 456 + case RI(sr[0]) ... RI(sr[7]): return regs->sr[num - RI(sr[0])]; 457 + case RI(iasq[0]): return regs->iasq[0]; 458 + case RI(iasq[1]): return regs->iasq[1]; 459 + case RI(iir): return regs->iir; 460 + case RI(isr): return regs->isr; 461 + case RI(ior): return regs->ior; 462 + case RI(ipsw): return regs->ipsw; 463 + case RI(cr27): return regs->cr27; 464 + case cr0, cr24, cr25, cr26, cr27, cr28, cr29, cr30, cr31; 465 + case cr8, cr9, cr12, cr13, cr10, cr15; 466 + #endif 467 + } 468 + } 469 + 470 + static int gpr_get(struct task_struct *target, 471 + const struct user_regset *regset, 472 + unsigned int pos, unsigned int count, 473 + void *kbuf, void __user *ubuf) 474 + { 475 + struct pt_regs *regs = task_regs(target); 476 + unsigned long *k = kbuf; 477 + unsigned long __user *u = ubuf; 478 + unsigned long reg; 479 + 480 + pos /= sizeof(reg); 481 + count /= sizeof(reg); 482 + 483 + if (kbuf) 484 + for (; count > 0 && pos < ELF_NGREG; --count) 485 + *k++ = get_reg(regs, pos++); 486 + else 487 + for (; count > 0 && pos < ELF_NGREG; --count) 488 + if (__put_user(get_reg(regs, pos++), u++)) 489 + return -EFAULT; 490 + kbuf = k; 491 + ubuf = u; 492 + pos *= sizeof(reg); 493 + count *= sizeof(reg); 494 + return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 495 + ELF_NGREG * sizeof(reg), -1); 496 + } 497 + 498 + static int gpr_set(struct task_struct *target, 499 + const struct user_regset *regset, 500 + unsigned int pos, unsigned int count, 501 + const void *kbuf, const void __user *ubuf) 502 + { 503 + struct pt_regs *regs = task_regs(target); 504 + const unsigned long *k = kbuf; 505 + const unsigned long __user *u = ubuf; 506 + unsigned long reg; 507 + 508 + pos /= sizeof(reg); 509 + count /= sizeof(reg); 510 + 511 + if (kbuf) 512 + for (; count > 0 && pos < ELF_NGREG; --count) 513 + set_reg(regs, pos++, *k++); 514 + else 515 + for (; count > 0 && pos < ELF_NGREG; --count) { 516 + if (__get_user(reg, u++)) 517 + return -EFAULT; 518 + set_reg(regs, pos++, reg); 519 + } 520 + 521 + kbuf = k; 522 + ubuf = u; 523 + pos *= sizeof(reg); 524 + count *= sizeof(reg); 525 + return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 526 + ELF_NGREG * sizeof(reg), -1); 527 + } 528 + 529 + static const struct user_regset native_regsets[] = { 530 + [REGSET_GENERAL] = { 531 + .core_note_type = NT_PRSTATUS, .n = ELF_NGREG, 532 + .size = sizeof(long), .align = sizeof(long), 533 + .get = gpr_get, .set = gpr_set 534 + }, 535 + [REGSET_FP] = { 536 + .core_note_type = NT_PRFPREG, .n = ELF_NFPREG, 537 + .size = sizeof(__u64), .align = sizeof(__u64), 538 + .get = fpr_get, .set = fpr_set 539 + } 540 + }; 541 + 542 + static const struct user_regset_view user_parisc_native_view = { 543 + .name = "parisc", .e_machine = ELF_ARCH, .ei_osabi = ELFOSABI_LINUX, 544 + .regsets = native_regsets, .n = ARRAY_SIZE(native_regsets) 545 + }; 546 + 547 + #ifdef CONFIG_64BIT 548 + #include <linux/compat.h> 549 + 550 + static int gpr32_get(struct task_struct *target, 551 + const struct user_regset *regset, 552 + unsigned int pos, unsigned int count, 553 + void *kbuf, void __user *ubuf) 554 + { 555 + struct pt_regs *regs = task_regs(target); 556 + compat_ulong_t *k = kbuf; 557 + compat_ulong_t __user *u = ubuf; 558 + compat_ulong_t reg; 559 + 560 + pos /= sizeof(reg); 561 + count /= sizeof(reg); 562 + 563 + if (kbuf) 564 + for (; count > 0 && pos < ELF_NGREG; --count) 565 + *k++ = get_reg(regs, pos++); 566 + else 567 + for (; count > 0 && pos < ELF_NGREG; --count) 568 + if (__put_user((compat_ulong_t) get_reg(regs, pos++), u++)) 569 + return -EFAULT; 570 + 571 + kbuf = k; 572 + ubuf = u; 573 + pos *= sizeof(reg); 574 + count *= sizeof(reg); 575 + return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 576 + ELF_NGREG * sizeof(reg), -1); 577 + } 578 + 579 + static int gpr32_set(struct task_struct *target, 580 + const struct user_regset *regset, 581 + unsigned int pos, unsigned int count, 582 + const void *kbuf, const void __user *ubuf) 583 + { 584 + struct pt_regs *regs = task_regs(target); 585 + const compat_ulong_t *k = kbuf; 586 + const compat_ulong_t __user *u = ubuf; 587 + compat_ulong_t reg; 588 + 589 + pos /= sizeof(reg); 590 + count /= sizeof(reg); 591 + 592 + if (kbuf) 593 + for (; count > 0 && pos < ELF_NGREG; --count) 594 + set_reg(regs, pos++, *k++); 595 + else 596 + for (; count > 0 && pos < ELF_NGREG; --count) { 597 + if (__get_user(reg, u++)) 598 + return -EFAULT; 599 + set_reg(regs, pos++, reg); 600 + } 601 + 602 + kbuf = k; 603 + ubuf = u; 604 + pos *= sizeof(reg); 605 + count *= sizeof(reg); 606 + return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 607 + ELF_NGREG * sizeof(reg), -1); 608 + } 609 + 610 + /* 611 + * These are the regset flavors matching the 32bit native set. 612 + */ 613 + static const struct user_regset compat_regsets[] = { 614 + [REGSET_GENERAL] = { 615 + .core_note_type = NT_PRSTATUS, .n = ELF_NGREG, 616 + .size = sizeof(compat_long_t), .align = sizeof(compat_long_t), 617 + .get = gpr32_get, .set = gpr32_set 618 + }, 619 + [REGSET_FP] = { 620 + .core_note_type = NT_PRFPREG, .n = ELF_NFPREG, 621 + .size = sizeof(__u64), .align = sizeof(__u64), 622 + .get = fpr_get, .set = fpr_set 623 + } 624 + }; 625 + 626 + static const struct user_regset_view user_parisc_compat_view = { 627 + .name = "parisc", .e_machine = EM_PARISC, .ei_osabi = ELFOSABI_LINUX, 628 + .regsets = compat_regsets, .n = ARRAY_SIZE(compat_regsets) 629 + }; 630 + #endif /* CONFIG_64BIT */ 631 + 632 + const struct user_regset_view *task_user_regset_view(struct task_struct *task) 633 + { 634 + BUILD_BUG_ON(sizeof(struct user_regs_struct)/sizeof(long) != ELF_NGREG); 635 + BUILD_BUG_ON(sizeof(struct user_fp_struct)/sizeof(__u64) != ELF_NFPREG); 636 + #ifdef CONFIG_64BIT 637 + if (is_compat_task()) 638 + return &user_parisc_compat_view; 639 + #endif 640 + return &user_parisc_native_view; 367 641 }
+7 -1
tools/testing/selftests/seccomp/seccomp_bpf.c
··· 1234 1234 # define ARCH_REGS struct user_pt_regs 1235 1235 # define SYSCALL_NUM regs[8] 1236 1236 # define SYSCALL_RET regs[0] 1237 + #elif defined(__hppa__) 1238 + # define ARCH_REGS struct user_regs_struct 1239 + # define SYSCALL_NUM gr[20] 1240 + # define SYSCALL_RET gr[28] 1237 1241 #elif defined(__powerpc__) 1238 1242 # define ARCH_REGS struct pt_regs 1239 1243 # define SYSCALL_NUM gpr[0] ··· 1307 1303 EXPECT_EQ(0, ret); 1308 1304 1309 1305 #if defined(__x86_64__) || defined(__i386__) || defined(__powerpc__) || \ 1310 - defined(__s390__) 1306 + defined(__s390__) || defined(__hppa__) 1311 1307 { 1312 1308 regs.SYSCALL_NUM = syscall; 1313 1309 } ··· 1509 1505 # define __NR_seccomp 383 1510 1506 # elif defined(__aarch64__) 1511 1507 # define __NR_seccomp 277 1508 + # elif defined(__hppa__) 1509 + # define __NR_seccomp 338 1512 1510 # elif defined(__powerpc__) 1513 1511 # define __NR_seccomp 358 1514 1512 # elif defined(__s390__)