实验要求“
- 找一个系统调用,系统调用号为学号最后2位相同的系统调用,学号末尾2位为10
- 通过汇编指令触发该系统调用
- 通过gdb跟踪该系统调用的内核处理过程
- 重点阅读分析系统调用入口的保存现场、恢复现场和系统调用返回,以及重点关注系统调用过程中内核堆栈状态的变化
一 环境准备
上次实验已经下载好内核源码参考https://www.cnblogs.com/russian/p/12873826.html,接下来进行内核编译选项。
配置内核编译选项,
首先打开debug相关选项 ;选择进入Kernel Hacking
接着选择 Compile-time checks and compiler options -->
修改下列两个选项为Y
然后关闭KASLR,否则会导致打断点失败,首先进入Processor type and features选项
保存退出。
二 制作根文件系统
1.下载跟文件系统 :
axel -n 20 https://busybox.net/downloads/busybox-1.31.1.tar.bz2
tar -jxvf busybox-1.31.1.tar.bz2
cd busybox-1.31.1
2.制作根文件系统:
make menuconfig
编译成静态链接,不用动态链接库:在setting中设置
然后编译安装,默认会安装到元年吗目录下_install目录中;
make -j$(nproc) && make install
3.接着制作内存根文件系统镜像
mkdir rootfs
cd rootfs
cp ../busybox-1.31.1/_install/* ./ -rf
mkdir dev proc sys home
sudo cp -a /dev/{null,console,tty,tty1,tty2,tty3,tty4} dev/
4.准备添加init脚本文件放根目录下,
touch init.sh
vi init.sh
i键入内容如下:
#!/bin/sh mount -t proc none /proc mount -t sysfs none /sys echo "Wellcome MengningOS!" echo "--------------------" cd home /bin/sh
保存退出 :wq
接着给init脚本添加可执行权限: chmod +x init
打包成内存根文件系统镜像:find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../rootfs.cpio.gz
测试挂在根文件系统,看内核启动完是否执行脚本:qemu-system-x86_64 -kernel linux-5.4.34/arch/x86/boot/bzImage -initrd rootfs.cpio.gz
最终挂载成功之后显示
三 系统调用
1.查看系统调用
打开内核源码中中断调用号,找到与自己学号末尾相同的中断服务例程,目录为linux-5.4.34/arch/x86/entry/syscalls/syscall_64.tbl
可知第10号调用为mprotect ,对应的处理函数为__x64_sys_mprotect。
2.编写汇编调用代码
由于我们搭建的系统不支持动态链接,因此这里我们在使用gcc编译时要用-static静态编译参数)。
gcc test.c -o test -static
3.重新执行根文件系统(重新打包,用qemu运行)
find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../rootfs.cpio.gz
qemu-system-x86_64 -kernel linux-5.4.34
/arch/x86/boot/bzImage
-initrd rootfs.cpio.gz
四 gdb调试。
1. 启动gdb调试
首先命令行启动qemu:
qemu-system-x86_64 -kernel linux-5.4.34/arch/x86/boot/bzImage -initrd rootfs.cpio.gz -S -s -nographic -append "console=ttyS0"
然后重新开一个命令行,在源码目录下启动gdb
gdb vmlinux
接着在gdb中运行:target remote:1234
然后给对应大的系统调用打上断点
如图成功触发断点。
2.gdb单步调试
五 结果分析‘
系统调用的保存现场和恢复现场;entry_SYSCALL_64是系统调用的入口点,它完成了保存现场,调用对应的内核处理函数、恢复现场、系统调用返回等工作。
汇编指令syscall 触发系统调用,通过MSR寄存器找到了中断函数入口;
可以看到,它没有使用sava_all命令保存现场,而使用了特殊的swapgs,来快照式地保存现场,加快了系统调用的速度。
接着跳转获得系统调用号,执行系统调用的内容
调用结束,恢复到用户态执行syscall_return_slowpath
函数要为恢复现场做准备
swapgs——恢复现场