containers / bubblewrap

Low-level unprivileged sandboxing tool used by Flatpak and similar projects
Other
3.9k stars 238 forks source link

[Question] How does bwrap handle nested bindings? #612

Closed ruanformigoni closed 10 months ago

ruanformigoni commented 10 months ago

For example, say I have:

test-ro/
└── dir1
    └── dir2

If I execute:

bwrap --bind ./root-alpine/ / --ro-bind test-ro /media --bind test-ro/dir1 /media/dir1 /bin/sh

Is it well-defined behavior that dir1 would be writeable and attempted to be mounted after the test-ro -> /media binding (following the positional ordering)?

When I do the reverse:

bwrap --bind ./root-alpine/ / --bind test-ro/dir1 /media/dir1 --ro-bind test-ro /media /bin/sh

It tries to create the path /media/dir1 inside root-alpine (fails if it is read-only), and then binds the read-only top level directory test-ro, which makes sense.

smcv commented 10 months ago

Is it well-defined behavior that dir1 would be writeable and attempted to be mounted after the test-ro -> /media binding (following the positional ordering)?

Yes, the man page documents that "Filesystem related options [...] are applied in the order they are given as arguments".

When I do the reverse:

bwrap --bind ./root-alpine/ / --bind test-ro/dir1 /media/dir1 --ro-bind test-ro /media /bin/sh

It tries to create the path /media/dir1 inside root-alpine (fails if it is read-only), and then binds the read-only top level directory test-ro, which makes sense.

Yes, the --ro-bind in this example will cover up the previous --bind, and this behaviour is as documented (and not particularly useful in this case, but you asked for it, so you got it).

ruanformigoni commented 10 months ago

Thanks for answering the previous question. I have encountered a behavior with symlinks I did not expect, consider this directory structure:

bin -> usr/bin
dev
etc -> /home/user/bwrap/etc
fim
home
lib -> usr/lib
lib64 -> usr/lib
media
mnt
opt
proc
root
run
sbin -> usr/bin
share -> /usr/share
sys
tmp
usr
var

If I run something like this:

bwrap  --bind "root-alpine/" / --bind /tmp /tmp --bind "$HOME" "$HOME" --bind "/etc/passwd" "/etc/passwd" /usr/bin/bash

I thought it would bind the host /etc/passwd on /home/user/bwrap/etc/passwd, however it errors out with bwrap: Can't create file at /etc/passwd: No such file or directory. But I can make it work dereferencing beforehand, which would be something like this:

bwrap  --bind "root-alpine/" / --bind /tmp /tmp --bind "$HOME" "$HOME" --bind "/etc/passwd" "/home/user/bwrap/etc" /usr/bin/bash

Is there a flag to dereference the target beforehand the bind attempt?

smcv commented 10 months ago

Is there a flag to dereference the target beforehand the bind attempt?

No. If that is something you want, that's something that a larger framework around bwrap can/should do if it wants to (for example, take a look at the FlatpakExports object in flatpak, which manages many of flatpak's uses of bwrap).

bwrap is a tool for making use of namespaces, rather than a ready-to-use container/sandbox product. Because bwrap is setuid root in some system configurations, every line of code in bwrap is a potential root security vulnerability, so it doesn't generally do "nice to have" functionality that could be done equally well by a higher-level tool that calls into it, like Flatpak.