Exported resources

Bryan Atsatt bryan.atsatt at oracle.com
Mon Jun 4 21:42:46 PDT 2007


Hey Stanley,

Yeah, sorry about the flood of mail; I've had a little time to catch up.

You seem to have a JRE-centric perspective here ;^). Third-party
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.

And signing a jar by itself doesn't grant any additional permissions, it
simply enables verification of the contained classes. Some environments
may support UI to grant additional permissions, of course, but that is
orthogonal.

But, lets leave aside the whole grant issue for now, and assume that we
can grant permissions as needed to access module private resources.

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?

// Bryan

Stanley M. Ho wrote:
> Hi Bryan,
>
> I would like to get closures on a few open issues first, so my responses
> will be limited to those threads rather than all the new threads that
> have been started recently.
>
> Bryan Atsatt wrote:
>> Hi Stanley,
>>
>> Sorry if I'm not being clear. Let me try to summarize:
>>
>> - I *do* want 277 to support private (non-exported) resources, but
>
> Good.
>
>> - I do not think we should use permissions as the enforcement mechanism.
>>
>> - I believe the 'caller-class-is-member' enforcement mechanism is
>> sufficient, and
>>
>> - I do realize that this means ResourceBundle.getBundle() (or similar)
>> will fail to find private resources; these must be made public.
>>
>> Let me give more detailed reasoning for this position...
>>
>> You are of course correct that a class loader is free to add permissions
>> to any class by assigning a ProtectionDomain with those permissions
>> during defineClass(). (Let's call these "hard-wired" permissions.)
>>
>> So permission to access private resources could easily be hard-wired for
>> other classes *in the same module*.
>>
>> To this point, there really isn't any meaningful difference between
>> using permissions or using my approach: both allow module classes to
>> directly access their private resources.
>>
>> But if we want to grant that same permission to *any* class outside of
>> the module, it gets far more interesting. And it is this problem that
>> I'm concerned with.
>>
>> For ResourceBundle.getBundle(), for example, to access a private
>> resource, we must grant permission to the *ResourceBundle* class. And
>> how do we do that?
>>
>> We could hard-wire permission for ResourceBundle, but... what about
>> ServiceLoader? Ok, so let's just hard-wire permission for any JRE module.
>
> The system classes are granted with all permissions, so they will have
> sufficient permissions to access the private resources in a module. I
> don't think this is a real issue.
>
>> Problem solved? Not at all: what about all the non JRE frameworks out in
>> the world that need the same kind of access?
>
> I agreed that using other frameworks might be a concern.
>
>> Clearly we cannot hard-wire permissions for these. So now we need to use
>> policy file entries to do so. We could of course take this approach, but
>> it either leaves some poor admin running around to update policy files
>> as things break, or some fancy mechanism to grant access during
>> framework module install. Ick.
>
> If the framework is bundled as part of your module, it will have the
> same set of permissions as the other code in your module, so it will
> have sufficient permissions to allow your code to access the private
> resources. If the framework is deployed through the typical mechanisms
> (e.g. extension classpath, etc.), it will have all permissions, hence it
> will also have sufficient permissions to access the private resources.
> Further, if the framework is deployed as another module in one of the
> system's repositories, it will likely have all permissions to allow your
> code to access the private resources in your module as well. Moreover,
> if the framework JAR/module is signed and is trusted, the system will
> typically grant all permissions to the code in the framework when the
> code is loaded. In other words, there is no need to explicitly grant
> permissions in most scenarios.
>
> The scenario where this may be an issue is when the framework is
> deployed through some other means (e.g. other modules in a
> URLRepository, JARs in custom classloaders) *and* the framework is
> unsigned (or if the framework is signed but not trusted for some
> reasons), it may not have sufficient permissions to allow your code to
> access the private resources through the framework API. However, it is
> unclear to me if there are frameworks deployed like this for this issue
> to become a real problem. Do you have any example that shows this is a
> real problem?
>
>> And, hard-wired or not, permissions *are* a friend model.
>>
>> But 294 is not likely to provide such a model for classes.
>>
>> So, even if we hard-wire permission for ResourceBundle to access a
>> private resource, how is it going to access a private ListResourceBundle
>> class? Or how will the ServiceLoader gain access to the service provider
>> class? How will third-party frameworks solve this problem?
>
> In a typical classloader, all public and private classes are visible
> (return from loadClass()) externally but only the public ones are
> accessible (invoke without access control failure). When a module uses
> the ResourceBundle API to load the ListResourceBundle from the module
> itself, the ResourceBundle API only loads the class from the module
> classloader and the class is returned to the code in the module for
> actual access. ServiceLoader works in similar way that the ServiceLoader
> only loads the service-provider class but it's the actual caller who
> accesses the class. Therefore, I don't think there is a real problem here.
>
>> It is hard for me to see how all this complexity is justified, simply to
>> hide resources that have never been hidden before.
>>
>> This doesn't mean there is no place for private resources! It just means
>> that they can only be used by the module classes themselves. And this is
>> still a very valuable feature: developers can restrict access to
>> resources that are strictly implementation details.
>
> I don't think the security permission approach is actually complex, and
> I do have two concerns with the approach you suggested:
>
> 1. A module has to export its own supposed-to-be-private resources in
> the same module in order to use the ResourceBundle API to load them.
>
> 2. It does not allow private resources in a module to be accessed
> externally by any mean.
>
> My main concern is around #1 'cause it doesn't sound right to me - I
> think a private resource should stay non-exported. #2 is an issue if we
> want to support a way for external code to access the private resources.
> There is already a setAccessible() method that allows you to override
> the default access control and to access private methods/fields in
> classes, so I think it would also make sense to have a way for external
> code to access the private resources when necessary (e.g. debugging,
> diagnosis, etc.).
>
> - Stanley
>



More information about the jsr277-eg-observer mailing list