Commit c3ef1500ec833890275172c7d063333404b64d60

Authored by Tetsuo Handa
Committed by James Morris
1 parent 17fcfbd9d4

TOMOYO: Split files into some pieces.

security/tomoyo/common.c became too large to read.

Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: James Morris <jmorris@namei.org>

Showing 11 changed files with 1469 additions and 1416 deletions Side-by-side Diff

security/tomoyo/Makefile
1   -obj-y = common.o realpath.o tomoyo.o domain.o file.o gc.o path_group.o number_group.o mount.o
  1 +obj-y = common.o domain.o file.o gc.o load_policy.o memory.o mount.o number_group.o path_group.o realpath.o securityfs_if.o tomoyo.o util.o
security/tomoyo/common.c
Changes suppressed. Click to show
... ... @@ -3,10 +3,7 @@
3 3 *
4 4 * Common functions for TOMOYO.
5 5 *
6   - * Copyright (C) 2005-2009 NTT DATA CORPORATION
7   - *
8   - * Version: 2.2.0 2009/04/01
9   - *
  6 + * Copyright (C) 2005-2010 NTT DATA CORPORATION
10 7 */
11 8  
12 9 #include <linux/uaccess.h>
... ... @@ -15,12 +12,6 @@
15 12 #include <linux/hardirq.h>
16 13 #include "common.h"
17 14  
18   -/* Lock for protecting policy. */
19   -DEFINE_MUTEX(tomoyo_policy_lock);
20   -
21   -/* Has loading policy done? */
22   -bool tomoyo_policy_loaded;
23   -
24 15 /* String table for functionality that takes 4 modes. */
25 16 static const char *tomoyo_mode_4[4] = {
26 17 "disabled", "learning", "permissive", "enforcing"
27 18  
... ... @@ -64,43 +55,7 @@
64 55  
65 56 /* Utility functions. */
66 57  
67   -/* Open operation for /sys/kernel/security/tomoyo/ interface. */
68   -static int tomoyo_open_control(const u8 type, struct file *file);
69   -/* Close /sys/kernel/security/tomoyo/ interface. */
70   -static int tomoyo_close_control(struct file *file);
71   -/* Read operation for /sys/kernel/security/tomoyo/ interface. */
72   -static int tomoyo_read_control(struct file *file, char __user *buffer,
73   - const int buffer_len);
74   -/* Write operation for /sys/kernel/security/tomoyo/ interface. */
75   -static int tomoyo_write_control(struct file *file, const char __user *buffer,
76   - const int buffer_len);
77   -/* Check whether the domain has too many ACL entries to hold. */
78   -static bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r);
79   -
80 58 /**
81   - * tomoyo_parse_name_union - Parse a tomoyo_name_union.
82   - *
83   - * @filename: Name or name group.
84   - * @ptr: Pointer to "struct tomoyo_name_union".
85   - *
86   - * Returns true on success, false otherwise.
87   - */
88   -bool tomoyo_parse_name_union(const char *filename,
89   - struct tomoyo_name_union *ptr)
90   -{
91   - if (!tomoyo_is_correct_path(filename, 0, 0, 0))
92   - return false;
93   - if (filename[0] == '@') {
94   - ptr->group = tomoyo_get_path_group(filename + 1);
95   - ptr->is_group = true;
96   - return ptr->group != NULL;
97   - }
98   - ptr->filename = tomoyo_get_name(filename);
99   - ptr->is_group = false;
100   - return ptr->filename != NULL;
101   -}
102   -
103   -/**
104 59 * tomoyo_print_name_union - Print a tomoyo_name_union.
105 60 *
106 61 * @head: Pointer to "struct tomoyo_io_buffer".
... ... @@ -121,69 +76,6 @@
121 76 }
122 77  
123 78 /**
124   - * tomoyo_parse_ulong - Parse an "unsigned long" value.
125   - *
126   - * @result: Pointer to "unsigned long".
127   - * @str: Pointer to string to parse.
128   - *
129   - * Returns value type on success, 0 otherwise.
130   - *
131   - * The @src is updated to point the first character after the value
132   - * on success.
133   - */
134   -u8 tomoyo_parse_ulong(unsigned long *result, char **str)
135   -{
136   - const char *cp = *str;
137   - char *ep;
138   - int base = 10;
139   - if (*cp == '0') {
140   - char c = *(cp + 1);
141   - if (c == 'x' || c == 'X') {
142   - base = 16;
143   - cp += 2;
144   - } else if (c >= '0' && c <= '7') {
145   - base = 8;
146   - cp++;
147   - }
148   - }
149   - *result = simple_strtoul(cp, &ep, base);
150   - if (cp == ep)
151   - return 0;
152   - *str = ep;
153   - switch (base) {
154   - case 16:
155   - return TOMOYO_VALUE_TYPE_HEXADECIMAL;
156   - case 8:
157   - return TOMOYO_VALUE_TYPE_OCTAL;
158   - default:
159   - return TOMOYO_VALUE_TYPE_DECIMAL;
160   - }
161   -}
162   -
163   -/**
164   - * tomoyo_print_ulong - Print an "unsigned long" value.
165   - *
166   - * @buffer: Pointer to buffer.
167   - * @buffer_len: Size of @buffer.
168   - * @value: An "unsigned long" value.
169   - * @type: Type of @value.
170   - *
171   - * Returns nothing.
172   - */
173   -void tomoyo_print_ulong(char *buffer, const int buffer_len,
174   - const unsigned long value, const u8 type)
175   -{
176   - if (type == TOMOYO_VALUE_TYPE_DECIMAL)
177   - snprintf(buffer, buffer_len, "%lu", value);
178   - else if (type == TOMOYO_VALUE_TYPE_OCTAL)
179   - snprintf(buffer, buffer_len, "0%lo", value);
180   - else if (type == TOMOYO_VALUE_TYPE_HEXADECIMAL)
181   - snprintf(buffer, buffer_len, "0x%lX", value);
182   - else
183   - snprintf(buffer, buffer_len, "type(%u)", type);
184   -}
185   -
186   -/**
187 79 * tomoyo_print_number_union - Print a tomoyo_number_union.
188 80 *
189 81 * @head: Pointer to "struct tomoyo_io_buffer".
... ... @@ -234,704 +126,6 @@
234 126 }
235 127  
236 128 /**
237   - * tomoyo_parse_number_union - Parse a tomoyo_number_union.
238   - *
239   - * @data: Number or number range or number group.
240   - * @ptr: Pointer to "struct tomoyo_number_union".
241   - *
242   - * Returns true on success, false otherwise.
243   - */
244   -bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num)
245   -{
246   - u8 type;
247   - unsigned long v;
248   - memset(num, 0, sizeof(*num));
249   - if (data[0] == '@') {
250   - if (!tomoyo_is_correct_path(data, 0, 0, 0))
251   - return false;
252   - num->group = tomoyo_get_number_group(data + 1);
253   - num->is_group = true;
254   - return num->group != NULL;
255   - }
256   - type = tomoyo_parse_ulong(&v, &data);
257   - if (!type)
258   - return false;
259   - num->values[0] = v;
260   - num->min_type = type;
261   - if (!*data) {
262   - num->values[1] = v;
263   - num->max_type = type;
264   - return true;
265   - }
266   - if (*data++ != '-')
267   - return false;
268   - type = tomoyo_parse_ulong(&v, &data);
269   - if (!type || *data)
270   - return false;
271   - num->values[1] = v;
272   - num->max_type = type;
273   - return true;
274   -}
275   -
276   -/**
277   - * tomoyo_is_byte_range - Check whether the string isa \ooo style octal value.
278   - *
279   - * @str: Pointer to the string.
280   - *
281   - * Returns true if @str is a \ooo style octal value, false otherwise.
282   - *
283   - * TOMOYO uses \ooo style representation for 0x01 - 0x20 and 0x7F - 0xFF.
284   - * This function verifies that \ooo is in valid range.
285   - */
286   -static inline bool tomoyo_is_byte_range(const char *str)
287   -{
288   - return *str >= '0' && *str++ <= '3' &&
289   - *str >= '0' && *str++ <= '7' &&
290   - *str >= '0' && *str <= '7';
291   -}
292   -
293   -/**
294   - * tomoyo_is_alphabet_char - Check whether the character is an alphabet.
295   - *
296   - * @c: The character to check.
297   - *
298   - * Returns true if @c is an alphabet character, false otherwise.
299   - */
300   -static inline bool tomoyo_is_alphabet_char(const char c)
301   -{
302   - return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
303   -}
304   -
305   -/**
306   - * tomoyo_make_byte - Make byte value from three octal characters.
307   - *
308   - * @c1: The first character.
309   - * @c2: The second character.
310   - * @c3: The third character.
311   - *
312   - * Returns byte value.
313   - */
314   -static inline u8 tomoyo_make_byte(const u8 c1, const u8 c2, const u8 c3)
315   -{
316   - return ((c1 - '0') << 6) + ((c2 - '0') << 3) + (c3 - '0');
317   -}
318   -
319   -/**
320   - * tomoyo_str_starts - Check whether the given string starts with the given keyword.
321   - *
322   - * @src: Pointer to pointer to the string.
323   - * @find: Pointer to the keyword.
324   - *
325   - * Returns true if @src starts with @find, false otherwise.
326   - *
327   - * The @src is updated to point the first character after the @find
328   - * if @src starts with @find.
329   - */
330   -static bool tomoyo_str_starts(char **src, const char *find)
331   -{
332   - const int len = strlen(find);
333   - char *tmp = *src;
334   -
335   - if (strncmp(tmp, find, len))
336   - return false;
337   - tmp += len;
338   - *src = tmp;
339   - return true;
340   -}
341   -
342   -/**
343   - * tomoyo_normalize_line - Format string.
344   - *
345   - * @buffer: The line to normalize.
346   - *
347   - * Leading and trailing whitespaces are removed.
348   - * Multiple whitespaces are packed into single space.
349   - *
350   - * Returns nothing.
351   - */
352   -static void tomoyo_normalize_line(unsigned char *buffer)
353   -{
354   - unsigned char *sp = buffer;
355   - unsigned char *dp = buffer;
356   - bool first = true;
357   -
358   - while (tomoyo_is_invalid(*sp))
359   - sp++;
360   - while (*sp) {
361   - if (!first)
362   - *dp++ = ' ';
363   - first = false;
364   - while (tomoyo_is_valid(*sp))
365   - *dp++ = *sp++;
366   - while (tomoyo_is_invalid(*sp))
367   - sp++;
368   - }
369   - *dp = '\0';
370   -}
371   -
372   -/**
373   - * tomoyo_tokenize - Tokenize string.
374   - *
375   - * @buffer: The line to tokenize.
376   - * @w: Pointer to "char *".
377   - * @size: Sizeof @w .
378   - *
379   - * Returns true on success, false otherwise.
380   - */
381   -bool tomoyo_tokenize(char *buffer, char *w[], size_t size)
382   -{
383   - int count = size / sizeof(char *);
384   - int i;
385   - for (i = 0; i < count; i++)
386   - w[i] = "";
387   - for (i = 0; i < count; i++) {
388   - char *cp = strchr(buffer, ' ');
389   - if (cp)
390   - *cp = '\0';
391   - w[i] = buffer;
392   - if (!cp)
393   - break;
394   - buffer = cp + 1;
395   - }
396   - return i < count || !*buffer;
397   -}
398   -
399   -/**
400   - * tomoyo_is_correct_path - Validate a pathname.
401   - * @filename: The pathname to check.
402   - * @start_type: Should the pathname start with '/'?
403   - * 1 = must / -1 = must not / 0 = don't care
404   - * @pattern_type: Can the pathname contain a wildcard?
405   - * 1 = must / -1 = must not / 0 = don't care
406   - * @end_type: Should the pathname end with '/'?
407   - * 1 = must / -1 = must not / 0 = don't care
408   - *
409   - * Check whether the given filename follows the naming rules.
410   - * Returns true if @filename follows the naming rules, false otherwise.
411   - */
412   -bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
413   - const s8 pattern_type, const s8 end_type)
414   -{
415   - const char *const start = filename;
416   - bool in_repetition = false;
417   - bool contains_pattern = false;
418   - unsigned char c;
419   - unsigned char d;
420   - unsigned char e;
421   -
422   - if (!filename)
423   - goto out;
424   - c = *filename;
425   - if (start_type == 1) { /* Must start with '/' */
426   - if (c != '/')
427   - goto out;
428   - } else if (start_type == -1) { /* Must not start with '/' */
429   - if (c == '/')
430   - goto out;
431   - }
432   - if (c)
433   - c = *(filename + strlen(filename) - 1);
434   - if (end_type == 1) { /* Must end with '/' */
435   - if (c != '/')
436   - goto out;
437   - } else if (end_type == -1) { /* Must not end with '/' */
438   - if (c == '/')
439   - goto out;
440   - }
441   - while (1) {
442   - c = *filename++;
443   - if (!c)
444   - break;
445   - if (c == '\\') {
446   - c = *filename++;
447   - switch (c) {
448   - case '\\': /* "\\" */
449   - continue;
450   - case '$': /* "\$" */
451   - case '+': /* "\+" */
452   - case '?': /* "\?" */
453   - case '*': /* "\*" */
454   - case '@': /* "\@" */
455   - case 'x': /* "\x" */
456   - case 'X': /* "\X" */
457   - case 'a': /* "\a" */
458   - case 'A': /* "\A" */
459   - case '-': /* "\-" */
460   - if (pattern_type == -1)
461   - break; /* Must not contain pattern */
462   - contains_pattern = true;
463   - continue;
464   - case '{': /* "/\{" */
465   - if (filename - 3 < start ||
466   - *(filename - 3) != '/')
467   - break;
468   - if (pattern_type == -1)
469   - break; /* Must not contain pattern */
470   - contains_pattern = true;
471   - in_repetition = true;
472   - continue;
473   - case '}': /* "\}/" */
474   - if (*filename != '/')
475   - break;
476   - if (!in_repetition)
477   - break;
478   - in_repetition = false;
479   - continue;
480   - case '0': /* "\ooo" */
481   - case '1':
482   - case '2':
483   - case '3':
484   - d = *filename++;
485   - if (d < '0' || d > '7')
486   - break;
487   - e = *filename++;
488   - if (e < '0' || e > '7')
489   - break;
490   - c = tomoyo_make_byte(c, d, e);
491   - if (tomoyo_is_invalid(c))
492   - continue; /* pattern is not \000 */
493   - }
494   - goto out;
495   - } else if (in_repetition && c == '/') {
496   - goto out;
497   - } else if (tomoyo_is_invalid(c)) {
498   - goto out;
499   - }
500   - }
501   - if (pattern_type == 1) { /* Must contain pattern */
502   - if (!contains_pattern)
503   - goto out;
504   - }
505   - if (in_repetition)
506   - goto out;
507   - return true;
508   - out:
509   - return false;
510   -}
511   -
512   -/**
513   - * tomoyo_is_correct_domain - Check whether the given domainname follows the naming rules.
514   - * @domainname: The domainname to check.
515   - *
516   - * Returns true if @domainname follows the naming rules, false otherwise.
517   - */
518   -bool tomoyo_is_correct_domain(const unsigned char *domainname)
519   -{
520   - unsigned char c;
521   - unsigned char d;
522   - unsigned char e;
523   -
524   - if (!domainname || strncmp(domainname, TOMOYO_ROOT_NAME,
525   - TOMOYO_ROOT_NAME_LEN))
526   - goto out;
527   - domainname += TOMOYO_ROOT_NAME_LEN;
528   - if (!*domainname)
529   - return true;
530   - do {
531   - if (*domainname++ != ' ')
532   - goto out;
533   - if (*domainname++ != '/')
534   - goto out;
535   - while ((c = *domainname) != '\0' && c != ' ') {
536   - domainname++;
537   - if (c == '\\') {
538   - c = *domainname++;
539   - switch ((c)) {
540   - case '\\': /* "\\" */
541   - continue;
542   - case '0': /* "\ooo" */
543   - case '1':
544   - case '2':
545   - case '3':
546   - d = *domainname++;
547   - if (d < '0' || d > '7')
548   - break;
549   - e = *domainname++;
550   - if (e < '0' || e > '7')
551   - break;
552   - c = tomoyo_make_byte(c, d, e);
553   - if (tomoyo_is_invalid(c))
554   - /* pattern is not \000 */
555   - continue;
556   - }
557   - goto out;
558   - } else if (tomoyo_is_invalid(c)) {
559   - goto out;
560   - }
561   - }
562   - } while (*domainname);
563   - return true;
564   - out:
565   - return false;
566   -}
567   -
568   -/**
569   - * tomoyo_is_domain_def - Check whether the given token can be a domainname.
570   - *
571   - * @buffer: The token to check.
572   - *
573   - * Returns true if @buffer possibly be a domainname, false otherwise.
574   - */
575   -bool tomoyo_is_domain_def(const unsigned char *buffer)
576   -{
577   - return !strncmp(buffer, TOMOYO_ROOT_NAME, TOMOYO_ROOT_NAME_LEN);
578   -}
579   -
580   -/**
581   - * tomoyo_find_domain - Find a domain by the given name.
582   - *
583   - * @domainname: The domainname to find.
584   - *
585   - * Returns pointer to "struct tomoyo_domain_info" if found, NULL otherwise.
586   - *
587   - * Caller holds tomoyo_read_lock().
588   - */
589   -struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname)
590   -{
591   - struct tomoyo_domain_info *domain;
592   - struct tomoyo_path_info name;
593   -
594   - name.name = domainname;
595   - tomoyo_fill_path_info(&name);
596   - list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
597   - if (!domain->is_deleted &&
598   - !tomoyo_pathcmp(&name, domain->domainname))
599   - return domain;
600   - }
601   - return NULL;
602   -}
603   -
604   -/**
605   - * tomoyo_const_part_length - Evaluate the initial length without a pattern in a token.
606   - *
607   - * @filename: The string to evaluate.
608   - *
609   - * Returns the initial length without a pattern in @filename.
610   - */
611   -static int tomoyo_const_part_length(const char *filename)
612   -{
613   - char c;
614   - int len = 0;
615   -
616   - if (!filename)
617   - return 0;
618   - while ((c = *filename++) != '\0') {
619   - if (c != '\\') {
620   - len++;
621   - continue;
622   - }
623   - c = *filename++;
624   - switch (c) {
625   - case '\\': /* "\\" */
626   - len += 2;
627   - continue;
628   - case '0': /* "\ooo" */
629   - case '1':
630   - case '2':
631   - case '3':
632   - c = *filename++;
633   - if (c < '0' || c > '7')
634   - break;
635   - c = *filename++;
636   - if (c < '0' || c > '7')
637   - break;
638   - len += 4;
639   - continue;
640   - }
641   - break;
642   - }
643   - return len;
644   -}
645   -
646   -/**
647   - * tomoyo_fill_path_info - Fill in "struct tomoyo_path_info" members.
648   - *
649   - * @ptr: Pointer to "struct tomoyo_path_info" to fill in.
650   - *
651   - * The caller sets "struct tomoyo_path_info"->name.
652   - */
653   -void tomoyo_fill_path_info(struct tomoyo_path_info *ptr)
654   -{
655   - const char *name = ptr->name;
656   - const int len = strlen(name);
657   -
658   - ptr->const_len = tomoyo_const_part_length(name);
659   - ptr->is_dir = len && (name[len - 1] == '/');
660   - ptr->is_patterned = (ptr->const_len < len);
661   - ptr->hash = full_name_hash(name, len);
662   -}
663   -
664   -/**
665   - * tomoyo_file_matches_pattern2 - Pattern matching without '/' character
666   - * and "\-" pattern.
667   - *
668   - * @filename: The start of string to check.
669   - * @filename_end: The end of string to check.
670   - * @pattern: The start of pattern to compare.
671   - * @pattern_end: The end of pattern to compare.
672   - *
673   - * Returns true if @filename matches @pattern, false otherwise.
674   - */
675   -static bool tomoyo_file_matches_pattern2(const char *filename,
676   - const char *filename_end,
677   - const char *pattern,
678   - const char *pattern_end)
679   -{
680   - while (filename < filename_end && pattern < pattern_end) {
681   - char c;
682   - if (*pattern != '\\') {
683   - if (*filename++ != *pattern++)
684   - return false;
685   - continue;
686   - }
687   - c = *filename;
688   - pattern++;
689   - switch (*pattern) {
690   - int i;
691   - int j;
692   - case '?':
693   - if (c == '/') {
694   - return false;
695   - } else if (c == '\\') {
696   - if (filename[1] == '\\')
697   - filename++;
698   - else if (tomoyo_is_byte_range(filename + 1))
699   - filename += 3;
700   - else
701   - return false;
702   - }
703   - break;
704   - case '\\':
705   - if (c != '\\')
706   - return false;
707   - if (*++filename != '\\')
708   - return false;
709   - break;
710   - case '+':
711   - if (!isdigit(c))
712   - return false;
713   - break;
714   - case 'x':
715   - if (!isxdigit(c))
716   - return false;
717   - break;
718   - case 'a':
719   - if (!tomoyo_is_alphabet_char(c))
720   - return false;
721   - break;
722   - case '0':
723   - case '1':
724   - case '2':
725   - case '3':
726   - if (c == '\\' && tomoyo_is_byte_range(filename + 1)
727   - && strncmp(filename + 1, pattern, 3) == 0) {
728   - filename += 3;
729   - pattern += 2;
730   - break;
731   - }
732   - return false; /* Not matched. */
733   - case '*':
734   - case '@':
735   - for (i = 0; i <= filename_end - filename; i++) {
736   - if (tomoyo_file_matches_pattern2(
737   - filename + i, filename_end,
738   - pattern + 1, pattern_end))
739   - return true;
740   - c = filename[i];
741   - if (c == '.' && *pattern == '@')
742   - break;
743   - if (c != '\\')
744   - continue;
745   - if (filename[i + 1] == '\\')
746   - i++;
747   - else if (tomoyo_is_byte_range(filename + i + 1))
748   - i += 3;
749   - else
750   - break; /* Bad pattern. */
751   - }
752   - return false; /* Not matched. */
753   - default:
754   - j = 0;
755   - c = *pattern;
756   - if (c == '$') {
757   - while (isdigit(filename[j]))
758   - j++;
759   - } else if (c == 'X') {
760   - while (isxdigit(filename[j]))
761   - j++;
762   - } else if (c == 'A') {
763   - while (tomoyo_is_alphabet_char(filename[j]))
764   - j++;
765   - }
766   - for (i = 1; i <= j; i++) {
767   - if (tomoyo_file_matches_pattern2(
768   - filename + i, filename_end,
769   - pattern + 1, pattern_end))
770   - return true;
771   - }
772   - return false; /* Not matched or bad pattern. */
773   - }
774   - filename++;
775   - pattern++;
776   - }
777   - while (*pattern == '\\' &&
778   - (*(pattern + 1) == '*' || *(pattern + 1) == '@'))
779   - pattern += 2;
780   - return filename == filename_end && pattern == pattern_end;
781   -}
782   -
783   -/**
784   - * tomoyo_file_matches_pattern - Pattern matching without without '/' character.
785   - *
786   - * @filename: The start of string to check.
787   - * @filename_end: The end of string to check.
788   - * @pattern: The start of pattern to compare.
789   - * @pattern_end: The end of pattern to compare.
790   - *
791   - * Returns true if @filename matches @pattern, false otherwise.
792   - */
793   -static bool tomoyo_file_matches_pattern(const char *filename,
794   - const char *filename_end,
795   - const char *pattern,
796   - const char *pattern_end)
797   -{
798   - const char *pattern_start = pattern;
799   - bool first = true;
800   - bool result;
801   -
802   - while (pattern < pattern_end - 1) {
803   - /* Split at "\-" pattern. */
804   - if (*pattern++ != '\\' || *pattern++ != '-')
805   - continue;
806   - result = tomoyo_file_matches_pattern2(filename,
807   - filename_end,
808   - pattern_start,
809   - pattern - 2);
810   - if (first)
811   - result = !result;
812   - if (result)
813   - return false;
814   - first = false;
815   - pattern_start = pattern;
816   - }
817   - result = tomoyo_file_matches_pattern2(filename, filename_end,
818   - pattern_start, pattern_end);
819   - return first ? result : !result;
820   -}
821   -
822   -/**
823   - * tomoyo_path_matches_pattern2 - Do pathname pattern matching.
824   - *
825   - * @f: The start of string to check.
826   - * @p: The start of pattern to compare.
827   - *
828   - * Returns true if @f matches @p, false otherwise.
829   - */
830   -static bool tomoyo_path_matches_pattern2(const char *f, const char *p)
831   -{
832   - const char *f_delimiter;
833   - const char *p_delimiter;
834   -
835   - while (*f && *p) {
836   - f_delimiter = strchr(f, '/');
837   - if (!f_delimiter)
838   - f_delimiter = f + strlen(f);
839   - p_delimiter = strchr(p, '/');
840   - if (!p_delimiter)
841   - p_delimiter = p + strlen(p);
842   - if (*p == '\\' && *(p + 1) == '{')
843   - goto recursive;
844   - if (!tomoyo_file_matches_pattern(f, f_delimiter, p,
845   - p_delimiter))
846   - return false;
847   - f = f_delimiter;
848   - if (*f)
849   - f++;
850   - p = p_delimiter;
851   - if (*p)
852   - p++;
853   - }
854   - /* Ignore trailing "\*" and "\@" in @pattern. */
855   - while (*p == '\\' &&
856   - (*(p + 1) == '*' || *(p + 1) == '@'))
857   - p += 2;
858   - return !*f && !*p;
859   - recursive:
860   - /*
861   - * The "\{" pattern is permitted only after '/' character.
862   - * This guarantees that below "*(p - 1)" is safe.
863   - * Also, the "\}" pattern is permitted only before '/' character
864   - * so that "\{" + "\}" pair will not break the "\-" operator.
865   - */
866   - if (*(p - 1) != '/' || p_delimiter <= p + 3 || *p_delimiter != '/' ||
867   - *(p_delimiter - 1) != '}' || *(p_delimiter - 2) != '\\')
868   - return false; /* Bad pattern. */
869   - do {
870   - /* Compare current component with pattern. */
871   - if (!tomoyo_file_matches_pattern(f, f_delimiter, p + 2,
872   - p_delimiter - 2))
873   - break;
874   - /* Proceed to next component. */
875   - f = f_delimiter;
876   - if (!*f)
877   - break;
878   - f++;
879   - /* Continue comparison. */
880   - if (tomoyo_path_matches_pattern2(f, p_delimiter + 1))
881   - return true;
882   - f_delimiter = strchr(f, '/');
883   - } while (f_delimiter);
884   - return false; /* Not matched. */
885   -}
886   -
887   -/**
888   - * tomoyo_path_matches_pattern - Check whether the given filename matches the given pattern.
889   - *
890   - * @filename: The filename to check.
891   - * @pattern: The pattern to compare.
892   - *
893   - * Returns true if matches, false otherwise.
894   - *
895   - * The following patterns are available.
896   - * \\ \ itself.
897   - * \ooo Octal representation of a byte.
898   - * \* Zero or more repetitions of characters other than '/'.
899   - * \@ Zero or more repetitions of characters other than '/' or '.'.
900   - * \? 1 byte character other than '/'.
901   - * \$ One or more repetitions of decimal digits.
902   - * \+ 1 decimal digit.
903   - * \X One or more repetitions of hexadecimal digits.
904   - * \x 1 hexadecimal digit.
905   - * \A One or more repetitions of alphabet characters.
906   - * \a 1 alphabet character.
907   - *
908   - * \- Subtraction operator.
909   - *
910   - * /\{dir\}/ '/' + 'One or more repetitions of dir/' (e.g. /dir/ /dir/dir/
911   - * /dir/dir/dir/ ).
912   - */
913   -bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
914   - const struct tomoyo_path_info *pattern)
915   -{
916   - const char *f = filename->name;
917   - const char *p = pattern->name;
918   - const int len = pattern->const_len;
919   -
920   - /* If @pattern doesn't contain pattern, I can use strcmp(). */
921   - if (!pattern->is_patterned)
922   - return !tomoyo_pathcmp(filename, pattern);
923   - /* Don't compare directory and non-directory. */
924   - if (filename->is_dir != pattern->is_dir)
925   - return false;
926   - /* Compare the initial length without patterns. */
927   - if (strncmp(f, p, len))
928   - return false;
929   - f += len;
930   - p += len;
931   - return tomoyo_path_matches_pattern2(f, p);
932   -}
933   -
934   -/**
935 129 * tomoyo_io_printf - Transactional printf() to "struct tomoyo_io_buffer" structure.
936 130 *
937 131 * @head: Pointer to "struct tomoyo_io_buffer".
... ... @@ -960,33 +154,6 @@
960 154 }
961 155  
962 156 /**
963   - * tomoyo_get_exe - Get tomoyo_realpath() of current process.
964   - *
965   - * Returns the tomoyo_realpath() of current process on success, NULL otherwise.
966   - *
967   - * This function uses kzalloc(), so the caller must call kfree()
968   - * if this function didn't return NULL.
969   - */
970   -static const char *tomoyo_get_exe(void)
971   -{
972   - struct mm_struct *mm = current->mm;
973   - struct vm_area_struct *vma;
974   - const char *cp = NULL;
975   -
976   - if (!mm)
977   - return NULL;
978   - down_read(&mm->mmap_sem);
979   - for (vma = mm->mmap; vma; vma = vma->vm_next) {
980   - if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) {
981   - cp = tomoyo_realpath_from_path(&vma->vm_file->f_path);
982   - break;
983   - }
984   - }
985   - up_read(&mm->mmap_sem);
986   - return cp;
987   -}
988   -
989   -/**
990 157 * tomoyo_check_flags - Check mode for specified functionality.
991 158 *
992 159 * @domain: Pointer to "struct tomoyo_domain_info".
... ... @@ -1025,76 +192,6 @@
1025 192 }
1026 193  
1027 194 /**
1028   - * tomoyo_domain_quota_is_ok - Check for domain's quota.
1029   - *
1030   - * @r: Pointer to "struct tomoyo_request_info".
1031   - *
1032   - * Returns true if the domain is not exceeded quota, false otherwise.
1033   - *
1034   - * Caller holds tomoyo_read_lock().
1035   - */
1036   -static bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r)
1037   -{
1038   - unsigned int count = 0;
1039   - struct tomoyo_domain_info *domain = r->domain;
1040   - struct tomoyo_acl_info *ptr;
1041   -
1042   - if (r->mode != TOMOYO_CONFIG_LEARNING)
1043   - return false;
1044   - if (!domain)
1045   - return true;
1046   - list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
1047   - switch (ptr->type) {
1048   - u16 perm;
1049   - u8 i;
1050   - case TOMOYO_TYPE_PATH_ACL:
1051   - perm = container_of(ptr, struct tomoyo_path_acl, head)
1052   - ->perm;
1053   - for (i = 0; i < TOMOYO_MAX_PATH_OPERATION; i++)
1054   - if (perm & (1 << i))
1055   - count++;
1056   - if (perm & (1 << TOMOYO_TYPE_READ_WRITE))
1057   - count -= 2;
1058   - break;
1059   - case TOMOYO_TYPE_PATH2_ACL:
1060   - perm = container_of(ptr, struct tomoyo_path2_acl, head)
1061   - ->perm;
1062   - for (i = 0; i < TOMOYO_MAX_PATH2_OPERATION; i++)
1063   - if (perm & (1 << i))
1064   - count++;
1065   - break;
1066   - case TOMOYO_TYPE_PATH_NUMBER_ACL:
1067   - perm = container_of(ptr, struct tomoyo_path_number_acl,
1068   - head)->perm;
1069   - for (i = 0; i < TOMOYO_MAX_PATH_NUMBER_OPERATION; i++)
1070   - if (perm & (1 << i))
1071   - count++;
1072   - break;
1073   - case TOMOYO_TYPE_PATH_NUMBER3_ACL:
1074   - perm = container_of(ptr, struct tomoyo_path_number3_acl,
1075   - head)->perm;
1076   - for (i = 0; i < TOMOYO_MAX_PATH_NUMBER3_OPERATION; i++)
1077   - if (perm & (1 << i))
1078   - count++;
1079   - break;
1080   - case TOMOYO_TYPE_MOUNT_ACL:
1081   - if (!container_of(ptr, struct tomoyo_mount_acl, head)->
1082   - is_deleted)
1083   - count++;
1084   - }
1085   - }
1086   - if (count < tomoyo_check_flags(domain, TOMOYO_MAX_ACCEPT_ENTRY))
1087   - return true;
1088   - if (!domain->quota_warned) {
1089   - domain->quota_warned = true;
1090   - printk(KERN_WARNING "TOMOYO-WARNING: "
1091   - "Domain '%s' has so many ACLs to hold. "
1092   - "Stopped learning mode.\n", domain->domainname->name);
1093   - }
1094   - return false;
1095   -}
1096   -
1097   -/**
1098 195 * tomoyo_find_or_assign_new_profile - Create a new profile.
1099 196 *
1100 197 * @profile: Profile number to create.
1101 198  
... ... @@ -2118,92 +1215,7 @@
2118 1215 return 0;
2119 1216 }
2120 1217  
2121   -/* path to policy loader */
2122   -static const char *tomoyo_loader = "/sbin/tomoyo-init";
2123   -
2124 1218 /**
2125   - * tomoyo_policy_loader_exists - Check whether /sbin/tomoyo-init exists.
2126   - *
2127   - * Returns true if /sbin/tomoyo-init exists, false otherwise.
2128   - */
2129   -static bool tomoyo_policy_loader_exists(void)
2130   -{
2131   - /*
2132   - * Don't activate MAC if the policy loader doesn't exist.
2133   - * If the initrd includes /sbin/init but real-root-dev has not
2134   - * mounted on / yet, activating MAC will block the system since
2135   - * policies are not loaded yet.
2136   - * Thus, let do_execve() call this function everytime.
2137   - */
2138   - struct path path;
2139   -
2140   - if (kern_path(tomoyo_loader, LOOKUP_FOLLOW, &path)) {
2141   - printk(KERN_INFO "Not activating Mandatory Access Control now "
2142   - "since %s doesn't exist.\n", tomoyo_loader);
2143   - return false;
2144   - }
2145   - path_put(&path);
2146   - return true;
2147   -}
2148   -
2149   -/**
2150   - * tomoyo_load_policy - Run external policy loader to load policy.
2151   - *
2152   - * @filename: The program about to start.
2153   - *
2154   - * This function checks whether @filename is /sbin/init , and if so
2155   - * invoke /sbin/tomoyo-init and wait for the termination of /sbin/tomoyo-init
2156   - * and then continues invocation of /sbin/init.
2157   - * /sbin/tomoyo-init reads policy files in /etc/tomoyo/ directory and
2158   - * writes to /sys/kernel/security/tomoyo/ interfaces.
2159   - *
2160   - * Returns nothing.
2161   - */
2162   -void tomoyo_load_policy(const char *filename)
2163   -{
2164   - char *argv[2];
2165   - char *envp[3];
2166   -
2167   - if (tomoyo_policy_loaded)
2168   - return;
2169   - /*
2170   - * Check filename is /sbin/init or /sbin/tomoyo-start.
2171   - * /sbin/tomoyo-start is a dummy filename in case where /sbin/init can't
2172   - * be passed.
2173   - * You can create /sbin/tomoyo-start by
2174   - * "ln -s /bin/true /sbin/tomoyo-start".
2175   - */
2176   - if (strcmp(filename, "/sbin/init") &&
2177   - strcmp(filename, "/sbin/tomoyo-start"))
2178   - return;
2179   - if (!tomoyo_policy_loader_exists())
2180   - return;
2181   -
2182   - printk(KERN_INFO "Calling %s to load policy. Please wait.\n",
2183   - tomoyo_loader);
2184   - argv[0] = (char *) tomoyo_loader;
2185   - argv[1] = NULL;
2186   - envp[0] = "HOME=/";
2187   - envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
2188   - envp[2] = NULL;
2189   - call_usermodehelper(argv[0], argv, envp, 1);
2190   -
2191   - printk(KERN_INFO "TOMOYO: 2.2.0 2009/04/01\n");
2192   - printk(KERN_INFO "Mandatory Access Control activated.\n");
2193   - tomoyo_policy_loaded = true;
2194   - { /* Check all profiles currently assigned to domains are defined. */
2195   - struct tomoyo_domain_info *domain;
2196   - list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
2197   - const u8 profile = domain->profile;
2198   - if (tomoyo_profile_ptr[profile])
2199   - continue;
2200   - panic("Profile %u (used by '%s') not defined.\n",
2201   - profile, domain->domainname->name);
2202   - }
2203   - }
2204   -}
2205   -
2206   -/**
2207 1219 * tomoyo_print_header - Get header line of audit log.
2208 1220 *
2209 1221 * @r: Pointer to "struct tomoyo_request_info".
... ... @@ -2601,7 +1613,7 @@
2601 1613 *
2602 1614 * Caller acquires tomoyo_read_lock().
2603 1615 */
2604   -static int tomoyo_open_control(const u8 type, struct file *file)
  1616 +int tomoyo_open_control(const u8 type, struct file *file)
2605 1617 {
2606 1618 struct tomoyo_io_buffer *head = kzalloc(sizeof(*head), GFP_NOFS);
2607 1619  
... ... @@ -2744,8 +1756,8 @@
2744 1756 *
2745 1757 * Caller holds tomoyo_read_lock().
2746 1758 */
2747   -static int tomoyo_read_control(struct file *file, char __user *buffer,
2748   - const int buffer_len)
  1759 +int tomoyo_read_control(struct file *file, char __user *buffer,
  1760 + const int buffer_len)
2749 1761 {
2750 1762 int len = 0;
2751 1763 struct tomoyo_io_buffer *head = file->private_data;
... ... @@ -2789,8 +1801,8 @@
2789 1801 *
2790 1802 * Caller holds tomoyo_read_lock().
2791 1803 */
2792   -static int tomoyo_write_control(struct file *file, const char __user *buffer,
2793   - const int buffer_len)
  1804 +int tomoyo_write_control(struct file *file, const char __user *buffer,
  1805 + const int buffer_len)
2794 1806 {
2795 1807 struct tomoyo_io_buffer *head = file->private_data;
2796 1808 int error = buffer_len;
... ... @@ -2841,7 +1853,7 @@
2841 1853 *
2842 1854 * Caller looses tomoyo_read_lock().
2843 1855 */
2844   -static int tomoyo_close_control(struct file *file)
  1856 +int tomoyo_close_control(struct file *file)
2845 1857 {
2846 1858 struct tomoyo_io_buffer *head = file->private_data;
2847 1859 const bool is_write = !!head->write_buf;
2848 1860  
2849 1861  
2850 1862  
... ... @@ -2868,132 +1880,23 @@
2868 1880 }
2869 1881  
2870 1882 /**
2871   - * tomoyo_open - open() for /sys/kernel/security/tomoyo/ interface.
2872   - *
2873   - * @inode: Pointer to "struct inode".
2874   - * @file: Pointer to "struct file".
2875   - *
2876   - * Returns 0 on success, negative value otherwise.
  1883 + * tomoyo_check_profile - Check all profiles currently assigned to domains are defined.
2877 1884 */
2878   -static int tomoyo_open(struct inode *inode, struct file *file)
  1885 +void tomoyo_check_profile(void)
2879 1886 {
2880   - const int key = ((u8 *) file->f_path.dentry->d_inode->i_private)
2881   - - ((u8 *) NULL);
2882   - return tomoyo_open_control(key, file);
  1887 + struct tomoyo_domain_info *domain;
  1888 + const int idx = tomoyo_read_lock();
  1889 + tomoyo_policy_loaded = true;
  1890 + /* Check all profiles currently assigned to domains are defined. */
  1891 + list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
  1892 + const u8 profile = domain->profile;
  1893 + if (tomoyo_profile_ptr[profile])
  1894 + continue;
  1895 + panic("Profile %u (used by '%s') not defined.\n",
  1896 + profile, domain->domainname->name);
  1897 + }
  1898 + tomoyo_read_unlock(idx);
  1899 + printk(KERN_INFO "TOMOYO: 2.2.0 2009/04/01\n");
  1900 + printk(KERN_INFO "Mandatory Access Control activated.\n");
2883 1901 }
2884   -
2885   -/**
2886   - * tomoyo_release - close() for /sys/kernel/security/tomoyo/ interface.
2887   - *
2888   - * @inode: Pointer to "struct inode".
2889   - * @file: Pointer to "struct file".
2890   - *
2891   - * Returns 0 on success, negative value otherwise.
2892   - */
2893   -static int tomoyo_release(struct inode *inode, struct file *file)
2894   -{
2895   - return tomoyo_close_control(file);
2896   -}
2897   -
2898   -/**
2899   - * tomoyo_read - read() for /sys/kernel/security/tomoyo/ interface.
2900   - *
2901   - * @file: Pointer to "struct file".
2902   - * @buf: Pointer to buffer.
2903   - * @count: Size of @buf.
2904   - * @ppos: Unused.
2905   - *
2906   - * Returns bytes read on success, negative value otherwise.
2907   - */
2908   -static ssize_t tomoyo_read(struct file *file, char __user *buf, size_t count,
2909   - loff_t *ppos)
2910   -{
2911   - return tomoyo_read_control(file, buf, count);
2912   -}
2913   -
2914   -/**
2915   - * tomoyo_write - write() for /sys/kernel/security/tomoyo/ interface.
2916   - *
2917   - * @file: Pointer to "struct file".
2918   - * @buf: Pointer to buffer.
2919   - * @count: Size of @buf.
2920   - * @ppos: Unused.
2921   - *
2922   - * Returns @count on success, negative value otherwise.
2923   - */
2924   -static ssize_t tomoyo_write(struct file *file, const char __user *buf,
2925   - size_t count, loff_t *ppos)
2926   -{
2927   - return tomoyo_write_control(file, buf, count);
2928   -}
2929   -
2930   -/*
2931   - * tomoyo_operations is a "struct file_operations" which is used for handling
2932   - * /sys/kernel/security/tomoyo/ interface.
2933   - *
2934   - * Some files under /sys/kernel/security/tomoyo/ directory accept open(O_RDWR).
2935   - * See tomoyo_io_buffer for internals.
2936   - */
2937   -static const struct file_operations tomoyo_operations = {
2938   - .open = tomoyo_open,
2939   - .release = tomoyo_release,
2940   - .read = tomoyo_read,
2941   - .write = tomoyo_write,
2942   -};
2943   -
2944   -/**
2945   - * tomoyo_create_entry - Create interface files under /sys/kernel/security/tomoyo/ directory.
2946   - *
2947   - * @name: The name of the interface file.
2948   - * @mode: The permission of the interface file.
2949   - * @parent: The parent directory.
2950   - * @key: Type of interface.
2951   - *
2952   - * Returns nothing.
2953   - */
2954   -static void __init tomoyo_create_entry(const char *name, const mode_t mode,
2955   - struct dentry *parent, const u8 key)
2956   -{
2957   - securityfs_create_file(name, mode, parent, ((u8 *) NULL) + key,
2958   - &tomoyo_operations);
2959   -}
2960   -
2961   -/**
2962   - * tomoyo_initerface_init - Initialize /sys/kernel/security/tomoyo/ interface.
2963   - *
2964   - * Returns 0.
2965   - */
2966   -static int __init tomoyo_initerface_init(void)
2967   -{
2968   - struct dentry *tomoyo_dir;
2969   -
2970   - /* Don't create securityfs entries unless registered. */
2971   - if (current_cred()->security != &tomoyo_kernel_domain)
2972   - return 0;
2973   -
2974   - tomoyo_dir = securityfs_create_dir("tomoyo", NULL);
2975   - tomoyo_create_entry("query", 0600, tomoyo_dir,
2976   - TOMOYO_QUERY);
2977   - tomoyo_create_entry("domain_policy", 0600, tomoyo_dir,
2978   - TOMOYO_DOMAINPOLICY);
2979   - tomoyo_create_entry("exception_policy", 0600, tomoyo_dir,
2980   - TOMOYO_EXCEPTIONPOLICY);
2981   - tomoyo_create_entry("self_domain", 0400, tomoyo_dir,
2982   - TOMOYO_SELFDOMAIN);
2983   - tomoyo_create_entry(".domain_status", 0600, tomoyo_dir,
2984   - TOMOYO_DOMAIN_STATUS);
2985   - tomoyo_create_entry(".process_status", 0600, tomoyo_dir,
2986   - TOMOYO_PROCESS_STATUS);
2987   - tomoyo_create_entry("meminfo", 0600, tomoyo_dir,
2988   - TOMOYO_MEMINFO);
2989   - tomoyo_create_entry("profile", 0600, tomoyo_dir,
2990   - TOMOYO_PROFILE);
2991   - tomoyo_create_entry("manager", 0600, tomoyo_dir,
2992   - TOMOYO_MANAGER);
2993   - tomoyo_create_entry("version", 0400, tomoyo_dir,
2994   - TOMOYO_VERSION);
2995   - return 0;
2996   -}
2997   -
2998   -fs_initcall(tomoyo_initerface_init);
security/tomoyo/common.h
... ... @@ -673,6 +673,31 @@
673 673 extern asmlinkage long sys_getpid(void);
674 674 extern asmlinkage long sys_getppid(void);
675 675  
  676 +/* Check whether the given string starts with the given keyword. */
  677 +bool tomoyo_str_starts(char **src, const char *find);
  678 +/* Get tomoyo_realpath() of current process. */
  679 +const char *tomoyo_get_exe(void);
  680 +/* Format string. */
  681 +void tomoyo_normalize_line(unsigned char *buffer);
  682 +/* Print warning or error message on console. */
  683 +void tomoyo_warn_log(struct tomoyo_request_info *r, const char *fmt, ...)
  684 + __attribute__ ((format(printf, 2, 3)));
  685 +/* Check all profiles currently assigned to domains are defined. */
  686 +void tomoyo_check_profile(void);
  687 +/* Open operation for /sys/kernel/security/tomoyo/ interface. */
  688 +int tomoyo_open_control(const u8 type, struct file *file);
  689 +/* Close /sys/kernel/security/tomoyo/ interface. */
  690 +int tomoyo_close_control(struct file *file);
  691 +/* Read operation for /sys/kernel/security/tomoyo/ interface. */
  692 +int tomoyo_read_control(struct file *file, char __user *buffer,
  693 + const int buffer_len);
  694 +/* Write operation for /sys/kernel/security/tomoyo/ interface. */
  695 +int tomoyo_write_control(struct file *file, const char __user *buffer,
  696 + const int buffer_len);
  697 +/* Check whether the domain has too many ACL entries to hold. */
  698 +bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r);
  699 +/* Print out of memory warning message. */
  700 +void tomoyo_warn_oom(const char *function);
676 701 /* Check whether the given name matches the given name_union. */
677 702 bool tomoyo_compare_name_union(const struct tomoyo_path_info *name,
678 703 const struct tomoyo_name_union *ptr);
... ... @@ -837,8 +862,8 @@
837 862 /* Set memory quota. */
838 863 int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head);
839 864  
840   -/* Initialize realpath related code. */
841   -void __init tomoyo_realpath_init(void);
  865 +/* Initialize mm related code. */
  866 +void __init tomoyo_mm_init(void);
842 867 int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain,
843 868 const struct tomoyo_path_info *filename);
844 869 int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
security/tomoyo/domain.c
1 1 /*
2 2 * security/tomoyo/domain.c
3 3 *
4   - * Implementation of the Domain-Based Mandatory Access Control.
  4 + * Domain transition functions for TOMOYO.
5 5 *
6   - * Copyright (C) 2005-2009 NTT DATA CORPORATION
7   - *
8   - * Version: 2.2.0 2009/04/01
9   - *
  6 + * Copyright (C) 2005-2010 NTT DATA CORPORATION
10 7 */
11 8  
12 9 #include "common.h"
13 10  
... ... @@ -697,23 +694,10 @@
697 694 struct tomoyo_path_info rn; /* real name */
698 695 struct tomoyo_path_info sn; /* symlink name */
699 696 struct tomoyo_path_info ln; /* last name */
700   - static bool initialized;
701 697  
702 698 tomoyo_init_request_info(&r, NULL);
703 699 if (!tmp)
704 700 goto out;
705   -
706   - if (!initialized) {
707   - /*
708   - * Built-in initializers. This is needed because policies are
709   - * not loaded until starting /sbin/init.
710   - */
711   - tomoyo_update_domain_initializer_entry(NULL, "/sbin/hotplug",
712   - false, false);
713   - tomoyo_update_domain_initializer_entry(NULL, "/sbin/modprobe",
714   - false, false);
715   - initialized = true;
716   - }
717 701  
718 702 retry:
719 703 /* Get tomoyo_realpath of program. */
security/tomoyo/file.c
1 1 /*
2 2 * security/tomoyo/file.c
3 3 *
4   - * Implementation of the Domain-Based Mandatory Access Control.
  4 + * Pathname restriction functions.
5 5 *
6   - * Copyright (C) 2005-2009 NTT DATA CORPORATION
7   - *
8   - * Version: 2.2.0 2009/04/01
9   - *
  6 + * Copyright (C) 2005-2010 NTT DATA CORPORATION
10 7 */
11 8  
12 9 #include "common.h"
... ... @@ -97,61 +94,6 @@
97 94 if (ptr->is_group)
98 95 return tomoyo_number_matches_group(value, value, ptr->group);
99 96 return value >= ptr->values[0] && value <= ptr->values[1];
100   -}
101   -
102   -/**
103   - * tomoyo_init_request_info - Initialize "struct tomoyo_request_info" members.
104   - *
105   - * @r: Pointer to "struct tomoyo_request_info" to initialize.
106   - * @domain: Pointer to "struct tomoyo_domain_info". NULL for tomoyo_domain().
107   - *
108   - * Returns mode.
109   - */
110   -int tomoyo_init_request_info(struct tomoyo_request_info *r,
111   - struct tomoyo_domain_info *domain)
112   -{
113   - memset(r, 0, sizeof(*r));
114   - if (!domain)
115   - domain = tomoyo_domain();
116   - r->domain = domain;
117   - r->mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
118   - return r->mode;
119   -}
120   -
121   -static void tomoyo_warn_log(struct tomoyo_request_info *r, const char *fmt, ...)
122   - __attribute__ ((format(printf, 2, 3)));
123   -/**
124   - * tomoyo_warn_log - Print warning or error message on console.
125   - *
126   - * @r: Pointer to "struct tomoyo_request_info".
127   - * @fmt: The printf()'s format string, followed by parameters.
128   - */
129   -static void tomoyo_warn_log(struct tomoyo_request_info *r, const char *fmt, ...)
130   -{
131   - int len = PAGE_SIZE;
132   - va_list args;
133   - char *buffer;
134   - if (!tomoyo_verbose_mode(r->domain))
135   - return;
136   - while (1) {
137   - int len2;
138   - buffer = kmalloc(len, GFP_NOFS);
139   - if (!buffer)
140   - return;
141   - va_start(args, fmt);
142   - len2 = vsnprintf(buffer, len - 1, fmt, args);
143   - va_end(args);
144   - if (len2 <= len - 1) {
145   - buffer[len2] = '\0';
146   - break;
147   - }
148   - len = len2 + 1;
149   - kfree(buffer);
150   - }
151   - printk(KERN_WARNING "TOMOYO-%s: Access %s denied for %s\n",
152   - r->mode == TOMOYO_CONFIG_ENFORCING ? "ERROR" : "WARNING",
153   - buffer, tomoyo_get_last_name(r->domain));
154   - kfree(buffer);
155 97 }
156 98  
157 99 /**
security/tomoyo/load_policy.c
  1 +/*
  2 + * security/tomoyo/load_policy.c
  3 + *
  4 + * Policy loader launcher for TOMOYO.
  5 + *
  6 + * Copyright (C) 2005-2010 NTT DATA CORPORATION
  7 + */
  8 +
  9 +#include "common.h"
  10 +
  11 +/* path to policy loader */
  12 +static const char *tomoyo_loader = "/sbin/tomoyo-init";
  13 +
  14 +/**
  15 + * tomoyo_policy_loader_exists - Check whether /sbin/tomoyo-init exists.
  16 + *
  17 + * Returns true if /sbin/tomoyo-init exists, false otherwise.
  18 + */
  19 +static bool tomoyo_policy_loader_exists(void)
  20 +{
  21 + /*
  22 + * Don't activate MAC if the policy loader doesn't exist.
  23 + * If the initrd includes /sbin/init but real-root-dev has not
  24 + * mounted on / yet, activating MAC will block the system since
  25 + * policies are not loaded yet.
  26 + * Thus, let do_execve() call this function everytime.
  27 + */
  28 + struct path path;
  29 +
  30 + if (kern_path(tomoyo_loader, LOOKUP_FOLLOW, &path)) {
  31 + printk(KERN_INFO "Not activating Mandatory Access Control now "
  32 + "since %s doesn't exist.\n", tomoyo_loader);
  33 + return false;
  34 + }
  35 + path_put(&path);
  36 + return true;
  37 +}
  38 +
  39 +/**
  40 + * tomoyo_load_policy - Run external policy loader to load policy.
  41 + *
  42 + * @filename: The program about to start.
  43 + *
  44 + * This function checks whether @filename is /sbin/init , and if so
  45 + * invoke /sbin/tomoyo-init and wait for the termination of /sbin/tomoyo-init
  46 + * and then continues invocation of /sbin/init.
  47 + * /sbin/tomoyo-init reads policy files in /etc/tomoyo/ directory and
  48 + * writes to /sys/kernel/security/tomoyo/ interfaces.
  49 + *
  50 + * Returns nothing.
  51 + */
  52 +void tomoyo_load_policy(const char *filename)
  53 +{
  54 + char *argv[2];
  55 + char *envp[3];
  56 +
  57 + if (tomoyo_policy_loaded)
  58 + return;
  59 + /*
  60 + * Check filename is /sbin/init or /sbin/tomoyo-start.
  61 + * /sbin/tomoyo-start is a dummy filename in case where /sbin/init can't
  62 + * be passed.
  63 + * You can create /sbin/tomoyo-start by
  64 + * "ln -s /bin/true /sbin/tomoyo-start".
  65 + */
  66 + if (strcmp(filename, "/sbin/init") &&
  67 + strcmp(filename, "/sbin/tomoyo-start"))
  68 + return;
  69 + if (!tomoyo_policy_loader_exists())
  70 + return;
  71 +
  72 + printk(KERN_INFO "Calling %s to load policy. Please wait.\n",
  73 + tomoyo_loader);
  74 + argv[0] = (char *) tomoyo_loader;
  75 + argv[1] = NULL;
  76 + envp[0] = "HOME=/";
  77 + envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
  78 + envp[2] = NULL;
  79 + call_usermodehelper(argv[0], argv, envp, 1);
  80 + tomoyo_check_profile();
  81 +}
security/tomoyo/memory.c
  1 +/*
  2 + * security/tomoyo/memory.c
  3 + *
  4 + * Memory management functions for TOMOYO.
  5 + *
  6 + * Copyright (C) 2005-2010 NTT DATA CORPORATION
  7 + */
  8 +
  9 +#include <linux/hash.h>
  10 +#include <linux/slab.h>
  11 +#include "common.h"
  12 +
  13 +/**
  14 + * tomoyo_warn_oom - Print out of memory warning message.
  15 + *
  16 + * @function: Function's name.
  17 + */
  18 +void tomoyo_warn_oom(const char *function)
  19 +{
  20 + /* Reduce error messages. */
  21 + static pid_t tomoyo_last_pid;
  22 + const pid_t pid = current->pid;
  23 + if (tomoyo_last_pid != pid) {
  24 + printk(KERN_WARNING "ERROR: Out of memory at %s.\n",
  25 + function);
  26 + tomoyo_last_pid = pid;
  27 + }
  28 + if (!tomoyo_policy_loaded)
  29 + panic("MAC Initialization failed.\n");
  30 +}
  31 +
  32 +/* Memory allocated for policy. */
  33 +static atomic_t tomoyo_policy_memory_size;
  34 +/* Quota for holding policy. */
  35 +static unsigned int tomoyo_quota_for_policy;
  36 +
  37 +/**
  38 + * tomoyo_memory_ok - Check memory quota.
  39 + *
  40 + * @ptr: Pointer to allocated memory.
  41 + *
  42 + * Returns true on success, false otherwise.
  43 + *
  44 + * Returns true if @ptr is not NULL and quota not exceeded, false otherwise.
  45 + */
  46 +bool tomoyo_memory_ok(void *ptr)
  47 +{
  48 + size_t s = ptr ? ksize(ptr) : 0;
  49 + atomic_add(s, &tomoyo_policy_memory_size);
  50 + if (ptr && (!tomoyo_quota_for_policy ||
  51 + atomic_read(&tomoyo_policy_memory_size)
  52 + <= tomoyo_quota_for_policy)) {
  53 + memset(ptr, 0, s);
  54 + return true;
  55 + }
  56 + atomic_sub(s, &tomoyo_policy_memory_size);
  57 + tomoyo_warn_oom(__func__);
  58 + return false;
  59 +}
  60 +
  61 +/**
  62 + * tomoyo_commit_ok - Check memory quota.
  63 + *
  64 + * @data: Data to copy from.
  65 + * @size: Size in byte.
  66 + *
  67 + * Returns pointer to allocated memory on success, NULL otherwise.
  68 + * @data is zero-cleared on success.
  69 + */
  70 +void *tomoyo_commit_ok(void *data, const unsigned int size)
  71 +{
  72 + void *ptr = kzalloc(size, GFP_NOFS);
  73 + if (tomoyo_memory_ok(ptr)) {
  74 + memmove(ptr, data, size);
  75 + memset(data, 0, size);
  76 + return ptr;
  77 + }
  78 + return NULL;
  79 +}
  80 +
  81 +/**
  82 + * tomoyo_memory_free - Free memory for elements.
  83 + *
  84 + * @ptr: Pointer to allocated memory.
  85 + */
  86 +void tomoyo_memory_free(void *ptr)
  87 +{
  88 + atomic_sub(ksize(ptr), &tomoyo_policy_memory_size);
  89 + kfree(ptr);
  90 +}
  91 +
  92 +/*
  93 + * tomoyo_name_list is used for holding string data used by TOMOYO.
  94 + * Since same string data is likely used for multiple times (e.g.
  95 + * "/lib/libc-2.5.so"), TOMOYO shares string data in the form of
  96 + * "const struct tomoyo_path_info *".
  97 + */
  98 +struct list_head tomoyo_name_list[TOMOYO_MAX_HASH];
  99 +
  100 +/**
  101 + * tomoyo_get_name - Allocate permanent memory for string data.
  102 + *
  103 + * @name: The string to store into the permernent memory.
  104 + *
  105 + * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise.
  106 + */
  107 +const struct tomoyo_path_info *tomoyo_get_name(const char *name)
  108 +{
  109 + struct tomoyo_name_entry *ptr;
  110 + unsigned int hash;
  111 + int len;
  112 + int allocated_len;
  113 + struct list_head *head;
  114 +
  115 + if (!name)
  116 + return NULL;
  117 + len = strlen(name) + 1;
  118 + hash = full_name_hash((const unsigned char *) name, len - 1);
  119 + head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)];
  120 + if (mutex_lock_interruptible(&tomoyo_policy_lock))
  121 + return NULL;
  122 + list_for_each_entry(ptr, head, list) {
  123 + if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name))
  124 + continue;
  125 + atomic_inc(&ptr->users);
  126 + goto out;
  127 + }
  128 + ptr = kzalloc(sizeof(*ptr) + len, GFP_NOFS);
  129 + allocated_len = ptr ? ksize(ptr) : 0;
  130 + if (!ptr || (tomoyo_quota_for_policy &&
  131 + atomic_read(&tomoyo_policy_memory_size) + allocated_len
  132 + > tomoyo_quota_for_policy)) {
  133 + kfree(ptr);
  134 + ptr = NULL;
  135 + tomoyo_warn_oom(__func__);
  136 + goto out;
  137 + }
  138 + atomic_add(allocated_len, &tomoyo_policy_memory_size);
  139 + ptr->entry.name = ((char *) ptr) + sizeof(*ptr);
  140 + memmove((char *) ptr->entry.name, name, len);
  141 + atomic_set(&ptr->users, 1);
  142 + tomoyo_fill_path_info(&ptr->entry);
  143 + list_add_tail(&ptr->list, head);
  144 + out:
  145 + mutex_unlock(&tomoyo_policy_lock);
  146 + return ptr ? &ptr->entry : NULL;
  147 +}
  148 +
  149 +/**
  150 + * tomoyo_mm_init - Initialize mm related code.
  151 + */
  152 +void __init tomoyo_mm_init(void)
  153 +{
  154 + int idx;
  155 +
  156 + BUILD_BUG_ON(TOMOYO_MAX_PATHNAME_LEN > PATH_MAX);
  157 + for (idx = 0; idx < TOMOYO_MAX_HASH; idx++)
  158 + INIT_LIST_HEAD(&tomoyo_name_list[idx]);
  159 + INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list);
  160 + tomoyo_kernel_domain.domainname = tomoyo_get_name(TOMOYO_ROOT_NAME);
  161 + list_add_tail_rcu(&tomoyo_kernel_domain.list, &tomoyo_domain_list);
  162 + idx = tomoyo_read_lock();
  163 + if (tomoyo_find_domain(TOMOYO_ROOT_NAME) != &tomoyo_kernel_domain)
  164 + panic("Can't register tomoyo_kernel_domain");
  165 + {
  166 + /* Load built-in policy. */
  167 + tomoyo_write_domain_initializer_policy("/sbin/hotplug",
  168 + false, false);
  169 + tomoyo_write_domain_initializer_policy("/sbin/modprobe",
  170 + false, false);
  171 + }
  172 + tomoyo_read_unlock(idx);
  173 +}
  174 +
  175 +
  176 +/* Memory allocated for query lists. */
  177 +unsigned int tomoyo_query_memory_size;
  178 +/* Quota for holding query lists. */
  179 +unsigned int tomoyo_quota_for_query;
  180 +
  181 +/**
  182 + * tomoyo_read_memory_counter - Check for memory usage in bytes.
  183 + *
  184 + * @head: Pointer to "struct tomoyo_io_buffer".
  185 + *
  186 + * Returns memory usage.
  187 + */
  188 +int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head)
  189 +{
  190 + if (!head->read_eof) {
  191 + const unsigned int policy
  192 + = atomic_read(&tomoyo_policy_memory_size);
  193 + const unsigned int query = tomoyo_query_memory_size;
  194 + char buffer[64];
  195 +
  196 + memset(buffer, 0, sizeof(buffer));
  197 + if (tomoyo_quota_for_policy)
  198 + snprintf(buffer, sizeof(buffer) - 1,
  199 + " (Quota: %10u)",
  200 + tomoyo_quota_for_policy);
  201 + else
  202 + buffer[0] = '\0';
  203 + tomoyo_io_printf(head, "Policy: %10u%s\n", policy,
  204 + buffer);
  205 + if (tomoyo_quota_for_query)
  206 + snprintf(buffer, sizeof(buffer) - 1,
  207 + " (Quota: %10u)",
  208 + tomoyo_quota_for_query);
  209 + else
  210 + buffer[0] = '\0';
  211 + tomoyo_io_printf(head, "Query lists: %10u%s\n", query,
  212 + buffer);
  213 + tomoyo_io_printf(head, "Total: %10u\n", policy + query);
  214 + head->read_eof = true;
  215 + }
  216 + return 0;
  217 +}
  218 +
  219 +/**
  220 + * tomoyo_write_memory_quota - Set memory quota.
  221 + *
  222 + * @head: Pointer to "struct tomoyo_io_buffer".
  223 + *
  224 + * Returns 0.
  225 + */
  226 +int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head)
  227 +{
  228 + char *data = head->write_buf;
  229 + unsigned int size;
  230 +
  231 + if (sscanf(data, "Policy: %u", &size) == 1)
  232 + tomoyo_quota_for_policy = size;
  233 + else if (sscanf(data, "Query lists: %u", &size) == 1)
  234 + tomoyo_quota_for_query = size;
  235 + return 0;
  236 +}
security/tomoyo/realpath.c
1 1 /*
2 2 * security/tomoyo/realpath.c
3 3 *
4   - * Get the canonicalized absolute pathnames. The basis for TOMOYO.
  4 + * Pathname calculation functions for TOMOYO.
5 5 *
6   - * Copyright (C) 2005-2009 NTT DATA CORPORATION
7   - *
8   - * Version: 2.2.0 2009/04/01
9   - *
  6 + * Copyright (C) 2005-2010 NTT DATA CORPORATION
10 7 */
11 8  
12 9 #include <linux/types.h>
13 10 #include <linux/mount.h>
14 11 #include <linux/mnt_namespace.h>
15 12 #include <linux/fs_struct.h>
16   -#include <linux/hash.h>
17 13 #include <linux/magic.h>
18 14 #include <linux/slab.h>
19 15 #include "common.h"
... ... @@ -123,7 +119,7 @@
123 119 }
124 120 }
125 121 if (error)
126   - printk(KERN_WARNING "tomoyo_realpath: Pathname too long.\n");
  122 + tomoyo_warn_oom(__func__);
127 123 return error;
128 124 }
129 125  
... ... @@ -141,6 +137,7 @@
141 137 {
142 138 char *buf = kzalloc(sizeof(struct tomoyo_page_buffer), GFP_NOFS);
143 139  
  140 + BUILD_BUG_ON(TOMOYO_MAX_PATHNAME_LEN > PATH_MAX);
144 141 BUILD_BUG_ON(sizeof(struct tomoyo_page_buffer)
145 142 <= TOMOYO_MAX_PATHNAME_LEN - 1);
146 143 if (!buf)
... ... @@ -188,208 +185,5 @@
188 185 return buf;
189 186 }
190 187 return NULL;
191   -}
192   -
193   -/* Memory allocated for non-string data. */
194   -static atomic_t tomoyo_policy_memory_size;
195   -/* Quota for holding policy. */
196   -static unsigned int tomoyo_quota_for_policy;
197   -
198   -/**
199   - * tomoyo_memory_ok - Check memory quota.
200   - *
201   - * @ptr: Pointer to allocated memory.
202   - *
203   - * Returns true on success, false otherwise.
204   - *
205   - * Caller holds tomoyo_policy_lock.
206   - * Memory pointed by @ptr will be zeroed on success.
207   - */
208   -bool tomoyo_memory_ok(void *ptr)
209   -{
210   - int allocated_len = ptr ? ksize(ptr) : 0;
211   - atomic_add(allocated_len, &tomoyo_policy_memory_size);
212   - if (ptr && (!tomoyo_quota_for_policy ||
213   - atomic_read(&tomoyo_policy_memory_size)
214   - <= tomoyo_quota_for_policy)) {
215   - memset(ptr, 0, allocated_len);
216   - return true;
217   - }
218   - printk(KERN_WARNING "ERROR: Out of memory "
219   - "for tomoyo_alloc_element().\n");
220   - if (!tomoyo_policy_loaded)
221   - panic("MAC Initialization failed.\n");
222   - return false;
223   -}
224   -
225   -/**
226   - * tomoyo_commit_ok - Check memory quota.
227   - *
228   - * @data: Data to copy from.
229   - * @size: Size in byte.
230   - *
231   - * Returns pointer to allocated memory on success, NULL otherwise.
232   - */
233   -void *tomoyo_commit_ok(void *data, const unsigned int size)
234   -{
235   - void *ptr = kzalloc(size, GFP_NOFS);
236   - if (tomoyo_memory_ok(ptr)) {
237   - memmove(ptr, data, size);
238   - memset(data, 0, size);
239   - return ptr;
240   - }
241   - return NULL;
242   -}
243   -
244   -/**
245   - * tomoyo_memory_free - Free memory for elements.
246   - *
247   - * @ptr: Pointer to allocated memory.
248   - */
249   -void tomoyo_memory_free(void *ptr)
250   -{
251   - atomic_sub(ksize(ptr), &tomoyo_policy_memory_size);
252   - kfree(ptr);
253   -}
254   -
255   -/*
256   - * tomoyo_name_list is used for holding string data used by TOMOYO.
257   - * Since same string data is likely used for multiple times (e.g.
258   - * "/lib/libc-2.5.so"), TOMOYO shares string data in the form of
259   - * "const struct tomoyo_path_info *".
260   - */
261   -struct list_head tomoyo_name_list[TOMOYO_MAX_HASH];
262   -
263   -/**
264   - * tomoyo_get_name - Allocate permanent memory for string data.
265   - *
266   - * @name: The string to store into the permernent memory.
267   - *
268   - * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise.
269   - */
270   -const struct tomoyo_path_info *tomoyo_get_name(const char *name)
271   -{
272   - struct tomoyo_name_entry *ptr;
273   - unsigned int hash;
274   - int len;
275   - int allocated_len;
276   - struct list_head *head;
277   -
278   - if (!name)
279   - return NULL;
280   - len = strlen(name) + 1;
281   - hash = full_name_hash((const unsigned char *) name, len - 1);
282   - head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)];
283   - if (mutex_lock_interruptible(&tomoyo_policy_lock))
284   - return NULL;
285   - list_for_each_entry(ptr, head, list) {
286   - if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name))
287   - continue;
288   - atomic_inc(&ptr->users);
289   - goto out;
290   - }
291   - ptr = kzalloc(sizeof(*ptr) + len, GFP_NOFS);
292   - allocated_len = ptr ? ksize(ptr) : 0;
293   - if (!ptr || (tomoyo_quota_for_policy &&
294   - atomic_read(&tomoyo_policy_memory_size) + allocated_len
295   - > tomoyo_quota_for_policy)) {
296   - kfree(ptr);
297   - printk(KERN_WARNING "ERROR: Out of memory "
298   - "for tomoyo_get_name().\n");
299   - if (!tomoyo_policy_loaded)
300   - panic("MAC Initialization failed.\n");
301   - ptr = NULL;
302   - goto out;
303   - }
304   - atomic_add(allocated_len, &tomoyo_policy_memory_size);
305   - ptr->entry.name = ((char *) ptr) + sizeof(*ptr);
306   - memmove((char *) ptr->entry.name, name, len);
307   - atomic_set(&ptr->users, 1);
308   - tomoyo_fill_path_info(&ptr->entry);
309   - list_add_tail(&ptr->list, head);
310   - out:
311   - mutex_unlock(&tomoyo_policy_lock);
312   - return ptr ? &ptr->entry : NULL;
313   -}
314   -
315   -/**
316   - * tomoyo_realpath_init - Initialize realpath related code.
317   - */
318   -void __init tomoyo_realpath_init(void)
319   -{
320   - int i;
321   -
322   - BUILD_BUG_ON(TOMOYO_MAX_PATHNAME_LEN > PATH_MAX);
323   - for (i = 0; i < TOMOYO_MAX_HASH; i++)
324   - INIT_LIST_HEAD(&tomoyo_name_list[i]);
325   - INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list);
326   - tomoyo_kernel_domain.domainname = tomoyo_get_name(TOMOYO_ROOT_NAME);
327   - /*
328   - * tomoyo_read_lock() is not needed because this function is
329   - * called before the first "delete" request.
330   - */
331   - list_add_tail_rcu(&tomoyo_kernel_domain.list, &tomoyo_domain_list);
332   - if (tomoyo_find_domain(TOMOYO_ROOT_NAME) != &tomoyo_kernel_domain)
333   - panic("Can't register tomoyo_kernel_domain");
334   -}
335   -
336   -unsigned int tomoyo_quota_for_query;
337   -unsigned int tomoyo_query_memory_size;
338   -
339   -/**
340   - * tomoyo_read_memory_counter - Check for memory usage in bytes.
341   - *
342   - * @head: Pointer to "struct tomoyo_io_buffer".
343   - *
344   - * Returns memory usage.
345   - */
346   -int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head)
347   -{
348   - if (!head->read_eof) {
349   - const unsigned int policy
350   - = atomic_read(&tomoyo_policy_memory_size);
351   - const unsigned int query = tomoyo_query_memory_size;
352   - char buffer[64];
353   -
354   - memset(buffer, 0, sizeof(buffer));
355   - if (tomoyo_quota_for_policy)
356   - snprintf(buffer, sizeof(buffer) - 1,
357   - " (Quota: %10u)",
358   - tomoyo_quota_for_policy);
359   - else
360   - buffer[0] = '\0';
361   - tomoyo_io_printf(head, "Policy: %10u%s\n", policy,
362   - buffer);
363   - if (tomoyo_quota_for_query)
364   - snprintf(buffer, sizeof(buffer) - 1,
365   - " (Quota: %10u)",
366   - tomoyo_quota_for_query);
367   - else
368   - buffer[0] = '\0';
369   - tomoyo_io_printf(head, "Query lists: %10u%s\n", query,
370   - buffer);
371   - tomoyo_io_printf(head, "Total: %10u\n", policy + query);
372   - head->read_eof = true;
373   - }
374   - return 0;
375   -}
376   -
377   -/**
378   - * tomoyo_write_memory_quota - Set memory quota.
379   - *
380   - * @head: Pointer to "struct tomoyo_io_buffer".
381   - *
382   - * Returns 0.
383   - */
384   -int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head)
385   -{
386   - char *data = head->write_buf;
387   - unsigned int size;
388   -
389   - if (sscanf(data, "Policy: %u", &size) == 1)
390   - tomoyo_quota_for_policy = size;
391   - else if (sscanf(data, "Query lists: %u", &size) == 1)
392   - tomoyo_quota_for_query = size;
393   - return 0;
394 188 }
security/tomoyo/securityfs_if.c
  1 +/*
  2 + * security/tomoyo/common.c
  3 + *
  4 + * Securityfs interface for TOMOYO.
  5 + *
  6 + * Copyright (C) 2005-2010 NTT DATA CORPORATION
  7 + */
  8 +
  9 +#include <linux/security.h>
  10 +#include "common.h"
  11 +
  12 +/**
  13 + * tomoyo_open - open() for /sys/kernel/security/tomoyo/ interface.
  14 + *
  15 + * @inode: Pointer to "struct inode".
  16 + * @file: Pointer to "struct file".
  17 + *
  18 + * Returns 0 on success, negative value otherwise.
  19 + */
  20 +static int tomoyo_open(struct inode *inode, struct file *file)
  21 +{
  22 + const int key = ((u8 *) file->f_path.dentry->d_inode->i_private)
  23 + - ((u8 *) NULL);
  24 + return tomoyo_open_control(key, file);
  25 +}
  26 +
  27 +/**
  28 + * tomoyo_release - close() for /sys/kernel/security/tomoyo/ interface.
  29 + *
  30 + * @inode: Pointer to "struct inode".
  31 + * @file: Pointer to "struct file".
  32 + *
  33 + * Returns 0 on success, negative value otherwise.
  34 + */
  35 +static int tomoyo_release(struct inode *inode, struct file *file)
  36 +{
  37 + return tomoyo_close_control(file);
  38 +}
  39 +
  40 +/**
  41 + * tomoyo_read - read() for /sys/kernel/security/tomoyo/ interface.
  42 + *
  43 + * @file: Pointer to "struct file".
  44 + * @buf: Pointer to buffer.
  45 + * @count: Size of @buf.
  46 + * @ppos: Unused.
  47 + *
  48 + * Returns bytes read on success, negative value otherwise.
  49 + */
  50 +static ssize_t tomoyo_read(struct file *file, char __user *buf, size_t count,
  51 + loff_t *ppos)
  52 +{
  53 + return tomoyo_read_control(file, buf, count);
  54 +}
  55 +
  56 +/**
  57 + * tomoyo_write - write() for /sys/kernel/security/tomoyo/ interface.
  58 + *
  59 + * @file: Pointer to "struct file".
  60 + * @buf: Pointer to buffer.
  61 + * @count: Size of @buf.
  62 + * @ppos: Unused.
  63 + *
  64 + * Returns @count on success, negative value otherwise.
  65 + */
  66 +static ssize_t tomoyo_write(struct file *file, const char __user *buf,
  67 + size_t count, loff_t *ppos)
  68 +{
  69 + return tomoyo_write_control(file, buf, count);
  70 +}
  71 +
  72 +/*
  73 + * tomoyo_operations is a "struct file_operations" which is used for handling
  74 + * /sys/kernel/security/tomoyo/ interface.
  75 + *
  76 + * Some files under /sys/kernel/security/tomoyo/ directory accept open(O_RDWR).
  77 + * See tomoyo_io_buffer for internals.
  78 + */
  79 +static const struct file_operations tomoyo_operations = {
  80 + .open = tomoyo_open,
  81 + .release = tomoyo_release,
  82 + .read = tomoyo_read,
  83 + .write = tomoyo_write,
  84 +};
  85 +
  86 +/**
  87 + * tomoyo_create_entry - Create interface files under /sys/kernel/security/tomoyo/ directory.
  88 + *
  89 + * @name: The name of the interface file.
  90 + * @mode: The permission of the interface file.
  91 + * @parent: The parent directory.
  92 + * @key: Type of interface.
  93 + *
  94 + * Returns nothing.
  95 + */
  96 +static void __init tomoyo_create_entry(const char *name, const mode_t mode,
  97 + struct dentry *parent, const u8 key)
  98 +{
  99 + securityfs_create_file(name, mode, parent, ((u8 *) NULL) + key,
  100 + &tomoyo_operations);
  101 +}
  102 +
  103 +/**
  104 + * tomoyo_initerface_init - Initialize /sys/kernel/security/tomoyo/ interface.
  105 + *
  106 + * Returns 0.
  107 + */
  108 +static int __init tomoyo_initerface_init(void)
  109 +{
  110 + struct dentry *tomoyo_dir;
  111 +
  112 + /* Don't create securityfs entries unless registered. */
  113 + if (current_cred()->security != &tomoyo_kernel_domain)
  114 + return 0;
  115 +
  116 + tomoyo_dir = securityfs_create_dir("tomoyo", NULL);
  117 + tomoyo_create_entry("query", 0600, tomoyo_dir,
  118 + TOMOYO_QUERY);
  119 + tomoyo_create_entry("domain_policy", 0600, tomoyo_dir,
  120 + TOMOYO_DOMAINPOLICY);
  121 + tomoyo_create_entry("exception_policy", 0600, tomoyo_dir,
  122 + TOMOYO_EXCEPTIONPOLICY);
  123 + tomoyo_create_entry("self_domain", 0400, tomoyo_dir,
  124 + TOMOYO_SELFDOMAIN);
  125 + tomoyo_create_entry(".domain_status", 0600, tomoyo_dir,
  126 + TOMOYO_DOMAIN_STATUS);
  127 + tomoyo_create_entry(".process_status", 0600, tomoyo_dir,
  128 + TOMOYO_PROCESS_STATUS);
  129 + tomoyo_create_entry("meminfo", 0600, tomoyo_dir,
  130 + TOMOYO_MEMINFO);
  131 + tomoyo_create_entry("profile", 0600, tomoyo_dir,
  132 + TOMOYO_PROFILE);
  133 + tomoyo_create_entry("manager", 0600, tomoyo_dir,
  134 + TOMOYO_MANAGER);
  135 + tomoyo_create_entry("version", 0400, tomoyo_dir,
  136 + TOMOYO_VERSION);
  137 + return 0;
  138 +}
  139 +
  140 +fs_initcall(tomoyo_initerface_init);
security/tomoyo/tomoyo.c
... ... @@ -3,10 +3,7 @@
3 3 *
4 4 * LSM hooks for TOMOYO Linux.
5 5 *
6   - * Copyright (C) 2005-2009 NTT DATA CORPORATION
7   - *
8   - * Version: 2.2.0 2009/04/01
9   - *
  6 + * Copyright (C) 2005-2010 NTT DATA CORPORATION
10 7 */
11 8  
12 9 #include <linux/security.h>
... ... @@ -286,7 +283,7 @@
286 283 panic("Failure registering TOMOYO Linux");
287 284 printk(KERN_INFO "TOMOYO Linux initialized\n");
288 285 cred->security = &tomoyo_kernel_domain;
289   - tomoyo_realpath_init();
  286 + tomoyo_mm_init();
290 287 return 0;
291 288 }
292 289  
security/tomoyo/util.c
  1 +/*
  2 + * security/tomoyo/util.c
  3 + *
  4 + * Utility functions for TOMOYO.
  5 + *
  6 + * Copyright (C) 2005-2010 NTT DATA CORPORATION
  7 + */
  8 +
  9 +#include <linux/slab.h>
  10 +#include "common.h"
  11 +
  12 +/* Lock for protecting policy. */
  13 +DEFINE_MUTEX(tomoyo_policy_lock);
  14 +
  15 +/* Has /sbin/init started? */
  16 +bool tomoyo_policy_loaded;
  17 +
  18 +/**
  19 + * tomoyo_parse_ulong - Parse an "unsigned long" value.
  20 + *
  21 + * @result: Pointer to "unsigned long".
  22 + * @str: Pointer to string to parse.
  23 + *
  24 + * Returns value type on success, 0 otherwise.
  25 + *
  26 + * The @src is updated to point the first character after the value
  27 + * on success.
  28 + */
  29 +u8 tomoyo_parse_ulong(unsigned long *result, char **str)
  30 +{
  31 + const char *cp = *str;
  32 + char *ep;
  33 + int base = 10;
  34 + if (*cp == '0') {
  35 + char c = *(cp + 1);
  36 + if (c == 'x' || c == 'X') {
  37 + base = 16;
  38 + cp += 2;
  39 + } else if (c >= '0' && c <= '7') {
  40 + base = 8;
  41 + cp++;
  42 + }
  43 + }
  44 + *result = simple_strtoul(cp, &ep, base);
  45 + if (cp == ep)
  46 + return 0;
  47 + *str = ep;
  48 + switch (base) {
  49 + case 16:
  50 + return TOMOYO_VALUE_TYPE_HEXADECIMAL;
  51 + case 8:
  52 + return TOMOYO_VALUE_TYPE_OCTAL;
  53 + default:
  54 + return TOMOYO_VALUE_TYPE_DECIMAL;
  55 + }
  56 +}
  57 +
  58 +/**
  59 + * tomoyo_print_ulong - Print an "unsigned long" value.
  60 + *
  61 + * @buffer: Pointer to buffer.
  62 + * @buffer_len: Size of @buffer.
  63 + * @value: An "unsigned long" value.
  64 + * @type: Type of @value.
  65 + *
  66 + * Returns nothing.
  67 + */
  68 +void tomoyo_print_ulong(char *buffer, const int buffer_len,
  69 + const unsigned long value, const u8 type)
  70 +{
  71 + if (type == TOMOYO_VALUE_TYPE_DECIMAL)
  72 + snprintf(buffer, buffer_len, "%lu", value);
  73 + else if (type == TOMOYO_VALUE_TYPE_OCTAL)
  74 + snprintf(buffer, buffer_len, "0%lo", value);
  75 + else if (type == TOMOYO_VALUE_TYPE_HEXADECIMAL)
  76 + snprintf(buffer, buffer_len, "0x%lX", value);
  77 + else
  78 + snprintf(buffer, buffer_len, "type(%u)", type);
  79 +}
  80 +
  81 +/**
  82 + * tomoyo_parse_name_union - Parse a tomoyo_name_union.
  83 + *
  84 + * @filename: Name or name group.
  85 + * @ptr: Pointer to "struct tomoyo_name_union".
  86 + *
  87 + * Returns true on success, false otherwise.
  88 + */
  89 +bool tomoyo_parse_name_union(const char *filename,
  90 + struct tomoyo_name_union *ptr)
  91 +{
  92 + if (!tomoyo_is_correct_path(filename, 0, 0, 0))
  93 + return false;
  94 + if (filename[0] == '@') {
  95 + ptr->group = tomoyo_get_path_group(filename + 1);
  96 + ptr->is_group = true;
  97 + return ptr->group != NULL;
  98 + }
  99 + ptr->filename = tomoyo_get_name(filename);
  100 + ptr->is_group = false;
  101 + return ptr->filename != NULL;
  102 +}
  103 +
  104 +/**
  105 + * tomoyo_parse_number_union - Parse a tomoyo_number_union.
  106 + *
  107 + * @data: Number or number range or number group.
  108 + * @ptr: Pointer to "struct tomoyo_number_union".
  109 + *
  110 + * Returns true on success, false otherwise.
  111 + */
  112 +bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num)
  113 +{
  114 + u8 type;
  115 + unsigned long v;
  116 + memset(num, 0, sizeof(*num));
  117 + if (data[0] == '@') {
  118 + if (!tomoyo_is_correct_path(data, 0, 0, 0))
  119 + return false;
  120 + num->group = tomoyo_get_number_group(data + 1);
  121 + num->is_group = true;
  122 + return num->group != NULL;
  123 + }
  124 + type = tomoyo_parse_ulong(&v, &data);
  125 + if (!type)
  126 + return false;
  127 + num->values[0] = v;
  128 + num->min_type = type;
  129 + if (!*data) {
  130 + num->values[1] = v;
  131 + num->max_type = type;
  132 + return true;
  133 + }
  134 + if (*data++ != '-')
  135 + return false;
  136 + type = tomoyo_parse_ulong(&v, &data);
  137 + if (!type || *data)
  138 + return false;
  139 + num->values[1] = v;
  140 + num->max_type = type;
  141 + return true;
  142 +}
  143 +
  144 +/**
  145 + * tomoyo_is_byte_range - Check whether the string is a \ooo style octal value.
  146 + *
  147 + * @str: Pointer to the string.
  148 + *
  149 + * Returns true if @str is a \ooo style octal value, false otherwise.
  150 + *
  151 + * TOMOYO uses \ooo style representation for 0x01 - 0x20 and 0x7F - 0xFF.
  152 + * This function verifies that \ooo is in valid range.
  153 + */
  154 +static inline bool tomoyo_is_byte_range(const char *str)
  155 +{
  156 + return *str >= '0' && *str++ <= '3' &&
  157 + *str >= '0' && *str++ <= '7' &&
  158 + *str >= '0' && *str <= '7';
  159 +}
  160 +
  161 +/**
  162 + * tomoyo_is_alphabet_char - Check whether the character is an alphabet.
  163 + *
  164 + * @c: The character to check.
  165 + *
  166 + * Returns true if @c is an alphabet character, false otherwise.
  167 + */
  168 +static inline bool tomoyo_is_alphabet_char(const char c)
  169 +{
  170 + return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
  171 +}
  172 +
  173 +/**
  174 + * tomoyo_make_byte - Make byte value from three octal characters.
  175 + *
  176 + * @c1: The first character.
  177 + * @c2: The second character.
  178 + * @c3: The third character.
  179 + *
  180 + * Returns byte value.
  181 + */
  182 +static inline u8 tomoyo_make_byte(const u8 c1, const u8 c2, const u8 c3)
  183 +{
  184 + return ((c1 - '0') << 6) + ((c2 - '0') << 3) + (c3 - '0');
  185 +}
  186 +
  187 +/**
  188 + * tomoyo_str_starts - Check whether the given string starts with the given keyword.
  189 + *
  190 + * @src: Pointer to pointer to the string.
  191 + * @find: Pointer to the keyword.
  192 + *
  193 + * Returns true if @src starts with @find, false otherwise.
  194 + *
  195 + * The @src is updated to point the first character after the @find
  196 + * if @src starts with @find.
  197 + */
  198 +bool tomoyo_str_starts(char **src, const char *find)
  199 +{
  200 + const int len = strlen(find);
  201 + char *tmp = *src;
  202 +
  203 + if (strncmp(tmp, find, len))
  204 + return false;
  205 + tmp += len;
  206 + *src = tmp;
  207 + return true;
  208 +}
  209 +
  210 +/**
  211 + * tomoyo_normalize_line - Format string.
  212 + *
  213 + * @buffer: The line to normalize.
  214 + *
  215 + * Leading and trailing whitespaces are removed.
  216 + * Multiple whitespaces are packed into single space.
  217 + *
  218 + * Returns nothing.
  219 + */
  220 +void tomoyo_normalize_line(unsigned char *buffer)
  221 +{
  222 + unsigned char *sp = buffer;
  223 + unsigned char *dp = buffer;
  224 + bool first = true;
  225 +
  226 + while (tomoyo_is_invalid(*sp))
  227 + sp++;
  228 + while (*sp) {
  229 + if (!first)
  230 + *dp++ = ' ';
  231 + first = false;
  232 + while (tomoyo_is_valid(*sp))
  233 + *dp++ = *sp++;
  234 + while (tomoyo_is_invalid(*sp))
  235 + sp++;
  236 + }
  237 + *dp = '\0';
  238 +}
  239 +
  240 +/**
  241 + * tomoyo_tokenize - Tokenize string.
  242 + *
  243 + * @buffer: The line to tokenize.
  244 + * @w: Pointer to "char *".
  245 + * @size: Sizeof @w .
  246 + *
  247 + * Returns true on success, false otherwise.
  248 + */
  249 +bool tomoyo_tokenize(char *buffer, char *w[], size_t size)
  250 +{
  251 + int count = size / sizeof(char *);
  252 + int i;
  253 + for (i = 0; i < count; i++)
  254 + w[i] = "";
  255 + for (i = 0; i < count; i++) {
  256 + char *cp = strchr(buffer, ' ');
  257 + if (cp)
  258 + *cp = '\0';
  259 + w[i] = buffer;
  260 + if (!cp)
  261 + break;
  262 + buffer = cp + 1;
  263 + }
  264 + return i < count || !*buffer;
  265 +}
  266 +
  267 +/**
  268 + * tomoyo_is_correct_path - Validate a pathname.
  269 + *
  270 + * @filename: The pathname to check.
  271 + * @start_type: Should the pathname start with '/'?
  272 + * 1 = must / -1 = must not / 0 = don't care
  273 + * @pattern_type: Can the pathname contain a wildcard?
  274 + * 1 = must / -1 = must not / 0 = don't care
  275 + * @end_type: Should the pathname end with '/'?
  276 + * 1 = must / -1 = must not / 0 = don't care
  277 + *
  278 + * Check whether the given filename follows the naming rules.
  279 + * Returns true if @filename follows the naming rules, false otherwise.
  280 + */
  281 +bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
  282 + const s8 pattern_type, const s8 end_type)
  283 +{
  284 + const char *const start = filename;
  285 + bool in_repetition = false;
  286 + bool contains_pattern = false;
  287 + unsigned char c;
  288 + unsigned char d;
  289 + unsigned char e;
  290 +
  291 + if (!filename)
  292 + goto out;
  293 + c = *filename;
  294 + if (start_type == 1) { /* Must start with '/' */
  295 + if (c != '/')
  296 + goto out;
  297 + } else if (start_type == -1) { /* Must not start with '/' */
  298 + if (c == '/')
  299 + goto out;
  300 + }
  301 + if (c)
  302 + c = *(filename + strlen(filename) - 1);
  303 + if (end_type == 1) { /* Must end with '/' */
  304 + if (c != '/')
  305 + goto out;
  306 + } else if (end_type == -1) { /* Must not end with '/' */
  307 + if (c == '/')
  308 + goto out;
  309 + }
  310 + while (1) {
  311 + c = *filename++;
  312 + if (!c)
  313 + break;
  314 + if (c == '\\') {
  315 + c = *filename++;
  316 + switch (c) {
  317 + case '\\': /* "\\" */
  318 + continue;
  319 + case '$': /* "\$" */
  320 + case '+': /* "\+" */
  321 + case '?': /* "\?" */
  322 + case '*': /* "\*" */
  323 + case '@': /* "\@" */
  324 + case 'x': /* "\x" */
  325 + case 'X': /* "\X" */
  326 + case 'a': /* "\a" */
  327 + case 'A': /* "\A" */
  328 + case '-': /* "\-" */
  329 + if (pattern_type == -1)
  330 + break; /* Must not contain pattern */
  331 + contains_pattern = true;
  332 + continue;
  333 + case '{': /* "/\{" */
  334 + if (filename - 3 < start ||
  335 + *(filename - 3) != '/')
  336 + break;
  337 + if (pattern_type == -1)
  338 + break; /* Must not contain pattern */
  339 + contains_pattern = true;
  340 + in_repetition = true;
  341 + continue;
  342 + case '}': /* "\}/" */
  343 + if (*filename != '/')
  344 + break;
  345 + if (!in_repetition)
  346 + break;
  347 + in_repetition = false;
  348 + continue;
  349 + case '0': /* "\ooo" */
  350 + case '1':
  351 + case '2':
  352 + case '3':
  353 + d = *filename++;
  354 + if (d < '0' || d > '7')
  355 + break;
  356 + e = *filename++;
  357 + if (e < '0' || e > '7')
  358 + break;
  359 + c = tomoyo_make_byte(c, d, e);
  360 + if (tomoyo_is_invalid(c))
  361 + continue; /* pattern is not \000 */
  362 + }
  363 + goto out;
  364 + } else if (in_repetition && c == '/') {
  365 + goto out;
  366 + } else if (tomoyo_is_invalid(c)) {
  367 + goto out;
  368 + }
  369 + }
  370 + if (pattern_type == 1) { /* Must contain pattern */
  371 + if (!contains_pattern)
  372 + goto out;
  373 + }
  374 + if (in_repetition)
  375 + goto out;
  376 + return true;
  377 + out:
  378 + return false;
  379 +}
  380 +
  381 +/**
  382 + * tomoyo_is_correct_domain - Check whether the given domainname follows the naming rules.
  383 + *
  384 + * @domainname: The domainname to check.
  385 + *
  386 + * Returns true if @domainname follows the naming rules, false otherwise.
  387 + */
  388 +bool tomoyo_is_correct_domain(const unsigned char *domainname)
  389 +{
  390 + unsigned char c;
  391 + unsigned char d;
  392 + unsigned char e;
  393 +
  394 + if (!domainname || strncmp(domainname, TOMOYO_ROOT_NAME,
  395 + TOMOYO_ROOT_NAME_LEN))
  396 + goto out;
  397 + domainname += TOMOYO_ROOT_NAME_LEN;
  398 + if (!*domainname)
  399 + return true;
  400 + do {
  401 + if (*domainname++ != ' ')
  402 + goto out;
  403 + if (*domainname++ != '/')
  404 + goto out;
  405 + while ((c = *domainname) != '\0' && c != ' ') {
  406 + domainname++;
  407 + if (c == '\\') {
  408 + c = *domainname++;
  409 + switch ((c)) {
  410 + case '\\': /* "\\" */
  411 + continue;
  412 + case '0': /* "\ooo" */
  413 + case '1':
  414 + case '2':
  415 + case '3':
  416 + d = *domainname++;
  417 + if (d < '0' || d > '7')
  418 + break;
  419 + e = *domainname++;
  420 + if (e < '0' || e > '7')
  421 + break;
  422 + c = tomoyo_make_byte(c, d, e);
  423 + if (tomoyo_is_invalid(c))
  424 + /* pattern is not \000 */
  425 + continue;
  426 + }
  427 + goto out;
  428 + } else if (tomoyo_is_invalid(c)) {
  429 + goto out;
  430 + }
  431 + }
  432 + } while (*domainname);
  433 + return true;
  434 + out:
  435 + return false;
  436 +}
  437 +
  438 +/**
  439 + * tomoyo_is_domain_def - Check whether the given token can be a domainname.
  440 + *
  441 + * @buffer: The token to check.
  442 + *
  443 + * Returns true if @buffer possibly be a domainname, false otherwise.
  444 + */
  445 +bool tomoyo_is_domain_def(const unsigned char *buffer)
  446 +{
  447 + return !strncmp(buffer, TOMOYO_ROOT_NAME, TOMOYO_ROOT_NAME_LEN);
  448 +}
  449 +
  450 +/**
  451 + * tomoyo_find_domain - Find a domain by the given name.
  452 + *
  453 + * @domainname: The domainname to find.
  454 + *
  455 + * Returns pointer to "struct tomoyo_domain_info" if found, NULL otherwise.
  456 + *
  457 + * Caller holds tomoyo_read_lock().
  458 + */
  459 +struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname)
  460 +{
  461 + struct tomoyo_domain_info *domain;
  462 + struct tomoyo_path_info name;
  463 +
  464 + name.name = domainname;
  465 + tomoyo_fill_path_info(&name);
  466 + list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
  467 + if (!domain->is_deleted &&
  468 + !tomoyo_pathcmp(&name, domain->domainname))
  469 + return domain;
  470 + }
  471 + return NULL;
  472 +}
  473 +
  474 +/**
  475 + * tomoyo_const_part_length - Evaluate the initial length without a pattern in a token.
  476 + *
  477 + * @filename: The string to evaluate.
  478 + *
  479 + * Returns the initial length without a pattern in @filename.
  480 + */
  481 +static int tomoyo_const_part_length(const char *filename)
  482 +{
  483 + char c;
  484 + int len = 0;
  485 +
  486 + if (!filename)
  487 + return 0;
  488 + while ((c = *filename++) != '\0') {
  489 + if (c != '\\') {
  490 + len++;
  491 + continue;
  492 + }
  493 + c = *filename++;
  494 + switch (c) {
  495 + case '\\': /* "\\" */
  496 + len += 2;
  497 + continue;
  498 + case '0': /* "\ooo" */
  499 + case '1':
  500 + case '2':
  501 + case '3':
  502 + c = *filename++;
  503 + if (c < '0' || c > '7')
  504 + break;
  505 + c = *filename++;
  506 + if (c < '0' || c > '7')
  507 + break;
  508 + len += 4;
  509 + continue;
  510 + }
  511 + break;
  512 + }
  513 + return len;
  514 +}
  515 +
  516 +/**
  517 + * tomoyo_fill_path_info - Fill in "struct tomoyo_path_info" members.
  518 + *
  519 + * @ptr: Pointer to "struct tomoyo_path_info" to fill in.
  520 + *
  521 + * The caller sets "struct tomoyo_path_info"->name.
  522 + */
  523 +void tomoyo_fill_path_info(struct tomoyo_path_info *ptr)
  524 +{
  525 + const char *name = ptr->name;
  526 + const int len = strlen(name);
  527 +
  528 + ptr->const_len = tomoyo_const_part_length(name);
  529 + ptr->is_dir = len && (name[len - 1] == '/');
  530 + ptr->is_patterned = (ptr->const_len < len);
  531 + ptr->hash = full_name_hash(name, len);
  532 +}
  533 +
  534 +/**
  535 + * tomoyo_file_matches_pattern2 - Pattern matching without '/' character and "\-" pattern.
  536 + *
  537 + * @filename: The start of string to check.
  538 + * @filename_end: The end of string to check.
  539 + * @pattern: The start of pattern to compare.
  540 + * @pattern_end: The end of pattern to compare.
  541 + *
  542 + * Returns true if @filename matches @pattern, false otherwise.
  543 + */
  544 +static bool tomoyo_file_matches_pattern2(const char *filename,
  545 + const char *filename_end,
  546 + const char *pattern,
  547 + const char *pattern_end)
  548 +{
  549 + while (filename < filename_end && pattern < pattern_end) {
  550 + char c;
  551 + if (*pattern != '\\') {
  552 + if (*filename++ != *pattern++)
  553 + return false;
  554 + continue;
  555 + }
  556 + c = *filename;
  557 + pattern++;
  558 + switch (*pattern) {
  559 + int i;
  560 + int j;
  561 + case '?':
  562 + if (c == '/') {
  563 + return false;
  564 + } else if (c == '\\') {
  565 + if (filename[1] == '\\')
  566 + filename++;
  567 + else if (tomoyo_is_byte_range(filename + 1))
  568 + filename += 3;
  569 + else
  570 + return false;
  571 + }
  572 + break;
  573 + case '\\':
  574 + if (c != '\\')
  575 + return false;
  576 + if (*++filename != '\\')
  577 + return false;
  578 + break;
  579 + case '+':
  580 + if (!isdigit(c))
  581 + return false;
  582 + break;
  583 + case 'x':
  584 + if (!isxdigit(c))
  585 + return false;
  586 + break;
  587 + case 'a':
  588 + if (!tomoyo_is_alphabet_char(c))
  589 + return false;
  590 + break;
  591 + case '0':
  592 + case '1':
  593 + case '2':
  594 + case '3':
  595 + if (c == '\\' && tomoyo_is_byte_range(filename + 1)
  596 + && strncmp(filename + 1, pattern, 3) == 0) {
  597 + filename += 3;
  598 + pattern += 2;
  599 + break;
  600 + }
  601 + return false; /* Not matched. */
  602 + case '*':
  603 + case '@':
  604 + for (i = 0; i <= filename_end - filename; i++) {
  605 + if (tomoyo_file_matches_pattern2(
  606 + filename + i, filename_end,
  607 + pattern + 1, pattern_end))
  608 + return true;
  609 + c = filename[i];
  610 + if (c == '.' && *pattern == '@')
  611 + break;
  612 + if (c != '\\')
  613 + continue;
  614 + if (filename[i + 1] == '\\')
  615 + i++;
  616 + else if (tomoyo_is_byte_range(filename + i + 1))
  617 + i += 3;
  618 + else
  619 + break; /* Bad pattern. */
  620 + }
  621 + return false; /* Not matched. */
  622 + default:
  623 + j = 0;
  624 + c = *pattern;
  625 + if (c == '$') {
  626 + while (isdigit(filename[j]))
  627 + j++;
  628 + } else if (c == 'X') {
  629 + while (isxdigit(filename[j]))
  630 + j++;
  631 + } else if (c == 'A') {
  632 + while (tomoyo_is_alphabet_char(filename[j]))
  633 + j++;
  634 + }
  635 + for (i = 1; i <= j; i++) {
  636 + if (tomoyo_file_matches_pattern2(
  637 + filename + i, filename_end,
  638 + pattern + 1, pattern_end))
  639 + return true;
  640 + }
  641 + return false; /* Not matched or bad pattern. */
  642 + }
  643 + filename++;
  644 + pattern++;
  645 + }
  646 + while (*pattern == '\\' &&
  647 + (*(pattern + 1) == '*' || *(pattern + 1) == '@'))
  648 + pattern += 2;
  649 + return filename == filename_end && pattern == pattern_end;
  650 +}
  651 +
  652 +/**
  653 + * tomoyo_file_matches_pattern - Pattern matching without '/' character.
  654 + *
  655 + * @filename: The start of string to check.
  656 + * @filename_end: The end of string to check.
  657 + * @pattern: The start of pattern to compare.
  658 + * @pattern_end: The end of pattern to compare.
  659 + *
  660 + * Returns true if @filename matches @pattern, false otherwise.
  661 + */
  662 +static bool tomoyo_file_matches_pattern(const char *filename,
  663 + const char *filename_end,
  664 + const char *pattern,
  665 + const char *pattern_end)
  666 +{
  667 + const char *pattern_start = pattern;
  668 + bool first = true;
  669 + bool result;
  670 +
  671 + while (pattern < pattern_end - 1) {
  672 + /* Split at "\-" pattern. */
  673 + if (*pattern++ != '\\' || *pattern++ != '-')
  674 + continue;
  675 + result = tomoyo_file_matches_pattern2(filename,
  676 + filename_end,
  677 + pattern_start,
  678 + pattern - 2);
  679 + if (first)
  680 + result = !result;
  681 + if (result)
  682 + return false;
  683 + first = false;
  684 + pattern_start = pattern;
  685 + }
  686 + result = tomoyo_file_matches_pattern2(filename, filename_end,
  687 + pattern_start, pattern_end);
  688 + return first ? result : !result;
  689 +}
  690 +
  691 +/**
  692 + * tomoyo_path_matches_pattern2 - Do pathname pattern matching.
  693 + *
  694 + * @f: The start of string to check.
  695 + * @p: The start of pattern to compare.
  696 + *
  697 + * Returns true if @f matches @p, false otherwise.
  698 + */
  699 +static bool tomoyo_path_matches_pattern2(const char *f, const char *p)
  700 +{
  701 + const char *f_delimiter;
  702 + const char *p_delimiter;
  703 +
  704 + while (*f && *p) {
  705 + f_delimiter = strchr(f, '/');
  706 + if (!f_delimiter)
  707 + f_delimiter = f + strlen(f);
  708 + p_delimiter = strchr(p, '/');
  709 + if (!p_delimiter)
  710 + p_delimiter = p + strlen(p);
  711 + if (*p == '\\' && *(p + 1) == '{')
  712 + goto recursive;
  713 + if (!tomoyo_file_matches_pattern(f, f_delimiter, p,
  714 + p_delimiter))
  715 + return false;
  716 + f = f_delimiter;
  717 + if (*f)
  718 + f++;
  719 + p = p_delimiter;
  720 + if (*p)
  721 + p++;
  722 + }
  723 + /* Ignore trailing "\*" and "\@" in @pattern. */
  724 + while (*p == '\\' &&
  725 + (*(p + 1) == '*' || *(p + 1) == '@'))
  726 + p += 2;
  727 + return !*f && !*p;
  728 + recursive:
  729 + /*
  730 + * The "\{" pattern is permitted only after '/' character.
  731 + * This guarantees that below "*(p - 1)" is safe.
  732 + * Also, the "\}" pattern is permitted only before '/' character
  733 + * so that "\{" + "\}" pair will not break the "\-" operator.
  734 + */
  735 + if (*(p - 1) != '/' || p_delimiter <= p + 3 || *p_delimiter != '/' ||
  736 + *(p_delimiter - 1) != '}' || *(p_delimiter - 2) != '\\')
  737 + return false; /* Bad pattern. */
  738 + do {
  739 + /* Compare current component with pattern. */
  740 + if (!tomoyo_file_matches_pattern(f, f_delimiter, p + 2,
  741 + p_delimiter - 2))
  742 + break;
  743 + /* Proceed to next component. */
  744 + f = f_delimiter;
  745 + if (!*f)
  746 + break;
  747 + f++;
  748 + /* Continue comparison. */
  749 + if (tomoyo_path_matches_pattern2(f, p_delimiter + 1))
  750 + return true;
  751 + f_delimiter = strchr(f, '/');
  752 + } while (f_delimiter);
  753 + return false; /* Not matched. */
  754 +}
  755 +
  756 +/**
  757 + * tomoyo_path_matches_pattern - Check whether the given filename matches the given pattern.
  758 + *
  759 + * @filename: The filename to check.
  760 + * @pattern: The pattern to compare.
  761 + *
  762 + * Returns true if matches, false otherwise.
  763 + *
  764 + * The following patterns are available.
  765 + * \\ \ itself.
  766 + * \ooo Octal representation of a byte.
  767 + * \* Zero or more repetitions of characters other than '/'.
  768 + * \@ Zero or more repetitions of characters other than '/' or '.'.
  769 + * \? 1 byte character other than '/'.
  770 + * \$ One or more repetitions of decimal digits.
  771 + * \+ 1 decimal digit.
  772 + * \X One or more repetitions of hexadecimal digits.
  773 + * \x 1 hexadecimal digit.
  774 + * \A One or more repetitions of alphabet characters.
  775 + * \a 1 alphabet character.
  776 + *
  777 + * \- Subtraction operator.
  778 + *
  779 + * /\{dir\}/ '/' + 'One or more repetitions of dir/' (e.g. /dir/ /dir/dir/
  780 + * /dir/dir/dir/ ).
  781 + */
  782 +bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
  783 + const struct tomoyo_path_info *pattern)
  784 +{
  785 + const char *f = filename->name;
  786 + const char *p = pattern->name;
  787 + const int len = pattern->const_len;
  788 +
  789 + /* If @pattern doesn't contain pattern, I can use strcmp(). */
  790 + if (!pattern->is_patterned)
  791 + return !tomoyo_pathcmp(filename, pattern);
  792 + /* Don't compare directory and non-directory. */
  793 + if (filename->is_dir != pattern->is_dir)
  794 + return false;
  795 + /* Compare the initial length without patterns. */
  796 + if (strncmp(f, p, len))
  797 + return false;
  798 + f += len;
  799 + p += len;
  800 + return tomoyo_path_matches_pattern2(f, p);
  801 +}
  802 +
  803 +/**
  804 + * tomoyo_get_exe - Get tomoyo_realpath() of current process.
  805 + *
  806 + * Returns the tomoyo_realpath() of current process on success, NULL otherwise.
  807 + *
  808 + * This function uses kzalloc(), so the caller must call kfree()
  809 + * if this function didn't return NULL.
  810 + */
  811 +const char *tomoyo_get_exe(void)
  812 +{
  813 + struct mm_struct *mm = current->mm;
  814 + struct vm_area_struct *vma;
  815 + const char *cp = NULL;
  816 +
  817 + if (!mm)
  818 + return NULL;
  819 + down_read(&mm->mmap_sem);
  820 + for (vma = mm->mmap; vma; vma = vma->vm_next) {
  821 + if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) {
  822 + cp = tomoyo_realpath_from_path(&vma->vm_file->f_path);
  823 + break;
  824 + }
  825 + }
  826 + up_read(&mm->mmap_sem);
  827 + return cp;
  828 +}
  829 +
  830 +/**
  831 + * tomoyo_init_request_info - Initialize "struct tomoyo_request_info" members.
  832 + *
  833 + * @r: Pointer to "struct tomoyo_request_info" to initialize.
  834 + * @domain: Pointer to "struct tomoyo_domain_info". NULL for tomoyo_domain().
  835 + *
  836 + * Returns mode.
  837 + */
  838 +int tomoyo_init_request_info(struct tomoyo_request_info *r,
  839 + struct tomoyo_domain_info *domain)
  840 +{
  841 + memset(r, 0, sizeof(*r));
  842 + if (!domain)
  843 + domain = tomoyo_domain();
  844 + r->domain = domain;
  845 + r->mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
  846 + return r->mode;
  847 +}
  848 +
  849 +/**
  850 + * tomoyo_warn_log - Print warning or error message on console.
  851 + *
  852 + * @r: Pointer to "struct tomoyo_request_info".
  853 + * @fmt: The printf()'s format string, followed by parameters.
  854 + */
  855 +void tomoyo_warn_log(struct tomoyo_request_info *r, const char *fmt, ...)
  856 +{
  857 + int len = PAGE_SIZE;
  858 + va_list args;
  859 + char *buffer;
  860 + if (!tomoyo_verbose_mode(r->domain))
  861 + return;
  862 + while (1) {
  863 + int len2;
  864 + buffer = kmalloc(len, GFP_NOFS);
  865 + if (!buffer)
  866 + return;
  867 + va_start(args, fmt);
  868 + len2 = vsnprintf(buffer, len - 1, fmt, args);
  869 + va_end(args);
  870 + if (len2 <= len - 1) {
  871 + buffer[len2] = '\0';
  872 + break;
  873 + }
  874 + len = len2 + 1;
  875 + kfree(buffer);
  876 + }
  877 + printk(KERN_WARNING "TOMOYO-%s: Access %s denied for %s\n",
  878 + r->mode == TOMOYO_CONFIG_ENFORCING ? "ERROR" : "WARNING",
  879 + buffer, tomoyo_get_last_name(r->domain));
  880 + kfree(buffer);
  881 +}
  882 +
  883 +/**
  884 + * tomoyo_domain_quota_is_ok - Check for domain's quota.
  885 + *
  886 + * @r: Pointer to "struct tomoyo_request_info".
  887 + *
  888 + * Returns true if the domain is not exceeded quota, false otherwise.
  889 + *
  890 + * Caller holds tomoyo_read_lock().
  891 + */
  892 +bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r)
  893 +{
  894 + unsigned int count = 0;
  895 + struct tomoyo_domain_info *domain = r->domain;
  896 + struct tomoyo_acl_info *ptr;
  897 +
  898 + if (r->mode != TOMOYO_CONFIG_LEARNING)
  899 + return false;
  900 + if (!domain)
  901 + return true;
  902 + list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
  903 + switch (ptr->type) {
  904 + u16 perm;
  905 + u8 i;
  906 + case TOMOYO_TYPE_PATH_ACL:
  907 + perm = container_of(ptr, struct tomoyo_path_acl, head)
  908 + ->perm;
  909 + for (i = 0; i < TOMOYO_MAX_PATH_OPERATION; i++)
  910 + if (perm & (1 << i))
  911 + count++;
  912 + if (perm & (1 << TOMOYO_TYPE_READ_WRITE))
  913 + count -= 2;
  914 + break;
  915 + case TOMOYO_TYPE_PATH2_ACL:
  916 + perm = container_of(ptr, struct tomoyo_path2_acl, head)
  917 + ->perm;
  918 + for (i = 0; i < TOMOYO_MAX_PATH2_OPERATION; i++)
  919 + if (perm & (1 << i))
  920 + count++;
  921 + break;
  922 + case TOMOYO_TYPE_PATH_NUMBER_ACL:
  923 + perm = container_of(ptr, struct tomoyo_path_number_acl,
  924 + head)->perm;
  925 + for (i = 0; i < TOMOYO_MAX_PATH_NUMBER_OPERATION; i++)
  926 + if (perm & (1 << i))
  927 + count++;
  928 + break;
  929 + case TOMOYO_TYPE_PATH_NUMBER3_ACL:
  930 + perm = container_of(ptr, struct tomoyo_path_number3_acl,
  931 + head)->perm;
  932 + for (i = 0; i < TOMOYO_MAX_PATH_NUMBER3_OPERATION; i++)
  933 + if (perm & (1 << i))
  934 + count++;
  935 + break;
  936 + case TOMOYO_TYPE_MOUNT_ACL:
  937 + if (!container_of(ptr, struct tomoyo_mount_acl, head)->
  938 + is_deleted)
  939 + count++;
  940 + }
  941 + }
  942 + if (count < tomoyo_check_flags(domain, TOMOYO_MAX_ACCEPT_ENTRY))
  943 + return true;
  944 + if (!domain->quota_warned) {
  945 + domain->quota_warned = true;
  946 + printk(KERN_WARNING "TOMOYO-WARNING: "
  947 + "Domain '%s' has so many ACLs to hold. "
  948 + "Stopped learning mode.\n", domain->domainname->name);
  949 + }
  950 + return false;
  951 +}