IllegalAccessException is not a SecurityException

IllegalAccessException is not a SecurityException

What is your first response when you see an application failed with java.lang.IllegalAccessException?  Is it caused by insufficient security permissions?  Not really.  IllegalAccessException is not a subtype of java.lang.SecurityException.  Let's say you want to call a private method in anotehr class, which is normally not allowed by javac.  But you know you can bypass javac with reflection like this:

 1 import java.lang.reflect.Method;
2 public class CallFoo {
3     public static void main(String args[]) throws Exception {
4         Class fooClass = Class.forName("Foo");
5         Foo foo = (Foo) fooClass.newInstance();
6         Method helloMethod = fooClass.getDeclaredMethod("hello");
7         helloMethod.invoke(foo);
8     }
9 }
1 public class Foo {
2     private void hello() {
3         System.out.println("This is Foo.hello");
4     }
5 }

C:\\ws\\nb\\Simple>java CallFoo

Exception in thread "main" java.lang.IllegalAccessException: Class CallFoo can not access a member of class Foo with modifiers "private"
        at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:65)
        at java.lang.reflect.Method.invoke(Method.java:578)
        at CallFoo.main(CallFoo.java:7)


My first response was that I don't have sufficient security permission.  But there is no SecurityManager installed in the above test run, and so both Foo and CallFoo classes should have AllPermissions.

Well, the real cause is that we need to suppress Java language access checking, in order to reflectively invoke a private method in another class, with setAccessible(true):

 6 Method helloMethod = fooClass.getDeclaredMethod("hello");
7     if(!helloMethod.isAccessible()) {
8         helloMethod.setAccessible(true);
9     }
10 helloMethod.invoke(foo);

Furthermore, when a SecurityManager is enable, we need extra permissions to call setAccessible(true).  Otherwise, we get:

C:\\ws\\nb\\Simple>java -Djava.security.manager CallFoo
Exception in thread "main" java.security.AccessControlException: access denied (java.lang.reflect.ReflectPermission suppressAccessChecks)
        at java.security.AccessControlContext.checkPermission(AccessControlContext.java:264)
        at java.security.AccessController.checkPermission(AccessController.java:427)
        at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
        at java.lang.reflect.AccessibleObject.setAccessible(AccessibleObject.java:107)
        at CallFoo.main(CallFoo.java:8)


We only want to grant this suppressAccessChecks permission to trusted code source, definitely not to all classes in the call stack.  So we would modify CallFoo.java:

 1 import java.lang.reflect.InvocationTargetException;
2 import java.lang.reflect.Method;
3 import java.security.AccessController;
4 import java.security.PrivilegedActionException;
5 import java.security.PrivilegedExceptionAction;

6 public class CallFoo {
7     public static void main(String args[]) throws Exception {
8         doCallFoo();
9     }
10
11     public static void doCallFoo() throws IllegalAccessException, ClassNotFoundException, NoSuchMethodException,
12             InvocationTargetException, InstantiationException, PrivilegedActionException {
13           Class fooClass = Class.forName("Foo");
14         final Foo foo = (Foo) fooClass.newInstance();
15         final Method helloMethod = fooClass.getDeclaredMethod("hello");
16
17         AccessController.doPrivileged(new PrivilegedExceptionAction() {
18             public Object run() throws Exception {
19                 if(!helloMethod.isAccessible()) {
20                     helloMethod.setAccessible(true);
21                 }
22                 helloMethod.invoke(foo);
23               return null;
24             }
25         });
26     }
27 }

In addition, we specify our security requirement in foo.policy:

// Core classes get all permissions
grant codeBase "file:./-" {
    permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
};


Finally, this test can pass with or without SecurityManager:

C:\\ws\\nb\\Simple>java -Djava.security.manager -Djava.security.policy=foo.policy CallFoo
This is Foo.hello

C:\\ws\\nb\\Simple>java CallFoo
This is Foo.hello

technorati tags: , ,

Comments:

thanks alot this helped me out

Posted by craig e. on November 07, 2007 at 08:56 AM EST #

hi

Posted by guest on November 17, 2009 at 11:59 PM EST #

Hi craig,

I did not understand below line.
"In addition, we specify our security requirement in foo.policy:"

Can you guide me where this application specific foo.policy file exists ? or where we need to put this policy file ?

Thanks in advnace,
Pratik

Posted by guest on June 16, 2011 at 10:19 PM EDT #

Post a Comment:
  • HTML Syntax: NOT allowed
About

Cheng Fang

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today