Caveats for no-patchelf in a classic snap

In previous posts (e.g. Snap crashes when using intel graphics), it has been noted that using no-patchelf may fix a problem seen by classic snaps where they may crash on startup. In some of the discussions in those posts, there are vague comments like “there are some caveats” (e.g. Problems after switching to classic confinement), but I haven’t found a clear description of the consequences of using no-patchelf. For the specific case that affects the cmake snap, no-patchelf appears to help by preventing the build-id from being stripped out of the libgl1-mesa-dri library. Before I commit to using no-patchelf though, I would like to understand what else I’m disabling by adding that build attribute and whether it will negatively impact the cmake snap.

  • @sergiusens You seem best placed to provide this info, can you clarify what no-patchelf will do?
  • @popey You’ve made comments about the caveats too, please feel free to chime in with details.
  • @cjp256 Pinging you since you found the workaround discussed here.

Note that for snaps using the snapcraft-desktop-helpers, it is not so straightforward to limit the no-patchelf attribute to specific libraries, so it may get applied more broadly to other libraries that might not otherwise need it. See my naive, simple way that appears to fix the problem for the cmake snap, but it will affect many libraries, not just the problematic libgl1-mesa-dri library.

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