【问题标题】:what to do with page fault from copy_from_user()?如何处理来自 copy_from_user() 的页面错误?
【发布时间】:2014-12-05 07:50:02
【问题描述】:

我有以下系统调用:

long do_print(int n, char *p){
  char tmp[n]; //allocate array of n bytes
  int ret = copy_from_user(tmp,p,n); 
  if (!ret){
    //do something with tmp
  }
  return ret; 
}

它为n>5000 返回非零值(我估计是因为页面错误)。

如何强制复制成功。也就是说,如果系统调用返回非零值怎么办?

【问题讨论】:

    标签: c linux memory linux-kernel operating-system


    【解决方案1】:

    在堆栈上分配一个大数组不是你应该做的,也不是真的可以做的。 linux 内核使用一个小堆栈运行,通常是 2 个内存页。如果您的char tmp[n]; 依赖于来自用户空间的n,这同样更危险,这让用户空间可能使内核崩溃。在这种情况下,您将不得不动态分配内存,而不是使用堆栈上的缓冲区。

    至于如果 copy_from_user() 失败你会怎么做,用户对内核撒了谎,把错误的东西传递给了内核。

    处理这个问题的正常方法是退出你正在执行的任何操作,并将 -EFAULT 传递回用户空间。

    【讨论】:

    • 在用户空间代码中,我确保为指针分配了 n 个字节。我如何处理 -EINVAL 值?
    • @user1734905 你处理它就像处理任何其他错误一样。此外,nos 指的是n,因为您在内核堆栈上使用的数组的大小。您绝对不希望用户空间能够使内核崩溃。
    • @user1734905 那么也许在其他地方出了点问题。您是否验证过n 在内核中的值与在用户空间代码中的值相同?我不知道您在实现什么(例如系统调用、字符设备中的 read() 函数等),但您可以查看其他示例,例如this ,它实现了一个 ioctl() 调用 - 在该示例中,如果 copy_from_user() 失败,它将导致用户空间中的 ioctl() 返回 -1,(并且 errno 为 EFAULT)。不过,您需要修复代码,使其不在堆栈上分配。
    猜你喜欢
    • 2015-06-29
    • 1970-01-01
    • 1970-01-01
    • 2016-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-11
    • 2011-01-11
    相关资源
    最近更新 更多