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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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