diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/module.c | 12 | ||||
-rw-r--r-- | kernel/panic.c | 63 | ||||
-rw-r--r-- | kernel/softlockup.c | 2 | ||||
-rw-r--r-- | kernel/sysctl.c | 67 |
4 files changed, 81 insertions, 63 deletions
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) | |||
100 | static inline void add_taint_module(struct module *mod, unsigned flag) | 100 | static 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; | |||
923 | static int try_to_force_load(struct module *mod, const char *symname) | 923 | static 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 | ||
25 | int panic_on_oops; | 25 | int panic_on_oops; |
26 | int tainted; | 26 | static unsigned long tainted_mask; |
27 | static int pause_on_oops; | 27 | static int pause_on_oops; |
28 | static int pause_on_oops_flag; | 28 | static int pause_on_oops_flag; |
29 | static DEFINE_SPINLOCK(pause_on_oops_lock); | 29 | static 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 | ||
162 | struct tnt { | ||
163 | u8 bit; | ||
164 | char true; | ||
165 | char false; | ||
166 | }; | ||
167 | |||
168 | static 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 | |||
162 | const char *print_tainted(void) | 181 | const 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 | ||
201 | int test_taint(unsigned flag) | ||
202 | { | ||
203 | return test_bit(flag, &tainted_mask); | ||
204 | } | ||
205 | EXPORT_SYMBOL(test_taint); | ||
206 | |||
207 | unsigned long get_taint(void) | ||
208 | { | ||
209 | return tainted_mask; | ||
210 | } | ||
211 | |||
183 | void add_taint(unsigned flag) | 212 | void 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 | } |
188 | EXPORT_SYMBOL(add_taint); | 217 | EXPORT_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 |
150 | static int proc_do_cad_pid(struct ctl_table *table, int write, struct file *filp, | 150 | static 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); |
152 | static int proc_dointvec_taint(struct ctl_table *table, int write, struct file *filp, | 152 | static 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 | |||
2235 | static 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 | */ |
2263 | static int proc_dointvec_taint(struct ctl_table *table, int write, struct file *filp, | 2234 | static 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 | ||
2276 | struct do_proc_dointvec_minmax_conv_param { | 2265 | struct do_proc_dointvec_minmax_conv_param { |