Песочница Java.Использование SecurityManager для перенаправления доступа ввода / вывода - PullRequest
9 голосов
/ 01 декабря 2010

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

Теперь я хочу не запрещать, а перенаправлять вызовы в файловую систему, т. Е. Если приложение хочет записать в "/ home / user / application.txt" путь к файлу, который необходимо заменить с чем-то вроде "/ temp /rust_folder / application.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 и не может изменять внутренние переменные в методе (например, name или file ) или каким-либо образом влиять на порядок выполнения, кроме броска SecurityException. Я понимаю, что доступ к внутренним полям является нарушением объектно-ориентированных принципов, я понимаю, что локальные переменные видимы и существуют только внутри метода, в котором они были объявлены.

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

Надеюсь, я был достаточно ясен.

Ответы [ 4 ]

6 голосов
/ 01 декабря 2010

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

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

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

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

5 голосов
/ 01 декабря 2010

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

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

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

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

    * 1017.*
0 голосов
/ 01 декабря 2010

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

0 голосов
/ 01 декабря 2010

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

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

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

...