aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sysctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sysctl.c')
-rw-r--r--kernel/sysctl.c98
1 files changed, 43 insertions, 55 deletions
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index cfc5295f1e82..617d41e4d6a0 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
@@ -1282,6 +1281,7 @@ static struct ctl_table fs_table[] = {
1282 .extra2 = &two, 1281 .extra2 = &two,
1283 }, 1282 },
1284#endif 1283#endif
1284#ifdef CONFIG_AIO
1285 { 1285 {
1286 .procname = "aio-nr", 1286 .procname = "aio-nr",
1287 .data = &aio_nr, 1287 .data = &aio_nr,
@@ -1296,6 +1296,7 @@ static struct ctl_table fs_table[] = {
1296 .mode = 0644, 1296 .mode = 0644,
1297 .proc_handler = &proc_doulongvec_minmax, 1297 .proc_handler = &proc_doulongvec_minmax,
1298 }, 1298 },
1299#endif /* CONFIG_AIO */
1299#ifdef CONFIG_INOTIFY_USER 1300#ifdef CONFIG_INOTIFY_USER
1300 { 1301 {
1301 .ctl_name = FS_INOTIFY, 1302 .ctl_name = FS_INOTIFY,
@@ -1501,7 +1502,6 @@ void register_sysctl_root(struct ctl_table_root *root)
1501/* Perform the actual read/write of a sysctl table entry. */ 1502/* Perform the actual read/write of a sysctl table entry. */
1502static int do_sysctl_strategy(struct ctl_table_root *root, 1503static int do_sysctl_strategy(struct ctl_table_root *root,
1503 struct ctl_table *table, 1504 struct ctl_table *table,
1504 int __user *name, int nlen,
1505 void __user *oldval, size_t __user *oldlenp, 1505 void __user *oldval, size_t __user *oldlenp,
1506 void __user *newval, size_t newlen) 1506 void __user *newval, size_t newlen)
1507{ 1507{
@@ -1515,8 +1515,7 @@ static int do_sysctl_strategy(struct ctl_table_root *root,
1515 return -EPERM; 1515 return -EPERM;
1516 1516
1517 if (table->strategy) { 1517 if (table->strategy) {
1518 rc = table->strategy(table, name, nlen, oldval, oldlenp, 1518 rc = table->strategy(table, oldval, oldlenp, newval, newlen);
1519 newval, newlen);
1520 if (rc < 0) 1519 if (rc < 0)
1521 return rc; 1520 return rc;
1522 if (rc > 0) 1521 if (rc > 0)
@@ -1526,8 +1525,7 @@ static int do_sysctl_strategy(struct ctl_table_root *root,
1526 /* If there is no strategy routine, or if the strategy returns 1525 /* If there is no strategy routine, or if the strategy returns
1527 * zero, proceed with automatic r/w */ 1526 * zero, proceed with automatic r/w */
1528 if (table->data && table->maxlen) { 1527 if (table->data && table->maxlen) {
1529 rc = sysctl_data(table, name, nlen, oldval, oldlenp, 1528 rc = sysctl_data(table, oldval, oldlenp, newval, newlen);
1530 newval, newlen);
1531 if (rc < 0) 1529 if (rc < 0)
1532 return rc; 1530 return rc;
1533 } 1531 }
@@ -1559,7 +1557,7 @@ repeat:
1559 table = table->child; 1557 table = table->child;
1560 goto repeat; 1558 goto repeat;
1561 } 1559 }
1562 error = do_sysctl_strategy(root, table, name, nlen, 1560 error = do_sysctl_strategy(root, table,
1563 oldval, oldlenp, 1561 oldval, oldlenp,
1564 newval, newlen); 1562 newval, newlen);
1565 return error; 1563 return error;
@@ -2228,49 +2226,39 @@ int proc_dointvec(struct ctl_table *table, int write, struct file *filp,
2228 NULL,NULL); 2226 NULL,NULL);
2229} 2227}
2230 2228
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/* 2229/*
2261 * Taint values can only be increased 2230 * Taint values can only be increased
2231 * This means we can safely use a temporary.
2262 */ 2232 */
2263static int proc_dointvec_taint(struct ctl_table *table, int write, struct file *filp, 2233static int proc_taint(struct ctl_table *table, int write, struct file *filp,
2264 void __user *buffer, size_t *lenp, loff_t *ppos) 2234 void __user *buffer, size_t *lenp, loff_t *ppos)
2265{ 2235{
2266 int op; 2236 struct ctl_table t;
2237 unsigned long tmptaint = get_taint();
2238 int err;
2267 2239
2268 if (write && !capable(CAP_SYS_ADMIN)) 2240 if (write && !capable(CAP_SYS_ADMIN))
2269 return -EPERM; 2241 return -EPERM;
2270 2242
2271 op = OP_OR; 2243 t = *table;
2272 return do_proc_dointvec(table,write,filp,buffer,lenp,ppos, 2244 t.data = &tmptaint;
2273 do_proc_dointvec_bset_conv,&op); 2245 err = proc_doulongvec_minmax(&t, write, filp, buffer, lenp, ppos);
2246 if (err < 0)
2247 return err;
2248
2249 if (write) {
2250 /*
2251 * Poor man's atomic or. Not worth adding a primitive
2252 * to everyone's atomic.h for this
2253 */
2254 int i;
2255 for (i = 0; i < BITS_PER_LONG && tmptaint >> i; i++) {
2256 if ((tmptaint >> i) & 1)
2257 add_taint(i);
2258 }
2259 }
2260
2261 return err;
2274} 2262}
2275 2263
2276struct do_proc_dointvec_minmax_conv_param { 2264struct do_proc_dointvec_minmax_conv_param {
@@ -2718,7 +2706,7 @@ int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write,
2718 */ 2706 */
2719 2707
2720/* The generic sysctl data routine (used if no strategy routine supplied) */ 2708/* The generic sysctl data routine (used if no strategy routine supplied) */
2721int sysctl_data(struct ctl_table *table, int __user *name, int nlen, 2709int sysctl_data(struct ctl_table *table,
2722 void __user *oldval, size_t __user *oldlenp, 2710 void __user *oldval, size_t __user *oldlenp,
2723 void __user *newval, size_t newlen) 2711 void __user *newval, size_t newlen)
2724{ 2712{
@@ -2752,7 +2740,7 @@ int sysctl_data(struct ctl_table *table, int __user *name, int nlen,
2752} 2740}
2753 2741
2754/* The generic string strategy routine: */ 2742/* The generic string strategy routine: */
2755int sysctl_string(struct ctl_table *table, int __user *name, int nlen, 2743int sysctl_string(struct ctl_table *table,
2756 void __user *oldval, size_t __user *oldlenp, 2744 void __user *oldval, size_t __user *oldlenp,
2757 void __user *newval, size_t newlen) 2745 void __user *newval, size_t newlen)
2758{ 2746{
@@ -2798,7 +2786,7 @@ int sysctl_string(struct ctl_table *table, int __user *name, int nlen,
2798 * are between the minimum and maximum values given in the arrays 2786 * are between the minimum and maximum values given in the arrays
2799 * table->extra1 and table->extra2, respectively. 2787 * table->extra1 and table->extra2, respectively.
2800 */ 2788 */
2801int sysctl_intvec(struct ctl_table *table, int __user *name, int nlen, 2789int sysctl_intvec(struct ctl_table *table,
2802 void __user *oldval, size_t __user *oldlenp, 2790 void __user *oldval, size_t __user *oldlenp,
2803 void __user *newval, size_t newlen) 2791 void __user *newval, size_t newlen)
2804{ 2792{
@@ -2834,7 +2822,7 @@ int sysctl_intvec(struct ctl_table *table, int __user *name, int nlen,
2834} 2822}
2835 2823
2836/* Strategy function to convert jiffies to seconds */ 2824/* Strategy function to convert jiffies to seconds */
2837int sysctl_jiffies(struct ctl_table *table, int __user *name, int nlen, 2825int sysctl_jiffies(struct ctl_table *table,
2838 void __user *oldval, size_t __user *oldlenp, 2826 void __user *oldval, size_t __user *oldlenp,
2839 void __user *newval, size_t newlen) 2827 void __user *newval, size_t newlen)
2840{ 2828{
@@ -2868,7 +2856,7 @@ int sysctl_jiffies(struct ctl_table *table, int __user *name, int nlen,
2868} 2856}
2869 2857
2870/* Strategy function to convert jiffies to seconds */ 2858/* Strategy function to convert jiffies to seconds */
2871int sysctl_ms_jiffies(struct ctl_table *table, int __user *name, int nlen, 2859int sysctl_ms_jiffies(struct ctl_table *table,
2872 void __user *oldval, size_t __user *oldlenp, 2860 void __user *oldval, size_t __user *oldlenp,
2873 void __user *newval, size_t newlen) 2861 void __user *newval, size_t newlen)
2874{ 2862{
@@ -2923,35 +2911,35 @@ asmlinkage long sys_sysctl(struct __sysctl_args __user *args)
2923 return error; 2911 return error;
2924} 2912}
2925 2913
2926int sysctl_data(struct ctl_table *table, int __user *name, int nlen, 2914int sysctl_data(struct ctl_table *table,
2927 void __user *oldval, size_t __user *oldlenp, 2915 void __user *oldval, size_t __user *oldlenp,
2928 void __user *newval, size_t newlen) 2916 void __user *newval, size_t newlen)
2929{ 2917{
2930 return -ENOSYS; 2918 return -ENOSYS;
2931} 2919}
2932 2920
2933int sysctl_string(struct ctl_table *table, int __user *name, int nlen, 2921int sysctl_string(struct ctl_table *table,
2934 void __user *oldval, size_t __user *oldlenp, 2922 void __user *oldval, size_t __user *oldlenp,
2935 void __user *newval, size_t newlen) 2923 void __user *newval, size_t newlen)
2936{ 2924{
2937 return -ENOSYS; 2925 return -ENOSYS;
2938} 2926}
2939 2927
2940int sysctl_intvec(struct ctl_table *table, int __user *name, int nlen, 2928int sysctl_intvec(struct ctl_table *table,
2941 void __user *oldval, size_t __user *oldlenp, 2929 void __user *oldval, size_t __user *oldlenp,
2942 void __user *newval, size_t newlen) 2930 void __user *newval, size_t newlen)
2943{ 2931{
2944 return -ENOSYS; 2932 return -ENOSYS;
2945} 2933}
2946 2934
2947int sysctl_jiffies(struct ctl_table *table, int __user *name, int nlen, 2935int sysctl_jiffies(struct ctl_table *table,
2948 void __user *oldval, size_t __user *oldlenp, 2936 void __user *oldval, size_t __user *oldlenp,
2949 void __user *newval, size_t newlen) 2937 void __user *newval, size_t newlen)
2950{ 2938{
2951 return -ENOSYS; 2939 return -ENOSYS;
2952} 2940}
2953 2941
2954int sysctl_ms_jiffies(struct ctl_table *table, int __user *name, int nlen, 2942int sysctl_ms_jiffies(struct ctl_table *table,
2955 void __user *oldval, size_t __user *oldlenp, 2943 void __user *oldval, size_t __user *oldlenp,
2956 void __user *newval, size_t newlen) 2944 void __user *newval, size_t newlen)
2957{ 2945{