Меню Рубрики

Установка линукс на арм процессор

Устанавливаем пакет инструментов GNU ARM под Linux

Инструменты разработки встроенных систем для популярного процессора

Если вы интересуетесь разработкой встроенных систем для популярного микропроцессора, вам стоит познакомиться с архитектурой Advanced RISC Machines (ARM). Эта статья поможет вам сделать первые шаги к пониманию процесса программирования встроенных систем, познакомив с широко используемым пакетом инструментов GNU ARM.

Семейство процессоров ARM

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

Ядро ARM развивается на протяжении 20 лет, в течение которых было выпущено несколько поколений процессоров. Последние из них – процессоры вида «системы на кристалле» (system on a chip или SoC), — работают на таких мобильных устройствах, как G1 Android от T-Mobile, и имеют по два ядра (ARM9 и ARM11), что позволяет улучшить производительность мультимедийных приложений на платформах с малыми ресурсами электропитания.

Последние версии процессоров ARM поддерживают два режима работы: режим ARM, в котором ядро выполняет 32-разрядные инструкции и режим THUMB, в котором выполняются 16-разрядные инструкции. Режим ARM позволяет задействовать всю мощь процессора, тогда как режим THUMB дает возможность писать определенные части программы, придерживаясь жестких ограничений, позволяющих экономить память. Переключение между режимами выполняется очень просто, что позволяет существенно уменьшить размер необходимого кода для множества алгоритмов.

Хорошая производительность процессоров ARM достигается благодаря использованию модифицированной гарвардской архитектуры. В этой архитектуре процессор использует отдельные кэши данных и инструкций, которые, однако, находятся на одной шине и одновременно очищаются при доступе к внешней памяти. Кроме того, инструкции размещаются в пятиступенчатом «конвейере». Таким образом, процессор осуществляет параллельную обработку последних пяти инструкций, помещенных в конвейер: каждое из пяти отдельных действий (чтение, декодирование, арифметико-логические операции, чтение памяти и запись), составляющих инструкцию, выполняется параллельно с другими. Таким образом, в случае непрерывного потока выполнения код выполняется быстро благодаря параллелизму, однако если после инструкции ветвления программе будет нужно выполнить код, находящийся вне конвейера, происходит очистка содержимого всего конвейера, ухудшающая производительность. Отсюда мораль: следует аккуратно проектировать код, используя инструкции ветвления в минимальном количестве.

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

Пакет инструментов GNU ARM

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

Описываемый в этой статье пакет инструментов GNU, также известный как Sourcery G++ Lite, размещен на сайте группы CodeSourcery (см. ссылку в разделе Ресурсы) и доступен для бесплатной загрузки и использования. Все инструменты, за исключением библиотеки GNU C, распространяются под стандартной публичной лицензией GNU версии 3 (GPL3). Библиотека GNU C распространяется согласно лицензии GPL версии 2.1. В набор бинарных утилит этого пакета ( binutils ) входит набор компиляторов GNU (GCC), отладчик удаленного кода GNU (GDB), GNU make и базовые утилиты GNU.

Также в пакет Sourcery G++ Lite включена подробная документация набора инструментов GNU, в том числе Стандарты Кодирования GNU — документ, достойный тщательного изучения! В документации по ассемблеру GNU, as,, вы найдете множество информации, специфичной для платформы ARM: коды операций, синтаксис, директивы и так далее.

Загрузка и установка пакета инструментов GNU

Чтобы скачать набор инструментов GNU, посетите страницу загрузки сайта CodeSourcery (см. ссылку в разделе Ресурсы) и выберите там TAR-файл для IA32 GNU/Linux:

Различные версии пакета инструментов GNU доступны для всех распространенных клиентских операционных систем, однако мы в этой статье рассмотрим установку и использование версии Lite в системе Linux®.

За время развития проекта ARM было разработано несколько поколений процессоров. Поэтому пакет Lite включает в себя различные C-библиотеки для трех наиболее распространенных версий архитектуры процессора — ARM v4T, ARM v5T и ARM 7.

Теперь с помощью команды bunzip2 распакуйте архив в свою домашнюю директорию.

Листинг 1. Извлечение пакета инструментов GNU из загруженного архива.

Теперь остается только добавить в переменную среды PATH путь к директории bin пакета, после чего инструменты можно использовать.

Настройка Linux для использования пакета инструментов GNU

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

Если вы занимаетесь программированием для архитектуры ARM гораздо больше, чем для архитектуры Intel®, в качестве альтернативы можно добавить в директорию /usr/local/bin символические ссылки, указывающие на директорию с бинарными файлами пакета. Тогда вы сможете использовать укороченную форму запуска команд, например as вместо arm-none-linux-gnueabi-as . В листинге 2 показано, как создавать подобные символические ссылки.

Листинг 2. Создание символических ссылок для инструментов ARM

Сначала, используя команду which , мы определили полный путь команды, чтобы его было легче скопировать и вставить в команду ln . Затем с помощью команды ln -s мы создали символическую ссылку. После этого, чтобы убедиться, что ссылка успешно создана, мы просмотрели информацию о ней с помощью ls , а потом запустили ее. Создав простые символические ссылки на все инструменты из директории с бинарными файлами пакета, вы избавите себя от необходимости вводить длинные имена с клавиатуры. Ведь определенно гораздо проще набирать as , а не arm-none-linux-gnueabi-as каждый раз, когда вы запускаете ассемблер!

Пишем программу для архитектуры ARM

Есть множество руководств по созданию ARM программ на вечно популярном языке программирования C, однако по программированию на чистом ассемблере руководств гораздо меньше. Я собираюсь сломать эту традицию и приведу здесь пример написания программы на чистом ассемблере, — того, что обычно считается черной магией программирования. Это простая программа из разряда “Hello World”, но специально написанная для конкретной версии ARM Linux.

Программа-пример, приведенная в этой статье, рассчитана на запуск на мобильном телефоне T-Mobile G1, работающем на платформе Android Linux. Она написана таким образом, что также может работать на любой другой Linux-системе, основанной на ARM (поскольку выполняет только стандартные системные вызовы). Однако, для того, чтобы работать с используемым здесь новым интерфейсом системных вызовов ядра EABI (Embedded Application Binary Interface – двоичный интерфейс для встроенных приложений), вам необходимо использовать версию ядра Linux не ниже 2.6.16.

Замечание: В разделе Ресурсы можно найти ссылку на статью с сайта Embedded.com, в которой рассказывается об ARM-программировании не для системы Linux, а непосредственно для «железа».

Читайте также:  Установка водосчетчиков рекомендованные фирмы

Теперь, используя код, приведенный в листинге 3, создайте в вашем любимом текстовом редакторе скрипт с названием build. Этот скрипт сначала запускает ассемблер GNU ARM, а затем компоновщик. При создании этой программы я старался получить исполняемый файл как можно меньшего размера, поэтому отключил вывод всей отладочной информации с помощью параметра компоновщика —strip-all . После создания скрипта сделайте его исполняемым командой chmod +x build .

Листинг 3. Сборка приложения Hello World для ARM Linux

После этого создайте модуль исходного кода hw.S и поместите в него код, приведенный в листинге 4.

Листинг 4. Приложение Hello World для ARM Linux

В ассемблере GNU символ «at» ( @ ) обозначает начало комментария. Ассемблер игнорирует все, что следует после символа @ до конца строки.

В программе используются два стандартных системных вызова Linux – sys_write и sys_exit . Перед кодом на ассемблере в комментариях приводится его эквивалент, написанный на C. Это позволяет показать, как регистры ARM отображаются в параметры выполняемых системных вызовов. Запомните, что параметры перечисляются слева направо, от r0 до r6 . В регистре r7 помещается номер используемого системного вызова.

Инструкция svc 0x00000000 командует процессору ARM вызвать «супервизор», которым в данном случае является ядро Linux.

Тестирование программы для ARM

В пакете Sourcery G++ Lite для отладки низкоуровневых программ предоставляется не теряющий популярности отладчик GDB. Этот отладчик позволяет (помимо прочего) удаленно отлаживать ARM-код, выполняющийся на одноплатном компьютере с подсоединенным к нему модулем JTAG или ICE.

Если вы хотите протестировать код так, как это сделал я – на системе Android Linux, запущенной на мобильном телефоне, — сначала вам нужно подключить телефон к рабочему компьютеру поставляемым вместе с телефоном USB-кабелем, а затем, используя команду adb push из набора инструментов разработки (SDK) для Android, скопировать программу на телефон. После этого на телефоне переместитесь в директорию, содержащую исполняемые файлы (/data/local/bin) и командой chmod 555 hw сделайте файл программы выполняемым. (Команда chmod на Android не позволяет в таких случаях использовать параметр +x , поэтому приходится передавать 555 .)

Наконец, используя команду adb shell , соединитесь с телефоном, переместитесь с помощью cd в нужную директорию и запустите программу: ./hw . Если все пойдет правильно, то программа, как на моем телефоне, выведет на экран приветствие «Hello Android!».

Заключение

Если это небольшое введение в программирование на ассемблере для ARM вас заинтересовало, то по ссылкам в разделе Ресурсы вы можете более подробно познакомиться с архитектурой этого процессора. Наилучшим ресурсом для глубокого изучения ядра ARM является справочное руководство по архитектуре ARM (ARM Architecture ReferenceManual. или ARM ARM,) – библия разработки для процессоров ARM.

Тем, кто строит карьерные планы, я предлагаю подумать о следующем: сегодня в мире миллионы мобильных телефонов, и с каждым годом их количество увеличивается. Прогресс дошел до такого состояния, что мы можем носить в своем кармане машину с двухъядерным процессором, устройством хранения данных емкостью несколько гигабайт и полноценными сетевыми возможностями, обеспечивающими моментальный доступ к информации и развлечениям через Интернет. Со стороны производителей мобильных телефонов существует большой спрос на талантливых программистов. При такой распространенности процессоров ARM у вас всегда будет много работы, причем интересной! Как всегда, играйте с инструментами и получайте удовольствие от работы, которую вы делаете. Программирование – это отчасти искусство, отчасти наука, и, возможно, одна из самых приятных технических профессий.

Ресурсы для скачивания

Похожие темы

  • Ознакомьтесь с оригиналом статьи: Install the GNU ARM toolchain under Linux (EN, developerWorks, май 2009 г.).
  • Посетите сайт проекта ARM (EN).
  • Посетите сайт проекта GNU ARM (EN).
  • Познакомьтесь с серией статей Программирование на аппаратном уровне для систем ARM инструментами GNU (EN) с сайта Embedded.com.
  • Почитайте о двухъядерных процессорах типа «система на кристалле» (SoC) от Qualcomm (EN).
  • Загрузите пакет Sourcery G++ Lite со страницы загрузки проекта CodeSourcery .
  • Загрузите и читайте руководство ARM ARM (EN) — библию разработки для процессоров ARM.
  • Если вам более интересна встроенная разработка для архитектуры PowerPC, ознакомьтесь с циклом из девяти статей Migrating from x86 to PowerPC (EN) на developerWorks, в котором рассказывается о разработке устройства управления автомобилем на прототипе платы Kuro Box.
  • Используйте в вашем следующем Linux-проекте ознакомительное ПО от IBM, которое можно загрузить непосредственно с сайта developerWorks.(EN)

Комментарии

Войдите или зарегистрируйтесь для того чтобы оставлять комментарии или подписаться на них.

источник

Загрузка ОС на ARM

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

Загрузка ARM в четырех прямоугольниках — под катом.

Сразу ограничим уровень детализации. Нас интересует, что происходит, а не как, то есть конкретные инструкции процессора оставим в стороне. Постараемся найти общее у всех процессоров и всех ОС. Поищем угрозы безопасности.

Разновидности процессоров ARM

Если вы знаете про ARM, то этот раздел можно смело пропустить.

В производстве и эксплуатации сейчас встречаются процессоры ARM пяти архитектур: ARMv4, ARMv5, ARMv6, ARMv7 и ARMv8. Компания ARM дает этим архитектурам коммерческие названия, поэтому ARMv4 называется, например, ARM7, ARMv5 – ARM9, а название Cortex имеют процессоры на архитектурах ARMv6, v7, v8. Следующая таблица перечисляет основные разновидности.

Архитектура Коммерческое название Распространенные виды Запуск Linux
ARMv4 ARM7 ARM7TDMI Нецелесообразно
ARMv5 ARM9 ARM926EJ-S Да
ARMv6 ARM11 ARM1176JZF-S Да
Cortex-M0 Cortex-M0 Нет
ARMv7 Cortex-M Cortex-M3 Нецелесообразно
Cortex-A Cortex-A9 Да
Cortex-R Cortex-R4 Да
ARMv8 Cortex-A Cortex-A53 Да

Например, кнопочные телефоны в основном используют ARM7, а смартфоны – Cortex-A. Современные смартфоны строятся преимущественно на ARMv8, единственных 64-битных. Процессоры ARM7 и ARM9 широко применялись в различных промышленных контроллерах, сетевом оборудовании, а сейчас фокус переходит на использование в них Cortex-A. В различной бытовой технике, мелких электронных приборах, в области безопасности и т.п. применяются микроконтроллеры Cortex-M.

Вообще все устройства ARM можно условно разбить на микроконтроллеры и Application Processor.

  • Микроконтроллеры отличаются наличием на кристалле Flash-памяти и рабочего ОЗУ. Применяются для задач относительно малой автоматизации.
  • Application Processor преимущественно пользуется внешней памятью — DDRAM и Flash. Мы их дальше будем называть просто — процессоры. Масштаб задач у них больше.

Долгое время одни и те же архитектуры ARM7, ARM9 использовались как для построения процессоров, так и микроконтроллеров. С появлением линейки Cortex произошло разделение, и теперь микроконтроллеры называются Cortex-M, а процессоры Cortex-A и Cortex-R.

Виды ОС

Какие есть варианты запуска ОС:

  • на микроконтроллерах обычно запущена маленькая ОС реального времени (RTOS) или просто программа без ОС;
  • на процессорах чаще запущена ОС общего применения (Linux, Android), иногда маленькая RTOS, иногда полнофункциональная RTOS (типа vxWORKS).

Например, в планшетах и смартфонах используется Android, iOS или вариант Linux. В телекоммуникационном оборудовании может быть Linux или один из вариантов RTOS. В более простом оборудовании может применяться RTOS или программа без ОС.

Читайте также:  Установка классического автокада 2016

В дальнейшем мы будем говорить только о запуске ОС (Linux, Android) или RTOS на ARM. По способу запуска “большие” RTOS попадают в одну группу с Linux, а “малые” RTOS объединяются с программами без ОС.

Для запуска Linux хорошо подходят процессоры ARM9, ARM11, Cortex-A. Усеченную версию Linux также можно загрузить на ARM7, Cortex-M4 и Cortex-M7, но это нецелесообразно.

Для запуска малых RTOS подходят микроконтроллеры и процессоры ARM7, ARM9, Cortex-M. В некоторых случаях для RTOS используют начальные модели Cortex-A, например, Cortex-A5. Большинство же процессоров Cortex-A столь сложны, что их возможности можно использовать только совместно с поставляемым производителем Linux/Android SDK, что и определяет выбор в пользу Linux.

Загрузчик ОС

С точки зрения разработчика системное ПО устройства делится на загрузчик и ОС. Основную функцию всегда выполняет программа, работающая под управлением ОС или RTOS.

Загрузчик обеспечивает загрузку ОС и сервисные функции, такие, как:

  • проверка целостности образа ОС перед запуском;
  • обновление программ;
  • сервисные функции, функции первоначальной инициализации устройства;
  • самотестирование.

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

Таким образом, с точки зрения разработчика изделия запуск ОС выглядит следующим образом:

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

Схема “Загрузчик-ОС” очень удобна из практических соображений, ведь загрузчик берет на себя всю низкоуровневую работу:

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

Например, для запуска Linux на ARM загрузчик должен инициализировать память, хотя бы один терминал, загрузить образ ядра и Device Tree в память и передать управление на ядро. Все это описано в . Код инициализации ядра Linux не будет делать сам то, что должен делать загрузчик.

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

Рассмотрим работу загрузчика на примере u-boot, загружающего Linux, по шагам.

  1. После включения или сброса процессор загружает образ u-boot, хранимый в Flash-памяти, в ОЗУ и передает управление на первую команду этого образа.
  2. u-boot инициализирует DDRAM.
  3. u-boot инициализирует драйверы загрузочного носителя (ЗН), например, eMMC, NAND Flash.
  4. u-boot читает с ЗН область переменных конфигураций. В конфигурации задан скрипт загрузки, который u-boot далее исполняет.
  5. u-boot выводит в консоль предложение прервать процесс загрузки и сконфигурировать устройство. Если за 2-3 секунды пользователь этого не сделает, запускается скрипт загрузки.
  6. Иногда скрипт начинается с поиска подходящего образа ОС для загрузки на всех доступных носителях. В других случаях ЗН задается в скрипте жестко.
  7. Скрипт загружает с ЗН в DDRAM образ ядра Linux (zImage), файл Device Tree с параметрами ядра (*.dtb).
  8. Дополнительно скрипт может загрузить в DDRAM образ initrd – маленькой файловой системы с необходимыми для старта драйверами устройств. Современные дистрибутивы Linux иногда используют initrd, а иногда – нет.
  9. Разместив загруженные 2 или 3 файла в памяти, скрипт передает управление на первую команду образа zImage (ядро Linux).
  10. zImage состоит из распаковщика и сжатого образа ядра. Распаковщик развертывает ядро в памяти, и загрузка ОС начинается.

Запуск загрузчика – предзагрузчик

Однако в реальности почти никогда не бывает, чтобы команды загрузчика выполнялись первыми после включения или сброса процессора. Это еще было на процессорах ARM7, но почти не встречалось далее.

Любое ядро процессора ARM при сбросе начинает исполнение с адреса 0, где записан вектор “reset”. Старые серии процессоров буквально начинали загружаться с внешней памяти, отображенной по нулевому адресу, и тогда первая команда процессора была командной загрузчика. Однако для такой загрузки подходит только параллельная NOR Flash или ROM. Эти типы памяти работают очень просто – при подаче адреса они выдают данные. Характерный пример параллельной NOR Flash – микросхема BIOS в персональных компьютерах.

В современных системах используются другие виды памяти, потому что они дешевле, а объем больше. Это NAND, eMMC, SPI/QSPI Flash. Эти типы памяти уже не работают по принципу: подал адрес — читаешь данные, а значит, для прямого исполнения команд из них не подходят. Даже для простого чтения тут требуется написать драйвер, и мы имеем проблему «курицы и яйца»: драйвер нужно откуда-то заранее загрузить.

По этой причине в современные процессоры ARM интегрировано ПЗУ с предзагрузчиком. ПЗУ отображено в памяти процессора на адрес 0, и именно с него начинает исполнение команд процессор.

В задачи предзагрузчика входят следующие:

  • определение конфигурации подключенных устройств;
  • определение загрузочного носителя (ЗН);
  • инициализация устройств и ЗН;
  • чтение загрузчика с ЗН;
  • передача управления загрузчику.

Конфигурация предзагрузчика обычно устанавливается одним из двух способов:

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

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

Подобный предзагрузчик устанавливается как в процессорах ARM, таких, как Cortex-A, так и в микроконтроллерах, даже таких маленьких, как Cortex-M0. Вместе с предзагрузчиком процедура запуска ОС выглядит так:

Анализ угроз на этом этапе

Исходный код предзагрузчика пишется производителем процессора, а не компанией ARM, является частью микросхемы как продукта компании-производителя и защищен авторским правом. Например, в процессорах ARM компаний Atmel и NXP предзагрузчики написаны, соответственно, Atmel и NXP.

В некоторых случаях предзагрузчик можно прочитать из ROM и проанализировать, но иногда доступ к нему ограничен. Например, предзагрузчик процессора серии Psoc4000 компании Cypress был закрыт несколькими слоями защиты (но был взломан талантливым хакером).

Использования предзагрузчика в большинстве сценариев избежать нельзя. Можно рассматривать его как вариант BIOS, которого в ARM-системах нет.

Сам по себе предзагрузчик в ROM несет в себе угрозу нарушения порядка загрузки и выполнения произвольного кода. Но после того как управление передано загрузчику ОС, предзагрузчик уже безвреден. Мы можем просто не передавать ему управление, перенастроить все обработчики прерываний и так далее.

Читайте также:  Установка автокад 2015 ключ подробная активация

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

Это в общем случае небезопасно, но встречается только в некоторых микроконтроллерах на архитектуре ARM. На таких микроконтроллерах обычно запускаются программы без ОС или малые RTOS, и дизайнер системы может оценить риски.

Загрузка с TrustZone

В процессоры ARM Cortex-A и Cortex-R встраивается технология TrustZone. Эта технология позволяет на аппаратном уровне выделить два режима исполнения: Secure (Безопасный) и Non-Secure (Гостевой).

Эти процессоры в основном нацелены на рынок смартфонов и планшетных компьютеров, и TrustZone используется для создания в режиме Secure доверенной “песочницы” для исполнения кода, связанного с криптографией, DRM, хранением пользовательских данных.

В режиме Secure при этом запускается специальная ОС, называемая в общем случае TEE (Trusted Execution Environment, доверенная среда исполнения), а нормальная ОС, такая, как Linux, Android, iOS, запускается в режиме Non-Secure. При этом права доступа к некоторым устройствам ограничены для нормальной ОС, поэтому ее еще называют гостевой ОС.

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

Например, гостевая ОС использует функции TEE для:

  • включения и выключения ядер процессора (в ARMv8-A это происходит через PSCI — часть ARM Trusted Firmware, а в ARMv7 — по-разному для каждого производителя процессоров);
  • хранения ключей, данных банковских карт и т.п.;
  • хранения ключей полнодискового шифрования;
  • операций с криптографией;
  • отображения DRM-контента.

При этом, с точки зрения безопасности, на время таких вызовов управление передается в неизвестный нам, непроверенный код. Мы не можем однозначно сказать, что делают Samsung KNOX или QSEE от Qualcomm.

Почему же разработчики систем соглашаются на такой режим функционирования? В процессоры с поддержкой TrustZone встроен и механизм Secure Boot в том или ином виде.

С Secure Boot предзагрузчик проверяет подпись загружаемого образа с помощью прошитого на этапе производства открытого ключа. Таким образом, гарантируется, что загружен будет только подписанный образ. Это функция безопасности.

То есть загрузка ОС становится следующей:

  1. стартует предзагрузчик в ROM. Он загружает ключи для проверки подписи TEE из ROM;
  2. предзагрузчик загружает в память образ TEE, проверяет подпись. Если проверка прошла успешно, запускается TEE;
  3. TEE настраивает режимы Secure и Non-Secure. Далее TEE загружает основной загрузчик ОС и переходит на него в режиме Non-Secure. Сам TEE остается в режиме Secure и ждет;
  4. загрузчик основной ОС загружает ОС как обычно;
  5. ОС вынуждена время от времени вызывать функции TEE для выполнения некоторых задач.

Однако производитель, как правило, поставляет подписанные образы загрузчика и TEE в составе SDK для процессора и поставляет процессоры, уже “зашитые” ключом производителя. В этом случае предзагрузчик из ROM не станет выполнять любой загрузчик, если он не подписан производителем. Все основные процессоры для смартфонов сейчас поставляются уже “прошитыми” под исполнение собственного TEE перед исполнением загрузчика ОС.

Далее действует лень — c TEE все работает, а без TEE даже не запускается. Разработчики используют SDK с TEE, вызывают закрытый бинарный код из ядра Linux и не волнуются.

Как проверить свой проект на обращения к TrustZone

Может даже показаться, что всей этой TrustZone не существует, по крайней мере, в вашей конкретной разработке. Проверить это совсем несложно.

Дело в том, что все процессоры с TrustZone стартуют в режиме Secure, а только потом переключаются в Normal. Если ваша ОС запущена в режиме Normal, то какая-то Secure OS (TEE) существует в системе и перевела ее в этот режим.

Лакмусовой бумажкой является обращение к TEE для включения кэш-памяти 2-го уровня. По какой-то причине архитектура ARM не позволяет этого делать из Normal World. Поэтому для включения кэша ядру ОС потребуется сделать хоть один вызов к TrustZone. Делается это единственной командой: smc #0, и вы можете поискать ее сами в ядре Linux или Android.

Разумеется, мы и сами поискали, и нашли такие вызовы в коде поддержки ряда процессоров Qualcomm, Samsung, Mediatek, Rockchip, Spreadtrum, HiSilicon, Broadcom, Cavium.

Загрузка ARM Cortex-A и анализ угроз

На схеме пунктиром обозначен путь обращения из ядра ОС в TEE.

В двух блоках — неизвестный нам код. Посмотрим, чем это грозит.

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

Предзагрузчик работает на самом раннем этапе, когда схема подключения к процессору различных периферийных устройств еще не известна, никакие коммуникационные устройства (WiFi, 3G и т.д.) не настроены, коммуникационные протоколы не работают. При этом предзагрузчик – небольшая программа, с размером кода порядка нескольких десятков килобайт, и сложно представить размещение в нем полных стеков протоколов или серьезной эвристики по определению подключенных устройств. Поэтому предзагрузчик вряд ли таит в себе серьезные закладки, связанные со слежкой, передачей данных и т.п.

Гораздо более интересной точкой атаки является TEE, так как его функции вызываются в процессе работы ОС, когда все периферийные устройства работают, а коммуникационные протоколы настроены. Создание шпионской закладки в коде TEE позволяет практически неограниченно следить за пользователем СВТ.

В небольшом исследовании мы показали реализуемость закладки в TEE, незаметно перехватывающей системные вызовы ОС Linux. Для активации закладки нужно только одно обращение из ядра Linux в TEE (например, то самое, для кэша второго уровня), после чего система становится полностью управляемой. Это позволяет:

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

Несомненно, выявленные возможности – только вершина айсберга, и создание закладок не было целью исследования.

Выводы

Мы рассмотрели процесс загрузки различных микроконтроллеров и процессоров ARM.

У микроконтроллеров наиболее уязвимым местом в процессе загрузки является загрузчик ОС.

Современные процессоры ARM Cortex-A включают в себя TrustZone — и от этого никуда не уйти. TrustZone предполагает запуск перед ОС доверенной среды исполнения TEE.

TEE является самой уязвимой точкой в процессе загрузки ОС на ARM Cortex-A, потому что обращения к TEE приводят к выполнению закрытого системного кода, известного производителю, но скрытого от нас.

Без контроля над TEE невозможно обеспечить безопасность и доверенность исполнения любой ОС на ARM Cortex-A.

источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *