diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 510e95e481ba..9f93b1064b0b 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -858,11 +858,11 @@ StorePathSet LocalStore::queryAllValidPaths() } -void LocalStore::queryReferrers(State & state, const StorePath & path, StorePathSet & referrers) +void LocalStore::queryReferrers(State & state, const StorePath & path, StorePathSet & referrers, bool accessCheck) { auto useQueryReferrers(state.stmts->QueryReferrers.use()(printStorePath(path))); - if (!canAccess(path)) throw AccessDenied("Access Denied"); + if (accessCheck && !canAccess(path)) throw AccessDenied("Access Denied"); while (useQueryReferrers.next()) referrers.insert(parseStorePath(useQueryReferrers.getStr(0))); @@ -1086,7 +1086,7 @@ void LocalStore::setCurrentAccessStatus(const Path & path, const LocalStore::Acc auto info = promise.get_future().get(); - if (info){ + if (info) { for (auto reference : info->references) { if (reference == storePath) continue; auto otherStatus = getCurrentAccessStatus(printStorePath(reference)); @@ -1103,6 +1103,28 @@ void LocalStore::setCurrentAccessStatus(const Path & path, const LocalStore::Acc } } } + + StorePathSet referrers; + retrySQLite([&]() { + auto state(_state.lock()); + queryReferrers(*state, storePath, referrers, false); + }); + + for (auto referrer : referrers) { + if (referrer == storePath) continue; + auto otherStatus = getCurrentAccessStatus(printStorePath(referrer)); + if (!status.isProtected) continue; + if (!otherStatus.isProtected) + throw AccessDenied("can not make %s protected because it is referenced by a non-protected path %s", path, printStorePath(referrer)); + std::vector difference; + std::set_difference(otherStatus.entities.begin(), otherStatus.entities.end(), status.entities.begin(), status.entities.end(),std::inserter(difference, difference.begin())); + + if (! difference.empty()) { + std::string entities; + for (auto entity : difference) entities += ACL::printTag(entity) + ", "; + throw AccessDenied("can not deny %s access to %s because it is referenced by a path %s to which they do not have access", entities.substr(0, entities.size()-2), path, printStorePath(referrer)); + } + } } } diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index f87f5fc40629..15cf7445fc77 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -371,7 +371,7 @@ private: // Internal versions that are not wrapped in retry_sqlite. bool isValidPath_(State & state, const StorePath & path); - void queryReferrers(State & state, const StorePath & path, StorePathSet & referrers); + void queryReferrers(State & state, const StorePath & path, StorePathSet & referrers, bool accessCheck = true); /** * Add signatures to a ValidPathInfo or Realisation using the secret keys