Closed Bug 199051 Opened 21 years ago Closed 21 years ago

Invoker optimization does not work with security manager

Categories

(Rhino Graveyard :: Core, defect)

defect
Not set
normal

Tracking

(Not tracked)

VERIFIED FIXED

People

(Reporter: igor, Assigned: norrisboyd)

Details

Attachments

(2 files, 3 obsolete files)

To speedup invocation of Java methods via reflection Rhino generates special
classes that calls the reflected method directly. It requires to create a class
loader to load the generated byte code for the class but currently Rhino does
not check for a possible SecurityException during loader creation/class load. 

It can happen, for example, if a system security policy disable creation of
class loaders or a currently executed script does not have sufficient privileges
even if Rhino classes are allowed to do that.

The problem was initially reported in netscape.public.mozilla.jseng, see
http://groups.google.com/groups?dq=&hl=en&lr=&ie=UTF-8&threadm=3E708F75.2020108%40icesoft.com&prev=/groups%3Fdq%3D%26num%3D25%26hl%3Den%26lr%3D%26ie%3DUTF-8%26group%3Dnetscape.public.mozilla.jseng%26start%3D25

Here is a way to reproduce the problem based on that:

1. Create the policy file test.policy that prevents Rhino from creating class
loaders with the following body:

grant codeBase "file:${user.home}/path-to-js-jar" 
{
  permission java.lang.RuntimePermission "accessDeclaredMembers";
  permission java.io.FilePermission "<<ALL FILES>>", "read";
  permission java.util.PropertyPermission "*", "read";
}; 


where ${user.home}/path-to-js-jar should be adjusted accordingly (on windows one
may use something like file:/d:/rhino1_5/js.jar

2. Put the following 2 lines into the file test.js in the same directory as
test.policy:

var x = new java.lang.Integer(2);
print(x.intValue());


3. Run Rhino shell in the interpreted mode (if creation of class loaders is
disabled, the optimizer would not work):

java -Djava.security.manager -Djava.security.policy=test.policy
org.mozilla.javascript.tools.shell.Main -opt -1 test.js

It gives instead of expected printed number 2 an exception stack trace:

Exception in thread "main" java.security.AccessControlException: access denied
(java.lang.RuntimePermission createClassLoader)
        at
java.security.AccessControlContext.checkPermission(AccessControlContext.java:272)
        at java.security.AccessController.checkPermission(AccessController.java:399)
        at java.lang.SecurityManager.checkPermission(SecurityManager.java:545)
        at
java.lang.SecurityManager.checkCreateClassLoader(SecurityManager.java:610)
        at java.lang.ClassLoader.<init>(ClassLoader.java:234)
        at
org.mozilla.javascript.DefiningClassLoader.<init>(DefiningClassLoader.java:55)


More complex test case would be to grant the createClassLoader permission to
Rhino classes and use optimizer. In this case the generated classes does not
sufficient privileges and triggers AccessControlException as well:

test.policy:

grant codeBase "file:${user.home}/path-to-js-jar" 
{
  permission java.lang.RuntimePermission "createClassLoader";
  permission java.lang.RuntimePermission "accessDeclaredMembers";
  permission java.io.FilePermission "<<ALL FILES>>", "read";
  permission java.util.PropertyPermission "*", "read";
}; 

invocation:

java -Djava.security.manager -Djava.security.policy=test.policy
org.mozilla.javascript.tools.shell.Main -opt 9 test.js

leads to exactly the same exception.
The patch adds a public API to enable/disable on per Context basis the invoker
optimization and disables it for any Context instance that has seen
SecurityException during invoker invocation. 

The patch also disables invoker optimization in case of var-arg methods since
there any speedup in method invocation is berried under the need to
create/unwrap additional argument arrays.
A simple way to resolve the issue is to create an invoker object in
FunctionObject constructor instead of doing this lazily during script call. In
typical applications FunctionObject instances are constructed during
initialization when there is no script or other code on Java stack with
restricted permissions, so as long as Rhino classes have enough permissions,
Invoker optimization should be available. And if it is not, the patch catches
SecurityException to disable the optimization in this case which will happen
only once and not during each call, so the performance impact should be minimal
even in this case.
Attachment #118361 - Attachment is obsolete: true
Attachment #118908 - Attachment is obsolete: true
I committed the above patch.
Status: NEW → RESOLVED
Closed: 21 years ago
Resolution: --- → FIXED
Verified FIXED.

I followed the steps that Igor outlined above in the Rhino1_5R4
shell vs. the Rhino1_5R5pre shell. I got the same exception as
Igor in R4, but no exception in R5pre. I tried both variations
of the test (opt -1 and opt 9) which Igor explained above.

I will attach my opt -1 results below -
Status: RESOLVED → VERIFIED
Targeting as resolved against 1.5R5
Target Milestone: --- → 1.5R5
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: