启用PTI时的用户空间CR3值

时间:2019-02-10 23:02:05

标签: linux-kernel x86 cpu-registers

在内核模式下执行时,启用页表隔离(PTI)时是否有任何方法可以获取用户空间CR3值?

1 个答案:

答案 0 :(得分:3)

在当前的Linux中,请参见arch/x86/entry/calling.h中的asm .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始终是较低的内核,因此在当前CR3中设置位12总是使其指向用户空间页面目录。(如果当前任务具有用户空间,并且如果启用了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.Sentry_64_compat.Sentry_32.S中使用。


大概是一种从C访问用户空间页表的更简洁的方法。

您最好的选择是查看页面错误处理程序,以了解它如何访问进程的页面表。 (或mmap的{​​{1}}实现)。