New proposal for #ReflectiveAccessToNonExportedTypes: Open modules & open packages
forax at univ-mlv.fr
forax at univ-mlv.fr
Wed Nov 2 13:06:35 UTC 2016
> De: "Peter Levart" <peter.levart at gmail.com>
> À: "Remi Forax" <forax at univ-mlv.fr>, "David M. Lloyd" <david.lloyd at redhat.com>
> Cc: jigsaw-dev at openjdk.java.net
> Envoyé: Mercredi 2 Novembre 2016 11:31:04
> Objet: Re: New proposal for #ReflectiveAccessToNonExportedTypes: Open modules &
> open packages
> 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?
The idea was if the impostor wins, you will get an exception when the legit framework will try to request the access, and obviously, this is the weak point of this variant.
> 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.
A nice idea,
so iteration 4, you have to provide a lookup of a class inside a module that provide an implementation to the interface used when granting the access
https://github.com/forax/access-broker
So a code of application using a framework will use @GrantAccess (i've put the annotation on the module of the app just for fun)
https://github.com/forax/access-broker/blob/master/src/my.jpa.app/my/jpa/app/Bean.java
https://github.com/forax/access-broker/blob/master/src/my.jpa.app/module-info.java
and the implementation of the framework will use the AccessBroken to get access to private members of the application code
https://github.com/forax/access-broker/blob/master/src/org.hibernate.jpa/org/hibernate/jpa/EntityManagerImpl.java
In that case the AccessBroker is the same as the previous iteration but uses Class instead of String to allow a framework and check that the class that requires a privileged access is in a module that implement the interface of the spec
https://github.com/forax/access-broker/blob/master/src/java.base/java/lang/invoke/AccessBroker.java
> 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
regards,
Rémi
>> ----- 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