diff --git a/apps/init.cpp b/apps/init.cpp index 3e8ec3d9..612822ca 100644 --- a/apps/init.cpp +++ b/apps/init.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -19,6 +20,8 @@ #include #include +static bool g_is_system = false; + FILE* g_init_log = nullptr; // Request a successful exit from the system (for tests) @@ -42,6 +45,8 @@ struct Service String standard_output; String standard_error; String standard_input; + Option user {}; + Option group {}; bool wait { false }; Option pid {}; }; @@ -67,6 +72,12 @@ static Result service_child(const Service& service, SharedPtr ou if (error) dup2(error->fd(), STDERR_FILENO); if (input) dup2(input->fd(), STDIN_FILENO); + if (service.user.has_value()) + { + setgid(service.group.value()); + setuid(service.user.value()); + } + if (service.environment.is_empty()) { TRY(os::Process::exec(args[0].view(), args.slice(), false)); } else { @@ -216,6 +227,15 @@ static Result load_service(const os::Path& path) continue; } + if (g_is_system && parts[0].view() == "User") + { + auto* pw = getpwnam(parts[1].chars()); + if (!pw) continue; + service.user = pw->pw_uid; + service.group = pw->pw_gid; + continue; + } + if (parts[0].view() == "Wait") { if (parts[1].view() == "true" || parts[1].view().to_uint().value_or(0) == 1) @@ -311,6 +331,8 @@ Result sysinit() return 1; } + g_is_system = true; + // Before this point, we don't even have an stdin, stdout and stderr. Set it up now so that child processes (and us) // can print stuff. stdin = fopen("/dev/console", "r");