Quiero agregar una nueva llamada particular al sistema en el kernel 3.2.x de Linux pero como un módulo de kernel cargable (ya que no quiero volver a compilar el kernel una y otra vez)
Leí muchas publicaciones en Internet y también en SO, y algunos lugares afirman que la implementación de llamadas al sistema como módulos cargables no es posible, mientras que otros dicen que es posible.
Cual es ¿Cómo se hace si es posible?
ioctl()
s para la tarea, son fácilmente modularizables. Afaik, la razón principal detrás de hacer esto tan difícil como sea posible, es que el número de llamadas al sistema es algo altamente codificado y nadie quiere el caos en lo que podría aparecer en la imagen. Pero existen numerosas interfaces de kernel para alcanzar la misma funcionalidad, por ejemplo, sysfs, ioctls o similares.Respuestas:
No es posible porque la tabla de llamadas del sistema (llamada
sys_call_table
) es una matriz de tamaño estático. Y su tamaño está determinado en tiempo de compilación por el número de llamadas al sistema registradas. Esto significa que no hay espacio para otro.Puede verificar la implementación, por ejemplo, para la arquitectura x86 en el
arch/x86/kernel/syscall_64.c
archivo, dondesys_call_table
se define. Su tamaño es exactamente__NR_syscall_max+1
.__NR_syscall_max
se definearch/x86/kernel/asm-offsets_64.c
comosizeof(syscalls) - 1
(es el número de la última llamada al sistema), dondesyscall
hay una tabla con todas las llamadas al sistema.Una posible solución es reutilizar algunos
sys_setaltroot
números existentes (o obsoletos si su arquitectura tiene uno, ver por ejemplo) syscall con el suyo, ya que esto no requerirá más espacio en la memoria. Algunas arquitecturas también pueden tener agujeros en la tabla syscall (como la versión de 64 bits de x86) para que pueda usar esto también.Puede usar esta técnica si está desarrollando una nueva llamada al sistema y solo desea evitar reiniciar mientras experimenta. Tendrá que definir su nueva llamada al sistema, buscar la entrada existente en la tabla syscall y luego reemplazarla desde su módulo.
Hacer esto desde el módulo del núcleo no es trivial ya que el núcleo no se exporta
sys_call_table
a los módulos a partir de la versión 2.6 (la última versión del núcleo que tenía este símbolo exportado era2.5.41
).Una forma de evitar esto es cambiar su núcleo para exportar el
sys_call_table
símbolo a los módulos. Para hacer esto, debe agregar las siguientes dos líneaskernel/kallsyms.c
( no haga esto en máquinas de producción ):Otra técnica es encontrar la tabla syscall dinámicamente. Usted itera sobre la memoria del núcleo, comparando cada palabra con un puntero con la función conocida de llamada del sistema. Como conoce el desplazamiento de esta llamada al sistema en la tabla, puede calcular la dirección inicial de la tabla.
fuente
Lamentablemente, no puede agregar llamadas al sistema al núcleo como módulos cargables. Debe tomarse la molestia de compilar el núcleo cada vez que agrega una nueva llamada al sistema.
fuente