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

powerpc/ptrace: Expose HASHKEYR register to ptrace

The HASHKEYR register contains a secret per-process key to enable unique
hashes per process. In general it should not be exposed to userspace
at all and a regular process has no need to know its key.

However, checkpoint restore in userspace (CRIU) functionality requires
that a process be able to set the HASHKEYR of another process, otherwise
existing hashes on the stack would be invalidated by a new random key.

Exposing HASHKEYR in this way also makes it appear in core dumps, which
is a security concern. Multiple threads may share a key, for example
just after a fork() call, where the kernel cannot know if the child is
going to return back along the parent's stack. If such a thread is
coerced into making a core dump, then the HASHKEYR value will be
readable and able to be used against all other threads sharing that key,
effectively undoing any protection offered by hashst/hashchk.

Therefore we expose HASHKEYR to ptrace when CONFIG_CHECKPOINT_RESTORE is
enabled, providing a choice of increased security or migratable ROP
protected processes. This is similar to how ARM exposes its PAC keys.

Signed-off-by: Benjamin Gray <bgray@linux.ibm.com>
Reviewed-by: Russell Currey <ruscur@russell.cc>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://msgid.link/20230616034846.311705-8-bgray@linux.ibm.com

authored by

Benjamin Gray and committed by
Michael Ellerman
97228ca3 884ad5c5

+41
+1
arch/powerpc/include/uapi/asm/elf.h
··· 99 99 #define ELF_NPMU 5 /* includes siar, sdar, sier, mmcr2, mmcr0 */ 100 100 #define ELF_NPKEY 3 /* includes amr, iamr, uamor */ 101 101 #define ELF_NDEXCR 2 /* includes dexcr, hdexcr */ 102 + #define ELF_NHASHKEYR 1 /* includes hashkeyr */ 102 103 103 104 typedef unsigned long elf_greg_t64; 104 105 typedef elf_greg_t64 elf_gregset_t64[ELF_NGREG];
+3
arch/powerpc/kernel/ptrace/ptrace-decl.h
··· 58 58 REGSET_EBB, /* EBB registers */ 59 59 REGSET_PMR, /* Performance Monitor Registers */ 60 60 REGSET_DEXCR, /* DEXCR registers */ 61 + #ifdef CONFIG_CHECKPOINT_RESTORE 62 + REGSET_HASHKEYR, /* HASHKEYR register */ 63 + #endif 61 64 #endif 62 65 #ifdef CONFIG_PPC_MEM_KEYS 63 66 REGSET_PKEY, /* AMR register */
+36
arch/powerpc/kernel/ptrace/ptrace-view.c
··· 483 483 return membuf_store(&to, (u64)lower_32_bits(mfspr(SPRN_HDEXCR_RO))); 484 484 } 485 485 486 + #ifdef CONFIG_CHECKPOINT_RESTORE 487 + static int hashkeyr_active(struct task_struct *target, const struct user_regset *regset) 488 + { 489 + if (!cpu_has_feature(CPU_FTR_ARCH_31)) 490 + return -ENODEV; 491 + 492 + return regset->n; 493 + } 494 + 495 + static int hashkeyr_get(struct task_struct *target, const struct user_regset *regset, 496 + struct membuf to) 497 + { 498 + if (!cpu_has_feature(CPU_FTR_ARCH_31)) 499 + return -ENODEV; 500 + 501 + return membuf_store(&to, target->thread.hashkeyr); 502 + } 503 + 504 + static int hashkeyr_set(struct task_struct *target, const struct user_regset *regset, 505 + unsigned int pos, unsigned int count, const void *kbuf, 506 + const void __user *ubuf) 507 + { 508 + if (!cpu_has_feature(CPU_FTR_ARCH_31)) 509 + return -ENODEV; 510 + 511 + return user_regset_copyin(&pos, &count, &kbuf, &ubuf, &target->thread.hashkeyr, 512 + 0, sizeof(unsigned long)); 513 + } 514 + #endif /* CONFIG_CHECKPOINT_RESTORE */ 486 515 #endif /* CONFIG_PPC_BOOK3S_64 */ 487 516 488 517 #ifdef CONFIG_PPC_MEM_KEYS ··· 678 649 .size = sizeof(u64), .align = sizeof(u64), 679 650 .active = dexcr_active, .regset_get = dexcr_get 680 651 }, 652 + #ifdef CONFIG_CHECKPOINT_RESTORE 653 + [REGSET_HASHKEYR] = { 654 + .core_note_type = NT_PPC_HASHKEYR, .n = ELF_NHASHKEYR, 655 + .size = sizeof(u64), .align = sizeof(u64), 656 + .active = hashkeyr_active, .regset_get = hashkeyr_get, .set = hashkeyr_set 657 + }, 658 + #endif 681 659 #endif 682 660 #ifdef CONFIG_PPC_MEM_KEYS 683 661 [REGSET_PKEY] = {
+1
include/uapi/linux/elf.h
··· 404 404 #define NT_PPC_TM_CDSCR 0x10f /* TM checkpointed Data Stream Control Register */ 405 405 #define NT_PPC_PKEY 0x110 /* Memory Protection Keys registers */ 406 406 #define NT_PPC_DEXCR 0x111 /* PowerPC DEXCR registers */ 407 + #define NT_PPC_HASHKEYR 0x112 /* PowerPC HASHKEYR register */ 407 408 #define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */ 408 409 #define NT_386_IOPERM 0x201 /* x86 io permission bitmap (1=deny) */ 409 410 #define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */