1
votes

My goal is to modify a process's open file descriptor's access permission. For eg, there is a process whose PID is known, which has 2 file descriptors open apart from the standard 3. One was opened with read only permission and other was opened with write only permission. I want to modify the file descriptors permission from read only to read and write. After which, the file descriptor can be used to write the object it was created with.

I have written a kernel module that gives me access to the file descriptor of the process identified by its PID. I searched the header and forums to understand how the linux data structure works for handling the file descriptor but I am still confused. What I found out is, every process has its own task_struct, which contains a member for all open files under, which contains an array of open file descriptor. I do not know how it links from here on with the inode.

I found out that there is member of struct file, called as f_mode that gives us the permissions but I cannot find a method to call it. When I access it directly, it gives me an unsigned int but I don't know what value maps to what? Also, I am not sure if this is the data member which stores the access permissions. If I modify this would it change the access permissions for file descriptor?

The code is given below:

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

1 Answers

-2
votes

The idea is wrong and the code is wrong. What is the actual goal? Why is the file not open for writing to begin with? How can the program suddenly start writing to the file if it explicitly opened it for reading? This does not add up whatsoever.

You can't just plop the flag to have the file open for writing either. You will have to re-do all the checks in the open path.

static int __init mainInit(void){

For the most part the kernel does not use camelCase.

    int pid=13433;

Missing spaces around '='.

    struct task_struct * task;

Spurious space between '*' and 'task'.

    struct files_struct * files;
    struct fdtable * filestable;

The iditom is to name it 'fdt'.

    struct path files_path;

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

Neither rcu nor tasklist are held, hence this is unsafe.

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

task lock is not held, hence the derefeence is unsafe.

    filestable=files_fdtable(files);

The kernel itself would tell you the line is wrong if you had debug enabled.

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

Why cast, why 100 and why include sizeof(char)? Hardcoded 100 here is additionally wrong as it invites an error prone repetition of the number.

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

Not only fd table lock is not held, hence the traversal is unsafe, it does not work they way you want it to. A process can have unused fds in-between used ones.

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

Invited error prone repetition of the number 100. What makes you think it is safe to d_path here in the first place?

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