Call SecurityManager.checkPackageAccess from Class Loaders

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

 



This is something we discussed a while ago.  gcj never got around to
doing this, so I added the check.  However, there were two problems,
which have taken me all day (grr) to fix.

* Class.initializeClass has a nasty habit of swallowing exceptions and
  re-throwing them as NoClassDefFoundErrors.  This is wrong, becasue
  we really do need to re-throw the SecurityException.

* When testing I ran into a nasty crash with a user-defined
  SecurityManager.  The problem was that
  SecurityManager.checkPackageAccess itself needs to load Security
  classes, and if the user-defined SecurityManager then calls
  checkPackageAccess we have infinite recursion.  Interestingly, this
  is Sun bug #4242924.

Most of this is gcj-specific, but the last one may as well be applied
to Classpath.

Testcase to follow.

Andrew.


2007-01-26  Andrew Haley  <aph@xxxxxxxxxx>

        * java/lang/natClass.cc (initializeClass): Re-throw
        SecurityExceptions.
        * java/lang/natVMClassLoader.cc (loadClass): checkPackageAccess.
        * java/lang/ClassLoader.java: (loadClass): Likewise.

2007-01-26  Andrew Haley  <aph@xxxxxxxxxx>

        * java/lang/SecurityManager.java: Load and initialize
        java.security.Security.

Index: classpath/java/lang/SecurityManager.java
===================================================================
--- classpath/java/lang/SecurityManager.java	(revision 121113)
+++ classpath/java/lang/SecurityManager.java	(working copy)
@@ -167,6 +167,18 @@
    */
   public SecurityManager()
   {
+    /* "When there is security manager installed, the security manager
+       need to check the package access. However, if the security
+       manager itself uses any unloaded class, it will trigger the
+       classloading, which causes infinite loop. There is no easy
+       legal solution. The workaround will be that security manager
+       can not depend on any unloaded class. In the constructor of
+       security manager, it must transitively load all classes it
+       refers to."  Sun bug #4242924.  */
+
+    // Load and initialize java.security.Security
+    java.security.Security.getProvider((String)null);
+
     SecurityManager sm = System.getSecurityManager();
     if (sm != null)
       sm.checkPermission(new RuntimePermission("createSecurityManager"));
Index: java/lang/ClassLoader.java
===================================================================
--- java/lang/ClassLoader.java	(revision 121113)
+++ java/lang/ClassLoader.java	(working copy)
@@ -404,6 +404,14 @@
   protected synchronized Class loadClass(String name, boolean resolve)
     throws ClassNotFoundException
   {
+    SecurityManager sm = SecurityManager.current;
+    if (sm != null)
+      {
+	int lastDot = name.lastIndexOf('.');
+	if (lastDot != -1)
+	  sm.checkPackageAccess(name.substring(0, lastDot));
+      }
+
     // Arrays are handled specially.
     Class c;
     if (name.length() > 0 && name.charAt(0) == '[')
Index: java/lang/natClass.cc
===================================================================
--- java/lang/natClass.cc	(revision 121113)
+++ java/lang/natClass.cc	(working copy)
@@ -50,6 +50,7 @@
 #include <java/lang/NullPointerException.h>
 #include <java/lang/RuntimePermission.h>
 #include <java/lang/System.h>
+#include <java/lang/SecurityException.h>
 #include <java/lang/SecurityManager.h>
 #include <java/lang/StringBuffer.h>
 #include <java/lang/VMClassLoader.h>
@@ -690,6 +691,10 @@
 	  {
 	    _Jv_Linker::wait_for_state(this, JV_STATE_LINKED);
 	  }
+	catch (java::lang::SecurityException *x)
+	  {
+	    throw x;
+	  }
 	catch (java::lang::Throwable *x)
 	  {
 	    // Turn into a NoClassDefFoundError.
@@ -727,6 +732,10 @@
 	{
 	  _Jv_InitClass (superclass);
 	}
+      catch (java::lang::SecurityException *x)
+	{
+	  throw x;
+	}
       catch (java::lang::Throwable *except)
 	{
 	  // Caught an exception.
@@ -745,6 +754,10 @@
       if (meth)
 	((void (*) (void)) meth->ncode) ();
     }
+  catch (java::lang::SecurityException *x)
+    {
+      throw x;
+    }
   catch (java::lang::Throwable *except)
     {
       if (! java::lang::Error::class$.isInstance(except))
Index: java/lang/natVMClassLoader.cc
===================================================================
--- java/lang/natVMClassLoader.cc	(revision 121113)
+++ java/lang/natVMClassLoader.cc	(working copy)
@@ -32,8 +32,10 @@
 #include <java/security/ProtectionDomain.h>
 #include <java/lang/ClassFormatError.h>
 #include <java/lang/StringBuffer.h>
+#include <java/lang/SecurityManager.h>
 #include <java/lang/Runtime.h>
 #include <java/util/HashSet.h>
+#include <java/lang/SecurityException.h>
 #include <java/lang/VirtualMachineError.h>
 
 java::lang::Class *
@@ -204,6 +206,16 @@
 jclass
 java::lang::VMClassLoader::loadClass(jstring name, jboolean resolve)
 {
+  using namespace ::java::lang;
+
+  SecurityManager *sm = (SecurityManager *)SecurityManager::current;
+  if (sm)
+    {
+      jint lastDot = name->lastIndexOf('.');
+      if (lastDot != -1)
+	sm->checkPackageAccess(name->substring(0, lastDot));
+    }
+
   // We try the boot loader first, so that the endorsed directory
   // overrides compiled-in classes.
   jclass klass = NULL;


[Index of Archives]     [Linux Kernel]     [Linux Cryptography]     [Fedora]     [Fedora Directory]     [Red Hat Development]

  Powered by Linux