The patch titled
     futex: fix address computation in compat code
has been added to the -mm tree.  Its filename is
     futex-fix-address-computation-in-compat-code.patch

*** Remember to use Documentation/SubmitChecklist when testing your code ***

See http://www.zip.com.au/~akpm/linux/patches/stuff/added-to-mm.txt to find
out what to do about this

------------------------------------------------------
Subject: futex: fix address computation in compat code
From: David Miller <[EMAIL PROTECTED]>

compat_exit_robust_list() computes a pointer to the futex entry in
userspace as follows:

        (void __user *)entry + futex_offset

'entry' is a 'struct robust_list __user *', and
'futex_offset' is a 'compat_long_t' (typically a 's32').

Things explode if the 32-bit sign bit is set in futex_offset.

Type promotion sign extends futex_offset to a 64-bit value before adding it
to 'entry'.

This triggered a problem on sparc64 running 32-bit applications which would
lock up a cpu looping forever in the fault handling for the userspace load
in handle_futex_death().

Compat userspace runs with address masking (wherein the cpu zeros out the
top 32-bits of every effective address given to a memory operation
instruction) so the sparc64 fault handler accounts for this by zero'ing out
the top 32-bits of the fault address too.

Since the kernel properly uses the compat_uptr interfaces, kernel side
accesses to compat userspace work too since they will only use addresses
with the top 32-bit clear.

Because of this compat futex layer bug we get into the following loop
when executing the get_user() load near the top of handle_futex_death():

1) load from address '0xfffffffff7f16bd8', FAULT
2) fault handler clears upper 32-bits, processes fault
   for address '0xf7f16bd8' which succeeds
3) goto #1

I want to thank Bernd Zeimetz, Josip Rodin, and Fabio Massimo Di Nitto
for their tireless efforts helping me track down this bug.

Signed-off-by: David S. Miller <[EMAIL PROTECTED]>
Cc: <[EMAIL PROTECTED]>
Cc: Arnd Bergmann <[EMAIL PROTECTED]>
Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
---

 kernel/futex_compat.c |   27 ++++++++++++++++++++-------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff -puN kernel/futex_compat.c~futex-fix-address-computation-in-compat-code 
kernel/futex_compat.c
--- a/kernel/futex_compat.c~futex-fix-address-computation-in-compat-code
+++ a/kernel/futex_compat.c
@@ -30,6 +30,15 @@ fetch_robust_entry(compat_uptr_t *uentry
        return 0;
 }
 
+static void __user *futex_uaddr(struct robust_list *entry,
+                               compat_long_t futex_offset)
+{
+       compat_uptr_t base = ptr_to_compat(entry);
+       void __user *uaddr = compat_ptr(base + futex_offset);
+
+       return uaddr;
+}
+
 /*
  * Walk curr->robust_list (very carefully, it's a userspace list!)
  * and mark any locks found there dead, and notify any waiters.
@@ -76,11 +85,13 @@ void compat_exit_robust_list(struct task
                 * A pending lock might already be on the list, so
                 * dont process it twice:
                 */
-               if (entry != pending)
-                       if (handle_futex_death((void __user *)entry + 
futex_offset,
-                                               curr, pi))
-                               return;
+               if (entry != pending) {
+                       void __user *uaddr = futex_uaddr(entry,
+                                                        futex_offset);
 
+                       if (handle_futex_death(uaddr, curr, pi))
+                               return;
+               }
                if (rc)
                        return;
                uentry = next_uentry;
@@ -94,9 +105,11 @@ void compat_exit_robust_list(struct task
 
                cond_resched();
        }
-       if (pending)
-               handle_futex_death((void __user *)pending + futex_offset,
-                                  curr, pip);
+       if (pending) {
+               void __user *uaddr = futex_uaddr(pending, futex_offset);
+
+               handle_futex_death(uaddr, curr, pip);
+       }
 }
 
 asmlinkage long
_

Patches currently in -mm which might be from [EMAIL PROTECTED] are

futex-fix-address-computation-in-compat-code.patch
git-net.patch
pfkey-sending-an-sadb_get-responds-with-an-sadb_get.patch
lmc_ioctl-dont-return-with-locks-held-fix.patch
ucc_geth-fix-build-break-introduced-by-commit-09f75cd7bf13720738e6a196cc0107ce9a5bd5a0-checkpatch-fixes.patch
git-sparc64.patch
git-wireless.patch
sunrpc-xprtrdma-transportc-fix-use-after-free.patch
sysctl-fix-token-ring-procname.patch
tty-fix-network-driver-interactions-with-tcget-set-checkpatch-fixes.patch
tty-fix-tty-network-driver-interactions-with-tcget-tcset-calls-x86-fix.patch
fix-versus-precedence-in-various-places.patch
fix-versus-precedence-in-various-places-checkpatch-fixes.patch
genericizing-iova.patch
read_current_time-cleanups.patch
iget-stop-openpromfs-from-using-iget-and.patch
add-cmpxchg_local-to-sparc-move-__cmpxchg-to-systemh.patch
add-cmpxchg_local-to-sparc64.patch

-
To unsubscribe from this list: send the line "unsubscribe mm-commits" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to