我正在修改来自不同 Linux 发行版的一堆initramfs
档案,其中通常只更改一个文件。
我想自动化该过程,而无需切换到 root 用户来提取initramfs
映像内的所有文件并再次打包它们。
首先我尝试生成文件列表gen_init_cpio
没有提取存档上的所有内容initramfs
,即通过脚本解析输出cpio -tvn initrd.img
(如ls -l
输出),该脚本将所有权限更改为八进制并将输出安排为gen_init_cpio
所需的格式,例如:
dir /dev 755 0 0
nod /dev/console 644 0 0 c 5 1
slink /bin/sh busybox 777 0 0
file /bin/busybox initramfs/busybox 755 0 0
这涉及到一些替换,而且脚本对我来说可能很难写,所以我找到了一种更好的方法,我问的是它的安全性和便携性如何:
在某些发行版中,我们有一个initramfs
包含串联部分的文件,显然内核会解析整个文件,提取包装在 1 字节边界中的所有部分,因此无需将每个部分填充为 512 字节的倍数。我认为这个“功能”对我来说很有用,可以避免在修改其中的文件时重新创建存档。事实上它有效,至少对于Debian
和CloneZilla
。
例如,如果我们修改了Debian 8.2.0/init
上的文件initrd.gz
,我们可以将其附加到initrd.gz
映像中:
$ echo ./init | cpio -H newc -o | gzip >> initrd.gz
因此initrd.gz
有两个串联的档案,原始档案和修改后的档案。让我们看看结果binwalk
:
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 gzip compressed data, maximum compression, has original file name: "initrd", from Unix, last modified: Tue Sep 1 09:33:08 2015
6299939 0x602123 gzip compressed data, from Unix, last modified: Tue Nov 17 16:06:13 2015
它工作完美。但它可靠吗?将数据附加到文件时有哪些限制initfamfs
?在不将原始存档填充到 512 字节的倍数的情况下追加是否安全?哪个内核版本支持此功能?
答案1
它非常可靠,并且受到所有支持 initrd 的内核版本的支持,据我所知。这是构成 cpio
档案的一个特征。只是继续提取其输入......我们可能知道该文件是一个接一个的两个 cpio 存档,但 cpio 只是将其视为单个输入流。initramfs
cpio
Debian 建议使用这种方法(将另一个 cpio 附加到 initramfs)将二进制 blob 固件添加到其安装程序 initramfs。例如:
Debian 安装程序 / Netboot 固件 | Debian 维基
Initramfs 本质上是 gzip 压缩的 cpio 存档的串联,这些存档被提取到 ramdisk 中并由 Linux 内核用作早期用户空间。 Debian 安装程序的 initrd.gz 实际上是一个 gzip 压缩的 cpio 存档,其中包含安装程序在启动时所需的所有文件。通过简单地附加另一个 gzipped cpio 存档 - 包含我们缺少的固件文件 - 我们就可以上路了!
答案2
否,现有的 initramfs需要填充以便可靠地继续解析附加到压缩档案的任意档案。
尤其是xz
和“传统帧格式”lz4
压缩很棘手,四分之三会失败 - 具体来说,每次前一个存档的字节数不能被 4 整除时。这通常会被忽视,因为将 raw format=newc cpio 放在前面时并不需要担心单个压缩存档 - 未压缩的形式始终对齐。
虽然从理论上讲,initramfs 格式除了是(可选压缩)存档的简单串联之外没有指定,但当解压缩例程(在某些情况下,根据设计)无法分辨一个存档在哪里结束以及下一个存档在哪里开始时,仍然需要填充。一些边缘情况是Linux 版本 5.14 中的改进,其他的似乎很难(如果不是不可能)在内核中明确检测到。如果压缩档案后面有附加数据,则诸如以下的消息表明它被忽略:
Initramfs unpacking failed: Decoding failed
Initramfs unpacking failed: invalid magic at start of compressed archive
Initramfs unpacking failed: broken padding
如果压缩仅应用于最后一个存档,则这些消息是无害的 - 没有进一步解析任何内容,但无论如何也没有任何内容需要解析。