* Disallow the Nix store or any of its parents from being symlinks.

This is because the contents of these symlinks are not incorporated
  into the hashes of derivations, and could therefore cause a mismatch
  between the build system and the target system.  E.g., if
  `/nix/store' is a symlink to `/data/nix/store', then a builder could
  expand this path and store the result.  If on the target system
  `/nix/store' is not a symlink, or is a symlink that points somewhere
  else, we have a dangling pointer.

  The trigger for this change is that gcc 3.3.3 does exactly that (it
  applies realpath() to some files, such as libraries, which causes
  our impurity checker to bail out.)

  An annoying side-effect of this change is that it makes it harder to
  move the Nix store to a different file system.  On Linux, bind
  mounts can be used instead of symlink for this purpose (e.g., `mount
  -o bind /data/nix/store /nix/store').
This commit is contained in:
Eelco Dolstra 2004-03-27 17:58:04 +00:00
parent f0f7a9f299
commit f8cd904e05
2 changed files with 37 additions and 11 deletions

View file

@ -1,7 +1,10 @@
#include <iostream> #include <iostream>
#include <cctype> #include <cctype>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
extern "C" { extern "C" {
#include <aterm2.h> #include <aterm2.h>
} }
@ -27,6 +30,22 @@ void setLogType(string lt)
} }
void checkStoreNotSymlink(Path path)
{
struct stat st;
while (path.size()) {
if (lstat(path.c_str(), &st))
throw SysError(format("getting status of `%1%'") % path);
if (S_ISLNK(st.st_mode))
throw Error(format(
"the path `%1%' is a symlink; "
"this is not allowed for the Nix store and its parent directories")
% path);
path = dirOf(path);
}
}
/* Initialize and reorder arguments, then call the actual argument /* Initialize and reorder arguments, then call the actual argument
processor. */ processor. */
static void initAndRun(int argc, char * * argv) static void initAndRun(int argc, char * * argv)
@ -39,11 +58,15 @@ static void initAndRun(int argc, char * * argv)
} }
/* Setup Nix paths. */ /* Setup Nix paths. */
nixStore = NIX_STORE_DIR; nixStore = canonPath(NIX_STORE_DIR);
nixDataDir = NIX_DATA_DIR; nixDataDir = canonPath(NIX_DATA_DIR);
nixLogDir = NIX_LOG_DIR; nixLogDir = canonPath(NIX_LOG_DIR);
nixStateDir = (string) NIX_STATE_DIR; nixStateDir = canonPath(NIX_STATE_DIR);
nixDBPath = (string) NIX_STATE_DIR + "/db"; nixDBPath = canonPath(NIX_STATE_DIR) + "/db";
/* Check that the store directory and its parent are not
symlinks. */
checkStoreNotSymlink(nixStore);
/* Catch SIGINT. */ /* Catch SIGINT. */
struct sigaction act, oact; struct sigaction act, oact;

View file

@ -60,15 +60,18 @@ extern string thisSystem;
is also canonicalised. */ is also canonicalised. */
Path absPath(Path path, Path dir = ""); Path absPath(Path path, Path dir = "");
/* Canonicalise a path (as in realpath(3)). */ /* Canonicalise a path by removing all `.' or `..' components and
double or trailing slashes. */
Path canonPath(const Path & path); Path canonPath(const Path & path);
/* Return the directory part of the given path, i.e., everything /* Return the directory part of the given canonical path, i.e.,
before the final `/'. */ everything before the final `/'. If the path is the root or an
immediate child thereof (e.g., `/foo'), this means an empty string
is returned. */
Path dirOf(const Path & path); Path dirOf(const Path & path);
/* Return the base name of the given path, i.e., everything following /* Return the base name of the given canonical path, i.e., everything
the final `/'. */ following the final `/'. */
string baseNameOf(const Path & path); string baseNameOf(const Path & path);
/* Return true iff the given path exists. */ /* Return true iff the given path exists. */