mirror of
https://github.com/reactos/syzkaller.git
synced 2025-03-03 00:59:13 +00:00

* 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
158 lines
4.6 KiB
Go
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: ")},
|
|
}
|