My position on module security/access control
mark.reinhold at oracle.com
mark.reinhold at oracle.com
Thu Dec 10 01:29:45 UTC 2015
2015/11/18 8:10 -0800, david.lloyd at redhat.com:
> I wanted to summarize my position on module security and access control,
> so that all my thoughts are in one place instead of scattered across
> various threads.
>
> The first point I want to make is that I think that the idea of having
> public classes that are not public is a red flag. If a class and member
> is public, it should always be accessible to everyone regardless of who
> imports what module. There should only be one access control mechanism
> in the language. Users already seem keen to find ways to break out of
> the Jigsaw export-based restrictions and I think this is an indicator
> that, while expedient, the Jigsaw approach is far from ideal. In
> addition I think this is an essential step towards the ultimate goal of
> removing the dreaded setAccessible() method; if frameworks cannot even
> access public members then they will never be able break away from using
> reflection as a back door. The concept being established here is the
> ability to have a public class which is not exported but is still
> accessible to anyone.
If I understand correctly, you're proposing that a public type in a
non-exported package be accessible via reflection, but not via static
references in source or class files. (There would still have to be some
way to declare whether the public types in a package are exported for
use in static references, but how that's done is a different issue.)
You argue that "public" should always mean "public", yet your proposal
would change the meaning of "public". To tell whether something marked
"public" is accessible statically from outside a module, a developer
would still have to consult the file (in whatever format) in which the
relevant package is declared to be exported (or not). "public" inside
a module would still have a different meaning than "public" outside a
module, and a different meaning from what "public" meant in Java 8.
So, do you want to preserve the meaning of "public", or not?
Your proposal would, further, introduce an asymmetry between access
control in the language and the VM vs. access control in the reflection
APIs. With the exception of escape hatches such as setAccessible, the
reflection APIs have always worked in exactly the same way as the
corresponding static constructs.
Your proposal would address the issue of making it easier for frameworks
to migrate to modules, but it is not the only approach to that problem
(about which more later).
> The second point is around module privacy. It is clear that
> (language-wise) we need an access level that is module-private. Given
> the relative uselessness of package-private accessibility in the module
> world, I propose that any reference to a default-access-level member in
> a Java 9 class should be considered to be a module-private access, not a
> package-private access, in both javac and the JVM. The protected access
> level should be similarly widened. ...
If a Java 9 class is not inside a module, i.e., it's on the class path,
then what is the default access mode? If it's package-private then it
would work differently than from within a module. If it's private to the
unnamed module in which all classes found on the class path are defined
then it would work differently from any pre-9 classes on the class path.
Either outcome is likely to confuse people.
If a Java 8 class is inside a module then I assume the default access
mode would remain package-private. (We expect this to be common, with
modular JAR files intended for use on the module path in 9 and on the
class path in earlier releases.) Taken with the proposal in your first
point then all public pre-9 classes would be available via the reflection
APIs, regardless of whether their packages are exported. The only way to
encapsulate such classes, therefore, would be to upgrade them to Java 9,
at which point the modular JAR would no longer work on earlier releases.
This limitation would add complexity to the migration story.
At a higher level, I agree that the package-private access mode has
proved to be of limited utility. It has, however, been a fundamental
part of the language and the VM from the very beginning. To widen it in
such an incompatible fashion now, after twenty years, would make it more
difficult to migrate existing code to modules and would risk enabling
further security vulnerabilities.
The design as proposed, by contrast, narrows rather than widens an
existing access mode (public), so security is not an issue, and it
narrows that mode in a way that's relatively easy to explain -- just
consult the relevant module declaration.
> The third point is around "friend" modules. It seems clear that we have
> a requirement (which can be extrapolated easily from the document) that
> some modules need the ability to provide selective access to nonpublic
> members to other modules. ...
There's no need to extrapolate, since we captured this requirement
explicitly [1].
(I don't see a specific proposal here, so I have no further comments
on this point.)
> The fourth point relates to ServiceLoader. If ServiceLoader has a
> unique and special blessing to bypass the access mechanism, then we've
> failed to design an adequately flexible (and secure) access control
> mechanism. By implementing the three points above, ServiceLoader no
> longer needs to be a special citizen, because all service implementation
> classes are public (as they are today, and as they should be). A user
> could implement ServiceLoader in unprivileged code and it would work
> with no special trapdoors.
I agree that, as a proof point, it'd be nice to implement ServiceLoader
using only reflective operations that are also available to non-system
modules. ServiceLoader is, after all, just a small kind of framework.
Services are bound and provisioned by the module system itself, however,
so ServiceLoader does, of necessity, have some special privileges, and I
don't think that can be avoided.
- Mark
[1] http://openjdk.java.net/projects/jigsaw/spec/reqs/#qualified-exports
More information about the jpms-spec-observers
mailing list