Domanda

Si consideri un driver Linux che usi get_user_pages (o get_page) per mappare le pagine del processo chiamante. L'indirizzo fisico delle pagine vengono poi passato a un dispositivo hardware. Sia il processo e il dispositivo può leggere e scrivere le pagine fino a quando le parti decidono di porre fine alla comunicazione. In particolare, la comunicazione può continuare ad utilizzare le pagine dopo la chiamata di sistema che chiama i rendimenti get_user_pages. La chiamata di sistema è in effetti la creazione di un zona di memoria condivisa tra il processo e il dispositivo hardware .

Sono preoccupato cosa succede se le chiamate di processo fork (che potrebbe essere un altro filo, e potrebbe capitare sia nella syscall che le chiamate get_user_pages è in corso o successiva). In particolare, se il genitore scrive per l'area di memoria condivisa dopo il bivio, quello che ne so io l'indirizzo fisico sottostante (presumibilmente cambiato a causa di copy-on-write)? Voglio capire:

  1. quali sono le esigenze del kernel da fare per difendersi da un processo potenzialmente comportamento anomalo (io non voglio creare un Sicurezza buco!);
  2. quali restrizioni alla necessità processo di obbedire in modo che il funzionalità del nostro autista funziona correttamente (vale a dire i resti memoria fisica mappati allo stesso indirizzo nel processo padre).

    • Idealmente, vorrei che il caso comune in cui il processo figlio non usa il nostro autista a tutti (probabilmente chiama exec quasi subito) al lavoro.
    • Idealmente, il processo genitore non dovrebbe prendere tutte le misure speciali quando assegnano la memoria, come abbiamo codice che passa un buffer di stack assegnata al driver esistente.
    • Sono consapevole di madvise con MADV_DONTFORK, e sarebbe ok per avere la memoria scompare dallo spazio del processo figlio, ma non è applicabile ad un buffer di stack-allocato.
    • “Non usare la forcella, mentre si dispone di una connessione attiva con il nostro autista” sarebbe fastidioso, ma accettabile come ultima risorsa, se il punto 1 è soddisfatto.

Sono disposto ad essere indicato documentazione o codice sorgente. Ho guardato in particolare a Linux Driver , ma non ho trovato questo problema affrontato. RTFS applicata alla anche solo la parte rilevante dei sorgenti del kernel è un po 'opprimente.

La versione del kernel non è completamente risolto, ma è una recente (diciamo ≥2.6.26). Siamo solo destinati a piattaforme ARM (singolo processore multicore finora, ma è proprio dietro l'angolo), se è importante.

È stato utile?

Soluzione

Un fork() non interferirà con get_user_pages():. get_user_pages() vi darà una struct page

Si avrebbe bisogno di kmap() prima di essere in grado di accedervi, e questa mappatura è fatto nello spazio del kernel, non userspace.

EDIT:. get_user_pages() toccare la tabella delle pagine, ma non si dovrebbe essere preoccupati per questo (ma solo assicurarsi che le pagine sono mappati in userspace), e ritorna -EFAULT se avesse alcun problema facendo in modo

Se fork (), finché non viene eseguita copy-on-write, il bambino sarà in grado di vedere che la pagina. Una volta copy-on-write è fatto (perché il bambino / il conducente / il genitore ha scritto sulla pagina attraverso la mappatura userspace - non il kmap kernel () il conducente deve), la pagina non sarà più condiviso. Se ancora in possesso di un kmap () nella pagina (nel codice del driver), non sarà in grado di sapere se si è in possesso della pagina genitore o del bambino.

1) Non è un buco nella sicurezza, perché una volta che execve (), tutto questo è andato.

2) Quando si fork () che si desidera sia di processo sia identico (Si tratta di una forchetta !!). Vorrei pensare che il vostro disegno dovrebbe consentire sia il genitore e il bambino per accedere al driver. Execve () saranno svuotati ogni cosa.

Che dire l'aggiunta di alcune funzionalità in userspace come:

 f = open("/dev/your_thing")
 mapping = mmap(f, ...)

Quando mmap () viene chiamato sul dispositivo, si installa una mappatura della memoria, con le bandiere speciali: http://os1a.cs.columbia.edu/lxr /source/include/linux/mm.h#071

Avete alcune cose interessanti come:

#define VM_SHARED       0x00000008
#define VM_LOCKED       0x00002000
#define VM_DONTCOPY     0x00020000      /* Do not copy this vma on fork */

VM_SHARED disabiliterà copy on write VM_LOCKED disabiliterà lo swapping in quella pagina VM_DONTCOPY dirà al kernel di non copiare la regione VMA sulla forcella, anche se non credo che sia una buona idea

Altri suggerimenti

La risposta breve è quella di utilizzare madvise(addr, len, MADV_DONTFORK) su eventuali buffer spazio utente si dà al driver. Questo dice al kernel che la mappatura non deve essere copiato da genitore a figlio e quindi non c'è vaccino.

Lo svantaggio è che il bambino eredita alcun mapping a tale indirizzo, quindi se si vuole che il bambino, per poi iniziare a utilizzare il driver avrà bisogno di rimappare quella memoria. Ma questo è abbastanza facile da fare in userspace.

Aggiorna :. Un buffer sullo stack è problematico, io non sono sicuro che si può renderlo sicuro in generale

Non è possibile contrassegnare che DONTFORK, perché il bambino potrebbe essere in esecuzione su quella pagina pila quando Forks, o (peggio ancora in un certo senso) si potrebbe fare un ritorno funzione più tardi e ha colpito la pagina di pila non mappata. (Ho anche provato questo, si può tranquillamente segnare il tuo DONTFORK pila, succedono cose brutte quando si forca).

L'altro modo per evitare una mucca è quello di creare una mappatura condivisa, ma non si può mappare il vostro stack condiviso per ovvi motivi.

Ciò significa che si rischia una mucca se forchetta. Anche se il bambino "appena" dirigenti potrebbe ancora toccare la pagina di stack e causare una mucca, che porta al genitore ottenere una pagina diversa, che è male.

Il punto di un minore a tuo favore è che il codice utilizzando un on-buffer dello stack deve solo preoccuparsi di codice che chiama forking, vale a dire. non è possibile utilizzare un buffer on-stack dopo la funzione è tornato. Quindi, avete solo bisogno di controllare le vostre callees, e se mai sborsare sei al sicuro, ma che ancora può essere fattibile, ed è fragile se il codice cambia mai.

Penso che si vuole veramente avere tutta la memoria che viene dato al driver di venire da un allocatore personalizzato in userspace. Non dovrebbe essere così invadente. L'allocatore può sia mmap il dispositivo direttamente, come l'altra risposta suggerita, o semplicemente usare mmap anonima, madvise(DONTFORK), e probabilmente mlock() per evitare di scambiare fuori.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top