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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1191 - (show annotations) (download) (as text)
Fri May 9 01:46:04 2008 UTC (16 years ago) by kumaneko
Original Path: trunk/1.6.x/ccs-patch/fs/ccs_common.c
File MIME type: text/x-csrc
File size: 81219 byte(s)


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

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