diff options
| author | George Guo <guodongtai@kylinos.cn> | 2026-07-23 22:27:30 +0800 |
|---|---|---|
| committer | Huacai Chen <chenhuacai@loongson.cn> | 2026-07-23 22:27:30 +0800 |
| commit | 485ed44db5694d8d2e5027f63ad608e705286f30 (patch) | |
| tree | 8a8c6c53805a61c8f9a3cd969fef7a7b46d37376 /arch | |
| parent | 4e8f58620f6717f72f3d88a2c8f25c0c656d0ba7 (diff) | |
LoongArch: Fix address space mismatch in kexec command line lookup
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 *
Here 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.
Cc: stable@vger.kernel.org
Fixes: 4a03b2ac06a5 ("LoongArch: Add kexec support")
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202605051639.aEPioXdD-lkp@intel.com/
Co-developed-by: Kexin Liu <liukexin@kylinos.cn>
Signed-off-by: Kexin Liu <liukexin@kylinos.cn>
Signed-off-by: George Guo <guodongtai@kylinos.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/loongarch/kernel/machine_kexec.c | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/arch/loongarch/kernel/machine_kexec.c b/arch/loongarch/kernel/machine_kexec.c index d7fafda1d541..1883cae93bc3 100644 --- a/arch/loongarch/kernel/machine_kexec.c +++ b/arch/loongarch/kernel/machine_kexec.c @@ -42,6 +42,7 @@ static unsigned long first_ind_entry; int machine_kexec_prepare(struct kimage *kimage) { int i; + char head[8]; char *bootloader = "kexec"; void *cmdline_ptr = (void *)KEXEC_CMDLINE_ADDR; @@ -59,7 +60,9 @@ int machine_kexec_prepare(struct kimage *kimage) } else { /* 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(head, kimage->segment[i].buf, strlen(bootloader))) + continue; + if (!strncmp(bootloader, head, strlen(bootloader))) { if (!copy_from_user(cmdline_ptr, kimage->segment[i].buf, COMMAND_LINE_SIZE)) kimage->arch.cmdline_ptr = (unsigned long)cmdline_ptr; break; |
