LKML Archive on lore.kernel.org help / color / mirror / Atom feed
* futex local DoS on most architectures @ 2008-02-11 13:07 Adrian Bunk 2008-02-11 13:56 ` Mikael Pettersson 2008-02-11 13:59 ` Thomas Gleixner 0 siblings, 2 replies; 9+ messages in thread From: Adrian Bunk @ 2008-02-11 13:07 UTC (permalink / raw) To: Ingo Molnar, Thomas Gleixner Cc: linux-kernel, Riku Voipio, Mikael Pettersson, Lennert Buytenhek, Rusty Russell The issue described in [1] is still present and unfixed (and even the fix there wasn't complete since it didn't cover SMP). Thanks to Riku Voipio for noting that it is still unfixed. cu Adrian [1] http://lkml.org/lkml/2007/8/1/474 ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: futex local DoS on most architectures 2008-02-11 13:07 futex local DoS on most architectures Adrian Bunk @ 2008-02-11 13:56 ` Mikael Pettersson 2008-02-11 13:59 ` Thomas Gleixner 1 sibling, 0 replies; 9+ messages in thread From: Mikael Pettersson @ 2008-02-11 13:56 UTC (permalink / raw) To: Adrian Bunk Cc: Ingo Molnar, Thomas Gleixner, linux-kernel, Riku Voipio, Mikael Pettersson, Lennert Buytenhek, Rusty Russell Adrian Bunk writes: > The issue described in [1] is still present and unfixed (and even the > fix there wasn't complete since it didn't cover SMP). > > Thanks to Riku Voipio for noting that it is still unfixed. > > cu > Adrian > > [1] http://lkml.org/lkml/2007/8/1/474 I think calling it a local DoS may make people take it less seriously. The problem is not related to attacks or malice. It's NORMAL futex usage on the affected architectures that's broken and will throw the kernel into a loop. /Mikael ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: futex local DoS on most architectures 2008-02-11 13:07 futex local DoS on most architectures Adrian Bunk 2008-02-11 13:56 ` Mikael Pettersson @ 2008-02-11 13:59 ` Thomas Gleixner 2008-02-11 14:16 ` Lennert Buytenhek ` (2 more replies) 1 sibling, 3 replies; 9+ messages in thread From: Thomas Gleixner @ 2008-02-11 13:59 UTC (permalink / raw) To: Adrian Bunk Cc: Ingo Molnar, linux-kernel, Riku Voipio, Mikael Pettersson, Lennert Buytenhek, Rusty Russell On Mon, 11 Feb 2008, Adrian Bunk wrote: > The issue described in [1] is still present and unfixed (and even the > fix there wasn't complete since it didn't cover SMP). Damn, this slipped through my attention completely. Hotfix (which can be easily backported) below. > Thanks to Riku Voipio for noting that it is still unfixed. > > cu > Adrian > > [1] http://lkml.org/lkml/2007/8/1/474 --------> Subject: futex: disable PI/robust on archs w/o valid implementation From: Thomas Gleixner <tglx@linutronix.de> We have to disable the complete PI/robust functionality for those archs, which do not implement futex_atomic_cmpxchg_inatomic(). The code in question relies on a valid implementation and does not expect -ENOSYS, which is returned by the stub implementation in asm-generic/futex.h Pointed out by: Mikael Pettersson, Riku Voipio and Adrian Bunk This patch is intended for easy backporting and needs to be cleaned up further for current mainline. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: Ingo Molnar <mingo@elte.hu> --- include/asm-generic/futex.h | 2 ++ kernel/futex.c | 13 +++++++++++++ 2 files changed, 15 insertions(+) Index: linux-2.6/include/asm-generic/futex.h =================================================================== --- linux-2.6.orig/include/asm-generic/futex.h +++ linux-2.6/include/asm-generic/futex.h @@ -55,5 +55,7 @@ futex_atomic_cmpxchg_inatomic(int __user return -ENOSYS; } +#define FUTEX_ATOMIC_CMPXCHG_NOT_IMPLEMENTED + #endif #endif Index: linux-2.6/kernel/futex.c =================================================================== --- linux-2.6.orig/kernel/futex.c +++ linux-2.6/kernel/futex.c @@ -1870,6 +1870,9 @@ asmlinkage long sys_set_robust_list(struct robust_list_head __user *head, size_t len) { +#ifdef FUTEX_ATOMIC_CMPXCHG_NOT_IMPLEMENTED + return -ENOSYS; +#else /* * The kernel knows only one size for now: */ @@ -1879,6 +1882,7 @@ sys_set_robust_list(struct robust_list_h current->robust_list = head; return 0; +#endif } /** @@ -1891,6 +1895,9 @@ asmlinkage long sys_get_robust_list(int pid, struct robust_list_head __user * __user *head_ptr, size_t __user *len_ptr) { +#ifdef FUTEX_ATOMIC_CMPXCHG_NOT_IMPLEMENTED + return -ENOSYS; +#else struct robust_list_head __user *head; unsigned long ret; @@ -1920,6 +1927,7 @@ err_unlock: rcu_read_unlock(); return ret; +#endif } /* @@ -2082,6 +2090,9 @@ long do_futex(u32 __user *uaddr, int op, case FUTEX_WAKE_OP: ret = futex_wake_op(uaddr, fshared, uaddr2, val, val2, val3); break; + +#ifndef FUTEX_ATOMIC_CMPXCHG_NOT_IMPLEMENTED + case FUTEX_LOCK_PI: ret = futex_lock_pi(uaddr, fshared, val, timeout, 0); break; @@ -2091,6 +2102,8 @@ long do_futex(u32 __user *uaddr, int op, case FUTEX_TRYLOCK_PI: ret = futex_lock_pi(uaddr, fshared, 0, timeout, 1); break; +#endif + default: ret = -ENOSYS; } ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: futex local DoS on most architectures 2008-02-11 13:59 ` Thomas Gleixner @ 2008-02-11 14:16 ` Lennert Buytenhek 2008-02-12 12:50 ` Riku Voipio 2008-02-14 21:46 ` Andrew Morton 2 siblings, 0 replies; 9+ messages in thread From: Lennert Buytenhek @ 2008-02-11 14:16 UTC (permalink / raw) To: Thomas Gleixner Cc: Adrian Bunk, Ingo Molnar, linux-kernel, Riku Voipio, Mikael Pettersson, Rusty Russell On Mon, Feb 11, 2008 at 02:59:34PM +0100, Thomas Gleixner wrote: > Subject: futex: disable PI/robust on archs w/o valid implementation > From: Thomas Gleixner <tglx@linutronix.de> > > We have to disable the complete PI/robust functionality for those > archs, which do not implement futex_atomic_cmpxchg_inatomic(). The > code in question relies on a valid implementation and does not expect > -ENOSYS, which is returned by the stub implementation in > asm-generic/futex.h > > Pointed out by: Mikael Pettersson, Riku Voipio and Adrian Bunk FWIW, I reported it originally. > This patch is intended for easy backporting and needs to be cleaned up > further for current mainline. > > Signed-off-by: Thomas Gleixner <tglx@linutronix.de> > Acked-by: Ingo Molnar <mingo@elte.hu> Looks good to me. Thanks. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: futex local DoS on most architectures 2008-02-11 13:59 ` Thomas Gleixner 2008-02-11 14:16 ` Lennert Buytenhek @ 2008-02-12 12:50 ` Riku Voipio 2008-02-14 21:46 ` Andrew Morton 2 siblings, 0 replies; 9+ messages in thread From: Riku Voipio @ 2008-02-12 12:50 UTC (permalink / raw) To: Thomas Gleixner Cc: Adrian Bunk, Ingo Molnar, linux-kernel, Mikael Pettersson, Lennert Buytenhek, Rusty Russell Thomas Gleixner wrote: > We have to disable the complete PI/robust functionality for those > archs, which do not implement futex_atomic_cmpxchg_inatomic(). The > code in question relies on a valid implementation and does not expect > -ENOSYS, which is returned by the stub implementation in > asm-generic/futex.h > > Pointed out by: Mikael Pettersson, Riku Voipio and Adrian Bunk > Original credits for finding this issue belong to Lennert Buytenhek. > This patch is intended for easy backporting and needs to be cleaned up > further for current mainline. > > Signed-off-by: Thomas Gleixner <tglx@linutronix.de> > Acked-by: Ingo Molnar <mingo@elte.hu> Looks good for me and kernel no longer deadlocks with this patch! ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: futex local DoS on most architectures 2008-02-11 13:59 ` Thomas Gleixner 2008-02-11 14:16 ` Lennert Buytenhek 2008-02-12 12:50 ` Riku Voipio @ 2008-02-14 21:46 ` Andrew Morton 2008-02-15 1:19 ` Thomas Gleixner 2 siblings, 1 reply; 9+ messages in thread From: Andrew Morton @ 2008-02-14 21:46 UTC (permalink / raw) To: Thomas Gleixner Cc: adrian.bunk, mingo, linux-kernel, riku.voipio, mikpe, buytenh, rusty, stable On Mon, 11 Feb 2008 14:59:34 +0100 (CET) Thomas Gleixner <tglx@linutronix.de> wrote: > On Mon, 11 Feb 2008, Adrian Bunk wrote: > > > The issue described in [1] is still present and unfixed (and even the > > fix there wasn't complete since it didn't cover SMP). > > Damn, this slipped through my attention completely. Hotfix (which can > be easily backported) below. > > > Thanks to Riku Voipio for noting that it is still unfixed. > > > > cu > > Adrian > > > > [1] http://lkml.org/lkml/2007/8/1/474 > > --------> > > Subject: futex: disable PI/robust on archs w/o valid implementation > From: Thomas Gleixner <tglx@linutronix.de> > > We have to disable the complete PI/robust functionality for those > archs, which do not implement futex_atomic_cmpxchg_inatomic(). The > code in question relies on a valid implementation and does not expect > -ENOSYS, which is returned by the stub implementation in > asm-generic/futex.h > > Pointed out by: Mikael Pettersson, Riku Voipio and Adrian Bunk > > This patch is intended for easy backporting and needs to be cleaned up > further for current mainline. So... I queued up this version with a cc to stable under the assumption that this is the patch which should be applied to 2.6.x.y, but this version is not the one which will go into 2.6.25. Correct? If so: messy. The stable guys might want to wait until they see the real 2.6.25 patch and perhaps prefer to backport that version. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: futex local DoS on most architectures 2008-02-14 21:46 ` Andrew Morton @ 2008-02-15 1:19 ` Thomas Gleixner 2008-02-15 1:23 ` [PATCH 1/2] futex: fix init order Thomas Gleixner 2008-02-15 1:36 ` [PATCH 2/2] futex: runtime enable pi and robust functionality Thomas Gleixner 0 siblings, 2 replies; 9+ messages in thread From: Thomas Gleixner @ 2008-02-15 1:19 UTC (permalink / raw) To: Andrew Morton Cc: adrian.bunk, mingo, linux-kernel, riku.voipio, mikpe, buytenh, rusty, stable On Thu, 14 Feb 2008, Andrew Morton wrote: > > This patch is intended for easy backporting and needs to be cleaned up > > further for current mainline. > > So... > > I queued up this version with a cc to stable under the assumption that this > is the patch which should be applied to 2.6.x.y, but this version is not > the one which will go into 2.6.25. > > Correct? > > If so: messy. The stable guys might want to wait until they see the real > 2.6.25 patch and perhaps prefer to backport that version. Yup. I worked out a sane solution, which allows runtime detection. The compile time solution is not perfect, as there is already arch code which checks cpu features on runtime. Patches follow in separate mail. Thanks, tglx ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/2] futex: fix init order 2008-02-15 1:19 ` Thomas Gleixner @ 2008-02-15 1:23 ` Thomas Gleixner 2008-02-15 1:36 ` [PATCH 2/2] futex: runtime enable pi and robust functionality Thomas Gleixner 1 sibling, 0 replies; 9+ messages in thread From: Thomas Gleixner @ 2008-02-15 1:23 UTC (permalink / raw) To: Andrew Morton Cc: adrian.bunk, mingo, linux-kernel, riku.voipio, mikpe, buytenh, rusty, stable When the futex init code fails to initialize the futex pseudo file system it returns early without initializing the hash queues. Should the boot succeed then a futex syscall which tries to enqueue a waiter on the hashqueue will crash due to the unitilialized plist heads. Initialize the hash queues before the filesystem. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: Ingo Molnar <mingo@elte.hu> --- kernel/futex.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) Index: linux-2.6/kernel/futex.c =================================================================== --- linux-2.6.orig/kernel/futex.c +++ linux-2.6/kernel/futex.c @@ -2145,8 +2145,14 @@ static struct file_system_type futex_fs_ static int __init init(void) { - int i = register_filesystem(&futex_fs_type); + int i; + for (i = 0; i < ARRAY_SIZE(futex_queues); i++) { + plist_head_init(&futex_queues[i].chain, &futex_queues[i].lock); + spin_lock_init(&futex_queues[i].lock); + } + + i = register_filesystem(&futex_fs_type); if (i) return i; @@ -2156,10 +2162,6 @@ static int __init init(void) return PTR_ERR(futex_mnt); } - for (i = 0; i < ARRAY_SIZE(futex_queues); i++) { - plist_head_init(&futex_queues[i].chain, &futex_queues[i].lock); - spin_lock_init(&futex_queues[i].lock); - } return 0; } __initcall(init); ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/2] futex: runtime enable pi and robust functionality 2008-02-15 1:19 ` Thomas Gleixner 2008-02-15 1:23 ` [PATCH 1/2] futex: fix init order Thomas Gleixner @ 2008-02-15 1:36 ` Thomas Gleixner 1 sibling, 0 replies; 9+ messages in thread From: Thomas Gleixner @ 2008-02-15 1:36 UTC (permalink / raw) To: Andrew Morton Cc: adrian.bunk, mingo, linux-kernel, riku.voipio, mikpe, buytenh, rusty, stable Not all architectures implement futex_atomic_cmpxchg_inatomic(). The default implementation returns -ENOSYS, which is currently not handled inside of the futex guts. Futex PI calls and robust list exits with a held futex result in an endless loop in the futex code on architectures which have no support. Fixing up every place where futex_atomic_cmpxchg_inatomic() is called would add a fair amount of extra if/else constructs to the already complex code. It is also not possible to disable the robust feature before user space tries to register robust lists. Compile time disabling is not a good idea either, as there are already architectures with runtime detection of futex_atomic_cmpxchg_inatomic support. Detect the functionality at runtime instead by calling cmpxchg_futex_value_locked() with a NULL pointer from the futex initialization code. This is guaranteed to fail, but the call of futex_atomic_cmpxchg_inatomic() happens with pagefaults disabled. On architectures, which use the asm-generic implementation or have a runtime CPU feature detection, a -ENOSYS return value disables the PI/robust features. On architectures with a working implementation the call returns -EFAULT and the PI/robust features are enabled. The relevant syscalls return -ENOSYS and the robust list exit code is blocked, when the detection fails. Fixes http://lkml.org/lkml/2008/2/11/149 Originally reported by: Lennart Buytenhek Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: Ingo Molnar <mingo@elte.hu> Cc: stable@kernel.org --- include/linux/futex.h | 1 + kernel/futex.c | 38 ++++++++++++++++++++++++++++++++++---- kernel/futex_compat.c | 9 +++++++++ 3 files changed, 44 insertions(+), 4 deletions(-) Index: linux-2.6/include/linux/futex.h =================================================================== --- linux-2.6.orig/include/linux/futex.h +++ linux-2.6/include/linux/futex.h @@ -167,6 +167,7 @@ union futex_key { #ifdef CONFIG_FUTEX extern void exit_robust_list(struct task_struct *curr); extern void exit_pi_state_list(struct task_struct *curr); +extern int futex_cmpxchg_enabled; #else static inline void exit_robust_list(struct task_struct *curr) { Index: linux-2.6/kernel/futex.c =================================================================== --- linux-2.6.orig/kernel/futex.c +++ linux-2.6/kernel/futex.c @@ -60,6 +60,8 @@ #include "rtmutex_common.h" +int __read_mostly futex_cmpxchg_enabled; + #define FUTEX_HASHBITS (CONFIG_BASE_SMALL ? 4 : 8) /* @@ -469,6 +471,8 @@ void exit_pi_state_list(struct task_stru struct futex_hash_bucket *hb; union futex_key key; + if (!futex_cmpxchg_enabled) + return; /* * We are a ZOMBIE and nobody can enqueue itself on * pi_state_list anymore, but we have to be careful @@ -1870,6 +1874,8 @@ asmlinkage long sys_set_robust_list(struct robust_list_head __user *head, size_t len) { + if (!futex_cmpxchg_enabled) + return -ENOSYS; /* * The kernel knows only one size for now: */ @@ -1894,6 +1900,9 @@ sys_get_robust_list(int pid, struct robu struct robust_list_head __user *head; unsigned long ret; + if (!futex_cmpxchg_enabled) + return -ENOSYS; + if (!pid) head = current->robust_list; else { @@ -1997,6 +2006,9 @@ void exit_robust_list(struct task_struct unsigned long futex_offset; int rc; + if (!futex_cmpxchg_enabled) + return; + /* * Fetch the list head (which was registered earlier, via * sys_set_robust_list()): @@ -2051,7 +2063,7 @@ void exit_robust_list(struct task_struct long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout, u32 __user *uaddr2, u32 val2, u32 val3) { - int ret; + int ret = -ENOSYS; int cmd = op & FUTEX_CMD_MASK; struct rw_semaphore *fshared = NULL; @@ -2083,13 +2095,16 @@ long do_futex(u32 __user *uaddr, int op, ret = futex_wake_op(uaddr, fshared, uaddr2, val, val2, val3); break; case FUTEX_LOCK_PI: - ret = futex_lock_pi(uaddr, fshared, val, timeout, 0); + if (futex_cmpxchg_enabled) + ret = futex_lock_pi(uaddr, fshared, val, timeout, 0); break; case FUTEX_UNLOCK_PI: - ret = futex_unlock_pi(uaddr, fshared); + if (futex_cmpxchg_enabled) + ret = futex_unlock_pi(uaddr, fshared); break; case FUTEX_TRYLOCK_PI: - ret = futex_lock_pi(uaddr, fshared, 0, timeout, 1); + if (futex_cmpxchg_enabled) + ret = futex_lock_pi(uaddr, fshared, 0, timeout, 1); break; default: ret = -ENOSYS; @@ -2145,8 +2160,23 @@ static struct file_system_type futex_fs_ static int __init init(void) { + u32 curval; int i; + /* + * This will fail and we want it. Some arch implementations do + * runtime detection of the futex_atomic_cmpxchg_inatomic() + * functionality. We want to know that before we call in any + * of the complex code paths. Also we want to prevent + * registration of robust lists in that case. NULL is + * guaranteed to fault and we get -EFAULT on functional + * implementation, the non functional ones will return + * -ENOSYS. + */ + curval = cmpxchg_futex_value_locked(NULL, 0, 0); + if (curval == -EFAULT) + futex_cmpxchg_enabled = 1; + for (i = 0; i < ARRAY_SIZE(futex_queues); i++) { plist_head_init(&futex_queues[i].chain, &futex_queues[i].lock); spin_lock_init(&futex_queues[i].lock); Index: linux-2.6/kernel/futex_compat.c =================================================================== --- linux-2.6.orig/kernel/futex_compat.c +++ linux-2.6/kernel/futex_compat.c @@ -54,6 +54,9 @@ void compat_exit_robust_list(struct task compat_long_t futex_offset; int rc; + if (!futex_cmpxchg_enabled) + return; + /* * Fetch the list head (which was registered earlier, via * sys_set_robust_list()): @@ -115,6 +118,9 @@ asmlinkage long compat_sys_set_robust_list(struct compat_robust_list_head __user *head, compat_size_t len) { + if (!futex_cmpxchg_enabled) + return -ENOSYS; + if (unlikely(len != sizeof(*head))) return -EINVAL; @@ -130,6 +136,9 @@ compat_sys_get_robust_list(int pid, comp struct compat_robust_list_head __user *head; unsigned long ret; + if (!futex_cmpxchg_enabled) + return -ENOSYS; + if (!pid) head = current->compat_robust_list; else { ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2008-02-15 1:38 UTC | newest] Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2008-02-11 13:07 futex local DoS on most architectures Adrian Bunk 2008-02-11 13:56 ` Mikael Pettersson 2008-02-11 13:59 ` Thomas Gleixner 2008-02-11 14:16 ` Lennert Buytenhek 2008-02-12 12:50 ` Riku Voipio 2008-02-14 21:46 ` Andrew Morton 2008-02-15 1:19 ` Thomas Gleixner 2008-02-15 1:23 ` [PATCH 1/2] futex: fix init order Thomas Gleixner 2008-02-15 1:36 ` [PATCH 2/2] futex: runtime enable pi and robust functionality Thomas Gleixner
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).