aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/smpboot.c14
-rw-r--r--include/linux/kernel.h25
-rw-r--r--kernel/module.c12
-rw-r--r--kernel/panic.c63
-rw-r--r--kernel/softlockup.c2
-rw-r--r--kernel/sysctl.c67
6 files changed, 101 insertions, 82 deletions
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 8c3aca7cb343..7ed9e070a6e9 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -282,6 +282,8 @@ static void __cpuinit smp_callin(void)
282 cpu_set(cpuid, cpu_callin_map); 282 cpu_set(cpuid, cpu_callin_map);
283} 283}
284 284
285static int __cpuinitdata unsafe_smp;
286
285/* 287/*
286 * Activate a secondary processor. 288 * Activate a secondary processor.
287 */ 289 */
@@ -397,7 +399,7 @@ static void __cpuinit smp_apply_quirks(struct cpuinfo_x86 *c)
397 goto valid_k7; 399 goto valid_k7;
398 400
399 /* If we get here, not a certified SMP capable AMD system. */ 401 /* If we get here, not a certified SMP capable AMD system. */
400 add_taint(TAINT_UNSAFE_SMP); 402 unsafe_smp = 1;
401 } 403 }
402 404
403valid_k7: 405valid_k7:
@@ -414,12 +416,10 @@ static void __cpuinit smp_checks(void)
414 * Don't taint if we are running SMP kernel on a single non-MP 416 * Don't taint if we are running SMP kernel on a single non-MP
415 * approved Athlon 417 * approved Athlon
416 */ 418 */
417 if (tainted & TAINT_UNSAFE_SMP) { 419 if (unsafe_smp && num_online_cpus() > 1) {
418 if (num_online_cpus()) 420 printk(KERN_INFO "WARNING: This combination of AMD"
419 printk(KERN_INFO "WARNING: This combination of AMD" 421 "processors is not suitable for SMP.\n");
420 "processors is not suitable for SMP.\n"); 422 add_taint(TAINT_UNSAFE_SMP);
421 else
422 tainted &= ~TAINT_UNSAFE_SMP;
423 } 423 }
424} 424}
425 425
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 75d81f157d2e..e971c55f45ac 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -235,9 +235,10 @@ extern int oops_in_progress; /* If set, an oops, panic(), BUG() or die() is in
235extern int panic_timeout; 235extern int panic_timeout;
236extern int panic_on_oops; 236extern int panic_on_oops;
237extern int panic_on_unrecovered_nmi; 237extern int panic_on_unrecovered_nmi;
238extern int tainted;
239extern const char *print_tainted(void); 238extern const char *print_tainted(void);
240extern void add_taint(unsigned); 239extern void add_taint(unsigned flag);
240extern int test_taint(unsigned flag);
241extern unsigned long get_taint(void);
241extern int root_mountflags; 242extern int root_mountflags;
242 243
243/* Values used for system_state */ 244/* Values used for system_state */
@@ -250,16 +251,16 @@ extern enum system_states {
250 SYSTEM_SUSPEND_DISK, 251 SYSTEM_SUSPEND_DISK,
251} system_state; 252} system_state;
252 253
253#define TAINT_PROPRIETARY_MODULE (1<<0) 254#define TAINT_PROPRIETARY_MODULE 0
254#define TAINT_FORCED_MODULE (1<<1) 255#define TAINT_FORCED_MODULE 1
255#define TAINT_UNSAFE_SMP (1<<2) 256#define TAINT_UNSAFE_SMP 2
256#define TAINT_FORCED_RMMOD (1<<3) 257#define TAINT_FORCED_RMMOD 3
257#define TAINT_MACHINE_CHECK (1<<4) 258#define TAINT_MACHINE_CHECK 4
258#define TAINT_BAD_PAGE (1<<5) 259#define TAINT_BAD_PAGE 5
259#define TAINT_USER (1<<6) 260#define TAINT_USER 6
260#define TAINT_DIE (1<<7) 261#define TAINT_DIE 7
261#define TAINT_OVERRIDDEN_ACPI_TABLE (1<<8) 262#define TAINT_OVERRIDDEN_ACPI_TABLE 8
262#define TAINT_WARN (1<<9) 263#define TAINT_WARN 9
263 264
264extern void dump_stack(void) __cold; 265extern void dump_stack(void) __cold;
265 266
diff --git a/kernel/module.c b/kernel/module.c
index 9db11911e04b..dd9ac6ad5cb9 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -100,7 +100,7 @@ static inline int strong_try_module_get(struct module *mod)
100static inline void add_taint_module(struct module *mod, unsigned flag) 100static inline void add_taint_module(struct module *mod, unsigned flag)
101{ 101{
102 add_taint(flag); 102 add_taint(flag);
103 mod->taints |= flag; 103 mod->taints |= (1U << flag);
104} 104}
105 105
106/* 106/*
@@ -923,7 +923,7 @@ static const char vermagic[] = VERMAGIC_STRING;
923static int try_to_force_load(struct module *mod, const char *symname) 923static int try_to_force_load(struct module *mod, const char *symname)
924{ 924{
925#ifdef CONFIG_MODULE_FORCE_LOAD 925#ifdef CONFIG_MODULE_FORCE_LOAD
926 if (!(tainted & TAINT_FORCED_MODULE)) 926 if (!test_taint(TAINT_FORCED_MODULE))
927 printk("%s: no version for \"%s\" found: kernel tainted.\n", 927 printk("%s: no version for \"%s\" found: kernel tainted.\n",
928 mod->name, symname); 928 mod->name, symname);
929 add_taint_module(mod, TAINT_FORCED_MODULE); 929 add_taint_module(mod, TAINT_FORCED_MODULE);
@@ -1033,7 +1033,7 @@ static unsigned long resolve_symbol(Elf_Shdr *sechdrs,
1033 const unsigned long *crc; 1033 const unsigned long *crc;
1034 1034
1035 ret = find_symbol(name, &owner, &crc, 1035 ret = find_symbol(name, &owner, &crc,
1036 !(mod->taints & TAINT_PROPRIETARY_MODULE), true); 1036 !(mod->taints & (1 << TAINT_PROPRIETARY_MODULE)), true);
1037 if (!IS_ERR_VALUE(ret)) { 1037 if (!IS_ERR_VALUE(ret)) {
1038 /* use_module can fail due to OOM, 1038 /* use_module can fail due to OOM,
1039 or module initialization or unloading */ 1039 or module initialization or unloading */
@@ -1634,7 +1634,7 @@ static void set_license(struct module *mod, const char *license)
1634 license = "unspecified"; 1634 license = "unspecified";
1635 1635
1636 if (!license_is_gpl_compatible(license)) { 1636 if (!license_is_gpl_compatible(license)) {
1637 if (!(tainted & TAINT_PROPRIETARY_MODULE)) 1637 if (!test_taint(TAINT_PROPRIETARY_MODULE))
1638 printk(KERN_WARNING "%s: module license '%s' taints " 1638 printk(KERN_WARNING "%s: module license '%s' taints "
1639 "kernel.\n", mod->name, license); 1639 "kernel.\n", mod->name, license);
1640 add_taint_module(mod, TAINT_PROPRIETARY_MODULE); 1640 add_taint_module(mod, TAINT_PROPRIETARY_MODULE);
@@ -2552,9 +2552,9 @@ static char *module_flags(struct module *mod, char *buf)
2552 mod->state == MODULE_STATE_GOING || 2552 mod->state == MODULE_STATE_GOING ||
2553 mod->state == MODULE_STATE_COMING) { 2553 mod->state == MODULE_STATE_COMING) {
2554 buf[bx++] = '('; 2554 buf[bx++] = '(';
2555 if (mod->taints & TAINT_PROPRIETARY_MODULE) 2555 if (mod->taints & (1 << TAINT_PROPRIETARY_MODULE))
2556 buf[bx++] = 'P'; 2556 buf[bx++] = 'P';
2557 if (mod->taints & TAINT_FORCED_MODULE) 2557 if (mod->taints & (1 << TAINT_FORCED_MODULE))
2558 buf[bx++] = 'F'; 2558 buf[bx++] = 'F';
2559 /* 2559 /*
2560 * TAINT_FORCED_RMMOD: could be added. 2560 * TAINT_FORCED_RMMOD: could be added.
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
diff --git a/kernel/softlockup.c b/kernel/softlockup.c
index cb838ee93a82..3953e4aed733 100644
--- a/kernel/softlockup.c
+++ b/kernel/softlockup.c
@@ -226,7 +226,7 @@ static void check_hung_uninterruptible_tasks(int this_cpu)
226 * If the system crashed already then all bets are off, 226 * If the system crashed already then all bets are off,
227 * do not report extra hung tasks: 227 * do not report extra hung tasks:
228 */ 228 */
229 if ((tainted & TAINT_DIE) || did_panic) 229 if (test_taint(TAINT_DIE) || did_panic)
230 return; 230 return;
231 231
232 read_lock(&tasklist_lock); 232 read_lock(&tasklist_lock);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index cfc5295f1e82..ec88fcc9a0d2 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -149,7 +149,7 @@ extern int max_lock_depth;
149#ifdef CONFIG_PROC_SYSCTL 149#ifdef CONFIG_PROC_SYSCTL
150static int proc_do_cad_pid(struct ctl_table *table, int write, struct file *filp, 150static int proc_do_cad_pid(struct ctl_table *table, int write, struct file *filp,
151 void __user *buffer, size_t *lenp, loff_t *ppos); 151 void __user *buffer, size_t *lenp, loff_t *ppos);
152static int proc_dointvec_taint(struct ctl_table *table, int write, struct file *filp, 152static int proc_taint(struct ctl_table *table, int write, struct file *filp,
153 void __user *buffer, size_t *lenp, loff_t *ppos); 153 void __user *buffer, size_t *lenp, loff_t *ppos);
154#endif 154#endif
155 155
@@ -379,10 +379,9 @@ static struct ctl_table kern_table[] = {
379#ifdef CONFIG_PROC_SYSCTL 379#ifdef CONFIG_PROC_SYSCTL
380 { 380 {
381 .procname = "tainted", 381 .procname = "tainted",
382 .data = &tainted, 382 .maxlen = sizeof(long),
383 .maxlen = sizeof(int),
384 .mode = 0644, 383 .mode = 0644,
385 .proc_handler = &proc_dointvec_taint, 384 .proc_handler = &proc_taint,
386 }, 385 },
387#endif 386#endif
388#ifdef CONFIG_LATENCYTOP 387#ifdef CONFIG_LATENCYTOP
@@ -2228,49 +2227,39 @@ int proc_dointvec(struct ctl_table *table, int write, struct file *filp,
2228 NULL,NULL); 2227 NULL,NULL);
2229} 2228}
2230 2229
2231#define OP_SET 0
2232#define OP_AND 1
2233#define OP_OR 2
2234
2235static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp,
2236 int *valp,
2237 int write, void *data)
2238{
2239 int op = *(int *)data;
2240 if (write) {
2241 int val = *negp ? -*lvalp : *lvalp;
2242 switch(op) {
2243 case OP_SET: *valp = val; break;
2244 case OP_AND: *valp &= val; break;
2245 case OP_OR: *valp |= val; break;
2246 }
2247 } else {
2248 int val = *valp;
2249 if (val < 0) {
2250 *negp = -1;
2251 *lvalp = (unsigned long)-val;
2252 } else {
2253 *negp = 0;
2254 *lvalp = (unsigned long)val;
2255 }
2256 }
2257 return 0;
2258}
2259
2260/* 2230/*
2261 * Taint values can only be increased 2231 * Taint values can only be increased
2232 * This means we can safely use a temporary.
2262 */ 2233 */
2263static int proc_dointvec_taint(struct ctl_table *table, int write, struct file *filp, 2234static int proc_taint(struct ctl_table *table, int write, struct file *filp,
2264 void __user *buffer, size_t *lenp, loff_t *ppos) 2235 void __user *buffer, size_t *lenp, loff_t *ppos)
2265{ 2236{
2266 int op; 2237 struct ctl_table t;
2238 unsigned long tmptaint = get_taint();
2239 int err;
2267 2240
2268 if (write && !capable(CAP_SYS_ADMIN)) 2241 if (write && !capable(CAP_SYS_ADMIN))
2269 return -EPERM; 2242 return -EPERM;
2270 2243
2271 op = OP_OR; 2244 t = *table;
2272 return do_proc_dointvec(table,write,filp,buffer,lenp,ppos, 2245 t.data = &tmptaint;
2273 do_proc_dointvec_bset_conv,&op); 2246 err = proc_doulongvec_minmax(&t, write, filp, buffer, lenp, ppos);
2247 if (err < 0)
2248 return err;
2249
2250 if (write) {
2251 /*
2252 * Poor man's atomic or. Not worth adding a primitive
2253 * to everyone's atomic.h for this
2254 */
2255 int i;
2256 for (i = 0; i < BITS_PER_LONG && tmptaint >> i; i++) {
2257 if ((tmptaint >> i) & 1)
2258 add_taint(i);
2259 }
2260 }
2261
2262 return err;
2274} 2263}
2275 2264
2276struct do_proc_dointvec_minmax_conv_param { 2265struct do_proc_dointvec_minmax_conv_param {