libutil: don't trust RemoteStore activity ids

remotes can generate the same activity ids we might generate locally,
especially if the remote is accessed over the network. in that case a
pid collision is possible, and since activity ids are sequential it's
very possible to create colliding activity ids on both sides as well.

Change-Id: Id58074a41f5f7a59171b52818d1fb5a1beb4bf40
This commit is contained in:
eldritch horrors
2025-10-12 22:37:31 +00:00
parent ed034d0526
commit 47000b658e
+32 -21
View File
@@ -784,43 +784,54 @@ RemoteStore::Connection::processStderr(AsyncFdIoStream & stream)
try {
AsyncBufferedInputStream from{stream, fromBuf};
std::map<ActivityId, Activity> remoteActivities;
while (true) {
auto msg = TRY_AWAIT(readNum<uint64_t>(from));
if (msg == STDERR_ERROR) {
co_return RemoteError{std::make_exception_ptr(TRY_AWAIT(readError(from)))};
}
else if (msg == STDERR_NEXT)
} else if (msg == STDERR_NEXT) {
printError("%1%", Uncolored(chomp(TRY_AWAIT(readString(from)))));
else if (msg == STDERR_START_ACTIVITY) {
} else if (msg == STDERR_START_ACTIVITY) {
auto act = TRY_AWAIT(readNum<ActivityId>(from));
auto lvl = (Verbosity) TRY_AWAIT(readNum<unsigned>(from));
auto type = (ActivityType) TRY_AWAIT(readNum<unsigned>(from));
auto s = TRY_AWAIT(readString(from));
auto fields = TRY_AWAIT(readFields(from));
auto parent = TRY_AWAIT(readNum<ActivityId>(from));
logger->startActivity(act, lvl, type, s, fields, parent);
}
else if (msg == STDERR_STOP_ACTIVITY) {
auto act = TRY_AWAIT(readNum<ActivityId>(from));
logger->stopActivity(act);
}
else if (msg == STDERR_RESULT) {
const auto parentId = TRY_AWAIT(readNum<ActivityId>(from));
const auto parent = parentId == 0 ? nullptr : [&] {
const auto parent = get(remoteActivities, parentId);
if (!parent) {
printError(
"remote started child activity of %s that isn't currently known!", parentId
);
}
return parent;
}();
remoteActivities.emplace(act, Activity(*logger, lvl, type, s, fields, parent));
} else if (msg == STDERR_STOP_ACTIVITY) {
auto act = TRY_AWAIT(readNum<ActivityId>(from));
if (remoteActivities.erase(act) == 0) {
printError("remote stopped activity %s that isn't currently known!", act);
}
} else if (msg == STDERR_RESULT) {
const auto actId = TRY_AWAIT(readNum<ActivityId>(from));
auto type = (ResultType) TRY_AWAIT(readNum<unsigned>(from));
auto fields = TRY_AWAIT(readFields(from));
logger->result(act, type, fields);
}
else if (msg == STDERR_LAST)
const auto act = get(remoteActivities, actId);
if (!act) {
printError(
"remote reported result for activity %s that isn't currently known!", actId
);
continue;
}
act->result(type, fields);
} else if (msg == STDERR_LAST) {
break;
else
} else {
throw Error("got unknown message type %x from Nix daemon", msg);
}
}
co_return RemoteError{nullptr};