diff options
-rw-r--r-- | cmd/podman/main.go | 2 | ||||
-rw-r--r-- | libpod/runtime.go | 28 |
2 files changed, 27 insertions, 3 deletions
diff --git a/cmd/podman/main.go b/cmd/podman/main.go index 0e6a2e600..6b9bda55e 100644 --- a/cmd/podman/main.go +++ b/cmd/podman/main.go @@ -29,6 +29,8 @@ var cmdsNotRequiringRootless = map[string]bool{ "help": true, "version": true, "exec": true, + // `info` must be executed in an user namespace. + // If this change, please also update libpod.refreshRootless() "login": true, "logout": true, "kill": true, diff --git a/libpod/runtime.go b/libpod/runtime.go index 2df4ef760..da5d9fa70 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -4,6 +4,7 @@ import ( "fmt" "io/ioutil" "os" + "os/exec" "path/filepath" "sync" "syscall" @@ -547,7 +548,12 @@ func makeRuntime(runtime *Runtime) (err error) { // TODO: we can't close the FD in this lock, so we should keep it around // and use it to lock important operations aliveLock.Lock() - defer aliveLock.Unlock() + locked := true + defer func() { + if locked { + aliveLock.Unlock() + } + }() _, err = os.Stat(runtimeAliveFile) if err != nil { // If the file doesn't exist, we need to refresh the state @@ -555,8 +561,16 @@ func makeRuntime(runtime *Runtime) (err error) { // empty state only creates a single file // As such, it's not really a performance concern if os.IsNotExist(err) { - if err2 := runtime.refresh(runtimeAliveFile); err2 != nil { - return err2 + if os.Getuid() != 0 { + aliveLock.Unlock() + locked = false + if err2 := runtime.refreshRootless(); err2 != nil { + return err2 + } + } else { + if err2 := runtime.refresh(runtimeAliveFile); err2 != nil { + return err2 + } } } else { return errors.Wrapf(err, "error reading runtime status file %s", runtimeAliveFile) @@ -631,6 +645,14 @@ func (r *Runtime) Shutdown(force bool) error { return lastError } +// Reconfigures the runtime after a reboot for a rootless process +func (r *Runtime) refreshRootless() error { + // Take advantage of a command that requires a new userns + // so that we are running as the root user and able to use refresh() + cmd := exec.Command(os.Args[0], "info") + return cmd.Run() +} + // Reconfigures the runtime after a reboot // Refreshes the state, recreating temporary files // Does not check validity as the runtime is not valid until after this has run |