Skip to content

Commit 0e2a5b5

Browse files
committed
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
2 parents da0acd7 + 45800fb commit 0e2a5b5

File tree

5 files changed

+26
-12
lines changed

5 files changed

+26
-12
lines changed

arch/parisc/include/asm/unistd.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \
166166
#define __ARCH_WANT_SYS_FORK
167167
#define __ARCH_WANT_SYS_VFORK
168168
#define __ARCH_WANT_SYS_CLONE
169+
#define __ARCH_WANT_SYS_CLONE3
169170
#define __ARCH_WANT_COMPAT_SYS_SENDFILE
170171

171172
#ifdef CONFIG_64BIT

arch/parisc/kernel/entry.S

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1732,6 +1732,7 @@ ENDPROC_CFI(sys_\name\()_wrapper)
17321732
.endm
17331733

17341734
fork_like clone
1735+
fork_like clone3
17351736
fork_like fork
17361737
fork_like vfork
17371738

arch/parisc/kernel/kprobes.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ int __kprobes parisc_kprobe_ss_handler(struct pt_regs *regs)
133133
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
134134
struct kprobe *p = kprobe_running();
135135

136+
if (!p)
137+
return 0;
138+
136139
if (regs->iaoq[0] != (unsigned long)p->ainsn.insn+4)
137140
return 0;
138141

arch/parisc/kernel/ptrace.c

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,9 @@ long arch_ptrace(struct task_struct *child, long request,
167167
if ((addr & (sizeof(unsigned long)-1)) ||
168168
addr >= sizeof(struct pt_regs))
169169
break;
170+
if (addr == PT_IAOQ0 || addr == PT_IAOQ1) {
171+
data |= 3; /* ensure userspace privilege */
172+
}
170173
if ((addr >= PT_GR1 && addr <= PT_GR31) ||
171174
addr == PT_IAOQ0 || addr == PT_IAOQ1 ||
172175
(addr >= PT_FR0 && addr <= PT_FR31 + 4) ||
@@ -228,16 +231,18 @@ long arch_ptrace(struct task_struct *child, long request,
228231

229232
static compat_ulong_t translate_usr_offset(compat_ulong_t offset)
230233
{
231-
if (offset < 0)
232-
return sizeof(struct pt_regs);
233-
else if (offset <= 32*4) /* gr[0..31] */
234-
return offset * 2 + 4;
235-
else if (offset <= 32*4+32*8) /* gr[0..31] + fr[0..31] */
236-
return offset + 32*4;
237-
else if (offset < sizeof(struct pt_regs)/2 + 32*4)
238-
return offset * 2 + 4 - 32*8;
234+
compat_ulong_t pos;
235+
236+
if (offset < 32*4) /* gr[0..31] */
237+
pos = offset * 2 + 4;
238+
else if (offset < 32*4+32*8) /* fr[0] ... fr[31] */
239+
pos = (offset - 32*4) + PT_FR0;
240+
else if (offset < sizeof(struct pt_regs)/2 + 32*4) /* sr[0] ... ipsw */
241+
pos = (offset - 32*4 - 32*8) * 2 + PT_SR0 + 4;
239242
else
240-
return sizeof(struct pt_regs);
243+
pos = sizeof(struct pt_regs);
244+
245+
return pos;
241246
}
242247

243248
long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
@@ -281,9 +286,12 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
281286
addr = translate_usr_offset(addr);
282287
if (addr >= sizeof(struct pt_regs))
283288
break;
289+
if (addr == PT_IAOQ0+4 || addr == PT_IAOQ1+4) {
290+
data |= 3; /* ensure userspace privilege */
291+
}
284292
if (addr >= PT_FR0 && addr <= PT_FR31 + 4) {
285293
/* Special case, fp regs are 64 bits anyway */
286-
*(__u64 *) ((char *) task_regs(child) + addr) = data;
294+
*(__u32 *) ((char *) task_regs(child) + addr) = data;
287295
ret = 0;
288296
}
289297
else if ((addr >= PT_GR1+4 && addr <= PT_GR31+4) ||
@@ -496,7 +504,8 @@ static void set_reg(struct pt_regs *regs, int num, unsigned long val)
496504
return;
497505
case RI(iaoq[0]):
498506
case RI(iaoq[1]):
499-
regs->iaoq[num - RI(iaoq[0])] = val;
507+
/* set 2 lowest bits to ensure userspace privilege: */
508+
regs->iaoq[num - RI(iaoq[0])] = val | 3;
500509
return;
501510
case RI(sar): regs->sar = val;
502511
return;

arch/parisc/kernel/syscalls/syscall.tbl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,4 +431,4 @@
431431
432 common fsmount sys_fsmount
432432
433 common fspick sys_fspick
433433
434 common pidfd_open sys_pidfd_open
434-
# 435 reserved for clone3
434+
435 common clone3 sys_clone3_wrapper

0 commit comments

Comments
 (0)