深入理解系统调用
一、实验内容
找一个系统调用,系统调用号为学号最后2位相同的系统调用
通过汇编指令触发该系统调用
通过gdb跟踪该系统调用的内核处理过程
重点阅读分析系统调用入口的保存现场、恢复现场和系统调用返回,以及重点关注系统调用过程中内核堆栈状态的变化
二、实验环境配置
sudo apt install build-essential sudo apt install qemu # install QEMU sudo apt install libncurses5-dev bison flex libssl-dev libelf-dev sudo apt install axel
axel -n 20 https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.4.34.tar.xz xz -d linux-5.4.34.tar.xz tar -xvf linux-5.4.34.tar
cd linux-5.4.34
make defconfig make menuconfig
#打开debug相关选项 Kernel hacking ---> Compile-time checks and compiler options ---> [*] Compile the kernel with debug info [*] Provide GDB scripts for kernel debugging [*] Kernel debugging
#关闭KASLR,否则会导致打断点失败 Processor type and features ----> [] Randomize the address of the kernel image (KASLR)
编译内核
make -j$(nproc)
测试一下内核能不能正常加载运行,因为没有文件系统最终会kernel panic
qemu-system-x86_64 -kernel arch/x86/boot/bzImage
制作根文件系统
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
make menuconfig
/*
记得要编译成静态链接,不用动态链接库。
Settings --->
[*] Build static binary (no shared libs)
然后编译安装,默认会安装到源码目录下的 _install 目录中。
*/
make -j$(nproc) && make install
制作内存根文件系统镜像
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/
准备init脚本文件放在根文件系统跟目录下(rootfs/init),内核才能加载启动文件从而启动,
#!/bin/sh mount -t proc none /proc mount -t sysfs none /sys echo "Wellcome MengningOS!" echo "--------------------" cd home /bin/sh 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
可以看到内核成功启动
三.查看系统调用表
打开linux内核下arch/x86/entry/syscalls/syscall_64.tbl文件,查看系统调用列表。选择04号系统调用,对应的系统调用为stat。
查看stat函数定义:int stat(const char *path, struct stat *buf);
该函数用来获取文件属性,返回值:成功返回0,失败返回-1
编写汇编指令触发系统调用功能:
int main() { asm volatile( "movl $0x04,%eax\n\t" //使⽤EAX传递系统调⽤号04 "syscall\n\t" //触发系统调⽤ ); return 0; }
四.gdb调试
使用gcc静态编译,并重新打包
gcc -o test_dup test_dup.c -static find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../rootfs.cpio.gz
进行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 cd linux-5.4.34 # 启动 gdb vmlinux target remote:1234 # 在semctl调用处打断点 b __x64_sys_semctl