8064331: JavaSecurityAccess.doIntersectionPrivilege() drops the information about the domain combiner of the stack ACC
Reviewed-by: mullan
--- a/jdk/src/java.base/share/classes/java/security/AccessControlContext.java Fri Feb 06 10:44:57 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/security/AccessControlContext.java Fri Jan 16 18:19:23 2015 +0100
@@ -172,9 +172,24 @@
public AccessControlContext(AccessControlContext acc,
DomainCombiner combiner) {
- SecurityManager sm = System.getSecurityManager();
- if (sm != null) {
- sm.checkPermission(SecurityConstants.CREATE_ACC_PERMISSION);
+ this(acc, combiner, false);
+ }
+
+ /**
+ * package private to allow calls from ProtectionDomain without performing
+ * the security check for {@linkplain SecurityConstants.CREATE_ACC_PERMISSION}
+ * permission
+ */
+ AccessControlContext(AccessControlContext acc,
+ DomainCombiner combiner,
+ boolean preauthorized) {
+ if (!preauthorized) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(SecurityConstants.CREATE_ACC_PERMISSION);
+ this.isAuthorized = true;
+ }
+ } else {
this.isAuthorized = true;
}
--- a/jdk/src/java.base/share/classes/java/security/ProtectionDomain.java Fri Feb 06 10:44:57 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/security/ProtectionDomain.java Fri Jan 16 18:19:23 2015 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, 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
@@ -27,7 +27,6 @@
import java.lang.ref.WeakReference;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
@@ -60,35 +59,44 @@
*/
public class ProtectionDomain {
+ private static class JavaSecurityAccessImpl implements JavaSecurityAccess {
+
+ private JavaSecurityAccessImpl() {
+ }
+
+ @Override
+ public <T> T doIntersectionPrivilege(
+ PrivilegedAction<T> action,
+ final AccessControlContext stack,
+ final AccessControlContext context) {
+ if (action == null) {
+ throw new NullPointerException();
+ }
+
+ return AccessController.doPrivileged(
+ action,
+ getCombinedACC(context, stack)
+ );
+ }
+
+ @Override
+ public <T> T doIntersectionPrivilege(
+ PrivilegedAction<T> action,
+ AccessControlContext context) {
+ return doIntersectionPrivilege(action,
+ AccessController.getContext(), context);
+ }
+
+ private static AccessControlContext getCombinedACC(AccessControlContext context, AccessControlContext stack) {
+ AccessControlContext acc = new AccessControlContext(context, stack.getDomainCombiner(), true);
+
+ return new AccessControlContext(stack.getContext(), acc).optimize();
+ }
+ }
static {
// Set up JavaSecurityAccess in SharedSecrets
- SharedSecrets.setJavaSecurityAccess(
- new JavaSecurityAccess() {
- public <T> T doIntersectionPrivilege(
- PrivilegedAction<T> action,
- final AccessControlContext stack,
- final AccessControlContext context)
- {
- if (action == null) {
- throw new NullPointerException();
- }
- return AccessController.doPrivileged(
- action,
- new AccessControlContext(
- stack.getContext(), context).optimize()
- );
- }
-
- public <T> T doIntersectionPrivilege(
- PrivilegedAction<T> action,
- AccessControlContext context)
- {
- return doIntersectionPrivilege(action,
- AccessController.getContext(), context);
- }
- }
- );
+ SharedSecrets.setJavaSecurityAccess(new JavaSecurityAccessImpl());
}
/* CodeSource */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/ProtectionDomain/PreserveCombinerTest.java Fri Jan 16 18:19:23 2015 +0100
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.DomainCombiner;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+import sun.misc.SharedSecrets;
+
+/*
+ * @test
+ * @bug 8064331
+ * @summary Make sure that JavaSecurityAccess.doIntersectionPrivilege()
+ * is not dropping the information about the domain combiner of
+ * the stack ACC
+ */
+
+public class PreserveCombinerTest {
+ public static void main(String[]args) throws Exception {
+ final DomainCombiner dc = new DomainCombiner() {
+ @Override
+ public ProtectionDomain[] combine(ProtectionDomain[] currentDomains, ProtectionDomain[] assignedDomains) {
+ return currentDomains; // basically a no-op
+ }
+ };
+
+ // Get an instance of the saved ACC
+ AccessControlContext saved = AccessController.getContext();
+ // Simulate the stack ACC with a DomainCombiner attached
+ AccessControlContext stack = new AccessControlContext(AccessController.getContext(), dc);
+
+ // Now try to run JavaSecurityAccess.doIntersectionPrivilege() and assert
+ // whether the DomainCombiner from the stack ACC is preserved
+ boolean ret = SharedSecrets.getJavaSecurityAccess().doIntersectionPrivilege(new PrivilegedAction<Boolean>() {
+ @Override
+ public Boolean run() {
+ return dc == AccessController.getContext().getDomainCombiner();
+ }
+ }, stack, saved);
+
+ if (!ret) {
+ System.exit(1);
+ }
+ }
+}
+