sched-ext discussion
[PATCH] selftests/sched_ext: Check skeleton open failure in exit test
LLM 分析
sched_ext selftest:exit 测试缺少 skeleton 打开失败检查
系列概况
- 标题:[PATCH] selftests/sched_ext: Check skeleton open failure in exit test
- 作者:Liang Luo luoliang@kylinos.cn
- 版本:v1,单 patch
- 规模:1 文件,+1 行
- 修改文件:
tools/testing/selftests/sched_ext/exit.c - 代码统计:1 insertion(+), 0 deletion(-)
- Message-ID:
20260807013912.3178229-1-luoliang@kylinos.cn - 完整性:完整。patch + maintainer 接受回执(Tejun Heo 已合入
sched_ext/for-7.3)
补丁目的
sched_ext 提供了一组 BPF selftests,每个测试在 run() 中调用对应的 xxx__open() 打开 libbpf 生成的 skeleton。
exit.c 是其中用来验证「BPF 程序运行中触发用户态 exit_point 路径」的测试,但它没有像其它 selftest 那样在 exit__open() 返回 NULL 时立刻 fail。一旦 skeleton 打开失败,下一行 SCX_ENUM_INIT(skel) 就会通过 skel->rodata 解引用空指针,造成 NULL pointer dereference。
本 patch 的目标:在 exit__open() 返回 NULL 时使用 SCX_FAIL_IF(!skel, "Failed to open") 显式失败,使错误信息更清晰,并消除空指针解引用风险。
旧流程的问题
[run() in exit.c, before fix]
skel = exit__open();
|
v +---------------------------+
| skel == NULL ? |
+---------------------------+
|
| (not checked -- bug)
v
SCX_ENUM_INIT(skel);
|
v
SCX_ENUM_SET(skel->rodata, ...)
|
v
*** NULL pointer dereference ***
exit__open()在 libbpf 分配 skeleton 失败、ELF 解析失败等情况下会返回NULL。SCX_ENUM_INIT(skel)宏展开后访问skel->rodata,对空指针解引用。- 后果是测试进程直接崩溃(segfault),而不是输出可定位的错误信息;同时 selftest 框架无法把这个失败归类为「打开失败」。
- 其它兄弟 selftest(如
enq_last、enq_select_cpu_fails等)都已经有SCX_FAIL_IF(!skel, "Failed to open skel"),只有exit.c漏掉了。
新流程
[run() in exit.c, after fix]
skel = exit__open();
|
v
+---------------------------+
| skel == NULL ? |
+---------------------------+
| |
NULL | | non-NULL
v v
+-----------+ SCX_ENUM_INIT(skel)
| SCX_FAIL | skel->rodata->exit_point = tc
| _IF(!skel)| SCX_FAIL_IF(exit__load(skel), ...)
+-----------+
|
v
return SCX_TEST_STATUS_FAIL
("Failed to open")
失败路径上:exit__open() 返回 NULL -> SCX_FAIL_IF 立刻把测试标记为 FAILED 并打印 "Failed to open",避免后续空指针解引用。
关键实现
新增的就是一行:
SCX_FAIL_IF(!skel, "Failed to open");
SCX_FAIL_IF 是 sched_ext selftest 框架提供的宏,语义是:当条件为真时,打印第二条参数给出的信息,把测试状态置为 SCX_TEST_STATUS_FAIL 并 return。它正是 selftest 里「提前 bail」的惯用 idiom,与其它 selftest 的写法保持一致。
类比
把 xxx__open() 想成去图书馆借一本特定编号的书:
- 其它 selftest:柜台服务员会先看手里是不是真的拿到书(
SCX_FAIL_IF(!skel, ...)),拿到空册子就直接告诉你「借不到」,然后让你离开。 - 旧版
exit.c:柜台递过来一个空册子,你没检查就翻到第 5 页写笔记(skel->rodata->exit_point = tc),结果翻页时书页是空的——页码指向虚无,手指戳穿了「空气」,当场崩溃(NULL deref)。 - 修复后:你在翻页前先看一眼,发现是空册子,立刻说「借不到」,柜台记录这次失败,流程干净结束。
Highlight:风险与注意点
- 看似一行 but 关键:
exit__open()失败概率不高,但只要发生就是进程崩溃;修复后变成受控失败,CI 上更易诊断。 - 同质化要求:sched_ext selftests 数量在增长,每个新 selftest 都需要遵循
SCX_FAIL_IF(!skel, ...)的统一风格。可以考虑把「打开失败检查」写进一个公共 helper 或断言宏,从源头杜绝漏写。 - 后续观察点:
SCX_ENUM_INIT(skel)自身是否也会被调用到?它访问skel->rodata,因此修复必须放在它之前——本次 patch 顺序正确。 Fixestag 链向原始 selftest 引入 commit:a5db7817af78 ("sched_ext: Add selftests"),说明这是从一开始引入时就遗留的疏漏,对 stable 回溯有价值。
版本变化
本线程只有 v1 一次提交,maintainer Tejun Heo 直接回复「Applied to sched_ext/for-7.3.」,没有 v2 也没有 review 争论,属于干净利落的一行修复。
一句话总结
sched_ext selftest 中 exit.c 漏掉了对 exit__open() 返回值的检查,导致 skeleton 打开失败时会触发空指针解引用;本 patch 用一行 SCX_FAIL_IF(!skel, "Failed to open") 与其它 selftest 对齐,已被 Tejun 合入 sched_ext/for-7.3。