From 340cecaf809c224d564b59559e0ef37f58b48e5a Mon Sep 17 00:00:00 2001 From: Brendan Coles Date: Sun, 30 May 2021 06:00:25 +0000 Subject: [PATCH] pls: Unveil search paths with browse permissions --- Userland/Utilities/pls.cpp | 54 ++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/Userland/Utilities/pls.cpp b/Userland/Utilities/pls.cpp index 7cfb1ecedb..182e95782c 100644 --- a/Userland/Utilities/pls.cpp +++ b/Userland/Utilities/pls.cpp @@ -28,30 +28,31 @@ bool unveil_paths(const char*); // Unveil paths, given the current user's path and the command they want to execute bool unveil_paths(const char* command) { - bool did_unveil_ok = false; - - // Attempt to unveil command via `realpath` - auto* command_path = realpath(command, nullptr); - - // Command found via `realpath` (meaning it was probably a locally executed program) - if (command_path) { - if (unveil(command_path, "x") == 0) - did_unveil_ok = true; - - free(command_path); - return did_unveil_ok; + // Unveil all trusted paths with browse permissions + auto trusted_directories = Array { "/bin", "/usr/bin", "/usr/local/bin" }; + for (auto directory : trusted_directories) { + if (unveil(directory, "b") < 0) { + perror("unveil"); + return false; + } + } + + // Attempt to unveil command via `realpath` + auto command_path = Core::File::real_path_for(command); + + // Command found via `realpath` (meaning it was probably a locally executed program) + if (!command_path.is_empty()) { + if (unveil(command_path.characters(), "x") == 0) + return true; + return false; } - // Okay, so we couldn't find the actual file specified by the user, let's - // instead search PATH for it... auto command_path_system = Core::find_executable_in_path(command); if (command_path_system.is_empty()) return false; - - if (unveil(command_path_system.characters(), "x") == 0) - did_unveil_ok = true; - - return did_unveil_ok; + if (unveil(command_path_system.characters(), "x") < 0) + return false; + return true; } int main(int argc, char** argv) @@ -59,9 +60,13 @@ int main(int argc, char** argv) Vector command; Core::ArgsParser args_parser; args_parser.add_positional_argument(command, "Command to run at elevated privilege level", "command"); - args_parser.parse(argc, argv); + // Unveil command path. + // Fail silently to prevent disclosing whether the specified path is valid + auto command_path = LexicalPath(Core::File::real_path_for(command.at(0))).dirname(); + unveil(command_path.characters(), "b"); + if (pledge("stdio tty rpath exec id", nullptr) < 0) { perror("pledge"); return 1; @@ -87,12 +92,9 @@ int main(int argc, char** argv) return 1; } - // Unveil all paths in the user's PATH, as well as the command they've specified. - auto unveil_count = unveil_paths(command.at(0)); - if (unveil_count == 0) { - warnln("Error: Failed to unveil paths!"); - return 1; - } + // Find and unveil the user's command executable. + // Fail silently to prevent disclosing whether the specified path is valid + unveil_paths(command.at(0)); // Lock veil unveil(nullptr, nullptr);