Read access to a file in /var/lib on the host


#1

Hello!

I’m developing a tool to help gathering data when filing a bug about a device.

I need to access the content of the file /var/lib/ubuntu_dist_channel (when available). It’s the same file that is used by ubuntu-report to gather info about an OEM image (see ubuntu-report source code here).

The problem is that this file is not available from within the snap, not even in --devmode:

# From outside the snap on a device with an OEM image
$ ls /var/lib/ubuntu_dist_channel 
/var/lib/ubuntu_dist_channel
$ ls -l /var/lib/ubuntu_dist_channel 
-rwxr-xr-x 1 root root 209  六  11 14:44 /var/lib/ubuntu_dist_channel

# From inside the snap
$ snap run --shell qabro
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

$ ls -l /var/lib/ubuntu_dist_channel
ls: cannot access '/var/lib/ubuntu_dist_channel': No such file or directory

How can I access the content of this file?

Thank you!


#2

Your snap is running in a separate mount namespace where the root file system is provided by the base snap you’re using. As the file in question does not exist in the core snap, you get the “No such file” error even when running in devmode.

The host system’s root file system is available at /var/lib/snapd/hostfs though, so if you are running in devmode you could probably access /var/lib/snapd/hostfs/var/lib/ubuntu_dist_channel. However this access will be blocked by AppArmor when running with strict confinement.

You could probably get this working with strict confinement through the use of the system-files interface. Try adding something like this to your snapcraft.yaml:

plugs:
  dist-channel:
    interface: system-files
    read:
      - /var/lib/snapd/hostfs/var/lib/ubuntu_dist_channel

You would then need to ensure the plug was connected before running your command. Use of this interface triggers manual review on the store, but I doubt that will be a problem for a tool like this.


#3

Thanks a lot for this detailed reply! The file is indeed accessible (using devmode) in /var/lib/snapd/hostfs/var/lib/ubuntu_dist_channel.

I’ll investigate how complicated it would be to switch to strict, but it might be very tricky since I also use sosreport which gathers a lot of data about the system.


#4

Well, devmode is not going to be a workable solution for distributing your app. As it’s name implies, it is intended for development, and disables automatic updates.

If the kind of data you want to gather cannot be expressed via the interfaces provided by snapd (including via system-files), it might be worth exploring classic confinement. This is roughly equivalent to the environment your app would run in as a .deb: you will see the host system file system, and run with a permissive AppArmor profile that is roughly equivalent to unconfined.

Note that classic confinement snaps have their own issues: since you’re running against the host’s root file system, it is a lot easier to produce a snap that only behaves correctly on a few distro releases. You’ve lost many of the “build once run anywhere” guarantees of snaps.


#5

Thanks for the feedback.

I know that --devmode should be limited to, well, development (but it’s always good to remind people about that!).

My app serves a very special purpose, though: debugging devices while ongoing OEM testing with Ubuntu. Therefore, a typical use case would be to install its latest version when QA engineers find a bug in order to file it quickly on Launchpad with as much info as possible. The device will likely be formatted a few days/weeks later in order to test a newly released OEM image.

In addition, my snap also needs to work on Ubuntu Core (cause of some IoT projects), so --classic won’t do, unfortunately.

P.S.: I didn’t know --devmode snaps didn’t retrieve updates automatically, TIL :slight_smile:


#6

Some of the access to hardware information can be granted via the hardware-observe interface. For processes you can try process-control. There’s also system-observe.

ref: https://docs.snapcraft.io/t/the-system-observe-interface/7921
and: https://docs.snapcraft.io/supported-interfaces

You might also want mount-observe https://docs.snapcraft.io/t/the-mount-observe-interface/7876