Đóng gói lại hình ảnh hệ thống tập tin từ vmlinux.bin (nhúng initramfs) mà không xây dựng lại?


7

Trong Làm cách nào để trích xuất hình ảnh hệ thống tập tin từ vmlinux.bin? https://wiki.gentoo.org/wiki/Custom_Initramfs#Salvaging được trình bày để nhận và giải nén một initramfs / initrd được nhúng trong hình ảnh kernel.

Bây giờ tôi muốn chèn hệ thống tệp đã sửa đổi ( cpio+ có thể được đóng gói bằng vd lzma) vào kernel có thể thực thi được mà không phải biên dịch lại. Có thể sửa đổi hình ảnh ELF của kernel theo cách này không? Nếu vậy thì thế nào? Tôi có cần phải giữ một cái gì đó tôn trọng nếu tôi chỉ đơn giản là thay thế các byte tại chỗ (có thể là một số băm?)?


objdump-h Đầu ra:
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

1
Bạn có thể trích xuất tập tin kernel elf từ vmlinux.bin không? Nếu vậy bạn có thể thêm đầu ra của objdump -h kernel.elfcâu hỏi? Cụ thể, phần .init.ramfsnên chứa initramfs. Chúng ta có thể có thể chèn một hệ thống tập tin sửa đổi nhỏ hơn vào vị trí của nó và điều chỉnh mốc thời gian cho chiều dài của nó. Nói chung không rõ ràng là đáng làm, nhưng nếu bạn có kernel, ví dụ như cho một thiết bị nhúng, nơi bạn không có tất cả nguồn kernel để xây dựng lại, tôi có thể thấy trường hợp sử dụng,
icarus

@icarus Đã thêm đầu ra, một phần chính xác tên này tôi không thể tìm thấy mặc dù. Và bạn hoàn toàn chính xác, đó là một thiết bị nhúng mà tôi không có nguồn hạt nhân chính xác.
phk

Câu trả lời:


2

Có, có thể nhưng thay đổi kích thước và địa chỉ của phần .init.ramfs là không đủ vì thực thi ELF của Kernel được liên kết tĩnh với địa chỉ ảo của phần bắt đầu và kết thúc của phần initramfs.

Trong các nguồn Linux, mã có liên quan nằm trong tệp nguồn iniramfs.c:

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

Vì vậy, bạn cũng cần thay đổi hai độ lệch này trong mã máy của lệnh gọi hàm unpack_to_rootfs (), nằm trong phần .init.text. (coi chừng mọi mục liên quan trong bảng di dời! ... nếu có

Ngoài ra, liên quan đến câu trả lời của Icarus, việc thao tác kích thước của phần initramfs, bù tệp và bắt đầu địa chỉ ảo, cũng như hai phần bù đã nói ở trên (đối số cho hàm unpack_to_rootfs ()), cho phép bạn thêm LARGER tùy chỉnh của riêng bạn phần initramfs được tải TRÊN địa chỉ ảo tối đa của tệp ELF. Trường "Kích thước bộ nhớ" của Header Chương trình (PHead) cũng cần phải được sửa đổi, để phản ánh phần initramfs lớn hơn được nối sau khi kết thúc không gian địa chỉ ảo cũ.

PS "Lỗ" trong không gian địa chỉ ảo của Kernel còn lại sau khi di chuyển phần init.ramfs ban đầu sang địa chỉ ảo bắt đầu cao mới, không làm tổn hại gì vì bộ nhớ liên quan sau đó được giải phóng bởi hàm free_initmem (void) được xác định trong init tập tin nguồn .c.


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.