3 |
* |
* |
4 |
* Copyright (C) 2005-2010 NTT DATA CORPORATION |
* Copyright (C) 2005-2010 NTT DATA CORPORATION |
5 |
* |
* |
6 |
* Version: 1.7.2+ 2010/06/04 |
* Version: 1.8.0-pre 2010/08/01 |
7 |
* |
* |
8 |
* This file is applicable to both 2.4.30 and 2.6.11 and later. |
* This file is applicable to both 2.4.30 and 2.6.11 and later. |
9 |
* See README.ccs for ChangeLog. |
* See README.ccs for ChangeLog. |
13 |
#include "internal.h" |
#include "internal.h" |
14 |
|
|
15 |
static struct ccs_profile ccs_default_profile = { |
static struct ccs_profile ccs_default_profile = { |
|
.learning = &ccs_default_profile.preference, |
|
|
.permissive = &ccs_default_profile.preference, |
|
|
.enforcing = &ccs_default_profile.preference, |
|
|
.audit = &ccs_default_profile.preference, |
|
16 |
#ifdef CONFIG_CCSECURITY_AUDIT |
#ifdef CONFIG_CCSECURITY_AUDIT |
17 |
.preference.audit_max_grant_log = CONFIG_CCSECURITY_MAX_GRANT_LOG, |
.preference.audit_max_grant_log = CONFIG_CCSECURITY_MAX_GRANT_LOG, |
18 |
.preference.audit_max_reject_log = CONFIG_CCSECURITY_MAX_REJECT_LOG, |
.preference.audit_max_reject_log = CONFIG_CCSECURITY_MAX_REJECT_LOG, |
20 |
.preference.audit_task_info = true, |
.preference.audit_task_info = true, |
21 |
.preference.audit_path_info = true, |
.preference.audit_path_info = true, |
22 |
.preference.enforcing_penalty = 0, |
.preference.enforcing_penalty = 0, |
|
.preference.enforcing_verbose = true, |
|
23 |
.preference.learning_max_entry = CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY, |
.preference.learning_max_entry = CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY, |
|
.preference.learning_verbose = false, |
|
24 |
.preference.learning_exec_realpath = true, |
.preference.learning_exec_realpath = true, |
25 |
.preference.learning_exec_argv0 = true, |
.preference.learning_exec_argv0 = true, |
26 |
.preference.learning_symlink_target = true, |
.preference.learning_symlink_target = true, |
|
.preference.permissive_verbose = true |
|
27 |
}; |
}; |
28 |
|
|
29 |
/* Profile version. Currently only 20090903 is defined. */ |
/* Profile version. Currently only 20090903 is defined. */ |
33 |
static struct ccs_profile *ccs_profile_ptr[CCS_MAX_PROFILES]; |
static struct ccs_profile *ccs_profile_ptr[CCS_MAX_PROFILES]; |
34 |
|
|
35 |
/* String table for functionality that takes 4 modes. */ |
/* String table for functionality that takes 4 modes. */ |
36 |
static const char *ccs_mode[CCS_CONFIG_MAX_MODE] = { |
const char *ccs_mode[CCS_CONFIG_MAX_MODE] = { |
37 |
[CCS_CONFIG_DISABLED] = "disabled", |
[CCS_CONFIG_DISABLED] = "disabled", |
38 |
[CCS_CONFIG_LEARNING] = "learning", |
[CCS_CONFIG_LEARNING] = "learning", |
39 |
[CCS_CONFIG_PERMISSIVE] = "permissive", |
[CCS_CONFIG_PERMISSIVE] = "permissive", |
64 |
= "file::truncate", |
= "file::truncate", |
65 |
[CCS_MAC_FILE_SYMLINK] |
[CCS_MAC_FILE_SYMLINK] |
66 |
= "file::symlink", |
= "file::symlink", |
|
[CCS_MAC_FILE_REWRITE] |
|
|
= "file::rewrite", |
|
67 |
[CCS_MAC_FILE_MKBLOCK] |
[CCS_MAC_FILE_MKBLOCK] |
68 |
= "file::mkblock", |
= "file::mkblock", |
69 |
[CCS_MAC_FILE_MKCHAR] |
[CCS_MAC_FILE_MKCHAR] |
92 |
= "file::transit", |
= "file::transit", |
93 |
[CCS_MAC_ENVIRON] |
[CCS_MAC_ENVIRON] |
94 |
= "misc::env", |
= "misc::env", |
|
[CCS_MAC_NETWORK_UDP_BIND] |
|
|
= "network::inet_udp_bind", |
|
|
[CCS_MAC_NETWORK_UDP_CONNECT] |
|
|
= "network::inet_udp_connect", |
|
95 |
[CCS_MAC_NETWORK_TCP_BIND] |
[CCS_MAC_NETWORK_TCP_BIND] |
96 |
= "network::inet_tcp_bind", |
= "network::inet_tcp_bind", |
97 |
[CCS_MAC_NETWORK_TCP_LISTEN] |
[CCS_MAC_NETWORK_TCP_LISTEN] |
100 |
= "network::inet_tcp_connect", |
= "network::inet_tcp_connect", |
101 |
[CCS_MAC_NETWORK_TCP_ACCEPT] |
[CCS_MAC_NETWORK_TCP_ACCEPT] |
102 |
= "network::inet_tcp_accept", |
= "network::inet_tcp_accept", |
103 |
|
[CCS_MAC_NETWORK_UDP_BIND] |
104 |
|
= "network::inet_udp_bind", |
105 |
|
[CCS_MAC_NETWORK_UDP_SEND] |
106 |
|
= "network::inet_udp_send", |
107 |
|
[CCS_MAC_NETWORK_UDP_RECV] |
108 |
|
= "network::inet_udp_recv", |
109 |
[CCS_MAC_NETWORK_RAW_BIND] |
[CCS_MAC_NETWORK_RAW_BIND] |
110 |
= "network::inet_raw_bind", |
= "network::inet_raw_bind", |
111 |
[CCS_MAC_NETWORK_RAW_CONNECT] |
[CCS_MAC_NETWORK_RAW_SEND] |
112 |
= "network::inet_raw_connect", |
= "network::inet_raw_send", |
113 |
|
[CCS_MAC_NETWORK_RAW_RECV] |
114 |
|
= "network::inet_raw_recv", |
115 |
[CCS_MAC_SIGNAL] |
[CCS_MAC_SIGNAL] |
116 |
= "ipc::signal", |
= "ipc::signal", |
|
[CCS_MAX_MAC_INDEX + CCS_INET_STREAM_SOCKET_CREATE] |
|
|
= "capability::inet_tcp_create", |
|
|
[CCS_MAX_MAC_INDEX + CCS_INET_STREAM_SOCKET_LISTEN] |
|
|
= "capability::inet_tcp_listen", |
|
|
[CCS_MAX_MAC_INDEX + CCS_INET_STREAM_SOCKET_CONNECT] |
|
|
= "capability::inet_tcp_connect", |
|
|
[CCS_MAX_MAC_INDEX + CCS_USE_INET_DGRAM_SOCKET] |
|
|
= "capability::use_inet_udp", |
|
|
[CCS_MAX_MAC_INDEX + CCS_USE_INET_RAW_SOCKET] |
|
|
= "capability::use_inet_ip", |
|
117 |
[CCS_MAX_MAC_INDEX + CCS_USE_ROUTE_SOCKET] |
[CCS_MAX_MAC_INDEX + CCS_USE_ROUTE_SOCKET] |
118 |
= "capability::use_route", |
= "capability::use_route", |
119 |
[CCS_MAX_MAC_INDEX + CCS_USE_PACKET_SOCKET] |
[CCS_MAX_MAC_INDEX + CCS_USE_PACKET_SOCKET] |
120 |
= "capability::use_packet", |
= "capability::use_packet", |
|
[CCS_MAX_MAC_INDEX + CCS_SYS_MOUNT] |
|
|
= "capability::SYS_MOUNT", |
|
|
[CCS_MAX_MAC_INDEX + CCS_SYS_UMOUNT] |
|
|
= "capability::SYS_UMOUNT", |
|
121 |
[CCS_MAX_MAC_INDEX + CCS_SYS_REBOOT] |
[CCS_MAX_MAC_INDEX + CCS_SYS_REBOOT] |
122 |
= "capability::SYS_REBOOT", |
= "capability::SYS_REBOOT", |
|
[CCS_MAX_MAC_INDEX + CCS_SYS_CHROOT] |
|
|
= "capability::SYS_CHROOT", |
|
|
[CCS_MAX_MAC_INDEX + CCS_SYS_KILL] |
|
|
= "capability::SYS_KILL", |
|
123 |
[CCS_MAX_MAC_INDEX + CCS_SYS_VHANGUP] |
[CCS_MAX_MAC_INDEX + CCS_SYS_VHANGUP] |
124 |
= "capability::SYS_VHANGUP", |
= "capability::SYS_VHANGUP", |
125 |
[CCS_MAX_MAC_INDEX + CCS_SYS_SETTIME] |
[CCS_MAX_MAC_INDEX + CCS_SYS_SETTIME] |
130 |
= "capability::SYS_SETHOSTNAME", |
= "capability::SYS_SETHOSTNAME", |
131 |
[CCS_MAX_MAC_INDEX + CCS_USE_KERNEL_MODULE] |
[CCS_MAX_MAC_INDEX + CCS_USE_KERNEL_MODULE] |
132 |
= "capability::use_kernel_module", |
= "capability::use_kernel_module", |
|
[CCS_MAX_MAC_INDEX + CCS_CREATE_FIFO] |
|
|
= "capability::create_fifo", |
|
|
[CCS_MAX_MAC_INDEX + CCS_CREATE_BLOCK_DEV] |
|
|
= "capability::create_block_dev", |
|
|
[CCS_MAX_MAC_INDEX + CCS_CREATE_CHAR_DEV] |
|
|
= "capability::create_char_dev", |
|
|
[CCS_MAX_MAC_INDEX + CCS_CREATE_UNIX_SOCKET] |
|
|
= "capability::create_unix_socket", |
|
|
[CCS_MAX_MAC_INDEX + CCS_SYS_LINK] |
|
|
= "capability::SYS_LINK", |
|
|
[CCS_MAX_MAC_INDEX + CCS_SYS_SYMLINK] |
|
|
= "capability::SYS_SYMLINK", |
|
|
[CCS_MAX_MAC_INDEX + CCS_SYS_RENAME] |
|
|
= "capability::SYS_RENAME", |
|
|
[CCS_MAX_MAC_INDEX + CCS_SYS_UNLINK] |
|
|
= "capability::SYS_UNLINK", |
|
|
[CCS_MAX_MAC_INDEX + CCS_SYS_CHMOD] |
|
|
= "capability::SYS_CHMOD", |
|
|
[CCS_MAX_MAC_INDEX + CCS_SYS_CHOWN] |
|
|
= "capability::SYS_CHOWN", |
|
|
[CCS_MAX_MAC_INDEX + CCS_SYS_IOCTL] |
|
|
= "capability::SYS_IOCTL", |
|
133 |
[CCS_MAX_MAC_INDEX + CCS_SYS_KEXEC_LOAD] |
[CCS_MAX_MAC_INDEX + CCS_SYS_KEXEC_LOAD] |
134 |
= "capability::SYS_KEXEC_LOAD", |
= "capability::SYS_KEXEC_LOAD", |
|
[CCS_MAX_MAC_INDEX + CCS_SYS_PIVOT_ROOT] |
|
|
= "capability::SYS_PIVOT_ROOT", |
|
135 |
[CCS_MAX_MAC_INDEX + CCS_SYS_PTRACE] |
[CCS_MAX_MAC_INDEX + CCS_SYS_PTRACE] |
136 |
= "capability::SYS_PTRACE", |
= "capability::SYS_PTRACE", |
|
[CCS_MAX_MAC_INDEX + CCS_CONCEAL_MOUNT] |
|
|
= "capability::conceal_mount", |
|
137 |
[CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX |
[CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX |
138 |
+ CCS_MAC_CATEGORY_FILE] = "file", |
+ CCS_MAC_CATEGORY_FILE] = "file", |
139 |
[CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX |
[CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX |
240 |
head->r.w[head->r.w_pos++] = string; |
head->r.w[head->r.w_pos++] = string; |
241 |
ccs_flush(head); |
ccs_flush(head); |
242 |
} else |
} else |
243 |
WARN_ON(1); |
printk(KERN_WARNING "Too many words in a line.\n"); |
244 |
} |
} |
245 |
|
|
246 |
/** |
/** |
261 |
len = vsnprintf(head->read_buf + pos, size, fmt, args) + 1; |
len = vsnprintf(head->read_buf + pos, size, fmt, args) + 1; |
262 |
va_end(args); |
va_end(args); |
263 |
if (pos + len >= head->readbuf_size) { |
if (pos + len >= head->readbuf_size) { |
264 |
WARN_ON(1); |
printk(KERN_WARNING "Too many words in a line.\n"); |
265 |
return; |
return; |
266 |
} |
} |
267 |
head->r.avail += len; |
head->r.avail += len; |
301 |
ptr = ccs_profile_ptr[profile]; |
ptr = ccs_profile_ptr[profile]; |
302 |
if (!ptr && ccs_memory_ok(entry, sizeof(*entry))) { |
if (!ptr && ccs_memory_ok(entry, sizeof(*entry))) { |
303 |
ptr = entry; |
ptr = entry; |
|
ptr->audit = &ccs_default_profile.preference; |
|
|
ptr->learning = &ccs_default_profile.preference; |
|
|
ptr->permissive = &ccs_default_profile.preference; |
|
|
ptr->enforcing = &ccs_default_profile.preference; |
|
304 |
ptr->default_config = CCS_CONFIG_DISABLED | |
ptr->default_config = CCS_CONFIG_DISABLED | |
305 |
|
CCS_CONFIG_VERBOSE | |
306 |
CCS_CONFIG_WANT_GRANT_LOG | CCS_CONFIG_WANT_REJECT_LOG; |
CCS_CONFIG_WANT_GRANT_LOG | CCS_CONFIG_WANT_REJECT_LOG; |
307 |
memset(ptr->config, CCS_CONFIG_USE_DEFAULT, |
memset(ptr->config, CCS_CONFIG_USE_DEFAULT, |
308 |
sizeof(ptr->config)); |
sizeof(ptr->config)); |
335 |
if (ccs_profile_version != 20090903) |
if (ccs_profile_version != 20090903) |
336 |
panic("Profile version %u is not supported.\n", |
panic("Profile version %u is not supported.\n", |
337 |
ccs_profile_version); |
ccs_profile_version); |
338 |
printk(KERN_INFO "CCSecurity: 1.7.2+ 2010/06/04\n"); |
printk(KERN_INFO "CCSecurity: 1.8.0-pre 2010/08/01\n"); |
339 |
printk(KERN_INFO "Mandatory Access Control activated.\n"); |
printk(KERN_INFO "Mandatory Access Control activated.\n"); |
340 |
} |
} |
341 |
|
|
388 |
} |
} |
389 |
|
|
390 |
static void ccs_set_pref(const char *name, const char *value, |
static void ccs_set_pref(const char *name, const char *value, |
391 |
const bool use_default, struct ccs_profile *profile) |
struct ccs_profile *profile) |
392 |
{ |
{ |
|
struct ccs_preference **pref; |
|
|
bool *verbose; |
|
393 |
if (!strcmp(name, "audit")) { |
if (!strcmp(name, "audit")) { |
|
if (use_default) { |
|
|
pref = &profile->audit; |
|
|
goto set_default; |
|
|
} |
|
|
profile->audit = &profile->preference; |
|
394 |
#ifdef CONFIG_CCSECURITY_AUDIT |
#ifdef CONFIG_CCSECURITY_AUDIT |
395 |
ccs_set_uint(&profile->preference.audit_max_grant_log, value, |
ccs_set_uint(&profile->preference.audit_max_grant_log, value, |
396 |
"max_grant_log"); |
"max_grant_log"); |
404 |
return; |
return; |
405 |
} |
} |
406 |
if (!strcmp(name, "enforcing")) { |
if (!strcmp(name, "enforcing")) { |
|
if (use_default) { |
|
|
pref = &profile->enforcing; |
|
|
goto set_default; |
|
|
} |
|
|
profile->enforcing = &profile->preference; |
|
407 |
ccs_set_uint(&profile->preference.enforcing_penalty, value, |
ccs_set_uint(&profile->preference.enforcing_penalty, value, |
408 |
"penalty"); |
"penalty"); |
409 |
verbose = &profile->preference.enforcing_verbose; |
return; |
|
goto set_verbose; |
|
|
} |
|
|
if (!strcmp(name, "permissive")) { |
|
|
if (use_default) { |
|
|
pref = &profile->permissive; |
|
|
goto set_default; |
|
|
} |
|
|
profile->permissive = &profile->preference; |
|
|
verbose = &profile->preference.permissive_verbose; |
|
|
goto set_verbose; |
|
410 |
} |
} |
411 |
if (!strcmp(name, "learning")) { |
if (!strcmp(name, "learning")) { |
|
if (use_default) { |
|
|
pref = &profile->learning; |
|
|
goto set_default; |
|
|
} |
|
|
profile->learning = &profile->preference; |
|
412 |
ccs_set_uint(&profile->preference.learning_max_entry, value, |
ccs_set_uint(&profile->preference.learning_max_entry, value, |
413 |
"max_entry"); |
"max_entry"); |
414 |
ccs_set_bool(&profile->preference.learning_exec_realpath, |
ccs_set_bool(&profile->preference.learning_exec_realpath, |
417 |
"exec.argv0"); |
"exec.argv0"); |
418 |
ccs_set_bool(&profile->preference.learning_symlink_target, |
ccs_set_bool(&profile->preference.learning_symlink_target, |
419 |
value, "symlink.target"); |
value, "symlink.target"); |
420 |
verbose = &profile->preference.learning_verbose; |
return; |
|
goto set_verbose; |
|
421 |
} |
} |
|
return; |
|
|
set_default: |
|
|
*pref = &ccs_default_profile.preference; |
|
|
return; |
|
|
set_verbose: |
|
|
ccs_set_bool(verbose, value, "verbose"); |
|
422 |
} |
} |
423 |
|
|
424 |
static int ccs_set_mode(char *name, const char *value, const bool use_default, |
static int ccs_set_mode(char *name, const char *value, |
425 |
struct ccs_profile *profile) |
struct ccs_profile *profile) |
426 |
{ |
{ |
427 |
u8 i; |
u8 i; |
445 |
} else { |
} else { |
446 |
return -EINVAL; |
return -EINVAL; |
447 |
} |
} |
448 |
if (use_default) { |
if (strstr(value, "use_default")) { |
449 |
config = CCS_CONFIG_USE_DEFAULT; |
config = CCS_CONFIG_USE_DEFAULT; |
450 |
} else { |
} else { |
451 |
u8 mode; |
u8 mode; |
456 |
* 'config' from 'CCS_CONFIG_USE_DEAFULT'. |
* 'config' from 'CCS_CONFIG_USE_DEAFULT'. |
457 |
*/ |
*/ |
458 |
config = (config & ~7) | mode; |
config = (config & ~7) | mode; |
|
#ifdef CONFIG_CCSECURITY_AUDIT |
|
459 |
if (config != CCS_CONFIG_USE_DEFAULT) { |
if (config != CCS_CONFIG_USE_DEFAULT) { |
460 |
|
switch (ccs_find_yesno(value, "verbose")) { |
461 |
|
case 1: |
462 |
|
config |= CCS_CONFIG_VERBOSE; |
463 |
|
break; |
464 |
|
case 0: |
465 |
|
config &= ~CCS_CONFIG_VERBOSE; |
466 |
|
break; |
467 |
|
} |
468 |
|
#ifdef CONFIG_CCSECURITY_AUDIT |
469 |
switch (ccs_find_yesno(value, "grant_log")) { |
switch (ccs_find_yesno(value, "grant_log")) { |
470 |
case 1: |
case 1: |
471 |
config |= CCS_CONFIG_WANT_GRANT_LOG; |
config |= CCS_CONFIG_WANT_GRANT_LOG; |
482 |
config &= ~CCS_CONFIG_WANT_REJECT_LOG; |
config &= ~CCS_CONFIG_WANT_REJECT_LOG; |
483 |
break; |
break; |
484 |
} |
} |
|
} |
|
485 |
#endif |
#endif |
486 |
|
} |
487 |
} |
} |
488 |
if (i < CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX |
if (i < CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX |
489 |
+ CCS_MAX_MAC_CATEGORY_INDEX) |
+ CCS_MAX_MAC_CATEGORY_INDEX) |
503 |
static int ccs_write_profile(struct ccs_io_buffer *head) |
static int ccs_write_profile(struct ccs_io_buffer *head) |
504 |
{ |
{ |
505 |
char *data = head->write_buf; |
char *data = head->write_buf; |
506 |
bool use_default = false; |
unsigned int i; |
507 |
char *cp; |
char *cp; |
|
int i; |
|
508 |
struct ccs_profile *profile; |
struct ccs_profile *profile; |
509 |
if (sscanf(data, "PROFILE_VERSION=%u", &ccs_profile_version) == 1) |
if (sscanf(data, "PROFILE_VERSION=%u", &ccs_profile_version) == 1) |
510 |
return 0; |
return 0; |
511 |
i = simple_strtoul(data, &cp, 10); |
i = simple_strtoul(data, &cp, 10); |
512 |
if (data == cp) { |
if (*cp != '-') |
513 |
profile = &ccs_default_profile; |
return -EINVAL; |
514 |
} else { |
data = cp + 1; |
515 |
if (*cp != '-') |
profile = ccs_assign_profile(i); |
516 |
return -EINVAL; |
if (!profile) |
517 |
data = cp + 1; |
return -EINVAL; |
|
profile = ccs_assign_profile(i); |
|
|
if (!profile) |
|
|
return -EINVAL; |
|
|
} |
|
518 |
cp = strchr(data, '='); |
cp = strchr(data, '='); |
519 |
if (!cp) |
if (!cp) |
520 |
return -EINVAL; |
return -EINVAL; |
521 |
*cp++ = '\0'; |
*cp++ = '\0'; |
|
if (profile != &ccs_default_profile) |
|
|
use_default = strstr(cp, "use_default") != NULL; |
|
522 |
if (ccs_str_starts(&data, "PREFERENCE::")) { |
if (ccs_str_starts(&data, "PREFERENCE::")) { |
523 |
ccs_set_pref(data, cp, use_default, profile); |
ccs_set_pref(data, cp, profile); |
524 |
return 0; |
return 0; |
525 |
} |
} |
|
if (profile == &ccs_default_profile) |
|
|
return -EINVAL; |
|
526 |
if (!strcmp(data, "COMMENT")) { |
if (!strcmp(data, "COMMENT")) { |
527 |
const struct ccs_path_info *old_comment = profile->comment; |
const struct ccs_path_info *old_comment = profile->comment; |
528 |
profile->comment = ccs_get_name(cp); |
profile->comment = ccs_get_name(cp); |
529 |
ccs_put_name(old_comment); |
ccs_put_name(old_comment); |
530 |
return 0; |
return 0; |
531 |
} |
} |
532 |
return ccs_set_mode(data, cp, use_default, profile); |
return ccs_set_mode(data, cp, profile); |
533 |
} |
} |
534 |
|
|
535 |
static void ccs_print_preference(struct ccs_io_buffer *head, const int idx) |
static void ccs_print_preference(struct ccs_io_buffer *head, const int index) |
536 |
{ |
{ |
537 |
struct ccs_preference *pref = &ccs_default_profile.preference; |
struct ccs_profile *profile = ccs_profile_ptr[index]; |
538 |
const struct ccs_profile *profile = idx >= 0 ? |
struct ccs_preference *pref = &profile->preference; |
539 |
ccs_profile_ptr[idx] : NULL; |
ccs_io_printf(head, "%u-PREFERENCE::%s={ " |
|
char buffer[16] = ""; |
|
|
if (profile) { |
|
|
buffer[sizeof(buffer) - 1] = '\0'; |
|
|
snprintf(buffer, sizeof(buffer) - 1, "%u-", idx); |
|
|
} |
|
|
if (profile) { |
|
|
pref = profile->audit; |
|
|
if (pref == &ccs_default_profile.preference) |
|
|
goto skip0; |
|
|
} |
|
|
ccs_io_printf(head, "%sPREFERENCE::%s={ " |
|
540 |
#ifdef CONFIG_CCSECURITY_AUDIT |
#ifdef CONFIG_CCSECURITY_AUDIT |
541 |
"max_grant_log=%u max_reject_log=%u " |
"max_grant_log=%u max_reject_log=%u " |
542 |
#endif |
#endif |
543 |
"task_info=%s path_info=%s }\n", buffer, |
"task_info=%s path_info=%s }\n", index, |
544 |
"audit", |
"audit", |
545 |
#ifdef CONFIG_CCSECURITY_AUDIT |
#ifdef CONFIG_CCSECURITY_AUDIT |
546 |
pref->audit_max_grant_log, |
pref->audit_max_grant_log, |
548 |
#endif |
#endif |
549 |
ccs_yesno(pref->audit_task_info), |
ccs_yesno(pref->audit_task_info), |
550 |
ccs_yesno(pref->audit_path_info)); |
ccs_yesno(pref->audit_path_info)); |
551 |
skip0: |
ccs_io_printf(head, "%u-PREFERENCE::%s={ " |
552 |
if (profile) { |
"max_entry=%u exec.realpath=%s " |
|
pref = profile->learning; |
|
|
if (pref == &ccs_default_profile.preference) |
|
|
goto skip1; |
|
|
} |
|
|
ccs_io_printf(head, "%sPREFERENCE::%s={ " |
|
|
"verbose=%s max_entry=%u exec.realpath=%s " |
|
553 |
"exec.argv0=%s symlink.target=%s }\n", |
"exec.argv0=%s symlink.target=%s }\n", |
554 |
buffer, "learning", |
index, "learning", |
|
ccs_yesno(pref->learning_verbose), |
|
555 |
pref->learning_max_entry, |
pref->learning_max_entry, |
556 |
ccs_yesno(pref->learning_exec_realpath), |
ccs_yesno(pref->learning_exec_realpath), |
557 |
ccs_yesno(pref->learning_exec_argv0), |
ccs_yesno(pref->learning_exec_argv0), |
558 |
ccs_yesno(pref->learning_symlink_target)); |
ccs_yesno(pref->learning_symlink_target)); |
559 |
skip1: |
ccs_io_printf(head, "%u-PREFERENCE::%s={ penalty=%u }\n", index, |
560 |
if (profile) { |
"enforcing", pref->enforcing_penalty); |
|
pref = profile->permissive; |
|
|
if (pref == &ccs_default_profile.preference) |
|
|
goto skip2; |
|
|
} |
|
|
ccs_io_printf(head, "%sPREFERENCE::%s={ verbose=%s }\n", |
|
|
buffer, "permissive", |
|
|
ccs_yesno(pref->permissive_verbose)); |
|
|
skip2: |
|
|
if (profile) { |
|
|
pref = profile->enforcing; |
|
|
if (pref == &ccs_default_profile.preference) |
|
|
return; |
|
|
} |
|
|
ccs_io_printf(head, "%sPREFERENCE::%s={ verbose=%s " |
|
|
"penalty=%u }\n", buffer, "enforcing", |
|
|
ccs_yesno(pref->enforcing_verbose), |
|
|
pref->enforcing_penalty); |
|
561 |
} |
} |
562 |
|
|
563 |
static void ccs_print_config(struct ccs_io_buffer *head, const u8 config) |
static void ccs_print_config(struct ccs_io_buffer *head, const u8 config) |
564 |
{ |
{ |
565 |
ccs_io_printf(head, "={ mode=%s", ccs_mode[config & 3]); |
ccs_io_printf(head, "={ mode=%s verbose=%s", ccs_mode[config & 3], |
566 |
|
ccs_yesno(config & CCS_CONFIG_VERBOSE)); |
567 |
#ifdef CONFIG_CCSECURITY_AUDIT |
#ifdef CONFIG_CCSECURITY_AUDIT |
568 |
ccs_io_printf(head, " grant_log=%s reject_log=%s", |
ccs_io_printf(head, " grant_log=%s reject_log=%s", |
569 |
ccs_yesno(config & CCS_CONFIG_WANT_GRANT_LOG), |
ccs_yesno(config & CCS_CONFIG_WANT_GRANT_LOG), |
587 |
switch (head->r.step) { |
switch (head->r.step) { |
588 |
case 0: |
case 0: |
589 |
ccs_io_printf(head, "PROFILE_VERSION=%s\n", "20090903"); |
ccs_io_printf(head, "PROFILE_VERSION=%s\n", "20090903"); |
|
ccs_print_preference(head, -1); |
|
590 |
head->r.step++; |
head->r.step++; |
591 |
break; |
break; |
592 |
case 1: |
case 1: |
642 |
goto next; |
goto next; |
643 |
} |
} |
644 |
|
|
645 |
static bool ccs_same_manager_entry(const struct ccs_acl_head *a, |
static bool ccs_same_manager(const struct ccs_acl_head *a, |
646 |
const struct ccs_acl_head *b) |
const struct ccs_acl_head *b) |
647 |
{ |
{ |
648 |
return container_of(a, struct ccs_manager, head)->manager |
return container_of(a, struct ccs_manager, head)->manager |
649 |
== container_of(b, struct ccs_manager, head)->manager; |
== container_of(b, struct ccs_manager, head)->manager; |
674 |
return error; |
return error; |
675 |
error = ccs_update_policy(&e.head, sizeof(e), is_delete, |
error = ccs_update_policy(&e.head, sizeof(e), is_delete, |
676 |
&ccs_policy_list[CCS_ID_MANAGER], |
&ccs_policy_list[CCS_ID_MANAGER], |
677 |
ccs_same_manager_entry); |
ccs_same_manager); |
678 |
ccs_put_name(e.manager); |
ccs_put_name(e.manager); |
679 |
return error; |
return error; |
680 |
} |
} |
806 |
unsigned int pid; |
unsigned int pid; |
807 |
struct ccs_domain_info *domain = NULL; |
struct ccs_domain_info *domain = NULL; |
808 |
bool global_pid = false; |
bool global_pid = false; |
809 |
if (!strcmp(data, "allow_execute")) { |
if (!strcmp(data, "execute")) { |
810 |
head->r.print_execute_only = true; |
head->r.print_execute_only = true; |
811 |
return true; |
return true; |
812 |
} |
} |
837 |
return true; /* Do nothing if open(O_WRONLY). */ |
return true; /* Do nothing if open(O_WRONLY). */ |
838 |
memset(&head->r, 0, sizeof(head->r)); |
memset(&head->r, 0, sizeof(head->r)); |
839 |
head->r.print_this_domain_only = true; |
head->r.print_this_domain_only = true; |
840 |
head->r.eof = !domain; |
if (domain) |
841 |
head->r.domain = &domain->list; |
head->r.domain = &domain->list; |
842 |
|
else |
843 |
|
head->r.eof = true; |
844 |
ccs_io_printf(head, "# select %s\n", data); |
ccs_io_printf(head, "# select %s\n", data); |
845 |
if (domain && domain->is_deleted) |
if (domain && domain->is_deleted) |
846 |
ccs_set_string(head, "# This is a deleted domain.\n"); |
ccs_set_string(head, "# This is a deleted domain.\n"); |
854 |
const char *keyword; |
const char *keyword; |
855 |
int (*write) (char *, struct ccs_domain_info *, |
int (*write) (char *, struct ccs_domain_info *, |
856 |
struct ccs_condition *, const bool); |
struct ccs_condition *, const bool); |
857 |
} ccs_callback[5] = { |
} ccs_callback[4] = { |
858 |
{ CCS_KEYWORD_ALLOW_NETWORK, ccs_write_network }, |
{ "network ", ccs_write_network }, |
859 |
{ CCS_KEYWORD_ALLOW_ENV, ccs_write_env }, |
{ "misc ", ccs_write_misc }, |
860 |
{ CCS_KEYWORD_ALLOW_CAPABILITY, ccs_write_capability }, |
{ "capability ", ccs_write_capability }, |
861 |
{ CCS_KEYWORD_ALLOW_SIGNAL, ccs_write_signal }, |
{ "ipc ", ccs_write_ipc }, |
|
{ CCS_KEYWORD_ALLOW_MOUNT, ccs_write_mount } |
|
862 |
}; |
}; |
863 |
int (*write) (char *, struct ccs_domain_info *, struct ccs_condition *, |
int (*write) (char *, struct ccs_domain_info *, struct ccs_condition *, |
864 |
const bool) = ccs_write_file; |
const bool) = ccs_write_file; |
871 |
if (!cond) |
if (!cond) |
872 |
return -EINVAL; |
return -EINVAL; |
873 |
} |
} |
874 |
for (i = 0; i < 5; i++) { |
for (i = 0; i < 4; i++) { |
875 |
if (!ccs_str_starts(&data, ccs_callback[i].keyword)) |
if (!ccs_str_starts(&data, ccs_callback[i].keyword)) |
876 |
continue; |
continue; |
877 |
write = ccs_callback[i].write; |
write = ccs_callback[i].write; |
885 |
|
|
886 |
static const char *ccs_dif[CCS_MAX_DOMAIN_INFO_FLAGS] = { |
static const char *ccs_dif[CCS_MAX_DOMAIN_INFO_FLAGS] = { |
887 |
[CCS_DIF_QUOTA_WARNED] = CCS_KEYWORD_QUOTA_EXCEEDED "\n", |
[CCS_DIF_QUOTA_WARNED] = CCS_KEYWORD_QUOTA_EXCEEDED "\n", |
|
[CCS_DIF_IGNORE_GLOBAL] = CCS_KEYWORD_IGNORE_GLOBAL "\n", |
|
|
[CCS_DIF_IGNORE_GLOBAL_ALLOW_READ] |
|
|
= CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n", |
|
|
[CCS_DIF_IGNORE_GLOBAL_ALLOW_ENV] |
|
|
= CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_ENV "\n", |
|
888 |
[CCS_DIF_TRANSITION_FAILED] = CCS_KEYWORD_TRANSITION_FAILED "\n" |
[CCS_DIF_TRANSITION_FAILED] = CCS_KEYWORD_TRANSITION_FAILED "\n" |
889 |
}; |
}; |
890 |
|
|
918 |
else if (is_select) |
else if (is_select) |
919 |
domain = ccs_find_domain(data); |
domain = ccs_find_domain(data); |
920 |
else |
else |
921 |
domain = ccs_assign_domain(data, 0); |
domain = ccs_assign_domain(data, 0, 0); |
922 |
head->w.domain = domain; |
head->w.domain = domain; |
923 |
return 0; |
return 0; |
924 |
} |
} |
931 |
domain->profile = (u8) profile; |
domain->profile = (u8) profile; |
932 |
return 0; |
return 0; |
933 |
} |
} |
934 |
|
if (sscanf(data, CCS_KEYWORD_USE_GROUP "%u", &profile) == 1 |
935 |
|
&& profile < CCS_MAX_ACL_GROUPS) { |
936 |
|
domain->group = (u8) profile; |
937 |
|
return 0; |
938 |
|
} |
939 |
for (profile = 0; profile < CCS_MAX_DOMAIN_INFO_FLAGS; profile++) { |
for (profile = 0; profile < CCS_MAX_DOMAIN_INFO_FLAGS; profile++) { |
940 |
const char *cp = ccs_dif[profile]; |
const char *cp = ccs_dif[profile]; |
941 |
if (strncmp(data, cp, strlen(cp) - 1)) |
if (strncmp(data, cp, strlen(cp) - 1)) |
1180 |
return bit; |
return bit; |
1181 |
} |
} |
1182 |
|
|
1183 |
|
static void ccs_set_group(struct ccs_io_buffer *head) |
1184 |
|
{ |
1185 |
|
if (head->type == CCS_EXCEPTIONPOLICY) |
1186 |
|
ccs_io_printf(head, "acl_group %u ", head->r.group_index); |
1187 |
|
} |
1188 |
|
|
1189 |
/** |
/** |
1190 |
* ccs_print_entry - Print an ACL entry. |
* ccs_print_entry - Print an ACL entry. |
1191 |
* |
* |
1217 |
if (head->r.print_execute_only && |
if (head->r.print_execute_only && |
1218 |
bit != CCS_TYPE_EXECUTE && bit != CCS_TYPE_TRANSIT) |
bit != CCS_TYPE_EXECUTE && bit != CCS_TYPE_TRANSIT) |
1219 |
continue; |
continue; |
|
/* Print "read/write" instead of "read" and "write". */ |
|
|
if ((bit == CCS_TYPE_READ || bit == CCS_TYPE_WRITE) |
|
|
&& (perm & (1 << CCS_TYPE_READ_WRITE))) |
|
|
continue; |
|
1220 |
break; |
break; |
1221 |
} |
} |
1222 |
if (bit >= CCS_MAX_PATH_OPERATION) |
if (bit >= CCS_MAX_PATH_OPERATION) |
1223 |
goto done; |
goto done; |
1224 |
ccs_io_printf(head, "allow_%s", ccs_path_keyword[bit]); |
ccs_set_group(head); |
1225 |
|
ccs_set_string(head, "file "); |
1226 |
|
ccs_set_string(head, ccs_path_keyword[bit]); |
1227 |
ccs_print_name_union(head, &ptr->name); |
ccs_print_name_union(head, &ptr->name); |
1228 |
} else if (acl_type == CCS_TYPE_EXECUTE_HANDLER || |
} else if (acl_type == CCS_TYPE_EXECUTE_HANDLER || |
1229 |
acl_type == CCS_TYPE_DENIED_EXECUTE_HANDLER) { |
acl_type == CCS_TYPE_DENIED_EXECUTE_HANDLER) { |
1230 |
struct ccs_execute_handler *ptr |
struct ccs_execute_handler *ptr |
1231 |
= container_of(acl, typeof(*ptr), head); |
= container_of(acl, typeof(*ptr), head); |
1232 |
|
ccs_set_group(head); |
1233 |
ccs_io_printf(head, "%s ", |
ccs_io_printf(head, "%s ", |
1234 |
acl_type == CCS_TYPE_EXECUTE_HANDLER ? |
acl_type == CCS_TYPE_EXECUTE_HANDLER ? |
1235 |
CCS_KEYWORD_EXECUTE_HANDLER : |
CCS_KEYWORD_EXECUTE_HANDLER : |
1243 |
bit = ccs_fns(ptr->perm, bit); |
bit = ccs_fns(ptr->perm, bit); |
1244 |
if (bit >= CCS_MAX_MKDEV_OPERATION) |
if (bit >= CCS_MAX_MKDEV_OPERATION) |
1245 |
goto done; |
goto done; |
1246 |
ccs_io_printf(head, "allow_%s", ccs_mkdev_keyword[bit]); |
ccs_set_group(head); |
1247 |
|
ccs_set_string(head, "file "); |
1248 |
|
ccs_set_string(head, ccs_mkdev_keyword[bit]); |
1249 |
ccs_print_name_union(head, &ptr->name); |
ccs_print_name_union(head, &ptr->name); |
1250 |
ccs_print_number_union(head, &ptr->mode); |
ccs_print_number_union(head, &ptr->mode); |
1251 |
ccs_print_number_union(head, &ptr->major); |
ccs_print_number_union(head, &ptr->major); |
1256 |
bit = ccs_fns(ptr->perm, bit); |
bit = ccs_fns(ptr->perm, bit); |
1257 |
if (bit >= CCS_MAX_PATH2_OPERATION) |
if (bit >= CCS_MAX_PATH2_OPERATION) |
1258 |
goto done; |
goto done; |
1259 |
ccs_io_printf(head, "allow_%s", ccs_path2_keyword[bit]); |
ccs_set_group(head); |
1260 |
|
ccs_set_string(head, "file "); |
1261 |
|
ccs_set_string(head, ccs_path2_keyword[bit]); |
1262 |
ccs_print_name_union(head, &ptr->name1); |
ccs_print_name_union(head, &ptr->name1); |
1263 |
ccs_print_name_union(head, &ptr->name2); |
ccs_print_name_union(head, &ptr->name2); |
1264 |
} else if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) { |
} else if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) { |
1267 |
bit = ccs_fns(ptr->perm, bit); |
bit = ccs_fns(ptr->perm, bit); |
1268 |
if (bit >= CCS_MAX_PATH_NUMBER_OPERATION) |
if (bit >= CCS_MAX_PATH_NUMBER_OPERATION) |
1269 |
goto done; |
goto done; |
1270 |
ccs_io_printf(head, "allow_%s", |
ccs_set_group(head); |
1271 |
ccs_path_number_keyword[bit]); |
ccs_set_string(head, "file "); |
1272 |
|
ccs_set_string(head, ccs_path_number_keyword[bit]); |
1273 |
ccs_print_name_union(head, &ptr->name); |
ccs_print_name_union(head, &ptr->name); |
1274 |
ccs_print_number_union(head, &ptr->number); |
ccs_print_number_union(head, &ptr->number); |
1275 |
} else if (acl_type == CCS_TYPE_ENV_ACL) { |
} else if (acl_type == CCS_TYPE_ENV_ACL) { |
1276 |
struct ccs_env_acl *ptr = |
struct ccs_env_acl *ptr = |
1277 |
container_of(acl, typeof(*ptr), head); |
container_of(acl, typeof(*ptr), head); |
1278 |
ccs_set_string(head, CCS_KEYWORD_ALLOW_ENV); |
ccs_set_group(head); |
1279 |
|
ccs_set_string(head, "misc env "); |
1280 |
ccs_set_string(head, ptr->env->name); |
ccs_set_string(head, ptr->env->name); |
1281 |
} else if (acl_type == CCS_TYPE_CAPABILITY_ACL) { |
} else if (acl_type == CCS_TYPE_CAPABILITY_ACL) { |
1282 |
struct ccs_capability_acl *ptr = |
struct ccs_capability_acl *ptr = |
1283 |
container_of(acl, typeof(*ptr), head); |
container_of(acl, typeof(*ptr), head); |
1284 |
ccs_set_string(head, CCS_KEYWORD_ALLOW_CAPABILITY); |
ccs_set_group(head); |
1285 |
|
ccs_set_string(head, "capability "); |
1286 |
ccs_set_string(head, ccs_cap2keyword(ptr->operation)); |
ccs_set_string(head, ccs_cap2keyword(ptr->operation)); |
1287 |
} else if (acl_type == CCS_TYPE_IP_NETWORK_ACL) { |
} else if (acl_type == CCS_TYPE_IP_NETWORK_ACL) { |
1288 |
struct ccs_ip_network_acl *ptr = |
struct ccs_ip_network_acl *ptr = |
1290 |
bit = ccs_fns(ptr->perm, bit); |
bit = ccs_fns(ptr->perm, bit); |
1291 |
if (bit >= CCS_MAX_NETWORK_OPERATION) |
if (bit >= CCS_MAX_NETWORK_OPERATION) |
1292 |
goto done; |
goto done; |
1293 |
ccs_io_printf(head, CCS_KEYWORD_ALLOW_NETWORK "%s ", |
ccs_set_group(head); |
1294 |
ccs_net_keyword[bit]); |
ccs_set_string(head, "network "); |
1295 |
|
ccs_set_string(head, ccs_net_protocol_keyword[ptr->protocol]); |
1296 |
|
ccs_set_space(head); |
1297 |
|
ccs_set_string(head, ccs_net_keyword[bit]); |
1298 |
|
ccs_set_space(head); |
1299 |
switch (ptr->address_type) { |
switch (ptr->address_type) { |
1300 |
char buf[128]; |
char buf[128]; |
1301 |
case CCS_IP_ADDRESS_TYPE_ADDRESS_GROUP: |
case CCS_IP_ADDRESS_TYPE_ADDRESS_GROUP: |
1318 |
} else if (acl_type == CCS_TYPE_SIGNAL_ACL) { |
} else if (acl_type == CCS_TYPE_SIGNAL_ACL) { |
1319 |
struct ccs_signal_acl *ptr = |
struct ccs_signal_acl *ptr = |
1320 |
container_of(acl, typeof(*ptr), head); |
container_of(acl, typeof(*ptr), head); |
1321 |
ccs_io_printf(head, CCS_KEYWORD_ALLOW_SIGNAL "%u ", ptr->sig); |
ccs_set_group(head); |
1322 |
|
ccs_set_string(head, "ipc signal "); |
1323 |
|
ccs_io_printf(head, "%u ", ptr->sig); |
1324 |
ccs_set_string(head, ptr->domainname->name); |
ccs_set_string(head, ptr->domainname->name); |
1325 |
} else if (acl_type == CCS_TYPE_MOUNT_ACL) { |
} else if (acl_type == CCS_TYPE_MOUNT_ACL) { |
1326 |
struct ccs_mount_acl *ptr = |
struct ccs_mount_acl *ptr = |
1327 |
container_of(acl, typeof(*ptr), head); |
container_of(acl, typeof(*ptr), head); |
1328 |
ccs_io_printf(head, "allow_mount"); |
ccs_set_group(head); |
1329 |
|
ccs_io_printf(head, "file mount"); |
1330 |
ccs_print_name_union(head, &ptr->dev_name); |
ccs_print_name_union(head, &ptr->dev_name); |
1331 |
ccs_print_name_union(head, &ptr->dir_name); |
ccs_print_name_union(head, &ptr->dir_name); |
1332 |
ccs_print_name_union(head, &ptr->fs_type); |
ccs_print_name_union(head, &ptr->fs_type); |
1406 |
ccs_set_lf(head); |
ccs_set_lf(head); |
1407 |
ccs_io_printf(head, CCS_KEYWORD_USE_PROFILE "%u\n", |
ccs_io_printf(head, CCS_KEYWORD_USE_PROFILE "%u\n", |
1408 |
domain->profile); |
domain->profile); |
1409 |
|
ccs_io_printf(head, CCS_KEYWORD_USE_GROUP "%u\n", |
1410 |
|
domain->group); |
1411 |
for (i = 0; i < CCS_MAX_DOMAIN_INFO_FLAGS; i++) |
for (i = 0; i < CCS_MAX_DOMAIN_INFO_FLAGS; i++) |
1412 |
if (domain->flags[i]) |
if (domain->flags[i]) |
1413 |
ccs_set_string(head, ccs_dif[i]); |
ccs_set_string(head, ccs_dif[i]); |
1602 |
static const struct { |
static const struct { |
1603 |
const char *keyword; |
const char *keyword; |
1604 |
int (*write) (char *, const bool); |
int (*write) (char *, const bool); |
1605 |
} ccs_callback[4] = { |
} ccs_callback[3] = { |
1606 |
{ CCS_KEYWORD_AGGREGATOR, ccs_write_aggregator }, |
{ CCS_KEYWORD_AGGREGATOR, ccs_write_aggregator }, |
1607 |
{ CCS_KEYWORD_FILE_PATTERN, ccs_write_pattern }, |
{ CCS_KEYWORD_FILE_PATTERN, ccs_write_pattern }, |
|
{ CCS_KEYWORD_DENY_REWRITE, ccs_write_no_rewrite }, |
|
1608 |
{ CCS_KEYWORD_DENY_AUTOBIND, ccs_write_reserved_port } |
{ CCS_KEYWORD_DENY_AUTOBIND, ccs_write_reserved_port } |
1609 |
}; |
}; |
1610 |
for (i = 0; i < 4; i++) { |
for (i = 0; i < 3; i++) |
1611 |
if (ccs_str_starts(&data, ccs_callback[i].keyword)) |
if (ccs_str_starts(&data, ccs_callback[i].keyword)) |
1612 |
return ccs_callback[i].write(data, is_delete); |
return ccs_callback[i].write(data, is_delete); |
1613 |
} |
for (i = 0; i < CCS_MAX_TRANSITION_TYPE; i++) |
|
for (i = 0; i < CCS_MAX_TRANSITION_TYPE; i++) { |
|
1614 |
if (ccs_str_starts(&data, ccs_transition_type[i])) |
if (ccs_str_starts(&data, ccs_transition_type[i])) |
1615 |
return ccs_write_transition_control(data, is_delete, |
return ccs_write_transition_control(data, is_delete, |
1616 |
i); |
i); |
1617 |
} |
for (i = 0; i < CCS_MAX_GROUP; i++) |
|
for (i = 0; i < CCS_MAX_GROUP; i++) { |
|
1618 |
if (ccs_str_starts(&data, ccs_group_name[i])) |
if (ccs_str_starts(&data, ccs_group_name[i])) |
1619 |
return ccs_write_group(data, is_delete, i); |
return ccs_write_group(data, is_delete, i); |
1620 |
|
if (ccs_str_starts(&data, "acl_group ")) { |
1621 |
|
unsigned int group; |
1622 |
|
if (sscanf(data, "%u", &group) == 1 && |
1623 |
|
group < CCS_MAX_ACL_GROUPS) { |
1624 |
|
data = strchr(data, ' '); |
1625 |
|
if (data) |
1626 |
|
return ccs_write_domain2(data + 1, |
1627 |
|
&ccs_acl_group[group], |
1628 |
|
is_delete); |
1629 |
|
} |
1630 |
} |
} |
1631 |
return ccs_write_domain2(data, &ccs_global_domain, is_delete); |
return -EINVAL; |
1632 |
} |
} |
1633 |
|
|
1634 |
/** |
/** |
1739 |
ccs_set_string(head, ptr->pattern->name); |
ccs_set_string(head, ptr->pattern->name); |
1740 |
} |
} |
1741 |
break; |
break; |
|
case CCS_ID_NO_REWRITE: |
|
|
{ |
|
|
struct ccs_no_rewrite *ptr = |
|
|
container_of(acl, typeof(*ptr), head); |
|
|
ccs_set_string(head, CCS_KEYWORD_DENY_REWRITE); |
|
|
ccs_set_string(head, ptr->pattern->name); |
|
|
} |
|
|
break; |
|
1742 |
case CCS_ID_RESERVEDPORT: |
case CCS_ID_RESERVEDPORT: |
1743 |
{ |
{ |
1744 |
struct ccs_reserved *ptr = |
struct ccs_reserved *ptr = |
1782 |
head->r.step++; |
head->r.step++; |
1783 |
if (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP) |
if (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP) |
1784 |
return; |
return; |
1785 |
head->r.eof = ccs_read_domain2(head, &ccs_global_domain); |
while (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP |
1786 |
|
+ CCS_MAX_ACL_GROUPS) { |
1787 |
|
head->r.group_index = head->r.step - CCS_MAX_POLICY |
1788 |
|
- CCS_MAX_GROUP; |
1789 |
|
if (!ccs_read_domain2(head, |
1790 |
|
&ccs_acl_group[head->r.group_index])) |
1791 |
|
return; |
1792 |
|
head->r.step++; |
1793 |
|
} |
1794 |
|
head->r.eof = true; |
1795 |
} |
} |
1796 |
|
|
1797 |
/* Wait queue for ccs_query_list. */ |
/* Wait queue for ccs_query_list. */ |
1801 |
static DEFINE_SPINLOCK(ccs_query_list_lock); |
static DEFINE_SPINLOCK(ccs_query_list_lock); |
1802 |
|
|
1803 |
/* Structure for query. */ |
/* Structure for query. */ |
1804 |
struct ccs_query_entry { |
struct ccs_query { |
1805 |
struct list_head list; |
struct list_head list; |
1806 |
char *query; |
char *query; |
1807 |
int query_len; |
int query_len; |
1810 |
int answer; |
int answer; |
1811 |
}; |
}; |
1812 |
|
|
1813 |
/* The list for "struct ccs_query_entry". */ |
/* The list for "struct ccs_query". */ |
1814 |
static LIST_HEAD(ccs_query_list); |
static LIST_HEAD(ccs_query_list); |
1815 |
|
|
1816 |
/* Number of "struct file" referring /proc/ccs/query interface. */ |
/* Number of "struct file" referring /proc/ccs/query interface. */ |
1841 |
int pos; |
int pos; |
1842 |
int len; |
int len; |
1843 |
static unsigned int ccs_serial; |
static unsigned int ccs_serial; |
1844 |
struct ccs_query_entry *ccs_query_entry = NULL; |
struct ccs_query *entry = NULL; |
1845 |
bool quota_exceeded = false; |
bool quota_exceeded = false; |
1846 |
char *header; |
char *header; |
1847 |
struct ccs_domain_info * const domain = ccs_current_domain(); |
struct ccs_domain_info * const domain = ccs_current_domain(); |
1860 |
header = ccs_init_log(&len, r); |
header = ccs_init_log(&len, r); |
1861 |
if (!header) |
if (!header) |
1862 |
return 0; |
return 0; |
1863 |
pref = ccs_profile(r->profile)->learning; |
pref = &ccs_profile(r->profile)->preference; |
1864 |
/* strstr() will return NULL if ordering is wrong. */ |
/* strstr() will return NULL if ordering is wrong. */ |
1865 |
if (r->param_type == CCS_TYPE_PATH_ACL && |
if (r->param_type == CCS_TYPE_PATH_ACL && |
1866 |
r->param.path.operation == CCS_TYPE_EXECUTE) { |
r->param.path.operation == CCS_TYPE_EXECUTE) { |
1923 |
int i; |
int i; |
1924 |
if (current->ccs_flags & CCS_DONT_SLEEP_ON_ENFORCE_ERROR) |
if (current->ccs_flags & CCS_DONT_SLEEP_ON_ENFORCE_ERROR) |
1925 |
return -EPERM; |
return -EPERM; |
1926 |
for (i = 0; i < ccs_profile(domain->profile)->enforcing-> |
for (i = 0; i < ccs_profile(domain->profile)->preference. |
1927 |
enforcing_penalty; i++) { |
enforcing_penalty; i++) { |
1928 |
set_current_state(TASK_INTERRUPTIBLE); |
set_current_state(TASK_INTERRUPTIBLE); |
1929 |
schedule_timeout(HZ / 10); |
schedule_timeout(HZ / 10); |
1933 |
header = ccs_init_log(&len, r); |
header = ccs_init_log(&len, r); |
1934 |
if (!header) |
if (!header) |
1935 |
goto out; |
goto out; |
1936 |
ccs_query_entry = kzalloc(sizeof(*ccs_query_entry), CCS_GFP_FLAGS); |
entry = kzalloc(sizeof(*entry), CCS_GFP_FLAGS); |
1937 |
if (!ccs_query_entry) |
if (!entry) |
1938 |
goto out; |
goto out; |
1939 |
len = ccs_round2(len); |
len = ccs_round2(len); |
1940 |
ccs_query_entry->query = kzalloc(len, CCS_GFP_FLAGS); |
entry->query = kzalloc(len, CCS_GFP_FLAGS); |
1941 |
if (!ccs_query_entry->query) |
if (!entry->query) |
1942 |
goto out; |
goto out; |
|
INIT_LIST_HEAD(&ccs_query_entry->list); |
|
1943 |
spin_lock(&ccs_query_list_lock); |
spin_lock(&ccs_query_list_lock); |
1944 |
if (ccs_quota_for_query && ccs_query_memory_size + len + |
if (ccs_quota_for_query && ccs_query_memory_size + len + |
1945 |
sizeof(*ccs_query_entry) >= ccs_quota_for_query) { |
sizeof(*entry) >= ccs_quota_for_query) { |
1946 |
quota_exceeded = true; |
quota_exceeded = true; |
1947 |
} else { |
} else { |
1948 |
ccs_query_memory_size += len + sizeof(*ccs_query_entry); |
ccs_query_memory_size += len + sizeof(*entry); |
1949 |
ccs_query_entry->serial = ccs_serial++; |
entry->serial = ccs_serial++; |
1950 |
} |
} |
1951 |
spin_unlock(&ccs_query_list_lock); |
spin_unlock(&ccs_query_list_lock); |
1952 |
if (quota_exceeded) |
if (quota_exceeded) |
1953 |
goto out; |
goto out; |
1954 |
pos = snprintf(ccs_query_entry->query, len - 1, "Q%u-%hu\n%s", |
pos = snprintf(entry->query, len - 1, "Q%u-%hu\n%s", |
1955 |
ccs_query_entry->serial, r->retry, header); |
entry->serial, r->retry, header); |
1956 |
kfree(header); |
kfree(header); |
1957 |
header = NULL; |
header = NULL; |
1958 |
va_start(args, fmt); |
va_start(args, fmt); |
1959 |
vsnprintf(ccs_query_entry->query + pos, len - 1 - pos, fmt, args); |
vsnprintf(entry->query + pos, len - 1 - pos, fmt, args); |
1960 |
ccs_query_entry->query_len = strlen(ccs_query_entry->query) + 1; |
entry->query_len = strlen(entry->query) + 1; |
1961 |
va_end(args); |
va_end(args); |
1962 |
spin_lock(&ccs_query_list_lock); |
spin_lock(&ccs_query_list_lock); |
1963 |
list_add_tail(&ccs_query_entry->list, &ccs_query_list); |
list_add_tail(&entry->list, &ccs_query_list); |
1964 |
spin_unlock(&ccs_query_list_lock); |
spin_unlock(&ccs_query_list_lock); |
1965 |
/* Give 10 seconds for supervisor's opinion. */ |
/* Give 10 seconds for supervisor's opinion. */ |
1966 |
for (ccs_query_entry->timer = 0; |
for (entry->timer = 0; |
1967 |
atomic_read(&ccs_query_observers) && ccs_query_entry->timer < 100; |
atomic_read(&ccs_query_observers) && entry->timer < 100; |
1968 |
ccs_query_entry->timer++) { |
entry->timer++) { |
1969 |
wake_up(&ccs_query_wait); |
wake_up(&ccs_query_wait); |
1970 |
set_current_state(TASK_INTERRUPTIBLE); |
set_current_state(TASK_INTERRUPTIBLE); |
1971 |
schedule_timeout(HZ / 10); |
schedule_timeout(HZ / 10); |
1972 |
if (ccs_query_entry->answer) |
if (entry->answer) |
1973 |
break; |
break; |
1974 |
} |
} |
1975 |
spin_lock(&ccs_query_list_lock); |
spin_lock(&ccs_query_list_lock); |
1976 |
list_del(&ccs_query_entry->list); |
list_del(&entry->list); |
1977 |
ccs_query_memory_size -= len + sizeof(*ccs_query_entry); |
ccs_query_memory_size -= len + sizeof(*entry); |
1978 |
spin_unlock(&ccs_query_list_lock); |
spin_unlock(&ccs_query_list_lock); |
1979 |
switch (ccs_query_entry->answer) { |
switch (entry->answer) { |
1980 |
case 3: /* Asked to retry by administrator. */ |
case 3: /* Asked to retry by administrator. */ |
1981 |
error = CCS_RETRY_REQUEST; |
error = CCS_RETRY_REQUEST; |
1982 |
r->retry++; |
r->retry++; |
1993 |
break; |
break; |
1994 |
} |
} |
1995 |
out: |
out: |
1996 |
if (ccs_query_entry) |
if (entry) |
1997 |
kfree(ccs_query_entry->query); |
kfree(entry->query); |
1998 |
kfree(ccs_query_entry); |
kfree(entry); |
1999 |
kfree(header); |
kfree(header); |
2000 |
return error; |
return error; |
2001 |
} |
} |
2018 |
for (i = 0; i < 2; i++) { |
for (i = 0; i < 2; i++) { |
2019 |
spin_lock(&ccs_query_list_lock); |
spin_lock(&ccs_query_list_lock); |
2020 |
list_for_each(tmp, &ccs_query_list) { |
list_for_each(tmp, &ccs_query_list) { |
2021 |
struct ccs_query_entry *ptr = |
struct ccs_query *ptr = |
2022 |
list_entry(tmp, struct ccs_query_entry, list); |
list_entry(tmp, typeof(*ptr), list); |
2023 |
if (ptr->answer) |
if (ptr->answer) |
2024 |
continue; |
continue; |
2025 |
found = true; |
found = true; |
2054 |
} |
} |
2055 |
spin_lock(&ccs_query_list_lock); |
spin_lock(&ccs_query_list_lock); |
2056 |
list_for_each(tmp, &ccs_query_list) { |
list_for_each(tmp, &ccs_query_list) { |
2057 |
struct ccs_query_entry *ptr |
struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list); |
|
= list_entry(tmp, struct ccs_query_entry, list); |
|
2058 |
if (ptr->answer) |
if (ptr->answer) |
2059 |
continue; |
continue; |
2060 |
if (pos++ != head->r.query_index) |
if (pos++ != head->r.query_index) |
2073 |
pos = 0; |
pos = 0; |
2074 |
spin_lock(&ccs_query_list_lock); |
spin_lock(&ccs_query_list_lock); |
2075 |
list_for_each(tmp, &ccs_query_list) { |
list_for_each(tmp, &ccs_query_list) { |
2076 |
struct ccs_query_entry *ptr |
struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list); |
|
= list_entry(tmp, struct ccs_query_entry, list); |
|
2077 |
if (ptr->answer) |
if (ptr->answer) |
2078 |
continue; |
continue; |
2079 |
if (pos++ != head->r.query_index) |
if (pos++ != head->r.query_index) |
2111 |
unsigned int answer; |
unsigned int answer; |
2112 |
spin_lock(&ccs_query_list_lock); |
spin_lock(&ccs_query_list_lock); |
2113 |
list_for_each(tmp, &ccs_query_list) { |
list_for_each(tmp, &ccs_query_list) { |
2114 |
struct ccs_query_entry *ptr |
struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list); |
|
= list_entry(tmp, struct ccs_query_entry, list); |
|
2115 |
ptr->timer = 0; |
ptr->timer = 0; |
2116 |
} |
} |
2117 |
spin_unlock(&ccs_query_list_lock); |
spin_unlock(&ccs_query_list_lock); |
2119 |
return -EINVAL; |
return -EINVAL; |
2120 |
spin_lock(&ccs_query_list_lock); |
spin_lock(&ccs_query_list_lock); |
2121 |
list_for_each(tmp, &ccs_query_list) { |
list_for_each(tmp, &ccs_query_list) { |
2122 |
struct ccs_query_entry *ptr |
struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list); |
|
= list_entry(tmp, struct ccs_query_entry, list); |
|
2123 |
if (ptr->serial != serial) |
if (ptr->serial != serial) |
2124 |
continue; |
continue; |
2125 |
if (!ptr->answer) |
if (!ptr->answer) |
2139 |
{ |
{ |
2140 |
if (head->r.eof) |
if (head->r.eof) |
2141 |
return; |
return; |
2142 |
ccs_set_string(head, "1.7.2"); |
ccs_set_string(head, "1.8.0-pre"); |
2143 |
head->r.eof = true; |
head->r.eof = true; |
2144 |
} |
} |
2145 |
|
|