fix: lock crash report ring buffer (SMP race) and guard crashpad crash loop

This commit is contained in:
2026-06-19 19:36:21 +02:00
parent 820b908b80
commit de871ac402
5 changed files with 72 additions and 28 deletions
+1 -1
View File
@@ -12,4 +12,4 @@
#pragma once
#define MONTAUK_BUILD_NUMBER 128
#define MONTAUK_BUILD_NUMBER 129
+27 -25
View File
@@ -13,38 +13,40 @@ namespace montauk::abi {
static int64_t Sys_CrashReport(CrashReportInfo* out) {
if (!out) return 0;
if (CrashReport::g_reportCount == 0) return 0;
int oldestIdx = (CrashReport::g_reportHead - CrashReport::g_reportCount + CrashReport::MaxReports) % CrashReport::MaxReports;
auto* rep = &CrashReport::g_reports[oldestIdx];
// Pop the oldest report into a kernel-local copy under the ring lock,
// then marshal into user memory with the lock released.
CrashReport::Report rep;
int had = CrashReport::TakeOldest(rep);
if (had == 0) return 0;
out->pid = rep->pid;
out->pid = rep.pid;
int pn;
for (pn = 0; pn < 63 && rep->processName[pn]; pn++) out->processName[pn] = rep->processName[pn];
for (pn = 0; pn < 63 && rep.processName[pn]; pn++) out->processName[pn] = rep.processName[pn];
out->processName[pn] = '\0';
out->exceptionVector = rep->exceptionVector;
out->exceptionVector = rep.exceptionVector;
int en;
for (en = 0; en < 31 && rep->exceptionName[en]; en++) out->exceptionName[en] = rep->exceptionName[en];
for (en = 0; en < 31 && rep.exceptionName[en]; en++) out->exceptionName[en] = rep.exceptionName[en];
out->exceptionName[en] = '\0';
out->faultingAddress = rep->faultingAddress;
out->instructionPointer = rep->instructionPointer;
out->stackPointer = rep->stackPointer;
out->codeSegment = rep->codeSegment;
out->flags = rep->flags;
out->stackSegment = rep->stackSegment;
out->pfPresent = rep->pfPresent;
out->pfWrite = rep->pfWrite;
out->pfUser = rep->pfUser;
out->pfReservedWrite = rep->pfReservedWrite;
out->pfInstructionFetch = rep->pfInstructionFetch;
out->pfProtectionKey = rep->pfProtectionKey;
out->pfShadowStack = rep->pfShadowStack;
out->pfSGX = rep->pfSGX;
out->timestampTick = rep->timestampTick;
rep->valid = false;
CrashReport::g_reportCount--;
out->faultingAddress = rep.faultingAddress;
out->instructionPointer = rep.instructionPointer;
out->stackPointer = rep.stackPointer;
out->codeSegment = rep.codeSegment;
out->flags = rep.flags;
out->stackSegment = rep.stackSegment;
out->pfPresent = rep.pfPresent;
out->pfWrite = rep.pfWrite;
out->pfUser = rep.pfUser;
out->pfReservedWrite = rep.pfReservedWrite;
out->pfInstructionFetch = rep.pfInstructionFetch;
out->pfProtectionKey = rep.pfProtectionKey;
out->pfShadowStack = rep.pfShadowStack;
out->pfSGX = rep.pfSGX;
out->timestampTick = rep.timestampTick;
return CrashReport::g_reportCount + 1;
// Preserve the original contract: count of reports present before this
// call (i.e. including the one just returned).
return had;
}
}