Linux 什么是 vdso 和 vsyscall?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19938324/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-07 01:19:08  来源:igfitidea点击:

What are vdso and vsyscall?

clinuxlinux-kernelkernelvdso

提问by liv2hak

I did sudo cat /proc/1/maps -vv

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

I am attempting to make sense of the output.I can see a lot of shared libraries being mapped to the memory mapping segment as expected.

我正在尝试理解输出。我可以看到许多共享库按预期映射到内存映射段。

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

Towards the end there is something like

到最后有类似的东西

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]

What does vdsoand vsyscallmean? is vsyscall the kernel portion of the memory? It would be great if anyone can throw some light on the issue.

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

采纳答案by Giuseppe Pes

The vsyscalland vDSOsegments are two mechanisms used to accelerate certain system calls in Linux. For instance, gettimeofdayis usually invoked through this mechanism. The first mechanism introduced was vsyscall, which was added as a way to execute specific system calls which do not need any real level of privilege to run in order to reduce the system call overhead. Following the previous example, all gettimeofdayneeds to do is to read the kernel's the current time. There are applications that call gettimeofdayfrequently (e.g to generate timestamps), to the point that they care about even a little bit of overhead. To address this concern, the kernel maps into user space a page containing the current time and a fast gettimeofdayimplementation (i.e. just a function which reads the time saved into vsyscall). Using this virtual system call, the C library can provide a fast gettimeofdaywhich does not have the overhead introduced by the context switch between kernel space and user space usually introduced by the classic system call model INT 0x80or SYSCALL.

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

However, this vsyscallmechanism has some limitations: the memory allocated is small and allows only 4 system calls, and, more important and serious, the vsyscallpage is statically allocated to the same address in each process, since the location of the vsyscallpage is nailed down in the kernel ABI. This static allocation of the vsyscall compromises the benefit introduced by the memory space randomisation commonly used by Linux. An attacker, after compromising an application by exploiting a stack-overflow, can invoke a system call from the vsyscallpage with arbitrary parameters. All he needs is the address of the system call, which is easily predicable as it is statically allocated (if you try to run again your command even with different applications, you'll notice that the address of the vsyscalldoes not change). It would be nice to remove or at least randomize the location of the vsyscall page to thwart this type of attack. Unfortunately, applications depend on the existence and exact address of that page, so nothing can be done.

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

This security issue has been addressed by replacing all system call instructions at fixed addresses by a special trap instruction. An application trying to call into the vsyscallpage will trap into the kernel, which will then emulate the desired virtual system call in kernel space. The result is a kernel system call emulating a virtual system call which was put there to avoid the kernel system call in the first place. The result is a vsyscallwhich takes longer to execute but, crucially, does not break the existing ABI. In any case, the slowdown will only be seen if the application is trying to use the vsyscallpage instead of the vDSO.

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

The vDSOoffers the same functionality as the vsyscall, while overcoming its limitations. The vDSO (Virtual Dynamically linked Shared Objects) is a memory area allocated in user space which exposes some kernel functionalities at user space in a safe manner. This has been introduced to solve the security threats caused by the vsyscall. The vDSO is dynamically allocated which solves security concerns and can have more than 4 system calls. The vDSOlinks are provided via the glibc library. The linker will link in the glibc vDSOfunctionality, provided that such a routine has an accompanying vDSOversion, such as gettimeofday. When your program executes, if your kernel does not have vDSOsupport, a traditional syscall will be made.

VDSO提供相同的功能vsyscall,同时克服其局限性。vDSO(虚拟动态链接共享对象)是在用户空间分配的内存区域,它以安全的方式在用户空间公开一些内核功能。引入此功能是为了解决由vsyscall. vDSO 是动态分配的,解决了安全问题,并且可以有 4 个以上的系统调用。该VDSO链接通过glibc库提供。链接器将链接 glibc vDSO功能,前提是此类例程具有随附的vDSO版本,例如gettimeofday. 当您的程序执行时,如果您的内核没有vDSO支持,将进行传统的系统调用。

Credits and useful links :

积分和有用的链接:

回答by incompetent

I just want to add that now in new kernels, vDSOis not used only for "safe" syscalls but it is used to decide which syscall mechanism is preferred method to invoke a syscall on the system.

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