2009-07-10 23:13:25

by Sonny Rao

[permalink] [raw]
Subject: [PATCH] futexs: fix infinite loop in get_futex_key on huge page

get_futex_key() can infinitely loop if it is called on a virtual address
that is within a huge page but not aligned to the beginning of that
page. The call to get_user_pages_fast will return the struct page for
a sub-page within the huge page and the check for page->mapping will
always fail.

The fix is to call compound_head on the page before checking that it's mapped.

Signed-off-by: Sonny Rao <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: [email protected]

Index: linux-2.6.31-rc2/kernel/futex.c
===================================================================
--- linux-2.6.31-rc2.orig/kernel/futex.c 2009-07-10 17:45:46.181084475 -0500
+++ linux-2.6.31-rc2/kernel/futex.c 2009-07-10 17:46:47.345084062 -0500
@@ -247,6 +247,7 @@
if (err < 0)
return err;

+ page = compound_head(page);
lock_page(page);
if (!page->mapping) {
unlock_page(page);


2009-07-11 08:20:06

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH] futexs: fix infinite loop in get_futex_key on huge page


* Sonny Rao <[email protected]> wrote:

> get_futex_key() can infinitely loop if it is called on a virtual
> address that is within a huge page but not aligned to the
> beginning of that page. The call to get_user_pages_fast will
> return the struct page for a sub-page within the huge page and the
> check for page->mapping will always fail.
>
> The fix is to call compound_head on the page before checking that
> it's mapped.
>
> Signed-off-by: Sonny Rao <[email protected]>
> Cc: Ingo Molnar <[email protected]>
> Cc: [email protected]
>
> Index: linux-2.6.31-rc2/kernel/futex.c
> ===================================================================
> --- linux-2.6.31-rc2.orig/kernel/futex.c 2009-07-10 17:45:46.181084475 -0500
> +++ linux-2.6.31-rc2/kernel/futex.c 2009-07-10 17:46:47.345084062 -0500
> @@ -247,6 +247,7 @@
> if (err < 0)
> return err;
>
> + page = compound_head(page);
> lock_page(page);
> if (!page->mapping) {
> unlock_page(page);

Nice catch! Applied it to tip:core/urgent - Thomas, do you agree
with the fix?

Ingo

2009-07-11 08:22:51

by Sonny Rao

[permalink] [raw]
Subject: [tip:core/urgent] futexes: Fix infinite loop in get_futex_key() on huge page

Commit-ID: 7c8fa4f04ab956076605422d5ed37410893a8a73
Gitweb: http://git.kernel.org/tip/7c8fa4f04ab956076605422d5ed37410893a8a73
Author: Sonny Rao <[email protected]>
AuthorDate: Fri, 10 Jul 2009 18:13:13 -0500
Committer: Ingo Molnar <[email protected]>
CommitDate: Sat, 11 Jul 2009 10:18:45 +0200

futexes: Fix infinite loop in get_futex_key() on huge page

get_futex_key() can infinitely loop if it is called on a
virtual address that is within a huge page but not aligned to
the beginning of that page. The call to get_user_pages_fast
will return the struct page for a sub-page within the huge page
and the check for page->mapping will always fail.

The fix is to call compound_head on the page before checking
that it's mapped.

Signed-off-by: Sonny Rao <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>


---
kernel/futex.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/kernel/futex.c b/kernel/futex.c
index 794c862..0672ff8 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -247,6 +247,7 @@ again:
if (err < 0)
return err;

+ page = compound_head(page);
lock_page(page);
if (!page->mapping) {
unlock_page(page);

2009-07-11 10:17:17

by Thomas Gleixner

[permalink] [raw]
Subject: Re: [PATCH] futexs: fix infinite loop in get_futex_key on huge page

On Sat, 11 Jul 2009, Ingo Molnar wrote:
>
> * Sonny Rao <[email protected]> wrote:
>
> > get_futex_key() can infinitely loop if it is called on a virtual
> > address that is within a huge page but not aligned to the
> > beginning of that page. The call to get_user_pages_fast will
> > return the struct page for a sub-page within the huge page and the
> > check for page->mapping will always fail.
> >
> > The fix is to call compound_head on the page before checking that
> > it's mapped.
> >
> > Signed-off-by: Sonny Rao <[email protected]>
> > Cc: Ingo Molnar <[email protected]>
> > Cc: [email protected]
> >
> > Index: linux-2.6.31-rc2/kernel/futex.c
> > ===================================================================
> > --- linux-2.6.31-rc2.orig/kernel/futex.c 2009-07-10 17:45:46.181084475 -0500
> > +++ linux-2.6.31-rc2/kernel/futex.c 2009-07-10 17:46:47.345084062 -0500
> > @@ -247,6 +247,7 @@
> > if (err < 0)
> > return err;
> >
> > + page = compound_head(page);
> > lock_page(page);
> > if (!page->mapping) {
> > unlock_page(page);
>
> Nice catch! Applied it to tip:core/urgent - Thomas, do you agree
> with the fix?

Acked-by-me.

2009-07-11 10:43:23

by Sonny Rao

[permalink] [raw]
Subject: [tip:core/urgent] futexes: Fix infinite loop in get_futex_key() on huge page

Commit-ID: ce2ae53b750abfaa012ce408e93da131a5b5649b
Gitweb: http://git.kernel.org/tip/ce2ae53b750abfaa012ce408e93da131a5b5649b
Author: Sonny Rao <[email protected]>
AuthorDate: Fri, 10 Jul 2009 18:13:13 -0500
Committer: Ingo Molnar <[email protected]>
CommitDate: Sat, 11 Jul 2009 12:40:44 +0200

futexes: Fix infinite loop in get_futex_key() on huge page

get_futex_key() can infinitely loop if it is called on a
virtual address that is within a huge page but not aligned to
the beginning of that page. The call to get_user_pages_fast
will return the struct page for a sub-page within the huge page
and the check for page->mapping will always fail.

The fix is to call compound_head on the page before checking
that it's mapped.

Signed-off-by: Sonny Rao <[email protected]>
Acked-by: Thomas Gleixner <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>


---
kernel/futex.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/kernel/futex.c b/kernel/futex.c
index 794c862..0672ff8 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -247,6 +247,7 @@ again:
if (err < 0)
return err;

+ page = compound_head(page);
lock_page(page);
if (!page->mapping) {
unlock_page(page);