Bug 813758 - Need additional security checks for the geolocation permission. r=sicking a=blocking-basecamp
authorDoug Turner <dougt@dougt.org>
Wed, 02 Jan 2013 13:21:37 -0800
changeset 126395 8c3bd23a156754db45d31b572d56d3a8d9f381ff
parent 126394 a812ef63de87c9e3b22f125c448f997062f3fb1d
child 126396 7a7bf00cd969a4f15dee94b7796c81a5276dfda4
push id2151
push userlsblakk@mozilla.com
push dateTue, 19 Feb 2013 18:06:57 +0000
treeherdermozilla-beta@4952e88741ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssicking, blocking-basecamp
bugs813758
milestone20.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 813758 - Need additional security checks for the geolocation permission. r=sicking a=blocking-basecamp
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
dom/src/geolocation/nsGeolocation.cpp
dom/src/geolocation/nsGeolocation.h
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -1938,18 +1938,59 @@ ContentParent::RecvAsyncMessage(const ns
 
     ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
                         aMsg, false, &cloneData, nullptr, nullptr);
   }
   return true;
 }
 
 bool
-ContentParent::RecvAddGeolocationListener()
+ContentParent::RecvAddGeolocationListener(const IPC::Principal& aPrincipal)
 {
+#ifdef MOZ_PERMISSIONS
+
+  nsIPrincipal* principal = aPrincipal;
+  uint32_t principalAppId;
+  nsresult rv = principal->GetAppId(&principalAppId);
+  if (NS_FAILED(rv)) {
+    return true;
+  }
+
+  bool found = false;
+  const InfallibleTArray<PBrowserParent*>& browsers = ManagedPBrowserParent();
+  for (uint32_t i = 0; i < browsers.Length(); ++i) {
+  
+      TabParent* tab = static_cast<TabParent*>(browsers[i]);
+      nsCOMPtr<mozIApplication> app = tab->GetOwnOrContainingApp();
+      uint32_t appId;
+      app->GetLocalId(&appId);
+      if (appId == principalAppId) {
+          found = true;
+          break;
+      }
+  }
+
+  if (!found) {
+    return true;
+  }
+
+  // We need to ensure that this permission has been set.
+  // If it hasn't, just noop
+  nsCOMPtr<nsIPermissionManager> pm = do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
+  if (!pm) {
+    return false;
+  }
+  uint32_t permission = nsIPermissionManager::UNKNOWN_ACTION;
+  rv = pm->TestPermissionFromPrincipal(principal, "geolocation", &permission);
+  if (NS_FAILED(rv) || permission != nsIPermissionManager::ALLOW_ACTION) {
+    KillHard();
+    return true;
+  }
+#endif
+
   if (mGeolocationWatchID == -1) {
     nsCOMPtr<nsIDOMGeoGeolocation> geo = do_GetService("@mozilla.org/geolocation;1");
     if (!geo) {
       return true;
     }
     jsval dummy = JSVAL_VOID;
     geo->WatchPosition(this, nullptr, dummy, nullptr, &mGeolocationWatchID);
   }
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -21,16 +21,17 @@
 #include "nsIThreadInternal.h"
 #include "nsNetUtil.h"
 #include "nsIPermissionManager.h"
 #include "nsIDOMGeoPositionCallback.h"
 #include "nsIMemoryReporter.h"
 #include "nsCOMArray.h"
 #include "nsDataHashtable.h"
 #include "nsHashKeys.h"
+#include "PermissionMessageUtils.h"
 
 #define CHILD_PROCESS_SHUTDOWN_MESSAGE NS_LITERAL_STRING("child-process-shutdown")
 
 #define CONTENT_PARENT_UNKNOWN_CHILD_ID -1
 
 class mozIApplication;
 class nsConsoleService;
 class nsIDOMBlob;
@@ -295,17 +296,17 @@ private:
     virtual bool RecvLoadURIExternal(const URIParams& uri);
 
     virtual bool RecvSyncMessage(const nsString& aMsg,
                                  const ClonedMessageData& aData,
                                  InfallibleTArray<nsString>* aRetvals);
     virtual bool RecvAsyncMessage(const nsString& aMsg,
                                   const ClonedMessageData& aData);
 
-    virtual bool RecvAddGeolocationListener();
+    virtual bool RecvAddGeolocationListener(const IPC::Principal& aPrincipal);
     virtual bool RecvRemoveGeolocationListener();
     virtual bool RecvSetGeolocationHigherAccuracy(const bool& aEnable);
 
     virtual bool RecvConsoleMessage(const nsString& aMessage);
     virtual bool RecvScriptError(const nsString& aMessage,
                                  const nsString& aSourceName,
                                  const nsString& aSourceLine,
                                  const uint32_t& aLineNumber,
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -18,29 +18,30 @@ include protocol PMemoryReportRequest;
 include protocol PNecko;
 include protocol PSms;
 include protocol PStorage;
 include protocol PTestShell;
 include DOMTypes;
 include URIParams;
 
 include "mozilla/chrome/RegistryMessageUtils.h";
+include "mozilla/dom/PermissionMessageUtils.h";
 include "mozilla/dom/TabMessageUtils.h";
 include "mozilla/layout/RenderFrameUtils.h";
 include "mozilla/net/NeckoMessageUtils.h";
-
 include "nsGeoPositionIPCSerialiser.h";
 
 using GeoPosition;
 using PrefTuple;
 
 using ChromePackage;
 using ResourceMapping;
 using OverrideMapping;
 using IPC::Permission;
+using IPC::Principal;
 using mozilla::null_t;
 using mozilla::void_t;
 using mozilla::dom::AudioChannelType;
 using mozilla::dom::NativeThreadId;
 using mozilla::layout::ScrollingBehavior;
 using gfxIntSize;
 
 namespace mozilla {
@@ -390,17 +391,17 @@ parent:
                           bool textClickable,
                           nsString cookie,
                           nsString name);
 
     PExternalHelperApp(OptionalURIParams uri, nsCString aMimeContentType,
                        nsCString aContentDisposition, bool aForceSave,
                        int64_t aContentLength, OptionalURIParams aReferrer);
 
-    AddGeolocationListener();
+    AddGeolocationListener(Principal principal);
     RemoveGeolocationListener();
     SetGeolocationHigherAccuracy(bool enable);
 
     ConsoleMessage(nsString message);
     ScriptError(nsString message, nsString sourceName, nsString sourceLine,
                 uint32_t lineNumber, uint32_t colNumber, uint32_t flags,
                 nsCString category); 
 
--- a/dom/src/geolocation/nsGeolocation.cpp
+++ b/dom/src/geolocation/nsGeolocation.cpp
@@ -419,17 +419,17 @@ nsGeolocationRequest::Allow()
   nsCOMPtr<nsIDOMWindow> window;
   GetWindow(getter_AddRefs(window));
   nsCOMPtr<nsIWebNavigation> webNav = do_GetInterface(window);
   nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(webNav);
   bool isPrivate = loadContext && loadContext->UsePrivateBrowsing();
 
   // Kick off the geo device, if it isn't already running
   nsRefPtr<nsGeolocationService> gs = nsGeolocationService::GetGeolocationService();
-  nsresult rv = gs->StartDevice(isPrivate);
+  nsresult rv = gs->StartDevice(GetPrincipal(), isPrivate);
 
   if (NS_FAILED(rv)) {
     // Location provider error
     NotifyError(nsIDOMGeoPositionError::POSITION_UNAVAILABLE);
     return NS_OK;
   }
 
   nsCOMPtr<nsIDOMGeoPosition> lastPosition = gs->GetCachedPosition();
@@ -536,16 +536,25 @@ nsGeolocationRequest::SendLocation(nsIDO
   JSContext* cx;
   stack->Pop(&cx);
 
   if (mIsWatchPositionRequest) {
     SetTimeoutTimer();
   }
 }
 
+nsIPrincipal*
+nsGeolocationRequest::GetPrincipal()
+{
+  if (!mLocator) {
+    return nullptr;
+  }
+  return mLocator->GetPrincipal();
+}
+
 bool
 nsGeolocationRequest::Update(nsIDOMGeoPosition* aPosition, bool aIsBetter)
 {
   if (!mAllowed) {
     return false;
   }
   // Only dispatch callbacks if this is the first position for this request, or
   // if the accuracy is as good or improving.
@@ -947,30 +956,30 @@ nsGeolocationService::SetCachedPosition(
 
 nsIDOMGeoPosition*
 nsGeolocationService::GetCachedPosition()
 {
   return mLastPosition;
 }
 
 nsresult
-nsGeolocationService::StartDevice(bool aRequestPrivate)
+nsGeolocationService::StartDevice(nsIPrincipal *aPrincipal, bool aRequestPrivate)
 {
   if (!sGeoEnabled || sGeoInitPending) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   // we do not want to keep the geolocation devices online
   // indefinitely.  Close them down after a reasonable period of
   // inactivivity
   SetDisconnectTimer();
 
   if (XRE_GetProcessType() == GeckoProcessType_Content) {
     ContentChild* cpc = ContentChild::GetSingleton();
-    cpc->SendAddGeolocationListener();
+    cpc->SendAddGeolocationListener(IPC::Principal(aPrincipal));
     return NS_OK;
   }
 
   // Start them up!
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (!obs) {
     return NS_ERROR_FAILURE;
   }
--- a/dom/src/geolocation/nsGeolocation.h
+++ b/dom/src/geolocation/nsGeolocation.h
@@ -62,16 +62,17 @@ class nsGeolocationRequest
   // isBetter: the accuracy is as good or better than the previous position. 
   bool Update(nsIDOMGeoPosition* aPosition, bool aIsBetter);
 
   void SendLocation(nsIDOMGeoPosition* location);
   void MarkCleared();
   bool IsActive() {return !mCleared;}
   bool Allowed() {return mAllowed;}
   void SetTimeoutTimer();
+  nsIPrincipal* GetPrincipal();
 
   ~nsGeolocationRequest();
 
   bool Recv__delete__(const bool& allow);
   void IPDLRelease() { Release(); }
 
   int32_t WatchId() { return mWatchId; }
 
@@ -120,17 +121,17 @@ public:
   void AddLocator(nsGeolocation* locator);
   void RemoveLocator(nsGeolocation* locator);
 
   void SetCachedPosition(nsIDOMGeoPosition* aPosition);
   nsIDOMGeoPosition* GetCachedPosition();
   PRBool IsBetterPosition(nsIDOMGeoPosition *aSomewhere);
 
   // Find and startup a geolocation device (gps, nmea, etc.)
-  nsresult StartDevice(bool aRequestPrivate);
+  nsresult StartDevice(nsIPrincipal* aPrincipal, bool aRequestPrivate);
 
   // Stop the started geolocation device (gps, nmea, etc.)
   void     StopDevice();
 
   // create, or reinitalize the callback timer
   void     SetDisconnectTimer();
 
   // request higher accuracy, if possible