2013-03-13 59 views
2

我正在完成OS类的项目,并且无法确定与将用户空间的数据复制到内核以及从内核回到用户空间的操作有关的几件事情,以及如何妥善丢弃这些信息。关于将数据复制到Linux内核或从Linux内核复制数据的问题

说我有几个系统调用:

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

在这两种情况下long length是要复制的字节数。

件事我是能够找出迄今:
1.验证指针*datanull
2.验证length < 0
3.我需要使用access_ok。但是,我不确定是否需要将它用于这两种功能,或者仅用于long sys_into()
3.使用kmalloc(长度)复制到内核中以分配字节数并确保我实际上可以分配此内存。
4.最后使用copy_from_user & copy_to_user复制数据。

到目前为止,我发现的信息非常少。 1. Source code example from "Linux kernel programming"(正如指出的,Linux内核开发中的例子很危险)。 2. http://www.quora.com/Linux-Kernel/How-does-copy_to_user-work

谢谢!

+0

为什么不使用'size_t'来表示大小的东西? – 2017-07-26 09:35:04

回答

3

我想你的考虑是正确的,我提供了一些代码如下:

#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; 
} 

其他考虑: (1)如果复印尺寸可能是真正的大和变化,您应该使用GET_USER(考虑)/ put_user()检查,这意味着你必须改变sys_from()的参数表为int sys_from(空隙__user * UADDR,INT __user *尤伦),该代码将被更改为:

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 )如果可能的话,最好不要动态地使用kmalloc/kfree缓冲区经常。尽管在初始化时kmalloc的内核缓冲区足够大,但它更好。