linux-mips
[Top] [All Lists]

[PATCH] Fix negative buffer overflow in copy_from_user

To: linux-mips@linux-mips.org
Subject: [PATCH] Fix negative buffer overflow in copy_from_user
From: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Date: Mon, 11 Dec 2006 01:16:47 +0900 (JST)
Cc: ralf@linux-mips.org
Original-recipient: rfc822;linux-mips@linux-mips.org
Sender: linux-mips-bounce@linux-mips.org
If we passed an invalid _and_ unaligned source address to
copy_from_user(), the fault handling code miscalculates a length of
uncopied bytes and returns a value greater than original length.  This
also causes an negative buffer overflow and overwrites some bytes just
before the destination kernel buffer.

This can happen "src_unaligned" case in memcpy.S.  If the first load
from source buffer was a LDFIRST/LDREST (L[WD][RL]) instruction, it
raise an exception and the THREAD_BUADDR will be an aligned address so
it will _smaller_ than its real target address.

For all case "src" register is smaller than its target load address
(ie. the offset of load instruction is always greater then zero), and
on the first load instruction "src" is always start of uncopied source
buffer, so we can fix the faulted address using the "src" value.

Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
---
diff --git a/arch/mips/lib/memcpy.S b/arch/mips/lib/memcpy.S
index a526c62..7b21bc9 100644
--- a/arch/mips/lib/memcpy.S
+++ b/arch/mips/lib/memcpy.S
@@ -434,6 +434,12 @@ l_exc:
         nop
        LOAD    t0, THREAD_BUADDR(t0)   # t0 is just past last good address
         nop
+       /* If src was unaligned, t0 might be _smaller_ then src.  Fix it. */
+       slt     t1, t0, src
+       beqz    t1, 1f
+        nop
+       move    t0, src
+1:
        SUB     len, AT, t0             # len number of uncopied bytes
        /*
         * Here's where we rely on src and dst being incremented in tandem,

<Prev in Thread] Current Thread [Next in Thread>