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>
9 static int sysctl_depth(struct ctl_table
*table
)
11 struct ctl_table
*tmp
;
15 for (tmp
= table
; tmp
->parent
; tmp
= tmp
->parent
)
21 static struct ctl_table
*sysctl_parent(struct ctl_table
*table
, int n
)
25 for (i
= 0; table
&& i
< n
; i
++)
26 table
= table
->parent
;
32 static void sysctl_print_path(struct ctl_table
*table
)
34 struct ctl_table
*tmp
;
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
:"");
46 static struct ctl_table
*sysctl_check_lookup(struct nsproxy
*namespaces
,
47 struct ctl_table
*table
)
49 struct ctl_table_header
*head
;
50 struct ctl_table
*ref
, *test
;
53 depth
= sysctl_depth(table
);
55 for (head
= __sysctl_head_next(namespaces
, NULL
); head
;
56 head
= __sysctl_head_next(namespaces
, head
)) {
58 ref
= head
->ctl_table
;
60 test
= sysctl_parent(table
, cur_depth
);
61 for (; ref
->procname
; ref
++) {
63 if (cur_depth
&& !ref
->child
)
66 if (test
->procname
&& ref
->procname
&&
67 (strcmp(test
->procname
, ref
->procname
) == 0))
82 sysctl_head_finish(head
);
86 static void set_fail(const char **fail
, struct ctl_table
*table
, const char *str
)
89 printk(KERN_ERR
"sysctl table check failed: ");
90 sysctl_print_path(table
);
91 printk(" %s\n", *fail
);
97 static void sysctl_check_leaf(struct nsproxy
*namespaces
,
98 struct ctl_table
*table
, const char **fail
)
100 struct ctl_table
*ref
;
102 ref
= sysctl_check_lookup(namespaces
, table
);
103 if (ref
&& (ref
!= table
))
104 set_fail(fail
, table
, "Sysctl already exists");
107 int sysctl_check_table(struct nsproxy
*namespaces
, struct ctl_table
*table
)
110 for (; table
->procname
; table
++) {
111 const char *fail
= NULL
;
114 if (!table
->parent
->procname
)
115 set_fail(&fail
, table
, "Parent without procname");
119 set_fail(&fail
, table
, "Directory with data?");
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");
127 set_fail(&fail
, table
, "Directory with extra1");
129 set_fail(&fail
, table
, "Directory with extra2");
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
)) {
140 set_fail(&fail
, table
, "No data");
142 set_fail(&fail
, table
, "No maxlen");
144 #ifdef CONFIG_PROC_SYSCTL
145 if (!table
->proc_handler
)
146 set_fail(&fail
, table
, "No proc_handler");
148 sysctl_check_leaf(namespaces
, table
, &fail
);
150 if (table
->mode
> 0777)
151 set_fail(&fail
, table
, "bogus .mode");
153 set_fail(&fail
, table
, NULL
);
157 error
|= sysctl_check_table(namespaces
, table
->child
);