LD_PRELOAD from host environment should be cleared when starting an app

Currently, if the host has an LD_PRELOAD environment variable set this is leaked into the Snap environment when starting an application. This means that the linker inside the Snap will attempt to load the library indicated by the host’s LD_PRELOAD and fail because the library is invariably not exposed through confinement. Therefore it is prudent for Snapd to clear the LD_PRELOAD environment variable when starting a Snapped application.

Seems reasonable to me for strict snaps, what about classic snaps? Is there any valid use case for a classic snap to use/read LD_PRELOAD from the host given that it can use arbitrary programs from the host?

It was the strict snap usecase that I was thinking about.

For classic snaps I can see an argument either way: on the one hand a snap is supposed to be self-contained even though as classic it can access other programs so it should not load libraries into its runtime that are not shipped in the snap. On the other hand classic indicates that all rules are disabled so people might expect to be able to force the app to load any library they choose.

Personally, I would prefer that LD_PRELOAD be disabled for both strict and classic snaps to allow a snap author to be certain that what they shipped is what is actually running.

I think LD_PRELOAD is just the tip of the iceberg:

  • PATH - a strict snap has a completely different root file system and is restricted in what it can execute by AppArmor, so likely won’t be able to see binaries in non-default locations anyway.
  • LD_LIBRARY_PATH - the same deal as above, but for libraries.
  • XDG_DATA_DIRS - similar for desktop data files. The fact that we add /var/lib/snapd/desktop to this variable is already a source of AppArmor denials.
  • various other XDG base dir environment variables, for similar reasons.
  • GTK_MODULES / GTK2_MODULES - if the listed GTK plugins are not available in the sandbox, then it results in warnings on stderr. With that said, loadable modules are used to enable accessibility in GTK 2 apps, so simply clearing them is not obviously right either.

I’m sure there are other similar cases.

@jamesh @lucyllewy can you think of any situations where if we did start doing this in snapd (i.e. dropping the value of LD_PRELOAD) we would break strict current snaps? I think the issue to me is not so much whether there are other such variables that do leaky things that are most likely unwanted, the issue to me is whether if we emptied those variables if we would end up breaking valid use cases.

I can’t think of any except those that explicitly specify new content for the variable in their yaml, but I would hope that snapd would clear the variable before applying any overrides from the yaml.

Yes that is correct, the value would be cleared in snap-confine, before snap-exec which processes the environment section from the snap.yaml (which is what the snapcraft.yaml gets transformed into).

1 Like

I can’t think of a case where it would likely do something useful.

As far as non-technical users hitting this kind of thing, one case that would trigger the problem is Ubuntu users installing the Unity 7 desktop session. This currently has gtk3-nocsd in the recommends, which sets LD_PRELOAD to an executable that tries to prevent GTK apps from using client side decorations. That’s likely to result in warning messages on stderr every time they start a snap application, since the library won’t be available in the sandbox.

Interestingly, we currently have the following code in snap-confine:

And there’s similar code to set TMPDIR/TEMPDIR. I think you could apply the same logic to these other variables just as easily.

in fact it is not only not useful but even pretty awful on raspiOS where by default /etc/ld.so.preload enforces preloading of libarmmem.so (which cant be found inside the snap env) so you get massive log/cli spam… i’m not sure if just unsetting the var is sufficient to override here though, perhaps that needs more…

I doubt there is anything we can do with the environment to affect /etc/ld.so.preload processing. Maybe bind mounting /dev/null over the top would make sense though?

/etc/ld.so.preload is probably in the same situation as /etc/ld.so.cache in that whatever values the host system have in those files are totally unusable if the strict snap tried to use them. I had a proposal to bind mount a private ld.so.cache for strict snaps, probably bind mounting an empty ld.so.preload file makes sense for the same reasons.

1 Like

I was thinking of applications like VirtualGL, but I guess there’s no way of using it with a Snapped app, unless it’s been packaged inside the Snap and somehow setup to use it.

It looks like that VirtualGL library is at least partially written in C++. So even if the snap application could see the host system’s copy of the library, there’s an open question of whether it would be compatible with the libstdc++ found within the sandbox.

probably bind mounting an empty ld.so.preload file makes sense for the same reasons.

That’s what I ended up doing here just to get rid of the repeated error messages. I was surprised that snapd was even exposing that file to a confined snap. I expected only the files in the core18 base that I’m using to be exposed to the snap, not the /etc/ld.so.preload file on the host.