58 |
/* Has /sbin/init started? */ |
/* Has /sbin/init started? */ |
59 |
bool sbin_init_started; |
bool sbin_init_started; |
60 |
|
|
61 |
|
/* Domain for keeping system policy. */ |
62 |
|
static struct domain_info ccs_system_policy; |
63 |
|
|
64 |
/* Log level for SAKURA's printk(). */ |
/* Log level for SAKURA's printk(). */ |
65 |
const char *ccs_log_level = KERN_DEBUG; |
const char *ccs_log_level = KERN_DEBUG; |
66 |
|
|
1121 |
if (!cp) |
if (!cp) |
1122 |
return -EINVAL; |
return -EINVAL; |
1123 |
*cp = '\0'; |
*cp = '\0'; |
|
ccs_update_counter(CCS_UPDATES_COUNTER_PROFILE); |
|
1124 |
if (!strcmp(data, "COMMENT")) { |
if (!strcmp(data, "COMMENT")) { |
1125 |
profile->comment = ccs_save_name(cp + 1); |
profile->comment = ccs_save_name(cp + 1); |
1126 |
return 0; |
return 0; |
1338 |
error = 0; |
error = 0; |
1339 |
out: |
out: |
1340 |
mutex_unlock(&lock); |
mutex_unlock(&lock); |
|
if (!error) |
|
|
ccs_update_counter(CCS_UPDATES_COUNTER_MANAGER); |
|
1341 |
return error; |
return error; |
1342 |
} |
} |
1343 |
|
|
1554 |
else |
else |
1555 |
domain = ccs_find_or_assign_new_domain(data, 0); |
domain = ccs_find_or_assign_new_domain(data, 0); |
1556 |
head->write_var1 = domain; |
head->write_var1 = domain; |
|
ccs_update_counter(CCS_UPDATES_COUNTER_DOMAIN_POLICY); |
|
1557 |
return 0; |
return 0; |
1558 |
} |
} |
1559 |
if (!domain) |
if (!domain) |
1592 |
return ccs_write_argv0_policy(data, domain, cond, is_delete); |
return ccs_write_argv0_policy(data, domain, cond, is_delete); |
1593 |
else if (str_starts(&data, KEYWORD_ALLOW_ENV)) |
else if (str_starts(&data, KEYWORD_ALLOW_ENV)) |
1594 |
return ccs_write_env_policy(data, domain, cond, is_delete); |
return ccs_write_env_policy(data, domain, cond, is_delete); |
1595 |
|
else if (str_starts(&data, KEYWORD_ALLOW_MOUNT)) |
1596 |
|
return ccs_write_mount_policy(data, domain, cond, is_delete); |
1597 |
|
else if (str_starts(&data, KEYWORD_DENY_UNMOUNT)) |
1598 |
|
return ccs_write_no_umount_policy(data, domain, cond, is_delete); |
1599 |
|
else if (str_starts(&data, KEYWORD_ALLOW_CHROOT)) |
1600 |
|
return ccs_write_chroot_policy(data, domain, cond, is_delete); |
1601 |
|
else if (str_starts(&data, KEYWORD_ALLOW_PIVOT_ROOT)) |
1602 |
|
return ccs_write_pivot_root_policy(data, domain, cond, is_delete); |
1603 |
|
else if (str_starts(&data, KEYWORD_DENY_AUTOBIND)) |
1604 |
|
return ccs_write_reserved_port_policy(data, is_delete); |
1605 |
else |
else |
1606 |
return ccs_write_file_policy(data, domain, cond, is_delete); |
return ccs_write_file_policy(data, domain, cond, is_delete); |
1607 |
} |
} |
1888 |
* print_signal_acl - Print a signal ACL entry. |
* print_signal_acl - Print a signal ACL entry. |
1889 |
* |
* |
1890 |
* @head: Pointer to "struct ccs_io_buffer". |
* @head: Pointer to "struct ccs_io_buffer". |
1891 |
* @ptr: Pointer to "struct signale_acl_record". |
* @ptr: Pointer to "struct signal_acl_record". |
1892 |
* @cond: Pointer to "struct condition_list". May be NULL. |
* @cond: Pointer to "struct condition_list". May be NULL. |
1893 |
* |
* |
1894 |
* Returns true on success, false otherwise. |
* Returns true on success, false otherwise. |
1926 |
} |
} |
1927 |
|
|
1928 |
/** |
/** |
1929 |
|
* print_no_umount_acl - Print a deny_umount ACL entry. |
1930 |
|
* |
1931 |
|
* @head: Pointer to "struct ccs_io_buffer". |
1932 |
|
* @ptr: Pointer to "struct no_umount_entry". |
1933 |
|
* @cond: Pointer to "struct condition_list". May be NULL. |
1934 |
|
* |
1935 |
|
* Returns true on success, false otherwise. |
1936 |
|
*/ |
1937 |
|
static bool print_no_umount_acl(struct ccs_io_buffer *head, |
1938 |
|
struct no_umount_entry *ptr, |
1939 |
|
const struct condition_list *cond) |
1940 |
|
{ |
1941 |
|
int pos = head->read_avail; |
1942 |
|
if (!ccs_io_printf(head, KEYWORD_DENY_UNMOUNT "%s", ptr->dir->name)) |
1943 |
|
goto out; |
1944 |
|
if (!ccs_print_condition(head, cond)) |
1945 |
|
goto out; |
1946 |
|
return true; |
1947 |
|
out: |
1948 |
|
head->read_avail = pos; |
1949 |
|
return false; |
1950 |
|
} |
1951 |
|
|
1952 |
|
/** |
1953 |
|
* print_mount_acl - Print a umount ACL entry. |
1954 |
|
* |
1955 |
|
* @head: Pointer to "struct ccs_io_buffer". |
1956 |
|
* @ptr: Pointer to "struct mount_entry". |
1957 |
|
* @cond: Pointer to "struct condition_list". May be NULL. |
1958 |
|
* |
1959 |
|
* Returns true on success, false otherwise. |
1960 |
|
*/ |
1961 |
|
static bool print_mount_acl(struct ccs_io_buffer *head, |
1962 |
|
struct mount_entry *ptr, |
1963 |
|
const struct condition_list *cond) |
1964 |
|
{ |
1965 |
|
int pos = head->read_avail; |
1966 |
|
if (!ccs_io_printf(head, KEYWORD_ALLOW_MOUNT "%s %s %s 0x%lX", |
1967 |
|
ptr->dev_name->name, ptr->dir_name->name, |
1968 |
|
ptr->fs_type->name, ptr->flags)) |
1969 |
|
goto out; |
1970 |
|
if (!ccs_print_condition(head, cond)) |
1971 |
|
goto out; |
1972 |
|
return true; |
1973 |
|
out: |
1974 |
|
head->read_avail = pos; |
1975 |
|
return false; |
1976 |
|
} |
1977 |
|
|
1978 |
|
/** |
1979 |
|
* print_chroot_acl - Print a chroot ACL entry. |
1980 |
|
* |
1981 |
|
* @head: Pointer to "struct ccs_io_buffer". |
1982 |
|
* @ptr: Pointer to "struct chroot_entry". |
1983 |
|
* @cond: Pointer to "struct condition_list". May be NULL. |
1984 |
|
* |
1985 |
|
* Returns true on success, false otherwise. |
1986 |
|
*/ |
1987 |
|
static bool print_chroot_acl(struct ccs_io_buffer *head, |
1988 |
|
struct chroot_entry *ptr, |
1989 |
|
const struct condition_list *cond) |
1990 |
|
{ |
1991 |
|
int pos = head->read_avail; |
1992 |
|
if (!ccs_io_printf(head, KEYWORD_ALLOW_CHROOT "%s", ptr->dir->name)) |
1993 |
|
goto out; |
1994 |
|
if (!ccs_print_condition(head, cond)) |
1995 |
|
goto out; |
1996 |
|
return true; |
1997 |
|
out: |
1998 |
|
head->read_avail = pos; |
1999 |
|
return false; |
2000 |
|
} |
2001 |
|
|
2002 |
|
/** |
2003 |
|
* print_pivot_root_acl - Print a pivot_root ACL entry. |
2004 |
|
* |
2005 |
|
* @head: Pointer to "struct ccs_io_buffer". |
2006 |
|
* @ptr: Pointer to "struct chroot_entry". |
2007 |
|
* @cond: Pointer to "struct condition_list". May be NULL. |
2008 |
|
* |
2009 |
|
* Returns true on success, false otherwise. |
2010 |
|
*/ |
2011 |
|
static bool print_pivot_root_acl(struct ccs_io_buffer *head, |
2012 |
|
struct pivot_root_entry *ptr, |
2013 |
|
const struct condition_list *cond) |
2014 |
|
{ |
2015 |
|
int pos = head->read_avail; |
2016 |
|
if (!ccs_io_printf(head, KEYWORD_ALLOW_PIVOT_ROOT |
2017 |
|
"%s %s", ptr->new_root->name, |
2018 |
|
ptr->old_root->name)) |
2019 |
|
goto out; |
2020 |
|
if (!ccs_print_condition(head, cond)) |
2021 |
|
goto out; |
2022 |
|
return true; |
2023 |
|
out: |
2024 |
|
head->read_avail = pos; |
2025 |
|
return false; |
2026 |
|
} |
2027 |
|
|
2028 |
|
/** |
2029 |
* print_entry - Print an ACL entry. |
* print_entry - Print an ACL entry. |
2030 |
* |
* |
2031 |
* @head: Pointer to "struct ccs_io_buffer". |
* @head: Pointer to "struct ccs_io_buffer". |
2090 |
const char *keyword = KEYWORD_DENIED_EXECUTE_HANDLER; |
const char *keyword = KEYWORD_DENIED_EXECUTE_HANDLER; |
2091 |
return print_execute_handler_record(head, keyword, acl); |
return print_execute_handler_record(head, keyword, acl); |
2092 |
} |
} |
2093 |
|
if (acl_type == TYPE_NO_UMOUNT_ACL) { |
2094 |
|
struct no_umount_entry *acl |
2095 |
|
= list1_entry(ptr, struct no_umount_entry, head); |
2096 |
|
return print_no_umount_acl(head, acl, cond); |
2097 |
|
} |
2098 |
|
if (acl_type == TYPE_MOUNT_ACL) { |
2099 |
|
struct mount_entry *acl |
2100 |
|
= list1_entry(ptr, struct mount_entry, head); |
2101 |
|
return print_mount_acl(head, acl, cond); |
2102 |
|
} |
2103 |
|
if (acl_type == TYPE_CHROOT_ACL) { |
2104 |
|
struct chroot_entry *acl |
2105 |
|
= list1_entry(ptr, struct chroot_entry, head); |
2106 |
|
return print_chroot_acl(head, acl, cond); |
2107 |
|
} |
2108 |
|
if (acl_type == TYPE_PIVOT_ROOT_ACL) { |
2109 |
|
struct pivot_root_entry *acl |
2110 |
|
= list1_entry(ptr, struct pivot_root_entry, head); |
2111 |
|
return print_pivot_root_acl(head, acl, cond); |
2112 |
|
} |
2113 |
/* Workaround for gcc 3.2.2's inline bug. */ |
/* Workaround for gcc 3.2.2's inline bug. */ |
2114 |
if (acl_type & ACL_DELETED) |
if (acl_type & ACL_DELETED) |
2115 |
return true; |
return true; |
2213 |
if (domain && profile < MAX_PROFILES |
if (domain && profile < MAX_PROFILES |
2214 |
&& (profile_ptr[profile] || !sbin_init_started)) |
&& (profile_ptr[profile] || !sbin_init_started)) |
2215 |
domain->profile = (u8) profile; |
domain->profile = (u8) profile; |
|
ccs_update_counter(CCS_UPDATES_COUNTER_DOMAIN_POLICY); |
|
2216 |
return 0; |
return 0; |
2217 |
} |
} |
2218 |
|
|
2442 |
*/ |
*/ |
2443 |
static int write_system_policy(struct ccs_io_buffer *head) |
static int write_system_policy(struct ccs_io_buffer *head) |
2444 |
{ |
{ |
2445 |
|
const struct condition_list *cond = NULL; |
2446 |
char *data = head->write_buf; |
char *data = head->write_buf; |
2447 |
bool is_delete = false; |
bool is_delete = false; |
2448 |
|
char *cp = ccs_find_condition_part(data); |
2449 |
|
if (cp) { |
2450 |
|
cond = ccs_find_or_assign_new_condition(cp); |
2451 |
|
if (!cond) |
2452 |
|
return -EINVAL; |
2453 |
|
} |
2454 |
if (str_starts(&data, KEYWORD_DELETE)) |
if (str_starts(&data, KEYWORD_DELETE)) |
2455 |
is_delete = true; |
is_delete = true; |
2456 |
if (str_starts(&data, KEYWORD_ALLOW_MOUNT)) |
if (str_starts(&data, KEYWORD_ALLOW_MOUNT)) |
2457 |
return ccs_write_mount_policy(data, is_delete); |
return ccs_write_mount_policy(data, &ccs_system_policy, cond, |
2458 |
if (str_starts(&data, KEYWORD_DENY_UNMOUNT)) |
is_delete); |
2459 |
return ccs_write_no_umount_policy(data, is_delete); |
else if (str_starts(&data, KEYWORD_DENY_UNMOUNT)) |
2460 |
if (str_starts(&data, KEYWORD_ALLOW_CHROOT)) |
return ccs_write_no_umount_policy(data, &ccs_system_policy, |
2461 |
return ccs_write_chroot_policy(data, is_delete); |
cond, is_delete); |
2462 |
if (str_starts(&data, KEYWORD_ALLOW_PIVOT_ROOT)) |
else if (str_starts(&data, KEYWORD_ALLOW_CHROOT)) |
2463 |
return ccs_write_pivot_root_policy(data, is_delete); |
return ccs_write_chroot_policy(data, &ccs_system_policy, cond, |
2464 |
if (str_starts(&data, KEYWORD_DENY_AUTOBIND)) |
is_delete); |
2465 |
|
else if (str_starts(&data, KEYWORD_ALLOW_PIVOT_ROOT)) |
2466 |
|
return ccs_write_pivot_root_policy(data, &ccs_system_policy, |
2467 |
|
cond, is_delete); |
2468 |
|
else if (str_starts(&data, KEYWORD_DENY_AUTOBIND)) |
2469 |
return ccs_write_reserved_port_policy(data, is_delete); |
return ccs_write_reserved_port_policy(data, is_delete); |
2470 |
return -EINVAL; |
return -EINVAL; |
2471 |
} |
} |
2472 |
|
|
2473 |
/** |
/** |
2474 |
|
* ccs_read_system_policy - Read system policy list. |
2475 |
|
* |
2476 |
|
* @head: Pointer to "struct ccs_io_buffer". |
2477 |
|
* |
2478 |
|
* Returns true on success, false otherwise. |
2479 |
|
*/ |
2480 |
|
static bool ccs_read_system_policy(struct ccs_io_buffer *head) |
2481 |
|
{ |
2482 |
|
struct list1_head *pos; |
2483 |
|
/* Print ACL entries in the domain. */ |
2484 |
|
list1_for_each_cookie(pos, head->read_var2, |
2485 |
|
&ccs_system_policy.acl_info_list) { |
2486 |
|
struct acl_info *ptr = list1_entry(pos, struct acl_info, list); |
2487 |
|
if (!print_entry(head, ptr)) |
2488 |
|
return false; |
2489 |
|
} |
2490 |
|
return true; |
2491 |
|
} |
2492 |
|
|
2493 |
|
/** |
2494 |
* read_system_policy - Read system policy. |
* read_system_policy - Read system policy. |
2495 |
* |
* |
2496 |
* @head: Pointer to "struct ccs_io_buffer". |
* @head: Pointer to "struct ccs_io_buffer". |
2505 |
head->read_var2 = NULL; |
head->read_var2 = NULL; |
2506 |
head->read_step = 1; |
head->read_step = 1; |
2507 |
case 1: |
case 1: |
2508 |
if (!ccs_read_mount_policy(head)) |
if (!ccs_read_system_policy(head)) |
2509 |
break; |
break; |
2510 |
head->read_var2 = NULL; |
head->read_var2 = NULL; |
2511 |
head->read_step = 2; |
head->read_step = 2; |
2512 |
case 2: |
case 2: |
|
if (!ccs_read_no_umount_policy(head)) |
|
|
break; |
|
|
head->read_var2 = NULL; |
|
|
head->read_step = 3; |
|
|
case 3: |
|
|
if (!ccs_read_chroot_policy(head)) |
|
|
break; |
|
|
head->read_var2 = NULL; |
|
|
head->read_step = 4; |
|
|
case 4: |
|
|
if (!ccs_read_pivot_root_policy(head)) |
|
|
break; |
|
|
head->read_var2 = NULL; |
|
|
head->read_step = 5; |
|
|
case 5: |
|
2513 |
if (!ccs_read_reserved_port_policy(head)) |
if (!ccs_read_reserved_port_policy(head)) |
2514 |
break; |
break; |
2515 |
head->read_eof = true; |
head->read_eof = true; |
2785 |
list_add_tail(&query_entry->list, &query_list); |
list_add_tail(&query_entry->list, &query_list); |
2786 |
spin_unlock(&query_list_lock); |
spin_unlock(&query_list_lock); |
2787 |
/***** CRITICAL SECTION END *****/ |
/***** CRITICAL SECTION END *****/ |
|
ccs_update_counter(CCS_UPDATES_COUNTER_QUERY); |
|
2788 |
/* Give 10 seconds for supervisor's opinion. */ |
/* Give 10 seconds for supervisor's opinion. */ |
2789 |
for (query_entry->timer = 0; atomic_read(&queryd_watcher) |
for (query_entry->timer = 0; atomic_read(&queryd_watcher) |
2790 |
&& query_entry->timer < 100; query_entry->timer++) { |
&& query_entry->timer < 100; query_entry->timer++) { |
2794 |
if (query_entry->answer) |
if (query_entry->answer) |
2795 |
break; |
break; |
2796 |
} |
} |
|
ccs_update_counter(CCS_UPDATES_COUNTER_QUERY); |
|
2797 |
/***** CRITICAL SECTION START *****/ |
/***** CRITICAL SECTION START *****/ |
2798 |
spin_lock(&query_list_lock); |
spin_lock(&query_list_lock); |
2799 |
list_del(&query_entry->list); |
list_del(&query_entry->list); |
2972 |
return 0; |
return 0; |
2973 |
} |
} |
2974 |
|
|
|
/* Policy updates counter. */ |
|
|
static unsigned int updates_counter[MAX_CCS_UPDATES_COUNTER]; |
|
|
|
|
|
/* Policy updates counter lock. */ |
|
|
static DEFINE_SPINLOCK(updates_counter_lock); |
|
|
|
|
|
/** |
|
|
* ccs_update_counter - Increment policy change counter. |
|
|
* |
|
|
* @index: Type of policy. |
|
|
* |
|
|
* Returns nothing. |
|
|
*/ |
|
|
void ccs_update_counter(const unsigned char index) |
|
|
{ |
|
|
/***** CRITICAL SECTION START *****/ |
|
|
spin_lock(&updates_counter_lock); |
|
|
if (index < MAX_CCS_UPDATES_COUNTER) |
|
|
updates_counter[index]++; |
|
|
spin_unlock(&updates_counter_lock); |
|
|
/***** CRITICAL SECTION END *****/ |
|
|
} |
|
|
|
|
|
/** |
|
|
* read_updates_counter - Check for policy change counter. |
|
|
* |
|
|
* @head: Pointer to "struct ccs_io_buffer". |
|
|
* |
|
|
* Returns how many times policy has changed since the previous check. |
|
|
*/ |
|
|
static int read_updates_counter(struct ccs_io_buffer *head) |
|
|
{ |
|
|
if (!head->read_eof) { |
|
|
unsigned int counter[MAX_CCS_UPDATES_COUNTER]; |
|
|
/***** CRITICAL SECTION START *****/ |
|
|
spin_lock(&updates_counter_lock); |
|
|
memmove(counter, updates_counter, sizeof(updates_counter)); |
|
|
memset(updates_counter, 0, sizeof(updates_counter)); |
|
|
spin_unlock(&updates_counter_lock); |
|
|
/***** CRITICAL SECTION END *****/ |
|
|
ccs_io_printf(head, |
|
|
"/proc/ccs/system_policy: %10u\n" |
|
|
"/proc/ccs/domain_policy: %10u\n" |
|
|
"/proc/ccs/exception_policy: %10u\n" |
|
|
"/proc/ccs/profile: %10u\n" |
|
|
"/proc/ccs/query: %10u\n" |
|
|
"/proc/ccs/manager: %10u\n" |
|
|
"/proc/ccs/grant_log: %10u\n" |
|
|
"/proc/ccs/reject_log: %10u\n", |
|
|
counter[CCS_UPDATES_COUNTER_SYSTEM_POLICY], |
|
|
counter[CCS_UPDATES_COUNTER_DOMAIN_POLICY], |
|
|
counter[CCS_UPDATES_COUNTER_EXCEPTION_POLICY], |
|
|
counter[CCS_UPDATES_COUNTER_PROFILE], |
|
|
counter[CCS_UPDATES_COUNTER_QUERY], |
|
|
counter[CCS_UPDATES_COUNTER_MANAGER], |
|
|
counter[CCS_UPDATES_COUNTER_GRANT_LOG], |
|
|
counter[CCS_UPDATES_COUNTER_REJECT_LOG]); |
|
|
head->read_eof = true; |
|
|
} |
|
|
return 0; |
|
|
} |
|
|
|
|
2975 |
/** |
/** |
2976 |
* read_version: Get version. |
* read_version: Get version. |
2977 |
* |
* |
3089 |
head->write = write_manager_policy; |
head->write = write_manager_policy; |
3090 |
head->read = read_manager_policy; |
head->read = read_manager_policy; |
3091 |
break; |
break; |
|
case CCS_UPDATESCOUNTER: /* /proc/ccs/.updates_counter */ |
|
|
head->read = read_updates_counter; |
|
|
break; |
|
3092 |
} |
} |
3093 |
if (!(file->f_mode & FMODE_READ)) { |
if (!(file->f_mode & FMODE_READ)) { |
3094 |
/* |
/* |
3325 |
case TYPE_DENIED_EXECUTE_HANDLER: |
case TYPE_DENIED_EXECUTE_HANDLER: |
3326 |
len = sizeof(struct execute_handler_record); |
len = sizeof(struct execute_handler_record); |
3327 |
break; |
break; |
3328 |
|
case TYPE_NO_UMOUNT_ACL: |
3329 |
|
len = sizeof(struct no_umount_entry); |
3330 |
|
break; |
3331 |
|
case TYPE_MOUNT_ACL: |
3332 |
|
len = sizeof(struct mount_entry); |
3333 |
|
break; |
3334 |
|
case TYPE_CHROOT_ACL: |
3335 |
|
len = sizeof(struct chroot_entry); |
3336 |
|
break; |
3337 |
|
case TYPE_PIVOT_ROOT_ACL: |
3338 |
|
len = sizeof(struct pivot_root_entry); |
3339 |
|
break; |
3340 |
default: |
default: |
3341 |
return NULL; |
return NULL; |
3342 |
} |
} |
3364 |
ptr->type = acl_type; |
ptr->type = acl_type; |
3365 |
return ptr; |
return ptr; |
3366 |
} |
} |
3367 |
|
|
3368 |
|
/** |
3369 |
|
* ccs_common_init - Initialize realpath related code. |
3370 |
|
* |
3371 |
|
* Returns 0. |
3372 |
|
*/ |
3373 |
|
static int __init ccs_common_init(void) |
3374 |
|
{ |
3375 |
|
INIT_LIST1_HEAD(&ccs_system_policy.list); |
3376 |
|
INIT_LIST1_HEAD(&ccs_system_policy.acl_info_list); |
3377 |
|
ccs_system_policy.domainname = ccs_save_name("<SYSTEM>"); |
3378 |
|
return 0; |
3379 |
|
} |
3380 |
|
|
3381 |
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) |
3382 |
|
__initcall(ccs_common_init); |
3383 |
|
#else |
3384 |
|
core_initcall(ccs_common_init); |
3385 |
|
#endif |