LINUX.ORG.RU

Выявлена дыра, позволяющая «уронить» компьютер с Linux под любым пользователем

 ,


0

2

В списке рассылки разработчиков ядра Linux (LKML) был обнародован код, позволяющий через вызов функции ядра socketpair() создать процесс, съедающий 100% процессорного времени и все файловые дескрипторы. Процесс, будучи запущенным от имени любого пользователя, может привести систему к состоянию полной неработоспособности.

Пробный патч, который, тем не менее, не устраняет проблему, опубликован здесь.

>>> Подробности

★★★★★

Проверено: post-factum ()
Последнее исправление: post-factum (всего исправлений: 2)

Ответ на: комментарий от anonymous

Сколько раз копируются данные при работе TCP.

sv75 ★★★★★
()
Ответ на: комментарий от anonymous

> А что грустного?

Что ты нахватался умных слоа, но не понимаешь элементарных вещей.

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

>Все верно, разницы нет, пока то, что блокирует программа, управляется ядром. То есть пока речь идет о взаимодействии ядра и программы. Разницы нет для монолитного ядра. Но для микроядра взаимодействие происходит не только между программами и ядром, но еще и между программами и программами. То есть одна программа должна будет блокировать ресурсы другой программы (да хоть те же сегменты shared memory). В этом проблема - во взаимодействии, оно значительно усложняется.

Вообще-то, уже сейчас есть DragonFly BSD, в которой почти нет необходимости в явной блокировке ресурсов. Это, конечно, не система с микроядром, это система с гибридным ядром, но она значительно отличается от сложившихся архитектурных традиций к построению многозадачных операционных систем.

В ней есть потоки ядра, количество которых равняется количеству процессорных ядер системы. Каждому потоку ядра монопольно принадлежат определённые ресурсы и определённые процессы. Процессы могут обращаться непосредственно только к тем ресурсам, которые принадлежат тому же потоку ядра. Чтобы обратиться к чужому ресурсу, процесс просит свой поток ядра перевести себя на другой поток ядра.

Чтобы процесс не был прерван планировщиком задач потока ядра во время выполнения какой-то транзакции с ресурсом, существует возможность указать потоку ядра, что сейчас процесс войдёт в критическую секцию и его нельзя прерывать, а вот сейчас он вышел из критической секции и поток ядра может его прервать и запустить другой процесс.

Таким образом все блокировки в системе сводятся к обозначению принадлежности ресурсов к ядрам и к критическим секциям.

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

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

Пока что мы делаем все наоборот. :) Мы медленно превращаем микроядро в монолитное. Сначала мы переносим в ядро менеджер блокировок и управление памятью. Позже у нас там появится paging. И мы уже упоминали, что драйвера будут работать через shared memory. Следом мы перенесем в ядро файловый кеш, как часть менеджера памяти. Потом там же окажется работа с дескрипторами, иначе нельзя будет прозрачно реализовать работу с файлами и сокетами. Последними туда переползут драйвера и файловые системы, чтобы обеспечить нужную производительность, все равно они итак работали через огромные куски shared memory. И мы получим Линукс. :)


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

А причем тут Xen? Он выполняет другие функции. В частности он не дает двум гостям использовать общий аппаратный ресурс.


А Xen тут при том, что ядро системы только и должно заниматься разграничением аппартных ресурсов.

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

В линуксе я могу запусить две копии glxgears, и они обе будут рендериться на видеокарте. А в xen-е два гостя могут использовать аппаратные возможности рендеринга одной видеокарты?


А почему-бы и нет? Только прошу учитывать, что Xen - это не операционная система, а пример работающего микроядра. Микроядро является только частью операционной системы.

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

morbo
()
Ответ на: комментарий от anonymous

>Не так. Эту ситуацию нужно обрабатывать ДОПОЛНИТЕЛЬНО к тем ситуациям ошибки чтения и др. Если программа этого не делает... А многие не делают.

Я вообще понимаю, что «старая программа», о которой идёт речь, работает через слой эмуляции POSIX. Слой эмуляции POSIX может преобразовывать ошибку «недействительный идентификатор» в «ошибку чтения», тогда программа будет работать так, как и было расчитано программистом. Если же программа изначально пишется нативно, без использования слоя POSIX, то почему бы программисту и не предусмотреть ситуацию «недействительный идентификатор»?

Не может. Тогда не будет работать вызов select. Дескриптор должны быть натуральным числом, и чем меньше - тем лучше.


Они и останутся натуральными числами. А почему они должны быть маленькими?

Замечу, что select - это ядерный вызов.


А будет библиотечная функция слоя эмуляции POSIX. А «под капотом» это будет сообщение, отправляемое процессом стека TCP/IP процессу-клиенту.

morbo
()
Ответ на: комментарий от morbo

>но она значительно отличается от сложившихся архитектурных традиций к построению многозадачных операционных систем.

Описался:

но она значительно отличается от сложившихся архитектурных традиций к построению _многопроцессорных_ операционных систем.

morbo
()
Ответ на: комментарий от morbo

>> В этом проблема - во взаимодействии, оно значительно усложняется.

Вообще-то, уже сейчас есть DragonFly BSD, в которой почти нет необходимости в явной блокировке ресурсов.

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

это система с гибридным ядром

Оно такое же гибридное, как ядро линукса. Вообще «гибридность» ядра - это маркетинг, выдумка. Есть критерий разделяющий монолитные и микроядра, а критерия, отделяющего гибридное ядро от монолитного и микроядра, нет.

В ней есть потоки ядра, количество которых равняется количеству процессорных ядер системы.

Да, в линуксе тоже есть потоки ядра. В dragonfly просто такой специфический шедулинг.

Каждому потоку ядра монопольно принадлежат определённые ресурсы и определённые процессы.

Да? То есть работа с дисковыми ресурсами, например, может быть только в одном потоке? А работа с сетью в другом? А если программа работает и с сетью и с дисками, то она должна прыгать между потоками? Еще остались те, кто думают, что такой метод проще? ;)

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

Вообще исследования в области ОС - довольно популярная тема для различных докторских работ. Работы по той же миникс, или, например, reiserfs - как раз из таких исследований. Может, все наоборот? Может именно исследования показывают, что альтернативы являются сложнее и при этом медленнее?

С нетерпением жду ядерного модуля для просмотра видео.

Уже есть. nvidia+libvdpau

А то, при просмотре видео же издержки ого-го какие ... что уж говорить про переключения контекста при многопоточном декодировании аудио- и видеопотоков.

Нет там издержек. 25 переключений контекста в секунду, чтобы отправить очередной готовый кадр - это мелочь. А аудио может вообще реже, чем раз в секунду отправляться.

Для примера, на гигабитном ethernet нужно получать до 60000 пакетов в секунду. Даже перемещение мыши по экрану вызывает в 10 раз больше переключений контекста, чем видеоплеер - в этом легко убедиться, посмотрев vmstat.

А Xen тут при том, что ядро системы только и должно заниматься разграничением аппартных ресурсов.

Верно. Только не разграничением, а управлением доступом. Любая программа должна иметь возможность обратиться к любому ресурсу. Без этой задачи ядром можно назвать что попало, например, BIOS или GRUB. Именно эту задачу Xen НЕ решает. И именно в этой задаче, в вопросе взаимодействия - сложность качественной реализации ядра, особенно микроядра.

anonymous
()
Ответ на: комментарий от morbo

>> Не может. Тогда не будет работать вызов select. Дескриптор должны быть натуральным числом, и чем меньше - тем лучше.

А почему они должны быть маленькими?

Для этого надо объяснять, как работает select, а мне - лень. :-) Предлагаю посмотреть его реализацию.

Замечу, что select - это ядерный вызов.

А будет библиотечная функция слоя эмуляции POSIX.

Ну... Это уже никуда не годится. Каким образом библиотечная функция будет перехватывать ядерные вызовы? Попытаюсь объяснить на пальцах. Есть такой архиватор RAR, он распространяется в виде статически слинкованного 32-битного бинарника. И даже собранный лет пять назад он работает в современных 64-битных (!) ядрах. Все потому, что он использует стандартизированные вызовы. Как теперь наличие слоя эмуляции поможет мне запустить этот RAR в нашей гипотетической системе с микроядром? Как я заставлю его вызывать методы библиотеки, а не ядра?

Проблема, на самом деле, глубже. Например, gcc генерирует точно такие же бинарники, которые точно так же будут делать ядерные вызовы... Или мы под наше микроядро напишем свой компилятор и glibc, которые будут заменять ядерные вызовы на наши сообщения? Микроядро - это просто... ;-)

anonymous
()

ubuntu 10.10 в кернел паник не впал, но проц загрузил ) Красиво )

xSudo ★★★
()
Ответ на: комментарий от anonymous

>> Ты не понял. ... Т.е. драйвер падает, пакеты перестают доходить, драйвер перезапускается, делается повторная передача пакетов, и приложение видит всего лишь паузу.

Как новый перезапущенный драйвер узнает, куда посылать пакеты, отправленные по сокету с socketid 174? Все открытые дескрипторы перестанут работать. То есть придется перезапускать все приложения, которые открывали сокеты. Это и есть ребут.

Вы оба не вполне правы. Да, все файловые дескрипторы станут невалидными, но это не ребут. Это, например, EBADF в ошибках POSIX и программы открывающие сокет вполне могут реконнектиться (и, пожалуй, должны так делать) получив такую ошибку. Разработчики программ ведь всегда проверяют возвращаемые коды ошибок, не так ли? :)

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

rudchenkos
()
Ответ на: комментарий от anonymous

Ну да, большую часть программистов и тестеров можно будет освободить от их работы, что-бы они создавали что-то новое и полезное, а не подпорки и костыли. А вот системные архитекторы и опытные старые программисты ничего не потеряют, они как правило имеют сильное влияние на всю команду.

lucentcode ★★★★★
()

>Пробный патч, который, тем не менее, не устраняет проблему, опубликован здесь.

Это как сапожник без сапог? Или как баян, который не рубит нифига, хотя должен? Или я что-то не понял в этой жизни?

rinsvid ★★
()
Ответ на: комментарий от rudchenkos

О, тут что-то шевелится? 0_о

Да, все файловые дескрипторы станут невалидными, но это не ребут. Это, например, EBADF в ошибках POSIX

Да, никто не спорит, можно даже ввести отдельный новый вид ошибки, но это не меняет проблемы.

Разработчики программ ведь всегда проверяют возвращаемые коды ошибок, не так ли? :)

А проблема как раз в том, что дескриптор, который БЫЛ валидным на предыдущей итерации цикла вдруг стал невалидным на следующей. Многие ли распространенные программы учитывают и проверяют сейчас ТАКУЮ ошибку? Или программу таки придется перезапустить для «обработки» ошибки?

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

Все существующие программы под микроядерную архитектуру надо переписывать, и никакая POSIX-прослойка не поможет? Так об этом и речь, не решая никаких проблем микроядерная архитектура только добавляет работы и увеличивает сложность. В микроядерной системе вдруг появляются и требуют специальной обработки ошибки, которых раньше просто не могло быть.

anonymous
()
Ответ на: комментарий от tailgunner

>> Да, все файловые дескрипторы станут невалидными

Не станут.

Потому что они будут обрабатываться основным ядром системы? ;)

anonymous
()
Ответ на: комментарий от anonymous

Да, все файловые дескрипторы станут невалидными

Не станут.

Потому что они будут обрабатываться основным ядром системы? ;)

Нет, конечно.

В качестве новогоднего подарка вот тебе ответ (я сейчас в настроении объяснять очевидные вещи :))

Итак, сервер сети и драйвер карты - это разные процессы; в сервере сети есть:

struct socket {
 unsigned open:1; /* этот сокет открыт */
 /* тут куча полей */
 pid_t driver; /* это PID процесса-драйвера сетевой карты */
};

и

struct socket sockets[MAX_NR_SOCKETS];

Клиенты в качестве файловых дескрипторов получают _индексы_ в массиве sockets. Теперь предполагаем, что процесс-драйвер рухнул и был перезапущен. Это значит, что сетевой сервер должен будет... правильно, поменять значение поля driver. Как нетрудно понять, все индексы в массиве останутся неизменными => у клиентов сервера сети все дескрипторы сокетов останутся валидными.

Если тебе и это объяснение непонятно, то просто найди себе другую работу :D

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> В качестве новогоднего подарка вот тебе ответ (я сейчас в настроении объяснять очевидные вещи :))

Замечательно. :) Тогда и я последую этому примеру. :)

Итак, сервер сети и драйвер карты - это разные процессы

Это, вероятно, объяснит, как дескрипторы выживут после того, как упал драйвер карты. Но сабжевый баг ведь был не в драйвере карты, а как раз в этом самом «сервере сети». А значит в случае сабжа и падения этого сервера станут невалидными и все дескрипторы.

Клиенты в качестве файловых дескрипторов получают _индексы_ в массиве sockets.

Так просто оно работать не будет. Идея, в целом, правильная, если бы на каждый процесс был свой «сервер сети», как это сделано в монолитном ядре. Но в нашем микроядре «сервер» - общий для всех, а значит в нем должен быть индивидуальный массив sockets для каждого процесса. Ведь дескриптор 1 есть у всех процессов, и у всех он - разный. Так что в целом получится что-то вроде map-а массива сокетов.

Но и это еще не все. Например, отдельным, очень интересным костылем надо будет обрабатывать fork(). Придется сделать этот «сервер сети» fork-aware, и ядро должно будет посылать ему какой-то специальный сигнал каждый раз, когда создается новый процесс, чтобы «сервер сети» мог продублировать для него нужные сокеты. И сигнал этот должен быть синхронным, чтобы не оказалось, что процесс создастся раньше, чем занятый «сервер сети» приготовит для него сокеты...

На этом интересные места только начинаются. Например, кому ядро будет посылать сигнал о создании процесса, когда будет запускать сам процесс «сервера сети»? Каким должен быть костыль на случай, если «сервер сети» упал, не вернув ответ на сигнал о создании процесса, ведь ядро не должно упасть следом?

Такие вот неожиданные проблемы вылезают в микроядре на каждом шагу.

anonymous
()
Ответ на: комментарий от anonymous

> Но сабжевый баг ведь был не в драйвере карты, а как раз в этом самом «сервере сети»

Речь идет не о сабжевом баге, а о баге в драйвере сетевой карты.

Такие вот неожиданные проблемы вылезают в микроядре на каждом шагу.

Ребенок открывает для себя мир. Еще немного, и он откроет для себя, что все эти «проблемы» были решены еще до его рождения.

tailgunner ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.