diff options
Diffstat (limited to 'kernel/sysctl.c')
-rw-r--r-- | kernel/sysctl.c | 91 |
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 |
152 | static int proc_do_cad_pid(ctl_table *table, int write, struct file *filp, | 152 | static 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); |
154 | static 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 | ||
156 | static ctl_table root_table[]; | 158 | static ctl_table root_table[]; |
@@ -174,6 +176,7 @@ extern ctl_table inotify_table[]; | |||
174 | int sysctl_legacy_va_layout; | 176 | int sysctl_legacy_va_layout; |
175 | #endif | 177 | #endif |
176 | 178 | ||
179 | |||
177 | static void *get_uts(ctl_table *table, int write) | 180 | static 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 | ||
1931 | static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp, | 1945 | static 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 | */ | ||
1991 | static 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 | |||
1973 | struct do_proc_dointvec_minmax_conv_param { | 2004 | struct 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 | ||
2735 | static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen, | 2779 | static 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 | /* |