ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

深入理解系统调用

2020-05-25 23:03:59  阅读:226  来源: 互联网

标签:调用 34 理解 64 linux 深入 include socketpair


1. 实验要求


  • 本人学号后两位为53,则寻找系统调用号为53的系统调用

  • 通过汇编指令触发该系统调用

  • 通过gdb跟踪该系统调用的内核处理过程

  • 重点阅读分析系统调用入口的保存现场、恢复现场和系统调用返回,以及重点关注系统调用过程中内核堆栈状态的变化

2. 环境搭建

2.1 安装环境

在实验一中已经安装过了环境,如果需要可以按照以下命令:

sudo apt install build-essential
sudo apt 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
# 建议不要使用上面命令,下载慢,可以提前下载好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

2.2 配置内核编译选项

运行以下命令:

 make defconfig 
 make menuconfig

进入 Kernel hackingCompile-time checks and compiler options:

进入Processor type and features:

2.3 编译内核

运行以下命令:

make -j$(nproc)
qemu-system-x86_64 -kernel arch/x86/boot/bzImage

由于没有文件系统,最终会 kernel panic

2.4 利用busybox制作根文件系统

下载并制作根文件系统:

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
make -j$(nproc) && make install

在配置选项时进入Settings,选择Build static binary (no shared libs)

制作内存根文件系统镜像:

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脚本,并修改权限:

vi init

#!/bin/sh
mount -t proc none /proc mount -t sysfs none /sys
echo "Wellcome WangbaOS!"
cd home
/bin/sh

chmod +x init

打包成内存根文件系统镜像,并测试挂载根文件系统:

find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../rootfs.cpio.gz

cd ..

qemu-system-x86_64 -kernel linux-5.4.34/arch/x86/boot/bzImage -initrd rootfs.cpio.gz

运行结果如下:

3. 汇编指令触发该系统调用

3.1 查询系统调用号为53为的系统调用

使用以下命令查询:

cd linux-5.4.34/arch/x86/entry/syscalls  # 进入syscalls文件夹

cat syscall_64.tbl | grep 53  # 查询和53相关的系统调用

可以看到是 socketpair:

使用手册看该函数:

man socketpair

从上面的描述中可以看出:

socketpair 函数用于创建一对无名的、相互连接的套接字;如果函数成功,则返回0,创建好的套接字分别是sv[0]sv[1];否则返回-1,错误码保存于errno中。

3.2 编写普通汇编调用代码

rootfs/home 编写socketpair.c,如下:

#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <error.h> 
#include <errno.h> 
#include <sys/socket.h> 
#include <stdlib.h> 
 
const char* str = "SOCKET PAIR TEST.";
 
int main(int argc, char* argv[]){
    char buf[128] = {0};
    int socket_pair[2]; 
    pid_t pid; 
 
    if(socketpair(AF_UNIX, SOCK_STREAM, 0, socket_pair) == -1 ) { 
      // 如果返回-1,打印errno
        printf("Error, socketpair create failed, errno(%d): %s\n", errno, strerror(errno));
        return EXIT_FAILURE; 
    } 
 
    int size = write(socket_pair[0], str, strlen(str));  	// 将str从socket_pair[0]写入
  
    read(socket_pair[1], buf, size);
    printf("Read result: %s\n",buf);    // 将str从socket_pair[1]读出,并打印结果
  
    return EXIT_SUCCESS;    
} 

gcc 静态编译,并运行,可以看到 str 的值:

4. 利用gdb跟踪系统调用的内核处理过程

4.1 重新制作根文件系统,并启动qemu

find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../rootfs.cpio.gz

cd ..

qemu-system-x86_64 -kernel linux-5.4.34/arch/x86/boot/bzImage -initrd rootfs.cpio.gz -S -s -nographic -append "console=ttyS0"

重新打开一个终端,并运行以下命令:

# 打开gdb
gdb vmlinux
target remote:1234

# 并在gdb中对__x64_sys_socketpair进行断点
b __x64_sys_socketpair

输入c(continue)继续运行。

4.2 在qemu窗口运行程序并在gdb窗口进行单步调试

qemu窗口:

gdb窗口:

可以看到调用了 net/socket.c下的1619行:

又调用了do_syscall_64

继续调用了entry_SYSCALL_64 ()

整个流程大概如下:

用户态:

socketpair.c ----> __x64_sys_socketpair ----> _sys_socketpair

内核态:

entry_SYSCALL_64 () ----> do_syscall_64 ----> _sys_socketpair ----> do_syscall_64 ----> syscall_return_slowpath() ----> entry_SYSCALL_64 ()

标签:调用,34,理解,64,linux,深入,include,socketpair
来源: https://www.cnblogs.com/woderfuleight/p/12961532.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有