2025-11-20T07:49:14.984146

Montsalvat: Partitioning Java Applications to Minimize the TCB in Intel SGX

Yuhala, Ménétrey, Felber et al.
The popularity of the Java programming language has led to its wide adoption in cloud computing infrastructures. However, Java applications running in untrusted clouds are vulnerable to various forms of privileged attacks. The emergence of trusted execution environments (TEEs) such as Intel SGX mitigates this problem. TEEs protect code and data in secure enclaves inaccessible to untrusted software, including the kernel and hypervisors. To efficiently use TEEs, developers must manually partition their applications into trusted and untrusted parts, in order to reduce the size of the trusted computing base (TCB) and minimise the risks of security vulnerabilities. However, partitioning applications poses two important challenges: (i) ensuring efficient object communication between the partitioned components, and (ii) ensuring the consistency of garbage collection between the parts, especially with memory-managed languages such as Java. We present Montsalvat, a tool which provides a practical and intuitive annotation-based partitioning approach for Java applications destined for secure enclaves. Montsalvat provides an RMI-like mechanism to ensure inter-object communication, as well as consistent garbage collection across the partitioned components. We implement Montsalvat with GraalVM native-image, a tool for compiling Java applications ahead-of-time into standalone native executables that do not require a JVM at runtime. Our extensive evaluation with micro- and macro-benchmarks shows our partitioning approach to boost performance in real-world applications
academic

Montsalvat: Разделение приложений Java для минимизации TCB в Intel SGX

Основная информация

  • ID статьи: 2305.00766
  • Название: Montsalvat: Partitioning Java Applications to Minimize the TCB in Intel SGX
  • Авторы: Peterson Yuhala, Jämes Ménétrey, Pascal Felber, Valerio Schiavoni, Alain Tchana, Gaël Thomas, Hugo Guiroux, Jean-Pierre Lozi
  • Категория: cs.CR (Криптография и безопасность)
  • Конференция: 22-я Международная конференция по промежуточному программному обеспечению (Middleware 2021)
  • Ссылка на статью: https://arxiv.org/abs/2305.00766

Аннотация

Популярность языка программирования Java привела к его широкому внедрению в облачной инфраструктуре. Однако приложения Java, работающие в ненадежных облачных средах, подвержены различным привилегированным атакам. Появление доверенных сред выполнения (TEE), таких как Intel SGX, смягчает эту проблему. TEE защищает код и данные в безопасных анклавах от доступа ненадежного программного обеспечения, включая ядро и гипервизор. Для эффективного использования TEE разработчики должны вручную разделить приложение на доверенные и недоверенные части, чтобы уменьшить размер доверенной вычислительной базы (TCB) и минимизировать риск уязвимостей безопасности. В данной статье предлагается инструмент Montsalvat, который обеспечивает практичный и интуитивный метод разделения на основе аннотаций для приложений Java, ориентированных на безопасные анклавы. Montsalvat предоставляет механизм, подобный RMI, для обеспечения связи между объектами, а также согласованную сборку мусора между разделенными компонентами.

Исследовательский контекст и мотивация

Определение проблемы

  1. Угрозы безопасности: приложения Java в ненадежных облачных средах сталкиваются с угрозами привилегированных атак, включая атаки на уровне ядра и гипервизора
  2. Требование минимизации TCB: при использовании TEE, таких как Intel SGX, необходимо минимизировать доверенную вычислительную базу для снижения поверхности атаки
  3. Сложность разделения: ручное разделение приложений Java требует обработки сложных проблем, таких как связь между объектами и согласованность сборки мусора

Ограничения существующих решений

  1. Решения с полным приложением: SCONE, Graphene-SGX и другие размещают все приложение (включая JVM) в анклаве, что приводит к чрезмерно большому TCB (миллионы строк кода)
  2. Решения для конкретных фреймворков: VC3, SecureKeeper и другие применимы только к определенным фреймворкам и не универсальны
  3. Существующие решения для разделения Java:
    • Civet требует полной LibOS, TCB остается большим
    • Uranus требует инструментов третьих сторон для определения доверенного раздела, требуя значительного вмешательства разработчика

Исследовательская мотивация

Разработать универсальный автоматизированный инструмент разделения приложений Java, способный:

  • Обеспечить интуитивный способ аннотирования на уровне класса
  • Реализовать эффективную связь объектов между анклавами
  • Обеспечить согласованность распределенной сборки мусора
  • Значительно уменьшить размер TCB

Основные вклады

  1. Метод разделения на основе аннотаций: предложен практичный и интуитивный способ аннотирования на уровне класса (@Trusted, @Untrusted, @Neutral) для разделения приложений Java
  2. Механизм RMI: разработан механизм связи объектов между анклавами, подобный RMI, реализующий прозрачные удаленные вызовы методов через прокси-объекты
  3. Распределенная сборка мусора: реализовано расширение GC на основе слабых ссылок, обеспечивающее согласованность уничтожения объектов между доверенной и недоверенной кучей
  4. Интеграция с GraalVM: глубокая интеграция с GraalVM native-image, использующая AOT-компиляцию для оптимизации производительности
  5. Улучшение производительности: достижение значительного улучшения производительности в реальных приложениях (PalDB 6.6×, GraphChi 2.2×)

Подробное описание метода

Определение задачи

Входные данные: исходный код приложения Java с аннотациями безопасности Выходные данные: разделенные доверенный и недоверенный native image, готовые к развертыванию в среде Intel SGX Ограничения: сохранение исходной семантики приложения, обеспечение связи объектов и согласованности GC

Архитектура системы

Рабочий процесс Montsalvat включает 4 основных этапа:

1. Этап аннотирования кода

Предоставляются три типа аннотаций:

  • @Trusted: класс и его экземпляры всегда создаются и работают внутри анклава
  • @Untrusted: класс и его экземпляры всегда работают вне анклава
  • @Neutral: служебные классы, могут независимо существовать в нескольких копиях на обеих сторонах

2. Этап трансформации байт-кода

Использование фреймворка Javassist для трансформации байт-кода:

Генерация прокси-классов:

  • Для каждого доверенного класса генерируется прокси-класс в недоверенной среде выполнения
  • Для каждого недоверенного класса генерируется прокси-класс в доверенной среде выполнения
  • Прокси-классы сохраняют исходные сигнатуры методов, но тело методов заменяется на вызовы между анклавами

Внедрение методов-ретрансляторов:

// Исходный метод преобразуется в метод-ретранслятор
@CEntryPoint
public static void relayAccount(Isolate ctx, int hash, 
                               CCharPointer buf, int b) {
    String s = deserialize(buf);
    Account mirror = new Account(s, b);
    mirrorProxyRegistry.add(hash, mirror);
}

Механизм отображения объектов:

  • Каждому прокси-объекту назначается уникальное хеш-значение
  • Ведется реестр соответствия прокси-объектов и зеркальных объектов
  • Ссылки между объектами в разных анклавах реализуются через хеш-значения

3. Разделение Native Image

Использование статического анализа GraalVM:

  • Доверенный образ: содержит конкретные реализации доверенных классов + прокси-классы недоверенных классов
  • Недоверенный образ: содержит конкретные реализации недоверенных классов + прокси-классы доверенных классов
  • Анализ точек автоматически удаляет недостижимый код

4. Генерация приложения SGX

  • Shim-библиотека: легковесная библиотека, перехватывающая неподдерживаемые вызовы libc и ретранслирующая их в недоверенную среду выполнения
  • Генерация EDL: автоматическая генерация файла определения анклава
  • Финальная компоновка: генерация исполняемого приложения SGX

Технические инновации

1. Стратегия разделения на уровне класса

По сравнению с разделением на уровне метода или данных:

  • Более соответствует интуиции объектно-ориентированного программирования
  • Избегает сложного анализа потока данных
  • Естественные границы инкапсуляции

2. Механизм прозрачного прокси

  • Сохранение исходной модели программирования
  • Автоматическая обработка сериализации/десериализации параметров
  • Поддержка передачи сложных графов объектов между анклавами

3. Дизайн распределенной GC

// Синхронизация GC на основе слабых ссылок
WeakReference<ProxyObject> weakRef = new WeakReference<>(proxy);
proxyWeakRefs.add(new ProxyWeakRefEntry(weakRef, proxy.getHash()));

// Периодическая проверка GC Helper
if (weakRef.get() == null) {
    // Прокси-объект был собран, уведомляем другую сторону об уничтожении зеркального объекта
    notifyMirrorDestruction(hash);
}

Экспериментальная установка

Экспериментальная среда

  • Оборудование: Intel Xeon E3-1270 CPU (3.80 GHz), 64GB RAM
  • Конфигурация SGX: 128MB EPC (93.5MB доступно), максимальная куча 4GB, стек 8MB
  • Программное обеспечение: Ubuntu 18.04, SGX SDK v2.11, GraalVM CE v21.0.0
  • Базовые линии сравнения: SCONE (JVM работает внутри анклава)

Метрики оценки

  • Метрики производительности: время выполнения приложения, задержка операций
  • Анализ затрат: затраты на создание прокси-объектов, затраты на вызовы RMI, производительность GC
  • Коэффициент ускорения: производительность относительно неразделенного решения и решения SCONE

Тестовые приложения

  1. Синтетические бенчмарки: операции, интенсивные по CPU и I/O
  2. PalDB: встроенное хранилище ключ-значение от LinkedIn
  3. GraphChi: фреймворк для обработки больших графов (алгоритм PageRank)
  4. SPECjvm2008: стандартные микробенчмарки Java

Результаты экспериментов

Основные результаты производительности

1. Улучшение производительности реальных приложений

  • PalDB: улучшение в 6.6× по сравнению с SCONE (схема RTWU), 2.8× (схема RUTW)
  • GraphChi: улучшение в 2.2× по сравнению с SCONE
  • SPECjvm2008: значительное улучшение в 5 из 6 бенчмарков (1.38×-2.66×)

2. Анализ затрат прокси-объектов

  • Создание прокси-объектов медленнее конкретных объектов на 3-4 порядка
  • Вызовы RMI медленнее локальных вызовов на 3-4 порядка
  • Сериализация параметров добавляет 10× затрат (внутри анклава) до 3× затрат (вне анклава)

3. Влияние на производительность GC

  • GC внутри анклава медленнее GC вне анклава на 1 порядок
  • Проверка согласованности GC: зеркальные объекты правильно очищаются при уничтожении прокси-объектов

Абляционные эксперименты

Сравнение стратегий разделения

Через синтетические бенчмарки с различными пропорциями доверенных классов:

  • Интенсивные по CPU: значительное улучшение производительности при перемещении большего количества классов из анклава
  • Интенсивные по I/O: еще более заметное улучшение производительности при перемещении операций I/O из анклава

Неразделенное vs разделенное vs SCONE

Во всех тестах порядок производительности:

  1. Нативное выполнение (без SGX) - самое быстрое, но небезопасное
  2. Разделенный native image - баланс производительности и безопасности
  3. Неразделенный native image - средняя производительность
  4. SCONE+JVM - самое медленное, но лучшая совместимость

Анализ конкретных случаев

Стратегия разделения PalDB

@Trusted class DBReader   // Защита чувствительных операций чтения
@Untrusted class DBWriter // Перемещение операций записи I/O вне анклава

Схема RTWU показывает лучшую производительность благодаря избеганию дорогостоящих переходов записи в анклав.

Стратегия разделения GraphChi

@Trusted class GraphChiEngine    // Защита основной логики вычислений
@Untrusted class FastSharder     // Операции I/O разделения графа

После перемещения операций разделения вне анклава производительность приближается к нативной.

Связанные работы

Решения с полным приложением в анклаве

  • SCONE, Graphene-SGX, SGX-LKL: обеспечивают хорошую совместимость, но TCB слишком большой
  • Haven: ранее решение с полным приложением

Разделение для конкретных фреймворков

  • VC3: анализ данных Hadoop
  • SecureKeeper: расширение ZooKeeper
  • Opaque: платформа Spark SQL
  • Ограничение: применимы только к конкретным фреймворкам

Универсальные решения разделения

  • Glamdring: автоматическое разделение C/C++, не применимо к Java
  • Panoply: решение с микроконтейнерами
  • Civet: разделение Java, но использует полную LibOS
  • Uranus: аннотирование на уровне метода, требует инструментов третьих сторон

Заключение и обсуждение

Основные выводы

  1. Проверка осуществимости: метод разделения на основе аннотаций на уровне класса осуществим и интуитивен
  2. Преимущества производительности: разделенные приложения показывают значительное улучшение производительности по сравнению с полными решениями для анклава
  3. Снижение TCB: значительное снижение доверенной кодовой базы благодаря использованию shim-библиотеки вместо LibOS
  4. Удобство разработки: способ аннотирования более интуитивен для разработчиков

Ограничения

  1. Требования инкапсуляции: предполагается, что все аннотированные классы правильно инкапсулированы (приватные поля)
  2. Затраты RMI: вызовы между анклавами все еще имеют значительные затраты, не подходят для сценариев частого взаимодействия
  3. Зависимость от GraalVM: ограничение экосистемой GraalVM
  4. Ограничения статического анализа: ограниченная поддержка некоторых динамических функций

Будущие направления

  1. Вызовы без трансформации: исследование техник для снижения дорогостоящих вызовов RMI
  2. Поддержка нескольких изолятов: расширение на среды с несколькими isolate
  3. Автоматическое разделение: рекомендации автоматического разделения на основе статического анализа
  4. Поддержка других TEE: расширение на AMD SME, ARM TrustZone

Глубокая оценка

Преимущества

  1. Высокая инновационность: первый метод разделения приложений Java на уровне класса, дизайн логичен и интуитивен
  2. Полнота инженерной реализации: полная цепочка инструментов от аннотирования до финального приложения SGX
  3. Отличная производительность: демонстрирует значительное улучшение производительности в реальных приложениях
  4. Высокая практическая ценность: решает реальную проблему безопасного развертывания приложений Java в облаке

Недостатки

  1. Все еще значительные затраты: затраты на вызовы RMI остаются на уровне 3-4 порядков, ограничивая применимость
  2. Строгие условия предположений: требования к инкапсуляции классов могут ограничить применимость к существующему коду
  3. Неполнота оценки: отсутствие оценки крупномасштабных и долгосрочных приложений
  4. Недостаточный анализ безопасности: ограниченный анализ защиты от высокоуровневых угроз, таких как атаки по побочным каналам

Влияние

  1. Академический вклад: предоставляет новый подход к разделению приложений управляемых языков в среде TEE
  2. Практическая ценность: может быть непосредственно применен для защиты облачных приложений Java
  3. Воспроизводимость: авторы обещают открыть исходный код, облегчая воспроизведение и расширение исследований

Сценарии применения

  1. Облачные сервисы Java: облачные приложения, требующие защиты чувствительной бизнес-логики
  2. Платформы анализа данных: фреймворки анализа, обрабатывающие чувствительные данные
  3. Приложения финтеха: финансовые сервисы, требующие высокого уровня безопасности
  4. Периферийные вычисления IoT: безопасные вычисления в среде с ограниченными ресурсами

Библиография

Статья цитирует 60 связанных работ, охватывающих технологию SGX, приложения TEE, безопасность Java, оптимизацию компиляции и другие важные области, обеспечивая прочную теоретическую основу для данного исследования.


Общая оценка: это высококачественная системная исследовательская работа, решающая практическую проблему развертывания приложений Java в среде TEE. Метод хорошо разработан, реализация полна, эксперименты тщательны, обладает высокой академической ценностью и практической значимостью. Несмотря на возможности улучшения в отношении затрат RMI и применимости, работа предоставляет важный справочный материал для смежных исследований.