• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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