
Olá pessoal! Demoramos um tempo para continuar uma série de artigos sobre o dispositivo Android interno. Neste artigo, falarei sobre o processo de inicialização do Android, sobre o conteúdo do sistema de arquivos, sobre como os dados do usuário e do aplicativo são armazenados, sobre o acesso root, sobre a portabilidade de montagens do Android e sobre o problema de fragmentação.
Artigos da série:
Pacotes
Como eu disse antes, a arquitetura Android é construída em torno de aplicativos. São os aplicativos que desempenham um papel fundamental no dispositivo de muitas partes do sistema, é para a interação harmoniosa dos aplicativos que os modelos de atividade e intenção são criados, e o modelo de segurança do Android é baseado no isolamento de aplicativos. E se o gerenciador de atividades estiver envolvido em orquestrar a interação dos componentes do aplicativo, ele será responsável por instalar, atualizar e gerenciar os direitos do aplicativo (gerenciador de pacotes - você pode chamá-lo no shell com o comando pm
).
Como o nome sugere "gerenciador de pacotes", nesse nível os aplicativos são chamados de pacotes . Os pacotes são distribuídos no formato APK (pacote Android) - arquivos zip especiais. Cada pacote possui um nome (também conhecido como ID do aplicativo ) que identifica exclusivamente esse aplicativo (mas não sua versão específica - pelo contrário, os nomes das diferentes versões do pacote devem corresponder, caso contrário, serão considerados pacotes separados). Os nomes dos pacotes geralmente são escritos na notação do nome DNS reverso - por exemplo, o aplicativo do YouTube usa o nome do pacote com.google.android.youtube
. Geralmente, o nome do pacote corresponde ao namespace usado no código Java, mas o Android não o exige (além disso, os arquivos APK do aplicativo geralmente incluem bibliotecas de terceiros, cujo namespace, é claro, não tem nada a ver com os nomes dos pacotes, quem os usa).
Cada APK durante a montagem deve ser assinado pelo desenvolvedor usando uma assinatura digital. O Android verifica a presença dessa assinatura ao instalar o aplicativo e ao atualizar um aplicativo já instalado, além disso, compara as chaves públicas com as quais as versões antiga e nova são assinadas; eles devem corresponder, o que garante que a nova versão foi criada pelo mesmo desenvolvedor que a antiga. (Se essa verificação não estiver disponível, o invasor poderá criar um pacote com o mesmo nome que o aplicativo existente, convencer o usuário a instalá-lo “atualizando” o aplicativo e obter acesso aos dados desse aplicativo.)
A atualização do pacote em si é a instalação de sua nova versão, em vez da antiga, com a preservação dos dados e permissões recebidos do usuário. Você também pode "fazer o downgrade" dos aplicativos para versões mais antigas, mas, ao mesmo tempo, por padrão, o Android apaga os dados salvos pela nova versão, pois a versão antiga pode não ser capaz de trabalhar com os formatos de dados usados pela nova versão.
Como eu já disse, normalmente o código de cada aplicativo é executado sob seu próprio usuário Unix (UID), o que garante seu isolamento mútuo. Vários aplicativos podem solicitar explicitamente ao Android que use um UID comum para eles, o que permitirá que eles acessem diretamente os arquivos uns dos outros e, mesmo que desejem, sejam executados no mesmo processo.
Embora geralmente um pacote corresponda a um arquivo APK, o Android suporta pacotes que consistem em vários APKs (isso é chamado de APKs divididos ou APKs divididos ). Essa é a base desses recursos "mágicos" do Android, como carregamento dinâmico de módulos de aplicativos adicionais (módulos de recursos dinâmicos ) e Execução Instantânea no Android Studio (atualização automática do código do aplicativo em execução sem a reinstalação completa e, em muitos casos, mesmo sem reiniciar).

Sistema de arquivos
O dispositivo do sistema de arquivos é um dos problemas mais importantes e interessantes na arquitetura do sistema operacional, e o dispositivo do sistema de arquivos no Android não é exceção.
De interesse, em primeiro lugar, quais sistemas de arquivos são usados, ou seja, em qual formato o conteúdo dos arquivos é salvo em um disco condicional (no caso do Android, isso geralmente é memória flash e cartões SD) e como o kernel do sistema fornece suporte para esse formato . O kernel Linux usado no Android, em um grau ou outro, suporta um grande número de sistemas de arquivos diferentes - daqueles usados no Windows FAT e NTFS e aqueles usados em Darwin pelo infame HFS + e pelo moderno APFS - para a rede 9pfs do Plano 9. Existem muitos »Para sistemas de arquivos Linux - por exemplo, Btrfs e a família ext.
O padrão de fato para Linux há muito tempo é o ext4 , usado por padrão pelas distribuições mais populares do Linux. Portanto, não há nada inesperado no fato de ser usado no Android. Algumas montagens (e alguns entusiastas) também usam o F2FS (Flash-Friendly File System), otimizado especificamente para memória flash (no entanto, com suas vantagens, tudo não é tão claro ).
Em segundo lugar, o chamado layout do sistema de arquivos é interessante - o local das pastas e arquivos do sistema e do usuário no sistema de arquivos. O layout do sistema de arquivos no “Linux normal” merece uma descrição mais detalhada (que pode ser encontrada, por exemplo, neste link ); Mencionarei aqui apenas alguns dos diretórios mais importantes:
/home
armazena pastas pessoais do usuário; aqui, em várias pastas ocultas ( .cache
, .cache
, .config
e outras), os programas armazenam suas configurações, dados e cache, específicos para o usuário,/boot
armazena o kernel do Linux e a imagem initramfs (sistema de arquivos de inicialização especial),/usr
(seria mais lógico chamar /system
) armazena a parte principal do sistema, incluindo bibliotecas, arquivos executáveis, arquivos de configuração e recursos - temas para a interface, ícones, conteúdo do manual do sistema etc./etc
(seria mais lógico chamar /config
) armazena configurações em todo o sistema,/dev
armazena arquivos de dispositivos e outros arquivos especiais (por exemplo, o soquete /dev/log
),/var
armazena dados mutáveis - logs, cache do sistema, conteúdo do banco de dados, etc.
O Android usa um layout de sistema de arquivos semelhante, mas notavelmente diferente. Aqui estão algumas das partes mais importantes:
/data
armazena dados mutáveis,- O kernel e a imagem initramfs são armazenados em uma partição flash separada, que não pode ser montada no sistema de arquivos principal.
/system
corresponde a /usr
e armazena o sistema,/vendor
- um análogo de /system
desenvolvido para arquivos específicos deste assembly Android e não incluído no Android "padrão",/dev
, como no "Linux normal", armazena arquivos de dispositivos e outros arquivos especiais.
O mais interessante desses diretórios são /data
e /system
. O conteúdo de /system
descreve o sistema e contém a maioria de seus arquivos constituintes. /system
está localizado em uma seção separada da memória flash, montada por padrão no modo somente leitura; geralmente os dados nele são alterados apenas quando o sistema é atualizado. /data
também /data
localizado em uma seção separada e descreve o estado mutável de um dispositivo específico, incluindo configurações do usuário, aplicativos instalados e seus dados, caches, etc. Limpar todos os dados do usuário, a chamada redefinição de fábrica, com esse esquema é simplesmente limpar o conteúdo da seção de dados ; um sistema intocado permanece instalado na seção do sistema .
# mount | grep /system /dev/block/mmcblk0p14 on /system type ext4 (ro,seclabel,relatime,data=ordered) # mount | grep /data /dev/block/mmcblk0p24 on /data type ext4 (rw,seclabel,nosuid,nodev,noatime,noauto_da_alloc,data=writeback)
Os aplicativos - ou seja, seus arquivos APK, odex (código Java compilado antecipadamente) e bibliotecas ELF - são instalados em /system/app
(para aplicativos entregues com o sistema) ou em /data/app
(para usuário instalado aplicações). Ao criar um assembly Android, cada aplicativo pré-instalado recebe uma pasta com o nome do formulário /system/app/Terminal
e, para aplicativos instalados pelo usuário durante a instalação, são criadas pastas cujos nomes começam com o nome do pacote. Por exemplo, um aplicativo do YouTube é salvo em uma pasta com um nome como /data/app/com.google.android.youtube-bkJAtUtbTuzvAioW-LEStg==/
.
Sobre este sufixoO sufixo no nome das pastas do aplicativo tem 16 bytes aleatórios codificados em Base64. O uso desse sufixo impede que outros aplicativos “adivinhem” o caminho para um aplicativo que eles não devem estar cientes. Em princípio, a lista de aplicativos instalados no dispositivo e os caminhos para eles não é um segredo - pode ser obtida por meio de APIs padrão - mas, em alguns casos (principalmente para aplicativos Instantâneos), o acesso a esses dados é restrito.
Esse sufixo serve a outro propósito. Sempre que o aplicativo é atualizado, o novo APK é instalado na pasta com um novo sufixo, após o qual a pasta antiga é excluída. Antes da versão 8.0 Oreo, esse era o objetivo dos sufixos e, em vez de bytes aleatórios , -1
e -2
usados alternadamente (por exemplo, /data/app/com.google.android.youtube-2
para o YouTube).
O caminho completo para a pasta do aplicativo em /system/app
ou /data/app
pode ser obtido usando a API padrão ou o pm path org.example.packagename
, que exibe os caminhos de todos os arquivos APK do aplicativo.
# pm path com.android.egg package:/system/app/EasterEgg/EasterEgg.apk
Como os aplicativos pré-instalados são armazenados na seção do sistema (cujo conteúdo, lembro-me, muda apenas quando o sistema é atualizado), eles não podem ser excluídos (em vez disso, o Android oferece a capacidade de "desativá-los"). No entanto, a atualização de aplicativos pré-instalados é suportada - nesse caso, uma pasta em /data/app
é criada para a nova versão e a versão fornecida com o sistema permanece em /system/app
. Nesse caso, o usuário tem a oportunidade de "remover atualizações" desse aplicativo, retornando à versão em /system/app
.
Outro recurso dos aplicativos pré-instalados é que eles podem receber permissões especiais do "sistema" . Por exemplo, aplicativos de terceiros não obtêm a permissão DELETE_PACKAGES
, que permite remover outros aplicativos, REBOOT
, que permite reiniciar o sistema, e READ_FRAME_BUFFER
, que permite acesso direto ao conteúdo da tela. Essas permissões têm um nível de proteção de assinatura , ou seja, o aplicativo que tenta acessá-las deve ser assinado com a mesma chave que o aplicativo ou serviço em que foram implementadas - nesse caso, uma vez que essas permissões são implementadas pelo sistema, a chave com a qual é assinado Android build
Para armazenar dados mutáveis, cada aplicativo recebe uma pasta em /data/data
(por exemplo, /data/data/com.google.android.youtube
para YouTube). Somente o próprio aplicativo tem acesso a essa pasta - ou seja, apenas o UID sob o qual esse aplicativo é iniciado (se o aplicativo usar vários UIDs ou se vários aplicativos usarem um UID comum, tudo poderá ser mais complicado). Nesta pasta, os aplicativos salvam configurações, cache (nas subpastas shared_prefs
e cache
, respectivamente) e quaisquer outros dados necessários:
# ls /data/data/com.google.android.youtube/ cache code_cache databases files lib no_backup shared_prefs # cat /data/data/com.google.android.youtube/shared_prefs/youtube.xml <?xml version='1.0' encoding='utf-8' standalone='yes' ?> <map> <string name="user_account">username@gmail.com</string> <boolean name="h264_main_profile_supported7.1.2" value="true" /> <int name="last_manual_video_quality_selection_max" value="-2" /> <...> </map>
O sistema conhece a existência da pasta de cache
e pode limpá-la por conta própria, se não houver espaço suficiente. Quando você desinstala o aplicativo, toda a pasta desse aplicativo é completamente excluída e o aplicativo não deixa rastros. Como alternativa, os dois usuários podem fazer explicitamente nas configurações:

Esse armazenamento de dados alocado para cada aplicativo é chamado de armazenamento interno.
Além disso, o Android possui outro tipo de armazenamento - o chamado armazenamento externo ( armazenamento externo - esse nome reflete a ideia original de que o armazenamento externo deve estar localizado em um cartão SD externo inserido no telefone). De fato, o armazenamento externo desempenha o papel da pasta inicial do usuário - pastas como Documentos, Download, Música e Imagens estão localizadas lá; é o armazenamento externo que os gerenciadores de arquivos abrem como pasta padrão; permite que o computador acesse o conteúdo do armazenamento externo quando conectado por cabo.
# ls /sdcard Alarms Download Podcasts Android Movies Ringtones Books Music Subtitles DCIM Notifications bluetooth Documents Pictures
Diferentemente do armazenamento interno, dividido em pastas de aplicativos individuais, o armazenamento externo é uma "zona comum": qualquer aplicativo que tenha recebido a permissão apropriada do usuário terá acesso total a ele. Como mencionei em um artigo anterior, aplicativos como o gerenciador de arquivos devem solicitar esta permissão; e para a maioria dos outros aplicativos, é melhor usar a intenção com a ação ACTION_GET_CONTENT
, dando ao usuário a oportunidade de escolher o arquivo desejado no gerenciador de arquivos do sistema.
Muitos aplicativos preferem salvar alguns de seus arquivos internos, que são grandes (por exemplo, um cache de imagens e arquivos de áudio baixados) em armazenamento externo. Para fazer isso, o Android aloca para aplicativos em pastas de armazenamento externo com nomes no formato Android/data/com.google.android.youtube
. O aplicativo em si não requer permissão para acessar todo o armazenamento externo para acessar esta pasta (já que seu UID é definido como o proprietário desta pasta), mas qualquer outro aplicativo que tenha essa permissão pode acessar essa pasta, portanto, vale a pena usar Somente para armazenar dados públicos e não críticos. Quando você desinstala o aplicativo, o sistema também exclui sua pasta especial no armazenamento externo; mas os arquivos criados pelos aplicativos no armazenamento externo fora de sua pasta especial são considerados pertencentes ao usuário e permanecem no local após a remoção do aplicativo que os criou.
Como mencionei acima, assumiu-se inicialmente que o armazenamento externo estaria realmente localizado em um cartão SD externo, já que naquele momento o volume de cartões SD era significativamente maior que a quantidade de memória incorporada nos telefones (no HTC Dream, eram apenas 256 megabytes, dos quais cerca de 90 megabytes foram alocados para a seção de dados ). Desde então, muitas condições mudaram; os telefones modernos geralmente não têm um slot para cartão SD, mas uma quantidade enorme de memória interna é instalada pelos padrões móveis (por exemplo, no Samsung Galaxy Note 9, pode ser de até 512 gigabytes ).
Portanto, no Android moderno, quase sempre o armazenamento interno e o externo estão localizados na memória interna. O caminho real pelo qual o armazenamento externo está localizado no sistema de arquivos assume o formato /data/media/0
( um armazenamento externo separado é criado para cada usuário do dispositivo e o número no caminho corresponde ao número do usuário). Para fins de compatibilidade, o armazenamento externo também pode ser acessado pelos caminhos /sdcard
, /mnt/sdcard
, /storage/self/primary
, /storage/emulated/0
, vários caminhos iniciados por /mnt/runtime/
e outros.
Por outro lado, muitos dispositivos ainda têm um slot para cartão SD. O cartão SD inserido no dispositivo Android pode ser usado como uma unidade externa comum (sem transformá-lo em armazenamento interno ou externo do sistema) - salve arquivos nele, abra os arquivos armazenados nele, use-o para transferir arquivos para outros dispositivos, etc. Além disso, o Android permite "emprestar" um cartão SD e colocar armazenamento interno e externo nele (isso é chamado de armazenamento emprestado - armazenamento adotado ). Ao mesmo tempo, o sistema reformata o cartão SD e criptografa seu conteúdo - os dados armazenados nele não podem ser lidos conectando-o a outro dispositivo.

Você pode ler mais sobre tudo isso, por exemplo, nesta postagem e na documentação oficial para desenvolvedores de aplicativos e criadores de montagem do Android .
A carregar
A abordagem tradicional à segurança do sistema de computador limita-se a proteger o sistema contra ataques de software. Acredita-se que, se um invasor tiver acesso físico a um computador, o jogo já estará perdido : ele poderá obter acesso total a todos os dados armazenados nele. Para fazer isso, basta, por exemplo, executar neste computador um sistema operacional arbitrário controlado por ele, que lhe permite ignorar quaisquer restrições impostas pelo sistema "principal" de direitos ou conectar diretamente o disco de dados a outro dispositivo. Se desejado, um invasor pode deixar o computador em estado operacional, mas corrige o sistema instalado, instala backdoors arbitrários, keyloggers, etc.
É a proteção contra ataques de software que se concentra no modelo de restrição de direitos de usuário no Unix (e na tecnologia sandbox de aplicativos baseada no Android); A restrição Unix, por si só, não protege o sistema de um usuário que foi para a sala do servidor e obteve acesso físico ao computador. E se servidores multiusuários sérios puderem e devem ser protegidos contra acesso físico não autorizado a computadores pessoais - e especialmente dispositivos móveis - essa abordagem simplesmente não é aplicável.
Há duas maneiras de tentar melhorar a situação com proteção contra um invasor que obteve acesso físico ao dispositivo:
- Primeiramente, é possível criptografar os dados armazenados em um disco , impedindo que um invasor obtenha acesso aos dados em si, mesmo que ele tenha acesso ao conteúdo do disco.
- Em segundo lugar, é possível limitar de alguma forma a capacidade de carregar sistemas operacionais arbitrários no dispositivo , forçando um invasor a passar por procedimentos de autenticação e autorização no sistema instalado.
É com essas duas áreas de proteção que o modelo de inicialização segura no Android é associado.
Inicialização verificada
O processo de inicialização do Android foi projetado para que, por um lado, não permita que os invasores carreguem um sistema operacional arbitrário no dispositivo; por outro lado, permita que os usuários instalem assemblies personalizados do Android (e outros sistemas).
Antes de tudo, os dispositivos Android, diferentemente dos computadores "desktop", geralmente não permitem que um usuário (ou invasor) seja inicializado a partir de uma mídia externa; em vez disso, o carregador de inicialização instalado no dispositivo (carregador de inicialização) inicia imediatamente. O Bootloader é um programa relativamente simples cujas tarefas (ao carregar no modo normal) incluem:
- inicialização e configuração do Trusted Execution Environment (por exemplo, ARM TrustZone),
- localizando partições de memória interna que armazenam imagens do kernel Linux e initramfs,
- (integrity) — — ,
- initramfs .
Flashing, unlocking, fastboot recovery
, bootloader .
-, (Android) , recovery . recovery, Android- , , Android recovery .
«» bootloader', — ( flashing ) . bootloader , fastboot mode ( bootloader mode), bootloader' fastboot ( fastboot
Android SDK ).
bootloader' . , Samsung, bootloader'a (Loke) (Odin). Odin Samsung ( Odin), Heimdall .
bootloader' ( ), recovery Android, , :
$ fastboot flash recovery recovery.img $ fastboot flash boot boot.img $ fastboot flash system system.img
; : , , bootloader' Android, , , , .
, bootloader' (unlocking the bootloader, OEM unlock) — bootloader' recovery, ( ). Android, LineageOS ( CyanogenMod ), Paranoid Android , AOKP , OmniROM .
bootloader' - , ( data ) . , , (, Google ), — , .

recovery bootloader , .
bootloader' :

recovery, «» (flashaholics) — TWRP (Team Win Recovery Project). - «», zip-, :

Android ( file-based encryption ). ext4 , Linux ( fscrypt ), .
, data , , (credential encrypted storage). , , . , , .

credential encrypted storage Android device encrypted storage — , ( Trusted Execution Environment). , , , . , Direct Boot : ; ( ) device encrypted storage, , . , Direct Boot , , - .
Root
root- — « root» (UID 0, ). , root — Unix-, — — , .
, Android , root- . , « », Android « », root- «», :
- — , APK ,
- : -, email-, , , , , , ( activity intent', ),
- (icon packs),
- , ,
- ( Android-) ,
- , Android, .

, , , root- . root- ( ), Android root . , , Unix-; shell, adb shell
, Unix- shell .
, , root :
- -, root- Android — Android Studio QEMU, .

- -, root- Android ( pre-rooted ROMs).
- -, bootloader' root- Android , ,
su
, bootloader. - , -, , , root-, ( root- ). , 2016 , root- Dirty Cow .
? , root- . , root-, , , . — , . , , system ( ).
, root- — , .
root-
With great power comes great responsibility.
, . , root- .
, , . , root- , , , root- . root, , , , — , , , ..
, Unix, Android , — . root- , , . , root- Android, .
, , root- , . , , , , , . , — , Google Pay ( Android Pay) — root- , .

, - Pokémon GO root- , , .
Google Play root-
Google Google Play Store Google Play Services , root- , Android , , , , . Play Store — ( , ) Android, . ( — , Amazon Android Fire OS — Echo, Fire TV, Fire Phone, Kindle Fire Tablet — Google). root- Android-.
, Google , root-, Google Play ( Open GApps ); Google , .
Device manufacturers work with Google to certify that Android devices with Google apps installed are secure and will run apps correctly. To be certified, a device must pass Android compatibility tests. If you are unable to add a Google Account on your Android device, your Android device software might not have passed Android compatibility tests, or the device manufacturer has not submitted the results to Google to seek approval. As a result, your device is uncertified. This means that your device might not be secure.
If you are a User wanting to use custom ROMs on your device, please register your device by submitting your Google Services Framework Android ID below.
root
«» Linux, Unix-, root- ( sudo
su
) ( , Unix- root, ) (, ). , root-.
su
Android Open Source Project , Unix- shell ( root), root-. su
, , , .
, su
. su
, root-. , SuperSU ; Magisk .

Magisk
Magisk — , , /system
, system ( systemless-ly ), «» Linux . Magisk Hide — root-, root- Magisk — - Google Pay, root- . Magisk Hide root-, SafetyNet Google.
, , Google Pay root- — root- . , root-, - Google Pay. , .
Magisk systemless- «» Magisk Modules , Magisk. , , root- Xposed ViPER , .
SoC,
, «», , — , — (, Wi-Fi ).
, Android- (system on a chip, SoC). — , , -, , LTE-, Bluetooth- Wi-Fi- .. — . , , , , , .
, , . , «», , , , . , , -, , , , .
— Android — SoC . , , — LTE- — . , ; , , .
SoC (, Qualcomm) Android- (, Sony LG), Android, Android Open Source Project. , Android, , , .
Android Android-. , Android. Android , , . .
, : Android — , . Android, .
, , , Android. .
-, . , . , , , , .
-, Android — developer experience (DX, user experience/UX). , Android, API — Android Framework, OpenGL/Vulkan — . , , , Android — , , .

Don't Stop Thinking About Tomorrow
Android- . , Google Nexus Pixel , Android. Android , , , .
, , Android, SoC. Android «» (, , Android-x86 RemixOS ). Android ChromeOS, Chromebook' Android- Linux- -. — Android — Anbox , Android- «» Linux-. (, Android- x86-, , Java, .)

, Android — , Android .
— Android. , , . , , Android .
. 2017 Google Project Treble — , ( HAL, hardware abstraction layer) ( , ) . Treble , , , — — .
Treble . Treble (Sony, Nokia, OnePlus, Oppo, Xiaomi, Essential Vivo — Google) - Android Pie. Treble Essential Android Pie Essential Phone Android Pie. Android — - — , Treble, , SoC.
Treble . Java «write once, run everywhere» — Android- . Treble — , Android SoC. , , Treble. , Android- .
userspace Android: init, Zygote, Binder, props.