2011-10-21 14 views
8

En un sistema x86, tengo un módulo de kernel de Linux ("módulo de vigilante") que recibe la notificación del kernel cada vez que se carga un módulo kernel particular ("objetivo"). Casi cualquier módulo kernel puede ser un objetivo. Uso esto en an instrumentation system en el que estoy trabajando.¿Hay alguna manera de que un módulo kernel encuentre direcciones de sección de otro módulo cargado?

Cuando el módulo del vigilante maneja tal notificación, podría ser conveniente por alguna razón, si el vigilante conocía las direcciones de las secciones ELF del módulo de destino cargado. ¿Alguna idea de cómo se puede obtener esta información en el espacio del kernel?

Por supuesto, probablemente podría obtener el contenido de los archivos apropiados en /sys/module/<target_name>/sections/ en el espacio de usuario tan pronto como se cargue el objetivo y de alguna manera pasar estos datos al módulo de observador, pero esto es demasiado torpe. Me gustaría encontrar una forma de obtener esta información directamente en el espacio del kernel.

Por lo que he visto en las fuentes del cargador de módulos, no almacena direcciones de sección en struct module, solo crea archivos sysfs para las secciones. ¿Puede ser posible encontrar de algún modo los objetos kernel correspondientes a esos archivos y leer los datos necesarios de estos objetos? ¿O probablemente use algún otro enfoque?

+0

Parece que el kobject contenía 'struct module' (' mkobj.kobj' field) participa en la representación del módulo en sysfs. Profundizaré en esto cuando tenga tiempo. Es posible acceder a los atributos que contienen los nombres y las direcciones de las secciones utilizando ese kobject como punto de partida. – Eugene

Respuesta

5

Después de investigar cómo la información sobre las secciones de un módulo entra en sysfs, no encontré la forma de recuperarla sin utilizar las definiciones de estructura internas del kernel. Usar tales cosas no es una opción en mi proyecto, así que finalmente he implementado otro enfoque, que es, con suerte, más confiable.

En resumen, la idea es la siguiente. Mi módulo kernel utiliza la API de ayudante en modo usuario para iniciar un proceso de espacio de usuario (un intérprete de comandos que ejecuta mi secuencia de comandos, en realidad). Ese proceso recibe el nombre del módulo kernel "objetivo" como parámetro y recopila la información sobre sus secciones de sysfs (/sys/module/<target_name>/sections/). Desde el espacio de usuario, esta información se puede obtener fácilmente. Después de eso, pasa los datos recopilados a mi módulo kernel como una cadena a través de un archivo en debugfs. El módulo analiza la cadena y valida su contenido. Si todo está bien, los nombres y las direcciones de inicio de las secciones ELF estarán disponibles.

Admito que el truco con el ayudante en modo usuario es bastante torpe pero hace el trabajo bien.

He preparado una implementación de ejemplo del enfoque descrito anteriormente - ver "Sections" example.

Para obtener más información sobre la API auxiliar del modo de usuario, consulte el código en <linux/kmod.c> y <linux/kmod.h> en las fuentes del kernel, es decir, la definición de call_usermodehelper(). Los ejemplos y la explicación del uso típico de la API están disponibles en this article.

Tenga en cuenta que los ejemplos de that article son un poco inexactos: la función init del módulo devuelve el resultado de call_usermodehelper() allí. Sin embargo, este último devuelve un código de estado de 2 bytes (al menos cuando se llama con UMH_WAIT_PROC) en lugar de 0 o un código de error negativo que se espera que devuelva la función init. Esto puede ocasionar advertencias de tiempo de ejecución. Lo que call_usermodehelper() realmente devuelve, se explica here.

1

El archivo linux/kernel/module.c tiene algunas funciones no estáticas (pero sin este EXPORT_SYMBOL al frente) como module_address_lookup(), pero estas funciones usan cosas como preempt_disable() y _enable(). Preferiría no utilizar estas funciones y sugeriría usar sysfs-interface en su lugar, aunque su controlador ya está en modo kernel.

+0

Gracias por la respuesta. Sí, sé sobre 'module_address_lookup()' y similares. Se utilizan en el sistema kallsyms para la búsqueda de símbolos y tal. Pero necesito algo diferente, las direcciones de las _sections_ del módulo (.text, .devinit.text, .exit.text, etc.) en lugar de símbolos. Puedo obtener las direcciones de las áreas "init" y "core" del módulo, pero cada una de ellas puede contener más de una sección ELF. – Eugene

+0

Parece del código fuente del cargador que para el momento en que se emiten las notificaciones de carga, la información sobre las secciones del módulo recién cargado solo está disponible en sysfs. Si no me equivoco, cada archivo en sysfs está respaldado por un objeto kernel. Si tiene una idea de cómo mi módulo podría encontrar esos objetos correspondientes a los archivos en '/ sys/module/', sería genial. – Eugene

+0

No veo forma de obtener esta información desde el kernel, a menos que modifique kernel/module.c para exportar un símbolo o función. Podría intentar enviar un parche con un mensaje razonable, por qué lo querría de esta manera. –

Cuestiones relacionadas