Набрёл на
новость:
Цитата:
Автор проекта grsecurity, Brad Spengler, опубликовал эксплойт, использующий очень интересную уязвимость в ядре Linux (драйвер net/tun).
Специфика этой уязвимости состоит в том, что уязвимость отсутствует в исходном коде, но присутствует в бинарном. Как такое возможно? Давайте рассмотрим это на примере. Все начинается с того, что происходит инициализация указателя sk:
Код:
struct sock *sk = tun->sk;
Этот код не вызывает ошибок даже если tun == NULL, и не является сам по себе уязвимостью.
Несколькими строками ниже происходит проверка инициализации указателя tun:
Код:
if (!tun)
return POLLERR;
Казалось бы, теперь все правильно. Злодей не пройдет.
Но!
При сборке кода компилятор полагает, что указатель tun уже корректно инициализирован и, оптимизируя код, выкидывает проверку факта инициализации (приведенный выше оператор if). Таким образом, ничто не мешает злоумышленнику заставить ядро обращаться по нулевому адресу. Имеем классическую null pointer dereference vulnerability.
Заявление про
"даже если tun == NULL, и не является сам по себе уязвимостью" меня удивило (я с C++ не шибко знаком), полез проверять.
Действительно:
Цитата:
Еще одна известная особенность языка C++ может усугубить проблемы, возникающие при вызове delete this. После удаления объекта можно продолжить с ним работать, вызывать те его функции, что не работают с данными и не подозревать о том, что он вообще удален.
Пример:
Код:
class CBase
{
int m_i;
public:
CBase() : m_i (0){}
void printBase() { cout<<"CBase"<<endl; }
};
int main()
{
CBase* b = NULL;
b->printBase();
return 0;
}
Экземпляр объекта CBase никогда даже и не создавался, но код будет шикарно работать годами до тех пор, пока вы не обратитесь к данным класса как-нибудь так:
Код:
void printBase() { m_i++; cout<<"CBase"<<endl; }
Понятно, что приведённый код изначально кривой. Но сочетание с оптимизатором получилось интересное