深入理解系统调用
一、实验内容
1使用94号系统调用
2.通过汇编指令触发系统调用
3.通过gdb跟踪该系统调用的内核处理过程
4.阅读分析系统调用入口的保存现场、恢复现场和系统调用返回,以及关注系统调用过程中内核堆栈状态的变化
二、环境搭建
1、安装开发工具
1 sudo apt install build-essential 2 sudo apt install qemu 3 sudo apt install libncurses5-dev bison flex libssl-dev libelf-dev 4 sudo apt install axel
2、下载内核源码
1 axel -n 20 https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.4.34.tar.xz 2 xz -d linux-5.4.34.tar.xz 3 tar -xvf linux-5.4.34.tar cd linux-5.4.34
3、配置内核选项
1 make defconfig #Default configuration is based on 'x86_64_defconfig' 2 make menuconfig 3 //打开debug相关选项 4 Kernel hacking ---> 5 Compile-time checks and compiler options ---> 6 [*] Compile the kernel with debug info 7 [*] Provide GDB scripts for kernel debugging [*] Kernel debugging 8 //关闭KASLR,否则会导致打断点失败 9 Processor type and features ----> 10 [] Randomize the address of the kernel image (KASLR)
4、编译和运行内核
1 make -j$(nproc) 2 //测试一下内核能不能正常加载运行,因为没有文件系统最终会kernel panic 3 qemu-system-x86_64 -kernel arch/x86/boot/bzImage //此时应该无法正常运行
5、制作根文件系统
下载 busybox源代码解压
1 axel -n 20 https://busybox.net/downloads/busybox-1.31.1.tar.bz2 2 tar -jxvf busybox-1.31.1.tar.bz2 3 cd busybox-1.31.1
配置编译 并安装
1 make menuconfig 2 记得要编译成静态链接,不用动态链接库。 3 Settings ---> 4 [*] Build static binary (no shared libs) 5 然后编译安装,默认会安装到源码目录下的 _install 目录中。 6 make -j$(nproc) && make install
6、制作内存根文件系统镜像
1 mkdir rootfs
2 cd rootfs
3 cp ../busybox-1.31.1/_install/* ./ -rf
4 mkdir dev proc sys home
5 sudo cp -a /dev/{null,console,tty,tty1,tty2,tty3,tty4} dev/
7、 准备init脚本文件放在根文件系统跟目录下(rootfs/init),添加如下内容到init文件。
1 #!/bin/sh 2 mount -t proc none /proc mount -t sysfs none /sys 3 echo "Wellcome MengningOS!" echo "--------------------" 4 cd home 5 /bin/sh
8、给init脚本添加可执行权限
1 chmod +x init
打包成内存根文件系统镜像
1 find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../rootfs.cpio.gz

查看系统调用

查看文档可知94号系统调用为lchown。对应的内核处理函数为__x64_sys_lchown。作用:修改文件所有者和组别。触发这一系统调用,我们需要写一个小程序。使用内联汇编小程序test1.c如下:
int main()
{
asm volatile(
"movl $0x5E,%eax\n\t" //使⽤EAX传递系统调⽤号94
"syscall\n\t" //触发系统调⽤
);
return 0;
}
9、使用gcc静态编译,并重新打包
1 gcc -o test1 test1.c -static
2 find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../rootfs.cpio.gz
可以看到,文件已编译成功


10、执行下列命令,进行gdb调试。
qemu-system-x86_64 -kernel linux-5.4.34/arch/x86/boot/bzImage -initrd rootfs.cpio.gz -S -s -nographic -append "console=ttyS0" #开启新的terminal cd linux-5.4.34 gdb vmlinux target remote:1234
#设置断点
b __x64_sys_lchown

11、进行gdb单步调试



三、结果分析
1. 汇编指令syscall 触发系统调用,通过MSR寄存器找到了中断函数入口
用户态程序触发系统调用-》然后系统进入内核态,完成内核初始化-》调用entry_SYSCALL_64 ()。通过 swapgs 指令保存现场

然后,执行了do_syscall_64这一内核函数,跳转获得系统调用号,执行系统调用的内容
调用结束,恢复到用户态执行
syscall_return_slowpath 函数要为恢复现场做准备。

最后swapgs——恢复现场。


浙公网安备 33010602011771号