diff options
author | Sergey Bugaev <bugaevc@serenityos.org> | 2020-12-26 15:12:49 +0300 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-12-26 14:23:29 +0100 |
commit | 95157f8b818c198a4934eb5a786d682f8f347f25 (patch) | |
tree | 2a22a6e34a16534eadb532f2c690894e84d05933 /Services/SystemServer | |
parent | 7babe5ade6050367d455623b67c86940ecca4604 (diff) | |
download | serenity-95157f8b818c198a4934eb5a786d682f8f347f25.zip |
SystemServer: Port to Core::Account
We now have a handy Core::Account class that we can use instead of iterating
over the passwd database ourselves.
Diffstat (limited to 'Services/SystemServer')
-rw-r--r-- | Services/SystemServer/Service.cpp | 62 | ||||
-rw-r--r-- | Services/SystemServer/Service.h | 8 |
2 files changed, 21 insertions, 49 deletions
diff --git a/Services/SystemServer/Service.cpp b/Services/SystemServer/Service.cpp index acc06062a3..1bd205e873 100644 --- a/Services/SystemServer/Service.cpp +++ b/Services/SystemServer/Service.cpp @@ -40,43 +40,8 @@ #include <sys/stat.h> #include <unistd.h> -struct UidAndGids { - uid_t uid; - gid_t gid; - Vector<gid_t> extra_gids; -}; - -static HashMap<String, UidAndGids>* s_user_map; static HashMap<pid_t, Service*> s_service_map; -void Service::resolve_user() -{ - if (s_user_map == nullptr) { - s_user_map = new HashMap<String, UidAndGids>; - for (struct passwd* passwd = getpwent(); passwd; passwd = getpwent()) { - Vector<gid_t> extra_gids; - for (struct group* group = getgrent(); group; group = getgrent()) { - for (size_t m = 0; group->gr_mem[m]; ++m) { - if (!strcmp(group->gr_mem[m], passwd->pw_name)) - extra_gids.append(group->gr_gid); - } - } - endgrent(); - s_user_map->set(passwd->pw_name, { passwd->pw_uid, passwd->pw_gid, move(extra_gids) }); - } - endpwent(); - } - - auto user = s_user_map->get(m_user); - if (!user.has_value()) { - dbg() << "Failed to resolve user name " << m_user; - ASSERT_NOT_REACHED(); - } - m_uid = user.value().uid; - m_gid = user.value().gid; - m_extra_gids = user.value().extra_gids; -} - Service* Service::find_by_pid(pid_t pid) { auto it = s_service_map.find(pid); @@ -102,9 +67,12 @@ void Service::setup_socket() ASSERT_NOT_REACHED(); } - if (fchown(m_socket_fd, m_uid, m_gid) < 0) { - perror("fchown"); - ASSERT_NOT_REACHED(); + if (m_account.has_value()) { + auto& account = m_account.value(); + if (fchown(m_socket_fd, account.uid(), account.gid()) < 0) { + perror("fchown"); + ASSERT_NOT_REACHED(); + } } if (fchmod(m_socket_fd, m_socket_permissions) < 0) { @@ -240,9 +208,10 @@ void Service::spawn(int socket_fd) setenv("SOCKET_TAKEOVER", "1", true); } - if (!m_user.is_null()) { - if (setgid(m_gid) < 0 || setgroups(m_extra_gids.size(), m_extra_gids.data()) < 0 || setuid(m_uid) < 0) { - dbgprintf("Failed to drop privileges (GID=%u, UID=%u)\n", m_gid, m_uid); + if (m_account.has_value()) { + auto& account = m_account.value(); + if (setgid(account.gid()) < 0 || setgroups(account.extra_gids().size(), account.extra_gids().data()) < 0 || setuid(account.uid()) < 0) { + dbgprintf("Failed to drop privileges (GID=%u, UID=%u)\n", account.gid(), account.uid()); exit(1); } } @@ -324,8 +293,13 @@ Service::Service(const Core::ConfigFile& config, const StringView& name) m_lazy = config.read_bool_entry(name, "Lazy"); m_user = config.read_entry(name, "User"); - if (!m_user.is_null()) - resolve_user(); + if (!m_user.is_null()) { + auto result = Core::Account::from_name(m_user.characters()); + if (result.is_error()) + warnln("Failed to resolve user {}: {}", m_user, result.error()); + else + m_account = result.value(); + } m_working_directory = config.read_entry(name, "WorkingDirectory"); m_environment = config.read_entry(name, "Environment").split(' '); @@ -382,8 +356,6 @@ void Service::save_to(JsonObject& json) json.set("socket_permissions", m_socket_permissions); json.set("lazy", m_lazy); json.set("user", m_user); - json.set("uid", m_uid); - json.set("gid", m_gid); json.set("multi_instance", m_multi_instance); json.set("accept_socket_connections", m_accept_socket_connections); diff --git a/Services/SystemServer/Service.h b/Services/SystemServer/Service.h index 7b4bbed380..23014825cf 100644 --- a/Services/SystemServer/Service.h +++ b/Services/SystemServer/Service.h @@ -28,6 +28,7 @@ #include <AK/RefPtr.h> #include <AK/String.h> +#include <LibCore/Account.h> #include <LibCore/ElapsedTimer.h> #include <LibCore/Notifier.h> #include <LibCore/Object.h> @@ -71,9 +72,6 @@ private: bool m_lazy; // The name of the user we should run this service as. String m_user; - uid_t m_uid { 0 }; - gid_t m_gid { 0 }; - Vector<gid_t> m_extra_gids; // The working directory in which to spawn the service. String m_working_directory; // Boot modes to run this service in. By default, this is the graphical mode. @@ -83,6 +81,9 @@ private: // Environment variables to pass to the service. Vector<String> m_environment; + // The resolved user account to run this service as. + Optional<Core::Account> m_account; + // For single-instance services, PID of the running instance of this service. pid_t m_pid { -1 }; // An open fd to the socket. @@ -95,7 +96,6 @@ private: // times where it has exited unsuccessfully and too quickly. int m_restart_attempts { 0 }; - void resolve_user(); void setup_socket(); void setup_notifier(); void handle_socket_connection(); |