security - 内核代码能否以其他内核代码无法撤消的方式将内容设置为只读?

标签 security assembly linux-kernel x86-64 page-tables

我的印象是,Linux 内核保护自身的尝试围绕着不让恶意代码在内核空间中运行。特别是,如果加载了恶意内核模块,从安全角度来看,它将“游戏结束”。然而,我最近遇到了a post这与这种信念相矛盾,并表示内核可以通过某种方式保护自身的某些部分免受自身其他部分的影响:

There is plenty of mechanisms to protect you against malicious modules. I write kernel code for fun so I have some experience in the field; it's basically a flag in the pagetable.

What's there to stop any kernel module from changing that flag in the pagetable back? The only protection against malicious modules is keeping them from loading at all. Once one loads, it's game over.

Make the pagetable readonly. Done.

Kernel modules can just make it read-write again, the same way your code made it read-only, then carry on with their changes.

You can actually lock this down so that kernel mode cannot modify the page table until an interrupt occurs. If your IDT is read-only as well there is no way for the module to do anything about it.

这对我来说没有任何意义。我错过了关于内核内存如何工作的重要信息吗?内核空间代码可以限制自己修改页表吗?这真的能防止内核 rootkit 吗?如果是这样,那么为什么 Linux 内核今天不这样做以结束所有内核 rootkit?

最佳答案

如果恶意内核代码以受信任的方式加载(例如加载内核模块而不是利用漏洞),则:内核代码就是内核代码。

Intel CPU 确实有一系列机制来禁用对内核内存的读/写访问:

  • CR0.WP 如果设置为不允许对用户和内核只读页面进行写访问。用于检测内核代码中的错误。
  • CR4.PKE 如果设置(必须启用 4 级分页,在 64 位模式下是强制的)不允许内核访问(不包括取指令)用户页面模式,除非这些被标记使用正确的 key (标记其 RW 权限)。用于允许内核写入 VSDO 和 KUSER_SHARED_DATA 等结构,但不允许写入其他用户模式结构。 key 权限在 MSR 中,而不是在内存中;键本身在页表条目中。
  • CR4.SMEP 如果设置为不允许从用户模式页面获取内核指令。用于防止将内核函数指针重定向到用户模式分配页面的攻击(例如 nelson.c 特权升级漏洞利用)。
  • CR4.SMAP 如果设置为在隐式 访问或任何类型(隐式或显式)访问期间不允许内核访问用户模式页面(如果 EFLAGS. AC=0,从而覆盖保护 key )。用于执行更严格的无用户模式访问政策。
  • 当然,分页结构中的 R/WU/S 位控制项目是只读/读写还是分配给用户或内核.

您可以在 Intel 手册中阅读如何为 supervisor-mode access 应用权限:

Data writes to supervisor-mode addresses.
Access rights depend on the value of CR0.WP:
- If CR0.WP = 0, data may be written to any supervisor-mode address.
- If CR0.WP = 1, data may be written to any supervisor-mode address with a translation for which the R/W flag (bit 1) is 1 in every paging-structure entry controlling the translation; data may not be written to any supervisor-mode address with a translation for which the R/W flag is 0 in any paging-structure entry controlling the translation.

因此,即使内核将页面 X 保护为只读,然后将页面结构本身保护为只读,恶意模块也可以简单地清除 CR0.WP.
它还可以更改 CR3 并使用自己的分页结构。

请注意,英特尔开发了 SGX 来解决内核本身是邪恶的威胁模型。
然而,以安全的方式(即没有单点故障)将内核组件运行到 enclaves 中可能并非易事。

另一种方法是使用 VMX 扩展对内核进行虚拟化,尽管实现起来绝非易事。

最后,CPU在segmentation层有四个保护级别,而paging只有两个:supervisor(CPL = 0)和user(CPL > 0)。
理论上可以在“Ring 1”中运行内核组件,但随后您需要创建一个接口(interface)(例如调用门或 syscall 之类的东西)才能访问其他内核函数。
完全在用户模式下运行它更容易(因为您首先不信任该模块)。

我不知道这是什么意思:

You can actually lock this down so that kernel mode cannot modify the page table until an interrupt occurs.

我不记得中断处理将锁定/解锁任何东西的任何机制。 不过我很好奇,如果有人可以提供一些信息,欢迎他们。

x86 CPU 中的安全性(但这可能是普遍的)一直等级:先来的人为后来的人设置约束。
在同一层级的非隔离组件之间通常几乎没有保护。

关于security - 内核代码能否以其他内核代码无法撤消的方式将内容设置为只读?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61397730/

相关文章:

c# - 使用 C# 的 GnuPG 包装器

java - 如何在java中安全地存储用户密码以便在整个应用程序中重用

ruby-on-rails - ActionMailer 密码安全

.net - 用于从/向数据库检索/发送数据的 API

assembly - MOV r/m8,r8 和 MOV r8,r/m8 的区别

ios - Mach-O 符号 stub (IOS)

c++ - 将引用参数传递给汇编函数

linux - Yocto如何生成这些/etc/limits文件

linux - 什么 API 将允许我实现一个 linux 文件系统,它知道哪个进程正在访问它?

linux - 解释内核消息 : "page allocation failure. order:1"