5 |
* |
* |
6 |
* Copyright (C) 2005-2008 NTT DATA CORPORATION |
* Copyright (C) 2005-2008 NTT DATA CORPORATION |
7 |
* |
* |
8 |
* Version: 1.6.1 2008/05/10 |
* Version: 1.6.5-pre 2008/09/09 |
9 |
* |
* |
10 |
* 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. |
11 |
* See README.ccs for ChangeLog. |
* See README.ccs for ChangeLog. |
1014 |
struct path_info r; /* real name */ |
struct path_info r; /* real name */ |
1015 |
struct path_info s; /* symlink name */ |
struct path_info s; /* symlink name */ |
1016 |
struct path_info l; /* last name */ |
struct path_info l; /* last name */ |
1017 |
|
const u32 tomoyo_flags = current->tomoyo_flags; |
1018 |
|
|
1019 |
{ |
{ |
1020 |
/* |
/* |
1031 |
} |
} |
1032 |
} |
} |
1033 |
|
|
1034 |
|
retry: |
1035 |
|
current->tomoyo_flags = tomoyo_flags; |
1036 |
/* Get ccs_realpath of program. */ |
/* Get ccs_realpath of program. */ |
1037 |
retval = -ENOENT; /* I hope ccs_realpath() won't fail with -ENOMEM. */ |
retval = -ENOENT; /* I hope ccs_realpath() won't fail with -ENOMEM. */ |
1038 |
|
ccs_free(real_program_name); |
1039 |
real_program_name = ccs_realpath(original_name); |
real_program_name = ccs_realpath(original_name); |
1040 |
if (!real_program_name) |
if (!real_program_name) |
1041 |
goto out; |
goto out; |
1042 |
/* Get ccs_realpath of symbolic link. */ |
/* Get ccs_realpath of symbolic link. */ |
1043 |
|
ccs_free(symlink_program_name); |
1044 |
symlink_program_name = ccs_realpath_nofollow(original_name); |
symlink_program_name = ccs_realpath_nofollow(original_name); |
1045 |
if (!symlink_program_name) |
if (!symlink_program_name) |
1046 |
goto out; |
goto out; |
1097 |
base_filename++; |
base_filename++; |
1098 |
if (strcmp(base_argv0, base_filename)) { |
if (strcmp(base_argv0, base_filename)) { |
1099 |
retval = ccs_check_argv0_perm(&r, base_argv0); |
retval = ccs_check_argv0_perm(&r, base_argv0); |
1100 |
if (retval) |
if (retval == 1) |
1101 |
|
goto retry; |
1102 |
|
if (retval < 0) |
1103 |
goto out; |
goto out; |
1104 |
} |
} |
1105 |
} |
} |
1122 |
|
|
1123 |
/* Check execute permission. */ |
/* Check execute permission. */ |
1124 |
retval = ccs_check_exec_perm(&r, bprm, tmp); |
retval = ccs_check_exec_perm(&r, bprm, tmp); |
1125 |
|
if (retval == 1) |
1126 |
|
goto retry; |
1127 |
if (retval < 0) |
if (retval < 0) |
1128 |
goto out; |
goto out; |
1129 |
|
|
1153 |
domain = ccs_find_domain(new_domain_name); |
domain = ccs_find_domain(new_domain_name); |
1154 |
if (domain) |
if (domain) |
1155 |
goto done; |
goto done; |
1156 |
if (is_enforce && ccs_check_supervisor("#Need to create domain\n%s\n", |
if (is_enforce) { |
1157 |
new_domain_name)) |
int error = ccs_check_supervisor(NULL, |
1158 |
|
"# wants to create domain\n" |
1159 |
|
"%s\n", new_domain_name); |
1160 |
|
if (error == 1) |
1161 |
|
goto retry; |
1162 |
|
if (error < 0) |
1163 |
goto done; |
goto done; |
1164 |
|
} |
1165 |
domain = ccs_find_or_assign_new_domain(new_domain_name, |
domain = ccs_find_or_assign_new_domain(new_domain_name, |
1166 |
old_domain->profile); |
old_domain->profile); |
1167 |
if (domain) |
if (domain) |
1173 |
new_domain_name); |
new_domain_name); |
1174 |
if (is_enforce) |
if (is_enforce) |
1175 |
retval = -EPERM; |
retval = -EPERM; |
1176 |
else |
else { |
1177 |
|
retval = 0; |
1178 |
ccs_set_domain_flag(old_domain, false, |
ccs_set_domain_flag(old_domain, false, |
1179 |
DOMAIN_FLAGS_TRANSITION_FAILED); |
DOMAIN_FLAGS_TRANSITION_FAILED); |
1180 |
|
} |
1181 |
} else { |
} else { |
1182 |
retval = 0; |
retval = 0; |
1183 |
} |
} |
1332 |
{ |
{ |
1333 |
int depth = 0; |
int depth = 0; |
1334 |
/***** CRITICAL SECTION START *****/ |
/***** CRITICAL SECTION START *****/ |
1335 |
spin_lock(&dcache_lock); |
ccs_realpath_lock(); |
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0) |
|
|
spin_lock(&vfsmount_lock); |
|
|
#endif |
|
1336 |
for (;;) { |
for (;;) { |
1337 |
if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) { |
if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) { |
1338 |
/* Global root? */ |
/* Global root? */ |
1345 |
dentry = dentry->d_parent; |
dentry = dentry->d_parent; |
1346 |
depth++; |
depth++; |
1347 |
} |
} |
1348 |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0) |
ccs_realpath_unlock(); |
|
spin_unlock(&vfsmount_lock); |
|
|
#endif |
|
|
spin_unlock(&dcache_lock); |
|
1349 |
/***** CRITICAL SECTION END *****/ |
/***** CRITICAL SECTION END *****/ |
1350 |
return depth; |
return depth; |
1351 |
} |
} |
1390 |
* try_alt_exec - Try to start execute handler. |
* try_alt_exec - Try to start execute handler. |
1391 |
* |
* |
1392 |
* @bprm: Pointer to "struct linux_binprm". |
* @bprm: Pointer to "struct linux_binprm". |
1393 |
* @filename: The name of requested program. |
* @handler: Pointer to the name of execute handler. |
1394 |
* @work: Pointer to pointer to the name of execute handler. |
* @eh_path: Pointer to pointer to the name of execute handler. |
1395 |
* @next_domain: Pointer to pointer to "struct domain_info". |
* @next_domain: Pointer to pointer to "struct domain_info". |
1396 |
* @tmp: Buffer for temporal use. |
* @tmp: Buffer for temporal use. |
1397 |
* |
* |
1398 |
* Returns 0 on success, negative value otherwise. |
* Returns 0 on success, negative value otherwise. |
1399 |
*/ |
*/ |
1400 |
static int try_alt_exec(struct linux_binprm *bprm, |
static int try_alt_exec(struct linux_binprm *bprm, |
1401 |
const struct path_info *filename, char **work, |
const struct path_info *handler, char **eh_path, |
1402 |
struct domain_info **next_domain, |
struct domain_info **next_domain, |
1403 |
struct ccs_page_buffer *tmp) |
struct ccs_page_buffer *tmp) |
1404 |
{ |
{ |
1446 |
char *buffer = tmp->buffer; |
char *buffer = tmp->buffer; |
1447 |
/* Allocate memory for execute handler's pathname. */ |
/* Allocate memory for execute handler's pathname. */ |
1448 |
char *execute_handler = ccs_alloc(sizeof(struct ccs_page_buffer)); |
char *execute_handler = ccs_alloc(sizeof(struct ccs_page_buffer)); |
1449 |
*work = execute_handler; |
*eh_path = execute_handler; |
1450 |
if (!execute_handler) |
if (!execute_handler) |
1451 |
return -ENOMEM; |
return -ENOMEM; |
1452 |
strncpy(execute_handler, filename->name, |
strncpy(execute_handler, handler->name, |
1453 |
sizeof(struct ccs_page_buffer) - 1); |
sizeof(struct ccs_page_buffer) - 1); |
1454 |
unescape(execute_handler); |
unescape(execute_handler); |
1455 |
|
|
1575 |
if (retval < 0) |
if (retval < 0) |
1576 |
goto out; |
goto out; |
1577 |
task->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR; |
task->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR; |
1578 |
retval = find_next_domain(bprm, next_domain, filename, tmp); |
retval = find_next_domain(bprm, next_domain, handler, tmp); |
1579 |
task->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR; |
task->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR; |
1580 |
out: |
out: |
1581 |
return retval; |
return retval; |
1627 |
const struct path_info *handler; |
const struct path_info *handler; |
1628 |
int retval; |
int retval; |
1629 |
/* |
/* |
1630 |
* "work" holds path to program. |
* "eh_path" holds path to execute handler program. |
1631 |
* Thus, keep valid until search_binary_handler() finishes. |
* Thus, keep valid until search_binary_handler() finishes. |
1632 |
*/ |
*/ |
1633 |
char *work = NULL; |
char *eh_path = NULL; |
1634 |
struct ccs_page_buffer *buf = ccs_alloc(sizeof(struct ccs_page_buffer)); |
struct ccs_page_buffer *tmp = ccs_alloc(sizeof(struct ccs_page_buffer)); |
1635 |
ccs_load_policy(bprm->filename); |
ccs_load_policy(bprm->filename); |
1636 |
if (!buf) |
if (!tmp) |
1637 |
return -ENOMEM; |
return -ENOMEM; |
1638 |
/* printk(KERN_DEBUG "rootdepth=%d\n", get_root_depth()); */ |
/* printk(KERN_DEBUG "rootdepth=%d\n", get_root_depth()); */ |
1639 |
handler = find_execute_handler(TYPE_EXECUTE_HANDLER); |
handler = find_execute_handler(TYPE_EXECUTE_HANDLER); |
1640 |
if (handler) { |
if (handler) { |
1641 |
retval = try_alt_exec(bprm, handler, &work, &next_domain, buf); |
retval = try_alt_exec(bprm, handler, &eh_path, &next_domain, |
1642 |
|
tmp); |
1643 |
if (!retval) |
if (!retval) |
1644 |
audit_execute_handler_log(true, work, bprm); |
audit_execute_handler_log(true, handler->name, bprm); |
1645 |
goto ok; |
goto ok; |
1646 |
} |
} |
1647 |
retval = find_next_domain(bprm, &next_domain, NULL, buf); |
retval = find_next_domain(bprm, &next_domain, NULL, tmp); |
1648 |
if (retval != -EPERM) |
if (retval != -EPERM) |
1649 |
goto ok; |
goto ok; |
1650 |
handler = find_execute_handler(TYPE_DENIED_EXECUTE_HANDLER); |
handler = find_execute_handler(TYPE_DENIED_EXECUTE_HANDLER); |
1651 |
if (handler) { |
if (handler) { |
1652 |
retval = try_alt_exec(bprm, handler, &work, &next_domain, buf); |
retval = try_alt_exec(bprm, handler, &eh_path, &next_domain, |
1653 |
|
tmp); |
1654 |
if (!retval) |
if (!retval) |
1655 |
audit_execute_handler_log(false, work, bprm); |
audit_execute_handler_log(false, handler->name, bprm); |
1656 |
} |
} |
1657 |
ok: |
ok: |
1658 |
if (retval) |
if (retval < 0) |
1659 |
goto out; |
goto out; |
1660 |
task->domain_info = next_domain; |
task->domain_info = next_domain; |
1661 |
retval = check_environ(bprm, buf); |
retval = check_environ(bprm, tmp); |
1662 |
if (retval) |
if (retval < 0) |
1663 |
goto out; |
goto out; |
1664 |
task->tomoyo_flags |= TOMOYO_CHECK_READ_FOR_OPEN_EXEC; |
task->tomoyo_flags |= TOMOYO_CHECK_READ_FOR_OPEN_EXEC; |
1665 |
retval = search_binary_handler(bprm, regs); |
retval = search_binary_handler(bprm, regs); |
1674 |
/* Mark the current process as normal process. */ |
/* Mark the current process as normal process. */ |
1675 |
else |
else |
1676 |
task->tomoyo_flags &= ~TOMOYO_TASK_IS_EXECUTE_HANDLER; |
task->tomoyo_flags &= ~TOMOYO_TASK_IS_EXECUTE_HANDLER; |
1677 |
ccs_free(work); |
ccs_free(eh_path); |
1678 |
ccs_free(buf); |
ccs_free(tmp); |
1679 |
return retval; |
return retval; |
1680 |
} |
} |
1681 |
|
|