diff options
author | Chen LinX <linx.z.chen@intel.com> | 2013-10-30 16:56:18 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-11-12 22:05:34 -0500 |
commit | 18b683a2334848c003fe89e3002244ca298544f4 (patch) | |
tree | f20bb79711f7ae4b17d2bc0044125b744e172201 /mm | |
parent | e86100b54cd487c13956f09f2c38955f1a1a0909 (diff) |
mm/pagewalk.c: fix walk_page_range() access of wrong PTEs
commit 3017f079efd6af199b0852b5c425364513db460e upstream.
When walk_page_range walk a memory map's page tables, it'll skip
VM_PFNMAP area, then variable 'next' will to assign to vma->vm_end, it
maybe larger than 'end'. In next loop, 'addr' will be larger than
'next'. Then in /proc/XXXX/pagemap file reading procedure, the 'addr'
will growing forever in pagemap_pte_range, pte_to_pagemap_entry will
access the wrong pte.
BUG: Bad page map in process procrank pte:8437526f pmd:785de067
addr:9108d000 vm_flags:00200073 anon_vma:f0d99020 mapping: (null) index:9108d
CPU: 1 PID: 4974 Comm: procrank Tainted: G B W O 3.10.1+ #1
Call Trace:
dump_stack+0x16/0x18
print_bad_pte+0x114/0x1b0
vm_normal_page+0x56/0x60
pagemap_pte_range+0x17a/0x1d0
walk_page_range+0x19e/0x2c0
pagemap_read+0x16e/0x200
vfs_read+0x84/0x150
SyS_read+0x4a/0x80
syscall_call+0x7/0xb
Signed-off-by: Liu ShuoX <shuox.liu@intel.com>
Signed-off-by: Chen LinX <linx.z.chen@intel.com>
Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Reviewed-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/pagewalk.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/mm/pagewalk.c b/mm/pagewalk.c index 5da2cbcfdbb5..2beeabf502c5 100644 --- a/mm/pagewalk.c +++ b/mm/pagewalk.c | |||
@@ -242,7 +242,7 @@ int walk_page_range(unsigned long addr, unsigned long end, | |||
242 | if (err) | 242 | if (err) |
243 | break; | 243 | break; |
244 | pgd++; | 244 | pgd++; |
245 | } while (addr = next, addr != end); | 245 | } while (addr = next, addr < end); |
246 | 246 | ||
247 | return err; | 247 | return err; |
248 | } | 248 | } |