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", |
95 |
[CCS_MAC_NETWORK_UDP_BIND] |
[CCS_MAC_NETWORK_INET_TCP_BIND] |
|
= "network::inet_udp_bind", |
|
|
[CCS_MAC_NETWORK_UDP_CONNECT] |
|
|
= "network::inet_udp_connect", |
|
|
[CCS_MAC_NETWORK_TCP_BIND] |
|
96 |
= "network::inet_tcp_bind", |
= "network::inet_tcp_bind", |
97 |
[CCS_MAC_NETWORK_TCP_LISTEN] |
[CCS_MAC_NETWORK_INET_TCP_LISTEN] |
98 |
= "network::inet_tcp_listen", |
= "network::inet_tcp_listen", |
99 |
[CCS_MAC_NETWORK_TCP_CONNECT] |
[CCS_MAC_NETWORK_INET_TCP_CONNECT] |
100 |
= "network::inet_tcp_connect", |
= "network::inet_tcp_connect", |
101 |
[CCS_MAC_NETWORK_TCP_ACCEPT] |
[CCS_MAC_NETWORK_INET_TCP_ACCEPT] |
102 |
= "network::inet_tcp_accept", |
= "network::inet_tcp_accept", |
103 |
[CCS_MAC_NETWORK_RAW_BIND] |
[CCS_MAC_NETWORK_INET_UDP_BIND] |
104 |
|
= "network::inet_udp_bind", |
105 |
|
[CCS_MAC_NETWORK_INET_UDP_SEND] |
106 |
|
= "network::inet_udp_send", |
107 |
|
[CCS_MAC_NETWORK_INET_UDP_RECV] |
108 |
|
= "network::inet_udp_recv", |
109 |
|
[CCS_MAC_NETWORK_INET_RAW_BIND] |
110 |
= "network::inet_raw_bind", |
= "network::inet_raw_bind", |
111 |
[CCS_MAC_NETWORK_RAW_CONNECT] |
[CCS_MAC_NETWORK_INET_RAW_SEND] |
112 |
= "network::inet_raw_connect", |
= "network::inet_raw_send", |
113 |
|
[CCS_MAC_NETWORK_INET_RAW_RECV] |
114 |
|
= "network::inet_raw_recv", |
115 |
|
[CCS_MAC_NETWORK_UNIX_STREAM_BIND] |
116 |
|
= "network::unix_stream_bind", |
117 |
|
[CCS_MAC_NETWORK_UNIX_STREAM_LISTEN] |
118 |
|
= "network::unix_stream_listen", |
119 |
|
[CCS_MAC_NETWORK_UNIX_STREAM_CONNECT] |
120 |
|
= "network::unix_stream_connect", |
121 |
|
[CCS_MAC_NETWORK_UNIX_STREAM_ACCEPT] |
122 |
|
= "network::unix_stream_accept", |
123 |
|
[CCS_MAC_NETWORK_UNIX_DGRAM_BIND] |
124 |
|
= "network::unix_dgram_bind", |
125 |
|
[CCS_MAC_NETWORK_UNIX_DGRAM_SEND] |
126 |
|
= "network::unix_dgram_send", |
127 |
|
[CCS_MAC_NETWORK_UNIX_DGRAM_RECV] |
128 |
|
= "network::unix_dgram_recv", |
129 |
|
[CCS_MAC_NETWORK_UNIX_SEQPACKET_BIND] |
130 |
|
= "network::unix_seqpacket_bind", |
131 |
|
[CCS_MAC_NETWORK_UNIX_SEQPACKET_LISTEN] |
132 |
|
= "network::unix_seqpacket_listen", |
133 |
|
[CCS_MAC_NETWORK_UNIX_SEQPACKET_CONNECT] |
134 |
|
= "network::unix_seqpacket_connect", |
135 |
|
[CCS_MAC_NETWORK_UNIX_SEQPACKET_ACCEPT] |
136 |
|
= "network::unix_seqpacket_accept", |
137 |
[CCS_MAC_SIGNAL] |
[CCS_MAC_SIGNAL] |
138 |
= "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", |
|
139 |
[CCS_MAX_MAC_INDEX + CCS_USE_ROUTE_SOCKET] |
[CCS_MAX_MAC_INDEX + CCS_USE_ROUTE_SOCKET] |
140 |
= "capability::use_route", |
= "capability::use_route", |
141 |
[CCS_MAX_MAC_INDEX + CCS_USE_PACKET_SOCKET] |
[CCS_MAX_MAC_INDEX + CCS_USE_PACKET_SOCKET] |
142 |
= "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", |
|
143 |
[CCS_MAX_MAC_INDEX + CCS_SYS_REBOOT] |
[CCS_MAX_MAC_INDEX + CCS_SYS_REBOOT] |
144 |
= "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", |
|
145 |
[CCS_MAX_MAC_INDEX + CCS_SYS_VHANGUP] |
[CCS_MAX_MAC_INDEX + CCS_SYS_VHANGUP] |
146 |
= "capability::SYS_VHANGUP", |
= "capability::SYS_VHANGUP", |
147 |
[CCS_MAX_MAC_INDEX + CCS_SYS_SETTIME] |
[CCS_MAX_MAC_INDEX + CCS_SYS_SETTIME] |
152 |
= "capability::SYS_SETHOSTNAME", |
= "capability::SYS_SETHOSTNAME", |
153 |
[CCS_MAX_MAC_INDEX + CCS_USE_KERNEL_MODULE] |
[CCS_MAX_MAC_INDEX + CCS_USE_KERNEL_MODULE] |
154 |
= "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", |
|
155 |
[CCS_MAX_MAC_INDEX + CCS_SYS_KEXEC_LOAD] |
[CCS_MAX_MAC_INDEX + CCS_SYS_KEXEC_LOAD] |
156 |
= "capability::SYS_KEXEC_LOAD", |
= "capability::SYS_KEXEC_LOAD", |
|
[CCS_MAX_MAC_INDEX + CCS_SYS_PIVOT_ROOT] |
|
|
= "capability::SYS_PIVOT_ROOT", |
|
157 |
[CCS_MAX_MAC_INDEX + CCS_SYS_PTRACE] |
[CCS_MAX_MAC_INDEX + CCS_SYS_PTRACE] |
158 |
= "capability::SYS_PTRACE", |
= "capability::SYS_PTRACE", |
|
[CCS_MAX_MAC_INDEX + CCS_CONCEAL_MOUNT] |
|
|
= "capability::conceal_mount", |
|
159 |
[CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX |
[CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX |
160 |
+ CCS_MAC_CATEGORY_FILE] = "file", |
+ CCS_MAC_CATEGORY_FILE] = "file", |
161 |
[CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX |
[CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX |
262 |
head->r.w[head->r.w_pos++] = string; |
head->r.w[head->r.w_pos++] = string; |
263 |
ccs_flush(head); |
ccs_flush(head); |
264 |
} else |
} else |
265 |
WARN_ON(1); |
printk(KERN_WARNING "Too many words in a line.\n"); |
266 |
} |
} |
267 |
|
|
268 |
/** |
/** |
283 |
len = vsnprintf(head->read_buf + pos, size, fmt, args) + 1; |
len = vsnprintf(head->read_buf + pos, size, fmt, args) + 1; |
284 |
va_end(args); |
va_end(args); |
285 |
if (pos + len >= head->readbuf_size) { |
if (pos + len >= head->readbuf_size) { |
286 |
WARN_ON(1); |
printk(KERN_WARNING "Too many words in a line.\n"); |
287 |
return; |
return; |
288 |
} |
} |
289 |
head->r.avail += len; |
head->r.avail += len; |
323 |
ptr = ccs_profile_ptr[profile]; |
ptr = ccs_profile_ptr[profile]; |
324 |
if (!ptr && ccs_memory_ok(entry, sizeof(*entry))) { |
if (!ptr && ccs_memory_ok(entry, sizeof(*entry))) { |
325 |
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; |
|
326 |
ptr->default_config = CCS_CONFIG_DISABLED | |
ptr->default_config = CCS_CONFIG_DISABLED | |
327 |
|
CCS_CONFIG_VERBOSE | |
328 |
CCS_CONFIG_WANT_GRANT_LOG | CCS_CONFIG_WANT_REJECT_LOG; |
CCS_CONFIG_WANT_GRANT_LOG | CCS_CONFIG_WANT_REJECT_LOG; |
329 |
memset(ptr->config, CCS_CONFIG_USE_DEFAULT, |
memset(ptr->config, CCS_CONFIG_USE_DEFAULT, |
330 |
sizeof(ptr->config)); |
sizeof(ptr->config)); |
357 |
if (ccs_profile_version != 20090903) |
if (ccs_profile_version != 20090903) |
358 |
panic("Profile version %u is not supported.\n", |
panic("Profile version %u is not supported.\n", |
359 |
ccs_profile_version); |
ccs_profile_version); |
360 |
printk(KERN_INFO "CCSecurity: 1.7.2+ 2010/06/04\n"); |
printk(KERN_INFO "CCSecurity: 1.8.0-pre 2010/08/01\n"); |
361 |
printk(KERN_INFO "Mandatory Access Control activated.\n"); |
printk(KERN_INFO "Mandatory Access Control activated.\n"); |
362 |
} |
} |
363 |
|
|
410 |
} |
} |
411 |
|
|
412 |
static void ccs_set_pref(const char *name, const char *value, |
static void ccs_set_pref(const char *name, const char *value, |
413 |
const bool use_default, struct ccs_profile *profile) |
struct ccs_profile *profile) |
414 |
{ |
{ |
|
struct ccs_preference **pref; |
|
|
bool *verbose; |
|
415 |
if (!strcmp(name, "audit")) { |
if (!strcmp(name, "audit")) { |
|
if (use_default) { |
|
|
pref = &profile->audit; |
|
|
goto set_default; |
|
|
} |
|
|
profile->audit = &profile->preference; |
|
416 |
#ifdef CONFIG_CCSECURITY_AUDIT |
#ifdef CONFIG_CCSECURITY_AUDIT |
417 |
ccs_set_uint(&profile->preference.audit_max_grant_log, value, |
ccs_set_uint(&profile->preference.audit_max_grant_log, value, |
418 |
"max_grant_log"); |
"max_grant_log"); |
426 |
return; |
return; |
427 |
} |
} |
428 |
if (!strcmp(name, "enforcing")) { |
if (!strcmp(name, "enforcing")) { |
|
if (use_default) { |
|
|
pref = &profile->enforcing; |
|
|
goto set_default; |
|
|
} |
|
|
profile->enforcing = &profile->preference; |
|
429 |
ccs_set_uint(&profile->preference.enforcing_penalty, value, |
ccs_set_uint(&profile->preference.enforcing_penalty, value, |
430 |
"penalty"); |
"penalty"); |
431 |
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; |
|
432 |
} |
} |
433 |
if (!strcmp(name, "learning")) { |
if (!strcmp(name, "learning")) { |
|
if (use_default) { |
|
|
pref = &profile->learning; |
|
|
goto set_default; |
|
|
} |
|
|
profile->learning = &profile->preference; |
|
434 |
ccs_set_uint(&profile->preference.learning_max_entry, value, |
ccs_set_uint(&profile->preference.learning_max_entry, value, |
435 |
"max_entry"); |
"max_entry"); |
436 |
ccs_set_bool(&profile->preference.learning_exec_realpath, |
ccs_set_bool(&profile->preference.learning_exec_realpath, |
439 |
"exec.argv0"); |
"exec.argv0"); |
440 |
ccs_set_bool(&profile->preference.learning_symlink_target, |
ccs_set_bool(&profile->preference.learning_symlink_target, |
441 |
value, "symlink.target"); |
value, "symlink.target"); |
442 |
verbose = &profile->preference.learning_verbose; |
return; |
|
goto set_verbose; |
|
443 |
} |
} |
|
return; |
|
|
set_default: |
|
|
*pref = &ccs_default_profile.preference; |
|
|
return; |
|
|
set_verbose: |
|
|
ccs_set_bool(verbose, value, "verbose"); |
|
444 |
} |
} |
445 |
|
|
446 |
static int ccs_set_mode(char *name, const char *value, const bool use_default, |
static int ccs_set_mode(char *name, const char *value, |
447 |
struct ccs_profile *profile) |
struct ccs_profile *profile) |
448 |
{ |
{ |
449 |
u8 i; |
u8 i; |
467 |
} else { |
} else { |
468 |
return -EINVAL; |
return -EINVAL; |
469 |
} |
} |
470 |
if (use_default) { |
if (strstr(value, "use_default")) { |
471 |
config = CCS_CONFIG_USE_DEFAULT; |
config = CCS_CONFIG_USE_DEFAULT; |
472 |
} else { |
} else { |
473 |
u8 mode; |
u8 mode; |
478 |
* 'config' from 'CCS_CONFIG_USE_DEAFULT'. |
* 'config' from 'CCS_CONFIG_USE_DEAFULT'. |
479 |
*/ |
*/ |
480 |
config = (config & ~7) | mode; |
config = (config & ~7) | mode; |
|
#ifdef CONFIG_CCSECURITY_AUDIT |
|
481 |
if (config != CCS_CONFIG_USE_DEFAULT) { |
if (config != CCS_CONFIG_USE_DEFAULT) { |
482 |
|
switch (ccs_find_yesno(value, "verbose")) { |
483 |
|
case 1: |
484 |
|
config |= CCS_CONFIG_VERBOSE; |
485 |
|
break; |
486 |
|
case 0: |
487 |
|
config &= ~CCS_CONFIG_VERBOSE; |
488 |
|
break; |
489 |
|
} |
490 |
|
#ifdef CONFIG_CCSECURITY_AUDIT |
491 |
switch (ccs_find_yesno(value, "grant_log")) { |
switch (ccs_find_yesno(value, "grant_log")) { |
492 |
case 1: |
case 1: |
493 |
config |= CCS_CONFIG_WANT_GRANT_LOG; |
config |= CCS_CONFIG_WANT_GRANT_LOG; |
504 |
config &= ~CCS_CONFIG_WANT_REJECT_LOG; |
config &= ~CCS_CONFIG_WANT_REJECT_LOG; |
505 |
break; |
break; |
506 |
} |
} |
|
} |
|
507 |
#endif |
#endif |
508 |
|
} |
509 |
} |
} |
510 |
if (i < CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX |
if (i < CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX |
511 |
+ CCS_MAX_MAC_CATEGORY_INDEX) |
+ CCS_MAX_MAC_CATEGORY_INDEX) |
525 |
static int ccs_write_profile(struct ccs_io_buffer *head) |
static int ccs_write_profile(struct ccs_io_buffer *head) |
526 |
{ |
{ |
527 |
char *data = head->write_buf; |
char *data = head->write_buf; |
528 |
bool use_default = false; |
unsigned int i; |
529 |
char *cp; |
char *cp; |
|
int i; |
|
530 |
struct ccs_profile *profile; |
struct ccs_profile *profile; |
531 |
if (sscanf(data, "PROFILE_VERSION=%u", &ccs_profile_version) == 1) |
if (sscanf(data, "PROFILE_VERSION=%u", &ccs_profile_version) == 1) |
532 |
return 0; |
return 0; |
533 |
i = simple_strtoul(data, &cp, 10); |
i = simple_strtoul(data, &cp, 10); |
534 |
if (data == cp) { |
if (*cp != '-') |
535 |
profile = &ccs_default_profile; |
return -EINVAL; |
536 |
} else { |
data = cp + 1; |
537 |
if (*cp != '-') |
profile = ccs_assign_profile(i); |
538 |
return -EINVAL; |
if (!profile) |
539 |
data = cp + 1; |
return -EINVAL; |
|
profile = ccs_assign_profile(i); |
|
|
if (!profile) |
|
|
return -EINVAL; |
|
|
} |
|
540 |
cp = strchr(data, '='); |
cp = strchr(data, '='); |
541 |
if (!cp) |
if (!cp) |
542 |
return -EINVAL; |
return -EINVAL; |
543 |
*cp++ = '\0'; |
*cp++ = '\0'; |
|
if (profile != &ccs_default_profile) |
|
|
use_default = strstr(cp, "use_default") != NULL; |
|
544 |
if (ccs_str_starts(&data, "PREFERENCE::")) { |
if (ccs_str_starts(&data, "PREFERENCE::")) { |
545 |
ccs_set_pref(data, cp, use_default, profile); |
ccs_set_pref(data, cp, profile); |
546 |
return 0; |
return 0; |
547 |
} |
} |
|
if (profile == &ccs_default_profile) |
|
|
return -EINVAL; |
|
548 |
if (!strcmp(data, "COMMENT")) { |
if (!strcmp(data, "COMMENT")) { |
549 |
const struct ccs_path_info *old_comment = profile->comment; |
const struct ccs_path_info *old_comment = profile->comment; |
550 |
profile->comment = ccs_get_name(cp); |
profile->comment = ccs_get_name(cp); |
551 |
ccs_put_name(old_comment); |
ccs_put_name(old_comment); |
552 |
return 0; |
return 0; |
553 |
} |
} |
554 |
return ccs_set_mode(data, cp, use_default, profile); |
return ccs_set_mode(data, cp, profile); |
555 |
} |
} |
556 |
|
|
557 |
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) |
558 |
{ |
{ |
559 |
struct ccs_preference *pref = &ccs_default_profile.preference; |
struct ccs_profile *profile = ccs_profile_ptr[index]; |
560 |
const struct ccs_profile *profile = idx >= 0 ? |
struct ccs_preference *pref = &profile->preference; |
561 |
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={ " |
|
562 |
#ifdef CONFIG_CCSECURITY_AUDIT |
#ifdef CONFIG_CCSECURITY_AUDIT |
563 |
"max_grant_log=%u max_reject_log=%u " |
"max_grant_log=%u max_reject_log=%u " |
564 |
#endif |
#endif |
565 |
"task_info=%s path_info=%s }\n", buffer, |
"task_info=%s path_info=%s }\n", index, |
566 |
"audit", |
"audit", |
567 |
#ifdef CONFIG_CCSECURITY_AUDIT |
#ifdef CONFIG_CCSECURITY_AUDIT |
568 |
pref->audit_max_grant_log, |
pref->audit_max_grant_log, |
570 |
#endif |
#endif |
571 |
ccs_yesno(pref->audit_task_info), |
ccs_yesno(pref->audit_task_info), |
572 |
ccs_yesno(pref->audit_path_info)); |
ccs_yesno(pref->audit_path_info)); |
573 |
skip0: |
ccs_io_printf(head, "%u-PREFERENCE::%s={ " |
574 |
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 " |
|
575 |
"exec.argv0=%s symlink.target=%s }\n", |
"exec.argv0=%s symlink.target=%s }\n", |
576 |
buffer, "learning", |
index, "learning", |
|
ccs_yesno(pref->learning_verbose), |
|
577 |
pref->learning_max_entry, |
pref->learning_max_entry, |
578 |
ccs_yesno(pref->learning_exec_realpath), |
ccs_yesno(pref->learning_exec_realpath), |
579 |
ccs_yesno(pref->learning_exec_argv0), |
ccs_yesno(pref->learning_exec_argv0), |
580 |
ccs_yesno(pref->learning_symlink_target)); |
ccs_yesno(pref->learning_symlink_target)); |
581 |
skip1: |
ccs_io_printf(head, "%u-PREFERENCE::%s={ penalty=%u }\n", index, |
582 |
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); |
|
583 |
} |
} |
584 |
|
|
585 |
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) |
586 |
{ |
{ |
587 |
ccs_io_printf(head, "={ mode=%s", ccs_mode[config & 3]); |
ccs_io_printf(head, "={ mode=%s verbose=%s", ccs_mode[config & 3], |
588 |
|
ccs_yesno(config & CCS_CONFIG_VERBOSE)); |
589 |
#ifdef CONFIG_CCSECURITY_AUDIT |
#ifdef CONFIG_CCSECURITY_AUDIT |
590 |
ccs_io_printf(head, " grant_log=%s reject_log=%s", |
ccs_io_printf(head, " grant_log=%s reject_log=%s", |
591 |
ccs_yesno(config & CCS_CONFIG_WANT_GRANT_LOG), |
ccs_yesno(config & CCS_CONFIG_WANT_GRANT_LOG), |
609 |
switch (head->r.step) { |
switch (head->r.step) { |
610 |
case 0: |
case 0: |
611 |
ccs_io_printf(head, "PROFILE_VERSION=%s\n", "20090903"); |
ccs_io_printf(head, "PROFILE_VERSION=%s\n", "20090903"); |
|
ccs_print_preference(head, -1); |
|
612 |
head->r.step++; |
head->r.step++; |
613 |
break; |
break; |
614 |
case 1: |
case 1: |
664 |
goto next; |
goto next; |
665 |
} |
} |
666 |
|
|
667 |
static bool ccs_same_manager_entry(const struct ccs_acl_head *a, |
static bool ccs_same_manager(const struct ccs_acl_head *a, |
668 |
const struct ccs_acl_head *b) |
const struct ccs_acl_head *b) |
669 |
{ |
{ |
670 |
return container_of(a, struct ccs_manager, head)->manager |
return container_of(a, struct ccs_manager, head)->manager |
671 |
== container_of(b, struct ccs_manager, head)->manager; |
== container_of(b, struct ccs_manager, head)->manager; |
696 |
return error; |
return error; |
697 |
error = ccs_update_policy(&e.head, sizeof(e), is_delete, |
error = ccs_update_policy(&e.head, sizeof(e), is_delete, |
698 |
&ccs_policy_list[CCS_ID_MANAGER], |
&ccs_policy_list[CCS_ID_MANAGER], |
699 |
ccs_same_manager_entry); |
ccs_same_manager); |
700 |
ccs_put_name(e.manager); |
ccs_put_name(e.manager); |
701 |
return error; |
return error; |
702 |
} |
} |
828 |
unsigned int pid; |
unsigned int pid; |
829 |
struct ccs_domain_info *domain = NULL; |
struct ccs_domain_info *domain = NULL; |
830 |
bool global_pid = false; |
bool global_pid = false; |
831 |
if (!strcmp(data, "allow_execute")) { |
if (!strcmp(data, "execute")) { |
832 |
head->r.print_execute_only = true; |
head->r.print_execute_only = true; |
833 |
return true; |
return true; |
834 |
} |
} |
859 |
return true; /* Do nothing if open(O_WRONLY). */ |
return true; /* Do nothing if open(O_WRONLY). */ |
860 |
memset(&head->r, 0, sizeof(head->r)); |
memset(&head->r, 0, sizeof(head->r)); |
861 |
head->r.print_this_domain_only = true; |
head->r.print_this_domain_only = true; |
862 |
head->r.eof = !domain; |
if (domain) |
863 |
head->r.domain = &domain->list; |
head->r.domain = &domain->list; |
864 |
|
else |
865 |
|
head->r.eof = true; |
866 |
ccs_io_printf(head, "# select %s\n", data); |
ccs_io_printf(head, "# select %s\n", data); |
867 |
if (domain && domain->is_deleted) |
if (domain && domain->is_deleted) |
868 |
ccs_set_string(head, "# This is a deleted domain.\n"); |
ccs_set_string(head, "# This is a deleted domain.\n"); |
877 |
int (*write) (char *, struct ccs_domain_info *, |
int (*write) (char *, struct ccs_domain_info *, |
878 |
struct ccs_condition *, const bool); |
struct ccs_condition *, const bool); |
879 |
} ccs_callback[5] = { |
} ccs_callback[5] = { |
880 |
{ CCS_KEYWORD_ALLOW_NETWORK, ccs_write_network }, |
{ "network inet ", ccs_write_inet_network }, |
881 |
{ CCS_KEYWORD_ALLOW_ENV, ccs_write_env }, |
{ "network unix ", ccs_write_unix_network }, |
882 |
{ CCS_KEYWORD_ALLOW_CAPABILITY, ccs_write_capability }, |
{ "misc ", ccs_write_misc }, |
883 |
{ CCS_KEYWORD_ALLOW_SIGNAL, ccs_write_signal }, |
{ "capability ", ccs_write_capability }, |
884 |
{ CCS_KEYWORD_ALLOW_MOUNT, ccs_write_mount } |
{ "ipc ", ccs_write_ipc }, |
885 |
}; |
}; |
886 |
int (*write) (char *, struct ccs_domain_info *, struct ccs_condition *, |
int (*write) (char *, struct ccs_domain_info *, struct ccs_condition *, |
887 |
const bool) = ccs_write_file; |
const bool) = ccs_write_file; |
908 |
|
|
909 |
static const char *ccs_dif[CCS_MAX_DOMAIN_INFO_FLAGS] = { |
static const char *ccs_dif[CCS_MAX_DOMAIN_INFO_FLAGS] = { |
910 |
[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", |
|
911 |
[CCS_DIF_TRANSITION_FAILED] = CCS_KEYWORD_TRANSITION_FAILED "\n" |
[CCS_DIF_TRANSITION_FAILED] = CCS_KEYWORD_TRANSITION_FAILED "\n" |
912 |
}; |
}; |
913 |
|
|
941 |
else if (is_select) |
else if (is_select) |
942 |
domain = ccs_find_domain(data); |
domain = ccs_find_domain(data); |
943 |
else |
else |
944 |
domain = ccs_assign_domain(data, 0); |
domain = ccs_assign_domain(data, 0, 0, false); |
945 |
head->w.domain = domain; |
head->w.domain = domain; |
946 |
return 0; |
return 0; |
947 |
} |
} |
954 |
domain->profile = (u8) profile; |
domain->profile = (u8) profile; |
955 |
return 0; |
return 0; |
956 |
} |
} |
957 |
|
if (sscanf(data, CCS_KEYWORD_USE_GROUP "%u", &profile) == 1 |
958 |
|
&& profile < CCS_MAX_ACL_GROUPS) { |
959 |
|
domain->group = (u8) profile; |
960 |
|
return 0; |
961 |
|
} |
962 |
for (profile = 0; profile < CCS_MAX_DOMAIN_INFO_FLAGS; profile++) { |
for (profile = 0; profile < CCS_MAX_DOMAIN_INFO_FLAGS; profile++) { |
963 |
const char *cp = ccs_dif[profile]; |
const char *cp = ccs_dif[profile]; |
964 |
if (strncmp(data, cp, strlen(cp) - 1)) |
if (strncmp(data, cp, strlen(cp) - 1)) |
1203 |
return bit; |
return bit; |
1204 |
} |
} |
1205 |
|
|
1206 |
|
static void ccs_set_group(struct ccs_io_buffer *head) |
1207 |
|
{ |
1208 |
|
if (head->type == CCS_EXCEPTIONPOLICY) |
1209 |
|
ccs_io_printf(head, "acl_group %u ", head->r.group_index); |
1210 |
|
} |
1211 |
|
|
1212 |
/** |
/** |
1213 |
* ccs_print_entry - Print an ACL entry. |
* ccs_print_entry - Print an ACL entry. |
1214 |
* |
* |
1240 |
if (head->r.print_execute_only && |
if (head->r.print_execute_only && |
1241 |
bit != CCS_TYPE_EXECUTE && bit != CCS_TYPE_TRANSIT) |
bit != CCS_TYPE_EXECUTE && bit != CCS_TYPE_TRANSIT) |
1242 |
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; |
|
1243 |
break; |
break; |
1244 |
} |
} |
1245 |
if (bit >= CCS_MAX_PATH_OPERATION) |
if (bit >= CCS_MAX_PATH_OPERATION) |
1246 |
goto done; |
goto done; |
1247 |
ccs_io_printf(head, "allow_%s", ccs_path_keyword[bit]); |
ccs_set_group(head); |
1248 |
|
ccs_set_string(head, "file "); |
1249 |
|
ccs_set_string(head, ccs_path_keyword[bit]); |
1250 |
ccs_print_name_union(head, &ptr->name); |
ccs_print_name_union(head, &ptr->name); |
1251 |
} else if (acl_type == CCS_TYPE_EXECUTE_HANDLER || |
} else if (acl_type == CCS_TYPE_EXECUTE_HANDLER || |
1252 |
acl_type == CCS_TYPE_DENIED_EXECUTE_HANDLER) { |
acl_type == CCS_TYPE_DENIED_EXECUTE_HANDLER) { |
1253 |
struct ccs_execute_handler *ptr |
struct ccs_execute_handler *ptr |
1254 |
= container_of(acl, typeof(*ptr), head); |
= container_of(acl, typeof(*ptr), head); |
1255 |
|
ccs_set_group(head); |
1256 |
ccs_io_printf(head, "%s ", |
ccs_io_printf(head, "%s ", |
1257 |
acl_type == CCS_TYPE_EXECUTE_HANDLER ? |
acl_type == CCS_TYPE_EXECUTE_HANDLER ? |
1258 |
CCS_KEYWORD_EXECUTE_HANDLER : |
CCS_KEYWORD_EXECUTE_HANDLER : |
1266 |
bit = ccs_fns(ptr->perm, bit); |
bit = ccs_fns(ptr->perm, bit); |
1267 |
if (bit >= CCS_MAX_MKDEV_OPERATION) |
if (bit >= CCS_MAX_MKDEV_OPERATION) |
1268 |
goto done; |
goto done; |
1269 |
ccs_io_printf(head, "allow_%s", ccs_mkdev_keyword[bit]); |
ccs_set_group(head); |
1270 |
|
ccs_set_string(head, "file "); |
1271 |
|
ccs_set_string(head, ccs_mkdev_keyword[bit]); |
1272 |
ccs_print_name_union(head, &ptr->name); |
ccs_print_name_union(head, &ptr->name); |
1273 |
ccs_print_number_union(head, &ptr->mode); |
ccs_print_number_union(head, &ptr->mode); |
1274 |
ccs_print_number_union(head, &ptr->major); |
ccs_print_number_union(head, &ptr->major); |
1279 |
bit = ccs_fns(ptr->perm, bit); |
bit = ccs_fns(ptr->perm, bit); |
1280 |
if (bit >= CCS_MAX_PATH2_OPERATION) |
if (bit >= CCS_MAX_PATH2_OPERATION) |
1281 |
goto done; |
goto done; |
1282 |
ccs_io_printf(head, "allow_%s", ccs_path2_keyword[bit]); |
ccs_set_group(head); |
1283 |
|
ccs_set_string(head, "file "); |
1284 |
|
ccs_set_string(head, ccs_path2_keyword[bit]); |
1285 |
ccs_print_name_union(head, &ptr->name1); |
ccs_print_name_union(head, &ptr->name1); |
1286 |
ccs_print_name_union(head, &ptr->name2); |
ccs_print_name_union(head, &ptr->name2); |
1287 |
} else if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) { |
} else if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) { |
1290 |
bit = ccs_fns(ptr->perm, bit); |
bit = ccs_fns(ptr->perm, bit); |
1291 |
if (bit >= CCS_MAX_PATH_NUMBER_OPERATION) |
if (bit >= CCS_MAX_PATH_NUMBER_OPERATION) |
1292 |
goto done; |
goto done; |
1293 |
ccs_io_printf(head, "allow_%s", |
ccs_set_group(head); |
1294 |
ccs_path_number_keyword[bit]); |
ccs_set_string(head, "file "); |
1295 |
|
ccs_set_string(head, ccs_path_number_keyword[bit]); |
1296 |
ccs_print_name_union(head, &ptr->name); |
ccs_print_name_union(head, &ptr->name); |
1297 |
ccs_print_number_union(head, &ptr->number); |
ccs_print_number_union(head, &ptr->number); |
1298 |
} else if (acl_type == CCS_TYPE_ENV_ACL) { |
} else if (acl_type == CCS_TYPE_ENV_ACL) { |
1299 |
struct ccs_env_acl *ptr = |
struct ccs_env_acl *ptr = |
1300 |
container_of(acl, typeof(*ptr), head); |
container_of(acl, typeof(*ptr), head); |
1301 |
ccs_set_string(head, CCS_KEYWORD_ALLOW_ENV); |
ccs_set_group(head); |
1302 |
|
ccs_set_string(head, "misc env "); |
1303 |
ccs_set_string(head, ptr->env->name); |
ccs_set_string(head, ptr->env->name); |
1304 |
} else if (acl_type == CCS_TYPE_CAPABILITY_ACL) { |
} else if (acl_type == CCS_TYPE_CAPABILITY_ACL) { |
1305 |
struct ccs_capability_acl *ptr = |
struct ccs_capability_acl *ptr = |
1306 |
container_of(acl, typeof(*ptr), head); |
container_of(acl, typeof(*ptr), head); |
1307 |
ccs_set_string(head, CCS_KEYWORD_ALLOW_CAPABILITY); |
ccs_set_group(head); |
1308 |
|
ccs_set_string(head, "capability "); |
1309 |
ccs_set_string(head, ccs_cap2keyword(ptr->operation)); |
ccs_set_string(head, ccs_cap2keyword(ptr->operation)); |
1310 |
} else if (acl_type == CCS_TYPE_IP_NETWORK_ACL) { |
} else if (acl_type == CCS_TYPE_INET_ACL) { |
1311 |
struct ccs_ip_network_acl *ptr = |
struct ccs_inet_acl *ptr = |
1312 |
container_of(acl, typeof(*ptr), head); |
container_of(acl, typeof(*ptr), head); |
1313 |
bit = ccs_fns(ptr->perm, bit); |
bit = ccs_fns(ptr->perm, bit); |
1314 |
if (bit >= CCS_MAX_NETWORK_OPERATION) |
if (bit >= CCS_MAX_NETWORK_OPERATION) |
1315 |
goto done; |
goto done; |
1316 |
ccs_io_printf(head, CCS_KEYWORD_ALLOW_NETWORK "%s ", |
ccs_set_group(head); |
1317 |
ccs_net_keyword[bit]); |
ccs_set_string(head, "network inet "); |
1318 |
|
ccs_set_string(head, ccs_inet_keyword[ptr->protocol]); |
1319 |
|
ccs_set_space(head); |
1320 |
|
ccs_set_string(head, ccs_net_keyword[bit]); |
1321 |
|
ccs_set_space(head); |
1322 |
switch (ptr->address_type) { |
switch (ptr->address_type) { |
1323 |
char buf[128]; |
char buf[128]; |
1324 |
case CCS_IP_ADDRESS_TYPE_ADDRESS_GROUP: |
case CCS_IP_ADDRESS_TYPE_ADDRESS_GROUP: |
1338 |
break; |
break; |
1339 |
} |
} |
1340 |
ccs_print_number_union(head, &ptr->port); |
ccs_print_number_union(head, &ptr->port); |
1341 |
|
} else if (acl_type == CCS_TYPE_UNIX_ACL) { |
1342 |
|
struct ccs_unix_acl *ptr = |
1343 |
|
container_of(acl, typeof(*ptr), head); |
1344 |
|
bit = ccs_fns(ptr->perm, bit); |
1345 |
|
if (bit >= CCS_MAX_NETWORK_OPERATION) |
1346 |
|
goto done; |
1347 |
|
ccs_set_group(head); |
1348 |
|
ccs_set_string(head, "network unix "); |
1349 |
|
ccs_set_string(head, ccs_unix_keyword[ptr->protocol]); |
1350 |
|
ccs_set_space(head); |
1351 |
|
ccs_set_string(head, ccs_net_keyword[bit]); |
1352 |
|
ccs_print_name_union(head, &ptr->name); |
1353 |
} else if (acl_type == CCS_TYPE_SIGNAL_ACL) { |
} else if (acl_type == CCS_TYPE_SIGNAL_ACL) { |
1354 |
struct ccs_signal_acl *ptr = |
struct ccs_signal_acl *ptr = |
1355 |
container_of(acl, typeof(*ptr), head); |
container_of(acl, typeof(*ptr), head); |
1356 |
ccs_io_printf(head, CCS_KEYWORD_ALLOW_SIGNAL "%u ", ptr->sig); |
ccs_set_group(head); |
1357 |
|
ccs_set_string(head, "ipc signal "); |
1358 |
|
ccs_io_printf(head, "%u ", ptr->sig); |
1359 |
ccs_set_string(head, ptr->domainname->name); |
ccs_set_string(head, ptr->domainname->name); |
1360 |
} else if (acl_type == CCS_TYPE_MOUNT_ACL) { |
} else if (acl_type == CCS_TYPE_MOUNT_ACL) { |
1361 |
struct ccs_mount_acl *ptr = |
struct ccs_mount_acl *ptr = |
1362 |
container_of(acl, typeof(*ptr), head); |
container_of(acl, typeof(*ptr), head); |
1363 |
ccs_io_printf(head, "allow_mount"); |
ccs_set_group(head); |
1364 |
|
ccs_io_printf(head, "file mount"); |
1365 |
ccs_print_name_union(head, &ptr->dev_name); |
ccs_print_name_union(head, &ptr->dev_name); |
1366 |
ccs_print_name_union(head, &ptr->dir_name); |
ccs_print_name_union(head, &ptr->dir_name); |
1367 |
ccs_print_name_union(head, &ptr->fs_type); |
ccs_print_name_union(head, &ptr->fs_type); |
1385 |
case CCS_TYPE_MKDEV_ACL: |
case CCS_TYPE_MKDEV_ACL: |
1386 |
case CCS_TYPE_PATH2_ACL: |
case CCS_TYPE_PATH2_ACL: |
1387 |
case CCS_TYPE_PATH_NUMBER_ACL: |
case CCS_TYPE_PATH_NUMBER_ACL: |
1388 |
case CCS_TYPE_IP_NETWORK_ACL: |
case CCS_TYPE_INET_ACL: |
1389 |
|
case CCS_TYPE_UNIX_ACL: |
1390 |
goto next; |
goto next; |
1391 |
} |
} |
1392 |
done: |
done: |
1442 |
ccs_set_lf(head); |
ccs_set_lf(head); |
1443 |
ccs_io_printf(head, CCS_KEYWORD_USE_PROFILE "%u\n", |
ccs_io_printf(head, CCS_KEYWORD_USE_PROFILE "%u\n", |
1444 |
domain->profile); |
domain->profile); |
1445 |
|
ccs_io_printf(head, CCS_KEYWORD_USE_GROUP "%u\n", |
1446 |
|
domain->group); |
1447 |
for (i = 0; i < CCS_MAX_DOMAIN_INFO_FLAGS; i++) |
for (i = 0; i < CCS_MAX_DOMAIN_INFO_FLAGS; i++) |
1448 |
if (domain->flags[i]) |
if (domain->flags[i]) |
1449 |
ccs_set_string(head, ccs_dif[i]); |
ccs_set_string(head, ccs_dif[i]); |
1638 |
static const struct { |
static const struct { |
1639 |
const char *keyword; |
const char *keyword; |
1640 |
int (*write) (char *, const bool); |
int (*write) (char *, const bool); |
1641 |
} ccs_callback[4] = { |
} ccs_callback[3] = { |
1642 |
{ CCS_KEYWORD_AGGREGATOR, ccs_write_aggregator }, |
{ CCS_KEYWORD_AGGREGATOR, ccs_write_aggregator }, |
1643 |
{ CCS_KEYWORD_FILE_PATTERN, ccs_write_pattern }, |
{ CCS_KEYWORD_FILE_PATTERN, ccs_write_pattern }, |
|
{ CCS_KEYWORD_DENY_REWRITE, ccs_write_no_rewrite }, |
|
1644 |
{ CCS_KEYWORD_DENY_AUTOBIND, ccs_write_reserved_port } |
{ CCS_KEYWORD_DENY_AUTOBIND, ccs_write_reserved_port } |
1645 |
}; |
}; |
1646 |
for (i = 0; i < 4; i++) { |
for (i = 0; i < 3; i++) |
1647 |
if (ccs_str_starts(&data, ccs_callback[i].keyword)) |
if (ccs_str_starts(&data, ccs_callback[i].keyword)) |
1648 |
return ccs_callback[i].write(data, is_delete); |
return ccs_callback[i].write(data, is_delete); |
1649 |
} |
for (i = 0; i < CCS_MAX_TRANSITION_TYPE; i++) |
|
for (i = 0; i < CCS_MAX_TRANSITION_TYPE; i++) { |
|
1650 |
if (ccs_str_starts(&data, ccs_transition_type[i])) |
if (ccs_str_starts(&data, ccs_transition_type[i])) |
1651 |
return ccs_write_transition_control(data, is_delete, |
return ccs_write_transition_control(data, is_delete, |
1652 |
i); |
i); |
1653 |
} |
for (i = 0; i < CCS_MAX_GROUP; i++) |
|
for (i = 0; i < CCS_MAX_GROUP; i++) { |
|
1654 |
if (ccs_str_starts(&data, ccs_group_name[i])) |
if (ccs_str_starts(&data, ccs_group_name[i])) |
1655 |
return ccs_write_group(data, is_delete, i); |
return ccs_write_group(data, is_delete, i); |
1656 |
|
if (ccs_str_starts(&data, "acl_group ")) { |
1657 |
|
unsigned int group; |
1658 |
|
if (sscanf(data, "%u", &group) == 1 && |
1659 |
|
group < CCS_MAX_ACL_GROUPS) { |
1660 |
|
data = strchr(data, ' '); |
1661 |
|
if (data) |
1662 |
|
return ccs_write_domain2(data + 1, |
1663 |
|
&ccs_acl_group[group], |
1664 |
|
is_delete); |
1665 |
|
} |
1666 |
} |
} |
1667 |
return ccs_write_domain2(data, &ccs_global_domain, is_delete); |
return -EINVAL; |
1668 |
} |
} |
1669 |
|
|
1670 |
/** |
/** |
1775 |
ccs_set_string(head, ptr->pattern->name); |
ccs_set_string(head, ptr->pattern->name); |
1776 |
} |
} |
1777 |
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; |
|
1778 |
case CCS_ID_RESERVEDPORT: |
case CCS_ID_RESERVEDPORT: |
1779 |
{ |
{ |
1780 |
struct ccs_reserved *ptr = |
struct ccs_reserved *ptr = |
1818 |
head->r.step++; |
head->r.step++; |
1819 |
if (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP) |
if (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP) |
1820 |
return; |
return; |
1821 |
head->r.eof = ccs_read_domain2(head, &ccs_global_domain); |
while (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP |
1822 |
|
+ CCS_MAX_ACL_GROUPS) { |
1823 |
|
head->r.group_index = head->r.step - CCS_MAX_POLICY |
1824 |
|
- CCS_MAX_GROUP; |
1825 |
|
if (!ccs_read_domain2(head, |
1826 |
|
&ccs_acl_group[head->r.group_index])) |
1827 |
|
return; |
1828 |
|
head->r.step++; |
1829 |
|
} |
1830 |
|
head->r.eof = true; |
1831 |
} |
} |
1832 |
|
|
1833 |
/* Wait queue for ccs_query_list. */ |
/* Wait queue for ccs_query_list. */ |
1837 |
static DEFINE_SPINLOCK(ccs_query_list_lock); |
static DEFINE_SPINLOCK(ccs_query_list_lock); |
1838 |
|
|
1839 |
/* Structure for query. */ |
/* Structure for query. */ |
1840 |
struct ccs_query_entry { |
struct ccs_query { |
1841 |
struct list_head list; |
struct list_head list; |
1842 |
char *query; |
char *query; |
1843 |
int query_len; |
int query_len; |
1846 |
int answer; |
int answer; |
1847 |
}; |
}; |
1848 |
|
|
1849 |
/* The list for "struct ccs_query_entry". */ |
/* The list for "struct ccs_query". */ |
1850 |
static LIST_HEAD(ccs_query_list); |
static LIST_HEAD(ccs_query_list); |
1851 |
|
|
1852 |
/* Number of "struct file" referring /proc/ccs/query interface. */ |
/* Number of "struct file" referring /proc/ccs/query interface. */ |
1877 |
int pos; |
int pos; |
1878 |
int len; |
int len; |
1879 |
static unsigned int ccs_serial; |
static unsigned int ccs_serial; |
1880 |
struct ccs_query_entry *ccs_query_entry = NULL; |
struct ccs_query *entry = NULL; |
1881 |
bool quota_exceeded = false; |
bool quota_exceeded = false; |
1882 |
char *header; |
char *header; |
1883 |
struct ccs_domain_info * const domain = ccs_current_domain(); |
struct ccs_domain_info * const domain = ccs_current_domain(); |
1896 |
header = ccs_init_log(&len, r); |
header = ccs_init_log(&len, r); |
1897 |
if (!header) |
if (!header) |
1898 |
return 0; |
return 0; |
1899 |
pref = ccs_profile(r->profile)->learning; |
pref = &ccs_profile(r->profile)->preference; |
1900 |
/* strstr() will return NULL if ordering is wrong. */ |
/* strstr() will return NULL if ordering is wrong. */ |
1901 |
if (r->param_type == CCS_TYPE_PATH_ACL && |
if (r->param_type == CCS_TYPE_PATH_ACL && |
1902 |
r->param.path.operation == CCS_TYPE_EXECUTE) { |
r->param.path.operation == CCS_TYPE_EXECUTE) { |
1959 |
int i; |
int i; |
1960 |
if (current->ccs_flags & CCS_DONT_SLEEP_ON_ENFORCE_ERROR) |
if (current->ccs_flags & CCS_DONT_SLEEP_ON_ENFORCE_ERROR) |
1961 |
return -EPERM; |
return -EPERM; |
1962 |
for (i = 0; i < ccs_profile(domain->profile)->enforcing-> |
for (i = 0; i < ccs_profile(domain->profile)->preference. |
1963 |
enforcing_penalty; i++) { |
enforcing_penalty; i++) { |
1964 |
set_current_state(TASK_INTERRUPTIBLE); |
set_current_state(TASK_INTERRUPTIBLE); |
1965 |
schedule_timeout(HZ / 10); |
schedule_timeout(HZ / 10); |
1969 |
header = ccs_init_log(&len, r); |
header = ccs_init_log(&len, r); |
1970 |
if (!header) |
if (!header) |
1971 |
goto out; |
goto out; |
1972 |
ccs_query_entry = kzalloc(sizeof(*ccs_query_entry), CCS_GFP_FLAGS); |
entry = kzalloc(sizeof(*entry), CCS_GFP_FLAGS); |
1973 |
if (!ccs_query_entry) |
if (!entry) |
1974 |
goto out; |
goto out; |
1975 |
len = ccs_round2(len); |
len = ccs_round2(len); |
1976 |
ccs_query_entry->query = kzalloc(len, CCS_GFP_FLAGS); |
entry->query = kzalloc(len, CCS_GFP_FLAGS); |
1977 |
if (!ccs_query_entry->query) |
if (!entry->query) |
1978 |
goto out; |
goto out; |
|
INIT_LIST_HEAD(&ccs_query_entry->list); |
|
1979 |
spin_lock(&ccs_query_list_lock); |
spin_lock(&ccs_query_list_lock); |
1980 |
if (ccs_quota_for_query && ccs_query_memory_size + len + |
if (ccs_quota_for_query && ccs_query_memory_size + len + |
1981 |
sizeof(*ccs_query_entry) >= ccs_quota_for_query) { |
sizeof(*entry) >= ccs_quota_for_query) { |
1982 |
quota_exceeded = true; |
quota_exceeded = true; |
1983 |
} else { |
} else { |
1984 |
ccs_query_memory_size += len + sizeof(*ccs_query_entry); |
ccs_query_memory_size += len + sizeof(*entry); |
1985 |
ccs_query_entry->serial = ccs_serial++; |
entry->serial = ccs_serial++; |
1986 |
} |
} |
1987 |
spin_unlock(&ccs_query_list_lock); |
spin_unlock(&ccs_query_list_lock); |
1988 |
if (quota_exceeded) |
if (quota_exceeded) |
1989 |
goto out; |
goto out; |
1990 |
pos = snprintf(ccs_query_entry->query, len - 1, "Q%u-%hu\n%s", |
pos = snprintf(entry->query, len - 1, "Q%u-%hu\n%s", |
1991 |
ccs_query_entry->serial, r->retry, header); |
entry->serial, r->retry, header); |
1992 |
kfree(header); |
kfree(header); |
1993 |
header = NULL; |
header = NULL; |
1994 |
va_start(args, fmt); |
va_start(args, fmt); |
1995 |
vsnprintf(ccs_query_entry->query + pos, len - 1 - pos, fmt, args); |
vsnprintf(entry->query + pos, len - 1 - pos, fmt, args); |
1996 |
ccs_query_entry->query_len = strlen(ccs_query_entry->query) + 1; |
entry->query_len = strlen(entry->query) + 1; |
1997 |
va_end(args); |
va_end(args); |
1998 |
spin_lock(&ccs_query_list_lock); |
spin_lock(&ccs_query_list_lock); |
1999 |
list_add_tail(&ccs_query_entry->list, &ccs_query_list); |
list_add_tail(&entry->list, &ccs_query_list); |
2000 |
spin_unlock(&ccs_query_list_lock); |
spin_unlock(&ccs_query_list_lock); |
2001 |
/* Give 10 seconds for supervisor's opinion. */ |
/* Give 10 seconds for supervisor's opinion. */ |
2002 |
for (ccs_query_entry->timer = 0; |
for (entry->timer = 0; |
2003 |
atomic_read(&ccs_query_observers) && ccs_query_entry->timer < 100; |
atomic_read(&ccs_query_observers) && entry->timer < 100; |
2004 |
ccs_query_entry->timer++) { |
entry->timer++) { |
2005 |
wake_up(&ccs_query_wait); |
wake_up(&ccs_query_wait); |
2006 |
set_current_state(TASK_INTERRUPTIBLE); |
set_current_state(TASK_INTERRUPTIBLE); |
2007 |
schedule_timeout(HZ / 10); |
schedule_timeout(HZ / 10); |
2008 |
if (ccs_query_entry->answer) |
if (entry->answer) |
2009 |
break; |
break; |
2010 |
} |
} |
2011 |
spin_lock(&ccs_query_list_lock); |
spin_lock(&ccs_query_list_lock); |
2012 |
list_del(&ccs_query_entry->list); |
list_del(&entry->list); |
2013 |
ccs_query_memory_size -= len + sizeof(*ccs_query_entry); |
ccs_query_memory_size -= len + sizeof(*entry); |
2014 |
spin_unlock(&ccs_query_list_lock); |
spin_unlock(&ccs_query_list_lock); |
2015 |
switch (ccs_query_entry->answer) { |
switch (entry->answer) { |
2016 |
case 3: /* Asked to retry by administrator. */ |
case 3: /* Asked to retry by administrator. */ |
2017 |
error = CCS_RETRY_REQUEST; |
error = CCS_RETRY_REQUEST; |
2018 |
r->retry++; |
r->retry++; |
2029 |
break; |
break; |
2030 |
} |
} |
2031 |
out: |
out: |
2032 |
if (ccs_query_entry) |
if (entry) |
2033 |
kfree(ccs_query_entry->query); |
kfree(entry->query); |
2034 |
kfree(ccs_query_entry); |
kfree(entry); |
2035 |
kfree(header); |
kfree(header); |
2036 |
return error; |
return error; |
2037 |
} |
} |
2054 |
for (i = 0; i < 2; i++) { |
for (i = 0; i < 2; i++) { |
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 = |
2058 |
list_entry(tmp, struct ccs_query_entry, list); |
list_entry(tmp, typeof(*ptr), list); |
2059 |
if (ptr->answer) |
if (ptr->answer) |
2060 |
continue; |
continue; |
2061 |
found = true; |
found = true; |
2090 |
} |
} |
2091 |
spin_lock(&ccs_query_list_lock); |
spin_lock(&ccs_query_list_lock); |
2092 |
list_for_each(tmp, &ccs_query_list) { |
list_for_each(tmp, &ccs_query_list) { |
2093 |
struct ccs_query_entry *ptr |
struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list); |
|
= list_entry(tmp, struct ccs_query_entry, list); |
|
2094 |
if (ptr->answer) |
if (ptr->answer) |
2095 |
continue; |
continue; |
2096 |
if (pos++ != head->r.query_index) |
if (pos++ != head->r.query_index) |
2109 |
pos = 0; |
pos = 0; |
2110 |
spin_lock(&ccs_query_list_lock); |
spin_lock(&ccs_query_list_lock); |
2111 |
list_for_each(tmp, &ccs_query_list) { |
list_for_each(tmp, &ccs_query_list) { |
2112 |
struct ccs_query_entry *ptr |
struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list); |
|
= list_entry(tmp, struct ccs_query_entry, list); |
|
2113 |
if (ptr->answer) |
if (ptr->answer) |
2114 |
continue; |
continue; |
2115 |
if (pos++ != head->r.query_index) |
if (pos++ != head->r.query_index) |
2147 |
unsigned int answer; |
unsigned int answer; |
2148 |
spin_lock(&ccs_query_list_lock); |
spin_lock(&ccs_query_list_lock); |
2149 |
list_for_each(tmp, &ccs_query_list) { |
list_for_each(tmp, &ccs_query_list) { |
2150 |
struct ccs_query_entry *ptr |
struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list); |
|
= list_entry(tmp, struct ccs_query_entry, list); |
|
2151 |
ptr->timer = 0; |
ptr->timer = 0; |
2152 |
} |
} |
2153 |
spin_unlock(&ccs_query_list_lock); |
spin_unlock(&ccs_query_list_lock); |
2155 |
return -EINVAL; |
return -EINVAL; |
2156 |
spin_lock(&ccs_query_list_lock); |
spin_lock(&ccs_query_list_lock); |
2157 |
list_for_each(tmp, &ccs_query_list) { |
list_for_each(tmp, &ccs_query_list) { |
2158 |
struct ccs_query_entry *ptr |
struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list); |
|
= list_entry(tmp, struct ccs_query_entry, list); |
|
2159 |
if (ptr->serial != serial) |
if (ptr->serial != serial) |
2160 |
continue; |
continue; |
2161 |
if (!ptr->answer) |
if (!ptr->answer) |
2175 |
{ |
{ |
2176 |
if (head->r.eof) |
if (head->r.eof) |
2177 |
return; |
return; |
2178 |
ccs_set_string(head, "1.7.2"); |
ccs_set_string(head, "1.8.0-pre"); |
2179 |
head->r.eof = true; |
head->r.eof = true; |
2180 |
} |
} |
2181 |
|
|