PBrowserParent* ContentParent::AllocPBrowser(const PRUint32& aChromeFlags, const bool& aIsBrowserElement, const AppId& aApp) { // We only use this Alloc() method when the content processes asks // us to open a window. In that case, we're expecting to see the // opening PBrowser as its app descriptor, and we can trust the data // associated with that PBrowser since it's fully owned by this // process. if (AppId::TPBrowserParent != aApp.type()) { NS_ERROR("Content process attempting to forge app ID"); return nullptr; } TabParent* opener = static_cast<TabParent*>(aApp.get_PBrowserParent()); // Popup windows of isBrowser frames are isBrowser if the parent // isBrowser. Allocating a !isBrowser frame with same app ID // would allow the content to access data it's not supposed to. if (opener && opener->IsBrowserElement() && !aIsBrowserElement) { NS_ERROR("Content process attempting to escalate data access privileges"); return nullptr; } TabParent* parent = new TabParent(opener ? opener->GetApp() : nullptr, aIsBrowserElement); // We release this ref in DeallocPBrowser() NS_ADDREF(parent); return parent; }
bool AssertAppProcess(PBrowserParent* aActor, AssertAppProcessType aType, const char* aCapability) { if (!aActor) { NS_WARNING("Testing process capability for null actor"); return false; } TabParent* tab = TabParent::GetFrom(aActor); nsCOMPtr<mozIApplication> app = tab->GetOwnOrContainingApp(); return CheckAppTypeHelper(app, aType, aCapability, tab->IsBrowserElement()); }
bool AssertAppProcess(PBrowserParent* aActor, AssertAppProcessType aType, const char* aCapability) { if (!aActor) { NS_WARNING("Testing process capability for null actor"); return false; } TabParent* tab = static_cast<TabParent*>(aActor); nsCOMPtr<mozIApplication> app = tab->GetOwnOrContainingApp(); bool aValid = false; // isBrowser frames inherit their app descriptor to identify their // data storage, but they don't inherit the capability associated // with that descriptor. if (app && (aType == ASSERT_APP_HAS_PERMISSION || !tab->IsBrowserElement())) { switch (aType) { case ASSERT_APP_HAS_PERMISSION: case ASSERT_APP_PROCESS_PERMISSION: if (!NS_SUCCEEDED(app->HasPermission(aCapability, &aValid))) { aValid = false; } break; case ASSERT_APP_PROCESS_MANIFEST_URL: { nsAutoString manifestURL; if (NS_SUCCEEDED(app->GetManifestURL(manifestURL)) && manifestURL.EqualsASCII(aCapability)) { aValid = true; } break; } default: break; } } if (!aValid) { printf_stderr("Security problem: Content process does not have `%s'. It will be killed.\n", aCapability); ContentParent* process = tab->Manager(); process->KillHard(); } return aValid; }
bool nsIContentParent::CanOpenBrowser(const IPCTabContext& aContext) { const IPCTabAppBrowserContext& appBrowser = aContext.appBrowserContext(); // We don't trust the IPCTabContext we receive from the child, so we'll bail // if we receive an IPCTabContext that's not a PopupIPCTabContext. // (PopupIPCTabContext lets the child process prove that it has access to // the app it's trying to open.) if (appBrowser.type() != IPCTabAppBrowserContext::TPopupIPCTabContext) { NS_ERROR("Unexpected IPCTabContext type. Aborting AllocPBrowserParent."); return false; } const PopupIPCTabContext& popupContext = appBrowser.get_PopupIPCTabContext(); TabParent* opener = static_cast<TabParent*>(popupContext.openerParent()); if (!opener) { NS_ERROR("Got null opener from child; aborting AllocPBrowserParent."); return false; } // Popup windows of isBrowser frames must be isBrowser if the parent // isBrowser. Allocating a !isBrowser frame with same app ID would allow // the content to access data it's not supposed to. if (!popupContext.isBrowserElement() && opener->IsBrowserElement()) { NS_ERROR("Child trying to escalate privileges! Aborting AllocPBrowserParent."); return false; } MaybeInvalidTabContext tc(aContext); if (!tc.IsValid()) { NS_ERROR(nsPrintfCString("Child passed us an invalid TabContext. (%s) " "Aborting AllocPBrowserParent.", tc.GetInvalidReason()).get()); return false; } return true; }