aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKris Alder <kalder@google.com>2022-05-03 11:05:34 -0700
committerDmitry Vyukov <dvyukov@google.com>2022-05-06 08:59:20 +0200
commite60b110364688cf334ec68e073edf8d9cebc9fcb (patch)
treee10026e4c1246c6b4d7206da4a7cd3acbff8343e
parentabda9b1a98d331fa672f556e33f18df2eed424bd (diff)
pkg/build: refactor cuttlefish image code to embedFiles()
Since most of the image mounting code is duplicated, we can instead extract it to an embedFiles() function that takes a callback. The Linux- or Android-specific code can be in the callback.
-rw-r--r--pkg/build/android.go69
-rw-r--r--pkg/build/android_linux.go67
-rw-r--r--pkg/build/android_nolinux.go15
-rw-r--r--pkg/build/linux_linux.go13
-rw-r--r--pkg/build/linux_nolinux.go4
5 files changed, 81 insertions, 87 deletions
diff --git a/pkg/build/android.go b/pkg/build/android.go
index 9fb38bd5c..cc4e041da 100644
--- a/pkg/build/android.go
+++ b/pkg/build/android.go
@@ -4,7 +4,11 @@
package build
import (
+ "archive/tar"
+ "compress/gzip"
"fmt"
+ "io/ioutil"
+ "os"
"path/filepath"
"time"
@@ -27,6 +31,40 @@ func (a android) runBuild(kernelDir, buildConfig string) error {
return err
}
+func (a android) readCompiler(archivePath string) (string, error) {
+ f, err := os.Open(archivePath)
+ if err != nil {
+ return "", err
+ }
+ defer f.Close()
+
+ gr, err := gzip.NewReader(f)
+ if err != nil {
+ return "", err
+ }
+ defer gr.Close()
+
+ tr := tar.NewReader(gr)
+
+ h, err := tr.Next()
+ for ; err == nil; h, err = tr.Next() {
+ if filepath.Base(h.Name) == "compile.h" {
+ bytes, err := ioutil.ReadAll(tr)
+ if err != nil {
+ return "", err
+ }
+ result := linuxCompilerRegexp.FindSubmatch(bytes)
+ if result == nil {
+ return "", fmt.Errorf("include/generated/compile.h does not contain build information")
+ }
+
+ return string(result[1]), nil
+ }
+ }
+
+ return "", fmt.Errorf("archive %s doesn't contain include/generated/compile.h", archivePath)
+}
+
func (a android) build(params Params) (ImageDetails, error) {
var details ImageDetails
@@ -44,13 +82,37 @@ func (a android) build(params Params) (ImageDetails, error) {
return details, fmt.Errorf("failed to build modules: %s", err)
}
- buildOutDir := filepath.Join(params.KernelDir, "out/dist")
+ buildOutDir := filepath.Join(params.KernelDir, "out", "dist")
bzImage := filepath.Join(buildOutDir, "bzImage")
vmlinux := filepath.Join(buildOutDir, "vmlinux")
initramfs := filepath.Join(buildOutDir, "initramfs.img")
- if err := buildCuttlefishImage(params, bzImage, vmlinux, initramfs); err != nil {
- return details, fmt.Errorf("failed to build image: %s", err)
+ var err error
+ details.CompilerID, err = a.readCompiler(filepath.Join(buildOutDir, "kernel-headers.tar.gz"))
+ if err != nil {
+ return details, err
+ }
+
+ if err := embedFiles(params, func(mountDir string) error {
+ homeDir := filepath.Join(mountDir, "root")
+
+ if _, err := osutil.RunCmd(time.Hour, homeDir, "./fetchcvd"); err != nil {
+ return err
+ }
+
+ if err := osutil.CopyFile(bzImage, filepath.Join(homeDir, "bzImage")); err != nil {
+ return err
+ }
+ if err := osutil.CopyFile(vmlinux, filepath.Join(homeDir, "vmlinux")); err != nil {
+ return err
+ }
+ if err := osutil.CopyFile(initramfs, filepath.Join(homeDir, "initramfs.img")); err != nil {
+ return err
+ }
+
+ return nil
+ }); err != nil {
+ return details, err
}
if err := osutil.CopyFile(vmlinux, filepath.Join(params.OutputDir, "kernel")); err != nil {
@@ -60,7 +122,6 @@ func (a android) build(params Params) (ImageDetails, error) {
return details, err
}
- var err error
details.Signature, err = elfBinarySignature(vmlinux)
if err != nil {
return details, fmt.Errorf("failed to generate signature: %s", err)
diff --git a/pkg/build/android_linux.go b/pkg/build/android_linux.go
deleted file mode 100644
index a6e4e086c..000000000
--- a/pkg/build/android_linux.go
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2022 syzkaller project authors. All rights reserved.
-// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
-
-package build
-
-import (
- "fmt"
- "io/ioutil"
- "os"
- "path/filepath"
- "time"
-
- "golang.org/x/sys/unix"
-
- "github.com/google/syzkaller/pkg/osutil"
-)
-
-// buildCuttlefishImage mounts a disk image, fetches and installs a Cuttlefish emulator binary,
-// and copies in the required kernel artifacts.
-func buildCuttlefishImage(params Params, bzImage, vmlinux, initramfs string) error {
- tempDir, err := ioutil.TempDir("", "syz-build")
- if err != nil {
- return err
- }
- defer os.RemoveAll(tempDir)
- imageFile := filepath.Join(tempDir, "image")
- if err := osutil.CopyFile(params.UserspaceDir, imageFile); err != nil {
- return err
- }
- loop, loopFile, err := linuxSetupLoop(imageFile)
- if err != nil {
- return err
- }
- defer func() {
- unix.IoctlGetInt(loop, unix.LOOP_CLR_FD)
- unix.Close(loop)
- }()
- mountDir := filepath.Join(tempDir, "mnt")
- if err := osutil.MkdirAll(mountDir); err != nil {
- return err
- }
- if err := tryMount(loopFile+"p1", mountDir); err != nil {
- return fmt.Errorf("mount(%vp1, %v) failed: %v", loopFile, mountDir, err)
- }
- defer unix.Unmount(mountDir, 0)
-
- imageHomeDir := filepath.Join(mountDir, "root")
- if _, err := osutil.RunCmd(time.Hour, imageHomeDir, "./fetchcvd"); err != nil {
- return fmt.Errorf("run fetch_cvd: %s", err)
- }
-
- if err := osutil.CopyFile(bzImage, filepath.Join(imageHomeDir, "bzImage")); err != nil {
- return err
- }
- if err := osutil.CopyFile(vmlinux, filepath.Join(imageHomeDir, "vmlinux")); err != nil {
- return err
- }
- if err := osutil.CopyFile(initramfs, filepath.Join(imageHomeDir, "initramfs.img")); err != nil {
- return err
- }
-
- if err := unix.Unmount(mountDir, 0); err != nil {
- return err
- }
-
- return osutil.CopyFile(imageFile, filepath.Join(params.OutputDir, "image"))
-}
diff --git a/pkg/build/android_nolinux.go b/pkg/build/android_nolinux.go
deleted file mode 100644
index 100d7669c..000000000
--- a/pkg/build/android_nolinux.go
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2022 syzkaller project authors. All rights reserved.
-// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
-
-//go:build !linux
-// +build !linux
-
-package build
-
-import (
- "errors"
-)
-
-func buildCuttlefishImage(params Params, bzImage, vmlinux, initramfs string) error {
- return errors.New("building android cuttlefish image is only supported on linux")
-}
diff --git a/pkg/build/linux_linux.go b/pkg/build/linux_linux.go
index 4a8270353..55f21a7ee 100644
--- a/pkg/build/linux_linux.go
+++ b/pkg/build/linux_linux.go
@@ -23,6 +23,17 @@ import (
// - cmdline file is not supported (should be moved to kernel config)
// - the kernel is stored in the image in /vmlinuz file.
func embedLinuxKernel(params Params, kernelPath string) error {
+ return embedFiles(params, func(mountDir string) error {
+ if err := copyKernel(mountDir, kernelPath); err != nil {
+ return err
+ }
+ return nil
+ })
+}
+
+// embedFiles mounts the disk image specified by params.UserspaceDir and then calls the given
+// callback function which should copy files into the image as needed.
+func embedFiles(params Params, callback func(mountDir string) error) error {
if params.CmdlineFile != "" {
return fmt.Errorf("cmdline file is not supported for linux images")
}
@@ -51,7 +62,7 @@ func embedLinuxKernel(params Params, kernelPath string) error {
return fmt.Errorf("mount(%vp1, %v) failed: %v", loopFile, mountDir, err)
}
defer unix.Unmount(mountDir, 0)
- if err := copyKernel(mountDir, kernelPath); err != nil {
+ if err := callback(mountDir); err != nil {
return err
}
if params.SysctlFile != "" {
diff --git a/pkg/build/linux_nolinux.go b/pkg/build/linux_nolinux.go
index 0210627f5..03ea0da27 100644
--- a/pkg/build/linux_nolinux.go
+++ b/pkg/build/linux_nolinux.go
@@ -13,3 +13,7 @@ import (
func embedLinuxKernel(params Params, kernelPath string) error {
return errors.New("building linux image is only supported on linux")
}
+
+func embedFiles(params Params, callback func(mountDir string) error) error {
+ return errors.New("building linux image is only supported on linux")
+}