Reempacote a imagem do sistema de arquivos do vmlinux.bin (initramfs incorporado) sem reconstruir?

7

Em Como eu extraio o sistema de arquivos Os métodos image from vmlinux.bin? e link são apresentados para obter e descompactar um initramfs / initrd incorporado incluído na imagem do kernel.

Agora gostaria de inserir o sistema de arquivos modificado ( cpio + possivelmente compactado usando, por exemplo, lzma ) no executável do kernel sem ter que recompilá-lo. Seria possível modificar a imagem ELF do kernel dessa maneira? Se sim, então como? Eu precisaria manter alguma coisa a respeito se eu simplesmente substituísse os bytes no local (talvez algum hash?)?

objdump-h de saída:
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
    
por phk 03.02.2017 / 17:00

2 respostas

1

Como mencionado na resposta a uma pergunta semelhante sobre como substituir as seções ELF discutidas em reverseengineering.se simplesmente usando dd pode ser suficiente em algumas circunstâncias, além do novo arquivo não ser maior, por exemplo se há relocações.

    
por 13.04.2017 / 14:49
2

Sim, é possível, mas alterar o tamanho e os endereços das seções .init.ramfs não é suficiente porque o executável ELF do Kernel está vinculado estaticamente ao endereço virtual início e fim do initramfs ' seção.

Nas origens do Linux, o código relevante está localizado no arquivo de origem iniramfs.c:

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

Portanto, você também precisa alterar esses dois deslocamentos no código da máquina da invocação da função unpack_to_rootfs (), localizada na seção .init.text. (atente para quaisquer entradas relevantes na tabela de realocação! ... se houver)

Além disso, em referência à resposta de Icarus, a manipulação do tamanho da seção 'initramfs', deslocamento do arquivo e início do endereço virtual, bem como esses dois deslocamentos acima mencionados (argumentos para a função unpack_to_rootfs ()) permitem que você o adicione seção initramfs LARGER personalizada que é carregada ACIMA do endereço virtual máximo do arquivo ELF. O campo "Tamanho da Memória" do Cabeçalho do Programa (PHeader) também precisa ser modificado, para refletir a seção initramfs maior anexada após o término do espaço de endereço virtual antigo.

P.S. O "buraco" no espaço de endereço virtual do Kernel que permanece após mover a seção init.ramfs original para um novo endereço virtual inicial alto, não atrapalha nada porque a memória associada é liberada mais tarde pela função free_initmem (void) definida em o arquivo de origem init.c.

    
por 25.07.2018 / 18:07