具有共享X11套接字的Docker:为什么它可以“启动”? Firefox在容器之外? [英] Docker with shared X11 socket: Why can it "start" Firefox outside of the container?

查看:95
本文介绍了具有共享X11套接字的Docker:为什么它可以“启动”? Firefox在容器之外?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下情况:


  1. 我设置了一个可以访问X11套接字的Docker容器,基本上是这样做的:< a href = https://stackoverflow.com/a/25334301> https://stackoverflow.com/a/25334301

  2. 然后我在容器中安装了Firefox并使用bash中的 firefox命令启动它。

我注意到:如果Firefox在我的主机上已经在运行在容器中启动它,实际上它只是在打开Firefox主机实例的新窗口时逃脱了容器。因此,它可以访问主机上的所有内容,并且容器变得无用。



反之亦然:如果Firefox没有在主机上运行,​​而我启动了一个实例在容器中,它实际上在容器中运行。如果随后在主机上启动Firefox,则新实例也在容器内运行。



但是,我无法使用gvim而不是Firefox重现此行为。 / p>

我很清楚X11套接字共享所固有的安全性问题,但是我无法解释上述情况。为什么容器可以在受限制的环境之外启动进程(或者更确切地说是窗口)?以及我的主机系统怎么可能仅由于容器中已经运行了相同的程序而在容器中启动进程?



(请注意,我没有不知道如何调用进程以外的程序的此类图形实例,尽管在这种情况下它可能不是真正的进程...)



系统:Ubuntu GNOME 14.10,Docker 1.5,ubuntu:最新的Docker映像。



更新:如果我使用 -new-instance启动Firefox,则不会发生这种情况标志,所以它似乎更多是Firefox问题而不是X11套接字问题。



更新2:似乎在其他情况下也会发生同样,例如,将ssh与X转发一起使用:

https://unix.stackexchange.com/questions/104476/why-starting-firefox-from-command-line-in-vm-starts主机中的firefox



https://superuser.com/questions/462055/launching-firefox-on-remote-server-causes-local-firefox-to-open-the-page-instead



现在的问题是,Firefox到底是怎么做到的?他们使用哪种X11魔术来确定Firefox是否已经在运行?

解决方案

因为您将x11套接字转发到了容器,任何图形程序,无论是在容器内部还是在容器外部,都将与同一台Xorg服务器通信。这与在X-forwarding中使用ssh相同。



现在,假设一个firefox实例已经启动并与该xserver通信。如果我们是第二个启动的Firefox进程,则可以通过从根目录导航窗口树。我们可以通过某些属性来识别属于Firefox的窗口。找到属于firefox的窗口后,我们可以发送消息到拥有该窗口的进程,要求它添加一个新标签。



也许我们找到了这样一个进程并要求它打开一个新窗口标签,我们只是在完成工作后就死了。



当然,我们总是可以查看源代码,发现实际上Firefox实际上是这样做的。特别是它们:





但是他们不会用客户消息通知它。他们通过更改window属性来实现。大概创建窗口的过程也订阅属性更改通知。如果您对代码的完整路径感到好奇,请执行以下操作:




  • 通过解析命令行 StartRemoteClient

  • 其中创建一个客户端(请注意,他们也通过d-bus / wayland进行此操作),然后调用 SendCommandLine()

  • 是一个虚拟函数,因此请找到它 XRemoteClient

  • ,然后在其中看到链接到 Fin的前两个函数的位置dBestWindow(),然后 DoSendCommandLine()


I have the following scenario:

  1. I set up a Docker container with access to the X11 socket, essentially I did this: https://stackoverflow.com/a/25334301
  2. Then I installed Firefox within the container and started it using the "firefox" command in bash.

What I noticed: If Firefox was already running on my host machine when I started it in the container, it essentially "escaped" the container as it just opened a new window of the host instance of Firefox. It therefore had access to everything on the host machine and the container became useless.

This also works vice versa: If Firefox is not running on the host and I start an instance in the container, it is really running inside the container. If I then start Firefox on the host, the new instance is also running inside the container.

However, I couldn't reproduce this behavior with gvim instead of Firefox.

I am well aware of the security problems inherent with X11 socket sharing, but I cannot explain the scenario I described above. Why can a container start a "process"---or rather a window---outside of its restricted environment? And how is it even possible that my host system starts a process within a container only because the same program is already running inside a container?

(Please note that I didn't know how to call such a graphical instance of a program other than "process", although it's probably not a real process in this case...)

System: Ubuntu GNOME 14.10, Docker 1.5, ubuntu:latest Docker image.

UPDATE: This doesn't happen if I start Firefox using the -new-instance flag, so it seems to be more of a Firefox problem than a X11 socket problem.

UPDATE 2: Seems that this happens in other scenarios as well, for example using ssh with X-forwarding:
https://unix.stackexchange.com/questions/104476/why-starting-firefox-from-command-line-in-vm-starts-the-firefox-in-the-host-ma
and
https://superuser.com/questions/462055/launching-firefox-on-remote-server-causes-local-firefox-to-open-the-page-instead

Now the question is, how the hell does Firefox do this? What kind of X11 sorcery do they use to find out if Firefox is already running?

解决方案

Because you forward the x11 socket into the container, any graphical program, whether inside the container or outside the container, will be talking to the same Xorg server. This is the same as when using ssh with X-forwarding.

Now let's say that one firefox instance is already started and communicating with that xserver. If we are the second firefox process starting up, we might find that first process by navigating the window tree from the root. We might be able to identify a window belonging to firefox through some properties that it sets on it's windows. Once we found a window belonging to firefox, we might send a message to the process owning that window, asking it to add a new tab.

Perhaps if we find such a process and ask it to open a new tab, we just die off as our job is done.

Of course, we could always just look at the source and find out that indeed firefox does basically this. In particular they:

But they don't notify it with a client message. They do it by changing a window property. Presumably the process that creates the window also subscribes to property change notifications. In case you're curious the full path through the code is:

  • from parsing the command line, StartRemoteClient
  • which creats a client (note that they do this over d-bus/wayland also) and then calls SendCommandLine()
  • which is a virtual function, so find it's override XRemoteClient
  • and in there you see where it calls the previous two functions linked to FindBestWindow() and then DoSendCommandLine().

这篇关于具有共享X11套接字的Docker:为什么它可以“启动”? Firefox在容器之外?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆