aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShadowNinja <shadowninja@minetest.net>2016-02-18 16:06:07 -0500
committerparamat <mat.gregory@virginmedia.com>2016-02-19 14:52:10 +0000
commit4827ee1258ac9d68808ca4e2a9cb88bf49473e6b (patch)
treee2900cf20cb7aed59fb69e94b97784e02843e0cd
parent997be666e37e9494bb92a50521b4b749156a609c (diff)
downloadminetest-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.txt2
-rw-r--r--src/script/lua_api/l_util.cpp32
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;
}