オープンソース・ソフトウェアの開発とダウンロード

Subversion リポジトリの参照

Contents of /trunk/1.7.x/ccs-patch/security/ccsecurity/util.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2778 - (show annotations) (download) (as text)
Sat Jul 18 12:49:32 2009 UTC (14 years, 10 months ago) by kumaneko
Original Path: branches/ccs-patch/fs/ccs_common.c
File MIME type: text/x-csrc
File size: 88117 byte(s)


1 /*
2 * fs/ccs_common.c
3 *
4 * Common functions for SAKURA and TOMOYO.
5 *
6 * Copyright (C) 2005-2009 NTT DATA CORPORATION
7 *
8 * Version: 1.7.0-pre 2009/07/03
9 *
10 * This file is applicable to both 2.4.30 and 2.6.11 and later.
11 * See README.ccs for ChangeLog.
12 *
13 */
14
15 #include <linux/version.h>
16 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
17 #define __KERNEL_SYSCALLS__
18 #endif
19 #include <linux/string.h>
20 #include <linux/mm.h>
21 #include <linux/utime.h>
22 #include <linux/file.h>
23 #include <linux/module.h>
24 #include <linux/slab.h>
25 #include <asm/uaccess.h>
26 #include <stdarg.h>
27 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
28 #include <linux/namei.h>
29 #include <linux/mount.h>
30 static const int ccs_lookup_flags = LOOKUP_FOLLOW;
31 #else
32 static const int ccs_lookup_flags = LOOKUP_FOLLOW | LOOKUP_POSITIVE;
33 #endif
34 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
35 #include <linux/unistd.h>
36 #endif
37 #include <linux/ccs_common.h>
38 #include <linux/tomoyo.h>
39
40 /* To support PID namespace. */
41 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
42 #define find_task_by_pid find_task_by_vpid
43 #endif
44
45 /* Set default specified by the kernel config. */
46 #define MAX_ACCEPT_ENTRY (CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY)
47 #define MAX_GRANT_LOG (CONFIG_CCSECURITY_MAX_GRANT_LOG)
48 #define MAX_REJECT_LOG (CONFIG_CCSECURITY_MAX_REJECT_LOG)
49
50 DEFINE_MUTEX(ccs_policy_lock);
51
52 /* Has /sbin/init started? */
53 bool ccs_policy_loaded;
54
55 /* Log level for SAKURA's printk(). */
56 const char *ccs_log_level = KERN_DEBUG;
57
58 /* String table for functionality that takes 4 modes. */
59 static const char *ccs_mode_4[4] = {
60 "disabled", "learning", "permissive", "enforcing"
61 };
62 /* String table for functionality that takes 2 modes. */
63 static const char *ccs_mode_2[4] = {
64 "disabled", "enabled", "enabled", "enabled"
65 };
66
67 /* Table for profile. */
68 static struct {
69 const char *keyword;
70 unsigned int current_value;
71 const unsigned int max_value;
72 } ccs_control_array[CCS_MAX_CONTROL_INDEX] = {
73 [CCS_MAC_FOR_FILE] = { "MAC_FOR_FILE", 0, 3 },
74 [CCS_MAC_FOR_IOCTL] = { "MAC_FOR_IOCTL", 0, 3 },
75 [CCS_MAC_FOR_ARGV0] = { "MAC_FOR_ARGV0", 0, 3 },
76 [CCS_MAC_FOR_ENV] = { "MAC_FOR_ENV", 0, 3 },
77 [CCS_MAC_FOR_NETWORK] = { "MAC_FOR_NETWORK", 0, 3 },
78 [CCS_MAC_FOR_SIGNAL] = { "MAC_FOR_SIGNAL", 0, 3 },
79 [CCS_MAC_FOR_NAMESPACE] = { "MAC_FOR_NAMESPACE", 0, 3 },
80 [CCS_RESTRICT_AUTOBIND] = { "RESTRICT_AUTOBIND", 0, 1 },
81 [CCS_MAX_ACCEPT_ENTRY]
82 = { "MAX_ACCEPT_ENTRY", MAX_ACCEPT_ENTRY, INT_MAX },
83 #ifdef CONFIG_CCSECURITY_AUDIT
84 [CCS_MAX_GRANT_LOG]
85 = { "MAX_GRANT_LOG", MAX_GRANT_LOG, INT_MAX },
86 [CCS_MAX_REJECT_LOG]
87 = { "MAX_REJECT_LOG", MAX_REJECT_LOG, INT_MAX },
88 #endif
89 [CCS_VERBOSE] = { "TOMOYO_VERBOSE", 1, 1 },
90 [CCS_SLEEP_PERIOD]
91 = { "SLEEP_PERIOD", 0, 3000 }, /* in 0.1 second */
92 };
93
94 /* Capability name used by domain policy. */
95 static const char *ccs_capability_control_keyword[CCS_MAX_CAPABILITY_INDEX]
96 = {
97 [CCS_INET_STREAM_SOCKET_CREATE] = "inet_tcp_create",
98 [CCS_INET_STREAM_SOCKET_LISTEN] = "inet_tcp_listen",
99 [CCS_INET_STREAM_SOCKET_CONNECT] = "inet_tcp_connect",
100 [CCS_USE_INET_DGRAM_SOCKET] = "use_inet_udp",
101 [CCS_USE_INET_RAW_SOCKET] = "use_inet_ip",
102 [CCS_USE_ROUTE_SOCKET] = "use_route",
103 [CCS_USE_PACKET_SOCKET] = "use_packet",
104 [CCS_SYS_MOUNT] = "SYS_MOUNT",
105 [CCS_SYS_UMOUNT] = "SYS_UMOUNT",
106 [CCS_SYS_REBOOT] = "SYS_REBOOT",
107 [CCS_SYS_CHROOT] = "SYS_CHROOT",
108 [CCS_SYS_KILL] = "SYS_KILL",
109 [CCS_SYS_VHANGUP] = "SYS_VHANGUP",
110 [CCS_SYS_SETTIME] = "SYS_TIME",
111 [CCS_SYS_NICE] = "SYS_NICE",
112 [CCS_SYS_SETHOSTNAME] = "SYS_SETHOSTNAME",
113 [CCS_USE_KERNEL_MODULE] = "use_kernel_module",
114 [CCS_CREATE_FIFO] = "create_fifo",
115 [CCS_CREATE_BLOCK_DEV] = "create_block_dev",
116 [CCS_CREATE_CHAR_DEV] = "create_char_dev",
117 [CCS_CREATE_UNIX_SOCKET] = "create_unix_socket",
118 [CCS_SYS_LINK] = "SYS_LINK",
119 [CCS_SYS_SYMLINK] = "SYS_SYMLINK",
120 [CCS_SYS_RENAME] = "SYS_RENAME",
121 [CCS_SYS_UNLINK] = "SYS_UNLINK",
122 [CCS_SYS_CHMOD] = "SYS_CHMOD",
123 [CCS_SYS_CHOWN] = "SYS_CHOWN",
124 [CCS_SYS_IOCTL] = "SYS_IOCTL",
125 [CCS_SYS_KEXEC_LOAD] = "SYS_KEXEC_LOAD",
126 [CCS_SYS_PIVOT_ROOT] = "SYS_PIVOT_ROOT",
127 [CCS_SYS_PTRACE] = "SYS_PTRACE",
128 [CCS_CONCEAL_MOUNT] = "conceal_mount",
129 };
130
131 static bool ccs_profile_entry_used[CCS_MAX_CONTROL_INDEX +
132 CCS_MAX_CAPABILITY_INDEX + 1];
133
134 /* Profile table. Memory is allocated as needed. */
135 static struct ccs_profile {
136 unsigned int value[CCS_MAX_CONTROL_INDEX];
137 const struct ccs_path_info *comment;
138 unsigned char capability_value[CCS_MAX_CAPABILITY_INDEX];
139 } *ccs_profile_ptr[MAX_PROFILES];
140
141 /* Permit policy management by non-root user? */
142 static bool ccs_manage_by_non_root;
143
144 /* Utility functions. */
145
146 /**
147 * ccs_quiet_setup - Set CCS_VERBOSE=0 by default.
148 *
149 * @str: Unused.
150 *
151 * Returns 0.
152 */
153 static int __init ccs_quiet_setup(char *str)
154 {
155 ccs_control_array[CCS_VERBOSE].current_value = 0;
156 return 0;
157 }
158
159 __setup("CCS_QUIET", ccs_quiet_setup);
160
161 /**
162 * ccs_is_byte_range - Check whether the string isa \ooo style octal value.
163 *
164 * @str: Pointer to the string.
165 *
166 * Returns true if @str is a \ooo style octal value, false otherwise.
167 */
168 static inline bool ccs_is_byte_range(const char *str)
169 {
170 return *str >= '0' && *str++ <= '3' &&
171 *str >= '0' && *str++ <= '7' &&
172 *str >= '0' && *str <= '7';
173 }
174
175 /**
176 * ccs_is_decimal - Check whether the character is a decimal character.
177 *
178 * @c: The character to check.
179 *
180 * Returns true if @c is a decimal character, false otherwise.
181 */
182 static inline bool ccs_is_decimal(const char c)
183 {
184 return c >= '0' && c <= '9';
185 }
186
187 /**
188 * ccs_is_hexadecimal - Check whether the character is a hexadecimal character.
189 *
190 * @c: The character to check.
191 *
192 * Returns true if @c is a hexadecimal character, false otherwise.
193 */
194 static inline bool ccs_is_hexadecimal(const char c)
195 {
196 return (c >= '0' && c <= '9') ||
197 (c >= 'A' && c <= 'F') ||
198 (c >= 'a' && c <= 'f');
199 }
200
201 /**
202 * ccs_is_alphabet_char - Check whether the character is an alphabet.
203 *
204 * @c: The character to check.
205 *
206 * Returns true if @c is an alphabet character, false otherwise.
207 */
208 static inline bool ccs_is_alphabet_char(const char c)
209 {
210 return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
211 }
212
213 /**
214 * ccs_make_byte - Make byte value from three octal characters.
215 *
216 * @c1: The first character.
217 * @c2: The second character.
218 * @c3: The third character.
219 *
220 * Returns byte value.
221 */
222 static inline u8 ccs_make_byte(const u8 c1, const u8 c2, const u8 c3)
223 {
224 return ((c1 - '0') << 6) + ((c2 - '0') << 3) + (c3 - '0');
225 }
226
227 /**
228 * ccs_str_starts - Check whether the given string starts with the given keyword.
229 *
230 * @src: Pointer to pointer to the string.
231 * @find: Pointer to the keyword.
232 *
233 * Returns true if @src starts with @find, false otherwise.
234 *
235 * The @src is updated to point the first character after the @find
236 * if @src starts with @find.
237 */
238 static bool ccs_str_starts(char **src, const char *find)
239 {
240 const int len = strlen(find);
241 char *tmp = *src;
242 if (strncmp(tmp, find, len))
243 return false;
244 tmp += len;
245 *src = tmp;
246 return true;
247 }
248
249 /**
250 * ccs_normalize_line - Format string.
251 *
252 * @buffer: The line to normalize.
253 *
254 * Leading and trailing whitespaces are removed.
255 * Multiple whitespaces are packed into single space.
256 *
257 * Returns nothing.
258 */
259 void ccs_normalize_line(unsigned char *buffer)
260 {
261 unsigned char *sp = buffer;
262 unsigned char *dp = buffer;
263 bool first = true;
264 while (*sp && (*sp <= ' ' || *sp >= 127))
265 sp++;
266 while (*sp) {
267 if (!first)
268 *dp++ = ' ';
269 first = false;
270 while (*sp > ' ' && *sp < 127)
271 *dp++ = *sp++;
272 while (*sp && (*sp <= ' ' || *sp >= 127))
273 sp++;
274 }
275 *dp = '\0';
276 }
277
278 /**
279 * ccs_is_correct_path - Validate a pathname.
280 * @filename: The pathname to check.
281 * @start_type: Should the pathname start with '/'?
282 * 1 = must / -1 = must not / 0 = don't care
283 * @pattern_type: Can the pathname contain a wildcard?
284 * 1 = must / -1 = must not / 0 = don't care
285 * @end_type: Should the pathname end with '/'?
286 * 1 = must / -1 = must not / 0 = don't care
287 *
288 * Check whether the given filename follows the naming rules.
289 * Returns true if @filename follows the naming rules, false otherwise.
290 */
291 bool ccs_is_correct_path(const char *filename, const s8 start_type,
292 const s8 pattern_type, const s8 end_type)
293 {
294 bool contains_pattern = false;
295 unsigned char c;
296 unsigned char d;
297 unsigned char e;
298 const char *original_filename = filename;
299 if (!filename)
300 goto out;
301 c = *filename;
302 if (start_type == 1) { /* Must start with '/' */
303 if (c != '/')
304 goto out;
305 } else if (start_type == -1) { /* Must not start with '/' */
306 if (c == '/')
307 goto out;
308 }
309 if (c)
310 c = *(filename + strlen(filename) - 1);
311 if (end_type == 1) { /* Must end with '/' */
312 if (c != '/')
313 goto out;
314 } else if (end_type == -1) { /* Must not end with '/' */
315 if (c == '/')
316 goto out;
317 }
318 while (1) {
319 c = *filename++;
320 if (!c)
321 break;
322 if (c == '\\') {
323 c = *filename++;
324 switch (c) {
325 case '\\': /* "\\" */
326 continue;
327 case '$': /* "\$" */
328 case '+': /* "\+" */
329 case '?': /* "\?" */
330 case '*': /* "\*" */
331 case '@': /* "\@" */
332 case 'x': /* "\x" */
333 case 'X': /* "\X" */
334 case 'a': /* "\a" */
335 case 'A': /* "\A" */
336 case '-': /* "\-" */
337 if (pattern_type == -1)
338 break; /* Must not contain pattern */
339 contains_pattern = true;
340 continue;
341 case '0': /* "\ooo" */
342 case '1':
343 case '2':
344 case '3':
345 d = *filename++;
346 if (d < '0' || d > '7')
347 break;
348 e = *filename++;
349 if (e < '0' || e > '7')
350 break;
351 c = ccs_make_byte(c, d, e);
352 if (c && (c <= ' ' || c >= 127))
353 continue; /* pattern is not \000 */
354 }
355 goto out;
356 } else if (c <= ' ' || c >= 127) {
357 goto out;
358 }
359 }
360 if (pattern_type == 1) { /* Must contain pattern */
361 if (!contains_pattern)
362 goto out;
363 }
364 return true;
365 out:
366 printk(KERN_DEBUG "Invalid pathname '%s'\n", original_filename);
367 return false;
368 }
369
370 /**
371 * ccs_is_correct_domain - Check whether the given domainname follows the naming rules.
372 * @domainname: The domainname to check.
373 *
374 * Returns true if @domainname follows the naming rules, false otherwise.
375 */
376 bool ccs_is_correct_domain(const unsigned char *domainname)
377 {
378 unsigned char c;
379 unsigned char d;
380 unsigned char e;
381 const char *org_domainname = domainname;
382 if (!domainname || strncmp(domainname, ROOT_NAME, ROOT_NAME_LEN))
383 goto out;
384 domainname += ROOT_NAME_LEN;
385 if (!*domainname)
386 return true;
387 do {
388 if (*domainname++ != ' ')
389 goto out;
390 if (*domainname++ != '/')
391 goto out;
392 while (1) {
393 c = *domainname;
394 if (!c || c == ' ')
395 break;
396 domainname++;
397 if (c == '\\') {
398 c = *domainname++;
399 switch ((c)) {
400 case '\\': /* "\\" */
401 continue;
402 case '0': /* "\ooo" */
403 case '1':
404 case '2':
405 case '3':
406 d = *domainname++;
407 if (d < '0' || d > '7')
408 break;
409 e = *domainname++;
410 if (e < '0' || e > '7')
411 break;
412 c = ccs_make_byte(c, d, e);
413 if (c && (c <= ' ' || c >= 127))
414 /* pattern is not \000 */
415 continue;
416 }
417 goto out;
418 } else if (c < ' ' || c >= 127) {
419 goto out;
420 }
421 }
422 } while (*domainname);
423 return true;
424 out:
425 printk(KERN_DEBUG "Invalid domainname '%s'\n", org_domainname);
426 return false;
427 }
428
429 /**
430 * ccs_is_domain_def - Check whether the given token can be a domainname.
431 *
432 * @buffer: The token to check.
433 *
434 * Returns true if @buffer possibly be a domainname, false otherwise.
435 */
436 bool ccs_is_domain_def(const unsigned char *buffer)
437 {
438 return !strncmp(buffer, ROOT_NAME, ROOT_NAME_LEN);
439 }
440
441 /**
442 * ccs_find_domain - Find a domain by the given name.
443 *
444 * @domainname: The domainname to find.
445 *
446 * Returns pointer to "struct ccs_domain_info" if found, NULL otherwise.
447 *
448 * Caller holds srcu_read_lock(&ccs_ss).
449 */
450 struct ccs_domain_info *ccs_find_domain(const char *domainname)
451 {
452 struct ccs_domain_info *domain;
453 struct ccs_path_info name;
454 name.name = domainname;
455 ccs_fill_path_info(&name);
456 list_for_each_entry_rcu(domain, &ccs_domain_list, list) {
457 if (!domain->is_deleted &&
458 !ccs_pathcmp(&name, domain->domainname))
459 return domain;
460 }
461 return NULL;
462 }
463
464 /**
465 * ccs_path_depth - Evaluate the number of '/' in a string.
466 *
467 * @pathname: The string to evaluate.
468 *
469 * Returns path depth of the string.
470 *
471 * I score 2 for each of the '/' in the @pathname
472 * and score 1 if the @pathname ends with '/'.
473 */
474 static int ccs_path_depth(const char *pathname)
475 {
476 int i = 0;
477 if (pathname) {
478 const char *ep = pathname + strlen(pathname);
479 if (pathname < ep--) {
480 if (*ep != '/')
481 i++;
482 while (pathname <= ep)
483 if (*ep-- == '/')
484 i += 2;
485 }
486 }
487 return i;
488 }
489
490 /**
491 * ccs_const_part_length - Evaluate the initial length without a pattern in a token.
492 *
493 * @filename: The string to evaluate.
494 *
495 * Returns the initial length without a pattern in @filename.
496 */
497 static int ccs_const_part_length(const char *filename)
498 {
499 char c;
500 int len = 0;
501 if (!filename)
502 return 0;
503 while (1) {
504 c = *filename++;
505 if (!c)
506 break;
507 if (c != '\\') {
508 len++;
509 continue;
510 }
511 c = *filename++;
512 switch (c) {
513 case '\\': /* "\\" */
514 len += 2;
515 continue;
516 case '0': /* "\ooo" */
517 case '1':
518 case '2':
519 case '3':
520 c = *filename++;
521 if (c < '0' || c > '7')
522 break;
523 c = *filename++;
524 if (c < '0' || c > '7')
525 break;
526 len += 4;
527 continue;
528 }
529 break;
530 }
531 return len;
532 }
533
534 /**
535 * ccs_fill_path_info - Fill in "struct ccs_path_info" members.
536 *
537 * @ptr: Pointer to "struct ccs_path_info" to fill in.
538 *
539 * The caller sets "struct ccs_path_info"->name.
540 */
541 void ccs_fill_path_info(struct ccs_path_info *ptr)
542 {
543 const char *name = ptr->name;
544 const int len = strlen(name);
545 ptr->total_len = len;
546 ptr->const_len = ccs_const_part_length(name);
547 ptr->is_dir = len && (name[len - 1] == '/');
548 ptr->is_patterned = (ptr->const_len < len);
549 ptr->hash = full_name_hash(name, len);
550 ptr->depth = ccs_path_depth(name);
551 }
552
553 /**
554 * ccs_file_matches_pattern2 - Pattern matching without '/' character
555 * and "\-" pattern.
556 *
557 * @filename: The start of string to check.
558 * @filename_end: The end of string to check.
559 * @pattern: The start of pattern to compare.
560 * @pattern_end: The end of pattern to compare.
561 *
562 * Returns true if @filename matches @pattern, false otherwise.
563 */
564 static bool ccs_file_matches_pattern2(const char *filename,
565 const char *filename_end,
566 const char *pattern,
567 const char *pattern_end)
568 {
569 while (filename < filename_end && pattern < pattern_end) {
570 char c;
571 if (*pattern != '\\') {
572 if (*filename++ != *pattern++)
573 return false;
574 continue;
575 }
576 c = *filename;
577 pattern++;
578 switch (*pattern) {
579 int i;
580 int j;
581 case '?':
582 if (c == '/') {
583 return false;
584 } else if (c == '\\') {
585 if (filename[1] == '\\')
586 filename++;
587 else if (ccs_is_byte_range(filename + 1))
588 filename += 3;
589 else
590 return false;
591 }
592 break;
593 case '\\':
594 if (c != '\\')
595 return false;
596 if (*++filename != '\\')
597 return false;
598 break;
599 case '+':
600 if (!ccs_is_decimal(c))
601 return false;
602 break;
603 case 'x':
604 if (!ccs_is_hexadecimal(c))
605 return false;
606 break;
607 case 'a':
608 if (!ccs_is_alphabet_char(c))
609 return false;
610 break;
611 case '0':
612 case '1':
613 case '2':
614 case '3':
615 if (c == '\\' && ccs_is_byte_range(filename + 1)
616 && strncmp(filename + 1, pattern, 3) == 0) {
617 filename += 3;
618 pattern += 2;
619 break;
620 }
621 return false; /* Not matched. */
622 case '*':
623 case '@':
624 for (i = 0; i <= filename_end - filename; i++) {
625 if (ccs_file_matches_pattern2(filename + i,
626 filename_end,
627 pattern + 1,
628 pattern_end))
629 return true;
630 c = filename[i];
631 if (c == '.' && *pattern == '@')
632 break;
633 if (c != '\\')
634 continue;
635 if (filename[i + 1] == '\\')
636 i++;
637 else if (ccs_is_byte_range(filename + i + 1))
638 i += 3;
639 else
640 break; /* Bad pattern. */
641 }
642 return false; /* Not matched. */
643 default:
644 j = 0;
645 c = *pattern;
646 if (c == '$') {
647 while (ccs_is_decimal(filename[j]))
648 j++;
649 } else if (c == 'X') {
650 while (ccs_is_hexadecimal(filename[j]))
651 j++;
652 } else if (c == 'A') {
653 while (ccs_is_alphabet_char(filename[j]))
654 j++;
655 }
656 for (i = 1; i <= j; i++) {
657 if (ccs_file_matches_pattern2(filename + i,
658 filename_end,
659 pattern + 1,
660 pattern_end))
661 return true;
662 }
663 return false; /* Not matched or bad pattern. */
664 }
665 filename++;
666 pattern++;
667 }
668 while (*pattern == '\\' &&
669 (*(pattern + 1) == '*' || *(pattern + 1) == '@'))
670 pattern += 2;
671 return filename == filename_end && pattern == pattern_end;
672 }
673
674 /**
675 * ccs_file_matches_pattern - Pattern matching without without '/' character.
676 *
677 * @filename: The start of string to check.
678 * @filename_end: The end of string to check.
679 * @pattern: The start of pattern to compare.
680 * @pattern_end: The end of pattern to compare.
681 *
682 * Returns true if @filename matches @pattern, false otherwise.
683 */
684 static bool ccs_file_matches_pattern(const char *filename,
685 const char *filename_end,
686 const char *pattern,
687 const char *pattern_end)
688 {
689 const char *pattern_start = pattern;
690 bool first = true;
691 bool result;
692 while (pattern < pattern_end - 1) {
693 /* Split at "\-" pattern. */
694 if (*pattern++ != '\\' || *pattern++ != '-')
695 continue;
696 result = ccs_file_matches_pattern2(filename, filename_end,
697 pattern_start, pattern - 2);
698 if (first)
699 result = !result;
700 if (result)
701 return false;
702 first = false;
703 pattern_start = pattern;
704 }
705 result = ccs_file_matches_pattern2(filename, filename_end,
706 pattern_start, pattern_end);
707 return first ? result : !result;
708 }
709
710 /**
711 * ccs_path_matches_pattern - Check whether the given filename matches the given pattern.
712 * @filename: The filename to check.
713 * @pattern: The pattern to compare.
714 *
715 * Returns true if matches, false otherwise.
716 *
717 * The following patterns are available.
718 * \\ \ itself.
719 * \ooo Octal representation of a byte.
720 * \* More than or equals to 0 character other than '/'.
721 * \@ More than or equals to 0 character other than '/' or '.'.
722 * \? 1 byte character other than '/'.
723 * \$ More than or equals to 1 decimal digit.
724 * \+ 1 decimal digit.
725 * \X More than or equals to 1 hexadecimal digit.
726 * \x 1 hexadecimal digit.
727 * \A More than or equals to 1 alphabet character.
728 * \a 1 alphabet character.
729 * \- Subtraction operator.
730 */
731 bool ccs_path_matches_pattern(const struct ccs_path_info *filename,
732 const struct ccs_path_info *pattern)
733 {
734 /*
735 if (!filename || !pattern)
736 return false;
737 */
738 const char *f = filename->name;
739 const char *p = pattern->name;
740 const int len = pattern->const_len;
741 /* If @pattern doesn't contain pattern, I can use strcmp(). */
742 if (!pattern->is_patterned)
743 return !ccs_pathcmp(filename, pattern);
744 /* Dont compare if the number of '/' differs. */
745 if (filename->depth != pattern->depth)
746 return false;
747 /* Compare the initial length without patterns. */
748 if (strncmp(f, p, len))
749 return false;
750 f += len;
751 p += len;
752 /* Main loop. Compare each directory component. */
753 while (*f && *p) {
754 const char *f_delimiter = strchr(f, '/');
755 const char *p_delimiter = strchr(p, '/');
756 if (!f_delimiter)
757 f_delimiter = f + strlen(f);
758 if (!p_delimiter)
759 p_delimiter = p + strlen(p);
760 if (!ccs_file_matches_pattern(f, f_delimiter, p, p_delimiter))
761 return false;
762 f = f_delimiter;
763 if (*f)
764 f++;
765 p = p_delimiter;
766 if (*p)
767 p++;
768 }
769 /* Ignore trailing "\*" and "\@" in @pattern. */
770 while (*p == '\\' &&
771 (*(p + 1) == '*' || *(p + 1) == '@'))
772 p += 2;
773 return !*f && !*p;
774 }
775
776 /**
777 * ccs_io_printf - Transactional printf() to "struct ccs_io_buffer" structure.
778 *
779 * @head: Pointer to "struct ccs_io_buffer".
780 * @fmt: The printf()'s format string, followed by parameters.
781 *
782 * Returns true on success, false otherwise.
783 *
784 * The snprintf() will truncate, but ccs_io_printf() won't.
785 */
786 bool ccs_io_printf(struct ccs_io_buffer *head, const char *fmt, ...)
787 {
788 va_list args;
789 int len;
790 int pos = head->read_avail;
791 int size = head->readbuf_size - pos;
792 if (size <= 0)
793 return false;
794 va_start(args, fmt);
795 len = vsnprintf(head->read_buf + pos, size, fmt, args);
796 va_end(args);
797 if (pos + len >= head->readbuf_size)
798 return false;
799 head->read_avail += len;
800 return true;
801 }
802
803 /**
804 * ccs_get_exe - Get ccs_realpath() of current process.
805 *
806 * Returns the ccs_realpath() of current process on success, NULL otherwise.
807 *
808 * This function uses kzalloc(), so the caller must kfree()
809 * if this function didn't return NULL.
810 */
811 const char *ccs_get_exe(void)
812 {
813 struct mm_struct *mm = current->mm;
814 struct vm_area_struct *vma;
815 const char *cp = NULL;
816 if (!mm)
817 return NULL;
818 down_read(&mm->mmap_sem);
819 for (vma = mm->mmap; vma; vma = vma->vm_next) {
820 if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) {
821 cp = ccs_realpath_from_dentry(vma->vm_file->f_dentry,
822 vma->vm_file->f_vfsmnt);
823 break;
824 }
825 }
826 up_read(&mm->mmap_sem);
827 return cp;
828 }
829
830 /**
831 * ccs_get_msg - Get warning message.
832 *
833 * @is_enforce: Is it enforcing mode?
834 *
835 * Returns "ERROR" or "WARNING".
836 */
837 const char *ccs_get_msg(const bool is_enforce)
838 {
839 if (is_enforce)
840 return "ERROR";
841 else
842 return "WARNING";
843 }
844
845 /**
846 * ccs_can_sleep - Check whether it is permitted to do operations that may sleep.
847 *
848 * Returns true if it is permitted to do operations that may sleep,
849 * false otherwise.
850 *
851 * TOMOYO Linux supports interactive enforcement that lets processes
852 * wait for the administrator's decision.
853 * All hooks but the one for ccs_may_autobind() are inserted where
854 * it is permitted to do operations that may sleep.
855 * Thus, this warning should not happen.
856 */
857 bool ccs_can_sleep(void)
858 {
859 static u8 count = 20;
860 if (likely(!in_interrupt()))
861 return true;
862 if (count) {
863 count--;
864 printk(KERN_ERR "BUG: sleeping function called "
865 "from invalid context.\n");
866 dump_stack();
867 }
868 return false;
869 }
870
871 /**
872 * ccs_check_flags - Check mode for specified functionality.
873 *
874 * @domain: Pointer to "struct ccs_domain_info". NULL for ccs_current_domain().
875 * @index: The functionality to check mode.
876 *
877 * Returns the mode of specified functionality.
878 */
879 unsigned int ccs_check_flags(const struct ccs_domain_info *domain,
880 const u8 index)
881 {
882 u8 profile;
883 if (!domain)
884 domain = ccs_current_domain();
885 profile = domain->profile;
886 return ccs_policy_loaded && index < CCS_MAX_CONTROL_INDEX
887 #if MAX_PROFILES != 256
888 && profile < MAX_PROFILES
889 #endif
890 && ccs_profile_ptr[profile] ?
891 ccs_profile_ptr[profile]->value[index] : 0;
892 }
893
894 /**
895 * ccs_check_capability_flags - Check mode for specified capability.
896 *
897 * @domain: Pointer to "struct ccs_domain_info". NULL for ccs_current_domain().
898 * @index: The capability to check mode.
899 *
900 * Returns the mode of specified capability.
901 */
902 static u8 ccs_check_capability_flags(const struct ccs_domain_info *domain,
903 const u8 index)
904 {
905 const u8 profile = domain ? domain->profile :
906 ccs_current_domain()->profile;
907 return ccs_policy_loaded && index < CCS_MAX_CAPABILITY_INDEX
908 #if MAX_PROFILES != 256
909 && profile < MAX_PROFILES
910 #endif
911 && ccs_profile_ptr[profile] ?
912 ccs_profile_ptr[profile]->capability_value[index] : 0;
913 }
914
915 /**
916 * ccs_cap2keyword - Convert capability operation to capability name.
917 *
918 * @operation: The capability index.
919 *
920 * Returns the name of the specified capability's name.
921 */
922 const char *ccs_cap2keyword(const u8 operation)
923 {
924 return operation < CCS_MAX_CAPABILITY_INDEX
925 ? ccs_capability_control_keyword[operation] : NULL;
926 }
927
928 /**
929 * ccs_init_request_info - Initialize "struct ccs_request_info" members.
930 *
931 * @r: Pointer to "struct ccs_request_info" to initialize.
932 * @domain: Pointer to "struct ccs_domain_info". NULL for ccs_current_domain().
933 * @index: Index number of functionality.
934 */
935 void ccs_init_request_info(struct ccs_request_info *r,
936 struct ccs_domain_info *domain, const u8 index)
937 {
938 memset(r, 0, sizeof(*r));
939 if (!domain)
940 domain = ccs_current_domain();
941 r->domain = domain;
942 r->profile = domain->profile;
943 if (index < CCS_MAX_CONTROL_INDEX)
944 r->mode = ccs_check_flags(domain, index);
945 else
946 r->mode = ccs_check_capability_flags(domain, index
947 - CCS_MAX_CONTROL_INDEX);
948 }
949
950 /**
951 * ccs_verbose_mode - Check whether TOMOYO is verbose mode.
952 *
953 * @domain: Pointer to "struct ccs_domain_info". NULL for ccs_current_domain().
954 *
955 * Returns true if domain policy violation warning should be printed to
956 * console.
957 */
958 bool ccs_verbose_mode(const struct ccs_domain_info *domain)
959 {
960 return ccs_check_flags(domain, CCS_VERBOSE) != 0;
961 }
962
963 /**
964 * ccs_domain_quota_ok - Check for domain's quota.
965 *
966 * @domain: Pointer to "struct ccs_domain_info".
967 *
968 * Returns true if the domain is not exceeded quota, false otherwise.
969 *
970 * Caller holds srcu_read_lock(&ccs_ss).
971 */
972 bool ccs_domain_quota_ok(struct ccs_domain_info * const domain)
973 {
974 unsigned int count = 0;
975 struct ccs_acl_info *ptr;
976 if (!domain)
977 return true;
978 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
979 if (ptr->type & ACL_DELETED)
980 continue;
981 switch (ccs_acl_type2(ptr)) {
982 struct ccs_single_path_acl_record *acl1;
983 struct ccs_double_path_acl_record *acl2;
984 u16 perm;
985 case TYPE_SINGLE_PATH_ACL:
986 acl1 = container_of(ptr,
987 struct ccs_single_path_acl_record,
988 head);
989 perm = acl1->perm;
990 if (perm & (1 << TYPE_EXECUTE_ACL))
991 count++;
992 if (perm &
993 ((1 << TYPE_READ_ACL) | (1 << TYPE_WRITE_ACL)))
994 count++;
995 if (perm & (1 << TYPE_CREATE_ACL))
996 count++;
997 if (perm & (1 << TYPE_UNLINK_ACL))
998 count++;
999 if (perm & (1 << TYPE_MKDIR_ACL))
1000 count++;
1001 if (perm & (1 << TYPE_RMDIR_ACL))
1002 count++;
1003 if (perm & (1 << TYPE_MKFIFO_ACL))
1004 count++;
1005 if (perm & (1 << TYPE_MKSOCK_ACL))
1006 count++;
1007 if (perm & (1 << TYPE_MKBLOCK_ACL))
1008 count++;
1009 if (perm & (1 << TYPE_MKCHAR_ACL))
1010 count++;
1011 if (perm & (1 << TYPE_TRUNCATE_ACL))
1012 count++;
1013 if (perm & (1 << TYPE_SYMLINK_ACL))
1014 count++;
1015 if (perm & (1 << TYPE_REWRITE_ACL))
1016 count++;
1017 break;
1018 case TYPE_DOUBLE_PATH_ACL:
1019 acl2 = container_of(ptr,
1020 struct ccs_double_path_acl_record,
1021 head);
1022 perm = acl2->perm;
1023 if (perm & (1 << TYPE_LINK_ACL))
1024 count++;
1025 if (perm & (1 << TYPE_RENAME_ACL))
1026 count++;
1027 break;
1028 case TYPE_EXECUTE_HANDLER:
1029 case TYPE_DENIED_EXECUTE_HANDLER:
1030 break;
1031 default:
1032 count++;
1033 }
1034 }
1035 if (count < ccs_check_flags(domain, CCS_MAX_ACCEPT_ENTRY))
1036 return true;
1037 if (!domain->quota_warned) {
1038 domain->quota_warned = true;
1039 printk(KERN_WARNING "TOMOYO-WARNING: "
1040 "Domain '%s' has so many ACLs to hold. "
1041 "Stopped learning mode.\n", domain->domainname->name);
1042 }
1043 return false;
1044 }
1045
1046 /**
1047 * ccs_find_or_assign_new_profile - Create a new profile.
1048 *
1049 * @profile: Profile number to create.
1050 *
1051 * Returns pointer to "struct ccs_profile" on success, NULL otherwise.
1052 */
1053 static struct ccs_profile *ccs_find_or_assign_new_profile(const unsigned int
1054 profile)
1055 {
1056 struct ccs_profile *ptr;
1057 struct ccs_profile *entry;
1058 int i;
1059 if (profile >= MAX_PROFILES)
1060 return NULL;
1061 ptr = ccs_profile_ptr[profile];
1062 if (ptr)
1063 return ptr;
1064 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
1065 mutex_lock(&ccs_policy_lock);
1066 ptr = ccs_profile_ptr[profile];
1067 if (!ptr && ccs_memory_ok(entry, sizeof(*entry))) {
1068 ptr = entry;
1069 for (i = 0; i < CCS_MAX_CONTROL_INDEX; i++)
1070 ptr->value[i] = ccs_control_array[i].current_value;
1071 /*
1072 * Needn't to initialize "ptr->capability_value"
1073 * because they are always 0.
1074 */
1075 mb(); /* Avoid out-of-order execution. */
1076 ccs_profile_ptr[profile] = ptr;
1077 entry = NULL;
1078 }
1079 mutex_unlock(&ccs_policy_lock);
1080 kfree(entry);
1081 return ptr;
1082 }
1083
1084 /**
1085 * ccs_write_profile - Write profile table.
1086 *
1087 * @head: Pointer to "struct ccs_io_buffer".
1088 *
1089 * Returns 0 on success, negative value otherwise.
1090 */
1091 static int ccs_write_profile(struct ccs_io_buffer *head)
1092 {
1093 char *data = head->write_buf;
1094 unsigned int i;
1095 unsigned int value;
1096 char *cp;
1097 struct ccs_profile *ccs_profile;
1098 i = simple_strtoul(data, &cp, 10);
1099 if (data != cp) {
1100 if (*cp != '-')
1101 return -EINVAL;
1102 data = cp + 1;
1103 }
1104 ccs_profile = ccs_find_or_assign_new_profile(i);
1105 if (!ccs_profile)
1106 return -EINVAL;
1107 cp = strchr(data, '=');
1108 if (!cp)
1109 return -EINVAL;
1110 *cp = '\0';
1111 if (!strcmp(data, "COMMENT")) {
1112 ccs_profile->comment = ccs_get_name(cp + 1);
1113 ccs_profile_entry_used[0] = true;
1114 return 0;
1115 }
1116 if (ccs_str_starts(&data, KEYWORD_MAC_FOR_CAPABILITY)) {
1117 if (sscanf(cp + 1, "%u", &value) != 1) {
1118 for (i = 0; i < 4; i++) {
1119 if (strcmp(cp + 1, ccs_mode_4[i]))
1120 continue;
1121 value = i;
1122 break;
1123 }
1124 if (i == 4)
1125 return -EINVAL;
1126 }
1127 if (value > 3)
1128 value = 3;
1129 for (i = 0; i < CCS_MAX_CAPABILITY_INDEX; i++) {
1130 if (strcmp(data, ccs_capability_control_keyword[i]))
1131 continue;
1132 ccs_profile->capability_value[i] = value;
1133 ccs_profile_entry_used[i + 1 + CCS_MAX_CONTROL_INDEX]
1134 = true;
1135 return 0;
1136 }
1137 return -EINVAL;
1138 }
1139 for (i = 0; i < CCS_MAX_CONTROL_INDEX; i++) {
1140 if (strcmp(data, ccs_control_array[i].keyword))
1141 continue;
1142 if (sscanf(cp + 1, "%u", &value) != 1) {
1143 int j;
1144 const char **modes;
1145 switch (i) {
1146 case CCS_RESTRICT_AUTOBIND:
1147 case CCS_VERBOSE:
1148 modes = ccs_mode_2;
1149 break;
1150 default:
1151 modes = ccs_mode_4;
1152 break;
1153 }
1154 for (j = 0; j < 4; j++) {
1155 if (strcmp(cp + 1, modes[j]))
1156 continue;
1157 value = j;
1158 break;
1159 }
1160 if (j == 4)
1161 return -EINVAL;
1162 } else if (value > ccs_control_array[i].max_value) {
1163 value = ccs_control_array[i].max_value;
1164 }
1165 ccs_profile->value[i] = value;
1166 ccs_profile_entry_used[i + 1] = true;
1167 return 0;
1168 }
1169 return -EINVAL;
1170 }
1171
1172 /**
1173 * ccs_read_profile - Read profile table.
1174 *
1175 * @head: Pointer to "struct ccs_io_buffer".
1176 *
1177 * Returns 0.
1178 */
1179 static int ccs_read_profile(struct ccs_io_buffer *head)
1180 {
1181 static const int ccs_total
1182 = CCS_MAX_CONTROL_INDEX + CCS_MAX_CAPABILITY_INDEX + 1;
1183 int step;
1184 if (head->read_eof)
1185 return 0;
1186 for (step = head->read_step; step < MAX_PROFILES * ccs_total; step++) {
1187 const u8 index = step / ccs_total;
1188 u8 type = step % ccs_total;
1189 const struct ccs_profile *ccs_profile = ccs_profile_ptr[index];
1190 head->read_step = step;
1191 if (!ccs_profile)
1192 continue;
1193 if (!ccs_profile_entry_used[type])
1194 continue;
1195 if (!type) { /* Print profile' comment tag. */
1196 if (!ccs_io_printf(head, "%u-COMMENT=%s\n",
1197 index, ccs_profile->comment ?
1198 ccs_profile->comment->name : ""))
1199 break;
1200 continue;
1201 }
1202 type--;
1203 if (type >= CCS_MAX_CONTROL_INDEX) {
1204 const int i = type - CCS_MAX_CONTROL_INDEX;
1205 const u8 value = ccs_profile->capability_value[i];
1206 if (!ccs_io_printf(head,
1207 "%u-" KEYWORD_MAC_FOR_CAPABILITY
1208 "%s=%s\n", index,
1209 ccs_capability_control_keyword[i],
1210 ccs_mode_4[value]))
1211 break;
1212 } else {
1213 const unsigned int value = ccs_profile->value[type];
1214 const char **modes = NULL;
1215 const char *keyword = ccs_control_array[type].keyword;
1216 switch (ccs_control_array[type].max_value) {
1217 case 3:
1218 modes = ccs_mode_4;
1219 break;
1220 case 1:
1221 modes = ccs_mode_2;
1222 break;
1223 }
1224 if (modes) {
1225 if (!ccs_io_printf(head, "%u-%s=%s\n", index,
1226 keyword, modes[value]))
1227 break;
1228 } else {
1229 if (!ccs_io_printf(head, "%u-%s=%u\n", index,
1230 keyword, value))
1231 break;
1232 }
1233 }
1234 }
1235 if (step == MAX_PROFILES * ccs_total)
1236 head->read_eof = true;
1237 return 0;
1238 }
1239
1240 /* The list for "struct ccs_policy_manager_entry". */
1241 LIST_HEAD(ccs_policy_manager_list);
1242
1243 /**
1244 * ccs_update_manager_entry - Add a manager entry.
1245 *
1246 * @manager: The path to manager or the domainnamme.
1247 * @is_delete: True if it is a delete request.
1248 *
1249 * Returns 0 on success, negative value otherwise.
1250 */
1251 static int ccs_update_manager_entry(const char *manager, const bool is_delete)
1252 {
1253 struct ccs_policy_manager_entry *entry = NULL;
1254 struct ccs_policy_manager_entry *ptr;
1255 const struct ccs_path_info *saved_manager;
1256 int error = is_delete ? -ENOENT : -ENOMEM;
1257 bool is_domain = false;
1258 if (ccs_is_domain_def(manager)) {
1259 if (!ccs_is_correct_domain(manager))
1260 return -EINVAL;
1261 is_domain = true;
1262 } else {
1263 if (!ccs_is_correct_path(manager, 1, -1, -1))
1264 return -EINVAL;
1265 }
1266 saved_manager = ccs_get_name(manager);
1267 if (!saved_manager)
1268 return -ENOMEM;
1269 if (!is_delete)
1270 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
1271 mutex_lock(&ccs_policy_lock);
1272 list_for_each_entry_rcu(ptr, &ccs_policy_manager_list, list) {
1273 if (ptr->manager != saved_manager)
1274 continue;
1275 ptr->is_deleted = is_delete;
1276 error = 0;
1277 break;
1278 }
1279 if (!is_delete && error && ccs_memory_ok(entry, sizeof(*entry))) {
1280 entry->manager = saved_manager;
1281 saved_manager = NULL;
1282 entry->is_domain = is_domain;
1283 list_add_tail_rcu(&entry->list, &ccs_policy_manager_list);
1284 entry = NULL;
1285 error = 0;
1286 }
1287 mutex_unlock(&ccs_policy_lock);
1288 ccs_put_name(saved_manager);
1289 kfree(entry);
1290 return error;
1291 }
1292
1293 /**
1294 * ccs_write_manager_policy - Write manager policy.
1295 *
1296 * @head: Pointer to "struct ccs_io_buffer".
1297 *
1298 * Returns 0 on success, negative value otherwise.
1299 */
1300 static int ccs_write_manager_policy(struct ccs_io_buffer *head)
1301 {
1302 char *data = head->write_buf;
1303 bool is_delete = ccs_str_starts(&data, KEYWORD_DELETE);
1304 if (!strcmp(data, "manage_by_non_root")) {
1305 ccs_manage_by_non_root = !is_delete;
1306 return 0;
1307 }
1308 return ccs_update_manager_entry(data, is_delete);
1309 }
1310
1311 /**
1312 * ccs_read_manager_policy - Read manager policy.
1313 *
1314 * @head: Pointer to "struct ccs_io_buffer".
1315 *
1316 * Returns 0.
1317 *
1318 * Caller holds srcu_read_lock(&ccs_ss).
1319 */
1320 static int ccs_read_manager_policy(struct ccs_io_buffer *head)
1321 {
1322 struct list_head *pos;
1323 if (head->read_eof)
1324 return 0;
1325 list_for_each_cookie(pos, head->read_var2, &ccs_policy_manager_list) {
1326 struct ccs_policy_manager_entry *ptr;
1327 ptr = list_entry(pos, struct ccs_policy_manager_entry, list);
1328 if (ptr->is_deleted)
1329 continue;
1330 if (!ccs_io_printf(head, "%s\n", ptr->manager->name))
1331 return 0;
1332 }
1333 head->read_eof = true;
1334 return 0;
1335 }
1336
1337 /**
1338 * ccs_is_policy_manager - Check whether the current process is a policy manager.
1339 *
1340 * Returns true if the current process is permitted to modify policy
1341 * via /proc/ccs/ interface.
1342 *
1343 * Caller holds srcu_read_lock(&ccs_ss).
1344 */
1345 static bool ccs_is_policy_manager(void)
1346 {
1347 struct ccs_policy_manager_entry *ptr;
1348 const char *exe;
1349 struct task_struct *task = current;
1350 const struct ccs_path_info *domainname
1351 = ccs_current_domain()->domainname;
1352 bool found = false;
1353 if (!ccs_policy_loaded)
1354 return true;
1355 if (task->ccs_flags & CCS_TASK_IS_POLICY_MANAGER)
1356 return true;
1357 if (!ccs_manage_by_non_root && (current_uid() || current_euid()))
1358 return false;
1359 list_for_each_entry_rcu(ptr, &ccs_policy_manager_list, list) {
1360 if (!ptr->is_deleted && ptr->is_domain
1361 && !ccs_pathcmp(domainname, ptr->manager)) {
1362 /* Set manager flag. */
1363 task->ccs_flags |= CCS_TASK_IS_POLICY_MANAGER;
1364 return true;
1365 }
1366 }
1367 exe = ccs_get_exe();
1368 if (!exe)
1369 return false;
1370 list_for_each_entry_rcu(ptr, &ccs_policy_manager_list, list) {
1371 if (!ptr->is_deleted && !ptr->is_domain
1372 && !strcmp(exe, ptr->manager->name)) {
1373 found = true;
1374 /* Set manager flag. */
1375 task->ccs_flags |= CCS_TASK_IS_POLICY_MANAGER;
1376 break;
1377 }
1378 }
1379 if (!found) { /* Reduce error messages. */
1380 static pid_t ccs_last_pid;
1381 const pid_t pid = current->pid;
1382 if (ccs_last_pid != pid) {
1383 printk(KERN_WARNING "%s ( %s ) is not permitted to "
1384 "update policies.\n", domainname->name, exe);
1385 ccs_last_pid = pid;
1386 }
1387 }
1388 kfree(exe);
1389 return found;
1390 }
1391
1392 /**
1393 * ccs_find_condition_part - Find condition part from the statement.
1394 *
1395 * @data: String to parse.
1396 *
1397 * Returns pointer to the condition part if it was found in the statement,
1398 * NULL otherwise.
1399 */
1400 static char *ccs_find_condition_part(char *data)
1401 {
1402 char *cp = strstr(data, " if ");
1403 if (cp) {
1404 while (1) {
1405 char *cp2 = strstr(cp + 3, " if ");
1406 if (!cp2)
1407 break;
1408 cp = cp2;
1409 }
1410 *cp++ = '\0';
1411 } else {
1412 cp = strstr(data, " ; set ");
1413 if (cp)
1414 *cp++ = '\0';
1415 }
1416 return cp;
1417 }
1418
1419 /**
1420 * ccs_is_select_one - Parse select command.
1421 *
1422 * @head: Pointer to "struct ccs_io_buffer".
1423 * @data: String to parse.
1424 *
1425 * Returns true on success, false otherwise.
1426 *
1427 * Caller holds srcu_read_lock(&ccs_ss).
1428 */
1429 static bool ccs_is_select_one(struct ccs_io_buffer *head, const char *data)
1430 {
1431 unsigned int pid;
1432 struct ccs_domain_info *domain = NULL;
1433 if (!strcmp(data, "allow_execute")) {
1434 head->read_execute_only = true;
1435 return true;
1436 }
1437 if (sscanf(data, "pid=%u", &pid) == 1) {
1438 struct task_struct *p;
1439 /***** CRITICAL SECTION START *****/
1440 read_lock(&tasklist_lock);
1441 p = find_task_by_pid(pid);
1442 if (p)
1443 domain = ccs_task_domain(p);
1444 read_unlock(&tasklist_lock);
1445 /***** CRITICAL SECTION END *****/
1446 } else if (!strncmp(data, "domain=", 7)) {
1447 if (ccs_is_domain_def(data + 7))
1448 domain = ccs_find_domain(data + 7);
1449 } else
1450 return false;
1451 head->write_var1 = domain;
1452 /* Accessing read_buf is safe because head->io_sem is held. */
1453 if (!head->read_buf)
1454 return true; /* Do nothing if open(O_WRONLY). */
1455 head->read_avail = 0;
1456 ccs_io_printf(head, "# select %s\n", data);
1457 head->read_single_domain = true;
1458 head->read_eof = !domain;
1459 if (domain) {
1460 struct ccs_domain_info *d;
1461 head->read_var1 = NULL;
1462 list_for_each_entry_rcu(d, &ccs_domain_list, list) {
1463 if (d == domain)
1464 break;
1465 head->read_var1 = &d->list;
1466 }
1467 head->read_var2 = NULL;
1468 head->read_bit = 0;
1469 head->read_step = 0;
1470 if (domain->is_deleted)
1471 ccs_io_printf(head, "# This is a deleted domain.\n");
1472 }
1473 return true;
1474 }
1475
1476 /**
1477 * ccs_write_domain_policy - Write domain policy.
1478 *
1479 * @head: Pointer to "struct ccs_io_buffer".
1480 *
1481 * Returns 0 on success, negative value otherwise.
1482 */
1483 static int ccs_write_domain_policy(struct ccs_io_buffer *head)
1484 {
1485 char *data = head->write_buf;
1486 struct ccs_domain_info *domain = head->write_var1;
1487 bool is_delete = false;
1488 bool is_select = false;
1489 unsigned int profile;
1490 struct ccs_condition *cond = NULL;
1491 char *cp;
1492 int error;
1493 if (ccs_str_starts(&data, KEYWORD_DELETE))
1494 is_delete = true;
1495 else if (ccs_str_starts(&data, KEYWORD_SELECT))
1496 is_select = true;
1497 if (is_select && ccs_is_select_one(head, data))
1498 return 0;
1499 /* Don't allow updating policies by non manager programs. */
1500 if (!ccs_is_policy_manager())
1501 return -EPERM;
1502 if (ccs_is_domain_def(data)) {
1503 domain = NULL;
1504 if (is_delete)
1505 ccs_delete_domain(data);
1506 else if (is_select)
1507 domain = ccs_find_domain(data);
1508 else
1509 domain = ccs_find_or_assign_new_domain(data, 0);
1510 head->write_var1 = domain;
1511 return 0;
1512 }
1513 if (!domain)
1514 return -EINVAL;
1515
1516 if (sscanf(data, KEYWORD_USE_PROFILE "%u", &profile) == 1
1517 && profile < MAX_PROFILES) {
1518 if (ccs_profile_ptr[profile] || !ccs_policy_loaded)
1519 domain->profile = (u8) profile;
1520 return 0;
1521 }
1522 if (!strcmp(data, KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) {
1523 domain->ignore_global_allow_read = !is_delete;
1524 return 0;
1525 }
1526 if (!strcmp(data, KEYWORD_IGNORE_GLOBAL_ALLOW_ENV)) {
1527 domain->ignore_global_allow_env = !is_delete;
1528 return 0;
1529 }
1530 cp = ccs_find_condition_part(data);
1531 if (cp) {
1532 cond = ccs_get_condition(cp);
1533 if (!cond)
1534 return -EINVAL;
1535 }
1536 if (ccs_str_starts(&data, KEYWORD_ALLOW_CAPABILITY))
1537 error = ccs_write_capability_policy(data, domain, cond,
1538 is_delete);
1539 else if (ccs_str_starts(&data, KEYWORD_ALLOW_NETWORK))
1540 error = ccs_write_network_policy(data, domain, cond, is_delete);
1541 else if (ccs_str_starts(&data, KEYWORD_ALLOW_SIGNAL))
1542 error = ccs_write_signal_policy(data, domain, cond, is_delete);
1543 else if (ccs_str_starts(&data, KEYWORD_ALLOW_ARGV0))
1544 error = ccs_write_argv0_policy(data, domain, cond, is_delete);
1545 else if (ccs_str_starts(&data, KEYWORD_ALLOW_ENV))
1546 error = ccs_write_env_policy(data, domain, cond, is_delete);
1547 else if (ccs_str_starts(&data, KEYWORD_ALLOW_IOCTL))
1548 error = ccs_write_ioctl_policy(data, domain, cond, is_delete);
1549 else if (ccs_str_starts(&data, KEYWORD_ALLOW_MOUNT))
1550 error = ccs_write_mount_policy(data, domain, cond, is_delete);
1551 else if (ccs_str_starts(&data, KEYWORD_ALLOW_UNMOUNT))
1552 error = ccs_write_umount_policy(data, domain, cond, is_delete);
1553 else if (ccs_str_starts(&data, KEYWORD_ALLOW_CHROOT))
1554 error = ccs_write_chroot_policy(data, domain, cond, is_delete);
1555 else if (ccs_str_starts(&data, KEYWORD_ALLOW_PIVOT_ROOT))
1556 error = ccs_write_pivot_root_policy(data, domain, cond,
1557 is_delete);
1558 else
1559 error = ccs_write_file_policy(data, domain, cond, is_delete);
1560 if (cond)
1561 ccs_put_condition(cond);
1562 return error;
1563 }
1564
1565 /**
1566 * ccs_print_single_path_acl - Print a single path ACL entry.
1567 *
1568 * @head: Pointer to "struct ccs_io_buffer".
1569 * @ptr: Pointer to "struct ccs_single_path_acl_record".
1570 * @cond: Pointer to "struct ccs_condition". May be NULL.
1571 *
1572 * Returns true on success, false otherwise.
1573 */
1574 static bool ccs_print_single_path_acl(struct ccs_io_buffer *head,
1575 struct ccs_single_path_acl_record *ptr,
1576 const struct ccs_condition *cond)
1577 {
1578 int pos;
1579 u8 bit;
1580 const char *atmark = "";
1581 const char *filename;
1582 const u16 perm = ptr->perm;
1583 if (ptr->u_is_group) {
1584 atmark = "@";
1585 filename = ptr->u.group->group_name->name;
1586 } else {
1587 filename = ptr->u.filename->name;
1588 }
1589 for (bit = head->read_bit; bit < MAX_SINGLE_PATH_OPERATION; bit++) {
1590 const char *msg;
1591 if (!(perm & (1 << bit)))
1592 continue;
1593 if (head->read_execute_only && bit != TYPE_EXECUTE_ACL)
1594 continue;
1595 /* Print "read/write" instead of "read" and "write". */
1596 if ((bit == TYPE_READ_ACL || bit == TYPE_WRITE_ACL)
1597 && (perm & (1 << TYPE_READ_WRITE_ACL)))
1598 continue;
1599 msg = ccs_sp2keyword(bit);
1600 pos = head->read_avail;
1601 if (!ccs_io_printf(head, "allow_%s %s%s", msg,
1602 atmark, filename) ||
1603 !ccs_print_condition(head, cond))
1604 goto out;
1605 }
1606 head->read_bit = 0;
1607 return true;
1608 out:
1609 head->read_bit = bit;
1610 head->read_avail = pos;
1611 return false;
1612 }
1613
1614 /**
1615 * ccs_print_mkdev_acl - Print a mkdev ACL entry.
1616 *
1617 * @head: Pointer to "struct ccs_io_buffer".
1618 * @ptr: Pointer to "struct ccs_mkdev_acl_record".
1619 * @cond: Pointer to "struct ccs_condition". May be NULL.
1620 *
1621 * Returns true on success, false otherwise.
1622 */
1623 static bool ccs_print_mkdev_acl(struct ccs_io_buffer *head,
1624 struct ccs_mkdev_acl_record *ptr,
1625 const struct ccs_condition *cond)
1626 {
1627 int pos;
1628 u8 bit;
1629 const char *atmark = "";
1630 const char *filename;
1631 const u16 perm = ptr->perm;
1632 if (ptr->u_is_group) {
1633 atmark = "@";
1634 filename = ptr->u.group->group_name->name;
1635 } else {
1636 filename = ptr->u.filename->name;
1637 }
1638 for (bit = head->read_bit; bit < MAX_MKDEV_OPERATION; bit++) {
1639 const char *msg;
1640 const unsigned int min_major = ptr->min_major;
1641 const unsigned int max_major = ptr->max_major;
1642 const unsigned int min_minor = ptr->min_minor;
1643 const unsigned int max_minor = ptr->max_minor;
1644 if (!(perm & (1 << bit)))
1645 continue;
1646 msg = ccs_mkdev2keyword(bit);
1647 pos = head->read_avail;
1648 if (!ccs_io_printf(head, "allow_%s %s%s %u", msg, atmark,
1649 filename, min_major) ||
1650 (min_major != max_major &&
1651 !ccs_io_printf(head, "-%u", max_major)) ||
1652 !ccs_io_printf(head, " %u", min_minor) ||
1653 (min_minor != max_minor &&
1654 !ccs_io_printf(head, "-%u", max_minor)) ||
1655 !ccs_print_condition(head, cond))
1656 goto out;
1657 }
1658 head->read_bit = 0;
1659 return true;
1660 out:
1661 head->read_bit = bit;
1662 head->read_avail = pos;
1663 return false;
1664 }
1665
1666 /**
1667 * ccs_print_double_path_acl - Print a double path ACL entry.
1668 *
1669 * @head: Pointer to "struct ccs_io_buffer".
1670 * @ptr: Pointer to "struct ccs_double_path_acl_record".
1671 * @cond: Pointer to "struct ccs_condition". May be NULL.
1672 *
1673 * Returns true on success, false otherwise.
1674 */
1675 static bool ccs_print_double_path_acl(struct ccs_io_buffer *head,
1676 struct ccs_double_path_acl_record *ptr,
1677 const struct ccs_condition *cond)
1678 {
1679 int pos;
1680 const char *atmark1 = "";
1681 const char *atmark2 = "";
1682 const char *filename1;
1683 const char *filename2;
1684 const u8 perm = ptr->perm;
1685 u8 bit;
1686 if (ptr->u1_is_group) {
1687 atmark1 = "@";
1688 filename1 = ptr->u1.group1->group_name->name;
1689 } else {
1690 filename1 = ptr->u1.filename1->name;
1691 }
1692 if (ptr->u2_is_group) {
1693 atmark2 = "@";
1694 filename2 = ptr->u2.group2->group_name->name;
1695 } else {
1696 filename2 = ptr->u2.filename2->name;
1697 }
1698 for (bit = head->read_bit; bit < MAX_DOUBLE_PATH_OPERATION; bit++) {
1699 const char *msg;
1700 if (!(perm & (1 << bit)))
1701 continue;
1702 msg = ccs_dp2keyword(bit);
1703 pos = head->read_avail;
1704 if (!ccs_io_printf(head, "allow_%s %s%s %s%s", msg,
1705 atmark1, filename1, atmark2, filename2) ||
1706 !ccs_print_condition(head, cond))
1707 goto out;
1708 }
1709 head->read_bit = 0;
1710 return true;
1711 out:
1712 head->read_bit = bit;
1713 head->read_avail = pos;
1714 return false;
1715 }
1716
1717 /**
1718 * ccs_print_ioctl_acl - Print an ioctl ACL entry.
1719 *
1720 * @head: Pointer to "struct ccs_io_buffer".
1721 * @ptr: Pointer to "struct ccs_ioctl_acl_record".
1722 * @cond: Pointer to "struct ccs_condition". May be NULL.
1723 *
1724 * Returns true on success, false otherwise.
1725 */
1726 static bool ccs_print_ioctl_acl(struct ccs_io_buffer *head,
1727 struct ccs_ioctl_acl_record *ptr,
1728 const struct ccs_condition *cond)
1729 {
1730 int pos = head->read_avail;
1731 const char *atmark = "";
1732 const char *filename;
1733 const unsigned int cmd_min = ptr->cmd_min;
1734 const unsigned int cmd_max = ptr->cmd_max;
1735 if (ptr->u_is_group) {
1736 atmark = "@";
1737 filename = ptr->u.group->group_name->name;
1738 } else {
1739 filename = ptr->u.filename->name;
1740 }
1741 if (!ccs_io_printf(head, KEYWORD_ALLOW_IOCTL "%s%s ", atmark, filename))
1742 goto out;
1743 if (!ccs_io_printf(head, "%u", cmd_min))
1744 goto out;
1745 if (cmd_min != cmd_max && !ccs_io_printf(head, "-%u", cmd_max))
1746 goto out;
1747 if (!ccs_print_condition(head, cond))
1748 goto out;
1749 return true;
1750 out:
1751 head->read_avail = pos;
1752 return false;
1753 }
1754
1755 /**
1756 * ccs_print_argv0_acl - Print an argv[0] ACL entry.
1757 *
1758 * @head: Pointer to "struct ccs_io_buffer".
1759 * @ptr: Pointer to "struct ccs_argv0_acl_record".
1760 * @cond: Pointer to "struct ccs_condition". May be NULL.
1761 *
1762 * Returns true on success, false otherwise.
1763 */
1764 static bool ccs_print_argv0_acl(struct ccs_io_buffer *head,
1765 struct ccs_argv0_acl_record *ptr,
1766 const struct ccs_condition *cond)
1767 {
1768 int pos = head->read_avail;
1769 if (!ccs_io_printf(head, KEYWORD_ALLOW_ARGV0 "%s %s",
1770 ptr->filename->name, ptr->argv0->name))
1771 goto out;
1772 if (!ccs_print_condition(head, cond))
1773 goto out;
1774 return true;
1775 out:
1776 head->read_avail = pos;
1777 return false;
1778 }
1779
1780 /**
1781 * ccs_print_env_acl - Print an evironment variable name's ACL entry.
1782 *
1783 * @head: Pointer to "struct ccs_io_buffer".
1784 * @ptr: Pointer to "struct ccs_env_acl_record".
1785 * @cond: Pointer to "struct ccs_condition". May be NULL.
1786 *
1787 * Returns true on success, false otherwise.
1788 */
1789 static bool ccs_print_env_acl(struct ccs_io_buffer *head,
1790 struct ccs_env_acl_record *ptr,
1791 const struct ccs_condition *cond)
1792 {
1793 int pos = head->read_avail;
1794 if (!ccs_io_printf(head, KEYWORD_ALLOW_ENV "%s", ptr->env->name))
1795 goto out;
1796 if (!ccs_print_condition(head, cond))
1797 goto out;
1798 return true;
1799 out:
1800 head->read_avail = pos;
1801 return false;
1802 }
1803
1804 /**
1805 * ccs_print_capability_acl - Print a capability ACL entry.
1806 *
1807 * @head: Pointer to "struct ccs_io_buffer".
1808 * @ptr: Pointer to "struct ccs_capability_acl_record".
1809 * @cond: Pointer to "struct ccs_condition". May be NULL.
1810 *
1811 * Returns true on success, false otherwise.
1812 */
1813 static bool ccs_print_capability_acl(struct ccs_io_buffer *head,
1814 struct ccs_capability_acl_record *ptr,
1815 const struct ccs_condition *cond)
1816 {
1817 int pos = head->read_avail;
1818 if (!ccs_io_printf(head, KEYWORD_ALLOW_CAPABILITY "%s",
1819 ccs_cap2keyword(ptr->operation)))
1820 goto out;
1821 if (!ccs_print_condition(head, cond))
1822 goto out;
1823 return true;
1824 out:
1825 head->read_avail = pos;
1826 return false;
1827 }
1828
1829 /**
1830 * ccs_print_ipv4_entry - Print IPv4 address of a network ACL entry.
1831 *
1832 * @head: Pointer to "struct ccs_io_buffer".
1833 * @ptr: Pointer to "struct ccs_ip_network_acl_record".
1834 *
1835 * Returns true on success, false otherwise.
1836 */
1837 static bool ccs_print_ipv4_entry(struct ccs_io_buffer *head,
1838 struct ccs_ip_network_acl_record *ptr)
1839 {
1840 const u32 min_address = ptr->u.ipv4.min;
1841 const u32 max_address = ptr->u.ipv4.max;
1842 if (!ccs_io_printf(head, "%u.%u.%u.%u", HIPQUAD(min_address)))
1843 return false;
1844 if (min_address != max_address
1845 && !ccs_io_printf(head, "-%u.%u.%u.%u", HIPQUAD(max_address)))
1846 return false;
1847 return true;
1848 }
1849
1850 /**
1851 * ccs_print_ipv6_entry - Print IPv6 address of a network ACL entry.
1852 *
1853 * @head: Pointer to "struct ccs_io_buffer".
1854 * @ptr: Pointer to "struct ccs_ip_network_acl_record".
1855 *
1856 * Returns true on success, false otherwise.
1857 */
1858 static bool ccs_print_ipv6_entry(struct ccs_io_buffer *head,
1859 struct ccs_ip_network_acl_record *ptr)
1860 {
1861 char buf[64];
1862 const struct in6_addr *min_address = ptr->u.ipv6.min;
1863 const struct in6_addr *max_address = ptr->u.ipv6.max;
1864 ccs_print_ipv6(buf, sizeof(buf), min_address);
1865 if (!ccs_io_printf(head, "%s", buf))
1866 return false;
1867 if (min_address != max_address) {
1868 ccs_print_ipv6(buf, sizeof(buf), max_address);
1869 if (!ccs_io_printf(head, "-%s", buf))
1870 return false;
1871 }
1872 return true;
1873 }
1874
1875 /**
1876 * ccs_print_port_entry - Print port number of a network ACL entry.
1877 *
1878 * @head: Pointer to "struct ccs_io_buffer".
1879 * @ptr: Pointer to "struct ccs_ip_network_acl_record".
1880 *
1881 * Returns true on success, false otherwise.
1882 */
1883 static bool ccs_print_port_entry(struct ccs_io_buffer *head,
1884 struct ccs_ip_network_acl_record *ptr)
1885 {
1886 const u16 min_port = ptr->min_port;
1887 const u16 max_port = ptr->max_port;
1888 if (!ccs_io_printf(head, " %u", min_port))
1889 return false;
1890 if (min_port != max_port && !ccs_io_printf(head, "-%u", max_port))
1891 return false;
1892 return true;
1893 }
1894
1895 /**
1896 * ccs_print_network_acl - Print a network ACL entry.
1897 *
1898 * @head: Pointer to "struct ccs_io_buffer".
1899 * @ptr: Pointer to "struct ccs_ip_network_acl_record".
1900 * @cond: Pointer to "struct ccs_condition". May be NULL.
1901 *
1902 * Returns true on success, false otherwise.
1903 */
1904 static bool ccs_print_network_acl(struct ccs_io_buffer *head,
1905 struct ccs_ip_network_acl_record *ptr,
1906 const struct ccs_condition *cond)
1907 {
1908 int pos = head->read_avail;
1909 if (!ccs_io_printf(head, KEYWORD_ALLOW_NETWORK "%s ",
1910 ccs_net2keyword(ptr->operation_type)))
1911 goto out;
1912 switch (ptr->record_type) {
1913 case IP_RECORD_TYPE_ADDRESS_GROUP:
1914 if (!ccs_io_printf(head, "@%s", ptr->u.group->group_name->name))
1915 goto out;
1916 break;
1917 case IP_RECORD_TYPE_IPv4:
1918 if (!ccs_print_ipv4_entry(head, ptr))
1919 goto out;
1920 break;
1921 case IP_RECORD_TYPE_IPv6:
1922 if (!ccs_print_ipv6_entry(head, ptr))
1923 goto out;
1924 break;
1925 }
1926 if (!ccs_print_port_entry(head, ptr))
1927 goto out;
1928 if (!ccs_print_condition(head, cond))
1929 goto out;
1930 return true;
1931 out:
1932 head->read_avail = pos;
1933 return false;
1934 }
1935
1936 /**
1937 * ccs_print_signal_acl - Print a signal ACL entry.
1938 *
1939 * @head: Pointer to "struct ccs_io_buffer".
1940 * @ptr: Pointer to "struct signale_acl_record".
1941 * @cond: Pointer to "struct ccs_condition". May be NULL.
1942 *
1943 * Returns true on success, false otherwise.
1944 */
1945 static bool ccs_print_signal_acl(struct ccs_io_buffer *head,
1946 struct ccs_signal_acl_record *ptr,
1947 const struct ccs_condition *cond)
1948 {
1949 int pos = head->read_avail;
1950 if (!ccs_io_printf(head, KEYWORD_ALLOW_SIGNAL "%u %s",
1951 ptr->sig, ptr->domainname->name))
1952 goto out;
1953 if (!ccs_print_condition(head, cond))
1954 goto out;
1955 return true;
1956 out:
1957 head->read_avail = pos;
1958 return false;
1959 }
1960
1961 /**
1962 * ccs_print_execute_handler_record - Print an execute handler ACL entry.
1963 *
1964 * @head: Pointer to "struct ccs_io_buffer".
1965 * @keyword: Name of the keyword.
1966 * @ptr: Pointer to "struct ccs_execute_handler_record".
1967 *
1968 * Returns true on success, false otherwise.
1969 */
1970 static bool ccs_print_execute_handler_record(struct ccs_io_buffer *head,
1971 const char *keyword,
1972 struct ccs_execute_handler_record *
1973 ptr)
1974 {
1975 return ccs_io_printf(head, "%s %s\n", keyword, ptr->handler->name);
1976 }
1977
1978 /**
1979 * ccs_print_mount_acl - Print a mount ACL entry.
1980 *
1981 * @head: Pointer to "struct ccs_io_buffer".
1982 * @ptr: Pointer to "struct ccs_mount_acl_record".
1983 * @cond: Pointer to "struct ccs_condition". May be NULL.
1984 *
1985 * Returns true on success, false otherwise.
1986 */
1987 static bool ccs_print_mount_acl(struct ccs_io_buffer *head,
1988 struct ccs_mount_acl_record *ptr,
1989 const struct ccs_condition *cond)
1990 {
1991 int pos = head->read_avail;
1992 if (!ccs_io_printf(head, KEYWORD_ALLOW_MOUNT "%s %s %s 0x%lX\n",
1993 ptr->dev_name->name, ptr->dir_name->name,
1994 ptr->fs_type->name, ptr->flags))
1995 goto out;
1996 if (!ccs_print_condition(head, cond))
1997 goto out;
1998 return true;
1999 out:
2000 head->read_avail = pos;
2001 return false;
2002 }
2003
2004 /**
2005 * ccs_print_umount_acl - Print a mount ACL entry.
2006 *
2007 * @head: Pointer to "struct ccs_io_buffer".
2008 * @ptr: Pointer to "struct ccs_umount_acl_record".
2009 * @cond: Pointer to "struct ccs_condition". May be NULL.
2010 *
2011 * Returns true on success, false otherwise.
2012 */
2013 static bool ccs_print_umount_acl(struct ccs_io_buffer *head,
2014 struct ccs_umount_acl_record *ptr,
2015 const struct ccs_condition *cond)
2016 {
2017 int pos = head->read_avail;
2018 if (!ccs_io_printf(head, KEYWORD_ALLOW_UNMOUNT "%s\n",
2019 ptr->dir->name))
2020 goto out;
2021 if (!ccs_print_condition(head, cond))
2022 goto out;
2023 return true;
2024 out:
2025 head->read_avail = pos;
2026 return false;
2027 }
2028
2029 /**
2030 * ccs_print_chroot_acl - Print a chroot ACL entry.
2031 *
2032 * @head: Pointer to "struct ccs_io_buffer".
2033 * @ptr: Pointer to "struct ccs_chroot_acl_record".
2034 * @cond: Pointer to "struct ccs_condition". May be NULL.
2035 *
2036 * Returns true on success, false otherwise.
2037 */
2038 static bool ccs_print_chroot_acl(struct ccs_io_buffer *head,
2039 struct ccs_chroot_acl_record *ptr,
2040 const struct ccs_condition *cond)
2041 {
2042 int pos = head->read_avail;
2043 if (!ccs_io_printf(head, KEYWORD_ALLOW_CHROOT "%s\n",
2044 ptr->dir->name))
2045 goto out;
2046 if (!ccs_print_condition(head, cond))
2047 goto out;
2048 return true;
2049 out:
2050 head->read_avail = pos;
2051 return false;
2052 }
2053
2054 /**
2055 * ccs_print_pivot_root_acl - Print a pivot_root ACL entry.
2056 *
2057 * @head: Pointer to "struct ccs_io_buffer".
2058 * @ptr: Pointer to "struct ccs_pivot_root_acl_record".
2059 * @cond: Pointer to "struct ccs_condition". May be NULL.
2060 *
2061 * Returns true on success, false otherwise.
2062 */
2063 static bool ccs_print_pivot_root_acl(struct ccs_io_buffer *head,
2064 struct ccs_pivot_root_acl_record *ptr,
2065 const struct ccs_condition *cond)
2066 {
2067 int pos = head->read_avail;
2068 if (!ccs_io_printf(head, KEYWORD_ALLOW_PIVOT_ROOT "%s %s\n",
2069 ptr->new_root->name, ptr->old_root->name))
2070 goto out;
2071 if (!ccs_print_condition(head, cond))
2072 goto out;
2073 return true;
2074 out:
2075 head->read_avail = pos;
2076 return false;
2077 }
2078
2079 /**
2080 * ccs_print_entry - Print an ACL entry.
2081 *
2082 * @head: Pointer to "struct ccs_io_buffer".
2083 * @ptr: Pointer to an ACL entry.
2084 *
2085 * Returns true on success, false otherwise.
2086 */
2087 static bool ccs_print_entry(struct ccs_io_buffer *head,
2088 struct ccs_acl_info *ptr)
2089 {
2090 const struct ccs_condition *cond = ptr->cond;
2091 const u8 acl_type = ccs_acl_type2(ptr);
2092 if (acl_type & ACL_DELETED)
2093 return true;
2094 if (acl_type == TYPE_SINGLE_PATH_ACL) {
2095 struct ccs_single_path_acl_record *acl
2096 = container_of(ptr, struct ccs_single_path_acl_record,
2097 head);
2098 return ccs_print_single_path_acl(head, acl, cond);
2099 }
2100 if (acl_type == TYPE_EXECUTE_HANDLER) {
2101 struct ccs_execute_handler_record *acl
2102 = container_of(ptr, struct ccs_execute_handler_record,
2103 head);
2104 const char *keyword = KEYWORD_EXECUTE_HANDLER;
2105 return ccs_print_execute_handler_record(head, keyword, acl);
2106 }
2107 if (acl_type == TYPE_DENIED_EXECUTE_HANDLER) {
2108 struct ccs_execute_handler_record *acl
2109 = container_of(ptr, struct ccs_execute_handler_record,
2110 head);
2111 const char *keyword = KEYWORD_DENIED_EXECUTE_HANDLER;
2112 return ccs_print_execute_handler_record(head, keyword, acl);
2113 }
2114 if (head->read_execute_only)
2115 return true;
2116 if (acl_type == TYPE_MKDEV_ACL) {
2117 struct ccs_mkdev_acl_record *acl
2118 = container_of(ptr, struct ccs_mkdev_acl_record, head);
2119 return ccs_print_mkdev_acl(head, acl, cond);
2120 }
2121 if (acl_type == TYPE_DOUBLE_PATH_ACL) {
2122 struct ccs_double_path_acl_record *acl
2123 = container_of(ptr, struct ccs_double_path_acl_record,
2124 head);
2125 return ccs_print_double_path_acl(head, acl, cond);
2126 }
2127 if (acl_type == TYPE_IOCTL_ACL) {
2128 struct ccs_ioctl_acl_record *acl
2129 = container_of(ptr, struct ccs_ioctl_acl_record, head);
2130 return ccs_print_ioctl_acl(head, acl, cond);
2131 }
2132 if (acl_type == TYPE_ARGV0_ACL) {
2133 struct ccs_argv0_acl_record *acl
2134 = container_of(ptr, struct ccs_argv0_acl_record, head);
2135 return ccs_print_argv0_acl(head, acl, cond);
2136 }
2137 if (acl_type == TYPE_ENV_ACL) {
2138 struct ccs_env_acl_record *acl
2139 = container_of(ptr, struct ccs_env_acl_record, head);
2140 return ccs_print_env_acl(head, acl, cond);
2141 }
2142 if (acl_type == TYPE_CAPABILITY_ACL) {
2143 struct ccs_capability_acl_record *acl
2144 = container_of(ptr, struct ccs_capability_acl_record,
2145 head);
2146 return ccs_print_capability_acl(head, acl, cond);
2147 }
2148 if (acl_type == TYPE_IP_NETWORK_ACL) {
2149 struct ccs_ip_network_acl_record *acl
2150 = container_of(ptr, struct ccs_ip_network_acl_record,
2151 head);
2152 return ccs_print_network_acl(head, acl, cond);
2153 }
2154 if (acl_type == TYPE_SIGNAL_ACL) {
2155 struct ccs_signal_acl_record *acl
2156 = container_of(ptr, struct ccs_signal_acl_record, head);
2157 return ccs_print_signal_acl(head, acl, cond);
2158 }
2159 if (acl_type == TYPE_MOUNT_ACL) {
2160 struct ccs_mount_acl_record *acl
2161 = container_of(ptr, struct ccs_mount_acl_record, head);
2162 return ccs_print_mount_acl(head, acl, cond);
2163 }
2164 if (acl_type == TYPE_UMOUNT_ACL) {
2165 struct ccs_umount_acl_record *acl
2166 = container_of(ptr, struct ccs_umount_acl_record, head);
2167 return ccs_print_umount_acl(head, acl, cond);
2168 }
2169 if (acl_type == TYPE_CHROOT_ACL) {
2170 struct ccs_chroot_acl_record *acl
2171 = container_of(ptr, struct ccs_chroot_acl_record, head);
2172 return ccs_print_chroot_acl(head, acl, cond);
2173 }
2174 if (acl_type == TYPE_PIVOT_ROOT_ACL) {
2175 struct ccs_pivot_root_acl_record *acl
2176 = container_of(ptr, struct ccs_pivot_root_acl_record,
2177 head);
2178 return ccs_print_pivot_root_acl(head, acl, cond);
2179 }
2180 /* Workaround for gcc 3.2.2's inline bug. */
2181 if (acl_type & ACL_DELETED)
2182 return true;
2183 BUG(); /* This must not happen. */
2184 return false;
2185 }
2186
2187 /**
2188 * ccs_read_domain_policy - Read domain policy.
2189 *
2190 * @head: Pointer to "struct ccs_io_buffer".
2191 *
2192 * Returns 0.
2193 *
2194 * Caller holds srcu_read_lock(&ccs_ss).
2195 */
2196 static int ccs_read_domain_policy(struct ccs_io_buffer *head)
2197 {
2198 struct list_head *dpos;
2199 struct list_head *apos;
2200 if (head->read_eof)
2201 return 0;
2202 if (head->read_step == 0)
2203 head->read_step = 1;
2204 list_for_each_cookie(dpos, head->read_var1, &ccs_domain_list) {
2205 struct ccs_domain_info *domain;
2206 const char *quota_exceeded = "";
2207 const char *transition_failed = "";
2208 const char *ignore_global_allow_read = "";
2209 const char *ignore_global_allow_env = "";
2210 domain = list_entry(dpos, struct ccs_domain_info, list);
2211 if (head->read_step != 1)
2212 goto acl_loop;
2213 if (domain->is_deleted && !head->read_single_domain)
2214 continue;
2215 /* Print domainname and flags. */
2216 if (domain->quota_warned)
2217 quota_exceeded = "quota_exceeded\n";
2218 if (domain->domain_transition_failed)
2219 transition_failed = "transition_failed\n";
2220 if (domain->ignore_global_allow_read)
2221 ignore_global_allow_read
2222 = KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n";
2223 if (domain->ignore_global_allow_env)
2224 ignore_global_allow_env
2225 = KEYWORD_IGNORE_GLOBAL_ALLOW_ENV "\n";
2226 if (!ccs_io_printf(head, "%s\n" KEYWORD_USE_PROFILE "%u\n"
2227 "%s%s%s%s\n", domain->domainname->name,
2228 domain->profile, quota_exceeded,
2229 transition_failed,
2230 ignore_global_allow_read,
2231 ignore_global_allow_env))
2232 return 0;
2233 head->read_step = 2;
2234 acl_loop:
2235 if (head->read_step == 3)
2236 goto tail_mark;
2237 /* Print ACL entries in the domain. */
2238 list_for_each_cookie(apos, head->read_var2,
2239 &domain->acl_info_list) {
2240 struct ccs_acl_info *ptr
2241 = list_entry(apos, struct ccs_acl_info, list);
2242 if (!ccs_print_entry(head, ptr))
2243 return 0;
2244 }
2245 head->read_step = 3;
2246 tail_mark:
2247 if (!ccs_io_printf(head, "\n"))
2248 return 0;
2249 head->read_step = 1;
2250 if (head->read_single_domain)
2251 break;
2252 }
2253 head->read_eof = true;
2254 return 0;
2255 }
2256
2257 /**
2258 * ccs_write_domain_profile - Assign profile for specified domain.
2259 *
2260 * @head: Pointer to "struct ccs_io_buffer".
2261 *
2262 * Returns 0 on success, -EINVAL otherwise.
2263 *
2264 * This is equivalent to doing
2265 *
2266 * ( echo "select " $domainname; echo "use_profile " $profile ) |
2267 * /usr/lib/ccs/loadpolicy -d
2268 *
2269 * Caller holds srcu_read_lock(&ccs_ss).
2270 */
2271 static int ccs_write_domain_profile(struct ccs_io_buffer *head)
2272 {
2273 char *data = head->write_buf;
2274 char *cp = strchr(data, ' ');
2275 struct ccs_domain_info *domain;
2276 unsigned int profile;
2277 if (!cp)
2278 return -EINVAL;
2279 *cp = '\0';
2280 profile = simple_strtoul(data, NULL, 10);
2281 if (profile >= MAX_PROFILES)
2282 return -EINVAL;
2283 domain = ccs_find_domain(cp + 1);
2284 if (domain && (ccs_profile_ptr[profile] || !ccs_policy_loaded))
2285 domain->profile = (u8) profile;
2286 return 0;
2287 }
2288
2289 /**
2290 * ccs_read_domain_profile - Read only domainname and profile.
2291 *
2292 * @head: Pointer to "struct ccs_io_buffer".
2293 *
2294 * Returns list of profile number and domainname pairs.
2295 *
2296 * This is equivalent to doing
2297 *
2298 * grep -A 1 '^<kernel>' /proc/ccs/domain_policy |
2299 * awk ' { if ( domainname == "" ) { if ( $1 == "<kernel>" )
2300 * domainname = $0; } else if ( $1 == "use_profile" ) {
2301 * print $2 " " domainname; domainname = ""; } } ; '
2302 *
2303 * Caller holds srcu_read_lock(&ccs_ss).
2304 */
2305 static int ccs_read_domain_profile(struct ccs_io_buffer *head)
2306 {
2307 struct list_head *pos;
2308 if (head->read_eof)
2309 return 0;
2310 list_for_each_cookie(pos, head->read_var1, &ccs_domain_list) {
2311 struct ccs_domain_info *domain;
2312 domain = list_entry(pos, struct ccs_domain_info, list);
2313 if (domain->is_deleted)
2314 continue;
2315 if (!ccs_io_printf(head, "%u %s\n", domain->profile,
2316 domain->domainname->name))
2317 return 0;
2318 }
2319 head->read_eof = true;
2320 return 0;
2321 }
2322
2323 /**
2324 * ccs_write_pid: Specify PID to obtain domainname.
2325 *
2326 * @head: Pointer to "struct ccs_io_buffer".
2327 *
2328 * Returns 0.
2329 */
2330 static int ccs_write_pid(struct ccs_io_buffer *head)
2331 {
2332 head->read_eof = false;
2333 return 0;
2334 }
2335
2336 /**
2337 * ccs_read_pid - Read information of a process.
2338 *
2339 * @head: Pointer to "struct ccs_io_buffer".
2340 *
2341 * Returns the domainname which the specified PID is in or
2342 * process information of the specified PID on success,
2343 * empty string otherwise.
2344 *
2345 * Caller holds srcu_read_lock(&ccs_ss).
2346 */
2347 static int ccs_read_pid(struct ccs_io_buffer *head)
2348 {
2349 char *buf = head->write_buf;
2350 bool task_info = false;
2351 unsigned int pid;
2352 struct task_struct *p;
2353 struct ccs_domain_info *domain = NULL;
2354 u32 ccs_flags = 0;
2355 /* Accessing write_buf is safe because head->io_sem is held. */
2356 if (!buf)
2357 goto done; /* Do nothing if open(O_RDONLY). */
2358 if (head->read_avail || head->read_eof)
2359 goto done;
2360 head->read_eof = true;
2361 if (ccs_str_starts(&buf, "info "))
2362 task_info = true;
2363 pid = (unsigned int) simple_strtoul(buf, NULL, 10);
2364 /***** CRITICAL SECTION START *****/
2365 read_lock(&tasklist_lock);
2366 p = find_task_by_pid(pid);
2367 if (p) {
2368 domain = ccs_task_domain(p);
2369 ccs_flags = p->ccs_flags;
2370 }
2371 read_unlock(&tasklist_lock);
2372 /***** CRITICAL SECTION END *****/
2373 if (!domain)
2374 goto done;
2375 if (!task_info)
2376 ccs_io_printf(head, "%u %u %s", pid, domain->profile,
2377 domain->domainname->name);
2378 else
2379 ccs_io_printf(head, "%u manager=%s execute_handler=%s "
2380 "state[0]=%u state[1]=%u state[2]=%u", pid,
2381 ccs_flags & CCS_TASK_IS_POLICY_MANAGER ?
2382 "yes" : "no",
2383 ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER ?
2384 "yes" : "no",
2385 (u8) (ccs_flags >> 24),
2386 (u8) (ccs_flags >> 16),
2387 (u8) (ccs_flags >> 8));
2388 done:
2389 return 0;
2390 }
2391
2392 /**
2393 * ccs_write_exception_policy - Write exception policy.
2394 *
2395 * @head: Pointer to "struct ccs_io_buffer".
2396 *
2397 * Returns 0 on success, negative value otherwise.
2398 */
2399 static int ccs_write_exception_policy(struct ccs_io_buffer *head)
2400 {
2401 char *data = head->write_buf;
2402 bool is_delete = ccs_str_starts(&data, KEYWORD_DELETE);
2403 if (ccs_str_starts(&data, KEYWORD_KEEP_DOMAIN))
2404 return ccs_write_domain_keeper_policy(data, false, is_delete);
2405 if (ccs_str_starts(&data, KEYWORD_NO_KEEP_DOMAIN))
2406 return ccs_write_domain_keeper_policy(data, true, is_delete);
2407 if (ccs_str_starts(&data, KEYWORD_INITIALIZE_DOMAIN))
2408 return ccs_write_domain_initializer_policy(data, false,
2409 is_delete);
2410 if (ccs_str_starts(&data, KEYWORD_NO_INITIALIZE_DOMAIN))
2411 return ccs_write_domain_initializer_policy(data, true,
2412 is_delete);
2413 if (ccs_str_starts(&data, KEYWORD_AGGREGATOR))
2414 return ccs_write_aggregator_policy(data, is_delete);
2415 if (ccs_str_starts(&data, KEYWORD_ALLOW_READ))
2416 return ccs_write_globally_readable_policy(data, is_delete);
2417 if (ccs_str_starts(&data, KEYWORD_ALLOW_ENV))
2418 return ccs_write_globally_usable_env_policy(data, is_delete);
2419 if (ccs_str_starts(&data, KEYWORD_FILE_PATTERN))
2420 return ccs_write_pattern_policy(data, is_delete);
2421 if (ccs_str_starts(&data, KEYWORD_PATH_GROUP))
2422 return ccs_write_path_group_policy(data, is_delete);
2423 if (ccs_str_starts(&data, KEYWORD_DENY_REWRITE))
2424 return ccs_write_no_rewrite_policy(data, is_delete);
2425 if (ccs_str_starts(&data, KEYWORD_ADDRESS_GROUP))
2426 return ccs_write_address_group_policy(data, is_delete);
2427 if (ccs_str_starts(&data, KEYWORD_DENY_AUTOBIND))
2428 return ccs_write_reserved_port_policy(data, is_delete);
2429 return -EINVAL;
2430 }
2431
2432 /**
2433 * ccs_read_exception_policy - Read exception policy.
2434 *
2435 * @head: Pointer to "struct ccs_io_buffer".
2436 *
2437 * Returns 0 on success, -EINVAL otherwise.
2438 *
2439 * Caller holds srcu_read_lock(&ccs_ss).
2440 */
2441 static int ccs_read_exception_policy(struct ccs_io_buffer *head)
2442 {
2443 if (!head->read_eof) {
2444 switch (head->read_step) {
2445 case 0:
2446 head->read_var2 = NULL;
2447 head->read_step = 1;
2448 case 1:
2449 if (!ccs_read_domain_keeper_policy(head))
2450 break;
2451 head->read_var2 = NULL;
2452 head->read_step = 2;
2453 case 2:
2454 if (!ccs_read_globally_readable_policy(head))
2455 break;
2456 head->read_var2 = NULL;
2457 head->read_step = 3;
2458 case 3:
2459 if (!ccs_read_globally_usable_env_policy(head))
2460 break;
2461 head->read_var2 = NULL;
2462 head->read_step = 4;
2463 case 4:
2464 if (!ccs_read_domain_initializer_policy(head))
2465 break;
2466 head->read_var2 = NULL;
2467 head->read_step = 6;
2468 case 6:
2469 if (!ccs_read_aggregator_policy(head))
2470 break;
2471 head->read_var2 = NULL;
2472 head->read_step = 7;
2473 case 7:
2474 if (!ccs_read_file_pattern(head))
2475 break;
2476 head->read_var2 = NULL;
2477 head->read_step = 8;
2478 case 8:
2479 if (!ccs_read_no_rewrite_policy(head))
2480 break;
2481 head->read_var2 = NULL;
2482 head->read_step = 9;
2483 case 9:
2484 if (!ccs_read_path_group_policy(head))
2485 break;
2486 head->read_var1 = NULL;
2487 head->read_var2 = NULL;
2488 head->read_step = 10;
2489 case 10:
2490 if (!ccs_read_address_group_policy(head))
2491 break;
2492 head->read_var2 = NULL;
2493 head->read_step = 11;
2494 case 11:
2495 if (!ccs_read_reserved_port_policy(head))
2496 break;
2497 head->read_eof = true;
2498 break;
2499 default:
2500 return -EINVAL;
2501 }
2502 }
2503 return 0;
2504 }
2505
2506 /* Path to the policy loader. The default is /sbin/ccs-init. */
2507 static const char *ccs_loader;
2508
2509 /**
2510 * ccs_loader_setup - Specify the policy loader to use.
2511 *
2512 * @str: Path to the policy loader.
2513 *
2514 * Returns 0.
2515 */
2516 static int __init ccs_loader_setup(char *str)
2517 {
2518 ccs_loader = str;
2519 return 0;
2520 }
2521
2522 __setup("CCS_loader=", ccs_loader_setup);
2523
2524 /**
2525 * ccs_policy_loader_exists - Check whether /sbin/ccs-init exists.
2526 *
2527 * Returns true if /sbin/ccs-init exists, false otherwise.
2528 */
2529 static bool ccs_policy_loader_exists(void)
2530 {
2531 /*
2532 * Don't activate MAC if the path given by 'CCS_loader=' option doesn't
2533 * exist. If the initrd includes /sbin/init but real-root-dev has not
2534 * mounted on / yet, activating MAC will block the system since
2535 * policies are not loaded yet.
2536 * Thus, let do_execve() call this function everytime.
2537 */
2538 struct nameidata nd;
2539 if (!ccs_loader)
2540 ccs_loader = "/sbin/ccs-init";
2541 if (path_lookup(ccs_loader, ccs_lookup_flags, &nd)) {
2542 printk(KERN_INFO "Not activating Mandatory Access Control now "
2543 "since %s doesn't exist.\n", ccs_loader);
2544 return false;
2545 }
2546 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
2547 path_put(&nd.path);
2548 #else
2549 path_release(&nd);
2550 #endif
2551 return true;
2552 }
2553
2554 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
2555 /**
2556 * ccs_run_loader - Start /sbin/ccs-init .
2557 *
2558 * @unused: Not used.
2559 *
2560 * Returns PID of /sbin/ccs-init on success, negative value otherwise.
2561 */
2562 static int ccs_run_loader(void *unused)
2563 {
2564 char *argv[2];
2565 char *envp[3];
2566 printk(KERN_INFO "Calling %s to load policy. Please wait.\n",
2567 ccs_loader);
2568 argv[0] = (char *) ccs_loader;
2569 argv[1] = NULL;
2570 envp[0] = "HOME=/";
2571 envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
2572 envp[2] = NULL;
2573 return exec_usermodehelper(argv[0], argv, envp);
2574 }
2575 #endif
2576
2577 /**
2578 * ccs_load_policy - Run external policy loader to load policy.
2579 *
2580 * @filename: The program about to start.
2581 *
2582 * This function checks whether @filename is /sbin/init , and if so
2583 * invoke /sbin/ccs-init and wait for the termination of /sbin/ccs-init
2584 * and then continues invocation of /sbin/init.
2585 * /sbin/ccs-init reads policy files in /etc/ccs/ directory and
2586 * writes to /proc/ccs/ interfaces.
2587 *
2588 * Returns nothing.
2589 */
2590 void ccs_load_policy(const char *filename)
2591 {
2592 if (ccs_policy_loaded)
2593 return;
2594 /*
2595 * Check filename is /sbin/init or /sbin/ccs-start.
2596 * /sbin/ccs-start is a dummy filename in case where /sbin/init can't
2597 * be passed.
2598 * You can create /sbin/ccs-start by "ln -s /bin/true /sbin/ccs-start".
2599 */
2600 if (strcmp(filename, "/sbin/init") &&
2601 strcmp(filename, "/sbin/ccs-start"))
2602 return;
2603 if (!ccs_policy_loader_exists())
2604 return;
2605 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
2606 {
2607 char *argv[2];
2608 char *envp[3];
2609 printk(KERN_INFO "Calling %s to load policy. Please wait.\n",
2610 ccs_loader);
2611 argv[0] = (char *) ccs_loader;
2612 argv[1] = NULL;
2613 envp[0] = "HOME=/";
2614 envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
2615 envp[2] = NULL;
2616 call_usermodehelper(argv[0], argv, envp, 1);
2617 }
2618 #elif defined(TASK_DEAD)
2619 {
2620 /* Copied from kernel/kmod.c */
2621 struct task_struct *task = current;
2622 pid_t pid = kernel_thread(ccs_run_loader, NULL, 0);
2623 sigset_t tmpsig;
2624 spin_lock_irq(&task->sighand->siglock);
2625 tmpsig = task->blocked;
2626 siginitsetinv(&task->blocked,
2627 sigmask(SIGKILL) | sigmask(SIGSTOP));
2628 recalc_sigpending();
2629 spin_unlock_irq(&current->sighand->siglock);
2630 if (pid >= 0)
2631 waitpid(pid, NULL, __WCLONE);
2632 spin_lock_irq(&task->sighand->siglock);
2633 task->blocked = tmpsig;
2634 recalc_sigpending();
2635 spin_unlock_irq(&task->sighand->siglock);
2636 }
2637 #else
2638 {
2639 /* Copied from kernel/kmod.c */
2640 struct task_struct *task = current;
2641 pid_t pid = kernel_thread(ccs_run_loader, NULL, 0);
2642 sigset_t tmpsig;
2643 spin_lock_irq(&task->sigmask_lock);
2644 tmpsig = task->blocked;
2645 siginitsetinv(&task->blocked,
2646 sigmask(SIGKILL) | sigmask(SIGSTOP));
2647 recalc_sigpending(task);
2648 spin_unlock_irq(&task->sigmask_lock);
2649 if (pid >= 0)
2650 waitpid(pid, NULL, __WCLONE);
2651 spin_lock_irq(&task->sigmask_lock);
2652 task->blocked = tmpsig;
2653 recalc_sigpending(task);
2654 spin_unlock_irq(&task->sigmask_lock);
2655 }
2656 #endif
2657 printk(KERN_INFO "SAKURA: 1.7.0-pre 2009/07/03\n");
2658 printk(KERN_INFO "TOMOYO: 1.7.0-pre 2009/07/03\n");
2659 printk(KERN_INFO "Mandatory Access Control activated.\n");
2660 ccs_policy_loaded = true;
2661 ccs_log_level = KERN_WARNING;
2662 { /* Check all profiles currently assigned to domains are defined. */
2663 struct ccs_domain_info *domain;
2664 list_for_each_entry_rcu(domain, &ccs_domain_list, list) {
2665 const u8 profile = domain->profile;
2666 if (ccs_profile_ptr[profile])
2667 continue;
2668 panic("Profile %u (used by '%s') not defined.\n",
2669 profile, domain->domainname->name);
2670 }
2671 }
2672 }
2673
2674 /* Wait queue for ccs_query_list. */
2675 static DECLARE_WAIT_QUEUE_HEAD(ccs_query_wait);
2676
2677 /* Lock for manipulating ccs_query_list. */
2678 static DEFINE_SPINLOCK(ccs_query_list_lock);
2679
2680 /* Structure for query. */
2681 struct ccs_query_entry {
2682 struct list_head list;
2683 char *query;
2684 int query_len;
2685 unsigned int serial;
2686 int timer;
2687 int answer;
2688 };
2689
2690 /* The list for "struct ccs_query_entry". */
2691 static LIST_HEAD(ccs_query_list);
2692
2693 /* Number of "struct file" referring /proc/ccs/query interface. */
2694 static atomic_t ccs_query_observers = ATOMIC_INIT(0);
2695
2696 /**
2697 * ccs_check_supervisor - Ask for the supervisor's decision.
2698 *
2699 * @r: Pointer to "struct ccs_request_info".
2700 * @fmt: The printf()'s format string, followed by parameters.
2701 *
2702 * Returns 0 if the supervisor decided to permit the access request which
2703 * violated the policy in enforcing mode, 1 if the supervisor decided to
2704 * retry the access request which violated the policy in enforcing mode,
2705 * -EPERM otherwise.
2706 */
2707 int ccs_check_supervisor(struct ccs_request_info *r, const char *fmt, ...)
2708 {
2709 va_list args;
2710 int error = -EPERM;
2711 int pos;
2712 int len;
2713 static unsigned int ccs_serial;
2714 struct ccs_query_entry *ccs_query_entry = NULL;
2715 bool quota_exceeded = false;
2716 char *header;
2717 if (!r->domain)
2718 r->domain = ccs_current_domain();
2719 if (!atomic_read(&ccs_query_observers)) {
2720 int i;
2721 if (current->ccs_flags & CCS_DONT_SLEEP_ON_ENFORCE_ERROR)
2722 return -EPERM;
2723 for (i = 0; i < ccs_check_flags(r->domain, CCS_SLEEP_PERIOD);
2724 i++) {
2725 set_current_state(TASK_INTERRUPTIBLE);
2726 schedule_timeout(HZ / 10);
2727 }
2728 return -EPERM;
2729 }
2730 va_start(args, fmt);
2731 len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 32;
2732 va_end(args);
2733 header = ccs_init_audit_log(&len, r);
2734 if (!header)
2735 goto out;
2736 ccs_query_entry = kzalloc(sizeof(*ccs_query_entry), GFP_KERNEL);
2737 if (!ccs_query_entry)
2738 goto out;
2739 ccs_query_entry->query = kzalloc(len, GFP_KERNEL);
2740 if (!ccs_query_entry->query)
2741 goto out;
2742 INIT_LIST_HEAD(&ccs_query_entry->list);
2743 /***** CRITICAL SECTION START *****/
2744 spin_lock(&ccs_query_list_lock);
2745 if (ccs_quota_for_query && ccs_query_memory_size + len +
2746 sizeof(*ccs_query_entry) >= ccs_quota_for_query) {
2747 quota_exceeded = true;
2748 } else {
2749 ccs_query_memory_size += len + sizeof(*ccs_query_entry);
2750 ccs_query_entry->serial = ccs_serial++;
2751 }
2752 spin_unlock(&ccs_query_list_lock);
2753 /***** CRITICAL SECTION END *****/
2754 if (quota_exceeded)
2755 goto out;
2756 pos = snprintf(ccs_query_entry->query, len - 1, "Q%u-%hu\n%s",
2757 ccs_query_entry->serial, r->retry, header);
2758 kfree(header);
2759 header = NULL;
2760 va_start(args, fmt);
2761 vsnprintf(ccs_query_entry->query + pos, len - 1 - pos, fmt, args);
2762 ccs_query_entry->query_len = strlen(ccs_query_entry->query) + 1;
2763 va_end(args);
2764 /***** CRITICAL SECTION START *****/
2765 spin_lock(&ccs_query_list_lock);
2766 list_add_tail(&ccs_query_entry->list, &ccs_query_list);
2767 spin_unlock(&ccs_query_list_lock);
2768 /***** CRITICAL SECTION END *****/
2769 /* Give 10 seconds for supervisor's opinion. */
2770 for (ccs_query_entry->timer = 0;
2771 atomic_read(&ccs_query_observers) && ccs_query_entry->timer < 100;
2772 ccs_query_entry->timer++) {
2773 wake_up(&ccs_query_wait);
2774 set_current_state(TASK_INTERRUPTIBLE);
2775 schedule_timeout(HZ / 10);
2776 if (ccs_query_entry->answer)
2777 break;
2778 }
2779 /***** CRITICAL SECTION START *****/
2780 spin_lock(&ccs_query_list_lock);
2781 list_del(&ccs_query_entry->list);
2782 ccs_query_memory_size -= len + sizeof(*ccs_query_entry);
2783 spin_unlock(&ccs_query_list_lock);
2784 /***** CRITICAL SECTION END *****/
2785 switch (ccs_query_entry->answer) {
2786 case 3: /* Asked to retry by administrator. */
2787 error = 1;
2788 r->retry++;
2789 break;
2790 case 1:
2791 /* Granted by administrator. */
2792 error = 0;
2793 break;
2794 case 0:
2795 /* Timed out. */
2796 break;
2797 default:
2798 /* Rejected by administrator. */
2799 break;
2800 }
2801 out:
2802 if (ccs_query_entry)
2803 kfree(ccs_query_entry->query);
2804 kfree(ccs_query_entry);
2805 kfree(header);
2806 return error;
2807 }
2808
2809 /**
2810 * ccs_poll_query - poll() for /proc/ccs/query.
2811 *
2812 * @file: Pointer to "struct file".
2813 * @wait: Pointer to "poll_table".
2814 *
2815 * Returns POLLIN | POLLRDNORM when ready to read, 0 otherwise.
2816 *
2817 * Waits for access requests which violated policy in enforcing mode.
2818 */
2819 static int ccs_poll_query(struct file *file, poll_table *wait)
2820 {
2821 struct list_head *tmp;
2822 bool found = false;
2823 u8 i;
2824 for (i = 0; i < 2; i++) {
2825 /***** CRITICAL SECTION START *****/
2826 spin_lock(&ccs_query_list_lock);
2827 list_for_each(tmp, &ccs_query_list) {
2828 struct ccs_query_entry *ptr
2829 = list_entry(tmp, struct ccs_query_entry, list);
2830 if (ptr->answer)
2831 continue;
2832 found = true;
2833 break;
2834 }
2835 spin_unlock(&ccs_query_list_lock);
2836 /***** CRITICAL SECTION END *****/
2837 if (found)
2838 return POLLIN | POLLRDNORM;
2839 if (i)
2840 break;
2841 poll_wait(file, &ccs_query_wait, wait);
2842 }
2843 return 0;
2844 }
2845
2846 /**
2847 * ccs_read_query - Read access requests which violated policy in enforcing mode.
2848 *
2849 * @head: Pointer to "struct ccs_io_buffer".
2850 *
2851 * Returns 0.
2852 */
2853 static int ccs_read_query(struct ccs_io_buffer *head)
2854 {
2855 struct list_head *tmp;
2856 int pos = 0;
2857 int len = 0;
2858 char *buf;
2859 if (head->read_avail)
2860 return 0;
2861 if (head->read_buf) {
2862 kfree(head->read_buf);
2863 head->read_buf = NULL;
2864 head->readbuf_size = 0;
2865 }
2866 /***** CRITICAL SECTION START *****/
2867 spin_lock(&ccs_query_list_lock);
2868 list_for_each(tmp, &ccs_query_list) {
2869 struct ccs_query_entry *ptr
2870 = list_entry(tmp, struct ccs_query_entry, list);
2871 if (ptr->answer)
2872 continue;
2873 if (pos++ != head->read_step)
2874 continue;
2875 len = ptr->query_len;
2876 break;
2877 }
2878 spin_unlock(&ccs_query_list_lock);
2879 /***** CRITICAL SECTION END *****/
2880 if (!len) {
2881 head->read_step = 0;
2882 return 0;
2883 }
2884 buf = kzalloc(len, GFP_KERNEL);
2885 if (!buf)
2886 return 0;
2887 pos = 0;
2888 /***** CRITICAL SECTION START *****/
2889 spin_lock(&ccs_query_list_lock);
2890 list_for_each(tmp, &ccs_query_list) {
2891 struct ccs_query_entry *ptr
2892 = list_entry(tmp, struct ccs_query_entry, list);
2893 if (ptr->answer)
2894 continue;
2895 if (pos++ != head->read_step)
2896 continue;
2897 /*
2898 * Some query can be skipped because ccs_query_list
2899 * can change, but I don't care.
2900 */
2901 if (len == ptr->query_len)
2902 memmove(buf, ptr->query, len);
2903 break;
2904 }
2905 spin_unlock(&ccs_query_list_lock);
2906 /***** CRITICAL SECTION END *****/
2907 if (buf[0]) {
2908 head->read_avail = len;
2909 head->readbuf_size = head->read_avail;
2910 head->read_buf = buf;
2911 head->read_step++;
2912 } else {
2913 kfree(buf);
2914 }
2915 return 0;
2916 }
2917
2918 /**
2919 * ccs_write_answer - Write the supervisor's decision.
2920 *
2921 * @head: Pointer to "struct ccs_io_buffer".
2922 *
2923 * Returns 0 on success, -EINVAL otherwise.
2924 */
2925 static int ccs_write_answer(struct ccs_io_buffer *head)
2926 {
2927 char *data = head->write_buf;
2928 struct list_head *tmp;
2929 unsigned int serial;
2930 unsigned int answer;
2931 /***** CRITICAL SECTION START *****/
2932 spin_lock(&ccs_query_list_lock);
2933 list_for_each(tmp, &ccs_query_list) {
2934 struct ccs_query_entry *ptr
2935 = list_entry(tmp, struct ccs_query_entry, list);
2936 ptr->timer = 0;
2937 }
2938 spin_unlock(&ccs_query_list_lock);
2939 /***** CRITICAL SECTION END *****/
2940 if (sscanf(data, "A%u=%u", &serial, &answer) != 2)
2941 return -EINVAL;
2942 /***** CRITICAL SECTION START *****/
2943 spin_lock(&ccs_query_list_lock);
2944 list_for_each(tmp, &ccs_query_list) {
2945 struct ccs_query_entry *ptr
2946 = list_entry(tmp, struct ccs_query_entry, list);
2947 if (ptr->serial != serial)
2948 continue;
2949 if (!ptr->answer)
2950 ptr->answer = answer;
2951 break;
2952 }
2953 spin_unlock(&ccs_query_list_lock);
2954 /***** CRITICAL SECTION END *****/
2955 return 0;
2956 }
2957
2958 /**
2959 * ccs_read_version: Get version.
2960 *
2961 * @head: Pointer to "struct ccs_io_buffer".
2962 *
2963 * Returns version information.
2964 */
2965 static int ccs_read_version(struct ccs_io_buffer *head)
2966 {
2967 if (!head->read_eof) {
2968 ccs_io_printf(head, "1.7.0-pre");
2969 head->read_eof = true;
2970 }
2971 return 0;
2972 }
2973
2974 /**
2975 * ccs_read_self_domain - Get the current process's domainname.
2976 *
2977 * @head: Pointer to "struct ccs_io_buffer".
2978 *
2979 * Returns the current process's domainname.
2980 */
2981 static int ccs_read_self_domain(struct ccs_io_buffer *head)
2982 {
2983 if (!head->read_eof) {
2984 /*
2985 * ccs_current_domain()->domainname != NULL
2986 * because every process belongs to a domain and
2987 * the domain's name cannot be NULL.
2988 */
2989 ccs_io_printf(head, "%s",
2990 ccs_current_domain()->domainname->name);
2991 head->read_eof = true;
2992 }
2993 return 0;
2994 }
2995
2996 /**
2997 * ccs_open_control - open() for /proc/ccs/ interface.
2998 *
2999 * @type: Type of interface.
3000 * @file: Pointer to "struct file".
3001 *
3002 * Associates policy handler and returns 0 on success, -ENOMEM otherwise.
3003 */
3004 int ccs_open_control(const u8 type, struct file *file)
3005 {
3006 struct ccs_io_buffer *head = kzalloc(sizeof(*head), GFP_KERNEL);
3007 if (!head)
3008 return -ENOMEM;
3009 mutex_init(&head->io_sem);
3010 head->type = type;
3011 switch (type) {
3012 case CCS_DOMAINPOLICY: /* /proc/ccs/domain_policy */
3013 head->write = ccs_write_domain_policy;
3014 head->read = ccs_read_domain_policy;
3015 break;
3016 case CCS_EXCEPTIONPOLICY: /* /proc/ccs/exception_policy */
3017 head->write = ccs_write_exception_policy;
3018 head->read = ccs_read_exception_policy;
3019 break;
3020 #ifdef CONFIG_CCSECURITY_AUDIT
3021 case CCS_GRANTLOG: /* /proc/ccs/grant_log */
3022 head->poll = ccs_poll_grant_log;
3023 head->read = ccs_read_grant_log;
3024 break;
3025 case CCS_REJECTLOG: /* /proc/ccs/reject_log */
3026 head->poll = ccs_poll_reject_log;
3027 head->read = ccs_read_reject_log;
3028 break;
3029 #endif
3030 case CCS_SELFDOMAIN: /* /proc/ccs/self_domain */
3031 head->read = ccs_read_self_domain;
3032 break;
3033 case CCS_DOMAIN_STATUS: /* /proc/ccs/.domain_status */
3034 head->write = ccs_write_domain_profile;
3035 head->read = ccs_read_domain_profile;
3036 break;
3037 case CCS_EXECUTE_HANDLER: /* /proc/ccs/.execute_handler */
3038 /* Allow execute_handler to read process's status. */
3039 if (!(current->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER)) {
3040 kfree(head);
3041 return -EPERM;
3042 }
3043 /* fall through */
3044 case CCS_PROCESS_STATUS: /* /proc/ccs/.process_status */
3045 head->write = ccs_write_pid;
3046 head->read = ccs_read_pid;
3047 break;
3048 case CCS_VERSION: /* /proc/ccs/version */
3049 head->read = ccs_read_version;
3050 head->readbuf_size = 128;
3051 break;
3052 case CCS_MEMINFO: /* /proc/ccs/meminfo */
3053 head->write = ccs_write_memory_quota;
3054 head->read = ccs_read_memory_counter;
3055 head->readbuf_size = 512;
3056 break;
3057 case CCS_PROFILE: /* /proc/ccs/profile */
3058 head->write = ccs_write_profile;
3059 head->read = ccs_read_profile;
3060 break;
3061 case CCS_QUERY: /* /proc/ccs/query */
3062 head->poll = ccs_poll_query;
3063 head->write = ccs_write_answer;
3064 head->read = ccs_read_query;
3065 break;
3066 case CCS_MANAGER: /* /proc/ccs/manager */
3067 head->write = ccs_write_manager_policy;
3068 head->read = ccs_read_manager_policy;
3069 break;
3070 }
3071 if (!(file->f_mode & FMODE_READ)) {
3072 /*
3073 * No need to allocate read_buf since it is not opened
3074 * for reading.
3075 */
3076 head->read = NULL;
3077 head->poll = NULL;
3078 } else if (type != CCS_QUERY &&
3079 type != CCS_GRANTLOG && type != CCS_REJECTLOG) {
3080 /*
3081 * Don't allocate buffer for reading if the file is one of
3082 * /proc/ccs/grant_log , /proc/ccs/reject_log , /proc/ccs/query.
3083 */
3084 if (!head->readbuf_size)
3085 head->readbuf_size = 4096 * 2;
3086 head->read_buf = kzalloc(head->readbuf_size, GFP_KERNEL);
3087 if (!head->read_buf) {
3088 kfree(head);
3089 return -ENOMEM;
3090 }
3091 }
3092 if (!(file->f_mode & FMODE_WRITE)) {
3093 /*
3094 * No need to allocate write_buf since it is not opened
3095 * for writing.
3096 */
3097 head->write = NULL;
3098 } else if (head->write) {
3099 head->writebuf_size = 4096 * 2;
3100 head->write_buf = kzalloc(head->writebuf_size, GFP_KERNEL);
3101 if (!head->write_buf) {
3102 kfree(head->read_buf);
3103 kfree(head);
3104 return -ENOMEM;
3105 }
3106 }
3107 if (type != CCS_QUERY &&
3108 type != CCS_GRANTLOG && type != CCS_REJECTLOG)
3109 head->srcu_idx = srcu_read_lock(&ccs_ss);
3110 file->private_data = head;
3111 /*
3112 * Call the handler now if the file is /proc/ccs/self_domain
3113 * so that the user can use "cat < /proc/ccs/self_domain" to
3114 * know the current process's domainname.
3115 */
3116 if (type == CCS_SELFDOMAIN)
3117 ccs_read_control(file, NULL, 0);
3118 /*
3119 * If the file is /proc/ccs/query , increment the observer counter.
3120 * The obserber counter is used by ccs_check_supervisor() to see if
3121 * there is some process monitoring /proc/ccs/query.
3122 */
3123 else if (type == CCS_QUERY)
3124 atomic_inc(&ccs_query_observers);
3125 return 0;
3126 }
3127
3128 /**
3129 * ccs_poll_control - poll() for /proc/ccs/ interface.
3130 *
3131 * @file: Pointer to "struct file".
3132 * @wait: Pointer to "poll_table".
3133 *
3134 * Waits for read readiness.
3135 * /proc/ccs/query is handled by /usr/lib/ccs/ccs-queryd and
3136 * /proc/ccs/grant_log and /proc/ccs/reject_log are handled by
3137 * /usr/lib/ccs/ccs-auditd.
3138 */
3139 int ccs_poll_control(struct file *file, poll_table *wait)
3140 {
3141 struct ccs_io_buffer *head = file->private_data;
3142 if (!head->poll)
3143 return -ENOSYS;
3144 return head->poll(file, wait);
3145 }
3146
3147 /**
3148 * ccs_read_control - read() for /proc/ccs/ interface.
3149 *
3150 * @file: Pointer to "struct file".
3151 * @buffer: Poiner to buffer to write to.
3152 * @buffer_len: Size of @buffer.
3153 *
3154 * Returns bytes read on success, negative value otherwise.
3155 */
3156 int ccs_read_control(struct file *file, char __user *buffer,
3157 const int buffer_len)
3158 {
3159 int len = 0;
3160 struct ccs_io_buffer *head = file->private_data;
3161 char *cp;
3162 if (!head->read)
3163 return -ENOSYS;
3164 if (!access_ok(VERIFY_WRITE, buffer, buffer_len))
3165 return -EFAULT;
3166 if (mutex_lock_interruptible(&head->io_sem))
3167 return -EINTR;
3168 /* Call the policy handler. */
3169 len = head->read(head);
3170 if (len < 0)
3171 goto out;
3172 /* Write to buffer. */
3173 len = head->read_avail;
3174 if (len > buffer_len)
3175 len = buffer_len;
3176 if (!len)
3177 goto out;
3178 /* head->read_buf changes by some functions. */
3179 cp = head->read_buf;
3180 if (copy_to_user(buffer, cp, len)) {
3181 len = -EFAULT;
3182 goto out;
3183 }
3184 head->read_avail -= len;
3185 memmove(cp, cp + len, head->read_avail);
3186 out:
3187 mutex_unlock(&head->io_sem);
3188 return len;
3189 }
3190
3191 /**
3192 * ccs_write_control - write() for /proc/ccs/ interface.
3193 *
3194 * @file: Pointer to "struct file".
3195 * @buffer: Pointer to buffer to read from.
3196 * @buffer_len: Size of @buffer.
3197 *
3198 * Returns @buffer_len on success, negative value otherwise.
3199 */
3200 int ccs_write_control(struct file *file, const char __user *buffer,
3201 const int buffer_len)
3202 {
3203 struct ccs_io_buffer *head = file->private_data;
3204 int error = buffer_len;
3205 int avail_len = buffer_len;
3206 char *cp0 = head->write_buf;
3207 if (!head->write)
3208 return -ENOSYS;
3209 if (!access_ok(VERIFY_READ, buffer, buffer_len))
3210 return -EFAULT;
3211 /* Don't allow updating policies by non manager programs. */
3212 if (head->write != ccs_write_pid &&
3213 head->write != ccs_write_domain_policy &&
3214 !ccs_is_policy_manager())
3215 return -EPERM;
3216 if (mutex_lock_interruptible(&head->io_sem))
3217 return -EINTR;
3218 /* Read a line and dispatch it to the policy handler. */
3219 while (avail_len > 0) {
3220 char c;
3221 if (head->write_avail >= head->writebuf_size - 1) {
3222 error = -ENOMEM;
3223 break;
3224 } else if (get_user(c, buffer)) {
3225 error = -EFAULT;
3226 break;
3227 }
3228 buffer++;
3229 avail_len--;
3230 cp0[head->write_avail++] = c;
3231 if (c != '\n')
3232 continue;
3233 cp0[head->write_avail - 1] = '\0';
3234 head->write_avail = 0;
3235 ccs_normalize_line(cp0);
3236 head->write(head);
3237 }
3238 mutex_unlock(&head->io_sem);
3239 return error;
3240 }
3241
3242 /**
3243 * ccs_close_control - close() for /proc/ccs/ interface.
3244 *
3245 * @file: Pointer to "struct file".
3246 *
3247 * Releases memory and returns 0.
3248 */
3249 int ccs_close_control(struct file *file)
3250 {
3251 struct ccs_io_buffer *head = file->private_data;
3252 const bool is_write = head->write_buf != NULL;
3253 const u8 type = head->type;
3254 /*
3255 * If the file is /proc/ccs/query , decrement the observer counter.
3256 */
3257 if (type == CCS_QUERY)
3258 atomic_dec(&ccs_query_observers);
3259 if (type != CCS_QUERY &&
3260 type != CCS_GRANTLOG && type != CCS_REJECTLOG)
3261 srcu_read_unlock(&ccs_ss, head->srcu_idx);
3262 /* Release memory used for policy I/O. */
3263 kfree(head->read_buf);
3264 head->read_buf = NULL;
3265 kfree(head->write_buf);
3266 head->write_buf = NULL;
3267 kfree(head);
3268 head = NULL;
3269 file->private_data = NULL;
3270 if (is_write)
3271 ccs_run_gc();
3272 return 0;
3273 }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26