Root/
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->procname && !table->parent->procname) |
115 | set_fail(&fail, table, "Parent without procname"); |
116 | } |
117 | if (!table->procname) |
118 | set_fail(&fail, table, "No procname"); |
119 | if (table->child) { |
120 | if (table->data) |
121 | set_fail(&fail, table, "Directory with data?"); |
122 | if (table->maxlen) |
123 | set_fail(&fail, table, "Directory with maxlen?"); |
124 | if ((table->mode & (S_IRUGO|S_IXUGO)) != table->mode) |
125 | set_fail(&fail, table, "Writable sysctl directory"); |
126 | if (table->proc_handler) |
127 | set_fail(&fail, table, "Directory with proc_handler"); |
128 | if (table->extra1) |
129 | set_fail(&fail, table, "Directory with extra1"); |
130 | if (table->extra2) |
131 | set_fail(&fail, table, "Directory with extra2"); |
132 | } else { |
133 | if ((table->proc_handler == proc_dostring) || |
134 | (table->proc_handler == proc_dointvec) || |
135 | (table->proc_handler == proc_dointvec_minmax) || |
136 | (table->proc_handler == proc_dointvec_jiffies) || |
137 | (table->proc_handler == proc_dointvec_userhz_jiffies) || |
138 | (table->proc_handler == proc_dointvec_ms_jiffies) || |
139 | (table->proc_handler == proc_doulongvec_minmax) || |
140 | (table->proc_handler == proc_doulongvec_ms_jiffies_minmax)) { |
141 | if (!table->data) |
142 | set_fail(&fail, table, "No data"); |
143 | if (!table->maxlen) |
144 | set_fail(&fail, table, "No maxlen"); |
145 | } |
146 | #ifdef CONFIG_PROC_SYSCTL |
147 | if (table->procname && !table->proc_handler) |
148 | set_fail(&fail, table, "No proc_handler"); |
149 | #endif |
150 | #if 0 |
151 | if (!table->procname && table->proc_handler) |
152 | set_fail(&fail, table, "proc_handler without procname"); |
153 | #endif |
154 | sysctl_check_leaf(namespaces, table, &fail); |
155 | } |
156 | if (table->mode > 0777) |
157 | set_fail(&fail, table, "bogus .mode"); |
158 | if (fail) { |
159 | set_fail(&fail, table, NULL); |
160 | error = -EINVAL; |
161 | } |
162 | if (table->child) |
163 | error |= sysctl_check_table(namespaces, table->child); |
164 | } |
165 | return error; |
166 | } |
167 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9