[PATCH] LoongArch: kexec: Fix address space mismatch in command line lookup

From: George Guo

Date: Fri Jun 26 2026 - 06:39:18 EST


From: George Guo <guodongtai@xxxxxxxxxx>

When searching the loaded segments for the "kexec" command line marker,
the kexec_load(2) path (file_mode == 0) passes the user-space segment
buffer straight to strncmp() through a bogus (char __user *) cast. This
dereferences a user pointer in kernel context, which is wrong and is
flagged by sparse:

arch/loongarch/kernel/machine_kexec.c:84:51: sparse: incorrect type in
argument 2 (different address spaces) @@ expected char const * @@ got
char [noderef] __user *

Copy the marker-sized prefix of each segment into a small on-stack
buffer with copy_from_user() before comparing, and skip segments that
fault. The subsequent copy_from_user() that stages the full command line
into the safe area is left unchanged.

Fixes: 4a03b2ac06a5 ("LoongArch: Add kexec support")
Reported-by: kernel test robot <lkp@xxxxxxxxx>
Closes: https://lore.kernel.org/oe-kbuild-all/202605051639.aEPioXdD-lkp@xxxxxxxxx/
Co-developed-by: Kexin Liu <liukexin@xxxxxxxxxx>
Signed-off-by: Kexin Liu <liukexin@xxxxxxxxxx>
Signed-off-by: George Guo <guodongtai@xxxxxxxxxx>
---
arch/loongarch/kernel/machine_kexec.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/arch/loongarch/kernel/machine_kexec.c b/arch/loongarch/kernel/machine_kexec.c
index d7fafda1d541..6f563175ddbf 100644
--- a/arch/loongarch/kernel/machine_kexec.c
+++ b/arch/loongarch/kernel/machine_kexec.c
@@ -42,7 +42,7 @@ static unsigned long first_ind_entry;
int machine_kexec_prepare(struct kimage *kimage)
{
int i;
- char *bootloader = "kexec";
+ static const char bootloader[] = "kexec";
void *cmdline_ptr = (void *)KEXEC_CMDLINE_ADDR;

kimage->arch.efi_boot = fw_arg0;
@@ -57,9 +57,13 @@ int machine_kexec_prepare(struct kimage *kimage)
strlen((char *)kimage->arch.cmdline_ptr) + 1);
kimage->arch.cmdline_ptr = (unsigned long)KEXEC_CMDLINE_ADDR;
} else {
+ char tmp[sizeof(bootloader)];
+
/* Find the command line */
for (i = 0; i < kimage->nr_segments; i++) {
- if (!strncmp(bootloader, (char __user *)kimage->segment[i].buf, strlen(bootloader))) {
+ if (copy_from_user(tmp, kimage->segment[i].buf, strlen(bootloader)))
+ continue;
+ if (!strncmp(bootloader, tmp, strlen(bootloader))) {
if (!copy_from_user(cmdline_ptr, kimage->segment[i].buf, COMMAND_LINE_SIZE))
kimage->arch.cmdline_ptr = (unsigned long)cmdline_ptr;
break;
--
2.25.1