2011-10-21 14 views
8

Su un sistema x86, ho un modulo del kernel Linux ("modulo watcher") che viene notificato dal kernel ogni volta che viene caricato un particolare modulo del kernel ("target"). Quasi tutti i moduli del kernel possono essere un bersaglio. Lo uso in an instrumentation system su cui sto lavorando.Esiste un modo per un modulo del kernel per trovare gli indirizzi di sezione di un altro modulo caricato?

Quando il modulo Watcher gestisce tale notifica, potrebbe essere conveniente per qualche motivo, se l'osservatore conosceva gli indirizzi delle sezioni ELF del modulo di destinazione caricato. Qualche idea su come ottenere queste informazioni nello spazio del kernel?

Ovviamente potrei ottenere il contenuto dei file appropriati in /sys/module/<target_name>/sections/ nello spazio utente non appena il target viene caricato e quindi in qualche modo passare questi dati al modulo watcher ma questo è troppo maldestro. Mi piacerebbe trovare un modo per ottenere queste informazioni direttamente nello spazio del kernel.

Per quanto ho visto nei sorgenti del caricatore di moduli, non memorizza gli indirizzi di sezione in struct module, crea solo file sysfs per le sezioni. Può essere possibile trovare in qualche modo gli oggetti del kernel corrispondenti a quei file e leggere i dati necessari da questi oggetti? O probabilmente usi qualche altro approccio?

+0

Sembra che il kobject contenuto in 'struct module' (' mkobj.campo kobj') è coinvolto nella rappresentazione del modulo in sysfs. Approfondirò ulteriormente quando avrò tempo. Potrebbe essere possibile ottenere gli attributi contenenti i nomi e gli indirizzi delle sezioni usando quel kobject come punto di partenza. – Eugene

risposta

5

Dopo aver analizzato il modo in cui le informazioni sulle sezioni di un modulo entrano in sysfs, non ho trovato alcun modo per recuperarlo senza utilizzare le definizioni di struttura interne al kernel. L'utilizzo di queste cose non è un'opzione nel mio progetto, quindi ho finalmente implementato un altro approccio, che è, si spera, più affidabile.

In breve, l'idea è la seguente. Il mio modulo del kernel utilizza l'API helper in modalità utente per avviare un processo spazio utente (una shell che esegue il mio script, in realtà). Questo processo prende il nome del modulo del kernel "target" come parametro e raccoglie le informazioni sulle sue sezioni da sysfs (/sys/module/<target_name>/sections/). Dallo spazio utente, questa informazione può essere ottenuta facilmente. Dopo di ciò, passa i dati raccolti al mio modulo del kernel come una stringa tramite un file in debugfs. Il modulo analizza la stringa e ne convalida il contenuto. Se tutto è OK, saranno disponibili i nomi e gli indirizzi iniziali delle sezioni ELF.

Devo ammettere che il trucco con l'helper in modalità utente è piuttosto maldestro ma consente di completare il lavoro.

Ho preparato un esempio di implementazione dell'approccio sopra descritto - vedere "Sections" example.

Per i dettagli sull'API helper in modalità utente, consultare il codice in <linux/kmod.c> e <linux/kmod.h> nelle origini del kernel, ovvero la definizione di call_usermodehelper(). Gli esempi e la spiegazione dell'utilizzo tipico dell'API sono disponibili in this article.

Si noti che gli esempi da that article sono un po 'imprecisi: la funzione di inizializzazione del modulo restituisce il risultato di call_usermodehelper() lì. Quest'ultimo, tuttavia, restituisce il codice di stato a 2 byte (almeno quando chiamato con UMH_WAIT_PROC) anziché 0 o codice di errore negativo che si prevede che la funzione di init restituisca. Ciò potrebbe causare avvisi di runtime. Ciò che call_usermodehelper() restituisce effettivamente, viene spiegato here.

1

Il file linux/kernel/module.c ha alcune funzioni non statiche (ma senza questo EXPORT_SYMBOL in primo piano) come module_address_lookup(), ma queste funzioni usano cose come preempt_disable() e _enable(). Preferirei non usare queste funzioni e suggerirei di usare sysfs-interface, anche se il tuo driver è già in modalità kernel.

+0

Grazie per la risposta. Sì, conosco 'module_address_lookup()' e simili. Sono usati nel sistema kallsyms per la ricerca di simboli e così via. Ma ho bisogno di una cosa diversa, gli indirizzi delle _sections_ (.text, .devinit.text, .exit.text, ecc.) Del modulo piuttosto che i simboli. Posso ottenere gli indirizzi delle aree "init" e "core" del modulo ma ognuno di questi può contenere più di una sezione ELF. – Eugene

+0

Sembra dal codice sorgente del caricatore che al momento del rilascio delle notifiche di caricamento, le informazioni sulle sezioni del modulo appena caricato sono disponibili solo in sysfs. Se non sbaglio, ogni file in sysfs è supportato da un oggetto kernel. Se hai un'idea di come il mio modulo possa trovare tali oggetti corrispondenti ai file in '/ sys/module/', sarebbe fantastico. – Eugene

+0

Non vedo alcun modo per ottenere queste informazioni dal kernel, a meno che non si modifichi kernel/module.c per esportare un simbolo o una funzione. Potresti provare a inviare una patch con un messaggio ragionevole, perché dovresti farlo in questo modo. –

Problemi correlati