Blame view

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