From 05ea99914bdac7d881926c6240fd51cf0e8852e6 Mon Sep 17 00:00:00 2001 From: mullan Date: Tue, 8 Dec 2009 15:58:49 -0500 Subject: [PATCH] 6633872: Policy/PolicyFile leak dynamic ProtectionDomains. Reviewed-by: hawtin --- src/share/classes/java/security/Policy.java | 42 ++++++++++--------- .../java/security/ProtectionDomain.java | 42 +++++++++++++++++-- .../JavaSecurityProtectionDomainAccess.java | 39 +++++++++++++++++ src/share/classes/sun/misc/SharedSecrets.java | 12 +++++- .../sun/security/provider/PolicyFile.java | 35 +++++++++------- 5 files changed, 132 insertions(+), 38 deletions(-) create mode 100644 src/share/classes/sun/misc/JavaSecurityProtectionDomainAccess.java diff --git a/src/share/classes/java/security/Policy.java b/src/share/classes/java/security/Policy.java index fdc8657c9..bb3efdf1c 100644 --- a/src/share/classes/java/security/Policy.java +++ b/src/share/classes/java/security/Policy.java @@ -1,5 +1,5 @@ /* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. 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 @@ -28,19 +28,17 @@ package java.security; import java.io.*; import java.lang.RuntimePermission; +import java.lang.reflect.*; import java.net.MalformedURLException; import java.net.URL; import java.util.Enumeration; import java.util.Hashtable; -import java.util.Vector; -import java.util.StringTokenizer; import java.util.PropertyPermission; - -import java.lang.reflect.*; - +import java.util.StringTokenizer; +import java.util.Vector; import java.util.WeakHashMap; -import sun.security.util.Debug; import sun.security.jca.GetInstance; +import sun.security.util.Debug; import sun.security.util.SecurityConstants; @@ -113,8 +111,8 @@ public abstract class Policy { private static final Debug debug = Debug.getInstance("policy"); - // Cache mapping ProtectionDomain to PermissionCollection - private WeakHashMap pdMapping; + // Cache mapping ProtectionDomain.Key to PermissionCollection + private WeakHashMap pdMapping; /** package private for AccessControlContext */ static boolean isSet() @@ -307,7 +305,7 @@ public abstract class Policy { synchronized (p) { if (p.pdMapping == null) { p.pdMapping = - new WeakHashMap(); + new WeakHashMap(); } } @@ -323,7 +321,7 @@ public abstract class Policy { synchronized (p.pdMapping) { // cache of pd to permissions - p.pdMapping.put(policyDomain, policyPerms); + p.pdMapping.put(policyDomain.key, policyPerms); } } return; @@ -638,7 +636,7 @@ public abstract class Policy { } synchronized (pdMapping) { - pc = pdMapping.get(domain); + pc = pdMapping.get(domain.key); } if (pc != null) { @@ -697,7 +695,7 @@ public abstract class Policy { } synchronized (pdMapping) { - pc = pdMapping.get(domain); + pc = pdMapping.get(domain.key); } if (pc != null) { @@ -711,7 +709,7 @@ public abstract class Policy { synchronized (pdMapping) { // cache it - pdMapping.put(domain, pc); + pdMapping.put(domain.key, pc); } return pc.implies(permission); @@ -747,21 +745,25 @@ public abstract class Policy { this.params = params; } - public String getType() { return type; } + @Override public String getType() { return type; } - public Policy.Parameters getParameters() { return params; } + @Override public Policy.Parameters getParameters() { return params; } - public Provider getProvider() { return p; } + @Override public Provider getProvider() { return p; } + @Override public PermissionCollection getPermissions(CodeSource codesource) { return spi.engineGetPermissions(codesource); } + @Override public PermissionCollection getPermissions(ProtectionDomain domain) { return spi.engineGetPermissions(domain); } + @Override public boolean implies(ProtectionDomain domain, Permission perm) { return spi.engineImplies(domain, perm); } + @Override public void refresh() { spi.engineRefresh(); } @@ -803,7 +805,7 @@ public abstract class Policy { * @exception SecurityException - if this PermissionCollection object * has been marked readonly */ - public void add(Permission permission) { + @Override public void add(Permission permission) { perms.add(permission); } @@ -816,7 +818,7 @@ public abstract class Policy { * @return true if "permission" is implied by the permissions in * the collection, false if not. */ - public boolean implies(Permission permission) { + @Override public boolean implies(Permission permission) { return perms.implies(permission); } @@ -826,7 +828,7 @@ public abstract class Policy { * * @return an enumeration of all the Permissions. */ - public Enumeration elements() { + @Override public Enumeration elements() { return perms.elements(); } } diff --git a/src/share/classes/java/security/ProtectionDomain.java b/src/share/classes/java/security/ProtectionDomain.java index 313fa5a55..946dafe24 100644 --- a/src/share/classes/java/security/ProtectionDomain.java +++ b/src/share/classes/java/security/ProtectionDomain.java @@ -1,5 +1,5 @@ /* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. 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,9 +25,15 @@ package java.security; +import java.util.ArrayList; +import java.util.Collections; import java.util.Enumeration; import java.util.List; -import java.util.ArrayList; +import java.util.Map; +import java.util.WeakHashMap; +import sun.misc.JavaSecurityProtectionDomainAccess; +import static sun.misc.JavaSecurityProtectionDomainAccess.ProtectionDomainCache; +import sun.misc.SharedSecrets; import sun.security.util.Debug; import sun.security.util.SecurityConstants; @@ -72,6 +78,11 @@ public class ProtectionDomain { or dynamic (via a policy refresh) */ private boolean staticPermissions; + /* + * An object used as a key when the ProtectionDomain is stored in a Map. + */ + final Key key = new Key(); + private static final Debug debug = Debug.getInstance("domain"); /** @@ -238,7 +249,7 @@ public class ProtectionDomain { /** * Convert a ProtectionDomain to a String. */ - public String toString() { + @Override public String toString() { String pals = ""; if (principals != null && principals.length > 0) { StringBuilder palBuf = new StringBuilder("(principals "); @@ -396,4 +407,29 @@ public class ProtectionDomain { return mergedPerms; } + + /** + * Used for storing ProtectionDomains as keys in a Map. + */ + final class Key {} + + static { + SharedSecrets.setJavaSecurityProtectionDomainAccess( + new JavaSecurityProtectionDomainAccess() { + public ProtectionDomainCache getProtectionDomainCache() { + return new ProtectionDomainCache() { + private final Map map = + Collections.synchronizedMap + (new WeakHashMap()); + public void put(ProtectionDomain pd, + PermissionCollection pc) { + map.put((pd == null ? null : pd.key), pc); + } + public PermissionCollection get(ProtectionDomain pd) { + return pd == null ? map.get(null) : map.get(pd.key); + } + }; + } + }); + } } diff --git a/src/share/classes/sun/misc/JavaSecurityProtectionDomainAccess.java b/src/share/classes/sun/misc/JavaSecurityProtectionDomainAccess.java new file mode 100644 index 000000000..2f03b975a --- /dev/null +++ b/src/share/classes/sun/misc/JavaSecurityProtectionDomainAccess.java @@ -0,0 +1,39 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package sun.misc; + +import java.security.PermissionCollection; +import java.security.ProtectionDomain; + +public interface JavaSecurityProtectionDomainAccess { + interface ProtectionDomainCache { + void put(ProtectionDomain pd, PermissionCollection pc); + PermissionCollection get(ProtectionDomain pd); + } + /** + * Returns the ProtectionDomainCache. + */ + ProtectionDomainCache getProtectionDomainCache(); +} diff --git a/src/share/classes/sun/misc/SharedSecrets.java b/src/share/classes/sun/misc/SharedSecrets.java index 16b5727c6..7ebbe46e7 100644 --- a/src/share/classes/sun/misc/SharedSecrets.java +++ b/src/share/classes/sun/misc/SharedSecrets.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2002-2009 Sun Microsystems, Inc. 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 @@ -47,6 +47,7 @@ public class SharedSecrets { private static JavaNetAccess javaNetAccess; private static JavaNioAccess javaNioAccess; private static JavaIOFileDescriptorAccess javaIOFileDescriptorAccess; + private static JavaSecurityProtectionDomainAccess javaSecurityProtectionDomainAccess; public static JavaUtilJarAccess javaUtilJarAccess() { if (javaUtilJarAccess == null) { @@ -113,4 +114,13 @@ public class SharedSecrets { return javaIOFileDescriptorAccess; } + public static void setJavaSecurityProtectionDomainAccess + (JavaSecurityProtectionDomainAccess jspda) { + javaSecurityProtectionDomainAccess = jspda; + } + + public static JavaSecurityProtectionDomainAccess + getJavaSecurityProtectionDomainAccess() { + return javaSecurityProtectionDomainAccess; + } } diff --git a/src/share/classes/sun/security/provider/PolicyFile.java b/src/share/classes/sun/security/provider/PolicyFile.java index ed4757d3c..2a18ac6ab 100644 --- a/src/share/classes/sun/security/provider/PolicyFile.java +++ b/src/share/classes/sun/security/provider/PolicyFile.java @@ -1,5 +1,5 @@ /* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. 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 @@ -65,6 +65,9 @@ import java.lang.reflect.ReflectPermission; import javax.sound.sampled.AudioPermission; import javax.net.ssl.SSLPermission; */ +import sun.misc.JavaSecurityProtectionDomainAccess; +import static sun.misc.JavaSecurityProtectionDomainAccess.ProtectionDomainCache; +import sun.misc.SharedSecrets; import sun.security.util.Password; import sun.security.util.PolicyUtil; import sun.security.util.PropertyExpander; @@ -1105,7 +1108,7 @@ public class PolicyFile extends java.security.Policy { /** * Refreshes the policy object by re-reading all the policy files. */ - public void refresh() { + @Override public void refresh() { init(url); } @@ -1122,9 +1125,10 @@ public class PolicyFile extends java.security.Policy { * * @see java.security.ProtectionDomain */ + @Override public boolean implies(ProtectionDomain pd, Permission p) { PolicyInfo pi = policyInfo.get(); - Map pdMap = pi.getPdMapping(); + ProtectionDomainCache pdMap = pi.getPdMapping(); PermissionCollection pc = pdMap.get(pd); @@ -1170,6 +1174,7 @@ public class PolicyFile extends java.security.Policy { * @return the Permissions granted to the provided * ProtectionDomain. */ + @Override public PermissionCollection getPermissions(ProtectionDomain domain) { Permissions perms = new Permissions(); @@ -1205,6 +1210,7 @@ public class PolicyFile extends java.security.Policy { * * @return the set of permissions according to the policy. */ + @Override public PermissionCollection getPermissions(CodeSource codesource) { return getPermissions(new Permissions(), codesource); } @@ -2198,7 +2204,7 @@ public class PolicyFile extends java.security.Policy { return codesource; } - public String toString(){ + @Override public String toString(){ StringBuilder sb = new StringBuilder(); sb.append(ResourcesMgr.getString("(")); sb.append(getCodeSource()); @@ -2334,7 +2340,7 @@ public class PolicyFile extends java.security.Policy { * * @return false. */ - public boolean implies(Permission p) { + @Override public boolean implies(Permission p) { return false; } @@ -2351,7 +2357,7 @@ public class PolicyFile extends java.security.Policy { * type (class) name, permission name, actions, and * certificates as this object. */ - public boolean equals(Object obj) { + @Override public boolean equals(Object obj) { if (obj == this) return true; @@ -2399,7 +2405,7 @@ public class PolicyFile extends java.security.Policy { * * @return a hash code value for this object. */ - public int hashCode() { + @Override public int hashCode() { int hash = type.hashCode(); if (name != null) hash ^= name.hashCode(); @@ -2418,7 +2424,7 @@ public class PolicyFile extends java.security.Policy { * * @return the empty string "". */ - public String getActions() { + @Override public String getActions() { return ""; } @@ -2445,7 +2451,7 @@ public class PolicyFile extends java.security.Policy { * * @return information about this SelfPermission. */ - public String toString() { + @Override public String toString() { return "(SelfPermission " + type + " " + name + " " + actions + ")"; } } @@ -2467,7 +2473,7 @@ public class PolicyFile extends java.security.Policy { final Map aliasMapping; // Maps ProtectionDomain to PermissionCollection - private final Map[] pdMapping; + private final ProtectionDomainCache[] pdMapping; private java.util.Random random; PolicyInfo(int numCaches) { @@ -2476,16 +2482,17 @@ public class PolicyFile extends java.security.Policy { Collections.synchronizedList(new ArrayList(2)); aliasMapping = Collections.synchronizedMap(new HashMap(11)); - pdMapping = new Map[numCaches]; + pdMapping = new ProtectionDomainCache[numCaches]; + JavaSecurityProtectionDomainAccess jspda + = SharedSecrets.getJavaSecurityProtectionDomainAccess(); for (int i = 0; i < numCaches; i++) { - pdMapping[i] = Collections.synchronizedMap - (new WeakHashMap()); + pdMapping[i] = jspda.getProtectionDomainCache(); } if (numCaches > 1) { random = new java.util.Random(); } } - Map getPdMapping() { + ProtectionDomainCache getPdMapping() { if (pdMapping.length == 1) { return pdMapping[0]; } else { -- GitLab