diff options
author | Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> | 2010-06-03 07:38:44 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2010-08-02 01:33:43 -0400 |
commit | 57c2590fb7fd38bd52708ff2716a577d0c2b3c5a (patch) | |
tree | 19db2e176e1e49d85482995249ba18aebbb8f7eb /security/tomoyo/common.c | |
parent | 1084307ca097745ed6e40a192329b133a49271ac (diff) |
TOMOYO: Update profile structure.
This patch allows users to change access control mode for per-operation basis.
This feature comes from non LSM version of TOMOYO which is designed for
permitting users to use SELinux and TOMOYO at the same time.
SELinux does not care filename in a directory whereas TOMOYO does. Change of
filename can change how the file is used. For example, renaming index.txt to
.htaccess will change how the file is used. Thus, letting SELinux to enforce
read()/write()/mmap() etc. restriction and letting TOMOYO to enforce rename()
restriction is an example usage of this feature.
What is unfortunate for me is that currently LSM does not allow users to use
SELinux and LSM version of TOMOYO at the same time...
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/tomoyo/common.c')
-rw-r--r-- | security/tomoyo/common.c | 431 |
1 files changed, 259 insertions, 172 deletions
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index bdf1ed7ca45b..811adb5e9fea 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c | |||
@@ -9,53 +9,74 @@ | |||
9 | #include <linux/uaccess.h> | 9 | #include <linux/uaccess.h> |
10 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
11 | #include <linux/security.h> | 11 | #include <linux/security.h> |
12 | #include <linux/hardirq.h> | ||
13 | #include "common.h" | 12 | #include "common.h" |
14 | 13 | ||
14 | static struct tomoyo_profile tomoyo_default_profile = { | ||
15 | .learning = &tomoyo_default_profile.preference, | ||
16 | .permissive = &tomoyo_default_profile.preference, | ||
17 | .enforcing = &tomoyo_default_profile.preference, | ||
18 | .preference.enforcing_verbose = true, | ||
19 | .preference.learning_max_entry = 2048, | ||
20 | .preference.learning_verbose = false, | ||
21 | .preference.permissive_verbose = true | ||
22 | }; | ||
23 | |||
24 | /* Profile version. Currently only 20090903 is defined. */ | ||
25 | static unsigned int tomoyo_profile_version; | ||
26 | |||
27 | /* Profile table. Memory is allocated as needed. */ | ||
28 | static struct tomoyo_profile *tomoyo_profile_ptr[TOMOYO_MAX_PROFILES]; | ||
29 | |||
15 | /* String table for functionality that takes 4 modes. */ | 30 | /* String table for functionality that takes 4 modes. */ |
16 | static const char *tomoyo_mode_4[4] = { | 31 | static const char *tomoyo_mode_4[4] = { |
17 | "disabled", "learning", "permissive", "enforcing" | 32 | "disabled", "learning", "permissive", "enforcing" |
18 | }; | 33 | }; |
19 | /* String table for functionality that takes 2 modes. */ | ||
20 | static const char *tomoyo_mode_2[4] = { | ||
21 | "disabled", "enabled", "enabled", "enabled" | ||
22 | }; | ||
23 | 34 | ||
24 | /* | 35 | /* String table for /sys/kernel/security/tomoyo/profile */ |
25 | * tomoyo_control_array is a static data which contains | 36 | static const char *tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX |
26 | * | 37 | + TOMOYO_MAX_MAC_CATEGORY_INDEX] = { |
27 | * (1) functionality name used by /sys/kernel/security/tomoyo/profile . | 38 | [TOMOYO_MAC_FILE_EXECUTE] = "file::execute", |
28 | * (2) initial values for "struct tomoyo_profile". | 39 | [TOMOYO_MAC_FILE_OPEN] = "file::open", |
29 | * (3) max values for "struct tomoyo_profile". | 40 | [TOMOYO_MAC_FILE_CREATE] = "file::create", |
30 | */ | 41 | [TOMOYO_MAC_FILE_UNLINK] = "file::unlink", |
31 | static struct { | 42 | [TOMOYO_MAC_FILE_MKDIR] = "file::mkdir", |
32 | const char *keyword; | 43 | [TOMOYO_MAC_FILE_RMDIR] = "file::rmdir", |
33 | unsigned int current_value; | 44 | [TOMOYO_MAC_FILE_MKFIFO] = "file::mkfifo", |
34 | const unsigned int max_value; | 45 | [TOMOYO_MAC_FILE_MKSOCK] = "file::mksock", |
35 | } tomoyo_control_array[TOMOYO_MAX_CONTROL_INDEX] = { | 46 | [TOMOYO_MAC_FILE_TRUNCATE] = "file::truncate", |
36 | [TOMOYO_MAC_FOR_FILE] = { "MAC_FOR_FILE", 0, 3 }, | 47 | [TOMOYO_MAC_FILE_SYMLINK] = "file::symlink", |
37 | [TOMOYO_MAX_ACCEPT_ENTRY] = { "MAX_ACCEPT_ENTRY", 2048, INT_MAX }, | 48 | [TOMOYO_MAC_FILE_REWRITE] = "file::rewrite", |
38 | [TOMOYO_VERBOSE] = { "TOMOYO_VERBOSE", 1, 1 }, | 49 | [TOMOYO_MAC_FILE_MKBLOCK] = "file::mkblock", |
50 | [TOMOYO_MAC_FILE_MKCHAR] = "file::mkchar", | ||
51 | [TOMOYO_MAC_FILE_LINK] = "file::link", | ||
52 | [TOMOYO_MAC_FILE_RENAME] = "file::rename", | ||
53 | [TOMOYO_MAC_FILE_CHMOD] = "file::chmod", | ||
54 | [TOMOYO_MAC_FILE_CHOWN] = "file::chown", | ||
55 | [TOMOYO_MAC_FILE_CHGRP] = "file::chgrp", | ||
56 | [TOMOYO_MAC_FILE_IOCTL] = "file::ioctl", | ||
57 | [TOMOYO_MAC_FILE_CHROOT] = "file::chroot", | ||
58 | [TOMOYO_MAC_FILE_MOUNT] = "file::mount", | ||
59 | [TOMOYO_MAC_FILE_UMOUNT] = "file::umount", | ||
60 | [TOMOYO_MAC_FILE_PIVOT_ROOT] = "file::pivot_root", | ||
61 | [TOMOYO_MAX_MAC_INDEX + TOMOYO_MAC_CATEGORY_FILE] = "file", | ||
39 | }; | 62 | }; |
40 | 63 | ||
41 | /* | ||
42 | * tomoyo_profile is a structure which is used for holding the mode of access | ||
43 | * controls. TOMOYO has 4 modes: disabled, learning, permissive, enforcing. | ||
44 | * An administrator can define up to 256 profiles. | ||
45 | * The ->profile of "struct tomoyo_domain_info" is used for remembering | ||
46 | * the profile's number (0 - 255) assigned to that domain. | ||
47 | */ | ||
48 | static struct tomoyo_profile { | ||
49 | unsigned int value[TOMOYO_MAX_CONTROL_INDEX]; | ||
50 | const struct tomoyo_path_info *comment; | ||
51 | } *tomoyo_profile_ptr[TOMOYO_MAX_PROFILES]; | ||
52 | |||
53 | /* Permit policy management by non-root user? */ | 64 | /* Permit policy management by non-root user? */ |
54 | static bool tomoyo_manage_by_non_root; | 65 | static bool tomoyo_manage_by_non_root; |
55 | 66 | ||
56 | /* Utility functions. */ | 67 | /* Utility functions. */ |
57 | 68 | ||
58 | /** | 69 | /** |
70 | * tomoyo_yesno - Return "yes" or "no". | ||
71 | * | ||
72 | * @value: Bool value. | ||
73 | */ | ||
74 | static const char *tomoyo_yesno(const unsigned int value) | ||
75 | { | ||
76 | return value ? "yes" : "no"; | ||
77 | } | ||
78 | |||
79 | /** | ||
59 | * tomoyo_print_name_union - Print a tomoyo_name_union. | 80 | * tomoyo_print_name_union - Print a tomoyo_name_union. |
60 | * | 81 | * |
61 | * @head: Pointer to "struct tomoyo_io_buffer". | 82 | * @head: Pointer to "struct tomoyo_io_buffer". |
@@ -154,80 +175,62 @@ bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) | |||
154 | } | 175 | } |
155 | 176 | ||
156 | /** | 177 | /** |
157 | * tomoyo_check_flags - Check mode for specified functionality. | ||
158 | * | ||
159 | * @domain: Pointer to "struct tomoyo_domain_info". | ||
160 | * @index: The functionality to check mode. | ||
161 | * | ||
162 | * TOMOYO checks only process context. | ||
163 | * This code disables TOMOYO's enforcement in case the function is called from | ||
164 | * interrupt context. | ||
165 | */ | ||
166 | unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, | ||
167 | const u8 index) | ||
168 | { | ||
169 | const u8 profile = domain->profile; | ||
170 | |||
171 | if (WARN_ON(in_interrupt())) | ||
172 | return 0; | ||
173 | return tomoyo_policy_loaded && index < TOMOYO_MAX_CONTROL_INDEX | ||
174 | #if TOMOYO_MAX_PROFILES != 256 | ||
175 | && profile < TOMOYO_MAX_PROFILES | ||
176 | #endif | ||
177 | && tomoyo_profile_ptr[profile] ? | ||
178 | tomoyo_profile_ptr[profile]->value[index] : 0; | ||
179 | } | ||
180 | |||
181 | /** | ||
182 | * tomoyo_verbose_mode - Check whether TOMOYO is verbose mode. | ||
183 | * | ||
184 | * @domain: Pointer to "struct tomoyo_domain_info". | ||
185 | * | ||
186 | * Returns true if domain policy violation warning should be printed to | ||
187 | * console. | ||
188 | */ | ||
189 | bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain) | ||
190 | { | ||
191 | return tomoyo_check_flags(domain, TOMOYO_VERBOSE) != 0; | ||
192 | } | ||
193 | |||
194 | /** | ||
195 | * tomoyo_find_or_assign_new_profile - Create a new profile. | 178 | * tomoyo_find_or_assign_new_profile - Create a new profile. |
196 | * | 179 | * |
197 | * @profile: Profile number to create. | 180 | * @profile: Profile number to create. |
198 | * | 181 | * |
199 | * Returns pointer to "struct tomoyo_profile" on success, NULL otherwise. | 182 | * Returns pointer to "struct tomoyo_profile" on success, NULL otherwise. |
200 | */ | 183 | */ |
201 | static struct tomoyo_profile *tomoyo_find_or_assign_new_profile(const unsigned | 184 | static struct tomoyo_profile *tomoyo_find_or_assign_new_profile |
202 | int profile) | 185 | (const unsigned int profile) |
203 | { | 186 | { |
204 | struct tomoyo_profile *ptr = NULL; | 187 | struct tomoyo_profile *ptr; |
205 | int i; | 188 | struct tomoyo_profile *entry; |
206 | |||
207 | if (profile >= TOMOYO_MAX_PROFILES) | 189 | if (profile >= TOMOYO_MAX_PROFILES) |
208 | return NULL; | 190 | return NULL; |
209 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | ||
210 | return NULL; | ||
211 | ptr = tomoyo_profile_ptr[profile]; | 191 | ptr = tomoyo_profile_ptr[profile]; |
212 | if (ptr) | 192 | if (ptr) |
213 | goto ok; | 193 | return ptr; |
214 | ptr = kmalloc(sizeof(*ptr), GFP_NOFS); | 194 | entry = kzalloc(sizeof(*entry), GFP_NOFS); |
215 | if (!tomoyo_memory_ok(ptr)) { | 195 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) |
216 | kfree(ptr); | 196 | goto out; |
217 | ptr = NULL; | 197 | ptr = tomoyo_profile_ptr[profile]; |
218 | goto ok; | 198 | if (!ptr && tomoyo_memory_ok(entry)) { |
199 | ptr = entry; | ||
200 | ptr->learning = &tomoyo_default_profile.preference; | ||
201 | ptr->permissive = &tomoyo_default_profile.preference; | ||
202 | ptr->enforcing = &tomoyo_default_profile.preference; | ||
203 | ptr->default_config = TOMOYO_CONFIG_DISABLED; | ||
204 | memset(ptr->config, TOMOYO_CONFIG_USE_DEFAULT, | ||
205 | sizeof(ptr->config)); | ||
206 | mb(); /* Avoid out-of-order execution. */ | ||
207 | tomoyo_profile_ptr[profile] = ptr; | ||
208 | entry = NULL; | ||
219 | } | 209 | } |
220 | for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) | ||
221 | ptr->value[i] = tomoyo_control_array[i].current_value; | ||
222 | mb(); /* Avoid out-of-order execution. */ | ||
223 | tomoyo_profile_ptr[profile] = ptr; | ||
224 | ok: | ||
225 | mutex_unlock(&tomoyo_policy_lock); | 210 | mutex_unlock(&tomoyo_policy_lock); |
211 | out: | ||
212 | kfree(entry); | ||
226 | return ptr; | 213 | return ptr; |
227 | } | 214 | } |
228 | 215 | ||
229 | /** | 216 | /** |
230 | * tomoyo_write_profile - Write to profile table. | 217 | * tomoyo_profile - Find a profile. |
218 | * | ||
219 | * @profile: Profile number to find. | ||
220 | * | ||
221 | * Returns pointer to "struct tomoyo_profile". | ||
222 | */ | ||
223 | struct tomoyo_profile *tomoyo_profile(const u8 profile) | ||
224 | { | ||
225 | struct tomoyo_profile *ptr = tomoyo_profile_ptr[profile]; | ||
226 | if (!tomoyo_policy_loaded) | ||
227 | return &tomoyo_default_profile; | ||
228 | BUG_ON(!ptr); | ||
229 | return ptr; | ||
230 | } | ||
231 | |||
232 | /** | ||
233 | * tomoyo_write_profile - Write profile table. | ||
231 | * | 234 | * |
232 | * @head: Pointer to "struct tomoyo_io_buffer". | 235 | * @head: Pointer to "struct tomoyo_io_buffer". |
233 | * | 236 | * |
@@ -237,64 +240,116 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head) | |||
237 | { | 240 | { |
238 | char *data = head->write_buf; | 241 | char *data = head->write_buf; |
239 | unsigned int i; | 242 | unsigned int i; |
240 | unsigned int value; | 243 | int value; |
244 | int mode; | ||
245 | u8 config; | ||
246 | bool use_default = false; | ||
241 | char *cp; | 247 | char *cp; |
242 | struct tomoyo_profile *profile; | 248 | struct tomoyo_profile *profile; |
243 | unsigned long num; | 249 | if (sscanf(data, "PROFILE_VERSION=%u", &tomoyo_profile_version) == 1) |
244 | 250 | return 0; | |
245 | cp = strchr(data, '-'); | 251 | i = simple_strtoul(data, &cp, 10); |
246 | if (cp) | 252 | if (data == cp) { |
247 | *cp = '\0'; | 253 | profile = &tomoyo_default_profile; |
248 | if (strict_strtoul(data, 10, &num)) | 254 | } else { |
249 | return -EINVAL; | 255 | if (*cp != '-') |
250 | if (cp) | 256 | return -EINVAL; |
251 | data = cp + 1; | 257 | data = cp + 1; |
252 | profile = tomoyo_find_or_assign_new_profile(num); | 258 | profile = tomoyo_find_or_assign_new_profile(i); |
253 | if (!profile) | 259 | if (!profile) |
254 | return -EINVAL; | 260 | return -EINVAL; |
261 | } | ||
255 | cp = strchr(data, '='); | 262 | cp = strchr(data, '='); |
256 | if (!cp) | 263 | if (!cp) |
257 | return -EINVAL; | 264 | return -EINVAL; |
258 | *cp = '\0'; | 265 | *cp++ = '\0'; |
266 | if (profile != &tomoyo_default_profile) | ||
267 | use_default = strstr(cp, "use_default") != NULL; | ||
268 | if (strstr(cp, "verbose=yes")) | ||
269 | value = 1; | ||
270 | else if (strstr(cp, "verbose=no")) | ||
271 | value = 0; | ||
272 | else | ||
273 | value = -1; | ||
274 | if (!strcmp(data, "PREFERENCE::enforcing")) { | ||
275 | if (use_default) { | ||
276 | profile->enforcing = &tomoyo_default_profile.preference; | ||
277 | return 0; | ||
278 | } | ||
279 | profile->enforcing = &profile->preference; | ||
280 | if (value >= 0) | ||
281 | profile->preference.enforcing_verbose = value; | ||
282 | return 0; | ||
283 | } | ||
284 | if (!strcmp(data, "PREFERENCE::permissive")) { | ||
285 | if (use_default) { | ||
286 | profile->permissive = &tomoyo_default_profile.preference; | ||
287 | return 0; | ||
288 | } | ||
289 | profile->permissive = &profile->preference; | ||
290 | if (value >= 0) | ||
291 | profile->preference.permissive_verbose = value; | ||
292 | return 0; | ||
293 | } | ||
294 | if (!strcmp(data, "PREFERENCE::learning")) { | ||
295 | char *cp2; | ||
296 | if (use_default) { | ||
297 | profile->learning = &tomoyo_default_profile.preference; | ||
298 | return 0; | ||
299 | } | ||
300 | profile->learning = &profile->preference; | ||
301 | if (value >= 0) | ||
302 | profile->preference.learning_verbose = value; | ||
303 | cp2 = strstr(cp, "max_entry="); | ||
304 | if (cp2) | ||
305 | sscanf(cp2 + 10, "%u", | ||
306 | &profile->preference.learning_max_entry); | ||
307 | return 0; | ||
308 | } | ||
309 | if (profile == &tomoyo_default_profile) | ||
310 | return -EINVAL; | ||
259 | if (!strcmp(data, "COMMENT")) { | 311 | if (!strcmp(data, "COMMENT")) { |
260 | const struct tomoyo_path_info *old_comment = profile->comment; | 312 | const struct tomoyo_path_info *old_comment = profile->comment; |
261 | profile->comment = tomoyo_get_name(cp + 1); | 313 | profile->comment = tomoyo_get_name(cp); |
262 | tomoyo_put_name(old_comment); | 314 | tomoyo_put_name(old_comment); |
263 | return 0; | 315 | return 0; |
264 | } | 316 | } |
265 | for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) { | 317 | if (!strcmp(data, "CONFIG")) { |
266 | if (strcmp(data, tomoyo_control_array[i].keyword)) | 318 | i = TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX; |
267 | continue; | 319 | config = profile->default_config; |
268 | if (sscanf(cp + 1, "%u", &value) != 1) { | 320 | } else if (tomoyo_str_starts(&data, "CONFIG::")) { |
269 | int j; | 321 | config = 0; |
270 | const char **modes; | 322 | for (i = 0; i < TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX; i++) { |
271 | switch (i) { | 323 | if (strcmp(data, tomoyo_mac_keywords[i])) |
272 | case TOMOYO_VERBOSE: | 324 | continue; |
273 | modes = tomoyo_mode_2; | 325 | config = profile->config[i]; |
274 | break; | 326 | break; |
275 | default: | ||
276 | modes = tomoyo_mode_4; | ||
277 | break; | ||
278 | } | ||
279 | for (j = 0; j < 4; j++) { | ||
280 | if (strcmp(cp + 1, modes[j])) | ||
281 | continue; | ||
282 | value = j; | ||
283 | break; | ||
284 | } | ||
285 | if (j == 4) | ||
286 | return -EINVAL; | ||
287 | } else if (value > tomoyo_control_array[i].max_value) { | ||
288 | value = tomoyo_control_array[i].max_value; | ||
289 | } | 327 | } |
290 | profile->value[i] = value; | 328 | if (i == TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX) |
291 | return 0; | 329 | return -EINVAL; |
330 | } else { | ||
331 | return -EINVAL; | ||
292 | } | 332 | } |
293 | return -EINVAL; | 333 | if (use_default) { |
334 | config = TOMOYO_CONFIG_USE_DEFAULT; | ||
335 | } else { | ||
336 | for (mode = 3; mode >= 0; mode--) | ||
337 | if (strstr(cp, tomoyo_mode_4[mode])) | ||
338 | /* | ||
339 | * Update lower 3 bits in order to distinguish | ||
340 | * 'config' from 'TOMOYO_CONFIG_USE_DEAFULT'. | ||
341 | */ | ||
342 | config = (config & ~7) | mode; | ||
343 | } | ||
344 | if (i < TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX) | ||
345 | profile->config[i] = config; | ||
346 | else if (config != TOMOYO_CONFIG_USE_DEFAULT) | ||
347 | profile->default_config = config; | ||
348 | return 0; | ||
294 | } | 349 | } |
295 | 350 | ||
296 | /** | 351 | /** |
297 | * tomoyo_read_profile - Read from profile table. | 352 | * tomoyo_read_profile - Read profile table. |
298 | * | 353 | * |
299 | * @head: Pointer to "struct tomoyo_io_buffer". | 354 | * @head: Pointer to "struct tomoyo_io_buffer". |
300 | * | 355 | * |
@@ -302,53 +357,82 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head) | |||
302 | */ | 357 | */ |
303 | static int tomoyo_read_profile(struct tomoyo_io_buffer *head) | 358 | static int tomoyo_read_profile(struct tomoyo_io_buffer *head) |
304 | { | 359 | { |
305 | static const int total = TOMOYO_MAX_CONTROL_INDEX + 1; | 360 | int index; |
306 | int step; | ||
307 | |||
308 | if (head->read_eof) | 361 | if (head->read_eof) |
309 | return 0; | 362 | return 0; |
310 | for (step = head->read_step; step < TOMOYO_MAX_PROFILES * total; | 363 | if (head->read_bit) |
311 | step++) { | 364 | goto body; |
312 | const u8 index = step / total; | 365 | tomoyo_io_printf(head, "PROFILE_VERSION=%s\n", "20090903"); |
313 | u8 type = step % total; | 366 | tomoyo_io_printf(head, "PREFERENCE::learning={ verbose=%s " |
367 | "max_entry=%u }\n", | ||
368 | tomoyo_yesno(tomoyo_default_profile.preference. | ||
369 | learning_verbose), | ||
370 | tomoyo_default_profile.preference.learning_max_entry); | ||
371 | tomoyo_io_printf(head, "PREFERENCE::permissive={ verbose=%s }\n", | ||
372 | tomoyo_yesno(tomoyo_default_profile.preference. | ||
373 | permissive_verbose)); | ||
374 | tomoyo_io_printf(head, "PREFERENCE::enforcing={ verbose=%s }\n", | ||
375 | tomoyo_yesno(tomoyo_default_profile.preference. | ||
376 | enforcing_verbose)); | ||
377 | head->read_bit = 1; | ||
378 | body: | ||
379 | for (index = head->read_step; index < TOMOYO_MAX_PROFILES; index++) { | ||
380 | bool done; | ||
381 | u8 config; | ||
382 | int i; | ||
383 | int pos; | ||
314 | const struct tomoyo_profile *profile | 384 | const struct tomoyo_profile *profile |
315 | = tomoyo_profile_ptr[index]; | 385 | = tomoyo_profile_ptr[index]; |
316 | head->read_step = step; | 386 | const struct tomoyo_path_info *comment; |
387 | head->read_step = index; | ||
317 | if (!profile) | 388 | if (!profile) |
318 | continue; | 389 | continue; |
319 | if (!type) { /* Print profile' comment tag. */ | 390 | pos = head->read_avail; |
320 | if (!tomoyo_io_printf(head, "%u-COMMENT=%s\n", | 391 | comment = profile->comment; |
321 | index, profile->comment ? | 392 | done = tomoyo_io_printf(head, "%u-COMMENT=%s\n", index, |
322 | profile->comment->name : "")) | 393 | comment ? comment->name : ""); |
323 | break; | 394 | if (!done) |
324 | continue; | 395 | goto out; |
325 | } | 396 | config = profile->default_config; |
326 | type--; | 397 | if (!tomoyo_io_printf(head, "%u-CONFIG={ mode=%s }\n", index, |
327 | if (type < TOMOYO_MAX_CONTROL_INDEX) { | 398 | tomoyo_mode_4[config & 3])) |
328 | const unsigned int value = profile->value[type]; | 399 | goto out; |
329 | const char **modes = NULL; | 400 | for (i = 0; i < TOMOYO_MAX_MAC_INDEX + |
330 | const char *keyword | 401 | TOMOYO_MAX_MAC_CATEGORY_INDEX; i++) { |
331 | = tomoyo_control_array[type].keyword; | 402 | config = profile->config[i]; |
332 | switch (tomoyo_control_array[type].max_value) { | 403 | if (config == TOMOYO_CONFIG_USE_DEFAULT) |
333 | case 3: | 404 | continue; |
334 | modes = tomoyo_mode_4; | 405 | if (!tomoyo_io_printf(head, |
335 | break; | 406 | "%u-CONFIG::%s={ mode=%s }\n", |
336 | case 1: | 407 | index, tomoyo_mac_keywords[i], |
337 | modes = tomoyo_mode_2; | 408 | tomoyo_mode_4[config & 3])) |
338 | break; | 409 | goto out; |
339 | } | ||
340 | if (modes) { | ||
341 | if (!tomoyo_io_printf(head, "%u-%s=%s\n", index, | ||
342 | keyword, modes[value])) | ||
343 | break; | ||
344 | } else { | ||
345 | if (!tomoyo_io_printf(head, "%u-%s=%u\n", index, | ||
346 | keyword, value)) | ||
347 | break; | ||
348 | } | ||
349 | } | 410 | } |
411 | if (profile->learning != &tomoyo_default_profile.preference && | ||
412 | !tomoyo_io_printf(head, "%u-PREFERENCE::learning={ " | ||
413 | "verbose=%s max_entry=%u }\n", index, | ||
414 | tomoyo_yesno(profile->preference. | ||
415 | learning_verbose), | ||
416 | profile->preference.learning_max_entry)) | ||
417 | goto out; | ||
418 | if (profile->permissive != &tomoyo_default_profile.preference | ||
419 | && !tomoyo_io_printf(head, "%u-PREFERENCE::permissive={ " | ||
420 | "verbose=%s }\n", index, | ||
421 | tomoyo_yesno(profile->preference. | ||
422 | permissive_verbose))) | ||
423 | goto out; | ||
424 | if (profile->enforcing != &tomoyo_default_profile.preference && | ||
425 | !tomoyo_io_printf(head, "%u-PREFERENCE::enforcing={ " | ||
426 | "verbose=%s }\n", index, | ||
427 | tomoyo_yesno(profile->preference. | ||
428 | enforcing_verbose))) | ||
429 | goto out; | ||
430 | continue; | ||
431 | out: | ||
432 | head->read_avail = pos; | ||
433 | break; | ||
350 | } | 434 | } |
351 | if (step == TOMOYO_MAX_PROFILES * total) | 435 | if (index == TOMOYO_MAX_PROFILES) |
352 | head->read_eof = true; | 436 | head->read_eof = true; |
353 | return 0; | 437 | return 0; |
354 | } | 438 | } |
@@ -1595,7 +1679,7 @@ static int tomoyo_write_answer(struct tomoyo_io_buffer *head) | |||
1595 | static int tomoyo_read_version(struct tomoyo_io_buffer *head) | 1679 | static int tomoyo_read_version(struct tomoyo_io_buffer *head) |
1596 | { | 1680 | { |
1597 | if (!head->read_eof) { | 1681 | if (!head->read_eof) { |
1598 | tomoyo_io_printf(head, "2.2.0"); | 1682 | tomoyo_io_printf(head, "2.3.0-pre"); |
1599 | head->read_eof = true; | 1683 | head->read_eof = true; |
1600 | } | 1684 | } |
1601 | return 0; | 1685 | return 0; |
@@ -1915,6 +1999,9 @@ void tomoyo_check_profile(void) | |||
1915 | profile, domain->domainname->name); | 1999 | profile, domain->domainname->name); |
1916 | } | 2000 | } |
1917 | tomoyo_read_unlock(idx); | 2001 | tomoyo_read_unlock(idx); |
1918 | printk(KERN_INFO "TOMOYO: 2.2.0 2009/04/01\n"); | 2002 | if (tomoyo_profile_version != 20090903) |
2003 | panic("Profile version %u is not supported.\n", | ||
2004 | tomoyo_profile_version); | ||
2005 | printk(KERN_INFO "TOMOYO: 2.3.0-pre 2010/06/03\n"); | ||
1919 | printk(KERN_INFO "Mandatory Access Control activated.\n"); | 2006 | printk(KERN_INFO "Mandatory Access Control activated.\n"); |
1920 | } | 2007 | } |