作者: wzt
本文為作者投稿,Seebug Paper 期待你的分享,凡經采用即有禮品相送! 投稿郵箱:paper@seebug.org
bootstrap_pagetables頁表重寫
之前內核啟動時設置的臨時頁表_bootstrap_pagetables, 為了方便使用的是block類型的映射,block映射涵蓋的虛擬地址范圍非常大,后面對它的映射可能會被ktrr攔截下來,所以需要更改下_bootstrap_pagetables的頁表,改為table類型,同時_bootstrap_pagetables需要用到的代碼地址映射范圍只需要到開啟mmu為止就可以。這個地址可以通過_bootstrap_instructions符號來定位。
_arm_vm_init:
ADRL X8, _bootstrap_instructions
AND X21, X8, #0xFFFFFFFFFFFFC000
MOV X0, X21
BL _mmu_kvtop
MOV X20, X0
計算出_bootstrap_instructions的虛擬地址和物理地址。
ADRL X0, _bootstrap_pagetables ; l1 table
BL _mmu_kvtop
CBNZ X0, loc_FFFFFFF007B69070
_bootstrap_pagetables為l1 table地址。
MOV X21, X0 ; l1 table
UBFX X19, X20, #0x24, #3 ; '$' ; l1 index
LDR X8, [X0,X19,LSL#3] ; l1 pte
AND X24, X8, #0xFFFFFFFFF000
MOV X0, X24 ; l2 table paddr
BL _phystokv
MOV X22, X0 ; l2 table vaddr
提取l1 index,pte以及l2 table虛擬地址。
ADRP X9, #_ropage_next@PAGE
LDR X23, [X9,#_ropage_next@PAGEOFF]
CBNZ X23, loc_FFFFFFF007B690AC ; l2 index
ADRL X23, _ropagetable_begin
STR X23, [X9,#_ropage_next@PAGEOFF]
UBFX X26, X20, #0x19, #0xB ; l2 index
ADD X8, X23, #4,LSL#12
STR X8, [X9,#_ropage_next@PAGEOFF] ; _ropage_next += 4096
MOV X0, X23
BL _mmu_kvtop
MOV X25, X0 ; new l3 table
提取l2 index以及從_ropage_next 分配一個物理頁作為l3 table。
UBFX X27, X20, #0xE, #0xB ; l3 index
提取l3 index。
MOV X0, X21 ; void *
MOV W1, #0x4000 ; size_t
BL _bzero ; clear l1 talbe
清空l1table所有頁表項內容。
ORR X8, X24, #3
STR X8, [X21,X19,LSL#3] ; reset l1 pte with 0x3(table & vaild)
然后重新設置_bootstrap_instructions對應的l1 pte,屬性改為table類型。
MOV X0, X22 ; void *
MOV W1, #0x4000 ; size_t
BL _bzero ; clear l2 table
AND X8, X25, #0xFFFFFFFFF000
ORR X8, X8, #3
STR X8, [X22,X26,LSL#3] ; reset l2 talbe pte
清空l2 table所有頁表項,然后重新設置_bootstrap_instructions對應的l2 pte,屬性改為table類型。
AND X8, X20, #0xFFFFFFFFC000
MOV X9, #0x40000000000683
ORR X8, X8, X9
STR X8, [X23,X27,LSL#3] ; setup l3 pte
重新設置_bootstrap_instructions對應的l3 pte,至此_bootstrap_pagetables已經重新初始化完畢,不在受ktrr影響了。
對devicetree內存屬性的改動
通常來講,對ktrr/ctrr的鎖定是在devicetree加載和引用結束后才實施的,但也可能在ktrr/ctrr鎖定后,也有對devicetree的引用。因此在內核啟動階段對各個內核數據段進行權限設置時,也要把devicetree所在的區域加入到ktrr/ctrr的保護區域。
_arm_vm_prot_init:
ADRP X21, #_segPRELINKTEXTB@PAGE
STR X8, [X24,#_segEXTRADATA@PAGEOFF]
起初_segEXTRADATA保存的是_segPRELINKTEXTB地址,這是kernelcache的最低地址。
BL _SecureDTIsLockedDown
CBZ W0, loc_FFFFFFF007B68054
ADRL X8, _PE_state.deviceTreeHead
LDR X9, [X8]
STR X9, [X24,#_segEXTRADATA@PAGEOFF]
LDR X8, [X8,#(qword_FFFFFFF00772C240 - 0xFFFFFFF00772C230)]
STR X8, [X25,#_segSizeEXTRADATA@PAGEOFF]
調用_SecureDTIsLockedDown,如果返回1,代表devicetree的加載地址不包含在_segPRELINKTEXTB內,因此要把devicetree的加載地址重新寫入segEXTRADATA,然后在調用_arm_vm_page_granular_prot做屬性調整。
_SecureDTIsLockedDown:
ADRL X20, __mh_execute_header
ADRP X8, #_DTRootNode@PAGE
LDR X20, [X8,#_DTRootNode@PAGEOFF]
CMP X8, #0
判斷_DTRootNode地址是否小于__mh_execute_header。
對_update_mdscr的保護
mdscr寄存器是arm調試機制的控制寄存器,開啟調試機制可能會繞過ktrr保護,xnu的一個緩解措施是在設置完mdscr后,判斷kde位是否開啟,如果開啟就panic。
__TEXT_EXEC:__text:FFFFFFF008139478 _update_mdscr:
MOV X4, #0
MRS X2, #0, c0, c2, #2
BIC X2, X2, X0
X0保存的是要清楚的bit位。
ORR X2, X2, X1
AND X2, X2, #0xFFFFFFFFFFFFDFFF
MSR #0, c0, c2, #2, X2
X1保存的是要設置的bit位。
ANDS X3, X2, #0x2000
ORR X4, X4, X3
B.NE loc_FFFFFFF008139488
CMP X4, XZR
B.NE loc_FFFFFFF0081394A8
RET
__TEXT_EXEC:__text:FFFFFFF0081394A8
ADRL X0, aMdscrKdeWasSet ; "MDSCR.KDE was set"
B _panic
判斷kde位是否開啟,如果開啟就panic。
Ktrr/ctrr鎖定
_kernel_bootstrap->_machine_init->_rorgn_stash_range
_rorgn_stash_range:
ADRP X8, #_segLOWESTRO@PAGE
LDR X19, [X8,#_segLOWESTRO@PAGEOFF]
MOV X0, X19
BL _mmu_kvtop
CBNZ X0, loc_FFFFFFF007B624E8
loc_FFFFFFF007B624E8 ; CODE XREF: _rorgn_stash_range+1D8↑j
ADRP X8, #_ctrr_begin@PAGE
STR X0, [X8,#_ctrr_begin@PAGEOFF]
將_segLOWESTRO地址寫入_ctrr_begin
ADRP X8, #_segHIGHESTRO@PAGE
LDR X19, [X8,#_segHIGHESTRO@PAGEOFF]
CBZ X19, loc_FFFFFFF007B6252C
SUB X8, X0, #1
ADRP X9, #_ctrr_end@PAGE
STR X8, [X9,#_ctrr_end@PAGEOFF]
如果kernelcache binary存在_segHIGHESTRO,則將_segHIGHESTRO - 1存入_ctrr_end。
loc_FFFFFFF007B6252C ; CODE XREF: _rorgn_stash_range+20C↑j
ADRP X8, #_segLASTB@PAGE
LDR X19, [X8,#_segLASTB@PAGEOFF]
MOV X0, X19
ADRP X8, #_segSizeLAST@PAGE
LDR X8, [X8,#_segSizeLAST@PAGEOFF]
ADD X0, X8, X0
SUB X8, X0, #1
ADRP X9, #_ctrr_end@PAGE
STR X8, [X9,#_ctrr_end@PAGEOFF]
如果kernelcache binary不存在_segHIGHESTRO,則將_segLASTB+segSizeLAST-1寫入_ctrr_end。
_rorgn_stash_range函數只是計算出了_ctrr_begin和_ctrr_end,真正對內核鎖定是在_rorgn_lockdown函數。
_kernel_bootstrap_thread->_machine_lockdown->_rorgn_lockdown
_rorgn_lockdown:
ADRP X9, #_ctrr_begin@PAGE
LDR X9, [X9,#_ctrr_begin@PAGEOFF]
ADRP X10, #_ctrr_end@PAGE
LDR X10, [X10,#_ctrr_end@PAGEOFF]
MSR #4, c15, c2, #3, X9 ; S3_4_C15_C2_3
MSR #4, c15, c2, #4, X10 ; S3_4_C15_C2_4
MOV W11, #0x12
MSR #4, c15, c2, #5, X11 ; S3_4_C15_C2_5
MOV W11, #1
MSR #4, c15, c2, #2, X11 ; S3_4_C15_C2_2
將_ctrr_begin寫入S3_4_C15_C2_3寄存器,它保存的是ctrr保護的起始地址,將_ctrr_end寫入S3_4_C15_C2_4,它保存的是ctrr保護的結束地址。
將0x12寫入S3_4_C15_C2_5寄存器,它保存的是ctrr的控制狀態。Xnu source code里已經有對它的描述:
Apple_arm64_regs.h
\#define CTRR_CTL_EL1_A_MMUOFF_WRPROTECT (1 << 0)
\#define CTRR_CTL_EL1_A_MMUON_WRPROTECT (1 << 1)
\#define CTRR_CTL_EL1_B_MMUOFF_WRPROTECT (1 << 2)
\#define CTRR_CTL_EL1_B_MMUON_WRPROTECT (1 << 3)
\#define CTRR_CTL_EL1_A_PXN (1 << 4)
\#define CTRR_CTL_EL1_B_PXN (1 << 5)
\#define CTRR_CTL_EL1_A_UXN (1 << 6)
\#define CTRR_CTL_EL1_B_UXN (1 << 7)
將1寫入S3_4_C15_C2_2寄存器,鎖定ctrr。
MRS X11, #0, c4, c2, #2 ; CurrentEL
CMP X11, #8 ; el2
B.NE loc_FFFFFFF007B62DEC
MSR #4, c15, c11, #0, X9 ; S3_4_C15_C11_0
MSR #4, c15, c11, #1, X10 ; S3_4_C15_C11_1
MOV W9, #0x12
MSR #4, c15, c11, #4, X9 ; S3_4_C15_C11_4
MOV W9, #1
MSR #4, c15, c11, #5, X9 ; S3_4_C15_C11_5
可以看到ctrr除了能對el1內核代碼做保護,還可以對el2 hypervisor做保護。
S3_4_C15_C11_0代表要保存的el2代碼起始地址,S3_4_C15_C11_1代表結束地址,S3_4_C15_C11_4代表控制寄存器,S3_4_C15_C11_5代表鎖定寄存器。
Ktrr/ctrr保護的區域范圍如下:
\* __PRELINK_TEXT <--- First KTRR (ReadOnly) segment
\* __PLK_DATA_CONST
\* __PLK_TEXT_EXEC
\* __TEXT
\* __DATA_CONST
\* __TEXT_EXEC
\* __KLD
\* __LAST <--- Last KTRR (ReadOnly) segment
\* __DATA
\* __BOOTDATA (if present)
\* __LINKEDIT
\* __PRELINK_DATA (expected populated now)
\* __PLK_LINKEDIT
\* __PRELINK_INFO
_reset_vector的行為
系統重啟后的第一件事就是鎖定ktrr/ctrr寄存器。
_reset_vector:
ADRL X17, _ctrr_begin
LDR X17, [X17]
CBZ X17, loc_FFFFFFF00813445C
ADRL X19, _ctrr_end
LDR X19, [X19]
CBZ X19, loc_FFFFFFF00813446C
MRS X18, #4, c15, c2, #2
CBNZ X18, loc_FFFFFFF0081344A8
MSR #4, c15, c2, #3, X17 ; S3_4_C15_C2_3
MSR #4, c15, c2, #4, X19 ; S3_4_C15_C2_4
MOV X18, #0x12
MSR #4, c15, c2, #5, X18 ; S3_4_C15_C2_5
MOV X18, #1
MSR #4, c15, c2, #2, X18 ; S3_4_C15_C2_2
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/1769/
暫無評論