举例跟踪分析Linux内核5.0系统调用处理过程

学号后三位<126>

原创作品转载请注明出处https://github.com/mengning/linuxkernel/

 

一、编译内核5.0

// 安装所需依赖
sudo apt install bison flex libssl-dev gcc-multilib

// 下载并编译内核
wget https://github.com/mengning/linux/archive/v5.0.tar.gz
tar -zxvf v5.0.tar.gz
cd v5.0.tar.gz
make i386_defconfig

// 制作文件系统
cd ..
mkdir rootfs
git clone https://github.com/mengning/menu.git
cd menu
gcc -pthread -o init linktable.c menu.c test.c -m32 -static
cd ../rootfs
cp ../menu/init ./
find . | cpio -o -Hnewc | gzip -9 > ../rootfs.img

 

二、启动MenuOS准备跟踪分析

qemu-system-i386 -kernel bzImage -initrd rootfs.img

// 通过gdb跟踪调试内核启动
qemu-system-i386 -kernel bzImage -initrd rootfs.img -S -s -append nokaslr
cd linux-5.0
gdb vmlinux

 

三、选择系统调用进行分析

选择学号后两位的系统调用<26>

 

编写分析用的test.c

/*test.c*/
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <linux/user.h>   
int main()
{
   pid_t child;
    long orig_eax;
    child = fork();
    if(child == 0) {
        ptrace(PTRACE_TRACEME, 0, NULL, NULL);
        execl("/bin/ls", "ls", NULL);
    }
    else {
        wait(NULL);
        orig_eax = ptrace(PTRACE_PEEKUSER, 
                          child, 4 * ORIG_EAX, 
                          NULL);
        printf("The child made a "
               "system call %ld ", orig_eax);
        ptrace(PTRACE_CONT, child, NULL, NULL);
    }
    return 0;
}

 

得到输出入下:

The child made a system call 11

 

系统调用分析:

在上述输出中,父进程fork了一个子进程并跟踪。在调用exec前,子进程使用PTRACE_TRACEME作第一个参数调用ptrace,它告诉内核:让别人跟踪我吧!然后,在子进程调用execve()后,它将控制权交还给父进程。当时父进程正使用wait()函数来等待来自内核的通知,现在它得到了通知,于是它可以开始察看子进程都作了些什么,比如看看寄存器的值之类。

 

四、实验总结

本次实验中,系统调用主要就是一种用户态到内核态最后再到用户态的一种过程,用户态可以说成间接操作内存的程序,而内核态也就是通过汇编代码直接操作内存,而他们再转换过程中,由于涉及上下文的切换问题,所以需要对内容进行保护,所以再进入中断程序前,将内核态寄存器的值放入栈中,在程序结束后再进行出栈。而且中断有两个重要的属性,中断号和中断处理程序。中断号用来标识不同的中断,不同的中断具有不同的中断处理程序。在操作系统内核中维护着一个中断向量表(Interrupt Vector Table)。这个数组存储了全部中断处理程序的地址,而中断号就是对应中断在中断向量表中的偏移量。

 

posted @ 2019-03-19 15:11  Prinny  阅读(232)  评论(0编辑  收藏  举报