O que o endereço físico 0 no x86 Linux contém?

11

Não tenho certeza se essa pergunta deve ser feita aqui ou em reverseengineering.stackexchange.com

Citações de wikipedia :

In the 8086 processor, the interrupt table is called IVT (interrupt vector table). The IVT always resides at the same location in memory, ranging from 0x0000 to 0x03ff, and consists of 256 four-byte real mode far pointers (256 × 4 = 1024 bytes of memory).

Isto é o que eu encontro no monitor do qemu:

(qemu) xp/128xw 0
0000000000000000: 0xf000ff53 0xf000ff53 0xf000e2c3 0xf000ff53
0000000000000010: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000020: 0xf000fea5 0xf000e987 0xf000d62c 0xf000d62c
0000000000000030: 0xf000d62c 0xf000d62c 0xf000ef57 0xf000d62c
0000000000000040: 0xc0005526 0xf000f84d 0xf000f841 0xf000e3fe
0000000000000050: 0xf000e739 0xf000f859 0xf000e82e 0xf000efd2
0000000000000060: 0xf000d648 0xf000e6f2 0xf000fe6e 0xf000ff53
0000000000000070: 0xf000ff53 0xf000ff53 0xf0006aa4 0xc0008930
0000000000000080: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000090: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000000a0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000000b0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000000c0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000000d0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000000e0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000000f0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000100: 0xf000ec59 0xf000ff53 0xf000ff53 0xc0006730
0000000000000110: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000120: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000130: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000140: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000150: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000160: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000170: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
0000000000000180: 0x00000000 0x00000000 0x00000000 0x00000000
0000000000000190: 0x00000000 0x00000000 0x00000000 0xf000ff53
00000000000001a0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000001b0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53
00000000000001c0: 0xf000d611 0xf000ec4e 0xf000ec4e 0xf000ec4e
00000000000001d0: 0xf000d61a 0xf000d623 0xf000d608 0xf000ec4e
00000000000001e0: 0xf000ff53 0x00000000 0xf000ff53 0xf000ff53
00000000000001f0: 0xf000ff53 0xf000ff53 0xf000ff53 0xf000ff53

Não sei o que fazer com esses valores. Ele não se parece com uma tabela de descritores de interrupção (desreferenciar esses valores fornece todos os nulos). Então o que eu estou realmente olhando aqui?

    
por rhodeo 10.08.2018 / 01:13

3 respostas

8

O que quer que seu firmware tenha deixado.

Em um sistema moderno ideal, o processador nunca entra em modo real, como expliquei neste documento.

Como os modernos PCs com chip Intel de 64 bits executam o setor de inicialização? , o primeiro KiB da memória física é tão irrelevante quanto Johan Myréen chegou a ser em outra resposta aqui. Mas muitos firmwares modernos (ainda) têm suporte a compatibilidade , o que significa que

  • eles podem retroceder (sim, voltar , dado que foram diretamente do modo irreal para o modo protegido) do modo protegido para o modo real para executar softwares do sistema que são escritos em modo real, tais como programas de inicialização do estilo antigo PC / AT em MBRs e VBRs; e
  • eles fornecem as APIs de firmware do modo real antigo e configuram todas as estruturas de dados para essas APIs, das quais os softwares de sistemas mencionados anteriormente dependem.

Uma dessas estruturas de dados é o modo real IVT. As antigas APIs de firmware de modo real são baseadas em instruções int , e o IVT de modo real é preenchido pelo firmware como parte de sua inicialização com ponteiros para as diversas rotinas de manipulação de firmware para essas instruções.

Os softwares de sistema no modo protegido não precisam das APIs de firmware do modo real antigo e nunca executam o processador em modo real, portanto, o modo real IVT no primeiro 1 KiB de memória física não é utilizado. (o modo protegido v8086 não endereça o endereço físico 00000000 e para cima, lembre-se. Endereços lógicos 00000000 e para cima, que são traduzidos por tabelas de páginas.) Em sistemas EFI modernos, o firmware entrega um mapa de memória da memória física ao bootstrap do sistema operacional, informando quais partes estão reservadas ao firmware para suas próprias finalidades de API de modo protegido e quais partes do sistema operacional é livre para ir em frente e usar para seu pool de memória física. Em teoria, a primeira página da memória física pode estar na última categoria.

Na prática, primeiramente, os firmwares geralmente marcam a primeira página da memória física como "boot services code", significando que um sistema operacional pode reivindicá-lo e simplesmente usá-lo como parte de seu sistema operacional. pool de memória física, mas somente após os serviços de tempo de inicialização do firmware EFI foram encerrados pelo sistema operacional e o firmware foi reduzido para fornecer apenas seus serviços de tempo de execução. Um exemplo disso pode ser visto no log do kernel do Linux (com a opção add_efi_memmap ) mostrado por Finnbarr P. Murphy:

[ 0.000000] efi: mem00: type=3, attr=0xf, range=[0x0000000000000000-0x0000000000001000) (0MB)
que xe decodifica com outro programa em uma forma mais legível como:
[#00] Type: EfiBootServicesCode Attr: 0xF
      Phys: 0000000000000000-0000000000001000
      Virt: 0000000000000000-0000000000001000

Na prática, em segundo lugar, o Linux explicitamente ignora esse intervalo de memória física mesmo que o firmware diga que ele pode ser usado e usado. Você descobrirá isso tanto nos firmwares EFI quanto nos não-EFI, assim que o Linux tiver o mapa de memória física, ele corrige (em uma função chamada trim_bios_range ), resultando em mensagens de log do kernel como:

[    0.000000] e820: update [mem 0x00000000-0x00000fff] usable ==> reserved

Isto não é tanto para lidar com firmwares EFI modernos, onde o modo real IVT não faz parte da API de firmware, como é lidar com firmwares PC98 antigos, onde é parte da API de firmware, mas o relatório firmwares (através da mesma API) como memória física disponível para ser reescrita pelo sistema operacional.

Assim, enquanto que, teoricamente, a faixa de memória física poderia conter código ou dados arbitrários, dependendo das necessidades momentâneas dos alocadores de memória do kernel e da memória virtual paginada por demanda; na prática, o Linux simplesmente o deixa intacto, já que o firmware originalmente o configurou.

E no seu sistema, o firmware o preenchia com entradas IVT de modo real. Entradas de IVT em modo real são apenas 16:16 ponteiros distantes, é claro, e se você olhar para sua memória usando um hexdump de 2 bytes, você pode realmente ver isso claramente. Alguns exemplos:

  • A maioria de suas entradas de IVT apontam para F000: FF53, um endereço na área ROM de firmware de modo real. É provavelmente uma rotina fictícia que não faz nada mais do que um iret .
  • A entrada 1E do IVT aponta para F000: 6AA4, uma tabela na mesma área da ROM.
  • Entrada IVT 1F aponta para C000: 8930, uma tabela na área de firmware da ROM de vídeo em modo real.
  • A entrada IVT 43 aponta para C000: 6730, outra tabela na área de firmware da ROM de vídeo em modo real.

Leitura adicional

por 10.08.2018 / 13:42
5

A arquitetura original do processador 8086 (implementada como Real Mode nos processadores 80286+) não tem relevância para o Linux, que opera no Modo Protegido. Não há tabela de vetores de interrupção no endereço físico 0, em vez disso, é utilizada uma Tabela de Descritores de Interrupções contendo Descritores de Interrupção. O IDT pode estar localizado em qualquer lugar na memória.

O kernel do Linux obtém um mapa de memória física do firmware (BIOS ou EFI) que informa quais quadros da página de memória física são utilizáveis e quais estão reservados ou não presentes. O intervalo de quadros de página utilizáveis não é contíguo, mas normalmente possui grandes buracos. Tradicionalmente, o kernel do x86 Linux pulou o início da memória física, mesmo que esteja marcada como utilizável. Assim, o endereço físico 0 não é usado pelo kernel do Linux.

    
por 10.08.2018 / 09:01
4

Dumping memory

Aqui está uma maneira alternativa de despejar o conteúdo da memória dentro do sistema em vez de fazê-lo externamente:

$ head /dev/mem | hexdump -C
00000000  53 ff 00 f0 53 ff 00 f0  53 ff 00 f0 53 ff 00 f0  |S...S...S...S...|
00000010  53 ff 00 f0 53 ff 00 f0  cc e9 00 f0 53 ff 00 f0  |S...S.......S...|
00000020  a5 fe 00 f0 87 e9 00 f0  53 ff 00 f0 46 e7 00 f0  |........S...F...|
00000030  46 e7 00 f0 46 e7 00 f0  57 ef 00 f0 53 ff 00 f0  |F...F...W...S...|
00000040  22 00 00 c0 4d f8 00 f0  41 f8 00 f0 fe e3 00 f0  |"...M...A.......|
00000050  39 e7 00 f0 59 f8 00 f0  2e e8 00 f0 d4 ef 00 f0  |9...Y...........|
00000060  a4 f0 00 f0 f2 e6 00 f0  6e fe 00 f0 53 ff 00 f0  |........n...S...|
00000070  ed ef 00 f0 53 ff 00 f0  c7 ef 00 f0 ed 57 00 c0  |....S........W..|
00000080  53 ff 00 f0 53 ff 00 f0  53 ff 00 f0 53 ff 00 f0  |S...S...S...S...|
...
...
000afea0  00 00 00 00 00 00 00 00  aa aa aa 00 aa aa aa 00  |................|
000afeb0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000b0000  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
*
000c0000  55 aa 40 e9 62 0a 00 00  00 00 00 00 00 00 00 00  |[email protected]...........|
000c0010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 49 42  |..............IB|

Análise

A parte superior acima de 000c0000 pode estar relacionada ao bootloader. Por que eu suspeitaria disso? O código 55aah na localização 000c0000 geralmente pode ser uma marca na memória para coisas como um gatilho para o BIOS executar um bootloader secundário.

Referência: Boot Signature - BIOS

Noentanto,dadoqueeste55aahocorrenointervaloc0000h-effffh,émaisprovávelqueestapartesejaocabeçalhodeexpansãoPNP:

Referência: Especificação de inicialização do BIOS

3.3 Devices with PnP Expansion Headers

All IPL devices with option ROMs must contain a valid option ROM header that resides between system memory addresses C0000h and EFFFFh on a 2k boundary and begins with 55AAh. A Device’s booting can only be controlled if it has a PnP Expansion Header. The Expansion Header, whose address resides within the standard option ROM header at offset +1Ah, contains important information used to configure the device. It also contains pointers to code in the device’s option ROM (BCV or BEV) that the BIOS will call to boot from the device. See Appendix A for the structure of the PnP Expansion Header. There are two ways an IPL device with a PnP Expansion Header can be booted. It must contain a BCV or a BEV.

53ff ...

Quanto aos dados 53ffh que estão no começo. Não está claro para mim o que realmente é. Pesquisando mais, é provável que algo que o kernel do Linux escreveu lá após o bootloading da BIOS do MBR entregue ao kernel do Linux para inicializar.

Usually, the bootloader will load the kernel into memory, and then jump to the kernel. The kernel will then be able to reclaim the memory used by the bootloader (because it has already performed its job). However it is possible to include OS code within the boot sector and keep it resident after the OS begins

Aprofundando ainda mais, consegui encontrar este parágrafo em um artigo de pesquisa intitulado: Injeção de código mal-intencionado via / dev / mem :

1 The mem Device

/dev/mem is the driver interface to physically addressable memory. The original intent of both mem and kmem was for assisting in debugging the kernel. We can use the device like a regular character device, using lseek() to select an address offset. The kmem device is similar but provides an image of kernel memory in the context of virtual addressing. The Xorg server makes use of the mem device to access VESA video memory as well as the BIOS ROM Interrupt Vector Table (IVT) located at physical address 0x00000000 to manipulate video modes in VM86 mode. DOSEMU also uses this to access the BIOS IVT to be able to make BIOS Interrupts for various tasks (disk reads, printing to the console, etc).

Referências

por 10.08.2018 / 02:15

Tags