@@ -213,35 +213,54 @@ EvalState::EvalState(
213
213
, settings{settings}
214
214
, symbols(StaticEvalSymbols::staticSymbolTable())
215
215
, repair(NoRepair)
216
- , storeFS(makeMountedSourceAccessor({
217
- {CanonPath::root, makeEmptySourceAccessor ()},
218
- /* In the pure eval case, we can simply require
219
- valid paths. However, in the *impure* eval
220
- case this gets in the way of the union
221
- mechanism, because an invalid access in the
222
- upper layer will *not* be caught by the union
223
- source accessor, but instead abort the entire
224
- lookup.
225
-
226
- This happens when the store dir in the
227
- ambient file system has a path (e.g. because
228
- another Nix store there), but the relocated
229
- store does not.
230
-
231
- TODO make the various source accessors doing
232
- access control all throw the same type of
233
- exception, and make union source accessor
234
- catch it, so we don't need to do this hack.
235
- */
236
- {CanonPath (store->storeDir ), store->getFSAccessor (settings.pureEval )},
237
- }))
238
- , rootFS([&] {
239
- auto accessor = [&]() -> decltype (rootFS) {
240
- /* In pure eval mode, we provide a filesystem that only
241
- contains the Nix store. */
242
- if (settings.pureEval )
243
- return storeFS;
216
+ , storeFS([&] {
217
+ auto accessor = makeMountedSourceAccessor ({{CanonPath::root, makeEmptySourceAccessor ()}});
218
+
219
+ /* In the pure eval case, we can simply require
220
+ valid paths. However, in the *impure* eval
221
+ case this gets in the way of the union
222
+ mechanism, because an invalid access in the
223
+ upper layer will *not* be caught by the union
224
+ source accessor, but instead abort the entire
225
+ lookup.
226
+
227
+ This happens when the store dir in the
228
+ ambient file system has a path (e.g. because
229
+ another Nix store there), but the relocated
230
+ store does not.
231
+
232
+ TODO make the various source accessors doing
233
+ access control all throw the same type of
234
+ exception, and make union source accessor
235
+ catch it, so we don't need to do this hack.
236
+ */
237
+ if (settings.pureEval ) {
238
+ /* This is just an overkill way to make sure other store
239
+ paths get this error, and not the "doesn't exist" error
240
+ that the mounted source accessor would do on its own. */
241
+ accessor->mount (
242
+ CanonPath::root,
243
+ AllowListSourceAccessor::create (
244
+ getFSSourceAccessor (), {}, {CanonPath::root, CanonPath (store->storeDir )}, [&](const CanonPath & path) -> RestrictedPathError {
245
+ throw RestrictedPathError (
246
+ " access to absolute path '%1%' is forbidden in pure evaluation mode (use '--impure' to override)" ,
247
+ CanonPath (store->storeDir ) / path);
248
+ }));
249
+ /* We don't want to list store paths */
250
+ accessor->mount (CanonPath (store->storeDir ), makeEmptySourceAccessor ());
251
+ } else {
252
+ accessor->mount (CanonPath (store->storeDir ), store->getFSAccessor (false ));
253
+ }
254
+
255
+ return accessor;
256
+ }())
257
+ , rootFS([&] -> decltype (rootFS) {
258
+ /* In pure eval mode, we provide a filesystem that only
259
+ contains the Nix store. */
260
+ if (settings.pureEval )
261
+ return storeFS;
244
262
263
+ auto makeImpureAccessor = [&]() -> decltype (rootFS) {
245
264
/* If we have a chroot store and pure eval is not enabled,
246
265
use a union accessor to make the chroot store available
247
266
at its logical location while still having the underlying
@@ -253,18 +272,16 @@ EvalState::EvalState(
253
272
return makeUnionSourceAccessor ({getFSSourceAccessor (), storeFS});
254
273
255
274
return getFSSourceAccessor ();
256
- }() ;
275
+ };
257
276
258
277
/* Apply access control if needed. */
259
- if (settings.restrictEval || settings.pureEval )
260
- accessor = AllowListSourceAccessor::create (
261
- accessor, {}, {}, [&settings](const CanonPath & path) -> RestrictedPathError {
262
- auto modeInformation = settings.pureEval ? " in pure evaluation mode (use '--impure' to override)"
263
- : " in restricted mode" ;
264
- throw RestrictedPathError (" access to absolute path '%1%' is forbidden %2%" , path, modeInformation);
278
+ if (settings.restrictEval )
279
+ return AllowListSourceAccessor::create (
280
+ makeImpureAccessor (), {}, {}, [](const CanonPath & path) -> RestrictedPathError {
281
+ throw RestrictedPathError (" access to absolute path '%1%' is forbidden in restricted mode" , path);
265
282
});
266
283
267
- return accessor ;
284
+ return makeImpureAccessor () ;
268
285
}())
269
286
, corepkgsFS(make_ref<MemorySourceAccessor>())
270
287
, internalFS(make_ref<MemorySourceAccessor>())
@@ -351,13 +368,19 @@ void EvalState::allowPathLegacy(const Path & path)
351
368
352
369
void EvalState::allowPath (const StorePath & storePath)
353
370
{
354
- if (auto rootFS2 = rootFS.dynamic_pointer_cast <AllowListSourceAccessor>())
371
+ if (settings.pureEval ) {
372
+ storeFS->mount (CanonPath (store->printStorePath (storePath)), ref{store->getFSAccessor (storePath)});
373
+ }
374
+ if (settings.restrictEval ) {
375
+ auto rootFS2 = rootFS.dynamic_pointer_cast <AllowListSourceAccessor>();
376
+ assert (rootFS2);
355
377
rootFS2->allowPrefix (CanonPath (store->printStorePath (storePath)));
378
+ }
356
379
}
357
380
358
381
void EvalState::allowClosure (const StorePath & storePath)
359
382
{
360
- if (!rootFS. dynamic_pointer_cast <AllowListSourceAccessor>() )
383
+ if (!settings. pureEval && !settings. restrictEval )
361
384
return ;
362
385
363
386
StorePathSet closure;
0 commit comments