From: Yu Watanabe Date: Sun, 20 Apr 2025 21:27:35 +0000 (+0900) Subject: utmp: drop setting runlevel entry in utmp X-Git-Tag: v258-rc1~58^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dc1505555ba4058b0e17735f4e008540517e13ec;p=thirdparty%2Fsystemd.git utmp: drop setting runlevel entry in utmp This removes systemd-update-utmp-runlevel.service and related command. --- diff --git a/TODO b/TODO index 7e23ddb2c8a..916c3096aa8 100644 --- a/TODO +++ b/TODO @@ -2268,7 +2268,7 @@ Features: * clean up date formatting and parsing so that all absolute/relative timestamps we format can also be parsed -* on shutdown: move utmp, wall, audit logic all into PID 1 (or logind?), get rid of systemd-update-utmp-runlevel +* on shutdown: move utmp, wall, audit logic all into PID 1 (or logind?) * make repeated alt-ctrl-del presses printing a dump diff --git a/man/rules/meson.build b/man/rules/meson.build index 246a059fa5a..1fcf30e6928 100644 --- a/man/rules/meson.build +++ b/man/rules/meson.build @@ -1185,10 +1185,7 @@ manpages = [ 'systemd-udevd-varlink.socket'], ''], ['systemd-update-done.service', '8', ['systemd-update-done'], ''], - ['systemd-update-utmp.service', - '8', - ['systemd-update-utmp', 'systemd-update-utmp-runlevel.service'], - 'ENABLE_UTMP'], + ['systemd-update-utmp.service', '8', ['systemd-update-utmp'], 'ENABLE_UTMP'], ['systemd-user-sessions.service', '8', ['systemd-user-sessions'], 'HAVE_PAM'], ['systemd-userdbd.service', '8', ['systemd-userdbd'], 'ENABLE_USERDB'], ['systemd-validatefs@.service', '8', [], 'HAVE_BLKID'], diff --git a/man/systemd-update-utmp.service.xml b/man/systemd-update-utmp.service.xml index 2d7dee9d3a5..a3044e9739c 100644 --- a/man/systemd-update-utmp.service.xml +++ b/man/systemd-update-utmp.service.xml @@ -17,26 +17,21 @@ systemd-update-utmp.service - systemd-update-utmp-runlevel.service systemd-update-utmp - Write audit and utmp updates at bootup, runlevel - changes and shutdown + Write audit and utmp updates at bootup and shutdown systemd-update-utmp.service - systemd-update-utmp-runlevel.service /usr/lib/systemd/systemd-update-utmp Description - systemd-update-utmp-runlevel.service is - a service that writes SysV runlevel changes to utmp and wtmp, as - well as the audit logs, as they occur. - systemd-update-utmp.service does the same for - system reboots and shutdown requests. + + systemd-update-utmp.service is a service that writes system reboots and shutdown + requests to utmp and wtmp, as well as the audit logs. diff --git a/src/shared/utmp-wtmp.c b/src/shared/utmp-wtmp.c index 8a69e9692ba..6d150e7dcf3 100644 --- a/src/shared/utmp-wtmp.c +++ b/src/shared/utmp-wtmp.c @@ -11,44 +11,6 @@ #include "time-util.h" #include "utmp-wtmp.h" -int utmp_get_runlevel(int *runlevel, int *previous) { - _unused_ _cleanup_(utxent_cleanup) bool utmpx = false; - struct utmpx *found, lookup = { .ut_type = RUN_LVL }; - const char *e; - - assert(runlevel); - - /* If these values are set in the environment this takes - * precedence. Presumably, sysvinit does this to work around a - * race condition that would otherwise exist where we'd always - * go to disk and hence might read runlevel data that might be - * very new and not apply to the current script being executed. */ - - e = getenv("RUNLEVEL"); - if (!isempty(e)) { - *runlevel = e[0]; - if (previous) - *previous = 0; - - return 0; - } - - if (utmpxname(UTMPX_FILE) < 0) - return -errno; - - utmpx = utxent_start(); - - found = getutxid(&lookup); - if (!found) - return -errno; - - *runlevel = found->ut_pid & 0xFF; - if (previous) - *previous = (found->ut_pid >> 8) & 0xFF; - - return 0; -} - static void init_timestamp(struct utmpx *store, usec_t t) { assert(store); @@ -237,33 +199,3 @@ int utmp_put_dead_process(const char *id, pid_t pid, int code, int status) { return write_utmp_wtmp(&store, &store_wtmp); } - -int utmp_put_runlevel(int runlevel, int previous) { - struct utmpx store = {}; - int r; - - assert(runlevel > 0); - - if (previous <= 0) { - /* Find the old runlevel automatically */ - - r = utmp_get_runlevel(&previous, NULL); - if (r < 0) { - if (r != -ESRCH) - return r; - - previous = 0; - } - } - - if (previous == runlevel) - return 0; - - init_entry(&store, 0); - - store.ut_type = RUN_LVL; - store.ut_pid = (runlevel & 0xFF) | ((previous & 0xFF) << 8); - strncpy(store.ut_user, "runlevel", sizeof(store.ut_user)); - - return write_entry_both(&store); -} diff --git a/src/shared/utmp-wtmp.h b/src/shared/utmp-wtmp.h index f4b543e6c08..72e8ff375b8 100644 --- a/src/shared/utmp-wtmp.h +++ b/src/shared/utmp-wtmp.h @@ -6,11 +6,8 @@ #if ENABLE_UTMP #include -int utmp_get_runlevel(int *runlevel, int *previous); - int utmp_put_shutdown(void); int utmp_put_reboot(usec_t timestamp); -int utmp_put_runlevel(int runlevel, int previous); int utmp_put_dead_process(const char *id, pid_t pid, int code, int status); int utmp_put_init_process(const char *id, pid_t pid, pid_t sid, const char *line, int ut_type, const char *user); @@ -27,18 +24,12 @@ static inline void utxent_cleanup(bool *initialized) { #else /* ENABLE_UTMP */ -static inline int utmp_get_runlevel(int *runlevel, int *previous) { - return -ESRCH; -} static inline int utmp_put_shutdown(void) { return 0; } static inline int utmp_put_reboot(usec_t timestamp) { return 0; } -static inline int utmp_put_runlevel(int runlevel, int previous) { - return 0; -} static inline int utmp_put_dead_process(const char *id, pid_t pid, int code, int status) { return 0; } diff --git a/src/update-utmp/update-utmp.c b/src/update-utmp/update-utmp.c index 78c693012e2..4f96f3a377b 100644 --- a/src/update-utmp/update-utmp.c +++ b/src/update-utmp/update-utmp.c @@ -57,81 +57,6 @@ static int get_startup_monotonic_time(Context *c, usec_t *ret) { return 0; } -#define MAX_ATTEMPTS 64u - -static int get_current_runlevel(Context *c) { - static const struct { - const int runlevel; - const char *special; - } table[] = { - /* The first target of this list that is active or has a job scheduled wins. We prefer - * runlevels 5 and 3 here over the others, since these are the main runlevels used on Fedora. - * It might make sense to change the order on some distributions. */ - { '5', SPECIAL_GRAPHICAL_TARGET }, - { '3', SPECIAL_MULTI_USER_TARGET }, - { '1', SPECIAL_RESCUE_TARGET }, - }; - int r; - - assert(c); - - for (unsigned n_attempts = 0;;) { - if (n_attempts++ > 0) { - /* systemd might have dropped off momentarily, let's not make this an error, - * and wait some random time. Let's pick a random time in the range 100ms…2000ms, - * linearly scaled by the number of failed attempts. */ - c->bus = sd_bus_flush_close_unref(c->bus); - - usec_t usec = - UINT64_C(100) * USEC_PER_MSEC + - random_u64_range(UINT64_C(1900) * USEC_PER_MSEC * n_attempts / MAX_ATTEMPTS); - (void) usleep_safe(usec); - } - - if (!c->bus) { - r = bus_connect_system_systemd(&c->bus); - if (r == -ECONNREFUSED && n_attempts < 64) { - log_debug_errno(r, "Failed to %s to system bus, retrying after a slight delay: %m", - n_attempts <= 1 ? "connect" : "reconnect"); - continue; - } - if (r < 0) - return log_error_errno(r, "Failed to reconnect to system bus: %m"); - } - - FOREACH_ELEMENT(e, table) { - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_free_ char *state = NULL, *path = NULL; - - path = unit_dbus_path_from_name(e->special); - if (!path) - return log_oom(); - - r = sd_bus_get_property_string( - c->bus, - "org.freedesktop.systemd1", - path, - "org.freedesktop.systemd1.Unit", - "ActiveState", - &error, - &state); - if ((r == -ENOTCONN || bus_error_is_connection(&error)) && - n_attempts < MAX_ATTEMPTS) { - log_debug_errno(r, "Failed to get state of %s, retrying after a slight delay: %s", - e->special, bus_error_message(&error, r)); - break; - } - if (r < 0) - return log_warning_errno(r, "Failed to get state of %s: %s", e->special, bus_error_message(&error, r)); - - if (STR_IN_SET(state, "active", "reloading")) - return e->runlevel; - } - if (r >= 0) - return 0; - } -} - static int on_reboot(int argc, char *argv[], void *userdata) { Context *c = ASSERT_PTR(userdata); usec_t t = 0, boottime; @@ -182,59 +107,10 @@ static int on_shutdown(int argc, char *argv[], void *userdata) { return q; } -static int on_runlevel(int argc, char *argv[], void *userdata) { - Context *c = ASSERT_PTR(userdata); - int r, q = 0, previous, runlevel; - - /* We finished changing runlevel, so let's write the utmp record and send the audit msg. */ - - /* First, get last runlevel */ - r = utmp_get_runlevel(&previous, NULL); - if (r < 0) { - if (!IN_SET(r, -ESRCH, -ENOENT)) - return log_error_errno(r, "Failed to get the last runlevel from utmp: %m"); - - previous = 0; - } - - /* Secondly, get new runlevel */ - runlevel = get_current_runlevel(c); - if (runlevel < 0) - return runlevel; - if (runlevel == 0) { - log_warning("Failed to get the current runlevel, utmp update skipped."); - return 0; - } - - if (previous == runlevel) - return 0; - -#if HAVE_AUDIT - if (c->audit_fd >= 0) { - char s[STRLEN("old-level=_ new-level=_") + 1]; - - xsprintf(s, "old-level=%c new-level=%c", - previous > 0 ? previous : 'N', - runlevel); - - if (audit_log_user_comm_message(c->audit_fd, AUDIT_SYSTEM_RUNLEVEL, s, - "systemd-update-utmp", NULL, NULL, NULL, 1) < 0 && errno != EPERM) - q = log_error_errno(errno, "Failed to send audit message: %m"); - } -#endif - - r = utmp_put_runlevel(runlevel, previous); - if (r < 0 && !IN_SET(r, -ESRCH, -ENOENT)) - return log_error_errno(r, "Failed to write utmp record: %m"); - - return q; -} - static int run(int argc, char *argv[]) { static const Verb verbs[] = { { "reboot", 1, 1, 0, on_reboot }, { "shutdown", 1, 1, 0, on_shutdown }, - { "runlevel", 1, 1, 0, on_runlevel }, {} }; diff --git a/test/units/TEST-01-BASIC.sh b/test/units/TEST-01-BASIC.sh index bb3ff2f1e9e..780f37ee128 100755 --- a/test/units/TEST-01-BASIC.sh +++ b/test/units/TEST-01-BASIC.sh @@ -45,19 +45,4 @@ systemctl daemon-reload # of systemd-analyze blame. See issue #27187. systemd-analyze blame -# Test for 'systemd-update-utmp runlevel' vs 'systemctl daemon-reexec'. -# See issue #27163. -# shellcheck disable=SC2034 -if [[ -x /usr/lib/systemd/systemd-update-utmp ]]; then - for _ in {0..10}; do - systemctl daemon-reexec & - pid_reexec=$! - # shellcheck disable=SC2034 - for _ in {0..10}; do - SYSTEMD_LOG_LEVEL=debug /usr/lib/systemd/systemd-update-utmp runlevel - done - wait "$pid_reexec" - done -fi - touch /testok diff --git a/units/meson.build b/units/meson.build index bc67a6ee8ab..34b3222f114 100644 --- a/units/meson.build +++ b/units/meson.build @@ -818,11 +818,6 @@ units = [ 'file' : 'systemd-update-done.service.in', 'symlinks' : ['sysinit.target.wants/'], }, - { - 'file' : 'systemd-update-utmp-runlevel.service.in', - 'conditions' : ['ENABLE_UTMP', 'HAVE_SYSV_COMPAT'], - 'symlinks' : ['multi-user.target.wants/', 'graphical.target.wants/', 'rescue.target.wants/'], - }, { 'file' : 'systemd-update-utmp.service.in', 'conditions' : ['ENABLE_UTMP'], diff --git a/units/systemd-update-utmp-runlevel.service.in b/units/systemd-update-utmp-runlevel.service.in deleted file mode 100644 index 17772d4576c..00000000000 --- a/units/systemd-update-utmp-runlevel.service.in +++ /dev/null @@ -1,25 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# -# This file is part of systemd. -# -# systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. - -[Unit] -Description=Record Runlevel Change in UTMP -Documentation=man:systemd-update-utmp-runlevel.service(8) man:utmp(5) -ConditionPathExists=!/etc/initrd-release - -DefaultDependencies=no -RequiresMountsFor=/var/log/wtmp -Conflicts=shutdown.target -Requisite=systemd-update-utmp.service -After=systemd-update-utmp.service -After=runlevel1.target runlevel2.target runlevel3.target runlevel4.target runlevel5.target -Before=shutdown.target - -[Service] -Type=oneshot -ExecStart={{LIBEXECDIR}}/systemd-update-utmp runlevel