@@ -454,8 +454,46 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
454
454
readDerivation (from, *store, drv, Derivation::nameFromPath (drvPath));
455
455
BuildMode buildMode = (BuildMode) readInt (from);
456
456
logger->startWork ();
457
- if (!trusted)
458
- throw Error (" you are not privileged to build derivations" );
457
+
458
+ /* Content-addressed derivations are trustless because their output paths
459
+ are verified by their content alone, so any derivation is free to
460
+ try to produce such a path.
461
+
462
+ Input-addressed derivation output paths, however, are calculated
463
+ from the derivation closure that produced them---even knowing the
464
+ root derivation is not enough. That the output data actually came
465
+ from those derivations is fundamentally unverifiable, but the daemon
466
+ trusts itself on that matter. The question instead is whether the
467
+ submitted plan has rights to the output paths it wants to fill, and
468
+ at least the derivation closure proves that.
469
+
470
+ It would have been nice if input-address algorithm merely depended
471
+ on the build time closure, rather than depending on the derivation
472
+ closure. That would mean input-addressed paths used at build time
473
+ would just be trusted and not need their own evidence. This is in
474
+ fact fine as the same guarantees would hold *inductively*: either
475
+ the remote builder has those paths and already trusts them, or it
476
+ needs to build them too and thus their evidence must be provided in
477
+ turn. The advantage of this variant algorithm is that the evidence
478
+ for input-addressed paths which the remote builder already has
479
+ doesn't need to be sent again.
480
+
481
+ That said, now that we have floating CA derivations, it is better
482
+ that people just migrate to those which also solve this problem, and
483
+ others. It's the same migration difficulty with strictly more
484
+ benefit.
485
+
486
+ Lastly, do note that when we parse fixed-output content-addressed
487
+ derivations, we throw out the precomputed output paths and just
488
+ store the hashes, so there aren't two competing sources of truth an
489
+ attacker could exploit. */
490
+ if (drv.type () == DerivationType::InputAddressed && !trusted)
491
+ throw Error (" you are not privileged to build input-addressed derivations" );
492
+
493
+ /* Make sure that the non-input-addressed derivations that got this far
494
+ are in fact content-addressed if we don't trust them. */
495
+ assert (derivationIsCA (drv.type ()) || trusted);
496
+
459
497
auto res = store->buildDerivation (drvPath, drv, buildMode);
460
498
logger->stopWork ();
461
499
to << res.status << res.errorMsg ;
0 commit comments