int lua_sandbox_init(lua_sandbox* lsb, const char* data_file) { if (lsb == NULL || lsb->m_lua != NULL) { return 0; } if (lsb->m_lua_file == NULL) { snprintf(lsb->m_error_message, ERROR_SIZE, "no Lua script provided"); sandbox_terminate(lsb); return 1; } lsb->m_lua = lua_newstate(memory_manager, lsb); if (lsb->m_lua == NULL) { snprintf(lsb->m_error_message, ERROR_SIZE, "out of memory"); sandbox_terminate(lsb); return 2; } load_library(lsb->m_lua, "", luaopen_base, disable_base_functions); load_library(lsb->m_lua, LUA_MATHLIBNAME, luaopen_math, disable_none); load_library(lsb->m_lua, LUA_OSLIBNAME, luaopen_os, disable_os_functions); load_library(lsb->m_lua, LUA_STRLIBNAME, luaopen_string, disable_none); load_library(lsb->m_lua, LUA_TABLIBNAME, luaopen_table, disable_none); luaopen_circular_buffer(lsb->m_lua); lua_pushlightuserdata(lsb->m_lua, (void*)lsb); lua_pushcclosure(lsb->m_lua, &read_message, 1); lua_setglobal(lsb->m_lua, "read_message"); lua_pushlightuserdata(lsb->m_lua, (void*)lsb); lua_pushcclosure(lsb->m_lua, &output, 1); lua_setglobal(lsb->m_lua, "output"); lua_pushlightuserdata(lsb->m_lua, (void*)lsb); lua_pushcclosure(lsb->m_lua, &inject_message, 1); lua_setglobal(lsb->m_lua, "inject_message"); lua_sethook(lsb->m_lua, instruction_manager, LUA_MASKCOUNT, lsb->m_usage[USAGE_TYPE_INSTRUCTION][USAGE_STAT_LIMIT]); if (luaL_dofile(lsb->m_lua, lsb->m_lua_file) != 0) { snprintf(lsb->m_error_message, ERROR_SIZE, "%s", lua_tostring(lsb->m_lua, -1)); sandbox_terminate(lsb); return 3; } else { lua_gc(lsb->m_lua, LUA_GCCOLLECT, 0); lsb->m_usage[USAGE_TYPE_INSTRUCTION][USAGE_STAT_CURRENT] = instruction_usage(lsb); if (lsb->m_usage[USAGE_TYPE_INSTRUCTION][USAGE_STAT_CURRENT] > lsb->m_usage[USAGE_TYPE_INSTRUCTION][USAGE_STAT_MAXIMUM]) { lsb->m_usage[USAGE_TYPE_INSTRUCTION][USAGE_STAT_MAXIMUM] = lsb->m_usage[USAGE_TYPE_INSTRUCTION][USAGE_STAT_CURRENT]; } lsb->m_status = STATUS_RUNNING; if (data_file != NULL && strlen(data_file) > 0) { return restore_global_data(lsb, data_file); } } return 0; }
lsb_err_value lsb_init(lsb_lua_sandbox *lsb, const char *state_file) { if (!lsb) { return LSB_ERR_UTIL_NULL; } if (lsb->state != LSB_UNKNOWN) { lsb_terminate(lsb, LSB_ERR_INIT); return LSB_ERR_INIT; } if (state_file && strlen(state_file) > 0) { lsb->state_file = malloc(strlen(state_file) + 1); if (!lsb->state_file) { lsb_terminate(lsb, LSB_ERR_UTIL_OOM); return LSB_ERR_UTIL_OOM; } strcpy(lsb->state_file, state_file); } #ifndef LUA_JIT size_t mem_limit = lsb->usage[LSB_UT_MEMORY][LSB_US_LIMIT]; lsb->usage[LSB_UT_MEMORY][LSB_US_LIMIT] = 0; #endif preload_modules(lsb->lua); // load package module lua_pushcfunction(lsb->lua, luaopen_package); lua_pushstring(lsb->lua, LUA_LOADLIBNAME); lua_call(lsb->lua, 1, 1); lua_newtable(lsb->lua); lua_setmetatable(lsb->lua, -2); lua_pop(lsb->lua, 1); // load base module lua_getglobal(lsb->lua, "require"); if (!lua_iscfunction(lsb->lua, -1)) { snprintf(lsb->error_message, LSB_ERROR_SIZE, "lsb_init() 'require' not found"); lsb_terminate(lsb, NULL); return LSB_ERR_LUA; } lua_pushstring(lsb->lua, LUA_BASELIBNAME); if (lua_pcall(lsb->lua, 1, 0, 0)) { snprintf(lsb->error_message, LSB_ERROR_SIZE, "lsb_init %s", lua_tostring(lsb->lua, -1)); lsb_terminate(lsb, NULL); return LSB_ERR_LUA; } if (lsb->usage[LSB_UT_INSTRUCTION][LSB_US_LIMIT] != 0) { lua_sethook(lsb->lua, instruction_manager, LUA_MASKCOUNT, (int)lsb->usage[LSB_UT_INSTRUCTION][LSB_US_LIMIT]); } else { lua_sethook(lsb->lua, NULL, 0, 0); } #ifdef LUA_JIT // todo limit lua_gc(lsb->lua, LUA_GCSETMEMLIMIT, (int)lsb->usage[LSB_UT_MEMORY][LSB_US_LIMIT]); #else lsb->usage[LSB_UT_MEMORY][LSB_US_LIMIT] = mem_limit; #endif lua_CFunction pf = lua_atpanic(lsb->lua, unprotected_panic); int jump = setjmp(g_jbuf); if (jump || luaL_dofile(lsb->lua, lsb->lua_file) != 0) { int len = snprintf(lsb->error_message, LSB_ERROR_SIZE, "%s", lua_tostring(lsb->lua, -1)); if (len >= LSB_ERROR_SIZE || len < 0) { lsb->error_message[LSB_ERROR_SIZE - 1] = 0; } lsb_terminate(lsb, NULL); return LSB_ERR_LUA; } else { lua_gc(lsb->lua, LUA_GCCOLLECT, 0); lsb->usage[LSB_UT_INSTRUCTION][LSB_US_CURRENT] = instruction_usage(lsb); if (lsb->usage[LSB_UT_INSTRUCTION][LSB_US_CURRENT] > lsb->usage[LSB_UT_INSTRUCTION][LSB_US_MAXIMUM]) { lsb->usage[LSB_UT_INSTRUCTION][LSB_US_MAXIMUM] = lsb->usage[LSB_UT_INSTRUCTION][LSB_US_CURRENT]; } lsb->state = LSB_RUNNING; if (lsb->state_file) { lsb_err_value ret = restore_global_data(lsb); if (ret) return ret; } } lua_atpanic(lsb->lua, pf); return NULL; }