21c3c2507e
Not sure how this ever worked before, if it did. The device nodes pointed to by /dev/qubes_dom0/* are owned by root:disk with perms 660, qubes user is not in disk group, and service is invoked as qubes user, not root.
59 lines
2.2 KiB
Bash
Executable File
59 lines
2.2 KiB
Bash
Executable File
#!/bin/sh
|
|
#
|
|
# This Admin API call is implemented as a custom script, instead of dumb
|
|
# passthrough to qubesd because it may get huge amount of data (whole root.img
|
|
# for example). qubesd cannot handle it because:
|
|
# 1. It loads the whole payload into memory, before even start looking at it
|
|
# (and later, do not allow to modify/append it).
|
|
# 2. There is 64kB limit on payload size that qubesd can handle (because of
|
|
# point 1).
|
|
# 3. Performance reasons (qubesd is not optimized for performance, passing
|
|
# such large data stream through it would take ages).
|
|
#
|
|
# The whole admin.vm.volume.Import consists of:
|
|
# 1. Permissions checks, getting a path from appropriate storage pool (done
|
|
# by qubesd)
|
|
# 2. Actual data import (done by this script, using dd)
|
|
# 3. Report final result, produce final response to the caller (done by
|
|
# qubesd)
|
|
#
|
|
# This way we do not pass all the data through qubesd, but still can
|
|
# control the process from there in a meaningful way. Note that the last
|
|
# part (second call to qubesd) may perform all kind of verification (like
|
|
# a signature check on the data, or so) and can also prevent VM from
|
|
# starting (hooking also domain-pre-start event) from not verified image.
|
|
|
|
set -e
|
|
|
|
# use temporary file, because env variables deal poorly with \0 inside
|
|
tmpfile=$(mktemp)
|
|
trap "rm -f $tmpfile" EXIT
|
|
qubesd-query -e \
|
|
"$QREXEC_REMOTE_DOMAIN" \
|
|
"admin.vm.volume.Import" \
|
|
"$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"
|
|
exit 1
|
|
fi
|
|
size=$(tail -c +3 "$tmpfile"|cut -d ' ' -f 1)
|
|
path=$(tail -c +3 "$tmpfile"|cut -d ' ' -f 2)
|
|
|
|
# now process stdin into this path
|
|
if sudo dd bs=4k of="$path" count="$size" iflag=count_bytes,fullblock \
|
|
conv=sparse,notrunc,nocreat,fdatasync status=none; then
|
|
status="ok"
|
|
else
|
|
status="fail"
|
|
fi
|
|
|
|
# send status notification to qubesd, and pass its response to the caller
|
|
echo -n "$status" | qubesd-query -c /var/run/qubesd.internal.sock \
|
|
"$QREXEC_REMOTE_DOMAIN" \
|
|
"internal.vm.volume.ImportEnd" \
|
|
"$QREXEC_REQUESTED_TARGET" \
|
|
"$1"
|