【问题标题】:Controlling the memory map of another process控制另一个进程的内存映射
【发布时间】:2014-06-30 07:29:53
【问题描述】:

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

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

【问题讨论】:

  • 我怀疑 ptrace 可以实现这一点,但我不知道细节。
  • @nneonneo:如果是这样,那么ptrace 手册页肯定没有说清楚。 :)
  • 最愚蠢(但足够)的方法之一是使用ptrace 暂停目标,修补接下来的几条指令以包含对mmap 的所需调用,然后恢复它。处理完mmap 后,您取消修补目标并恢复指令指针。这是邪恶的,但它会起作用(this page 提供了类似技术的详细信息)。
  • 当然,但是我认为只编写我自己的 libc 会更容易和更清晰。 :)
  • 实际上您可能想编写自己的程序解释器 (ld.so)。该程序在实际目标之前运行,并负责将所有内容链接到位(包括为所有共享库依赖项分配内存映射)

标签: linux process mmap virtual-memory


【解决方案1】:

mmap 映射内存由fork 保留,但被exec 系列的系统调用擦除,因此经典序列fork 无法实现这一点,然后设置东西exec。

一个简单的解决方案是使用LD_PRELOAD 挂钩。让我们把这段代码放在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
...

编辑

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

【讨论】:

  • 很抱歉,但我必须承认我不明白这是如何回答问题的。
  • 我理解您的问题的方式是如何构建内存映射,然后将其传递给某个现有程序。也许您应该准确说明您正在做什么以及您期望的答案是什么。
  • 嗯,直接的问题是是否可以操纵 另一个 进程的内存布局。 :) 但是,您似乎试图回答的更一般的问题是关于完全任意地构建进程的内存空间;而据我所知,您的回答仅涉及 adding 映射。我必须承认,我不太明白如何重新表述这个问题以更清楚地说明这一点。
  • @Dolda2000 好的,所以我的回答并不像您在第一条评论中所说的那样完全离题。我向您展示了如何添加映射。我的示例可以很容易地扩展为在程序中透明地注入“内存管理器”线程。该线程将通过 IPC 机制(如套接字)接收订单并相应地操作映射。
  • 当然可以,但我想我在这个问题中已经说清楚了,为什么我想避免从进程本身控制内存映射的想法。 :)
猜你喜欢
  • 2014-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-16
  • 1970-01-01
相关资源
最近更新 更多