【问题标题】:Do I need to reset protection before calling free我需要在免费通话之前重置保护吗
【发布时间】:2017-09-27 23:58:10
【问题描述】:

我通过mallocaligned_alloc 分配了一些大块内存,然后我使用mprotect 为内存内的一个页面大小的区域设置了一个围栏:

void *buf = malloc(128 * PAGE_SIZE);
int ret = mprotect(buf, PAGE_SIZE, PROT_NONE);

现在我已经完成了内存并正在调用free(buf); 来释放它,我的问题是在调用free 之前是否需要重置mprotect,如下所示:

ret = mprotect(buf, PAGE_SIZE, PROT_READ|PROT_WRITE);
free(buf);

或者我应该只做free?我读到glibc有时会重用之前分配的一些内存,所以如果这块内存区域稍后返回malloc,访问它会不会导致问题(因为它是PROT_NONE)?

【问题讨论】:

    标签: c linux memory posix mprotect


    【解决方案1】:

    在@doron 的回答之上,我挖掘了更多内容,因为我专门在 Linux 上工作。根据posix standard of mprotect

    如果映射不是通过调用 mmap() 建立的,则此函数的行为未指定。

    Linux 上有点不同:

    在 Linux 上,总是允许对进程地址空间中的任何地址调用 mprotect()(内核 vsyscall 区域除外)。特别是它可用于将现有的代码映射更改为可写。

    这意味着确实允许在malloc'ed 内存区域上调用mprotect,但free 不会重置它,因为无法知道旧的保护标志,所以我必须重置标志在致电free之前。

    其实这正是我遇到的问题,当程序运行一段时间后,它在malloc中随机崩溃,那是因为malloc正在将它的家政数据写入之前分配的内存中,而该内存是由之前的mprotect 设置为PROT_NONE,在我在调用free 之前将内存设置为可写之后,程序再也不会崩溃了。

    话虽如此,这只是在Linux上,要编写可移植程序,应该只在mmap'ed内存上使用mprotect

    【讨论】:

      【解决方案2】:

      从堆中分配的 Malloc 不一定向系统请求内存。同样,free 不一定会将内存返回给系统。

      对于您正在做的事情,您应该使用 mmap munmap,它总是会进入系统。如果您使用 mfree,则无需事先调用 mprotect。

      【讨论】:

      • 你在说什么mfree?你是说 munmap 吗?
      • 对不起,我的意思是 munmap。现已更正。我的坏
      • malloc 呢?在 malloc 的内存上使用 mprotect 是错误的吗?还是依赖于实现?甚至是未定义的行为?
      • 是的,不要在分配的内存上使用 mprotect。 Malloc 是一个堆分配器,用于管理可能小于 OS 页的内存。 mprotect 需要整个页面,因为访问属性只有页面粒度。
      猜你喜欢
      • 1970-01-01
      • 2011-06-17
      • 1970-01-01
      • 1970-01-01
      • 2012-08-01
      • 2020-12-18
      • 2020-11-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多