Вплив програмних помилок на наше життя дедалі більший. Зависання домашнього комп’ютера дратує, але зовсім інша ціна помилки там, де програма керує ракетою, телефонною мережею чи медичним обладнанням. Саме тому мене зацікавила добірка History’s Worst Software Bugs Сімсона Гарфінкеля, опублікована у WIRED 2005 року.
Нижче — всі десять історій, які потрапили до мого допису 2007 року. Поряд із задокументованими аваріями в тій добірці була й непідтверджена історія. Розрізняти їх потрібно так само уважно, як перевіряти результати програми: переконливий переказ ще не робить твердження фактом.
Звідки взялося слово «баг»
Знаменитий метелик у Harvard Mark II справді існував, але його знайшли 1947 року, а не 1945-го. Комаха потрапила в один із компонентів машини; інженери вклеїли її до журналу. Сам журнал зберігає Смітсонівський інститут. Словом bug технічні несправності називали задовго до цього випадку: музей згадує його використання Томасом Едісоном у 1870-х роках. Отже, метелик став чудовою ілюстрацією терміна, а не початком історії всіх комп’ютерних помилок.
1. Mariner 1: пропущений знак у формулі, 1962 рік
Першу американську спробу відправити апарат до Венери здійснили 22 липня 1962 року. Носій Mariner 1 відхилився від курсу, і його довелося знищити з міркувань безпеки. За описом NASA, поєдналися несправність антени наведення Atlas і помилка в програмному забезпеченні керування.
У рівнянні пропустили риску над символом R: замість R̅ залишилося R. Це не був дефіс, як іноді пишуть. Програма неправильно відпрацювала ситуацію, яка виникла під час польоту. Приклад показує, чому перенесення математичної моделі в код потребує перевірки її змісту, а не лише того, чи запускається програма.
2. Сибірський трубопровід: історія, яку не можна подавати як доведений факт
У старому переліку був сюжет про нібито спричинений зміненим програмним забезпеченням вибух радянського трубопроводу 1982 року. Його подавали впевнено, аж до твердження про надзвичайний масштаб вибуху. Проте достатніх доказів такого причинного зв’язку немає.
У дослідженні Марка Трахтенберга та дискусії істориків H-Diplo|RJISSF розібрано походження цієї розповіді й проблеми її доказової бази. Спогади та перекази не дають надійно встановити обставини й роль програмного забезпечення. Тому цей пункт залишаю як приклад неперевіреної історії з популярного списку. Робити з нього доведену програмну катастрофу або приписувати конкретній установі відповідальність немає підстав.
3. Therac-25: програмний контроль без достатнього незалежного захисту, 1985–1987 роки
Медичний прискорювач Therac-25 міг працювати з електронним і рентгенівським випромінюванням. У ньому програмі передали більше функцій безпеки, ніж у попередніх моделях, і не продублювали всі апаратні блокування. Помилка керування в такій системі могла мати фізичні наслідки для пацієнта.
Розслідування Ненсі Левесон і Кларка Тернера описує шість відомих аварій від червня 1985-го до січня 1987 року, пов’язаних із великими передозуваннями, смертями та тяжкими травмами. Зводити їх до «недосвідченого програміста» неправильно: автори розглядають взаємодію програмного забезпечення, обладнання, аналізу безпеки та організації роботи. Для мене тут головне — необхідність захисту, який не залежить від того самого програмного припущення.
4. Черв’як Морріса: кілька слабких місць одночасно, 1988 рік
Увечері 2 листопада 1988 року мережею почала поширюватися програма, відома як черв’як Морріса. Вона вражала певні системи Unix, а повторне зараження збільшувало кількість процесів і виснажувало ресурси машин. Наслідки відчули тисячі комп’ютерів.
У технічному аналізі Юджина Спаффорда описано кілька шляхів проникнення, зокрема помилку обробки введення у fingerd, пов’язану з gets(), та можливості налагоджувального режиму sendmail. Отже, вся історія не зводиться до однієї функції або однієї вразливості. Називати цю програму першим черв’яком в історії також не слід. Цей випадок добре показує, як декілька слабких місць утворюють значно небезпечніший ланцюжок.
5. Kerberos V4: слабка випадковість, виправлена 1996 року
Для криптографічного захисту недостатньо великого простору можливих ключів: важливо, наскільки непередбачувано вони обираються. У Kerberos Version 4 генератор випадкових чисел виявився слабшим, ніж очікували розробники.
Повідомлення MIT від 28 лютого 1996 року стосується саме V4. У ньому розробник Джеффрі Шиллер пояснює, що сильніший генератор із Version 5 перенесли до центру розподілу ключів V4, перевірили й увели в роботу в MIT. Поширювати висновок на всі версії Kerberos або стверджувати, що будь-хто міг без зусиль увійти до будь-якої захищеної системи, було б перебільшенням. Версія й конкретна реалізація тут мають принципове значення.
6. Мережа AT&T: збій відновлення зв’язку, 1990 рік
15 січня 1990 року відмова компонента сигнальної системи SS7 та неправильна реакція програмної процедури спричинили масштабне порушення роботи мережі AT&T. Проблема торкнулася механізмів, які мали допомагати мережі переживати відмови.
Звіт Конгресу США з посиланням на FCC описує перебої різної інтенсивності протягом дев’яти годин. Із наведених у ньому 148 мільйонів спроб дзвінків завершилися 83 мільйони. Це значно точніше характеризує масштаб, ніж число «60 тисяч людей» у старому переказі. Перевіряти потрібно й аварійні сценарії: процедура відновлення сама може стати джерелом проблеми.
7. Intel Pentium FDIV: помилка ділення й довіра до результату, 1994 рік
Історія раннього Pentium пов’язана з неточними результатами окремих операцій ділення з рухомою комою. Йдеться про дефект процесора, а не про програму, яка завжди помилялася на однаковий відсоток. Проблема стала публічною 1994 року, тому прив’язувати весь інцидент до 1993-го некоректно.
У повідомленні Intel про результати 1994 року зазначено одноразові витрати 475 мільйонів доларів, пов’язані із заміною процесорів та іншими наслідками дефекту. У грудні компанія запропонувала заміну кожному власнику відповідної версії Pentium. Цей випадок нагадує: навіть рідкісний неправильний числовий результат потребує зрозумілого пояснення й способу виправлення для користувача.
8. «Пінг смерті»: небезпечна обробка некоректних пакетів, 1996 рік
Так назвали відмову в обслуговуванні, яку могли спричиняти завеликі ICMP-пакети в уразливих реалізаціях мережевого стека. Тут важлива не магічна сила команди ping, а перевірка довжини та коректності даних, зокрема під час збирання IP-фрагментів.
У RFC 6274 розглянуто цю проблему та перевірки меж розміру датаграми. Гранична довжина IPv4-датаграми — 65 535 байтів; фрагментація не дає права перевищувати її після збирання. Запис CVE-1999-0128 фіксує «Ping o’ Death» як відповідну вразливість. Твердження про можливість зруйнувати «практично будь-яку ОС» надто широке: результат залежав від реалізації та її виправлень.
9. Ariane 5: однакова помилка в основній і резервній системах, 1996 рік
Перший політ Ariane 5 4 червня 1996 року завершився втратою ракети. Комісія розслідування встановила: приблизно через 37 секунд після початку запуску головного двигуна, тобто близько 30 секунд після відриву, було втрачено коректну інформацію про орієнтацію.
Під час перетворення 64-бітного числа з рухомою комою на 16-бітне ціле зі знаком значення вийшло за допустимий діапазон. Це спричинило виняток і зупинку інерціальної системи. Резервна система з тим самим програмним забезпеченням відмовила з тієї самої причини. Йшлося про числове перетворення, а не переповнення буфера.
Частину програмних припущень успадкували від Ariane 4, а траєкторія Ariane 5 виходила за їхні межі. Випробування не перевірили цю комбінацію умов. Отже, дублювання обладнання саме по собі не усуває спільної помилки проєктування; повторне використання коду потребує перевірки нових умов роботи.
10. Панама: спосіб введення даних і незалежна перевірка, 2000–2001 роки
В онкологічному інституті Панами помилки планування променевої терапії призвели до переопромінення 28 пацієнтів. Експерти МАГАТЕ дослідили, як до програми Multidata вводили контури захисних блоків. Обмеження одного з режимів до чотирьох блоків намагалися обійти, задаючи кілька блоків як складний спільний контур. Різний порядок обходу його меж давав різні розрахунки часу опромінення, хоча програма приймала введені дані.
FDA виділило три чинники: брак перевірки планів, спосіб введення даних про блоки та їх інтерпретацію програмою. Відомості не вказували на несправність самого апарата телетерапії як причину інцидентів. Наслідки включали смерті й тяжкі ускладнення, але число всіх померлих пацієнтів не можна автоматично ототожнювати з кількістю смертей, спричинених переопроміненням. Для інженерного висновку тут достатньо встановленого: прийняття даних програмою не підтверджує правильності її розрахунку, а повторний перегляд тих самих результатів не замінює незалежної перевірки.
Що я виніс із цих історій
Комп’ютер виконує закладені в нього правила, але правила створюють люди. Тому довіра має спиратися на перевірку: чи правильні початкові дані, чи враховано межі чисел і режимів, чи перевірено поведінку після відмови та чи відповідають випробування реальним умовам.
Особливо насторожує ситуація, коли кілька перевірок залежать від одного й того самого коду або неперевіреного припущення. Історії Therac-25, Ariane 5 та Панами показують різні варіанти цієї проблеми. А непідтверджений сюжет про трубопровід додає ще один урок: перевіряти потрібно не лише програми, а й історії про їхні помилки.