mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-25 10:03:23 +00:00
feat: debug kernel stack (#1176)
* feat: debug kernel stack Signed-off-by: Godones <chenlinfeng25@outlook.com> * fix: Create guard pages for the kstack through remap Signed-off-by: Godones <chenlinfeng25@outlook.com> * feat(arch/x86_64): 启用内核态写保护功能 添加enable_kernel_wp函数来设置CR0的WP位,防止内核错误写入只读页面 Signed-off-by: longjin <longjin@DragonOS.org> * fix(x86_64/mm): 在内核地址错误处理中添加RIP寄存器信息 Signed-off-by: longjin <longjin@DragonOS.org> * fix: Fixed the error introduced by enabling WP flag on x86 Restore accidentally deleted functions. Signed-off-by: Godones <chenlinfeng25@outlook.com> * refactor: 移除kstack_protect默认特性并优化内存管理 - 从default特性中移除kstack_protect - 为X86_64MMBootstrapInfo添加kernel_rodata_start字段 - 调整内核页标志对rodata区域的判断逻辑 Signed-off-by: longjin <longjin@DragonOS.org> * fix(mm): 解决加载二进制文件到用户空间的时候,忘记关闭wp的问题 Signed-off-by: longjin <longjin@DragonOS.org> * fix Signed-off-by: longjin <longjin@DragonOS.org> --------- Signed-off-by: Godones <chenlinfeng25@outlook.com> Signed-off-by: longjin <longjin@DragonOS.org> Co-authored-by: longjin <longjin@DragonOS.org>
This commit is contained in:
@ -137,6 +137,10 @@ impl MemoryManagementArch for LoongArch64MMArch {
|
||||
fn make_entry(paddr: crate::mm::PhysAddr, page_flags: usize) -> usize {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn enable_kernel_wp() {}
|
||||
|
||||
fn disable_kernel_wp() {}
|
||||
}
|
||||
|
||||
/// 获取内核地址默认的页面标志
|
||||
|
@ -284,6 +284,10 @@ impl MemoryManagementArch for RiscV64MMArch {
|
||||
const PAGE_READONLY_EXEC: usize = 0;
|
||||
|
||||
const PROTECTION_MAP: [EntryFlags<MMArch>; 16] = protection_map();
|
||||
|
||||
fn enable_kernel_wp() {}
|
||||
|
||||
fn disable_kernel_wp() {}
|
||||
}
|
||||
|
||||
const fn protection_map() -> [EntryFlags<MMArch>; 16] {
|
||||
|
@ -149,18 +149,37 @@ impl X86_64MMArch {
|
||||
/// - `error_code`: 错误标志
|
||||
/// - `address`: 发生缺页异常的虚拟地址
|
||||
pub fn do_kern_addr_fault(
|
||||
_regs: &'static TrapFrame,
|
||||
regs: &'static TrapFrame,
|
||||
error_code: X86PfErrorCode,
|
||||
address: VirtAddr,
|
||||
) {
|
||||
unsafe { crate::debug::traceback::lookup_kallsyms(regs.rip, 0xff) };
|
||||
let pcb = crate::process::ProcessManager::current_pcb();
|
||||
let kstack_guard_addr = pcb.kernel_stack().guard_page_address();
|
||||
if let Some(guard_page) = kstack_guard_addr {
|
||||
let guard_page_size = pcb.kernel_stack().guard_page_size().unwrap();
|
||||
if address.data() >= guard_page.data()
|
||||
&& address.data() < guard_page.data() + guard_page_size
|
||||
{
|
||||
// 发生在内核栈保护页上
|
||||
error!(
|
||||
"kernel stack guard page fault at {:#x}, guard page range: {:#x} - {:#x}",
|
||||
address.data(),
|
||||
guard_page.data(),
|
||||
guard_page.data() + guard_page_size
|
||||
);
|
||||
}
|
||||
}
|
||||
panic!(
|
||||
"do_kern_addr_fault has not yet been implemented,
|
||||
fault address: {:#x},
|
||||
fault address: {:#x},
|
||||
rip: {:#x},
|
||||
error_code: {:#b},
|
||||
pid: {}\n",
|
||||
address.data(),
|
||||
regs.rip,
|
||||
error_code,
|
||||
crate::process::ProcessManager::current_pid().data()
|
||||
pcb.pid().data()
|
||||
);
|
||||
//TODO https://code.dragonos.org.cn/xref/linux-6.6.21/arch/x86/mm/fault.c#do_kern_addr_fault
|
||||
}
|
||||
|
@ -42,12 +42,14 @@ static mut INITIAL_CR3_VALUE: PhysAddr = PhysAddr::new(0);
|
||||
|
||||
static INNER_ALLOCATOR: SpinLock<Option<BuddyAllocator<MMArch>>> = SpinLock::new(None);
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct X86_64MMBootstrapInfo {
|
||||
kernel_load_base_paddr: usize,
|
||||
kernel_code_start: usize,
|
||||
kernel_code_end: usize,
|
||||
kernel_data_end: usize,
|
||||
kernel_rodata_start: usize,
|
||||
kernel_rodata_end: usize,
|
||||
start_brk: usize,
|
||||
}
|
||||
@ -134,6 +136,7 @@ impl MemoryManagementArch for X86_64MMArch {
|
||||
fn _text();
|
||||
fn _etext();
|
||||
fn _edata();
|
||||
fn _rodata();
|
||||
fn _erodata();
|
||||
fn _end();
|
||||
fn _default_kernel_load_base();
|
||||
@ -146,6 +149,7 @@ impl MemoryManagementArch for X86_64MMArch {
|
||||
kernel_code_start: _text as usize,
|
||||
kernel_code_end: _etext as usize,
|
||||
kernel_data_end: _edata as usize,
|
||||
kernel_rodata_start: _rodata as usize,
|
||||
kernel_rodata_end: _erodata as usize,
|
||||
start_brk: _end as usize,
|
||||
};
|
||||
@ -158,15 +162,14 @@ impl MemoryManagementArch for X86_64MMArch {
|
||||
boot_callbacks()
|
||||
.early_init_memory_blocks()
|
||||
.expect("init memory area failed");
|
||||
|
||||
debug!("bootstrap info: {:?}", unsafe { BOOTSTRAP_MM_INFO });
|
||||
debug!("bootstrap info: {:#x?}", unsafe { BOOTSTRAP_MM_INFO });
|
||||
debug!("phys[0]=virt[0x{:x}]", unsafe {
|
||||
MMArch::phys_2_virt(PhysAddr::new(0)).unwrap().data()
|
||||
});
|
||||
|
||||
// 初始化内存管理器
|
||||
unsafe { allocator_init() };
|
||||
|
||||
Self::enable_kernel_wp();
|
||||
send_to_default_serial8250_port("x86 64 mm init done\n\0".as_bytes());
|
||||
}
|
||||
|
||||
@ -366,10 +369,35 @@ impl MemoryManagementArch for X86_64MMArch {
|
||||
const PAGE_WRITE: usize = 0;
|
||||
const PAGE_WRITE_EXEC: usize = 0;
|
||||
const PAGE_EXEC: usize = 0;
|
||||
|
||||
/// 启用 内核态的 Write Protect
|
||||
/// 这样即使在内核态,CPU也会检查页面的写保护位
|
||||
/// 防止内核错误地写入只读页面
|
||||
fn enable_kernel_wp() {
|
||||
unsafe {
|
||||
use x86::controlregs::{cr0, cr0_write, Cr0};
|
||||
let mut cr0_val = cr0();
|
||||
cr0_val.insert(Cr0::CR0_WRITE_PROTECT);
|
||||
cr0_write(cr0_val);
|
||||
// log::debug!("CR0.WP bit enabled for kernel write protection");
|
||||
}
|
||||
}
|
||||
|
||||
/// 禁用 内核态的 Write Protect
|
||||
fn disable_kernel_wp() {
|
||||
unsafe {
|
||||
use x86::controlregs::{cr0, cr0_write, Cr0};
|
||||
let mut cr0_val = cr0();
|
||||
cr0_val.remove(Cr0::CR0_WRITE_PROTECT);
|
||||
cr0_write(cr0_val);
|
||||
// log::debug!("CR0.WP bit disabled for kernel write protection");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 获取保护标志的映射表
|
||||
///
|
||||
/// 参考: https://code.dragonos.org.cn/xref/linux-6.6.21/arch/x86/mm/pgprot.c#8
|
||||
///
|
||||
/// ## 返回值
|
||||
/// - `[usize; 16]`: 长度为16的映射表
|
||||
@ -681,7 +709,7 @@ pub unsafe fn kernel_page_flags<A: MemoryManagementArch>(virt: VirtAddr) -> Entr
|
||||
if virt.data() >= info.kernel_code_start && virt.data() < info.kernel_code_end {
|
||||
// Remap kernel code execute
|
||||
return EntryFlags::new().set_execute(true).set_write(true);
|
||||
} else if virt.data() >= info.kernel_data_end && virt.data() < info.kernel_rodata_end {
|
||||
} else if virt.data() >= info.kernel_rodata_start && virt.data() < info.kernel_rodata_end {
|
||||
// Remap kernel rodata read only
|
||||
return EntryFlags::new().set_execute(true);
|
||||
} else {
|
||||
|
Reference in New Issue
Block a user