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