文章目录

  • 前言
  • 一、简介
  • 二、Decoding tainted state at runtime
  • 三、源码分析
  • 总结
  • 参考资料

前言

(1)
在加载自己编写得驱动模块是,加载时看到:

module verification failed: signature and/or required key missing - tainting kernel

signature 或者 required key missing是导致内核受到污染的事件,不过这对于模块的运行没啥影响。因此我们一般都忽略掉这个问题。

(2)系统宕机时看到:

dmesg --follow-w, --followWait for new messages. This feature is supported on systems with readable /dev/kmsg only (since kernel 3.5.0).
CPU: 0 PID: 31024 Comm: ... Kdump: loaded Tainted: G        W  OE  ----V-------   3.10.0-&version.x86_64 #1

于是便查阅 tainting kernel 相关资料。

一、简介

大多数情况下,运行受污染的内核没有什么问题,来自受污染内核的错误报告通常会被开发人员忽略。

即使撤消导致污染的原因(即卸载专有内核模块),内核仍将保持污染,这表明内核仍然不可信。 这也是为什么内核在发现内部问题(‘kernel bug’)、可恢复错误(‘kernel oops’)或不可恢复错误(‘kernel panic’)时会打印污染状态,并将有关此的调试信息写入日志 dmesg 输出。 也可以通过 /proc/ 中的文件在运行时检查污染状态。

在以“CPU:”开头的行中的顶部附近找到受污染的状态; 内核是否或为什么被污染显示在进程 ID (‘PID:’) 和触发事件的command的缩写名称 (‘Comm:’) 之后:

CPU: 0 PID: 31024 Comm: ... Kdump: loaded Tainted: G        W  OE  ----V-------   3.10.0-&version.x86_64 #1

如果内核在事件发生时没有被污染,将会显示 Not tainted: 如果污染了,那么将打印“Tainted:和字符,无论是字母还是空白。 在上面的示例中:

Tainted: G        W  OE

G :表示所有加载的模块都有一个GPL或兼容的许可,P表示加载了任何专有模块。
没有MODULE_LICENSE或具有MODULE_LICENSE但不被insmod认可为兼容GPL的模块被认为是专有的。

O :表示如果已加载外部构建(out-of-tree)模块。

E :表示内核支持模块签名,加载了未签名的模块。

二、Decoding tainted state at runtime

在运行时,您可以通过读取 cat /proc/sys/kernel/tainted 来查询污染状态。

如果返回 0,则内核没有被污染; 任何其他数字都表明了它的原因。 解码该数字的最简单方法是脚本 tools/debugging/kernel-chktaint。

#! /bin/sh
# SPDX-License-Identifier: GPL-2.0
#
# Randy Dunlap <rdunlap@infradead.org>, 2018
# Thorsten Leemhuis <linux@leemhuis.info>, 2018usage()
{cat <<EOF
usage: ${0##*/}${0##*/} <int>Call without parameters to decode /proc/sys/kernel/tainted.Call with a positive integer as parameter to decode a value you
retrieved from /proc/sys/kernel/tainted on another system.EOF
}if [ "$1"x != "x" ]; thenif  [ "$1"x == "--helpx" ] || [ "$1"x == "-hx" ] ; thenusageexit 1elif  [ $1 -ge 0 ] 2>/dev/null ; thentaint=$1elseecho "Error: Parameter '$1' not a positive integer. Aborting." >&2exit 1fi
elseTAINTFILE="/proc/sys/kernel/tainted"if [ ! -r $TAINTFILE ]; thenecho "No file: $TAINTFILE"exitfitaint=`cat $TAINTFILE`
fiif [ $taint -eq 0 ]; thenecho "Kernel not Tainted"exit
elseecho "Kernel is \"tainted\" for the following reasons:"
fiT=$taint
out=addout() {out=$out$1
}if [ `expr $T % 2` -eq 0 ]; thenaddout "G"
elseaddout "P"echo " * proprietary module was loaded (#0)"
fiT=`expr $T / 2`
if [ `expr $T % 2` -eq 0 ]; thenaddout " "
elseaddout "F"echo " * module was force loaded (#1)"
fiT=`expr $T / 2`
if [ `expr $T % 2` -eq 0 ]; thenaddout " "
elseaddout "S"echo " * kernel running on an out of specification system (#2)"
fiT=`expr $T / 2`
if [ `expr $T % 2` -eq 0 ]; thenaddout " "
elseaddout "R"echo " * module was force unloaded (#3)"
fiT=`expr $T / 2`
if [ `expr $T % 2` -eq 0 ]; thenaddout " "
elseaddout "M"echo " * processor reported a Machine Check Exception (MCE) (#4)"
fiT=`expr $T / 2`
if [ `expr $T % 2` -eq 0 ]; thenaddout " "
elseaddout "B"echo " * bad page referenced or some unexpected page flags (#5)"
fiT=`expr $T / 2`
if [ `expr $T % 2` -eq 0 ]; thenaddout " "
elseaddout "U"echo " * taint requested by userspace application (#6)"
fiT=`expr $T / 2`
if [ `expr $T % 2` -eq 0 ]; thenaddout " "
elseaddout "D"echo " * kernel died recently, i.e. there was an OOPS or BUG (#7)"
fiT=`expr $T / 2`
if [ `expr $T % 2` -eq 0 ]; thenaddout " "
elseaddout "A"echo " * an ACPI table was overridden by user (#8)"
fiT=`expr $T / 2`
if [ `expr $T % 2` -eq 0 ]; thenaddout " "
elseaddout "W"echo " * kernel issued warning (#9)"
fiT=`expr $T / 2`
if [ `expr $T % 2` -eq 0 ]; thenaddout " "
elseaddout "C"echo " * staging driver was loaded (#10)"
fiT=`expr $T / 2`
if [ `expr $T % 2` -eq 0 ]; thenaddout " "
elseaddout "I"echo " * workaround for bug in platform firmware applied (#11)"
fiT=`expr $T / 2`
if [ `expr $T % 2` -eq 0 ]; thenaddout " "
elseaddout "O"echo " * externally-built ('out-of-tree') module was loaded  (#12)"
fiT=`expr $T / 2`
if [ `expr $T % 2` -eq 0 ]; thenaddout " "
elseaddout "E"echo " * unsigned module was loaded (#13)"
fiT=`expr $T / 2`
if [ `expr $T % 2` -eq 0 ]; thenaddout " "
elseaddout "L"echo " * soft lockup occurred (#14)"
fiT=`expr $T / 2`
if [ `expr $T % 2` -eq 0 ]; thenaddout " "
elseaddout "K"echo " * kernel has been live patched (#15)"
fiT=`expr $T / 2`
if [ `expr $T % 2` -eq 0 ]; thenaddout " "
elseaddout "X"echo " * auxiliary taint, defined for and used by distros (#16)"fi
T=`expr $T / 2`
if [ `expr $T % 2` -eq 0 ]; thenaddout " "
elseaddout "T"echo " * kernel was built with the struct randomization plugin (#17)"
fiecho "Raw taint value as int/string: $taint/'$out'"
#EOF#

可以通过上述数字解码该号码。 如果只有一个原因导致内核受到污染,这很容易,因为在这种情况下,可以在下表中找到数字。 如果有多种原因,您需要解码该数字,因为它是一个位域,其中每个位表示特定类型的污点的缺失或存在。 最好用之前提到的脚本进行解码 tools/debugging/kernel-chktaint。

但也可以使用下面 shell 命令来检查哪些位被设置:

for i in $(seq 18)
do echo $(($i-1)) $(($(cat /proc/sys/kernel/tainted)>>($i-1)&1));
done



注:为方便阅读,本表中字符_代表空白。
上面显示:
bit9=1,kernel issued warning。
bit12=1,externally-built (“out-of-tree”) module was loaded。

执行 tools/debugging/kernel-chktaint脚本:

加载一个自定义模块后:
上面显示
bit9=1,kernel issued warning。
bit12=1,externally-built (“out-of-tree”) module was loaded。
bit13=1,unsigned module was loaded。

执行 tools/debugging/kernel-chktaint脚本:

卸载掉加载的模块后:

污染event仍然存在:即使撤消导致污染的原因(即卸载专有内核模块),内核仍将保持污染,这表明内核仍然不可信。

三、源码分析

struct module结构中的成员taints表示内核模块是否会污染内核,如果模块会污染内核,便调用add_taint_module函数 设置 struct module的taints成员。

// linux-5.13/include/linux/module.hstruct module {......unsigned long taints;   /* same bits as kernel:taint_flags */......
}
// linux-5.13/kernel/module.cstatic inline void add_taint_module(struct module *mod, unsigned flag,enum lockdep_ok lockdep_ok)
{add_taint(flag, lockdep_ok);set_bit(flag, &mod->taints);
}
// linux-5.13/kernel/panic.c/*** add_taint: add a taint flag if not already set.* @flag: one of the TAINT_* constants.* @lockdep_ok: whether lock debugging is still OK.** If something bad has gone wrong, you'll want @lockdebug_ok = false, but for* some notewortht-but-not-corrupting cases, it can be set to true.*/
void add_taint(unsigned flag, enum lockdep_ok lockdep_ok)
{if (lockdep_ok == LOCKDEP_NOW_UNRELIABLE && __debug_locks_off())pr_warn("Disabling lock debugging due to kernel taint\n");set_bit(flag, &tainted_mask);if (tainted_mask & panic_on_taint) {panic_on_taint = 0;panic("panic_on_taint set ...");}
}
EXPORT_SYMBOL(add_taint);
// include/linux/kernel.h/* This cannot be an enum because some may be used in assembly source. */
#define TAINT_PROPRIETARY_MODULE    0
#define TAINT_FORCED_MODULE     1
#define TAINT_CPU_OUT_OF_SPEC       2
#define TAINT_FORCED_RMMOD      3
#define TAINT_MACHINE_CHECK     4
#define TAINT_BAD_PAGE          5
#define TAINT_USER          6
#define TAINT_DIE           7
#define TAINT_OVERRIDDEN_ACPI_TABLE 8
#define TAINT_WARN          9
#define TAINT_CRAP          10
#define TAINT_FIRMWARE_WORKAROUND   11
#define TAINT_OOT_MODULE        12
#define TAINT_UNSIGNED_MODULE       13
#define TAINT_SOFTLOCKUP        14
#define TAINT_LIVEPATCH         15
#define TAINT_AUX           16
#define TAINT_RANDSTRUCT        17
#define TAINT_FLAGS_COUNT       18
#define TAINT_FLAGS_MAX         ((1UL << TAINT_FLAGS_COUNT) - 1)struct taint_flag {char c_true;   /* character printed when tainted */char c_false;   /* character printed when not tainted */bool module;    /* also show as a per-module taint flag */extern const struct taint_flag taint_flags[TAINT_FLAGS_COUNT];
// /kernel/panic.cstatic unsigned long tainted_mask =IS_ENABLED(CONFIG_GCC_PLUGIN_RANDSTRUCT) ? (1 << TAINT_RANDSTRUCT) : 0;/** TAINT_FORCED_RMMOD could be a per-module flag but the module* is being removed anyway.*/
const struct taint_flag taint_flags[TAINT_FLAGS_COUNT] = {[ TAINT_PROPRIETARY_MODULE ] = { 'P', 'G', true },[ TAINT_FORCED_MODULE ]       = { 'F', ' ', true },[ TAINT_CPU_OUT_OF_SPEC ] = { 'S', ' ', false },[ TAINT_FORCED_RMMOD ]       = { 'R', ' ', false },[ TAINT_MACHINE_CHECK ]      = { 'M', ' ', false },[ TAINT_BAD_PAGE ]       = { 'B', ' ', false },[ TAINT_USER ]           = { 'U', ' ', false },[ TAINT_DIE ]            = { 'D', ' ', false },[ TAINT_OVERRIDDEN_ACPI_TABLE ]  = { 'A', ' ', false },[ TAINT_WARN ]           = { 'W', ' ', false },[ TAINT_CRAP ]           = { 'C', ' ', true },[ TAINT_FIRMWARE_WORKAROUND ] = { 'I', ' ', false },[ TAINT_OOT_MODULE ]     = { 'O', ' ', true },[ TAINT_UNSIGNED_MODULE ] = { 'E', ' ', true },[ TAINT_SOFTLOCKUP ]      = { 'L', ' ', false },[ TAINT_LIVEPATCH ]      = { 'K', ' ', true },[ TAINT_AUX ]         = { 'X', ' ', true },[ TAINT_RANDSTRUCT ]      = { 'T', ' ', true },
};/*** print_tainted - return a string to represent the kernel taint state.** For individual taint flag meanings, see Documentation/admin-guide/sysctl/kernel.rst** The string is overwritten by the next call to print_tainted(),* but is always NULL terminated.*/
const char *print_tainted(void)
{static char buf[TAINT_FLAGS_COUNT + sizeof("Tainted: ")];BUILD_BUG_ON(ARRAY_SIZE(taint_flags) != TAINT_FLAGS_COUNT);if (tainted_mask) {char *s;int i;s = buf + sprintf(buf, "Tainted: ");for (i = 0; i < TAINT_FLAGS_COUNT; i++) {const struct taint_flag *t = &taint_flags[i];*s++ = test_bit(i, &tainted_mask) ?t->c_true : t->c_false;}*s = 0;} elsesnprintf(buf, sizeof(buf), "Not tainted");return buf;
}int test_taint(unsigned flag)
{return test_bit(flag, &tainted_mask);
}
EXPORT_SYMBOL(test_taint);unsigned long get_taint(void)
{return tainted_mask;
}

看了下源码,感觉挺清晰的,就不分析了。

总结

以上就是Tainted kernels的相关知识。

参考资料

Linux 5.13.0

https://www.kernel.org/doc/html/latest/admin-guide/tainted-kernels.html

Tainted kernels相关推荐

  1. Tainted: G O 分析(Tainted kernels)

    最近编译内核驱动出现错误,使用dump_stack()函数查看问题,出现以下日志: 其中,对CPU: 0 PID: 7852 Comm: v4l_id Tainted: G           O   ...

  2. Linux 内核编程指南

    Linux 内核编程指南   PeterJay Salzman MichaelBurian OriPomerantz Copyright© 2001 Peter Jay Salzman 2007−05 ...

  3. linux内核文档汇集

    链接:https://01.org/linuxgraphics/gfx-docs/drm/ The Linux Kernel documentation This is the top level o ...

  4. keras bi-lstm_LSTM用于文本生成的应用介绍-使用Keras和启用GPU的Kaggle Kernels

    keras bi-lstm by Megan Risdal 梅根·里斯达尔(Megan Risdal) LSTM用于文本生成的应用介绍-使用Keras和启用GPU的Kaggle Kernels (An ...

  5. 时间序列入门教程,从理论到业务实践,Kaggle kernels Master 整理分享

    一.前言 最近逛了逛Kaggle,发现了一个非常详细的时间序列教程. 里面记载了很多关于时间序列的知识,并且一直在updating中. 可以看到这个教程已经被观看了6w多次. 点赞700+, copy ...

  6. KerGNNs:结合Graph kernels的可解释GNN

    目录 引言 方法 KerGNNs 时间复杂度分析 实验 实验结果 可解释性 AAAI2022的文章 "KerGNNs: Interpretable Graph Neural Networks ...

  7. WARNING:tensorflow:Layer gru will not use cuDNN kernels since it doesn‘t meet the criteria. It will

    WARNING:tensorflow:Layer gru will not use cuDNN kernels since it doesn't meet the criteria. It will ...

  8. 带你走进Kaggle Kernels(内附视频讲解)

    更为详细内容,请查看文末视频链接. 在这一集的AI奇遇记中,我们的任务是介绍Kaggle Kernels是什么,以及如何开始使用它们. Kaggle是一个用来研究和共享数据科学的平台,你可能听说过Ka ...

  9. linux/usr/src/kernels 目录下没有内核源码 解决方法

    有时我们在安装系统后,发现没有安装当前系统的内核源码在/usr/src/kernels目录下,其实我们是少安装了一个rpm包: 当你配置好yum源后,然后安装下面的包就可以了: 针对CentOS系统: ...

最新文章

  1. 教你如何以对象的方式思考
  2. 外包网络推广公司探索出高排名网站优化的技巧!
  3. Servlet-Access denied for user 'root'@'localhost' (using password: YES
  4. python colorlist_Python list的常用操作
  5. 【干货】全球大数据领域顶级开源工具汇总
  6. java magnolia,java – Magnolia富文本字段
  7. Java无所不能的反射在Android中需要熟练的知识
  8. Java 8 新特性001_Java 8 Optional 类
  9. Process Explorer更新至v15.2
  10. Spark Streaming 实时流处理总结
  11. elementui如何在input 框中搜索_【挑战自学Python编程】第八天:while循环以及input()函数...
  12. ⒔Bash 内部命令
  13. AutoCAD 2021-2022
  14. VM189:1 Uncaught SyntaxError: Unexpected token o in JSON at position 1
  15. 计算机配置时能关机吗,怎么设置时间让电脑自动关机?
  16. iOS 苹果2.1大礼包解决方法
  17. javaweb项目JS文件报错解决办法
  18. 故障-未识别的网络的几种情况
  19. 真的!?在阅读体验感上赢过微信读书?
  20. Ubuntu离线安装无线网卡驱动

热门文章

  1. 几何级数的计算机验证法c语言解析,c语言编程20例.doc
  2. 设计模式 行为型模式 实例 -- 备忘录模式实例:游戏备忘录
  3. android socketio权限,简要分析socketio-auth
  4. charles抓包工具代理抓手机包
  5. input框添加disabled属性
  6. hexo上传网页无法显示图片的有效解决方法
  7. 最小二乘法的原理理解
  8. GIT全局代理和局部代理
  9. php opcache缺点,PHP Opcache 注意事项以及调优
  10. 微信小程序的同步异步解决方案