kexec: copy only happens before uchunk goes to zero
When loading segments, ubytes is <= mbytes. When ubytes is exhausted, there could be remaining mbytes. Then in the while loop, the buf pointer advancing with mchunk will causing meaningless reading even though it doesn't harm. So let's change to make sure that all of the copying and the rest only happens before uchunk goes to zero. Link: https://lkml.kernel.org/r/20240222092119.5602-1-gaoshanliukou@163.com Signed-off-by: yang.zhang <yang.zhang@hexintek.com> Acked-by: Baoquan He <bhe@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
a436184e3b
commit
4bb7be96fc
@ -800,22 +800,24 @@ static int kimage_load_normal_segment(struct kimage *image,
|
||||
PAGE_SIZE - (maddr & ~PAGE_MASK));
|
||||
uchunk = min(ubytes, mchunk);
|
||||
|
||||
/* For file based kexec, source pages are in kernel memory */
|
||||
if (image->file_mode)
|
||||
memcpy(ptr, kbuf, uchunk);
|
||||
else
|
||||
result = copy_from_user(ptr, buf, uchunk);
|
||||
if (uchunk) {
|
||||
/* For file based kexec, source pages are in kernel memory */
|
||||
if (image->file_mode)
|
||||
memcpy(ptr, kbuf, uchunk);
|
||||
else
|
||||
result = copy_from_user(ptr, buf, uchunk);
|
||||
ubytes -= uchunk;
|
||||
if (image->file_mode)
|
||||
kbuf += uchunk;
|
||||
else
|
||||
buf += uchunk;
|
||||
}
|
||||
kunmap_local(ptr);
|
||||
if (result) {
|
||||
result = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
ubytes -= uchunk;
|
||||
maddr += mchunk;
|
||||
if (image->file_mode)
|
||||
kbuf += mchunk;
|
||||
else
|
||||
buf += mchunk;
|
||||
mbytes -= mchunk;
|
||||
|
||||
cond_resched();
|
||||
@ -866,11 +868,18 @@ static int kimage_load_crash_segment(struct kimage *image,
|
||||
memset(ptr + uchunk, 0, mchunk - uchunk);
|
||||
}
|
||||
|
||||
/* For file based kexec, source pages are in kernel memory */
|
||||
if (image->file_mode)
|
||||
memcpy(ptr, kbuf, uchunk);
|
||||
else
|
||||
result = copy_from_user(ptr, buf, uchunk);
|
||||
if (uchunk) {
|
||||
/* For file based kexec, source pages are in kernel memory */
|
||||
if (image->file_mode)
|
||||
memcpy(ptr, kbuf, uchunk);
|
||||
else
|
||||
result = copy_from_user(ptr, buf, uchunk);
|
||||
ubytes -= uchunk;
|
||||
if (image->file_mode)
|
||||
kbuf += uchunk;
|
||||
else
|
||||
buf += uchunk;
|
||||
}
|
||||
kexec_flush_icache_page(page);
|
||||
kunmap_local(ptr);
|
||||
arch_kexec_pre_free_pages(page_address(page), 1);
|
||||
@ -878,12 +887,7 @@ static int kimage_load_crash_segment(struct kimage *image,
|
||||
result = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
ubytes -= uchunk;
|
||||
maddr += mchunk;
|
||||
if (image->file_mode)
|
||||
kbuf += mchunk;
|
||||
else
|
||||
buf += mchunk;
|
||||
mbytes -= mchunk;
|
||||
|
||||
cond_resched();
|
||||
|
Loading…
Reference in New Issue
Block a user