Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 源代码示例来自;“Linux内核编程”;_C_Linux Kernel - Fatal编程技术网

C 源代码示例来自;“Linux内核编程”;

C 源代码示例来自;“Linux内核编程”;,c,linux-kernel,C,Linux Kernel,正在阅读Robert Love的书,关于系统调用的第5章,发现这个简单的例子有点可疑: 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”是类型

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

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”字节是否有效,即是否可以覆盖有用的内容?也许这只适用于这个特定的例子?

这是非常值得怀疑的。事实上,这是非常危险的。我将在这里给作者一个质疑的好处,因为他们只是想展示
从用户
复制到用户和
复制到用户
是如何工作的,但他们真的应该提供一个不那么危险的例子

尤其是因为这本书抒情地讲述了你必须格外小心:

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

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


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

让我们考虑一个示例系统调用,它使用了 CopyOfFuxUs()/<代码>和<代码> CopyStoToUs()/<代码>。它将数据从第一个参数复制到第二个参数。这是次优的,因为它涉及到一个中间的和无关的复制到内核空间,而没有任何收益。但这有助于说明这一点


除了没有检查参数的灾难性失败之外,我非常确定
SYSCALL\u DEFINE3
的最后一个参数缺少一个逗号(尽管这只是一个输入错误)

一个更好的例子是,在不必分配任意内存的情况下:

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;
}
SYSCALL\u DEFINE3(愚蠢的副本,
无符号长*,src,
无符号长*,dst,
无符号长(len)
{
块的无符号长buf[64];/*缓冲区*/
无符号长lenleft=len;/*剩余大小*/
无符号长chunklen=sizeof(buf);/*初始块长度*/
/*循环处理块大小*/
而(左>0){
/*更改最后一个区块的区块长度*/
如果(lenleft


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

只要len==sizeof(unsigned long),就可以了。所发生的一切就是src中的len字节被写入buf。只是不要太大,否则ret地址和其他重要结构可能会太大overwritten@kisplit:您从不依赖调用方遵守规则,特别是如果您是内核。如果要确保复制仅用于单个ulong,则在复制操作中使用
sizeof(unsigned long)
,而不是
len
。我在回答中提供了一个更安全的版本。@paxdiablo:我完全同意。当然,这是危险的,除非在此特定示例中len==sizeof(unsigned long)。谢谢您的评论!在您的示例中,它不应该是copy_from_user(buf,src,chunklen)而不是copy_from_user(&buf,src,chunklen),也就是说,它足以提供指向数组第一个元素和长度的指针。@Mark,是的,您是对的,我已将其更改为正确的形式。
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;
}
int init_module(void)
{

    mempool_t *mempool;

    struct kmem_cache *kmem_cache;
    void *p0 , *p1;
    kmem_cache = kmem_cache_create("Ashrama" ,100 , 0 ,SLAB_PANIC ,NULL);
    mempool = mempool_create(4 , mempool_alloc_slab , mempool_free_slab , kmem_cache);
    p0 = mempool_alloc(mempool, SLAB_PANIC);
    p1 = mempool_alloc(mempool , SLAB_PANIC);
    strcpy(p0 , "Ranjan.B.M");
    strcpy(p1 , "Mithun.V");
    mempool_free( p0 , mempool);
    printk(KERN_ALERT"%s",p0);
    printk(KERN_ALERT"%s",p1);
}