системный вызов mmap завершается с ошибкой 14

#c #c #linux #system-calls #mmap

#c #c #linux #системные вызовы #mmap

Вопрос:

Я пытался выполнить внедрение системного вызова с помощью 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: %pn", alloc0);
    printf("Alloc1: %pn", alloc1);
    printf("Errno:  %in", errno);

    return 0;
}
  

Вывод:

 Alloc0: 0xf7fac000
Alloc1: 0xffffffff
Errno:  14
  

Почему обычный mmap работает, а системный вызов mmap с теми же параметрами не работает?
Я запускаю Manjaro, и программа была скомпилирована с использованием GCC на 32 бита. Кроме того, когда я скомпилировал его в 64 бита, он работал просто отлично, без ошибок. Есть идеи?

Комментарии:

1. Вы должны сохранить значение errno сразу после неудачного системного вызова, поскольку printf оно может быть перезаписано. Кроме того, используйте perror() или strerror() для получения удобочитаемого сообщения об ошибке вместо «errno 14».

Ответ №1:

Устаревший __NR_mmap системный вызов на 32-разрядной версии (по крайней мере, на 32-разрядной x86 в любом случае) не имеет такой подписи. Он принимает один аргумент, который является указателем на a 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 это 32-битное количество единиц 4k, а не прямое смещение. Это позволяет адресовать смещения величиной до 2 ^ 44.