在 Linus Torvalds 忙碌的一周时间里,他在维也纳参加 Linux 内核维护者峰会和相关 Linux 基金会活动,以及管理 Linux 6.12 合并窗口,推出sched_ext和实时PREEMPT_RT等新功能,他还设法为下一个内核版本完成了自己的一些代码。今天被合并的是他自己的代码,它使用地址掩码在新的用户访问快速验证路径上工作。
虽然现在 Linus Torvalds 本人很少开始编写任何闪亮而重要的新内核功能,但在 Linux 6.11 中,他制定了一些新的 ARM64 (AArch64) 优化,现在对于 Linux 6.12,他通过地址屏蔽功能实现了用户访问快速验证。不过,最初这个适用于 Linux 6.12 的新代码只是让 x86_64 CPU 受益。
简短的解释是,由于这些 Spectre 变体 1 缓解措施,这个新代码可以绕过对一些 Spectre V1 推测屏障的需求和现在昂贵的 access_ok() 调用。Torvalds 在今天的 Git 合并中解释道:
“使用地址掩码进行合并用户访问快速验证。
这允许架构选择性地使用数据依赖型地址掩码模型而不是条件分支来验证用户访问。这避免了 Spectre-v1 的投机障碍。
目前只有 x86-64 利用了这一点,而且并非所有架构都能够做到这一点。它需要在用户和内核地址空间之间有一个保护区域(这样你就不会从一个溢出到另一个),以及一种为无效的用户指针生成保证出错地址的简单方法。
另请注意,这当前假定用户读取和写入访问之间没有区别。如果扩展到像 powerpc 这样的架构,我们还需要分离出用户读 vs 写的情况。
Torvalds 作为其中一个补丁的一部分进行了更详细的解释:
“Spectre-v1 缓解措施使 access_ok()’ 的成本大大增加,因为它必须使用测试来序列化执行,以获得有效的用户地址。
所有普通的用户复制例程都通过仅使用数据依赖掩码来屏蔽用户地址来避免这种情况,但是本应是快速情况的快速 “unsafe_user_read()” 模式的速度变慢了。
这引入了使用
src = masked_user_access_begin(src) 的概念;
要使用数据依赖掩码而不是更传统的条件
if (user_read_access_begin(src, len)) {
模型来实现用户地址健全性。
此模型仅适用于从 ‘src’ 开始的密集访问,以及在用户空间和内核空间区域之间具有保证会出错的保护区域的体系结构。
这样,就不需要手动检查用户访问权限,因为坏地址肯定会出错(通过一些架构屏蔽技巧:在 x86-64 上,这只涉及将无效的用户地址转换为所有用户地址,因为我们没有映射地址空间的顶部)。
这暂时只转换了几个示例。从用户空间加载两个单词的 x86-64 代码生成示例:
stac
mov %rax,%rcx
sar $0x3f,%rcx
或 %rax,%rcx
mov (%rcx),%r13
mov 0x8(%rcx),%r14
clac,其中所有错误处理和 -EFAULT 现在完全由异常路径进行内联处理。
当然,如果微架构在 ‘clac’ 和 ‘stac’ 上表现不佳,那么上述操作仍然慢得可怜。但至少我们做得尽可能好。
这种基于地址掩码的用户访问快速验证现已合并到 x86_64 上的 Linux 6.12 中,以及本周即将推出的许多其他有趣的新代码。Linux 6.12 合并窗口将在一周内结束,最终以 Linux 6.12-rc1 版本结束。
转自 Linus Torvalds Adds User-Access Fast Validation Via Address Masking To Linux 6.12 – Phoronix