为何malloc返回的高地址不在/proc/pid/maps中且无法被/proc/pid/mem修改?
问题分析:Termux中malloc返回地址异常的原因
测试代码
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <assert.h> #include <sys/mman.h> int main(void){ int fd,*p1,*p2; p1=malloc(100000000); p2=mmap(NULL,100000000,PROT_READ|PROT_WRITE,MAP_ANONYMOUS|MAP_PRIVATE,-1,0); *p1=*p2=7; printf("*p1=%d,*p2=%d\n",*p1,*p2);//check the 2 addresses available fd=open("/proc/self/mem",O_RDWR); assert(fd>=0); pwrite(fd,"\5\0\0\0",4,(off_t)p1); pwrite(fd,"\5\0\0\0",4,(off_t)p2); close(fd); printf("*p1=%d,*p2=%d\n",*p1,*p2);//check the 2 addresses available printf("malloced at %p,mmaped at %p\n",p1,p2); getchar();//can look /proc/pid/maps when blocking here free(p1); munmap(p2,100000000); getchar(); }
运行输出(Termux arm64 Android)
*p1=7,*p2=7 *p1=7,*p2=5 malloced at 0xb400007c0bf81f00,mmaped at 0x7c06021000
strace关键输出
mmap(NULL, 100012032, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x7c0bf80000 mmap(0x7c0bf81000, 100003840, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7c0bf81000 ... pwrite64(3, "\5\0\0\0", 4, -5476376614105768192) = -1 EINVAL (Invalid argument) ... munmap(0x7c0bf80000, 100012032) = 0
疑问
malloc返回的地址0xb400007c0bf81f00不在/proc/pid/maps的地址范围内,且无法通过/proc/pid/mem修改该地址内容;但直接访问该地址不会触发Segmentation fault。strace显示malloc内部调用的mmap返回的是正常地址,而free(p1)时调用的munmap使用的也是该正常地址,与malloc返回的地址差异极大,请问这一现象的原因是什么?
解答
这是因为Android的bionic libc在arm64架构下启用了指针标记(Pointer Tagging)机制,基于arm64的Top-byte Ignore(TBI)特性实现:
- 指针标记原理:arm64架构的TBI允许CPU忽略虚拟地址的最高8位(第55到63位),内核仅使用低55位寻址。bionic的malloc会给返回的用户态指针的最高字节添加随机标记,你看到的
0xb400007c0bf81f00其实是真实映射地址0x7c0bf81f00加上了0xb400000000000000的标记值。 - 直接访问不崩溃的原因:CPU访问带标记的指针时会自动忽略最高8位,实际访问的是内核真实映射的地址(即strace中看到的
0x7c0bf81000附近区域),因此不会触发段错误。 - /proc/pid/mem和strace的异常表现:
/proc/pid/mem和strace直接使用用户传入的原始指针值作为操作偏移,没有处理标记位,导致带标记的地址超出内核认可的虚拟地址范围,所以pwrite返回EINVAL,且该地址不会出现在/proc/pid/maps中——maps记录的是内核实际映射的无标记真实地址。而malloc内部和free操作使用的是去除标记后的真实地址,因此strace里的mmap、munmap地址都是正常的内核映射地址。 - 机制目的:通过随机标记指针,降低UAF(Use-After-Free)、缓冲区溢出等内存漏洞的利用成功率,攻击者很难猜测到正确的标记位,即使获取到指针也无法正常使用。
内容的提问来源于stack exchange,提问作者kawayi
相关产品推荐
相关产品推荐

