Ich verwende Firefox als Webbrowser und schon eh und je ist er eine besondere Anwendung, bei der ich zum Beispiel früher am OOM-Killer-Wert gedreht habe, damit Firefox vor anderen wichtigen Programmen beendet wird. Aber auch heute noch hat Firefox einiges Verhalten, weshalb ich ihn besonders behandele.
Verwaltet von Systemd
Mit systemd-run kann man Prozesse von Systemd überwachen lassen. Mit der
Option --user
wird dafür der Benutzerdienst und nicht der Systemdient
genutzt. Es ist ähnlich wie man mit Cron Prozesse zu einer bestimmten Zeit
ausführen kann, die dann von Cron überwacht werden.
Der Vorteil an der Überwachung mit Systemd sind die vielen Funktionen, die Systemd bietet. Unter anderem werden die Ausgaben der Prozesse ins Journal geschrieben und verschwinden nicht im Nirgendwo oder landen ohne Zuordnung in ~/.xsession-errors.
srun
Als Hilfe habe ich mir ein Skript srun in ~/bin angelegt, um die Optionen besser kontrollieren und das Skript auch für andere Programme einsetzen zu können. Das gute an systemd-run ist, dass es die Prozesse in einer bereinigten Prozessumgebung startet. Daher werden bei mir jedoch auch einige wichtige Variablen nicht übernommen, die ich mithilfe der Option übergebe:
#!/bin/sh
if test -n "$MANAGERPID$INVOCATION_ID"
then
# we are already under control of Systemd
exec "$@"
fi
exec systemd-run --user --quiet --collect \
--setenv=PATH=$HOME/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \
--setenv=GDK_SCALE=$GDK_SCALE --setenv=GDK_DPI_SCALE=$GDK_DPI_SCALE \
--setenv=QT_AUTO_SCREEN_SCALE_FACTOR=$QT_AUTO_SCREEN_SCALE_FACTOR \
${DESKTOP_STARTUP_ID:+--setenv=DESKTOP_STARTUP_ID=$DESKTOP_STARTUP_ID} \
${XDG_RUNTIME_DIR:+--setenv=XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR} \
"$@"
Die Variablen mit GDK und QT sind bei mir für den
HiRes-Display notwendig. Die
DESKTOP_STARTUP_ID ist notwendig, damit der Fenster-Manager AwesomeWM die
Fenster einem bestimmten Prozess zuordnen kann. Durch --collect
bleiben
fehlerhaft beendete Prozesse nicht als Eintrag bei Systemd hängen und würden
zukünftige Aufrufe blockieren.
ff
Zum Starten von Firefox verwende ich bereits das Skript ff, um besser meine Browser-Profile verwalten zu können. Dieses Skript habe ich jetzt um den Aufruf von srun erweitert. Um besser im Journal die Firefox-Instanzen unterscheiden zu können, habe ich den Units, die automatisch von systemd-run erzeugt werden, entsprechende Namen gegeben. Die normale Firefox-Instanz heißt ff, die für die Bank ff-bank u. s. w.
Da eine Unit nur ein Mal gestartet werden darf und ein weiterer Aufruf von Firefox nur den Hauptprozess kontaktiert und eine Seite öffnen lässt, soll nur der erste Aufruf tatsächlich mit srun geschehen:
if systemctl --user is-active $unit >/dev/null
then
exec firefox "$@"
else
exec srun --unit=$unit --property=SyslogIdentifier=$unit firefox "$@"
fi
Möglichkeiten mit AppArmor begrenzen
Systemd bietet die Option, für eine Unit ein AppArmor-Profil festzulegen. Da ich unterschiedliche Browser-Profile nutze, um Online-Bank, Matrix, Entwicklung und Nightly vom normalen Surfen zu trennen, benötige ich auch unterschiedliche AppArmor-Regeln.
Die Entwickler- und die Nightly-Version habe ich in eigenen Verzeichnissen abgelegt, die in den Profilen variieren. Jede Instanz soll dabei nur auf ihr eigenen Firefox-Profilverzeichnis zugreifen können und in einigen Profilen ist Sound und Drucken erlaubt.
Anfangs habe ich mehrere Dateien für die Profile verwendet, gemeinsame Bestandteile ausgelagert und über include jeweils eingebunden. Jedoch entwickelten sich die Anforderungen an die Profile so komplex, dass ich das Skript gen-ff-aa-profiles zur Erzeugung der Profile geschrieben habe.
Darin wird eine Funktion ff_profile definiert, der der Profilname, optional das Programmverzeichnis von Firefox, Parameter für bestimmte Regeln und am Ende weitere Einträge für das Profil übergeben werden.
ff_profile default deny_pinger '
include <abstractions/cups-client>
owner @{HOME}/.mozilla/native-messaging-hosts/* r,
/home/joerg/git/keepassxc/build/src/proxy/keepassxc-proxy Ux,
owner @{HOME}/.config/.keysnail.js r,
owner @{HOME}/Downloads/{,**} rw,
deny $ff_dir/update.test{,/} w,
'
In meinem Online-Bank-Profil will ich weder Musik hören, noch drucken und nur Zugriff auf das Verzeichnis ~/Bank haben, damit ich dort Dateien speichern kann.
ff_profile bank deny_audio deny_pinger deny_fs_browsing '
owner @{HOME}/Bank/{,**} rw,
'
Alle Profile lasse ich gemeinsam in eine Datei schreiben und lade diese mit
AppArmor. Mit der zusätzlichen Option -C
bei für AppArmor werden die Regeln
nicht erzwungen, aber Meldungen bei Verstößen ausgegeben – ein Testmodus.
gen-ff-aa-profiles > /etc/apparmor.d/firefox && apparmor_parser -r /etc/apparmor.d/firefox
Beim Aufruf von srun in ff musste ich nur noch die Option -p
AppArmorProfile=$unit
ergänzen.
Für die Entwicklerversion und die Nightly-Version sehen die Profile ähnlich aus. Zu der Entwicklerversion ist noch zu sagen, dass Firefox immer versucht ein zusätzliches Profil anzulegen, was man aber durch die leere Datei ~/.mozilla/firefox/ignore-dev-edition-profile unterbinden kann.
ff_profile dev /home/joerg/kein_Backup/firefox-dev allow_updater '
owner @{HOME}/.mozilla/native-messaging-hosts/* r,
/home/joerg/git/keepassxc/build/src/proxy/keepassxc-proxy Ux,
owner @{HOME}/Downloads/{,**} rw,
'
Fazit
Ein Browser wie Firefox ist durch das Laden von unbekannten Inhalten aus dem Internet und die Ausführung von Javascript einer sehr großen Bedrohung ausgesetzt. Um dem Nutzer viele Funktionen bieten zu können, braucht der Browser andererseits viele Rechte: Dateisystemzugriff, Zugriff auf Sound- und Video-Geräte, Ausführung von Programmen.
Wer jedoch seine Nutzung des Browsers und der Profile genauer spezifiziert, kann mit systemd-run und AppArmor Firefox besser einhegen, um im Falle eines Fehlverhaltens – das im Web nicht abwegig ist – den Schaden zu begrenzen.