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 endmaster
parent
997be666e3
commit
4827ee1258
|
@ -2437,7 +2437,7 @@ These functions return the leftover itemstack.
|
||||||
* `minetest.request_insecure_environment()`: returns an environment containing
|
* `minetest.request_insecure_environment()`: returns an environment containing
|
||||||
insecure functions if the calling mod has been listed as trusted in the
|
insecure functions if the calling mod has been listed as trusted in the
|
||||||
`secure.trusted_mods` setting or security is disabled, otherwise returns `nil`.
|
`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
|
* **DO NOT ALLOW ANY OTHER MODS TO ACCESS THE RETURNED ENVIRONMENT, STORE IT IN
|
||||||
A LOCAL VARIABLE!**
|
A LOCAL VARIABLE!**
|
||||||
|
|
||||||
|
|
|
@ -357,22 +357,44 @@ int ModApiUtil::l_get_dir_list(lua_State *L)
|
||||||
int ModApiUtil::l_request_insecure_environment(lua_State *L)
|
int ModApiUtil::l_request_insecure_environment(lua_State *L)
|
||||||
{
|
{
|
||||||
NO_MAP_LOCK_REQUIRED;
|
NO_MAP_LOCK_REQUIRED;
|
||||||
|
|
||||||
|
// Just return _G if security is disabled
|
||||||
if (!ScriptApiSecurity::isSecure(L)) {
|
if (!ScriptApiSecurity::isSecure(L)) {
|
||||||
lua_getglobal(L, "_G");
|
lua_getglobal(L, "_G");
|
||||||
return 1;
|
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);
|
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
|
||||||
if (!lua_isstring(L, -1)) {
|
if (!lua_isstring(L, -1)) {
|
||||||
lua_pushnil(L);
|
return 0;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check secure.trusted_mods
|
||||||
const char *mod_name = lua_tostring(L, -1);
|
const char *mod_name = lua_tostring(L, -1);
|
||||||
std::string trusted_mods = g_settings->get("secure.trusted_mods");
|
std::string trusted_mods = g_settings->get("secure.trusted_mods");
|
||||||
std::vector<std::string> mod_list = str_split(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()) {
|
if (std::find(mod_list.begin(), mod_list.end(), mod_name) ==
|
||||||
lua_pushnil(L);
|
mod_list.end()) {
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Push insecure environment
|
||||||
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_GLOBALS_BACKUP);
|
lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_GLOBALS_BACKUP);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue