syzkaller/pkg/build/build.go
Siddharth M 7fa29a5895 pkg/build: added feature to copy kernel image for netbsd
* Modified pkg/build/netbsd.go
1. Made kernel build incremental
2. Added code to copy kernel to disk image

* Fix formating issues

* Fixed basic issues

* Fixed copy kernel to disk
1. Added CPU option to default
2. Added snapshot option to vm/qemu/qemu.go
3. Hacky solution to get the build working

* Fixed issues and added vm.MonitorExecution

* Added sync instead of poweroff
2019-02-22 13:18:44 +01:00

158 lines
4.6 KiB
Go

// Copyright 2018 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 contains helper functions for building kernels/images.
package build
import (
"bytes"
"fmt"
"path/filepath"
"strings"
"time"
"github.com/google/syzkaller/pkg/osutil"
)
// Image creates a disk image for the specified OS/ARCH/VM.
// Kernel is taken from kernelDir, userspace system is taken from userspaceDir.
// If cmdlineFile is not empty, contents of the file are appended to the kernel command line.
// If sysctlFile is not empty, contents of the file are appended to the image /etc/sysctl.conf.
// Output is stored in outputDir and includes (everything except for image is optional):
// - image: the image
// - key: ssh key for the image
// - kernel: kernel for injected boot
// - initrd: initrd for injected boot
// - kernel.config: actual kernel config used during build
// - obj/: directory with kernel object files (this should match KernelObject
// specified in sys/targets, e.g. vmlinux for linux)
func Image(targetOS, targetArch, vmType, kernelDir, outputDir, compiler, userspaceDir,
cmdlineFile, sysctlFile string, config []byte) error {
builder, err := getBuilder(targetOS, targetArch, vmType)
if err != nil {
return err
}
if err := osutil.MkdirAll(filepath.Join(outputDir, "obj")); err != nil {
return err
}
if len(config) != 0 {
// Write kernel config early, so that it's captured on build failures.
if err := osutil.WriteFile(filepath.Join(outputDir, "kernel.config"), config); err != nil {
return fmt.Errorf("failed to write config file: %v", err)
}
}
return builder.build(targetArch, vmType, kernelDir, outputDir, compiler, userspaceDir, cmdlineFile, sysctlFile, config)
}
func Clean(targetOS, targetArch, vmType, kernelDir string) error {
builder, err := getBuilder(targetOS, targetArch, vmType)
if err != nil {
return err
}
return builder.clean(kernelDir)
}
type KernelBuildError struct {
*osutil.VerboseError
}
type builder interface {
build(targetArch, vmType, kernelDir, outputDir, compiler, userspaceDir,
cmdlineFile, sysctlFile string, config []byte) error
clean(kernelDir string) error
}
func getBuilder(targetOS, targetArch, vmType string) (builder, error) {
switch {
case targetOS == "linux" && targetArch == "amd64" && vmType == "gvisor":
return gvisor{}, nil
case targetOS == "linux" && targetArch == "amd64" && (vmType == "qemu" || vmType == "gce"):
return linux{}, nil
case targetOS == "fuchsia" && (targetArch == "amd64" || targetArch == "arm64") && vmType == "qemu":
return fuchsia{}, nil
case targetOS == "akaros" && targetArch == "amd64" && vmType == "qemu":
return akaros{}, nil
case targetOS == "openbsd" && targetArch == "amd64" && (vmType == "gce" || vmType == "vmm"):
return openbsd{}, nil
case targetOS == "netbsd" && targetArch == "amd64" && (vmType == "qemu" || vmType == "gce"):
return netbsd{}, nil
default:
return nil, fmt.Errorf("unsupported image type %v/%v/%v", targetOS, targetArch, vmType)
}
}
func CompilerIdentity(compiler string) (string, error) {
if compiler == "" {
return "", nil
}
bazel := strings.HasSuffix(compiler, "bazel")
arg := "--version"
if bazel {
arg = ""
}
output, err := osutil.RunCmd(time.Minute, "", compiler, arg)
if err != nil {
return "", err
}
for _, line := range strings.Split(string(output), "\n") {
if bazel {
// Strip extracting and log lines...
if strings.Contains(line, "Extracting Bazel") {
continue
}
if strings.HasPrefix(line, "INFO: ") {
continue
}
if strings.HasPrefix(line, "WARNING: ") {
continue
}
}
return strings.TrimSpace(line), nil
}
return "", fmt.Errorf("no output from compiler --version")
}
func extractRootCause(err error) error {
verr, ok := err.(*osutil.VerboseError)
if !ok {
return err
}
cause := extractCauseInner(verr.Output)
if cause != nil {
verr.Title = string(cause)
}
return KernelBuildError{verr}
}
func extractCauseInner(s []byte) []byte {
var cause []byte
for _, line := range bytes.Split(s, []byte{'\n'}) {
for _, pattern := range buildFailureCauses {
if pattern.weak && cause != nil {
continue
}
if bytes.Contains(line, pattern.pattern) {
cause = line
break
}
}
}
return cause
}
type buildFailureCause struct {
pattern []byte
weak bool
}
var buildFailureCauses = [...]buildFailureCause{
{pattern: []byte(": error: ")},
{pattern: []byte(": fatal error: ")},
{pattern: []byte(": undefined reference to")},
{weak: true, pattern: []byte(": final link failed: ")},
{weak: true, pattern: []byte("collect2: error: ")},
}