推测控制¶
相当多的 CPU 存在与推测相关的错误功能,这些功能实际上是漏洞,会导致各种形式的数据泄露,甚至跨越特权域。
内核以各种形式为此类漏洞提供缓解措施。其中一些缓解措施是编译时可配置的,一些可以在内核命令行上提供。
还有一类缓解措施非常昂贵,但它们可以限制在受控环境中的一组特定进程或任务中。控制这些缓解措施的机制是通过 prctl(2)。
有两个与此相关的 prctl 选项
PR_GET_SPECULATION_CTRL
PR_SET_SPECULATION_CTRL
PR_GET_SPECULATION_CTRL¶
PR_GET_SPECULATION_CTRL 返回使用 prctl(2) 的 arg2 选择的推测错误功能的状态。返回值使用位 0-3,含义如下
位 |
定义 |
描述 |
---|---|---|
0 |
PR_SPEC_PRCTL |
可以使用 PR_SET_SPECULATION_CTRL 按任务控制缓解措施。 |
1 |
PR_SPEC_ENABLE |
推测功能已启用,缓解措施已禁用。 |
2 |
PR_SPEC_DISABLE |
推测功能已禁用,缓解措施已启用。 |
3 |
PR_SPEC_FORCE_DISABLE |
与 PR_SPEC_DISABLE 相同,但无法撤消。后续的 prctl(..., PR_SPEC_ENABLE) 将失败。 |
4 |
PR_SPEC_DISABLE_NOEXEC |
与 PR_SPEC_DISABLE 相同,但该状态将在 execve(2) 上清除。 |
如果所有位均为 0,则 CPU 不受推测错误功能的影响。
如果设置了 PR_SPEC_PRCTL,则可以使用按任务控制缓解措施。如果未设置,则对推测错误功能使用 prctl(PR_SET_SPECULATION_CTRL) 将失败。
PR_SET_SPECULATION_CTRL¶
PR_SET_SPECULATION_CTRL 允许控制由 prctl(2) 的 arg2 选择的每个任务的推测错误功能。arg3 用于传入控制值,即 PR_SPEC_ENABLE 或 PR_SPEC_DISABLE 或 PR_SPEC_FORCE_DISABLE。
常见错误代码¶
值 |
含义 |
---|---|
EINVAL |
该 prctl 未由架构实现,或未使用的 prctl(2) 参数不为 0。 |
ENODEV |
arg2 选择了一个不支持的推测错误功能。 |
PR_SET_SPECULATION_CTRL 错误代码¶
值 |
含义 |
---|---|
0 |
成功 |
ERANGE |
arg3 不正确,即它既不是 PR_SPEC_ENABLE,也不是 PR_SPEC_DISABLE,也不是 PR_SPEC_FORCE_DISABLE。 |
ENXIO |
无法控制选定的推测错误功能。请参阅 PR_GET_SPECULATION_CTRL。 |
EPERM |
推测已通过 PR_SPEC_FORCE_DISABLE 禁用,并且调用者尝试再次启用它。 |
推测错误功能控制¶
PR_SPEC_STORE_BYPASS:推测性存储旁路
- 调用
prctl(PR_GET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, 0, 0, 0);
prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_ENABLE, 0, 0);
prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_DISABLE, 0, 0);
prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_FORCE_DISABLE, 0, 0);
prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_DISABLE_NOEXEC, 0, 0);
- PR_SPEC_INDIR_BRANCH:用户进程中的间接分支推测
(缓解针对用户进程的 Spectre V2 样式攻击)
- 调用
prctl(PR_GET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, 0, 0, 0);
prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, PR_SPEC_ENABLE, 0, 0);
prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, PR_SPEC_DISABLE, 0, 0);
prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, PR_SPEC_FORCE_DISABLE, 0, 0);
- PR_SPEC_L1D_FLUSH:在任务上下文切换出时刷新 L1D 缓存
(仅当任务在非 SMT 核心上运行时才有效)
- 调用
prctl(PR_GET_SPECULATION_CTRL, PR_SPEC_L1D_FLUSH, 0, 0, 0);
prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_L1D_FLUSH, PR_SPEC_ENABLE, 0, 0);
prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_L1D_FLUSH, PR_SPEC_DISABLE, 0, 0);