aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sysctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sysctl.c')
-rw-r--r--kernel/sysctl.c91
1 files changed, 68 insertions, 23 deletions
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 600b33358ded..e0ac6cd79fcf 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -151,6 +151,8 @@ static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen,
151#ifdef CONFIG_PROC_SYSCTL 151#ifdef CONFIG_PROC_SYSCTL
152static int proc_do_cad_pid(ctl_table *table, int write, struct file *filp, 152static int proc_do_cad_pid(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);
154static int proc_dointvec_taint(ctl_table *table, int write, struct file *filp,
155 void __user *buffer, size_t *lenp, loff_t *ppos);
154#endif 156#endif
155 157
156static ctl_table root_table[]; 158static ctl_table root_table[];
@@ -174,6 +176,7 @@ extern ctl_table inotify_table[];
174int sysctl_legacy_va_layout; 176int sysctl_legacy_va_layout;
175#endif 177#endif
176 178
179
177static void *get_uts(ctl_table *table, int write) 180static void *get_uts(ctl_table *table, int write)
178{ 181{
179 char *which = table->data; 182 char *which = table->data;
@@ -344,14 +347,16 @@ static ctl_table kern_table[] = {
344 .proc_handler = &proc_dostring, 347 .proc_handler = &proc_dostring,
345 .strategy = &sysctl_string, 348 .strategy = &sysctl_string,
346 }, 349 },
350#ifdef CONFIG_PROC_SYSCTL
347 { 351 {
348 .ctl_name = KERN_TAINTED, 352 .ctl_name = KERN_TAINTED,
349 .procname = "tainted", 353 .procname = "tainted",
350 .data = &tainted, 354 .data = &tainted,
351 .maxlen = sizeof(int), 355 .maxlen = sizeof(int),
352 .mode = 0444, 356 .mode = 0644,
353 .proc_handler = &proc_dointvec, 357 .proc_handler = &proc_dointvec_taint,
354 }, 358 },
359#endif
355 { 360 {
356 .ctl_name = KERN_CAP_BSET, 361 .ctl_name = KERN_CAP_BSET,
357 .procname = "cap-bound", 362 .procname = "cap-bound",
@@ -1681,13 +1686,12 @@ static int _proc_do_string(void* data, int maxlen, int write,
1681 size_t len; 1686 size_t len;
1682 char __user *p; 1687 char __user *p;
1683 char c; 1688 char c;
1684 1689
1685 if (!data || !maxlen || !*lenp || 1690 if (!data || !maxlen || !*lenp) {
1686 (*ppos && !write)) {
1687 *lenp = 0; 1691 *lenp = 0;
1688 return 0; 1692 return 0;
1689 } 1693 }
1690 1694
1691 if (write) { 1695 if (write) {
1692 len = 0; 1696 len = 0;
1693 p = buffer; 1697 p = buffer;
@@ -1708,6 +1712,15 @@ static int _proc_do_string(void* data, int maxlen, int write,
1708 len = strlen(data); 1712 len = strlen(data);
1709 if (len > maxlen) 1713 if (len > maxlen)
1710 len = maxlen; 1714 len = maxlen;
1715
1716 if (*ppos > len) {
1717 *lenp = 0;
1718 return 0;
1719 }
1720
1721 data += *ppos;
1722 len -= *ppos;
1723
1711 if (len > *lenp) 1724 if (len > *lenp)
1712 len = *lenp; 1725 len = *lenp;
1713 if (len) 1726 if (len)
@@ -1927,6 +1940,7 @@ int proc_dointvec(ctl_table *table, int write, struct file *filp,
1927 1940
1928#define OP_SET 0 1941#define OP_SET 0
1929#define OP_AND 1 1942#define OP_AND 1
1943#define OP_OR 2
1930 1944
1931static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp, 1945static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp,
1932 int *valp, 1946 int *valp,
@@ -1938,6 +1952,7 @@ static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp,
1938 switch(op) { 1952 switch(op) {
1939 case OP_SET: *valp = val; break; 1953 case OP_SET: *valp = val; break;
1940 case OP_AND: *valp &= val; break; 1954 case OP_AND: *valp &= val; break;
1955 case OP_OR: *valp |= val; break;
1941 } 1956 }
1942 } else { 1957 } else {
1943 int val = *valp; 1958 int val = *valp;
@@ -1961,7 +1976,7 @@ int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
1961{ 1976{
1962 int op; 1977 int op;
1963 1978
1964 if (!capable(CAP_SYS_MODULE)) { 1979 if (write && !capable(CAP_SYS_MODULE)) {
1965 return -EPERM; 1980 return -EPERM;
1966 } 1981 }
1967 1982
@@ -1970,6 +1985,22 @@ int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
1970 do_proc_dointvec_bset_conv,&op); 1985 do_proc_dointvec_bset_conv,&op);
1971} 1986}
1972 1987
1988/*
1989 * Taint values can only be increased
1990 */
1991static int proc_dointvec_taint(ctl_table *table, int write, struct file *filp,
1992 void __user *buffer, size_t *lenp, loff_t *ppos)
1993{
1994 int op;
1995
1996 if (!capable(CAP_SYS_ADMIN))
1997 return -EPERM;
1998
1999 op = OP_OR;
2000 return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
2001 do_proc_dointvec_bset_conv,&op);
2002}
2003
1973struct do_proc_dointvec_minmax_conv_param { 2004struct do_proc_dointvec_minmax_conv_param {
1974 int *min; 2005 int *min;
1975 int *max; 2006 int *max;
@@ -2553,17 +2584,23 @@ int sysctl_jiffies(ctl_table *table, int __user *name, int nlen,
2553 void __user *oldval, size_t __user *oldlenp, 2584 void __user *oldval, size_t __user *oldlenp,
2554 void __user *newval, size_t newlen) 2585 void __user *newval, size_t newlen)
2555{ 2586{
2556 if (oldval) { 2587 if (oldval && oldlenp) {
2557 size_t olen; 2588 size_t olen;
2558 if (oldlenp) { 2589
2559 if (get_user(olen, oldlenp)) 2590 if (get_user(olen, oldlenp))
2591 return -EFAULT;
2592 if (olen) {
2593 int val;
2594
2595 if (olen < sizeof(int))
2596 return -EINVAL;
2597
2598 val = *(int *)(table->data) / HZ;
2599 if (put_user(val, (int __user *)oldval))
2600 return -EFAULT;
2601 if (put_user(sizeof(int), oldlenp))
2560 return -EFAULT; 2602 return -EFAULT;
2561 if (olen!=sizeof(int))
2562 return -EINVAL;
2563 } 2603 }
2564 if (put_user(*(int *)(table->data)/HZ, (int __user *)oldval) ||
2565 (oldlenp && put_user(sizeof(int),oldlenp)))
2566 return -EFAULT;
2567 } 2604 }
2568 if (newval && newlen) { 2605 if (newval && newlen) {
2569 int new; 2606 int new;
@@ -2581,17 +2618,23 @@ int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen,
2581 void __user *oldval, size_t __user *oldlenp, 2618 void __user *oldval, size_t __user *oldlenp,
2582 void __user *newval, size_t newlen) 2619 void __user *newval, size_t newlen)
2583{ 2620{
2584 if (oldval) { 2621 if (oldval && oldlenp) {
2585 size_t olen; 2622 size_t olen;
2586 if (oldlenp) { 2623
2587 if (get_user(olen, oldlenp)) 2624 if (get_user(olen, oldlenp))
2625 return -EFAULT;
2626 if (olen) {
2627 int val;
2628
2629 if (olen < sizeof(int))
2630 return -EINVAL;
2631
2632 val = jiffies_to_msecs(*(int *)(table->data));
2633 if (put_user(val, (int __user *)oldval))
2634 return -EFAULT;
2635 if (put_user(sizeof(int), oldlenp))
2588 return -EFAULT; 2636 return -EFAULT;
2589 if (olen!=sizeof(int))
2590 return -EINVAL;
2591 } 2637 }
2592 if (put_user(jiffies_to_msecs(*(int *)(table->data)), (int __user *)oldval) ||
2593 (oldlenp && put_user(sizeof(int),oldlenp)))
2594 return -EFAULT;
2595 } 2638 }
2596 if (newval && newlen) { 2639 if (newval && newlen) {
2597 int new; 2640 int new;
@@ -2732,12 +2775,14 @@ static int sysctl_uts_string(ctl_table *table, int __user *name, int nlen,
2732{ 2775{
2733 return -ENOSYS; 2776 return -ENOSYS;
2734} 2777}
2778#ifdef CONFIG_SYSVIPC
2735static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen, 2779static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen,
2736 void __user *oldval, size_t __user *oldlenp, 2780 void __user *oldval, size_t __user *oldlenp,
2737 void __user *newval, size_t newlen) 2781 void __user *newval, size_t newlen)
2738{ 2782{
2739 return -ENOSYS; 2783 return -ENOSYS;
2740} 2784}
2785#endif
2741#endif /* CONFIG_SYSCTL_SYSCALL */ 2786#endif /* CONFIG_SYSCTL_SYSCALL */
2742 2787
2743/* 2788/*