diff --git a/cmd/skopeo/unshare.go b/cmd/skopeo/unshare.go index ce1aa1a6..1e9a391d 100644 --- a/cmd/skopeo/unshare.go +++ b/cmd/skopeo/unshare.go @@ -2,5 +2,6 @@ package main -func maybeReexec() { +func maybeReexec() error { + return nil } diff --git a/cmd/skopeo/unshare_linux.go b/cmd/skopeo/unshare_linux.go index bffa4fe3..f9291c0c 100644 --- a/cmd/skopeo/unshare_linux.go +++ b/cmd/skopeo/unshare_linux.go @@ -1,7 +1,34 @@ package main -import "github.com/containers/buildah/pkg/unshare" +import ( + "github.com/containers/buildah/pkg/unshare" + "github.com/pkg/errors" + "github.com/syndtr/gocapability/capability" +) -func maybeReexec() { - unshare.MaybeReexecUsingUserNamespace(false) +var neededCapabilities = []capability.Cap{ + capability.CAP_CHOWN, + capability.CAP_DAC_OVERRIDE, + capability.CAP_FOWNER, + capability.CAP_FSETID, + capability.CAP_MKNOD, + capability.CAP_SETFCAP, +} + +func maybeReexec() error { + // With Skopeo we need only the subset of the root capabilities necessary + // for pulling an image to the storage. Do not attempt to create a namespace + // if we already have the capabilities we need. + capabilities, err := capability.NewPid(0) + if err != nil { + return errors.Wrapf(err, "error reading the current capabilities sets") + } + for _, cap := range neededCapabilities { + if !capabilities.Get(capability.EFFECTIVE, cap) { + // We miss a capability we need, create a user namespaces + unshare.MaybeReexecUsingUserNamespace(true) + return nil + } + } + return nil } diff --git a/cmd/skopeo/utils.go b/cmd/skopeo/utils.go index 85e8b5d2..fb97e440 100644 --- a/cmd/skopeo/utils.go +++ b/cmd/skopeo/utils.go @@ -17,8 +17,7 @@ type errorShouldDisplayUsage struct { } func needsRexec(c *cli.Context) error { - maybeReexec() - return nil + return maybeReexec() } // commandAction intermediates between the cli.ActionFunc interface and the real handler,