fix(kernel): paging.init 先清 WP 再 MakePTWritable 再置 WP(bootloader 已设 WP=1)
UEFI/bootloader 的 CR0.WP 已是 1(原代码清 WP 正因此),MakePTWritable 在 WP=1 下写只读页表页即 #PF(cr2=0xf8033e0)。改为:清 WP → 放开页表页 → 置 WP=1。
This commit is contained in:
1 parent
56e38c43ea
commit
b1956ea722
1 file changed
+9
-7
@@ -30,14 +30,16 @@ pt: _p | t.CPtr
|
||||
def init(MemmapAddr: t.CUInt64T, MemmapSize: t.CUInt64T):
|
||||
global pml4
|
||||
pml4 = GetCurrentPml4()
|
||||
# 先把所有页表页设为可写(此时 CR0.WP=0,允许写只读页表页):
|
||||
# bootloader 建立的 pml4/pdp/pd/pt 位于 0xf8xxxx 默认只读,而内核运行时
|
||||
# MapPage/clone 需修改页表。若在 WP=1 之后再改页表页自身 → 写只读页 #PF
|
||||
# (ProtectKernelRO 阶段 cr2=0xf8033e0 根因:设大页 W 位时写 pd 页自身)。
|
||||
# bootloader/UEFI 的 CR0.WP 通常已是 1(原代码清 WP 正因此)。页表页
|
||||
# (pml4/pdp/pd/pt,0xf8xxxx)默认只读,而内核运行时 MapPage/clone 需
|
||||
# 修改页表。顺序:先清 WP(允许写只读页表页)→ MakePTWritable 放开
|
||||
# 全部页表页 → 再置 WP=1(此后写只读页即 #PF 暴露越界写源)。
|
||||
c.Asm(f"""
|
||||
mov rax, cr0
|
||||
and rax, ~0x10000
|
||||
mov cr0, rax
|
||||
""")
|
||||
MakePTWritable()
|
||||
# 置位 CR0.WP:内核态写只读页也会 #PF(此前清除 WP 使页表只读形同虚设,
|
||||
# 越界写 .rodata 字符串常量静默破坏 → 格式串/路径/符号名损坏连锁)。
|
||||
# 配合 ProtectKernelRO() 把 .rodata 页清 W 位,越界写立即 #PF 暴露写源。
|
||||
c.Asm(f"""
|
||||
mov rax, cr0
|
||||
or rax, 0x10000
|
||||
|
||||
Reference in new issue
Block a user