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 }