GNU/Linux >> Znalost Linux >  >> Linux

Neočekávané oprávnění exec od mmap při zahrnutí souborů sestavy do projektu

Linux má spouštěcí doménu s názvem READ_IMPLIES_EXEC , což způsobí, že všechny stránky budou přiřazeny PROT_READ má být také uvedeno PROT_EXEC . Starší jádra Linuxu to používala pro spustitelné soubory, které používaly ekvivalent gcc -z execstack . Tento program vám ukáže, zda je tato funkce povolena:

#include <stdio.h>
#include <sys/personality.h>

int main(void) {
    printf("Read-implies-exec is %s\n", personality(0xffffffff) & READ_IMPLIES_EXEC ? "true" : "false");
    return 0;
}

Pokud to zkompilujete spolu s prázdným .s soubor, uvidíte, že je povoleno, ale bez něj bude zakázáno. Počáteční hodnota pochází z metainformací ELF ve vašem binárním souboru. Proveďte readelf -Wl example . Tento řádek uvidíte, když zkompilujete bez prázdného .s soubor:

  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW  0x10

Ale tohle, když jste s ním kompilovali:

  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RWE 0x10

Poznámka RWE místo pouze RW . Důvodem je to, že linker předpokládá, že vaše soubory sestavení vyžadují read-implies-exec, pokud není výslovně řečeno, že ne, a pokud některá část vašeho programu vyžaduje read-implies-exec, pak je povolena pro celý váš program. . Soubory sestavení, které GCC zkompiluje, mu tímto řádkem říkají, že to nepotřebuje (uvidíte to, pokud kompilujete s -S ):

    .section        .note.GNU-stack,"",@progbits

Výchozí oprávnění sekce nezahrnují ex ec. Viz část ELF .section dokumentaci pro význam „vlajek“ a @attributes.

(A nezapomeňte přepnout na jinou sekci, například .text nebo .data poté .section direktivu .s spoléhal na .text protože výchozí sekce v horní části souboru.)

Vložte tento řádek do example.s (a každý další .s soubor ve vašem projektu). Přítomnost tohoto .note.GNU-stack sekce bude sloužit k tomu, aby sdělil linkeru, že tento objektový soubor nezávisí na spustitelném zásobníku, takže linker použije RW místo RWE na GNU_STACK metadata a váš program pak bude fungovat podle očekávání.

Podobně pro NASM, section direktiva se správnými příznaky určuje nespustitelné zásobníky.

Moderní linuxová jádra mezi 5.4 a 5.8 změnila chování zavaděče programu ELF. Pro x86-64 se nic nezapne READ_IMPLIES_EXEC už Maximálně (s RWE GNU_STACK přidal ld ), získáte spustitelný samotný zásobník, ne každou čitelnou stránku. (Tato odpověď pokrývá poslední změnu v 5.8, ale před tím musely být jiné změny, protože tato otázka ukazuje úspěšné provedení kódu v .data na x86-64 Linux 5.4)

exec-all (READ_IMPLIES_EXEC ) dochází pouze u starších 32bitových spustitelných souborů, do kterých linker nepřidal GNU_STACK záhlaví vůbec. Ale jak je zde ukázáno, moderní ld vždy přidá, že s jedním nebo druhým nastavením, i když je vstup .o v souboru chybí poznámka.

Měli byste stále používat toto .note sekce pro signalizaci nespustitelných zásobníků v normálních programech. Ale pokud jste doufali, že otestujete samomodifikační kód v .data nebo následovat nějaký starý tutoriál pro testování shell kódu, to není na moderních jádrech možnost.


Jako alternativu k úpravě souborů sestavení pomocí variant direktiv sekce specifických pro GNU můžete přidat -Wa,--noexecstack do příkazového řádku pro vytváření souborů sestavy. Podívejte se například, jak to dělám v muslově configure :

https://git.musl-libc.org/cgit/musl/commit/configure?id=adefe830dd376be386df5650a09c313c483adf1a

Věřím, že alespoň některé verze clang s integrovaným-assemblerem mohou vyžadovat, aby byl předán jako --noexecstack (bez -Wa ), takže váš konfigurační skript by měl pravděpodobně zkontrolovat obojí a zjistit, která je přijata.

Můžete také použít -Wl,-z,noexecstack v čase odkazu (v LDFLAGS ), abyste dosáhli stejného výsledku. Nevýhodou tohoto je, že nepomůže, pokud váš projekt vytváří statický náboj (.a ) soubory knihovny pro použití jiným softwarem, protože pak neřídíte možnosti doby propojení, když je používán jinými programy.


Linux
  1. Facl Ignoruje oprávnění „x“, ale pouze u souborů?

  2. Když spustitelné soubory nejsou?

  3. Kam jdou soubory, když je vydán příkaz Rm?

  1. Co se přesně stane, když spustím soubor v prostředí Shell?

  2. Zrychlete rsync při migraci linuxového serveru z příkazového řádku

  3. Jak odstranit soubory .fuse_hidden*?

  1. Grep Word v souboru a pak zkopírujte soubor?

  2. Vzít první sloupec ze 2 souborů a zapsat ho do třetího souboru?

  3. Jak odstranit Bom ze souboru UTF-8?