我正在为 Linux 编写一个静态程序加载器,我正在读取 ELF 程序头并将段映射到内存。
我遇到了一个可执行文件,它假设其第一个段的虚拟地址为 0。我的内存映射失败,在地址
0
处分配虚拟页时出错。
我想知道是否可以在地址
0
处为用户空间分配所有内存。
请参阅此示例代码:
/*mmaptests.c*/
#include <sys/mman.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
int main()
{
void* p = mmap(0, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
printf("mmap result %p (errno %s)\n",p,strerror(errno));
return 0;
}
我编译它:
gcc mmaptests.c
这就是它返回的内容:
$./a.out
mmap result 0xffffffffffffffff (errno Operation not permitted)
我会很高兴获得任何见解。
谢谢 B
如果您有权限,或者在具有 sysctl 设置的系统上
mmap
(而不是默认的 65536),Linux 只会让您vm.mmap_min_addr = 0
访问第 0 页。
gcc mmaptests.c && sudo ./a.out
应该让你:
mmap result (nil) (errno Success)
根据 https://wiki.debian.org/mmap_min_addr,16 位 Windows 应用程序的 WINE 需要
vm.mmap_min_addr = 0
,旧版本的 QEMU 也需要以非 root 身份运行。不过,即使在这些软件包的安装程序中,大多数发行版也不会这样做,因为通过错误使 NULL-deref 大声失败是非常可取的。 (64 KiB 还涵盖以 0 为基数的小数组索引。)
您可以使用
cat /proc/sys/vm/mmap_min_addr
检查当前设置,或将其格式化为十六进制,printf '%#x\n' $(cat /proc/sys/vm/mmap_min_addr)