MIT 6.1810 · Lab syscall · 系统调用

Lab: 系统调用

在上一个实验中,你使用系统调用编写了一些工具。在本实验中,你将向 xv6 添加一个新的系统调用,帮助你了解它们的工作原理。

难度:中等

分支:syscall

实验日期:2026 秋季

在开始编码之前,阅读xv6 手册的第 2 章,以及第 4 章的 4.3 和 4.4 节,以及相关源文件:

要开始实验,切换到 syscall 分支:

$ git fetch
$ git checkout syscall
$ make clean

使用 gdb 简单

在许多情况下,print 语句足以调试内核,但有时单步执行代码或获取堆栈回溯很有用。GDB 调试器可以帮忙。

$ make qemu-gdb
# 在另一个窗口启动 gdb
(gdb) b syscall
Breakpoint 1 at 0x80002142: file kernel/syscall.c, line 243.
(gdb) c
Continuing.
(gdb) layout src
(gdb) backtrace

在 answers-syscall.txt 中回答以下问题:

查看回溯输出,哪个函数调用了 syscall?

键入 n 几次以单步执行过 struct proc *p = myproc();。一旦过了这条语句,键入 p /x *p,以十六进制打印当前进程的 proc struct。

p->trapframe->a7 的值是多少?该值代表什么?

CPU 之前处于什么模式?

写下内核 panic 的汇编指令。哪个寄存器对应变量 num?

为什么内核崩溃?提示:查看教材中的图 3-3;地址 0 在内核地址空间中是否映射?

内核 panic 时运行的进程名称是什么?它的进程 ID(pid)是什么?

沙箱化命令 中等

在这个任务中,你将"沙箱化"一个进程以限制它可以进行的系统调用。例如,可以沙箱化一个进程以禁止打开文件。你将创建一个新的 interpose 系统调用,指定内核应该拒绝哪些系统调用。

interpose 应该接受两个参数:一个整数掩码和一个路径。掩码的位指定要拒绝的系统调用。例如,要阻止进程使用 open 系统调用,它应该调用 interpose(1 << SYS_open, "-")。

$ sandbox 32768 - cat README
cat: cannot open README
$

一些提示:

允许路径名的沙箱 简单

在这个任务中,你将扩展沙箱以允许基于路径名的掩码 open 和 exec 系统调用。如果 open 或 exec 被掩码但路径名与允许的路径名匹配,则应该允许这些系统调用。

$ sandbox 32768 README grep xv6 README
xv6 is a re-implementation of Dennis Ritchie's and Ken Thompson's Unix Version 6 (v6).
$ sandbox 32768 README grep xv6 x
grep: cannot open x
$

攻击 xv6 中等

user/secret.c 在其内存中写入一个秘密字符串,然后退出(释放其内存)。你的目标是在 user/attack.c 中添加几行代码,找到前一次执行 secret.c 写入内存的秘密,并单独打印该秘密。

$ secret xyzzy
$ attack
xyzzy
$

本实验故意省略了 uvmalloc() 中的 memset(mem, 0, sz) 和 kalloc.c 中的两行 memset。结果是,新分配的内存保留上次使用的内容。

提交实验

时间花费

创建一个新文件 time.txt,放入一个整数,表示你花在实验上的小时数。

答案

将你的答案写在 answers-syscall.txt 中。

提交

运行 make zipball,上传到 Gradescope。

可选挑战练习