Closed
Bug 1182537
Opened 10 years ago
Closed 10 years ago
Use channel->ascynOpen2 in dom/base/Navigator.cpp
Categories
(Core :: DOM: Security, defect)
Core
DOM: Security
Tracking
()
RESOLVED
FIXED
mozilla43
Tracking | Status | |
---|---|---|
firefox42 | --- | fixed |
People
(Reporter: ckerschb, Assigned: ckerschb)
References
Details
Attachments
(2 files, 8 obsolete files)
11.02 KB,
patch
|
ckerschb
:
review+
|
Details | Diff | Splinter Review |
6.23 KB,
patch
|
ckerschb
:
review+
|
Details | Diff | Splinter Review |
No description provided.
Assignee | ||
Comment 1•10 years ago
|
||
Attachment #8638262 -
Flags: review?(jonas)
Comment on attachment 8638262 [details] [diff] [review]
bug_1182537_asyncopen2_navigator.patch
Review of attachment 8638262 [details] [diff] [review]:
-----------------------------------------------------------------
::: dom/base/Navigator.cpp
@@ +1101,5 @@
> rv = NS_NewChannel(getter_AddRefs(channel),
> uri,
> doc,
> + nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL |
> + nsILoadInfo::SEC_DISALLOW_SCRIPT,
This should use CORS, no? Doesn't seem like we are right now, but I think we should per spec, no? Makes a difference during redirects.
::: dom/security/nsContentSecurityManager.cpp
@@ +69,5 @@
> +
> + // map nsILoadInfo flags to nsIScriptSecurityManager flags
> + uint32_t flags = nsIScriptSecurityManager::STANDARD;
> + if (securityMode & nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL) {
> + flags |= nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL;
This is not correct. DATA_IS_NULL doesn't mean that inheriting protocols are forbidden, it means that they end up as a null-principal.
I think we should explicitly check for data: in the sendBeacon code and leave it at that.
@@ +183,5 @@
> + mimeTypeGuess = EmptyCString();
> + requestingContext = aLoadInfo->LoadingNode();
> + MOZ_ASSERT(requestingContext
> + ? (requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE)
> + : true, "type_beacon requires requestingContext of type Document");
!requestiongContext || requestingContext->NodeType() == DOCUMENT_NODE
Attachment #8638262 -
Flags: review?(jonas) → review-
Assignee | ||
Comment 3•10 years ago
|
||
You are right, we definitely need cors, but in fact, thinks are not quite that simple. We also need a way to communicate the bits for the nsINetworkInterceptController, hence I added yet another flag, or is there a simpler way of doing that?
Anything else I missed?
Attachment #8638262 -
Attachment is obsolete: true
Attachment #8639387 -
Flags: review?(jonas)
This is a big mess.
The reason we're setting an intercept handler is because normally we get that through the loadgroup. But since no loadgroup is used here the SW folks added a horrible hack to the CORS code which makes it deal with things that aren't CORS related, nor otherwise generic, in any way.
There's a few ways we can fix this.
1. The reason that we're not setting a loadgroup here is to avoid having the request cancelled when
the loadgroup dies. But that's breaking a lot of other functionality, like the intercept handler,
appid/browserflag and privatebrowsing, that the loadgroup normally provide.
So we could add code to loadgroups that make it possible to add a request to a loadgroup without
causing that request to get cancelled when the loadgroup is cancelled.
2. Setting a intercept handler as the notificationcallback on the *channel* before setting up the CORS
listener would have solved the problem that the SW folks were facing, without having to resort to
ugly hacks in the CORS code.
3. A more generic solution of 2 is to set the docshell as the notificationcallback on the channel
before setting up the CORS listener. That would likely solve many issues that the current lack of
loadgroup is currently causing.
4. We can do what the <a ping> code is doing here and simply create a new loadgroup which has the
docshell as notification callbacks.
http://mxr.mozilla.org/mozilla-central/source/docshell/base/nsDocShell.cpp#732
I'd recommend doing 3 or 4.
Either way we need to get rid of this intercept handler hack since that's also causing us to add *two* cors-listeners on the preflight. Currently the sendBeacon code adds one cors-listener, and then NS_StartCORSPreflight adds a second one.
Assignee | ||
Comment 5•10 years ago
|
||
(In reply to Jonas Sicking (:sicking) from comment #4)
> 4. We can do what the <a ping> code is doing here and simply create a new
> loadgroup which has the
> docshell as notification callbacks.
Jonas, thanks for clarification. 4 sounds reasonable to me. I set up the interceptcontroller exactly the same way as <ping> does. Nevertheless I can't claim I fully understand what's going on here, but I suppose this is what you had in mind, right?
Attachment #8639387 -
Attachment is obsolete: true
Attachment #8639387 -
Flags: review?(jonas)
Attachment #8639673 -
Flags: review?(jonas)
Assignee | ||
Comment 6•10 years ago
|
||
Jonas, as discussed over IRC I took the DISALLOW_SCRIPT bits out of the patch again because javascript: URLs are disabled by default now anyway.
I am still not sure if the interceptController bits are correct though.
Attachment #8639673 -
Attachment is obsolete: true
Attachment #8639673 -
Flags: review?(jonas)
Attachment #8640084 -
Flags: review?(jonas)
Comment on attachment 8640084 [details] [diff] [review]
bug_1182537_asyncopen2_navigator.patch
Review of attachment 8640084 [details] [diff] [review]:
-----------------------------------------------------------------
The SendPing code does some crazy stuff. No idea why it does things that way but I don't think we should copy it. Do the below instead but get a review from bz as well.
::: dom/base/Navigator.cpp
@@ +1020,5 @@
> return mGeolocation;
> }
>
> class BeaconStreamListener final : public nsIStreamListener
> + , public nsIInterfaceRequestor
This isn't right.
necko doesn't request interface through the streamlistener of the channel, but rather through the notificationCallbacks of the channel. So adding additional interfaces on the streamlistener will do nothing.
See
http://mxr.mozilla.org/mozilla-central/source/netwerk/base/nsNetUtil.h#629
http://mxr.mozilla.org/mozilla-central/source/netwerk/base/nsIChannel.idl#83
http://mxr.mozilla.org/mozilla-central/source/netwerk/base/nsILoadGroup.idl#76
This is the code that fails because we don't have a loadgroup. Normally the docshell is the notificationcallbacks on the loadgroup.
@@ +1075,5 @@
> return NS_OK;
> }
>
> +NS_IMETHODIMP
> +BeaconStreamListener::GetInterface(const nsIID& aIID, void** aResult)
So this is also not needed.
@@ +1271,5 @@
> + channel->SetLoadGroup(loadGroup);
> +
> + BeaconStreamListener* beaconListener = new BeaconStreamListener();
> + nsCOMPtr<nsINetworkInterceptController> interceptController =
> + do_QueryInterface(docShell);
This is also not needed.
@@ +1276,5 @@
> + beaconListener->SetInterceptController(interceptController);
> + nsCOMPtr<nsIStreamListener> listener(beaconListener);
> +
> + // Observe redirects as well:
> + nsCOMPtr<nsIInterfaceRequestor> callbacks = do_QueryInterface(listener);
Just change 'listener' to 'docShell' here instead.
If you do this, you can delete the stuff about mozIThirdPartyUtil and nsIPrivateBrowsingChannel above.
You will however have to make the Beacon listener hold a strong reference to the loadGroup. And then release that reference in OnRequestStart. Though only set the reference if AsyncOpen2 succeeds.
@@ +1298,5 @@
> + principal,
> + true);
> +
> + rv = cors->Init(channel, DataURIHandling::Allow);
> + NS_ENSURE_SUCCESS(rv, false);
This isn't needed. NS_StartCORSPreflight adds a CORSlistenerproxy to the preflight channel.
Attachment #8640084 -
Flags: review?(jonas) → review-
Assignee | ||
Comment 8•10 years ago
|
||
(In reply to Jonas Sicking (:sicking) from comment #7)
> The SendPing code does some crazy stuff. No idea why it does things that way
> but I don't think we should copy it. Do the below instead but get a review
> from bz as well.
Will do.
> > + nsCOMPtr<nsIInterfaceRequestor> callbacks = do_QueryInterface(listener);
> Just change 'listener' to 'docShell' here instead.
>
> If you do this, you can delete the stuff about mozIThirdPartyUtil and
> nsIPrivateBrowsingChannel above.
I did that, but I have to admit I don't fully understand how that works under the hood, so please take another close look if that is what you wanted to have done.
> You will however have to make the Beacon listener hold a strong reference to
> the loadGroup. And then release that reference in OnRequestStart. Though
> only set the reference if AsyncOpen2 succeeds.
Should we set the loadgroup after the if-else or really only if asyncOpen2() succeeds?
Attachment #8640084 -
Attachment is obsolete: true
Attachment #8640599 -
Flags: review?(bzbarsky)
![]() |
||
Comment 9•10 years ago
|
||
Comment on attachment 8640599 [details] [diff] [review]
bug_1182537_asyncopen2_navigator.patch
The explicit scheme check does not make me a happy camper, but ok.
>+ BeaconStreamListener* beaconListener = new BeaconStreamListener();
This needs to be an nsRefPtr. Otherwise after your call to nsCORSListenerProxy() this object could be dead for all you know.
>+ nsRefPtr<nsCORSListenerProxy> cors = new nsCORSListenerProxy(beaconListener,
Does the "SEC_REQUIRE_CORS_DATA_INHERITS" bit you passed to NewChannel not handle this?
>+ // make the beaconListener hold a strong reference to the loadgroup
To answer your question, yes this should only happen if AsyncOpen succeeds. Otherwise you leak.
r=me, I think
Attachment #8640599 -
Flags: review?(bzbarsky) → review+
Assignee | ||
Comment 10•10 years ago
|
||
Comment on attachment 8640599 [details] [diff] [review]
bug_1182537_asyncopen2_navigator.patch
Thanks Boris - Jonas, just to make sure, can you have another look if I ended up adding all the code you requested?
Attachment #8640599 -
Flags: review?(jonas)
Comment on attachment 8640599 [details] [diff] [review]
bug_1182537_asyncopen2_navigator.patch
Review of attachment 8640599 [details] [diff] [review]:
-----------------------------------------------------------------
::: dom/base/Navigator.cpp
@@ +1259,5 @@
>
> + nsCOMPtr<nsIPrincipal> principal = doc->NodePrincipal();
> + nsRefPtr<nsCORSListenerProxy> cors = new nsCORSListenerProxy(beaconListener,
> + principal,
> + true);
This isn't needed, NS_StartCORSPreflight will add a cors-listener to the preflight, and AsyncOpen2 will add one to the request itself.
Oooh! But we do need to make sure that NS_StartCORSPreflight calls AsyncOpen2!
Maybe make NS_StartCORSPreflight call AsyncOpen2 if the loadinfo sets one of the mode-flags.
@@ +1284,5 @@
> return false;
> }
> + // make the beaconListener hold a strong reference to the loadgroup
> + // which is released in ::OnStartRequest
> + beaconListener->setLoadGroup(loadGroup);
Actually, just do this if NS_SUCCEEDED(rv). I.e. if we successfully started the request.
Attachment #8640599 -
Flags: review+
(In reply to Boris Zbarsky [:bz] from comment #9)
> The explicit scheme check does not make me a happy camper, but ok.
I think it's ok since this isn't a security check. It's rather a "pinging a data: URL is meaningless" check.
Assignee | ||
Comment 13•10 years ago
|
||
(In reply to Jonas Sicking (:sicking) from comment #11)
> @@ +1284,5 @@
> > return false;
> > }
> > + // make the beaconListener hold a strong reference to the loadgroup
> > + // which is released in ::OnStartRequest
> > + beaconListener->setLoadGroup(loadGroup);
>
> Actually, just do this if NS_SUCCEEDED(rv). I.e. if we successfully started
> the request.
There is an if (NS_FAILED(rv)) block that returns false right above that code. In other words we only set the loadgroup if opening succeeded.
Attachment #8640599 -
Attachment is obsolete: true
Attachment #8640599 -
Flags: review?(jonas)
Attachment #8640692 -
Flags: review+
Assignee | ||
Comment 14•10 years ago
|
||
Attachment #8640693 -
Flags: review?(jonas)
Comment on attachment 8640693 [details] [diff] [review]
bug_1182537_asyncopen2_corspreflight.patch
Review of attachment 8640693 [details] [diff] [review]:
-----------------------------------------------------------------
Somewhat related, we should probably make NS_StartCORSPreflight fail, rather than use a system principal, if the passed in channel doesn't have a loadinfo.
::: dom/security/nsCORSListenerProxy.cpp
@@ +1182,5 @@
> AddResultToCache(aRequest);
>
> + nsCOMPtr<nsILoadInfo> loadInfo = mOuterChannel->GetLoadInfo();
> + nsSecurityFlags securityMode = loadInfo ? loadInfo->GetSecurityMode()
> + : 0; // no security mode flags
Please assert that securityMode is either SEC_REQUIRE_CORS_DATA_INHERITS or 0. Otherwise we shouldn't get here.
@@ +1273,5 @@
> + rv = aRequestChannel->GetLoadInfo(getter_AddRefs(loadInfo));
> + NS_ENSURE_SUCCESS(rv, rv);
> +
> + nsSecurityFlags securityMode = loadInfo ? loadInfo->GetSecurityMode()
> + : 0; // no security mode flags
Same here.
@@ +1348,5 @@
> preflightListener = corsListener;
>
> // Start preflight
> + if (securityMode == nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) {
> + rv = preflightChannel->AsyncOpen2(preflightListener);
Sorry, my bad, you also need to remove the CORS-listener-proxy here. Since AsyncOpen2 will install one.
@@ +1351,5 @@
> + if (securityMode == nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) {
> + rv = preflightChannel->AsyncOpen2(preflightListener);
> + }
> + else {
> + rv = preflightChannel->AsyncOpen(preflightListener, nullptr);
But here we still need the listener :(
Attachment #8640693 -
Flags: review?(jonas) → review-
Assignee | ||
Comment 16•10 years ago
|
||
I agree, we should fail if we do not have a LoadInfo available as of now!
Attachment #8640693 -
Attachment is obsolete: true
Attachment #8640798 -
Flags: review?(jonas)
Comment on attachment 8640798 [details] [diff] [review]
bug_1182537_asyncopen2_corspreflight.patch
Review of attachment 8640798 [details] [diff] [review]:
-----------------------------------------------------------------
::: dom/security/nsCORSListenerProxy.cpp
@@ +1339,5 @@
> + }
> + else {
> + // Set up listener which will start the original channel
> + nsCOMPtr<nsIStreamListener> preflightListener =
> + new nsCORSPreflightListener(aRequestChannel, aListener, nullptr, aPrincipal,
You'll still need this listener for the AsyncOpen2 case. This listener is what actually calls AsyncOpen(2) on the channel if the preflight succeeds. See nsCORSPreflightListener::OnStartRequest
Attachment #8640798 -
Flags: review?(jonas) → review-
Assignee | ||
Comment 18•10 years ago
|
||
Makes sense, we still want the nsCORSPreflightListener in both cases, but asyncOpen(2) sets up the nsCORSListenerProxy for us, whereas the regular open doesn't.
That should be correct now.
Attachment #8640798 -
Attachment is obsolete: true
Attachment #8640880 -
Flags: review?(jonas)
Comment on attachment 8640880 [details] [diff] [review]
bug_1182537_asyncopen2_corspreflight.patch
Review of attachment 8640880 [details] [diff] [review]:
-----------------------------------------------------------------
::: dom/security/nsCORSListenerProxy.cpp
@@ +1192,5 @@
> + securityMode == nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS,
> + "how did we end up here?");
> +
> + if (securityMode == nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) {
> + rv = mOuterChannel->AsyncOpen2(mOuterListener);
Add an assertion that mOuterContext is null
@@ +1354,2 @@
>
> + rv = preflightChannel->AsyncOpen(preflightListener, nullptr);
Nit: Just pass corsListener here instead of first assigning it to preflightListener.
Attachment #8640880 -
Flags: review?(jonas) → review+
Assignee | ||
Comment 20•10 years ago
|
||
Assignee | ||
Comment 21•10 years ago
|
||
Let's have a look:
https://treeherder.mozilla.org/#/jobs?repo=try&revision=00203039437b
Attachment #8640880 -
Attachment is obsolete: true
Attachment #8640900 -
Flags: review+
Assignee | ||
Comment 22•10 years ago
|
||
(In reply to Christoph Kerschbaumer [:ckerschb] from comment #21)
> Created attachment 8640900 [details] [diff] [review]
> bug_1182537_asyncopen2_corspreflight.patch
>
> Let's have a look:
> https://treeherder.mozilla.org/#/jobs?repo=try&revision=00203039437b
Looks good; missed the '!' when adding the assertion last night:
Assertion failure: mOuterContext (AsyncOpen(2) does not take context as a second arg), at /builds/slave/try-lx-d-000000000000000000000/build/src/dom/security/nsCORSListenerProxy.cpp:1196
should be:
> MOZ_ASSERT(!mOuterContext, "AsyncOpen(2) does not take context as a second arg");
Comment 23•10 years ago
|
||
Comment 24•10 years ago
|
||
https://hg.mozilla.org/mozilla-central/rev/a11078290110
https://hg.mozilla.org/mozilla-central/rev/dc7fa51079ad
Status: NEW → RESOLVED
Closed: 10 years ago
status-firefox42:
--- → fixed
Resolution: --- → FIXED
Target Milestone: --- → mozilla42
Assignee | ||
Comment 26•10 years ago
|
||
It seems that Bug 1190201 is not going to land anytime before the 22nd (which is when the next uplift happens). Even then it's not a great idea to uplift a security sensitive patch to beta. I just discussed with Jonas over IRC and we both agree that we should back out [1] (only the one patch) on aurora before it goes into beta.
Ryan, could you please perform that backout for me?
[1] https://hg.mozilla.org/releases/mozilla-aurora/rev/a11078290110
Depends on: 1190201
Flags: needinfo?(ryanvm)
Comment 27•10 years ago
|
||
I'm not an active sheriff anymore.
Flags: needinfo?(ryanvm) → needinfo?(wkocher)
Backed out in https://hg.mozilla.org/releases/mozilla-aurora/rev/7239a71b423f
Please update the status-firefox42 flag as desired (since half of this was backed out, unsure if that counts as 'fixed' or 'affected').
Flags: needinfo?(wkocher)
Assignee | ||
Comment 29•10 years ago
|
||
(In reply to Wes Kocher (:KWierso) from comment #28)
> Backed out in https://hg.mozilla.org/releases/mozilla-aurora/rev/7239a71b423f
Thanks!
Target Milestone: mozilla42 → mozilla43
Assignee | ||
Comment 30•10 years ago
|
||
(In reply to Wes Kocher (:KWierso) from comment #28)
> Please update the status-firefox42 flag as desired (since half of this was
> backed out, unsure if that counts as 'fixed' or 'affected').
Setting the flag to >> Target Milestone: mozilla43 <<
The code that remains in 42 [1] is only plumbing that remains *unused* if the loadInfo does not contain the right security flags.
[1] https://hg.mozilla.org/mozilla-central/rev/dc7fa51079ad
Assignee | ||
Comment 31•10 years ago
|
||
Wes, I have discussed things with Jonas and it seems that Bug 1190201 is not going to land anytime soon. Could you please back out the one patch [1] of aurora before its going to hit beta? I will fix the target milestone flags afterwards. (Just to make sure, the same patch as in comment 28). Thanks.
[1] https://hg.mozilla.org/mozilla-central/rev/a11078290110
Flags: needinfo?(wkocher)
This is conflicting with the changes from bug 1199049. Could you provided a rebased backout patch, please?
Flags: needinfo?(wkocher) → needinfo?(mozilla)
Assignee | ||
Comment 33•10 years ago
|
||
(In reply to Wes Kocher (:KWierso) from comment #32)
> This is conflicting with the changes from bug 1199049. Could you provided a
> rebased backout patch, please?
Wes, I filed bug 1218667 because i think that backout is going to need some discussion. I'll let you know once it's ready. Thanks!
Flags: needinfo?(mozilla)
You need to log in
before you can comment on or make changes to this bug.
Description
•