arm compiler 5 не полностью соблюдает изменчивый классификатор - PullRequest
4 голосов
/ 01 апреля 2019

Рассмотрим следующий код:

volatile int status;

status = process_package_header(&pack_header, PACK_INFO_CONST);

if ((((status) == (SUCCESS_CONST)) ? ((random_delay() && ((SUCCESS_CONST) == (status))) ? 0 : side_channel_sttack_detected()) : 1))
{
    ...
}

, который генерирует этот машинный код (создается с помощью objdump ) в цепочке инструментов:

  60:   f7ff fffe       bl      0 <process_package_header>
  64:   9000            str     r0, [sp, #0]     /* <- storing to memory as status is volatile */
  66:   42a0            cmp     r0, r4           /* <- where is the load before compare? status is volatile, it could have change between the last store instruction (above line) and now */
  68:   d164            bne.n   134 <func+0x134>
  6a:   f7ff fffe       bl      0 <random_delay>

Теперь, поскольку status является энергозависимым, он должен был считываться из памяти при достижении оператора if. Я бы ожидал увидеть некоторую команду загрузки, прежде чем сравнивать ее (cmp) с SUCCESS_CONST, несмотря на тот факт, что ей было присвоено возвращаемое значение из функции process_package_header() и он сохранен в памяти, поскольку status является энергозависимым и может были изменены между str инструкция и cmp инструкция.

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

Toolchain ARM DS-5_v5.27.0 arm компилятор: ARMCompiler5.06u5 (armcc)

Целью является ARM CortexM0 + CPU

Ответы [ 2 ]

4 голосов
/ 01 апреля 2019

Основное правило, управляющее объектами volatile, заключается в следующем: C11 6.7.3 / 7 :

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

И далее говорится, что

То, что составляет доступ к объекту, имеющему тип с изменчивой квалификацией, определяется реализацией.

, который применяется к тому, как другие правила (например, в 5.1.2.3)быть истолкованным.В Руководстве пользователя вашего компилятора обсуждаются подробности нестабильного доступа , но в этом нет ничего удивительного.Сам раздел 5.1.2.3 в основном говорит о правилах последовательности;правила оценки выражений приведены в другом месте (но все равно должны соблюдаться, как указано в отношении доступа к вашему изменчивому объекту).

Вот соответствующие подробности поведения абстрактной машины:

  1. Операция присваивания имеет побочный эффект сохранения значения в объекте, обозначенном status.В конце этого оператора есть точка последовательности, поэтому

    • побочный эффект применяется перед выполнением любых оценок, появляющихся в последующих операторах, и
    • , поскольку status является изменчивым, присваиваемое этой строке присваивание представляет собой последнюю запись в status, выполненную программой перед точкой последовательности.
  2. условное выражение вОператор if вычисляется следующим, с

    • сначала выполняется вычисление подвыражения (status) == (SUCCESS_CONST), прежде чем произойдет любое из других вложенных выражений.
    • Произойдет оценка statusперед оценкой операции == и
    • принимает форму преобразования этого идентификатора в значение, хранящееся в идентифицируемом объекте (преобразование lvalue, для , параграф 6.3.2.1/2).
    • Чтобы сделать что-либо со значением , хранящимся в status в то время, это значение должно быть сначала прочитано.

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

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

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

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

1 голос
/ 01 апреля 2019

Описанное поведение не соответствует стандарту C, за исключением нетрадиционных интерпретаций. Если компилятор должен соответствовать этому, об этом следует сообщить как об ошибке.

...