Packen Sie das Dateisystem-Image aus vmlinux.bin (eingebettetes initramfs) neu, ohne es neu zu erstellen?

7

In Wie extrahiere ich das Dateisystem-Image aus vmlinux.bin? und https://wiki.gentoo.org/wiki/Custom_Initramfs#Salvaging-Methoden werden zum Abrufen und Entpacken eines eingebetteten initramfs / initrd vorgestellt, das im Kernel-Image enthalten ist.

Jetzt möchte ich das modifizierte Dateisystem ( cpio+ möglicherweise mit z. B. gepackt lzma) in die ausführbare Datei des Kernels einfügen, ohne es neu kompilieren zu müssen. Wäre es möglich, das ELF-Image des Kernels auf diese Weise zu ändern? Wenn ja, wie dann? Würde ich etwas respektieren müssen, wenn ich einfach die Bytes an Ort und Stelle ersetzen würde (vielleicht etwas Hash?)?


objdump-h Ausgabe:
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
phk
quelle
1
Können Sie die Kernel-Elf-Datei aus der Datei vmlinux.bin extrahieren? Wenn ja, können Sie die Ausgabe von objdump -h kernel.elfzur Frage hinzufügen ? Insbesondere sollte der Abschnitt .init.ramfsdie initramfs enthalten. Wir können wahrscheinlich ein kleineres modifiziertes Dateisystem an seiner Stelle einfügen und das Datum anpassen, das seine Länge angibt. Es ist nicht klar, ob es sich im Allgemeinen lohnt, dies zu tun, aber wenn Sie einen Kernel haben, z. B. für ein eingebettetes Gerät, bei dem Sie nicht über die gesamte Kernelquelle verfügen, die neu erstellt werden kann, kann ich einen Anwendungsfall sehen
icarus
@icarus Die Ausgabe wurde hinzugefügt, ein Abschnitt, den ich genau diesen Namen nicht finden konnte. Und Sie haben genau Recht, es ist ein eingebettetes Gerät, für das ich nicht die genauen Kernelquellen habe.
Phk

Antworten:

2

Ja, es ist möglich, aber das Ändern der Abschnittsgröße und -adressen von .init.ramfs reicht nicht aus, da die ausführbare ELF-Datei des Kernels statisch mit der virtuellen Adresse des Beginns und Endes des Abschnitts von initramfs verknüpft ist .

In den Linux-Quellen befindet sich der relevante Code in der Quelldatei iniramfs.c:

void __init populate_rootfs(void)
{
  char *err = unpack_to_rootfs(__initramfs_start, __initramfs_end - __initramfs_start, 0); 
...
}

Daher müssen Sie diese beiden Offsets auch im Maschinencode des Aufrufs der Funktion unpack_to_rootfs () ändern, die sich im Abschnitt .init.text befindet. (Achten Sie auf relevante Einträge in der Umzugstabelle! ... falls vorhanden)

In Bezug auf die Antwort von Icarus können Sie durch Manipulieren der Größe des Initramfs-Abschnitts, des Dateiversatzes und der virtuellen Startadresse sowie dieser beiden oben genannten Offsets (Argumente für die Funktion unpack_to_rootfs ()) Ihren eigenen benutzerdefinierten LARGER hinzufügen initramfs-Abschnitt, der ÜBER der maximalen virtuellen Adresse der ELF-Datei geladen wird. Das Feld "Speichergröße" des Programm-Headers (PHeader) muss ebenfalls geändert werden, um den größeren initramfs-Abschnitt widerzuspiegeln, der nach dem Ende des alten virtuellen Adressraums angehängt wird.

PS Die "Lücke" im virtuellen Adressraum des Kernels, die nach dem Verschieben des ursprünglichen Abschnitts init.ramfs in eine neue virtuelle Adresse mit hohem Start verbleibt, schadet nichts, da der zugehörige Speicher später durch die in init definierte Funktion free_initmem (void) freigegeben wird .c Quelldatei.

George Robinson
quelle