/var/lib/snapd/hostfs and the removable-media interface

So I have these Pi Pico devices lying around since a while and decided on the weekend that it is time to take a look at how to work with them …

Following the getting started tutorial it turns out that the MicroPython side of the Pico is revolving a lot around the thonny IDE … I quickly found that the version of thonny in the archive is way to old to have the Pico support builtin, so as usual when I hit such a blocker I decided to take the 30min to quickly create a snap from upstream thonny …

… turns out that wasnt such a quick thing in the end …

When plugging in a Pico to your PC it auto-mounts under a fixed device name in /media/$USER/, so what Thonny does to detect the devices is to simply call “mount” via a subprocess call, parse the returned list of mountpoints and match for the expected device name … I indeed gave the app snap access to /media/$USER via removable-media …

… now … it turns out that “mount” actually returns also /var/lib/snapd/hostfs/media/$USER alongside with just /media/$USER … and apparently the snap tries to access the hostfs one first … which makes it fail and produce a permission denied traceback …

That made two questions materialize in my brain …

  • why do we expose hostfs by default all the time, is that really necessary
  • should removable-media not allow access to /var/lib/snapd/hostfs/media/$USER (being essentially the same as /media/$USER itself)

Oh, and in case anyone is interested in a quick and dirty Thonny snap, you can find the source at:

(along with a hacky patch to overcome the above issue)

Just to propose another “hack” that doesn’t involve patching, you could write a short wrapper around the mount binary to call the real mount and just reverse it’s output with tac to get thonny to use the last one, or you could just filter out hostfs mount entries yourself with grep there.

As to why we expose it, we expose it because it’s needed when we set things up in the mount namespace and we rely on the setup stages of snap-confine/snap-update-ns/friends, and IIRC since we use pivot_root, we need to leave the old rootfs that we pivoted away from mounted somewhere, but maybe we can still unmount it later technically speaking.

Perhaps more importantly though, some interfaces such as opengl allow access to files in /var/lib/snapd/hostfs/… so we would need to ensure that all such interface accesses continue to be available even if we unmount the real rootfs at /var/lib/snapd/hostfs. Also there is the journalctl from the host system access that we allow with the log-observe interface that would need to be handled elegantly.

that was actually my first attempt, but it turned out that subprocess.check_output() seems to not be happy with shell scripts without further changes to its options … since i had to touch that code anyway i decided to do all of it in the patch …

Note that it is clear to me why we have /var/lib/snapd/hostfs and that we cant get away without it in the current design. What i did absolutely not expect is that mountpoints in /media are duplicated in it though … and along with that, that removable-media doesnt grant access to the media path under hostfs/

that sounds really weird, what was the specific unhappiness ?

sorry I misunderstood your original question about why the interface grants it, but it doesn’t so I was confused. We probably could grant it like we do for other interfaces, but I think it would be leaking an abstraction that ideally we only leak in cases necessary like in the opengl case and the journalctl case for log-observe.

I think it needs shell=True or some such IIRC … it caused a traceback when i replaced mount with a script which worked fine standalone …

it is more like: “why is the mountpoint exposed twice” ?

I can not access /var/lib/snapd/hostfs/media/$USER/$DEVICE, I can access it via /media/$USER/$DEVICE through removable-media … could we perhaps hide the mounted bits in /var/lib/snapd/hostfs/media or are they of any actual use (and if we can’t, can we make them at least accessible alongside /media/$USER) ?

Well it’s not that snapd makes the choice to expose it twice, I think it has more to do with the fact that we have /var/lib/snapd/hostfs/media mounted and it’s setup to inherit mounts from the hostfs, so when it gets mounted on the host at /media, we inherit that mount both in /media where you can see it and in /var/lib/snapd/hostfs/media. I’m not sure if it’s possible to somehow unmount or prevent propogation of the /var/lib/snapd/hostfs/media mountpoint, but I did just test that it could be unmounted after the fact and then it stops showing up in mountinfo for hostfs, but still is available in /media since that’s a separate bind mount inside the snap’s mount namespace.

So TLDR, yeah technically it can probably be made such that it doesn’t show up, but it seems like a bit of work, so if I were you I would just file a LP bug and maybe we can try to fix it :grinning_face_with_smiling_eyes:

1 Like

Thinking on this… pivot_root calls allow the new root to mask the old root. (this is how initramfs works, for example.) Is there a reason we’re not mounting the accessible files/folders from our host’s real root into the target root at the same path relative to the target root as they have in the real root and then pivoting to that target root masking the original root? This will allow us to completely eliminate the hostfs path altogether…