aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/build
diff options
context:
space:
mode:
authorKris Alder <kalder@google.com>2022-04-29 15:24:59 -0700
committerDmitry Vyukov <dvyukov@google.com>2022-05-06 08:59:20 +0200
commitabda9b1a98d331fa672f556e33f18df2eed424bd (patch)
tree5671d162b54faf776af37409a20478037f56a914 /pkg/build
parentefeff0a5c583d6c8158481970f1b0dd581358d5a (diff)
pkg/build: build Android kernel and embed in Cuttlefish image
Android uses some config files (specified with the BUILD_CONFIG environment variable) to configure kernel builds. KASan configurations already exist. We want to mount the image, install a new Cuttlefish emulator binary (using fetch_cvd) and copy over the kernel that we've built.
Diffstat (limited to 'pkg/build')
-rw-r--r--pkg/build/android.go74
-rw-r--r--pkg/build/android_linux.go67
-rw-r--r--pkg/build/android_nolinux.go15
-rw-r--r--pkg/build/build.go8
4 files changed, 162 insertions, 2 deletions
diff --git a/pkg/build/android.go b/pkg/build/android.go
new file mode 100644
index 000000000..9fb38bd5c
--- /dev/null
+++ b/pkg/build/android.go
@@ -0,0 +1,74 @@
+// 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"
+ "path/filepath"
+ "time"
+
+ "github.com/google/syzkaller/pkg/osutil"
+)
+
+const (
+ kernelConfig = "common/build.config.gki_kasan.x86_64"
+ moduleConfig = "common-modules/virtual-device/build.config.virtual_device_kasan.x86_64"
+)
+
+type android struct{}
+
+func (a android) runBuild(kernelDir, buildConfig string) error {
+ cmd := osutil.Command("build/build.sh")
+ cmd.Dir = kernelDir
+ cmd.Env = append(cmd.Env, "DIST_DIR=out/dist", fmt.Sprintf("BUILD_CONFIG=%s", buildConfig))
+
+ _, err := osutil.Run(time.Hour, cmd)
+ return err
+}
+
+func (a android) build(params Params) (ImageDetails, error) {
+ var details ImageDetails
+
+ if params.CmdlineFile != "" {
+ return details, fmt.Errorf("cmdline file is not supported for android cuttlefish images")
+ }
+ if params.SysctlFile != "" {
+ return details, fmt.Errorf("sysctl file is not supported for android cuttlefish images")
+ }
+
+ if err := a.runBuild(params.KernelDir, kernelConfig); err != nil {
+ return details, fmt.Errorf("failed to build kernel: %s", err)
+ }
+ if err := a.runBuild(params.KernelDir, moduleConfig); err != nil {
+ return details, fmt.Errorf("failed to build modules: %s", err)
+ }
+
+ 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)
+ }
+
+ if err := osutil.CopyFile(vmlinux, filepath.Join(params.OutputDir, "kernel")); err != nil {
+ return details, err
+ }
+ if err := osutil.CopyFile(initramfs, filepath.Join(params.OutputDir, "initrd")); err != nil {
+ return details, err
+ }
+
+ var err error
+ details.Signature, err = elfBinarySignature(vmlinux)
+ if err != nil {
+ return details, fmt.Errorf("failed to generate signature: %s", err)
+ }
+
+ return details, nil
+}
+
+func (a android) clean(kernelDir, targetArch string) error {
+ return osutil.RemoveAll(filepath.Join(kernelDir, "out"))
+}
diff --git a/pkg/build/android_linux.go b/pkg/build/android_linux.go
new file mode 100644
index 000000000..a6e4e086c
--- /dev/null
+++ b/pkg/build/android_linux.go
@@ -0,0 +1,67 @@
+// 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
new file mode 100644
index 000000000..100d7669c
--- /dev/null
+++ b/pkg/build/android_nolinux.go
@@ -0,0 +1,15 @@
+// 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/build.go b/pkg/build/build.go
index 0f19787ac..284bc0949 100644
--- a/pkg/build/build.go
+++ b/pkg/build/build.go
@@ -121,8 +121,12 @@ type builder interface {
}
func getBuilder(targetOS, targetArch, vmType string) (builder, error) {
- if targetOS == targets.Linux && vmType == "gvisor" {
- return gvisor{}, nil
+ if targetOS == targets.Linux {
+ if vmType == "gvisor" {
+ return gvisor{}, nil
+ } else if vmType == "cuttlefish" {
+ return android{}, nil
+ }
}
builders := map[string]builder{
targets.Linux: linux{},