From: Vivek Goyal <vgoyal@redhat.com>
To: linux-kernel@vger.kernel.org, kexec@lists.infradead.org
Cc: mjg59@srcf.ucam.org, greg@kroah.com, ebiederm@xmission.com,
Vivek Goyal <vgoyal@redhat.com>,
hpa@zytor.com
Subject: [PATCH 2/6] kexec: Move segment verification code in a separate function
Date: Wed, 20 Nov 2013 12:50:47 -0500 [thread overview]
Message-ID: <1384969851-7251-3-git-send-email-vgoyal@redhat.com> (raw)
In-Reply-To: <1384969851-7251-1-git-send-email-vgoyal@redhat.com>
Previously do_kimage_alloc() will allocate a kimage structure, copy
segment list from user space and then do the segment list sanity verification.
Break down this function in 3 parts. do_kimage_alloc_init() to do actual
allocation and basic initialization of kimage structure.
copy_user_segment_list() to copy segment list from user space and
sanity_check_segment_list() to verify the sanity of segment list as passed
by user space.
In later patches, I need to only allocate kimage and not copy segment
list from user space. So breaking down in smaller functions enables
re-use of code at other places.
Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
---
kernel/kexec.c | 182 +++++++++++++++++++++++++++++++-------------------------
1 files changed, 101 insertions(+), 81 deletions(-)
diff --git a/kernel/kexec.c b/kernel/kexec.c
index 490afc0..6238927 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -120,45 +120,27 @@ static struct page *kimage_alloc_page(struct kimage *image,
gfp_t gfp_mask,
unsigned long dest);
-static int do_kimage_alloc(struct kimage **rimage, unsigned long entry,
- unsigned long nr_segments,
- struct kexec_segment __user *segments)
+static int copy_user_segment_list(struct kimage *image,
+ unsigned long nr_segments,
+ struct kexec_segment __user *segments)
{
+ int ret;
size_t segment_bytes;
- struct kimage *image;
- unsigned long i;
- int result;
-
- /* Allocate a controlling structure */
- result = -ENOMEM;
- image = kzalloc(sizeof(*image), GFP_KERNEL);
- if (!image)
- goto out;
-
- image->head = 0;
- image->entry = &image->head;
- image->last_entry = &image->head;
- image->control_page = ~0; /* By default this does not apply */
- image->start = entry;
- image->type = KEXEC_TYPE_DEFAULT;
-
- /* Initialize the list of control pages */
- INIT_LIST_HEAD(&image->control_pages);
-
- /* Initialize the list of destination pages */
- INIT_LIST_HEAD(&image->dest_pages);
-
- /* Initialize the list of unusable pages */
- INIT_LIST_HEAD(&image->unuseable_pages);
/* Read in the segments */
image->nr_segments = nr_segments;
segment_bytes = nr_segments * sizeof(*segments);
- result = copy_from_user(image->segment, segments, segment_bytes);
- if (result) {
- result = -EFAULT;
- goto out;
- }
+ ret = copy_from_user(image->segment, segments, segment_bytes);
+ if (ret)
+ ret = -EFAULT;
+
+ return ret;
+}
+
+static int sanity_check_segment_list(struct kimage *image)
+{
+ int result, i;
+ unsigned long nr_segments = image->nr_segments;
/*
* Verify we have good destination addresses. The caller is
@@ -180,9 +162,9 @@ static int do_kimage_alloc(struct kimage **rimage, unsigned long entry,
mstart = image->segment[i].mem;
mend = mstart + image->segment[i].memsz;
if ((mstart & ~PAGE_MASK) || (mend & ~PAGE_MASK))
- goto out;
+ return result;
if (mend >= KEXEC_DESTINATION_MEMORY_LIMIT)
- goto out;
+ return result;
}
/* Verify our destination addresses do not overlap.
@@ -203,7 +185,7 @@ static int do_kimage_alloc(struct kimage **rimage, unsigned long entry,
pend = pstart + image->segment[j].memsz;
/* Do the segments overlap ? */
if ((mend > pstart) && (mstart < pend))
- goto out;
+ return result;
}
}
@@ -215,18 +197,61 @@ static int do_kimage_alloc(struct kimage **rimage, unsigned long entry,
result = -EINVAL;
for (i = 0; i < nr_segments; i++) {
if (image->segment[i].bufsz > image->segment[i].memsz)
- goto out;
+ return result;
}
- result = 0;
-out:
- if (result == 0)
- *rimage = image;
- else
- kfree(image);
+ /*
+ * Verify we have good destination addresses. Normally
+ * the caller is responsible for making certain we don't
+ * attempt to load the new image into invalid or reserved
+ * areas of RAM. But crash kernels are preloaded into a
+ * reserved area of ram. We must ensure the addresses
+ * are in the reserved area otherwise preloading the
+ * kernel could corrupt things.
+ */
- return result;
+ if (image->type == KEXEC_TYPE_CRASH) {
+ result = -EADDRNOTAVAIL;
+ for (i = 0; i < nr_segments; i++) {
+ unsigned long mstart, mend;
+ mstart = image->segment[i].mem;
+ mend = mstart + image->segment[i].memsz - 1;
+ /* Ensure we are within the crash kernel limits */
+ if ((mstart < crashk_res.start) ||
+ (mend > crashk_res.end))
+ return result;
+ }
+ }
+
+ return 0;
+}
+
+static struct kimage *do_kimage_alloc_init(void)
+{
+ struct kimage *image;
+
+ /* Allocate a controlling structure */
+ image = kzalloc(sizeof(*image), GFP_KERNEL);
+ if (!image)
+ return NULL;
+
+ image->head = 0;
+ image->entry = &image->head;
+ image->last_entry = &image->head;
+ image->control_page = ~0; /* By default this does not apply */
+ image->type = KEXEC_TYPE_DEFAULT;
+
+ /* Initialize the list of control pages */
+ INIT_LIST_HEAD(&image->control_pages);
+
+ /* Initialize the list of destination pages */
+ INIT_LIST_HEAD(&image->dest_pages);
+
+ /* Initialize the list of unusable pages */
+ INIT_LIST_HEAD(&image->unuseable_pages);
+
+ return image;
}
static void kimage_free_page_list(struct list_head *list);
@@ -239,10 +264,19 @@ static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry,
struct kimage *image;
/* Allocate and initialize a controlling structure */
- image = NULL;
- result = do_kimage_alloc(&image, entry, nr_segments, segments);
+ image = do_kimage_alloc_init();
+ if (!image)
+ return -ENOMEM;
+
+ image->start = entry;
+
+ result = copy_user_segment_list(image, nr_segments, segments);
if (result)
- goto out;
+ goto out_free_image;
+
+ result = sanity_check_segment_list(image);
+ if (result)
+ goto out_free_image;
/*
* Find a location for the control code buffer, and add it
@@ -254,22 +288,23 @@ 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_free;
+ goto out_free_image;
}
image->swap_page = kimage_alloc_control_pages(image, 0);
if (!image->swap_page) {
printk(KERN_ERR "Could not allocate swap buffer\n");
- goto out_free;
+ goto out_free_control_pages;
}
*rimage = image;
return 0;
-out_free:
+
+out_free_control_pages:
kimage_free_page_list(&image->control_pages);
+out_free_image:
kfree(image);
-out:
return result;
}
@@ -279,19 +314,17 @@ static int kimage_crash_alloc(struct kimage **rimage, unsigned long entry,
{
int result;
struct kimage *image;
- unsigned long i;
- image = NULL;
/* Verify we have a valid entry point */
- if ((entry < crashk_res.start) || (entry > crashk_res.end)) {
- result = -EADDRNOTAVAIL;
- goto out;
- }
+ if ((entry < crashk_res.start) || (entry > crashk_res.end))
+ return -EADDRNOTAVAIL;
/* Allocate and initialize a controlling structure */
- result = do_kimage_alloc(&image, entry, nr_segments, segments);
- if (result)
- goto out;
+ image = do_kimage_alloc_init();
+ if (!image)
+ return -ENOMEM;
+
+ image->start = entry;
/* Enable the special crash kernel control page
* allocation policy.
@@ -299,25 +332,13 @@ static int kimage_crash_alloc(struct kimage **rimage, unsigned long entry,
image->control_page = crashk_res.start;
image->type = KEXEC_TYPE_CRASH;
- /*
- * Verify we have good destination addresses. Normally
- * the caller is responsible for making certain we don't
- * attempt to load the new image into invalid or reserved
- * areas of RAM. But crash kernels are preloaded into a
- * reserved area of ram. We must ensure the addresses
- * are in the reserved area otherwise preloading the
- * kernel could corrupt things.
- */
- result = -EADDRNOTAVAIL;
- for (i = 0; i < nr_segments; i++) {
- unsigned long mstart, mend;
+ result = copy_user_segment_list(image, nr_segments, segments);
+ if (result)
+ goto out_free_image;
- mstart = image->segment[i].mem;
- mend = mstart + image->segment[i].memsz - 1;
- /* Ensure we are within the crash kernel limits */
- if ((mstart < crashk_res.start) || (mend > crashk_res.end))
- goto out_free;
- }
+ result = sanity_check_segment_list(image);
+ if (result)
+ goto out_free_image;
/*
* Find a location for the control code buffer, and add
@@ -329,15 +350,14 @@ static int kimage_crash_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_free;
+ goto out_free_image;
}
*rimage = image;
return 0;
-out_free:
+out_free_image:
kfree(image);
-out:
return result;
}
--
1.7.7.6
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
next prev parent reply other threads:[~2013-11-20 17:52 UTC|newest]
Thread overview: 90+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-11-20 17:50 [PATCH 0/6] kexec: A new system call to allow in kernel loading Vivek Goyal
2013-11-20 17:50 ` [PATCH 1/6] kexec: Export vmcoreinfo note size properly Vivek Goyal
2013-11-21 18:59 ` Greg KH
2013-11-21 19:08 ` Vivek Goyal
2013-11-20 17:50 ` Vivek Goyal [this message]
2013-11-20 17:50 ` [PATCH 3/6] resource: Provide new functions to walk through resources Vivek Goyal
2013-11-20 17:50 ` [PATCH 4/6] kexec: A new system call, kexec_file_load, for in kernel kexec Vivek Goyal
2013-11-21 19:03 ` Greg KH
2013-11-21 19:06 ` Matthew Garrett
2013-11-21 19:13 ` Vivek Goyal
2013-11-21 19:19 ` Matthew Garrett
2013-11-21 19:24 ` Vivek Goyal
2013-11-22 18:57 ` Vivek Goyal
2013-11-23 3:39 ` Eric W. Biederman
2013-11-25 16:39 ` Vivek Goyal
2013-11-26 12:23 ` Eric W. Biederman
2013-11-26 14:27 ` Vivek Goyal
2013-12-19 12:54 ` Torsten Duwe
2013-12-20 14:19 ` Vivek Goyal
2013-12-20 23:11 ` Eric W. Biederman
2013-12-20 23:20 ` Kees Cook
2013-12-21 11:38 ` Torsten Duwe
2014-01-02 20:39 ` Vivek Goyal
2014-01-02 20:56 ` H. Peter Anvin
2014-01-06 21:33 ` Josh Boyer
2014-01-07 4:22 ` H. Peter Anvin
2013-12-20 23:20 ` H. Peter Anvin
2013-12-21 1:32 ` Eric W. Biederman
2013-12-21 3:32 ` H. Peter Anvin
2013-12-21 12:15 ` Torsten Duwe
2013-11-21 19:16 ` Vivek Goyal
2013-11-22 1:03 ` Kees Cook
2013-11-22 2:13 ` Vivek Goyal
2013-11-22 20:42 ` Jiri Kosina
2014-01-17 19:17 ` Vivek Goyal
2013-11-29 3:10 ` Baoquan He
2013-12-02 15:27 ` WANG Chao
2013-12-02 15:44 ` Vivek Goyal
2013-12-04 1:35 ` Baoquan He
2013-12-04 17:19 ` Vivek Goyal
2013-12-04 1:56 ` Baoquan He
2013-12-04 8:19 ` Baoquan He
2013-12-04 17:32 ` Vivek Goyal
2013-11-20 17:50 ` [PATCH 5/6] kexec-bzImage: Support for loading bzImage using 64bit entry Vivek Goyal
2013-11-21 19:07 ` Greg KH
2013-11-21 19:21 ` Vivek Goyal
2013-11-22 15:24 ` H. Peter Anvin
2013-11-28 11:35 ` Baoquan He
2013-12-02 15:36 ` Vivek Goyal
2013-11-20 17:50 ` [PATCH 6/6] kexec: Support for Kexec on panic using new system call Vivek Goyal
2013-11-28 11:28 ` Baoquan He
2013-12-02 15:30 ` Vivek Goyal
2013-12-04 1:51 ` Baoquan He
2013-12-04 17:20 ` Vivek Goyal
2013-12-04 1:41 ` Baoquan He
2013-12-04 17:19 ` Vivek Goyal
2013-11-21 18:58 ` [PATCH 0/6] kexec: A new system call to allow in kernel loading Greg KH
2013-11-21 19:07 ` Vivek Goyal
2013-11-21 19:46 ` Vivek Goyal
2013-11-21 19:06 ` Geert Uytterhoeven
2013-11-21 19:14 ` Vivek Goyal
2013-11-21 23:07 ` Eric W. Biederman
2013-11-22 1:28 ` H. Peter Anvin
2013-11-22 2:35 ` Vivek Goyal
2013-11-22 2:40 ` H. Peter Anvin
2013-11-22 1:55 ` Vivek Goyal
2013-11-22 9:09 ` Geert Uytterhoeven
2013-11-22 13:30 ` Jiri Kosina
2013-11-22 13:46 ` Vivek Goyal
2013-11-22 13:50 ` Jiri Kosina
2013-11-22 15:33 ` Vivek Goyal
2013-11-22 17:45 ` Kees Cook
2013-11-22 13:43 ` Vivek Goyal
2013-11-22 15:25 ` Geert Uytterhoeven
2013-11-22 15:33 ` Jiri Kosina
2013-11-22 15:57 ` Eric Paris
2013-11-22 16:04 ` Jiri Kosina
2013-11-22 16:08 ` Vivek Goyal
2013-11-22 13:34 ` Eric W. Biederman
2013-11-22 14:19 ` Vivek Goyal
2013-11-22 19:48 ` Greg KH
2013-11-23 3:23 ` Eric W. Biederman
2013-12-04 19:34 ` Vivek Goyal
2013-12-05 4:10 ` Eric W. Biederman
2013-11-25 10:04 ` Michael Holzheu
2013-11-25 15:36 ` Vivek Goyal
2013-11-25 16:15 ` Michael Holzheu
2013-11-22 0:55 ` HATAYAMA Daisuke
2013-11-22 2:03 ` Vivek Goyal
2013-12-03 13:23 ` Baoquan He
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1384969851-7251-3-git-send-email-vgoyal@redhat.com \
--to=vgoyal@redhat.com \
--cc=ebiederm@xmission.com \
--cc=greg@kroah.com \
--cc=hpa@zytor.com \
--cc=kexec@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mjg59@srcf.ucam.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).