Bug 833935 - Warn when child is about to issue illegal IPDL request. r=jdm a=blocking-b2g
--- a/netwerk/cookie/CookieServiceChild.cpp
+++ b/netwerk/cookie/CookieServiceChild.cpp
@@ -119,16 +119,19 @@ CookieServiceChild::GetCookieStringInter
nsCOMPtr<nsITabChild> iTabChild;
mozilla::dom::TabChild* tabChild = nullptr;
if (aChannel) {
NS_QueryNotificationCallbacks(aChannel, iTabChild);
if (iTabChild) {
tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get());
}
+ if (MissingRequiredTabChild(tabChild, "cookie")) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
}
// Synchronously call the parent.
nsAutoCString result;
SendGetCookieString(uriParams, !!isForeign, aFromHttp,
IPC::SerializedLoadContext(aChannel), tabChild, &result);
if (!result.IsEmpty())
*aCookieString = ToNewCString(result);
@@ -161,16 +164,19 @@ CookieServiceChild::SetCookieStringInter
nsCOMPtr<nsITabChild> iTabChild;
mozilla::dom::TabChild* tabChild = nullptr;
if (aChannel) {
NS_QueryNotificationCallbacks(aChannel, iTabChild);
if (iTabChild) {
tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get());
}
+ if (MissingRequiredTabChild(tabChild, "cookie")) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
}
// Synchronously call the parent.
SendSetCookieString(uriParams, !!isForeign, cookieString, serverTime,
aFromHttp, IPC::SerializedLoadContext(aChannel), tabChild);
return NS_OK;
}
--- a/netwerk/ipc/NeckoCommon.h
+++ b/netwerk/ipc/NeckoCommon.h
@@ -8,16 +8,20 @@
#ifndef mozilla_net_NeckoCommon_h
#define mozilla_net_NeckoCommon_h
#include "nsXULAppAPI.h"
#include "prenv.h"
#include "nsPrintfCString.h"
#include "mozilla/Preferences.h"
+namespace mozilla { namespace dom {
+class TabChild;
+}}
+
#if defined(DEBUG) || defined(ENABLE_TESTS)
# define NECKO_ERRORS_ARE_FATAL_DEFAULT true
#else
# define NECKO_ERRORS_ARE_FATAL_DEFAULT false
#endif
// TODO: Eventually remove NECKO_MAYBE_ABORT and DROP_DEAD (bug 575494).
// Still useful for catching listener interfaces we don't yet support across
@@ -88,15 +92,34 @@ UsingNeckoIPCSecurity()
if (!registeredBool) {
Preferences::AddBoolVarCache(&securityDisabled,
"network.disable.ipc.security");
registeredBool = true;
}
return !securityDisabled;
}
+inline bool
+MissingRequiredTabChild(mozilla::dom::TabChild* tabChild,
+ const char* context)
+{
+ if (UsingNeckoIPCSecurity()) {
+ // Bug 833935: during navigation away from page some loads may lack
+ // TabParent: we don't want to kill browser for that. Doesn't happen in
+ // test harness, so fail in debug mode so we can catch new code that fails
+ // to pass security info.
+ MOZ_ASSERT(tabChild);
+
+ if (!tabChild) {
+ printf_stderr("WARNING: child tried to open %s IPDL channel w/o "
+ "security info\n", context);
+ return true;
+ }
+ }
+ return false;
+}
} // namespace net
} // namespace mozilla
#endif // mozilla_net_NeckoCommon_h
--- a/netwerk/ipc/RemoteOpenFileChild.cpp
+++ b/netwerk/ipc/RemoteOpenFileChild.cpp
@@ -101,16 +101,19 @@ RemoteOpenFileChild::AsyncRemoteFileOpen
if (aFlags != PR_RDONLY) {
return NS_ERROR_NOT_AVAILABLE;
}
mozilla::dom::TabChild* tabChild = nullptr;
if (aTabChild) {
tabChild = static_cast<mozilla::dom::TabChild*>(aTabChild);
}
+ if (MissingRequiredTabChild(tabChild, "remoteopenfile")) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
#if defined(XP_WIN) || defined(MOZ_WIDGET_COCOA)
// Windows/OSX desktop builds skip remoting, and just open file in child
// process when asked for NSPR handle
aListener->OnRemoteFileOpenComplete(NS_OK);
mAsyncOpenCalled = true;
return NS_OK;
#else
--- a/netwerk/protocol/ftp/FTPChannelChild.cpp
+++ b/netwerk/protocol/ftp/FTPChannelChild.cpp
@@ -160,16 +160,19 @@ FTPChannelChild::AsyncOpen(::nsIStreamLi
nsCOMPtr<nsITabChild> iTabChild;
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup,
NS_GET_IID(nsITabChild),
getter_AddRefs(iTabChild));
GetCallback(iTabChild);
if (iTabChild) {
tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get());
}
+ if (MissingRequiredTabChild(tabChild, "ftp")) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
// FIXME: like bug 558623, merge constructor+SendAsyncOpen into 1 IPC msg
gNeckoChild->SendPFTPChannelConstructor(this, tabChild, IPC::SerializedLoadContext(this));
mListener = listener;
mListenerContext = aContext;
// add ourselves to the load group.
if (mLoadGroup)
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -797,16 +797,19 @@ NS_IMETHODIMP
HttpChannelChild::ConnectParent(uint32_t id)
{
mozilla::dom::TabChild* tabChild = nullptr;
nsCOMPtr<nsITabChild> iTabChild;
GetCallback(iTabChild);
if (iTabChild) {
tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get());
}
+ if (MissingRequiredTabChild(tabChild, "http")) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
// The socket transport in the chrome process now holds a logical ref to us
// until OnStopRequest, or we do a redirect, or we hit an IPDL error.
AddIPDLReference();
if (!gNeckoChild->SendPHttpChannelConstructor(
this, tabChild, IPC::SerializedLoadContext(this))) {
return NS_ERROR_FAILURE;
@@ -1029,16 +1032,19 @@ HttpChannelChild::AsyncOpen(nsIStreamLis
// FIXME: bug 558623: Combine constructor and SendAsyncOpen into one IPC msg
mozilla::dom::TabChild* tabChild = nullptr;
nsCOMPtr<nsITabChild> iTabChild;
GetCallback(iTabChild);
if (iTabChild) {
tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get());
}
+ if (MissingRequiredTabChild(tabChild, "http")) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
// The socket transport in the chrome process now holds a logical ref to us
// until OnStopRequest, or we do a redirect, or we hit an IPDL error.
AddIPDLReference();
gNeckoChild->SendPHttpChannelConstructor(this, tabChild,
IPC::SerializedLoadContext(this));
--- a/netwerk/protocol/websocket/WebSocketChannelChild.cpp
+++ b/netwerk/protocol/websocket/WebSocketChannelChild.cpp
@@ -326,16 +326,19 @@ WebSocketChannelChild::AsyncOpen(nsIURI
mozilla::dom::TabChild* tabChild = nullptr;
nsCOMPtr<nsITabChild> iTabChild;
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup,
NS_GET_IID(nsITabChild),
getter_AddRefs(iTabChild));
if (iTabChild) {
tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get());
}
+ if (MissingRequiredTabChild(tabChild, "websocket")) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
URIParams uri;
SerializeURI(aURI, uri);
// Corresponding release in DeallocPWebSocket
AddIPDLReference();
gNeckoChild->SendPWebSocketConstructor(this, tabChild,
--- a/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp
+++ b/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp
@@ -598,16 +598,20 @@ WyciwygChannelChild::AsyncOpen(nsIStream
if (mLoadGroup)
mLoadGroup->AddRequest(this, nullptr);
URIParams originalURI;
SerializeURI(mOriginalURI, originalURI);
mozilla::dom::TabChild* tabChild = GetTabChild(this);
+ if (MissingRequiredTabChild(tabChild, "wyciwyg")) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+
SendAsyncOpen(originalURI, mLoadFlags, IPC::SerializedLoadContext(this), tabChild);
mSentAppData = true;
mState = WCC_OPENED;
return NS_OK;
}
--- a/uriloader/prefetch/OfflineCacheUpdateChild.cpp
+++ b/uriloader/prefetch/OfflineCacheUpdateChild.cpp
@@ -3,16 +3,17 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "OfflineCacheUpdateChild.h"
#include "nsOfflineCacheUpdate.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/TabChild.h"
#include "mozilla/ipc/URIUtils.h"
+#include "mozilla/net/NeckoCommon.h"
#include "nsIApplicationCacheContainer.h"
#include "nsIApplicationCacheChannel.h"
#include "nsIApplicationCacheService.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeItem.h"
#include "nsIDocShellTreeOwner.h"
#include "nsIDOMWindow.h"
@@ -26,16 +27,18 @@
#include "nsServiceManagerUtils.h"
#include "nsStreamUtils.h"
#include "nsThreadUtils.h"
#include "nsProxyRelease.h"
#include "prlog.h"
#include "nsIAsyncVerifyRedirectCallback.h"
using namespace mozilla::ipc;
+using namespace mozilla::net;
+using mozilla::dom::TabChild;
#if defined(PR_LOGGING)
//
// To enable logging (see prlog.h for full details):
//
// set NSPR_LOG_MODULES=nsOfflineCacheUpdate:5
// set NSPR_LOG_FILE=offlineupdate.log
//
@@ -400,29 +403,28 @@ OfflineCacheUpdateChild::Schedule()
NS_WARNING("doc shell tree item is null");
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDocShellTreeOwner> owner;
item->GetTreeOwner(getter_AddRefs(owner));
nsCOMPtr<nsITabChild> tabchild = do_GetInterface(owner);
- if (!tabchild) {
- NS_WARNING("tab is null");
+ // because owner implements nsITabChild, we can assume that it is
+ // the one and only TabChild.
+ TabChild* child = tabchild ? static_cast<TabChild*>(tabchild.get()) : nullptr;
+
+ if (MissingRequiredTabChild(child, "offlinecacheupdate")) {
return NS_ERROR_FAILURE;
}
URIParams manifestURI, documentURI;
SerializeURI(mManifestURI, manifestURI);
SerializeURI(mDocumentURI, documentURI);
- // because owner implements nsITabChild, we can assume that it is
- // the one and only TabChild.
- mozilla::dom::TabChild* child = static_cast<mozilla::dom::TabChild*>(tabchild.get());
-
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
if (observerService) {
LOG(("Calling offline-cache-update-added"));
observerService->NotifyObservers(static_cast<nsIOfflineCacheUpdate*>(this),
"offline-cache-update-added",
nullptr);
LOG(("Done offline-cache-update-added"));