Tengo una aplicación que tiene dos módulos de kernel externos y un daemon de espacio de usuario. Quiero cargar los módulos desde el código del daemon, escritos en C, al inicio, y descargarlos en la salida de limpieza. ¿Puedo cargarlos de una manera más limpia que haciendo system("modprobe module");
y descargarlos usando el rmmod
correspondiente?¿Cómo se pueden cargar los módulos del kernel de Linux desde el código C?
Respuesta
Puede realizar las mismas tareas que modprobe
y Co., pero dudo que pueda caracterizarse como limpiador.
No estoy seguro de que haya limpiador manera que system
.
Pero, por supuesto, si desea cargar/descargar los módulos de su daemon de espacio de usuario, entonces se fuerza a ejecutar el daemon como root *, que puede no considerarse seguro.
*: o puede agregar los comandos explícitos en el archivo sudoers, pero esto será una pesadilla para administrar al implementar su aplicación.
lo recomiendo contra el uso de system()
en cualquier código de demonio que se ejecuta con permisos de root, ya que es relativamente fácil de explotar desde el punto de vista de la seguridad. modprobe
y rmmod
son, de hecho, las herramientas adecuadas para el trabajo. Sin embargo, sería un poco más limpio y mucho más seguro usar un fork()
+ exec()
explícito para invocarlos.
insmod/rmmod utilizar las funciones init_module
y delete_module
Para ello, que tienen también un hombre páginas disponibles. Ambas declaran las funciones como extern
en lugar de incluir un encabezado, pero la página man dice que deberían estar en <linux/module.h>
.
Minimal ejemplo runnable
probado en un QEMU + Buildroot VM y Ubuntu 16.04 anfitrión with this simple parameter printer module.
Utilizamos init_module
y remove_module
Linux system calls.
glibc no parece proporcionar una envoltura de C para ellos, por lo que solo creamos la nuestra con syscall
.
#define _GNU_SOURCE
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts)
int main(int argc, char **argv) {
const char *params;
int fd;
size_t image_size;
struct stat st;
void *image;
if (argc < 2) {
puts("Usage ./prog mymodule.ko [args]");
return EXIT_FAILURE;
}
if (argc < 3) {
params = "";
} else {
params = argv[2];
}
fd = open(argv[1], O_RDONLY);
fstat(fd, &st);
image_size = st.st_size;
image = malloc(image_size);
read(fd, image, image_size);
close(fd);
if (init_module(image, image_size, params) != 0) {
perror("init_module");
return EXIT_FAILURE;
}
free(image);
return EXIT_SUCCESS;
}
#define _GNU_SOURCE
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#define delete_module(name, flags) syscall(__NR_delete_module, name, flags)
int main(int argc, char **argv) {
if (argc != 2) {
puts("Usage ./prog mymodule");
return EXIT_FAILURE;
}
if (delete_module(argv[1], O_NONBLOCK) != 0) {
perror("delete_module");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
interpretación fuente Busybox
Busybox ofrece insmod
, y ya que está diseñado por el minimalismo, podemos tratar de deducir cómo se se hace desde allí.
En la versión 1.24.2, el punto de entrada está en modutils/insmod.c
función insmod_main
.
El IF_FEATURE_2_4_MODULES
es un soporte opcional para los módulos más antiguos de Linux kernel 2.4, por lo que podemos ignorarlo por el momento.
Eso solo lo remite a modutils.c
función bb_init_module
.
bb_init_module
intenta dos cosas:
mmap
el archivo a la memoria a travéstry_to_mmap_module
.Esto siempre establece
image_size
al tamaño del archivo.ko
como efecto secundario.si eso falla,
malloc
el archivo en la memoria conxmalloc_open_zipped_read_close
.Esta función opcionalmente descomprime el archivo primero si es un archivo comprimido, y lo malloc de lo contrario.
No entiendo por qué se realiza este negocio de compresión, ya que no podemos confiar en él porque el
try_to_mmap_module
no parece descomprimir las cosas.
Por fin llega la llamada:
init_module(image, image_size, options);
donde image
es el ejecutable que se puso en la memoria, y las opciones son sólo ""
si llamamos insmod file.elf
sin más argumentos.
init_module
se proporciona por encima de:
#ifdef __UCLIBC__
extern int init_module(void *module, unsigned long len, const char *options);
extern int delete_module(const char *module, unsigned int flags);
#else
# include <sys/syscall.h>
# define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts)
# define delete_module(mod, flags) syscall(__NR_delete_module, mod, flags)
#endif
ulibc
es una implementación de libc incrustado, y parece proporcionar init_module
.
Si no está presente, creo que glibc se supone, sino como man init_module
dice:
El init_module() llamada al sistema no es compatible con glibc. No se proporciona ninguna declaración en los encabezados de glibc, pero, a través de un capricho de la historia, glibc exporta un ABI para esta llamada al sistema. Por lo tanto, para emplear esta llamada al sistema, es suficiente declarar manualmente la interfaz en su código; alternativamente, puede invocar la llamada al sistema usando syscall (2).
BusyBox sabiamente sigue ese consejo y utiliza syscall
, que proporciona glibc, y que ofrece una API C para llamadas al sistema.
- 1. Cómo recargar los módulos kernel modificados
- 2. ¿Cómo cargar automáticamente un módulo kernel en Gentoo Linux?
- 3. Cómo usar ioctl() desde el espacio del kernel en Linux?
- 4. Módulos de kernel de Linux - ¿riesgo de seguridad?
- 5. ¿Cómo sabe Linux Kernel dónde buscar el firmware del controlador?
- 6. Cómo reiniciar el teléfono Android desde el código del kernel
- 7. ¿Cómo se pueden evitar los duplicados de módulos con MEF?
- 8. Exporte correctamente los Encabezados de Linux, Módulos
- 9. Cómo comenzar con el desarrollo del kernel de Linux
- 10. ¿Cómo detener los hilos del kernel de Linux en rmmod?
- 11. Programación del kernel de Linux
- 12. desarrollo del kernel de Linux
- 13. módulo del kernel Linux compilar
- 14. ¿Cómo incluir C backtrace en un código de módulo kernel?
- 15. ¿Los módulos pueden tener propiedades?
- 16. Acceda a los símbolos del kernel de Linux que no se exportan a través de EXPORT_SYMBOL *
- 17. Cómo limpiar los cachés utilizados por el kernel de Linux
- 18. Debug-info para módulos de kernel cargables
- 19. Módulos que se pueden llamar
- 20. ¿Cómo configuro el kernel de Linux dentro de Buildroot?
- 21. ¿Cómo se lee el búfer de anillo dentro del espacio del kernel de Linux?
- 22. Cómo codificar un módulo kernel de Linux?
- 23. Herramientas de refactorización de código para C, ¿se pueden usar en GNU/Linux? Se prefiere FOSS
- 24. Organización de los encabezados kernel de Linux
- 25. Inserte y elimine mediante programación módulos kernel en C
- 26. ¿Qué significa "EXPORT_SYMBOL" en el código de kernel de Linux?
- 27. ¿Impresiones de depuración del kernel de Linux?
- 28. ¿Cómo elimino los símbolos locales del módulo del kernel de Linux sin romperlo?
- 29. ¿Cómo distribuir módulos kernel usando un RPM?
- 30. Símbolo exportado del kernel de Linux
¿Crees que ... mediante el uso de fork y exec el proceso se vuelve más limpio para eliminar el módulo.? – kzs