Lesen/Schreiben von Dateien innerhalb eines Linux-Kernelmoduls

Lesezeit: 4 Minuten

Benutzeravatar von Methos
Methoden

Ich kenne alle Diskussionen darüber, warum man Dateien nicht aus dem Kernel lesen/schreiben sollte, sondern wie man sie verwendet /proz oder Netzverbindung das zu tun. Ich will trotzdem lesen/schreiben. habe ich auch gelesen
Driving Me Nuts – Dinge, die Sie niemals im Kernel tun sollten.

Das Problem ist jedoch, dass 2.6.30 nicht exportiert sys_read(). Vielmehr ist es eingepackt SYSCALL_DEFINE3. Wenn ich es also in meinem Modul verwende, erhalte ich die folgenden Warnungen:

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

Offensichtlich insmod kann das Modul nicht laden, da die Verknüpfung nicht korrekt erfolgt.

Fragen:

  • Lesen/Schreiben im Kernel nach 2.6.22 (where sys_read()/sys_open() werden nicht exportiert)?
  • Im Allgemeinen, wie man in Makros verpackte Systemaufrufe verwendet SYSCALL_DEFINEn() aus dem Kernel?

Benutzeravatar von dmeister
Meister

Sie sollten sich bewusst sein, dass Sie Datei-I/O aus dem Linux-Kernel nach Möglichkeit vermeiden sollten. Die Hauptidee ist, „eine Ebene tiefer“ zu gehen und zu rufen Funktionen auf VFS-Ebene anstelle des Syscall-Handlers direkt:

Beinhaltet:

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

Datei öffnen (ähnlich open):

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

Schließen Sie eine Datei (ähnlich wie close):

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

Daten aus einer Datei lesen (ähnlich wie pread):

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

Daten in eine Datei schreiben (ähnlich 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;
}

Das Synchronisieren ändert eine Datei (ähnlich wie fsync):

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

[Edit] Ursprünglich schlug ich vor, file_fsync zu verwenden, das in neueren Kernel-Versionen weg ist. Danke an den armen Kerl, der die Änderung vorgeschlagen hat, dessen Änderung aber abgelehnt wurde. Die Änderung wurde abgelehnt, bevor ich sie überprüfen konnte.

  • Vielen Dank. Ich dachte daran, etwas Ähnliches zu tun, indem ich die sys_read/sys_open-Funktionalität repliziere. Aber das ist eine große Hilfe. Eine Kuriosität, gibt es eine Möglichkeit, Systemaufrufe zu verwenden, die mit SYSCALL_DEFINE deklariert wurden?

    – Methos

    26. Juli 2009 um 12:48 Uhr

  • Ich habe diesen Code in Kernel 2.6.30 (Ubuntu 9.04) ausprobiert und beim Lesen der Datei stürzt das System ab. Hatte jemand das gleiche Problem?

    – Enrico Detoma

    13. Oktober 2009 um 8:35 Uhr

  • @Enrico Detoma? Oh wow. Gibt es eine Möglichkeit, mir das Modul zu geben, das Sie verwendet haben? Noch nie gesehen?

    – Meister

    13. Oktober 2009 um 9:36 Uhr

  • Das wirft sofort die Frage auf, “warum machst du diesen FS-Tanz, übrigens”, die hier ganz nett beantwortet wird: linuxjournal.com/node/8110/print im Abschnitt “Reparieren des Adressraums”.

    – PypeBros

    24. August 2011 um 14:10 Uhr

  • @dmeister, Objekt nicht gefunden für Ihre Link-VFS-Level-Funktionen

    – uss

    1. April 2014 um 18:47 Uhr


Seit Version 4.14 des Linux-Kernels vfs_read und vfs_write Funktionen sind nicht mehr exportiert für den Einsatz in Modulen. Stattdessen werden Funktionen ausschließlich für den Dateizugriff des Kernels bereitgestellt:

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

Ebenfalls, filp_open akzeptiert keinen User-Space-String mehr, kann also für den Kernel-Zugriff verwendet werden direkt (ohne Tanz mit set_fs).

  • Welche Alternativen haben wir außer filp_open? Ich weiß, wir sollten keine Dateioperationen für Userspace-Dateien über den Kernel durchführen, aber sagen wir mal, wir wollen es.

    – Roi

    28. Mai um 11:41 Uhr

  • Das filp_open Funktion zugänglich ist. Warum möchten Sie stattdessen eine andere Funktion verwenden?

    – Zywarew

    28. Mai um 11:58 Uhr

  • Wenn ich versuche, eine Userspace-Datei zu öffnen, schlägt sie einfach fehl und behauptet, dass sie versucht hat, einen Nullzeiger zu dereferenzieren, wahrscheinlich weil sie nicht auf eine Datei zugreifen kann, die sich im Userspace-Bereich befindet. Z.B ~/.text

    – Roi

    28. Mai um 12:01 Uhr

  • Es gibt keine “Datei im Userspace-Bereich abgelegt”. Alle Dateien (auch die unter ~) werden im einzelnen Namensraum gespeichert. Aber die ~ ist das Konzept der Hülse: Dieses Zeichen wird von Kernel- und Nicht-Shell-Programmen nicht verarbeitet. Der Kernel ist sich nicht einmal des Home-Verzeichnisses eines Benutzers bewusst: Dieses Konzept wird vom User Space-Teil des Betriebssystems verwaltet. Um vom Kernel aus auf eine Datei im Home-Verzeichnis des Benutzers zuzugreifen, müssen Sie dieses Verzeichnis als “normalen” Pfad angeben. Z.B /home/tester/.text.

    – Zywarew

    28. Mai um 12:12 Uhr


  • ja ich meine ~/.text war nur ein Beispiel, jeder andere ABS-Pfad, den ich zur Verfügung stelle, scheint überhaupt nicht zu funktionieren, nach dem Debuggen scheint der Kernel abzubrechen dereferencing a null pointer und es ist in der Tat das erste Argument, das es verursacht, aber wenn du es sagst, dann ok.

    – Roi

    28. Mai um 12:16 Uhr

1422390cookie-checkLesen/Schreiben von Dateien innerhalb eines Linux-Kernelmoduls

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy