summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/spack/llnl/util/filesystem.py25
-rw-r--r--lib/spack/spack/directory_layout.py13
2 files changed, 37 insertions, 1 deletions
diff --git a/lib/spack/llnl/util/filesystem.py b/lib/spack/llnl/util/filesystem.py
index ced29ad760..e58f657aea 100644
--- a/lib/spack/llnl/util/filesystem.py
+++ b/lib/spack/llnl/util/filesystem.py
@@ -423,14 +423,39 @@ def mkdirp(*paths, **kwargs):
Keyword Aguments:
mode (permission bits or None, optional): optional permissions to
set on the created directory -- use OS default if not provided
+ mode_intermediate (permission bits or None, optional):
+ same as mode, but for newly-created intermediate directories
"""
mode = kwargs.get('mode', None)
+ mode_intermediate = kwargs.get('mode_intermediate', None)
for path in paths:
if not os.path.exists(path):
try:
+ intermediate_folders = []
+ if mode_intermediate is not None:
+ # detect missing intermediate folders
+ intermediate_path = os.path.dirname(path)
+
+ while intermediate_path:
+ if os.path.exists(intermediate_path):
+ break
+
+ intermediate_folders.append(intermediate_path)
+ intermediate_path = os.path.dirname(intermediate_path)
+
+ # create folders
os.makedirs(path)
+
+ # leaf folder permissions
if mode is not None:
os.chmod(path, mode)
+
+ # for intermediate folders, change mode just for newly created
+ # ones and if mode_intermediate has been specified, otherwise
+ # intermediate folders list is not populated at all and default
+ # OS mode will be used
+ for intermediate_path in reversed(intermediate_folders):
+ os.chmod(intermediate_path, mode_intermediate)
except OSError as e:
if e.errno != errno.EEXIST or not os.path.isdir(path):
raise e
diff --git a/lib/spack/spack/directory_layout.py b/lib/spack/spack/directory_layout.py
index 5ba8ac144c..35a8e4dcc5 100644
--- a/lib/spack/spack/directory_layout.py
+++ b/lib/spack/spack/directory_layout.py
@@ -254,15 +254,26 @@ class YamlDirectoryLayout(DirectoryLayout):
# Cannot import at top of file
from spack.package_prefs import get_package_dir_permissions
from spack.package_prefs import get_package_group
+
+ # Each package folder can have its own specific permissions, while
+ # intermediate folders (arch/compiler) are set with full access to
+ # everyone (0o777) and install_tree root folder is the chokepoint
+ # for restricting global access.
+ # So, whoever has access to the install_tree is allowed to install
+ # packages for same arch/compiler and since no data is stored in
+ # intermediate folders, it does not represent a security threat.
group = get_package_group(spec)
perms = get_package_dir_permissions(spec)
- mkdirp(spec.prefix, mode=perms)
+ perms_intermediate = 0o777
+
+ mkdirp(spec.prefix, mode=perms, mode_intermediate=perms_intermediate)
if group:
chgrp(spec.prefix, group)
# Need to reset the sticky group bit after chgrp
os.chmod(spec.prefix, perms)
mkdirp(self.metadata_path(spec), mode=perms)
+
self.write_spec(spec, self.spec_file_path(spec))
def check_installed(self, spec):