Security

David M. Lloyd david.lloyd at redhat.com
Thu Sep 17 15:34:37 UTC 2015


On 09/17/2015 09:56 AM, mark.reinhold at oracle.com wrote:
> 2015/9/11 10:15 -0700, forax at univ-mlv.fr:
>>                 While this change may improve the security, it's a
>> backward incompatible change is not strictly required to support
>> modules it's more an enhancement of the current security model and i
>> don't think it's a good idea to mix it with the introduction of the
>> module support.
>
> This is not an enhancement of the security model per se (which would,
> anyway, be beyond the scope of this JSR).  This change is, rather, in
> service of the strong-encapsulation goal (which does, of course, help
> ensure security).

I think this assertion should be substantiated with some examples.

While strong encapsulation is good in terms of design principles, to me 
it's only evident that this somehow leads to better security in the most 
hand-wavy possible way (in particular, as it relates to this specific 
mechanism).  On the other hand, there is strong evidence to support the 
assertion that enhancing the security model in any way immediately leads 
to new CVEs.  The more behavioral rules there are in place, the more 
vectors for exploitation will appear.

So if you, like me, define "security" as "resistance to exploitation by 
untrusted code", I fail to see how this kind of change can possibly be 
an improvement over the status quo (particularly, security between class 
loaders).  If you add in the inevitable breakage in real-world software 
that will result, the picture looks even worse.

> To truly support strong encapsulation would require taking setAccessible
> away completely.  I think that's desirable in the (very) long term, but
> it would break too much existing code in the near term.

I don't agree that this is true.  Encapsulation is really a social 
construct; while accessibility can be used to create and enforce 
encapsulation-justified rules, it doesn't *have* to.  You do need some 
kind of back door, no matter what, or else you severely limit the power 
and capability of the platform (as evidenced by the widespread usage of 
the reflection back door by many widely-used frameworks generally 
considered to be powerful and capable).

If encapsulation as a design principle is the goal, then simple 
isolation rules between modules (as between unrelated class loaders) has 
already been proven to be highly effective.  The relationship between 
this new encapsulation rule and security, on the other hand, has yet to 
be shown.

In this light, I don't see how these changes cannot be considered a 
modification of the security model just because they ride in on the 
coattails of a new abstraction.

> The present behavior of setAccessible is a compromise, one of several
> possible choices.  For types in unnamed modules (e.g., on the class path)
> it behaves exactly as it does in SE 8, since types in unnamed modules are
> always in exported packages.  What a couple of early testers have run up
> against is the fact that if a type is in an unexported package in a named
> module (e.g., in a Java SE or JDK module) then setAccessible fails [1].
>
> Some other consequences of this particular choice:
>
>    - If you want to use a framework that uses setAccessible upon members
>      of Java SE or JDK modules (e.g., some third-party serializers) then
>      you'll have to use the command-line -XaddExports option to grant them
>      the necessary access.
>
>    - If you put code into a module, and you want to use a framework that
>      uses setAccessible upon members of that module, then the module must
>      export the packages containing the declaring types of those members,
>      even if those types are not public.  (Qualified exports can be used
>      to limit, by name, the modules to which such packages are exported.)
>
>    - The only way to really hide something in a module is to put it in
>      an unexported package (but at least there's one way to really hide
>      something!).  If it's a package-private or private nested member in
>      an exported package then setAccessible can still be used to break
>      into it.
>
> While working on the prototype we did consider some alternatives:
>
>    (a) Limit setAccessible to require the caller to have access to the
>        target member's declaring type, consistent with the rest of the
>        core reflection API.  (The problem with this approach is that it
>        does not allow setAccessible to be used on package-private types.)
>
>    (b) Limit setAccessible so that both the caller and the target must be
>        in the same module.  (This would break almost as much existing code
>        as taking setAccessible away completely.)
>
>    (c) Variants of (a) or (b) which add a way to grant specific modules,
>        via a command-line option, the power to use setAccessible as it
>        exists today.
>
>    (d) Do not change the behavior of setAccessible in SE 9, but deprecate
>        it with an eye toward removing it in a future release, after
>        supported (and safer!) replacements for known use cases have been
>        defined.
>
>  From one of your later messages, I'm guessing that you'd be content with
> this last option.

I would be - if it could be shown that a suitable and effective 
replacement could be put in place, and if the future release were far 
enough in the future in order to mitigate the massive amount of breakage 
in existing reflection-based code, and if it could be shown that there 
are material benefits to doing so.

>>                  More philosophically, every libraries that propose an
>> abstraction that hide underlying dirts provides an escape hatch, the
>> reflection API is one of such hatch of Java the language allowing to
>> bypass the typechecker and the security sandbox. Trying to close the
>> hatch will just make people to open holes in the nearby wall with
>> hacks that are less secure and that may even compromise the integrity
>> of the plateform.
>
> Philosophically, I can't agree with this.  If encapsulation is to mean
> anything then it should not be possible to break it solely from within
> the language itself.  Enabling such powers via an external, second-class
> mechanism such as a command-line option or a debugger is fine, but the
> history of Java has shown that if it's easy to break encapsulation then
> people will do so, increasing everyone's maintenance burdens over the
> long haul.

I think this may be a somewhat narrow view.  People break encapsulation 
when they need a capability that cannot be provided another way.  Now 
the JDK, unfortunately, historically contains very many "goodies" and 
bits of useful functionality that users want access to, so it is a 
disproportionately popular target for such breakage, but apart from 
accessing JDK internals, I believe that the use cases for breaking in 
through the security model are legitimate and should be allowed to 
adequately privileged code.  Using an appropriate security model, it is 
not difficult to ensure that such powers are not exploited (though while 
in practice it is more difficult due to a variety of factors, I do not 
believe those factors are directly related to this mechanism but rather 
to exceptions, special "holes", and other technical debt that exists in 
the JDK itself for historical or other reasons).

> [1] It throws an exception that does not extend SecurityException, which
>      breaks some existing code in other ways, but that's a separate issue.

Yep I'm personally not too concerned with these issues (which are 
generally easily addressed); the focus of the discussion lies elsewhere, 
in my view.

-- 
- DML


More information about the jpms-spec-experts mailing list