[release-1.33] Bump c/storage to v1.51.2, fixes CVE-2024-9676

As the title says.  Addresses CVE-2024-9676

Fixes: https://issues.redhat.com/browse/RHEL-61853, https://issues.redhat.com/browse/RHEL-61860

[NO NEW TESTS NEEDED]

Signed-off-by: tomsweeneyredhat <tsweeney@redhat.com>
This commit is contained in:
tomsweeneyredhat 2024-10-25 11:47:30 -04:00
parent bd85c17037
commit df8f557271
8 changed files with 118 additions and 42 deletions

2
go.mod
View File

@ -10,7 +10,7 @@ require (
github.com/containers/image/v5 v5.29.4 github.com/containers/image/v5 v5.29.4
github.com/containers/luksy v0.0.0-20231030195837-b5a7f79da98b github.com/containers/luksy v0.0.0-20231030195837-b5a7f79da98b
github.com/containers/ocicrypt v1.1.10 github.com/containers/ocicrypt v1.1.10
github.com/containers/storage v1.51.0 github.com/containers/storage v1.51.2
github.com/cyphar/filepath-securejoin v0.2.4 github.com/cyphar/filepath-securejoin v0.2.4
github.com/docker/distribution v2.8.3+incompatible github.com/docker/distribution v2.8.3+incompatible
github.com/docker/docker v24.0.7+incompatible github.com/docker/docker v24.0.7+incompatible

4
go.sum
View File

@ -64,8 +64,8 @@ github.com/containers/luksy v0.0.0-20231030195837-b5a7f79da98b h1:8XvNAm+g7ivwPU
github.com/containers/luksy v0.0.0-20231030195837-b5a7f79da98b/go.mod h1:menB9p4o5HckgcLW6cO0+dl6+axkVmSqKlrNcratsh4= github.com/containers/luksy v0.0.0-20231030195837-b5a7f79da98b/go.mod h1:menB9p4o5HckgcLW6cO0+dl6+axkVmSqKlrNcratsh4=
github.com/containers/ocicrypt v1.1.10 h1:r7UR6o8+lyhkEywetubUUgcKFjOWOaWz8cEBrCPX0ic= github.com/containers/ocicrypt v1.1.10 h1:r7UR6o8+lyhkEywetubUUgcKFjOWOaWz8cEBrCPX0ic=
github.com/containers/ocicrypt v1.1.10/go.mod h1:YfzSSr06PTHQwSTUKqDSjish9BeW1E4HUmreluQcMd8= github.com/containers/ocicrypt v1.1.10/go.mod h1:YfzSSr06PTHQwSTUKqDSjish9BeW1E4HUmreluQcMd8=
github.com/containers/storage v1.51.0 h1:AowbcpiWXzAjHosKz7MKvPEqpyX+ryZA/ZurytRrFNA= github.com/containers/storage v1.51.2 h1:Xw8p1AG1A+Nh6dCsb1UOB3YKF5uzlCkI3uAP4fsFup4=
github.com/containers/storage v1.51.0/go.mod h1:ybl8a3j1PPtpyaEi/5A6TOFs+5TrEyObeKJzVtkUlfc= github.com/containers/storage v1.51.2/go.mod h1:ybl8a3j1PPtpyaEi/5A6TOFs+5TrEyObeKJzVtkUlfc=
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=

View File

@ -119,7 +119,7 @@ lint_task:
env: env:
CIRRUS_WORKING_DIR: "/go/src/github.com/containers/storage" CIRRUS_WORKING_DIR: "/go/src/github.com/containers/storage"
container: container:
image: golang image: golang:1.19
modules_cache: modules_cache:
fingerprint_script: cat go.sum fingerprint_script: cat go.sum
folder: $GOPATH/pkg/mod folder: $GOPATH/pkg/mod

View File

@ -1 +1 @@
1.51.0 1.51.2

View File

@ -1670,13 +1670,21 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
} }
if err := idtools.MkdirAllAs(diffDir, perms, rootUID, rootGID); err != nil { if err := idtools.MkdirAllAs(diffDir, perms, rootUID, rootGID); err != nil {
return "", err if !inAdditionalStore {
return "", err
}
// if it is in an additional store, do not fail if the directory already exists
if _, err2 := os.Stat(diffDir); err2 != nil {
return "", err
}
} }
mergedDir := path.Join(workDirBase, "merged") mergedDir := path.Join(workDirBase, "merged")
// Create the driver merged dir // Attempt to create the merged dir only if it doesn't exist.
if err := idtools.MkdirAs(mergedDir, 0o700, rootUID, rootGID); err != nil && !os.IsExist(err) { if _, err := os.Stat(mergedDir); err != nil && os.IsNotExist(err) {
return "", err if err := idtools.MkdirAs(mergedDir, 0o700, rootUID, rootGID); err != nil && !os.IsExist(err) {
return "", err
}
} }
if count := d.ctr.Increment(mergedDir); count > 1 { if count := d.ctr.Increment(mergedDir); count > 1 {
return mergedDir, nil return mergedDir, nil
@ -1841,7 +1849,7 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
// Put unmounts the mount path created for the give id. // Put unmounts the mount path created for the give id.
func (d *Driver) Put(id string) error { func (d *Driver) Put(id string) error {
dir := d.dir(id) dir, _, inAdditionalStore := d.dir2(id)
if _, err := os.Stat(dir); err != nil { if _, err := os.Stat(dir); err != nil {
return err return err
} }
@ -1902,11 +1910,27 @@ func (d *Driver) Put(id string) error {
} }
} }
if err := unix.Rmdir(mountpoint); err != nil && !os.IsNotExist(err) { if !inAdditionalStore {
logrus.Debugf("Failed to remove mountpoint %s overlay: %s - %v", id, mountpoint, err) uid, gid := int(0), int(0)
return fmt.Errorf("removing mount point %q: %w", mountpoint, err) fi, err := os.Stat(mountpoint)
} if err != nil {
return err
}
if stat, ok := fi.Sys().(*syscall.Stat_t); ok {
uid, gid = int(stat.Uid), int(stat.Gid)
}
tmpMountpoint := path.Join(dir, "merged.1")
if err := idtools.MkdirAs(tmpMountpoint, 0o700, uid, gid); err != nil && !errors.Is(err, os.ErrExist) {
return err
}
// rename(2) can be used on an empty directory, as it is the mountpoint after umount, and it retains
// its atomic semantic. In this way the "merged" directory is never removed.
if err := unix.Rename(tmpMountpoint, mountpoint); err != nil {
logrus.Debugf("Failed to replace mountpoint %s overlay: %s - %v", id, mountpoint, err)
return fmt.Errorf("replacing mount point %q: %w", mountpoint, err)
}
}
return nil return nil
} }

View File

@ -1,18 +1,21 @@
//go:build linux
package storage package storage
import ( import (
"fmt" "fmt"
"os" "os"
"os/user" "os/user"
"path/filepath"
"strconv" "strconv"
drivers "github.com/containers/storage/drivers" drivers "github.com/containers/storage/drivers"
"github.com/containers/storage/pkg/idtools" "github.com/containers/storage/pkg/idtools"
"github.com/containers/storage/pkg/unshare" "github.com/containers/storage/pkg/unshare"
"github.com/containers/storage/types" "github.com/containers/storage/types"
securejoin "github.com/cyphar/filepath-securejoin"
libcontainerUser "github.com/opencontainers/runc/libcontainer/user" libcontainerUser "github.com/opencontainers/runc/libcontainer/user"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
) )
// getAdditionalSubIDs looks up the additional IDs configured for // getAdditionalSubIDs looks up the additional IDs configured for
@ -85,40 +88,59 @@ const nobodyUser = 65534
// parseMountedFiles returns the maximum UID and GID found in the /etc/passwd and // parseMountedFiles returns the maximum UID and GID found in the /etc/passwd and
// /etc/group files. // /etc/group files.
func parseMountedFiles(containerMount, passwdFile, groupFile string) uint32 { func parseMountedFiles(containerMount, passwdFile, groupFile string) uint32 {
var (
passwd *os.File
group *os.File
size int
err error
)
if passwdFile == "" { if passwdFile == "" {
passwdFile = filepath.Join(containerMount, "etc/passwd") passwd, err = secureOpen(containerMount, "/etc/passwd")
} else {
// User-specified override from a volume. Will not be in
// container root.
passwd, err = os.Open(passwdFile)
} }
if groupFile == "" {
groupFile = filepath.Join(groupFile, "etc/group")
}
size := 0
users, err := libcontainerUser.ParsePasswdFile(passwdFile)
if err == nil { if err == nil {
for _, u := range users { defer passwd.Close()
// Skip the "nobody" user otherwise we end up with 65536
// ids with most images users, err := libcontainerUser.ParsePasswd(passwd)
if u.Name == "nobody" { if err == nil {
continue for _, u := range users {
} // Skip the "nobody" user otherwise we end up with 65536
if u.Uid > size && u.Uid != nobodyUser { // ids with most images
size = u.Uid if u.Name == "nobody" || u.Name == "nogroup" {
} continue
if u.Gid > size && u.Gid != nobodyUser { }
size = u.Gid if u.Uid > size && u.Uid != nobodyUser {
size = u.Uid + 1
}
if u.Gid > size && u.Gid != nobodyUser {
size = u.Gid + 1
}
} }
} }
} }
groups, err := libcontainerUser.ParseGroupFile(groupFile) if groupFile == "" {
group, err = secureOpen(containerMount, "/etc/group")
} else {
// User-specified override from a volume. Will not be in
// container root.
group, err = os.Open(groupFile)
}
if err == nil { if err == nil {
for _, g := range groups { defer group.Close()
if g.Name == "nobody" {
continue groups, err := libcontainerUser.ParseGroup(group)
} if err == nil {
if g.Gid > size && g.Gid != nobodyUser { for _, g := range groups {
size = g.Gid if g.Name == "nobody" || g.Name == "nogroup" {
continue
}
if g.Gid > size && g.Gid != nobodyUser {
size = g.Gid + 1
}
} }
} }
} }
@ -309,3 +331,19 @@ func getAutoUserNSIDMappings(
gidMap := append(availableGIDs.zip(requestedContainerGIDs), additionalGIDMappings...) gidMap := append(availableGIDs.zip(requestedContainerGIDs), additionalGIDMappings...)
return uidMap, gidMap, nil return uidMap, gidMap, nil
} }
// Securely open (read-only) a file in a container mount.
func secureOpen(containerMount, file string) (*os.File, error) {
filePath, err := securejoin.SecureJoin(containerMount, file)
if err != nil {
return nil, err
}
flags := unix.O_PATH | unix.O_CLOEXEC | unix.O_RDONLY
fileHandle, err := os.OpenFile(filePath, flags, 0)
if err != nil {
return nil, err
}
return fileHandle, nil
}

View File

@ -0,0 +1,14 @@
//go:build !linux
package storage
import (
"errors"
"github.com/containers/storage/pkg/idtools"
"github.com/containers/storage/types"
)
func (s *store) getAutoUserNS(_ *types.AutoUserNsOptions, _ *Image, _ rwLayerStore, _ []roLayerStore) ([]idtools.IDMap, []idtools.IDMap, error) {
return nil, nil, errors.New("user namespaces are not supported on this platform")
}

2
vendor/modules.txt vendored
View File

@ -233,7 +233,7 @@ github.com/containers/ocicrypt/keywrap/pkcs7
github.com/containers/ocicrypt/spec github.com/containers/ocicrypt/spec
github.com/containers/ocicrypt/utils github.com/containers/ocicrypt/utils
github.com/containers/ocicrypt/utils/keyprovider github.com/containers/ocicrypt/utils/keyprovider
# github.com/containers/storage v1.51.0 # github.com/containers/storage v1.51.2
## explicit; go 1.19 ## explicit; go 1.19
github.com/containers/storage github.com/containers/storage
github.com/containers/storage/drivers github.com/containers/storage/drivers