0%

Linux-Lab0-Preparation

Experimental preparation

在 Github 上下载对应的实验文件:linux-kernel-labs/linux: Linux kernel source tree (github.com)

tools/labs 目录中输入命令:

1
2
make clean
LABS=kernel_modules make skels

然后在 skels/kernel_modules 目录中就会有实验文件:

1
2
3
➜  labs git:(master) ✗ ls skels/kernel_modules/
1-2-test-mod 4-multi-mod 6-cmd-mod 8-kdb
3-error-mod 5-oops-mod 7-list-proc 9-dyndbg

Booting the virtual machine

虚拟机基础结构摘要:

  • ~/src/linux:Linux 内核源代码,编译模块需要
  • ~/src/linux/tools/labs/qemu:用于生成和运行 QEMU VM 的脚本和辅助文件

为了启动虚拟机,我们需要在 ~/src/linux/tools/labs 目录中使用 make boot 命令:

1
2
3
4
5
6
7
8
➜  labs git:(master) ✗ make boot 
make -C /home/yhellow/linux
make[1]: 进入目录“/home/yhellow/linux”
SYSTBL arch/x86/include/generated/asm/syscalls_32.h
SYSHDR arch/x86/include/generated/uapi/asm/unistd_32.h
SYSHDR arch/x86/include/generated/uapi/asm/unistd_64.h
SYSHDR arch/x86/include/generated/uapi/asm/unistd_x32.h
......

在默认情况下,您不会收到提示或任何图形界面,但您可以使用 minicom 或屏幕连接到虚拟机公开的控制台:

  • ~/src/linux/tools/labs 目录中使用 minicom -D serial.pts
1
➜  labs git:(master) ✗ minicom -D serial.pts
1
2
3
4
5
6
7
Welcome to minicom 2.7.1

OPTIONS: I18n
Compiled on Dec 23 2019, 02:06:26.
Port serial.pts, 19:21:44

Press CTRL-A Z for help on special keys
  • 要访问虚拟机,请在登录提示符下输入用户名 root,无需输入密码
  • 虚拟机将使用 root 帐户的权限启动
1
2
3
4
5
6
Poky (Yocto Project Reference Distro) 2.3 qemux86 /dev/hvc0

qemux86 login: root
root@qemux86:~# whoami
root
root@qemux86:~#

Adding and using a virtual disk

在目录中,您有一个新的虚拟机磁盘,位于文件 ~/src/linux/tools/labs/mydisk.img,我们要将磁盘添加到虚拟机中,并在虚拟机中使用它

  • 如果没有 mydisk.img 文件,则在如下网站中下载:mydisk.img

修改 ~/src/linux/tools/labs/qemu/Makefile,在对应位置添加如下代码:

1
2
3
4
-drive file=$(YOCTO_IMAGE),if=virtio,format=raw \
-drive file=disk1.img,if=virtio,format=raw \
-drive file=disk2.img,if=virtio,format=raw \
-drive file=mydisk.img,if=virtio,format=raw \ # new

启动虚拟机,创建目录并尝试挂载新磁盘

  • 已经向 qemu 添加了两个磁盘(disk1.imgdisk2.img
1
2
root@qemux86:~# /dev/vd                                                         
vda vdb vdc vdd
  • vda 是根分区,vdb 是 disk1.img,vdc 是 disk2.img,vdd 是 mydisk.img
  • 无需在 /dev 中手动创建新磁盘的条目,因为虚拟机使用 devtmpfs(在 Linux 内核启动早期建立一个初步的 /dev,令一般启动程序不用等待 udev)
  • 使用 mount 命令进行挂载:
1
2
mkdir /test
mount /dev/vdd /test
  • 结果挂载失败了(/test 中并没有出现 mydisk.img 中的文件),我们无法挂载虚拟磁盘的原因是,我们在内核中没有支持格式化的文件系统
  • 您需要识别 mydisk.img 的文件系统,并编译对该文件系统的内核支持
1
2
➜  labs git:(master) ✗ file mydisk.img 
mydisk.img: BTRFS Filesystem sectorsize 4096, nodesize 4096, leafsize 4096, UUID=df3c665a-363d-46f8-aef0-f9959bad6832, 32768/104857600 bytes used, 1 devices
  • 您需要在内核中启用 btrfs 支持并重新编译内核映像(退出前记得 save)
1
2
3
make menuconfig
----------------------------------------
File systems -> Btrfs filesystem support
1
2
3
4
5
6
7
root@qemux86:~# mount /dev/vdd /test                                            
BTRFS: device fsid df3c665a-363d-46f8-aef0-f9959bad6832 devid 1 transid 9 /dev/)
BTRFS info (device vdd): disk space caching is enabled
root@qemux86:~# ls /test
README
root@qemux86:~# cat /test/README
Congratulations, you were able to follow instructions!

GDB spelunking

使用 gdb 显示创建内核线程 kernel_thread 的函数的源代码

  • 使用 gdb 查找内存中 jiffies 变量的地址及其内容
  • 该变量保存自系统启动以来的计时周期数

要跟踪 jiffies 变量的值,请在 gdb 中使用动态分析,方法是:

  • 先启动虚拟机
  • 然后运行 make gdb 命令

PS:由于我这里的环境有点问题,所以我使用了 gdb vmlinux 外加 target remote :1234 的形式来进行调试(也可以参考一下)

1
2
pwndbg> x/gx & jiffies
0xc194b500 <jiffies_64>: 0x00000000ffff96c2