gpt4 book ai didi

namespaces - unshare 命令不会创建新的 PID 命名空间

转载 作者:行者123 更新时间:2023-12-04 17:00:56 27 4
gpt4 key购买 nike

我正在学习 Linux 核心,现在正在讨论命名空间主题。我尝试使用“unshare”命令只是为了掌握命名空间及其要点。问题是它没有,或者更有可能的是,我做错了什么。如果您能帮助我理解,我将不胜感激。我尝试在它自己的 PID 命名空间内执行 busybox sh 程序。这就是我所做的:

[ab@a ~]$ sudo unshare --pid  busybox sh
/home/ab # ps
PID TTY TIME CMD
6014 pts/1 00:00:00 sudo
6016 pts/1 00:00:00 busybox
6026 pts/1 00:00:00 ps

正如我从 ps 命令的输出中看到的那样,所有进程在新环境中都是可见的。当我检查新创建的进程和当前进程的 pid 命名空间 id 时,这一点得到了确认。见下文

[ab@a ~]$ ps -p 6016,$$
PID TTY TIME CMD
4604 pts/0 00:00:00 bash
6016 pts/1 00:00:00 busybox
[ab@a ~]$ sudo ls -l /proc/4604/ns
total 0
lrwxrwxrwx. 1 ab ab 0 Aug 8 23:49 ipc -> ipc:[4026531839]
lrwxrwxrwx. 1 ab ab 0 Aug 8 23:49 mnt -> mnt:[4026531840]
lrwxrwxrwx. 1 ab ab 0 Aug 8 23:49 net -> net:[4026531968]
lrwxrwxrwx. 1 ab ab 0 Aug 8 23:49 pid -> pid:[4026531836]
lrwxrwxrwx. 1 ab ab 0 Aug 8 23:49 user -> user:[4026531837]
lrwxrwxrwx. 1 ab ab 0 Aug 8 23:49 uts -> uts:[4026531838]
[ab@a ~]$ sudo ls -l /proc/6016/ns
total 0
lrwxrwxrwx. 1 root root 0 Aug 9 00:07 ipc -> ipc:[4026531839]
lrwxrwxrwx. 1 root root 0 Aug 9 00:07 mnt -> mnt:[4026531840]
lrwxrwxrwx. 1 root root 0 Aug 9 00:07 net -> net:[4026531968]
lrwxrwxrwx. 1 root root 0 Aug 9 00:07 pid -> pid:[4026531836]
lrwxrwxrwx. 1 root root 0 Aug 9 00:07 user -> user:[4026531837]
lrwxrwxrwx. 1 root root 0 Aug 9 00:07 uts -> uts:[4026531838]

因此,尽管我为 unshare 调用提供了 --pid 参数,但 pid 命名空间仍保持不变。您能帮我理解为什么会发生这种情况吗?谢谢

最佳答案

解决方案

您应该将 --fork--mount-proc 开关添加到 unshare,如手册​​页中所述

-f, --fork
Fork the specified program as a child process of unshare rather than running it directly. This is useful
when creating a new PID namespace. Note that when unshare is waiting for the child process, then it
ignores SIGINT and SIGTERM and does not forward any signals to the child. It is necessary to send
signals to the child process.

说明(来自 man pid_namespaces)

a process's PID namespace membership is determined when the process is created and cannot be changed thereafter.

当您提供 --pid 时,unshare 实际执行的操作是将文件描述符设置在 /proc/[PID]/ns/pid_for_children将当前进程添加到新的 PID 命名空间,导致该进程随后创建的子进程被放置在不同的 PID 命名空间中(其子进程不是其本身!!重要!)。

因此,当您向 unshare 提供 --fork 时,它会将您的程序(在本例中为 busybox sh) fork 为子程序取消共享并将其放置在新的 PID 命名空间中的过程。

为什么需要--mount-proc

尝试仅使用 --pid--fork 运行 unshare,让我们看看会发生什么。

wendel@gentoo-grill ~ λ sudo unshare --pid --fork busybox sh
/home/wendel # echo $$
1
/home/wendel # ps
PID USER TIME COMMAND
12443 root 0:00 unshare --pid --fork busybox sh
12444 root 0:00 busybox sh
24370 root 0:00 {ps} busybox sh
.
.
. // bunch more

echo $$ 我们可以看到 pid 实际上是 1,所以我们知道我们必须位于新的 PID 命名空间中,但是当我们运行 ps 时,我们看到其他进程就好像我们仍在父 PID 命名空间中一样。

这是因为 /proc 是一个名为 procfs 的特殊文件系统,内核在内存中创建,并且来自手册页。

A /proc filesystem shows (in the /proc/[pid] directories) only processes visible in the PID namespace of the process that performed the mount, even if the /proc filesystem is viewed from processes in other namespaces.

因此,为了让 ps 等工具正常工作,我们需要使用新命名空间中的进程重新挂载 /proc

但是,假设您的进程位于根挂载命名空间中,如果我们重新挂载 /proc,这会弄乱同一挂载命名空间中其他进程的许多事情,因为现在它们可以什么也没有看到(在 /proc 中)。所以你也应该把你的进程放在新的挂载命名空间中。

好消息是 unshare 有 --mount-proc

--mount-proc[=mountpoint]
Just before running the program, mount the proc filesystem at mountpoint (default is /proc). This is useful when creating a new PID namespace. It also implies creating a new mount namespace since the /proc mount would
otherwise mess up existing programs on the system. The new proc filesystem is explicitly mounted as private (with MS_PRIVATE|MS_REC).

让我们验证 --mount-proc 是否也将您的进程放入新的挂载命名空间中。

外面的bash:

wendel@gentoo-grill ~ λ ls -go /proc/$$/ns/{user,mnt,pid}
lrwxrwxrwx 1 0 Aug 9 10:05 /proc/17011/ns/mnt -> 'mnt:[4026531840]'
lrwxrwxrwx 1 0 Aug 9 10:10 /proc/17011/ns/pid -> 'pid:[4026531836]'
lrwxrwxrwx 1 0 Aug 9 10:10 /proc/17011/ns/user -> 'user:[4026531837]'

忙碌盒:

wendel@gentoo-grill ~ λ doas ls -go /proc/16436/ns/{user,mnt,pid}
lrwxrwxrwx 1 0 Aug 9 10:05 /proc/16436/ns/mnt -> 'mnt:[4026533479]'
lrwxrwxrwx 1 0 Aug 9 10:04 /proc/16436/ns/pid -> 'pid:[4026533481]'
lrwxrwxrwx 1 0 Aug 9 10:17 /proc/16436/ns/user -> 'user:[4026531837]'

请注意,它们的用户命名空间相同,但 mount 和 pid 不同。

注意:您可以看到我从手册页中引用了很多内容。如果您想了解有关 linux 命名空间(或任何真正的 unix 的东西)的更多信息,您要做的第一件事就是阅读每个命名空间的手册页。写得很好,内容也很丰富。

关于namespaces - unshare 命令不会创建新的 PID 命名空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68704803/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com