From: Lennart Poettering Date: Thu, 7 Nov 2024 10:38:23 +0000 (+0100) Subject: ask-password-api: add new "hup_fd" field to AskPasswordReq X-Git-Tag: v258-rc1~1751^2~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d66894a7a53f0eb26228074ef1b8dcca2a316f87;p=thirdparty%2Fsystemd.git ask-password-api: add new "hup_fd" field to AskPasswordReq This new field allows specification of an fd on which the password prompt logic will look for POLLHUP events for, and if seen will abort the query. The usecase for this is that when we query for a pw on behalf of a Varlink client we can abort the query automatically if the client dies. --- diff --git a/src/ask-password/ask-password.c b/src/ask-password/ask-password.c index d3afc377813..154aaa030e8 100644 --- a/src/ask-password/ask-password.c +++ b/src/ask-password/ask-password.c @@ -259,6 +259,7 @@ static int run(int argc, char *argv[]) { .keyring = arg_key_name, .credential = arg_credential_name ?: "password", .until = timeout, + .hup_fd = -EBADF, }; r = ask_password_auto(&req, arg_flags, &l); diff --git a/src/bootctl/bootctl-install.c b/src/bootctl/bootctl-install.c index 76deba56e7b..884521bcfa9 100644 --- a/src/bootctl/bootctl-install.c +++ b/src/bootctl/bootctl-install.c @@ -989,6 +989,7 @@ int verb_install(int argc, char *argv[], void *userdata) { .keyring = arg_private_key, .credential = "bootctl.private-key-pin", .until = USEC_INFINITY, + .hup_fd = -EBADF, }, &private_key, &ui); diff --git a/src/cryptenroll/cryptenroll-password.c b/src/cryptenroll/cryptenroll-password.c index 56a3bb44566..c6888cc83b1 100644 --- a/src/cryptenroll/cryptenroll-password.c +++ b/src/cryptenroll/cryptenroll-password.c @@ -62,6 +62,7 @@ int load_volume_key_password( .keyring = "cryptenroll", .credential = "cryptenroll.passphrase", .until = USEC_INFINITY, + .hup_fd = -EBADF, }; for (;;) { @@ -138,6 +139,7 @@ int enroll_password( .keyring = "cryptenroll", .credential = "cryptenroll.new-passphrase", .until = USEC_INFINITY, + .hup_fd = -EBADF, }; for (;;) { diff --git a/src/cryptenroll/cryptenroll-tpm2.c b/src/cryptenroll/cryptenroll-tpm2.c index 42d5a9cd036..fd03fecc629 100644 --- a/src/cryptenroll/cryptenroll-tpm2.c +++ b/src/cryptenroll/cryptenroll-tpm2.c @@ -125,6 +125,7 @@ static int get_pin(char **ret_pin_str, TPM2Flags *ret_flags) { .keyring = "tpm2-pin", .credential = "cryptenroll.new-tpm2-pin", .until = USEC_INFINITY, + .hup_fd = -EBADF, }; pin = strv_free_erase(pin); diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index cb3b591186a..e5f21bbce77 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -913,6 +913,7 @@ static int get_password( .keyring = "cryptsetup", .credential = "cryptsetup.passphrase", .until = until, + .hup_fd = -EBADF, }; if (ignore_cached) @@ -1430,6 +1431,7 @@ static int crypt_activate_by_token_pin_ask_password( .keyring = keyring, .credential = credential, .until = until, + .hup_fd = -EBADF, }; r = ask_password_auto(&req, flags, &pins); diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c index 5658255358c..15abb53be84 100644 --- a/src/firstboot/firstboot.c +++ b/src/firstboot/firstboot.c @@ -738,6 +738,7 @@ static int prompt_root_password(int rfd) { .tty_fd = -EBADF, .message = msg1, .until = USEC_INFINITY, + .hup_fd = -EBADF, }; r = ask_password_tty(&req, /* flags= */ 0, &a); diff --git a/src/home/homectl.c b/src/home/homectl.c index 611fb966fe6..104c35454b5 100644 --- a/src/home/homectl.c +++ b/src/home/homectl.c @@ -269,6 +269,7 @@ static int acquire_existing_password( .keyring = "home-password", .credential = "home.password", .until = USEC_INFINITY, + .hup_fd = -EBADF, }; r = ask_password_auto(&req, flags, &password); @@ -329,6 +330,7 @@ static int acquire_recovery_key( .keyring = "home-recovery-key", .credential = "home.recovery-key", .until = USEC_INFINITY, + .hup_fd = -EBADF, }; r = ask_password_auto(&req, flags, &recovery_key); @@ -385,6 +387,7 @@ static int acquire_token_pin( .keyring = "token-pin", .credential = "home.token-pin", .until = USEC_INFINITY, + .hup_fd = -EBADF, }; r = ask_password_auto(&req, flags, &pin); @@ -1241,6 +1244,7 @@ static int acquire_new_password( .keyring = "home-password", .credential = "home.new-password", .until = USEC_INFINITY, + .hup_fd = -EBADF, }; r = ask_password_auto( diff --git a/src/keyutil/keyutil.c b/src/keyutil/keyutil.c index bae74215728..23459e48f59 100644 --- a/src/keyutil/keyutil.c +++ b/src/keyutil/keyutil.c @@ -187,6 +187,7 @@ static int verb_validate(int argc, char *argv[], void *userdata) { .keyring = arg_private_key, .credential = "keyutil.private-key-pin", .until = USEC_INFINITY, + .hup_fd = -EBADF, }, &private_key, &ui); @@ -245,6 +246,7 @@ static int verb_public(int argc, char *argv[], void *userdata) { .keyring = arg_private_key, .credential = "keyutil.private-key-pin", .until = USEC_INFINITY, + .hup_fd = -EBADF, }, &private_key, &ui); diff --git a/src/measure/measure.c b/src/measure/measure.c index fbd039da791..18461797b7e 100644 --- a/src/measure/measure.c +++ b/src/measure/measure.c @@ -893,6 +893,7 @@ static int verb_sign(int argc, char *argv[], void *userdata) { .keyring = arg_private_key, .credential = "measure.private-key-pin", .until = USEC_INFINITY, + .hup_fd = -EBADF, }, &privkey, &ui); diff --git a/src/pcrlock/pcrlock.c b/src/pcrlock/pcrlock.c index b22ee57788e..72b13f8fac4 100644 --- a/src/pcrlock/pcrlock.c +++ b/src/pcrlock/pcrlock.c @@ -4556,6 +4556,7 @@ static int make_policy(bool force, RecoveryPinMode recovery_pin_mode) { .id = "pcrlock-recovery-pin", .credential = "pcrlock.recovery-pin", .until = USEC_INFINITY, + .hup_fd = -EBADF, }; r = ask_password_auto( diff --git a/src/repart/repart.c b/src/repart/repart.c index b381d4808ac..7934a974355 100644 --- a/src/repart/repart.c +++ b/src/repart/repart.c @@ -8577,6 +8577,7 @@ static int parse_argv(int argc, char *argv[], X509 **ret_certificate, EVP_PKEY * .keyring = arg_private_key, .credential = "repart.private-key-pin", .until = USEC_INFINITY, + .hup_fd = -EBADF, }, &private_key, &ui); diff --git a/src/sbsign/sbsign.c b/src/sbsign/sbsign.c index 5c5c884c98d..92b82842198 100644 --- a/src/sbsign/sbsign.c +++ b/src/sbsign/sbsign.c @@ -208,6 +208,7 @@ static int verb_sign(int argc, char *argv[], void *userdata) { .keyring = arg_private_key, .credential = "sbsign.private-key-pin", .until = USEC_INFINITY, + .hup_fd = -EBADF, }, &private_key, &ui); diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c index 39e6277b376..502b22ee89e 100644 --- a/src/shared/ask-password-api.c +++ b/src/shared/ask-password-api.c @@ -355,15 +355,30 @@ int ask_password_plymouth( enum { POLL_SOCKET, - POLL_INOTIFY, /* Must be last, because optional */ + POLL_TWO, + POLL_THREE, _POLL_MAX, }; struct pollfd pollfd[_POLL_MAX] = { - [POLL_SOCKET] = { .fd = fd, .events = POLLIN }, - [POLL_INOTIFY] = { .fd = inotify_fd, .events = POLLIN }, + [POLL_SOCKET] = { + .fd = fd, + .events = POLLIN, + }, }; - size_t n_pollfd = inotify_fd >= 0 ? _POLL_MAX : _POLL_MAX-1; + size_t n_pollfd = POLL_SOCKET + 1, inotify_idx = SIZE_MAX, hup_fd_idx = SIZE_MAX; + if (inotify_fd >= 0) + pollfd[inotify_idx = n_pollfd++] = (struct pollfd) { + .fd = inotify_fd, + .events = POLLIN, + }; + if (req->hup_fd >= 0) + pollfd[hup_fd_idx = n_pollfd++] = (struct pollfd) { + .fd = req->hup_fd, + .events = POLLHUP, + }; + + assert(n_pollfd <= _POLL_MAX); for (;;) { usec_t timeout; @@ -384,7 +399,10 @@ int ask_password_plymouth( if (r == 0) return -ETIME; - if (inotify_fd >= 0 && pollfd[POLL_INOTIFY].revents != 0) + if (req->hup_fd >= 0 && pollfd[hup_fd_idx].revents & POLLHUP) + return -ECONNRESET; + + if (inotify_fd >= 0 && pollfd[inotify_idx].revents != 0) (void) flush_fd(inotify_fd); if (pollfd[POLL_SOCKET].revents == 0) @@ -567,15 +585,31 @@ int ask_password_tty( enum { POLL_TTY, - POLL_INOTIFY, /* Must be last, because optional */ + POLL_TWO, + POLL_THREE, _POLL_MAX, }; struct pollfd pollfd[_POLL_MAX] = { - [POLL_TTY] = { .fd = ttyfd >= 0 ? ttyfd : STDIN_FILENO, .events = POLLIN }, - [POLL_INOTIFY] = { .fd = inotify_fd, .events = POLLIN }, + [POLL_TTY] = { + .fd = ttyfd >= 0 ? ttyfd : STDIN_FILENO, + .events = POLLIN, + }, }; - size_t n_pollfd = inotify_fd >= 0 ? _POLL_MAX : _POLL_MAX-1; + size_t n_pollfd = POLL_TTY + 1, inotify_idx = SIZE_MAX, hup_fd_idx = SIZE_MAX; + + if (inotify_fd >= 0) + pollfd[inotify_idx = n_pollfd++] = (struct pollfd) { + .fd = inotify_fd, + .events = POLLIN, + }; + if (req->hup_fd >= 0) + pollfd[hup_fd_idx = n_pollfd++] = (struct pollfd) { + .fd = req->hup_fd, + .events = POLLHUP, + }; + + assert(n_pollfd <= _POLL_MAX); for (;;) { _cleanup_(erase_char) char c; @@ -603,7 +637,12 @@ int ask_password_tty( goto finish; } - if (inotify_fd >= 0 && pollfd[POLL_INOTIFY].revents != 0 && keyring) { + if (req->hup_fd >= 0 && pollfd[hup_fd_idx].revents & POLLHUP) { + r = -ECONNRESET; + goto finish; + } + + if (inotify_fd >= 0 && pollfd[inotify_idx].revents != 0 && keyring) { (void) flush_fd(inotify_fd); r = ask_password_keyring(req, flags, ret); @@ -924,16 +963,29 @@ int ask_password_agent( enum { POLL_SOCKET, POLL_SIGNAL, - POLL_INOTIFY, /* Must be last, because optional */ + POLL_THREE, + POLL_FOUR, _POLL_MAX }; struct pollfd pollfd[_POLL_MAX] = { [POLL_SOCKET] = { .fd = socket_fd, .events = POLLIN }, [POLL_SIGNAL] = { .fd = signal_fd, .events = POLLIN }, - [POLL_INOTIFY] = { .fd = inotify_fd, .events = POLLIN }, }; - size_t n_pollfd = inotify_fd >= 0 ? _POLL_MAX : _POLL_MAX - 1; + size_t n_pollfd = POLL_SIGNAL + 1, inotify_idx = SIZE_MAX, hup_fd_idx = SIZE_MAX; + + if (inotify_fd >= 0) + pollfd[inotify_idx = n_pollfd++] = (struct pollfd) { + .fd = inotify_fd, + .events = POLLIN, + }; + if (req->hup_fd >= 0) + pollfd[hup_fd_idx = n_pollfd ++] = (struct pollfd) { + .fd = req->hup_fd, + .events = POLLHUP, + }; + + assert(n_pollfd <= _POLL_MAX); for (;;) { CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred))) control; @@ -963,7 +1015,10 @@ int ask_password_agent( goto finish; } - if (inotify_fd >= 0 && pollfd[POLL_INOTIFY].revents != 0) { + if (req->hup_fd >= 0 && pollfd[hup_fd_idx].revents & POLLHUP) + return -ECONNRESET; + + if (inotify_fd >= 0 && pollfd[inotify_idx].revents != 0) { (void) flush_fd(inotify_fd); if (req && req->keyring) { diff --git a/src/shared/ask-password-api.h b/src/shared/ask-password-api.h index fe453522fca..03c6d1abdbb 100644 --- a/src/shared/ask-password-api.h +++ b/src/shared/ask-password-api.h @@ -28,6 +28,7 @@ typedef struct AskPasswordRequest { const char *credential; /* $CREDENTIALS_DIRECTORY credential name */ const char *flag_file; /* Once this flag file disappears abort the query */ int tty_fd; /* If querying on a TTY, the TTY to query on (or -EBADF) */ + int hup_fd; /* An extra fd to watch for POLLHUP, in which case to abort the query */ usec_t until; /* CLOCK_MONOTONIC time until which to show the prompt (if zero: forever) */ } AskPasswordRequest; diff --git a/src/shared/cryptsetup-fido2.c b/src/shared/cryptsetup-fido2.c index 070908d5257..8d4c1791837 100644 --- a/src/shared/cryptsetup-fido2.c +++ b/src/shared/cryptsetup-fido2.c @@ -118,6 +118,7 @@ int acquire_fido2_key( .keyring = "fido2-pin", .credential = "cryptsetup.fido2-pin", .until = until, + .hup_fd = -EBADF, }; pins = strv_free_erase(pins); diff --git a/src/shared/cryptsetup-tpm2.c b/src/shared/cryptsetup-tpm2.c index 7a1275eb381..c1cd67bacd7 100644 --- a/src/shared/cryptsetup-tpm2.c +++ b/src/shared/cryptsetup-tpm2.c @@ -41,6 +41,7 @@ static int get_pin( .keyring = "tpm2-pin", .credential = askpw_credential, .until = until, + .hup_fd = -EBADF, }; pin = strv_free_erase(pin); diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 3feda770af9..86a549477c3 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -3083,6 +3083,7 @@ int dissected_image_decrypt_interactively( .keyring = "dissect", .credential = "dissect.passphrase", .until = USEC_INFINITY, + .hup_fd = -EBADF, }; r = ask_password_auto(&req, /* flags= */ 0, &z); diff --git a/src/shared/libfido2-util.c b/src/shared/libfido2-util.c index 200068dce44..101641e7fe4 100644 --- a/src/shared/libfido2-util.c +++ b/src/shared/libfido2-util.c @@ -863,6 +863,7 @@ int fido2_generate_hmac_hash( .keyring = "fido2-pin", .credential = askpw_credential, .until = USEC_INFINITY, + .hup_fd = -EBADF, }; r = ask_password_auto(&req, /* flags= */ 0, &pin); diff --git a/src/shared/pkcs11-util.c b/src/shared/pkcs11-util.c index 8d14b2f8f7e..a38a91279d7 100644 --- a/src/shared/pkcs11-util.c +++ b/src/shared/pkcs11-util.c @@ -387,6 +387,7 @@ int pkcs11_token_login( .keyring = askpw_keyring, .credential = askpw_credential, .until = until, + .hup_fd = -EBADF, }; /* We never cache PINs, simply because it's fatal if we use wrong PINs, since usually there are only 3 tries */ diff --git a/src/test/test-ask-password-api.c b/src/test/test-ask-password-api.c index 38afe0c6efc..d79c4764896 100644 --- a/src/test/test-ask-password-api.c +++ b/src/test/test-ask-password-api.c @@ -13,6 +13,7 @@ TEST(ask_password) { .message = "hello?", .keyring = "da key", .until = USEC_INFINITY, + .hup_fd = -EBADF, }; r = ask_password_tty(&req, /* flags= */ ASK_PASSWORD_CONSOLE_COLOR, &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 31292d5acf5..094810dcb39 100644 --- a/src/tty-ask-password-agent/tty-ask-password-agent.c +++ b/src/tty-ask-password-agent/tty-ask-password-agent.c @@ -152,6 +152,7 @@ static int agent_ask_password_tty( .message = message, .flag_file = flag_file, .until = until, + .hup_fd = -EBADF, }; r = ask_password_tty(&req, flags, ret); @@ -260,6 +261,7 @@ static int process_one_password_file(const char *filename, FILE *f) { .message = message, .flag_file = filename, .until = not_after, + .hup_fd = -EBADF, }; r = ask_password_plymouth(&req, flags, &passwords);