From ec572753c3ae3b51ed45369ec7d5f5f1fb9b93a4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 13 Sep 2024 13:54:36 +0200 Subject: [PATCH] tty-ask-password-agent: support for watching both system-wide and per-user askpw dir Fixes: #1232 #2217 --- src/shared/ask-password-api.c | 16 ++++++++++ src/shared/ask-password-api.h | 2 ++ .../tty-ask-password-agent.c | 31 ++++++++++++++----- 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c index 0bb6611c64..53d1f986b8 100644 --- a/src/shared/ask-password-api.c +++ b/src/shared/ask-password-api.c @@ -36,6 +36,7 @@ #include "missing_syscall.h" #include "mkdir-label.h" #include "nulstr-util.h" +#include "path-lookup.h" #include "plymouth-util.h" #include "process-util.h" #include "random-util.h" @@ -1021,3 +1022,18 @@ int ask_password_auto( return -EUNATCH; } + +int acquire_user_ask_password_directory(char **ret) { + int r; + + r = xdg_user_runtime_dir("systemd/ask-password", ret); + if (r == -ENXIO) { + if (ret) + *ret = NULL; + return 0; + } + if (r < 0) + return r; + + return 1; +} diff --git a/src/shared/ask-password-api.h b/src/shared/ask-password-api.h index e851d6d087..9b197230e9 100644 --- a/src/shared/ask-password-api.h +++ b/src/shared/ask-password-api.h @@ -31,3 +31,5 @@ int ask_password_tty(int tty_fd, const AskPasswordRequest *req, usec_t until, As int ask_password_plymouth(const AskPasswordRequest *req, usec_t until, AskPasswordFlags flags, const char *flag_file, char ***ret); int ask_password_agent(const AskPasswordRequest *req, usec_t until, AskPasswordFlags flag, char ***ret); int ask_password_auto(const AskPasswordRequest *req, usec_t until, AskPasswordFlags flag, char ***ret); + +int acquire_user_ask_password_directory(char **ret); diff --git a/src/tty-ask-password-agent/tty-ask-password-agent.c b/src/tty-ask-password-agent/tty-ask-password-agent.c index 1e4eb9b768..ce0a598d87 100644 --- a/src/tty-ask-password-agent/tty-ask-password-agent.c +++ b/src/tty-ask-password-agent/tty-ask-password-agent.c @@ -295,19 +295,21 @@ static int wall_tty_block(void) { return fd; } -static int process_password_files(void) { +static int process_password_files(const char *path) { _cleanup_closedir_ DIR *d = NULL; int ret = 0, r; - d = opendir("/run/systemd/ask-password"); + assert(path); + + d = opendir(path); if (!d) { if (errno == ENOENT) return 0; - return log_error_errno(errno, "Failed to open /run/systemd/ask-password: %m"); + return log_error_errno(errno, "Failed to open '%s': %m", path); } - FOREACH_DIRENT(de, d, return log_error_errno(errno, "Failed to read directory: %m")) { + FOREACH_DIRENT(de, d, return log_error_errno(errno, "Failed to read directory '%s': %m", path)) { _cleanup_free_ char *p = NULL; if (!IN_SET(de->d_type, DT_REG, DT_UNKNOWN)) @@ -316,7 +318,7 @@ static int process_password_files(void) { if (!startswith(de->d_name, "ask.")) continue; - p = path_join("/run/systemd/ask-password", de->d_name); + p = path_join(path, de->d_name); if (!p) return log_oom(); @@ -340,6 +342,7 @@ static int process_and_watch_password_files(bool watch) { _FD_MAX }; + _cleanup_free_ char *user_ask_password_directory = NULL; _unused_ _cleanup_close_ int tty_block_fd = -EBADF; _cleanup_close_ int notify = -EBADF, signal_fd = -EBADF; struct pollfd pollfd[_FD_MAX]; @@ -350,6 +353,12 @@ static int process_and_watch_password_files(bool watch) { (void) mkdir_p_label("/run/systemd/ask-password", 0755); + r = acquire_user_ask_password_directory(&user_ask_password_directory); + if (r < 0) + return log_error_errno(r, "Failed to determine per-user password directory: %m"); + if (r > 0) + (void) mkdir_p_label(user_ask_password_directory, 0755); + assert_se(sigemptyset(&mask) >= 0); assert_se(sigset_add_many(&mask, SIGTERM) >= 0); assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) >= 0); @@ -365,17 +374,25 @@ static int process_and_watch_password_files(bool watch) { if (notify < 0) return log_error_errno(errno, "Failed to allocate directory watch: %m"); - r = inotify_add_watch_and_warn(notify, "/run/systemd/ask-password", IN_CLOSE_WRITE|IN_MOVED_TO); + r = inotify_add_watch_and_warn(notify, "/run/systemd/ask-password", IN_CLOSE_WRITE|IN_MOVED_TO|IN_ONLYDIR); if (r < 0) return r; + if (user_ask_password_directory) { + r = inotify_add_watch_and_warn(notify, user_ask_password_directory, IN_CLOSE_WRITE|IN_MOVED_TO|IN_ONLYDIR); + if (r < 0) + return r; + } + pollfd[FD_INOTIFY] = (struct pollfd) { .fd = notify, .events = POLLIN }; } for (;;) { usec_t timeout = USEC_INFINITY; - r = process_password_files(); + r = process_password_files("/run/systemd/ask-password"); + if (user_ask_password_directory) + RET_GATHER(r, process_password_files(user_ask_password_directory)); if (r == -ECANCELED) /* Disable poll() timeout since at least one password has been skipped and therefore * one file remains and is unlikely to trigger any events. */ -- 2.25.1