diff options
author | Lauri Aarnio <Lauri.Aarnio@iki.fi> | 2008-09-15 17:56:50 +0300 |
---|---|---|
committer | Lauri Leukkunen <lle@rahina.org> | 2008-09-27 00:02:42 +0300 |
commit | 7b1c05e4af87ef66b94cd70cc420750778c42982 (patch) | |
tree | beb73ec098eed9f03f164ff8c34ec2b52c0011a6 /luaif | |
parent | 47119b3499fe574bd3c07748ecf90f636ffa0d41 (diff) |
Implemented policy-based execution of native binaries. - Exec policies can be used to define how native binaries are started: For example, the tools that are used from "tools_root" may need to load dynamic libraries from nonstandard locations and/or use a nonstandard ld.so; also, if the target architecture is the same as the host architecture, binaries may also need special settings and a special ld.so. - These features are off by default, but can be taken into use by installing a libsb2.so to tools_root (or to the rootstrap, if target arch.==host arch) - NOTE/WARNING: These features are currently off because the current ld.so (which is part of glibc) is not fully transparent to the application. See comments in the source for a longer explanation of this.
Diffstat (limited to 'luaif')
-rw-r--r-- | luaif/argvenvp.c | 92 | ||||
-rw-r--r-- | luaif/paths.c | 122 |
2 files changed, 191 insertions, 23 deletions
diff --git a/luaif/argvenvp.c b/luaif/argvenvp.c index 05f3f4d..e7a5323 100644 --- a/luaif/argvenvp.c +++ b/luaif/argvenvp.c @@ -1,5 +1,7 @@ /* * Copyright (C) 2006,2007 Lauri Leukkunen <lle@rahina.org> + * Portion Copyright (c) 2008 Nokia Corporation. + * (exec postprocessing code implemented by Lauri T. Aarnio at Nokia) * * Licensed under LGPL version 2.1, see top level LICENSE file for details. */ @@ -126,3 +128,93 @@ int sb_execve_preprocess(char **file, char ***argv, char ***envp) "sb_execve_preprocess: at exit, gettop=%d", lua_gettop(luaif->lua)); return res; } + +/* Exec Postprocessing: + * Called with "rule" and "exec_policy" already in lua's stack. +*/ +int sb_execve_postprocess(char *exec_type, + char **mapped_file, + char **filename, + const char *binary_name, + char ***argv, + char ***envp) +{ + struct lua_instance *luaif; + int res, new_argc, new_envc; + + luaif = get_lua(); + if (!luaif) return(0); + + if (!argv || !envp) { + SB_LOG(SB_LOGLEVEL_ERROR, + "ERROR: sb_argvenvp: (argv || envp) == NULL"); + return -1; + } + + SB_LOG(SB_LOGLEVEL_NOISE, + "sb_execve_postprocess: gettop=%d", lua_gettop(luaif->lua)); + + lua_getfield(luaif->lua, LUA_GLOBALSINDEX, "sb_execve_postprocess"); + + /* stack now contains "rule", "exec_policy" and "sb_execve_postprocess". * move "sb_execve_postprocess" to the bottom : */ + lua_insert(luaif->lua, -3); + + lua_pushstring(luaif->lua, exec_type); + lua_pushstring(luaif->lua, *mapped_file); + lua_pushstring(luaif->lua, *filename); + lua_pushstring(luaif->lua, binary_name); + strvec_to_lua_table(luaif, *argv); + strvec_to_lua_table(luaif, *envp); + + /* args: rule, exec_policy, exec_type, mapped_file, filename, + * binaryname, argv, envp + * returns: err, mapped_file, filename, argc, argv, envc, envp */ + lua_call(luaif->lua, 8, 7); + + res = lua_tointeger(luaif->lua, -7); + switch (res) { + + case 0: + /* exec arguments were modified, replace contents of + * argv and envp vectors */ + SB_LOG(SB_LOGLEVEL_DEBUG, + "sb_execve_postprocess: Updated argv&envp"); + free(*mapped_file); + *mapped_file = strdup(lua_tostring(luaif->lua, -6)); + + free(*filename); + *filename = strdup(lua_tostring(luaif->lua, -5)); + + strvec_free(*argv); + new_argc = lua_tointeger(luaif->lua, -4); + lua_string_table_to_strvec(luaif, -3, argv, new_argc); + + new_envc = lua_tointeger(luaif->lua, -2); + strvec_free(*envp); + lua_string_table_to_strvec(luaif, -1, envp, new_envc); + break; + + case 1: + SB_LOG(SB_LOGLEVEL_DEBUG, + "sb_execve_postprocess: argv&envp were not modified"); + break; + + case -1: + SB_LOG(SB_LOGLEVEL_DEBUG, + "sb_execve_postprocess: exec denied"); + break; + + default: + SB_LOG(SB_LOGLEVEL_ERROR, + "sb_execve_postprocess: Unsupported result %d", res); + break; + } + + /* remove sb_execve_postprocess return values from the stack. */ + lua_pop(luaif->lua, 6); + + SB_LOG(SB_LOGLEVEL_NOISE, + "sb_execve_postprocess: at exit, gettop=%d", lua_gettop(luaif->lua)); + return res; +} + diff --git a/luaif/paths.c b/luaif/paths.c index 545401b..8cf0eaf 100644 --- a/luaif/paths.c +++ b/luaif/paths.c @@ -373,7 +373,7 @@ static char last_char_in_str(const char *str) /* note: this expects that the lua stack already contains the mapping rule, * needed by sbox_translate_path (lua code). - * at exit this leaves the rule to stack. + * at exit this always leaves the rule AND exec policy to stack! */ static char *call_lua_function_sbox_translate_path( int result_log_level, @@ -389,6 +389,9 @@ static char *call_lua_function_sbox_translate_path( SB_LOG(SB_LOGLEVEL_NOISE, "calling sbox_translate_path for %s(%s)", func_name, decolon_path); + SB_LOG(SB_LOGLEVEL_NOISE, + "call_lua_function_sbox_translate_path: gettop=%d", + lua_gettop(luaif->lua)); lua_getfield(luaif->lua, LUA_GLOBALSINDEX, "sbox_translate_path"); /* stack now contains the rule object and string "sbox_translate_path", @@ -399,7 +402,8 @@ static char *call_lua_function_sbox_translate_path( lua_pushstring(luaif->lua, func_name); lua_pushstring(luaif->lua, work_dir); lua_pushstring(luaif->lua, decolon_path); - lua_call(luaif->lua, 5, 3); /* 5 arguments, returns rule,path,ro_flag */ + /* 5 arguments, returns rule,policy,path,ro_flag */ + lua_call(luaif->lua, 5, 4); traslate_result = (char *)lua_tostring(luaif->lua, -2); if (traslate_result) { @@ -407,7 +411,7 @@ static char *call_lua_function_sbox_translate_path( } ro_flag = lua_toboolean(luaif->lua, -1); if (ro_flagp) *ro_flagp = ro_flag; - lua_pop(luaif->lua, 2); /* leave rule to the stack */ + lua_pop(luaif->lua, 2); /* leave rule and policy to the stack */ if (traslate_result) { /* sometimes a mapping rule may create paths that contain @@ -440,11 +444,17 @@ static char *call_lua_function_sbox_translate_path( func_name, decolon_path, cleaned_path, (ro_flag ? " (readonly)" : "")); } + SB_LOG(SB_LOGLEVEL_NOISE, + "call_lua_function_sbox_translate_path: at exit, gettop=%d", + lua_gettop(luaif->lua)); return cleaned_path; } SB_LOG(SB_LOGLEVEL_ERROR, "No result from sbox_translate_path for: %s '%s'", func_name, decolon_path); + SB_LOG(SB_LOGLEVEL_NOISE, + "call_lua_function_sbox_translate_path: at exit, gettop=%d", + lua_gettop(luaif->lua)); return(NULL); } @@ -467,6 +477,9 @@ static int call_lua_function_sbox_get_mapping_requirements( SB_LOG(SB_LOGLEVEL_NOISE, "calling sbox_get_mapping_requirements for %s(%s)", func_name, full_path_for_rule_selection); + SB_LOG(SB_LOGLEVEL_NOISE, + "call_lua_function_sbox_get_mapping_requirements: gettop=%d", + lua_gettop(luaif->lua)); lua_getfield(luaif->lua, LUA_GLOBALSINDEX, "sbox_get_mapping_requirements"); @@ -488,19 +501,25 @@ static int call_lua_function_sbox_get_mapping_requirements( SB_LOG(SB_LOGLEVEL_DEBUG, "sbox_get_mapping_requirements -> %d,%d", rule_found, min_path_len); + SB_LOG(SB_LOGLEVEL_NOISE, + "call_lua_function_sbox_get_mapping_requirements: at exit, gettop=%d", + lua_gettop(luaif->lua)); return(rule_found); } /* ========== Path resolution: ========== */ /* clean up path resolution environment from lua stack */ -static void drop_rule_from_lua_stack(struct lua_instance *luaif) +#define drop_policy_from_lua_stack(luaif) drop_from_lua_stack(luaif,"policy") +#define drop_rule_from_lua_stack(luaif) drop_from_lua_stack(luaif,"rule") + +static void drop_from_lua_stack(struct lua_instance *luaif, + const char *o_name) { - /* remove "rule" from the stack. */ lua_pop(luaif->lua, 1); SB_LOG(SB_LOGLEVEL_NOISE, - "path resolution cleanup: at exit, gettop=%d", + "drop %s from stack: at exit, gettop=%d", o_name, lua_gettop(luaif->lua)); } @@ -622,6 +641,7 @@ static char *sb_path_resolution( 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); @@ -757,23 +777,25 @@ static char *sb_path_resolution( return buf; } -/* ========== Public interfaces to the mapping & resolution code: ========== */ +/* ========== Mapping & path resolution, internal implementation: ========== */ /* make sure to use disable_mapping(m); * to prevent recursive calls to this function. * Returns a pointer to an allocated buffer which contains the result. */ -char *scratchbox_path3(const char *binary_name, - const char *func_name, - const char *path, - const char *mapping_mode, - int *ro_flagp, - int dont_resolve_final_symlink) +static char *scratchbox_path_internal( + const char *binary_name, + const char *func_name, + const char *path, + const char *mapping_mode, + int *ro_flagp, + int dont_resolve_final_symlink, + int leave_mapping_rule_and_policy_to_stack) { struct lua_instance *luaif; char *mapping_result; - SB_LOG(SB_LOGLEVEL_DEBUG, "scratchbox_path3: %s(%s)", func_name, path); + SB_LOG(SB_LOGLEVEL_DEBUG, "scratchbox_path_internal: %s(%s)", func_name, path); #ifdef EXTREME_DEBUGGING #define SIZE 100 @@ -805,7 +827,8 @@ char *scratchbox_path3(const char *binary_name, if (!path) { SB_LOG(SB_LOGLEVEL_ERROR, - "ERROR: scratchbox_path3: path==NULL [%s]", func_name); + "ERROR: scratchbox_path_internal: path==NULL [%s]", + func_name); return NULL; } @@ -842,7 +865,7 @@ char *scratchbox_path3(const char *binary_name, getcwd(work_dir, sizeof(work_dir)-1); SB_LOG(SB_LOGLEVEL_DEBUG, - "scratchbox_path3: process '%s', n='%s'", + "scratchbox_path_internal: process '%s', n='%s'", path, full_path_for_rule_selection); /* sb_path_resolution() leaves the rule to the stack... */ @@ -853,12 +876,20 @@ char *scratchbox_path3(const char *binary_name, if (!decolon_path) { SB_LOG(SB_LOGLEVEL_ERROR, - "ERROR: scratchbox_path3: decolon_path failed [%s]", + "scratchbox_path_internal: " + "decolon_path failed [%s]", func_name); mapping_result = NULL; + if (leave_mapping_rule_and_policy_to_stack) { + /* can't map, but still need to leave "rule" + * (string) and "policy" (nil) to the stack */ + lua_pushstring(luaif->lua, + "mapping failed (decolon path failed"); + lua_pushnil(luaif->lua); + } } else { SB_LOG(SB_LOGLEVEL_NOISE2, - "scratchbox_path3: decolon_path='%s'" + "scratchbox_path_internal: decolon_path='%s'" " work_dir='%s'", decolon_path, work_dir); @@ -866,19 +897,36 @@ char *scratchbox_path3(const char *binary_name, SB_LOGLEVEL_INFO, luaif, binary_name, func_name, work_dir, decolon_path, ro_flagp); + /* ...and remove the rule from stack */ + if (leave_mapping_rule_and_policy_to_stack == 0) { + drop_policy_from_lua_stack(luaif); + drop_rule_from_lua_stack(luaif); + } } if(decolon_path) free(decolon_path); if(full_path_for_rule_selection) free(full_path_for_rule_selection); - /* ...and remove the rule from stack */ - drop_rule_from_lua_stack(luaif); } enable_mapping(luaif); - SB_LOG(SB_LOGLEVEL_NOISE2, "scratchbox_path3: mapping_result='%s'", + SB_LOG(SB_LOGLEVEL_NOISE2, "scratchbox_path_internal: mapping_result='%s'", mapping_result ? mapping_result : "<No result>"); return(mapping_result); } +/* ========== Public interfaces to the mapping & resolution code: ========== */ + +char *scratchbox_path3( + const char *binary_name, + const char *func_name, + const char *path, + const char *mapping_mode, + int *ro_flagp, + int dont_resolve_final_symlink) +{ + return(scratchbox_path_internal(binary_name, func_name, path, + mapping_mode, ro_flagp, dont_resolve_final_symlink, 0)); +} + char *scratchbox_path( const char *func_name, const char *path, @@ -897,7 +945,35 @@ char *scratchbox_path( if (!(mapping_mode = getenv("SBOX_MAPMODE"))) { mapping_mode = "simple"; } - return (scratchbox_path3(binary_name, func_name, path, mapping_mode, - ro_flagp, dont_resolve_final_symlink)); + return (scratchbox_path_internal(binary_name, func_name, + path, mapping_mode, + ro_flagp, dont_resolve_final_symlink, 0)); +} + +/* this maps the path and then leaves "rule" and "exec_policy" to the stack, + * because exec post-processing needs them +*/ +char *scratchbox_path_for_exec( + const char *func_name, + const char *path, + int *ro_flagp, + int dont_resolve_final_symlink) +{ + char binary_name[PATH_MAX+1]; + char *bin_name; + const char *mapping_mode; + + memset(binary_name, '\0', PATH_MAX+1); + if (!(bin_name = getenv("__SB2_BINARYNAME"))) { + bin_name = "UNKNOWN"; + } + strcpy(binary_name, bin_name); + + if (!(mapping_mode = getenv("SBOX_MAPMODE"))) { + mapping_mode = "simple"; + } + return (scratchbox_path_internal(binary_name, func_name, + path, mapping_mode, + ro_flagp, dont_resolve_final_symlink, 1)); } |