Denials when opening libraries appear after snapcraft change

Latest snapcraft changes the way LD_LIBRARY_PATH is defined in the command wrappers. Now it is

export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$SNAP/lib:$SNAP/usr/lib:$SNAP/lib/x86_64-linux-gnu:$SNAP/usr/lib/x86_64-linux-gnu"
export LD_LIBRARY_PATH=$SNAP_LIBRARY_PATH:$LD_LIBRARY_PATH

while previously it did not include $SNAP/lib and $SNAP/lib/<arch>. Due to this, I had to explicitly include the dynamic linker in the network-manager snap, which was not previously needed. Also, some apparmor denials started to appear when running the service:

[ 3804.003697] audit: type=1400 audit(1528271878.010:336): apparmor="DENIED" operation="open" profile="snap.network-manager.networkmanager" name="/snap/core/4650/lib/x86_64-linux-gnu/libuuid.so.1.3.0" pid=6951 comm="NetworkManager" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
[ 3804.004200] audit: type=1400 audit(1528271878.010:337): apparmor="DENIED" operation="open" profile="snap.network-manager.networkmanager" name="/snap/core/4650/lib/x86_64-linux-gnu/libglib-2.0.so.0.4800.2" pid=6951 comm="NetworkManager" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
[ 3804.004328] audit: type=1400 audit(1528271878.010:338): apparmor="DENIED" operation="open" profile="snap.network-manager.networkmanager" name="/snap/core/4650/lib/x86_64-linux-gnu/libnl-3.so.200.22.0" pid=6951 comm="NetworkManager" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
[ 3804.004491] audit: type=1400 audit(1528271878.010:339): apparmor="DENIED" operation="open" profile="snap.network-manager.networkmanager" name="/snap/core/4650/lib/x86_64-linux-gnu/libdl-2.23.so" pid=6951 comm="NetworkManager" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
[ 3804.004605] audit: type=1400 audit(1528271878.010:340): apparmor="DENIED" operation="open" profile="snap.network-manager.networkmanager" name="/snap/core/4650/lib/x86_64-linux-gnu/libm-2.23.so" pid=6951 comm="NetworkManager" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
[ 3804.004712] audit: type=1400 audit(1528271878.010:341): apparmor="DENIED" operation="open" profile="snap.network-manager.networkmanager" name="/snap/core/4650/lib/x86_64-linux-gnu/libpthread-2.23.so" pid=6951 comm="NetworkManager" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
[ 3804.004812] audit: type=1400 audit(1528271878.010:342): apparmor="DENIED" operation="open" profile="snap.network-manager.networkmanager" name="/snap/core/4650/lib/x86_64-linux-gnu/libc-2.23.so" pid=6951 comm="NetworkManager" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
[ 3804.005029] audit: type=1400 audit(1528271878.010:343): apparmor="DENIED" operation="open" profile="snap.network-manager.networkmanager" name="/snap/core/4650/lib/x86_64-linux-gnu/librt-2.23.so" pid=6951 comm="NetworkManager" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
[ 3804.005079] audit: type=1400 audit(1528271878.010:344): apparmor="DENIED" operation="open" profile="snap.network-manager.networkmanager" name="/snap/core/4650/lib/x86_64-linux-gnu/librt-2.23.so" pid=6951 comm="NetworkManager" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
[ 3804.005179] audit: type=1400 audit(1528271878.010:345): apparmor="DENIED" operation="open" profile="snap.network-manager.networkmanager" name="/snap/core/4650/lib/x86_64-linux-gnu/libz.so.1.2.8" pid=6951 comm="NetworkManager" requested_mask="r" denied_mask="r" fsuid=0 ouid=0

For some reason, the dynamic loader is trying to load files from /snap/core, while that path is not in LD_LIBRARY_PATH. The denials have no side effect, as in the end the dl loads the libraries from /lib/<arch>/ - which are those shipped by the core snap indeed. But, I would like to understand why this happens and how to get rid of the denials. An option is including all libraries inside the snap, but that increases quite a bit its size, so that will not be always an option.

It might be patchelf doing things to your binaries here. Could you please try the solution that @sergiusens suggested in Patchelf broke my binary? ? I.e.:

parts:
    part-name:
        build-attributes: [no-patchelf]

and see if that helps?

This seems to be a strictly confined snap for which we do not do any elf patching.
We do now however do a search for symbols inside the primed directory to figure out the exact list of library paths to export, so if you have hidden dependencies from other parts, the use of after is key. Alternatively you can add whatever you need by use of environment:

apps:
    foo:
        command: ...
        ...
        environment:
            LD_LIBRARY_PATH: "<library-path>"

Or master it completely by getting rid of the wrapper entirely:

apps:
    foo:
        command: ...
        ...
        adapter: none
        environment:
            LD_LIBRARY_PATH: "<library-path>"

@sergiusens following @mvo 's suggestion I have tried with and without no-patchelf. Without that attribute, this is the output of readelf -d:

And this is the output when the attribute is not present:

The second one does have RPATH defined, so definitely something is going on there. Furthermore, setting no-patchelf solves the denials, so it looks like patchelf is related ti the issue. This is the snapcraft version I am using (snap rev 1594):

$ snapcraft version
snapcraft, version 2.42.1

Looking more closely to the RPATH in https://paste.ubuntu.com/p/KJtqFGh55P/, the bad path is there:

...:/snap/core/current/lib/x86_64-linux-gnu

that is the reason for the denials, it is in the search path.

This snap had libc6 in stage-packages of a part, and it looks like that triggers usage of patchelf from snapcraft. Dropping that seems like the best solution atm.

It will be the best solution in the past and future too :slight_smile: That said, I think we want to trigger a warning when people add libc6, it is a very interesting library to say the least.

@sergiusens is this intentional? Libc can only be used from the rootfs (that is /lib/…) and not from the core snap directly. The only exception for this rule is classic confinement where it is the reverse.

Yes, this is how you can backport binaries from future compilations to the past (such as 17.10), done in such a way that you basically rely on almost nothing from the base.

Unless I misunderstand something this was not communicated to us before and as such apparmor rules will prevent accessing libraries from core snap (that is from /snap/core/current/) to strictly confined processes.

This doesn’t apply to snaps that ship libraries inside their own snap obviously, this was always allowed.

I do not intend to be able to explain the denials with this, not at all.