]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
boot: introduce a common structure for cpio target dirs
authorLennart Poettering <lennart@amutable.com>
Wed, 25 Mar 2026 17:11:45 +0000 (18:11 +0100)
committerLennart Poettering <lennart@amutable.com>
Tue, 21 Apr 2026 06:30:26 +0000 (08:30 +0200)
There are only a few target dirs we place resources in when generating
on-the-fly initrd cpios. These dirs have very specific attributes.
Instead of repeating this everywhere, let's encapsulate them in a new
explicit structure, that we can reuse at various places.

This is preparation for placing extra resources of Type #1 entry also in
them without having to encode access modes at multiple places
redundantly.

src/boot/cpio.c
src/boot/cpio.h
src/boot/stub.c

index 7ad4b470fae022846e160587741b46e324c7c9af..77bf7a8352603bc8569e3039136132ee89ad7d4d 100644 (file)
@@ -56,8 +56,7 @@ static EFI_STATUS pack_cpio_one(
                 const char16_t *fname,
                 const void *contents,
                 size_t contents_size,
-                const char *target_dir_prefix,
-                uint32_t access_mode,
+                const CpioTarget *target,
                 uint32_t *inode_counter,
                 void **cpio_buffer,
                 size_t *cpio_buffer_size) {
@@ -67,7 +66,7 @@ static EFI_STATUS pack_cpio_one(
 
         assert(fname);
         assert(contents || contents_size == 0);
-        assert(target_dir_prefix);
+        assert(target);
         assert(inode_counter);
         assert(cpio_buffer);
         assert(cpio_buffer_size);
@@ -84,7 +83,7 @@ static EFI_STATUS pack_cpio_one(
 
         l = 6 + 13*8 + 1 + 1; /* Fixed CPIO header size, slash separator, and NUL byte after the file name */
 
-        target_dir_prefix_size = strlen8(target_dir_prefix);
+        target_dir_prefix_size = strlen8(target->directory);
         if (l > SIZE_MAX - target_dir_prefix_size)
                 return EFI_OUT_OF_RESOURCES;
         l += target_dir_prefix_size;
@@ -121,11 +120,11 @@ static EFI_STATUS pack_cpio_one(
 
         a = mempcpy(a, "070701", 6); /* magic ID */
 
-        a = write_cpio_word(a, (*inode_counter)++);                         /* inode */
-        a = write_cpio_word(a, access_mode | 0100000 /* = S_IFREG */);      /* mode */
-        a = write_cpio_word(a, 0);                                          /* uid */
-        a = write_cpio_word(a, 0);                                          /* gid */
-        a = write_cpio_word(a, 1);                                          /* nlink */
+        a = write_cpio_word(a, (*inode_counter)++);                            /* inode */
+        a = write_cpio_word(a, target->access_mode | 0100000 /* = S_IFREG */); /* mode */
+        a = write_cpio_word(a, 0);                                             /* uid */
+        a = write_cpio_word(a, 0);                                             /* gid */
+        a = write_cpio_word(a, 1);                                             /* nlink */
 
         /* Note: we don't make any attempt to propagate the mtime here, for two reasons: it's a mess given
          * that FAT usually is assumed to operate with timezoned timestamps, while UNIX does not. More
@@ -141,7 +140,7 @@ static EFI_STATUS pack_cpio_one(
         a = write_cpio_word(a, target_dir_prefix_size + fname_size + 2);    /* fname size */
         a = write_cpio_word(a, 0);                                          /* "crc" */
 
-        a = mempcpy(a, target_dir_prefix, target_dir_prefix_size);
+        a = mempcpy(a, target->directory, target_dir_prefix_size);
         *(a++) = '/';
         a = mangle_filename(a, fname);
 
@@ -226,15 +225,14 @@ static EFI_STATUS pack_cpio_dir(
 }
 
 static EFI_STATUS pack_cpio_prefix(
-                const char *path,
-                uint32_t dir_mode,
+                const CpioTarget *target,
                 uint32_t *inode_counter,
                 void **cpio_buffer,
                 size_t *cpio_buffer_size) {
 
         EFI_STATUS err;
 
-        assert(path);
+        assert(target);
         assert(inode_counter);
         assert(cpio_buffer);
         assert(cpio_buffer_size);
@@ -243,7 +241,7 @@ static EFI_STATUS pack_cpio_prefix(
          * (similar to mkdir -p behaviour) all leading paths are created with 0555 access mode, only the
          * final dir is created with the specified directory access mode. */
 
-        for (const char *p = path;;) {
+        for (const char *p = target->directory;;) {
                 const char *e;
 
                 e = strchr8(p, '/');
@@ -253,7 +251,7 @@ static EFI_STATUS pack_cpio_prefix(
                 if (e > p) {
                         _cleanup_free_ char *t = NULL;
 
-                        t = xstrndup8(path, e - path);
+                        t = xstrndup8(target->directory, e - target->directory);
                         if (!t)
                                 return EFI_OUT_OF_RESOURCES;
 
@@ -265,7 +263,7 @@ static EFI_STATUS pack_cpio_prefix(
                 p = e + 1;
         }
 
-        return pack_cpio_dir(path, dir_mode, inode_counter, cpio_buffer, cpio_buffer_size);
+        return pack_cpio_dir(target->directory, target->dir_mode, inode_counter, cpio_buffer, cpio_buffer_size);
 }
 
 static EFI_STATUS pack_cpio_trailer(
@@ -307,9 +305,7 @@ EFI_STATUS pack_cpio(
                 const char16_t *dropin_dir,
                 const char16_t *match_suffix,
                 const char16_t *exclude_suffix,
-                const char *target_dir_prefix,
-                uint32_t dir_mode,
-                uint32_t access_mode,
+                const CpioTarget *target,
                 uint32_t tpm_pcr,
                 const char16_t *tpm_description,
                 struct iovec *ret_buffer,
@@ -325,7 +321,7 @@ EFI_STATUS pack_cpio(
         EFI_STATUS err;
 
         assert(loaded_image);
-        assert(target_dir_prefix);
+        assert(target);
         assert(ret_buffer);
 
         if (!loaded_image->DeviceHandle)
@@ -400,7 +396,7 @@ EFI_STATUS pack_cpio(
 
         /* Generate the leading directory inodes right before adding the first files, to the
          * archive. Otherwise the cpio archive cannot be unpacked, since the leading dirs won't exist. */
-        err = pack_cpio_prefix(target_dir_prefix, dir_mode, &inode, &buffer, &buffer_size);
+        err = pack_cpio_prefix(target, &inode, &buffer, &buffer_size);
         if (err != EFI_SUCCESS)
                 return log_error_status(err, "Failed to pack cpio prefix: %m");
 
@@ -417,8 +413,7 @@ EFI_STATUS pack_cpio(
                 err = pack_cpio_one(
                                 items[i],
                                 content, contentsize,
-                                target_dir_prefix,
-                                access_mode,
+                                target,
                                 &inode,
                                 &buffer, &buffer_size);
                 if (err != EFI_SUCCESS)
@@ -453,10 +448,8 @@ nothing:
 EFI_STATUS pack_cpio_literal(
                 const void *data,
                 size_t data_size,
-                const char *target_dir_prefix,
+                const CpioTarget *target,
                 const char16_t *target_filename,
-                uint32_t dir_mode,
-                uint32_t access_mode,
                 uint32_t tpm_pcr,
                 const char16_t *tpm_description,
                 struct iovec *ret_buffer,
@@ -468,22 +461,21 @@ EFI_STATUS pack_cpio_literal(
         EFI_STATUS err;
 
         assert(data || data_size == 0);
-        assert(target_dir_prefix);
+        assert(target);
         assert(target_filename);
         assert(ret_buffer);
 
         /* Generate the leading directory inodes right before adding the first files, to the
          * archive. Otherwise the cpio archive cannot be unpacked, since the leading dirs won't exist. */
 
-        err = pack_cpio_prefix(target_dir_prefix, dir_mode, &inode, &buffer, &buffer_size);
+        err = pack_cpio_prefix(target, &inode, &buffer, &buffer_size);
         if (err != EFI_SUCCESS)
                 return log_error_status(err, "Failed to pack cpio prefix: %m");
 
         err = pack_cpio_one(
                         target_filename,
                         data, data_size,
-                        target_dir_prefix,
-                        access_mode,
+                        target,
                         &inode,
                         &buffer, &buffer_size);
         if (err != EFI_SUCCESS)
@@ -505,3 +497,55 @@ EFI_STATUS pack_cpio_literal(
         *ret_buffer = IOVEC_MAKE(TAKE_PTR(buffer), buffer_size);
         return EFI_SUCCESS;
 }
+
+/* The following are canonical definitions of the various cpio target directories we place resources in. We
+ * define them here in a single canonical list of targets because we need to reuse them at various places
+ * (well, some of them at least), and we don't want the access modes to deviate slightly on each use. */
+
+const CpioTarget cpio_target_credentials = {
+        .directory = ".extra/credentials",
+        .dir_mode = 0500,
+        .access_mode = 0400,
+};
+
+const CpioTarget cpio_target_global_credentials = {
+        .directory = ".extra/global_credentials",
+        .dir_mode = 0500,
+        .access_mode = 0400,
+};
+
+const CpioTarget cpio_target_sysext = {
+        .directory = ".extra/sysext",
+        .dir_mode = 0555,
+        .access_mode = 0444,
+};
+
+const CpioTarget cpio_target_global_sysext = {
+        .directory = ".extra/global_sysext",
+        .dir_mode = 0555,
+        .access_mode = 0444,
+};
+
+const CpioTarget cpio_target_confext = {
+        .directory = ".extra/confext",
+        .dir_mode = 0555,
+        .access_mode = 0444,
+};
+
+const CpioTarget cpio_target_global_confext = {
+        .directory = ".extra/global_confext",
+        .dir_mode = 0555,
+        .access_mode = 0444,
+};
+
+const CpioTarget cpio_target_meta = {
+        .directory = ".extra",
+        .dir_mode = 0555,
+        .access_mode = 0444,
+};
+
+const CpioTarget cpio_target_meta_secret = {
+        .directory = ".extra",
+        .dir_mode = 0555,
+        .access_mode = 0400,
+};
index bb741278fdc24363c0b70622cf16c02cfc0d054f..f5c7b9fdec035e8533744a58f60151886532acbd 100644 (file)
@@ -4,14 +4,18 @@
 #include "efi.h"
 #include "proto/loaded-image.h"
 
+typedef struct CpioTarget {
+        const char *directory; /* Path to directory where to place resources */
+        uint32_t dir_mode;     /* Access mode for the directory */
+        uint32_t access_mode;  /* Access mode for the files in the directory */
+} CpioTarget;
+
 EFI_STATUS pack_cpio(
                 EFI_LOADED_IMAGE_PROTOCOL *loaded_image,
                 const char16_t *dropin_dir,
                 const char16_t *match_suffix,
                 const char16_t *exclude_suffix,
-                const char *target_dir_prefix,
-                uint32_t dir_mode,
-                uint32_t access_mode,
+                const CpioTarget *target,
                 uint32_t tpm_pcr,
                 const char16_t *tpm_description,
                 struct iovec *ret_buffer,
@@ -20,11 +24,18 @@ EFI_STATUS pack_cpio(
 EFI_STATUS pack_cpio_literal(
                 const void *data,
                 size_t data_size,
-                const char *target_dir_prefix,
+                const CpioTarget *target,
                 const char16_t *target_filename,
-                uint32_t dir_mode,
-                uint32_t access_mode,
                 uint32_t tpm_pcr,
                 const char16_t *tpm_description,
                 struct iovec *ret_buffer,
                 bool *ret_measured);
+
+extern const CpioTarget cpio_target_credentials;
+extern const CpioTarget cpio_target_global_credentials;
+extern const CpioTarget cpio_target_sysext;
+extern const CpioTarget cpio_target_global_sysext;
+extern const CpioTarget cpio_target_confext;
+extern const CpioTarget cpio_target_global_confext;
+extern const CpioTarget cpio_target_meta;
+extern const CpioTarget cpio_target_meta_secret;
index 664ee7cb851d541a683d39683c5ef499b5cadd08..00ffa2889c5fdbda0e40bf06de866b71c1826512 100644 (file)
@@ -862,9 +862,7 @@ static void generate_sidecar_initrds(
                       /* dropin_dir= */ NULL,
                       u".cred",
                       /* exclude_suffix= */ NULL,
-                      ".extra/credentials",
-                      /* dir_mode= */ 0500,
-                      /* access_mode= */ 0400,
+                      &cpio_target_credentials,
                       /* tpm_pcr= */ TPM2_PCR_KERNEL_CONFIG,
                       u"Credentials initrd",
                       initrds + INITRD_CREDENTIAL,
@@ -875,9 +873,7 @@ static void generate_sidecar_initrds(
                       u"\\loader\\credentials",
                       u".cred",
                       /* exclude_suffix= */ NULL,
-                      ".extra/global_credentials",
-                      /* dir_mode= */ 0500,
-                      /* access_mode= */ 0400,
+                      &cpio_target_global_credentials,
                       /* tpm_pcr= */ TPM2_PCR_KERNEL_CONFIG,
                       u"Global credentials initrd",
                       initrds + INITRD_GLOBAL_CREDENTIAL,
@@ -888,9 +884,7 @@ static void generate_sidecar_initrds(
                       /* dropin_dir= */ NULL,
                       u".raw",         /* ideally we'd pick up only *.sysext.raw here, but for compat we pick up *.raw instead … */
                       u".confext.raw", /* … but then exclude *.confext.raw again */
-                      ".extra/sysext",
-                      /* dir_mode= */ 0555,
-                      /* access_mode= */ 0444,
+                      &cpio_target_sysext,
                       /* tpm_pcr= */ TPM2_PCR_SYSEXTS,
                       u"System extension initrd",
                       initrds + INITRD_SYSEXT,
@@ -901,9 +895,7 @@ static void generate_sidecar_initrds(
                       u"\\loader\\extensions",
                       u".raw", /* as above */
                       u".confext.raw",
-                      ".extra/global_sysext",
-                      /* dir_mode= */ 0555,
-                      /* access_mode= */ 0444,
+                      &cpio_target_global_sysext,
                       /* tpm_pcr= */ TPM2_PCR_SYSEXTS,
                       u"Global system extension initrd",
                       initrds + INITRD_GLOBAL_SYSEXT,
@@ -914,9 +906,7 @@ static void generate_sidecar_initrds(
                       /* dropin_dir= */ NULL,
                       u".confext.raw",
                       /* exclude_suffix= */ NULL,
-                      ".extra/confext",
-                      /* dir_mode= */ 0555,
-                      /* access_mode= */ 0444,
+                      &cpio_target_confext,
                       /* tpm_pcr= */ TPM2_PCR_KERNEL_CONFIG,
                       u"Configuration extension initrd",
                       initrds + INITRD_CONFEXT,
@@ -927,9 +917,7 @@ static void generate_sidecar_initrds(
                       u"\\loader\\extensions",
                       u".confext.raw",
                       /* exclude_suffix= */ NULL,
-                      ".extra/global_confext",
-                      /* dir_mode= */ 0555,
-                      /* access_mode= */ 0444,
+                      &cpio_target_global_confext,
                       /* tpm_pcr= */ TPM2_PCR_KERNEL_CONFIG,
                       u"Global configuration extension initrd",
                       initrds + INITRD_GLOBAL_CONFEXT,
@@ -980,10 +968,8 @@ static void generate_embedded_initrds(
                 (void) pack_cpio_literal(
                                 (const uint8_t*) loaded_image->ImageBase + sections[t->section].memory_offset,
                                 sections[t->section].memory_size,
-                                ".extra",
+                                &cpio_target_meta,
                                 t->filename,
-                                /* dir_mode= */ 0555,
-                                /* access_mode= */ 0444,
                                 /* tpm_pcr= */ UINT32_MAX,
                                 /* tpm_description= */ NULL,
                                 initrds + t->initrd_index,
@@ -1004,10 +990,8 @@ static void generate_boot_secret_initrd(
         (void) pack_cpio_literal(
                         boot_secret,
                         BOOT_SECRET_SIZE,
-                        ".extra",
+                        &cpio_target_meta_secret,
                         u"boot-secret",
-                        /* dir_mode= */ 0555,
-                        /* access_mode= */ 0400,
                         /* tpm_pcr= */ UINT32_MAX,
                         /* tpm_description= */ NULL,
                         initrds + INITRD_BOOT_SECRET,