来源$ C ​​$ C例如从" Linux内核编程" [英] Source code example from "Linux kernel programming"

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

问题描述

在阅读上的系统调用罗伯特·爱的书,第5章,发现这个简单的例子有点可疑的:

  asmlinkage长sys_silly_copy(无符号长* SRC,无符号长* DST,无符号长LEN)
{
   无符号长BUF;   如果(调用copy_from_user(安培; BUF,SRC,LEN))
     返回-EFAULT;   ...
}

正如我们看到的BUF的类型为对象的无符号长和内核堆栈上定义,即其初始值很可能垃圾。反正它是有效的在堆栈,其中buf是复制LEN字节,即它可以覆盖一些有用的东西?也许这只是为这个特殊的例子是罚款?


解决方案

这是的非常的质疑。事实上,这是非常危险。我在这里给笔者的疑点利益,因为他们只是想说明如何调用copy_from_user copy_to_user 工作,但他们真的应该提供这并非如此危险的一个例子。

尤其的自书蜡抒情你是如何的必须的要格外小心:


  

系统调用必须认真核实其所有参数,以确保它们是有效的,
  legal.The系统调用在内核空间中运行,并且如果用户可以通过无效输入到
  不加节制的内核,系统的安全性和稳定性会受到影响。


和然后为用户提供到完全消灭内核的装置: - )


从复制我有状态的文本:


  

让我们考虑同时使用调用copy_from_user()的实例系统调用 copy_to_user()。这个系统调用, silly_copy(),是一钱不值;因为它涉及到一个中间和外来复制到内核空间,而并无益处从它的第一个参数是将数据复制到其second.This是最理想的。但它有助于说明这一点。


  / *
* silly_copy - 毫无意义的系统调用是复制的len字节
*SRC到夏令时使用的内核作为副本的中介。
*以作为复制到和从内核的一个例子。
* /
SYSCALL_DEFINE3(silly_copy,
                无符号长*,SRC,
                无符号长*,DST,
                无符号长LEN)
{
    无符号长BUF;    / *拷贝的src,这是在用户的地址空间,进入的buf * /
    如果(调用copy_from_user(安培; BUF,SRC,LEN))
        返回-EFAULT;    / *复制到BUF DST,这是在用户的地址空间* /
    如果(copy_to_user(DST,&安培; BUF,LEN))
        返回-EFAULT;    / *返回复制的数据量* /
    返回LEN;
}


除了不检查参数的灾难性的失败,我是pretty特定的最后一个参数的 SYSCALL_DEFINE3 缺少一个逗号(虽然这也只是一个错字)。

有一个更好的例子,而不必分配任意内存,将沿着线:

  SYSCALL_DEFINE3(silly_copy,
                无符号长*,SRC,
                无符号长*,DST,
                无符号长,LEN)
{
    无符号长BUF [64]; / *缓冲区的块* /
    无符号长lenleft = LEN; / *剩余大小* /
    无符号长chunklen = sizeof的(BUF); / *初始块长度* /    / *循环处理的块大小* /    而(lenleft大于0){
        / *在最后一个块更改块长度* /        如果(lenleft< chunklen)chunklen = lenleft;        / *副本SRC(用户)BUF(内核),则DST(用户)* /        如果(调用copy_from_user(BUF,SRC,chunklen))回报-EFAULT;
        如果(copy_to_user(DST,BUF,chunklen))回报-EFAULT;        / *调整指针和剩余大小* /        SRC + = chunklen; DST + = chunklen; lenleft - = chunklen;
    }    / *返回复制的数据量* /
    返回LEN;
}


任何人试图实施该系统调用将被建议从书中那个特定的样本引导了,虽然我想,在最低限度,它会给你一些好的内核调试经验: - )

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;

   ...
}

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?

解决方案

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:

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


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 :-)

这篇关于来源$ C ​​$ C例如从&QUOT; Linux内核编程&QUOT;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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