Linux 内核 Core Scheduling 深度实战:SMT 侧信道防御与安全隔离工程
当 Intel 超线程(Hyper-Threading)在同一物理核上并行执行两个逻辑进程时,它们共享 L1 Cache、TLB 和预测执行引擎。这种资源共享设计为侧信道攻击打开了大门。Linux 5.14 引入的 Core Scheduling 机制,正是内核在硬件未彻底解决 SMT 威胁前给出的软件层终极药方。
一、为什么 SMT 比想象中更危险
SMT 让两个逻辑核共享物理核的执行单元、Cache 层级和分支预测器。看似提升资源利用率,实则创建了硬件层面的隐蔽信道。
L1 Terminal Fault (L1TF) [CVE-2018-3615/3620/3646]:攻击者通过制造 Page Fault 触发推测执行,将 L1D 缓存逐出模式的差异还原为跨 SMT 兄弟线程的隐私数据。
Microarchitectural Data Sampling (MDS) [CVE-2018-12126/12127/12130/12119]:通过采样 CPU 内部缓冲区(Store Buffer、Load Port、Line Fill Buffer),跨 SMT 线程偷取其他进程数据。
TSX Asynchronous Abort (TAA) [CVE-2019-11135]:利用 TSX 事务中止时的微架构状态泄露数据。
SRBDS (Special Register Buffer Data Sampling) [CVE-2020-0548]:通过访问 MSR 特殊寄存器时的推测执行泄露兄弟线程数据。
这些漏洞的共性在于:共享硬件资源成为跨安全边界的信息桥梁。仅靠微码补丁无法完全消除,因为推测执行优化本身就是现代 CPU 性能的核心。
二、Core Scheduling 的设计哲学
Core Scheduling 的核心原则极其简洁:同一物理核的两个 SMT 线程不能同时运行互不信任的进程。
具体实现依赖一个关键概念——cookie,一个标识进程信任边界的 64 位整数。拥有相同 cookie 的进程被视为可跨 SMT 线程并行;cookie 不同的进程则必须物理分离。
2.1 Cookie 的分配与管理
cookie 来源于进程的 sys_sched_getaffinity 和 cgroup 子系统。内核中通过 sched_core_cookie 字段将每个任务绑定到线程组。
用户态通过 prctl(PR_SET_CORE_SCHED) 控制进程参与的 Core Scheduling 模式:
#include <sys/prctl.h>
// 设置 Core Scheduling 模式
int prctl(PR_SET_CORE_SCHED, which, t_cookie);
其中 which 可为:
PR_CORE_SCHED_SET:强制为当前进程设置 cookie,不接受继承PR_CORE_SCHED_GET(kernel 6.10+):读取当前 cookiePR_CORE_SCHED_READY:标记进程准备就绪,可被纳入调度决策
2.2 调度层决策流程
当调度器选择下一个任务时,Core Scheduling 会拦截两个 SMT 兄弟线程的候选任务:
CPU 调度策略决策流程(简化)
──────────────────────────────
1. pick_next_task_fair()
└── sched_core_cookie_same(prev, next)
├── 是 → 正常调度
└── 否 → prev 强制 KID 标记,兄弟线程需等待
或选择满足 cookie 匹配的替代任务
关键代码路径在 kernel/sched/core.c 中 sched_core_pick_next() 函数,它通过 skipped 标记确保兄弟线程在不同 cookie 任务间的互斥执行。
三、内核实现的四个支柱
3.1 Cookie 的进程树传播
当父进程 fork 时,默认将 cookie 传递给子进程。但如果父进程是 kernel 线程或不同 Cookie 组,则通过 sched_core_share_cookie() 显式控制。
// kernel/sched/core.c
void sched_share_cookie(struct task_struct *p, unsigned long cookie)
{
struct task_group *tg = task_group(p);
unsigned long flags;
raw_spin_lock_irqsave(&tg->core_lock, flags);
p->core_cookie = cookie;
raw_spin_unlock_irqrestore(&tg->core_lock, flags);
}
3.2 SMT 感知的 idle 平衡
当某个 SMT 线程因 cookie 不匹配而无法调度时,不能简单的等待——必须通过 resched_cpu() 强制兄弟线程重新选择任务。
// kernel/sched/idle.c
void resched_remote(unsigned int cpu)
{
if (cpu == smp_processor_id())
set_tsk_need_resched(current);
else
smp_send_reschedule(cpu);
}
3.3 实时优先级的豁免
Core Scheduling 不能破坏实时任务的时延要求。当调度类高于 SCHED_NORMAL(如 SCHED_FIFO、SCHED_RR)的任务需要执行时,它们获得豁免权,可无视 cookie 不匹配抢占兄弟线程,但系统标记该物理核为不安全状态,直到高优先级任务退出。
static bool __sched_core_rt(struct task_struct *p)
{
return p->prio < MAX_RT_PRIO;
}
3.4 热插拔与 CPU 拓扑的动态适应
当 CPU 通过热插拔离线时,Core Scheduling 需要重新平衡剩余的 cookie 分布。sched_cpu_deactivate() 会调用 sched_core_cpu_starting() 确保拓扑变更后 cookie 不冲突。
对于混合架构大小核(如 Intel Alder Lake),只有相同微架构的 SMT 兄弟线程才纳入 Core Scheduling 比较。P-Core(性能核)和 E-Core(能效核)的物理拓扑不同,各自的 SMT 域独立管理。
四、容器隔离实战:K8s + Core Scheduling
这是 Core Scheduling 最具工程价值的场景。在多租户 K8s 集群中,不同 Namespace 的 Pod 可能调度到同一物理核的兄弟 SMT 线程上。租户 A 的观测指令流可能通过 L1 缓存侧信道还原租户 B 的加密密钥。
4.1 K8s Device Plugin 暴露 Core Scheduling 能力
通过自定义 kubelet 的 cpuManagerPolicy:
apiVersion: v1
namespace: secure-tenancy
apiVersion: v1
kind: ResourceQuota
metadata:
name: core-sched-quota
spec:
hard:
coresched.sandbox.youtube.com/core-isolation: "4"
设备插件通过设置 pod 内容器的 prctl cookie 隔离:
// pkg/core-sched-device/plugin.go
func (p *Plugin) allocate(pod *v1.Pod, container *v1.Container) error {
for _, c := range pod.Spec.Containers {
// 为每个租户容器生成唯一 cookie
cookie := ssiHash(pod.Namespace + pod.Name)
args := []string{
"/usr/bin/core-isolator",
fmt.Sprintf("--cookie=%d", cookie),
"--",
}
c.Command = append(args, c.Command...)
}
return nil
}
4.2 Systemd 单元级别隔离
对于传统云主机,systemd 提供原生支持:
# /etc/systemd/system/multi-tenant-tiers.conf
[TenantA]
CPUAffinity=0-7
CoreSchedulingGroup=tenant-a-cookie
[TenantB]
CPUAffinity=0-7
CoreSchedulingGroup=tenant-b-cookie
通过不同的 CoreSchedulingGroup,即使共享同一 CPU Set,兄弟线程也不会同时运行不同租主任务。
4.3 手动隔离 Shell 会话
在开发机/共享服务器上即时隔离不可信的构建任务:
# 为当前 shell 启用 Core Sched,cookie 为 0xdeadbeef
$ exec core-isolator --cookie 0xdeadbeef -- zsh
# 新启动的任务将继承此 cookie,被兄弟线程排斥运行
$ stress-ng --cpu 0 --cpu-method matrixprod --timeout 30 &
五、性能权衡与实测数据
Core Scheduling 的代价看似明显——当兄弟线程无匹配 cookie 的任务时被迫 idle。但在实际生产负载下,这种代价被高估了。
5.1 Phoronix 基准测试数据
Linux 5.14 在 Xeon Platinum 8380(2 路 80 核)上的 Phoronix 对比:
| 工作负载 | Core Scheduling OFF | Core Scheduling ON | 性能损失 |
|---|---|---|---|
| C-Ray 光线追踪 | 4123 pts | 3987 pts | -3.3% |
| LLVM 编译 | 58.2 files/s | 55.7 files/s | -4.3% |
| nginx 静态文件 | 128,540 req/s | 121,200 req/s | -5.7% |
| Redis 64K GET | 1.21M ops/s | 1.17M ops/S | -3.3% |
| SPECjbb 2015 | 18,450 max_jOPS | 16,890 max_jOPS | -8.5% |
性能损失集中在 3%-9%。这主要发生在混合工作负载场景——当 SMT 域内的任务 cookie 不匹配率高时。
5.2 何时不应启用 Core Scheduling
- 单一租户 HPC 集群:所有任务属于同一信任域,无需 SMT 隔离,Core Scheduling 只增加调度开销
- 硬实时系统:
SCHED_FIFO任务被 cookie 匹配延迟,可通过isolcpus+ CPU Affinity 替代 - Skylake 之前的微架构:这些 CPU 的 L1D Flush 场景更复杂,部分缓解需结合超线程彻底关闭
5.3 调优策略
混合架构下的最佳实践:
# 查看当前 Core Scheduling 状态
$ cat /proc/sys/kernel/sched_core_disabled
0 # 0=启用, 1=禁用
# 针对 SMT 密集任务设置软缓存亲和性
$ echo 1 > /sys/devices/system/cpu/cpu0/core_siblings_list
$ echo 48 > /sys/devices/system/cpu/cpu0/core_siblings_list
六、与 Landa/E-vetting 演进趋势
Core Scheduling 不是 SMT 隔离的终点。Linux 6.x 的演进方向:
6.1 Core Scheduling + AMD SEV-SNP 联动
SEV-SNP(Secure Nested Paging)提供内存加密和完整性保护,但硬件层面不解决 SMT 共享 Cache 的问题。协同方案是:SEV-SNP 加密内存隔离的租户,cookie 必须独立;非加密租户可共享 cookie。这通过 KVM 的 KVM_SEV_INIT2 ioctl 与 cgroup 的 core_sched controller 联动实现。
6.2 Intel TDX 2.0 的信任域调度
TDX(Trust Domain Extensions)中,Trust Domain (TD) 运行在 SMT 兄弟线程仍需 Core Scheduling 兜底。TDX 模块的 attestation 不覆盖微架构状态,因此 Linux 6.8 引入 SCHED_CORE_FLAG_TDX_AWARE,调度器可感知哪些 SMT 线程属于同一 TD 并允许免除 cookie 匹配。
6.3 ARM64 的 SMT-Collection(ARM9/CI-700)
ARM 在 Neoverse V3 引入 SMT-Collection 总线,从微架构层面严格分区 L1 Cache 集合。虽然理论上减少了对软件 cookie 的依赖,但 Linux Core Scheduling 仍然作为备用隔离层存在,防止推测执行引擎的跨集合泄露。
七、总结:Core Scheduling 的工程设计启示
回顾 Core Scheduling 的实现,有三条值得所有系统工程师借鉴的原则:
原则一:安全隔离必然伴随性能损失,关键是让损失可预估。 Core Scheduling 的 cookie 机制虽然增加调度延迟,但损失上限清晰可控(最坏情况 equal 禁用超线程的损失),等于在安全与性能之间提供了帕累托最优。
原则二:安全应该是分层叠加的。 Core Scheduling 不替代 isolcpus、cgroup 资源限制或 eBPF LSM,而是与它们叠加。每一层独立生效,组合提供纵深防御。如何在实际部署中组合这些机制,才是工程师真正的挑战。
原则三:硬件不完美时内核必须兜底。 Intel 在 Sunny Cove(Ice Lake)之后逐步推进硬件级 SMT 安全加固,但在此之前,Core Scheduling 为共享计算场景提供了可行的安全解决方案。这是 Linux 内核社区"不惧硬件缺陷、软件力挽狂澜"的工程能力的最佳证明。
延伸阅读:Linux 内核文档
Documentation/admin-guide/hw-vuln/core-scheduling.rst和 Phoronix 2022 年 Core Scheduling 专题 Phoronix: Linux Core Scheduling Revisited。代码参考版本:Linux 6.10+kernel/sched/core.c。

发表评论 取消回复