diff --git a/docshell/base/LoadContext.cpp b/docshell/base/LoadContext.cpp index 6861ecac3d61..7bf55a466590 100644 --- a/docshell/base/LoadContext.cpp +++ b/docshell/base/LoadContext.cpp @@ -8,22 +8,12 @@ #include "nsIScriptSecurityManager.h" #include "nsServiceManagerUtils.h" #include "nsContentUtils.h" +#include "mozIApplication.h" namespace mozilla { NS_IMPL_ISUPPORTS1(LoadContext, nsILoadContext); -LoadContext::LoadContext(const IPC::SerializedLoadContext& aToCopy, - nsIDOMElement* aTopFrameElemenet) - : mIsNotNull(aToCopy.mIsNotNull) - , mIsContent(aToCopy.mIsContent) - , mUsePrivateBrowsing(aToCopy.mUsePrivateBrowsing) - , mIsInBrowserElement(aToCopy.mIsInBrowserElement) - , mAppId(aToCopy.mAppId) - , mTopFrameElement(do_GetWeakReference(aTopFrameElemenet)) -{} - - //----------------------------------------------------------------------------- // LoadContext::nsILoadContext //----------------------------------------------------------------------------- diff --git a/docshell/base/LoadContext.h b/docshell/base/LoadContext.h index 29961ca44ac7..c1ba521b9bbd 100644 --- a/docshell/base/LoadContext.h +++ b/docshell/base/LoadContext.h @@ -10,6 +10,9 @@ #include "SerializedLoadContext.h" #include "mozilla/Attributes.h" #include "nsWeakReference.h" +#include "nsIDOMElement.h" + +class mozIApplication; namespace mozilla { @@ -29,17 +32,19 @@ public: NS_DECL_ISUPPORTS NS_DECL_NSILOADCONTEXT - LoadContext(const IPC::SerializedLoadContext& aToCopy) + // AppId/inBrowser arguments override those in SerializedLoadContext provided + // by child process. + LoadContext(const IPC::SerializedLoadContext& aToCopy, + nsIDOMElement* aTopFrameElement, + uint32_t aAppId, bool aInBrowser) : mIsNotNull(aToCopy.mIsNotNull) , mIsContent(aToCopy.mIsContent) , mUsePrivateBrowsing(aToCopy.mUsePrivateBrowsing) - , mIsInBrowserElement(aToCopy.mIsInBrowserElement) - , mAppId(aToCopy.mAppId) + , mIsInBrowserElement(aInBrowser) + , mAppId(aAppId) + , mTopFrameElement(do_GetWeakReference(aTopFrameElement)) {} - LoadContext(const IPC::SerializedLoadContext& aToCopy, - nsIDOMElement* aTopFrameElemenet); - private: bool mIsNotNull; bool mIsContent; diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl index e1ae01bf0119..5526967a5128 100644 --- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -214,8 +214,6 @@ parent: * URI of the manifest to fetch, the application cache group ID * @param documentURI * URI of the document that referred the manifest - * @param clientID - * The group cache version identifier to use * @param stickDocument * True if the update was initiated by a document load that referred * a manifest. @@ -233,7 +231,6 @@ parent: * has already been cached (stickDocument=false). */ POfflineCacheUpdate(URIParams manifestURI, URIParams documentURI, - bool isInBrowserElement, uint32_t appId, bool stickDocument); sync PIndexedDB(nsCString asciiOrigin) diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 55e8347756b9..7ebd1a3430c3 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -1570,8 +1570,6 @@ TabChild::RecvActivateFrameEvent(const nsString& aType, const bool& capture) POfflineCacheUpdateChild* TabChild::AllocPOfflineCacheUpdate(const URIParams& manifestURI, const URIParams& documentURI, - const bool& isInBrowserElement, - const uint32_t& appId, const bool& stickDocument) { NS_RUNTIMEABORT("unused"); diff --git a/dom/ipc/TabChild.h b/dom/ipc/TabChild.h index bc9e06d0fc11..e44ae9aa1835 100644 --- a/dom/ipc/TabChild.h +++ b/dom/ipc/TabChild.h @@ -277,8 +277,6 @@ public: virtual POfflineCacheUpdateChild* AllocPOfflineCacheUpdate( const URIParams& manifestURI, const URIParams& documentURI, - const bool& isInBrowserElement, - const uint32_t& appId, const bool& stickDocument); virtual bool DeallocPOfflineCacheUpdate(POfflineCacheUpdateChild* offlineCacheUpdate); diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index 492c14df6ee4..3a0c2265c100 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -1128,15 +1128,13 @@ TabParent::DeallocPRenderFrame(PRenderFrameParent* aFrame) mozilla::docshell::POfflineCacheUpdateParent* TabParent::AllocPOfflineCacheUpdate(const URIParams& aManifestURI, const URIParams& aDocumentURI, - const bool& isInBrowserElement, - const uint32_t& appId, const bool& stickDocument) { nsRefPtr update = - new mozilla::docshell::OfflineCacheUpdateParent(); + new mozilla::docshell::OfflineCacheUpdateParent(OwnOrContainingAppId(), + IsBrowserElement()); - nsresult rv = update->Schedule(aManifestURI, aDocumentURI, - isInBrowserElement, appId, stickDocument); + nsresult rv = update->Schedule(aManifestURI, aDocumentURI, stickDocument); if (NS_FAILED(rv)) return nullptr; diff --git a/dom/ipc/TabParent.h b/dom/ipc/TabParent.h index c44528fc8f70..bd640e3c9b7d 100644 --- a/dom/ipc/TabParent.h +++ b/dom/ipc/TabParent.h @@ -191,8 +191,6 @@ public: virtual POfflineCacheUpdateParent* AllocPOfflineCacheUpdate( const URIParams& aManifestURI, const URIParams& aDocumentURI, - const bool& isInBrowserElement, - const uint32_t& appId, const bool& stickDocument); virtual bool DeallocPOfflineCacheUpdate(POfflineCacheUpdateParent* actor); diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index eea68723e883..b3a59502b5ed 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -770,6 +770,9 @@ pref("security.fileuri.strict_origin_policy", true); // the results pref("network.allow-experiments", true); +// Turn off interprocess security checks. Needed to run xpcshell tests. +pref("network.disable.ipc.security", false); + // Default action for unlisted external protocol handlers pref("network.protocol-handler.external-default", true); // OK to load pref("network.protocol-handler.warn-external-default", true); // warn before load diff --git a/netwerk/cookie/CookieServiceChild.cpp b/netwerk/cookie/CookieServiceChild.cpp index a20b33bff158..d0e88c578103 100644 --- a/netwerk/cookie/CookieServiceChild.cpp +++ b/netwerk/cookie/CookieServiceChild.cpp @@ -4,12 +4,14 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/net/CookieServiceChild.h" - +#include "mozilla/dom/TabChild.h" #include "mozilla/ipc/URIUtils.h" #include "mozilla/net/NeckoChild.h" #include "nsIURI.h" #include "nsIPrefService.h" #include "nsIPrefBranch.h" +#include "nsITabChild.h" +#include "nsNetUtil.h" using namespace mozilla::ipc; @@ -115,10 +117,19 @@ CookieServiceChild::GetCookieStringInternal(nsIURI *aHostURI, URIParams uriParams; SerializeURI(aHostURI, uriParams); + nsCOMPtr iTabChild; + mozilla::dom::TabChild* tabChild = nullptr; + if (aChannel) { + NS_QueryNotificationCallbacks(aChannel, iTabChild); + if (iTabChild) { + tabChild = static_cast(iTabChild.get()); + } + } + // Synchronously call the parent. nsAutoCString result; SendGetCookieString(uriParams, !!isForeign, aFromHttp, - IPC::SerializedLoadContext(aChannel), &result); + IPC::SerializedLoadContext(aChannel), tabChild, &result); if (!result.IsEmpty()) *aCookieString = ToNewCString(result); @@ -148,9 +159,18 @@ CookieServiceChild::SetCookieStringInternal(nsIURI *aHostURI, URIParams uriParams; SerializeURI(aHostURI, uriParams); + nsCOMPtr iTabChild; + mozilla::dom::TabChild* tabChild = nullptr; + if (aChannel) { + NS_QueryNotificationCallbacks(aChannel, iTabChild); + if (iTabChild) { + tabChild = static_cast(iTabChild.get()); + } + } + // Synchronously call the parent. SendSetCookieString(uriParams, !!isForeign, cookieString, serverTime, - aFromHttp, IPC::SerializedLoadContext(aChannel)); + aFromHttp, IPC::SerializedLoadContext(aChannel), tabChild); return NS_OK; } diff --git a/netwerk/cookie/CookieServiceParent.cpp b/netwerk/cookie/CookieServiceParent.cpp index 90cb528574f6..ef9655a69c80 100644 --- a/netwerk/cookie/CookieServiceParent.cpp +++ b/netwerk/cookie/CookieServiceParent.cpp @@ -4,32 +4,44 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/net/CookieServiceParent.h" +#include "mozilla/dom/PBrowserParent.h" +#include "mozilla/net/NeckoParent.h" #include "mozilla/ipc/URIUtils.h" #include "nsCookieService.h" #include "nsNetUtil.h" +#include "nsPrintfCString.h" using namespace mozilla::ipc; +using mozilla::dom::PBrowserParent; +using mozilla::net::NeckoParent; -static void -GetAppInfoFromLoadContext(const IPC::SerializedLoadContext &aLoadContext, - uint32_t& aAppId, - bool& aIsInBrowserElement, - bool& aIsPrivate) +MOZ_WARN_UNUSED_RESULT +static bool +GetAppInfoFromParams(const IPC::SerializedLoadContext &aLoadContext, + PBrowserParent* aBrowser, + uint32_t& aAppId, + bool& aIsInBrowserElement, + bool& aIsPrivate) { - // TODO: bug 782542: what to do when we get null loadContext? For now assume - // NECKO_NO_APP_ID. aAppId = NECKO_NO_APP_ID; aIsInBrowserElement = false; aIsPrivate = false; - if (aLoadContext.IsNotNull()) { - aAppId = aLoadContext.mAppId; - aIsInBrowserElement = aLoadContext.mIsInBrowserElement; + const char* error = NeckoParent::GetValidatedAppInfo(aLoadContext, aBrowser, + &aAppId, + &aIsInBrowserElement); + if (error) { + NS_WARNING(nsPrintfCString("CookieServiceParent: GetAppInfoFromParams: " + "FATAL error: %s: KILLING CHILD PROCESS\n", + error).get()); + return false; } if (aLoadContext.IsPrivateBitValid()) aIsPrivate = aLoadContext.mUsePrivateBrowsing; + + return true; } namespace mozilla { @@ -57,6 +69,7 @@ CookieServiceParent::RecvGetCookieString(const URIParams& aHost, const bool& aFromHttp, const IPC::SerializedLoadContext& aLoadContext, + PBrowserParent* aBrowser, nsCString* aResult) { if (!mCookieService) @@ -70,10 +83,15 @@ CookieServiceParent::RecvGetCookieString(const URIParams& aHost, uint32_t appId; bool isInBrowserElement, isPrivate; - GetAppInfoFromLoadContext(aLoadContext, appId, isInBrowserElement, isPrivate); + bool valid = GetAppInfoFromParams(aLoadContext, aBrowser, appId, + isInBrowserElement, isPrivate); + if (!valid) { + return false; + } mCookieService->GetCookieStringInternal(hostURI, aIsForeign, aFromHttp, appId, - isInBrowserElement, isPrivate, *aResult); + isInBrowserElement, isPrivate, + *aResult); return true; } @@ -84,7 +102,8 @@ CookieServiceParent::RecvSetCookieString(const URIParams& aHost, const nsCString& aServerTime, const bool& aFromHttp, const IPC::SerializedLoadContext& - aLoadContext) + aLoadContext, + PBrowserParent* aBrowser) { if (!mCookieService) return true; @@ -97,7 +116,11 @@ CookieServiceParent::RecvSetCookieString(const URIParams& aHost, uint32_t appId; bool isInBrowserElement, isPrivate; - GetAppInfoFromLoadContext(aLoadContext, appId, isInBrowserElement, isPrivate); + bool valid = GetAppInfoFromParams(aLoadContext, aBrowser, appId, + isInBrowserElement, isPrivate); + if (!valid) { + return false; + } nsDependentCString cookieString(aCookieString, 0); //TODO: bug 812475, pass a real channel object diff --git a/netwerk/cookie/CookieServiceParent.h b/netwerk/cookie/CookieServiceParent.h index d51a209287ff..ec228ae6a67e 100644 --- a/netwerk/cookie/CookieServiceParent.h +++ b/netwerk/cookie/CookieServiceParent.h @@ -13,6 +13,9 @@ class nsCookieService; class nsIIOService; namespace mozilla { +namespace dom { + class PBrowserParent; +} namespace net { class CookieServiceParent : public PCookieServiceParent @@ -27,6 +30,7 @@ protected: const bool& aFromHttp, const IPC::SerializedLoadContext& loadContext, + mozilla::dom::PBrowserParent* aBrowser, nsCString* aResult); virtual bool RecvSetCookieString(const URIParams& aHost, @@ -35,7 +39,8 @@ protected: const nsCString& aServerTime, const bool& aFromHttp, const IPC::SerializedLoadContext& - loadContext); + loadContext, + mozilla::dom::PBrowserParent* aBrowser); nsRefPtr mCookieService; }; diff --git a/netwerk/cookie/PCookieService.ipdl b/netwerk/cookie/PCookieService.ipdl index 768eabf1f53e..5a004a9b1581 100644 --- a/netwerk/cookie/PCookieService.ipdl +++ b/netwerk/cookie/PCookieService.ipdl @@ -6,6 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ include protocol PNecko; +include protocol PBrowser; include URIParams; include "SerializedLoadContext.h"; @@ -64,7 +65,8 @@ parent: sync GetCookieString(URIParams host, bool isForeign, bool fromHttp, - SerializedLoadContext loadContext) + SerializedLoadContext loadContext, + nullable PBrowser browser) returns (nsCString result); /* @@ -101,7 +103,8 @@ parent: nsCString cookieString, nsCString serverTime, bool fromHttp, - SerializedLoadContext loadContext); + SerializedLoadContext loadContext, + nullable PBrowser browser); __delete__(); }; diff --git a/netwerk/ipc/NeckoChild.cpp b/netwerk/ipc/NeckoChild.cpp index d47242928604..eb415269a2d0 100644 --- a/netwerk/ipc/NeckoChild.cpp +++ b/netwerk/ipc/NeckoChild.cpp @@ -14,17 +14,22 @@ #include "mozilla/net/FTPChannelChild.h" #include "mozilla/net/WebSocketChannelChild.h" #include "mozilla/dom/network/TCPSocketChild.h" +#include "mozilla/Preferences.h" using mozilla::dom::TCPSocketChild; namespace mozilla { namespace net { +static bool gDisableIPCSecurity = false; +static const char kPrefDisableIPCSecurity[] = "network.disable.ipc.security"; + PNeckoChild *gNeckoChild = nullptr; // C++ file contents NeckoChild::NeckoChild() { + Preferences::AddBoolVarCache(&gDisableIPCSecurity, kPrefDisableIPCSecurity); } NeckoChild::~NeckoChild() @@ -80,7 +85,8 @@ NeckoChild::DeallocPHttpChannel(PHttpChannelChild* channel) } PFTPChannelChild* -NeckoChild::AllocPFTPChannel() +NeckoChild::AllocPFTPChannel(PBrowserChild* aBrowser, + const SerializedLoadContext& aSerialized) { // We don't allocate here: see FTPChannelChild::AsyncOpen() NS_RUNTIMEABORT("AllocPFTPChannel should not be called"); @@ -134,7 +140,8 @@ NeckoChild::DeallocPWyciwygChannel(PWyciwygChannelChild* channel) } PWebSocketChild* -NeckoChild::AllocPWebSocket(PBrowserChild* browser) +NeckoChild::AllocPWebSocket(PBrowserChild* browser, + const SerializedLoadContext& aSerialized) { NS_NOTREACHED("AllocPWebSocket should not be called"); return nullptr; diff --git a/netwerk/ipc/NeckoChild.h b/netwerk/ipc/NeckoChild.h index 8006c4c86937..9bf3021bc450 100644 --- a/netwerk/ipc/NeckoChild.h +++ b/netwerk/ipc/NeckoChild.h @@ -33,9 +33,10 @@ protected: virtual bool DeallocPCookieService(PCookieServiceChild*); virtual PWyciwygChannelChild* AllocPWyciwygChannel(); virtual bool DeallocPWyciwygChannel(PWyciwygChannelChild*); - virtual PFTPChannelChild* AllocPFTPChannel(); + virtual PFTPChannelChild* AllocPFTPChannel(PBrowserChild* aBrowser, + const SerializedLoadContext& aSerialized); virtual bool DeallocPFTPChannel(PFTPChannelChild*); - virtual PWebSocketChild* AllocPWebSocket(PBrowserChild*); + virtual PWebSocketChild* AllocPWebSocket(PBrowserChild*, const SerializedLoadContext&); virtual bool DeallocPWebSocket(PWebSocketChild*); virtual PTCPSocketChild* AllocPTCPSocket(const nsString& aHost, const uint16_t& aPort, diff --git a/netwerk/ipc/NeckoParent.cpp b/netwerk/ipc/NeckoParent.cpp index ae43859f493c..7f3582c5a9d2 100644 --- a/netwerk/ipc/NeckoParent.cpp +++ b/netwerk/ipc/NeckoParent.cpp @@ -14,30 +14,142 @@ #include "mozilla/net/WebSocketChannelParent.h" #include "mozilla/dom/TabParent.h" #include "mozilla/dom/network/TCPSocketParent.h" - +#include "mozilla/Preferences.h" +#include "mozilla/LoadContext.h" +#include "nsPrintfCString.h" #include "nsHTMLDNSPrefetch.h" using mozilla::dom::TabParent; using mozilla::net::PTCPSocketParent; using mozilla::dom::TCPSocketParent; +using IPC::SerializedLoadContext; namespace mozilla { namespace net { +static bool gDisableIPCSecurity = false; +static const char kPrefDisableIPCSecurity[] = "network.disable.ipc.security"; + // C++ file contents NeckoParent::NeckoParent() { + Preferences::AddBoolVarCache(&gDisableIPCSecurity, kPrefDisableIPCSecurity); } NeckoParent::~NeckoParent() { } -PHttpChannelParent* -NeckoParent::AllocPHttpChannel(PBrowserParent* browser, - const SerializedLoadContext& loadContext) +static PBOverrideStatus +PBOverrideStatusFromLoadContext(const SerializedLoadContext& aSerialized) { - HttpChannelParent *p = new HttpChannelParent(browser, loadContext); + if (!aSerialized.IsNotNull() && aSerialized.IsPrivateBitValid()) { + return aSerialized.mUsePrivateBrowsing ? + kPBOverride_Private : + kPBOverride_NotPrivate; + } + return kPBOverride_Unset; +} + +const char* +NeckoParent::GetValidatedAppInfo(const SerializedLoadContext& aSerialized, + PBrowserParent* aBrowser, + uint32_t* aAppId, + bool* aInBrowserElement) +{ + if (!gDisableIPCSecurity) { + if (!aBrowser) { + return "missing required PBrowser argument"; + } + if (!aSerialized.IsNotNull()) { + return "SerializedLoadContext from child is null"; + } + } + + *aAppId = NECKO_UNKNOWN_APP_ID; + *aInBrowserElement = false; + + if (aBrowser) { + nsRefPtr tabParent = static_cast(aBrowser); + + *aAppId = tabParent->OwnOrContainingAppId(); + *aInBrowserElement = tabParent->IsBrowserElement(); + + if (*aAppId == NECKO_UNKNOWN_APP_ID) { + return "TabParent reports appId=NECKO_UNKNOWN_APP_ID!"; + } + // We may get appID=NO_APP if child frame is neither a browser nor an app + if (*aAppId == NECKO_NO_APP_ID) { + if (tabParent->HasOwnApp()) { + return "TabParent reports NECKO_NO_APP_ID but also is an app"; + } + if (tabParent->IsBrowserElement()) { + //