diff -u:内核开发的新进展
长期以来,Linux中的NMI(不可屏蔽中断)系统一直是一个臭名昭著的补丁集合,Andy Lutomirski 最近决定尝试清理它。 当运行系统底层的硬件出现问题时,就会发生 NMI。 通常在这些情况下,NMI 会尝试保存用户数据,并使系统尽可能进入有序状态,然后不可避免地崩溃。
Andy 认为,在当前的 NMI 代码中,存在各种需要理顺的极端情况和安全漏洞,但如何去做并不明显。 例如,有时可能会在另一个 NMI 中合法地触发 NMI,在这种情况下,中断代码需要知道它已从“NMI 上下文”而不是从常规内核空间调用。 但是,检测 NMI 上下文的最佳方法并不容易确定。
此外,如果他的目标是考虑所有可能的极端情况,Andy 认为无法避免显着的加速成本。 另一方面,允许某种相对可以接受的不正确程度可以让内核以更快的速度运行。 他应该专注于最大化速度还是保证正确性?
他提交了一些补丁,倾向于更正确的方法,但实际上遭到了 Linus Torvalds 的反对。 Linus 希望尽可能地优先考虑速度而不是正确性,这意味着分析不太正确的方法会引入的具体问题。 它们中的任何一个会导致实际问题吗?或者这些问题在很大程度上可以忽略不计吗?
正如 Linus 所说,例如,在一种情况下,从理论上讲,不良代码可能会循环无限递归 NMI,导致堆栈无限增长。 但是,执行此操作的代码没有任何用处,因此执行此操作的任何代码无论如何都存在错误。 因此,Linus 认为没有必要让 Andy 的补丁来防范这种可能性。
Linus 进一步表示,最简单的方法是不允许嵌套 NMI——这将省去猜测代码是否在 NMI 上下文中的麻烦,并且可以节省与嵌套调用堆栈相关的所有其他常见麻烦。
问题解决了! 但事实并非如此。 Andy 和其他人不愿接受 Linus 的想法。 不是因为它会在内核中引起任何问题,而是因为它需要丢弃代码中可能遇到的一些断点。 如果内核丢弃 GDB 调试器 所需的断点,这将使 GDB 无法用于调试内核。
Andy 更深入地研究了代码,试图找到一种方法来避免 NMI 递归,同时避免禁用 GDB 所需的那些断点。 最后,他提出了 Linus 可以接受的解决方案:只有内核中的断点才会被丢弃。 用户断点(例如 GDB 用户程序设置的断点)仍然可以保留。
NMI 代码非常棘手且混乱。 但总的来说,似乎越来越多的超混乱的东西正在被内核开发人员解决。 NMI 代码就是一个例子。 经过多年的脆弱性和不一致性,它即将变得更加干净和可预测。