From 254b54771cc4c00002f796be65d2885191dca9dc Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 27 Sep 2005 21:45:31 -0700 Subject: [PATCH] swsusp: remove wrong code from data_free The following patch removes some wrong code from the data_free() function in swsusp. This function could only be called if there's an error while writing the suspend image to swap, so it is not triggered easily. However, if triggered, it would probably corrupt some memory. Signed-off-by: Rafael J. Wysocki Acked-by: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/power/swsusp.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'kernel/power/swsusp.c') diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index 1cc9ff25e479..8aef1b49150f 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c @@ -402,15 +402,14 @@ static int write_page(unsigned long addr, swp_entry_t * loc) static void data_free(void) { swp_entry_t entry; - int i; + struct pbe * p; - for (i = 0; i < nr_copy_pages; i++) { - entry = (pagedir_nosave + i)->swap_address; + for_each_pbe(p, pagedir_nosave) { + entry = p->swap_address; if (entry.val) swap_free(entry); else break; - (pagedir_nosave + i)->swap_address = (swp_entry_t){0}; } } -- cgit v1.3.1 From f2d613799af915da1fd78463ba8ec5086a0d6f92 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 27 Sep 2005 21:45:32 -0700 Subject: [PATCH] swsusp: prevent possible memory leak Prevent swsusp from leaking some memory in case of an error in read_pagedir(). It also prevents the BUG_ON() from triggering if there's an error while reading swap. Signed-off-by: Rafael J. Wysocki Acked-by: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/power/swsusp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'kernel/power/swsusp.c') diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index 8aef1b49150f..0dfb24948907 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c @@ -1437,9 +1437,9 @@ static int read_pagedir(struct pbe *pblist) } if (error) - free_page((unsigned long)pblist); - - BUG_ON(i != swsusp_info.pagedir_pages); + free_pagedir(pblist); + else + BUG_ON(i != swsusp_info.pagedir_pages); return error; } -- cgit v1.3.1 From 0f7347c20c410c300be0db4c132945fd02e54110 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 27 Sep 2005 21:45:43 -0700 Subject: [PATCH] swsusp: avoid problems if there are too many pages to save The following patch makes swsusp avoid problems during resume if there are too many pages to save on suspend. It adds a constant that allows us to verify if we are going to save too many pages and implements the check (this is done as early as we can tell that the check will trigger, which is in swsusp_alloc()). Signed-off-by: Rafael J. Wysocki Acked-by: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/power/power.h | 5 ++++- kernel/power/swsusp.c | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'kernel/power/swsusp.c') diff --git a/kernel/power/power.h b/kernel/power/power.h index 9c9167d910dd..6748de23e83c 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -9,6 +9,9 @@ #define SUSPEND_CONSOLE (MAX_NR_CONSOLES-1) #endif +#define MAX_PBES ((PAGE_SIZE - sizeof(struct new_utsname) \ + - 4 - 3*sizeof(unsigned long) - sizeof(int) \ + - sizeof(void *)) / sizeof(swp_entry_t)) struct swsusp_info { struct new_utsname uts; @@ -18,7 +21,7 @@ struct swsusp_info { unsigned long image_pages; unsigned long pagedir_pages; suspend_pagedir_t * suspend_pagedir; - swp_entry_t pagedir[768]; + swp_entry_t pagedir[MAX_PBES]; } __attribute__((aligned(PAGE_SIZE))); diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index 0dfb24948907..acf79ac1cb6d 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c @@ -931,6 +931,10 @@ static int swsusp_alloc(void) if (!enough_swap()) return -ENOSPC; + if (MAX_PBES < nr_copy_pages / PBES_PER_PAGE + + !!(nr_copy_pages % PBES_PER_PAGE)) + return -ENOSPC; + if (!(pagedir_save = alloc_pagedir(nr_copy_pages))) { printk(KERN_ERR "suspend: Allocating pagedir failed.\n"); return -ENOMEM; -- cgit v1.3.1