Содержание статьи
По данным Гугла, на сегодняшний день существует примерно 31 000 000 OpenSource-проектов, которые суммарно содержат около 2 000 000 000 строк кода. Естественно, что в таком количестве исходников — миллионы багов, описанные в тысячах багтрекеров. Но не все ошибки одинаково интересны — я расскажу о самых знаменитых.
Самый старый
Начну обзор с самых старых багов, которые не фиксились долгие годы: либо о них никто не знал, либо они никому не были интересны. Первый баг из этой категории почти отпраздновал свои 30 лет, когда его пофиксили. Скорее всего, этот жук закрался еще в 4.1BSD (а может, и еще раньше), откуда успешно перекочевал уже во все современные BSD-системы. Он проявил себя в новых релизах Samba — сервер падал при попытке доступа к каталогу. Имя героя, откопавшего древний баг еще в середине 2008 года, — Марк Балмер. Сначала Марк винил во всем новый релиз Samba, но потом нашел баг в OpenBSD’шной библиотеке libc (если быть точным, в файлах lib/libc/gen/{readdir.c,telldir.c}, отвечающих за доступ к каталогам). Ошибку нельзя было обнаружить с более ранними версиями Samba из-за специального костыля, который в новых релизах почему-то убрали. Оказалось, что баг затрагивал все современные BSD-системы, в том числе и Mac OS X.
Следующему багу, пожалуй, можно вручить чемпионский титул бага-долгожителя. Целых 33 года о нем никто не подозревал. За нахождение и ликвидацию ошибки можно сказать спасибо двум людям – Отто Мёрбеку и Николаю Штурму. Эта история произошла также в середине 2008. Отто Мёрбек работал над новой реализацией malloc в OpenBSD, а Николай Штурм тестировал код. В результате тестирования на платформе sparc64 было обнаружено, что иногда компиляция большого C++ проекта может заканчиваться с ошибкой Internal Compiler Error. Мёрбек начал искать причину этой проблемы и обнаружил переполнение буфера в генераторе синтаксических парсеров yacc(1): в файле skeleton.c, в функции yyparse(), происходило обращение к несуществующему элементу массива.
Для OpenBSD Отто выпустил шестистрочный патч, исправляющий данную проблему. Скорее всего (за давностью лет точно сказать уже сложно), баг берет свое начало примерно с UNIX V6 (который был выпущен в мае 1975) или UNIX V7.
Самый глупый
Первый претендент на эту номинацию — GRUB2, в версии 1.97 которого был обнаружен баг, позволяющий очень просто подобрать пароль на загрузчик. Смысл ошибки в том, что для ввода пароля необязательно знать весь пароль целиком — GRUB’у было достаточно хотя бы его части. Например, если пароль — xakep, то достаточно было ввести «xake», «xak», «xa» или даже просто «x». Таким образом, подобрать любой пароль можно было, просто подобрав первый символ. Баг был быстренько пофиксен в новой версии 1.97.1.
Следующий участник — Ping of Death в OpenBSD Packet Filter (CVE-2009-0687), был обнаружен 9 апреля 2009 года и исправлен спустя два дня. Как можно понять из названия, ошибка заключалась в возможности вызвать kernel panic с помощью специально сформированного пакета. Не то чтобы баг сам по себе очень глупый.
Просто тот факт, что OpenBSD можно вот так запросто положить одним пингом — это нонсенс и больше похоже на первоапрельскую шутку. Уязвимы были все версии OpenBSD с pf вплоть до 4.5, на всех архитектурах, а также NetBSD 5.0 RC3. Причем, никаких особых эксплоитов не нужно, достаточно сделать:
nmap -sO $target_IP
или
hping -0 -H 58 $target_IP
К слову сказать, это не первая уязвимость подобного рода в OpenBSD, просто на моей памяти самая широко распространенная. К примеру, в 2005 году из-за ошибки в драйвере беспроводного адаптера ral(4) при использовании IPsec ОС тоже паниковала, но уже от самого обычного пинга — достаточно было отправить 2 эхо-запроса. Прим. ред.: сам себя не похвалишь, никто не узнает — этот баг был обнаружен мной во время настройки домашнего Wi-Fi.
После исследования проблемы я отправил разработчикам детальное описание сценария, при котором возникает remote crash, конфиги pf.conf, isakmpd.conf и isakmpd.policy, а также traceback ядра, полученный с помощью отладчика ddb(4). Тео де Раадту и команде понадобилось три с половиной месяца, чтобы странить эту брешь. И, наконец, чемпион в номинации «Самый глупый» — глюк в прошивке первого Android-телефона HTC G1. Оказалось, что все нажатия клавиш переадресовывались в рутовую консоль.
То есть, например, набрал ты в SMS слово «reboot», а потом <Enter>, и очень удивился, что телефон послушался и ушел в ребут. А ведь можно и что пострашнее набрать! Но нет худа без добра — с помощью этой ошибки на G1 можно было легко поставить Debian. Эх, такой баг пофиксили! 🙂
Самый «железный»
Ни для кого не секрет, что баги в ПО могут выводить из строя железо. Хорошо, что встречаются такие ошибки очень редко, а широкое распространение получают еще реже. Самый скандальный (а вероятнее, просто раздутый) за последнее время баг такого типа — «Ubuntu убивает ноутбучные винты».
Винт в ноутбуке отличается от винта на десктопе тем, что во время работы от батареи он периодически останавливается (паркует головку). Часто при этом слышен характерный щелчок. Это реализовано ради экономии заряда батареи (еще один плюс — в остановленном состоянии винт способен выдержать большие перегрузки от встряхиваний и падений).
И Ubuntu все правильно делала — останавливала винт, когда он был не нужен. Вот только на некоторых моделях это происходило многократно — частично по вине прошивки самого винта. С большой долей вероятности на таких моделях наблюдалась бы частая парковка головок под любой ОС. Посмотреть, подвержен ли твой винт такому багу, можно следующим образом. Ставим пакет smartmontools:
$ sudo apt-get install smartmontools
Если твой винт — sda, то:
$ sudo smartctl -a /dev/sda | grep Load_Cycle
Последнее число в этой строке — это количество парковок головки. У меня это значение равно 13 137, что совсем не много. Ресурс обычного ноутбучного винта, гарантированный производителем, может доходить до 600 000. Теперь можно подождать несколько минут/ча сов и снова проверить это значение, чтобы примерно определить скорость, с которой оно растет.
По идее, быстро расти не должно, так как фикс был доступен еще для 8.04 (путем активации менее агрессивного режима сохранения энергии). Если баг все же присутствует, то можно попробовать отключить парковку головок с помощью APM (Advanced Power Management):
$ sudo hdparm -B 254 /dev/sda
Если и после этого проблема осталась (как вариант, попалась модель с нестандартными значениями APM или невозможностью управлять APM в принципе), то полезно почитать комментарии на страничке goo.gl/bTNhy, там предлагается несколько возможных решений.
И еще один довольно свежий баг, связанный с железом. Правда, к OpenSource он не имеет особого отношения. Разве что тот факт, что он также проявляется и на *nix-системах. Речь пойдет о закрытых драйверах от Nvidia. Весной 2010 года на официальном сайте появились новые версии драйверов — 196.75 и 195.36.
Спустя некоторое время пользователи начали сообщать о выходящих из строя видеокартах. Оказалось, что в новые драйвера закралась ошибка, которая иногда приводила к полному выключению или снижению до минимума скорости вращения кулера видеоадаптера, несмотря на сильный нагрев видеоядра. После обнаружения бага новые версии дров были спешно убраны с сайта, а всем пользователям было рекомендовано откатиться до старых версий.
Самый массовый
Выше я описывал баги, которые встречаются не у всех и не часто. Пришла пора рассмотреть более массовые экземпляры, с которыми сталкивался, пожалуй, любой пользователь *nix-систем. Первый баг уже пофиксен, но, думаю, многие его помнят: неработающие хоткеи Firefox в русской раскладке на *nix’ах (goo.gl/Hiagm). Был обнаружен в 2001 году, а исправлен только спустя семь лет, в Firefox 3 beta 2. На более старых версиях можно было решить проблему костылем в виде аддона Russian hot keys bugfix. Примечателен баг еще и тем, что он был исправлен в рамках программы «Деньги за исправление багов» от Mozilla Russia. Имя героя — Олег Крылов. Mozilla Russia готова платить за устранение багов, специфичных для российских пользователей.
Размер вознаграждения не очень большой — от $300 до $500, а все «лоты», на которых его можно заработать, указаны на страничке проекта: goo.gl/dhYxN. Подробнее про вознаграждения за отстрел багов в OpenSource-продуктах читай во врезке.
Следующий претендент тоже связан с хоткеями, но теперь проект уже посолиднее — X.Org, да и затрагивает этот баг всех пользователей, вне зависимости от раскладки. Описать его можно так: применение хоткея происходит при нажатии, а не при отпускании клавиш. Приведу пример: допустим, переключение раскладки клавиатуры в системе забиндено на <Alt+Shift>. Тогда вместе с прокручиванием назад списка открытых окон (Alt+Shift+Tab) будет переключаться раскладка.
В багтрекере X.Org баг висит с 2004 года: goo.gl/GaRqQ. Но вся проблема в том, что патч (дружно скажем за него спасибо Илье Муравьеву), устраняющий глюк, нарушает спецификацию XKB. А спецификации, как известно, нарушать нельзя :). Поэтому пока в апстрим патч не будет принят, по крайней мере, до внедрения XKB2 (а это счастливое событие откладывается уже несколько лет). Единственный известный мне дистрибутив, который уже включил этот патч — Ubuntu (с версии 11.04). Для более старых версий можно установить патченый X.Org из ppa. Ссылка на баг в убунтовском трекере: goo.gl/7E6uK. Следующий интересный и достаточно известный в узких кругах баг раньше был серьезным контраргументом против использования FreeBSD на десктопе.
Вызвать его было просто: втыкаем USB-флешку, монтируем, вытаскиваем флешку не отмонтировав — хоп, получаем Kernel Panic. Жила себе эта ошибка преспокойно с самой первой версии FreeBSD вплоть до восьмой, в которой поменяли весь USB-стек.
И, наверное, самый распространенный баг — кракозябры в нелатинских именах файлов при распаковке RAR и ZIP-архивов, созданных под Windows. В случае с RAR проблема, как правило, решается очень просто:
$ sudo apt-get remove rar
$ sudo apt-get install unrar
С ZIP все гораздо сложнее. На launchpad’е уже давно висит баг goo.gl/Y5YVj, собравший более сотни комментариев (правда, не все из них одинаково полезны) и около 1000 голосов (благодаря недавно прошедшему «флешмобу» баг поднялся на второе место в launchpad по количеству голосов), подтвердивших существование проблемы. Одно время эту ошибку номинировали в категорию HundredPaperCuts – это позволило было надеяться на то, что ее скоро исправят. Однако вскоре одумались (видимо, посчитав, что фикс слишком сложен). Рассмотрим, какие решения есть на данный момент.
1.Поставить AltLinux, там эта проблема решена.
2.Попытаться прикрутить решение из AltLinux в свой дистрибутив. К сожалению, не все так тривиально, как может показаться на первый взгляд. Кроме самого патча на zip/unzip, придется прикручивать еще специальную библиотеку libnatspec. Для Ubuntu есть ppa: goo.gl/AFSQq (здесь лежат патченные zip/unzip) и goo.gl/eGGAe (здесь — libnatspec).
3.Собрать последнюю бета-версию unzip: goo.gl/0Bd9Y. К сожалению, это решение работает только для некоторых архивов и не устраняет проблему полностью.
4. Перекодировать имена распакованных файлов с помощью convmv (который надо предварительно установить):
$ convmv -f cp866 -t utf8 -r --notest *
5.Поставить скрипт для Nautilus:
$ sudo apt-get install nautilus-fi lename-repairer
Самый неуловимый
Этот титул безоговорочно отходит #12309. 12309 — баг-легенда, летучий голландец. Им пугают начинающих линуксоидов, его используют как железный аргумент в холиварах Linux vs FreeBSD vs Windows. Проявляется он на абсолютно разном железе и на разных конфигурациях ядра и файловых систем. Сам баг звучит как «Large I/O operations result in poor interactive performance and high iowait times», и его обсуждение собрало более 550 комментариев: goo.gl/uMKEn.
Баг был описан в декабре 2008 года и на данный момент имеет приоритет P1 high. Проверить, восприимчива ли к нему твоя система, очень просто. Нужно всего лишь запустить:
$ dd if=/dev/zero of=/tmp/test bs=1M count=1M
и понаблюдать за отзывчивостью ОС, особенно графических приложений. Если при этом дико подскочет wa (а с ним и LA), и система станет неюзабельной чуть более, чем полностью, — бинго, ты поймал 12309.
На самом деле 12309 — это не один, а несколько багов, смешанных в кучу. Можно выделить следующие случаи появления:
- при копировании больших объемов данных с винта на винт (или с раздела на раздел одного винта);
- при нехватке ОЗУ (и, соответственно, диком своппинге);
- при копировании на USB-девайсы;
- при использовании зашифрованных разделов;
Соответственно, фиксы тоже будут разные:
1.Смена планировщика ввода-вывода на какой-нибудь не-cfq. Посмотреть текущий планировщик можно так:
$ cat /sys/block/sdX/queue/scheduler
где sdX — нужный девайс (обычно — sda). Используемый в данный момент планировщик будет указан в квадратных скобках. Можно сменить планировщик и посмотреть на результат:
# echo deadline > /sys/block/sdX/queue/scheduler
Чтобы выбранный планировщик устанавливался при загрузке, нужно передать ядру параметр elevator=deadline. В случае с grub необходимо изменить строку GRUB_CMDLINE_LINUX_DEFAULT в /etc/default/grub, а затем обновить конфигурацию:
$ sudo update-grub
2.Настроить ОС на менее агрессивное использование swap:
# echo 10 > /proc/sys/vm/swappiness
Теперь система начнет использовать swap только в том случае, если свободной ОЗУ останется меньше 10%. В Ubuntu, например, значение swappiness по умолчанию — 60. Чтобы значение не менялось после ребута, не забудь добавить его в /etc/sysctl.conf.
3.Добавить ОЗУ. Часто проблема возникает при активном использовании swap.
4.В некоторых случаях помогает смена ядра на что-нибудь старше 2.6.17 или новее 2.6.34.
К слову, я сам несколько раз видел 12309, но только на ядрах < 2.6.35. Иногда глюк проявляется только при копировании на USB-носитель.
Самый-самый
Самый важный баг зарегистрирован под гордым первым номером в багтрекере Ubuntu, bugs.launchpad.net, 20 августа 2004 и называется «Microsoft has a majority market share». Авторство принадлежит Марку Шаттлворту. Мой вольный перевод описания: «У Microsoft доминирующее положение на рынке десктопов. Ubuntu создана для того, чтобы пофиксить этот баг. Закрытое ПО сдерживает инновации в IT-отрасли, ограничивает доступ к IT для небольшого процента мирового населения и не позволяет разработчикам во всем мире в полной мере реализовывать свой потенциал. Этот баг очень широко распространен.
Способ воспроизведения бага: Посетить компьютерный магазин в своем районе.
Что мы там увидим:
- Большинство ПК продается с предустановленным закрытым ПО.
- Очень небольшая доля ПК продается с предустановленной Ubuntu и/или другим свободным ПО.
Что должны будем увидеть:
- Большинство новых компьютеров должны включать только свободное программное обеспечение — например Ubuntu.
- Ubuntu должна продвигаться таким образом, чтобы ее удивительные возможности и преимущества были очевидны и известны всем.
- С течением времени система должна становиться все более и более дружественной пользователю.»
Странно, что на момент написания статьи этот баг затрагивает всего 619 человек, однако имеет 1500 комментариев. Будем с нетерпением ждать фикса :).
Заключение
Да, в больших OpenSource проектах много багов. Но и в больших проектах с закрытыми исходниками их не меньше — просто не всегда они доступны широкой общественности. Большое преимущество OpenSource здесь в том, что при желании ты сам можешь провести аудит кода и поправить любой баг.
Links
- Подробности про баг с доступом к каталогу в BSD: goo.gl/qH316;
- Ping of Death в OpenBSD: goo.gl/uHoCj;
- Описание планировщиков вводавывода в Linux: goo.gl/LJ2B1.