diff options
authorJoonsoo Kim <js1304@gmail.com>2015-07-17 16:24:15 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2015-07-17 16:39:54 -0700
commitf3a14ced32513d103a3ed0ce89c4e713fac01461 (patch)
parenta2673b6e040663bf16a552f8619e6bde9f4b9acf (diff)
mm/page_owner: fix possible access violation
When I tested my new patches, I found that page pointer which is used for setting page_owner information is changed. This is because page pointer is used to set new migratetype in loop. After this work, page pointer could be out of bound. If this wrong pointer is used for page_owner, access violation happens. Below is error message that I got. BUG: unable to handle kernel paging request at 0000000000b00018 IP: [<ffffffff81025f30>] save_stack_address+0x30/0x40 PGD 1af2d067 PUD 166e0067 PMD 0 Oops: 0002 [#1] SMP ...snip... Call Trace: print_context_stack+0xcf/0x100 dump_trace+0x15f/0x320 save_stack_trace+0x2f/0x50 __set_page_owner+0x46/0x70 __isolate_free_page+0x1f7/0x210 split_free_page+0x21/0xb0 isolate_freepages_block+0x1e2/0x410 compaction_alloc+0x22d/0x2d0 migrate_pages+0x289/0x8b0 compact_zone+0x409/0x880 compact_zone_order+0x6d/0x90 try_to_compact_pages+0x110/0x210 __alloc_pages_direct_compact+0x3d/0xe6 __alloc_pages_nodemask+0x6cd/0x9a0 alloc_pages_current+0x91/0x100 runtest_store+0x296/0xa50 simple_attr_write+0xbd/0xe0 __vfs_write+0x28/0xf0 vfs_write+0xa9/0x1b0 SyS_write+0x46/0xb0 system_call_fastpath+0x16/0x75 This patch fixes this error by moving up set_page_owner(). Signed-off-by: Joonsoo Kim <iamjoonsoo.kim@lge.com> Cc: Mel Gorman <mgorman@suse.de> Cc: Vlastimil Babka <vbabka@suse.cz> Acked-by: Minchan Kim <minchan@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 files changed, 3 insertions, 1 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index ac05e7ae399e..fbba675a0bd9 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1994,6 +1994,8 @@ int __isolate_free_page(struct page *page, unsigned int order)
+ set_page_owner(page, order, 0);
/* Set the pageblock if the isolated page is at least a pageblock */
if (order >= pageblock_order - 1) {
struct page *endpage = page + (1 << order) - 1;
@@ -2005,7 +2007,7 @@ int __isolate_free_page(struct page *page, unsigned int order)
- set_page_owner(page, order, 0);
return 1UL << order;