parisc: fix bug in compat_arch_ptrace
Subsystems (2)
Helge Deller
maintainerPATCH 1/1 parisc: fix bug in compat_arch_ptrace
This commit in 2.6.28-rc:
81e192d6ce303b6792aa38ff35f41a1a7357f23a parisc: convert to generic compat_sys_ptrace
introduced a bug which segfaults the parisc 64bit kernel when stracing 32bit applications:
Kernel Fault: Code=15 regs=00000000bafa42b0 (Addr=00000001baf5ab57)
YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI
PSW: 00001000000001101111111100001011 Tainted: G W
r00-03 000000ff0806ff0b 000000004068edc0 00000000401203f8 00000000fb3e2508 r04-07 0000000040686dc0 00000000baf5a800 fffffffffffffffc fffffffffb3e2508 r08-11 00000000baf5a800 000000000004b068 00000000000402b0 0000000000040d68 r12-15 0000000000042a9c 0000000000040a9c 0000000000040d60 0000000000042e9c r16-19 000000000004b060 000000000004b058 0000000000042d9c ffffffffffffffff r20-23 000000000800000b 0000000000000000 000000000800000b fffffffffb3e2508 r24-27 00000000fffffffc 0000000000000003 00000000fffffffc 0000000040686dc0 r28-31 00000001baf5a7ff 00000000bafa4280 00000000bafa42b0 00000000000001d7
sr00-03 0000000000fca000 0000000000000000 0000000000000000 0000000000fca000 sr04-07 0000000000000000 0000000000000000 0000000000000000 0000000000000000
IASQ: 0000000000000000 0000000000000000 IAOQ: 0000000040120400 0000000040120404
IIR: 4b9a06b0 ISR: 0000000000000000 IOR: 00000001baf5ab57
CPU: 0 CR30: 00000000bafa4000 CR31: 00000000d22344e0
ORIG_R28: 00000000fb3e2248
IAOQ[0]: compat_arch_ptrace+0xb8/0x160
IAOQ[1]: compat_arch_ptrace+0xbc/0x160
RP(r2): compat_arch_ptrace+0xb0/0x160
Backtrace: [<00000000401612ac>] compat_sys_ptrace+0x15c/0x180 [<0000000040104ef8>] syscall_exit+0x0/0x14
Problem is, that compat_arch_ptrace() enters with an addr value of type compat_ulong_t and calls translate_usr_offset() to translate the address offset into a struct pt_regs offset like this:
addr = translate_usr_offset(addr)
This means, any return value of translate_usr_offset() is stored back as compat_ulong_t type into the addr variable.
But since translate_usr_offset() returns -1 for invalid offsets, addr can now get the value 0xffffffff which then fails the next return-value sanity check and thus the kernel tries to access invalid memory:
if (addr < 0) break;
Fix this bug by modifying translate_usr_offset() to take and return values of type compat_ulong_t, and by returning the value "sizeof(struct pt_regs)" as an error indicator. Additionally change the sanity check to check for return values for >= sizeof(struct pt_regs).
This patch survived my compile and run-tests.
arch/parisc/kernel/ptrace.c +5 -5
@@ -183,10 +183,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)* being 64 bit in both cases. */ -static long translate_usr_offset (long offset) +static compat_ulong_t translate_usr_offset (compat_ulong_t offset) {if (offset <0 ) -return -1 ; +return sizeof (struct pt_regs );else if (offset <=32 *4 )/* gr[0..31] */ return offset *2 +4 ;else if (offset <=32 *4 +32 *8 )/* gr[0..31] + fr[0..31] */
@@ -194,7 +194,7 @@ static long translate_usr_offset(long offset)else if (offset <sizeof (struct pt_regs )/2 +32 *4 )return offset *2 +4 -32 *8 ;else -return -1 ; +return sizeof (struct pt_regs ); } long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
@@ -209,7 +209,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,if (addr & (sizeof (compat_uint_t)-1 ))break ; addr =translate_usr_offset (addr); -if (addr <0 ) +if (addr >=sizeof (struct pt_regs ))break ; tmp = *(compat_uint_t *) ((char *)task_regs (child) + addr);
@@ -236,7 +236,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,if (addr & (sizeof (compat_uint_t)-1 ))break ; addr =translate_usr_offset (addr); -if (addr <0 ) +if (addr >=sizeof (struct pt_regs ))break ;if (addr >=PT_FR0 && addr <=PT_FR31 +4 ) {/* Special case, fp regs are 64 bits anyway */
Quoted 7 lines · Helge Deller
This commit in 2.6.28-rc:
81e192d6ce303b6792aa38ff35f41a1a7357f23a parisc: convert to generic compat_sys_ptraceintroduced a bug which segfaults the parisc 64bit kernel when stracing 32bit applications:
Thanks, looks fine.