In How do I extract the filesystem image from vmlinux.bin? and https://wiki.gentoo.org/wiki/Custom_Initramfs#Salvaging methods are presented for getting and unpacking an embedded initramfs/initrd included in the kernel image.
Now I would like to insert the modified file system (cpio
+ possibly packed using e.g. lzma
) into the kernel executable without having to recompile it. Would it be possible to modify the ELF image of the kernel in this way? If so then how? Would I need to keep something in respect if I were to simply replace the bytes in-place (maybe some hash?)?
objdump-h
Output:
vmlinux.64.orig: file format elf64-big
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 004162b8 ffffffff80100000 ffffffff80100000 00010000 2**7
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 __ex_table 000063a0 ffffffff805162c0 ffffffff805162c0 004262c0 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .notes 00000024 ffffffff8051c660 ffffffff8051c660 0042c660 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .rodata 0041f700 ffffffff8051d000 ffffffff8051d000 0042d000 2**8
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .pci_fixup 00000d40 ffffffff8093c700 ffffffff8093c700 0084c700 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 __ksymtab 0000a430 ffffffff8093d440 ffffffff8093d440 0084d440 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 __ksymtab_gpl 00004ff0 ffffffff80947870 ffffffff80947870 00857870 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
7 __ksymtab_strings 00010f14 ffffffff8094c860 ffffffff8094c860 0085c860 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
8 __init_rodata 00000500 ffffffff8095d778 ffffffff8095d778 0086d778 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
9 __param 00001388 ffffffff8095dc78 ffffffff8095dc78 0086dc78 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
10 .data 000508c0 ffffffff80960000 ffffffff80960000 00870000 2**14
CONTENTS, ALLOC, LOAD, DATA
11 .init.text 0002b084 ffffffff809b1000 ffffffff809b1000 008c1000 2**5
CONTENTS, ALLOC, LOAD, READONLY, CODE
12 .init.data 00bc6d78 ffffffff809dc088 ffffffff809dc088 008ec088 2**3
CONTENTS, ALLOC, LOAD, DATA
13 .exit.text 000019e0 ffffffff815a2e00 ffffffff815a2e00 014b2e00 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
14 .data.percpu 00003680 ffffffff815a5000 ffffffff815a5000 014b5000 2**7
CONTENTS, ALLOC, LOAD, DATA
15 .bss 00068fb0 ffffffff815b0000 ffffffff815b0000 014b8680 2**16
ALLOC
16 .mdebug.abi64 00000000 ffffffff81618fb0 ffffffff81618fb0 014b8680 2**0
CONTENTS, READONLY
17 .comment 0000cd74 0000000000000000 0000000000000000 014b8680 2**0
CONTENTS, READONLY
18 .gnu.attributes 00000010 0000000000000000 0000000000000000 014c53f4 2**0
Best Answer
Yes, it is possible but changing the .init.ramfs section size and addresses is not enough because the Kernel's ELF executable is statically linked with the virtual address of the start and end of the initramfs' section.
In the Linux sources the relevant code is located in the iniramfs.c source file:
So you also need to change these two offsets in the machine code of the invocation of the unpack_to_rootfs() function, which is located in the .init.text section. ( watch out for any relevant entries in the relocation table! ...if one exists )
Also, in reference to Icarus's reply, the manipulation of the initramfs' section' size, file offset and starting virtual address, as well as these two aforementioned offsets (arguments to the unpack_to_rootfs() function), enables you to add you own custom LARGER initramfs section that is loaded ABOVE the maximum virtual address of the ELF file. The Program Header's (PHeader) "Memory Size" field needs to be modified too, in order to reflect the larger initramfs section appended after the end of the old virtual address space.
P.S. The "hole" in the Kernel's virtual address space remaining after moving the original init.ramfs section to a new high starting virtual address, does not hurt anything because the associated memory is later freed by the free_initmem(void) function defined in the init.c source file.