--- old/src/java.base/share/classes/java/lang/Class.java 2018-03-12 02:31:54.506796800 -0400
+++ new/src/java.base/share/classes/java/lang/Class.java 2018-03-12 02:31:52.982709647 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2018, 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
@@ -3855,26 +3855,39 @@
*
* @return the nest host of this class, or {@code this} if we cannot
* obtain a valid nest host
- *
+ * @throws SecurityException
+ * If a security manager, s, is present and the caller's
+ * class loader is not the same as or an ancestor of the class
+ * loader for the current class and invocation of {@link
+ * SecurityManager#checkPackageAccess s.checkPackageAccess()}
+ * denies access to the package of the current class
* @since 11
*/
+ @CallerSensitive
public Class> getNestHost() {
if (isPrimitive() || isArray()) {
return this;
}
+ Class> host;
try {
- Class> host = getNestHost0();
- // if null then nest membership validation failed, so we
- // act as-if we have no nest-host
- if (host == null) {
- host = this;
- }
- return host;
+ host = getNestHost0();
} catch (LinkageError e) {
// if we couldn't load our nest-host then we
- // again act as-if we have no nest-host
+ // act as-if we have no nest-host
+ return this;
+ }
+ // if null then nest membership validation failed, so we
+ // act as-if we have no nest-host
+ if (host == null || host == this) {
return this;
}
+ // returning a different class requires a security check
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkPackageAccess(sm,
+ ClassLoader.getClassLoader(Reflection.getCallerClass()), true);
+ }
+ return host;
}
/**
@@ -3889,10 +3902,18 @@
* @since 11
*/
public boolean isNestmateOf(Class> c) {
- // We could use Reflection.areNestmates(this, c) and ignore
- // any IllegalAccessError, but prefer to minimize exception
- // creation by using getNestHost() directly.
- return getNestHost() == c.getNestHost();
+ if (this == c) {
+ return true;
+ }
+ if (isPrimitive() || isArray() ||
+ c.isPrimitive() || c.isArray()) {
+ return false;
+ }
+ try {
+ return getNestHost0() == c.getNestHost0();
+ } catch (LinkageError e) {
+ return false;
+ }
}
private native Class>[] getNestMembers0();
@@ -3917,15 +3938,33 @@
* @return an array of all classes and interfaces in the same nest as
* this class
*
- * @throws LinkageError if there is any problem loading or validating
- * a nest member or its nest host
+ * @throws LinkageError
+ * If there is any problem loading or validating a nest member or
+ * its nest host
+ * @throws SecurityException
+ * If a security manager, s, is present and the caller's
+ * class loader is not the same as or an ancestor of the class
+ * loader for the current class and invocation of {@link
+ * SecurityManager#checkPackageAccess s.checkPackageAccess()}
+ * denies access to the package of the current class
*
* @since 11
*/
+ @CallerSensitive
public Class>[] getNestMembers() {
if (isPrimitive() || isArray()) {
return new Class>[] { this };
}
- return getNestMembers0();
+ Class>[] members = getNestMembers0();
+ if (members.length > 1) {
+ // If we return anything other than the current class we need
+ // a security check
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkPackageAccess(sm,
+ ClassLoader.getClassLoader(Reflection.getCallerClass()), true);
+ }
+ }
+ return members;
}
}
--- old/test/hotspot/jtreg/runtime/Nestmates/reflectionAPI/TestReflectionAPI.java 2018-03-12 02:31:59.015054598 -0400
+++ new/test/hotspot/jtreg/runtime/Nestmates/reflectionAPI/TestReflectionAPI.java 2018-03-12 02:31:57.486967217 -0400
@@ -50,6 +50,7 @@
* HostWithDuplicateMembers.jcod
*
* @run main/othervm TestReflectionAPI
+ * @run main/othervm/java.security.policy=empty.policy TestReflectionAPI
*/
// We need a nest member class that is invalid for each of the possible reasons,
--- /dev/null 2018-03-08 04:59:07.267967999 -0500
+++ new/test/hotspot/jtreg/runtime/Nestmates/reflectionAPI/TestSecurityManagerChecks.java 2018-03-12 02:32:01.823215179 -0400
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2018, 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 8046171
+ * @summary Test that security checks occur for getNestHost/getNestMembers
+ *
+ * @library /test/lib
+ * @build TestSecurityManagerChecks testPkg.Host testPkg.Singleton
+ * @run driver ClassFileInstaller testPkg.Host testPkg.Host$Member testPkg.Singleton
+ * @run main/othervm -Xbootclasspath/a:. TestSecurityManagerChecks
+ */
+
+// ClassFileInstaller copies the testPkg files into the "current" directory
+// so we can add it to the bootclasspath. Then when we run the test the
+// loader for the testPkg files is the bootloader but the loader for the
+// test class is the system loader, hence a package access check will fail
+// because the system loader is not the same as, nor a parent of, the bootloader.
+import java.security.Security;
+
+public class TestSecurityManagerChecks {
+
+ public static void main(String[] args) throws Throwable {
+
+ // First get hold of the target classes before we enable security
+ Class> host = testPkg.Host.class;
+ Class> member = testPkg.Host.Member.class;
+ Class> memberArray = testPkg.Host.Member[].class;
+ Class> singleton = testPkg.Singleton.class;
+
+ // Next add testPkg to the set of packages for which package-access
+ // permission is required
+ Security.setProperty("package.access",
+ Security.getProperty("package.access") + ",testPkg.");
+
+ // Finally install a default security manager
+ SecurityManager sm = new SecurityManager();
+ System.setSecurityManager(sm);
+
+ // These cases all succeed
+ getNestHost(int.class); // primitive
+ getNestHost(int[].class); // primitive[]
+ getNestHost(host); // host class
+ getNestHost(memberArray); // NestedT[]
+ getNestHost(singleton); // Singleton nest
+
+ getNestMembers(int.class); // primitive
+ getNestMembers(int[].class); // primitive[]
+ getNestMembers(memberArray); // NestedT[]
+ getNestMembers(singleton); // Singleton nest
+
+ // these cases all fail
+ getNestHostThrows(member); // NestedT
+
+ getNestMembersThrows(member); // NestedT
+ getNestMembersThrows(host); // host class
+ }
+
+ static void getNestHost(Class> c) {
+ Class> host = c.getNestHost();
+ System.out.println("OK - getNestHost succeeded for " + c.getName());
+ }
+
+ static void getNestHostThrows(Class> c) throws SecurityException {
+ try {
+ Class> host = c.getNestHost();
+ throw new Error("getNestHost succeeded for " + c.getName());
+ } catch (SecurityException e) {
+ System.out.println("OK - getNestHost for " + c.getName() +
+ " got expected exception: " + e);
+ }
+ }
+
+ static void getNestMembers(Class> c) {
+ Class>[] members = c.getNestMembers();
+ System.out.println("OK - getNestMembers succeeded for " + c.getName());
+ }
+
+ static void getNestMembersThrows(Class> c) throws SecurityException {
+ try {
+ Class>[] members = c.getNestMembers();
+ throw new Error("getNestMembers succeeded for " + c.getName());
+ } catch (SecurityException e) {
+ System.out.println("OK - getNestMembers for " + c.getName() +
+ " got expected exception: " + e);
+ }
+ }
+
+}
--- /dev/null 2018-03-08 04:59:07.267967999 -0500
+++ new/test/hotspot/jtreg/runtime/Nestmates/reflectionAPI/empty.policy 2018-03-12 02:32:06.159463140 -0400
@@ -0,0 +1,5 @@
+// A deliberately empty policy file for use with jtreg.
+// Setting othervm/java.security.policy=empty.policy
+// causes jtreg to run under the default system policy
+// and default security manager, with the addition of
+// the permissions jtreg itself needs to run.
--- /dev/null 2018-03-08 04:59:07.267967999 -0500
+++ new/test/hotspot/jtreg/runtime/Nestmates/reflectionAPI/testPkg/Host.java 2018-03-12 02:32:10.479710187 -0400
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+package testPkg;
+
+// Host class with single member
+public class Host {
+ public static class Member {
+ }
+}
--- /dev/null 2018-03-08 04:59:07.267967999 -0500
+++ new/test/hotspot/jtreg/runtime/Nestmates/reflectionAPI/testPkg/Singleton.java 2018-03-12 02:32:14.791956775 -0400
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+package testPkg;
+
+// Self-hosting singleton nest
+public class Singleton {
+}