From 53f4153710684b328ff23c6b0f54a0b93bb376c4 Mon Sep 17 00:00:00 2001 From: "Kearwood (Kip) Gilbert" Date: Thu, 24 Nov 2016 11:50:43 -0800 Subject: [PATCH] Bug 1315543 - Eliminate UAF in Navigator::NotifyVRDisplaysUpdated,r=dmu --- dom/base/Navigator.cpp | 4 ++-- dom/vr/VRDisplay.cpp | 4 ++-- dom/vr/VRDisplay.h | 2 +- gfx/vr/ipc/VRManagerChild.cpp | 17 +++++++++++++---- gfx/vr/ipc/VRManagerChild.h | 4 ++-- 5 files changed, 20 insertions(+), 11 deletions(-) diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index 80c840e4e34b..d175e19880da 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -1647,9 +1647,9 @@ Navigator::GetVRDisplays(ErrorResult& aRv) return nullptr; } - // We pass ourself to RefreshVRDisplays, so NotifyVRDisplaysUpdated will + // We pass mWindow's id to RefreshVRDisplays, so NotifyVRDisplaysUpdated will // be called asynchronously, resolving the promises in mVRGetDisplaysPromises. - if (!VRDisplay::RefreshVRDisplays(this)) { + if (!VRDisplay::RefreshVRDisplays(win->WindowID())) { p->MaybeReject(NS_ERROR_FAILURE); return p.forget(); } diff --git a/dom/vr/VRDisplay.cpp b/dom/vr/VRDisplay.cpp index 72219f0a757d..80922422f9b7 100644 --- a/dom/vr/VRDisplay.cpp +++ b/dom/vr/VRDisplay.cpp @@ -77,10 +77,10 @@ VRDisplayCapabilities::MaxLayers() const } /*static*/ bool -VRDisplay::RefreshVRDisplays(dom::Navigator* aNavigator) +VRDisplay::RefreshVRDisplays(uint64_t aWindowId) { gfx::VRManagerChild* vm = gfx::VRManagerChild::Get(); - return vm && vm->RefreshVRDisplaysWithCallback(aNavigator); + return vm && vm->RefreshVRDisplaysWithCallback(aWindowId); } /*static*/ void diff --git a/dom/vr/VRDisplay.h b/dom/vr/VRDisplay.h index 378efc98ed1d..d40d3d8aca22 100644 --- a/dom/vr/VRDisplay.h +++ b/dom/vr/VRDisplay.h @@ -282,7 +282,7 @@ public: uint32_t DisplayId() const { return mDisplayId; } void GetDisplayName(nsAString& aDisplayName) const { aDisplayName = mDisplayName; } - static bool RefreshVRDisplays(dom::Navigator* aNavigator); + static bool RefreshVRDisplays(uint64_t aWindowId); static void UpdateVRDisplays(nsTArray >& aDisplays, nsPIDOMWindowInner* aWindow); diff --git a/gfx/vr/ipc/VRManagerChild.cpp b/gfx/vr/ipc/VRManagerChild.cpp index f4732b9a071e..726ca5fb64b6 100644 --- a/gfx/vr/ipc/VRManagerChild.cpp +++ b/gfx/vr/ipc/VRManagerChild.cpp @@ -269,13 +269,22 @@ mozilla::ipc::IPCResult VRManagerChild::RecvUpdateDisplayInfo(nsTArray&& aDisplayUpdates) { UpdateDisplayInfo(aDisplayUpdates); - for (auto& nav : mNavigatorCallbacks) { + for (auto& windowId : mNavigatorCallbacks) { /** We must call NotifyVRDisplaysUpdated for every - * Navigator in mNavigatorCallbacks to ensure that + * window's Navigator in mNavigatorCallbacks to ensure that * the promise returned by Navigator.GetVRDevices * can resolve. This must happen even if no changes * to VRDisplays have been detected here. */ + nsGlobalWindow* window = nsGlobalWindow::GetInnerWindowWithId(windowId); + if (!window) { + continue; + } + ErrorResult result; + dom::Navigator* nav = window->GetNavigator(result); + if (NS_WARN_IF(result.Failed())) { + continue; + } nav->NotifyVRDisplaysUpdated(); } mNavigatorCallbacks.Clear(); @@ -300,11 +309,11 @@ VRManagerChild::GetVRDisplays(nsTArray>& aDisplays) } bool -VRManagerChild::RefreshVRDisplaysWithCallback(dom::Navigator* aNavigator) +VRManagerChild::RefreshVRDisplaysWithCallback(uint64_t aWindowId) { bool success = SendRefreshDisplays(); if (success) { - mNavigatorCallbacks.AppendElement(aNavigator); + mNavigatorCallbacks.AppendElement(aWindowId); } return success; } diff --git a/gfx/vr/ipc/VRManagerChild.h b/gfx/vr/ipc/VRManagerChild.h index a3b6d0b85a6c..dbe9139be11b 100644 --- a/gfx/vr/ipc/VRManagerChild.h +++ b/gfx/vr/ipc/VRManagerChild.h @@ -49,7 +49,7 @@ public: int GetInputFrameID(); bool GetVRDisplays(nsTArray >& aDisplays); - bool RefreshVRDisplaysWithCallback(dom::Navigator* aNavigator); + bool RefreshVRDisplaysWithCallback(uint64_t aWindowId); static void InitSameProcess(); static void InitWithGPUProcess(Endpoint&& aEndpoint); @@ -152,7 +152,7 @@ private: nsTArray > mDisplays; bool mDisplaysInitialized; - nsTArray mNavigatorCallbacks; + nsTArray mNavigatorCallbacks; dom::GamepadManager* mGamepadManager; int32_t mInputFrameID;