New proposal for #ReflectiveAccessToNonExportedTypes: Open modules & open packages
Peter Levart
peter.levart at gmail.com
Wed Nov 2 10:31:04 UTC 2016
Hi Remi,
On 11/01/2016 11:59 PM, Remi Forax wrote:
> Iteration 3,
> https://gist.github.com/forax/c08ce0a8dc88705bce97b17b63e7e2d5
>
> GrantAccess can now be put on a class, on a package or on a module, and give access to several frameworks by their names. Getting access to the lookup of a class is now a 2 steps process, first claim a framework name to get an AccessFacade and then through the AccessFacade, a framework have access to all classes annotated (directly or indirectly) by GrantAccess and allowing the framework. The facade corresponding to a framework name can only be requested once so how to store the FacadeAccess is let to the framework implementation and if a code try to sneak in and use a framework name it will be detected.
>
> Rémi
Hm, this variant requires the real framework code to race against its
impostor(s) for the access facade granted to a particular name. What if
an impostor gets it first?
In addition, I see a similarity of this approach to simply "opening" the
required packages of the "granting" module to a chosen "granted" module
(i.e. the "hibernate") in the granting module declaration. At least the
module name is harder to "spoof" as it is embedded in the module search
path layout. But I get the point. Instead of "hibernate", the granting
module could declare that it gives access to a "jpa" framework, which is
a more general name that several implementations could claim. But I
think that they should not simply claim the name and get it on a
first-comes basis. What about introducing a general registry of: (module
name -> access name) mappings controlled by privileged code or some
policy? The problem I see is a problem of choosing the names in general
as they get to be hard-coded in the code or declaration of the granting
module. Who chooses that "jpa" is the name of the JPA framework? Module
names are chosen by their authors. There has to be a module 1st and then
one can "require" it. OTOH there has to be a general agreement on the
"access name" among several authors of the modules that claim that name.
And this requires a central name registry like IANA. And that's not
something jigsaw is going to dive into.
I tried to tackle the issue from another perspective. If you ask
yourself what is common to all JPA framework implementations, for
example, then the answer is: they all implement the same API (in the
form of interface(s) or abstract classes). This API will usually be a
module by itself. 1st there has to be an API module with the agreed-upon
API and then the authors can produce implementation modules (hibernate,
eclipse-link, ...). So I thought that the name of the API module could
be used as the "access name" of the grant and every implementation
module that could prove it contains the implementation of this API would
inherit the grant.
Ideally, but not necessarily, services and providers could be leveraged
in the implementation. The mechanism could be "secured" on a
service-by-service basis using SecurityManager permission(s) like it is
done today (the security check is put into the constructor(s) of the
abstract service class) so that impostor(s) are kept back.
Regards, Peter
> ----- Mail original -----
>> De: "David M. Lloyd" <david.lloyd at redhat.com>
>> À: "Andrew Dinn" <adinn at redhat.com>, jigsaw-dev at openjdk.java.net
>> Envoyé: Mardi 1 Novembre 2016 21:00:35
>> Objet: Re: New proposal for #ReflectiveAccessToNonExportedTypes: Open modules & open packages
>> On 11/01/2016 11:02 AM, Andrew Dinn wrote:
>>> On 01/11/16 15:35, David M. Lloyd wrote:
>>>> On 11/01/2016 10:09 AM, Andrew Dinn wrote:
>>>>> There is a very easy way to provide tightly controlled access to a
>>>>> framework. Export access to e.g. jdk.internal.misc.Unsafe or e.g.
>>>>> java.lang.[invoke].MethodHandles to a nominated module provided by your
>>>>> framework then arrange for that module to hand out Lookups (or better
>>>>> MethodHandles) to framework code as and when they are needed via a
>>>>> private channel. You can do arrange that with a single addExports option
>>>>> on the command line and a very small amount of setup code to establish
>>>>> the private channel
>>>> I don't see how this is safer though. You're proposing to hand all the
>>>> keys (or none) to modules which don't need all the keys, whereas I
>>>> propose that a module should only gain incremental additional access on
>>>> a grant basis.
>>> No, I'm suggesting handing the keys to a single module provided by your
>>> framework -- which module will then use a key to open a room on demand
>>> for your code and your code only. That means the privilege can be
>>> granted using one command line switch with use of that privilege
>>> controlled by a runtime mechanism of your choosing.
>> Yes, however that means that I'm on the hook to make sure that the keys
>> aren't mislaid. And given the fact of open modules - which already
>> semantically grants me privileges - requiring a special command line
>> switch (which is itself undesirable) and custom code to enable those
>> privileges in the *preferred* manner (i.e. MethodHandles) seems
>> backwards when open modules would already grant me the ability to
>> utilize a much finer instrument albeit with the legacy approach (i.e.
>> reflection). It seems quite logical to extend this mechanism to the
>> preferred MethodHandle approach instead, and forget about Unsafe and
>> anything like it, which I think is in everyone's best interests in the
>> long term.
>>
>>>> At least Rémi's approach requires a specific grant and non-Unsafe
>>>> vector, though as I said the weaknesses (of his first approach) are that
>>>> the grant must come from the target class (programmatically) instead of
>>>> being a static declaration ("opens" is a natural fit for this if I
>>>> understand the proposal correctly). The other weakness is that it
>>>> requires class init, but that's purely a consequence of requiring a
>>>> programmatic grant as far as I understand.
>>> I did actually suggest a way of avoiding the use of Unsafe. You give
>>> your nominated module full reflective access to java.lang.invoke
>>> allowing it to create Lookup instances (it can actually just create a
>>> single all privileges lookup and use this to clone others). You don't
>>> need to insert a class into java.lang.invoke to do this. You simply add
>>> one exports directive on the command line.
>> That is marginally better, of course, but I think the rest of my
>> objections still stand against this argument.
>>
>>>> Rémi's newest Gist uses an annotation, which is closer but not quite on
>>>> the target IMO. An annotation cannot be module-deployment-agnostic in
>>>> the way that I outlined previously (hence
>>>> #IndirectQualifiedReflectiveAccess); ultimately accessibility
>>>> information ought to come from the module configuration itself.
>>> If you implement a module with the ability to hand out Lookup instances
>>> you can use whatever control model you like. For example, you might park
>>> an instance which hands out Lookups in a location only available to your
>>> framework or ensure that any caller asking for a Lookup belongs in a
>>> package implemented by your framework or whatever you want. the point is
>>> that once you have granted a class in our code the ability to create
>>> Lookups you can implement whatever runtime access control you want.
>>> Clearly,as John said, you need to do that responsibly.
>>>
>>> regards,
>>>
>>>
>>> Andrew Dinn
>>> -----------
>>> Senior Principal Software Engineer
>>> Red Hat UK Ltd
>>> Registered in England and Wales under Company Registration No. 03798903
>>> Directors: Michael Cunningham, Michael ("Mike") O'Neill, Eric Shander
>>>
>> --
>> - DML
More information about the jigsaw-dev
mailing list