From 3de13e6148731ae9c36885afd78b1421e6f16305 Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Wed, 31 Jul 2024 15:02:07 +0200 Subject: [PATCH] exec-credential: Skip duplicate credentials in load_credential_glob() We document that when multiple credentials of the same name are found, we use the first one found so let's actually implement that behavior. --- src/core/exec-credential.c | 15 +++++++++++---- test/units/TEST-54-CREDS.sh | 5 ++++- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/core/exec-credential.c b/src/core/exec-credential.c index a70cf23eaaa..75eca830f80 100644 --- a/src/core/exec-credential.c +++ b/src/core/exec-credential.c @@ -417,6 +417,17 @@ static int load_credential_glob( _cleanup_(erase_and_freep) char *data = NULL; size_t size; + r = path_extract_filename(*p, &fn); + if (r < 0) + return log_debug_errno(r, "Failed to extract filename from '%s': %m", *p); + + if (faccessat(write_dfd, fn, F_OK, AT_SYMLINK_NOFOLLOW) >= 0) { + log_debug("Skipping credential with duplicated ID %s at %s", fn, *p); + continue; + } + if (errno != ENOENT) + return log_debug_errno(errno, "Failed to test if credential %s exists: %m", fn); + /* path is absolute, hence pass AT_FDCWD as nop dir fd here */ r = read_full_file_full( AT_FDCWD, @@ -429,10 +440,6 @@ static int load_credential_glob( if (r < 0) return log_debug_errno(r, "Failed to read credential '%s': %m", *p); - r = path_extract_filename(*p, &fn); - if (r < 0) - return log_debug_errno(r, "Failed to extract filename from '%s': %m", *p); - r = maybe_decrypt_and_write_credential( write_dfd, fn, diff --git a/test/units/TEST-54-CREDS.sh b/test/units/TEST-54-CREDS.sh index fe410d567e9..89d6dcdf034 100755 --- a/test/units/TEST-54-CREDS.sh +++ b/test/units/TEST-54-CREDS.sh @@ -273,8 +273,11 @@ rm -rf /tmp/ts54-creds # Check that globs work as expected mkdir -p /run/credstore echo -n a >/run/credstore/test.creds.first -echo -n b >/run/credstore/test.creds.second +# Make sure that when multiple credentials of the same name are found, the first one is used (/etc/credstore +# is searched before /run/credstore). +echo -n ignored >/run/credstore/test.creds.second mkdir -p /etc/credstore +echo -n b >/etc/credstore/test.creds.second echo -n c >/etc/credstore/test.creds.third systemd-run -p "ImportCredential=test.creds.*" \ --unit=test-54-ImportCredential.service \ -- 2.47.3