beldmit: (Программизм)
Dmitry Belyavskiy ([personal profile] beldmit) wrote2014-05-11 03:34 pm

Несвопируемая память

Узнал тут из переписки в криптографической рассылке о функциях mlock/munlock. Почитал man-ы. К счастью, по разным операционкам. И кажется мне, что эти функции сильно недоделаны.

То, что оно позволяет блокировать в памяти от помещения в swap всю страницу целиком, это нормально и по-другому скорее всего не делается. То, что в половине операционок может быть вызваны только из-под рута (под Линуксом не так, там можно задать количество для не-рута через ulimit начиная с ядра 2.6.9), это уже большой привет. То, что там нет встроенного счетчика, сколько раз страницу лочили, и единственный вызов munlock разблокирует страницу, залоченную трижды – уже хуже, поскольку вынуждает сотворить собственный менеджер памяти, пусть даже вырожденный, системы «залочил страницу и отдаем по кусочку, все ценное туда» – совсем уже нехорошо.

А жалко. Потому как функциональность полезная.

Update: В комменты пришел [livejournal.com profile] dmih и рассказал про виртуализацию и ее издержки. Да, скорее всего все эти прелести в условиях виртуализации действительно неактуальны.

[identity profile] p_govorun.livejournal.com 2014-05-11 12:13 pm (UTC)(link)
А зачем лочить дважды? Залочил страницу, положил ключ, потёр ключ, разлочил страницу.

[identity profile] beldmit.livejournal.com 2014-05-11 12:16 pm (UTC)(link)
То есть ключ грузить в память каждый раз on demand и не шифровать на разовых ключах, например? Да, но тогда проще ключ прочитать не из свопа, а оттуда, где он лежит.

[identity profile] p_govorun.livejournal.com 2014-05-11 12:24 pm (UTC)(link)
s/положил/создал/

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

[identity profile] beldmit.livejournal.com 2014-05-11 12:26 pm (UTC)(link)
Ключ существенно меньше страницы. А malloc выдает адреса откуда попало. Так что получаем необходимость своего менеджера памяти.

[identity profile] p_govorun.livejournal.com 2014-05-11 12:31 pm (UTC)(link)
Это будет не менеджер памяти, а менеджер ключей. То есть, кто-то должен сказать: "на этой странице больше нет секретной информации", и это явно не работа менеджера памяти.

[identity profile] beldmit.livejournal.com 2014-05-11 12:37 pm (UTC)(link)
Эмм. А в чем разница, если все равно этого "кого-то" программировать?

[identity profile] p_govorun.livejournal.com 2014-05-11 12:42 pm (UTC)(link)
Ну, менеджер памяти точно не будет забивать страницу нулями прежде чем объявить её свободной. Так что "кто-то" всё равно нужен.

[identity profile] beldmit.livejournal.com 2014-05-11 12:44 pm (UTC)(link)
Нужен, нужен. А нэту. Потому что, будь там счетчик, можно было бы поручить это все деструктору: и память нулями затереть, и munlock вызвать...
ext_605364: geg MOPO4 (geg_MOPO4)

[identity profile] gegmopo4.livejournal.com 2014-05-11 01:36 pm (UTC)(link)
Не всегда память нужно затирать. Лочат не только ради безопасности, но и ради производительности.

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

[identity profile] beldmit.livejournal.com 2014-05-11 01:39 pm (UTC)(link)
Это уже детали. А то, что нельзя делать malloc/mlock/munlock/free, приводит к необходимости лишней работы дополнительной аккуратности.
vitus_wagner: My photo 2005 (white)

[personal profile] vitus_wagner 2014-05-12 04:12 am (UTC)(link)
А нехрен экономить Страница не настолько велика, чтобы ключ не стоил выделения под него целой страницы.

[identity profile] beldmit.livejournal.com 2014-05-12 04:23 am (UTC)(link)
Да мне не жалко страницы для ключа. Даже для одноразового. Но как гарантировать, что malloc отдаст ровно новую страницу?
vitus_wagner: My photo 2005 (white)

[personal profile] vitus_wagner 2014-05-12 04:32 am (UTC)(link)
А ты делай mmap(MAP_ANONYMOUS).

[identity profile] beldmit.livejournal.com 2014-05-12 05:08 am (UTC)(link)
Вариант. То есть остается только недоступность от обычного пользователя.
vitus_wagner: My photo 2005 (white)

[personal profile] vitus_wagner 2014-05-12 06:10 am (UTC)(link)
Которую пофиксили еще когда номер версии ядра был меньше числа e

[identity profile] beldmit.livejournal.com 2014-05-12 06:53 am (UTC)(link)
Это на линуксе пофиксили.
vitus_wagner: My photo 2005 (white)

[personal profile] vitus_wagner 2014-05-12 06:57 am (UTC)(link)
У тебя еще много HP/UX-ов и Solaris-ов среди пользователей твоего софта?

[identity profile] beldmit.livejournal.com 2014-05-12 07:00 am (UTC)(link)
У меня такого софта вообще нет. На FreeBSD вроде как только от рута.

[identity profile] dmih.livejournal.com 2014-05-11 02:37 pm (UTC)(link)
Вообще это должно быть API уровня ОС. Потому что то, что названо (не свопить) - это частный случай какой-то.
Есть еще миллион способов в современной ОС и компьютере, который довольно таки сложен уже, получить или не получить чужую память. Реализация этих способов зависит от ОС, это ну никак, потому что нет тут общего в архитектурах, это буквально может даже от возможности процессора зависеть даже на одинаковых с виду компьютерах.
Соответственно в Win32 есть какое-то crypto-API на эту тему, ну и так далее.

[identity profile] beldmit.livejournal.com 2014-05-11 02:41 pm (UTC)(link)
Ну для unix-ов это и есть уровня OS. Случай частный, но характерный. Данные в свопе читаются кем ни попадя, отсюда желательно, чтобы секретные ключи и пароли туда не попадали в голом виде, и работа со свопом медленнее, так что все, что должно быть доступно быстро, имеет смысл не свопировать. Еще что-то можно придумать, наверное.

[identity profile] dmih.livejournal.com 2014-05-11 02:47 pm (UTC)(link)
Уровня ОС - это демон, который висит от root-а, и этим рулит с учетом ВСЕХ возможностей КОНКРЕТНОГО ядра и архитектуры.
Например, в современных машинах только ленивый не занимается виртуализацией. Тут ты свопь, не свопь, для машины уровнем выше всё как открытая книга. Save-state опять же. И вот тут-то гипервизор может давать дополнительные возможности, а кое-где даже их и предоставляет, читал про это, запамятовал название экстеншена этого для XEN-а (как пример).
А то, что не свопить - это не уровня ОС, это скорее, уровня ядра называется, причем, механизм явно не по назначению. Бесправный пользователь и своп-то с трудом прочитает, а службе уровня root-а с таким флагом будет только проще ключи в памяти искать, причем проще порядка на два.

[identity profile] beldmit.livejournal.com 2014-05-11 03:35 pm (UTC)(link)
(Отвечу сразу на все). Тут, пожалуй, согласен. Гибернация никаких сигналов не посылает, который обработать можно? Про реализации через page fault - интересно было бы почитать в деталях.

Про виртуализацию да. Боюсь, тупо выделить физическую железку уже не спасет.

[identity profile] dmih.livejournal.com 2014-05-11 03:44 pm (UTC)(link)
Ну кому посылает, кому нет. Драйверам, конечно, посылает, причем дает возможность сделать что-то до гибернации (поэтому см. опять про службу, а не возможность ядра). Пользовательский софт этого боюсь не видит никак даже уровня root-а. Максимум он может получить извещение о событии, и может даже даже заблаговременно до гибернации (пока там драйвера чухаются - он еще жив и в сознании), но без гарантии и без возможности отложить или фиксированно что-то сделать.

[identity profile] dmih.livejournal.com 2014-05-11 03:52 pm (UTC)(link)
А про реализации через page fault - да вот тут список софтварного FIPS-а подходящего уровня уже с 8-го этажа до пола - http://csrc.nist.gov/groups/STM/cmvp/documents/140-1/140val-all.htm
Там и VMWare отметилось, и Microsoft много раз, и так далее.
Я поскольку крепко всё забыл, какую конкретно реализацию я смотрел, я не помню (собственно у меня была нужда её поломать как раз), но половина софтварные и ключи у них из памяти, надо сказать, хрен сопрешь.
Надо вот API выстраивать к этим системам, а не страницы в памяти лочить в помощь хакерам, убирая даже security through obscurity (например, когда стоит необходимость поломать Windows с полным Address Space Randomization, все сразу унывают, и геморрой иногда возрастает за предел tradeoff-а с практичностью взлома).

[identity profile] dmih.livejournal.com 2014-05-11 02:50 pm (UTC)(link)
Еще пример - ты запустил mlock, потом тебе раз, гибернация. Ключ твой на диске по любому, ты даже не узнаешь об этом никогда.
Служба же сможет решить этот вопрос.
Ну не о том разговор короче, IMHO.
vitus_wagner: My photo 2005 (white)

[personal profile] vitus_wagner 2014-05-12 04:15 am (UTC)(link)
Вообще-то есть системная шина сообщений. Которая как раз подобного рода вещи позволяет достаточно элегантно решить. Хотя используют ее обычно абсолютно не по делу.

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

[identity profile] dmih.livejournal.com 2014-05-11 03:17 pm (UTC)(link)
Ну, еще пример до кучи, как это обычно НОРМАЛЬНО делают: страница памяти не помечается несвопируемой, а наоборот кроется page-fault-ом самого высокого уровня.
Потом обработчик этого в ОС начинает разбираться, чем вызван отказ страницы, какой процесс вызвал срабатывание, и так далее со всеми выводами. На мощных современных процессорах с многократной защитой хрен уведешь даже из соседнего root-а, не разрушив необратимо пол системы (ну т.е. понятно, что ключ достижим, но хотя бы аудит в некотором смысле выполняется).
Я этим не интересовался уже лет 10 наверное, поэтому не могу сказать, в каких современных обычных ОС это сейчас реализовано например вот так, как описано, но точно были реализации для XP, класса почти штатных. Мне кажется могли бы быть и сейчас такие. Но опять же пользовательский процесс тут вот никак.