From ca9a496e421dd0375414481a361ade8cc2bcf643 Mon Sep 17 00:00:00 2001 From: Demi Marie Obenour Date: Thu, 26 Nov 2020 21:15:34 -0500 Subject: [PATCH] Enhance qvm-console-dispvm and admin.vm.Console - use `/run` instead of deprecated symlink `/var/run` - add `--autostart` option to automatically start the qube - check for invalid qube name before querying qubesd - use `--fail` option of qubesd-query instead of parsing its output file - add `--` and double quotes in various places - allow `--` to be passed to `qvm-console-dispvm` to mark end of options --- qubes-rpc/admin.vm.Console | 19 +++++++++---------- qvm-tools/qvm-console-dispvm | 29 +++++++++++++++++++++++------ 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/qubes-rpc/admin.vm.Console b/qubes-rpc/admin.vm.Console index 4dcb2c7d..d69e553e 100755 --- a/qubes-rpc/admin.vm.Console +++ b/qubes-rpc/admin.vm.Console @@ -1,22 +1,21 @@ -#!/bin/bash +#!/bin/bash -- +set -euo pipefail -lock="/var/run/qubes/$QREXEC_REQUESTED_TARGET.terminal.lock" +lock="/run/qubes/$QREXEC_REQUESTED_TARGET.terminal.lock" # use temporary file, because env variables deal poorly with \0 inside tmpfile=$(mktemp) -trap "rm -f $tmpfile" EXIT -qubesd-query -e \ +trap 'rm -f -- "$tmpfile"' EXIT +# exit if qubesd returned an error +if ! qubesd-query -e --fail -- \ "$QREXEC_REMOTE_DOMAIN" \ "admin.vm.Console" \ "$QREXEC_REQUESTED_TARGET" \ - "$1" >$tmpfile - -# exit if qubesd returned an error (not '0\0') -if [ "$(head -c 2 $tmpfile | xxd -p)" != "3000" ]; then - cat "$tmpfile" + ${1+"$1"} >"$tmpfile"; then + cat -- "$tmpfile" exit 1 fi -path=$(tail -c +3 "$tmpfile") +path=$(tail -c +3 -- "$tmpfile") # Create an exclusive lock to ensure that multiple qubes cannot access to the same socket # In the case of multiple qrexec calls it returns a specific exit code diff --git a/qvm-tools/qvm-console-dispvm b/qvm-tools/qvm-console-dispvm index d676b839..21b1bce9 100755 --- a/qvm-tools/qvm-console-dispvm +++ b/qvm-tools/qvm-console-dispvm @@ -1,22 +1,39 @@ -#!/bin/bash +#!/bin/bash -- +set -eu print_usage() { cat >&2 << USAGE -Usage: $0 vmname +Usage: $0 [--autostart] [--] vmname Connects to VM console throught DispVM using the qubes.ShowInTerminal RPC service. +With --autostart, start the VM first. USAGE } -if [ $# -lt 1 ]; then +do_start=false +if [[ $# -ge 2 ]] && [[ "$1" = '--autostart' ]]; then + do_start=: + shift +fi +if [[ $# -eq 2 ]] && [[ "$1" = '--' ]]; then + shift +elif [ $# -ne 1 ]; then print_usage exit 1 fi QREXEC_REQUESTED_TARGET="$1" -qvm-check --quiet --running "$QREXEC_REQUESTED_TARGET" > /dev/null 2>&1 || { echo "Error: domain '$QREXEC_REQUESTED_TARGET' does not exist or is not running"; exit 1; } +[[ "$QREXEC_REQUESTED_TARGET" =~ ^[A-Za-z][A-Za-z0-9_-]*$ ]] || { printf 'Invalid qube name %q\n' "$QREXEC_REQUESTED_TARGET">&2; exit 1; } -DISPVM="$(qvm-prefs "$QREXEC_REQUESTED_TARGET" management_dispvm)" +if "$do_start"; then + msg='cannot be started' + qvm-start --skip-if-running -- "$QREXEC_REQUESTED_TARGET" +else + msg='is not running' + qvm-check --quiet --running -- "$QREXEC_REQUESTED_TARGET" +fi > /dev/null 2>&1 || { echo "Error: domain '$QREXEC_REQUESTED_TARGET' does not exist or $msg">&2; exit 1; } -[[ "x$DISPVM" == "x" ]] && { echo "Error: cannot determine management DispVM to use"; exit 1; } +DISPVM="$(qvm-prefs -- "$QREXEC_REQUESTED_TARGET" management_dispvm)" + +[[ "x$DISPVM" == "x" ]] && { echo "Error: cannot determine management DispVM of domain '$QREXEC_REQUESTED_TARGET'">&2; exit 1; } sudo qvm-run -p --localcmd="QREXEC_REQUESTED_TARGET=$QREXEC_REQUESTED_TARGET QREXEC_REMOTE_DOMAIN=dom0 /etc/qubes-rpc/admin.vm.Console" --service --dispvm="$DISPVM" -- qubes.ShowInTerminal