此命令序列有效:
unshare --fork --pid --mount
umount /proc
mount -t proc proc /proc
umount /dev/pts
mount -t devpts devpts /dev/pts
但是,相应的C程序无法按预期运行(它似乎没有卸载先前的/proc,并且它提供EBUSY试图卸载devpts):
unshare(CLONE_NEWPID | CLONE_NEWNS );
int pid = fork();
if (pid != 0) {
int status;
waitpid(-1, &status, 0);
return status;
}
printf("My pid: %i\n", getpid()); // It prints 1 as expected
umount("/proc"); // Returns 0
system("mount"); // Should print error on mtab, but it prints the previous mounted filesystems
mount("proc", "/proc", "proc",
MS_MGC_VAL | MS_NOSUID | MS_NOEXEC | MS_NODEV,
NULL)); // Returns 0
umount("/dev/pts"); // Returns -1 errno = 0 (??)
mount("devpts", "/dev/pts", "devpts",
MS_MGC_VAL | MS_NOSUID | MS_NOEXEC | MS_NODEV,
NULL) ); // Returns -1 errno = EBUSY
我在这里省略了可读性的错误检查
我认为unshare或unmount不能按预期工作:即使返回零,似乎也不能卸载/proc(如果我之后尝试执行
system("mount")
,它将打印已挂载的文件系统)。 最佳答案
尽管您有评论
,在您的pastebin进行的10000次代码试用中,umount()
总是对我失败,返回-1
而不卸载/proc
。我不敢相信umount()
会返回0
,尽管未能执行请求的卸载,但是如果这样做,那将构成umount()
中的错误。如果实际上您可以证实这种错误,那么社区意识的回应就是针对glibc提交错误报告。
问题变成了为什么以及您的bash
脚本表现不同。但是实际上,它似乎没有。
首先,您对unshare(1)
命令有错误的期望。与unshare(2)
函数不同,unshare
命令不影响在其中执行命令的shell。相反,它将启动一个单独的进程,该进程具有自己的指定 namespace 的私有(private)副本。通常,您将在unshare
命令行上指定启动该进程的命令,实际上,该程序的手册页指示这样做是强制性的。
根据经验,我发现,如果您未能指定这样的命令(如您所做的那样),那么unshare
将启动一个新的Shell作为目标进程。特别是,当我运行您的脚本(具有足够的特权来使用unshare
)时,我立即获得一个新的提示,但这是在前台运行的新shell的提示。这对我来说立即显而易见,因为提示有所不同(但是,在这种情况下,您的提示可能没有任何不同)。此时umount
尚无错误消息等,因为它尚未运行。如果我手动尝试在(umount
d)子 shell 中使用unshare
proc,它将因“设备繁忙”而失败-这类似于您的C程序尝试执行的操作。
当我退出子Shell时,脚本的其余部分将运行,并且umount
和mount
都失败。这是可以预期的,因为主脚本共享其安装 namespace 。
完全合理的是,/proc
确实很忙,因此无法卸载,即使对于具有安装命名空间的专用副本的进程也是如此。这样的过程很可能本身就是使用/proc
挂载的私有(private)副本。相反,我发现我可以在具有未共享的安装 namespace 的进程中成功卸载/dev/pts
,但不能在共享该 namespace 的系统副本的进程中成功卸载ojit_code。
关于c - 'unshare'在C api中无法正常工作,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34872453/