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

Subversion リポジトリの参照

Contents of /branches/ccs-patch/security/ccsecurity/policy_io.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2894 - (show annotations) (download) (as text)
Tue Aug 11 08:15:11 2009 UTC (14 years, 9 months ago) by kumaneko
File MIME type: text/x-csrc
File size: 62742 byte(s)


1 /*
2 * security/ccsecurity/policy_io.c
3 *
4 * Copyright (C) 2005-2009 NTT DATA CORPORATION
5 *
6 * Version: 1.7.0-pre 2009/08/08
7 *
8 * This file is applicable to both 2.4.30 and 2.6.11 and later.
9 * See README.ccs for ChangeLog.
10 *
11 */
12
13 #include "internal.h"
14
15 /* Lock for protecting ccs_profile->comment */
16 static DEFINE_SPINLOCK(ccs_profile_comment_lock);
17
18 static bool ccs_profile_entry_used[CCS_MAX_CONTROL_INDEX +
19 CCS_MAX_CAPABILITY_INDEX + 1];
20
21 /* String table for functionality that takes 4 modes. */
22 static const char *ccs_mode_4[4] = {
23 "disabled", "learning", "permissive", "enforcing"
24 };
25 /* String table for functionality that takes 2 modes. */
26 static const char *ccs_mode_2[4] = {
27 "disabled", "enabled", "enabled", "enabled"
28 };
29
30 /* Table for profile. */
31 static struct {
32 const char *keyword;
33 unsigned int current_value;
34 const unsigned int max_value;
35 } ccs_control_array[CCS_MAX_CONTROL_INDEX] = {
36 [CCS_MAC_FOR_FILE] = { "MAC_FOR_FILE", 0, 3 },
37 [CCS_AUTOLEARN_EXEC_REALPATH] = { "AUTOLEARN_EXEC_REALPATH", 0, 1 },
38 [CCS_AUTOLEARN_EXEC_ARGV0] = { "AUTOLEARN_EXEC_ARGV0", 0, 1 },
39 [CCS_MAC_FOR_IOCTL] = { "MAC_FOR_IOCTL", 0, 3 },
40 [CCS_MAC_FOR_FILEATTR] = { "MAC_FOR_FILEATTR", 0, 3 },
41 [CCS_MAC_FOR_ENV] = { "MAC_FOR_ENV", 0, 3 },
42 [CCS_MAC_FOR_NETWORK] = { "MAC_FOR_NETWORK", 0, 3 },
43 [CCS_MAC_FOR_SIGNAL] = { "MAC_FOR_SIGNAL", 0, 3 },
44 [CCS_MAC_FOR_NAMESPACE] = { "MAC_FOR_NAMESPACE", 0, 3 },
45 [CCS_RESTRICT_AUTOBIND] = { "RESTRICT_AUTOBIND", 0, 1 },
46 [CCS_MAX_ACCEPT_ENTRY]
47 = { "MAX_ACCEPT_ENTRY", CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY, INT_MAX },
48 #ifdef CONFIG_CCSECURITY_AUDIT
49 [CCS_MAX_GRANT_LOG]
50 = { "MAX_GRANT_LOG", CONFIG_CCSECURITY_MAX_GRANT_LOG, INT_MAX },
51 [CCS_MAX_REJECT_LOG]
52 = { "MAX_REJECT_LOG", CONFIG_CCSECURITY_MAX_REJECT_LOG, INT_MAX },
53 #endif
54 [CCS_VERBOSE] = { "TOMOYO_VERBOSE", 1, 1 },
55 [CCS_SLEEP_PERIOD]
56 = { "SLEEP_PERIOD", 0, 3000 }, /* in 0.1 second */
57 };
58
59 /* Permit policy management by non-root user? */
60 static bool ccs_manage_by_non_root;
61
62 /**
63 * ccs_quiet_setup - Set CCS_VERBOSE=0 by default.
64 *
65 * @str: Unused.
66 *
67 * Returns 0.
68 */
69 static int __init ccs_quiet_setup(char *str)
70 {
71 ccs_control_array[CCS_VERBOSE].current_value = 0;
72 return 0;
73 }
74
75 __setup("CCS_QUIET", ccs_quiet_setup);
76
77 /**
78 * ccs_io_printf - Transactional printf() to "struct ccs_io_buffer" structure.
79 *
80 * @head: Pointer to "struct ccs_io_buffer".
81 * @fmt: The printf()'s format string, followed by parameters.
82 *
83 * Returns true on success, false otherwise.
84 *
85 * The snprintf() will truncate, but ccs_io_printf() won't.
86 */
87 bool ccs_io_printf(struct ccs_io_buffer *head, const char *fmt, ...)
88 {
89 va_list args;
90 int len;
91 int pos = head->read_avail;
92 int size = head->readbuf_size - pos;
93 if (size <= 0)
94 return false;
95 va_start(args, fmt);
96 len = vsnprintf(head->read_buf + pos, size, fmt, args);
97 va_end(args);
98 if (pos + len >= head->readbuf_size)
99 return false;
100 head->read_avail += len;
101 return true;
102 }
103
104 /**
105 * ccs_find_or_assign_new_profile - Create a new profile.
106 *
107 * @profile: Profile number to create.
108 *
109 * Returns pointer to "struct ccs_profile" on success, NULL otherwise.
110 */
111 static struct ccs_profile *ccs_find_or_assign_new_profile(const unsigned int
112 profile)
113 {
114 struct ccs_profile *ptr;
115 struct ccs_profile *entry;
116 int i;
117 if (profile >= CCS_MAX_PROFILES)
118 return NULL;
119 ptr = ccs_profile_ptr[profile];
120 if (ptr)
121 return ptr;
122 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
123 mutex_lock(&ccs_policy_lock);
124 ptr = ccs_profile_ptr[profile];
125 if (!ptr && ccs_memory_ok(entry, sizeof(*entry))) {
126 ptr = entry;
127 for (i = 0; i < CCS_MAX_CONTROL_INDEX; i++)
128 ptr->value[i] = ccs_control_array[i].current_value;
129 /*
130 * Needn't to initialize "ptr->capability_value"
131 * because they are always 0.
132 */
133 mb(); /* Avoid out-of-order execution. */
134 ccs_profile_ptr[profile] = ptr;
135 entry = NULL;
136 }
137 mutex_unlock(&ccs_policy_lock);
138 kfree(entry);
139 return ptr;
140 }
141
142 /**
143 * ccs_write_profile - Write profile table.
144 *
145 * @head: Pointer to "struct ccs_io_buffer".
146 *
147 * Returns 0 on success, negative value otherwise.
148 */
149 static int ccs_write_profile(struct ccs_io_buffer *head)
150 {
151 char *data = head->write_buf;
152 unsigned int i;
153 unsigned int value;
154 char *cp;
155 struct ccs_profile *ccs_profile;
156 i = simple_strtoul(data, &cp, 10);
157 if (data != cp) {
158 if (*cp != '-')
159 return -EINVAL;
160 data = cp + 1;
161 }
162 ccs_profile = ccs_find_or_assign_new_profile(i);
163 if (!ccs_profile)
164 return -EINVAL;
165 cp = strchr(data, '=');
166 if (!cp)
167 return -EINVAL;
168 *cp = '\0';
169 if (!strcmp(data, "COMMENT")) {
170 const struct ccs_path_info *new_comment
171 = ccs_get_name(cp + 1);
172 const struct ccs_path_info *old_comment;
173 /* Protect reader from ccs_put_name(). */
174 /***** CRITICAL SECTION START *****/
175 spin_lock(&ccs_profile_comment_lock);
176 old_comment = ccs_profile->comment;
177 ccs_profile->comment = new_comment;
178 spin_unlock(&ccs_profile_comment_lock);
179 /***** CRITICAL SECTION END *****/
180 ccs_put_name(old_comment);
181 ccs_profile_entry_used[0] = true;
182 return 0;
183 }
184 if (ccs_str_starts(&data, CCS_KEYWORD_MAC_FOR_CAPABILITY)) {
185 if (sscanf(cp + 1, "%u", &value) != 1) {
186 for (i = 0; i < 4; i++) {
187 if (strcmp(cp + 1, ccs_mode_4[i]))
188 continue;
189 value = i;
190 break;
191 }
192 if (i == 4)
193 return -EINVAL;
194 }
195 if (value > 3)
196 value = 3;
197 for (i = 0; i < CCS_MAX_CAPABILITY_INDEX; i++) {
198 if (strcmp(data, ccs_capability_control_keyword[i]))
199 continue;
200 ccs_profile->capability_value[i] = value;
201 ccs_profile_entry_used[i + 1 + CCS_MAX_CONTROL_INDEX]
202 = true;
203 return 0;
204 }
205 return -EINVAL;
206 }
207 for (i = 0; i < CCS_MAX_CONTROL_INDEX; i++) {
208 if (strcmp(data, ccs_control_array[i].keyword))
209 continue;
210 if (sscanf(cp + 1, "%u", &value) != 1) {
211 int j;
212 const char **modes;
213 switch (i) {
214 case CCS_AUTOLEARN_EXEC_REALPATH:
215 case CCS_AUTOLEARN_EXEC_ARGV0:
216 case CCS_RESTRICT_AUTOBIND:
217 case CCS_VERBOSE:
218 modes = ccs_mode_2;
219 break;
220 default:
221 modes = ccs_mode_4;
222 break;
223 }
224 for (j = 0; j < 4; j++) {
225 if (strcmp(cp + 1, modes[j]))
226 continue;
227 value = j;
228 break;
229 }
230 if (j == 4)
231 return -EINVAL;
232 } else if (value > ccs_control_array[i].max_value) {
233 value = ccs_control_array[i].max_value;
234 }
235 ccs_profile->value[i] = value;
236 ccs_profile_entry_used[i + 1] = true;
237 return 0;
238 }
239 return -EINVAL;
240 }
241
242 /**
243 * ccs_read_profile - Read profile table.
244 *
245 * @head: Pointer to "struct ccs_io_buffer".
246 *
247 * Returns 0.
248 */
249 static int ccs_read_profile(struct ccs_io_buffer *head)
250 {
251 static const int ccs_total
252 = CCS_MAX_CONTROL_INDEX + CCS_MAX_CAPABILITY_INDEX + 1;
253 int step;
254 if (head->read_eof)
255 return 0;
256 for (step = head->read_step; step < CCS_MAX_PROFILES * ccs_total;
257 step++) {
258 const u8 index = step / ccs_total;
259 u8 type = step % ccs_total;
260 const struct ccs_profile *ccs_profile = ccs_profile_ptr[index];
261 head->read_step = step;
262 if (!ccs_profile)
263 continue;
264 if (!ccs_profile_entry_used[type])
265 continue;
266 if (!type) { /* Print profile' comment tag. */
267 bool done;
268 /***** CRITICAL SECTION START *****/
269 spin_lock(&ccs_profile_comment_lock);
270 done = ccs_io_printf(head, "%u-COMMENT=%s\n",
271 index, ccs_profile->comment ?
272 ccs_profile->comment->name : "");
273 spin_unlock(&ccs_profile_comment_lock);
274 /***** CRITICAL SECTION END *****/
275 if (!done)
276 break;
277 continue;
278 }
279 type--;
280 if (type >= CCS_MAX_CONTROL_INDEX) {
281 const int i = type - CCS_MAX_CONTROL_INDEX;
282 const u8 value = ccs_profile->capability_value[i];
283 if (!ccs_io_printf(head,
284 "%u-" CCS_KEYWORD_MAC_FOR_CAPABILITY
285 "%s=%s\n", index,
286 ccs_capability_control_keyword[i],
287 ccs_mode_4[value]))
288 break;
289 } else {
290 const unsigned int value = ccs_profile->value[type];
291 const char **modes = NULL;
292 const char *keyword = ccs_control_array[type].keyword;
293 switch (ccs_control_array[type].max_value) {
294 case 3:
295 modes = ccs_mode_4;
296 break;
297 case 1:
298 modes = ccs_mode_2;
299 break;
300 }
301 if (modes) {
302 if (!ccs_io_printf(head, "%u-%s=%s\n", index,
303 keyword, modes[value]))
304 break;
305 } else {
306 if (!ccs_io_printf(head, "%u-%s=%u\n", index,
307 keyword, value))
308 break;
309 }
310 }
311 }
312 if (step == CCS_MAX_PROFILES * ccs_total)
313 head->read_eof = true;
314 return 0;
315 }
316
317 /* The list for "struct ccs_policy_manager_entry". */
318 LIST_HEAD(ccs_policy_manager_list);
319
320 /**
321 * ccs_update_manager_entry - Add a manager entry.
322 *
323 * @manager: The path to manager or the domainnamme.
324 * @is_delete: True if it is a delete request.
325 *
326 * Returns 0 on success, negative value otherwise.
327 */
328 static int ccs_update_manager_entry(const char *manager, const bool is_delete)
329 {
330 struct ccs_policy_manager_entry *entry = NULL;
331 struct ccs_policy_manager_entry *ptr;
332 const struct ccs_path_info *saved_manager;
333 int error = is_delete ? -ENOENT : -ENOMEM;
334 bool is_domain = false;
335 if (ccs_is_domain_def(manager)) {
336 if (!ccs_is_correct_domain(manager))
337 return -EINVAL;
338 is_domain = true;
339 } else {
340 if (!ccs_is_correct_path(manager, 1, -1, -1))
341 return -EINVAL;
342 }
343 saved_manager = ccs_get_name(manager);
344 if (!saved_manager)
345 return -ENOMEM;
346 if (!is_delete)
347 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
348 mutex_lock(&ccs_policy_lock);
349 list_for_each_entry_rcu(ptr, &ccs_policy_manager_list, list) {
350 if (ptr->manager != saved_manager)
351 continue;
352 ptr->is_deleted = is_delete;
353 error = 0;
354 break;
355 }
356 if (!is_delete && error && ccs_memory_ok(entry, sizeof(*entry))) {
357 entry->manager = saved_manager;
358 saved_manager = NULL;
359 entry->is_domain = is_domain;
360 list_add_tail_rcu(&entry->list, &ccs_policy_manager_list);
361 entry = NULL;
362 error = 0;
363 }
364 mutex_unlock(&ccs_policy_lock);
365 ccs_put_name(saved_manager);
366 kfree(entry);
367 return error;
368 }
369
370 /**
371 * ccs_write_manager_policy - Write manager policy.
372 *
373 * @head: Pointer to "struct ccs_io_buffer".
374 *
375 * Returns 0 on success, negative value otherwise.
376 */
377 static int ccs_write_manager_policy(struct ccs_io_buffer *head)
378 {
379 char *data = head->write_buf;
380 bool is_delete = ccs_str_starts(&data, CCS_KEYWORD_DELETE);
381 if (!strcmp(data, "manage_by_non_root")) {
382 ccs_manage_by_non_root = !is_delete;
383 return 0;
384 }
385 return ccs_update_manager_entry(data, is_delete);
386 }
387
388 /**
389 * ccs_read_manager_policy - Read manager policy.
390 *
391 * @head: Pointer to "struct ccs_io_buffer".
392 *
393 * Returns 0.
394 *
395 * Caller holds ccs_read_lock().
396 */
397 static int ccs_read_manager_policy(struct ccs_io_buffer *head)
398 {
399 struct list_head *pos;
400 ccs_check_read_lock();
401 if (head->read_eof)
402 return 0;
403 list_for_each_cookie(pos, head->read_var2, &ccs_policy_manager_list) {
404 struct ccs_policy_manager_entry *ptr;
405 ptr = list_entry(pos, struct ccs_policy_manager_entry, list);
406 if (ptr->is_deleted)
407 continue;
408 if (!ccs_io_printf(head, "%s\n", ptr->manager->name))
409 return 0;
410 }
411 head->read_eof = true;
412 return 0;
413 }
414
415 /**
416 * ccs_is_policy_manager - Check whether the current process is a policy manager.
417 *
418 * Returns true if the current process is permitted to modify policy
419 * via /proc/ccs/ interface.
420 *
421 * Caller holds ccs_read_lock().
422 */
423 static bool ccs_is_policy_manager(void)
424 {
425 struct ccs_policy_manager_entry *ptr;
426 const char *exe;
427 struct task_struct *task = current;
428 const struct ccs_path_info *domainname
429 = ccs_current_domain()->domainname;
430 bool found = false;
431 ccs_check_read_lock();
432 if (!ccs_policy_loaded)
433 return true;
434 if (task->ccs_flags & CCS_TASK_IS_POLICY_MANAGER)
435 return true;
436 if (!ccs_manage_by_non_root && (current_uid() || current_euid()))
437 return false;
438 list_for_each_entry_rcu(ptr, &ccs_policy_manager_list, list) {
439 if (!ptr->is_deleted && ptr->is_domain
440 && !ccs_pathcmp(domainname, ptr->manager)) {
441 /* Set manager flag. */
442 task->ccs_flags |= CCS_TASK_IS_POLICY_MANAGER;
443 return true;
444 }
445 }
446 exe = ccs_get_exe();
447 if (!exe)
448 return false;
449 list_for_each_entry_rcu(ptr, &ccs_policy_manager_list, list) {
450 if (!ptr->is_deleted && !ptr->is_domain
451 && !strcmp(exe, ptr->manager->name)) {
452 found = true;
453 /* Set manager flag. */
454 task->ccs_flags |= CCS_TASK_IS_POLICY_MANAGER;
455 break;
456 }
457 }
458 if (!found) { /* Reduce error messages. */
459 static pid_t ccs_last_pid;
460 const pid_t pid = current->pid;
461 if (ccs_last_pid != pid) {
462 printk(KERN_WARNING "%s ( %s ) is not permitted to "
463 "update policies.\n", domainname->name, exe);
464 ccs_last_pid = pid;
465 }
466 }
467 kfree(exe);
468 return found;
469 }
470
471 /**
472 * ccs_find_condition_part - Find condition part from the statement.
473 *
474 * @data: String to parse.
475 *
476 * Returns pointer to the condition part if it was found in the statement,
477 * NULL otherwise.
478 */
479 static char *ccs_find_condition_part(char *data)
480 {
481 char *cp = strstr(data, " if ");
482 if (cp) {
483 while (1) {
484 char *cp2 = strstr(cp + 3, " if ");
485 if (!cp2)
486 break;
487 cp = cp2;
488 }
489 *cp++ = '\0';
490 } else {
491 cp = strstr(data, " ; set ");
492 if (cp)
493 *cp++ = '\0';
494 }
495 return cp;
496 }
497
498 /**
499 * ccs_is_select_one - Parse select command.
500 *
501 * @head: Pointer to "struct ccs_io_buffer".
502 * @data: String to parse.
503 *
504 * Returns true on success, false otherwise.
505 *
506 * Caller holds ccs_read_lock().
507 */
508 static bool ccs_is_select_one(struct ccs_io_buffer *head, const char *data)
509 {
510 unsigned int pid;
511 struct ccs_domain_info *domain = NULL;
512 ccs_check_read_lock();
513 if (!strcmp(data, "allow_execute")) {
514 head->read_execute_only = true;
515 return true;
516 }
517 if (sscanf(data, "pid=%u", &pid) == 1) {
518 struct task_struct *p;
519 /***** CRITICAL SECTION START *****/
520 read_lock(&tasklist_lock);
521 p = find_task_by_pid(pid);
522 if (p)
523 domain = ccs_task_domain(p);
524 read_unlock(&tasklist_lock);
525 /***** CRITICAL SECTION END *****/
526 } else if (!strncmp(data, "domain=", 7)) {
527 if (ccs_is_domain_def(data + 7))
528 domain = ccs_find_domain(data + 7);
529 } else
530 return false;
531 head->write_var1 = domain;
532 /* Accessing read_buf is safe because head->io_sem is held. */
533 if (!head->read_buf)
534 return true; /* Do nothing if open(O_WRONLY). */
535 head->read_avail = 0;
536 ccs_io_printf(head, "# select %s\n", data);
537 head->read_single_domain = true;
538 head->read_eof = !domain;
539 if (domain) {
540 struct ccs_domain_info *d;
541 head->read_var1 = NULL;
542 list_for_each_entry_rcu(d, &ccs_domain_list, list) {
543 if (d == domain)
544 break;
545 head->read_var1 = &d->list;
546 }
547 head->read_var2 = NULL;
548 head->read_bit = 0;
549 head->read_step = 0;
550 if (domain->is_deleted)
551 ccs_io_printf(head, "# This is a deleted domain.\n");
552 }
553 return true;
554 }
555
556 /**
557 * ccs_write_domain_policy - Write domain policy.
558 *
559 * @head: Pointer to "struct ccs_io_buffer".
560 *
561 * Returns 0 on success, negative value otherwise.
562 */
563 static int ccs_write_domain_policy(struct ccs_io_buffer *head)
564 {
565 char *data = head->write_buf;
566 struct ccs_domain_info *domain = head->write_var1;
567 bool is_delete = false;
568 bool is_select = false;
569 unsigned int profile;
570 struct ccs_condition *cond = NULL;
571 char *cp;
572 int error;
573 if (ccs_str_starts(&data, CCS_KEYWORD_DELETE))
574 is_delete = true;
575 else if (ccs_str_starts(&data, CCS_KEYWORD_SELECT))
576 is_select = true;
577 if (is_select && ccs_is_select_one(head, data))
578 return 0;
579 /* Don't allow updating policies by non manager programs. */
580 if (!ccs_is_policy_manager())
581 return -EPERM;
582 if (ccs_is_domain_def(data)) {
583 domain = NULL;
584 if (is_delete)
585 ccs_delete_domain(data);
586 else if (is_select)
587 domain = ccs_find_domain(data);
588 else
589 domain = ccs_find_or_assign_new_domain(data, 0);
590 head->write_var1 = domain;
591 return 0;
592 }
593 if (!domain)
594 return -EINVAL;
595
596 if (sscanf(data, CCS_KEYWORD_USE_PROFILE "%u", &profile) == 1
597 && profile < CCS_MAX_PROFILES) {
598 if (ccs_profile_ptr[profile] || !ccs_policy_loaded)
599 domain->profile = (u8) profile;
600 return 0;
601 }
602 if (!strcmp(data, CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) {
603 domain->ignore_global_allow_read = !is_delete;
604 return 0;
605 }
606 if (!strcmp(data, CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_ENV)) {
607 domain->ignore_global_allow_env = !is_delete;
608 return 0;
609 }
610 cp = ccs_find_condition_part(data);
611 if (cp) {
612 cond = ccs_get_condition(cp);
613 if (!cond)
614 return -EINVAL;
615 }
616 if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_CAPABILITY))
617 error = ccs_write_capability_policy(data, domain, cond,
618 is_delete);
619 else if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_NETWORK))
620 error = ccs_write_network_policy(data, domain, cond, is_delete);
621 else if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_SIGNAL))
622 error = ccs_write_signal_policy(data, domain, cond, is_delete);
623 else if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_ENV))
624 error = ccs_write_env_policy(data, domain, cond, is_delete);
625 else if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_MOUNT))
626 error = ccs_write_mount_policy(data, domain, cond, is_delete);
627 else if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_UNMOUNT))
628 error = ccs_write_umount_policy(data, domain, cond, is_delete);
629 else if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_CHROOT))
630 error = ccs_write_chroot_policy(data, domain, cond, is_delete);
631 else if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_PIVOT_ROOT))
632 error = ccs_write_pivot_root_policy(data, domain, cond,
633 is_delete);
634 else
635 error = ccs_write_file_policy(data, domain, cond, is_delete);
636 if (cond)
637 ccs_put_condition(cond);
638 return error;
639 }
640
641 static bool ccs_print_name_union(struct ccs_io_buffer *head,
642 const struct ccs_name_union *ptr)
643 {
644 int pos = head->read_avail;
645 if (pos && head->read_buf[pos - 1] == ' ')
646 head->read_avail--;
647 if (ptr->is_group)
648 return ccs_io_printf(head, " @%s",
649 ptr->group->group_name->name);
650 return ccs_io_printf(head, " %s", ptr->filename->name);
651 }
652
653 static bool ccs_print_name_union_quoted(struct ccs_io_buffer *head,
654 const struct ccs_name_union *ptr)
655 {
656 if (ptr->is_group)
657 return ccs_io_printf(head, "@%s",
658 ptr->group->group_name->name);
659 return ccs_io_printf(head, "\"%s\"", ptr->filename->name);
660 }
661
662 static bool ccs_print_number_union_common(struct ccs_io_buffer *head,
663 const struct ccs_number_union *ptr,
664 const bool need_space)
665 {
666 unsigned long min;
667 unsigned long max;
668 u8 min_type;
669 u8 max_type;
670 if (need_space && !ccs_io_printf(head, " "))
671 return false;
672 if (ptr->is_group)
673 return ccs_io_printf(head, "@%s",
674 ptr->group->group_name->name);
675 min_type = ptr->min_type;
676 max_type = ptr->max_type;
677 min = ptr->values[0];
678 max = ptr->values[1];
679 switch (min_type) {
680 case CCS_VALUE_TYPE_HEXADECIMAL:
681 if (!ccs_io_printf(head, "0x%lX", min))
682 return false;
683 break;
684 case CCS_VALUE_TYPE_OCTAL:
685 if (!ccs_io_printf(head, "0%lo", min))
686 return false;
687 break;
688 default:
689 if (!ccs_io_printf(head, "%lu", min))
690 return false;
691 break;
692 }
693 if (min == max && min_type == max_type)
694 return true;
695 switch (max_type) {
696 case CCS_VALUE_TYPE_HEXADECIMAL:
697 return ccs_io_printf(head, "-0x%lX", max);
698 case CCS_VALUE_TYPE_OCTAL:
699 return ccs_io_printf(head, "-0%lo", max);
700 default:
701 return ccs_io_printf(head, "-%lu", max);
702 }
703 }
704
705 static bool ccs_print_number_union(struct ccs_io_buffer *head,
706 const struct ccs_number_union *ptr)
707 {
708 return ccs_print_number_union_common(head, ptr, true);
709 }
710
711 static bool ccs_print_number_union_nospace(struct ccs_io_buffer *head,
712 const struct ccs_number_union *ptr)
713 {
714 return ccs_print_number_union_common(head, ptr, false);
715 }
716
717 /**
718 * ccs_print_condition - Print condition part.
719 *
720 * @head: Pointer to "struct ccs_io_buffer".
721 * @cond: Pointer to "struct ccs_condition". May be NULL.
722 *
723 * Returns true on success, false otherwise.
724 */
725 static bool ccs_print_condition(struct ccs_io_buffer *head,
726 const struct ccs_condition *cond)
727 {
728 const struct ccs_condition_element *condp;
729 const struct ccs_number_union *numbers_p;
730 const struct ccs_name_union *names_p;
731 const struct ccs_argv_entry *argv;
732 const struct ccs_envp_entry *envp;
733 u16 condc;
734 u16 i;
735 u16 j;
736 char buffer[32];
737 if (!cond)
738 goto no_condition;
739 condc = cond->condc;
740 condp = (const struct ccs_condition_element *) (cond + 1);
741 numbers_p = (const struct ccs_number_union *) (condp + condc);
742 names_p = (const struct ccs_name_union *)
743 (numbers_p + cond->numbers_count);
744 argv = (const struct ccs_argv_entry *) (names_p + cond->names_count);
745 envp = (const struct ccs_envp_entry *) (argv + cond->argc);
746 memset(buffer, 0, sizeof(buffer));
747 if (condc && !ccs_io_printf(head, "%s", " if"))
748 goto out;
749 for (i = 0; i < condc; i++) {
750 const u8 match = condp->equals;
751 const u8 left = condp->left;
752 const u8 right = condp->right;
753 condp++;
754 switch (left) {
755 case CCS_ARGV_ENTRY:
756 if (!ccs_io_printf(head, " exec.argv[%u]%s\"%s\"",
757 argv->index, argv->is_not ?
758 "!=" : "=", argv->value->name))
759 goto out;
760 argv++;
761 continue;
762 case CCS_ENVP_ENTRY:
763 if (!ccs_io_printf(head, " exec.envp[\"%s\"]%s",
764 envp->name->name, envp->is_not ?
765 "!=" : "="))
766 goto out;
767 if (envp->value) {
768 if (!ccs_io_printf(head, "\"%s\"",
769 envp->value->name))
770 goto out;
771 } else {
772 if (!ccs_io_printf(head, "NULL"))
773 goto out;
774 }
775 envp++;
776 continue;
777 case CCS_NUMBER_UNION:
778 if (!ccs_print_number_union(head, numbers_p++))
779 goto out;
780 break;
781 default:
782 if (left >= CCS_MAX_CONDITION_KEYWORD)
783 goto out;
784 if (!ccs_io_printf(head, " %s",
785 ccs_condition_keyword[left]))
786 goto out;
787 break;
788 }
789 if (!ccs_io_printf(head, "%s", match ? "=" : "!="))
790 goto out;
791 switch (right) {
792 case CCS_NAME_UNION:
793 if (!ccs_print_name_union_quoted(head, names_p++))
794 goto out;
795 break;
796 case CCS_NUMBER_UNION:
797 if (!ccs_print_number_union_nospace(head, numbers_p++))
798 goto out;
799 break;
800 default:
801 if (right >= CCS_MAX_CONDITION_KEYWORD)
802 goto out;
803 if (!ccs_io_printf(head, "%s",
804 ccs_condition_keyword[right]))
805 goto out;
806 break;
807 }
808 }
809 i = cond->post_state[3];
810 if (!i)
811 goto no_condition;
812 if (!ccs_io_printf(head, " ; set"))
813 goto out;
814 for (j = 0; j < 3; j++) {
815 if (!(i & (1 << j)))
816 continue;
817 if (!ccs_io_printf(head, " task.state[%u]=%u", j,
818 cond->post_state[j]))
819 goto out;
820 }
821 no_condition:
822 if (ccs_io_printf(head, "\n"))
823 return true;
824 out:
825 return false;
826 }
827
828 /**
829 * ccs_print_single_path_acl - Print a single path ACL entry.
830 *
831 * @head: Pointer to "struct ccs_io_buffer".
832 * @ptr: Pointer to "struct ccs_single_path_acl_record".
833 * @cond: Pointer to "struct ccs_condition". May be NULL.
834 *
835 * Returns true on success, false otherwise.
836 */
837 static bool ccs_print_single_path_acl(struct ccs_io_buffer *head,
838 struct ccs_single_path_acl_record *ptr,
839 const struct ccs_condition *cond)
840 {
841 int pos;
842 u8 bit;
843 const u16 perm = ptr->perm;
844 for (bit = head->read_bit; bit < CCS_MAX_SINGLE_PATH_OPERATION; bit++) {
845 const char *msg;
846 if (!(perm & (1 << bit)))
847 continue;
848 if (head->read_execute_only && bit != CCS_TYPE_EXECUTE_ACL)
849 continue;
850 /* Print "read/write" instead of "read" and "write". */
851 if ((bit == CCS_TYPE_READ_ACL || bit == CCS_TYPE_WRITE_ACL)
852 && (perm & (1 << CCS_TYPE_READ_WRITE_ACL)))
853 continue;
854 msg = ccs_sp2keyword(bit);
855 pos = head->read_avail;
856 if (!ccs_io_printf(head, "allow_%s", msg) ||
857 !ccs_print_name_union(head, &ptr->name) ||
858 !ccs_print_condition(head, cond))
859 goto out;
860 }
861 head->read_bit = 0;
862 return true;
863 out:
864 head->read_bit = bit;
865 head->read_avail = pos;
866 return false;
867 }
868
869 /**
870 * ccs_print_mkdev_acl - Print a mkdev ACL entry.
871 *
872 * @head: Pointer to "struct ccs_io_buffer".
873 * @ptr: Pointer to "struct ccs_mkdev_acl_record".
874 * @cond: Pointer to "struct ccs_condition". May be NULL.
875 *
876 * Returns true on success, false otherwise.
877 */
878 static bool ccs_print_mkdev_acl(struct ccs_io_buffer *head,
879 struct ccs_mkdev_acl_record *ptr,
880 const struct ccs_condition *cond)
881 {
882 int pos;
883 u8 bit;
884 const u16 perm = ptr->perm;
885 for (bit = head->read_bit; bit < CCS_MAX_MKDEV_OPERATION; bit++) {
886 const char *msg;
887 if (!(perm & (1 << bit)))
888 continue;
889 msg = ccs_mkdev2keyword(bit);
890 pos = head->read_avail;
891 if (!ccs_io_printf(head, "allow_%s", msg) ||
892 !ccs_print_name_union(head, &ptr->name) ||
893 !ccs_print_number_union(head, &ptr->major) ||
894 !ccs_print_number_union(head, &ptr->minor) ||
895 !ccs_print_condition(head, cond))
896 goto out;
897 }
898 head->read_bit = 0;
899 return true;
900 out:
901 head->read_bit = bit;
902 head->read_avail = pos;
903 return false;
904 }
905
906 /**
907 * ccs_print_double_path_acl - Print a double path ACL entry.
908 *
909 * @head: Pointer to "struct ccs_io_buffer".
910 * @ptr: Pointer to "struct ccs_double_path_acl_record".
911 * @cond: Pointer to "struct ccs_condition". May be NULL.
912 *
913 * Returns true on success, false otherwise.
914 */
915 static bool ccs_print_double_path_acl(struct ccs_io_buffer *head,
916 struct ccs_double_path_acl_record *ptr,
917 const struct ccs_condition *cond)
918 {
919 int pos;
920 u8 bit;
921 const u8 perm = ptr->perm;
922 for (bit = head->read_bit; bit < CCS_MAX_DOUBLE_PATH_OPERATION; bit++) {
923 const char *msg;
924 if (!(perm & (1 << bit)))
925 continue;
926 msg = ccs_dp2keyword(bit);
927 pos = head->read_avail;
928 if (!ccs_io_printf(head, "allow_%s", msg) ||
929 !ccs_print_name_union(head, &ptr->name1) ||
930 !ccs_print_name_union(head, &ptr->name2) ||
931 !ccs_print_condition(head, cond))
932 goto out;
933 }
934 head->read_bit = 0;
935 return true;
936 out:
937 head->read_bit = bit;
938 head->read_avail = pos;
939 return false;
940 }
941
942 /**
943 * ccs_print_path_number_acl - Print an ioctl/chmod/chown/chgrp ACL entry.
944 *
945 * @head: Pointer to "struct ccs_io_buffer".
946 * @ptr: Pointer to "struct ccs_path_number_acl_record".
947 * @cond: Pointer to "struct ccs_condition". May be NULL.
948 *
949 * Returns true on success, false otherwise.
950 */
951 static bool ccs_print_path_number_acl(struct ccs_io_buffer *head,
952 struct ccs_path_number_acl_record *ptr,
953 const struct ccs_condition *cond)
954 {
955 int pos;
956 u8 bit;
957 const u8 perm = ptr->perm;
958 for (bit = head->read_bit; bit < CCS_MAX_PATH_NUMBER_OPERATION; bit++) {
959 const char *msg;
960 if (!(perm & (1 << bit)))
961 continue;
962 msg = ccs_path_number2keyword(bit);
963 pos = head->read_avail;
964 if (!ccs_io_printf(head, "allow_%s", msg) ||
965 !ccs_print_name_union(head, &ptr->name) ||
966 !ccs_print_number_union(head, &ptr->number) ||
967 !ccs_print_condition(head, cond))
968 goto out;
969 }
970 head->read_bit = 0;
971 return true;
972 out:
973 head->read_bit = bit;
974 head->read_avail = pos;
975 return false;
976 }
977
978 /**
979 * ccs_print_env_acl - Print an evironment variable name's ACL entry.
980 *
981 * @head: Pointer to "struct ccs_io_buffer".
982 * @ptr: Pointer to "struct ccs_env_acl_record".
983 * @cond: Pointer to "struct ccs_condition". May be NULL.
984 *
985 * Returns true on success, false otherwise.
986 */
987 static bool ccs_print_env_acl(struct ccs_io_buffer *head,
988 struct ccs_env_acl_record *ptr,
989 const struct ccs_condition *cond)
990 {
991 int pos = head->read_avail;
992 if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_ENV "%s", ptr->env->name))
993 goto out;
994 if (!ccs_print_condition(head, cond))
995 goto out;
996 return true;
997 out:
998 head->read_avail = pos;
999 return false;
1000 }
1001
1002 /**
1003 * ccs_print_capability_acl - Print a capability ACL entry.
1004 *
1005 * @head: Pointer to "struct ccs_io_buffer".
1006 * @ptr: Pointer to "struct ccs_capability_acl_record".
1007 * @cond: Pointer to "struct ccs_condition". May be NULL.
1008 *
1009 * Returns true on success, false otherwise.
1010 */
1011 static bool ccs_print_capability_acl(struct ccs_io_buffer *head,
1012 struct ccs_capability_acl_record *ptr,
1013 const struct ccs_condition *cond)
1014 {
1015 int pos = head->read_avail;
1016 if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_CAPABILITY "%s",
1017 ccs_cap2keyword(ptr->operation)))
1018 goto out;
1019 if (!ccs_print_condition(head, cond))
1020 goto out;
1021 return true;
1022 out:
1023 head->read_avail = pos;
1024 return false;
1025 }
1026
1027 /**
1028 * ccs_print_ipv4_entry - Print IPv4 address of a network ACL entry.
1029 *
1030 * @head: Pointer to "struct ccs_io_buffer".
1031 * @ptr: Pointer to "struct ccs_ip_network_acl_record".
1032 *
1033 * Returns true on success, false otherwise.
1034 */
1035 static bool ccs_print_ipv4_entry(struct ccs_io_buffer *head,
1036 struct ccs_ip_network_acl_record *ptr)
1037 {
1038 const u32 min_address = ptr->address.ipv4.min;
1039 const u32 max_address = ptr->address.ipv4.max;
1040 if (!ccs_io_printf(head, "%u.%u.%u.%u", HIPQUAD(min_address)))
1041 return false;
1042 if (min_address != max_address
1043 && !ccs_io_printf(head, "-%u.%u.%u.%u", HIPQUAD(max_address)))
1044 return false;
1045 return true;
1046 }
1047
1048 /**
1049 * ccs_print_ipv6_entry - Print IPv6 address of a network ACL entry.
1050 *
1051 * @head: Pointer to "struct ccs_io_buffer".
1052 * @ptr: Pointer to "struct ccs_ip_network_acl_record".
1053 *
1054 * Returns true on success, false otherwise.
1055 */
1056 static bool ccs_print_ipv6_entry(struct ccs_io_buffer *head,
1057 struct ccs_ip_network_acl_record *ptr)
1058 {
1059 char buf[64];
1060 const struct in6_addr *min_address = ptr->address.ipv6.min;
1061 const struct in6_addr *max_address = ptr->address.ipv6.max;
1062 ccs_print_ipv6(buf, sizeof(buf), min_address);
1063 if (!ccs_io_printf(head, "%s", buf))
1064 return false;
1065 if (min_address != max_address) {
1066 ccs_print_ipv6(buf, sizeof(buf), max_address);
1067 if (!ccs_io_printf(head, "-%s", buf))
1068 return false;
1069 }
1070 return true;
1071 }
1072
1073 /**
1074 * ccs_print_network_acl - Print a network ACL entry.
1075 *
1076 * @head: Pointer to "struct ccs_io_buffer".
1077 * @ptr: Pointer to "struct ccs_ip_network_acl_record".
1078 * @cond: Pointer to "struct ccs_condition". May be NULL.
1079 *
1080 * Returns true on success, false otherwise.
1081 */
1082 static bool ccs_print_network_acl(struct ccs_io_buffer *head,
1083 struct ccs_ip_network_acl_record *ptr,
1084 const struct ccs_condition *cond)
1085 {
1086 int pos = head->read_avail;
1087 if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_NETWORK "%s ",
1088 ccs_net2keyword(ptr->operation_type)))
1089 goto out;
1090 switch (ptr->record_type) {
1091 case CCS_IP_RECORD_TYPE_ADDRESS_GROUP:
1092 if (!ccs_io_printf(head, "@%s",
1093 ptr->address.group->group_name->name))
1094 goto out;
1095 break;
1096 case CCS_IP_RECORD_TYPE_IPv4:
1097 if (!ccs_print_ipv4_entry(head, ptr))
1098 goto out;
1099 break;
1100 case CCS_IP_RECORD_TYPE_IPv6:
1101 if (!ccs_print_ipv6_entry(head, ptr))
1102 goto out;
1103 break;
1104 }
1105 if (!ccs_print_number_union(head, &ptr->port) ||
1106 !ccs_print_condition(head, cond))
1107 goto out;
1108 return true;
1109 out:
1110 head->read_avail = pos;
1111 return false;
1112 }
1113
1114 /**
1115 * ccs_print_signal_acl - Print a signal ACL entry.
1116 *
1117 * @head: Pointer to "struct ccs_io_buffer".
1118 * @ptr: Pointer to "struct signale_acl_record".
1119 * @cond: Pointer to "struct ccs_condition". May be NULL.
1120 *
1121 * Returns true on success, false otherwise.
1122 */
1123 static bool ccs_print_signal_acl(struct ccs_io_buffer *head,
1124 struct ccs_signal_acl_record *ptr,
1125 const struct ccs_condition *cond)
1126 {
1127 int pos = head->read_avail;
1128 if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_SIGNAL "%u %s",
1129 ptr->sig, ptr->domainname->name))
1130 goto out;
1131 if (!ccs_print_condition(head, cond))
1132 goto out;
1133 return true;
1134 out:
1135 head->read_avail = pos;
1136 return false;
1137 }
1138
1139 /**
1140 * ccs_print_execute_handler_record - Print an execute handler ACL entry.
1141 *
1142 * @head: Pointer to "struct ccs_io_buffer".
1143 * @keyword: Name of the keyword.
1144 * @ptr: Pointer to "struct ccs_execute_handler_record".
1145 *
1146 * Returns true on success, false otherwise.
1147 */
1148 static bool ccs_print_execute_handler_record(struct ccs_io_buffer *head,
1149 const char *keyword,
1150 struct ccs_execute_handler_record *
1151 ptr)
1152 {
1153 return ccs_io_printf(head, "%s %s\n", keyword, ptr->handler->name);
1154 }
1155
1156 /**
1157 * ccs_print_mount_acl - Print a mount ACL entry.
1158 *
1159 * @head: Pointer to "struct ccs_io_buffer".
1160 * @ptr: Pointer to "struct ccs_mount_acl_record".
1161 * @cond: Pointer to "struct ccs_condition". May be NULL.
1162 *
1163 * Returns true on success, false otherwise.
1164 */
1165 static bool ccs_print_mount_acl(struct ccs_io_buffer *head,
1166 struct ccs_mount_acl_record *ptr,
1167 const struct ccs_condition *cond)
1168 {
1169 int pos = head->read_avail;
1170 if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_MOUNT "%s %s %s 0x%lX\n",
1171 ptr->dev_name->name, ptr->dir_name->name,
1172 ptr->fs_type->name, ptr->flags))
1173 goto out;
1174 if (!ccs_print_condition(head, cond))
1175 goto out;
1176 return true;
1177 out:
1178 head->read_avail = pos;
1179 return false;
1180 }
1181
1182 /**
1183 * ccs_print_umount_acl - Print a mount ACL entry.
1184 *
1185 * @head: Pointer to "struct ccs_io_buffer".
1186 * @ptr: Pointer to "struct ccs_umount_acl_record".
1187 * @cond: Pointer to "struct ccs_condition". May be NULL.
1188 *
1189 * Returns true on success, false otherwise.
1190 */
1191 static bool ccs_print_umount_acl(struct ccs_io_buffer *head,
1192 struct ccs_umount_acl_record *ptr,
1193 const struct ccs_condition *cond)
1194 {
1195 int pos = head->read_avail;
1196 if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_UNMOUNT "%s\n",
1197 ptr->dir->name))
1198 goto out;
1199 if (!ccs_print_condition(head, cond))
1200 goto out;
1201 return true;
1202 out:
1203 head->read_avail = pos;
1204 return false;
1205 }
1206
1207 /**
1208 * ccs_print_chroot_acl - Print a chroot ACL entry.
1209 *
1210 * @head: Pointer to "struct ccs_io_buffer".
1211 * @ptr: Pointer to "struct ccs_chroot_acl_record".
1212 * @cond: Pointer to "struct ccs_condition". May be NULL.
1213 *
1214 * Returns true on success, false otherwise.
1215 */
1216 static bool ccs_print_chroot_acl(struct ccs_io_buffer *head,
1217 struct ccs_chroot_acl_record *ptr,
1218 const struct ccs_condition *cond)
1219 {
1220 int pos = head->read_avail;
1221 if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_CHROOT "%s\n",
1222 ptr->dir->name))
1223 goto out;
1224 if (!ccs_print_condition(head, cond))
1225 goto out;
1226 return true;
1227 out:
1228 head->read_avail = pos;
1229 return false;
1230 }
1231
1232 /**
1233 * ccs_print_pivot_root_acl - Print a pivot_root ACL entry.
1234 *
1235 * @head: Pointer to "struct ccs_io_buffer".
1236 * @ptr: Pointer to "struct ccs_pivot_root_acl_record".
1237 * @cond: Pointer to "struct ccs_condition". May be NULL.
1238 *
1239 * Returns true on success, false otherwise.
1240 */
1241 static bool ccs_print_pivot_root_acl(struct ccs_io_buffer *head,
1242 struct ccs_pivot_root_acl_record *ptr,
1243 const struct ccs_condition *cond)
1244 {
1245 int pos = head->read_avail;
1246 if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_PIVOT_ROOT "%s %s\n",
1247 ptr->new_root->name, ptr->old_root->name))
1248 goto out;
1249 if (!ccs_print_condition(head, cond))
1250 goto out;
1251 return true;
1252 out:
1253 head->read_avail = pos;
1254 return false;
1255 }
1256
1257 /**
1258 * ccs_print_entry - Print an ACL entry.
1259 *
1260 * @head: Pointer to "struct ccs_io_buffer".
1261 * @ptr: Pointer to an ACL entry.
1262 *
1263 * Returns true on success, false otherwise.
1264 */
1265 static bool ccs_print_entry(struct ccs_io_buffer *head,
1266 struct ccs_acl_info *ptr)
1267 {
1268 const struct ccs_condition *cond = ptr->cond;
1269 const u8 acl_type = ccs_acl_type2(ptr);
1270 if (acl_type & CCS_ACL_DELETED)
1271 return true;
1272 if (acl_type == CCS_TYPE_SINGLE_PATH_ACL) {
1273 struct ccs_single_path_acl_record *acl
1274 = container_of(ptr, struct ccs_single_path_acl_record,
1275 head);
1276 return ccs_print_single_path_acl(head, acl, cond);
1277 }
1278 if (acl_type == CCS_TYPE_EXECUTE_HANDLER) {
1279 struct ccs_execute_handler_record *acl
1280 = container_of(ptr, struct ccs_execute_handler_record,
1281 head);
1282 const char *keyword = CCS_KEYWORD_EXECUTE_HANDLER;
1283 return ccs_print_execute_handler_record(head, keyword, acl);
1284 }
1285 if (acl_type == CCS_TYPE_DENIED_EXECUTE_HANDLER) {
1286 struct ccs_execute_handler_record *acl
1287 = container_of(ptr, struct ccs_execute_handler_record,
1288 head);
1289 const char *keyword = CCS_KEYWORD_DENIED_EXECUTE_HANDLER;
1290 return ccs_print_execute_handler_record(head, keyword, acl);
1291 }
1292 if (head->read_execute_only)
1293 return true;
1294 if (acl_type == CCS_TYPE_MKDEV_ACL) {
1295 struct ccs_mkdev_acl_record *acl
1296 = container_of(ptr, struct ccs_mkdev_acl_record, head);
1297 return ccs_print_mkdev_acl(head, acl, cond);
1298 }
1299 if (acl_type == CCS_TYPE_DOUBLE_PATH_ACL) {
1300 struct ccs_double_path_acl_record *acl
1301 = container_of(ptr, struct ccs_double_path_acl_record,
1302 head);
1303 return ccs_print_double_path_acl(head, acl, cond);
1304 }
1305 if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) {
1306 struct ccs_path_number_acl_record *acl
1307 = container_of(ptr, struct ccs_path_number_acl_record,
1308 head);
1309 return ccs_print_path_number_acl(head, acl, cond);
1310 }
1311 if (acl_type == CCS_TYPE_ENV_ACL) {
1312 struct ccs_env_acl_record *acl
1313 = container_of(ptr, struct ccs_env_acl_record, head);
1314 return ccs_print_env_acl(head, acl, cond);
1315 }
1316 if (acl_type == CCS_TYPE_CAPABILITY_ACL) {
1317 struct ccs_capability_acl_record *acl
1318 = container_of(ptr, struct ccs_capability_acl_record,
1319 head);
1320 return ccs_print_capability_acl(head, acl, cond);
1321 }
1322 if (acl_type == CCS_TYPE_IP_NETWORK_ACL) {
1323 struct ccs_ip_network_acl_record *acl
1324 = container_of(ptr, struct ccs_ip_network_acl_record,
1325 head);
1326 return ccs_print_network_acl(head, acl, cond);
1327 }
1328 if (acl_type == CCS_TYPE_SIGNAL_ACL) {
1329 struct ccs_signal_acl_record *acl
1330 = container_of(ptr, struct ccs_signal_acl_record, head);
1331 return ccs_print_signal_acl(head, acl, cond);
1332 }
1333 if (acl_type == CCS_TYPE_MOUNT_ACL) {
1334 struct ccs_mount_acl_record *acl
1335 = container_of(ptr, struct ccs_mount_acl_record, head);
1336 return ccs_print_mount_acl(head, acl, cond);
1337 }
1338 if (acl_type == CCS_TYPE_UMOUNT_ACL) {
1339 struct ccs_umount_acl_record *acl
1340 = container_of(ptr, struct ccs_umount_acl_record, head);
1341 return ccs_print_umount_acl(head, acl, cond);
1342 }
1343 if (acl_type == CCS_TYPE_CHROOT_ACL) {
1344 struct ccs_chroot_acl_record *acl
1345 = container_of(ptr, struct ccs_chroot_acl_record, head);
1346 return ccs_print_chroot_acl(head, acl, cond);
1347 }
1348 if (acl_type == CCS_TYPE_PIVOT_ROOT_ACL) {
1349 struct ccs_pivot_root_acl_record *acl
1350 = container_of(ptr, struct ccs_pivot_root_acl_record,
1351 head);
1352 return ccs_print_pivot_root_acl(head, acl, cond);
1353 }
1354 /* Workaround for gcc 3.2.2's inline bug. */
1355 if (acl_type & CCS_ACL_DELETED)
1356 return true;
1357 BUG(); /* This must not happen. */
1358 return false;
1359 }
1360
1361 /**
1362 * ccs_read_domain_policy - Read domain policy.
1363 *
1364 * @head: Pointer to "struct ccs_io_buffer".
1365 *
1366 * Returns 0.
1367 *
1368 * Caller holds ccs_read_lock().
1369 */
1370 static int ccs_read_domain_policy(struct ccs_io_buffer *head)
1371 {
1372 struct list_head *dpos;
1373 struct list_head *apos;
1374 ccs_check_read_lock();
1375 if (head->read_eof)
1376 return 0;
1377 if (head->read_step == 0)
1378 head->read_step = 1;
1379 list_for_each_cookie(dpos, head->read_var1, &ccs_domain_list) {
1380 struct ccs_domain_info *domain;
1381 const char *quota_exceeded = "";
1382 const char *transition_failed = "";
1383 const char *ignore_global_allow_read = "";
1384 const char *ignore_global_allow_env = "";
1385 domain = list_entry(dpos, struct ccs_domain_info, list);
1386 if (head->read_step != 1)
1387 goto acl_loop;
1388 if (domain->is_deleted && !head->read_single_domain)
1389 continue;
1390 /* Print domainname and flags. */
1391 if (domain->quota_warned)
1392 quota_exceeded = "quota_exceeded\n";
1393 if (domain->domain_transition_failed)
1394 transition_failed = "transition_failed\n";
1395 if (domain->ignore_global_allow_read)
1396 ignore_global_allow_read
1397 = CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n";
1398 if (domain->ignore_global_allow_env)
1399 ignore_global_allow_env
1400 = CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_ENV "\n";
1401 if (!ccs_io_printf(head, "%s\n" CCS_KEYWORD_USE_PROFILE "%u\n"
1402 "%s%s%s%s\n", domain->domainname->name,
1403 domain->profile, quota_exceeded,
1404 transition_failed,
1405 ignore_global_allow_read,
1406 ignore_global_allow_env))
1407 return 0;
1408 head->read_step = 2;
1409 acl_loop:
1410 if (head->read_step == 3)
1411 goto tail_mark;
1412 /* Print ACL entries in the domain. */
1413 list_for_each_cookie(apos, head->read_var2,
1414 &domain->acl_info_list) {
1415 struct ccs_acl_info *ptr
1416 = list_entry(apos, struct ccs_acl_info, list);
1417 if (!ccs_print_entry(head, ptr))
1418 return 0;
1419 }
1420 head->read_step = 3;
1421 tail_mark:
1422 if (!ccs_io_printf(head, "\n"))
1423 return 0;
1424 head->read_step = 1;
1425 if (head->read_single_domain)
1426 break;
1427 }
1428 head->read_eof = true;
1429 return 0;
1430 }
1431
1432 /**
1433 * ccs_write_domain_profile - Assign profile for specified domain.
1434 *
1435 * @head: Pointer to "struct ccs_io_buffer".
1436 *
1437 * Returns 0 on success, -EINVAL otherwise.
1438 *
1439 * This is equivalent to doing
1440 *
1441 * ( echo "select " $domainname; echo "use_profile " $profile ) |
1442 * /usr/lib/ccs/loadpolicy -d
1443 *
1444 * Caller holds ccs_read_lock().
1445 */
1446 static int ccs_write_domain_profile(struct ccs_io_buffer *head)
1447 {
1448 char *data = head->write_buf;
1449 char *cp = strchr(data, ' ');
1450 struct ccs_domain_info *domain;
1451 unsigned int profile;
1452 ccs_check_read_lock();
1453 if (!cp)
1454 return -EINVAL;
1455 *cp = '\0';
1456 profile = simple_strtoul(data, NULL, 10);
1457 if (profile >= CCS_MAX_PROFILES)
1458 return -EINVAL;
1459 domain = ccs_find_domain(cp + 1);
1460 if (domain && (ccs_profile_ptr[profile] || !ccs_policy_loaded))
1461 domain->profile = (u8) profile;
1462 return 0;
1463 }
1464
1465 /**
1466 * ccs_read_domain_profile - Read only domainname and profile.
1467 *
1468 * @head: Pointer to "struct ccs_io_buffer".
1469 *
1470 * Returns list of profile number and domainname pairs.
1471 *
1472 * This is equivalent to doing
1473 *
1474 * grep -A 1 '^<kernel>' /proc/ccs/domain_policy |
1475 * awk ' { if ( domainname == "" ) { if ( $1 == "<kernel>" )
1476 * domainname = $0; } else if ( $1 == "use_profile" ) {
1477 * print $2 " " domainname; domainname = ""; } } ; '
1478 *
1479 * Caller holds ccs_read_lock().
1480 */
1481 static int ccs_read_domain_profile(struct ccs_io_buffer *head)
1482 {
1483 struct list_head *pos;
1484 ccs_check_read_lock();
1485 if (head->read_eof)
1486 return 0;
1487 list_for_each_cookie(pos, head->read_var1, &ccs_domain_list) {
1488 struct ccs_domain_info *domain;
1489 domain = list_entry(pos, struct ccs_domain_info, list);
1490 if (domain->is_deleted)
1491 continue;
1492 if (!ccs_io_printf(head, "%u %s\n", domain->profile,
1493 domain->domainname->name))
1494 return 0;
1495 }
1496 head->read_eof = true;
1497 return 0;
1498 }
1499
1500 /**
1501 * ccs_write_pid: Specify PID to obtain domainname.
1502 *
1503 * @head: Pointer to "struct ccs_io_buffer".
1504 *
1505 * Returns 0.
1506 */
1507 static int ccs_write_pid(struct ccs_io_buffer *head)
1508 {
1509 head->read_eof = false;
1510 return 0;
1511 }
1512
1513 /**
1514 * ccs_read_pid - Read information of a process.
1515 *
1516 * @head: Pointer to "struct ccs_io_buffer".
1517 *
1518 * Returns the domainname which the specified PID is in or
1519 * process information of the specified PID on success,
1520 * empty string otherwise.
1521 *
1522 * Caller holds ccs_read_lock().
1523 */
1524 static int ccs_read_pid(struct ccs_io_buffer *head)
1525 {
1526 char *buf = head->write_buf;
1527 bool task_info = false;
1528 unsigned int pid;
1529 struct task_struct *p;
1530 struct ccs_domain_info *domain = NULL;
1531 u32 ccs_flags = 0;
1532 ccs_check_read_lock();
1533 /* Accessing write_buf is safe because head->io_sem is held. */
1534 if (!buf)
1535 goto done; /* Do nothing if open(O_RDONLY). */
1536 if (head->read_avail || head->read_eof)
1537 goto done;
1538 head->read_eof = true;
1539 if (ccs_str_starts(&buf, "info "))
1540 task_info = true;
1541 pid = (unsigned int) simple_strtoul(buf, NULL, 10);
1542 /***** CRITICAL SECTION START *****/
1543 read_lock(&tasklist_lock);
1544 p = find_task_by_pid(pid);
1545 if (p) {
1546 domain = ccs_task_domain(p);
1547 ccs_flags = p->ccs_flags;
1548 }
1549 read_unlock(&tasklist_lock);
1550 /***** CRITICAL SECTION END *****/
1551 if (!domain)
1552 goto done;
1553 if (!task_info)
1554 ccs_io_printf(head, "%u %u %s", pid, domain->profile,
1555 domain->domainname->name);
1556 else
1557 ccs_io_printf(head, "%u manager=%s execute_handler=%s "
1558 "state[0]=%u state[1]=%u state[2]=%u", pid,
1559 ccs_flags & CCS_TASK_IS_POLICY_MANAGER ?
1560 "yes" : "no",
1561 ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER ?
1562 "yes" : "no",
1563 (u8) (ccs_flags >> 24),
1564 (u8) (ccs_flags >> 16),
1565 (u8) (ccs_flags >> 8));
1566 done:
1567 return 0;
1568 }
1569
1570 /**
1571 * ccs_write_exception_policy - Write exception policy.
1572 *
1573 * @head: Pointer to "struct ccs_io_buffer".
1574 *
1575 * Returns 0 on success, negative value otherwise.
1576 */
1577 static int ccs_write_exception_policy(struct ccs_io_buffer *head)
1578 {
1579 char *data = head->write_buf;
1580 bool is_delete = ccs_str_starts(&data, CCS_KEYWORD_DELETE);
1581 if (ccs_str_starts(&data, CCS_KEYWORD_KEEP_DOMAIN))
1582 return ccs_write_domain_keeper_policy(data, false, is_delete);
1583 if (ccs_str_starts(&data, CCS_KEYWORD_NO_KEEP_DOMAIN))
1584 return ccs_write_domain_keeper_policy(data, true, is_delete);
1585 if (ccs_str_starts(&data, CCS_KEYWORD_INITIALIZE_DOMAIN))
1586 return ccs_write_domain_initializer_policy(data, false,
1587 is_delete);
1588 if (ccs_str_starts(&data, CCS_KEYWORD_NO_INITIALIZE_DOMAIN))
1589 return ccs_write_domain_initializer_policy(data, true,
1590 is_delete);
1591 if (ccs_str_starts(&data, CCS_KEYWORD_AGGREGATOR))
1592 return ccs_write_aggregator_policy(data, is_delete);
1593 if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_READ))
1594 return ccs_write_globally_readable_policy(data, is_delete);
1595 if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_ENV))
1596 return ccs_write_globally_usable_env_policy(data, is_delete);
1597 if (ccs_str_starts(&data, CCS_KEYWORD_FILE_PATTERN))
1598 return ccs_write_pattern_policy(data, is_delete);
1599 if (ccs_str_starts(&data, CCS_KEYWORD_PATH_GROUP))
1600 return ccs_write_path_group_policy(data, is_delete);
1601 if (ccs_str_starts(&data, CCS_KEYWORD_NUMBER_GROUP))
1602 return ccs_write_number_group_policy(data, is_delete);
1603 if (ccs_str_starts(&data, CCS_KEYWORD_DENY_REWRITE))
1604 return ccs_write_no_rewrite_policy(data, is_delete);
1605 if (ccs_str_starts(&data, CCS_KEYWORD_ADDRESS_GROUP))
1606 return ccs_write_address_group_policy(data, is_delete);
1607 if (ccs_str_starts(&data, CCS_KEYWORD_DENY_AUTOBIND))
1608 return ccs_write_reserved_port_policy(data, is_delete);
1609 return -EINVAL;
1610 }
1611
1612 /**
1613 * ccs_read_exception_policy - Read exception policy.
1614 *
1615 * @head: Pointer to "struct ccs_io_buffer".
1616 *
1617 * Returns 0 on success, -EINVAL otherwise.
1618 *
1619 * Caller holds ccs_read_lock().
1620 */
1621 static int ccs_read_exception_policy(struct ccs_io_buffer *head)
1622 {
1623 ccs_check_read_lock();
1624 if (!head->read_eof) {
1625 switch (head->read_step) {
1626 case 0:
1627 head->read_var2 = NULL;
1628 head->read_step = 1;
1629 case 1:
1630 if (!ccs_read_domain_keeper_policy(head))
1631 break;
1632 head->read_var2 = NULL;
1633 head->read_step = 2;
1634 case 2:
1635 if (!ccs_read_globally_readable_policy(head))
1636 break;
1637 head->read_var2 = NULL;
1638 head->read_step = 3;
1639 case 3:
1640 if (!ccs_read_globally_usable_env_policy(head))
1641 break;
1642 head->read_var2 = NULL;
1643 head->read_step = 4;
1644 case 4:
1645 if (!ccs_read_domain_initializer_policy(head))
1646 break;
1647 head->read_var2 = NULL;
1648 head->read_step = 6;
1649 case 6:
1650 if (!ccs_read_aggregator_policy(head))
1651 break;
1652 head->read_var2 = NULL;
1653 head->read_step = 7;
1654 case 7:
1655 if (!ccs_read_file_pattern(head))
1656 break;
1657 head->read_var2 = NULL;
1658 head->read_step = 8;
1659 case 8:
1660 if (!ccs_read_no_rewrite_policy(head))
1661 break;
1662 head->read_var2 = NULL;
1663 head->read_step = 9;
1664 case 9:
1665 if (!ccs_read_path_group_policy(head))
1666 break;
1667 head->read_var1 = NULL;
1668 head->read_var2 = NULL;
1669 head->read_step = 10;
1670 case 10:
1671 if (!ccs_read_number_group_policy(head))
1672 break;
1673 head->read_var1 = NULL;
1674 head->read_var2 = NULL;
1675 head->read_step = 11;
1676 case 11:
1677 if (!ccs_read_address_group_policy(head))
1678 break;
1679 head->read_var2 = NULL;
1680 head->read_step = 12;
1681 case 12:
1682 if (!ccs_read_reserved_port_policy(head))
1683 break;
1684 head->read_eof = true;
1685 break;
1686 default:
1687 return -EINVAL;
1688 }
1689 }
1690 return 0;
1691 }
1692
1693 /* Wait queue for ccs_query_list. */
1694 static DECLARE_WAIT_QUEUE_HEAD(ccs_query_wait);
1695
1696 /* Lock for manipulating ccs_query_list. */
1697 static DEFINE_SPINLOCK(ccs_query_list_lock);
1698
1699 /* Structure for query. */
1700 struct ccs_query_entry {
1701 struct list_head list;
1702 char *query;
1703 int query_len;
1704 unsigned int serial;
1705 int timer;
1706 int answer;
1707 };
1708
1709 /* The list for "struct ccs_query_entry". */
1710 static LIST_HEAD(ccs_query_list);
1711
1712 /* Number of "struct file" referring /proc/ccs/query interface. */
1713 static atomic_t ccs_query_observers = ATOMIC_INIT(0);
1714
1715 /**
1716 * ccs_check_supervisor - Ask for the supervisor's decision.
1717 *
1718 * @r: Pointer to "struct ccs_request_info".
1719 * @fmt: The printf()'s format string, followed by parameters.
1720 *
1721 * Returns 0 if the supervisor decided to permit the access request which
1722 * violated the policy in enforcing mode, 1 if the supervisor decided to
1723 * retry the access request which violated the policy in enforcing mode,
1724 * -EPERM otherwise.
1725 */
1726 int ccs_check_supervisor(struct ccs_request_info *r, const char *fmt, ...)
1727 {
1728 va_list args;
1729 int error = -EPERM;
1730 int pos;
1731 int len;
1732 static unsigned int ccs_serial;
1733 struct ccs_query_entry *ccs_query_entry = NULL;
1734 bool quota_exceeded = false;
1735 char *header;
1736 if (!r->domain)
1737 r->domain = ccs_current_domain();
1738 if (!atomic_read(&ccs_query_observers)) {
1739 int i;
1740 if (current->ccs_flags & CCS_DONT_SLEEP_ON_ENFORCE_ERROR)
1741 return -EPERM;
1742 for (i = 0; i < ccs_check_flags(r->domain, CCS_SLEEP_PERIOD);
1743 i++) {
1744 set_current_state(TASK_INTERRUPTIBLE);
1745 schedule_timeout(HZ / 10);
1746 }
1747 return -EPERM;
1748 }
1749 va_start(args, fmt);
1750 len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 32;
1751 va_end(args);
1752 header = ccs_init_audit_log(&len, r);
1753 if (!header)
1754 goto out;
1755 ccs_query_entry = kzalloc(sizeof(*ccs_query_entry), GFP_KERNEL);
1756 if (!ccs_query_entry)
1757 goto out;
1758 ccs_query_entry->query = kzalloc(len, GFP_KERNEL);
1759 if (!ccs_query_entry->query)
1760 goto out;
1761 INIT_LIST_HEAD(&ccs_query_entry->list);
1762 /***** CRITICAL SECTION START *****/
1763 spin_lock(&ccs_query_list_lock);
1764 if (ccs_quota_for_query && ccs_query_memory_size + len +
1765 sizeof(*ccs_query_entry) >= ccs_quota_for_query) {
1766 quota_exceeded = true;
1767 } else {
1768 ccs_query_memory_size += len + sizeof(*ccs_query_entry);
1769 ccs_query_entry->serial = ccs_serial++;
1770 }
1771 spin_unlock(&ccs_query_list_lock);
1772 /***** CRITICAL SECTION END *****/
1773 if (quota_exceeded)
1774 goto out;
1775 pos = snprintf(ccs_query_entry->query, len - 1, "Q%u-%hu\n%s",
1776 ccs_query_entry->serial, r->retry, header);
1777 kfree(header);
1778 header = NULL;
1779 va_start(args, fmt);
1780 vsnprintf(ccs_query_entry->query + pos, len - 1 - pos, fmt, args);
1781 ccs_query_entry->query_len = strlen(ccs_query_entry->query) + 1;
1782 va_end(args);
1783 /***** CRITICAL SECTION START *****/
1784 spin_lock(&ccs_query_list_lock);
1785 list_add_tail(&ccs_query_entry->list, &ccs_query_list);
1786 spin_unlock(&ccs_query_list_lock);
1787 /***** CRITICAL SECTION END *****/
1788 /* Give 10 seconds for supervisor's opinion. */
1789 for (ccs_query_entry->timer = 0;
1790 atomic_read(&ccs_query_observers) && ccs_query_entry->timer < 100;
1791 ccs_query_entry->timer++) {
1792 wake_up(&ccs_query_wait);
1793 set_current_state(TASK_INTERRUPTIBLE);
1794 schedule_timeout(HZ / 10);
1795 if (ccs_query_entry->answer)
1796 break;
1797 }
1798 /***** CRITICAL SECTION START *****/
1799 spin_lock(&ccs_query_list_lock);
1800 list_del(&ccs_query_entry->list);
1801 ccs_query_memory_size -= len + sizeof(*ccs_query_entry);
1802 spin_unlock(&ccs_query_list_lock);
1803 /***** CRITICAL SECTION END *****/
1804 switch (ccs_query_entry->answer) {
1805 case 3: /* Asked to retry by administrator. */
1806 error = 1;
1807 r->retry++;
1808 break;
1809 case 1:
1810 /* Granted by administrator. */
1811 error = 0;
1812 break;
1813 case 0:
1814 /* Timed out. */
1815 break;
1816 default:
1817 /* Rejected by administrator. */
1818 break;
1819 }
1820 out:
1821 if (ccs_query_entry)
1822 kfree(ccs_query_entry->query);
1823 kfree(ccs_query_entry);
1824 kfree(header);
1825 return error;
1826 }
1827
1828 /**
1829 * ccs_poll_query - poll() for /proc/ccs/query.
1830 *
1831 * @file: Pointer to "struct file".
1832 * @wait: Pointer to "poll_table".
1833 *
1834 * Returns POLLIN | POLLRDNORM when ready to read, 0 otherwise.
1835 *
1836 * Waits for access requests which violated policy in enforcing mode.
1837 */
1838 static int ccs_poll_query(struct file *file, poll_table *wait)
1839 {
1840 struct list_head *tmp;
1841 bool found = false;
1842 u8 i;
1843 for (i = 0; i < 2; i++) {
1844 /***** CRITICAL SECTION START *****/
1845 spin_lock(&ccs_query_list_lock);
1846 list_for_each(tmp, &ccs_query_list) {
1847 struct ccs_query_entry *ptr
1848 = list_entry(tmp, struct ccs_query_entry, list);
1849 if (ptr->answer)
1850 continue;
1851 found = true;
1852 break;
1853 }
1854 spin_unlock(&ccs_query_list_lock);
1855 /***** CRITICAL SECTION END *****/
1856 if (found)
1857 return POLLIN | POLLRDNORM;
1858 if (i)
1859 break;
1860 poll_wait(file, &ccs_query_wait, wait);
1861 }
1862 return 0;
1863 }
1864
1865 /**
1866 * ccs_read_query - Read access requests which violated policy in enforcing mode.
1867 *
1868 * @head: Pointer to "struct ccs_io_buffer".
1869 *
1870 * Returns 0.
1871 */
1872 static int ccs_read_query(struct ccs_io_buffer *head)
1873 {
1874 struct list_head *tmp;
1875 int pos = 0;
1876 int len = 0;
1877 char *buf;
1878 if (head->read_avail)
1879 return 0;
1880 if (head->read_buf) {
1881 kfree(head->read_buf);
1882 head->read_buf = NULL;
1883 head->readbuf_size = 0;
1884 }
1885 /***** CRITICAL SECTION START *****/
1886 spin_lock(&ccs_query_list_lock);
1887 list_for_each(tmp, &ccs_query_list) {
1888 struct ccs_query_entry *ptr
1889 = list_entry(tmp, struct ccs_query_entry, list);
1890 if (ptr->answer)
1891 continue;
1892 if (pos++ != head->read_step)
1893 continue;
1894 len = ptr->query_len;
1895 break;
1896 }
1897 spin_unlock(&ccs_query_list_lock);
1898 /***** CRITICAL SECTION END *****/
1899 if (!len) {
1900 head->read_step = 0;
1901 return 0;
1902 }
1903 buf = kzalloc(len, GFP_KERNEL);
1904 if (!buf)
1905 return 0;
1906 pos = 0;
1907 /***** CRITICAL SECTION START *****/
1908 spin_lock(&ccs_query_list_lock);
1909 list_for_each(tmp, &ccs_query_list) {
1910 struct ccs_query_entry *ptr
1911 = list_entry(tmp, struct ccs_query_entry, list);
1912 if (ptr->answer)
1913 continue;
1914 if (pos++ != head->read_step)
1915 continue;
1916 /*
1917 * Some query can be skipped because ccs_query_list
1918 * can change, but I don't care.
1919 */
1920 if (len == ptr->query_len)
1921 memmove(buf, ptr->query, len);
1922 break;
1923 }
1924 spin_unlock(&ccs_query_list_lock);
1925 /***** CRITICAL SECTION END *****/
1926 if (buf[0]) {
1927 head->read_avail = len;
1928 head->readbuf_size = head->read_avail;
1929 head->read_buf = buf;
1930 head->read_step++;
1931 } else {
1932 kfree(buf);
1933 }
1934 return 0;
1935 }
1936
1937 /**
1938 * ccs_write_answer - Write the supervisor's decision.
1939 *
1940 * @head: Pointer to "struct ccs_io_buffer".
1941 *
1942 * Returns 0 on success, -EINVAL otherwise.
1943 */
1944 static int ccs_write_answer(struct ccs_io_buffer *head)
1945 {
1946 char *data = head->write_buf;
1947 struct list_head *tmp;
1948 unsigned int serial;
1949 unsigned int answer;
1950 /***** CRITICAL SECTION START *****/
1951 spin_lock(&ccs_query_list_lock);
1952 list_for_each(tmp, &ccs_query_list) {
1953 struct ccs_query_entry *ptr
1954 = list_entry(tmp, struct ccs_query_entry, list);
1955 ptr->timer = 0;
1956 }
1957 spin_unlock(&ccs_query_list_lock);
1958 /***** CRITICAL SECTION END *****/
1959 if (sscanf(data, "A%u=%u", &serial, &answer) != 2)
1960 return -EINVAL;
1961 /***** CRITICAL SECTION START *****/
1962 spin_lock(&ccs_query_list_lock);
1963 list_for_each(tmp, &ccs_query_list) {
1964 struct ccs_query_entry *ptr
1965 = list_entry(tmp, struct ccs_query_entry, list);
1966 if (ptr->serial != serial)
1967 continue;
1968 if (!ptr->answer)
1969 ptr->answer = answer;
1970 break;
1971 }
1972 spin_unlock(&ccs_query_list_lock);
1973 /***** CRITICAL SECTION END *****/
1974 return 0;
1975 }
1976
1977 /**
1978 * ccs_read_version: Get version.
1979 *
1980 * @head: Pointer to "struct ccs_io_buffer".
1981 *
1982 * Returns version information.
1983 */
1984 static int ccs_read_version(struct ccs_io_buffer *head)
1985 {
1986 if (!head->read_eof) {
1987 ccs_io_printf(head, "1.7.0-pre");
1988 head->read_eof = true;
1989 }
1990 return 0;
1991 }
1992
1993 /**
1994 * ccs_read_self_domain - Get the current process's domainname.
1995 *
1996 * @head: Pointer to "struct ccs_io_buffer".
1997 *
1998 * Returns the current process's domainname.
1999 */
2000 static int ccs_read_self_domain(struct ccs_io_buffer *head)
2001 {
2002 if (!head->read_eof) {
2003 /*
2004 * ccs_current_domain()->domainname != NULL
2005 * because every process belongs to a domain and
2006 * the domain's name cannot be NULL.
2007 */
2008 ccs_io_printf(head, "%s",
2009 ccs_current_domain()->domainname->name);
2010 head->read_eof = true;
2011 }
2012 return 0;
2013 }
2014
2015 /**
2016 * ccs_open_control - open() for /proc/ccs/ interface.
2017 *
2018 * @type: Type of interface.
2019 * @file: Pointer to "struct file".
2020 *
2021 * Associates policy handler and returns 0 on success, -ENOMEM otherwise.
2022 */
2023 int ccs_open_control(const u8 type, struct file *file)
2024 {
2025 struct ccs_io_buffer *head = kzalloc(sizeof(*head), GFP_KERNEL);
2026 if (!head)
2027 return -ENOMEM;
2028 mutex_init(&head->io_sem);
2029 head->type = type;
2030 switch (type) {
2031 case CCS_DOMAINPOLICY: /* /proc/ccs/domain_policy */
2032 head->write = ccs_write_domain_policy;
2033 head->read = ccs_read_domain_policy;
2034 break;
2035 case CCS_EXCEPTIONPOLICY: /* /proc/ccs/exception_policy */
2036 head->write = ccs_write_exception_policy;
2037 head->read = ccs_read_exception_policy;
2038 break;
2039 #ifdef CONFIG_CCSECURITY_AUDIT
2040 case CCS_GRANTLOG: /* /proc/ccs/grant_log */
2041 head->poll = ccs_poll_grant_log;
2042 head->read = ccs_read_grant_log;
2043 break;
2044 case CCS_REJECTLOG: /* /proc/ccs/reject_log */
2045 head->poll = ccs_poll_reject_log;
2046 head->read = ccs_read_reject_log;
2047 break;
2048 #endif
2049 case CCS_SELFDOMAIN: /* /proc/ccs/self_domain */
2050 head->read = ccs_read_self_domain;
2051 break;
2052 case CCS_DOMAIN_STATUS: /* /proc/ccs/.domain_status */
2053 head->write = ccs_write_domain_profile;
2054 head->read = ccs_read_domain_profile;
2055 break;
2056 case CCS_EXECUTE_HANDLER: /* /proc/ccs/.execute_handler */
2057 /* Allow execute_handler to read process's status. */
2058 if (!(current->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER)) {
2059 kfree(head);
2060 return -EPERM;
2061 }
2062 /* fall through */
2063 case CCS_PROCESS_STATUS: /* /proc/ccs/.process_status */
2064 head->write = ccs_write_pid;
2065 head->read = ccs_read_pid;
2066 break;
2067 case CCS_VERSION: /* /proc/ccs/version */
2068 head->read = ccs_read_version;
2069 head->readbuf_size = 128;
2070 break;
2071 case CCS_MEMINFO: /* /proc/ccs/meminfo */
2072 head->write = ccs_write_memory_quota;
2073 head->read = ccs_read_memory_counter;
2074 head->readbuf_size = 512;
2075 break;
2076 case CCS_PROFILE: /* /proc/ccs/profile */
2077 head->write = ccs_write_profile;
2078 head->read = ccs_read_profile;
2079 break;
2080 case CCS_QUERY: /* /proc/ccs/query */
2081 head->poll = ccs_poll_query;
2082 head->write = ccs_write_answer;
2083 head->read = ccs_read_query;
2084 break;
2085 case CCS_MANAGER: /* /proc/ccs/manager */
2086 head->write = ccs_write_manager_policy;
2087 head->read = ccs_read_manager_policy;
2088 break;
2089 }
2090 if (!(file->f_mode & FMODE_READ)) {
2091 /*
2092 * No need to allocate read_buf since it is not opened
2093 * for reading.
2094 */
2095 head->read = NULL;
2096 head->poll = NULL;
2097 } else if (type != CCS_QUERY &&
2098 type != CCS_GRANTLOG && type != CCS_REJECTLOG) {
2099 /*
2100 * Don't allocate buffer for reading if the file is one of
2101 * /proc/ccs/grant_log , /proc/ccs/reject_log , /proc/ccs/query.
2102 */
2103 if (!head->readbuf_size)
2104 head->readbuf_size = 4096 * 2;
2105 head->read_buf = kzalloc(head->readbuf_size, GFP_KERNEL);
2106 if (!head->read_buf) {
2107 kfree(head);
2108 return -ENOMEM;
2109 }
2110 }
2111 if (!(file->f_mode & FMODE_WRITE)) {
2112 /*
2113 * No need to allocate write_buf since it is not opened
2114 * for writing.
2115 */
2116 head->write = NULL;
2117 } else if (head->write) {
2118 head->writebuf_size = 4096 * 2;
2119 head->write_buf = kzalloc(head->writebuf_size, GFP_KERNEL);
2120 if (!head->write_buf) {
2121 kfree(head->read_buf);
2122 kfree(head);
2123 return -ENOMEM;
2124 }
2125 }
2126 if (type != CCS_QUERY &&
2127 type != CCS_GRANTLOG && type != CCS_REJECTLOG)
2128 head->reader_idx = ccs_read_lock();
2129 file->private_data = head;
2130 /*
2131 * Call the handler now if the file is /proc/ccs/self_domain
2132 * so that the user can use "cat < /proc/ccs/self_domain" to
2133 * know the current process's domainname.
2134 */
2135 if (type == CCS_SELFDOMAIN)
2136 ccs_read_control(file, NULL, 0);
2137 /*
2138 * If the file is /proc/ccs/query , increment the observer counter.
2139 * The obserber counter is used by ccs_check_supervisor() to see if
2140 * there is some process monitoring /proc/ccs/query.
2141 */
2142 else if (type == CCS_QUERY)
2143 atomic_inc(&ccs_query_observers);
2144 return 0;
2145 }
2146
2147 /**
2148 * ccs_poll_control - poll() for /proc/ccs/ interface.
2149 *
2150 * @file: Pointer to "struct file".
2151 * @wait: Pointer to "poll_table".
2152 *
2153 * Waits for read readiness.
2154 * /proc/ccs/query is handled by /usr/lib/ccs/ccs-queryd and
2155 * /proc/ccs/grant_log and /proc/ccs/reject_log are handled by
2156 * /usr/lib/ccs/ccs-auditd.
2157 */
2158 int ccs_poll_control(struct file *file, poll_table *wait)
2159 {
2160 struct ccs_io_buffer *head = file->private_data;
2161 if (!head->poll)
2162 return -ENOSYS;
2163 return head->poll(file, wait);
2164 }
2165
2166 /**
2167 * ccs_read_control - read() for /proc/ccs/ interface.
2168 *
2169 * @file: Pointer to "struct file".
2170 * @buffer: Poiner to buffer to write to.
2171 * @buffer_len: Size of @buffer.
2172 *
2173 * Returns bytes read on success, negative value otherwise.
2174 */
2175 int ccs_read_control(struct file *file, char __user *buffer,
2176 const int buffer_len)
2177 {
2178 int len = 0;
2179 struct ccs_io_buffer *head = file->private_data;
2180 char *cp;
2181 if (!head->read)
2182 return -ENOSYS;
2183 if (!access_ok(VERIFY_WRITE, buffer, buffer_len))
2184 return -EFAULT;
2185 if (mutex_lock_interruptible(&head->io_sem))
2186 return -EINTR;
2187 /* Call the policy handler. */
2188 len = head->read(head);
2189 if (len < 0)
2190 goto out;
2191 /* Write to buffer. */
2192 len = head->read_avail;
2193 if (len > buffer_len)
2194 len = buffer_len;
2195 if (!len)
2196 goto out;
2197 /* head->read_buf changes by some functions. */
2198 cp = head->read_buf;
2199 if (copy_to_user(buffer, cp, len)) {
2200 len = -EFAULT;
2201 goto out;
2202 }
2203 head->read_avail -= len;
2204 memmove(cp, cp + len, head->read_avail);
2205 out:
2206 mutex_unlock(&head->io_sem);
2207 return len;
2208 }
2209
2210 /**
2211 * ccs_write_control - write() for /proc/ccs/ interface.
2212 *
2213 * @file: Pointer to "struct file".
2214 * @buffer: Pointer to buffer to read from.
2215 * @buffer_len: Size of @buffer.
2216 *
2217 * Returns @buffer_len on success, negative value otherwise.
2218 */
2219 int ccs_write_control(struct file *file, const char __user *buffer,
2220 const int buffer_len)
2221 {
2222 struct ccs_io_buffer *head = file->private_data;
2223 int error = buffer_len;
2224 int avail_len = buffer_len;
2225 char *cp0 = head->write_buf;
2226 if (!head->write)
2227 return -ENOSYS;
2228 if (!access_ok(VERIFY_READ, buffer, buffer_len))
2229 return -EFAULT;
2230 /* Don't allow updating policies by non manager programs. */
2231 if (head->write != ccs_write_pid &&
2232 head->write != ccs_write_domain_policy &&
2233 !ccs_is_policy_manager())
2234 return -EPERM;
2235 if (mutex_lock_interruptible(&head->io_sem))
2236 return -EINTR;
2237 /* Read a line and dispatch it to the policy handler. */
2238 while (avail_len > 0) {
2239 char c;
2240 if (head->write_avail >= head->writebuf_size - 1) {
2241 error = -ENOMEM;
2242 break;
2243 } else if (get_user(c, buffer)) {
2244 error = -EFAULT;
2245 break;
2246 }
2247 buffer++;
2248 avail_len--;
2249 cp0[head->write_avail++] = c;
2250 if (c != '\n')
2251 continue;
2252 cp0[head->write_avail - 1] = '\0';
2253 head->write_avail = 0;
2254 ccs_normalize_line(cp0);
2255 head->write(head);
2256 }
2257 mutex_unlock(&head->io_sem);
2258 return error;
2259 }
2260
2261 /**
2262 * ccs_close_control - close() for /proc/ccs/ interface.
2263 *
2264 * @file: Pointer to "struct file".
2265 *
2266 * Releases memory and returns 0.
2267 */
2268 int ccs_close_control(struct file *file)
2269 {
2270 struct ccs_io_buffer *head = file->private_data;
2271 const bool is_write = head->write_buf != NULL;
2272 const u8 type = head->type;
2273 /*
2274 * If the file is /proc/ccs/query , decrement the observer counter.
2275 */
2276 if (type == CCS_QUERY)
2277 atomic_dec(&ccs_query_observers);
2278 if (type != CCS_QUERY &&
2279 type != CCS_GRANTLOG && type != CCS_REJECTLOG)
2280 ccs_read_unlock(head->reader_idx);
2281 /* Release memory used for policy I/O. */
2282 kfree(head->read_buf);
2283 head->read_buf = NULL;
2284 kfree(head->write_buf);
2285 head->write_buf = NULL;
2286 kfree(head);
2287 head = NULL;
2288 file->private_data = NULL;
2289 if (is_write)
2290 ccs_run_gc();
2291 return 0;
2292 }

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