Bug 1125961 - Allow sending null PBrowser actors when there's a triggering principal which can be used for security checks; r=dragana

This commit is contained in:
Josh Matthews 2015-06-15 14:35:06 -04:00 committed by Ehsan Akhgari
parent ed25606ef3
commit c630379743
15 changed files with 89 additions and 19 deletions

View File

@ -1,5 +1,4 @@
[DEFAULT] [DEFAULT]
skip-if = buildapp == 'b2g'
support-files = support-files =
worker.js worker.js
worker2.js worker2.js

View File

@ -270,7 +270,6 @@ private:
nsCOMPtr<nsIProgressEventSink> mProgressSink; nsCOMPtr<nsIProgressEventSink> mProgressSink;
nsCOMPtr<nsIURI> mOriginalURI; nsCOMPtr<nsIURI> mOriginalURI;
nsCOMPtr<nsISupports> mOwner; nsCOMPtr<nsISupports> mOwner;
nsCOMPtr<nsILoadInfo> mLoadInfo;
nsCOMPtr<nsISupports> mSecurityInfo; nsCOMPtr<nsISupports> mSecurityInfo;
nsCOMPtr<nsIChannel> mRedirectChannel; nsCOMPtr<nsIChannel> mRedirectChannel;
nsCString mContentType; nsCString mContentType;
@ -289,6 +288,7 @@ protected:
nsCOMPtr<nsIInterfaceRequestor> mCallbacks; nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
nsCOMPtr<nsIStreamListener> mListener; nsCOMPtr<nsIStreamListener> mListener;
nsCOMPtr<nsISupports> mListenerContext; nsCOMPtr<nsISupports> mListenerContext;
nsCOMPtr<nsILoadInfo> mLoadInfo;
nsresult mStatus; nsresult mStatus;
uint32_t mContentDispositionHint; uint32_t mContentDispositionHint;
nsAutoPtr<nsString> mContentDispositionFilename; nsAutoPtr<nsString> mContentDispositionFilename;

View File

@ -153,7 +153,8 @@ NeckoChild::DeallocPWyciwygChannelChild(PWyciwygChannelChild* channel)
PWebSocketChild* PWebSocketChild*
NeckoChild::AllocPWebSocketChild(const PBrowserOrId& browser, NeckoChild::AllocPWebSocketChild(const PBrowserOrId& browser,
const SerializedLoadContext& aSerialized) const SerializedLoadContext& aSerialized,
const PrincipalInfo& requestingPrincipal)
{ {
NS_NOTREACHED("AllocPWebSocketChild should not be called"); NS_NOTREACHED("AllocPWebSocketChild should not be called");
return nullptr; return nullptr;

View File

@ -41,7 +41,8 @@ protected:
virtual bool DeallocPFTPChannelChild(PFTPChannelChild*) override; virtual bool DeallocPFTPChannelChild(PFTPChannelChild*) override;
virtual PWebSocketChild* virtual PWebSocketChild*
AllocPWebSocketChild(const PBrowserOrId&, AllocPWebSocketChild(const PBrowserOrId&,
const SerializedLoadContext&) override; const SerializedLoadContext&,
const PrincipalInfo&) override;
virtual bool DeallocPWebSocketChild(PWebSocketChild*) override; virtual bool DeallocPWebSocketChild(PWebSocketChild*) override;
virtual PTCPSocketChild* AllocPTCPSocketChild(const nsString& host, virtual PTCPSocketChild* AllocPTCPSocketChild(const nsString& host,
const uint16_t& port) override; const uint16_t& port) override;

View File

@ -12,6 +12,7 @@
#include "prenv.h" #include "prenv.h"
#include "nsPrintfCString.h" #include "nsPrintfCString.h"
#include "mozilla/Preferences.h" #include "mozilla/Preferences.h"
#include "nsILoadInfo.h"
namespace mozilla { namespace dom { namespace mozilla { namespace dom {
class TabChild; class TabChild;
@ -120,10 +121,11 @@ UsingNeckoIPCSecurity()
inline bool inline bool
MissingRequiredTabChild(mozilla::dom::TabChild* tabChild, MissingRequiredTabChild(mozilla::dom::TabChild* tabChild,
nsILoadInfo* loadInfo,
const char* context) const char* context)
{ {
if (UsingNeckoIPCSecurity()) { if (UsingNeckoIPCSecurity()) {
if (!tabChild) { if (!tabChild && (!loadInfo || !loadInfo->LoadingPrincipal())) {
printf_stderr("WARNING: child tried to open %s IPDL channel w/o " printf_stderr("WARNING: child tried to open %s IPDL channel w/o "
"security info\n", context); "security info\n", context);
return true; return true;

View File

@ -27,6 +27,7 @@
#include "mozilla/dom/network/TCPSocketParent.h" #include "mozilla/dom/network/TCPSocketParent.h"
#include "mozilla/dom/network/TCPServerSocketParent.h" #include "mozilla/dom/network/TCPServerSocketParent.h"
#include "mozilla/dom/network/UDPSocketParent.h" #include "mozilla/dom/network/UDPSocketParent.h"
#include "mozilla/ipc/BackgroundUtils.h"
#include "mozilla/ipc/URIUtils.h" #include "mozilla/ipc/URIUtils.h"
#include "mozilla/LoadContext.h" #include "mozilla/LoadContext.h"
#include "mozilla/AppProcessChecker.h" #include "mozilla/AppProcessChecker.h"
@ -166,6 +167,7 @@ NeckoParent::GetValidatedAppInfo(const SerializedLoadContext& aSerialized,
const char * const char *
NeckoParent::CreateChannelLoadContext(const PBrowserOrId& aBrowser, NeckoParent::CreateChannelLoadContext(const PBrowserOrId& aBrowser,
nsIPrincipal* aRequestingPrincipal,
PContentParent* aContent, PContentParent* aContent,
const SerializedLoadContext& aSerialized, const SerializedLoadContext& aSerialized,
nsCOMPtr<nsILoadContext> &aResult) nsCOMPtr<nsILoadContext> &aResult)
@ -188,6 +190,23 @@ NeckoParent::CreateChannelLoadContext(const PBrowserOrId& aBrowser,
dom::Element* topFrameElement = nullptr; dom::Element* topFrameElement = nullptr;
if (tabParent) { if (tabParent) {
topFrameElement = tabParent->GetOwnerElement(); topFrameElement = tabParent->GetOwnerElement();
} else {
if (!aRequestingPrincipal) {
return "missing associated browser and requesting principal";
}
// If a null tab parent is provided, we rely on comparing the requesting principal's
// reported data against the provided load context's data.
uint32_t reportedAppId = NECKO_UNKNOWN_APP_ID;
nsresult rv = aRequestingPrincipal->GetAppId(&reportedAppId);
if (NS_WARN_IF(NS_FAILED(rv)) || appId != reportedAppId) {
return "app id mismatch for request without associated browser";
}
bool reportedInBrowser = false;
rv = aRequestingPrincipal->GetIsInBrowserElement(&reportedInBrowser);
if (NS_WARN_IF(NS_FAILED(rv)) || reportedInBrowser != inBrowser) {
return "browser element mismatch for request without associated browser";
}
} }
aResult = new LoadContext(aSerialized, topFrameElement, aResult = new LoadContext(aSerialized, topFrameElement,
appId, inBrowser); appId, inBrowser);
@ -218,8 +237,22 @@ NeckoParent::AllocPHttpChannelParent(const PBrowserOrId& aBrowser,
const SerializedLoadContext& aSerialized, const SerializedLoadContext& aSerialized,
const HttpChannelCreationArgs& aOpenArgs) const HttpChannelCreationArgs& aOpenArgs)
{ {
nsCOMPtr<nsIPrincipal> requestingPrincipal;
if (aOpenArgs.type() == HttpChannelCreationArgs::THttpChannelOpenArgs) {
nsresult rv;
requestingPrincipal =
mozilla::ipc::PrincipalInfoToPrincipal(aOpenArgs.get_HttpChannelOpenArgs()
.requestingPrincipalInfo(), &rv);
if (NS_FAILED(rv)) {
printf_stderr("NeckoParent::AllocPHttpChannelParent: "
"FATAL error: couldn't deserialize principal: KILLING CHILD PROCESS\n");
return nullptr;
}
}
nsCOMPtr<nsILoadContext> loadContext; nsCOMPtr<nsILoadContext> loadContext;
const char *error = CreateChannelLoadContext(aBrowser, Manager(), const char *error = CreateChannelLoadContext(aBrowser, requestingPrincipal, Manager(),
aSerialized, loadContext); aSerialized, loadContext);
if (error) { if (error) {
printf_stderr("NeckoParent::AllocPHttpChannelParent: " printf_stderr("NeckoParent::AllocPHttpChannelParent: "
@ -257,8 +290,22 @@ NeckoParent::AllocPFTPChannelParent(const PBrowserOrId& aBrowser,
const SerializedLoadContext& aSerialized, const SerializedLoadContext& aSerialized,
const FTPChannelCreationArgs& aOpenArgs) const FTPChannelCreationArgs& aOpenArgs)
{ {
nsCOMPtr<nsIPrincipal> requestingPrincipal;
if (aOpenArgs.type() == FTPChannelCreationArgs::TFTPChannelOpenArgs) {
nsresult rv;
requestingPrincipal =
mozilla::ipc::PrincipalInfoToPrincipal(aOpenArgs.get_FTPChannelOpenArgs()
.requestingPrincipalInfo(), &rv);
if (NS_FAILED(rv)) {
printf_stderr("NeckoParent::AllocPFTPChannelParent: "
"FATAL error: couldn't deserialize principal: KILLING CHILD PROCESS\n");
return nullptr;
}
}
nsCOMPtr<nsILoadContext> loadContext; nsCOMPtr<nsILoadContext> loadContext;
const char *error = CreateChannelLoadContext(aBrowser, Manager(), const char *error = CreateChannelLoadContext(aBrowser, requestingPrincipal, Manager(),
aSerialized, loadContext); aSerialized, loadContext);
if (error) { if (error) {
printf_stderr("NeckoParent::AllocPFTPChannelParent: " printf_stderr("NeckoParent::AllocPFTPChannelParent: "
@ -322,10 +369,20 @@ NeckoParent::DeallocPWyciwygChannelParent(PWyciwygChannelParent* channel)
PWebSocketParent* PWebSocketParent*
NeckoParent::AllocPWebSocketParent(const PBrowserOrId& browser, NeckoParent::AllocPWebSocketParent(const PBrowserOrId& browser,
const SerializedLoadContext& serialized) const SerializedLoadContext& serialized,
const PrincipalInfo& requestingPrincipalInfo)
{ {
nsresult rv;
nsCOMPtr<nsIPrincipal> requestingPrincipal =
mozilla::ipc::PrincipalInfoToPrincipal(requestingPrincipalInfo, &rv);
if (NS_FAILED(rv)) {
printf_stderr("NeckoParent::AllocPWebSocketParent: "
"FATAL error: couldn't deserialize principal: KILLING CHILD PROCESS\n");
return nullptr;
}
nsCOMPtr<nsILoadContext> loadContext; nsCOMPtr<nsILoadContext> loadContext;
const char *error = CreateChannelLoadContext(browser, Manager(), const char *error = CreateChannelLoadContext(browser, requestingPrincipal, Manager(),
serialized, loadContext); serialized, loadContext);
if (error) { if (error) {
printf_stderr("NeckoParent::AllocPWebSocketParent: " printf_stderr("NeckoParent::AllocPWebSocketParent: "

View File

@ -48,6 +48,7 @@ public:
MOZ_WARN_UNUSED_RESULT MOZ_WARN_UNUSED_RESULT
static const char* static const char*
CreateChannelLoadContext(const PBrowserOrId& aBrowser, CreateChannelLoadContext(const PBrowserOrId& aBrowser,
nsIPrincipal* aRequestingPrincipal,
PContentParent* aContent, PContentParent* aContent,
const SerializedLoadContext& aSerialized, const SerializedLoadContext& aSerialized,
nsCOMPtr<nsILoadContext> &aResult); nsCOMPtr<nsILoadContext> &aResult);
@ -121,7 +122,8 @@ protected:
virtual bool DeallocPFTPChannelParent(PFTPChannelParent*) override; virtual bool DeallocPFTPChannelParent(PFTPChannelParent*) override;
virtual PWebSocketParent* virtual PWebSocketParent*
AllocPWebSocketParent(const PBrowserOrId& browser, AllocPWebSocketParent(const PBrowserOrId& browser,
const SerializedLoadContext& aSerialized) override; const SerializedLoadContext& aSerialized,
const PrincipalInfo& requestingPrincipal) override;
virtual bool DeallocPWebSocketParent(PWebSocketParent*) override; virtual bool DeallocPWebSocketParent(PWebSocketParent*) override;
virtual PTCPSocketParent* AllocPTCPSocketParent(const nsString& host, virtual PTCPSocketParent* AllocPTCPSocketParent(const nsString& host,
const uint16_t& port) override; const uint16_t& port) override;

View File

@ -28,6 +28,7 @@ include URIParams;
include InputStreamParams; include InputStreamParams;
include NeckoChannelParams; include NeckoChannelParams;
include PBrowserOrId; include PBrowserOrId;
include PBackgroundSharedTypes;
using class IPC::SerializedLoadContext from "SerializedLoadContext.h"; using class IPC::SerializedLoadContext from "SerializedLoadContext.h";
using mozilla::dom::TabId from "mozilla/dom/ipc/IdType.h"; using mozilla::dom::TabId from "mozilla/dom/ipc/IdType.h";
@ -66,7 +67,8 @@ parent:
PFTPChannel(PBrowserOrId browser, SerializedLoadContext loadContext, PFTPChannel(PBrowserOrId browser, SerializedLoadContext loadContext,
FTPChannelCreationArgs args); FTPChannelCreationArgs args);
PWebSocket(PBrowserOrId browser, SerializedLoadContext loadContext); PWebSocket(PBrowserOrId browser, SerializedLoadContext loadContext,
PrincipalInfo requestingPrincipalInfo);
PTCPServerSocket(uint16_t localPort, uint16_t backlog, nsString binaryType); PTCPServerSocket(uint16_t localPort, uint16_t backlog, nsString binaryType);
PUDPSocket(Principal principal, nsCString filter); PUDPSocket(Principal principal, nsCString filter);

View File

@ -209,7 +209,7 @@ RemoteOpenFileChild::AsyncRemoteFileOpen(int32_t aFlags,
mTabChild = static_cast<TabChild*>(aTabChild); mTabChild = static_cast<TabChild*>(aTabChild);
if (MissingRequiredTabChild(mTabChild, "remoteopenfile")) { if (MissingRequiredTabChild(mTabChild, nullptr, "remoteopenfile")) {
return NS_ERROR_ILLEGAL_VALUE; return NS_ERROR_ILLEGAL_VALUE;
} }

View File

@ -208,7 +208,7 @@ FTPChannelChild::AsyncOpen(::nsIStreamListener* listener, nsISupports* aContext)
if (iTabChild) { if (iTabChild) {
tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get()); tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get());
} }
if (MissingRequiredTabChild(tabChild, "ftp")) { if (MissingRequiredTabChild(tabChild, mLoadInfo, "ftp")) {
return NS_ERROR_ILLEGAL_VALUE; return NS_ERROR_ILLEGAL_VALUE;
} }

View File

@ -1266,7 +1266,7 @@ HttpChannelChild::ConnectParent(uint32_t id)
if (iTabChild) { if (iTabChild) {
tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get()); tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get());
} }
if (MissingRequiredTabChild(tabChild, "http")) { if (MissingRequiredTabChild(tabChild, mLoadInfo, "http")) {
return NS_ERROR_ILLEGAL_VALUE; return NS_ERROR_ILLEGAL_VALUE;
} }
@ -1618,7 +1618,7 @@ HttpChannelChild::ContinueAsyncOpen()
if (iTabChild) { if (iTabChild) {
tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get()); tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get());
} }
if (MissingRequiredTabChild(tabChild, "http")) { if (MissingRequiredTabChild(tabChild, mLoadInfo, "http")) {
return NS_ERROR_ILLEGAL_VALUE; return NS_ERROR_ILLEGAL_VALUE;
} }

View File

@ -494,7 +494,7 @@ WebSocketChannelChild::AsyncOpen(nsIURI *aURI,
if (iTabChild) { if (iTabChild) {
tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get()); tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get());
} }
if (MissingRequiredTabChild(tabChild, "websocket")) { if (MissingRequiredTabChild(tabChild, mLoadInfo, "websocket")) {
return NS_ERROR_ILLEGAL_VALUE; return NS_ERROR_ILLEGAL_VALUE;
} }
@ -507,8 +507,13 @@ WebSocketChannelChild::AsyncOpen(nsIURI *aURI,
WebSocketLoadInfoArgs wsArgs; WebSocketLoadInfoArgs wsArgs;
propagateLoadInfo(mLoadInfo, wsArgs); propagateLoadInfo(mLoadInfo, wsArgs);
mozilla::ipc::PrincipalInfo requestingPrincipalInfo;
mozilla::ipc::PrincipalToPrincipalInfo(mLoadInfo->LoadingPrincipal(),
&requestingPrincipalInfo);
gNeckoChild->SendPWebSocketConstructor(this, tabChild, gNeckoChild->SendPWebSocketConstructor(this, tabChild,
IPC::SerializedLoadContext(this)); IPC::SerializedLoadContext(this),
requestingPrincipalInfo);
if (!SendAsyncOpen(uri, nsCString(aOrigin), mProtocol, mEncrypted, if (!SendAsyncOpen(uri, nsCString(aOrigin), mProtocol, mEncrypted,
mPingInterval, mClientSetPingInterval, mPingInterval, mClientSetPingInterval,
mPingResponseTimeout, mClientSetPingTimeout, wsArgs)) { mPingResponseTimeout, mClientSetPingTimeout, wsArgs)) {

View File

@ -657,7 +657,7 @@ WyciwygChannelChild::AsyncOpen(nsIStreamListener *aListener, nsISupports *aConte
SerializeURI(mOriginalURI, originalURI); SerializeURI(mOriginalURI, originalURI);
mozilla::dom::TabChild* tabChild = GetTabChild(this); mozilla::dom::TabChild* tabChild = GetTabChild(this);
if (MissingRequiredTabChild(tabChild, "wyciwyg")) { if (MissingRequiredTabChild(tabChild, nullptr, "wyciwyg")) {
return NS_ERROR_ILLEGAL_VALUE; return NS_ERROR_ILLEGAL_VALUE;
} }

View File

@ -134,6 +134,7 @@ WyciwygChannelParent::SetupAppData(const IPC::SerializedLoadContext& loadContext
return true; return true;
const char* error = NeckoParent::CreateChannelLoadContext(aParent, const char* error = NeckoParent::CreateChannelLoadContext(aParent,
nullptr,
Manager()->Manager(), Manager()->Manager(),
loadContext, loadContext,
mLoadContext); mLoadContext);

View File

@ -401,7 +401,7 @@ OfflineCacheUpdateChild::Schedule()
// the one and only TabChild. // the one and only TabChild.
TabChild* child = tabchild ? static_cast<TabChild*>(tabchild.get()) : nullptr; TabChild* child = tabchild ? static_cast<TabChild*>(tabchild.get()) : nullptr;
if (MissingRequiredTabChild(child, "offlinecacheupdate")) { if (MissingRequiredTabChild(child, nullptr, "offlinecacheupdate")) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }