Skip to content

Commit 4609528

Browse files
authored
Merge pull request #14080 from NixOS/storeFS-prep
Some `storeFS` and similar cleanup
2 parents 099a74e + 9b2f282 commit 4609528

File tree

9 files changed

+82
-37
lines changed

9 files changed

+82
-37
lines changed

src/libexpr/eval.cc

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "nix/expr/print.hh"
1818
#include "nix/fetchers/filtering-source-accessor.hh"
1919
#include "nix/util/memory-source-accessor.hh"
20+
#include "nix/util/mounted-source-accessor.hh"
2021
#include "nix/expr/gc-small-vector.hh"
2122
#include "nix/util/url.hh"
2223
#include "nix/fetchers/fetch-to-store.hh"
@@ -225,22 +226,25 @@ EvalState::EvalState(
225226
*/
226227
{CanonPath(store->storeDir), store->getFSAccessor(settings.pureEval)},
227228
}))
228-
, rootFS(({
229-
/* In pure eval mode, we provide a filesystem that only
230-
contains the Nix store.
231-
232-
If we have a chroot store and pure eval is not enabled,
233-
use a union accessor to make the chroot store available
234-
at its logical location while still having the
235-
underlying directory available. This is necessary for
236-
instance if we're evaluating a file from the physical
237-
/nix/store while using a chroot store. */
238-
auto accessor = getFSSourceAccessor();
239-
240-
auto realStoreDir = dirOf(store->toRealPath(StorePath::dummy));
241-
if (settings.pureEval || store->storeDir != realStoreDir) {
242-
accessor = settings.pureEval ? storeFS : makeUnionSourceAccessor({accessor, storeFS});
243-
}
229+
, rootFS([&] {
230+
auto accessor = [&]() -> decltype(rootFS) {
231+
/* In pure eval mode, we provide a filesystem that only
232+
contains the Nix store. */
233+
if (settings.pureEval)
234+
return storeFS;
235+
236+
/* If we have a chroot store and pure eval is not enabled,
237+
use a union accessor to make the chroot store available
238+
at its logical location while still having the underlying
239+
directory available. This is necessary for instance if
240+
we're evaluating a file from the physical /nix/store
241+
while using a chroot store. */
242+
auto realStoreDir = dirOf(store->toRealPath(StorePath::dummy));
243+
if (store->storeDir != realStoreDir)
244+
return makeUnionSourceAccessor({getFSSourceAccessor(), storeFS});
245+
246+
return getFSSourceAccessor();
247+
}();
244248

245249
/* Apply access control if needed. */
246250
if (settings.restrictEval || settings.pureEval)
@@ -251,8 +255,8 @@ EvalState::EvalState(
251255
throw RestrictedPathError("access to absolute path '%1%' is forbidden %2%", path, modeInformation);
252256
});
253257

254-
accessor;
255-
}))
258+
return accessor;
259+
}())
256260
, corepkgsFS(make_ref<MemorySourceAccessor>())
257261
, internalFS(make_ref<MemorySourceAccessor>())
258262
, derivationInternal{corepkgsFS->addFile(
@@ -334,7 +338,7 @@ EvalState::EvalState(
334338

335339
EvalState::~EvalState() {}
336340

337-
void EvalState::allowPath(const Path & path)
341+
void EvalState::allowPathLegacy(const Path & path)
338342
{
339343
if (auto rootFS2 = rootFS.dynamic_pointer_cast<AllowListSourceAccessor>())
340344
rootFS2->allowPrefix(CanonPath(path));
@@ -3177,7 +3181,7 @@ std::optional<SourcePath> EvalState::resolveLookupPathPath(const LookupPath::Pat
31773181

31783182
/* Allow access to paths in the search path. */
31793183
if (initAccessControl) {
3180-
allowPath(path.path.abs());
3184+
allowPathLegacy(path.path.abs());
31813185
if (store->isInStore(path.path.abs())) {
31823186
try {
31833187
allowClosure(store->toStorePath(path.path.abs()).first);

src/libexpr/include/nix/expr/eval.hh

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class StorePath;
4949
struct SingleDerivedPath;
5050
enum RepairFlag : bool;
5151
struct MemorySourceAccessor;
52+
struct MountedSourceAccessor;
5253

5354
namespace eval_cache {
5455
class EvalCache;
@@ -320,7 +321,7 @@ public:
320321
/**
321322
* The accessor corresponding to `store`.
322323
*/
323-
const ref<SourceAccessor> storeFS;
324+
const ref<MountedSourceAccessor> storeFS;
324325

325326
/**
326327
* The accessor for the root filesystem.
@@ -489,8 +490,11 @@ public:
489490

490491
/**
491492
* Allow access to a path.
493+
*
494+
* Only for restrict eval: pure eval just whitelist store paths,
495+
* never arbitrary paths.
492496
*/
493-
void allowPath(const Path & path);
497+
void allowPathLegacy(const Path & path);
494498

495499
/**
496500
* Allow access to a store path. Note that this gets remapped to

src/libfetchers/git.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "nix/fetchers/fetch-settings.hh"
1616
#include "nix/util/json-utils.hh"
1717
#include "nix/util/archive.hh"
18+
#include "nix/util/mounted-source-accessor.hh"
1819

1920
#include <regex>
2021
#include <string.h>

src/libutil/include/nix/util/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ headers = files(
4747
'logging.hh',
4848
'lru-cache.hh',
4949
'memory-source-accessor.hh',
50+
'mounted-source-accessor.hh',
5051
'muxable-pipe.hh',
5152
'os-string.hh',
5253
'pool.hh',
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#pragma once
2+
3+
#include "source-accessor.hh"
4+
5+
namespace nix {
6+
7+
struct MountedSourceAccessor : SourceAccessor
8+
{
9+
virtual void mount(CanonPath mountPoint, ref<SourceAccessor> accessor) = 0;
10+
11+
/**
12+
* Return the accessor mounted on `mountPoint`, or `nullptr` if
13+
* there is no such mount point.
14+
*/
15+
virtual std::shared_ptr<SourceAccessor> getMount(CanonPath mountPoint) = 0;
16+
};
17+
18+
ref<MountedSourceAccessor> makeMountedSourceAccessor(std::map<CanonPath, ref<SourceAccessor>> mounts);
19+
20+
} // namespace nix

src/libutil/include/nix/util/source-accessor.hh

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,8 +214,6 @@ ref<SourceAccessor> getFSSourceAccessor();
214214
*/
215215
ref<SourceAccessor> makeFSSourceAccessor(std::filesystem::path root);
216216

217-
ref<SourceAccessor> makeMountedSourceAccessor(std::map<CanonPath, ref<SourceAccessor>> mounts);
218-
219217
/**
220218
* Construct an accessor that presents a "union" view of a vector of
221219
* underlying accessors. Earlier accessors take precedence over later.

src/libutil/mounted-source-accessor.cc

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
1-
#include "nix/util/source-accessor.hh"
1+
#include "nix/util/mounted-source-accessor.hh"
2+
3+
#include <boost/unordered/concurrent_flat_map.hpp>
24

35
namespace nix {
46

5-
struct MountedSourceAccessor : SourceAccessor
7+
struct MountedSourceAccessorImpl : MountedSourceAccessor
68
{
7-
std::map<CanonPath, ref<SourceAccessor>> mounts;
9+
boost::concurrent_flat_map<CanonPath, ref<SourceAccessor>> mounts;
810

9-
MountedSourceAccessor(std::map<CanonPath, ref<SourceAccessor>> _mounts)
10-
: mounts(std::move(_mounts))
11+
MountedSourceAccessorImpl(std::map<CanonPath, ref<SourceAccessor>> _mounts)
1112
{
1213
displayPrefix.clear();
1314

1415
// Currently we require a root filesystem. This could be relaxed.
15-
assert(mounts.contains(CanonPath::root));
16+
assert(_mounts.contains(CanonPath::root));
17+
18+
for (auto & [path, accessor] : _mounts)
19+
mount(path, accessor);
1620

1721
// FIXME: return dummy parent directories automatically?
1822
}
@@ -52,10 +56,9 @@ struct MountedSourceAccessor : SourceAccessor
5256
// Find the nearest parent of `path` that is a mount point.
5357
std::vector<std::string> subpath;
5458
while (true) {
55-
auto i = mounts.find(path);
56-
if (i != mounts.end()) {
59+
if (auto mount = getMount(path)) {
5760
std::reverse(subpath.begin(), subpath.end());
58-
return {i->second, CanonPath(subpath)};
61+
return {ref(mount), CanonPath(subpath)};
5962
}
6063

6164
assert(!path.isRoot());
@@ -69,11 +72,24 @@ struct MountedSourceAccessor : SourceAccessor
6972
auto [accessor, subpath] = resolve(path);
7073
return accessor->getPhysicalPath(subpath);
7174
}
75+
76+
void mount(CanonPath mountPoint, ref<SourceAccessor> accessor) override
77+
{
78+
mounts.emplace(std::move(mountPoint), std::move(accessor));
79+
}
80+
81+
std::shared_ptr<SourceAccessor> getMount(CanonPath mountPoint) override
82+
{
83+
if (auto res = getConcurrent(mounts, mountPoint))
84+
return *res;
85+
else
86+
return nullptr;
87+
}
7288
};
7389

74-
ref<SourceAccessor> makeMountedSourceAccessor(std::map<CanonPath, ref<SourceAccessor>> mounts)
90+
ref<MountedSourceAccessor> makeMountedSourceAccessor(std::map<CanonPath, ref<SourceAccessor>> mounts)
7591
{
76-
return make_ref<MountedSourceAccessor>(std::move(mounts));
92+
return make_ref<MountedSourceAccessorImpl>(std::move(mounts));
7793
}
7894

7995
} // namespace nix

src/nix/env.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "nix/util/strings.hh"
88
#include "nix/util/executable-path.hh"
99
#include "nix/util/environment-variables.hh"
10+
#include "nix/util/mounted-source-accessor.hh"
1011

1112
using namespace nix;
1213

src/nix/profile.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,8 @@ struct ProfileManifest
177177

178178
else if (std::filesystem::exists(profile / "manifest.nix")) {
179179
// FIXME: needed because of pure mode; ugly.
180-
state.allowPath(state.store->followLinksToStore(profile.string()));
181-
state.allowPath(state.store->followLinksToStore((profile / "manifest.nix").string()));
180+
state.allowPath(state.store->followLinksToStorePath(profile.string()));
181+
state.allowPath(state.store->followLinksToStorePath((profile / "manifest.nix").string()));
182182

183183
auto packageInfos = queryInstalled(state, state.store->followLinksToStore(profile.string()));
184184

0 commit comments

Comments
 (0)