为什么通过 tmux 进行 SSH 登录后新组未激活?

为什么通过 tmux 进行 SSH 登录后新组未激活?

这是我的情况:

  • 我已为我的用户添加了一个新组。
  • 我已确认/etc/group设置正确。
  • 如果我这样做,su - myuser则显示该组id -a
  • 但是登录退出并再次登录(通过ssh)不会重新加载该组:id -a 才不是显示新组

这是因为 SSH 连接正在重复使用具有旧组设置的某些进程。

这是什么?

附加信息:

  • 我正在使用tmux,但在客户端上。我要 ssh 连接的服务器(以及我要更改组的位置)没有tmux运行。
  • 这可能与 ssh 连接共享有关。

答案1

因为该ssh连接正在重复使用具有旧组设置的某些进程

在您提到 SSH 连接共享之后,很明显这是罪魁祸首。为了理解这个问题,让我们看看 Linux 中的进程如何携带有关其所有者的信息。


产生新进程

所有进程都源自 PID 为 1(initupstartsystemd,无论什么)且属于用户的进程root。进程可以自我复制,请参阅man 2 fork;或者它可以用另一个映像替换自己的映像,请参阅man 3 exec。程序的常用方法是A产生程序是分叉,因此暂时有两个实例A,然后执行(新的A变成)现在A(父进程)和(子进程)。

每个进程都带有关于其所有者和组的信息,请参阅man 2 getuid、、man 2 getgidman 2 getgroups当生成子进程时,它通常会继承此信息。

为了创建属于 之外的用户的进程root,特权进程在某个时候必须更改其所有者。它使用setuid(2)setgid(2)setgroups(2)类似来实现这一点。通常会给出所需的 UID,并从中派生出组(包括补充组)。这是新组活跃的时刻。

非特权进程生成后,其子进程(如果有)将直接继承该信息,而无需向操作系统查询当前的用户所属的组集。此时新组无法激活。但也有例外:像susg或 这样的程序sudo,它们带有 setuid 标志,并由rootstart 拥有特权。在它们确保用户被允许执行操作后,情况与已经讨论过的情况相同,新组将激活。

因此su - myuser注意到了新组,因为它在后台更改了用户。检索当前的用户所属的组集是此过程的一部分。

另一方面,它id显示了它从 shell 继承的内容。这些信息很旧;它来自其特权祖先操纵其用户 ID 的时候。

注意id myuser会注意到新的组。Soleid检索与自身相关的信息(与getgroups(2)和因此),同时id myuser查询操作系统当前的关于所选用户的信息。

结论是:如果新组是某个特权进程的后代,您的 shell(及其子进程)将会注意到该新组,因此root和您的用户之间的转换发生在添加组之后。(正式说明:从到root的转换root没有什么不同;重要的是重新设置所有权的行为)。


在实践中

/dev/tty2左右(没有 SSH)

我可以通过标准文本控制台登录(/dev/tty2或类似)。进程树的相关部分是:

systemd───login───bash───pstree
^^^^^^^^^^^^^^^                 these are owned by root
                  ^^^^^^^^^^^^^ these are owned by my user

将我的用户添加到新组并在另一个 tty 中登录后:

systemd─┬─login───bash
        └─login───bash───pstree
^^^^^^^^^^^^^^^                 these are owned by root
                  ^^^^^^^^^^^^^ these are owned by my user

因为第二个bash是在我进行更改后从特权用户生成的login,所以它会知道新组。在这个基本情况下,“注销并再次登录”方法有效。

GUI(仍然没有 SSH)

考虑进程树的一个示例部分:

systemd───plasmashell───konsole───bash
^^^^^^^                                this is owned by root
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ these are owned by my user

将我的用户添加到新组后,中的新 shell(新选项卡)konsole不会看到变化。xterm如果我从 KDE Plasma ( plasmashell) 生成它,也不会看到。但如果我通过 登录/dev/tty2,正确设置并导出DISPLAY变量,然后从那里生成xterm,则 shell 中的xterm 将要看到更改。在两种情况下xterm都显示在同一个 KDE 桌面上,但第一种情况(间接地)源自很久以前(在更改之前)切换用户的特权进程;第二种情况(间接地)源自一分钟前(在更改之后)切换用户的特权进程。

SSH

在我的 Debian sshd(SSH 守护进程)中,反复分叉后,进程树的相关部分如下:

systemd───sshd───sshd───sshd───bash
^^^^^^^^^^^^^^^^^^^^^               these are owned by root
                        ^^^^^^^^^^^ these are owned by my user

第二次连接后,没有连接共享:

systemd───sshd─┬─sshd───sshd───bash
               └─sshd===sshd───bash───pstree
^^^^^^^^^^^^^^^^^^^^^                        these are owned by root
                        ^^^^^^^^^^^^^^^^^^^^ these are owned by my user

假设我同时将我的用户添加到一个新组。我标记的“链接”===表示sshd在更改后,某个特权用户产生了一个非特权用户。后者及其后代都知道这个新组。

有了连接共享,情况就有所不同:

systemd───sshd───sshd───sshd─┬─bash
                             └─bash───pstree
^^^^^^^^^^^^^^^^^^^^^                        these are owned by root
                        ^^^^^^^^^^^^^^^^^^^^ these are owned by my user

在这种情况下,新的bash老的 sshd由我的用户拥有。这sshd包含有关我的组的旧信息,新组bash继承了它。

我相信你的情况也会发生同样的情况。

tmux

问题不仅限于sshd。 以 为例tmux。 在一般情况下,使用tmux,在用户登录后,tmux可以直接作为登录 shell 启动,也可以间接从(非tmux)登录 shell 启动(手动或像从.bashrc;带或不带exec)。 该工具作为客户端连接到tmux用户拥有的服务器。 如果尚未为该特定用户设置服务器,它将被启动。 服务器启动“最终”shell。 进程树可能如下所示:

systemd─┬─login───bash───tmux: client
        └─tmux: server─┬─3*[bash]
                       └─bash───pstree

在我将用户添加到新组后,新bash生成的用户login确实可以看到该组。新的 tmux服务器及其子服务器将会看到它。但是已经运行 tmux服务器及其子服务器则不然;即使对于在我将用户添加到新组后产生的子服务器(shell),情况也是如此。

要明确的是:tmux客户端和服务器与 SSH 客户端和服务器无关;它们都在同一台机器上运行。tmux只有在发生更改的地方运行时才会有关系。您提到tmux只在 SSH 的客户端上,而更改是在 SSH 的服务器端进行的;所以对你来说tmux无关紧要

假设我已经知道了tmux更改发生的位置。为了让内部的新 shelltmux注意到新组,我需要退出(不是分离,而是真正退出)内部正在运行的所有内容tmux,这样我的tmux服务器也会退出,因此可以重新诞生。关闭服务器应该可行,但是这样做有明显的缺点。

从技术上讲,启动单独的tmux服务器是可行的。如果我不需要连接到已经运行的会话,这就是要走的路。请参阅中的-L和。如果在我登录后自动运行,我可能需要绕过这一点才能通过,例如:-Sman 1 tmuxtmux-L

ssh -t user@host tmux -L foo

相关内容