[RFC PATCH] initramfs: correctly handle space in path on cpio list generation

From: Christian Marangi

Date: Mon Feb 09 2026 - 10:38:12 EST


The current gen_initramfs.sh and gen_init_cpio.c tools doesn't correctly
handle path or filename with space in it. Although highly discouraged,
Linux also supports filename or path with whiespace and currently this
will produce error on generating and parsing the cpio_list file as the
pattern won't match the expected variables order. (with gid or mode
parsed as string)

This was notice when creating an initramfs with including the ALSA test
files and configuration that have whitespace in both some .conf and even
some symbolic links.

Example error:
usr/gen_initramfs.sh: line 97: [: Devkit.conf: integer expected
usr/gen_initramfs.sh: line 97: [: Devkit.conf: integer expected
usr/gen_initramfs.sh: line 97: [: Nexus: integer expected
usr/gen_initramfs.sh: line 97: [: Tab: integer expected
usr/gen_initramfs.sh: line 98: [: A500: integer expected
usr/gen_initramfs.sh: line 97: [: Slider: integer expected
usr/gen_initramfs.sh: line 98: [: WM8903.conf: integer expected
usr/gen_initramfs.sh: line 97: [: Transformer: integer expected
usr/gen_initramfs.sh: line 98: [: WM8903.conf: integer expected
usr/gen_initramfs.sh: line 97: [: Infinity: integer expected
usr/gen_initramfs.sh: line 98: [: TF700T: integer expected
usr/gen_initramfs.sh: line 97: [: Pad: integer expected
usr/gen_initramfs.sh: line 98: [: TF300T: integer expected
usr/gen_initramfs.sh: line 97: [: Pad: integer expected
usr/gen_initramfs.sh: line 98: [: TF300TG: integer expected
usr/gen_initramfs.sh: line 97: [: Pad: integer expected
usr/gen_initramfs.sh: line 98: [: TF300TL: integer expected
usr/gen_initramfs.sh: line 97: [: Prime: integer expected
usr/gen_initramfs.sh: line 98: [: TF201: integer expected
usr/gen_initramfs.sh: line 97: [: 4X: integer expected
usr/gen_initramfs.sh: line 98: [: HD: integer expected
usr/gen_initramfs.sh: line 97: [: Vu: integer expected
usr/gen_initramfs.sh: line 98: [: MAX98089.conf: integer expected

Caused by example file:

/usr/share/alsa/ucm2/conf.d/tegra/Asus Transformer Pad TF300TL RT5631.conf

To correctly handle this problem, rework the gen_initramfs.sh and
gen_init_cpio.c to guard all the path with "" to handle all kind of
whitespace for filename/path.

The default_cpio_list is also updated to follow this new pattern.

Signed-off-by: Christian Marangi <ansuelsmth@xxxxxxxxx>
---
usr/default_cpio_list | 6 +++---
usr/gen_init_cpio.c | 10 +++++-----
usr/gen_initramfs.sh | 27 +++++++++++++++++++--------
3 files changed, 27 insertions(+), 16 deletions(-)

diff --git a/usr/default_cpio_list b/usr/default_cpio_list
index 37b3864066e8..d4a66b4aa7f7 100644
--- a/usr/default_cpio_list
+++ b/usr/default_cpio_list
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
# This is a very simple, default initramfs

-dir /dev 0755 0 0
-nod /dev/console 0600 0 0 c 5 1
-dir /root 0700 0 0
+dir "/dev" 0755 0 0
+nod "/dev/console" 0600 0 0 c 5 1
+dir "/root" 0700 0 0
diff --git a/usr/gen_init_cpio.c b/usr/gen_init_cpio.c
index b7296edc6626..ca5950998841 100644
--- a/usr/gen_init_cpio.c
+++ b/usr/gen_init_cpio.c
@@ -166,7 +166,7 @@ static int cpio_mkslink_line(const char *line)
int gid;
int rc = -1;

- if (5 != sscanf(line, "%" str(PATH_MAX) "s %" str(PATH_MAX) "s %o %d %d", name, target, &mode, &uid, &gid)) {
+ if (5 != sscanf(line, "\"%" str(PATH_MAX) "[^\"]\" \"%" str(PATH_MAX) "[^\"]\" %o %d %d", name, target, &mode, &uid, &gid)) {
fprintf(stderr, "Unrecognized dir format '%s'", line);
goto fail;
}
@@ -244,7 +244,7 @@ static int cpio_mkgeneric_line(const char *line, enum generic_types gt)
int gid;
int rc = -1;

- if (4 != sscanf(line, "%" str(PATH_MAX) "s %o %d %d", name, &mode, &uid, &gid)) {
+ if (4 != sscanf(line, "\"%" str(PATH_MAX) "[^\"]\" %o %d %d", name, &mode, &uid, &gid)) {
fprintf(stderr, "Unrecognized %s format '%s'",
line, generic_type_table[gt].type);
goto fail;
@@ -322,7 +322,7 @@ static int cpio_mknod_line(const char *line)
unsigned int min;
int rc = -1;

- if (7 != sscanf(line, "%" str(PATH_MAX) "s %o %d %d %c %u %u",
+ if (7 != sscanf(line, "\"%" str(PATH_MAX) "[^\"]\" %o %d %d %c %u %u",
name, &mode, &uid, &gid, &dev_type, &maj, &min)) {
fprintf(stderr, "Unrecognized nod format '%s'", line);
goto fail;
@@ -527,8 +527,8 @@ static int cpio_mkfile_line(const char *line)
int end = 0, dname_len = 0;
int rc = -1;

- if (5 > sscanf(line, "%" str(PATH_MAX) "s %" str(PATH_MAX)
- "s %o %d %d %n",
+ if (5 > sscanf(line, "\"%" str(PATH_MAX) "[^\"]\" \"%"
+ str(PATH_MAX) "[^\"]\" %o %d %d %n",
name, location, &mode, &uid, &gid, &end)) {
fprintf(stderr, "Unrecognized file format '%s'", line);
goto fail;
diff --git a/usr/gen_initramfs.sh b/usr/gen_initramfs.sh
index 7eba2fddf0ef..13f2219a1ce9 100755
--- a/usr/gen_initramfs.sh
+++ b/usr/gen_initramfs.sh
@@ -103,7 +103,8 @@ parse() {

case "${ftype}" in
"file")
- str="${ftype} ${name} ${location} ${str}"
+ printf "%s \"%s\" \"%s\" %s\n" \
+ "${ftype}" "${name}" "${location}" "${str}" >> $cpio_list
;;
"nod")
local dev="`LC_ALL=C ls -l "${location}"`"
@@ -113,19 +114,20 @@ parse() {

[ -b "${location}" ] && dev="b" || dev="c"

- str="${ftype} ${name} ${str} ${dev} ${maj} ${min}"
+ printf "%s \"%s\" %s %s %s %s\n" \
+ "${ftype}" "${name}" "${str}" "${dev}" "${maj}" "${min}" >> $cpio_list
;;
"slink")
local target=`readlink "${location}"`
- str="${ftype} ${name} ${target} ${str}"
+ printf "%s \"%s\" \"%s\" %s\n" \
+ "${ftype}" "${name}" "${target}" "${str}" >> $cpio_list
;;
*)
- str="${ftype} ${name} ${str}"
+ printf "%s \"%s\" %s\n" \
+ "${ftype}" "${name}" "${str}" >> $cpio_list
;;
esac

- echo "${str}" >> $cpio_list
-
return 0
}

@@ -156,8 +158,17 @@ dir_filelist() {

echo "${dirlist}" | \
while read x; do
- list_parse $x
- parse $x
+ # Reverse progressive matching to handle path
+ # with space (last arg)
+ gid=${x##* }
+ x=${x% *}
+ uid=${x##* }
+ x=${x% *}
+ mode=${x##* }
+ path=${x% *}
+
+ list_parse "$path" "$mode" "$uid" "$gid"
+ parse "$path" "$mode" "$uid" "$gid"
done
fi
}
--
2.51.0