System-wide sandboxing framework - sandbox-app-launcher

Unrelated to the current topic but gVisor would be a good idea to further strengthen the sandbox in the far future.

I will look into ways to restrict user namespace to root.

I don’t know any other place where I can really talk about my small project, so I talk here.

What do you recommend for compiling seccomp bpf for bubblewrap? Should I just create a binding to libseccomp and create a wrapper around bubblewrap and libseccomp?

I’m currently playing with the idea of creating a cryptocurrency signing device out of a single board computer with a USB OTG port that gets power from USB and also serves as an ethernet port.

Basically, single board computer’s USB OTG port <–SSH–> desktop computer or laptop

I send unsigned transaction over ssh to single board computer, sign unsigned transaction on single board computer in ssh session, and send signed transaction back via SSH.

In order to prevent private keys and public keys from leaking over SSH or USB ethernet, I may use AppArmor, setuid bubblewrap, and nftables.

  • nftables makes sure that the USB ethernet connection is not routed to the internet and is strictly between the single board computer and the machine on the other side of USB cable.
  • AppArmor and bubblewrap make it so that only cryptocurrency wallet softwares have access to cryptocurrency wallets on an encrypted file system and only openssh has access to USB ethernet.

A cold signing device is simple, low tech, easy, and far securer, but I want to at least play with my above idea. What do you think of security of my single board computer cryptocurrency signing device?

You should create your own thread in the general section of the forum.

We have a shell script to automatically generate complete seccomp filters from simple rules that you can use: sandbox-app-launcher/usr/share/sandbox-app-launcher/autogen-seccomp at master · Kicksecure/sandbox-app-launcher · GitHub

You can see the whitelist we use here: sandbox-app-launcher/usr/share/sandbox-app-launcher/seccomp-whitelist at master · Kicksecure/sandbox-app-launcher · GitHub

It will spit out the source code so you can pipe it to a file and compile it: sandbox-app-launcher/usr/bin/sandbox-app-launcher at e8291d6884c2bf4c022b01f0056ffdf0b639e629 · Kicksecure/sandbox-app-launcher · GitHub

We used to just keep the raw source code but it can be hard to maintain / review. sandbox-app-launcher/usr/share/sandbox-app-launcher/seccomp.c at 589d5ccd3496483255c43985db0bbe4d15f21d58 · Kicksecure/sandbox-app-launcher · GitHub (outdated version)

I can’t really say. Crypto isn’t my forte.

General section is locked. I better look for somewhere else.

I can see that you created a sandbox framework around bubblewrap and libseccomp.
One problem with your sandbox framework is that it’s not designed to be re-useable outside whonix.

I may create

  • A thin wrapper around libseccomp in a scripting language.
  • Perhaps, a general-purpose sandbox framework in the future?

Why do you think that?
I think a lot people assume many things are Whonix-only even though these have been designed with compatibility in mind. And certainly no artificial restrictions on purpose. At very least since Whonix is based on Debian, it’s actually hard and rare to add corner cases which make it Whonix-only.

Reasons for Freedom Software / Open Source

But what can we do? Invent a new identity for every component invented within Whonix community?

Put it in github.com/Sandbox-App-Launcher-Project/sandbox-app-launcher?

1 Like

Very good.
How about a wrapper that allows to run sal program-name? As a short wrapper. To avoid having to type a lot and to be able to drop the run parameter.

Sounds great!

Didn’t test but looks good in principle.

To be more generic, less Whonix / Kicksecure specific…
Could be improved by allowing only the linux user group of sandboxers doing that. Therefore user could be replaced with %sandboxers.
(Then I would add linux user user by default to group sandboxers.)

That is OK too. To avoid typing a long and complicated line, another wrapper could be added?

Makes sense. Please add as a comment in the source code somewhere.

Good question. Not sure. Maximum length for linux user account names is what?
The latter is quite long. Perhaps better an acronym such as sal?
By looking at /etc/groups and /etc/passwd examples I guess we shouldn’t use a too long name.

  • Sets wrapper_script at the top of the file like every other variable

This is cool. I wanted this too. Did that previously too. But by doing that I actually introduced a bug. Therefore set wrapper_script further below. Added an inline comment:

Various improvements by madaidan · Pull Request #46 · Kicksecure/sandbox-app-launcher · GitHub

Could you please have a look and check this works as intended?

1 Like

That would be a good idea.

This will usually only be used internally by the script - not by the user. A wrapper wouldn’t be needed.

https://linux.die.net/man/8/useradd

Usernames may only be up to 32 characters long.

That would definitely be an issue. sal is much better.

1 Like

Actually, having the name of the application as part of the user name might be an issue too. Long file names would break it. E.g. monero-blockchain-mark-spent-outputs (random file I found in /usr/bin, not necessarily important) would exceed the limit by far.

Instead, we could give them totally unrelated user names e.g. sal1, sal2, sal3, etc. The only way this could exceed the limit is if the user has used sandbox-app-launcher for an exorbitant amount of programs.

Or this issue could be deemed too niche to be acted on and we could keep the user names we currently have.

1 Like

Should sandbox-app-launcher have multi-user support? Someone asked for this a while ago: some questions · Issue #7 · madaidan/sandbox-app-launcher · GitHub

The sudoers exceptions would complicate this more too.

1 Like

For now we have a somewhat beautiful application home folder (app_homedir):
/home/sandbox-app-launcher-appdata/${app_name}

app_user is also nice: app_user="sandbox-${app_name}".

Thereby we have reproducible/deterministic/predictable application home folder and application user names. app_homedir and app_user are also connected through adduser --home "${app_homedir}". When manually examining /home/sandbox-app-launcher-appdata or sudo ps aux things look very clean and self-explanatory.

By using random hashes or an increasing number (sal1, sal2, …) we would introduce some issues.

When restoring backups the mapping of app_homedir and app_user might break. In Non-Qubes-Whonix imagine sandbox-app-launcher being run (perhaps auto-run by pre-wrapped applications) before restoring any backups or in Qubes(-Whonix) TemplateBased AppVMs app_homedir persists while app_user needs to be re-created at every reboot.

It makes it also harder to manually run under such a user account (such as development / debugging) since it would no longer be clear from the user name alone to which application it is referring.

As a simple solution for now sandbox-app-launcher setup could:

  • Use shorter prefixes, i.e. sal-.
  • Check after setting the app_user if the app_user variable is too long, echo error to stderr and exit non-zero.

To handle very long user names, perhaps that could be handled through config, command line parameter and/or environment variables?

monero-blockchain-mark-spent-outputs is actually an interesting case because while the binary is a different one, one would like to run all of the following:

  • monero-wallet-gui
  • monero-wallet-cli
  • monero-blockchain-mark-spent-outputs,
  • other monero-... tools

probably all under the same sal-monero user account (app_user) and app home folder /home/sandbox-app-launcher-appdata/monero (app_homedir).

Handing these two special cases (very long application names; running applications with different names under same app_user / app_homedir) seems low priority to me, could be done later as future work or patches welcome.

For me, since I will use this primarily with Whonix and Kicksecure, this would be nice to have / low priority / patches welcome. Good feature though if you’d like Debian, Ubuntu and other users use it too standalone.

Perhaps at least one thing should be implemented soonish for multi-user support? appdata_dir="/home/sandbox-app-launcher-appdata" is bad for that.

There was a reason for not using /home/user/sandbox-app-launcher-appdata. Could you add a script comment please?

How about

  • appdata_dir="/home/sandbox-app-launcher-appdata/user"
  • appdata_dir="/home/sandbox-app-launcher-appdata/another-user"

That would make future multi-user support easier? (Wondering what else would be missing after implementing the following…)

In case someone wondering… How would the script know under which /user/ it should create appdata_dir?

  • sandbox-app-launcher setup could demand to be run under sudo, i.e. sudo sandbox-app-launcher setup.
  • sandbox-app-launcher setup could refuse to directly run as user root (because then it doesn’t know for who user to setup).
  • The SUDO_USER environment variable could be tested for this purpose. Ie. appdata_dir="/home/sandbox-app-launcher-appdata/${detected_user_name}"
  • If sandbox-app-launcher setup is run and environment variable SUDO_USER = "", abort running (not running under sudo).
  • When sandbox-app-launcher run is run under sudo, exit error.
  • When sandbox-app-launcher run is run as user root, exit error.
  • When sandbox-app-launcher run is run, set detected_user_name to always existing environment variable USER. (Environment variable USER might be prone to manipulation by unprivileged user but that should be OK due to linux user access rights?)
  • When sudo sandbox-app-launcher setup is run, set detected_user_name to environment variable SUDO_USER.

How does that sound?

For non-Whonix / non-Kicksecure…
The sudoers exception(s) can use group %sandboxers. It would need to be documented in installation instructions and the postinst script could point out that no user is a member of the sandboxers group yet as a usability feature (with hint how to add or link to documentation).

I don’t see any disadvantage of using group %sandboxers instead of hardcoded user name user. Plain Debian mostly does not use username user anyhow. Similar issues often arise for Linux distributions without pre-configured user name with the need for the user to add oneself to audio, lpadmin, scanner, plugdev, audio, sudo, vboxusers among other examples. A major usability issue, complication for single user systems, which are most popular nowadays. But this isn’t a new disadvantage and I don’t see any solution for other than what I already described.

(Btw %sandboxers, not %sandbox since group %sandbox could be something else perhaps in future. Maybe all app_user would be useful to all be in group sandbox but that would be something to carefully think thought.)

Let’s say I sandboxed https://swaywm.org/

To send notifications to a sway session, you need to know $DBUS_SESSION_BUS_ADDRESS.
How can I send a notification from a user cronjob to a sway session?
For now, I extract $DBUS_SESSION_BUS_ADDRESS from /proc/sway's_pid/environ.

Perhaps, should I create a user cronjob for sandbox-username-sway user?
When you sandbox every application in its own home directory, IPC can become really difficult.

What about communicating with sandboxed pulseaudio?

We could keep the home directory names the same - home directories don’t have to be named the same as the user. We could also have a “translator” for the user names. E.g. /etc/sandbox-app-launcher/users with the contents:

sal1 torbrowser
sal2 hexchat
sal3 xpdf
...

We could handle this similar to app_path. i.e.

: ${app_user:="sal-${app_name}"}

So if the user wants to run e.g. monero-blockchain-mark-spent-outputs as sal-monero, they can execute:

app_user="sal-monero" sandbox-app-launcher run monero-blockchain-mark-spent-outputs

Seems like the best way to handle this.

That would allow any users in the %sandboxers group to access app data from other users. There would be no isolation between users.

We can dynamically append the exact user and sandbox they’re allowed to use to the sudoers file. Something like this in setup:

echo "${SUDO_USER} ALL=NOPASSWD: /usr/bin/sudo -H -u ${app_user}" >> /etc/sudoers.d/sandbox-app-launcher

Another issue with multi-user support would be, again, the user names. If a user has already setup a sandbox for Firefox, the sal-firefox user will be taken and other users won’t be able to sandbox Firefox. We could set:

app_user="sal-${SUDO_USER}-${app_name}"

but this would further worsen the issue of the user name length limit.

Is there a way to somehow increase the limit?

1 Like

D-Bus / PulseAudio are fully isolated. D-Bus is restricted to each user and PulseAudio is blacklisted entirely.

This could be relaxed in the future if we add a way to manage them safely (D-Bus filtering, PipeWire, etc.) but for now, allowing them would allow easy sandbox escapes so we can’t do that.

1 Like

Seems like this is hard coded in glibc. /usr/include/x86_64-linux-gnu/bits/local_lim.h contains:

/* Maximum login name length.  This is arbitrary.  */
#define LOGIN_NAME_MAX		256

(256 bits = 32 bytes)

We could probably change this by editing the file but I wouldn’t trust it enough to not crash and burn.

1 Like
1 Like

I want to be able to send notifications from a user cronjob to a sandboxed sway session with its own dbus session. Have you thought of a way other than setting up a passwordless sudo command for each command? Perhaps, I should start a cron daemon from sway?

What about using ALSA in a sandbox?

How is an older codebase than pulseaudio supposed to be a better idea?

I prefer ALSA to PulseAudio after using both. ALSA is simpler. I can plug PipeWire into ALSA.

$ echo $DBUS_SESSION_BUS_ADDRESS
unix:abstract=/tmp/dbus-HSBQCNgTjD,guid=2429fa577f9384ff718d3ba25fa1fa63

An abstract unix socket doesn’t have file permission. Thus, anything that has dbus session bus address can access it. Fortunately, /proc/PID/environ can only be read by the owner of PID.