classpath
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Security manager problem


From: Mark Wielaard
Subject: Re: Security manager problem
Date: Tue, 13 Dec 2005 19:39:19 +0100

Hi Gary,

On Mon, 2005-12-12 at 17:55 +0000, Gary Benson wrote:
> Gary Benson wrote:
> > Robert Lougher wrote:
> > > Do you have a testcase?
> > 
> > If you build and run the attached testcase you ought to see only one
> > checkPermission() between "Calling checkRead()" and "Done". ... In
> > reality, JamVM chokes on it pretty hard.  I _think_ what is
> > happening is that the System.out.println in checkPermission() is
> > itself doing some initialisation which causes security checks,
> > causing an infinite loop.
> 
> The initialisation in question turns out to be:
> 
>  1. Loading java.lang.StringBuffer to build the message.
>  2. Loading java.io.PrintStream to print it out.
>  3. Converting the message to bytes using String.getBytes(encoding).
> 
> Any one of them will trigger a security check and hence an infinite
> loop.

Aha! There is your clue. libgcj hasn't merged in the new nio charset
provider setup. And indeed creating a new CharsetProvider requires a
RuntimePermission("charsetProvider"). Even for creating the default
provider. Which obviously should always be created, otherwise nothing
works. It is safe in this case since we know the default provider
doesn't do nasty things (or at least we hope so). So you need the
attached patch to gnu/java/nio/charset/Provider.java.

But even then you need some more workaround. There are two steps needed:
- Before the SecurityManager is installer we make sure that the whole
  System.out pipeline gets initialized.
- In the user defined TestSecurityManager we make sure that all classes
  that are used in the checkPermission() method are loaded before it
  gets installed. That is System and StringBuffer (because we use +).
Modified Test.java attached.

All this seems to come from having a user defined security manager
loaded by a user defined class loader (the default System/Application
class loader). We need to do ClassLoader.loadClass() checks in that
case. But as shown in this example that leads very easily to recursive
checkPermission() calls.

I don't have a good idea how to make this easier. Any ideas?

Cheers,

Mark
import java.security.*;

class Test
{
  static class TestSecurityManager extends SecurityManager
  {
    TestSecurityManager()
    {
        // Make sure the classes needed by checkPermission() are loaded.
        Class c = System.class;
        c = StringBuffer.class;
    }

    public void checkPermission(Permission perm) {
      System.out.println("  checkPermission(" + perm + ")");
    }
  }
        
  public static void main(String[] args) {
    try {
      // Make sure System is loaded
      // and the full System.out pipeline is initialized.
      System.out.println("Installing TestSecurityManager");

      SecurityManager sm = new TestSecurityManager();
      System.setSecurityManager(sm);
      System.out.println("Calling checkRead()");
      sm.checkRead("/");
      System.out.println("Done");
    }
    catch (Throwable t) {
      t.printStackTrace();
    }
  }
}
Index: gnu/java/nio/charset/Provider.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/nio/charset/Provider.java,v
retrieving revision 1.6
diff -u -r1.6 Provider.java
--- gnu/java/nio/charset/Provider.java  2 Jul 2005 20:32:13 -0000       1.6
+++ gnu/java/nio/charset/Provider.java  13 Dec 2005 18:38:18 -0000
@@ -39,6 +39,8 @@
 
 import java.nio.charset.Charset;
 import java.nio.charset.spi.CharsetProvider;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -232,8 +234,16 @@
 
   public static synchronized Provider provider ()
   {
+    // The default provider is safe to instantiate.
     if (singleton == null)
-      singleton = new Provider ();
+      singleton = (Provider) AccessController.doPrivileged
+       (new PrivilegedAction()
+         {
+           public Object run()
+           {
+             return new Provider();
+           }
+         });
     return singleton;
   }
 }

Attachment: signature.asc
Description: This is a digitally signed message part


reply via email to

[Prev in Thread] Current Thread [Next in Thread]