汙點核心

當發生一些可能與以後調查問題相關的事情時,核心會將自己標記為“汙點”。不要太擔心這一點,大多數時候執行汙點核心沒有問題;一旦有人想要調查某些問題,這些資訊主要是有意義的,因為它的真正原因可能是導致核心汙點的事件。這就是為什麼來自汙點核心的錯誤報告通常會被開發人員忽略,因此請嘗試用未汙點的核心重現問題。

請注意,即使在您撤消導致汙點的原因(即解除安裝專有核心模組)後,核心仍將保持汙點狀態,以表明核心仍然不可信。這也是為什麼當核心注意到內部問題(“核心錯誤”)、可恢復錯誤(“核心 oops”)或不可恢復錯誤(“核心 panic”)時,會列印汙點狀態並將有關此問題的除錯資訊寫入日誌 dmesg 輸出。也可以透過/proc/中的檔案在執行時檢查汙點狀態。

錯誤、oops或panic訊息中的汙點標誌

您可以在以“CPU:”開頭的一行的頂部附近找到汙點狀態;如果在程序ID (“PID:”) 和觸發該事件的命令的縮寫名稱 (“Comm:”) 之後顯示核心被汙點的原因

BUG: unable to handle kernel NULL pointer dereference at 0000000000000000
Oops: 0002 [#1] SMP PTI
CPU: 0 PID: 4424 Comm: insmod Tainted: P        W  O      4.20.0-0.rc6.fc30 #1
Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011
RIP: 0010:my_oops_init+0x13/0x1000 [kpanic]
[...]

如果核心在事件發生時未被汙點,您會在此處找到“Not tainted: ”;如果被汙點,則將列印“Tainted: ”以及字母或空格。在上面的例子中,它看起來像這樣

Tainted: P        W  O

這些字元的含義在下表中進行了解釋。在這種情況下,核心早期被汙染是因為載入了專有模組 (P),發生了警告 (W),並且載入了外部構建的模組 (O)。要解碼其他字母,請使用下表。

在執行時解碼汙點狀態

在執行時,您可以透過讀取cat /proc/sys/kernel/tainted來查詢汙點狀態。如果返回0,則核心未被汙點;任何其他數字都表示被汙點的原因。解碼該數字的最簡單方法是指令碼tools/debugging/kernel-chktaint,您的發行版可能會將其作為名為linux-toolskernel-tools的軟體包的一部分;如果沒有,您可以從git.kernel.org下載該指令碼,並使用sh kernel-chktaint執行它,這將在先前引用的日誌中包含語句的機器上列印如下內容

Kernel is Tainted for following reasons:
 * Proprietary module was loaded (#0)
 * Kernel issued warning (#9)
 * Externally-built ('out-of-tree') module was loaded  (#12)
See Documentation/admin-guide/tainted-kernels.rst in the Linux kernel or
 https://kernel.linux.club.tw/doc/html/latest/admin-guide/tainted-kernels.html for
 a more details explanation of the various taint flags.
Raw taint value as int/string: 4609/'P        W  O     '

您可以嘗試自己解碼該數字。如果只有一種原因導致您的核心被汙點,那麼這很容易,在這種情況下,您可以在下表中找到該數字。如果有多個原因,您需要解碼該數字,因為它是一個位域,其中每個位表示是否存在特定型別的汙點。最好將此留給前面提到的指令碼,但如果您需要快速的東西,可以使用此shell命令來檢查設定了哪些位

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

解碼汙點狀態的表

日誌

編號

導致核心被汙染的原因

0

G/P

1

已載入專有模組

1

_/F

2

強制載入模組

2

_/S

4

核心在不符合規範的系統上執行

3

_/R

8

強制解除安裝模組

4

_/M

16

處理器報告了機器檢查異常 (MCE)

5

_/B

32

引用了錯誤的頁面或一些意外的頁面標誌

6

_/U

64

使用者空間應用程式請求汙點

7

_/D

128

核心最近已死亡,即存在 OOPS 或 BUG

8

_/A

256

ACPI表被使用者覆蓋

9

_/W

512

核心發出警告

10

_/C

1024

已載入暫存驅動程式

11

_/I

2048

應用了針對平臺韌體中錯誤的解決方法

12

_/O

4096

已載入外部構建(“樹外”)模組

13

_/E

8192

已載入未簽名的模組

14

_/L

16384

發生軟鎖死

15

_/K

32768

核心已進行即時修補

16

_/X

65536

輔助汙點,為發行版定義和使用

17

_/T

131072

核心使用結構隨機化外掛構建

18

_/N

262144

已執行核心測試

19

_/J

524288

使用者空間在fwctl中使用了改變除錯操作

注意:字元_在此表中表示空格,以方便閱讀。

汙點的更詳細說明

  1. 如果載入的所有模組都具有GPL或相容許可證,則為G;如果已載入任何專有模組,則為P。沒有MODULE_LICENSE或MODULE_LICENSE未被insmod識別為GPL相容的模組被假定為專有模組。

  2. 如果任何模組被insmod -f強制載入,則為F;如果所有模組都正常載入,則為' '

  3. 如果核心在不符合規範的處理器或系統上執行,則為S:硬體已置於不受支援的配置中,因此無法保證正確的執行。例如,如果核心被汙染

    • 在x86上:在不報告PAE但可能具有功能實現的intel CPU(例如Pentium M)上,透過forcepae強制使用PAE,SMP核心在非官方支援SMP的Athlon CPU上執行,MSR正在從使用者空間被探測。

    • 在arm上:核心在某些CPU(例如Keystone 2)上執行,而沒有啟用某些核心功能。

    • 在arm64上:CPU之間的硬體功能不匹配,引導載入程式以不同的模式啟動CPU。

    • 某些驅動程式在不受支援的體系結構上使用(例如,x86_64以外的scsi/snic,非x86/x86_64/itanium上的scsi/ips,為arm64上的irqchip/irq-gic具有損壞的韌體設定......)。

    • x86/x86_64:微程式碼延遲載入是危險的,會導致核心汙染。它要求所有CPU匯合以確保在系統儘可能靜止時進行更新。但是,更高優先順序的MCE/SMI/NMI可以使控制流遠離該匯合並中斷更新,這對機器可能有害。

  4. 如果模組被rmmod -f強制解除安裝,則為R;如果所有模組都正常解除安裝,則為' '

  5. 如果任何處理器報告了機器檢查異常,則為M;如果未發生機器檢查異常,則為' '

  6. 如果頁面釋放函式找到錯誤的頁面引用或一些意外的頁面標誌。這表示硬體問題或核心錯誤;日誌中應該有其他資訊指示發生此汙點的原因。

  7. 如果使用者或使用者應用程式專門請求設定Tainted標誌,則為U;否則為' '

  8. 如果核心最近已死亡,即存在OOPS或BUG,則為D

  9. 如果ACPI表已被覆蓋,則為A

  10. 如果核心先前已發出警告,則為W。(儘管某些警告可能會設定更具體的汙點標誌。)

  11. 如果已載入暫存驅動程式,則為C

  12. 如果核心正在解決平臺韌體(BIOS或類似韌體)中的嚴重錯誤,則為I

  13. 如果已載入外部構建(“樹外”)模組,則為O

  14. 如果在支援模組簽名的核心中載入了未簽名的模組,則為E

  15. 如果系統先前發生了軟鎖死,則為L

  16. 如果核心已進行即時修補,則為K

  17. X 輔助汙點,為Linux發行商定義和使用。

  18. T 核心使用 randstruct 外掛構建,該外掛可能會有意產生極其不尋常的核心結構佈局(甚至是效能病態的佈局),這在除錯時非常重要。 在構建時設定。

  19. N 如果已執行核心測試,例如 KUnit 測試。

  20. J 如果使用者空間打開了 /dev/fwctl/* 並執行了 FWTCL_RPC_DEBUG_WRITE 來使用該裝置的除錯功能。 裝置除錯功能可能會導致裝置以未定義的方式發生故障。