deps: update runc to 1.1.0
This updates vendored runc/libcontainer to 1.1.0, and google/cadvisor to a version updated to runc 1.1.0 (google/cadvisor#3048). Changes in vendor are generated by (roughly): ./hack/pin-dependency.sh github.com/google/cadvisor v0.44.0 ./hack/pin-dependency.sh github.com/opencontainers/runc v1.1.0 ./hack/update-vendor.sh ./hack/lint-dependencies.sh # And follow all its recommendations. ./hack/update-vendor.sh ./hack/update-internal-modules.sh ./hack/lint-dependencies.sh # Re-check everything again. Co-Authored-By: Kir Kolyshkin <kolyshkin@gmail.com>
This commit is contained in:
252
vendor/github.com/opencontainers/runc/libcontainer/factory_linux.go
generated
vendored
252
vendor/github.com/opencontainers/runc/libcontainer/factory_linux.go
generated
vendored
@@ -1,9 +1,8 @@
|
||||
// +build linux
|
||||
|
||||
package libcontainer
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -13,17 +12,14 @@ import (
|
||||
|
||||
securejoin "github.com/cyphar/filepath-securejoin"
|
||||
"github.com/moby/sys/mountinfo"
|
||||
"github.com/opencontainers/runc/libcontainer/cgroups"
|
||||
"github.com/opencontainers/runc/libcontainer/cgroups/fs"
|
||||
"github.com/opencontainers/runc/libcontainer/cgroups/fs2"
|
||||
"github.com/opencontainers/runc/libcontainer/cgroups/systemd"
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/opencontainers/runc/libcontainer/cgroups/manager"
|
||||
"github.com/opencontainers/runc/libcontainer/configs"
|
||||
"github.com/opencontainers/runc/libcontainer/configs/validate"
|
||||
"github.com/opencontainers/runc/libcontainer/intelrdt"
|
||||
"github.com/opencontainers/runc/libcontainer/utils"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -41,7 +37,9 @@ func InitArgs(args ...string) func(*LinuxFactory) error {
|
||||
// Resolve relative paths to ensure that its available
|
||||
// after directory changes.
|
||||
if args[0], err = filepath.Abs(args[0]); err != nil {
|
||||
return newGenericError(err, ConfigInvalid)
|
||||
// The only error returned from filepath.Abs is
|
||||
// the one from os.Getwd, i.e. a system error.
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,100 +48,6 @@ func InitArgs(args ...string) func(*LinuxFactory) error {
|
||||
}
|
||||
}
|
||||
|
||||
func getUnifiedPath(paths map[string]string) string {
|
||||
path := ""
|
||||
for k, v := range paths {
|
||||
if path == "" {
|
||||
path = v
|
||||
} else if v != path {
|
||||
panic(errors.Errorf("expected %q path to be unified path %q, got %q", k, path, v))
|
||||
}
|
||||
}
|
||||
// can be empty
|
||||
if path != "" {
|
||||
if filepath.Clean(path) != path || !filepath.IsAbs(path) {
|
||||
panic(errors.Errorf("invalid dir path %q", path))
|
||||
}
|
||||
}
|
||||
|
||||
return path
|
||||
}
|
||||
|
||||
func systemdCgroupV2(l *LinuxFactory, rootless bool) error {
|
||||
l.NewCgroupsManager = func(config *configs.Cgroup, paths map[string]string) cgroups.Manager {
|
||||
return systemd.NewUnifiedManager(config, getUnifiedPath(paths), rootless)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SystemdCgroups is an options func to configure a LinuxFactory to return
|
||||
// containers that use systemd to create and manage cgroups.
|
||||
func SystemdCgroups(l *LinuxFactory) error {
|
||||
if !systemd.IsRunningSystemd() {
|
||||
return fmt.Errorf("systemd not running on this host, can't use systemd as cgroups manager")
|
||||
}
|
||||
|
||||
if cgroups.IsCgroup2UnifiedMode() {
|
||||
return systemdCgroupV2(l, false)
|
||||
}
|
||||
|
||||
l.NewCgroupsManager = func(config *configs.Cgroup, paths map[string]string) cgroups.Manager {
|
||||
return systemd.NewLegacyManager(config, paths)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RootlessSystemdCgroups is rootless version of SystemdCgroups.
|
||||
func RootlessSystemdCgroups(l *LinuxFactory) error {
|
||||
if !systemd.IsRunningSystemd() {
|
||||
return fmt.Errorf("systemd not running on this host, can't use systemd as cgroups manager")
|
||||
}
|
||||
|
||||
if !cgroups.IsCgroup2UnifiedMode() {
|
||||
return fmt.Errorf("cgroup v2 not enabled on this host, can't use systemd (rootless) as cgroups manager")
|
||||
}
|
||||
return systemdCgroupV2(l, true)
|
||||
}
|
||||
|
||||
func cgroupfs2(l *LinuxFactory, rootless bool) error {
|
||||
l.NewCgroupsManager = func(config *configs.Cgroup, paths map[string]string) cgroups.Manager {
|
||||
m, err := fs2.NewManager(config, getUnifiedPath(paths), rootless)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return m
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func cgroupfs(l *LinuxFactory, rootless bool) error {
|
||||
if cgroups.IsCgroup2UnifiedMode() {
|
||||
return cgroupfs2(l, rootless)
|
||||
}
|
||||
l.NewCgroupsManager = func(config *configs.Cgroup, paths map[string]string) cgroups.Manager {
|
||||
return fs.NewManager(config, paths, rootless)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Cgroupfs is an options func to configure a LinuxFactory to return containers
|
||||
// that use the native cgroups filesystem implementation to create and manage
|
||||
// cgroups.
|
||||
func Cgroupfs(l *LinuxFactory) error {
|
||||
return cgroupfs(l, false)
|
||||
}
|
||||
|
||||
// RootlessCgroupfs is an options func to configure a LinuxFactory to return
|
||||
// containers that use the native cgroups filesystem implementation to create
|
||||
// and manage cgroups. The difference between RootlessCgroupfs and Cgroupfs is
|
||||
// that RootlessCgroupfs can transparently handle permission errors that occur
|
||||
// during rootless container (including euid=0 in userns) setup (while still allowing cgroup usage if
|
||||
// they've been set up properly).
|
||||
func RootlessCgroupfs(l *LinuxFactory) error {
|
||||
return cgroupfs(l, true)
|
||||
}
|
||||
|
||||
// IntelRdtfs is an options func to configure a LinuxFactory to return
|
||||
// containers that use the Intel RDT "resource control" filesystem to
|
||||
// create and manage Intel RDT resources (e.g., L3 cache, memory bandwidth).
|
||||
@@ -165,7 +69,7 @@ func TmpfsRoot(l *LinuxFactory) error {
|
||||
return err
|
||||
}
|
||||
if !mounted {
|
||||
if err := unix.Mount("tmpfs", l.Root, "tmpfs", 0, ""); err != nil {
|
||||
if err := mount("tmpfs", l.Root, "", "tmpfs", 0, ""); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -186,7 +90,7 @@ func CriuPath(criupath string) func(*LinuxFactory) error {
|
||||
func New(root string, options ...func(*LinuxFactory) error) (Factory, error) {
|
||||
if root != "" {
|
||||
if err := os.MkdirAll(root, 0o700); err != nil {
|
||||
return nil, newGenericError(err, SystemError)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
l := &LinuxFactory{
|
||||
@@ -197,10 +101,6 @@ func New(root string, options ...func(*LinuxFactory) error) (Factory, error) {
|
||||
CriuPath: "criu",
|
||||
}
|
||||
|
||||
if err := Cgroupfs(l); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, opt := range options {
|
||||
if opt == nil {
|
||||
continue
|
||||
@@ -237,37 +137,69 @@ type LinuxFactory struct {
|
||||
// Validator provides validation to container configurations.
|
||||
Validator validate.Validator
|
||||
|
||||
// NewCgroupsManager returns an initialized cgroups manager for a single container.
|
||||
NewCgroupsManager func(config *configs.Cgroup, paths map[string]string) cgroups.Manager
|
||||
|
||||
// NewIntelRdtManager returns an initialized Intel RDT manager for a single container.
|
||||
NewIntelRdtManager func(config *configs.Config, id string, path string) intelrdt.Manager
|
||||
}
|
||||
|
||||
func (l *LinuxFactory) Create(id string, config *configs.Config) (Container, error) {
|
||||
if l.Root == "" {
|
||||
return nil, newGenericError(fmt.Errorf("invalid root"), ConfigInvalid)
|
||||
return nil, errors.New("root not set")
|
||||
}
|
||||
if err := l.validateID(id); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := l.Validator.Validate(config); err != nil {
|
||||
return nil, newGenericError(err, ConfigInvalid)
|
||||
return nil, err
|
||||
}
|
||||
containerRoot, err := securejoin.SecureJoin(l.Root, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := os.Stat(containerRoot); err == nil {
|
||||
return nil, newGenericError(fmt.Errorf("container with id exists: %v", id), IdInUse)
|
||||
return nil, ErrExist
|
||||
} else if !os.IsNotExist(err) {
|
||||
return nil, newGenericError(err, SystemError)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cm, err := manager.New(config.Cgroups)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Check that cgroup does not exist or empty (no processes).
|
||||
// Note for cgroup v1 this check is not thorough, as there are multiple
|
||||
// separate hierarchies, while both Exists() and GetAllPids() only use
|
||||
// one for "devices" controller (assuming others are the same, which is
|
||||
// probably true in almost all scenarios). Checking all the hierarchies
|
||||
// would be too expensive.
|
||||
if cm.Exists() {
|
||||
pids, err := cm.GetAllPids()
|
||||
// Reading PIDs can race with cgroups removal, so ignore ENOENT and ENODEV.
|
||||
if err != nil && !errors.Is(err, os.ErrNotExist) && !errors.Is(err, unix.ENODEV) {
|
||||
return nil, fmt.Errorf("unable to get cgroup PIDs: %w", err)
|
||||
}
|
||||
if len(pids) != 0 {
|
||||
// TODO: return an error.
|
||||
logrus.Warnf("container's cgroup is not empty: %d process(es) found", len(pids))
|
||||
logrus.Warn("DEPRECATED: running container in a non-empty cgroup won't be supported in runc 1.2; https://github.com/opencontainers/runc/issues/3132")
|
||||
}
|
||||
}
|
||||
|
||||
// Check that cgroup is not frozen. Do not use Exists() here
|
||||
// since in cgroup v1 it only checks "devices" controller.
|
||||
st, err := cm.GetFreezerState()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to get cgroup freezer state: %w", err)
|
||||
}
|
||||
if st == configs.Frozen {
|
||||
return nil, errors.New("container's cgroup unexpectedly frozen")
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(containerRoot, 0o711); err != nil {
|
||||
return nil, newGenericError(err, SystemError)
|
||||
return nil, err
|
||||
}
|
||||
if err := os.Chown(containerRoot, unix.Geteuid(), unix.Getegid()); err != nil {
|
||||
return nil, newGenericError(err, SystemError)
|
||||
return nil, err
|
||||
}
|
||||
c := &linuxContainer{
|
||||
id: id,
|
||||
@@ -278,7 +210,7 @@ func (l *LinuxFactory) Create(id string, config *configs.Config) (Container, err
|
||||
criuPath: l.CriuPath,
|
||||
newuidmapPath: l.NewuidmapPath,
|
||||
newgidmapPath: l.NewgidmapPath,
|
||||
cgroupManager: l.NewCgroupsManager(config.Cgroups, nil),
|
||||
cgroupManager: cm,
|
||||
}
|
||||
if l.NewIntelRdtManager != nil {
|
||||
c.intelRdtManager = l.NewIntelRdtManager(config, id, "")
|
||||
@@ -289,7 +221,7 @@ func (l *LinuxFactory) Create(id string, config *configs.Config) (Container, err
|
||||
|
||||
func (l *LinuxFactory) Load(id string) (Container, error) {
|
||||
if l.Root == "" {
|
||||
return nil, newGenericError(fmt.Errorf("invalid root"), ConfigInvalid)
|
||||
return nil, errors.New("root not set")
|
||||
}
|
||||
// when load, we need to check id is valid or not.
|
||||
if err := l.validateID(id); err != nil {
|
||||
@@ -299,7 +231,7 @@ func (l *LinuxFactory) Load(id string) (Container, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
state, err := l.loadState(containerRoot, id)
|
||||
state, err := l.loadState(containerRoot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -308,6 +240,10 @@ func (l *LinuxFactory) Load(id string) (Container, error) {
|
||||
processStartTime: state.InitProcessStartTime,
|
||||
fds: state.ExternalDescriptors,
|
||||
}
|
||||
cm, err := manager.NewWithPaths(state.Config.Cgroups, state.CgroupPaths)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c := &linuxContainer{
|
||||
initProcess: r,
|
||||
initProcessStartTime: state.InitProcessStartTime,
|
||||
@@ -318,7 +254,7 @@ func (l *LinuxFactory) Load(id string) (Container, error) {
|
||||
criuPath: l.CriuPath,
|
||||
newuidmapPath: l.NewuidmapPath,
|
||||
newgidmapPath: l.NewgidmapPath,
|
||||
cgroupManager: l.NewCgroupsManager(state.Config.Cgroups, state.CgroupPaths),
|
||||
cgroupManager: cm,
|
||||
root: containerRoot,
|
||||
created: state.Created,
|
||||
}
|
||||
@@ -343,11 +279,26 @@ func (l *LinuxFactory) StartInitialization() (err error) {
|
||||
envInitPipe := os.Getenv("_LIBCONTAINER_INITPIPE")
|
||||
pipefd, err := strconv.Atoi(envInitPipe)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to convert _LIBCONTAINER_INITPIPE=%s to int: %s", envInitPipe, err)
|
||||
err = fmt.Errorf("unable to convert _LIBCONTAINER_INITPIPE: %w", err)
|
||||
logrus.Error(err)
|
||||
return err
|
||||
}
|
||||
pipe := os.NewFile(uintptr(pipefd), "pipe")
|
||||
defer pipe.Close()
|
||||
|
||||
defer func() {
|
||||
// We have an error during the initialization of the container's init,
|
||||
// send it back to the parent process in the form of an initError.
|
||||
if werr := writeSync(pipe, procError); werr != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return
|
||||
}
|
||||
if werr := utils.WriteJSON(pipe, &initError{Message: err.Error()}); werr != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
// Only init processes have FIFOFD.
|
||||
fifofd := -1
|
||||
envInitType := os.Getenv("_LIBCONTAINER_INITTYPE")
|
||||
@@ -355,7 +306,7 @@ func (l *LinuxFactory) StartInitialization() (err error) {
|
||||
if it == initStandard {
|
||||
envFifoFd := os.Getenv("_LIBCONTAINER_FIFOFD")
|
||||
if fifofd, err = strconv.Atoi(envFifoFd); err != nil {
|
||||
return fmt.Errorf("unable to convert _LIBCONTAINER_FIFOFD=%s to int: %s", envFifoFd, err)
|
||||
return fmt.Errorf("unable to convert _LIBCONTAINER_FIFOFD: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -363,7 +314,7 @@ func (l *LinuxFactory) StartInitialization() (err error) {
|
||||
if envConsole := os.Getenv("_LIBCONTAINER_CONSOLE"); envConsole != "" {
|
||||
console, err := strconv.Atoi(envConsole)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to convert _LIBCONTAINER_CONSOLE=%s to int: %s", envConsole, err)
|
||||
return fmt.Errorf("unable to convert _LIBCONTAINER_CONSOLE: %w", err)
|
||||
}
|
||||
consoleSocket = os.NewFile(uintptr(console), "console-socket")
|
||||
defer consoleSocket.Close()
|
||||
@@ -372,32 +323,26 @@ func (l *LinuxFactory) StartInitialization() (err error) {
|
||||
logPipeFdStr := os.Getenv("_LIBCONTAINER_LOGPIPE")
|
||||
logPipeFd, err := strconv.Atoi(logPipeFdStr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to convert _LIBCONTAINER_LOGPIPE=%s to int: %s", logPipeFdStr, err)
|
||||
return fmt.Errorf("unable to convert _LIBCONTAINER_LOGPIPE: %w", err)
|
||||
}
|
||||
|
||||
// Get mount files (O_PATH).
|
||||
mountFds, err := parseMountFds()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// clear the current process's environment to clean any libcontainer
|
||||
// specific env vars.
|
||||
os.Clearenv()
|
||||
|
||||
defer func() {
|
||||
// We have an error during the initialization of the container's init,
|
||||
// send it back to the parent process in the form of an initError.
|
||||
if werr := utils.WriteJSON(pipe, syncT{procError}); werr != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return
|
||||
}
|
||||
if werr := utils.WriteJSON(pipe, newSystemError(err)); werr != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
err = fmt.Errorf("panic from initialization: %v, %v", e, string(debug.Stack()))
|
||||
err = fmt.Errorf("panic from initialization: %w, %v", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
|
||||
i, err := newContainerInit(it, pipe, consoleSocket, fifofd, logPipeFd)
|
||||
i, err := newContainerInit(it, pipe, consoleSocket, fifofd, logPipeFd, mountFds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -406,7 +351,7 @@ func (l *LinuxFactory) StartInitialization() (err error) {
|
||||
return i.Init()
|
||||
}
|
||||
|
||||
func (l *LinuxFactory) loadState(root, id string) (*State, error) {
|
||||
func (l *LinuxFactory) loadState(root string) (*State, error) {
|
||||
stateFilePath, err := securejoin.SecureJoin(root, stateFilename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -414,21 +359,21 @@ func (l *LinuxFactory) loadState(root, id string) (*State, error) {
|
||||
f, err := os.Open(stateFilePath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, newGenericError(fmt.Errorf("container %q does not exist", id), ContainerNotExists)
|
||||
return nil, ErrNotExist
|
||||
}
|
||||
return nil, newGenericError(err, SystemError)
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
var state *State
|
||||
if err := json.NewDecoder(f).Decode(&state); err != nil {
|
||||
return nil, newGenericError(err, SystemError)
|
||||
return nil, err
|
||||
}
|
||||
return state, nil
|
||||
}
|
||||
|
||||
func (l *LinuxFactory) validateID(id string) error {
|
||||
if !idRegex.MatchString(id) || string(os.PathSeparator)+id != utils.CleanPath(string(os.PathSeparator)+id) {
|
||||
return newGenericError(fmt.Errorf("invalid id format: %v", id), InvalidIdFormat)
|
||||
return ErrInvalidID
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -451,3 +396,18 @@ func NewgidmapPath(newgidmapPath string) func(*LinuxFactory) error {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func parseMountFds() ([]int, error) {
|
||||
fdsJson := os.Getenv("_LIBCONTAINER_MOUNT_FDS")
|
||||
if fdsJson == "" {
|
||||
// Always return the nil slice if no fd is present.
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var mountFds []int
|
||||
if err := json.Unmarshal([]byte(fdsJson), &mountFds); err != nil {
|
||||
return nil, fmt.Errorf("Error unmarshalling _LIBCONTAINER_MOUNT_FDS: %w", err)
|
||||
}
|
||||
|
||||
return mountFds, nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user