diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-29 17:07:55 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-29 17:07:55 -0500 |
commit | 5d2a2dbbc1025dbf7998b9289574d9592b8f21cc (patch) | |
tree | b4f3f45190b814b5196235c21f983fbc7878a47b /mm/memory.c | |
parent | c9cfcddfd65735437a4cb8563d6b66a6da8a5ed6 (diff) |
cow_user_page: fix page alignment
High Dickins points out that the user virtual address passed to the page
fault handler isn't necessarily page-aligned.
Also, add a comment on why the copy could fail for the user address case.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'mm/memory.c')
-rw-r--r-- | mm/memory.c | 11 |
1 files changed, 9 insertions, 2 deletions
diff --git a/mm/memory.c b/mm/memory.c index 74f95ae0510b..745b3482e6c2 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -1394,8 +1394,15 @@ static inline void cow_user_page(struct page *dst, struct page *src, unsigned lo | |||
1394 | */ | 1394 | */ |
1395 | if (unlikely(!src)) { | 1395 | if (unlikely(!src)) { |
1396 | void *kaddr = kmap_atomic(dst, KM_USER0); | 1396 | void *kaddr = kmap_atomic(dst, KM_USER0); |
1397 | unsigned long left = __copy_from_user_inatomic(kaddr, (void __user *)va, PAGE_SIZE); | 1397 | void __user *uaddr = (void __user *)(va & PAGE_MASK); |
1398 | if (left) | 1398 | |
1399 | /* | ||
1400 | * This really shouldn't fail, because the page is there | ||
1401 | * in the page tables. But it might just be unreadable, | ||
1402 | * in which case we just give up and fill the result with | ||
1403 | * zeroes. | ||
1404 | */ | ||
1405 | if (__copy_from_user_inatomic(kaddr, uaddr, PAGE_SIZE)) | ||
1399 | memset(kaddr, 0, PAGE_SIZE); | 1406 | memset(kaddr, 0, PAGE_SIZE); |
1400 | kunmap_atomic(kaddr, KM_USER0); | 1407 | kunmap_atomic(kaddr, KM_USER0); |
1401 | return; | 1408 | return; |