aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Dobriyan <adobriyan@openvz.org>2007-02-10 04:44:39 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-11 13:51:24 -0500
commit3ee75ac3c0f4904633322b7d9b111566fbc4a7d3 (patch)
tree2456021d63e95e92ce6bfae2e1f9d83c1843319d
parent8b6312f4dcc1efe7975731b6c47dd134282bd9ac (diff)
[PATCH] sysctl_{,ms_}jiffies: fix oldlen semantics
currently it's 1) if *oldlenp == 0, don't writeback anything 2) if *oldlenp >= table->maxlen, don't writeback more than table->maxlen bytes and rewrite *oldlenp don't look at underlying type granularity 3) if 0 < *oldlenp < table->maxlen, *cough* string sysctls don't writeback more than *oldlenp bytes. OK, that's because sizeof(char) == 1 int sysctls writeback anything in (0, table->maxlen] range Though accept integers divisible by sizeof(int) for writing. sysctl_jiffies and sysctl_ms_jiffies don't writeback anything but sizeof(int), which violates 1) and 2). So, make sysctl_jiffies and sysctl_ms_jiffies accept a) *oldlenp == 0, not doing writeback b) *oldlenp >= sizeof(int), writing one integer. -EINVAL still returned for *oldlenp == 1, 2, 3. Signed-off-by: Alexey Dobriyan <adobriyan@openvz.org> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--kernel/sysctl.c44
1 files changed, 28 insertions, 16 deletions
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 41bbba1a15da..16ef870fa75a 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -2553,17 +2553,23 @@ int sysctl_jiffies(ctl_table *table, int __user *name, int nlen,
2553 void __user *oldval, size_t __user *oldlenp, 2553 void __user *oldval, size_t __user *oldlenp,
2554 void __user *newval, size_t newlen) 2554 void __user *newval, size_t newlen)
2555{ 2555{
2556 if (oldval) { 2556 if (oldval && oldlenp) {
2557 size_t olen; 2557 size_t olen;
2558 if (oldlenp) { 2558
2559 if (get_user(olen, oldlenp)) 2559 if (get_user(olen, oldlenp))
2560 return -EFAULT;
2561 if (olen) {
2562 int val;
2563
2564 if (olen < sizeof(int))
2565 return -EINVAL;
2566
2567 val = *(int *)(table->data) / HZ;
2568 if (put_user(val, (int __user *)oldval))
2569 return -EFAULT;
2570 if (put_user(sizeof(int), oldlenp))
2560 return -EFAULT; 2571 return -EFAULT;
2561 if (olen!=sizeof(int))
2562 return -EINVAL;
2563 } 2572 }
2564 if (put_user(*(int *)(table->data)/HZ, (int __user *)oldval) ||
2565 (oldlenp && put_user(sizeof(int),oldlenp)))
2566 return -EFAULT;
2567 } 2573 }
2568 if (newval && newlen) { 2574 if (newval && newlen) {
2569 int new; 2575 int new;
@@ -2581,17 +2587,23 @@ int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen,
2581 void __user *oldval, size_t __user *oldlenp, 2587 void __user *oldval, size_t __user *oldlenp,
2582 void __user *newval, size_t newlen) 2588 void __user *newval, size_t newlen)
2583{ 2589{
2584 if (oldval) { 2590 if (oldval && oldlenp) {
2585 size_t olen; 2591 size_t olen;
2586 if (oldlenp) { 2592
2587 if (get_user(olen, oldlenp)) 2593 if (get_user(olen, oldlenp))
2594 return -EFAULT;
2595 if (olen) {
2596 int val;
2597
2598 if (olen < sizeof(int))
2599 return -EINVAL;
2600
2601 val = jiffies_to_msecs(*(int *)(table->data));
2602 if (put_user(val, (int __user *)oldval))
2603 return -EFAULT;
2604 if (put_user(sizeof(int), oldlenp))
2588 return -EFAULT; 2605 return -EFAULT;
2589 if (olen!=sizeof(int))
2590 return -EINVAL;
2591 } 2606 }
2592 if (put_user(jiffies_to_msecs(*(int *)(table->data)), (int __user *)oldval) ||
2593 (oldlenp && put_user(sizeof(int),oldlenp)))
2594 return -EFAULT;
2595 } 2607 }
2596 if (newval && newlen) { 2608 if (newval && newlen) {
2597 int new; 2609 int new;