【问题标题】:When does copy_from/to_user returns a non-zero valuecopy_from/to_user 何时返回非零值
【发布时间】:2019-09-17 14:57:09
【问题描述】:

我阅读了copy_from/to_user函数的源代码。 似乎他们总是返回0

static inline int copy_from_user(void *to, const void __user volatile *from,
                 unsigned long n)
{
    __chk_user_ptr(from, n);
    volatile_memcpy(to, from, n);
    return 0;
}

https://github.com/torvalds/linux/blob/6f0d349d922ba44e4348a17a78ea51b7135965b1/tools/virtio/linux/uaccess.h#L37-L51

但是,有一些类似下面的代码可以检查 copy_from/to_user 的返回值。

    if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
        return -EFAULT;

https://github.com/torvalds/linux/blob/db54615e21419c3cb4d699a0b0aa16cc44d0e9da/net/ipv4/netfilter/ip_tables.c#L1114-L1115

那么我有三个问题。

  1. 返回非零的copy_from/to_user的代码在哪里定义?
  2. 是什么导致copy_from/to_user 返回非零值?
  3. 返回什么值?

【问题讨论】:

    标签: c linux linux-kernel kernel


    【解决方案1】:

    我很确定您正在查看错误的文件; tools/* 不是内核的一部分,而是用户空间工具的源代码。此代码看起来像是用于链接为用户空间程序中的内核 API 编写的代码的存根。

    实际的copy_from/to_user 函数也可能看起来总是返回 0,但据我了解,它们有一些花哨的技巧,将链接器部分连接到它们的内联 asm 中,这样当 cpu 在复制过程中捕获访问错误时操作,故障处理程序可以在调用者处以假的-EFAULT 返回值恢复执行。这些函数的定义是特定于架构的,可能可以在 arch/ 树的某处找到。

    【讨论】:

      【解决方案2】:
      1. copy_from/to_user返回非零的代码在哪里定义?

      在 Linux 源代码树的“include/linux/uaccess.h”中。请注意,这些将在调用特定于架构的 raw_copy_from/to_user 函数之前进行一些初始检查。

      1. 是什么导致copy_from/to_user 返回非零值?

      可能的原因是指定的用户内存范围无效,或者在读/写指定的用户内存范围时出现未处理的故障。

      1. 返回什么值?

      返回未复制字节数。这将介于 0 和指定长度(含)之间。我们将返回值称为“不成功的长度”。

      我们将指定长度减去(返回的)“不成功长度”称为“成功长度”。

      调用者可以认为“成功长度”的字节数已经复制成功。

      请注意,目标缓冲区中实际覆盖的字节数将介于“成功长度”和指定长度(含)之间,但只有初始“成功长度”字节应被视为可用。

      【讨论】:

        猜你喜欢
        • 2018-12-19
        • 1970-01-01
        • 2015-07-11
        • 1970-01-01
        • 2012-06-20
        • 2023-03-25
        • 1970-01-01
        • 2021-06-29
        • 1970-01-01
        相关资源
        最近更新 更多