diff options
author | sfan5 <sfan5@live.de> | 2021-03-28 22:53:48 +0200 |
---|---|---|
committer | sfan5 <sfan5@live.de> | 2021-04-18 16:06:42 +0200 |
commit | 623f0a8613bd8677e259366a1d540deedb9d2302 (patch) | |
tree | 01f03f6c7e77c0384086f194c68202a8884c40f7 /src/script/cpp_api | |
parent | 52c0384bd1c9f564f7a6deab93e560dc49ff8915 (diff) | |
download | minetest-623f0a8613bd8677e259366a1d540deedb9d2302.tar.gz minetest-623f0a8613bd8677e259366a1d540deedb9d2302.tar.bz2 minetest-623f0a8613bd8677e259366a1d540deedb9d2302.zip |
Isolate library tables between sandbox and insecure env
Diffstat (limited to 'src/script/cpp_api')
-rw-r--r-- | src/script/cpp_api/s_security.cpp | 44 |
1 files changed, 43 insertions, 1 deletions
diff --git a/src/script/cpp_api/s_security.cpp b/src/script/cpp_api/s_security.cpp index 63058d7c3..add7b1658 100644 --- a/src/script/cpp_api/s_security.cpp +++ b/src/script/cpp_api/s_security.cpp @@ -45,6 +45,21 @@ static inline void copy_safe(lua_State *L, const char *list[], unsigned len, int } } +static void shallow_copy_table(lua_State *L, int from=-2, int to=-1) +{ + if (from < 0) from = lua_gettop(L) + from + 1; + if (to < 0) to = lua_gettop(L) + to + 1; + lua_pushnil(L); + while (lua_next(L, from) != 0) { + assert(lua_type(L, -1) != LUA_TTABLE); + // duplicate key and value for lua_rawset + lua_pushvalue(L, -2); + lua_pushvalue(L, -2); + lua_rawset(L, to); + lua_pop(L, 1); + } +} + // Pushes the original version of a library function on the stack, from the old version static inline void push_original(lua_State *L, const char *lib, const char *func) { @@ -83,7 +98,10 @@ void ScriptApiSecurity::initializeSecurity() "unpack", "_VERSION", "xpcall", - // Completely safe libraries + }; + static const char *whitelist_tables[] = { + // These libraries are completely safe BUT we need to duplicate their table + // to ensure the sandbox can't affect the insecure env "coroutine", "string", "table", @@ -167,6 +185,17 @@ void ScriptApiSecurity::initializeSecurity() lua_pop(L, 1); + // Copy safe libraries + for (const char *libname : whitelist_tables) { + lua_getfield(L, old_globals, libname); + lua_newtable(L); + shallow_copy_table(L); + + lua_setglobal(L, libname); + lua_pop(L, 1); + } + + // Copy safe IO functions lua_getfield(L, old_globals, "io"); lua_newtable(L); @@ -222,6 +251,19 @@ void ScriptApiSecurity::initializeSecurity() #endif lua_pop(L, 1); // Pop globals_backup + + + /* + * In addition to copying the tables in whitelist_tables, we also need to + * replace the string metatable. Otherwise old_globals.string would + * be accessible via getmetatable("").__index from inside the sandbox. + */ + lua_pushliteral(L, ""); + lua_newtable(L); + lua_getglobal(L, "string"); + lua_setfield(L, -2, "__index"); + lua_setmetatable(L, -2); + lua_pop(L, 1); // Pop empty string } void ScriptApiSecurity::initializeSecurityClient() |