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

[Feature] Sandboxed mode #28

Open
89luca89 opened this issue Dec 11, 2021 · 36 comments
Open

[Feature] Sandboxed mode #28

89luca89 opened this issue Dec 11, 2021 · 36 comments
Labels
enhancement New feature or request

Comments

@89luca89
Copy link
Owner

Right now the distrobox's containers are created in privileged mode and share a lot of sensitive host's folder.

This is done because the aim is tight integration with the host, not sandboxing.


It would be nice to have an optional (see: disabled if not specified) --unprivileged or a --sandbox flag in distrobox-create to have a more isolated container to work with.

@89luca89 89luca89 added enhancement New feature or request help wanted Extra attention is needed good first issue Good for newcomers labels Dec 12, 2021
@89luca89 89luca89 changed the title [ Feature ] Unprivileged/sandboxed mode [Feature] Unprivileged/sandboxed mode Dec 13, 2021
@89luca89
Copy link
Owner Author

Sandboxed distrobox should not integrate with the host as tightly as the normal one

$HOME should not be bind mounted
Host's rootfs should be mounted in readonly (or ideally not mounted at all)
Sockets should not be passed to the container

Sandboxed distrobox should not use --privileged and should not use --ipc host, --pid host

Thinking of functionality:

  • --sandbox seems an understandable flag to use
  • --allow-path could be used to allow some path to be mounted as read-write

@89luca89 89luca89 changed the title [Feature] Unprivileged/sandboxed mode [Feature] Sandboxed mode Dec 13, 2021
@89luca89
Copy link
Owner Author

Depends on #70

@BlauerHunger
Copy link

I think only implementing "fully sandboxed+unprivileged" and "fully integrated+privileged" modes are not the way to go, but rather adding options to configure it finer-grained like making only a specified set of devices available, only select sockets, mapping a custom selection of directories or other things possible for Flatpaks using Flatseal.

Based on that you could then add presets for integrated vs. sandboxed.

@89luca89
Copy link
Owner Author

89luca89 commented Jan 14, 2022

Well there is a big difference between distrobox and Flatpak, distrobox is not an application distribution method.
On one hand I agree having some more fine grained support is good
On the other, it's an extreme work to add support to filter specific devices (like, usb pen1 passes, usb pen2 does not pass etc etc)

I was thinking more on the lines of

Sanbox mode:

1 - custom home
2 - you specify which path can the container access
3 - you decide if devices in /dev/ are accessible or not
4 - you decide if you share:
- network namespace
- process namespace
- ipc namespace
- mount namespace
- (others)

And on that one can do a couple of profiles (low to high sandboxing)

@89luca89
Copy link
Owner Author

Adding to before
we should give options to:

  • mount in overlay, or not mount at all
    • /home
    • /
    • /dev
  • disable additional group mappings: run.oci.keep_original_groups=0
  • disable stuff like
    • network namespace
    • process namespace
    • ipc namespace
    • mount namespace
    • (others)

@ennec-e
Copy link
Contributor

ennec-e commented Feb 25, 2022

I had some ideas on sandboxing modes.
This gives overview of the modes I thought of, describing general use cases and overall access to Host.
The technical implementation specifics (what to mount / allow or exclude etc) of each mode shall be predetermined[?].

Mode Short see touch Comments
porous rw yes yes (default currently)
read-only ro yes nope
overlay-fork of touched up self (~fantasy host) ("just works" mode) [*]
isolate iso no no way! (fully locked down) [#]

[*]: try to be smoothe, smoother than porous even. does not conflict with sovereign Host. but [guest view] may diverge from ground truth (host state)
[#]: as close to completely seperate and airgapped [guest, host] as possible

[*], [#]: >
User should be able to successfully do as guest sudo rm -rf / (and deal with the consequences) without causing any hiccups on Host.
In effect overlay-fork can be thought to be like isolate mode but the starting point is Host state (in -of), as opposed to a blank slate (in -iso).

[?]: User would make a simple choice of mode and distrobox should make intelligent decisions in the backend.

@89luca89
Copy link
Owner Author

Great analysis yes, that is what I had in mind, with rw being the default.
For this to work we will need first to implement #119 and #120

And we will need a way to fix the workdir stuff (probaby depending on the level, we completely omit that?)

@bd4
Copy link

bd4 commented Mar 10, 2022

I was just thinking this, great to see it's already in the works!

Another possible use case here is running graphical windows apps with wine or native old / experimental proprietary applications, or even experimental open source apps. There is overlap with x11docker (and flatpak) here, so not sure what makes sense for distrobox; this use case requires more work re fine grained controls like sound, webcam, nested X server vs host X server, gpu vs not. Maybe makes sense to start simple with "isolate".

@89luca89
Copy link
Owner Author

I was just thinking this, great to see it's already in the works!

Another possible use case here is running graphical windows apps with wine or native old / experimental proprietary applications, or even experimental open source apps. There is overlap with x11docker (and flatpak) here, so not sure what makes sense for distrobox; this use case requires more work re fine grained controls like sound, webcam, nested X server vs host X server, gpu vs not. Maybe makes sense to start simple with "isolate".

Yea starting with a "simpler" sandbox mode

The target (at least generally speaking) is some sort of general isolation (not going to provide super-capillar controls like flatpak for example)
Adding such fine grained controls would be too much and out of scope of the project (imho), let's keep in mind that the point of distrobox (and toolbx) is integration not isolation, obviously if you need complete isolation and security it is faster adding just the bits you need to a plain podman/docker than removing all the integration from here 😄

@bd4
Copy link

bd4 commented Mar 10, 2022

Yes simple is good, I think that is what makes toolbox/distrobox so great!

I think an interesting distinction with distrobox vs something like x11docker is mutability and persistence. x11docker and similar are designed to have an immutable core, that is changed by creating a new image, e.g. Dockerfile with new layers, and have mutable data exposed via volumes. Distrobox and toolbox on the other hand have a mutable core by default, you can just sudo dnf/apt/zypper etc as much as you want, so it's more like working in a standard chroot. I think both have their pros and cons. What excites me about distrobox+isolate is that it can provide a more chroot like workflow while still providing sandbox/isolation. I think LXC and systemd-nspawn are in this category as well, but so far only toolbox and distrobox hit the too simple not to use threshold (even easier than setting up schroot and debootstrap/pacstrap really).

The cool thing is, with just isolate + the ability to bind mount specific files (pass directly to docker/podman -v?), a lot of more advanced use cases should be possible, e.g. mostly isolated but expose gpu for CUDA/ROCm/oneAPI development. They may not all be trivial with a specialized switch, but possible and still easier than doing it manually with podman.

@89luca89
Copy link
Owner Author

89luca89 commented Mar 10, 2022

Yes simple is good, I think that is what makes toolbox/distrobox so great!

I think an interesting distinction with distrobox vs something like x11docker is mutability and persistence. x11docker and similar are designed to have an immutable core, that is changed by creating a new image, e.g. Dockerfile with new layers, and have mutable data exposed via volumes. Distrobox and toolbox on the other hand have a mutable core by default, you can just sudo dnf/apt/zypper etc as much as you want, so it's more like working in a standard chroot. I think both have their pros and cons. What excites me about distrobox+isolate is that it can provide a more chroot like workflow while still providing sandbox/isolation. I think LXC and systemd-nspawn are in this category as well, but so far only toolbox and distrobox hit the too simple not to use threshold (even easier than setting up schroot and debootstrap/pacstrap really).

Yes the point of toolbox and distrobox is simplicity and well use the big number of well maintained container images on the vaiorus registries 😄

The cool thing is, with just isolate + the ability to bind mount specific files (pass directly to docker/podman -v?), a lot of more advanced use cases should be possible, e.g. mostly isolated but expose gpu for CUDA/ROCm/oneAPI development. They may not all be trivial with a specialized switch, but possible and still easier than doing it manually with podman.

As you can see in the docs here:

Distrobox already supports a --additional-flags/-a flag to pass directly the podman/docker flags to the container manager, and a --volume/-v flags to add additional volumes 😄

@leleleSDX
Copy link

would leveraging sandbox tools like firejail work for the moment?

@89luca89
Copy link
Owner Author

would leveraging sandbox tools like firejail work for the moment?

Didn't think of this, we could use bwrap maybe as it does not require root to run, but probably worth experimenting

@Aex12
Copy link

Aex12 commented May 28, 2022

Didn't think of this, we could use bwrap maybe as it does not require root to run, but probably worth experimenting

Doesn't podman already isolate the container from the host? Wouldn't it be redundant to bwrap podman?

@xerz-one
Copy link

xerz-one commented Aug 4, 2022

ok so while we're at it, here's a hacky solution I just crafted. This does not substitute the mounts performed by distrobox-init as of yet, so it won't expose things like networking or GUI sockets as expected.

Just declare $NAME and $IMAGE and run the following

mkdir -p ~/.local/bin ~/.local/share/distrobox/$NAME
cp $(which distrobox)-{init,create,export,host-exec} ~/.local/bin/
sed -i '/--volume \/:\/run\/host:rslave/d' ~/.local/bin/distrobox-create
DBX_CONTAINER_CUSTOM_HOME=~/.local/share/distrobox/$NAME ~/.local/bin/distrobox-create --image $IMAGE --home ~/.local/share/distrobox/test --name $NAME

now you can just run it with distrobox enter --no-workdir $NAME 🎉

Update: if all you need is an Internet connection, you can further patch distrobox-create to bind into /run/host/etc/{hosts,localtime,resolv.conf}

@89luca89
Copy link
Owner Author

89luca89 commented Aug 8, 2022

@xerz-one

I'm not planning on working on this very soon

The plan anyway should be:

1 find what is needed to have the minimum possible to have working:

  • audio
  • video
  • xorg/wayland
  • internet/lan

2 create a "sandboxed" profile that just mounts the minimum

Anything more than that should not be in scope of the project, as the point of toolbox/distrobox type of software is the host's integration, and de-integrating too much would just be a waste of effort. If anyone needs further sandboxing, they can always use podman/docker directly

@FedX-sudo
Copy link
Contributor

I was experimenting with this idea, and I was wondering if it would be benefitial to include a --disalow-path to compliment the --allow-path.

@xerz-one
Copy link

xerz-one commented Dec 20, 2022

Personal update: I find myself no longer needing this. It turns out a more bare podman with Pods can easily achieve a sandboxed environment with support for desktop apps and nested desktop sessions. Leaving it here in case anyone is interested, still hoping the best for Distrobox!

Here's what's needed to get Podman to launch apps

  • XDG
    • Volumes
      • /run/user/1000:/run/user/1000, where the first 1000 is the host $UID (check $XDG_RUNTIME_DIR on host to make sure)
    • Environment variables
      • XDG_RUNTIME_DIR=/run/user/1000
  • Wayland
    • Requires XDG settings
    • Environment variables
      • WAYLAND_DISPLAY=wayland-0, where wayland-0 is the host $WAYLAND_DISPLAY (it represents a file at $XDG_RUNTIME_DIR)
  • X11
    • Volumes
      • /tmp/.X11-unix:/tmp/.X11-unix
    • Environment variables
      • DISPLAY=:0, where :0 is the host $DISPLAY
    • Commands to run on host
      • xhost +"local:podman@"
  • Pulseaudio
    • Requires XDG settings
    • Environment variables
      • PULSE_SERVER=/run/user/1000/pulse/native

It's worth keeping in mind that returning from the in-app terminal to the main UI will end the shell process and all of its children, so if you want to use it you should detach any process you want to keep alive.

@89luca89
Copy link
Owner Author

@xerz-one that's great finding thanks!
This will surely be useful in the future when I (or someone else? 👀 ) will work on this

Thanks!

@TheComputerM
Copy link

Any updates on this?

@damianoognissanti
Copy link
Contributor

Since the container only can see the home of the user running distrobox (but it sees it even when another home folder is specified for the container), isn't one solution that a sandbox-mode just creates another user without password (e.g. named distrobox) that runs distrobox-enter, so that when you run an exported program it will run something like:
"su -l distrobox -c distrobox-enter -n debian -- /usr/bin/chromium %U"

@juhp
Copy link
Contributor

juhp commented Apr 14, 2023

It turns out a more bare podman with Pods can easily achieve a sandboxed environment with support for desktop apps and nested desktop sessions. [..]
Here's what's needed to get Podman to launch apps

@xerz-one, is the setup described in more detail somewhere?

@digitalsignalperson
Copy link

Since the container only can see the home of the user running distrobox (but it sees it even when another home folder is specified for the container), isn't one solution that a sandbox-mode just creates another user without password (e.g. named distrobox) that runs distrobox-enter, so that when you run an exported program it will run something like: "su -l distrobox -c distrobox-enter -n debian -- /usr/bin/chromium %U"

This tool might help achieve this or be inspiration: https://github.com/intgr/ego

@diegosouza
Copy link

diegosouza commented Jun 9, 2023

My 2 cents to the discussion: some services (like Bitbucket Pipelines Cloud) do not support --privileged (reference).
I was almost ready to deliver a reestructured pipeline and I could not finish because of this kind of limitation.

To sum up: --unprivileged could solve my problem.

89luca89 added a commit that referenced this issue Jun 23, 2023
Signed-off-by: Luca Di Maio <luca.dimaio1@gmail.com>
@89luca89
Copy link
Owner Author

Hi all
I did a basic draft that you can check here:

#818

Let me know how this works 👍

@89luca89 89luca89 linked a pull request Jun 23, 2023 that will close this issue
@osalbahr
Copy link
Contributor

osalbahr commented Jun 28, 2023

This seems great for porting to macOS, actually (#36). On macOS I don’t need to interact with the base system from inside the distrobox for my use case, but only access to dev tools (and the internet). So podman running in a VM shouldn’t be an issue for this mode.

89luca89 added a commit that referenced this issue Aug 26, 2023
Signed-off-by: Luca Di Maio <luca.dimaio1@gmail.com>
89luca89 added a commit that referenced this issue Aug 26, 2023
Signed-off-by: Luca Di Maio <luca.dimaio1@gmail.com>
89luca89 added a commit that referenced this issue Aug 26, 2023
Signed-off-by: Luca Di Maio <luca.dimaio1@gmail.com>
@89luca89 89luca89 removed a link to a pull request Aug 26, 2023
89luca89 added a commit that referenced this issue Aug 26, 2023
This should ensure a basic unsharing between guest and hosts

This is not a proper sandbox

This allows to:

-unshare-devsys: do not share host devices and sysfs dirs from host
-unshare-ipc: do not share ipc namemspace with host
-unshare-netns: do not share the net namespace with host
-unshare-process: do not share process namemspace with host

And an unshare-all to do all the above.
This allows to have only the minimal requirements to:

access user's HOME
launch applications with GUI/GPU/Audio/Video
Additional mountpoints can be declared with --volume

Signed-off-by: Luca Di Maio <luca.dimaio1@gmail.com>
@89luca89
Copy link
Owner Author

I have just now merged #818

As explained in the PR:

THIS IS NOT A PROPER DATA SANDBOX

This should ensure a basic unsharing between guest and hosts

This allows to:

-unshare-devsys: do not share host devices and sysfs dirs from host
-unshare-ipc: do not share ipc namemspace with host
-unshare-netns: do not share the net namespace with host
-unshare-process: do not share process namemspace with host

And an unshare-all to do all the above.

This allows to have only the minimal requirements to:

access user's HOME
launch applications with GUI/GPU/Audio/Video
Additional mountpoints can be declared with --volume

For now I'm not contemplating unsharing the home that would be a bit too much and denaturalise the purpose of distrobox itself.

@bigpod98
Copy link

i guess my suggestion #969 would fall around this

@soufrabi
Copy link
Contributor

soufrabi commented Oct 8, 2023

Is there a way to atleast deny the container access to a few paths such as the host's ~/.gnupg , ~/.password-store, ~/.ssh ?

@IPlayZed
Copy link

For now I'm not contemplating unsharing the home that would be a bit too much and denaturalise the purpose of distrobox itself.
Is there a way to atleast deny the container access to a few paths such as the host's ~/.gnupg , ~/.password-store, ~/.ssh ?

In my opinion, going a whitelist route is the most sensible, something like Flatpak does. Only share what needs to be shared.
Certain images for Distrobox could declare their specific needs, like Waydroid would need binderfs for instance, but by default never allow, only deny, that is the point of sandboxing.
I wonder, is there a solution for running certain programs temporarily with a well defined privilage set? Like with polkit, only allowing certain actions for a given program in a container.

@Froggy232
Copy link

Hi,
First, thanks you a lot for your work!

I agree that a data sandbox mode with whitelist would be awesome, and I have the feeling that it would be really close to attain with options like custom home for container.
Is it really not an option to develop this feature in the future?
I find it sad that it got dismissed, it would really be useful for some containerized software (if not the majority of them) to not having access to home directory, and then having a whitelist system that permit to give access to one or few specifics folders.
Of course, this feature would not be a default, it would just be an option at the creation of the container.

I think it would be really, really useful to a lot of people, myself included.
Anyway, thanks you a lot for your work, I use it everyday on universalblue and it's really amazing, thanks you again!

@IPlayZed
Copy link

I think it would be really, really useful to a lot of people, myself included.

The point of this would be a platform-independent implemention of something like firejail for programs not made for the given platform of with sandboxing in mind, like a snap or flatpak package, as far as I see.

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

No branches or pull requests