Войти в систему

Home
    - Создать дневник
    - Написать в дневник
       - Подробный режим

LJ.Rossia.org
    - Новости сайта
    - Общие настройки
    - Sitemap
    - Оплата
    - ljr-fif

Редактировать...
    - Настройки
    - Список друзей
    - Дневник
    - Картинки
    - Пароль
    - Вид дневника

Сообщества

Настроить S2

Помощь
    - Забыли пароль?
    - FAQ
    - Тех. поддержка



Пишет dibr ([info]dibr)
@ 2011-08-06 16:56:00


Previous Entry  Add to memories!  Tell a Friend!  Next Entry
защищённость без защиты
     Операционная система должна быть защищена от работающих в ней приложений, и обеспечивать защиту приложений друг от друга (привет от К.О.). Речь сейчас в основном не о вирусах/троянах, которые используют штатные возможности системы чтобы делать нехорошие вещи (здесь мы рано или поздно упрёмся в то, что отличить "хорошую" вещь от "нехорошей" не всегда просто), а о том, чтобы ошибки в обычном, не вредоносном, приложении (такие как обращение к "чужой" памяти) оставались внутри приложения и не приводили к нарушениям работы других приложений и собственно ОС. Сейчас для этого обычно используются аппаратные методы, такие как "защищённый режим" процессора: ОС выставляет процессу ограничения на используемые им ресурсы, процессор при выполнении кода аппаратно проверяет допустимость операций, и при выполнении операции, нарушающей ограничения, генерируется "исключение", обрабатываемое операционной системой ("программа выполнила и будет закрыта"), или отдаваемое приложению ("runtime error..."). И, хотя аппаратные проверки и замедляют работу (на любую проверку нужно время, кроме того - при переключении между процессами тратится время на перегрузку "описания ограничений" в процессоре), и увеличивают сложность процессора - всё равно по другому как бы вроде бы и не получится. Даже если конкретный компилятор порождает код, делающий все необходимые проверки - компиляторов много, кто-то может вообще использовать ассемблер или "писать в шестнадцатеричных кодах", а значит в выполняемом файле может оказаться инструкция, обращающаяся "не туда", эта инструкция может выполниться на реальном, аппаратном, процессоре, а при аппаратном выполнении инструкции единственный способ отследить "обращение не туда" - делать это аппаратно, на уровне процессора.

     Или нет? Например, сейчас вовсю набирают популярность языки, где возможность "обратиться не туда" исключается самим языком: достаточно отказаться от указателей внутри языка (вместо них ввести какие-нибудь высокоуровневые "ссылки"), ввести принудительную проверку индексов массивов и приравненных к ним сущностей, а чтобы не делать лишние проверки где не надо - максимально "обернуть" типовые действия над множествами объектов разнообразными "итераторами" и прочими примочками. И, собственно, всё - если язык by design не позволяет совершать такого типа ошибки, а компилятор исправен и не допускает их сам - полученный машинный код можно запускать "без защиты", ошибки в нём могут быть, но только внутренние, не мешающие остальным. Проблема получается только в том, что не весь код создаётся именно этим, "правильным", компилятором, на "правильном" языке (а возвращаясь к "вредоносным программам" - кто-то может создать "неправильный" код непосредственно в коде, минуя компилятор), а значит совсем отказаться от аппаратной защиты как бы опять же... или таки нет?

     А что если попробовать возродить что-то вроде UCSD P-System, но на новом уровне? Для начала - разрабатываем "относительно низкоуровневый" псевдокод (вроде того же UCSD P-code или Java bytecode), в который можно оттранслировать программу на любом интересующем нас языке, но при этом обладающий тем свойством, что в рамках этого псевдокода нельзя обратиться к не принадлежащему тебе объекту - просто потому что нет метода это сделать, как, например, нет метода обратиться к произвольной ячейке памяти в языках без указателей. Помнится, Великий и Ужасный dz когда-то упоминал (жаль, без подробностей) архитектуру Intel 432, где в самом машинном коде просто не было способа создать указатель из числа - только получить его извне, а значит и обратиться "не туда" программа не могла, ввиду отсутствия метода это сделать. (Как я понимаю, "метод создать указатель" там всё-таки был, но он был доступен только на определенном уровне привилегий - грубо говоря, "только ОС и доверенный код" - раз уж указатели предусмотрены архитектурой, кто-то же их должен порождать). А значит, "тьюринг-полный" псевдокод, застрахованный от ошибок вида "обратился к чужому", придумать можно.
     А дальше - очень просто. Программы распространяются не в "бинарниках" с машинным кодом, а в псевдокоде. Принесённый извне (скопированный) бинарник с машинным кодом ОС игнорируется - "это не моё, запускать не буду", при первом запуске программы в псевдокоде - из него генерируется бинарник в машинном коде (заведомо не содержащий ошибок вида "обратиться к чужому", в силу устройства псевдокода), и именно он уже запускается. Сгенерированный бинарник с машинным кодом на уровне ОС доступен пользователю только на просмотр и удаление, изменение разрешено только самой ОС - а значит хотя в машинном коде и могли бы содержаться ошибки вида "обращение к чужому", взяться им там неоткуда: ОС генерирует код без ошибок, а подменить машинный код на ошибочный так просто не получится - ОС защищает файл.
     При "добропорядочном" использовании системы этого уже достаточно: принесённые извне бинарники с машинным кодом не запускаются (а по потребности - пересоздаются из псевдокода), лежащие на локальных несменных дисках бинарники с машинным кодом защищены от изменения средствами самой ОС. На втором уровне паранойи ("а мы теперь такие загрузимся с дискетки и таки подменим бинарник с маш. кодом") можно предусмотреть, например, "подписывание" бинарников этой копией ОС, и даже их перегенерацию из псевдокода при запуске после перезагрузки системы, но это уже подробности - если не заглубляться в рассуждения, как ещё можно обмануть ОС, если поставить себе цель, то достаточную безопасность обеспечить можно, а если заглубиться - так имея физический доступ к диску всегда можно обойти любую защиту, вопрос только в сложности.

     В результате мы получаем операционную систему, с возможностью разработки приложений на большинстве языков (на всех тех, что допускают компиляцию в наш псевдокод), способную обеспечить защиту памяти не хуже других ОС, при этом работающую даже на процессорах, не имеющих аппаратных средств защиты (хоть, простигосподи, 8086 какой-нибудь), и работающую быстро - используется не интерпретация псевдокода, а выполнение машинного кода на реальном процессоре. Сейчас, когда с одной стороны довольно мощные системы вовсю "лезут в карман" (используются в портативных применениях), а с другой стороны - активно идёт разработка новых платформ (пусть даже наворачиванием очередного слоя обёртки на уже существующие, главное что разработчики уже спокойно относятся к частой смене платформ), возможность без проблем выкинуть из процессора сколько-то "лишних" транзисторов и "лишних" проверок при выполнении - может оказаться востребованной.

     ...А теперь скажите мне, какой велосипед я на этот раз изобрёл? Не верю, что с момента изобретения p-code никто не пытался сформулировать эту идею именно так :-)


(Добавить комментарий)


[info]starcat13@lj
2011-08-06 10:05 (ссылка)
> Для начала - разрабатываем "относительно низкоуровневый" псевдокод (вроде того же UCSD P-code или Java bytecode), в который можно оттранслировать программу на любом интересующем нас языке, но при этом обладающий тем свойством, что в рамках этого псевдокода нельзя обратиться к не принадлежащему тебе объекту

А это не противоречивые условия? Возможно ли принципиально создать такой псевдокод, чтобы в него можно было отранcлировать программу на C, например?

(Ответить) (Ветвь дискуссии)


[info]dibr@lj
2011-08-06 10:23 (ссылка)
Формально - нет, Си нельзя: в нём указатели, а у нас их нет(*)
Но если объявить указатели "персоной нон-грата", а для сильно желающих - завести в памяти "песочницу" с данными, все обращения через указатели обносить проверками на невыход за границы "песочницы", а случаи вроде указателей на функции обрабатывать особо - 99% программ будут компилироваться и работать.

(*) ...совсем формально - можно: на нашем псевдокоде можно написать эмулятор целого компьютера, а уже в нём - "виртуально" гонять что угодно, хоть ассемблерные "войны в памяти". Но это очень, очень медленно, поэтому для желающих "старый добрый Си" - только вышеприведённый компромисс.

(Ответить) (Уровень выше)


[info]thenexus6@lj
2011-08-06 10:06 (ссылка)
AS/400 изобрёл :)
Про её историю и архитектуру есть великолепная книжка от одного из главных разработчиков. На русский переведена также отлично.

(Ответить) (Ветвь дискуссии)


[info]starcat13@lj
2011-08-06 10:07 (ссылка)
а как называется? Интересно почитать

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]thenexus6@lj
2011-08-06 10:13 (ссылка)
Основы AS/400 - Солтис Фрэнк.
А переводил (или редактировал?) книгу один из лучших спецов по этим системам в России.

Только там схемок прилично, поэтому в text-only формате лучше не читать.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]dibr@lj
2011-08-06 10:23 (ссылка)
Хм. Спасибо, попробую поискать - интересно, как всё это в реальности реализовали :-)

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]thenexus6@lj
2011-08-06 10:26 (ссылка)
Если найдётся только без картинок - пиши, у меня есть с картинками :)

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]dibr@lj
2011-08-06 10:42 (ссылка)
Нашёл с картинками, поизучаю :-)

(Ответить) (Уровень выше) (Ветвь дискуссии)


(Анонимно)
2011-08-07 06:14 (ссылка)
Можно ссылку? Хотел как раз про AIX ещё дописать, но явно это было в 400й...

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]dibr@lj
2011-08-07 07:34 (ссылка)
http://www.e-reading.org.ua/book.php?book=147881

Я качал оттуда html, картинки при этом грузятся с сети, поэтому для сохранности пересохранил в mht

(Ответить) (Уровень выше)


[info]starcat13@lj
2011-08-06 10:27 (ссылка)
спасибо, поищу

(Ответить) (Уровень выше)


[info]hml@lj
2011-08-06 10:32 (ссылка)
хехе, великий и ужасный dz прямо сейчас вовсю пилит обственную Фантом-ОС, где именно так и есть -- jit, псевдокод и секурность by design :)

(Ответить) (Ветвь дискуссии)


[info]dibr@lj
2011-08-06 10:44 (ссылка)
JIT и псевдокодом уже никого не удивишь. А вот секурность у него, интересно - аппаратная, как в виндах-линухах, или вот такая вот, "за счёт дизайна и таможенного контроля на входе"?

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]hml@lj
2011-08-06 11:51 (ссылка)
секурность таможенная

(Ответить) (Уровень выше)


[info]ext_229571@lj
2011-08-06 10:51 (ссылка)
Во-первых, уже сегодня можно виртуализовать ОС с приложением насовсем, и избежать проблемы доступа к соседнему процессу через это. Даже преднамеренные попытки обратиться не туда будут блокироваться гипервизором. И ради совместимости с унаследованным говном мамонта все коммерческие производители так или иначе будут тянуть эту идею, параллельно выдумывая всякие облака.

Но Фантом чем-то напоминает, ага.

(Ответить) (Ветвь дискуссии)


[info]dibr@lj
2011-08-06 11:12 (ссылка)
> Во-первых, уже сегодня можно виртуализовать ОС с приложением насовсем, и избежать проблемы доступа к соседнему процессу через это

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

> Но Фантом чем-то напоминает, ага.

А ты не в курсе - там аппаратная защита, или вот такая вот, "за счёт дизайна и таможенного контроля кода"?

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]ext_229571@lj
2011-08-06 11:33 (ссылка)
> Это дорого

Я зачем сказал слово «облака»? Для одного клиента дорого, для тысяч — очень дёшево.

> А ты не в курсе - там аппаратная защита, или вот такая вот, "за счёт дизайна и таможенного контроля кода"?

Не в курсе, но он же собирается пускать её на обычных машинах, а значит, вряд ли аппаратная. Вот у Бабаяна в ОС Эльбрус — там была аппаратная.

(Ответить) (Уровень выше)


[info]ufm@lj
2011-08-06 11:47 (ссылка)
За счет дизайна.

(Ответить) (Уровень выше)


[info]ext_229571@lj
2011-08-08 15:12 (ссылка)
Вот кстати, об аппаратной изоляции процессов и пользовательских данных — есть такая ОС, называется IBM i, она же i5/OS и OS/400. Вот там оно.

(Ответить) (Уровень выше)


[info]mc6312@lj
2011-08-06 12:11 (ссылка)
> А дальше - очень просто. Программы распространяются не в "бинарниках" с машинным кодом, а в псевдокоде
Из реально существующих и с оговорками - жаба, дотнет.

Из несуществующих (в пригодном для реального мира виде) - тут уже Фантом упоминали, еще MS Singularity.
И мильен всяких академических грантопопильных поделок.

(Ответить) (Ветвь дискуссии)


[info]dibr@lj
2011-08-06 12:23 (ссылка)
Жаба - да. Но просто жабы мало, нужно чтобы "бинарники в машкодах" в принципе создавались только самой ОС, а принесённые извне - не исполнялись бы (впрочем, можно сделать исключение для "доверенных и подписанных" бинарников, вроде апдейтов к самой ОС).

Вот и посмотрим на фантом, что там будет...

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]mc6312@lj
2011-08-06 12:44 (ссылка)
Если будет. Че-то оно очень сомнительно.

(Ответить) (Уровень выше)


[info]brmail@lj
2011-08-06 13:18 (ссылка)
И, собственно, всё - если язык by design не позволяет совершать такого типа ошибки, а компилятор исправен и не допускает их сам - полученный машинный код можно запускать "без защиты"

Напомнило мне visual basic 6 - именно так там все и было.

(Ответить) (Ветвь дискуссии)


[info]dibr@lj
2011-08-06 13:29 (ссылка)
Любой язык, в котором нет указателей, и производится проверка индексов в процессе выполнения, скорее всего будет "именно таким". А это почти все скриптовые языки (указатели им не нужны, а диагностика ошибок важнее скорости), куча современных "сильно объектных" - ну и бейсик, да. Причём не только вижуал, но и древние версии тоже (если забыть про peek/poke) :-)

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]mc6312@lj
2011-08-06 13:42 (ссылка)
> диагностика ошибок важнее скорости

...прощайте игрухи с тяжёлой графикой, прощай склейка панорам с помощью GPU, прощайте шустрые (или хотя бы не катастрофически тормозные) архиваторы и прочая, прочая, прочая... зато безопасно.

Не, лет через 20, когда в каждом дверном звонке будет стоять 64-ядерный процессор с тактовой под 10 ГГц, оно м.б. и оправдается, но не сейчас.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]nlothik@lj
2011-08-06 14:17 (ссылка)
> ...прощайте игрухи с тяжёлой графикой, прощай склейка панорам с помощью GPU, прощайте шустрые (или хотя бы не катастрофически тормозные) архиваторы и прочая, прочая, прочая... зато безопасно.

Ну никто и не предлагает писать Doom 4 на Джаве %)

А на сервере, где надо с гарантией, чтобы он падал как можно реже -- Джава рулит и педалит.

(Ответить) (Уровень выше)


[info]dibr@lj
2011-08-06 15:15 (ссылка)
>> диагностика ошибок важнее скорости
>> почти все скриптовые языки (указатели им не нужны, а диагностика ошибок важнее скорости)
> ...прощайте игрухи с тяжёлой графикой, прощай склейка панорам с помощью GPU

Привет! Ты давно последний раз видел "игруху с тяжелой графикой" или "склейщика панорам с помощью GPU", написанного на скриптовом языке? А там ведь прямо написано, что "диагностика важнее скорости" - это именно про скриптовые.

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

Так чтааа... то, что сейчас жаба - тормоз, ещё не значит, что эта концепция в принципе такая уж тормозная. Может, её просто никто всерьёз в эту сторону не допиливал...

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]starcat13@lj
2011-08-06 15:54 (ссылка)
Раз уж поминали dz, то: http://dz.livejournal.com/204180.html - "Ява обогнала С++, во как..."

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]mc6312@lj
2011-08-06 16:12 (ссылка)
На отдельном тесте.

(Ответить) (Уровень выше)


[info]mc6312@lj
2011-08-06 16:07 (ссылка)
> Ты давно последний раз видел "игруху с тяжелой графикой" или "склейщика панорам с помощью GPU", написанного на скриптовом языке?

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

> С GPU вообще вопрос отдельный
Нифига не отдельный. GPU нужно скармливать данные и код, причем с такой скоростью, чтоб оно вообще себя оправдало по сравнению с CPU онлы, и в том виде, какой жрет текущий GPU. Т.е. один фиг без всякой низкоуровневой шняги не обойтись.

(Ответить) (Уровень выше)


[info]ilya_314@lj
2011-08-06 17:51 (ссылка)
OS MS Singularity реализует защиту на уровне доказательства безопасности кода. Сейчас там используется специально докрученый компилятор bartok C#, который генерирует безопасный код. Процессы изолируются программно, для этого несколько расширили MSIL (ассемблер .net) и код верифицируется до запуска.

Кстати ведутся еще другие работы - инструменты верификации уже скомпилированного кода. Есть такое направление - TAL (Typed Assembly Language). К exe файлу прикладывается дополнительная инфа о типах и на ее основе уже достаточно простой проверяльщик верифицирует может ли что-то нехорошее сделать данный ассемблерный код. Таким образом убирается поледнее узкое место - ошибки в оптимизаторе.

Хотел кстати давно написать об этих вещах, все как-то руки не доходили.

(Ответить) (Ветвь дискуссии)


[info]ilya_314@lj
2011-08-06 17:56 (ссылка)
Про singularity:

http://www.computerra.ru/vision/617626/
http://www.computerra.ru/618124/
http://www.rsdn.ru/article/singularity/singularity.xml

Про TAL, который делает MS можно посмотреть на channel9.

Кстати dz упоминал, что одним из серъезных конкурентов фантома является simgularity. Про возврат состояния речи не идет, но что касается программного контроля безопасности - тут все очень серьезно продвинуто и движение идет в сторону высокой степени доказанности безопасности.

(Ответить) (Уровень выше)


[info]ilya_314@lj
2011-08-06 18:00 (ссылка)
Ну и еще в догонку - программная изоляция процессов в фантоме конечно тоже сделана.

(Ответить) (Уровень выше)


[info]dibr@lj
2011-08-06 19:05 (ссылка)
Любопытно. То есть, они допиливают даже верификацию машинного кода, не промежуточного псевдокода - это серьёзно.
Но я правильно понимаю - для такой верификации бинарник должен кроме собственно кода содержать дополнительную информацию? И ключевой вопрос - верифицирует машинный код сама система (тогда всё как у меня: если код верифицирован, его можно запускать вообще без защиты, не верифицирован - не запускаем вообще), или верификация возложена на разработчика, а система сама не верифицирует (например, если это слишком ресурсоёмко) и вынуждена либо априори "доверять" коду, имеющему какие-то опознавательные знаки, либо на всякий случай как и сейчас, запускать процессы с аппаратной изоляцией/защитой памяти?

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]ilya_314@lj
2011-08-07 01:03 (ссылка)
Система не использует аппаратную защиту вообще. Да, код верифицируется перед запуском, сейчас MSIL, а в будущем будет верифицироваться ассемблер.

И вобщем да, идея по сути та, которую ты описываешь.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]ilya_314@lj
2011-08-07 01:12 (ссылка)
Под ассемблером я имею ввиду обычный бинарник с дополнительными метаданными.

(Ответить) (Уровень выше)


[info]dibr@lj
2011-08-07 06:17 (ссылка)
Вообще, верификация машинного кода x86 - это очень круто, круче чем я предполагал. Будем надеяться, что из этого что-то вырастет - а то цепочка "следующая винда должна быть совместимой с предыдущей" вряд ли приведёт нас к победе роботов :-)

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]ilya_314@lj
2011-08-07 06:44 (ссылка)
Да, думаю что-то из этого вырастет.

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

По совместимости делали примерно следующее:

Компоненты (в частности DLL) жестко версионируются, никакой простой подмены нет (можно только если явно сильно захотеть). Кстати с подменой библиотек на самом деле все несколько хитрее в том-же Linux (где то я обсуждал подобные вещи в жж), там вроде как такое все еще практикуется и вообще непонятно можно ли там миксовать компоненты например с разными версиями crt. В том же самом QT были проблемы с подменой без версионирования, в частности meego огребла проблемы по этой части ([info]vikky_13@lj рассказыыала), софт переставал работать, странно что встают на грабли, которые windows давно уже прошла.

В .net CLR очень удачно заморозили в стадии версии 2 (это поддержка generics - типа шаблонов на уровне MSIL), а все остальное - это библиотеки, библиотеки строятся путем добавления новых - .net 4 включает API .net 3.5, тот .net 3.

На уровне всей ОС думаю активно будут использовать виртуализацию. Когда в архитектуре происходит точка качественно изменения, тогда все старое просто погружаем внутрь виртуальной подсистемы, обеспечиваем нужный уровень сшивания с внешним миром. Сейчас это можно видеть в частичной виртуализации типа UAC (реестр, файловая система) и полной виртуализации типа XP mode (тут не сильно бесшовно получается - это по сути виртуальная машина работает). Дальше вероятно собираются использовать гипервизор Hyper-V (уже есть намеки на это про Windows 8), чтобы иметь несколько работающих ядер и при этом железный уровень будет шарится с хорошей производительностью.

А в целом тенденция такая - максимально загонять приложения в рамки того, что ему надо. Вот совсем скоро будет конференция build на которой MS расскажет о новых API для построения приложений для Win8. Там идея примерно в том, что приложение снабжается манифестом, который описывает что и где оно делает, но видимо и API дополнительный будет. Если все регламентировано и описано, то сразу появляются красивые фишки типа синхронизации в облаке, перенос настроек и контроль за тем что можно и нельзя софту делать. А пока этого нет, для всего старого пришлось придумывать механизмы типа UAC, когда приложение продолжает думать что пишет в папку program files или system32.

(Ответить) (Уровень выше)


[info]ilya_314@lj
2011-08-07 06:52 (ссылка)
Винде по причине проблем с обратной совместимостью предрекали быструю смерть, однако ничего подобного не произошло, оказывается есть еще возможности, думаю не все так страшно. Причем ведь любая система сталкивается с подобным, винда просто развивается, а Linux топчется на месте, поэтому там вроде как было, так и осталось, т.е. по сути они плотно с этим и не работают.

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

(Ответить) (Уровень выше)


[info]tarnyagin@lj
2011-08-07 07:16 (ссылка)
А быстрее не получится. Аппаратная защита памяти - бесплатное приложение к механизму виртуальной памяти, без которой современный компьютер представить сложно. Кстати, механизм этот дёшев, реализован на всём что шевелится (тех же ARM, к примеру).

(Ответить) (Ветвь дискуссии)


[info]ilya_314@lj
2011-08-07 07:31 (ссылка)
Если исполняемый код порожден из "управляемого" языка, главным свойством которого является запрет на бесконтрольное манипулирование указателями, тогда обеспечение безопасности и изоляция делается бесплатно. Если же коду принципиально дается возможность делать что угодно в памяти, то программная эмуляция страничной зашиты очевидно не имеет никакого смысла.

Вот в рамках такого расширения "управляемого" окружения до масштабов ОС и ведутся работы. В частности OS Singularity уже давно развивается как исследовательский проект. Здесь важно опустить верификацию исполняемого кода на как можно более низкий уровень, чтобы верификатор стал простым и надежным и не было привязки к языку программирования, для этого разрабатывается технология TAL (typed assembly language) - как снабдить обычный бинарный код информацией достаточной для доказательства безовпасности кода.

(Ответить) (Уровень выше)


[info]dibr@lj
2011-08-07 08:02 (ссылка)
А бесплатное ли? Чтобы реализовать виртуальную память, достаточно иметь (одну) таблицу страниц памяти, и генерировать исключение при обращении куда не надо. А чтобы к этому прикрепить защиту памяти - нужно для каждого процесса иметь свою таблицу "куда можно", и при каждом переключении процессов загружать актуальную таблицу.

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

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]tarnyagin@lj
2011-08-08 03:15 (ссылка)
Как всё-же хорошо на русской клавиатуре, можно и более развёрнутый ответ написать :)

Начну с конца:
> А если вдруг окажется, что можно и без этого?
А вот нельзя "без этого". Каждому потоку, выполняющемуся на целевой машине требуется отдельный участок непрерывной памяти под стек. Размер стека заранее не известен и выделять физическую память "с запасом" -- расточительство. Поэтому если не брать совсем уж встроенные применения, то мультипоточность требует зачаточной виртуализации памяти.
Важно здесь что статической трансляцией адреса не обойтись, даже "минимальное", только для обеспечения функционирования стеков, решение будет требовать а) полноценный ассоциативный транслятор, б) программный обработчик отказов страницы.
Второе. Системе где-то требуется хранить атрибуты памяти (cacheable, bufferable, cache policy etc). Вообще говоря, ассоциированных с физическим адресом статических признаков было бы достаточно, но, чтобы не вводить ещё один уровень косвенности при доступе к памяти, для хранения этих битов проще, дешевле и быстрее в) использовать ту же таблицу трансляции.
Если есть "а" и "б" и "в", приделать "г" -- биты "readwrite" и "executable" не стоит совсем ничего, а гибкость в теле появляется необычайная. Начинает работать полноценная виртуализация памяти - возможность скидывать страницы в своп или отбрасывать их.
Последнее - "при каждом переключении процессов загружать актуальную таблицу". Неа. Не так. При каждом переключении инвалидируется (где частично, где целиком) TLB (внутри-MMU-шный кэш трансляции). Затраты на это копеечные, как и затраты на трансляцию в целом. "Вышибание" строк обычного, процессорного кэша при переключении контекста бьёт по производительности гораздо, гораздо сильнее.

Вот такой вот велосипед...

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]ilya_314@lj
2011-08-08 03:42 (ссылка)
Согласен, что стек и виртаульная память - эти проблемы остаются. В singularity используется одно адресное пространство на все процессы, т.е. нет множества таблиц трансляции и все работает с одним уровнем привелегий, соответственно дешев вызов в ядро. Они как раз в статьях показывают, как у них быстро это работает по сравнению с другими OS.

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

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

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]tarnyagin@lj
2011-08-08 04:05 (ссылка)
> используется одно адресное пространство на все процессы
Это как? Предел - 4 Gb на все процессы, я правильно понимаю? Больше памяти не выделить? Маловато будет.

> продвинуть создание софта на новый более надежный уровень
:-)

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]ilya_314@lj
2011-08-08 04:27 (ссылка)
> используется одно адресное пространство на все процессы
> Это как? Предел - 4 Gb на все процессы, я правильно понимаю? Больше памяти не выделить? Маловато будет.

Да, но сейчас повсеместно 64-битные процессоры, это не проблема. Кроме того, когда если это воплотится в реальной коммерческой системе, то не сегодня и не завтра, тогда уж точно это не станет проблемой.

> продвинуть создание софта на новый более надежный уровень
> :-)

Цель проекта singularity - проверка концепта высоконадежной системы с управляемым кодом ядра и драйверов. Такая вот забавная у людей цель.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]tarnyagin@lj
2011-08-08 15:40 (ссылка)
> Да, но сейчас повсеместно 64-битные процессоры
Я боюсь, это немножко не так. Количество процессоров в телефонах (в мире) сравнимо с количеством процессоров в персональных компьютерах (в мире). Приплюсуем к телефонам к телефонам сет-топ-боксы, телевизоры, плейеры, DVD и прочую другую встроенку.
И получим что самый распространённый процессор в мире -- ARM. 32-х битный.

> на новый более надежный уровень
> > :-)
> > > проверка концепта высоконадежной системы
Ирония моя в том, что на новый, более надёжный уровень описанный концепт софт не продвигает. На существенно более надёжный.
Я -- целевой потребитель концептов высоконадёжных систем. Если телефон падает - это плохо, очень плохо, но не смертельно. Если телефон своей активностью валит центр SMS оператора - это катастрофа. Первое отслеживается в статике инструментарием много проще предложенного, второе не предложенным инструментарием не отслеживается совсем.

Как-то так.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]ilya_314@lj
2011-08-08 16:56 (ссылка)
> Ирония моя в том, что на новый, более надёжный уровень описанный концепт софт не продвигает. На существенно более надёжный. Я -- целевой потребитель концептов высоконадёжных систем. Если телефон падает - это плохо, очень плохо, но не смертельно. Если телефон своей активностью валит центр SMS оператора - это катастрофа. Первое отслеживается в статике инструментарием много проще предложенного, второе не предложенным инструментарием не отслеживается совсем.

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

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

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]tarnyagin@lj
2011-08-09 19:49 (ссылка)
> Как пример - сравнить затраты на отладку native и managed приложения написанных разработчиками одного уровня
Ой, это моя больная мозоль как работодателя (в прошлом). Ключевое слово здесь "одного уровня". Если это как-нибудь обеспечить (найти волшебную фею, которая побудит высококлассного специалиста-системщика писать на managed коде и что-нибудь сделает чтобы не разрушить его мотивацию), то всё наверное заработает. А если феи нет, то проведя "соревнование" универсальных языков мы увидим что большую надёжность и вероятность успешного запуска продукта обеспечивают те из них, в которых для описания целевой проблемы надо больше потрудится. Желательно, чтобы написать код без предварительно разрисованного листа бумаги с алгоритмом было бы невозможно. Если расширить соревнование на не-универсальные языки (сюда попадают всякие кодогенераторы и т.д.), то побеждает язык, обеспечивающий максимальную компактность записи целевой проблемы.
Managed языки и развеситые фреймворки побуждают писать не думая, приоткрывают программирование для людей низкой квалификации, а на качество это влияет очень плохо. Даже если конечный продукт не падает.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]ilya_314@lj
2011-08-10 03:04 (ссылка)
Я сам практически все время программирую на C++, но мне кажется нет ничего плохого в том, чтобы поработать на managed языке, но просто 95% у нас делается на C++. Многие классные специалисты (если не рассматривать web, где своя специфика) работают на native языках и наверное просто сложнее найти того, кто также хорошо будет делать свою работу на managed языке. Это кстати говорит в целом о том, что native языки никуда не подевались, как некоторые наивно полагают не видя вокруг себя ничего кроме java и c#. Ведь нередко можно встретить рассуждения, мол c++ это динозавр и нечего на нем делать, язык умирает, чушь конечно.

Но с другой стороны и на C++ неопытные и низкоквалифицированные программисты такого могут наворотить, что мало не покажется. Т.е. если человек пишет на C/C++ это еще не значит, что код будет хорошим. Библиотеки контейнеров и алгоритмов есть и в C++ и с ними можно успешно молотить код мало задумываясь и получая на выходе очень нехорошие вещи.

Мне кажется ситуация скорее такая - сложные системы и реальные большие продукты разрабатывают на native языках, это и формирует спрос, на managed делают web и более мелкие задачи. Поэтому и расклад на рынке такой. По мере проникновения managed в крупные проекты ситуация изменится.

(Ответить) (Уровень выше)


[info]dibr@lj
2011-08-08 04:52 (ссылка)
А что стек. Стек же не сам растёт, стек программа использует. Одна проверка при выделении места в стеке - и стек можно отращивать по мере потребности.
И - я же не против виртуальной памяти, она полезная. Я только сомневаюсь, что этот механизм так уж необходимо использовать _ещё и_ для изоляции памяти процессов.

> При каждом переключении инвалидируется (где частично, где целиком) TLB (внутри-MMU-шный кэш трансляции)

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

> "Вышибание" строк обычного, процессорного кэша при переключении контекста

А это что за процедура? А то я не в курсе, у меня познания тут довольно обрывочные :-)

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]ilya_314@lj
2011-08-08 05:22 (ссылка)
Вот кстати цена вызовов:

Image

(Ответить) (Уровень выше)


[info]tarnyagin@lj
2011-08-08 15:17 (ссылка)
Со стеком фишка в том, что адресное пространство под него нужно отводить в момент создания потока, этот стек использующий. Расширить это пространство в runtime невозможно. Физическую же память в это пространство маппить не обязательно. Поэтому если в системе нет динамически обновляемой трансляции адресов - под стек придётся аллоцировать и физическую память тоже, а это жуткий overhead.

> > "Вышибание" строк обычного, процессорного кэша
> А это что за процедура?
Это, скорее, явление а не процедура. Кэш сконструирован из предположения локальности кода: за обращением к ячейке P вероятно последует обращение к ячейке P +- эпсилон. При переключении контекста эта идиома нарушается. Получивший квант процесс исполняет совсем другой код над совсем другими данными, нелокальный по отношению к процессу, квант отдавшему. Поэтому при смене контекста содержимое кэша с большой вероятностью инвалидируется, что ударяет по производительности весьма заметно.

TLB -- другая история. Подгружение TLB в большинстве случаев вообще абсолютно ничего не стоит, и вот почему: примерный, плюс-минус лапоть, виртуальный адрес становится известен на раннем этапе выполнения команды. К примеру, если выполняется команда "mov %eax,0x48(%esi)", смещение 0x48 может быть спокойно отброшено как скорее всего не влияющее на индес страницы. Не угадали - не страшно, всё равно за TLB-промахом последует более "тяжёлый" кэш-промах, можно спекулятивно считать дальше.

Да, ещё: таблица трансляции адресов в процессор не влезает. Поэтому подгружаться из памяти она будет в любом случае.

(Ответить) (Уровень выше) (Ветвь дискуссии)


[info]dibr@lj
2011-08-08 17:09 (ссылка)
> Поэтому если в системе нет динамически обновляемой трансляции адресов - под стек придётся аллоцировать и физическую память тоже, а это жуткий overhead.

Так и не надо сразу физическую память. Я ж не отказываюсь от виртуальной памяти, а она подразумевает, что таблица трансляции будет иногда изменяться (хотя бы при выгрузке/загрузке страницы с диска), я только хочу, чтобы эта таблица была одинаковой для всех приложений (и ОС), и не менялась при переключении между приложениями. А дальше - обнаружили (чисто программно), что стек "скоро кончится" - подмаппили дополнительной памяти, вот и всё. Да, собственно, можно и аппаратно нехватку стека обнаруживать - если механизм VM есть, то лишних телодвижений делать почти не надо.

> Это, скорее, явление а не процедура. Кэш сконструирован из предположения локальности кода

У меня когнитивные аберрации: вижу "кеш", читаю "стек" :-))) Да, при переключении процесса процессорный кеш действительно будет очень активно перегружаться, при сегодняшних объемах данных, и при не менее чем двух активно "молотящих" процессах - с какой-то вероятностью вообще полностью :-)

> примерный, плюс-минус лапоть, виртуальный адрес становится известен на раннем этапе выполнения команды. К примеру, если выполняется команда "mov %eax,0x48(%esi)

Блин, и тут оптимизировали :-)
В-общем, вынужден согласиться: по сравнению с перегрузкой кеша, перегрузка какого-то там TLB будет ничтожна по затратам.

(Ответить) (Уровень выше)


[info]vikky_13@lj
2011-08-08 15:47 (ссылка)
вижу тут слабое место - саму ОС. Да, она будет защищать, но кто защитит ее саму от несанкционированных модификаций, которые удалят эту защиту?
Единственный выход - прописывать ОС в ROM, но тогда не нужны будут псевдокоды - защитить можно будет проще, но это (read only OS) - сам пониаешь, какие проблемы.

(Ответить) (Ветвь дискуссии)


[info]dibr@lj
2011-08-08 16:55 (ссылка)
Как я уже писал, при "добропорядочном" использовании (несъёмные диски никогда не монтируются под другой ОС, съёмные априори считаются "грязными") ОС защитит себя сама: просто на уровне файлового API не будет давать никому (кроме себя) писать в бинарники в машкодах. А при "недобропорядочном" использовании - в точности та же проблема есть и у обычных ОС: кто защитит твою винду от модификации, если приду я, и загружусь с live CD?
100% решения, как я понимаю, нет, но для каждого уровня паранойи есть частичные решения. Крутящиеся вокруг "подписывания" бинарников этим экземпляром ОС (взломщик должен уметь пересоздавать "подпись"), сверки контрольных сумм с хранящимися в независимом хранилище (взломщик должен уметь доступаться до "хранилища" и подменять чексумму), и шифрования FS (взломщик должен в принципе уметь доступиться до FS). Все они обходятся, все они "небесплатны". Но и у обычных ОС - те же проблемы.

> Единственный выход - прописывать ОС в ROM, но тогда не нужны будут псевдокоды - защитить можно будет проще, но это (read only OS) - сам пониаешь, какие проблемы.

А толку то? ОС в ROM, а данные, которыми она пользуется, один фиг в RAM и без защиты. Плюс приложения - хорошая ОС должна не только защищать себя, но и защищать приложения друг от друга. Ну, и про проблемы ты в курсе :-)

(Ответить) (Уровень выше)


[info]ilya_314@lj
2011-08-08 17:01 (ссылка)
Если требуется абсолютная защита, то очевидно единственный способ - никак не подпустить пользователя к ядру системы. Это вообще говоря решается аппаратно как в консолях. Но речь не об этом, а о том, чтобы софт не мог поломать систему и внутри системы жестко гарантировалась целостность. Чтобы например какой-то драйвер не поломал систему.

(Ответить) (Уровень выше)


[info]dz@lj
2011-08-10 19:31 (ссылка)
Это и есть одна из базовых идей Фантома. Собственно, из всего сказанного не реализована только трансляция в бинарник.

(Ответить)


[info]1master@lj
2011-08-10 19:37 (ссылка)
Фундаментальная проблема защиты в том, что для ее абсолютной надежности нужно отобрать у пользователя святое право сделать со своей машиной то, что он хочет.

(Ответить) (Ветвь дискуссии)


[info]dibr@lj
2011-08-11 05:23 (ссылка)
Ну, поскольку абсолютная защита предполагает защиту в том числе от пользователя - то как бы да, пользователя в правах ущемлять придётся (и это в том или ином виде и делается в уже существующих системах). Но, поскольку имея физический доступ сделать можно всё-таки всё что хочешь (вопрос только в сложности) - речь идёт о разной степени компромисса, заточенной под разные сценарии использования. А там уж зависит от того, какая именно реальная (не абсолютная) степень защиты нам нужна :-)

(Ответить) (Уровень выше)