Linux内核安全模块深入剖析【2.6】
第 11 章 Yama11.1 简介Yama 是一个源自古印度语的英文单词翻译成汉语就是“阎罗”阎罗是印度神话中掌管地狱的神。Yama 可以称为半个安全模块说它是“半个”原因是1它是目前3.14 Linux 主线中最简单的安全模块只用到了 4 个 LSM 钩子函数这4 个钩子函数都和 ptrace 相关。2它没有一个完整的安全概念在背后支撑多级安全、基于角色的访问控制、类型增强等都和它无关它是针对具体问题——ptrace——的安全加固。3它可以和其他安全模块同时起作用系统里可以既有 SELinux 的访问控制又有 Yama对 ptrace 的控制而 SELinux、 SMACK、 Tomoyo、 AppArmor 这四者之间是互斥的不能同时存在。11.2 机制先谈一下 ptrace 有什么潜在的安全问题。 ptrace 是一个系统调用调用它可以让两个进程形成“跟踪”关系。跟踪进程可以查看和修改被跟踪进程内存、寄存器、信号等可以了解被跟踪进程系统调用情况。也就是说在跟踪进程面前被跟踪进程毫无秘密可言。Linux 原有的、自主访问控制下的对 ptrace 的操作控制是满足下列两个条件之一即可1跟踪进程的 uid 同时等于被跟踪进程的 uid、 euid、 suid并且跟踪者进程的 gid 同时等于被跟踪者进程的 gid、 egid、 sgid。2跟踪者进程具备能力 CAP_SYS_PTRACE。看一下代码kernel/ptrace.c static int __ptrace_may_access(struct task_struct *task, unsigned int mode) { … const struct cred *cred current_cred(), *tcred; tcred __task_cred(task); if (uid_eq(cred-uid, tcred-euid) uid_eq(cred-uid, tcred-suid) uid_eq(cred-uid, tcred-uid) gid_eq(cred-gid, tcred-egid) gid_eq(cred-gid, tcred-sgid) gid_eq(cred-gid, tcred-gid)) goto ok; if (ptrace_has_cap(tcred-user_ns, mode)) goto ok; … } static int ptrace_has_cap(struct user_namespace *ns, unsigned int mode) { if (mode PTRACE_MODE_NOAUDIT) return has_ns_capability_noaudit(current, ns, CAP_SYS_PTRACE); else return has_ns_capability(current, ns, CAP_SYS_PTRACE); }这里的问题是 uid/gid 相同的进程可以互相跟踪如果一个进程被攻破与之同 uid/gid的进程都沦陷。而如果特权进程被攻破全系统的进程都不能幸免。Yama 提供了四种模式 disabled、 relational、 capability、 no_attach。 disabled 就是 Yama 不起作用和没有它一样。 capability 就是只有在跟踪者进程具备 CAP_SYS_PTRACE 能力时允许跟踪进程和被跟踪进程之间形成跟踪关系。 no_attach 就是根本不允许任何进程之间形成跟踪关系。 relational 是在以下三种情况之一出现时允许形成跟踪关系1跟踪者进程和被跟踪者进程之间存在纵向亲缘关系跟踪者进程是被跟踪者进程的父进程、祖父进程……2 被跟踪者进程曾经通过系统调用 prctl 的选项 PR_SET_PTRACER 声明愿意被某个跟踪者进程跟踪。3跟踪者进程具备 CAP_SYS_PTRACE 能力。security/yama/yama_lsm.c int yama_ptrace_access_check(struct task_struct *child, unsigned int mode) { … if (mode PTRACE_MODE_ATTACH) { switch (ptrace_scope) { case YAMA_SCOPE_DISABLED: /* No additional restrictions. */ break; case YAMA_SCOPE_RELATIONAL: rcu_read_lock(); if (!task_is_descendant(current, child) !ptracer_exception_found(current, child) !ns_capable(__task_cred(child)-user_ns, CAP_SYS_PTRACE)) rc -EPERM; rcu_read_unlock(); break; case YAMA_SCOPE_CAPABILITY: rcu_read_lock(); if (!ns_capable(__task_cred(child)-user_ns, CAP_SYS_PTRACE)) rc -EPERM; rcu_read_unlock(); break; case YAMA_SCOPE_NO_ATTACH: default: rc -EPERM; break; } } … }Yama 在系统调用 prctl 中增加了一个选项:PR_SET_PTRACER通过它进程可以明确向内核注册自己可以被哪个进程跟踪。举个例子prctl(PR_SET_PTRACER, 1972, 0, 0, 0)这个例子意思是进程可以被系统中 pid 为 1972 的进程跟踪。如果传入的进程号是 0表示进程不愿被任何进程跟踪有纵向亲缘关系的除外如果传入的进程号是-1表示愿意被任何进程跟踪。11.3 伪文件系统Yama 的设计者希望 Yama 能够和别的安全模块同时起作用所以 Yama 不能使用/proc/[pid]/attr 目录下的文件。 Yama 也没有使用 securityfs 文件系统虽然使用 securityfs 不会引起和别的安全模块的冲突。 Yama 的做法是在/proc/sys/kernel/目录下创建子目录 yama在子目录 yama 下创建文件 ptrace_scope。这个伪文件的内容是一个 0 到 3 的数字对应 Yama 的四种工作模式见表 11-1。对此文件的读操作不需要特殊能力写操作需要能力 CAP_SYS_PTRACE。还有一点需要注意一旦向此文件写入了 3就不可以再写入其他值了。背后的含义就是一旦切入了最安全模式 no_attach就不可以再变为不安全模式了。11.4 嵌套使用Yama 提供了一个内核编译选项 CONFIG_SECURITY_YAMA_STACKED选择了它可以让 Yama 和其他安全模块同时起作用。11.5 总结很多人都曾经利用 LSM 机制开发过自己的安全模块功能或多或少但是这类工作大都未能进入主线。 Yama 是一个特例。从某种角度看 Yama 堪称完美。首先 Yama 解决的是一类实际的安全问题而不是某种虚无缥缈的假想的安全威胁。其次 Yama 可以和别的安全模块共存。 Yama 承认自己只做了很小一部分工作如果用户想要更全面的安全可以启用另一个安全模块来和 Yama 合作。其实内核各个安全模块所做的工作重复之处甚多。Yama 的开发者 Kees Cook 在 Yama 被 Linux 主线接收后还曾经提交过新的安全模块不过没有被接收 在 Ubuntu 发行版中 那些未进主线的新模块的功能至少有一部分被合并入 Ubuntu修改过的 Yama 之中。11.6 参考资料读者可参考 Documentation/security/Yama.txt。习题Yama 可以和别的 LSM 模块共存。阅读代码看看 Yama 是如何做到和别的 LSM 模块共存的。思考一下 Yama 的这种作法可否推广到其他 LSM 模块。第三部分 完整性保护完整性保护的目的可以概括为一句话防止数据被篡改。完整性保护的手段就是保存一个从原始数据推导出的度量值在访问数据之前先针对数据推导出当前的度量值如果这个度量值和原始的度量值不一致那么就说明数据已经有了变化。这样就产生了两个深层的问题一个是这个度量值保存在哪里另一个是如何保证这个度量值本身不被篡改。第 12 章 IMA/EVM12.1 简介本章介绍 Linux 内核的完整性子系统代码位于 security/integrity 目录下。完整性子系统又可分为两个部分IMAIntegrity Measurement Architecture和 EVMExtended Verification Module。在解释它们的具体含义之前读者首先要明白 IMA/EVM 是 TCGTrusted Computing Group开放标准的一部分。在 TCG 开放标准的架构中可信平台模块Trusted Platform Module TPM是一个芯片其上层是可信启动Trusted BootTBoot。在实践中可信启动的一种实现方式是修改 GRUB在其中加入完整性度量功能形成 GRUB-IMA。在启动层之上是内核内核中含有 TPM 的驱动以及本章要讲述的 IMA 和 EVM。内核之上是用户态的库和应用这部分包含可信软件栈Trusted Software Stack和平台信任服务Platform Trust Services。TCG 开放标准规定的可信计算架构如图 12-1 所示。所以首先要了解一下什么是可信计算Trusted Computing。12.1.1 可信计算可信计算的首要问题是什么是可信而关于可信目前还没有统一的定义不同的专家和不同的组织有不同的解释。1990 年国际标准化组织与国际电子技术委员会ISO/IEC在其发布的目录服务系列标准中基于行为预期性定义了可信性如果第二个实体完全按照第一个实体的预期行动则第一个实体认为第二个实体是可信的。2002 年TCG 用实体行为的预期性来定义可信如果一个实体的行为总是以预期的方式达到预期的目标则这个实体是可信的。在人类社会中“信任”是一个模糊的概念可以是百分之百信任百分之五十信任不信任可以今天信任明天就不信任。在计算机的世界里很难做到模糊化TCG 在可信 PC 规范中采用了一种简单的信任度量模型1二值化只考虑信任和不信任两种极端情况。2无损化不考虑信任传递中的损失即认为信任在传递过程中没有损失。所谓信任传递就是甲信任乙乙信任丙于是甲也信任丙。3用数据完整性度量值充当信任值受目前信任度量理论和技术的限制还不能直接度量measure计算机系统的可信性于是采用数据完整性的度量值来作为可信性的度量值。在可信 PC 规范中信任链起始于 BIOS 启动块Boot BlockBIOS 启动块度量 BIOS BIOS 度量启动加载模块boot loader启动加载模块度量 OSOS 度量应用。一级度量一级一级信任一级把信任扩展到整个计算机系统。而存储和保护度量值的地方就在 TPMTrusted Platform Module。TCG 所定义的 TPM 是一种 SoCSystem on Chip芯片如图 12-2 所示。TPM 主要用来管理密钥、执行加解密运算、数字签名、安全存储数据。本章要介绍的 IMA和 EVM 会使用 TPM 管理的密钥会利用 TPM 提供的 PCRPlatform Configuration Register来存储完整性度量值。