Merge pull request #14622 from rhatdan/storage

Vendor in latest containers/storage
This commit is contained in:
openshift-ci[bot]
2022-06-17 07:54:59 +00:00
committed by GitHub
11 changed files with 135 additions and 45 deletions

2
go.mod
View File

@ -17,7 +17,7 @@ require (
github.com/containers/image/v5 v5.21.2-0.20220520105616-e594853d6471 github.com/containers/image/v5 v5.21.2-0.20220520105616-e594853d6471
github.com/containers/ocicrypt v1.1.4-0.20220428134531-566b808bdf6f github.com/containers/ocicrypt v1.1.4-0.20220428134531-566b808bdf6f
github.com/containers/psgo v1.7.2 github.com/containers/psgo v1.7.2
github.com/containers/storage v1.41.1-0.20220607143333-8951d0153bf6 github.com/containers/storage v1.41.1-0.20220616120034-7df64288ef35
github.com/coreos/go-systemd/v22 v22.3.2 github.com/coreos/go-systemd/v22 v22.3.2
github.com/coreos/stream-metadata-go v0.0.0-20210225230131-70edb9eb47b3 github.com/coreos/stream-metadata-go v0.0.0-20210225230131-70edb9eb47b3
github.com/cyphar/filepath-securejoin v0.2.3 github.com/cyphar/filepath-securejoin v0.2.3

3
go.sum
View File

@ -361,8 +361,9 @@ github.com/containers/storage v1.37.0/go.mod h1:kqeJeS0b7DO2ZT1nVWs0XufrmPFbgV3c
github.com/containers/storage v1.38.0/go.mod h1:lBzt28gAk5ADZuRtwdndRJyqX22vnRaXmlF+7ktfMYc= github.com/containers/storage v1.38.0/go.mod h1:lBzt28gAk5ADZuRtwdndRJyqX22vnRaXmlF+7ktfMYc=
github.com/containers/storage v1.40.2/go.mod h1:zUyPC3CFIGR1OhY1CKkffxgw9+LuH76PGvVcFj38dgs= github.com/containers/storage v1.40.2/go.mod h1:zUyPC3CFIGR1OhY1CKkffxgw9+LuH76PGvVcFj38dgs=
github.com/containers/storage v1.41.0/go.mod h1:Pb0l5Sm/89kolX3o2KolKQ5cCHk5vPNpJrhNaLcdS5s= github.com/containers/storage v1.41.0/go.mod h1:Pb0l5Sm/89kolX3o2KolKQ5cCHk5vPNpJrhNaLcdS5s=
github.com/containers/storage v1.41.1-0.20220607143333-8951d0153bf6 h1:AWGEIiqWFIfzTIv4Q3k6vJt/EYyo8dh35ny7WhnOd0s=
github.com/containers/storage v1.41.1-0.20220607143333-8951d0153bf6/go.mod h1:6XQ68cEG8ojfP/m3HIupFV1rZsnqeFmaE8N1ctBP94Y= github.com/containers/storage v1.41.1-0.20220607143333-8951d0153bf6/go.mod h1:6XQ68cEG8ojfP/m3HIupFV1rZsnqeFmaE8N1ctBP94Y=
github.com/containers/storage v1.41.1-0.20220616120034-7df64288ef35 h1:6o+kw2z0BrdJ1wNYUbwLVzlb/65KPmZSy+32GNfppzM=
github.com/containers/storage v1.41.1-0.20220616120034-7df64288ef35/go.mod h1:6XQ68cEG8ojfP/m3HIupFV1rZsnqeFmaE8N1ctBP94Y=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=

View File

@ -21,12 +21,12 @@ type inode struct {
type platformChowner struct { type platformChowner struct {
mutex sync.Mutex mutex sync.Mutex
inodes map[inode]bool inodes map[inode]string
} }
func newLChowner() *platformChowner { func newLChowner() *platformChowner {
return &platformChowner{ return &platformChowner{
inodes: make(map[inode]bool), inodes: make(map[inode]string),
} }
} }
@ -40,15 +40,33 @@ func (c *platformChowner) LChown(path string, info os.FileInfo, toHost, toContai
Dev: uint64(st.Dev), Dev: uint64(st.Dev),
Ino: uint64(st.Ino), Ino: uint64(st.Ino),
} }
c.mutex.Lock() c.mutex.Lock()
_, found := c.inodes[i]
oldTarget, found := c.inodes[i]
if !found { if !found {
c.inodes[i] = true c.inodes[i] = path
} }
// If we are dealing with a file with multiple links then keep the lock until the file is
// chowned to avoid a race where we link to the old version if the file is copied up.
if found || st.Nlink > 1 {
defer c.mutex.Unlock()
} else {
c.mutex.Unlock() c.mutex.Unlock()
}
if found { if found {
return nil // If the dev/inode was already chowned then create a link to the old target instead
// of chowning it again. This is necessary when the underlying file system breaks
// inodes on copy-up (as it is with overlay with index=off) to maintain the original
// link and correct file ownership.
// The target already exists so remove it before creating the link to the new target.
if err := os.Remove(path); err != nil {
return err
}
return os.Link(oldTarget, path)
} }
// Map an on-disk UID/GID pair from host to container // Map an on-disk UID/GID pair from host to container

View File

@ -1,3 +1,4 @@
//go:build linux
// +build linux // +build linux
package graphdriver package graphdriver
@ -162,11 +163,32 @@ func (c *defaultChecker) IsMounted(path string) bool {
return m return m
} }
// isMountPoint checks that the given path is a mount point
func isMountPoint(mountPath string) (bool, error) {
// it is already the root
if mountPath == "/" {
return true, nil
}
var s1, s2 unix.Stat_t
if err := unix.Stat(mountPath, &s1); err != nil {
return true, err
}
if err := unix.Stat(filepath.Dir(mountPath), &s2); err != nil {
return true, err
}
return s1.Dev != s2.Dev, nil
}
// Mounted checks if the given path is mounted as the fs type // Mounted checks if the given path is mounted as the fs type
func Mounted(fsType FsMagic, mountPath string) (bool, error) { func Mounted(fsType FsMagic, mountPath string) (bool, error) {
var buf unix.Statfs_t var buf unix.Statfs_t
if err := unix.Statfs(mountPath, &buf); err != nil { if err := unix.Statfs(mountPath, &buf); err != nil {
return false, err return false, err
} }
return FsMagic(buf.Type) == fsType, nil if FsMagic(buf.Type) != fsType {
return false, nil
}
return isMountPoint(mountPath)
} }

View File

@ -1,8 +1,10 @@
//go:build linux && cgo && libsubid
// +build linux,cgo,libsubid // +build linux,cgo,libsubid
package idtools package idtools
import ( import (
"os/user"
"unsafe" "unsafe"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -32,19 +34,34 @@ import "C"
func readSubid(username string, isUser bool) (ranges, error) { func readSubid(username string, isUser bool) (ranges, error) {
var ret ranges var ret ranges
uidstr := ""
if username == "ALL" { if username == "ALL" {
return nil, errors.New("username ALL not supported") return nil, errors.New("username ALL not supported")
} }
if u, err := user.Lookup(username); err == nil {
uidstr = u.Uid
}
cUsername := C.CString(username) cUsername := C.CString(username)
defer C.free(unsafe.Pointer(cUsername)) defer C.free(unsafe.Pointer(cUsername))
cuidstr := C.CString(uidstr)
defer C.free(unsafe.Pointer(cuidstr))
var nRanges C.int var nRanges C.int
var cRanges *C.struct_subid_range var cRanges *C.struct_subid_range
if isUser { if isUser {
nRanges = C.subid_get_uid_ranges(cUsername, &cRanges) nRanges = C.subid_get_uid_ranges(cUsername, &cRanges)
if nRanges <= 0 {
nRanges = C.subid_get_uid_ranges(cuidstr, &cRanges)
}
} else { } else {
nRanges = C.subid_get_gid_ranges(cUsername, &cRanges) nRanges = C.subid_get_gid_ranges(cUsername, &cRanges)
if nRanges <= 0 {
nRanges = C.subid_get_gid_ranges(cuidstr, &cRanges)
}
} }
if nRanges < 0 { if nRanges < 0 {
return nil, errors.New("cannot read subids") return nil, errors.New("cannot read subids")

View File

@ -1,15 +1,19 @@
//go:build linux || solaris || darwin || freebsd
// +build linux solaris darwin freebsd // +build linux solaris darwin freebsd
package lockfile package lockfile
import ( import (
"bytes"
cryptorand "crypto/rand"
"encoding/binary"
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"sync" "sync"
"sync/atomic"
"time" "time"
"github.com/containers/storage/pkg/stringid"
"github.com/containers/storage/pkg/system" "github.com/containers/storage/pkg/system"
"github.com/pkg/errors" "github.com/pkg/errors"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
@ -23,13 +27,44 @@ type lockfile struct {
counter int64 counter int64
file string file string
fd uintptr fd uintptr
lw string lw []byte // "last writer"-unique value valid as of the last .Touch() or .Modified(), generated by newLastWriterID()
locktype int16 locktype int16
locked bool locked bool
ro bool ro bool
recursive bool recursive bool
} }
const lastWriterIDSize = 64 // This must be the same as len(stringid.GenerateRandomID)
var lastWriterIDCounter uint64 // Private state for newLastWriterID
// newLastWriterID returns a new "last writer" ID.
// The value must be different on every call, and also differ from values
// generated by other processes.
func newLastWriterID() []byte {
// The ID is (PID, time, per-process counter, random)
// PID + time represents both a unique process across reboots,
// and a specific time within the process; the per-process counter
// is an extra safeguard for in-process concurrency.
// The random part disambiguates across process namespaces
// (where PID values might collide), serves as a general-purpose
// extra safety, _and_ is used to pad the output to lastWriterIDSize,
// because other versions of this code exist and they don't work
// efficiently if the size of the value changes.
pid := os.Getpid()
tm := time.Now().UnixNano()
counter := atomic.AddUint64(&lastWriterIDCounter, 1)
res := make([]byte, lastWriterIDSize)
binary.LittleEndian.PutUint64(res[0:8], uint64(tm))
binary.LittleEndian.PutUint64(res[8:16], counter)
binary.LittleEndian.PutUint32(res[16:20], uint32(pid))
if n, err := cryptorand.Read(res[20:lastWriterIDSize]); err != nil || n != lastWriterIDSize-20 {
panic(err) // This shouldn't happen
}
return res
}
// openLock opens the file at path and returns the corresponding file // openLock opens the file at path and returns the corresponding file
// descriptor. Note that the path is opened read-only when ro is set. If ro // descriptor. Note that the path is opened read-only when ro is set. If ro
// is unset, openLock will open the path read-write and create the file if // is unset, openLock will open the path read-write and create the file if
@ -89,7 +124,7 @@ func createLockerForPath(path string, ro bool) (Locker, error) {
stateMutex: &sync.Mutex{}, stateMutex: &sync.Mutex{},
rwMutex: &sync.RWMutex{}, rwMutex: &sync.RWMutex{},
file: path, file: path,
lw: stringid.GenerateRandomID(), lw: newLastWriterID(),
locktype: int16(locktype), locktype: int16(locktype),
locked: false, locked: false,
ro: ro}, nil ro: ro}, nil
@ -212,13 +247,12 @@ func (l *lockfile) Touch() error {
panic("attempted to update last-writer in lockfile without the write lock") panic("attempted to update last-writer in lockfile without the write lock")
} }
defer l.stateMutex.Unlock() defer l.stateMutex.Unlock()
l.lw = stringid.GenerateRandomID() l.lw = newLastWriterID()
id := []byte(l.lw) n, err := unix.Pwrite(int(l.fd), l.lw, 0)
n, err := unix.Pwrite(int(l.fd), id, 0)
if err != nil { if err != nil {
return err return err
} }
if n != len(id) { if n != len(l.lw) {
return unix.ENOSPC return unix.ENOSPC
} }
return nil return nil
@ -228,21 +262,21 @@ func (l *lockfile) Touch() error {
// was loaded. // was loaded.
func (l *lockfile) Modified() (bool, error) { func (l *lockfile) Modified() (bool, error) {
l.stateMutex.Lock() l.stateMutex.Lock()
id := []byte(l.lw)
if !l.locked { if !l.locked {
panic("attempted to check last-writer in lockfile without locking it first") panic("attempted to check last-writer in lockfile without locking it first")
} }
defer l.stateMutex.Unlock() defer l.stateMutex.Unlock()
n, err := unix.Pread(int(l.fd), id, 0) currentLW := make([]byte, len(l.lw))
n, err := unix.Pread(int(l.fd), currentLW, 0)
if err != nil { if err != nil {
return true, err return true, err
} }
if n != len(id) { if n != len(l.lw) {
return true, nil return true, nil
} }
lw := l.lw oldLW := l.lw
l.lw = string(id) l.lw = currentLW
return l.lw != lw, nil return !bytes.Equal(currentLW, oldLW), nil
} }
// IsReadWriteLock indicates if the lock file is a read-write lock. // IsReadWriteLock indicates if the lock file is a read-write lock.

View File

@ -12,6 +12,7 @@ import (
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
"sync"
"time" "time"
) )
@ -20,6 +21,9 @@ const shortLen = 12
var ( var (
validShortID = regexp.MustCompile("^[a-f0-9]{12}$") validShortID = regexp.MustCompile("^[a-f0-9]{12}$")
validHex = regexp.MustCompile(`^[a-f0-9]{64}$`) validHex = regexp.MustCompile(`^[a-f0-9]{64}$`)
rngLock sync.Mutex
rng *rand.Rand // A RNG with seeding properties we control. It can only be accessed with randLock held.
) )
// IsShortID determines if an arbitrary string *looks like* a short ID. // IsShortID determines if an arbitrary string *looks like* a short ID.
@ -67,7 +71,9 @@ func GenerateRandomID() string {
// secure sources of random. // secure sources of random.
// It helps you to save entropy. // It helps you to save entropy.
func GenerateNonCryptoID() string { func GenerateNonCryptoID() string {
return generateID(readerFunc(rand.Read)) rngLock.Lock()
defer rngLock.Unlock()
return generateID(readerFunc(rng.Read))
} }
// ValidateID checks whether an ID string is a valid image ID. // ValidateID checks whether an ID string is a valid image ID.
@ -79,7 +85,7 @@ func ValidateID(id string) error {
} }
func init() { func init() {
// safely set the seed globally so we generate random ids. Tries to use a // Initialize a private RNG so we generate random ids. Tries to use a
// crypto seed before falling back to time. // crypto seed before falling back to time.
var seed int64 var seed int64
if cryptoseed, err := cryptorand.Int(cryptorand.Reader, big.NewInt(math.MaxInt64)); err != nil { if cryptoseed, err := cryptorand.Int(cryptorand.Reader, big.NewInt(math.MaxInt64)); err != nil {
@ -89,7 +95,7 @@ func init() {
seed = cryptoseed.Int64() seed = cryptoseed.Int64()
} }
rand.Seed(seed) rng = rand.New(rand.NewSource(seed))
} }
type readerFunc func(p []byte) (int, error) type readerFunc func(p []byte) (int, error)

View File

@ -1,5 +1,8 @@
//go:build !linux && !windows && !solaris && !freebsd //go:build !linux && !windows && !solaris && !(freebsd && cgo)
// +build !linux,!windows,!solaris,!freebsd // +build !linux
// +build !windows
// +build !solaris
// +build !freebsd !cgo
package system package system

View File

@ -21,7 +21,6 @@ import (
"github.com/containers/storage/pkg/idtools" "github.com/containers/storage/pkg/idtools"
"github.com/containers/storage/pkg/ioutils" "github.com/containers/storage/pkg/ioutils"
"github.com/containers/storage/pkg/parsers" "github.com/containers/storage/pkg/parsers"
"github.com/containers/storage/pkg/stringid"
"github.com/containers/storage/pkg/stringutils" "github.com/containers/storage/pkg/stringutils"
"github.com/containers/storage/pkg/system" "github.com/containers/storage/pkg/system"
"github.com/containers/storage/types" "github.com/containers/storage/types"
@ -1016,9 +1015,6 @@ func (s *store) PutLayer(id, parent string, names []string, mountLabel string, w
if err := rcstore.ReloadIfChanged(); err != nil { if err := rcstore.ReloadIfChanged(); err != nil {
return nil, -1, err return nil, -1, err
} }
if id == "" {
id = stringid.GenerateRandomID()
}
if options == nil { if options == nil {
options = &LayerOptions{} options = &LayerOptions{}
} }
@ -1097,10 +1093,6 @@ func (s *store) CreateLayer(id, parent string, names []string, mountLabel string
} }
func (s *store) CreateImage(id string, names []string, layer, metadata string, options *ImageOptions) (*Image, error) { func (s *store) CreateImage(id string, names []string, layer, metadata string, options *ImageOptions) (*Image, error) {
if id == "" {
id = stringid.GenerateRandomID()
}
if layer != "" { if layer != "" {
lstore, err := s.LayerStore() lstore, err := s.LayerStore()
if err != nil { if err != nil {
@ -1279,9 +1271,6 @@ func (s *store) CreateContainer(id string, names []string, image, layer, metadat
if err != nil { if err != nil {
return nil, err return nil, err
} }
if id == "" {
id = stringid.GenerateRandomID()
}
var imageTopLayer *Layer var imageTopLayer *Layer
imageID := "" imageID := ""
@ -1337,14 +1326,14 @@ func (s *store) CreateContainer(id string, names []string, image, layer, metadat
} }
} }
if cimage == nil { if cimage == nil {
return nil, errors.Wrapf(ErrImageUnknown, "error locating image with ID %q", id) return nil, errors.Wrapf(ErrImageUnknown, "error locating image with ID %q", image)
} }
imageID = cimage.ID imageID = cimage.ID
} }
if options.AutoUserNs { if options.AutoUserNs {
var err error var err error
options.UIDMap, options.GIDMap, err = s.getAutoUserNS(id, &options.AutoUserNsOpts, cimage) options.UIDMap, options.GIDMap, err = s.getAutoUserNS(&options.AutoUserNsOpts, cimage)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -124,7 +124,7 @@ func parseMountedFiles(containerMount, passwdFile, groupFile string) uint32 {
// getMaxSizeFromImage returns the maximum ID used by the specified image. // getMaxSizeFromImage returns the maximum ID used by the specified image.
// The layer stores must be already locked. // The layer stores must be already locked.
func (s *store) getMaxSizeFromImage(id string, image *Image, passwdFile, groupFile string) (uint32, error) { func (s *store) getMaxSizeFromImage(image *Image, passwdFile, groupFile string) (uint32, error) {
lstore, err := s.LayerStore() lstore, err := s.LayerStore()
if err != nil { if err != nil {
return 0, err return 0, err
@ -183,7 +183,7 @@ outer:
// We need to create a temporary layer so we can mount it and lookup the // We need to create a temporary layer so we can mount it and lookup the
// maximum IDs used. // maximum IDs used.
clayer, err := rlstore.Create(id, topLayer, nil, "", nil, layerOptions, false) clayer, err := rlstore.Create("", topLayer, nil, "", nil, layerOptions, false)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -211,7 +211,7 @@ outer:
} }
// getAutoUserNS creates an automatic user namespace // getAutoUserNS creates an automatic user namespace
func (s *store) getAutoUserNS(id string, options *types.AutoUserNsOptions, image *Image) ([]idtools.IDMap, []idtools.IDMap, error) { func (s *store) getAutoUserNS(options *types.AutoUserNsOptions, image *Image) ([]idtools.IDMap, []idtools.IDMap, error) {
requestedSize := uint32(0) requestedSize := uint32(0)
initialSize := uint32(1) initialSize := uint32(1)
if options.Size > 0 { if options.Size > 0 {
@ -250,7 +250,7 @@ func (s *store) getAutoUserNS(id string, options *types.AutoUserNsOptions, image
size = s.autoNsMinSize size = s.autoNsMinSize
} }
if image != nil { if image != nil {
sizeFromImage, err := s.getMaxSizeFromImage(id, image, options.PasswdFile, options.GroupFile) sizeFromImage, err := s.getMaxSizeFromImage(image, options.PasswdFile, options.GroupFile)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

2
vendor/modules.txt vendored
View File

@ -239,7 +239,7 @@ github.com/containers/psgo/internal/dev
github.com/containers/psgo/internal/host github.com/containers/psgo/internal/host
github.com/containers/psgo/internal/proc github.com/containers/psgo/internal/proc
github.com/containers/psgo/internal/process github.com/containers/psgo/internal/process
# github.com/containers/storage v1.41.1-0.20220607143333-8951d0153bf6 # github.com/containers/storage v1.41.1-0.20220616120034-7df64288ef35
## explicit ## explicit
github.com/containers/storage github.com/containers/storage
github.com/containers/storage/drivers github.com/containers/storage/drivers