clang не застрял в #include "/dev/what"

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

#include "/dev/stdin"
#include "/proc/self/fd/0"
#include <stdio.h>
// Other legitimate code

Я пытаюсь воспроизвести это. При компиляции с gcc foo.c, gcc застревает и читает с терминала до EOF (Ctrl-D), как и ожидалось. Когда я clang foo.cну ничего не случилось. Clang ведет себя так, как будто линий никогда не существовало. Тогда я попробовал эти коды:

#include "/dev/zero"
#include "/dev/random"
#include "/dev/ram"

Все еще не повезло. Почему Clang игнорирует все это? Как я могу заставить Clang застрять #includeчто-то?

2 ответа

Решение

Сделай FIFO и включи его. Обратите внимание, что это только кажется, чтобы остановить лязг; это не читает из этого. Это может работать только до тех пор, пока команда Clang не увидит это....

Стандарт C указывает, что

Директива предварительной обработки вида

# include <h-char-sequence> new-line

ищет последовательность мест, определенных реализацией, для заголовка, уникально идентифицированного указанной последовательностью [...]. Как места определяются или как определяется заголовок, определяется реализацией.

Директива предварительной обработки вида

# include "q-char-sequence" new-line

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

# include <h-char-sequence> new-line

с идентичной содержащейся последовательностью (включая> символы, если таковые имеются) из исходной директивы.

( C2011 6.10.2 / 2-3; выделение добавлено)

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

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

Обновить:

Почему Clang игнорирует все это?

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

Как я могу заставить Clang застрять, включив что-то?

Подходы, которые вы уже попробовали, кажутся наиболее вероятными. Если бы они не работали, то, возможно, не было способа сломить Кланга таким образом.

Другие вопросы по тегам