findRoots(): Add 'censor' parameter
This is less brittle than filtering paths after the fact in nix-daemon.
This commit is contained in:
parent
a3f37d87ea
commit
53522cb6ac
7 changed files with 40 additions and 53 deletions
|
@ -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,6 +470,9 @@ 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);
|
||||||
|
if (censor)
|
||||||
|
roots[path].insert(censored);
|
||||||
|
else
|
||||||
roots[path].insert(links.begin(), links.end());
|
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());
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
|
@ -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;
|
|
||||||
for (auto & link : root.second) {
|
|
||||||
if (link.rfind("{memory:", 0) == 0) {
|
|
||||||
if (hasMemoryLink) continue;
|
|
||||||
++total_length;
|
|
||||||
hasMemoryLink = true;
|
|
||||||
} else {
|
|
||||||
++total_length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
to << total_length;
|
to << size;
|
||||||
int n = 0;
|
|
||||||
for (auto & [target, links] : roots) {
|
for (auto & [target, links] : roots)
|
||||||
bool hasMemoryLink = false;
|
for (auto & link : links)
|
||||||
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;
|
to << link << target;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue