Keep gloved in a systemd-owned supervisor leaf while creating sibling session cgroups under the empty delegated parent. Under mapped-root supervisors, attach blocked children before releasing their existing start gate instead of combining nested UID mapping with CLONE_INTO_CGROUP.
126 lines
4.9 KiB
C++
126 lines
4.9 KiB
C++
#include "glove/host/daemon.hpp"
|
|
#include "glove/host/setup.hpp"
|
|
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
|
|
#include <cstdio>
|
|
#include <filesystem>
|
|
#include <fstream>
|
|
#include <string>
|
|
#include <system_error>
|
|
|
|
namespace {
|
|
|
|
#define REQUIRE(condition) \
|
|
do { \
|
|
if (!(condition)) { \
|
|
std::fprintf(stderr, "REQUIRE failed: %s @ %s:%d\n", #condition, __FILE__, __LINE__); \
|
|
return 1; \
|
|
} \
|
|
} while (false)
|
|
|
|
class temporary_directory {
|
|
public:
|
|
temporary_directory() {
|
|
std::string pattern = "/tmp/glove-daemon-test-XXXXXX";
|
|
char* created = ::mkdtemp(pattern.data());
|
|
if (created != nullptr) {
|
|
root_ = created;
|
|
}
|
|
}
|
|
|
|
temporary_directory(const temporary_directory&) = delete;
|
|
auto operator=(const temporary_directory&) -> temporary_directory& = delete;
|
|
temporary_directory(temporary_directory&&) = delete;
|
|
auto operator=(temporary_directory&&) -> temporary_directory& = delete;
|
|
|
|
~temporary_directory() {
|
|
std::error_code ignored;
|
|
std::filesystem::remove_all(root_, ignored);
|
|
}
|
|
|
|
[[nodiscard]] auto root() const -> const std::filesystem::path& { return root_; }
|
|
|
|
private:
|
|
std::filesystem::path root_{};
|
|
};
|
|
|
|
auto write_executable(const std::filesystem::path& path) -> bool {
|
|
std::ofstream output{path, std::ios::binary | std::ios::trunc};
|
|
output << "#!/bin/sh\nexit 0\n";
|
|
output.close();
|
|
return output.good() && ::chmod(path.c_str(), 0700) == 0;
|
|
}
|
|
|
|
auto run() -> int {
|
|
using namespace glove::host;
|
|
|
|
const temporary_directory temporary;
|
|
REQUIRE(!temporary.root().empty());
|
|
environment values{};
|
|
values.home = temporary.root().string();
|
|
auto setup = plan_setup(setup_options{}, values);
|
|
REQUIRE(setup.has_value());
|
|
REQUIRE(execute_setup(*setup).has_value());
|
|
|
|
const auto gloved = temporary.root() / "gloved test";
|
|
REQUIRE(write_executable(gloved));
|
|
auto plan = plan_daemon_service(
|
|
daemon_options{.config_path = setup->config_path, .gloved_path = gloved}, values
|
|
);
|
|
REQUIRE(plan.has_value());
|
|
REQUIRE(plan->config_path == setup->config_path);
|
|
REQUIRE(plan->gloved_path == std::filesystem::canonical(gloved));
|
|
REQUIRE(plan->service_definition.find(gloved.string()) != std::string::npos);
|
|
REQUIRE(plan->service_definition.find(setup->config_path.string()) != std::string::npos);
|
|
|
|
std::error_code remove_error;
|
|
std::filesystem::remove_all(setup->service.runtime_directory, remove_error);
|
|
REQUIRE(!remove_error);
|
|
REQUIRE(!std::filesystem::exists(setup->service.runtime_directory));
|
|
REQUIRE(prepare_daemon_runtime(*plan).has_value());
|
|
struct stat runtime_metadata{};
|
|
REQUIRE(::lstat(setup->service.runtime_directory.c_str(), &runtime_metadata) == 0);
|
|
REQUIRE(S_ISDIR(runtime_metadata.st_mode));
|
|
REQUIRE((static_cast<unsigned int>(runtime_metadata.st_mode) & 0777U) == 0700U);
|
|
|
|
REQUIRE(::chmod(setup->service.runtime_directory.c_str(), 0755) == 0);
|
|
REQUIRE(prepare_daemon_runtime(*plan).has_value());
|
|
REQUIRE(::lstat(setup->service.runtime_directory.c_str(), &runtime_metadata) == 0);
|
|
REQUIRE((static_cast<unsigned int>(runtime_metadata.st_mode) & 0777U) == 0700U);
|
|
|
|
REQUIRE(::chmod(setup->service.runtime_directory.c_str(), 0777) == 0);
|
|
REQUIRE(!prepare_daemon_runtime(*plan).has_value());
|
|
REQUIRE(::chmod(setup->service.runtime_directory.c_str(), 0700) == 0);
|
|
|
|
#if defined(__linux__)
|
|
REQUIRE(plan->manager == daemon_service_manager::systemd_user);
|
|
REQUIRE(plan->service_name == "sage-gloved.service");
|
|
REQUIRE(plan->service_path == temporary.root() / ".config/systemd/user/sage-gloved.service");
|
|
REQUIRE(
|
|
plan->service_definition.find(
|
|
"ExecStart=\"/usr/bin/unshare\" --user --map-root-user --mount "
|
|
"--propagation private -- \""
|
|
) != std::string::npos
|
|
);
|
|
REQUIRE(plan->service_definition.find(gloved.string()) != std::string::npos);
|
|
REQUIRE(plan->service_definition.find("Delegate=cpu memory pids\n") != std::string::npos);
|
|
REQUIRE(plan->service_definition.find("DelegateSubgroup=glove-host\n") != std::string::npos);
|
|
#elif defined(__APPLE__)
|
|
REQUIRE(plan->manager == daemon_service_manager::launchd_user);
|
|
REQUIRE(plan->service_name == "org.sage-protocol.gloved");
|
|
REQUIRE(
|
|
plan->service_path ==
|
|
temporary.root() / "Library/LaunchAgents/org.sage-protocol.gloved.plist"
|
|
);
|
|
REQUIRE(plan->service_definition.find("<key>ProgramArguments</key>") != std::string::npos);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
auto main() -> int {
|
|
return run();
|
|
}
|