Alternative mechanism for reflective access control (#ReflectiveAccessToNonExportedTypes / #AwkwardStrongEncapsulation)
David M. Lloyd
david.lloyd at redhat.com
Wed Sep 28 18:21:11 UTC 2016
On 09/28/2016 07:01 AM, Alan Bateman wrote:
> On 28/09/2016 10:37, Gunnar Morling wrote:
>> I don't think that is what those folks asking about using the SM had
>> in mind.
>> Rather, the idea would be - IIUC - to grant code in module B (say an
>> ORM tool) reflective access to non-exported (and of course exported)
>> types in module A (say a module with entities) by default. If needed,
>> the code in B would then use setAccessible() for making private
>> members in A accessible before invoking them, allowing it to obtain
>> the entity state. This is where the SM is part of the picture: if in a
>> given environment the user wants to restrict who may call
>> setAccessible(), they could use the SM for it, with a fine grained
>> policy, e.g. allowing the call only to the ORM module.
>> I.e. ReflectiveAccessToNonExportedTypes would be granted by default,
>> only if an SM is enabled at runtime, actions to suppress accessibility
>> checks would be subject to the current security policy.
>> This is not to say that I'm behind this idea, I just felt it hasn't
>> been discussed in the way it may have been meant.
>> I can see though how JDK devs and library authors want to prevent
>> access to private code in their modules at all, hence relying on the
>> SM to be enabled at runtime is not an option to address that requirement.
> The original question mentioned "reflective access" and we've said, has
> always been specified to do the same access checks as the Java Language
> and VM.
> On setAccessible, then it wouldn't be hard to have setAccessible
> implement fine grain permission checks but not clear how useful this is
> given that the SM is opt-in and not widely used. Having setAccessible
> ignore module boundaries (assume no SM) goes against the goal of strong
> encapsulation and of course makes #AwkwardStrongEncapsulation a lot worse.
> In general then I think that we need to find ways to reduce the use of
> setAccessible over time. We really need a long term plan to degrade,
> deprecate and eventually remove it. This would of course mean working on
> some challenging problems and use-cases.
> So what would the alternative to setAccessible be? It would be nice if
> the framework libraries (you mention ORM tools and maybe the Hibernate
> ORM devs could be the guinea pig) would start to make use of the "new
> reflection API" that is java.lang.invoke. So rather than bypassing
> access checks with legacy core reflection then they would instead use
> MH.Lookup objects as capabilities. Think code in a consumer module
> creating a Lookup object with the appropriate lookup class + mode that
> it cooperatively hands to the framework. This puts the access check in
> the consumer module so that the frameworks don't need to break in. This
> direction isn't without challenges of course as there may be
> initialization issues to deal with. It might, for example, involve
> injecting helper code into a submissive consumer module when there isn't
> explicit initialization. John Rose has good write-ups in JIRA with ideas
> in this area.
Using Lookups are very likely to be an essential piece to solving the
security conundrum. It is not without its problems though at present.
Bytecode injection in particular only works in a container setting, for
example, and only for wholly managed modules. Relying on cooperative
code is also a comparatively onerous burden to place on regular
application developers, and of course few if any existing frameworks and
standards are set up in this way so it doesn't help the migration story any.
More work definitely needs to be done in this area before we can really
say that it's a viable alternative to setAccessible().
More information about the jigsaw-dev