Repository: spack/spack

Issue:
Errors untaring source tarballs Docker
Some source tarballs are created in a way that tries to preserve user and group perms. 
Yes, it's a bad to create a source tarball for release with these properties -- but I suspect it's easy to go undetected until you run in a security constrained linux.

Cython is one example example I hit when trying to build in a Docker container using ubuntu:latest

```
/bin/tar: Cython-0.25.2/.gitrev: Cannot change ownership to uid 96258, gid 5000: Invalid argument
.... (many many more errors)
/bin/tar: Cython-0.25.2/USAGE.txt: Cannot change ownership to uid 96258, gid 5000: Invalid argument
/bin/tar: Cython-0.25.2: Cannot change ownership to uid 96258, gid 5000: Invalid argument
/bin/tar: Exiting with failure status due to previous errors
```
The tar errors cause spack to stop.  I am not sure if there is anyway to defensively avoid this, but if its possible it would be a good enhancement to spack. 



Discussion:
Cython folks suggest using ``--no-same-owner`` to tar may avoid the issue. (https://github.com/cython/cython/issues/2052)


More context: You can't reproduce by simply running in Docker, the docker container has be be running on a host that has se-linux enabled. I ran into this on circleci.
@cyrush any insight into how this can be fixed on circleci context?
@chrismerck sorry for the delay, I just re-discovered what I did for this case. Unfortunately, I simply avoided any tarballs with these annotations by selecting specific versions of packages. I doubt that helps in general, but thats how I moved forward.
Ok thanks. In my case, I put a shim layer above the real `tar` binary which strips out the `p` parameter. This seemed to work around the issue!

(Unfortunately I ran into another compile issue later on. I do not know whether it is caused by this hack --- so beware!)

I modified my docker image for CI, copying `/sbin/tar` to `/sbin/real_tar`, and then creating a shell script `/sbin/tar` as follows:

```
root@aaeca8b945a0:/# cat `which tar`
#!/bin/bash -x
if [[ $1 == "xpf" ]]
then
        real_tar --no-same-owner -xf "${@:2}"
else
        real_tar --no-same-owner $@
fi
```

Actually this issue comes up again in [Rootless Docker](https://docs.docker.com/engine/security/rootless/), which is probably what a lot of people will be using when Docker 20.x comes out. For instance:

```
[+] /opt/software/linux-ubuntu18.04-zen/gcc-7.5.0/automake-1.16.2-cetkqb2wqygduaihiyjgqqap22iygwnv
==> 37: Installing git
/bin/tar: git-2.27.0/configure: Cannot change ownership to uid 110493, gid 5000: Invalid argument
/bin/tar: git-2.27.0/version: Cannot change ownership to uid 110493, gid 5000: Invalid argument
/bin/tar: git-2.27.0/git-gui/version: Cannot change ownership to uid 110493, gid 5000: Invalid argument
/bin/tar: Exiting with failure status due to previous errors
==> Fetching https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.27.0.tar.gz
==> Fetching https://www.kernel.org/pub/software/scm/git/git-manpages-2.27.0.tar.gz
==> Staging archive: /tmp/root/spack-stage/spack-stage-git-2.27.0-u6tcqxdzc4xpweo5kal4qsdymv7npowk/git-2.27.0.tar.gz
==> Error: ProcessError: Command exited with status 2:
    '/bin/tar' '-xf' '/tmp/root/spack-stage/spack-stage-git-2.27.0-u6tcqxdzc4xpweo5kal4qsdymv7npowk/git-2.27.0.tar.gz'
```

I can reproduce it with

```
FROM ubuntu:18.04
RUN apt-get update -qq && apt-get install tar wget ca-certificates -qq --no-install-recommends
WORKDIR /test
RUN wget https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.27.0.tar.gz && \
    tar -xvf git-2.27.0.tar.gz
```

using Rootless Docker version
```
$ docker --version
Docker version 19.03.11, build 42e35e61f3
```
Maybe we should just go for `--no-same-owner` by default, also outside of Docker. I don't immediately see any reason why one would wish to untar files as a different user anyways, especially when they are distributed across different systems.


Resolving patch:
diff --git a/lib/spack/spack/util/compression.py b/lib/spack/spack/util/compression.py
--- a/lib/spack/spack/util/compression.py
+++ b/lib/spack/spack/util/compression.py
@@ -14,7 +14,7 @@
 NOTAR_EXTS = ["zip", "tgz", "tbz2", "txz"]
 
 # Add PRE_EXTS and EXTS last so that .tar.gz is matched *before* .tar or .gz
-ALLOWED_ARCHIVE_TYPES = [".".join(l) for l in product(
+ALLOWED_ARCHIVE_TYPES = [".".join(ext) for ext in product(
     PRE_EXTS, EXTS)] + PRE_EXTS + EXTS + NOTAR_EXTS
 
 
@@ -36,7 +36,7 @@ def decompressor_for(path, extension=None):
         bunzip2 = which('bunzip2', required=True)
         return bunzip2
     tar = which('tar', required=True)
-    tar.add_default_arg('-xf')
+    tar.add_default_arg('-oxf')
     return tar
 
 


Test patch: