Группа исследователей из Массачусетского технологического университета (MIT) опубликовала (PDF, 240 Кб) результаты изучения особенностей работы систем оптимизации кода современных компиляторов, способных привести к понижению безопасности приложений. В итоге, выявлены многочисленные факты, когда в процессе компиляции в машинный код из приложения исключаются блоки, бессмысленные с точки зрения оптимизатора, но важные для обеспечения безопасности.
Например, компилятор исключает неопределённые или нестабильные участки кода, которые на деле могут выступать проверками на появление нулевого указателя или выхода за границы области памяти (например, оптимизатор может заменить «data + x = 0» если ранее была проверка «if (k Например, оптимизатор GCC удалит вторую проверку из следующего кода:
char *buf = ...; char *buf_end = ...; unsigned int len = ...; if (buf + len = buf_end) return; /* len too large */ if (buf + lenПрограммист использует условие "buf + len = buf_end" для проверки на переполнение указателя, подразумевая, что при очень большом значении будет осуществлено переполнение размерности типа. GCC оперирует тем, что значение после переполнения переменной с указателем в стандарте языка С считается неопределённым.
В качестве другого примера можно привести код для которого будет удалена проверка на нулевой указатель (gcc считает, что tun-sk не может принимать значение NULL, так как в стандарте С указано, что указатель не может быть нулевым и является в этом случае неопределённым):
struct tun_struct *tun = ...; struct sock *sk = tun-sk; if (!tun) return POLLERR; /* write to address based on tun */Для выявления потенциально проблемных мест в коде на языках C и C++, которые могут быть удалены на стадии оптимизации, исследователями подготовлен специальный статический анализатор STACK. Изучение при помощи STACK типовых открытых проектов выявило 160 подобных проблем, из которых 32 присутствуют в ядре Linux, 3 в Mozilla, 9 в PostgreSQL, 4 в QEMU, 21 в FFmpeg, 3 в Xen, 5 в Python.
Более широкая проверка исходных текстов показала, что нестабильные блоки кода присутствуют в 3471 пакете из 8575 пакетов, доступных в репозиториях Debian. Наибольшее число выявленных проблем (59230 проблем в 2800 пакетах) связано с разыменованием нулевого указателя, 5795 проблем могут привести к переполнению буфера, 4364 к проблемам целочисленной арифметики, 3680 - проблемам с переполнением указателя.
Таким образом, описанные в работе проблемы не являются единичными, а широко распространены и могут быть использованы злоумышленниками для организации новых типов атак.