Browse Source

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
Demi Marie Obenour 3 years ago
parent
commit
ca9a496e42
2 changed files with 32 additions and 16 deletions
  1. 9 10
      qubes-rpc/admin.vm.Console
  2. 23 6
      qvm-tools/qvm-console-dispvm

+ 9 - 10
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

+ 23 - 6
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; }
+
+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; }
 
-DISPVM="$(qvm-prefs "$QREXEC_REQUESTED_TARGET" management_dispvm)"
+DISPVM="$(qvm-prefs -- "$QREXEC_REQUESTED_TARGET" management_dispvm)"
 
-[[ "x$DISPVM" == "x" ]] && { echo "Error: cannot determine management DispVM to use"; exit 1; }
+[[ "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