Skip to content

Commit 99e78c3

Browse files
committed
Use UnionSourceAccessor to mount the chroot store on top of the real store directory
1 parent 5b7c240 commit 99e78c3

File tree

6 files changed

+42
-49
lines changed

6 files changed

+42
-49
lines changed

src/libcmd/common-eval-args.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ EvalSettings evalSettings {
3737
auto [accessor, lockedRef] = flakeRef.resolve(state.store).lazyFetch(state.store);
3838
auto storePath = nix::fetchToStore(*state.store, SourcePath(accessor), FetchMode::Copy, lockedRef.input.getName());
3939
state.allowPath(storePath);
40-
return state.rootPath(state.store->toRealPath(storePath));
40+
return state.rootPath(state.store->printStorePath(storePath));
4141
},
4242
},
4343
},
@@ -179,7 +179,7 @@ SourcePath lookupFileArg(EvalState & state, std::string_view s, const Path * bas
179179
state.fetchSettings,
180180
EvalSettings::resolvePseudoUrl(s));
181181
auto storePath = fetchToStore(*state.store, SourcePath(accessor), FetchMode::Copy);
182-
return state.rootPath(CanonPath(state.store->toRealPath(storePath)));
182+
return state.rootPath(CanonPath(state.store->printStorePath(storePath)));
183183
}
184184

185185
else if (hasPrefix(s, "flake:")) {
@@ -188,7 +188,7 @@ SourcePath lookupFileArg(EvalState & state, std::string_view s, const Path * bas
188188
auto [accessor, lockedRef] = flakeRef.resolve(state.store).lazyFetch(state.store);
189189
auto storePath = nix::fetchToStore(*state.store, SourcePath(accessor), FetchMode::Copy, lockedRef.input.getName());
190190
state.allowPath(storePath);
191-
return state.rootPath(CanonPath(state.store->toRealPath(storePath)));
191+
return state.rootPath(CanonPath(state.store->printStorePath(storePath)));
192192
}
193193

194194
else if (s.size() > 2 && s.at(0) == '<' && s.at(s.size() - 1) == '>') {

src/libexpr/eval.cc

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -246,21 +246,37 @@ EvalState::EvalState(
246246
, repair(NoRepair)
247247
, emptyBindings(0)
248248
, rootFS(
249-
settings.restrictEval || settings.pureEval
250-
? ref<SourceAccessor>(AllowListSourceAccessor::create(getFSSourceAccessor(), {},
251-
[&settings](const CanonPath & path) -> RestrictedPathError {
252-
auto modeInformation = settings.pureEval
253-
? "in pure evaluation mode (use '--impure' to override)"
254-
: "in restricted mode";
255-
throw RestrictedPathError("access to absolute path '%1%' is forbidden %2%", path, modeInformation);
256-
}))
257-
: getFSSourceAccessor())
258-
, storeFS(
259-
makeMountedSourceAccessor(
260-
{
261-
{CanonPath::root, makeEmptySourceAccessor()},
262-
{CanonPath(store->storeDir), makeFSSourceAccessor(dirOf(store->toRealPath(StorePath::dummy)))}
263-
}))
249+
({
250+
auto accessor = getFSSourceAccessor();
251+
252+
/* If we have a chroot store, make a union accessor to
253+
make the chroot store available at its logical location
254+
while still having the underlying directory
255+
available. This is necessary for instance if we're
256+
evaluating a file from the physical /nix/store while
257+
using a chroot store. */
258+
auto realStoreDir = dirOf(store->toRealPath(StorePath::dummy));
259+
if (store->storeDir != realStoreDir) {
260+
auto storeFS = makeMountedSourceAccessor(
261+
{
262+
{CanonPath::root, makeEmptySourceAccessor()},
263+
{CanonPath(store->storeDir), makeFSSourceAccessor(realStoreDir)}
264+
});
265+
accessor = makeUnionSourceAccessor({accessor, storeFS});
266+
}
267+
268+
/* Apply access control if needed. */
269+
if (settings.restrictEval || settings.pureEval)
270+
accessor = AllowListSourceAccessor::create(accessor, {},
271+
[&settings](const CanonPath & path) -> RestrictedPathError {
272+
auto modeInformation = settings.pureEval
273+
? "in pure evaluation mode (use '--impure' to override)"
274+
: "in restricted mode";
275+
throw RestrictedPathError("access to absolute path '%1%' is forbidden %2%", path, modeInformation);
276+
});
277+
278+
accessor;
279+
}))
264280
, corepkgsFS(make_ref<MemorySourceAccessor>())
265281
, internalFS(make_ref<MemorySourceAccessor>())
266282
, derivationInternal{corepkgsFS->addFile(
@@ -350,7 +366,7 @@ void EvalState::allowPath(const Path & path)
350366
void EvalState::allowPath(const StorePath & storePath)
351367
{
352368
if (auto rootFS2 = rootFS.dynamic_pointer_cast<AllowListSourceAccessor>())
353-
rootFS2->allowPrefix(CanonPath(store->toRealPath(storePath)));
369+
rootFS2->allowPrefix(CanonPath(store->printStorePath(storePath)));
354370
}
355371

356372
void EvalState::allowClosure(const StorePath & storePath)
@@ -2428,7 +2444,7 @@ SourcePath EvalState::coerceToPath(const PosIdx pos, Value & v, NixStringContext
24282444
auto path = coerceToString(pos, v, context, errorCtx, false, false, true).toOwned();
24292445
if (path == "" || path[0] != '/')
24302446
error<EvalError>("string '%1%' doesn't represent an absolute path", path).withTrace(pos, errorCtx).debugThrow();
2431-
return stringWithContextToPath(path, context);
2447+
return rootPath(path);
24322448
}
24332449

24342450

@@ -3082,7 +3098,7 @@ std::optional<SourcePath> EvalState::resolveLookupPathPath(const LookupPath::Pat
30823098
fetchSettings,
30833099
EvalSettings::resolvePseudoUrl(value));
30843100
auto storePath = fetchToStore(*store, SourcePath(accessor), FetchMode::Copy);
3085-
return finish(rootPath(store->toRealPath(storePath)));
3101+
return finish(rootPath(store->printStorePath(storePath)));
30863102
} catch (Error & e) {
30873103
logWarning({
30883104
.msg = HintFmt("Nix search path entry '%1%' cannot be downloaded, ignoring", value)

src/libexpr/eval.hh

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -250,11 +250,6 @@ public:
250250
*/
251251
const ref<SourceAccessor> rootFS;
252252

253-
/**
254-
* The accessor for the store.
255-
*/
256-
const ref<SourceAccessor> storeFS;
257-
258253
/**
259254
* The in-memory filesystem for <nix/...> paths.
260255
*/
@@ -394,18 +389,6 @@ public:
394389
*/
395390
SourcePath rootPath(PathView path);
396391

397-
/**
398-
* Convert `s` to a path. If `context` is not empty, the resulting
399-
* path will use the `storeFS` accessor; otherwise it will use
400-
* `rootFS`. When using a chroot store, this allows us to
401-
* distinguish between store paths resulting from
402-
* import-from-derivation and sources stored in the actual
403-
* /nix/store.
404-
*/
405-
SourcePath stringWithContextToPath(
406-
std::string_view s,
407-
const NixStringContext & context);
408-
409392
/**
410393
* Allow access to a path.
411394
*/

src/libexpr/paths.cc

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,4 @@ SourcePath EvalState::rootPath(PathView path)
1313
return {rootFS, CanonPath(absPath(path))};
1414
}
1515

16-
SourcePath EvalState::stringWithContextToPath(std::string_view s, const NixStringContext & context)
17-
{
18-
auto path = CanonPath(s);
19-
return !context.empty() ? SourcePath{storeFS, std::move(path)} : rootPath(std::move(path));
20-
}
21-
2216
}

src/libexpr/primops.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ static SourcePath realisePath(EvalState & state, const PosIdx pos, Value & v, st
143143
auto path = state.coerceToPath(noPos, v, context, "while realising the context of a path");
144144

145145
try {
146-
if (!context.empty() && path.accessor == state.storeFS) {
146+
if (!context.empty() && path.accessor == state.rootFS) {
147147
auto rewrites = state.realiseContext(context);
148148
path = {path.accessor, CanonPath(rewriteStrings(path.path.abs(), rewrites))};
149149
}
@@ -2480,7 +2480,7 @@ static void addPath(
24802480
try {
24812481
StorePathSet refs;
24822482

2483-
if (path.accessor == state.storeFS && state.store->isInStore(path.path.abs())) {
2483+
if (path.accessor == state.rootFS && state.store->isInStore(path.path.abs())) {
24842484
// FIXME: handle CA derivation outputs (where path needs to
24852485
// be rewritten to the actual output).
24862486
auto rewrites = state.realiseContext(context);

src/libflake/flake/flake.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ static Flake readFlake(
337337
auto storePath = fetchToStore(*state.store, setting.value->path(), FetchMode::Copy);
338338
flake.config.settings.emplace(
339339
state.symbols[setting.name],
340-
state.store->toRealPath(storePath));
340+
state.store->printStorePath(storePath));
341341
}
342342
else if (setting.value->type() == nInt)
343343
flake.config.settings.emplace(
@@ -423,7 +423,7 @@ static Flake getFlake(
423423
auto storePath = copyInputToStore(state, lockedRef.input, originalRef.input, accessor);
424424

425425
// Re-parse flake.nix from the store.
426-
return readFlake(state, originalRef, resolvedRef, lockedRef, state.rootPath(state.store->toRealPath(storePath)), lockRootAttrPath);
426+
return readFlake(state, originalRef, resolvedRef, lockedRef, state.rootPath(state.store->printStorePath(storePath)), lockRootAttrPath);
427427
}
428428

429429
Flake getFlake(EvalState & state, const FlakeRef & originalRef, bool useRegistries)
@@ -784,7 +784,7 @@ LockedFlake lockFlake(
784784
// FIXME: allow input to be lazy.
785785
auto storePath = copyInputToStore(state, lockedRef.input, input.ref->input, accessor);
786786

787-
return {state.rootPath(state.store->toRealPath(storePath)), lockedRef};
787+
return {state.rootPath(state.store->printStorePath(storePath)), lockedRef};
788788
}
789789
}();
790790

0 commit comments

Comments
 (0)