В списке рассылки Full Disclosure опубликован (http://seclists.org/fulldisclosure/2011/Aug/2) разбор достаточно интересной уязвимости в OpenSSH, найденной в реализации алгоритма аутентификации через вызов модулей GSSAPI. Сама по себе уязвимости малопригодна для осуществления атаки, так как может быть использована для осуществления DoS-атаки (исчерпание доступной процессу памяти) на стадии после совершения аутентификации, т.е. эксплуатировать проблему можно только имея работающий аккаунт в системе. Тем не менее интерес вызывает то, что несмотря на то, что проблема проявляется в большинстве современных Linux-дистрибутивов, которые используют метод аутентификации "gssapi-with-mic", ошибка была найдена еще в 2008 году и обнародована только сейчас.
По словам (http://blog.pi3.com.pl/?p=159) нашедшего ошибку исследователя, проблема была так долго не обнародована так как было предположение, что ошибку можно использовать на стадии до совершения аутентификации, т.е. оставалась надежда н...URL: http://seclists.org/fulldisclosure/2011/Aug/2
Новость: http://www.opennet.me/opennews/art.shtml?num=31368
А разве нельзя установить квоты на максимальный размер выделяемой памяти для sshd?
если ограничивать на каждый процесс, то их можно ещё кучу наплодить
если по сумме, то легальные пользователи не смогут заходить, т.ч. также получаем dos
Вообще-то достаточно ограничить пользователя и всё. Если уязвимость требует наличия аккаунта, значит sshd уже сделал setuid и работает из-под пользователя - итого никакой опасности и в логах сразу будет видно кто шалит.
Большими malloc'ами нельзя исчерпать свободную память в системе, потому что при malloc'е физические страницы не выделяются - делается банальный анонимный mmap. Либо переводчик лажанул и там было что-нибудь про заполнение этой памяти, либо это уязвимость - чушь на постном масле, либо работает только на редких системах с ущербной виртуальной памятью.
> Большими malloc'ами нельзя исчерпать свободную память в системе, потому что при malloc'е
> физические страницы не выделяются - делается банальный анонимный mmap.Вы бы вначале на код посмотрели, прежде чем критиковать. OpenSSH сразу забивает содержимое буфера перед использованием, что и приводит к физическому выделению страниц:
name->value = xmalloc(name->length+1);
memcpy(name->value, tok+offset, name->length);
рискую быть неправым, но разве в современных менеджерах не copy-on-write схема? Где копирование физически происходит только при изменении исходных данных? Память она такая - сейчас самая дорогая операция, глупо писать бит при пенальти в 50-200 тактов.
> рискую быть неправым, но разве в современных менеджерах не copy-on-write схема?При чём тут cow? Если вы думаете что процессор через libastral определяет что содержимое страниц идентично и шарит страницы вместо копирования, то это бред.
Ни процессор, ни процесс тут совершенно не причем. Это забота MM. Он как раз всё про всех знает. Причем, он еще и тем самым астралом планирует выделения/освобождения на основе своей статистики.
> Ни процессор, ни процесс тут совершенно не причем. Это забота MM. Он как раз всё про всех знает. Причем, он еще и тем самым астралом планирует выделения/освобождения на основе своей статистикиЛол.
понятно, работа менеджера памяти ядра недоступна до понимания...
Вполне доступна, если захотите разберётесь. Начните с осознания того, что менеджер памяти приложений работает в userspace, а не в ядре.
вот это точно лол :)))
А что лол-то? Это чистая правда.
угу. как и я к примеру пишу файлы на винт(!!!) из юзер-спейсной проги.
это магия! :D
Начали нормально с "рискую быть неправым", а закончили пятой точкой глубоко в луже... аллокатор ничего не знает про страницы и cow, а у ядра память запрашивает через банальный mmap, что уже в этом треде, между прочим, было сказано. cow же работает при форках, например, и в свою очередь не имеет ни малейшего понятия что память используется каким-то там аллокатором.А вот вас с понятием на уровне "Он как раз всё про всех знает" серьёзно воспринимать невозможно :)
Нет. Аллокатор всегда выделяет страницы сразу.Функция malloc() возвращает либо указатель на область ОЗУ, либо NULL, если выделение ОЗУ по каким-либо причинам не удалось. Если выделять ОЗУ фиктивно, тогда от момента вызова malloc() до момента записи в выделенную область ОЗУ вполне может выполниться несколько malloc()'ов других процессов (напоминаю: UNIX -- система многозадачная), и когда фиктивное выделение придётся сделать физическим, ОЗУ может просто закончиться.
Что тогда? SIGKILL "Out of swap space"? Это неправильно. Противоречит семантике работы malloc(). Если ОЗУ нет -- возвратите NULL и не полируйте моск. Если возвратили указатель -- отдайте моё ОЗУ мне.
>Если ОЗУ нет - возвратите NULL и не полируйте моск. Если возвратили указатель - отдайте моё ОЗУ мне.echo "vm.overcommit_memory = 2" >> /etc/sysctl.conf
===
{3} user@host:~ $ sysctl -a | grep overcommit_memory | wc -l
0
===sysctl сами придумали?-)
sudo sysctl -a | grep overcommit_memory | wc -l
1
Тщательный анализ grep'ом по исходникам ядра показал, что слово 'overcommit' встречается в vm/swap_pager.c, но отвечает только за возможность выделения ФИЗИЧЕСКОГО ОЗУ для процесса в количестве, большем, чем есть СВОБОДНОГО СВОПА.
Такая ситуация возможна, если в системе размер ОЗУ больше размера свопа, но для FreeBSD такие настройки нехарактерны -- Handbook рекомендует иметь свопа больше, чем физического ОЗУ.
Впрочем, доки на Солярис говорят, что лучше наоборот, но там и sysctl такого нет. :)
> Нет. Аллокатор всегда выделяет страницы сразу.Вы уже не раз показали себя ламером, может пора научиться хотя-бы проверять, прежде чем говорить о том, о чём понятия не имеете? Сделайте программу, malloc(); system("ps"); memset(); system("ps"); и посмотрите что будет с VM и RSS.
> Что тогда? SIGKILL "Out of swap space"?
Именно, и это правильно.
> Противоречит семантике работы malloc()
OOM killer не имеет никакого отношения к семантике работы malloc, и избежать его всё равно нельзя из-за фундаментальных принципов работы системы виртуальной памяти. Кроме того, выделение физических страниц на аллокации - это кошмарное падение производительности, рост потребления памяти, невозможность выделить фрагмент больше размера физической памяти.
Почему нельзя избежать OOM - показываю на примере: процесс выделил много памяти, допустим даже честно выделил физические страницы, далее он форкается. Либо вы честно копируете всё адресное пространство (а с такой системой вы никому не нужны), либо одна из копий будет убита при записи в память, когда при cow кончатся физические страницы.
Другой пример - процесс выделил память-ok, был вытеснен в swap и весь его занял. Другой процесс выделил память-ok, и занял всё физическую. Когда проснётся первый процесс и полезет из swap'а, он будет прибит безо всяких malloc по причине исчерпания физических страниц.Итого - на деле malloc вернёт 0 скорее всего только в одном случае - при исчерпании адресного пространства (т.е. невозможности сделать анонимный mmap). Во всех остальных случаях процесс будет убит по OOM, это полностью ожидаемое и корректное поведение.
>> Нет. Аллокатор всегда выделяет страницы сразу.
> Вы уже не раз показали себя ламером, может пора научиться хотя-бы проверять,
> прежде чем говорить о том, о чём понятия не имеете? Сделайте
> программу, malloc(); system("ps"); memset(); system("ps"); и посмотрите что будет с VM
> и RSS.Я бы порекомендовал вам перед тем, как говорить о личности собеседника, научиться программировать хотя бы на каком-нибудь языке программирования. Ну, хоть на Бейсике, что ли.
>> Что тогда? SIGKILL "Out of swap space"?
> Именно, и это правильно.Ну-ну.
>> Противоречит семантике работы malloc()
> OOM killer не имеет никакого отношения к семантике работы malloc, и избежать
> его всё равно нельзя из-за фундаментальных принципов работы системы виртуальной памяти.
> Кроме того, выделение физических страниц на аллокации - это кошмарное падение
> производительности, рост потребления памяти, невозможность выделить фрагмент больше
> размера физической памяти.Это вы сами придумали, да?
> Почему нельзя избежать OOM - показываю на примере: процесс выделил много памяти,
> допустим даже честно выделил физические страницы, далее он форкается. Либо вы
> честно копируете всё адресное пространство (а с такой системой вы никому
> не нужны), либо одна из копий будет убита при записи в
> память, когда при cow кончатся физические страницы.
> Другой пример - процесс выделил память-ok, был вытеснен в swap и весь
> его занял. Другой процесс выделил память-ok, и занял всё физическую. Когда
> проснётся первый процесс и полезет из swap'а, он будет прибит безо
> всяких malloc по причине исчерпания физических страниц.Вы бредите. Почитайте про VM в Юниксе на досуге.
Понятия "процесс был вытеснен в swap" и VM -- взаимоисключающие параграфы.
> Итого - на деле malloc вернёт 0 скорее всего только в одном
> случае - при исчерпании адресного пространства (т.е. невозможности сделать анонимный mmap).
> Во всех остальных случаях процесс будет убит по OOM, это полностью
> ожидаемое и корректное поведение.Чудесный, непередаваемый бред.
===
{11} user@host:/usr/src/lib/libc $ grep 'return (NULL)' stdlib/malloc.c | wc -l
30
{12} user@host:/usr/src/lib/libc $ grep 'mmap' stdlib/malloc.c | wc -l
22
===Перед тем, как рассуждать про "ожидаемое и корректное", настоятельно рекомендуется сверять свои ожидания с исходными текстами системных библиотек.
> Итого - на деле malloc вернёт 0 скорее всего только в одном
> случае - при исчерпании адресного пространства (т.е. невозможности сделать анонимный mmap).
> Во всех остальных случаях процесс будет убит по OOM, это полностью
> ожидаемое и корректное поведение.По уточнённым данным:
===
{40} user@host:/usr/src/lib/libc $ cc -I /usr/src/lib/libc/include -E stdlib/malloc.c | grep -v "^#" | grep '= mmap'|wc -l
1
{41} user@host:/usr/src/lib/libc $ cc -I /usr/src/lib/libc/include -E stdlib/malloc.c | grep -v "^#" | grep 'return (0)' | wc -l
16
===Итого, случаев возврата NULL'ей в malloc() ровно в 16 раз больше случаев вызова mmap().
> Вы бы вначале на код посмотрелиЯ, по-моему, всё ясно написал:
> Либо переводчик лажанул и там было что-нибудь про заполнение этой памяти