Stanley M. Ho wrote:
Hi Bryan,

Bryan Atsatt wrote:
...
frameworks/libraries are precisely what a module system is for: to allow
their clients to *avoid* bundling the jars. And they aren't likely to be
deployed as extensions, either; not when there's this nice repository
model. Consider Spring. Or any of the hundreds of other third party
frameworks/libraries out there. We *want* these to be deployed as
normal, separate modules.

I agreed. My point was that in many cases, these frameworks/libraries
would be deployed into the repository and loaded with all permissions at
runtime,

That last phrase seems like a huge leap to me. How exactly would this
grant all permissions? And, even if it did, it seems like an *extremely*
large security hole!

(But, again, I don't feel the need to dwell on the grant issue at the
moment--we have bigger fish to fry.)

so this should not be an issue even they are deployed as
normal, separate modules.

There is a much bigger issue, which is that this whole model falls apart
simply because we can't grant this type of "friend" access to module
private classes...

Your description of how ResourceBundle or ServiceLoader accesses the
class contains a big assumption, one that *could* be correct for such
JRE code, but is almost certainly wrong for third-party code.

These types of frameworks call Class.forName() or loader.loadClass().
And then they call either Class.newInstance() or
Constructor.newInstance().

Regardless of whether or not they invoke any other methods, JSR 294 will
require an access control check at the point of instantiation, extending
those it performs today. Look at how Class.newInstance() and
Constructor.newInstance() both use:

    Reflection.ensureMemberAccess()

This is the logical point at which to inject the new module private
access control check.

Could this be made to succeed for JRE callers? Of course (but it
wouldn't be right, IMO).

But, more importantly: it won't, and cannot, succeed for third-party
callers without some sort of friend model for classes. Which isn't on
the table.

So, again, if we're not going to do this for classes, why should we do
it for resources?

Sorry, I still don't think I fully understand your point. From my
perspective, the access model for exported classes and exported
resources are orthogonal. I agreed that it would be nice to have some
symmetries between them, but I think we already concluded why this is
not feasible because of their fundamental differences. The fact that
this is not how we support classes today doesn't mean we could not do it
for resources.

Perhaps it would help to pull out the following question you had couple
emails back for our discussion:

Bryan Atsatt wrote:
 > And what about the mismatch issue I brought up? Lots of existing
 > frameworks use the "services" pattern, in which:
 >
 > 1. A well known resource name is used in a getResource() call.
 > 2. The resource contains a string naming a provider class.
 > 3. The provider class is loaded using Class.forName().
 >
 > This is a simple but very powerful pattern, but it requires that *both*
 > the resource and the named class be accessible to the framework. If we
 > require a permission grant for the resource, but not for the class, it
 > will be very easy to get access to one and not the other. Is it really
 > worth opening up this potential headache to enable a friend model for
 > resources?

In today's model, if the resource is available, #1 will always succeed.
If the provider class is available, then #3 will also succeed, and
whether the class is accessible will be determined by the JVM. The
entire "exported resources" issue is basically around the behavioral
change in #1; this is orthogonal to #2 and #3, and I think we should
ignore the entire "exported classes" issue for the moment to keep this
discussion focus.

That said, I realize that we might have been thinking about two very
different use cases (correct me if I misunderstand you) here:

a. Some service-related frameworks (e.g. ServiceLoader) need to retrieve
resources like META-INF/services/<service-provider> from the module
classloader.
b. A module uses the ResourceBundle APIs to retrieve property-based
resources or list-based resources from its own module.

For (a) alone, I would agree with you that this kind of resource might
simply be exported. In fact, I don't think this should even be
considered a private resource because its content is intended for
external consumption.

For (b), I don't think it makes sense to require a module exporting the
private resources for its own consumption, and this is where I hope the
security permission approach would help to make it work.

Suppose we say that resources like (a) should be exported while
resources like (b) should remain private (and we'll use the security
permission approach to allow module to access its own private
resources), do you think you can live with this?

It isn't just me that can't live with it :^). You are correct that
private *property-based* resources could be retrieved this way, but
incorrect about *list-based* resources.

"List-based" resources are... *Class* instances. Specifically, they are
subclasses of ListResourceBundle. They must be loaded and instantiated
by ResourceBundle.

If ListResourceBundle subclasses are module private,
ResourceBundle.getBundle() will fail. And we have no mechanism to grant
access.

// Bryan


- Stanley

Reply via email to