summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralbestro <9337627+albestro@users.noreply.github.com>2019-07-19 17:13:29 +0200
committerGreg Becker <becker33@llnl.gov>2019-07-19 10:13:29 -0500
commit3a026f14123e8a010e0c969bb38dfdde2738226f (patch)
tree0d1c8d198285b08cc852d8722cdc43a24e4ec740
parentcadff917c7fa6bdbb7c01724dc8831a876c01210 (diff)
downloadspack-3a026f14123e8a010e0c969bb38dfdde2738226f.tar.gz
spack-3a026f14123e8a010e0c969bb38dfdde2738226f.tar.bz2
spack-3a026f14123e8a010e0c969bb38dfdde2738226f.tar.xz
spack-3a026f14123e8a010e0c969bb38dfdde2738226f.zip
Fix #11240 (#11995)
* extends mkdirs with permissions for intermediate folders Does not use os.makedirs mode parameter because its behavior is changed with Python 3.7 (it ignores it for intermediate dirs), and moreover it was not possible to set different modes for newly-created folders and leaf folder. reference: - https://bugs.python.org/issue19930 - https://docs.python.org/3.7/library/os.html#os.makedirs * comment mkdirp step easing code understanding * revert mkdir to default for package metapath since metapath is nested in package folder, there is no need to specify permissions for intermediate folders because the prefix already exists. * comment create_install_directory package modes
-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):