@@ -45,6 +45,21 @@ static inline void copy_safe(lua_State *L, const char *list[], unsigned len, int
45
45
}
46
46
}
47
47
48
+ static void shallow_copy_table (lua_State *L, int from=-2 , int to=-1 )
49
+ {
50
+ if (from < 0 ) from = lua_gettop (L) + from + 1 ;
51
+ if (to < 0 ) to = lua_gettop (L) + to + 1 ;
52
+ lua_pushnil (L);
53
+ while (lua_next (L, from) != 0 ) {
54
+ assert (lua_type (L, -1 ) != LUA_TTABLE);
55
+ // duplicate key and value for lua_rawset
56
+ lua_pushvalue (L, -2 );
57
+ lua_pushvalue (L, -2 );
58
+ lua_rawset (L, to);
59
+ lua_pop (L, 1 );
60
+ }
61
+ }
62
+
48
63
// Pushes the original version of a library function on the stack, from the old version
49
64
static inline void push_original (lua_State *L, const char *lib, const char *func)
50
65
{
@@ -83,7 +98,10 @@ void ScriptApiSecurity::initializeSecurity()
83
98
" unpack" ,
84
99
" _VERSION" ,
85
100
" xpcall" ,
86
- // Completely safe libraries
101
+ };
102
+ static const char *whitelist_tables[] = {
103
+ // These libraries are completely safe BUT we need to duplicate their table
104
+ // to ensure the sandbox can't affect the insecure env
87
105
" coroutine" ,
88
106
" string" ,
89
107
" table" ,
@@ -167,6 +185,17 @@ void ScriptApiSecurity::initializeSecurity()
167
185
lua_pop (L, 1 );
168
186
169
187
188
+ // Copy safe libraries
189
+ for (const char *libname : whitelist_tables) {
190
+ lua_getfield (L, old_globals, libname);
191
+ lua_newtable (L);
192
+ shallow_copy_table (L);
193
+
194
+ lua_setglobal (L, libname);
195
+ lua_pop (L, 1 );
196
+ }
197
+
198
+
170
199
// Copy safe IO functions
171
200
lua_getfield (L, old_globals, " io" );
172
201
lua_newtable (L);
@@ -222,6 +251,19 @@ void ScriptApiSecurity::initializeSecurity()
222
251
#endif
223
252
224
253
lua_pop (L, 1 ); // Pop globals_backup
254
+
255
+
256
+ /*
257
+ * In addition to copying the tables in whitelist_tables, we also need to
258
+ * replace the string metatable. Otherwise old_globals.string would
259
+ * be accessible via getmetatable("").__index from inside the sandbox.
260
+ */
261
+ lua_pushliteral (L, " " );
262
+ lua_newtable (L);
263
+ lua_getglobal (L, " string" );
264
+ lua_setfield (L, -2 , " __index" );
265
+ lua_setmetatable (L, -2 );
266
+ lua_pop (L, 1 ); // Pop empty string
225
267
}
226
268
227
269
void ScriptApiSecurity::initializeSecurityClient ()
0 commit comments