unmkinitramfs: Stop splitting into "early" and "main" subdirectories

We originally unpacked each cpio archive into its own subdirectory for
security reasons.  Since we are now able to stitch together multiple
cpio archives to feed to a single cpio process, that concern no longer
applies.

We maintained the split up to the release of "trixie" out of concern
for possible breakage of callers that relied on this split.  Since
that release is done, stop splitting and always unpack everything
directly into the output directory.

Signed-off-by: Ben Hutchings <benh@debian.org>
This commit is contained in:
Ben Hutchings 2025-04-07 01:05:41 +02:00
parent 49f3bbadce
commit 810421833a
3 changed files with 21 additions and 128 deletions

View File

@ -9,7 +9,7 @@ make_one_archive() {
case "$type" in
early)
dir_name=kernel
dir_name="kernel/dir$i"
;;
main)
dir_name="dir$i"
@ -94,23 +94,13 @@ for n_early in 0 1 2; do
rm -rf "$AUTOPKGTEST_TMP/reference"
mkdir "$AUTOPKGTEST_TMP/reference"
for i in $(seq 0 $((n_early - 1))); do
if [ "$i" -eq 0 ]; then
dir_name=early
else
dir_name=early$((i + 1))
fi
ln -s ../input/"early$i" \
"$AUTOPKGTEST_TMP/reference/$dir_name"
mkdir -p "$AUTOPKGTEST_TMP/reference/kernel"
ln -s ../../input/"early$i/kernel/dir$i" \
"$AUTOPKGTEST_TMP/reference/kernel/"
done
for i in $(seq 0 $((n_main - 1))); do
if [ $n_early = 0 ]; then
ln -s ../input/"main$i/dir$i" \
"$AUTOPKGTEST_TMP/reference/dir$i"
else
mkdir -p "$AUTOPKGTEST_TMP/reference/main"
ln -s ../../input/"main$i/dir$i" \
"$AUTOPKGTEST_TMP/reference/main/dir$i"
fi
ln -s ../input/"main$i/dir$i" \
"$AUTOPKGTEST_TMP/reference/"
done
# Compare reference and output

View File

@ -21,14 +21,9 @@ The initramfs image may be a single compressed cpio archive, or the
concatenation of any number of uncompressed cpio archives optionally
followed by a compressed cpio archive.
When the initramfs image includes one or more "early initramfs"
archives, that is uncompressed archives with microcode or other files
that the kernel uses directly, these are extracted to sub\-directories
named "\fBearly\fR", "\fBearly2\fR", etc., and the other archives are
extracted to a sub\-directory named "\fBmain\fR".
In a future version of initramfs\-tools this behaviour may change so
that all archives are extracted directly into the given directory.
Earlier versions of this command would in some cases unpack an
initramfs consisting of multiple archives into multiple subdirectories
of the given directory.
.SH OPTIONS

View File

@ -255,30 +255,6 @@ static void cpio_close(struct cpio_handle *cpio)
free(cpio);
}
static bool detect_early_initramfs(FILE *in_file, const char *in_filename)
{
struct cpio_handle *cpio;
struct cpio_entry entry;
bool ret = false;
off_t start = ftell(in_file);
cpio = cpio_open(in_file, in_filename);
if (!cpio)
return false;
while (cpio_get_next(cpio, &entry) > 0) {
if (strncmp(entry.name, "kernel/", 7) == 0) {
ret = true;
break;
}
}
cpio_close(cpio);
fseek(in_file, start, SEEK_SET);
return ret;
}
static bool copy_to_pipe(FILE *in_file, const char *in_filename,
off_t start, off_t end, int out_pipe)
{
@ -519,12 +495,10 @@ int main(int argc, char **argv)
bool verbose = false;
const char *in_filename;
FILE *in_file;
const char *out_dirname = NULL;
char *out_subdirname = NULL;
const char *out_dirname;
const char *cpio_optv[3];
int cpio_optc;
struct cpio_proc cpio_proc = { 0 };
unsigned int early_count = 0;
bool ok;
/* Parse options */
@ -561,21 +535,20 @@ int main(int argc, char **argv)
out_dirname = argv[optind + 1];
if (!mkdir_allow_exist(out_dirname, 0777))
err(1, "%s", out_dirname);
out_subdirname = malloc(strlen(out_dirname) + 20);
if (!out_subdirname)
err(1, "malloc");
}
/* Set up extra options for cpio */
/* Spawn cpio with appropriate options and pipe */
cpio_optc = 0;
if (do_list) {
cpio_optv[cpio_optc++] = "--list";
} else {
cpio_optv[cpio_optc++] = "-D";
cpio_optv[cpio_optc++] = out_subdirname;
cpio_optv[cpio_optc++] = out_dirname;
}
if (verbose)
cpio_optv[cpio_optc++] = "-v";
if (!spawn_cpio(cpio_optc, cpio_optv, &cpio_proc))
return 1;
/* Iterate over archives within the initramfs */
for (;;) {
@ -594,7 +567,7 @@ int main(int argc, char **argv)
warn("%s", in_filename);
ok = false;
}
if (cpio_proc.pid && !write_trailer(cpio_proc.pipe))
if (!write_trailer(cpio_proc.pipe))
ok = false;
break;
}
@ -612,86 +585,21 @@ int main(int argc, char **argv)
break;
}
/*
* Extract the archive to an "early" or "early<n>"
* subdirectory if:
* - We have not already started the main cpio process
* - We are not listing
* - This looks like an early initramfs (uncompressed
* and contains files under kernel/)
*/
if (!cpio_proc.pid && !do_list &&
me->format == FORMAT_CPIO_NEW &&
detect_early_initramfs(in_file, in_filename)) {
struct cpio_proc early_cpio_proc;
if (++early_count == 1)
sprintf(out_subdirname, "%s/early",
out_dirname);
else
sprintf(out_subdirname, "%s/early%u",
out_dirname, early_count);
if (!mkdir_allow_exist(out_subdirname, 0777)) {
warn("%s", out_subdirname);
ok = false;
break;
}
if (!spawn_cpio(cpio_optc, cpio_optv,
&early_cpio_proc)) {
ok = false;
break;
}
if (me->format == FORMAT_CPIO_NEW) {
ok = handle_uncompressed(in_file, in_filename,
early_cpio_proc.pipe)
&& write_trailer(early_cpio_proc.pipe);
if (!end_cpio(&early_cpio_proc, ok))
ok = false;
cpio_proc.pipe);
if (!ok)
break;
} else {
/*
* Otherwise, extract to either the base
* output directory or a "main" subdirectory,
* depending on whether we already created
* subdirectories.
*/
if (!cpio_proc.pid) {
if (do_list) {
;
} else if (early_count) {
sprintf(out_subdirname, "%s/main",
out_dirname);
if (!mkdir_allow_exist(out_subdirname,
0777)) {
warn("%s", out_subdirname);
ok = false;
break;
}
} else {
strcpy(out_subdirname, out_dirname);
}
if (!spawn_cpio(cpio_optc, cpio_optv,
&cpio_proc)) {
ok = false;
break;
}
}
if (me->format == FORMAT_CPIO_NEW) {
ok = handle_uncompressed(in_file, in_filename,
cpio_proc.pipe);
if (!ok)
break;
} else {
ok = handle_compressed(in_file, me->format,
cpio_proc.pipe);
break;
}
ok = handle_compressed(in_file, me->format,
cpio_proc.pipe);
break;
}
}
fclose(in_file);
if (cpio_proc.pid && !end_cpio(&cpio_proc, ok))
if (!end_cpio(&cpio_proc, ok))
ok = false;
return !ok;