Read/write files within a Linux kernel module Read/write files within a Linux kernel module c c

Read/write files within a Linux kernel module


You should be aware that you should avoid file I/O from within Linux kernel when possible. The main idea is to go "one level deeper" and call VFS level functions instead of the syscall handler directly:

Includes:

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

Opening a file (similar to 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;}

Close a file (similar to close):

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

Reading data from a file (similar to 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;}   

Writing data to a file (similar to 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;}

Syncing changes a file (similar to fsync):

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

[Edit] Originally, I proposed using file_fsync, which is gone in newer kernel versions. Thanks to the poor guy suggesting the change, but whose change was rejected. The edit was rejected before I could review it.


Since version 4.14 of Linux kernel, vfs_read and vfs_write functions are no longer exported for use in modules. Instead, functions exclusively for kernel's file access are provided:

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

Also, filp_open no longer accepts user-space string, so it can be used for kernel access directly (without dance with set_fs).