Newsgroup: it.comp.os.linux.development
Titolo: Scaricare modulo

Salve a tutti,
è la prima volta che metto mani sul kernel di linux e dovrei svolgere il 
seguente compito:
quando un modulo fa utilizzo di un puntatore nullo, questo deve essere 
scaricato.
Ho scritto un semplice modulo indipendente associato ad un dispositivo a 
caratteri che quando viene fatta richiesta di una read utilizza un puntatore 
nullo.
Leggendo nei sorgenti del kernel, il punto in cui dovrei modificare il 
codice è nella funzione
do_page_fault()
Mi serve però conoscere il nome del modulo (se di modulo si tratta) che ha 
provocato il fault e chiamare la funzione sys_delete_module().
Ho notato che quando c'è un oops il sistema stampa il contenuto dei registri 
e, tramite l' EIP riesce a risalire al nome del modulo. Avevo quindi pensato 
di fare la stessa cosa anche io, ma vi chiedo: esiste un modo più pulito per 
ottenere il nome del modulo che sta causando il fault?
Nel fare delle prove, per non ricompilare ogni volta il kernel, avevo 
pensato di provare le funzioni che mi restituiscono il nome del modulo 
(nello specifico la funzione kallsyms_lookup() ) all'interno del modulo, ma 
il linker mi dà errore dicendo simbolo sconosciuto.
Questa cosa non l'ho capita molto bene...avevo letto che tutti i simboli 
contenuti all'interno di /proc/kallsyms possono essere utilizzati e questa 
funzione c'è! Nel file kallsyms.c però non ho trovato la macro 
EXPORT_SYMBOL(kallsyms_lookup), come è possibile che c'è nel file 
proc/kallsyms?!
Avrei anche altre domande da fare, ma procederò per gradi.
La cosa importante che vorrei capire è proprio la risoluzione dei simboli!
Ad esempio, ho modificato il codice della do_page_fault e al suo interno ho 
chiamato la funzione kallsyms_lookup() oppure la sys_delete_module() e 
quando compila mi dà un warning "implicit declaration of function" ... 
perchè mi dà questa warning?
Chiedo scusa per la lunghezza del post, spero possiate chiarire i miei dubbi 
:)
Saluti. 

 provocato il fault e chiamare la funzione sys_delete_module().
Devi esportare la lista dei moduli (kernel/module.c), a questo punto sai
che ogni modulo inizia a ->module_core ed e' lungo ->core_size. Usando
l'indirizzo che ha generato il fault puoi trovare il modulo.
Non puoi usare sys_delete_module() perche' strncpy_from_user()
ritornerebbe -EFAULT (per via del check sull'address space).
Inoltre non sono sicuro che tu possa lockare la mutex del semafori ed
aspettare che il refcount vada a zero all'interno dell'handler (anzi,
direi decisamente che non puoi).
Puoi gestire il fault con un fixup sistemando l'eip (il problema e'
_dove_ impostarlo), ma poi comunque non riesci a scaricare il modulo
(visto che il risultato netto e' quello di troncare l'esecuzione di una
funzione).
Puoi certamente scaricare "brutalmente" il modulo, ma gli effetti
collaterali sono molti:
- il resto del kernel ha ancora riferimenti al modulo (prima o poi ti
  becchi un OOPS)
- se il modulo stava eseguendo una chiamata da userspace il processo
  rimane bloccato (puoi forse rimediare con il fixup, tornando in
  userspace)
- se il modulo controllava hardware puo' succedere un po' di tutto: bus
  PCI lockato e macchina morta, DMA che scrive a caso, fault
  nell'interrupt handler (e questo e' molto divertente)
Se la tua idea e' la fault tollerance direi che crei solo altri problemi
;)
Luca
-- 
"I've seen things you people wouldn't believe...
 Attack Ships on fire off the shores of Orion.
 I've watched C-beams glitter in the dark off of Tanhauser Gate.
 All those moments will be lost in time...like tears, in rain.
 Time to die." -- Roy Batty (played by Rutger Hauer)

 ha scritto nel messaggio 
news:ei8n94$etb$1...@dreamland.darkstar.lan...

Ciao,
hai colto nel segno, l'idea è la fault tollerance!
Mi è stato assegnato come lavoro per la tesi triennale e devo portarlo a
termine in questo mese.
In effetti leggendo da alcuni libri e leggendo il codice nel kernel mi sono
accorto che ci sono troppe cose che non vanno e che effettivamente, come hai
detto tu, creo solamente altri problemi.
Nel mio caso però mi limito ad un semplice driver che ha un bug in una zona
non molto critica, ossia che quando viene fatta la release() e la exit() del
modulo non rimane nessun problema. Nessuna dipendenza ad altri moduli e, per
adesso, con un solo processo attaccato per volta.
Non è una cosa proprio utilissima, ma gestire un bug del genere è una
problematica molto ampia e dipende da tantissimi fattori (o almeno
credo...per quel poco che so).
Ritornando a noi:
Avevo cmq pensato di modificare la do_exit():
do_page_fault() dopo aver stampato il messaggio di errore sul puntatore
nullo chiama la funzione die().
die() stampa il contenuto dei registri e tramite la funzione print_symbol()
e correlate, mi riesce ad individuare il nome del modulo (tramite quelle
funzioni quindi riesco a trovare il nome del modulo dall'indirizzo EIP).
L'ultima operazione di die() è do_exit(SIGSEGV);
La do_exit() chiama una serie di funzioni di uscita e, debuggando, ho
scoperto che mi rilascia il dispositivo (e quindi il driver) dopo la
__exit_files().
A questo punto, visto che il modulo è stato rilasciato posso scaricarlo dal
kernel, ma, come hai detto tu, la funzione sys_delete_module() mi
ritorna -EFAULT!!!
strncpy_from_user si aspetta una stringa dallo user_space...mmm...ho visto
la funzione, ma è in assembly e ancora non ho chiarissimo il concetto di
user_space (devo approfondire).
Seguendo questa strada come potrei fare? Dovrei far pervenire alla funzione
una stringa dallo user_space...in che modo?
Magari sfruttando lo spazio del processo che si sta terminando?
Non so se sto sparando stupidaggini...qualche dritta?
Grazie per l'aiuto!

 Magari sfruttando lo spazio del processo che si sta terminando?
No, meglio replicare la logica della sys_delete_module() in una funzione
ad hoc.
Questa e' la teoria, in pratica devi verificare che sia effettivamente
possibile fare tutto questo dal fault handler (in particolare devi
controllare il protocollo di locking).
Luca
-- 
"Ci sono le balle, le megaballe e le statistiche".
 Mark Twain