1、系统调用号查询
打开/linux-5.4.34/arch/x86/entry/syscalls/syscall_64.tbl
,查看要选择进行实验的系统调用。系统调用为mlockall。
mlockall() 将进程使用的部分或者全部的地址空间锁定在物理内存中,防止其被交换到swap空间。有些对时间敏感的应用会希望全部使用物理内存,以提高数据访问和操作的效率。
2、实验环境搭建
make menuconfig
勾选Compile the kernel with debug info,并且关闭KASLR
make -j$(nproc)
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
勾选Bulid static binary (no shared libs)
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文件的内容
#!/bin/sh mount -t proc none /proc mount -t sysfs none /sys echo "Wellcome MyOS!" echo "--------------------" cd home /bin/sh
给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
3、汇编语言调用
#include#include int main(){ int o; o=mlockall(MCL_CURRENT); printf("out:%d\n",o); return 0; }
然后静态编译
gcc -o gsn gsn.c -static
改写触发系统调用
#include#include int main(){ int o; int i; asm volatile( "movq $0x1, %%rdi\n\t" "movl $0x97, %%eax\n\t" "syscall\n\t" "movq %%rax, %0\n\t" :"=m"(o) :"g"(in) ) printf("out: %d \n",o) return 0; }
编译后查看结果
4、gdb调试与分析
并且在另一个终端开启调试
连接进行调试
gdb输入命令c
在gdb函数入口做断点,监听,然后在虚拟机中执行gsn
断点定位到端口799
执行完这个函数,到do_sys_call_64
中 ,接下来为要执行的 syscall_return_slowpath
函数恢复现场
继续执行,再次entry_SYSCALL_64
,接下来执行用于恢复现场的汇编指令,最后popq出栈指令,恢复了rdi
和rsp
寄存器,系统调用完成
5、总结
触发系统调用后,通过调用swapgs和压栈保存了现场,然后通过do_syscall_64
函数,在ax寄存器中得到系统调用号,然后去执行系统调用。再完成执行现场的恢复,然后出栈指令恢复原 rdi 和 rsp的内容,也就是完成了堆栈的切换。