0

I know there have been questions like this before, but I'm hoping that I can get some help. As an academic exercise, I'm trying to write to a file from a kernel module. I have saved the original write call from the system call table to a typedef (sys_write_orig) and have replaced it with my own function. That all works fine.

In my new sys_write function, if I use sys_write_orig with the original buffer passed in from userland - it works fine. But when I try to create a new buffer - the issues begin. I understand the separation of kernel memory and user memory - but I thought there was a way to do all this. Any ideas? Here's kind of what I'm trying to do:

char* kernbuf = "foo";
char __user* userbuf = (char*) kmalloc(3*sizeof(char), GFP_USER);

int n = copy_to_user(userbuf,kernbuf,3); 
printk("%d bytes copied to user space (I think).\n",n);

n = sys_write_orig(fd,userbuf,3);
printk("%d is the result from the write.\n",n);

I'm kind of new to kernel-land. So any help is appreciated. Thanks!

Michael Andrews
  • 828
  • 8
  • 13
  • I get 3 bytes written as the result of copy_to_user and then I get -14 as the result of sys_write_orig (-14 = "The address specified in the function is an invalid address.") – Michael Andrews Nov 21 '13 at 15:07
  • actually nothing is getting written to user space. The return of copy_to_user is the number of bytes NOT copied. – Michael Andrews Nov 21 '13 at 15:13
  • Would it be possible for you to include an example conforming generally to ***[SSCCE](http://sscce.org/)*** criteria? If example can at least compile, better yet build, the issues with code will more easily be identified. – ryyker Nov 21 '13 at 15:58
  • ***[Have you seen this?](http://stackoverflow.com/a/1184346/645128)*** – ryyker Nov 21 '13 at 16:08
  • I did see that. Thanks. The VFS is an option I guess - but I have the file descriptor already. Seems that I should be able to pass a new buffer to the write sys call. *sigh* Maybe I'll look into using the file operations table. I can use current->files and then get the file pointer by using fcheck and the get the f_op pointer from the file. Seems a long way to go though. Will also post better code. Thanks for the help. – Michael Andrews Nov 21 '13 at 16:25
  • This looks promising http://www.linuxjournal.com/node/8110/print – Michael Andrews Nov 21 '13 at 16:57

1 Answers1

0

I think this does it. I did not want to use VFS because I have a pointer to the sys_write function (I hooked it with my own function and saved the original), so I might as well use it. But either way - I sill needed to get kernel space data into user space. This seems to do the trick. Thanks for pointing me back to the VFS post - it had the info that got me to this solution.

void append_file(unsigned int fd)
{
    // http://www.linuxjournal.com/node/8110/print
    mm_segment_t old_fs;
    old_fs = get_fs();
    set_fs(KERNEL_DS);

    sys_write_orig(fd, (char*)APPEND_TEXT, strlen(APPEND_TEXT));  

    set_fs(old_fs); 
    printk(KERN_INFO "Appended \"%s\" to fd:%d.\n", APPEND_TEXT, fd);
}
Michael Andrews
  • 828
  • 8
  • 13