The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kernel/sysctl_check.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 #include <linux/stat.h>
    2 #include <linux/sysctl.h>
    3 #include "../fs/xfs/linux-2.6/xfs_sysctl.h"
    4 #include <linux/sunrpc/debug.h>
    5 #include <linux/string.h>
    6 #include <net/ip_vs.h>
    7 
    8 
    9 static int sysctl_depth(struct ctl_table *table)
   10 {
   11         struct ctl_table *tmp;
   12         int depth;
   13 
   14         depth = 0;
   15         for (tmp = table; tmp->parent; tmp = tmp->parent)
   16                 depth++;
   17 
   18         return depth;
   19 }
   20 
   21 static struct ctl_table *sysctl_parent(struct ctl_table *table, int n)
   22 {
   23         int i;
   24 
   25         for (i = 0; table && i < n; i++)
   26                 table = table->parent;
   27 
   28         return table;
   29 }
   30 
   31 
   32 static void sysctl_print_path(struct ctl_table *table)
   33 {
   34         struct ctl_table *tmp;
   35         int depth, i;
   36         depth = sysctl_depth(table);
   37         if (table->procname) {
   38                 for (i = depth; i >= 0; i--) {
   39                         tmp = sysctl_parent(table, i);
   40                         printk("/%s", tmp->procname?tmp->procname:"");
   41                 }
   42         }
   43         printk(" ");
   44 }
   45 
   46 static struct ctl_table *sysctl_check_lookup(struct nsproxy *namespaces,
   47                                                 struct ctl_table *table)
   48 {
   49         struct ctl_table_header *head;
   50         struct ctl_table *ref, *test;
   51         int depth, cur_depth;
   52 
   53         depth = sysctl_depth(table);
   54 
   55         for (head = __sysctl_head_next(namespaces, NULL); head;
   56              head = __sysctl_head_next(namespaces, head)) {
   57                 cur_depth = depth;
   58                 ref = head->ctl_table;
   59 repeat:
   60                 test = sysctl_parent(table, cur_depth);
   61                 for (; ref->procname; ref++) {
   62                         int match = 0;
   63                         if (cur_depth && !ref->child)
   64                                 continue;
   65 
   66                         if (test->procname && ref->procname &&
   67                             (strcmp(test->procname, ref->procname) == 0))
   68                                         match++;
   69 
   70                         if (match) {
   71                                 if (cur_depth != 0) {
   72                                         cur_depth--;
   73                                         ref = ref->child;
   74                                         goto repeat;
   75                                 }
   76                                 goto out;
   77                         }
   78                 }
   79         }
   80         ref = NULL;
   81 out:
   82         sysctl_head_finish(head);
   83         return ref;
   84 }
   85 
   86 static void set_fail(const char **fail, struct ctl_table *table, const char *str)
   87 {
   88         if (*fail) {
   89                 printk(KERN_ERR "sysctl table check failed: ");
   90                 sysctl_print_path(table);
   91                 printk(" %s\n", *fail);
   92                 dump_stack();
   93         }
   94         *fail = str;
   95 }
   96 
   97 static void sysctl_check_leaf(struct nsproxy *namespaces,
   98                                 struct ctl_table *table, const char **fail)
   99 {
  100         struct ctl_table *ref;
  101 
  102         ref = sysctl_check_lookup(namespaces, table);
  103         if (ref && (ref != table))
  104                 set_fail(fail, table, "Sysctl already exists");
  105 }
  106 
  107 int sysctl_check_table(struct nsproxy *namespaces, struct ctl_table *table)
  108 {
  109         int error = 0;
  110         for (; table->procname; table++) {
  111                 const char *fail = NULL;
  112 
  113                 if (table->parent) {
  114                         if (!table->parent->procname)
  115                                 set_fail(&fail, table, "Parent without procname");
  116                 }
  117                 if (table->child) {
  118                         if (table->data)
  119                                 set_fail(&fail, table, "Directory with data?");
  120                         if (table->maxlen)
  121                                 set_fail(&fail, table, "Directory with maxlen?");
  122                         if ((table->mode & (S_IRUGO|S_IXUGO)) != table->mode)
  123                                 set_fail(&fail, table, "Writable sysctl directory");
  124                         if (table->proc_handler)
  125                                 set_fail(&fail, table, "Directory with proc_handler");
  126                         if (table->extra1)
  127                                 set_fail(&fail, table, "Directory with extra1");
  128                         if (table->extra2)
  129                                 set_fail(&fail, table, "Directory with extra2");
  130                 } else {
  131                         if ((table->proc_handler == proc_dostring) ||
  132                             (table->proc_handler == proc_dointvec) ||
  133                             (table->proc_handler == proc_dointvec_minmax) ||
  134                             (table->proc_handler == proc_dointvec_jiffies) ||
  135                             (table->proc_handler == proc_dointvec_userhz_jiffies) ||
  136                             (table->proc_handler == proc_dointvec_ms_jiffies) ||
  137                             (table->proc_handler == proc_doulongvec_minmax) ||
  138                             (table->proc_handler == proc_doulongvec_ms_jiffies_minmax)) {
  139                                 if (!table->data)
  140                                         set_fail(&fail, table, "No data");
  141                                 if (!table->maxlen)
  142                                         set_fail(&fail, table, "No maxlen");
  143                         }
  144 #ifdef CONFIG_PROC_SYSCTL
  145                         if (!table->proc_handler)
  146                                 set_fail(&fail, table, "No proc_handler");
  147 #endif
  148                         sysctl_check_leaf(namespaces, table, &fail);
  149                 }
  150                 if (table->mode > 0777)
  151                         set_fail(&fail, table, "bogus .mode");
  152                 if (fail) {
  153                         set_fail(&fail, table, NULL);
  154                         error = -EINVAL;
  155                 }
  156                 if (table->child)
  157                         error |= sysctl_check_table(namespaces, table->child);
  158         }
  159         return error;
  160 }

Cache object: cfa00c2f2e5139a0bdb35c92a00b8901


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.