Як скласти компілятор C з нуля, потім компілювати Unix / Linux з нуля


64

Скажімо, я працюю у великій організації з обслуговування за межами США та Великобританії. Ми широко використовуємо сервери UNIX та Linux.

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

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

Питання

Який правильний (і безпечний спосіб) піти на компіляцію компілятора з вихідного коду (начебто сценарій курячого яйця), а потім компілювати надійний дистрибутив Unix / Linux з нуля?

Ви можете припустити, що я або інші мають змогу читати та розуміти вихідний код на предмет недоліків безпеки, тому вихідний код буде спочатку перевірений перед його компілюванням. Що я дійсно шукаю, - це робочий посібник для безпечного виготовлення цього компілятора, який може бути використаний для компіляції ядра, інших частин ОС та додатків.

Стек безпеки повинен починатися на базовому рівні, якщо ми маємо довіру до операційної системи або додатків, що працюють на цьому стеку. Так, я розумію, що може бути апаратне забезпечення на задньому плані, яке може вставити якийсь мікрокод у компілятор під час його створення. Наразі ми з цим не можемо зробити, за винятком випадків, крім того, можемо використовувати чіпи, не розроблені в США. Давайте почнемо сортувати цей шар для початку та припустимо, що я міг би створити його на старому комп’ютері потенційно до того, як було вставлено будь-яке заднє місце.

Як каже Брюс Шнейер: "Інженерам я це кажу: ми побудували Інтернет, і дехто з нас допоміг його підривати. Тепер ті з нас, хто любить свободу, мають це виправити".

Додаткові посилання:


7
Чорт, це дуже цікаве питання, і я не хочу його мігрувати, але я не думаю, що це тут на тему. Це краще підходить до stackoverflow.com, оскільки ваш основний питання полягає в тому, як скласти компілятор з нуля, що в значній мірі є агностиком ОС і дуже питанням програмування. Якщо ви не отримаєте відповідь через деякий час, подумайте про використання посилання "прапор" під тегами свого запитання та попросіть модератора перенести це на ТАК.
terdon

2
@terdon Це може насправді краще підходити для Programmers.SE, оскільки мова йде більше про загальні проблеми програмування, ніж про конкретну проблему розробки. Насправді це може бути дублікат .
CVn

2
GCC є відкритим кодом, як би вставити будь-який backdoor?
Михайло Паньков

2
Майте на увазі, що для стабільного експлуатації Томпсона потрібен код, який можна розпізнати під час компіляції програми входу або компілятора. Якщо ви можете вручну перетворити джерело у форму, не розпізнавану компілятором як одну з цих програм, backdoor не буде розповсюджуватися.
Рассел Борогов

2
@Constantius - прочитайте статтю Томпсона, пов’язану в першому рядку. Хто складає компілятор?
Рассел Борогов

Відповіді:


30

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

Звідти ви можете використовувати ваш компілятор з нуля для завантаження, наприклад, ланцюжок інструментів GNU. Тоді ви можете використовувати вашу власну ланцюжок інструментів для складання системи Linux From Scratch .

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


13
Незважаючи на це, це все ще захищає лише від шкідливого компілятора. Ще потрібно довіряти системі, на якій виконується компілятор. Жодне програмне забезпечення не існує ізольовано.
CVn

3
Все, що є автономним, за своєю суттю небезпечно. Ви ефективно пропонуєте компілятор ланцюгів інструментів (хоч і дивний), що означає, що він, можливо, може бути змінений точно так, як ви намагаєтеся уникати. Ще краще, що це може бути змінено під час транзиту через MitM.
strugee

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 для створення системи, здатної виконувати корисні завдання.

Ні в якому разі система "компілятора" ніколи не може бути підключена до мережі будь-яким способом (у тому числі як VM на мережевому хості); ви ризикуєте проникнути через будь-який мережевий компонент, включаючи ядро. Якщо ви переживаєте за атаку компілятора Томпсона , вам доведеться сподіватися, що будь-який хостинг VM також може бути порушений. Використовуйте sneakernet, щоб отримати вихідний код і двійкові файли від фізичного хоста, на якому ви збираєте речі. Очікуйте проблем із ввімкненням та вимкненням файлів принаймні перед тим, як дістатися до точки, де реалізована підтримка масового зберігання USB. Якщо ви справді параноїк, надрукуйте списки вихідного коду та введіть їх вручну (і сподівайтеся, що драйвер принтера та принтер не мають у них подібного коду) або прочитати код на одному моніторі комп'ютера та ввести його на інший комп'ютер фізично поруч із ним, але не підключений до нього.

Так, це займе багато часу. Але перевага такого підходу полягає в тому, що кожен крок є поступовим, це означає, що будь-яке шкідливе значення буде набагато складніше, якщо це не буде поступово впроваджено протягом багатьох версій; це тому, що набір змін на кожному кроці порівняно невеликий і, таким чином, набагато простіше переглядати. Порівняйте набір патчів із журналом змін і переконайтеся, що ви можете точно визначити, який запис журналу змін відповідає кожній зміні вихідного коду. Знову ж таки, це передбачає, що у вас є можливість (можливо, через когось, кому ви довіряєте) переконатися, що такі зміни не проникли в кодову базу даних, але це повинно наблизити вас до настільки ж надійної системи, як лише програмне забезпечення, за винятком, підхід прошивки може.


Метод демонтажу-перевірки дуже хибний, оскільки він все ще робить величезне припущення, що машина перевірки є повністю надійною. Якщо ви не побудували цю машину та її програмне забезпечення з нуля, чи не знаєте людину, яка зробила її особисто та довіряєте їй, цього не відбудеться. Тож це все ще небезпечно. Вибачте. …… Також у цих питаннях “якнайближче до…” все ще означає “незахищеність”, оскільки потрібно лише одне ненадійне місце, щоб зруйнувати всю точку.
Evi1M4chine

9

Якщо вам потрібен довірений компілятор, ви можете ознайомитись з академічною роботою, як проект compcert . Це компілятор, створений INRIA (французька громадська лабораторія ІТ), розроблений для "сертифікації", тобто для створення виконуваного семантично ідеально еквівалентного коду (і, звичайно, це було математично доведено).


1
Кожному потрібен надійний компілятор. Як працює математика, щоб вони могли створити "довірений" компілятор?
David J

@DavidJ завантаження, швидше за все. Створіть якийсь крихітний фрагмент, який ви зможете повністю перевірити і довести правильність, а потім використовуйте його як фундамент для створення більш складних компіляторів.
CVn

1
"" "Що відрізняє CompCert C від будь-якого іншого компілятора виробництва, це те, що він формально перевірений, використовуючи машинні математичні докази, звільняється від проблем, пов’язаних з компіляцією." "" Compcert.inria.fr/compcert-C.html Компіляція не так емпірично, як раніше.
lgeorget

1
@ MichaelKjörling, що, ймовірно, не враховує, що ядро ​​може бути поставлено під загрозу, щоб включити backdoor у джерело компілятора, коли його читає компілятор
ratchet freak

1
Я також знайшов це посилання, яке теж могло працювати.
David J

2

Хоча вручну створення власного компілятора як відправної точки було б найбезпечнішим, інший варіант - встановити систему з 5-ти (або 10-річного) компакт-диска для встановлення, який ви довіряєте, був створений до існування цих подвигів. Потім використовуйте це як основу для складання нового перевіреного джерела.


5
Напад був загальновідомий з 1984 року. Імовірно, Томпсон не вперше задумався про таку можливість. Повернутися назад так далеко означає, що більшості речей, які ми сьогодні сприймаємо як належне, не було навколо; Подумайте, на що здатні робити комп’ютери 20 років тому, і порівняйте їх із сучасним станом. Навіть оригінальна завантажувальна система Linux Minix була випущена до 87 року , а розвиток GNU почався у 84 році. Тож, хоча теоретично це може дати відповідь на питання, на практиці це багато в чому марно як відповідь.
CVn

2
Найдавніший комп’ютер, на який я міг би отримати руки, був би 286. Я повинен побачити, чи є у моїх бабусь і дідусів.
David J

1
Бонусні бали за те, що насправді вважають :-). @DavidJ
11684

@ MichaelKjörling: Не дуже; оскільки це лише збільшує вашу ланцюг завантаження. Але, можливо, не до того, як писати власний компілятор з нуля машинною мовою.
Evi1M4chine
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.