|
@@ -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 @@ out:
|
|
|
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);
|