summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/spack/hooks/permissions_setters.py11
-rw-r--r--lib/spack/spack/test/permissions.py35
2 files changed, 46 insertions, 0 deletions
diff --git a/lib/spack/spack/hooks/permissions_setters.py b/lib/spack/spack/hooks/permissions_setters.py
index 631118ffac..9ada697ad8 100644
--- a/lib/spack/spack/hooks/permissions_setters.py
+++ b/lib/spack/spack/hooks/permissions_setters.py
@@ -4,11 +4,13 @@
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os
+import stat
from llnl.util.filesystem import chmod_x, chgrp
from spack.package_prefs import get_package_permissions, get_package_group
from spack.package_prefs import get_package_dir_permissions
+from spack.error import SpackError
def forall_files(path, fn, args, dir_args=None):
@@ -31,6 +33,11 @@ def forall_files(path, fn, args, dir_args=None):
def chmod_real_entries(path, perms):
# Don't follow links so we don't change things outside the prefix
if not os.path.islink(path):
+ mode = os.stat(path).st_mode
+ perms |= mode & (stat.S_ISUID | stat.S_ISGID | stat.S_ISVTX)
+ if perms & stat.S_ISUID and perms & stat.S_IWGRP:
+ raise InvalidPermissionsError(
+ 'Attempting to set suid with world writable')
chmod_x(path, perms)
@@ -44,3 +51,7 @@ def post_install(spec):
if group:
forall_files(spec.prefix, chgrp, [group])
+
+
+class InvalidPermissionsError(SpackError):
+ """Error class for invalid permission setters"""
diff --git a/lib/spack/spack/test/permissions.py b/lib/spack/spack/test/permissions.py
new file mode 100644
index 0000000000..223b3e8319
--- /dev/null
+++ b/lib/spack/spack/test/permissions.py
@@ -0,0 +1,35 @@
+# Copyright 2013-2019 Lawrence Livermore National Security, LLC and other
+# Spack Project Developers. See the top-level COPYRIGHT file for details.
+#
+# SPDX-License-Identifier: (Apache-2.0 OR MIT)
+
+import os
+import pytest
+import stat
+
+from spack.hooks.permissions_setters import (
+ chmod_real_entries, InvalidPermissionsError
+)
+import llnl.util.filesystem as fs
+
+
+def test_chmod_real_entries_ignores_suid_sgid(tmpdir):
+ path = str(tmpdir.join('file').ensure())
+ mode = stat.S_ISUID | stat.S_ISGID | stat.S_ISVTX
+ os.chmod(path, mode)
+ mode = os.stat(path).st_mode # adds a high bit we aren't concerned with
+
+ perms = stat.S_IRWXU
+ chmod_real_entries(path, perms)
+
+ assert os.stat(path).st_mode == mode | perms & ~stat.S_IXUSR
+
+
+def test_chmod_rejects_group_writable_suid(tmpdir):
+ path = str(tmpdir.join('file').ensure())
+ mode = stat.S_ISUID | stat.S_ISGID | stat.S_ISVTX
+ fs.chmod_x(path, mode)
+
+ perms = stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO
+ with pytest.raises(InvalidPermissionsError):
+ chmod_real_entries(path, perms)