My position on module security/access control
mark.reinhold at oracle.com
mark.reinhold at oracle.com
Mon Dec 14 19:45:13 UTC 2015
2015/12/10 8:00 -0800, david.lloyd at redhat.com:
> On 12/09/2015 07:29 PM, mark.reinhold at oracle.com wrote:
>> 2015/11/18 8:10 -0800, david.lloyd at redhat.com:
>>> ... 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.
>
> Not "will", "does". This is the current status quo. Types that are not
> visible by a class loader cannot be linked against; this doesn't change
> the definition of "public", which has been well-established since the
> dawn of Java. Today I can instantiate public types and invoke public
> methods on them regardless of what class loader they live in, yet I can
> restrict linkage to such types, simply by arrangement of class loaders.
> This is all possible and expected behavior today and I propose that
> these concepts be leveraged, not changed.
>
>> So, do you want to preserve the meaning of "public", or not?
>
> Yes, I want to preserve it exactly with no changes to the JLS or JVM
> specification.
Okay, I think I'm starting to get it, but in your statement
>>> The concept being established here is the
>>> ability to have a public class which is not exported but is still
>>> accessible to anyone.
the clause "is not exported" suggests that some public types are
"exported" and some are not. I read this to mean that public types would
still be subject to some sort of access control based upon some kind of
export declarations, but only for static linkage. If that's not the
case, then what's the distinction between "not exported" and "exported"?
>>> 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.
>
> Class path private; see my other mail.
Okay. Suppose that I upgrade a pre-9 component into a module using this
approach, and ship it as a modular JAR file so that it can be used both
as a module and on the class path. If it's used on the class path then
any types that formerly were package-private are now accessible to all
other code on the class path, regardless of whether that other code was
compiled with 9 or with an earlier release, right?
>> 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.
>
> It would add no complexity, because this is the status quo today.
>
> Public types are universally accessible today, and I do not propose that
> to be changed. No application will be worse off security-wise, but they
> will have a path to improve their encapsulation over time.
Yes, they would have a migration path, but a very long one.
The only way to encapsulate an existing public type within a module would
be to change its access mode to the default and compile it -target 9. As
a consequence the resulting class file would only be usable on Java 9 and
later releases. The maintainer of an existing library would only be able
to convert that library into a module after all existing users upgrade to
Java 9. If history is any guide then, for a popular library, that's
likely to be many years after Java 9 ships.
Is that what we want?
>> 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.
>
> I think this is objectively false. Existing code would continue to have
> the same encapsulation; only new code would have the expanded capability
> and only in reference to other new code.
What about references from outside a module? Would the default access
mode on a Java 9 type mean "module private" if the the code attempting
to access that type is itself compiled -target 9, and "package private"
otherwise?
- Mark
More information about the jpms-spec-experts
mailing list