From 85b1f93f8dbbc767c564e494a6353aa3517d5d49 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Mon, 16 Oct 2017 12:18:50 +0200 Subject: executor, pkg/ipc: unify ipc protocol between linux and other OSes We currently use more complex and functional protocol on linux, and a simple ad-hoc protocol on other OSes. This leads to code duplication in both ipc and executor. Linux supports coverage, shared memory communication and fork server, which would also be useful for most other OSes. Unify communication protocol and parametrize it by (1) use of shmem or only pipes, (2) use of fork server. This reduces duplication in ipc and executor and will allow to support the useful features for other OSes easily. Finally, this fixes akaros support as it currently uses syz-stress running on host (linux) and executor running on akaros. --- pkg/osutil/fileutil_linux.go | 26 ------------------ pkg/osutil/osutil_akaros.go | 19 +++++++++++++ pkg/osutil/osutil_darwin.go | 11 ++++++++ pkg/osutil/osutil_freebsd.go | 14 ++++++++++ pkg/osutil/osutil_fuchsia.go | 28 +++++++++++++++++++ pkg/osutil/osutil_linux.go | 16 +++++++++++ pkg/osutil/osutil_stub.go | 13 --------- pkg/osutil/osutil_unix.go | 65 ++++++++++++++++++++++++++++++++++++++++++++ pkg/osutil/osutil_windows.go | 28 +++++++++++++++++++ 9 files changed, 181 insertions(+), 39 deletions(-) delete mode 100644 pkg/osutil/fileutil_linux.go create mode 100644 pkg/osutil/osutil_akaros.go create mode 100644 pkg/osutil/osutil_darwin.go create mode 100644 pkg/osutil/osutil_freebsd.go delete mode 100644 pkg/osutil/osutil_stub.go (limited to 'pkg/osutil') diff --git a/pkg/osutil/fileutil_linux.go b/pkg/osutil/fileutil_linux.go deleted file mode 100644 index f1a0c1b66..000000000 --- a/pkg/osutil/fileutil_linux.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2017 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. - -// +build !appengine - -package osutil - -import ( - "io/ioutil" - "path/filepath" - "syscall" - "unsafe" -) - -// UmountAll recurusively unmounts all mounts in dir. -func UmountAll(dir string) { - files, _ := ioutil.ReadDir(dir) - for _, f := range files { - name := filepath.Join(dir, f.Name()) - if f.IsDir() { - UmountAll(name) - } - fn := []byte(name + "\x00") - syscall.Syscall(syscall.SYS_UMOUNT2, uintptr(unsafe.Pointer(&fn[0])), syscall.MNT_FORCE, 0) - } -} diff --git a/pkg/osutil/osutil_akaros.go b/pkg/osutil/osutil_akaros.go new file mode 100644 index 000000000..d2107b9b9 --- /dev/null +++ b/pkg/osutil/osutil_akaros.go @@ -0,0 +1,19 @@ +// Copyright 2017 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. + +// +build akaros + +package osutil + +import ( + "os" +) + +func HandleInterrupts(shutdown chan struct{}) { +} + +func UmountAll(dir string) { +} + +func prolongPipe(r, w *os.File) { +} diff --git a/pkg/osutil/osutil_darwin.go b/pkg/osutil/osutil_darwin.go new file mode 100644 index 000000000..fa6e3f59c --- /dev/null +++ b/pkg/osutil/osutil_darwin.go @@ -0,0 +1,11 @@ +// Copyright 2017 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 osutil + +import ( + "os" +) + +func prolongPipe(r, w *os.File) { +} diff --git a/pkg/osutil/osutil_freebsd.go b/pkg/osutil/osutil_freebsd.go new file mode 100644 index 000000000..aedbfd09d --- /dev/null +++ b/pkg/osutil/osutil_freebsd.go @@ -0,0 +1,14 @@ +// Copyright 2017 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 osutil + +import ( + "os" +) + +func UmountAll(dir string) { +} + +func prolongPipe(r, w *os.File) { +} diff --git a/pkg/osutil/osutil_fuchsia.go b/pkg/osutil/osutil_fuchsia.go index db7b041d6..e0a1f5fce 100644 --- a/pkg/osutil/osutil_fuchsia.go +++ b/pkg/osutil/osutil_fuchsia.go @@ -5,5 +5,33 @@ package osutil +import ( + "fmt" + "os" +) + func HandleInterrupts(shutdown chan struct{}) { } + +func UmountAll(dir string) { +} + +func CreateMemMappedFile(size int) (f *os.File, mem []byte, err error) { + return nil, nil, fmt.Errorf("CreateMemMappedFile is not implemented") +} + +func CloseMemMappedFile(f *os.File, mem []byte) error { + return fmt.Errorf("CloseMemMappedFile is not implemented") +} + +func ProcessExitStatus(ps *os.ProcessState) int { + // TODO: can be extracted from ExitStatus string. + return 0 +} + +func ProcessSignal(p *os.Process, sig int) bool { + return false +} + +func prolongPipe(r, w *os.File) { +} diff --git a/pkg/osutil/osutil_linux.go b/pkg/osutil/osutil_linux.go index b31905599..81fc74822 100644 --- a/pkg/osutil/osutil_linux.go +++ b/pkg/osutil/osutil_linux.go @@ -6,10 +6,26 @@ package osutil import ( + "io/ioutil" "os" + "path/filepath" "syscall" + "unsafe" ) +// UmountAll recurusively unmounts all mounts in dir. +func UmountAll(dir string) { + files, _ := ioutil.ReadDir(dir) + for _, f := range files { + name := filepath.Join(dir, f.Name()) + if f.IsDir() { + UmountAll(name) + } + fn := []byte(name + "\x00") + syscall.Syscall(syscall.SYS_UMOUNT2, uintptr(unsafe.Pointer(&fn[0])), syscall.MNT_FORCE, 0) + } +} + func prolongPipe(r, w *os.File) { for sz := 128 << 10; sz <= 2<<20; sz *= 2 { syscall.Syscall(syscall.SYS_FCNTL, w.Fd(), syscall.F_SETPIPE_SZ, uintptr(sz)) diff --git a/pkg/osutil/osutil_stub.go b/pkg/osutil/osutil_stub.go deleted file mode 100644 index 74ce2cc31..000000000 --- a/pkg/osutil/osutil_stub.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2017 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. - -// +build !linux - -package osutil - -import ( - "os" -) - -func prolongPipe(r, w *os.File) { -} diff --git a/pkg/osutil/osutil_unix.go b/pkg/osutil/osutil_unix.go index 87dc6a729..2f6a9f327 100644 --- a/pkg/osutil/osutil_unix.go +++ b/pkg/osutil/osutil_unix.go @@ -90,3 +90,68 @@ func LongPipe() (io.ReadCloser, io.WriteCloser, error) { prolongPipe(r, w) return r, w, err } + +// CreateMemMappedFile creates a temp file with the requested size and maps it into memory. +func CreateMemMappedFile(size int) (f *os.File, mem []byte, err error) { + f, err = ioutil.TempFile("./", "syzkaller-shm") + if err != nil { + err = fmt.Errorf("failed to create temp file: %v", err) + return + } + if err = f.Truncate(int64(size)); err != nil { + err = fmt.Errorf("failed to truncate shm file: %v", err) + f.Close() + os.Remove(f.Name()) + return + } + f.Close() + fname := f.Name() + f, err = os.OpenFile(f.Name(), os.O_RDWR, DefaultFilePerm) + if err != nil { + err = fmt.Errorf("failed to open shm file: %v", err) + os.Remove(fname) + return + } + mem, err = syscall.Mmap(int(f.Fd()), 0, size, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED) + if err != nil { + err = fmt.Errorf("failed to mmap shm file: %v", err) + f.Close() + os.Remove(f.Name()) + return + } + return +} + +// CloseMemMappedFile destroys memory mapping created by CreateMemMappedFile. +func CloseMemMappedFile(f *os.File, mem []byte) error { + err1 := syscall.Munmap(mem) + err2 := f.Close() + err3 := os.Remove(f.Name()) + switch { + case err1 != nil: + return err1 + case err2 != nil: + return err2 + case err3 != nil: + return err3 + default: + return nil + } +} + +// ProcessExitStatus returns process exit status. +// This is here only because of fuchsia that does not implement WaitStatus. +func ProcessExitStatus(ps *os.ProcessState) int { + return ps.Sys().(syscall.WaitStatus).ExitStatus() +} + +// ProcessSignal sends signal sig to the process, returns true if the process was killed. +// Again, this is here only because of fuchsia. +func ProcessSignal(p *os.Process, sig int) bool { + SIGKILL := int(syscall.SIGKILL) + if sig <= 0 || sig >= 32 { + sig = SIGKILL + } + p.Signal(syscall.Signal(sig)) + return sig == SIGKILL +} diff --git a/pkg/osutil/osutil_windows.go b/pkg/osutil/osutil_windows.go index 861ae8fb3..9919689d0 100644 --- a/pkg/osutil/osutil_windows.go +++ b/pkg/osutil/osutil_windows.go @@ -3,5 +3,33 @@ package osutil +import ( + "fmt" + "os" + "syscall" +) + func HandleInterrupts(shutdown chan struct{}) { } + +func UmountAll(dir string) { +} + +func prolongPipe(r, w *os.File) { +} + +func CreateMemMappedFile(size int) (f *os.File, mem []byte, err error) { + return nil, nil, fmt.Errorf("CreateMemMappedFile is not implemented") +} + +func CloseMemMappedFile(f *os.File, mem []byte) error { + return fmt.Errorf("CloseMemMappedFile is not implemented") +} + +func ProcessExitStatus(ps *os.ProcessState) int { + return ps.Sys().(syscall.WaitStatus).ExitStatus() +} + +func ProcessSignal(p *os.Process, sig int) bool { + return false +} -- cgit mrf-deployment