其他设备驱动程序:无法通过open()系统调用打开设备 [英] Miscellaneous Device Driver: Unable to open the device with open() system call

查看:87
本文介绍了其他设备驱动程序:无法通过open()系统调用打开设备的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过内核模块为sys_open()调用实现系统调用拦截,为此,我定义了可作为内核模块插入的其他设备驱动程序MyDevice.下面是我的内核模块的代码:

I am trying to implement a system call interception for sys_open() call via kernel module and for that I have defined a miscellaneous device driver MyDevice which can be inserted as kernel module. Below is the code for my kernel module:

#include <linux/version.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/highmem.h>
#include <asm/unistd.h>

MODULE_LICENSE("GPL");

// IOCTL commands
#define IOCTL_PATCH_TABLE 0x00000001
#define IOCTL_FIX_TABLE 0x00000004

//Global variables
int in_use = 0; //set to 1 in open handler and reset to zero in release handler
int is_set = 0; // flag to detect system call interception
unsigned long *sys_call_table = (unsigned long*)0xffffffff81801400; //hard coded address of sys_call_table from /boot/System.map

//function pointer to original sys_open
asmlinkage int (*real_open)(const char* __user, int, int);

//Replacement of original call with modified system call
asmlinkage int custom_open(const char* __user file_name, int flags, int mode)
{
    printk("interceptor: open(\"%s\", %X, %X)\n", file_name,flags,mode);
    return real_open(file_name,flags,mode);
}

/*
Make the memory page writable
This is little risky as directly arch level protection bit is changed
*/
int make_rw(unsigned long address)
{
    unsigned int level;
    pte_t *pte = lookup_address(address, &level);
    if(pte->pte &~ _PAGE_RW)
        pte->pte |= _PAGE_RW;
    return 0;
}

/* Make the page write protected */
int make_ro(unsigned long address)
{
    unsigned int level;
    pte_t *pte = lookup_address(address, &level);
    pte->pte = pte->pte &~ _PAGE_RW;
    return 0;
}

/* This function will be invoked each time a user process attempts
       to open my device. You should keep in mind that the prototype
      of this function may change along different kernel versions. */
static int my_open(struct inode *inode, struct file *file)
{
    /*Do not allow multiple processes to open this device*/
    if(in_use)
        return -EBUSY;
    in_use++;
    printk("MyDevice opened\n");
    return 0;
}

/* This function, in turn, will be called when a process closes our device */
static int my_release(struct inode *inode, struct file *file)
{
    in_use--;
    printk("MyDevice closed\n");
    return 0;
}

/*This static function handles ioctl calls performed on MyDevice*/
static int my_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    int retval = 0;

    switch(cmd)
   {
      case IOCTL_PATCH_TABLE:
         make_rw((unsigned long)sys_call_table);
         real_open = (void*)*(sys_call_table + __NR_open);
         *(sys_call_table + __NR_open) = (unsigned long)custom_open;
         make_ro((unsigned long)sys_call_table);
         is_set=1;
         break;
      case IOCTL_FIX_TABLE:
         make_rw((unsigned long)sys_call_table);
         *(sys_call_table + __NR_open) = (unsigned long)real_open;
         make_ro((unsigned long)sys_call_table);
         is_set=0;
         break;
      default:
         printk("sys_open not executed\n");
         break;
   }

    return retval;
}

//populate data struct for file operations
static const struct file_operations my_fops = {
    .owner = THIS_MODULE,
    .open = &my_open,
    .release = &my_release,
    .unlocked_ioctl = (void*)&my_ioctl,
    .compat_ioctl = (void*)&my_ioctl
};

//populate miscdevice data structure
static struct miscdevice my_device = {
    MISC_DYNAMIC_MINOR,
    "MyDevice",
    &my_fops
};

static int __init init_my_module(void)
{
    int retval;
    printk(KERN_INFO "Inside kernel space\n");
    retval = misc_register(&my_device);
    return retval;
}

static void __exit cleanup_my_module(void)
{
    if (is_set)
    {
        make_rw((unsigned long)sys_call_table);
        *(sys_call_table + __NR_open) = (unsigned long)real_open;
        make_ro((unsigned long)sys_call_table);
    }

    misc_deregister(&my_device);
    printk(KERN_INFO "Exiting kernel space\n");
    return;
}

module_init(init_my_module);
module_exit(cleanup_my_module);

我的测试文件的代码如下:

The code for my test file is as follows:

#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


/* Define ioctl commands */
#define IOCTL_PATCH_TABLE 0x00000001
#define IOCTL_FIX_TABLE   0x00000004


int main(void)
{
   int device = open("/dev/MyDevice", O_RDWR);
   printf("%d\n",device);
   ioctl(device, IOCTL_PATCH_TABLE);
   sleep(2);
   ioctl(device, IOCTL_FIX_TABLE);
   close(device);
   return 0;
}

问题在于在我的测试文件中open("/dev/MyDevice",O_RDWR);总是返回-1,为什么会这样呢?我要去哪里错了?我用ls -l/dev/MyDevice检查过,MyDevice已经成功注册了以下详细信息:crw ------- 1 root root 10,56 Dec 9 19:33/dev/MyDevice

The problem is that in my test file open("/dev/MyDevice", O_RDWR); is always returning -1, why is it so ? Where am I going wrong ? I checked with ls -l /dev/MyDevice, MyDevice has been successfully registered with following details: crw------- 1 root root 10, 56 Dec 9 19:33 /dev/MyDevice

推荐答案

对不起,这是一个非常愚蠢的错误,这是菜鸟在做事情时发生的事情.我只需要授予其他char设备驱动程序的读写权限.

Sorry, seriously stupid mistake, that's what happens when rookies do things. I just needed to grant the read and write permissions for my miscellaneous char device driver.

sudo chmod a+r+w /dev/MyDevice

这篇关于其他设备驱动程序:无法通过open()系统调用打开设备的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆