关于Linux内核月报
Linux阅码场
Linux阅码场内核月报栏目,是汇总当月Linux内核社区最重要的一线开发动态,方便读者们更容易跟踪Linux内核的最前沿发展动向。
限于篇幅,只会对最新技术做些粗略概括,技术细节敬请期待后续文章,也欢迎广大读者踊跃投稿为阅码场社区添砖加瓦。
本期月报主要贡献人员:
张健、廖威雄、chenwei、夏天
往期链接:
Linux阅码场 - Linux内核月报(2020年06月)
Linux阅码场 - Linux内核月报(2020年07月)
Linux阅码场 - Linux内核月报(2020年08月)
Linux阅码场 - Linux内核月报(2020年09月)
阅码场征稿Linux阅码场征集Linux工程师一线研发心得;工程师、高校学生老师、科研院所研研究人员对Linux某一技术要点深入分析的稿件。您的文章将获得近十万一线Linux工程师的广泛受众。投稿要求:原创且从未在任何媒体、博客、公众号发表过的文章。高屋建瓴、深刻全面地论述一个技术点或者面。投稿请微信联系小月:linuxer2016录取的稿件,我们也会奉上微薄的稿酬聊表寸心,稿费标准为300-500元/篇。
一、 体系结构相关
1.1 ARM/arm64 set_fs
补丁集1:ARM: remove set_fs callers and implementation
补丁集2:arm64: remove set_fs() and friends
当你在内核代码中看到fs,你会想到什么?文件系统?然鹅,图样图森破,今天要说的fs其实是x86的fs寄存器[1]。0.1版本的内核引入了set_fs,用于设置用户空间(`set_fs(USER_DS)`)和内核空间(`set_fs(KERNEL_DS)`)的地址范围。原本set_fs仅仅是设置x86的fs寄存器,后续其它架构也沿用了set_fs的名称。如果仅仅是名称困惑也还好,问题是set_fs看起来是在做保护,这同样
是一个攻击点。如果从内核返回用户空间时没有设置相应的限制`set_fs(USER_DS)`,用户空间获得了不受限制内存空间的能力。2010年(CVE-2010-4258)和2016年分别有过类似的报道。
基于set_fs加固[2]似乎是个办法,但是由于会影响内核系统调用性能被否决。于是,只有一个选择——移除set_fs。emm,三年前,这是三年前社区讨论的结果。今年Christoph Hellwig继续了自己当初的提议,目前内核core code部分工作已经完成,剩余还需要各个体系结构完成修改这个月ARM和ARM64两个架构补丁正在提交review。
ARM64方面,除了clean up代码,需要处理涉及内核和用户空间切换的代码,主要涉及SDEI,PAN和UAO三部分。ARM方面,除了删除set_fs代码,还需要处理oabi的几个系统调用。
参考资料
[1]https://lwn.net/Articles/722267/
[2]https://lwn.net/Articles/721305/
1.2 KASan for ARM
Kernel Address SANitizer (KASAN)是一个动态的内存错误detector,主要检查越界和use-after-free。目前X86,ARM64,RISC-V,PowerPC等架构均已支持。
Linus Walleij本月发送了KASan for Arm的第十四版补丁——这是ARM架构对KASan的支持——和上个月的补丁相比,Linus修复了自己在高通APQ8060平台的crash,他希望也能修复Florian和Ard报告的issue。
ARM64的KASan正在增加基于硬件tag内存错误检测。这个系列补丁把Memory Tagging Extension (MTE)的能力应用于KASan,在每次内存分配时生成随机的tag,并在每次内存访问时,由MTE自动检查。如果不匹配则产生tag fault,并有KASan报出该错误。
(补丁名称:kasan: add hardware tag-based mode for arm64)
1.3 Carry forward IMA measurement log on kexec on ARM64
内核各个体系结构实现既有共性又有特性,往往后来者会考虑把先前某个架构的实现修改的更为通用化。之前我们在内核月报中介绍的RISC-VNUMA工作就是基于ARM64的工作。今天这个补丁集也是类似的情况。
IMA(Integrity Measurement Architecture)是内核完整性的两大组成部分之一。IMA可以在文件执行或打开时检查其完整性。对于kexec(kexec支持从当前内核启动新的内核):IMA可以检查其内核,initramfs和命令行。Lakshmi的四个补丁是补齐当前ARM64不支持的这个能力。
1.4 除了上面的补丁,10月还有不少值得关注的补丁。例如
Introduce the TDP MMU
目的是提高TB级内存虚拟机的热迁移性能。TDP的含义是:two dimensional paging。目前TDP MMU已经用于google 拥有416个vCPU的12TiB m2-ultramem-416 VM中提供必要的热迁移性能。
这项工作的动机是需要并行处理非常大的虚拟机里的page fault。当VM具有数百个vCPU和TB的内存时,KVM的MMU锁遭受极端竞争,从而导致guest OS里面page fault处理的soft-lockup或巨大延迟。
Add support for Asymmetric AArch32 systems
目的是在系统只有部分arm64 CPU支持aarch32 EL0运行环境时,在用户空间可以使用aarch32应用。备注:arm64 CPU可以有两种运行环境(EE:Execution Environment),分别是aarch64和aarch32。
PKS: Add Protection Keys Supervisor (PKS) support
这是和PKU(用户空间Memory Protection Keys)类似的内核工作,预计的使用场景有trusted keys和PMEM。
二. Core-kernel相关
2.1 可睡眠tracepoints
现在的Tracers因为没法处理page faults,导致了无法访问用户态的数据,然而这有时是个需求。
这个系列的patch在tracepoint框架实现了一套能让tracers处理page faults的框架,未来各种tracer会做相应修改.
2.2 Core scheduling v8
Core scheduling是一个允许信任的进程在共享资源的cpus上同时运行的特性,主要目的是想不禁止SMT功能的同时,消除core-level层面的侧信道攻击。
默认情况下,这个特性不会改变现在的任何调度行为。需要用户决定哪些tasks可以在同一个core同时运行,比如可以设定当一个进程A在运行时,同一个core的hyperthreads要么是idle,要么只能运行进程A信任的进程。
2.3 KFENCE v5: 一个低采样的内存错误检测工具
KFENCE的主要特点是想用尽量低的性能牺牲来采样线上的各种内存错误,跟KASAN比起来,KFENCE的精度虽然没那么高,但是KFENCE对性能影响小,可以在产品环境大量部署,从而也能检测出内存bug。
这个系列Patch给arm和x86架构都增加了KFENCE支持。
三、文件系统和Block Layer
3.1 块请求过滤与块设备快照模块
* 补丁:https://lwn.net/Articles/834867/
* veeamsnap:
https://github.com/veeam/veeamsnap/
补丁作者来自 veeam ,一个提供 Linux 的备份方案的企业。长期以来以一个内核树外模块(veeamsnap)的形式提供块设备备份服务,这次的提交算是尝试将其主功能模块合入主分支。
补丁实现了两个功能,分别是blk-filter和blk-snap:
blk-filter实现了对块设备 BIO 请求的截流,而且是在 BIO请求非常早的时候就拦截了,完全不影响请求处理队列。除了对整个存储介质截流之外,其还支持截断特定的块设备,既以分区为单位。还有一个特点,其支持动态启用、禁用过滤功能。在块设备加载时,可以自动开始对 BIO 请求过滤;当块设备被移除时,过滤器也会自动移除。
blk-snap实现了快照和块更改跟踪功能。毫无疑问,其依赖于 blk-filter。它旨在创建任何块设备的备份副本,而不使用设备映射器。快照是临时的,在备份过程完成后将被销毁。更改的块跟踪允许增量和差异备份副本。
3.2 btrfs新增支持4K子页读写
* 补丁:https://lwn.net/Articles/834872/
补丁主要是让 64K 页大小的系统可以挂载 4K 扇区大小的btrfs,以及在这状态下支持正常的读写。
64 K 页大小在一些小数据下会造成内部空间浪费,如果可以有更小的操作粒度,可以大大缓解空间浪费的情况。因此才需要支持 4K 子页的操作。作者测试后足够稳定,认为可以执行子页面大小的纯元数据操作,例如 reflink。作者在压缩和非压缩的情况下验证了读数据子页,验证了元数据的子页读和写,也验证了非压缩情况下的全页写。
这补丁其实还有不少的事儿要做,以及还有不少挑战。例如没实现写入子页的数据(非元数据),例如子页数据的回写支持 iomap。
四、 虚拟化
4.1 KVM protected memory extension
== 背景和相关问题 ==
现在有许多的硬件特性(例如MKTME、SEV)可以防止虚拟机的内存受到主机上未授权的访问。这个补丁集提出了一个纯软件的特性,可以缓解一些相同的主机端只读攻击。
== 这个补丁集缓解了什么? ==
- 主机内核“意外”访问虚拟机数据(考虑下speculation)
- 主机内核导致对虚拟机数据的访问(write(fd &guest_data_ptr, len))
- 主机用户空间访问虚拟机数据(比如通过篡改的QEMU)
- 通过篡改的QEMU设备模拟器来提升虚拟机的特权
== 这个补丁集没有缓解什么? ==
- 主机的内核被完全篡改。内核将再次映射页面
- 基于硬件的攻击
第二版的RFC补丁集解决了大部分的反馈意见。
但仍然没有找到一个好的方案来解决重新启动和KEXEC。在这些的操作中,需要取消对所有内存的保护,这样做和我们这个特性的目标是相矛盾的。
在不保护重启(或KEXEC)所需要的内容之前,清理大部分内存耗时很长且容易出错的。也许我们应该声明这些操作不被支持?
== 序列概览 ==
通过硬件特性对虚拟机的数据进行加密,然后确保只有正确的虚拟机才能解密,从而保护虚拟机数据。这样做的副作用是使内核直接映射和用户空间映射(QEMU等使用)变得无用。
但是,这告诉了我们一些非常有用的信息:对于普通的虚拟机操作,内核映射和用户空间映射有时候都不是真正必要的。
在我们这个补丁集中,我们不使用加密,而是简单地解除内存映射。与允许访问密文相比,它的一个优点是错误的访问会引起异常,从而被捕获,而不是像加密数据一样,简单地返回垃圾数据。
4.2 KVM: Dirty ring interface
该补丁在10月份更新了两次,都是将v15 rebase到最新的KVM分支。这个工作是在Lei Cao <lei.cao@stratus.com> 和Paolo Bonzini 之前所做的KVM dirty ring接口工作的继续。
这个新的dirty ring接口是虚拟机回收脏页的另外一种方法。在很多方面,它都不同于已有的dirty logging接口,主要有:
数据格式: 脏数据现在是环形格式而不再是bitmap格式,所以用来同步脏数据日志的bit不再依赖于虚拟机内存的大小,而是数据脏的速度。另外,新的dirty ring是每个vCPU独享,而dirty bitmap则是所有vCPU共享一份,dirty bitmap是per-VM的。
数据拷贝:脏页的同步不再需要拷贝数据,相反,dirty ring通过页面共享 (通过在vcpu_fd上的mmap)在用户空间和内核空间共享
接口: 当我们想再次将收集到的脏页重置为保护模式时,新的dirty ring使用了新的KVM_RESET_DIRTY_RINGS ioctl接口,而不是使用原有的KVM_GET_DIRTY_LOG、KVM_CLEAR_DIRTY_LOG接口。而为了收集dirty bit,我们只需要读取dirty ring中的数据,不再需要调用ioctl接口。
(END)
更多精彩,尽在"Linux阅码场",扫描下方二维码关注