From 9b0ab92b16f682e65e9847e8127b6ce09fc5759c Mon Sep 17 00:00:00 2001 From: Roger Riggs <rriggs@openjdk.org> Date: Mon, 18 Nov 2024 16:17:07 +0000 Subject: [PATCH] 8344034: Remove security manager dependency in Serialization Reviewed-by: mullan, alanb --- .../classes/java/io/ObjectInputFilter.java | 20 +- .../classes/java/io/ObjectInputStream.java | 126 ++------- .../classes/java/io/ObjectOutputStream.java | 85 ++---- .../classes/java/io/ObjectStreamClass.java | 252 ++++-------------- .../classes/java/io/ObjectStreamField.java | 13 +- .../SerializationMisdeclarationChecker.java | 26 +- .../reflect/CallerSensitive/CheckCSMs.java | 3 +- 7 files changed, 106 insertions(+), 419 deletions(-) diff --git a/src/java.base/share/classes/java/io/ObjectInputFilter.java b/src/java.base/share/classes/java/io/ObjectInputFilter.java index 9a04e1f58e3..9232111de07 100644 --- a/src/java.base/share/classes/java/io/ObjectInputFilter.java +++ b/src/java.base/share/classes/java/io/ObjectInputFilter.java @@ -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() diff --git a/src/java.base/share/classes/java/io/ObjectInputStream.java b/src/java.base/share/classes/java/io/ObjectInputStream.java index 60d8cadf6a3..31d0aecf831 100644 --- a/src/java.base/share/classes/java/io/ObjectInputStream.java +++ b/src/java.base/share/classes/java/io/ObjectInputStream.java @@ -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; } } diff --git a/src/java.base/share/classes/java/io/ObjectOutputStream.java b/src/java.base/share/classes/java/io/ObjectOutputStream.java index 429c91ab673..5225c673705 100644 --- a/src/java.base/share/classes/java/io/ObjectOutputStream.java +++ b/src/java.base/share/classes/java/io/ObjectOutputStream.java @@ -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; } /** diff --git a/src/java.base/share/classes/java/io/ObjectStreamClass.java b/src/java.base/share/classes/java/io/ObjectStreamClass.java index 73bb162e843..4fb9847a4e8 100644 --- a/src/java.base/share/classes/java/io/ObjectStreamClass.java +++ b/src/java.base/share/classes/java/io/ObjectStreamClass.java @@ -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 diff --git a/src/java.base/share/classes/java/io/ObjectStreamField.java b/src/java.base/share/classes/java/io/ObjectStreamField.java index 75c955440c1..465c29c101c 100644 --- a/src/java.base/share/classes/java/io/ObjectStreamField.java +++ b/src/java.base/share/classes/java/io/ObjectStreamField.java @@ -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; } diff --git a/src/java.base/share/classes/java/io/SerializationMisdeclarationChecker.java b/src/java.base/share/classes/java/io/SerializationMisdeclarationChecker.java index 5eae83e80f7..5a9a6f02ab4 100644 --- a/src/java.base/share/classes/java/io/SerializationMisdeclarationChecker.java +++ b/src/java.base/share/classes/java/io/SerializationMisdeclarationChecker.java @@ -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 { diff --git a/test/jdk/jdk/internal/reflect/CallerSensitive/CheckCSMs.java b/test/jdk/jdk/internal/reflect/CallerSensitive/CheckCSMs.java index ee4d2021b87..6b63ce122a3 100644 --- a/test/jdk/jdk/internal/reflect/CallerSensitive/CheckCSMs.java +++ b/test/jdk/jdk/internal/reflect/CallerSensitive/CheckCSMs.java @@ -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;" );