diff options
author | Lauri Aarnio <Lauri.Aarnio@iki.fi> | 2008-10-09 12:00:50 +0300 |
---|---|---|
committer | Lauri Leukkunen <lle@rahina.org> | 2008-10-18 15:18:15 +0300 |
commit | bb32ad6c4372e62346ee5cfdc50479e1788e2084 (patch) | |
tree | 09e7ec87696b2a8ad570e67232dbcfa4a791b0c5 /luaif/paths.c | |
parent | 0de2d64763a7f827d67cad3360c84ce09a001c92 (diff) |
Optimized C/Lua interface and path resolution logic (performance optimizations)
Diffstat (limited to 'luaif/paths.c')
-rw-r--r-- | luaif/paths.c | 165 |
1 files changed, 100 insertions, 65 deletions
diff --git a/luaif/paths.c b/luaif/paths.c index 14ab9e2..e54f89c 100644 --- a/luaif/paths.c +++ b/luaif/paths.c @@ -307,6 +307,9 @@ static char *absolute_path(const char *path) return(cpath); } +/* returns an allocated buffer containing absolute, + * decolonized version of "path" +*/ char *sb_decolonize_path(const char *path) { char *cpath; @@ -380,7 +383,6 @@ static char *call_lua_function_sbox_translate_path( struct lua_instance *luaif, const char *binary_name, const char *func_name, - const char *work_dir, const char *decolon_path, int *ro_flagp) { @@ -400,10 +402,9 @@ static char *call_lua_function_sbox_translate_path( /* add other parameters */ lua_pushstring(luaif->lua, binary_name); lua_pushstring(luaif->lua, func_name); - lua_pushstring(luaif->lua, work_dir); lua_pushstring(luaif->lua, decolon_path); - /* 5 arguments, returns rule,policy,path,ro_flag */ - lua_call(luaif->lua, 5, 4); + /* 4 arguments, returns rule,policy,path,ro_flag */ + lua_call(luaif->lua, 4, 4); traslate_result = (char *)lua_tostring(luaif->lua, -2); if (traslate_result) { @@ -466,7 +467,6 @@ static int call_lua_function_sbox_get_mapping_requirements( struct lua_instance *luaif, const char *binary_name, const char *func_name, - const char *work_dir, const char *full_path_for_rule_selection, int *min_path_lenp) { @@ -484,10 +484,9 @@ static int call_lua_function_sbox_get_mapping_requirements( "sbox_get_mapping_requirements"); lua_pushstring(luaif->lua, binary_name); lua_pushstring(luaif->lua, func_name); - lua_pushstring(luaif->lua, work_dir); lua_pushstring(luaif->lua, full_path_for_rule_selection); - /* four arguments, returns (rule, rule_found_flag, min_path_len) */ - lua_call(luaif->lua, 4, 3); + /* 3 arguments, returns (rule, rule_found_flag, min_path_len) */ + lua_call(luaif->lua, 3, 3); rule_found = lua_toboolean(luaif->lua, -2); min_path_len = lua_tointeger(luaif->lua, -1); @@ -528,29 +527,25 @@ static void drop_from_lua_stack(struct lua_instance *luaif, * Note: when this function returns, lua stack contains the rule which was * used to do the path resolution. drop_rule_from_lua_stack() must * be called after it is not needed anymore! - * - * FIXME: It might be possible to eliminate parameter - * "full_path_for_rule_selection" now when the separate call to - * sbox_get_mapping_requirements is used to ensure that "path" is long - * enough. However, this has been left to be done in the future, together - * with other optimizations. */ static char *sb_path_resolution( int nest_count, struct lua_instance *luaif, const char *binary_name, const char *func_name, - const char *work_dir, - const char *path, - const char *full_path_for_rule_selection, + const char *abs_path, int dont_resolve_final_symlink) { - char *cpath; struct path_entry_list orig_path_list; char *buf = NULL; struct path_entry *work; int component_index = 0; int min_path_len_to_check; + char *decolon_tmp; + char *prefix_mapping_result; + struct path_entry_list prefix_path_list; + int ro_tmp; + char *path_copy; if (nest_count > 16) { SB_LOG(SB_LOGLEVEL_ERROR, @@ -569,26 +564,25 @@ static char *sb_path_resolution( return NULL; } - if (!path) { + if (!abs_path) { SB_LOG(SB_LOGLEVEL_ERROR, "sb_path_resolution called with NULL path"); return NULL; } SB_LOG(SB_LOGLEVEL_NOISE, - "sb_path_resolution %d '%s'", nest_count, path); + "sb_path_resolution %d '%s'", nest_count, abs_path); orig_path_list.pl_first = NULL; - cpath = absolute_path(path); - - split_path_to_path_entries(cpath, &orig_path_list); + path_copy = strdup(abs_path); + split_path_to_path_entries(path_copy, &orig_path_list); + free(path_copy); work = orig_path_list.pl_first; if (call_lua_function_sbox_get_mapping_requirements( - luaif, binary_name, func_name, - work_dir, full_path_for_rule_selection, + luaif, binary_name, func_name, abs_path, &min_path_len_to_check)) { /* has requirements: * skip over path components that we are not supposed to check, @@ -602,16 +596,33 @@ static char *sb_path_resolution( } } + SB_LOG(SB_LOGLEVEL_NOISE, "Map prefix [%d] '%s'", + component_index, work->pe_full_path); + + prefix_path_list.pl_first = NULL; + split_path_to_path_entries(work->pe_full_path, &prefix_path_list); + remove_dots_and_dotdots_from_path_entries(&prefix_path_list); + decolon_tmp = path_entries_to_string(prefix_path_list.pl_first); + free_path_entries(&prefix_path_list); + + SB_LOG(SB_LOGLEVEL_NOISE, "decolon_tmp => %s", decolon_tmp); + + prefix_mapping_result = call_lua_function_sbox_translate_path( + SB_LOGLEVEL_NOISE, + luaif, binary_name, "PATH_RESOLUTION", + decolon_tmp, &ro_tmp); + free(decolon_tmp); + drop_policy_from_lua_stack(luaif); + + SB_LOG(SB_LOGLEVEL_NOISE, "prefix_mapping_result before loop => %s", + prefix_mapping_result); + /* Path resolution loop = walk thru directories, and if a symlink * is found, recurse.. */ while (work) { char link_dest[PATH_MAX+1]; - char *decolon_tmp; int link_len; - char *prefix_mapping_result; - struct path_entry_list prefix_path_list; - int ro_tmp; if (dont_resolve_final_symlink && (work->pe_next == NULL)) { /* this is last component, but here a final symlink @@ -624,24 +635,8 @@ static char *sb_path_resolution( break; } - SB_LOG(SB_LOGLEVEL_NOISE2, "test [%d] '%s'", - component_index, work->pe_full_path); - - prefix_path_list.pl_first = NULL; - split_path_to_path_entries(work->pe_full_path, &prefix_path_list); - remove_dots_and_dotdots_from_path_entries(&prefix_path_list); - decolon_tmp = path_entries_to_string(prefix_path_list.pl_first); - free_path_entries(&prefix_path_list); - - prefix_mapping_result = call_lua_function_sbox_translate_path( - SB_LOGLEVEL_NOISE, - luaif, binary_name, "PATH_RESOLUTION", - work_dir, decolon_tmp, &ro_tmp); - free(decolon_tmp); - drop_policy_from_lua_stack(luaif); - - SB_LOG(SB_LOGLEVEL_NOISE2, "prefix_mapping_result='%s'", - prefix_mapping_result); + SB_LOG(SB_LOGLEVEL_NOISE, "path_resolution: test if symlink [%d] '%s'", + component_index, prefix_mapping_result); /* determine if "prefix_mapping_result" is a symbolic link. * this can't be done with lstat(), because lstat() does not @@ -747,15 +742,24 @@ static char *sb_path_resolution( /* Then the recursion */ result_path = sb_path_resolution(nest_count + 1, luaif, binary_name, func_name, - work_dir, new_path, new_path, dont_resolve_final_symlink); /* and finally, cleanup */ free(new_path); return(result_path); } - free(prefix_mapping_result); work = work->pe_next; + if (work) { + char *next_dir = NULL; + + asprintf(&next_dir, "%s/%s", prefix_mapping_result, work->pe_last_component_name); + if (prefix_mapping_result) { + free(prefix_mapping_result); + } + prefix_mapping_result = next_dir; + } else { + free(prefix_mapping_result); + } component_index++; } @@ -786,8 +790,8 @@ static char *scratchbox_path_internal( const char *path, int *ro_flagp, int dont_resolve_final_symlink, - int leave_mapping_rule_and_policy_to_stack) -{ + int process_path_for_exec) +{ struct lua_instance *luaif; char *mapping_result; @@ -845,15 +849,10 @@ static char *scratchbox_path_internal( { /* Mapping disabled inside this block - do not use "return"!! */ char *decolon_path = NULL; - char *full_path_for_rule_selection; - char work_dir[PATH_MAX + 1]; + char *full_path_for_rule_selection = NULL; full_path_for_rule_selection = sb_decolonize_path(path); - /* FIXME: work_dir should be unnecessary if path is absolute? */ - memset(work_dir, '\0', sizeof(work_dir)); - getcwd_nomap_nolog(work_dir, sizeof(work_dir)-1); - SB_LOG(SB_LOGLEVEL_DEBUG, "scratchbox_path_internal: process '%s', n='%s'", path, full_path_for_rule_selection); @@ -861,7 +860,7 @@ static char *scratchbox_path_internal( /* sb_path_resolution() leaves the rule to the stack... */ decolon_path = sb_path_resolution(0, luaif, binary_name, func_name, - work_dir, path, full_path_for_rule_selection, + full_path_for_rule_selection, dont_resolve_final_symlink); if (!decolon_path) { @@ -870,7 +869,7 @@ static char *scratchbox_path_internal( "decolon_path failed [%s]", func_name); mapping_result = NULL; - if (leave_mapping_rule_and_policy_to_stack) { + if (process_path_for_exec) { /* can't map, but still need to leave "rule" * (string) and "policy" (nil) to the stack */ lua_pushstring(luaif->lua, @@ -879,16 +878,15 @@ static char *scratchbox_path_internal( } } else { SB_LOG(SB_LOGLEVEL_NOISE2, - "scratchbox_path_internal: decolon_path='%s'" - " work_dir='%s'", - decolon_path, work_dir); + "scratchbox_path_internal: decolon_path='%s'", + decolon_path); mapping_result = call_lua_function_sbox_translate_path( SB_LOGLEVEL_INFO, luaif, binary_name, func_name, - work_dir, decolon_path, ro_flagp); + decolon_path, ro_flagp); /* ...and remove the rule from stack */ - if (leave_mapping_rule_and_policy_to_stack == 0) { + if (process_path_for_exec == 0) { drop_policy_from_lua_stack(luaif); drop_rule_from_lua_stack(luaif); } @@ -898,7 +896,44 @@ static char *scratchbox_path_internal( } enable_mapping(luaif); - SB_LOG(SB_LOGLEVEL_NOISE2, "scratchbox_path_internal: mapping_result='%s'", + /* now "mapping_result" is an absolute path. + * sb2's exec logic needs absolute paths, but otherwise, + * try to return a relative path if the original path was relative. + */ + if ((process_path_for_exec == 0) && + (path[0] != '/') && + mapping_result) { + char cwd[PATH_MAX + 1]; + + if (getcwd_nomap_nolog(cwd, sizeof(cwd))) { + int cwd_len = strlen(cwd); + int result_len = strlen(mapping_result); + + if ((result_len == cwd_len) && + !strcmp(cwd, mapping_result)) { + SB_LOG(SB_LOGLEVEL_DEBUG, + "scratchbox_path_internal: result==CWD"); + free(mapping_result); + mapping_result = strdup("."); + } else if ((result_len > cwd_len) && + (mapping_result[cwd_len] == '/') && + (mapping_result[cwd_len+1] != '/') && + (mapping_result[cwd_len+1] != '\0') && + !strncmp(cwd, mapping_result, cwd_len)) { + /* cwd is a prefix of result; convert result + * back to a relative path + */ + char *relative_result = strdup(mapping_result+cwd_len+1); + SB_LOG(SB_LOGLEVEL_DEBUG, + "scratchbox_path_internal: result==relative (%s) (%s)", + relative_result, mapping_result); + free(mapping_result); + mapping_result = relative_result; + } + } + } + + SB_LOG(SB_LOGLEVEL_NOISE, "scratchbox_path_internal: mapping_result='%s'", mapping_result ? mapping_result : "<No result>"); return(mapping_result); } |