github.com/Lephar/snapd@v0.0.0-20210825215435-c7fba9cef4d2/snap/snapenv/snapenv.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2014-2015 Canonical Ltd
     5   *
     6   * This program is free software: you can redistribute it and/or modify
     7   * it under the terms of the GNU General Public License version 3 as
     8   * published by the Free Software Foundation.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  package snapenv
    21  
    22  import (
    23  	"os"
    24  	"os/user"
    25  	"path/filepath"
    26  
    27  	"github.com/snapcore/snapd/arch"
    28  	"github.com/snapcore/snapd/dirs"
    29  	"github.com/snapcore/snapd/features"
    30  	"github.com/snapcore/snapd/osutil"
    31  	"github.com/snapcore/snapd/osutil/sys"
    32  	"github.com/snapcore/snapd/snap"
    33  )
    34  
    35  // PreservedUnsafePrefix is used to escape env variables that are
    36  // usually stripped out by ld.so when starting a setuid process, to preserve
    37  // them through snap-confine (for classic confined snaps).
    38  const PreservedUnsafePrefix = "SNAP_SAVED_"
    39  
    40  // ExtendEnvForRun extends the given environment with what is is
    41  // required for snap-{confine,exec}, that means SNAP_{NAME,REVISION}
    42  // etc are all set.
    43  //
    44  // It ensures all SNAP_* override any pre-existing environment
    45  // variables.
    46  func ExtendEnvForRun(env osutil.Environment, info *snap.Info) {
    47  	// Set various SNAP_ environment variables as well as some non-SNAP variables,
    48  	// depending on snap confinement mode. Note that this does not include environment
    49  	// set by snap-exec.
    50  	for k, v := range snapEnv(info) {
    51  		env[k] = v
    52  	}
    53  }
    54  
    55  func snapEnv(info *snap.Info) osutil.Environment {
    56  	// Environment variables with basic properties of a snap.
    57  	env := basicEnv(info)
    58  	if usr, err := user.Current(); err == nil && usr.HomeDir != "" {
    59  		// Environment variables with values specific to the calling user.
    60  		for k, v := range userEnv(info, usr.HomeDir) {
    61  			env[k] = v
    62  		}
    63  	}
    64  	return env
    65  }
    66  
    67  // basicEnv returns the app-level environment variables for a snap.
    68  // Despite this being a bit snap-specific, this is in helpers.go because it's
    69  // used by so many other modules, we run into circular dependencies if it's
    70  // somewhere more reasonable like the snappy module.
    71  func basicEnv(info *snap.Info) osutil.Environment {
    72  	return osutil.Environment{
    73  		// This uses CoreSnapMountDir because the computed environment
    74  		// variables are conveyed to the started application process which
    75  		// shall *either* execute with the new mount namespace where snaps are
    76  		// always mounted on /snap OR it is a classically confined snap where
    77  		// /snap is a part of the distribution package.
    78  		//
    79  		// For parallel-installs the mount namespace setup is making the
    80  		// environment of each snap instance appear as if it's the only
    81  		// snap, i.e. SNAP paths point to the same locations within the
    82  		// mount namespace
    83  		"SNAP":               filepath.Join(dirs.CoreSnapMountDir, info.SnapName(), info.Revision.String()),
    84  		"SNAP_COMMON":        snap.CommonDataDir(info.SnapName()),
    85  		"SNAP_DATA":          snap.DataDir(info.SnapName(), info.Revision),
    86  		"SNAP_NAME":          info.SnapName(),
    87  		"SNAP_INSTANCE_NAME": info.InstanceName(),
    88  		"SNAP_INSTANCE_KEY":  info.InstanceKey,
    89  		"SNAP_VERSION":       info.Version,
    90  		"SNAP_REVISION":      info.Revision.String(),
    91  		"SNAP_ARCH":          arch.DpkgArchitecture(),
    92  		// see https://github.com/snapcore/snapd/pull/2732#pullrequestreview-18827193
    93  		"SNAP_LIBRARY_PATH": "/var/lib/snapd/lib/gl:/var/lib/snapd/lib/gl32:/var/lib/snapd/void",
    94  		"SNAP_REEXEC":       os.Getenv("SNAP_REEXEC"),
    95  	}
    96  }
    97  
    98  // userEnv returns the user-level environment variables for a snap.
    99  // Despite this being a bit snap-specific, this is in helpers.go because it's
   100  // used by so many other modules, we run into circular dependencies if it's
   101  // somewhere more reasonable like the snappy module.
   102  func userEnv(info *snap.Info, home string) osutil.Environment {
   103  	// To keep things simple the user variables always point to the
   104  	// instance-specific directories.
   105  	env := osutil.Environment{
   106  		"SNAP_USER_COMMON": info.UserCommonDataDir(home),
   107  		"SNAP_USER_DATA":   info.UserDataDir(home),
   108  	}
   109  	if info.NeedsClassic() {
   110  		// Snaps using classic confinement don't have an override for
   111  		// HOME but may have an override for XDG_RUNTIME_DIR.
   112  		if !features.ClassicPreservesXdgRuntimeDir.IsEnabled() {
   113  			env["XDG_RUNTIME_DIR"] = info.UserXdgRuntimeDir(sys.Geteuid())
   114  		}
   115  	} else {
   116  		// Snaps using strict or devmode confinement get an override for both
   117  		// HOME and XDG_RUNTIME_DIR.
   118  		env["HOME"] = info.UserDataDir(home)
   119  		env["XDG_RUNTIME_DIR"] = info.UserXdgRuntimeDir(sys.Geteuid())
   120  	}
   121  	// Provide the location of the real home directory.
   122  	env["SNAP_REAL_HOME"] = home
   123  	return env
   124  }