valoq / bwscripts

Bubblewrap example scripts
GNU Lesser General Public License v2.1
49 stars 3 forks source link

Isolating D-Bus #3

Open WhyNotHugo opened 1 year ago

WhyNotHugo commented 1 year ago

I'm using an approach similar to yours to sandbox a few applications with bubblewrap. It's still somewhat experimental, but I've managed to isolate D-Bus pretty well using xdg-dbus-proxy.

Here's an example for telegram-desktop:

https://git.sr.ht/~whynothugo/dotfiles/tree/main/item/home/.local/bin/telegram-desktop

It picks up dark mode changes (via portal), can show notifications, and grabs media keys to play/pause (useful when playing voice clips).

I hope this sample serves as a reference!

WhyNotHugo commented 1 year ago

BTW: thanks for publishing this repo, these samples helped me figure out how to unbreak multiple apps that suddenly broke and need access to /dev/dri, /sys/dev/char and /sys/devices/pci0000:00. I guess for the last two it would be ideal to narrow it down to only gpu-related files, right?

valoq commented 1 year ago

BTW: thanks for publishing this repo, these samples helped me figure out how to unbreak multiple apps that suddenly broke and need access to /dev/dri, /sys/dev/char and /sys/devices/pci0000:00. I guess for the last two it would be ideal to narrow it down to only gpu-related files, right?

The dev mounts were mostly added for fido2 support in order to allow WebAuthn, but some may be required for performance reasons as well.

darrenldl commented 1 year ago

@WhyNotHugo Thanks! This is massively helpful!

Could I ask how do you infer what parameters to provide to xdg-dbus-proxy though? Do you do it via the --log option in xdg-dbus-proxy?

(I recently wrote a tool for summarising syscall parameters relevant to sandboxing, see here for example json - I am thinking if a similar tool for going through dbus logs would be useful too.)

WhyNotHugo commented 1 year ago

The dev mounts were mostly added for fido2 support in order to allow WebAuthn, but some may be required for performance reasons as well.

Odd, I had keepassxc and telegram-desktop fail to start without them (failing to initialise something related to opengl). Adding these fixed the issue. /dev/dri is definitely graphics related.

Could I ask how do you infer what parameters to provide to xdg-dbus-proxy though? Do you do it via the --log option in xdg-dbus-proxy?

I was familiar with these D-Bus interfaces already. Telegram-desktop tries to use other D-Bus interfaces too, but I only allowed the ones I care about:

The org.freedesktop.portal.Desktop interface is a delicate one (which is why I've been so granular on it). The same service also exposes things like screencasting, camera and a bunch of other things.

StandingPadAnimations commented 10 months ago

@WhyNotHugo first off, massive thanks for releasing examples, they've been useful.

After a lot of work with file portals however, there is one thing I need to add: the sandboxes for both xdg-dbus-proxy and the program in question need to have a file called /.flatpak-info if you want portals like FileChooser to work properly. Otherwise, xdg-desktop-portal will just assume the program has full access to the file system. Here's an example with Vivaldi that implements this workaround:

#! /usr/bin/sh

APP_NAME="net.vivaldi.Vivaldi"
APP_FOLDER="$XDG_RUNTIME_DIR/app/$APP_NAME"
mkdir -p "$APP_FOLDER"

if [ -z "$DBUS_SESSION_BUS_ADDRESS" ]; then
  export DBUS_SESSION_BUS_ADDRESS="unix:path=$XDG_RUNTIME_DIR/bus"
fi

# A sandboxed dbus filter that 
# makes things a little safer
#
# Bwrap was initially for --die-with-parent,
# but was expanded to fix bugs related to portals
set_up_dbus_proxy() {
  bwrap \
    --new-session \
    --symlink /usr/lib64 /lib64 \
    --ro-bind /usr/lib /usr/lib \
    --ro-bind /usr/lib64 /usr/lib64 \
    --ro-bind /usr/bin /usr/bin \
    --bind "$XDG_RUNTIME_DIR" "$XDG_RUNTIME_DIR" \
    --ro-bind-data 3 "/.flatpak-info" \
    --die-with-parent \
    -- \
    env -i xdg-dbus-proxy \
    "$DBUS_SESSION_BUS_ADDRESS" \
    "$APP_FOLDER/bus" \
    --filter \
    --log \
    --talk=org.freedesktop.portal.Documents \
    --talk=org.freedesktop.portal.Flatpak \
    --talk=org.freedesktop.portal.Desktop \
    --talk=org.freedesktop.portal.Notifications \
    --talk=org.freedesktop.portal.FileChooser \
    --call="org.freedesktop.portal.Desktop=org.freedesktop.portal.Settings.Read@/org/freedesktop/portal/desktop" \
    --broadcast="org.freedesktop.portal.Desktop=org.freedesktop.portal.Settings.SettingChanged@/org/freedesktop/portal/desktop" 3<<EOF
[Application]
name=$APP_NAME
EOF
}

set_up_dbus_proxy &
sleep 0.1
bwrap \
  --unshare-all \
  --share-net \
  --as-pid-1 \
  --new-session \
  --symlink /usr/lib /lib \
  --symlink /usr/lib64 /lib64 \
  --symlink /usr/bin /bin \
  --symlink /usr/bin /sbin \
  --ro-bind /usr/lib /usr/lib \
  --ro-bind /usr/lib64 /usr/lib64 \
  --ro-bind /usr/bin /usr/bin \
  --ro-bind /etc /etc \
  --ro-bind /usr/share /usr/share \
  --ro-bind /opt/vivaldi /opt/vivaldi \
  --dev /dev \
  --dev-bind /dev/dri /dev/dri \
  --proc /proc \
  --ro-bind /sys/dev/char /sys/dev/char \
  --ro-bind /sys/devices /sys/devices \
  --ro-bind /run/dbus /run/dbus \
  --bind "$XDG_RUNTIME_DIR" "$XDG_RUNTIME_DIR" \
  --ro-bind "$XDG_RUNTIME_DIR/wayland-1" "$XDG_RUNTIME_DIR/wayland-1" \
  --ro-bind "$XDG_RUNTIME_DIR/pipewire-0" "$XDG_RUNTIME_DIR/pipewire-0" \
  --ro-bind "$XDG_RUNTIME_DIR/pulse" "$XDG_RUNTIME_DIR/pulse" \
  --bind "$XDG_RUNTIME_DIR/doc" "$XDG_RUNTIME_DIR/doc" \
  --bind "$APP_FOLDER/bus" "$XDG_RUNTIME_DIR/bus" \
  --bind-try "$XDG_RUNTIME_DIR/app/org.keepassxc.KeePassXC/org.keepassxc.KeePassXC.BrowserServer" "$XDG_RUNTIME_DIR/app/org.keepassxc.KeePassXC/org.keepassxc.KeePassXC.BrowserServer" \
  --tmpfs /tmp \
  --dir "$HOME" \
  --dir "$HOME"/.cache \
  --bind "$HOME"/.config/vivaldi "$HOME"/.config/vivaldi \
  --bind "$HOME"/VivaldiDownloads "$HOME"/Downloads \
  --ro-bind "$HOME"/.icons "$HOME"/.icons \
  --ro-bind-data 3 "/.flatpak-info" \
  --setenv XCURSOR_PATH "/run/host/user-share/icons:/run/host/share/icons:$HOME/.icons" \
  --setenv GTK_USE_PORTAL 1 \
  --cap-drop ALL \
  -- \
  /usr/bin/vivaldi-stable --enable-features=UseOzonePlatform --ozone-platform=wayland "${@}" \
  3<<EOF
[Application]
name=$APP_NAME
EOF

With this workaround, you can eliminate any access to the home directory, just like the Firefox Flatpak does (here though I've kept access to .config ). I have more info in a (albeit basic and somewhat rushed) write-up on my website.

EDIT: I know my example gives access to all portals, but I've tried without success to narrow them down. From what I can tell, it's a Chromium issue. By giving access to all portals, regular dbus calls will use portals (this is affirmed in Flatpak's documentation)

EDIT 2: I've gotten limited portal access working, I just needed to add --talk=org.freedesktop.portal.Flatpak to the list of portals Vivaldi can "talk" to