我正在开发一个使用 ptrace(2) 监视其他进程的系统调用的软件。不幸的是,大多数现代操作系统都实现了某种快速的用户模式系统调用,在 Linux 中称为vsyscalls。
有没有办法禁止对单个进程使用 vsyscalls/vDSO,或者,如果不可能,对整个操作系统禁用?
我正在开发一个使用 ptrace(2) 监视其他进程的系统调用的软件。不幸的是,大多数现代操作系统都实现了某种快速的用户模式系统调用,在 Linux 中称为vsyscalls。
有没有办法禁止对单个进程使用 vsyscalls/vDSO,或者,如果不可能,对整个操作系统禁用?
尝试echo 0 > /proc/sys/kernel/vsyscall64
如果您尝试对 gettimeofday 调用进行 ptrace 并且它们没有出现,那么系统使用的时间源是什么(pmtimer、acpi、tsc、hpet 等)。我想知道您是否会通过尝试将计时器强制设置为像 pmtimer 这样较旧的东西来取笑我。许多 gtod 计时器特定优化之一可能会导致您的 ptrace 调用被避免,即使 vsyscall 设置为零也是如此。
有没有办法禁止对单个进程使用 vsyscalls/vDSO,或者,如果不可能,对整个操作系统禁用?
事实证明,有一种方法可以有效地禁用单个进程的链接 vDSO,而无需在系统范围内使用ptrace
!
您所要做的就是在它返回之前停止被跟踪的进程并从辅助向量execve
中删除AT_SYSINFO_EHDR
条目(它直接位于指向 in 的内存区域的环境变量之后rsp
)。PTRACE_EVENT_EXEC
是这样做的好地方。
AT_SYSINFO_EHDR
是内核用来告诉系统链接器 vDSO 在进程地址空间中的映射位置。如果此条目不存在,ld
则似乎系统未映射 vDSO。
请注意,这不会以某种方式从您的进程内存中取消映射 vDSO,它只是在链接其他共享库时忽略它。如果作者真的愿意,恶意程序仍然可以与之交互。
我知道这个答案有点晚了,但我希望这些信息能让一些可怜的人头疼
对于较新的系统echo 0 > /proc/sys/kernel/vsyscall64
可能无法正常工作。在 Ubuntu 16.04 中,可以通过在参数下添加内核参数vdso=0
来在系统范围内禁用 vDSO :./etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT
重要提示:参数GRUB_CMDLINE_LINUX_DEFAULT
可能会被 中的其他配置文件覆盖/etc/default/grub.d/...
,因此请仔细检查何时添加您的自定义配置。
采用Tenders McChiken 的方法,我确实创建了一个包装器,它为任意二进制文件禁用 vDSO,而不影响系统的其余部分:https ://github.com/danteu/novdso
一般程序非常简单: