netblue30 / firejail

Linux namespaces and seccomp-bpf sandbox
https://firejail.wordpress.com
GNU General Public License v2.0
5.72k stars 561 forks source link

Is there way to start few applications in single x11 sandbox? #1824

Closed punksta closed 6 years ago

punksta commented 6 years ago

I'd like to run time-tracking app with ide and browser in single x11 sandbox. Is it possible?

Fincer commented 6 years ago

I have used systemd-nspawn to run Pale Moon web browser in a container with graphical interface (X11) + Pulseaudio enabled. Pulseaudio is needed for any web media content that have audio in it (such as Youtube videos).

I have read it is possible to run graphical applications with docker, too.

Please take also a look on x11docker project which claims to focus on X11 security issues and should provide a somewhat easy set-up for X11 + docker container environment.

For loose reference: Running Firefox in a systemd-nspawn container

You can very likely use firejail inside systemd-nspawn container so that the end-user environment is kind of having two containers stacked. I have planned to use firejail in my systemd-nspawn containers after issue private-lib doesn't work with Palemoon & Firefox is fixed.

Security & X11

Problem of sharing X11 environment with the host is the shared memory which, in some cases, can be a security issue. This is likely an issue with Pulseaudio, too.

Setting up systemd-nspawn container + X11 application (my personal setup)

I have done this on Arch Linux, so some parts are specific for that distribution. The following stuff assumes you have your main system's current user in sudo group and you have working internet connection available in the system.

  1. Create a new container folder (in your home folder, for example):

    mkdir -p ~/my-container

    You can choose whatever path you want to. ~/my-container is just an example here.

  2. Set up container environment by running the following in your main system (this is Arch Linux specific approach):

    sudo pacman -S arch-install-scripts
    sudo pacstrap -i -c ~/my-container curl pacman coreutils systemd nano
  3. Login to the Arch Linux container environment:

    sudo systemd-nspawn -b -D ~/my-container
  4. In container environment, login as root when login credentials are asked.

  5. In this step, we request public keys of Arch Linux package maintainers and run database updates. In container environment, run:

    pacman-key --init && pacman-key --populate archlinux
    pacman -Syy && pacman -Fy
  6. In container environment, create a new user 'default' & set home directory óf this user to /home/default:

    useradd -d /home/default -u 1000 default
    mkdir -p /home/default && chown 1000:1000 /home/default
  7. In container environment, install your program (as root):

    pacman -S program_name
  8. In container environment, add password to user 'default' and change to user 'default' shell. In default user's shell, create a new file called 'launch.sh' in his/her home directory and set it as executable:

    passwd default
    su default
    touch /home/default/launch.sh
    chmod +x /home/default/launch.sh

The last two commands (touch & chmod) must be run as 'default' user.

  1. In container environment, edit the created 'launch.sh' file as user 'default' (nano /home/default/launch.sh). Add the following contents in it:
    
    #!/bin/sh

su default -c "QT_X11_NO_MITSHM=1 PULSE_SERVER=unix:/run/user/host/pulse/native DISPLAY=:0 my_command"


where 'my_command' is the name of your program's executable file in container environment. If you don't use Pulseaudio in container environment, remove _PULSE_SERVER=unix:/run/user/host/pulse/native_ part.

Note: any environment variables you describe in the command above depends on your set-up. If you use ALSA, for example, write a correct string for that.

10. Exit the container environment by pressing _CTRL + %_ key combination (or _CTRL + ]_ with en_US keyboard) rapidly three times sequentially.

11. Execute your program in container by running the following command in your main system:

sudo xhost local:root && sudo systemd-nspawn \ --bind-ro=$HOME/.Xauthority:/home/default/.Xauthority \ --bind-ro=/tmp/.X11-unix \ --bind-ro=/run/user/1000/pulse:/run/user/host/pulse \ --bind-ro=/dev/snd \ -D ~/my-container \ /home/default/launch.sh


The above command does as follows:

- Share main system X11 environment

- Initialize systemd-nspawn container

- bind your main system's current user .Xauthority file to the container's default user home directory (read-only).

- bind your main system's X11 sockets to the container environment (read-only)

- bind your main system's Pulseaudio to the container environment (read-only)

- specify container path (-D ~/my-container)

- in container environment, execute _home/default/launch.sh_ (in which we have set up that our command is executed as user 'default')

Additional Pale Moon parameters
-----------

NOTE: bind parameters you might want to use vary, depending on the requirements for the program. For example, I have additional parameters for my 'Pale Moon' web browser environment:

--bind-ro=/usr/share/icons/:/usr/share/icons/ \ --bind-ro=/usr/share/themes/:/usr/share/themes/ \ --bind-ro=/usr/share/fonts/:/usr/share/fonts/ \ --bind-ro=$HOME/.gtkrc-2.0:/home/browser/.gtkrc-2.0 \ --bind=$HOME/Downloads:/home/browser/Downloads \

Note that I have binded my main system's _$HOME/Downloads_ folder as writable.

Some of these bindings are irrelevant if I have set up a working GTK2 environment or installed fonts/icons into the container. As I haven't installed fonts/icons in the container, I bind the ones I have in my main system. And, for example, without GTK2/icon bindings the program (Pale Moon) works but looks awful.

Which systemd-nspawn bindings to use?
-----------

How do you know which bindings you want to use? Check your program requirements.

Does your containerized program use Qt5, GTK2 or GTK3? Does it require ALSA or Pulseaudio? Does it require some fonts installed? Does it require some icons installed? Just find out (can be tricky) and by your findings, set up your _--bind-ro_ parameters correctly to the command in step 11.

Firefox/Palemoon + systemd-nspawn X11 workaround
-----------

For Firefox and Pale Moon, there seems to be a bug of some sort which prevents these web browsers to start ([ABORT: X_ShmPutImage](https://bugzilla.mozilla.org/show_bug.cgi?format=default&id=1129790)). 

If you encounter this issue, you may try the following as a workaround: set up a short while loop for the launch command (in _/home/default/launch.sh_) which executes it twice unless the program has already been started successfully. So, in my case with Pale Moon, I replace the contents of _/home/default/launch.sh_ with the following:

!/bin/sh

i=1 while [[ i -ge 0 ]]; do su browser -c "QT_X11_NO_MITSHM=1 PULSE_SERVER=unix:/run/user/host/pulse/native DISPLAY=:0 palemoon" 2>/dev/null if [[ $(ps -C palemoon | wc -l) -gt 2 ]]; then break fi let i-- done

NOTE: Executable name varies depending on your program of choice. In my case, it is _palemoon_, as seen in the above command.

NOTE: I don't guarantee this workaround works for you but I can say "It works for me".

In the above command, I need _procps-ng_ package to be installed in my Arch Linux container. To do that, I simply execute the following in the main system:

sudo pacstrap -i -c ~/my-container procps-ng


Now I should be able to launch the program correctly with the command introduced in step 11, with additional Pale Moon parameters (see 'Additional Pale Moon parameters' section above).

Setting up a shortcut for the container
-----------

12. To set up a shortcut for your container in your main system, simply create a new _.desktop_ file (such as my-container.desktop) with the following 'Exec=' parameter (NOTE: this applies to KDE environment, use your preferred terminal emulator here):

Exec=konsole -e /home/user/launch-my-container.sh


13. Create a new file _launch-my-container.sh_ in the home folder of your system's current user with the contents described in step 11. Make this file as executable:

chmod +x /home/user/launch-my-container.sh



Other contents of your desktop file vary depending on your program of choice.

Controlling systemd-nspawn container resources
-----------

Please check [this](https://copyninja.info/blog/taming_systemd_nsapwn.html), [this](https://blog.selectel.com/systemd-containers-introduction-systemd-nspawn/) and [this link](https://www.freedesktop.org/software/systemd/man/systemd.resource-control.html) for some details.

-----------

I hope this helps you a little bit in your issue. Remember to fit my instructions depending on your running system environment (do you run Ubuntu/Debian/Fedora...etc.) and program requirements.

-Fincer
punksta commented 6 years ago

@Fincer Thank you for such detailed answer! it's was unexpected. I'll try to follow this in free time. For quick solution I've just set up qemu-kvm image for work environment with not trusted applications (upwork, zoom, slack, teamviewer). I can combine firejail and vm os now :). Maybe having second os on another encrypted partition is best option for that case.

Fincer commented 6 years ago

You are welcome. :+1: Actually, I just had similar problem earlier in this week so the timing for your question was a fun coincidence for me.

Take your time, feel free to comment the solution as well!


Not many answers given for this issue in the internet satisfied me. Personally, either I couldn't find a proper answer which could perfectly satisfy my needs.

Therefore, as... 1) ...I investigated the issue + found satisfying answer by myself and...

2) ...because I see there are people who fight with the exact same issues...

...I decided to write my personal documented answer here. It's not foolproof, may have security or other issues depending on system environment but, at least, it's a good starting point and can be fine tuned afterwards.


Personally, I haven't checked the docker solution I described above, but I think it's totally worth closer look.

My starting point for the little "Create a container for Pale Moon web browser" project was my basic requirement to get rid of bulky x86_64 virtual machine environments (Oracle VirtualBox) I have set up on my main system, and to reduce RAM usage as a result.

I have also set up an encrypted Vault container (KDE) for my Pale Moon browser profile. The solution I currently use is not a good one and should be improved. I have ideas for this but just haven't tried them yet.

netblue30 commented 6 years ago

It is quite easy, you start the first application and find out on what display is running:

$ firejail --x11=xephyr transmission-qt
Reading profile /etc/firejail/Xephyr.profile
Reading profile /etc/firejail/whitelist-common.inc
Parent pid 28509, child pid 28510
Child process initialized in 34.46 ms

*** Attaching to Xephyr display 230 ***

Reading profile /home/netblue/.config/firejail/transmission-qt.profile
Reading profile /etc/firejail/transmission-qt.profile
Reading profile /etc/firejail/disable-common.inc
[...]

Then, you start all the other sandboxes using DISPLAY environment variable:

$ DISPLAY=":230" firejail xterm
[...]

If you want to verify, run "firemon --x11":

$ firemon --x11
28509:netblue::/usr/bin/firejail /usr/bin/Xephyr -ac -br -noreset -screen 800x
28526:netblue:torrent:firejail transmission-qt 
  DISPLAY :230
28693:netblue::firejail xterm 
  DISPLAY :230

So, you'll have a sandbox for each app, and another one for xephyr/xpra