了解用于处理文件描述符的linux内核数据结构

时间:2016-11-09 20:48:54

标签: c linux-kernel kernel-module

我的目标是修改进程的打开文件描述符的访问权限。例如,有一个PID已知的进程,它有2个文件描述符,与标准3分开。一个以只读权限打开,另一个以只写权限打开。我想将文件描述符权限从只读修改为读写。之后,文件描述符可用于编写用它创建的对象。

我编写了一个内核模块,可以访问由PID识别的进程的文件描述符。我搜索了标题和论坛,以了解linux数据结构如何处理文件描述符,但我仍然感到困惑。我发现,每个进程都有自己的 task_struct ,其中包含所有打开文件的成员,其中包含一个打开文件描述符数组。我不知道它是如何从这里链接到inode。

我发现有一个struct文件的成员,称为 f_mode ,它为我们提供了权限,但我找不到调用它的方法。当我直接访问它时,它给了我一个unsigned int但我不知道什么值映射到什么?另外,我不确定这是否是存储访问权限的数据成员。如果我修改它会改变文件描述符的访问权限吗?

代码如下:

static int __init mainInit(void){

    int pid=13433;
    struct task_struct * task;
    struct files_struct * files;
    struct fdtable * filestable;
    struct path files_path;

    //Get Task structure from PID
    task = pid_task(find_vpid(pid), PIDTYPE_PID );
    //Get open FIles from the task tstructure
    files = task->files;

    filestable=files_fdtable(files);

    int i=0;
    char *cwd;
    char *buf = (char *)kmalloc(GFP_KERNEL,100*sizeof(char));

    while(filestable->fd[i] != NULL){
        files_path = filestable->fd[i]->f_path;
        cwd=d_path(&files_path,buf, 100*sizeof(char));

        printk(KERN_INFO "Open FD with %d with name %s with access %x\n", i, cwd,filestable->fd[i]->f_mode);

        //printk(KERN_INFO "FMode read:%x Fmodewrite:%x\n",FMODE_READ,FMODE_WRITE);


        //Check access mode
        if(filestable->fd[i]->f_mode==FMODE_READ){
            printk(KERN_INFO "File has access FMODE_READ\n");
        }else if(filestable->fd[i]->f_mode==FMODE_WRITE){
            printk(KERN_INFO "File has access FMODE_WRTIE\n");
        }
        i++;
    }
    return 0;
}

static void __exit mainExit(void){
    printk(KERN_INFO "Goodbye Kernel!. Returning to normal useless world!\n");
}

module_init(mainInit);
module_exit(mainExit);

1 个答案:

答案 0 :(得分:0)

这个想法错了,代码错了。实际目标是什么?为什么文件不能开始写入?如果程序显式打开它进行读取,程序如何突然开始写入文件?这并没有加起来。

你不能只是将标志打开以使文件打开以进行写入。您必须在开放路径中重新执行所有检查。

static int __init mainInit(void){

在大多数情况下,内核不使用camelCase。

    int pid=13433;

'='周围缺少空格。

    struct task_struct * task;

'*'和'task'之间的虚假空间。

    struct files_struct * files;
    struct fdtable * filestable;

iditom将它命名为'fdt'。

    struct path files_path;

    //Get Task structure from PID
    task = pid_task(find_vpid(pid), PIDTYPE_PID );

既没有rcu也没有任务列表,因此这是不安全的。

    //Get open FIles from the task tstructure
    files = task->files;

任务锁定未被保留,因此缺失是不安全的。

    filestable=files_fdtable(files);

如果启用了调试,内核本身会告诉你这行是错误的。

    int i=0;
    char *cwd;
    char *buf = (char *)kmalloc(GFP_KERNEL,100*sizeof(char));

为什么要施放,为什么包含100和为什么包含sizeof(char)?这里硬编码100也是错误的,因为它会导致错误的重复数字。

    while(filestable->fd[i] != NULL){

不仅没有fd表锁,因此遍历是不安全的,它不会按照你想要的方式工作。一个进程可以在使用过的fds之间使用未使用的fds。

        files_path = filestable->fd[i]->f_path;
        cwd=d_path(&files_path,buf, 100*sizeof(char));

邀请容易出错的重复数字100.首先,您认为d_path的安全性是什么?

        printk(KERN_INFO "Open FD with %d with name %s with access %x\n", i, cwd,filestable->fd[i]->f_mode);

        //printk(KERN_INFO "FMode read:%x Fmodewrite:%x\n",FMODE_READ,FMODE_WRITE);


        //Check access mode
        if(filestable->fd[i]->f_mode==FMODE_READ){
            printk(KERN_INFO "File has access FMODE_READ\n");
        }else if(filestable->fd[i]->f_mode==FMODE_WRITE){
            printk(KERN_INFO "File has access FMODE_WRTIE\n");
        }
        i++;
    }
    return 0;
}

static void __exit mainExit(void){
    printk(KERN_INFO "Goodbye Kernel!. Returning to normal useless world!\n");
}