而在内核模式下执行,有没有什么办法的时候(PTI)已启用页表隔离来获得用户空间的CR3值?
在当前的Linux,请参阅ASM arch/x86/entry/calling.h
和其他的东西.macro SWITCH_TO_USER_CR3_NOSTACK
看到Linux内核与用户之间的CR3如何翻转。而就在常量先前的评论,它使用:
/*
* PAGE_TABLE_ISOLATION PGDs are 8k. Flip bit 12 to switch between the two
* halves:
*/
#define PTI_USER_PGTABLE_BIT PAGE_SHIFT
#define PTI_USER_PGTABLE_MASK (1 << PTI_USER_PGTABLE_BIT)
#define PTI_USER_PCID_BIT X86_CR3_PTI_PCID_USER_BIT
#define PTI_USER_PCID_MASK (1 << PTI_USER_PCID_BIT)
#define PTI_USER_PGTABLE_AND_PCID_MASK (PTI_USER_PCID_MASK | PTI_USER_PGTABLE_MASK)
它看起来像内核CR3永远是下一个,所以设置位12在当前的CR3总是使其指向用户空间页目录。 (如果当前任务具有用户空间,并且启用了PTI。这些ASM宏只在代码路径是即将返回到用户空间中使用。)
.macro SWITCH_TO_USER_CR3_NOSTACK scratch_reg:req scratch_reg2:req
...
mov %cr3, \scratch_reg
...
.Lwrcr3_\@:
/* Flip the PGD to the user version */
orq $(PTI_USER_PGTABLE_MASK), \scratch_reg
mov \scratch_reg, %cr3
这些宏在entry_64.S
,entry_64_compat.S
和entry_32.S
用于返回到用户空间路径。
有可能从下访问用户空间页表一个更清洁的方式
你最好的选择可能是看网页出错处理程序以找出如何访问进程的页表。 (或者mmap
的实现MAP_POPULATE
的)。