LINUX.ORG.RU
ФорумTalks

Linux для параноика :)


0

0

Переполнения буффера были и остаются частью нашей жизни. Уж сколько раз твердили миру, а мир всё пишет на C/C++.

Так вот, мне интересны техники исключения небезопасностей C++. А именно, переполнения буффера и висячие указатели, хотя бы эти источники ошибок. Меня интересуют компиляторы, виртуальные машины C++ и т. д., в которых выполнить подобную операцию было бы невозможно. В идеале -- пересобрать какой-нибудь популярный дистр этим компилятором. Но это вряд ли, как-то нереально звучит, поэтому топик в Talks. Это было бы полезно не только для безопасности юзера, но и для улучшения кода. Ошибки, которые могут быть не видны при исполнении в обычном режиме, не проскочат в режиме защищённом. Соответственно, можно слать баг-репорты куда надо. Это лучше, чем просто надеяться на авось^Wмиллион пытливых глаз.

Конечно, это падение производительности и другие затраты. Скажем, трёхкратное падение производительности на Core 2 Duo можно позволить. Просто очень хочется.

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

Если кто знает, как такое дебажить - самому интересно.

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

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

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

true
()

noexec (1) + stack protection (2) + MAC (3) + code verification (4)

Use Fedora 7, Luke. В ней есть 1, 2 и 3.

А за 4 нужно деньги платить или своё время ;-)

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

>noexec (1) + stack protection (2) + MAC (3)

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

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

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

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

Я наталкивался на подходящее решение, это виртуальная машина фирмы Интерстрон.

http://www.interstron.ru/text.asp?key=white_paper5

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

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

Nihilist
() автор топика
Ответ на: комментарий от true

> Лучше отпинать авторов такого кода.

Ног не хватит.

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

Программа ИМХО не должна делать того, чего не нельзя, не потому что прав таких нету, а потому что в ней этого не было написано.

Тем не менее, надо как-то использовать накопившийся балласт^Wбагаж C/C++ кода. В этом и заключается топик. Кто знает, быть может так оно и будет когда-нибудь.

Nihilist
() автор топика

> Уж сколько раз твердили миру, а мир всё пишет на C/C++.

Альтернативы есть?

Небезопасные поинтеры -- это фича. Товальдс по этому поводу очень правильно высказался.

> Конечно, это падение производительности и другие затраты. Скажем, трёхкратное падение производительности на Core 2 Duo можно позволить. Просто очень хочется.

Пишите на Java или Python и будет вас счастье.

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

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

откуда? У компилятора связь с астралом?

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

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

>откуда? У компилятора связь с астралом?

В объявлении строк в C/C++ уже не принято указывать их размер?

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

>В объявлении строк в C/C++ уже не принято указывать их размер?

а что ты понимаешь под объявлением строк?

вот char* str; - это объявление строки или нет? ;)

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

Я понимаю то, где подразумевается, сколько памяти надо выделить под переменную. По этим данным при компиляции сделать код проверки, который в рантайме проверяет, не выходят ли входные данные за границу переменной.

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

>Я понимаю то, где подразумевается, сколько памяти надо выделить под переменную. По этим данным при компиляции сделать код проверки, который в рантайме проверяет, не выходят ли входные данные за границу переменной.

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

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

> Пиши на паскале и будет тебе счастье.

Не будет.

В Паскале точно так же можно написать

var i: integer, p: pointer, pf: ^real;
begin
    p := @i;
    pf := p;
    ^pf := 3.14159;

и точно так же испортить стек.

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

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

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

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

А проверяльщик вставляется при компиляции.

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

>Если оно определяется в рантайме, значит его можно сохранить где-то, и использовать сохраненное значение в проверяльщике.

для этого надо переписать _все_ функции всех библиотек. И передавать кроме указателя ещё и размер. И про арифметику указателей придется забыть

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

>для этого надо переписать _все_ функции всех библиотек. И передавать кроме указателя ещё и размер.

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

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

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

тебе в сторону .NET :)

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

>можно написать

так ведь не пишут же. Нужно аж 3 оператора, чтоб наконец ошибиться: i:=0; 1) p:= @i; 2) pf:= p; 3) pf^:= 3.141;

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

> для этого надо переписать _все_ функции всех библиотек. И передавать кроме указателя ещё и размер. И про арифметику указателей придется забыть

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

Правда, как устроить эти жирные указатели (ЖУ, термин из языка Cyclone), ещё вопрос, однозначного решения нет.

Затравкой для ЖУ обычно является структура из указателя, его min и max. Далее, в качестве модификации можно вместо трёх указателей иметь три смещения, и ещё одним членом структуры handle на домен памяти, в котором всё расположено. Или три указателя, но оставить handle для проверки, а не освободилась ли эта память. Или вообще отслеживать граф ссылок. С разной степенью эффективности, но эта задача решаема.

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

>Да нет, жирные указатели арифметику прекрасно позволяют делать. Все функции переписывать не надо, достаточно изменить те места, где выделяется и освобождается память.

а те-же strcmp будут телепатически узнавать - сколько выделено и где можно ползать? :)

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

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

Перечисленные ошибки во многих случаях позволяет отлавливать valgrind (который тоже по сути является виртуальной машиной).

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

> Альтернативы есть?

Для меня лучшая такая альтернатива -- это Ада. К сожалению, в начале 90х её компиляторы не отличались доступностью по цене, а в 80х и вовсе едва доказывали теорему о своём существовании. (Об этом ещё писал Бьярн Страуструп : "My attempts to implement algorithms that work on any sequential structure (both lists and arrays) failed because of the state of Ada compilers at the time. I had equivalences to many STL algorithms, but could not compile them") -- за это и последующее время было создано много кода на C++. К счастью, несколько лет назад обе эти проблемы решены, а сейчас и вовсе закончилась стандартизация Ады 2005, которая по некоторым причинам занимает в моём сознании то же место, что для кого-то C++ 0x. Так что теперь надо как-то совмещать разноязыковые компоненты.

Допустим, у нас связка Ada&Lisp&C++ (Java, C#, Python, OCAML -- добавить по вкусу). С Лиспом у нас всё в порядке, с Адой тем более. Можно долго говорить о том, какая Ада безопасная, но непременное наличие C/C++ компонент несколько нивелирует это достоинство. В несложных проектах это всего лишь такие библиотеки, как Gtk, Qt, SDL, которые интенсивно "тестируются" по всему миру круглосуточно. Но есть много кода, расчитывать на такую поддержку которого не приходится. И вот эти исходники в экспериментальном порядке было бы интересно собрать в безопасный код. Лисп на своей машине работает, Ада и так безопасна, а C++ часть кода собрана особым компилятором. А потом по возможности переносить по частям с C++ на Аду, чтоб быстрее работало.

В идеале этот компилятор способен собрать весь дистриб какого-нибудь Линукса. В идеале, потому что в коде драйверов может быть что-то, что тяжело "обезопасить". Да и в некоторых пакетах кто знает, с чем придётся встретиться. И, тем не менее, было бы полезно знать, какие именно это пакеты, и, быть может, пропатчить их до компилируемого состояния.

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

>В идеале этот компилятор способен собрать весь дистриб какого-нибудь Линукса. В идеале, потому что в коде драйверов может быть что-то, что тяжело "обезопасить". Да и в некоторых пакетах кто знает, с чем придётся встретиться. И, тем не менее, было бы полезно знать, какие именно это пакеты, и, быть может, пропатчить их до компилируемого состояния.

как этот гипотетический "безопасный транслятор" оттранслирует strcpy?

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

> а те-же strcmp будут телепатически узнавать - сколько выделено и где можно ползать? :)

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

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

Nihilist
() автор топика
Ответ на: комментарий от slav

> Перечисленные ошибки во многих случаях позволяет отлавливать valgrind (который тоже по сути является виртуальной машиной).

Посмотрю. Хоть и не совсем то, но всё же.

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

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

для этого эти функции придется _переписывать_.

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

geek ★★★
()

Паскаль, конкретно fpc, плюсы: быстрее жабы и других животных, поддерживает объектную модель, перегрузку методов, операторов, чистый синтаксис, разумный контроль типов и переполнения, возможность asm-inline, генерация native-executable, меньше требования к озу, не нужно писать Мake-файлы :) Минусы: бинарники медленнее gcc в некоторых (только в некоторых) тестах в 2 раза, слабо подходит для системного программирования, нет шаблонов. Впрочем, все недостатки можно исправить за счёт built-in asm при желании :)

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

>Минусы: бинарники медленнее gcc в некоторых (только в некоторых) тестах в 2 раза, слабо подходит для системного программирования, нет шаблонов. Впрочем, все недостатки можно исправить за счёт built-in asm при желании :)

Угу, особенно отсутствие шаблонов... На built-in asm. Удачи.

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

>Угу, особенно отсутствие шаблонов... На built-in asm. Удачи.

=)))))

а всё потому, что кто-то слишком много ест^W^W^W ленится выучить lisp :)

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

> Я понимаю то, где подразумевается, сколько памяти надо выделить под переменную. По этим данным при компиляции сделать код проверки, который в рантайме проверяет, не выходят ли входные данные за границу переменной.

Для статики это давно уже придумано.
Если параноик и руки не из жопы, то велкам:
http://www.linuxfromscratch.org/hlfs/view/unstable/
В частности:
Stack Smashing Protector, this is now part of GCC-4.1+: http://www.trl.ibm.com/projects/security/ssp/
Поэтому переставайте устраивать визг и придумывать очередные вселенские способы всех защитить и осчастливить, а просто используйте дистрибутивы, собранные с -fstack-protector и -fstack-protector-all:
http://www.trl.ibm.com/projects/security/ssp/links.html
Если ленивые и/или руки вместо ног, то продолжайте наяривать на зюзи с федорами, обсуждая шрифты и пакетные менеджеры и не лезьте в секьюрити.

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

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

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

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

>а всё потому, что кто-то слишком много ест^W^W^W ленится выучить lisp :)

Как раз в данный момент учу. Пока не впечатлён.

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