From 5933eb1a712ea533261811a4f9448a207672565a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 23 Jun 2025 14:37:58 +0200 Subject: [PATCH 1/2] homed: set "secrets" section to 'sensitive' in more places We already do this in all placed where we it *really* matters, i.e. for passwords PINs. But let's do this also at any place where we add the section at all, regardless whether it is for storing a pw or something else. With this we establish the rule that if it's in "secrets", then it shall be marked "sensitive". --- src/home/homectl-pkcs11.c | 2 ++ src/home/homectl-recovery-key.c | 2 ++ src/home/homed-home.c | 2 ++ src/home/user-record-util.c | 10 ++++++++-- 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/home/homectl-pkcs11.c b/src/home/homectl-pkcs11.c index 12037a667d..38541c51ce 100644 --- a/src/home/homectl-pkcs11.c +++ b/src/home/homectl-pkcs11.c @@ -50,6 +50,8 @@ int identity_add_token_pin(sd_json_variant **v, const char *pin) { if (r < 0) return log_error_errno(r, "Failed to update PIN field: %m"); + sd_json_variant_sensitive(w); + r = sd_json_variant_set_field(v, "secret", w); if (r < 0) return log_error_errno(r, "Failed to update secret object: %m"); diff --git a/src/home/homectl-recovery-key.c b/src/home/homectl-recovery-key.c index ad1850d056..c8d6a9b2fa 100644 --- a/src/home/homectl-recovery-key.c +++ b/src/home/homectl-recovery-key.c @@ -94,6 +94,8 @@ static int add_secret(sd_json_variant **v, const char *password) { if (r < 0) return log_error_errno(r, "Failed to update password field: %m"); + sd_json_variant_sensitive(w); + r = sd_json_variant_set_field(v, "secret", w); if (r < 0) return log_error_errno(r, "Failed to update secret object: %m"); diff --git a/src/home/homed-home.c b/src/home/homed-home.c index be6a7bf515..4b5aed46bf 100644 --- a/src/home/homed-home.c +++ b/src/home/homed-home.c @@ -1256,6 +1256,8 @@ static int home_start_work( if (!sub) return -ENOKEY; + sd_json_variant_sensitive(sub); + r = sd_json_variant_set_field(&v, "secret", sub); if (r < 0) return r; diff --git a/src/home/user-record-util.c b/src/home/user-record-util.c index fdc99e1c4f..3cc100ac94 100644 --- a/src/home/user-record-util.c +++ b/src/home/user-record-util.c @@ -1022,8 +1022,11 @@ int user_record_set_fido2_user_presence_permitted(UserRecord *h, int b) { if (sd_json_variant_is_blank_object(w)) r = sd_json_variant_filter(&h->json, STRV_MAKE("secret")); - else + else { + sd_json_variant_sensitive(w); + r = sd_json_variant_set_field(&h->json, "secret", w); + } if (r < 0) return r; @@ -1050,8 +1053,11 @@ int user_record_set_fido2_user_verification_permitted(UserRecord *h, int b) { if (sd_json_variant_is_blank_object(w)) r = sd_json_variant_filter(&h->json, STRV_MAKE("secret")); - else + else { + sd_json_variant_sensitive(w); + r = sd_json_variant_set_field(&h->json, "secret", w); + } if (r < 0) return r; From e3d0fa5ac4397263a039f85cb39c3b72715ba798 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 23 Jun 2025 14:40:25 +0200 Subject: [PATCH 2/2] userdb: when loading a user record from JSON, mark 'secret' section in JSON variant as sensitive as side effect When we load a user record we retain a reference to the original JSON. Thus the loaded objects might live at least as long as our user record object, hence we better make sure we set the 'sensitive' flag for the 'secret' section if it's not marked like that yet. This is paranoia only: we already should be setting this flag properly earlier, when acquiring the json variant in the first place. But it's better to be safe than sorry. --- src/shared/user-record.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/shared/user-record.c b/src/shared/user-record.c index 20f5d92246..09e96f0c9a 100644 --- a/src/shared/user-record.c +++ b/src/shared/user-record.c @@ -1531,6 +1531,11 @@ int user_group_record_mangle( if (USER_RECORD_STRIP_MASK(load_flags) == _USER_RECORD_MASK_MAX) /* strip everything? */ return json_log(v, json_flags, SYNTHETIC_ERRNO(EINVAL), "Stripping everything from record, refusing."); + /* Extra safety: mark the "secret" part (that contains literal passwords and such) as sensitive, so + * that it is not included in debug output and erased from memory when we are done. We do this for + * any record that passes through here. */ + sd_json_variant_sensitive(sd_json_variant_by_key(v, "secret")); + /* Check if we have the special sections and if they match our flags set */ FOREACH_ELEMENT(i, mask_field) { sd_json_variant *e, *k;