微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Linux如何提取系统调用的第六个参数?

在32位英特尔架构中,mmap2系统调用有6个参数。 第六个参数存储在ebp寄存器中。 然而,在通过sysenter进入内核之前,会发生这种情况(在linux-gate.so.1中 ,由内核映射到用户进程的代码页):

push %ebp movl %esp,%ebp sysenter

这意味着ebp现在应该有栈指针的内容而不是第六个参数。 Linux如何获得正确的参数?

在Linux中调度中断和系统调用

使用PTRACE(2)读取进程的stderr

如何从用户空间访问系统调用

Linux系统调用,libc,VDSO和实施解剖

在给定受保护的内存时,如何使系统调用调用我的SIGSEGV处理程序?

那个链接评论中的博客文章一个链接到Linus的帖子 ,这给了我一个答案的线索:

这意味着现在内核可以很高兴地将%ebp作为第六个参数设置的一部分进行%ebp ,因为系统调用重新启动将重新初始化它以指向我们在%ebp所需的用户级堆栈,否则它将完全丢失。

我是一个恶心的猪,并为它引导感到自豪。

– Linus Torvalds

事实证明, sysenter被设计为要求用户空间与内核协作保存返回地址和用户空间堆栈指针。 (进入内核后, %esp将成为内核堆栈。)它比int 0x80方式更少,这就是为什么它更快。

在进入内核之后,内核在%ebp拥有用户间的%esp值,无论如何它都需要它。 它从用户空间栈存储器访问第6个参数,以及SYSEXIT的返回地址。 输入后立即(%ebp)保存第6个系统调用参数。 从迈克尔的评论:“这是32位sysenter_target代码 :看看行417开始部分”

从英特尔的SYSENTER指令参考手册条目( x86 wiki中的链接):

SYSENTER和SYSEXIT指令是配套指令,但不构成调用/返回对。 执行SYSENTER指令时,处理器不保存用户代码(例如指令指针)的状态信息,SYSENTER和SYSEXIT指令都不支持在堆栈上传递参数。 要将SYSENTER和SYSEXIT指令作为配置指令在特权级别3代码和特权级别0操作系统过程之间转换,必须遵循以下约定:

特权级别0代码和堆栈段以及特权级别3代码和堆栈段的段描述符在描述符表中必须是连续的。 该约定允许处理器根据在SYSENTER_CS_MSR MSR中输入的值计算段选择器。

如果需要返回调用过程,用户代码(通常在共享库或DLL中)执行的快速系统调用“存根”例程必须保存所需的返回IP和处理器状态信息。 同样,用SYSENTER指令调用的操作系统或执行程序在返回用户代码时必须能够访问和使用这个保存的返回和状态信息。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐