问题描述
我想确保 sbrk
的返回地址在某个特定范围内。我在某处读到 sbrk
从程序初始化时分配的区域分配。所以我想知道是否有办法强制程序初始化从特定地址分配?例如,使用 mmap
,我将能够使用 MAP_FIXED_NOREPLACE
执行此操作。有没有可能有类似的东西?
解决方法
不,这是不可能的。 brk
和sbrk
是指程序的数据段,可以在任何满足动态链接器需要的有效地址加载。不同的架构可以并且确实使用不同的地址,甚至相同架构的机器也可以根据内核的配置使用不同的范围。使用固定地址或地址范围极不可移植,并且会使您的程序对未来的更改非常脆弱。我完全希望这样做会导致您的程序在未来仅通过升级 libc 就崩溃。
此外,现代程序通常被编译为与位置无关的可执行文件,以便可以使用 ASLR 来提高安全性。因此,即使您知道用于一次程序调用的地址范围,程序的下一次调用也可能使用完全不同的地址范围。
此外,您几乎从不想手动调用 brk
或 sbrk
。在几乎所有情况下,您都希望使用系统内存分配器(或替代品,如 jemalloc),它将为您处理这种情况。例如,glibc 的 malloc 实现与大多数其他实现一样,将使用 mmap
分配大块内存,这可以显着减少长时间运行的程序中的内存使用量,因为这些大块可以独立释放。内存分配器也可能不同意您在不咨询数据段的情况下更改数据段的大小。
最后,如果您关心到其他 Unix 系统的可移植性,并非所有系统都具有 brk
和 sbrk
。 OpenBSD 使用 mmap
分配所有内存,这通过扩展 ASLR 的使用来提高安全性(以性能为代价)。
如果您绝对必须使用固定地址或地址范围并且别无选择,则需要使用 mmap
分配该范围的内存。