12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758 |
- #!/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"
|