3cacf290bb
Implement this in two parts: 1. Permissions checks, getting a path from appropriate storage pool 2. Actual data import The first part is done by qubesd in a standard way, but then, instead of accepting all the data (which may be several GB), return a path to which a shell script (in practice: `dd` command) will write the data. Then the script call back to qubesd again to report success/failure and qubesd response from that call is actually returned to the user. 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. QubesOS/qubes-issues#2622
36 lines
950 B
Bash
Executable File
36 lines
950 B
Bash
Executable File
#!/bin/sh
|
|
|
|
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 dd bs=4k of="$path" count="$size" iflag=count_bytes \
|
|
conv=sparse,notrunc,nocreat,fdatasync; 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"
|