2011-10-11 11 views
5

Ho scritto diversi programmi e ho scoperto che quando compilato a 64 bit, il segmento di mappatura della memoria (dove sono conservati ad esempio oggetti condivisi e memoria condivisa) è sempre situato da qualche parte intorno a 7f9aca84a000-7fff88400000 ma mai esattamente lo stesso.ELF64/x86_64 e indirizzo iniziale del segmento di mappatura della memoria (per oggetti condivisi)

Vorrei sapere se esiste un indirizzo di avvio fisso per questo segmento di memoria su architettura x86_64 (ELF64) o qual è l'intervallo massimo e minimo per questo segmento?

Ecco perché faccio questa domanda. Stiamo migrando un sistema da Tru64 UNIX a Linux. Questo sistema utilizzava una mappatura complessa della memoria fissa della memoria condivisa di Sys V IPC e utilizza l'elenco concatenato per passare da una struttura all'altra all'interno di questo segmento. Con le dimensioni e la complessità di questo pezzo di codice e il tempo limitato a disposizione, stiamo cercando di trovare un modo efficace per correggere l'inizio della memoria condivisa (utilizzando in modo efficace shmat con un indirizzo specifico al quale allegare il segmento). Con 64 bit, lo spazio degli indirizzi virtuali è così grande (48bit indirizzi effettivamente possibili) che scegliere un indirizzo fisso "sicuro" è molto più facile e meno rischioso rispetto a 32 bit.

risposta

4

Il layout di mappatura della memoria x86-64 è definito in arch/x86/mm/mmap.c. Come puoi vedere, ci sono due strategie utilizzate: dall'alto verso il basso e dal basso verso l'alto.

L'assegnazione top-down è l'impostazione predefinita. Inizia a 128 MB al di sotto dell'estensione massima dello stack (come definito dallo stack rlimit), ottimizzato da un offset casuale e quindi assegna i mapping successivi verso il basso nella memoria da lì.

L'allocazione bottom-up è il fallback. Viene utilizzato se:

  • Il rlimit di stack è illimitato;
  • Il processo ha il set di personalità ADDR_COMPAT_LAYOUT; oppure
  • Il sysctl vm.legacy_va_layout non è zero.

Under allocazione bottom-up, regioni mappate vengono assegnati indirizzi progressivamente crescenti, a partire TASK_SIZE/3, ottimizzato da un offset casuale. TASK_SIZE su x86-64 è 0x800000000000, quindi le allocazioni bottom-up inizieranno intorno a 0x2AAAAAAAAAAA.

Vorrei suggerire un foro adatto per le mappature fisse che dovrebbe essere OK in entrambe le strategie di allocazione è intorno a 2 * TASK_SIZE/3 - Vorrei utilizzare 0x500000000000.

+0

Grazie per l'intuizione. Vado a dare un'occhiata a tutte le informazioni che mi hai indicato. – Huygens

+0

quindi non posso fornire il nostro indirizzo di partenza? – sdkie

3

Non ho una risposta diretta per voi (ancora!), Ma posso dire che ho avuto una memoria di mappatura di successo ben al di fuori delle gamme di memoria più alte. Per esempio:

#include <stdio.h> 
#include <sys/mman.h> 
#include <stdint.h> 

#define ADDRESS 0x700000000 

int main(int argc, char *argv[]) { 
    uint64_t *map = mmap((void *)ADDRESS, 4096, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); 

    map[0] = 64; 

    printf("Value: %lu\n", map[0]); 

    munmap(map, 4096); 

    return 0; 
} 

ho paura che non ho tempo di guardare attraverso i sorgenti del kernel in questo momento, ma sicuramente dare un'occhiata più tardi. Mi sono sempre chiesto quale fosse la risposta a questa domanda. . .

+0

Grazie per l'informazione, una tecnica simile è usata nel codice con System V IPC, abbiamo impostato un indirizzo speciale quando chiamiamo shmat. Vedere l'estratto della pagina man: Se shmaddr non è NULL e SHM_RND è specificato in shmflg, il collegamento avviene all'indirizzo uguale a shmaddr arrotondato al multiplo più vicino di SHMLBA. Altrimenti shmaddr deve essere un indirizzo allineato alla pagina in cui si verifica il collegamento. – Huygens

+0

La difficoltà è determinare un indirizzo corretto, come quello che si propone: 0x700000000. E vorremmo essere in grado di giustificare chiaramente la nostra scelta. – Huygens

4

C'è un indirizzo iniziale fisso per i segmenti mmaped?

No. Linux supporta ASLR (Address Space Layout Randomization), il che significa che gli indirizzi nei programmi hanno qualche elemento di casualità. Questo per rendere meno probabile l'exploit di alcuni exploit. Inoltre, probabilmente alcune patch del kernel implementano diverse strategie ASLR (lo fanno per x86 regolari), pensate a PaX, exec-shield, ...

Quindi, se si desidera utilizzare un indirizzo fisso si può ottenere usando MAP_FIXED , come raccomandato da @Ethereal.