aboutsummaryrefslogtreecommitdiffstats
path: root/security/tomoyo/common.c
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /security/tomoyo/common.c
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'security/tomoyo/common.c')
-rw-r--r--security/tomoyo/common.c576
1 files changed, 269 insertions, 307 deletions
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index 3c8bd8ee0b95..975c45d88baa 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -10,11 +10,13 @@
10 */ 10 */
11 11
12#include <linux/uaccess.h> 12#include <linux/uaccess.h>
13#include <linux/slab.h>
13#include <linux/security.h> 14#include <linux/security.h>
14#include <linux/hardirq.h> 15#include <linux/hardirq.h>
15#include "realpath.h"
16#include "common.h" 16#include "common.h"
17#include "tomoyo.h" 17
18/* Lock for protecting policy. */
19DEFINE_MUTEX(tomoyo_policy_lock);
18 20
19/* Has loading policy done? */ 21/* Has loading policy done? */
20bool tomoyo_policy_loaded; 22bool tomoyo_policy_loaded;
@@ -178,20 +180,19 @@ static void tomoyo_normalize_line(unsigned char *buffer)
178 * 1 = must / -1 = must not / 0 = don't care 180 * 1 = must / -1 = must not / 0 = don't care
179 * @end_type: Should the pathname end with '/'? 181 * @end_type: Should the pathname end with '/'?
180 * 1 = must / -1 = must not / 0 = don't care 182 * 1 = must / -1 = must not / 0 = don't care
181 * @function: The name of function calling me.
182 * 183 *
183 * Check whether the given filename follows the naming rules. 184 * Check whether the given filename follows the naming rules.
184 * Returns true if @filename follows the naming rules, false otherwise. 185 * Returns true if @filename follows the naming rules, false otherwise.
185 */ 186 */
186bool tomoyo_is_correct_path(const char *filename, const s8 start_type, 187bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
187 const s8 pattern_type, const s8 end_type, 188 const s8 pattern_type, const s8 end_type)
188 const char *function)
189{ 189{
190 const char *const start = filename;
191 bool in_repetition = false;
190 bool contains_pattern = false; 192 bool contains_pattern = false;
191 unsigned char c; 193 unsigned char c;
192 unsigned char d; 194 unsigned char d;
193 unsigned char e; 195 unsigned char e;
194 const char *original_filename = filename;
195 196
196 if (!filename) 197 if (!filename)
197 goto out; 198 goto out;
@@ -212,9 +213,13 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
212 if (c == '/') 213 if (c == '/')
213 goto out; 214 goto out;
214 } 215 }
215 while ((c = *filename++) != '\0') { 216 while (1) {
217 c = *filename++;
218 if (!c)
219 break;
216 if (c == '\\') { 220 if (c == '\\') {
217 switch ((c = *filename++)) { 221 c = *filename++;
222 switch (c) {
218 case '\\': /* "\\" */ 223 case '\\': /* "\\" */
219 continue; 224 continue;
220 case '$': /* "\$" */ 225 case '$': /* "\$" */
@@ -231,6 +236,22 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
231 break; /* Must not contain pattern */ 236 break; /* Must not contain pattern */
232 contains_pattern = true; 237 contains_pattern = true;
233 continue; 238 continue;
239 case '{': /* "/\{" */
240 if (filename - 3 < start ||
241 *(filename - 3) != '/')
242 break;
243 if (pattern_type == -1)
244 break; /* Must not contain pattern */
245 contains_pattern = true;
246 in_repetition = true;
247 continue;
248 case '}': /* "\}/" */
249 if (*filename != '/')
250 break;
251 if (!in_repetition)
252 break;
253 in_repetition = false;
254 continue;
234 case '0': /* "\ooo" */ 255 case '0': /* "\ooo" */
235 case '1': 256 case '1':
236 case '2': 257 case '2':
@@ -246,6 +267,8 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
246 continue; /* pattern is not \000 */ 267 continue; /* pattern is not \000 */
247 } 268 }
248 goto out; 269 goto out;
270 } else if (in_repetition && c == '/') {
271 goto out;
249 } else if (tomoyo_is_invalid(c)) { 272 } else if (tomoyo_is_invalid(c)) {
250 goto out; 273 goto out;
251 } 274 }
@@ -254,27 +277,24 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
254 if (!contains_pattern) 277 if (!contains_pattern)
255 goto out; 278 goto out;
256 } 279 }
280 if (in_repetition)
281 goto out;
257 return true; 282 return true;
258 out: 283 out:
259 printk(KERN_DEBUG "%s: Invalid pathname '%s'\n", function,
260 original_filename);
261 return false; 284 return false;
262} 285}
263 286
264/** 287/**
265 * tomoyo_is_correct_domain - Check whether the given domainname follows the naming rules. 288 * tomoyo_is_correct_domain - Check whether the given domainname follows the naming rules.
266 * @domainname: The domainname to check. 289 * @domainname: The domainname to check.
267 * @function: The name of function calling me.
268 * 290 *
269 * Returns true if @domainname follows the naming rules, false otherwise. 291 * Returns true if @domainname follows the naming rules, false otherwise.
270 */ 292 */
271bool tomoyo_is_correct_domain(const unsigned char *domainname, 293bool tomoyo_is_correct_domain(const unsigned char *domainname)
272 const char *function)
273{ 294{
274 unsigned char c; 295 unsigned char c;
275 unsigned char d; 296 unsigned char d;
276 unsigned char e; 297 unsigned char e;
277 const char *org_domainname = domainname;
278 298
279 if (!domainname || strncmp(domainname, TOMOYO_ROOT_NAME, 299 if (!domainname || strncmp(domainname, TOMOYO_ROOT_NAME,
280 TOMOYO_ROOT_NAME_LEN)) 300 TOMOYO_ROOT_NAME_LEN))
@@ -317,8 +337,6 @@ bool tomoyo_is_correct_domain(const unsigned char *domainname,
317 } while (*domainname); 337 } while (*domainname);
318 return true; 338 return true;
319 out: 339 out:
320 printk(KERN_DEBUG "%s: Invalid domainname '%s'\n", function,
321 org_domainname);
322 return false; 340 return false;
323} 341}
324 342
@@ -339,10 +357,9 @@ bool tomoyo_is_domain_def(const unsigned char *buffer)
339 * 357 *
340 * @domainname: The domainname to find. 358 * @domainname: The domainname to find.
341 * 359 *
342 * Caller must call down_read(&tomoyo_domain_list_lock); or
343 * down_write(&tomoyo_domain_list_lock); .
344 *
345 * Returns pointer to "struct tomoyo_domain_info" if found, NULL otherwise. 360 * Returns pointer to "struct tomoyo_domain_info" if found, NULL otherwise.
361 *
362 * Caller holds tomoyo_read_lock().
346 */ 363 */
347struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname) 364struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname)
348{ 365{
@@ -351,7 +368,7 @@ struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname)
351 368
352 name.name = domainname; 369 name.name = domainname;
353 tomoyo_fill_path_info(&name); 370 tomoyo_fill_path_info(&name);
354 list_for_each_entry(domain, &tomoyo_domain_list, list) { 371 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
355 if (!domain->is_deleted && 372 if (!domain->is_deleted &&
356 !tomoyo_pathcmp(&name, domain->domainname)) 373 !tomoyo_pathcmp(&name, domain->domainname))
357 return domain; 374 return domain;
@@ -360,33 +377,6 @@ struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname)
360} 377}
361 378
362/** 379/**
363 * tomoyo_path_depth - Evaluate the number of '/' in a string.
364 *
365 * @pathname: The string to evaluate.
366 *
367 * Returns path depth of the string.
368 *
369 * I score 2 for each of the '/' in the @pathname
370 * and score 1 if the @pathname ends with '/'.
371 */
372static int tomoyo_path_depth(const char *pathname)
373{
374 int i = 0;
375
376 if (pathname) {
377 const char *ep = pathname + strlen(pathname);
378 if (pathname < ep--) {
379 if (*ep != '/')
380 i++;
381 while (pathname <= ep)
382 if (*ep-- == '/')
383 i += 2;
384 }
385 }
386 return i;
387}
388
389/**
390 * tomoyo_const_part_length - Evaluate the initial length without a pattern in a token. 380 * tomoyo_const_part_length - Evaluate the initial length without a pattern in a token.
391 * 381 *
392 * @filename: The string to evaluate. 382 * @filename: The string to evaluate.
@@ -444,11 +434,10 @@ void tomoyo_fill_path_info(struct tomoyo_path_info *ptr)
444 ptr->is_dir = len && (name[len - 1] == '/'); 434 ptr->is_dir = len && (name[len - 1] == '/');
445 ptr->is_patterned = (ptr->const_len < len); 435 ptr->is_patterned = (ptr->const_len < len);
446 ptr->hash = full_name_hash(name, len); 436 ptr->hash = full_name_hash(name, len);
447 ptr->depth = tomoyo_path_depth(name);
448} 437}
449 438
450/** 439/**
451 * tomoyo_file_matches_to_pattern2 - Pattern matching without '/' character 440 * tomoyo_file_matches_pattern2 - Pattern matching without '/' character
452 * and "\-" pattern. 441 * and "\-" pattern.
453 * 442 *
454 * @filename: The start of string to check. 443 * @filename: The start of string to check.
@@ -458,10 +447,10 @@ void tomoyo_fill_path_info(struct tomoyo_path_info *ptr)
458 * 447 *
459 * Returns true if @filename matches @pattern, false otherwise. 448 * Returns true if @filename matches @pattern, false otherwise.
460 */ 449 */
461static bool tomoyo_file_matches_to_pattern2(const char *filename, 450static bool tomoyo_file_matches_pattern2(const char *filename,
462 const char *filename_end, 451 const char *filename_end,
463 const char *pattern, 452 const char *pattern,
464 const char *pattern_end) 453 const char *pattern_end)
465{ 454{
466 while (filename < filename_end && pattern < pattern_end) { 455 while (filename < filename_end && pattern < pattern_end) {
467 char c; 456 char c;
@@ -519,7 +508,7 @@ static bool tomoyo_file_matches_to_pattern2(const char *filename,
519 case '*': 508 case '*':
520 case '@': 509 case '@':
521 for (i = 0; i <= filename_end - filename; i++) { 510 for (i = 0; i <= filename_end - filename; i++) {
522 if (tomoyo_file_matches_to_pattern2( 511 if (tomoyo_file_matches_pattern2(
523 filename + i, filename_end, 512 filename + i, filename_end,
524 pattern + 1, pattern_end)) 513 pattern + 1, pattern_end))
525 return true; 514 return true;
@@ -550,7 +539,7 @@ static bool tomoyo_file_matches_to_pattern2(const char *filename,
550 j++; 539 j++;
551 } 540 }
552 for (i = 1; i <= j; i++) { 541 for (i = 1; i <= j; i++) {
553 if (tomoyo_file_matches_to_pattern2( 542 if (tomoyo_file_matches_pattern2(
554 filename + i, filename_end, 543 filename + i, filename_end,
555 pattern + 1, pattern_end)) 544 pattern + 1, pattern_end))
556 return true; 545 return true;
@@ -567,7 +556,7 @@ static bool tomoyo_file_matches_to_pattern2(const char *filename,
567} 556}
568 557
569/** 558/**
570 * tomoyo_file_matches_to_pattern - Pattern matching without without '/' character. 559 * tomoyo_file_matches_pattern - Pattern matching without without '/' character.
571 * 560 *
572 * @filename: The start of string to check. 561 * @filename: The start of string to check.
573 * @filename_end: The end of string to check. 562 * @filename_end: The end of string to check.
@@ -576,7 +565,7 @@ static bool tomoyo_file_matches_to_pattern2(const char *filename,
576 * 565 *
577 * Returns true if @filename matches @pattern, false otherwise. 566 * Returns true if @filename matches @pattern, false otherwise.
578 */ 567 */
579static bool tomoyo_file_matches_to_pattern(const char *filename, 568static bool tomoyo_file_matches_pattern(const char *filename,
580 const char *filename_end, 569 const char *filename_end,
581 const char *pattern, 570 const char *pattern,
582 const char *pattern_end) 571 const char *pattern_end)
@@ -589,10 +578,10 @@ static bool tomoyo_file_matches_to_pattern(const char *filename,
589 /* Split at "\-" pattern. */ 578 /* Split at "\-" pattern. */
590 if (*pattern++ != '\\' || *pattern++ != '-') 579 if (*pattern++ != '\\' || *pattern++ != '-')
591 continue; 580 continue;
592 result = tomoyo_file_matches_to_pattern2(filename, 581 result = tomoyo_file_matches_pattern2(filename,
593 filename_end, 582 filename_end,
594 pattern_start, 583 pattern_start,
595 pattern - 2); 584 pattern - 2);
596 if (first) 585 if (first)
597 result = !result; 586 result = !result;
598 if (result) 587 if (result)
@@ -600,13 +589,79 @@ static bool tomoyo_file_matches_to_pattern(const char *filename,
600 first = false; 589 first = false;
601 pattern_start = pattern; 590 pattern_start = pattern;
602 } 591 }
603 result = tomoyo_file_matches_to_pattern2(filename, filename_end, 592 result = tomoyo_file_matches_pattern2(filename, filename_end,
604 pattern_start, pattern_end); 593 pattern_start, pattern_end);
605 return first ? result : !result; 594 return first ? result : !result;
606} 595}
607 596
608/** 597/**
598 * tomoyo_path_matches_pattern2 - Do pathname pattern matching.
599 *
600 * @f: The start of string to check.
601 * @p: The start of pattern to compare.
602 *
603 * Returns true if @f matches @p, false otherwise.
604 */
605static bool tomoyo_path_matches_pattern2(const char *f, const char *p)
606{
607 const char *f_delimiter;
608 const char *p_delimiter;
609
610 while (*f && *p) {
611 f_delimiter = strchr(f, '/');
612 if (!f_delimiter)
613 f_delimiter = f + strlen(f);
614 p_delimiter = strchr(p, '/');
615 if (!p_delimiter)
616 p_delimiter = p + strlen(p);
617 if (*p == '\\' && *(p + 1) == '{')
618 goto recursive;
619 if (!tomoyo_file_matches_pattern(f, f_delimiter, p,
620 p_delimiter))
621 return false;
622 f = f_delimiter;
623 if (*f)
624 f++;
625 p = p_delimiter;
626 if (*p)
627 p++;
628 }
629 /* Ignore trailing "\*" and "\@" in @pattern. */
630 while (*p == '\\' &&
631 (*(p + 1) == '*' || *(p + 1) == '@'))
632 p += 2;
633 return !*f && !*p;
634 recursive:
635 /*
636 * The "\{" pattern is permitted only after '/' character.
637 * This guarantees that below "*(p - 1)" is safe.
638 * Also, the "\}" pattern is permitted only before '/' character
639 * so that "\{" + "\}" pair will not break the "\-" operator.
640 */
641 if (*(p - 1) != '/' || p_delimiter <= p + 3 || *p_delimiter != '/' ||
642 *(p_delimiter - 1) != '}' || *(p_delimiter - 2) != '\\')
643 return false; /* Bad pattern. */
644 do {
645 /* Compare current component with pattern. */
646 if (!tomoyo_file_matches_pattern(f, f_delimiter, p + 2,
647 p_delimiter - 2))
648 break;
649 /* Proceed to next component. */
650 f = f_delimiter;
651 if (!*f)
652 break;
653 f++;
654 /* Continue comparison. */
655 if (tomoyo_path_matches_pattern2(f, p_delimiter + 1))
656 return true;
657 f_delimiter = strchr(f, '/');
658 } while (f_delimiter);
659 return false; /* Not matched. */
660}
661
662/**
609 * tomoyo_path_matches_pattern - Check whether the given filename matches the given pattern. 663 * tomoyo_path_matches_pattern - Check whether the given filename matches the given pattern.
664 *
610 * @filename: The filename to check. 665 * @filename: The filename to check.
611 * @pattern: The pattern to compare. 666 * @pattern: The pattern to compare.
612 * 667 *
@@ -615,24 +670,24 @@ static bool tomoyo_file_matches_to_pattern(const char *filename,
615 * The following patterns are available. 670 * The following patterns are available.
616 * \\ \ itself. 671 * \\ \ itself.
617 * \ooo Octal representation of a byte. 672 * \ooo Octal representation of a byte.
618 * \* More than or equals to 0 character other than '/'. 673 * \* Zero or more repetitions of characters other than '/'.
619 * \@ More than or equals to 0 character other than '/' or '.'. 674 * \@ Zero or more repetitions of characters other than '/' or '.'.
620 * \? 1 byte character other than '/'. 675 * \? 1 byte character other than '/'.
621 * \$ More than or equals to 1 decimal digit. 676 * \$ One or more repetitions of decimal digits.
622 * \+ 1 decimal digit. 677 * \+ 1 decimal digit.
623 * \X More than or equals to 1 hexadecimal digit. 678 * \X One or more repetitions of hexadecimal digits.
624 * \x 1 hexadecimal digit. 679 * \x 1 hexadecimal digit.
625 * \A More than or equals to 1 alphabet character. 680 * \A One or more repetitions of alphabet characters.
626 * \a 1 alphabet character. 681 * \a 1 alphabet character.
682 *
627 * \- Subtraction operator. 683 * \- Subtraction operator.
684 *
685 * /\{dir\}/ '/' + 'One or more repetitions of dir/' (e.g. /dir/ /dir/dir/
686 * /dir/dir/dir/ ).
628 */ 687 */
629bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, 688bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
630 const struct tomoyo_path_info *pattern) 689 const struct tomoyo_path_info *pattern)
631{ 690{
632 /*
633 if (!filename || !pattern)
634 return false;
635 */
636 const char *f = filename->name; 691 const char *f = filename->name;
637 const char *p = pattern->name; 692 const char *p = pattern->name;
638 const int len = pattern->const_len; 693 const int len = pattern->const_len;
@@ -640,37 +695,15 @@ bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
640 /* If @pattern doesn't contain pattern, I can use strcmp(). */ 695 /* If @pattern doesn't contain pattern, I can use strcmp(). */
641 if (!pattern->is_patterned) 696 if (!pattern->is_patterned)
642 return !tomoyo_pathcmp(filename, pattern); 697 return !tomoyo_pathcmp(filename, pattern);
643 /* Dont compare if the number of '/' differs. */ 698 /* Don't compare directory and non-directory. */
644 if (filename->depth != pattern->depth) 699 if (filename->is_dir != pattern->is_dir)
645 return false; 700 return false;
646 /* Compare the initial length without patterns. */ 701 /* Compare the initial length without patterns. */
647 if (strncmp(f, p, len)) 702 if (strncmp(f, p, len))
648 return false; 703 return false;
649 f += len; 704 f += len;
650 p += len; 705 p += len;
651 /* Main loop. Compare each directory component. */ 706 return tomoyo_path_matches_pattern2(f, p);
652 while (*f && *p) {
653 const char *f_delimiter = strchr(f, '/');
654 const char *p_delimiter = strchr(p, '/');
655 if (!f_delimiter)
656 f_delimiter = f + strlen(f);
657 if (!p_delimiter)
658 p_delimiter = p + strlen(p);
659 if (!tomoyo_file_matches_to_pattern(f, f_delimiter,
660 p, p_delimiter))
661 return false;
662 f = f_delimiter;
663 if (*f)
664 f++;
665 p = p_delimiter;
666 if (*p)
667 p++;
668 }
669 /* Ignore trailing "\*" and "\@" in @pattern. */
670 while (*p == '\\' &&
671 (*(p + 1) == '*' || *(p + 1) == '@'))
672 p += 2;
673 return !*f && !*p;
674} 707}
675 708
676/** 709/**
@@ -706,7 +739,7 @@ bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...)
706 * 739 *
707 * Returns the tomoyo_realpath() of current process on success, NULL otherwise. 740 * Returns the tomoyo_realpath() of current process on success, NULL otherwise.
708 * 741 *
709 * This function uses tomoyo_alloc(), so the caller must call tomoyo_free() 742 * This function uses kzalloc(), so the caller must call kfree()
710 * if this function didn't return NULL. 743 * if this function didn't return NULL.
711 */ 744 */
712static const char *tomoyo_get_exe(void) 745static const char *tomoyo_get_exe(void)
@@ -787,6 +820,8 @@ bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain)
787 * @domain: Pointer to "struct tomoyo_domain_info". 820 * @domain: Pointer to "struct tomoyo_domain_info".
788 * 821 *
789 * Returns true if the domain is not exceeded quota, false otherwise. 822 * Returns true if the domain is not exceeded quota, false otherwise.
823 *
824 * Caller holds tomoyo_read_lock().
790 */ 825 */
791bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain) 826bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain)
792{ 827{
@@ -795,61 +830,29 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain)
795 830
796 if (!domain) 831 if (!domain)
797 return true; 832 return true;
798 down_read(&tomoyo_domain_acl_info_list_lock); 833 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
799 list_for_each_entry(ptr, &domain->acl_info_list, list) { 834 switch (ptr->type) {
800 if (ptr->type & TOMOYO_ACL_DELETED) 835 struct tomoyo_path_acl *acl;
801 continue; 836 u32 perm;
802 switch (tomoyo_acl_type2(ptr)) { 837 u8 i;
803 struct tomoyo_single_path_acl_record *acl1; 838 case TOMOYO_TYPE_PATH_ACL:
804 struct tomoyo_double_path_acl_record *acl2; 839 acl = container_of(ptr, struct tomoyo_path_acl, head);
805 u16 perm; 840 perm = acl->perm | (((u32) acl->perm_high) << 16);
806 case TOMOYO_TYPE_SINGLE_PATH_ACL: 841 for (i = 0; i < TOMOYO_MAX_PATH_OPERATION; i++)
807 acl1 = container_of(ptr, 842 if (perm & (1 << i))
808 struct tomoyo_single_path_acl_record, 843 count++;
809 head); 844 if (perm & (1 << TOMOYO_TYPE_READ_WRITE))
810 perm = acl1->perm; 845 count -= 2;
811 if (perm & (1 << TOMOYO_TYPE_EXECUTE_ACL))
812 count++;
813 if (perm &
814 ((1 << TOMOYO_TYPE_READ_ACL) |
815 (1 << TOMOYO_TYPE_WRITE_ACL)))
816 count++;
817 if (perm & (1 << TOMOYO_TYPE_CREATE_ACL))
818 count++;
819 if (perm & (1 << TOMOYO_TYPE_UNLINK_ACL))
820 count++;
821 if (perm & (1 << TOMOYO_TYPE_MKDIR_ACL))
822 count++;
823 if (perm & (1 << TOMOYO_TYPE_RMDIR_ACL))
824 count++;
825 if (perm & (1 << TOMOYO_TYPE_MKFIFO_ACL))
826 count++;
827 if (perm & (1 << TOMOYO_TYPE_MKSOCK_ACL))
828 count++;
829 if (perm & (1 << TOMOYO_TYPE_MKBLOCK_ACL))
830 count++;
831 if (perm & (1 << TOMOYO_TYPE_MKCHAR_ACL))
832 count++;
833 if (perm & (1 << TOMOYO_TYPE_TRUNCATE_ACL))
834 count++;
835 if (perm & (1 << TOMOYO_TYPE_SYMLINK_ACL))
836 count++;
837 if (perm & (1 << TOMOYO_TYPE_REWRITE_ACL))
838 count++;
839 break; 846 break;
840 case TOMOYO_TYPE_DOUBLE_PATH_ACL: 847 case TOMOYO_TYPE_PATH2_ACL:
841 acl2 = container_of(ptr, 848 perm = container_of(ptr, struct tomoyo_path2_acl, head)
842 struct tomoyo_double_path_acl_record, 849 ->perm;
843 head); 850 for (i = 0; i < TOMOYO_MAX_PATH2_OPERATION; i++)
844 perm = acl2->perm; 851 if (perm & (1 << i))
845 if (perm & (1 << TOMOYO_TYPE_LINK_ACL)) 852 count++;
846 count++;
847 if (perm & (1 << TOMOYO_TYPE_RENAME_ACL))
848 count++;
849 break; 853 break;
850 } 854 }
851 } 855 }
852 up_read(&tomoyo_domain_acl_info_list_lock);
853 if (count < tomoyo_check_flags(domain, TOMOYO_MAX_ACCEPT_ENTRY)) 856 if (count < tomoyo_check_flags(domain, TOMOYO_MAX_ACCEPT_ENTRY))
854 return true; 857 return true;
855 if (!domain->quota_warned) { 858 if (!domain->quota_warned) {
@@ -881,9 +884,12 @@ static struct tomoyo_profile *tomoyo_find_or_assign_new_profile(const unsigned
881 ptr = tomoyo_profile_ptr[profile]; 884 ptr = tomoyo_profile_ptr[profile];
882 if (ptr) 885 if (ptr)
883 goto ok; 886 goto ok;
884 ptr = tomoyo_alloc_element(sizeof(*ptr)); 887 ptr = kmalloc(sizeof(*ptr), GFP_KERNEL);
885 if (!ptr) 888 if (!tomoyo_memory_ok(ptr)) {
889 kfree(ptr);
890 ptr = NULL;
886 goto ok; 891 goto ok;
892 }
887 for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) 893 for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++)
888 ptr->value[i] = tomoyo_control_array[i].current_value; 894 ptr->value[i] = tomoyo_control_array[i].current_value;
889 mb(); /* Avoid out-of-order execution. */ 895 mb(); /* Avoid out-of-order execution. */
@@ -924,7 +930,9 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head)
924 return -EINVAL; 930 return -EINVAL;
925 *cp = '\0'; 931 *cp = '\0';
926 if (!strcmp(data, "COMMENT")) { 932 if (!strcmp(data, "COMMENT")) {
927 profile->comment = tomoyo_save_name(cp + 1); 933 const struct tomoyo_path_info *old_comment = profile->comment;
934 profile->comment = tomoyo_get_name(cp + 1);
935 tomoyo_put_name(old_comment);
928 return 0; 936 return 0;
929 } 937 }
930 for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) { 938 for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) {
@@ -1019,27 +1027,6 @@ static int tomoyo_read_profile(struct tomoyo_io_buffer *head)
1019} 1027}
1020 1028
1021/* 1029/*
1022 * tomoyo_policy_manager_entry is a structure which is used for holding list of
1023 * domainnames or programs which are permitted to modify configuration via
1024 * /sys/kernel/security/tomoyo/ interface.
1025 * It has following fields.
1026 *
1027 * (1) "list" which is linked to tomoyo_policy_manager_list .
1028 * (2) "manager" is a domainname or a program's pathname.
1029 * (3) "is_domain" is a bool which is true if "manager" is a domainname, false
1030 * otherwise.
1031 * (4) "is_deleted" is a bool which is true if marked as deleted, false
1032 * otherwise.
1033 */
1034struct tomoyo_policy_manager_entry {
1035 struct list_head list;
1036 /* A path to program or a domainname. */
1037 const struct tomoyo_path_info *manager;
1038 bool is_domain; /* True if manager is a domainname. */
1039 bool is_deleted; /* True if this entry is deleted. */
1040};
1041
1042/*
1043 * tomoyo_policy_manager_list is used for holding list of domainnames or 1030 * tomoyo_policy_manager_list is used for holding list of domainnames or
1044 * programs which are permitted to modify configuration via 1031 * programs which are permitted to modify configuration via
1045 * /sys/kernel/security/tomoyo/ interface. 1032 * /sys/kernel/security/tomoyo/ interface.
@@ -1069,8 +1056,7 @@ struct tomoyo_policy_manager_entry {
1069 * 1056 *
1070 * # cat /sys/kernel/security/tomoyo/manager 1057 * # cat /sys/kernel/security/tomoyo/manager
1071 */ 1058 */
1072static LIST_HEAD(tomoyo_policy_manager_list); 1059LIST_HEAD(tomoyo_policy_manager_list);
1073static DECLARE_RWSEM(tomoyo_policy_manager_list_lock);
1074 1060
1075/** 1061/**
1076 * tomoyo_update_manager_entry - Add a manager entry. 1062 * tomoyo_update_manager_entry - Add a manager entry.
@@ -1079,48 +1065,50 @@ static DECLARE_RWSEM(tomoyo_policy_manager_list_lock);
1079 * @is_delete: True if it is a delete request. 1065 * @is_delete: True if it is a delete request.
1080 * 1066 *
1081 * Returns 0 on success, negative value otherwise. 1067 * Returns 0 on success, negative value otherwise.
1068 *
1069 * Caller holds tomoyo_read_lock().
1082 */ 1070 */
1083static int tomoyo_update_manager_entry(const char *manager, 1071static int tomoyo_update_manager_entry(const char *manager,
1084 const bool is_delete) 1072 const bool is_delete)
1085{ 1073{
1086 struct tomoyo_policy_manager_entry *new_entry; 1074 struct tomoyo_policy_manager_entry *entry = NULL;
1087 struct tomoyo_policy_manager_entry *ptr; 1075 struct tomoyo_policy_manager_entry *ptr;
1088 const struct tomoyo_path_info *saved_manager; 1076 const struct tomoyo_path_info *saved_manager;
1089 int error = -ENOMEM; 1077 int error = is_delete ? -ENOENT : -ENOMEM;
1090 bool is_domain = false; 1078 bool is_domain = false;
1091 1079
1092 if (tomoyo_is_domain_def(manager)) { 1080 if (tomoyo_is_domain_def(manager)) {
1093 if (!tomoyo_is_correct_domain(manager, __func__)) 1081 if (!tomoyo_is_correct_domain(manager))
1094 return -EINVAL; 1082 return -EINVAL;
1095 is_domain = true; 1083 is_domain = true;
1096 } else { 1084 } else {
1097 if (!tomoyo_is_correct_path(manager, 1, -1, -1, __func__)) 1085 if (!tomoyo_is_correct_path(manager, 1, -1, -1))
1098 return -EINVAL; 1086 return -EINVAL;
1099 } 1087 }
1100 saved_manager = tomoyo_save_name(manager); 1088 saved_manager = tomoyo_get_name(manager);
1101 if (!saved_manager) 1089 if (!saved_manager)
1102 return -ENOMEM; 1090 return -ENOMEM;
1103 down_write(&tomoyo_policy_manager_list_lock); 1091 if (!is_delete)
1104 list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) { 1092 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
1093 mutex_lock(&tomoyo_policy_lock);
1094 list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) {
1105 if (ptr->manager != saved_manager) 1095 if (ptr->manager != saved_manager)
1106 continue; 1096 continue;
1107 ptr->is_deleted = is_delete; 1097 ptr->is_deleted = is_delete;
1108 error = 0; 1098 error = 0;
1109 goto out; 1099 break;
1110 } 1100 }
1111 if (is_delete) { 1101 if (!is_delete && error && tomoyo_memory_ok(entry)) {
1112 error = -ENOENT; 1102 entry->manager = saved_manager;
1113 goto out; 1103 saved_manager = NULL;
1104 entry->is_domain = is_domain;
1105 list_add_tail_rcu(&entry->list, &tomoyo_policy_manager_list);
1106 entry = NULL;
1107 error = 0;
1114 } 1108 }
1115 new_entry = tomoyo_alloc_element(sizeof(*new_entry)); 1109 mutex_unlock(&tomoyo_policy_lock);
1116 if (!new_entry) 1110 tomoyo_put_name(saved_manager);
1117 goto out; 1111 kfree(entry);
1118 new_entry->manager = saved_manager;
1119 new_entry->is_domain = is_domain;
1120 list_add_tail(&new_entry->list, &tomoyo_policy_manager_list);
1121 error = 0;
1122 out:
1123 up_write(&tomoyo_policy_manager_list_lock);
1124 return error; 1112 return error;
1125} 1113}
1126 1114
@@ -1130,6 +1118,8 @@ static int tomoyo_update_manager_entry(const char *manager,
1130 * @head: Pointer to "struct tomoyo_io_buffer". 1118 * @head: Pointer to "struct tomoyo_io_buffer".
1131 * 1119 *
1132 * Returns 0 on success, negative value otherwise. 1120 * Returns 0 on success, negative value otherwise.
1121 *
1122 * Caller holds tomoyo_read_lock().
1133 */ 1123 */
1134static int tomoyo_write_manager_policy(struct tomoyo_io_buffer *head) 1124static int tomoyo_write_manager_policy(struct tomoyo_io_buffer *head)
1135{ 1125{
@@ -1149,6 +1139,8 @@ static int tomoyo_write_manager_policy(struct tomoyo_io_buffer *head)
1149 * @head: Pointer to "struct tomoyo_io_buffer". 1139 * @head: Pointer to "struct tomoyo_io_buffer".
1150 * 1140 *
1151 * Returns 0. 1141 * Returns 0.
1142 *
1143 * Caller holds tomoyo_read_lock().
1152 */ 1144 */
1153static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head) 1145static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head)
1154{ 1146{
@@ -1157,7 +1149,6 @@ static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head)
1157 1149
1158 if (head->read_eof) 1150 if (head->read_eof)
1159 return 0; 1151 return 0;
1160 down_read(&tomoyo_policy_manager_list_lock);
1161 list_for_each_cookie(pos, head->read_var2, 1152 list_for_each_cookie(pos, head->read_var2,
1162 &tomoyo_policy_manager_list) { 1153 &tomoyo_policy_manager_list) {
1163 struct tomoyo_policy_manager_entry *ptr; 1154 struct tomoyo_policy_manager_entry *ptr;
@@ -1169,7 +1160,6 @@ static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head)
1169 if (!done) 1160 if (!done)
1170 break; 1161 break;
1171 } 1162 }
1172 up_read(&tomoyo_policy_manager_list_lock);
1173 head->read_eof = done; 1163 head->read_eof = done;
1174 return 0; 1164 return 0;
1175} 1165}
@@ -1179,6 +1169,8 @@ static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head)
1179 * 1169 *
1180 * Returns true if the current process is permitted to modify policy 1170 * Returns true if the current process is permitted to modify policy
1181 * via /sys/kernel/security/tomoyo/ interface. 1171 * via /sys/kernel/security/tomoyo/ interface.
1172 *
1173 * Caller holds tomoyo_read_lock().
1182 */ 1174 */
1183static bool tomoyo_is_policy_manager(void) 1175static bool tomoyo_is_policy_manager(void)
1184{ 1176{
@@ -1192,29 +1184,25 @@ static bool tomoyo_is_policy_manager(void)
1192 return true; 1184 return true;
1193 if (!tomoyo_manage_by_non_root && (task->cred->uid || task->cred->euid)) 1185 if (!tomoyo_manage_by_non_root && (task->cred->uid || task->cred->euid))
1194 return false; 1186 return false;
1195 down_read(&tomoyo_policy_manager_list_lock); 1187 list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) {
1196 list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) {
1197 if (!ptr->is_deleted && ptr->is_domain 1188 if (!ptr->is_deleted && ptr->is_domain
1198 && !tomoyo_pathcmp(domainname, ptr->manager)) { 1189 && !tomoyo_pathcmp(domainname, ptr->manager)) {
1199 found = true; 1190 found = true;
1200 break; 1191 break;
1201 } 1192 }
1202 } 1193 }
1203 up_read(&tomoyo_policy_manager_list_lock);
1204 if (found) 1194 if (found)
1205 return true; 1195 return true;
1206 exe = tomoyo_get_exe(); 1196 exe = tomoyo_get_exe();
1207 if (!exe) 1197 if (!exe)
1208 return false; 1198 return false;
1209 down_read(&tomoyo_policy_manager_list_lock); 1199 list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) {
1210 list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) {
1211 if (!ptr->is_deleted && !ptr->is_domain 1200 if (!ptr->is_deleted && !ptr->is_domain
1212 && !strcmp(exe, ptr->manager->name)) { 1201 && !strcmp(exe, ptr->manager->name)) {
1213 found = true; 1202 found = true;
1214 break; 1203 break;
1215 } 1204 }
1216 } 1205 }
1217 up_read(&tomoyo_policy_manager_list_lock);
1218 if (!found) { /* Reduce error messages. */ 1206 if (!found) { /* Reduce error messages. */
1219 static pid_t last_pid; 1207 static pid_t last_pid;
1220 const pid_t pid = current->pid; 1208 const pid_t pid = current->pid;
@@ -1224,7 +1212,7 @@ static bool tomoyo_is_policy_manager(void)
1224 last_pid = pid; 1212 last_pid = pid;
1225 } 1213 }
1226 } 1214 }
1227 tomoyo_free(exe); 1215 kfree(exe);
1228 return found; 1216 return found;
1229} 1217}
1230 1218
@@ -1235,6 +1223,8 @@ static bool tomoyo_is_policy_manager(void)
1235 * @data: String to parse. 1223 * @data: String to parse.
1236 * 1224 *
1237 * Returns true on success, false otherwise. 1225 * Returns true on success, false otherwise.
1226 *
1227 * Caller holds tomoyo_read_lock().
1238 */ 1228 */
1239static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head, 1229static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head,
1240 const char *data) 1230 const char *data)
@@ -1244,17 +1234,16 @@ static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head,
1244 1234
1245 if (sscanf(data, "pid=%u", &pid) == 1) { 1235 if (sscanf(data, "pid=%u", &pid) == 1) {
1246 struct task_struct *p; 1236 struct task_struct *p;
1237 rcu_read_lock();
1247 read_lock(&tasklist_lock); 1238 read_lock(&tasklist_lock);
1248 p = find_task_by_vpid(pid); 1239 p = find_task_by_vpid(pid);
1249 if (p) 1240 if (p)
1250 domain = tomoyo_real_domain(p); 1241 domain = tomoyo_real_domain(p);
1251 read_unlock(&tasklist_lock); 1242 read_unlock(&tasklist_lock);
1243 rcu_read_unlock();
1252 } else if (!strncmp(data, "domain=", 7)) { 1244 } else if (!strncmp(data, "domain=", 7)) {
1253 if (tomoyo_is_domain_def(data + 7)) { 1245 if (tomoyo_is_domain_def(data + 7))
1254 down_read(&tomoyo_domain_list_lock);
1255 domain = tomoyo_find_domain(data + 7); 1246 domain = tomoyo_find_domain(data + 7);
1256 up_read(&tomoyo_domain_list_lock);
1257 }
1258 } else 1247 } else
1259 return false; 1248 return false;
1260 head->write_var1 = domain; 1249 head->write_var1 = domain;
@@ -1268,13 +1257,11 @@ static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head,
1268 if (domain) { 1257 if (domain) {
1269 struct tomoyo_domain_info *d; 1258 struct tomoyo_domain_info *d;
1270 head->read_var1 = NULL; 1259 head->read_var1 = NULL;
1271 down_read(&tomoyo_domain_list_lock); 1260 list_for_each_entry_rcu(d, &tomoyo_domain_list, list) {
1272 list_for_each_entry(d, &tomoyo_domain_list, list) {
1273 if (d == domain) 1261 if (d == domain)
1274 break; 1262 break;
1275 head->read_var1 = &d->list; 1263 head->read_var1 = &d->list;
1276 } 1264 }
1277 up_read(&tomoyo_domain_list_lock);
1278 head->read_var2 = NULL; 1265 head->read_var2 = NULL;
1279 head->read_bit = 0; 1266 head->read_bit = 0;
1280 head->read_step = 0; 1267 head->read_step = 0;
@@ -1290,6 +1277,8 @@ static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head,
1290 * @domainname: The name of domain. 1277 * @domainname: The name of domain.
1291 * 1278 *
1292 * Returns 0. 1279 * Returns 0.
1280 *
1281 * Caller holds tomoyo_read_lock().
1293 */ 1282 */
1294static int tomoyo_delete_domain(char *domainname) 1283static int tomoyo_delete_domain(char *domainname)
1295{ 1284{
@@ -1298,9 +1287,9 @@ static int tomoyo_delete_domain(char *domainname)
1298 1287
1299 name.name = domainname; 1288 name.name = domainname;
1300 tomoyo_fill_path_info(&name); 1289 tomoyo_fill_path_info(&name);
1301 down_write(&tomoyo_domain_list_lock); 1290 mutex_lock(&tomoyo_policy_lock);
1302 /* Is there an active domain? */ 1291 /* Is there an active domain? */
1303 list_for_each_entry(domain, &tomoyo_domain_list, list) { 1292 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
1304 /* Never delete tomoyo_kernel_domain */ 1293 /* Never delete tomoyo_kernel_domain */
1305 if (domain == &tomoyo_kernel_domain) 1294 if (domain == &tomoyo_kernel_domain)
1306 continue; 1295 continue;
@@ -1310,7 +1299,7 @@ static int tomoyo_delete_domain(char *domainname)
1310 domain->is_deleted = true; 1299 domain->is_deleted = true;
1311 break; 1300 break;
1312 } 1301 }
1313 up_write(&tomoyo_domain_list_lock); 1302 mutex_unlock(&tomoyo_policy_lock);
1314 return 0; 1303 return 0;
1315} 1304}
1316 1305
@@ -1320,6 +1309,8 @@ static int tomoyo_delete_domain(char *domainname)
1320 * @head: Pointer to "struct tomoyo_io_buffer". 1309 * @head: Pointer to "struct tomoyo_io_buffer".
1321 * 1310 *
1322 * Returns 0 on success, negative value otherwise. 1311 * Returns 0 on success, negative value otherwise.
1312 *
1313 * Caller holds tomoyo_read_lock().
1323 */ 1314 */
1324static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head) 1315static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head)
1325{ 1316{
@@ -1342,11 +1333,9 @@ static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head)
1342 domain = NULL; 1333 domain = NULL;
1343 if (is_delete) 1334 if (is_delete)
1344 tomoyo_delete_domain(data); 1335 tomoyo_delete_domain(data);
1345 else if (is_select) { 1336 else if (is_select)
1346 down_read(&tomoyo_domain_list_lock);
1347 domain = tomoyo_find_domain(data); 1337 domain = tomoyo_find_domain(data);
1348 up_read(&tomoyo_domain_list_lock); 1338 else
1349 } else
1350 domain = tomoyo_find_or_assign_new_domain(data, 0); 1339 domain = tomoyo_find_or_assign_new_domain(data, 0);
1351 head->write_var1 = domain; 1340 head->write_var1 = domain;
1352 return 0; 1341 return 0;
@@ -1361,43 +1350,39 @@ static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head)
1361 return 0; 1350 return 0;
1362 } 1351 }
1363 if (!strcmp(data, TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) { 1352 if (!strcmp(data, TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) {
1364 tomoyo_set_domain_flag(domain, is_delete, 1353 domain->ignore_global_allow_read = !is_delete;
1365 TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ);
1366 return 0; 1354 return 0;
1367 } 1355 }
1368 return tomoyo_write_file_policy(data, domain, is_delete); 1356 return tomoyo_write_file_policy(data, domain, is_delete);
1369} 1357}
1370 1358
1371/** 1359/**
1372 * tomoyo_print_single_path_acl - Print a single path ACL entry. 1360 * tomoyo_print_path_acl - Print a single path ACL entry.
1373 * 1361 *
1374 * @head: Pointer to "struct tomoyo_io_buffer". 1362 * @head: Pointer to "struct tomoyo_io_buffer".
1375 * @ptr: Pointer to "struct tomoyo_single_path_acl_record". 1363 * @ptr: Pointer to "struct tomoyo_path_acl".
1376 * 1364 *
1377 * Returns true on success, false otherwise. 1365 * Returns true on success, false otherwise.
1378 */ 1366 */
1379static bool tomoyo_print_single_path_acl(struct tomoyo_io_buffer *head, 1367static bool tomoyo_print_path_acl(struct tomoyo_io_buffer *head,
1380 struct tomoyo_single_path_acl_record * 1368 struct tomoyo_path_acl *ptr)
1381 ptr)
1382{ 1369{
1383 int pos; 1370 int pos;
1384 u8 bit; 1371 u8 bit;
1385 const char *atmark = ""; 1372 const char *atmark = "";
1386 const char *filename; 1373 const char *filename;
1387 const u16 perm = ptr->perm; 1374 const u32 perm = ptr->perm | (((u32) ptr->perm_high) << 16);
1388 1375
1389 filename = ptr->filename->name; 1376 filename = ptr->filename->name;
1390 for (bit = head->read_bit; bit < TOMOYO_MAX_SINGLE_PATH_OPERATION; 1377 for (bit = head->read_bit; bit < TOMOYO_MAX_PATH_OPERATION; bit++) {
1391 bit++) {
1392 const char *msg; 1378 const char *msg;
1393 if (!(perm & (1 << bit))) 1379 if (!(perm & (1 << bit)))
1394 continue; 1380 continue;
1395 /* Print "read/write" instead of "read" and "write". */ 1381 /* Print "read/write" instead of "read" and "write". */
1396 if ((bit == TOMOYO_TYPE_READ_ACL || 1382 if ((bit == TOMOYO_TYPE_READ || bit == TOMOYO_TYPE_WRITE)
1397 bit == TOMOYO_TYPE_WRITE_ACL) 1383 && (perm & (1 << TOMOYO_TYPE_READ_WRITE)))
1398 && (perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)))
1399 continue; 1384 continue;
1400 msg = tomoyo_sp2keyword(bit); 1385 msg = tomoyo_path2keyword(bit);
1401 pos = head->read_avail; 1386 pos = head->read_avail;
1402 if (!tomoyo_io_printf(head, "allow_%s %s%s\n", msg, 1387 if (!tomoyo_io_printf(head, "allow_%s %s%s\n", msg,
1403 atmark, filename)) 1388 atmark, filename))
@@ -1412,16 +1397,15 @@ static bool tomoyo_print_single_path_acl(struct tomoyo_io_buffer *head,
1412} 1397}
1413 1398
1414/** 1399/**
1415 * tomoyo_print_double_path_acl - Print a double path ACL entry. 1400 * tomoyo_print_path2_acl - Print a double path ACL entry.
1416 * 1401 *
1417 * @head: Pointer to "struct tomoyo_io_buffer". 1402 * @head: Pointer to "struct tomoyo_io_buffer".
1418 * @ptr: Pointer to "struct tomoyo_double_path_acl_record". 1403 * @ptr: Pointer to "struct tomoyo_path2_acl".
1419 * 1404 *
1420 * Returns true on success, false otherwise. 1405 * Returns true on success, false otherwise.
1421 */ 1406 */
1422static bool tomoyo_print_double_path_acl(struct tomoyo_io_buffer *head, 1407static bool tomoyo_print_path2_acl(struct tomoyo_io_buffer *head,
1423 struct tomoyo_double_path_acl_record * 1408 struct tomoyo_path2_acl *ptr)
1424 ptr)
1425{ 1409{
1426 int pos; 1410 int pos;
1427 const char *atmark1 = ""; 1411 const char *atmark1 = "";
@@ -1433,12 +1417,11 @@ static bool tomoyo_print_double_path_acl(struct tomoyo_io_buffer *head,
1433 1417
1434 filename1 = ptr->filename1->name; 1418 filename1 = ptr->filename1->name;
1435 filename2 = ptr->filename2->name; 1419 filename2 = ptr->filename2->name;
1436 for (bit = head->read_bit; bit < TOMOYO_MAX_DOUBLE_PATH_OPERATION; 1420 for (bit = head->read_bit; bit < TOMOYO_MAX_PATH2_OPERATION; bit++) {
1437 bit++) {
1438 const char *msg; 1421 const char *msg;
1439 if (!(perm & (1 << bit))) 1422 if (!(perm & (1 << bit)))
1440 continue; 1423 continue;
1441 msg = tomoyo_dp2keyword(bit); 1424 msg = tomoyo_path22keyword(bit);
1442 pos = head->read_avail; 1425 pos = head->read_avail;
1443 if (!tomoyo_io_printf(head, "allow_%s %s%s %s%s\n", msg, 1426 if (!tomoyo_io_printf(head, "allow_%s %s%s %s%s\n", msg,
1444 atmark1, filename1, atmark2, filename2)) 1427 atmark1, filename1, atmark2, filename2))
@@ -1463,23 +1446,17 @@ static bool tomoyo_print_double_path_acl(struct tomoyo_io_buffer *head,
1463static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, 1446static bool tomoyo_print_entry(struct tomoyo_io_buffer *head,
1464 struct tomoyo_acl_info *ptr) 1447 struct tomoyo_acl_info *ptr)
1465{ 1448{
1466 const u8 acl_type = tomoyo_acl_type2(ptr); 1449 const u8 acl_type = ptr->type;
1467 1450
1468 if (acl_type & TOMOYO_ACL_DELETED) 1451 if (acl_type == TOMOYO_TYPE_PATH_ACL) {
1469 return true; 1452 struct tomoyo_path_acl *acl
1470 if (acl_type == TOMOYO_TYPE_SINGLE_PATH_ACL) { 1453 = container_of(ptr, struct tomoyo_path_acl, head);
1471 struct tomoyo_single_path_acl_record *acl 1454 return tomoyo_print_path_acl(head, acl);
1472 = container_of(ptr,
1473 struct tomoyo_single_path_acl_record,
1474 head);
1475 return tomoyo_print_single_path_acl(head, acl);
1476 } 1455 }
1477 if (acl_type == TOMOYO_TYPE_DOUBLE_PATH_ACL) { 1456 if (acl_type == TOMOYO_TYPE_PATH2_ACL) {
1478 struct tomoyo_double_path_acl_record *acl 1457 struct tomoyo_path2_acl *acl
1479 = container_of(ptr, 1458 = container_of(ptr, struct tomoyo_path2_acl, head);
1480 struct tomoyo_double_path_acl_record, 1459 return tomoyo_print_path2_acl(head, acl);
1481 head);
1482 return tomoyo_print_double_path_acl(head, acl);
1483 } 1460 }
1484 BUG(); /* This must not happen. */ 1461 BUG(); /* This must not happen. */
1485 return false; 1462 return false;
@@ -1491,6 +1468,8 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head,
1491 * @head: Pointer to "struct tomoyo_io_buffer". 1468 * @head: Pointer to "struct tomoyo_io_buffer".
1492 * 1469 *
1493 * Returns 0. 1470 * Returns 0.
1471 *
1472 * Caller holds tomoyo_read_lock().
1494 */ 1473 */
1495static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head) 1474static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head)
1496{ 1475{
@@ -1502,7 +1481,6 @@ static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head)
1502 return 0; 1481 return 0;
1503 if (head->read_step == 0) 1482 if (head->read_step == 0)
1504 head->read_step = 1; 1483 head->read_step = 1;
1505 down_read(&tomoyo_domain_list_lock);
1506 list_for_each_cookie(dpos, head->read_var1, &tomoyo_domain_list) { 1484 list_for_each_cookie(dpos, head->read_var1, &tomoyo_domain_list) {
1507 struct tomoyo_domain_info *domain; 1485 struct tomoyo_domain_info *domain;
1508 const char *quota_exceeded = ""; 1486 const char *quota_exceeded = "";
@@ -1516,10 +1494,9 @@ static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head)
1516 /* Print domainname and flags. */ 1494 /* Print domainname and flags. */
1517 if (domain->quota_warned) 1495 if (domain->quota_warned)
1518 quota_exceeded = "quota_exceeded\n"; 1496 quota_exceeded = "quota_exceeded\n";
1519 if (domain->flags & TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED) 1497 if (domain->transition_failed)
1520 transition_failed = "transition_failed\n"; 1498 transition_failed = "transition_failed\n";
1521 if (domain->flags & 1499 if (domain->ignore_global_allow_read)
1522 TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ)
1523 ignore_global_allow_read 1500 ignore_global_allow_read
1524 = TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n"; 1501 = TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n";
1525 done = tomoyo_io_printf(head, "%s\n" TOMOYO_KEYWORD_USE_PROFILE 1502 done = tomoyo_io_printf(head, "%s\n" TOMOYO_KEYWORD_USE_PROFILE
@@ -1535,7 +1512,6 @@ acl_loop:
1535 if (head->read_step == 3) 1512 if (head->read_step == 3)
1536 goto tail_mark; 1513 goto tail_mark;
1537 /* Print ACL entries in the domain. */ 1514 /* Print ACL entries in the domain. */
1538 down_read(&tomoyo_domain_acl_info_list_lock);
1539 list_for_each_cookie(apos, head->read_var2, 1515 list_for_each_cookie(apos, head->read_var2,
1540 &domain->acl_info_list) { 1516 &domain->acl_info_list) {
1541 struct tomoyo_acl_info *ptr 1517 struct tomoyo_acl_info *ptr
@@ -1545,7 +1521,6 @@ acl_loop:
1545 if (!done) 1521 if (!done)
1546 break; 1522 break;
1547 } 1523 }
1548 up_read(&tomoyo_domain_acl_info_list_lock);
1549 if (!done) 1524 if (!done)
1550 break; 1525 break;
1551 head->read_step = 3; 1526 head->read_step = 3;
@@ -1557,7 +1532,6 @@ tail_mark:
1557 if (head->read_single_domain) 1532 if (head->read_single_domain)
1558 break; 1533 break;
1559 } 1534 }
1560 up_read(&tomoyo_domain_list_lock);
1561 head->read_eof = done; 1535 head->read_eof = done;
1562 return 0; 1536 return 0;
1563} 1537}
@@ -1573,6 +1547,8 @@ tail_mark:
1573 * 1547 *
1574 * ( echo "select " $domainname; echo "use_profile " $profile ) | 1548 * ( echo "select " $domainname; echo "use_profile " $profile ) |
1575 * /usr/lib/ccs/loadpolicy -d 1549 * /usr/lib/ccs/loadpolicy -d
1550 *
1551 * Caller holds tomoyo_read_lock().
1576 */ 1552 */
1577static int tomoyo_write_domain_profile(struct tomoyo_io_buffer *head) 1553static int tomoyo_write_domain_profile(struct tomoyo_io_buffer *head)
1578{ 1554{
@@ -1584,9 +1560,7 @@ static int tomoyo_write_domain_profile(struct tomoyo_io_buffer *head)
1584 if (!cp) 1560 if (!cp)
1585 return -EINVAL; 1561 return -EINVAL;
1586 *cp = '\0'; 1562 *cp = '\0';
1587 down_read(&tomoyo_domain_list_lock);
1588 domain = tomoyo_find_domain(cp + 1); 1563 domain = tomoyo_find_domain(cp + 1);
1589 up_read(&tomoyo_domain_list_lock);
1590 if (strict_strtoul(data, 10, &profile)) 1564 if (strict_strtoul(data, 10, &profile))
1591 return -EINVAL; 1565 return -EINVAL;
1592 if (domain && profile < TOMOYO_MAX_PROFILES 1566 if (domain && profile < TOMOYO_MAX_PROFILES
@@ -1608,6 +1582,8 @@ static int tomoyo_write_domain_profile(struct tomoyo_io_buffer *head)
1608 * awk ' { if ( domainname == "" ) { if ( $1 == "<kernel>" ) 1582 * awk ' { if ( domainname == "" ) { if ( $1 == "<kernel>" )
1609 * domainname = $0; } else if ( $1 == "use_profile" ) { 1583 * domainname = $0; } else if ( $1 == "use_profile" ) {
1610 * print $2 " " domainname; domainname = ""; } } ; ' 1584 * print $2 " " domainname; domainname = ""; } } ; '
1585 *
1586 * Caller holds tomoyo_read_lock().
1611 */ 1587 */
1612static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head) 1588static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head)
1613{ 1589{
@@ -1616,7 +1592,6 @@ static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head)
1616 1592
1617 if (head->read_eof) 1593 if (head->read_eof)
1618 return 0; 1594 return 0;
1619 down_read(&tomoyo_domain_list_lock);
1620 list_for_each_cookie(pos, head->read_var1, &tomoyo_domain_list) { 1595 list_for_each_cookie(pos, head->read_var1, &tomoyo_domain_list) {
1621 struct tomoyo_domain_info *domain; 1596 struct tomoyo_domain_info *domain;
1622 domain = list_entry(pos, struct tomoyo_domain_info, list); 1597 domain = list_entry(pos, struct tomoyo_domain_info, list);
@@ -1627,7 +1602,6 @@ static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head)
1627 if (!done) 1602 if (!done)
1628 break; 1603 break;
1629 } 1604 }
1630 up_read(&tomoyo_domain_list_lock);
1631 head->read_eof = done; 1605 head->read_eof = done;
1632 return 0; 1606 return 0;
1633} 1607}
@@ -1665,11 +1639,13 @@ static int tomoyo_read_pid(struct tomoyo_io_buffer *head)
1665 const int pid = head->read_step; 1639 const int pid = head->read_step;
1666 struct task_struct *p; 1640 struct task_struct *p;
1667 struct tomoyo_domain_info *domain = NULL; 1641 struct tomoyo_domain_info *domain = NULL;
1642 rcu_read_lock();
1668 read_lock(&tasklist_lock); 1643 read_lock(&tasklist_lock);
1669 p = find_task_by_vpid(pid); 1644 p = find_task_by_vpid(pid);
1670 if (p) 1645 if (p)
1671 domain = tomoyo_real_domain(p); 1646 domain = tomoyo_real_domain(p);
1672 read_unlock(&tasklist_lock); 1647 read_unlock(&tasklist_lock);
1648 rcu_read_unlock();
1673 if (domain) 1649 if (domain)
1674 tomoyo_io_printf(head, "%d %u %s", pid, domain->profile, 1650 tomoyo_io_printf(head, "%d %u %s", pid, domain->profile,
1675 domain->domainname->name); 1651 domain->domainname->name);
@@ -1684,6 +1660,8 @@ static int tomoyo_read_pid(struct tomoyo_io_buffer *head)
1684 * @head: Pointer to "struct tomoyo_io_buffer". 1660 * @head: Pointer to "struct tomoyo_io_buffer".
1685 * 1661 *
1686 * Returns 0 on success, negative value otherwise. 1662 * Returns 0 on success, negative value otherwise.
1663 *
1664 * Caller holds tomoyo_read_lock().
1687 */ 1665 */
1688static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head) 1666static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head)
1689{ 1667{
@@ -1718,6 +1696,8 @@ static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head)
1718 * @head: Pointer to "struct tomoyo_io_buffer". 1696 * @head: Pointer to "struct tomoyo_io_buffer".
1719 * 1697 *
1720 * Returns 0 on success, -EINVAL otherwise. 1698 * Returns 0 on success, -EINVAL otherwise.
1699 *
1700 * Caller holds tomoyo_read_lock().
1721 */ 1701 */
1722static int tomoyo_read_exception_policy(struct tomoyo_io_buffer *head) 1702static int tomoyo_read_exception_policy(struct tomoyo_io_buffer *head)
1723{ 1703{
@@ -1847,15 +1827,13 @@ void tomoyo_load_policy(const char *filename)
1847 tomoyo_policy_loaded = true; 1827 tomoyo_policy_loaded = true;
1848 { /* Check all profiles currently assigned to domains are defined. */ 1828 { /* Check all profiles currently assigned to domains are defined. */
1849 struct tomoyo_domain_info *domain; 1829 struct tomoyo_domain_info *domain;
1850 down_read(&tomoyo_domain_list_lock); 1830 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
1851 list_for_each_entry(domain, &tomoyo_domain_list, list) {
1852 const u8 profile = domain->profile; 1831 const u8 profile = domain->profile;
1853 if (tomoyo_profile_ptr[profile]) 1832 if (tomoyo_profile_ptr[profile])
1854 continue; 1833 continue;
1855 panic("Profile %u (used by '%s') not defined.\n", 1834 panic("Profile %u (used by '%s') not defined.\n",
1856 profile, domain->domainname->name); 1835 profile, domain->domainname->name);
1857 } 1836 }
1858 up_read(&tomoyo_domain_list_lock);
1859 } 1837 }
1860} 1838}
1861 1839
@@ -1903,10 +1881,12 @@ static int tomoyo_read_self_domain(struct tomoyo_io_buffer *head)
1903 * @file: Pointer to "struct file". 1881 * @file: Pointer to "struct file".
1904 * 1882 *
1905 * Associates policy handler and returns 0 on success, -ENOMEM otherwise. 1883 * Associates policy handler and returns 0 on success, -ENOMEM otherwise.
1884 *
1885 * Caller acquires tomoyo_read_lock().
1906 */ 1886 */
1907static int tomoyo_open_control(const u8 type, struct file *file) 1887static int tomoyo_open_control(const u8 type, struct file *file)
1908{ 1888{
1909 struct tomoyo_io_buffer *head = tomoyo_alloc(sizeof(*head)); 1889 struct tomoyo_io_buffer *head = kzalloc(sizeof(*head), GFP_KERNEL);
1910 1890
1911 if (!head) 1891 if (!head)
1912 return -ENOMEM; 1892 return -ENOMEM;
@@ -1967,9 +1947,9 @@ static int tomoyo_open_control(const u8 type, struct file *file)
1967 } else { 1947 } else {
1968 if (!head->readbuf_size) 1948 if (!head->readbuf_size)
1969 head->readbuf_size = 4096 * 2; 1949 head->readbuf_size = 4096 * 2;
1970 head->read_buf = tomoyo_alloc(head->readbuf_size); 1950 head->read_buf = kzalloc(head->readbuf_size, GFP_KERNEL);
1971 if (!head->read_buf) { 1951 if (!head->read_buf) {
1972 tomoyo_free(head); 1952 kfree(head);
1973 return -ENOMEM; 1953 return -ENOMEM;
1974 } 1954 }
1975 } 1955 }
@@ -1981,13 +1961,14 @@ static int tomoyo_open_control(const u8 type, struct file *file)
1981 head->write = NULL; 1961 head->write = NULL;
1982 } else if (head->write) { 1962 } else if (head->write) {
1983 head->writebuf_size = 4096 * 2; 1963 head->writebuf_size = 4096 * 2;
1984 head->write_buf = tomoyo_alloc(head->writebuf_size); 1964 head->write_buf = kzalloc(head->writebuf_size, GFP_KERNEL);
1985 if (!head->write_buf) { 1965 if (!head->write_buf) {
1986 tomoyo_free(head->read_buf); 1966 kfree(head->read_buf);
1987 tomoyo_free(head); 1967 kfree(head);
1988 return -ENOMEM; 1968 return -ENOMEM;
1989 } 1969 }
1990 } 1970 }
1971 head->reader_idx = tomoyo_read_lock();
1991 file->private_data = head; 1972 file->private_data = head;
1992 /* 1973 /*
1993 * Call the handler now if the file is 1974 * Call the handler now if the file is
@@ -2009,6 +1990,8 @@ static int tomoyo_open_control(const u8 type, struct file *file)
2009 * @buffer_len: Size of @buffer. 1990 * @buffer_len: Size of @buffer.
2010 * 1991 *
2011 * Returns bytes read on success, negative value otherwise. 1992 * Returns bytes read on success, negative value otherwise.
1993 *
1994 * Caller holds tomoyo_read_lock().
2012 */ 1995 */
2013static int tomoyo_read_control(struct file *file, char __user *buffer, 1996static int tomoyo_read_control(struct file *file, char __user *buffer,
2014 const int buffer_len) 1997 const int buffer_len)
@@ -2052,6 +2035,8 @@ static int tomoyo_read_control(struct file *file, char __user *buffer,
2052 * @buffer_len: Size of @buffer. 2035 * @buffer_len: Size of @buffer.
2053 * 2036 *
2054 * Returns @buffer_len on success, negative value otherwise. 2037 * Returns @buffer_len on success, negative value otherwise.
2038 *
2039 * Caller holds tomoyo_read_lock().
2055 */ 2040 */
2056static int tomoyo_write_control(struct file *file, const char __user *buffer, 2041static int tomoyo_write_control(struct file *file, const char __user *buffer,
2057 const int buffer_len) 2042 const int buffer_len)
@@ -2102,52 +2087,29 @@ static int tomoyo_write_control(struct file *file, const char __user *buffer,
2102 * @file: Pointer to "struct file". 2087 * @file: Pointer to "struct file".
2103 * 2088 *
2104 * Releases memory and returns 0. 2089 * Releases memory and returns 0.
2090 *
2091 * Caller looses tomoyo_read_lock().
2105 */ 2092 */
2106static int tomoyo_close_control(struct file *file) 2093static int tomoyo_close_control(struct file *file)
2107{ 2094{
2108 struct tomoyo_io_buffer *head = file->private_data; 2095 struct tomoyo_io_buffer *head = file->private_data;
2096 const bool is_write = !!head->write_buf;
2109 2097
2098 tomoyo_read_unlock(head->reader_idx);
2110 /* Release memory used for policy I/O. */ 2099 /* Release memory used for policy I/O. */
2111 tomoyo_free(head->read_buf); 2100 kfree(head->read_buf);
2112 head->read_buf = NULL; 2101 head->read_buf = NULL;
2113 tomoyo_free(head->write_buf); 2102 kfree(head->write_buf);
2114 head->write_buf = NULL; 2103 head->write_buf = NULL;
2115 tomoyo_free(head); 2104 kfree(head);
2116 head = NULL; 2105 head = NULL;
2117 file->private_data = NULL; 2106 file->private_data = NULL;
2107 if (is_write)
2108 tomoyo_run_gc();
2118 return 0; 2109 return 0;
2119} 2110}
2120 2111
2121/** 2112/**
2122 * tomoyo_alloc_acl_element - Allocate permanent memory for ACL entry.
2123 *
2124 * @acl_type: Type of ACL entry.
2125 *
2126 * Returns pointer to the ACL entry on success, NULL otherwise.
2127 */
2128void *tomoyo_alloc_acl_element(const u8 acl_type)
2129{
2130 int len;
2131 struct tomoyo_acl_info *ptr;
2132
2133 switch (acl_type) {
2134 case TOMOYO_TYPE_SINGLE_PATH_ACL:
2135 len = sizeof(struct tomoyo_single_path_acl_record);
2136 break;
2137 case TOMOYO_TYPE_DOUBLE_PATH_ACL:
2138 len = sizeof(struct tomoyo_double_path_acl_record);
2139 break;
2140 default:
2141 return NULL;
2142 }
2143 ptr = tomoyo_alloc_element(len);
2144 if (!ptr)
2145 return NULL;
2146 ptr->type = acl_type;
2147 return ptr;
2148}
2149
2150/**
2151 * tomoyo_open - open() for /sys/kernel/security/tomoyo/ interface. 2113 * tomoyo_open - open() for /sys/kernel/security/tomoyo/ interface.
2152 * 2114 *
2153 * @inode: Pointer to "struct inode". 2115 * @inode: Pointer to "struct inode".