Don't rely on XDG_RUNTIME_DIR when running as root
This is one more step towards enabling toolbox(1) to be run as root. When invoked as 'sudo toolbox' there's no XDG_RUNTIME_DIR available for the root user. Neither the environment variable nor the directory are present. XDG_RUNTIME_DIR is used for two reasons. First, to place the 'lock' file to synchronize Podman migrations and the initialization stamp file to synchronize the container's entry point with the user-facing 'enter' command running on the host. Second, it's used to propagate things like the user D-Bus, Pipewire and Wayland sockets. The first use-case is important for toolbox(1) itself to work. When running as root, XDG_RUNTIME_DIR is replaced with /run/toolbox for this purpose. The second use-case is mostly ignored because sudo(8) doesn't create a full-fledged user session. Graphical applications can still work by connecting to a X11 server over the local abstract socket or the file system socket in /tmp/.X11-unix. https://github.com/containers/toolbox/issues/267
This commit is contained in:
		
							parent
							
								
									de2101464c
								
							
						
					
					
						commit
						25b647d635
					
				|  | @ -191,9 +191,23 @@ func createContainer(container, image, release string, showCommandToEnter bool) | |||
| 	toolboxPathEnvArg := "TOOLBOX_PATH=" + toolboxPath | ||||
| 	toolboxPathMountArg := toolboxPath + ":/usr/bin/toolbox:ro" | ||||
| 
 | ||||
| 	var runtimeDirectory string | ||||
| 	var xdgRuntimeDirEnv []string | ||||
| 
 | ||||
| 	if currentUser.Uid == "0" { | ||||
| 		runtimeDirectory, err = utils.GetRuntimeDirectory(currentUser) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} else { | ||||
| 		xdgRuntimeDir := os.Getenv("XDG_RUNTIME_DIR") | ||||
| 		xdgRuntimeDirEnvArg := "XDG_RUNTIME_DIR=" + xdgRuntimeDir | ||||
| 	xdgRuntimeDirMountArg := xdgRuntimeDir + ":" + xdgRuntimeDir | ||||
| 		xdgRuntimeDirEnv = []string{"--env", xdgRuntimeDirEnvArg} | ||||
| 
 | ||||
| 		runtimeDirectory = xdgRuntimeDir | ||||
| 	} | ||||
| 
 | ||||
| 	runtimeDirectoryMountArg := runtimeDirectory + ":" + runtimeDirectory | ||||
| 
 | ||||
| 	logrus.Debug("Checking if 'podman create' supports '--mount type=devpts'") | ||||
| 
 | ||||
|  | @ -337,12 +351,16 @@ func createContainer(container, image, release string, showCommandToEnter bool) | |||
| 		"create", | ||||
| 		"--dns", "none", | ||||
| 		"--env", toolboxPathEnvArg, | ||||
| 		"--env", xdgRuntimeDirEnvArg, | ||||
| 	} | ||||
| 
 | ||||
| 	createArgs = append(createArgs, xdgRuntimeDirEnv...) | ||||
| 
 | ||||
| 	createArgs = append(createArgs, []string{ | ||||
| 		"--hostname", "toolbox", | ||||
| 		"--ipc", "host", | ||||
| 		"--label", "com.github.containers.toolbox=true", | ||||
| 		"--label", "com.github.debarshiray.toolbox=true", | ||||
| 	} | ||||
| 	}...) | ||||
| 
 | ||||
| 	createArgs = append(createArgs, devPtsMount...) | ||||
| 
 | ||||
|  | @ -370,7 +388,7 @@ func createContainer(container, image, release string, showCommandToEnter bool) | |||
| 		"--volume", homeDirMountArg, | ||||
| 		"--volume", toolboxPathMountArg, | ||||
| 		"--volume", usrMountArg, | ||||
| 		"--volume", xdgRuntimeDirMountArg, | ||||
| 		"--volume", runtimeDirectoryMountArg, | ||||
| 	}...) | ||||
| 
 | ||||
| 	createArgs = append(createArgs, kcmSocketMount...) | ||||
|  |  | |||
|  | @ -23,6 +23,7 @@ import ( | |||
| 	"os" | ||||
| 	"os/user" | ||||
| 	"path/filepath" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| 
 | ||||
|  | @ -127,15 +128,7 @@ func initContainer(cmd *cobra.Command, args []string) error { | |||
| 		return errors.New(errMsg) | ||||
| 	} | ||||
| 
 | ||||
| 	runtimeDirectory := os.Getenv("XDG_RUNTIME_DIR") | ||||
| 	if runtimeDirectory == "" { | ||||
| 		logrus.Debug("XDG_RUNTIME_DIR is unset") | ||||
| 
 | ||||
| 		runtimeDirectory = fmt.Sprintf("/run/user/%d", initContainerFlags.uid) | ||||
| 		os.Setenv("XDG_RUNTIME_DIR", runtimeDirectory) | ||||
| 
 | ||||
| 		logrus.Debugf("XDG_RUNTIME_DIR set to %s", runtimeDirectory) | ||||
| 	} | ||||
| 	utils.EnsureXdgRuntimeDirIsSet(initContainerFlags.uid) | ||||
| 
 | ||||
| 	logrus.Debug("Creating /run/.toolboxenv") | ||||
| 
 | ||||
|  | @ -285,16 +278,15 @@ func initContainer(cmd *cobra.Command, args []string) error { | |||
| 
 | ||||
| 	logrus.Debug("Finished initializing container") | ||||
| 
 | ||||
| 	toolboxRuntimeDirectory := runtimeDirectory + "/toolbox" | ||||
| 	logrus.Debugf("Creating runtime directory %s", toolboxRuntimeDirectory) | ||||
| 
 | ||||
| 	if err := os.MkdirAll(toolboxRuntimeDirectory, 0700); err != nil { | ||||
| 		return fmt.Errorf("failed to create runtime directory %s", toolboxRuntimeDirectory) | ||||
| 	uidString := strconv.Itoa(initContainerFlags.uid) | ||||
| 	targetUser, err := user.LookupId(uidString) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("failed to lookup user ID %s: %w", uidString, err) | ||||
| 	} | ||||
| 
 | ||||
| 	if err := os.Chown(toolboxRuntimeDirectory, initContainerFlags.uid, initContainerFlags.uid); err != nil { | ||||
| 		return fmt.Errorf("failed to change ownership of the runtime directory %s", | ||||
| 			toolboxRuntimeDirectory) | ||||
| 	toolboxRuntimeDirectory, err := utils.GetRuntimeDirectory(targetUser) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	pid := os.Getpid() | ||||
|  |  | |||
|  | @ -226,10 +226,9 @@ func migrate() error { | |||
| 		return fmt.Errorf("failed to create configuration directory") | ||||
| 	} | ||||
| 
 | ||||
| 	runtimeDirectory := os.Getenv("XDG_RUNTIME_DIR") | ||||
| 	toolboxRuntimeDirectory := runtimeDirectory + "/toolbox" | ||||
| 	if err := os.MkdirAll(toolboxRuntimeDirectory, 0700); err != nil { | ||||
| 		return fmt.Errorf("failed to create runtime directory %s", toolboxRuntimeDirectory) | ||||
| 	toolboxRuntimeDirectory, err := utils.GetRuntimeDirectory(currentUser) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	migrateLock := toolboxRuntimeDirectory + "/migrate.lock" | ||||
|  |  | |||
|  | @ -238,8 +238,11 @@ func runCommand(container string, | |||
| 
 | ||||
| 	logrus.Debugf("Waiting for container %s to finish initializing", container) | ||||
| 
 | ||||
| 	runtimeDirectory := os.Getenv("XDG_RUNTIME_DIR") | ||||
| 	toolboxRuntimeDirectory := runtimeDirectory + "/toolbox" | ||||
| 	toolboxRuntimeDirectory, err := utils.GetRuntimeDirectory(currentUser) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	initializedStamp := fmt.Sprintf("%s/container-initialized-%d", toolboxRuntimeDirectory, entryPointPID) | ||||
| 
 | ||||
| 	logrus.Debugf("Checking if initialization stamp %s exists", initializedStamp) | ||||
|  |  | |||
|  | @ -22,6 +22,7 @@ import ( | |||
| 	"os" | ||||
| 	"os/exec" | ||||
| 	"os/user" | ||||
| 	"path" | ||||
| 	"path/filepath" | ||||
| 	"regexp" | ||||
| 	"sort" | ||||
|  | @ -174,6 +175,17 @@ func CreateErrorInvalidRelease(executableBase string) error { | |||
| 	return errors.New(errMsg) | ||||
| } | ||||
| 
 | ||||
| func EnsureXdgRuntimeDirIsSet(uid int) { | ||||
| 	if xdgRuntimeDir, ok := os.LookupEnv("XDG_RUNTIME_DIR"); !ok { | ||||
| 		logrus.Debug("XDG_RUNTIME_DIR is unset") | ||||
| 
 | ||||
| 		xdgRuntimeDir = fmt.Sprintf("/run/user/%d", uid) | ||||
| 		os.Setenv("XDG_RUNTIME_DIR", xdgRuntimeDir) | ||||
| 
 | ||||
| 		logrus.Debugf("XDG_RUNTIME_DIR set to %s", xdgRuntimeDir) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func ForwardToHost() (int, error) { | ||||
| 	envOptions := GetEnvOptionsForPreservedVariables() | ||||
| 	toolboxPath := os.Getenv("TOOLBOX_PATH") | ||||
|  | @ -336,6 +348,40 @@ func GetMountOptions(target string) (string, error) { | |||
| 	return mountOptions, nil | ||||
| } | ||||
| 
 | ||||
| func GetRuntimeDirectory(targetUser *user.User) (string, error) { | ||||
| 	uid, err := strconv.Atoi(targetUser.Uid) | ||||
| 	if err != nil { | ||||
| 		return "", fmt.Errorf("failed to convert user ID to integer: %w", err) | ||||
| 	} | ||||
| 
 | ||||
| 	var runtimeDirectory string | ||||
| 
 | ||||
| 	if uid == 0 { | ||||
| 		runtimeDirectory = "/run" | ||||
| 	} else { | ||||
| 		runtimeDirectory = os.Getenv("XDG_RUNTIME_DIR") | ||||
| 	} | ||||
| 
 | ||||
| 	toolboxRuntimeDirectory := path.Join(runtimeDirectory, "toolbox") | ||||
| 	logrus.Debugf("Creating runtime directory %s", toolboxRuntimeDirectory) | ||||
| 
 | ||||
| 	if err := os.MkdirAll(toolboxRuntimeDirectory, 0700); err != nil { | ||||
| 		wrapped_err := fmt.Errorf("failed to create runtime directory %s: %w", | ||||
| 			toolboxRuntimeDirectory, | ||||
| 			err) | ||||
| 		return "", wrapped_err | ||||
| 	} | ||||
| 
 | ||||
| 	if err := os.Chown(toolboxRuntimeDirectory, uid, uid); err != nil { | ||||
| 		wrapped_err := fmt.Errorf("failed to change ownership of the runtime directory %s: %w", | ||||
| 			toolboxRuntimeDirectory, | ||||
| 			err) | ||||
| 		return "", wrapped_err | ||||
| 	} | ||||
| 
 | ||||
| 	return toolboxRuntimeDirectory, nil | ||||
| } | ||||
| 
 | ||||
| // HumanDuration accepts a Unix time value and converts it into a human readable
 | ||||
| // string.
 | ||||
| //
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue