@@ -100,6 +100,9 @@ struct kexec_segment {
size_t bufsz;
unsigned long mem;
size_t memsz;
+
+ /* Whether this segment is ignored in the checksum calculation. */
+ bool skip_checksum;
};
#ifdef CONFIG_COMPAT
@@ -151,15 +154,16 @@ struct kexec_file_ops {
/**
* struct kexec_buf - parameters for finding a place for a buffer in memory
- * @image: kexec image in which memory to search.
- * @buffer: Contents which will be copied to the allocated memory.
- * @bufsz: Size of @buffer.
- * @mem: On return will have address of the buffer in memory.
- * @memsz: Size for the buffer in memory.
- * @buf_align: Minimum alignment needed.
- * @buf_min: The buffer can't be placed below this address.
- * @buf_max: The buffer can't be placed above this address.
- * @top_down: Allocate from top of memory.
+ * @image: kexec image in which memory to search.
+ * @buffer: Contents which will be copied to the allocated memory.
+ * @bufsz: Size of @buffer.
+ * @mem: On return will have address of the buffer in memory.
+ * @memsz: Size for the buffer in memory.
+ * @buf_align: Minimum alignment needed.
+ * @buf_min: The buffer can't be placed below this address.
+ * @buf_max: The buffer can't be placed above this address.
+ * @top_down: Allocate from top of memory.
+ * @skip_checksum: Don't verify checksum for this buffer in purgatory.
*/
struct kexec_buf {
struct kimage *image;
@@ -171,6 +175,7 @@ struct kexec_buf {
unsigned long buf_min;
unsigned long buf_max;
bool top_down;
+ bool skip_checksum;
};
int __weak arch_kexec_walk_mem(struct kexec_buf *kbuf,
@@ -658,6 +658,7 @@ int kexec_add_buffer(struct kexec_buf *kbuf)
ksegment->bufsz = kbuf->bufsz;
ksegment->mem = kbuf->mem;
ksegment->memsz = kbuf->memsz;
+ ksegment->skip_checksum = kbuf->skip_checksum;
kbuf->image->nr_segments++;
return 0;
}
@@ -672,7 +673,6 @@ static int kexec_calculate_store_digests(struct kimage *image)
char *digest;
void *zero_buf;
struct kexec_sha_region *sha_regions;
- struct purgatory_info *pi = &image->purgatory_info;
zero_buf = __va(page_to_pfn(ZERO_PAGE(0)) << PAGE_SHIFT);
zero_buf_sz = PAGE_SIZE;
@@ -712,11 +712,7 @@ static int kexec_calculate_store_digests(struct kimage *image)
struct kexec_segment *ksegment;
ksegment = &image->segment[i];
- /*
- * Skip purgatory as it will be modified once we put digest
- * info in purgatory.
- */
- if (ksegment->kbuf == pi->purgatory_buf)
+ if (ksegment->skip_checksum)
continue;
ret = crypto_shash_update(desc, ksegment->kbuf,
@@ -788,7 +784,7 @@ static int __kexec_load_purgatory(struct kimage *image, unsigned long min,
Elf_Shdr *sechdrs = NULL;
struct kexec_buf kbuf = { .image = image, .bufsz = 0, .buf_align = 1,
.buf_min = min, .buf_max = max,
- .top_down = top_down };
+ .top_down = top_down, .skip_checksum = true };
/*
* sechdrs_c points to section headers in purgatory and are read
@@ -893,7 +889,10 @@ static int __kexec_load_purgatory(struct kimage *image, unsigned long min,
if (kbuf.buf_align < bss_align)
kbuf.buf_align = bss_align;
- /* Add buffer to segment list */
+ /*
+ * Add buffer to segment list. Don't checksum the segment as
+ * it will be modified once we put digest info in purgatory.
+ */
ret = kexec_add_buffer(&kbuf);
if (ret)
goto out;