set -eu
export PATH={ path }
log() \{
if [[ -e /dev/kmsg ]]; then
echo "<6>vmtest: $*" >/dev/kmsg
else
echo "vmtest: $*"
fi
}
/bin/mount -t proc -o nosuid,nodev,noexec proc /proc
trap 'poweroff -f' EXIT
umask 022
if ! mount | grep -q " /dev "; then
log "devtmpfs not automounted, mounting at /dev"
mkdir -p /dev
mount -t devtmpfs -o nosuid,noexec dev /dev
fi
if [[ ! -d /dev/shm ]]; then
log "Mounting tmpfs at /dev/shm"
mkdir /dev/shm
mount -t tmpfs -o nosuid,nodev tmpfs /dev/shm
fi
log "Mounting tmpfs at /run"
mount -t tmpfs -o nosuid,nodev tmpfs /run
ln -s /var/run ../run
log "Mounting sysfs at /sys"
mount -t sysfs -o nosuid,nodev,noexec sys /sys
log "Mounting debugfs at /sys/kernel/debug"
mount -t debugfs debugfs /sys/kernel/debug || log "Failed to mount debugfs. CONFIG_DEBUG_FS might be missing from the kernel config"
log "Mounting tracefs at /sys/kernel/debug/tracing"
mount -t tracefs tracefs /sys/kernel/debug/tracing || log "Failed to mount tracefs. CONFIG_DEBUG_FS might be missing from the kernel config"
log "Mounting cgroup2 at /sys/fs/cgroup"
mount -t cgroup2 -o nosuid,nodev,noexec cgroup2 /sys/fs/cgroup
log "Mounting tmpfs at /mnt"
mount -t tmpfs -o nosuid,nodev tmpfs /mnt
log "Symlink /dev/fd to /proc/self/fd"
[[ -a /dev/fd ]] || ln -s /proc/self/fd /dev/fd
log "Init done"
vport=
for dir in /sys/class/virtio-ports/*; do
if [[ "$(cat "$dir/name")" == "org.qemu.guest_agent.0" ]]; then
vport_name=$(basename "$dir")
vport="/dev/$\{vport_name}"
fi
done
if [[ -z "$vport" ]]; then
log "Failed to locate qemu-guest-agent virtio-port"
exit 1
fi
log "Located qemu-guest-agent virtio port: $\{vport}"
# Send QGA logs out via kmsg if possible
qga_logs=
if [[ -e /dev/kmsg ]]; then
qga_logs="--logfile /dev/kmsg"
fi
log "Spawning qemu-ga in the background"
# These --statedir and --pidfile match th default on typical QEMU builds, but
# versions exist where the default is something else. See
# https://github.com/danobi/vmtest/issues/101
qemu-ga --statedir /var/run --pidfile /var/run/qemu-ga.pid \
--method=virtio-serial --path="$vport" $qga_logs -d
# Run a login shell
# In non-interactive mode, init will block on the shell process. The VM will be killed through QMP.
# In interactive mode, the user will be given a prompt, exiting the shell will trigger the trap function.
# We use `setsid` to make stdin a controlling tty and create a new session.
# https://stackoverflow.com/a/77840840
setsid --ctty --wait /bin/bash --login