copy_from_user 和 toctou

      copy_from_user 是把数据从用户空间 copy 到 内核空间。 

     driver 先 把数据从用户空间copy 到内核空间,然后再进行 check.

      因为如果数据在user 空间 check 之后再copy 到内核,check 后到copy 之间的时间,数据有可能会被改变。参见TOCTOU 问题。

      所以把数据 copy 到 内核空间,内核空间不太容易被攻击,数据check 后再使用。


     还有一个问题,如果 copy_from_user() copy 的struct 里面包含指向用户态的指针,该怎么办呢?

     回答: Driver 需要 aware of this.

                 问题中的copy_from_user 只是copy 了指针,并没有copy 指针所指向的数据。需要另外进行copy. 参见下面                    的网页。


http://stackoverflow.com/questions/1698396/linux-kernel-copy-from-user-struct-with-pointers


I've implemented some kind of character device and I need help with copy_ from_user function.

I've a structure:

struct  my_struct{

int a;

int *b;
};

I initialize it in user space and pass pointer to my_struct to my char device using 'write' function. In Kernel's Space character device 'write' function I cast it from a *char to this kind of structure. I alloc some memory for a struct using kmalloc and do copy_from_user into it.

It's fine for simple 'int a', but it copies only pointer (address) of b value, not value pointed by b, so I'm now in Kernel Space and I'm working with a pointer that points to a user space memory. Is this incorrect and I shouldn't access to user space pointer directly and I have to copy_from_user every single pointer in my struct and then copy back every pointer in "read" function using copy_to_userfunction?

回答1:

You must always use copy_from_user and similar to access user space memory from kernel space, regardless of how you got the pointer. Since b is a pointer to user space memory, you must use copy_from_user to access it.

These functions do two important additional tasks:

  1. They make sure the pointer points into user space and not kernel space. Without this check, user space programs might be able to read or write to kernel memory, bypassing normal security.
  2. They handle page faults correctly. Normally a page fault in kernel mode will result in an OOPS or panic - the copy_*_user family of functions have a special override that tells the PF handler that all is well, and the fault should be handled normally; and in the event that the fault cannot be satisfied by IO (ie, what would normally cause a SIGSEGV or SIGBUS), return an error code instead so their caller can do any necessary cleanup before returning to userspace with -EFAULT.
回答2:

You are correct in your surmising. If you need to access the value *b, you will need to use copy_from_user (and copy_to_user to update it back in the user process).



你可能感兴趣的:(security)