1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
/*
*
* This is a part of taint-info.
* Copyright (C) 2018 Cynthia Revstrom <me@cynthia.re>
*
* taint-info is licensed under the MIT License.
* For a full license please refer to the LICENSE file in the root of the taint-info repository.
*
* The taint flag info in this file is from the Linux kernel documentation, available at: https://www.kernel.org/doc/Documentation/sysctl/kernel.txt
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "taint_flags.h"
void usage() {
printf("taint-info - Kernel Taint Info\n");
printf("Copyright (C) 2018 Cynthia Revström <me@cynthia.re>\n");
printf("Usage:\n");
printf(" -h: this help\n");
printf(" -i <taint value>: show information based on \"taint\" value.\n");
printf(" -p: show information based on this computer's taint value.\n");
}
void check_taint_flag(int taintval, int flag, char* flag_name, char* msg) {
if(taintval & flag) {
printf("%s: %s\n", flag_name, msg);
}
}
void check_flags(int taintval) {
if(taintval != 0) {
printf("Kernel is tainted :(\n");
printf("Taint value: %d\n", taintval);
// Check for taint flags
printf("Taint flags: \n");
check_taint_flag(taintval, TAINT_NON_GPL, "NON_GPL", "Non-GPL module loaded");
check_taint_flag(taintval, TAINT_FORCE_LOAD, "FORCE_LOAD", "Kernel module force loaded with insmod -f");
check_taint_flag(taintval, TAINT_UNSAFE_SMP, "UNSAFE_SMP", "SMP with CPU not designed for SMP");
check_taint_flag(taintval, TAINT_FORCE_UNLOAD, "FORCE_UNLOAD", "Kernel module force unloaded with rmmod -f");
check_taint_flag(taintval, TAINT_HW_CHECK_ERR, "HW_CHECK_ERR", "Hardware check error");
check_taint_flag(taintval, TAINT_BAD_PAGE, "BAD_PAGE", "A bad page was discovered on the system");
check_taint_flag(taintval, TAINT_MARK_TAINT, "MARK_TAINT", "The user has marked the software as tainted");
check_taint_flag(taintval, TAINT_SYSTEM_DIED, "SYSTEM_DIED", "The system has died");
check_taint_flag(taintval, TAINT_ACPI_DSDT_OVERRIDE, "ACPI_DSDT_OVERRIDE", "The ACPI DSDT has been overridden");
check_taint_flag(taintval, TAINT_KERNEL_WARN, "KERNEL_WARN", "A kernel warning has occured");
check_taint_flag(taintval, TAINT_MOD_STAGING, "MOD_STAGING", "A module from drivers/staging was loaded");
check_taint_flag(taintval, TAINT_SYS_FW_BUG, "SYS_FW_BUG", "The system is working around a severe firmware bug");
check_taint_flag(taintval, TAINT_OOT_MOD, "OOT_MOD", "An out-of-tree-module has been loaded");
check_taint_flag(taintval, TAINT_UNSIGNED, "UNSIGNED", "An unsigned module has been loaded into a kernel supporting module signatures");
check_taint_flag(taintval, TAINT_SOFT_LOCKUP, "SOFT_LOCKUP", "A soft lockup has previously occured on the system");
check_taint_flag(taintval, TAINT_LIVE_PATCHED, "LIVE_PATCHED", "The kernel has been live patched");
check_taint_flag(taintval, TAINT_AUX, "AUX", "Auxiliary taint, defined and used by distros");
check_taint_flag(taintval, TAINT_STRUCT_RANDOM, "STRUCT_RANDOM", "The kernel was built with the struct randomization plugin");
} else {
printf("Kernel is not tainted :)");
}
}
void check_proc() {
char buf[2048];
FILE* fh;
size_t size;
// Read /proc/sys/kernel/tainted
fh = fopen("/proc/sys/kernel/tainted", "r");
size = fread(&buf, 1, sizeof(buf), fh);
fclose(fh);
buf[size] = '\0';
// Parse the string from tainted to an int
char* end;
long l = strtol(buf, &end, 10);
int taintval = (int) l;
// Check the taint
check_flags(taintval);
}
void check_flags_cli(char* flagstr) {
// Parse the string to an int
char* end;
long l = strtol(flagstr, &end, 10);
int taintval = (int) l;
// Check the taint
check_flags(taintval);
}
int main(int argc, char** argv) {
char* flag_input;
int opt;
enum { INTEGER_FLAG_MODE, PROC_MODE, HELP_MODE } mode = HELP_MODE;
while ((opt = getopt(argc, argv, "i:hp")) != -1) {
switch(opt) {
case 'i':
mode = INTEGER_FLAG_MODE;
flag_input = optarg;
break;
case 'h':
mode = HELP_MODE;
break;
case 'p':
mode = PROC_MODE;
break;
default:
usage();
exit(EXIT_FAILURE);
}
}
if (mode == INTEGER_FLAG_MODE) {
check_flags_cli(flag_input);
} else if (mode == PROC_MODE) {
check_proc();
} else if (mode == HELP_MODE) {
usage();
}
return 0;
}
|