什么是vdso和vsyscall?

时间:2013-11-12 19:37:27

标签: c linux linux-kernel kernel vdso

我做了sudo cat /proc/1/maps -vv

我试图理解输出。我可以看到很多共享库按预期映射到内存映射段。

7f3c00137000-7f3c00179000 r-xp 00000000 08:01 21233923                   /lib/x86_64-linux-gnu/libdbus-1.so.3.5.8
7f3c00179000-7f3c00379000 ---p 00042000 08:01 21233923                   /lib/x86_64-linux-gnu/libdbus-1.so.3.5.8
7f3c00379000-7f3c0037a000 r--p 00042000 08:01 21233923                   /lib/x86_64-linux-gnu/libdbus-1.so.3.5.8
7f3c0037a000-7f3c0037b000 rw-p 00043000 08:01 21233923                   /lib/x86_64-linux-gnu/libdbus-1.so.3.5.8
7f3c0037b000-7f3c00383000 r-xp 00000000 08:01 21237216                   /lib/x86_64-linux-gnu/libnih-dbus.so.1.0.0
7f3c00383000-7f3c00583000 ---p 00008000 08:01 21237216                   /lib/x86_64-linux-gnu/libnih-dbus.so.1.0.0
7f3c00583000-7f3c00584000 r--p 00008000 08:01 21237216                   /lib/x86_64-linux-gnu/libnih-dbus.so.1.0.0
7f3c00584000-7f3c00585000 rw-p 00009000 08:01 21237216                   /lib/x86_64-linux-gnu/libnih-dbus.so.1.0.0
7f3c00585000-7f3c0059b000 r-xp 00000000 08:01 21237220                   /lib/x86_64-linux-gnu/libnih.so.1.0.0
7f3c0059b000-7f3c0079b000 ---p 00016000 08:01 21237220                   /lib/x86_64-linux-gnu/libnih.so.1.0.0
7f3c0079b000-7f3c0079c000 r--p 00016000 08:01 21237220                   /lib/x86_64-linux-gnu/libnih.so.1.0.0

接近尾声有类似

的东西
7f3c0165b000-7f3c0177e000 rw-p 00000000 00:00 0                          [heap]
7fff97863000-7fff97884000 rw-p 00000000 00:00 0                          [stack]
7fff97945000-7fff97946000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

vdsovsyscall是什么意思? vsyscall内存的内核部分?如果有人能够对这个问题有所了解,那就太好了。

2 个答案:

答案 0 :(得分:129)

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

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

通过使用特殊陷阱指令替换固定地址处的所有系统调用指令,解决了此安全问题。尝试调用 vsyscall 页面的应用程序将陷入内核,然后内核将模拟内核空间中所需的虚拟系统调用。结果是一个内核系统调用模拟一个虚拟系统调用,它被放在那里以避免首先调用内核系统。结果是 vsyscall ,执行时间更长,但关键是,不会破坏现有的ABI。在任何情况下,仅当应用程序尝试使用 vsyscall 页面而不是 vDSO 时才会看到减速。

vDSO 提供与vsyscall相同的功能,同时克服了其局限性。 vDSO(虚拟动态链接共享对象)是在用户空间中分配的存储区域,其以安全的方式暴露用户空间中的一些内核功能。 这是为了解决SYSCALL引起的安全威胁而引入的。 vDSO是动态分配的,它解决了安全问题,可以进行4次以上的系统调用。 vDSO 链接通过glibc库提供。链接器将链接glibc vDSO 功能,前提是此类例程具有附带的 vDSO 版本,例如vsyscall。当您的程序执行时,如果您的内核没有 vDSO 支持,则会进行传统的系统调用。

致谢和有用的链接:

答案 1 :(得分:6)

我只想在新内核中添加它,vDSO不仅用于" safe"系统调用,但它用于决定哪种系统调用机制是在系统上调用系统调用的首选方法。