2011-11-25 15 views

risposta

15

L'implementazione di copy_from_user() dipende molto dall'architettura.

Su x86 e x86-64, esegue semplicemente una lettura diretta dall'indirizzo dello spazio utente e scrive sull'indirizzo kernelspace, mentre disabilita temporaneamente SMAP (Supervisor Mode Access Prevention) se è configurato. La parte più difficile è che il codice copy_from_user() viene inserito in una regione speciale in modo che il gestore degli errori di pagina possa riconoscere quando si verifica un errore al suo interno. Un errore di protezione della memoria che si verifica in copy_from_user() non uccide il processo come sarebbe se fosse attivato da qualsiasi altro codice di contesto del processo, o eseguisse il panico del kernel come sarebbe se si verificasse nel contesto di interruzione - riprende semplicemente l'esecuzione in un codice percorso che restituisce -EFAULT al chiamante.

+0

Grazie, ero sicuro di accedere direttamente dal kernel, quindi in pratica credo che faccia un controllo preliminare sul puntatore/indirizzo che viene passato su di esso in modo da controllare se qualche indirizzo non valido non viene passato alla funzione i voglio dire indirizzo appartenente ad un altro processo dello spazio utente ... in ogni caso non sapevo cosa fosse la protezione della memoria che hai menzionato .... Quindi il mio DOUBT è nel caso di copy_to_user ... poiché lo spazio dell'utente viene passato un indirizzo all'interno dello spazio del kernel VM .... come fa l'utente ad acccessarlo..oppure è che il kernel mappa quell'indirizzo ad un indirizzo dello spazio utente – Santi1986

+3

@ Santi1986: 'copy_to_user()' funziona esattamente nello stesso modo, tranne che gli indirizzi di origine e destinazione sono scambiati - legge dagli indirizzi del kernel e scrive negli indirizzi dello spazio utente. L'unico controllo che viene eseguito in entrambi è che l'indirizzo dello spazio utente sia * * * al di sotto della divisione kernel/utente; non è necessario verificare la presenza di indirizzi appartenenti ad altri processi utente, poiché 'copia _ * _ utente()' è chiamato solo nel contesto del processo, il che significa che * tutti * gli indirizzi sono o indirizzi del kernel o appartengono al processo corrente. – caf

+0

Grazie per il tuo tempo ho solo sfogliato il codice e ho scoperto che questo kernel controlla la validità dei puntatori tramite access_ok), fondamentalmente la funzione __copy _ * _ l'utente è chiamato che internamente usa questa funzione __copy _ * _ user_inatomic che alla fine chiama __copy __ * _ user_ll, che fa la copia di ATTUALI e anche le PAGINE SONO PRELIMINATE PRIMA DI COPIARE .... se l'intero dato non viene copiato è riempito con zero (dalla len passata alla chiamata) – Santi1986

1

L'implementazione della chiamata di sistema copy_from_user() viene eseguita utilizzando due buffer da diversi spazi di indirizzi.

  • Il buffer user-space in indirizzamento virtuale dell'utente.
  • Il buffer dello spazio del kernel all'indirizzo virtuale del kernel.

Quando viene richiamata la chiamata di sistema copy_from_user(), i dati vengono copiati dal buffer dell'utente al buffer del kernel.

Una parte (operazione di scrittura) del carattere codice del driver dispositivo in cui viene utilizzato copy_from_user() è il seguente:

ssize_t cdev_fops_write (struct file * vibrazione, const char __user * ubuf, conteggio size_t, loff_t * f_pos)

{

unsigned int *kbuf; 

copy_from_user(kbuf, ubuf, count); 

printk(KERN_INFO "Data: %d",*kbuf); 

}

+0

ok il mio dubbio con la tua risposta è che va bene per copy_from_user. .how bout copy_to_user dato che il kernel sta passando l'indirizzo dello spazio del kernel, come può un processo dello spazio utente accedervi ... fa sì che il kernel esegua un mapping precedente nello spazio utente VM in modo che l'utente possa accedervi da lì – Santi1986

7

per quanto riguarda "come bout copy_to_user dal momento che il kernel sta passando sull'indirizzo dello spazio del kernel, come può un processo dello spazio utente accedervi"

Un processo di spazio utente può tentare di accedere a qualsiasi indirizzo. Tuttavia, se l'indirizzo non è mappato nello spazio utente di quel processo (cioè nelle tabelle della pagina di quel processo) o se c'è un problema con l'accesso come un tentativo di scrittura in una posizione di sola lettura, viene generato un errore di pagina. Si noti che almeno su x86, ogni processo ha tutto lo spazio del kernel mappato nel più basso 1 gigabyte dello spazio di indirizzamento virtuale di quel processo, mentre i 3 gigabyte superiori dello spazio di indirizzamento totale da 4 GB (sto usando qui il classico a 32 bit caso) vengono utilizzati per il testo del processo (es. codice) e dati. Una copia da o verso lo spazio utente viene eseguita dal codice del kernel che è in esecuzione per conto del processo e in realtà è la mappatura della memoria (cioè le tabelle delle pagine) di quel processo che sono in uso durante la copia. Ciò avviene mentre l'esecuzione è in modalità kernel, vale a dire la modalità privilegiata/supervisore in linguaggio x86. Supponendo che il codice dello spazio utente abbia passato una posizione di destinazione legittima (ad es.un indirizzo correttamente mappato nello spazio di indirizzamento del processo) per fare in modo che i dati copiati, copy_to_user, eseguiti dal contesto del kernel siano in grado di scrivere normalmente su quell'indirizzo/area senza problemi e dopo che il controllo ritorna all'utente, lo spazio utente può anche leggere da questa impostazione della posizione dal processo stesso per iniziare. Ulteriori dettagli interessanti si possono trovare nei capitoli 9 e 10 di Understanding the Linux Kernel, 3rd Edition, di Daniel P. Bovet, Marco Cesati. In particolare, access_ok() è un controllo di validità necessario ma non sufficiente. L'utente può ancora passare indirizzi che non appartengono allo spazio degli indirizzi del processo. In questo caso, si verificherà un'eccezione di errore di pagina mentre il codice del kernel sta eseguendo la copia. La parte più interessante è come il gestore di errori della pagina del kernel determina che l'errore di pagina in questo caso non è dovuto a un bug nel codice del kernel ma piuttosto a un indirizzo errato dall'utente (specialmente se il codice del kernel in questione proviene da un modulo del kernel caricato).

1

La migliore risposta ha qualcosa che non va, copy_ (da | a) utente non può essere utilizzato in un contesto di interrupt, essi possono dormire, copiare (da | a) funzione utente può essere utilizzata solo nel contesto del processo, la tabella delle pagine del processo include tutte le informazioni a cui il kernel ha bisogno di accedervi, in modo che il kernel possa indirizzare l'accesso allo spazio utente se possiamo assicurarci che la pagina indirizzata sia in memoria, usa la funzione (da | a) _user, perché può controllarlo per noi e se la pagina indirizzata allo spazio utente non è residente, la risolverà direttamente per noi.

Problemi correlati