Русский
Русский
English
Статистика
Реклама

Aosp

Data driven подход для усиления защиты Android

01.03.2021 16:18:41 | Автор: admin


Мы делаем все, чтобы платформа Androidбыла безопасной для всех пользователей на всех устройствах. Каждый месяц выходятобновления системы безопасностис исправлениями уязвимости, найденными участниками программыVulnerability Rewards Program (VRP). Однако мы также стараемся защищать платформу от других потенциальных уязвимостей, напримериспользуя компилятори улучшая тестовую среду. Экосистема Android включает в себя устройства с самыми разными возможностями, поэтому все решения должны быть взвешенными и должны учитывать доступные данные.

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

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

  • Какие у нас есть данные и как они могут помочь в принятии решений?
  • Какие средства предотвращения атак доступны? Как их можно улучшить? В каких ситуациях их следует применять?
  • Какие проблемы могут возникнуть при использовании тех или иных средств безопасности? Какие возможные расклады следует принять во внимание?

Принципы, на которые мы опираемся при выборе средств безопасности, отражают наш общий подход к защите пользователей платформы Android.

Принятие решений по обеспечению безопасности на основе данных


Чтобы выяснить, для каких компонентов платформы будут эффективны те или иные решения, мы обращаемся к различным источникам. ПрограммаAndroid Vulnerability Rewards Program(VRP) едва ли не самый информативный из них. Наши инженеры по безопасности анализируют все уязвимости, обнаруженные участниками программы, определяя их первопричины и уровень серьезности (на основеэтих рекомендаций). Кроме того, есть внутренние и внешние отчеты об ошибках. Они помогают выявлять уязвимые компоненты, а также фрагменты кода, которые часто вызывают сбои. Зная, как выглядят такие фрагменты, и представляя себе серьезность и частоту ошибок, возникающих из-за них, мы можем принимать взвешенные решения о том, какие средства безопасности будут наиболее эффективными.


Уязвимости с высоким и критическим уровнем серьезности, исправленные в бюллетенях по безопасности Android в 2019 г.

Однако не стоит полагаться только на отчеты об уязвимостях. Они изначально дают искаженную картину, так как специалисты по безопасности часто обращают внимание на горячие зоны, то есть на те области, где ранее уже были найдены уязвимости (например,Stagefright). Или они могут искать уязвимости там, где их проще обнаружить с помощью готовых решений. Например, если на платформе GitHub будет опубликован какой-нибудь аналитический инструмент безопасности, многие специалисты будут им пользоваться.

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

В рамках программы Android VRP мы поощряем разработчиков, которые добавляютполные цепочки уязвимостей,позволяющие проследить весь процесс атаки от начала до конца. Как правило, злоумышленники используют сразу несколько уязвимостей, и в подобных цепочках эти связки хорошо видны, поэтому они очень информативные. Наши инженеры по безопасности анализируют как цепочки целиком, так и их отдельные звенья и пытаются обнаружить в них новые стратегии атак. Такой анализ помогает определить стратегии, помогающие предотвратить последовательное использование уязвимостей (например,случайное распределение адресного пространстваи методыControl Flow Integrity), а также понять, можно ли уменьшить масштабы атаки, если процесса получил нежелательный доступ к ресурсам.

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

Чтобы понимать текущие угрозы безопасности и прогнозировать будущие тенденции, нужно постоянно держать руку на пульсе сообщества специалистов безопасности, в частности:

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

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

Почему усиление защиты необходимо


Усиление защиты и предотвращение атак


Анализ данных помогает выявлять области, в которых эффективные средства предотвращения атак могут устранить целые классы уязвимостей. Например, если в некоторых компонентах платформы появляется много уязвимостей из-за ошибок целочисленного переполнения, следует использовать санитайзер неопределенного поведения (UBSan), например Integer Overflow Sanitizer. Если часто наблюдаются уязвимости, связанные с доступом к памяти, необходимо использоватьпрограммы распределения памяти с усиленной защитойAndroid 11 они включены по умолчанию) и средства предотвращения атак (например,Control Flow Integrity), устойчивые к переполнению памяти и уязвимостям Use-After-Free.

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

  • Средства устранения эксплойтов
    • Средства детерминированного устранения уязвимостей в среде выполнениявыявляют неопределенное или нежелательное поведение и прерывают выполнение программы. Это исключает повреждение данных в памяти, при этом сохраняется вероятность лишь менее серьезных сбоев. Часто такие средства можно применять точечно, и они все равно будут эффективными, так как рассчитаны на отдельные ошибки. Примеры:санитайзер для целочисленного переполненияиBoundsSanitizer.
    • Средства снижения воздействия эксплойтовпредотвращают переход от одной уязвимости к другой или получение возможности выполнения кода. В теории эти средства могут полностью устранять некоторые уязвимости. Однако чаще всего они ограничивают возможности их использования. В результате злоумышленникам приходится тратить больше времени и ресурсов на разработку эксплойта. Часто эти средства задействуют весь объем памяти, занимаемый процессом. Примеры: случайное распределение адресного пространства, Control Flow Integrity (CFI), стековый индикатор, добавление тегов к памяти.
    • Преобразование компилятора, изменяющие неопределенного поведения в определенное на этапе компиляции. В результате злоумышленники не могут воспользоваться неопределенным поведением, напримернеинициализированной областью памяти. Пример: инициализация стека.
  • Декомпозиция архитектуры
    • Отдельные блоки разделяются на мелкие компоненты с меньшими привилегиями. В результате воздействие уязвимостей в этих компонентах уменьшается, так как злоумышленник не получает прежнего доступа к системе. Этот метод удлиняет цепочки уязвимостей, а также усложняет доступ к конфиденциальным данным и дополнительным путям повышения привилегий.
  • Песочницы и изоляция
    • Здесь действует принцип, схожий с декомпозицией. Процессу выделяется минимальный набор разрешений и возможностей, необходимых для нормальной работы (часто с помощью обязательного и/или избирательного контроля доступа). Как и в случае с декомпозицией, песочница ограничивает возможности злоумышленников и делает уязвимости в этих процессах менее значимыми благодаря принципу минимальных привилегий. Примеры:разрешения в Android,разрешения в Unix,возможности Linux,SELinux иSeccomp.
  • Использование языков с безопасной обработкой памяти
    • Языки программирования C и C++, в отличие от Java, Kotlin и Rust, не обеспечивают достаточный уровень безопасности памяти. Учитывая, чтобольшинствоуязвимостей в Androidсвязаны с памятью, мы применяем двусторонний подход: улучшаем безопасность языков C/C++ и одновременно рекомендуем использовать более надежные языки программирования.

Реализация этих инструментов


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


Декомпозиция архитектуры и изоляция медиа фреймворков в историческом контексте

Объекты удаленных атак (NFC, Bluetooth, Wi-Fi и медиаконтент) традиционно сопряжены с самыми серьезными уязвимостями, поэтому усиление их безопасности должно стать приоритетной задачей. Как правило, появление этих уязвимостей вызвано самыми распространенными первопричинами, которые выявляют в рамках программы VRP, и недавно мы добавили для всех них санитайзеры.

Средства предотвращения атак удобно использовать для библиотек и процессов, которые задают границы безопасности или находятся в них (например,libbinder, а также стандартные библиотекиlibui,libcore иlibcutils), так как они не привязаны к конкретным процессам. Однако эти библиотеки отвечают за эффективную и стабильную работу систем, поэтому перед тем как применять тот или иной метод, необходима серьезная гарантия того, что он усилит безопасность.

Наконец, важно обеспечить защиту ядра, учитывая высокий уровень его привилегий. У всех кодовых баз разные характеристики и функциональность, поэтому и вероятность появления уязвимостей в них отличается. Главные критерии здесь стабильность и производительность. Следует применять только эффективные средства безопасности, которые не будут мешать пользователям работать. Поэтому прежде чем выбрать оптимальную стратегию усиления защиты, мы тщательно анализируем все доступные данные, связанные с ядром.
Подход, основанный на данных, дал ощутимые результаты. После обнаружения уязвимости Stagefright в 2015 году мы стали получать сообщения о большом количестве другихкритическихуязвимостей мультимедийной платформы Android. Ситуацию усложняло то, что многие из них были доступны удаленно. Мы провелимасштабную декомпозицию системы Android Nougat иускорили исправление уязвимостей в мультимедийных компонентах. Благодаря этим изменениям в 2020 году не было ни одного сообщения о критических уязвимостях в мультимедийных платформах, к которым можно получить доступ через Интернет.

Как принимается решение о развертывании


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

Производительность


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

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

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

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

  • Выборочно отключить средства предотвращения атак для функций, существенно влияющих на производительность. Как правило, только некоторые функции потребляют ресурсы в среде выполнения. Если не применять к ним средства предотвращения атак, можно сохранить производительность и максимально усилить влияние на безопасность.Вот примертакого подхода для одного из медиакодеков. Чтобы исключить риски, упомянутые функции следует предварительно проверить на наличие ошибок.
  • Оптимизировать использование средства предотвращения атак. Часто для этого необходимо внести изменения в компилятор. Например, наша команда перешла на использование IntegerOverflowSanitizer иBoundsSanitizer.
  • Параметры некоторых средств предотвращения атак, таких как встроенная устойчивость распределителя Scudo к уязвимостям в динамической памяти,можно настраиватьдля повышения производительности.

Для многих из этих улучшений необходимы изменения в проекте LLVM. В результате выигрывает не только платформа Android, но и другие участники сообщества LLVM.

Развертывание и поддержка


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

Влияние средств безопасности на стабильную работу системы


Важно понимать, возможно ли ложное срабатывание того или иного средства предотвращения атак. Например, если санитайзер Bounds выдает ошибку, речь точно идет о запрещенном доступе (хотя его могли и не использовать). В случае с санитайзером Integer Overflow возможны ложные срабатывания, так как целочисленное переполнение часто бывает абсолютно нормальным и безвредным процессом.

Поэтому важно учитывать влияние средств предотвращения атак на стабильность системы. Неважно, произошло ли ложное срабатывание или была реальная угроза безопасности, в любом случае пользователь испытывает неудобства. И здесь мы снова отмечаем, что необходимо четко понимать, для каких компонентов следует использовать те или иные средства безопасности. Потому что сбои в некоторых компонентах сильнее сказываются на стабильности системы. Если средство предотвращения атак вызывает сбой в медиакодеке, видео просто перестанет воспроизводиться. Однако в случае ошибки в процессеnetdпри установке обновления устройство может больше не включиться. Даже если для некоторых средств предотвращения атак ложное срабатывание не вызывает проблемы (например, как в случае с санитайзером Bounds), мы все равно проводим подробное тестирование, чтобы убедиться в стабильной работе устройства. Например, ошибки смещения на единицу могут не приводить к сбоям в обычном режиме, а санитайзер Bounds прерывает выполнение процесса и нарушает стабильную работу системы.

Также важно понимать, можно ли заранее выявить все компоненты, которые средство предотвращения атак может вывести из строя. Например, в случае с санитайзером Integer Overflow очень сложно предсказать риски, не проводя масштабного тестирования, потому что трудно определить, какие целочисленные переполнения являются намеренными (разрешенными), а какие могут вызвать уязвимости.

Поддержка


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

Мы стремимся к тому, чтобы средства предотвращения атак минимально влияли на стабильность работы и чтобы у разработчиков была вся необходимая информация. Для реализации этих целей мы улучшаем текущие алгоритмы, чтобы уменьшить число ложных срабатываний, и публикуем документацию на страницеsource.android.com. Упростив отладку в случае сбоев, можно снизить нагрузку на разработчиков при обслуживании. Например, чтобы было проще обнаружить ошибки санитайзера UBSan, мы по умолчанию добавили в систему сборки Androidподдержкуминимального времени выполнения UBSan. Изначально минимальное время выполнения былодобавленодругими разработчиками Google специально для этой цели. При сбое программы из-за санитайзера Integer Overflow в сообщение об ошибке SIGABRT добавляется следующий фрагмент:

Abort message: 'ubsan: sub-overflow' 

Увидев это сообщение, разработчики поймут, что необходимовключить режим диагностики, чтобы распечатать информацию о сбое:

frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp:2188:32: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'size_t' (aka 'unsigned long')

При этом в SELinux есть инструмент audit2allow, который позволяет предлагать правила, разрешающие те или иные заблокированные операции:

adb logcat -d | audit2allow -p policy #============= rmt ============== allow rmt kmem_device:chr_file { read write };

И пусть audit2allow не всегда предлагает правильные варианты, он сильно помогает разработчикам, плохо знакомым с SELinux.

Заключение


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



Благодарим наших коллег и авторов: Кевин Деус, Джоэл Галенсон, Билли Лау, Иван Лосано специалистов по вопросам безопасности и конфиденциальности данных Android. Отдельная благодарность Звиаду Кардава и Джеффа Ван Дер Ступа за помощь в подготовке статьи.
Подробнее..

Загрузка и сборка AOSP

05.09.2020 10:09:13 | Автор: admin

Решил поделиться своей инструкцией как собрать AOSP (Android Open Source Project). Эта инструкция будет полезна тем кто хочет посмотреть что-же внутри Android и возможно заняться системной разработкой. В любом случаи эти знания полезны для понимания самого Android, как раз для этого и решил собрать AOSP.


Проект собираю на elementary 5.1 OS Ubuntu 18.04 LTS (bionic), пытался на MacOS собрать, но так и не удалось. Для исходников и сборки нужно 200 Гб на жестком диске (лучше SSD, на обычном производительность сильно проседает). Так же много времени, я потратил чтобы скачать и собрать около 20 часов, частично виновата "слабая" конфигурация моего компьютера. У меня установлено всего 8 Гб оперативной памяти, но увеличил размер swap-а до 16 Гб.


Загружаем AOSP


Установить требуемые пакеты для загрузки и сборки :


sudo apt-get install git-core gnupg flex bison build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z1-dev libgl1-mesa-dev libxml2-utils xsltproc unzip fontconfig

Создаем папку и качаем repo утилиту для загрузки исходного кода


mkdir aosp # имя папки можно выбрать любоеcd aospcurl https://storage.googleapis.com/git-repo-downloads/repo > repochmod a+x repo

Исходники AOSP состоит из отдельных проектов с собственными git-репозиториями, repo позволяет упросить всю загрузку всех проектов и разложить по нужным папкам.


Инициализируем repo


./repo init -b android-10.0.0_r45 --depth 1 -u https://android.googlesource.com/platform/manifest

Параметры:


  • -u урл git-репозитория с манифестом
  • -b ветка (самая последняя на текущий момент)
  • depth скачивать только одну ветку (если не использовать, то для каждого репозитория скачается весь индекс, что увеличит время загрузки и место на диске)

Выбрал самую последнюю версию Android 10. Не использую develop или master, так как там устаревший манифест и проект скорее не соберется.


Теперь можно запустить загрузку исходников AOSP


./repo sync -c  -j $(nproc) --no-tags --no-clone-bundle

Параметры:


  • -c скачивать только текущую ветку манифеста (как у казали выше android-10.0.0_r45)
  • -j количество потоков, обычно указывается столько доступно процессоров
  • no-tags не скачивать тэги с репозитариев
  • no-clone-bundle не пытаться качать clone.bundle (упакованная репа, которая уменьшить время на загрузку, но не у всех сервер формирует этот bundle),

no-clone-bundle можно попробовать убрать, что в теории ускорит скачивание, но у меня заваливается с 404 ошибкой

Скачивание может занять минуты и часы, теперь с repo закончили, если нужно почитать больше то ищите в официальной документации: https://source.android.com/setup/develop/repo


Сборка


Настраиваем среду разработчика:


source build/envsetup.sh

конфигурируем сборку


lunch aosp_x86_64-eng

x86_64 указывается под какой девайс собирать, в данном случаи Generic x86_64 подходит для эмуляторов, если будете запускать на Nexus девайсах, то ищите детали в документации https://source.android.com/setup/build/building#choose-a-target


eng тип сборки (сокращение от engineering), с максимальными логами и дополнительными утилитами для отладки. Другие тип сборки думаю не особо интересны


Для сборки java файлов увеличиваем Heap size, если этого не сделать, то сборка всего завалится с StackOverflow ошибкой:


export _JAVA_OPTIONS="-Xmx4g"

Так же можно добавить в .bashrc чтобы постоянно не повторять команду

Все, теперь готовы к сборке:


USE_CCACHE=1 CCACHE_DIR=ccache make -j $(nproc)

Можно не использовать CCACHE, что уменьшит количество занимаемого места на диске, но увеличит время повторной сборки. На моем "слабом" компьютере сборка заняла где-то 16 часов.


После окончания сборки, запускаем эмулятор:


emulator -show-kernel

-show-kernel выводить уведомления в консоль


Если нажать Enter, то попадем в консоль эмулятора


Если эмулятор не запустился, нужно будет проверить что включена виртуализация

Эмулятор


Готовим IDE для отладки


Для начала необходимо сгенериовать проект для IDE, проект генерируется для IDEA. Собираем модули для генератора:


mmm development/tools/idegen

Чтобы весь AOSP затолкать в проект, то просто запускаем генератор


development/tools/idegen/idegen.sh

Но сгенерированный IDEA проект будет очень "тяжелым". Одно открытие и индексация занимает достаточно много времени. Лучше генерировать IDEA проект для каждого отдельного проекта, например для Android фреймворка


development/tools/idegen/intellij-gen.sh frameworks/base

Весь список доступных проектов можно посмотреть в


cat .repo/project.list

Открываем сгенерированный base.iml (находится в папке frameworks/base) в IDEA. Дальше нужно настроить Java, только нужно подключать java без библиотек, так как у AOSP-а свои реализации.


Настройка Java в проекте


Запускаем отладку


Для начала необходимо запустить monitor


 ~/Android/Sdk/tools/lib/monitor-x86_64/monitor

возможно потребуется дополнительно поставить jre
sudo apt install openjdk-8-jre-headless

Выбираем процесс, который будем отлаживать. В monitor-е выбираем процесс и справа от порта процесса появится /8700, это как раз порт отладчика, к нему можно подключаться через IDEA.
Все системные штуки находятся в system_process. Его мы и будем отлаживать.


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

monitor из Android


В проекте добавляем новую Remote конфигурацию, только указываем 8700 порт. Именно к этому порту и будем подключаться


Добавляем Remote конфигурацию в IDEA


Запускаем Debug (Run Debug)


Чтобы удостоверится, что все подключилось поставьте брейкпоинт в frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java файле на метод:


// line 1040int startActivityAsUser(IApplicationThread caller, String callingPackage,            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,            boolean validateIncomingUser) {//...}

и запустить любое приложение на эмуляторе (например, Settings).


Теперь все готово для экспериментов.

Подробнее..

Бесшовные AB-обновления в Android как они устроены

29.09.2020 10:08:21 | Автор: admin
image

Всем привет.

В SberDevices наша команда занимается разработкой различных железок прошивок и для них на базе AOSP.

Начиная с Android 8 (у некоторых вендоров с 7.1) в системе появился новый механизм накатки OTA-обновлений, т. н. Seamless A/B OTA Updates бесшовные обновления. В этом посте я опишу общие принципы его работы, рассмотрю механизм с точки зрения разработчика, а также проведу сравнение со старым (будем его называть recovery-based) подходом применения обновлений. Всё нижесказанное будет справедливо только для чистого AOSP, т. к. конкретная реализация зависит от вендора.

Recovery-based OTA


Обновления для Android поставляются в виде zip-архива с образами обновляемых разделов (block-based updates). Во времена KitKat это был просто набор файлов, которые копировались на устройство прилагаемым скриптом. Я не стану подробно останавливаться на этом режиме, кратко опишу основные принципы его работы:

  • zip-архив скачивается системой на устройство;
  • система перезагружается в режим recovery;
  • проверяется совместимость обновления с устройством, его подпись;
  • если всё OK, выполняется updater-script из zip-архива;
  • в процессе обновления устройство может несколько раз перезагрузиться (например, для обновления device tree);
  • если всё прошло успешно, загружаемся в новую прошивку.

Какие минусы в данной схеме?

  • Необходимость резервировать достаточное количество встроенной памяти для OTA-архива. Для этого служит раздел /cache. Некоторые вендоры используют /data, но это редкость. В итоге пользователю остаётся меньше места (да, приложения всё ещё могут использовать место в разделе /cache, но с некоторыми ограничениями).
  • Перезагрузка и применение обновления занимает время, что может быть критично для некоторых видов устройств, например, для Smart TV.
  • Прерывание процесса обновления может привести к boot loop.
  • Нет возможности откатиться на старую версию прошивки.

Эти неудобства позволяет обойти способ бесшовного обновления. Давайте посмотрим, как он устроен.

Seamless A/B OTA


Ключевые компоненты и механизмы, необходимые для реализации бесшовных A/B-обновлений:

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

Слотирование


Основным принципом работы A/B OTA являетсяслотирование.Все разделы, которые необходимо обновлять (это могут быть любые разделы, а не только системные),должны находиться в двух копиях или, иначе, в слотах. В Android-реализации поддерживается 2 слота,которыеименуются соответственно A и B. Система загружается и работает изтекущего слота, второй используется только в момент обновления.К имени раздела добавляется суффикс с именем слота.

Ниже приведена таблица сравнения двух вариантов организации разделов на устройстве.
image

Все слотируемые разделыпомечаютсяопциеймонтированияslotselect, чтобы системамоглавыбратьправильный слот.В зависимости от того, где они описаны, это может быть fstab либо dts.

Изменения в таблице разделов


  • В /сache большенет необходимости.Теперьобновлениеможет сохраняться либов /data,либосразупрошиваться внеактивныйслот(обэтом ниже).
  • Раздел recovery также больше не используется.Однакорежимrecoveryвсё ещё существует, оннеобходим, например, для сброса устройства на заводские настройки (к этому может привестиrescueparty). Или для т. н. ручного обновления (sideload) через adb.Recovery ramdiskтеперьлежит внутриboot-раздела,ядро общее.
  • Для переключения режима загрузки (android/recovery) появилась новая опция в cmdline skip_initramfs.

На первый взгляд кажется, что такая схема не оптимальна, т. к. под систему необходимо выделить в два раза больше места. Но ведь мы избавились от/cache,а значит уже сэкономили большое количествопамяти. Таким образом,система будет заниматьнемногобольше, чем в варианте с recovery.

Главным достоинством A/B-обновлений является возможностьстриминга прошивки. Именно она обеспечивает бесшовность и прозрачность обновлений для пользователя: для обновления устройству достаточно перезагрузиться в новый слот. В этом режиме нет необходимости заранее скачивать zip-архив, занимая место в /data. Вместо этого система сразу пишет блоки данных из специально подготовленного файла (payload, см. ниже) в каждый разделнеактивногослота. С точки зрения реализации нет разницы, скачиваем ли мы предварительно обновление либо сразу стримим его в слот.

Слоты имеют следующие состояния:

  • active активный слот, из него будет загружена система при следующей перезагрузке;
  • bootable обновление успешно прошито в слот, прошло валидацию, совпали хеш-суммы и т. д.;
  • successful система смогла успешно загрузиться в новый слот;
  • unbootable слот поврежден. Система всегда помечает слот как unbootable перед началом процесса обновления.

Оба слота могут бытьbootableиsuccessful, но только один active.

Алгоритм работы загрузчика при выборе слота:
image
  • Загрузчик определяет, что имеется один или более слотов с флагомbootable.
  • Из них выбирается активный слот (либо слот с наибольшим приоритетом).
  • Если система загрузилась успешно, слот помечается какsuccessfulиactive.
  • Иначе слот помечается как unbootable и система перезагружается.


Изменение состояний слотов во время обновления:
image

Необходимые компоненты для работы с Seamless A/B.


boot_control


Для поддержки A/B-обновлений вендор должен реализовать специальный HAL-интерфейс boot_control. Он позволяет изменять состояния слотов и получать о них информацию. Для внешней работы (например, через adb shell) используется утилита bootctl. Интерфейс используется как средство взаимодействия между ОС и загрузчиком.

update_engine


Основной компонент всей A/B-схемы. Занимается загрузкой, стримингом обновлений, проверкой подписи и многим другим. Изменяет состояния слотов через boot_control. Позволяет контролировать процесс обновления устройства: приостанавливать, возобновлять, отменять.
Компонент пришёл в Android из ChromeOS, где уже используется некоторое время.AOSP поддерживает update_engine в виде статической sideload-сборки. Именно она используется в recovery, т.к данный режим не поддерживает динамическую линковку.

Процесс работы данного компонента можно разделить на следующие шаги:

  • загрузка обновления в слот. Загружать можно как из предварительно скачанного пакета с обновлением, так и напрямую по Сети через http/https. В процессе загрузки проверяется подпись, открытый ключ уже находится на устройстве (/system/etc/update_engine/update-payload-key.pub.pem);
  • верификация загруженного обновления и сравнение хеш-сумм;
  • выполнение post-install скриптов.

Структура пакета обновления:
2009-01-01 00:00:00 .....          360          360  META-INF/com/android/metadata2009-01-01 00:00:00 .....          107          107  care_map.txt2009-01-01 00:00:00 .....    384690699    384690699  payload.bin2009-01-01 00:00:00 .....          154          154  payload_properties.txt2009-01-01 00:00:00 .....         1675          943  META-INF/com/android/otacert

  • care_map.txt используется update_verifier-ом (см. ниже);
  • payload_properties.txt содержит хеши и размеры данных внутри payload;
  • payload.bin пакет обновления, содержит блоки всех разделов, метаданные, подпись.


update_engine_client


Клиент для управления демоном update_engine. Может напрямую вызываться вендором для применения обновления.

update_verifier


Утилита для проверки целостности системы при первом запуске (слот с флагомactive, но еще неsuccessful). Контроль целостности реализуется с помощью модуля ядра dm-verity. Если проверка закончилась успешно, утилита помечает текущий слот какsuccessful. Иначе система перезагружается в старый слот. Верифицируются только блоки, указанные в файле care_map.txt.

UpdateEngineApi


Для реализации vendor-сервисов обновлений существует Java API. Также имеется пример реализации такого сервиса.

Рассмотрим пример сборки A/B update в AOSP. Для этого отредактируем Makefile целевой платформы:
#Включим поддержку A/BAB_OTA_UPDATER := true#Укажем необходимые разделы для слотирования:AB_OTA_PARTITIONS := boot system vendor#Добавим необходимые пакетыPRODUCT_PACKAGES := update_engine update_engine_client update_verifier#Отключим раздел recoveryTARGET_NO_RECOVERY := true#Убедимся, что НЕ определяются переменные для раздела cache:#BOARD_CACHEIMAGE_PARTITION_SIZE := ...#BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := ...

После вызова make otapackage получаем zip-архив с обновлением. В таком виде он уже подходит для sideload-режима. Можем выполнить перезагрузку в recovery и вызвать adb sideload ota.zip. Этот способ удобен для отладки.

Применение обновления изнутри рабочей системы обычно определяется вендором. Самый простой способ выложить payload.bin на http-сервер и напрямую вызвать update_engine_client.

Пример вызова:
update_engine_client \--payload=http://path/to/payload.bin\--update \--headers=" \FILE_HASH=ozGgyQEddkI5Zax+Wbjo6I/PCR8PEZka9gGd0nWa+oY= \FILE_SIZE=282344983\METADATA_HASH=GLIKfE6KRwylWMHsNadG/Q8iy5f786WTatvMdBlpOPg= \METADATA_SIZE=26723"

В параметр headers передается содержимое файла payload_properties.txt. В logcat можно наблюдать прогресс обновления. Если передать ключ --follow, прогресс будет дублироваться в stdout.

Заключение


Плюсы нового механизма обновлений очевидны:
  • обновление системы происходит в фоне, не прерывая работу пользователя. Да, всё так же потребуется перезагрузка (в новый слот), но пройдёт оназначительнобыстрее, чем перезагрузка в recovery для применения обновления;
  • минимизируется вероятность boot loop (от ошибок в реализации никто не застрахован). Процесс обновления можно прерывать, наактивныйслот это никак не повлияет;
  • появляется возможность отката на предыдущую версию прошивки. Даже если по каким-то причинам обновление прошло неуспешно, система простовернётся к старой версии;
  • благодаря стримингу устройство обновится быстрее;
  • в зависимости от реализации можно полностью исключить пользователя из процесса обновления.

Из минусов я бы выделил два момента:
  • A/B OTA становится зависимой от текущей разметки диска, т. к. обновление происходит во время работы системы. Т. е. становится невозможно накатить обновление с изменёнными разделами;
  • относительная сложность реализации.

И все же, на мой взгляд, плюсы перевешивают. Кстати, в нашем недавно анонсированном устройстве мы используем A/B OTA обновления.
Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru