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
Post a Comment