【问题标题】:Testing whether memory is accessible in Linux在 Linux 中测试内存是否可访问
【发布时间】:2013-01-24 17:47:44
【问题描述】:

给定一个不受信任的内存地址,Linux 中有没有办法测试它是否指向有效的、可访问的内存?

例如,在 mach 中,您可以使用 vm_read_overwrite() 尝试从指定位置复制数据。如果地址无效或无法访问,它将返回错误代码而不是使进程崩溃。

【问题讨论】:

标签: linux memory


【解决方案1】:

write 从该内存中(例如,进入/dev/null(编辑:使用/dev/null,它可能无法按预期工作,请使用管道)),如果地址为无法访问。

我不知道如何测试 可写 内存而不破坏它的内容,如果它 可写的。

【讨论】:

  • “我不知道如何测试可写内存而不破坏它的内容,如果它是可写的”如果你从用户空间这样做,你不会破坏它的内容,但会得到一个段错误!
【解决方案2】:

这是TOCTOU 的典型案例 - 您在某个时刻检查内存是否可写,然后您尝试写入它,但不知何故(例如,因为应用程序释放了它),内存不再可访问.

实际上只有一种有效的方法可以做到这一点,那就是,当你真正需要使用它时,捕获你写给它的错误。

当然,您可以使用技巧来尝试确定内存是否“可写”,但实际上无法确保它是可写的。

您可能想稍微解释一下您实际尝试做的事情,如果您更具体,也许我们可以有一些更好的想法。

【讨论】:

  • 我实际上并没有尝试写入内存位置。我只想检查内存是否可以读取。上下文将是一个暂停的进程(所有线程都暂停)。
  • 那么如果你不想写,为什么要知道它是否可写。可读的仍然有同样的问题——你可能会发现它现在是可读的,但在一些指令之后它就不是了,因为对页表进行了一些修改。尽管如此,唯一有保证的方法是处理代码中的段错误。
  • 我不想知道它是否可写。我从没干过。另外,如果我捕获故障,当我从信号处理程序返回时,我将如何阻止它再次出现故障?我是否需要更改 PC 或更改寄存器以指向有效位置?
  • 抱歉,我误解了您想要的内容 - 因为在您的原始帖子中“覆盖”很遗憾,我误以为您希望能够写信到该地址。但无论哪种方式,是的,当您遇到段错误时,您需要做其他事情。但是由于没有其他方法可以确保在您想要读取它时它是可读的[我假设您确实想要读取内存,或者您只是想知道它是否出于某种任意原因而可读?] -最简单的方法是使用 C++ 异常或 setjmp/longjmp 来避免从 segfault 中返回。
  • 好吧,这是有道理的,但是现在如果进程中的所有线程(检查内存的线程除外)都停止,内存是否仍然容易变得无法访问?
【解决方案3】:

你可以试试msync:

int page_size = getpagesize();                                                            
void *aligned = (void *)((uintptr_t)p & ~(page_size - 1));                           
if (msync(aligned, page_size, MS_ASYNC) == -1 && errno == ENOMEM) {
    // Non-accessibe
}

但是这个功能可能会很慢,不应该在性能关键的情况下使用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-09
    • 1970-01-01
    • 2011-02-28
    • 2013-05-30
    • 1970-01-01
    相关资源
    最近更新 更多