来自“Linux内核编程"的源代码示例 [英] Source code example from "Linux kernel programming"

查看:26
本文介绍了来自“Linux内核编程"的源代码示例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

正在阅读 Robert Love 的书,关于系统调用的第 5 章,发现这个简单的例子有点问题:

was reading Robert Love's book, chapter 5 on syscalls, and found this simple example a bit questionable:

asmlinkage long sys_silly_copy(unsigned long *src, unsigned long *dst, unsigned long len)
{
   unsigned long buf;

   if (copy_from_user(&buf, src, len))
     return -EFAULT;

   ...
}

正如我们所见,'buf' 是类型为 'unsigned long' 并在内核堆栈上定义的对象,即它的初始值可能是垃圾.无论如何,在 buf 所在的堆栈中复制len"字节是否有效,即它可以覆盖一些有用的东西?也许这仅适用于这个特定示例?

As we see 'buf' is object of type 'unsigned long' and defined on the kernel stack, i.e. its initial value is likely garbage. Anyway is it valid to copy 'len' bytes in the stack where buf is, i.e. it could overwrite something useful? Perhaps this is fine only for this particular example?

推荐答案

非常 有问题.事实上,这是非常危险的.我会在这里给作者一个怀疑的好处,因为他们只是想展示 copy_from_usercopy_to_user 是如何工作的,但他们真的应该提供一个例子太危险了.

It is very questionable. In fact, it's downright dangerous. I'll give the author the benefit of the doubt here since they're just trying to show how copy_from_user and copy_to_user work but they really should have provided an example that wasn't so dangerous.

特别是,因为这本书抒情地讲述了你如何必须格外小心:

Especially since the book waxes lyrical about how you must be extra careful:

系统调用必须仔细验证其所有参数以确保它们有效且合法.系统调用在内核空间运行,如果用户可以将无效输入传递到内核不受约束,系统的安全性和稳定性就会受到影响.

System calls must carefully verify all their parameters to ensure that they are valid and legal.The system call runs in kernel-space, and if the user can pass invalid input into the kernel without restraint, the system’s security and stability can suffer.

然后为用户提供一种完全消灭内核的方法:-)

and then provides a means for the user to totally annihilate the kernel :-)

我所拥有的副本中的文字说明:

The text from the copy I have states:

让我们考虑一个使用 copy_from_user()copy_to_user() 的系统调用示例.这个系统调用 silly_copy() 完全是一文不值;它将数据从它的第一个参数复制到它的第二个参数中.这是次优的,因为它涉及到内核空间的中间和无关复制而没有任何收益.但它有助于说明这一点.

Let’s consider an example system call that uses both copy_from_user() and copy_to_user().This syscall, silly_copy(), is utterly worthless; it copies data from its first parameter into its second.This is suboptimal in that it involves an intermediate and extraneous copy into kernel-space for no gain. But it helps illustrate the point.

/*
* silly_copy - pointless syscall that copies the len bytes from
* ‘src’ to ‘dst’ using the kernel as an intermediary in the copy.
* Intended as an example of copying to and from the kernel.
*/
SYSCALL_DEFINE3(silly_copy,
                unsigned long *, src,
                unsigned long *, dst,
                unsigned long len)
{
    unsigned long buf;

    /* copy src, which is in the user’s address space, into buf */
    if (copy_from_user(&buf, src, len))
        return -EFAULT;

    /* copy buf into dst, which is in the user’s address space */
    if (copy_to_user(dst, &buf, len))
        return -EFAULT;

    /* return amount of data copied */
    return len;
}

<小时>

除了不检查参数的灾难性失败之外,我很确定 SYSCALL_DEFINE3 的最后一个参数缺少逗号(尽管这只是一个错字).


Other than the catastrophic failure of not checking parameters, I'm pretty certain the last parameter of the SYSCALL_DEFINE3 is missing a comma (though that would just be a typo).

一个更好的例子,无需分配任意内存,将是这样的:

A far better example, without having to allocate arbitrary memory, would be along the lines of:

SYSCALL_DEFINE3(silly_copy,
                unsigned long *, src,
                unsigned long *, dst,
                unsigned long,   len)
{
    unsigned long buf[64];                 /* Buffer for chunks */
    unsigned long lenleft = len;           /* Remaining size */
    unsigned long chunklen = sizeof(buf);  /* Initial chunk length */

    /* Loop handling chunk sizes */

    while (lenleft > 0) {
        /* Change chunk length on last chunk */

        if (lenleft < chunklen) chunklen = lenleft;

        /* copy src(user) to buf(kernel) then dst(user) */

        if (copy_from_user(buf, src, chunklen)) return -EFAULT;
        if (copy_to_user(dst, buf, chunklen)) return -EFAULT;

        /* Adjust pointers and remaining size */

        src += chunklen; dst += chunklen; lenleft -= chunklen;
    }

    /* return amount of data copied */
    return len;
}

<小时>

建议任何尝试实现该系统调用的人都远离本书中的特定示例,尽管我认为它至少会给您一些良好的内核调试体验:-)


Anyone trying to implement that system call would be well advised to steer away from that particular sample in the book, although I suppose, at a bare minimum, it will give you some good kernel debugging experience :-)

这篇关于来自“Linux内核编程"的源代码示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆