From 84e86faad317af8654f52b80a5c1c86af34a6e03 Mon Sep 17 00:00:00 2001 From: jwilhelm Date: Thu, 14 Sep 2017 23:02:56 +0200 Subject: [PATCH] 8187556: Backout of a fix reintroduced a dependency that had since been removed Reviewed-by: duke --- .../sun/jmx/remote/internal/RMIExporter.java | 6 +- .../com/sun/jmx/remote/util/EnvHelp.java | 57 ++- .../classes/java/io/ObjectInputStream.java | 22 -- .../remote/rmi/RMIConnectorServer.java | 3 +- .../remote/rmi/RMIJRMPServerImpl.java | 148 ++++---- .../jmxremote/ConnectorBootstrap.java | 33 +- src/share/classes/sun/misc/SharedSecrets.java | 14 +- .../sun/rmi/server/MarshalInputStream.java | 38 +- .../sun/rmi/server/UnicastServerRef.java | 90 +---- .../lib/management/management.properties | 35 ++ .../connection/DefaultAgentFilterTest.java | 327 ++++++++++++++++++ .../connection/NewRMIClientFilterTest.java | 146 ++++++++ .../mandatory/connection/mgmt1.properties | 34 ++ .../mandatory/connection/mgmt2.properties | 34 ++ .../connectorServer/RMIExporterTest.java | 6 +- 15 files changed, 737 insertions(+), 256 deletions(-) create mode 100644 test/javax/management/remote/mandatory/connection/DefaultAgentFilterTest.java create mode 100644 test/javax/management/remote/mandatory/connection/NewRMIClientFilterTest.java create mode 100644 test/javax/management/remote/mandatory/connection/mgmt1.properties create mode 100644 test/javax/management/remote/mandatory/connection/mgmt2.properties 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 8568aa95f..ead4a4d24 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, 2017, 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 9d924a300..8856d6b00 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, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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,6 +69,61 @@ 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 c7924daf3..de9c6366d 100644 --- a/src/share/classes/java/io/ObjectInputStream.java +++ b/src/share/classes/java/io/ObjectInputStream.java @@ -45,8 +45,6 @@ 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,9 +1748,6 @@ public class ObjectInputStream throw new StreamCorruptedException( String.format("invalid type code: %02X", tc)); } - if (descriptor != null) { - validateDescriptor(descriptor); - } return descriptor; } @@ -3897,21 +3892,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 4cdb092c6..621bccbc8 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, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2017, 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,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; diff --git a/src/share/classes/javax/management/remote/rmi/RMIJRMPServerImpl.java b/src/share/classes/javax/management/remote/rmi/RMIJRMPServerImpl.java index 562de79f6..c16936b0d 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, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2017, 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,6 +26,7 @@ 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; @@ -47,6 +48,11 @@ 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 @@ -59,8 +65,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.

@@ -101,31 +105,37 @@ public class RMIJRMPServerImpl extends RMIServerImpl { 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 credentialsFilter + = (String) this.env.get(EnvHelp.CREDENTIALS_FILTER_PATTERN); + + if(credentialsFilter != null){ + cFilter = ObjectInputFilter.Config.createFilter(credentialsFilter); + allowedTypes = null; } - exportedWrapper = types != null ? - new ExportedWrapper(this, types) : - 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; + } + + String userJmxFilter = + (String) this.env.get(EnvHelp.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 +146,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 +180,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 +210,7 @@ public class RMIJRMPServerImpl extends RMIServerImpl { RMIConnection client = new RMIConnectionImpl(this, connectionId, getDefaultClassLoader(), subject, env); - export(client); + export(client, jmxRmiFilter); return client; } @@ -223,56 +227,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 56287edbd..2bde8911b 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, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 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(EnvHelp.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(EnvHelp.CREDENTIALS_FILTER_PATTERN, String.class.getName() + ";!*"); + + if(jmxRmiFilter != null && !jmxRmiFilter.isEmpty()) { + env.put(EnvHelp.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 3539962ba..18accf8eb 100644 --- a/src/share/classes/sun/misc/SharedSecrets.java +++ b/src/share/classes/sun/misc/SharedSecrets.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2017, 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 @@ -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) { @@ -200,15 +199,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 ccac7f1f5..838ac3279 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, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2017, 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,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 0da55822e..285dba5e0 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.AccessException; @@ -332,11 +331,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 (AccessException aex) { // For compatibility, AccessException is not wrapped in UnmarshalException // disable saving any refs in the inputStream for GC @@ -605,84 +609,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 70efa2eef..6b689e0b3 100644 --- a/src/share/lib/management/management.properties +++ b/src/share/lib/management/management.properties @@ -329,3 +329,38 @@ # 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/connection/DefaultAgentFilterTest.java b/test/javax/management/remote/mandatory/connection/DefaultAgentFilterTest.java new file mode 100644 index 000000000..6f4ead3ee --- /dev/null +++ b/test/javax/management/remote/mandatory/connection/DefaultAgentFilterTest.java @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2017, 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 + * @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 params); + + public void op2(String s, HashSet params); + + public void op3(MyTestObject obj, String s, HashMap param); + } + + public static class Test implements TestMBean { + + @Override + public void op1(HashSet params) { + System.out.println("Invoked op1"); + } + + @Override + public void op2(String s, HashSet params) { + System.out.println("Invoked op2"); + } + + @Override + public void op3(MyTestObject obj, String s, HashMap param) { + System.out.println("Invoked op3"); + } + } + + private static class TestAppRun implements AutoCloseable { + + private Process p; + private final ProcessBuilder pb; + private final String name; + private final AtomicBoolean started = new AtomicBoolean(false); + + public TestAppRun(ProcessBuilder pb, String name) { + this.pb = pb; + this.name = name; + } + + public synchronized void start() throws Exception { + if (started.compareAndSet(false, true)) { + try { + AtomicBoolean error = new AtomicBoolean(false); + AtomicBoolean bindError = new AtomicBoolean(false); + p = ProcessTools.startProcess( + TEST_APP_NAME + "{" + name + "}", + pb, + (line) -> { + if (line.toLowerCase().contains("exception") + || line.toLowerCase().contains("error")) { + error.set(true); + } + bindError.set(line.toLowerCase().contains("bindexception")); + return true; + }, 10, TimeUnit.SECONDS); + if (bindError.get()) { + throw new BindException("Process could not be started"); + } else if (error.get()) { + throw new RuntimeException(); + } + } catch (Exception ex) { + if (p != null) { + p.destroy(); + p.waitFor(); + } + throw ex; + } + } + } + + public synchronized void stop() + throws IOException, InterruptedException { + if (started.compareAndSet(true, false)) { + p.getOutputStream().write(0); + p.getOutputStream().flush(); + int ec = p.waitFor(); + if (ec != 0) { + StringBuilder msg = new StringBuilder(); + msg.append("Test application '").append(name); + msg.append("' failed with exit code: "); + msg.append(ec); + System.err.println(msg); + } + } + } + + @Override + public void close() throws Exception { + stop(); + } + } + + private static final String TEST_APP_NAME = "TestApp"; + + private static void testDefaultAgent(String propertyFile) throws Exception { + int port = Utils.getFreePort(); + String propFile = System.getProperty("test.src") + File.separator + propertyFile; + List pbArgs = new ArrayList<>(Arrays.asList( + "-cp", + System.getProperty("test.class.path"), + "-XX:+UsePerfData" + )); + String[] args = new String[]{ + "-Dcom.sun.management.jmxremote.port=" + port, + "-Dcom.sun.management.jmxremote.authenticate=false", + "-Dcom.sun.management.jmxremote.ssl=false", + "-Dcom.sun.management.config.file=" + propFile + }; + pbArgs.addAll(Arrays.asList(args)); + pbArgs.add(TEST_APP_NAME); + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + pbArgs.toArray(new String[pbArgs.size()]) + ); + + try (TestAppRun s = new TestAppRun(pb, DefaultAgentFilterTest.class.getSimpleName())) { + s.start(); + JMXServiceURL url = testConnect(port); + testMBeanOperations(url); + } + } + + private static JMXServiceURL testConnect(int port) throws Exception { + EOFException lastException = null; + JMXServiceURL url = null; + // factor adjusted timeout (5 seconds) for the RMI to become available + long timeout = System.currentTimeMillis() + Utils.adjustTimeout(5000); + do { + lastException = null; + try { + Registry registry = LocateRegistry.getRegistry(port); + String[] relist = registry.list(); + for (int i = 0; i < relist.length; ++i) { + System.out.println("Got registry: " + relist[i]); + } + String jmxUrlStr = String.format( + "service:jmx:rmi:///jndi/rmi://localhost:%d/jmxrmi", + port); + url = new JMXServiceURL(jmxUrlStr); + + try (JMXConnector c = JMXConnectorFactory.connect(url, null)) { + MBeanServerConnection conn = c.getMBeanServerConnection(); + ObjectName name = new ObjectName("jtreg:type=Test"); + conn.createMBean(Test.class.getName(), name); + } + } catch (Exception ex) { + if (ex instanceof EOFException) { + lastException = (EOFException) ex; + System.out.println("Error establishing RMI connection. Retrying in 500ms."); + Thread.sleep(500); + } else { + throw ex; + } + } + } while (lastException != null && System.currentTimeMillis() < timeout); + if (lastException != null) { + throw lastException; + } + return url; + } + + public static void main(String[] args) throws Exception { + System.out.println("---" + DefaultAgentFilterTest.class.getName() + "-main: starting ..."); + + boolean retry = false; + do { + try { + // blacklist String + testDefaultAgent("mgmt1.properties"); + System.out.println("----\tTest FAILED !!"); + throw new RuntimeException("---" + DefaultAgentFilterTest.class.getName() + " - No exception reported"); + } catch (Exception ex) { + if (ex instanceof InvocationTargetException) { + if (ex.getCause() instanceof BindException + || ex.getCause() instanceof java.rmi.ConnectException) { + System.out.println("Failed to allocate ports. Retrying ..."); + retry = true; + } + } else if (ex instanceof InvalidClassException) { + System.out.println("----\tTest PASSED !!"); + } else if (ex instanceof UnmarshalException + && ((UnmarshalException) ex).getCause() instanceof InvalidClassException) { + System.out.println("----\tTest PASSED !!"); + } else { + System.out.println(ex); + System.out.println("----\tTest FAILED !!"); + throw ex; + } + } + } while (retry); + retry = false; + do { + try { + // blacklist non-existent class + testDefaultAgent("mgmt2.properties"); + System.out.println("----\tTest PASSED !!"); + } catch (Exception ex) { + if (ex instanceof InvocationTargetException) { + if (ex.getCause() instanceof BindException + || ex.getCause() instanceof java.rmi.ConnectException) { + System.out.println("Failed to allocate ports. Retrying ..."); + retry = true; + } + } else { + System.out.println(ex); + System.out.println("----\tTest FAILED !!"); + throw ex; + } + } + } while (retry); + + System.out.println("---" + DefaultAgentFilterTest.class.getName() + "-main: finished ..."); + } + + private static void testMBeanOperations(JMXServiceURL serverUrl) throws Exception { + Map clientEnv = new HashMap<>(1); + ObjectName name = new ObjectName("jtreg:type=Test"); + try (JMXConnector client = JMXConnectorFactory.connect(serverUrl, clientEnv)) { + MBeanServerConnection conn = client.getMBeanServerConnection(); + + HashSet set = new HashSet<>(); + set.add("test1"); + set.add("test2"); + + String a = "A"; + + Object[] params1 = {set}; + String[] sig1 = {HashSet.class.getName()}; + conn.invoke(name, "op1", params1, sig1); + + Object[] params2 = {a, set}; + String[] sig2 = {String.class.getName(), HashSet.class.getName()}; + conn.invoke(name, "op2", params2, sig2); + + HashMap map = new HashMap<>(); + map.put("a", "A"); + map.put("b", "B"); + + Object[] params3 = {new MyTestObject(), a, map}; + String[] sig3 = {MyTestObject.class.getName(), String.class.getName(), + HashMap.class.getName()}; + conn.invoke(name, "op3", params3, sig3); + } + } +} + +class TestApp { + + private static void doSomething() throws IOException { + int r = System.in.read(); + System.out.println("read: " + r); + } + + public static void main(String args[]) throws Exception { + System.out.println("main enter"); + System.out.flush(); + doSomething(); + System.out.println("main exit"); + } +} diff --git a/test/javax/management/remote/mandatory/connection/NewRMIClientFilterTest.java b/test/javax/management/remote/mandatory/connection/NewRMIClientFilterTest.java new file mode 100644 index 000000000..570d5c47f --- /dev/null +++ b/test/javax/management/remote/mandatory/connection/NewRMIClientFilterTest.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2017, 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 + * @summary Tests ObjectInputFilter on RMIServer.newClient + * @author Harsha Wardhana B + * @run clean NewRMIClientFilterTest + * @run build NewRMIClientFilterTest + * @run main NewRMIClientFilterTest + */ +import java.io.InvalidClassException; +import java.io.Serializable; +import java.lang.management.ManagementFactory; +import java.util.HashMap; +import java.util.Map; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXConnectorServer; +import javax.management.remote.JMXConnectorServerFactory; +import javax.management.remote.JMXServiceURL; +import com.sun.jmx.remote.util.EnvHelp; + +public class NewRMIClientFilterTest { + + public static void main(String[] args) throws Exception { + System.out.println("---NewRMIClientFilterTest-main: starting ..."); + String filter1 = java.lang.String.class.getName() + ";!*"; + String filter2 = java.lang.String.class.getName() + ";" + MyCredentials.class.getName() + ";!*"; + + JMXServiceURL url = new JMXServiceURL("rmi", null, 0); + JMXServiceURL serverUrl = null; + Map env = new HashMap<>(1); + JMXConnectorServer server = null; + + System.out.println("\n---NewRMIClientFilterTest-main: testing types = null"); + server = newServer(url, null); + serverUrl = server.getAddress(); + doTest(serverUrl, null); + doTest(serverUrl, new String[]{"toto", "titi"}); + doTest(serverUrl, new Object[]{new MyCredentials(), "toto"}); + server.stop(); + + System.out.println("\n---NewRMIClientFilterTest-main: testing types = String[]"); + env.put(EnvHelp.CREDENTIALS_FILTER_PATTERN, + filter1); + server = newServer(url, env); + serverUrl = server.getAddress(); + doTest(serverUrl, null); + doTest(serverUrl, new String[]{"toto", "titi"}); + try { + doTest(serverUrl, new MyCredentials()); + throw new Error("Bad client is not refused!"); + } catch (Exception e) { + isInvalidClassEx(e); + } finally { + server.stop(); + } + + System.out.println("\n---NewRMIClientFilterTest-main: testing user specific types = String, MyCredentials"); + env.put(EnvHelp.CREDENTIALS_FILTER_PATTERN, + filter2); + server = newServer(url, env); + serverUrl = server.getAddress(); + doTest(serverUrl, null); + doTest(serverUrl, new String[]{"toto", "titi"}); + doTest(serverUrl, new MyCredentials[]{new MyCredentials(), (MyCredentials) null}); + try { + doTest(serverUrl, new Object[]{"toto", new byte[3]}); + throw new Error("Bad client is not refused!"); + } catch (Exception e) { + isInvalidClassEx(e); + } finally { + server.stop(); + } + + System.out.println("---NewRMIClientFilterTest-main PASSED!!!"); + } + + private static void doTest(JMXServiceURL serverAddr, Object credentials) throws Exception { + System.out.println("---NewRMIClientFilterTest-test:\n\tserver address: " + + serverAddr + "\n\tcredentials: " + credentials); + + Map env = new HashMap<>(1); + env.put("jmx.remote.credentials", credentials); + JMXConnector client = null; + try { + client = JMXConnectorFactory.connect(serverAddr, env); + client.getMBeanServerConnection().getDefaultDomain(); + } finally { + try { + client.close(); + } catch (Exception e) { + } + } + System.out.println("---NewRMIClientFilterTest-test: PASSED!"); + } + + private static JMXConnectorServer newServer(JMXServiceURL url, Map env) + throws Exception { + JMXConnectorServer server = JMXConnectorServerFactory.newJMXConnectorServer( + url, + env, + ManagementFactory.getPlatformMBeanServer()); + + server.start(); + return server; + } + + private static class MyCredentials implements Serializable { + } + + private static void isInvalidClassEx(Exception e) { + Throwable cause = e; + while (cause != null) { + if (cause instanceof InvalidClassException) { + System.out.println("---NewRMIClientFilterTest-InvalidClassException expected: " + cause); + return; + } + cause = cause.getCause(); + } + e.printStackTrace(); + throw new RuntimeException("Did not get expected InvalidClassException!"); + } +} diff --git a/test/javax/management/remote/mandatory/connection/mgmt1.properties b/test/javax/management/remote/mandatory/connection/mgmt1.properties new file mode 100644 index 000000000..cca1a7788 --- /dev/null +++ b/test/javax/management/remote/mandatory/connection/mgmt1.properties @@ -0,0 +1,34 @@ +# ################ Filter for ObjectInputStream ############################# +com.sun.management.jmxremote.serial.filter.pattern=!DefaultAgentFilterTest$MyTestObject +# 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/connection/mgmt2.properties b/test/javax/management/remote/mandatory/connection/mgmt2.properties new file mode 100644 index 000000000..1caa28011 --- /dev/null +++ b/test/javax/management/remote/mandatory/connection/mgmt2.properties @@ -0,0 +1,34 @@ +# ################ Filter for ObjectInputStream ############################# +com.sun.management.jmxremote.serial.filter.pattern=!DefaultAgentFilterTest$ThisTypeIsNotUsed +# 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 2ac2084a6..4f591572b 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, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2017, 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,6 +46,7 @@ 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 { @@ -59,7 +60,8 @@ public class RMIExporterTest { public Remote exportObject(Remote obj, int port, RMIClientSocketFactory csf, - RMIServerSocketFactory ssf) + RMIServerSocketFactory ssf, + ObjectInputFilter unused) throws RemoteException { System.out.println("CustomRMIExporter::exportObject():: " + "Remote = " + obj); -- GitLab