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:
Elana Hashman
2022-03-28 11:32:04 -07:00
parent 41830a1f79
commit 07af1bab70
245 changed files with 6520 additions and 5250 deletions

View File

@@ -1,30 +1,29 @@
// +build linux
package libcontainer
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"net"
"os"
"strconv"
"strings"
"unsafe"
"github.com/containerd/console"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/sirupsen/logrus"
"github.com/vishvananda/netlink"
"golang.org/x/sys/unix"
"github.com/opencontainers/runc/libcontainer/capabilities"
"github.com/opencontainers/runc/libcontainer/cgroups"
"github.com/opencontainers/runc/libcontainer/configs"
"github.com/opencontainers/runc/libcontainer/system"
"github.com/opencontainers/runc/libcontainer/user"
"github.com/opencontainers/runc/libcontainer/utils"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/vishvananda/netlink"
"golang.org/x/sys/unix"
)
type initType string
@@ -77,7 +76,7 @@ type initer interface {
Init() error
}
func newContainerInit(t initType, pipe *os.File, consoleSocket *os.File, fifoFd, logFd int) (initer, error) {
func newContainerInit(t initType, pipe *os.File, consoleSocket *os.File, fifoFd, logFd int, mountFds []int) (initer, error) {
var config *initConfig
if err := json.NewDecoder(pipe).Decode(&config); err != nil {
return nil, err
@@ -87,6 +86,11 @@ func newContainerInit(t initType, pipe *os.File, consoleSocket *os.File, fifoFd,
}
switch t {
case initSetns:
// mountFds must be nil in this case. We don't mount while doing runc exec.
if mountFds != nil {
return nil, errors.New("mountFds must be nil. Can't mount while doing runc exec.")
}
return &linuxSetnsInit{
pipe: pipe,
consoleSocket: consoleSocket,
@@ -101,6 +105,7 @@ func newContainerInit(t initType, pipe *os.File, consoleSocket *os.File, fifoFd,
config: config,
fifoFd: fifoFd,
logFd: logFd,
mountFds: mountFds,
}, nil
}
return nil, fmt.Errorf("unknown init type %q", t)
@@ -139,7 +144,7 @@ func finalizeNamespace(config *initConfig) error {
// inherited are marked close-on-exec so they stay out of the
// container
if err := utils.CloseExecFrom(config.PassedFilesCount + 3); err != nil {
return errors.Wrap(err, "close exec fds")
return fmt.Errorf("error closing exec fds: %w", err)
}
// we only do chdir if it's specified
@@ -158,7 +163,7 @@ func finalizeNamespace(config *initConfig) error {
// to the directory, but the user running runc does not.
// This is useful in cases where the cwd is also a volume that's been chowned to the container user.
default:
return fmt.Errorf("chdir to cwd (%q) set in config.json failed: %v", config.Cwd, err)
return fmt.Errorf("chdir to cwd (%q) set in config.json failed: %w", config.Cwd, err)
}
}
@@ -174,26 +179,26 @@ func finalizeNamespace(config *initConfig) error {
}
// drop capabilities in bounding set before changing user
if err := w.ApplyBoundingSet(); err != nil {
return errors.Wrap(err, "apply bounding set")
return fmt.Errorf("unable to apply bounding set: %w", err)
}
// preserve existing capabilities while we change users
if err := system.SetKeepCaps(); err != nil {
return errors.Wrap(err, "set keep caps")
return fmt.Errorf("unable to set keep caps: %w", err)
}
if err := setupUser(config); err != nil {
return errors.Wrap(err, "setup user")
return fmt.Errorf("unable to setup user: %w", err)
}
// Change working directory AFTER the user has been set up, if we haven't done it yet.
if doChdir {
if err := unix.Chdir(config.Cwd); err != nil {
return fmt.Errorf("chdir to cwd (%q) set in config.json failed: %v", config.Cwd, err)
return fmt.Errorf("chdir to cwd (%q) set in config.json failed: %w", config.Cwd, err)
}
}
if err := system.ClearKeepCaps(); err != nil {
return errors.Wrap(err, "clear keep caps")
return fmt.Errorf("unable to clear keep caps: %w", err)
}
if err := w.ApplyCaps(); err != nil {
return errors.Wrap(err, "apply caps")
return fmt.Errorf("unable to apply caps: %w", err)
}
return nil
}
@@ -272,6 +277,36 @@ func syncParentHooks(pipe io.ReadWriter) error {
return readSync(pipe, procResume)
}
// syncParentSeccomp sends to the given pipe a JSON payload which
// indicates that the parent should pick up the seccomp fd with pidfd_getfd()
// and send it to the seccomp agent over a unix socket. It then waits for
// the parent to indicate that it is cleared to resume and closes the seccompFd.
// If the seccompFd is -1, there isn't anything to sync with the parent, so it
// returns no error.
func syncParentSeccomp(pipe io.ReadWriter, seccompFd int) error {
if seccompFd == -1 {
return nil
}
// Tell parent.
if err := writeSyncWithFd(pipe, procSeccomp, seccompFd); err != nil {
unix.Close(seccompFd)
return err
}
// Wait for parent to give the all-clear.
if err := readSync(pipe, procSeccompDone); err != nil {
unix.Close(seccompFd)
return fmt.Errorf("sync parent seccomp: %w", err)
}
if err := unix.Close(seccompFd); err != nil {
return fmt.Errorf("close seccomp fd: %w", err)
}
return nil
}
// setupUser changes the groups, gid, and uid for the user inside the container
func setupUser(config *initConfig) error {
// Set up defaults.
@@ -325,11 +360,11 @@ func setupUser(config *initConfig) error {
// Before we change to the container's user make sure that the processes
// STDIO is correctly owned by the user that we are switching to.
if err := fixStdioPermissions(config, execUser); err != nil {
if err := fixStdioPermissions(execUser); err != nil {
return err
}
setgroups, err := ioutil.ReadFile("/proc/self/setgroups")
setgroups, err := os.ReadFile("/proc/self/setgroups")
if err != nil && !os.IsNotExist(err) {
return err
}
@@ -343,7 +378,7 @@ func setupUser(config *initConfig) error {
if allowSupGroups {
suppGroups := append(execUser.Sgids, addGroups...)
if err := unix.Setgroups(suppGroups); err != nil {
return err
return &os.SyscallError{Syscall: "setgroups", Err: err}
}
}
@@ -366,10 +401,10 @@ func setupUser(config *initConfig) error {
// fixStdioPermissions fixes the permissions of PID 1's STDIO within the container to the specified user.
// The ownership needs to match because it is created outside of the container and needs to be
// localized.
func fixStdioPermissions(config *initConfig, u *user.ExecUser) error {
func fixStdioPermissions(u *user.ExecUser) error {
var null unix.Stat_t
if err := unix.Stat("/dev/null", &null); err != nil {
return err
return &os.PathError{Op: "stat", Path: "/dev/null", Err: err}
}
for _, fd := range []uintptr{
os.Stdin.Fd(),
@@ -378,7 +413,7 @@ func fixStdioPermissions(config *initConfig, u *user.ExecUser) error {
} {
var s unix.Stat_t
if err := unix.Fstat(int(fd), &s); err != nil {
return err
return &os.PathError{Op: "fstat", Path: "fd " + strconv.Itoa(int(fd)), Err: err}
}
// Skip chown of /dev/null if it was used as one of the STDIO fds.
@@ -399,10 +434,12 @@ func fixStdioPermissions(config *initConfig, u *user.ExecUser) error {
// privileged_wrt_inode_uidgid() has failed). In either case, we
// are in a configuration where it's better for us to just not
// touch the stdio rather than bail at this point.
// nolint:errorlint // unix errors are bare
if err == unix.EINVAL || err == unix.EPERM {
continue
}
return err
return &os.PathError{Op: "fchown", Path: "fd " + strconv.Itoa(int(fd)), Err: err}
}
}
return nil
@@ -456,8 +493,8 @@ func setupRoute(config *configs.Config) error {
func setupRlimits(limits []configs.Rlimit, pid int) error {
for _, rlimit := range limits {
if err := system.Prlimit(pid, rlimit.Type, unix.Rlimit{Max: rlimit.Hard, Cur: rlimit.Soft}); err != nil {
return fmt.Errorf("error setting rlimit type %v: %v", rlimit.Type, err)
if err := unix.Prlimit(pid, rlimit.Type, &unix.Rlimit{Max: rlimit.Hard, Cur: rlimit.Soft}, nil); err != nil {
return fmt.Errorf("error setting rlimit type %v: %w", rlimit.Type, err)
}
}
return nil
@@ -482,27 +519,12 @@ func isWaitable(pid int) (bool, error) {
si := &siginfo{}
_, _, e := unix.Syscall6(unix.SYS_WAITID, _P_PID, uintptr(pid), uintptr(unsafe.Pointer(si)), unix.WEXITED|unix.WNOWAIT|unix.WNOHANG, 0, 0)
if e != 0 {
return false, os.NewSyscallError("waitid", e)
return false, &os.SyscallError{Syscall: "waitid", Err: e}
}
return si.si_pid != 0, nil
}
// isNoChildren returns true if err represents a unix.ECHILD (formerly syscall.ECHILD) false otherwise
func isNoChildren(err error) bool {
switch err := err.(type) {
case unix.Errno:
if err == unix.ECHILD {
return true
}
case *os.SyscallError:
if err.Err == unix.ECHILD {
return true
}
}
return false
}
// signalAllProcesses freezes then iterates over all the processes inside the
// manager's cgroups sending the signal s to them.
// If s is SIGKILL then it will wait for each process to exit.
@@ -548,7 +570,7 @@ func signalAllProcesses(m cgroups.Manager, s os.Signal) error {
for _, p := range procs {
if s != unix.SIGKILL {
if ok, err := isWaitable(p.Pid); err != nil {
if !isNoChildren(err) {
if !errors.Is(err, unix.ECHILD) {
logrus.Warn("signalAllProcesses: ", p.Pid, err)
}
continue
@@ -565,7 +587,7 @@ func signalAllProcesses(m cgroups.Manager, s os.Signal) error {
// to retrieve its exit code.
if subreaper == 0 {
if _, err := p.Wait(); err != nil {
if !isNoChildren(err) {
if !errors.Is(err, unix.ECHILD) {
logrus.Warn("wait: ", err)
}
}