Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Building fails when a dependency tarball has files with uid 0 #56

Open
utdemir opened this issue Feb 8, 2021 · 9 comments
Open

Building fails when a dependency tarball has files with uid 0 #56

utdemir opened this issue Feb 8, 2021 · 9 comments

Comments

@utdemir
Copy link

utdemir commented Feb 8, 2021

When building a package depends on char-regex-1.0.2, building that depedency fails at unpackPhase:

builder for '/nix/store/h87kk5zssq2kdajfmzswbzf437n83j1k-char-regex-1.0.2.drv' failed with exit code 1; last 8 log lines:
  unpacking sources
  unpacking source archive /nix/store/v9p98kqplf4kflmy91p0687xlvr6klb1-char-regex-1.0.2.tgz
  source root is package
  chmod: cannot access 'package/package.json': Permission denied
  chmod: cannot access 'package/index.d.ts': Permission denied
  chmod: cannot access 'package/index.js': Permission denied
  chmod: cannot access 'package/README.md': Permission denied
  chmod: cannot access 'package/LICENSE': Permission denied

Here're the contents of the mentioned tarball:

% tar -tvf /nix/store/v9p98kqplf4kflmy91p0687xlvr6klb1-char-regex-1.0.2.tgz
drw-rw-rw- 0/0               0 2020-02-18 22:50 package
-rw-rw-rw- 0/0             297 2020-02-18 22:50 package/index.d.ts
-rw-rw-rw- 0/0            1920 2020-02-18 22:50 package/index.js
-rw-rw-rw- 0/0            1092 2020-01-31 23:31 package/LICENSE
-rw-rw-rw- 0/0             937 2020-02-18 22:51 package/package.json
-rw-rw-rw- 0/0             713 2020-02-18 22:50 package/README.md

I think the files having uid/gid 0/0 causes a permission error.

I was able to mitigate the issue with overriding unpackPhase and passing --no-same-owner flag to tar:

diff --git a/nix-lib/buildNodePackage.nix b/nix-lib/buildNodePackage.nix
index e32c6bd..e490207 100644
--- a/nix-lib/buildNodePackage.nix
+++ b/nix-lib/buildNodePackage.nix
@@ -30,6 +30,19 @@ in stdenv.mkDerivation ((removeAttrs args [ "key" "nodeBuildInputs" ]) // {
   # skip the build phase except when given as attribute
   dontBuild = !(args ? buildPhase);
 
+  # unpacking fails when the tarball contains files with uid 0
+  unpackPhase = ''
+    case "$src" in
+      *.tgz)
+        tar xf "$src" --strip 1 --no-same-owner
+        ;;
+      *)
+        cp -rT "$src" ./
+        ;;
+     esac
+  '';
+
   # TODO: maybe we can enable tests?
   doCheck = false;

My patch isn't great, since it assumes that the src is either a tgz file or a directory. Which seems to work because this function is only called with npm tarballs for dependencies, and once more for the actual project, which is a directory.

As another possible solution; looking at the default unpackPhase, these lines seem relevant: https://github.com/NixOS/nixpkgs/blob/d79612672e0ac39072754dce5a812c64a01c9cb2/pkgs/stdenv/generic/setup.sh#L914-L919. However, simply passing something like dontMakeSourcesWritable = 1 didn't help in my case.

@utdemir utdemir changed the title Building fails when a depedency tarball has files with uid 00 Building fails when a dependency tarball has files with uid 0 Feb 8, 2021
@sternenseemann
Copy link
Collaborator

sternenseemann commented Feb 9, 2021

Seems to me that the issue is not necessarily that the files in the tar archive are owned by root, but that they are owned by root and the directory is not marked as executable: dontMakeSourcesWritable = true works, but leads to the following:

find: 'package/index.d.ts': Permission denied
find: 'package/index.js': Permission denied
find: 'package/LICENSE': Permission denied
find: 'package/package.json': Permission denied
find: 'package/README.md': Permission denied
/nix/store/333six1faw9bhccsx9qw5718k6b1wiq2-stdenv-linux/setup: line 1304: cd: package: Permission denied

The fix seems to be to set

   postUnpack = "chmod +x $sourceRoot";
   dontMakeSourcesWritable = true;

in _buildNodePackage. But I'm not sure if this isn't asking for another edge case.

The best courses of action I can think of:

  • Make it easy to override _buildNodePackage in `buildNodeDeps, so you can easily fix this locally if necessary
  • Add a fix for this in nixpkgs
  • Get char-regex to release an 1.03 with a non-broken tar ball (we definitely should do this)

@ziprandom
Copy link

meanwhile can you provide a snippet to patch this from outside using .override or smth. ?

@Profpatsch
Copy link
Owner

@ziprandom are you having the same problem?

@ziprandom
Copy link

@Profpatsch yes

@sternenseemann
Copy link
Collaborator

sternenseemann commented Mar 23, 2021

Ugly hack which you can try to fix your problem (also interesting question if this causes any other problems).
I'd like to get rid of the postUnpack, I believe we can upstream a fix for that in nixpkgs maybe?
It is only necessary for char-regex which just has a terribly broken tar ball.

diff --git a/src/Distribution/Nixpkgs/Nodejs/OptimizedNixOutput.hs b/src/Distribution/Nixpkgs/Nodejs/OptimizedNixOutput.hs
index f24ceb0..24f395e 100644
--- a/src/Distribution/Nixpkgs/Nodejs/OptimizedNixOutput.hs
+++ b/src/Distribution/Nixpkgs/Nodejs/OptimizedNixOutput.hs
@@ -270,6 +270,8 @@ mkPackageSet packages =
         $ ("super" !!. "_buildNodePackage") @@ N.mkNonRecSet
           [ inheritStatic ["key", "version"]
           , "src" $= srcNExpr
+          , "dontMakeSourcesWritable" $= N.mkBool True
+          , "postUnpack" $= N.mkStr "chmod +x \"$sourceRoot\""
           , "nodeBuildInputs" $= "deps" ]
     -- | Building a 'YLT.FileRemote' package.
     buildPkgFn :: NExpr

@ziprandom
Copy link

@sternenseemann I'm just trying to get a build to work, so I was wondering whether nixs builtin overloading facilities can help me instead of patching source code ..

@sternenseemann
Copy link
Collaborator

sternenseemann commented Mar 23, 2021

@ziprandom Unfortunately the nix library of yarn2nix is not overrideable yet since it has no fix point…

The easiest way to do it is probably to add the following to nix-lib/buildNodePackage.nix:

  dontMakeSourcesWritable = false;
  postUnpack = ''
    chmod +x $sourceRoot"
  '';

Also not really nice, sorry :/

@ziprandom
Copy link

@sternenseemann no problem & thanks for the effort! I will try that ..

sternenseemann added a commit to sternenseemann/nixpkgs that referenced this issue Mar 23, 2021
This change is prompted by the following, admittedly cursed tarball:

```
> curl https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz 2>/dev/null \
  | tar -ztv
drw-rw-rw- 0/0               0 2020-02-18 10:50 package
-rw-rw-rw- 0/0             297 2020-02-18 10:50 package/index.d.ts
-rw-rw-rw- 0/0            1920 2020-02-18 10:50 package/index.js
-rw-rw-rw- 0/0            1092 2020-01-31 11:31 package/LICENSE
-rw-rw-rw- 0/0             937 2020-02-18 10:51 package/package.json
-rw-rw-rw- 0/0             713 2020-02-18 10:50 package/README.md
```

The minimal reproducer for the issue is the following derivation trying
to work around the uid 0 issue with `dontMakeSourcesWritable = true`:

```nix
{ stdenv, fetchurl }:

stdenv.mkDerivation {
  name = "test";

  src = fetchurl {
    sha1 = "d744358226217f981ed58f479b1d6bcc29545dcf";
    url = "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz";
  };

  dontMakeSourcesWritable = true;

  installPhase = ''
    cp -R . $out
  '';
}
```

This currently fails in the following way:

```
these derivations will be built:
  /nix/store/pc3jbydl0xcc8nrndf5xkf7hdhpgpb41-test.drv
building '/nix/store/pc3jbydl0xcc8nrndf5xkf7hdhpgpb41-test.drv'...
unpacking sources
unpacking source archive /nix/store/v9p98kqplf4kflmy91p0687xlvr6klb1-char-regex-1.0.2.tgz
source root is package
find: 'package/index.d.ts': Permission denied
find: 'package/index.js': Permission denied
find: 'package/LICENSE': Permission denied
find: 'package/package.json': Permission denied
find: 'package/README.md': Permission denied
/nix/store/6c47azxacncswc1pllzj28zfzqw40d7c-stdenv-linux/setup: line 1311: cd: package: Permission denied
builder for '/nix/store/pc3jbydl0xcc8nrndf5xkf7hdhpgpb41-test.drv' failed with exit code 1
error: build of '/nix/store/pc3jbydl0xcc8nrndf5xkf7hdhpgpb41-test.drv' failed
```

As you can see, the issue is that `$sourceRoot` isn't executable,
prohibiting the call to `cd`. This can be fixed by running
`chmod +x "${sourceRoot}"` before `cd` regardless of
`dontMakeSourcesWritable` in `unpackPhase` since if `chmod` fails, `cd`
would fail as well and we are out of options.

Verified that the workaround works locally.

Another thing to investigate is investigating if we should use
`--no-same-owner` for `tar` and if it helps in this case as well.
See also <Profpatsch/yarn2nix#56>.
sternenseemann added a commit to NixOS/nixpkgs that referenced this issue Mar 24, 2022
This change is prompted by the following, admittedly cursed tarball:

```
> curl https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz 2>/dev/null \
  | tar -ztv
drw-rw-rw- 0/0               0 2020-02-18 10:50 package
-rw-rw-rw- 0/0             297 2020-02-18 10:50 package/index.d.ts
-rw-rw-rw- 0/0            1920 2020-02-18 10:50 package/index.js
-rw-rw-rw- 0/0            1092 2020-01-31 11:31 package/LICENSE
-rw-rw-rw- 0/0             937 2020-02-18 10:51 package/package.json
-rw-rw-rw- 0/0             713 2020-02-18 10:50 package/README.md
```

The minimal reproducer for the issue is the following derivation trying
to work around the uid 0 issue with `dontMakeSourcesWritable = true`:

```nix
{ stdenv, fetchurl }:

stdenv.mkDerivation {
  name = "test";

  src = fetchurl {
    sha1 = "d744358226217f981ed58f479b1d6bcc29545dcf";
    url = "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz";
  };

  dontMakeSourcesWritable = true;

  installPhase = ''
    cp -R . $out
  '';
}
```

This currently fails in the following way:

```
these derivations will be built:
  /nix/store/pc3jbydl0xcc8nrndf5xkf7hdhpgpb41-test.drv
building '/nix/store/pc3jbydl0xcc8nrndf5xkf7hdhpgpb41-test.drv'...
unpacking sources
unpacking source archive /nix/store/v9p98kqplf4kflmy91p0687xlvr6klb1-char-regex-1.0.2.tgz
source root is package
find: 'package/index.d.ts': Permission denied
find: 'package/index.js': Permission denied
find: 'package/LICENSE': Permission denied
find: 'package/package.json': Permission denied
find: 'package/README.md': Permission denied
/nix/store/6c47azxacncswc1pllzj28zfzqw40d7c-stdenv-linux/setup: line 1311: cd: package: Permission denied
builder for '/nix/store/pc3jbydl0xcc8nrndf5xkf7hdhpgpb41-test.drv' failed with exit code 1
error: build of '/nix/store/pc3jbydl0xcc8nrndf5xkf7hdhpgpb41-test.drv' failed
```

As you can see, the issue is that `$sourceRoot` isn't executable,
prohibiting the call to `cd`. This can be fixed by running
`chmod +x "${sourceRoot}"` before `cd` regardless of
`dontMakeSourcesWritable` in `unpackPhase` since if `chmod` fails, `cd`
would fail as well and we are out of options.

Verified that the workaround works locally.

Another thing to investigate is investigating if we should use
`--no-same-owner` for `tar` and if it helps in this case as well.
See also <Profpatsch/yarn2nix#56>.
@sternenseemann
Copy link
Collaborator

Should be resolved upstream in nixpkgs when #117357 lands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants