当前位置:  开发笔记 > 运维 > 正文

unshare mount命名空间无法按预期工作

如何解决《unsharemount命名空间无法按预期工作》经验,为你挑选了1个好方法。

当我调用Linux系统函数unshare(CLONE_NEWNS)时,它返回0表示成功.但是,它似乎并没有像我期望的那样起作用.特别是当我然后添加一个新的挂载(如tmpfs)时,它是全局可见的.因此,它实际上不是预期的私有安装命名空间.

这是一个演示该问题的示例程序.编译它并在一个终端中运行它.然后打开另一个终端并检查示例程序写入的路径是否可见.它不应该是.它表现得好像取消共享呼叫没有做任何事情.我期待的是,从那一刻开始,该程序执行的任何后续安装将不会被其他进程看到.

/* Run this program as root.  As mount and unshare requires higher privileges. */

#define _GNU_SOURCE
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define errExit(msg)    do { perror(msg); exit(EXIT_FAILURE); \
    } while (0)

int main(int argc, char *argv[])
{
    // Create a temporary directory at /tmp/unshare
    mkdir("/tmp/unshare", S_IRWXG);
    if (unshare(CLONE_NEWNS) == -1)
        errExit("unshare");

    if (mount("none", "/tmp/unshare", "tmpfs", 0, "mode=0700") == -1)
        errExit("unshare");

    FILE* fp = fopen("/tmp/unshare/test", "w");
    fprintf(fp, "This file should not be seen by other processes right?\n");
    fclose(fp);

    // Pause
    printf("Now open another shell.  As the root user, verify the file /tmp/unshare/test is not seen\n.Press enter end finish\n");
    char c = getchar();

    if (umount("/tmp/unshare") == -1)
        errExit("umount");
}

我应该指出,mount manpage建议这应该有效.特别标记为"每个进程名称空间"的部分.

A process can obtain a private mount namespace if ... 
it calls unshare(2)  with  the  CLONE_NEWNS  flag,  which
causes  the  caller's  mount  namespace to obtain a private copy of the
namespace that it was previously sharing with other processes, so  that
future  mounts  and  unmounts by the caller are invisible to other pro?
cesses (except child processes that the  caller  subsequently  creates)
and vice versa.

如果您使用unshare terminal命令,它可以工作.但这也要求另一个过程.但是手册页建议在使用unshare系统调用时不需要fork或clone.我在这做错了什么?



1> Matt..:

运行strace后,我找到了答案.

\> strace unmount -m true
...
unshare(CLONE_NEWNS)                    = 0
mount("none", "/", NULL, MS_REC|MS_PRIVATE, NULL) = 0
execve("/home/matt/.nvm/versions/node/v6.9.1/bin/true", ["true"], [/* 29 vars */]) = -1 ENOENT (No such file or directory)
...

请注意取消共享后的挂载.此挂载调用似乎递归地将对挂载的所有后续更改标记为私有.看看这个沙盒代码:https://github.com/swetland/mkbox 作者也在这样做.

所以这是工作版本.

/* Run this program as root.  As mount and unshare requires higher privileges. */

#define _GNU_SOURCE
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define errExit(msg)    do { perror(msg); exit(EXIT_FAILURE); \
    } while (0)

int main(int argc, char *argv[])
{
    // Create a temporary directory at /tmp/unshare
    mkdir("/tmp/unshare", S_IRWXG);
    if (unshare(CLONE_NEWNS | CLONE_FS | CLONE_THREAD) == -1)
        errExit("unshare");

    /* ensure that changes to our mount namespace do not "leak" to
     * outside namespaces (what mount --make-rprivate / does)
     */
    if (mount("none", "/", NULL, MS_REC|MS_PRIVATE, NULL) == -1)
        errExit("mount1");

    if (mount("none", "/tmp/unshare", "tmpfs", 0, NULL) == -1)
        errExit("mount2");

    // if (mount("none", "/tmp/unshare", NULL, MS_PRIVATE, NULL) == -1)
    //  errExit("mount2");

    FILE* fp = fopen("/tmp/unshare/test", "w");
    fprintf(fp, "This file should not be seen\n");
    fclose(fp);

    // Pause
    printf("Now open another shell.  As the root user, verify the file /tmp/unshare/test is not seen\n.Press enter end finish\n");
    char c = getchar();

    if (umount("/tmp/unshare") == -1)
        errExit("umount");
}

推荐阅读
wurtjq
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有