Realization of File Read and Write in Linux Kernel Based on Kernel Module

tags: File system  linux

In the modules written for the linux kernel, the user space open, read, write, llseek and other functions are not available. Instead, its corresponding function in the kernel must be used. You can use filp->open with read/write in struct file to read and write files.
Directly upload dry goods (content yourself!):

example 1 :

filp->f_op->read
filp_open
filp->f_op->write

#include <linux/kernel.h> 
#include <linux/module.h> 
#include <linux/fs.h> 
#include <asm/uaccess.h> 
#include <linux/mm.h> 

MODULE_AUTHOR("[email protected]."); 
MODULE_DESCRIPTION("Kernel study and test."); 


void fileread(const char * filename) 
{ 
  struct file *filp; 
  struct inode *inode; 
  mm_segment_t fs; 
  off_t fsize; 
  char *buf; 
  unsigned long magic; 
  printk("<1>start....\n"); 
  filp=filp_open(filename,O_RDONLY,0); 
  inode=filp->f_dentry->d_inode;  
  
  magic=inode->i_sb->s_magic; 
  printk("<1>file system magic:%li \n",magic); 
  printk("<1>super blocksize:%li \n",inode->i_sb->s_blocksize); 
  printk("<1>inode %li \n",inode->i_ino); 
  fsize=inode->i_size; 
  printk("<1>file size:%i \n",(int)fsize); 
 Buf=(char *) kmalloc(fsize+1,GFP_ATOMIC);//Address of kernel space

  fs=get_fs(); 
 Set_fs(KERNEL_DS);//Set the address space to avoid checking
 Filp->f_op->read(filp,buf,fsize,&(filp->f_pos));//read into buf in kernel space
  set_fs(fs); 

  buf[fsize]='\0'; 
  printk("<1>The File Content is:\n"); 
  printk("<1>%s",buf); 


  filp_close(filp,NULL); 
} 

void filewrite(char* filename, char* data)
{
  struct file *filp; 
 mm_segment_t fs;
 filp = filp_open(filename, O_RDWR|O_APPEND, 0644);
 if(IS_ERR(filp))
    {
      printk("open error...\n"); 
      return;
        }   

  fs=get_fs();
  set_fs(KERNEL_DS);
  filp->f_op->write(filp, data, strlen(data),&filp->f_pos);
  set_fs(fs);
  filp_close(filp,NULL);
}

int init_module() 
{ 
  char *filename="/root/test1.c"; 

  printk("<1>Read File from Kernel.\n"); 
  fileread(filename); 
  filewrite(filename, "kernel write test\n");
  return 0; 
} 

void cleanup_module() 
{ 
  printk("<1>Good,Bye!\n"); 
} 


Example 2

#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/init.h>

#include<linux/types.h>

#include<linux/fs.h>
#include<linux/string.h>
#include<asm/uaccess.h> /* get_fs(),set_fs(),get_ds() */

#define FILE_DIR "/root/test.txt"

MODULE_LICENSE("GPL");
MODULE_AUTHOR("[email protected]");

char *buff = "module read/write test";
char tmp[100];

static struct file *filp = NULL;

static int __init wr_test_init(void)
{
    mm_segment_t old_fs;
    ssize_t ret;
    
    filp = filp_open(FILE_DIR, O_RDWR | O_CREAT, 0644);
    
    //    if(!filp)

    if(IS_ERR(filp))
        printk("open error...\n");
    
    old_fs = get_fs();
    set_fs(get_ds());
    
    filp->f_op->write(filp, buff, strlen(buff), &filp->f_pos);
    
    filp->f_op->llseek(filp,0,0);
    ret = filp->f_op->read(filp, tmp, strlen(buff), &filp->f_pos);
    
    set_fs(old_fs);
    
    if(ret > 0)
        printk("%s\n",tmp);
    else if(ret == 0)
        printk("read nothing.............\n");
    else 
        {
            printk("read error\n");
            return -1;
        }

    return 0;
}

static void __exit wr_test_exit(void)
{
    if(filp)
        filp_close(filp,NULL);
}

module_init(wr_test_init);
module_exit(wr_test_exit);


Makefile:

obj-m := os_attack.o

KDIR := /lib/modules/$(uname -r)/build/
PWD := $(shell pwd)

all:module

module:
        $(MAKE) -C $(KDIR) M=$(PWD) modules


clean:
        rm -rf *.ko *.mod.c *.o Module.* modules.* .*.cmd .tmp_versions

You can also use:
filp_open
vfs_wirte
vfs_read
Example:

   

 #include <linux/module.h>
    #include <linux/init.h>
    #include <linux/fs.h>
    #include <linux/uaccess.h>
Static charbuf[] =" ";
    static charbuf1[10];
     
    int __inithello_init(void)
    {
        struct file *fp;
        mm_segment_t fs;
        loff_t pos;
        printk("hello enter/n");
        fp =filp_open("/home/niutao/kernel_file",O_RDWR | O_CREAT,0644);
        if (IS_ERR(fp)){
            printk("create file error/n");
            return -1;
        }
        fs =get_fs();
        set_fs(KERNEL_DS);
        pos =0;
        vfs_write(fp,buf, sizeof(buf), &pos);
        pos =0;
        vfs_read(fp,buf1, sizeof(buf), &pos);
        printk("read: %s/n",buf1);
        filp_close(fp,NULL);
        set_fs(fs);
        return 0;
    }
    void __exithello_exit(void)
    {
        printk("hello exit/n");
    }
     
    module_init(hello_init);
    module_exit(hello_exit);
     
    MODULE_LICENSE("GPL");


Makefile:

ifneq ($(KERNELRELEASE),)
 obj-m:=extent_tree_test.o // modify here
else

#generate the path
CURRENT_PATH:=$(shell pwd)

#the absolute path
LINUX_KERNEL_PATH:=/lib/modules/$(shell uname -r)/build

#complie object
default:
        make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
clean:
        make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean
endif


Note:
Before calling filp->f_op->read and filp->f_op->write operations on the file, FS should be set first.
By default, filp->f_op->read or filp->f_op->write will check the pointer of the passed parameter buff. If it is not in user space, access will be denied. Because it is in the kernel module, the buff is definitely not in user space, so its addressing range must be increased.

Take filp->f_op->write as an example to illustrate:
filp->f_op->write will eventually call access_ok ==> range_ok.
and range_ok will determine whether the accessed address is between 0 and addr_limit. If it is, then ok, continue. If not, access is forbidden. The buff passed from the kernel space must be greater than addr_limit. So set_fs(get_ds()).
These functions are defined in asm/uaccess.h. The following are some of the contents of this header file:

#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })

#define KERNEL_DS MAKE_MM_SEG(-1UL)
#define USER_DS MAKE_MM_SEG(PAGE_OFFSET)

#define get_ds() (KERNEL_DS)
#define get_fs() (current_thread_info()->addr_limit)
#define set_fs(x) (current_thread_info()->addr_limit = (x))

#define segment_eq(a, b) ((a).seg == (b).seg)

You can see that set_fs(get_ds()) changes the value of addr_limit. In this way, the parameters passed in from the module can also be used normally.

When writing the test module, the function to be realized is to write something in, and then read it out and put it in the tmp array. But after writing, filp->f_ops is already at the end. At this time, nothing can be read. If you want to read the data, you should change the value of filp->f-ops, which requires filp- >f_op->llseek function. Checked on the Internet, the parameters need to be noted:

System call:
off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
offset is the offset.
If the origin is SEEK_SET(0), the displacement of the file is set to offset bytes from the beginning of the file.
If the origin is SEEK_CUR(1), the displacement of the file is set to its current value plus offset. The offset can be positive or negative.
If the origin is SEEK_END(2), the displacement of the file is set to the file length plus offset, and the offset can be positive or negative.

 

Intelligent Recommendation

Linux kernel module write method

table of Contents Nuclear module structure Two module compilation test 1 compilation 11 Makefile file writing 12 compilation method 2 loading module 3 uninstall module Three module parameters 1 C lang...

How to write a Linux kernel module

Overview The kernel module is running in the kernel space. Different from the application run in the user space, most kernel modules are drivers that complete the hardware device or bus, the file name...

Read and write process of EXT4 file system in Linux kernel system

table of Contents 1 Overview 2 Virtual file system and Ext4 file system 2.1 sys_write() code tracking 2.2 sys_write() process analysis 2.3 The core part of sys_write() vfs_write() 2.4 ext4_file_write(...

Linux kernel module compilation file

A kernel module is not a file that can be executed independently, but a target file that needs to be connected to the kernel at runtime. So, they need to be compiled with the -c option. Moreover, all ...

Linux kernel module configuration file

Take CentOS as an example: / boot / configure- * For the module configuration file of the current Linux kernel, that is, in the current Linux kernel, which modules have been enabled, which content has...

More Recommendation

[linux kernel] Self-built kernel module, and provide external access interface in the form of proc file, you can read kernel data by reading this file

Foreword: Divided from the memory area, the kernel area and the user area are separated. If a user mode program wants to interact with the kernel, there are several ways: 1) Through the system call ap...

Linux Kernel--Realization of Kernel-level Packet Filtering Firewall Based on Netfilter

Test kernel version: Linux Kernel 2.6.35 ---- Linux Kernel 3.2.1 Original works, please indicate For more, please see the column Author: Yan Ming Knowledge base: The development of this firewall is ba...

Read and write semaphores of the Linux kernel synchronization mechanism

The relationship between read and write semaphores and semaphores is similar to spin locks and read and write spin locks. Read and write semaphores may cause process blocking, but it allows N read exe...

Linux kernel synchronization method-read-write lock

Read-write spinlock One or more tasks can hold reader locks concurrently; on the contrary, the lock used for writing can only be held by one write task at most, and there can be no concurrent read ope...

Linux kernel memory read and write attribute changes

Under the arm system, the read and write restrictions of the kernel in earlier versions were not enabled, at least before version 4.4. But after 4.19, the kernel is enabled by default. There is a set_...

Copyright  DMCA © 2018-2026 - All Rights Reserved - www.programmersought.com  User Notice

Top