clone() 之后的 mount() with CLONE_NEWNS set effects parent

mount() after clone() with CLONE_NEWNS set effects parent

我对这里发生的事情有点困惑。我正在关注 guide,其中在调用设置了 CLONE_NEWNS 标志的克隆之后添加了一个新的挂载点。挂载点应该只存在于子进程中。我正在尝试更改新的文件系统命名空间,它似乎影响了父命名空间。

我的c程序很简单。 Main 会调用 clone

pid_t pid = clone(child_exec,c_stack, SIGCHLD | CLONE_NEWNS | CLONE_NEWPID ,args);

args 是一个聊天数组,其中包含要执行的命令。

int child_exec(void *arg)
{
        int err =0; 
        char **commands = (char **)arg;
        mount("none", "/mytmp", "tmpfs", 0, "");    
        execvp(commands[0],commands);   
        return 0;
}

如果传递给 execvp 的命令是 mount 我希望输出包含 /mytmp 挂载点并且 运行 在程序退出后再次执行命令 mount看不到 /mytmp 出现。那没有发生。我在调用 execvp 时以及在 运行 mount.

之后看到它

我尝试使用 MS_PRIVATE 标志安装并使用 unshare(CLONE_FS);

我也遇到了类似的问题,我试图从子进程中卸载 /proc,但出现获取资源繁忙错误。我认为新命名空间不应该发生这种情况。

这对我来说归结为两个问题。

首先,我正在使用的 Ubuntu(16.04.1 LTS) 或 util-linux 包的版本似乎共享 / mount 命名空间并且 CLONE_NEWNS 传播了它环境。我的 / 挂载已共享。我在 /proc/self/mountinfo 和 /proc/1/mountinfo 中验证了这一点。我从这个答案中尝试 sudo mount --make-private -o remount / 并升级了提到的包。 https://unix.stackexchange.com/questions/246312/why-is-my-bind-mount-visible-outside-its-mount-namespace。这让我可以在不影响父名称空间的情况下进行额外的挂载。

第二个问题是卸载/proc。这没有用,因为我的系统 /proc/sys/fs/binfmt_misc 安装了两次。这里的讨论启发了我去检查一下。 http://linux-kernel.vger.kernel.narkive.com/aVUicig1/umount-proc-after-clone-newns-in-2-6-25

我的最终 child_exec 代码最终是

int child_exec(void *arg)
{
        int err =0; 
        char **commands = (char **)arg;
        printf("child...%s\n",commands[0]);
//      if(unshare(CLONE_NEWNS) <0)
//              printf("unshare issue?\n");
        if (umount("/proc/sys/fs/binfmt_misc") <0) 
                printf("error unmount bin: %s\n",strerror(errno));
        if (umount("/proc/sys/fs/binfmt_misc") <0) 
                printf("error unmount bin: %s\n",strerror(errno));
        if (umount("/proc") <0) 
                printf("error unmount: %s\n",strerror(errno));
        if (mount("proc", "/proc", "proc",0, NULL) <0) 
                printf("error mount: %s\n",strerror(errno));
        execvp(commands[0],commands);   
        return 0;
}