findRoots(): Add 'censor' parameter

This is less brittle than filtering paths after the fact in
nix-daemon.
This commit is contained in:
Eelco Dolstra 2019-03-14 13:50:07 +01:00
parent a3f37d87ea
commit 53522cb6ac
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE
7 changed files with 40 additions and 53 deletions

View file

@ -129,7 +129,7 @@ Path LocalFSStore::addPermRoot(const Path & _storePath,
check if the root is in a directory in or linked from the check if the root is in a directory in or linked from the
gcroots directory. */ gcroots directory. */
if (settings.checkRootReachability) { if (settings.checkRootReachability) {
Roots roots = findRoots(); Roots roots = findRoots(false);
if (roots[storePath].count(gcRoot) == 0) if (roots[storePath].count(gcRoot) == 0)
printError( printError(
format( format(
@ -197,7 +197,10 @@ void LocalStore::addTempRoot(const Path & path)
} }
void LocalStore::findTempRoots(FDs & fds, Roots & tempRoots) static std::string censored = "{censored}";
void LocalStore::findTempRoots(FDs & fds, Roots & tempRoots, bool censor)
{ {
/* Read the `temproots' directory for per-process temporary root /* Read the `temproots' directory for per-process temporary root
files. */ files. */
@ -248,7 +251,7 @@ void LocalStore::findTempRoots(FDs & fds, Roots & tempRoots)
Path root(contents, pos, end - pos); Path root(contents, pos, end - pos);
debug("got temporary root '%s'", root); debug("got temporary root '%s'", root);
assertStorePath(root); assertStorePath(root);
tempRoots[root].emplace(fmt("{temp:%d}", pid)); tempRoots[root].emplace(censor ? censored : fmt("{temp:%d}", pid));
pos = end + 1; pos = end + 1;
} }
@ -317,7 +320,7 @@ void LocalStore::findRoots(const Path & path, unsigned char type, Roots & roots)
} }
void LocalStore::findRootsNoTemp(Roots & roots) void LocalStore::findRootsNoTemp(Roots & roots, bool censor)
{ {
/* Process direct roots in {gcroots,profiles}. */ /* Process direct roots in {gcroots,profiles}. */
findRoots(stateDir + "/" + gcRootsDir, DT_UNKNOWN, roots); findRoots(stateDir + "/" + gcRootsDir, DT_UNKNOWN, roots);
@ -327,17 +330,17 @@ void LocalStore::findRootsNoTemp(Roots & roots)
NIX_ROOT_FINDER environment variable. This is typically used NIX_ROOT_FINDER environment variable. This is typically used
to add running programs to the set of roots (to prevent them to add running programs to the set of roots (to prevent them
from being garbage collected). */ from being garbage collected). */
findRuntimeRoots(roots); findRuntimeRoots(roots, censor);
} }
Roots LocalStore::findRoots() Roots LocalStore::findRoots(bool censor)
{ {
Roots roots; Roots roots;
findRootsNoTemp(roots); findRootsNoTemp(roots, censor);
FDs fds; FDs fds;
findTempRoots(fds, roots); findTempRoots(fds, roots, censor);
return roots; return roots;
} }
@ -381,7 +384,7 @@ static void readFileRoots(const char * path, Roots & roots)
} }
} }
void LocalStore::findRuntimeRoots(Roots & roots) void LocalStore::findRuntimeRoots(Roots & roots, bool censor)
{ {
Roots unchecked; Roots unchecked;
@ -467,7 +470,10 @@ void LocalStore::findRuntimeRoots(Roots & roots)
Path path = toStorePath(target); Path path = toStorePath(target);
if (isStorePath(path) && isValidPath(path)) { if (isStorePath(path) && isValidPath(path)) {
debug(format("got additional root '%1%'") % path); debug(format("got additional root '%1%'") % path);
roots[path].insert(links.begin(), links.end()); if (censor)
roots[path].insert(censored);
else
roots[path].insert(links.begin(), links.end());
} }
} }
} }
@ -739,7 +745,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
printError(format("finding garbage collector roots...")); printError(format("finding garbage collector roots..."));
Roots rootMap; Roots rootMap;
if (!options.ignoreLiveness) if (!options.ignoreLiveness)
findRootsNoTemp(rootMap); findRootsNoTemp(rootMap, true);
for (auto & i : rootMap) state.roots.insert(i.first); for (auto & i : rootMap) state.roots.insert(i.first);
@ -748,7 +754,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
can be added to the set of temporary roots. */ can be added to the set of temporary roots. */
FDs fds; FDs fds;
Roots tempRoots; Roots tempRoots;
findTempRoots(fds, tempRoots); findTempRoots(fds, tempRoots, true);
for (auto & root : tempRoots) for (auto & root : tempRoots)
state.tempRoots.insert(root.first); state.tempRoots.insert(root.first);
state.roots.insert(state.tempRoots.begin(), state.tempRoots.end()); state.roots.insert(state.tempRoots.begin(), state.tempRoots.end());

View file

@ -180,11 +180,11 @@ private:
typedef std::shared_ptr<AutoCloseFD> FDPtr; typedef std::shared_ptr<AutoCloseFD> FDPtr;
typedef list<FDPtr> FDs; typedef list<FDPtr> FDs;
void findTempRoots(FDs & fds, Roots & roots); void findTempRoots(FDs & fds, Roots & roots, bool censor);
public: public:
Roots findRoots() override; Roots findRoots(bool censor) override;
void collectGarbage(const GCOptions & options, GCResults & results) override; void collectGarbage(const GCOptions & options, GCResults & results) override;
@ -267,9 +267,9 @@ private:
void findRoots(const Path & path, unsigned char type, Roots & roots); void findRoots(const Path & path, unsigned char type, Roots & roots);
void findRootsNoTemp(Roots & roots); void findRootsNoTemp(Roots & roots, bool censor);
void findRuntimeRoots(Roots & roots); void findRuntimeRoots(Roots & roots, bool censor);
void removeUnusedLinks(const GCState & state); void removeUnusedLinks(const GCState & state);

View file

@ -596,7 +596,7 @@ void RemoteStore::syncWithGC()
} }
Roots RemoteStore::findRoots() Roots RemoteStore::findRoots(bool censor)
{ {
auto conn(getConnection()); auto conn(getConnection());
conn->to << wopFindRoots; conn->to << wopFindRoots;

View file

@ -82,7 +82,7 @@ public:
void syncWithGC() override; void syncWithGC() override;
Roots findRoots() override; Roots findRoots(bool censor) override;
void collectGarbage(const GCOptions & options, GCResults & results) override; void collectGarbage(const GCOptions & options, GCResults & results) override;

View file

@ -484,8 +484,10 @@ public:
/* Find the roots of the garbage collector. Each root is a pair /* Find the roots of the garbage collector. Each root is a pair
(link, storepath) where `link' is the path of the symlink (link, storepath) where `link' is the path of the symlink
outside of the Nix store that point to `storePath'. */ outside of the Nix store that point to `storePath'. If
virtual Roots findRoots() 'censor' is true, privacy-sensitive information about roots
found in /proc is censored. */
virtual Roots findRoots(bool censor)
{ unsupported("findRoots"); } { unsupported("findRoots"); }
/* Perform a garbage collection. */ /* Perform a garbage collection. */

View file

@ -475,40 +475,19 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
case wopFindRoots: { case wopFindRoots: {
logger->startWork(); logger->startWork();
Roots roots = store->findRoots(); Roots roots = store->findRoots(true);
logger->stopWork(); logger->stopWork();
// Pre-compute roots length using same algo as below. size_t size = 0;
size_t total_length = 0; for (auto & i : roots)
bool hasMemoryLink; size += i.second.size();
for (auto & root : roots) {
hasMemoryLink = false; to << size;
for (auto & link : root.second) {
if (link.rfind("{memory:", 0) == 0) { for (auto & [target, links] : roots)
if (hasMemoryLink) continue; for (auto & link : links)
++total_length; to << link << target;
hasMemoryLink = true;
} else {
++total_length;
}
}
}
to << total_length;
int n = 0;
for (auto & [target, links] : roots) {
bool hasMemoryLink = false;
for (auto & link : links) {
// Obfuscate 'memory' roots as they expose information about other users,
if (link.rfind("{memory:", 0) == 0) {
if (hasMemoryLink) continue;
to << fmt("{memory:%d}", n++) << target;
hasMemoryLink = true;
} else {
to << link << target;
}
}
}
break; break;
} }

View file

@ -427,7 +427,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise), maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise),
referrers, true, settings.gcKeepOutputs, settings.gcKeepDerivations); referrers, true, settings.gcKeepOutputs, settings.gcKeepDerivations);
} }
Roots roots = store->findRoots(); Roots roots = store->findRoots(false);
for (auto & [target, links] : roots) for (auto & [target, links] : roots)
if (referrers.find(target) != referrers.end()) if (referrers.find(target) != referrers.end())
for (auto & link : links) for (auto & link : links)
@ -591,7 +591,7 @@ static void opGC(Strings opFlags, Strings opArgs)
if (!opArgs.empty()) throw UsageError("no arguments expected"); if (!opArgs.empty()) throw UsageError("no arguments expected");
if (printRoots) { if (printRoots) {
Roots roots = store->findRoots(); Roots roots = store->findRoots(false);
for (auto & [target, links] : roots) for (auto & [target, links] : roots)
for (auto & link : links) for (auto & link : links)
cout << link << " -> " << target << std::endl; cout << link << " -> " << target << std::endl;