From b1956ea72222e36f146e50ed33c8beb69bfe34e5 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sat, 29 Aug 2026 17:42:34 +0800 Subject: [PATCH] =?UTF-8?q?fix(kernel):=20paging.init=20=E5=85=88=E6=B8=85?= =?UTF-8?q?=20WP=20=E5=86=8D=20MakePTWritable=20=E5=86=8D=E7=BD=AE=20WP?= =?UTF-8?q?=EF=BC=88bootloader=20=E5=B7=B2=E8=AE=BE=20WP=3D1=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit UEFI/bootloader 的 CR0.WP 已是 1(原代码清 WP 正因此),MakePTWritable 在 WP=1 下写只读页表页即 #PF(cr2=0xf8033e0)。改为:清 WP → 放开页表页 → 置 WP=1。 --- VKernel/Kernel/paging/paging.vp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/VKernel/Kernel/paging/paging.vp b/VKernel/Kernel/paging/paging.vp index 6a9c4c3..cff46f9 100644 --- a/VKernel/Kernel/paging/paging.vp +++ b/VKernel/Kernel/paging/paging.vp @@ -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