mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-01 06:33:07 +00:00
Revert "PM / Hibernate: Iterate over set bits instead of PFNs in swsusp_free()"
Revert commit6efde38f07
(PM / Hibernate: Iterate over set bits instead of PFNs in swsusp_free()) that introduced a NULL pointer dereference during system resume from hibernation: BUG: unable to handle kernel NULL pointer dereference at (null) IP: [<ffffffff810a8cc1>] swsusp_free+0x21/0x190 PGD b39c2067 PUD b39c1067 PMD 0 Oops: 0000 [#1] SMP Modules linked in: <irrelevant list of modules> CPU: 1 PID: 4898 Comm: s2disk Tainted: G C 3.17-rc5-amd64 #1 Debian 3.17~rc5-1~exp1 Hardware name: LENOVO 2776LEG/2776LEG, BIOS 6EET55WW (3.15 ) 12/19/2011 task: ffff88023155ea40 ti: ffff8800b3b14000 task.ti: ffff8800b3b14000 RIP: 0010:[<ffffffff810a8cc1>] [<ffffffff810a8cc1>] swsusp_free+0x21/0x190 RSP: 0018:ffff8800b3b17ea8 EFLAGS: 00010246 RAX: 0000000000000000 RBX: ffff8800b39bab00 RCX: 0000000000000001 RDX: ffff8800b39bab10 RSI: ffff8800b39bab00 RDI: 0000000000000000 RBP: 0000000000000010 R08: 0000000000000000 R09: 0000000000000000 R10: ffff8800b39bab10 R11: 0000000000000246 R12: ffffea0000000000 R13: ffff880232f485a0 R14: ffff88023ac27cd8 R15: ffff880232927590 FS: 00007f406d83b700(0000) GS:ffff88023bc80000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 0000000000000000 CR3: 00000000b3a62000 CR4: 00000000000007e0 Stack: ffff8800b39bab00 0000000000000010 ffff880232927590 ffffffff810acb4a ffff8800b39bab00 ffffffff811a955a ffff8800b39bab10 0000000000000000 ffff88023155f098 ffffffff81a6b8c0 ffff88023155ea40 0000000000000007 Call Trace: [<ffffffff810acb4a>] ? snapshot_release+0x2a/0xb0 [<ffffffff811a955a>] ? __fput+0xca/0x1d0 [<ffffffff81080627>] ? task_work_run+0x97/0xd0 [<ffffffff81012d89>] ? do_notify_resume+0x69/0xa0 [<ffffffff8151452a>] ? int_signal+0x12/0x17 Code: 66 2e 0f 1f 84 00 00 00 00 00 66 66 66 66 90 41 54 48 8b 05 ba 62 9c 00 49 bc 00 00 00 00 00 ea ff ff 48 8b 3d a1 62 9c 00 55 53 <48> 8b 10 48 89 50 18 48 8b 52 20 48 c7 40 28 00 00 00 00 c7 40 RIP [<ffffffff810a8cc1>] swsusp_free+0x21/0x190 RSP <ffff8800b3b17ea8> CR2: 0000000000000000 ---[ end trace f02be86a1ec0cccb ]--- due to forbidden_pages_map being NULL in swsusp_free(). Fixes:6efde38f07
"PM / Hibernate: Iterate over set bits instead of PFNs in swsusp_free()" Reported-by: Bjørn Mork <bjorn@mork.no> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
parent
0f33be009b
commit
5c4dd348af
1 changed files with 14 additions and 34 deletions
|
@ -725,14 +725,6 @@ static void memory_bm_clear_bit(struct memory_bitmap *bm, unsigned long pfn)
|
|||
clear_bit(bit, addr);
|
||||
}
|
||||
|
||||
static void memory_bm_clear_current(struct memory_bitmap *bm)
|
||||
{
|
||||
int bit;
|
||||
|
||||
bit = max(bm->cur.node_bit - 1, 0);
|
||||
clear_bit(bit, bm->cur.node->data);
|
||||
}
|
||||
|
||||
static int memory_bm_test_bit(struct memory_bitmap *bm, unsigned long pfn)
|
||||
{
|
||||
void *addr;
|
||||
|
@ -1341,35 +1333,23 @@ static struct memory_bitmap copy_bm;
|
|||
|
||||
void swsusp_free(void)
|
||||
{
|
||||
unsigned long fb_pfn, fr_pfn;
|
||||
struct zone *zone;
|
||||
unsigned long pfn, max_zone_pfn;
|
||||
|
||||
memory_bm_position_reset(forbidden_pages_map);
|
||||
memory_bm_position_reset(free_pages_map);
|
||||
for_each_populated_zone(zone) {
|
||||
max_zone_pfn = zone_end_pfn(zone);
|
||||
for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++)
|
||||
if (pfn_valid(pfn)) {
|
||||
struct page *page = pfn_to_page(pfn);
|
||||
|
||||
loop:
|
||||
fr_pfn = memory_bm_next_pfn(free_pages_map);
|
||||
fb_pfn = memory_bm_next_pfn(forbidden_pages_map);
|
||||
|
||||
/*
|
||||
* Find the next bit set in both bitmaps. This is guaranteed to
|
||||
* terminate when fb_pfn == fr_pfn == BM_END_OF_MAP.
|
||||
*/
|
||||
do {
|
||||
if (fb_pfn < fr_pfn)
|
||||
fb_pfn = memory_bm_next_pfn(forbidden_pages_map);
|
||||
if (fr_pfn < fb_pfn)
|
||||
fr_pfn = memory_bm_next_pfn(free_pages_map);
|
||||
} while (fb_pfn != fr_pfn);
|
||||
|
||||
if (fr_pfn != BM_END_OF_MAP && pfn_valid(fr_pfn)) {
|
||||
struct page *page = pfn_to_page(fr_pfn);
|
||||
|
||||
memory_bm_clear_current(forbidden_pages_map);
|
||||
memory_bm_clear_current(free_pages_map);
|
||||
if (swsusp_page_is_forbidden(page) &&
|
||||
swsusp_page_is_free(page)) {
|
||||
swsusp_unset_page_forbidden(page);
|
||||
swsusp_unset_page_free(page);
|
||||
__free_page(page);
|
||||
goto loop;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
nr_copy_pages = 0;
|
||||
nr_meta_pages = 0;
|
||||
restore_pblist = NULL;
|
||||
|
|
Loading…
Reference in a new issue