On Fri, Jun 7, 2024 at 1:19 PM Ron Pressler <ron.press...@oracle.com> wrote:

>
> > On 6 Jun 2024, at 18:37, David Lloyd <david.ll...@redhat.com> wrote:
> >
> > Just bumping this one more time. I intend to start by opening a JIRA to
> add the two proposed methods to `ReflectionFactory`, and go from there. I
> guess that we might need a JEP for the proposed serialization restrictions,
> which is going to be considerably more involved, so I'm putting that off as
> a second step for now, pending further discussion.
>
>
> Hi.
>
> Seven years before the upcoming delivery of JEP 471 we [announced that the
> world of accessing JDK internals would be coming to an end](
> https://openjdk.org/jeps/260). Four years later, the JDK [started
> enforcing that](https://openjdk.org/jeps/403), but to give extra time to
> laggards who have not yet adapted to either refraining from accessing
> internals or instructing their users on the proper configuration of the JDK
> to allow doing so, we left some unsupported mechanisms in place to
> temporarily allow hacking around the restrictions until they can properly
> adapt. Now, three years later, we're starting the process of removing the
> temporary hacks, although we don't yet know how long the process should
> last.
>
> My first question is, how many more years do you think we should wait for
> libraries to finish the process by which they either refrain from accessing
> internals or instruct their users on the proper configuration that allows
> them to do so? Knowing how long we should wait for the libraries that have
> not yet finished their adaptation in the past seven years, and how far
> along they are in the process, could help inform how long we should wait
> until the actual removal of Unsafe.
>
> My second question has to do with the consideration that any serialization
> procedure should no longer bypass constructors (at least not without
> `--add-opens`, that is). I'd be interested to know about the difficulties
> serialization libraries have encountered in their process of migrating away
> from accessing internals and toward custom serializers for JDK classes,
> such as what public constructors are missing. This would help us identify
> what constructors we should add to support serialization that doesn't
> violate integrity.
>

The first thing to understand is that, unlike APIs in the JDK which may
only be implemented *in* the JDK, serialization is governed by a
specification [1]. This specification is still implemented by multiple
external libraries (including the OpenJDK ORB) as well as the JDK itself.
We aren't talking about libraries which invent some arbitrary kind of
serialization that requires unsafe object creation. We're talking about
libraries which conform to some or all of the serialization specification.

If you look back at the history of the discussion of serialization support
with regards to the JDK (which is referenced in the history of this email
thread), it was determined at the time of Java 9 that serialization would
be considered an exception to the rule of reflection restrictions, for
purely pragmatic reasons. Brian Goetz has talked frequently about the
limitations of existing serialization and how this impacts the platform in
various ways. He's also hinted at a future where some alternative
serialization mechanism exists which would presumably avoid the need for
the things we find in `ReflectionFactory`.

However we don't live in that world just yet. So, to answer your first
question ("How many more years...") I would start by modifying the
question. It's not about waiting for libraries; I think this greatly
mischaracterizes the problem. It's about waiting for OpenJDK to have a new
serialization mechanism. Until then, there is no replacement, so we're in a
holding pattern, like it or not. At best we're talking about small,
monotonic improvements which bring the platform closer to the goal of
integrity.

And so the answer to the first question is, "however many years it takes
for there to be an alternative, blessed OpenJDK serialization mechanism",
which presumably will involve both language and core library modifications.

For your second question, serialization *must*, by specification, bypass
constructors in the bottom part of the serializable class's type hierarchy
which correspond to serializable classes (most frequently this means
everything other than `Object` itself, but occasionally there are more
levels involved). If the platform were to drop that support, then all
serialization libraries would break, including the OpenJDK ORB, and the
specification would be unimplementable.

The serialization specification is not deprecated. Nor are the classes
which support serialization in the JDK. So in my opinion it would not yet
be appropriate to break these things. In order to tackle this particular
corner of platform integrity, those two problems must be addressed first
and foremost, and such an action would necessarily involve a deprecation
cycle on serialization as a whole.

I would also like to be very clear that I am not proposing adding a
mechanism to bypass constructors. Such a mechanism already exists on
ReflectionFactory, and has not been deprecated. I am proposing that any
caller which already has permission to do such a thing (and the other
integrity-bypassing things already provided by this existing API) should
also have permission to implement the remainder of the specification as
well (reading and writing fields), and to do so using this same API, rather
than Unsafe. In my view this is absolutely a monotonic step in the right
direction (i.e. towards platform integrity), since we're putting all of the
"offenders" into one bucket based on use case.

It might be shocking to discover the existence of these APIs if one wasn't
already aware of them. Presently, these APIs have essentially no
restrictions (ignoring security manager). They're even easier to access
than Unsafe, in fact. Therefore, I would suggest that another monotonic
improvement would be to restrict these APIs under a command-line switch,
like FFM is. In this way, we've unambiguously moved towards platform
integrity, at least as far as it is currently possible to do so. Nothing
would be enabled that isn't already possible, and some things that are now
possible would be unambiguously restricted.

Requiring `--add-opens` for ORBs/serialization probably isn't practical. It
is important to note that in addition to user classes, a large number of
JDK classes are serializable, spanning many packages. The burden on users
would be extremely high in this case. Is it really better for users to have
to list every package containing a serializable class, than to opt in
wholesale to saying "I want serialization to be allowed for module X"? We
don't (and wouldn't) do the same for native access for example, even though
a similar level of access is given. In fact one *could* use native access
to achieve the same thing, though this would be unfortunate on several
levels.

Another reason that requiring `--add-opens` would be inadequate is that
ReflectionFactory allows bypassing not just access restrictions, but also
certain provisions of the language and JVM specifications. Do we really
want any open package to be accessible in this way? Do we really want this
API to remain unrestricted? I would think that we would all agree that we
do not. Yet, deprecation is not yet indicated for the reasons given above.
I think restriction is the only answer here. And if this API is already
restricted, why not let the implicit contract of that restriction carry the
user's intent to grant serialization access to certain modules? Surely it
could be made clear what such access entails, much as we do for FFM which
has similar risks (and more).

[1]
https://docs.oracle.com/en/java/javase/22/docs/specs/serialization/index.html

-- 
- DML • he/him

Reply via email to