【发布时间】:2017-05-24 11:43:21
【问题描述】:
调用Linux系统函数unshare(CLONE_NEWNS),返回0表示成功。但是,它似乎没有像我预期的那样工作。 具体来说,当我添加一个新的挂载(例如 tmpfs 挂载)时,它是全局可见的。因此,它实际上并不是预期的私有挂载命名空间。
这是一个演示该问题的示例程序。编译它并在一个终端中运行它。然后打开另一个终端,检查示例程序写入的路径是否可见。不应该,但确实如此。它的行为好像 unshare 调用什么也没做。我所期待的是,从那一刻起,该程序执行的任何后续挂载都不会对其他进程可见。
/* Run this program as root. As mount and unshare requires higher privileges. */
#define _GNU_SOURCE
#include <sched.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mount.h>
#include <stdlib.h>
#include <stdio.h>
#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 手册页表明这应该可以工作。特别是标记为“每进程命名空间”的部分。
即
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 终端命令,它可以工作。但这也分叉了另一个过程。但是手册页建议在使用 unshare 系统调用时不需要分叉或克隆。我在这里做错了什么?
【问题讨论】:
-
老兄,unshare(CLONE_NEWNS) 是一个 C 调用!这是使用 linux API。题外话是什么意思?我需要这个从 C 中工作。
-
你是如何挂载文件系统的?在程序退出后从同一个程序还是从您的 shell?
-
从程序中使用 mount 系统调用。没有外壳。
-
能否附上演示问题的小程序源代码?
-
跟踪您的
unshare命令并查看它调用了哪些系统调用。