core: remove cgroups-agent

This commit is contained in:
Mike Yuan
2025-03-16 21:09:07 +01:00
parent f0f2675e24
commit be1d96dbc3
13 changed files with 23 additions and 409 deletions

View File

@@ -271,7 +271,6 @@ conf.set_quoted('SYSTEMCTL_BINARY_PATH', bindir / 'systemct
conf.set_quoted('SYSTEMD_BINARY_PATH', libexecdir / 'systemd')
conf.set_quoted('SYSTEMD_EXECUTOR_BINARY_PATH', libexecdir / 'systemd-executor')
conf.set_quoted('SYSTEMD_CATALOG_DIR', catalogdir)
conf.set_quoted('SYSTEMD_CGROUPS_AGENT_PATH', libexecdir / 'systemd-cgroups-agent')
conf.set_quoted('SYSTEMD_CRYPTSETUP_PATH', bindir / 'systemd-cryptsetup')
conf.set_quoted('SYSTEMD_EXPORT_PATH', libexecdir / 'systemd-export')
conf.set_quoted('SYSTEMD_FSCK_PATH', libexecdir / 'systemd-fsck')
@@ -2304,7 +2303,6 @@ subdir('src/boot')
subdir('src/bootctl')
subdir('src/busctl')
subdir('src/cgls')
subdir('src/cgroups-agent')
subdir('src/cgtop')
subdir('src/coredump')
subdir('src/creds')

View File

@@ -18,8 +18,10 @@ TS="${SOURCE_DATE_EPOCH:-$(date +%s)}"
# The openSUSE filelists hardcode the manpage compression extension. This causes rpmbuild errors since we
# disable manpage compression as the files cannot be found. Fix the issue by removing the compression
# extension.
#
# TODO: remove manual cgroups-agent patch when the upstream spec is updated
while read -r filelist; do
sed 's/\.gz$//' "$filelist" >"/tmp/$(basename "$filelist")"
sed 's/\.gz$//; /systemd-cgroups-agent/d' "$filelist" >"/tmp/$(basename "$filelist")"
mount --bind "/tmp/$(basename "$filelist")" "$filelist"
done < <(find "pkg/$PKG_SUBDIR${GIT_SUBDIR:+/$GIT_SUBDIR}" -name "files.*")

View File

@@ -1,54 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <stdlib.h>
#include "fd-util.h"
#include "log.h"
#include "socket-util.h"
int main(int argc, char *argv[]) {
static const union sockaddr_union sa = {
.un.sun_family = AF_UNIX,
.un.sun_path = "/run/systemd/cgroups-agent",
};
_cleanup_close_ int fd = -EBADF;
ssize_t n;
size_t l;
int r;
r = make_null_stdio();
if (r < 0) {
log_error_errno(r, "Failed to connect stdin/stdout/stderr with /dev/null: %m");
return EXIT_FAILURE;
}
if (argc != 2) {
log_error("Incorrect number of arguments.");
return EXIT_FAILURE;
}
log_setup();
fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
if (fd < 0) {
log_debug_errno(errno, "Failed to allocate socket: %m");
return EXIT_FAILURE;
}
l = strlen(argv[1]);
n = sendto(fd, argv[1], l, 0, &sa.sa, SOCKADDR_UN_LEN(sa.un));
if (n < 0) {
log_debug_errno(errno, "Failed to send cgroups agent message: %m");
return EXIT_FAILURE;
}
if ((size_t) n != l) {
log_debug("Datagram size mismatch");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}

View File

@@ -1,8 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
executables += [
libexec_template + {
'name' : 'systemd-cgroups-agent',
'sources' : files('cgroups-agent.c'),
},
]

View File

@@ -4332,44 +4332,26 @@ int manager_setup_cgroup(Manager *m) {
(void) sd_event_source_set_description(m->cgroup_empty_event_source, "cgroup-empty");
/* 4. Install notifier inotify object, or agent */
if (cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER) > 0) {
/* 4. Install cgroup empty event notifier inotify object */
m->cgroup_inotify_event_source = sd_event_source_disable_unref(m->cgroup_inotify_event_source);
safe_close(m->cgroup_inotify_fd);
/* In the unified hierarchy we can get cgroup empty notifications via inotify. */
m->cgroup_inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
if (m->cgroup_inotify_fd < 0)
return log_error_errno(errno, "Failed to create control group inotify object: %m");
m->cgroup_inotify_event_source = sd_event_source_disable_unref(m->cgroup_inotify_event_source);
safe_close(m->cgroup_inotify_fd);
r = sd_event_add_io(m->event, &m->cgroup_inotify_event_source, m->cgroup_inotify_fd, EPOLLIN, on_cgroup_inotify_event, m);
if (r < 0)
return log_error_errno(r, "Failed to watch control group inotify object: %m");
m->cgroup_inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
if (m->cgroup_inotify_fd < 0)
return log_error_errno(errno, "Failed to create control group inotify object: %m");
/* Process cgroup empty notifications early. Note that when this event is dispatched it'll
* just add the unit to a cgroup empty queue, hence let's run earlier than that. Also see
* handling of cgroup agent notifications, for the classic cgroup hierarchy support. */
r = sd_event_source_set_priority(m->cgroup_inotify_event_source, EVENT_PRIORITY_CGROUP_INOTIFY);
if (r < 0)
return log_error_errno(r, "Failed to set priority of inotify event source: %m");
r = sd_event_add_io(m->event, &m->cgroup_inotify_event_source, m->cgroup_inotify_fd, EPOLLIN, on_cgroup_inotify_event, m);
if (r < 0)
return log_error_errno(r, "Failed to watch control group inotify object: %m");
/* Process cgroup empty notifications early. Note that when this event is dispatched it'll
* just add the unit to a cgroup empty queue, hence let's run earlier than that. Also see
* handling of cgroup agent notifications, for the classic cgroup hierarchy support. */
r = sd_event_source_set_priority(m->cgroup_inotify_event_source, EVENT_PRIORITY_CGROUP_INOTIFY);
if (r < 0)
return log_error_errno(r, "Failed to set priority of inotify event source: %m");
(void) sd_event_source_set_description(m->cgroup_inotify_event_source, "cgroup-inotify");
} else if (MANAGER_IS_SYSTEM(m) && manager_owns_host_root_cgroup(m) && !MANAGER_IS_TEST_RUN(m)) {
/* On the legacy hierarchy we only get notifications via cgroup agents. (Which isn't really reliable,
* since it does not generate events when control groups with children run empty. */
r = cg_install_release_agent(SYSTEMD_CGROUP_CONTROLLER, SYSTEMD_CGROUPS_AGENT_PATH);
if (r < 0)
log_warning_errno(r, "Failed to install release agent, ignoring: %m");
else if (r > 0)
log_debug("Installed release agent.");
else if (r == 0)
log_debug("Release agent already installed.");
}
(void) sd_event_source_set_description(m->cgroup_inotify_event_source, "cgroup-inotify");
/* 5. Make sure we are in the special "init.scope" unit in the root slice. */
scope_path = strjoina(m->cgroup_root, "/" SPECIAL_INIT_SCOPE);

View File

@@ -69,61 +69,6 @@ void bus_send_pending_reload_message(Manager *m) {
return;
}
int bus_forward_agent_released(Manager *m, const char *path) {
int r;
assert(m);
assert(path);
if (!MANAGER_IS_SYSTEM(m))
return 0;
if (!m->system_bus)
return 0;
/* If we are running a system instance we forward the agent message on the system bus, so that the user
* instances get notified about this, too */
r = sd_bus_emit_signal(m->system_bus,
"/org/freedesktop/systemd1/agent",
"org.freedesktop.systemd1.Agent",
"Released",
"s", path);
if (r < 0)
return log_debug_errno(r, "Failed to propagate agent release message: %m");
return 1;
}
static int signal_agent_released(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
Manager *m = ASSERT_PTR(userdata);
const char *cgroup;
uid_t sender_uid;
int r;
assert(message);
/* only accept org.freedesktop.systemd1.Agent from UID=0 */
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
if (r < 0)
return r;
r = sd_bus_creds_get_euid(creds, &sender_uid);
if (r < 0 || sender_uid != 0)
return 0;
/* parse 'cgroup-empty' notification */
r = sd_bus_message_read(message, "s", &cgroup);
if (r < 0) {
bus_log_parse_error(r);
return 0;
}
manager_notify_cgroup_empty(m, cgroup);
return 0;
}
static int signal_disconnected(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = ASSERT_PTR(userdata);
sd_bus *bus;
@@ -890,30 +835,6 @@ int bus_init_api(Manager *m) {
return 0;
}
static void bus_setup_system(Manager *m, sd_bus *bus) {
int r;
assert(m);
assert(bus);
/* if we are a user instance we get the Released message via the system bus */
if (MANAGER_IS_USER(m)) {
r = sd_bus_match_signal_async(
bus,
NULL,
NULL,
"/org/freedesktop/systemd1/agent",
"org.freedesktop.systemd1.Agent",
"Released",
signal_agent_released, NULL, m);
if (r < 0)
log_warning_errno(r, "Failed to request Released match on system bus: %m");
}
log_debug("Successfully connected to system bus.");
return;
}
int bus_init_system(Manager *m) {
_cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
int r;
@@ -938,10 +859,10 @@ int bus_init_system(Manager *m) {
return r;
}
bus_setup_system(m, bus);
m->system_bus = TAKE_PTR(bus);
log_debug("Successfully connected to system bus.");
return 0;
}

View File

@@ -22,8 +22,6 @@ void bus_track_serialize(sd_bus_track *t, FILE *f, const char *prefix);
int bus_foreach_bus(Manager *m, sd_bus_track *subscribed2, int (*send_message)(sd_bus *bus, void *userdata), void *userdata);
int bus_forward_agent_released(Manager *m, const char *path);
uint64_t manager_bus_n_queued_write(Manager *m);
void dump_bus_properties(FILE *f);

View File

@@ -1723,11 +1723,6 @@ static int become_shutdown(int objective, int retval) {
if (arg_watchdog_device)
(void) strv_extendf(&env_block, "WATCHDOG_DEVICE=%s", arg_watchdog_device);
/* Avoid the creation of new processes forked by the kernel; at this
* point, we will not listen to the signals anyway */
if (detect_container() <= 0)
(void) cg_uninstall_release_agent(SYSTEMD_CGROUP_CONTROLLER);
(void) write_boot_or_shutdown_osc("shutdown");
execve(SYSTEMD_SHUTDOWN_BINARY_PATH, (char **) command_line, env_block);

View File

@@ -137,12 +137,6 @@ int manager_serialize(
(void) serialize_item(f, "notify-socket", m->notify_socket);
}
if (m->cgroups_agent_fd >= 0) {
r = serialize_fd(f, fds, "cgroups-agent-fd", m->cgroups_agent_fd);
if (r < 0)
return r;
}
if (m->user_lookup_fds[0] >= 0) {
r = serialize_fd_many(f, fds, "user-lookup", m->user_lookup_fds, 2);
if (r < 0)
@@ -453,15 +447,6 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
if (r < 0)
return r;
} else if ((val = startswith(l, "cgroups-agent-fd="))) {
int fd;
fd = deserialize_fd(fds, val);
if (fd >= 0) {
m->cgroups_agent_event_source = sd_event_source_disable_unref(m->cgroups_agent_event_source);
close_and_replace(m->cgroups_agent_fd, fd);
}
} else if ((val = startswith(l, "user-lookup="))) {
m->user_lookup_event_source = sd_event_source_disable_unref(m->user_lookup_event_source);
@@ -550,7 +535,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
if (q < _MANAGER_TIMESTAMP_MAX) /* found it */
(void) deserialize_dual_timestamp(val, m->timestamps + q);
else if (!STARTSWITH_SET(l, "kdbus-fd=", "honor-device-enumeration=", "ready-sent=")) /* ignore deprecated values */
else if (!STARTSWITH_SET(l, "kdbus-fd=", "honor-device-enumeration=", "ready-sent=", "cgroups-agent-fd=")) /* ignore deprecated values */
log_notice("Unknown serialization item '%s', ignoring.", l);
}
}

View File

@@ -122,7 +122,6 @@
#define DEFAULT_TASKS_MAX ((CGroupTasksMax) { 15U, 100U }) /* 15% */
static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
static int manager_dispatch_cgroups_agent_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
static int manager_dispatch_time_change_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
static int manager_dispatch_idle_pipe_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
@@ -912,7 +911,6 @@ int manager_new(RuntimeScope runtime_scope, ManagerTestRunFlags test_run_flags,
.show_status_overridden = _SHOW_STATUS_INVALID,
.notify_fd = -EBADF,
.cgroups_agent_fd = -EBADF,
.signal_fd = -EBADF,
.user_lookup_fds = EBADF_PAIR,
.handoff_timestamp_fds = EBADF_PAIR,
@@ -1136,80 +1134,6 @@ static int manager_setup_notify(Manager *m) {
return 0;
}
static int manager_setup_cgroups_agent(Manager *m) {
static const union sockaddr_union sa = {
.un.sun_family = AF_UNIX,
.un.sun_path = "/run/systemd/cgroups-agent",
};
int r;
/* This creates a listening socket we receive cgroups agent messages on. We do not use D-Bus for delivering
* these messages from the cgroups agent binary to PID 1, as the cgroups agent binary is very short-living, and
* each instance of it needs a new D-Bus connection. Since D-Bus connections are SOCK_STREAM/AF_UNIX, on
* overloaded systems the backlog of the D-Bus socket becomes relevant, as not more than the configured number
* of D-Bus connections may be queued until the kernel will start dropping further incoming connections,
* possibly resulting in lost cgroups agent messages. To avoid this, we'll use a private SOCK_DGRAM/AF_UNIX
* socket, where no backlog is relevant as communication may take place without an actual connect() cycle, and
* we thus won't lose messages.
*
* Note that PID 1 will forward the agent message to system bus, so that the user systemd instance may listen
* to it. The system instance hence listens on this special socket, but the user instances listen on the system
* bus for these messages. */
if (MANAGER_IS_TEST_RUN(m))
return 0;
if (!MANAGER_IS_SYSTEM(m))
return 0;
r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER);
if (r < 0)
return log_error_errno(r, "Failed to determine whether unified cgroups hierarchy is used: %m");
if (r > 0) /* We don't need this anymore on the unified hierarchy */
return 0;
if (m->cgroups_agent_fd < 0) {
_cleanup_close_ int fd = -EBADF;
/* First free all secondary fields */
m->cgroups_agent_event_source = sd_event_source_disable_unref(m->cgroups_agent_event_source);
fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
if (fd < 0)
return log_error_errno(errno, "Failed to allocate cgroups agent socket: %m");
(void) fd_increase_rxbuf(fd, MANAGER_SOCKET_RCVBUF_SIZE);
(void) sockaddr_un_unlink(&sa.un);
/* Only allow root to connect to this socket */
WITH_UMASK(0077)
r = bind(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un));
if (r < 0)
return log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path);
m->cgroups_agent_fd = TAKE_FD(fd);
}
if (!m->cgroups_agent_event_source) {
r = sd_event_add_io(m->event, &m->cgroups_agent_event_source, m->cgroups_agent_fd, EPOLLIN, manager_dispatch_cgroups_agent_fd, m);
if (r < 0)
return log_error_errno(r, "Failed to allocate cgroups agent event source: %m");
/* Process cgroups notifications early. Note that when the agent notification is received
* we'll just enqueue the unit in the cgroup empty queue, hence pick a high priority than
* that. Also see handling of cgroup inotify for the unified cgroup stuff. */
r = sd_event_source_set_priority(m->cgroups_agent_event_source, EVENT_PRIORITY_CGROUP_AGENT);
if (r < 0)
return log_error_errno(r, "Failed to set priority of cgroups agent event source: %m");
(void) sd_event_source_set_description(m->cgroups_agent_event_source, "manager-cgroups-agent");
}
return 0;
}
static int manager_setup_user_lookup_fd(Manager *m) {
int r;
@@ -1763,7 +1687,6 @@ Manager* manager_free(Manager *m) {
sd_event_source_unref(m->signal_event_source);
sd_event_source_unref(m->sigchld_event_source);
sd_event_source_unref(m->notify_event_source);
sd_event_source_unref(m->cgroups_agent_event_source);
sd_event_source_unref(m->time_change_event_source);
sd_event_source_unref(m->timezone_change_event_source);
sd_event_source_unref(m->jobs_in_progress_event_source);
@@ -1775,7 +1698,6 @@ Manager* manager_free(Manager *m) {
safe_close(m->signal_fd);
safe_close(m->notify_fd);
safe_close(m->cgroups_agent_fd);
safe_close_pair(m->user_lookup_fds);
safe_close_pair(m->handoff_timestamp_fds);
safe_close_pair(m->pidref_transport_fds);
@@ -2137,11 +2059,6 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds, const char *roo
/* No sense to continue without notifications, our children would fail anyway. */
return r;
r = manager_setup_cgroups_agent(m);
if (r < 0)
/* Likewise, no sense to continue without empty cgroup notifications. */
return r;
r = manager_setup_user_lookup_fd(m);
if (r < 0)
/* This shouldn't fail, except if things are really broken. */
@@ -2681,35 +2598,6 @@ static unsigned manager_dispatch_dbus_queue(Manager *m) {
return n;
}
static int manager_dispatch_cgroups_agent_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
Manager *m = userdata;
char buf[PATH_MAX];
ssize_t n;
n = recv(fd, buf, sizeof(buf), 0);
if (n < 0)
return log_error_errno(errno, "Failed to read cgroups agent message: %m");
if (n == 0) {
log_error("Got zero-length cgroups agent message, ignoring.");
return 0;
}
if ((size_t) n >= sizeof(buf)) {
log_error("Got overly long cgroups agent message, ignoring.");
return 0;
}
if (memchr(buf, 0, n)) {
log_error("Got cgroups agent message with embedded NUL byte, ignoring.");
return 0;
}
buf[n] = 0;
manager_notify_cgroup_empty(m, buf);
(void) bus_forward_agent_released(m, buf);
return 0;
}
static bool manager_process_barrier_fd(char * const *tags, FDSet *fds) {
/* nothing else must be sent when using BARRIER=1 */
@@ -3713,7 +3601,6 @@ int manager_reload(Manager *m) {
/* Re-register notify_fd as event source, and set up other sockets/communication channels we might need */
(void) manager_setup_notify(m);
(void) manager_setup_cgroups_agent(m);
(void) manager_setup_user_lookup_fd(m);
(void) manager_setup_handoff_timestamp_fd(m);
(void) manager_setup_pidref_transport_fd(m);

View File

@@ -269,9 +269,6 @@ struct Manager {
int notify_fd;
sd_event_source *notify_event_source;
int cgroups_agent_fd;
sd_event_source *cgroups_agent_event_source;
int signal_fd;
sd_event_source *signal_event_source;
@@ -684,8 +681,7 @@ enum {
EVENT_PRIORITY_USER_LOOKUP = SD_EVENT_PRIORITY_NORMAL-12,
EVENT_PRIORITY_MOUNT_TABLE = SD_EVENT_PRIORITY_NORMAL-11,
EVENT_PRIORITY_SWAP_TABLE = SD_EVENT_PRIORITY_NORMAL-11,
EVENT_PRIORITY_CGROUP_AGENT = SD_EVENT_PRIORITY_NORMAL-10, /* cgroupv1 */
EVENT_PRIORITY_CGROUP_INOTIFY = SD_EVENT_PRIORITY_NORMAL-10, /* cgroupv2 */
EVENT_PRIORITY_CGROUP_INOTIFY = SD_EVENT_PRIORITY_NORMAL-10,
EVENT_PRIORITY_CGROUP_OOM = SD_EVENT_PRIORITY_NORMAL-9,
EVENT_PRIORITY_PIDREF = SD_EVENT_PRIORITY_NORMAL-8,
EVENT_PRIORITY_HANDOFF_TIMESTAMP = SD_EVENT_PRIORITY_NORMAL-7,

View File

@@ -868,91 +868,6 @@ int cg_trim_v1_controllers(CGroupMask supported, CGroupMask mask, const char *pa
return r;
}
int cg_install_release_agent(const char *controller, const char *agent) {
_cleanup_free_ char *fs = NULL, *contents = NULL;
const char *sc;
int r;
assert(agent);
r = cg_unified_controller(controller);
if (r < 0)
return r;
if (r > 0) /* doesn't apply to unified hierarchy */
return -EOPNOTSUPP;
r = cg_get_path(controller, NULL, "release_agent", &fs);
if (r < 0)
return r;
r = read_one_line_file(fs, &contents);
if (r < 0)
return r;
sc = strstrip(contents);
if (isempty(sc)) {
r = write_string_file(fs, agent, WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
return r;
} else if (!path_equal(sc, agent))
return -EEXIST;
fs = mfree(fs);
r = cg_get_path(controller, NULL, "notify_on_release", &fs);
if (r < 0)
return r;
contents = mfree(contents);
r = read_one_line_file(fs, &contents);
if (r < 0)
return r;
sc = strstrip(contents);
if (streq(sc, "0")) {
r = write_string_file(fs, "1", WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
return r;
return 1;
}
if (!streq(sc, "1"))
return -EIO;
return 0;
}
int cg_uninstall_release_agent(const char *controller) {
_cleanup_free_ char *fs = NULL;
int r;
r = cg_unified_controller(controller);
if (r < 0)
return r;
if (r > 0) /* Doesn't apply to unified hierarchy */
return -EOPNOTSUPP;
r = cg_get_path(controller, NULL, "notify_on_release", &fs);
if (r < 0)
return r;
r = write_string_file(fs, "0", WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
return r;
fs = mfree(fs);
r = cg_get_path(controller, NULL, "release_agent", &fs);
if (r < 0)
return r;
r = write_string_file(fs, "", WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
return r;
return 0;
}
int cg_has_legacy(void) {
struct statfs fs;

View File

@@ -38,7 +38,4 @@ int cg_migrate_recursive_fallback(const char *cfrom, const char *pfrom, const ch
int cg_migrate_v1_controllers(CGroupMask supported, CGroupMask mask, const char *from, cg_migrate_callback_t to_callback, void *userdata);
int cg_trim_v1_controllers(CGroupMask supported, CGroupMask mask, const char *path, bool delete_root);
int cg_install_release_agent(const char *controller, const char *agent);
int cg_uninstall_release_agent(const char *controller);
int cg_has_legacy(void);