linux-kernel - vsdo 和 vsyscall 的区别

标签 linux-kernel x86 system-calls

我试图了解 Linux 用于调用系统调用的机制。特别是,我很难理解 VSDO 机制。可以用来调用所有系统调用吗?进程内存中的vsdo页面和vsyscall页面有什么区别?他们总是在那里吗?

例如使用 cat/proc/self/maps :

7fff32938000-7fff32939000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

最好的事物,

最佳答案

vsyscall 和 vDSO 段是用于加速 Linux 中某些系统调用的两种机制。例如,gettimeoftheday通常通过这种机制调用。引入的第一个机制是 vsyscall,它是作为一种执行特定系统调用的方式而添加的,这些系统调用不需要任何真正级​​别的特权来运行,以减少系统调用开销。按照前面的例子,所有 gettimeofday需要做的是读取内核的当前时间。有应用调用gettimeofday经常(例如生成时间戳),以至于他们甚至关心一点点开销。为了解决这个问题,内核将包含当前时间和快速 gettimeofday 的页面映射到用户空间。实现(即只是一个读取保存到 vsyscall 中的时间的函数)。使用这个虚拟系统调用,C 库可以提供一个快速的 gettimeofday它没有通常由经典系统调用模型引入的内核空间和用户空间之间的上下文切换引入的开销INT 0x80SYSCALL .

但是,这种vsyscall机制有一些局限性:分配的内存很小,只允许4个系统调用,而且更重要和严重的是,vsyscall页面在每个进程中静态分配到同一个地址,因为vsyscall页面的位置是确定在内核 ABI 中。 vsyscall 的这种静态分配损害了 Linux 常用的内存空间随机化带来的好处。攻击者在利用堆栈溢出危害应用程序后,可以使用任意参数从 vsyscall 页面调用系统调用。他所需要的只是系统调用的地址,因为它是静态分配的,所以很容易预测(如果您尝试再次运行您的命令,即使使用不同的应用程序,您会注意到 vsyscall 的地址不会改变)。
最好删除或至少随机化 vsyscall 页面的位置以阻止此类攻击。不幸的是,应用程序依赖于该页面的存在和确切地址,因此无能为力。

此安全问题已通过用特殊陷阱指令替换固定地址处的所有系统调用指令得到解决。尝试调用 vsyscall 页面的应用程序将陷入内核,然后内核将在内核空间中模拟所需的虚拟系统调用。结果是一个内核系统调用模拟了一个虚拟系统调用,它被放在那里首先是为了避免内核系统调用。结果是 vsyscall 需要更长的时间来执行,但至关重要的是,不会破坏现有的 ABI。在任何情况下,只有当应用程序尝试使用 vsyscall 页面而不是 vDSO 时才会看到速度变慢。 vDSO 提供与 vsyscall 相同的功能,同时克服了其局限性。 vDSO(虚拟动态链接共享对象)是在用户空间分配的内存区域,它以安全的方式在用户空间公开一些内核功能。
引入这个是为了解决vsyscall引起的安全威胁。 .
vDSO 是动态分配的,解决了安全问题,并且可以有 4 个以上的系统调用。 vDSO 链接通过 glibc 库提供。链接器将链接 glibc vDSO 功能,前提是此类例程具有随附的 vDSO 版本,例如 gettimeofday .当您的程序执行时,如果您的内核不支持 vDSO,则会进行传统的系统调用。

积分和有用的链接:

  • Awesome tutorial, how to create your own vDSO .
  • vsyscall andvDSO, nice article
  • useful article and links
  • What is linux-gate.so.1?
  • 关于linux-kernel - vsdo 和 vsyscall 的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15613687/

    相关文章:

    assembly - “PUSH”指令的操作可以用其他指令执行吗?

    c - 如何从用户 ID 中检索用户名

    c - 无法释放键盘 irq 线 : Device or resource busy

    linux - 如何识别 linux block 设备的请求队列

    performance - 使用perf_event_open监视Docker容器

    c - 启用从用户空间进程调试内核模块

    performance - Haswell内存访问

    c - .byte 在这个 asm 行中是什么意思?

    linux - gem5 系统调用仿真 arm C hello world 失败,出现 "fatal: syscall gettid (#224) unimplemented"

    子父进程与管道的进程间通信