]>
Commit | Line | Data |
---|---|---|
9ad5c5a3 GKH |
1 | From 23aaed6659df9adfabe9c583e67a36b54e21df46 Mon Sep 17 00:00:00 2001 |
2 | From: Shiraz Hashim <shashim@codeaurora.org> | |
3 | Date: Thu, 5 Feb 2015 12:25:06 -0800 | |
4 | Subject: mm: pagewalk: call pte_hole() for VM_PFNMAP during walk_page_range | |
5 | ||
6 | From: Shiraz Hashim <shashim@codeaurora.org> | |
7 | ||
8 | commit 23aaed6659df9adfabe9c583e67a36b54e21df46 upstream. | |
9 | ||
10 | walk_page_range() silently skips vma having VM_PFNMAP set, which leads | |
11 | to undesirable behaviour at client end (who called walk_page_range). | |
12 | Userspace applications get the wrong data, so the effect is like just | |
13 | confusing users (if the applications just display the data) or sometimes | |
14 | killing the processes (if the applications do something with | |
15 | misunderstanding virtual addresses due to the wrong data.) | |
16 | ||
17 | For example for pagemap_read, when no callbacks are called against | |
18 | VM_PFNMAP vma, pagemap_read may prepare pagemap data for next virtual | |
19 | address range at wrong index. | |
20 | ||
21 | Eventually userspace may get wrong pagemap data for a task. | |
22 | Corresponding to a VM_PFNMAP marked vma region, kernel may report | |
23 | mappings from subsequent vma regions. User space in turn may account | |
24 | more pages (than really are) to the task. | |
25 | ||
26 | In my case I was using procmem, procrack (Android utility) which uses | |
27 | pagemap interface to account RSS pages of a task. Due to this bug it | |
28 | was giving a wrong picture for vmas (with VM_PFNMAP set). | |
29 | ||
30 | Fixes: a9ff785e4437 ("mm/pagewalk.c: walk_page_range should avoid VM_PFNMAP areas") | |
31 | Signed-off-by: Shiraz Hashim <shashim@codeaurora.org> | |
32 | Acked-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com> | |
33 | Signed-off-by: Andrew Morton <akpm@linux-foundation.org> | |
34 | Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> | |
35 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
36 | ||
37 | --- | |
38 | mm/pagewalk.c | 5 ++++- | |
39 | 1 file changed, 4 insertions(+), 1 deletion(-) | |
40 | ||
41 | --- a/mm/pagewalk.c | |
42 | +++ b/mm/pagewalk.c | |
43 | @@ -199,7 +199,10 @@ int walk_page_range(unsigned long addr, | |
44 | */ | |
45 | if ((vma->vm_start <= addr) && | |
46 | (vma->vm_flags & VM_PFNMAP)) { | |
47 | - next = vma->vm_end; | |
48 | + if (walk->pte_hole) | |
49 | + err = walk->pte_hole(addr, next, walk); | |
50 | + if (err) | |
51 | + break; | |
52 | pgd = pgd_offset(walk->mm, next); | |
53 | continue; | |
54 | } |