Java sandbox. Using SecurityManager to redirect I/O access
Asked Answered
P

4

10

Currently I'm trying to write the Sandbox for running untrusted Java code. The idea is to isolate Java application from accessing file system or network sockets. The solution I have at the moment is rewritten SecurityManager, that forbids any access to IO or network.

Now I want not to forbid, but to redirect calls to the file system, i.e. if application wants to write to "/home/user/application.txt" the path to the file should be replaced with something like "/temp/trusted_folder/application.txt". So basically I want to allow applications to access file system only in some particular folder and to redirect all other calls to this folder.

So here is the method from the class FileOutputStream, where SM is asked, whether there is a permission to write to the given path.

 public FileOutputStream(File file, boolean append)
    throws FileNotFoundException
{
    String name = (file != null ? file.getPath() : null);
    SecurityManager security = System.getSecurityManager();
    if (security != null) {
        security.checkWrite(name);
    }
    if (name == null) {
        throw new NullPointerException();
    }
    fd = new FileDescriptor();
    fd.incrementAndGetUseCount();
    this.append = append;
    if (append) {
        openAppend(name);
    } else {
        open(name);
    }
}

Obviously, the SM does not have an access to FileOutputStream and can not change inner variables in method (like name or file) or somehow affect the execution order, except throwing the SecurityException. I do understand, that accessing inner fields is violation of Object oriented principles, I do understand, that local variable are visible and exist only inside the method, where they were declared.

So my question is: Are there any ways to allow Security Manager to replace calls to file system? If not, are there any other approaches I can use in order to do this?

I hope I was clear enough.

Psychopathology answered 1/12, 2010 at 8:59 Comment(0)
R
6

The SecurityManager cannot do that, it can only say yes or no.

I can think of two options:

  1. Do something on the OS level with the file system. There are things like chroot jails. That would be transparent for the application, but requires work outside of Java.

  2. Provide an API to the application that opens the FileOutputStream for them. The API layer gets to decide where the files are from, and it is privileged (in Security Manager terms) to open files from anywhere. Of course, this requires that the sandboxed application uses your API instead of java.io.File directly. But it is also much more flexible, and at some point it is probably necessary for an application to be aware of the sandbox and use the sandbox API, just like on Java WebStart for example.

Rideout answered 1/12, 2010 at 9:12 Comment(1)
thanks for the answer. First option I could not accept, since I don't want to restrict my self to one OS, but the second option looks quite nice. I searched for some API replacement and found out, that JMockit tool can mock classes and do stubs. So basically I'll look into it and I think, that this is what I need now.Psychopathology
D
6

Now that Java is open source, you can download the source code to FileOutputStream, modify its source code to enforce whatever constraints you wish, recompile it, add it to a jar, and prepend that JAR to the JVM's bootloader classpath:

java -Xbootclasspath/p:myModifiedJavaClasses.jar sandbox.Main -run untrusted.Main

The JVM will now use your implementation of java.io.FileOutputStream instead of the usual one. Rinse and repeat for all JSE classes which need special sandbox redirection logic.

It is not the most portable or easily deployed solution, as it requires "outside the VM" modifications to launch parameters, but in certain situations this solution may be acceptable and effective.

Damarisdamarra answered 1/12, 2010 at 9:27 Comment(1)
I was using this myself, but with Java9, Xbootclasspath and Xbootclasspath/p have been removed. Now --patch-module is supposed to be used. Still reading the changes to make sense of it lol openjdk.java.net/jeps/261Manda
S
0

I don't think it can be done. The security manager is designed to deny access to specific operations, not to redirect IO or do other things like that.

even if it is possible through some serious reflection hackery, it will probably not be portable between different jvm vendors and even different operating systems running the same jvm. (that's because you will need to manipulate OS specific classes).

what you want to do should be attempted at a lower level, see chroot for linux and other heavier virtualization techniques.

Spillar answered 1/12, 2010 at 9:15 Comment(0)
S
0

I think that what you're trying to do was already implemented by the engineers at Wealthfront.
Here's their blog entry about it : http://eng.wealthfront.com/2010/11/less-io-for-your-java-unit-tests.html

Sheugh answered 1/12, 2010 at 9:27 Comment(1)
The article does not say anything like that. They are describing a SecurityManager that audits and potentially disallows unexpected I/O operations. Disallows, not modifies.Rideout

© 2022 - 2024 — McMap. All rights reserved.