System-package leaks into confined snap?

Hi,

So I’m experiencing an odd behavior of a snap package I’m maintaining. This package requires tcpdump and libpcap8.0, which is staged and shipped with the snap.

For a while I’ve been investigating why it works on my laptop (Ubuntu Desktop) and a RPi3 with Ubuntu Server, but not on my RPi4 with Ubuntu Core.

So Yesterday I re-installed a new version of Ubuntu Server and installed the snap. It worked as expected.

Then I realized that the packages tcpdump and libpcap8.0 is pre-installed on Ubuntu Server, through apt.

So I uninstalled them and did a reboot. Now the snap won’t work anymore.

It’s the Python program scapy that uses the above packages. I have narrowed the problem down to the method find_library within the ctypes.util module. The documentation says that it will use

ctypes.util.find_library(name)

Try to find a library and return a pathname. name is the library name without any prefix like lib, suffix like .so, .dylib or version number (this is the form used for the posix linker option -l). If no library can be found, returns None.

The exact functionality is system dependent.

On Linux, find_library() tries to run external programs (/sbin/ldconfig, gcc, objdump and ld) to find the library file. It returns the filename of the library file.

Changed in version 3.6: On Linux, the value of the environment variable LD_LIBRARY_PATH is used when searching for libraries, if a library cannot be found by any other means.

I know that /usr/sbin/ldconfig is available on the «main» system of Ubuntu, and also included in the core* snap pacakges. It is not bundled with my snap.

However I don’t understand how ctypes.util can gain access to this program and list system libraries? It shoudl be restricted access to the program ldconfig, and fallback (from doc) to LD_LIBRARY_PATH, which is set correctly:

LD_LIBRARY_PATH:=/var/lib/snapd/lib/gl:/var/lib/snapd/lib/gl32:
    /var/lib/snapd/void:/snap/<snap>/354/lib:/snap/<snap>/354/usr/lib:
    /snap/<snap>/354/lib/aarch64-linux-gnu:
    /snap/<snap>/354/usr/lib/aarch64-linux-gnu

But I guess it’s never used since ldconfig is leaked into the snap package?

This is the PATH:

PATH=/snap/<snap>/354/usr/sbin:/snap/<snap>/354/usr/bin: 
     /snap/<snap>/354/sbin:/snap/<snap>/354/bin:
     /usr/local/sbin:/usr/local/bin:/usr/sbin:
     /usr/bin:/sbin:/bin:/usr/games:
     /usr/local/games

I could probably restrict this by doing a layout for /usr/sbin/ and every other path in the PATH-variable that is not /snap/. But shouldn’t it work like this by default, since the PATH variable is set by default like this, and at least restrict access to files withing them?

Could also ship ldconfig with the snap, but since ctypes.util already have the information it needs in LD_LIBRARY_PATH I figured it shouldn’t be unnecessary?

Figured out that /etc/ld.so.cache is readable from the snap (it is not in $SNAP/etc/ld.so.cache)

However, that does not explain why ldconfig is available.

it might be that an interface you connected actually adds access to libpcap of the host (likely one of the network- ones) … and while your UbuntuServer has a normal deb based rootfs, Ubuntu Core actually uses the respective core snap (i.e. core20 on UC20 … core18 on UC18) as rootfs … there libpcap is not shipped …

the proper solution is really to ship what you need in stage-packages and not rely on such interface behavior …

Hi, thanks for the reply.

As mentioned in my post, «tcpdump» and «libpcap» is staged and shipped with my snap. But ldconfig is used by ctypes.util.find_library which reads the libraries specified in the /etd/ld.so* cache-/config-files

(ldconfig is not shipped by my snap):

This is on Core:

$ sudo snap run --shell <snap>

root@ubuntu:/snap/<snap>/352# ldconfig -p
159 libs found in cache '/etc/ld.so.cache'
libzstd.so.1 (libc6,AArch64) => /lib/aarch64-linux-gnu/libzstd.so.1
[.. + list of 158 other files ..]
root@ubuntu:/snap/<snap>/352# which ldconfig
/usr/sbin/ldconfig

which is not in $SNAP/lib/aarch64-linux-gnu/ or $SNAP/usr/lib/aarch64-linux-gnu

What happens if you add libzstd1 to stage-packages? Does that fix the problem?

Edit: Actually, you are finding libzstd. Which library are you not finding on the search path?

Thanks, I’ll try - but what benefit does this package give?

It reads the /etc/ld.so.cache from host. So actually any that you like to find through ctypes.util.find_library - considered the scenario where the libraries totally differs.

If the host have the library - and the snap do too - there’s no problem. However… The Ubuntu Core do not have libpcap and it’s not possible to add it either.

EDIT: But I’ve noticed that my snap do not have access to /usr/local/lib which is configured for ldconfig. So I’m trying to layout this path.

I think you’re incorrect in this, but I’m not 100% certain. AFAIK the ld.so.cache is stored in the base snap you’re targetting. Would it be possible for you to share your project and snapcraft.yaml so we might investigate?

I’ve validated it by going into the shell of the snap and simply ran dlconfig -v.

That output reflects what is in /usr/lib/<arch> on the host.

None of the packages in $SNAP/usr/lib/<arch> is listed, except when they both have the same library of course.

Here’s the yaml.