From f67a59fabc1b2e3c4f5613a7bf10c619ca59095e Mon Sep 17 00:00:00 2001 From: Greg Becker Date: Fri, 10 May 2019 16:38:13 +0900 Subject: permissions: preserve suid and sgid bits (#10727) * Don't overwrite suid/sgid bits when setting permissions * add tests for permission setting --- lib/spack/spack/hooks/permissions_setters.py | 11 +++++++++ lib/spack/spack/test/permissions.py | 35 ++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 lib/spack/spack/test/permissions.py 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) -- cgit v1.2.3-60-g2f50