简体   繁体   中英

System Call write

The system call write it's defined as follow:

SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf, size_t, count)
{
     struct file *file;
     ssize_t ret = -EBADF;
     int fput_needed;

     file = fget_light(fd, &fput_needed);
     if (file) {
             loff_t pos = file_pos_read(file);
             ret = vfs_write(file, buf, count, &pos);
             file_pos_write(file, pos);
             fput_light(file, fput_needed);
     }

     return ret;
}

I'd like to copy the variable buf to modify your content and then use this new variable at:

vfs_write(file, new_buf, count, &pos);

I've tried to allocate memory to a char pointer variable with kmalloc and then I've used copy_from_user( ) to do the copy. Finally I've used the new variable at vfs_write() . After recompile the kernel and reboot the system I've got kernel panic error message.

Here is my implementation that generates a kernel panic error message:

SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf, size_t, count){
    struct file *file;
    ssize_t ret = -EBADF;
    int fput_needed;
    char *data;

    data = kmalloc(count, GFP_KERNEL);
    if(!data)
        return ret;

    copy_from_user(data, buf, count);

    file = fget_light(fd, &fput_needed);
    if (file) {
        loff_t pos = file_pos_read(file);
        ret = vfs_write(file, data, count, &pos);
        file_pos_write(file, pos);
        fput_light(file, fput_needed);
    }

    return ret;
}

How can I do this copy in kernel mode?

I'm using Linux Mint 12 - Kernel version: 3.0.30

You should probably also post your code. Ie the changes you made to the write system call to be certain where the error is.

That said, there are checks in place that don't allow you to use kernel memory for system calls. You either need to allocate your buffer in user address space for the process (bad) or disable the checks (not as bad).

I'm not as familiar with the 3.0 kernel but this answer looks promising:

mm_segment_t old_fs;

old_fs = get_fs();
set_fs(KERNEL_DS);
/* Your syscall here */
set_fs(old_fs);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM