Песочницу Java. Используя securitymanager, чтобы перенаправить ввод-вывод

В настоящее время я пытаюсь написать песочницу для запуска ненадежного кода Java. Идея состоит в том, чтобы изолировать приложение Java от доступа к файловой системе или сетевым сокетам. Решение, которое у меня есть на данный момент, переписано SecurityManager, который запрещает любой доступ к IO или сети.

теперь я хочу не запрещать, а перенаправлять вызовы в файловую систему, т. е. если приложение хочет написать "/главная/пользователя/приложения.txt" путь к файлу должен быть заменен что-то вроде "/ "темп" /trusted_folder/приложения.txt". Поэтому в основном я хочу разрешить приложениям доступ к файловой системе только в определенной папке и перенаправлять все остальные вызовы в эту папку.

Итак, вот метод из класса FileOutputStream, где SM спрашивается, есть ли разрешение на запись в данный путь.

 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);
    }
}

очевидно, что SM не имеет доступа к FileOutputStream и не может изменить внутренний переменные в методе (например,имя или ) или как-то влияют на порядок выполнения, за исключением бросания SecurityException. Я понимаю, что доступ к внутренним полям является нарушением объектно-ориентированных принципов, я понимаю, что локальные переменные видны и существуют только внутри метода, где они были объявлены.

Итак, мой вопрос: есть ли способы разрешить Security Manager заменять вызовы в файловую систему? Если нет, есть ли другие подходы, которые я могу использовать для этого?

надеюсь, я достаточно ясно выразился.

4 ответов


SecurityManager не может этого сделать, он может только сказать да или нет.

Я могу придумать два варианта:

  1. сделайте что-нибудь на уровне ОС с файловой системой. Есть такие вещи, как chroot jails. Это будет прозрачно для приложения, но требует работы за пределами Java.

  2. предоставьте API приложению, которое открывает FileOutputStream для них. Уровень API решает, где находятся файлы из, и это привилегировано (в терминах Security Manager), чтобы открыть файлы из любого места. Конечно, для этого требуется, чтобы изолированное приложение использовало ваш API вместо java.io.File напрямую. Но он также намного более гибкий, и в какой-то момент, вероятно, необходимо, чтобы приложение знало о песочнице и использовало sandbox API, как и на Java WebStart .


Теперь, что Java с открытым исходным кодом, вы можете загрузить исходный код FileOutputStream, измените его исходный код, чтобы применить любые ограничения, которые вы хотите, перекомпилируйте его, добавьте его в jar и добавьте этот JAR в путь к классу загрузчика JVM:

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

JVM теперь будет использовать вашу реализацию java.io.FileOutputStream вместо обычного одного. Промыть и повторить для всех классов JSE, которые нуждаются в специальной логике перенаправления песочницы.

Это не самый портативный и легко развернуть решение, поскольку оно требует" вне виртуальной машины " модификации параметров запуска, но в определенных ситуациях это решение может быть приемлемым и эффективным.


Я не думаю, что это можно сделать. Менеджер безопасности предназначен для запрета доступа к определенным операциям, а не для перенаправления ввода-вывода или других подобных действий.

даже если это возможно через некоторые серьезные размышления hackery, он, вероятно, не будет портативным между различными поставщиками jvm и даже различными операционными системами, работающими под одной и той же jvm. (это потому, что вам нужно будет манипулировать конкретными классами ОС).

то, что вы хотите сделать, следует попытаться сделать ниже уровень, см. chroot для linux и другие более тяжелые методы виртуализации.


Я думаю, что то, что вы пытаетесь сделать, уже было реализовано инженерами Wealthfront.
Вот их запись в блоге об этом:http://eng.wealthfront.com/2010/11/less-io-for-your-java-unit-tests.html