794 |
} |
} |
795 |
|
|
796 |
/** |
/** |
|
* ccs_find_condition_part - Find condition part from the statement. |
|
|
* |
|
|
* @data: String to parse. |
|
|
* |
|
|
* Returns pointer to the condition part if it was found in the statement, |
|
|
* NULL otherwise. |
|
|
*/ |
|
|
static char *ccs_find_condition_part(char *data) |
|
|
{ |
|
|
char *cp = strstr(data, " if "); |
|
|
if (cp) { |
|
|
while (1) { |
|
|
char *cp2 = strstr(cp + 3, " if "); |
|
|
if (!cp2) |
|
|
break; |
|
|
cp = cp2; |
|
|
} |
|
|
*cp = '\0'; |
|
|
cp += 4; |
|
|
} |
|
|
return cp; |
|
|
} |
|
|
|
|
|
/** |
|
797 |
* ccs_select_one - Parse select command. |
* ccs_select_one - Parse select command. |
798 |
* |
* |
799 |
* @head: Pointer to "struct ccs_io_buffer". |
* @head: Pointer to "struct ccs_io_buffer". |
854 |
{ |
{ |
855 |
const struct ccs_handler_acl *p1 = container_of(a, typeof(*p1), head); |
const struct ccs_handler_acl *p1 = container_of(a, typeof(*p1), head); |
856 |
const struct ccs_handler_acl *p2 = container_of(b, typeof(*p2), head); |
const struct ccs_handler_acl *p2 = container_of(b, typeof(*p2), head); |
857 |
return ccs_same_acl_head(&p1->head, &p2->head) && |
return p1->handler == p2->handler; |
|
p1->handler == p2->handler; |
|
858 |
} |
} |
859 |
|
|
860 |
static bool ccs_same_task_acl(const struct ccs_acl_info *a, |
static bool ccs_same_task_acl(const struct ccs_acl_info *a, |
862 |
{ |
{ |
863 |
const struct ccs_task_acl *p1 = container_of(a, typeof(*p1), head); |
const struct ccs_task_acl *p1 = container_of(a, typeof(*p1), head); |
864 |
const struct ccs_task_acl *p2 = container_of(b, typeof(*p2), head); |
const struct ccs_task_acl *p2 = container_of(b, typeof(*p2), head); |
865 |
return ccs_same_acl_head(&p1->head, &p2->head) && |
return p1->domainname == p2->domainname; |
|
p1->domainname == p2->domainname; |
|
866 |
} |
} |
867 |
|
|
868 |
/** |
/** |
869 |
* ccs_write_task - Update task related list. |
* ccs_write_task - Update task related list. |
870 |
* |
* |
871 |
* @data: String to parse. |
* @param: Pointer to "struct ccs_acl_param". |
|
* @domain: Pointer to "struct ccs_domain_info". |
|
|
* @condition: Pointer to "struct ccs_condition". Maybe NULL. |
|
|
* @is_delete: True if it is a delete request. |
|
872 |
* |
* |
873 |
* Returns 0 on success, negative value otherwise. |
* Returns 0 on success, negative value otherwise. |
874 |
*/ |
*/ |
875 |
static int ccs_write_task(char *data, struct ccs_domain_info *domain, |
static int ccs_write_task(struct ccs_acl_param *param) |
|
struct ccs_condition *condition, |
|
|
const bool is_delete) |
|
876 |
{ |
{ |
877 |
int error; |
int error; |
878 |
const bool is_auto = ccs_str_starts(&data, "auto_domain_transition "); |
const bool is_auto = ccs_str_starts(¶m->data, |
879 |
if (!is_auto && !ccs_str_starts(&data, "manual_domain_transition ")) { |
"auto_domain_transition "); |
880 |
struct ccs_handler_acl e = { |
if (!is_auto && !ccs_str_starts(¶m->data, |
881 |
.head.cond = condition, |
"manual_domain_transition ")) { |
882 |
}; |
struct ccs_handler_acl e = { }; |
883 |
if (ccs_str_starts(&data, "auto_execute_handler ")) |
char *handler; |
884 |
|
if (ccs_str_starts(¶m->data, "auto_execute_handler ")) |
885 |
e.head.type = CCS_TYPE_AUTO_EXECUTE_HANDLER; |
e.head.type = CCS_TYPE_AUTO_EXECUTE_HANDLER; |
886 |
else if (ccs_str_starts(&data, "denied_execute_handler ")) |
else if (ccs_str_starts(¶m->data, |
887 |
|
"denied_execute_handler ")) |
888 |
e.head.type = CCS_TYPE_DENIED_EXECUTE_HANDLER; |
e.head.type = CCS_TYPE_DENIED_EXECUTE_HANDLER; |
889 |
else |
else |
890 |
return -EINVAL; |
return -EINVAL; |
891 |
if (!ccs_correct_path(data)) |
handler = ccs_read_token(param); |
892 |
|
if (!ccs_correct_path(handler)) |
893 |
return -EINVAL; |
return -EINVAL; |
894 |
e.handler = ccs_get_name(data); |
e.handler = ccs_get_name(handler); |
895 |
if (!e.handler) |
if (!e.handler) |
896 |
return -ENOMEM; |
return -ENOMEM; |
897 |
if (e.handler->is_patterned) |
if (e.handler->is_patterned) |
898 |
error = -EINVAL; /* No patterns allowed. */ |
error = -EINVAL; /* No patterns allowed. */ |
899 |
else |
else |
900 |
error = ccs_update_domain(&e.head, sizeof(e), |
error = ccs_update_domain(&e.head, sizeof(e), param, |
|
is_delete, domain, |
|
901 |
ccs_same_handler_acl, NULL); |
ccs_same_handler_acl, NULL); |
902 |
ccs_put_name(e.handler); |
ccs_put_name(e.handler); |
903 |
} else { |
} else { |
904 |
struct ccs_task_acl e = { |
struct ccs_task_acl e = { |
905 |
.head.type = is_auto ? |
.head.type = is_auto ? |
906 |
CCS_TYPE_AUTO_TASK_ACL : CCS_TYPE_MANUAL_TASK_ACL, |
CCS_TYPE_AUTO_TASK_ACL : CCS_TYPE_MANUAL_TASK_ACL, |
907 |
.head.cond = condition, |
.domainname = ccs_get_domainname(param), |
908 |
}; |
}; |
|
if (!ccs_correct_domain(data)) |
|
|
return -EINVAL; |
|
|
e.domainname = ccs_get_name(data); |
|
909 |
if (!e.domainname) |
if (!e.domainname) |
910 |
return -ENOMEM; |
error = -EINVAL; |
911 |
error = ccs_update_domain(&e.head, sizeof(e), is_delete, |
else |
912 |
domain, ccs_same_task_acl, NULL); |
error = ccs_update_domain(&e.head, sizeof(e), param, |
913 |
|
ccs_same_task_acl, NULL); |
914 |
ccs_put_name(e.domainname); |
ccs_put_name(e.domainname); |
915 |
} |
} |
916 |
return error; |
return error; |
919 |
static int ccs_write_domain2(char *data, struct ccs_domain_info *domain, |
static int ccs_write_domain2(char *data, struct ccs_domain_info *domain, |
920 |
const bool is_delete) |
const bool is_delete) |
921 |
{ |
{ |
922 |
|
struct ccs_acl_param param = { |
923 |
|
.data = data, |
924 |
|
.domain = domain, |
925 |
|
.is_delete = is_delete, |
926 |
|
}; |
927 |
static const struct { |
static const struct { |
928 |
const char *keyword; |
const char *keyword; |
929 |
int (*write) (char *, struct ccs_domain_info *, |
int (*write) (struct ccs_acl_param *); |
|
struct ccs_condition *, const bool); |
|
930 |
} ccs_callback[7] = { |
} ccs_callback[7] = { |
931 |
{ "file ", ccs_write_file }, |
{ "file ", ccs_write_file }, |
932 |
{ "network inet ", ccs_write_inet_network }, |
{ "network inet ", ccs_write_inet_network }, |
936 |
{ "ipc ", ccs_write_ipc }, |
{ "ipc ", ccs_write_ipc }, |
937 |
{ "task ", ccs_write_task }, |
{ "task ", ccs_write_task }, |
938 |
}; |
}; |
|
int error = -EINVAL; |
|
939 |
u8 i; |
u8 i; |
|
struct ccs_condition *cond = NULL; |
|
|
char *cp = ccs_find_condition_part(data); |
|
|
if (cp) { |
|
|
cond = ccs_get_condition(cp); |
|
|
if (!cond) |
|
|
return -EINVAL; |
|
|
} |
|
940 |
for (i = 0; i < 7; i++) { |
for (i = 0; i < 7; i++) { |
941 |
if (!ccs_str_starts(&data, ccs_callback[i].keyword)) |
if (!ccs_str_starts(¶m.data, ccs_callback[i].keyword)) |
942 |
continue; |
continue; |
943 |
error = ccs_callback[i].write(data, domain, cond, is_delete); |
return ccs_callback[i].write(¶m); |
|
break; |
|
944 |
} |
} |
945 |
if (cond) |
return -EINVAL; |
|
ccs_put_condition(cond); |
|
|
return error; |
|
946 |
} |
} |
947 |
|
|
948 |
static const char *ccs_dif[CCS_MAX_DOMAIN_INFO_FLAGS] = { |
static const char *ccs_dif[CCS_MAX_DOMAIN_INFO_FLAGS] = { |
1092 |
{ |
{ |
1093 |
switch (head->r.cond_step) { |
switch (head->r.cond_step) { |
1094 |
case 0: |
case 0: |
1095 |
{ |
head->r.cond_index = 0; |
1096 |
ccs_set_string(head, " if"); |
head->r.cond_step++; |
|
head->r.cond_index = 0; |
|
|
head->r.cond_step++; |
|
|
} |
|
1097 |
/* fall through */ |
/* fall through */ |
1098 |
case 1: |
case 1: |
1099 |
{ |
{ |
1975 |
vsnprintf(buffer, len - 1, fmt, args); |
vsnprintf(buffer, len - 1, fmt, args); |
1976 |
va_end(args); |
va_end(args); |
1977 |
if (handler || realpath || argv0 || symlink) { |
if (handler || realpath || argv0 || symlink) { |
|
ccs_addprintf(buffer, len, " if"); |
|
1978 |
if (handler) |
if (handler) |
1979 |
ccs_addprintf(buffer, len, " task.%s", |
ccs_addprintf(buffer, len, " task.%s", |
1980 |
handler); |
handler); |