diff options
| author | Kris Alder <kalder@google.com> | 2022-04-29 15:24:59 -0700 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2022-05-06 08:59:20 +0200 |
| commit | abda9b1a98d331fa672f556e33f18df2eed424bd (patch) | |
| tree | 5671d162b54faf776af37409a20478037f56a914 | |
| parent | efeff0a5c583d6c8158481970f1b0dd581358d5a (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.
| -rw-r--r-- | pkg/build/android.go | 74 | ||||
| -rw-r--r-- | pkg/build/android_linux.go | 67 | ||||
| -rw-r--r-- | pkg/build/android_nolinux.go | 15 | ||||
| -rw-r--r-- | pkg/build/build.go | 8 |
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{}, |
