GNU/Linux >> Linux Esercitazione >  >> Linux

Proibisci gli accessi alla memoria non allineati su x86/x86_64

Sia GCC che Clang hanno UndefinedBehaviorSanitizer integrato. Uno di questi controlli, alignment , può essere abilitato con -fsanitize=alignment . Emetterà codice per controllare l'allineamento del puntatore in fase di esecuzione e si interromperà se i puntatori non allineati vengono dereferenziati.

Consulta la documentazione online all'indirizzo:

  • https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html

È complicato e non l'ho fatto personalmente, ma penso che tu possa farlo nel modo seguente:

Le CPU x86_64 (in particolare ho controllato Intel Corei7 ma immagino anche altre) hanno un contatore delle prestazioni MISALIGN_MEM_REF che contrasta i riferimenti di memoria disallineati.

Quindi, prima di tutto, puoi eseguire il tuo programma e utilizzare lo strumento "perf" sotto Linux per ottenere un conteggio del numero di accessi disallineati che il tuo codice ha effettuato.

Un hack più complicato e interessante sarebbe scrivere un modulo del kernel che programmi il contatore delle prestazioni per generare un interrupt in caso di overflow e farlo traboccare dal primo carico/archivio non allineato. Rispondi a questo interrupt nel modulo del kernel ma invia un segnale al tuo processo.

Questo, in effetti, trasformerà x86_64 in un core che non supporta l'accesso non allineato.

Non sarà semplice però:oltre al tuo codice, anche le librerie di sistema utilizzano accessi non allineati, quindi sarà complicato separarli dal tuo codice.


Ho appena letto la domanda L'accesso non allineato alla memoria causa sempre errori del bus? che rimandava all'articolo di Wikipedia Segmentation Fault.

Nell'articolo, c'è un meraviglioso promemoria dei flag del processore Intel piuttosto insoliti AC, ovvero Alignment Check.

Ed ecco come abilitarlo (dall'esempio Bus Error di Wikipedia, con un bug clobber della zona rossa corretto per x86-64 System V, quindi è sicuro su Linux e MacOS e convertito da Basic asm che non è mai una buona idea all'interno delle funzioni:vuoi che le modifiche ad AC siano ordinate rispetto agli accessi alla memoria.

#if defined(__GNUC__)
# if defined(__i386__)
    /* Enable Alignment Checking on x86 */
    __asm__("pushf\n orl $0x40000,(%%esp)\n popf" ::: "memory");
# elif defined(__x86_64__) 
     /* Enable Alignment Checking on x86_64 */
    __asm__("add $-128, %%rsp \n"    // skip past the red-zone, in case there is one and the compiler has local vars there.
            "pushf\n"
            "orl $0x40000,(%%rsp)\n"
            "popf \n"
            "sub $-128, %%rsp"       // and restore the stack pointer.
           ::: "memory");       // ordered wrt. other mem access
# endif
#endif

Una volta abilitato, funziona in modo molto simile alle impostazioni di allineamento ARM in /proc/cpu/alignment , vedi risposta Come intrappolare l'accesso alla memoria non allineato? per esempi.

Inoltre, se stai usando GCC, ti suggerisco di abilitare -Wcast-align avvertimenti. Quando si costruisce per un target con severi requisiti di allineamento (ad esempio ARM), GCC riporterà le posizioni che potrebbero portare a un accesso alla memoria non allineato.

Ma si noti che l'asm scritto a mano di libc per memcpy e altre funzioni effettuerà comunque accessi non allineati, quindi l'impostazione AC spesso non è pratica su x86 (incluso x86-64). GCC a volte emetterà asm che effettua accessi non allineati anche se la tua fonte non lo fa, ad es. come ottimizzazione per copiare o azzerare due elementi array o membri struct adiacenti contemporaneamente.


Linux
  1. Misurare l'utilizzo della RAM di un programma?

  2. Killer di memoria insufficiente di Linux

  3. Monitoraggio e gestione della memoria

  4. Diagnostica di Windows con memoria insufficiente

  5. Cos'è ioremap()

Utilizzo della memoria di Linux

Che cos'è la NVM (memoria non volatile)?

Come cancellare la memoria di scambio in Linux

Utilizzo della memoria dei comandi TOP

Memoria inattiva di Linux

Perché i numeri di chiamata del sistema Linux in x86 e x86_64 sono diversi?