英文:
On AArch64, how does SCTLR_EL1.SPAN=0 work when a translation fault occurs while PSTATE.PAN=1?
问题
例如,XNU内核具有copyin()
/copyout()
函数,用于在用户空间和内核空间之间复制数据。由于这些函数需要访问用户空间,它们通过将PSTATE.PAN
设置为0
来禁用PAN。但是,如果将SCTLR_EL1.SPAN
设置为0
,规范规定“在从EL1引发异常时将PSTATE.PAN设置为1”。
首先,假设在启用PAN的情况下(无论是在用户地址还是内核地址上)在复制操作期间发生了翻译故障。然后,将引发到EL1的异常。请注意,我们已经在EL1中运行,所以我不确定这是否算作“引发异常到EL1”。我会假设它是,但如果我错了,请纠正我。在这种情况下,由于SCTLR_EL1.SPAN
设置为0
,在执行故障处理程序之前,PAN会在自动重新启用。
接下来,假设故障处理程序成功(即它找到页面并将其插入页面表中),那么当异常返回时会发生什么?我在规范中没有看到PAN应在异常返回时自动重新禁用的提及。然而,如果PAN保持启用状态,那么下一个用户空间访问将触发另一个异常,这应该会导致内核崩溃,因为内核在启用PAN的情况下访问用户地址。
我理解错了什么吗?我更熟悉XNU,但同样的问题可能也适用于Linux内核的copy_from_user()
/copy_to_user()
。
英文:
For example, the XNU kernel has the copyin()
/copyout()
functions to copy data from user-space to kernel-space and vice versa. Since these functions need to access user-space, they disable PAN by setting PSTATE.PAN
to 0
. However, if SCTLR_EL1.SPAN
is set to 0
, the specification says that "PSTATE.PAN is set to 1 on taking an exception to EL1".
First, let's say that a translation fault occurs during the copy operation while PAN is enabled (either on a user address or a kernel address). Then, an exception would be taken to EL1. Note that we were already running in EL1, so I'm not 100% sure that this counts as taking an exception "to EL1". I'll assume that it does, but please correct me if I'm wrong. In that case, because SCTLR_EL1.SPAN
is set to 0
, PAN is re-enabled automatically before the fault handler is executed.
Next, let's say that the fault handler succeeds (i.e. it finds the page and inserts it in the page tables), then what happens when the exception returns? I don't see any mention in the specification that PAN should be re-disabled automatically when the exception returns. However, if PAN stays enabled, then the next user-space access will trigger another exception, which should cause a kernel panic because the kernel is accessing a user address while PAN is enabled.
What am I getting wrong? I'm more familiar with XNU, but the same question probably applies to the Linux kernel with copy_from_user()
/copy_to_user()
.
答案1
得分: 2
根据Arm® A-profile架构参考手册的D8.4.1节“PSTATE对访问权限的影响”:
当从AArch64状态的EL中发生异常到ELx时,
PSTATE.PAN
会保存到SPSR_ELx.PAN
中,并在ELx中执行异常返回操作时从SPSR_ELx.PAN
中恢复。
而且,如果我们在C5.2.18节中查看SPSR_EL1.PAN
,我们可以看到:
当实施
FEAT_PAN
时:特权访问不允许。在发生EL1异常时设置为
PSTATE.PAN
的值,并在EL1中执行异常返回操作时复制到PSTATE.PAN
。
因此,这似乎是一种简单的硬件辅助方法来解决这个问题。不需要魔术软件变通方法。
英文:
According to the Arm® Architecture Reference Manual for A-profile architecture, section D8.4.1 "Effect of PSTATE on access permission":
> When taking an exception from an EL in AArch64 state to an ELx
, PSTATE.PAN
is saved to and restored from SPSR_ELx.PAN
.
And if we take a look at SPSR_EL1.PAN
in section C5.2.18 we can read:
> When FEAT_PAN
is implemented:
>
> Privileged Access Never. Set to the value of PSTATE.PAN
on taking an exception to EL1, and copied to PSTATE.PAN
on executing an exception return operation in EL1.
So this seems like an easy hardware-assisted way to solve the problem. No magic software workarounds needed.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论