diff options
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/api/handlers/compat/containers.go | 12 | ||||
-rw-r--r-- | pkg/api/handlers/libpod/info.go | 4 | ||||
-rw-r--r-- | pkg/api/handlers/utils/containers.go | 2 | ||||
-rw-r--r-- | pkg/domain/infra/abi/images.go | 4 | ||||
-rw-r--r-- | pkg/domain/infra/abi/play.go | 4 | ||||
-rw-r--r-- | pkg/domain/infra/abi/system.go | 17 | ||||
-rw-r--r-- | pkg/machine/pull.go | 2 | ||||
-rw-r--r-- | pkg/rootless/rootless_linux.go | 65 | ||||
-rw-r--r-- | pkg/specgen/generate/kube/kube.go | 2 | ||||
-rw-r--r-- | pkg/systemd/generate/common_test.go | 4 | ||||
-rw-r--r-- | pkg/util/filters.go | 2 | ||||
-rw-r--r-- | pkg/util/utils.go | 23 |
12 files changed, 109 insertions, 32 deletions
diff --git a/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go index e7146a5d8..d97a4d3bd 100644 --- a/pkg/api/handlers/compat/containers.go +++ b/pkg/api/handlers/compat/containers.go @@ -26,6 +26,7 @@ import ( "github.com/docker/go-units" "github.com/gorilla/schema" "github.com/pkg/errors" + "github.com/sirupsen/logrus" ) func RemoveContainer(w http.ResponseWriter, r *http.Request) { @@ -148,14 +149,19 @@ func ListContainers(w http.ResponseWriter, r *http.Request) { containers = containers[:query.Limit] } } - var list = make([]*handlers.Container, len(containers)) - for i, ctnr := range containers { + list := make([]*handlers.Container, 0, len(containers)) + for _, ctnr := range containers { api, err := LibpodToContainer(ctnr, query.Size) if err != nil { + if errors.Cause(err) == define.ErrNoSuchCtr { + // container was removed between the initial fetch of the list and conversion + logrus.Debugf("Container %s removed between initial fetch and conversion, ignoring in output", ctnr.ID()) + continue + } utils.InternalServerError(w, err) return } - list[i] = api + list = append(list, api) } utils.WriteResponse(w, http.StatusOK, list) } diff --git a/pkg/api/handlers/libpod/info.go b/pkg/api/handlers/libpod/info.go index 546609451..8868d563d 100644 --- a/pkg/api/handlers/libpod/info.go +++ b/pkg/api/handlers/libpod/info.go @@ -5,11 +5,13 @@ import ( "github.com/containers/podman/v3/libpod" "github.com/containers/podman/v3/pkg/api/handlers/utils" + "github.com/containers/podman/v3/pkg/domain/infra/abi" ) func GetInfo(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value("runtime").(*libpod.Runtime) - info, err := runtime.Info() + containerEngine := abi.ContainerEngine{Libpod: runtime} + info, err := containerEngine.Info(r.Context()) if err != nil { utils.InternalServerError(w, err) return diff --git a/pkg/api/handlers/utils/containers.go b/pkg/api/handlers/utils/containers.go index 91e02abf1..c4c9cc2ea 100644 --- a/pkg/api/handlers/utils/containers.go +++ b/pkg/api/handlers/utils/containers.go @@ -76,7 +76,7 @@ func WaitContainerDocker(w http.ResponseWriter, r *http.Request) { exitCode, err := waitDockerCondition(ctx, name, interval, condition) msg := "" if err != nil { - logrus.Errorf("error while waiting on condtion: %q", err) + logrus.Errorf("error while waiting on condition: %q", err) msg = err.Error() } responseData := handlers.ContainerWaitOKBody{ diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go index c02eb2bfc..84c7ebecd 100644 --- a/pkg/domain/infra/abi/images.go +++ b/pkg/domain/infra/abi/images.go @@ -620,8 +620,8 @@ func (ir *ImageEngine) Remove(ctx context.Context, images []string, opts entitie for _, img := range storageImages { isParent, err := img.IsParent(ctx) if err != nil { - rmErrors = append(rmErrors, err) - continue + logrus.Warnf("%v, ignoring the error", err) + isParent = false } // Skip parent images. if isParent { diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go index 4a13a8029..6ddd4a042 100644 --- a/pkg/domain/infra/abi/play.go +++ b/pkg/domain/infra/abi/play.go @@ -428,7 +428,7 @@ func readConfigMapFromFile(r io.Reader) (v1.ConfigMap, error) { return cm, nil } -// splitMultiDocYAML reads mutiple documents in a YAML file and +// splitMultiDocYAML reads multiple documents in a YAML file and // returns them as a list. func splitMultiDocYAML(yamlContent []byte) ([][]byte, error) { var documentList [][]byte @@ -471,7 +471,7 @@ func getKubeKind(obj []byte) (string, error) { } // sortKubeKinds adds the correct creation order for the kube kinds. -// Any pod dependecy will be created first like volumes, secrets, etc. +// Any pod dependency will be created first like volumes, secrets, etc. func sortKubeKinds(documentList [][]byte) ([][]byte, error) { var sortedDocumentList [][]byte diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go index f87f9e370..9bba0fa6c 100644 --- a/pkg/domain/infra/abi/system.go +++ b/pkg/domain/infra/abi/system.go @@ -21,6 +21,7 @@ import ( "github.com/containers/podman/v3/pkg/util" "github.com/containers/podman/v3/utils" "github.com/containers/storage" + "github.com/containers/storage/pkg/unshare" "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -32,17 +33,11 @@ func (ic *ContainerEngine) Info(ctx context.Context) (*define.Info, error) { if err != nil { return nil, err } - xdg, err := util.GetRuntimeDir() + + socketPath, err := util.SocketPath() if err != nil { return nil, err } - if len(xdg) == 0 { - // If no xdg is returned, assume root socket - xdg = "/run" - } - - // Glue the socket path together - socketPath := filepath.Join(xdg, "podman", "podman.sock") rs := define.RemoteSocket{ Path: socketPath, Exists: false, @@ -64,7 +59,11 @@ func (ic *ContainerEngine) Info(ctx context.Context) (*define.Info, error) { func (ic *ContainerEngine) SetupRootless(_ context.Context, cmd *cobra.Command) error { // do it only after podman has already re-execed and running with uid==0. - if os.Geteuid() == 0 { + hasCapSysAdmin, err := unshare.HasCapSysAdmin() + if err != nil { + return err + } + if hasCapSysAdmin { ownsCgroup, err := cgroups.UserOwnsCurrentSystemdCgroup() if err != nil { logrus.Infof("Failed to detect the owner for the current cgroup: %v", err) diff --git a/pkg/machine/pull.go b/pkg/machine/pull.go index 41abe6993..d9f34057f 100644 --- a/pkg/machine/pull.go +++ b/pkg/machine/pull.go @@ -170,7 +170,7 @@ func Decompress(localPath, uncompressedPath string) error { // Will error out if file without .xz already exists // Maybe extracting then renameing is a good idea here.. -// depends on xz: not pre-installed on mac, so it becomes a brew dependecy +// depends on xz: not pre-installed on mac, so it becomes a brew dependency func decompressXZ(src string, output io.Writer) error { fmt.Println("Extracting compressed file") cmd := exec.Command("xzcat", "-k", src) diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go index dda230dbc..fdfeed854 100644 --- a/pkg/rootless/rootless_linux.go +++ b/pkg/rootless/rootless_linux.go @@ -4,6 +4,7 @@ package rootless import ( "bufio" + "bytes" "fmt" "io" "io/ioutil" @@ -18,6 +19,7 @@ import ( "github.com/containers/podman/v3/pkg/errorhandling" "github.com/containers/storage/pkg/idtools" + "github.com/containers/storage/pkg/unshare" "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/sys/unix" @@ -67,6 +69,15 @@ func IsRootless() bool { } } isRootless = os.Geteuid() != 0 || os.Getenv("_CONTAINERS_USERNS_CONFIGURED") != "" + if !isRootless { + hasCapSysAdmin, err := unshare.HasCapSysAdmin() + if err != nil { + logrus.Warnf("failed to read CAP_SYS_ADMIN presence for the current process") + } + if err == nil && !hasCapSysAdmin { + isRootless = true + } + } }) return isRootless } @@ -142,8 +153,12 @@ func tryMappingTool(uid bool, pid int, hostID int, mappings []idtools.IDMap) err // namespace of the specified PID without looking up its parent. Useful to join directly // the conmon process. func joinUserAndMountNS(pid uint, pausePid string) (bool, int, error) { - if os.Geteuid() == 0 || os.Getenv("_CONTAINERS_USERNS_CONFIGURED") != "" { - return false, -1, nil + hasCapSysAdmin, err := unshare.HasCapSysAdmin() + if err != nil { + return false, 0, err + } + if hasCapSysAdmin || os.Getenv("_CONTAINERS_USERNS_CONFIGURED") != "" { + return false, 0, nil } cPausePid := C.CString(pausePid) @@ -180,8 +195,11 @@ func GetConfiguredMappings() ([]idtools.IDMap, []idtools.IDMap, error) { } mappings, err := idtools.NewIDMappings(username, username) if err != nil { - logrus.Errorf( - "cannot find UID/GID for user %s: %v - check rootless mode in man pages.", username, err) + logLevel := logrus.ErrorLevel + if os.Geteuid() == 0 && GetRootlessUID() == 0 { + logLevel = logrus.DebugLevel + } + logrus.StandardLogger().Logf(logLevel, "cannot find UID/GID for user %s: %v - check rootless mode in man pages.", username, err) } else { uids = mappings.UIDs() gids = mappings.GIDs() @@ -189,8 +207,28 @@ func GetConfiguredMappings() ([]idtools.IDMap, []idtools.IDMap, error) { return uids, gids, nil } +func copyMappings(from, to string) error { + content, err := ioutil.ReadFile(from) + if err != nil { + return err + } + // Both runc and crun check whether the current process is in a user namespace + // by looking up 4294967295 in /proc/self/uid_map. If the mappings would be + // copied as they are, the check in the OCI runtimes would fail. So just split + // it in two different ranges. + if bytes.Contains(content, []byte("4294967295")) { + content = []byte("0 0 1\n1 1 4294967294\n") + } + return ioutil.WriteFile(to, content, 0600) +} + func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (_ bool, _ int, retErr error) { - if os.Geteuid() == 0 || os.Getenv("_CONTAINERS_USERNS_CONFIGURED") != "" { + hasCapSysAdmin, err := unshare.HasCapSysAdmin() + if err != nil { + return false, 0, err + } + + if hasCapSysAdmin || os.Getenv("_CONTAINERS_USERNS_CONFIGURED") != "" { if os.Getenv("_CONTAINERS_USERNS_CONFIGURED") == "init" { return false, 0, runInUser() } @@ -247,8 +285,16 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (_ boo return false, -1, err } + uidMap := fmt.Sprintf("/proc/%d/uid_map", pid) + gidMap := fmt.Sprintf("/proc/%d/gid_map", pid) + uidsMapped := false - if uids != nil { + + if err := copyMappings("/proc/self/uid_map", uidMap); err == nil { + uidsMapped = true + } + + if uids != nil && !uidsMapped { err := tryMappingTool(true, pid, os.Geteuid(), uids) // If some mappings were specified, do not ignore the error if err != nil && len(uids) > 0 { @@ -265,7 +311,6 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (_ boo } logrus.Debugf("write setgroups file exited with 0") - uidMap := fmt.Sprintf("/proc/%d/uid_map", pid) err = ioutil.WriteFile(uidMap, []byte(fmt.Sprintf("%d %d 1\n", 0, os.Geteuid())), 0666) if err != nil { return false, -1, errors.Wrapf(err, "cannot write uid_map") @@ -274,7 +319,10 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (_ boo } gidsMapped := false - if gids != nil { + if err := copyMappings("/proc/self/gid_map", gidMap); err == nil { + gidsMapped = true + } + if gids != nil && !gidsMapped { err := tryMappingTool(false, pid, os.Getegid(), gids) // If some mappings were specified, do not ignore the error if err != nil && len(gids) > 0 { @@ -283,7 +331,6 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (_ boo gidsMapped = err == nil } if !gidsMapped { - gidMap := fmt.Sprintf("/proc/%d/gid_map", pid) err = ioutil.WriteFile(gidMap, []byte(fmt.Sprintf("%d %d 1\n", 0, os.Getegid())), 0666) if err != nil { return false, -1, errors.Wrapf(err, "cannot write gid_map") diff --git a/pkg/specgen/generate/kube/kube.go b/pkg/specgen/generate/kube/kube.go index 7aeec9d41..1347ed1e0 100644 --- a/pkg/specgen/generate/kube/kube.go +++ b/pkg/specgen/generate/kube/kube.go @@ -56,7 +56,7 @@ func ToPodGen(ctx context.Context, podName string, podYAML *v1.PodTemplateSpec) } p.DNSServer = servers } - // search domans + // search domains if domains := dnsConfig.Searches; len(domains) > 0 { p.DNSSearch = domains } diff --git a/pkg/systemd/generate/common_test.go b/pkg/systemd/generate/common_test.go index 30e758127..fdcc9d21b 100644 --- a/pkg/systemd/generate/common_test.go +++ b/pkg/systemd/generate/common_test.go @@ -199,8 +199,8 @@ func TestEscapeSystemdArguments(t *testing.T) { []string{"foo", `"command with backslash \\"`}, }, { - []string{"foo", `command with two backslashs \\`}, - []string{"foo", `"command with two backslashs \\\\"`}, + []string{"foo", `command with two backslashes \\`}, + []string{"foo", `"command with two backslashes \\\\"`}, }, } diff --git a/pkg/util/filters.go b/pkg/util/filters.go index 43bf646f1..e252c1ddf 100644 --- a/pkg/util/filters.go +++ b/pkg/util/filters.go @@ -94,7 +94,7 @@ func PrepareFilters(r *http.Request) (*map[string][]string, error) { return &filterMap, nil } -// MatchLabelFilters matches labels and returs true if they are valid +// MatchLabelFilters matches labels and returns true if they are valid func MatchLabelFilters(filterValues []string, labels map[string]string) bool { outer: for _, filterValue := range filterValues { diff --git a/pkg/util/utils.go b/pkg/util/utils.go index bbaf72981..622fbde99 100644 --- a/pkg/util/utils.go +++ b/pkg/util/utils.go @@ -706,3 +706,26 @@ func IDtoolsToRuntimeSpec(idMaps []idtools.IDMap) (convertedIDMap []specs.LinuxI } return convertedIDMap } + +var socketPath string + +func SetSocketPath(path string) { + socketPath = path +} + +func SocketPath() (string, error) { + if socketPath != "" { + return socketPath, nil + } + xdg, err := GetRuntimeDir() + if err != nil { + return "", err + } + if len(xdg) == 0 { + // If no xdg is returned, assume root socket + xdg = "/run" + } + + // Glue the socket path together + return filepath.Join(xdg, "podman", "podman.sock"), nil +} |