所以我试图检查是否可以使用 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
之后之前分配的堆被分为三个部分并且只有堆的第二部分获得了我在函数中给出的访问权限。
为什么会发生这种划分,为什么只有划分堆的第二个区域获得权限?
注意:我搜索了联机帮助页,但没有发现任何与此相关的内容。
最佳答案
您分配了0x1000
地址 p
处的字节,即0x1778000
在你的例子中。当您调用mprotect
时使用这些参数,它确实按照您想要的方式工作并标记为 01778000-01779000 rwxp
.
因此,您的问题可以更恰本地表述为,为什么posix_memalign(3)
似乎分配的空间比您要求的多?
让我们看一下man posix_memalign
:
POSIX requires that memory obtained from posix_memalign() can be freed using free(3).
但是free(3)
怎么办?知道要释放多少字节吗?它需要将其存储在您分配的页面之外的某个位置。以及如何后续调用 malloc(3)
或者 friend 知道哪里可以找到释放的 block 吗?这些也需要存储在某个地方。
堆分配器将用于管理堆的数据结构存储在堆上也就不足为奇了。
如果您想要一种更底层的方式来分配页面,请使用 mmap(2)
:
p = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
当您调用munmap(2)
时,该内存由您管理。 ,直接通知内核删除映射。用户空间中没有进行回收或管理。
有关
malloc(3)
的更多信息做: How do malloc() and free() work?维基百科关于 C 动态内存设施的文章:https://en.wikipedia.org/wiki/C_dynamic_memory_allocation
glibc 的
malloc(3)
的实现等人:https://github.com/lattera/glibc/blob/master/malloc/malloc.c#L3016有关 glibc 实现的博客文章: https://sploitfun.wordpress.com/2015/02/10/understanding-glibc-malloc/
关于c - 堆对齐内存上的 mprotect 神秘地工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35239300/