Linux Headquarters
[ Register ]
[ About us ] [ Home Page ]

[ Kernel ] [ Documentation ] [ Links ] [ Books ]

Kernel v2.6.26-rc1 /kernel/sysctl.c

Filename:/kernel/sysctl.c
Lines Added:99
Lines Deleted:92
Also changed in: (Previous) 2.6.25-git20  2.6.25-git19  2.6.25-git18  2.6.25-git17  2.6.25-git16  2.6.25-git15 
(Following) 2.6.26-rc2  2.6.26-rc3  2.6.26-rc3-git1  2.6.26-rc3-git2  2.6.26-rc3-git3  2.6.26-rc3-git4 

Location
[  2.6.26-rc1
  [  kernel
     o  sysctl.c

Patch

diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index b2a2d68..d7ffdc5 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -38,6 +38,7 @@
 #include <linux/writeback.h>
 #include <linux/hugetlb.h>
 #include <linux/initrd.h>
+#include <linux/key.h>
 #include <linux/times.h>
 #include <linux/limits.h>
 #include <linux/dcache.h>
@@ -144,12 +145,6 @@ extern int no_unaligned_warning;
 extern int max_lock_depth;
 #endif
 
-#ifdef CONFIG_SYSCTL_SYSCALL
-static int parse_table(int __user *, int, void __user *, size_t __user *,
-      void __user *, size_t, struct ctl_table *);
-#endif
-
-
 #ifdef CONFIG_PROC_SYSCTL
 static int proc_do_cad_pid(struct ctl_table *table, int write, struct file *filp,
         void __user *buffer, size_t *lenp, loff_t *ppos);
@@ -270,17 +265,6 @@ static struct ctl_table kern_table[] = {
    },
    {
       .ctl_name   = CTL_UNNUMBERED,
-      .procname   = "sched_batch_wakeup_granularity_ns",
-      .data      = &sysctl_sched_batch_wakeup_granularity,
-      .maxlen      = sizeof(unsigned int),
-      .mode      = 0644,
-      .proc_handler   = &proc_dointvec_minmax,
-      .strategy   = &sysctl_intvec,
-      .extra1      = &min_wakeup_granularity_ns,
-      .extra2      = &max_wakeup_granularity_ns,
-   },
-   {
-      .ctl_name   = CTL_UNNUMBERED,
       .procname   = "sched_child_runs_first",
       .data      = &sysctl_sched_child_runs_first,
       .maxlen      = sizeof(unsigned int),
@@ -318,7 +302,7 @@ static struct ctl_table kern_table[] = {
       .data      = &sysctl_sched_rt_period,
       .maxlen      = sizeof(unsigned int),
       .mode      = 0644,
-      .proc_handler   = &proc_dointvec,
+      .proc_handler   = &sched_rt_handler,
    },
    {
       .ctl_name   = CTL_UNNUMBERED,
@@ -326,7 +310,7 @@ static struct ctl_table kern_table[] = {
       .data      = &sysctl_sched_rt_runtime,
       .maxlen      = sizeof(int),
       .mode      = 0644,
-      .proc_handler   = &proc_dointvec,
+      .proc_handler   = &sched_rt_handler,
    },
    {
       .ctl_name   = CTL_UNNUMBERED,
@@ -820,6 +804,14 @@ static struct ctl_table kern_table[] = {
       .proc_handler   = &proc_dostring,
       .strategy   = &sysctl_string,
    },
+#ifdef CONFIG_KEYS
+   {
+      .ctl_name   = CTL_UNNUMBERED,
+      .procname   = "keys",
+      .mode      = 0555,
+      .child      = key_sysctls,
+   },
+#endif
 /*
  * NOTE: do not add new entries to this table unless you have read
  * Documentation/sysctl/ctl_unnumbered.txt
@@ -1441,6 +1433,76 @@ void register_sysctl_root(struct ctl_table_root *root)
 }
 
 #ifdef CONFIG_SYSCTL_SYSCALL
+/* Perform the actual read/write of a sysctl table entry. */
+static int do_sysctl_strategy(struct ctl_table_root *root,
+         struct ctl_table *table,
+         int __user *name, int nlen,
+         void __user *oldval, size_t __user *oldlenp,
+         void __user *newval, size_t newlen)
+{
+   int op = 0, rc;
+
+   if (oldval)
+      op |= 004;
+   if (newval)
+      op |= 002;
+   if (sysctl_perm(root, table, op))
+      return -EPERM;
+
+   if (table->strategy) {
+      rc = table->strategy(table, name, nlen, oldval, oldlenp,
+                 newval, newlen);
+      if (rc < 0)
+         return rc;
+      if (rc > 0)
+         return 0;
+   }
+
+   /* If there is no strategy routine, or if the strategy returns
+    * zero, proceed with automatic r/w */
+   if (table->data && table->maxlen) {
+      rc = sysctl_data(table, name, nlen, oldval, oldlenp,
+             newval, newlen);
+      if (rc < 0)
+         return rc;
+   }
+   return 0;
+}
+
+static int parse_table(int __user *name, int nlen,
+             void __user *oldval, size_t __user *oldlenp,
+             void __user *newval, size_t newlen,
+             struct ctl_table_root *root,
+             struct ctl_table *table)
+{
+   int n;
+repeat:
+   if (!nlen)
+      return -ENOTDIR;
+   if (get_user(n, name))
+      return -EFAULT;
+   for ( ; table->ctl_name || table->procname; table++) {
+      if (!table->ctl_name)
+         continue;
+      if (n == table->ctl_name) {
+         int error;
+         if (table->child) {
+            if (sysctl_perm(root, table, 001))
+               return -EPERM;
+            name++;
+            nlen--;
+            table = table->child;
+            goto repeat;
+         }
+         error = do_sysctl_strategy(root, table, name, nlen,
+                     oldval, oldlenp,
+                     newval, newlen);
+         return error;
+      }
+   }
+   return -ENOTDIR;
+}
+
 int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp,
           void __user *newval, size_t newlen)
 {
@@ -1458,7 +1520,8 @@ int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *ol
    for (head = sysctl_head_next(NULL); head;
          head = sysctl_head_next(head)) {
       error = parse_table(name, nlen, oldval, oldlenp, 
-               newval, newlen, head->ctl_table);
+               newval, newlen,
+               head->root, head->ctl_table);
       if (error != -ENOTDIR) {
          sysctl_head_finish(head);
          break;
@@ -1504,84 +1567,22 @@ static int test_perm(int mode, int op)
    return -EACCES;
 }
 
-int sysctl_perm(struct ctl_table *table, int op)
+int sysctl_perm(struct ctl_table_root *root, struct ctl_table *table, int op)
 {
    int error;
+   int mode;
+
    error = security_sysctl(table, op);
    if (error)
       return error;
-   return test_perm(table->mode, op);
-}
 
-#ifdef CONFIG_SYSCTL_SYSCALL
-static int parse_table(int __user *name, int nlen,
-             void __user *oldval, size_t __user *oldlenp,
-             void __user *newval, size_t newlen,
-             struct ctl_table *table)
-{
-   int n;
-repeat:
-   if (!nlen)
-      return -ENOTDIR;
-   if (get_user(n, name))
-      return -EFAULT;
-   for ( ; table->ctl_name || table->procname; table++) {
-      if (!table->ctl_name)
-         continue;
-      if (n == table->ctl_name) {
-         int error;
-         if (table->child) {
-            if (sysctl_perm(table, 001))
-               return -EPERM;
-            name++;
-            nlen--;
-            table = table->child;
-            goto repeat;
-         }
-         error = do_sysctl_strategy(table, name, nlen,
-                     oldval, oldlenp,
-                     newval, newlen);
-         return error;
-      }
-   }
-   return -ENOTDIR;
-}
-
-/* Perform the actual read/write of a sysctl table entry. */
-int do_sysctl_strategy (struct ctl_table *table,
-         int __user *name, int nlen,
-         void __user *oldval, size_t __user *oldlenp,
-         void __user *newval, size_t newlen)
-{
-   int op = 0, rc;
+   if (root->permissions)
+      mode = root->permissions(root, current->nsproxy, table);
+   else
+      mode = table->mode;
 
-   if (oldval)
-      op |= 004;
-   if (newval) 
-      op |= 002;
-   if (sysctl_perm(table, op))
-      return -EPERM;
-
-   if (table->strategy) {
-      rc = table->strategy(table, name, nlen, oldval, oldlenp,
-                 newval, newlen);
-      if (rc < 0)
-         return rc;
-      if (rc > 0)
-         return 0;
-   }
-
-   /* If there is no strategy routine, or if the strategy returns
-    * zero, proceed with automatic r/w */
-   if (table->data && table->maxlen) {
-      rc = sysctl_data(table, name, nlen, oldval, oldlenp,
-             newval, newlen);
-      if (rc < 0)
-         return rc;
-   }
-   return 0;
+   return test_perm(mode, op);
 }
-#endif /* CONFIG_SYSCTL_SYSCALL */
 
 static void sysctl_set_parent(struct ctl_table *parent, struct ctl_table *table)
 {
@@ -1594,9 +1595,13 @@ static void sysctl_set_parent(struct ctl_table *parent, struct ctl_table *table)
 
 static __init int sysctl_init(void)
 {
-   int err;
    sysctl_set_parent(NULL, root_table);
-   err = sysctl_check_table(current->nsproxy, root_table);
+#ifdef CONFIG_SYSCTL_SYSCALL_CHECK
+   {
+      int err;
+      err = sysctl_check_table(current->nsproxy, root_table);
+   }
+#endif
    return 0;
 }
 
@@ -1723,10 +1728,12 @@ struct ctl_table_header *__register_sysctl_paths(
    header->unregistering = NULL;
    header->root = root;
    sysctl_set_parent(NULL, header->ctl_table);
+#ifdef CONFIG_SYSCTL_SYSCALL_CHECK
    if (sysctl_check_table(namespaces, header->ctl_table)) {
       kfree(header);
       return NULL;
    }
+#endif
    spin_lock(&sysctl_lock);
    header_list = lookup_header_list(root, namespaces);
    list_add_tail(&header->ctl_entry, header_list);


Comments: webmaster (at) linuxhq.com.
Advertising: banners (at) linuxhq.com.
Compilation ©1998-2008 Linux Headquarters, Inc.