mirror of
https://github.com/reactos/syzkaller.git
synced 2024-12-12 13:56:12 +00:00
c4d43f4773
When manager is stopped there are sometimes runaway qemu processes still running. Set PDEATHSIG for all subprocesses. We never need child processes outliving parents.
139 lines
3.2 KiB
Go
139 lines
3.2 KiB
Go
// 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 vmimpl
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"os/exec"
|
|
"sync"
|
|
"syscall"
|
|
"unsafe"
|
|
|
|
"github.com/google/syzkaller/pkg/osutil"
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
// Tested on Suzy-Q and BeagleBone.
|
|
func OpenConsole(con string) (rc io.ReadCloser, err error) {
|
|
fd, err := syscall.Open(con, syscall.O_RDONLY|syscall.O_NOCTTY|syscall.O_SYNC, 0)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to open console file: %v", err)
|
|
}
|
|
defer func() {
|
|
if fd != -1 {
|
|
syscall.Close(fd)
|
|
}
|
|
}()
|
|
var term unix.Termios
|
|
if _, _, errno := syscall.Syscall(unix.SYS_IOCTL, uintptr(fd), syscall_TCGETS, uintptr(unsafe.Pointer(&term))); errno != 0 {
|
|
return nil, fmt.Errorf("failed to get console termios: %v", errno)
|
|
}
|
|
// no parity bit, only need 1 stop bit, no hardware flowcontrol
|
|
term.Cflag &^= unix_CBAUD | unix.CSIZE | unix.PARENB | unix.CSTOPB | unix_CRTSCTS
|
|
// ignore modem controls
|
|
term.Cflag |= unix.B115200 | unix.CS8 | unix.CLOCAL | unix.CREAD
|
|
// setup for non-canonical mode
|
|
term.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON
|
|
term.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN
|
|
term.Oflag &^= unix.OPOST
|
|
term.Cc[unix.VMIN] = 0
|
|
term.Cc[unix.VTIME] = 10 // 1 second timeout
|
|
if _, _, errno := syscall.Syscall(unix.SYS_IOCTL, uintptr(fd), syscall_TCSETS, uintptr(unsafe.Pointer(&term))); errno != 0 {
|
|
return nil, fmt.Errorf("failed to get console termios: %v", errno)
|
|
}
|
|
tmp := fd
|
|
fd = -1
|
|
return &tty{fd: tmp}, nil
|
|
}
|
|
|
|
type tty struct {
|
|
mu sync.Mutex
|
|
fd int
|
|
}
|
|
|
|
func (t *tty) Read(buf []byte) (int, error) {
|
|
t.mu.Lock()
|
|
defer t.mu.Unlock()
|
|
if t.fd == -1 {
|
|
return 0, io.EOF
|
|
}
|
|
n, err := syscall.Read(t.fd, buf)
|
|
if n < 0 {
|
|
n = 0
|
|
}
|
|
return n, err
|
|
}
|
|
|
|
func (t *tty) Close() error {
|
|
t.mu.Lock()
|
|
defer t.mu.Unlock()
|
|
if t.fd != -1 {
|
|
syscall.Close(t.fd)
|
|
t.fd = -1
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Open dmesg remotely
|
|
func OpenRemoteConsole(bin string, args ...string) (rc io.ReadCloser, err error) {
|
|
rpipe, wpipe, err := osutil.LongPipe()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
args = append(args, "dmesg -w")
|
|
cmd := osutil.Command(bin, args...)
|
|
cmd.Stdout = wpipe
|
|
cmd.Stderr = wpipe
|
|
if err := cmd.Start(); err != nil {
|
|
rpipe.Close()
|
|
wpipe.Close()
|
|
return nil, fmt.Errorf("failed to start adb: %v", err)
|
|
}
|
|
wpipe.Close()
|
|
con := &remoteCon{
|
|
cmd: cmd,
|
|
rpipe: rpipe,
|
|
}
|
|
return con, err
|
|
}
|
|
|
|
// OpenAdbConsole provides fallback console output using 'adb shell dmesg -w'.
|
|
func OpenAdbConsole(bin, dev string) (rc io.ReadCloser, err error) {
|
|
return OpenRemoteConsole(bin, "-s", dev, "shell")
|
|
}
|
|
|
|
type remoteCon struct {
|
|
closeMu sync.Mutex
|
|
readMu sync.Mutex
|
|
cmd *exec.Cmd
|
|
rpipe io.ReadCloser
|
|
}
|
|
|
|
func (t *remoteCon) Read(buf []byte) (int, error) {
|
|
t.readMu.Lock()
|
|
n, err := t.rpipe.Read(buf)
|
|
t.readMu.Unlock()
|
|
return n, err
|
|
}
|
|
|
|
func (t *remoteCon) Close() error {
|
|
t.closeMu.Lock()
|
|
cmd := t.cmd
|
|
t.cmd = nil
|
|
t.closeMu.Unlock()
|
|
if cmd == nil {
|
|
return nil
|
|
}
|
|
|
|
cmd.Process.Kill()
|
|
|
|
t.readMu.Lock()
|
|
t.rpipe.Close()
|
|
t.readMu.Unlock()
|
|
|
|
cmd.Process.Wait()
|
|
return nil
|
|
}
|