mirror of
https://github.com/containers/podman.git
synced 2025-11-30 01:58:46 +08:00
update github.com/opencontainers/runc to v1.2.0-rc.3
Signed-off-by: Paul Holzinger <pholzing@redhat.com>
This commit is contained in:
112
vendor/github.com/opencontainers/runc/libcontainer/utils/utils_unix.go
generated
vendored
112
vendor/github.com/opencontainers/runc/libcontainer/utils/utils_unix.go
generated
vendored
@@ -3,6 +3,7 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
@@ -13,6 +14,8 @@ import (
|
||||
"sync"
|
||||
_ "unsafe" // for go:linkname
|
||||
|
||||
"github.com/opencontainers/runc/libcontainer/system"
|
||||
|
||||
securejoin "github.com/cyphar/filepath-securejoin"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/sys/unix"
|
||||
@@ -275,3 +278,112 @@ func IsLexicallyInRoot(root, path string) bool {
|
||||
}
|
||||
return strings.HasPrefix(path, root)
|
||||
}
|
||||
|
||||
// MkdirAllInRootOpen attempts to make
|
||||
//
|
||||
// path, _ := securejoin.SecureJoin(root, unsafePath)
|
||||
// os.MkdirAll(path, mode)
|
||||
// os.Open(path)
|
||||
//
|
||||
// safer against attacks where components in the path are changed between
|
||||
// SecureJoin returning and MkdirAll (or Open) being called. In particular, we
|
||||
// try to detect any symlink components in the path while we are doing the
|
||||
// MkdirAll.
|
||||
//
|
||||
// NOTE: Unlike os.MkdirAll, mode is not Go's os.FileMode, it is the unix mode
|
||||
// (the suid/sgid/sticky bits are not the same as for os.FileMode).
|
||||
//
|
||||
// NOTE: If unsafePath is a subpath of root, we assume that you have already
|
||||
// called SecureJoin and so we use the provided path verbatim without resolving
|
||||
// any symlinks (this is done in a way that avoids symlink-exchange races).
|
||||
// This means that the path also must not contain ".." elements, otherwise an
|
||||
// error will occur.
|
||||
//
|
||||
// This is a somewhat less safe alternative to
|
||||
// <https://github.com/cyphar/filepath-securejoin/pull/13>, but it should
|
||||
// detect attempts to trick us into creating directories outside of the root.
|
||||
// We should migrate to securejoin.MkdirAll once it is merged.
|
||||
func MkdirAllInRootOpen(root, unsafePath string, mode uint32) (_ *os.File, Err error) {
|
||||
// If the path is already "within" the root, use it verbatim.
|
||||
fullPath := unsafePath
|
||||
if !IsLexicallyInRoot(root, unsafePath) {
|
||||
var err error
|
||||
fullPath, err = securejoin.SecureJoin(root, unsafePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
subPath, err := filepath.Rel(root, fullPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Check for any silly mode bits.
|
||||
if mode&^0o7777 != 0 {
|
||||
return nil, fmt.Errorf("tried to include non-mode bits in MkdirAll mode: 0o%.3o", mode)
|
||||
}
|
||||
|
||||
currentDir, err := os.OpenFile(root, unix.O_DIRECTORY|unix.O_CLOEXEC, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("open root handle: %w", err)
|
||||
}
|
||||
defer func() {
|
||||
if Err != nil {
|
||||
currentDir.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
for _, part := range strings.Split(subPath, string(filepath.Separator)) {
|
||||
switch part {
|
||||
case "", ".":
|
||||
// Skip over no-op components.
|
||||
continue
|
||||
case "..":
|
||||
return nil, fmt.Errorf("possible breakout detected: found %q component in SecureJoin subpath %s", part, subPath)
|
||||
}
|
||||
|
||||
nextDir, err := system.Openat(currentDir, part, unix.O_DIRECTORY|unix.O_NOFOLLOW|unix.O_CLOEXEC, 0)
|
||||
switch {
|
||||
case err == nil:
|
||||
// Update the currentDir.
|
||||
_ = currentDir.Close()
|
||||
currentDir = nextDir
|
||||
|
||||
case errors.Is(err, unix.ENOTDIR):
|
||||
// This might be a symlink or some other random file. Either way,
|
||||
// error out.
|
||||
return nil, fmt.Errorf("cannot mkdir in %s/%s: %w", currentDir.Name(), part, unix.ENOTDIR)
|
||||
|
||||
case errors.Is(err, os.ErrNotExist):
|
||||
// Luckily, mkdirat will not follow trailing symlinks, so this is
|
||||
// safe to do as-is.
|
||||
if err := system.Mkdirat(currentDir, part, mode); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Open the new directory. There is a race here where an attacker
|
||||
// could swap the directory with a different directory, but
|
||||
// MkdirAll's fuzzy semantics mean we don't care about that.
|
||||
nextDir, err := system.Openat(currentDir, part, unix.O_DIRECTORY|unix.O_NOFOLLOW|unix.O_CLOEXEC, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("open newly created directory: %w", err)
|
||||
}
|
||||
// Update the currentDir.
|
||||
_ = currentDir.Close()
|
||||
currentDir = nextDir
|
||||
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return currentDir, nil
|
||||
}
|
||||
|
||||
// MkdirAllInRoot is a wrapper around MkdirAllInRootOpen which closes the
|
||||
// returned handle, for callers that don't need to use it.
|
||||
func MkdirAllInRoot(root, unsafePath string, mode uint32) error {
|
||||
f, err := MkdirAllInRootOpen(root, unsafePath, mode)
|
||||
if err == nil {
|
||||
_ = f.Close()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user