aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHugh Dickins <hugh@veritas.com>2009-01-06 17:39:32 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-01-06 18:59:03 -0500
commit878b63ac889df706d01048f2c110e322ad2f996d (patch)
treee0bd69b890fda939fc190675d977dd0fd75e0427
parent2da02997e08d3efe8174c7a47696e6f7cbe69ba9 (diff)
mm: gup persist for write permission
do_wp_page()'s VM_FAULT_WRITE return value tells __get_user_pages() that COW has been done if necessary, though it may be leaving the pte without write permission - for the odd case of forced writing to a readonly vma for ptrace. At present GUP then retries the follow_page() without asking for write permission, to escape an endless loop when forced. But an application may be relying on GUP to guarantee a writable page which won't be COWed again when written from userspace, whereas a race here might leave a readonly pte in place? Change the VM_FAULT_WRITE handling to ask follow_page() for write permission again, except in that odd case of forced writing to a readonly vma. Signed-off-by: Hugh Dickins <hugh@veritas.com> Cc: Lee Schermerhorn <lee.schermerhorn@hp.com> Cc: Rik van Riel <riel@redhat.com> Cc: Nick Piggin <nickpiggin@yahoo.com.au> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Robin Holt <holt@sgi.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--mm/memory.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/mm/memory.c b/mm/memory.c
index 122d965e820f..f594bb65a9f1 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1264,9 +1264,15 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
1264 * do_wp_page has broken COW when necessary, 1264 * do_wp_page has broken COW when necessary,
1265 * even if maybe_mkwrite decided not to set 1265 * even if maybe_mkwrite decided not to set
1266 * pte_write. We can thus safely do subsequent 1266 * pte_write. We can thus safely do subsequent
1267 * page lookups as if they were reads. 1267 * page lookups as if they were reads. But only
1268 * do so when looping for pte_write is futile:
1269 * in some cases userspace may also be wanting
1270 * to write to the gotten user page, which a
1271 * read fault here might prevent (a readonly
1272 * page might get reCOWed by userspace write).
1268 */ 1273 */
1269 if (ret & VM_FAULT_WRITE) 1274 if ((ret & VM_FAULT_WRITE) &&
1275 !(vma->vm_flags & VM_WRITE))
1270 foll_flags &= ~FOLL_WRITE; 1276 foll_flags &= ~FOLL_WRITE;
1271 1277
1272 cond_resched(); 1278 cond_resched();