Caveats for no-patchelf in a classic snap

patchelf is used to do two things for classic snaps:

Strict snaps have the advantage of having their own namespace with the base (e.g. core18) snap as its root, providing the linker and libraries in the correct location as far as the running snap is concerned (e.g. /lib64/ld-linux-x86-64.so.2 and /usr/lib/x86_64-linux-gnu/). The former being a path hardcoded in the binary executable, with the latter being configured by ldconfig, etc.

Classic snaps OTOH share the same namespace as the host, so we must modify the executables’ interpreter and RPATH so the correct interpreter and libraries are found on load (e.g. /snap/core18/current/lib64/ld-linux-x86-64.so.2 and /snap/core18/current/usr/lib/x86_64-linux-gnu).

To make these changes, snapcraft relies on patchelf to modify these on the already-built executables. Unfortunately, to make these modifications to executable (that’s already been linked) changes may be required to increase the size of certain ELF segments/sections to include these strings. This results in patchelf shuffling around some of the data found in the executable.

Specifically here, there are two issues at play. As part of the shuffling, in some scenarios, patchelf may end up shuffling the GNU build id note section, that normally will live in the “note” segment (i.e. PT_NOTE) into another segment (not PT_NOTE). This may cause issues for applications that assume they are in the note segment, such as mesa (https://github.com/intel/external-mesa/blob/master/src/util/build_id.c#L75), and even snapcraft itself until recently (https://github.com/snapcore/snapcraft/pull/3111).

It has been on my wishlist to (1) sort out a fix for mesa’s segfaulting behavior and (2) sort out a fix for patchelf to improve handle the shuffling of the notes (segments). While we can still find the build-id note correctly if we look for the note sections, patchelf leaves the note segment around with data that causes anyone parsing it, thinking they’re legitimate note sections, to fail - as happening with mesa, happened with snapcraft, and occurs even with binutil’s readelf.

In general, when using no-patchelf for a classic snap, I would minimize the parts that its applied to. If the classic snap works without the patchelf, you may be good, but there is always the possibility of issues. It’s most important that it gets applied to the binaries that are executed, perhaps it matters less for some shared objects (?) like in this mesa case.

It would be nice if snapcraft offered a more fine-grained approach to controlling patchelf, but in the meantime I would suggest that the part minimize what it is staging/priming when using it.

2 Likes