summaryrefslogtreecommitdiff
path: root/hyprpm/src/helpers/Sys.cpp
diff options
context:
space:
mode:
authorVaxry <43317083+vaxerski@users.noreply.github.com>2025-05-06 22:43:08 +0200
committerGitHub <noreply@github.com>2025-05-06 22:43:08 +0200
commitf8bbe5124c0012865ea36f52d304313084a31fe9 (patch)
tree803f46d75b4807c0bd1343eedfa1a3c1aeb0b8d0 /hyprpm/src/helpers/Sys.cpp
parent948277895efba5e8bcc66d34dcafe87518fc7b61 (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.cpp120
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();
}