Skip to content

Ruby-based SecurityManager can recurse forever #7726

@headius

Description

@headius

It appears that some logic in the invokebinder library is triggering a security check while acquiring a logger.

When Ruby is is compiled by JRuby's JIT using invokedynamic operations, the Binder class is used to set up chains of MethodHandle adaptations. This Binder class has logging features to aid debugging those adaptations, and for this it requests a new Logger instance for each Binder. This is unnecessary, since the loggers should be allocated once and shared for all calls to getLogger anyway, but apparently the security check continues to happen.

This leads to a scenario whereby combining a Ruby-based SecurityManager with invokedynamic causes Binder to trigger a security check, which calls back into the Ruby-based SecurityManager, and so on.

	at rubyobj.TestHigherJavasupport.JRubySecurityManager.checkPermission(test/jruby/test_higher_javasupport.rb:1975)
	at java.base/java.lang.Module.getClassLoader(Module.java:210)
	at java.base/jdk.internal.logger.DefaultLoggerFinder$1.run(DefaultLoggerFinder.java:149)
	at java.base/jdk.internal.logger.DefaultLoggerFinder$1.run(DefaultLoggerFinder.java:144)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:318)
	at java.base/jdk.internal.logger.DefaultLoggerFinder.isSystem(DefaultLoggerFinder.java:144)
	at java.logging/java.util.logging.Logger.demandLogger(Logger.java:651)
	at java.logging/java.util.logging.Logger.getLogger(Logger.java:718)
	at java.logging/java.util.logging.Logger.getLogger(Logger.java:702)
	at org.jruby.dist/com.headius.invokebinder.Binder.<init>(Binder.java:71)
	at org.jruby.dist/com.headius.invokebinder.Binder.from(Binder.java:162)
	at org.jruby.dist/com.headius.invokebinder.SmartBinder.from(SmartBinder.java:89)
	at org.jruby.dist/org.jruby.ir.targets.indy.InvokeSite.prepareBinder(InvokeSite.java:509)
	at org.jruby.dist/org.jruby.ir.targets.indy.InvokeSite.<init>(InvokeSite.java:146)
	at org.jruby.dist/org.jruby.ir.targets.simple.NormalInvokeSite.<init>(NormalInvokeSite.java:26)
	at org.jruby.dist/org.jruby.ir.targets.simple.NormalInvokeSite.newSite(NormalInvokeSite.java:44)
	at org.jruby.dist/org.jruby.ir.targets.simple.NormalInvokeSite.bootstrap(NormalInvokeSite.java:40)
	at java.base/java.lang.invoke.BootstrapMethodInvoker.invoke(BootstrapMethodInvoker.java:168)
	at java.base/java.lang.invoke.CallSite.makeSite(CallSite.java:315)
	at java.base/java.lang.invoke.MethodHandleNatives.linkCallSiteImpl(MethodHandleNatives.java:281)
	at java.base/java.lang.invoke.MethodHandleNatives.linkCallSite(MethodHandleNatives.java:271)
	at test.jruby.test_higher_javasupport.RUBY$method$checkPermission$287(test/jruby/test_higher_javasupport.rb:1975)
	at test.jruby.test_higher_javasupport.RUBY$method$checkPermission$287$__VARARGS__(test/jruby/test_higher_javasupport.rb:1975)
	at org.jruby.dist/org.jruby.internal.runtime.methods.CompiledIRMethod.call(CompiledIRMethod.java:202)
	at org.jruby.dist/org.jruby.RubyClass.finvoke(RubyClass.java:792)
	at org.jruby.dist/org.jruby.runtime.Helpers.invoke(Helpers.java:660)
	at org.jruby.dist/org.jruby.RubyBasicObject.callMethod(RubyBasicObject.java:369)
	at rubyobj.TestHigherJavasupport.JRubySecurityManager.checkPermission(test/jruby/test_higher_javasupport.rb:1975)

A simple fix would be to make the logger a static final field in Binder.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions