--- a/src/java.base/share/classes/java/io/FilePermission.java Fri Apr 19 10:22:20 2019 +0800
+++ b/src/java.base/share/classes/java/io/FilePermission.java Mon Apr 22 13:01:57 2019 +0800
@@ -463,6 +463,9 @@
* <P>
* The default value of the {@code jdk.io.permissionsUseCanonicalPath}
* system property is {@code false} in this implementation.
+ * <p>
+ * The value can also be set with a security property using the same name,
+ * but setting a system property will override the security property value.
*
* @param path the pathname of the file/directory.
* @param actions the action string.
--- a/src/java.base/share/classes/sun/security/util/FilePermCompat.java Fri Apr 19 10:22:20 2019 +0800
+++ b/src/java.base/share/classes/sun/security/util/FilePermCompat.java Mon Apr 22 13:01:57 2019 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, 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
@@ -42,8 +42,11 @@
public static final boolean compat;
static {
- String flag = GetPropertyAction.privilegedGetProperty(
- "jdk.io.permissionsUseCanonicalPath", "false");
+ String flag = SecurityProperties.privilegedGetOverridable(
+ "jdk.io.permissionsUseCanonicalPath");
+ if (flag == null) {
+ flag = "false";
+ }
switch (flag) {
case "true":
nb = false;
--- a/src/java.base/share/conf/security/java.security Fri Apr 19 10:22:20 2019 +0800
+++ b/src/java.base/share/conf/security/java.security Mon Apr 22 13:01:57 2019 +0800
@@ -1215,6 +1215,25 @@
jdk.security.caDistrustPolicies=SYMANTEC_TLS
#
+# FilePermission path canonicalization
+#
+# This security property dictates how the path argument is processed and stored
+# while constructing a FilePermission object. If the value is set to true, the
+# path argument is canonicalized and FilePermission methods (such as implies,
+# equals, and hashCode) are implemented based on this canonicalized result.
+# Otherwise, the path argument is not canonicalized and FilePermission methods are
+# implemented based on the original input. See the implementation note of the
+# FilePermission class for more details.
+#
+# If a system property of the same name is also specified, it supersedes the
+# security property value defined here.
+#
+# The default value for this property is false.
+#
+jdk.io.permissionsUseCanonicalPath=false
+
+
+#
# Policies for the proxy_impersonator Kerberos ccache configuration entry
#
# The proxy_impersonator ccache configuration entry indicates that the ccache
--- a/test/jdk/java/security/testlibrary/Proc.java Fri Apr 19 10:22:20 2019 +0800
+++ b/test/jdk/java/security/testlibrary/Proc.java Mon Apr 22 13:01:57 2019 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, 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,6 +25,9 @@
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -110,6 +113,7 @@
private List<String> args = new ArrayList<>();
private Map<String,String> env = new HashMap<>();
private Map<String,String> prop = new HashMap();
+ private Map<String,String> secprop = new HashMap();
private boolean inheritIO = false;
private boolean noDump = false;
@@ -176,6 +180,11 @@
prop.put(a, b);
return this;
}
+ // Specifies a security property. Can be called multiple times.
+ public Proc secprop(String a, String b) {
+ secprop.put(a, b);
+ return this;
+ }
// Inherit the value of a system property
public Proc inheritProp(String k) {
String v = System.getProperty(k);
@@ -282,6 +291,17 @@
cmd.add(cp.stream().collect(Collectors.joining(File.pathSeparator)));
}
+ if (!secprop.isEmpty()) {
+ Path p = Path.of(getId("security"));
+ try (OutputStream fos = Files.newOutputStream(p);
+ PrintStream ps = new PrintStream(fos)) {
+ secprop.forEach((k,v) -> ps.println(k + "=" + v));
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ prop.put("java.security.properties", p.toString());
+ }
+
for (Entry<String,String> e: prop.entrySet()) {
cmd.add("-D" + e.getKey() + "=" + e.getValue());
}
@@ -380,6 +400,12 @@
}
return p.waitFor();
}
+ // Wait for process end with expected exit code
+ public void waitFor(int expected) throws Exception {
+ if (p.waitFor() != expected) {
+ throw new RuntimeException("Exit code not " + expected);
+ }
+ }
// The following methods are used inside a proc
--- a/test/jdk/sun/security/util/FilePermCompat/Flag.java Fri Apr 19 10:22:20 2019 +0800
+++ b/test/jdk/sun/security/util/FilePermCompat/Flag.java Mon Apr 22 13:01:57 2019 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, 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
@@ -23,22 +23,84 @@
/*
* @test
- * @bug 8164705
+ * @bug 8164705 8209901
+ * @library /test/jdk/java/security/testlibrary
+ * @modules java.base/jdk.internal.misc
* @summary check jdk.filepermission.canonicalize
- * @run main/othervm/policy=flag.policy
- * -Djdk.io.permissionsUseCanonicalPath=true Flag true true
- * @run main/othervm/policy=flag.policy
- * -Djdk.io.permissionsUseCanonicalPath=false Flag false true
- * @run main/othervm/policy=flag.policy Flag false true
*/
import java.io.File;
import java.io.FilePermission;
import java.lang.*;
+import java.nio.file.Path;
public class Flag {
public static void main(String[] args) throws Exception {
+ if (args.length == 0) {
+ String policy = Path.of(
+ System.getProperty("test.src"), "flag.policy").toString();
+
+ // effectively true
+ Proc.create("Flag")
+ .prop("java.security.manager", "")
+ .prop("java.security.policy", policy)
+ .prop("jdk.io.permissionsUseCanonicalPath", "true")
+ .args("run", "true", "true")
+ .start()
+ .waitFor(0);
+ Proc.create("Flag")
+ .prop("java.security.manager", "")
+ .prop("java.security.policy", policy)
+ .secprop("jdk.io.permissionsUseCanonicalPath", "true")
+ .args("run", "true", "true")
+ .start()
+ .waitFor(0);
+ Proc.create("Flag")
+ .prop("java.security.manager", "")
+ .prop("java.security.policy", policy)
+ .secprop("jdk.io.permissionsUseCanonicalPath", "false")
+ .prop("jdk.io.permissionsUseCanonicalPath", "true")
+ .args("run", "true", "true")
+ .start()
+ .waitFor(0);
+
+ // effectively false
+ Proc.create("Flag")
+ .prop("java.security.manager", "")
+ .prop("java.security.policy", policy)
+ .prop("jdk.io.permissionsUseCanonicalPath", "false")
+ .args("run", "false", "true")
+ .start()
+ .waitFor(0);
+ Proc.create("Flag")
+ .prop("java.security.manager", "")
+ .prop("java.security.policy", policy)
+ .secprop("jdk.io.permissionsUseCanonicalPath", "false")
+ .args("run", "false", "true")
+ .start()
+ .waitFor(0);
+ Proc.create("Flag")
+ .prop("java.security.manager", "")
+ .prop("java.security.policy", policy)
+ .secprop("jdk.io.permissionsUseCanonicalPath", "true")
+ .prop("jdk.io.permissionsUseCanonicalPath", "false")
+ .args("run", "false", "true")
+ .start()
+ .waitFor(0);
+ Proc.create("Flag")
+ .prop("java.security.manager", "")
+ .prop("java.security.policy", policy)
+ .args("run", "false", "true")
+ .start()
+ .waitFor(0);
+ } else {
+ run(args);
+ }
+ }
+
+ static void run(String[] args) throws Exception {
+
boolean test1;
boolean test2;
@@ -55,8 +117,8 @@
test2 = false;
}
- if (test1 != Boolean.parseBoolean(args[0]) ||
- test2 != Boolean.parseBoolean(args[1])) {
+ if (test1 != Boolean.parseBoolean(args[1]) ||
+ test2 != Boolean.parseBoolean(args[2])) {
throw new Exception("Test failed: " + test1 + " " + test2);
}
}