Implements executing of commands on qemu system
This commit is contained in:
parent
dfc1f64841
commit
5c31812089
@ -14,6 +14,8 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/ssh"
|
||||||
)
|
)
|
||||||
|
|
||||||
func readBytesUntilEOF(pipe io.ReadCloser) (buf []byte, err error) {
|
func readBytesUntilEOF(pipe io.ReadCloser) (buf []byte, err error) {
|
||||||
@ -75,7 +77,7 @@ type QemuSystem struct {
|
|||||||
stdout io.ReadCloser
|
stdout io.ReadCloser
|
||||||
}
|
}
|
||||||
died bool
|
died bool
|
||||||
sshHostFwd string
|
sshAddrPort string
|
||||||
|
|
||||||
// accessible after qemu is closed
|
// accessible after qemu is closed
|
||||||
Stdout, Stderr string
|
Stdout, Stderr string
|
||||||
@ -135,15 +137,16 @@ func kvmExists() bool {
|
|||||||
// Start qemu process
|
// Start qemu process
|
||||||
func (q *QemuSystem) Start() (err error) {
|
func (q *QemuSystem) Start() (err error) {
|
||||||
rand.Seed(time.Now().UnixNano()) // Are you sure?
|
rand.Seed(time.Now().UnixNano()) // Are you sure?
|
||||||
q.sshHostFwd = fmt.Sprintf("hostfwd=tcp:%s-:22", getFreeAddrPort())
|
q.sshAddrPort = getFreeAddrPort()
|
||||||
|
hostfwd := fmt.Sprintf("hostfwd=tcp:%s-:22", q.sshAddrPort)
|
||||||
qemuArgs := []string{"-snapshot", "-nographic",
|
qemuArgs := []string{"-snapshot", "-nographic",
|
||||||
"-hda", q.drivePath,
|
"-hda", q.drivePath,
|
||||||
"-kernel", q.kernel.Path,
|
"-kernel", q.kernel.Path,
|
||||||
"-append", "root=/dev/sda console=ttyS0 rw",
|
"-append", "root=/dev/sda ignore_loglevel console=ttyS0 rw",
|
||||||
"-smp", fmt.Sprintf("%d", q.Cpus),
|
"-smp", fmt.Sprintf("%d", q.Cpus),
|
||||||
"-m", fmt.Sprintf("%d", q.Memory),
|
"-m", fmt.Sprintf("%d", q.Memory),
|
||||||
"-device", "e1000,netdev=n1",
|
"-device", "e1000,netdev=n1",
|
||||||
"-netdev", "user,id=n1," + q.sshHostFwd,
|
"-netdev", "user,id=n1," + hostfwd,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (q.arch == X86_64 || q.arch == I386) && kvmExists() {
|
if (q.arch == X86_64 || q.arch == I386) && kvmExists() {
|
||||||
@ -197,3 +200,26 @@ func (q *QemuSystem) Stop() {
|
|||||||
q.cmd.Process.Signal(syscall.SIGKILL)
|
q.cmd.Process.Signal(syscall.SIGKILL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Command executes shell commands on qemu system
|
||||||
|
func (q *QemuSystem) Command(user, cmd string) (output string, err error) {
|
||||||
|
cfg := &ssh.ClientConfig{
|
||||||
|
User: user,
|
||||||
|
}
|
||||||
|
cfg.HostKeyCallback = ssh.InsecureIgnoreHostKey()
|
||||||
|
|
||||||
|
client, err := ssh.Dial("tcp", q.sshAddrPort, cfg)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
session, err := client.NewSession()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
bytesOutput, err := session.CombinedOutput(cmd)
|
||||||
|
output = string(bytesOutput)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
@ -6,6 +6,7 @@ package qemukernel
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -63,3 +64,39 @@ func TestGetFreeAddrPort(t *testing.T) {
|
|||||||
}
|
}
|
||||||
ln.Close()
|
ln.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestQemuSystemCommand(t *testing.T) {
|
||||||
|
// FIXME hardcoded kernel path
|
||||||
|
kernel := Kernel{Name: "Host kernel", Path: "/boot/vmlinuz-4.18.8"}
|
||||||
|
// FIXME hardcoded qcow2 path
|
||||||
|
qemu, err := NewQemuSystem(X86_64, kernel, "/home/user/qemu/sid.img")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = qemu.Start(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer qemu.Stop()
|
||||||
|
|
||||||
|
output, err := qemu.Command("root", "cat /etc/shadow")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !strings.Contains(output, "root::") {
|
||||||
|
t.Fatal("Wrong output from `cat /etc/shadow` by root")
|
||||||
|
}
|
||||||
|
|
||||||
|
output, err = qemu.Command("user", "cat /etc/passwd")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !strings.Contains(output, "root:x:0:0:root:/root:/bin/bash") {
|
||||||
|
t.Fatal("Wrong output from `cat /etc/passwd` by user")
|
||||||
|
}
|
||||||
|
|
||||||
|
output, err = qemu.Command("user", "cat /etc/shadow")
|
||||||
|
if err == nil { // unsucessful is good because user must not read /etc/shadow
|
||||||
|
t.Fatal("User have rights for /etc/shadow. WAT?!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user