• 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 	"N (In-kernel test has been run)",
37 };
38 
tst_taint_read(void)39 static unsigned int tst_taint_read(void)
40 {
41 	unsigned int val;
42 
43 	SAFE_FILE_SCANF(TAINT_FILE, "%u", &val);
44 
45 	return val;
46 }
47 
tst_taint_check_kver(unsigned int mask)48 static int tst_taint_check_kver(unsigned int mask)
49 {
50 	int r1;
51 	int r2;
52 	int r3 = 0;
53 
54 	if (mask & TST_TAINT_N) {
55 		r1 = 6;
56 		r2 = 0;
57 	} else if (mask & TST_TAINT_X) {
58 		r1 = 4;
59 		r2 = 15;
60 	} else if (mask & TST_TAINT_K) {
61 		r1 = 4;
62 		r2 = 0;
63 	} else {
64 		return 1;
65 	}
66 
67 	return tst_kvercmp(r1, r2, r3);
68 }
69 
tst_taint_init(unsigned int mask)70 void tst_taint_init(unsigned int mask)
71 {
72 	unsigned int taint = -1;
73 	unsigned long i;
74 
75 	if (mask == 0)
76 		tst_brk(TBROK, "mask is not allowed to be 0");
77 
78 	if (tst_taint_check_kver(mask) < 0)
79 		tst_res(TCONF, "Kernel is too old for requested mask");
80 
81 	taint_mask = mask;
82 	taint = tst_taint_read();
83 
84 	if (taint & TST_TAINT_W) {
85 		tst_res(TCONF, "Ignoring already set kernel warning taint");
86 		taint_mask &= ~TST_TAINT_W;
87 	}
88 
89 	if ((taint & taint_mask) != 0) {
90 		for (i = 0; i < ARRAY_SIZE(taint_strings); i++) {
91 			if (taint & (1 << i))
92 				tst_res(TINFO, "tainted: %s", taint_strings[i]);
93 		}
94 
95 		tst_brk(TBROK, "Kernel is already tainted");
96 	}
97 }
98 
99 
tst_taint_check(void)100 unsigned int tst_taint_check(void)
101 {
102 	unsigned int taint = -1;
103 
104 	if (taint_mask == (unsigned int) -1)
105 		tst_brk(TBROK, "need to call tst_taint_init() first");
106 
107 	taint = tst_taint_read();
108 
109 	return (taint & taint_mask);
110 }
111