Vendor in new opencontainers/selinux

Also update vendor of containers/common,buildah,storage,image

Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2069586

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
Daniel J Walsh
2022-03-29 07:31:23 -04:00
parent f838333b7e
commit dc17195bd9
62 changed files with 1229 additions and 616 deletions

View File

@@ -12,6 +12,7 @@ import (
"net"
"os"
"os/exec"
"os/signal"
"path/filepath"
"runtime"
"strconv"
@@ -43,6 +44,7 @@ import (
"github.com/containers/storage"
"github.com/containers/storage/pkg/idtools"
"github.com/containers/storage/pkg/ioutils"
"github.com/containers/storage/pkg/lockfile"
"github.com/containers/storage/pkg/reexec"
"github.com/containers/storage/pkg/stringid"
"github.com/containers/storage/pkg/unshare"
@@ -190,16 +192,19 @@ func (b *Builder) Run(command []string, options RunOptions) error {
return err
}
// Figure out who owns files that will appear to be owned by UID/GID 0 in the container.
rootUID, rootGID, err := util.GetHostRootIDs(spec)
if err != nil {
return err
uid, gid := spec.Process.User.UID, spec.Process.User.GID
if spec.Linux != nil {
uid, gid, err = util.GetHostIDs(spec.Linux.UIDMappings, spec.Linux.GIDMappings, uid, gid)
if err != nil {
return err
}
}
rootIDPair := &idtools.IDPair{UID: int(rootUID), GID: int(rootGID)}
idPair := &idtools.IDPair{UID: int(uid), GID: int(gid)}
mode := os.FileMode(0755)
coptions := copier.MkdirOptions{
ChownNew: rootIDPair,
ChownNew: idPair,
ChmodNew: &mode,
}
if err := copier.Mkdir(mountPoint, filepath.Join(mountPoint, spec.Process.Cwd), coptions); err != nil {
@@ -210,6 +215,13 @@ func (b *Builder) Run(command []string, options RunOptions) error {
namespaceOptions := append(b.NamespaceOptions, options.NamespaceOptions...)
volumes := b.Volumes()
// Figure out who owns files that will appear to be owned by UID/GID 0 in the container.
rootUID, rootGID, err := util.GetHostRootIDs(spec)
if err != nil {
return err
}
rootIDPair := &idtools.IDPair{UID: int(rootUID), GID: int(rootGID)}
if !options.NoHosts && !contains(volumes, "/etc/hosts") {
hostFile, err := b.generateHosts(path, spec.Hostname, b.CommonBuildOpts.AddHost, rootIDPair)
if err != nil {
@@ -243,7 +255,7 @@ func (b *Builder) Run(command []string, options RunOptions) error {
rootless = 1
}
// Populate the .containerenv with container information
containerenv := fmt.Sprintf(`\
containerenv := fmt.Sprintf(`
engine="buildah-%s"
name=%q
id=%q
@@ -289,9 +301,7 @@ rootless=%d
case define.IsolationOCI:
var moreCreateArgs []string
if options.NoPivot {
moreCreateArgs = []string{"--no-pivot"}
} else {
moreCreateArgs = nil
moreCreateArgs = append(moreCreateArgs, "--no-pivot")
}
err = b.runUsingRuntimeSubproc(isolation, options, configureNetwork, configureNetworks, moreCreateArgs, spec, mountPoint, path, define.Package+"-"+filepath.Base(path))
case IsolationChroot:
@@ -828,7 +838,7 @@ func runUsingRuntime(options RunOptions, configureNetwork bool, moreCreateArgs [
if err = unix.Pipe(finishCopy); err != nil {
return 1, errors.Wrapf(err, "error creating pipe for notifying to stop stdio")
}
finishedCopy := make(chan struct{})
finishedCopy := make(chan struct{}, 1)
var pargs []string
if spec.Process != nil {
pargs = spec.Process.Args
@@ -884,22 +894,27 @@ func runUsingRuntime(options RunOptions, configureNetwork bool, moreCreateArgs [
pidFile := filepath.Join(bundlePath, "pid")
args := append(append(append(runtimeArgs, "create", "--bundle", bundlePath, "--pid-file", pidFile), moreCreateArgs...), containerName)
create := exec.Command(runtime, args...)
setPdeathsig(create)
create.Dir = bundlePath
stdin, stdout, stderr := getCreateStdio()
create.Stdin, create.Stdout, create.Stderr = stdin, stdout, stderr
if create.SysProcAttr == nil {
create.SysProcAttr = &syscall.SysProcAttr{}
}
args = append(options.Args, "start", containerName)
start := exec.Command(runtime, args...)
setPdeathsig(start)
start.Dir = bundlePath
start.Stderr = os.Stderr
args = append(options.Args, "kill", containerName)
kill := exec.Command(runtime, args...)
kill.Dir = bundlePath
kill.Stderr = os.Stderr
kill := func(signal string) *exec.Cmd {
args := append(options.Args, "kill", containerName)
if signal != "" {
args = append(args, signal)
}
kill := exec.Command(runtime, args...)
kill.Dir = bundlePath
kill.Stderr = os.Stderr
return kill
}
args = append(options.Args, "delete", containerName)
del := exec.Command(runtime, args...)
@@ -980,13 +995,23 @@ func runUsingRuntime(options RunOptions, configureNetwork bool, moreCreateArgs [
}
defer func() {
if atomic.LoadUint32(&stopped) == 0 {
if err2 := kill.Run(); err2 != nil {
options.Logger.Infof("error from %s stopping container: %v", runtime, err2)
if err := kill("").Run(); err != nil {
options.Logger.Infof("error from %s stopping container: %v", runtime, err)
}
atomic.StoreUint32(&stopped, 1)
}
}()
// Wait for the container to exit.
interrupted := make(chan os.Signal, 100)
go func() {
for range interrupted {
if err := kill("SIGKILL").Run(); err != nil {
logrus.Errorf("%v sending SIGKILL", err)
}
}
}()
signal.Notify(interrupted, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM)
for {
now := time.Now()
var state specs.State
@@ -1025,6 +1050,8 @@ func runUsingRuntime(options RunOptions, configureNetwork bool, moreCreateArgs [
break
}
}
signal.Stop(interrupted)
close(interrupted)
// Close the writing end of the stop-handling-stdio notification pipe.
unix.Close(finishCopy[1])
@@ -1111,6 +1138,7 @@ func setupRootlessNetwork(pid int) (teardown func(), err error) {
}
cmd := exec.Command(slirp4netns, "--mtu", "65520", "-r", "3", "-c", strconv.Itoa(pid), "tap0")
setPdeathsig(cmd)
cmd.Stdin, cmd.Stdout, cmd.Stderr = nil, nil, nil
cmd.ExtraFiles = []*os.File{rootlessSlirpSyncW}
@@ -1228,6 +1256,7 @@ func runCopyStdio(logger *logrus.Logger, stdio *sync.WaitGroup, copyPipes bool,
}
stdio.Done()
finishedCopy <- struct{}{}
close(finishedCopy)
}()
// Map describing where data on an incoming descriptor should go.
relayMap := make(map[int]int)
@@ -1964,9 +1993,6 @@ func setupCapAdd(g *generate.Generator, caps ...string) error {
if err := g.AddProcessCapabilityEffective(cap); err != nil {
return errors.Wrapf(err, "error adding %q to the effective capability set", cap)
}
if err := g.AddProcessCapabilityInheritable(cap); err != nil {
return errors.Wrapf(err, "error adding %q to the inheritable capability set", cap)
}
if err := g.AddProcessCapabilityPermitted(cap); err != nil {
return errors.Wrapf(err, "error adding %q to the permitted capability set", cap)
}
@@ -1985,9 +2011,6 @@ func setupCapDrop(g *generate.Generator, caps ...string) error {
if err := g.DropProcessCapabilityEffective(cap); err != nil {
return errors.Wrapf(err, "error removing %q from the effective capability set", cap)
}
if err := g.DropProcessCapabilityInheritable(cap); err != nil {
return errors.Wrapf(err, "error removing %q from the inheritable capability set", cap)
}
if err := g.DropProcessCapabilityPermitted(cap); err != nil {
return errors.Wrapf(err, "error removing %q from the permitted capability set", cap)
}
@@ -2232,6 +2255,7 @@ func (b *Builder) runUsingRuntimeSubproc(isolation define.Isolation, options Run
return errors.Wrapf(conferr, "error encoding configuration for %q", runUsingRuntimeCommand)
}
cmd := reexec.Command(runUsingRuntimeCommand)
setPdeathsig(cmd)
cmd.Dir = bundlePath
cmd.Stdin = options.Stdin
if cmd.Stdin == nil {
@@ -2260,23 +2284,23 @@ func (b *Builder) runUsingRuntimeSubproc(isolation define.Isolation, options Run
}()
// create network configuration pipes
var containerCreateR, containerCreateW *os.File
var containerStartR, containerStartW *os.File
var containerCreateR, containerCreateW fileCloser
var containerStartR, containerStartW fileCloser
if configureNetwork {
containerCreateR, containerCreateW, err = os.Pipe()
containerCreateR.file, containerCreateW.file, err = os.Pipe()
if err != nil {
return errors.Wrapf(err, "error creating container create pipe")
}
defer containerCreateR.Close()
defer containerCreateW.Close()
containerStartR, containerStartW, err = os.Pipe()
containerStartR.file, containerStartW.file, err = os.Pipe()
if err != nil {
return errors.Wrapf(err, "error creating container create pipe")
}
defer containerStartR.Close()
defer containerStartW.Close()
cmd.ExtraFiles = []*os.File{containerCreateW, containerStartR}
cmd.ExtraFiles = []*os.File{containerCreateW.file, containerStartR.file}
}
cmd.ExtraFiles = append([]*os.File{preader}, cmd.ExtraFiles...)
@@ -2286,8 +2310,20 @@ func (b *Builder) runUsingRuntimeSubproc(isolation define.Isolation, options Run
return errors.Wrapf(err, "error while starting runtime")
}
interrupted := make(chan os.Signal, 100)
go func() {
for receivedSignal := range interrupted {
if err := cmd.Process.Signal(receivedSignal); err != nil {
logrus.Infof("%v while attempting to forward %v to child process", err, receivedSignal)
}
}
}()
signal.Notify(interrupted, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM)
if configureNetwork {
if err := waitForSync(containerCreateR); err != nil {
// we already passed the fd to the child, now close the writer so we do not hang if the child closes it
containerCreateW.Close()
if err := waitForSync(containerCreateR.file); err != nil {
// we do not want to return here since we want to capture the exit code from the child via cmd.Wait()
// close the pipes here so that the child will not hang forever
containerCreateR.Close()
@@ -2313,16 +2349,19 @@ func (b *Builder) runUsingRuntimeSubproc(isolation define.Isolation, options Run
}
logrus.Debug("network namespace successfully setup, send start message to child")
_, err = containerStartW.Write([]byte{1})
_, err = containerStartW.file.Write([]byte{1})
if err != nil {
return err
}
}
}
if err := cmd.Wait(); err != nil {
return errors.Wrapf(err, "error while running runtime")
}
confwg.Wait()
signal.Stop(interrupted)
close(interrupted)
if err == nil {
return conferr
}
@@ -2332,9 +2371,25 @@ func (b *Builder) runUsingRuntimeSubproc(isolation define.Isolation, options Run
return err
}
// waitForSync waits for a maximum of 5 seconds to read something from the file
// fileCloser is a helper struct to prevent closing the file twice in the code
// users must call (fileCloser).Close() and not fileCloser.File.Close()
type fileCloser struct {
file *os.File
closed bool
}
func (f *fileCloser) Close() {
if !f.closed {
if err := f.file.Close(); err != nil {
logrus.Errorf("failed to close file: %v", err)
}
f.closed = true
}
}
// waitForSync waits for a maximum of 4 minutes to read something from the file
func waitForSync(pipeR *os.File) error {
if err := pipeR.SetDeadline(time.Now().Add(5 * time.Second)); err != nil {
if err := pipeR.SetDeadline(time.Now().Add(4 * time.Minute)); err != nil {
return err
}
b := make([]byte, 16)
@@ -2448,6 +2503,7 @@ func (b *Builder) runSetupRunMounts(context *imagetypes.SystemContext, mounts []
sshCount := 0
defaultSSHSock := ""
tokens := []string{}
lockedTargets := []string{}
for _, mount := range mounts {
arr := strings.SplitN(mount, ",", 2)
@@ -2506,12 +2562,13 @@ func (b *Builder) runSetupRunMounts(context *imagetypes.SystemContext, mounts []
finalMounts = append(finalMounts, *mount)
mountTargets = append(mountTargets, mount.Destination)
case "cache":
mount, err := b.getCacheMount(tokens, rootUID, rootGID, processUID, processGID, stageMountPoints)
mount, lockedPaths, err := b.getCacheMount(tokens, rootUID, rootGID, processUID, processGID, stageMountPoints)
if err != nil {
return nil, nil, err
}
finalMounts = append(finalMounts, *mount)
mountTargets = append(mountTargets, mount.Destination)
lockedTargets = lockedPaths
default:
return nil, nil, errors.Errorf("invalid mount type %q", kv[1])
}
@@ -2522,6 +2579,7 @@ func (b *Builder) runSetupRunMounts(context *imagetypes.SystemContext, mounts []
Agents: agents,
MountedImages: mountImages,
SSHAuthSock: defaultSSHSock,
LockedTargets: lockedTargets,
}
return finalMounts, artifacts, nil
}
@@ -2557,18 +2615,18 @@ func (b *Builder) getTmpfsMount(tokens []string, rootUID, rootGID, processUID, p
return &volumes[0], nil
}
func (b *Builder) getCacheMount(tokens []string, rootUID, rootGID, processUID, processGID int, stageMountPoints map[string]internal.StageMountDetails) (*spec.Mount, error) {
func (b *Builder) getCacheMount(tokens []string, rootUID, rootGID, processUID, processGID int, stageMountPoints map[string]internal.StageMountDetails) (*spec.Mount, []string, error) {
var optionMounts []specs.Mount
mount, err := internalParse.GetCacheMount(tokens, b.store, b.MountLabel, stageMountPoints)
mount, lockedTargets, err := internalParse.GetCacheMount(tokens, b.store, b.MountLabel, stageMountPoints)
if err != nil {
return nil, err
return nil, lockedTargets, err
}
optionMounts = append(optionMounts, mount)
volumes, err := b.runSetupVolumeMounts(b.MountLabel, nil, optionMounts, rootUID, rootGID, processUID, processGID)
if err != nil {
return nil, err
return nil, lockedTargets, err
}
return &volumes[0], nil
return &volumes[0], lockedTargets, nil
}
func getSecretMount(tokens []string, secrets map[string]define.Secret, mountlabel string, containerWorkingDir string, uidmap []spec.LinuxIDMapping, gidmap []spec.LinuxIDMapping) (*spec.Mount, string, error) {
@@ -2850,6 +2908,32 @@ func (b *Builder) cleanupRunMounts(context *imagetypes.SystemContext, mountpoint
prevErr = err
}
}
// unlock if any locked files from this RUN statement
for _, path := range artifacts.LockedTargets {
_, err := os.Stat(path)
if err != nil {
// Lockfile not found this might be a problem,
// since LockedTargets must contain list of all locked files
// don't break here since we need to unlock other files but
// log so user can take a look
logrus.Warnf("Lockfile %q was expected here, stat failed with %v", path, err)
continue
}
lockfile, err := lockfile.GetLockfile(path)
if err != nil {
// unable to get lockfile
// lets log error and continue
// unlocking other files
logrus.Warn(err)
continue
}
if lockfile.Locked() {
lockfile.Unlock()
} else {
logrus.Warnf("Lockfile %q was expected to be locked, this is unexpected", path)
continue
}
}
return prevErr
}
@@ -2875,3 +2959,11 @@ func getNetworkInterface(store storage.Store, cniConfDir, cniPluginPath string)
}
return netInt, nil
}
// setPdeathsig sets a parent-death signal for the process
func setPdeathsig(cmd *exec.Cmd) {
if cmd.SysProcAttr == nil {
cmd.SysProcAttr = &syscall.SysProcAttr{}
}
cmd.SysProcAttr.Pdeathsig = syscall.SIGKILL
}