diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/tomoyo/common.c | 431 | ||||
-rw-r--r-- | security/tomoyo/common.h | 68 | ||||
-rw-r--r-- | security/tomoyo/domain.c | 9 | ||||
-rw-r--r-- | security/tomoyo/file.c | 131 | ||||
-rw-r--r-- | security/tomoyo/mount.c | 3 | ||||
-rw-r--r-- | security/tomoyo/util.c | 92 |
6 files changed, 486 insertions, 248 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 | } |
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 54db39aa339b..c777c594a00b 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h | |||
@@ -42,7 +42,8 @@ enum tomoyo_mode_index { | |||
42 | TOMOYO_CONFIG_DISABLED, | 42 | TOMOYO_CONFIG_DISABLED, |
43 | TOMOYO_CONFIG_LEARNING, | 43 | TOMOYO_CONFIG_LEARNING, |
44 | TOMOYO_CONFIG_PERMISSIVE, | 44 | TOMOYO_CONFIG_PERMISSIVE, |
45 | TOMOYO_CONFIG_ENFORCING | 45 | TOMOYO_CONFIG_ENFORCING, |
46 | TOMOYO_CONFIG_USE_DEFAULT = 255 | ||
46 | }; | 47 | }; |
47 | 48 | ||
48 | /* Keywords for ACLs. */ | 49 | /* Keywords for ACLs. */ |
@@ -75,14 +76,6 @@ enum tomoyo_mode_index { | |||
75 | #define TOMOYO_VALUE_TYPE_HEXADECIMAL 3 | 76 | #define TOMOYO_VALUE_TYPE_HEXADECIMAL 3 |
76 | 77 | ||
77 | /* Index numbers for Access Controls. */ | 78 | /* Index numbers for Access Controls. */ |
78 | enum tomoyo_mac_index { | ||
79 | TOMOYO_MAC_FOR_FILE, /* domain_policy.conf */ | ||
80 | TOMOYO_MAX_ACCEPT_ENTRY, | ||
81 | TOMOYO_VERBOSE, | ||
82 | TOMOYO_MAX_CONTROL_INDEX | ||
83 | }; | ||
84 | |||
85 | /* Index numbers for Access Controls. */ | ||
86 | enum tomoyo_acl_entry_type_index { | 79 | enum tomoyo_acl_entry_type_index { |
87 | TOMOYO_TYPE_PATH_ACL, | 80 | TOMOYO_TYPE_PATH_ACL, |
88 | TOMOYO_TYPE_PATH2_ACL, | 81 | TOMOYO_TYPE_PATH2_ACL, |
@@ -157,6 +150,38 @@ enum tomoyo_securityfs_interface_index { | |||
157 | TOMOYO_MANAGER | 150 | TOMOYO_MANAGER |
158 | }; | 151 | }; |
159 | 152 | ||
153 | enum tomoyo_mac_index { | ||
154 | TOMOYO_MAC_FILE_EXECUTE, | ||
155 | TOMOYO_MAC_FILE_OPEN, | ||
156 | TOMOYO_MAC_FILE_CREATE, | ||
157 | TOMOYO_MAC_FILE_UNLINK, | ||
158 | TOMOYO_MAC_FILE_MKDIR, | ||
159 | TOMOYO_MAC_FILE_RMDIR, | ||
160 | TOMOYO_MAC_FILE_MKFIFO, | ||
161 | TOMOYO_MAC_FILE_MKSOCK, | ||
162 | TOMOYO_MAC_FILE_TRUNCATE, | ||
163 | TOMOYO_MAC_FILE_SYMLINK, | ||
164 | TOMOYO_MAC_FILE_REWRITE, | ||
165 | TOMOYO_MAC_FILE_MKBLOCK, | ||
166 | TOMOYO_MAC_FILE_MKCHAR, | ||
167 | TOMOYO_MAC_FILE_LINK, | ||
168 | TOMOYO_MAC_FILE_RENAME, | ||
169 | TOMOYO_MAC_FILE_CHMOD, | ||
170 | TOMOYO_MAC_FILE_CHOWN, | ||
171 | TOMOYO_MAC_FILE_CHGRP, | ||
172 | TOMOYO_MAC_FILE_IOCTL, | ||
173 | TOMOYO_MAC_FILE_CHROOT, | ||
174 | TOMOYO_MAC_FILE_MOUNT, | ||
175 | TOMOYO_MAC_FILE_UMOUNT, | ||
176 | TOMOYO_MAC_FILE_PIVOT_ROOT, | ||
177 | TOMOYO_MAX_MAC_INDEX | ||
178 | }; | ||
179 | |||
180 | enum tomoyo_mac_category_index { | ||
181 | TOMOYO_MAC_CATEGORY_FILE, | ||
182 | TOMOYO_MAX_MAC_CATEGORY_INDEX | ||
183 | }; | ||
184 | |||
160 | #define TOMOYO_RETRY_REQUEST 1 /* Retry this request. */ | 185 | #define TOMOYO_RETRY_REQUEST 1 /* Retry this request. */ |
161 | 186 | ||
162 | /********** Structure definitions. **********/ | 187 | /********** Structure definitions. **********/ |
@@ -174,6 +199,7 @@ struct tomoyo_request_info { | |||
174 | u8 retry; | 199 | u8 retry; |
175 | u8 profile; | 200 | u8 profile; |
176 | u8 mode; /* One of tomoyo_mode_index . */ | 201 | u8 mode; /* One of tomoyo_mode_index . */ |
202 | u8 type; | ||
177 | }; | 203 | }; |
178 | 204 | ||
179 | /* | 205 | /* |
@@ -649,6 +675,23 @@ struct tomoyo_policy_manager_entry { | |||
649 | bool is_deleted; /* True if this entry is deleted. */ | 675 | bool is_deleted; /* True if this entry is deleted. */ |
650 | }; | 676 | }; |
651 | 677 | ||
678 | struct tomoyo_preference { | ||
679 | unsigned int learning_max_entry; | ||
680 | bool enforcing_verbose; | ||
681 | bool learning_verbose; | ||
682 | bool permissive_verbose; | ||
683 | }; | ||
684 | |||
685 | struct tomoyo_profile { | ||
686 | const struct tomoyo_path_info *comment; | ||
687 | struct tomoyo_preference *learning; | ||
688 | struct tomoyo_preference *permissive; | ||
689 | struct tomoyo_preference *enforcing; | ||
690 | struct tomoyo_preference preference; | ||
691 | u8 default_config; | ||
692 | u8 config[TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX]; | ||
693 | }; | ||
694 | |||
652 | /********** Function prototypes. **********/ | 695 | /********** Function prototypes. **********/ |
653 | 696 | ||
654 | extern asmlinkage long sys_getpid(void); | 697 | extern asmlinkage long sys_getpid(void); |
@@ -685,6 +728,7 @@ bool tomoyo_compare_name_union(const struct tomoyo_path_info *name, | |||
685 | /* Check whether the given number matches the given number_union. */ | 728 | /* Check whether the given number matches the given number_union. */ |
686 | bool tomoyo_compare_number_union(const unsigned long value, | 729 | bool tomoyo_compare_number_union(const unsigned long value, |
687 | const struct tomoyo_number_union *ptr); | 730 | const struct tomoyo_number_union *ptr); |
731 | int tomoyo_get_mode(const u8 profile, const u8 index); | ||
688 | /* Transactional sprintf() for policy dump. */ | 732 | /* Transactional sprintf() for policy dump. */ |
689 | bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) | 733 | bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) |
690 | __attribute__ ((format(printf, 2, 3))); | 734 | __attribute__ ((format(printf, 2, 3))); |
@@ -747,7 +791,8 @@ const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain); | |||
747 | const char *tomoyo_path2keyword(const u8 operation); | 791 | const char *tomoyo_path2keyword(const u8 operation); |
748 | /* Fill "struct tomoyo_request_info". */ | 792 | /* Fill "struct tomoyo_request_info". */ |
749 | int tomoyo_init_request_info(struct tomoyo_request_info *r, | 793 | int tomoyo_init_request_info(struct tomoyo_request_info *r, |
750 | struct tomoyo_domain_info *domain); | 794 | struct tomoyo_domain_info *domain, |
795 | const u8 index); | ||
751 | /* Check permission for mount operation. */ | 796 | /* Check permission for mount operation. */ |
752 | int tomoyo_mount_permission(char *dev_name, struct path *path, char *type, | 797 | int tomoyo_mount_permission(char *dev_name, struct path *path, char *type, |
753 | unsigned long flags, void *data_page); | 798 | unsigned long flags, void *data_page); |
@@ -794,6 +839,7 @@ struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname); | |||
794 | struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * | 839 | struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * |
795 | domainname, | 840 | domainname, |
796 | const u8 profile); | 841 | const u8 profile); |
842 | struct tomoyo_profile *tomoyo_profile(const u8 profile); | ||
797 | /* Allocate memory for "struct tomoyo_path_group". */ | 843 | /* Allocate memory for "struct tomoyo_path_group". */ |
798 | struct tomoyo_path_group *tomoyo_get_path_group(const char *group_name); | 844 | struct tomoyo_path_group *tomoyo_get_path_group(const char *group_name); |
799 | struct tomoyo_number_group *tomoyo_get_number_group(const char *group_name); | 845 | struct tomoyo_number_group *tomoyo_get_number_group(const char *group_name); |
@@ -844,7 +890,7 @@ int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head); | |||
844 | 890 | ||
845 | /* Initialize mm related code. */ | 891 | /* Initialize mm related code. */ |
846 | void __init tomoyo_mm_init(void); | 892 | void __init tomoyo_mm_init(void); |
847 | int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, | 893 | int tomoyo_check_exec_perm(struct tomoyo_request_info *r, |
848 | const struct tomoyo_path_info *filename); | 894 | const struct tomoyo_path_info *filename); |
849 | int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | 895 | int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, |
850 | struct path *path, const int flag); | 896 | struct path *path, const int flag); |
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index a07ca6dc1a08..09ec37c12a9c 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c | |||
@@ -812,8 +812,8 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) | |||
812 | struct tomoyo_domain_info *domain = NULL; | 812 | struct tomoyo_domain_info *domain = NULL; |
813 | const char *old_domain_name = old_domain->domainname->name; | 813 | const char *old_domain_name = old_domain->domainname->name; |
814 | const char *original_name = bprm->filename; | 814 | const char *original_name = bprm->filename; |
815 | const u8 mode = tomoyo_check_flags(old_domain, TOMOYO_MAC_FOR_FILE); | 815 | u8 mode; |
816 | const bool is_enforce = (mode == TOMOYO_CONFIG_ENFORCING); | 816 | bool is_enforce; |
817 | int retval = -ENOMEM; | 817 | int retval = -ENOMEM; |
818 | bool need_kfree = false; | 818 | bool need_kfree = false; |
819 | struct tomoyo_path_info rn = { }; /* real name */ | 819 | struct tomoyo_path_info rn = { }; /* real name */ |
@@ -822,7 +822,8 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) | |||
822 | 822 | ||
823 | ln.name = tomoyo_get_last_name(old_domain); | 823 | ln.name = tomoyo_get_last_name(old_domain); |
824 | tomoyo_fill_path_info(&ln); | 824 | tomoyo_fill_path_info(&ln); |
825 | tomoyo_init_request_info(&r, NULL); | 825 | mode = tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_EXECUTE); |
826 | is_enforce = (mode == TOMOYO_CONFIG_ENFORCING); | ||
826 | if (!tmp) | 827 | if (!tmp) |
827 | goto out; | 828 | goto out; |
828 | 829 | ||
@@ -880,7 +881,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) | |||
880 | } | 881 | } |
881 | 882 | ||
882 | /* Check execute permission. */ | 883 | /* Check execute permission. */ |
883 | retval = tomoyo_check_exec_perm(old_domain, &rn); | 884 | retval = tomoyo_check_exec_perm(&r, &rn); |
884 | if (retval == TOMOYO_RETRY_REQUEST) | 885 | if (retval == TOMOYO_RETRY_REQUEST) |
885 | goto retry; | 886 | goto retry; |
886 | if (retval < 0) | 887 | if (retval < 0) |
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 83fa17a1113a..8e51348d022e 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c | |||
@@ -51,6 +51,42 @@ static const char *tomoyo_path_number_keyword | |||
51 | [TOMOYO_TYPE_CHGRP] = "chgrp", | 51 | [TOMOYO_TYPE_CHGRP] = "chgrp", |
52 | }; | 52 | }; |
53 | 53 | ||
54 | static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = { | ||
55 | [TOMOYO_TYPE_READ_WRITE] = TOMOYO_MAC_FILE_OPEN, | ||
56 | [TOMOYO_TYPE_EXECUTE] = TOMOYO_MAC_FILE_EXECUTE, | ||
57 | [TOMOYO_TYPE_READ] = TOMOYO_MAC_FILE_OPEN, | ||
58 | [TOMOYO_TYPE_WRITE] = TOMOYO_MAC_FILE_OPEN, | ||
59 | [TOMOYO_TYPE_UNLINK] = TOMOYO_MAC_FILE_UNLINK, | ||
60 | [TOMOYO_TYPE_RMDIR] = TOMOYO_MAC_FILE_RMDIR, | ||
61 | [TOMOYO_TYPE_TRUNCATE] = TOMOYO_MAC_FILE_TRUNCATE, | ||
62 | [TOMOYO_TYPE_SYMLINK] = TOMOYO_MAC_FILE_SYMLINK, | ||
63 | [TOMOYO_TYPE_REWRITE] = TOMOYO_MAC_FILE_REWRITE, | ||
64 | [TOMOYO_TYPE_CHROOT] = TOMOYO_MAC_FILE_CHROOT, | ||
65 | [TOMOYO_TYPE_UMOUNT] = TOMOYO_MAC_FILE_UMOUNT, | ||
66 | }; | ||
67 | |||
68 | static const u8 tomoyo_pnnn2mac[TOMOYO_MAX_PATH_NUMBER3_OPERATION] = { | ||
69 | [TOMOYO_TYPE_MKBLOCK] = TOMOYO_MAC_FILE_MKBLOCK, | ||
70 | [TOMOYO_TYPE_MKCHAR] = TOMOYO_MAC_FILE_MKCHAR, | ||
71 | }; | ||
72 | |||
73 | static const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION] = { | ||
74 | [TOMOYO_TYPE_LINK] = TOMOYO_MAC_FILE_LINK, | ||
75 | [TOMOYO_TYPE_RENAME] = TOMOYO_MAC_FILE_RENAME, | ||
76 | [TOMOYO_TYPE_PIVOT_ROOT] = TOMOYO_MAC_FILE_PIVOT_ROOT, | ||
77 | }; | ||
78 | |||
79 | static const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = { | ||
80 | [TOMOYO_TYPE_CREATE] = TOMOYO_MAC_FILE_CREATE, | ||
81 | [TOMOYO_TYPE_MKDIR] = TOMOYO_MAC_FILE_MKDIR, | ||
82 | [TOMOYO_TYPE_MKFIFO] = TOMOYO_MAC_FILE_MKFIFO, | ||
83 | [TOMOYO_TYPE_MKSOCK] = TOMOYO_MAC_FILE_MKSOCK, | ||
84 | [TOMOYO_TYPE_IOCTL] = TOMOYO_MAC_FILE_IOCTL, | ||
85 | [TOMOYO_TYPE_CHMOD] = TOMOYO_MAC_FILE_CHMOD, | ||
86 | [TOMOYO_TYPE_CHOWN] = TOMOYO_MAC_FILE_CHOWN, | ||
87 | [TOMOYO_TYPE_CHGRP] = TOMOYO_MAC_FILE_CHGRP, | ||
88 | }; | ||
89 | |||
54 | void tomoyo_put_name_union(struct tomoyo_name_union *ptr) | 90 | void tomoyo_put_name_union(struct tomoyo_name_union *ptr) |
55 | { | 91 | { |
56 | if (!ptr) | 92 | if (!ptr) |
@@ -1057,6 +1093,10 @@ static int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, | |||
1057 | int error; | 1093 | int error; |
1058 | 1094 | ||
1059 | next: | 1095 | next: |
1096 | r->type = tomoyo_p2mac[operation]; | ||
1097 | r->mode = tomoyo_get_mode(r->profile, r->type); | ||
1098 | if (r->mode == TOMOYO_CONFIG_DISABLED) | ||
1099 | return 0; | ||
1060 | do { | 1100 | do { |
1061 | error = tomoyo_path_acl(r, filename, 1 << operation); | 1101 | error = tomoyo_path_acl(r, filename, 1 << operation); |
1062 | if (!error) | 1102 | if (!error) |
@@ -1249,8 +1289,8 @@ int tomoyo_path_number_perm(const u8 type, struct path *path, | |||
1249 | struct tomoyo_path_info buf; | 1289 | struct tomoyo_path_info buf; |
1250 | int idx; | 1290 | int idx; |
1251 | 1291 | ||
1252 | if (tomoyo_init_request_info(&r, NULL) == TOMOYO_CONFIG_DISABLED || | 1292 | if (tomoyo_init_request_info(&r, NULL, tomoyo_pn2mac[type]) |
1253 | !path->mnt || !path->dentry) | 1293 | == TOMOYO_CONFIG_DISABLED || !path->mnt || !path->dentry) |
1254 | return 0; | 1294 | return 0; |
1255 | idx = tomoyo_read_lock(); | 1295 | idx = tomoyo_read_lock(); |
1256 | if (!tomoyo_get_realpath(&buf, path)) | 1296 | if (!tomoyo_get_realpath(&buf, path)) |
@@ -1269,21 +1309,19 @@ int tomoyo_path_number_perm(const u8 type, struct path *path, | |||
1269 | /** | 1309 | /** |
1270 | * tomoyo_check_exec_perm - Check permission for "execute". | 1310 | * tomoyo_check_exec_perm - Check permission for "execute". |
1271 | * | 1311 | * |
1272 | * @domain: Pointer to "struct tomoyo_domain_info". | 1312 | * @r: Pointer to "struct tomoyo_request_info". |
1273 | * @filename: Check permission for "execute". | 1313 | * @filename: Check permission for "execute". |
1274 | * | 1314 | * |
1275 | * Returns 0 on success, negativevalue otherwise. | 1315 | * Returns 0 on success, negativevalue otherwise. |
1276 | * | 1316 | * |
1277 | * Caller holds tomoyo_read_lock(). | 1317 | * Caller holds tomoyo_read_lock(). |
1278 | */ | 1318 | */ |
1279 | int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, | 1319 | int tomoyo_check_exec_perm(struct tomoyo_request_info *r, |
1280 | const struct tomoyo_path_info *filename) | 1320 | const struct tomoyo_path_info *filename) |
1281 | { | 1321 | { |
1282 | struct tomoyo_request_info r; | 1322 | if (r->mode == TOMOYO_CONFIG_DISABLED) |
1283 | |||
1284 | if (tomoyo_init_request_info(&r, NULL) == TOMOYO_CONFIG_DISABLED) | ||
1285 | return 0; | 1323 | return 0; |
1286 | return tomoyo_file_perm(&r, filename, 1); | 1324 | return tomoyo_file_perm(r, filename, 1); |
1287 | } | 1325 | } |
1288 | 1326 | ||
1289 | /** | 1327 | /** |
@@ -1304,17 +1342,11 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | |||
1304 | struct tomoyo_request_info r; | 1342 | struct tomoyo_request_info r; |
1305 | int idx; | 1343 | int idx; |
1306 | 1344 | ||
1307 | if (tomoyo_init_request_info(&r, domain) == TOMOYO_CONFIG_DISABLED || | 1345 | if (!path->mnt || |
1308 | !path->mnt) | 1346 | (path->dentry->d_inode && S_ISDIR(path->dentry->d_inode->i_mode))) |
1309 | return 0; | ||
1310 | if (acc_mode == 0) | ||
1311 | return 0; | ||
1312 | if (path->dentry->d_inode && S_ISDIR(path->dentry->d_inode->i_mode)) | ||
1313 | /* | ||
1314 | * I don't check directories here because mkdir() and rmdir() | ||
1315 | * don't call me. | ||
1316 | */ | ||
1317 | return 0; | 1347 | return 0; |
1348 | buf.name = NULL; | ||
1349 | r.mode = TOMOYO_CONFIG_DISABLED; | ||
1318 | idx = tomoyo_read_lock(); | 1350 | idx = tomoyo_read_lock(); |
1319 | if (!tomoyo_get_realpath(&buf, path)) | 1351 | if (!tomoyo_get_realpath(&buf, path)) |
1320 | goto out; | 1352 | goto out; |
@@ -1324,15 +1356,26 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | |||
1324 | * we need to check "allow_rewrite" permission when the filename is not | 1356 | * we need to check "allow_rewrite" permission when the filename is not |
1325 | * opened for append mode or the filename is truncated at open time. | 1357 | * opened for append mode or the filename is truncated at open time. |
1326 | */ | 1358 | */ |
1327 | if ((acc_mode & MAY_WRITE) && | 1359 | if ((acc_mode & MAY_WRITE) && !(flag & O_APPEND) |
1328 | ((flag & O_TRUNC) || !(flag & O_APPEND)) && | 1360 | && tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_REWRITE) |
1329 | (tomoyo_is_no_rewrite_file(&buf))) { | 1361 | != TOMOYO_CONFIG_DISABLED) { |
1330 | error = tomoyo_path_permission(&r, TOMOYO_TYPE_REWRITE, &buf); | 1362 | if (!tomoyo_get_realpath(&buf, path)) { |
1363 | error = -ENOMEM; | ||
1364 | goto out; | ||
1365 | } | ||
1366 | if (tomoyo_is_no_rewrite_file(&buf)) | ||
1367 | error = tomoyo_path_permission(&r, TOMOYO_TYPE_REWRITE, | ||
1368 | &buf); | ||
1331 | } | 1369 | } |
1332 | if (!error) | 1370 | if (!error && acc_mode && |
1371 | tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_OPEN) | ||
1372 | != TOMOYO_CONFIG_DISABLED) { | ||
1373 | if (!buf.name && !tomoyo_get_realpath(&buf, path)) { | ||
1374 | error = -ENOMEM; | ||
1375 | goto out; | ||
1376 | } | ||
1333 | error = tomoyo_file_perm(&r, &buf, acc_mode); | 1377 | error = tomoyo_file_perm(&r, &buf, acc_mode); |
1334 | if (!error && (flag & O_TRUNC)) | 1378 | } |
1335 | error = tomoyo_path_permission(&r, TOMOYO_TYPE_TRUNCATE, &buf); | ||
1336 | out: | 1379 | out: |
1337 | kfree(buf.name); | 1380 | kfree(buf.name); |
1338 | tomoyo_read_unlock(idx); | 1381 | tomoyo_read_unlock(idx); |
@@ -1356,9 +1399,12 @@ int tomoyo_path_perm(const u8 operation, struct path *path) | |||
1356 | struct tomoyo_request_info r; | 1399 | struct tomoyo_request_info r; |
1357 | int idx; | 1400 | int idx; |
1358 | 1401 | ||
1359 | if (tomoyo_init_request_info(&r, NULL) == TOMOYO_CONFIG_DISABLED || | 1402 | if (!path->mnt) |
1360 | !path->mnt) | 1403 | return 0; |
1404 | if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation]) | ||
1405 | == TOMOYO_CONFIG_DISABLED) | ||
1361 | return 0; | 1406 | return 0; |
1407 | buf.name = NULL; | ||
1362 | idx = tomoyo_read_lock(); | 1408 | idx = tomoyo_read_lock(); |
1363 | if (!tomoyo_get_realpath(&buf, path)) | 1409 | if (!tomoyo_get_realpath(&buf, path)) |
1364 | goto out; | 1410 | goto out; |
@@ -1371,6 +1417,7 @@ int tomoyo_path_perm(const u8 operation, struct path *path) | |||
1371 | break; | 1417 | break; |
1372 | case TOMOYO_TYPE_RMDIR: | 1418 | case TOMOYO_TYPE_RMDIR: |
1373 | case TOMOYO_TYPE_CHROOT: | 1419 | case TOMOYO_TYPE_CHROOT: |
1420 | case TOMOYO_TYPE_UMOUNT: | ||
1374 | tomoyo_add_slash(&buf); | 1421 | tomoyo_add_slash(&buf); |
1375 | break; | 1422 | break; |
1376 | } | 1423 | } |
@@ -1442,8 +1489,9 @@ int tomoyo_path_number3_perm(const u8 operation, struct path *path, | |||
1442 | struct tomoyo_path_info buf; | 1489 | struct tomoyo_path_info buf; |
1443 | int idx; | 1490 | int idx; |
1444 | 1491 | ||
1445 | if (tomoyo_init_request_info(&r, NULL) == TOMOYO_CONFIG_DISABLED || | 1492 | if (!path->mnt || |
1446 | !path->mnt) | 1493 | tomoyo_init_request_info(&r, NULL, tomoyo_pnnn2mac[operation]) |
1494 | == TOMOYO_CONFIG_DISABLED) | ||
1447 | return 0; | 1495 | return 0; |
1448 | idx = tomoyo_read_lock(); | 1496 | idx = tomoyo_read_lock(); |
1449 | error = -ENOMEM; | 1497 | error = -ENOMEM; |
@@ -1477,8 +1525,9 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1, | |||
1477 | struct tomoyo_request_info r; | 1525 | struct tomoyo_request_info r; |
1478 | int idx; | 1526 | int idx; |
1479 | 1527 | ||
1480 | if (tomoyo_init_request_info(&r, NULL) == TOMOYO_CONFIG_DISABLED || | 1528 | if (!path1->mnt || !path2->mnt || |
1481 | !path1->mnt || !path2->mnt) | 1529 | tomoyo_init_request_info(&r, NULL, tomoyo_pp2mac[operation]) |
1530 | == TOMOYO_CONFIG_DISABLED) | ||
1482 | return 0; | 1531 | return 0; |
1483 | buf1.name = NULL; | 1532 | buf1.name = NULL; |
1484 | buf2.name = NULL; | 1533 | buf2.name = NULL; |
@@ -1486,13 +1535,19 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1, | |||
1486 | if (!tomoyo_get_realpath(&buf1, path1) || | 1535 | if (!tomoyo_get_realpath(&buf1, path1) || |
1487 | !tomoyo_get_realpath(&buf2, path2)) | 1536 | !tomoyo_get_realpath(&buf2, path2)) |
1488 | goto out; | 1537 | goto out; |
1489 | { | 1538 | switch (operation) { |
1490 | struct dentry *dentry = path1->dentry; | 1539 | struct dentry *dentry; |
1491 | if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) { | 1540 | case TOMOYO_TYPE_RENAME: |
1492 | tomoyo_add_slash(&buf1); | 1541 | case TOMOYO_TYPE_LINK: |
1493 | tomoyo_add_slash(&buf2); | 1542 | dentry = path1->dentry; |
1494 | } | 1543 | if (!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode)) |
1495 | } | 1544 | break; |
1545 | /* fall through */ | ||
1546 | case TOMOYO_TYPE_PIVOT_ROOT: | ||
1547 | tomoyo_add_slash(&buf1); | ||
1548 | tomoyo_add_slash(&buf2); | ||
1549 | break; | ||
1550 | } | ||
1496 | do { | 1551 | do { |
1497 | error = tomoyo_path2_acl(&r, operation, &buf1, &buf2); | 1552 | error = tomoyo_path2_acl(&r, operation, &buf1, &buf2); |
1498 | if (!error) | 1553 | if (!error) |
diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c index 7c1c7fdd3681..77ee8bf41948 100644 --- a/security/tomoyo/mount.c +++ b/security/tomoyo/mount.c | |||
@@ -248,7 +248,8 @@ int tomoyo_mount_permission(char *dev_name, struct path *path, char *type, | |||
248 | int error; | 248 | int error; |
249 | int idx; | 249 | int idx; |
250 | 250 | ||
251 | if (tomoyo_init_request_info(&r, NULL) == TOMOYO_CONFIG_DISABLED) | 251 | if (tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_MOUNT) |
252 | == TOMOYO_CONFIG_DISABLED) | ||
252 | return 0; | 253 | return 0; |
253 | if (!type) | 254 | if (!type) |
254 | type = "<NULL>"; | 255 | type = "<NULL>"; |
diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c index 592b76a2bce8..307793ed6075 100644 --- a/security/tomoyo/util.c +++ b/security/tomoyo/util.c | |||
@@ -792,25 +792,67 @@ const char *tomoyo_get_exe(void) | |||
792 | } | 792 | } |
793 | 793 | ||
794 | /** | 794 | /** |
795 | * tomoyo_get_mode - Get MAC mode. | ||
796 | * | ||
797 | * @profile: Profile number. | ||
798 | * @index: Index number of functionality. | ||
799 | * | ||
800 | * Returns mode. | ||
801 | */ | ||
802 | int tomoyo_get_mode(const u8 profile, const u8 index) | ||
803 | { | ||
804 | u8 mode; | ||
805 | const u8 category = TOMOYO_MAC_CATEGORY_FILE; | ||
806 | if (!tomoyo_policy_loaded) | ||
807 | return TOMOYO_CONFIG_DISABLED; | ||
808 | mode = tomoyo_profile(profile)->config[index]; | ||
809 | if (mode == TOMOYO_CONFIG_USE_DEFAULT) | ||
810 | mode = tomoyo_profile(profile)->config[category]; | ||
811 | if (mode == TOMOYO_CONFIG_USE_DEFAULT) | ||
812 | mode = tomoyo_profile(profile)->default_config; | ||
813 | return mode & 3; | ||
814 | } | ||
815 | |||
816 | /** | ||
795 | * tomoyo_init_request_info - Initialize "struct tomoyo_request_info" members. | 817 | * tomoyo_init_request_info - Initialize "struct tomoyo_request_info" members. |
796 | * | 818 | * |
797 | * @r: Pointer to "struct tomoyo_request_info" to initialize. | 819 | * @r: Pointer to "struct tomoyo_request_info" to initialize. |
798 | * @domain: Pointer to "struct tomoyo_domain_info". NULL for tomoyo_domain(). | 820 | * @domain: Pointer to "struct tomoyo_domain_info". NULL for tomoyo_domain(). |
821 | * @index: Index number of functionality. | ||
799 | * | 822 | * |
800 | * Returns mode. | 823 | * Returns mode. |
801 | */ | 824 | */ |
802 | int tomoyo_init_request_info(struct tomoyo_request_info *r, | 825 | int tomoyo_init_request_info(struct tomoyo_request_info *r, |
803 | struct tomoyo_domain_info *domain) | 826 | struct tomoyo_domain_info *domain, const u8 index) |
804 | { | 827 | { |
828 | u8 profile; | ||
805 | memset(r, 0, sizeof(*r)); | 829 | memset(r, 0, sizeof(*r)); |
806 | if (!domain) | 830 | if (!domain) |
807 | domain = tomoyo_domain(); | 831 | domain = tomoyo_domain(); |
808 | r->domain = domain; | 832 | r->domain = domain; |
809 | r->mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); | 833 | profile = domain->profile; |
834 | r->profile = profile; | ||
835 | r->type = index; | ||
836 | r->mode = tomoyo_get_mode(profile, index); | ||
810 | return r->mode; | 837 | return r->mode; |
811 | } | 838 | } |
812 | 839 | ||
813 | /** | 840 | /** |
841 | * tomoyo_last_word - Get last component of a line. | ||
842 | * | ||
843 | * @line: A line. | ||
844 | * | ||
845 | * Returns the last word of a line. | ||
846 | */ | ||
847 | static const char *tomoyo_last_word(const char *name) | ||
848 | { | ||
849 | const char *cp = strrchr(name, ' '); | ||
850 | if (cp) | ||
851 | return cp + 1; | ||
852 | return name; | ||
853 | } | ||
854 | |||
855 | /** | ||
814 | * tomoyo_warn_log - Print warning or error message on console. | 856 | * tomoyo_warn_log - Print warning or error message on console. |
815 | * | 857 | * |
816 | * @r: Pointer to "struct tomoyo_request_info". | 858 | * @r: Pointer to "struct tomoyo_request_info". |
@@ -818,29 +860,34 @@ int tomoyo_init_request_info(struct tomoyo_request_info *r, | |||
818 | */ | 860 | */ |
819 | void tomoyo_warn_log(struct tomoyo_request_info *r, const char *fmt, ...) | 861 | void tomoyo_warn_log(struct tomoyo_request_info *r, const char *fmt, ...) |
820 | { | 862 | { |
821 | int len = PAGE_SIZE; | ||
822 | va_list args; | 863 | va_list args; |
823 | char *buffer; | 864 | char *buffer; |
824 | if (!tomoyo_verbose_mode(r->domain)) | 865 | const struct tomoyo_domain_info * const domain = r->domain; |
825 | return; | 866 | const struct tomoyo_profile *profile = tomoyo_profile(domain->profile); |
826 | while (1) { | 867 | switch (r->mode) { |
827 | int len2; | 868 | case TOMOYO_CONFIG_ENFORCING: |
828 | buffer = kmalloc(len, GFP_NOFS); | 869 | if (!profile->enforcing->enforcing_verbose) |
829 | if (!buffer) | ||
830 | return; | 870 | return; |
831 | va_start(args, fmt); | 871 | break; |
832 | len2 = vsnprintf(buffer, len - 1, fmt, args); | 872 | case TOMOYO_CONFIG_PERMISSIVE: |
833 | va_end(args); | 873 | if (!profile->permissive->permissive_verbose) |
834 | if (len2 <= len - 1) { | 874 | return; |
835 | buffer[len2] = '\0'; | 875 | break; |
836 | break; | 876 | case TOMOYO_CONFIG_LEARNING: |
837 | } | 877 | if (!profile->learning->learning_verbose) |
838 | len = len2 + 1; | 878 | return; |
839 | kfree(buffer); | 879 | break; |
840 | } | 880 | } |
841 | printk(KERN_WARNING "TOMOYO-%s: Access %s denied for %s\n", | 881 | buffer = kmalloc(4096, GFP_NOFS); |
842 | r->mode == TOMOYO_CONFIG_ENFORCING ? "ERROR" : "WARNING", | 882 | if (!buffer) |
843 | buffer, tomoyo_get_last_name(r->domain)); | 883 | return; |
884 | va_start(args, fmt); | ||
885 | vsnprintf(buffer, 4095, fmt, args); | ||
886 | va_end(args); | ||
887 | buffer[4095] = '\0'; | ||
888 | printk(KERN_WARNING "%s: Access %s denied for %s\n", | ||
889 | r->mode == TOMOYO_CONFIG_ENFORCING ? "ERROR" : "WARNING", buffer, | ||
890 | tomoyo_last_word(domain->domainname->name)); | ||
844 | kfree(buffer); | 891 | kfree(buffer); |
845 | } | 892 | } |
846 | 893 | ||
@@ -903,7 +950,8 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r) | |||
903 | count++; | 950 | count++; |
904 | } | 951 | } |
905 | } | 952 | } |
906 | if (count < tomoyo_check_flags(domain, TOMOYO_MAX_ACCEPT_ENTRY)) | 953 | if (count < tomoyo_profile(domain->profile)->learning-> |
954 | learning_max_entry) | ||
907 | return true; | 955 | return true; |
908 | if (!domain->quota_warned) { | 956 | if (!domain->quota_warned) { |
909 | domain->quota_warned = true; | 957 | domain->quota_warned = true; |