From 61eeaf511b19621324fea5e74b6bddfb26c82732 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 18 Oct 2007 03:05:23 -0700 Subject: [PATCH] --- yaml --- r: 71144 b: refs/heads/master c: 49a0c45833c9aa9852ba02c9df0f18029509d0a9 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/include/linux/sysctl.h | 1 + trunk/kernel/sysctl.c | 66 +++++++++++++++++++++++++----------- 3 files changed, 48 insertions(+), 21 deletions(-) diff --git a/[refs] b/[refs] index b6a4069b9964..1eb2ed832cd1 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: d8217f076b73441dd3869c0c880df000655084cc +refs/heads/master: 49a0c45833c9aa9852ba02c9df0f18029509d0a9 diff --git a/trunk/include/linux/sysctl.h b/trunk/include/linux/sysctl.h index f73be4cd662e..5ca510b3cbe2 100644 --- a/trunk/include/linux/sysctl.h +++ b/trunk/include/linux/sysctl.h @@ -972,6 +972,7 @@ extern int do_sysctl_strategy (struct ctl_table *table, void __user *oldval, size_t __user *oldlenp, void __user *newval, size_t newlen); +extern ctl_handler sysctl_data; extern ctl_handler sysctl_string; extern ctl_handler sysctl_intvec; extern ctl_handler sysctl_jiffies; diff --git a/trunk/kernel/sysctl.c b/trunk/kernel/sysctl.c index 73c84b6e7a35..88c8ea8f5e8c 100644 --- a/trunk/kernel/sysctl.c +++ b/trunk/kernel/sysctl.c @@ -1443,7 +1443,6 @@ int do_sysctl_strategy (struct ctl_table *table, void __user *newval, size_t newlen) { int op = 0, rc; - size_t len; if (oldval) op |= 004; @@ -1464,25 +1463,10 @@ int do_sysctl_strategy (struct ctl_table *table, /* If there is no strategy routine, or if the strategy returns * zero, proceed with automatic r/w */ if (table->data && table->maxlen) { - if (oldval && oldlenp) { - if (get_user(len, oldlenp)) - return -EFAULT; - if (len) { - if (len > table->maxlen) - len = table->maxlen; - if(copy_to_user(oldval, table->data, len)) - return -EFAULT; - if(put_user(len, oldlenp)) - return -EFAULT; - } - } - if (newval && newlen) { - len = newlen; - if (len > table->maxlen) - len = table->maxlen; - if(copy_from_user(table->data, newval, len)) - return -EFAULT; - } + rc = sysctl_data(table, name, nlen, oldval, oldlenp, + newval, newlen); + if (rc < 0) + return rc; } return 0; } @@ -2381,6 +2365,40 @@ int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write, * General sysctl support routines */ +/* The generic sysctl data routine (used if no strategy routine supplied) */ +int sysctl_data(struct ctl_table *table, int __user *name, int nlen, + void __user *oldval, size_t __user *oldlenp, + void __user *newval, size_t newlen) +{ + size_t len; + + /* Get out of I don't have a variable */ + if (!table->data || !table->maxlen) + return -ENOTDIR; + + if (oldval && oldlenp) { + if (get_user(len, oldlenp)) + return -EFAULT; + if (len) { + if (len > table->maxlen) + len = table->maxlen; + if (copy_to_user(oldval, table->data, len)) + return -EFAULT; + if (put_user(len, oldlenp)) + return -EFAULT; + } + } + + if (newval && newlen) { + if (newlen > table->maxlen) + newlen = table->maxlen; + + if (copy_from_user(table->data, newval, newlen)) + return -EFAULT; + } + return 1; +} + /* The generic string strategy routine: */ int sysctl_string(struct ctl_table *table, int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp, @@ -2569,6 +2587,13 @@ asmlinkage long sys_sysctl(struct __sysctl_args __user *args) return -ENOSYS; } +int sysctl_data(struct ctl_table *table, int __user *name, int nlen, + void __user *oldval, size_t __user *oldlenp, + void __user *newval, size_t newlen) +{ + return -ENOSYS; +} + int sysctl_string(struct ctl_table *table, int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp, void __user *newval, size_t newlen) @@ -2616,4 +2641,5 @@ EXPORT_SYMBOL(sysctl_intvec); EXPORT_SYMBOL(sysctl_jiffies); EXPORT_SYMBOL(sysctl_ms_jiffies); EXPORT_SYMBOL(sysctl_string); +EXPORT_SYMBOL(sysctl_data); EXPORT_SYMBOL(unregister_sysctl_table);