diff --git a/src/share/classes/com/sun/jmx/remote/internal/RMIExporter.java b/src/share/classes/com/sun/jmx/remote/internal/RMIExporter.java
index ead4a4d2445233eec5d31f58cf12b59ac62900c4..8568aa95f359446450b2671d3269d43dca755a44 100644
--- a/src/share/classes/com/sun/jmx/remote/internal/RMIExporter.java
+++ b/src/share/classes/com/sun/jmx/remote/internal/RMIExporter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -25,7 +25,6 @@
package com.sun.jmx.remote.internal;
-import sun.misc.ObjectInputFilter;
import java.rmi.NoSuchObjectException;
import java.rmi.Remote;
import java.rmi.RemoteException;
@@ -52,8 +51,7 @@ public interface RMIExporter {
public Remote exportObject(Remote obj,
int port,
RMIClientSocketFactory csf,
- RMIServerSocketFactory ssf,
- ObjectInputFilter filter)
+ RMIServerSocketFactory ssf)
throws RemoteException;
public boolean unexportObject(Remote obj, boolean force)
diff --git a/src/share/classes/com/sun/jmx/remote/util/EnvHelp.java b/src/share/classes/com/sun/jmx/remote/util/EnvHelp.java
index 8856d6b0025a2f3fb03eb2eac267dd11cb6cd697..9d924a300c0214572a16dadeab6868fdb79eac11 100644
--- a/src/share/classes/com/sun/jmx/remote/util/EnvHelp.java
+++ b/src/share/classes/com/sun/jmx/remote/util/EnvHelp.java
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, 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
@@ -69,61 +69,6 @@ public class EnvHelp {
public static final String CREDENTIAL_TYPES =
"jmx.remote.rmi.server.credential.types";
- /**
- * Name of the attribute that specifies an
- * {@link ObjectInputFilter} pattern string to filter classes acceptable
- * for {@link RMIServer#newClient(java.lang.Object) RMIServer.newClient()}
- * remote method call.
- *
- * The filter pattern must be in same format as used in
- * {@link java.io.ObjectInputFilter.Config.createFilter}
- *
- * This list of classes allowed by filter should correspond to the
- * transitive closure of the credentials class (or classes) used by the
- * installed {@linkplain JMXAuthenticator} associated with the
- * {@linkplain RMIServer} implementation.
- * If the attribute is not set then any class is deemed acceptable.
- * @see ObjectInputFilter
- */
- public static final String CREDENTIALS_FILTER_PATTERN =
- "jmx.remote.rmi.server.credentials.filter.pattern";
-
- /**
- * This attribute defines a pattern from which to create a
- * {@link java.io.ObjectInputFilter} that will be used when deserializing
- * objects sent to the {@code JMXConnectorServer} by any client.
- *
- * The filter will be called for any class found in the serialized
- * stream sent to server by client, including all JMX defined classes
- * (such as {@link javax.management.ObjectName}), all method parameters,
- * and, if present in the stream, all classes transitively referred by
- * the serial form of any deserialized object.
- * The pattern must be in same format as used in
- * {@link java.io.ObjectInputFilter.Config.createFilter}.
- * It may define a white list of permitted classes, a black list of
- * rejected classes, a maximum depth for the deserialized objects,
- * etc.
- *
- * To be functional, the filter should allow at least all the
- * concrete types in the transitive closure of all objects that
- * might get serialized when serializing all JMX classes referred
- * as parameters in the {@link
- * javax.management.remote.rmi.RMIConnection} interface,
- * plus all classes that a {@link javax.management.remote.rmi.RMIConnectorClient}
- * might need to transmit wrapped in {@linkplain java.rmi.MarshalledObject
- * marshalled objects} in order to interoperate with the MBeans registered
- * in the {@code MBeanServer}. That would potentially include all the
- * concrete {@linkplain javax.management.openmbean JMX OpenTypes} and the
- * classes they use in their serial form.
- *
- * Care must be taken when defining such a filter, as defining
- * a white list too restrictive or a too wide a black list may
- * prevent legitimate clients from interoperating with the
- * {@code JMXConnectorServer}.
- */
- public static final String SERIAL_FILTER_PATTERN =
- "jmx.remote.rmi.server.serial.filter.pattern";
-
/**
*
Name of the attribute that specifies a default class loader
* object.
diff --git a/src/share/classes/java/io/ObjectInputStream.java b/src/share/classes/java/io/ObjectInputStream.java
index e43d46148b847e593114d9b3e6eb4e92450f82c8..7e173ebd32fad417b8a08942613909c52ac389c9 100644
--- a/src/share/classes/java/io/ObjectInputStream.java
+++ b/src/share/classes/java/io/ObjectInputStream.java
@@ -45,6 +45,8 @@ import static java.io.ObjectStreamClass.processQueue;
import sun.misc.SharedSecrets;
import sun.misc.ObjectInputFilter;
+import sun.misc.ObjectStreamClassValidator;
+import sun.misc.SharedSecrets;
import sun.reflect.misc.ReflectUtil;
import sun.misc.JavaOISAccess;
import sun.util.logging.PlatformLogger;
@@ -1750,6 +1752,9 @@ public class ObjectInputStream
throw new StreamCorruptedException(
String.format("invalid type code: %02X", tc));
}
+ if (descriptor != null) {
+ validateDescriptor(descriptor);
+ }
return descriptor;
}
@@ -3895,4 +3900,21 @@ public class ObjectInputStream
throw new AssertionError();
}
}
+
+ private void validateDescriptor(ObjectStreamClass descriptor) {
+ ObjectStreamClassValidator validating = validator;
+ if (validating != null) {
+ validating.validateDescriptor(descriptor);
+ }
+ }
+
+ // controlled access to ObjectStreamClassValidator
+ private volatile ObjectStreamClassValidator validator;
+
+ private static void setValidator(ObjectInputStream ois, ObjectStreamClassValidator validator) {
+ ois.validator = validator;
+ }
+ static {
+ SharedSecrets.setJavaObjectInputStreamAccess(ObjectInputStream::setValidator);
+ }
}
diff --git a/src/share/classes/javax/management/remote/rmi/RMIConnectorServer.java b/src/share/classes/javax/management/remote/rmi/RMIConnectorServer.java
index 621bccbc81988e1ae4da378aebbd294f3e88eb27..4cdb092c6d262e4ad90d186e3b64ca8409957a6d 100644
--- a/src/share/classes/javax/management/remote/rmi/RMIConnectorServer.java
+++ b/src/share/classes/javax/management/remote/rmi/RMIConnectorServer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2013, 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
@@ -33,7 +33,6 @@ import com.sun.jmx.remote.util.EnvHelp;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import sun.misc.ObjectInputFilter;
import java.io.ObjectOutputStream;
import java.net.MalformedURLException;
import java.rmi.server.RMIClientSocketFactory;
diff --git a/src/share/classes/javax/management/remote/rmi/RMIJRMPServerImpl.java b/src/share/classes/javax/management/remote/rmi/RMIJRMPServerImpl.java
index c16936b0d2d05aa1bf5b115e33ba8994318a26da..562de79f6524fd1fd3d45607757b3f96a07f5a13 100644
--- a/src/share/classes/javax/management/remote/rmi/RMIJRMPServerImpl.java
+++ b/src/share/classes/javax/management/remote/rmi/RMIJRMPServerImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, 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,7 +26,6 @@
package javax.management.remote.rmi;
import java.io.IOException;
-import sun.misc.ObjectInputFilter;
import java.rmi.NoSuchObjectException;
import java.rmi.Remote;
import java.rmi.RemoteException;
@@ -48,11 +47,6 @@ import sun.reflect.misc.ReflectUtil;
import sun.rmi.server.DeserializationChecker;
import sun.rmi.server.UnicastServerRef;
import sun.rmi.server.UnicastServerRef2;
-import java.util.Arrays;
-import java.util.Set;
-import java.util.stream.Collectors;
-import sun.rmi.transport.LiveRef;
-
/**
*
An {@link RMIServer} object that is exported through JRMP and that
@@ -65,6 +59,8 @@ import sun.rmi.transport.LiveRef;
*/
public class RMIJRMPServerImpl extends RMIServerImpl {
+ private final ExportedWrapper exportedWrapper;
+
/**
*
Creates a new {@link RMIServer} object that will be exported
* on the given port using the given socket factories.
@@ -105,37 +101,31 @@ public class RMIJRMPServerImpl extends RMIServerImpl {
String[] credentialsTypes
= (String[]) this.env.get(EnvHelp.CREDENTIAL_TYPES);
-
- String credentialsFilter
- = (String) this.env.get(EnvHelp.CREDENTIALS_FILTER_PATTERN);
-
- if(credentialsFilter != null){
- cFilter = ObjectInputFilter.Config.createFilter(credentialsFilter);
- allowedTypes = null;
- }
- else if (credentialsTypes != null) {
- allowedTypes = Arrays.stream(credentialsTypes).filter(
- s -> s!= null).collect(Collectors.toSet());
- allowedTypes.stream().forEach(ReflectUtil::checkPackageAccess);
- cFilter = this::newClientCheckInput;
- } else {
- allowedTypes = null;
- cFilter = null;
+ List types = null;
+ if (credentialsTypes != null) {
+ types = new ArrayList<>();
+ for (String type : credentialsTypes) {
+ if (type == null) {
+ throw new IllegalArgumentException("A credential type is null.");
+ }
+ ReflectUtil.checkPackageAccess(type);
+ types.add(type);
+ }
}
-
- String userJmxFilter =
- (String) this.env.get(EnvHelp.SERIAL_FILTER_PATTERN);
- if(userJmxFilter != null && !userJmxFilter.isEmpty())
- jmxRmiFilter = ObjectInputFilter.Config.createFilter(userJmxFilter);
- else
- jmxRmiFilter = null;
+ exportedWrapper = types != null ?
+ new ExportedWrapper(this, types) :
+ null;
}
protected void export() throws IOException {
- export(this, cFilter);
+ if (exportedWrapper != null) {
+ export(exportedWrapper);
+ } else {
+ export(this);
+ }
}
- private void export(Remote obj, ObjectInputFilter typeFilter) throws RemoteException {
+ private void export(Remote obj) throws RemoteException {
final RMIExporter exporter =
(RMIExporter) env.get(RMIExporter.EXPORTER_ATTRIBUTE);
final boolean daemon = EnvHelp.isServerDaemon(env);
@@ -146,14 +136,16 @@ public class RMIJRMPServerImpl extends RMIServerImpl {
" cannot be used to specify an exporter!");
}
- if (exporter != null) {
- exporter.exportObject(obj, port, csf, ssf, typeFilter);
- } else {
+ if (daemon) {
if (csf == null && ssf == null) {
- new UnicastServerRef(new LiveRef(port), typeFilter).exportObject(obj, null, daemon);
+ new UnicastServerRef(port).exportObject(obj, null, true);
} else {
- new UnicastServerRef2(port, csf, ssf, typeFilter).exportObject(obj, null, daemon);
+ new UnicastServerRef2(port, csf, ssf).exportObject(obj, null, true);
}
+ } else if (exporter != null) {
+ exporter.exportObject(obj, port, csf, ssf);
+ } else {
+ UnicastRemoteObject.exportObject(obj, port, csf, ssf);
}
}
@@ -180,7 +172,11 @@ public class RMIJRMPServerImpl extends RMIServerImpl {
* RMIJRMPServerImpl has not been exported yet.
*/
public Remote toStub() throws IOException {
- return RemoteObject.toStub(this);
+ if (exportedWrapper != null) {
+ return RemoteObject.toStub(exportedWrapper);
+ } else {
+ return RemoteObject.toStub(this);
+ }
}
/**
@@ -210,7 +206,7 @@ public class RMIJRMPServerImpl extends RMIServerImpl {
RMIConnection client =
new RMIConnectionImpl(this, connectionId, getDefaultClassLoader(),
subject, env);
- export(client, jmxRmiFilter);
+ export(client);
return client;
}
@@ -227,38 +223,56 @@ public class RMIJRMPServerImpl extends RMIServerImpl {
* server failed.
*/
protected void closeServer() throws IOException {
- unexport(this, true);
- }
-
- /**
- * Check that a type in the remote invocation of {@link RMIServerImpl#newClient}
- * is one of the {@code allowedTypes}.
- *
- * @param clazz the class; may be null
- * @param size the size for arrays, otherwise is 0
- * @param nObjectRefs the current number of object references
- * @param depth the current depth
- * @param streamBytes the current number of bytes consumed
- * @return {@code ObjectInputFilter.Status.ALLOWED} if the class is allowed,
- * otherwise {@code ObjectInputFilter.Status.REJECTED}
- */
- ObjectInputFilter.Status newClientCheckInput(ObjectInputFilter.FilterInfo filterInfo) {
- ObjectInputFilter.Status status = ObjectInputFilter.Status.UNDECIDED;
- if (allowedTypes != null && filterInfo.serialClass() != null) {
- // If enabled, check type
- String type = filterInfo.serialClass().getName();
- if (allowedTypes.contains(type))
- status = ObjectInputFilter.Status.ALLOWED;
- else
- status = ObjectInputFilter.Status.REJECTED;
+ if (exportedWrapper != null) {
+ unexport(exportedWrapper, true);
+ } else {
+ unexport(this, true);
}
- return status;
}
+
private final int port;
private final RMIClientSocketFactory csf;
private final RMIServerSocketFactory ssf;
private final Map env;
- private final Set allowedTypes;
- private final ObjectInputFilter jmxRmiFilter;
- private final ObjectInputFilter cFilter;
+
+ private static class ExportedWrapper implements RMIServer, DeserializationChecker {
+ private final RMIServer impl;
+ private final List allowedTypes;
+ private ExportedWrapper(RMIServer impl, List credentialsTypes) {
+ this.impl = impl;
+ allowedTypes = credentialsTypes;
+ }
+
+ @Override
+ public String getVersion() throws RemoteException {
+ return impl.getVersion();
+ }
+
+ @Override
+ public RMIConnection newClient(Object credentials) throws IOException {
+ return impl.newClient(credentials);
+ }
+
+ @Override
+ public void check(Method method, ObjectStreamClass descriptor,
+ int paramIndex, int callID) {
+
+ String type = descriptor.getName();
+ if (!allowedTypes.contains(type)) {
+ throw new ClassCastException("Unsupported type: " + type);
+ }
+ }
+
+ @Override
+ public void checkProxyClass(Method method, String[] ifaces,
+ int paramIndex, int callID) {
+ if (ifaces != null && ifaces.length > 0) {
+ for (String iface : ifaces) {
+ if (!allowedTypes.contains(iface)) {
+ throw new ClassCastException("Unsupported type: " + iface);
+ }
+ }
+ }
+ }
+ }
}
diff --git a/src/share/classes/sun/management/jmxremote/ConnectorBootstrap.java b/src/share/classes/sun/management/jmxremote/ConnectorBootstrap.java
index 2bde8911b0607dbc587078183e549e9c4c767898..56287edbd0459f05cec8e2f459c4f55e3050f2dd 100644
--- a/src/share/classes/sun/management/jmxremote/ConnectorBootstrap.java
+++ b/src/share/classes/sun/management/jmxremote/ConnectorBootstrap.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, 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
@@ -30,7 +30,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
-import sun.misc.ObjectInputFilter;
+import java.io.Serializable;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.MalformedURLException;
@@ -43,6 +43,7 @@ import java.rmi.RemoteException;
import java.rmi.registry.Registry;
import java.rmi.server.RMIClientSocketFactory;
import java.rmi.server.RMIServerSocketFactory;
+import java.rmi.server.RMISocketFactory;
import java.rmi.server.RemoteObject;
import java.rmi.server.UnicastRemoteObject;
import java.security.KeyStore;
@@ -82,7 +83,6 @@ import sun.management.FileSystem;
import sun.rmi.server.UnicastRef;
import sun.rmi.server.UnicastServerRef;
import sun.rmi.server.UnicastServerRef2;
-import sun.rmi.transport.LiveRef;
/**
* This class initializes and starts the RMIConnectorServer for JSR 163
@@ -141,8 +141,6 @@ public final class ConnectorBootstrap {
"com.sun.management.jmxremote.ssl.need.client.auth";
public static final String SSL_CONFIG_FILE_NAME =
"com.sun.management.jmxremote.ssl.config.file";
- public static final String SERIAL_FILTER_PATTERN =
- "com.sun.management.jmxremote.serial.filter.pattern";
}
/**
@@ -183,8 +181,7 @@ public final class ConnectorBootstrap {
public Remote exportObject(Remote obj,
int port,
RMIClientSocketFactory csf,
- RMIServerSocketFactory ssf,
- ObjectInputFilter filter)
+ RMIServerSocketFactory ssf)
throws RemoteException {
synchronized (this) {
@@ -195,9 +192,9 @@ public final class ConnectorBootstrap {
final UnicastServerRef ref;
if (csf == null && ssf == null) {
- ref = new UnicastServerRef(new LiveRef(port), filter);
+ ref = new UnicastServerRef(port);
} else {
- ref = new UnicastServerRef2(port, csf, ssf, filter);
+ ref = new UnicastServerRef2(port, csf, ssf);
}
return ref.exportObject(obj, null, true);
}
@@ -437,7 +434,6 @@ public final class ConnectorBootstrap {
final String bindAddress =
props.getProperty(PropertyNames.HOST);
- final String jmxRmiFilter = props.getProperty(PropertyNames.SERIAL_FILTER_PATTERN);
if (log.debugOn()) {
log.debug("startRemoteConnectorServer",
@@ -474,7 +470,7 @@ public final class ConnectorBootstrap {
sslConfigFileName, enabledCipherSuitesList,
enabledProtocolsList, sslNeedClientAuth,
useAuthentication, loginConfigName,
- passwordFileName, accessFileName, bindAddress, jmxRmiFilter);
+ passwordFileName, accessFileName, bindAddress);
cs = data.jmxConnectorServer;
url = data.jmxRemoteURL;
log.config("startRemoteConnectorServer",
@@ -514,7 +510,9 @@ public final class ConnectorBootstrap {
// This RMI server should not keep the VM alive
Map env = new HashMap<>();
env.put(RMIExporter.EXPORTER_ATTRIBUTE, new PermanentExporter());
- env.put(EnvHelp.CREDENTIALS_FILTER_PATTERN, String.class.getName() + ";!*");
+ env.put(EnvHelp.CREDENTIAL_TYPES, new String[]{
+ String[].class.getName(), String.class.getName()
+ });
// The local connector server need only be available via the
// loopback connection.
@@ -730,8 +728,7 @@ public final class ConnectorBootstrap {
String loginConfigName,
String passwordFileName,
String accessFileName,
- String bindAddress,
- String jmxRmiFilter)
+ String bindAddress)
throws IOException, MalformedURLException {
/* Make sure we use non-guessable RMI object IDs. Otherwise
@@ -746,11 +743,9 @@ public final class ConnectorBootstrap {
PermanentExporter exporter = new PermanentExporter();
env.put(RMIExporter.EXPORTER_ATTRIBUTE, exporter);
- env.put(EnvHelp.CREDENTIALS_FILTER_PATTERN, String.class.getName() + ";!*");
-
- if(jmxRmiFilter != null && !jmxRmiFilter.isEmpty()) {
- env.put(EnvHelp.SERIAL_FILTER_PATTERN, jmxRmiFilter);
- }
+ env.put(EnvHelp.CREDENTIAL_TYPES, new String[]{
+ String[].class.getName(), String.class.getName()
+ });
boolean useSocketFactory = bindAddress != null && !useSsl;
diff --git a/src/share/classes/sun/misc/JavaObjectInputStreamAccess.java b/src/share/classes/sun/misc/JavaObjectInputStreamAccess.java
new file mode 100644
index 0000000000000000000000000000000000000000..8b6a7e152b60342e6cb96527a8b8043b706b4710
--- /dev/null
+++ b/src/share/classes/sun/misc/JavaObjectInputStreamAccess.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2016, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.misc;
+
+import java.io.ObjectInputStream;
+
+/**
+ * The interface to specify methods for accessing {@code ObjectInputStream}
+ * @author sjiang
+ */
+public interface JavaObjectInputStreamAccess {
+ /**
+ * Sets a descriptor validating.
+ * @param ois stream to have the descriptors validated
+ * @param validator validator used to validate a descriptor.
+ */
+ public void setValidator(ObjectInputStream ois, ObjectStreamClassValidator validator);
+}
diff --git a/src/share/classes/sun/misc/ObjectStreamClassValidator.java b/src/share/classes/sun/misc/ObjectStreamClassValidator.java
new file mode 100644
index 0000000000000000000000000000000000000000..f98a387dbcaa2ba504f722a8328bbc0e0f5fbbd7
--- /dev/null
+++ b/src/share/classes/sun/misc/ObjectStreamClassValidator.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2016, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.misc;
+
+import java.io.ObjectStreamClass;
+
+/**
+ * A callback used by {@code ObjectInputStream} to do descriptor validation.
+ *
+ * @author sjiang
+ */
+public interface ObjectStreamClassValidator {
+ /**
+ * This method will be called by ObjectInputStream to
+ * check a descriptor just before creating an object described by this descriptor.
+ * The object will not be created if this method throws a {@code RuntimeException}.
+ * @param descriptor descriptor to be checked.
+ */
+ public void validateDescriptor(ObjectStreamClass descriptor);
+}
diff --git a/src/share/classes/sun/misc/SharedSecrets.java b/src/share/classes/sun/misc/SharedSecrets.java
index 5f8ee1b4a287af6ab7cac462ce07099b1fd5a482..cc3fc642afafe7549fb8ecc5473086132f295783 100644
--- a/src/share/classes/sun/misc/SharedSecrets.java
+++ b/src/share/classes/sun/misc/SharedSecrets.java
@@ -59,6 +59,7 @@ public class SharedSecrets {
private static JavaAWTAccess javaAWTAccess;
private static JavaOISAccess javaOISAccess;
private static JavaxCryptoSealedObjectAccess javaxCryptoSealedObjectAccess;
+ private static JavaObjectInputStreamAccess javaObjectInputStreamAccess;
public static JavaUtilJarAccess javaUtilJarAccess() {
if (javaUtilJarAccess == null) {
@@ -201,6 +202,18 @@ public class SharedSecrets {
return javaAWTAccess;
}
+
+ public static JavaObjectInputStreamAccess getJavaObjectInputStreamAccess() {
+ if (javaObjectInputStreamAccess == null) {
+ unsafe.ensureClassInitialized(ObjectInputStream.class);
+ }
+ return javaObjectInputStreamAccess;
+ }
+
+ public static void setJavaObjectInputStreamAccess(JavaObjectInputStreamAccess access) {
+ javaObjectInputStreamAccess = access;
+ }
+
public static void setJavaxCryptoSealedObjectAccess(JavaxCryptoSealedObjectAccess jcsoa) {
javaxCryptoSealedObjectAccess = jcsoa;
}
diff --git a/src/share/classes/sun/rmi/server/MarshalInputStream.java b/src/share/classes/sun/rmi/server/MarshalInputStream.java
index 91be64bc441ba6d1bdc833de57c5ac30a6eb3145..ed13d45c213d5b0db3b8f2c0c77f1ae2e058fd8f 100644
--- a/src/share/classes/sun/rmi/server/MarshalInputStream.java
+++ b/src/share/classes/sun/rmi/server/MarshalInputStream.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, 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
@@ -34,6 +34,8 @@ import java.util.*;
import java.security.AccessControlException;
import java.security.Permission;
import java.rmi.server.RMIClassLoader;
+import sun.misc.ObjectStreamClassValidator;
+import sun.misc.SharedSecrets;
/**
* MarshalInputStream is an extension of ObjectInputStream. When resolving
@@ -51,6 +53,11 @@ import java.rmi.server.RMIClassLoader;
* @author Peter Jones
*/
public class MarshalInputStream extends ObjectInputStream {
+ interface StreamChecker extends ObjectStreamClassValidator {
+ void checkProxyInterfaceNames(String[] ifaces);
+ }
+
+ private volatile StreamChecker streamChecker = null;
/**
* Value of "java.rmi.server.useCodebaseOnly" property,
@@ -237,6 +244,11 @@ public class MarshalInputStream extends ObjectInputStream {
protected Class> resolveProxyClass(String[] interfaces)
throws IOException, ClassNotFoundException
{
+ StreamChecker checker = streamChecker;
+ if (checker != null) {
+ checker.checkProxyInterfaceNames(interfaces);
+ }
+
/*
* Always read annotation written by MarshalOutputStream.
*/
@@ -318,4 +330,28 @@ public class MarshalInputStream extends ObjectInputStream {
void useCodebaseOnly() {
useCodebaseOnly = true;
}
+
+ synchronized void setStreamChecker(StreamChecker checker) {
+ streamChecker = checker;
+ SharedSecrets.getJavaObjectInputStreamAccess().setValidator(this, checker);
+ }
+ @Override
+ protected ObjectStreamClass readClassDescriptor() throws IOException,
+ ClassNotFoundException {
+ ObjectStreamClass descriptor = super.readClassDescriptor();
+
+ validateDesc(descriptor);
+
+ return descriptor;
+ }
+
+ private void validateDesc(ObjectStreamClass descriptor) {
+ StreamChecker checker;
+ synchronized (this) {
+ checker = streamChecker;
+ }
+ if (checker != null) {
+ checker.validateDescriptor(descriptor);
+ }
+ }
}
diff --git a/src/share/classes/sun/rmi/server/UnicastServerRef.java b/src/share/classes/sun/rmi/server/UnicastServerRef.java
index 285dba5e0716c21c24e33741bfc458b16e263eba..d8274603041e898e5e5ba4dd89964c84489bcf1b 100644
--- a/src/share/classes/sun/rmi/server/UnicastServerRef.java
+++ b/src/share/classes/sun/rmi/server/UnicastServerRef.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, 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
@@ -29,6 +29,7 @@ import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
+import java.io.ObjectStreamClass;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.rmi.AccessException;
@@ -331,15 +332,10 @@ public class UnicastServerRef extends UnicastRef
logCall(obj, method);
// unmarshal parameters
- Class>[] types = method.getParameterTypes();
- Object[] params = new Object[types.length];
-
+ Object[] params = null;
try {
unmarshalCustomCallData(in);
- // Unmarshal the parameters
- for (int i = 0; i < types.length; i++) {
- params[i] = unmarshalValue(types[i], in);
- }
+ params = unmarshalParameters(obj, method, marshalStream);
} catch (AccessException aex) {
// For compatibility, AccessException is not wrapped in UnmarshalException
@@ -609,4 +605,84 @@ public class UnicastServerRef extends UnicastRef
}
}
+ /**
+ * Unmarshal parameters for the given method of the given instance over
+ * the given marshalinputstream. Perform any necessary checks.
+ */
+ private Object[] unmarshalParameters(Object obj, Method method, MarshalInputStream in)
+ throws IOException, ClassNotFoundException {
+ return (obj instanceof DeserializationChecker) ?
+ unmarshalParametersChecked((DeserializationChecker)obj, method, in) :
+ unmarshalParametersUnchecked(method, in);
+ }
+
+ /**
+ * Unmarshal parameters for the given method of the given instance over
+ * the given marshalinputstream. Do not perform any additional checks.
+ */
+ private Object[] unmarshalParametersUnchecked(Method method, ObjectInput in)
+ throws IOException, ClassNotFoundException {
+ Class>[] types = method.getParameterTypes();
+ Object[] params = new Object[types.length];
+ for (int i = 0; i < types.length; i++) {
+ params[i] = unmarshalValue(types[i], in);
+ }
+ return params;
+ }
+
+ /**
+ * Unmarshal parameters for the given method of the given instance over
+ * the given marshalinputstream. Do perform all additional checks.
+ */
+ private Object[] unmarshalParametersChecked(
+ DeserializationChecker checker,
+ Method method, MarshalInputStream in)
+ throws IOException, ClassNotFoundException {
+ int callID = methodCallIDCount.getAndIncrement();
+ MyChecker myChecker = new MyChecker(checker, method, callID);
+ in.setStreamChecker(myChecker);
+ try {
+ Class>[] types = method.getParameterTypes();
+ Object[] values = new Object[types.length];
+ for (int i = 0; i < types.length; i++) {
+ myChecker.setIndex(i);
+ values[i] = unmarshalValue(types[i], in);
+ }
+ myChecker.end(callID);
+ return values;
+ } finally {
+ in.setStreamChecker(null);
+ }
+ }
+
+ private static class MyChecker implements MarshalInputStream.StreamChecker {
+ private final DeserializationChecker descriptorCheck;
+ private final Method method;
+ private final int callID;
+ private int parameterIndex;
+
+ MyChecker(DeserializationChecker descriptorCheck, Method method, int callID) {
+ this.descriptorCheck = descriptorCheck;
+ this.method = method;
+ this.callID = callID;
+ }
+
+ @Override
+ public void validateDescriptor(ObjectStreamClass descriptor) {
+ descriptorCheck.check(method, descriptor, parameterIndex, callID);
+ }
+
+ @Override
+ public void checkProxyInterfaceNames(String[] ifaces) {
+ descriptorCheck.checkProxyClass(method, ifaces, parameterIndex, callID);
+ }
+
+ void setIndex(int parameterIndex) {
+ this.parameterIndex = parameterIndex;
+ }
+
+ void end(int callId) {
+ descriptorCheck.end(callId);
+ }
+ }
}
diff --git a/src/share/lib/management/management.properties b/src/share/lib/management/management.properties
index 6b689e0b3944dad167d023d32f04d1d5af8161dd..70efa2eefbdcd407d02b5502b29e375890bf79d1 100644
--- a/src/share/lib/management/management.properties
+++ b/src/share/lib/management/management.properties
@@ -329,38 +329,3 @@
# The format of the value for that property is any string accepted
# by java.net.InetAddress.getByName(String).
#
-
-# ################ Filter for ObjectInputStream #############################
-# com.sun.management.jmxremote.serial.filter.pattern=
-# A filter, if configured, is used by java.io.ObjectInputStream during
-# deserialization of parameters sent to the JMX default agent to validate the
-# contents of the stream.
-# A filter is configured as a sequence of patterns, each pattern is either
-# matched against the name of a class in the stream or defines a limit.
-# Patterns are separated by ";" (semicolon).
-# Whitespace is significant and is considered part of the pattern.
-#
-# If a pattern includes a "=", it sets a limit.
-# If a limit appears more than once the last value is used.
-# Limits are checked before classes regardless of the order in the sequence of patterns.
-# If any of the limits are exceeded, the filter status is REJECTED.
-#
-# maxdepth=value - the maximum depth of a graph
-# maxrefs=value - the maximum number of internal references
-# maxbytes=value - the maximum number of bytes in the input stream
-# maxarray=value - the maximum array length allowed
-#
-# Other patterns, from left to right, match the class or package name as
-# returned from Class.getName.
-# If the class is an array type, the class or package to be matched is the element type.
-# Arrays of any number of dimensions are treated the same as the element type.
-# For example, a pattern of "!example.Foo", rejects creation of any instance or
-# array of example.Foo.
-#
-# If the pattern starts with "!", the status is REJECTED if the remaining pattern
-# is matched; otherwise the status is ALLOWED if the pattern matches.
-# If the pattern ends with ".**" it matches any class in the package and all subpackages.
-# If the pattern ends with ".*" it matches any class in the package.
-# If the pattern ends with "*", it matches any class with the pattern as a prefix.
-# If the pattern is equal to the class name, it matches.
-# Otherwise, the status is UNDECIDED.
diff --git a/test/javax/management/remote/mandatory/connectorServer/RMIExporterTest.java b/test/javax/management/remote/mandatory/connectorServer/RMIExporterTest.java
index 4f591572bcd149da174e527488a1cbbebc723adf..2ac2084a6557e4916c34ae43b091e49471806e6f 100644
--- a/test/javax/management/remote/mandatory/connectorServer/RMIExporterTest.java
+++ b/test/javax/management/remote/mandatory/connectorServer/RMIExporterTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 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
@@ -46,7 +46,6 @@ import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;
import com.sun.jmx.remote.internal.RMIExporter;
-import sun.misc.ObjectInputFilter;
public class RMIExporterTest {
@@ -60,8 +59,7 @@ public class RMIExporterTest {
public Remote exportObject(Remote obj,
int port,
RMIClientSocketFactory csf,
- RMIServerSocketFactory ssf,
- ObjectInputFilter unused)
+ RMIServerSocketFactory ssf)
throws RemoteException {
System.out.println("CustomRMIExporter::exportObject():: " +
"Remote = " + obj);