C - 堆对齐内存上的 mProtect 神秘地工作



所以我正在尝试检查我是否可以使用 mprotect 正确更改对已映射分配内存的访问权限,这就是我写的:

#include <stdio.h>
#include <sys/mman.h>
#include <malloc.h>
#include <unistd.h>
void main()
{
        int pagesize;
        pagesize = getpagesize();
        void *p;
        p = malloc(pagesize);
        getchar();
        int q = posix_memalign(&p, pagesize, pagesize);
        getchar();
        int a = mprotect(p, pagesize, PROT_READ | PROT_WRITE | PROT_EXEC);
        getchar();
        free(p);
}

现在,在每个函数之后,我都使用getchar使用cat /proc/<pid>/maps文件分析我的内存段,这就是我得到的:(仅显示有关堆的信息,因为这是我唯一关心的问题(posix_memalign后:

01776000-01798000 rw-p 00000000 00:00 0                                  [heap]

mprotect功能之后:

01776000-01778000 rw-p 00000000 00:00 0                                  [heap]
01778000-01779000 rwxp 00000000 00:00 0                                  [heap]
01779000-01798000 rw-p 00000000 00:00 0                                  [heap]

因此,如果您注意到之前分配的堆在我使用mprotect后被分成三部分,只有堆的第二部分获得我在函数中授予的访问权限。为什么会发生这种划分,为什么只有被划分的堆的第二个区域获得权限?注意:我搜索了手册页,但完全没有找到任何关于此的内容。

您在地址 p 分配了 0x1000 个字节,这在您的示例中0x1778000。当您使用这些参数调用mprotect时,它确实按您想要的方式工作并标记为01778000-01779000 rwxp

因此,您的问题可以更恰当地表述为,为什么posix_memalign(3)似乎分配了比您要求的更多的空间?

让我们来看看man posix_memalign

POSIX 要求从 posix_memalign(( 获得的内存可以使用 free(3( 释放。

但是free(3)怎么知道要释放多少字节呢?它需要将其存储在您分配的页面之外的某个位置。随后对malloc(3)或朋友的调用如何知道在哪里可以找到释放的块?这些也需要存储在某个地方。

分配器存储用于管理堆上堆的数据结构也就不足为奇了。

如果要使用更底层的方式来分配页面,请使用mmap(2)

p = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);

此内存由您管理,当您调用 munmap(2) 时,通过直接通知内核来删除映射。无需在用户空间进行回收或管理。

  • 有关malloc(3)功能的更多信息:malloc(( 和 free(( 是如何工作的?

  • 维基百科关于C的动态内存设施的文章:https://en.wikipedia.org/wiki/C_dynamic_memory_allocation

  • glibc 对 malloc(3) et al: https://github.com/lattera/glibc/blob/master/malloc/malloc.c#L3016 的实现

  • 关于glibc实现的博客文章:https://sploitfun.wordpress.com/2015/02/10/understanding-glibc-malloc/

相关内容

  • 没有找到相关文章

最新更新