仅与多个子进程之一共享内存?

时间:2021-01-02 06:56:56

标签: c linux security shared-memory

我正在 Linux 上使用 C 语言开发一个应用程序,该应用程序管理多个沙盒环境,每个环境都在自己的内核命名空间中。这些环境最终旨在尽可能与系统的其余部分和彼此隔离,但仍然需要通过共享内存区域等方式与它们进行通信的能力。我目前通过 mmapMAP_SHAREDMAP_ANONYMOUS 共享内存来完成这项工作,但这当然授予 all 子进程访问 all 我的应用程序的共享内存。似乎没有一种简单的/“内置”方式来指定一个内存区域与一个子进程共享(即不是 PRIVATE)但不是与所有子进程共享(即不是 {{1 }}) 或者。

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 state\n");

    //Wait for both processes to return
    waitpid(pid1, NULL, 0);
    waitpid(pid2, NULL, 0);

    return 0;
}

限制共享内存仅访问其中之一的最佳方法是什么?我可以想象,也许每个沙箱都使用一个受信任的子进程来执行此操作,但这似乎很棘手且过于复杂 - 肯定有更好的方法来做到这一点吗?

1 个答案:

答案 0 :(得分:1)

我假设父进程想要​​与所有子进程交谈,但每个子进程只应该“看到”父进程。

每个孩子需要一个 mmap 句柄。首先,创建尽可能多的手柄,您希望有孩子。然后,对于每个子进程,克隆,关闭除 fork 子进程之外的所有句柄(这会从子进程中取消映射禁止内存),然后留在进程中并运行子代码,或者执行子进程二进制,保留打开的句柄。