Craig's right.

The way the Java 2 security manager works is pretty simple. Most system classes whose methods call "sensitive" functions need to know that callers possess the correct privileges. To do this, the security manager does what's called a "stack walk" -- essentially, it starts with the current stack frame (class+method+line of code) and walks its way backwards in the call stack until it gets to the very topmost frame (e.g., the Main method that started the program) or a doPrivileged() block, whichever comes first. All of the code sources in between must be granted the privilege in order for it to be granted.

The idea is very simple, and provably secure. The consequences are complex, however... here's an example.

We've got an application (JSPWiki) running in a web container. One of our classes has a method foo() that needs to read the file /usr/bin/ bar. You'd think that our code source (e.g., JSPWiki.jar) would needs to be granted java.io.FilePermission "/usr/bin/bin", "read". And you'd be right. That's easy enough to understand, but not the end of the story.

Because of the way the security manager works, unless the code that invokes the read operation is bracketed by a doPrivileged() block, the code source for the stack frame that called foo() ALSO needs to be granted the FilePermission in the security policy. And so does the parent *that* frame. And so forth...

Practically speaking, this means that code that performs sensitive functions (that is, causes a privilege check) needs to be isolated by doPrivileged() blocks so that it doesn't "infect" upstream callers with the requirement to be granted the same privileges. As it stands now, all of the privileges we would have to grant JSPWiki would also need to be granted to all of the Catalina JARs (or OAS, or whatever).

There are two ways of dealing with this:

1) Leaving the code the way it is, but requiring that container JARs be granted all of the privileges we grant JSPWiki. This makes the security policy non-portable, and would be a pain in the arse for system admins.

2) Adding doPrivileged blocks to code that calls sensitive functions, which makes the policy portable. But it's a pain in the arse for us coders. :)

As it happens, one of my side projects outside of JSPWiki is a "policy- maker" project called (with tongue planted firmly in cheek) Kissinger. Kissinger's role is to install a dummy SecurityManager at runtime that logs what privileges callers need. Then, after program termination it tries to create an optimal security policy. It also recommends places to inject doPrivileged() blocks. The recording and policy-writing part works just fine, thanks to some clever code that works sort of like a rootkit (Craig, as the token Sun rep here, please cover your ears). But the analytics part -- doesn't work yet. And I haven't touched the code in over 9 months...

Janne, if you want, I can dust off Kissinger (har har) and see what's required to get it working.

In the meantime, the best thing to do is start looking for code that calls methods that require privilege checks (notably file access, serialization, system properties, SQL, reflection) and put doPrivileged() blocks around them. The list of methods that require permissions are here:

http://java.sun.com/j2se/1.4.2/docs/guide/security/permissions.html

The file I/O code is the most important. I've previously done this already for the JAAS-related code.

Andrew


On Nov 21, 2007, at 4:03 PM, Craig L Russell wrote:

Hi Janne,

On Nov 21, 2007, at 12:46 PM, Janne Jalkanen wrote:

(Digression for Janne and the dev team: any time we do things like file access, we need to bracket the code with a doPrivileged() block so that we don't have to grant file I/O privileges to the container... this is one of the big complicating factors that is preventing a full enumeration of privileges at the moment...)

This sounds insane to me. It complicates everything, and what would we gain by doing it?

What we gain is the ability to run the code inside a standard Java EE container. Instead of mucking around with container permissions or application permissions, you put the required privileges associated with the jspwiki jar file.

There are just a few things that need to be wrapped in a doPrivileged block, like i/o and reflection. It's not all i/o, just stuff like file.createNewFile() and FileInputStream(file). Once you have an InputStream the rest of the code is normal.

Craig

/Janne

Craig Russell
Architect, Sun Java Enterprise System http://java.sun.com/products/jdo
408 276-5638 mailto:[EMAIL PROTECTED]
P.S. A good JDO? O, Gasp!


Reply via email to