Skip to content

Commit 5bcffdf

Browse files
authored
Merge pull request #4101 from cyphar/runc-dmz-go-get-build
libcontainer: dmz: fix "go get" builds
2 parents 2705c9c + 9d8fa6d commit 5bcffdf

File tree

4 files changed

+36
-17
lines changed

4 files changed

+36
-17
lines changed

libcontainer/dmz/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ else
1414
CFLAGS += -DRUNC_USE_STDLIB
1515
endif
1616

17-
runc-dmz: _dmz.c
17+
binary/runc-dmz: _dmz.c
1818
$(CC) $(CFLAGS) -static -o $@ $^
1919
$(STRIP) -gs $@
File renamed without changes.

libcontainer/dmz/binary/dummy-file.txt

Whitespace-only changes.

libcontainer/dmz/dmz_linux.go

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,32 @@ package dmz
66
import (
77
"bytes"
88
"debug/elf"
9-
_ "embed"
9+
"embed"
1010
"os"
11+
"sync"
1112

1213
"github.com/sirupsen/logrus"
1314
)
1415

15-
// Try to build the runc-dmz binary. If it fails, replace it with an empty file
16-
// (this will trigger us to fall back to a clone of /proc/self/exe). Yeah, this
17-
// is a bit ugly but it makes sure that weird cross-compilation setups don't
18-
// break because of runc-dmz.
16+
// Try to build the runc-dmz binary on "go generate". If it fails (or
17+
// libcontainer is being imported as a library), the embed.FS will not contain
18+
// the file, which will then cause us to fall back to a clone of
19+
// /proc/self/exe.
1920
//
20-
//go:generate sh -c "make -B runc-dmz || echo -n >runc-dmz"
21-
//go:embed runc-dmz
22-
var runcDmzBinary []byte
21+
// There is an empty file called dummy-file.txt in libcontainer/dmz/binary in
22+
// order to work around the restriction that go:embed requires at least one
23+
// file to match the pattern.
24+
//
25+
//go:generate make -B binary/runc-dmz
26+
//go:embed binary
27+
var runcDmzFs embed.FS
28+
29+
// A cached copy of the contents of runc-dmz.
30+
var (
31+
runcDmzBinaryOnce sync.Once
32+
runcDmzBinaryIsValid bool
33+
runcDmzBinary []byte
34+
)
2335

2436
// Binary returns a cloned copy (see CloneBinary) of a very minimal C program
2537
// that just does an execve() of its arguments. This is used in the final
@@ -31,18 +43,25 @@ var runcDmzBinary []byte
3143
// If the runc-dmz binary is not embedded into the runc binary, Binary will
3244
// return ErrNoDmzBinary as the error.
3345
func Binary(tmpDir string) (*os.File, error) {
34-
rdr := bytes.NewBuffer(runcDmzBinary)
35-
// Verify that our embedded binary has a standard ELF header.
36-
if !bytes.HasPrefix(rdr.Bytes(), []byte(elf.ELFMAG)) {
37-
if rdr.Len() != 0 {
38-
logrus.Infof("misconfigured build: embedded runc-dmz binary is non-empty but is missing a proper ELF header")
39-
}
40-
return nil, ErrNoDmzBinary
41-
}
4246
// Setting RUNC_DMZ=legacy disables this dmz method.
4347
if os.Getenv("RUNC_DMZ") == "legacy" {
4448
logrus.Debugf("RUNC_DMZ=legacy set -- switching back to classic /proc/self/exe cloning")
4549
return nil, ErrNoDmzBinary
4650
}
51+
runcDmzBinaryOnce.Do(func() {
52+
runcDmzBinary, _ = runcDmzFs.ReadFile("binary/runc-dmz")
53+
// Verify that our embedded binary has a standard ELF header.
54+
if !bytes.HasPrefix(runcDmzBinary, []byte(elf.ELFMAG)) {
55+
if len(runcDmzBinary) != 0 {
56+
logrus.Infof("misconfigured build: embedded runc-dmz binary is non-empty but is missing a proper ELF header")
57+
}
58+
} else {
59+
runcDmzBinaryIsValid = true
60+
}
61+
})
62+
if !runcDmzBinaryIsValid {
63+
return nil, ErrNoDmzBinary
64+
}
65+
rdr := bytes.NewBuffer(runcDmzBinary)
4766
return CloneBinary(rdr, int64(rdr.Len()), "runc-dmz", tmpDir)
4867
}

0 commit comments

Comments
 (0)