【问题标题】:copy_from_user() error: destination size is to smallcopy_from_user() 错误:目标大小太小
【发布时间】:2020-04-17 11:47:23
【问题描述】:

我正在为内核模块编写 ioctls 处理程序,我想从用户空间复制数据。当我使用禁用的优化(-O0 -g 标志)编译代码时,编译器返回以下错误: ./include/linux/thread_info.h:136:17: error: call to ‘__bad_copy_to’ declared with attribute error: copy destination size is too small。我的代码:

struct my_struct {
    int x;
    int y;
}

...

long ioctl_handler(struct file *filp, unsigned int cmd, unsigned long arg) {

  switch(cmd) {
  case MY_IOCTL_ID:
    struct my_struct *cmd_info = vmalloc(sizeof(struct my_struct));
    if (!cmd_info)    
        //error handling

    if (copy_from_user(cmd_info, (void __user*)arg, sizeof(struct my_struct)))
        //error handling

     //perform some action

    vfree(cmd_info);

    return 0;
  }
}

当我在堆栈 (struct my_struct cmd_info;) 上声明变量而不是使用 vmalloc 时,问题消失并且模块编译时没有任何错误,但我想避免这种解决方案。同样当使用-O2 标志编译成功。

在快速查看kernel internals 后,我找到了返回错误的位置,但我认为在我的情况下它不应该发生,因为__compiletime_object_size(addr) 等于sizeof(struct my_struct)

int sz = __compiletime_object_size(addr);
if (unlikely(sz >= 0 && sz < bytes)) {
        if (!__builtin_constant_p(bytes))
            copy_overflow(sz, bytes);
        else if (is_source)
            __bad_copy_from();
        else
            __bad_copy_to();
        return false;
}

【问题讨论】:

    标签: c linux kernel


    【解决方案1】:

    当我编译禁用优化的代码时(-O0 -g 标志)

    不支持不进行优化的编译 (-O0)。但是,也不要尝试自己设置其他受支持的标志,例如 -Og,而必须使用 CONFIG_CC_OPTIMIZE_FOR_DEBUGGING 等配置选项。

    原因是代码会根据配置选项的值而变化。因此,即使标志相同,您最终还是会得到损坏的构建。

    【讨论】:

    • 所以我需要在启用CONFIG_CC_OPTIMIZE_FOR_DEBUGGING 的情况下重新编译内核,然后在该系统上构建的所有模块(甚至是我自己自定义的树外模块)都将默认使用调试符号进行编译?
    • @mmichal10 没错!始终使用内核构建系统构建您的内核(及其模块),不要调用gcc 或自行使用标志,除非您真的知道自己在做什么。模块实际上是内核的一部分,它们的编译方式应该与内核完全相同。
    猜你喜欢
    • 1970-01-01
    • 2018-08-15
    • 2016-02-23
    • 2020-05-13
    • 2020-09-06
    • 2012-03-06
    • 2014-09-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多