From d102ea5f8183bad5ab0f09f2402b4b8a6739d88c Mon Sep 17 00:00:00 2001 From: Liav A Date: Mon, 24 Oct 2022 17:59:56 +0300 Subject: [PATCH] Userland: Unveil /usr/lib/Loader.so when using 'x' permissions on unveil We should not rely on the Kernel to unveil this for us, so if a program needs to execute another program it should unveil the dynamic loader too to prevent crashing. To do this, we check if the user program tried to unveil a binary with at least using the 'x' permission, so we will try to also unveil the dynamic loader too. --- Userland/Libraries/LibCore/System.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Userland/Libraries/LibCore/System.cpp b/Userland/Libraries/LibCore/System.cpp index fc49a9bc22..170a0c7336 100644 --- a/Userland/Libraries/LibCore/System.cpp +++ b/Userland/Libraries/LibCore/System.cpp @@ -81,10 +81,34 @@ ErrorOr pledge(StringView promises, StringView execpromises) HANDLE_SYSCALL_RETURN_VALUE("pledge", rc, {}); } +static ErrorOr unveil_dynamic_loader() +{ + static bool dynamic_loader_unveiled { false }; + if (dynamic_loader_unveiled) + return {}; + // FIXME: Try to find a way to not hardcode the dynamic loader path. + constexpr auto dynamic_loader_path = "/usr/lib/Loader.so"sv; + constexpr auto dynamic_loader_permissions = "x"sv; + + Syscall::SC_unveil_params params { + { dynamic_loader_path.characters_without_null_termination(), dynamic_loader_path.length() }, + { dynamic_loader_permissions.characters_without_null_termination(), dynamic_loader_permissions.length() }, + }; + int rc = syscall(SC_unveil, ¶ms); + if (rc < 0) { + return Error::from_syscall("unveil (DynamicLoader @ /usr/lib/Loader.so)"sv, rc); + } + dynamic_loader_unveiled = true; + return {}; +} + ErrorOr unveil(StringView path, StringView permissions) { auto const parsed_path = TRY(Core::SessionManagement::parse_path_with_sid(path)); + if (permissions.contains('x')) + TRY(unveil_dynamic_loader()); + Syscall::SC_unveil_params params { { parsed_path.characters(), parsed_path.length() }, { permissions.characters_without_null_termination(), permissions.length() },