* Create a /tmp with 1777 permission in the chroot. Some builders

need a writable /tmp (they don't respect $TMPDIR).
This commit is contained in:
Eelco Dolstra 2008-08-27 16:03:03 +00:00
parent 99dc3e613a
commit 9cc0da8453

View file

@ -715,12 +715,15 @@ private:
/* Whether we're currently doing a chroot build. */ /* Whether we're currently doing a chroot build. */
bool useChroot; bool useChroot;
/* A RAII object to delete the chroot directory. */ /* RAII objects to delete the chroot directory and its /tmp
boost::shared_ptr<AutoDelete> autoDelChroot; directory. Don't change the order: autoDelChrootTmp has to be
deleted before autoDelChrootRoot. */
boost::shared_ptr<AutoDelete> autoDelChrootRoot;
boost::shared_ptr<AutoDelete> autoDelChrootTmp;
/* In chroot builds, the list of bind mounts currently active. /* In chroot builds, the list of bind mounts currently active.
The destructor of BindMount will cause the binds to be The destructor of BindMount will cause the binds to be
unmounted. */ unmounted. Keep this *below* autoDelChroot* just to be safe! */
list<boost::shared_ptr<BindMount> > bindMounts; list<boost::shared_ptr<BindMount> > bindMounts;
typedef void (DerivationGoal::*GoalState)(); typedef void (DerivationGoal::*GoalState)();
@ -1692,7 +1695,7 @@ void DerivationGoal::startBuilder()
work properly. Purity checking for fixed-output derivations work properly. Purity checking for fixed-output derivations
is somewhat pointless anyway. */ is somewhat pointless anyway. */
useChroot = queryBoolSetting("build-use-chroot", false); useChroot = queryBoolSetting("build-use-chroot", false);
Path tmpRootDir; Path chrootRootDir;
if (fixedOutput) useChroot = false; if (fixedOutput) useChroot = false;
@ -1706,22 +1709,39 @@ void DerivationGoal::startBuilder()
/tmp/chroot-nix-*" to clean up aborted builds, and if some /tmp/chroot-nix-*" to clean up aborted builds, and if some
of the bind-mounts are still active, then "rm -rf" will of the bind-mounts are still active, then "rm -rf" will
happily recurse into those mount points (thereby deleting, happily recurse into those mount points (thereby deleting,
say, /nix/store). Ideally, tmpRootDir should be created in say, /nix/store). Ideally, chrootRootDir should be created in
some special location (maybe in /nix/var/nix) where Nix some special location (maybe in /nix/var/nix) where Nix
takes care of unmounting / deleting old chroots takes care of unmounting / deleting old chroots
automatically. */ automatically. */
tmpRootDir = createTempDir("", "chroot-nix"); chrootRootDir = createTempDir("", "chroot-nix");
/* Clean up the chroot directory automatically, but don't /* Clean up the chroot directory automatically, but don't
recurse; that would be very very bad if the unmount of a recurse; that would be very very bad if the unmount of a
bind-mount fails. Instead BindMount::unbind() unmounts and bind-mount fails. Instead BindMount::unbind() unmounts and
deletes exactly those directories that it created to deletes exactly those directories that it created to
produce the mount point, so that after all the BindMount produce the mount point, so that after all the BindMount
destructors have run, tmpRootDir should be empty. */ destructors have run, chrootRootDir should be empty. */
autoDelChroot = boost::shared_ptr<AutoDelete>(new AutoDelete(tmpRootDir, false)); autoDelChrootRoot = boost::shared_ptr<AutoDelete>(new AutoDelete(chrootRootDir, false));
printMsg(lvlChatty, format("setting up chroot environment in `%1%'") % tmpRootDir); printMsg(lvlChatty, format("setting up chroot environment in `%1%'") % chrootRootDir);
/* Create a writable /tmp in the chroot. Many builders need
this. (Of course they should really respect $TMPDIR
instead.) */
Path chrootTmpDir = chrootRootDir + "/tmp";
createDirs(chrootTmpDir);
if (chmod(chrootTmpDir.c_str(), 01777) == -1)
throw SysError("creating /tmp in the chroot");
/* When deleting this, do recurse (the builder might have left
crap there). As long as nothing important is bind-mounted
under /tmp it's okay (and the bind-mounts are unmounted
before autoDelChrootTmp's destructor runs, anyway). */
autoDelChrootTmp = boost::shared_ptr<AutoDelete>(new AutoDelete(chrootTmpDir));
/* Bind-mount a user-configurable set of directories from the
host file system. */
Paths defaultDirs; Paths defaultDirs;
defaultDirs.push_back("/dev"); defaultDirs.push_back("/dev");
defaultDirs.push_back("/proc"); defaultDirs.push_back("/proc");
@ -1734,7 +1754,7 @@ void DerivationGoal::startBuilder()
unmounted in LIFO order. (!!! Does the C++ standard unmounted in LIFO order. (!!! Does the C++ standard
guarantee that list elements are destroyed in order?) */ guarantee that list elements are destroyed in order?) */
for (Paths::iterator i = dirsInChroot.begin(); i != dirsInChroot.end(); ++i) for (Paths::iterator i = dirsInChroot.begin(); i != dirsInChroot.end(); ++i)
bindMounts.push_front(boost::shared_ptr<BindMount>(new BindMount(*i, tmpRootDir + *i))); bindMounts.push_front(boost::shared_ptr<BindMount>(new BindMount(*i, chrootRootDir + *i)));
#else #else
throw Error("chroot builds are not supported on this platform"); throw Error("chroot builds are not supported on this platform");
@ -1773,8 +1793,8 @@ void DerivationGoal::startBuilder()
chroot. (Actually the order doesn't matter, since due chroot. (Actually the order doesn't matter, since due
to the bind mount tmpDir and tmpRootDit/tmpDir are the to the bind mount tmpDir and tmpRootDit/tmpDir are the
same directories.) */ same directories.) */
if (useChroot && chroot(tmpRootDir.c_str()) == -1) if (useChroot && chroot(chrootRootDir.c_str()) == -1)
throw SysError(format("cannot change root directory to `%1%'") % tmpRootDir); throw SysError(format("cannot change root directory to `%1%'") % chrootRootDir);
#endif #endif
initChild(); initChild();