Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Docker with shared X11 socket: Why can it "start" Firefox outside of the container?

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?

like image 206
ctitze Avatar asked Mar 11 '15 13:03

ctitze


1 Answers

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:

  • find an existing window
  • and then notify it

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().
like image 164
cheshirekow Avatar answered Nov 19 '22 02:11

cheshirekow