LWN:利用O_MAYEXEC flag通知内核此文件会被执行!

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

O_MAYEXEC — explicitly opening files for execution

By Jonathan Corbet
May 11, 2020

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

主译:DeepL

通常,当内核开发者提出一个没有什么效果的option时,可以预料到在review过程中会收到许多质疑。但也有例外。Mickaël Salaün提议为openat2()系统调用增加一个新flag (O_MAYEXEC),在默认情况下,这个flag不会有任何作用。但它确实在某些情况下可能可以用来增强系统安全性。

在类Unix的系统上执行文件时,要求该文件的属性中必须设置好了合适执行权限位。该文件也不可以存放在使用了noexec的mount选项的文件系统中。这些检查可以用来严格控制系统,避免错误运行了不该运行的代码。但这种保护有一个重要的漏洞:解释器(interpreters)会愿意读取和执行文件中的代码。比如说,如果一个文件中包含Perl代码,那么上述两个检查条件中如果有没有通过的,我们就无法直接拿这个文件作为可执行文件来输入名字直接执行。但攻击者可以将该文件作为参数传递给 perl -e 命令,那么它里面的代码仍然会被执行。

新增的 O_MAYEXEC  flag可以供语言解释器language interpreters (或其他程序,如动态链接器dynamic linker等也会执行代码的程序) 用来告知一个文件正在被打开,并且打开的目的是要执行其中的文件内容。open()会忽略这个flag,因为它从不检查无效的标志(kernel新增的标志对它旧代码的open来说全部都是无效标志),所以open()接口很难扩展。较新的openat2()系统调用在传递给它未知标志时也确实会失败,但它增加了识别O_MAYEXEC的能力。不过,默认情况下如果该标志存在,则对系统行为不会有任何影响。

patch set中还增加了一个新的 sysctl开关,名为 fs.open_mayexec_enforce,它可以控制系统行为是否改变。它的默认值(0)自然地保留了当前的行为,因此没有什么人的系统会因为此patch而被错误破坏。如果把bit0设置为1了,并且放置目标文件的文件系统是用noexec选项挂载的,那么用O_MAYEXEC调用openat2()就会失败。类似地,如果文件的相应执行权限没有打开,那么bit 1将导致打开这种文件时失败。因此,设置这两个bit就可以让使用了O_MAYEXEC的文件打开操作失败,就跟直接执行这个文件时行为一致了。

Integrity measurement是另一个可以从O_MAYEXEC中受益的子系统。内核的integrity measurement子系统经过配置之后,可以用来阻止不符合integrity(完整性)标准的文件被执行。但是,上面讲解过后大家都清楚了,直接将文件作为参数传递给解释器就可以绕过这个检查。这个patch set中增加了一个hook,这样有文件被打开时设置了O_MAYEXEC的话,这些文件在被成功打开之前就可以传递给integrity measurement代码来进行审核。

最后,正如人们所期望的,security modules(安全模块)也可以利用这个标志做出相应的保护。完全可以为 SELinux 或 Smack 编写一个policy,来阻止缺乏某种label的文件被执行(当然,也可以完全阻止这种类型的文件件执行方式)。

上面的讨论跳过了一个小细节:这个机制只有在执行文件中的代码的程序经过修改、来提供O_MAYEXEC标志之后才会起作用。这就需要在各种语言解释器、链接器(linker)等打上补丁,以正确标记任何那些可能导致会要执行其中代码的文件打开动作。例如打开命令行传递的文件、或import module等操作都需要加上这个标志。让所有常用的解释器打上补丁很可能需要不少时间,这还是在假设这些项目都愿意配合的情况。

好消息是,至少有些项目已经意识到了这个问题。例如Python项目从2017年开始(甚至更早)就一直在努力为底层操作系统提供audit信息;这项工作目前已经正式被确定为PEP 578("Python runtime audit hooks"),该项目已于2019年5月获得批准,似乎很可能Python 3.9版本中就会具备。仅仅只是加个O_MAYEXEC flag的话,并不需要新增多少复杂的软件代码,因此在其他解释器中支持这个flag估计也用不了1年时间。

截止本文撰写时,这组patch set已经是第五版了。经过review之后,patch有了很大变化。2018年年底发布的原始版本,比openat2()提出的还要早,当时是依赖Yama security module来执行的。不过开发者们似乎对当前版本相对来说还是比较满意的,所以可能已经接近于进入mainline了。只有走完这一步,才能开始在各种解释器中添加支持代码。

全文完

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

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

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

你可能感兴趣的:(LWN:利用O_MAYEXEC flag通知内核此文件会被执行!)