aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/panic.c
diff options
context:
space:
mode:
authorAndi Kleen <andi@firstfloor.org>2008-10-16 01:01:41 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-10-16 14:21:31 -0400
commit25ddbb18aae33ad255eb9f35aacebe3af01e1e9c (patch)
tree8df1f840a226ed640c2096710b7d0f1f4d1b88aa /kernel/panic.c
parent889d51a10712b6fd6175196626de2116858394f4 (diff)
Make the taint flags reliable
It's somewhat unlikely that it happens, but right now a race window between interrupts or machine checks or oopses could corrupt the tainted bitmap because it is modified in a non atomic fashion. Convert the taint variable to an unsigned long and use only atomic bit operations on it. Unfortunately this means the intvec sysctl functions cannot be used on it anymore. It turned out the taint sysctl handler could actually be simplified a bit (since it only increases capabilities) so this patch actually removes code. [akpm@linux-foundation.org: remove unneeded include] Signed-off-by: Andi Kleen <ak@linux.intel.com> Cc: Ingo Molnar <mingo@elte.hu> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/panic.c')
-rw-r--r--kernel/panic.c63
1 files changed, 46 insertions, 17 deletions
diff --git a/kernel/panic.c b/kernel/panic.c
index 12c5a0a6c89b..028013f7afd4 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -23,7 +23,7 @@
23#include <linux/kallsyms.h> 23#include <linux/kallsyms.h>
24 24
25int panic_on_oops; 25int panic_on_oops;
26int tainted; 26static unsigned long tainted_mask;
27static int pause_on_oops; 27static int pause_on_oops;
28static int pause_on_oops_flag; 28static int pause_on_oops_flag;
29static DEFINE_SPINLOCK(pause_on_oops_lock); 29static DEFINE_SPINLOCK(pause_on_oops_lock);
@@ -159,31 +159,60 @@ EXPORT_SYMBOL(panic);
159 * The string is overwritten by the next call to print_taint(). 159 * The string is overwritten by the next call to print_taint().
160 */ 160 */
161 161
162struct tnt {
163 u8 bit;
164 char true;
165 char false;
166};
167
168static const struct tnt tnts[] = {
169 { TAINT_PROPRIETARY_MODULE, 'P', 'G' },
170 { TAINT_FORCED_MODULE, 'F', ' ' },
171 { TAINT_UNSAFE_SMP, 'S', ' ' },
172 { TAINT_FORCED_RMMOD, 'R', ' ' },
173 { TAINT_MACHINE_CHECK, 'M', ' ' },
174 { TAINT_BAD_PAGE, 'B', ' ' },
175 { TAINT_USER, 'U', ' ' },
176 { TAINT_DIE, 'D', ' ' },
177 { TAINT_OVERRIDDEN_ACPI_TABLE, 'A', ' ' },
178 { TAINT_WARN, 'W', ' ' },
179};
180
162const char *print_tainted(void) 181const char *print_tainted(void)
163{ 182{
164 static char buf[20]; 183 static char buf[ARRAY_SIZE(tnts) + sizeof("Tainted: ") + 1];
165 if (tainted) { 184
166 snprintf(buf, sizeof(buf), "Tainted: %c%c%c%c%c%c%c%c%c%c", 185 if (tainted_mask) {
167 tainted & TAINT_PROPRIETARY_MODULE ? 'P' : 'G', 186 char *s;
168 tainted & TAINT_FORCED_MODULE ? 'F' : ' ', 187 int i;
169 tainted & TAINT_UNSAFE_SMP ? 'S' : ' ', 188
170 tainted & TAINT_FORCED_RMMOD ? 'R' : ' ', 189 s = buf + sprintf(buf, "Tainted: ");
171 tainted & TAINT_MACHINE_CHECK ? 'M' : ' ', 190 for (i = 0; i < ARRAY_SIZE(tnts); i++) {
172 tainted & TAINT_BAD_PAGE ? 'B' : ' ', 191 const struct tnt *t = &tnts[i];
173 tainted & TAINT_USER ? 'U' : ' ', 192 *s++ = test_bit(t->bit, &tainted_mask) ?
174 tainted & TAINT_DIE ? 'D' : ' ', 193 t->true : t->false;
175 tainted & TAINT_OVERRIDDEN_ACPI_TABLE ? 'A' : ' ', 194 }
176 tainted & TAINT_WARN ? 'W' : ' '); 195 *s = 0;
177 } 196 } else
178 else
179 snprintf(buf, sizeof(buf), "Not tainted"); 197 snprintf(buf, sizeof(buf), "Not tainted");
180 return(buf); 198 return(buf);
181} 199}
182 200
201int test_taint(unsigned flag)
202{
203 return test_bit(flag, &tainted_mask);
204}
205EXPORT_SYMBOL(test_taint);
206
207unsigned long get_taint(void)
208{
209 return tainted_mask;
210}
211
183void add_taint(unsigned flag) 212void add_taint(unsigned flag)
184{ 213{
185 debug_locks = 0; /* can't trust the integrity of the kernel anymore */ 214 debug_locks = 0; /* can't trust the integrity of the kernel anymore */
186 tainted |= flag; 215 set_bit(flag, &tainted_mask);
187} 216}
188EXPORT_SYMBOL(add_taint); 217EXPORT_SYMBOL(add_taint);
189 218