102

我做了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]

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

4

2 回答 2

181

vsyscall和vDSO段是用于加速 Linux 中某些系统调用的两种机制例如,gettimeofday通常通过这种机制调用。引入的第一个机制是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支持,将进行传统的系统调用。

学分和有用的链接:

于 2013-11-12T23:44:02.920 回答
11

我只想补充一点,现在在新内核中,vDSO它不仅用于“安全”系统调用,还用于决定哪种系统调用机制是在系统上调用系统调用的首选方法。

于 2016-01-01T15:57:28.470 回答