推测控制¶
相当多的 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);