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 8568aa95f359446450b2671d3269d43dca755a44..d5139cc791865065b6657de5af3f179af1bf271f 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, 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
@@ -25,6 +25,7 @@
package com.sun.jmx.remote.internal;
+import sun.misc.ObjectInputFilter;
import java.rmi.NoSuchObjectException;
import java.rmi.Remote;
import java.rmi.RemoteException;
@@ -51,7 +52,8 @@ public interface RMIExporter {
public Remote exportObject(Remote obj,
int port,
RMIClientSocketFactory csf,
- RMIServerSocketFactory ssf)
+ RMIServerSocketFactory ssf,
+ ObjectInputFilter filter)
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 9d924a300c0214572a16dadeab6868fdb79eac11..994ff4e9127fda5144f8e93ae4eff6b39b6978be 100644
--- a/src/share/classes/com/sun/jmx/remote/util/EnvHelp.java
+++ b/src/share/classes/com/sun/jmx/remote/util/EnvHelp.java
@@ -53,22 +53,6 @@ import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorServer;
public class EnvHelp {
-
- /**
- * Name of the attribute that specifies a list of class names acceptable
- * as parameters to the {@link RMIServer#newClient(java.lang.Object) RMIServer.newClient()}
- * remote method call.
- *
- * This list of classes 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, or is null, then any class is
- * deemed acceptable.
- */
- public static final String CREDENTIAL_TYPES =
- "jmx.remote.rmi.server.credential.types";
-
/**
*
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 b5cb8288deae8793eeac3b62973490a71c085424..55c2e36a275dff20ee57cf815c861ce103380d9b 100644
--- a/src/share/classes/java/io/ObjectInputStream.java
+++ b/src/share/classes/java/io/ObjectInputStream.java
@@ -44,8 +44,6 @@ import java.util.concurrent.ConcurrentMap;
import static java.io.ObjectStreamClass.processQueue;
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;
@@ -1716,9 +1714,6 @@ public class ObjectInputStream
throw new StreamCorruptedException(
String.format("invalid type code: %02X", tc));
}
- if (descriptor != null) {
- validateDescriptor(descriptor);
- }
return descriptor;
}
@@ -3845,21 +3840,4 @@ 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 4cdb092c6d262e4ad90d186e3b64ca8409957a6d..06018b80761ebc4ef52d4f43728e3a29aa314dda 100644
--- a/src/share/classes/javax/management/remote/rmi/RMIConnectorServer.java
+++ b/src/share/classes/javax/management/remote/rmi/RMIConnectorServer.java
@@ -33,6 +33,7 @@ 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;
@@ -100,6 +101,61 @@ public class RMIConnectorServer extends JMXConnectorServer {
public static final String RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE =
"jmx.remote.rmi.server.socket.factory";
+ /**
+ * 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";
+
/**
*
An {@link RMIServer} object that is exported through JRMP and that
@@ -59,8 +61,6 @@ import sun.rmi.server.UnicastServerRef2;
*/
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.
@@ -99,33 +99,48 @@ public class RMIJRMPServerImpl extends RMIServerImpl {
this.ssf = ssf;
this.env = (env == null) ? Collections.emptyMap() : env;
+ // This attribute was represented by RMIConnectorServer.CREDENTIALS_TYPES.
+ // This attribute is superceded by
+ // RMIConnectorServer.CREDENTIALS_FILTER_PATTERN.
+ // Retaining this for backward compatibility.
String[] credentialsTypes
- = (String[]) this.env.get(EnvHelp.CREDENTIAL_TYPES);
- 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[]) this.env.get("jmx.remote.rmi.server.credential.types");
+
+ String credentialsFilter
+ = (String) this.env.get(RMIConnectorServer.CREDENTIALS_FILTER_PATTERN);
+
+ // It is impossible for both attributes to be specified
+ if(credentialsTypes != null && credentialsFilter != null)
+ throw new IllegalArgumentException("Cannot specify both \""
+ + "jmx.remote.rmi.server.credential.types" + "\" and \""
+ + RMIConnectorServer.CREDENTIALS_FILTER_PATTERN + "\"");
+ else 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;
}
- exportedWrapper = types != null ?
- new ExportedWrapper(this, types) :
- null;
+
+ String userJmxFilter =
+ (String) this.env.get(RMIConnectorServer.SERIAL_FILTER_PATTERN);
+ if(userJmxFilter != null && !userJmxFilter.isEmpty())
+ jmxRmiFilter = ObjectInputFilter.Config.createFilter(userJmxFilter);
+ else
+ jmxRmiFilter = null;
}
protected void export() throws IOException {
- if (exportedWrapper != null) {
- export(exportedWrapper);
- } else {
- export(this);
- }
+ export(this, cFilter);
}
- private void export(Remote obj) throws RemoteException {
+ private void export(Remote obj, ObjectInputFilter typeFilter) throws RemoteException {
final RMIExporter exporter =
(RMIExporter) env.get(RMIExporter.EXPORTER_ATTRIBUTE);
final boolean daemon = EnvHelp.isServerDaemon(env);
@@ -136,16 +151,14 @@ public class RMIJRMPServerImpl extends RMIServerImpl {
" cannot be used to specify an exporter!");
}
- if (daemon) {
+ if (exporter != null) {
+ exporter.exportObject(obj, port, csf, ssf, typeFilter);
+ } else {
if (csf == null && ssf == null) {
- new UnicastServerRef(port).exportObject(obj, null, true);
+ new UnicastServerRef(new LiveRef(port), typeFilter).exportObject(obj, null, daemon);
} else {
- new UnicastServerRef2(port, csf, ssf).exportObject(obj, null, true);
+ new UnicastServerRef2(port, csf, ssf, typeFilter).exportObject(obj, null, daemon);
}
- } else if (exporter != null) {
- exporter.exportObject(obj, port, csf, ssf);
- } else {
- UnicastRemoteObject.exportObject(obj, port, csf, ssf);
}
}
@@ -172,11 +185,7 @@ public class RMIJRMPServerImpl extends RMIServerImpl {
* RMIJRMPServerImpl has not been exported yet.
*/
public Remote toStub() throws IOException {
- if (exportedWrapper != null) {
- return RemoteObject.toStub(exportedWrapper);
- } else {
- return RemoteObject.toStub(this);
- }
+ return RemoteObject.toStub(this);
}
/**
@@ -206,7 +215,7 @@ public class RMIJRMPServerImpl extends RMIServerImpl {
RMIConnection client =
new RMIConnectionImpl(this, connectionId, getDefaultClassLoader(),
subject, env);
- export(client);
+ export(client, jmxRmiFilter);
return client;
}
@@ -223,56 +232,38 @@ public class RMIJRMPServerImpl extends RMIServerImpl {
* server failed.
*/
protected void closeServer() throws IOException {
- if (exportedWrapper != null) {
- unexport(exportedWrapper, true);
- } else {
- unexport(this, true);
- }
+ 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;
+ }
+ return status;
+ }
private final int port;
private final RMIClientSocketFactory csf;
private final RMIServerSocketFactory ssf;
private final Map env;
-
- 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);
- }
- }
- }
- }
- }
+ private final Set allowedTypes;
+ private final ObjectInputFilter jmxRmiFilter;
+ private final ObjectInputFilter cFilter;
}
diff --git a/src/share/classes/sun/management/jmxremote/ConnectorBootstrap.java b/src/share/classes/sun/management/jmxremote/ConnectorBootstrap.java
index 56287edbd0459f05cec8e2f459c4f55e3050f2dd..8f3e82355e2413b40446aaa728bdbf8c906085e7 100644
--- a/src/share/classes/sun/management/jmxremote/ConnectorBootstrap.java
+++ b/src/share/classes/sun/management/jmxremote/ConnectorBootstrap.java
@@ -30,7 +30,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.Serializable;
+import sun.misc.ObjectInputFilter;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.MalformedURLException;
@@ -43,7 +43,6 @@ 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;
@@ -83,6 +82,7 @@ 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,6 +141,8 @@ 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";
}
/**
@@ -181,7 +183,8 @@ public final class ConnectorBootstrap {
public Remote exportObject(Remote obj,
int port,
RMIClientSocketFactory csf,
- RMIServerSocketFactory ssf)
+ RMIServerSocketFactory ssf,
+ ObjectInputFilter filter)
throws RemoteException {
synchronized (this) {
@@ -192,9 +195,9 @@ public final class ConnectorBootstrap {
final UnicastServerRef ref;
if (csf == null && ssf == null) {
- ref = new UnicastServerRef(port);
+ ref = new UnicastServerRef(new LiveRef(port), filter);
} else {
- ref = new UnicastServerRef2(port, csf, ssf);
+ ref = new UnicastServerRef2(port, csf, ssf, filter);
}
return ref.exportObject(obj, null, true);
}
@@ -434,6 +437,7 @@ 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",
@@ -470,7 +474,7 @@ public final class ConnectorBootstrap {
sslConfigFileName, enabledCipherSuitesList,
enabledProtocolsList, sslNeedClientAuth,
useAuthentication, loginConfigName,
- passwordFileName, accessFileName, bindAddress);
+ passwordFileName, accessFileName, bindAddress, jmxRmiFilter);
cs = data.jmxConnectorServer;
url = data.jmxRemoteURL;
log.config("startRemoteConnectorServer",
@@ -510,9 +514,7 @@ 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.CREDENTIAL_TYPES, new String[]{
- String[].class.getName(), String.class.getName()
- });
+ env.put(RMIConnectorServer.CREDENTIALS_FILTER_PATTERN, String.class.getName() + ";!*");
// The local connector server need only be available via the
// loopback connection.
@@ -728,7 +730,8 @@ public final class ConnectorBootstrap {
String loginConfigName,
String passwordFileName,
String accessFileName,
- String bindAddress)
+ String bindAddress,
+ String jmxRmiFilter)
throws IOException, MalformedURLException {
/* Make sure we use non-guessable RMI object IDs. Otherwise
@@ -743,9 +746,11 @@ public final class ConnectorBootstrap {
PermanentExporter exporter = new PermanentExporter();
env.put(RMIExporter.EXPORTER_ATTRIBUTE, exporter);
- env.put(EnvHelp.CREDENTIAL_TYPES, new String[]{
- String[].class.getName(), String.class.getName()
- });
+ env.put(RMIConnectorServer.CREDENTIALS_FILTER_PATTERN, String.class.getName() + ";!*");
+
+ if(jmxRmiFilter != null && !jmxRmiFilter.isEmpty()) {
+ env.put(RMIConnectorServer.SERIAL_FILTER_PATTERN, jmxRmiFilter);
+ }
boolean useSocketFactory = bindAddress != null && !useSsl;
diff --git a/src/share/classes/sun/misc/SharedSecrets.java b/src/share/classes/sun/misc/SharedSecrets.java
index 3539962ba3ab1d5950a7969d671da2e1c6d08e0e..7410e8c992217433d89535667a7ab3519196dfc6 100644
--- a/src/share/classes/sun/misc/SharedSecrets.java
+++ b/src/share/classes/sun/misc/SharedSecrets.java
@@ -58,7 +58,6 @@ public class SharedSecrets {
private static JavaUtilZipFileAccess javaUtilZipFileAccess;
private static JavaAWTAccess javaAWTAccess;
private static JavaOISAccess javaOISAccess;
- private static JavaObjectInputStreamAccess javaObjectInputStreamAccess;
public static JavaUtilJarAccess javaUtilJarAccess() {
if (javaUtilJarAccess == null) {
@@ -201,14 +200,4 @@ 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;
- }
}
diff --git a/src/share/classes/sun/rmi/server/MarshalInputStream.java b/src/share/classes/sun/rmi/server/MarshalInputStream.java
index ccac7f1f5d2e353b867090e4ffd3f4523b161385..3f771f6aa6586420696397a5ca31c18b93ad0606 100644
--- a/src/share/classes/sun/rmi/server/MarshalInputStream.java
+++ b/src/share/classes/sun/rmi/server/MarshalInputStream.java
@@ -34,8 +34,6 @@ 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
@@ -53,11 +51,6 @@ import sun.misc.SharedSecrets;
* @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,
@@ -244,11 +237,6 @@ 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.
*/
@@ -328,28 +316,4 @@ 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 66f9146193b282746a640a9a6198a3c531e7323a..cea1dd81f34578e84e1297c8e1a455480bff5230 100644
--- a/src/share/classes/sun/rmi/server/UnicastServerRef.java
+++ b/src/share/classes/sun/rmi/server/UnicastServerRef.java
@@ -29,7 +29,6 @@ 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.MarshalException;
@@ -325,11 +324,16 @@ public class UnicastServerRef extends UnicastRef
logCall(obj, method);
// unmarshal parameters
- Object[] params = null;
+ Class>[] types = method.getParameterTypes();
+ Object[] params = new Object[types.length];
try {
unmarshalCustomCallData(in);
- params = unmarshalParameters(obj, method, marshalStream);
+ // Unmarshal the parameters
+ for (int i = 0; i < types.length; i++) {
+ params[i] = unmarshalValue(types[i], in);
+ }
+
} catch (java.io.IOException e) {
throw new UnmarshalException(
"error unmarshalling arguments", e);
@@ -608,84 +612,4 @@ 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 70efa2eefbdcd407d02b5502b29e375890bf79d1..5c292bbd102069994653692285c2148740fae277 100644
--- a/src/share/lib/management/management.properties
+++ b/src/share/lib/management/management.properties
@@ -329,3 +329,42 @@
# 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 contains "/", the non-empty prefix up to the "/" is the module name;
+# if the module name matches the module name of the class then
+# the remaining pattern is matched with the class name.
+# If there is no "/", the module name is not compared.
+# 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/connection/DefaultAgentFilterTest.java b/test/javax/management/remote/mandatory/connection/DefaultAgentFilterTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..e6c96bc71fac33063d3210c1857f763fe09144e7
--- /dev/null
+++ b/test/javax/management/remote/mandatory/connection/DefaultAgentFilterTest.java
@@ -0,0 +1,328 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+ /*
+ * @test
+ * @bug 8159377
+ * @library /lib/testlibrary
+ * @summary Tests ObjectFilter on default agent
+ * @author Harsha Wardhana B
+ * @modules java.management
+ * @build jdk.testlibrary.* DefaultAgentFilterTest
+ * @run main/othervm/timeout=600 -XX:+UsePerfData DefaultAgentFilterTest
+ */
+import java.io.EOFException;
+import java.io.File;
+import java.io.IOException;
+import java.io.InvalidClassException;
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.net.BindException;
+import java.rmi.UnmarshalException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXServiceURL;
+import java.util.concurrent.TimeUnit;
+
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.Utils;
+
+public class DefaultAgentFilterTest {
+
+ public static class MyTestObject implements Serializable {
+
+ String a;
+ int id;
+ }
+
+ public interface TestMBean {
+
+ public void op1(HashSet