1

我在编译我的内核模块时遇到了一个我无法解决的警告。

首先看一下这个简化的代码:

#define READ_CHUNK 100u
static int _procfs_write(struct file *file, const char *buf, unsigned long count, void *data)
{
    char command[READ_CHUNK];
    unsigned long left = count;
    while (left > 0)
    {
        unsigned int amount = left<READ_CHUNK?left:READ_CHUNK;    
        if (copy_from_user(command, buf, amount))
            return -EFAULT;
        buf += amount;
        left -= amount;
        /* process buffer */
    }
    return count;
}

我得到的警告如下:

警告:调用带有属性警告的“copy_from_user_overflow”声明:copy_from_user() 缓冲区大小无法证明是正确的

如您所见,这是完全错误的。amount我读到的数据证明是好的!我发现这个链接min可以在最后一个参数中使用以使 gcc 静音,但它对我不起作用(我写道:

if (copy_from_user(command, buf, min((unsigned long)amount, count)))

无济于事)。

有谁知道如何让 gcc 知道这很酷而且不用担心?


发生这种情况的另一个地方如下所示:

static int _procfs_write(struct file *file, const char *buf, unsigned long count, void *data)
{
    char *read_buffer = vmalloc(count * sizeof(*read_buffer));
    if (read_buffer == NULL)
        return -ENOMEM;
    if (copy_from_user(read_buffer, buf, count))
    {
        vfree(read_buffer);
        return -EFAULT;
    }
    /* process buffer */
    vfree(read_buffer);
    return count;
}

在这种情况下,gcc 也会给我同样的警告,即使它肯定是正确的。


这是确切的错误:

In file included from /usr/src/linux-2.6.35.9-rtai-9jan2012/arch/x86/include/asm/uaccess.h:571:0,
                 from <my source file>:7:
/usr/src/linux-2.6.35.9-rtai-9jan2012/arch/x86/include/asm/uaccess_32.h: In function ‘copy_from_user’:
/usr/src/linux-2.6.35.9-rtai-9jan2012/arch/x86/include/asm/uaccess_32.h:212:26: warning: call to ‘copy_from_user_overflow’ declared with attribute warning: copy_from_user() buffer size is not provably correct

内核版本:2.6.35.9 用 rtai 打补丁(如您所见)

4

1 回答 1

2

在您的第一个示例中,尝试替换

min((unsigned long)amount, count)

min((unsigned long)READ_CHUNK, count)

现在,可以证明在编译时复制大小不会超过 100 字节,因此让 gcc 相信我们永远不会覆盖command同样是 100 字节的目标缓冲区。

在您的第二个示例中,在编译时既不知道read_buffer也不知道。count如果您不希望此错误困扰您,则需要编译时可评估参数(目标缓冲区和复制大小)发送到copy_from_user

如果您检查主线 linux 内核,您将几乎找不到他们将用户空间数据写入内核内的 malloced 缓冲区的示例。所以我想,如果你的代码必须完全安全,你需要取消缓冲区的分配

PS:阅读 gcc 如何实现有限的缓冲区溢出保护机制,可以防止一些缓冲区溢出攻击。

于 2012-04-03T18:51:45.093 回答