Skip to content
  • Helge Deller's avatar
    parisc: fix bug in compat_arch_ptrace · ed79b86d
    Helge Deller authored
    Commit 81e192d6
    
     ("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
    
    The 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 that 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.
    
    Signed-off-by: default avatarHelge Deller <deller@gmx.de>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    ed79b86d