From da71e86633d0b27cd02d7aac9fdac625d141ca13 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Wed, 25 May 2022 19:07:49 +0200 Subject: Protect a few more settings from being set from mods Of those settings main_menu_script has concrete security impact, the rest are added out of abundance of caution. --- src/script/lua_api/l_settings.cpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'src/script/lua_api') diff --git a/src/script/lua_api/l_settings.cpp b/src/script/lua_api/l_settings.cpp index 14398dda2..3f3fda56e 100644 --- a/src/script/lua_api/l_settings.cpp +++ b/src/script/lua_api/l_settings.cpp @@ -27,9 +27,11 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "log.h" -/* This protects: - * 'secure.*' settings from being set - * some mapgen settings from being set +/* This protects the following from being set: + * 'secure.*' settings + * some security-relevant settings + * (better solution pending) + * some mapgen settings * (not security-criticial, just to avoid messing up user configs) */ #define CHECK_SETTING_SECURITY(L, name) \ @@ -41,7 +43,7 @@ with this program; if not, write to the Free Software Foundation, Inc., static inline int checkSettingSecurity(lua_State* L, const std::string &name) { if (ScriptApiSecurity::isSecure(L) && name.compare(0, 7, "secure.") == 0) - throw LuaError("Attempt to set secure setting."); + throw LuaError("Attempted to set secure setting."); bool is_mainmenu = false; #ifndef SERVER @@ -54,6 +56,17 @@ static inline int checkSettingSecurity(lua_State* L, const std::string &name) return -1; } + const char *disallowed[] = { + "main_menu_script", "shader_path", "texture_path", "screenshot_path", + "serverlist_file", "serverlist_url", "map-dir", "contentdb_url", + }; + if (!is_mainmenu) { + for (const char *name2 : disallowed) { + if (name == name2) + throw LuaError("Attempted to set disallowed setting."); + } + } + return 0; } -- cgit v1.2.3 From f195db2d140a7b4f2f2fbc438680c9d5e23a0d6d Mon Sep 17 00:00:00 2001 From: sfan5 Date: Wed, 25 May 2022 19:29:11 +0200 Subject: Add API function to invoke player respawn closes #12272 --- doc/lua_api.txt | 2 ++ src/script/lua_api/l_object.cpp | 17 +++++++++++++++++ src/script/lua_api/l_object.h | 3 +++ src/server.cpp | 5 +++-- src/server.h | 3 ++- 5 files changed, 27 insertions(+), 3 deletions(-) (limited to 'src/script/lua_api') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 882c9c54c..15a067a5e 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -7099,6 +7099,8 @@ object you are working with still exists. * `intensity` sets the intensity of the shadows from 0 (no shadows, default) to 1 (blackness) * `get_lighting()`: returns the current state of lighting for the player. * Result is a table with the same fields as `light_definition` in `set_lighting`. +* `respawn()`: Respawns the player using the same mechanism as the death screen, + including calling on_respawnplayer callbacks. `PcgRandom` ----------- diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 39b19364e..37ba1521a 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -2323,6 +2323,21 @@ int ObjectRef::l_get_lighting(lua_State *L) return 1; } +// respawn(self) +int ObjectRef::l_respawn(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + RemotePlayer *player = getplayer(ref); + if (player == nullptr) + return 0; + + getServer(L)->RespawnPlayer(player->getPeerId()); + lua_pushboolean(L, true); + return 1; +} + + ObjectRef::ObjectRef(ServerActiveObject *object): m_object(object) {} @@ -2478,5 +2493,7 @@ luaL_Reg ObjectRef::methods[] = { luamethod(ObjectRef, set_minimap_modes), luamethod(ObjectRef, set_lighting), luamethod(ObjectRef, get_lighting), + luamethod(ObjectRef, respawn), + {0,0} }; diff --git a/src/script/lua_api/l_object.h b/src/script/lua_api/l_object.h index 3e4e6681a..b36bab492 100644 --- a/src/script/lua_api/l_object.h +++ b/src/script/lua_api/l_object.h @@ -382,4 +382,7 @@ private: // get_lighting(self) static int l_get_lighting(lua_State *L); + + // respawn(self) + static int l_respawn(lua_State *L); }; diff --git a/src/server.cpp b/src/server.cpp index b6330c96a..c775f5d07 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -2784,9 +2784,10 @@ void Server::RespawnPlayer(session_t peer_id) << playersao->getPlayer()->getName() << " respawns" << std::endl; - playersao->setHP(playersao->accessObjectProperties()->hp_max, + const auto *prop = playersao->accessObjectProperties(); + playersao->setHP(prop->hp_max, PlayerHPChangeReason(PlayerHPChangeReason::RESPAWN)); - playersao->setBreath(playersao->accessObjectProperties()->breath_max); + playersao->setBreath(prop->breath_max); bool repositioned = m_script->on_respawnplayer(playersao); if (!repositioned) { diff --git a/src/server.h b/src/server.h index 71f692e87..a9c5bcb5f 100644 --- a/src/server.h +++ b/src/server.h @@ -336,6 +336,8 @@ public: void setLighting(RemotePlayer *player, const Lighting &lighting); + void RespawnPlayer(session_t peer_id); + /* con::PeerHandler implementation. */ void peerAdded(con::Peer *peer); void deletingPeer(con::Peer *peer, bool timeout); @@ -529,7 +531,6 @@ private: */ void HandlePlayerDeath(PlayerSAO* sao, const PlayerHPChangeReason &reason); - void RespawnPlayer(session_t peer_id); void DeleteClient(session_t peer_id, ClientDeletionReason reason); void UpdateCrafting(RemotePlayer *player); bool checkInteractDistance(RemotePlayer *player, const f32 d, const std::string &what); -- cgit v1.2.3 From 8908a9101608d3343023b470743ef63f1c44b0b7 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Thu, 26 May 2022 15:45:34 +0200 Subject: Get rid of node metadata when it becomes empty fixes #8943 --- games/devtest/mods/unittests/misc.lua | 20 ++++++++++++++++++++ src/script/lua_api/l_nodemeta.cpp | 13 ++++++++----- src/script/lua_api/l_nodemeta.h | 6 ++++-- 3 files changed, 32 insertions(+), 7 deletions(-) (limited to 'src/script/lua_api') diff --git a/games/devtest/mods/unittests/misc.lua b/games/devtest/mods/unittests/misc.lua index ba980866a..4b53004b1 100644 --- a/games/devtest/mods/unittests/misc.lua +++ b/games/devtest/mods/unittests/misc.lua @@ -48,3 +48,23 @@ local function test_v3s16_metatable(player, pos) assert(vector.check(found_pos)) end unittests.register("test_v3s16_metatable", test_v3s16_metatable, {map=true}) + +local function test_clear_meta(_, pos) + local ref = core.get_meta(pos) + + for way = 1, 3 do + ref:set_string("foo", "bar") + assert(ref:contains("foo")) + + if way == 1 then + ref:from_table({}) + elseif way == 2 then + ref:from_table(nil) + else + ref:set_string("foo", "") + end + + assert(#core.find_nodes_with_meta(pos, pos) == 0, "clearing failed " .. way) + end +end +unittests.register("test_clear_meta", test_clear_meta, {map=true}) diff --git a/src/script/lua_api/l_nodemeta.cpp b/src/script/lua_api/l_nodemeta.cpp index 1d052685e..514a1b78b 100644 --- a/src/script/lua_api/l_nodemeta.cpp +++ b/src/script/lua_api/l_nodemeta.cpp @@ -40,7 +40,7 @@ NodeMetaRef* NodeMetaRef::checkobject(lua_State *L, int narg) Metadata* NodeMetaRef::getmeta(bool auto_create) { if (m_is_local) - return m_meta; + return m_local_meta; NodeMetadata *meta = m_env->getMap().getNodeMetadata(m_p); if (meta == NULL && auto_create) { @@ -62,9 +62,12 @@ void NodeMetaRef::clearMeta() void NodeMetaRef::reportMetadataChange(const std::string *name) { SANITY_CHECK(!m_is_local); - // NOTE: This same code is in rollback_interface.cpp // Inform other things that the metadata has changed - NodeMetadata *meta = dynamic_cast(m_meta); + NodeMetadata *meta = dynamic_cast(getmeta(false)); + + // If the metadata is now empty, get rid of it + if (meta && meta->empty()) + clearMeta(); MapEditEvent event; event.type = MEET_BLOCK_NODE_METADATA_CHANGED; @@ -174,8 +177,8 @@ NodeMetaRef::NodeMetaRef(v3s16 p, ServerEnvironment *env): } NodeMetaRef::NodeMetaRef(Metadata *meta): - m_meta(meta), - m_is_local(true) + m_is_local(true), + m_local_meta(meta) { } diff --git a/src/script/lua_api/l_nodemeta.h b/src/script/lua_api/l_nodemeta.h index fdc1766ed..265ece3d0 100644 --- a/src/script/lua_api/l_nodemeta.h +++ b/src/script/lua_api/l_nodemeta.h @@ -33,10 +33,12 @@ class NodeMetadata; class NodeMetaRef : public MetaDataRef { private: + bool m_is_local = false; + // Set for server metadata v3s16 m_p; ServerEnvironment *m_env = nullptr; - Metadata *m_meta = nullptr; - bool m_is_local = false; + // Set for client metadata + Metadata *m_local_meta = nullptr; static const char className[]; static const luaL_Reg methodsServer[]; -- cgit v1.2.3 From a9a207685a9d55e4fcdd97f5065383e2ec18e114 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Thu, 26 May 2022 22:28:33 +0200 Subject: Reject registering node with empty name fixes #10769 --- src/script/lua_api/l_item.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/script/lua_api') diff --git a/src/script/lua_api/l_item.cpp b/src/script/lua_api/l_item.cpp index b58b994d9..27c1b8875 100644 --- a/src/script/lua_api/l_item.cpp +++ b/src/script/lua_api/l_item.cpp @@ -594,6 +594,9 @@ int ModApiItemMod::l_register_item_raw(lua_State *L) // be done if (f.name == "ignore") return 0; + // This would break everything + if (f.name.empty()) + throw LuaError("Cannot register node with empty name"); content_t id = ndef->set(f.name, f); -- cgit v1.2.3 From 9fc018ded10225589d2559d24a5db739e891fb31 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Sun, 29 May 2022 16:00:44 +0200 Subject: Fix use-after-free in node meta cleanup bug introduced in 8908a9101608d3343023b470743ef63f1c44b0b7 --- src/script/lua_api/l_nodemeta.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/script/lua_api') diff --git a/src/script/lua_api/l_nodemeta.cpp b/src/script/lua_api/l_nodemeta.cpp index 514a1b78b..bdc4844c0 100644 --- a/src/script/lua_api/l_nodemeta.cpp +++ b/src/script/lua_api/l_nodemeta.cpp @@ -66,8 +66,10 @@ void NodeMetaRef::reportMetadataChange(const std::string *name) NodeMetadata *meta = dynamic_cast(getmeta(false)); // If the metadata is now empty, get rid of it - if (meta && meta->empty()) + if (meta && meta->empty()) { clearMeta(); + meta = nullptr; + } MapEditEvent event; event.type = MEET_BLOCK_NODE_METADATA_CHANGED; -- cgit v1.2.3