我正在Linux上用C语言开发一个应用程序,该应用程序管理多个沙盒环境,每个沙盒环境都有自己的内核命名空间。这些环境最终旨在尽可能地与系统的其他部分和彼此隔离,但仍然需要通过共享内存区域与它们通信的能力。我目前通过mmap
与MAP_SHARED
和MAP_ANONYMOUS
共享内存来实现这一点,但这当然允许所有子进程访问我的应用程序的所有共享内存。似乎没有一个琐碎的/";内置的";指定存储器区域将与一个子进程(即不是PRIVATE
(共享但也不与所有子进程(即也不是SHARED
(共享的方式。
#define _GNU_SOURCE
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/mount.h>
#include <stdio.h>
#include <sched.h>
#include <signal.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <string.h>
#include <sys/mman.h>
//Stack size for the containers
#define STACK_SIZE (1024 * 1024)
int *share;
//Two child processes that just read and print the shared state
int child1(void* arg){
for(int i=0;i<6;i++){
printf("Child 1 reads state as: %d.n", *share);
sleep(1);
}
return 1;
}
int child2(void* arg){
for(int i=0;i<6;i++){
printf("Child 2 reads state as: %d.n", *share);
sleep(1);
}
return 1;
}
int main(){
static char *stack_top;
//Map shared memory for the shared value - how do I share this with only one child process?
share = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
*share = 0;
//Map memory for a stack for each child namespace and start them
stack_top = mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
pid_t pid1 = clone(child1, stack_top + STACK_SIZE, CLONE_NEWNET | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWUSER | CLONE_NEWCGROUP | SIGCHLD, NULL);
stack_top = mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
pid_t pid2 = clone(child2, stack_top + STACK_SIZE, CLONE_NEWNET | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWUSER | CLONE_NEWCGROUP | SIGCHLD, NULL);
//Wait, then change the state
sleep(3);
*share = 1;
printf("Changing staten");
//Wait for both processes to return
waitpid(pid1, NULL, 0);
waitpid(pid2, NULL, 0);
return 0;
}
这就是我现在所拥有的。显然,两个孩子都可以读取共享内存中的值。
Child 1 reads state as: 0.
Child 2 reads state as: 0.
Child 1 reads state as: 0.
Child 2 reads state as: 0.
Child 1 reads state as: 0.
Child 2 reads state as: 0.
Child 1 reads state as: 0.
Changing state
Child 2 reads state as: 1.
Child 1 reads state as: 1.
Child 2 reads state as: 1.
Child 1 reads state as: 1.
Child 2 reads state as: 1.
将共享内存访问限制为其中一种的最佳方式是什么?我可以想象,也许每个沙盒都有一个受信任的子进程,但这似乎很棘手,而且过于复杂——肯定有更好的方法可以做到这一点吗?
我假设父进程想要与所有子进程对话,但每个子进程只应该"看到"父进程。
每个孩子需要一个mmap句柄。首先,创建尽可能多的控制柄以生成子对象。然后,对于每个子进程,克隆并关闭除fork所在的子进程之外的所有句柄(这将取消对子进程的内存限制(,然后留在进程中并运行子代码,或者执行子二进制文件,保留打开的句柄。