LWN: kernel warning 的时候应该怎么处理?

Linux News搬运工

共 2952字,需浏览 6分钟

 ·

2021-12-12 19:38

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

What to do in response to a kernel warning

By Jonathan Corbet
November 18, 2021
DeepL assisted translation
https://lwn.net/Articles/876209/

内核内部提供了一些宏,供代码在出错的时候调用从而产生 warning。然而,它并没有提供多少指导,来告诉人们在看到 warning 的时候应该做些什么。Alexander Popov 最近发布了一组 patch,为系统对在发出 warning 的时候增加了一个选项。这一组 patch 似乎不太可能按它当前的做法来被合入,但它确实成功地引起了人们关于如何处理 warning 的讨论。

warning 是通过调用 WARN()和 WARN_ON_ONCE() 等宏来触发的。默认情况下,warning 文本被发送到 kernel log 中,然后系统继续执行,就好像 warning 没有发生过一样。有一个 sysctl 开关 (kernel/panic_on_warn),打开的话会在每次 warning 发出时就让系统 panic,但对于系统管理员来说,要么忽略问题、要么让系统完全无法继续用,在这两个选项之间缺乏中间地带。

Popov 的 patch 是增加了另一个名为 kernel/pkill_on_warn 的 sysctl 开关。如果设置为非零值,那么这个参数会要求内核在 warning 出现时就 kill 掉当前正在运行的进程的所有线程。Popov 说,这种行为比起什么都不做来说,可以增加系统的 safety 和 security,同时又不像直接导致系统 panic 方案那么大的破坏性。它可能会杀死当前正在试图攻击系统的进程,并且平时也能让进程避免在已知出现了某些错误的情况下继续运行。

有一些人反对这个方案,Linus Torvalds 是第一个。他指出,当系统出现 warning 时,当前正在运行的进程可能与 warning 本身并没有任何关系。例如,问题可能发生在一个中断处理程序中,或者是其他一些什么情况。他说:"随便向某个进程发送 signal,这只能算是盲目地写程序(voodoo programming),都有可能导致其他一些奇怪的故障"。

Torvalds 认为更好的方法可能是创建一个新的/proc 文件,当某个会影响整个系统的事件发生时(如出现了 warning),就可以从这个 /proc 文件获取到相关信息。然后使用一个用户空间的守护程序(daemon)可以保持对该文件进行 poll 轮询,在看到 warning 时读取到相关信息,然后自己判断需要杀死相关进程的话就自己动手。Marco Elver 补充说,这里有一个 tracepoint 就可以提供相关的信息,只需做一点工作就好。Kees Cook 提出了一个实现方案,但 Popov 不太喜欢。他认为这种方法会让一个进程在 warning 发生后继续执行,而当用户空间对这种情况采取行动时,可能已经太晚了。

James Bottomley 认为,到目前为止讨论中提出的所有方法都是不对路的。他说,如果 warning 发生了,那么内核就不再处于一个已知的正确状态,什么事情都有可能发生:

WARN 的意思是发生了一个意外状况,这意味着内核本身处于一个未知的状态。你不能通过杀死和重启某些东西来恢复,而是必须要重新初始化到一个已知的状态(也就是说需要 reset 系统)。我们之所以用 WARN 而不是 BUG,部分原因可能是我们相信这里的状态被破坏的问题不严重,如果你小心谨慎使用的话,系统可以继续在这种稍微退化一些的状态下继续运行,只要用户愿意接受这种风险。

因此,他说,唯一合理的策略就是继续运行(接受可能发生坏事的风险)或杀死整个系统并重新启动。而这些已经是内核现在就支持的了。

Popov 曾提到 ELISA 项目,该项目正在努力将 Linux 部署到安全关键(safety-critical)的应用中,这个项目可能会支持增加 pkill_on_warning 开关。但为该项目工作的 Lukas Bulwahn(但他小心翼翼地表示他不代表 ELISA 的官方观点)表示不赞同。他说,正确的解决方案是在 warning 时杀死系统,但也要确保只有在事情真正脱离轨道的情况下才发出 warning:

应该是只在某些东西没有按照开发者的期望进行配置、或者内核被置于一个是意料之外的状态、并且基本上只有开发者在紧密关注、测试,尚未被人们广泛使用时,才应该发出 warning。warning 不应该被当作提供信息的机制(informative),因为这些信息提供机制仍然允许内核在正常的环境中继续适当地运行。

他补充说,真正的安全(truly safe)还需要确保对 panic() 的调用在无论什么情况下都能真正停止系统。这一点其实并不像人们想象的那么容易。例如,某次 panic() 调用中可能会在试图获得一个锁时就卡住了。

Christoph Leroy 认为,warning 应该在内核内处理,这样系统才能尽可能地保持良好的运行。鉴于此,他继续说:"pkill_on_warning 似乎很危险,而且关联性不强,可能比什么都不做更危险,尤其是 WARN 可能是因为与当前在运行的线程无关的原因而被触发"。然而,Popov 不同意这样的观点,他认为我们不可以期望所有的 warning 都能在内核中得到正确的处理:

对于在内核源代码中加入 BUG*(),存在着非常强烈的反对力量。所以有很多情况下,使用了 WARN*() 来处理严重的问题,因为内核开发者们没有其他选择。

确实,他的 patch 如何合入并启用了新的选项的话,warning 的行为几乎就跟 BUG() 调用相同了。BUG() 调用默认就会使运行中的进程立即结束。正如他所指出的,开发人员在试图使用这些 BUG() 之类的函数调用时遇到了阻力,因为人们认为这些函数的效果太严重(severe)了。

目前还不清楚这种增加一个让 warning 变得更严重的选项,是否是解决这个问题的最好办法。不过,这次讨论可能会产生一个好的结果,那就是对 warning 的含义和产生 warning 时应该发生什么会继续进行更好地定义。跟内核中的许多机制一样,warning 宏是在没有系统尚未进行整体设计的情况下出现的。现在有了很多关于开发者们使用 warning 的丰富经验,所以现在开始进行一些设计可能会使内核整体上更加茁壮稳定(robust)。

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

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

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



浏览 51
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报