Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

yang.zhang and committed by
Andrew Morton
4bb7be96 a436184e

+24 -20
+24 -20
kernel/kexec_core.c
··· 800 800 PAGE_SIZE - (maddr & ~PAGE_MASK)); 801 801 uchunk = min(ubytes, mchunk); 802 802 803 - /* For file based kexec, source pages are in kernel memory */ 804 - if (image->file_mode) 805 - memcpy(ptr, kbuf, uchunk); 806 - else 807 - result = copy_from_user(ptr, buf, uchunk); 803 + if (uchunk) { 804 + /* For file based kexec, source pages are in kernel memory */ 805 + if (image->file_mode) 806 + memcpy(ptr, kbuf, uchunk); 807 + else 808 + result = copy_from_user(ptr, buf, uchunk); 809 + ubytes -= uchunk; 810 + if (image->file_mode) 811 + kbuf += uchunk; 812 + else 813 + buf += uchunk; 814 + } 808 815 kunmap_local(ptr); 809 816 if (result) { 810 817 result = -EFAULT; 811 818 goto out; 812 819 } 813 - ubytes -= uchunk; 814 820 maddr += mchunk; 815 - if (image->file_mode) 816 - kbuf += mchunk; 817 - else 818 - buf += mchunk; 819 821 mbytes -= mchunk; 820 822 821 823 cond_resched(); ··· 868 866 memset(ptr + uchunk, 0, mchunk - uchunk); 869 867 } 870 868 871 - /* For file based kexec, source pages are in kernel memory */ 872 - if (image->file_mode) 873 - memcpy(ptr, kbuf, uchunk); 874 - else 875 - result = copy_from_user(ptr, buf, uchunk); 869 + if (uchunk) { 870 + /* For file based kexec, source pages are in kernel memory */ 871 + if (image->file_mode) 872 + memcpy(ptr, kbuf, uchunk); 873 + else 874 + result = copy_from_user(ptr, buf, uchunk); 875 + ubytes -= uchunk; 876 + if (image->file_mode) 877 + kbuf += uchunk; 878 + else 879 + buf += uchunk; 880 + } 876 881 kexec_flush_icache_page(page); 877 882 kunmap_local(ptr); 878 883 arch_kexec_pre_free_pages(page_address(page), 1); ··· 887 878 result = -EFAULT; 888 879 goto out; 889 880 } 890 - ubytes -= uchunk; 891 881 maddr += mchunk; 892 - if (image->file_mode) 893 - kbuf += mchunk; 894 - else 895 - buf += mchunk; 896 882 mbytes -= mchunk; 897 883 898 884 cond_resched();