aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>2010-06-03 07:38:44 -0400
committerJames Morris <jmorris@namei.org>2010-08-02 01:33:43 -0400
commit57c2590fb7fd38bd52708ff2716a577d0c2b3c5a (patch)
tree19db2e176e1e49d85482995249ba18aebbb8f7eb /security
parent1084307ca097745ed6e40a192329b133a49271ac (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')
-rw-r--r--security/tomoyo/common.c431
-rw-r--r--security/tomoyo/common.h68
-rw-r--r--security/tomoyo/domain.c9
-rw-r--r--security/tomoyo/file.c131
-rw-r--r--security/tomoyo/mount.c3
-rw-r--r--security/tomoyo/util.c92
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
14static 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. */
25static unsigned int tomoyo_profile_version;
26
27/* Profile table. Memory is allocated as needed. */
28static 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. */
16static const char *tomoyo_mode_4[4] = { 31static 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. */
20static 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 36static 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",
31static 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 */
48static 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? */
54static bool tomoyo_manage_by_non_root; 65static 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 */
74static 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 */
166unsigned 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 */
189bool 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 */
201static struct tomoyo_profile *tomoyo_find_or_assign_new_profile(const unsigned 184static 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 */
223struct 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 */
303static int tomoyo_read_profile(struct tomoyo_io_buffer *head) 358static 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)
1595static int tomoyo_read_version(struct tomoyo_io_buffer *head) 1679static 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. */
78enum 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. */
86enum tomoyo_acl_entry_type_index { 79enum 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
153enum 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
180enum 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
678struct tomoyo_preference {
679 unsigned int learning_max_entry;
680 bool enforcing_verbose;
681 bool learning_verbose;
682 bool permissive_verbose;
683};
684
685struct 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
654extern asmlinkage long sys_getpid(void); 697extern 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. */
686bool tomoyo_compare_number_union(const unsigned long value, 729bool tomoyo_compare_number_union(const unsigned long value,
687 const struct tomoyo_number_union *ptr); 730 const struct tomoyo_number_union *ptr);
731int tomoyo_get_mode(const u8 profile, const u8 index);
688/* Transactional sprintf() for policy dump. */ 732/* Transactional sprintf() for policy dump. */
689bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) 733bool 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);
747const char *tomoyo_path2keyword(const u8 operation); 791const char *tomoyo_path2keyword(const u8 operation);
748/* Fill "struct tomoyo_request_info". */ 792/* Fill "struct tomoyo_request_info". */
749int tomoyo_init_request_info(struct tomoyo_request_info *r, 793int 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. */
752int tomoyo_mount_permission(char *dev_name, struct path *path, char *type, 797int 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);
794struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * 839struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
795 domainname, 840 domainname,
796 const u8 profile); 841 const u8 profile);
842struct tomoyo_profile *tomoyo_profile(const u8 profile);
797/* Allocate memory for "struct tomoyo_path_group". */ 843/* Allocate memory for "struct tomoyo_path_group". */
798struct tomoyo_path_group *tomoyo_get_path_group(const char *group_name); 844struct tomoyo_path_group *tomoyo_get_path_group(const char *group_name);
799struct tomoyo_number_group *tomoyo_get_number_group(const char *group_name); 845struct 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. */
846void __init tomoyo_mm_init(void); 892void __init tomoyo_mm_init(void);
847int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, 893int tomoyo_check_exec_perm(struct tomoyo_request_info *r,
848 const struct tomoyo_path_info *filename); 894 const struct tomoyo_path_info *filename);
849int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, 895int 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
54static 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
68static 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
73static 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
79static 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
54void tomoyo_put_name_union(struct tomoyo_name_union *ptr) 90void 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 */
1279int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, 1319int 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 */
802int 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 */
802int tomoyo_init_request_info(struct tomoyo_request_info *r, 825int 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 */
847static 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 */
819void tomoyo_warn_log(struct tomoyo_request_info *r, const char *fmt, ...) 861void 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;