This changes comes with several different refactorings all rolled into one, unfotunately I couldn't find a way to pull them apart: - First of all annotations now can either recorded (that is, we copy the value and have the crash reporting code own the copy) or registered. Several annotations are changed to use this functionality so that we don't need to update them as their value change. - The code in the exception handler is modified to read the annotations from the mozannotation_client crate. This has the unfortunate side-effect that we need three different bits of code to serialize them: one for annotations read from a child process, one for reading annotations from the main process outside of the exception handler and one for reading annotations from the main process within the exception handler. As we move to fully out-of-process crash reporting the last two methods will go away. - The mozannotation_client crate now doesn't record annotation types anymore. I realized as I was working on this that storing types at runtime has two issues: the first one is that buggy code might change the type of an annotation (that is record it under two different types at two different moments), the second issue is that types might become corrupt during a crash, so better enforce them at annotation-writing time. The end result is that the mozannotation_* crates now only store byte buffers, track the format the data is stored in (null-terminated string, fixed size buffer, etc...) but not the type of data each annotation is supposed to contain. - Which brings us to the next change: concrete types for annotations are now enforced when they're written out. If an annotation doesn't match the expected type it's skipped. Storing an annotation with the wrong type will also trigger an assertion in debug builds. Differential Revision: https://phabricator.services.mozilla.com/D195248
191 lines
6.2 KiB
C++
191 lines
6.2 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#ifndef mozilla_net_NeckoMessageUtils_h
|
|
#define mozilla_net_NeckoMessageUtils_h
|
|
|
|
#include "mozilla/DebugOnly.h"
|
|
|
|
#include "ipc/EnumSerializer.h"
|
|
#include "ipc/IPCMessageUtils.h"
|
|
#include "ipc/IPCMessageUtilsSpecializations.h"
|
|
#include "mozilla/net/DNS.h"
|
|
#include "nsExceptionHandler.h"
|
|
#include "nsIDNSService.h"
|
|
#include "nsIHttpChannel.h"
|
|
#include "nsITRRSkipReason.h"
|
|
#include "nsPrintfCString.h"
|
|
#include "nsString.h"
|
|
#include "prio.h"
|
|
|
|
namespace IPC {
|
|
|
|
// nsIPermissionManager utilities
|
|
|
|
struct Permission {
|
|
nsCString origin, type;
|
|
uint32_t capability, expireType;
|
|
int64_t expireTime;
|
|
|
|
Permission() : capability(0), expireType(0), expireTime(0) {}
|
|
|
|
Permission(const nsCString& aOrigin, const nsACString& aType,
|
|
const uint32_t aCapability, const uint32_t aExpireType,
|
|
const int64_t aExpireTime)
|
|
: origin(aOrigin),
|
|
type(aType),
|
|
capability(aCapability),
|
|
expireType(aExpireType),
|
|
expireTime(aExpireTime) {}
|
|
|
|
bool operator==(const Permission& aOther) const {
|
|
return aOther.origin == origin && aOther.type == type &&
|
|
aOther.capability == capability && aOther.expireType == expireType &&
|
|
aOther.expireTime == expireTime;
|
|
}
|
|
};
|
|
|
|
template <>
|
|
struct ParamTraits<Permission> {
|
|
static void Write(MessageWriter* aWriter, const Permission& aParam) {
|
|
WriteParam(aWriter, aParam.origin);
|
|
WriteParam(aWriter, aParam.type);
|
|
WriteParam(aWriter, aParam.capability);
|
|
WriteParam(aWriter, aParam.expireType);
|
|
WriteParam(aWriter, aParam.expireTime);
|
|
}
|
|
|
|
static bool Read(MessageReader* aReader, Permission* aResult) {
|
|
return ReadParam(aReader, &aResult->origin) &&
|
|
ReadParam(aReader, &aResult->type) &&
|
|
ReadParam(aReader, &aResult->capability) &&
|
|
ReadParam(aReader, &aResult->expireType) &&
|
|
ReadParam(aReader, &aResult->expireTime);
|
|
}
|
|
};
|
|
|
|
template <>
|
|
struct ParamTraits<mozilla::net::NetAddr> {
|
|
static void Write(MessageWriter* aWriter,
|
|
const mozilla::net::NetAddr& aParam) {
|
|
WriteParam(aWriter, aParam.raw.family);
|
|
if (aParam.raw.family == AF_UNSPEC) {
|
|
aWriter->WriteBytes(aParam.raw.data, sizeof(aParam.raw.data));
|
|
} else if (aParam.raw.family == AF_INET) {
|
|
WriteParam(aWriter, aParam.inet.port);
|
|
WriteParam(aWriter, aParam.inet.ip);
|
|
} else if (aParam.raw.family == AF_INET6) {
|
|
WriteParam(aWriter, aParam.inet6.port);
|
|
WriteParam(aWriter, aParam.inet6.flowinfo);
|
|
WriteParam(aWriter, aParam.inet6.ip.u64[0]);
|
|
WriteParam(aWriter, aParam.inet6.ip.u64[1]);
|
|
WriteParam(aWriter, aParam.inet6.scope_id);
|
|
#if defined(XP_UNIX)
|
|
} else if (aParam.raw.family == AF_LOCAL) {
|
|
// Train's already off the rails: let's get a stack trace at least...
|
|
MOZ_CRASH(
|
|
"Error: please post stack trace to "
|
|
"https://bugzilla.mozilla.org/show_bug.cgi?id=661158");
|
|
aWriter->WriteBytes(aParam.local.path, sizeof(aParam.local.path));
|
|
#endif
|
|
} else {
|
|
if (XRE_IsParentProcess()) {
|
|
CrashReporter::RecordAnnotationU32(
|
|
CrashReporter::Annotation::UnknownNetAddrSocketFamily,
|
|
aParam.raw.family);
|
|
}
|
|
|
|
MOZ_CRASH("Unknown socket family");
|
|
}
|
|
}
|
|
|
|
static bool Read(MessageReader* aReader, mozilla::net::NetAddr* aResult) {
|
|
if (!ReadParam(aReader, &aResult->raw.family)) return false;
|
|
|
|
if (aResult->raw.family == AF_UNSPEC) {
|
|
return aReader->ReadBytesInto(&aResult->raw.data,
|
|
sizeof(aResult->raw.data));
|
|
} else if (aResult->raw.family == AF_INET) {
|
|
return ReadParam(aReader, &aResult->inet.port) &&
|
|
ReadParam(aReader, &aResult->inet.ip);
|
|
} else if (aResult->raw.family == AF_INET6) {
|
|
return ReadParam(aReader, &aResult->inet6.port) &&
|
|
ReadParam(aReader, &aResult->inet6.flowinfo) &&
|
|
ReadParam(aReader, &aResult->inet6.ip.u64[0]) &&
|
|
ReadParam(aReader, &aResult->inet6.ip.u64[1]) &&
|
|
ReadParam(aReader, &aResult->inet6.scope_id);
|
|
#if defined(XP_UNIX)
|
|
} else if (aResult->raw.family == AF_LOCAL) {
|
|
return aReader->ReadBytesInto(&aResult->local.path,
|
|
sizeof(aResult->local.path));
|
|
#endif
|
|
}
|
|
|
|
/* We've been tricked by some socket family we don't know about! */
|
|
return false;
|
|
}
|
|
};
|
|
|
|
template <>
|
|
struct ParamTraits<nsIRequest::TRRMode> {
|
|
static void Write(MessageWriter* aWriter, const nsIRequest::TRRMode& aParam) {
|
|
WriteParam(aWriter, (uint8_t)aParam);
|
|
}
|
|
static bool Read(MessageReader* aReader, nsIRequest::TRRMode* aResult) {
|
|
uint8_t mode;
|
|
if (!ReadParam(aReader, &mode)) {
|
|
return false;
|
|
}
|
|
// TODO: sanity check
|
|
*aResult = static_cast<nsIRequest::TRRMode>(mode);
|
|
return true;
|
|
}
|
|
};
|
|
|
|
template <>
|
|
struct ParamTraits<nsITRRSkipReason::value> {
|
|
static void Write(MessageWriter* aWriter,
|
|
const nsITRRSkipReason::value& aParam) {
|
|
WriteParam(aWriter, (uint8_t)aParam);
|
|
}
|
|
static bool Read(MessageReader* aReader, nsITRRSkipReason::value* aResult) {
|
|
uint8_t reason;
|
|
if (!ReadParam(aReader, &reason)) {
|
|
return false;
|
|
}
|
|
// TODO: sanity check
|
|
*aResult = static_cast<nsITRRSkipReason::value>(reason);
|
|
return true;
|
|
}
|
|
};
|
|
|
|
template <>
|
|
struct ParamTraits<nsIDNSService::DNSFlags>
|
|
: public BitFlagsEnumSerializer<
|
|
nsIDNSService::DNSFlags, nsIDNSService::DNSFlags::ALL_DNSFLAGS_BITS> {
|
|
};
|
|
|
|
template <>
|
|
struct ParamTraits<nsIDNSService::ResolverMode> {
|
|
static void Write(MessageWriter* aWriter,
|
|
const nsIDNSService::ResolverMode& aParam) {
|
|
WriteParam(aWriter, (uint8_t)aParam);
|
|
}
|
|
static bool Read(MessageReader* aReader,
|
|
nsIDNSService::ResolverMode* aResult) {
|
|
uint8_t mode;
|
|
if (!ReadParam(aReader, &mode)) {
|
|
return false;
|
|
}
|
|
// TODO: sanity check
|
|
*aResult = static_cast<nsIDNSService::ResolverMode>(mode);
|
|
return true;
|
|
}
|
|
};
|
|
|
|
} // namespace IPC
|
|
|
|
#endif // mozilla_net_NeckoMessageUtils_h
|