系统调用的实现

内核态 用户态

  • 当前程序执行在什么态,由CS的最低两位来表示:0是内核态,3是用户态
  • 内核态可以访问任何数据,用户态不能访问内核数据
  • 对于指令跳转也一样
    在这里插入图片描述
  • DPL用来描述目标段
    CPL用来描述当前段
    在这里插入图片描述
  • 这样设置可以防止外部可以查看一些私密信息

实现一个whoami系统调用

  • 用户程序main是当前段
    CPL是3
  • 内核中函数whoami是目标段
    DPL是0
  • 因为DPL < CPL
  • 所以无法实现跳转,也就无法调用这个函数
    在这里插入图片描述

硬件提供了主动进入内核的方法

  • 使用终端指令int,可以将CS中的CPL改为0
  • 系统调用的核心:
    用户程序中包含一段包含int指令的代码
    操作系统写终端处理,获取想调程序的编号
    操作系统根据编号执行相应的代码
  • 过程:
    开始CPL = 3(main),DPL = 0(whoami)
    设置系统调用号eax = 72
    调用指令 int 0x80;使CPL = 3DPL = 3,可以使调用whoami()成功,一旦穿过接口,那么CPL = 0
    _system_call中通过移动查表调用了sys_whoami
    这时候再调用100就可以了
    在这里插入图片描述

Linux系统调用的实现细节

  • 应用程序调用printf(...)
  • 库函数要调用write(...)
  • 所以需要使用库函数_syscall3(),将printf里面的参数转化成write需要的格式,
    #include <unistd.h>
    // 3的意思是有3个参数,意思是只要有3个参数的都可以调用这个套路
    _syscall3(int, write, int, fd, const, char *buf, off_t, count)
    
  • 下面这段核心代码只有一句int 0x80
  • "=a"(__res)这个是输出
  • ""(__NR_##name)这个是输入
  • __NR_write是系统调用号
    在这里插入图片描述
  • __NR_##name__NR_#write)放入到eax中,将参数a,b,c放入到ebxecxedx
    在这里插入图片描述
  • 然后执行int 0x80,执行完之后,把eax置给res,最后return res,就返回了系统调用号。
int 0x80中断的处理
  • 下面代码的意思就是初始化表中0x80(中断处理号)所对应的中断处理函数,如果之后再遇到0x80,就直接调用这个函数就可以了
  • 经过下面的设置之后,DPL就等于3了,而CPL也是3,所以可以实现跳转
  • 同时设置了新的CS和IP,让CS的最后两位为00,就可以到内核中去执行相关的函数调用了
    在这里插入图片描述
中断处理程序:system_call
  • _sys_call_table是那个表
  • eax就是系统调用号
  • 乘以4的目的是每个系统调用占4个字节
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值