JDK-8266345 : (fs) Custom DefaultFileSystemProvider security related loops
  • Type: Bug
  • Component: security-libs
  • Sub-Component: java.security
  • Affected Version: 13,14,16,17
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2021-04-29
  • Updated: 2021-11-09
  • Resolved: 2021-07-12
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 17 JDK 18
17 b31Fixed 18Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Description
ADDITIONAL SYSTEM INFORMATION :
macOS Catalina 10.15.7
JDK 16

A DESCRIPTION OF THE PROBLEM :
A custom DefaultFileSystemProvider with -Djava.security.manager and -Djava.security.policy=<policy> loops in FileSystemProvider newByteChannel.

REGRESSION : Last worked in version 12

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
It can be reproduced with the JDK TestProvider class
/usr/libexec/java_home -v 12 --exec javac -d . ~/Documents/GitHub/jdk16-master/test/jdk/java/nio/file/spi/TestProvider.java

JDK 12 is the last version where it works for me. (I don't have a working 13. It doesn't work at 14).
So I compile against that.
See test class source below.

It uses the all.poicy file with...
// 

grant {
    permission java.security.AllPermission;
};

Reproduce as shown in Results

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
/usr/libexec/java_home -v 12 --exec java -cp . -Djava.security.manager -Djava.security.policy=all.policy -Djava.nio.file.spi.DefaultFileSystemProvider=TestProvider org.test.Test
TestProvider$TestFileSystem@23fc625e
TestProvider

ACTUAL -
/usr/libexec/java_home -v 14 --exec java -cp . -Djava.security.manager -Djava.security.policy=Classes/all.policy -Djava.nio.file.spi.DefaultFileSystemProvider=TestProvider org.test.Test
TestProvider$TestFileSystem@23fc625e
Exception in thread "main" java.lang.StackOverflowError
	at java.base/java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:593)
	at java.base/java.lang.StringBuilder.append(StringBuilder.java:173)
	at java.base/sun.nio.fs.UnixFileSystem.getPath(UnixFileSystem.java:269)
	at TestProvider$TestFileSystem.getPath(TestProvider.java:261)
	at java.base/java.nio.file.Path.of(Path.java:147)
	at java.base/sun.security.provider.PolicyFile.initDefaultPolicy(PolicyFile.java:478)
	at java.base/sun.security.provider.PolicyFile$2.run(PolicyFile.java:340)
	at java.base/sun.security.provider.PolicyFile$2.run(PolicyFile.java:337)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:312)
	at java.base/sun.security.provider.PolicyFile.initPolicyFile(PolicyFile.java:337)
	at java.base/sun.security.provider.PolicyFile.init(PolicyFile.java:330)
	at java.base/sun.security.provider.PolicyFile.<init>(PolicyFile.java:283)
	at java.base/java.security.Policy.loadPolicyProvider(Policy.java:207)
	at java.base/java.security.Policy.getPolicyNoCheck(Policy.java:178)
	at java.base/java.security.ProtectionDomain.implies(ProtectionDomain.java:321)
	at java.base/java.security.ProtectionDomain.impliesWithAltFilePerm(ProtectionDomain.java:353)
	at java.base/java.security.AccessControlContext.checkPermission(AccessControlContext.java:450)
	at java.base/java.security.AccessController.checkPermission(AccessController.java:1036)
	at java.base/java.lang.SecurityManager.checkPermission(SecurityManager.java:408)
	at java.base/java.lang.SecurityManager.checkRead(SecurityManager.java:747)
	at java.base/sun.nio.fs.UnixChannelFactory.open(UnixChannelFactory.java:255)
	at java.base/sun.nio.fs.UnixChannelFactory.newFileChannel(UnixChannelFactory.java:143)
	at java.base/sun.nio.fs.UnixChannelFactory.newFileChannel(UnixChannelFactory.java:156)
	at java.base/sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:217)
	at TestProvider.newByteChannel(TestProvider.java:173)
...

---------- BEGIN SOURCE ----------

package org.test;

import java.nio.file.FileSystems;
import java.nio.file.spi.FileSystemProvider;
import java.lang.reflect.Constructor;

public class Test {
	
	public static void main(String [] args) {
		System.out.println(FileSystems.getDefault());
		System.out.println(System.getProperty("java.nio.file.spi.DefaultFileSystemProvider"));
	}
	
}

/usr/libexec/java_home -v 12 --exec javac -d . ~/testfsp/Test.java
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Run JDK12 for custom DefaultFileSystemProvider with -Djava.security.manager and -Djava.security.policy

FREQUENCY : always



Comments
I haven’t tried the incident test case because I assume that has been verified as fixed.
23-07-2021

Requested the submitter verify the fix by downloading the latest versions of JDK 18 from https://jdk.java.net/18/ and JDK 17 from https://jdk.java.net/17/
21-07-2021

Changeset: 4fc3180f Author: Sean Mullan <mullan@openjdk.org> Date: 2021-07-12 14:54:38 +0000 URL: https://git.openjdk.java.net/jdk17/commit/4fc3180f75e1cea4ebd613f8253be205d95f830c
12-07-2021

This regression was most likely introduced in JDK 13 by https://bugs.openjdk.java.net/browse/JDK-8218618 (which was fixed in JDK 13, not 14). That was when the `sun.security.provider.PolicyFile` code first called `Path.of` which would use the custom `FileSystem` provider, if specified.
12-07-2021

Indeed modifying sun.security.provider.PolicyFile as suggested appears to fix the problem. --- a/src/java.base/share/classes/sun/security/provider/PolicyFile.java +++ b/src/java.base/share/classes/sun/security/provider/PolicyFile.java @@ -44,6 +44,8 @@ import java.util.concurrent.ConcurrentHashMap; import jdk.internal.access.JavaSecurityAccess; import jdk.internal.access.SharedSecrets; import jdk.internal.util.StaticProperty; +import sun.nio.fs.DefaultFileSystemProvider; + import sun.security.util.*; import sun.net.www.ParseUtil; @@ -275,6 +277,13 @@ public class PolicyFile extends java.security.Policy { private static Set<URL> badPolicyURLs = Collections.newSetFromMap(new ConcurrentHashMap<URL,Boolean>()); + /** + * Use the platform's default file system to avoid recursive initialization + * issues when the VM is configured to use a custom file system provider. + */ + private static final java.nio.file.FileSystem builtInFS = + DefaultFileSystemProvider.theFileSystem(); + /** * Initializes the Policy object and reads the default policy * configuration file(s) into the Policy object. @@ -474,10 +483,10 @@ public class PolicyFile extends java.security.Policy { } private void initDefaultPolicy(PolicyInfo newInfo) { - Path defaultPolicy = Path.of(StaticProperty.javaHome(), - "lib", - "security", - "default.policy"); + Path defaultPolicy = builtInFS.getPath(StaticProperty.javaHome(), + "lib", + "security", + "default.policy"); if (debug != null) { debug.println("reading " + defaultPolicy); }
11-05-2021

The observations on Windows 10: JDK 11: Passed. StackOverflowError did not happen. JDK 12: Passed. JDK 13: Passed. JDK 14: Failed, Exception in thread "main" java.lang.StackOverflowError JDK 16: Failed. JDK 17ea+6: Failed.
04-05-2021

[~tongwan] Thanks, I suspect we'll need to move this to security-libs once we've looked at it a bit more.
30-04-2021

Yes. I tested with JDK 11 and the StackOverflowError did not happen. For JDK 16 and 17ea, both of them threw StackOverflowError.
30-04-2021

[~tongwan] Did you duplicate this? I'm curious if this is really a regression. In any case, it's yet another stack overflow issue with security manager. In this case, I suspect PolicyFile will need to be re-worked to use the built-in file system provider (like FilePermission).
30-04-2021