3
votes

I'd like pass a pointer from a user space memory into a function in my kernel module. I don't want to use copy_from_user. I've read that I should use get_user_pages function.

For example one page.

struct page **pages;
pages = kmalloc(1 * sizeof(*pages), GFP_KERNEL);

down_read(&current->mm->mmap_sem);
get_user_pages(current,current->mm,uaddr, 1, 1, 0,pages,NULL);
up_read(&current->mm->mmap_sem);

uaddr is an address in User Space.

  1. After doing this, am I allowed to cast and pass uaddr into my kernel module function? Or maybe I have to use these struct pages in some way?
  2. Why do I have to use down/up read?
  3. After everything do I have to use SetPageDirty() and page_cache_release() functions ?
4

4 Answers

3
votes
  1. No, you cannot directly access the userspace pages via uaddr. The struct pages are filled out to allow the kernel to access the physical pages that correspond to the userspace pages. Note also that they are most unlikely to be contiguous, so one must be careful to use the correct page index into the array from the start of the uaddr.
  2. You are changing the page mapping structures for this process, so need to protect them while the page mapping in the kernel is set up.
  3. When you are done with the mappings that were setup by get_user_pages(), you must 'release' them by the referenced functions.
2
votes

This is not what get_user_pages is for (and no - you can't then just cast and pass uaddr into your kernel module function).

If you don't want to call copy_from_user in the calling function, then just pass a void __user * to your module function and have it do the copy_from_user.

2
votes

You can only use the user pages for page type activity, for example setting up Scatter/Gather DMA into userspace memory. You cannot use it to directly access user space from kernel mode code. Hence the copy_to/from functions that are there for that reason. Unless your moving large amounts of data why not use these functions?

0
votes

Once you get the valid user space address, use get_user_pages to get the struct page pointer. once struct page pointer received , to access it in the kernel mode you have to map it to kernel virtual address by using kmap. hope that helps