Merge remote-tracking branch 'origin/pr/184'
* origin/pr/184: Add services for paranoid backup restore mode qfile-unpacker: add option (-w) to wait for disk space before extracting tar2qfile: fix argument parser qfile-unpacker: add option for custom user and target directory
This commit is contained in:
commit
0f3e1ae8af
2
debian/qubes-core-agent.install
vendored
2
debian/qubes-core-agent.install
vendored
@ -18,7 +18,9 @@ etc/qubes-rpc/qubes.InstallUpdatesGUI
|
||||
etc/qubes-rpc/qubes.OpenInVM
|
||||
etc/qubes-rpc/qubes.OpenURL
|
||||
etc/qubes-rpc/qubes.PostInstall
|
||||
etc/qubes-rpc/qubes.RegisterBackupLocation
|
||||
etc/qubes-rpc/qubes.ResizeDisk
|
||||
etc/qubes-rpc/qubes.RestoreById
|
||||
etc/qubes-rpc/qubes.Restore
|
||||
etc/qubes-rpc/qubes.SelectDirectory
|
||||
etc/qubes-rpc/qubes.SelectFile
|
||||
|
@ -60,6 +60,8 @@ install:
|
||||
qubes.WaitForSession \
|
||||
qubes.DetachPciDevice \
|
||||
qubes.Backup qubes.Restore \
|
||||
qubes.RegisterBackupLocation \
|
||||
qubes.RestoreById \
|
||||
qubes.SelectFile qubes.SelectDirectory \
|
||||
qubes.GetImageRGBA \
|
||||
qubes.SetDateTime \
|
||||
|
@ -36,7 +36,7 @@ char *prepare_creds_return_dir(int uid)
|
||||
return pwd->pw_dir;
|
||||
}
|
||||
|
||||
int main(int argc __attribute((__unused__)), char ** argv __attribute__((__unused__)))
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
char *home_dir;
|
||||
char *incoming_dir_root;
|
||||
@ -46,22 +46,45 @@ int main(int argc __attribute((__unused__)), char ** argv __attribute__((__unuse
|
||||
const char *remote_domain;
|
||||
char *procdir_path;
|
||||
int procfs_fd;
|
||||
int i;
|
||||
|
||||
uid = getuid();
|
||||
home_dir = prepare_creds_return_dir(uid);
|
||||
if (argc >= 3) {
|
||||
errno = 0;
|
||||
uid = strtol(argv[1], NULL, 10);
|
||||
if (errno)
|
||||
gui_fatal("Invalid user ID argument");
|
||||
home_dir = prepare_creds_return_dir(uid);
|
||||
incoming_dir = argv[2];
|
||||
} else {
|
||||
uid = getuid();
|
||||
home_dir = prepare_creds_return_dir(uid);
|
||||
remote_domain = getenv("QREXEC_REMOTE_DOMAIN");
|
||||
if (!remote_domain) {
|
||||
gui_fatal("Cannot get remote domain name");
|
||||
}
|
||||
|
||||
remote_domain = getenv("QREXEC_REMOTE_DOMAIN");
|
||||
if (!remote_domain) {
|
||||
gui_fatal("Cannot get remote domain name");
|
||||
if (asprintf(&incoming_dir_root, "%s/%s", home_dir, INCOMING_DIR_NAME) < 0) {
|
||||
gui_fatal("Error allocating memory");
|
||||
}
|
||||
mkdir(incoming_dir_root, 0700);
|
||||
if (asprintf(&incoming_dir, "%s/%s", incoming_dir_root, remote_domain) < 0)
|
||||
gui_fatal("Error allocating memory");
|
||||
mkdir(incoming_dir, 0700);
|
||||
}
|
||||
|
||||
if (asprintf(&incoming_dir_root, "%s/%s", home_dir, INCOMING_DIR_NAME) < 0) {
|
||||
gui_fatal("Error allocating memory");
|
||||
for (i = 3; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-v") == 0)
|
||||
set_verbose(1);
|
||||
else if (strcmp(argv[i], "-w") == 0)
|
||||
if (i+1 < argc && argv[i+1][0] != '-') {
|
||||
set_wait_for_space(atoi(argv[i+1]));
|
||||
i++;
|
||||
} else
|
||||
set_wait_for_space(1);
|
||||
else
|
||||
gui_fatal("Invalid option %s", argv[i]);
|
||||
}
|
||||
mkdir(incoming_dir_root, 0700);
|
||||
if (asprintf(&incoming_dir, "%s/%s", incoming_dir_root, remote_domain) < 0)
|
||||
gui_fatal("Error allocating memory");
|
||||
mkdir(incoming_dir, 0700);
|
||||
|
||||
if (chdir(incoming_dir))
|
||||
gui_fatal("Error chdir to %s", incoming_dir);
|
||||
|
||||
|
33
qubes-rpc/qubes.RegisterBackupLocation
Normal file
33
qubes-rpc/qubes.RegisterBackupLocation
Normal file
@ -0,0 +1,33 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Register backup location (path or a command) to be retrieved with qubes
|
||||
# .RestoreById service.
|
||||
# Registered location is only valid as long as this service call stays open
|
||||
|
||||
set -e
|
||||
|
||||
REGISTRY_DIR="$XDG_RUNTIME_DIR/qubes-backup-location"
|
||||
|
||||
if ! [ -d "$REGISTRY_DIR" ]; then
|
||||
mkdir -p "$REGISTRY_DIR"
|
||||
fi
|
||||
|
||||
read -r backup_location
|
||||
|
||||
REGISTRY_FILE=$(mktemp "$REGISTRY_DIR/XXXXXXXX")
|
||||
|
||||
PID=$$
|
||||
# this isn't perfetct, as comm field could contain spaces, but we do control
|
||||
# this value and we know it doesn't
|
||||
START_TIME=$(cut -f 22 -d ' ' /proc/$PID/stat)
|
||||
# add process id at the beginning to help verifying if it's still running;
|
||||
# record starttime too, to detect PID reuse
|
||||
printf "%d %d\n%s\n" "$PID" "$START_TIME" "$backup_location" >"$REGISTRY_FILE"
|
||||
# output registered ID to the user
|
||||
basename "$REGISTRY_FILE"
|
||||
# close stdout
|
||||
exec >&-
|
||||
# wait for stdin to close
|
||||
cat >/dev/null
|
||||
# and cleanup
|
||||
rm -f "$REGISTRY_FILE"
|
82
qubes-rpc/qubes.RestoreById
Executable file
82
qubes-rpc/qubes.RestoreById
Executable file
@ -0,0 +1,82 @@
|
||||
#!/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
|
@ -957,7 +957,6 @@ void tar_file_processor(int fd, struct filters *filters)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
char *entry;
|
||||
int fd = -1;
|
||||
int use_stdin = 1;
|
||||
@ -967,18 +966,15 @@ int main(int argc, char **argv)
|
||||
/* when extracting backup header, dom0 will terminate the transfer with
|
||||
* EDQUOT just after getting qubes.xml */
|
||||
set_ignore_quota_error(1);
|
||||
for (i = 1; i < argc; i++) {
|
||||
set_nonblock(0);
|
||||
if (strcmp(argv[i], "-")==0) {
|
||||
set_nonblock(0);
|
||||
if (argc > 1) {
|
||||
if (strcmp(argv[1], "-")==0) {
|
||||
use_stdin = 1;
|
||||
i++;
|
||||
break;
|
||||
} else {
|
||||
// Parse tar file
|
||||
use_stdin = 0;
|
||||
entry = argv[i];
|
||||
entry = argv[1];
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,"Parsing file %s\n",entry);
|
||||
fprintf(stderr, "Parsing file %s\n",entry);
|
||||
#endif
|
||||
|
||||
fd = open(entry, O_RDONLY);
|
||||
@ -986,12 +982,14 @@ int main(int argc, char **argv)
|
||||
fprintf(stderr,"Error opening file %s\n",entry);
|
||||
exit(2);
|
||||
}
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
filters.filters_count = argc-i;
|
||||
filters.filters = argv+i;
|
||||
// Parse tar file
|
||||
if (argc > 2)
|
||||
filters.filters_count = argc-2;
|
||||
else
|
||||
filters.filters_count = 0;
|
||||
filters.filters = argv+2;
|
||||
filters.filters_matches = calloc(filters.filters_count, sizeof(int));
|
||||
if (filters.filters_matches == NULL) {
|
||||
perror("calloc");
|
||||
|
@ -590,6 +590,8 @@ rm -f %{name}-%{version}
|
||||
%config(noreplace) /etc/qubes-rpc/qubes.DetachPciDevice
|
||||
%config(noreplace) /etc/qubes-rpc/qubes.Backup
|
||||
%config(noreplace) /etc/qubes-rpc/qubes.Restore
|
||||
%config(noreplace) /etc/qubes-rpc/qubes.RegisterBackupLocation
|
||||
%config(noreplace) /etc/qubes-rpc/qubes.RestoreById
|
||||
%config(noreplace) /etc/qubes-rpc/qubes.SelectFile
|
||||
%config(noreplace) /etc/qubes-rpc/qubes.SelectDirectory
|
||||
%config(noreplace) /etc/qubes-rpc/qubes.GetImageRGBA
|
||||
|
Loading…
Reference in New Issue
Block a user