Loading ipc/mscom/COMPtrHolder.h +36 −17 Original line number Diff line number Diff line Loading @@ -60,10 +60,10 @@ public: // This method is const because we need to call it during IPC write, where // we are passed as a const argument. At higher sandboxing levels we need to // save this artifact from the serialization process for later deletion. void PreserveStream(RefPtr<IStream>&& aPtr) const void PreserveStream(PreservedStreamPtr aPtr) const { MOZ_ASSERT(!mMarshaledStream); mMarshaledStream = ToPreservedStreamPtr(Move(aPtr)); mMarshaledStream = Move(aPtr); } PreservedStreamPtr GetPreservedStream() Loading @@ -76,6 +76,9 @@ public: COMPtrHolder(COMPtrHolder&& aOther) : mPtr(Move(aOther.mPtr)) #if defined(MOZ_CONTENT_SANDBOX) , mMarshaledStream(Move(aOther.mMarshaledStream)) #endif // defined(MOZ_CONTENT_SANDBOX) { } Loading @@ -89,12 +92,22 @@ public: ThisType& operator=(const ThisType& aOther) { Set(Move(aOther.mPtr)); #if defined(MOZ_CONTENT_SANDBOX) mMarshaledStream = Move(aOther.mMarshaledStream); #endif // defined(MOZ_CONTENT_SANDBOX) return *this; } ThisType& operator=(ThisType&& aOther) { Set(Move(aOther.mPtr)); #if defined(MOZ_CONTENT_SANDBOX) mMarshaledStream = Move(aOther.mMarshaledStream); #endif // defined(MOZ_CONTENT_SANDBOX) return *this; } Loading Loading @@ -131,7 +144,18 @@ struct ParamTraits<mozilla::mscom::COMPtrHolder<Interface, _IID>> static void Write(Message* aMsg, const paramType& aParam) { mozilla::mscom::ProxyStream proxyStream(_IID, aParam.Get()); #if defined(MOZ_CONTENT_SANDBOX) static const bool sIsStreamPreservationNeeded = XRE_IsParentProcess() && mozilla::GetEffectiveContentSandboxLevel() >= 3; #else const bool sIsStreamPreservationNeeded = false; #endif // defined(MOZ_CONTENT_SANDBOX) mozilla::mscom::ProxyStreamFlags flags = sIsStreamPreservationNeeded ? mozilla::mscom::ProxyStreamFlags::ePreservable : mozilla::mscom::ProxyStreamFlags::eDefault; mozilla::mscom::ProxyStream proxyStream(_IID, aParam.Get(), flags); int bufLen; const BYTE* buf = proxyStream.GetBuffer(bufLen); MOZ_ASSERT(buf || !bufLen); Loading @@ -141,9 +165,6 @@ struct ParamTraits<mozilla::mscom::COMPtrHolder<Interface, _IID>> } #if defined(MOZ_CONTENT_SANDBOX) if (XRE_IsParentProcess()) { static const bool sIsStreamPreservationNeeded = mozilla::GetEffectiveContentSandboxLevel() >= 3; if (sIsStreamPreservationNeeded) { /** * When we're sending a ProxyStream from parent to content and the Loading @@ -152,9 +173,7 @@ struct ParamTraits<mozilla::mscom::COMPtrHolder<Interface, _IID>> * marshaled proxy data here and later manually release it on content's * behalf. */ RefPtr<IStream> stream(proxyStream.GetStream()); aParam.PreserveStream(mozilla::Move(stream)); } aParam.PreserveStream(proxyStream.GetPreservedStream()); } #endif // defined(MOZ_CONTENT_SANDBOX) } Loading ipc/mscom/ProxyStream.cpp +31 −8 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ ProxyStream::ProxyStream() : mGlobalLockedBuf(nullptr) , mHGlobal(nullptr) , mBufSize(0) , mPreserveStream(false) { } Loading @@ -38,6 +39,7 @@ ProxyStream::ProxyStream(REFIID aIID, const BYTE* aInitBuf, , mGlobalLockedBuf(nullptr) , mHGlobal(nullptr) , mBufSize(aInitBufSize) , mPreserveStream(false) { #if defined(MOZ_CRASHREPORTER) NS_NAMED_LITERAL_CSTRING(kCrashReportKey, "ProxyStreamUnmarshalStatus"); Loading Loading @@ -163,6 +165,7 @@ ProxyStream::ProxyStream(ProxyStream&& aOther) : mGlobalLockedBuf(nullptr) , mHGlobal(nullptr) , mBufSize(0) , mPreserveStream(false) { *this = mozilla::Move(aOther); } Loading @@ -188,6 +191,8 @@ ProxyStream::operator=(ProxyStream&& aOther) aOther.mBufSize = 0; mUnmarshaledProxy = Move(aOther.mUnmarshaledProxy); mPreserveStream = aOther.mPreserveStream; return *this; } Loading @@ -198,6 +203,11 @@ ProxyStream::~ProxyStream() MOZ_ASSERT(!result && ::GetLastError() == NO_ERROR); // ::GlobalFree() is called implicitly when mStream is released } // If this assert triggers then we will be leaking a marshaled proxy! // Call GetPreservedStream to obtain a preservable stream and then save it // until the proxy is no longer needed. MOZ_ASSERT(!mPreserveStream); } const BYTE* Loading @@ -214,13 +224,20 @@ ProxyStream::GetBuffer(int& aReturnedBufSize) const return mGlobalLockedBuf; } RefPtr<IStream> ProxyStream::GetStream() const PreservedStreamPtr ProxyStream::GetPreservedStream() { MOZ_ASSERT(mStream); MOZ_ASSERT(mHGlobal); if (!mStream) { if (!mStream || !mPreserveStream) { return nullptr; } // Clone the stream so that the result has a distinct seek pointer. RefPtr<IStream> cloned; HRESULT hr = mStream->Clone(getter_AddRefs(cloned)); if (FAILED(hr)) { return nullptr; } Loading @@ -228,10 +245,13 @@ ProxyStream::GetStream() const // the stream to be pointing to the beginning of the marshal data. LARGE_INTEGER pos; pos.QuadPart = 0LL; DebugOnly<HRESULT> hr = mStream->Seek(pos, STREAM_SEEK_SET, nullptr); MOZ_ASSERT(SUCCEEDED(hr)); hr = cloned->Seek(pos, STREAM_SEEK_SET, nullptr); if (FAILED(hr)) { return nullptr; } return mStream; mPreserveStream = false; return ToPreservedStreamPtr(Move(cloned)); } bool Loading @@ -256,10 +276,12 @@ ProxyStream::GetInterface(void** aOutInterface) return true; } ProxyStream::ProxyStream(REFIID aIID, IUnknown* aObject) ProxyStream::ProxyStream(REFIID aIID, IUnknown* aObject, ProxyStreamFlags aFlags) : mGlobalLockedBuf(nullptr) , mHGlobal(nullptr) , mBufSize(0) , mPreserveStream(aFlags & ProxyStreamFlags::ePreservable) { if (!aObject) { return; Loading @@ -268,6 +290,7 @@ ProxyStream::ProxyStream(REFIID aIID, IUnknown* aObject) RefPtr<IStream> stream; HGLOBAL hglobal = NULL; int streamSize = 0; DWORD mshlFlags = mPreserveStream ? MSHLFLAGS_TABLESTRONG : MSHLFLAGS_NORMAL; HRESULT createStreamResult = S_OK; HRESULT marshalResult = S_OK; Loading @@ -282,7 +305,7 @@ ProxyStream::ProxyStream(REFIID aIID, IUnknown* aObject) } marshalResult = ::CoMarshalInterface(stream, aIID, aObject, MSHCTX_LOCAL, nullptr, MSHLFLAGS_NORMAL); nullptr, mshlFlags); if (FAILED(marshalResult)) { return; } Loading ipc/mscom/ProxyStream.h +16 −2 Original line number Diff line number Diff line Loading @@ -11,16 +11,28 @@ #include "mozilla/mscom/Ptr.h" #include "mozilla/RefPtr.h" #include "mozilla/TypedEnumBits.h" #include "mozilla/UniquePtr.h" namespace mozilla { namespace mscom { enum class ProxyStreamFlags : uint32_t { eDefault = 0, // When ePreservable is set on a ProxyStream, its caller *must* call // GetPreservableStream() before the ProxyStream is destroyed. ePreservable = 1 }; MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(ProxyStreamFlags); class ProxyStream final { public: ProxyStream(); ProxyStream(REFIID aIID, IUnknown* aObject); ProxyStream(REFIID aIID, IUnknown* aObject, ProxyStreamFlags aFlags = ProxyStreamFlags::eDefault); ProxyStream(REFIID aIID, const BYTE* aInitBuf, const int aInitBufSize); ~ProxyStream(); Loading @@ -39,7 +51,8 @@ public: bool GetInterface(void** aOutInterface); const BYTE* GetBuffer(int& aReturnedBufSize) const; RefPtr<IStream> GetStream() const; PreservedStreamPtr GetPreservedStream(); bool operator==(const ProxyStream& aOther) const { Loading @@ -56,6 +69,7 @@ private: HGLOBAL mHGlobal; int mBufSize; ProxyUniquePtr<IUnknown> mUnmarshaledProxy; bool mPreserveStream; }; } // namespace mscom Loading ipc/mscom/Ptr.h +6 −0 Original line number Diff line number Diff line Loading @@ -310,6 +310,12 @@ ToPreservedStreamPtr(RefPtr<IStream>&& aStream) return PreservedStreamPtr(aStream.forget().take()); } inline PreservedStreamPtr ToPreservedStreamPtr(already_AddRefed<IStream>& aStream) { return PreservedStreamPtr(aStream.take()); } template <typename T, typename Deleter> inline detail::UniquePtrGetterAddRefs<T, Deleter> getter_AddRefs(UniquePtr<T, Deleter>& aSmartPtr) Loading Loading
ipc/mscom/COMPtrHolder.h +36 −17 Original line number Diff line number Diff line Loading @@ -60,10 +60,10 @@ public: // This method is const because we need to call it during IPC write, where // we are passed as a const argument. At higher sandboxing levels we need to // save this artifact from the serialization process for later deletion. void PreserveStream(RefPtr<IStream>&& aPtr) const void PreserveStream(PreservedStreamPtr aPtr) const { MOZ_ASSERT(!mMarshaledStream); mMarshaledStream = ToPreservedStreamPtr(Move(aPtr)); mMarshaledStream = Move(aPtr); } PreservedStreamPtr GetPreservedStream() Loading @@ -76,6 +76,9 @@ public: COMPtrHolder(COMPtrHolder&& aOther) : mPtr(Move(aOther.mPtr)) #if defined(MOZ_CONTENT_SANDBOX) , mMarshaledStream(Move(aOther.mMarshaledStream)) #endif // defined(MOZ_CONTENT_SANDBOX) { } Loading @@ -89,12 +92,22 @@ public: ThisType& operator=(const ThisType& aOther) { Set(Move(aOther.mPtr)); #if defined(MOZ_CONTENT_SANDBOX) mMarshaledStream = Move(aOther.mMarshaledStream); #endif // defined(MOZ_CONTENT_SANDBOX) return *this; } ThisType& operator=(ThisType&& aOther) { Set(Move(aOther.mPtr)); #if defined(MOZ_CONTENT_SANDBOX) mMarshaledStream = Move(aOther.mMarshaledStream); #endif // defined(MOZ_CONTENT_SANDBOX) return *this; } Loading Loading @@ -131,7 +144,18 @@ struct ParamTraits<mozilla::mscom::COMPtrHolder<Interface, _IID>> static void Write(Message* aMsg, const paramType& aParam) { mozilla::mscom::ProxyStream proxyStream(_IID, aParam.Get()); #if defined(MOZ_CONTENT_SANDBOX) static const bool sIsStreamPreservationNeeded = XRE_IsParentProcess() && mozilla::GetEffectiveContentSandboxLevel() >= 3; #else const bool sIsStreamPreservationNeeded = false; #endif // defined(MOZ_CONTENT_SANDBOX) mozilla::mscom::ProxyStreamFlags flags = sIsStreamPreservationNeeded ? mozilla::mscom::ProxyStreamFlags::ePreservable : mozilla::mscom::ProxyStreamFlags::eDefault; mozilla::mscom::ProxyStream proxyStream(_IID, aParam.Get(), flags); int bufLen; const BYTE* buf = proxyStream.GetBuffer(bufLen); MOZ_ASSERT(buf || !bufLen); Loading @@ -141,9 +165,6 @@ struct ParamTraits<mozilla::mscom::COMPtrHolder<Interface, _IID>> } #if defined(MOZ_CONTENT_SANDBOX) if (XRE_IsParentProcess()) { static const bool sIsStreamPreservationNeeded = mozilla::GetEffectiveContentSandboxLevel() >= 3; if (sIsStreamPreservationNeeded) { /** * When we're sending a ProxyStream from parent to content and the Loading @@ -152,9 +173,7 @@ struct ParamTraits<mozilla::mscom::COMPtrHolder<Interface, _IID>> * marshaled proxy data here and later manually release it on content's * behalf. */ RefPtr<IStream> stream(proxyStream.GetStream()); aParam.PreserveStream(mozilla::Move(stream)); } aParam.PreserveStream(proxyStream.GetPreservedStream()); } #endif // defined(MOZ_CONTENT_SANDBOX) } Loading
ipc/mscom/ProxyStream.cpp +31 −8 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ ProxyStream::ProxyStream() : mGlobalLockedBuf(nullptr) , mHGlobal(nullptr) , mBufSize(0) , mPreserveStream(false) { } Loading @@ -38,6 +39,7 @@ ProxyStream::ProxyStream(REFIID aIID, const BYTE* aInitBuf, , mGlobalLockedBuf(nullptr) , mHGlobal(nullptr) , mBufSize(aInitBufSize) , mPreserveStream(false) { #if defined(MOZ_CRASHREPORTER) NS_NAMED_LITERAL_CSTRING(kCrashReportKey, "ProxyStreamUnmarshalStatus"); Loading Loading @@ -163,6 +165,7 @@ ProxyStream::ProxyStream(ProxyStream&& aOther) : mGlobalLockedBuf(nullptr) , mHGlobal(nullptr) , mBufSize(0) , mPreserveStream(false) { *this = mozilla::Move(aOther); } Loading @@ -188,6 +191,8 @@ ProxyStream::operator=(ProxyStream&& aOther) aOther.mBufSize = 0; mUnmarshaledProxy = Move(aOther.mUnmarshaledProxy); mPreserveStream = aOther.mPreserveStream; return *this; } Loading @@ -198,6 +203,11 @@ ProxyStream::~ProxyStream() MOZ_ASSERT(!result && ::GetLastError() == NO_ERROR); // ::GlobalFree() is called implicitly when mStream is released } // If this assert triggers then we will be leaking a marshaled proxy! // Call GetPreservedStream to obtain a preservable stream and then save it // until the proxy is no longer needed. MOZ_ASSERT(!mPreserveStream); } const BYTE* Loading @@ -214,13 +224,20 @@ ProxyStream::GetBuffer(int& aReturnedBufSize) const return mGlobalLockedBuf; } RefPtr<IStream> ProxyStream::GetStream() const PreservedStreamPtr ProxyStream::GetPreservedStream() { MOZ_ASSERT(mStream); MOZ_ASSERT(mHGlobal); if (!mStream) { if (!mStream || !mPreserveStream) { return nullptr; } // Clone the stream so that the result has a distinct seek pointer. RefPtr<IStream> cloned; HRESULT hr = mStream->Clone(getter_AddRefs(cloned)); if (FAILED(hr)) { return nullptr; } Loading @@ -228,10 +245,13 @@ ProxyStream::GetStream() const // the stream to be pointing to the beginning of the marshal data. LARGE_INTEGER pos; pos.QuadPart = 0LL; DebugOnly<HRESULT> hr = mStream->Seek(pos, STREAM_SEEK_SET, nullptr); MOZ_ASSERT(SUCCEEDED(hr)); hr = cloned->Seek(pos, STREAM_SEEK_SET, nullptr); if (FAILED(hr)) { return nullptr; } return mStream; mPreserveStream = false; return ToPreservedStreamPtr(Move(cloned)); } bool Loading @@ -256,10 +276,12 @@ ProxyStream::GetInterface(void** aOutInterface) return true; } ProxyStream::ProxyStream(REFIID aIID, IUnknown* aObject) ProxyStream::ProxyStream(REFIID aIID, IUnknown* aObject, ProxyStreamFlags aFlags) : mGlobalLockedBuf(nullptr) , mHGlobal(nullptr) , mBufSize(0) , mPreserveStream(aFlags & ProxyStreamFlags::ePreservable) { if (!aObject) { return; Loading @@ -268,6 +290,7 @@ ProxyStream::ProxyStream(REFIID aIID, IUnknown* aObject) RefPtr<IStream> stream; HGLOBAL hglobal = NULL; int streamSize = 0; DWORD mshlFlags = mPreserveStream ? MSHLFLAGS_TABLESTRONG : MSHLFLAGS_NORMAL; HRESULT createStreamResult = S_OK; HRESULT marshalResult = S_OK; Loading @@ -282,7 +305,7 @@ ProxyStream::ProxyStream(REFIID aIID, IUnknown* aObject) } marshalResult = ::CoMarshalInterface(stream, aIID, aObject, MSHCTX_LOCAL, nullptr, MSHLFLAGS_NORMAL); nullptr, mshlFlags); if (FAILED(marshalResult)) { return; } Loading
ipc/mscom/ProxyStream.h +16 −2 Original line number Diff line number Diff line Loading @@ -11,16 +11,28 @@ #include "mozilla/mscom/Ptr.h" #include "mozilla/RefPtr.h" #include "mozilla/TypedEnumBits.h" #include "mozilla/UniquePtr.h" namespace mozilla { namespace mscom { enum class ProxyStreamFlags : uint32_t { eDefault = 0, // When ePreservable is set on a ProxyStream, its caller *must* call // GetPreservableStream() before the ProxyStream is destroyed. ePreservable = 1 }; MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(ProxyStreamFlags); class ProxyStream final { public: ProxyStream(); ProxyStream(REFIID aIID, IUnknown* aObject); ProxyStream(REFIID aIID, IUnknown* aObject, ProxyStreamFlags aFlags = ProxyStreamFlags::eDefault); ProxyStream(REFIID aIID, const BYTE* aInitBuf, const int aInitBufSize); ~ProxyStream(); Loading @@ -39,7 +51,8 @@ public: bool GetInterface(void** aOutInterface); const BYTE* GetBuffer(int& aReturnedBufSize) const; RefPtr<IStream> GetStream() const; PreservedStreamPtr GetPreservedStream(); bool operator==(const ProxyStream& aOther) const { Loading @@ -56,6 +69,7 @@ private: HGLOBAL mHGlobal; int mBufSize; ProxyUniquePtr<IUnknown> mUnmarshaledProxy; bool mPreserveStream; }; } // namespace mscom Loading
ipc/mscom/Ptr.h +6 −0 Original line number Diff line number Diff line Loading @@ -310,6 +310,12 @@ ToPreservedStreamPtr(RefPtr<IStream>&& aStream) return PreservedStreamPtr(aStream.forget().take()); } inline PreservedStreamPtr ToPreservedStreamPtr(already_AddRefed<IStream>& aStream) { return PreservedStreamPtr(aStream.take()); } template <typename T, typename Deleter> inline detail::UniquePtrGetterAddRefs<T, Deleter> getter_AddRefs(UniquePtr<T, Deleter>& aSmartPtr) Loading