GNU/Linux >> Znalost Linux >  >> Linux

Jak získat přístup k fyzickým adresám z uživatelského prostoru v Linuxu?

Soubor zařízení můžete namapovat do paměti uživatelského procesu pomocí mmap(2) systémové volání. Soubory zařízení jsou obvykle mapování fyzické paměti na systém souborů. V opačném případě musíte napsat modul jádra, který takový soubor vytvoří nebo poskytne způsob, jak namapovat potřebnou paměť na uživatelský proces.

Dalším způsobem je přemapování částí /dev/mem do uživatelské paměti.

Edit:Příklad mmapování /dev/mem (tento program musí mít přístup k /dev/mem, např. mít práva root):

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    if (argc < 3) {
        printf("Usage: %s <phys_addr> <offset>\n", argv[0]);
        return 0;
    }

    off_t offset = strtoul(argv[1], NULL, 0);
    size_t len = strtoul(argv[2], NULL, 0);

    // Truncate offset to a multiple of the page size, or mmap will fail.
    size_t pagesize = sysconf(_SC_PAGE_SIZE);
    off_t page_base = (offset / pagesize) * pagesize;
    off_t page_offset = offset - page_base;

    int fd = open("/dev/mem", O_SYNC);
    unsigned char *mem = mmap(NULL, page_offset + len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, page_base);
    if (mem == MAP_FAILED) {
        perror("Can't map memory");
        return -1;
    }

    size_t i;
    for (i = 0; i < len; ++i)
        printf("%02x ", (int)mem[page_offset + i]);

    return 0;
}

busybox devmem

busybox devmem je malý nástroj CLI, který mmapuje /dev/mem .

Můžete jej získat v Ubuntu s:sudo apt-get install busybox

Použití:čtení 4 bajtů z fyzické adresy 0x12345678 :

sudo busybox devmem 0x12345678

Napište 0x9abcdef0 na tuto adresu:

sudo busybox devmem 0x12345678 w 0x9abcdef0

Zdroj:https://github.com/mirror/busybox/blob/1_27_2/miscutils/devmem.c#L85

mmap MAP_SHARED

Při mmapování /dev/mem , pravděpodobně budete chtít použít:

open("/dev/mem", O_RDWR | O_SYNC);
mmap(..., PROT_READ | PROT_WRITE, MAP_SHARED, ...)

MAP_SHARED umožňuje zápisy do fyzické paměti okamžitě, což usnadňuje pozorování a dává větší smysl pro zápisy do hardwarových registrů.

CONFIG_STRICT_DEVMEM a nopat

Chcete-li použít /dev/mem Chcete-li zobrazit a upravit běžnou RAM na jádře v4.9, musíte nejprve:

  • zakázat CONFIG_STRICT_DEVMEM (výchozí nastavení na Ubuntu 17.04)
  • předejte nopat možnost příkazového řádku jádra pro x86

IO porty bez nich stále fungují.

Viz také:mmap /dev/mem selže s neplatným argumentem pro adresu virt_to_phys, ale adresa je zarovnána na stránku

Vyprázdnění mezipaměti

Pokud se pokusíte zapisovat do RAM místo do registru, může být paměť ukládána do mezipaměti CPU:Jak vyprázdnit mezipaměť CPU pro oblast adresního prostoru v Linuxu? a nevidím příliš přenosný/snadný způsob, jak to spláchnout nebo označit oblast jako necachovatelnou:

  • Jak zapsat paměť prostoru jádra (fyzickou adresu) do souboru pomocí O_DIRECT?
  • Jak vyprázdnit mezipaměť CPU pro oblast adresního prostoru v systému Linux?
  • Je možné alokovat v uživatelském prostoru blok paměti, který nelze uložit do mezipaměti v systému Linux?

Takže možná /dev/mem nelze spolehlivě použít k předávání vyrovnávacích pamětí zařízením?

To bohužel nelze v QEMU pozorovat, protože QEMU nesimuluje mezipaměti.

Jak to otestovat

Nyní k té zábavnější části. Zde je několik skvělých nastavení:

  • Paměť uživatele
    • přidělit volatile proměnná v uživatelském procesu
    • získáte fyzickou adresu pomocí /proc/<pid>/maps + /proc/<pid>/pagemap
    • upravte hodnotu na fyzické adrese pomocí devmem a sledujte reakci uživatelského procesu
  • Paměť Kernelland
    • přidělte paměť jádra pomocí kmalloc
    • získáte fyzickou adresu pomocí virt_to_phys a předat jej zpět uživatelské zemi
    • upravte fyzickou adresu pomocí devmem
    • dotaz na hodnotu z modulu jádra
  • IO paměť a zařízení virtuální platformy QEMU
    • vytvořte platformové zařízení se známými adresami fyzického registru
    • použijte devmem zapsat do registru
    • sledujte printf s vycházejí z virtuálního zařízení jako odpověď

Bonus:určení fyzické adresy pro virtuální adresu

Existuje nějaké API pro určení fyzické adresy z virtuální adresy v Linuxu?


Linux
  1. Jak přidat nebo odebrat uživatele ze skupiny v Linuxu

  2. Linux – Jak přihlásit uživatele do Tty z Ssh?

  3. Jak odebrat uživatele ze skupiny v Linuxu [Rychlý tip]

  1. Jak získat přístup ke sdílené složce Windows z Linuxu?

  2. Jak přistupovat (pokud je to možné) k prostoru jádra z uživatelského prostoru?

  3. Jak mmapovat vyrovnávací paměť linuxového jádra do uživatelského prostoru?

  1. Jak zjistit svou IP adresu v Linuxu

  2. Jak nastavit IP adresu z C v linuxu

  3. Jak zjistit využití uživatelské paměti v linuxu