Как скомпилировать компилятор C с нуля, а затем скомпилировать Unix / Linux с нуля

64

Допустим, я работаю в крупной сервисной организации за пределами США / Великобритании. Мы широко используем серверы UNIX и Linux.

Читая эту статью, упоминается, что было бы легко вставить бэкдор в компилятор C, тогда любой код, скомпилированный с этим компилятором, также будет содержать бэкдор. Теперь, учитывая недавние утечки в отношении мандата NSA / GCHQ по установке бэкдоров / слабостей во всех методах шифрования, аппаратном и программном обеспечении, компилятор теперь является критической точкой отказа. Потенциально все стандартные дистрибутивы UNIX / Linix могут быть скомпрометированы. Мы не можем позволить, чтобы наши системы, данные и данные наших клиентов были скомпрометированы мошенническими правительствами.

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

Вопрос

Каков правильный (и безопасный) способ компиляции компилятора из исходного кода (по-видимому, сценарий «куриное яйцо») и компиляции надежного дистрибутива Unix / Linux с нуля?

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

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

Как говорит Брюс Шнайер: «Инженерам я говорю следующее: мы создали Интернет, и некоторые из нас помогли его разрушить. Теперь те из нас, кто любит свободу, должны это исправить».

Дополнительные ссылки:

Дэвид Дж
источник
7
Черт, это очень интересный вопрос, и я не хочу его переносить, но я не думаю, что он здесь по теме. Он лучше подходит для stackoverflow.com, так как ваш основной вопрос о том, как скомпилировать компилятор с нуля, который в значительной степени не зависит от ОС и в значительной степени является вопросом программирования. Если через некоторое время вы не получите ответа, рассмотрите возможность использования ссылки «flag» под тегами вашего вопроса и попросите модератора переместить его в SO.
Тердон
2
@terdon На самом деле это может быть лучше подходит для программистов. SE, так как это больше касается общих вопросов программирования, чем конкретной проблемы разработки. На самом деле, это может быть дубликатом там .
CVN
2
GCC с открытым исходным кодом, как любой бэкдор будет вставлен?
Михаил Панков
2
Имейте в виду, что стабильный эксплойт Томпсона требует кода, который может распознавать, когда программа входа в систему или компилятор компилируется. Если вы можете вручную преобразовать исходный код в форму, не распознаваемую компилятором как одну из этих программ, бэкдор не будет распространяться.
Рассел Борогове
2
@Constantius - прочитайте статью Томпсона, указанную в первой строке. Кто компилирует компилятор?
Рассел Борогове

Ответы:

30

AFAIK единственный способ быть полностью уверенным в безопасности - это написать компилятор на языке ассемблера (или изменить сам диск самостоятельно ). Только тогда вы сможете убедиться, что ваш компилятор не вставляет бэкдор - это работает, потому что вы фактически полностью удаляете компилятор.

Оттуда вы можете использовать свой компилятор с нуля для начальной загрузки, например, цепочки инструментов GNU. Затем вы можете использовать свой собственный набор инструментов для компиляции системы Linux From Scratch .

Обратите внимание, что для облегчения вашей работы у вас может быть второй промежуточный компилятор, написанный на C (или на любом другом языке). Таким образом, вы должны написать компилятор A в ассемблере, а затем переписать этот компилятор в C / C ++ / Python / Brainfuck / что угодно, чтобы получить компилятор B, который вы компилируете с использованием компилятора A. Затем вы будете использовать компилятор B для компиляции gcc и друзей.

strugee
источник
13
Тем не менее, это все еще только защищает от вредоносного компилятора. Вам все еще нужно доверять системе, в которой работает компилятор. Никакого программного обеспечения не существует изолированно.
CVN
3
Все автономное опасно по своей природе. Вы фактически предлагаете компилятор цепочки инструментов (хотя и странный), что означает, что он, вероятно, может быть изменен именно так, как вы пытаетесь избежать. Еще лучше, это может быть изменено в пути через MitM.
Струджи
1
Вы, ребята, должны понимать, что этот ответ исходит от 15-летнего. Продолжай в том же духе!
mtahmed
3
Не следует забывать также писать редактор кода с нуля - кто знает, компилирует ли ваш предварительно скомпилированный <code> vim </ code> или <code> vim </ code> ваш хороший компилятор из исходного кода, который вы проверяли только с использованием зараженных <code> vim </ code> заслуживает доверия?
Хаген фон Айцен
1
Никогда не забывайте, что если вы лично не написали этот первый машинный код (не сборку. Фактический машинный код), и вы не являетесь экспертом в распознавании скрытых дыр в безопасности, а также прочитали и проверили каждую отдельную строку кода, которую вы компилируете ... или хотя бы знаете человек, который сделал это лично , и доверяю ему сделать это ... ничто из этого не поможет вообще. Вот почему попытка Kickstarter это разрушает весь смысл. Что: высокая надежность.
Evi1M4chine
22

Один из возможных способов, хотя на практике это займет очень много времени, - вернуться к истокам. Разработка GNU началась в 1984 году, а оригинальная версия Minix (которая использовалась во время ранней разработки Linux для целей начальной загрузки) была выпущена в 1987 году.

Весь этот ответ основан на вашей предпосылке, что «[вы] или другие люди имеют возможность читать и понимать исходный код на наличие недостатков безопасности, поэтому исходный код будет проверен в первую очередь перед компиляцией», и что вы можете доверять результатам такого анализа , Без этого этот ответ, вероятно, хуже, чем бесполезный, так как вы будете тратить огромное количество времени на абсолютно никакой пользы.

Если вы можете найти копию оригинальной книги Minix с исходным кодом, вы можете ввести ее из книги. Скомпилируйте его, а затем используйте другой декомпилятор в другой системе, чтобы убедиться, что компилятор генерирует ожидаемый двоичный вывод машинного языка. (Код состоит всего из 12 000 строк, предположительно C, поэтому это занимает много времени, но все еще в пределах разумного, если вы серьезно относитесь к такому проекту.) Вы могли бы даже написать свой собственный дизассемблер; это не должно быть очень сложно.

Возьмите самые старые версии утилит GNU, которые вы можете получить (поскольку они, вероятно, имеют меньше кода и меньше зависимостей от внешних библиотек), просмотрите код, создайте его для Minix (хотя это может потребовать некоторой работы; абсолютно необходимо избегать внесения изменений в исходный код, потому что это сделает добавление патчей позже очень подверженным ошибкам) ​​и пройдет аналогичный цикл дизассемблирования-проверки для инструментов GNU. В этот момент вы доверяете ОС и инструментальной цепочке, поэтому вам нужно только просмотреть исходный код в наборе патчей (все, что не входит в набор патчей, уже доверено), но инструменты все равно будут очень примитивными и грубыми по сравнению с тем, что вы используете на сегодня. Например, не ожидайте, что будет работать что-то большее, чем самые базовые функции системных инструментов.Читать много XKCD.

В какой-то момент у вас будет система, которая может скомпилировать и загрузить раннюю версию ядра Linux, так же, как это было сделано в начале 1990-х годов, когда Linux начал завоевывать популярность среди хакеров. В этот момент я бы предложил перейти на Linux (перестроить системные библиотеки и набор инструментов для Linux, собрать ядро ​​Linux, загрузиться в Linux и, возможно, пересобрать ядро ​​Linux и набор инструментов GNU в Linux; последнее доказывает, что система теперь является саморегулируемой хостинг), но это во многом зависит от вас. Проверяйте исправления, исправляйте ядро, библиотеки и базовые инструменты GNU и перестраивайте, пока не доберетесь до современных версий.

Тогда у вас есть надежная базовая ОС и компилятор, который можно использовать для создания современного программного обеспечения. К тому времени вы можете, например, следовать указаниям Linux From Scratch, чтобы создать систему, способную выполнять полезные задачи.

Ни при каких условиях система «компилятор» не может быть подключена к сети каким-либо образом (в том числе в качестве виртуальной машины на сетевом хосте); вы рискуете проникнуть через любой сетевой компонент, включая ядро. Если вас беспокоит атака компилятора Томпсона , вам следует ожидать, что любой виртуальный хост также может быть взломан. Используйте sneakernet для получения исходного кода и двоичных файлов с физического хоста, на котором вы компилируете вещи. Ожидайте проблем с получением файлов в системе и из системы, по крайней мере, до того момента, когда вы достигнете точки, где была реализована поддержка USB-накопителей. Если вы действительно параноик, источник печати списки кодов и введите их вручную (и надеемся , что драйвер принтера и принтер не похожий код в них) или прочитайте код на одном мониторе компьютера и введите его на другом компьютере, физически рядом с ним, но не подключенным к нему.

Да, это займет много времени. Но преимущество этого подхода состоит в том, что каждый шаг является инкрементным, а это означает, что было бы намного труднее проскользнуть через что-либо злонамеренное, если оно не будет постепенно внедрено в течение периода многих версий; Это связано с тем, что набор изменений на каждом шаге сравнительно невелик, и поэтому его намного легче просматривать. Сравните набор исправлений с журналом изменений и убедитесь, что вы можете точно определить, какая запись журнала изменений соответствует каждому изменению в исходном коде. Опять же, это предполагает, что у вас есть возможность (возможно, через кого-то, кому вы доверяете), чтобы убедиться, что такие изменения не проникли в кодовую базу, но это должно приблизить вас к такой надежной системе, как только программное обеспечение, за исключением Прошивка подойти может.

CVn
источник
Метод disassemble-verify очень ошибочен, так как все еще делает огромное предположение, что машина верификации полностью заслуживает доверия. Если вы не построили эту машину и ее программное обеспечение с нуля, или не знаете человека, который делал это лично и доверял ей, этого не произойдет. Так что это все еще небезопасно. Сожалею. …… Кроме того, в этих вопросах «как можно ближе к…» по-прежнему означает «небезопасный», так как для разрушения всей точки зрения требуется только одно ненадежное место.
Evi1M4chine
9

Если вам нужен надежный компилятор, вы можете взглянуть на академическую работу, например, проект compcert . Это компилятор, созданный INRIA (французская публичная ИТ-лаборатория), предназначенный для «сертификации», то есть для создания исполняемого файла, семантически идеально эквивалентного коду (и, конечно, это было математически доказано).

lgeorget
источник
1
Всем нужен надежный компилятор. Как работает математика, что они могут создать «доверенный» компилятор?
Дэвид Дж
@DavidJ Начальная загрузка, скорее всего. Создайте какой-нибудь крошечный фрагмент, который вы можете полностью проверить и доказать, что он правильный, а затем использовать его как основу для создания более сложных компиляторов.
CVN
1
"" "Что отличает CompCert C от любого другого производственного компилятора, так это то, что он формально проверяется с помощью машинных математических доказательств, чтобы быть освобожденным от проблем неправильной компиляции ." "" Compcert.inria.fr/compcert-C.html Compilation не так эмпирически, как раньше.
lgeorget
1
@ MichaelKjörling, который, вероятно, не принимает во внимание, что ядро ​​может быть скомпрометировано для включения бэкдора в исходный код компилятора при чтении компилятором
ratchet freak
1
Я также нашел эту ссылку, которая может работать тоже.
Дэвид Дж.
2

Хотя ручное создание собственного компилятора в качестве отправной точки было бы наиболее безопасным, другой вариант заключается в установке системы с установочного компакт-диска 5 (или 10) лет, который, как вы полагаете, был создан до того, как существовали эти эксплойты. Затем используйте это как основу для компиляции нового проверенного источника.

sambler
источник
5
Атака была широко известна с 1984 года. Предположительно, Томпсон не был первым, кто задумался о такой возможности. Возвращение так далеко означает, что большинство вещей, которые мы считаем само собой разумеющимся сегодня, не было вокруг; рассмотрите, на что способны компьютеры 20 лет назад, и сравните это с их текущим состоянием. Даже оригинальная система начальной загрузки Linux Minix не была выпущена до 87 года , а разработка GNU началась в 84 году. Таким образом, хотя в теории это может дать ответ на вопрос, на практике это практически бесполезный ответ.
CVn
2
Самым ранним компьютером, который я мог бы получить, был 286. Мне нужно будет проверить, есть ли у моих бабушек и дедушек он до сих пор.
Дэвид Дж
1
Бонусные баллы за то, что на самом деле учел это @DavidJ
11684
@ MichaelKjörling: Не совсем; так как это только делает вашу цепочку начальной загрузки длиннее. Но, возможно, не так долго, как писать свой собственный компилятор с нуля на машинном языке.
Evi1M4chine