1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2018 Michael Moese <mmoese@suse.com>
4 * Copyright (c) Linux Test Project, 2020
5 */
6
7 #define TST_NO_DEFAULT_MAIN
8
9 #include "tst_test.h"
10 #include "tst_taint.h"
11 #include "tst_safe_stdio.h"
12
13 #define TAINT_FILE "/proc/sys/kernel/tainted"
14
15 static unsigned int taint_mask = -1;
16
17 static const char *const taint_strings[] = {
18 "G (Propriety module loaded)",
19 "F (Module force loaded)",
20 "S (Running on out of spec system)",
21 "R (Module force unloaded)",
22 "M (Machine check exception)",
23 "B (Bad page reference)",
24 "U (User request)",
25 "D (OOPS/BUG)",
26 "A (ACPI table overridden)",
27 "W (Warning)",
28 "C (Staging driver loaded)",
29 "I (Workaround BIOS/FW bug)",
30 "O (Out of tree module loaded)",
31 "E (Unsigned module loaded)",
32 "L (Soft lock up occured)",
33 "K (Live patched)",
34 "X (Auxilary)",
35 "T (Built with struct randomization)",
36 };
37
tst_taint_read(void)38 static unsigned int tst_taint_read(void)
39 {
40 unsigned int val;
41
42 SAFE_FILE_SCANF(TAINT_FILE, "%u", &val);
43
44 return val;
45 }
46
tst_taint_check_kver(unsigned int mask)47 static int tst_taint_check_kver(unsigned int mask)
48 {
49 int r1;
50 int r2;
51 int r3 = 0;
52
53 if (mask & TST_TAINT_X) {
54 r1 = 4;
55 r2 = 15;
56 } else if (mask & TST_TAINT_K) {
57 r1 = 4;
58 r2 = 0;
59 } else if (mask & TST_TAINT_L) {
60 r1 = 3;
61 r2 = 17;
62 } else if (mask & TST_TAINT_E) {
63 r1 = 3;
64 r2 = 15;
65 } else if (mask & TST_TAINT_O) {
66 r1 = 3;
67 r2 = 2;
68 } else if (mask & TST_TAINT_I) {
69 r1 = 2;
70 r2 = 6;
71 r3 = 35;
72 } else if (mask & TST_TAINT_C) {
73 r1 = 2;
74 r2 = 6;
75 r3 = 28;
76 } else if (mask & TST_TAINT_W) {
77 r1 = 2;
78 r2 = 6;
79 r3 = 26;
80 } else if (mask & TST_TAINT_A) {
81 r1 = 2;
82 r2 = 6;
83 r3 = 25;
84 } else if (mask & TST_TAINT_D) {
85 r1 = 2;
86 r2 = 6;
87 r3 = 23;
88 } else if (mask & TST_TAINT_U) {
89 r1 = 2;
90 r2 = 6;
91 r3 = 21;
92 } else {
93 r1 = 2;
94 r2 = 6;
95 r3 = 16;
96 }
97
98 return tst_kvercmp(r1, r2, r3);
99 }
100
tst_taint_init(unsigned int mask)101 void tst_taint_init(unsigned int mask)
102 {
103 unsigned int taint = -1;
104 unsigned long i;
105
106 if (mask == 0)
107 tst_brk(TBROK, "mask is not allowed to be 0");
108
109 if (tst_taint_check_kver(mask) < 0)
110 tst_res(TCONF, "Kernel is too old for requested mask");
111
112 taint_mask = mask;
113 taint = tst_taint_read();
114
115 if (taint & TST_TAINT_W) {
116 tst_res(TCONF, "Ignoring already set kernel warning taint");
117 taint_mask &= ~TST_TAINT_W;
118 }
119
120 if ((taint & taint_mask) != 0) {
121 for (i = 0; i < ARRAY_SIZE(taint_strings); i++) {
122 if (taint & (1 << i))
123 tst_res(TINFO, "tainted: %s", taint_strings[i]);
124 }
125
126 tst_brk(TBROK, "Kernel is already tainted");
127 }
128 }
129
130
tst_taint_check(void)131 unsigned int tst_taint_check(void)
132 {
133 unsigned int taint = -1;
134
135 if (taint_mask == (unsigned int) -1)
136 tst_brk(TBROK, "need to call tst_taint_init() first");
137
138 taint = tst_taint_read();
139
140 return (taint & taint_mask);
141 }
142