diff options
| author | Ludovic Courtès <ludo@gnu.org> | 2025-02-10 15:22:11 +0100 |
|---|---|---|
| committer | Ludovic Courtès <ludo@gnu.org> | 2025-03-26 17:57:43 +0100 |
| commit | 550ca89744453ffc53e998979231046fb3e81a6a (patch) | |
| tree | 8da36a6e6bb9ba216676f5df82b51b27308d3cd7 /nix | |
| parent | 5c0b93b2441c338ad8dda97c64a54832be76840d (diff) | |
daemon: Bind-mount all the inputs, not just directories.
* nix/libstore/build.cc (DerivationGoal::startBuilder): Add all of
‘inputPaths’ to ‘dirsInChroot’ instead of hard-linking regular files.
Special-case symlinks.
(DerivationGoal)[regularInputPaths]: Remove.
Reported-by: Reepca Russelstein <reepca@russelstein.xyz>
Change-Id: I070987f92d73f187f7826a975bee9ee309d67f56
Diffstat (limited to 'nix')
| -rw-r--r-- | nix/libstore/build.cc | 39 |
1 files changed, 14 insertions, 25 deletions
diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 8ca5e5b732c..193b279b88a 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc | |||
| @@ -659,9 +659,6 @@ private: | |||
| 659 | /* RAII object to delete the chroot directory. */ | 659 | /* RAII object to delete the chroot directory. */ |
| 660 | std::shared_ptr<AutoDelete> autoDelChroot; | 660 | std::shared_ptr<AutoDelete> autoDelChroot; |
| 661 | 661 | ||
| 662 | /* All inputs that are regular files. */ | ||
| 663 | PathSet regularInputPaths; | ||
| 664 | |||
| 665 | /* Whether this is a fixed-output derivation. */ | 662 | /* Whether this is a fixed-output derivation. */ |
| 666 | bool fixedOutput; | 663 | bool fixedOutput; |
| 667 | 664 | ||
| @@ -1850,9 +1847,7 @@ void DerivationGoal::startBuilder() | |||
| 1850 | 1847 | ||
| 1851 | /* Make the closure of the inputs available in the chroot, | 1848 | /* Make the closure of the inputs available in the chroot, |
| 1852 | rather than the whole store. This prevents any access | 1849 | rather than the whole store. This prevents any access |
| 1853 | to undeclared dependencies. Directories are bind-mounted, | 1850 | to undeclared dependencies. !!! As an extra security |
| 1854 | while other inputs are hard-linked (since only directories | ||
| 1855 | can be bind-mounted). !!! As an extra security | ||
| 1856 | precaution, make the fake store only writable by the | 1851 | precaution, make the fake store only writable by the |
| 1857 | build user. */ | 1852 | build user. */ |
| 1858 | Path chrootStoreDir = chrootRootDir + settings.nixStore; | 1853 | Path chrootStoreDir = chrootRootDir + settings.nixStore; |
| @@ -1863,28 +1858,22 @@ void DerivationGoal::startBuilder() | |||
| 1863 | throw SysError(format("cannot change ownership of ‘%1%’") % chrootStoreDir); | 1858 | throw SysError(format("cannot change ownership of ‘%1%’") % chrootStoreDir); |
| 1864 | 1859 | ||
| 1865 | foreach (PathSet::iterator, i, inputPaths) { | 1860 | foreach (PathSet::iterator, i, inputPaths) { |
| 1866 | struct stat st; | 1861 | struct stat st; |
| 1867 | if (lstat(i->c_str(), &st)) | 1862 | if (lstat(i->c_str(), &st)) |
| 1868 | throw SysError(format("getting attributes of path `%1%'") % *i); | 1863 | throw SysError(format("getting attributes of path `%1%'") % *i); |
| 1869 | if (S_ISDIR(st.st_mode)) | ||
| 1870 | dirsInChroot[*i] = *i; | ||
| 1871 | else { | ||
| 1872 | Path p = chrootRootDir + *i; | ||
| 1873 | if (link(i->c_str(), p.c_str()) == -1) { | ||
| 1874 | /* Hard-linking fails if we exceed the maximum | ||
| 1875 | link count on a file (e.g. 32000 of ext3), | ||
| 1876 | which is quite possible after a `nix-store | ||
| 1877 | --optimise'. */ | ||
| 1878 | if (errno != EMLINK) | ||
| 1879 | throw SysError(format("linking `%1%' to `%2%'") % p % *i); | ||
| 1880 | StringSink sink; | ||
| 1881 | dumpPath(*i, sink); | ||
| 1882 | StringSource source(sink.s); | ||
| 1883 | restorePath(p, source); | ||
| 1884 | } | ||
| 1885 | 1864 | ||
| 1886 | regularInputPaths.insert(*i); | 1865 | if (S_ISLNK(st.st_mode)) { |
| 1887 | } | 1866 | /* Since bind-mounts follow symlinks, thus representing their |
| 1867 | target and not the symlink itself, special-case | ||
| 1868 | symlinks. XXX: When running unprivileged, TARGET can be | ||
| 1869 | deleted by the build process. Use 'open_tree' & co. when | ||
| 1870 | it's more widely available. */ | ||
| 1871 | Path target = chrootRootDir + *i; | ||
| 1872 | if (symlink(readLink(*i).c_str(), target.c_str()) == -1) | ||
| 1873 | throw SysError(format("failed to create symlink '%1%' to '%2%'") % target % readLink(*i)); | ||
| 1874 | } | ||
| 1875 | else | ||
| 1876 | dirsInChroot[*i] = *i; | ||
| 1888 | } | 1877 | } |
| 1889 | 1878 | ||
| 1890 | /* If we're repairing, checking or rebuilding part of a | 1879 | /* If we're repairing, checking or rebuilding part of a |
