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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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