Thanks @jonleivent for bringing #3078 up.
Current situation:
Profiles with nodbus have no access to /run/dbus/system_bus_socket, profiles without nodbus have access. The must profiles without nodbus didn't have it because they need access to the _session-bus_.
Proposed change (soft):
Adding a nodbus.system option. If only this option is specified, the program can access the session-bus but not the system-bus.
Proposed change (hard):
Firejail blocks system-bus access by default, unless an allow-system-dbus-access option is specified.
I wonder if we could bring in xdg-dbus-proxy integration for fine grained dbus access control instead of all or nothing.
Sure we should. However this is a lot more work and blocking the system-bus works for almost all programs and prevents them from doing "privileged" actions.
Would it be possible to enclose a session bus within a jail with other applications, so that they can use it without interfering with applications and session busses outside the jail?
I did some experimenting, and it is possible with some additional firejail protections on /run and setting XDG_RUNTIME_DIR to launch dbus-launch --exit-with-session icewm-session into a x11=xephyr firejail container. Some testing shows that the session dbus inside the jail works. Anyone seen this configuration before?
Tested a bit with dbus-monitor --session, and it does seem that the session dbus in the jail and the one outside are separate and keeping their distance, with apps that would normally fail in a nodbus jail now working. Cool!
untested: firejail --noprofile --nodbus --private dbus-run-session APP
I have experimented with dbus-run-session but needed to add a new /etc and /tmp for that to work and isolate properly. Perhaps this could be integrated as --new-dbus-session?
@ned64
What in particular did you need to do to /etc and /tmp?
@Vincent43 Provided we had a convenient way to run xdg-dbus-proxy, what kind of policies would we want to enforce? I imagine usual suspects would be allowing notifications, and perhaps MPRIS or idle inhibition, depending on the app.
I am tempted to implement xdg-dbus-proxy support. It seems to have a straightforward format for filters (\0-separated options read from a given fd), but we will probably need something a bit more composable for profiles.
@kris7t if we implement it compatible to flatpak we will be able to add restricted dbus to the most commonly used program-profiles by using the permissions from flathub. I could write a script to automate this.
@jonleivent
I created a new machine id as well as password and group files so that dbus-session would start:
#!/bin/tcsh -f
set tmpdir = `mktemp -d /tmp/dbus-data-dir.XXXXXXXX`
if ( ! -d "${tmpdir}" ) then
echo `basename $0`: could not create temporary directory
exit 1
endif
# prepare files in new /tmp and /etc for dbus-session
mkdir "${tmpdir}"/etc
egrep ^root: /etc/passwd > "${tmpdir}"/etc/passwd
egrep ^${USER}: /etc/passwd >> "${tmpdir}"/etc/passwd
egrep ^${USER}: /etc/group > "${tmpdir}"/etc/group
# create a random machine id
set machineid = `cat /dev/random | hexdump -e '16/1 "%02.x" 1/0 "\n"' | head -1`
echo "${machineid}" > "${tmpdir}"/etc/machine-id
then bind "${tmpdir}" to /tmp/dbus-data and set XDG_RUNTIME_DIR to /tmp/dbus-data - or, use those files in a private /etc.
It would be perfect to have a dbus proxy. I would use a whitelist approach so that all (and new) services are blocked by default. evince would be able to open a new instance if it could only see itself on the dbus, nothing else needed. Same for loffice and others.
These simple things could also be done with --join-or-start and a per-group dbus session/instance but more complex ones would fail. Here a proxy with pre-made config files (a strength of firejail) would be great.
@ned64
I didn't have to do any of that to get dbus-run-session to work. Even the XDG_RUNTIME_DIR I thought I needed isn't needed, as long as XDG_RUNTIME_DIR is unset either by the profile or before, so that the default /tmp setting is used. I did use a --private-etc and --private-tmp. I have two profiles - one with network access and one without. The --private-etc settings in the one without are:
private-etc group,passwd,login.defs,fonts,timezone,localtime
the with-network one has (mostly tested with firefox):
private-etc group,passwd,login.defs,fonts,timezone,localtime,hosts,resolv.conf,resolvconf,network,ca-certificates,ssl,machine-id,dconf,selinux,hostname,nsswitch.conf,xdg,gtk-2.0,gtk-3.0,X11,pango,mime.types,mailcap,asound.conf,pulse,pki,crypto-policies,ld.so.cache
@Vincent43 Provided we had a convenient way to run xdg-dbus-proxy, what kind of policies would we want to enforce? I imagine usual suspects would be allowing notifications, and perhaps MPRIS or idle inhibition, depending on the app.
Ideally apps would own their namespace + portal access and the rest would be granted per profile. Maybe more relaxed dbus-common.inc with things you mentioned will be needed though. As it was said flathub is good place to see what apps need.
@Vincent43
Speaking in terms of concrete syntax, I am thinking along the lines of dbus allow|filter|none and dbus.system allow|filter|none to completely disable, filter with proxy, and completely allow access to the the session and system buses, respectively (nodbus being a synonym of dbus none, dbus.system none for compatibility).
Then, building on the same infrastructure as whitelist, we could have profile entries dbus.talk <name>, dbus.own <name>, dbus.see <name> and maybe dbus.call <rule> and dbus.broadcast <rule> for each rule, which generate the equivalent flags for the xdg-dbus-proxy instance (as well as dbus.system.talk, etc. for the instance on the system bus). We probably also need dbus.notalk, etc. pairs (similarly to whitelist/nowhitelist).
So the basic configuration would be something like
dbus filter
dbus.system filter
dbus.talk org.freedesktop.portal.*
while each application with bus access least contributes a dbus.own namespace.of.the.application.* line.
The system above has an advantage of being compatible both with existing profiles, and Flatpak premissions (--talk-name, --own-name, --system-talk-name, and --system-own-name map to dbus.talk, dbus.own, dbus.system.talk, and dbus.system.own, respectively), while supporting the #include mechanism of profile.
Of course, a much simpler approach, like dbus.talk being a comma-separated list of names (taking a hint from the seccomp command), would be sufficient, but the lack of simple #include support would be painful.
So one plan of action would be
xdg-dbus-proxy in addition to the current blocking behavior.xdg-dbus-proxy instances.dbus-common.inc and enhance profiles with dbus filters converted from Flatpak manifests.1, 2, and 3 looks fun enough (although I unfortunately cannot give an ETA, should I find the time to work on them), while 4 may require extensive testing before it can be released.
@ned64
I didn't have to do any of that to get dbus-run-session to work. Even the XDG_RUNTIME_DIR I thought I needed isn't needed, as long as XDG_RUNTIME_DIR is unset either by the profile or before, so that the default /tmp setting is used. I did use a --private-etc and --private-tmp. I have two profiles - one with network access and one without. The --private-etc settings in the one without are:private-etc group,passwd,login.defs,fonts,timezone,localtime
I personally needed to add alternatives to private-etc, otherwise vi and many other programs will not work.
the with-network one has (mostly tested with firefox):
private-etc group,passwd,login.defs,fonts,timezone,localtime,hosts,resolv.conf,resolvconf,network,ca-certificates,ssl,machine-id,dconf,selinux,hostname,nsswitch.conf,xdg,gtk-2.0,gtk-3.0,X11,pango,mime.types,mailcap,asound.conf,pulse,pki,crypto-policies,ld.so.cache
You are whitelisting machine-id which is quite possibly globally unique - better to generate a new one like I did above. dbus-run-session does not generate one, I tried. No id would be available if the machine-id is simply removed/inaccessible which might lead to problems for some programs.
Anyway, I didn't manage to run icecat with these switches. Is /usr/local mounted noexec? I couldn't see that mount:
````
-> firejail --profile=icecat --private-tmp --nodbus --private --private-etc=group,passwd,login.defs,fonts,timezone,localtime,hosts,resolv.conf,resolvconf,network,ca-certificates,ssl,dconf,selinux,hostname,nsswitch.conf,xdg,gtk-2.0,gtk-3.0,X11,pango,pki,crypto-policies,ld.so.cache,alternatives --blacklist=/mnt --blacklist=/media --blacklist=/run/media --whitelist=${HOME}/Download --whitelist=/usr/share/dbus-1/session.conf --debug-whitelists dbus-run-session /usr/local/icecat/icecat-bin
Error: cannot read UID_MIN and/or GID_MIN from /etc/login.defs, using 1000 by default
Reading profile /etc/firejail/icecat.profile
Reading profile /etc/firejail/firefox-common.profile
Reading profile /etc/firejail/disable-common.inc
Reading profile /etc/firejail/disable-devel.inc
Reading profile /etc/firejail/disable-exec.inc
Reading profile /etc/firejail/disable-interpreters.inc
Reading profile /etc/firejail/disable-programs.inc
Reading profile /etc/firejail/whitelist-common.inc
Reading profile /etc/firejail/whitelist-var-common.inc
Parent pid 7935, child pid 7937
Warning: cleaning all supplementary groups
Warning: cleaning all supplementary groups
Warning: cleaning all supplementary groups
Warning: skipping login.defs for private /etc
Warning: skipping timezone for private /etc
Warning: skipping resolvconf for private /etc
Warning: skipping network for private /etc
Warning: skipping pango for private /etc
Warning: skipping crypto-policies for private /etc
Private /etc installed in 34.33 ms
Warning: An abstract unix socket for session D-BUS might still be available. Use --net or remove unix from --protocol set.
Debug 423: new_name #/home/user/.cache/mozilla/icecat#, whitelist
Removed whitelist/nowhitelist path: whitelist ${HOME}/.cache/mozilla/icecat
expanded: /home/user/.cache/mozilla/icecat
real path: (null)
realpath: No such file or directory
Debug 423: new_name #/home/user/.mozilla#, whitelist
Removed whitelist/nowhitelist path: whitelist ${HOME}/.mozilla
expanded: /home/user/.mozilla
real path: (null)
realpath: No such file or directory
(...)
Debug 423: new_name #/var/lib/dbus#, whitelist
Debug 423: new_name #/var/lib/menu-xdg#, whitelist
real path /var/lib/dbus
Removed whitelist/nowhitelist path: whitelist /var/lib/menu-xdg
expanded: /var/lib/menu-xdg
real path: (null)
realpath: No such file or directory
Debug 423: new_name #/var/cache/fontconfig#, whitelist
Debug 423: new_name #/var/tmp#, whitelist
Debug 423: new_name #/var/run#, whitelist
Debug 423: new_name #/var/lock#, whitelist
Debug 423: new_name #/home/user/Download#, whitelist
real path /var/cache/fontconfig
real path /var/tmp
real path /run
Replaced whitelist path: whitelist /run
real path /run/lock
Replaced whitelist path: whitelist /run/lock
Removed whitelist/nowhitelist path: whitelist /home/user/Download
expanded: /home/user/Download
real path: (null)
realpath: No such file or directory
Debug 423: new_name #/usr/share/dbus-1/session.conf#, whitelist
Debug 423: new_name #/tmp/.X11-unix#, whitelist
Warning: cleaning all supplementary groups
Warning: cleaning all supplementary groups
Warning: cleaning all supplementary groups
Warning: cleaning all supplementary groups
Warning: cleaning all supplementary groups
Post-exec seccomp protector enabled
real path /usr/share/dbus-1/session.conf
real path /tmp/.X11-unix
Mounting tmpfs on /tmp directory
Mounting tmpfs on /var directory
Mounting tmpfs on /usr/share directory
Whitelisting /var/lib/dbus
Whitelisting /var/cache/fontconfig
Whitelisting /var/tmp
Created symbolic link /var/run -> /run
Created symbolic link /var/lock -> /run/lock
Whitelisting /usr/share/dbus-1/session.conf
Whitelisting /tmp/.X11-unix
Seccomp list in: !chroot, check list: @default-keep, prelist: unknown,
Child process initialized in 125.00 ms
dbus-run-session: failed to exec '/usr/local/icecat/icecat-bin': Permission denied
Parent is shutting down, bye...
````
Whitelisting ~/Download failed here, too. Tested by opening a shell (still within new dbus session) instead of icecat.
Maybe we want dbus-user.talk, dbus-system.talk and so on to clarify that dbus means only user.
Sounds good. How can I help?
I started working on DBus proxying in my fork: https://github.com/kris7t/firejail/tree/dbus-proxy
For now, the user and system buses can be blocked separately by --dbus-user=block and --dbus-system=block, and --dbus-user=filter and --dbus-system=filter can be used to run a very restrictive (nothing except org.freedesktop.DBus is visible) filter. Filter rules --dbus-user.talk, --dbus-user.own, --dbus-system.talk, and --dbus-system.own are supported. Documentation is still to go.
Most helpful comment
I wonder if we could bring in xdg-dbus-proxy integration for fine grained dbus access control instead of all or nothing.