diff options
| author | Alexander Potapenko <glider@google.com> | 2024-12-05 15:45:00 +0100 |
|---|---|---|
| committer | Alexander Potapenko <glider@google.com> | 2024-12-06 07:54:04 +0000 |
| commit | 637acba36dcf8a7d2a71ee856f5f6f36c612525c (patch) | |
| tree | 7ec5d415bef802bf1bcc8cabf30453f3ed404349 /pkg | |
| parent | fb1cc4d5036e3321687190e067576046b75b9401 (diff) | |
pkg/runtest: use qemu-<arch> binaries to run cross-compiled tests
When running the executor tests, do not rely on qemu-user providing
binfmt_misc handlers for alien arches (e.g. arm64 on x86), because
binfmt_misc cannot be mounted inside the Docker container.
Instead, explicitly run the cross-compiled executor under the
corresponding QEMU binary.
Diffstat (limited to 'pkg')
| -rw-r--r-- | pkg/runtest/executor_test.go | 57 |
1 files changed, 50 insertions, 7 deletions
diff --git a/pkg/runtest/executor_test.go b/pkg/runtest/executor_test.go index bb830e885..5655f5ea4 100644 --- a/pkg/runtest/executor_test.go +++ b/pkg/runtest/executor_test.go @@ -8,6 +8,8 @@ import ( "fmt" "math/rand" "os" + "os/exec" + "path/filepath" "runtime" "strings" "testing" @@ -24,6 +26,42 @@ import ( "github.com/google/syzkaller/sys/targets" ) +// Find the corresponding QEMU binary for the target arch, if needed. +func qemuBinary(arch string) (string, error) { + qarch, ok := map[string]string{ + "386": "i386", + "amd64": "x86_64", + "arm64": "aarch64", + "arm": "arm", + "mips64le": "mips64el", + "ppc64le": "ppc64le", + "riscv64": "riscv64", + "s390x": "s390x", + }[arch] + if !ok { + return "", fmt.Errorf("unsupported architecture: %s", arch) + } + + qemuBinary := "qemu-" + qarch + path, err := exec.LookPath(qemuBinary) + if err != nil { + return "", fmt.Errorf("qemu binary not found in PATH: %s", qemuBinary) + } + + return filepath.Base(path), nil +} + +// If the tests are running on CI, or if there is an assertion failure in the executor, +// report a fatal error. Otherwise, assume cross-arch execution does not work, and skip +// the test. +func handleCrossArchError(t *testing.T, err error) { + if os.Getenv("CI") != "" || strings.Contains(err.Error(), "SYZFAIL:") { + t.Fatal(err) + } else { + t.Skipf("skipping, cross-arch execution failed: %v", err) + } +} + // TestExecutor runs all internal executor unit tests. // We do it here because we already build executor binary here. func TestExecutor(t *testing.T) { @@ -41,15 +79,20 @@ func TestExecutor(t *testing.T) { t.Fatal(err) } bin := csource.BuildExecutor(t, target, "../..") - // qemu-user may allow us to run some cross-arch binaries. - if _, err := osutil.RunCmd(time.Minute, dir, bin, "test"); err != nil { - if sysTarget.Arch == runtime.GOARCH || sysTarget.VMArch == runtime.GOARCH { + if sysTarget.Arch == runtime.GOARCH || sysTarget.VMArch == runtime.GOARCH { + // Execute the tests natively. + if _, err := osutil.RunCmd(time.Minute, dir, bin, "test"); err != nil { t.Fatal(err) } - if os.Getenv("CI") != "" || strings.Contains(err.Error(), "SYZFAIL:") { - t.Fatal(err) - } else { - t.Skipf("skipping, cross-arch binary failed: %v", err) + } else { + // Get QEMU binary for the target arch. This code might run inside Docker, so it cannot + // rely on binfmt_misc handlers provided by qemu-user. + qemu, err := qemuBinary(sysTarget.Arch) + if err != nil { + handleCrossArchError(t, err) + } + if _, err := osutil.RunCmd(time.Minute, dir, qemu, bin, "test"); err != nil { + handleCrossArchError(t, err) } } }) |
