In CodebaseAccessClassLoader, I have been thinking that we might need the
following kind of check to manage exploits that
would know what CodebaseClassAccess instance was being used, and replace it with
one from another class loader.
public static void setCodebaseAccessClassLoader( CodebaseClassAccess access
) {
SecurityManager sm = System.getSecurityManager();
if( sm != null ) {
sm.checkPermission(
new CodebaseAccessOverridePermission(
provider.getClass().getName() ) );
}
// If the same class is replacing an already existing instance, it
might be an exploit to
// load from a different class loader, so don't allow that without the
replace.classname
// permission being in place.
if( provider != null &&
provider.getClass().getName().equals(access.getClass().getName()) &&
provider.getClass().getClassLoader() !=
access.getClass().getClassLoader() ) {
sm.checkPermission(new
CodebaseAccessOverridePermission("replace."+provider.getClass().getName()));
}
provider = access;
}
On 8/11/2012 7:05 PM, Peter Firmstone wrote:
Peter Firmstone wrote:
Just thought I'd get a little clarification on how CodebaseAccessClassLoader
should work and whether it needs any further refinements or tweaks. I'm
currently patching CodebaseAccessClassLoader back into the main trunk, so it
can make the next release.
All references to RMIClassLoader static method calls (except for
RMIClassLoader.getDefaultProviderInstance()) in the platform and supporting
service implementations were replaced with equivalent method calls to
CodebaseAccessClassLoader, I'm now going through the test kits, replacing all
similar method calls.
The relationship between PreferredClassProvider, RMIClassLoader and
CodebaseAccessClassLoader appear circular, so I'm finding it a little
confusing how it should be applied in Netbeans or an OSGi environment.
Observations:
1. CodebaseAccessClassLoader is the replacement for RMIClassLoader,
it has identical static methods (except for
getDefaultProviderInstance()) and three additional methods
(identical to CodebaseClassAccess).
2. CodebaseAccessClassLoader providers must implement the
CodebaseClassAccess interface, which it delegates to.
3. CodebaseAccessClassLoader has a static method to change the
provider, guarded with a security check.
4. CodebaseClassAccess has identical methods to RMIClassLoader
(except for getDefaultProviderInstance()) and three additional
methods:
1. createClassLoader(URL[] urls, ClassLoader parentLoader,
boolean requiredDlperm, AccessControlContext ctx)
2. getParentContextClassLoader()
3. getSystemContextLoader(ClassLoader defaultLoader).
5. RMIClassLoaderCodebaseAccess is a wrapper around RMIClassLoader
that implements CodebaseClassAccess
6. RMIClassLoaderCodebaseAccess is the default provider for
CodebaseAccessClassLoader
7. PreferredClassProvider doesn't implement CodebaseClassAccess.
8. PreferredClassProvider now calls CodebaseAccessClassLoader to get
the context ClassLoader (which may now be something other than the
call Thread's context ClassLoader) and also calls
CodebaseAccessClassLoader.createClassLoader instead of creating a
PreferredClassLoader directly.
9. Call path CodebaseAccessClassLoader -->
RMIClassLoaderCodebaseAccess --> RMIClassLoader -->
PreferredClassProvider --> CodebaseAccessClassLoader -->
RMIClassLoaderCodebaseAccess
10. The interface CodebaseClassAccess includes deprecated methods from
RMIClassLoader
A flaw with the original RMIClassLoaderSPI mechanism is you don't get a
choice of provider, like you do for encryption or other providers, you get
the first loaded provider. The ServiceProvider mechanism in Java 6 is more
flexible than RMIClassLoaderSPI, allowing loading from child ClassLoaders,
not just the system loader.
I understand and appreciate that Gregg has created this to allow development
using Netbeans, a task which the code has proven successful, I also
understand that Chris used it with OSGi. Lets make sure we get it right prior
to release.
Some Questions:
Should CodebaseAccessClassLoader be used to replace RMIClassLoaderSPI?
Shouldn't PreferredClassProvider also implement CodebaseClassAccess? So it
can be used directly as a provider without using RMIClassLoader or
RMIClassLoaderCodebaseAccess?
Shouldn't PreferredClassProvider provide its own methods for creating
ClassLoaders and finding the parent ClassLoader rather than relying on
CodebaseAccessClassLoader, which might be delegating to a different provider.
Should we drop the deprecated RMIClassLoader methods?
My mistake, it doesn't contain any deprecated RMIClassLoader methods.
Should we have additional mechanisms for loading CodebaseAccessClassLoader
providers other than the static setter method? Eg configuration or
ServiceProvider?
Should we have more than one provider available?
Regards,
Peter.