Как создать легкую песочницу с кодом C? - PullRequest
36 голосов
/ 11 июня 2009

Я хотел бы создать препроцессор / компилятор C, который позволяет собирать функции из локальных и онлайн-источников. то есть:

#fetch MP3FileBuilder http://scripts.com/MP3Builder.gz
#fetch IpodDeviceReader http://apple.com/modules/MP3Builder.gz

void mymodule_main() {
  MP3FileBuilder(&some_data);
}

Это легкая часть.

Сложная часть: Мне нужен надежный способ «песочницы» импортированного кода от прямого или неограниченного доступа к дисковым или системным ресурсам (включая выделение памяти и стек) . Мне нужен способ безопасного запуска небольших фрагментов ненадежного кода C (модули) без дополнительных затрат на помещение их в отдельный процесс, виртуальную машину или интерпретатор (хотя отдельный поток будет приемлемым).

ТРЕБОВАНИЯ

  • Мне нужно было бы установить квоты на доступ к данным и ресурсам, включая время процессора.
  • Я заблокирую прямой доступ к стандартным библиотекам
  • Я хочу остановить вредоносный код, который создает бесконечную рекурсию
  • Я хочу ограничить статическое и динамическое распределение определенными пределами
  • Я хочу перехватить все исключения, которые может вызвать модуль (например, делить на 0).
  • Модули могут взаимодействовать с другими модулями только через основные интерфейсы
  • Модули могут взаимодействовать с системой (ввод-вывод и т. Д.) Только через основные интерфейсы
  • Модули должны разрешать битовые операции, математические операции, массивы, перечисления, циклы и ветвления.
  • Модули не могут использовать ASM
  • Я хочу ограничить доступ указателя и массива к памяти, зарезервированной для модуля (через пользовательский safe_malloc ())
  • Должен поддерживать ANSI C или подмножество (см. Ниже)
  • Система должна быть легкой и кроссплатформенной (включая встроенные системы).
  • Система должна быть совместима с GPL или LGPL.

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

не означает, что существующий код C может быть повторно использован без модификации для создания модуля. Предполагается, что модули должны будут соответствовать набору правил и ограничений, предназначенных для ограничения модуля базовыми логическими операциями и операциями преобразования (например, такими как транскодирование видео или операции сжатия).

Теоретическим вводом для такого компилятора / препроцессора будет отдельный файл ANSI C (или безопасное подмножество) с функцией module_main, директивами препроцессора NO или NO, без ASM, он будет разрешать циклы, ветвления, функции вызовы, математические указатели (ограниченные диапазоном, выделенным модулю), сдвиг битов, битовые поля, приведение, перечисления, массивы, целые числа, числа с плавающей запятой, строки и математические вычисления. Все остальное необязательно.

ПРИМЕР ОСУЩЕСТВЛЕНИЯ

Вот фрагмент псевдокода, чтобы объяснить это лучше. Здесь модуль превышает свою квоту выделения памяти, а также создает бесконечную рекурсию.

buffer* transcodeToAVI_main( &in_buffer ) {
    int buffer[1000000000]; // allocation exceeding quota
    while(true) {} // infinite loop
    return buffer;
}

Вот преобразованная версия, в которой наш препроцессор добавил точки наблюдения для проверки использования памяти и рекурсии и поместил все это в обработчик исключений.

buffer* transcodeToAVI_main( &in_buffer ) {
    try {
        core_funcStart(__FILE__,__FUNC__); // tell core we're executing this function
        buffer = core_newArray(1000000000, __FILE__, __FUNC__); // memory allocation from quota
        while(true) {
           core_checkLoop(__FILE__, __FUNC__, __LINE__) && break; // break loop on recursion limit
        } 
        core_moduleEnd(__FILE__,__FUNC__);
    } catch {
        core_exceptionHandler(__FILE__, __FUNC__);
    }
    return buffer;
}

Я понимаю, что выполнение этих проверок влияет на производительность модуля, но я подозреваю, что он все равно будет превосходить языки высокого уровня или языки VM для задач, которые он должен решать. Я не пытаюсь помешать модулям совершать опасные действия напрямую, я просто пытаюсь заставить эти опасные вещи происходить контролируемым образом (например, через обратную связь с пользователем). т.е.: «Модуль X превысил выделение памяти, продолжить или прервать?».

UPDATE

Лучшее, что у меня есть, - это использование собственного компилятора (например, взломанного TCC) с проверкой границ и некоторой пользовательской функцией и циклическим кодом для перехвата рекурсий. Я все еще хотел бы услышать мысли о том, что еще мне нужно проверить или какие решения есть. Я полагаю, что удаление ASM и проверка указателей перед использованием решает многие проблемы, высказанные в предыдущих ответах ниже. Я добавил награду, чтобы получить еще больше отзывов от SO сообщества.

Для награды, которую я ищу:

  • Сведения о потенциальных подвигах против теоретической системы, определенной выше
  • Возможные оптимизации проверки указателей при каждом доступе
  • Экспериментальные реализации концепций с открытым исходным кодом (например, Google Native Client)
  • Решения, поддерживающие широкий спектр ОС и устройств (без ОС / аппаратных решений)
  • Решения, которые поддерживают большинство операций C или даже C ++ (если это возможно)

Дополнительный кредит за метод, который может работать с GCC (например, препроцессор или маленький патч GCC).

Я также рассмотрю каждого, кто может окончательно доказать, что я пытаюсь сделать, вообще не может быть. Вы должны будете быть достаточно убедительными, потому что ни одно из возражений до сих пор не выявило технических аспектов того, почему они считают это невозможным. В защиту тех, кто сказал «нет», этот вопрос изначально представлялся как способ безопасного запуска C ++. Теперь я сократил требование к ограниченному подмножеству C.

Мое понимание C может быть классифицировано как «промежуточное», мое понимание аппаратного обеспечения ПК, возможно, на шаг ниже «продвинутого». Попробуйте тренировать свои ответы для этого уровня, если можете. Поскольку я не эксперт по Си, я буду в основном опираться на голоса, отданные за ответ, а также на то, насколько близко ответ соответствует моим требованиям. Вы можете помочь, предоставив достаточные доказательства своих претензий (респонденты) и проголосовав (все остальные). Я назначу ответ, как только обратный отсчет достигнет 6 часов.

Наконец, я считаю, что решение этой проблемы было бы важным шагом к поддержанию актуальности C в мире, который становится все более сетевым и параноидальным. По мере того, как другие языки сокращают разрыв с точки зрения производительности и вычислительной мощности, все труднее будет оправдывать дополнительный риск разработки C (как это сейчас происходит с ASM). Я полагаю, что ваши ответы будут иметь гораздо большую актуальность, чем набирание нескольких SO-баллов, поэтому, пожалуйста, предоставьте все, что можете, даже если срок действия награды истек.

Ответы [ 13 ]

0 голосов
/ 11 июня 2009

Вы, похоже, пытаетесь решить две не проблемы. В моем собственном коде у меня нет проблем с выделением памяти или проблемами с рекурсией или бесконечными циклами.

То, что вы предлагаете, является другим, более ограниченным языком, чем C ++. Конечно, вы можете заниматься этим, но, как уже отмечали другие, вам придется написать для него компилятор - простая обработка текста не даст вам того, что вы хотите.

0 голосов
/ 11 июня 2009

Если вы хотите быть по-настоящему уверенным, я думаю, что лучший и, возможно, единственный способ сделать это - пойти по линии отдельных процессов и позволить O / S управлять контролем доступа. Это не , что больно писать универсальный многопоточный загрузчик, и как только он у вас есть, вы можете переопределить некоторые функции для загрузки определенных библиотек.

0 голосов
/ 11 июня 2009

Хорошая идея, но я вполне уверен, что то, что вы пытаетесь сделать, невозможно с C или C ++. Если вы отбросили идею песочницы, это может сработать.

Java уже имеет подобную (как в большой библиотеке стороннего кода) систему в Maven2

...