mirror of
https://github.com/reactos/syzkaller.git
synced 2024-11-23 11:29:46 +00:00
pkg/csource: support archs other than x86_64
This commit is contained in:
parent
52a33fd516
commit
19f9bc13d3
@ -268,9 +268,10 @@ int main(int argc, char** argv)
|
||||
install_segv_handler();
|
||||
use_temporary_dir();
|
||||
|
||||
#ifdef __i386__
|
||||
// mmap syscall on i386 is translated to old_mmap and has different signature.
|
||||
#if defined(__i386__) || defined(__arm__)
|
||||
// mmap syscall on i386/arm is translated to old_mmap and has different signature.
|
||||
// As a workaround fix it up to mmap2, which has signature that we expect.
|
||||
// pkg/csource has the same hack.
|
||||
for (size_t i = 0; i < sizeof(syscalls) / sizeof(syscalls[0]); i++) {
|
||||
if (syscalls[i].sys_nr == __NR_mmap)
|
||||
syscalls[i].sys_nr = __NR_mmap2;
|
||||
|
@ -20,7 +20,7 @@ import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/google/syzkaller/prog"
|
||||
_ "github.com/google/syzkaller/sys"
|
||||
"github.com/google/syzkaller/sys"
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
@ -83,24 +83,34 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) {
|
||||
for _, c := range p.Calls {
|
||||
handled[c.Meta.CallName] = c.Meta.NR
|
||||
}
|
||||
for name, nr := range handled {
|
||||
// Only generate defines for new syscalls (added after commit 8a1ab3155c2ac on 2012-10-04).
|
||||
// TODO: the syscall number 313 implies that we're dealing with linux/amd64.
|
||||
if nr >= 313 && !strings.HasPrefix(name, "syz_") {
|
||||
fmt.Fprintf(w, "#ifndef __NR_%v\n", name)
|
||||
fmt.Fprintf(w, "#define __NR_%v %v\n", name, nr)
|
||||
fmt.Fprintf(w, "#endif\n")
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(w, "\n")
|
||||
|
||||
hdr, err := preprocessCommonHeader(opts, handled, prog.RequiresBitmasks(p), prog.RequiresChecksums(p))
|
||||
hdr, err := preprocessCommonHeader(p.Target, opts, handled, prog.RequiresBitmasks(p), prog.RequiresChecksums(p))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fmt.Fprint(w, hdr)
|
||||
fmt.Fprint(w, "\n")
|
||||
|
||||
for name, nr := range handled {
|
||||
if strings.HasPrefix(name, "syz_") {
|
||||
continue
|
||||
}
|
||||
if p.Target.OS == "linux" && p.Target.Arch == "amd64" && nr < 313 {
|
||||
// Only generate defines for new syscalls (added after commit 8a1ab3155c2ac on 2012-10-04).
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(w, "#ifndef __NR_%v\n", name)
|
||||
fmt.Fprintf(w, "#define __NR_%v %v\n", name, nr)
|
||||
fmt.Fprintf(w, "#endif\n")
|
||||
}
|
||||
if p.Target.OS == "linux" && p.Target.PtrSize == 4 {
|
||||
// This is a dirty hack.
|
||||
// On 32-bit linux mmap translated to old_mmap syscall which has a different signature.
|
||||
// mmap2 has the right signature. executor translates mmap to mmap2, do the same here.
|
||||
fmt.Fprintf(w, "#undef __NR_mmap\n")
|
||||
fmt.Fprintf(w, "#define __NR_mmap __NR_mmap2\n")
|
||||
}
|
||||
fmt.Fprintf(w, "\n")
|
||||
|
||||
calls, nvar := generateCalls(p.Target, exec, opts)
|
||||
fmt.Fprintf(w, "long r[%v];\n", nvar)
|
||||
|
||||
@ -420,7 +430,7 @@ loop:
|
||||
return calls, n
|
||||
}
|
||||
|
||||
func preprocessCommonHeader(opts Options, handled map[string]uint64, useBitmasks, useChecksums bool) (string, error) {
|
||||
func preprocessCommonHeader(target *prog.Target, opts Options, handled map[string]uint64, useBitmasks, useChecksums bool) (string, error) {
|
||||
var defines []string
|
||||
if useBitmasks {
|
||||
defines = append(defines, "SYZ_USE_BITMASKS")
|
||||
@ -470,8 +480,9 @@ func preprocessCommonHeader(opts Options, handled map[string]uint64, useBitmasks
|
||||
for name, _ := range handled {
|
||||
defines = append(defines, "__NR_"+name)
|
||||
}
|
||||
// TODO: need to know target arch + do cross-compilation
|
||||
defines = append(defines, "__x86_64__")
|
||||
|
||||
sysTarget := sys.Targets[target.OS][target.Arch]
|
||||
defines = append(defines, sysTarget.CArch...)
|
||||
|
||||
cmd := exec.Command("cpp", "-nostdinc", "-undef", "-fdirectives-only", "-dDI", "-E", "-P", "-")
|
||||
for _, def := range defines {
|
||||
@ -512,25 +523,42 @@ func preprocessCommonHeader(opts Options, handled map[string]uint64, useBitmasks
|
||||
|
||||
// Build builds a C/C++ program from source src and returns name of the resulting binary.
|
||||
// lang can be "c" or "c++".
|
||||
func Build(lang, src string) (string, error) {
|
||||
func Build(target *prog.Target, lang, src string) (string, error) {
|
||||
bin, err := ioutil.TempFile("", "syzkaller")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to create temp file: %v", err)
|
||||
}
|
||||
bin.Close()
|
||||
out, err := exec.Command("gcc", "-x", lang, "-Wall", "-Werror", src, "-o", bin.Name(), "-pthread", "-static", "-O1", "-g").CombinedOutput()
|
||||
sysTarget := sys.Targets[target.OS][target.Arch]
|
||||
compiler := sysTarget.CCompilerPrefix + "gcc"
|
||||
if _, err := exec.LookPath(compiler); err != nil {
|
||||
return "", NoCompilerErr
|
||||
}
|
||||
flags := []string{
|
||||
"-x", lang, "-Wall", "-Werror", "-O1", "-g", "-o", bin.Name(),
|
||||
src, "-pthread",
|
||||
}
|
||||
flags = append(flags, sysTarget.CrossCFlags...)
|
||||
if sysTarget.PtrSize == 4 {
|
||||
// We do generate uint64's for syscall arguments that overflow longs on 32-bit archs.
|
||||
flags = append(flags, "-Wno-overflow")
|
||||
}
|
||||
out, err := exec.Command(compiler, append(flags, "-static")...).CombinedOutput()
|
||||
if err != nil {
|
||||
// Some distributions don't have static libraries.
|
||||
out, err = exec.Command("gcc", "-x", lang, "-Wall", "-Werror", src, "-o", bin.Name(), "-pthread", "-O1", "-g").CombinedOutput()
|
||||
out, err = exec.Command(compiler, flags...).CombinedOutput()
|
||||
}
|
||||
if err != nil {
|
||||
os.Remove(bin.Name())
|
||||
data, _ := ioutil.ReadFile(src)
|
||||
return "", fmt.Errorf("failed to build program:\n%s\n%s", data, out)
|
||||
return "", fmt.Errorf("failed to build program:\n%s\n%s\ncompiler invocation: %v %v\n",
|
||||
data, out, compiler, flags)
|
||||
}
|
||||
return bin.Name(), nil
|
||||
}
|
||||
|
||||
var NoCompilerErr = errors.New("no target compiler")
|
||||
|
||||
// Format reformats C source using clang-format.
|
||||
func Format(src []byte) ([]byte, error) {
|
||||
stdout, stderr := new(bytes.Buffer), new(bytes.Buffer)
|
||||
|
@ -89,7 +89,7 @@ func allOptionsPermutations() []Options {
|
||||
}
|
||||
|
||||
func TestOne(t *testing.T) {
|
||||
target, rs, _ := initTest(t)
|
||||
t.Parallel()
|
||||
opts := Options{
|
||||
Threaded: true,
|
||||
Collide: true,
|
||||
@ -99,8 +99,21 @@ func TestOne(t *testing.T) {
|
||||
Repro: true,
|
||||
UseTmpDir: true,
|
||||
}
|
||||
p := target.GenerateAllSyzProg(rs)
|
||||
testOne(t, p, opts)
|
||||
for _, target := range prog.AllTargets() {
|
||||
target := target
|
||||
t.Run(target.OS+"/"+target.Arch, func(t *testing.T) {
|
||||
if target.OS == "linux" && target.Arch == "arm" {
|
||||
// This currently fails (at least with my arm-linux-gnueabihf-gcc-4.8) with:
|
||||
// Assembler messages:
|
||||
// Error: alignment too large: 15 assumed
|
||||
t.Skip("broken")
|
||||
}
|
||||
t.Parallel()
|
||||
rs := rand.NewSource(0)
|
||||
p := target.GenerateAllSyzProg(rs)
|
||||
testOne(t, p, opts)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestOptions(t *testing.T) {
|
||||
@ -142,7 +155,10 @@ func testOne(t *testing.T, p *prog.Prog, opts Options) {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
defer os.Remove(srcf)
|
||||
bin, err := Build("c", srcf)
|
||||
bin, err := Build(p.Target, "c", srcf)
|
||||
if err == NoCompilerErr {
|
||||
t.Skip(err)
|
||||
}
|
||||
if err != nil {
|
||||
t.Logf("program:\n%s\n", p.Serialize())
|
||||
t.Fatalf("%v", err)
|
||||
|
@ -19,21 +19,21 @@ import (
|
||||
|
||||
const timeout = 10 * time.Second
|
||||
|
||||
func buildExecutor(t *testing.T) string {
|
||||
return buildProgram(t, filepath.FromSlash("../../executor/executor.cc"))
|
||||
func buildExecutor(t *testing.T, target *prog.Target) string {
|
||||
return buildProgram(t, target, filepath.FromSlash("../../executor/executor.cc"))
|
||||
}
|
||||
|
||||
func buildSource(t *testing.T, src []byte) string {
|
||||
func buildSource(t *testing.T, target *prog.Target, src []byte) string {
|
||||
tmp, err := osutil.WriteTempFile(src)
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
defer os.Remove(tmp)
|
||||
return buildProgram(t, tmp)
|
||||
return buildProgram(t, target, tmp)
|
||||
}
|
||||
|
||||
func buildProgram(t *testing.T, src string) string {
|
||||
bin, err := csource.Build("c++", src)
|
||||
func buildProgram(t *testing.T, target *prog.Target, src string) string {
|
||||
bin, err := csource.Build(target, "c++", src)
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
@ -53,7 +53,12 @@ func initTest(t *testing.T) (rand.Source, int) {
|
||||
}
|
||||
|
||||
func TestEmptyProg(t *testing.T) {
|
||||
bin := buildExecutor(t)
|
||||
target, err := prog.GetTarget("linux", runtime.GOARCH)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
bin := buildExecutor(t, target)
|
||||
defer os.Remove(bin)
|
||||
|
||||
cfg := Config{
|
||||
@ -88,7 +93,7 @@ func TestExecute(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
bin := buildExecutor(t)
|
||||
bin := buildExecutor(t, target)
|
||||
defer os.Remove(bin)
|
||||
|
||||
for _, flag := range flags {
|
||||
|
@ -558,7 +558,7 @@ func (ctx *context) testCProg(p *prog.Prog, duration time.Duration, opts csource
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
bin, err := csource.Build("c", srcf)
|
||||
bin, err := csource.Build(p.Target, "c", srcf)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ package prog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// Target describes target OS/arch pair.
|
||||
@ -72,12 +73,26 @@ func GetTarget(OS, arch string) (*Target, error) {
|
||||
for _, t := range targets {
|
||||
supported = append(supported, fmt.Sprintf("%v/%v", t.OS, t.Arch))
|
||||
}
|
||||
sort.Strings(supported)
|
||||
return nil, fmt.Errorf("unknown target: %v (supported: %v)", key, supported)
|
||||
}
|
||||
|
||||
return target, nil
|
||||
}
|
||||
|
||||
func AllTargets() []*Target {
|
||||
var res []*Target
|
||||
for _, t := range targets {
|
||||
res = append(res, t)
|
||||
}
|
||||
sort.Slice(res, func(i, j int) bool {
|
||||
if res[i].OS != res[j].OS {
|
||||
return res[i].OS < res[j].OS
|
||||
}
|
||||
return res[i].Arch < res[j].Arch
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
func initTarget(target *Target) {
|
||||
target.SyscallMap = make(map[string]*Syscall)
|
||||
for _, c := range target.Syscalls {
|
||||
|
@ -17031,6 +17031,7 @@ var consts_386 = []ConstValue{
|
||||
{Name: "__NR_mlock2", Value: 376},
|
||||
{Name: "__NR_mlockall", Value: 152},
|
||||
{Name: "__NR_mmap", Value: 90},
|
||||
{Name: "__NR_mmap2", Value: 192},
|
||||
{Name: "__NR_modify_ldt", Value: 123},
|
||||
{Name: "__NR_mount", Value: 21},
|
||||
{Name: "__NR_move_pages", Value: 317},
|
||||
|
@ -16976,6 +16976,7 @@ var consts_arm = []ConstValue{
|
||||
{Name: "__NR_mlock2", Value: 9437574},
|
||||
{Name: "__NR_mlockall", Value: 9437336},
|
||||
{Name: "__NR_mmap", Value: 9437274},
|
||||
{Name: "__NR_mmap2", Value: 9437376},
|
||||
{Name: "__NR_mount", Value: 9437205},
|
||||
{Name: "__NR_move_pages", Value: 9437528},
|
||||
{Name: "__NR_mprotect", Value: 9437309},
|
||||
|
@ -54,6 +54,7 @@ include <linux/memfd.h>
|
||||
include <uapi/linux/module.h>
|
||||
include <asm/prctl.h>
|
||||
include <linux/ioprio.h>
|
||||
include <uapi/linux/kcov.h>
|
||||
|
||||
resource fd[int32]: 0xffffffffffffffff, AT_FDCWD
|
||||
resource fd_dir[fd]
|
||||
@ -1017,14 +1018,14 @@ getrandom_flags = GRND_NONBLOCK, GRND_RANDOM
|
||||
uffdio_features = UFFD_FEATURE_PAGEFAULT_FLAG_WP, UFFD_FEATURE_EVENT_FORK, UFFD_FEATURE_EVENT_REMAP, UFFD_FEATURE_EVENT_REMOVE, UFFD_FEATURE_MISSING_HUGETLBFS, UFFD_FEATURE_MISSING_SHMEM, UFFD_FEATURE_EVENT_UNMAP
|
||||
clone_flags = CLONE_VM, CLONE_FS, CLONE_FILES, CLONE_SIGHAND, CLONE_PTRACE, CLONE_VFORK, CLONE_PARENT, CLONE_THREAD, CLONE_NEWNS, CLONE_SYSVSEM, CLONE_SETTLS, CLONE_PARENT_SETTID, CLONE_CHILD_CLEARTID, CLONE_UNTRACED, CLONE_CHILD_SETTID, CLONE_NEWCGROUP, CLONE_NEWUTS, CLONE_NEWIPC, CLONE_NEWUSER, CLONE_NEWPID, CLONE_NEWNET, CLONE_IO
|
||||
|
||||
include <uapi/linux/kcov.h>
|
||||
|
||||
kcov_ioctls = KCOV_INIT_TRACE, KCOV_ENABLE
|
||||
kcov_modes = KCOV_TRACE_PC, KCOV_TRACE_CMP
|
||||
# TODO: remove once the const is present in kernel headers.
|
||||
define KCOV_TRACE_PC 0
|
||||
define KCOV_TRACE_CMP 1
|
||||
|
||||
legacy_mmap_number = __NR_mmap2
|
||||
|
||||
# Not yet implemented syscalls
|
||||
#define __NR_umask 95
|
||||
#define __NR_vhangup 153
|
||||
|
@ -714,6 +714,7 @@ __NR_mlock = 150
|
||||
__NR_mlock2 = 376
|
||||
__NR_mlockall = 152
|
||||
__NR_mmap = 90
|
||||
__NR_mmap2 = 192
|
||||
__NR_modify_ldt = 123
|
||||
__NR_mount = 21
|
||||
__NR_move_pages = 317
|
||||
|
@ -704,6 +704,7 @@ __NR_mlock = 9437334
|
||||
__NR_mlock2 = 9437574
|
||||
__NR_mlockall = 9437336
|
||||
__NR_mmap = 9437274
|
||||
__NR_mmap2 = 9437376
|
||||
__NR_mount = 9437205
|
||||
__NR_move_pages = 9437528
|
||||
__NR_mprotect = 9437309
|
||||
|
@ -48,7 +48,7 @@ var Targets = map[string]map[string]*Target{
|
||||
"arm": {
|
||||
PtrSize: 4,
|
||||
CArch: []string{"__arm__"},
|
||||
CFlags: []string{"-D__LINUX_ARM_ARCH__=6", "-m32"},
|
||||
CFlags: []string{"-D__LINUX_ARM_ARCH__=6"},
|
||||
CrossCFlags: []string{"-march=armv6t2"},
|
||||
CCompilerPrefix: "arm-linux-gnueabihf-",
|
||||
KernelArch: "arm",
|
||||
|
Loading…
Reference in New Issue
Block a user