2

我正在完成 OS 类的项目,无法弄清楚与安全地将数据从用户空间复制到内核并从内核复制回用户空间有关的几件事,以及如何正确丢弃这些信息。

假设我有几个系统调用:

//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&copy_to_user复制数据。

到目前为止,我发现的信息很少。1.来自“Linux内核编程”的源代码示例(正如所指出的,Linux内核开发中的示例是危险的)。2. http://www.quora.com/Linux-Kernel/How-does-copy_to_user-work

谢谢 !!!

4

1 回答 1

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。

于 2013-03-13T06:42:31.420 回答