• 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 
tst_taint_read(void)17 static unsigned int tst_taint_read(void)
18 {
19 	unsigned int val;
20 
21 	SAFE_FILE_SCANF(TAINT_FILE, "%u", &val);
22 
23 	return val;
24 }
25 
tst_taint_check_kver(unsigned int mask)26 static int tst_taint_check_kver(unsigned int mask)
27 {
28 	int r1;
29 	int r2;
30 	int r3 = 0;
31 
32 	if (mask & TST_TAINT_X) {
33 		r1 = 4;
34 		r2 = 15;
35 	} else if (mask & TST_TAINT_K) {
36 		r1 = 4;
37 		r2 = 0;
38 	} else if (mask & TST_TAINT_L) {
39 		r1 = 3;
40 		r2 = 17;
41 	} else if (mask & TST_TAINT_E) {
42 		r1 = 3;
43 		r2 = 15;
44 	} else if (mask & TST_TAINT_O) {
45 		r1 = 3;
46 		r2 = 2;
47 	} else if (mask & TST_TAINT_I) {
48 		r1 = 2;
49 		r2 = 6;
50 		r3 = 35;
51 	} else if (mask & TST_TAINT_C) {
52 		r1 = 2;
53 		r2 = 6;
54 		r3 = 28;
55 	} else if (mask & TST_TAINT_W) {
56 		r1 = 2;
57 		r2 = 6;
58 		r3 = 26;
59 	} else if (mask & TST_TAINT_A) {
60 		r1 = 2;
61 		r2 = 6;
62 		r3 = 25;
63 	} else if (mask & TST_TAINT_D) {
64 		r1 = 2;
65 		r2 = 6;
66 		r3 = 23;
67 	} else if (mask & TST_TAINT_U) {
68 		r1 = 2;
69 		r2 = 6;
70 		r3 = 21;
71 	} else {
72 		r1 = 2;
73 		r2 = 6;
74 		r3 = 16;
75 	}
76 
77 	return tst_kvercmp(r1, r2, r3);
78 }
79 
tst_taint_init(unsigned int mask)80 void tst_taint_init(unsigned int mask)
81 {
82 	unsigned int taint = -1;
83 
84 	if (mask == 0)
85 		tst_brk(TBROK, "mask is not allowed to be 0");
86 
87 	if (tst_taint_check_kver(mask) < 0)
88 		tst_res(TCONF, "Kernel is too old for requested mask");
89 
90 	taint_mask = mask;
91 	taint = tst_taint_read();
92 
93 	if (taint & TST_TAINT_W) {
94 		tst_res(TCONF, "Ignoring already set kernel warning taint");
95 		taint_mask &= ~TST_TAINT_W;
96 	}
97 
98 	if ((taint & taint_mask) != 0)
99 		tst_brk(TBROK, "Kernel is already tainted: %u", taint);
100 }
101 
102 
tst_taint_check(void)103 unsigned int tst_taint_check(void)
104 {
105 	unsigned int taint = -1;
106 
107 	if (taint_mask == (unsigned int) -1)
108 		tst_brk(TBROK, "need to call tst_taint_init() first");
109 
110 	taint = tst_taint_read();
111 
112 	return (taint & taint_mask);
113 }
114