linux 0xc0000000 64位,为什么不能在64位内核的32位Linux进程中映射(MAP_FIXED)最高虚拟页面?...

博客探讨了在32位Linux用户空间中尝试映射包括零边界和最高页面的内存区域的问题。作者通过mmap系统调用尝试映射-4096地址,但遇到了ENOMEM错误。分析表明,尽管可以映射零页面,但内核不允许映射最高页面。讨论了可能的原因,包括内核保护高地址空间以及防止指针回绕的考虑。源代码和系统调用顺序的细节也进行了说明。
摘要由CSDN通过智能技术生成

尝试测试时是否允许访问跨越x86中零边界的内存?在Linux的用户空间中,我编写了一个32位测试程序,该程序试图映射32位虚拟地址空间的低和高页。

之后echo 0 | sudo tee

/proc/sys/vm/mmap_min_addr,我可以映射零页面,但是我不知道为什么不能映射-4096(即(void*)0xfffff000最高页面)。

为什么要mmap2((void*)-4096)退货-ENOMEM?

strace ./a.out

execve("./a.out", ["./a.out"], 0x7ffe08827c10 /* 65 vars */) = 0

strace: [ Process PID=1407 runs in 32 bit mode. ]

....

mmap2(0xfffff000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = -1 ENOMEM (Cannot allocate memory)

mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0

另外,什么支票在中拒绝它linux/mm/mmap.c,为什么要这样设计?这是确保创建指向一个过去的对象的指针不会回绕并中断指针比较的部分吗,因为ISO C和C

++允许创建指向过去的一个指针,但不能在外部对象。

我在64位内核(Arch

Linux上为4.12.8-2-ARCH)下运行,因此32位用户空间具有整个可用的4GiB。(与64位内核或32位内核(其中2:2或3:1用户/内核拆分会使高页成为内核地址)上的64位代码不同。)

我没有尝试使用最小的静态可执行文件(没有CRT启动程序或libc,只有asm),因为我认为这不会有所作为。没有一个CRT启动系统调用看起来可疑。

在断点处停下来时,我检查了一下/proc/PID/maps。主页尚未使用。堆栈包括第二高的页面,但未映射首页。

00000000-00001000 rw-p 00000000 00:00 0 ### the mmap(0) result

08048000-08049000 r-xp 00000000 00:15 3120510 /home/peter/src/SO/a.out

08049000-0804a000 r--p 00000000 00:15 3120510 /home/peter/src/SO/a.out

0804a000-0804b000 rw-p 00001000 00:15 3120510 /home/peter/src/SO/a.out

f7d81000-f7f3a000 r-xp 00000000 00:15 1511498 /usr/lib32/libc-2.25.so

f7f3a000-f7f3c000 r--p 001b8000 00:15 1511498 /usr/lib32/libc-2.25.so

f7f3c000-f7f3d000 rw-p 001ba000 00:15 1511498 /usr/lib32/libc-2.25.so

f7f3d000-f7f40000 rw-p 00000000 00:00 0

f7f7c000-f7f7e000 rw-p 00000000 00:00 0

f7f7e000-f7f81000 r--p 00000000 00:00 0 [vvar]

f7f81000-f7f83000 r-xp 00000000 00:00 0 [vdso]

f7f83000-f7fa6000 r-xp 00000000 00:15 1511499 /usr/lib32/ld-2.25.so

f7fa6000-f7fa7000 r--p 00022000 00:15 1511499 /usr/lib32/ld-2.25.so

f7fa7000-f7fa8000 rw-p 00023000 00:15 1511499 /usr/lib32/ld-2.25.so

fffdd000-ffffe000 rw-p 00000000 00:00 0 [stack]

是否有没有出现的VMA区域maps仍然说服内核拒绝该地址?我查看了ENOMEMin

的出现linux/mm/mmapc.,但是要阅读很多代码,所以也许我错过了一些东西。保留一些高地址范围的东西,还是因为它在堆栈旁边?

以其他顺序进行系统调用无济于事(但是PAGE_ALIGN和类似的宏会被仔细地编写,以避免在屏蔽之前回绕,因此无论如何都不可能。)

完整源代码,使用编译gcc -O3 -fno-pie -no-pie -m32 address-wrap.c:

#include

//void *mmap(void *addr, size_t len, int prot, int flags,

// int fildes, off_t off);

int main(void) {

volatile unsigned *high =

mmap((void*)-4096L, 4096, PROT_READ | PROT_WRITE,

MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS,

-1, 0);

volatile unsigned *zeropage =

mmap((void*)0, 4096, PROT_READ | PROT_WRITE,

MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS,

-1, 0);

return (high == MAP_FAILED) ? 2 : *high;

}

(我省去了尝试取消引用的部分,(int*)-2因为它在mmap失败时只会出现段错误。)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值