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:
110
vendor/github.com/opencontainers/runc/libcontainer/init_linux.go
generated
vendored
110
vendor/github.com/opencontainers/runc/libcontainer/init_linux.go
generated
vendored
@@ -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)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user