From b2027f70d992bd2d088e71ee5cea7637445766f9 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 20 Jul 2011 18:10:47 +0000 Subject: * 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. --- src/libstore/store-api.cc | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) (limited to 'src/libstore/store-api.cc') diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 4b04f5751ce8..d67ff2c77299 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -72,6 +72,13 @@ Path followLinksToStorePath(const Path & path) } +string storePathToName(const Path & path) +{ + assertStorePath(path); + return string(path, nixStore.size() + 34); +} + + void checkStoreName(const string & name) { string validChars = "+-._?="; @@ -101,7 +108,9 @@ void checkStoreName(const string & name) = a human readable name for the path, typically obtained from the name attribute of the derivation, or the name of the - source file from which the store path is created + source file from which the store path is created. For derivation + outputs other than the default "out" output, the string "-" + is suffixed to . = base-32 representation of the first 160 bits of a SHA-256 hash of ; the hash part of the store name @@ -120,11 +129,12 @@ void checkStoreName(const string & name) "source" for paths copied to the store using addToStore() when recursive = true and hashAlgo = "sha256" - "output:out" + "output:" for either the outputs created by derivations, OR paths copied to the store using addToStore() with recursive != true or hashAlgo != "sha256" (in that case "source" is used; it's - silly, but it's done that way for compatibility). + silly, but it's done that way for compatibility). is the + name of the output (usually, "out").

= base-16 representation of a SHA-256 hash of: if = "text:...": @@ -174,6 +184,14 @@ Path makeStorePath(const string & type, } +Path makeOutputPath(const string & id, + const Hash & hash, const string & name) +{ + return makeStorePath("output:" + id, hash, + name + (id == "out" ? "" : "-" + id)); +} + + Path makeFixedOutputPath(bool recursive, HashType hashAlgo, Hash hash, string name) { -- cgit 1.4.1