Linux vsyscall和vDSO加速系统调用

https://lwn.net/Articles/446528/

“ vsyscall”和“ vDSO”段是用于加速Linux中某些系统调用的两种机制。尽管它们的基本功能(无需在内核模式下运行即可提供对功能的快速访问)是相同的,但它们之间还是有一些明显的区别。最近,vsyscall已被视为安全攻击的促成因素,因此已组合了一些补丁程序以逐步淘汰它。对这些补丁程序的讨论表明,关于社区如何处理安全问题的分歧仍然一如既往。

vsyscall区域是这两种机制中较旧的一个。它是作为执行特定系统调用的一种方式添加的,不需要任何真正的特权级别即可运行。经典示例是gettimeofday() ; 它需要做的就是阅读内核当前的想法。有一些应用程序经常调用gettimeofday(),以至于它们只关心一点点开销。为了解决这个问题,内核允许将包含当前时间的页面以只读方式映射到用户空间。该页面还包含一个快速的 gettimeofday()实现。使用此虚拟系统调用,C库可以提供快速的gettimeofday(),而实际上不必更改为内核模式。

Vsyscall有一些局限性。除其他外,只有少量的虚拟系统调用空间。由于受到了这些限制,内核开发人员引入了更灵活的vDSO实现。快速浏览一下现代系统将发现两者仍在使用中:

    $ cat /proc/self/maps
    ...
    7fffcbcb7000-7fffcbcb8000 r-xp 00000000 00:00 0            [vdso]
    ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0    [vsyscall]

通过再次键入相同的命令并比较输出,可以看到当前讨论的关键:

    7fff379ff000-7fff37a00000 r-xp 00000000 00:00 0             [vdso]
    ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0     [vsyscall]

请注意,vDSO区域已移动,而vsyscall页面仍位于同一位置。vsyscall页面的位置被钉在内核ABI中,但是vDSO区域(与用户空间内存布局中的大多数其他区域一样)在每次映射时都会随机分配其位置。

地址空间布局随机化是防御安全漏洞的一种形式。能够超出堆栈范围的攻击者通常可以安排目标进程中的功能以“返回”至任意地址。根据在该地址找到的指令的不同,这种退货可能会导致几乎任何事情发生。返回到 C库中的system()函数是一个明显的例子。它可以用来执行任意命令。但是,如果不知道C库在内存中的位置,那么利用漏洞跳转到有用的位置将变得非常困难或不可能。

vsyscall页面中 没有system()函数,但是有一些调用系统调用的机器指令。仅需少量设置,这些指令就可以在堆栈溢出攻击中使用,以调用具有攻击者定义的参数的任意系统调用-这不是理想的结果。因此,最好删除vsyscall页面(或至少将其位置随机化)以阻止这种类型的攻击。不幸的是,应用程序取决于该页面的存在和确切地址,因此无法执行任何操作。

除了Andrew Lutomirski发现可以做的事情:从vsyscall页面上删除所有有用的指令。其中一个与vsyscall64 sysctl旋钮相关联,该旋钮实际上仅对用户模式Linux有用(即使在那里也无法正常工作)。它只是被删除了。其他时间并不是真正的系统调用指令:系统时间,如果仅保持正确的值而跳入(并因此执行,就像执行代码一样),则看起来像是系统调用指令。为了解决该问题,变量已被移到单独的页面中,并且执行许可权已关闭。

vsyscall页面中的其余代码已被简单地删除,并由特殊的陷阱指令代替。尝试调用vsyscall页面的应用程序将陷入内核,然后内核将在内核空间中模拟所需的虚拟系统调用。结果是一个内核系统调用模拟了一个虚拟系统调用,该虚拟系统调用被放置在该位置以避免首先出现内核系统调用。结果是执行“ vsyscall”,该过程需要花费一微秒的时间才能执行,但至关重要的是,它不会破坏现有的ABI。无论如何,只有在应用程序尝试使用vsyscall页面而不是vDSO时,才会看到速度下降。

除了一个小问题外,现代应用程序在大多数情况下都不应该这样做:glibc仍然使用time()的vsyscall版本 。该问题已在glibc信息库中得到修复,但该修复可能暂时无法向用户提供。同时,time() 调用将比以前慢一些。那不应该是一个真正的问题,但永远都不是问题,因此Andy放置了一个配置选项以保留旧的做事方式。有人担心仿真vsyscall页的开销可以设置 CONFIG_UNSAFE_VSYSCALLS得到旧的行为。

没有人真正反对整个补丁系列,但是Linus讨厌配置选项的名称。他要求将其 改为CONFIG_LEGACY_VSYSCALLS。或者,甚至更好的是,更改可以只是无条件进行。这导致 PaX开发人员对内核社区喜欢隐藏安全问题的方式做出了相当可预见的 回应,Linus表示

将旧的vdso称为“ UNSAFE ”作为配置选项只是愚蠢的。这是一个policy名称,除了您的policy议程之外,没有其他充分的理由。当我这样称呼您时,您只会吐出同样疲倦的旧安全性废话。
 
可以说谈话从那里走下坡路;有兴趣的人士可以点击上面引用的消息中的线程链接。

 

从该讨论中得出的一个有用的观点是,静态vsyscall页面实际上不是安全漏洞;它不是安全漏洞。它只是一种资源,可以使攻击者更容易利用系统中其他位置的漏洞。该方面是使该页面“不安全”还是仅使“旧版”留给读者练习。不管采用哪种方式,删除都被认为是一个好主意,尽管删除可能会导致真正的安全性错误仍未在内核中修复。论据全都与命名有关。

在撰写本文时,尚未发布补丁的最终版本,但是补丁的形状非常清晰。静态vsyscall页面将不再以其当前形式存在,并且仍在使用该页面的应用程序将继续工作,但速度会稍慢一些。控制此行为的配置选项可能存在也可能不存在,但是任何发行包含此更改的内核的发行版(可能是3.1或更高版本)也将具有C库,该库不再尝试使用vsyscall页。而且,幸运的是,利用漏洞将变得更加困难。

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值