#!/bin/sh set -e REGISTRY_DIR="$XDG_RUNTIME_DIR/qubes-backup-location" backup_location_id="$1" if [ -z "$backup_location_id" ]; then echo "Missing backup location ID argument" >&2 exit 1 fi if ! [ -e "$REGISTRY_DIR/$backup_location_id" ]; then echo "Invalid location ID" >&2 exit 1 fi while true; do read -r check_pid check_starttime read -r backup_location break done < "$REGISTRY_DIR/$backup_location_id" if ! [ -e "/proc/$check_pid" ]; then echo "Invalid location ID" >&2 exit 1 fi pid_starttime=$(cut -f 22 -d ' ' "/proc/$check_pid/stat") if [ "$check_starttime" != "$pid_starttime" ]; then echo "Invalid location ID" >&2 exit 1 fi # now $backup_location is verified to be still valid echo Starting Restorecopy >&2 read -r untrusted_paths echo "Backup location: $backup_location" >&2 echo "Paths: $untrusted_paths" >&2 if [ -f "$backup_location" ] ; then echo "Performing restore from backup file $backup_location" >&2 TARGET="$backup_location" echo "Copying $TARGET to STDOUT" >&2 # tar2qfile always use argv[1] for input path and the rest for selecting # paths to extract - no other options are supported, so passing # untrusted_paths directly is fine # shellcheck disable=SC2086 /usr/lib/qubes/tar2qfile "$TARGET" $untrusted_paths else echo "Checking if arguments is matching a command" >&2 COMMAND=$(echo "$backup_location" | cut -d ' ' -f 1) if command -v "$COMMAND" >/dev/null; then tmpdir=$(mktemp -d) mkfifo "$tmpdir/backup-data" echo "Redirecting $backup_location to STDOUT" >&2 # Parsing args to handle quotes correctly # Dangerous method if args are uncontrolled eval "set -- $backup_location" # Use named pipe to pass original stdin to tar2file "$@" > "$tmpdir/backup-data" < /dev/null & # shellcheck disable=SC2086 # tar2qfile always use argv[1] for input path and the rest for selecting # paths to extract - no other options are supported, so passing # untrusted_paths directly is fine /usr/lib/qubes/tar2qfile "$tmpdir/backup-data" $untrusted_paths # Restoration may be terminated earlier because of selected files. This # will be seen as EPIPE to the retrieving process, which may cause retcode # other than 0 in some cases - which would be incorrectly treated as backup # restore error. So instead of that, use tar2qfile exit code (and have dom0 # detect if anything wrong with actual data) retcode=$? wait $! rm "$tmpdir/backup-data" rmdir "$tmpdir" exit "$retcode" else echo "Invalid command $COMMAND" >&2 exit 2 fi fi