@@ -6,20 +6,32 @@ package dmz
66import (
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.
3345func 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