34 |
const unsigned int max_value; |
const unsigned int max_value; |
35 |
} ccs_control_array[CCS_MAX_CONTROL_INDEX] = { |
} ccs_control_array[CCS_MAX_CONTROL_INDEX] = { |
36 |
[CCS_MAC_FOR_FILE] = { "MAC_FOR_FILE", 0, 3 }, |
[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 }, |
[CCS_MAC_FOR_IOCTL] = { "MAC_FOR_IOCTL", 0, 3 }, |
40 |
[CCS_MAC_FOR_FILEATTR] = { "MAC_FOR_FILEATTR", 0, 3 }, |
[CCS_MAC_FOR_FILEATTR] = { "MAC_FOR_FILEATTR", 0, 3 }, |
|
[CCS_MAC_FOR_ARGV0] = { "MAC_FOR_ARGV0", 0, 3 }, |
|
41 |
[CCS_MAC_FOR_ENV] = { "MAC_FOR_ENV", 0, 3 }, |
[CCS_MAC_FOR_ENV] = { "MAC_FOR_ENV", 0, 3 }, |
42 |
[CCS_MAC_FOR_NETWORK] = { "MAC_FOR_NETWORK", 0, 3 }, |
[CCS_MAC_FOR_NETWORK] = { "MAC_FOR_NETWORK", 0, 3 }, |
43 |
[CCS_MAC_FOR_SIGNAL] = { "MAC_FOR_SIGNAL", 0, 3 }, |
[CCS_MAC_FOR_SIGNAL] = { "MAC_FOR_SIGNAL", 0, 3 }, |
108 |
* |
* |
109 |
* Returns pointer to "struct ccs_profile" on success, NULL otherwise. |
* Returns pointer to "struct ccs_profile" on success, NULL otherwise. |
110 |
*/ |
*/ |
111 |
struct ccs_profile *ccs_find_or_assign_new_profile(const unsigned int |
static struct ccs_profile *ccs_find_or_assign_new_profile(const unsigned int |
112 |
profile) |
profile) |
113 |
{ |
{ |
114 |
struct ccs_profile *ptr; |
struct ccs_profile *ptr; |
115 |
struct ccs_profile *entry; |
struct ccs_profile *entry; |
116 |
int i; |
int i; |
117 |
if (profile >= MAX_PROFILES) |
if (profile >= CCS_MAX_PROFILES) |
118 |
return NULL; |
return NULL; |
119 |
ptr = ccs_profile_ptr[profile]; |
ptr = ccs_profile_ptr[profile]; |
120 |
if (ptr) |
if (ptr) |
181 |
ccs_profile_entry_used[0] = true; |
ccs_profile_entry_used[0] = true; |
182 |
return 0; |
return 0; |
183 |
} |
} |
184 |
if (ccs_str_starts(&data, KEYWORD_MAC_FOR_CAPABILITY)) { |
if (ccs_str_starts(&data, CCS_KEYWORD_MAC_FOR_CAPABILITY)) { |
185 |
if (sscanf(cp + 1, "%u", &value) != 1) { |
if (sscanf(cp + 1, "%u", &value) != 1) { |
186 |
for (i = 0; i < 4; i++) { |
for (i = 0; i < 4; i++) { |
187 |
if (strcmp(cp + 1, ccs_mode_4[i])) |
if (strcmp(cp + 1, ccs_mode_4[i])) |
211 |
int j; |
int j; |
212 |
const char **modes; |
const char **modes; |
213 |
switch (i) { |
switch (i) { |
214 |
|
case CCS_AUTOLEARN_EXEC_REALPATH: |
215 |
|
case CCS_AUTOLEARN_EXEC_ARGV0: |
216 |
case CCS_RESTRICT_AUTOBIND: |
case CCS_RESTRICT_AUTOBIND: |
217 |
case CCS_VERBOSE: |
case CCS_VERBOSE: |
218 |
modes = ccs_mode_2; |
modes = ccs_mode_2; |
253 |
int step; |
int step; |
254 |
if (head->read_eof) |
if (head->read_eof) |
255 |
return 0; |
return 0; |
256 |
for (step = head->read_step; step < MAX_PROFILES * ccs_total; step++) { |
for (step = head->read_step; step < CCS_MAX_PROFILES * ccs_total; |
257 |
|
step++) { |
258 |
const u8 index = step / ccs_total; |
const u8 index = step / ccs_total; |
259 |
u8 type = step % ccs_total; |
u8 type = step % ccs_total; |
260 |
const struct ccs_profile *ccs_profile = ccs_profile_ptr[index]; |
const struct ccs_profile *ccs_profile = ccs_profile_ptr[index]; |
281 |
const int i = type - CCS_MAX_CONTROL_INDEX; |
const int i = type - CCS_MAX_CONTROL_INDEX; |
282 |
const u8 value = ccs_profile->capability_value[i]; |
const u8 value = ccs_profile->capability_value[i]; |
283 |
if (!ccs_io_printf(head, |
if (!ccs_io_printf(head, |
284 |
"%u-" KEYWORD_MAC_FOR_CAPABILITY |
"%u-" CCS_KEYWORD_MAC_FOR_CAPABILITY |
285 |
"%s=%s\n", index, |
"%s=%s\n", index, |
286 |
ccs_capability_control_keyword[i], |
ccs_capability_control_keyword[i], |
287 |
ccs_mode_4[value])) |
ccs_mode_4[value])) |
309 |
} |
} |
310 |
} |
} |
311 |
} |
} |
312 |
if (step == MAX_PROFILES * ccs_total) |
if (step == CCS_MAX_PROFILES * ccs_total) |
313 |
head->read_eof = true; |
head->read_eof = true; |
314 |
return 0; |
return 0; |
315 |
} |
} |
329 |
{ |
{ |
330 |
struct ccs_policy_manager_entry *entry = NULL; |
struct ccs_policy_manager_entry *entry = NULL; |
331 |
struct ccs_policy_manager_entry *ptr; |
struct ccs_policy_manager_entry *ptr; |
332 |
const struct ccs_path_info *saved_manager; |
struct ccs_policy_manager_entry e = { }; |
333 |
int error = is_delete ? -ENOENT : -ENOMEM; |
int error = is_delete ? -ENOENT : -ENOMEM; |
|
bool is_domain = false; |
|
334 |
if (ccs_is_domain_def(manager)) { |
if (ccs_is_domain_def(manager)) { |
335 |
if (!ccs_is_correct_domain(manager)) |
if (!ccs_is_correct_domain(manager)) |
336 |
return -EINVAL; |
return -EINVAL; |
337 |
is_domain = true; |
e.is_domain = true; |
338 |
} else { |
} else { |
339 |
if (!ccs_is_correct_path(manager, 1, -1, -1)) |
if (!ccs_is_correct_path(manager, 1, -1, -1)) |
340 |
return -EINVAL; |
return -EINVAL; |
341 |
} |
} |
342 |
saved_manager = ccs_get_name(manager); |
e.manager = ccs_get_name(manager); |
343 |
if (!saved_manager) |
if (!e.manager) |
344 |
return -ENOMEM; |
return -ENOMEM; |
345 |
if (!is_delete) |
if (!is_delete) |
346 |
entry = kzalloc(sizeof(*entry), GFP_KERNEL); |
entry = kmalloc(sizeof(e), GFP_KERNEL); |
347 |
mutex_lock(&ccs_policy_lock); |
mutex_lock(&ccs_policy_lock); |
348 |
list_for_each_entry_rcu(ptr, &ccs_policy_manager_list, list) { |
list_for_each_entry_rcu(ptr, &ccs_policy_manager_list, list) { |
349 |
if (ptr->manager != saved_manager) |
if (ptr->manager != e.manager) |
350 |
continue; |
continue; |
351 |
ptr->is_deleted = is_delete; |
ptr->is_deleted = is_delete; |
352 |
error = 0; |
error = 0; |
353 |
break; |
break; |
354 |
} |
} |
355 |
if (!is_delete && error && ccs_memory_ok(entry, sizeof(*entry))) { |
if (!is_delete && error && ccs_commit_ok(entry, &e, sizeof(e))) { |
|
entry->manager = saved_manager; |
|
|
saved_manager = NULL; |
|
|
entry->is_domain = is_domain; |
|
356 |
list_add_tail_rcu(&entry->list, &ccs_policy_manager_list); |
list_add_tail_rcu(&entry->list, &ccs_policy_manager_list); |
357 |
entry = NULL; |
entry = NULL; |
358 |
error = 0; |
error = 0; |
359 |
} |
} |
360 |
mutex_unlock(&ccs_policy_lock); |
mutex_unlock(&ccs_policy_lock); |
361 |
ccs_put_name(saved_manager); |
ccs_put_name(e.manager); |
362 |
kfree(entry); |
kfree(entry); |
363 |
return error; |
return error; |
364 |
} |
} |
373 |
static int ccs_write_manager_policy(struct ccs_io_buffer *head) |
static int ccs_write_manager_policy(struct ccs_io_buffer *head) |
374 |
{ |
{ |
375 |
char *data = head->write_buf; |
char *data = head->write_buf; |
376 |
bool is_delete = ccs_str_starts(&data, KEYWORD_DELETE); |
bool is_delete = ccs_str_starts(&data, CCS_KEYWORD_DELETE); |
377 |
if (!strcmp(data, "manage_by_non_root")) { |
if (!strcmp(data, "manage_by_non_root")) { |
378 |
ccs_manage_by_non_root = !is_delete; |
ccs_manage_by_non_root = !is_delete; |
379 |
return 0; |
return 0; |
549 |
return true; |
return true; |
550 |
} |
} |
551 |
|
|
552 |
|
static int ccs_write_domain_policy2(char *data, struct ccs_domain_info *domain, |
553 |
|
struct ccs_condition *cond, |
554 |
|
const bool is_delete) |
555 |
|
{ |
556 |
|
if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_CAPABILITY)) |
557 |
|
return ccs_write_capability_policy(data, domain, cond, |
558 |
|
is_delete); |
559 |
|
if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_NETWORK)) |
560 |
|
return ccs_write_network_policy(data, domain, cond, is_delete); |
561 |
|
if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_SIGNAL)) |
562 |
|
return ccs_write_signal_policy(data, domain, cond, is_delete); |
563 |
|
if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_ENV)) |
564 |
|
return ccs_write_env_policy(data, domain, cond, is_delete); |
565 |
|
if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_MOUNT)) |
566 |
|
return ccs_write_mount_policy(data, domain, cond, is_delete); |
567 |
|
if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_UNMOUNT)) |
568 |
|
return ccs_write_umount_policy(data, domain, cond, is_delete); |
569 |
|
if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_CHROOT)) |
570 |
|
return ccs_write_chroot_policy(data, domain, cond, is_delete); |
571 |
|
if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_PIVOT_ROOT)) |
572 |
|
return ccs_write_pivot_root_policy(data, domain, cond, |
573 |
|
is_delete); |
574 |
|
return ccs_write_file_policy(data, domain, cond, is_delete); |
575 |
|
} |
576 |
|
|
577 |
/** |
/** |
578 |
* ccs_write_domain_policy - Write domain policy. |
* ccs_write_domain_policy - Write domain policy. |
579 |
* |
* |
591 |
struct ccs_condition *cond = NULL; |
struct ccs_condition *cond = NULL; |
592 |
char *cp; |
char *cp; |
593 |
int error; |
int error; |
594 |
if (ccs_str_starts(&data, KEYWORD_DELETE)) |
if (ccs_str_starts(&data, CCS_KEYWORD_DELETE)) |
595 |
is_delete = true; |
is_delete = true; |
596 |
else if (ccs_str_starts(&data, KEYWORD_SELECT)) |
else if (ccs_str_starts(&data, CCS_KEYWORD_SELECT)) |
597 |
is_select = true; |
is_select = true; |
598 |
if (is_select && ccs_is_select_one(head, data)) |
if (is_select && ccs_is_select_one(head, data)) |
599 |
return 0; |
return 0; |
614 |
if (!domain) |
if (!domain) |
615 |
return -EINVAL; |
return -EINVAL; |
616 |
|
|
617 |
if (sscanf(data, KEYWORD_USE_PROFILE "%u", &profile) == 1 |
if (sscanf(data, CCS_KEYWORD_USE_PROFILE "%u", &profile) == 1 |
618 |
&& profile < MAX_PROFILES) { |
&& profile < CCS_MAX_PROFILES) { |
619 |
if (ccs_profile_ptr[profile] || !ccs_policy_loaded) |
if (ccs_profile_ptr[profile] || !ccs_policy_loaded) |
620 |
domain->profile = (u8) profile; |
domain->profile = (u8) profile; |
621 |
return 0; |
return 0; |
622 |
} |
} |
623 |
if (!strcmp(data, KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) { |
if (!strcmp(data, CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) { |
624 |
domain->ignore_global_allow_read = !is_delete; |
domain->ignore_global_allow_read = !is_delete; |
625 |
return 0; |
return 0; |
626 |
} |
} |
627 |
if (!strcmp(data, KEYWORD_IGNORE_GLOBAL_ALLOW_ENV)) { |
if (!strcmp(data, CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_ENV)) { |
628 |
domain->ignore_global_allow_env = !is_delete; |
domain->ignore_global_allow_env = !is_delete; |
629 |
return 0; |
return 0; |
630 |
} |
} |
634 |
if (!cond) |
if (!cond) |
635 |
return -EINVAL; |
return -EINVAL; |
636 |
} |
} |
637 |
if (ccs_str_starts(&data, KEYWORD_ALLOW_CAPABILITY)) |
error = ccs_write_domain_policy2(data, domain, cond, is_delete); |
|
error = ccs_write_capability_policy(data, domain, cond, |
|
|
is_delete); |
|
|
else if (ccs_str_starts(&data, KEYWORD_ALLOW_NETWORK)) |
|
|
error = ccs_write_network_policy(data, domain, cond, is_delete); |
|
|
else if (ccs_str_starts(&data, KEYWORD_ALLOW_SIGNAL)) |
|
|
error = ccs_write_signal_policy(data, domain, cond, is_delete); |
|
|
else if (ccs_str_starts(&data, KEYWORD_ALLOW_ARGV0)) |
|
|
error = ccs_write_argv0_policy(data, domain, cond, is_delete); |
|
|
else if (ccs_str_starts(&data, KEYWORD_ALLOW_ENV)) |
|
|
error = ccs_write_env_policy(data, domain, cond, is_delete); |
|
|
else if (ccs_str_starts(&data, KEYWORD_ALLOW_MOUNT)) |
|
|
error = ccs_write_mount_policy(data, domain, cond, is_delete); |
|
|
else if (ccs_str_starts(&data, KEYWORD_ALLOW_UNMOUNT)) |
|
|
error = ccs_write_umount_policy(data, domain, cond, is_delete); |
|
|
else if (ccs_str_starts(&data, KEYWORD_ALLOW_CHROOT)) |
|
|
error = ccs_write_chroot_policy(data, domain, cond, is_delete); |
|
|
else if (ccs_str_starts(&data, KEYWORD_ALLOW_PIVOT_ROOT)) |
|
|
error = ccs_write_pivot_root_policy(data, domain, cond, |
|
|
is_delete); |
|
|
else |
|
|
error = ccs_write_file_policy(data, domain, cond, is_delete); |
|
638 |
if (cond) |
if (cond) |
639 |
ccs_put_condition(cond); |
ccs_put_condition(cond); |
640 |
return error; |
return error; |
641 |
} |
} |
642 |
|
|
643 |
static bool ccs_print_name_union(struct ccs_io_buffer *head, |
static bool ccs_print_name_union(struct ccs_io_buffer *head, |
644 |
struct ccs_name_union *ptr) |
const struct ccs_name_union *ptr) |
645 |
{ |
{ |
646 |
const int pos = head->read_avail; |
int pos = head->read_avail; |
647 |
if (pos && head->read_buf[pos - 1] == ' ') |
if (pos && head->read_buf[pos - 1] == ' ') |
648 |
head->read_avail--; |
head->read_avail--; |
649 |
if (ptr->is_group) |
if (ptr->is_group) |
652 |
return ccs_io_printf(head, " %s", ptr->filename->name); |
return ccs_io_printf(head, " %s", ptr->filename->name); |
653 |
} |
} |
654 |
|
|
655 |
static bool ccs_print_number_union(struct ccs_io_buffer *head, |
static bool ccs_print_name_union_quoted(struct ccs_io_buffer *head, |
656 |
struct ccs_number_union *ptr) |
const struct ccs_name_union *ptr) |
657 |
|
{ |
658 |
|
if (ptr->is_group) |
659 |
|
return ccs_io_printf(head, "@%s", |
660 |
|
ptr->group->group_name->name); |
661 |
|
return ccs_io_printf(head, "\"%s\"", ptr->filename->name); |
662 |
|
} |
663 |
|
|
664 |
|
static bool ccs_print_number_union_common(struct ccs_io_buffer *head, |
665 |
|
const struct ccs_number_union *ptr, |
666 |
|
const bool need_space) |
667 |
{ |
{ |
668 |
unsigned long min; |
unsigned long min; |
669 |
unsigned long max; |
unsigned long max; |
670 |
u8 min_type; |
u8 min_type; |
671 |
u8 max_type; |
u8 max_type; |
672 |
|
if (need_space && !ccs_io_printf(head, " ")) |
673 |
|
return false; |
674 |
if (ptr->is_group) |
if (ptr->is_group) |
675 |
return ccs_io_printf(head, " @%s", |
return ccs_io_printf(head, "@%s", |
676 |
ptr->group->group_name->name); |
ptr->group->group_name->name); |
677 |
min_type = ptr->min_type; |
min_type = ptr->min_type; |
678 |
max_type = ptr->max_type; |
max_type = ptr->max_type; |
679 |
min = ptr->values[0]; |
min = ptr->values[0]; |
680 |
max = ptr->values[1]; |
max = ptr->values[1]; |
681 |
switch (min_type) { |
switch (min_type) { |
682 |
case VALUE_TYPE_HEXADECIMAL: |
case CCS_VALUE_TYPE_HEXADECIMAL: |
683 |
if (!ccs_io_printf(head, " 0x%lX", min)) |
if (!ccs_io_printf(head, "0x%lX", min)) |
684 |
return false; |
return false; |
685 |
break; |
break; |
686 |
case VALUE_TYPE_OCTAL: |
case CCS_VALUE_TYPE_OCTAL: |
687 |
if (!ccs_io_printf(head, " 0%lo", min)) |
if (!ccs_io_printf(head, "0%lo", min)) |
688 |
return false; |
return false; |
689 |
break; |
break; |
690 |
default: |
default: |
691 |
if (!ccs_io_printf(head, " %lu", min)) |
if (!ccs_io_printf(head, "%lu", min)) |
692 |
return false; |
return false; |
693 |
break; |
break; |
694 |
} |
} |
695 |
if (min == max && min_type == max_type) |
if (min == max && min_type == max_type) |
696 |
return true; |
return true; |
697 |
switch (max_type) { |
switch (max_type) { |
698 |
case VALUE_TYPE_HEXADECIMAL: |
case CCS_VALUE_TYPE_HEXADECIMAL: |
699 |
return ccs_io_printf(head, "-0x%lX", max); |
return ccs_io_printf(head, "-0x%lX", max); |
700 |
case VALUE_TYPE_OCTAL: |
case CCS_VALUE_TYPE_OCTAL: |
701 |
return ccs_io_printf(head, "-0%lo", max); |
return ccs_io_printf(head, "-0%lo", max); |
702 |
default: |
default: |
703 |
return ccs_io_printf(head, "-%lu", max); |
return ccs_io_printf(head, "-%lu", max); |
704 |
} |
} |
705 |
} |
} |
706 |
|
|
707 |
|
bool ccs_print_number_union(struct ccs_io_buffer *head, |
708 |
|
const struct ccs_number_union *ptr) |
709 |
|
{ |
710 |
|
return ccs_print_number_union_common(head, ptr, true); |
711 |
|
} |
712 |
|
|
713 |
|
static bool ccs_print_number_union_nospace(struct ccs_io_buffer *head, |
714 |
|
const struct ccs_number_union *ptr) |
715 |
|
{ |
716 |
|
return ccs_print_number_union_common(head, ptr, false); |
717 |
|
} |
718 |
|
|
719 |
|
/** |
720 |
|
* ccs_print_condition - Print condition part. |
721 |
|
* |
722 |
|
* @head: Pointer to "struct ccs_io_buffer". |
723 |
|
* @cond: Pointer to "struct ccs_condition". May be NULL. |
724 |
|
* |
725 |
|
* Returns true on success, false otherwise. |
726 |
|
*/ |
727 |
|
static bool ccs_print_condition(struct ccs_io_buffer *head, |
728 |
|
const struct ccs_condition *cond) |
729 |
|
{ |
730 |
|
const struct ccs_condition_element *condp; |
731 |
|
const struct ccs_number_union *numbers_p; |
732 |
|
const struct ccs_name_union *names_p; |
733 |
|
const struct ccs_argv_entry *argv; |
734 |
|
const struct ccs_envp_entry *envp; |
735 |
|
u16 condc; |
736 |
|
u16 i; |
737 |
|
u16 j; |
738 |
|
char buffer[32]; |
739 |
|
if (!cond) |
740 |
|
goto no_condition; |
741 |
|
condc = cond->condc; |
742 |
|
condp = (const struct ccs_condition_element *) (cond + 1); |
743 |
|
numbers_p = (const struct ccs_number_union *) (condp + condc); |
744 |
|
names_p = (const struct ccs_name_union *) |
745 |
|
(numbers_p + cond->numbers_count); |
746 |
|
argv = (const struct ccs_argv_entry *) (names_p + cond->names_count); |
747 |
|
envp = (const struct ccs_envp_entry *) (argv + cond->argc); |
748 |
|
memset(buffer, 0, sizeof(buffer)); |
749 |
|
if (condc && !ccs_io_printf(head, "%s", " if")) |
750 |
|
goto out; |
751 |
|
for (i = 0; i < condc; i++) { |
752 |
|
const u8 match = condp->equals; |
753 |
|
const u8 left = condp->left; |
754 |
|
const u8 right = condp->right; |
755 |
|
condp++; |
756 |
|
switch (left) { |
757 |
|
case CCS_ARGV_ENTRY: |
758 |
|
if (!ccs_io_printf(head, " exec.argv[%u]%s\"%s\"", |
759 |
|
argv->index, argv->is_not ? |
760 |
|
"!=" : "=", argv->value->name)) |
761 |
|
goto out; |
762 |
|
argv++; |
763 |
|
continue; |
764 |
|
case CCS_ENVP_ENTRY: |
765 |
|
if (!ccs_io_printf(head, " exec.envp[\"%s\"]%s", |
766 |
|
envp->name->name, envp->is_not ? |
767 |
|
"!=" : "=")) |
768 |
|
goto out; |
769 |
|
if (envp->value) { |
770 |
|
if (!ccs_io_printf(head, "\"%s\"", |
771 |
|
envp->value->name)) |
772 |
|
goto out; |
773 |
|
} else { |
774 |
|
if (!ccs_io_printf(head, "NULL")) |
775 |
|
goto out; |
776 |
|
} |
777 |
|
envp++; |
778 |
|
continue; |
779 |
|
case CCS_NUMBER_UNION: |
780 |
|
if (!ccs_print_number_union(head, numbers_p++)) |
781 |
|
goto out; |
782 |
|
break; |
783 |
|
default: |
784 |
|
if (left >= CCS_MAX_CONDITION_KEYWORD) |
785 |
|
goto out; |
786 |
|
if (!ccs_io_printf(head, " %s", |
787 |
|
ccs_condition_keyword[left])) |
788 |
|
goto out; |
789 |
|
break; |
790 |
|
} |
791 |
|
if (!ccs_io_printf(head, "%s", match ? "=" : "!=")) |
792 |
|
goto out; |
793 |
|
switch (right) { |
794 |
|
case CCS_NAME_UNION: |
795 |
|
if (!ccs_print_name_union_quoted(head, names_p++)) |
796 |
|
goto out; |
797 |
|
break; |
798 |
|
case CCS_NUMBER_UNION: |
799 |
|
if (!ccs_print_number_union_nospace(head, numbers_p++)) |
800 |
|
goto out; |
801 |
|
break; |
802 |
|
default: |
803 |
|
if (right >= CCS_MAX_CONDITION_KEYWORD) |
804 |
|
goto out; |
805 |
|
if (!ccs_io_printf(head, "%s", |
806 |
|
ccs_condition_keyword[right])) |
807 |
|
goto out; |
808 |
|
break; |
809 |
|
} |
810 |
|
} |
811 |
|
i = cond->post_state[3]; |
812 |
|
if (!i) |
813 |
|
goto no_condition; |
814 |
|
if (!ccs_io_printf(head, " ; set")) |
815 |
|
goto out; |
816 |
|
for (j = 0; j < 3; j++) { |
817 |
|
if (!(i & (1 << j))) |
818 |
|
continue; |
819 |
|
if (!ccs_io_printf(head, " task.state[%u]=%u", j, |
820 |
|
cond->post_state[j])) |
821 |
|
goto out; |
822 |
|
} |
823 |
|
no_condition: |
824 |
|
if (ccs_io_printf(head, "\n")) |
825 |
|
return true; |
826 |
|
out: |
827 |
|
return false; |
828 |
|
} |
829 |
|
|
830 |
/** |
/** |
831 |
* ccs_print_single_path_acl - Print a single path ACL entry. |
* ccs_print_single_path_acl - Print a single path ACL entry. |
832 |
* |
* |
843 |
int pos; |
int pos; |
844 |
u8 bit; |
u8 bit; |
845 |
const u16 perm = ptr->perm; |
const u16 perm = ptr->perm; |
846 |
for (bit = head->read_bit; bit < MAX_SINGLE_PATH_OPERATION; bit++) { |
for (bit = head->read_bit; bit < CCS_MAX_SINGLE_PATH_OPERATION; bit++) { |
847 |
const char *msg; |
const char *msg; |
848 |
if (!(perm & (1 << bit))) |
if (!(perm & (1 << bit))) |
849 |
continue; |
continue; |
850 |
if (head->read_execute_only && bit != TYPE_EXECUTE_ACL) |
if (head->read_execute_only && bit != CCS_TYPE_EXECUTE_ACL) |
851 |
continue; |
continue; |
852 |
/* Print "read/write" instead of "read" and "write". */ |
/* Print "read/write" instead of "read" and "write". */ |
853 |
if ((bit == TYPE_READ_ACL || bit == TYPE_WRITE_ACL) |
if ((bit == CCS_TYPE_READ_ACL || bit == CCS_TYPE_WRITE_ACL) |
854 |
&& (perm & (1 << TYPE_READ_WRITE_ACL))) |
&& (perm & (1 << CCS_TYPE_READ_WRITE_ACL))) |
855 |
continue; |
continue; |
856 |
msg = ccs_sp2keyword(bit); |
msg = ccs_sp2keyword(bit); |
857 |
pos = head->read_avail; |
pos = head->read_avail; |
858 |
if (!ccs_io_printf(head, "allow_%s", msg) || |
if (!ccs_io_printf(head, "allow_%s", msg) || |
859 |
!ccs_print_name_union(head, &ptr->name) || |
!ccs_print_name_union(head, &ptr->name) || |
860 |
!ccs_print_condition(head, cond)) |
!ccs_print_condition(head, cond)) { |
861 |
goto out; |
head->read_bit = bit; |
862 |
|
head->read_avail = pos; |
863 |
|
return false; |
864 |
|
} |
865 |
} |
} |
866 |
head->read_bit = 0; |
head->read_bit = 0; |
867 |
return true; |
return true; |
|
out: |
|
|
head->read_bit = bit; |
|
|
head->read_avail = pos; |
|
|
return false; |
|
868 |
} |
} |
869 |
|
|
870 |
/** |
/** |
883 |
int pos; |
int pos; |
884 |
u8 bit; |
u8 bit; |
885 |
const u16 perm = ptr->perm; |
const u16 perm = ptr->perm; |
886 |
for (bit = head->read_bit; bit < MAX_MKDEV_OPERATION; bit++) { |
for (bit = head->read_bit; bit < CCS_MAX_MKDEV_OPERATION; bit++) { |
887 |
const char *msg; |
const char *msg; |
888 |
if (!(perm & (1 << bit))) |
if (!(perm & (1 << bit))) |
889 |
continue; |
continue; |
893 |
!ccs_print_name_union(head, &ptr->name) || |
!ccs_print_name_union(head, &ptr->name) || |
894 |
!ccs_print_number_union(head, &ptr->major) || |
!ccs_print_number_union(head, &ptr->major) || |
895 |
!ccs_print_number_union(head, &ptr->minor) || |
!ccs_print_number_union(head, &ptr->minor) || |
896 |
!ccs_print_condition(head, cond)) |
!ccs_print_condition(head, cond)) { |
897 |
goto out; |
head->read_bit = bit; |
898 |
|
head->read_avail = pos; |
899 |
|
return false; |
900 |
|
} |
901 |
} |
} |
902 |
head->read_bit = 0; |
head->read_bit = 0; |
903 |
return true; |
return true; |
|
out: |
|
|
head->read_bit = bit; |
|
|
head->read_avail = pos; |
|
|
return false; |
|
904 |
} |
} |
905 |
|
|
906 |
/** |
/** |
919 |
int pos; |
int pos; |
920 |
u8 bit; |
u8 bit; |
921 |
const u8 perm = ptr->perm; |
const u8 perm = ptr->perm; |
922 |
for (bit = head->read_bit; bit < MAX_DOUBLE_PATH_OPERATION; bit++) { |
for (bit = head->read_bit; bit < CCS_MAX_DOUBLE_PATH_OPERATION; bit++) { |
923 |
const char *msg; |
const char *msg; |
924 |
if (!(perm & (1 << bit))) |
if (!(perm & (1 << bit))) |
925 |
continue; |
continue; |
928 |
if (!ccs_io_printf(head, "allow_%s", msg) || |
if (!ccs_io_printf(head, "allow_%s", msg) || |
929 |
!ccs_print_name_union(head, &ptr->name1) || |
!ccs_print_name_union(head, &ptr->name1) || |
930 |
!ccs_print_name_union(head, &ptr->name2) || |
!ccs_print_name_union(head, &ptr->name2) || |
931 |
!ccs_print_condition(head, cond)) |
!ccs_print_condition(head, cond)) { |
932 |
goto out; |
head->read_bit = bit; |
933 |
|
head->read_avail = pos; |
934 |
|
return false; |
935 |
|
} |
936 |
} |
} |
937 |
head->read_bit = 0; |
head->read_bit = 0; |
938 |
return true; |
return true; |
|
out: |
|
|
head->read_bit = bit; |
|
|
head->read_avail = pos; |
|
|
return false; |
|
939 |
} |
} |
940 |
|
|
941 |
/** |
/** |
954 |
int pos; |
int pos; |
955 |
u8 bit; |
u8 bit; |
956 |
const u8 perm = ptr->perm; |
const u8 perm = ptr->perm; |
957 |
for (bit = head->read_bit; bit < MAX_PATH_NUMBER_OPERATION; bit++) { |
for (bit = head->read_bit; bit < CCS_MAX_PATH_NUMBER_OPERATION; bit++) { |
958 |
const char *msg; |
const char *msg; |
959 |
if (!(perm & (1 << bit))) |
if (!(perm & (1 << bit))) |
960 |
continue; |
continue; |
963 |
if (!ccs_io_printf(head, "allow_%s", msg) || |
if (!ccs_io_printf(head, "allow_%s", msg) || |
964 |
!ccs_print_name_union(head, &ptr->name) || |
!ccs_print_name_union(head, &ptr->name) || |
965 |
!ccs_print_number_union(head, &ptr->number) || |
!ccs_print_number_union(head, &ptr->number) || |
966 |
!ccs_print_condition(head, cond)) |
!ccs_print_condition(head, cond)) { |
967 |
goto out; |
head->read_bit = bit; |
968 |
|
head->read_avail = pos; |
969 |
|
return false; |
970 |
|
} |
971 |
} |
} |
972 |
head->read_bit = 0; |
head->read_bit = 0; |
973 |
return true; |
return true; |
|
out: |
|
|
head->read_bit = bit; |
|
|
head->read_avail = pos; |
|
|
return false; |
|
|
} |
|
|
|
|
|
/** |
|
|
* ccs_print_argv0_acl - Print an argv[0] ACL entry. |
|
|
* |
|
|
* @head: Pointer to "struct ccs_io_buffer". |
|
|
* @ptr: Pointer to "struct ccs_argv0_acl_record". |
|
|
* @cond: Pointer to "struct ccs_condition". May be NULL. |
|
|
* |
|
|
* Returns true on success, false otherwise. |
|
|
*/ |
|
|
static bool ccs_print_argv0_acl(struct ccs_io_buffer *head, |
|
|
struct ccs_argv0_acl_record *ptr, |
|
|
const struct ccs_condition *cond) |
|
|
{ |
|
|
int pos = head->read_avail; |
|
|
if (!ccs_io_printf(head, KEYWORD_ALLOW_ARGV0 "%s %s", |
|
|
ptr->filename->name, ptr->argv0->name)) |
|
|
goto out; |
|
|
if (!ccs_print_condition(head, cond)) |
|
|
goto out; |
|
|
return true; |
|
|
out: |
|
|
head->read_avail = pos; |
|
|
return false; |
|
974 |
} |
} |
975 |
|
|
976 |
/** |
/** |
986 |
struct ccs_env_acl_record *ptr, |
struct ccs_env_acl_record *ptr, |
987 |
const struct ccs_condition *cond) |
const struct ccs_condition *cond) |
988 |
{ |
{ |
989 |
int pos = head->read_avail; |
const int pos = head->read_avail; |
990 |
if (!ccs_io_printf(head, KEYWORD_ALLOW_ENV "%s", ptr->env->name)) |
if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_ENV "%s", ptr->env->name) || |
991 |
goto out; |
!ccs_print_condition(head, cond)) { |
992 |
if (!ccs_print_condition(head, cond)) |
head->read_avail = pos; |
993 |
goto out; |
return false; |
994 |
|
} |
995 |
return true; |
return true; |
|
out: |
|
|
head->read_avail = pos; |
|
|
return false; |
|
996 |
} |
} |
997 |
|
|
998 |
/** |
/** |
1008 |
struct ccs_capability_acl_record *ptr, |
struct ccs_capability_acl_record *ptr, |
1009 |
const struct ccs_condition *cond) |
const struct ccs_condition *cond) |
1010 |
{ |
{ |
1011 |
int pos = head->read_avail; |
const int pos = head->read_avail; |
1012 |
if (!ccs_io_printf(head, KEYWORD_ALLOW_CAPABILITY "%s", |
if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_CAPABILITY "%s", |
1013 |
ccs_cap2keyword(ptr->operation))) |
ccs_cap2keyword(ptr->operation)) || |
1014 |
goto out; |
!ccs_print_condition(head, cond)) { |
1015 |
if (!ccs_print_condition(head, cond)) |
head->read_avail = pos; |
1016 |
goto out; |
return false; |
1017 |
|
} |
1018 |
return true; |
return true; |
|
out: |
|
|
head->read_avail = pos; |
|
|
return false; |
|
1019 |
} |
} |
1020 |
|
|
1021 |
/** |
/** |
1077 |
struct ccs_ip_network_acl_record *ptr, |
struct ccs_ip_network_acl_record *ptr, |
1078 |
const struct ccs_condition *cond) |
const struct ccs_condition *cond) |
1079 |
{ |
{ |
1080 |
int pos = head->read_avail; |
const int pos = head->read_avail; |
1081 |
if (!ccs_io_printf(head, KEYWORD_ALLOW_NETWORK "%s ", |
if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_NETWORK "%s ", |
1082 |
ccs_net2keyword(ptr->operation_type))) |
ccs_net2keyword(ptr->operation_type))) |
1083 |
goto out; |
goto out; |
1084 |
switch (ptr->record_type) { |
switch (ptr->record_type) { |
1085 |
case IP_RECORD_TYPE_ADDRESS_GROUP: |
case CCS_IP_RECORD_TYPE_ADDRESS_GROUP: |
1086 |
if (!ccs_io_printf(head, "@%s", |
if (!ccs_io_printf(head, "@%s", |
1087 |
ptr->address.group->group_name->name)) |
ptr->address.group->group_name->name)) |
1088 |
goto out; |
goto out; |
1089 |
break; |
break; |
1090 |
case IP_RECORD_TYPE_IPv4: |
case CCS_IP_RECORD_TYPE_IPv4: |
1091 |
if (!ccs_print_ipv4_entry(head, ptr)) |
if (!ccs_print_ipv4_entry(head, ptr)) |
1092 |
goto out; |
goto out; |
1093 |
break; |
break; |
1094 |
case IP_RECORD_TYPE_IPv6: |
case CCS_IP_RECORD_TYPE_IPv6: |
1095 |
if (!ccs_print_ipv6_entry(head, ptr)) |
if (!ccs_print_ipv6_entry(head, ptr)) |
1096 |
goto out; |
goto out; |
1097 |
break; |
break; |
1118 |
struct ccs_signal_acl_record *ptr, |
struct ccs_signal_acl_record *ptr, |
1119 |
const struct ccs_condition *cond) |
const struct ccs_condition *cond) |
1120 |
{ |
{ |
1121 |
int pos = head->read_avail; |
const int pos = head->read_avail; |
1122 |
if (!ccs_io_printf(head, KEYWORD_ALLOW_SIGNAL "%u %s", |
if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_SIGNAL "%u %s", |
1123 |
ptr->sig, ptr->domainname->name)) |
ptr->sig, ptr->domainname->name) || |
1124 |
goto out; |
!ccs_print_condition(head, cond)) { |
1125 |
if (!ccs_print_condition(head, cond)) |
head->read_avail = pos; |
1126 |
goto out; |
return false; |
1127 |
|
} |
1128 |
return true; |
return true; |
|
out: |
|
|
head->read_avail = pos; |
|
|
return false; |
|
1129 |
} |
} |
1130 |
|
|
1131 |
/** |
/** |
1158 |
struct ccs_mount_acl_record *ptr, |
struct ccs_mount_acl_record *ptr, |
1159 |
const struct ccs_condition *cond) |
const struct ccs_condition *cond) |
1160 |
{ |
{ |
1161 |
int pos = head->read_avail; |
const int pos = head->read_avail; |
1162 |
if (!ccs_io_printf(head, KEYWORD_ALLOW_MOUNT "%s %s %s 0x%lX\n", |
if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_MOUNT) || |
1163 |
ptr->dev_name->name, ptr->dir_name->name, |
!ccs_print_name_union(head, &ptr->dev_name) || |
1164 |
ptr->fs_type->name, ptr->flags)) |
!ccs_print_name_union(head, &ptr->dir_name) || |
1165 |
goto out; |
!ccs_print_name_union(head, &ptr->fs_type) || |
1166 |
if (!ccs_print_condition(head, cond)) |
!ccs_print_number_union(head, &ptr->flags) || |
1167 |
goto out; |
!ccs_print_condition(head, cond)) { |
1168 |
|
head->read_avail = pos; |
1169 |
|
return false; |
1170 |
|
} |
1171 |
return true; |
return true; |
|
out: |
|
|
head->read_avail = pos; |
|
|
return false; |
|
1172 |
} |
} |
1173 |
|
|
1174 |
/** |
/** |
1184 |
struct ccs_umount_acl_record *ptr, |
struct ccs_umount_acl_record *ptr, |
1185 |
const struct ccs_condition *cond) |
const struct ccs_condition *cond) |
1186 |
{ |
{ |
1187 |
int pos = head->read_avail; |
const int pos = head->read_avail; |
1188 |
if (!ccs_io_printf(head, KEYWORD_ALLOW_UNMOUNT "%s\n", |
if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_UNMOUNT) || |
1189 |
ptr->dir->name)) |
!ccs_print_name_union(head, &ptr->dir) || |
1190 |
goto out; |
!ccs_print_condition(head, cond)) { |
1191 |
if (!ccs_print_condition(head, cond)) |
head->read_avail = pos; |
1192 |
goto out; |
return false; |
1193 |
|
} |
1194 |
return true; |
return true; |
|
out: |
|
|
head->read_avail = pos; |
|
|
return false; |
|
1195 |
} |
} |
1196 |
|
|
1197 |
/** |
/** |
1207 |
struct ccs_chroot_acl_record *ptr, |
struct ccs_chroot_acl_record *ptr, |
1208 |
const struct ccs_condition *cond) |
const struct ccs_condition *cond) |
1209 |
{ |
{ |
1210 |
int pos = head->read_avail; |
const int pos = head->read_avail; |
1211 |
if (!ccs_io_printf(head, KEYWORD_ALLOW_CHROOT "%s\n", |
if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_CHROOT) || |
1212 |
ptr->dir->name)) |
!ccs_print_name_union(head, &ptr->dir) || |
1213 |
goto out; |
!ccs_print_condition(head, cond)) { |
1214 |
if (!ccs_print_condition(head, cond)) |
head->read_avail = pos; |
1215 |
goto out; |
return false; |
1216 |
|
} |
1217 |
return true; |
return true; |
|
out: |
|
|
head->read_avail = pos; |
|
|
return false; |
|
1218 |
} |
} |
1219 |
|
|
1220 |
/** |
/** |
1230 |
struct ccs_pivot_root_acl_record *ptr, |
struct ccs_pivot_root_acl_record *ptr, |
1231 |
const struct ccs_condition *cond) |
const struct ccs_condition *cond) |
1232 |
{ |
{ |
1233 |
int pos = head->read_avail; |
const int pos = head->read_avail; |
1234 |
if (!ccs_io_printf(head, KEYWORD_ALLOW_PIVOT_ROOT "%s %s\n", |
if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_PIVOT_ROOT) || |
1235 |
ptr->new_root->name, ptr->old_root->name)) |
!ccs_print_name_union(head, &ptr->new_root) || |
1236 |
goto out; |
!ccs_print_name_union(head, &ptr->old_root) || |
1237 |
if (!ccs_print_condition(head, cond)) |
!ccs_print_condition(head, cond)) { |
1238 |
goto out; |
head->read_avail = pos; |
1239 |
|
return false; |
1240 |
|
} |
1241 |
return true; |
return true; |
|
out: |
|
|
head->read_avail = pos; |
|
|
return false; |
|
1242 |
} |
} |
1243 |
|
|
1244 |
/** |
/** |
1253 |
struct ccs_acl_info *ptr) |
struct ccs_acl_info *ptr) |
1254 |
{ |
{ |
1255 |
const struct ccs_condition *cond = ptr->cond; |
const struct ccs_condition *cond = ptr->cond; |
1256 |
const u8 acl_type = ccs_acl_type2(ptr); |
const u8 acl_type = ptr->type; |
1257 |
if (acl_type & ACL_DELETED) |
if (ptr->is_deleted) |
1258 |
return true; |
return true; |
1259 |
if (acl_type == TYPE_SINGLE_PATH_ACL) { |
if (acl_type == CCS_TYPE_SINGLE_PATH_ACL) { |
1260 |
struct ccs_single_path_acl_record *acl |
struct ccs_single_path_acl_record *acl |
1261 |
= container_of(ptr, struct ccs_single_path_acl_record, |
= container_of(ptr, struct ccs_single_path_acl_record, |
1262 |
head); |
head); |
1263 |
return ccs_print_single_path_acl(head, acl, cond); |
return ccs_print_single_path_acl(head, acl, cond); |
1264 |
} |
} |
1265 |
if (acl_type == TYPE_EXECUTE_HANDLER) { |
if (acl_type == CCS_TYPE_EXECUTE_HANDLER) { |
1266 |
struct ccs_execute_handler_record *acl |
struct ccs_execute_handler_record *acl |
1267 |
= container_of(ptr, struct ccs_execute_handler_record, |
= container_of(ptr, struct ccs_execute_handler_record, |
1268 |
head); |
head); |
1269 |
const char *keyword = KEYWORD_EXECUTE_HANDLER; |
const char *keyword = CCS_KEYWORD_EXECUTE_HANDLER; |
1270 |
return ccs_print_execute_handler_record(head, keyword, acl); |
return ccs_print_execute_handler_record(head, keyword, acl); |
1271 |
} |
} |
1272 |
if (acl_type == TYPE_DENIED_EXECUTE_HANDLER) { |
if (acl_type == CCS_TYPE_DENIED_EXECUTE_HANDLER) { |
1273 |
struct ccs_execute_handler_record *acl |
struct ccs_execute_handler_record *acl |
1274 |
= container_of(ptr, struct ccs_execute_handler_record, |
= container_of(ptr, struct ccs_execute_handler_record, |
1275 |
head); |
head); |
1276 |
const char *keyword = KEYWORD_DENIED_EXECUTE_HANDLER; |
const char *keyword = CCS_KEYWORD_DENIED_EXECUTE_HANDLER; |
1277 |
return ccs_print_execute_handler_record(head, keyword, acl); |
return ccs_print_execute_handler_record(head, keyword, acl); |
1278 |
} |
} |
1279 |
if (head->read_execute_only) |
if (head->read_execute_only) |
1280 |
return true; |
return true; |
1281 |
if (acl_type == TYPE_MKDEV_ACL) { |
if (acl_type == CCS_TYPE_MKDEV_ACL) { |
1282 |
struct ccs_mkdev_acl_record *acl |
struct ccs_mkdev_acl_record *acl |
1283 |
= container_of(ptr, struct ccs_mkdev_acl_record, head); |
= container_of(ptr, struct ccs_mkdev_acl_record, head); |
1284 |
return ccs_print_mkdev_acl(head, acl, cond); |
return ccs_print_mkdev_acl(head, acl, cond); |
1285 |
} |
} |
1286 |
if (acl_type == TYPE_DOUBLE_PATH_ACL) { |
if (acl_type == CCS_TYPE_DOUBLE_PATH_ACL) { |
1287 |
struct ccs_double_path_acl_record *acl |
struct ccs_double_path_acl_record *acl |
1288 |
= container_of(ptr, struct ccs_double_path_acl_record, |
= container_of(ptr, struct ccs_double_path_acl_record, |
1289 |
head); |
head); |
1290 |
return ccs_print_double_path_acl(head, acl, cond); |
return ccs_print_double_path_acl(head, acl, cond); |
1291 |
} |
} |
1292 |
if (acl_type == TYPE_PATH_NUMBER_ACL) { |
if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) { |
1293 |
struct ccs_path_number_acl_record *acl |
struct ccs_path_number_acl_record *acl |
1294 |
= container_of(ptr, struct ccs_path_number_acl_record, |
= container_of(ptr, struct ccs_path_number_acl_record, |
1295 |
head); |
head); |
1296 |
return ccs_print_path_number_acl(head, acl, cond); |
return ccs_print_path_number_acl(head, acl, cond); |
1297 |
} |
} |
1298 |
if (acl_type == TYPE_ARGV0_ACL) { |
if (acl_type == CCS_TYPE_ENV_ACL) { |
|
struct ccs_argv0_acl_record *acl |
|
|
= container_of(ptr, struct ccs_argv0_acl_record, head); |
|
|
return ccs_print_argv0_acl(head, acl, cond); |
|
|
} |
|
|
if (acl_type == TYPE_ENV_ACL) { |
|
1299 |
struct ccs_env_acl_record *acl |
struct ccs_env_acl_record *acl |
1300 |
= container_of(ptr, struct ccs_env_acl_record, head); |
= container_of(ptr, struct ccs_env_acl_record, head); |
1301 |
return ccs_print_env_acl(head, acl, cond); |
return ccs_print_env_acl(head, acl, cond); |
1302 |
} |
} |
1303 |
if (acl_type == TYPE_CAPABILITY_ACL) { |
if (acl_type == CCS_TYPE_CAPABILITY_ACL) { |
1304 |
struct ccs_capability_acl_record *acl |
struct ccs_capability_acl_record *acl |
1305 |
= container_of(ptr, struct ccs_capability_acl_record, |
= container_of(ptr, struct ccs_capability_acl_record, |
1306 |
head); |
head); |
1307 |
return ccs_print_capability_acl(head, acl, cond); |
return ccs_print_capability_acl(head, acl, cond); |
1308 |
} |
} |
1309 |
if (acl_type == TYPE_IP_NETWORK_ACL) { |
if (acl_type == CCS_TYPE_IP_NETWORK_ACL) { |
1310 |
struct ccs_ip_network_acl_record *acl |
struct ccs_ip_network_acl_record *acl |
1311 |
= container_of(ptr, struct ccs_ip_network_acl_record, |
= container_of(ptr, struct ccs_ip_network_acl_record, |
1312 |
head); |
head); |
1313 |
return ccs_print_network_acl(head, acl, cond); |
return ccs_print_network_acl(head, acl, cond); |
1314 |
} |
} |
1315 |
if (acl_type == TYPE_SIGNAL_ACL) { |
if (acl_type == CCS_TYPE_SIGNAL_ACL) { |
1316 |
struct ccs_signal_acl_record *acl |
struct ccs_signal_acl_record *acl |
1317 |
= container_of(ptr, struct ccs_signal_acl_record, head); |
= container_of(ptr, struct ccs_signal_acl_record, head); |
1318 |
return ccs_print_signal_acl(head, acl, cond); |
return ccs_print_signal_acl(head, acl, cond); |
1319 |
} |
} |
1320 |
if (acl_type == TYPE_MOUNT_ACL) { |
if (acl_type == CCS_TYPE_MOUNT_ACL) { |
1321 |
struct ccs_mount_acl_record *acl |
struct ccs_mount_acl_record *acl |
1322 |
= container_of(ptr, struct ccs_mount_acl_record, head); |
= container_of(ptr, struct ccs_mount_acl_record, head); |
1323 |
return ccs_print_mount_acl(head, acl, cond); |
return ccs_print_mount_acl(head, acl, cond); |
1324 |
} |
} |
1325 |
if (acl_type == TYPE_UMOUNT_ACL) { |
if (acl_type == CCS_TYPE_UMOUNT_ACL) { |
1326 |
struct ccs_umount_acl_record *acl |
struct ccs_umount_acl_record *acl |
1327 |
= container_of(ptr, struct ccs_umount_acl_record, head); |
= container_of(ptr, struct ccs_umount_acl_record, head); |
1328 |
return ccs_print_umount_acl(head, acl, cond); |
return ccs_print_umount_acl(head, acl, cond); |
1329 |
} |
} |
1330 |
if (acl_type == TYPE_CHROOT_ACL) { |
if (acl_type == CCS_TYPE_CHROOT_ACL) { |
1331 |
struct ccs_chroot_acl_record *acl |
struct ccs_chroot_acl_record *acl |
1332 |
= container_of(ptr, struct ccs_chroot_acl_record, head); |
= container_of(ptr, struct ccs_chroot_acl_record, head); |
1333 |
return ccs_print_chroot_acl(head, acl, cond); |
return ccs_print_chroot_acl(head, acl, cond); |
1334 |
} |
} |
1335 |
if (acl_type == TYPE_PIVOT_ROOT_ACL) { |
if (acl_type == CCS_TYPE_PIVOT_ROOT_ACL) { |
1336 |
struct ccs_pivot_root_acl_record *acl |
struct ccs_pivot_root_acl_record *acl |
1337 |
= container_of(ptr, struct ccs_pivot_root_acl_record, |
= container_of(ptr, struct ccs_pivot_root_acl_record, |
1338 |
head); |
head); |
1339 |
return ccs_print_pivot_root_acl(head, acl, cond); |
return ccs_print_pivot_root_acl(head, acl, cond); |
1340 |
} |
} |
|
/* Workaround for gcc 3.2.2's inline bug. */ |
|
|
if (acl_type & ACL_DELETED) |
|
|
return true; |
|
1341 |
BUG(); /* This must not happen. */ |
BUG(); /* This must not happen. */ |
1342 |
return false; |
return false; |
1343 |
} |
} |
1378 |
transition_failed = "transition_failed\n"; |
transition_failed = "transition_failed\n"; |
1379 |
if (domain->ignore_global_allow_read) |
if (domain->ignore_global_allow_read) |
1380 |
ignore_global_allow_read |
ignore_global_allow_read |
1381 |
= KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n"; |
= CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n"; |
1382 |
if (domain->ignore_global_allow_env) |
if (domain->ignore_global_allow_env) |
1383 |
ignore_global_allow_env |
ignore_global_allow_env |
1384 |
= KEYWORD_IGNORE_GLOBAL_ALLOW_ENV "\n"; |
= CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_ENV "\n"; |
1385 |
if (!ccs_io_printf(head, "%s\n" KEYWORD_USE_PROFILE "%u\n" |
if (!ccs_io_printf(head, "%s\n" CCS_KEYWORD_USE_PROFILE "%u\n" |
1386 |
"%s%s%s%s\n", domain->domainname->name, |
"%s%s%s%s\n", domain->domainname->name, |
1387 |
domain->profile, quota_exceeded, |
domain->profile, quota_exceeded, |
1388 |
transition_failed, |
transition_failed, |
1438 |
return -EINVAL; |
return -EINVAL; |
1439 |
*cp = '\0'; |
*cp = '\0'; |
1440 |
profile = simple_strtoul(data, NULL, 10); |
profile = simple_strtoul(data, NULL, 10); |
1441 |
if (profile >= MAX_PROFILES) |
if (profile >= CCS_MAX_PROFILES) |
1442 |
return -EINVAL; |
return -EINVAL; |
1443 |
domain = ccs_find_domain(cp + 1); |
domain = ccs_find_domain(cp + 1); |
1444 |
if (domain && (ccs_profile_ptr[profile] || !ccs_policy_loaded)) |
if (domain && (ccs_profile_ptr[profile] || !ccs_policy_loaded)) |
1561 |
static int ccs_write_exception_policy(struct ccs_io_buffer *head) |
static int ccs_write_exception_policy(struct ccs_io_buffer *head) |
1562 |
{ |
{ |
1563 |
char *data = head->write_buf; |
char *data = head->write_buf; |
1564 |
bool is_delete = ccs_str_starts(&data, KEYWORD_DELETE); |
bool is_delete = ccs_str_starts(&data, CCS_KEYWORD_DELETE); |
1565 |
if (ccs_str_starts(&data, KEYWORD_KEEP_DOMAIN)) |
if (ccs_str_starts(&data, CCS_KEYWORD_KEEP_DOMAIN)) |
1566 |
return ccs_write_domain_keeper_policy(data, false, is_delete); |
return ccs_write_domain_keeper_policy(data, false, is_delete); |
1567 |
if (ccs_str_starts(&data, KEYWORD_NO_KEEP_DOMAIN)) |
if (ccs_str_starts(&data, CCS_KEYWORD_NO_KEEP_DOMAIN)) |
1568 |
return ccs_write_domain_keeper_policy(data, true, is_delete); |
return ccs_write_domain_keeper_policy(data, true, is_delete); |
1569 |
if (ccs_str_starts(&data, KEYWORD_INITIALIZE_DOMAIN)) |
if (ccs_str_starts(&data, CCS_KEYWORD_INITIALIZE_DOMAIN)) |
1570 |
return ccs_write_domain_initializer_policy(data, false, |
return ccs_write_domain_initializer_policy(data, false, |
1571 |
is_delete); |
is_delete); |
1572 |
if (ccs_str_starts(&data, KEYWORD_NO_INITIALIZE_DOMAIN)) |
if (ccs_str_starts(&data, CCS_KEYWORD_NO_INITIALIZE_DOMAIN)) |
1573 |
return ccs_write_domain_initializer_policy(data, true, |
return ccs_write_domain_initializer_policy(data, true, |
1574 |
is_delete); |
is_delete); |
1575 |
if (ccs_str_starts(&data, KEYWORD_AGGREGATOR)) |
if (ccs_str_starts(&data, CCS_KEYWORD_AGGREGATOR)) |
1576 |
return ccs_write_aggregator_policy(data, is_delete); |
return ccs_write_aggregator_policy(data, is_delete); |
1577 |
if (ccs_str_starts(&data, KEYWORD_ALLOW_READ)) |
if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_READ)) |
1578 |
return ccs_write_globally_readable_policy(data, is_delete); |
return ccs_write_globally_readable_policy(data, is_delete); |
1579 |
if (ccs_str_starts(&data, KEYWORD_ALLOW_ENV)) |
if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_ENV)) |
1580 |
return ccs_write_globally_usable_env_policy(data, is_delete); |
return ccs_write_globally_usable_env_policy(data, is_delete); |
1581 |
if (ccs_str_starts(&data, KEYWORD_FILE_PATTERN)) |
if (ccs_str_starts(&data, CCS_KEYWORD_FILE_PATTERN)) |
1582 |
return ccs_write_pattern_policy(data, is_delete); |
return ccs_write_pattern_policy(data, is_delete); |
1583 |
if (ccs_str_starts(&data, KEYWORD_PATH_GROUP)) |
if (ccs_str_starts(&data, CCS_KEYWORD_PATH_GROUP)) |
1584 |
return ccs_write_path_group_policy(data, is_delete); |
return ccs_write_path_group_policy(data, is_delete); |
1585 |
if (ccs_str_starts(&data, KEYWORD_NUMBER_GROUP)) |
if (ccs_str_starts(&data, CCS_KEYWORD_NUMBER_GROUP)) |
1586 |
return ccs_write_number_group_policy(data, is_delete); |
return ccs_write_number_group_policy(data, is_delete); |
1587 |
if (ccs_str_starts(&data, KEYWORD_DENY_REWRITE)) |
if (ccs_str_starts(&data, CCS_KEYWORD_DENY_REWRITE)) |
1588 |
return ccs_write_no_rewrite_policy(data, is_delete); |
return ccs_write_no_rewrite_policy(data, is_delete); |
1589 |
if (ccs_str_starts(&data, KEYWORD_ADDRESS_GROUP)) |
if (ccs_str_starts(&data, CCS_KEYWORD_ADDRESS_GROUP)) |
1590 |
return ccs_write_address_group_policy(data, is_delete); |
return ccs_write_address_group_policy(data, is_delete); |
1591 |
if (ccs_str_starts(&data, KEYWORD_DENY_AUTOBIND)) |
if (ccs_str_starts(&data, CCS_KEYWORD_DENY_AUTOBIND)) |
1592 |
return ccs_write_reserved_port_policy(data, is_delete); |
return ccs_write_reserved_port_policy(data, is_delete); |
1593 |
return -EINVAL; |
return -EINVAL; |
1594 |
} |
} |
1674 |
return 0; |
return 0; |
1675 |
} |
} |
1676 |
|
|
1677 |
|
/** |
1678 |
|
* ccs_get_argv0 - Get argv[0]. |
1679 |
|
* |
1680 |
|
* @ee: Pointer to "struct ccs_execve_entry". |
1681 |
|
* |
1682 |
|
* Returns true on success, false otherwise. |
1683 |
|
*/ |
1684 |
|
static bool ccs_get_argv0(struct ccs_execve_entry *ee) |
1685 |
|
{ |
1686 |
|
struct linux_binprm *bprm = ee->bprm; |
1687 |
|
char *arg_ptr = ee->tmp; |
1688 |
|
int arg_len = 0; |
1689 |
|
unsigned long pos = bprm->p; |
1690 |
|
int offset = pos % PAGE_SIZE; |
1691 |
|
bool done = false; |
1692 |
|
if (!bprm->argc) |
1693 |
|
goto out; |
1694 |
|
while (1) { |
1695 |
|
if (!ccs_dump_page(bprm, pos, &ee->dump)) |
1696 |
|
goto out; |
1697 |
|
pos += PAGE_SIZE - offset; |
1698 |
|
/* Read. */ |
1699 |
|
while (offset < PAGE_SIZE) { |
1700 |
|
const char *kaddr = ee->dump.data; |
1701 |
|
const unsigned char c = kaddr[offset++]; |
1702 |
|
if (c && arg_len < CCS_MAX_PATHNAME_LEN - 10) { |
1703 |
|
if (c == '\\') { |
1704 |
|
arg_ptr[arg_len++] = '\\'; |
1705 |
|
arg_ptr[arg_len++] = '\\'; |
1706 |
|
} else if (c == '/') { |
1707 |
|
arg_len = 0; |
1708 |
|
} else if (c > ' ' && c < 127) { |
1709 |
|
arg_ptr[arg_len++] = c; |
1710 |
|
} else { |
1711 |
|
arg_ptr[arg_len++] = '\\'; |
1712 |
|
arg_ptr[arg_len++] = (c >> 6) + '0'; |
1713 |
|
arg_ptr[arg_len++] |
1714 |
|
= ((c >> 3) & 7) + '0'; |
1715 |
|
arg_ptr[arg_len++] = (c & 7) + '0'; |
1716 |
|
} |
1717 |
|
} else { |
1718 |
|
arg_ptr[arg_len] = '\0'; |
1719 |
|
done = true; |
1720 |
|
break; |
1721 |
|
} |
1722 |
|
} |
1723 |
|
offset = 0; |
1724 |
|
if (done) |
1725 |
|
break; |
1726 |
|
} |
1727 |
|
return true; |
1728 |
|
out: |
1729 |
|
return false; |
1730 |
|
} |
1731 |
|
|
1732 |
|
static struct ccs_condition *ccs_get_execute_condition(struct ccs_execve_entry |
1733 |
|
*ee) |
1734 |
|
{ |
1735 |
|
struct ccs_condition *cond; |
1736 |
|
char *buf; |
1737 |
|
int len = 256; |
1738 |
|
char *realpath = NULL; |
1739 |
|
char *argv0 = NULL; |
1740 |
|
if (ccs_check_flags(NULL, CCS_AUTOLEARN_EXEC_REALPATH)) { |
1741 |
|
struct file *file = ee->bprm->file; |
1742 |
|
realpath = ccs_realpath_from_dentry(file->f_dentry, |
1743 |
|
file->f_vfsmnt); |
1744 |
|
if (realpath) |
1745 |
|
len += strlen(realpath) + 17; |
1746 |
|
} |
1747 |
|
if (ccs_check_flags(NULL, CCS_AUTOLEARN_EXEC_REALPATH)) { |
1748 |
|
if (ccs_get_argv0(ee)) { |
1749 |
|
argv0 = ee->tmp; |
1750 |
|
len += strlen(argv0) + 16; |
1751 |
|
} |
1752 |
|
} |
1753 |
|
buf = kmalloc(len, GFP_KERNEL); |
1754 |
|
if (!buf) |
1755 |
|
return NULL; |
1756 |
|
snprintf(buf, len - 1, "if"); |
1757 |
|
if (current->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER) { |
1758 |
|
const int pos = strlen(buf); |
1759 |
|
snprintf(buf + pos, len - pos - 1, |
1760 |
|
" task.type=execute_handler"); |
1761 |
|
} |
1762 |
|
if (realpath) { |
1763 |
|
const int pos = strlen(buf); |
1764 |
|
snprintf(buf + pos, len - pos - 1, " exec.realpath=\"%s\"", |
1765 |
|
realpath); |
1766 |
|
kfree(realpath); |
1767 |
|
} |
1768 |
|
if (argv0) { |
1769 |
|
const int pos = strlen(buf); |
1770 |
|
snprintf(buf + pos, len - pos - 1, " exec.argv[0]=\"%s\"", |
1771 |
|
argv0); |
1772 |
|
} |
1773 |
|
cond = ccs_get_condition(buf); |
1774 |
|
kfree(buf); |
1775 |
|
return cond; |
1776 |
|
} |
1777 |
|
|
1778 |
/* Wait queue for ccs_query_list. */ |
/* Wait queue for ccs_query_list. */ |
1779 |
static DECLARE_WAIT_QUEUE_HEAD(ccs_query_wait); |
static DECLARE_WAIT_QUEUE_HEAD(ccs_query_wait); |
1780 |
|
|
1806 |
* Returns 0 if the supervisor decided to permit the access request which |
* Returns 0 if the supervisor decided to permit the access request which |
1807 |
* violated the policy in enforcing mode, 1 if the supervisor decided to |
* violated the policy in enforcing mode, 1 if the supervisor decided to |
1808 |
* retry the access request which violated the policy in enforcing mode, |
* retry the access request which violated the policy in enforcing mode, |
1809 |
* -EPERM otherwise. |
* 0 if it is not in enforcing mode, -EPERM otherwise. |
1810 |
*/ |
*/ |
1811 |
int ccs_check_supervisor(struct ccs_request_info *r, const char *fmt, ...) |
int ccs_check_supervisor(struct ccs_request_info *r, const char *fmt, ...) |
1812 |
{ |
{ |
1820 |
char *header; |
char *header; |
1821 |
if (!r->domain) |
if (!r->domain) |
1822 |
r->domain = ccs_current_domain(); |
r->domain = ccs_current_domain(); |
1823 |
|
switch (r->mode) { |
1824 |
|
char *buffer; |
1825 |
|
struct ccs_condition *cond; |
1826 |
|
case 1: |
1827 |
|
if (!ccs_domain_quota_ok(r)) |
1828 |
|
return 0; |
1829 |
|
va_start(args, fmt); |
1830 |
|
len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 4; |
1831 |
|
va_end(args); |
1832 |
|
buffer = kmalloc(len, GFP_KERNEL); |
1833 |
|
if (!buffer) |
1834 |
|
return 0; |
1835 |
|
va_start(args, fmt); |
1836 |
|
vsnprintf(buffer, len - 1, fmt, args); |
1837 |
|
va_end(args); |
1838 |
|
ccs_normalize_line(buffer); |
1839 |
|
if (r->ee && !strncmp(buffer, "allow_execute ", 14)) |
1840 |
|
cond = ccs_get_execute_condition(r->ee); |
1841 |
|
else if ((current->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER)) { |
1842 |
|
char str[] = "if task.type=execute_handler"; |
1843 |
|
cond = ccs_get_condition(str); |
1844 |
|
} else |
1845 |
|
cond = NULL; |
1846 |
|
ccs_write_domain_policy2(buffer, r->domain, cond, false); |
1847 |
|
ccs_put_condition(cond); |
1848 |
|
kfree(buffer); |
1849 |
|
/* fall through */ |
1850 |
|
case 2: |
1851 |
|
return 0; |
1852 |
|
} |
1853 |
if (!atomic_read(&ccs_query_observers)) { |
if (!atomic_read(&ccs_query_observers)) { |
1854 |
int i; |
int i; |
1855 |
if (current->ccs_flags & CCS_DONT_SLEEP_ON_ENFORCE_ERROR) |
if (current->ccs_flags & CCS_DONT_SLEEP_ON_ENFORCE_ERROR) |
1870 |
ccs_query_entry = kzalloc(sizeof(*ccs_query_entry), GFP_KERNEL); |
ccs_query_entry = kzalloc(sizeof(*ccs_query_entry), GFP_KERNEL); |
1871 |
if (!ccs_query_entry) |
if (!ccs_query_entry) |
1872 |
goto out; |
goto out; |
1873 |
|
len = ccs_round2(len); |
1874 |
ccs_query_entry->query = kzalloc(len, GFP_KERNEL); |
ccs_query_entry->query = kzalloc(len, GFP_KERNEL); |
1875 |
if (!ccs_query_entry->query) |
if (!ccs_query_entry->query) |
1876 |
goto out; |
goto out; |