Is it possible to sandbox just a Runnable

306 Views Asked by At

Is it possible to sandbox my Runnable within Java? Given a Runnable, I want the code inside of it (along with whatever threads it spawns) to run in a sandbox that only lets the code access a specific path on the fileystem. Once that Runnable finishes, the thread should go back to whatever normal permissions it had while any remaining spawned threads would still have the filesystem restriction applied.

I want to do this at run-time. That means that I want to avoid creating policy files and passing in custom arguments to the JVM. I've so far been able to apply sandboxing to my entire application but I haven't found a way to scope it to just the Runnable running in the current thread...

if (System.getSecurityManager() == null) {
    System.setSecurityManager(new SecurityManager());
}

CodeSource nullSource = new CodeSource(null, (CodeSigner[]) null);

PermissionCollection perms = new Permissions();
perms.add(new FilePermission(path.toAbsolutePath().toString() + "/*", "read"));

ProtectionDomain domain = new ProtectionDomain(nullSource, perms);
AccessControlContext safeContext = new AccessControlContext(
        new ProtectionDomain[]{domain});

AccessController.doPrivileged((PrivilegedAction) () -> {
    try {
        r.run();
    } catch (Exception e) {
        throw new IllegalStateException(e);
    }
    return null;
}, safeContext);
1

There are 1 best solutions below

0
On

The doPrivileged technique of limiting permissions applies only to trusted code that does not abuse its position (for instance, by calling doPrivileged itself). So useful as a layer against XML inclusion, for instance, but not untrusted plugins.

You can load code at runtime with specific permissions using a custom ClassLoader, but you would have to reload the code if you wanted the permissions.

The Object Capability Model gives a 'pure' dynamic solution. The container passes the plugin an object that is capable of performing the privileged action. Internally the object's methods can just be the action surrounded by a doPrivileged. Crucially the actions are only available through an instance and unprivileged code is not permitted to instantiate it. This is similar to, say, FileOpenService in JNLP/WebStart, if you ignore ServiceMangaer. Internal to the JDK you may see the likes of Unsafe and SharedSecrets, although those are more about avoiding repeated security checks.