From 3b10a3f9b81229e3fec028fe173b3e7de69f65b6 Mon Sep 17 00:00:00 2001 From: Bradford Wetmore Date: Mon, 21 May 2012 15:42:15 -0700 Subject: [PATCH 01/19] 7167656: Multiple Seeders are being created Reviewed-by: smarks, mduigou, ahgross --- .../sun/security/provider/SecureRandom.java | 35 ++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/jdk/src/share/classes/sun/security/provider/SecureRandom.java b/jdk/src/share/classes/sun/security/provider/SecureRandom.java index e79e9d7f49a..fa88334e1c3 100644 --- a/jdk/src/share/classes/sun/security/provider/SecureRandom.java +++ b/jdk/src/share/classes/sun/security/provider/SecureRandom.java @@ -56,12 +56,6 @@ implements java.io.Serializable { private static final long serialVersionUID = 3581829991155417889L; - /** - * This static object will be seeded by SeedGenerator, and used - * to seed future instances of SecureRandom - */ - private static SecureRandom seeder; - private static final int DIGEST_SIZE = 20; private transient MessageDigest digest; private byte[] state; @@ -172,6 +166,28 @@ implements java.io.Serializable { state[0]++; } + /** + * This static object will be seeded by SeedGenerator, and used + * to seed future instances of SHA1PRNG SecureRandoms. + * + * Bloch, Effective Java Second Edition: Item 71 + */ + private static class SeederHolder { + + private static final SecureRandom seeder; + + static { + /* + * Call to SeedGenerator.generateSeed() to add additional + * seed material (likely from the Native implementation). + */ + seeder = new SecureRandom(SeedGenerator.getSystemEntropy()); + byte [] b = new byte[DIGEST_SIZE]; + SeedGenerator.generateSeed(b); + seeder.engineSetSeed(b); + } + } + /** * Generates a user-specified number of random bytes. * @@ -183,13 +199,8 @@ implements java.io.Serializable { byte[] output = remainder; if (state == null) { - if (seeder == null) { - seeder = new SecureRandom(SeedGenerator.getSystemEntropy()); - seeder.engineSetSeed(engineGenerateSeed(DIGEST_SIZE)); - } - byte[] seed = new byte[DIGEST_SIZE]; - seeder.engineNextBytes(seed); + SeederHolder.seeder.engineNextBytes(seed); state = digest.digest(seed); } From 52f39f95df16df5d3f5c9c6df42cacb2778f3a45 Mon Sep 17 00:00:00 2001 From: Sean Mullan Date: Fri, 8 Jun 2012 11:02:47 -0400 Subject: [PATCH 02/19] 7163198: Tightened package accessibility 7169887: Tightened package accessibility Reviewed-by: vinnie, hawtin --- jdk/src/share/lib/security/java.security | 4 ++-- jdk/src/share/lib/security/java.security-macosx | 4 ++-- jdk/src/share/lib/security/java.security-solaris | 4 ++-- jdk/src/share/lib/security/java.security-windows | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/jdk/src/share/lib/security/java.security b/jdk/src/share/lib/security/java.security index e8ca7bd7eea..3bb8597654c 100644 --- a/jdk/src/share/lib/security/java.security +++ b/jdk/src/share/lib/security/java.security @@ -145,7 +145,7 @@ keystore.type=jks # passed to checkPackageAccess unless the # corresponding RuntimePermission ("accessClassInPackage."+package) has # been granted. -package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils. +package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal. # # List of comma-separated packages that start with or equal this string @@ -157,7 +157,7 @@ package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun. # by default, none of the class loaders supplied with the JDK call # checkPackageDefinition. # -package.definition=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils. +package.definition=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal. # # Determines whether this properties file can be appended to diff --git a/jdk/src/share/lib/security/java.security-macosx b/jdk/src/share/lib/security/java.security-macosx index 1c04236e5d6..689172f40d6 100644 --- a/jdk/src/share/lib/security/java.security-macosx +++ b/jdk/src/share/lib/security/java.security-macosx @@ -146,7 +146,7 @@ keystore.type=jks # passed to checkPackageAccess unless the # corresponding RuntimePermission ("accessClassInPackage."+package) has # been granted. -package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,apple.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils. +package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,apple.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal. # # List of comma-separated packages that start with or equal this string @@ -158,7 +158,7 @@ package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun. # by default, none of the class loaders supplied with the JDK call # checkPackageDefinition. # -package.definition=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,apple.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils. +package.definition=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,apple.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal. # # Determines whether this properties file can be appended to diff --git a/jdk/src/share/lib/security/java.security-solaris b/jdk/src/share/lib/security/java.security-solaris index 87a6f1ea5b4..1c5062c4c8b 100644 --- a/jdk/src/share/lib/security/java.security-solaris +++ b/jdk/src/share/lib/security/java.security-solaris @@ -147,7 +147,7 @@ keystore.type=jks # passed to checkPackageAccess unless the # corresponding RuntimePermission ("accessClassInPackage."+package) has # been granted. -package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils. +package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal. # # List of comma-separated packages that start with or equal this string @@ -159,7 +159,7 @@ package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun. # by default, none of the class loaders supplied with the JDK call # checkPackageDefinition. # -package.definition=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils. +package.definition=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal. # # Determines whether this properties file can be appended to diff --git a/jdk/src/share/lib/security/java.security-windows b/jdk/src/share/lib/security/java.security-windows index e7c36d8c470..c98c0c95865 100644 --- a/jdk/src/share/lib/security/java.security-windows +++ b/jdk/src/share/lib/security/java.security-windows @@ -146,7 +146,7 @@ keystore.type=jks # passed to checkPackageAccess unless the # corresponding RuntimePermission ("accessClassInPackage."+package) has # been granted. -package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils. +package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal. # # List of comma-separated packages that start with or equal this string @@ -158,7 +158,7 @@ package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun. # by default, none of the class loaders supplied with the JDK call # checkPackageDefinition. # -package.definition=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils. +package.definition=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal. # # Determines whether this properties file can be appended to From a15896d20e9470d22e8cb97c1e51d94d7b9d760c Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Fri, 15 Jun 2012 09:51:09 +0800 Subject: [PATCH 03/19] 6631398: FilePermission improved path checking Reviewed-by: mullan, skoivu, jdn --- jdk/src/share/classes/java/io/FilePermission.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/share/classes/java/io/FilePermission.java b/jdk/src/share/classes/java/io/FilePermission.java index a5781f3fb00..2555a77644d 100644 --- a/jdk/src/share/classes/java/io/FilePermission.java +++ b/jdk/src/share/classes/java/io/FilePermission.java @@ -418,7 +418,7 @@ public final class FilePermission extends Permission implements Serializable { */ public int hashCode() { - return this.cpath.hashCode(); + return 0; } /** From d87e57ac8aaa1902baeadb3a73aa757a3505fda1 Mon Sep 17 00:00:00 2001 From: Sean Mullan Date: Mon, 18 Jun 2012 10:00:55 -0400 Subject: [PATCH 04/19] 7172522: Improve DomainCombiner checking Reviewed-by: vinnie, ahgross --- jdk/src/share/classes/java/security/AccessController.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/jdk/src/share/classes/java/security/AccessController.java b/jdk/src/share/classes/java/security/AccessController.java index 97383f54a46..8a8eadea62d 100644 --- a/jdk/src/share/classes/java/security/AccessController.java +++ b/jdk/src/share/classes/java/security/AccessController.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, 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 @@ -293,7 +293,7 @@ public final class AccessController { DomainCombiner dc = null; AccessControlContext acc = getStackAccessControlContext(); if (acc == null || (dc = acc.getAssignedCombiner()) == null) { - return AccessController.doPrivileged(action); + return AccessController.doPrivileged(action, acc); } return AccessController.doPrivileged(action, preserveCombiner(dc)); } @@ -389,7 +389,7 @@ public final class AccessController { DomainCombiner dc = null; AccessControlContext acc = getStackAccessControlContext(); if (acc == null || (dc = acc.getAssignedCombiner()) == null) { - return AccessController.doPrivileged(action); + return AccessController.doPrivileged(action, acc); } return AccessController.doPrivileged(action, preserveCombiner(dc)); } From 63cf10e50057789d99c83d231c14cb3005c663ad Mon Sep 17 00:00:00 2001 From: Stuart Marks Date: Thu, 21 Jun 2012 00:20:49 -0700 Subject: [PATCH 05/19] 7093490: adjust package access in rmiregistry Reviewed-by: ahgross, coffeys, dmocek --- jdk/src/share/classes/sun/rmi/registry/RegistryImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jdk/src/share/classes/sun/rmi/registry/RegistryImpl.java b/jdk/src/share/classes/sun/rmi/registry/RegistryImpl.java index 34579c204de..e086f79c1bf 100644 --- a/jdk/src/share/classes/sun/rmi/registry/RegistryImpl.java +++ b/jdk/src/share/classes/sun/rmi/registry/RegistryImpl.java @@ -405,7 +405,8 @@ public class RegistryImpl extends java.rmi.server.RemoteServer */ perms.add(new SocketPermission("*", "connect,accept")); - perms.add(new RuntimePermission("accessClassInPackage.sun.*")); + perms.add(new RuntimePermission("accessClassInPackage.sun.jvmstat.*")); + perms.add(new RuntimePermission("accessClassInPackage.sun.jvm.hotspot.*")); perms.add(new FilePermission("<>", "read")); From 9a307c8287e7cc0594d41bf877ef6263a0ec1b4c Mon Sep 17 00:00:00 2001 From: Dmitry Samersoff Date: Fri, 22 Jun 2012 16:22:22 +0400 Subject: [PATCH 06/19] 7158796: Tighten properties checking in EnvHelp Move getProperty call out of computeBooleanFromString Reviewed-by: skoivu, sla --- .../remote/internal/ServerNotifForwarder.java | 6 +- .../com/sun/jmx/remote/util/EnvHelp.java | 76 +++++-------------- .../management/remote/rmi/RMIConnector.java | 6 +- .../remote/rmi/RMIConnectorServer.java | 5 +- 4 files changed, 26 insertions(+), 67 deletions(-) diff --git a/jdk/src/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java b/jdk/src/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java index ba071411608..58ccfb45280 100644 --- a/jdk/src/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java +++ b/jdk/src/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java @@ -68,9 +68,9 @@ public class ServerNotifForwarder { this.notifBuffer = notifBuffer; this.connectionId = connectionId; connectionTimeout = EnvHelp.getServerConnectionTimeout(env); - checkNotificationEmission = EnvHelp.computeBooleanFromString( - env, - "jmx.remote.x.check.notification.emission",false); + + String stringBoolean = (String) env.get("jmx.remote.x.check.notification.emission"); + checkNotificationEmission = EnvHelp.computeBooleanFromString( stringBoolean ); notificationAccessController = EnvHelp.getNotificationAccessController(env); } diff --git a/jdk/src/share/classes/com/sun/jmx/remote/util/EnvHelp.java b/jdk/src/share/classes/com/sun/jmx/remote/util/EnvHelp.java index e61d9d09d60..b8bf9d37a0f 100644 --- a/jdk/src/share/classes/com/sun/jmx/remote/util/EnvHelp.java +++ b/jdk/src/share/classes/com/sun/jmx/remote/util/EnvHelp.java @@ -665,97 +665,57 @@ public class EnvHelp { * Computes a boolean value from a string value retrieved from a * property in the given map. * - * @param env the environment map. - * @param prop the name of the property in the environment map whose - * returned string value must be converted into a boolean value. - * @param systemProperty if true, consult a system property of the - * same name if there is no entry in the environment map. + * @param stringBoolean the string value that must be converted + * into a boolean value. * * @return *
    - *
  • {@code false} if {@code env.get(prop)} is {@code null}
  • + *
  • {@code false} if {@code stringBoolean} is {@code null}
  • *
  • {@code false} if - * {@code ((String)env.get(prop)).equalsIgnoreCase("false")} + * {@code stringBoolean.equalsIgnoreCase("false")} * is {@code true}
  • *
  • {@code true} if - * {@code ((String)env.get(prop)).equalsIgnoreCase("true")} + * {@code stringBoolean.equalsIgnoreCase("true")} * is {@code true}
  • *
* - * @throws IllegalArgumentException if {@code env} is {@code null} or - * {@code env.get(prop)} is not {@code null} and + * @throws IllegalArgumentException if * {@code ((String)env.get(prop)).equalsIgnoreCase("false")} and * {@code ((String)env.get(prop)).equalsIgnoreCase("true")} are * {@code false}. - * @throws ClassCastException if {@code env.get(prop)} cannot be cast - * to {@code String}. */ - public static boolean computeBooleanFromString( - Map env, String prop, boolean systemProperty) { - - if (env == null) - throw new IllegalArgumentException("env map cannot be null"); - + public static boolean computeBooleanFromString(String stringBoolean) { // returns a default value of 'false' if no property is found... - return computeBooleanFromString(env,prop,systemProperty,false); + return computeBooleanFromString(stringBoolean,false); } /** * Computes a boolean value from a string value retrieved from a * property in the given map. * - * @param env the environment map. - * @param prop the name of the property in the environment map whose - * returned string value must be converted into a boolean value. - * @param systemProperty if true, consult a system property of the - * same name if there is no entry in the environment map. + * @param stringBoolean the string value that must be converted + * into a boolean value. * @param defaultValue a default value to return in case no property * was defined. * * @return *
    - *
  • {@code defaultValue} if {@code env.get(prop)} is {@code null} - * and {@code systemProperty} is {@code false}
  • - *
  • {@code defaultValue} if {@code env.get(prop)} is {@code null} - * and {@code systemProperty} is {@code true} and - * {@code System.getProperty(prop)} is {@code null}
  • - *
  • {@code false} if {@code env.get(prop)} is {@code null} - * and {@code systemProperty} is {@code true} and - * {@code System.getProperty(prop).equalsIgnoreCase("false")} - * is {@code true}
  • - *
  • {@code true} if {@code env.get(prop)} is {@code null} - * and {@code systemProperty} is {@code true} and - * {@code System.getProperty(prop).equalsIgnoreCase("true")} - * is {@code true}
  • + *
  • {@code defaultValue} if {@code stringBoolean} + * is {@code null}
  • *
  • {@code false} if - * {@code ((String)env.get(prop)).equalsIgnoreCase("false")} + * {@code stringBoolean.equalsIgnoreCase("false")} * is {@code true}
  • *
  • {@code true} if - * {@code ((String)env.get(prop)).equalsIgnoreCase("true")} + * {@code stringBoolean.equalsIgnoreCase("true")} * is {@code true}
  • *
* - * @throws IllegalArgumentException if {@code env} is {@code null} or - * {@code env.get(prop)} is not {@code null} and + * @throws IllegalArgumentException if * {@code ((String)env.get(prop)).equalsIgnoreCase("false")} and * {@code ((String)env.get(prop)).equalsIgnoreCase("true")} are * {@code false}. - * @throws ClassCastException if {@code env.get(prop)} cannot be cast - * to {@code String}. */ - public static boolean computeBooleanFromString( - Map env, String prop, - boolean systemProperty, boolean defaultValue) { - - if (env == null) - throw new IllegalArgumentException("env map cannot be null"); - - String stringBoolean = (String) env.get(prop); - if (stringBoolean == null && systemProperty) { - stringBoolean = - AccessController.doPrivileged(new GetPropertyAction(prop)); - } - + public static boolean computeBooleanFromString( String stringBoolean, boolean defaultValue) { if (stringBoolean == null) return defaultValue; else if (stringBoolean.equalsIgnoreCase("true")) @@ -763,8 +723,8 @@ public class EnvHelp { else if (stringBoolean.equalsIgnoreCase("false")) return false; else - throw new IllegalArgumentException(prop + - " must be \"true\" or \"false\" instead of \"" + + throw new IllegalArgumentException( + "Property value must be \"true\" or \"false\" instead of \"" + stringBoolean + "\""); } diff --git a/jdk/src/share/classes/javax/management/remote/rmi/RMIConnector.java b/jdk/src/share/classes/javax/management/remote/rmi/RMIConnector.java index f5359f9b12c..f6d17d6cc08 100644 --- a/jdk/src/share/classes/javax/management/remote/rmi/RMIConnector.java +++ b/jdk/src/share/classes/javax/management/remote/rmi/RMIConnector.java @@ -277,9 +277,9 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable // Check for secure RMIServer stub if the corresponding // client-side environment property is set to "true". // - boolean checkStub = EnvHelp.computeBooleanFromString( - usemap, - "jmx.remote.x.check.stub",false); + String stringBoolean = (String) usemap.get("jmx.remote.x.check.stub"); + boolean checkStub = EnvHelp.computeBooleanFromString(stringBoolean); + if (checkStub) checkStub(stub, rmiServerImplStubClass); // Connect IIOP Stub if needed. diff --git a/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectorServer.java b/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectorServer.java index 909b9cb0d47..da92f49f70b 100644 --- a/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectorServer.java +++ b/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectorServer.java @@ -412,9 +412,8 @@ public class RMIConnectorServer extends JMXConnectorServer { if (tracing) logger.trace("start", "Using external directory: " + jndiUrl); - final boolean rebind = EnvHelp.computeBooleanFromString( - attributes, - JNDI_REBIND_ATTRIBUTE,false); + String stringBoolean = (String) attributes.get(JNDI_REBIND_ATTRIBUTE); + final boolean rebind = EnvHelp.computeBooleanFromString( stringBoolean ); if (tracing) logger.trace("start", JNDI_REBIND_ATTRIBUTE + "=" + rebind); From 5e84600efcf5392e04e12a6b56aa4104c241022d Mon Sep 17 00:00:00 2001 From: Dmitry Samersoff Date: Fri, 22 Jun 2012 18:19:48 +0400 Subject: [PATCH 07/19] 7169888: Narrowing resource definitions in JMX RMI connector CPU bug, we can't put offending calls outside doPrivileged, but narrow granted permissions. Reviewed-by: ahgross, fparain --- .../remote/rmi/RMIConnectionImpl.java | 89 ++++++++++--------- 1 file changed, 48 insertions(+), 41 deletions(-) diff --git a/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java b/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java index f322af0f2bc..9449210e897 100644 --- a/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java +++ b/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java @@ -25,6 +25,30 @@ package javax.management.remote.rmi; +import java.io.IOException; +import java.rmi.MarshalledObject; +import java.rmi.UnmarshalException; +import java.rmi.server.Unreferenced; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.Permission; +import java.security.PermissionCollection; +import java.security.Permissions; +import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.security.ProtectionDomain; +import java.util.Arrays; +import java.util.Collections; +import java.util.Map; +import java.util.Set; + +import javax.management.*; +import javax.management.remote.JMXServerErrorException; +import javax.management.remote.NotificationResult; +import javax.management.remote.TargetedNotification; +import javax.security.auth.Subject; + import static com.sun.jmx.mbeanserver.Util.cast; import com.sun.jmx.remote.internal.ServerCommunicatorAdmin; import com.sun.jmx.remote.internal.ServerNotifForwarder; @@ -35,44 +59,6 @@ import com.sun.jmx.remote.util.ClassLogger; import com.sun.jmx.remote.util.EnvHelp; import com.sun.jmx.remote.util.OrderClassLoaders; -import java.io.IOException; -import java.rmi.MarshalledObject; -import java.rmi.UnmarshalException; -import java.rmi.server.Unreferenced; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; -import java.util.Arrays; -import java.util.Collections; -import java.util.Map; -import java.util.Set; - -import javax.management.Attribute; -import javax.management.AttributeList; -import javax.management.AttributeNotFoundException; -import javax.management.InstanceAlreadyExistsException; -import javax.management.InstanceNotFoundException; -import javax.management.IntrospectionException; -import javax.management.InvalidAttributeValueException; -import javax.management.ListenerNotFoundException; -import javax.management.MBeanException; -import javax.management.MBeanInfo; -import javax.management.MBeanRegistrationException; -import javax.management.MBeanServer; -import javax.management.NotCompliantMBeanException; -import javax.management.NotificationFilter; -import javax.management.ObjectInstance; -import javax.management.ObjectName; -import javax.management.QueryExp; -import javax.management.ReflectionException; -import javax.management.RuntimeOperationsException; -import javax.management.remote.JMXServerErrorException; -import javax.management.remote.NotificationResult; -import javax.management.remote.TargetedNotification; -import javax.security.auth.Subject; - /** *

Implementation of the {@link RMIConnection} interface. User * code will not usually reference this class.

@@ -143,6 +129,7 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced { this.mbeanServer = rmiServer.getMBeanServer(); final ClassLoader dcl = defaultClassLoader; + this.classLoaderWithRepository = AccessController.doPrivileged( new PrivilegedAction() { @@ -151,13 +138,29 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced { mbeanServer.getClassLoaderRepository(), dcl); } - }); + }, + + withPermissions( new MBeanPermission("*", "getClassLoaderRepository"), + new RuntimePermission("createClassLoader")) + ); + serverCommunicatorAdmin = new RMIServerCommunicatorAdmin(EnvHelp.getServerConnectionTimeout(env)); this.env = env; } + private static AccessControlContext withPermissions(Permission ... perms){ + Permissions col = new Permissions(); + + for (Permission thePerm : perms ) { + col.add(thePerm); + } + + final ProtectionDomain pd = new ProtectionDomain(null, col); + return new AccessControlContext( new ProtectionDomain[] { pd }); + } + private synchronized ServerNotifForwarder getServerNotifFwd() { // Lazily created when first use. Mainly when // addNotificationListener is first called. @@ -1330,7 +1333,9 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced { public ClassLoader run() throws InstanceNotFoundException { return mbeanServer.getClassLoader(name); } - }); + }, + withPermissions(new MBeanPermission("*", "getClassLoader")) + ); } catch (PrivilegedActionException pe) { throw (InstanceNotFoundException) extractException(pe); } @@ -1345,7 +1350,9 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced { public Object run() throws InstanceNotFoundException { return mbeanServer.getClassLoaderFor(name); } - }); + }, + withPermissions(new MBeanPermission("*", "getClassLoaderFor")) + ); } catch (PrivilegedActionException pe) { throw (InstanceNotFoundException) extractException(pe); } From 1c29d4299bf222478eb9fb59540a8f631c5aaa7d Mon Sep 17 00:00:00 2001 From: Xue-Lei Andrew Fan Date: Sat, 28 Jul 2012 19:42:50 -0700 Subject: [PATCH 08/19] 7186286: TLS implementation to better adhere to RFC Also reviewed by Alexander Fomin , Andrew Gross, Sean Coffey Reviewed-by: valeriep, wetmore --- .../sun/security/ssl/HandshakeInStream.java | 13 ++++- .../classes/sun/security/ssl/Handshaker.java | 4 +- .../security/ssl/RSAClientKeyExchange.java | 56 ++++++++++++------- 3 files changed, 50 insertions(+), 23 deletions(-) diff --git a/jdk/src/share/classes/sun/security/ssl/HandshakeInStream.java b/jdk/src/share/classes/sun/security/ssl/HandshakeInStream.java index f6ca477efe2..81c84643f14 100644 --- a/jdk/src/share/classes/sun/security/ssl/HandshakeInStream.java +++ b/jdk/src/share/classes/sun/security/ssl/HandshakeInStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2012, 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 @@ -190,6 +190,7 @@ public class HandshakeInStream extends InputStream { byte[] getBytes8() throws IOException { int len = getInt8(); + verifyLength(len); byte b[] = new byte[len]; read(b, 0, len); @@ -198,6 +199,7 @@ public class HandshakeInStream extends InputStream { public byte[] getBytes16() throws IOException { int len = getInt16(); + verifyLength(len); byte b[] = new byte[len]; read(b, 0, len); @@ -206,10 +208,19 @@ public class HandshakeInStream extends InputStream { byte[] getBytes24() throws IOException { int len = getInt24(); + verifyLength(len); byte b[] = new byte[len]; read(b, 0, len); return b; } + // Is a length greater than available bytes in the record? + private void verifyLength(int len) throws SSLException { + if (len > available()) { + throw new SSLException( + "Not enough data to fill declared vector size"); + } + } + } diff --git a/jdk/src/share/classes/sun/security/ssl/Handshaker.java b/jdk/src/share/classes/sun/security/ssl/Handshaker.java index 4fb7fec7d61..38dd491f99f 100644 --- a/jdk/src/share/classes/sun/security/ssl/Handshaker.java +++ b/jdk/src/share/classes/sun/security/ssl/Handshaker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2012, 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 @@ -1063,7 +1063,6 @@ abstract class Handshaker { if (debug != null && Debug.isOn("handshake")) { System.out.println("RSA master secret generation error:"); e.printStackTrace(System.out); - System.out.println("Generating new random premaster secret"); } if (requestedVersion != null) { @@ -1130,7 +1129,6 @@ abstract class Handshaker { System.out.println("RSA PreMasterSecret version error: expected" + protocolVersion + " or " + requestedVersion + ", decrypted: " + premasterVersion); - System.out.println("Generating new random premaster secret"); } preMasterSecret = RSAClientKeyExchange.generateDummySecret(requestedVersion); diff --git a/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java b/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java index 1c0d6921091..36fda8c39cb 100644 --- a/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java +++ b/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2012, 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 @@ -36,6 +36,7 @@ import javax.crypto.spec.*; import javax.net.ssl.*; import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec; +import sun.security.util.KeyLength; /** * This is the client key exchange message (CLIENT --> SERVER) used with @@ -192,26 +193,38 @@ final class RSAClientKeyExchange extends HandshakeMessage { "unable to get the plaintext of the premaster secret"); } - // We are not always able to get the encoded key of the - // premaster secret. Pass the cheking to master secret + int keySize = KeyLength.getKeySize(secretKey); + if (keySize > 0 && keySize != 384) { // 384 = 48 * 8 + if (debug != null && Debug.isOn("handshake")) { + System.out.println( + "incorrect length of premaster secret: " + + (keySize/8)); + } + + return generateDummySecret(clientHelloVersion); + } + + // The key size is exactly 48 bytes or not accessible. + // + // Conservatively, pass the checking to master secret // calculation. return secretKey; } else if (encoded.length == 48) { // check the version if (clientHelloVersion.major == encoded[0] && clientHelloVersion.minor == encoded[1]) { + return secretKey; - } else if (clientHelloVersion.v <= ProtocolVersion.TLS10.v) { + } else if (clientHelloVersion.v <= ProtocolVersion.TLS10.v && + currentVersion.major == encoded[0] && + currentVersion.minor == encoded[1]) { /* - * we never checked the client_version in server side - * for TLS v1.0 and SSL v3.0. For compatibility, we - * maintain this behavior. + * For compatibility, we maintain the behavior that the + * version in pre_master_secret can be the negotiated + * version for TLS v1.0 and SSL v3.0. */ - if (currentVersion.major == encoded[0] && - currentVersion.minor == encoded[1]) { - this.protocolVersion = currentVersion; - return secretKey; - } + this.protocolVersion = currentVersion; + return secretKey; } if (debug != null && Debug.isOn("handshake")) { @@ -220,22 +233,23 @@ final class RSAClientKeyExchange extends HandshakeMessage { ", while PreMasterSecret.client_version is " + ProtocolVersion.valueOf(encoded[0], encoded[1])); } + + return generateDummySecret(clientHelloVersion); } else { if (debug != null && Debug.isOn("handshake")) { System.out.println( "incorrect length of premaster secret: " + encoded.length); } + + return generateDummySecret(clientHelloVersion); } } - if (debug != null && Debug.isOn("handshake")) { - if (failoverException != null) { - System.out.println("Error decrypting premaster secret:"); - failoverException.printStackTrace(System.out); - } - - System.out.println("Generating random secret"); + if (debug != null && Debug.isOn("handshake") && + failoverException != null) { + System.out.println("Error decrypting premaster secret:"); + failoverException.printStackTrace(System.out); } return generateDummySecret(clientHelloVersion); @@ -243,6 +257,10 @@ final class RSAClientKeyExchange extends HandshakeMessage { // generate a premaster secret with the specified version number static SecretKey generateDummySecret(ProtocolVersion version) { + if (debug != null && Debug.isOn("handshake")) { + System.out.println("Generating a random fake premaster secret"); + } + try { String s = ((version.v >= ProtocolVersion.TLS12.v) ? "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret"); From e5fbf0148998595f148f340e8f663afa5a99eefa Mon Sep 17 00:00:00 2001 From: Sean Mullan Date: Wed, 15 Aug 2012 15:31:30 -0400 Subject: [PATCH 09/19] 7189490: More improvements to DomainCombiner checking Reviewed-by: ahgross, jdn, vinnie --- .../java/security/AccessController.java | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/jdk/src/share/classes/java/security/AccessController.java b/jdk/src/share/classes/java/security/AccessController.java index 8a8eadea62d..4e790ffc8da 100644 --- a/jdk/src/share/classes/java/security/AccessController.java +++ b/jdk/src/share/classes/java/security/AccessController.java @@ -290,11 +290,11 @@ public final class AccessController { */ public static T doPrivilegedWithCombiner(PrivilegedAction action) { - DomainCombiner dc = null; AccessControlContext acc = getStackAccessControlContext(); - if (acc == null || (dc = acc.getAssignedCombiner()) == null) { - return AccessController.doPrivileged(action, acc); + if (acc == null) { + return AccessController.doPrivileged(action); } + DomainCombiner dc = acc.getAssignedCombiner(); return AccessController.doPrivileged(action, preserveCombiner(dc)); } @@ -386,11 +386,11 @@ public final class AccessController { public static T doPrivilegedWithCombiner (PrivilegedExceptionAction action) throws PrivilegedActionException { - DomainCombiner dc = null; AccessControlContext acc = getStackAccessControlContext(); - if (acc == null || (dc = acc.getAssignedCombiner()) == null) { - return AccessController.doPrivileged(action, acc); + if (acc == null) { + return AccessController.doPrivileged(action); } + DomainCombiner dc = acc.getAssignedCombiner(); return AccessController.doPrivileged(action, preserveCombiner(dc)); } @@ -417,7 +417,12 @@ public final class AccessController { // perform 'combine' on the caller of doPrivileged, // even if the caller is from the bootclasspath ProtectionDomain[] pds = new ProtectionDomain[] {callerPd}; - return new AccessControlContext(combiner.combine(pds, null), combiner); + if (combiner == null) { + return new AccessControlContext(pds); + } else { + return new AccessControlContext(combiner.combine(pds, null), + combiner); + } } From 9f27d2af4c0366b2ae376c510b28a80c17ac90ee Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Thu, 16 Aug 2012 15:02:34 +0100 Subject: [PATCH 10/19] 7189103: Executors needs to maintain state Reviewed-by: dholmes, hawtin --- .../java/util/concurrent/Executors.java | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/jdk/src/share/classes/java/util/concurrent/Executors.java b/jdk/src/share/classes/java/util/concurrent/Executors.java index 4ff71418422..78708f8d773 100644 --- a/jdk/src/share/classes/java/util/concurrent/Executors.java +++ b/jdk/src/share/classes/java/util/concurrent/Executors.java @@ -530,18 +530,17 @@ public class Executors { return AccessController.doPrivileged( new PrivilegedExceptionAction() { public T run() throws Exception { - ClassLoader savedcl = null; Thread t = Thread.currentThread(); - try { - ClassLoader cl = t.getContextClassLoader(); - if (ccl != cl) { - t.setContextClassLoader(ccl); - savedcl = cl; - } + ClassLoader cl = t.getContextClassLoader(); + if (ccl == cl) { return task.call(); - } finally { - if (savedcl != null) - t.setContextClassLoader(savedcl); + } else { + t.setContextClassLoader(ccl); + try { + return task.call(); + } finally { + t.setContextClassLoader(cl); + } } } }, acc); From 84603e4d94b7a0504aa1284a341c24a8ab9284f2 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Wed, 29 Aug 2012 14:05:37 +0100 Subject: [PATCH 11/19] 7189567: java net obselete protocol Reviewed-by: alanb, ahgross --- jdk/make/sun/net/FILES_java.gmk | 2 - .../net/www/protocol/gopher/GopherClient.java | 357 ------------------ .../sun/net/www/protocol/gopher/Handler.java | 100 ----- jdk/test/java/net/URL/Test.java | 4 - 4 files changed, 463 deletions(-) delete mode 100644 jdk/src/share/classes/sun/net/www/protocol/gopher/GopherClient.java delete mode 100644 jdk/src/share/classes/sun/net/www/protocol/gopher/Handler.java diff --git a/jdk/make/sun/net/FILES_java.gmk b/jdk/make/sun/net/FILES_java.gmk index 6c140abc68b..9c5feb4457e 100644 --- a/jdk/make/sun/net/FILES_java.gmk +++ b/jdk/make/sun/net/FILES_java.gmk @@ -128,8 +128,6 @@ FILES_java = \ sun/net/www/content/audio/x_wav.java \ sun/net/www/protocol/ftp/Handler.java \ sun/net/www/protocol/ftp/FtpURLConnection.java \ - sun/net/www/protocol/gopher/GopherClient.java \ - sun/net/www/protocol/gopher/Handler.java \ sun/net/www/protocol/mailto/Handler.java \ sun/net/www/protocol/mailto/MailToURLConnection.java \ sun/net/idn/Punycode.java \ diff --git a/jdk/src/share/classes/sun/net/www/protocol/gopher/GopherClient.java b/jdk/src/share/classes/sun/net/www/protocol/gopher/GopherClient.java deleted file mode 100644 index 03470634a37..00000000000 --- a/jdk/src/share/classes/sun/net/www/protocol/gopher/GopherClient.java +++ /dev/null @@ -1,357 +0,0 @@ -/* - * Copyright (c) 1996, 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 - * 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.net.www.protocol.gopher; - -import java.io.*; -import java.util.*; -import java.net.*; -import sun.net.www.*; -import sun.net.NetworkClient; -import java.net.URL; -import java.net.URLStreamHandler; - -import sun.security.action.GetBooleanAction; - -/** Class to maintain the state of a gopher fetch and handle the protocol */ -public class GopherClient extends NetworkClient implements Runnable { - - /* The following three data members are left in for binary - * backwards-compatibility. Unfortunately, HotJava sets them directly - * when it wants to change the settings. The new design has us not - * cache these, so this is unnecessary, but eliminating the data members - * would break HJB 1.1 under JDK 1.2. - * - * These data members are not used, and their values are meaningless. - * REMIND: Take them out for JDK 2.0! - */ - - /** - * @deprecated - */ - @Deprecated - public static boolean useGopherProxy; - - /** - * @deprecated - */ - @Deprecated - public static String gopherProxyHost; - - /** - * @deprecated - */ - @Deprecated - public static int gopherProxyPort; - - - static { - useGopherProxy = java.security.AccessController.doPrivileged( - new sun.security.action.GetBooleanAction("gopherProxySet")) - .booleanValue(); - - gopherProxyHost = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("gopherProxyHost")); - - gopherProxyPort = java.security.AccessController.doPrivileged( - new sun.security.action.GetIntegerAction("gopherProxyPort", 80)) - .intValue(); - } - - PipedOutputStream os; - URL u; - int gtype; - String gkey; - sun.net.www.URLConnection connection; - - GopherClient(sun.net.www.URLConnection connection) { - this.connection = connection; - } - - /** - * @return true if gopher connections should go through a proxy, according - * to system properties. - */ - public static boolean getUseGopherProxy() { - return java.security.AccessController.doPrivileged( - new GetBooleanAction("gopherProxySet")).booleanValue(); - } - - /** - * @return the proxy host to use, or null if nothing is set. - */ - public static String getGopherProxyHost() { - String host = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("gopherProxyHost")); - if ("".equals(host)) { - host = null; - } - return host; - } - - /** - * @return the proxy port to use. Will default reasonably. - */ - public static int getGopherProxyPort() { - return java.security.AccessController.doPrivileged( - new sun.security.action.GetIntegerAction("gopherProxyPort", 80)) - .intValue(); - } - - /** Given a url, setup to fetch the gopher document it refers to */ - InputStream openStream(URL u) throws IOException { - this.u = u; - this.os = os; - int i = 0; - String s = u.getFile(); - int limit = s.length(); - int c = '1'; - while (i < limit && (c = s.charAt(i)) == '/') - i++; - gtype = c == '/' ? '1' : c; - if (i < limit) - i++; - gkey = s.substring(i); - - openServer(u.getHost(), u.getPort() <= 0 ? 70 : u.getPort()); - - MessageHeader msgh = new MessageHeader(); - - switch (gtype) { - case '0': - case '7': - msgh.add("content-type", "text/plain"); - break; - case '1': - msgh.add("content-type", "text/html"); - break; - case 'g': - case 'I': - msgh.add("content-type", "image/gif"); - break; - default: - msgh.add("content-type", "content/unknown"); - break; - } - if (gtype != '7') { - serverOutput.print(decodePercent(gkey) + "\r\n"); - serverOutput.flush(); - } else if ((i = gkey.indexOf('?')) >= 0) { - serverOutput.print(decodePercent(gkey.substring(0, i) + "\t" + - gkey.substring(i + 1) + "\r\n")); - serverOutput.flush(); - msgh.add("content-type", "text/html"); - } else { - msgh.add("content-type", "text/html"); - } - connection.setProperties(msgh); - if (msgh.findValue("content-type") == "text/html") { - os = new PipedOutputStream(); - PipedInputStream ret = new PipedInputStream(); - ret.connect(os); - new Thread(this).start(); - return ret; - } - return new GopherInputStream(this, serverInput); - } - - /** Translate all the instances of %NN into the character they represent */ - private String decodePercent(String s) { - if (s == null || s.indexOf('%') < 0) - return s; - int limit = s.length(); - char d[] = new char[limit]; - int dp = 0; - for (int sp = 0; sp < limit; sp++) { - int c = s.charAt(sp); - if (c == '%' && sp + 2 < limit) { - int s1 = s.charAt(sp + 1); - int s2 = s.charAt(sp + 2); - if ('0' <= s1 && s1 <= '9') - s1 = s1 - '0'; - else if ('a' <= s1 && s1 <= 'f') - s1 = s1 - 'a' + 10; - else if ('A' <= s1 && s1 <= 'F') - s1 = s1 - 'A' + 10; - else - s1 = -1; - if ('0' <= s2 && s2 <= '9') - s2 = s2 - '0'; - else if ('a' <= s2 && s2 <= 'f') - s2 = s2 - 'a' + 10; - else if ('A' <= s2 && s2 <= 'F') - s2 = s2 - 'A' + 10; - else - s2 = -1; - if (s1 >= 0 && s2 >= 0) { - c = (s1 << 4) | s2; - sp += 2; - } - } - d[dp++] = (char) c; - } - return new String(d, 0, dp); - } - - /** Turn special characters into the %NN form */ - private String encodePercent(String s) { - if (s == null) - return s; - int limit = s.length(); - char d[] = null; - int dp = 0; - for (int sp = 0; sp < limit; sp++) { - int c = s.charAt(sp); - if (c <= ' ' || c == '"' || c == '%') { - if (d == null) - d = s.toCharArray(); - if (dp + 3 >= d.length) { - char nd[] = new char[dp + 10]; - System.arraycopy(d, 0, nd, 0, dp); - d = nd; - } - d[dp] = '%'; - int dig = (c >> 4) & 0xF; - d[dp + 1] = (char) (dig < 10 ? '0' + dig : 'A' - 10 + dig); - dig = c & 0xF; - d[dp + 2] = (char) (dig < 10 ? '0' + dig : 'A' - 10 + dig); - dp += 3; - } else { - if (d != null) { - if (dp >= d.length) { - char nd[] = new char[dp + 10]; - System.arraycopy(d, 0, nd, 0, dp); - d = nd; - } - d[dp] = (char) c; - } - dp++; - } - } - return d == null ? s : new String(d, 0, dp); - } - - /** This method is run as a seperate thread when an incoming gopher - document requires translation to html */ - public void run() { - int qpos = -1; - try { - if (gtype == '7' && (qpos = gkey.indexOf('?')) < 0) { - PrintStream ps = new PrintStream(os, false, encoding); - ps.print("Searchable Gopher Index\n

Searchable Gopher Index

\n\n"); - } else if (gtype != '1' && gtype != '7') { - byte buf[] = new byte[2048]; - try { - int n; - while ((n = serverInput.read(buf)) >= 0) - os.write(buf, 0, n); - } catch(Exception e) { - } - } else { - PrintStream ps = new PrintStream(os, false, encoding); - String title = null; - if (gtype == '7') - title = "Results of searching for \"" + gkey.substring(qpos + 1) - + "\" on " + u.getHost(); - else - title = "Gopher directory " + gkey + " from " + u.getHost(); - ps.print(""); - ps.print(title); - ps.print("\n\n

"); - ps.print(title); - ps.print("

\n"); - BufferedReader ds = new BufferedReader(new InputStreamReader(serverInput)); - String s; - while ((s = ds.readLine()) != null) { - int len = s.length(); - while (len > 0 && s.charAt(len - 1) <= ' ') - len--; - if (len <= 0) - continue; - int key = s.charAt(0); - int t1 = s.indexOf('\t'); - int t2 = t1 > 0 ? s.indexOf('\t', t1 + 1) : -1; - int t3 = t2 > 0 ? s.indexOf('\t', t2 + 1) : -1; - if (t3 < 0) { - // ps.print("
"+s+"\n"); - continue; - } - String port = t3 + 1 < len ? ":" + s.substring(t3 + 1, len) : ""; - String host = t2 + 1 < t3 ? s.substring(t2 + 1, t3) : u.getHost(); - ps.print("
\n"); - ps.print("
\n"); - ps.print(s.substring(1, t1) + "\n"); - } - ps.print("
\n"); - ps.close(); - } - - } catch (UnsupportedEncodingException e) { - throw new InternalError(encoding+ " encoding not found", e); - } catch (IOException e) { - } finally { - try { - closeServer(); - os.close(); - } catch (IOException e2) { - } - } - } -} - -/** An input stream that does nothing more than hold on to the NetworkClient - that created it. This is used when only the input stream is needed, and - the network client needs to be closed when the input stream is closed. */ -class GopherInputStream extends FilterInputStream { - NetworkClient parent; - - GopherInputStream(NetworkClient o, InputStream fd) { - super(fd); - parent = o; - } - - public void close() { - try { - parent.closeServer(); - super.close(); - } catch (IOException e) { - } - } -} diff --git a/jdk/src/share/classes/sun/net/www/protocol/gopher/Handler.java b/jdk/src/share/classes/sun/net/www/protocol/gopher/Handler.java deleted file mode 100644 index 800985960a3..00000000000 --- a/jdk/src/share/classes/sun/net/www/protocol/gopher/Handler.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 1995, 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 - * 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.net.www.protocol.gopher; - -import java.io.*; -import java.util.*; -import sun.net.NetworkClient; -import java.net.URL; -import java.net.URLStreamHandler; -import java.net.Proxy; -import java.net.InetSocketAddress; -import java.net.SocketPermission; -import java.security.Permission; -import sun.net.www.protocol.http.HttpURLConnection; - -/** - * A class to handle the gopher protocol. - */ - -public class Handler extends java.net.URLStreamHandler { - - protected int getDefaultPort() { - return 70; - } - - public java.net.URLConnection openConnection(URL u) - throws IOException { - return openConnection(u, null); - } - - public java.net.URLConnection openConnection(URL u, Proxy p) - throws IOException { - - - /* if set for proxy usage then go through the http code to get */ - /* the url connection. */ - if (p == null && GopherClient.getUseGopherProxy()) { - String host = GopherClient.getGopherProxyHost(); - if (host != null) { - InetSocketAddress saddr = InetSocketAddress.createUnresolved(host, GopherClient.getGopherProxyPort()); - - p = new Proxy(Proxy.Type.HTTP, saddr); - } - } - if (p != null) { - return new HttpURLConnection(u, p); - } - - return new GopherURLConnection(u); - } -} - -class GopherURLConnection extends sun.net.www.URLConnection { - - Permission permission; - - GopherURLConnection(URL u) { - super(u); - } - - public void connect() throws IOException { - } - - public InputStream getInputStream() throws IOException { - return new GopherClient(this).openStream(url); - } - - public Permission getPermission() { - if (permission == null) { - int port = url.getPort(); - port = port < 0 ? 70 : port; - String host = url.getHost() + ":" + url.getPort(); - permission = new SocketPermission(host, "connect"); - } - return permission; - } -} diff --git a/jdk/test/java/net/URL/Test.java b/jdk/test/java/net/URL/Test.java index 58c88182723..5a0909efe26 100644 --- a/jdk/test/java/net/URL/Test.java +++ b/jdk/test/java/net/URL/Test.java @@ -322,10 +322,6 @@ public class Test { test("ftp://ftp.is.co.za/rfc/rfc1808.txt") .s("ftp").h("ftp.is.co.za").p("/rfc/rfc1808.txt").z(); - test("gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles") - .s("gopher").h("spinaltap.micro.umn.edu") - .p("/00/Weather/California/Los%20Angeles").z(); - test("http://www.math.uio.no/faq/compression-faq/part1.html") .s("http").h("www.math.uio.no").p("/faq/compression-faq/part1.html").z(); From c6f43f359973f7ee8826c4ed250f38668e94e5dc Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Sat, 8 Sep 2012 20:31:42 +0100 Subject: [PATCH 12/19] 7169884: LogManager checks do not work correctly for sub-types Reviewed-by: mchung, ahgross --- .../java/util/logging/FileHandler.java | 12 +++++----- .../classes/java/util/logging/Handler.java | 16 ++++++------- .../classes/java/util/logging/LogManager.java | 23 ++++++++++--------- .../classes/java/util/logging/Logger.java | 16 ++++++------- .../java/util/logging/MemoryHandler.java | 2 +- .../java/util/logging/StreamHandler.java | 2 +- 6 files changed, 36 insertions(+), 35 deletions(-) diff --git a/jdk/src/share/classes/java/util/logging/FileHandler.java b/jdk/src/share/classes/java/util/logging/FileHandler.java index fb3b67c4d92..b9a5d73c341 100644 --- a/jdk/src/share/classes/java/util/logging/FileHandler.java +++ b/jdk/src/share/classes/java/util/logging/FileHandler.java @@ -220,7 +220,7 @@ public class FileHandler extends StreamHandler { * @exception NullPointerException if pattern property is an empty String. */ public FileHandler() throws IOException, SecurityException { - checkAccess(); + checkPermission(); configure(); openFiles(); } @@ -246,7 +246,7 @@ public class FileHandler extends StreamHandler { if (pattern.length() < 1 ) { throw new IllegalArgumentException(); } - checkAccess(); + checkPermission(); configure(); this.pattern = pattern; this.limit = 0; @@ -278,7 +278,7 @@ public class FileHandler extends StreamHandler { if (pattern.length() < 1 ) { throw new IllegalArgumentException(); } - checkAccess(); + checkPermission(); configure(); this.pattern = pattern; this.limit = 0; @@ -315,7 +315,7 @@ public class FileHandler extends StreamHandler { if (limit < 0 || count < 1 || pattern.length() < 1) { throw new IllegalArgumentException(); } - checkAccess(); + checkPermission(); configure(); this.pattern = pattern; this.limit = limit; @@ -354,7 +354,7 @@ public class FileHandler extends StreamHandler { if (limit < 0 || count < 1 || pattern.length() < 1) { throw new IllegalArgumentException(); } - checkAccess(); + checkPermission(); configure(); this.pattern = pattern; this.limit = limit; @@ -367,7 +367,7 @@ public class FileHandler extends StreamHandler { // configured instance variables. private void openFiles() throws IOException { LogManager manager = LogManager.getLogManager(); - manager.checkAccess(); + manager.checkPermission(); if (count < 1) { throw new IllegalArgumentException("file count = " + count); } diff --git a/jdk/src/share/classes/java/util/logging/Handler.java b/jdk/src/share/classes/java/util/logging/Handler.java index 1317b572d92..fd04c2cb496 100644 --- a/jdk/src/share/classes/java/util/logging/Handler.java +++ b/jdk/src/share/classes/java/util/logging/Handler.java @@ -111,7 +111,7 @@ public abstract class Handler { * the caller does not have LoggingPermission("control"). */ public void setFormatter(Formatter newFormatter) throws SecurityException { - checkAccess(); + checkPermission(); // Check for a null pointer: newFormatter.getClass(); formatter = newFormatter; @@ -140,7 +140,7 @@ public abstract class Handler { */ public void setEncoding(String encoding) throws SecurityException, java.io.UnsupportedEncodingException { - checkAccess(); + checkPermission(); if (encoding != null) { try { if(!java.nio.charset.Charset.isSupported(encoding)) { @@ -175,7 +175,7 @@ public abstract class Handler { * the caller does not have LoggingPermission("control"). */ public void setFilter(Filter newFilter) throws SecurityException { - checkAccess(); + checkPermission(); filter = newFilter; } @@ -199,7 +199,7 @@ public abstract class Handler { * the caller does not have LoggingPermission("control"). */ public void setErrorManager(ErrorManager em) { - checkAccess(); + checkPermission(); if (em == null) { throw new NullPointerException(); } @@ -213,7 +213,7 @@ public abstract class Handler { * the caller does not have LoggingPermission("control"). */ public ErrorManager getErrorManager() { - checkAccess(); + checkPermission(); return errorManager; } @@ -253,7 +253,7 @@ public abstract class Handler { if (newLevel == null) { throw new NullPointerException(); } - checkAccess(); + checkPermission(); logLevel = newLevel; } @@ -296,9 +296,9 @@ public abstract class Handler { // If "sealed" is true, we check that the caller has // appropriate security privileges to update Handler // state and if not throw a SecurityException. - void checkAccess() throws SecurityException { + void checkPermission() throws SecurityException { if (sealed) { - manager.checkAccess(); + manager.checkPermission(); } } } diff --git a/jdk/src/share/classes/java/util/logging/LogManager.java b/jdk/src/share/classes/java/util/logging/LogManager.java index 24f61b46f74..bfdf83f93da 100644 --- a/jdk/src/share/classes/java/util/logging/LogManager.java +++ b/jdk/src/share/classes/java/util/logging/LogManager.java @@ -314,7 +314,7 @@ public class LogManager { */ public void addPropertyChangeListener(PropertyChangeListener l) throws SecurityException { PropertyChangeListener listener = Objects.requireNonNull(l); - checkAccess(); + checkPermission(); synchronized (listenerMap) { // increment the registration count if already registered Integer value = listenerMap.get(listener); @@ -338,7 +338,7 @@ public class LogManager { * the caller does not have LoggingPermission("control"). */ public void removePropertyChangeListener(PropertyChangeListener l) throws SecurityException { - checkAccess(); + checkPermission(); if (l != null) { PropertyChangeListener listener = l; synchronized (listenerMap) { @@ -793,7 +793,7 @@ public class LogManager { * @exception IOException if there are IO problems reading the configuration. */ public void readConfiguration() throws IOException, SecurityException { - checkAccess(); + checkPermission(); // if a configuration class is specified, load it and use it. String cname = System.getProperty("java.util.logging.config.class"); @@ -851,7 +851,7 @@ public class LogManager { */ public void reset() throws SecurityException { - checkAccess(); + checkPermission(); synchronized (this) { props = new Properties(); // Since we are doing a reset we no longer want to initialize @@ -936,7 +936,7 @@ public class LogManager { * @exception IOException if there are problems reading from the stream. */ public void readConfiguration(InputStream ins) throws IOException, SecurityException { - checkAccess(); + checkPermission(); reset(); // Load the properties @@ -1113,8 +1113,13 @@ public class LogManager { loadLoggerHandlers(rootLogger, null, "handlers"); } + private final Permission controlPermission = new LoggingPermission("control", null); - private Permission ourPermission = new LoggingPermission("control", null); + void checkPermission() { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkPermission(controlPermission); + } /** * Check that the current context is trusted to modify the logging @@ -1127,11 +1132,7 @@ public class LogManager { * the caller does not have LoggingPermission("control"). */ public void checkAccess() throws SecurityException { - SecurityManager sm = System.getSecurityManager(); - if (sm == null) { - return; - } - sm.checkPermission(ourPermission); + checkPermission(); } // Nested class to represent a node in our tree of named loggers. diff --git a/jdk/src/share/classes/java/util/logging/Logger.java b/jdk/src/share/classes/java/util/logging/Logger.java index aebf63ed5e8..f1d6f729b91 100644 --- a/jdk/src/share/classes/java/util/logging/Logger.java +++ b/jdk/src/share/classes/java/util/logging/Logger.java @@ -276,13 +276,13 @@ public class Logger { this.manager = manager; } - private void checkAccess() throws SecurityException { + private void checkPermission() throws SecurityException { if (!anonymous) { if (manager == null) { // Complete initialization of the global Logger. manager = LogManager.getLogManager(); } - manager.checkAccess(); + manager.checkPermission(); } } @@ -482,7 +482,7 @@ public class Logger { * the caller does not have LoggingPermission("control"). */ public void setFilter(Filter newFilter) throws SecurityException { - checkAccess(); + checkPermission(); filter = newFilter; } @@ -1168,7 +1168,7 @@ public class Logger { * the caller does not have LoggingPermission("control"). */ public void setLevel(Level newLevel) throws SecurityException { - checkAccess(); + checkPermission(); synchronized (treeLock) { levelObject = newLevel; updateEffectiveLevel(); @@ -1223,7 +1223,7 @@ public class Logger { public void addHandler(Handler handler) throws SecurityException { // Check for null handler handler.getClass(); - checkAccess(); + checkPermission(); handlers.add(handler); } @@ -1237,7 +1237,7 @@ public class Logger { * the caller does not have LoggingPermission("control"). */ public void removeHandler(Handler handler) throws SecurityException { - checkAccess(); + checkPermission(); if (handler == null) { return; } @@ -1265,7 +1265,7 @@ public class Logger { * the caller does not have LoggingPermission("control"). */ public void setUseParentHandlers(boolean useParentHandlers) { - checkAccess(); + checkPermission(); this.useParentHandlers = useParentHandlers; } @@ -1420,7 +1420,7 @@ public class Logger { if (parent == null) { throw new NullPointerException(); } - manager.checkAccess(); + manager.checkPermission(); doSetParent(parent); } diff --git a/jdk/src/share/classes/java/util/logging/MemoryHandler.java b/jdk/src/share/classes/java/util/logging/MemoryHandler.java index 2c297301d92..06c0930ed5c 100644 --- a/jdk/src/share/classes/java/util/logging/MemoryHandler.java +++ b/jdk/src/share/classes/java/util/logging/MemoryHandler.java @@ -238,7 +238,7 @@ public class MemoryHandler extends Handler { throw new NullPointerException(); } LogManager manager = LogManager.getLogManager(); - checkAccess(); + checkPermission(); pushLevel = newLevel; } diff --git a/jdk/src/share/classes/java/util/logging/StreamHandler.java b/jdk/src/share/classes/java/util/logging/StreamHandler.java index 9ed9e57b768..f6407ec2bfd 100644 --- a/jdk/src/share/classes/java/util/logging/StreamHandler.java +++ b/jdk/src/share/classes/java/util/logging/StreamHandler.java @@ -249,7 +249,7 @@ public class StreamHandler extends Handler { } private synchronized void flushAndClose() throws SecurityException { - checkAccess(); + checkPermission(); if (writer != null) { try { if (!doneHeader) { From 7004635879b74a308e9f47af207cc4972d974ccd Mon Sep 17 00:00:00 2001 From: Stuart Marks Date: Mon, 10 Sep 2012 16:05:53 -0700 Subject: [PATCH 13/19] 7195919: (sl) ServiceLoader can throw CCE without needing to create instance Reviewed-by: ahgross, alanb, dmeetry --- .../share/classes/java/util/ServiceLoader.java | 15 +++++++++++---- jdk/src/share/classes/sun/misc/Service.java | 12 ++++++++++-- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/jdk/src/share/classes/java/util/ServiceLoader.java b/jdk/src/share/classes/java/util/ServiceLoader.java index 62aa9dd2453..37176c677a9 100644 --- a/jdk/src/share/classes/java/util/ServiceLoader.java +++ b/jdk/src/share/classes/java/util/ServiceLoader.java @@ -358,14 +358,21 @@ public final class ServiceLoader } String cn = nextName; nextName = null; + Class c = null; try { - S p = service.cast(Class.forName(cn, true, loader) - .newInstance()); - providers.put(cn, p); - return p; + c = Class.forName(cn, false, loader); } catch (ClassNotFoundException x) { fail(service, "Provider " + cn + " not found"); + } + if (!service.isAssignableFrom(c)) { + fail(service, + "Provider " + cn + " not a subtype"); + } + try { + S p = service.cast(c.newInstance()); + providers.put(cn, p); + return p; } catch (Throwable x) { fail(service, "Provider " + cn + " could not be instantiated: " + x, diff --git a/jdk/src/share/classes/sun/misc/Service.java b/jdk/src/share/classes/sun/misc/Service.java index 37d39b43019..d74abbd1cb3 100644 --- a/jdk/src/share/classes/sun/misc/Service.java +++ b/jdk/src/share/classes/sun/misc/Service.java @@ -284,12 +284,20 @@ public final class Service { } String cn = nextName; nextName = null; + Class c = null; try { - return service.cast(Class.forName(cn, true, loader).newInstance()); + c = Class.forName(cn, false, loader); } catch (ClassNotFoundException x) { fail(service, "Provider " + cn + " not found"); - } catch (Exception x) { + } + if (!service.isAssignableFrom(c)) { + fail(service, + "Provider " + cn + " not a subtype"); + } + try { + return service.cast(c.newInstance()); + } catch (Throwable x) { fail(service, "Provider " + cn + " could not be instantiated: " + x, x); From e539ff810a49ab7948c7a7194b371849b5afedad Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Tue, 11 Sep 2012 12:57:09 +0400 Subject: [PATCH 14/19] 7195549: Better bean object persistence Reviewed-by: art, ahgross --- .../sun/beans/decoder/PropertyElementHandler.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/jdk/src/share/classes/com/sun/beans/decoder/PropertyElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/PropertyElementHandler.java index f20829385d4..8f4c40cac93 100644 --- a/jdk/src/share/classes/com/sun/beans/decoder/PropertyElementHandler.java +++ b/jdk/src/share/classes/com/sun/beans/decoder/PropertyElementHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2012, 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 @@ -35,6 +35,8 @@ import java.lang.reflect.Array; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import sun.reflect.misc.MethodUtil; + /** * This class is intended to handle <property> element. * This element simplifies access to the properties. @@ -168,11 +170,11 @@ final class PropertyElementHandler extends AccessorElementHandler { private static Object getPropertyValue(Object bean, String name, Integer index) throws IllegalAccessException, IntrospectionException, InvocationTargetException, NoSuchMethodException { Class type = bean.getClass(); if (index == null) { - return findGetter(type, name).invoke(bean); + return MethodUtil.invoke(findGetter(type, name), bean, new Object[] {}); } else if (type.isArray() && (name == null)) { return Array.get(bean, index); } else { - return findGetter(type, name, int.class).invoke(bean, index); + return MethodUtil.invoke(findGetter(type, name, int.class), bean, new Object[] {index}); } } @@ -197,11 +199,11 @@ final class PropertyElementHandler extends AccessorElementHandler { : null; if (index == null) { - findSetter(type, name, param).invoke(bean, value); + MethodUtil.invoke(findSetter(type, name, param), bean, new Object[] {value}); } else if (type.isArray() && (name == null)) { Array.set(bean, index, value); } else { - findSetter(type, name, int.class, param).invoke(bean, index, value); + MethodUtil.invoke(findSetter(type, name, int.class, param), bean, new Object[] {index, value}); } } From 41e85e364f92496350236119d170ae7544ca7518 Mon Sep 17 00:00:00 2001 From: Pavel Porvatov Date: Tue, 11 Sep 2012 15:59:24 +0400 Subject: [PATCH 15/19] 7195194: Better data validation for Swing Reviewed-by: art, ahgross --- jdk/src/share/classes/javax/swing/text/DefaultFormatter.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jdk/src/share/classes/javax/swing/text/DefaultFormatter.java b/jdk/src/share/classes/javax/swing/text/DefaultFormatter.java index 5e003b55bca..b67966ab70a 100644 --- a/jdk/src/share/classes/javax/swing/text/DefaultFormatter.java +++ b/jdk/src/share/classes/javax/swing/text/DefaultFormatter.java @@ -24,6 +24,8 @@ */ package javax.swing.text; +import sun.reflect.misc.ConstructorUtil; + import java.io.Serializable; import java.lang.reflect.*; import java.text.ParseException; @@ -245,7 +247,7 @@ public class DefaultFormatter extends JFormattedTextField.AbstractFormatter Constructor cons; try { - cons = vc.getConstructor(new Class[] { String.class }); + cons = ConstructorUtil.getConstructor(vc, new Class[]{String.class}); } catch (NoSuchMethodException nsme) { cons = null; From 1a3e1b43e0f5a1b16abc8a127dd20680dfa6624c Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Wed, 19 Sep 2012 21:42:21 +0400 Subject: [PATCH 16/19] 7195917: XMLDecoder parsing at close-time should be improved Reviewed-by: art, ahgross --- .../sun/beans/decoder/DocumentHandler.java | 55 ++++++++++++------- .../share/classes/java/beans/XMLDecoder.java | 16 +++++- 2 files changed, 48 insertions(+), 23 deletions(-) diff --git a/jdk/src/share/classes/com/sun/beans/decoder/DocumentHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/DocumentHandler.java index f454006ab7e..4bbb8f4a201 100644 --- a/jdk/src/share/classes/com/sun/beans/decoder/DocumentHandler.java +++ b/jdk/src/share/classes/com/sun/beans/decoder/DocumentHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2012, 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 @@ -37,6 +37,9 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.PrivilegedAction; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParserFactory; @@ -46,6 +49,8 @@ import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; +import sun.misc.SharedSecrets; + /** * The main class to parse JavaBeans XML archive. * @@ -56,11 +61,10 @@ import org.xml.sax.helpers.DefaultHandler; * @see ElementHandler */ public final class DocumentHandler extends DefaultHandler { - private final Map> handlers = new HashMap>(); - - private final Map environment = new HashMap(); - - private final List objects = new ArrayList(); + private final AccessControlContext acc = AccessController.getContext(); + private final Map> handlers = new HashMap<>(); + private final Map environment = new HashMap<>(); + private final List objects = new ArrayList<>(); private Reference loader; private ExceptionListener listener; @@ -351,23 +355,32 @@ public final class DocumentHandler extends DefaultHandler { * * @param input the input source to parse */ - public void parse(InputSource input) { - try { - SAXParserFactory.newInstance().newSAXParser().parse(input, this); + public void parse(final InputSource input) { + if ((this.acc == null) && (null != System.getSecurityManager())) { + throw new SecurityException("AccessControlContext is not set"); } - catch (ParserConfigurationException exception) { - handleException(exception); - } - catch (SAXException wrapper) { - Exception exception = wrapper.getException(); - if (exception == null) { - exception = wrapper; + AccessControlContext stack = AccessController.getContext(); + SharedSecrets.getJavaSecurityAccess().doIntersectionPrivilege(new PrivilegedAction() { + public Void run() { + try { + SAXParserFactory.newInstance().newSAXParser().parse(input, DocumentHandler.this); + } + catch (ParserConfigurationException exception) { + handleException(exception); + } + catch (SAXException wrapper) { + Exception exception = wrapper.getException(); + if (exception == null) { + exception = wrapper; + } + handleException(exception); + } + catch (IOException exception) { + handleException(exception); + } + return null; } - handleException(exception); - } - catch (IOException exception) { - handleException(exception); - } + }, stack, this.acc); } /** diff --git a/jdk/src/share/classes/java/beans/XMLDecoder.java b/jdk/src/share/classes/java/beans/XMLDecoder.java index accef1199c9..2fb2fd0ef4d 100644 --- a/jdk/src/share/classes/java/beans/XMLDecoder.java +++ b/jdk/src/share/classes/java/beans/XMLDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, 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,9 @@ import com.sun.beans.decoder.DocumentHandler; import java.io.Closeable; import java.io.InputStream; import java.io.IOException; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.PrivilegedAction; import org.xml.sax.InputSource; import org.xml.sax.helpers.DefaultHandler; @@ -61,6 +64,7 @@ import org.xml.sax.helpers.DefaultHandler; * @author Philip Milne */ public class XMLDecoder implements AutoCloseable { + private final AccessControlContext acc = AccessController.getContext(); private final DocumentHandler handler = new DocumentHandler(); private final InputSource input; private Object owner; @@ -189,7 +193,15 @@ public class XMLDecoder implements AutoCloseable { return false; } if (this.array == null) { - this.handler.parse(this.input); + if ((this.acc == null) && (null != System.getSecurityManager())) { + throw new SecurityException("AccessControlContext is not set"); + } + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + XMLDecoder.this.handler.parse(XMLDecoder.this.input); + return null; + } + }, this.acc); this.array = this.handler.getObjects(); } return true; From 0a735e76f68ae912e6eb380c98cc1d7f20d314aa Mon Sep 17 00:00:00 2001 From: John R Rose Date: Thu, 20 Sep 2012 14:02:55 -0700 Subject: [PATCH 17/19] 7196190: Improve method of handling MethodHandles Bind callers to caller-sensitive methods. Reviewed-by: twisti, jjh, vlivanov, ahgross --- .../java/lang/invoke/MethodHandleImpl.java | 171 ++++++++++++++++- .../java/lang/invoke/MethodHandleNatives.java | 97 ++++++++++ .../java/lang/invoke/MethodHandleStatics.java | 4 +- .../java/lang/invoke/MethodHandles.java | 15 +- .../sun/invoke/anon/AnonymousClassLoader.java | 76 +------- .../sun/invoke/util/ValueConversions.java | 14 +- .../lang/invoke/7196190/ClassForNameTest.java | 98 ++++++++++ .../lang/invoke/7196190/GetUnsafeTest.java | 112 +++++++++++ .../java/lang/invoke/7196190/MHProxyTest.java | 181 ++++++++++++++++++ .../lang/invoke/7196190/jtreg.security.policy | 9 + 10 files changed, 699 insertions(+), 78 deletions(-) create mode 100644 jdk/test/java/lang/invoke/7196190/ClassForNameTest.java create mode 100644 jdk/test/java/lang/invoke/7196190/GetUnsafeTest.java create mode 100644 jdk/test/java/lang/invoke/7196190/MHProxyTest.java create mode 100644 jdk/test/java/lang/invoke/7196190/jtreg.security.policy diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java b/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java index d9822bd7189..6013a417cc5 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2012, 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,13 +25,14 @@ package java.lang.invoke; -import sun.invoke.util.VerifyType; - +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import sun.invoke.empty.Empty; import sun.invoke.util.ValueConversions; +import sun.invoke.util.VerifyType; import sun.invoke.util.Wrapper; import static java.lang.invoke.LambdaForm.*; import static java.lang.invoke.MethodHandleStatics.*; @@ -781,4 +782,168 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; return mh; } + /** + * Create an alias for the method handle which, when called, + * appears to be called from the same class loader and protection domain + * as hostClass. + * This is an expensive no-op unless the method which is called + * is sensitive to its caller. A small number of system methods + * are in this category, including Class.forName and Method.invoke. + */ + static + MethodHandle bindCaller(MethodHandle mh, Class hostClass) { + return BindCaller.bindCaller(mh, hostClass); + } + + // Put the whole mess into its own nested class. + // That way we can lazily load the code and set up the constants. + private static class BindCaller { + static + MethodHandle bindCaller(MethodHandle mh, Class hostClass) { + // Do not use this function to inject calls into system classes. + if (hostClass == null) { + hostClass = C_Trampoline; + } else if (hostClass.isArray() || + hostClass.isPrimitive() || + hostClass.getName().startsWith("java.") || + hostClass.getName().startsWith("sun.")) { + throw new InternalError(); // does not happen, and should not anyway + } + // For simplicity, convert mh to a varargs-like method. + MethodHandle vamh = prepareForInvoker(mh); + // Cache the result of makeInjectedInvoker once per argument class. + MethodHandle bccInvoker = CV_makeInjectedInvoker.get(hostClass); + return restoreToType(bccInvoker.bindTo(vamh), mh.type()); + } + + // This class ("Trampoline") is known to be inside a dead-end class loader. + // Inject all doubtful calls into this class. + private static Class C_Trampoline; + static { + Class tramp = null; + try { + final int FRAME_COUNT_ARG = 1; // [0] Reflection [1] Trampoline + java.lang.reflect.Method gcc = sun.reflect.Reflection.class.getMethod("getCallerClass", int.class); + tramp = (Class) sun.reflect.misc.MethodUtil.invoke(gcc, null, new Object[]{ FRAME_COUNT_ARG }); + if (tramp.getClassLoader() == BindCaller.class.getClassLoader()) + throw new RuntimeException(tramp.getName()+" class loader"); + } catch (Throwable ex) { + throw new InternalError(ex); + } + C_Trampoline = tramp; + } + + private static MethodHandle makeInjectedInvoker(Class hostClass) { + Class bcc = UNSAFE.defineAnonymousClass(hostClass, T_BYTES, null); + if (hostClass.getClassLoader() != bcc.getClassLoader()) + throw new InternalError(hostClass.getName()+" (CL)"); + try { + if (hostClass.getProtectionDomain() != bcc.getProtectionDomain()) + throw new InternalError(hostClass.getName()+" (PD)"); + } catch (SecurityException ex) { + // Self-check was blocked by security manager. This is OK. + // In fact the whole try body could be turned into an assertion. + } + try { + MethodHandle init = IMPL_LOOKUP.findStatic(bcc, "init", MethodType.methodType(void.class)); + init.invokeExact(); // force initialization of the class + } catch (Throwable ex) { + throw uncaughtException(ex); + } + MethodHandle bccInvoker; + try { + MethodType invokerMT = MethodType.methodType(Object.class, MethodHandle.class, Object[].class); + bccInvoker = IMPL_LOOKUP.findStatic(bcc, "invoke_V", invokerMT); + } catch (ReflectiveOperationException ex) { + throw uncaughtException(ex); + } + // Test the invoker, to ensure that it really injects into the right place. + try { + MethodHandle vamh = prepareForInvoker(MH_checkCallerClass); + Object ok = bccInvoker.invokeExact(vamh, new Object[]{hostClass, bcc}); + } catch (Throwable ex) { + throw new InternalError(ex); + } + return bccInvoker; + } + private static ClassValue CV_makeInjectedInvoker = new ClassValue() { + @Override protected MethodHandle computeValue(Class hostClass) { + return makeInjectedInvoker(hostClass); + } + }; + + // Adapt mh so that it can be called directly from an injected invoker: + private static MethodHandle prepareForInvoker(MethodHandle mh) { + mh = mh.asFixedArity(); + MethodType mt = mh.type(); + int arity = mt.parameterCount(); + MethodHandle vamh = mh.asType(mt.generic()); + vamh.internalForm().compileToBytecode(); // eliminate LFI stack frames + vamh = vamh.asSpreader(Object[].class, arity); + vamh.internalForm().compileToBytecode(); // eliminate LFI stack frames + return vamh; + } + + // Undo the adapter effect of prepareForInvoker: + private static MethodHandle restoreToType(MethodHandle vamh, MethodType type) { + return vamh.asCollector(Object[].class, type.parameterCount()).asType(type); + } + + private static final MethodHandle MH_checkCallerClass; + static { + final Class THIS_CLASS = BindCaller.class; + assert(checkCallerClass(THIS_CLASS, THIS_CLASS)); + try { + MH_checkCallerClass = IMPL_LOOKUP + .findStatic(THIS_CLASS, "checkCallerClass", + MethodType.methodType(boolean.class, Class.class, Class.class)); + assert((boolean) MH_checkCallerClass.invokeExact(THIS_CLASS, THIS_CLASS)); + } catch (Throwable ex) { + throw new InternalError(ex); + } + } + + private static boolean checkCallerClass(Class expected, Class expected2) { + final int FRAME_COUNT_ARG = 2; // [0] Reflection [1] BindCaller [2] Expected + Class actual = sun.reflect.Reflection.getCallerClass(FRAME_COUNT_ARG); + if (actual != expected && actual != expected2) + throw new InternalError("found "+actual.getName()+", expected "+expected.getName() + +(expected == expected2 ? "" : ", or else "+expected2.getName())); + return true; + } + + private static final byte[] T_BYTES; + static { + final Object[] values = {null}; + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + try { + Class tClass = T.class; + String tName = tClass.getName(); + String tResource = tName.substring(tName.lastIndexOf('.')+1)+".class"; + java.net.URLConnection uconn = tClass.getResource(tResource).openConnection(); + int len = uconn.getContentLength(); + byte[] bytes = new byte[len]; + try (java.io.InputStream str = uconn.getInputStream()) { + int nr = str.read(bytes); + if (nr != len) throw new java.io.IOException(tResource); + } + values[0] = bytes; + } catch (java.io.IOException ex) { + throw new InternalError(ex); + } + return null; + } + }); + T_BYTES = (byte[]) values[0]; + } + + // The following class is used as a template for Unsafe.defineAnonymousClass: + private static class T { + static void init() { } // side effect: initializes this class + static Object invoke_V(MethodHandle vamh, Object[] args) throws Throwable { + return vamh.invokeExact(args); + } + } + } } diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java b/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java index d27256fb337..06a9ba20e69 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java @@ -385,4 +385,101 @@ class MethodHandleNatives { throw err; } } + + /** + * Is this method a caller-sensitive method? + * I.e., does it call Reflection.getCallerClass or a similer method + * to ask about the identity of its caller? + */ + // FIXME: Replace this pattern match by an annotation @sun.reflect.CallerSensitive. + static boolean isCallerSensitive(MemberName mem) { + assert(mem.isInvocable()); + Class defc = mem.getDeclaringClass(); + switch (mem.getName()) { + case "doPrivileged": + return defc == java.security.AccessController.class; + case "getUnsafe": + return defc == sun.misc.Unsafe.class; + case "lookup": + return defc == java.lang.invoke.MethodHandles.class; + case "invoke": + return defc == java.lang.reflect.Method.class; + case "get": + case "getBoolean": + case "getByte": + case "getChar": + case "getShort": + case "getInt": + case "getLong": + case "getFloat": + case "getDouble": + case "set": + case "setBoolean": + case "setByte": + case "setChar": + case "setShort": + case "setInt": + case "setLong": + case "setFloat": + case "setDouble": + return defc == java.lang.reflect.Field.class; + case "newInstance": + if (defc == java.lang.reflect.Constructor.class) return true; + if (defc == java.lang.Class.class) return true; + break; + case "forName": + case "getClassLoader": + case "getClasses": + case "getFields": + case "getMethods": + case "getConstructors": + case "getDeclaredClasses": + case "getDeclaredFields": + case "getDeclaredMethods": + case "getDeclaredConstructors": + case "getField": + case "getMethod": + case "getConstructor": + case "getDeclaredField": + case "getDeclaredMethod": + case "getDeclaredConstructor": + return defc == java.lang.Class.class; + case "getConnection": + case "getDriver": + case "getDrivers": + case "deregisterDriver": + return defc == java.sql.DriverManager.class; + case "newUpdater": + if (defc == java.util.concurrent.atomic.AtomicIntegerFieldUpdater.class) return true; + if (defc == java.util.concurrent.atomic.AtomicLongFieldUpdater.class) return true; + if (defc == java.util.concurrent.atomic.AtomicReferenceFieldUpdater.class) return true; + break; + case "getContextClassLoader": + return defc == java.lang.Thread.class; + case "getPackage": + case "getPackages": + return defc == java.lang.Package.class; + case "getParent": + case "getSystemClassLoader": + return defc == java.lang.ClassLoader.class; + case "load": + case "loadLibrary": + if (defc == java.lang.Runtime.class) return true; + if (defc == java.lang.System.class) return true; + break; + case "getCallerClass": + if (defc == sun.reflect.Reflection.class) return true; + if (defc == java.lang.System.class) return true; + break; + case "getCallerClassLoader": + return defc == java.lang.ClassLoader.class; + case "getProxyClass": + case "newProxyInstance": + return defc == java.lang.reflect.Proxy.class; + case "getBundle": + case "clearCache": + return defc == java.util.ResourceBundle.class; + } + return false; + } } diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandleStatics.java b/jdk/src/share/classes/java/lang/invoke/MethodHandleStatics.java index 3db5712fdeb..50e273804ec 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandleStatics.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleStatics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2012, 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 @@ -108,7 +108,7 @@ import sun.misc.Unsafe; /*non-public*/ static RuntimeException newIllegalArgumentException(String message, Object obj, Object obj2) { return new IllegalArgumentException(message(message, obj, obj2)); } - /*non-public*/ static Error uncaughtException(Exception ex) { + /*non-public*/ static Error uncaughtException(Throwable ex) { throw new InternalError("uncaught exception", ex); } static Error NYI() { diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java index 5c55f202353..e7007dd2b89 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2012, 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 @@ -329,6 +329,7 @@ public class MethodHandles { * where {@code defcPkg} is the package of {@code defc}. * */ + // FIXME in MR1: clarify that the bytecode behavior of a caller-ID method (like Class.forName) is relative to the lookupClass used to create the method handle, not the dynamic caller of the method handle public static final class Lookup { /** The class on behalf of whom the lookup is being performed. */ @@ -1209,6 +1210,7 @@ return mh1; if (method.isMethodHandleInvoke()) return fakeMethodHandleInvoke(method); MethodHandle mh = DirectMethodHandle.make(refc, method); + mh = maybeBindCaller(method, mh); mh = mh.setVarargs(method); if (doRestrict) mh = restrictReceiver(method, mh, lookupClass()); @@ -1217,6 +1219,16 @@ return mh1; private MethodHandle fakeMethodHandleInvoke(MemberName method) { return throwException(method.getReturnType(), UnsupportedOperationException.class); } + private MethodHandle maybeBindCaller(MemberName method, MethodHandle mh) throws IllegalAccessException { + if (allowedModes == TRUSTED || !MethodHandleNatives.isCallerSensitive(method)) + return mh; + Class hostClass = lookupClass; + if ((allowedModes & PRIVATE) == 0) // caller must use full-power lookup + hostClass = null; + MethodHandle cbmh = MethodHandleImpl.bindCaller(mh, hostClass); + // Note: caller will apply varargs after this step happens. + return cbmh; + } private MethodHandle getDirectField(byte refKind, Class refc, MemberName field) throws IllegalAccessException { checkField(refKind, refc, field); MethodHandle mh = DirectMethodHandle.make(refc, field); @@ -1229,6 +1241,7 @@ return mh1; private MethodHandle getDirectConstructor(Class refc, MemberName ctor) throws IllegalAccessException { assert(ctor.isConstructor()); checkAccess(REF_newInvokeSpecial, refc, ctor); + assert(!MethodHandleNatives.isCallerSensitive(ctor)); // maybeBindCaller not relevant here return DirectMethodHandle.make(ctor).setVarargs(ctor); } diff --git a/jdk/src/share/classes/sun/invoke/anon/AnonymousClassLoader.java b/jdk/src/share/classes/sun/invoke/anon/AnonymousClassLoader.java index 3005a452f71..32624b40f97 100644 --- a/jdk/src/share/classes/sun/invoke/anon/AnonymousClassLoader.java +++ b/jdk/src/share/classes/sun/invoke/anon/AnonymousClassLoader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2012, 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 @@ -73,74 +73,14 @@ import sun.misc.IOUtils; public class AnonymousClassLoader { final Class hostClass; - // Note: Do not refactor the calls to checkHostClass unless you - // also adjust this constant: - private static int CHC_CALLERS = 3; - - public AnonymousClassLoader() { - this.hostClass = checkHostClass(null); - } - public AnonymousClassLoader(Class hostClass) { - this.hostClass = checkHostClass(hostClass); + // Privileged constructor. + private AnonymousClassLoader(Class hostClass) { + this.hostClass = hostClass; } - private static Class getTopLevelClass(Class clazz) { - for(Class outer = clazz.getDeclaringClass(); outer != null; - outer = outer.getDeclaringClass()) { - clazz = outer; - } - return clazz; - } - - private static Class checkHostClass(Class hostClass) { - // called only from the constructor - // does a context-sensitive check on caller class - // CC[0..3] = {Reflection, this.checkHostClass, this., caller} - Class caller = sun.reflect.Reflection.getCallerClass(CHC_CALLERS); - - if (caller == null) { - // called from the JVM directly - if (hostClass == null) - return AnonymousClassLoader.class; // anything central will do - return hostClass; - } - - if (hostClass == null) - hostClass = caller; // default value is caller itself - - // anonymous class will access hostClass on behalf of caller - Class callee = hostClass; - - if (caller == callee) - // caller can always nominate itself to grant caller's own access rights - return hostClass; - - // normalize caller and callee to their top-level classes: - caller = getTopLevelClass(caller); - callee = getTopLevelClass(callee); - if (caller == callee) - return caller; - - ClassLoader callerCL = caller.getClassLoader(); - if (callerCL == null) { - // caller is trusted code, so accept the proposed hostClass - return hostClass; - } - - // %%% should do something with doPrivileged, because trusted - // code should have a way to execute on behalf of - // partially-trusted clients - - // Does the caller have the right to access the private - // members of the callee? If not, raise an error. - final int ACC_PRIVATE = 2; - try { - sun.reflect.Reflection.ensureMemberAccess(caller, callee, null, ACC_PRIVATE); - } catch (IllegalAccessException ee) { - throw new IllegalArgumentException(ee); - } - - return hostClass; + public static AnonymousClassLoader make(sun.misc.Unsafe unsafe, Class hostClass) { + if (unsafe == null) throw new NullPointerException(); + return new AnonymousClassLoader(hostClass); } public Class loadClass(byte[] classFile) { @@ -249,7 +189,7 @@ public class AnonymousClassLoader { private static int fakeNameCounter = 99999; // ignore two warnings on this line: - static sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe(); + private static sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe(); // preceding line requires that this class be on the boot class path static private final Method defineAnonymousClass; diff --git a/jdk/src/share/classes/sun/invoke/util/ValueConversions.java b/jdk/src/share/classes/sun/invoke/util/ValueConversions.java index 1533f4b2ad2..b2044818f60 100644 --- a/jdk/src/share/classes/sun/invoke/util/ValueConversions.java +++ b/jdk/src/share/classes/sun/invoke/util/ValueConversions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2012, 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 @@ -522,13 +522,19 @@ public class ValueConversions { static { MethodHandle mh = null; try { - java.lang.reflect.Method m = MethodHandles.class + final java.lang.reflect.Method m = MethodHandles.class .getDeclaredMethod("collectArguments", MethodHandle.class, int.class, MethodHandle.class); - m.setAccessible(true); + AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Void run() { + m.setAccessible(true); + return null; + } + }); mh = IMPL_LOOKUP.unreflect(m); - } catch (ReflectiveOperationException | SecurityException ex) { + } catch (ReflectiveOperationException ex) { throw new InternalError(ex); } COLLECT_ARGUMENTS = mh; diff --git a/jdk/test/java/lang/invoke/7196190/ClassForNameTest.java b/jdk/test/java/lang/invoke/7196190/ClassForNameTest.java new file mode 100644 index 00000000000..48ccb2a6463 --- /dev/null +++ b/jdk/test/java/lang/invoke/7196190/ClassForNameTest.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2012, 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 7196190 + * @summary Improve method of handling MethodHandles + * + * @run main/othervm ClassForNameTest + */ + +import java.lang.invoke.*; +import java.lang.reflect.Method; +import java.util.Arrays; + +public class ClassForNameTest { + final static String NAME = ClassForNameTest.class.getName(); + + public static void main(String[] args) throws Throwable { + { + final MethodType mt = MethodType.methodType(Class.class, String.class); + final MethodHandle mh = MethodHandles.lookup() + .findStatic(Class.class, "forName", mt); + + Class.forName(NAME); + + mh.invoke(NAME); + mh.bindTo(NAME).invoke(); + mh.invokeWithArguments(Arrays.asList(NAME)); + mh.invokeWithArguments(NAME); + Class cls = (Class) mh.invokeExact(NAME); + } + + { + final Method fnMethod = Class.class.getMethod("forName", String.class); + final MethodType mt = MethodType.methodType(Object.class, Object.class, Object[].class); + final MethodHandle mh = MethodHandles.lookup() + .findVirtual(Method.class, "invoke", mt) + .bindTo(fnMethod); + + fnMethod.invoke(null, NAME); + + mh.bindTo(null).bindTo(new Object[]{NAME}).invoke(); + mh.invoke(null, new Object[]{NAME}); + mh.invokeWithArguments(null, new Object[]{NAME}); + mh.invokeWithArguments(Arrays.asList(null, new Object[]{NAME})); + Object obj = mh.invokeExact((Object) null, new Object[]{NAME}); + } + + { + final Method fnMethod = Class.class.getMethod("forName", String.class); + final MethodType mt = MethodType.methodType(Object.class, Object.class, Object[].class); + + final MethodHandle mh = MethodHandles.lookup() + .bind(fnMethod, "invoke", mt); + + mh.bindTo(null).bindTo(new Object[]{NAME}).invoke(); + mh.invoke(null, new Object[]{NAME}); + mh.invokeWithArguments(null, NAME); + mh.invokeWithArguments(Arrays.asList(null, NAME)); + Object obj = mh.invokeExact((Object) null, new Object[]{NAME}); + } + + { + final Method fnMethod = Class.class.getMethod("forName", String.class); + final MethodHandle mh = MethodHandles.lookup().unreflect(fnMethod); + + mh.bindTo(NAME).invoke(); + mh.invoke(NAME); + mh.invokeWithArguments(NAME); + mh.invokeWithArguments(Arrays.asList(NAME)); + Class cls = (Class) mh.invokeExact(NAME); + } + + System.out.println("TEST PASSED"); + } +} diff --git a/jdk/test/java/lang/invoke/7196190/GetUnsafeTest.java b/jdk/test/java/lang/invoke/7196190/GetUnsafeTest.java new file mode 100644 index 00000000000..0fd3cbd8d0f --- /dev/null +++ b/jdk/test/java/lang/invoke/7196190/GetUnsafeTest.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2012, 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 7196190 + * @summary Improve method of handling MethodHandles + * + * @run main/othervm/policy=jtreg.security.policy/secure=java.lang.SecurityManager GetUnsafeTest + */ + +import java.lang.invoke.*; +import java.lang.reflect.Method; +import java.util.Arrays; + +public class GetUnsafeTest { + final static String NAME = "sun.misc.Unsafe"; + + private static boolean isTestFailed = false; + + private static void fail() { + isTestFailed = true; + try { throw new Exception(); } catch (Throwable e) { + StackTraceElement frame = e.getStackTrace()[1]; + System.out.printf("Failed at %s:%d\n", frame.getFileName(), frame.getLineNumber()); + } + } + + public static void main(String[] args) throws Throwable { + { + final MethodType mt = MethodType.methodType(Class.class, String.class); + final MethodHandle mh = MethodHandles.lookup() + .findStatic(Class.class, "forName", mt); + + try { Class.forName(NAME); fail(); } catch (Throwable e) {} + + try { mh.invoke(NAME); fail(); } catch (Throwable e) {} + try { mh.bindTo(NAME).invoke(); fail(); } catch (Throwable e) {} + try { mh.invokeWithArguments(Arrays.asList(NAME)); fail(); } catch (Throwable e) {} + try { mh.invokeWithArguments(NAME); fail(); } catch (Throwable e) {} + try { Class cls = (Class) mh.invokeExact(NAME); fail(); } catch (Throwable e) {} + } + + { + final Method fnMethod = Class.class.getMethod("forName", String.class); + final MethodType mt = MethodType.methodType(Object.class, Object.class, Object[].class); + final MethodHandle mh = MethodHandles.lookup() + .findVirtual(Method.class, "invoke", mt) + .bindTo(fnMethod); + + try { fnMethod.invoke(null, NAME); fail(); } catch (Throwable e) {} + + try { mh.bindTo(null).bindTo(new Object[]{NAME}).invoke(); fail(); } catch (Throwable e) {} + try { mh.invoke(null, new Object[]{NAME}); fail(); } catch (Throwable e) {} + try { mh.invokeWithArguments(null, new Object[]{NAME}); fail(); } catch (Throwable e) {} + try { mh.invokeWithArguments(Arrays.asList(null, new Object[]{NAME})); fail(); } catch (Throwable e) {} + try { Object obj = mh.invokeExact((Object) null, new Object[]{NAME}); fail(); } catch (Throwable e) {} + } + + { + final Method fnMethod = Class.class.getMethod("forName", String.class); + final MethodType mt = MethodType.methodType(Object.class, Object.class, Object[].class); + + final MethodHandle mh = MethodHandles.lookup().bind(fnMethod, "invoke", mt); + + try { mh.bindTo(null).bindTo(new Object[]{NAME}).invoke(); fail(); } catch (Throwable e) {} + try { mh.invoke(null, new Object[]{NAME}); fail(); } catch (Throwable e) {} + try { mh.invokeWithArguments(null, NAME); fail(); } catch (Throwable e) {} + try { mh.invokeWithArguments(Arrays.asList(null, NAME)); fail(); } catch (Throwable e) {} + try { Object obj = mh.invokeExact((Object) null, new Object[]{NAME}); fail(); } catch (Throwable e) {} + } + + { + final Method fnMethod = Class.class.getMethod("forName", String.class); + final MethodHandle mh = MethodHandles.lookup().unreflect(fnMethod); + + try { mh.bindTo(NAME).invoke(); fail(); } catch (Throwable e) {} + try { mh.invoke(NAME); fail(); } catch (Throwable e) {} + try { mh.invokeWithArguments(NAME); fail(); } catch (Throwable e) {} + try { mh.invokeWithArguments(Arrays.asList(NAME)); fail(); } catch (Throwable e) {} + try { Class cls = (Class) mh.invokeExact(NAME); fail(); } catch (Throwable e) {} + } + + if (!isTestFailed) { + System.out.println("TEST PASSED"); + } else { + System.out.println("TEST FAILED"); + System.exit(1); + } + } +} diff --git a/jdk/test/java/lang/invoke/7196190/MHProxyTest.java b/jdk/test/java/lang/invoke/7196190/MHProxyTest.java new file mode 100644 index 00000000000..5e07f393cb1 --- /dev/null +++ b/jdk/test/java/lang/invoke/7196190/MHProxyTest.java @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2012, 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 7196190 + * @summary Improve method of handling MethodHandles + * + * @run main/othervm MHProxyTest + */ + +import java.lang.invoke.*; +import java.security.*; +import static java.lang.invoke.MethodHandles.*; +import static java.lang.invoke.MethodType.*; + +public class MHProxyTest { + private static final Class C_Unsafe; + private static final MethodHandle MH_getUnsafe; + static { + // Do these before there is a SM installed. + C_Unsafe = sun.misc.Unsafe.class; // EXPECT A WARNING ON THIS LINE + Lookup lookup = lookup(); + MethodHandle gumh = null; + try { + gumh = lookup.findStatic(C_Unsafe, "getUnsafe", methodType(C_Unsafe)); + } catch (ReflectiveOperationException ex) { + throw new InternalError(ex.toString()); + } + MH_getUnsafe = gumh; + // Try some different lookups: + try { + lookup.in(Object.class).findStatic(C_Unsafe, "getUnsafe", methodType(C_Unsafe)); + } catch (ReflectiveOperationException ex) { + throw new InternalError(ex.toString()); + } + lookup = lookup().in(C_Unsafe); + try { + lookup.in(C_Unsafe).findStatic(C_Unsafe, "getUnsafe", methodType(C_Unsafe)); + } catch (ReflectiveOperationException ex) { + throw new InternalError(ex.toString()); + } + } + + public static void main(String[] args) throws Throwable { + System.setSecurityManager(new SecurityManager()); + Lookup lookup = lookup(); + testBasic(lookup); + testDoPriv(lookup); + testSetVar(); + Lookup l2 = lookup.in(Object.class); + System.out.println("=== "+l2); + testBasic(l2); + testDoPriv(l2); + Lookup l3 = lookup.in(C_Unsafe); + System.out.println("=== "+l3); + testBasic(l3); + testDoPriv(l3); + if (failure != null) + throw failure; + } + + private static Throwable failure; + private static void fail(Throwable ex) { + if (failure == null) + failure = ex; + StackTraceElement frame = new Exception().getStackTrace()[1]; + System.out.printf("Failed at %s:%d: %s\n", frame.getFileName(), frame.getLineNumber(), ex); + } + private static void ok(Throwable ex) { + StackTraceElement frame = new Exception().getStackTrace()[1]; + System.out.printf("OK at %s:%d: %s\n", frame.getFileName(), frame.getLineNumber(), ex); + } + + private static void testBasic(Lookup lookup) throws Throwable { + // Verify that we can't get to this guy under the SM: + try { + MethodHandle badmh = lookup.findStatic(C_Unsafe, "getUnsafe", methodType(C_Unsafe)); + assert(badmh.type() == methodType(C_Unsafe)); + badmh = badmh.asType(badmh.type().generic()); + Object u = C_Unsafe.cast(badmh.invokeExact()); + assert(C_Unsafe.isInstance(u)); + fail(new AssertionError("got mh to getUnsafe!")); + } catch (SecurityException ex) { + ok(ex); + } + try { + Object u = MH_getUnsafe.invokeWithArguments(); + assert(C_Unsafe.isInstance(u)); + fail(new AssertionError("got the Unsafe object! (MH invoke)")); + } catch (SecurityException ex) { + ok(ex); + } + try { + MethodHandle mh = MH_getUnsafe; + mh = mh.asType(mh.type().generic()); + mh = foldArguments(identity(Object.class), mh); + mh = filterReturnValue(mh, identity(Object.class)); + Object u = mh.invokeExact(); + assert(C_Unsafe.isInstance(u)); + fail(new AssertionError("got the Unsafe object! (MH invokeWithArguments)")); + } catch (SecurityException ex) { + ok(ex); + } + } + + private static void testDoPriv(Lookup lookup) throws Throwable { + PrivilegedAction privAct = MethodHandleProxies.asInterfaceInstance(PrivilegedAction.class, MH_getUnsafe); + try { + Object u = AccessController.doPrivileged(privAct); + assert(C_Unsafe.isInstance(u)); + fail(new AssertionError("got the Unsafe object! (static doPriv)")); + } catch (SecurityException ex) { + ok(ex); + } + MethodHandle MH_doPriv = lookup.findStatic(AccessController.class, "doPrivileged", + methodType(Object.class, PrivilegedAction.class)); + MH_doPriv = MH_doPriv.bindTo(privAct); + try { + Object u = MH_doPriv.invoke(); + assert(C_Unsafe.isInstance(u)); + fail(new AssertionError("got the Unsafe object! (MH + doPriv)")); + } catch (SecurityException ex) { + ok(ex); + } + // try one more layer of indirection: + Runnable rbl = MethodHandleProxies.asInterfaceInstance(Runnable.class, MH_doPriv); + try { + rbl.run(); + fail(new AssertionError("got the Unsafe object! (Runnable + MH + doPriv)")); + } catch (SecurityException ex) { + ok(ex); + } + } + + private static void testSetVar() throws Throwable { + { + // Test the box pattern: + Object[] box = new Object[1]; + MethodHandle MH_getFoo = identity(Object.class).bindTo("foo"); + MethodHandle MH_storeToBox = insertArguments(arrayElementSetter(Object[].class), 0, box, 0); + MethodHandle mh = filterReturnValue(MH_getFoo, MH_storeToBox); + mh.invokeExact(); + assert(box[0] == "foo"); + } + { + Object[] box = new Object[1]; + MethodHandle MH_storeToBox = insertArguments(arrayElementSetter(Object[].class), 0, box, 0); + MethodHandle mh = filterReturnValue(MH_getUnsafe.asType(MH_getUnsafe.type().generic()), MH_storeToBox); + try { + mh.invokeExact(); + Object u = box[0]; + assert(C_Unsafe.isInstance(u)); + fail(new AssertionError("got the Unsafe object! (MH + setElement)")); + } catch (SecurityException ex) { + ok(ex); + } + } + } +} diff --git a/jdk/test/java/lang/invoke/7196190/jtreg.security.policy b/jdk/test/java/lang/invoke/7196190/jtreg.security.policy new file mode 100644 index 00000000000..d32c7af9b3f --- /dev/null +++ b/jdk/test/java/lang/invoke/7196190/jtreg.security.policy @@ -0,0 +1,9 @@ +/* + * security policy used by the test process + * must allow file reads so that jtreg itself can run + */ + +grant { + // standard test activation permissions + permission java.io.FilePermission "*", "read"; +}; From 898b21ebf3d77c37c54cb8e6f2a50d78d6446bd7 Mon Sep 17 00:00:00 2001 From: Frederic Parain Date: Mon, 24 Sep 2012 16:15:27 +0400 Subject: [PATCH 18/19] 7198296: Problem with classloader in JMX Wb classes have to be available for hotspot tests Co-authored-by: Daniel Fuchs Co-authored-by: Jean-Francois Denise Reviewed-by: ahgross, asaha --- .../remote/rmi/RMIConnectionImpl.java | 61 +++++++++++++++++-- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java b/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java index 9449210e897..3f880d0a8f9 100644 --- a/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java +++ b/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2012, 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 @@ -144,6 +144,17 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced { new RuntimePermission("createClassLoader")) ); + + this.defaultContextClassLoader = + AccessController.doPrivileged( + new PrivilegedAction() { + @Override + public ClassLoader run() { + return new CombinedClassLoader(Thread.currentThread().getContextClassLoader(), + dcl); + } + }); + serverCommunicatorAdmin = new RMIServerCommunicatorAdmin(EnvHelp.getServerConnectionTimeout(env)); @@ -510,7 +521,7 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced { "connectionId=" + connectionId +" unwrapping query with defaultClassLoader."); - queryValue = unwrap(query, defaultClassLoader, QueryExp.class); + queryValue = unwrap(query, defaultContextClassLoader, QueryExp.class); try { final Object params[] = new Object[] { name, queryValue }; @@ -545,7 +556,7 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced { "connectionId=" + connectionId +" unwrapping query with defaultClassLoader."); - queryValue = unwrap(query, defaultClassLoader, QueryExp.class); + queryValue = unwrap(query, defaultContextClassLoader, QueryExp.class); try { final Object params[] = new Object[] { name, queryValue }; @@ -1579,7 +1590,8 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced { ClassLoader orderCL = AccessController.doPrivileged( new PrivilegedExceptionAction() { public ClassLoader run() throws Exception { - return new OrderClassLoaders(cl1, cl2); + return new CombinedClassLoader(Thread.currentThread().getContextClassLoader(), + new OrderClassLoaders(cl1, cl2)); } } ); @@ -1671,6 +1683,8 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced { private final ClassLoader defaultClassLoader; + private final ClassLoader defaultContextClassLoader; + private final ClassLoaderWithRepository classLoaderWithRepository; private boolean terminated = false; @@ -1753,4 +1767,43 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced { private static final ClassLogger logger = new ClassLogger("javax.management.remote.rmi", "RMIConnectionImpl"); + + private static final class CombinedClassLoader extends ClassLoader { + + private final static class ClassLoaderWrapper extends ClassLoader { + ClassLoaderWrapper(ClassLoader cl) { + super(cl); + } + + @Override + protected Class loadClass(String name, boolean resolve) + throws ClassNotFoundException { + return super.loadClass(name, resolve); + } + }; + + final ClassLoaderWrapper defaultCL; + + private CombinedClassLoader(ClassLoader parent, ClassLoader defaultCL) { + super(parent); + this.defaultCL = new ClassLoaderWrapper(defaultCL); + } + + @Override + protected Class loadClass(String name, boolean resolve) + throws ClassNotFoundException { + try { + super.loadClass(name, resolve); + } catch(Exception e) { + for(Throwable t = e; t != null; t = t.getCause()) { + if(t instanceof SecurityException) { + throw t==e?(SecurityException)t:new SecurityException(t.getMessage(), e); + } + } + } + final Class cl = defaultCL.loadClass(name, resolve); + return cl; + } + + } } From 12bf2c7d5201ace92e558c217dafc89354796f29 Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Mon, 24 Sep 2012 17:00:40 +0400 Subject: [PATCH 19/19] 7192975: Issue with JMX reflection Make security check unconditional Reviewed-by: ahgross, asaha --- .../javax/management/modelmbean/DescriptorSupport.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/jdk/src/share/classes/javax/management/modelmbean/DescriptorSupport.java b/jdk/src/share/classes/javax/management/modelmbean/DescriptorSupport.java index 57b4b46365e..068047967ea 100644 --- a/jdk/src/share/classes/javax/management/modelmbean/DescriptorSupport.java +++ b/jdk/src/share/classes/javax/management/modelmbean/DescriptorSupport.java @@ -1245,13 +1245,12 @@ public class DescriptorSupport return s.substring(1, s.length() - 1); } final String className = s.substring(1, slash); + final Constructor constr; try { + ReflectUtil.checkPackageAccess(className); final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); - if (contextClassLoader == null) { - ReflectUtil.checkPackageAccess(className); - } final Class c = Class.forName(className, false, contextClassLoader); constr = c.getConstructor(new Class[] {String.class});