Необдуманное исправление привело к неполному устранению уязвимости Spectre в ядре Linux

Разработчики проекта Grsecurity поделились поучительной историей, демонстрирующей как необдуманное устранение предупреждений компилятора может привести к появлению уязвимостей в коде. В конце мая для ядра Linux было предложено исправление нового вектора эксплуатации уязвимости Spectre через системный вызов ptrace.

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

          int index = n;       	if (n < HBP_NUM) {                  index = array_index_nospec(index, HBP_NUM);  		struct perf_event *bp = thread->ptrace_bps[index];  

Линус принял исправление в свою master-ветку, избавившись от предупреждения через использование конструкции:

     	if (n < HBP_NUM) {  	        int index = array_index_nospec(n, HBP_NUM);  		struct perf_event *bp = thread->ptrace_bps[index];  

В июле исправление также было портировано в стабильные ветки ядра 4.4, 4.9, 4.14, 4.19 и 5.2. Сопровождающие стабильных веток также столкнулись с предупреждением и вместо того, чтобы проверить, не устранено ли оно уже в master-ветке, собственноручно внесли исправление. Проблема в том, что они особо не задумываясь просто перенесли определение структуры вверх, так, что вызов array_index_nospec, непосредственно обеспечивающий защиту от уязвимости, перестал использоваться при определении структуры и вместо переменной index всегда использовалась переменная «n»:

          int index = n;   	if (n < HBP_NUM ){  		struct perf_event *bp = thread->ptrace_bps[index];  		index = array_index_nospec(n, HBP_NUM);  

©  OpenNet