diff options
author | ShadowNinja <shadowninja@minetest.net> | 2016-02-18 16:06:07 -0500 |
---|---|---|
committer | paramat <mat.gregory@virginmedia.com> | 2016-02-19 14:52:10 +0000 |
commit | 4827ee1258ac9d68808ca4e2a9cb88bf49473e6b (patch) | |
tree | e2900cf20cb7aed59fb69e94b97784e02843e0cd | |
parent | 997be666e37e9494bb92a50521b4b749156a609c (diff) | |
download | minetest-4827ee1258ac9d68808ca4e2a9cb88bf49473e6b.tar.gz minetest-4827ee1258ac9d68808ca4e2a9cb88bf49473e6b.tar.bz2 minetest-4827ee1258ac9d68808ca4e2a9cb88bf49473e6b.zip |
Require request_insecure_environment to be called from the mod's main scope
Previously you could steal a secure environment from a trusted mod by wrapping
request_insecure_environment with some code like this:
local rie_cp = minetest.request_insecure_environment
local stolen_ie
function minetest.request_insecure_environment()
local ie = rie_cp()
stolen_ie = stolen_ie or ie
return ie
end
-rw-r--r-- | doc/lua_api.txt | 2 | ||||
-rw-r--r-- | src/script/lua_api/l_util.cpp | 32 |
2 files changed, 28 insertions, 6 deletions
diff --git a/doc/lua_api.txt b/doc/lua_api.txt index d9a8bea97..2df0cac7c 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -2437,7 +2437,7 @@ These functions return the leftover itemstack. * `minetest.request_insecure_environment()`: returns an environment containing insecure functions if the calling mod has been listed as trusted in the `secure.trusted_mods` setting or security is disabled, otherwise returns `nil`. - * Only works at init time. + * Only works at init time and must be called from the mod's main scope (not from a function). * **DO NOT ALLOW ANY OTHER MODS TO ACCESS THE RETURNED ENVIRONMENT, STORE IT IN A LOCAL VARIABLE!** diff --git a/src/script/lua_api/l_util.cpp b/src/script/lua_api/l_util.cpp index 39863b987..c1e883a98 100644 --- a/src/script/lua_api/l_util.cpp +++ b/src/script/lua_api/l_util.cpp @@ -357,22 +357,44 @@ int ModApiUtil::l_get_dir_list(lua_State *L) int ModApiUtil::l_request_insecure_environment(lua_State *L) { NO_MAP_LOCK_REQUIRED; + + // Just return _G if security is disabled if (!ScriptApiSecurity::isSecure(L)) { lua_getglobal(L, "_G"); return 1; } + + // We have to make sure that this function is being called directly by + // a mod, otherwise a malicious mod could override this function and + // steal its return value. + lua_Debug info; + // Make sure there's only one item below this function on the stack... + if (lua_getstack(L, 2, &info)) { + return 0; + } + assert(lua_getstack(L, 1, &info)); + assert(lua_getinfo(L, "S", &info)); + // ...and that that item is the main file scope. + if (strcmp(info.what, "main") != 0) { + return 0; + } + + // Get mod name lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME); if (!lua_isstring(L, -1)) { - lua_pushnil(L); - return 1; + return 0; } + + // Check secure.trusted_mods const char *mod_name = lua_tostring(L, -1); std::string trusted_mods = g_settings->get("secure.trusted_mods"); std::vector<std::string> mod_list = str_split(trusted_mods, ','); - if (std::find(mod_list.begin(), mod_list.end(), mod_name) == mod_list.end()) { - lua_pushnil(L); - return 1; + if (std::find(mod_list.begin(), mod_list.end(), mod_name) == + mod_list.end()) { + return 0; } + + // Push insecure environment lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_GLOBALS_BACKUP); return 1; } |