#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.