8344034: Remove security manager dependency in Serialization

Reviewed-by: mullan, alanb
This commit is contained in:
Roger Riggs 2024-11-18 16:17:07 +00:00
parent d52d136486
commit 9b0ab92b16
7 changed files with 106 additions and 419 deletions

View File

@ -29,8 +29,6 @@ import jdk.internal.access.SharedSecrets;
import jdk.internal.util.StaticProperty;
import java.lang.reflect.InvocationTargetException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.Security;
import java.util.ArrayList;
import java.util.List;
@ -630,17 +628,13 @@ public interface ObjectInputFilter {
configLog = System.getLogger("java.io.serialization");
// Get the values of the system properties, if they are defined
@SuppressWarnings("removal")
String factoryClassName = StaticProperty.jdkSerialFilterFactory() != null
? StaticProperty.jdkSerialFilterFactory()
: AccessController.doPrivileged((PrivilegedAction<String>) () ->
Security.getProperty(SERIAL_FILTER_FACTORY_PROPNAME));
: Security.getProperty(SERIAL_FILTER_FACTORY_PROPNAME);
@SuppressWarnings("removal")
String filterString = StaticProperty.jdkSerialFilter() != null
? StaticProperty.jdkSerialFilter()
: AccessController.doPrivileged((PrivilegedAction<String>) () ->
Security.getProperty(SERIAL_FILTER_PROPNAME));
: Security.getProperty(SERIAL_FILTER_PROPNAME);
// Initialize the static filter if the jdk.serialFilter is present
String filterMessage = null;
@ -734,11 +728,6 @@ public interface ObjectInputFilter {
*/
public static void setSerialFilter(ObjectInputFilter filter) {
Objects.requireNonNull(filter, "filter");
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(ObjectStreamConstants.SERIAL_FILTER_PERMISSION);
}
if (invalidFilterMessage != null) {
throw new IllegalStateException(invalidFilterMessage);
}
@ -831,11 +820,6 @@ public interface ObjectInputFilter {
*/
public static void setSerialFilterFactory(BinaryOperator<ObjectInputFilter> filterFactory) {
Objects.requireNonNull(filterFactory, "filterFactory");
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(ObjectStreamConstants.SERIAL_FILTER_PERMISSION);
}
if (filterFactoryNoReplace.getAndSet(true)) {
final String msg = serialFilterFactory != null
? "Cannot replace filter factory: " + serialFilterFactory.getClass().getName()

View File

@ -34,13 +34,7 @@ import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.nio.charset.StandardCharsets;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Arrays;
import java.util.Map;
import java.util.Objects;
import jdk.internal.access.JavaLangAccess;
@ -49,8 +43,6 @@ import jdk.internal.event.DeserializationEvent;
import jdk.internal.misc.Unsafe;
import jdk.internal.util.ByteArray;
import sun.reflect.misc.ReflectUtil;
import sun.security.action.GetBooleanAction;
import sun.security.action.GetIntegerAction;
/**
* An ObjectInputStream deserializes primitive data and objects previously
@ -278,8 +270,8 @@ public class ObjectInputStream
* have been read.
* See {@link #setObjectInputFilter(ObjectInputFilter)}
*/
static final boolean SET_FILTER_AFTER_READ = GetBooleanAction
.privilegedGetProperty("jdk.serialSetFilterAfterRead");
static final boolean SET_FILTER_AFTER_READ =
Boolean.getBoolean("jdk.serialSetFilterAfterRead");
/**
* Property to control {@link GetField#get(String, Object)} conversion of
@ -287,8 +279,8 @@ public class ObjectInputStream
* {@link GetField#get(String, Object)} returns null otherwise
* throwing {@link ClassNotFoundException}.
*/
private static final boolean GETFIELD_CNFE_RETURNS_NULL = GetBooleanAction
.privilegedGetProperty("jdk.serialGetFieldCnfeReturnsNull");
private static final boolean GETFIELD_CNFE_RETURNS_NULL =
Boolean.getBoolean("jdk.serialGetFieldCnfeReturnsNull");
/**
* Property to override the implementation limit on the number
@ -296,8 +288,8 @@ public class ObjectInputStream
* The maximum number of interfaces allowed for a proxy is limited to 65535 by
* {@link java.lang.reflect.Proxy#newProxyInstance(ClassLoader, Class[], InvocationHandler)}.
*/
static final int PROXY_INTERFACE_LIMIT = Math.clamp(GetIntegerAction
.privilegedGetProperty("jdk.serialProxyInterfaceLimit", 65535), 0, 65535);
static final int PROXY_INTERFACE_LIMIT =
Math.clamp(Integer.getInteger("jdk.serialProxyInterfaceLimit", 65535), 0, 65535);
}
/*
@ -386,7 +378,6 @@ public class ObjectInputStream
*/
@SuppressWarnings("this-escape")
public ObjectInputStream(InputStream in) throws IOException {
verifySubclass();
bin = new BlockDataInputStream(in);
handles = new HandleTable(10);
vlist = new ValidationList();
@ -416,11 +407,6 @@ public class ObjectInputStream
* fails due to invalid serial filter or serial filter factory properties.
*/
protected ObjectInputStream() throws IOException {
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
}
bin = null;
handles = null;
vlist = null;
@ -907,13 +893,6 @@ public class ObjectInputStream
if (enable == enableResolve) {
return enable;
}
if (enable) {
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(SUBSTITUTION_PERMISSION);
}
}
enableResolve = enable;
return !enableResolve;
}
@ -1309,11 +1288,6 @@ public class ObjectInputStream
* @since 9
*/
public final void setObjectInputFilter(ObjectInputFilter filter) {
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(ObjectStreamConstants.SERIAL_FILTER_PERMISSION);
}
if (totalObjectRefs > 0 && !Caches.SET_FILTER_AFTER_READ) {
throw new IllegalStateException(
"filter can not be set after an object has been read");
@ -1571,58 +1545,29 @@ public class ObjectInputStream
public abstract Object get(String name, Object val) throws IOException, ClassNotFoundException;
}
/**
* Verifies that this (possibly subclass) instance can be constructed
* without violating security constraints: the subclass must not override
* security-sensitive non-final methods, or else the
* "enableSubclassImplementation" SerializablePermission is checked.
*/
private void verifySubclass() {
Class<?> cl = getClass();
if (cl == ObjectInputStream.class) {
return;
}
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm == null) {
return;
}
boolean result = Caches.subclassAudits.get(cl);
if (!result) {
sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
}
}
/**
* Performs reflective checks on given subclass to verify that it doesn't
* override security-sensitive non-final methods. Returns TRUE if subclass
* is "safe", FALSE otherwise.
*/
@SuppressWarnings("removal")
private static Boolean auditSubclass(Class<?> subcl) {
return AccessController.doPrivileged(
new PrivilegedAction<Boolean>() {
public Boolean run() {
for (Class<?> cl = subcl;
cl != ObjectInputStream.class;
cl = cl.getSuperclass())
{
try {
cl.getDeclaredMethod(
"readUnshared", (Class[]) null);
return Boolean.FALSE;
} catch (NoSuchMethodException ex) {
}
try {
cl.getDeclaredMethod("readFields", (Class[]) null);
return Boolean.FALSE;
} catch (NoSuchMethodException ex) {
}
}
return Boolean.TRUE;
}
for (Class<?> cl = subcl;
cl != ObjectInputStream.class;
cl = cl.getSuperclass())
{
try {
cl.getDeclaredMethod(
"readUnshared", (Class[]) null);
return Boolean.FALSE;
} catch (NoSuchMethodException ex) {
}
);
try {
cl.getDeclaredMethod("readFields", (Class[]) null);
return Boolean.FALSE;
} catch (NoSuchMethodException ex) {
}
}
return Boolean.TRUE;
}
/**
@ -2702,16 +2647,11 @@ public class ObjectInputStream
final ObjectInputValidation obj;
final int priority;
Callback next;
@SuppressWarnings("removal")
final AccessControlContext acc;
Callback(ObjectInputValidation obj, int priority, Callback next,
@SuppressWarnings("removal") AccessControlContext acc)
{
Callback(ObjectInputValidation obj, int priority, Callback next) {
this.obj = obj;
this.priority = priority;
this.next = next;
this.acc = acc;
}
}
@ -2740,12 +2680,10 @@ public class ObjectInputStream
prev = cur;
cur = cur.next;
}
@SuppressWarnings("removal")
AccessControlContext acc = AccessController.getContext();
if (prev != null) {
prev.next = new Callback(obj, priority, cur, acc);
prev.next = new Callback(obj, priority, cur);
} else {
list = new Callback(obj, priority, list, acc);
list = new Callback(obj, priority, list);
}
}
@ -2756,23 +2694,15 @@ public class ObjectInputStream
* throws an InvalidObjectException, the callback process is terminated
* and the exception propagated upwards.
*/
@SuppressWarnings("removal")
void doCallbacks() throws InvalidObjectException {
try {
while (list != null) {
AccessController.doPrivileged(
new PrivilegedExceptionAction<Void>()
{
public Void run() throws InvalidObjectException {
list.obj.validateObject();
return null;
}
}, list.acc);
list.obj.validateObject();
list = list.next;
}
} catch (PrivilegedActionException ex) {
} catch (InvalidObjectException ex) {
list = null;
throw (InvalidObjectException) ex.getException();
throw ex;
}
}

View File

@ -26,8 +26,6 @@
package java.io;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -224,11 +222,8 @@ public class ObjectOutputStream
* value of "sun.io.serialization.extendedDebugInfo" property,
* as true or false for extended information about exception's place
*/
@SuppressWarnings("removal")
private static final boolean extendedDebugInfo =
java.security.AccessController.doPrivileged(
new sun.security.action.GetBooleanAction(
"sun.io.serialization.extendedDebugInfo")).booleanValue();
Boolean.getBoolean("sun.io.serialization.extendedDebugInfo");
/**
* Creates an ObjectOutputStream that writes to the specified OutputStream.
@ -247,7 +242,6 @@ public class ObjectOutputStream
*/
@SuppressWarnings("this-escape")
public ObjectOutputStream(OutputStream out) throws IOException {
verifySubclass();
bout = new BlockDataOutputStream(out);
handles = new HandleTable(10, (float) 3.00);
subs = new ReplaceTable(10, (float) 3.00);
@ -269,11 +263,6 @@ public class ObjectOutputStream
* @throws IOException if an I/O error occurs while creating this stream
*/
protected ObjectOutputStream() throws IOException {
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
}
bout = null;
handles = null;
subs = null;
@ -595,13 +584,6 @@ public class ObjectOutputStream
if (enable == enableReplace) {
return enable;
}
if (enable) {
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(SUBSTITUTION_PERMISSION);
}
}
enableReplace = enable;
return !enableReplace;
}
@ -625,8 +607,8 @@ public class ObjectOutputStream
* stream. Subclasses of ObjectOutputStream may override this method to
* customize the way in which class descriptors are written to the
* serialization stream. The corresponding method in ObjectInputStream,
* {@link ObjectInputStream#readClassDescriptor readClassDescriptor}, should then be overridden to
* reconstitute the class descriptor from its custom stream representation.
* {@link ObjectInputStream#readClassDescriptor readClassDescriptor}, should then be
* overridden to reconstitute the class descriptor from its custom stream representation.
* By default, this method writes class descriptors according to the format
* defined in the <a href="{@docRoot}/../specs/serialization/index.html">
* <cite>Java Object Serialization Specification</cite></a>.
@ -1022,58 +1004,29 @@ public class ObjectOutputStream
}
}
/**
* Verifies that this (possibly subclass) instance can be constructed
* without violating security constraints: the subclass must not override
* security-sensitive non-final methods, or else the
* "enableSubclassImplementation" SerializablePermission is checked.
*/
private void verifySubclass() {
Class<?> cl = getClass();
if (cl == ObjectOutputStream.class) {
return;
}
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm == null) {
return;
}
boolean result = Caches.subclassAudits.get(cl);
if (!result) {
sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
}
}
/**
* Performs reflective checks on given subclass to verify that it doesn't
* override security-sensitive non-final methods. Returns TRUE if subclass
* is "safe", FALSE otherwise.
*/
@SuppressWarnings("removal")
private static Boolean auditSubclass(Class<?> subcl) {
return AccessController.doPrivileged(
new PrivilegedAction<>() {
public Boolean run() {
for (Class<?> cl = subcl;
cl != ObjectOutputStream.class;
cl = cl.getSuperclass())
{
try {
cl.getDeclaredMethod(
"writeUnshared", new Class<?>[] { Object.class });
return Boolean.FALSE;
} catch (NoSuchMethodException ex) {
}
try {
cl.getDeclaredMethod("putFields", (Class<?>[]) null);
return Boolean.FALSE;
} catch (NoSuchMethodException ex) {
}
}
return Boolean.TRUE;
}
for (Class<?> cl = subcl;
cl != ObjectOutputStream.class;
cl = cl.getSuperclass())
{
try {
cl.getDeclaredMethod(
"writeUnshared", new Class<?>[] { Object.class });
return Boolean.FALSE;
} catch (NoSuchMethodException ex) {
}
);
try {
cl.getDeclaredMethod("putFields", (Class<?>[]) null);
return Boolean.FALSE;
} catch (NoSuchMethodException ex) {
}
}
return Boolean.TRUE;
}
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -32,21 +32,12 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.RecordComponent;
import java.lang.reflect.UndeclaredThrowableException;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PermissionCollection;
import java.security.Permissions;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@ -58,13 +49,8 @@ import java.util.concurrent.ConcurrentHashMap;
import jdk.internal.event.SerializationMisdeclarationEvent;
import jdk.internal.misc.Unsafe;
import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.Reflection;
import jdk.internal.reflect.ReflectionFactory;
import jdk.internal.access.SharedSecrets;
import jdk.internal.access.JavaSecurityAccess;
import jdk.internal.util.ByteArray;
import sun.reflect.misc.ReflectUtil;
/**
* Serialization's descriptor for classes. It contains the name and
@ -98,12 +84,6 @@ public final class ObjectStreamClass implements Serializable {
private static final ObjectStreamField[] serialPersistentFields =
NO_FIELDS;
/** reflection factory for obtaining serialization constructors */
@SuppressWarnings("removal")
private static final ReflectionFactory reflFactory =
AccessController.doPrivileged(
new ReflectionFactory.GetReflectionFactoryAction());
private static class Caches {
/** cache mapping local classes -> descriptors */
static final ClassCache<ObjectStreamClass> localDescs =
@ -206,8 +186,6 @@ public final class ObjectStreamClass implements Serializable {
/** session-cache of record deserialization constructor
* (in de-serialized OSC only), or null */
private MethodHandle deserializationCtr;
/** protection domains that need to be checked when calling the constructor */
private ProtectionDomain[] domains;
/** class-defined writeObject method, or null if none */
private Method writeObjectMethod;
@ -280,20 +258,13 @@ public final class ObjectStreamClass implements Serializable {
*
* @return the SUID of the class described by this descriptor
*/
@SuppressWarnings("removal")
public long getSerialVersionUID() {
// REMIND: synchronize instead of relying on volatile?
if (suid == null) {
if (isRecord)
return 0L;
suid = AccessController.doPrivileged(
new PrivilegedAction<Long>() {
public Long run() {
return computeDefaultSUID(cl);
}
}
);
suid = computeDefaultSUID(cl);
}
return suid.longValue();
}
@ -304,19 +275,11 @@ public final class ObjectStreamClass implements Serializable {
*
* @return the {@code Class} instance that this descriptor represents
*/
@SuppressWarnings("removal")
@CallerSensitive
public Class<?> forClass() {
if (cl == null) {
return null;
}
requireInitialized();
if (System.getSecurityManager() != null) {
Class<?> caller = Reflection.getCallerClass();
if (ReflectUtil.needsPackageAccessCheck(caller.getClassLoader(), cl.getClassLoader())) {
ReflectUtil.checkPackageAccess(cl);
}
}
return cl;
}
@ -369,7 +332,6 @@ public final class ObjectStreamClass implements Serializable {
/**
* Creates local class descriptor representing given class.
*/
@SuppressWarnings("removal")
private ObjectStreamClass(final Class<?> cl) {
this.cl = cl;
name = cl.getName();
@ -384,53 +346,44 @@ public final class ObjectStreamClass implements Serializable {
localDesc = this;
if (serializable) {
AccessController.doPrivileged(new PrivilegedAction<>() {
public Void run() {
if (isEnum) {
suid = 0L;
fields = NO_FIELDS;
return null;
}
if (cl.isArray()) {
fields = NO_FIELDS;
return null;
}
suid = getDeclaredSUID(cl);
try {
fields = getSerialFields(cl);
computeFieldOffsets();
} catch (InvalidClassException e) {
serializeEx = deserializeEx =
if (isEnum) {
suid = 0L;
fields = NO_FIELDS;
} else if (cl.isArray()) {
fields = NO_FIELDS;
} else {
suid = getDeclaredSUID(cl);
try {
fields = getSerialFields(cl);
computeFieldOffsets();
} catch (InvalidClassException e) {
serializeEx = deserializeEx =
new ExceptionInfo(e.classname, e.getMessage());
fields = NO_FIELDS;
}
if (isRecord) {
canonicalCtr = canonicalRecordCtr(cl);
deserializationCtrs = new DeserializationConstructorsCache();
} else if (externalizable) {
cons = getExternalizableConstructor(cl);
} else {
cons = getSerializableConstructor(cl);
writeObjectMethod = getPrivateMethod(cl, "writeObject",
new Class<?>[] { ObjectOutputStream.class },
Void.TYPE);
readObjectMethod = getPrivateMethod(cl, "readObject",
new Class<?>[] { ObjectInputStream.class },
Void.TYPE);
readObjectNoDataMethod = getPrivateMethod(
cl, "readObjectNoData", null, Void.TYPE);
hasWriteObjectData = (writeObjectMethod != null);
}
domains = getProtectionDomains(cons, cl);
writeReplaceMethod = getInheritableMethod(
cl, "writeReplace", null, Object.class);
readResolveMethod = getInheritableMethod(
cl, "readResolve", null, Object.class);
return null;
fields = NO_FIELDS;
}
});
if (isRecord) {
canonicalCtr = canonicalRecordCtr(cl);
deserializationCtrs = new DeserializationConstructorsCache();
} else if (externalizable) {
cons = getExternalizableConstructor(cl);
} else {
cons = getSerializableConstructor(cl);
writeObjectMethod = getPrivateMethod(cl, "writeObject",
new Class<?>[]{ObjectOutputStream.class},
Void.TYPE);
readObjectMethod = getPrivateMethod(cl, "readObject",
new Class<?>[]{ObjectInputStream.class},
Void.TYPE);
readObjectNoDataMethod = getPrivateMethod(
cl, "readObjectNoData", null, Void.TYPE);
hasWriteObjectData = (writeObjectMethod != null);
}
writeReplaceMethod = getInheritableMethod(
cl, "writeReplace", null, Object.class);
readResolveMethod = getInheritableMethod(
cl, "readResolve", null, Object.class);
}
} else {
suid = 0L;
fields = NO_FIELDS;
@ -474,66 +427,6 @@ public final class ObjectStreamClass implements Serializable {
ObjectStreamClass() {
}
/**
* Creates a PermissionDomain that grants no permission.
*/
private ProtectionDomain noPermissionsDomain() {
PermissionCollection perms = new Permissions();
perms.setReadOnly();
return new ProtectionDomain(null, perms);
}
/**
* Aggregate the ProtectionDomains of all the classes that separate
* a concrete class {@code cl} from its ancestor's class declaring
* a constructor {@code cons}.
*
* If {@code cl} is defined by the boot loader, or the constructor
* {@code cons} is declared by {@code cl}, or if there is no security
* manager, then this method does nothing and {@code null} is returned.
*
* @param cons A constructor declared by {@code cl} or one of its
* ancestors.
* @param cl A concrete class, which is either the class declaring
* the constructor {@code cons}, or a serializable subclass
* of that class.
* @return An array of ProtectionDomain representing the set of
* ProtectionDomain that separate the concrete class {@code cl}
* from its ancestor's declaring {@code cons}, or {@code null}.
*/
@SuppressWarnings("removal")
private ProtectionDomain[] getProtectionDomains(Constructor<?> cons,
Class<?> cl) {
ProtectionDomain[] domains = null;
if (cons != null && cl.getClassLoader() != null
&& System.getSecurityManager() != null) {
Class<?> cls = cl;
Class<?> fnscl = cons.getDeclaringClass();
Set<ProtectionDomain> pds = null;
while (cls != fnscl) {
ProtectionDomain pd = cls.getProtectionDomain();
if (pd != null) {
if (pds == null) pds = new HashSet<>();
pds.add(pd);
}
cls = cls.getSuperclass();
if (cls == null) {
// that's not supposed to happen
// make a ProtectionDomain with no permission.
// should we throw instead?
if (pds == null) pds = new HashSet<>();
else pds.clear();
pds.add(noPermissionsDomain());
break;
}
}
if (pds != null) {
domains = pds.toArray(new ProtectionDomain[0]);
}
}
return domains;
}
/**
* Initializes class descriptor representing a proxy class.
*/
@ -564,7 +457,6 @@ public final class ObjectStreamClass implements Serializable {
writeReplaceMethod = localDesc.writeReplaceMethod;
readResolveMethod = localDesc.readResolveMethod;
deserializeEx = localDesc.deserializeEx;
domains = localDesc.domains;
cons = localDesc.cons;
}
fieldRefl = getReflector(fields, localDesc);
@ -656,7 +548,6 @@ public final class ObjectStreamClass implements Serializable {
if (deserializeEx == null) {
deserializeEx = localDesc.deserializeEx;
}
domains = localDesc.domains;
assert cl.isRecord() ? localDesc.cons == null : true;
cons = localDesc.cons;
}
@ -1013,7 +904,6 @@ public final class ObjectStreamClass implements Serializable {
* class is non-serializable or if the appropriate no-arg constructor is
* inaccessible/unavailable.
*/
@SuppressWarnings("removal")
Object newInstance()
throws InstantiationException, InvocationTargetException,
UnsupportedOperationException
@ -1021,35 +911,7 @@ public final class ObjectStreamClass implements Serializable {
requireInitialized();
if (cons != null) {
try {
if (domains == null || domains.length == 0) {
return cons.newInstance();
} else {
JavaSecurityAccess jsa = SharedSecrets.getJavaSecurityAccess();
PrivilegedAction<?> pea = () -> {
try {
return cons.newInstance();
} catch (InstantiationException
| InvocationTargetException
| IllegalAccessException x) {
throw new UndeclaredThrowableException(x);
}
}; // Can't use PrivilegedExceptionAction with jsa
try {
return jsa.doIntersectionPrivilege(pea,
AccessController.getContext(),
new AccessControlContext(domains));
} catch (UndeclaredThrowableException x) {
Throwable cause = x.getCause();
if (cause instanceof InstantiationException ie)
throw ie;
if (cause instanceof InvocationTargetException ite)
throw ite;
if (cause instanceof IllegalAccessException iae)
throw iae;
// not supposed to happen
throw x;
}
}
return cons.newInstance();
} catch (IllegalAccessException ex) {
// should not occur, as access checks have been suppressed
throw new InternalError(ex);
@ -1454,7 +1316,7 @@ public final class ObjectStreamClass implements Serializable {
* returned constructor (if any).
*/
private static Constructor<?> getSerializableConstructor(Class<?> cl) {
return reflFactory.newConstructorForSerialization(cl);
return ReflectionFactory.getReflectionFactory().newConstructorForSerialization(cl);
}
/**
@ -1462,22 +1324,18 @@ public final class ObjectStreamClass implements Serializable {
* the not found ( which should never happen for correctly generated record
* classes ).
*/
@SuppressWarnings("removal")
private static MethodHandle canonicalRecordCtr(Class<?> cls) {
assert cls.isRecord() : "Expected record, got: " + cls;
PrivilegedAction<MethodHandle> pa = () -> {
Class<?>[] paramTypes = Arrays.stream(cls.getRecordComponents())
.map(RecordComponent::getType)
.toArray(Class<?>[]::new);
try {
Constructor<?> ctr = cls.getDeclaredConstructor(paramTypes);
ctr.setAccessible(true);
return MethodHandles.lookup().unreflectConstructor(ctr);
} catch (IllegalAccessException | NoSuchMethodException e) {
return null;
}
};
return AccessController.doPrivileged(pa);
Class<?>[] paramTypes = Arrays.stream(cls.getRecordComponents())
.map(RecordComponent::getType)
.toArray(Class<?>[]::new);
try {
Constructor<?> ctr = cls.getDeclaredConstructor(paramTypes);
ctr.setAccessible(true);
return MethodHandles.lookup().unreflectConstructor(ctr);
} catch (IllegalAccessException | NoSuchMethodException e) {
return null;
}
}
/**
@ -2358,7 +2216,6 @@ public final class ObjectStreamClass implements Serializable {
* and return
* {@code Object}
*/
@SuppressWarnings("removal")
static MethodHandle deserializationCtr(ObjectStreamClass desc) {
// check the cached value 1st
MethodHandle mh = desc.deserializationCtr;
@ -2367,14 +2224,7 @@ public final class ObjectStreamClass implements Serializable {
if (mh != null) return desc.deserializationCtr = mh;
// retrieve record components
RecordComponent[] recordComponents;
try {
Class<?> cls = desc.forClass();
PrivilegedExceptionAction<RecordComponent[]> pa = cls::getRecordComponents;
recordComponents = AccessController.doPrivileged(pa);
} catch (PrivilegedActionException e) {
throw new InternalError(e.getCause());
}
RecordComponent[] recordComponents = desc.forClass().getRecordComponents();
// retrieve the canonical constructor
// (T1, T2, ..., Tn):TR

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -26,9 +26,6 @@
package java.io;
import java.lang.reflect.Field;
import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.Reflection;
import sun.reflect.misc.ReflectUtil;
/**
* A description of a Serializable field from a Serializable class. An array
@ -161,15 +158,7 @@ public class ObjectStreamField
* @return a {@code Class} object representing the type of the
* serializable field
*/
@SuppressWarnings("removal")
@CallerSensitive
public Class<?> getType() {
if (System.getSecurityManager() != null) {
Class<?> caller = Reflection.getCallerClass();
if (ReflectUtil.needsPackageAccessCheck(caller.getClassLoader(), type.getClassLoader())) {
ReflectUtil.checkPackageAccess(type);
}
}
return type;
}

View File

@ -29,8 +29,6 @@ import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Arrays;
import static jdk.internal.event.SerializationMisdeclarationEvent.*;
@ -75,7 +73,7 @@ final class SerializationMisdeclarationChecker {
}
private static void checkSerialVersionUID(Class<?> cl) {
Field f = privilegedDeclaredField(cl, SUID_NAME);
Field f = declaredField(cl, SUID_NAME);
if (f == null) {
if (isOrdinaryClass(cl)) {
commitEvent(cl, SUID_NAME + " should be declared explicitly" +
@ -101,7 +99,7 @@ final class SerializationMisdeclarationChecker {
}
private static void checkSerialPersistentFields(Class<?> cl) {
Field f = privilegedDeclaredField(cl, SERIAL_PERSISTENT_FIELDS_NAME);
Field f = declaredField(cl, SERIAL_PERSISTENT_FIELDS_NAME);
if (f == null) {
return;
}
@ -142,7 +140,7 @@ final class SerializationMisdeclarationChecker {
private static void checkPrivateMethod(Class<?> cl,
String name, Class<?>[] paramTypes, Class<?> retType) {
for (Method m : privilegedDeclaredMethods(cl)) {
for (Method m : cl.getDeclaredMethods()) {
if (m.getName().equals(name)) {
checkPrivateMethod(cl, m, paramTypes, retType);
}
@ -173,7 +171,7 @@ final class SerializationMisdeclarationChecker {
private static void checkAccessibleMethod(Class<?> cl,
String name, Class<?>[] paramTypes, Class<?> retType) {
for (Class<?> superCl = cl; superCl != null; superCl = superCl.getSuperclass()) {
for (Method m : privilegedDeclaredMethods(superCl)) {
for (Method m : superCl.getDeclaredMethods()) {
if (m.getName().equals(name)) {
checkAccessibleMethod(cl, superCl, m, paramTypes, retType);
}
@ -236,14 +234,6 @@ final class SerializationMisdeclarationChecker {
return (m.getModifiers() & STATIC) != 0;
}
@SuppressWarnings("removal")
private static Field privilegedDeclaredField(Class<?> cl, String name) {
if (System.getSecurityManager() == null) {
return declaredField(cl, name);
}
return AccessController.doPrivileged((PrivilegedAction<Field>) () ->
declaredField(cl, name));
}
private static Field declaredField(Class<?> cl, String name) {
try {
@ -253,14 +243,6 @@ final class SerializationMisdeclarationChecker {
return null;
}
@SuppressWarnings("removal")
private static Method[] privilegedDeclaredMethods(Class<?> cl) {
if (System.getSecurityManager() == null) {
return cl.getDeclaredMethods();
}
return AccessController.doPrivileged(
(PrivilegedAction<Method[]>) cl::getDeclaredMethods);
}
private static Object objectFromStatic(Field f) {
try {

View File

@ -70,8 +70,7 @@ public class CheckCSMs {
// The goal is to remove this list of Non-final instance @CS methods
// over time. Do not add any new one to this list.
private static final Set<String> KNOWN_NON_FINAL_CSMS =
Set.of("java/io/ObjectStreamField#getType ()Ljava/lang/Class;",
"java/lang/Runtime#load (Ljava/lang/String;)V",
Set.of("java/lang/Runtime#load (Ljava/lang/String;)V",
"java/lang/Runtime#loadLibrary (Ljava/lang/String;)V",
"javax/sql/rowset/serial/SerialJavaObject#getFields ()[Ljava/lang/reflect/Field;"
);