mirror of
https://github.com/containers/podman.git
synced 2025-05-28 21:46:51 +08:00
119 lines
2.7 KiB
Go
119 lines
2.7 KiB
Go
package rootless
|
|
|
|
import (
|
|
"os"
|
|
"sync"
|
|
|
|
"github.com/containers/storage"
|
|
"github.com/opencontainers/runc/libcontainer/user"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
// TryJoinPauseProcess attempts to join the namespaces of the pause PID via
|
|
// TryJoinFromFilePaths. If joining fails, it attempts to delete the specified
|
|
// file.
|
|
func TryJoinPauseProcess(pausePidPath string) (bool, int, error) {
|
|
if _, err := os.Stat(pausePidPath); err != nil {
|
|
return false, -1, nil
|
|
}
|
|
|
|
became, ret, err := TryJoinFromFilePaths("", false, []string{pausePidPath})
|
|
if err == nil {
|
|
return became, ret, err
|
|
}
|
|
|
|
// It could not join the pause process, let's lock the file before trying to delete it.
|
|
pidFileLock, err := storage.GetLockfile(pausePidPath)
|
|
if err != nil {
|
|
// The file was deleted by another process.
|
|
if os.IsNotExist(err) {
|
|
return false, -1, nil
|
|
}
|
|
return false, -1, errors.Wrapf(err, "error acquiring lock on %s", pausePidPath)
|
|
}
|
|
|
|
pidFileLock.Lock()
|
|
defer func() {
|
|
if pidFileLock.Locked() {
|
|
pidFileLock.Unlock()
|
|
}
|
|
}()
|
|
|
|
// Now the pause PID file is locked. Try to join once again in case it changed while it was not locked.
|
|
became, ret, err = TryJoinFromFilePaths("", false, []string{pausePidPath})
|
|
if err != nil {
|
|
// It is still failing. We can safely remove it.
|
|
os.Remove(pausePidPath)
|
|
return false, -1, nil
|
|
}
|
|
return became, ret, err
|
|
}
|
|
|
|
var (
|
|
uidMap []user.IDMap
|
|
uidMapError error
|
|
uidMapOnce sync.Once
|
|
|
|
gidMap []user.IDMap
|
|
gidMapError error
|
|
gidMapOnce sync.Once
|
|
)
|
|
|
|
// GetAvailableUidMap returns the UID mappings in the
|
|
// current user namespace.
|
|
func GetAvailableUidMap() ([]user.IDMap, error) {
|
|
uidMapOnce.Do(func() {
|
|
var err error
|
|
uidMap, err = user.ParseIDMapFile("/proc/self/uid_map")
|
|
if err != nil {
|
|
uidMapError = err
|
|
return
|
|
}
|
|
})
|
|
return uidMap, uidMapError
|
|
}
|
|
|
|
// GetAvailableGidMap returns the GID mappings in the
|
|
// current user namespace.
|
|
func GetAvailableGidMap() ([]user.IDMap, error) {
|
|
gidMapOnce.Do(func() {
|
|
var err error
|
|
gidMap, err = user.ParseIDMapFile("/proc/self/gid_map")
|
|
if err != nil {
|
|
gidMapError = err
|
|
return
|
|
}
|
|
})
|
|
return gidMap, gidMapError
|
|
}
|
|
|
|
func countAvailableIDs(mappings []user.IDMap) int64 {
|
|
availableUids := int64(0)
|
|
for _, r := range mappings {
|
|
availableUids += r.Count
|
|
}
|
|
return availableUids
|
|
}
|
|
|
|
// GetAvailableUids returns how many UIDs are available in the
|
|
// current user namespace.
|
|
func GetAvailableUids() (int64, error) {
|
|
uids, err := GetAvailableUidMap()
|
|
if err != nil {
|
|
return -1, err
|
|
}
|
|
|
|
return countAvailableIDs(uids), nil
|
|
}
|
|
|
|
// GetAvailableGids returns how many GIDs are available in the
|
|
// current user namespace.
|
|
func GetAvailableGids() (int64, error) {
|
|
gids, err := GetAvailableGidMap()
|
|
if err != nil {
|
|
return -1, err
|
|
}
|
|
|
|
return countAvailableIDs(gids), nil
|
|
}
|