diff --git a/src/lua/lua_manager.cpp b/src/lua/lua_manager.cpp index d981c83b..9a6f8f8a 100644 --- a/src/lua/lua_manager.cpp +++ b/src/lua/lua_manager.cpp @@ -4,8 +4,9 @@ namespace big { - lua_manager::lua_manager(folder scripts_folder) : - m_scripts_folder(scripts_folder) + lua_manager::lua_manager(folder scripts_folder, folder scripts_config_folder) : + m_scripts_folder(scripts_folder), + m_scripts_config_folder(scripts_config_folder) { m_wake_time_changed_scripts_check = std::chrono::high_resolution_clock::now() + m_delay_between_changed_scripts_check; diff --git a/src/lua/lua_manager.hpp b/src/lua/lua_manager.hpp index f953b721..2c5d37d7 100644 --- a/src/lua/lua_manager.hpp +++ b/src/lua/lua_manager.hpp @@ -14,9 +14,10 @@ namespace big std::chrono::high_resolution_clock::time_point m_wake_time_changed_scripts_check; folder m_scripts_folder; + folder m_scripts_config_folder; public: - lua_manager(folder scripts_folder); + lua_manager(folder scripts_folder, folder scripts_config_folder); ~lua_manager(); void load_all_modules(); @@ -32,6 +33,11 @@ namespace big return m_scripts_folder; } + inline const folder& get_scripts_config_folder() const + { + return m_scripts_config_folder; + } + std::weak_ptr get_module(rage::joaat_t module_id); bool has_gui_to_draw(rage::joaat_t tab_hash); diff --git a/src/lua/lua_module.cpp b/src/lua/lua_module.cpp index 2cfb4418..e77a0950 100644 --- a/src/lua/lua_module.cpp +++ b/src/lua/lua_module.cpp @@ -16,8 +16,8 @@ #include "bindings/stats.hpp" #include "bindings/tunables.hpp" #include "bindings/vector.hpp" -#include "bindings/weapons.hpp" #include "bindings/vehicles.hpp" +#include "bindings/weapons.hpp" #include "file_manager.hpp" #include "script_mgr.hpp" @@ -96,6 +96,7 @@ namespace big sol::lib::math, sol::lib::table, sol::lib::bit32, + sol::lib::io, sol::lib::utf8 ); // clang-format on @@ -179,6 +180,45 @@ namespace big m_state["os"] = sandbox_os; } + void lua_module::sandbox_lua_io_library() + { + auto io = m_state["io"]; + sol::table sandbox_io(m_state, sol::create); + + m_io_open = io["open"]; + sandbox_io["open"] = [this](const std::string& filename, const std::string& mode) { + constexpr auto make_absolute = [](const std::filesystem::path& root, const std::filesystem::path& user_path) -> std::optional { + auto final_path = std::filesystem::weakly_canonical(root / user_path); + + auto [root_end, nothing] = std::mismatch(root.begin(), root.end(), final_path.begin()); + + if (root_end != root.end()) + return std::nullopt; + + return final_path; + }; + + const auto scripts_config_sub_path = make_absolute(g_lua_manager->get_scripts_config_folder().get_path(), filename); + if (!scripts_config_sub_path) + { + LOG(WARNING) << "io.open is restricted to the scripts_config folder, and the filename provided (" << filename << ") is outside of it."; + + return sol::reference(sol::lua_nil); + } + + const auto res = m_io_open(scripts_config_sub_path.value().u8string().c_str(), mode).get(); + + if (res.get_type() == sol::type::lua_nil) + { + LOG(WARNING) << "Couldn't io.open a file called " << filename << " mode (" << mode << "). Note that io.open is restricted to the scripts_config folder."; + } + + return res; + }; + + m_state["io"] = sandbox_io; + } + template static constexpr auto not_supported_lua_function(const char (&function_name)[N]) { @@ -216,6 +256,7 @@ namespace big // https://blog.rubenwardy.com/2020/07/26/sol3-script-sandbox/ // https://www.lua.org/manual/5.4/manual.html#pdf-require sandbox_lua_os_library(); + sandbox_lua_io_library(); sandbox_lua_loads(scripts_folder); lua::log::bind(m_state); diff --git a/src/lua/lua_module.hpp b/src/lua/lua_module.hpp index fd0d21c3..85c605fb 100644 --- a/src/lua/lua_module.hpp +++ b/src/lua/lua_module.hpp @@ -1,9 +1,10 @@ #pragma once +#include "../script.hpp" #include "bindings/gui/gui_element.hpp" #include "core/data/menu_event.hpp" #include "lua_patch.hpp" #include "sol.hpp" -#include "../script.hpp" + #include namespace big @@ -12,6 +13,8 @@ namespace big { sol::state m_state; + sol::protected_function m_io_open; + std::filesystem::path m_module_path; std::string m_module_name; @@ -47,6 +50,7 @@ namespace big void set_folder_for_lua_require(folder& scripts_folder); void sandbox_lua_os_library(); + void sandbox_lua_io_library(); void sandbox_lua_loads(folder& scripts_folder); void init_lua_api(folder& scripts_folder); diff --git a/src/main.cpp b/src/main.cpp index 408c7083..80eaa4f0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -113,11 +113,11 @@ BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID) auto pointers_instance = std::make_unique(); LOG(INFO) << "Pointers initialized."; - while(!disable_anticheat_skeleton()) - { - LOG(WARNING) << "Failed patching anticheat gameskeleton (injected too early?). Waiting 100ms and trying again"; - std::this_thread::sleep_for(100ms); - } + while (!disable_anticheat_skeleton()) + { + LOG(WARNING) << "Failed patching anticheat gameskeleton (injected too early?). Waiting 100ms and trying again"; + std::this_thread::sleep_for(100ms); + } LOG(INFO) << "Disabled anticheat gameskeleton."; auto byte_patch_manager_instance = std::make_unique(); @@ -187,7 +187,8 @@ BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID) auto native_hooks_instance = std::make_unique(); LOG(INFO) << "Dynamic native hooker initialized."; - auto lua_manager_instance = std::make_unique(g_file_manager.get_project_folder("scripts")); + auto lua_manager_instance = + std::make_unique(g_file_manager.get_project_folder("scripts"), g_file_manager.get_project_folder("scripts_config")); LOG(INFO) << "Lua manager initialized."; g_running = true;