1247 |
* Returns true on success, false otherwise. |
* Returns true on success, false otherwise. |
1248 |
*/ |
*/ |
1249 |
static bool ccs_print_path_acl(struct ccs_io_buffer *head, |
static bool ccs_print_path_acl(struct ccs_io_buffer *head, |
1250 |
struct ccs_path_acl *ptr) |
const struct ccs_path_acl *ptr) |
1251 |
{ |
{ |
1252 |
int pos; |
int pos; |
1253 |
u8 bit; |
u8 bit; |
1284 |
* Returns true on success, false otherwise. |
* Returns true on success, false otherwise. |
1285 |
*/ |
*/ |
1286 |
static bool ccs_print_mkdev_acl(struct ccs_io_buffer *head, |
static bool ccs_print_mkdev_acl(struct ccs_io_buffer *head, |
1287 |
struct ccs_mkdev_acl *ptr) |
const struct ccs_mkdev_acl *ptr) |
1288 |
{ |
{ |
1289 |
int pos; |
int pos; |
1290 |
u8 bit; |
u8 bit; |
1318 |
* Returns true on success, false otherwise. |
* Returns true on success, false otherwise. |
1319 |
*/ |
*/ |
1320 |
static bool ccs_print_path2_acl(struct ccs_io_buffer *head, |
static bool ccs_print_path2_acl(struct ccs_io_buffer *head, |
1321 |
struct ccs_path2_acl *ptr) |
const struct ccs_path2_acl *ptr) |
1322 |
{ |
{ |
1323 |
int pos; |
int pos; |
1324 |
u8 bit; |
u8 bit; |
1349 |
* Returns true on success, false otherwise. |
* Returns true on success, false otherwise. |
1350 |
*/ |
*/ |
1351 |
static bool ccs_print_path_number_acl(struct ccs_io_buffer *head, |
static bool ccs_print_path_number_acl(struct ccs_io_buffer *head, |
1352 |
struct ccs_path_number_acl *ptr) |
const struct ccs_path_number_acl *ptr) |
1353 |
{ |
{ |
1354 |
int pos; |
int pos; |
1355 |
u8 bit; |
u8 bit; |
1382 |
* Returns true on success, false otherwise. |
* Returns true on success, false otherwise. |
1383 |
*/ |
*/ |
1384 |
static bool ccs_print_env_acl(struct ccs_io_buffer *head, |
static bool ccs_print_env_acl(struct ccs_io_buffer *head, |
1385 |
struct ccs_env_acl *ptr) |
const struct ccs_env_acl *ptr) |
1386 |
{ |
{ |
1387 |
const int pos = head->read_avail; |
const int pos = head->read_avail; |
1388 |
if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_ENV "%s", ptr->env->name) || |
if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_ENV "%s", ptr->env->name) || |
1402 |
* Returns true on success, false otherwise. |
* Returns true on success, false otherwise. |
1403 |
*/ |
*/ |
1404 |
static bool ccs_print_capability_acl(struct ccs_io_buffer *head, |
static bool ccs_print_capability_acl(struct ccs_io_buffer *head, |
1405 |
struct ccs_capability_acl *ptr) |
const struct ccs_capability_acl *ptr) |
1406 |
{ |
{ |
1407 |
const int pos = head->read_avail; |
const int pos = head->read_avail; |
1408 |
if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_CAPABILITY "%s", |
if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_CAPABILITY "%s", |
1423 |
* Returns true on success, false otherwise. |
* Returns true on success, false otherwise. |
1424 |
*/ |
*/ |
1425 |
static bool ccs_print_network_acl(struct ccs_io_buffer *head, |
static bool ccs_print_network_acl(struct ccs_io_buffer *head, |
1426 |
struct ccs_ip_network_acl *ptr) |
const struct ccs_ip_network_acl *ptr) |
1427 |
{ |
{ |
1428 |
int pos; |
int pos; |
1429 |
u8 bit; |
u8 bit; |
1430 |
const u8 perm = ptr->perm; |
const u8 perm = ptr->perm; |
1431 |
char buf[128]; |
char buf[128]; |
1432 |
for (bit = head->read_bit; bit < CCS_MAX_NETWORK_OPERATION; bit++) { |
for (bit = head->read_bit; bit < CCS_MAX_NETWORK_OPERATION; bit++) { |
1433 |
const char *w[2] = { "", "" }; |
const char *w[2] = { buf, "" }; |
1434 |
if (!(perm & (1 << bit))) |
if (!(perm & (1 << bit))) |
1435 |
continue; |
continue; |
1436 |
pos = head->read_avail; |
pos = head->read_avail; |
1442 |
case CCS_IP_ADDRESS_TYPE_IPv4: |
case CCS_IP_ADDRESS_TYPE_IPv4: |
1443 |
ccs_print_ipv4(buf, sizeof(buf), ptr->address.ipv4.min, |
ccs_print_ipv4(buf, sizeof(buf), ptr->address.ipv4.min, |
1444 |
ptr->address.ipv4.max); |
ptr->address.ipv4.max); |
|
w[0] = buf; |
|
1445 |
break; |
break; |
1446 |
case CCS_IP_ADDRESS_TYPE_IPv6: |
case CCS_IP_ADDRESS_TYPE_IPv6: |
1447 |
ccs_print_ipv6(buf, sizeof(buf), ptr->address.ipv6.min, |
ccs_print_ipv6(buf, sizeof(buf), ptr->address.ipv6.min, |
1448 |
ptr->address.ipv6.max); |
ptr->address.ipv6.max); |
|
w[0] = buf; |
|
1449 |
break; |
break; |
1450 |
} |
} |
1451 |
if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_NETWORK "%s %s%s", |
if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_NETWORK "%s %s%s", |
1471 |
* Returns true on success, false otherwise. |
* Returns true on success, false otherwise. |
1472 |
*/ |
*/ |
1473 |
static bool ccs_print_signal_acl(struct ccs_io_buffer *head, |
static bool ccs_print_signal_acl(struct ccs_io_buffer *head, |
1474 |
struct ccs_signal_acl *ptr) |
const struct ccs_signal_acl *ptr) |
1475 |
{ |
{ |
1476 |
const int pos = head->read_avail; |
const int pos = head->read_avail; |
1477 |
if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_SIGNAL "%u %s", |
if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_SIGNAL "%u %s", |
1494 |
*/ |
*/ |
1495 |
static bool ccs_print_execute_handler(struct ccs_io_buffer *head, |
static bool ccs_print_execute_handler(struct ccs_io_buffer *head, |
1496 |
const char *keyword, |
const char *keyword, |
1497 |
struct ccs_execute_handler *ptr) |
const struct ccs_execute_handler *ptr) |
1498 |
{ |
{ |
1499 |
const int pos = head->read_avail; |
const int pos = head->read_avail; |
1500 |
if (!ccs_io_printf(head, "%s %s", keyword, ptr->handler->name) || |
if (!ccs_io_printf(head, "%s %s", keyword, ptr->handler->name) || |
1514 |
* Returns true on success, false otherwise. |
* Returns true on success, false otherwise. |
1515 |
*/ |
*/ |
1516 |
static bool ccs_print_mount_acl(struct ccs_io_buffer *head, |
static bool ccs_print_mount_acl(struct ccs_io_buffer *head, |
1517 |
struct ccs_mount_acl *ptr) |
const struct ccs_mount_acl *ptr) |
1518 |
{ |
{ |
1519 |
const int pos = head->read_avail; |
const int pos = head->read_avail; |
1520 |
if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_MOUNT) || |
if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_MOUNT) || |
1538 |
* Returns true on success, false otherwise. |
* Returns true on success, false otherwise. |
1539 |
*/ |
*/ |
1540 |
static bool ccs_print_entry(struct ccs_io_buffer *head, |
static bool ccs_print_entry(struct ccs_io_buffer *head, |
1541 |
struct ccs_acl_info *ptr) |
const struct ccs_acl_info *ptr) |
1542 |
{ |
{ |
1543 |
const u8 acl_type = ptr->type; |
const u8 acl_type = ptr->type; |
1544 |
if (ptr->is_deleted) |
if (ptr->is_deleted) |
1898 |
list_entry(mpos, struct ccs_acl_head, list); |
list_entry(mpos, struct ccs_acl_head, list); |
1899 |
if (ptr->is_deleted) |
if (ptr->is_deleted) |
1900 |
continue; |
continue; |
1901 |
|
w[2] = buffer; |
1902 |
if (idx == CCS_PATH_GROUP) { |
if (idx == CCS_PATH_GROUP) { |
1903 |
w[2] = container_of(ptr, struct ccs_path_group, |
w[2] = container_of(ptr, struct ccs_path_group, |
1904 |
head)->member_name->name; |
head)->member_name->name; |
1905 |
} else if (idx == CCS_NUMBER_GROUP) { |
} else if (idx == CCS_NUMBER_GROUP) { |
|
w[2] = buffer; |
|
1906 |
ccs_print_number(buffer, sizeof(buffer), |
ccs_print_number(buffer, sizeof(buffer), |
1907 |
&container_of |
&container_of |
1908 |
(ptr, struct ccs_number_group, |
(ptr, struct ccs_number_group, |
1911 |
struct ccs_address_group *member = |
struct ccs_address_group *member = |
1912 |
container_of(ptr, typeof(*member), |
container_of(ptr, typeof(*member), |
1913 |
head); |
head); |
|
w[2] = buffer; |
|
1914 |
if (member->is_ipv6) |
if (member->is_ipv6) |
1915 |
ccs_print_ipv6(buffer, sizeof(buffer), |
ccs_print_ipv6(buffer, sizeof(buffer), |
1916 |
member->min.ipv6, |
member->min.ipv6, |
2040 |
head->read = ccs_read_global_domain; |
head->read = ccs_read_global_domain; |
2041 |
} |
} |
2042 |
|
|
|
/** |
|
|
* ccs_get_argv0 - Get argv[0]. |
|
|
* |
|
|
* @ee: Pointer to "struct ccs_execve". |
|
|
* |
|
|
* Returns true on success, false otherwise. |
|
|
*/ |
|
|
static bool ccs_get_argv0(struct ccs_execve *ee) |
|
|
{ |
|
|
struct linux_binprm *bprm = ee->bprm; |
|
|
char *arg_ptr = ee->tmp; |
|
|
int arg_len = 0; |
|
|
unsigned long pos = bprm->p; |
|
|
int offset = pos % PAGE_SIZE; |
|
|
bool done = false; |
|
|
if (!bprm->argc) |
|
|
goto out; |
|
|
while (1) { |
|
|
if (!ccs_dump_page(bprm, pos, &ee->dump)) |
|
|
goto out; |
|
|
pos += PAGE_SIZE - offset; |
|
|
/* Read. */ |
|
|
while (offset < PAGE_SIZE) { |
|
|
const char *kaddr = ee->dump.data; |
|
|
const unsigned char c = kaddr[offset++]; |
|
|
if (c && arg_len < CCS_EXEC_TMPSIZE - 10) { |
|
|
if (c == '\\') { |
|
|
arg_ptr[arg_len++] = '\\'; |
|
|
arg_ptr[arg_len++] = '\\'; |
|
|
} else if (c > ' ' && c < 127) { |
|
|
arg_ptr[arg_len++] = c; |
|
|
} else { |
|
|
arg_ptr[arg_len++] = '\\'; |
|
|
arg_ptr[arg_len++] = (c >> 6) + '0'; |
|
|
arg_ptr[arg_len++] |
|
|
= ((c >> 3) & 7) + '0'; |
|
|
arg_ptr[arg_len++] = (c & 7) + '0'; |
|
|
} |
|
|
} else { |
|
|
arg_ptr[arg_len] = '\0'; |
|
|
done = true; |
|
|
break; |
|
|
} |
|
|
} |
|
|
offset = 0; |
|
|
if (done) |
|
|
break; |
|
|
} |
|
|
return true; |
|
|
out: |
|
|
return false; |
|
|
} |
|
|
|
|
2043 |
/* Wait queue for ccs_query_list. */ |
/* Wait queue for ccs_query_list. */ |
2044 |
static DECLARE_WAIT_QUEUE_HEAD(ccs_query_wait); |
static DECLARE_WAIT_QUEUE_HEAD(ccs_query_wait); |
2045 |
|
|
2070 |
vsnprintf(buffer + pos, len - pos - 1, fmt, args); |
vsnprintf(buffer + pos, len - pos - 1, fmt, args); |
2071 |
va_end(args); |
va_end(args); |
2072 |
} |
} |
2073 |
|
|
2074 |
|
static void ccs_truncate(char *str) |
2075 |
|
{ |
2076 |
|
while (* (unsigned char *) str > (unsigned char) ' ') |
2077 |
|
str++; |
2078 |
|
*str = '\0'; |
2079 |
|
} |
2080 |
|
|
2081 |
/** |
/** |
2082 |
* ccs_supervisor - Ask for the supervisor's decision. |
* ccs_supervisor - Ask for the supervisor's decision. |
2083 |
* |
* |
2107 |
char *buffer; |
char *buffer; |
2108 |
char *realpath = NULL; |
char *realpath = NULL; |
2109 |
char *argv0 = NULL; |
char *argv0 = NULL; |
2110 |
const char *symlink = NULL; |
char *symlink = NULL; |
2111 |
|
char *handler = NULL; |
2112 |
const struct ccs_preference *pref; |
const struct ccs_preference *pref; |
2113 |
if (!ccs_domain_quota_ok(r)) |
if (!ccs_domain_quota_ok(r)) |
2114 |
return 0; |
return 0; |
2115 |
|
header = ccs_init_log(&len, r); |
2116 |
|
if (!header) |
2117 |
|
return 0; |
2118 |
pref = ccs_profile(r->profile)->learning; |
pref = ccs_profile(r->profile)->learning; |
2119 |
|
/* strstr() will return NULL if ordering is wrong. */ |
2120 |
if (r->param_type == CCS_TYPE_PATH_ACL && |
if (r->param_type == CCS_TYPE_PATH_ACL && |
2121 |
r->param.path.operation == CCS_TYPE_EXECUTE) { |
r->param.path.operation == CCS_TYPE_EXECUTE) { |
|
if (pref->learning_exec_realpath) { |
|
|
struct file *file = r->ee->bprm->file; |
|
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) |
|
|
struct path path = { file->f_vfsmnt, |
|
|
file->f_dentry }; |
|
|
realpath = ccs_realpath_from_path(&path); |
|
|
#else |
|
|
realpath = ccs_realpath_from_path(&file-> |
|
|
f_path); |
|
|
#endif |
|
|
if (realpath) |
|
|
len += strlen(realpath); |
|
|
} |
|
2122 |
if (pref->learning_exec_argv0) { |
if (pref->learning_exec_argv0) { |
2123 |
if (ccs_get_argv0(r->ee)) { |
argv0 = strstr(header, " argv[]={ \""); |
2124 |
argv0 = r->ee->tmp; |
if (argv0) { |
2125 |
len += strlen(argv0); |
argv0 += 10; |
2126 |
|
ccs_truncate(argv0); |
2127 |
} |
} |
2128 |
} |
} |
2129 |
} |
if (pref->learning_exec_realpath) { |
2130 |
if (r->param_type == CCS_TYPE_PATH_ACL && |
realpath = strstr(header, |
2131 |
r->param.path.operation == CCS_TYPE_SYMLINK && |
" exec={ realpath=\""); |
2132 |
pref->learning_symlink_target) { |
if (realpath) { |
2133 |
symlink = r->obj->symlink_target->name; |
realpath += 8; |
2134 |
len += strlen(symlink); |
ccs_truncate(realpath); |
2135 |
} |
} |
2136 |
|
} |
2137 |
|
} else if (r->param_type == CCS_TYPE_PATH_ACL && |
2138 |
|
r->param.path.operation == CCS_TYPE_SYMLINK && |
2139 |
|
pref->learning_symlink_target) { |
2140 |
|
symlink = strstr(header, " symlink.target=\""); |
2141 |
|
if (symlink) |
2142 |
|
ccs_truncate(symlink + 1); |
2143 |
|
} |
2144 |
|
handler = strstr(header, "type=execute_handler"); |
2145 |
|
if (handler) |
2146 |
|
ccs_truncate(handler); |
2147 |
buffer = kmalloc(len, CCS_GFP_FLAGS); |
buffer = kmalloc(len, CCS_GFP_FLAGS); |
2148 |
if (buffer) { |
if (buffer) { |
|
const bool handler = (current->ccs_flags & |
|
|
CCS_TASK_IS_EXECUTE_HANDLER) |
|
|
!= 0; |
|
2149 |
va_start(args, fmt); |
va_start(args, fmt); |
2150 |
vsnprintf(buffer, len - 1, fmt, args); |
vsnprintf(buffer, len - 1, fmt, args); |
2151 |
va_end(args); |
va_end(args); |
2152 |
if (handler || realpath || argv0 || symlink) { |
if (handler || realpath || argv0 || symlink) { |
2153 |
ccs_addprintf(buffer, len, " if"); |
ccs_addprintf(buffer, len, " if"); |
2154 |
if (handler) |
if (handler) |
2155 |
ccs_addprintf(buffer, len, " task.type" |
ccs_addprintf(buffer, len, " task.%s", |
2156 |
"=execute_handler"); |
handler); |
2157 |
if (realpath) |
if (realpath) |
2158 |
ccs_addprintf(buffer, len, |
ccs_addprintf(buffer, len, " exec.%s", |
|
" exec.realpath=\"%s\"", |
|
2159 |
realpath); |
realpath); |
2160 |
if (argv0) |
if (argv0) |
2161 |
ccs_addprintf(buffer, len, |
ccs_addprintf(buffer, len, |
2162 |
" exec.argv[0]=\"%s\"", |
" exec.argv[0]=%s", |
2163 |
argv0); |
argv0); |
2164 |
if (symlink) |
if (symlink) |
2165 |
ccs_addprintf(buffer, len, |
ccs_addprintf(buffer, len, "%s", |
|
" symlink.target=\"%s\"", |
|
2166 |
symlink); |
symlink); |
2167 |
} |
} |
2168 |
ccs_normalize_line(buffer); |
ccs_normalize_line(buffer); |
2169 |
ccs_write_domain2(buffer, domain, false); |
ccs_write_domain2(buffer, domain, false); |
2170 |
kfree(buffer); |
kfree(buffer); |
2171 |
} |
} |
2172 |
kfree(realpath); |
kfree(header); |
2173 |
return 0; |
return 0; |
2174 |
} |
} |
2175 |
if (r->mode != CCS_CONFIG_ENFORCING) |
if (r->mode != CCS_CONFIG_ENFORCING) |