Autorizzazione exec imprevista da mmap quando i file assembly sono inclusi nel progetto

Autorizzazione exec imprevista da mmap quando i file assembly sono inclusi nel progetto

Linux ha un dominio di esecuzione chiamato READ_IMPLIES_EXEC , che fa sì che tutte le pagine siano allocate con PROT_READ da dare anche PROT_EXEC . Questo programma ti mostrerà se è abilitato per se stesso:

#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;
}

Se lo compili insieme a un .s vuoto file, vedrai che è abilitato, ma senza uno, sarà disabilitato. Il valore iniziale di questo deriva dalle meta-informazioni ELF nel tuo file binario. Esegui readelf -Wl example . Vedrai questa riga quando hai compilato senza il .s vuoto file:

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

Ma questo quando lo hai compilato:

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

Nota RWE anziché solo RW . La ragione di ciò è che il linker presuppone che i tuoi file assembly richiedano read-implies-exec a meno che non sia esplicitamente detto che non lo fanno, e se una parte del tuo programma richiede read-implies-exec, allora è abilitato per l'intero programma . I file assembly che GCC compila gli dicono che non ne ha bisogno, con questa riga (lo vedrai se compili con -S ):

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

Inserisci quella riga in example.s , e servirà a dire al linker che non ne ha nemmeno bisogno e il tuo programma funzionerà come previsto.


In alternativa alla modifica dei file assembly con varianti della direttiva di sezione specifiche di GNU, puoi aggiungere -Wa,--noexecstack alla riga di comando per la creazione di file di assieme. Ad esempio, guarda come lo faccio in configure di musl :

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

Credo che almeno alcune versioni di clang con l'assembler integrato potrebbero richiedere che venga passato come --noexecstack (senza il -Wa ), quindi il tuo script di configurazione dovrebbe probabilmente controllare entrambi e vedere quale è accettato.

Puoi anche usare -Wl,-z,noexecstack al momento del collegamento (in LDFLAGS ) per ottenere lo stesso risultato. Lo svantaggio di questo è che non aiuta se il tuo progetto produce statico (.a ) file di libreria per l'utilizzo da parte di altri software, poiché in tal caso non si controllano le opzioni del tempo di collegamento quando vengono utilizzati da altri programmi.