mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-12 09:46:25 +08:00
9d8fa6d695
Because runc-dmz is not checked into Git, go get will end up creating a copy of libcontainer/dmz with no runc-dmz binary, which causes external libcontainer users to have compilation errors. Unfortunately, we cannot get go:embed to just ignore that there are no files matching the provided pattern, so instead we need to create a dummy file that matches the go:embed (which we check into Git and so go get _will_ copy) and switch to embed.FS. This is a little bit uglier, but at least it will fix external libcontainer users. Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
68 lines
2.1 KiB
Go
68 lines
2.1 KiB
Go
//go:build !runc_nodmz
|
|
// +build !runc_nodmz
|
|
|
|
package dmz
|
|
|
|
import (
|
|
"bytes"
|
|
"debug/elf"
|
|
"embed"
|
|
"os"
|
|
"sync"
|
|
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// Try to build the runc-dmz binary on "go generate". If it fails (or
|
|
// libcontainer is being imported as a library), the embed.FS will not contain
|
|
// the file, which will then cause us to fall back to a clone of
|
|
// /proc/self/exe.
|
|
//
|
|
// There is an empty file called dummy-file.txt in libcontainer/dmz/binary in
|
|
// order to work around the restriction that go:embed requires at least one
|
|
// file to match the pattern.
|
|
//
|
|
//go:generate make -B binary/runc-dmz
|
|
//go:embed binary
|
|
var runcDmzFs embed.FS
|
|
|
|
// A cached copy of the contents of runc-dmz.
|
|
var (
|
|
runcDmzBinaryOnce sync.Once
|
|
runcDmzBinaryIsValid bool
|
|
runcDmzBinary []byte
|
|
)
|
|
|
|
// Binary returns a cloned copy (see CloneBinary) of a very minimal C program
|
|
// that just does an execve() of its arguments. This is used in the final
|
|
// execution step of the container execution as an intermediate process before
|
|
// the container process is execve'd. This allows for protection against
|
|
// CVE-2019-5736 without requiring a complete copy of the runc binary. Each
|
|
// call to Binary will return a new copy.
|
|
//
|
|
// If the runc-dmz binary is not embedded into the runc binary, Binary will
|
|
// return ErrNoDmzBinary as the error.
|
|
func Binary(tmpDir string) (*os.File, error) {
|
|
// Setting RUNC_DMZ=legacy disables this dmz method.
|
|
if os.Getenv("RUNC_DMZ") == "legacy" {
|
|
logrus.Debugf("RUNC_DMZ=legacy set -- switching back to classic /proc/self/exe cloning")
|
|
return nil, ErrNoDmzBinary
|
|
}
|
|
runcDmzBinaryOnce.Do(func() {
|
|
runcDmzBinary, _ = runcDmzFs.ReadFile("binary/runc-dmz")
|
|
// Verify that our embedded binary has a standard ELF header.
|
|
if !bytes.HasPrefix(runcDmzBinary, []byte(elf.ELFMAG)) {
|
|
if len(runcDmzBinary) != 0 {
|
|
logrus.Infof("misconfigured build: embedded runc-dmz binary is non-empty but is missing a proper ELF header")
|
|
}
|
|
} else {
|
|
runcDmzBinaryIsValid = true
|
|
}
|
|
})
|
|
if !runcDmzBinaryIsValid {
|
|
return nil, ErrNoDmzBinary
|
|
}
|
|
rdr := bytes.NewBuffer(runcDmzBinary)
|
|
return CloneBinary(rdr, int64(rdr.Len()), "runc-dmz", tmpDir)
|
|
}
|