Question about Mojo: Cross process check

67 views
Skip to first unread message

Tsuyoshi Horo

unread,
Jan 13, 2021, 11:08:20 PM1/13/21
to chromi...@chromium.org, webpack...@chromium.org, Kunihiko Sakamoto, Hayato Ito, Kinuko Yasuda
Hi.

I have a question about Mojo.
Is there any way to prohibit calling some Mojo method from different processes?

We are currently implementing the Subresource Web Bundles feature (explainer). With this feature, multiple subresources can be loaded from one web bundle file. For example, Chrome will fetch bundle.wbn from the server and load style.css and script.js from bundle.wbn.
  <link rel="webbundle"
        href="https://example.com/bundle.wbn"
        resources="https://example.com/style.css
                    https://example.com/script.js">
  <link href="https://example.com/style.css" rel="stylesheet">
  <script src="https://example.com/script.js"></script>

In the current implementation design (design doc), the web bundle data is held in the network process. The renderer process generates an unguessable token and uses the token both in the request for the web bundle (bundle.wbn) and in the requests for the other subresources (style.css, script.js). So the network process can return the subresources from the web bundle. This is done in WebBundleManager::GetWebBundleURLLoaderFactory().

But I think we can use a Mojo handle of mojom::URLLoaderFactory instead of the token.
The renderer process sends a pending_receiver<URLLoaderFactory> to the network process in the web bundle request (bundle.wbn). The network process fetches the web bundle from the server and generates a WebBundleURLLoaderFactory for the subresource loading from the web bundle. And the renderer process sends a cloned URLLoaderFactory handle to the network process for the subresources (style.css, script.js).

I’m not 100% sure yet whether using a Mojo handle is a better design than using an unguessable token or not. But if we use the Mojo handle, we want to make WebBundleURLLoaderFactory::CreateLoaderAndStart() callable only from the same process (network process). Is there any way to check whether the method is called from another process?

Thank you.

Ken Rockot

unread,
Jan 14, 2021, 2:53:35 PM1/14/21
to Tsuyoshi Horo, chromium-mojo, webpack...@chromium.org, Kunihiko Sakamoto, Hayato Ito, Kinuko Yasuda
I am confused by the problem statement. You say the network service creates a WebBundleURLLoaderFactory, but I don't see any logical connection between this object and anything happening in any other process. Are you saying that the URLLoaderFactory receiver sent by the renderer will be bound to that WebBundleURLLoaderFactory?

Also, I don't see any other methods on URLLoaderFactory (other than Clone). Why would a process even have a Remote<URLLoaderFactory> if they shouldn't be allowed to call the only method on that interface? Generally in Mojo, the way to to model "you can't call this method" is to not provide an interface connection in the first place.
 

Thank you.

--
You received this message because you are subscribed to the Google Groups "chromium-mojo" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-moj...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-mojo/CADk0S-UnyzHdD%2B8q8XWbstYp6yzzM8Y9YAXZu3-%2BoBhJDXzUFw%40mail.gmail.com.

Tsuyoshi Horo

unread,
Jan 14, 2021, 11:25:10 PM1/14/21
to Ken Rockot, chromium-mojo, webpack...@chromium.org, Kunihiko Sakamoto, Hayato Ito, Kinuko Yasuda
Hi.
 
I am confused by the problem statement. You say the network service creates a WebBundleURLLoaderFactory, but I don't see any logical connection between this object and anything happening in any other process.

The WebBundleURLLoaderFactory is used when the network process handles the URLRequests for the subresources (style.css, script.js) in URLLoaderFactory::CreateLoaderAndStart().

 
Are you saying that the URLLoaderFactory receiver sent by the renderer will be bound to that WebBundleURLLoaderFactory?

Yes. And the URLLoaderFactory remote will be used by the renderer process when it sends the URLRequests for the subresources to tell "Please use this URLLoaderFactory to load the subresource from the web bundle".

 
Also, I don't see any other methods on URLLoaderFactory (other than Clone). Why would a process even have a Remote<URLLoaderFactory> if they shouldn't be allowed to call the only method on that interface? Generally in Mojo, the way to to model "you can't call this method" is to not provide an interface connection in the first place.

The renderer process must be able to call Clone() because multiple subresources can be loaded from one web bundle.
But the renderer process must not be able to call CreateLoaderAndStart(), because the security checks (ex: CORS) for the response from WebBundleURLLoaderFactory should be done in the network process.

If there is no way to check the caller process, using an unguessable token is a better solution. But we must be careful while implementing the life time management of the WebBundleURLLoaderFactory to avoid race condition bugs.

Thank you.

Daniel Cheng

unread,
Jan 15, 2021, 2:05:34 AM1/15/21
to Tsuyoshi Horo, Ken Rockot, chromium-mojo, webpack...@chromium.org, Kunihiko Sakamoto, Hayato Ito, Kinuko Yasuda
Sorry I think I'm missing something, so I don't fully understand the problem.

It sounds like the network service is responsible for creating the WebBundleURLLoaderFactory. If I understand correctly, WebBundleURLLoaderFactory is an implementation of network::mojom::URLLoaderFactory and the network service owns the mojo::Receiver endpoint?

1. How does a renderer request subresources? Isn't CreateLoaderAndStart() the only way?
2. If we're using a token / URLLoaderFactory to identify the bundle, what URLLoaderFactory is the resource request being sent through? It sounds like we're not using the WebBundleURLLoaderFactory directly, and the token/ URLLoaderFactory would only be used to tag the request so the network process knows to serve it from the web bundle?
3. Don't other URLLoaderFactory implementations in the network service need to perform CORS checks in the network service? Could WebBundleURLLoaderFactory be implemented similarly and ensure the URLLoaders created by WebBundleURLLoaderFactory perform security checks before returning a response to the renderer?

Daniel


Tsuyoshi Horo

unread,
Jan 15, 2021, 4:01:43 AM1/15/21
to Daniel Cheng, Ken Rockot, chromium-mojo, webpack...@chromium.org, Kunihiko Sakamoto, Hayato Ito, Kinuko Yasuda
Hi.

It sounds like the network service is responsible for creating the WebBundleURLLoaderFactory. If I understand correctly, WebBundleURLLoaderFactory is an implementation of network::mojom::URLLoaderFactory and the network service owns the mojo::Receiver endpoint?

Yes. Correct.

> 1. How does a renderer request subresources? Isn't CreateLoaderAndStart() the only way?
> 2. If we're using a token / URLLoaderFactory to identify the bundle, what URLLoaderFactory is the resource request being sent through?

The requests for subresources inside the web bundles are sent to the network process as same as normal subresource requests.
The token is set in URLRequest.web_bundle_token_params.token, so the network process can return the subresource from the previously requested web bundle.
My idea is that if we can have URLRequest.web_bundle_token_params.web_bundle_url_loader_factory, we can stop using the token.

> It sounds like we're not using the WebBundleURLLoaderFactory directly, and the token/ URLLoaderFactory would only be used to tag the request so the network process knows to serve it from the web bundle?

Yes. Correct.

> 3. Don't other URLLoaderFactory implementations in the network service need to perform CORS checks in the network service? Could WebBundleURLLoaderFactory be implemented similarly and ensure the URLLoaders created by WebBundleURLLoaderFactory perform security checks before returning a response to the renderer?

WebBundleURLLoaderFactory::CreateLoaderAndStart() is called in network::URLLoaderFactory which is created inside CorsURLLoaderFactory. So I think CORS and other security checks are done before returning a response to the renderer.


By the way, could you please let me know whether there is a way to restrict cross process method calls or not?

Daniel Cheng

unread,
Jan 15, 2021, 4:07:05 AM1/15/21
to Tsuyoshi Horo, Ken Rockot, chromium-mojo, webpack...@chromium.org, Kunihiko Sakamoto, Hayato Ito, Kinuko Yasuda
On Fri, Jan 15, 2021 at 1:01 AM Tsuyoshi Horo <ho...@google.com> wrote:
Hi.

It sounds like the network service is responsible for creating the WebBundleURLLoaderFactory. If I understand correctly, WebBundleURLLoaderFactory is an implementation of network::mojom::URLLoaderFactory and the network service owns the mojo::Receiver endpoint?

Yes. Correct.

> 1. How does a renderer request subresources? Isn't CreateLoaderAndStart() the only way?
> 2. If we're using a token / URLLoaderFactory to identify the bundle, what URLLoaderFactory is the resource request being sent through?

The requests for subresources inside the web bundles are sent to the network process as same as normal subresource requests.
The token is set in URLRequest.web_bundle_token_params.token, so the network process can return the subresource from the previously requested web bundle.
My idea is that if we can have URLRequest.web_bundle_token_params.web_bundle_url_loader_factory, we can stop using the token.

> It sounds like we're not using the WebBundleURLLoaderFactory directly, and the token/ URLLoaderFactory would only be used to tag the request so the network process knows to serve it from the web bundle?

Yes. Correct.

> 3. Don't other URLLoaderFactory implementations in the network service need to perform CORS checks in the network service? Could WebBundleURLLoaderFactory be implemented similarly and ensure the URLLoaders created by WebBundleURLLoaderFactory perform security checks before returning a response to the renderer?

WebBundleURLLoaderFactory::CreateLoaderAndStart() is called in network::URLLoaderFactory which is created inside CorsURLLoaderFactory. So I think CORS and other security checks are done before returning a response to the renderer.


By the way, could you please let me know whether there is a way to restrict cross process method calls or not?

There is not. I think what I'm not understanding is--why can't the renderer just use WebBundleURLLoaderFactory directly? That seems simpler than passing along a token or message pipe to try to identify the endpoint in question.

Daniel

Tsuyoshi Horo

unread,
Jan 17, 2021, 7:57:16 PM1/17/21
to Daniel Cheng, Ken Rockot, chromium-mojo, webpack...@chromium.org, Kunihiko Sakamoto, Hayato Ito, Kinuko Yasuda
Hi.


> There is not. I think what I'm not understanding is--why can't the renderer just use WebBundleURLLoaderFactory directly? That seems simpler than passing along a token or message pipe to try to identify the endpoint in question.

Thank you for the answer.  This is because we don’t want to send CORB-protected cross-origin resources in the web bundles to the renderer processes.

Daniel Cheng

unread,
Jan 18, 2021, 1:12:42 AM1/18/21
to Tsuyoshi Horo, Ken Rockot, chromium-mojo, webpack...@chromium.org, Kunihiko Sakamoto, Hayato Ito, Kinuko Yasuda
On Sun, Jan 17, 2021, 16:57 Tsuyoshi Horo <ho...@google.com> wrote:
Hi.


> There is not. I think what I'm not understanding is--why can't the renderer just use WebBundleURLLoaderFactory directly? That seems simpler than passing along a token or message pipe to try to identify the endpoint in question.

Thank you for the answer.  This is because we don’t want to send CORB-protected cross-origin resources in the web bundles to the renderer processes.


Right, but can the URLLoaders that are created by WebBundleURLLoaderFactory::CreateLoaderAndStart perform these checks? I feel like that would be what I would expect the implementation to do.

Tsuyoshi Horo

unread,
Jan 18, 2021, 2:28:46 AM1/18/21
to Daniel Cheng, Kunihiko Sakamoto, Hayato Ito, Kinuko Yasuda, Ken Rockot, chromium-mojo, webpack...@chromium.org

Ah, yes. Now I understand what you mean. That sounds reasonable to me.

@ksakamoto, @hayato, @kinuko
What do you think about this?
I may have overlooked something in the design discussion held while I'm away. 



Kinuko Yasuda

unread,
Jan 18, 2021, 9:20:56 PM1/18/21
to Tsuyoshi Horo, Daniel Cheng, Kunihiko Sakamoto, Hayato Ito, Ken Rockot, chromium-mojo, webpack...@chromium.org
CORB checks are done in the similar way as others in Network Service (similarly as CORS), so I don't think that's something that prohibits us from the direction.  Technically both seem to work and it looks it's more about pros/cons discussion.  Using the same URLLoaderFactory allows most of the existing code to just work transparently, but the race issue might make the pros/cons calculation different.

The security property I'd think that its own URLLoaderFactory design should add/address is to have the broker / dispatch code in the browser process, so that its trusted parameters can be filled in a trusted way, and that'll need additional plumbing in the browser and renderer side, but that's probably it in my impression.

Daniel Cheng

unread,
Jan 18, 2021, 9:46:24 PM1/18/21
to Kinuko Yasuda, Tsuyoshi Horo, Kunihiko Sakamoto, Hayato Ito, Ken Rockot, chromium-mojo, webpack...@chromium.org
Doesn't reusing the same URLLoaderFactory require plumbing a new token though? Or do we already have that token and it's used for handling other cases as well?

I do feel like if we have to pass an extra token, then it really feels like it's the same amount of work to use a different URLLoaderFactory—but the latter feels more direct and similar to how we have things like URLLoaderFactoryBundle that partition URLLoaderFactory by scheme.

Daniel

Kinuko Yasuda

unread,
Jan 18, 2021, 9:54:29 PM1/18/21
to Daniel Cheng, Tsuyoshi Horo, Kunihiko Sakamoto, Hayato Ito, Ken Rockot, chromium-mojo, webpack...@chromium.org
What I (quickly) imagined was to pass an interface that can mint a new URLLoaderFactory (for each Bundle) from the browser process to the renderer process.  And the renderer probably needs to be able to distinguish and use the right factory.

Hayato Ito

unread,
Jan 18, 2021, 10:52:23 PM1/18/21
to Kinuko Yasuda, Daniel Cheng, Tsuyoshi Horo, Kunihiko Sakamoto, Ken Rockot, chromium-mojo, webpack...@chromium.org
To Tokyo webbundle folks,

I think we can discuss pros and cons in Today's sync meeting. Let's discuss and summarize pros and cons. It's still a bit unclear for me how a passed URLLoaderFactory is managed in network service. I hope we can make it clear in the meeting.
--
Hayato

Łukasz Anforowicz

unread,
Jan 21, 2021, 3:53:59 PM1/21/21
to chromium-mojo, Hayato Ito, dch...@chromium.org, Tsuyoshi Horo, Kunihiko Sakamoto, Ken Rockot, chromium-mojo, webpack...@chromium.org, Kinuko Yasuda
FWIW, I've tried to understand this problem after Daniel brought it to my attention.  I don't see blockers for replacing the token with a URLLoaderFactory:
  •  As you said above, the renderer would give the NetworkService a `PendingRemote<URLLoaderFactory>` when requesting the bundle.  When fetching subresources, the renderer would recognize/map a URL as one that is contained in a bundle and then use the right URLLoaderFactory.  Similarily, the right bundle-specific URLLoaderFactory can be sent in BeginNavigation IPC (instead of sending a token).
  • I don't understand why there might be requirement to "make WebBundleURLLoaderFactory::CreateLoaderAndStart() callable only from the same process".  I think that it is okay to pass the `Remote<URLLoaderFactory` A) to the renderer that will load subresources / the renderer that asked for the bundle (assuming that CORB will be applied and will filter out HTML/JSON/etc responses) and B) to the browser process (for navigations of subframes).  I don't see a security problem with A nor B - there are no security boundaries crossed (navigation has to use the factory, subresource bodies need to be present in the renderer).  We should be careful not to pass the `Remote<URLLoaderFactory>` to other, unrelated renderer processes (and this doesn't seem that difficult).

Daniel Cheng

unread,
Jan 29, 2021, 12:55:56 AM1/29/21
to Łukasz Anforowicz, chromium-mojo, Hayato Ito, Tsuyoshi Horo, Kunihiko Sakamoto, Ken Rockot, webpack...@chromium.org, Kinuko Yasuda
Hi all,

What was the outcome of this discussion? Were there notes somewhere?

I saw https://chromium-review.googlesource.com/c/chromium/src/+/2543726 and it looks like we're implementing it with an UnguessableToken? Would it be hard to switch this to use a URLLoaderFactory later? I'm asking this, because otherwise, we need to implement yet another navigation/subresource path for MHTML when we migrate it to a URLLoaderFactory later...

Daniel

Hayato Ito

unread,
Jan 29, 2021, 1:16:40 AM1/29/21
to Daniel Cheng, Łukasz Anforowicz, chromium-mojo, Tsuyoshi Horo, Kunihiko Sakamoto, Ken Rockot, webpack...@chromium.org, Kinuko Yasuda
The summary of the outcome of the discussion is:

- No one objects to switching the current implementation (UngussableToken) to use URLLoadingFactory.
- However, we don't have a plan to switch at least by M90 branch cut. We are now prioritizing other tasks so that we can start OT for M90. For OT, we use the current UngussableToken-based approach.
- We are happy to consider switching after M90. The details are TBD.

 
--
Hayato
Reply all
Reply to author
Forward
0 new messages