Cleaning the environment for execution in classic snaps

Hey, so a number of times we’ve found ourselves in the need to clean the environment for processes we start from our classic snaps.

miriway-unsnap is one such utility, snap-out is another, wezterm has another example… you catch the drift, I’m sure :slight_smile: .

Could we come up with a snap-wide solution for this? Something along the lines of snapctl env that would print what the environment was before the snap machinery worked its magic, and a snapctl env <arg …> that would execute processes in that environment?

Any other ideas?

1 Like

Interesting as we find outselves doing something similar at times in snapcraft itself. It would be useful to have a clean-room environment for shelling out.

FWIW, this first link is currently broken

1 Like

It should be: https://github.com/Miriway/Miriway/blob/main/miriway-unsnap

1 Like

There’s a few injected variables that could be freely unset. There’s one variable that remembers the old HOME directory and then there’s the slightly clobbered PATH. We could undo all of that at many layers.

@Saviq are you looking for an official way to run something without any snap environment variables that’s shipped by snapd or that’s injected by snapcraft?

Had a quick look at the linked repos. With the exception of SNAP_*, IIRC all other variables are most likely set by some command chain wrapper outside of snapd execution chain. For reference, have a look at https://github.com/snapcore/snapd/blob/f8e260ecca804e197b81f5d8c669f1df690800bc/snap/snapenv/snapenv.go#L59 for snap run .. part, then https://github.com/snapcore/snapd/blob/f8e260ecca804e197b81f5d8c669f1df690800bc/cmd/snap-confine/snap-confine.c#L771 for snap-confine

@zyga, I think there’s more to it than “undoing what snapd did”. Graphical snaps, for instance, may set __EGL_VENDOR_LIBRARY_DIRS, LIBGL_DRIVERS_PATH, LIBINPUT_QUIRKS_DIR. Qt ones, QT_PLUGIN_PATH, QT_QPA_PLATFORM_PLUGIN_PATH, QML2_IMPORT_PATH, and so on.

It is more a matter of “reset to the host activation environment”. But, in the general case, we want to add to that - e.g. by setting additional variables (e.g. Miriway sets DISPLAY, WAYLAND_DISPLAY, XDG_SESSION_TYPE, XDG_CURRENT_DESKTOP and SSH_AUTH_SOCK)

Indeed the changes are done across the layers:

  • snapd/snap-confine/snap-exec
  • snapcraft command chain
  • customization done in application startup scripts

I wonder if the problem we’re trying to solve is could be reframed as application activation. No matter what kind of environment overrides exist, run this app with those args as if the user had just started it from the shell.

Ultimately I’m after the environment snap was executed in (whether through snap run or /snap/bin/*). Maybe the user had a reason to set some variables, so I shouldn’t blindly unset / mangle things. That’s what snap-out does, to some extent, walking the process path up until it finds an ancestor with a snap-free environment. But that’s not the same, either, if things got exec'd in that chain.

That’s a simple way of thinking about it — assuming you mean “from the shell snap was invoked from” — but e.g. the Miriway case would potentially need to know the environment, not just exec.

Really I think an implementation of (parts of) /usr/bin/env, that would inherit the pre-snap environment, would be just about right.

If you want the vanilla environment the that snap-run was started from (or spiced vanilla in case the user had customized something) then there’s no way out other than to teach snap-run to save that environment somewhere. Perhaps in a mangled environment variable itself?

I think some of the environment variables may be preserved by snap run to workaround ld.so dropping them when when execing into a setuid binary. I can’t look at the sources right now but you should be able to find it. Anyways, it’s quite likely that not all of the variables @Saviq is interested in are included in said list.

Possibly, yeah. This way snapctl env could work, as well as any other way the snapped process needed it. Base64-encoded JSON? ¯\_(ツ)_/¯

I can propose a branch and see what happens next.

Just want to add that we need very similar functionality for our alacrity snap.

https://github.com/snapcrafters/alacritty/pull/2

1 Like