New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AccessControlException with wrong path when calling File.realpath under SecurityManager and classpath containing spaces #4633

Closed
trejkaz opened this Issue May 30, 2017 · 5 comments

Comments

Projects
None yet
3 participants
@trejkaz

trejkaz commented May 30, 2017

Environment

JRuby 9.1.10.0
Java 1.8.0 u92
Security manager enabled
IDEA installed at "/Applications/IntelliJ IDEA CE.app"

Other relevant info you may wish to add:

  • Installed or activated gems
  • Application/framework version (e.g. Rails, Sinatra)
  • Environment variables

Expected Behavior

This test code:

    ScriptEngine engine = createEngine();
    String path = "classpath:/com/nuix/integration/vendor/jruby/TestRubyFile.class";
    String result = (String) engine.eval("File.realpath('" + path + "')");
    assertThat(result, is(equalTo(path)));

When running with no security manager, passes. So I'd expect it to pass under the security manager too.

Actual Behavior

When running under the security manager, it appears to be accessing a bogus path:

javax.script.ScriptException: org.jruby.embed.EvalFailedException: java.security.AccessControlException: access denied ("java.io.FilePermission" "/Applications/IntelliJ%20IDEA%20CE.app/Contents/lib/idea_rt.jar" "read")
	at org.jruby.embed.jsr223.JRubyEngine.wrapException(JRubyEngine.java:104)
	at org.jruby.embed.jsr223.JRubyEngine.eval(JRubyEngine.java:93)
	at org.jruby.embed.jsr223.JRubyEngine.eval(JRubyEngine.java:142)
	at TestFile.testResolveClasspath(TestFile.java:68)
Caused by: org.jruby.embed.EvalFailedException: java.security.AccessControlException: access denied ("java.io.FilePermission" "/Applications/IntelliJ%20IDEA%20CE.app/Contents/lib/idea_rt.jar"     "read")
	at org.jruby.embed.internal.EmbedEvalUnitImpl.run(EmbedEvalUnitImpl.java:137)
	at org.jruby.embed.jsr223.JRubyEngine.eval(JRubyEngine.java:90)
	... 42 more
Caused by: java.security.AccessControlException: access denied ("java.io.FilePermission" "/Applications/IntelliJ%20IDEA%20CE.app/Contents/lib/idea_rt.jar" "read")
	at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)
	at java.security.AccessController.checkPermission(AccessController.java:884)
	at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
	at java.lang.SecurityManager.checkRead(SecurityManager.java:888)
	at java.util.zip.ZipFile.<init>(ZipFile.java:210)
	at java.util.zip.ZipFile.<init>(ZipFile.java:149)
	at java.util.jar.JarFile.<init>(JarFile.java:166)
	at java.util.jar.JarFile.<init>(JarFile.java:103)
	at org.jruby.util.JarCache$JarIndex.<init>(JarCache.java:46)
	at org.jruby.util.JarCache.getIndex(JarCache.java:146)
	at org.jruby.util.JarResource.createJarResource(JarResource.java:39)
	at org.jruby.util.JarResource.create(JarResource.java:29)
	at org.jruby.util.URLResource.addDirectoryEntries(URLResource.java:237)
	at org.jruby.util.URLResource.addDirectoriesFromClassloader(URLResource.java:225)
	at org.jruby.util.URLResource.createClassloaderURI(URLResource.java:201)
	at org.jruby.util.URLResource.create(URLResource.java:263)
	at org.jruby.util.JRubyFile.createResource(JRubyFile.java:98)
	at org.jruby.util.JRubyFile.createResource(JRubyFile.java:71)
	at org.jruby.RubyFile.fileResource(RubyFile.java:1433)
	at org.jruby.RubyFileTest.exist_p(RubyFileTest.java:125)
	at org.jruby.RubyFileTest.exist_p(RubyFileTest.java:117)
	at org.jruby.RubyFile.realpath(RubyFile.java:863)
	at org.jruby.RubyFile$INVOKER$s$0$1$realpath.call(RubyFile$INVOKER$s$0$1$realpath.gen)
	at org.jruby.internal.runtime.methods.JavaMethod$JavaMethodN.call(JavaMethod.java:721)
	at org.jruby.internal.runtime.methods.DynamicMethod.call(DynamicMethod.java:200)
	at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:338)
	at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:163)
	at org.jruby.ir.interpreter.InterpreterEngine.processCall(InterpreterEngine.java:314)
	at org.jruby.ir.interpreter.StartupInterpreterEngine.interpret(StartupInterpreterEngine.java:73)
	at org.jruby.ir.interpreter.Interpreter.INTERPRET_ROOT(Interpreter.java:112)
	at org.jruby.ir.interpreter.Interpreter.execute(Interpreter.java:99)
	at org.jruby.ir.interpreter.Interpreter.execute(Interpreter.java:35)
	at org.jruby.ir.IRTranslator.execute(IRTranslator.java:42)
	at org.jruby.Ruby.runInterpreter(Ruby.java:844)
	at org.jruby.Ruby.runInterpreter(Ruby.java:848)
	at org.jruby.embed.internal.EmbedEvalUnitImpl.run(EmbedEvalUnitImpl.java:118)
	... 43 more

The actual path has been granted in the policy, like so:

grant {
  permission java.io.FilePermission "/Applications/IntelliJ IDEA CE.app/-", "read";
}

So I think there are two problems here.

  1. I don't think that URL encoding is supposed to be present in strings passed to FilePermission, so I assume JRuby is accidentally trying to access "/Applications/IntellijJ%20IDEA%20CE.app" instead of "/Applications/IntellijJ IDEA CE.app".
  2. Even if the security manager rejects reading some path, I don't think that should stop this particular test passing, because the JAR containing the target file is not in that location.

Admittedly, this one is a pretty obscure issue. :/

@headius

This comment has been minimized.

Member

headius commented May 31, 2017

The URL encoding may be correct. Note from the stack trace that this constructor passes through URLResource on the way to the jar. Now whether that's the correct logic to use at that level, I'm not sure, but we're just asking for a resource out of a jar, which usually is handled as a URL at some point.

Is there really nothing at the path it reports, or is there some symlinking involved?

What happens if you give it permission for the "bogus" path?

@trejkaz

This comment has been minimized.

trejkaz commented Jun 1, 2017

If I add the permit line for the wrong path, it finishes. But the file it was wasn't in that jar anyway, so it should have worked either way, IMO.

If I log the calls to the JarFile(String) constructor, which is supposed to accept a file path, not a URL path, I see the %20 in the paths there too. I do see it also try to open the jar without the %20 though... smells like there is a hack where it tries it with and without decoding the string, because the code isn't sure whether the string it's holding is a file path or a URL. :/

Breakpoint reached at java.util.jar.JarFile.<init>(JarFile.java:103)
/Applications/IntelliJ%20IDEA%20CE.app/Contents/lib/idea_rt.jar
Breakpoint reached at java.util.jar.JarFile.<init>(JarFile.java:103)
/Applications/IntelliJ IDEA CE.app/Contents/lib/idea_rt.jar
@headius

This comment has been minimized.

Member

headius commented Jun 1, 2017

Ok so one theory would be that our JarIndex class should just fail to index jars when there's a security violation. Then it would move on to other jars looking for the requested file.

I'll push a branch, if you can test it out.

@headius

This comment has been minimized.

Member

headius commented Jun 1, 2017

@trejkaz Have a look at #4640.

@headius headius added this to the JRuby 9.1.12.0 milestone Jun 13, 2017

@enebo enebo modified the milestones: JRuby 9.2.0.0, JRuby 9.1.12.0 Jun 15, 2017

@trejkaz

This comment has been minimized.

trejkaz commented Jun 16, 2017

Verifying that everything is OK on 9.1.12.0. I know I should have checked earlier, but as usual, other things always seem to jump to the top of the stack...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment