summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml4
-rw-r--r--cmd/podman/main_local.go10
-rw-r--r--contrib/cirrus/git_authors_to_irc_nicks.csv4
-rwxr-xr-xcontrib/cirrus/success.sh7
-rwxr-xr-xcontrib/imgprune/entrypoint.sh14
-rw-r--r--pkg/rootless/rootless_linux.go139
-rw-r--r--pkg/rootless/rootless_unsupported.go12
-rw-r--r--pkg/util/utils.go16
8 files changed, 163 insertions, 43 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index 59f1b5e01..d41828d5d 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -300,11 +300,9 @@ image_prune_task:
memory: 1
env:
- # order is significant, Cirrus not always overriding alias values as intended
+ <<: *meta_env_vars
GCPJSON: ENCRYPTED[4c11d8e09c904c30fc70eecb95c73dec0ddf19976f9b981a0f80f3f6599e8f990bcef93c253ac0277f200850d98528e7]
GCPNAME: ENCRYPTED[7f54557ba6e5a437f11283a53e71baec9ca546f48a9835538cc54d297f79968eb1337d4596a1025b14f9d1c5723fbd29]
- GCPPROJECT: ENCRYPTED[7c80e728e046b1c76147afd156a32c1c57d4a1ac1eab93b7e68e718c61ca8564fc61fef815952b8ae0a64e7034b8fe4f]
- <<: *meta_env_vars
timeout_in: 10m
diff --git a/cmd/podman/main_local.go b/cmd/podman/main_local.go
index 648dc166e..0feba609b 100644
--- a/cmd/podman/main_local.go
+++ b/cmd/podman/main_local.go
@@ -120,6 +120,14 @@ func profileOff(cmd *cobra.Command) error {
}
func setupRootless(cmd *cobra.Command, args []string) error {
+ matches, err := rootless.ConfigurationMatches()
+ if err != nil {
+ return err
+ }
+ if !matches {
+ logrus.Warningf("the current user namespace doesn't match the configuration in /etc/subuid or /etc/subgid")
+ logrus.Warningf("you can use `%s system migrate` to recreate the user namespace and restart the containers", os.Args[0])
+ }
if os.Geteuid() == 0 || cmd == _searchCommand || cmd == _versionCommand || cmd == _mountCommand || cmd == _migrateCommand || strings.HasPrefix(cmd.Use, "help") {
return nil
}
@@ -140,7 +148,7 @@ func setupRootless(cmd *cobra.Command, args []string) error {
became, ret, err := rootless.TryJoinFromFilePaths("", false, []string{pausePidPath})
if err != nil {
logrus.Errorf("cannot join pause process. You may need to remove %s and stop all containers", pausePidPath)
- logrus.Errorf("you can use `%s system migrate` to recreate the pause process", os.Args[0])
+ logrus.Errorf("you can use `%s system migrate` to recreate the pause process and restart the containers", os.Args[0])
logrus.Errorf(err.Error())
os.Exit(1)
}
diff --git a/contrib/cirrus/git_authors_to_irc_nicks.csv b/contrib/cirrus/git_authors_to_irc_nicks.csv
index 4334b5cd2..a584cc76a 100644
--- a/contrib/cirrus/git_authors_to_irc_nicks.csv
+++ b/contrib/cirrus/git_authors_to_irc_nicks.csv
@@ -3,6 +3,10 @@
# Sorting is done at runtime - first-found e-mail match wins.
# Comments (like this) and blank lines are ignored.
+bbaude@redhat.com,baude
+matthew.heon@pm.me,mheon
+matthew.heon@gmail.com,mheon
+emilien@redhat.com,EmilienM
rothberg@redhat.com,vrothberg
santiago@redhat.com,edsantiago
gscrivan@redhat.com,giuseppe
diff --git a/contrib/cirrus/success.sh b/contrib/cirrus/success.sh
index f2c9fbc7f..30d375d95 100755
--- a/contrib/cirrus/success.sh
+++ b/contrib/cirrus/success.sh
@@ -4,12 +4,14 @@ set -e
source $(dirname $0)/lib.sh
-req_env_var CIRRUS_BRANCH CIRRUS_BUILD_ID CIRRUS_REPO_FULL_NAME
+req_env_var CIRRUS_BRANCH CIRRUS_BUILD_ID CIRRUS_REPO_FULL_NAME CIRRUS_BASE_SHA CIRRUS_CHANGE_IN_REPO
cd $CIRRUS_WORKING_DIR
if [[ "$CIRRUS_BRANCH" =~ "pull" ]]
then
+ echo "Retrieving latest HEADS and tags"
+ git fetch --all --tags
echo "Finding commit authors for PR $CIRRUS_PR"
unset NICKS
if [[ -r "$AUTHOR_NICKS_FILEPATH" ]]
@@ -20,7 +22,8 @@ then
# Depending on branch-state, it's possible SHARANGE could be _WAY_ too big
MAX_NICKS=10
# newline separated
- COMMIT_AUTHORS=$(git log --format='%ae' $SHARANGE | \
+ GITLOG="git log --format='%ae'"
+ COMMIT_AUTHORS=$($GITLOGt $SHARANGE || $GITLOG -1 HEAD | \
sort -u | \
egrep -v "$EXCLUDE_RE" | \
tail -$MAX_NICKS)
diff --git a/contrib/imgprune/entrypoint.sh b/contrib/imgprune/entrypoint.sh
index 829e9938e..b0f006332 100755
--- a/contrib/imgprune/entrypoint.sh
+++ b/contrib/imgprune/entrypoint.sh
@@ -6,13 +6,17 @@ source /usr/local/bin/lib_entrypoint.sh
req_env_var GCPJSON GCPNAME GCPPROJECT IMGNAMES
-BASE_IMAGES=""
-# When executing under Cirrus-CI, have access to current source
-if [[ "$CI" == "true" ]] && [[ -r "$CIRRUS_WORKING_DIR/$SCRIPT_BASE" ]]
+unset BASE_IMAGES
+# When executing under Cirrus-CI, script have access to current source
+LIB="$CIRRUS_WORKING_DIR/$SCRIPT_BASE/lib.sh"
+if [[ "$CI" == "true" ]] && [[ -r "$LIB" ]]
then
# Avoid importing anything that might conflict
- eval "$(egrep -sh '^export .+BASE_IMAGE=' < $CIRRUS_WORKING_DIR/$SCRIPT_BASE/lib.sh)"
- BASE_IMAGES="$UBUNTU_BASE_IMAGE $PRIOR_UBUNTU_BASE_IMAGE $FEDORA_BASE_IMAGE $PRIOR_FEDORA_BASE_IMAGE"
+ for env in $(sed -ne 's/^[^#]\+_BASE_IMAGE=/img=/p' "$LIB")
+ do
+ eval $env
+ BASE_IMAGES="$BASE_IMAGES $img"
+ done
else
# metadata labeling may have broken for some reason in the future
echo "Warning: Running outside of Cirrus-CI, very minor-risk of base-image deletion."
diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go
index 6e48988c5..ecb84f6a9 100644
--- a/pkg/rootless/rootless_linux.go
+++ b/pkg/rootless/rootless_linux.go
@@ -3,7 +3,9 @@
package rootless
import (
+ "bufio"
"fmt"
+ "io"
"io/ioutil"
"os"
"os/exec"
@@ -106,7 +108,7 @@ func tryMappingTool(tool string, pid int, hostID int, mappings []idtools.IDMap)
}
appendTriplet := func(l []string, a, b, c int) []string {
- return append(l, fmt.Sprintf("%d", a), fmt.Sprintf("%d", b), fmt.Sprintf("%d", c))
+ return append(l, strconv.Itoa(a), strconv.Itoa(b), strconv.Itoa(c))
}
args := []string{path, fmt.Sprintf("%d", pid)}
@@ -345,6 +347,32 @@ func joinUserAndMountNS(pid uint, pausePid string) (bool, int, error) {
return true, int(ret), nil
}
+// GetConfiguredMappings returns the additional IDs configured for the current user.
+func GetConfiguredMappings() ([]idtools.IDMap, []idtools.IDMap, error) {
+ var uids, gids []idtools.IDMap
+ username := os.Getenv("USER")
+ if username == "" {
+ var id string
+ if os.Geteuid() == 0 {
+ id = strconv.Itoa(GetRootlessUID())
+ } else {
+ id = strconv.Itoa(os.Geteuid())
+ }
+ userID, err := user.LookupId(id)
+ if err == nil {
+ username = userID.Username
+ }
+ }
+ mappings, err := idtools.NewIDMappings(username, username)
+ if err != nil {
+ logrus.Warnf("cannot find mappings for user %s: %v", username, err)
+ } else {
+ uids = mappings.UIDs()
+ gids = mappings.GIDs()
+ }
+ return uids, gids, nil
+}
+
func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (bool, int, error) {
if os.Geteuid() == 0 || os.Getenv("_CONTAINERS_USERNS_CONFIGURED") != "" {
if os.Getenv("_CONTAINERS_USERNS_CONFIGURED") == "init" {
@@ -386,25 +414,14 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (bool,
return false, -1, errors.Errorf("cannot re-exec process")
}
- var uids, gids []idtools.IDMap
- username := os.Getenv("USER")
- if username == "" {
- userID, err := user.LookupId(fmt.Sprintf("%d", os.Getuid()))
- if err == nil {
- username = userID.Username
- }
- }
- mappings, err := idtools.NewIDMappings(username, username)
+ uids, gids, err := GetConfiguredMappings()
if err != nil {
- logrus.Warnf("cannot find mappings for user %s: %v", username, err)
- } else {
- uids = mappings.UIDs()
- gids = mappings.GIDs()
+ return false, -1, err
}
uidsMapped := false
- if mappings != nil && uids != nil {
- err := tryMappingTool("newuidmap", pid, os.Getuid(), uids)
+ if uids != nil {
+ err := tryMappingTool("newuidmap", pid, os.Geteuid(), uids)
uidsMapped = err == nil
}
if !uidsMapped {
@@ -416,20 +433,20 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (bool,
}
uidMap := fmt.Sprintf("/proc/%d/uid_map", pid)
- err = ioutil.WriteFile(uidMap, []byte(fmt.Sprintf("%d %d 1\n", 0, os.Getuid())), 0666)
+ 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")
}
}
gidsMapped := false
- if mappings != nil && gids != nil {
- err := tryMappingTool("newgidmap", pid, os.Getgid(), gids)
+ if gids != nil {
+ err := tryMappingTool("newgidmap", pid, os.Getegid(), gids)
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.Getgid())), 0666)
+ 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")
}
@@ -586,3 +603,85 @@ func TryJoinFromFilePaths(pausePidPath string, needNewNamespace bool, paths []st
return joinUserAndMountNS(uint(pausePid), pausePidPath)
}
+func readMappingsProc(path string) ([]idtools.IDMap, error) {
+ file, err := os.Open(path)
+ if err != nil {
+ return nil, errors.Wrapf(err, "cannot open %s", path)
+ }
+ defer file.Close()
+
+ mappings := []idtools.IDMap{}
+
+ buf := bufio.NewReader(file)
+ for {
+ line, _, err := buf.ReadLine()
+ if err != nil {
+ if err == io.EOF {
+ return mappings, nil
+ }
+ return nil, errors.Wrapf(err, "cannot read line from %s", path)
+ }
+ if line == nil {
+ return mappings, nil
+ }
+
+ containerID, hostID, size := 0, 0, 0
+ if _, err := fmt.Sscanf(string(line), "%d %d %d", &containerID, &hostID, &size); err != nil {
+ return nil, errors.Wrapf(err, "cannot parse %s", string(line))
+ }
+ mappings = append(mappings, idtools.IDMap{ContainerID: containerID, HostID: hostID, Size: size})
+ }
+}
+
+func matches(id int, configuredIDs []idtools.IDMap, currentIDs []idtools.IDMap) bool {
+ // The first mapping is the host user, handle it separately.
+ if currentIDs[0].HostID != id || currentIDs[0].Size != 1 {
+ return false
+ }
+
+ currentIDs = currentIDs[1:]
+ if len(currentIDs) != len(configuredIDs) {
+ return false
+ }
+
+ // It is fine to iterate sequentially as both slices are sorted.
+ for i := range currentIDs {
+ if currentIDs[i].HostID != configuredIDs[i].HostID {
+ return false
+ }
+ if currentIDs[i].Size != configuredIDs[i].Size {
+ return false
+ }
+ }
+
+ return true
+}
+
+// ConfigurationMatches checks whether the additional uids/gids configured for the user
+// match the current user namespace.
+func ConfigurationMatches() (bool, error) {
+ if !IsRootless() || os.Geteuid() != 0 {
+ return true, nil
+ }
+
+ uids, gids, err := GetConfiguredMappings()
+ if err != nil {
+ return false, err
+ }
+
+ currentUIDs, err := readMappingsProc("/proc/self/uid_map")
+ if err != nil {
+ return false, err
+ }
+
+ if !matches(GetRootlessUID(), uids, currentUIDs) {
+ return false, err
+ }
+
+ currentGIDs, err := readMappingsProc("/proc/self/gid_map")
+ if err != nil {
+ return false, err
+ }
+
+ return matches(GetRootlessGID(), gids, currentGIDs), nil
+}
diff --git a/pkg/rootless/rootless_unsupported.go b/pkg/rootless/rootless_unsupported.go
index a8485c083..ddd9182b0 100644
--- a/pkg/rootless/rootless_unsupported.go
+++ b/pkg/rootless/rootless_unsupported.go
@@ -5,6 +5,7 @@ package rootless
import (
"os"
+ "github.com/containers/storage/pkg/idtools"
"github.com/pkg/errors"
)
@@ -53,3 +54,14 @@ func EnableLinger() (string, error) {
func TryJoinFromFilePaths(pausePidPath string, needNewNamespace bool, paths []string) (bool, int, error) {
return false, -1, errors.New("this function is not supported on this os")
}
+
+// ConfigurationMatches checks whether the additional uids/gids configured for the user
+// match the current user namespace.
+func ConfigurationMatches() (bool, error) {
+ return true, nil
+}
+
+// GetConfiguredMappings returns the additional IDs configured for the current user.
+func GetConfiguredMappings() ([]idtools.IDMap, []idtools.IDMap, error) {
+ return nil, nil, errors.New("this function is not supported on this os")
+}
diff --git a/pkg/util/utils.go b/pkg/util/utils.go
index 3f73639e7..2261934f0 100644
--- a/pkg/util/utils.go
+++ b/pkg/util/utils.go
@@ -3,7 +3,6 @@ package util
import (
"fmt"
"os"
- ouser "os/user"
"path/filepath"
"strings"
"sync"
@@ -156,22 +155,15 @@ func ParseIDMapping(mode namespaces.UsernsMode, UIDMapSlice, GIDMapSlice []strin
uid := rootless.GetRootlessUID()
gid := rootless.GetRootlessGID()
- username := os.Getenv("USER")
- if username == "" {
- user, err := ouser.LookupId(fmt.Sprintf("%d", uid))
- if err == nil {
- username = user.Username
- }
- }
- mappings, err := idtools.NewIDMappings(username, username)
+ uids, gids, err := rootless.GetConfiguredMappings()
if err != nil {
- return nil, errors.Wrapf(err, "cannot find mappings for user %s", username)
+ return nil, errors.Wrapf(err, "cannot read mappings")
}
maxUID, maxGID := 0, 0
- for _, u := range mappings.UIDs() {
+ for _, u := range uids {
maxUID += u.Size
}
- for _, g := range mappings.GIDs() {
+ for _, g := range gids {
maxGID += g.Size
}