mmap 系统调用失败,错误号为 14

mmap syscall fails with errno 14

我试图在另一个进程上使用 MMAP 进行系统调用注入,但失败了。我注意到系统调用执行正常,所以问题应该出在其他地方。我决定直接通过目标程序 运行 系统调用,使其更易于理解。毫不奇怪,它也没有用,我真的不知道为什么:

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <sys/errno.h>

int main()
{
    void* addr = 0;
    size_t len = sysconf(_SC_PAGE_SIZE);
    int prot = PROT_EXEC | PROT_READ | PROT_WRITE;
    int flags = MAP_PRIVATE | MAP_ANON;
    int fd = -1;
    off_t offset = 0;
    
    void* alloc0 = mmap(addr, len, prot, flags, fd, offset); //this works
    void* alloc1 = syscall(__NR_mmap, addr, len, prot, flags, fd, offset); //this doesn't work

    printf("Alloc0: %p\n", alloc0);
    printf("Alloc1: %p\n", alloc1);
    printf("Errno:  %i\n", errno);

    return 0;
}

输出:

Alloc0: 0xf7fac000
Alloc1: 0xffffffff
Errno:  14

为什么正常的 mmap 可以工作,而具有相同参数的 mmap 系统调用不能工作?
我是 运行ning Manjaro,程序是用 GCC 在 32 位上编译的。另外,当我以 64 位编译它时,它工作得很好,没有错误。有什么想法吗?

32 位(至少是 32 位 x86)上的遗留 __NR_mmap 系统调用没有该签名。它接受一个指向 struct mmap_arg_struct32 的指针的参数;参见 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/sys_ia32.c?id=v5.9#n214。自 90 年代中后期以来,此系统调用已被弃用,不应使用。错误编号 14 是 EFAULT,反映出您的第一个参数不是指向此类结构的有效指针。

现代替代品是 __NR_mmap2 并且它采用类似于 mmap 函数的参数,除了 offset 是 4k 单位的 32 位计数,而不是直接偏移.这允许寻址偏移量高达 2^44。