usr/default_cpio_list | 6 +++--- usr/gen_init_cpio.c | 10 +++++----- usr/gen_initramfs.sh | 27 +++++++++++++++++++-------- 3 files changed, 27 insertions(+), 16 deletions(-)
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@gmail.com>
---
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
[cc'ing fsdevel]
On Mon, 9 Feb 2026 16:37:58 +0100, Christian Marangi wrote:
> 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,
"highly discouraged" isn't really appropriate here; the kernel generally
doesn't care whether or not a filename carries whitespace.
The limitation here is specifically the gen_init_cpio manifest format,
which is strictly space-separated.
> 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:
The error messages don't really add any value here.
<snip>
> 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@gmail.com>
> ---
> 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)) {
This breaks parsing of existing manifest files, so is unacceptable
IMO. If we really want to go down the route of having gen_init_cpio
support space-separated paths, then perhaps a new --field-separator
parameter might make sense. For your specific workload it seems that
simply using an external cpio archiver with space support (e.g. GNU
cpio --null) would make sense. Did you consider going down that
path?
Thanks, David
© 2016 - 2026 Red Hat, Inc.