c - modprobe - kernel modules
Reemplazando la funcionalidad con módulos en kernel de Linux (13)
Dado que solo desea registrar las llamadas (es decir, no las anulará), y es aceptable una pequeña cantidad de cambios en el código del kernel, la forma más limpia sería agregar un gancho a cada función que le interese (usando un cadena de notificación o incluso un puntero de función simple). Entonces, su módulo simplemente se registra en todos los enganches que haya agregado (y se desmarca de ellos cuando se descarga).
También es muy posible que alguien más haya hecho el trabajo de agregar los ganchos para usted.
Sin entrar en los detalles de por qué , estoy buscando una manera limpia (como sea posible) para reemplazar las funciones del núcleo y las llamadas al sistema desde un módulo cargable. Mi idea inicial fue escribir un código para anular algunas funciones, que tomaría la función original (quizás, de ser posible, llame a la función) y luego agregue algo de mi propio código. La clave es que la función que escribo debe tener el nombre de la función original, para que otro código, al intentar acceder a ella, acceda a la mía en su lugar.
Puedo hacer esto fácilmente (comparativamente) directamente en el kernel simplemente lanzando mi código a las funciones apropiadas, pero me preguntaba si alguien sabía un poco de magia C que no es necesariamente una práctica de codificación kernel (o C) horrible que podría lograr el mismo resultado.
Me vienen a la cabeza los pensamientos de #defines y typedefs, pero no puedo hackearlos en mi cabeza.
En resumen: ¿alguien sabe cómo anular efectivamente las funciones en el kernel de Linux (desde un módulo)?
EDITAR: Dado que se me ha preguntado, esencialmente quiero registrar ciertas funciones (crear / eliminar directorios, etc.) desde dentro del kernel , pero por razones de cordura, un módulo cargable parece tener sentido, en lugar de tener que escribir un parche grande para el código del kernel y recompilar en cada cambio. Una cantidad mínima de código agregado al núcleo está bien, pero quiero descargar la mayor parte del trabajo a un módulo.
La mayoría del trabajo del sistema de archivos ya está hecho en módulos, suponiendo que el código del sistema de archivos se construyó como un módulo, en lugar de estar integrado en el kernel (lo que significa que la respuesta ''real'' depende de las opciones de compilación del kernel).
Suponiendo que los bits que desea registrar están relacionados con el sistema de archivos y que esas rutinas del sistema de archivos están compiladas como módulos, debería poder alterar los módulos del sistema de archivos que le interesan y volver a cargarlos.
Si esas suposiciones no son ciertas, o no pueden ser verdad, entonces las cosas claramente se vuelven más complicadas, y realmente no podría apuntar mucho más allá.
No desea modificar las llamadas al sistema existentes, quiere instrumentarlas. Esto es para lo que es SystemTap . Si realmente quieres hacerlo de la manera difícil e interceptar las llamadas al sistema codificando tu propio módulo, te sugiero que leas un poco de literatura de rootkits, pero no tengo ningún enlace a mano (aunque a phrack le viene a la mente).
No estoy del todo seguro de entender lo que quieres hacer, pero creo que ksplice puede ser una buena solución. Todavía está en desarrollo, así que no sé si está en algún tipo de condición utilizable en este momento.
Probablemente desee enganchar las llamadas al sistema (enlace PDF), lo que efectivamente le permitiría registrar procesos de usuario que llaman a las funciones del kernel. Si realmente desea registrar el uso del kernel de las funciones del kernel, debe buscar en el rastro de la función kernel .
Creo que puedes usar la auditoría para eso
Se ha realizado un gran trabajo en el kernel para garantizar que esto no ocurra, especialmente para no exponer la tabla de syscall a los módulos. El único mecanismo compatible para registrar el acceso a archivos es LSM , pero está orientado a la seguridad y tiene un futuro incierto. Aquí hay un PDF que documenta la API, pero puede no estar actualizado.
inotify es una forma mucho mejor de supervisar la creación, eliminación y modificación de archivos que tratar de subvertir las funciones de syscall del kernel, pero funciona desde el espacio de usuario.
Citado de Wikipedia ( http://en.wikipedia.org/wiki/Inotify ): Algunos de los eventos que se pueden monitorear son:
* IN_ACCESS - read of the file
* IN_MODIFY - last modification
* IN_ATTRIB - attributes of file change
* IN_OPEN and IN_CLOSE - open or close of file
* IN_MOVED_FROM and IN_MOVED_TO - when the file is moved or renamed
* IN_DELETE - a file/directory deleted
* IN_CREATE - a file/directory created
* IN_DELETE_SELF - file monitored is deleted
inotify existe en el núcleo desde 2.6.13, su predecesor es dnotify ( http://en.wikipedia.org/wiki/Dnotify ).
eche un vistazo a http://www.tldp.org/LDP/lkmpg/2.6/html/x978.html
De acuerdo con KernelTrap.org puedes hacer un parche simple y recompilar tu kernel para exportar la variable sys_call_table:
// add the following in the file arch/i386/kernel/i386_ksyms.c
extern void* sys_call_table[];
EXPORT_SYMBOL(sys_call_table);
Luego solo siga este procedimiento para reemplazar las llamadas al sistema desde la Guía de programación del Kernel Linux Kernel:
El código fuente aquí es un ejemplo de dicho módulo kernel. Queremos ''espiar'' a un determinado usuario e
printk()
un mensaje siempre que ese usuario abra un archivo. Con este fin, reemplazamos la llamada al sistema para abrir un archivo con nuestra propia función, llamadaour_sys_open
. Esta función verifica el uid (id del usuario) del proceso actual, y si es igual al uid queprintk()
, llama aprintk()
para mostrar el nombre del archivo que se abrirá. Entonces, de cualquier manera, llama a la función originalopen()
con los mismos parámetros, para abrir realmente el archivo.La función
init_module
reemplaza la ubicación apropiada ensys_call_table
y mantiene el puntero original en una variable. La funcióncleanup_module
usa esa variable para restaurar todo a la normalidad. Este enfoque es peligroso, debido a la posibilidad de que dos módulos kernel cambien la misma llamada al sistema. Imaginemos que tenemos dos módulos kernel, A y B. La llamada al sistemaopen
de A seráA_open
y B''sB_open
. Ahora, cuando se inserta A en el kernel, la llamada del sistema se reemplaza porA_open
, que llamará alsys_open
original cuando esté listo. A continuación, B se inserta en el kernel, que reemplaza la llamada del sistema conB_open
, que llamará a lo que cree que es la llamada original del sistema,A_open
, cuando esté listo.
Esto podría ser una lectura útil para usted.
Básicamente, dado que la tabla de llamadas del sistema no se exporta directamente en kernels más nuevos, debe realizar algunas búsquedas para determinar su ubicación usted mismo. Luego puede interceptar las llamadas de su sistema de elección y manipularlas. Sin embargo, reemplazar otras funciones del kernel será mucho más difícil, a menos que algunas de ellas estén organizadas de la misma manera que las llamadas al sistema (aparecen en alguna tabla de despacho, etc.), lo cual no es para nada común.
Me doy cuenta de que la pregunta tiene tres años, pero para beneficio de otras personas que intentan hacer este tipo de cosas, el núcleo tiene una interfaz llamada kprobes para hacer exactamente lo que necesitabas.
¿Has considerado implementar tu función usando LD_PRELOAD?
Su función se implementaría a través de una biblioteca compartida que viviría en un directorio especificado por la variable de entorno LD_PRELOAD.
La convención es que usted intercepta las llamadas al sistema y luego, después de realizar su magia, pasa la llamada al sistema real shlib. Pero no tienes que hacer eso.
Tal vez eche un vistazo al artículo " Construyendo intercaladores de biblioteca para divertirse y obtener ganancias ". Si bien es específico de Solaris, también es aplicable a Linux.
Por cierto, así es como funcionan la mayoría de las herramientas de análisis de memoria, por ejemplo, Purify.
Si las bibliotecas compartidas llaman a una llamada al sistema, se va a crear un módulo que altere esa llamada del sistema. Para obtener más información sobre cómo alterar las llamadas al sistema, es posible que desee consultar aquí http://www.xml.com/ldd/chapter/book/ hay algo allí sobre cómo cambian lo que llama el sistema open (). Un ejemplo está aquí http://tldp.org/LDP/lkmpg/x931.html