-
Notifications
You must be signed in to change notification settings - Fork 787
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
In a container, try to register binfmt_misc
If we're being started up in a container, default to attempting to register any emulators for which we find configurations of the type included in Fedora's qemu-user-static packages. Use a hidden global --register-binfmt flag to control this, and set its default based on whether or not $container is set to "oci". Signed-off-by: Nalin Dahyabhai <[email protected]>
- Loading branch information
Showing
3 changed files
with
109 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
//go:build linux | ||
|
||
package binfmt | ||
|
||
import ( | ||
"bufio" | ||
"errors" | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
"strings" | ||
"syscall" | ||
|
||
"github.com/containers/storage/pkg/unshare" | ||
"github.com/sirupsen/logrus" | ||
"golang.org/x/sys/unix" | ||
) | ||
|
||
// MaybeRegister() calls Register() if the current context is a rootless one, | ||
// or if the "container" environment variable suggests that we're in a | ||
// container. | ||
func MaybeRegister(configurationSearchDirectories []string) error { | ||
if unshare.IsRootless() || os.Getenv("container") != "" { // we _also_ own our own mount namespace | ||
return Register(configurationSearchDirectories) | ||
} | ||
return nil | ||
} | ||
|
||
// Register() registers binfmt.d emulators described by configuration files in | ||
// the passed-in slice of directories, or in the union of /etc/binfmt.d, | ||
// /run/binfmt.d, and /usr/lib/binfmt.d if the slice has no items. If any | ||
// emulators are configured, it will attempt to mount a binfmt_misc filesystem | ||
// in the current mount namespace first, ignoring only EPERM and EACCES errors. | ||
func Register(configurationSearchDirectories []string) error { | ||
if len(configurationSearchDirectories) == 0 { | ||
configurationSearchDirectories = []string{"/etc/binfmt.d", "/run/binfmt.d", "/usr/lib/binfmt.d"} | ||
} | ||
mounted := false | ||
for _, searchDir := range configurationSearchDirectories { | ||
globs, err := filepath.Glob(filepath.Join(searchDir, "*.conf")) | ||
if err != nil { | ||
return fmt.Errorf("looking for binfmt.d configuration in %q: %w", searchDir, err) | ||
} | ||
for _, conf := range globs { | ||
f, err := os.Open(conf) | ||
if err != nil { | ||
return fmt.Errorf("reading binfmt.d configuration: %w", err) | ||
} | ||
scanner := bufio.NewScanner(f) | ||
for scanner.Scan() { | ||
line := strings.TrimSpace(scanner.Text()) | ||
if len(line) == 0 || line[0] == ';' || line[0] == '#' { | ||
continue | ||
} | ||
if !mounted { | ||
if err = unix.Mount("none", "/proc/sys/fs/binfmt_misc", "binfmt_misc", 0, ""); err != nil { | ||
if errors.Is(err, syscall.EPERM) || errors.Is(err, syscall.EACCES) { | ||
// well, we tried. no need to make a stink about it | ||
return nil | ||
} | ||
return fmt.Errorf("mounting binfmt_misc: %w", err) | ||
} | ||
mounted = true | ||
} | ||
reg, err := os.Create("/proc/sys/fs/binfmt_misc/register") | ||
if err != nil { | ||
return fmt.Errorf("registering(open): %w", err) | ||
} | ||
if _, err = fmt.Fprintf(reg, "%s\n", line); err != nil { | ||
return fmt.Errorf("registering(write): %w", err) | ||
} | ||
logrus.Tracef("registered binfmt %q", line) | ||
if err = reg.Close(); err != nil { | ||
return fmt.Errorf("registering(close): %w", err) | ||
} | ||
} | ||
if err := f.Close(); err != nil { | ||
return fmt.Errorf("reading binfmt.d configuration: %w", err) | ||
} | ||
} | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
//go:build !linux | ||
|
||
package binfmt | ||
|
||
import "syscall" | ||
|
||
// MaybeRegister() returns no error. | ||
func MaybeRegister(configurationSearchDirectories []string) error { | ||
return nil | ||
} | ||
|
||
// Register() returns an error. | ||
func Register(configurationSearchDirectories []string) error { | ||
return syscall.ENOSYS | ||
} |