当前位置:首页 > 公众号精选 > 码农的荒岛求生

大家好,我是小风哥,畅销书《计算机底层的秘密》作者。

今天来聊个面试题,为什么mmap共享内存比malloc更危险,这是一个比较有区分度的题目。

在系统编程中,内存管理是程序员必须面对的核心问题之一。

C/C++开发者常用的内存分配方式包括malloc(堆内存)和mmap(共享内存/文件映射)。

虽然两者都能提供内存分配的能力,但从系统风险的角度来看,mmap共享内存比malloc更加危险,稍有不慎就可能引发严重的安全漏洞或稳定性问题。

mmap共享内存可能导致其它进程崩溃

mmap可以让多个进程直接读写同一块物理内存,这意味着一个进程的错误操作可能直接影响其他进程的数据,甚至导致崩溃。比如进程A的越界写入可能导致进程B崩溃或读取到损坏的数据。

一句话,共享内存破坏了进程间的内存隔离。

而如果使用malloc,这种越界写入最多只会影响当前进程,不会跨进程传播错误。因为malloc分配的内存仅在当前进程内有效,天然具备隔离性,其他进程无法直接访问。

mmap的权限风险

mmap可以设置内存的读写/执行权限(如PROT_EXEC),如果错误配置可能被黑客利用进行代码注入攻击(如缓冲区溢出后执行恶意代码)。

假设有一个网络服务程序,使用 mmap 分配了一块内存用于处理客户端请求,并错误地赋予了可执行权限(PROT_EXEC):

void *mem_start = mmap(NULL, 4096, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

同时,程序将用户输入数据(如网络数据包)复制到该内存区域,但未检查输入长度。

这样攻击者就可以构造一个超长数据包,其中包含恶意机器码(如 shellcode)和精心设计的溢出数据,溢出数据覆盖了程序的返回地址或函数指针,使其指向 mem_start 的起始地址。

当程序执行到该返回地址时,会跳转到 mem_start 区域。

由于 mem_start 被错误配置为可执行(PROT_EXEC),因此操作系统不会阻止该区域的代码执行。

攻击者的 shellcode 被成功执行,可能实现提权、反弹 Shell 等恶意操作。

而使用malloc分配的堆内存则无此问题。

多线程与同步风险

使用mmap共享内存时,多进程或线程需通过信号量、锁等机制同步访问,否则导致数据竞争(Data Race)或脏读,这显然会影响所有共享这块内存的进程。

malloc本身是线程安全的(通过全局锁或线程本地缓存),但程序员需自行管理分配的内存区域的并发访问。若未加锁,仍可能导致竞争条件,但与mmap的共享内存相比,影响范围限于当前进程内。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
关闭