Leer/escribir archivos dentro de un módulo del kernel de Linux

4 minutos de lectura

avatar de usuario
métodos

Conozco todas las discusiones sobre por qué uno no debe leer/escribir archivos desde el kernel, sino cómo usar /proc o enlace de red Para hacer eso. Quiero leer/escribir de todos modos. yo también he leído
Volviendome loco: cosas que nunca debe hacer en el kernel.

Sin embargo, el problema es que 2.6.30 no exporta sys_read(). Más bien está envuelto en SYSCALL_DEFINE3. Entonces, si lo uso en mi módulo, recibo las siguientes advertencias:

WARNING: "sys_read" [xxx.ko] undefined!
WARNING: "sys_open" [xxx.ko] undefined!

Obviamente insmod no se puede cargar el módulo porque la vinculación no se realiza correctamente.

Preguntas:

  • Cómo leer/escribir dentro del kernel después de 2.6.22 (donde sys_read()/sys_open() no se exportan)?
  • En general, cómo usar llamadas al sistema envueltas en macro SYSCALL_DEFINEn() desde dentro del núcleo?

Desde la versión 4.14 del kernel de Linux, vfs_read y vfs_write las funciones son ya no se exporta para uso en módulos. En su lugar, se proporcionan funciones exclusivamente para el acceso a archivos del kernel:

# Read the file from the kernel space.
ssize_t kernel_read(struct file *file, void *buf, size_t count, loff_t *pos);

# Write the file from the kernel space.
ssize_t kernel_write(struct file *file, const void *buf, size_t count,
            loff_t *pos);

También, filp_open ya no acepta una cadena de espacio de usuario, por lo que se puede usar para acceder al kernel directamente (sin bailar con set_fs).

avatar de usuario
dmeister

Debe tener en cuenta que debe evitar la E/S de archivos desde el kernel de Linux cuando sea posible. La idea principal es ir “un nivel más profundo” y llamar Funciones de nivel VFS en lugar del controlador syscall directamente:

Incluye:

#include <linux/fs.h>
#include <asm/segment.h>
#include <asm/uaccess.h>
#include <linux/buffer_head.h>

Abriendo un archivo (similar a abrir):

struct file *file_open(const char *path, int flags, int rights) 
{
    struct file *filp = NULL;
    mm_segment_t oldfs;
    int err = 0;

    oldfs = get_fs();
    set_fs(get_ds());
    filp = filp_open(path, flags, rights);
    set_fs(oldfs);
    if (IS_ERR(filp)) {
        err = PTR_ERR(filp);
        return NULL;
    }
    return filp;
}

Cerrar un archivo (similar a cerrar):

void file_close(struct file *file) 
{
    filp_close(file, NULL);
}

Leer datos de un archivo (similar a preread):

int file_read(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size) 
{
    mm_segment_t oldfs;
    int ret;

    oldfs = get_fs();
    set_fs(get_ds());

    ret = vfs_read(file, data, size, &offset);

    set_fs(oldfs);
    return ret;
}   

Escribir datos en un archivo (similar a pwrite):

int file_write(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size) 
{
    mm_segment_t oldfs;
    int ret;

    oldfs = get_fs();
    set_fs(get_ds());

    ret = vfs_write(file, data, size, &offset);

    set_fs(oldfs);
    return ret;
}

La sincronización cambia un archivo (similar a fsync):

int file_sync(struct file *file) 
{
    vfs_fsync(file, 0);
    return 0;
}

[Edit] Originalmente, propuse usar file_fsync, que ya no está en las versiones más nuevas del kernel. Gracias al pobre tipo que sugirió el cambio, pero cuyo cambio fue rechazado. La edición fue rechazada antes de que pudiera revisarla.

  • Gracias. Estaba pensando en hacer algo similar replicando la funcionalidad sys_read/sys_open. Pero esta es una gran ayuda. Una curiosidad, ¿hay alguna forma de usar llamadas al sistema declaradas usando SYSCALL_DEFINE?

    – Métodos

    26 de julio de 2009 a las 12:48

  • Probé este código en el kernel 2.6.30 (Ubuntu 9.04) y leer el archivo bloquea el sistema. ¿Alguien experimentó el mismo problema?

    – Enrico Detoma

    13 de octubre de 2009 a las 8:35

  • @Enrico Detoma? Oh, vaya. ¿Hay alguna manera de que me puedas dar el módulo que usaste? ¿Nunca habías visto eso antes?

    – dmeister

    13 de octubre de 2009 a las 9:36

  • Eso plantea inmediatamente la pregunta de “¿por qué estás haciendo ese baile FS, por cierto?”, que se responde muy bien aquí: linuxjournal.com/node/8110/print en la sección “Reparación del espacio de direcciones”.

    – PypeBros

    24 de agosto de 2011 a las 14:10

  • @dmeister, Objeto no encontrado para las funciones de nivel VFS de su enlace

    – sree

    01/04/2014 a las 18:47


¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad