@@ -861,8 +861,6 @@ uint64_t LocalStore::addValidPath(State & state,
861
861
throw Error (" cannot add path '%s' to the Nix store because it claims to be content-addressed but isn't" ,
862
862
printStorePath (info.path ));
863
863
864
- syncPathPermissions (info);
865
-
866
864
state.stmts ->RegisterValidPath .use ()
867
865
(printStorePath (info.path ))
868
866
(info.narHash .to_string (Base16, true ))
@@ -1174,20 +1172,22 @@ void LocalStore::syncPathPermissions(const ValidPathInfo & info)
1174
1172
}
1175
1173
}
1176
1174
1177
- void LocalStore::registerValidPath (const ValidPathInfo & info)
1175
+ void LocalStore::registerValidPath (const ValidPathInfo & info, bool syncPermissions )
1178
1176
{
1179
- registerValidPaths ({{info.path , info}});
1177
+ registerValidPaths ({{info.path , info}}, syncPermissions );
1180
1178
}
1181
1179
1182
1180
1183
- void LocalStore::registerValidPaths (const ValidPathInfos & infos)
1181
+ void LocalStore::registerValidPaths (const ValidPathInfos & infos, bool syncPermissions )
1184
1182
{
1185
1183
/* SQLite will fsync by default, but the new valid paths may not
1186
1184
be fsync-ed. So some may want to fsync them before registering
1187
1185
the validity, at the expense of some speed of the path
1188
1186
registering operation. */
1189
1187
if (settings.syncBeforeRegistering ) sync ();
1190
1188
1189
+ std::vector<StorePath> sortedPaths;
1190
+
1191
1191
retrySQLite<void >([&]() {
1192
1192
auto state (_state.lock ());
1193
1193
@@ -1222,7 +1222,7 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos)
1222
1222
error if a cycle is detected and roll back the
1223
1223
transaction. Cycles can only occur when a derivation
1224
1224
has multiple outputs. */
1225
- topoSort (paths,
1225
+ sortedPaths = topoSort (paths,
1226
1226
{[&](const StorePath & path) {
1227
1227
auto i = infos.find (path);
1228
1228
return i == infos.end () ? StorePathSet () : i->second .references ;
@@ -1236,12 +1236,55 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos)
1236
1236
1237
1237
txn.commit ();
1238
1238
});
1239
+
1240
+ std::reverse (sortedPaths.begin (), sortedPaths.end ());
1241
+
1242
+ if (syncPermissions)
1243
+ for (auto path : sortedPaths)
1244
+ syncPathPermissions (infos.at (path));
1239
1245
}
1240
1246
1241
1247
void LocalStore::setCurrentAccessStatus (const Path & path, const LocalStore::AccessStatus & status)
1242
1248
{
1243
1249
experimentalFeatureSettings.require (Xp::ACLs);
1244
1250
1251
+ if (isInStore (path)) {
1252
+ StorePath storePath (baseNameOf (path));
1253
+
1254
+ // FIXME(acls): cache is broken when called from registerValidPaths
1255
+
1256
+ std::promise<ref<const ValidPathInfo>> promise;
1257
+
1258
+ queryPathInfoUncached (storePath,
1259
+ {[&](std::future<std::shared_ptr<const ValidPathInfo>> result) {
1260
+ try {
1261
+ promise.set_value (ref (result.get ()));
1262
+ } catch (...) {
1263
+ promise.set_exception (std::current_exception ());
1264
+ }
1265
+ }});
1266
+
1267
+ auto info = promise.get_future ().get ();
1268
+
1269
+ for (auto reference : info->references ) {
1270
+ if (reference == storePath) continue ;
1271
+ auto otherStatus = getCurrentAccessStatus (printStorePath (reference));
1272
+ if (!otherStatus.isProtected ) continue ;
1273
+ if (!status.isProtected )
1274
+ throw AccessDenied (" can not make %s non-protected because it references a protected path %s" , path, printStorePath (reference));
1275
+ std::vector<AccessControlEntity> difference;
1276
+ std::set_difference (status.entities .begin (), status.entities .end (), otherStatus.entities .begin (), otherStatus.entities .end (), difference.begin ());
1277
+
1278
+ if (! difference.empty ()) {
1279
+ std::string entities;
1280
+ for (auto entity : difference) entities += ACL::printTag (entity) + " , " ;
1281
+ throw AccessDenied (" can not allow %s access to %s because it references path %s to which they do not have access" , entities.substr (0 , entities.size ()-2 ), path, printStorePath (reference));
1282
+ }
1283
+ }
1284
+ }
1285
+
1286
+ debug (" setting access status %s on %s" , status.json ().dump (), path);
1287
+
1245
1288
using namespace ACL ;
1246
1289
1247
1290
// NOTE: On Darwin, the standard posix permissions are not part of the ACL API.
0 commit comments