aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sysctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sysctl.c')
-rw-r--r--kernel/sysctl.c67
1 files changed, 28 insertions, 39 deletions
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 {