Compare commits
No commits in common. "6976fe1e4d4b939a008768e5b4e37db82c839435" and "a668a966693470725cfe0b6609cf697d5d08d35c" have entirely different histories.
6976fe1e4d
...
a668a96669
|
@ -1,5 +1,3 @@
|
||||||
ssh/*
|
ssh/*
|
||||||
image/*
|
image/*
|
||||||
!**/.gitkeep
|
!**/.gitkeep
|
||||||
.idea
|
|
||||||
nim/qsandbox
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# qemu-sandbox
|
# qemu-sandbox
|
||||||
|
|
||||||
PoC shell sandboxing using QEMU and virtiofsd. Simply enter `qsandbox run` to open your current working dir in a temporary QEMU vm.
|
PoC shell sandboxing using QEMU and virtiofsd. Just enter `qsandbox run` to open your current working dir in a temporary QEMU vm.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
|
12
build.sh
12
build.sh
|
@ -1,8 +1,7 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Based on https://blog.stefan-koch.name/2020/05/31/automation-archlinux-qemu-installation
|
# Based on https://blog.stefan-koch.name/2020/05/31/automation-archlinux-qemu-installation
|
||||||
|
|
||||||
src="https://mirror.rackspace.com/archlinux/iso/2021.11.01/archlinux-bootstrap-2021.11.01-x86_64.tar.gz"
|
src=https://ftp.halifax.rwth-aachen.de/archlinux/iso/2021.11.01/archlinux-bootstrap-2021.11.01-x86_64.tar.gz
|
||||||
|
|
||||||
archive=image/archlinux.tar.gz
|
archive=image/archlinux.tar.gz
|
||||||
image=image/image.raw
|
image=image/image.raw
|
||||||
mountpoint=image/arch
|
mountpoint=image/arch
|
||||||
|
@ -15,7 +14,6 @@ mkdir -p $mountpoint
|
||||||
mkdir -p ssh
|
mkdir -p ssh
|
||||||
|
|
||||||
qemu-img create -f raw $image 20G
|
qemu-img create -f raw $image 20G
|
||||||
|
|
||||||
loop="$(sudo losetup --show -f -P $image)"
|
loop="$(sudo losetup --show -f -P $image)"
|
||||||
sudo mkfs.ext4 "$loop"
|
sudo mkfs.ext4 "$loop"
|
||||||
sudo mount "$loop" "$mountpoint"
|
sudo mount "$loop" "$mountpoint"
|
||||||
|
@ -26,14 +24,16 @@ key="$(cat ssh/qemu_ssh.pub)"
|
||||||
sudo "$mountpoint/bin/arch-chroot" "$mountpoint" /bin/bash <<EOL
|
sudo "$mountpoint/bin/arch-chroot" "$mountpoint" /bin/bash <<EOL
|
||||||
set -v
|
set -v
|
||||||
|
|
||||||
echo 'Server = https://mirror.rackspace.com/archlinux/\$repo/os/\$arch' >> /etc/pacman.d/mirrorlist
|
echo 'Server = http://ftp.uni-bayreuth.de/linux/archlinux/\$repo/os/\$arch' >> /etc/pacman.d/mirrorlist
|
||||||
|
|
||||||
pacman-key --init
|
pacman-key --init
|
||||||
pacman-key --populate archlinux
|
pacman-key --populate archlinux
|
||||||
|
|
||||||
pacman -Syu --noconfirm
|
pacman -Syu --noconfirm
|
||||||
pacman -S --noconfirm base linux linux-firmware mkinitcpio openssh kitty-terminfo dhcpcd
|
pacman -S --noconfirm base linux linux-firmware mkinitcpio dhcpcd dropbear kitty-terminfo
|
||||||
systemctl enable sshd dhcpcd
|
systemctl enable dhcpcd dropbear
|
||||||
|
|
||||||
|
dropbearkey -t ed25519 -f /etc/dropbear/dropbear_ed25519_host_key
|
||||||
|
|
||||||
# Standard Archlinux Setup
|
# Standard Archlinux Setup
|
||||||
ln -sf /usr/share/zoneinfo/Europe/Berlin /etc/localtime
|
ln -sf /usr/share/zoneinfo/Europe/Berlin /etc/localtime
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
ip address add 10.0.2.15/24 broadcast + dev ens3
|
|
||||||
ip link set dev ens3 up
|
|
||||||
ip route add 10.0.2.0/24 dev ens3
|
|
||||||
ip route add default via 10.0.2.2 dev ens3
|
|
|
@ -1 +0,0 @@
|
||||||
nim rewrite, wip
|
|
|
@ -1,16 +0,0 @@
|
||||||
import std/strformat
|
|
||||||
import std/parseopt
|
|
||||||
import os
|
|
||||||
|
|
||||||
proc help*(args: OptParser) =
|
|
||||||
let bin = lastPathPart(getAppFilename())
|
|
||||||
|
|
||||||
echo "qsandbox - temporary sandboxes using qemu"
|
|
||||||
echo ""
|
|
||||||
echo "Usage:"
|
|
||||||
echo &" {bin} run - start sandbox and mount current working dir"
|
|
||||||
echo &" {bin} list - list running sandboxes"
|
|
||||||
echo &" {bin} enter - open ssh connection to a sandbox"
|
|
||||||
echo &" {bin} qemu - start the qemu process for a new sandbox, used by run"
|
|
||||||
|
|
||||||
quit(0)
|
|
|
@ -1,4 +0,0 @@
|
||||||
import std/parseopt
|
|
||||||
|
|
||||||
proc list*(args: OptParser) =
|
|
||||||
echo "list"
|
|
|
@ -1,97 +0,0 @@
|
||||||
import strformat
|
|
||||||
import parseopt
|
|
||||||
import osproc
|
|
||||||
import posix
|
|
||||||
import linux
|
|
||||||
import os
|
|
||||||
|
|
||||||
# should be in the linux module but seems to be missing
|
|
||||||
const CLONE_NEWUSER = 0x10000000'i32
|
|
||||||
|
|
||||||
# c bindings
|
|
||||||
proc unshare(flag: cint): cint {.importc, header: "<sched.h>"}
|
|
||||||
|
|
||||||
proc mount(source: cstring, target: cstring, filesystemtype: cstring,
|
|
||||||
mountflags: culong, data: pointer): cint {.importc, header:"<sys/mount.h>"}
|
|
||||||
|
|
||||||
const
|
|
||||||
UID_MAP = "/proc/self/uid_map"
|
|
||||||
GID_MAP = "/proc/self/gid_map"
|
|
||||||
SETGROUPS = "/proc/self/setgroups"
|
|
||||||
|
|
||||||
proc virtiofsd(paths: seq[string]): Pid =
|
|
||||||
let uid = getuid()
|
|
||||||
let gid = getgid()
|
|
||||||
let pid = fork()
|
|
||||||
|
|
||||||
if pid < 0:
|
|
||||||
raise newException(OSError, "Fork failed")
|
|
||||||
|
|
||||||
if pid > 0:
|
|
||||||
# we are the parent
|
|
||||||
return pid
|
|
||||||
|
|
||||||
# create new mount namespace
|
|
||||||
if unshare(CLONE_NEWUSER or CLONE_NEWNS) != 0:
|
|
||||||
raise newException(OSError, "Unshare failed")
|
|
||||||
|
|
||||||
# map our uid to root
|
|
||||||
writeFile(UID_MAP, &"0 {uid} 1")
|
|
||||||
writeFile(SETGROUPS, "deny")
|
|
||||||
writeFile(GID_MAP, &"0 {gid} 1")
|
|
||||||
|
|
||||||
# create a tmpfs in /var/run so virtiofsd can write there
|
|
||||||
if mount(cstring("tmpfs"), cstring("/var/run"), cstring("tmpfs"), 0, cstring("")) != 0:
|
|
||||||
raise newException(OSError, "Mount failed")
|
|
||||||
|
|
||||||
# start a virtiofsd process for each mount
|
|
||||||
var procs {.threadvar.}: seq[Process]
|
|
||||||
|
|
||||||
for i, path in paths:
|
|
||||||
procs.add(startProcess(
|
|
||||||
command = "/usr/lib/qemu/virtiofsd",
|
|
||||||
args = @[&"--socket-path=/tmp/mount.{i}.sock", "-o", &"source={path}"],
|
|
||||||
options = {poParentStreams}
|
|
||||||
))
|
|
||||||
|
|
||||||
onSignal(SIGTERM):
|
|
||||||
for process in procs:
|
|
||||||
terminate(process)
|
|
||||||
|
|
||||||
quit(0)
|
|
||||||
|
|
||||||
for process in procs:
|
|
||||||
discard waitForExit(process)
|
|
||||||
|
|
||||||
quit(0)
|
|
||||||
|
|
||||||
proc qemu*(args: OptParser) =
|
|
||||||
let childPid = virtiofsd(@["/tmp", "/home"])
|
|
||||||
|
|
||||||
let args = @[
|
|
||||||
"-enable-kvm", "-cpu", "host", "-m", "512m", "-smp", "2",
|
|
||||||
"-kernel", "/home/martin/code/qemu/build-image/image/vmlinuz-linux",
|
|
||||||
"-append", "earlyprintk=ttyS0 console=ttyS0 root=/dev/vda rw quiet",
|
|
||||||
"-initrd" , "/home/martin/code/qemu/build-image/image/initramfs-linux-custom.img",
|
|
||||||
"-m", "4G", "-object", "memory-backend-file,id=mem,size=4G,mem-path=/dev/shm,share=on", "-numa", "node,memdev=mem",
|
|
||||||
"-device", "virtio-rng-pci",
|
|
||||||
"-bios", "/usr/share/qemu/qboot.rom",
|
|
||||||
"-drive", "if=virtio,file=/home/martin/code/qemu/build-image/image/image.qcow2",
|
|
||||||
"-netdev", "user,id=net0,hostfwd=tcp::2222-:22",
|
|
||||||
"-device", "virtio-net-pci,netdev=net0",
|
|
||||||
"-nodefaults", "-no-user-config", "-nographic",
|
|
||||||
"-chardev", "socket,id=share.1,path=/tmp/mount.0.sock",
|
|
||||||
"-device", "vhost-user-fs-pci,queue-size=1024,chardev=share.1,tag=share.1",
|
|
||||||
"-serial", "stdio"
|
|
||||||
]
|
|
||||||
|
|
||||||
let qemu = startProcess(
|
|
||||||
command = "qemu-system-x86_64",
|
|
||||||
options = {poParentStreams, poUsePath},
|
|
||||||
args = args
|
|
||||||
)
|
|
||||||
|
|
||||||
discard waitForExit(qemu)
|
|
||||||
|
|
||||||
discard kill(childPid, SIGTERM)
|
|
||||||
discard waitPid(childPid,cast[var cint](nil),0)
|
|
|
@ -1,4 +0,0 @@
|
||||||
import std/parseopt
|
|
||||||
|
|
||||||
proc run*(args: OptParser) =
|
|
||||||
echo "Run"
|
|
|
@ -1,4 +0,0 @@
|
||||||
import std/parseopt
|
|
||||||
|
|
||||||
proc ssh*(args: OptParser) =
|
|
||||||
echo "ssh"
|
|
|
@ -1,34 +0,0 @@
|
||||||
import parseopt
|
|
||||||
|
|
||||||
import commands/help
|
|
||||||
import commands/list
|
|
||||||
import commands/qemu
|
|
||||||
import commands/run
|
|
||||||
import commands/ssh
|
|
||||||
|
|
||||||
proc cmd (options: OptParser) =
|
|
||||||
case options.key:
|
|
||||||
of "qemu":
|
|
||||||
qemu(options)
|
|
||||||
of "run":
|
|
||||||
run(options)
|
|
||||||
of "ssh":
|
|
||||||
ssh(options)
|
|
||||||
of "list":
|
|
||||||
list(options)
|
|
||||||
else:
|
|
||||||
help(options)
|
|
||||||
|
|
||||||
proc main () =
|
|
||||||
var options = initOptParser()
|
|
||||||
options.next()
|
|
||||||
|
|
||||||
case options.kind
|
|
||||||
of cmdEnd: help(options)
|
|
||||||
of cmdShortOption, cmdLongOption:
|
|
||||||
echo "Unkown argument"
|
|
||||||
quit(1)
|
|
||||||
of cmdArgument:
|
|
||||||
cmd(options)
|
|
||||||
|
|
||||||
main()
|
|
2
qsandbox
2
qsandbox
|
@ -82,6 +82,8 @@ function run {
|
||||||
|
|
||||||
tmp_dir="$(mktemp -d --suffix=.qemu)"
|
tmp_dir="$(mktemp -d --suffix=.qemu)"
|
||||||
|
|
||||||
|
echo "$work_dir"
|
||||||
|
|
||||||
echo "$ssh_port" > "$tmp_dir/ssh"
|
echo "$ssh_port" > "$tmp_dir/ssh"
|
||||||
echo "$ssh_port" > "$tmp_dir/app"
|
echo "$ssh_port" > "$tmp_dir/app"
|
||||||
echo "$work_dir" > "$tmp_dir/work_dir"
|
echo "$work_dir" > "$tmp_dir/work_dir"
|
||||||
|
|
Loading…
Reference in New Issue