【问题标题】:Most portable way to use mprotect() on allocated memory在分配的内存上使用 mprotect() 的最便携方式
【发布时间】:2021-02-16 12:41:46
【问题描述】:

我想知道是否有一种可移植的方式来动态分配内存,然后限制对该内存的一部分的读/写访问,例如。 G。使用 POSIX 函数mprotect()。我可以想到以下方法:

  1. 使用mmap()分配内存,即。 e. mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0):这里,内存保护标志已经可以在初始分配调用中给出,并且可以选择在以后使用mprotect()进行修改。
    问题: MAP_ANONYMOUS is not specified by POSIX,尽管它应该是由“almost all”“most” systems 支持。
  2. 显然,using mmap() on /dev/zero is an alternative to MAP_ANONYMOUS。这将使mmap() 称自己完全兼容POSIX,但似乎这种行为不一定比MAP_ANONYMOUS 更便携(显然不适用于Mac OS X/macOS)。
  3. 使用aligned_alloc()(或posix_memalign())分配内存并使用mprotect()
    问题:mprotect() according to POSIX is only specified for memory obtained via mmap()的行为,虽然至少“on Linux, it is always permissible to call mprotect() on any address in a process’s address space (except for the kernel vsyscall area)”

所以从标准的角度来看,问题在于mprotect()只与mmap()结合指定,但并没有标准与mmap()实际指定动态内存分配。似乎选项(1.)是最便携的。是否有另一种适用于更多系统的方法(或者更好的是,实际上由标准指定)?

【问题讨论】:

  • 便携,你只能对整个内存页面进行操作。您是否阅读过the POSIX mprotect() page 的这一部分:“mprotect() 函数应将访问保护更改为prot包含进程地址空间的任何部分的整个页面指定的访问保护从地址 addr 开始并继续 len 字节。"
  • @AndrewHenle 是的,我知道。我的问题是如何在mprotect()被允许操作的地方分配内存。
  • 为什么不使用共享内存段? mprotect 用于内存对象...
  • 好吧,既然 mprotect 只针对通过 mmap 获得的内存指定,我想你不应该问如何可移植地使用 mprotect,而应该问如何使用 mmap 可移植地分配内存。
  • @user253751 我想是这样,但我决定专注于mprotect(),因为我想做内存保护,而mmap() 只是该路径上的一个复杂细节。此外,也许还有另一种方式(我不知道)不直接使用mmap(),而是指定等效于使用mmap()。最后,在写这个问题时,我已经有点放弃了严格的 POSIX 合规性,所以我准备好接受使用mprotect() 而不使用mmap() 的答案。

标签: c posix standards mmap mprotect


【解决方案1】:

通过shm_open 共享内存对象怎么样? shm_open 返回一个可以被mmap 映射的文件描述符,因此mprotect(ed)。

【讨论】:

  • 我对共享内存对象并不是很熟悉——这可能是一种选择,尽管感觉有点像滥用共享内存对象来实现它们不是为它们设计的东西,并且有一堆不必要的开销。我真的只是想获得一个等效的malloc()(即单个进程本地的简单内存分配),我可以将它与mprotect()(或等效的东西)一起使用。但也许这是最接近 POSIX-only 的近似值?
  • 其实我不想跨进程共享内存。我的目标是一种基本的内存安全形式,即防止对已分配内存的部分进行写入或读取,这些部分已知在某些点不会被访问,similar to this question。有点像assert 声明。
  • 另外,shm_open() 有其自身的兼容性问题,与必须赋予对象的name 相关。这种循环回到mmap() 中存在的类似问题:理想情况下,我想要一个匿名 共享内存对象,但就像mmap() 一样,这样的事情不是由POSIX。这个question 和它被接受的answer 对细节有很好的解释。
  • 是的,我意识到我关于mprotect 的信息是错误的,所以我删除了我的评论(来不及编辑它)。保护内存的唯一方法是使用const(可以丢弃但编译器不会发出警告)或者像用户'Wernsey'在您的链接中建议的那样,通过封装,一个隐藏的getter方法数组。
  • 不幸的是,“隐藏”数组无法防止我试图捕获的错误类别(例如缓冲区溢出)。
猜你喜欢
  • 1970-01-01
  • 2012-12-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-09
  • 2013-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多