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

Merge branch 'parisc-5.3-2' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux

Pull parisc fixes from Helge Deller:

- Prevent kernel panics by adding proper checking of register values
injected via the ptrace interface

- Wire up the new clone3 syscall

* 'parisc-5.3-2' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux:
parisc: Wire up clone3 syscall
parisc: Avoid kernel panic triggered by invalid kprobe
parisc: Ensure userspace privilege for ptraced processes in regset functions
parisc: Fix kernel panic due invalid values in IAOQ0 or IAOQ1

+26 -12
+1
arch/parisc/include/asm/unistd.h
··· 166 166 #define __ARCH_WANT_SYS_FORK 167 167 #define __ARCH_WANT_SYS_VFORK 168 168 #define __ARCH_WANT_SYS_CLONE 169 + #define __ARCH_WANT_SYS_CLONE3 169 170 #define __ARCH_WANT_COMPAT_SYS_SENDFILE 170 171 171 172 #ifdef CONFIG_64BIT
+1
arch/parisc/kernel/entry.S
··· 1732 1732 .endm 1733 1733 1734 1734 fork_like clone 1735 + fork_like clone3 1735 1736 fork_like fork 1736 1737 fork_like vfork 1737 1738
+3
arch/parisc/kernel/kprobes.c
··· 133 133 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); 134 134 struct kprobe *p = kprobe_running(); 135 135 136 + if (!p) 137 + return 0; 138 + 136 139 if (regs->iaoq[0] != (unsigned long)p->ainsn.insn+4) 137 140 return 0; 138 141
+20 -11
arch/parisc/kernel/ptrace.c
··· 167 167 if ((addr & (sizeof(unsigned long)-1)) || 168 168 addr >= sizeof(struct pt_regs)) 169 169 break; 170 + if (addr == PT_IAOQ0 || addr == PT_IAOQ1) { 171 + data |= 3; /* ensure userspace privilege */ 172 + } 170 173 if ((addr >= PT_GR1 && addr <= PT_GR31) || 171 174 addr == PT_IAOQ0 || addr == PT_IAOQ1 || 172 175 (addr >= PT_FR0 && addr <= PT_FR31 + 4) || ··· 231 228 232 229 static compat_ulong_t translate_usr_offset(compat_ulong_t offset) 233 230 { 234 - if (offset < 0) 235 - return sizeof(struct pt_regs); 236 - else if (offset <= 32*4) /* gr[0..31] */ 237 - return offset * 2 + 4; 238 - else if (offset <= 32*4+32*8) /* gr[0..31] + fr[0..31] */ 239 - return offset + 32*4; 240 - else if (offset < sizeof(struct pt_regs)/2 + 32*4) 241 - return offset * 2 + 4 - 32*8; 231 + compat_ulong_t pos; 232 + 233 + if (offset < 32*4) /* gr[0..31] */ 234 + pos = offset * 2 + 4; 235 + else if (offset < 32*4+32*8) /* fr[0] ... fr[31] */ 236 + pos = (offset - 32*4) + PT_FR0; 237 + else if (offset < sizeof(struct pt_regs)/2 + 32*4) /* sr[0] ... ipsw */ 238 + pos = (offset - 32*4 - 32*8) * 2 + PT_SR0 + 4; 242 239 else 243 - return sizeof(struct pt_regs); 240 + pos = sizeof(struct pt_regs); 241 + 242 + return pos; 244 243 } 245 244 246 245 long compat_arch_ptrace(struct task_struct *child, compat_long_t request, ··· 286 281 addr = translate_usr_offset(addr); 287 282 if (addr >= sizeof(struct pt_regs)) 288 283 break; 284 + if (addr == PT_IAOQ0+4 || addr == PT_IAOQ1+4) { 285 + data |= 3; /* ensure userspace privilege */ 286 + } 289 287 if (addr >= PT_FR0 && addr <= PT_FR31 + 4) { 290 288 /* Special case, fp regs are 64 bits anyway */ 291 - *(__u64 *) ((char *) task_regs(child) + addr) = data; 289 + *(__u32 *) ((char *) task_regs(child) + addr) = data; 292 290 ret = 0; 293 291 } 294 292 else if ((addr >= PT_GR1+4 && addr <= PT_GR31+4) || ··· 504 496 return; 505 497 case RI(iaoq[0]): 506 498 case RI(iaoq[1]): 507 - regs->iaoq[num - RI(iaoq[0])] = val; 499 + /* set 2 lowest bits to ensure userspace privilege: */ 500 + regs->iaoq[num - RI(iaoq[0])] = val | 3; 508 501 return; 509 502 case RI(sar): regs->sar = val; 510 503 return;
+1 -1
arch/parisc/kernel/syscalls/syscall.tbl
··· 431 431 432 common fsmount sys_fsmount 432 432 433 common fspick sys_fspick 433 433 434 common pidfd_open sys_pidfd_open 434 - # 435 reserved for clone3 434 + 435 common clone3 sys_clone3_wrapper