使用 `nsenter:` 监禁子进程的可靠方法

mik*_*erv 16 process namespace

我知道 Linux 命名空间,除此之外,还可以用来安全地处理限制和监禁子进程,而不会让它们被僵尸化和转储到init. 但我对实现细节很模糊。我如何使用util-linux诸如mountand提供的工具nsenter来监视、监视和确保启动的所有进程都是另一个进程的直接命名空间后代?

Gra*_*eme 22

创建 PID 命名空间

此处使用的正确命令是unshare. 请注意,执行此操作的必要选项只能从util-linux 2.23. 这个想法是为你正在运行的程序创建一个新的PID 命名空间,这样它的所有子项也都在这个命名空间中创建。您只需执行以下操作即可在新的 PID 命名空间中运行命令:

sudo unshare -fp some_command
Run Code Online (Sandbox Code Playgroud)

要运行 shell,只需省略该命令。这将创建一个进程,该进程及其任何子进程将在父(系统)命名空间中像往常一样具有 PID。但是,在新的命名空间内,它将有一个 PID1以及init进程的一些特殊特征。也许从监控的角度来看,最相关的特征是,如果它的任何后代成为孤儿,他们将重新成为这个进程的父级,而不是真正的init进程。

对于大多数监控情况,简单地这样做可能就足够了。如前所述,命名空间中的进程在父命名空间中都有 PID,因此可以使用常规命令来监视它们的活动。我们还保证,如果命名空间中的任何进程成为孤立的,它不会从顶级程序的 PID 下的进程树分支中掉出来,这意味着它仍然可以很容易地被跟踪。

结合挂载命名空间

但是,我们不能做的是根据它认为具有的 PID 来监视进程。为此,特别是为了能够ps在新命名空间中使用该命令,您需要procfs为该命名空间挂载一个单独的文件系统。这又会导致另一个问题,因为ps接受 for的唯一位置procfs/proc。一种解决方案是创建一个chrootjail 并在procfs那里安装新的。但这是一种麻烦的方法,因为至少我们需要将我们打算使用的任何二进制文件以及它们依赖的任何库复制(或至少是硬链接)到新的根目录。

解决方案是还使用新的mount 命名空间。在此,我们可以procfs以使用真正根/proc目录的方式挂载新的,可以在 PID 命名空间中使用并且不干扰其他任何东西。为了使这个过程非常简单,该unshare命令提供了以下--mount-proc选项:

sudo unshare -fp --mount-proc some_command
Run Code Online (Sandbox Code Playgroud)

现在ps在组合的命名空间中运行将仅显示具有 PID namspace 的进程,并将显示顶级进程的 PID 为1.

怎么样nsenter

顾名思义,nsenter可以用来输入一个已经用unshare. 如果我们想从其他不相关的脚本中获取仅从命名空间内部可用的信息,这将非常有用。最简单的方法是访问给定在命名空间内运行的任何程序的 PID。为了清楚起见,这必须nsenter是正在运行的命名空间内的目标程序的 PID (因为命名空间可以嵌套,单个进程可能有多个 PID)。要在目标 PID/mount 命名空间中运行 shell,只需执行以下操作:

sudo nsenter -t $PID -m -p
Run Code Online (Sandbox Code Playgroud)

如果此命名空间设置如上,ps现在将仅列出该命名空间内的进程。