lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:	Thu, 20 Nov 2008 10:54:09 +0100
From:	Helge Deller <deller@....de>
To:	linux-kernel@...r.kernel.org, akpm@...ux-foundation.org,
	torvalds@...ux-foundation.org,
	Kyle Mc Martin <kyle@...a.kernel.org>,
	linux-parisc@...r.kernel.org, Christoph Hellwig <hch@....de>
Subject: [PATCH] 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.

Signed-off-by: Helge Deller <deller@....de>

diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
index 90904f9..927db36 100644
--- a/arch/parisc/kernel/ptrace.c
+++ b/arch/parisc/kernel/ptrace.c
@@ -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 */
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ