From c7f7d87db54d8537c54d259a369304ff9a352dd4 Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Fri, 21 Mar 2025 10:36:14 +0100 Subject: [PATCH 1/3] terminal-util: Make sure resolve_dev_console() always returns a full path Currently it returns a full path in some cases and a partial path in others. Let's make sure it always returns a full path. --- src/basic/terminal-util.c | 12 ++++++------ src/core/execute.c | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c index 50ad4c89af..498e2d532b 100644 --- a/src/basic/terminal-util.c +++ b/src/basic/terminal-util.c @@ -1156,10 +1156,12 @@ int resolve_dev_console(char **ret) { tty = active; } - if (tty != active) - return strdup_to(ret, tty); + _cleanup_free_ char *path = NULL; + path = path_join("/dev", tty); + if (!path) + return -ENOMEM; - *ret = TAKE_PTR(active); + *ret = TAKE_PTR(path); return 0; } @@ -1231,9 +1233,7 @@ bool tty_is_vc_resolve(const char *tty) { assert(tty); - tty = skip_dev_prefix(tty); - - if (streq(tty, "console")) { + if (streq(skip_dev_prefix(tty), "console")) { if (resolve_dev_console(&resolved) < 0) return false; diff --git a/src/core/execute.c b/src/core/execute.c index 3bc80cd643..93fce15d0d 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -970,7 +970,7 @@ static bool tty_may_match_dev_console(const char *tty) { return true; /* if we could not resolve, assume it may */ /* "tty0" means the active VC, so it may be the same sometimes */ - return path_equal(resolved, tty) || (streq(resolved, "tty0") && tty_is_vc(tty)); + return path_equal(skip_dev_prefix(resolved), tty) || (streq(skip_dev_prefix(resolved), "tty0") && tty_is_vc(tty)); } static bool exec_context_may_touch_tty(const ExecContext *ec) { From 6f1d594d637fe47480aa001ee62d20306af8f38e Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Fri, 21 Mar 2025 10:39:46 +0100 Subject: [PATCH 2/3] core: Resolve /dev/console if it's connected to stdin If /dev/console is connected to stdin there's a possibility that the unit might try to start a logind session from within the unit. Let's make sure that any such sessions are started on the tty that /dev/console points to and not on /dev/console itself. --- src/core/exec-invoke.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/core/exec-invoke.c b/src/core/exec-invoke.c index d9878e6088..0a29da522e 100644 --- a/src/core/exec-invoke.c +++ b/src/core/exec-invoke.c @@ -369,10 +369,21 @@ static int setup_input( case EXEC_INPUT_TTY_FORCE: case EXEC_INPUT_TTY_FAIL: { _cleanup_close_ int tty_fd = -EBADF; + _cleanup_free_ char *resolved = NULL; const char *tty_path; tty_path = ASSERT_PTR(exec_context_tty_path(context)); + if (tty_is_console(tty_path)) { + r = resolve_dev_console(&resolved); + if (r < 0) + log_debug_errno(r, "Failed to resolve /dev/console, ignoring: %m"); + else { + log_debug("Resolved /dev/console to %s", resolved); + tty_path = resolved; + } + } + tty_fd = acquire_terminal(tty_path, i == EXEC_INPUT_TTY_FAIL ? ACQUIRE_TERMINAL_TRY : i == EXEC_INPUT_TTY_FORCE ? ACQUIRE_TERMINAL_FORCE : From 2b0087e5b171e2292c07bacef8908bf4d5339a4b Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Thu, 3 Apr 2025 16:25:15 +0200 Subject: [PATCH 3/3] exec-invoke: Always go via stdin fd in setup_pam() to get tty We might have resolved the tty to something else if it was set to /dev/console, so let's always go via stdin in setup_pam(). This also means we won't set the pam tty if only stdout or stderr are connected to a tty, which seems like a sensible thing to do. --- src/core/exec-invoke.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/core/exec-invoke.c b/src/core/exec-invoke.c index 0a29da522e..ef501607b6 100644 --- a/src/core/exec-invoke.c +++ b/src/core/exec-invoke.c @@ -1201,6 +1201,7 @@ static int setup_pam( _cleanup_(barrier_destroy) Barrier barrier = BARRIER_NULL; _cleanup_strv_free_ char **e = NULL; + _cleanup_free_ char *tty = NULL; pam_handle_t *handle = NULL; sigset_t old_ss; int pam_code = PAM_SUCCESS, r; @@ -1236,15 +1237,14 @@ static int setup_pam( goto fail; } - const char *tty = context->tty_path; - if (!tty) { - _cleanup_free_ char *q = NULL; + if (getttyname_malloc(STDIN_FILENO, &tty) >= 0) { + _cleanup_free_ char *q = path_join("/dev", tty); + if (!q) { + r = -ENOMEM; + goto fail; + } - /* Hmm, so no TTY was explicitly passed, but an fd passed to us directly might be a TTY. Let's figure - * out if that's the case, and read the TTY off it. */ - - if (getttyname_malloc(STDIN_FILENO, &q) >= 0) - tty = strjoina("/dev/", q); + free_and_replace(tty, q); } if (tty) {