diff options
author | Harmen Stoppels <harmenstoppels@gmail.com> | 2022-03-23 15:54:55 +0100 |
---|---|---|
committer | Massimiliano Culpo <massimiliano.culpo@gmail.com> | 2022-04-14 11:08:17 +0200 |
commit | 1cc2b82408b380bf13d057305bf62d479779d3ea (patch) | |
tree | 3ffe0648542aaae8d1bd4ecc4665e55e008a70ea | |
parent | ad2c0208487daee84892e81ed248360a3feb4226 (diff) | |
download | spack-1cc2b82408b380bf13d057305bf62d479779d3ea.tar.gz spack-1cc2b82408b380bf13d057305bf62d479779d3ea.tar.bz2 spack-1cc2b82408b380bf13d057305bf62d479779d3ea.tar.xz spack-1cc2b82408b380bf13d057305bf62d479779d3ea.zip |
environment: be more defensive when deleting roots for old views (#29636)
Currently `old_root` is computed by reading the symlink at `self.root`.
We should be more defensive in removing it by checking that it is in the
same directory as the new root. Otherwise, in the worst case, when
someone runs `spack env create --with-view=./view -d .` and `view`
already exists and is a symlink to `/`, Spack effectively runs `rm -rf /`.
-rw-r--r-- | lib/spack/spack/environment/environment.py | 10 | ||||
-rw-r--r-- | lib/spack/spack/test/cmd/env.py | 11 |
2 files changed, 19 insertions, 2 deletions
diff --git a/lib/spack/spack/environment/environment.py b/lib/spack/spack/environment/environment.py index 3114f55638..ff85259cda 100644 --- a/lib/spack/spack/environment/environment.py +++ b/lib/spack/spack/environment/environment.py @@ -489,8 +489,14 @@ class ViewDescriptor(object): raise SpackEnvironmentViewError(msg) os.rename(tmp_symlink_name, self.root) - # remove old_root - if old_root and os.path.exists(old_root): + # Remove the old root when it's in the same folder as the new root. This + # guards against removal of an arbitrary path when the original symlink in + # self.root was not created by the environment, but by the user. + if ( + old_root and + os.path.exists(old_root) and + os.path.samefile(os.path.dirname(new_root), os.path.dirname(old_root)) + ): try: shutil.rmtree(old_root) except (IOError, OSError) as e: diff --git a/lib/spack/spack/test/cmd/env.py b/lib/spack/spack/test/cmd/env.py index d7e712d3d0..fbf3b61f8e 100644 --- a/lib/spack/spack/test/cmd/env.py +++ b/lib/spack/spack/test/cmd/env.py @@ -2693,3 +2693,14 @@ def test_activate_temp(monkeypatch, tmpdir): if ev.spack_env_var in line) assert str(tmpdir) in active_env_var assert ev.is_env_dir(str(tmpdir)) + + +def test_env_view_fail_if_symlink_points_elsewhere(tmpdir, install_mockery, mock_fetch): + view = str(tmpdir.join('view')) + # Put a symlink to an actual directory in view + non_view_dir = str(tmpdir.mkdir('dont-delete-me')) + os.symlink(non_view_dir, view) + with ev.create('env', with_view=view): + add('libelf') + install('--fake') + assert os.path.isdir(non_view_dir) |