mirror of
https://github.com/fergalmoran/ladybird.git
synced 2026-02-21 07:06:04 +00:00
If we try to launch a lazily-spawned service and the SystemServer as a (running --user) session leader is running with root permissions, then if it is instructed to drop the root permissions for a the new service then it will make sense to abort the entire spawn procedure if dropping of privileges failed. For other users, trying to change UID/GID to something else doesn't make sense (and will always actually fail) as we are already running in non root permissions, hence we don't attempt to do this anymore. It should be noted that if an explicit User configuration was actually specified for a Service to be used with, we would still try to login with the requested User option value, which would fail when running as non-root user. This is useful for example when trying to run the pro utility with pls to elevate to root permissions, but the session leader is still the same so trying to "drop" privileges to UID 0 doesn't make sense.
96 lines
3.2 KiB
C++
96 lines
3.2 KiB
C++
/*
|
|
* Copyright (c) 2019-2020, Sergey Bugaev <bugaevc@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/DeprecatedString.h>
|
|
#include <AK/RefPtr.h>
|
|
#include <LibCore/Account.h>
|
|
#include <LibCore/ElapsedTimer.h>
|
|
#include <LibCore/Notifier.h>
|
|
#include <LibCore/Object.h>
|
|
|
|
class Service final : public Core::Object {
|
|
C_OBJECT_ABSTRACT(Service)
|
|
|
|
public:
|
|
static ErrorOr<NonnullRefPtr<Service>> try_create(Core::ConfigFile const& config, StringView name);
|
|
~Service();
|
|
|
|
bool is_enabled() const;
|
|
ErrorOr<void> activate();
|
|
ErrorOr<void> did_exit(int exit_code);
|
|
|
|
static Service* find_by_pid(pid_t);
|
|
|
|
private:
|
|
Service(Core::ConfigFile const&, StringView name);
|
|
|
|
ErrorOr<void> spawn(int socket_fd = -1);
|
|
|
|
ErrorOr<void> determine_account(int fd);
|
|
|
|
ErrorOr<void> change_privileges();
|
|
|
|
/// SocketDescriptor describes the details of a single socket that was
|
|
/// requested by a service.
|
|
struct SocketDescriptor {
|
|
/// The path of the socket.
|
|
DeprecatedString path;
|
|
/// File descriptor of the socket. -1 if the socket hasn't been opened.
|
|
int fd { -1 };
|
|
/// File permissions of the socket.
|
|
mode_t permissions;
|
|
};
|
|
|
|
// Path to the executable. By default this is /bin/{m_name}.
|
|
DeprecatedString m_executable_path;
|
|
// Extra arguments, starting from argv[1], to pass when exec'ing.
|
|
DeprecatedString m_extra_arguments;
|
|
// File path to open as stdio fds.
|
|
DeprecatedString m_stdio_file_path;
|
|
int m_priority { 1 };
|
|
// Whether we should re-launch it if it exits.
|
|
bool m_keep_alive { false };
|
|
// Whether we should accept connections on the socket and pass the accepted
|
|
// (and not listening) socket to the service. This requires a multi-instance
|
|
// service.
|
|
bool m_accept_socket_connections { false };
|
|
// Whether we should only spawn this service once somebody connects to the socket.
|
|
bool m_lazy;
|
|
// The name of the user we should run this service as.
|
|
DeprecatedString m_user;
|
|
// The working directory in which to spawn the service.
|
|
DeprecatedString m_working_directory;
|
|
// System modes in which to run this service. By default, this is the graphical mode.
|
|
Vector<DeprecatedString> m_system_modes;
|
|
// Whether several instances of this service can run at once.
|
|
bool m_multi_instance { false };
|
|
// Environment variables to pass to the service.
|
|
DeprecatedString m_environment;
|
|
// Socket descriptors for this service.
|
|
Vector<SocketDescriptor> m_sockets;
|
|
|
|
// The resolved user account to run this service as.
|
|
Optional<Core::Account> m_account;
|
|
bool m_must_login { false };
|
|
|
|
// For single-instance services, PID of the running instance of this service.
|
|
pid_t m_pid { -1 };
|
|
RefPtr<Core::Notifier> m_socket_notifier;
|
|
|
|
// Timer since we last spawned the service.
|
|
Core::ElapsedTimer m_run_timer;
|
|
// How many times we have tried to restart this service, only counting those
|
|
// times where it has exited unsuccessfully and too quickly.
|
|
int m_restart_attempts { 0 };
|
|
|
|
ErrorOr<void> setup_socket(SocketDescriptor&);
|
|
ErrorOr<void> setup_sockets();
|
|
void setup_notifier();
|
|
ErrorOr<void> handle_socket_connection();
|
|
};
|