diff -u new/src/java.base/share/classes/java/io/FilePermission.java new/src/java.base/share/classes/java/io/FilePermission.java --- new/src/java.base/share/classes/java/io/FilePermission.java 2016-08-25 11:28:24.583447700 +0800 +++ new/src/java.base/share/classes/java/io/FilePermission.java 2016-09-01 22:20:56.770074200 +0800 @@ -33,8 +33,9 @@ import java.util.StringJoiner; import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Function; +import jdk.internal.misc.JavaIOFilePermissionAccess; +import jdk.internal.misc.SharedSecrets; import sun.nio.fs.DefaultFileSystemProvider; import sun.security.action.GetPropertyAction; import sun.security.util.FilePermCompat; @@ -262,35 +263,32 @@ } static { - FilePermCompat.newPermPlusAltPathFunction = new Function<>() { - @Override - public FilePermission apply(FilePermission input) { - if (input.npath2 == null && !input.allFiles) { - Path npath2 = altPath(input.npath); - if (npath2 != null) { - FilePermission np = new FilePermission(input); - np.npath2 = npath2; - return np; + SharedSecrets.setJavaIOFilePermissionAccess( + new JavaIOFilePermissionAccess() { + public FilePermission newPermPlusAltPath(FilePermission input) { + if (input.npath2 == null && !input.allFiles) { + Path npath2 = altPath(input.npath); + if (npath2 != null) { + FilePermission np = new FilePermission(input); + np.npath2 = npath2; + return np; + } } + return input; } - return input; - } - }; - - FilePermCompat.newPermUsingAltPathFunction = new Function<>() { - @Override - public FilePermission apply(FilePermission input) { - if (!input.allFiles) { - Path npath2 = altPath(input.npath); - if (npath2 != null) { - FilePermission np = new FilePermission(input); - np.npath = npath2; - return np; + public FilePermission newPermUsingAltPath(FilePermission input) { + if (!input.allFiles) { + Path npath2 = altPath(input.npath); + if (npath2 != null) { + FilePermission np = new FilePermission(input); + np.npath = npath2; + return np; + } } + return null; } - return null; } - }; + ); } /** diff -u new/src/java.base/share/classes/java/security/AccessControlContext.java new/src/java.base/share/classes/java/security/AccessControlContext.java --- new/src/java.base/share/classes/java/security/AccessControlContext.java 2016-08-25 11:28:32.274093700 +0800 +++ new/src/java.base/share/classes/java/security/AccessControlContext.java 2016-09-01 22:21:03.570121100 +0800 @@ -446,7 +446,7 @@ } for (int i=0; i< context.length; i++) { - if (context[i] != null && !context[i].impliesWithAltFP(perm)) { + if (context[i] != null && !context[i].impliesWithAltFilePerm(perm)) { if (dumpDebug) { debug.println("access denied " + perm); } diff -u new/src/java.base/share/classes/java/security/ProtectionDomain.java new/src/java.base/share/classes/java/security/ProtectionDomain.java --- new/src/java.base/share/classes/java/security/ProtectionDomain.java 2016-08-25 11:28:40.058188400 +0800 +++ new/src/java.base/share/classes/java/security/ProtectionDomain.java 2016-09-01 22:21:10.803595400 +0800 @@ -304,13 +304,11 @@ } if (!staticPermissions && - Policy.getPolicyNoCheck().implies(this, perm)) { + Policy.getPolicyNoCheck().implies(this, perm)) { return true; } if (permissions != null) { - if (permissions.implies(perm)) { - return true; - } + return permissions.implies(perm); } return false; @@ -326,7 +324,7 @@ * This method is called by {@link AccessControlContext#checkPermission} * and not intended to be called by an application. */ - boolean impliesWithAltFP(Permission perm) { + boolean impliesWithAltFilePerm(Permission perm) { // If this is a subclass of ProtectionDomain. Call the old method. if (!FilePermCompat.compat || getClass() != ProtectionDomain.class) { reverted: --- new/src/java.base/share/classes/sun/security/util/IOUtils.java 2016-08-25 11:29:03.263792600 +0800 +++ old/src/java.base/share/classes/sun/security/util/IOUtils.java 2016-08-25 11:29:04.218108300 +0800 @@ -29,15 +29,10 @@ package sun.security.util; -import jdk.internal.misc.Unsafe; - import java.io.EOFException; -import java.io.FilePermission; import java.io.IOException; import java.io.InputStream; -import java.security.Permission; import java.util.Arrays; -import java.util.function.Function; public class IOUtils { diff -u new/src/java.base/share/classes/sun/security/util/FilePermCompat.java new/src/java.base/share/classes/sun/security/util/FilePermCompat.java --- new/src/java.base/share/classes/sun/security/util/FilePermCompat.java 2016-08-25 11:29:45.937089100 +0800 +++ new/src/java.base/share/classes/sun/security/util/FilePermCompat.java 2016-09-01 22:22:15.945112900 +0800 @@ -25,26 +25,25 @@ package sun.security.util; -import jdk.internal.misc.Unsafe; import sun.security.action.GetPropertyAction; import java.io.FilePermission; import java.security.Permission; -import java.util.function.Function; +import jdk.internal.misc.SharedSecrets; /** * Take care of FilePermission compatibility after JDK-8164705. */ public class FilePermCompat { /** - * New behavior? Default "new". + * New behavior? Keep compatibility? Both default true. */ public static final boolean nb; public static final boolean compat; static { String flag = GetPropertyAction.privilegedGetProperty( - "jdk.filepermission.canonicalize", "compat"); + "jdk.io.permissionsUseCanonicalPath", "false"); switch (flag) { case "true": nb = false; @@ -52,51 +51,26 @@ break; case "false": nb = true; - compat = false; - break; - case "compat": - nb = true; compat = true; break; default: throw new RuntimeException( - "Invalid jdk.filepermission.canonicalize: " + flag); + "Invalid jdk.io.permissionsUseCanonicalPath: " + flag); } } - /** - * These fields will be initialized by FilePermission in a static - * block, so that they can access its internals. - */ - public static Function - newPermPlusAltPathFunction, newPermUsingAltPathFunction; - - /** - * Returns a new FilePermission plus an alternative path. - * - * @param input the input - * @return the new FilePermission plus the alt path (as npath2) - * or the input itself if no alt path is available. - */ public static Permission newPermPlusAltPath(Permission input) { if (compat && input instanceof FilePermission) { - Unsafe.getUnsafe().ensureClassInitialized(FilePermission.class); - return newPermPlusAltPathFunction.apply((FilePermission) input); + return SharedSecrets.getJavaIOFilePermissionAccess() + .newPermPlusAltPath((FilePermission) input); } return input; } - /** - * Returns a new FilePermission using an alternative path. - * - * @param input the input - * @return the new FilePermission using the alt path (as npath) - * or null if no alt path is available - */ public static Permission newPermUsingAltPath(Permission input) { if (input instanceof FilePermission) { - Unsafe.getUnsafe().ensureClassInitialized(FilePermission.class); - return newPermUsingAltPathFunction.apply((FilePermission) input); + return SharedSecrets.getJavaIOFilePermissionAccess() + .newPermUsingAltPath((FilePermission) input); } return null; } reverted: --- new/test/java/io/FilePermission/samepath.sh 2016-08-25 11:29:58.095274900 +0800 +++ /dev/null 2016-08-25 11:29:59.000000000 +0800 @@ -1,139 +0,0 @@ -# -# Copyright (c) 2016, 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 8164705 -# @summary Still able to read file on the same path -# -# @run shell samepath.sh - -if [ "${TESTSRC}" = "" ] ; then - TESTSRC="." -fi - -if [ "${TESTJAVA}" = "" ] ; then - JAVA_CMD=`which java` - TESTJAVA=`dirname $JAVA_CMD`/.. -fi - -JAVA="$TESTJAVA/bin/java -Djava.security.manager" -JAVAC=$TESTJAVA/bin/javac -JAR=$TESTJAVA/bin/jar - -if [ -f $TESTJAVA/bin/jlink ]; then - JAKE=true -else - JAKE=false -fi - -cat > App.java < module-info.java < /dev/null -echo base > classes/base -echo child > classes/sp/child -$JAR cvf oldjar/old.jar -C classes . - -if [ $JAKE = true ]; then - $JAVAC -d m/sp App.java module-info.java || exit 1 - echo base > m/sp/base - echo child > m/sp/sp/child - $JAR cvf newjar/new.jar -C m/sp . -fi - -$JAVA -cp classes sp.App S+++++ x classes/base classes/sp/child - child /base ../base || exit 1 -$JAVA -cp oldjar/old.jar sp.App S++0 classes/base - child /base ../base || exit 11 -if [ $JAKE = true ]; then - $JAVA -mp m -m sp/sp.App S+++++ m/sp m/sp/base m/sp/sp/child - child /base ../base || exit 21 - $JAVA -mp newjar -m sp/sp.App SSS++0 m/sp m/sp/base m/sp/sp/child - child /base ../base || exit 31 -fi - -# For Windows, we also check viewing from another drive. Even if there is no -# ALT_DRIVE: we can also check if C:x and x are the same file. - -# We do not support so much. -if [ -f /usr/bin/cygpath---XXX ]; then - [ -d /cygdrive/d ] && ALT_DRIVE=D || ALT_DRIVE=C - JAVA=`cygpath -m $TESTJAVA`"/bin/java -Djava.security.manager" - cmd /c "$ALT_DRIVE: && $JAVA -cp C:classes sp.App S+++++ C:x C:classes/base C:classes/sp/child - child /base ../base" || exit 41 - cmd /c "$ALT_DRIVE: && $JAVA -cp C:oldjar/old.jar sp.App S++0 C:classes/base - child /base ../base" || exit 51 - if [ $JAKE = true ]; then - cmd /c "$ALT_DRIVE: && $JAVA -mp C:m -m sp/sp.App S+++++ C:m/sp C:m/sp/base C:m/sp/sp/child - child /base ../base" || exit 61 - cmd /c "$ALT_DRIVE: && $JAVA -mp C:newjar -m sp/sp.App SSS++0 C:m/sp C:m/sp/base C:m/sp/sp/child - child /base ../base" || exit 71 - fi -fi -echo Done diff -u new/test/sun/security/util/FilePermCompat/Flag.java new/test/sun/security/util/FilePermCompat/Flag.java --- new/test/sun/security/util/FilePermCompat/Flag.java 2016-08-25 11:30:10.694687200 +0800 +++ new/test/sun/security/util/FilePermCompat/Flag.java 2016-09-01 22:22:50.292834600 +0800 @@ -27,9 +27,8 @@ * @summary check jdk.filepermission.canonicalize * @library /java/security/testlibrary/ * @modules java.base/jdk.internal.misc - * @run main/othervm -Djdk.filepermission.canonicalize=true Flag truetrue - * @run main/othervm -Djdk.filepermission.canonicalize=false Flag falsefalse - * @run main/othervm -Djdk.filepermission.canonicalize=compat Flag falsetrue + * @run main/othervm -Djdk.io.permissionsUseCanonicalPath=true Flag truetrue + * @run main/othervm -Djdk.io.permissionsUseCanonicalPath=false Flag falsetrue * @run main/othervm Flag falsetrue */ only in patch2: unchanged: --- old/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java 2016-09-01 22:21:18.260490500 +0800 +++ new/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java 2016-09-01 22:21:17.294984800 +0800 @@ -29,6 +29,7 @@ import java.util.jar.JarFile; import java.io.Console; import java.io.FileDescriptor; +import java.io.FilePermission; import java.io.ObjectInputStream; import java.io.RandomAccessFile; import java.security.ProtectionDomain; @@ -58,6 +59,7 @@ private static JavaNetSocketAccess javaNetSocketAccess; private static JavaNioAccess javaNioAccess; private static JavaIOFileDescriptorAccess javaIOFileDescriptorAccess; + private static JavaIOFilePermissionAccess javaIOFilePermissionAccess; private static JavaSecurityProtectionDomainAccess javaSecurityProtectionDomainAccess; private static JavaSecurityAccess javaSecurityAccess; private static JavaUtilZipFileAccess javaUtilZipFileAccess; @@ -201,6 +203,17 @@ javaIOFileDescriptorAccess = jiofda; } + public static JavaIOFilePermissionAccess getJavaIOFilePermissionAccess() { + if (javaIOFilePermissionAccess == null) + unsafe.ensureClassInitialized(FilePermission.class); + + return javaIOFilePermissionAccess; + } + + public static void setJavaIOFilePermissionAccess(JavaIOFilePermissionAccess jiofpa) { + javaIOFilePermissionAccess = jiofpa; + } + public static JavaIOFileDescriptorAccess getJavaIOFileDescriptorAccess() { if (javaIOFileDescriptorAccess == null) unsafe.ensureClassInitialized(FileDescriptor.class); only in patch2: unchanged: --- /dev/null 2016-09-01 22:22:11.000000000 +0800 +++ new/src/java.base/share/classes/jdk/internal/misc/JavaIOFilePermissionAccess.java 2016-09-01 22:22:09.978471900 +0800 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016, 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 jdk.internal.misc; + +import java.io.FilePermission; + +public interface JavaIOFilePermissionAccess { + + /** + * Returns a new FilePermission plus an alternative path. + * + * @param input the input + * @return the new FilePermission plus the alt path (as npath2) + * or the input itself if no alt path is available. + */ + FilePermission newPermPlusAltPath(FilePermission input); + + /** + * Returns a new FilePermission using an alternative path. + * + * @param input the input + * @return the new FilePermission using the alt path (as npath) + * or null if no alt path is available + */ + FilePermission newPermUsingAltPath(FilePermission input); +} only in patch2: unchanged: --- /dev/null 2016-09-01 22:22:28.000000000 +0800 +++ new/test/java/io/FilePermission/ReadFileOnPath.java 2016-09-01 22:22:27.359520300 +0800 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2016, 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 8164705 + * @library /lib/testlibrary /test/lib + * @modules java.base/jdk.internal.misc + * @run main ReadFileOnPath + * @summary Still able to read file on the same path + */ + +import jdk.test.lib.process.ProcessTools; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class ReadFileOnPath { + + private static final Path SRC_DIR = Paths.get(System.getProperty("test.src")); + private static final Path HERE_DIR = Paths.get("."); + private static final Path MODS_DIR = Paths.get("modules"); + + public static void main(String args[]) throws Exception { + CompilerUtils.compile(SRC_DIR.resolve("m"), MODS_DIR.resolve("m")); + Files.write(MODS_DIR.resolve("m/base"), "base".getBytes()); + Files.write(MODS_DIR.resolve("m/p/child"), "child".getBytes()); + JarUtils.createJarFile(HERE_DIR.resolve("old.jar"), + MODS_DIR.resolve("m"), + "base", "p/App.class", "p/child"); + JarUtils.createJarFile(HERE_DIR.resolve("new.jar"), + MODS_DIR.resolve("m"), + "module-info.class", "base", "p/App.class", "p/child"); + + // exploded module + test("--module-path", "modules", "-m", "m/p.App", "SS+++++"); + + // module in jar + test("--module-path", "new.jar", "-m", "m/p.App", "SSSS++0"); + + // exploded classpath + test("-cp", "modules/m", "p.App", "SS+++++"); + + // classpath in jar + test("-cp", "old.jar", "p.App", "SSSS++0"); + } + + static void test(String... args) throws Exception { + List cmds = new ArrayList<>(); + cmds.add("-Djava.security.manager"); + cmds.addAll(Arrays.asList(args)); + cmds.addAll(List.of( + "x", "modules/m", "modules/m/base", "modules/m/p/child", + "-", "child", "/base", "../base")); + ProcessTools.executeTestJvm(cmds.toArray(new String[cmds.size()])) + .shouldHaveExitValue(0); + } +} only in patch2: unchanged: --- /dev/null 2016-09-01 22:22:34.000000000 +0800 +++ new/test/java/io/FilePermission/m/module-info.java 2016-09-01 22:22:33.180356500 +0800 @@ -0,0 +1,3 @@ +module m { + exports p; +} only in patch2: unchanged: --- /dev/null 2016-09-01 22:22:40.000000000 +0800 +++ new/test/java/io/FilePermission/m/p/App.java 2016-09-01 22:22:38.900011600 +0800 @@ -0,0 +1,44 @@ +package p; +import java.io.InputStream; +import java.io.FileInputStream; +public class App { + public static void main(String[] args) throws Exception { + boolean f = true; + StringBuilder sb = new StringBuilder(); + String expected = null; + for (String s: args) { + if (expected == null) { + expected = s; + } else if (s.equals("-")) { + f = false; + } else if (f) { + try (InputStream is = new FileInputStream(s)) { + is.readAllBytes(); + sb.append('+'); + } catch (SecurityException se) { + System.out.println(se); + sb.append('S'); + } catch (Exception e) { + System.out.println(e); + sb.append('-'); + } + } else { + try (InputStream is = App.class.getResourceAsStream(s)) { + is.readAllBytes(); + sb.append('+'); + } catch (NullPointerException npe) { + System.out.println(npe); + sb.append('0'); + } catch (Exception e) { + System.out.println(e); + sb.append('-'); + } + } + } + if (!sb.toString().equals(expected)) { + throw new Exception("Expected " + expected + ", actually " + sb); + } else { + System.out.println("OK"); + } + } +}