boot: introduce a common structure for cpio target dirs
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.
This commit is contained in:
+74
-30
@@ -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,
|
||||
};
|
||||
|
||||
+17
-6
@@ -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;
|
||||
|
||||
+8
-24
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user