40 |
static struct ccs_profile *ccs_profile_ptr[CCS_MAX_PROFILES]; |
static struct ccs_profile *ccs_profile_ptr[CCS_MAX_PROFILES]; |
41 |
|
|
42 |
/* String table for functionality that takes 4 modes. */ |
/* String table for functionality that takes 4 modes. */ |
43 |
static const char *ccs_mode[CCS_CONFIG_MAX_MODE] = { |
const char *ccs_mode[CCS_CONFIG_MAX_MODE] = { |
44 |
[CCS_CONFIG_DISABLED] = "disabled", |
[CCS_CONFIG_DISABLED] = "disabled", |
45 |
[CCS_CONFIG_LEARNING] = "learning", |
[CCS_CONFIG_LEARNING] = "learning", |
46 |
[CCS_CONFIG_PERMISSIVE] = "permissive", |
[CCS_CONFIG_PERMISSIVE] = "permissive", |
581 |
static int ccs_write_profile(struct ccs_io_buffer *head) |
static int ccs_write_profile(struct ccs_io_buffer *head) |
582 |
{ |
{ |
583 |
char *data = head->write_buf; |
char *data = head->write_buf; |
584 |
|
unsigned int i; |
585 |
bool use_default = false; |
bool use_default = false; |
586 |
char *cp; |
char *cp; |
|
int i; |
|
587 |
struct ccs_profile *profile; |
struct ccs_profile *profile; |
588 |
if (sscanf(data, "PROFILE_VERSION=%u", &ccs_profile_version) == 1) |
if (sscanf(data, "PROFILE_VERSION=%u", &ccs_profile_version) == 1) |
589 |
return 0; |
return 0; |
764 |
goto next; |
goto next; |
765 |
} |
} |
766 |
|
|
767 |
static bool ccs_same_manager_entry(const struct ccs_acl_head *a, |
static bool ccs_same_manager(const struct ccs_acl_head *a, |
768 |
const struct ccs_acl_head *b) |
const struct ccs_acl_head *b) |
769 |
{ |
{ |
770 |
return container_of(a, struct ccs_manager, head)->manager |
return container_of(a, struct ccs_manager, head)->manager |
771 |
== container_of(b, struct ccs_manager, head)->manager; |
== container_of(b, struct ccs_manager, head)->manager; |
796 |
return error; |
return error; |
797 |
error = ccs_update_policy(&e.head, sizeof(e), is_delete, |
error = ccs_update_policy(&e.head, sizeof(e), is_delete, |
798 |
&ccs_policy_list[CCS_ID_MANAGER], |
&ccs_policy_list[CCS_ID_MANAGER], |
799 |
ccs_same_manager_entry); |
ccs_same_manager); |
800 |
ccs_put_name(e.manager); |
ccs_put_name(e.manager); |
801 |
return error; |
return error; |
802 |
} |
} |
1708 |
{ CCS_KEYWORD_DENY_REWRITE, ccs_write_no_rewrite }, |
{ CCS_KEYWORD_DENY_REWRITE, ccs_write_no_rewrite }, |
1709 |
{ CCS_KEYWORD_DENY_AUTOBIND, ccs_write_reserved_port } |
{ CCS_KEYWORD_DENY_AUTOBIND, ccs_write_reserved_port } |
1710 |
}; |
}; |
1711 |
for (i = 0; i < 4; i++) { |
for (i = 0; i < 4; i++) |
1712 |
if (ccs_str_starts(&data, ccs_callback[i].keyword)) |
if (ccs_str_starts(&data, ccs_callback[i].keyword)) |
1713 |
return ccs_callback[i].write(data, is_delete); |
return ccs_callback[i].write(data, is_delete); |
1714 |
} |
for (i = 0; i < CCS_MAX_TRANSITION_TYPE; i++) |
|
for (i = 0; i < CCS_MAX_TRANSITION_TYPE; i++) { |
|
1715 |
if (ccs_str_starts(&data, ccs_transition_type[i])) |
if (ccs_str_starts(&data, ccs_transition_type[i])) |
1716 |
return ccs_write_transition_control(data, is_delete, |
return ccs_write_transition_control(data, is_delete, |
1717 |
i); |
i); |
1718 |
} |
for (i = 0; i < CCS_MAX_GROUP; i++) |
|
for (i = 0; i < CCS_MAX_GROUP; i++) { |
|
1719 |
if (ccs_str_starts(&data, ccs_group_name[i])) |
if (ccs_str_starts(&data, ccs_group_name[i])) |
1720 |
return ccs_write_group(data, is_delete, i); |
return ccs_write_group(data, is_delete, i); |
|
} |
|
1721 |
return ccs_write_domain2(data, &ccs_global_domain, is_delete); |
return ccs_write_domain2(data, &ccs_global_domain, is_delete); |
1722 |
} |
} |
1723 |
|
|
1890 |
static DEFINE_SPINLOCK(ccs_query_list_lock); |
static DEFINE_SPINLOCK(ccs_query_list_lock); |
1891 |
|
|
1892 |
/* Structure for query. */ |
/* Structure for query. */ |
1893 |
struct ccs_query_entry { |
struct ccs_query { |
1894 |
struct list_head list; |
struct list_head list; |
1895 |
char *query; |
char *query; |
1896 |
int query_len; |
int query_len; |
1899 |
int answer; |
int answer; |
1900 |
}; |
}; |
1901 |
|
|
1902 |
/* The list for "struct ccs_query_entry". */ |
/* The list for "struct ccs_query". */ |
1903 |
static LIST_HEAD(ccs_query_list); |
static LIST_HEAD(ccs_query_list); |
1904 |
|
|
1905 |
/* Number of "struct file" referring /proc/ccs/query interface. */ |
/* Number of "struct file" referring /proc/ccs/query interface. */ |
1930 |
int pos; |
int pos; |
1931 |
int len; |
int len; |
1932 |
static unsigned int ccs_serial; |
static unsigned int ccs_serial; |
1933 |
struct ccs_query_entry *ccs_query_entry = NULL; |
struct ccs_query *entry = NULL; |
1934 |
bool quota_exceeded = false; |
bool quota_exceeded = false; |
1935 |
char *header; |
char *header; |
1936 |
struct ccs_domain_info * const domain = ccs_current_domain(); |
struct ccs_domain_info * const domain = ccs_current_domain(); |
2022 |
header = ccs_init_log(&len, r); |
header = ccs_init_log(&len, r); |
2023 |
if (!header) |
if (!header) |
2024 |
goto out; |
goto out; |
2025 |
ccs_query_entry = kzalloc(sizeof(*ccs_query_entry), CCS_GFP_FLAGS); |
entry = kzalloc(sizeof(*entry), CCS_GFP_FLAGS); |
2026 |
if (!ccs_query_entry) |
if (!entry) |
2027 |
goto out; |
goto out; |
2028 |
len = ccs_round2(len); |
len = ccs_round2(len); |
2029 |
ccs_query_entry->query = kzalloc(len, CCS_GFP_FLAGS); |
entry->query = kzalloc(len, CCS_GFP_FLAGS); |
2030 |
if (!ccs_query_entry->query) |
if (!entry->query) |
2031 |
goto out; |
goto out; |
|
INIT_LIST_HEAD(&ccs_query_entry->list); |
|
2032 |
spin_lock(&ccs_query_list_lock); |
spin_lock(&ccs_query_list_lock); |
2033 |
if (ccs_quota_for_query && ccs_query_memory_size + len + |
if (ccs_quota_for_query && ccs_query_memory_size + len + |
2034 |
sizeof(*ccs_query_entry) >= ccs_quota_for_query) { |
sizeof(*entry) >= ccs_quota_for_query) { |
2035 |
quota_exceeded = true; |
quota_exceeded = true; |
2036 |
} else { |
} else { |
2037 |
ccs_query_memory_size += len + sizeof(*ccs_query_entry); |
ccs_query_memory_size += len + sizeof(*entry); |
2038 |
ccs_query_entry->serial = ccs_serial++; |
entry->serial = ccs_serial++; |
2039 |
} |
} |
2040 |
spin_unlock(&ccs_query_list_lock); |
spin_unlock(&ccs_query_list_lock); |
2041 |
if (quota_exceeded) |
if (quota_exceeded) |
2042 |
goto out; |
goto out; |
2043 |
pos = snprintf(ccs_query_entry->query, len - 1, "Q%u-%hu\n%s", |
pos = snprintf(entry->query, len - 1, "Q%u-%hu\n%s", |
2044 |
ccs_query_entry->serial, r->retry, header); |
entry->serial, r->retry, header); |
2045 |
kfree(header); |
kfree(header); |
2046 |
header = NULL; |
header = NULL; |
2047 |
va_start(args, fmt); |
va_start(args, fmt); |
2048 |
vsnprintf(ccs_query_entry->query + pos, len - 1 - pos, fmt, args); |
vsnprintf(entry->query + pos, len - 1 - pos, fmt, args); |
2049 |
ccs_query_entry->query_len = strlen(ccs_query_entry->query) + 1; |
entry->query_len = strlen(entry->query) + 1; |
2050 |
va_end(args); |
va_end(args); |
2051 |
spin_lock(&ccs_query_list_lock); |
spin_lock(&ccs_query_list_lock); |
2052 |
list_add_tail(&ccs_query_entry->list, &ccs_query_list); |
list_add_tail(&entry->list, &ccs_query_list); |
2053 |
spin_unlock(&ccs_query_list_lock); |
spin_unlock(&ccs_query_list_lock); |
2054 |
/* Give 10 seconds for supervisor's opinion. */ |
/* Give 10 seconds for supervisor's opinion. */ |
2055 |
for (ccs_query_entry->timer = 0; |
for (entry->timer = 0; |
2056 |
atomic_read(&ccs_query_observers) && ccs_query_entry->timer < 100; |
atomic_read(&ccs_query_observers) && entry->timer < 100; |
2057 |
ccs_query_entry->timer++) { |
entry->timer++) { |
2058 |
wake_up(&ccs_query_wait); |
wake_up(&ccs_query_wait); |
2059 |
set_current_state(TASK_INTERRUPTIBLE); |
set_current_state(TASK_INTERRUPTIBLE); |
2060 |
schedule_timeout(HZ / 10); |
schedule_timeout(HZ / 10); |
2061 |
if (ccs_query_entry->answer) |
if (entry->answer) |
2062 |
break; |
break; |
2063 |
} |
} |
2064 |
spin_lock(&ccs_query_list_lock); |
spin_lock(&ccs_query_list_lock); |
2065 |
list_del(&ccs_query_entry->list); |
list_del(&entry->list); |
2066 |
ccs_query_memory_size -= len + sizeof(*ccs_query_entry); |
ccs_query_memory_size -= len + sizeof(*entry); |
2067 |
spin_unlock(&ccs_query_list_lock); |
spin_unlock(&ccs_query_list_lock); |
2068 |
switch (ccs_query_entry->answer) { |
switch (entry->answer) { |
2069 |
case 3: /* Asked to retry by administrator. */ |
case 3: /* Asked to retry by administrator. */ |
2070 |
error = CCS_RETRY_REQUEST; |
error = CCS_RETRY_REQUEST; |
2071 |
r->retry++; |
r->retry++; |
2082 |
break; |
break; |
2083 |
} |
} |
2084 |
out: |
out: |
2085 |
if (ccs_query_entry) |
if (entry) |
2086 |
kfree(ccs_query_entry->query); |
kfree(entry->query); |
2087 |
kfree(ccs_query_entry); |
kfree(entry); |
2088 |
kfree(header); |
kfree(header); |
2089 |
return error; |
return error; |
2090 |
} |
} |
2107 |
for (i = 0; i < 2; i++) { |
for (i = 0; i < 2; i++) { |
2108 |
spin_lock(&ccs_query_list_lock); |
spin_lock(&ccs_query_list_lock); |
2109 |
list_for_each(tmp, &ccs_query_list) { |
list_for_each(tmp, &ccs_query_list) { |
2110 |
struct ccs_query_entry *ptr = |
struct ccs_query *ptr = |
2111 |
list_entry(tmp, struct ccs_query_entry, list); |
list_entry(tmp, typeof(*ptr), list); |
2112 |
if (ptr->answer) |
if (ptr->answer) |
2113 |
continue; |
continue; |
2114 |
found = true; |
found = true; |
2143 |
} |
} |
2144 |
spin_lock(&ccs_query_list_lock); |
spin_lock(&ccs_query_list_lock); |
2145 |
list_for_each(tmp, &ccs_query_list) { |
list_for_each(tmp, &ccs_query_list) { |
2146 |
struct ccs_query_entry *ptr |
struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list); |
|
= list_entry(tmp, struct ccs_query_entry, list); |
|
2147 |
if (ptr->answer) |
if (ptr->answer) |
2148 |
continue; |
continue; |
2149 |
if (pos++ != head->r.query_index) |
if (pos++ != head->r.query_index) |
2162 |
pos = 0; |
pos = 0; |
2163 |
spin_lock(&ccs_query_list_lock); |
spin_lock(&ccs_query_list_lock); |
2164 |
list_for_each(tmp, &ccs_query_list) { |
list_for_each(tmp, &ccs_query_list) { |
2165 |
struct ccs_query_entry *ptr |
struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list); |
|
= list_entry(tmp, struct ccs_query_entry, list); |
|
2166 |
if (ptr->answer) |
if (ptr->answer) |
2167 |
continue; |
continue; |
2168 |
if (pos++ != head->r.query_index) |
if (pos++ != head->r.query_index) |
2200 |
unsigned int answer; |
unsigned int answer; |
2201 |
spin_lock(&ccs_query_list_lock); |
spin_lock(&ccs_query_list_lock); |
2202 |
list_for_each(tmp, &ccs_query_list) { |
list_for_each(tmp, &ccs_query_list) { |
2203 |
struct ccs_query_entry *ptr |
struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list); |
|
= list_entry(tmp, struct ccs_query_entry, list); |
|
2204 |
ptr->timer = 0; |
ptr->timer = 0; |
2205 |
} |
} |
2206 |
spin_unlock(&ccs_query_list_lock); |
spin_unlock(&ccs_query_list_lock); |
2208 |
return -EINVAL; |
return -EINVAL; |
2209 |
spin_lock(&ccs_query_list_lock); |
spin_lock(&ccs_query_list_lock); |
2210 |
list_for_each(tmp, &ccs_query_list) { |
list_for_each(tmp, &ccs_query_list) { |
2211 |
struct ccs_query_entry *ptr |
struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list); |
|
= list_entry(tmp, struct ccs_query_entry, list); |
|
2212 |
if (ptr->serial != serial) |
if (ptr->serial != serial) |
2213 |
continue; |
continue; |
2214 |
if (!ptr->answer) |
if (!ptr->answer) |