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.
This commit is contained in:
Rusty Bird 2021-02-15 15:14:03 +00:00
parent 5d2fe7643c
commit d4b1794c15
No known key found for this signature in database
GPG Key ID: 469D78F47AAF2ADF
2 changed files with 4 additions and 4 deletions

View File

@ -540,10 +540,8 @@ class Storage:
@asyncio.coroutine @asyncio.coroutine
def create(self): def create(self):
''' Creates volumes on disk ''' ''' Creates volumes on disk '''
old_umask = os.umask(0o002)
yield from qubes.utils.void_coros_maybe( yield from qubes.utils.void_coros_maybe(
vol.create() for vol in self.vm.volumes.values()) vol.create() for vol in self.vm.volumes.values())
os.umask(old_umask)
@asyncio.coroutine @asyncio.coroutine
def clone_volume(self, src_vm, name): def clone_volume(self, src_vm, name):

View File

@ -211,7 +211,7 @@ class FileVolume(qubes.storage.Volume):
assert isinstance(self.size, int) and self.size > 0, \ assert isinstance(self.size, int) and self.size > 0, \
'Volume size must be > 0' 'Volume size must be > 0'
if not self.snap_on_start: 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): def remove(self):
if not self.snap_on_start: 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 ''' ''' Create an empty sparse file '''
if os.path.exists(path): if os.path.exists(path):
raise IOError("Volume %s already 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): if not os.path.exists(parent_dir):
os.makedirs(parent_dir) os.makedirs(parent_dir)
with open(path, 'a+b') as fh: with open(path, 'a+b') as fh:
if permissions is not None:
os.fchmod(fh.fileno(), permissions)
fh.truncate(size) fh.truncate(size)