LWN:在memfd中附加安全保护功能!

关注了就能看到更多这么棒的文章哦~

Keeping secrets in memfd areas

By Jonathan Corbet
February 14, 2020

原文来自:https://lwn.net/Articles/812325/

2019年11月时,Mike Rapoport指出在Linux系统中有太多地址空间共享(address-space sharing)的情况了。这种共享很便捷,也对性能有好处,但是现代有了许多复杂的攻击方式以及一些硬件上的安全风险,所以地址空间共享很容易造成安全问题。当时他提出了一些改动建议,此时他提出了响应的patch,针对memfd机制实现了一些地址空间隔离的方案。这可以给大家展示一下我们今后可能的用法,不过也还遗留了许多有难度的工作有待完成。

有几种方法会导致地址空间的共享。Linux传统上一直会把kernel的地址空间映射到每个user-space进程里,这样可以在多方面提高性能。多年以来大家一直认为这种地址空间共享是很安全的,因为这个mapping禁止了user-space对这部分内存空间的访问。不过Meltdown和Spectre这两个硬件bug则会导致这个内存映射变得不安全,所以此前合入了kernel page-table isolation的patch来关闭这处地址共享。

另外,在处理器的memory cache里面也有空间共享。硬件bug同样会导致这部分共享区域的数据可能被泄露出去。这样一来kernel的direct map(kernel space里面的一个大范围地址映射,包含了所有的物理内存区域)就有问题了。这个direct map对kernel来说非常方便,不过也就导致所有user-space memory在kernel中其实都是可见的。换句话说,攻击者哪怕在kernel上下文只要能运行一点点代码,就可以访问到系统中的所有memory内容。所以,既然现在有了speculative-execution bug这类攻击方式了,那么肯定这里也就不安全了。

memfd subsystem本来设计的时候不是用于address-space isolation的,它的目的实际上是为了实现一种进程间通信的机制。不过,它确实也提供了能把一个memory区域关联到文件描述符上的功能,并且能有一些特殊的属性。比如可以把一个memfd改为"sealed"状态,这样接收方就能知道这个fd不会改变。Rapoport认为这个特点会非常有助于实现“secret memory"功能。

在真正创建一个隔离内存区域的时候,需要在memfd_create()里传入一个新的MFD_SECRET flag。不过这里并没有指定是哪种安全级别了。后面还有许多参数可以指定不同级别的安全和性能等级,这样用户就能自己来决定。在这个patch中已经实现的可用选项都可以在调用memfd_create()的时候用相应的flag来选择,不过Rapoport决定要求用户调用一次ioctl()来指定。等到用ioctl()来选择了安全级别之后,用户才可以对这个memfd进行map操作,因此不做的话其实无法使用这个memfd。

目前已经实现了两种模式。MFD_SECRET_EXCLUSIVE,会做一些操作来把memfd对应的memory隐藏起来,不让外人看到,比如说会把这类memory标记成unevictable,从而永远不会被flush到swap中去。这个效果类似于调用mlock(),不过还有一些区别:实际上直到真正发生mem fault的时候才会真正分配内存page,并且它这里设置的locked page数量限制跟mlock()的限制并不一样(这里可能是实现错误了?)。同时也没有办法能把page unlock掉,只有在销毁memfd的时候才会进行unmap操作、并关闭文件描述符。

MFD_SECRET_EXLUSIVE还做了一件事,它会把memfd所对应的内存page从kernel的direct map中移除,这样kernel space就无法再访问这块内存了。这里有点麻烦,是因为direct map通常都是用huge page方式映射的(因为这样在访问时效率更高),如果把小块page从中移除,就需要把huge page拆散成许多小page来,这样系统中所有人的操作都会更加低效。目前的代码(作者承认是个概念性的代码)会在各个page触发fault的时候分配这个page,这样会放大对direct map的影响。这里肯定需要大改,否则这个patch不可能被接受合入的。

另外一个模式就是MFD_SECRET_UNCACHED,它除了拥有MFD_SECRET_EXLUSIVE的所有特性之外,还会让这个memory在映射时指定不允许使用cache。这样这部分内容就不会出现在处理器的cache里面,哪怕用上那些硬件bug来攻击也无法访问到这些内容了。当然这也会导致访问这块memory的时候会更加慢,甚至可能会让用户误以为这块memory根本无法访问。不过,对于那些不经常访问的小块数据(比如秘钥),这个方案也许可以用得上。

目前来说,这个功能只允许选择一个模式。其实MFD_SECRET_UNCACHED已经包含了MFD_SECRET_EXCLUSIVE,只不过更加严格,所以目前哪怕只能选择一个模式也不是什么问题。Rapoport认为这个API今后可能还会变,有可能会是“指定各种秘密等级,例如从'比起普通数据稍微秘密一点'一直到'想尽办法来保护数据哪怕损失性能也在所不惜'。”

这个patch提出来的目的之一就是请大家反馈一下对这套API的看法,不过目前还没有多说反馈。这个改动也会也会沦为那种“直到开发完快要merge的时候大家才会认真考虑这个问题”的哪种情况。不过,至少这个工作不再是个秘密了,感兴趣的用户可以开始想想这个功能是否能满足自己的需求啦。

继续survey!

全文完

LWN文章遵循CC BY-SA 4.0许可协议。

欢迎分享、转载及基于现有协议再创作~

长按下面二维码关注,关注LWN深度文章以及开源社区的各种新近言论~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值