一个简单的问题(我希望)。如何通过mlock分配地址空间,然后在该空间内启动应用程序?
例如,我有一个二进制文件,它从一个配置环境的包装器程序启动。我只能访问包装器代码,并希望在某个地址空间中启动二进制文件。是否可以从包装器中执行此操作?
谢谢!
答案 0 :(得分:3)
如果您拥有该程序的源代码,请添加命令行选项,以便程序在某个时刻调用mlockall(MCL_CURRENT | MCL_FUTURE)
。这将它锁定在内存中。
如果要控制内核加载程序的地址空间,则需要深入研究内核内部。最有可能的是,没有理由这样做;只有拥有非常时髦硬件的人才会。
如果您没有源代码,或者不想重新编译程序,那么您可以创建一个执行命令的动态库,并通过LD_PRELOAD
将其注入流程
将以下内容另存为lockall.c
:
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
#include <errno.h>
static void wrerr(const char *p)
{
if (p) {
const char *q = p + strlen(p);
ssize_t n;
while (p < q) {
n = write(STDERR_FILENO, p, (size_t)(q - p));
if (n > 0)
p += n;
else
if (n != -1 || errno != EINTR)
return;
}
}
}
static void init(void) __attribute__((constructor));
static void init(void)
{
int saved_errno = errno;
if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
const char *errmsg = strerror(errno);
wrerr("Cannot lock all memory: ");
wrerr(errmsg);
wrerr(".\n");
exit(127);
} else
wrerr("All memory locked.\n");
errno = saved_errno;
}
使用
将其编译为动态库liblockall.so
gcc -Wall -O2 -fPIC -shared lockall.c -Wl,-soname,liblockall.so -o liblockall.so
在典型的某处安装库,例如
sudo install -o 0 -g 0 -m 0664 liblockall.so /usr/lib/
所以你可以运行任何二进制文件,并使用
将其锁定到内存中LD_PRELOAD=liblockall.so binary arguments..
如果您将库安装在其他位置(未在/etc/ld.so.conf
中列出),则需要指定库的路径,例如
LD_PRELOAD=/usr/lib/liblockall.so binary arguments..
通常,当以普通用户身份运行命令时,您将看到插入库打印的消息Cannot lock all memory: Cannot allocate memory.
。 (超级用户或root用户通常没有这样的限制。)这是因为出于显而易见的原因,大多数Linux发行版限制了非特权用户可以锁定到内存的内存量;这是RLIMIT_MEMLOCK
resource limit。运行ulimit -l
以查看当前设置的每个进程资源限制(显然对于当前用户)。
我建议你设置一个合适的限制,让进程可以运行多少内存,例如: ulimit -l 16384
bash-built-in执行之前(将限制设置为16384 * 1024字节,或16 MiB),如果以超级用户(root)身份运行。如果进程泄漏内存,而不是使您的计算机崩溃(因为它锁定了所有可用内存),则进程将死亡(来自SIGSEGV
),如果超出限制。也就是说,您可以使用
ulimit -l 16384
LD_PRELOAD=/usr/lib/liblockall.so binary arguments..
如果使用Bash或破折号外壳。
如果以专用用户身份运行,大多数发行版都使用pam_limits.so
PAM模块自动设置资源限制&#34;。限制列在/etc/security/limits.conf
文件中,或/etc/security/limits.d/
子目录中的文件中,使用this format; memlock
项指定每个进程可以锁定的内存量,以1024字节为单位。因此,如果您的服务以用户mydev
运行,并且您希望允许用户锁定每个进程最多16兆字节= 16384 * 1024字节,则将行mydev - memlock 16384
添加到/etc/security/limits.conf
或/etc/security/limits.d/mydev.conf
,无论您的Linux发行版更喜欢/建议哪个。
在PAM之前,shadow-utils用于控制资源限制。 memlock资源限制以1024字节为单位指定;使用M16384
设置的限制为16兆字节。因此,如果使用shadow-utils而不是PAM,则向mydev M16384
添加行/etc/limits
(后跟您希望指定的其他限制)应该可以解决问题。