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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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