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 44b94effd93..baf41923517 100644 --- a/src/pcrlock/pcrlock.c +++ b/src/pcrlock/pcrlock.c @@ -4555,6 +4555,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 355c51b5bc5..4976bf30fa5 100644 --- a/src/shared/ask-password-api.h +++ b/src/shared/ask-password-api.h @@ -29,6 +29,7 @@ typedef struct AskPasswordRequest { 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) */ usec_t until; /* CLOCK_MONOTONIC time until which to show the prompt */ + int hup_fd; /* An extra fd to watch for POLLHUP, in which case to abort the query */ } AskPasswordRequest; int ask_password_tty(const AskPasswordRequest *req, AskPasswordFlags flags, char ***ret); 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);