dlmalloc模式的内存layout
主要自己最近在调试这个,相比Windows的来说,Linux程序选择alloc的方式真是千奇百怪,alloc也是有一大堆,先看一个dlmalloc的实现。
A 简介
dlmalloc是目前一个十分流行的内存分配器,其由Doug
Lea1从1987年开始编写,到目前为止,最新版本为2.8.32,由于其高效率等特点被广泛的使用和研究(很多linux系统等用的就是dlmalloc或其变形,比如ptmalloc)。
B 内存布局
来源@https://cw.fel.cvut.cz/old/_media/courses/a4m33pal/04_dynamic_memory_v6.pdf
实际上的内存类似于:
P位的作用是:1 代表前一个thunk在使用,0 代表被释放。
参考@https://medium.com/@ktecv2000/heap-exploit-%E5%AD%B8%E7%BF%92%E7%AD%86%E8%A8%98-d724d0afa59b
C 有点太快了
源代码可以从ftp://gee.cs.oswego.edu/pub/misc/malloc.c获取到。
看一下malloc.h中的作者简介吧。写的比百度百科的词条要好很多。(机器翻译,我用上瘾了)
重要情报: 支持的指针/size_t表示:4或8个字节。size_t必须是与指针宽度相同的无符号类型。 (如果您使用的是一个将size_t 声明为有符号类型的古老系统,或者需要它与指针的宽度不同,则可以使用此malloc的以前版本(例如2.7.2)来支持)
对齐:8个字节(最少)。这对几乎所有当前机器和C编译器来说都足够了。但是,如果需要的话,您可以将MALLOC_ALIGNMENT定义为更宽的范围(最多128字节),代价是使用更多的空间。
每个分配块的最小开销:4或8个字节(如果是4字节大小,原文如此,指32bit)、8或16个字节(如果是8字节大小,指64bit),每个malloc的块都有一个隐藏字,其中包含大小和状态信息,如果定义了FOOTER,则还有其他交叉检查字。
最小分配大小:4字节指针:16字节(包括开销),8字节指针:32字节(包括开销),即使是对零字节(即malloc(0))的请求也会返回一个指向最小可分配大小的指针。
最大开销浪费(即分配的额外字节数比malloc中请求的字节数)小于或等于最小大小,但通过mmap()服务的请求>=mmap_阈值除外,其中最坏的浪费大约是32个字节加上系统页面(最小mmap单元)的剩余部分;通常是4096或8192字节。安全性:静态安全;可选地,malloc的“安全性”或多或少是指恶意代码在调用malloc的代码中强调错误影响的能力(例如,释放当前未被恶意占用的空间或覆盖过块的末端)。此malloc保证即使存在使用错误,也不会修改堆以下的任何内存位置(即静态变量)。例程还检测到大多数不适当的free和realloc。只要malloc本身的静态记录不被其他方法破坏,所有这些保护都是有效的。
这只是安全性的一个方面--这些检查也不能检测到所有可能的编程错误。如果FOOTER被定义为非零,则每个分配的块都带有一个额外的检查字,以验证它是从其空间中malloc的。
这些检查字在使用malloc的程序的每次执行中是相同的,但如果再次执行则不同,因此无法free由恶意代码构造的假内存块。
这可以通过拒绝可能损坏堆内存的free/realloc程序来提高安全性,此外还可以防止对始终处于打开状态的static写入进行检查。
这可能会以牺牲时间和空间开销为代价进一步提高安全性。(请注意,FOOTER可能也值得与MSPACES一起使用)。
默认情况下,检测到的错误会导致程序中止(调用“abort()”)。您可以重写它,通过定义PROCEED_ON_ERROR来处理错误。在这种情况下,恶意的free不会有任何影响,遇到用户覆盖造成的坏地址的malloc将通过将指针和索引删除所有已知内存而忽略恶意地址。
这可能适用于在遇到编程错误时应尽可能继续运行的程序,尽管它们可能会耗尽内存,因为这样的话,程序将永远不会回收掉那些恶意内存。
如果您不喜欢这两种选项中的任何一种,则可以定义CORRUPTION_ERROR_ACTION 和 USAGE_ERROR_ACTION
来执行其他任何操作。如果您确信您使用malloc的程序没有错误或漏洞,您可以将不安全定义为1,这可能(也可能不会)提供一个小的性能改进。还可以使用malloc_set_footprint_limit来限制最大总可分配空间。这本身并不是一个安全特性(对设置限制的调用没有屏蔽或特权),但是作为安全实现的一个方面可能很有用。