about summary refs log tree commit diff
path: root/src/libstore/build.cc
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2011-07-20T18·10+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2011-07-20T18·10+0000
commitb2027f70d992bd2d088e71ee5cea7637445766f9 (patch)
treeb7338ce0a9d994378f9cc6a9557d1df63bd9f5d3 /src/libstore/build.cc
parentd2bfe1b071d0d71bb981535a53e9c5de43aaac81 (diff)
* Fix a huuuuge security hole in the Nix daemon. It didn't check that
  derivations added to the store by clients have "correct" output
  paths (meaning that the output paths are computed by hashing the
  derivation according to a certain algorithm).  This means that a
  malicious user could craft a special .drv file to build *any*
  desired path in the store with any desired contents (so long as the
  path doesn't already exist).  Then the attacker just needs to wait
  for a victim to come along and install the compromised path.

  For instance, if Alice (the attacker) knows that the latest Firefox
  derivation in Nixpkgs produces the path

    /nix/store/1a5nyfd4ajxbyy97r1fslhgrv70gj8a7-firefox-5.0.1

  then (provided this path doesn't already exist) she can craft a .drv
  file that creates that path (i.e., has it as one of its outputs),
  add it to the store using "nix-store --add", and build it with
  "nix-store -r".  So the fake .drv could write a Trojan to the
  Firefox path.  Then, if user Bob (the victim) comes along and does

    $ nix-env -i firefox
    $ firefox

  he executes the Trojan injected by Alice.

  The fix is to have the Nix daemon verify that derivation outputs are
  correct (in addValidPath()).  This required some refactoring to move
  the hash computation code to libstore.

Diffstat (limited to 'src/libstore/build.cc')
-rw-r--r--src/libstore/build.cc15
1 files changed, 3 insertions, 12 deletions
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index 4df62acea761..26f9fcc59820 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -1916,14 +1916,9 @@ void DerivationGoal::computeClosure()
            hash). */ 
         if (i->second.hash != "") {
 
-            bool recursive = false;
-            string algo = i->second.hashAlgo;
+            bool recursive; HashType ht; Hash h;
+            i->second.parseHashInfo(recursive, ht, h);
             
-            if (string(algo, 0, 2) == "r:") {
-                recursive = true;
-                algo = string(algo, 2);
-            }
-
             if (!recursive) {
                 /* The output path should be a regular file without
                    execute permission. */
@@ -1934,15 +1929,11 @@ void DerivationGoal::computeClosure()
             }
 
             /* Check the hash. */
-            HashType ht = parseHashType(algo);
-            if (ht == htUnknown)
-                throw BuildError(format("unknown hash algorithm `%1%'") % algo);
-            Hash h = parseHash(ht, i->second.hash);
             Hash h2 = recursive ? hashPath(ht, path).first : hashFile(ht, path);
             if (h != h2)
                 throw BuildError(
                     format("output path `%1%' should have %2% hash `%3%', instead has `%4%'")
-                    % path % algo % printHash(h) % printHash(h2));
+                    % path % i->second.hashAlgo % printHash(h) % printHash(h2));
         }
 
         /* Get rid of all weird permissions. */