parent
d4eefd8ce9
commit
1b68697036
@ -0,0 +1,130 @@
|
||||
From 0117502d70f42dbc88674200ea6594d1d5454d9c Mon Sep 17 00:00:00 2001
|
||||
From: HATAYAMA Daisuke <d.hatayama@fujitsu.com>
|
||||
Date: Sun, 12 Feb 2023 12:15:08 +0000
|
||||
Subject: [PATCH] sulogin: fix control lost of the current terminal when
|
||||
default.target is rescue.target
|
||||
|
||||
When default.target is rescue.target, exiting from the single-user shell
|
||||
results in lost of the control of the current terminal. This is because the
|
||||
operation performed to continue to boot is systemctl default but default.target
|
||||
is now rescue.target and it is already active. Hence, no new process that
|
||||
controls the current terminal is created. Users need to make hardware reset to
|
||||
recover the situation.
|
||||
|
||||
This sounds like a bit corner case issue and some might feel configuring
|
||||
default.target as rescue.target is odd because there are several other ways to
|
||||
transition to rescue.mode without configuring default.target to rescue.target
|
||||
such as systemctl rescue or systemd.unit=rescue.target something like
|
||||
that. However, users unfamiliar with systemd operations tend to come up with
|
||||
systemctl set-default rescue.target.
|
||||
|
||||
To fix this issue, let's transition to default.target only when default.target
|
||||
is inactive. Otherwise, invoke the single-user shell again to keep control of
|
||||
the current terminal for users.
|
||||
|
||||
This new logic depends on whether D-Bus working well. Exiting without any check
|
||||
of result of systemctl default could lead to again the control lost of the
|
||||
current terminal. Hence, add checking results of each D-Bus operations
|
||||
including systemctl default and invoke the single-user shell if they fail.
|
||||
|
||||
(cherry picked from commit 937ca8330d11e406b8ef343bead6f4f6244e39c7)
|
||||
|
||||
Resolves: #2227769
|
||||
---
|
||||
src/sulogin-shell/sulogin-shell.c | 60 +++++++++++++++++++++++++------
|
||||
1 file changed, 50 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/src/sulogin-shell/sulogin-shell.c b/src/sulogin-shell/sulogin-shell.c
|
||||
index a1ea2333de..8f14ee11bb 100644
|
||||
--- a/src/sulogin-shell/sulogin-shell.c
|
||||
+++ b/src/sulogin-shell/sulogin-shell.c
|
||||
@@ -14,6 +14,8 @@
|
||||
#include "process-util.h"
|
||||
#include "sd-bus.h"
|
||||
#include "signal-util.h"
|
||||
+#include "special.h"
|
||||
+#include "unit-def.h"
|
||||
|
||||
static int reload_manager(sd_bus *bus) {
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
@@ -43,6 +45,28 @@ static int reload_manager(sd_bus *bus) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int default_target_is_inactive(sd_bus *bus) {
|
||||
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
+ _cleanup_free_ char *path = NULL, *state = NULL;
|
||||
+ int r;
|
||||
+
|
||||
+ path = unit_dbus_path_from_name(SPECIAL_DEFAULT_TARGET);
|
||||
+ if (!path)
|
||||
+ return log_oom();
|
||||
+
|
||||
+ r = sd_bus_get_property_string(bus,
|
||||
+ "org.freedesktop.systemd1",
|
||||
+ path,
|
||||
+ "org.freedesktop.systemd1.Unit",
|
||||
+ "ActiveState",
|
||||
+ &error,
|
||||
+ &state);
|
||||
+ if (r < 0)
|
||||
+ return log_error_errno(r, "Failed to retrieve unit state: %s", bus_error_message(&error, r));
|
||||
+
|
||||
+ return streq_ptr(state, "inactive");
|
||||
+}
|
||||
+
|
||||
static int start_default_target(sd_bus *bus) {
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
int r;
|
||||
@@ -95,7 +119,6 @@ int main(int argc, char *argv[]) {
|
||||
NULL, /* --force */
|
||||
NULL
|
||||
};
|
||||
- _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
||||
int r;
|
||||
|
||||
log_set_target(LOG_TARGET_AUTO);
|
||||
@@ -108,17 +131,34 @@ int main(int argc, char *argv[]) {
|
||||
/* allows passwordless logins if root account is locked. */
|
||||
sulogin_cmdline[1] = "--force";
|
||||
|
||||
- (void) fork_wait(sulogin_cmdline);
|
||||
+ for (;;) {
|
||||
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
||||
+
|
||||
+ (void) fork_wait(sulogin_cmdline);
|
||||
+
|
||||
+ r = bus_connect_system_systemd(&bus);
|
||||
+ if (r < 0) {
|
||||
+ log_warning_errno(r, "Failed to get D-Bus connection: %m");
|
||||
+ goto fallback;
|
||||
+ }
|
||||
|
||||
- r = bus_connect_system_systemd(&bus);
|
||||
- if (r < 0) {
|
||||
- log_warning_errno(r, "Failed to get D-Bus connection: %m");
|
||||
- r = 0;
|
||||
- } else {
|
||||
- (void) reload_manager(bus);
|
||||
+ if (reload_manager(bus) < 0)
|
||||
+ goto fallback;
|
||||
|
||||
- r = start_default_target(bus);
|
||||
+ r = default_target_is_inactive(bus);
|
||||
+ if (r < 0)
|
||||
+ goto fallback;
|
||||
+ if (!r) {
|
||||
+ log_warning(SPECIAL_DEFAULT_TARGET" is not inactive. Please review the "SPECIAL_DEFAULT_TARGET" setting.\n");
|
||||
+ goto fallback;
|
||||
+ }
|
||||
+
|
||||
+ if (start_default_target(bus) >= 0)
|
||||
+ break;
|
||||
+
|
||||
+ fallback:
|
||||
+ log_warning("Fallback to the single-user shell.\n");
|
||||
}
|
||||
|
||||
- return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
+ return 0;
|
||||
}
|
Loading…
Reference in new issue