RFR: JDK-8242888: Convert dynamic proxy to hidden classes
Peter Firmstone
peter.firmstone at zeus.net.au
Sun Apr 17 23:51:54 UTC 2022
We re-implemented a subset of Java Serialization, prior to the creation
Java serialization filters. Field types are read ahead from the stream
and invariant's validated during construction for failure atomicity (a
special constructor signature is used for deserialization), there are
also stream limits that require periodical stream resets, to avoid
million laugh style attacks. Also the source of the serialized data must
be authenticated before permission is granted for parsing serial data.
We also removed the ability to deserialize object graphs with circular
links.
This is used for an Remove invocation framework called JERI (Jini
extensible remote invocation). Serialization has been given a public
API to allow extensibility, that is to allow other serialization
protocols to be used via configuration, using a Serialization layer.
Service and service discovery architecture makes use of JERI, for
marshaling object parameters securely over the network, for remote
method calls on services, via remote proxy's.
The way that JERI serializes proxy's has changed significantly since
Jini, instead of marshaling proxy's, a bootstrap proxy (local code only)
is marshaled first, the client first authenticates the connection, the
bootstrap proxy is used to provide information for dynamic downloading
of any required jar files, or wiring of dependencies prior to the
unmarshaling of the service proxy. Unlike Java RMI, which uses
RMIClassLoading for class resolution, each Jeri Endpoint is assigned a
ClassLoader for class resolution during deserialization / object
unmarshaling, this solves the OSGi deserialzation class resolution problem.
https://github.com/pfirmstone/JGDMS/blob/trunk/JGDMS/jgdms-platform/src/main/java/org/apache/river/api/io/ProxySerializer.java
https://github.com/pfirmstone/JGDMS/blob/c1edf5892306f24f8f97f459f499dec54984b08f/JGDMS/jgdms-platform/src/main/java/org/apache/river/api/io/AtomicMarshalInputStream.java#L2263
https://github.com/pfirmstone/JGDMS/blob/c1edf5892306f24f8f97f459f499dec54984b08f/JGDMS/jgdms-platform/src/main/java/org/apache/river/api/io/AtomicMarshalInputStream.java#L853
Would be nice to do some testing with the changes.
--
Regards,
Peter Firmstone
0498 286 363
Zeus Project Services Pty Ltd.
On 18/04/2022 2:24 am, liach wrote:
> Convert dynamic proxies to hidden classes. Modifies the serialization of proxies (requires change in "Java Object Serialization Specification"). Makes the proxies hidden in stack traces. Removes duplicate logic in proxy building.
>
> The main compatibility changes and their rationales are:
> 1. Modification to the serialization specification: In the "An instance of the class is allocated... The contents restored appropriately" section, I propose explicitly state that handling of proxies are unspecified as to allow implementation freedom, though I've seen deliberate attempts for proxies to implement interfaces with `readResolve` in order to control their serialization behavior.
> - This is for the existing generated constructor accessor is bytecode-based, which cannot refer to hidden classes.
> - An alternative is to preserve the behavior, where the serialization constructor calls `invokespecial` on the closest serializable superclass' no-arg constructor, like in #1830 by @DasBrain.
> - My rationale against preservation is such super calls are unsafe and should be discouraged in the long term. Calling the existing constructor with a dummy argument, as in my implementation, would be more safe.
> 2. The disappearance of proxies in stack traces.
> - Same behavior exists in lambda expressions: For instance, in `((Runnable) () -> { throw new Error(); }).run();`, the `run` method, implemented by the lambda, will not appear in the stack trace, and isn't too problematic.
>
> A summary of the rest of the changes:
> 1. Merged the two passes of determining module and package of the proxy into one. This reduced a lot of code and allowed anchor class (for hidden class creation) selection be done together as well.
> 2. Exposed internal API for obtaining a full-privileged lookup to the rest of `java.base`. This API is intended for implementation of legacy (pre `MethodHandles.Lookup`) caller sensitive public APIs so they don't need more complex tricks to obtain proper permissions as lookups.
> 3. Implements [8229959](https://bugs.openjdk.java.net/browse/JDK-8229959): passes methods computed by proxy generator as class data to the hidden proxy class to reduce generated proxy class size and improve performance.
>
> In addition, since this change is somewhat large, should we keep the old proxy generator as well and have it toggled through a command-line flag (like the old v49 proxy generator or the old reflection implementation)?
>
> Please feel free to comment or review. This change definitely requires a CSR, but I have yet to determine what specifications should be changed.
>
> -------------
>
> Commit messages:
> - Change proxy serialization to work with hidden classes (require spec update)
> - Formatting
> - Move to hidden class and methods in class data
> - Implement anchors and remove proxyClassLookup factory
>
> Changes: https://git.openjdk.java.net/jdk/pull/8278/files
> Webrev: https://webrevs.openjdk.java.net/?repo=jdk&pr=8278&range=00
> Issue: https://bugs.openjdk.java.net/browse/JDK-8242888
> Stats: 400 lines in 6 files changed: 122 ins; 222 del; 56 mod
> Patch: https://git.openjdk.java.net/jdk/pull/8278.diff
> Fetch: git fetch https://git.openjdk.java.net/jdk pull/8278/head:pull/8278
>
> PR: https://git.openjdk.java.net/jdk/pull/8278
More information about the security-dev
mailing list