本文所述问题已在诸位助教学长努力下修复。向助教们致敬!
背景声明
本文适用于武汉大学『计算机系统基础』 配套的 Shell Lab 实验。 因本人精力有限,并未对 CSAPP 上游资源进行测试。 因此,本文所述内容对你的 Shell Lab 环境可能无效。请仔细甄别。
二次更新:经检查,CMU 上游无此 trace。 请允许我在此一并向此实验的非官方扩充者们致意! 使用套接字通信来测试时序问题无疑是个天才般的主意, 即便出现了细微漏洞,在总体上也瑕不掩瑜。
AIGC 使用声明
本文所述漏洞在 AIGC 辅助下发现。
今天运行 Shell Lab 对拍时我注意到一些奇妙的报错:
47. Running trace28.txt...
Oops: test and reference outputs for trace28.txt differed.
Test output:
#
# trace28.txt - Robustness: job continued by outside your shell
#
tsh> ./mycont 10
# Stop and check the job state
Job [1] (186197) stopped by signal 20
tsh> jobs
[1] (186197) Stopped ./mycont 10
# Now continue it, but not through fg/bg in shell
tsh> jobs
[1] (186197) Running ./mycont 10
Reference output:
#
# trace28.txt - Robustness: job continued by outside your shell
#
tsh> ./mycont 10
# Stop and check the job state
Job [1] (186207) stopped by signal 20
tsh> jobs
[1] (186207) Stopped ./mycont 10
# Now continue it, but not through fg/bg in shell
tsh> jobs
[1] (186207) Stopped ./mycont 10
Output of 'diff test reference':
6c6
< Job [1] (186197) stopped by signal 20
---
> Job [1] (186207) stopped by signal 20
8c8
< [1] (186197) Stopped ./mycont 10
---
> [1] (186207) Stopped ./mycont 10
11c11
< [1] (186197) Running ./mycont 10
---
> [1] (186207) Stopped ./mycont 10
我们注意到例程 tshref 在对子进程的 SIGCONT 信号发送后
仍然输出了 Stopped 状态。
我起初以为是 tshref 例程存在问题,当成笑话发给 AI。
AI 一通分析后指出是这里的测试点错了。
trace28.txt 的内容中有这样一段:
# Now continue it, but not through fg/bg in shell
SIGNAL # inform the child to continue its parent
/bin/echo -e tsh\076 jobs
NEXT
jobs
这里发送了一个信号给 mycont 程序。
让我们再来看看该程序中处理此信号的方式:
if (fork() == 0) {
/* Child. */
/* ... */
ssize_t rc;
if ((rc = send(syncfd, cmdp, strlen(cmdp), 0)) < 0) {
perror("send");
exit(1);
}
if ((rc = recv(syncfd, buf, MAXBUF, 0)) < 0) {
perror("recv");
exit(1);
}
/* Send SIGCONT after handshake */
kill(getppid(), SIGCONT);
exit(0);
}
我们注意到子进程在收到测评机发来的信号后,
将一个 SIGCONT 信号发给了自己的亲进程,
即是从我们的 tsh 中启动的那个。
但注意到,系统调度的次序是任意的,
即孙进程可能在 kill 后立即被调度走,
待评测机和 tsh 运行 jobs 命令结束后
子进程才被继续执行,收到信号,
然后才触发 tsh 的信号处理函数,
更新 Running 状态。
由此导致了如上的偶发错误。 在我的机器上,此错误的复现率约为 1%。
显然此错误在其他测试点中很可能同样存在, 但由于本人能力不足,暂时无法查清究竟哪些测试点受到影响。
因此,各位同学在做 Shell Lab 遇到玄学问题时, 不要怀疑,因为:
错的真的可能不是你,而是题。