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

@ -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;
}
/**