有关将数据复制到Linux内核中或从Linux内核中复制数据

时间:2013-03-13 06:02:32

标签: linux linux-kernel operating-system kernel

我正在完成OS类的项目,并且无法解决与SAFELY将数据从用户空间复制到内核以及从内核复制到用户空间以及如何正确丢弃此信息等方面的一些事情。

说我有几个系统调用:

//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.验证指针*data不是null 2.验证length < 0
3.我需要使用access_ok。但是,我不确定是否需要将它用于这两个功能或仅用于long sys_into()
3.使用kmalloc(length)复制到内核中以分配字节数并确保我可以实际分配此内存。
4.最后使用copy_from_user&amp; 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

谢谢!!!

1 个答案:

答案 0 :(得分: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(void __user * uaddr,int __user * ulen),代码将更改为:

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一个内核缓冲区,它在初始化期间足够大。