linux - 控制另一个进程的内存映射

标签 linux process mmap virtual-memory

是否有可能以某种方式更改 Linux 中另一个进程的内存映射?相反,也就是说,只能通过调用 mmap 的进程本身运行的代码来控制它。

我问的原因是因为我希望能够使用非常自定义的内存映射构建一个进程,并且不能使用共享库甚至 vDSO,我看不到任何方法在进程本身内执行此操作,基本上不涉及编写我自己的 libc 来处理系统调用等。 (即使我要静态链接 libc,它不会尝试使用 vDSO 吗?)

最佳答案

mmap 映射内存由 fork 保留,但会被 exec 系列的系统调用删除,因此无法通过经典序列 fork,设置内容然后 exec

一个简单的解决方案是使用 LD_PRELOAD Hook 。让我们将这段代码放在 add_mmap.c 中。

#include <sys/mman.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

void add_mmap(void) __attribute__((constructor));

void add_mmap(void)
{
    int fd;
    void *addr;

    printf("calling mmap() before main...\n");
    fd = open("/etc/passwd", O_RDONLY);
    printf("fd=%d\n", fd);
    /* map the first 100 bytes of the file to an address chosen by the kernel */
    addr = mmap(0, 100, PROT_READ, MAP_SHARED, fd, 0);
    printf("addr=%llx\n", (long long unsigned)addr);
}

然后,将其构建为动态库:

gcc -Wall -g -fPIC -shared -o add_mmap.so add_mmap.c

最后用它运行一些现有的程序:

$ LD_PRELOAD=./add_mmap.so /bin/cat 
calling mmap() before main...
fd=3
addr=7fe4916f8000

我们可以检查映射是否在 cat 运行之前设置并保存:

$ cat /proc/27967/maps
...
7f2f7f2d0000-7f2f7f2d1000 r--s 00000000 09:00 1056387                    /etc/passwd
...

编辑

我在这里只展示了如何在程序启动之前添加内存映射,但是我的示例可以很容易地扩展为在程序中透明地注入(inject)一个“内存管理器”线程。该线程将通过套接字等 IPC 机制接收命令,并相应地操作映射。

关于linux - 控制另一个进程的内存映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23617448/

相关文章:

c++ - linux/unix 下是否有相当于 WinAPI 的 MAX_PATH 的?

linux - Raspberry Pi 键盘接口(interface)(按键重映射?)

javascript - 如何在 npm install 中克服这个错误?

linux - 为什么内存映射区域在 Linux 中会向下增长

linux - malloc 中的 mmap 选项

linux - 用于开发和生产的不同 url

php - 如果用户关闭连接,apache会杀死PHP进程吗

Perl 进程文件句柄

node.js - 如何列出脚本中分离的进程?

c - 使用 mmap() 如何创建动态大小的结构