All of lore.kernel.org
 help / color / mirror / Atom feed
* [BUG] rmap: fix page_address_in_vma() to walk through anon_vma_chain
@ 2010-04-22  5:42 ` Naoya Horiguchi
  0 siblings, 0 replies; 12+ messages in thread
From: Naoya Horiguchi @ 2010-04-22  5:42 UTC (permalink / raw)
  To: linux-mm; +Cc: LKML, Andrew Morton, Rik van Riel, Andi Kleen

I found a bug on page_address_in_vma() related to anon_vma_chain.

I wrote a patch, but according to a comment in include/linux/rmap.h,
I suspect this doesn't meet lock requirement of anon_vma_chain
(mmap_sem and page_table_lock, see below).

                           mmap_sem      page_table_lock
  mm/ksm.c:
    write_protect_page()   hold          not hold
    replace_page()         hold          not hold
  mm/memory-failure.c:
    add_to_kill()          not hold      hold
  mm/mempolicy.c:
    new_vma_page()         hold          not hold
  mm/swapfile.c:
    unuse_vma()            hold          not hold

Any comments?

Thanks,
Naoya Horiguchi
---
Subject: [BUG] rmap: fix page_address_in_vma() to walk through anon_vma_chain

page_address_in_vma() checks if a given page is associated with a given vma.
Currently it just compares vma->anon_vma and page_anon_vma(page).
But in 2.6.34, a vma can have multiple anon_vmas with anon_vma_chain,
so we have to check all anon_vmas in the "same_vma" chain.
Otherwise, when a page is shared by multiple processes,
some (page,vma) pairs can be misjudged as not-mapped.

Need Work: Meet lock requirement of anon_vma_chain.

Signed-off-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Rik van Riel <riel@redhat.com>
Cc: Andi Kleen <andi@firstfloor.org>
---
 mm/rmap.c |   12 ++++++++++--
 1 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/mm/rmap.c b/mm/rmap.c
index 526704e..2e7462b 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -340,14 +340,22 @@ vma_address(struct page *page, struct vm_area_struct *vma)
 unsigned long page_address_in_vma(struct page *page, struct vm_area_struct *vma)
 {
 	if (PageAnon(page)) {
-		if (vma->anon_vma != page_anon_vma(page))
-			return -EFAULT;
+		struct anon_vma_chain *avc;
+		/*
+		 * Walking same_vma list needs mmap_sem and page_table_lock.
+		 * Do users of this function meet it?
+		 */
+		list_for_each_entry(avc, &vma->anon_vma_chain, same_vma)
+			if (avc->anon_vma == page_anon_vma(page))
+				goto get_address;
+		return -EFAULT;
 	} else if (page->mapping && !(vma->vm_flags & VM_NONLINEAR)) {
 		if (!vma->vm_file ||
 		    vma->vm_file->f_mapping != page->mapping)
 			return -EFAULT;
 	} else
 		return -EFAULT;
+get_address:
 	return vma_address(page, vma);
 }
 
-- 
1.7.0

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [BUG] rmap: fix page_address_in_vma() to walk through anon_vma_chain
@ 2010-04-22  5:42 ` Naoya Horiguchi
  0 siblings, 0 replies; 12+ messages in thread
From: Naoya Horiguchi @ 2010-04-22  5:42 UTC (permalink / raw)
  To: linux-mm; +Cc: LKML, Andrew Morton, Rik van Riel, Andi Kleen

I found a bug on page_address_in_vma() related to anon_vma_chain.

I wrote a patch, but according to a comment in include/linux/rmap.h,
I suspect this doesn't meet lock requirement of anon_vma_chain
(mmap_sem and page_table_lock, see below).

                           mmap_sem      page_table_lock
  mm/ksm.c:
    write_protect_page()   hold          not hold
    replace_page()         hold          not hold
  mm/memory-failure.c:
    add_to_kill()          not hold      hold
  mm/mempolicy.c:
    new_vma_page()         hold          not hold
  mm/swapfile.c:
    unuse_vma()            hold          not hold

Any comments?

Thanks,
Naoya Horiguchi
---
Subject: [BUG] rmap: fix page_address_in_vma() to walk through anon_vma_chain

page_address_in_vma() checks if a given page is associated with a given vma.
Currently it just compares vma->anon_vma and page_anon_vma(page).
But in 2.6.34, a vma can have multiple anon_vmas with anon_vma_chain,
so we have to check all anon_vmas in the "same_vma" chain.
Otherwise, when a page is shared by multiple processes,
some (page,vma) pairs can be misjudged as not-mapped.

Need Work: Meet lock requirement of anon_vma_chain.

Signed-off-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Rik van Riel <riel@redhat.com>
Cc: Andi Kleen <andi@firstfloor.org>
---
 mm/rmap.c |   12 ++++++++++--
 1 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/mm/rmap.c b/mm/rmap.c
index 526704e..2e7462b 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -340,14 +340,22 @@ vma_address(struct page *page, struct vm_area_struct *vma)
 unsigned long page_address_in_vma(struct page *page, struct vm_area_struct *vma)
 {
 	if (PageAnon(page)) {
-		if (vma->anon_vma != page_anon_vma(page))
-			return -EFAULT;
+		struct anon_vma_chain *avc;
+		/*
+		 * Walking same_vma list needs mmap_sem and page_table_lock.
+		 * Do users of this function meet it?
+		 */
+		list_for_each_entry(avc, &vma->anon_vma_chain, same_vma)
+			if (avc->anon_vma == page_anon_vma(page))
+				goto get_address;
+		return -EFAULT;
 	} else if (page->mapping && !(vma->vm_flags & VM_NONLINEAR)) {
 		if (!vma->vm_file ||
 		    vma->vm_file->f_mapping != page->mapping)
 			return -EFAULT;
 	} else
 		return -EFAULT;
+get_address:
 	return vma_address(page, vma);
 }
 
-- 
1.7.0

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [BUG] rmap: fix page_address_in_vma() to walk through anon_vma_chain
  2010-04-22  5:42 ` Naoya Horiguchi
@ 2010-04-22  6:03   ` Naoya Horiguchi
  -1 siblings, 0 replies; 12+ messages in thread
From: Naoya Horiguchi @ 2010-04-22  6:03 UTC (permalink / raw)
  To: linux-mm; +Cc: LKML, Andrew Morton, Rik van Riel, Andi Kleen

>                            mmap_sem      page_table_lock
>   mm/ksm.c:
>     write_protect_page()   hold          not hold
>     replace_page()         hold          not hold
>   mm/memory-failure.c:
>     add_to_kill()          not hold      hold
                                           ^^^^
Sorry, I misread here. This is "not hold".

Thanks,
Naoya Horiguchi

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [BUG] rmap: fix page_address_in_vma() to walk through anon_vma_chain
@ 2010-04-22  6:03   ` Naoya Horiguchi
  0 siblings, 0 replies; 12+ messages in thread
From: Naoya Horiguchi @ 2010-04-22  6:03 UTC (permalink / raw)
  To: linux-mm; +Cc: LKML, Andrew Morton, Rik van Riel, Andi Kleen

>                            mmap_sem      page_table_lock
>   mm/ksm.c:
>     write_protect_page()   hold          not hold
>     replace_page()         hold          not hold
>   mm/memory-failure.c:
>     add_to_kill()          not hold      hold
                                           ^^^^
Sorry, I misread here. This is "not hold".

Thanks,
Naoya Horiguchi

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [BUG] rmap: fix page_address_in_vma() to walk through anon_vma_chain
  2010-04-22  5:42 ` Naoya Horiguchi
@ 2010-04-22 15:17   ` Rik van Riel
  -1 siblings, 0 replies; 12+ messages in thread
From: Rik van Riel @ 2010-04-22 15:17 UTC (permalink / raw)
  To: Naoya Horiguchi; +Cc: linux-mm, LKML, Andrew Morton, Andi Kleen

On 04/22/2010 01:42 AM, Naoya Horiguchi wrote:
> I found a bug on page_address_in_vma() related to anon_vma_chain.
>
> I wrote a patch, but according to a comment in include/linux/rmap.h,
> I suspect this doesn't meet lock requirement of anon_vma_chain
> (mmap_sem and page_table_lock, see below).
>
>                             mmap_sem      page_table_lock
>    mm/ksm.c:
>      write_protect_page()   hold          not hold
>      replace_page()         hold          not hold
>    mm/memory-failure.c:
>      add_to_kill()          not hold      hold
>    mm/mempolicy.c:
>      new_vma_page()         hold          not hold
>    mm/swapfile.c:
>      unuse_vma()            hold          not hold
>
> Any comments?

Good catch.

However, for anonymous pages, page_address_in_vma only
ever determined whether the page _could_ be part of the
VMA, never whether it actually was.

The function page_address_in_vma has always given
false positives, which means all of the callers already
check that the page is actually part of the process.

This means we may be able to get away with not verifying
the anon_vma at all.  After all, verifying that the VMA
has the anon_vma mapped does not mean the VMA has this
page...

Doing away with that check gets rid of your locking
conundrum :)

Opinions?

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [BUG] rmap: fix page_address_in_vma() to walk through anon_vma_chain
@ 2010-04-22 15:17   ` Rik van Riel
  0 siblings, 0 replies; 12+ messages in thread
From: Rik van Riel @ 2010-04-22 15:17 UTC (permalink / raw)
  To: Naoya Horiguchi; +Cc: linux-mm, LKML, Andrew Morton, Andi Kleen

On 04/22/2010 01:42 AM, Naoya Horiguchi wrote:
> I found a bug on page_address_in_vma() related to anon_vma_chain.
>
> I wrote a patch, but according to a comment in include/linux/rmap.h,
> I suspect this doesn't meet lock requirement of anon_vma_chain
> (mmap_sem and page_table_lock, see below).
>
>                             mmap_sem      page_table_lock
>    mm/ksm.c:
>      write_protect_page()   hold          not hold
>      replace_page()         hold          not hold
>    mm/memory-failure.c:
>      add_to_kill()          not hold      hold
>    mm/mempolicy.c:
>      new_vma_page()         hold          not hold
>    mm/swapfile.c:
>      unuse_vma()            hold          not hold
>
> Any comments?

Good catch.

However, for anonymous pages, page_address_in_vma only
ever determined whether the page _could_ be part of the
VMA, never whether it actually was.

The function page_address_in_vma has always given
false positives, which means all of the callers already
check that the page is actually part of the process.

This means we may be able to get away with not verifying
the anon_vma at all.  After all, verifying that the VMA
has the anon_vma mapped does not mean the VMA has this
page...

Doing away with that check gets rid of your locking
conundrum :)

Opinions?

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [BUG] rmap: fix page_address_in_vma() to walk through anon_vma_chain
  2010-04-22 15:17   ` Rik van Riel
@ 2010-04-23  2:06     ` Naoya Horiguchi
  -1 siblings, 0 replies; 12+ messages in thread
From: Naoya Horiguchi @ 2010-04-23  2:06 UTC (permalink / raw)
  To: Rik van Riel; +Cc: linux-mm, LKML, Andrew Morton, Andi Kleen

> However, for anonymous pages, page_address_in_vma only
> ever determined whether the page _could_ be part of the
> VMA, never whether it actually was.
>
> The function page_address_in_vma has always given
> false positives, which means all of the callers already
> check that the page is actually part of the process.

I see.

> This means we may be able to get away with not verifying
> the anon_vma at all.  After all, verifying that the VMA
> has the anon_vma mapped does not mean the VMA has this
> page...
> 
> Doing away with that check gets rid of your locking
> conundrum :)

I get it, thank you :)
I'll rewrite fix patch based on your comments.

Thanks,
Naoya Horiguchi

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [BUG] rmap: fix page_address_in_vma() to walk through anon_vma_chain
@ 2010-04-23  2:06     ` Naoya Horiguchi
  0 siblings, 0 replies; 12+ messages in thread
From: Naoya Horiguchi @ 2010-04-23  2:06 UTC (permalink / raw)
  To: Rik van Riel; +Cc: linux-mm, LKML, Andrew Morton, Andi Kleen

> However, for anonymous pages, page_address_in_vma only
> ever determined whether the page _could_ be part of the
> VMA, never whether it actually was.
>
> The function page_address_in_vma has always given
> false positives, which means all of the callers already
> check that the page is actually part of the process.

I see.

> This means we may be able to get away with not verifying
> the anon_vma at all.  After all, verifying that the VMA
> has the anon_vma mapped does not mean the VMA has this
> page...
> 
> Doing away with that check gets rid of your locking
> conundrum :)

I get it, thank you :)
I'll rewrite fix patch based on your comments.

Thanks,
Naoya Horiguchi

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH] [BUGFIX] rmap: remove anon_vma check in page_address_in_vma()
  2010-04-22 15:17   ` Rik van Riel
@ 2010-04-23  2:08     ` Naoya Horiguchi
  -1 siblings, 0 replies; 12+ messages in thread
From: Naoya Horiguchi @ 2010-04-23  2:08 UTC (permalink / raw)
  To: Rik van Riel; +Cc: linux-mm, LKML, Andrew Morton, Andi Kleen

Currently page_address_in_vma() compares vma->anon_vma and page_anon_vma(page)
for parameter check, but in 2.6.34 a vma can have multiple anon_vmas with
anon_vma_chain, so current check does not work. (For anonymous page shared by
multiple processes, some verified (page,vma) pairs return -EFAULT wrongly.)

We can go to checking all anon_vmas in the "same_vma" chain, but it needs
to meet lock requirement. Instead, we can remove anon_vma check safely
because page_address_in_vma() assumes that page and vma are already checked
to belong to the identical process.

Signed-off-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Rik van Riel <riel@redhat.com>
Cc: Andi Kleen <andi@firstfloor.org>
---
 mm/rmap.c |    9 ++++-----
 1 files changed, 4 insertions(+), 5 deletions(-)

diff --git v2.6.34-rc5:mm/rmap.c v2.6.34-rc5:mm/rmap.c
index 526704e..486fd0a 100644
--- v2.6.34-rc5:mm/rmap.c
+++ v2.6.34-rc5:mm/rmap.c
@@ -335,14 +335,13 @@ vma_address(struct page *page, struct vm_area_struct *vma)
 
 /*
  * At what user virtual address is page expected in vma?
- * checking that the page matches the vma.
+ * Caller should check the page is actually part of the vma.
  */
 unsigned long page_address_in_vma(struct page *page, struct vm_area_struct *vma)
 {
-	if (PageAnon(page)) {
-		if (vma->anon_vma != page_anon_vma(page))
-			return -EFAULT;
-	} else if (page->mapping && !(vma->vm_flags & VM_NONLINEAR)) {
+	if (PageAnon(page))
+		;
+	else if (page->mapping && !(vma->vm_flags & VM_NONLINEAR)) {
 		if (!vma->vm_file ||
 		    vma->vm_file->f_mapping != page->mapping)
 			return -EFAULT;
-- 
1.7.0

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH] [BUGFIX] rmap: remove anon_vma check in page_address_in_vma()
@ 2010-04-23  2:08     ` Naoya Horiguchi
  0 siblings, 0 replies; 12+ messages in thread
From: Naoya Horiguchi @ 2010-04-23  2:08 UTC (permalink / raw)
  To: Rik van Riel; +Cc: linux-mm, LKML, Andrew Morton, Andi Kleen

Currently page_address_in_vma() compares vma->anon_vma and page_anon_vma(page)
for parameter check, but in 2.6.34 a vma can have multiple anon_vmas with
anon_vma_chain, so current check does not work. (For anonymous page shared by
multiple processes, some verified (page,vma) pairs return -EFAULT wrongly.)

We can go to checking all anon_vmas in the "same_vma" chain, but it needs
to meet lock requirement. Instead, we can remove anon_vma check safely
because page_address_in_vma() assumes that page and vma are already checked
to belong to the identical process.

Signed-off-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Rik van Riel <riel@redhat.com>
Cc: Andi Kleen <andi@firstfloor.org>
---
 mm/rmap.c |    9 ++++-----
 1 files changed, 4 insertions(+), 5 deletions(-)

diff --git v2.6.34-rc5:mm/rmap.c v2.6.34-rc5:mm/rmap.c
index 526704e..486fd0a 100644
--- v2.6.34-rc5:mm/rmap.c
+++ v2.6.34-rc5:mm/rmap.c
@@ -335,14 +335,13 @@ vma_address(struct page *page, struct vm_area_struct *vma)
 
 /*
  * At what user virtual address is page expected in vma?
- * checking that the page matches the vma.
+ * Caller should check the page is actually part of the vma.
  */
 unsigned long page_address_in_vma(struct page *page, struct vm_area_struct *vma)
 {
-	if (PageAnon(page)) {
-		if (vma->anon_vma != page_anon_vma(page))
-			return -EFAULT;
-	} else if (page->mapping && !(vma->vm_flags & VM_NONLINEAR)) {
+	if (PageAnon(page))
+		;
+	else if (page->mapping && !(vma->vm_flags & VM_NONLINEAR)) {
 		if (!vma->vm_file ||
 		    vma->vm_file->f_mapping != page->mapping)
 			return -EFAULT;
-- 
1.7.0

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH] [BUGFIX] rmap: remove anon_vma check in page_address_in_vma()
  2010-04-23  2:08     ` Naoya Horiguchi
@ 2010-04-23 13:52       ` Rik van Riel
  -1 siblings, 0 replies; 12+ messages in thread
From: Rik van Riel @ 2010-04-23 13:52 UTC (permalink / raw)
  To: Naoya Horiguchi; +Cc: linux-mm, LKML, Andrew Morton, Andi Kleen

On 04/22/2010 10:08 PM, Naoya Horiguchi wrote:
> Currently page_address_in_vma() compares vma->anon_vma and page_anon_vma(page)
> for parameter check, but in 2.6.34 a vma can have multiple anon_vmas with
> anon_vma_chain, so current check does not work. (For anonymous page shared by
> multiple processes, some verified (page,vma) pairs return -EFAULT wrongly.)
>
> We can go to checking all anon_vmas in the "same_vma" chain, but it needs
> to meet lock requirement. Instead, we can remove anon_vma check safely
> because page_address_in_vma() assumes that page and vma are already checked
> to belong to the identical process.
>
> Signed-off-by: Naoya Horiguchi<n-horiguchi@ah.jp.nec.com>
> Cc: Andrew Morton<akpm@linux-foundation.org>
> Cc: Rik van Riel<riel@redhat.com>
> Cc: Andi Kleen<andi@firstfloor.org>

Reviewed-by: Rik van Riel <riel@redhat.com>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] [BUGFIX] rmap: remove anon_vma check in page_address_in_vma()
@ 2010-04-23 13:52       ` Rik van Riel
  0 siblings, 0 replies; 12+ messages in thread
From: Rik van Riel @ 2010-04-23 13:52 UTC (permalink / raw)
  To: Naoya Horiguchi; +Cc: linux-mm, LKML, Andrew Morton, Andi Kleen

On 04/22/2010 10:08 PM, Naoya Horiguchi wrote:
> Currently page_address_in_vma() compares vma->anon_vma and page_anon_vma(page)
> for parameter check, but in 2.6.34 a vma can have multiple anon_vmas with
> anon_vma_chain, so current check does not work. (For anonymous page shared by
> multiple processes, some verified (page,vma) pairs return -EFAULT wrongly.)
>
> We can go to checking all anon_vmas in the "same_vma" chain, but it needs
> to meet lock requirement. Instead, we can remove anon_vma check safely
> because page_address_in_vma() assumes that page and vma are already checked
> to belong to the identical process.
>
> Signed-off-by: Naoya Horiguchi<n-horiguchi@ah.jp.nec.com>
> Cc: Andrew Morton<akpm@linux-foundation.org>
> Cc: Rik van Riel<riel@redhat.com>
> Cc: Andi Kleen<andi@firstfloor.org>

Reviewed-by: Rik van Riel <riel@redhat.com>

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2010-04-23 13:52 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-04-22  5:42 [BUG] rmap: fix page_address_in_vma() to walk through anon_vma_chain Naoya Horiguchi
2010-04-22  5:42 ` Naoya Horiguchi
2010-04-22  6:03 ` Naoya Horiguchi
2010-04-22  6:03   ` Naoya Horiguchi
2010-04-22 15:17 ` Rik van Riel
2010-04-22 15:17   ` Rik van Riel
2010-04-23  2:06   ` Naoya Horiguchi
2010-04-23  2:06     ` Naoya Horiguchi
2010-04-23  2:08   ` [PATCH] [BUGFIX] rmap: remove anon_vma check in page_address_in_vma() Naoya Horiguchi
2010-04-23  2:08     ` Naoya Horiguchi
2010-04-23 13:52     ` Rik van Riel
2010-04-23 13:52       ` Rik van Riel

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.