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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2893 - (show annotations) (download) (as text)
Tue Aug 11 04:11:19 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: 59203 byte(s)


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

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