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 <davem@xxxxxxxxxxxxx> 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 <davem@xxxxxxxxxxxxx> Cc: <stable@xxxxxxxxxx> Cc: Arnd Bergmann <arnd@xxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- 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 davem@xxxxxxxxxxxxx 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html