88 |
= "file::umount", |
= "file::umount", |
89 |
[CCS_MAC_FILE_PIVOT_ROOT] |
[CCS_MAC_FILE_PIVOT_ROOT] |
90 |
= "file::pivot_root", |
= "file::pivot_root", |
|
[CCS_MAC_FILE_TRANSIT] |
|
|
= "file::transit", |
|
91 |
[CCS_MAC_ENVIRON] |
[CCS_MAC_ENVIRON] |
92 |
= "misc::env", |
= "misc::env", |
93 |
[CCS_MAC_NETWORK_INET_TCP_BIND] |
[CCS_MAC_NETWORK_INET_TCP_BIND] |
804 |
static char *ccs_find_condition_part(char *data) |
static char *ccs_find_condition_part(char *data) |
805 |
{ |
{ |
806 |
char *cp = strstr(data, " if "); |
char *cp = strstr(data, " if "); |
807 |
if (!cp) |
if (cp) { |
808 |
cp = strstr(data, " ; set "); |
while (1) { |
809 |
if (cp) |
char *cp2 = strstr(cp + 3, " if "); |
810 |
*cp++ = '\0'; |
if (!cp2) |
811 |
|
break; |
812 |
|
cp = cp2; |
813 |
|
} |
814 |
|
*cp = '\0'; |
815 |
|
cp += 4; |
816 |
|
} |
817 |
return cp; |
return cp; |
818 |
} |
} |
819 |
|
|
873 |
return true; |
return true; |
874 |
} |
} |
875 |
|
|
876 |
|
static bool ccs_same_handler_acl(const struct ccs_acl_info *a, |
877 |
|
const struct ccs_acl_info *b) |
878 |
|
{ |
879 |
|
const struct ccs_handler_acl *p1 = container_of(a, typeof(*p1), head); |
880 |
|
const struct ccs_handler_acl *p2 = container_of(b, typeof(*p2), head); |
881 |
|
return ccs_same_acl_head(&p1->head, &p2->head) && |
882 |
|
p1->handler == p2->handler; |
883 |
|
} |
884 |
|
|
885 |
|
static bool ccs_same_task_acl(const struct ccs_acl_info *a, |
886 |
|
const struct ccs_acl_info *b) |
887 |
|
{ |
888 |
|
const struct ccs_task_acl *p1 = container_of(a, typeof(*p1), head); |
889 |
|
const struct ccs_task_acl *p2 = container_of(b, typeof(*p2), head); |
890 |
|
return ccs_same_acl_head(&p1->head, &p2->head) && |
891 |
|
p1->domainname == p2->domainname; |
892 |
|
} |
893 |
|
|
894 |
|
/** |
895 |
|
* ccs_write_task - Update task related list. |
896 |
|
* |
897 |
|
* @data: String to parse. |
898 |
|
* @domain: Pointer to "struct ccs_domain_info". |
899 |
|
* @condition: Pointer to "struct ccs_condition". Maybe NULL. |
900 |
|
* @is_delete: True if it is a delete request. |
901 |
|
* |
902 |
|
* Returns 0 on success, negative value otherwise. |
903 |
|
*/ |
904 |
|
static int ccs_write_task(char *data, struct ccs_domain_info *domain, |
905 |
|
struct ccs_condition *condition, |
906 |
|
const bool is_delete) |
907 |
|
{ |
908 |
|
int error; |
909 |
|
const bool is_auto = ccs_str_starts(&data, "auto_domain_transition "); |
910 |
|
if (!is_auto && !ccs_str_starts(&data, "manual_domain_transition ")) { |
911 |
|
struct ccs_handler_acl e = { |
912 |
|
.head.cond = condition, |
913 |
|
}; |
914 |
|
if (ccs_str_starts(&data, "auto_execute_handler ")) |
915 |
|
e.head.type = CCS_TYPE_AUTO_EXECUTE_HANDLER; |
916 |
|
else if (ccs_str_starts(&data, "denied_execute_handler ")) |
917 |
|
e.head.type = CCS_TYPE_DENIED_EXECUTE_HANDLER; |
918 |
|
else |
919 |
|
return -EINVAL; |
920 |
|
if (!ccs_correct_path(data)) |
921 |
|
return -EINVAL; |
922 |
|
e.handler = ccs_get_name(data); |
923 |
|
if (!e.handler) |
924 |
|
return -ENOMEM; |
925 |
|
if (e.handler->is_patterned) |
926 |
|
error = -EINVAL; /* No patterns allowed. */ |
927 |
|
else |
928 |
|
error = ccs_update_domain(&e.head, sizeof(e), |
929 |
|
is_delete, domain, |
930 |
|
ccs_same_handler_acl, NULL); |
931 |
|
ccs_put_name(e.handler); |
932 |
|
} else { |
933 |
|
struct ccs_task_acl e = { |
934 |
|
.head.type = is_auto ? |
935 |
|
CCS_TYPE_AUTO_TASK_ACL : CCS_TYPE_MANUAL_TASK_ACL, |
936 |
|
.head.cond = condition, |
937 |
|
}; |
938 |
|
if (!ccs_correct_domain(data)) |
939 |
|
return -EINVAL; |
940 |
|
e.domainname = ccs_get_name(data); |
941 |
|
if (!e.domainname) |
942 |
|
return -ENOMEM; |
943 |
|
error = ccs_update_domain(&e.head, sizeof(e), is_delete, |
944 |
|
domain, ccs_same_task_acl, NULL); |
945 |
|
ccs_put_name(e.domainname); |
946 |
|
} |
947 |
|
return error; |
948 |
|
} |
949 |
|
|
950 |
static int ccs_write_domain2(char *data, struct ccs_domain_info *domain, |
static int ccs_write_domain2(char *data, struct ccs_domain_info *domain, |
951 |
const bool is_delete) |
const bool is_delete) |
952 |
{ |
{ |
954 |
const char *keyword; |
const char *keyword; |
955 |
int (*write) (char *, struct ccs_domain_info *, |
int (*write) (char *, struct ccs_domain_info *, |
956 |
struct ccs_condition *, const bool); |
struct ccs_condition *, const bool); |
957 |
} ccs_callback[5] = { |
} ccs_callback[7] = { |
958 |
|
{ "file ", ccs_write_file }, |
959 |
{ "network inet ", ccs_write_inet_network }, |
{ "network inet ", ccs_write_inet_network }, |
960 |
{ "network unix ", ccs_write_unix_network }, |
{ "network unix ", ccs_write_unix_network }, |
961 |
{ "misc ", ccs_write_misc }, |
{ "misc ", ccs_write_misc }, |
962 |
{ "capability ", ccs_write_capability }, |
{ "capability ", ccs_write_capability }, |
963 |
{ "ipc ", ccs_write_ipc }, |
{ "ipc ", ccs_write_ipc }, |
964 |
|
{ "task ", ccs_write_task }, |
965 |
}; |
}; |
966 |
int (*write) (char *, struct ccs_domain_info *, struct ccs_condition *, |
int error = -EINVAL; |
|
const bool) = ccs_write_file; |
|
|
int error; |
|
967 |
u8 i; |
u8 i; |
968 |
struct ccs_condition *cond = NULL; |
struct ccs_condition *cond = NULL; |
969 |
char *cp = ccs_find_condition_part(data); |
char *cp = ccs_find_condition_part(data); |
972 |
if (!cond) |
if (!cond) |
973 |
return -EINVAL; |
return -EINVAL; |
974 |
} |
} |
975 |
for (i = 0; i < 5; i++) { |
for (i = 0; i < 7; i++) { |
976 |
if (!ccs_str_starts(&data, ccs_callback[i].keyword)) |
if (!ccs_str_starts(&data, ccs_callback[i].keyword)) |
977 |
continue; |
continue; |
978 |
write = ccs_callback[i].write; |
error = ccs_callback[i].write(data, domain, cond, is_delete); |
979 |
break; |
break; |
980 |
} |
} |
|
error = write(data, domain, cond, is_delete); |
|
981 |
if (cond) |
if (cond) |
982 |
ccs_put_condition(cond); |
ccs_put_condition(cond); |
983 |
return error; |
return error; |
1131 |
switch (head->r.cond_step) { |
switch (head->r.cond_step) { |
1132 |
case 0: |
case 0: |
1133 |
{ |
{ |
1134 |
if (cond->condc) |
ccs_set_string(head, " if"); |
|
ccs_set_string(head, " if"); |
|
1135 |
head->r.cond_index = 0; |
head->r.cond_index = 0; |
1136 |
head->r.cond_step++; |
head->r.cond_step++; |
1137 |
} |
} |
1243 |
head->r.cond_step++; |
head->r.cond_step++; |
1244 |
/* fall through */ |
/* fall through */ |
1245 |
case 3: |
case 3: |
1246 |
{ |
if (cond->audit) |
1247 |
u8 j; |
ccs_io_printf(head, " audit=%s", |
1248 |
const u8 i = cond->post_state[3]; |
ccs_yesno(cond->audit == 2)); |
1249 |
if (i) |
if (cond->transit) { |
1250 |
ccs_set_string(head, " ; set"); |
ccs_set_string(head, " auto_domain_transitition=\""); |
1251 |
for (j = 0; j < 3; j++) |
ccs_set_string(head, cond->transit->name); |
1252 |
if ((i & (1 << j))) |
ccs_set_string(head, "\""); |
|
ccs_io_printf(head, |
|
|
" task.state[%u]=%u", j, |
|
|
cond->post_state[j]); |
|
|
if (i & (1 << 4)) |
|
|
ccs_io_printf(head, " audit=%s", |
|
|
ccs_yesno(cond->post_state[4])); |
|
1253 |
} |
} |
1254 |
ccs_set_lf(head); |
ccs_set_lf(head); |
1255 |
return true; |
return true; |
1308 |
if (!(perm & (1 << bit))) |
if (!(perm & (1 << bit))) |
1309 |
continue; |
continue; |
1310 |
if (head->r.print_execute_only && |
if (head->r.print_execute_only && |
1311 |
bit != CCS_TYPE_EXECUTE && bit != CCS_TYPE_TRANSIT) |
bit != CCS_TYPE_EXECUTE |
1312 |
|
/* && bit != CCS_TYPE_TRANSIT */) |
1313 |
continue; |
continue; |
1314 |
break; |
break; |
1315 |
} |
} |
1319 |
ccs_set_string(head, "file "); |
ccs_set_string(head, "file "); |
1320 |
ccs_set_string(head, ccs_path_keyword[bit]); |
ccs_set_string(head, ccs_path_keyword[bit]); |
1321 |
ccs_print_name_union(head, &ptr->name); |
ccs_print_name_union(head, &ptr->name); |
1322 |
} else if (acl_type == CCS_TYPE_EXECUTE_HANDLER || |
} else if (acl_type == CCS_TYPE_AUTO_EXECUTE_HANDLER || |
1323 |
acl_type == CCS_TYPE_DENIED_EXECUTE_HANDLER) { |
acl_type == CCS_TYPE_DENIED_EXECUTE_HANDLER) { |
1324 |
struct ccs_execute_handler *ptr |
struct ccs_handler_acl *ptr |
1325 |
= container_of(acl, typeof(*ptr), head); |
= container_of(acl, typeof(*ptr), head); |
1326 |
ccs_set_group(head); |
ccs_set_group(head); |
1327 |
ccs_io_printf(head, "%s ", |
ccs_set_string(head, "task "); |
1328 |
acl_type == CCS_TYPE_EXECUTE_HANDLER ? |
ccs_set_string(head, acl_type == CCS_TYPE_AUTO_EXECUTE_HANDLER |
1329 |
CCS_KEYWORD_EXECUTE_HANDLER : |
? "auto_execute_handler " : |
1330 |
CCS_KEYWORD_DENIED_EXECUTE_HANDLER); |
"denied_execute_handler "); |
1331 |
ccs_set_string(head, ptr->handler->name); |
ccs_set_string(head, ptr->handler->name); |
1332 |
|
} else if (acl_type == CCS_TYPE_AUTO_TASK_ACL || |
1333 |
|
acl_type == CCS_TYPE_MANUAL_TASK_ACL) { |
1334 |
|
struct ccs_task_acl *ptr = |
1335 |
|
container_of(acl, typeof(*ptr), head); |
1336 |
|
ccs_set_group(head); |
1337 |
|
ccs_set_string(head, "task "); |
1338 |
|
ccs_set_string(head, acl_type == CCS_TYPE_AUTO_TASK_ACL ? |
1339 |
|
"auto_domain_transition " : |
1340 |
|
"manual_domain_transition "); |
1341 |
|
ccs_set_string(head, ptr->domainname->name); |
1342 |
} else if (head->r.print_execute_only) { |
} else if (head->r.print_execute_only) { |
1343 |
return true; |
return true; |
1344 |
} else if (acl_type == CCS_TYPE_MKDEV_ACL) { |
} else if (acl_type == CCS_TYPE_MKDEV_ACL) { |
1480 |
* |
* |
1481 |
* @head: Pointer to "struct ccs_io_buffer". |
* @head: Pointer to "struct ccs_io_buffer". |
1482 |
* @domain: Pointer to "struct ccs_domain_info". |
* @domain: Pointer to "struct ccs_domain_info". |
1483 |
|
* @index: Index number. |
1484 |
* |
* |
1485 |
* Caller holds ccs_read_lock(). |
* Caller holds ccs_read_lock(). |
1486 |
* |
* |
1487 |
* Returns true on success, false otherwise. |
* Returns true on success, false otherwise. |
1488 |
*/ |
*/ |
1489 |
static bool ccs_read_domain2(struct ccs_io_buffer *head, |
static bool ccs_read_domain2(struct ccs_io_buffer *head, |
1490 |
struct ccs_domain_info *domain) |
struct ccs_domain_info *domain, |
1491 |
|
const u8 index) |
1492 |
{ |
{ |
1493 |
list_for_each_cookie(head->r.acl, &domain->acl_info_list) { |
list_for_each_cookie(head->r.acl, &domain->acl_info_list[index]) { |
1494 |
struct ccs_acl_info *ptr = |
struct ccs_acl_info *ptr = |
1495 |
list_entry(head->r.acl, typeof(*ptr), list); |
list_entry(head->r.acl, typeof(*ptr), list); |
1496 |
if (!ccs_print_entry(head, ptr)) |
if (!ccs_print_entry(head, ptr)) |
1534 |
ccs_set_lf(head); |
ccs_set_lf(head); |
1535 |
/* fall through */ |
/* fall through */ |
1536 |
case 1: |
case 1: |
1537 |
if (!ccs_read_domain2(head, domain)) |
if (!ccs_read_domain2(head, domain, 0)) |
1538 |
|
return; |
1539 |
|
head->r.step++; |
1540 |
|
/* fall through */ |
1541 |
|
case 2: |
1542 |
|
if (!ccs_read_domain2(head, domain, 1)) |
1543 |
return; |
return; |
1544 |
head->r.step++; |
head->r.step++; |
1545 |
if (!ccs_set_lf(head)) |
if (!ccs_set_lf(head)) |
1546 |
return; |
return; |
1547 |
/* fall through */ |
/* fall through */ |
1548 |
case 2: |
case 3: |
1549 |
head->r.step = 0; |
head->r.step = 0; |
1550 |
if (head->r.print_this_domain_only) |
if (head->r.print_this_domain_only) |
1551 |
goto done; |
goto done; |
1685 |
ccs_io_printf(head, "%u %u ", pid, domain->profile); |
ccs_io_printf(head, "%u %u ", pid, domain->profile); |
1686 |
ccs_set_string(head, domain->domainname->name); |
ccs_set_string(head, domain->domainname->name); |
1687 |
} else { |
} else { |
1688 |
ccs_io_printf(head, "%u manager=%s execute_handler=%s " |
ccs_io_printf(head, "%u manager=%s execute_handler=%s ", pid, |
|
"state[0]=%u state[1]=%u state[2]=%u", pid, |
|
1689 |
ccs_yesno(ccs_flags & |
ccs_yesno(ccs_flags & |
1690 |
CCS_TASK_IS_MANAGER), |
CCS_TASK_IS_MANAGER), |
1691 |
ccs_yesno(ccs_flags & |
ccs_yesno(ccs_flags & |
1692 |
CCS_TASK_IS_EXECUTE_HANDLER), |
CCS_TASK_IS_EXECUTE_HANDLER)); |
|
(u8) (ccs_flags >> 24), |
|
|
(u8) (ccs_flags >> 16), |
|
|
(u8) (ccs_flags >> 8)); |
|
1693 |
} |
} |
1694 |
} |
} |
1695 |
|
|
1903 |
if (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP) |
if (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP) |
1904 |
return; |
return; |
1905 |
while (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP |
while (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP |
1906 |
+ CCS_MAX_ACL_GROUPS) { |
+ CCS_MAX_ACL_GROUPS * 2) { |
1907 |
head->r.group_index = head->r.step - CCS_MAX_POLICY |
head->r.group_index = (head->r.step - CCS_MAX_POLICY |
1908 |
- CCS_MAX_GROUP; |
- CCS_MAX_GROUP) / 2; |
1909 |
if (!ccs_read_domain2(head, |
if (!ccs_read_domain2(head, |
1910 |
&ccs_acl_group[head->r.group_index])) |
&ccs_acl_group[head->r.group_index], |
1911 |
|
head->r.step & 1)) |
1912 |
return; |
return; |
1913 |
head->r.step++; |
head->r.step++; |
1914 |
} |
} |