2011-05-10 9 views

Respuesta

0

Puede realizar las mismas tareas que modprobe y Co., pero dudo que pueda caracterizarse como limpiador.

1

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.

3

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.

+1

¿Crees que ... mediante el uso de fork y exec el proceso se vuelve más limpio para eliminar el módulo.? – kzs

9

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>.

11

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_moduleLinux system calls.

glibc no parece proporcionar una envoltura de C para ellos, por lo que solo creamos la nuestra con syscall.

insmod:

#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; 
} 

rmmod:

#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és try_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 con xmalloc_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.

Cuestiones relacionadas