深入理解系统调用

实验内容:

  1. 找一个系统调用,系统调用号为学号最后2位相同的系统调用
  2. 通过汇编指令触发该系统调用
  3. 通过gdb跟踪该系统调用的内核处理过程
  4. 重点阅读分析系统调用入口的保存现场、恢复现场和系统调用返回,以及重点关注系统调用过程中内核堆栈状态的变化

一、搭建Linux内核调试环境

1.配置内核选项

make defconfig # Default configuration is based on 'x86_64_defconfig' 
make menuconfig 

打开内核选项界面后,打开debug相关选项,关闭KASLR

# 打开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)

2.编译和运行内核

make -j$(nproc) # nproc gives the number of CPU cores/threads available 
qemu-system-x86_64 -kernel arch/x86/boot/bzImage # 测试⼀下内核能不能正常加载运⾏,因为没有⽂件系统最终会kernel panic 

启动 qemu 后,从下图的最后一行可以看出来内核不能正常加载运行,并且终止在 kernel panic
深入理解系统调用_第1张图片

3.利用busybox制作内存根文件系统

# 下载 busybox 源代码并解压
axel -n 20 https://busybox.net/downloads/busybox-1.31.1.tar.bz2 # 下载 busybox 源代码
tar -jxvf busybox-1.31.1.tar.bz2 # 解压
cd busybox-1.31.1

# 配置编译,并安装
make menuconfig # 配置编译
#编译成静态链接,不⽤动态链接库。
#Settings ---> 
#  [*] Build static binary (no shared libs) 
make -j$(nproc) && make install # 编译安装,默认会安装到源码⽬录下的 _install ⽬录中。

# 制作内存根⽂件系统镜像
cd ..
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)并添加可执⾏权限
chmod +x init

init文件添加如下内容

#!/bin/sh 
mount -t proc none /proc 
mount -t sysfs none /sys 
echo "Wellcome MengningOS!" 
echo "--------------------" 
cd home 
/bin/sh
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 # 测试挂载根⽂件系统,看内核启动完成后是否执⾏init脚本

从下图能看到输出的 "Wellcome MengningOS!",说明内核启动后已经成功执行init脚本
深入理解系统调用_第2张图片

二、跟踪系统调用

学号后两位为06,查找到系统调用为 lstat,该系统调用的功能为获取文件属性。

自己写汇编代码,不设置参数, 直接将 0x06 放入 %eax,系统调用会出错,并且在操作过程中发现 ls 指令会调用 lstat,所以直接通过 ls 指令来捕捉 lstst 系统调用中断。
如下图所示,系统调用中断入口为 entry_SYSCALL_64, 然后调用 do_syscall_64, 最后进入系统调用执行函数 __x64_sys_newlstat。
深入理解系统调用_第3张图片

1. entry_SYSCALL_64保护现场和恢复现场过程

源码
深入理解系统调用_第4张图片
深入理解系统调用_第5张图片

我们来看一下gdb跟踪到的恢复现场过程跟上图相同
深入理解系统调用_第6张图片

通过源码跟踪发现 USERGS_SYSRET64 是一个宏定义,实际上执行了 快照恢复指令 swapgs 和 系统调用返回指令 sysretq
深入理解系统调用_第7张图片

2. do_syscall_64 分析

深入理解系统调用_第8张图片

gdb跟踪到的行为与代码也是一致的,do_syscall_64 最后执行的是 syscall_return_slowpath(regs)
深入理解系统调用_第9张图片

3. __x64_sys_newlstat代码实现

深入理解系统调用_第10张图片

你可能感兴趣的:(深入理解系统调用)