diff --git a/src/shared/initrd-cpio.c b/src/shared/initrd-cpio.c index 30e434e5d94..f4bf913e03b 100644 --- a/src/shared/initrd-cpio.c +++ b/src/shared/initrd-cpio.c @@ -9,6 +9,7 @@ #include "fs-util.h" #include "initrd-cpio.h" #include "io-util.h" +#include "iovec-util.h" #include "log.h" #include "machine-credential.h" #include "memory-util.h" @@ -117,13 +118,11 @@ static void append_cpio_trailer(FILE *f) { fwrite(trailer, 1, sizeof trailer, f); } -int initrd_cpio_credentials_to_tempfile( +int initrd_cpio_credentials_to_memory( const MachineCredentialContext *creds, - char **ret_path) { + struct iovec *ret) { _cleanup_(memstream_done) MemStream m = {}; - _cleanup_(unlink_and_freep) char *path = NULL; - _cleanup_close_ int fd = -EBADF; _cleanup_(erase_and_freep) char *buf = NULL; /* holds plaintext credential bytes; scrub on free */ size_t buf_size = 0; uint32_t inode = 1; @@ -131,12 +130,7 @@ int initrd_cpio_credentials_to_tempfile( int r; assert(creds); - assert(ret_path); - - if (creds->n_credentials == 0) { - *ret_path = NULL; - return 0; - } + assert(ret); f = memstream_init(&m); if (!f) @@ -168,6 +162,31 @@ int initrd_cpio_credentials_to_tempfile( if (r < 0) return log_error_errno(r, "Failed to finalize credentials cpio: %m"); + *ret = IOVEC_MAKE(TAKE_PTR(buf), buf_size); + return 0; +} + +int initrd_cpio_credentials_to_tempfile( + const MachineCredentialContext *creds, + char **ret_path) { + + _cleanup_(unlink_and_freep) char *path = NULL; + _cleanup_close_ int fd = -EBADF; + _cleanup_(iovec_done_erase) struct iovec cpio = {}; /* holds plaintext credential bytes; scrub on free */ + int r; + + assert(creds); + assert(ret_path); + + if (creds->n_credentials == 0) { + *ret_path = NULL; + return 0; + } + + r = initrd_cpio_credentials_to_memory(creds, &cpio); + if (r < 0) + return r; + r = tempfn_random_child(NULL, "credentials-cpio", &path); if (r < 0) return log_error_errno(r, "Failed to generate temp file name: %m"); @@ -176,7 +195,7 @@ int initrd_cpio_credentials_to_tempfile( if (fd < 0) return log_error_errno(fd, "Failed to create temp file %s: %m", path); - r = loop_write(fd, buf, buf_size); + r = loop_write(fd, cpio.iov_base, cpio.iov_len); if (r < 0) return log_error_errno(r, "Failed to write credentials cpio: %m"); diff --git a/src/shared/initrd-cpio.h b/src/shared/initrd-cpio.h index 33dc298e44b..64e46f0a440 100644 --- a/src/shared/initrd-cpio.h +++ b/src/shared/initrd-cpio.h @@ -12,3 +12,8 @@ int initrd_cpio_credentials_to_tempfile( const MachineCredentialContext *creds, char **ret_path); + +/* Same, but returns the archive in memory. An archive is built even if there are no credentials. */ +int initrd_cpio_credentials_to_memory( + const MachineCredentialContext *creds, + struct iovec *ret); diff --git a/src/test/test-initrd-cpio.c b/src/test/test-initrd-cpio.c index e69884701e2..2f2f05dea1b 100644 --- a/src/test/test-initrd-cpio.c +++ b/src/test/test-initrd-cpio.c @@ -9,12 +9,34 @@ #include "fileio.h" #include "fs-util.h" #include "initrd-cpio.h" +#include "iovec-util.h" #include "machine-credential.h" #include "path-util.h" #include "rm-rf.h" #include "tests.h" #include "tmpfile-util.h" +TEST(initrd_cpio_credentials_to_memory) { + _cleanup_(machine_credential_context_done) MachineCredentialContext creds = {}; + _cleanup_(iovec_done) struct iovec empty = {}, archive = {}; + + /* Without credentials the archive still carries the directories and the trailer */ + ASSERT_OK(initrd_cpio_credentials_to_memory(&creds, &empty)); + ASSERT_NOT_NULL(empty.iov_base); + ASSERT_GT(empty.iov_len, 0U); + ASSERT_EQ(empty.iov_len % 4, 0U); + ASSERT_NOT_NULL(memmem(empty.iov_base, empty.iov_len, "TRAILER!!!", STRLEN("TRAILER!!!"))); + ASSERT_NOT_NULL(memmem(empty.iov_base, empty.iov_len, ".extra/system_credentials", STRLEN(".extra/system_credentials"))); + + ASSERT_OK(machine_credential_add(&creds, "foo", "hello", 5)); + ASSERT_OK(initrd_cpio_credentials_to_memory(&creds, &archive)); + ASSERT_NOT_NULL(archive.iov_base); + ASSERT_GT(archive.iov_len, empty.iov_len); + ASSERT_NOT_NULL(memmem(archive.iov_base, archive.iov_len, ".extra/system_credentials/foo.cred", STRLEN(".extra/system_credentials/foo.cred"))); + ASSERT_NOT_NULL(memmem(archive.iov_base, archive.iov_len, "hello", STRLEN("hello"))); + ASSERT_NULL(memmem(empty.iov_base, empty.iov_len, "foo.cred", STRLEN("foo.cred"))); +} + TEST_RET(initrd_cpio_credentials_basic) { struct stat st; size_t foo_size, bar_size;