LWN:IPE——用来确保只执行可信代码的security module!

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

The integrity policy enforcement security module

By Jonathan Corbet
April 16, 2020

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

主译:DeepL

有许多方法来提高系统的安全等级。其中之一,也是通常在嵌入式系统或其他专用系统中使用的方法,就是努力确保只有经过批准的代码(由对该系统拥有权力的人来批准)才能执行。安全启动(secure boot)机制是就是其中一个例子,它确保计算机只会启动可信的kernel版本,不过它通常只保护到启动正确的kernel为止。在系统启动后还有各种机制来保护系统,在这个阶段,我们有了一个新选择,就是Deven Bowers发布的Integrity Policy Enforcement (IPE)  security module安全模块。

IPE是新一代的security module (安全模块)之一,作为最近在进行的module stacking实现工作的一部分而启用的。它并没有像SELinux、AppArmor或Smack那样试图提供一个完整的安全加固(security enforcement)机制。具体来说,它专注于审查执行代码的尝试。特别是,它实现的加固机制归结为一个简单的问题:系统要执行的代码是否来自于正确签名过的disk volume(磁盘卷)?

IPE设计目标是可以配合dm-verity一起工作,dm-verity为块设备提供了完整性检查(integrity checking)。每个dm-verity卷都有一个root hash(哈希)值,它是根据这个disk volume中各个block的hash值计算出来的。每当从这个disk volume中读取block时,都会一路验证hash值直到root hash,以确保没有任何东西被篡改。如果一切正常的话,在打开了dm-verity的disk volume中读出的数据,就可以确保是原始数据和原始hash值,没有被篡改。

虽然dm-verity可以用来确保没有人破坏disk image(磁盘映像),但在确保整个系统的完整性时,仍有一些不足之处。首先,是需要确保volume的root hash值是正确的,这可以通过把hash值存在一个独立的安全区域,或者直接对它进行加密签名。即使整个disk volume都是经过验证的、确保完整的性的,可以假如系统能够执行来自其他disk volume的代码,那么仍然是不安全的。

有一些security module可以解决这些问题。IPE就是试图以一种相对简单的方式来解决这些问题。打开IPE之后,它就要确保执行的所有代码都是来自受dm-verity保护的卷上的,这些代码具有正确的hash或签名。为了让系统管理员可以指明哪些可执行文件是允许运行的,IPE还创建了一个简洁的policy定义语言。

声明policy的第一行用来提供policy的名称和版本号:

    policy_name="Evil lockdown策略" policy_version=6.6.6

名称只是用来指代具体哪个policy,版本号是用来防止系统回退到这个policy的早期版本。但是,IPE会允许一个策略被另一个具有相同版本号的策略覆盖。

其他语句都是用来定义针对每个访问决策来进行什么样的处理动作。例如,下面这个规则将允许执行此文件:

    op=EXECUTE action=ALLOW

可以在policy定义中来控制是否允许如下操作:

  • EXECUTE:执行一个文件或加载一个文件以供执行。这包括调用mmap()或mprotect()来创建拥有执行权限的内存映射。

  • FIRMWARE:加载固件。

  • KMODULE:用insmod或modprobe加载内核模块。

  • KEXEC_IMAGE和KEXEC_INITRAMFS:通过kexec机制启动一个新内核;而KEXEC_INITRAMFS控制新内核提供的initramfs。

  • POLICY:加载integrity-measurement policy。注意,这里指的是IMA integrity subsystem(https://sourceforge.net/p/linux-ima/wiki/Home/?version=8  ),而不是IPE。

  • X509_CERT:加载证书到IMA中。

action=只有ALLOW或DENY这两个选择。

不过到目前为止,我们还没有谈到如何设置哪些来源的代码可以执行。这是通过添加其他修饰符来描述特定二进制文件的出处来实现的。通常我们首先需要允许那些来自secure boot机制验证过的文件系统镜像的代码执行:

    op=EXECUTE boot_verified=TRUE action=ALLOW

secure boot机制确保了最初始的RAM文件系统是验证过可信的,所以这里的可执行程序应该都允许运行。这就形成了一个可信链来确保后续程序的可信性。当然,IPE没有办法确定是否使用了secure boot;所以上述boot_verified=TRUE这一句的真正作用只是启用了对初始文件系统的信任。在此基础上,还有两个修饰符来描述代码可以(或不能)从哪里来:

    dmverity_roothash=hash

    dmverity_signature=TRUE|FALSE

第一句规则,会查找哪个dmverity volume的root hash值等于参数hash。通常情况下,应该对它配置成ALLOW,就可以启用此volume的执行权限。但是可以设置为DENY,以禁止包含已知漏洞的代码的volume。第二句这个带有 dmverity_signature 的规则会检查可执行文件是否来自于一个root hash已经被内核的trusted keying所签名过。

而DEFAULT 修饰符则用来描述没有规则匹配成功的情况下会怎么处理。例如,像下面这样的写法将默认拒绝一切,这可能是大多数人使用IPE时候的第一条语句。

    DEFAULT action=DENY

举个例子,如果有需要允许默认加载内核模块,那么在上面这一行之前可以加上下面这一句:

    DEFAULT op=KMODULE action=ALLOW

规则是按顺序处理的,先匹配到的规则会生效,所以规则的排序要仔细考虑好。

当前patch set中的整个policy定义就是这样了。由于我们经常需要在系统有条件能加载policy之前就打开IPE,因此它也支持在编译的时候使用SECURITY_IPE_BOOT_POLICY来指定一个初始策略。如果没有指定初始策略的话,IPE会先被禁用,直到策略加载完毕才启用,具体来说就是等到有一个policy文本文件被写入/sys/kernel/security/ipe/new_policy才启用。策略文件必须用在trusted keyring中找到的密钥签过名。同时可以加载多个policy,这就是为什么每个policy都有个name。选择一个policy作为当前的active policy,可以通过把它的名字写入ipe.active_policy这个sysctl节点来做到。对于runtime切换策略这个功能,似乎代码里没有任何限制。

有意思的是,缺省情况下,IPE会忽略policy文件中任何它无法解析的内容。这样做是出于今后兼容性的考虑,但也可能会导致以后不小心写了错别字也会导致policy设置结果出乎意料。可以使用ipe.perter_parse这个sysctl节点,在出现这种情况是就报出fatal error。

这个patch提供了IPE功能的说明文档(https://lwn.net/ml/linux-kernel/20200406221439.1469862-12-deven.desai@linux.microsoft.com/  )。

像IPE这类的技术都有一个共同的特点,即可以用来办好事,也可以用来做坏事。我们看到的最明显的用法是用来确保消费者的设备里的image不会被篡改,甚至连设备的主人也不能进行修改。但它也可以用来确保运行OpenWrt的路由器能够正常运行主人加载的正确版本软件。至少IPE是相对简单的,这意味着个人也可以在自己的机器上进行设置,而无需耗费大量时间。

截止到写这篇文章的时候,IPE还没有收到多少review,所以很难说什么时候,或者说以什么形式,来并入mainline。不过,从目前简单看下来,似乎没有什么大问题,应该还是可以继续走下去的。

全文完

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值