xref: /third_party/ltp/lib/tst_taint.c (revision f08c3bdf)
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
15static unsigned int taint_mask = -1;
16
17static 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
38static 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
47static 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
101void 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
131unsigned 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