Messages in this thread Patch in this message | | | Date | Tue, 10 Dec 2013 14:19:43 -0800 | Subject | Re: process 'stuck' at exit. | From | Linus Torvalds <> |
| |
On Tue, Dec 10, 2013 at 1:57 PM, Linus Torvalds <torvalds@linux-foundation.org> wrote: > > So it looks like __get_user_pages_fast() fails, and keeps failing.
Hmm.. Is any of the addresses unchecked, perhaps? __get_user_pages_fast() does an access_ok() check, while get_user_pages_fast() does *not* seem to do one.
That looks a bit dangerous. Yeah, users should have checked the address range, but there really is no reason not to do it in get_user_pages_fast().
And it looks like the futex code is actually seriously buggered. It only does the access_ok() check for the non-shared case.
Why?
Shouldn't we do something like the attached?
Linus arch/x86/mm/gup.c | 4 +--- kernel/futex.c | 5 +++-- 2 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/arch/x86/mm/gup.c b/arch/x86/mm/gup.c index dd74e46828c0..61e726597599 100644 --- a/arch/x86/mm/gup.c +++ b/arch/x86/mm/gup.c @@ -326,10 +326,8 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write, if (end < start) goto slow_irqon; -#ifdef CONFIG_X86_64 - if (end >> __VIRTUAL_MASK_SHIFT) + if (end > TASK_SIZE_MAX) goto slow_irqon; -#endif /* * XXX: batch / limit 'nr', to avoid large irq off latency diff --git a/kernel/futex.c b/kernel/futex.c index 80ba086f021d..23c12a35dca2 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -251,6 +251,9 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, int rw) return -EINVAL; address -= key->both.offset; + if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))) + return -EFAULT; + /* * PROCESS_PRIVATE futexes are fast. * As the mm cannot disappear under us and the 'key' only needs @@ -259,8 +262,6 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, int rw) * but access_ok() should be faster than find_vma() */ if (!fshared) { - if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))) - return -EFAULT; key->private.mm = mm; key->private.address = address; get_futex_key_refs(key); | |