Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

access to the system DBus #3184

Closed
rusty-snake opened this issue Jan 25, 2020 · 18 comments · Fixed by #3265
Closed

access to the system DBus #3184

rusty-snake opened this issue Jan 25, 2020 · 18 comments · Fixed by #3265
Labels
enhancement New feature request

Comments

@rusty-snake
Copy link
Collaborator

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.

@Vincent43
Copy link
Collaborator

Vincent43 commented Jan 25, 2020

I wonder if we could bring in xdg-dbus-proxy integration for fine grained dbus access control instead of all or nothing.

@rusty-snake
Copy link
Collaborator Author

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.

@jonleivent
Copy link

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?

@jonleivent
Copy link

jonleivent commented Jan 28, 2020

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!

@rusty-snake
Copy link
Collaborator Author

untested: firejail --noprofile --nodbus --private dbus-run-session APP

@rusty-snake rusty-snake added the enhancement New feature request label Feb 10, 2020
@ned64
Copy link

ned64 commented Feb 22, 2020

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?

@jonleivent
Copy link

@ned64
What in particular did you need to do to /etc and /tmp?

@kris7t
Copy link
Collaborator

kris7t commented Feb 22, 2020

@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.

@rusty-snake
Copy link
Collaborator Author

@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.

@ned64
Copy link

ned64 commented Feb 22, 2020

@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.

@ned64
Copy link

ned64 commented Feb 22, 2020

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.

@jonleivent
Copy link

@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
Copy link
Collaborator

@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.

@kris7t
Copy link
Collaborator

kris7t commented Feb 23, 2020

@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

  1. Implement isolation from the system and session buses with xdg-dbus-proxy in addition to the current blocking behavior.
  2. Implement profile parsing for dbus filters by extending the current infrastructure for whitelists.
  3. Pass dbus filters to the xdg-dbus-proxy instances.
  4. Tweak 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
Copy link

ned64 commented Feb 23, 2020

@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.

@rusty-snake
Copy link
Collaborator Author

Maybe we want dbus-user.talk, dbus-system.talk and so on to clarify that dbus means only user.

@ned64
Copy link

ned64 commented Feb 23, 2020

Sounds good. How can I help?

@kris7t
Copy link
Collaborator

kris7t commented Feb 24, 2020

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants