Bug 1779829: Replace Shmem::PrivateIPDLCaller with friend specifiers. r=nika

Instead of using the public member type `PrivateIPDLCaller` to
restrict access to certain `Shmem` member functions, make them
`private`, and designated `IProtocol` and `ITopLevelProtocol` as
friends of `Shmem`.

Differential Revision: https://phabricator.services.mozilla.com/D151952
This commit is contained in:
Jim Blandy 2022-07-27 19:13:02 +00:00
parent e31680bb58
commit 610404dcde
4 changed files with 60 additions and 66 deletions

View File

@ -415,7 +415,7 @@ bool IProtocol::AllocShmem(size_t aSize, Shmem* aOutMem) {
return false;
}
*aOutMem = Shmem(Shmem::PrivateIPDLCaller(), rawmem, id);
*aOutMem = Shmem(rawmem, id);
return true;
}
@ -432,7 +432,7 @@ bool IProtocol::AllocUnsafeShmem(size_t aSize, Shmem* aOutMem) {
return false;
}
*aOutMem = Shmem(Shmem::PrivateIPDLCaller(), rawmem, id);
*aOutMem = Shmem(rawmem, id);
return true;
}
@ -448,7 +448,7 @@ bool IProtocol::DeallocShmem(Shmem& aMem) {
return false;
}
#endif // DEBUG
aMem.forget(Shmem::PrivateIPDLCaller());
aMem.forget();
return ok;
}
@ -673,22 +673,20 @@ void IToplevelProtocol::Unregister(int32_t aId) {
Shmem::SharedMemory* IToplevelProtocol::CreateSharedMemory(size_t aSize,
bool aUnsafe,
Shmem::id_t* aId) {
RefPtr<Shmem::SharedMemory> segment(
Shmem::Alloc(Shmem::PrivateIPDLCaller(), aSize, aUnsafe));
RefPtr<Shmem::SharedMemory> segment(Shmem::Alloc(aSize, aUnsafe));
if (!segment) {
return nullptr;
}
int32_t id = NextId();
Shmem shmem(Shmem::PrivateIPDLCaller(), segment.get(), id);
Shmem shmem(segment.get(), id);
UniquePtr<Message> descriptor =
shmem.MkCreatedMessage(Shmem::PrivateIPDLCaller(), MSG_ROUTING_CONTROL);
UniquePtr<Message> descriptor = shmem.MkCreatedMessage(MSG_ROUTING_CONTROL);
if (!descriptor) {
return nullptr;
}
Unused << GetIPCChannel()->Send(std::move(descriptor));
*aId = shmem.Id(Shmem::PrivateIPDLCaller());
*aId = shmem.Id();
Shmem::SharedMemory* rawSegment = segment.get();
MOZ_ASSERT(!mShmemMap.Contains(*aId), "Don't insert with an existing ID");
mShmemMap.InsertOrUpdate(*aId, segment.forget().take());
@ -709,19 +707,18 @@ bool IToplevelProtocol::IsTrackingSharedMemory(Shmem::SharedMemory* segment) {
}
bool IToplevelProtocol::DestroySharedMemory(Shmem& shmem) {
Shmem::id_t aId = shmem.Id(Shmem::PrivateIPDLCaller());
Shmem::id_t aId = shmem.Id();
Shmem::SharedMemory* segment = LookupSharedMemory(aId);
if (!segment) {
return false;
}
UniquePtr<Message> descriptor =
shmem.MkDestroyedMessage(Shmem::PrivateIPDLCaller(), MSG_ROUTING_CONTROL);
UniquePtr<Message> descriptor = shmem.MkDestroyedMessage(MSG_ROUTING_CONTROL);
MOZ_ASSERT(mShmemMap.Contains(aId),
"Attempting to remove an ID not in the shmem map");
mShmemMap.Remove(aId);
Shmem::Dealloc(Shmem::PrivateIPDLCaller(), segment);
Shmem::Dealloc(segment);
MessageChannel* channel = GetIPCChannel();
if (!channel->CanSend()) {
@ -733,15 +730,14 @@ bool IToplevelProtocol::DestroySharedMemory(Shmem& shmem) {
void IToplevelProtocol::DeallocShmems() {
for (const auto& shmem : mShmemMap.Values()) {
Shmem::Dealloc(Shmem::PrivateIPDLCaller(), shmem);
Shmem::Dealloc(shmem);
}
mShmemMap.Clear();
}
bool IToplevelProtocol::ShmemCreated(const Message& aMsg) {
Shmem::id_t id;
RefPtr<Shmem::SharedMemory> rawmem(
Shmem::OpenExisting(Shmem::PrivateIPDLCaller(), aMsg, &id, true));
RefPtr<Shmem::SharedMemory> rawmem(Shmem::OpenExisting(aMsg, &id, true));
if (!rawmem) {
return false;
}
@ -763,7 +759,7 @@ bool IToplevelProtocol::ShmemDestroyed(const Message& aMsg) {
MOZ_ASSERT(mShmemMap.Contains(id),
"Attempting to remove an ID not in the shmem map");
mShmemMap.Remove(id);
Shmem::Dealloc(Shmem::PrivateIPDLCaller(), rawmem);
Shmem::Dealloc(rawmem);
}
return true;
}

View File

@ -210,7 +210,7 @@ static void Unprotect(SharedMemory* aSegment) {
// to touch the segment, it dies with SIGSEGV.
//
Shmem::Shmem(PrivateIPDLCaller, SharedMemory* aSegment, id_t aId)
Shmem::Shmem(SharedMemory* aSegment, id_t aId)
: mSegment(aSegment), mData(nullptr), mSize(0) {
MOZ_ASSERT(mSegment, "null segment");
MOZ_ASSERT(aId != 0, "invalid ID");
@ -259,7 +259,7 @@ void Shmem::AssertInvariants() const {
Unused << checkMappingBack;
}
void Shmem::RevokeRights(PrivateIPDLCaller) {
void Shmem::RevokeRights() {
AssertInvariants();
size_t pageSize = SharedMemory::SystemPageSize();
@ -276,8 +276,7 @@ void Shmem::RevokeRights(PrivateIPDLCaller) {
}
// static
already_AddRefed<Shmem::SharedMemory> Shmem::Alloc(PrivateIPDLCaller,
size_t aNBytes, bool aUnsafe,
already_AddRefed<Shmem::SharedMemory> Shmem::Alloc(size_t aNBytes, bool aUnsafe,
bool aProtect) {
NS_ASSERTION(aNBytes <= UINT32_MAX, "Will truncate shmem segment size!");
MOZ_ASSERT(!aProtect || !aUnsafe, "protect => !unsafe");
@ -312,8 +311,7 @@ already_AddRefed<Shmem::SharedMemory> Shmem::Alloc(PrivateIPDLCaller,
// static
already_AddRefed<Shmem::SharedMemory> Shmem::OpenExisting(
PrivateIPDLCaller, const IPC::Message& aDescriptor, id_t* aId,
bool aProtect) {
const IPC::Message& aDescriptor, id_t* aId, bool aProtect) {
size_t size;
size_t pageSize = SharedMemory::SystemPageSize();
// |2*pageSize| is for the front and back sentinels
@ -345,7 +343,7 @@ already_AddRefed<Shmem::SharedMemory> Shmem::OpenExisting(
}
// static
void Shmem::Dealloc(PrivateIPDLCaller, SharedMemory* aSegment) {
void Shmem::Dealloc(SharedMemory* aSegment) {
if (!aSegment) return;
size_t pageSize = SharedMemory::SystemPageSize();
@ -365,7 +363,7 @@ void Shmem::Dealloc(PrivateIPDLCaller, SharedMemory* aSegment) {
#else // !defined(DEBUG)
Shmem::Shmem(PrivateIPDLCaller, SharedMemory* aSegment, id_t aId)
Shmem::Shmem(SharedMemory* aSegment, id_t aId)
: mSegment(aSegment), mData(aSegment->memory()), mSize(0), mId(aId) {
mSize = static_cast<size_t>(*PtrToSize(mSegment));
MOZ_RELEASE_ASSERT(mSegment->Size() - sizeof(uint32_t) >= mSize,
@ -373,8 +371,7 @@ Shmem::Shmem(PrivateIPDLCaller, SharedMemory* aSegment, id_t aId)
}
// static
already_AddRefed<Shmem::SharedMemory> Shmem::Alloc(PrivateIPDLCaller,
size_t aNBytes,
already_AddRefed<Shmem::SharedMemory> Shmem::Alloc(size_t aNBytes,
bool /*unused*/,
bool /*unused*/) {
RefPtr<SharedMemory> segment = CreateSegment(aNBytes, sizeof(uint32_t));
@ -389,8 +386,7 @@ already_AddRefed<Shmem::SharedMemory> Shmem::Alloc(PrivateIPDLCaller,
// static
already_AddRefed<Shmem::SharedMemory> Shmem::OpenExisting(
PrivateIPDLCaller, const IPC::Message& aDescriptor, id_t* aId,
bool /*unused*/) {
const IPC::Message& aDescriptor, id_t* aId, bool /*unused*/) {
size_t size;
RefPtr<SharedMemory> segment =
ReadSegment(aDescriptor, aId, &size, sizeof(uint32_t));
@ -407,14 +403,11 @@ already_AddRefed<Shmem::SharedMemory> Shmem::OpenExisting(
}
// static
void Shmem::Dealloc(PrivateIPDLCaller, SharedMemory* aSegment) {
DestroySegment(aSegment);
}
void Shmem::Dealloc(SharedMemory* aSegment) { DestroySegment(aSegment); }
#endif // if defined(DEBUG)
UniquePtr<IPC::Message> Shmem::MkCreatedMessage(PrivateIPDLCaller,
int32_t routingId) {
UniquePtr<IPC::Message> Shmem::MkCreatedMessage(int32_t routingId) {
AssertInvariants();
auto msg = MakeUnique<ShmemCreated>(routingId, mId, mSize);
@ -427,8 +420,7 @@ UniquePtr<IPC::Message> Shmem::MkCreatedMessage(PrivateIPDLCaller,
return msg;
}
UniquePtr<IPC::Message> Shmem::MkDestroyedMessage(PrivateIPDLCaller,
int32_t routingId) {
UniquePtr<IPC::Message> Shmem::MkDestroyedMessage(int32_t routingId) {
AssertInvariants();
return MakeUnique<ShmemDestroyed>(routingId, mId);
}
@ -437,8 +429,8 @@ void IPDLParamTraits<Shmem>::Write(IPC::MessageWriter* aWriter,
IProtocol* aActor, Shmem&& aParam) {
WriteIPDLParam(aWriter, aActor, aParam.mId);
aParam.RevokeRights(Shmem::PrivateIPDLCaller());
aParam.forget(Shmem::PrivateIPDLCaller());
aParam.RevokeRights();
aParam.forget();
}
bool IPDLParamTraits<Shmem>::Read(IPC::MessageReader* aReader,
@ -450,7 +442,7 @@ bool IPDLParamTraits<Shmem>::Read(IPC::MessageReader* aReader,
Shmem::SharedMemory* rawmem = aActor->LookupSharedMemory(id);
if (rawmem) {
*aResult = Shmem(Shmem::PrivateIPDLCaller(), rawmem, id);
*aResult = Shmem(rawmem, id);
return true;
}
*aResult = Shmem();

View File

@ -60,36 +60,44 @@ class ShadowLayerForwarder;
namespace ipc {
class IProtocol;
class IToplevelProtocol;
#ifdef FUZZING
class ProtocolFuzzerHelper;
#endif
template <typename P>
struct IPDLParamTraits;
class Shmem final {
friend struct IPDLParamTraits<mozilla::ipc::Shmem>;
friend class mozilla::ipc::IProtocol;
friend class mozilla::ipc::IToplevelProtocol;
#ifdef DEBUG
// For ShadowLayerForwarder::CheckSurfaceDescriptor
friend class mozilla::layers::ShadowLayerForwarder;
#endif
#ifdef FUZZING
friend class ProtocolFuzzerHelper;
template <typename T>
friend void FuzzProtocol(T*, const uint8_t*, size_t,
const nsTArray<nsCString>&);
#endif
public:
typedef int32_t id_t;
// Low-level wrapper around platform shmem primitives.
typedef mozilla::ipc::SharedMemory SharedMemory;
// Shmem objects should only be constructed directly from SharedMemory
// objects by the Shmem implementation itself, or by a select few functions
// in ProtocolUtils.{h,cpp}. You should not need to add new instances of
// this token.
struct PrivateIPDLCaller {};
Shmem() : mSegment(nullptr), mData(nullptr), mSize(0), mId(0) {}
Shmem(const Shmem& aOther) = default;
Shmem(PrivateIPDLCaller, SharedMemory* aSegment, id_t aId);
~Shmem() {
// Shmem only holds a "weak ref" to the actual segment, which is
// owned by IPDL. So there's nothing interesting to be done here
forget(PrivateIPDLCaller());
forget();
}
Shmem& operator=(const Shmem& aRhs) = default;
@ -130,26 +138,29 @@ class Shmem final {
return {get<T>(), Size<T>()};
}
private:
// These shouldn't be used directly, use the IPDL interface instead.
id_t Id(PrivateIPDLCaller) const { return mId; }
SharedMemory* Segment(PrivateIPDLCaller) const { return mSegment; }
Shmem(SharedMemory* aSegment, id_t aId);
id_t Id() const { return mId; }
SharedMemory* Segment() const { return mSegment; }
#ifndef DEBUG
void RevokeRights(PrivateIPDLCaller) {}
void RevokeRights() {}
#else
void RevokeRights(PrivateIPDLCaller);
void RevokeRights();
#endif
void forget(PrivateIPDLCaller) {
void forget() {
mSegment = nullptr;
mData = nullptr;
mSize = 0;
mId = 0;
}
static already_AddRefed<Shmem::SharedMemory> Alloc(PrivateIPDLCaller,
size_t aNBytes,
static already_AddRefed<Shmem::SharedMemory> Alloc(size_t aNBytes,
bool aUnsafe,
bool aProtect = false);
@ -157,27 +168,23 @@ class Shmem final {
// contains enough information for the other process to map this segment in
// OpenExisting() below. Return a new message if successful (owned by the
// caller), nullptr if not.
UniquePtr<IPC::Message> MkCreatedMessage(PrivateIPDLCaller,
int32_t routingId);
UniquePtr<IPC::Message> MkCreatedMessage(int32_t routingId);
// Stop sharing this with another process. Return an IPC message that
// contains enough information for the other process to unmap this
// segment. Return a new message if successful (owned by the
// caller), nullptr if not.
UniquePtr<IPC::Message> MkDestroyedMessage(PrivateIPDLCaller,
int32_t routingId);
UniquePtr<IPC::Message> MkDestroyedMessage(int32_t routingId);
// Return a SharedMemory instance in this process using the descriptor shared
// to us by the process that created the underlying OS shmem resource. The
// contents of the descriptor depend on the type of SharedMemory that was
// passed to us.
static already_AddRefed<SharedMemory> OpenExisting(
PrivateIPDLCaller, const IPC::Message& aDescriptor, id_t* aId,
bool aProtect = false);
const IPC::Message& aDescriptor, id_t* aId, bool aProtect = false);
static void Dealloc(PrivateIPDLCaller, SharedMemory* aSegment);
static void Dealloc(SharedMemory* aSegment);
private:
template <typename T>
void AssertAligned() const {
if (0 != (mSize % sizeof(T))) MOZ_CRASH("shmem is not T-aligned");

View File

@ -72,13 +72,12 @@ void FuzzProtocol(T* aProtocol, const uint8_t* aData, size_t aSize,
if (shmem_size > aSize) {
break;
}
RefPtr<Shmem::SharedMemory> segment(
Shmem::Alloc(Shmem::PrivateIPDLCaller(), shmem_size, false));
RefPtr<Shmem::SharedMemory> segment(Shmem::Alloc(shmem_size, false));
if (!segment) {
break;
}
Shmem shmem(Shmem::PrivateIPDLCaller(), segment.get(), i + 1);
Shmem shmem(segment.get(), i + 1);
memcpy(shmem.get<uint8_t>(), aData, shmem_size);
ProtocolFuzzerHelper::AddShmemToProtocol(
aProtocol, segment.forget().take(), i + 1);
@ -99,7 +98,7 @@ void FuzzProtocol(T* aProtocol, const uint8_t* aData, size_t aSize,
}
for (uint32_t i = 0; i < num_shmems; i++) {
Shmem::SharedMemory* segment = aProtocol->LookupSharedMemory(i + 1);
Shmem::Dealloc(Shmem::PrivateIPDLCaller(), segment);
Shmem::Dealloc(segment);
ProtocolFuzzerHelper::RemoveShmemFromProtocol(aProtocol, i + 1);
}
}