diff options
author | Zhang Yanfei <zhangyanfei@cn.fujitsu.com> | 2013-02-28 02:03:29 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-28 04:10:12 +0100 |
commit | b92e7e0daed31389ff5ad9f558ef1284c846f6ee (patch) | |
tree | 33ba2fe02e93a4af156f6425ac6dd0c5355b1980 /kernel/kexec.c | |
parent | kexec: prevent double free on image allocation failure (diff) | |
download | linux-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 'kernel/kexec.c')
-rw-r--r-- | kernel/kexec.c | 18 |
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; } |