Skip to content

Commit b04d611

Browse files
committed
Open block devices in qubesd
This makes race conditions (e.g. against udev) more obviously impossible. It also allows perfoming verification steps on the block device if that becomes necessary in the future.
1 parent 067b493 commit b04d611

1 file changed

Lines changed: 31 additions & 23 deletions

File tree

qubes/backup.py

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -640,29 +640,37 @@ async def _wrap_and_send_files(self, files_to_backup, output_queue):
640640
os.path.basename(path)
641641
])
642642
file_stat = os.stat(path)
643-
if stat.S_ISBLK(file_stat.st_mode) or \
644-
file_info.name != os.path.basename(path):
645-
# tar doesn't handle content of block device, use our
646-
# writer
647-
# also use our tar writer when renaming file
648-
assert not stat.S_ISDIR(file_stat.st_mode), \
649-
"Renaming directories not supported"
650-
tar_cmdline = ['python3', '-m', 'qubes.tarwriter',
651-
'--override-name=%s' % (
652-
os.path.join(file_info.subdir, os.path.basename(
653-
file_info.name))),
654-
path]
655-
if self.compressed:
656-
tar_cmdline.insert(-2,
657-
"--use-compress-program=%s" % self.compression_filter)
658-
659-
self.log.debug(" ".join(tar_cmdline))
660-
661-
# Pipe: tar-sparse | scrypt | tar | backup_target
662-
# TODO: log handle stderr
663-
# pylint: disable=not-an-iterable
664-
tar_sparse = await asyncio.create_subprocess_exec(
665-
*tar_cmdline, stdout=subprocess.PIPE)
643+
fd_to_close = None
644+
subprocess_kwargs = {'stdout': subprocess.PIPE}
645+
try:
646+
if stat.S_ISBLK(file_stat.st_mode) or \
647+
file_info.name != os.path.basename(path):
648+
# tar doesn't handle content of block device, use our
649+
# writer
650+
# also use our tar writer when renaming file
651+
assert not stat.S_ISDIR(file_stat.st_mode), \
652+
"Renaming directories not supported"
653+
# pylint: disable=line-too-long
654+
fd_to_close = os.open(path, os.O_RDONLY | os.O_NOCTTY | os.O_CLOEXEC)
655+
subprocess_kwargs['stdin'] = fd_to_close
656+
tar_cmdline = ['python3', '-m', 'qubes.tarwriter',
657+
'--override-name=%s' % (
658+
os.path.join(subdir, os.path.basename(
659+
file_info.name))),
660+
'/proc/self/fd/0']
661+
if self.compressed:
662+
tar_cmdline.insert(-2,
663+
"--use-compress-program=" + self.compression_filter)
664+
665+
# Pipe: tar-sparse | scrypt | tar | backup_target
666+
# TODO: log handle stderr
667+
# pylint: disable=not-an-iterable
668+
tar_sparse = await asyncio.create_subprocess_exec(
669+
*tar_cmdline, **subprocess_kwargs)
670+
finally:
671+
if fd_to_close is not None:
672+
os.close(fd_to_close)
673+
del fd_to_close, subprocess_kwargs
666674

667675
try:
668676
await self._split_and_send(

0 commit comments

Comments
 (0)