From cfb60fad25004b39f949c130f7c375172bc86743 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 14 Aug 2023 10:46:28 +0200 Subject: [PATCH] init: Use pledge and support init --user --- apps/init.cpp | 83 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 77 insertions(+), 6 deletions(-) diff --git a/apps/init.cpp b/apps/init.cpp index a18e395f..3e8ec3d9 100644 --- a/apps/init.cpp +++ b/apps/init.cpp @@ -4,9 +4,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -247,9 +249,9 @@ static Result load_service(const os::Path& path) return {}; } -static Result load_services() +static Result load_services(StringView path) { - auto dir = TRY(os::Directory::open("/etc/init")); + auto dir = TRY(os::Directory::open(path)); auto services = TRY(dir->list_names(os::Directory::Filter::ParentAndBase)); sort(services.begin(), services.end(), String::compare); @@ -259,9 +261,9 @@ static Result load_services() return {}; } -static Result start_services() +static Result start_services(StringView path) { - TRY(load_services()); + TRY(load_services(path)); for (auto& service : g_services) { do_log("[init] starting service %s\n", service.name.chars()); @@ -301,7 +303,7 @@ static void mount_shmfs() if (chmod("/dev/shm", 01777) < 0) exit(255); } -int main() +Result sysinit() { if (getpid() != 1) { @@ -315,6 +317,8 @@ int main() stdout = fopen("/dev/console", "w"); stderr = fopen("/dev/console", "w"); + TRY(os::Security::pledge("stdio rpath wpath cpath fattr host mount proc exec signal", nullptr)); + mount_tmpfs(); mount_shmfs(); @@ -330,7 +334,11 @@ int main() if (signal(SIGTERM, sigterm_handler) == SIG_ERR) do_log("[init] failed to register handler for SIGTERM\n"); if (signal(SIGQUIT, sigquit_handler) == SIG_ERR) do_log("[init] failed to register handler for SIGQUIT\n"); - start_services(); + TRY(os::Security::pledge("stdio rpath wpath cpath proc exec", nullptr)); + + start_services("/etc/init"); + + TRY(os::Security::pledge("stdio rpath wpath proc exec", nullptr)); while (1) { @@ -365,3 +373,66 @@ int main() } } } + +Result user_init() +{ + setpgid(0, 0); + + g_init_log = fopen("/dev/uart0", "w"); + check(g_init_log); + setlinebuf(g_init_log); + fcntl(fileno(g_init_log), F_SETFD, FD_CLOEXEC); + + TRY(os::Security::pledge("stdio rpath wpath cpath proc exec", nullptr)); + + start_services("/etc/user"); + + TRY(os::Security::pledge("stdio rpath wpath proc exec", nullptr)); + + while (1) + { + int status; + auto rc = os::Process::wait(os::Process::ANY_CHILD, &status); + if (rc.has_error()) continue; + + pid_t child = rc.release_value(); + + for (auto& service : g_services) + { + if (service.pid.has_value() && service.pid.value() == child) + { + if (WIFEXITED(status)) + { + do_log("[init] service %s exited with status %d\n", service.name.chars(), WEXITSTATUS(status)); + } + else + { + do_log("[init] service %s was terminated by signal %d\n", service.name.chars(), WTERMSIG(status)); + } + + if (service.restart) + { + do_log("[init] restarting service %s\n", service.name.chars()); + + start_service(service); + } + + break; + } + } + } +} + +Result luna_main(int argc, char** argv) +{ + bool user; + + os::ArgumentParser parser; + parser.add_description("The init system for Luna."); + parser.add_system_program_info("init"_sv); + parser.add_switch_argument(user, 'u', "user"_sv, "initialize a user session instead of the system"); + parser.parse(argc, argv); + + if (user) return user_init(); + return sysinit(); +}