forked from Mirrorlandia_minetest/minetest
Refactor loading of Lua code with mod security
This commit is contained in:
parent
17191a60fb
commit
5ab546f99b
src/script/cpp_api
@ -372,14 +372,16 @@ bool ScriptApiSecurity::isSecure(lua_State *L)
|
|||||||
return secure;
|
return secure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ScriptApiSecurity::safeLoadString(lua_State *L, const std::string &code, const char *chunk_name)
|
||||||
#define CHECK_FILE_ERR(ret, fp) \
|
{
|
||||||
if (ret) { \
|
if (code.size() > 0 && code[0] == LUA_SIGNATURE[0]) {
|
||||||
lua_pushfstring(L, "%s: %s", path, strerror(errno)); \
|
lua_pushliteral(L, "Bytecode prohibited when mod security is enabled.");
|
||||||
if (fp) std::fclose(fp); \
|
return false;
|
||||||
return false; \
|
|
||||||
}
|
}
|
||||||
|
if (luaL_loadbuffer(L, code.data(), code.size(), chunk_name))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ScriptApiSecurity::safeLoadFile(lua_State *L, const char *path, const char *display_name)
|
bool ScriptApiSecurity::safeLoadFile(lua_State *L, const char *path, const char *display_name)
|
||||||
{
|
{
|
||||||
@ -406,68 +408,49 @@ bool ScriptApiSecurity::safeLoadFile(lua_State *L, const char *path, const char
|
|||||||
int c = std::getc(fp);
|
int c = std::getc(fp);
|
||||||
if (c == '#') {
|
if (c == '#') {
|
||||||
// Skip the first line
|
// Skip the first line
|
||||||
while ((c = std::getc(fp)) != EOF && c != '\n');
|
while ((c = std::getc(fp)) != EOF && c != '\n') {}
|
||||||
if (c == '\n') c = std::getc(fp);
|
if (c == '\n')
|
||||||
|
std::getc(fp);
|
||||||
start = std::ftell(fp);
|
start = std::ftell(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c == LUA_SIGNATURE[0]) {
|
|
||||||
lua_pushliteral(L, "Bytecode prohibited when mod security is enabled.");
|
|
||||||
std::fclose(fp);
|
|
||||||
if (path) {
|
|
||||||
delete [] chunk_name;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the file
|
// Read the file
|
||||||
int ret = std::fseek(fp, 0, SEEK_END);
|
int ret = std::fseek(fp, 0, SEEK_END);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
lua_pushfstring(L, "%s: %s", path, strerror(errno));
|
lua_pushfstring(L, "%s: %s", path, strerror(errno));
|
||||||
std::fclose(fp);
|
|
||||||
if (path) {
|
if (path) {
|
||||||
|
std::fclose(fp);
|
||||||
delete [] chunk_name;
|
delete [] chunk_name;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size = std::ftell(fp) - start;
|
size_t size = std::ftell(fp) - start;
|
||||||
char *code = new char[size];
|
std::string code(size, '\0');
|
||||||
ret = std::fseek(fp, start, SEEK_SET);
|
ret = std::fseek(fp, start, SEEK_SET);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
lua_pushfstring(L, "%s: %s", path, strerror(errno));
|
lua_pushfstring(L, "%s: %s", path, strerror(errno));
|
||||||
std::fclose(fp);
|
|
||||||
delete [] code;
|
|
||||||
if (path) {
|
if (path) {
|
||||||
|
std::fclose(fp);
|
||||||
delete [] chunk_name;
|
delete [] chunk_name;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t num_read = std::fread(code, 1, size, fp);
|
size_t num_read = std::fread(&code[0], 1, size, fp);
|
||||||
if (path) {
|
if (path)
|
||||||
std::fclose(fp);
|
std::fclose(fp);
|
||||||
}
|
|
||||||
if (num_read != size) {
|
if (num_read != size) {
|
||||||
lua_pushliteral(L, "Error reading file to load.");
|
lua_pushliteral(L, "Error reading file to load.");
|
||||||
delete [] code;
|
if (path)
|
||||||
if (path) {
|
|
||||||
delete [] chunk_name;
|
delete [] chunk_name;
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (luaL_loadbuffer(L, code, size, chunk_name)) {
|
bool result = safeLoadString(L, code, chunk_name);
|
||||||
delete [] code;
|
if (path)
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete [] code;
|
|
||||||
|
|
||||||
if (path) {
|
|
||||||
delete [] chunk_name;
|
delete [] chunk_name;
|
||||||
}
|
return result;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -628,14 +611,9 @@ int ScriptApiSecurity::sl_g_load(lua_State *L)
|
|||||||
code += std::string(buf, len);
|
code += std::string(buf, len);
|
||||||
lua_pop(L, 1); // Pop return value
|
lua_pop(L, 1); // Pop return value
|
||||||
}
|
}
|
||||||
if (code[0] == LUA_SIGNATURE[0]) {
|
if (!safeLoadString(L, code, chunk_name)) {
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
lua_pushliteral(L, "Bytecode prohibited when mod security is enabled.");
|
lua_insert(L, -2);
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
if (luaL_loadbuffer(L, code.data(), code.size(), chunk_name)) {
|
|
||||||
lua_pushnil(L);
|
|
||||||
lua_insert(L, lua_gettop(L) - 1);
|
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@ -694,15 +672,11 @@ int ScriptApiSecurity::sl_g_loadstring(lua_State *L)
|
|||||||
|
|
||||||
size_t size;
|
size_t size;
|
||||||
const char *code = lua_tolstring(L, 1, &size);
|
const char *code = lua_tolstring(L, 1, &size);
|
||||||
|
std::string code_s(code, size);
|
||||||
|
|
||||||
if (size > 0 && code[0] == LUA_SIGNATURE[0]) {
|
if (!safeLoadString(L, code_s, chunk_name)) {
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
lua_pushliteral(L, "Bytecode prohibited when mod security is enabled.");
|
lua_insert(L, -2);
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
if (luaL_loadbuffer(L, code, size, chunk_name)) {
|
|
||||||
lua_pushnil(L);
|
|
||||||
lua_insert(L, lua_gettop(L) - 1);
|
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -50,6 +50,8 @@ public:
|
|||||||
void initializeSecurityClient();
|
void initializeSecurityClient();
|
||||||
// Checks if the Lua state has been secured
|
// Checks if the Lua state has been secured
|
||||||
static bool isSecure(lua_State *L);
|
static bool isSecure(lua_State *L);
|
||||||
|
// Loads a string as Lua code safely (doesn't allow bytecode).
|
||||||
|
static bool safeLoadString(lua_State *L, const std::string &code, const char *chunk_name);
|
||||||
// Loads a file as Lua code safely (doesn't allow bytecode).
|
// Loads a file as Lua code safely (doesn't allow bytecode).
|
||||||
static bool safeLoadFile(lua_State *L, const char *path, const char *display_name = NULL);
|
static bool safeLoadFile(lua_State *L, const char *path, const char *display_name = NULL);
|
||||||
// Checks if mods are allowed to read (and optionally write) to the path
|
// Checks if mods are allowed to read (and optionally write) to the path
|
||||||
|
Loading…
Reference in New Issue
Block a user