Skip to content

@main methods requires seemingly-unnecessary permissions #9006

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

Closed
propensive opened this issue May 19, 2020 · 5 comments
Closed

@main methods requires seemingly-unnecessary permissions #9006

propensive opened this issue May 19, 2020 · 5 comments

Comments

@propensive
Copy link
Contributor

When running a Dotty-compiled program with a @main method, invoking that main method requires that certain reflective permissions are granted which seem like they shouldn't be necessary. Granting them requires them to be granted to the entire application, which seems like too much of a concession to make in a security-conscious environment.

Minimized code

app.scala:

package app
@main def run(): Unit = println("hello, world")

policy:

grant {
};

Invocation:

java -classpath <classpath> -Djava.security.manager -Djava.security.policy=policy app.run

Output

Fails at runtime unless the following permissions are set:

grant {
  java.lang.RuntimePermission "accessClassInPackage.sun.misc";
  java.lang.RuntimePermission "accessDeclaredMembers";
  java.lang.reflect.ReflectPermission "suppressAccessChecks";
}

Expectation

Runs without exception with an empty security policy.

@smarter
Copy link
Member

smarter commented May 20, 2020

What's the runtime failure? Do you get a stacktrace showing what is trying to access these permissions? We do use sun.misc.Unsafe to implement lazy vals, but that's not specific to @main. We could avoid this usage of unsafe, but only on Java 9+.

@propensive
Copy link
Contributor Author

Sure. Here's the first stacktrace:

Exception in thread "main" java.lang.ExceptionInInitializerError
	at scala.runtime.Statics.releaseFence(Statics.java:148)
	at scala.collection.immutable.Vector.<init>(Vector.scala:135)
	at scala.collection.immutable.Vector$.<clinit>(Vector.scala:83)
	at scala.collection.immutable.IndexedSeq$.<init>(Seq.scala:114)
	at scala.collection.immutable.IndexedSeq$.<clinit>(Seq.scala:114)
	at scala.package$.<clinit>(package.scala:64)
	at scala.Predef$.<clinit>(Predef.scala:154)
	at HelloWorld$.<init>(hw.scala:5)
	at HelloWorld$.<clinit>(hw.scala)
	at HelloWorld.main(hw.scala)
Caused by: java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessClassInPackage.sun.misc")
	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.checkPackageAccess(SecurityManager.java:1564)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:329)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:264)
	at scala.runtime.Statics$VM.mkHandle(Statics.java:164)
	at scala.runtime.Statics$VM.<clinit>(Statics.java:155)
	... 10 more

and if I add the missing permission, the next stack trace is:

Exception in thread "main" java.lang.ExceptionInInitializerError
	at scala.runtime.Statics.releaseFence(Statics.java:148)
	at scala.collection.immutable.Vector.<init>(Vector.scala:135)
	at scala.collection.immutable.Vector$.<clinit>(Vector.scala:83)
	at scala.collection.immutable.IndexedSeq$.<init>(Seq.scala:114)
	at scala.collection.immutable.IndexedSeq$.<clinit>(Seq.scala:114)
	at scala.package$.<clinit>(package.scala:64)
	at scala.Predef$.<clinit>(Predef.scala:154)
	at HelloWorld$.<init>(hw.scala:5)
	at HelloWorld$.<clinit>(hw.scala)
	at HelloWorld.main(hw.scala)
Caused by: java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")
	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.Class.checkMemberAccess(Class.java:2348)
	at java.lang.Class.getDeclaredFields(Class.java:1915)
	at scala.runtime.Statics$VM.findUnsafe(Statics.java:178)
	at scala.runtime.Statics$VM.mkHandle(Statics.java:165)
	at scala.runtime.Statics$VM.<clinit>(Statics.java:155)
	... 10 more

and finally, after adding that permission, I get:

Exception in thread "main" java.lang.ExceptionInInitializerError
	at scala.runtime.Statics.releaseFence(Statics.java:148)
	at scala.collection.immutable.Vector.<init>(Vector.scala:135)
	at scala.collection.immutable.Vector$.<clinit>(Vector.scala:83)
	at scala.collection.immutable.IndexedSeq$.<init>(Seq.scala:114)
	at scala.collection.immutable.IndexedSeq$.<clinit>(Seq.scala:114)
	at scala.package$.<clinit>(package.scala:64)
	at scala.Predef$.<clinit>(Predef.scala:154)
	at HelloWorld$.<init>(hw.scala:5)
	at HelloWorld$.<clinit>(hw.scala)
	at HelloWorld.main(hw.scala)
Caused by: java.security.AccessControlException: access denied ("java.lang.reflect.ReflectPermission" "suppressAccessChecks")
	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.reflect.AccessibleObject.setAccessible(AccessibleObject.java:128)
	at scala.runtime.Statics$VM.findUnsafe(Statics.java:180)
	at scala.runtime.Statics$VM.mkHandle(Statics.java:165)
	at scala.runtime.Statics$VM.<clinit>(Statics.java:155)
	... 10 more

So it looks like it's more closely related to the collections library. I can't find a method called releaseFence in the Dotty source code, nor a file called Statics.java.

@smarter
Copy link
Member

smarter commented May 20, 2020

Yeah, releaseFence comes from https://github.com/scala/scala/blob/a8a726118d06c90b5506f907b1524457c0d401a7/src/library/scala/runtime/Statics.java#L147, note that it won't use sun.misc.Unsafe on Java 9+. (Dotty's lazy vals should do something similar but don't currently)

@smarter smarter closed this as completed May 20, 2020
@propensive
Copy link
Contributor Author

Sounds good. Thanks for the quick response!

@smarter
Copy link
Member

smarter commented May 20, 2020

I've opened #9013 to keep track of the lazy val issue.

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

No branches or pull requests

2 participants