diff options
| author | Vaxry <43317083+vaxerski@users.noreply.github.com> | 2025-05-06 22:43:08 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-05-06 22:43:08 +0200 |
| commit | f8bbe5124c0012865ea36f52d304313084a31fe9 (patch) | |
| tree | 803f46d75b4807c0bd1343eedfa1a3c1aeb0b8d0 /hyprpm/src/helpers/Sys.cpp | |
| parent | 948277895efba5e8bcc66d34dcafe87518fc7b61 (diff) | |
hyprpm: clean up root access and properly check input (#10304)
* manifest: reject bad names from parsing
* sys: restructure root functions
Diffstat (limited to 'hyprpm/src/helpers/Sys.cpp')
| -rw-r--r-- | hyprpm/src/helpers/Sys.cpp | 120 |
1 files changed, 82 insertions, 38 deletions
diff --git a/hyprpm/src/helpers/Sys.cpp b/hyprpm/src/helpers/Sys.cpp index 868ad9a9..a5876b9d 100644 --- a/hyprpm/src/helpers/Sys.cpp +++ b/hyprpm/src/helpers/Sys.cpp @@ -6,7 +6,7 @@ #include <unistd.h> #include <print> #include <filesystem> -#include <optional> +#include <algorithm> #include <hyprutils/os/Process.hpp> #include <hyprutils/string/VarList.hpp> @@ -20,7 +20,7 @@ inline constexpr std::array<std::string_view, 3> SUPERUSER_BINARIES = { "run0", }; -static std::string fetchSuperuserBins() { +static std::string validSubinsAsStr() { std::ostringstream oss; auto it = SUPERUSER_BINARIES.begin(); if (it != SUPERUSER_BINARIES.end()) { @@ -56,17 +56,30 @@ static bool executableExistsInPath(const std::string& exe) { return false; } -static std::optional<std::pair<std::string, int>> execAndGet(std::string_view cmd, bool noRedirect = false) { - std::string command = std::string{cmd}; - if (!noRedirect) - command += " 2>&1"; +static std::string subin() { + static std::string bin; + static bool once = true; + if (!once) + return bin; - CProcess proc("/bin/sh", {"-c", command}); - if (!proc.runSync()) - // optional handles nullopt gracefully - return std::nullopt; + for (const auto& BIN : SUPERUSER_BINARIES) { + if (!executableExistsInPath(std::string{BIN})) + continue; + + bin = BIN; + break; + } + + once = false; - return {{proc.stdOut(), proc.exitCode()}}; + if (bin.empty()) + Debug::die("{}", failureString("No valid superuser binary present. Supported: {}", validSubinsAsStr())); + + return bin; +} + +static bool verifyStringValid(const std::string& s) { + return std::ranges::none_of(s, [](const char& c) { return c == '`' || c == '$' || c == '(' || c == ')' || c == '\'' || c == '"'; }); } int NSys::getUID() { @@ -85,39 +98,70 @@ bool NSys::isSuperuser() { return getuid() != geteuid() || geteuid() == 0; } -std::string NSys::runAsSuperuser(const std::string& cmd) { - for (const auto& BIN : SUPERUSER_BINARIES) { - if (!executableExistsInPath(std::string{BIN})) - continue; - - const auto result = execAndGet(std::string{BIN} + " /bin/sh -c \"" + cmd + "\"", true); - if (!result.has_value() || result->second != 0) - Debug::die("Failed to run a command as sudo. This could be due to an invalid password, or a hyprpm bug."); +void NSys::root::cacheSudo() { + // "caches" the sudo so that the prompt later doesn't pop up in a weird spot + // sudo will not ask us again for a moment + CProcess proc(subin(), {"echo", "hyprland"}); + proc.runSync(); +} - return result->first; +void NSys::root::dropSudo() { + if (subin() != "sudo") { + std::println("{}", infoString("Don't know how to drop timestamp for '{}', ignoring.", subin())); + return; } - Debug::die("{} {}", "Failed to find a superuser binary. Supported: ", fetchSuperuserBins()); - return ""; + CProcess proc(subin(), {"-k"}); + proc.runSync(); } -void NSys::cacheSudo() { - // "caches" the sudo so that the prompt later doesn't pop up in a weird spot - // sudo will not ask us again for a moment - runAsSuperuser("echo e > /dev/null"); +bool NSys::root::createDirectory(const std::string& path, const std::string& mode) { + if (!verifyStringValid(path)) + return false; + + if (!std::ranges::all_of(mode, [](const char& c) { return c >= '0' && c <= '9'; })) + return false; + + CProcess proc(subin(), {"mkdir", "-p", "-m", mode, path}); + + return proc.runSync() && proc.exitCode() == 0; } -void NSys::dropSudo() { - for (const auto& BIN : SUPERUSER_BINARIES) { - if (!executableExistsInPath(std::string{BIN})) - continue; +bool NSys::root::removeRecursive(const std::string& path) { + if (!verifyStringValid(path)) + return false; - if (BIN == "sudo") - execAndGet("sudo -k"); - else { - // note the superuser binary that is being dropped - std::println("{}", infoString("Don't know how to drop timestamp for '{}', ignoring.", BIN)); - } - return; - } + std::error_code ec; + const std::string PATH_ABSOLUTE = std::filesystem::canonical(path, ec); + + if (ec) + return false; + + if (!PATH_ABSOLUTE.starts_with("/var/cache/hyprpm")) + return false; + + CProcess proc(subin(), {"rm", "-fr", PATH_ABSOLUTE}); + + return proc.runSync() && proc.exitCode() == 0; +} + +bool NSys::root::install(const std::string& what, const std::string& where, const std::string& mode) { + if (!verifyStringValid(what) || !verifyStringValid(where)) + return false; + + if (!std::ranges::all_of(mode, [](const char& c) { return c >= '0' && c <= '9'; })) + return false; + + CProcess proc(subin(), {"install", "-m" + mode, "-o", "root", "-g", "root", what, where}); + + return proc.runSync() && proc.exitCode() == 0; +} + +std::string NSys::root::runAsSuperuserUnsafe(const std::string& cmd) { + CProcess proc(subin(), {"/bin/sh", "-c", cmd}); + + if (!proc.runSync()) + return ""; + + return proc.stdOut(); } |
