C 理解linux内核数据结构以处理文件描述符

C 理解linux内核数据结构以处理文件描述符,c,linux-kernel,kernel-module,C,Linux Kernel,Kernel Module,我的目标是修改进程的打开文件描述符的访问权限。例如,有一个进程的PID是已知的,它有两个文件描述符,与标准的3不同。一个以只读权限打开,另一个以只读权限打开。我想将文件描述符权限从只读修改为读写。之后,可以使用文件描述符写入创建它时使用的对象 我已经编写了一个内核模块,它允许我访问由其PID标识的进程的文件描述符。我搜索了标题和论坛,以了解linux数据结构如何处理文件描述符,但我仍然感到困惑。我发现,每个进程都有自己的任务结构,其中包含下所有打开文件的成员,其中包含打开文件描述符数组。我不知道

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

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

我发现struct file中有一个名为f_mode的成员给了我们权限,但我找不到调用它的方法。当我直接访问它时,它会给我一个无符号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);

这个想法是错误的,代码是错误的。实际目标是什么?为什么文件一开始就没有打开进行写入?如果程序显式地打开文件进行读取,它怎么会突然开始写入文件?这根本算不上什么

您也不能仅仅通过弹出标志来打开文件进行写入。您必须重新执行开放路径中的所有检查

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);
任务锁未被保持,因此解除是不安全的

    //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(字符)?这里的硬编码100是另外一个错误,因为它会导致容易出错的数字重复

    while(filestable->fd[i] != NULL){
不仅fd表锁没有被持有,因此遍历是不安全的,它不能按您希望的方式工作。一个进程在使用的FD之间可以有未使用的FD

        files_path = filestable->fd[i]->f_path;
        cwd=d_path(&files_path,buf, 100*sizeof(char));
邀请容易出错的数字100的重复。你怎么会认为在这里走d_路是安全的

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

虽然代码可能不是惯用的内核代码,但这在这里并不重要。除非OP计划将其合并到内核中(不太可能,而且他需要一个很好的理由才能让它被接受),否则内核代码风格并不重要,只有OP个人喜欢的代码风格,以及他可能与之合作的任何人的代码风格你没有提供任何关于如何做的信息,只是说做得不对。很明显,OP已经知道了,否则他就不会问这个问题了。