[译] malloc中的系统调用brk和mmap
source link: http://www.pengrl.com/p/20032/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
阅读本文前你可能已经知道,malloc通过系统调用的方式从操作系统申请内存。事实上,malloc内部是通过系统调用 brk 或 mmap 来申请内存的。如下面的进程虚拟内存布局图所示,mmap对应 Memory Mapping Segment
,brk对应 Heap
。
brk
brk 通过增加program break的位置( brk )从内核申请(非零值初始化的)内存。一开始,堆段(heap segment)的起始位置( start_brk )和结束位置( brk )指向同一个位置:
- 当 ASLR (Address Space Layout Randomization)关闭时,
start_brk
和brk同时指向data/bss
段的结束位置( end_data )。 - 当ASLR打开时,
start_brk
和brk同时指向data/bss
段的结束位置(end_data
)再加上一个随机的brk偏移。
上面的进程虚拟内存布局图展示了,start_brk是堆段的开始位置,brk(program break)则是堆段的结束位置。
例子:
/* sbrk, brk 例子 */ #include <stdio.h> #include <unistd.h> #include <sys/types.h> int main() { void *curr_brk, *tmp_brk = NULL; printf("Welcome to sbrk example:%d\n", getpid()); /* sbrk(0) 获取当前 program break 位置 */ tmp_brk = curr_brk = sbrk(0); printf("Program Break Location1:%p\n", curr_brk); getchar(); /* 使用 brk 增加 program break 位置 */ brk(curr_brk+4096); curr_brk = sbrk(0); printf("Program break Location2:%p\n", curr_brk); getchar(); /* 使用 brk 减小 program break 位置 */ brk(tmp_brk); curr_brk = sbrk(0); printf("Program Break Location3:%p\n", curr_brk); getchar(); return 0; }
在增加program break之前,输出如下:
sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/syscalls$ ./sbrk Welcome to sbrk example:6141 Program Break Location1:0x804b000 ... sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/syscalls$ cat /proc/6141/maps ... 0804a000-0804b000 rw-p 00001000 08:01 539624 /home/sploitfun/ptmalloc.ppt/syscalls/sbrk b7e21000-b7e22000 rw-p 00000000 00:00 0 ...
-
start_brk=brk=end_data=0x804b000
此时没有堆段。
译者yoko注,这里通过 cat /proc/<pid>/maps
的方式查看进程映射的内存区域,输出的含义下文会具体讲
在增加program break之后,输出如下:
sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/syscalls$ ./sbrk Welcome to sbrk example:6141 Program Break Location1:0x804b000 Program Break Location2:0x804c000 ... sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/syscalls$ cat /proc/6141/maps ... 0804a000-0804b000 rw-p 00001000 08:01 539624 /home/sploitfun/ptmalloc.ppt/syscalls/sbrk 0804b000-0804c000 rw-p 00000000 00:00 0 [heap] b7e21000-b7e22000 rw-p 00000000 00:00 0 ...
start_brk=end_data=0x804b000 brk=0x804c000
可以观察到堆段。
其中 0804b000-0804c000 rw-p 00000000 00:00 0 [heap]
的含义:
-
0804b000-0804c000
是这个堆段的虚拟地址范围。 -
rw-p
标准的含义是Read, Write, NoeXecute, Private
-
00000000
是文件偏移量,由于并没有映射任何文件,所以为零 -
00:00
是major/minor device number,由于并没有映射任何文件,所以为零 -
0
是inode,由于并没有映射任何文件,所以为零 -
[heap]
是堆段
mmap
malloc使用 mmap 创建一个私有匿名的映射段。这个映射段的主要目的是申请一块(零值初始化的)新内存,并且这块内存只能被调用的这个进程独占使用。
例子:
/* 使用mmap系统调用做私有匿名映射的例子 */ #include <stdio.h> #include <sys/mman.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h> void static inline errExit(const char* msg) { printf("%s failed. Exiting the process\n", msg); exit(-1); } int main() { int ret = -1; printf("Welcome to private anonymous mapping example::PID:%d\n", getpid()); printf("Before mmap\n"); getchar(); char* addr = NULL; addr = mmap(NULL, (size_t)132*1024, PROT_READ|PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (addr == MAP_FAILED) errExit("mmap"); printf("After mmap\n"); getchar(); /* Unmap mapped region. */ ret = munmap(addr, (size_t)132*1024); if(ret == -1) errExit("munmap"); printf("After munmap\n"); getchar(); return 0; }
调用mmap之前:如下输出我们可以看到,只有属于 libc.so
和 ld-linux.so
共享库的内存映射段。
sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/syscalls$ cat /proc/6067/maps 08048000-08049000 r-xp 00000000 08:01 539691 /home/sploitfun/ptmalloc.ppt/syscalls/mmap 08049000-0804a000 r--p 00000000 08:01 539691 /home/sploitfun/ptmalloc.ppt/syscalls/mmap 0804a000-0804b000 rw-p 00001000 08:01 539691 /home/sploitfun/ptmalloc.ppt/syscalls/mmap b7e21000-b7e22000 rw-p 00000000 00:00 0 ...
调用mmap之后:如下输出我们可以观察到,我们mmap映射的内存段( b7e00000–b7e21000
,大小是132KB)和已经存在的内存映射段( b7e21000–b7e22000
)合并了(变成 b7e00000-b7e22000
)。
sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/syscalls$ cat /proc/6067/maps 08048000-08049000 r-xp 00000000 08:01 539691 /home/sploitfun/ptmalloc.ppt/syscalls/mmap 08049000-0804a000 r--p 00000000 08:01 539691 /home/sploitfun/ptmalloc.ppt/syscalls/mmap 0804a000-0804b000 rw-p 00001000 08:01 539691 /home/sploitfun/ptmalloc.ppt/syscalls/mmap b7e00000-b7e22000 rw-p 00000000 00:00 0 ...
其中 b7e00000-b7e22000 rw-p 00000000 00:00 0
的含义:
b7e00000-b7e22000 rw-p is Flags (Read, Write, NoeXecute, Private) 00000000 00:00 0
调用munmap之后:如下输出我们可以看到,mmap映射的内存段已经被解除映射了,换言之,相应的已归还给操作系统。
sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/syscalls$ cat /proc/6067/maps 08048000-08049000 r-xp 00000000 08:01 539691 /home/sploitfun/ptmalloc.ppt/syscalls/mmap 08049000-0804a000 r--p 00000000 08:01 539691 /home/sploitfun/ptmalloc.ppt/syscalls/mmap 0804a000-0804b000 rw-p 00001000 08:01 539691 /home/sploitfun/ptmalloc.ppt/syscalls/mmap b7e21000-b7e22000 rw-p 00000000 00:00 0 ...
注意:我们以上所做实验,ASLR是关闭的。
英文原文地址: https://sploitfun.wordpress.com/2015/02/11/syscalls-used-by-malloc/
原文链接: https://pengrl.com/p/20032/
原文出处: yoko blog ( https://pengrl.com )
原文作者: yoko ( https://github.com/q191201771 )
版权声明:本文欢迎任何形式转载,转载时完整保留本声明信息(包含原文链接、原文出处、原文作者、版权声明)即可。本文后续所有修改都会第一时间在原始地址更新。
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK