From d4b1794c15965337ef339623d22056cdeee0ae9c Mon Sep 17 00:00:00 2001 From: Rusty Bird Date: Mon, 15 Feb 2021 15:14:03 +0000 Subject: [PATCH] storage: avoid concurrent umask() umask() modifies the whole process, which could lead to odd permission problems in concurrent code. Use explicit fchmod() calls instead. Preserve the legacy storage/file behavior of creating files 0o664 in FileVolume.create() and 0o644 (from the normal qubesd umask) otherwise. --- qubes/storage/__init__.py | 2 -- qubes/storage/file.py | 6 ++++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/qubes/storage/__init__.py b/qubes/storage/__init__.py index 468c08de..aabcf3f5 100644 --- a/qubes/storage/__init__.py +++ b/qubes/storage/__init__.py @@ -540,10 +540,8 @@ class Storage: @asyncio.coroutine def create(self): ''' Creates volumes on disk ''' - old_umask = os.umask(0o002) yield from qubes.utils.void_coros_maybe( vol.create() for vol in self.vm.volumes.values()) - os.umask(old_umask) @asyncio.coroutine def clone_volume(self, src_vm, name): diff --git a/qubes/storage/file.py b/qubes/storage/file.py index 789ff35c..086d1da9 100644 --- a/qubes/storage/file.py +++ b/qubes/storage/file.py @@ -211,7 +211,7 @@ class FileVolume(qubes.storage.Volume): assert isinstance(self.size, int) and self.size > 0, \ 'Volume size must be > 0' if not self.snap_on_start: - create_sparse_file(self.path, self.size) + create_sparse_file(self.path, self.size, permissions=0o664) def remove(self): if not self.snap_on_start: @@ -455,7 +455,7 @@ class FileVolume(qubes.storage.Volume): -def create_sparse_file(path, size): +def create_sparse_file(path, size, permissions=None): ''' Create an empty sparse file ''' if os.path.exists(path): raise IOError("Volume %s already exists" % path) @@ -463,6 +463,8 @@ def create_sparse_file(path, size): if not os.path.exists(parent_dir): os.makedirs(parent_dir) with open(path, 'a+b') as fh: + if permissions is not None: + os.fchmod(fh.fileno(), permissions) fh.truncate(size)