db-derby-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Daniel John Debrunner <...@debrunners.com>
Subject Re: context classloader versus default classloader
Date Wed, 23 Nov 2005 04:12:49 GMT
David W. Van Couvering wrote:

> The concern I have is that DatabaseClasses.loadApplicationClass() uses
> the thread context classloader, and if the class is not found there (or
> there is no context classloader), only then does it use the default
> classloader.
> Let's say I'm able to create a classloader whose search path only
> includes specific derby jar files (to avoid the issues of mixed versions
> of Derby).
> Then let's say I try to make use of this when getting connections:
> URLClassLoader cl = new MyClassLoader()
> EmbeddedDataSource ds =
> (EmbeddedDataSource)(cl.loadClass("org.apache.derby.jdbc.EmbeddedDataSource").newInstance())
> Connection conn = ds.getConnection(...);

Of course the variable ds here would have to be declared as
javax.sql.DataSource and not EmbeddedDataSource. :-)

> This effectively sets the default classloader for EmbeddedDataSource
> (and all its dependent classes) to be MyClassLoader.
> What I am concerned about is that there is all this code in the Derby
> engine that calls DatabaseClasses.loadApplicationClass().  It looks like
> this is used to load classes for VTIs and Java stored procedures (it's
> hard to tell) as well as a number of other things I'm not clear on.  If
> any of these classes are Derby classes (for instance internal VTIs) then
> it would seem that my attempt to correctly load Derby classes from the
> right jar files will be thwarted.

So the use of the class context class loader was added for J2EE
applications. In those the application's classes for procedures,
functions, vti's etc. can be stored in the WAR or EAR file, and those
classes are available to the system through the context class loader.
The context class loader is set up by the container manager, ie. the
application server, WAS or Geronimo etc.

> Probably the right thing for me to do is test this, but if you have any
> observations about this that might guide me it would be much appreciated.

One of the changes I made to the Cloudscape code before it was open
sourced as Derby, was to separate the packages at a high level.
Previously all the code, product and tests, had a common package prefix,
COM.cloudscape or com.ibm.db2j. This meant there was no way to tell from
a class name if the class was a Derby class or a test class (e.g.
function). With Derby I separated the code so that tests were all under
org.apache.derbyTesting and product under org.apache.derby (and some
other splits.) This then allows (though it's not done yet) class loading
code to be more precise in loading classes, since it's obvious that any
org.apache.derby. class is  part of the system and not a test procedure etc.

As an example, related to the security changes I'm working on, I'm
thinking about making the class loaders for the application installed
jars (sqlj.install_jar) refuse to load any class starting with the
prefix 'org.apache.derby.'. This would then remove one potential hole
where an application could try to subvert an engine class.

There may be similar possible changes for loadApplicationClass(), don't
load org.apache.derby. classes through the context class loader.

It may be that ensuring the classes are loaded from the same jar/class
loader is good for security and for the multi-version issue.

In addition most of the packages in derby.jar are now sealed, which
means that classes in a sealed package must be loaded from the same jar.
 This is not sufficient because if a class is loaded from another jar an
error is thrown rather than ignoring the load. Thus, without changes, an
application can try to subvert and inject invalid versions of Derby
classes, which will not be accepted by the vm, but could cause a denial
of service.

Hope this helps as background info.

View raw message