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 | 	toolboxPathEnvArg := "TOOLBOX_PATH=" + toolboxPath | ||||||
| 	toolboxPathMountArg := toolboxPath + ":/usr/bin/toolbox:ro" | 	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") | 		xdgRuntimeDir := os.Getenv("XDG_RUNTIME_DIR") | ||||||
| 		xdgRuntimeDirEnvArg := "XDG_RUNTIME_DIR=" + xdgRuntimeDir | 		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'") | 	logrus.Debug("Checking if 'podman create' supports '--mount type=devpts'") | ||||||
| 
 | 
 | ||||||
|  | @ -337,12 +351,16 @@ func createContainer(container, image, release string, showCommandToEnter bool) | ||||||
| 		"create", | 		"create", | ||||||
| 		"--dns", "none", | 		"--dns", "none", | ||||||
| 		"--env", toolboxPathEnvArg, | 		"--env", toolboxPathEnvArg, | ||||||
| 		"--env", xdgRuntimeDirEnvArg, | 	} | ||||||
|  | 
 | ||||||
|  | 	createArgs = append(createArgs, xdgRuntimeDirEnv...) | ||||||
|  | 
 | ||||||
|  | 	createArgs = append(createArgs, []string{ | ||||||
| 		"--hostname", "toolbox", | 		"--hostname", "toolbox", | ||||||
| 		"--ipc", "host", | 		"--ipc", "host", | ||||||
| 		"--label", "com.github.containers.toolbox=true", | 		"--label", "com.github.containers.toolbox=true", | ||||||
| 		"--label", "com.github.debarshiray.toolbox=true", | 		"--label", "com.github.debarshiray.toolbox=true", | ||||||
| 	} | 	}...) | ||||||
| 
 | 
 | ||||||
| 	createArgs = append(createArgs, devPtsMount...) | 	createArgs = append(createArgs, devPtsMount...) | ||||||
| 
 | 
 | ||||||
|  | @ -370,7 +388,7 @@ func createContainer(container, image, release string, showCommandToEnter bool) | ||||||
| 		"--volume", homeDirMountArg, | 		"--volume", homeDirMountArg, | ||||||
| 		"--volume", toolboxPathMountArg, | 		"--volume", toolboxPathMountArg, | ||||||
| 		"--volume", usrMountArg, | 		"--volume", usrMountArg, | ||||||
| 		"--volume", xdgRuntimeDirMountArg, | 		"--volume", runtimeDirectoryMountArg, | ||||||
| 	}...) | 	}...) | ||||||
| 
 | 
 | ||||||
| 	createArgs = append(createArgs, kcmSocketMount...) | 	createArgs = append(createArgs, kcmSocketMount...) | ||||||
|  |  | ||||||
|  | @ -23,6 +23,7 @@ import ( | ||||||
| 	"os" | 	"os" | ||||||
| 	"os/user" | 	"os/user" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
|  | 	"strconv" | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
|  | @ -127,15 +128,7 @@ func initContainer(cmd *cobra.Command, args []string) error { | ||||||
| 		return errors.New(errMsg) | 		return errors.New(errMsg) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	runtimeDirectory := os.Getenv("XDG_RUNTIME_DIR") | 	utils.EnsureXdgRuntimeDirIsSet(initContainerFlags.uid) | ||||||
| 	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) |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	logrus.Debug("Creating /run/.toolboxenv") | 	logrus.Debug("Creating /run/.toolboxenv") | ||||||
| 
 | 
 | ||||||
|  | @ -285,16 +278,15 @@ func initContainer(cmd *cobra.Command, args []string) error { | ||||||
| 
 | 
 | ||||||
| 	logrus.Debug("Finished initializing container") | 	logrus.Debug("Finished initializing container") | ||||||
| 
 | 
 | ||||||
| 	toolboxRuntimeDirectory := runtimeDirectory + "/toolbox" | 	uidString := strconv.Itoa(initContainerFlags.uid) | ||||||
| 	logrus.Debugf("Creating runtime directory %s", toolboxRuntimeDirectory) | 	targetUser, err := user.LookupId(uidString) | ||||||
| 
 | 	if err != nil { | ||||||
| 	if err := os.MkdirAll(toolboxRuntimeDirectory, 0700); err != nil { | 		return fmt.Errorf("failed to lookup user ID %s: %w", uidString, err) | ||||||
| 		return fmt.Errorf("failed to create runtime directory %s", toolboxRuntimeDirectory) |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if err := os.Chown(toolboxRuntimeDirectory, initContainerFlags.uid, initContainerFlags.uid); err != nil { | 	toolboxRuntimeDirectory, err := utils.GetRuntimeDirectory(targetUser) | ||||||
| 		return fmt.Errorf("failed to change ownership of the runtime directory %s", | 	if err != nil { | ||||||
| 			toolboxRuntimeDirectory) | 		return err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	pid := os.Getpid() | 	pid := os.Getpid() | ||||||
|  |  | ||||||
|  | @ -226,10 +226,9 @@ func migrate() error { | ||||||
| 		return fmt.Errorf("failed to create configuration directory") | 		return fmt.Errorf("failed to create configuration directory") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	runtimeDirectory := os.Getenv("XDG_RUNTIME_DIR") | 	toolboxRuntimeDirectory, err := utils.GetRuntimeDirectory(currentUser) | ||||||
| 	toolboxRuntimeDirectory := runtimeDirectory + "/toolbox" | 	if err != nil { | ||||||
| 	if err := os.MkdirAll(toolboxRuntimeDirectory, 0700); err != nil { | 		return err | ||||||
| 		return fmt.Errorf("failed to create runtime directory %s", toolboxRuntimeDirectory) |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	migrateLock := toolboxRuntimeDirectory + "/migrate.lock" | 	migrateLock := toolboxRuntimeDirectory + "/migrate.lock" | ||||||
|  |  | ||||||
|  | @ -238,8 +238,11 @@ func runCommand(container string, | ||||||
| 
 | 
 | ||||||
| 	logrus.Debugf("Waiting for container %s to finish initializing", container) | 	logrus.Debugf("Waiting for container %s to finish initializing", container) | ||||||
| 
 | 
 | ||||||
| 	runtimeDirectory := os.Getenv("XDG_RUNTIME_DIR") | 	toolboxRuntimeDirectory, err := utils.GetRuntimeDirectory(currentUser) | ||||||
| 	toolboxRuntimeDirectory := runtimeDirectory + "/toolbox" | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	initializedStamp := fmt.Sprintf("%s/container-initialized-%d", toolboxRuntimeDirectory, entryPointPID) | 	initializedStamp := fmt.Sprintf("%s/container-initialized-%d", toolboxRuntimeDirectory, entryPointPID) | ||||||
| 
 | 
 | ||||||
| 	logrus.Debugf("Checking if initialization stamp %s exists", initializedStamp) | 	logrus.Debugf("Checking if initialization stamp %s exists", initializedStamp) | ||||||
|  |  | ||||||
|  | @ -22,6 +22,7 @@ import ( | ||||||
| 	"os" | 	"os" | ||||||
| 	"os/exec" | 	"os/exec" | ||||||
| 	"os/user" | 	"os/user" | ||||||
|  | 	"path" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
| 	"regexp" | 	"regexp" | ||||||
| 	"sort" | 	"sort" | ||||||
|  | @ -174,6 +175,17 @@ func CreateErrorInvalidRelease(executableBase string) error { | ||||||
| 	return errors.New(errMsg) | 	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) { | func ForwardToHost() (int, error) { | ||||||
| 	envOptions := GetEnvOptionsForPreservedVariables() | 	envOptions := GetEnvOptionsForPreservedVariables() | ||||||
| 	toolboxPath := os.Getenv("TOOLBOX_PATH") | 	toolboxPath := os.Getenv("TOOLBOX_PATH") | ||||||
|  | @ -336,6 +348,40 @@ func GetMountOptions(target string) (string, error) { | ||||||
| 	return mountOptions, nil | 	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
 | // HumanDuration accepts a Unix time value and converts it into a human readable
 | ||||||
| // string.
 | // string.
 | ||||||
| //
 | //
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue