summaryrefslogtreecommitdiffstats
path: root/kernel/kexec.c
diff options
context:
space:
mode:
authorZhang Yanfei <zhangyanfei@cn.fujitsu.com>2013-02-28 02:03:29 +0100
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-28 04:10:12 +0100
commitb92e7e0daed31389ff5ad9f558ef1284c846f6ee (patch)
tree33ba2fe02e93a4af156f6425ac6dd0c5355b1980 /kernel/kexec.c
parentkexec: prevent double free on image allocation failure (diff)
downloadlinux-b92e7e0daed31389ff5ad9f558ef1284c846f6ee.tar.xz
linux-b92e7e0daed31389ff5ad9f558ef1284c846f6ee.zip
kexec: fix memory leak in function kimage_normal_alloc
If kimage_normal_alloc() fails to alloc pages for image->swap_page, it should call kimage_free_page_list() to free allocated pages in image->control_pages list before it frees image. Signed-off-by: Zhang Yanfei <zhangyanfei@cn.fujitsu.com> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Sasha Levin <sasha.levin@oracle.com> Reviewed-by: Simon Horman <horms@verge.net.au> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to '')
-rw-r--r--kernel/kexec.c18
1 files changed, 10 insertions, 8 deletions
diff --git a/kernel/kexec.c b/kernel/kexec.c
index 855bfbbf4048..6b7455e3c96b 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -229,6 +229,8 @@ out:
}
+static void kimage_free_page_list(struct list_head *list);
+
static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry,
unsigned long nr_segments,
struct kexec_segment __user *segments)
@@ -252,22 +254,22 @@ static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry,
get_order(KEXEC_CONTROL_PAGE_SIZE));
if (!image->control_code_page) {
printk(KERN_ERR "Could not allocate control_code_buffer\n");
- goto out;
+ goto out_free;
}
image->swap_page = kimage_alloc_control_pages(image, 0);
if (!image->swap_page) {
printk(KERN_ERR "Could not allocate swap buffer\n");
- goto out;
+ goto out_free;
}
- result = 0;
- out:
- if (result == 0)
- *rimage = image;
- else
- kfree(image);
+ *rimage = image;
+ return 0;
+out_free:
+ kimage_free_page_list(&image->control_pages);
+ kfree(image);
+out:
return result;
}