Questions about copying data into/from Linux Kernel -


i finishing project os class , can't figure several things have safely copying data user-space kernel , kernel user space, , how discard information.

say have several system calls:

//copies data kernel space long sys_into(void __user *data, long length); // copies data user space long sys_from(void __user *data, long length); 

in both cases long length number of bytes copied.

things able figure out far:
1. validate pointers *data not null.
2. validate length < 0
3. need use access_ok. however, not sure if need use both functions or long sys_into()
3. when copying kernel using kmalloc(length) allocate number of bytes , make sure can allocate memory.
4. use copy_from_user & copy_to_user copy data.

so far, found little information. 1. source code example "linux kernel programming" (as pointed out, example in linux kernel development dangerous). 2. http://www.quora.com/linux-kernel/how-does-copy_to_user-work

thanks !!!

i think considering right, provide codes following:

#define maximum_length 128 char kaddr[maximum_length];  int sys_into(void __user *uaddr, int len) {     if (len < 0 || len > maximum_length)         return -einval;     if (len == 0)         return 0;      if (copy_from_user(kaddr, uaddr, len))         return -efault;      /* handling */      return len; }  int sys_from(void __user *uaddr, int len) {     if (len > maximum_length)         len = maximum_length;      if (len < 0 || len > maximum_length)         return -einval;     if (len) {         if (copy_to_user(uaddr, kaddr, len))             return -efault; }      return len; } 

other considering: (1)if copy size might large , vary, should considering using get_user()/put_user() check, means have change sys_from() parameters table int sys_from(void __user *uaddr, int __user *ulen), codes changed to:

int sys_from(void __user *uaddr, int __user *ulen) {     int err;     int len;      err = get_user(len, ulen);     if (err)         return err;     if (len > maximum_length)         len = maximum_length;     if (len < 0 || len > maximum_length)         return -einval;     if (len) {         if (copy_to_user(uaddr, kaddr, len))             return -efault; }      return __put_user(len, ulen); } 

(2) if possible, it's better not dynamically kmalloc/kfree buffers frequently. while it's better kmalloc 1 kernel buffer big enough during initialization.


Comments

Popular posts from this blog

c++ - llvm function pass ReplaceInstWithInst malloc -

Cross-Compiling Linux Kernel for Raspberry Pi - ${CCPREFIX}gcc -v does not work -

java.lang.NoClassDefFoundError When Creating New Android Project -