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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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